Home | History | Annotate | Download | only in aarch32
      1 // Copyright 2015, VIXL authors
      2 // All rights reserved.
      3 //
      4 // Redistribution and use in source and binary forms, with or without
      5 // modification, are permitted provided that the following conditions are met:
      6 //
      7 //   * Redistributions of source code must retain the above copyright notice,
      8 //     this list of conditions and the following disclaimer.
      9 //   * Redistributions in binary form must reproduce the above copyright notice,
     10 //     this list of conditions and the following disclaimer in the documentation
     11 //     and/or other materials provided with the distribution.
     12 //   * Neither the name of ARM Limited nor the names of its contributors may be
     13 //     used to endorse or promote products derived from this software without
     14 //     specific prior written permission.
     15 //
     16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS CONTRIBUTORS "AS IS" AND
     17 // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
     18 // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
     19 // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
     20 // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     21 // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
     22 // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
     23 // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
     24 // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     25 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     26 
     27 #ifndef VIXL_AARCH32_INSTRUCTIONS_AARCH32_H_
     28 #define VIXL_AARCH32_INSTRUCTIONS_AARCH32_H_
     29 
     30 extern "C" {
     31 #include <stdint.h>
     32 }
     33 
     34 #include <algorithm>
     35 #include <ostream>
     36 
     37 #include "utils-vixl.h"
     38 #include "code-buffer-vixl.h"
     39 #include "aarch32/constants-aarch32.h"
     40 #include "aarch32/label-aarch32.h"
     41 
     42 #ifdef __arm__
     43 #define HARDFLOAT __attribute__((noinline, pcs("aapcs-vfp")))
     44 #else
     45 #define HARDFLOAT __attribute__((noinline))
     46 #endif
     47 
     48 namespace vixl {
     49 namespace aarch32 {
     50 
     51 class Operand;
     52 class SOperand;
     53 class DOperand;
     54 class QOperand;
     55 class MemOperand;
     56 class AlignedMemOperand;
     57 
     58 enum AddrMode { Offset = 0, PreIndex = 1, PostIndex = 2 };
     59 
     60 class CPURegister {
     61  public:
     62   enum RegisterType {
     63     kNoRegister = 0,
     64     kRRegister = 1,
     65     kSRegister = 2,
     66     kDRegister = 3,
     67     kQRegister = 4
     68   };
     69 
     70  private:
     71   static const int kCodeBits = 5;
     72   static const int kTypeBits = 4;
     73   static const int kSizeBits = 8;
     74   static const int kCodeShift = 0;
     75   static const int kTypeShift = kCodeShift + kCodeBits;
     76   static const int kSizeShift = kTypeShift + kTypeBits;
     77   static const uint32_t kCodeMask = ((1 << kCodeBits) - 1) << kCodeShift;
     78   static const uint32_t kTypeMask = ((1 << kTypeBits) - 1) << kTypeShift;
     79   static const uint32_t kSizeMask = ((1 << kSizeBits) - 1) << kSizeShift;
     80   uint32_t value_;
     81 
     82  public:
     83   CPURegister(RegisterType type, uint32_t code, int size)
     84       : value_((type << kTypeShift) | (code << kCodeShift) |
     85                (size << kSizeShift)) {
     86 #ifdef VIXL_DEBUG
     87     switch (type) {
     88       case kNoRegister:
     89         break;
     90       case kRRegister:
     91         VIXL_ASSERT(code < kNumberOfRegisters);
     92         VIXL_ASSERT(size == kRegSizeInBits);
     93         break;
     94       case kSRegister:
     95         VIXL_ASSERT(code < kNumberOfSRegisters);
     96         VIXL_ASSERT(size == kSRegSizeInBits);
     97         break;
     98       case kDRegister:
     99         VIXL_ASSERT(code < kMaxNumberOfDRegisters);
    100         VIXL_ASSERT(size == kDRegSizeInBits);
    101         break;
    102       case kQRegister:
    103         VIXL_ASSERT(code < kNumberOfQRegisters);
    104         VIXL_ASSERT(size == kQRegSizeInBits);
    105         break;
    106       default:
    107         VIXL_UNREACHABLE();
    108         break;
    109     }
    110 #endif
    111   }
    112   RegisterType GetType() const {
    113     return static_cast<RegisterType>((value_ & kTypeMask) >> kTypeShift);
    114   }
    115   bool IsRegister() const { return GetType() == kRRegister; }
    116   bool IsS() const { return GetType() == kSRegister; }
    117   bool IsD() const { return GetType() == kDRegister; }
    118   bool IsQ() const { return GetType() == kQRegister; }
    119   bool IsVRegister() const { return IsS() || IsD() || IsQ(); }
    120   bool IsFPRegister() const { return IsS() || IsD(); }
    121   uint32_t GetCode() const { return (value_ & kCodeMask) >> kCodeShift; }
    122   uint32_t GetReg() const { return value_; }
    123   int GetSizeInBits() const { return (value_ & kSizeMask) >> kSizeShift; }
    124   int GetRegSizeInBytes() const {
    125     return (GetType() == kNoRegister) ? 0 : (GetSizeInBits() / 8);
    126   }
    127   bool Is64Bits() const { return GetSizeInBits() == 64; }
    128   bool Is128Bits() const { return GetSizeInBits() == 128; }
    129   bool IsSameFormat(CPURegister reg) {
    130     return (value_ & ~kCodeMask) == (reg.value_ & ~kCodeMask);
    131   }
    132   bool Is(CPURegister ref) const { return GetReg() == ref.GetReg(); }
    133   bool IsValid() const { return GetType() != kNoRegister; }
    134 };
    135 
    136 class Register : public CPURegister {
    137  public:
    138   Register() : CPURegister(kNoRegister, 0, kRegSizeInBits) {}
    139   explicit Register(uint32_t code)
    140       : CPURegister(kRRegister, code % kNumberOfRegisters, kRegSizeInBits) {
    141     VIXL_ASSERT(GetCode() < kNumberOfRegisters);
    142   }
    143   bool Is(Register ref) const { return GetCode() == ref.GetCode(); }
    144   bool IsLow() const { return GetCode() < kNumberOfT32LowRegisters; }
    145   bool IsLR() const { return GetCode() == kLrCode; }
    146   bool IsPC() const { return GetCode() == kPcCode; }
    147   bool IsSP() const { return GetCode() == kSpCode; }
    148 };
    149 
    150 std::ostream& operator<<(std::ostream& os, const Register reg);
    151 
    152 class RegisterOrAPSR_nzcv {
    153   uint32_t code_;
    154 
    155  public:
    156   explicit RegisterOrAPSR_nzcv(uint32_t code) : code_(code) {
    157     VIXL_ASSERT(code_ < kNumberOfRegisters);
    158   }
    159   bool IsAPSR_nzcv() const { return code_ == kPcCode; }
    160   uint32_t GetCode() const { return code_; }
    161   Register AsRegister() const {
    162     VIXL_ASSERT(!IsAPSR_nzcv());
    163     return Register(code_);
    164   }
    165 };
    166 
    167 inline std::ostream& operator<<(std::ostream& os,
    168                                 const RegisterOrAPSR_nzcv reg) {
    169   if (reg.IsAPSR_nzcv()) return os << "APSR_nzcv";
    170   return os << reg.AsRegister();
    171 }
    172 
    173 class SRegister;
    174 class DRegister;
    175 class QRegister;
    176 
    177 class VRegister : public CPURegister {
    178  public:
    179   VRegister() : CPURegister(kNoRegister, 0, 0) {}
    180   VRegister(RegisterType type, uint32_t code, int size)
    181       : CPURegister(type, code, size) {}
    182 
    183   SRegister S() const;
    184   DRegister D() const;
    185   QRegister Q() const;
    186 };
    187 
    188 class SRegister : public VRegister {
    189  public:
    190   SRegister() : VRegister(kNoRegister, 0, kSRegSizeInBits) {}
    191   explicit SRegister(uint32_t code)
    192       : VRegister(kSRegister, code, kSRegSizeInBits) {}
    193   uint32_t Encode(int single_bit_field, int four_bit_field_lowest_bit) const {
    194     if (four_bit_field_lowest_bit == 0) {
    195       return ((GetCode() & 0x1) << single_bit_field) |
    196              ((GetCode() & 0x1e) >> 1);
    197     }
    198     return ((GetCode() & 0x1) << single_bit_field) |
    199            ((GetCode() & 0x1e) << (four_bit_field_lowest_bit - 1));
    200   }
    201 };
    202 
    203 inline unsigned ExtractSRegister(uint32_t instr,
    204                                  int single_bit_field,
    205                                  int four_bit_field_lowest_bit) {
    206   VIXL_ASSERT(single_bit_field > 0);
    207   if (four_bit_field_lowest_bit == 0) {
    208     return ((instr << 1) & 0x1e) | ((instr >> single_bit_field) & 0x1);
    209   }
    210   return ((instr >> (four_bit_field_lowest_bit - 1)) & 0x1e) |
    211          ((instr >> single_bit_field) & 0x1);
    212 }
    213 
    214 inline std::ostream& operator<<(std::ostream& os, const SRegister reg) {
    215   return os << "s" << reg.GetCode();
    216 }
    217 
    218 class DRegister : public VRegister {
    219  public:
    220   DRegister() : VRegister(kNoRegister, 0, kDRegSizeInBits) {}
    221   explicit DRegister(uint32_t code)
    222       : VRegister(kDRegister, code, kDRegSizeInBits) {}
    223   SRegister GetLane(uint32_t lane) const {
    224     uint32_t lane_count = kDRegSizeInBits / kSRegSizeInBits;
    225     VIXL_ASSERT(lane < lane_count);
    226     VIXL_ASSERT(GetCode() * lane_count < kNumberOfSRegisters);
    227     return SRegister(GetCode() * lane_count + lane);
    228   }
    229   uint32_t Encode(int single_bit_field, int four_bit_field_lowest_bit) const {
    230     VIXL_ASSERT(single_bit_field >= 4);
    231     return ((GetCode() & 0x10) << (single_bit_field - 4)) |
    232            ((GetCode() & 0xf) << four_bit_field_lowest_bit);
    233   }
    234 };
    235 
    236 inline unsigned ExtractDRegister(uint32_t instr,
    237                                  int single_bit_field,
    238                                  int four_bit_field_lowest_bit) {
    239   VIXL_ASSERT(single_bit_field >= 4);
    240   return ((instr >> (single_bit_field - 4)) & 0x10) |
    241          ((instr >> four_bit_field_lowest_bit) & 0xf);
    242 }
    243 
    244 inline std::ostream& operator<<(std::ostream& os, const DRegister reg) {
    245   return os << "d" << reg.GetCode();
    246 }
    247 
    248 enum DataTypeType {
    249   kDataTypeS = 0x100,
    250   kDataTypeU = 0x200,
    251   kDataTypeF = 0x300,
    252   kDataTypeI = 0x400,
    253   kDataTypeP = 0x500,
    254   kDataTypeUntyped = 0x600
    255 };
    256 const int kDataTypeSizeMask = 0x0ff;
    257 const int kDataTypeTypeMask = 0x100;
    258 enum DataTypeValue {
    259   kDataTypeValueInvalid = 0x000,
    260   kDataTypeValueNone = 0x001,  // value used when dt is ignored.
    261   S8 = kDataTypeS | 8,
    262   S16 = kDataTypeS | 16,
    263   S32 = kDataTypeS | 32,
    264   S64 = kDataTypeS | 64,
    265   U8 = kDataTypeU | 8,
    266   U16 = kDataTypeU | 16,
    267   U32 = kDataTypeU | 32,
    268   U64 = kDataTypeU | 64,
    269   F16 = kDataTypeF | 16,
    270   F32 = kDataTypeF | 32,
    271   F64 = kDataTypeF | 64,
    272   I8 = kDataTypeI | 8,
    273   I16 = kDataTypeI | 16,
    274   I32 = kDataTypeI | 32,
    275   I64 = kDataTypeI | 64,
    276   P8 = kDataTypeP | 8,
    277   P64 = kDataTypeP | 64,
    278   Untyped8 = kDataTypeUntyped | 8,
    279   Untyped16 = kDataTypeUntyped | 16,
    280   Untyped32 = kDataTypeUntyped | 32,
    281   Untyped64 = kDataTypeUntyped | 64
    282 };
    283 
    284 class DataType {
    285   DataTypeValue value_;
    286 
    287  public:
    288   explicit DataType(uint32_t size)
    289       : value_(static_cast<DataTypeValue>(kDataTypeUntyped | size)) {
    290     VIXL_ASSERT((size == 8) || (size == 16) || (size == 32) || (size == 64));
    291   }
    292   // Users should be able to use "S8", "S6" and so forth to instantiate this
    293   // class.
    294   DataType(DataTypeValue value) : value_(value) {}  // NOLINT(runtime/explicit)
    295   DataTypeValue GetValue() const { return value_; }
    296   DataTypeType GetType() const {
    297     return static_cast<DataTypeType>(value_ & kDataTypeTypeMask);
    298   }
    299   uint32_t GetSize() const { return value_ & kDataTypeSizeMask; }
    300   bool IsSize(uint32_t size) const {
    301     return (value_ & kDataTypeSizeMask) == size;
    302   }
    303   const char* GetName() const;
    304   bool Is(DataTypeValue value) const { return value_ == value; }
    305   bool Is(DataTypeType type) const { return GetType() == type; }
    306   bool IsNoneOr(DataTypeValue value) const {
    307     return (value_ == value) || (value_ == kDataTypeValueNone);
    308   }
    309   bool Is(DataTypeType type, uint32_t size) const {
    310     return value_ == static_cast<DataTypeValue>(type | size);
    311   }
    312   bool IsNoneOr(DataTypeType type, uint32_t size) const {
    313     return Is(type, size) || Is(kDataTypeValueNone);
    314   }
    315 };
    316 
    317 inline std::ostream& operator<<(std::ostream& os, DataType dt) {
    318   return os << dt.GetName();
    319 }
    320 
    321 class DRegisterLane : public DRegister {
    322   uint32_t lane_;
    323 
    324  public:
    325   DRegisterLane(DRegister reg, uint32_t lane)
    326       : DRegister(reg.GetCode()), lane_(lane) {}
    327   DRegisterLane(uint32_t code, uint32_t lane) : DRegister(code), lane_(lane) {}
    328   uint32_t GetLane() const { return lane_; }
    329   uint32_t EncodeX(DataType dt,
    330                    int single_bit_field,
    331                    int four_bit_field_lowest_bit) const {
    332     VIXL_ASSERT(single_bit_field >= 4);
    333     uint32_t value = lane_ << ((dt.GetSize() == 16) ? 3 : 4) | GetCode();
    334     return ((value & 0x10) << (single_bit_field - 4)) |
    335            ((value & 0xf) << four_bit_field_lowest_bit);
    336   }
    337 };
    338 
    339 inline unsigned ExtractDRegisterAndLane(uint32_t instr,
    340                                         DataType dt,
    341                                         int single_bit_field,
    342                                         int four_bit_field_lowest_bit,
    343                                         int* lane) {
    344   VIXL_ASSERT(single_bit_field >= 4);
    345   uint32_t value = ((instr >> (single_bit_field - 4)) & 0x10) |
    346                    ((instr >> four_bit_field_lowest_bit) & 0xf);
    347   if (dt.GetSize() == 16) {
    348     *lane = value >> 3;
    349     return value & 0x7;
    350   }
    351   *lane = value >> 4;
    352   return value & 0xf;
    353 }
    354 
    355 inline std::ostream& operator<<(std::ostream& os, const DRegisterLane lane) {
    356   os << "d" << lane.GetCode() << "[";
    357   if (lane.GetLane() == static_cast<uint32_t>(-1)) return os << "??]";
    358   return os << lane.GetLane() << "]";
    359 }
    360 
    361 class QRegister : public VRegister {
    362  public:
    363   QRegister() : VRegister(kNoRegister, 0, kQRegSizeInBits) {}
    364   explicit QRegister(uint32_t code)
    365       : VRegister(kQRegister, code, kQRegSizeInBits) {}
    366   uint32_t Encode(int offset) { return GetCode() << offset; }
    367   DRegister GetDLane(uint32_t lane) const {
    368     uint32_t lane_count = kQRegSizeInBits / kDRegSizeInBits;
    369     VIXL_ASSERT(lane < lane_count);
    370     return DRegister(GetCode() * lane_count + lane);
    371   }
    372   DRegister GetLowDRegister() const { return DRegister(GetCode() * 2); }
    373   DRegister GetHighDRegister() const { return DRegister(1 + GetCode() * 2); }
    374   SRegister GetSLane(uint32_t lane) const {
    375     uint32_t lane_count = kQRegSizeInBits / kSRegSizeInBits;
    376     VIXL_ASSERT(lane < lane_count);
    377     VIXL_ASSERT(GetCode() * lane_count < kNumberOfSRegisters);
    378     return SRegister(GetCode() * lane_count + lane);
    379   }
    380   uint32_t Encode(int single_bit_field, int four_bit_field_lowest_bit) {
    381     // Encode "code * 2".
    382     VIXL_ASSERT(single_bit_field >= 3);
    383     return ((GetCode() & 0x8) << (single_bit_field - 3)) |
    384            ((GetCode() & 0x7) << (four_bit_field_lowest_bit + 1));
    385   }
    386 };
    387 
    388 inline unsigned ExtractQRegister(uint32_t instr,
    389                                  int single_bit_field,
    390                                  int four_bit_field_lowest_bit) {
    391   VIXL_ASSERT(single_bit_field >= 3);
    392   return ((instr >> (single_bit_field - 3)) & 0x8) |
    393          ((instr >> (four_bit_field_lowest_bit + 1)) & 0x7);
    394 }
    395 
    396 inline std::ostream& operator<<(std::ostream& os, const QRegister reg) {
    397   return os << "q" << reg.GetCode();
    398 }
    399 
    400 // clang-format off
    401 #define AARCH32_REGISTER_CODE_LIST(R)                                          \
    402   R(0)  R(1)  R(2)  R(3)  R(4)  R(5)  R(6)  R(7)                               \
    403   R(8)  R(9)  R(10) R(11) R(12) R(13) R(14) R(15)
    404 // clang-format on
    405 #define DEFINE_REGISTER(N) const Register r##N(N);
    406 AARCH32_REGISTER_CODE_LIST(DEFINE_REGISTER)
    407 #undef DEFINE_REGISTER
    408 #undef AARCH32_REGISTER_CODE_LIST
    409 
    410 enum RegNum { kIPRegNum = 12, kSPRegNum = 13, kLRRegNum = 14, kPCRegNum = 15 };
    411 
    412 const Register ip(kIPRegNum);
    413 const Register sp(kSPRegNum);
    414 const Register pc(kPCRegNum);
    415 const Register lr(kLRRegNum);
    416 const Register NoReg;
    417 const VRegister NoVReg;
    418 
    419 // clang-format off
    420 #define SREGISTER_CODE_LIST(R)                                                 \
    421   R(0)  R(1)  R(2)  R(3)  R(4)  R(5)  R(6)  R(7)                               \
    422   R(8)  R(9)  R(10) R(11) R(12) R(13) R(14) R(15)                              \
    423   R(16) R(17) R(18) R(19) R(20) R(21) R(22) R(23)                              \
    424   R(24) R(25) R(26) R(27) R(28) R(29) R(30) R(31)
    425 // clang-format on
    426 #define DEFINE_REGISTER(N) const SRegister s##N(N);
    427 SREGISTER_CODE_LIST(DEFINE_REGISTER)
    428 #undef DEFINE_REGISTER
    429 #undef SREGISTER_CODE_LIST
    430 const SRegister NoSReg;
    431 
    432 // clang-format off
    433 #define DREGISTER_CODE_LIST(R)                                                 \
    434 R(0)  R(1)  R(2)  R(3)  R(4)  R(5)  R(6)  R(7)                                 \
    435 R(8)  R(9)  R(10) R(11) R(12) R(13) R(14) R(15)                                \
    436 R(16) R(17) R(18) R(19) R(20) R(21) R(22) R(23)                                \
    437 R(24) R(25) R(26) R(27) R(28) R(29) R(30) R(31)
    438 // clang-format on
    439 #define DEFINE_REGISTER(N) const DRegister d##N(N);
    440 DREGISTER_CODE_LIST(DEFINE_REGISTER)
    441 #undef DEFINE_REGISTER
    442 #undef DREGISTER_CODE_LIST
    443 const DRegister NoDReg;
    444 
    445 // clang-format off
    446 #define QREGISTER_CODE_LIST(R)                                                 \
    447   R(0)  R(1)  R(2)  R(3)  R(4)  R(5)  R(6)  R(7)                               \
    448   R(8)  R(9)  R(10) R(11) R(12) R(13) R(14) R(15)
    449 // clang-format on
    450 #define DEFINE_REGISTER(N) const QRegister q##N(N);
    451 QREGISTER_CODE_LIST(DEFINE_REGISTER)
    452 #undef DEFINE_REGISTER
    453 #undef QREGISTER_CODE_LIST
    454 const QRegister NoQReg;
    455 
    456 class RegisterList {
    457  public:
    458   RegisterList() : list_(0) {}
    459   RegisterList(Register reg)  // NOLINT(runtime/explicit)
    460       : list_(RegisterToList(reg)) {}
    461   RegisterList(Register reg1, Register reg2)
    462       : list_(RegisterToList(reg1) | RegisterToList(reg2)) {}
    463   RegisterList(Register reg1, Register reg2, Register reg3)
    464       : list_(RegisterToList(reg1) | RegisterToList(reg2) |
    465               RegisterToList(reg3)) {}
    466   RegisterList(Register reg1, Register reg2, Register reg3, Register reg4)
    467       : list_(RegisterToList(reg1) | RegisterToList(reg2) |
    468               RegisterToList(reg3) | RegisterToList(reg4)) {}
    469   explicit RegisterList(uint32_t list) : list_(list) {}
    470   uint32_t GetList() const { return list_; }
    471   void SetList(uint32_t list) { list_ = list; }
    472   bool Includes(const Register& reg) const {
    473     return (list_ & RegisterToList(reg)) != 0;
    474   }
    475   void Combine(const RegisterList& other) { list_ |= other.GetList(); }
    476   void Combine(const Register& reg) { list_ |= RegisterToList(reg); }
    477   void Remove(const RegisterList& other) { list_ &= ~other.GetList(); }
    478   void Remove(const Register& reg) { list_ &= ~RegisterToList(reg); }
    479   bool Overlaps(const RegisterList& other) const {
    480     return (list_ & other.list_) != 0;
    481   }
    482   bool IsR0toR7orPC() const {
    483     // True if all the registers from the list are not from r8-r14.
    484     return (list_ & 0x7f00) == 0;
    485   }
    486   bool IsR0toR7orLR() const {
    487     // True if all the registers from the list are not from r8-r13 nor from r15.
    488     return (list_ & 0xbf00) == 0;
    489   }
    490   Register GetFirstAvailableRegister() const;
    491   bool IsEmpty() const { return list_ == 0; }
    492   static RegisterList Union(const RegisterList& list_1,
    493                             const RegisterList& list_2) {
    494     return RegisterList(list_1.list_ | list_2.list_);
    495   }
    496   static RegisterList Union(const RegisterList& list_1,
    497                             const RegisterList& list_2,
    498                             const RegisterList& list_3) {
    499     return Union(list_1, Union(list_2, list_3));
    500   }
    501   static RegisterList Union(const RegisterList& list_1,
    502                             const RegisterList& list_2,
    503                             const RegisterList& list_3,
    504                             const RegisterList& list_4) {
    505     return Union(Union(list_1, list_2), Union(list_3, list_4));
    506   }
    507   static RegisterList Intersection(const RegisterList& list_1,
    508                                    const RegisterList& list_2) {
    509     return RegisterList(list_1.list_ & list_2.list_);
    510   }
    511   static RegisterList Intersection(const RegisterList& list_1,
    512                                    const RegisterList& list_2,
    513                                    const RegisterList& list_3) {
    514     return Intersection(list_1, Intersection(list_2, list_3));
    515   }
    516   static RegisterList Intersection(const RegisterList& list_1,
    517                                    const RegisterList& list_2,
    518                                    const RegisterList& list_3,
    519                                    const RegisterList& list_4) {
    520     return Intersection(Intersection(list_1, list_2),
    521                         Intersection(list_3, list_4));
    522   }
    523 
    524  private:
    525   static uint32_t RegisterToList(Register reg) {
    526     if (reg.GetType() == CPURegister::kNoRegister) {
    527       return 0;
    528     } else {
    529       return UINT32_C(1) << reg.GetCode();
    530     }
    531   }
    532 
    533   // Bitfield representation of all registers in the list
    534   // (1 for r0, 2 for r1, 4 for r2, ...).
    535   uint32_t list_;
    536 };
    537 
    538 inline uint32_t GetRegisterListEncoding(const RegisterList& registers,
    539                                         int first,
    540                                         int count) {
    541   return (registers.GetList() >> first) & ((1 << count) - 1);
    542 }
    543 
    544 std::ostream& operator<<(std::ostream& os, RegisterList registers);
    545 
    546 class VRegisterList {
    547  public:
    548   VRegisterList() : list_(0) {}
    549   explicit VRegisterList(VRegister reg) : list_(RegisterToList(reg)) {}
    550   VRegisterList(VRegister reg1, VRegister reg2)
    551       : list_(RegisterToList(reg1) | RegisterToList(reg2)) {}
    552   VRegisterList(VRegister reg1, VRegister reg2, VRegister reg3)
    553       : list_(RegisterToList(reg1) | RegisterToList(reg2) |
    554               RegisterToList(reg3)) {}
    555   VRegisterList(VRegister reg1, VRegister reg2, VRegister reg3, VRegister reg4)
    556       : list_(RegisterToList(reg1) | RegisterToList(reg2) |
    557               RegisterToList(reg3) | RegisterToList(reg4)) {}
    558   explicit VRegisterList(uint64_t list) : list_(list) {}
    559   uint64_t GetList() const { return list_; }
    560   void SetList(uint64_t list) { list_ = list; }
    561   // Because differently-sized V registers overlap with one another, there is no
    562   // way to implement a single 'Includes' function in a way that is unsurprising
    563   // for all existing uses.
    564   bool IncludesAllOf(const VRegister& reg) const {
    565     return (list_ & RegisterToList(reg)) == RegisterToList(reg);
    566   }
    567   bool IncludesAliasOf(const VRegister& reg) const {
    568     return (list_ & RegisterToList(reg)) != 0;
    569   }
    570   void Combine(const VRegisterList& other) { list_ |= other.GetList(); }
    571   void Combine(const VRegister& reg) { list_ |= RegisterToList(reg); }
    572   void Remove(const VRegisterList& other) { list_ &= ~other.GetList(); }
    573   void Remove(const VRegister& reg) { list_ &= ~RegisterToList(reg); }
    574   bool Overlaps(const VRegisterList& other) const {
    575     return (list_ & other.list_) != 0;
    576   }
    577   QRegister GetFirstAvailableQRegister() const;
    578   DRegister GetFirstAvailableDRegister() const;
    579   SRegister GetFirstAvailableSRegister() const;
    580   bool IsEmpty() const { return list_ == 0; }
    581   static VRegisterList Union(const VRegisterList& list_1,
    582                              const VRegisterList& list_2) {
    583     return VRegisterList(list_1.list_ | list_2.list_);
    584   }
    585   static VRegisterList Union(const VRegisterList& list_1,
    586                              const VRegisterList& list_2,
    587                              const VRegisterList& list_3) {
    588     return Union(list_1, Union(list_2, list_3));
    589   }
    590   static VRegisterList Union(const VRegisterList& list_1,
    591                              const VRegisterList& list_2,
    592                              const VRegisterList& list_3,
    593                              const VRegisterList& list_4) {
    594     return Union(Union(list_1, list_2), Union(list_3, list_4));
    595   }
    596   static VRegisterList Intersection(const VRegisterList& list_1,
    597                                     const VRegisterList& list_2) {
    598     return VRegisterList(list_1.list_ & list_2.list_);
    599   }
    600   static VRegisterList Intersection(const VRegisterList& list_1,
    601                                     const VRegisterList& list_2,
    602                                     const VRegisterList& list_3) {
    603     return Intersection(list_1, Intersection(list_2, list_3));
    604   }
    605   static VRegisterList Intersection(const VRegisterList& list_1,
    606                                     const VRegisterList& list_2,
    607                                     const VRegisterList& list_3,
    608                                     const VRegisterList& list_4) {
    609     return Intersection(Intersection(list_1, list_2),
    610                         Intersection(list_3, list_4));
    611   }
    612 
    613  private:
    614   static uint64_t RegisterToList(VRegister reg) {
    615     if (reg.GetType() == CPURegister::kNoRegister) {
    616       return 0;
    617     } else {
    618       switch (reg.GetSizeInBits()) {
    619         case kQRegSizeInBits:
    620           return UINT64_C(0xf) << (reg.GetCode() * 4);
    621         case kDRegSizeInBits:
    622           return UINT64_C(0x3) << (reg.GetCode() * 2);
    623         case kSRegSizeInBits:
    624           return UINT64_C(0x1) << reg.GetCode();
    625         default:
    626           VIXL_UNREACHABLE();
    627           return 0;
    628       }
    629     }
    630   }
    631 
    632   // Bitfield representation of all registers in the list.
    633   // (0x3 for d0, 0xc0 for d1, 0x30 for d2, ...). We have one, two or four bits
    634   // per register according to their size. This way we can make sure that we
    635   // account for overlapping registers.
    636   // A register is wholly included in this list only if all of its bits are set.
    637   // A register is aliased by the list if at least one of its bits are set.
    638   // The IncludesAllOf and IncludesAliasOf helpers are provided to make this
    639   // distinction clear.
    640   uint64_t list_;
    641 };
    642 
    643 class SRegisterList {
    644   SRegister first_;
    645   int length_;
    646 
    647  public:
    648   explicit SRegisterList(SRegister reg) : first_(reg.GetCode()), length_(1) {}
    649   SRegisterList(SRegister first, int length)
    650       : first_(first.GetCode()), length_(length) {
    651     VIXL_ASSERT(length >= 0);
    652   }
    653   SRegister GetSRegister(int n) const {
    654     VIXL_ASSERT(n >= 0);
    655     VIXL_ASSERT(n < length_);
    656     return SRegister((first_.GetCode() + n) % kNumberOfSRegisters);
    657   }
    658   const SRegister& GetFirstSRegister() const { return first_; }
    659   SRegister GetLastSRegister() const { return GetSRegister(length_ - 1); }
    660   int GetLength() const { return length_; }
    661 };
    662 
    663 std::ostream& operator<<(std::ostream& os, SRegisterList registers);
    664 
    665 class DRegisterList {
    666   DRegister first_;
    667   int length_;
    668 
    669  public:
    670   explicit DRegisterList(DRegister reg) : first_(reg.GetCode()), length_(1) {}
    671   DRegisterList(DRegister first, int length)
    672       : first_(first.GetCode()), length_(length) {
    673     VIXL_ASSERT(length >= 0);
    674   }
    675   DRegister GetDRegister(int n) const {
    676     VIXL_ASSERT(n >= 0);
    677     VIXL_ASSERT(n < length_);
    678     return DRegister((first_.GetCode() + n) % kMaxNumberOfDRegisters);
    679   }
    680   const DRegister& GetFirstDRegister() const { return first_; }
    681   DRegister GetLastDRegister() const { return GetDRegister(length_ - 1); }
    682   int GetLength() const { return length_; }
    683 };
    684 
    685 std::ostream& operator<<(std::ostream& os, DRegisterList registers);
    686 
    687 enum SpacingType { kSingle, kDouble };
    688 
    689 enum TransferType { kMultipleLanes, kOneLane, kAllLanes };
    690 
    691 class NeonRegisterList {
    692   DRegister first_;
    693   SpacingType spacing_;
    694   TransferType type_;
    695   int lane_;
    696   int length_;
    697 
    698  public:
    699   NeonRegisterList(DRegister reg, TransferType type)
    700       : first_(reg.GetCode()),
    701         spacing_(kSingle),
    702         type_(type),
    703         lane_(-1),
    704         length_(1) {
    705     VIXL_ASSERT(type_ != kOneLane);
    706   }
    707   NeonRegisterList(DRegister reg, int lane)
    708       : first_(reg.GetCode()),
    709         spacing_(kSingle),
    710         type_(kOneLane),
    711         lane_(lane),
    712         length_(1) {
    713     VIXL_ASSERT((lane_ >= 0) && (lane_ < 4));
    714   }
    715   NeonRegisterList(DRegister first,
    716                    DRegister last,
    717                    SpacingType spacing,
    718                    TransferType type)
    719       : first_(first.GetCode()), spacing_(spacing), type_(type), lane_(-1) {
    720     VIXL_ASSERT(type != kOneLane);
    721     VIXL_ASSERT(first.GetCode() <= last.GetCode());
    722 
    723     int range = last.GetCode() - first.GetCode();
    724     VIXL_ASSERT(IsSingleSpaced() || IsMultiple(range, 2));
    725     length_ = (IsDoubleSpaced() ? (range / 2) : range) + 1;
    726 
    727     VIXL_ASSERT(length_ <= 4);
    728   }
    729   NeonRegisterList(DRegister first,
    730                    DRegister last,
    731                    SpacingType spacing,
    732                    int lane)
    733       : first_(first.GetCode()),
    734         spacing_(spacing),
    735         type_(kOneLane),
    736         lane_(lane) {
    737     VIXL_ASSERT((lane >= 0) && (lane < 4));
    738     VIXL_ASSERT(first.GetCode() <= last.GetCode());
    739 
    740     int range = last.GetCode() - first.GetCode();
    741     VIXL_ASSERT(IsSingleSpaced() || IsMultiple(range, 2));
    742     length_ = (IsDoubleSpaced() ? (range / 2) : range) + 1;
    743 
    744     VIXL_ASSERT(length_ <= 4);
    745   }
    746   DRegister GetDRegister(int n) const {
    747     VIXL_ASSERT(n >= 0);
    748     VIXL_ASSERT(n < length_);
    749     unsigned code = first_.GetCode() + (IsDoubleSpaced() ? (2 * n) : n);
    750     VIXL_ASSERT(code < kMaxNumberOfDRegisters);
    751     return DRegister(code);
    752   }
    753   const DRegister& GetFirstDRegister() const { return first_; }
    754   DRegister GetLastDRegister() const { return GetDRegister(length_ - 1); }
    755   int GetLength() const { return length_; }
    756   bool IsSingleSpaced() const { return spacing_ == kSingle; }
    757   bool IsDoubleSpaced() const { return spacing_ == kDouble; }
    758   bool IsTransferAllLanes() const { return type_ == kAllLanes; }
    759   bool IsTransferOneLane() const { return type_ == kOneLane; }
    760   bool IsTransferMultipleLanes() const { return type_ == kMultipleLanes; }
    761   int GetTransferLane() const { return lane_; }
    762 };
    763 
    764 std::ostream& operator<<(std::ostream& os, NeonRegisterList registers);
    765 
    766 enum SpecialRegisterType { APSR = 0, CPSR = 0, SPSR = 1 };
    767 
    768 class SpecialRegister {
    769   uint32_t reg_;
    770 
    771  public:
    772   explicit SpecialRegister(uint32_t reg) : reg_(reg) {}
    773   SpecialRegister(SpecialRegisterType reg)  // NOLINT(runtime/explicit)
    774       : reg_(reg) {}
    775   uint32_t GetReg() const { return reg_; }
    776   const char* GetName() const;
    777   bool Is(SpecialRegister value) const { return reg_ == value.reg_; }
    778   bool Is(uint32_t value) const { return reg_ == value; }
    779   bool IsNot(uint32_t value) const { return reg_ != value; }
    780 };
    781 
    782 inline std::ostream& operator<<(std::ostream& os, SpecialRegister reg) {
    783   return os << reg.GetName();
    784 }
    785 
    786 enum BankedRegisterType {
    787   R8_usr = 0x00,
    788   R9_usr = 0x01,
    789   R10_usr = 0x02,
    790   R11_usr = 0x03,
    791   R12_usr = 0x04,
    792   SP_usr = 0x05,
    793   LR_usr = 0x06,
    794   R8_fiq = 0x08,
    795   R9_fiq = 0x09,
    796   R10_fiq = 0x0a,
    797   R11_fiq = 0x0b,
    798   R12_fiq = 0x0c,
    799   SP_fiq = 0x0d,
    800   LR_fiq = 0x0e,
    801   LR_irq = 0x10,
    802   SP_irq = 0x11,
    803   LR_svc = 0x12,
    804   SP_svc = 0x13,
    805   LR_abt = 0x14,
    806   SP_abt = 0x15,
    807   LR_und = 0x16,
    808   SP_und = 0x17,
    809   LR_mon = 0x1c,
    810   SP_mon = 0x1d,
    811   ELR_hyp = 0x1e,
    812   SP_hyp = 0x1f,
    813   SPSR_fiq = 0x2e,
    814   SPSR_irq = 0x30,
    815   SPSR_svc = 0x32,
    816   SPSR_abt = 0x34,
    817   SPSR_und = 0x36,
    818   SPSR_mon = 0x3c,
    819   SPSR_hyp = 0x3e
    820 };
    821 
    822 class BankedRegister {
    823   uint32_t reg_;
    824 
    825  public:
    826   explicit BankedRegister(unsigned reg) : reg_(reg) {}
    827   BankedRegister(BankedRegisterType reg)  // NOLINT(runtime/explicit)
    828       : reg_(reg) {}
    829   uint32_t GetCode() const { return reg_; }
    830   const char* GetName() const;
    831 };
    832 
    833 inline std::ostream& operator<<(std::ostream& os, BankedRegister reg) {
    834   return os << reg.GetName();
    835 }
    836 
    837 enum MaskedSpecialRegisterType {
    838   APSR_nzcvq = 0x08,
    839   APSR_g = 0x04,
    840   APSR_nzcvqg = 0x0c,
    841   CPSR_c = 0x01,
    842   CPSR_x = 0x02,
    843   CPSR_xc = 0x03,
    844   CPSR_s = APSR_g,
    845   CPSR_sc = 0x05,
    846   CPSR_sx = 0x06,
    847   CPSR_sxc = 0x07,
    848   CPSR_f = APSR_nzcvq,
    849   CPSR_fc = 0x09,
    850   CPSR_fx = 0x0a,
    851   CPSR_fxc = 0x0b,
    852   CPSR_fs = APSR_nzcvqg,
    853   CPSR_fsc = 0x0d,
    854   CPSR_fsx = 0x0e,
    855   CPSR_fsxc = 0x0f,
    856   SPSR_c = 0x11,
    857   SPSR_x = 0x12,
    858   SPSR_xc = 0x13,
    859   SPSR_s = 0x14,
    860   SPSR_sc = 0x15,
    861   SPSR_sx = 0x16,
    862   SPSR_sxc = 0x17,
    863   SPSR_f = 0x18,
    864   SPSR_fc = 0x19,
    865   SPSR_fx = 0x1a,
    866   SPSR_fxc = 0x1b,
    867   SPSR_fs = 0x1c,
    868   SPSR_fsc = 0x1d,
    869   SPSR_fsx = 0x1e,
    870   SPSR_fsxc = 0x1f
    871 };
    872 
    873 class MaskedSpecialRegister {
    874   uint32_t reg_;
    875 
    876  public:
    877   explicit MaskedSpecialRegister(uint32_t reg) : reg_(reg) {
    878     VIXL_ASSERT(reg <= SPSR_fsxc);
    879   }
    880   MaskedSpecialRegister(
    881       MaskedSpecialRegisterType reg)  // NOLINT(runtime/explicit)
    882       : reg_(reg) {}
    883   uint32_t GetReg() const { return reg_; }
    884   const char* GetName() const;
    885   bool Is(MaskedSpecialRegister value) const { return reg_ == value.reg_; }
    886   bool Is(uint32_t value) const { return reg_ == value; }
    887   bool IsNot(uint32_t value) const { return reg_ != value; }
    888 };
    889 
    890 inline std::ostream& operator<<(std::ostream& os, MaskedSpecialRegister reg) {
    891   return os << reg.GetName();
    892 }
    893 
    894 enum SpecialFPRegisterType {
    895   FPSID = 0x0,
    896   FPSCR = 0x1,
    897   MVFR2 = 0x5,
    898   MVFR1 = 0x6,
    899   MVFR0 = 0x7,
    900   FPEXC = 0x8
    901 };
    902 
    903 class SpecialFPRegister {
    904   uint32_t reg_;
    905 
    906  public:
    907   explicit SpecialFPRegister(uint32_t reg) : reg_(reg) {
    908 #ifdef VIXL_DEBUG
    909     switch (reg) {
    910       case FPSID:
    911       case FPSCR:
    912       case MVFR2:
    913       case MVFR1:
    914       case MVFR0:
    915       case FPEXC:
    916         break;
    917       default:
    918         VIXL_UNREACHABLE();
    919     }
    920 #endif
    921   }
    922   SpecialFPRegister(SpecialFPRegisterType reg)  // NOLINT(runtime/explicit)
    923       : reg_(reg) {}
    924   uint32_t GetReg() const { return reg_; }
    925   const char* GetName() const;
    926   bool Is(SpecialFPRegister value) const { return reg_ == value.reg_; }
    927   bool Is(uint32_t value) const { return reg_ == value; }
    928   bool IsNot(uint32_t value) const { return reg_ != value; }
    929 };
    930 
    931 inline std::ostream& operator<<(std::ostream& os, SpecialFPRegister reg) {
    932   return os << reg.GetName();
    933 }
    934 
    935 class CRegister {
    936   uint32_t code_;
    937 
    938  public:
    939   explicit CRegister(uint32_t code) : code_(code) {
    940     VIXL_ASSERT(code < kNumberOfRegisters);
    941   }
    942   uint32_t GetCode() const { return code_; }
    943   bool Is(CRegister value) const { return code_ == value.code_; }
    944 };
    945 
    946 inline std::ostream& operator<<(std::ostream& os, const CRegister reg) {
    947   return os << "c" << reg.GetCode();
    948 }
    949 
    950 // clang-format off
    951 #define CREGISTER_CODE_LIST(R)                                                 \
    952   R(0)  R(1)  R(2)  R(3)  R(4)  R(5)  R(6)  R(7)                               \
    953   R(8)  R(9)  R(10) R(11) R(12) R(13) R(14) R(15)
    954 // clang-format on
    955 #define DEFINE_CREGISTER(N) const CRegister c##N(N);
    956 CREGISTER_CODE_LIST(DEFINE_CREGISTER)
    957 
    958 enum CoprocessorName { p10 = 10, p11 = 11, p14 = 14, p15 = 15 };
    959 
    960 class Coprocessor {
    961   uint32_t coproc_;
    962 
    963  public:
    964   explicit Coprocessor(uint32_t coproc) : coproc_(coproc) {}
    965   Coprocessor(CoprocessorName coproc)  // NOLINT(runtime/explicit)
    966       : coproc_(static_cast<uint32_t>(coproc)) {}
    967   bool Is(Coprocessor coproc) const { return coproc_ == coproc.coproc_; }
    968   bool Is(CoprocessorName coproc) const { return coproc_ == coproc; }
    969   uint32_t GetCoprocessor() const { return coproc_; }
    970 };
    971 
    972 inline std::ostream& operator<<(std::ostream& os, Coprocessor coproc) {
    973   return os << "p" << coproc.GetCoprocessor();
    974 }
    975 
    976 enum ConditionType {
    977   eq = 0,
    978   ne = 1,
    979   cs = 2,
    980   cc = 3,
    981   mi = 4,
    982   pl = 5,
    983   vs = 6,
    984   vc = 7,
    985   hi = 8,
    986   ls = 9,
    987   ge = 10,
    988   lt = 11,
    989   gt = 12,
    990   le = 13,
    991   al = 14,
    992   hs = cs,
    993   lo = cc
    994 };
    995 
    996 class Condition {
    997   uint32_t condition_;
    998   static const uint32_t kNever = 15;
    999   static const uint32_t kMask = 0xf;
   1000   static const uint32_t kNone = 0x10 | al;
   1001 
   1002  public:
   1003   static const Condition None() { return Condition(kNone); }
   1004   explicit Condition(uint32_t condition) : condition_(condition) {
   1005     VIXL_ASSERT(condition <= kNone);
   1006   }
   1007   // Users should be able to use "eq", "ne" and so forth to instantiate this
   1008   // class.
   1009   Condition(ConditionType condition)  // NOLINT(runtime/explicit)
   1010       : condition_(condition) {}
   1011   uint32_t GetCondition() const { return condition_ & kMask; }
   1012   bool IsNone() const { return condition_ == kNone; }
   1013   const char* GetName() const;
   1014   bool Is(Condition value) const { return condition_ == value.condition_; }
   1015   bool Is(uint32_t value) const { return condition_ == value; }
   1016   bool IsNot(uint32_t value) const { return condition_ != value; }
   1017   bool IsNever() const { return condition_ == kNever; }
   1018   bool IsNotNever() const { return condition_ != kNever; }
   1019   Condition Negate() const {
   1020     VIXL_ASSERT(IsNot(al) && IsNot(kNever));
   1021     return Condition(condition_ ^ 1);
   1022   }
   1023 };
   1024 
   1025 inline std::ostream& operator<<(std::ostream& os, Condition condition) {
   1026   return os << condition.GetName();
   1027 }
   1028 
   1029 enum SignType { plus, minus };
   1030 
   1031 class Sign {
   1032  public:
   1033   Sign() : sign_(plus) {}
   1034   Sign(SignType sign) : sign_(sign) {}  // NOLINT(runtime/explicit)
   1035   const char* GetName() const { return (IsPlus() ? "" : "-"); }
   1036   bool IsPlus() const { return sign_ == plus; }
   1037   bool IsMinus() const { return sign_ == minus; }
   1038   int32_t ApplyTo(uint32_t value) { return IsPlus() ? value : -value; }
   1039 
   1040  private:
   1041   SignType sign_;
   1042 };
   1043 
   1044 inline std::ostream& operator<<(std::ostream& os, Sign sign) {
   1045   return os << sign.GetName();
   1046 }
   1047 
   1048 enum ShiftType { LSL = 0x0, LSR = 0x1, ASR = 0x2, ROR = 0x3, RRX = 0x4 };
   1049 
   1050 class Shift {
   1051  public:
   1052   Shift() : shift_(LSL) {}
   1053   Shift(ShiftType shift) : shift_(shift) {}  // NOLINT(runtime/explicit)
   1054   explicit Shift(uint32_t shift) : shift_(static_cast<ShiftType>(shift)) {}
   1055   const Shift& GetShift() const { return *this; }
   1056   ShiftType GetType() const { return shift_; }
   1057   uint32_t GetValue() const { return shift_; }
   1058   const char* GetName() const;
   1059   bool IsLSL() const { return shift_ == LSL; }
   1060   bool IsLSR() const { return shift_ == LSR; }
   1061   bool IsASR() const { return shift_ == ASR; }
   1062   bool IsROR() const { return shift_ == ROR; }
   1063   bool IsRRX() const { return shift_ == RRX; }
   1064   bool Is(Shift value) const { return shift_ == value.shift_; }
   1065   bool IsNot(Shift value) const { return shift_ != value.shift_; }
   1066   bool IsValidAmount(uint32_t amount) const;
   1067   static const Shift NoShift;
   1068 
   1069  protected:
   1070   void SetType(ShiftType s) { shift_ = s; }
   1071 
   1072  private:
   1073   ShiftType shift_;
   1074 };
   1075 
   1076 inline std::ostream& operator<<(std::ostream& os, Shift shift) {
   1077   return os << shift.GetName();
   1078 }
   1079 
   1080 class ImmediateShiftOperand : public Shift {
   1081  public:
   1082   // Constructor used for assembly.
   1083   ImmediateShiftOperand(Shift shift, uint32_t amount)
   1084       : Shift(shift), amount_(amount) {
   1085 #ifdef VIXL_DEBUG
   1086     switch (shift.GetType()) {
   1087       case LSL:
   1088         VIXL_ASSERT(amount <= 31);
   1089         break;
   1090       case ROR:
   1091         VIXL_ASSERT(amount > 0);
   1092         VIXL_ASSERT(amount <= 31);
   1093         break;
   1094       case LSR:
   1095       case ASR:
   1096         VIXL_ASSERT(amount > 0);
   1097         VIXL_ASSERT(amount <= 32);
   1098         break;
   1099       case RRX:
   1100         VIXL_ASSERT(amount == 0);
   1101         break;
   1102       default:
   1103         VIXL_UNREACHABLE();
   1104         break;
   1105     }
   1106 #endif
   1107   }
   1108   // Constructor used for disassembly.
   1109   ImmediateShiftOperand(int shift, int amount);
   1110   uint32_t GetAmount() const { return amount_; }
   1111   bool Is(const ImmediateShiftOperand& rhs) const {
   1112     return amount_ == (rhs.amount_) && Shift::Is(*this);
   1113   }
   1114 
   1115  private:
   1116   uint32_t amount_;
   1117 };
   1118 
   1119 inline std::ostream& operator<<(std::ostream& os,
   1120                                 ImmediateShiftOperand const& shift_operand) {
   1121   if (shift_operand.IsLSL() && shift_operand.GetAmount() == 0) return os;
   1122   if (shift_operand.IsRRX()) return os << ", rrx";
   1123   return os << ", " << shift_operand.GetName() << " #"
   1124             << shift_operand.GetAmount();
   1125 }
   1126 
   1127 class RegisterShiftOperand : public Shift {
   1128  public:
   1129   RegisterShiftOperand(ShiftType shift, Register shift_register)
   1130       : Shift(shift), shift_register_(shift_register) {
   1131     VIXL_ASSERT(!IsRRX() && shift_register_.IsValid());
   1132   }
   1133   const Register GetShiftRegister() const { return shift_register_; }
   1134   bool Is(const RegisterShiftOperand& rhs) const {
   1135     return shift_register_.Is(rhs.shift_register_) && Shift::Is(*this);
   1136   }
   1137 
   1138  private:
   1139   Register shift_register_;
   1140 };
   1141 
   1142 inline std::ostream& operator<<(std::ostream& s,
   1143                                 const RegisterShiftOperand& shift_operand) {
   1144   return s << shift_operand.GetName() << " "
   1145            << shift_operand.GetShiftRegister();
   1146 }
   1147 
   1148 enum EncodingSizeType { Best, Narrow, Wide };
   1149 
   1150 class EncodingSize {
   1151   uint32_t size_;
   1152 
   1153  public:
   1154   explicit EncodingSize(uint32_t size) : size_(size) {}
   1155   EncodingSize(EncodingSizeType size)  // NOLINT(runtime/explicit)
   1156       : size_(size) {}
   1157   uint32_t GetSize() const { return size_; }
   1158   const char* GetName() const;
   1159   bool IsBest() const { return size_ == Best; }
   1160   bool IsNarrow() const { return size_ == Narrow; }
   1161   bool IsWide() const { return size_ == Wide; }
   1162 };
   1163 
   1164 inline std::ostream& operator<<(std::ostream& os, EncodingSize size) {
   1165   return os << size.GetName();
   1166 }
   1167 
   1168 enum WriteBackValue { NO_WRITE_BACK, WRITE_BACK };
   1169 
   1170 class WriteBack {
   1171   WriteBackValue value_;
   1172 
   1173  public:
   1174   WriteBack(WriteBackValue value)  // NOLINT(runtime/explicit)
   1175       : value_(value) {}
   1176   explicit WriteBack(int value)
   1177       : value_((value == 0) ? NO_WRITE_BACK : WRITE_BACK) {}
   1178   uint32_t GetWriteBackUint32() const { return (value_ == WRITE_BACK) ? 1 : 0; }
   1179   bool DoesWriteBack() const { return value_ == WRITE_BACK; }
   1180 };
   1181 
   1182 inline std::ostream& operator<<(std::ostream& os, WriteBack write_back) {
   1183   if (write_back.DoesWriteBack()) return os << "!";
   1184   return os;
   1185 }
   1186 
   1187 class EncodingValue {
   1188   bool valid_;
   1189   uint32_t encoding_value_;
   1190 
   1191  public:
   1192   EncodingValue() {
   1193     valid_ = false;
   1194     encoding_value_ = 0;
   1195   }
   1196   bool IsValid() const { return valid_; }
   1197   uint32_t GetEncodingValue() const { return encoding_value_; }
   1198   void SetEncodingValue(uint32_t encoding_value) {
   1199     valid_ = true;
   1200     encoding_value_ = encoding_value;
   1201   }
   1202 };
   1203 
   1204 class EncodingValueAndImmediate : public EncodingValue {
   1205   uint32_t encoded_immediate_;
   1206 
   1207  public:
   1208   EncodingValueAndImmediate() { encoded_immediate_ = 0; }
   1209   uint32_t GetEncodedImmediate() const { return encoded_immediate_; }
   1210   void SetEncodedImmediate(uint32_t encoded_immediate) {
   1211     encoded_immediate_ = encoded_immediate;
   1212   }
   1213 };
   1214 
   1215 class ImmediateT32 : public EncodingValue {
   1216  public:
   1217   explicit ImmediateT32(uint32_t imm);
   1218   static bool IsImmediateT32(uint32_t imm);
   1219   static uint32_t Decode(uint32_t value);
   1220 };
   1221 
   1222 class ImmediateA32 : public EncodingValue {
   1223  public:
   1224   explicit ImmediateA32(uint32_t imm);
   1225   static bool IsImmediateA32(uint32_t imm);
   1226   static uint32_t Decode(uint32_t value);
   1227 };
   1228 
   1229 // Return the encoding value of a shift type.
   1230 uint32_t TypeEncodingValue(Shift shift);
   1231 // Return the encoding value for a shift amount depending on the shift type.
   1232 uint32_t AmountEncodingValue(Shift shift, uint32_t amount);
   1233 
   1234 enum MemoryBarrierType {
   1235   OSHLD = 0x1,
   1236   OSHST = 0x2,
   1237   OSH = 0x3,
   1238   NSHLD = 0x5,
   1239   NSHST = 0x6,
   1240   NSH = 0x7,
   1241   ISHLD = 0x9,
   1242   ISHST = 0xa,
   1243   ISH = 0xb,
   1244   LD = 0xd,
   1245   ST = 0xe,
   1246   SY = 0xf
   1247 };
   1248 
   1249 class MemoryBarrier {
   1250   MemoryBarrierType type_;
   1251 
   1252  public:
   1253   MemoryBarrier(MemoryBarrierType type)  // NOLINT(runtime/explicit)
   1254       : type_(type) {}
   1255   MemoryBarrier(uint32_t type)  // NOLINT(runtime/explicit)
   1256       : type_(static_cast<MemoryBarrierType>(type)) {
   1257     VIXL_ASSERT((type & 0x3) != 0);
   1258   }
   1259   MemoryBarrierType GetType() const { return type_; }
   1260   const char* GetName() const;
   1261 };
   1262 
   1263 inline std::ostream& operator<<(std::ostream& os, MemoryBarrier option) {
   1264   return os << option.GetName();
   1265 }
   1266 
   1267 enum InterruptFlagsType {
   1268   F = 0x1,
   1269   I = 0x2,
   1270   IF = 0x3,
   1271   A = 0x4,
   1272   AF = 0x5,
   1273   AI = 0x6,
   1274   AIF = 0x7
   1275 };
   1276 
   1277 class InterruptFlags {
   1278   InterruptFlagsType type_;
   1279 
   1280  public:
   1281   InterruptFlags(InterruptFlagsType type)  // NOLINT(runtime/explicit)
   1282       : type_(type) {}
   1283   InterruptFlags(uint32_t type)  // NOLINT(runtime/explicit)
   1284       : type_(static_cast<InterruptFlagsType>(type)) {
   1285     VIXL_ASSERT(type <= 7);
   1286   }
   1287   InterruptFlagsType GetType() const { return type_; }
   1288   const char* GetName() const;
   1289 };
   1290 
   1291 inline std::ostream& operator<<(std::ostream& os, InterruptFlags option) {
   1292   return os << option.GetName();
   1293 }
   1294 
   1295 enum EndiannessType { LE = 0, BE = 1 };
   1296 
   1297 class Endianness {
   1298   EndiannessType type_;
   1299 
   1300  public:
   1301   Endianness(EndiannessType type) : type_(type) {}  // NOLINT(runtime/explicit)
   1302   Endianness(uint32_t type)                         // NOLINT(runtime/explicit)
   1303       : type_(static_cast<EndiannessType>(type)) {
   1304     VIXL_ASSERT(type <= 1);
   1305   }
   1306   EndiannessType GetType() const { return type_; }
   1307   const char* GetName() const;
   1308 };
   1309 
   1310 inline std::ostream& operator<<(std::ostream& os, Endianness endian_specifier) {
   1311   return os << endian_specifier.GetName();
   1312 }
   1313 
   1314 enum AlignmentType {
   1315   k16BitAlign = 0,
   1316   k32BitAlign = 1,
   1317   k64BitAlign = 2,
   1318   k128BitAlign = 3,
   1319   k256BitAlign = 4,
   1320   kNoAlignment = 5,
   1321   kBadAlignment = 6
   1322 };
   1323 
   1324 class Alignment {
   1325   AlignmentType align_;
   1326 
   1327  public:
   1328   Alignment(AlignmentType align)  // NOLINT(runtime/explicit)
   1329       : align_(align) {}
   1330   Alignment(uint32_t align)  // NOLINT(runtime/explicit)
   1331       : align_(static_cast<AlignmentType>(align)) {
   1332     VIXL_ASSERT(align <= static_cast<uint32_t>(k256BitAlign));
   1333   }
   1334   AlignmentType GetType() const { return align_; }
   1335   bool Is(AlignmentType type) { return align_ == type; }
   1336 };
   1337 
   1338 inline std::ostream& operator<<(std::ostream& os, Alignment align) {
   1339   if (align.GetType() == kBadAlignment) return os << " :??";
   1340   if (align.GetType() == kNoAlignment) return os;
   1341   return os << " :" << (0x10 << static_cast<uint32_t>(align.GetType()));
   1342 }
   1343 
   1344 class RawLiteral : public Label {
   1345  public:
   1346   enum PlacementPolicy { kPlacedWhenUsed, kManuallyPlaced };
   1347 
   1348   enum DeletionPolicy {
   1349     kDeletedOnPlacementByPool,
   1350     kDeletedOnPoolDestruction,
   1351     kManuallyDeleted
   1352   };
   1353 
   1354  public:
   1355   RawLiteral(const void* addr,
   1356              size_t size,
   1357              PlacementPolicy placement_policy = kPlacedWhenUsed,
   1358              DeletionPolicy deletion_policy = kManuallyDeleted)
   1359       : addr_(addr),
   1360         size_(size),
   1361         position_(kMaxOffset),
   1362         manually_placed_(placement_policy == kManuallyPlaced),
   1363         deletion_policy_(deletion_policy) {
   1364     // We can't have manually placed literals that are not manually deleted.
   1365     VIXL_ASSERT(!IsManuallyPlaced() ||
   1366                 (GetDeletionPolicy() == kManuallyDeleted));
   1367   }
   1368   RawLiteral(const void* addr, size_t size, DeletionPolicy deletion_policy)
   1369       : addr_(addr),
   1370         size_(size),
   1371         position_(kMaxOffset),
   1372         manually_placed_(false),
   1373         deletion_policy_(deletion_policy) {}
   1374   ~RawLiteral() {}
   1375   const void* GetDataAddress() const { return addr_; }
   1376   size_t GetSize() const { return size_; }
   1377   size_t GetAlignedSize() const { return (size_ + 3) & ~0x3; }
   1378 
   1379   Offset GetPositionInPool() const { return position_; }
   1380   void SetPositionInPool(Offset position_in_pool) {
   1381     // Assumed that the literal has not already been added to
   1382     // the pool.
   1383     VIXL_ASSERT(position_ == Label::kMaxOffset);
   1384     position_ = position_in_pool;
   1385   }
   1386 
   1387   bool IsManuallyPlaced() const { return manually_placed_; }
   1388   DeletionPolicy GetDeletionPolicy() const { return deletion_policy_; }
   1389 
   1390  private:
   1391   // Data address before it's moved into the code buffer.
   1392   const void* const addr_;
   1393   // Data size before it's moved into the code buffer.
   1394   const size_t size_;
   1395   // Position in the pool, if not in a pool: Label::kMaxOffset.
   1396   Offset position_;
   1397   // When this flag is true, the label will be placed manually.
   1398   bool manually_placed_;
   1399   // When is the literal to be removed from the memory
   1400   // Can be delete'd when:
   1401   //   moved into the code buffer: kDeletedOnPlacementByPool
   1402   //   the pool is delete'd: kDeletedOnPoolDestruction
   1403   //   or left to the application: kManuallyDeleted.
   1404   DeletionPolicy deletion_policy_;
   1405 };
   1406 
   1407 template <typename T>
   1408 class Literal : public RawLiteral {
   1409  public:
   1410   explicit Literal(const T& value,
   1411                    PlacementPolicy placement_policy = kPlacedWhenUsed,
   1412                    DeletionPolicy deletion_policy = kManuallyDeleted)
   1413       : RawLiteral(&value_, sizeof(T), placement_policy, deletion_policy),
   1414         value_(value) {}
   1415   explicit Literal(const T& value, DeletionPolicy deletion_policy)
   1416       : RawLiteral(&value_, sizeof(T), deletion_policy), value_(value) {}
   1417   void UpdateValue(const T& value, CodeBuffer* buffer) {
   1418     value_ = value;
   1419     if (IsBound()) {
   1420       buffer->UpdateData(GetLocation(), GetDataAddress(), GetSize());
   1421     }
   1422   }
   1423 
   1424  private:
   1425   T value_;
   1426 };
   1427 
   1428 class StringLiteral : public RawLiteral {
   1429  public:
   1430   explicit StringLiteral(const char* str,
   1431                          PlacementPolicy placement_policy = kPlacedWhenUsed,
   1432                          DeletionPolicy deletion_policy = kManuallyDeleted)
   1433       : RawLiteral(str, strlen(str) + 1, placement_policy, deletion_policy) {}
   1434   explicit StringLiteral(const char* str, DeletionPolicy deletion_policy)
   1435       : RawLiteral(str, strlen(str) + 1, deletion_policy) {}
   1436 };
   1437 
   1438 }  // namespace aarch32
   1439 }  // namespace vixl
   1440 
   1441 #endif  // VIXL_AARCH32_INSTRUCTIONS_AARCH32_H_
   1442