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