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