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