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