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