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