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