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