brintos

brintos / llvm-project-archived public Read only

0
0
Text · 10.4 KiB · 9256f92 Raw
378 lines · c
1//===-- ARMUtils.h ----------------------------------------------*- C++ -*-===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#ifndef LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_ARMUTILS_H10#define LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_ARMUTILS_H11 12#include "ARMDefines.h"13#include "InstructionUtils.h"14#include "llvm/ADT/bit.h"15#include "llvm/Support/MathExtras.h"16 17// Common utilities for the ARM/Thumb Instruction Set Architecture.18 19namespace lldb_private {20 21static inline uint32_t Align(uint32_t val, uint32_t alignment) {22  return alignment * (val / alignment);23}24 25static inline uint32_t DecodeImmShift(const uint32_t type, const uint32_t imm5,26                                      ARM_ShifterType &shift_t) {27  switch (type) {28  default:29    assert(0 && "Invalid shift type");30    break;31  case 0:32    shift_t = SRType_LSL;33    return imm5;34  case 1:35    shift_t = SRType_LSR;36    return (imm5 == 0 ? 32 : imm5);37  case 2:38    shift_t = SRType_ASR;39    return (imm5 == 0 ? 32 : imm5);40  case 3:41    if (imm5 == 0) {42      shift_t = SRType_RRX;43      return 1;44    } else {45      shift_t = SRType_ROR;46      return imm5;47    }48  }49  shift_t = SRType_Invalid;50  return UINT32_MAX;51}52 53// A8.6.35 CMP (register) -- Encoding T354// Convenience function.55static inline uint32_t DecodeImmShiftThumb(const uint32_t opcode,56                                           ARM_ShifterType &shift_t) {57  return DecodeImmShift(Bits32(opcode, 5, 4),58                        Bits32(opcode, 14, 12) << 2 | Bits32(opcode, 7, 6),59                        shift_t);60}61 62// A8.6.35 CMP (register) -- Encoding A163// Convenience function.64static inline uint32_t DecodeImmShiftARM(const uint32_t opcode,65                                         ARM_ShifterType &shift_t) {66  return DecodeImmShift(Bits32(opcode, 6, 5), Bits32(opcode, 11, 7), shift_t);67}68 69static inline uint32_t DecodeImmShift(const ARM_ShifterType shift_t,70                                      const uint32_t imm5) {71  ARM_ShifterType dont_care;72  return DecodeImmShift(shift_t, imm5, dont_care);73}74 75static inline ARM_ShifterType DecodeRegShift(const uint32_t type) {76  switch (type) {77  default:78    // assert(0 && "Invalid shift type");79    return SRType_Invalid;80  case 0:81    return SRType_LSL;82  case 1:83    return SRType_LSR;84  case 2:85    return SRType_ASR;86  case 3:87    return SRType_ROR;88  }89}90 91static inline uint32_t LSL_C(const uint32_t value, const uint32_t amount,92                             uint32_t &carry_out, bool *success) {93  if (amount == 0) {94    *success = false;95    return 0;96  }97  *success = true;98  carry_out = amount <= 32 ? Bit32(value, 32 - amount) : 0;99  return value << amount;100}101 102static inline uint32_t LSL(const uint32_t value, const uint32_t amount,103                           bool *success) {104  *success = true;105  if (amount == 0)106    return value;107  uint32_t dont_care;108  uint32_t result = LSL_C(value, amount, dont_care, success);109  if (*success)110    return result;111  else112    return 0;113}114 115static inline uint32_t LSR_C(const uint32_t value, const uint32_t amount,116                             uint32_t &carry_out, bool *success) {117  if (amount == 0) {118    *success = false;119    return 0;120  }121  *success = true;122  carry_out = amount <= 32 ? Bit32(value, amount - 1) : 0;123  return value >> amount;124}125 126static inline uint32_t LSR(const uint32_t value, const uint32_t amount,127                           bool *success) {128  *success = true;129  if (amount == 0)130    return value;131  uint32_t dont_care;132  uint32_t result = LSR_C(value, amount, dont_care, success);133  if (*success)134    return result;135  else136    return 0;137}138 139static inline uint32_t ASR_C(const uint32_t value, const uint32_t amount,140                             uint32_t &carry_out, bool *success) {141  if (amount == 0 || amount > 32) {142    *success = false;143    return 0;144  }145  *success = true;146  bool negative = BitIsSet(value, 31);147  if (amount <= 32) {148    carry_out = Bit32(value, amount - 1);149    int64_t extended = llvm::SignExtend64<32>(value);150    return UnsignedBits(extended, amount + 31, amount);151  } else {152    carry_out = (negative ? 1 : 0);153    return (negative ? 0xffffffff : 0);154  }155}156 157static inline uint32_t ASR(const uint32_t value, const uint32_t amount,158                           bool *success) {159  *success = true;160  if (amount == 0)161    return value;162  uint32_t dont_care;163  uint32_t result = ASR_C(value, amount, dont_care, success);164  if (*success)165    return result;166  else167    return 0;168}169 170static inline uint32_t ROR_C(const uint32_t value, const uint32_t amount,171                             uint32_t &carry_out, bool *success) {172  if (amount == 0) {173    *success = false;174    return 0;175  }176  *success = true;177  uint32_t result = llvm::rotr<uint32_t>(value, amount);178  carry_out = Bit32(value, 31);179  return result;180}181 182static inline uint32_t ROR(const uint32_t value, const uint32_t amount,183                           bool *success) {184  *success = true;185  if (amount == 0)186    return value;187  uint32_t dont_care;188  uint32_t result = ROR_C(value, amount, dont_care, success);189  if (*success)190    return result;191  else192    return 0;193}194 195static inline uint32_t RRX_C(const uint32_t value, const uint32_t carry_in,196                             uint32_t &carry_out, bool *success) {197  *success = true;198  carry_out = Bit32(value, 0);199  return Bit32(carry_in, 0) << 31 | Bits32(value, 31, 1);200}201 202static inline uint32_t RRX(const uint32_t value, const uint32_t carry_in,203                           bool *success) {204  *success = true;205  uint32_t dont_care;206  uint32_t result = RRX_C(value, carry_in, dont_care, success);207  if (*success)208    return result;209  else210    return 0;211}212 213static inline uint32_t Shift_C(const uint32_t value, ARM_ShifterType type,214                               const uint32_t amount, const uint32_t carry_in,215                               uint32_t &carry_out, bool *success) {216  if (type == SRType_RRX && amount != 1) {217    *success = false;218    return 0;219  }220  *success = true;221 222  if (amount == 0) {223    carry_out = carry_in;224    return value;225  }226  uint32_t result;227  switch (type) {228  case SRType_LSL:229    result = LSL_C(value, amount, carry_out, success);230    break;231  case SRType_LSR:232    result = LSR_C(value, amount, carry_out, success);233    break;234  case SRType_ASR:235    result = ASR_C(value, amount, carry_out, success);236    break;237  case SRType_ROR:238    result = ROR_C(value, amount, carry_out, success);239    break;240  case SRType_RRX:241    result = RRX_C(value, carry_in, carry_out, success);242    break;243  default:244    *success = false;245    break;246  }247  if (*success)248    return result;249  else250    return 0;251}252 253static inline uint32_t Shift(const uint32_t value, ARM_ShifterType type,254                             const uint32_t amount, const uint32_t carry_in,255                             bool *success) {256  // Don't care about carry out in this case.257  uint32_t dont_care;258  uint32_t result = Shift_C(value, type, amount, carry_in, dont_care, success);259  if (*success)260    return result;261  else262    return 0;263}264 265static inline uint32_t bits(const uint32_t val, const uint32_t msbit,266                            const uint32_t lsbit) {267  return Bits32(val, msbit, lsbit);268}269 270static inline uint32_t bit(const uint32_t val, const uint32_t msbit) {271  return bits(val, msbit, msbit);272}273 274static uint32_t ror(uint32_t val, uint32_t N, uint32_t shift) {275  uint32_t m = shift % N;276  return (val >> m) | (val << (N - m));277}278 279// (imm32, carry_out) = ARMExpandImm_C(imm12, carry_in)280static inline uint32_t ARMExpandImm_C(uint32_t opcode, uint32_t carry_in,281                                      uint32_t &carry_out) {282  uint32_t imm32;                         // the expanded result283  uint32_t imm = bits(opcode, 7, 0);      // immediate value284  uint32_t amt = 2 * bits(opcode, 11, 8); // rotate amount285  if (amt == 0) {286    imm32 = imm;287    carry_out = carry_in;288  } else {289    imm32 = ror(imm, 32, amt);290    carry_out = Bit32(imm32, 31);291  }292  return imm32;293}294 295static inline uint32_t ARMExpandImm(uint32_t opcode) {296  // 'carry_in' argument to following function call does not affect the imm32297  // result.298  uint32_t carry_in = 0;299  uint32_t carry_out;300  return ARMExpandImm_C(opcode, carry_in, carry_out);301}302 303// (imm32, carry_out) = ThumbExpandImm_C(imm12, carry_in)304static inline uint32_t ThumbExpandImm_C(uint32_t opcode, uint32_t carry_in,305                                        uint32_t &carry_out) {306  uint32_t imm32 = 0; // the expanded result307  const uint32_t i = bit(opcode, 26);308  const uint32_t imm3 = bits(opcode, 14, 12);309  const uint32_t abcdefgh = bits(opcode, 7, 0);310  const uint32_t imm12 = i << 11 | imm3 << 8 | abcdefgh;311 312  if (bits(imm12, 11, 10) == 0) {313    switch (bits(imm12, 9, 8)) {314    default: // Keep static analyzer happy with a default case315      break;316 317    case 0:318      imm32 = abcdefgh;319      break;320 321    case 1:322      imm32 = abcdefgh << 16 | abcdefgh;323      break;324 325    case 2:326      imm32 = abcdefgh << 24 | abcdefgh << 8;327      break;328 329    case 3:330      imm32 = abcdefgh << 24 | abcdefgh << 16 | abcdefgh << 8 | abcdefgh;331      break;332    }333    carry_out = carry_in;334  } else {335    const uint32_t unrotated_value = 0x80 | bits(imm12, 6, 0);336    imm32 = ror(unrotated_value, 32, bits(imm12, 11, 7));337    carry_out = Bit32(imm32, 31);338  }339  return imm32;340}341 342static inline uint32_t ThumbExpandImm(uint32_t opcode) {343  // 'carry_in' argument to following function call does not affect the imm32344  // result.345  uint32_t carry_in = 0;346  uint32_t carry_out;347  return ThumbExpandImm_C(opcode, carry_in, carry_out);348}349 350// imm32 = ZeroExtend(i:imm3:imm8, 32)351static inline uint32_t ThumbImm12(uint32_t opcode) {352  const uint32_t i = bit(opcode, 26);353  const uint32_t imm3 = bits(opcode, 14, 12);354  const uint32_t imm8 = bits(opcode, 7, 0);355  const uint32_t imm12 = i << 11 | imm3 << 8 | imm8;356  return imm12;357}358 359// imm32 = ZeroExtend(imm7:'00', 32)360static inline uint32_t ThumbImm7Scaled(uint32_t opcode) {361  const uint32_t imm7 = bits(opcode, 6, 0);362  return imm7 * 4;363}364 365// imm32 = ZeroExtend(imm8:'00', 32)366static inline uint32_t ThumbImm8Scaled(uint32_t opcode) {367  const uint32_t imm8 = bits(opcode, 7, 0);368  return imm8 * 4;369}370 371// This function performs the check for the register numbers 13 and 15 that are372// not permitted for many Thumb register specifiers.373static inline bool BadReg(uint32_t n) { return n == 13 || n == 15; }374 375} // namespace lldb_private376 377#endif // LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_ARMUTILS_H378