• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_AARCH64_INSTRUCTIONS_AARCH64_H_
28 #define VIXL_AARCH64_INSTRUCTIONS_AARCH64_H_
29 
30 #include "../globals-vixl.h"
31 #include "../utils-vixl.h"
32 
33 #include "constants-aarch64.h"
34 
35 namespace vixl {
36 namespace aarch64 {
37 // ISA constants. --------------------------------------------------------------
38 
39 typedef uint32_t Instr;
40 const unsigned kInstructionSize = 4;
41 const unsigned kInstructionSizeLog2 = 2;
42 const unsigned kLiteralEntrySize = 4;
43 const unsigned kLiteralEntrySizeLog2 = 2;
44 const unsigned kMaxLoadLiteralRange = 1 * MBytes;
45 
46 // This is the nominal page size (as used by the adrp instruction); the actual
47 // size of the memory pages allocated by the kernel is likely to differ.
48 const unsigned kPageSize = 4 * KBytes;
49 const unsigned kPageSizeLog2 = 12;
50 
51 const unsigned kBRegSize = 8;
52 const unsigned kBRegSizeLog2 = 3;
53 const unsigned kBRegSizeInBytes = kBRegSize / 8;
54 const unsigned kBRegSizeInBytesLog2 = kBRegSizeLog2 - 3;
55 const unsigned kHRegSize = 16;
56 const unsigned kHRegSizeLog2 = 4;
57 const unsigned kHRegSizeInBytes = kHRegSize / 8;
58 const unsigned kHRegSizeInBytesLog2 = kHRegSizeLog2 - 3;
59 const unsigned kWRegSize = 32;
60 const unsigned kWRegSizeLog2 = 5;
61 const unsigned kWRegSizeInBytes = kWRegSize / 8;
62 const unsigned kWRegSizeInBytesLog2 = kWRegSizeLog2 - 3;
63 const unsigned kXRegSize = 64;
64 const unsigned kXRegSizeLog2 = 6;
65 const unsigned kXRegSizeInBytes = kXRegSize / 8;
66 const unsigned kXRegSizeInBytesLog2 = kXRegSizeLog2 - 3;
67 const unsigned kSRegSize = 32;
68 const unsigned kSRegSizeLog2 = 5;
69 const unsigned kSRegSizeInBytes = kSRegSize / 8;
70 const unsigned kSRegSizeInBytesLog2 = kSRegSizeLog2 - 3;
71 const unsigned kDRegSize = 64;
72 const unsigned kDRegSizeLog2 = 6;
73 const unsigned kDRegSizeInBytes = kDRegSize / 8;
74 const unsigned kDRegSizeInBytesLog2 = kDRegSizeLog2 - 3;
75 const unsigned kQRegSize = 128;
76 const unsigned kQRegSizeLog2 = 7;
77 const unsigned kQRegSizeInBytes = kQRegSize / 8;
78 const unsigned kQRegSizeInBytesLog2 = kQRegSizeLog2 - 3;
79 const uint64_t kWRegMask = UINT64_C(0xffffffff);
80 const uint64_t kXRegMask = UINT64_C(0xffffffffffffffff);
81 const uint64_t kHRegMask = UINT64_C(0xffff);
82 const uint64_t kSRegMask = UINT64_C(0xffffffff);
83 const uint64_t kDRegMask = UINT64_C(0xffffffffffffffff);
84 const uint64_t kSSignMask = UINT64_C(0x80000000);
85 const uint64_t kDSignMask = UINT64_C(0x8000000000000000);
86 const uint64_t kWSignMask = UINT64_C(0x80000000);
87 const uint64_t kXSignMask = UINT64_C(0x8000000000000000);
88 const uint64_t kByteMask = UINT64_C(0xff);
89 const uint64_t kHalfWordMask = UINT64_C(0xffff);
90 const uint64_t kWordMask = UINT64_C(0xffffffff);
91 const uint64_t kXMaxUInt = UINT64_C(0xffffffffffffffff);
92 const uint64_t kWMaxUInt = UINT64_C(0xffffffff);
93 const uint64_t kHMaxUInt = UINT64_C(0xffff);
94 // Define k*MinInt with "-k*MaxInt - 1", because the hexadecimal representation
95 // (e.g. "INT32_C(0x80000000)") has implementation-defined behaviour.
96 const int64_t kXMaxInt = INT64_C(0x7fffffffffffffff);
97 const int64_t kXMinInt = -kXMaxInt - 1;
98 const int32_t kWMaxInt = INT32_C(0x7fffffff);
99 const int32_t kWMinInt = -kWMaxInt - 1;
100 const int16_t kHMaxInt = INT16_C(0x7fff);
101 const int16_t kHMinInt = -kHMaxInt - 1;
102 const unsigned kFpRegCode = 29;
103 const unsigned kLinkRegCode = 30;
104 const unsigned kSpRegCode = 31;
105 const unsigned kZeroRegCode = 31;
106 const unsigned kSPRegInternalCode = 63;
107 const unsigned kRegCodeMask = 0x1f;
108 
109 const unsigned kAtomicAccessGranule = 16;
110 
111 const unsigned kAddressTagOffset = 56;
112 const unsigned kAddressTagWidth = 8;
113 const uint64_t kAddressTagMask = ((UINT64_C(1) << kAddressTagWidth) - 1)
114                                  << kAddressTagOffset;
115 VIXL_STATIC_ASSERT(kAddressTagMask == UINT64_C(0xff00000000000000));
116 
117 const uint64_t kTTBRMask = UINT64_C(1) << 55;
118 
119 // Make these moved float constants backwards compatible
120 // with explicit vixl::aarch64:: namespace references.
121 using vixl::kDoubleMantissaBits;
122 using vixl::kDoubleExponentBits;
123 using vixl::kFloatMantissaBits;
124 using vixl::kFloatExponentBits;
125 using vixl::kFloat16MantissaBits;
126 using vixl::kFloat16ExponentBits;
127 
128 using vixl::kFP16PositiveInfinity;
129 using vixl::kFP16NegativeInfinity;
130 using vixl::kFP32PositiveInfinity;
131 using vixl::kFP32NegativeInfinity;
132 using vixl::kFP64PositiveInfinity;
133 using vixl::kFP64NegativeInfinity;
134 
135 using vixl::kFP16DefaultNaN;
136 using vixl::kFP32DefaultNaN;
137 using vixl::kFP64DefaultNaN;
138 
139 unsigned CalcLSDataSize(LoadStoreOp op);
140 unsigned CalcLSPairDataSize(LoadStorePairOp op);
141 
142 enum ImmBranchType {
143   UnknownBranchType = 0,
144   CondBranchType = 1,
145   UncondBranchType = 2,
146   CompareBranchType = 3,
147   TestBranchType = 4
148 };
149 
150 enum AddrMode { Offset, PreIndex, PostIndex };
151 
152 enum Reg31Mode { Reg31IsStackPointer, Reg31IsZeroRegister };
153 
154 // Instructions. ---------------------------------------------------------------
155 
156 class Instruction {
157  public:
GetInstructionBits()158   Instr GetInstructionBits() const {
159     return *(reinterpret_cast<const Instr*>(this));
160   }
161   VIXL_DEPRECATED("GetInstructionBits", Instr InstructionBits() const) {
162     return GetInstructionBits();
163   }
164 
SetInstructionBits(Instr new_instr)165   void SetInstructionBits(Instr new_instr) {
166     *(reinterpret_cast<Instr*>(this)) = new_instr;
167   }
168 
ExtractBit(int pos)169   int ExtractBit(int pos) const { return (GetInstructionBits() >> pos) & 1; }
Bit(int pos)170   VIXL_DEPRECATED("ExtractBit", int Bit(int pos) const) {
171     return ExtractBit(pos);
172   }
173 
ExtractBits(int msb,int lsb)174   uint32_t ExtractBits(int msb, int lsb) const {
175     return ExtractUnsignedBitfield32(msb, lsb, GetInstructionBits());
176   }
177   VIXL_DEPRECATED("ExtractBits", uint32_t Bits(int msb, int lsb) const) {
178     return ExtractBits(msb, lsb);
179   }
180 
181   // Compress bit extraction operation from Hacker's Delight.
182   // https://github.com/hcs0/Hackers-Delight/blob/master/compress.c.txt
Compress(uint32_t mask)183   uint32_t Compress(uint32_t mask) const {
184     uint32_t mk, mp, mv, t;
185     uint32_t x = GetInstructionBits() & mask;  // Clear irrelevant bits.
186     mk = ~mask << 1;                           // We will count 0's to right.
187     for (int i = 0; i < 5; i++) {
188       mp = mk ^ (mk << 1);  // Parallel suffix.
189       mp = mp ^ (mp << 2);
190       mp = mp ^ (mp << 4);
191       mp = mp ^ (mp << 8);
192       mp = mp ^ (mp << 16);
193       mv = mp & mask;                         // Bits to move.
194       mask = (mask ^ mv) | (mv >> (1 << i));  // Compress mask.
195       t = x & mv;
196       x = (x ^ t) | (t >> (1 << i));  // Compress x.
197       mk = mk & ~mp;
198     }
199     return x;
200   }
201 
202   template <uint32_t M>
ExtractBits()203   uint32_t ExtractBits() const {
204     return Compress(M);
205   }
206 
207   template <uint32_t M, uint32_t V>
IsMaskedValue()208   uint32_t IsMaskedValue() const {
209     return (Mask(M) == V) ? 1 : 0;
210   }
211 
ExtractSignedBits(int msb,int lsb)212   int32_t ExtractSignedBits(int msb, int lsb) const {
213     int32_t bits = *(reinterpret_cast<const int32_t*>(this));
214     return ExtractSignedBitfield32(msb, lsb, bits);
215   }
216   VIXL_DEPRECATED("ExtractSignedBits",
217                   int32_t SignedBits(int msb, int lsb) const) {
218     return ExtractSignedBits(msb, lsb);
219   }
220 
Mask(uint32_t mask)221   Instr Mask(uint32_t mask) const {
222     VIXL_ASSERT(mask != 0);
223     return GetInstructionBits() & mask;
224   }
225 
226 #define DEFINE_GETTER(Name, HighBit, LowBit, Func)                  \
227   int32_t Get##Name() const { return this->Func(HighBit, LowBit); } \
228   VIXL_DEPRECATED("Get" #Name, int32_t Name() const) { return Get##Name(); }
INSTRUCTION_FIELDS_LIST(DEFINE_GETTER)229   INSTRUCTION_FIELDS_LIST(DEFINE_GETTER)
230 #undef DEFINE_GETTER
231 
232   // ImmPCRel is a compound field (not present in INSTRUCTION_FIELDS_LIST),
233   // formed from ImmPCRelLo and ImmPCRelHi.
234   int GetImmPCRel() const {
235     uint32_t hi = static_cast<uint32_t>(GetImmPCRelHi());
236     uint32_t lo = GetImmPCRelLo();
237     uint32_t offset = (hi << ImmPCRelLo_width) | lo;
238     int width = ImmPCRelLo_width + ImmPCRelHi_width;
239     return ExtractSignedBitfield32(width - 1, 0, offset);
240   }
ImmPCRel()241   VIXL_DEPRECATED("GetImmPCRel", int ImmPCRel() const) { return GetImmPCRel(); }
242 
243   // ImmLSPAC is a compound field (not present in INSTRUCTION_FIELDS_LIST),
244   // formed from ImmLSPACLo and ImmLSPACHi.
GetImmLSPAC()245   int GetImmLSPAC() const {
246     uint32_t hi = static_cast<uint32_t>(GetImmLSPACHi());
247     uint32_t lo = GetImmLSPACLo();
248     uint32_t offset = (hi << ImmLSPACLo_width) | lo;
249     int width = ImmLSPACLo_width + ImmLSPACHi_width;
250     return ExtractSignedBitfield32(width - 1, 0, offset) << 3;
251   }
252 
253   uint64_t GetImmLogical() const;
254   VIXL_DEPRECATED("GetImmLogical", uint64_t ImmLogical() const) {
255     return GetImmLogical();
256   }
257 
258   unsigned GetImmNEONabcdefgh() const;
ImmNEONabcdefgh()259   VIXL_DEPRECATED("GetImmNEONabcdefgh", unsigned ImmNEONabcdefgh() const) {
260     return GetImmNEONabcdefgh();
261   }
262 
263   Float16 GetImmFP16() const;
264 
265   float GetImmFP32() const;
ImmFP32()266   VIXL_DEPRECATED("GetImmFP32", float ImmFP32() const) { return GetImmFP32(); }
267 
268   double GetImmFP64() const;
ImmFP64()269   VIXL_DEPRECATED("GetImmFP64", double ImmFP64() const) { return GetImmFP64(); }
270 
271   Float16 GetImmNEONFP16() const;
272 
273   float GetImmNEONFP32() const;
ImmNEONFP32()274   VIXL_DEPRECATED("GetImmNEONFP32", float ImmNEONFP32() const) {
275     return GetImmNEONFP32();
276   }
277 
278   double GetImmNEONFP64() const;
ImmNEONFP64()279   VIXL_DEPRECATED("GetImmNEONFP64", double ImmNEONFP64() const) {
280     return GetImmNEONFP64();
281   }
282 
GetSizeLS()283   unsigned GetSizeLS() const {
284     return CalcLSDataSize(static_cast<LoadStoreOp>(Mask(LoadStoreMask)));
285   }
SizeLS()286   VIXL_DEPRECATED("GetSizeLS", unsigned SizeLS() const) { return GetSizeLS(); }
287 
GetSizeLSPair()288   unsigned GetSizeLSPair() const {
289     return CalcLSPairDataSize(
290         static_cast<LoadStorePairOp>(Mask(LoadStorePairMask)));
291   }
SizeLSPair()292   VIXL_DEPRECATED("GetSizeLSPair", unsigned SizeLSPair() const) {
293     return GetSizeLSPair();
294   }
295 
GetNEONLSIndex(int access_size_shift)296   int GetNEONLSIndex(int access_size_shift) const {
297     int64_t q = GetNEONQ();
298     int64_t s = GetNEONS();
299     int64_t size = GetNEONLSSize();
300     int64_t index = (q << 3) | (s << 2) | size;
301     return static_cast<int>(index >> access_size_shift);
302   }
303   VIXL_DEPRECATED("GetNEONLSIndex",
NEONLSIndex(int access_size_shift)304                   int NEONLSIndex(int access_size_shift) const) {
305     return GetNEONLSIndex(access_size_shift);
306   }
307 
308   // Helpers.
IsCondBranchImm()309   bool IsCondBranchImm() const {
310     return Mask(ConditionalBranchFMask) == ConditionalBranchFixed;
311   }
312 
IsUncondBranchImm()313   bool IsUncondBranchImm() const {
314     return Mask(UnconditionalBranchFMask) == UnconditionalBranchFixed;
315   }
316 
IsCompareBranch()317   bool IsCompareBranch() const {
318     return Mask(CompareBranchFMask) == CompareBranchFixed;
319   }
320 
IsTestBranch()321   bool IsTestBranch() const { return Mask(TestBranchFMask) == TestBranchFixed; }
322 
IsImmBranch()323   bool IsImmBranch() const { return GetBranchType() != UnknownBranchType; }
324 
IsPCRelAddressing()325   bool IsPCRelAddressing() const {
326     return Mask(PCRelAddressingFMask) == PCRelAddressingFixed;
327   }
328 
IsLogicalImmediate()329   bool IsLogicalImmediate() const {
330     return Mask(LogicalImmediateFMask) == LogicalImmediateFixed;
331   }
332 
IsAddSubImmediate()333   bool IsAddSubImmediate() const {
334     return Mask(AddSubImmediateFMask) == AddSubImmediateFixed;
335   }
336 
IsAddSubExtended()337   bool IsAddSubExtended() const {
338     return Mask(AddSubExtendedFMask) == AddSubExtendedFixed;
339   }
340 
IsLoadOrStore()341   bool IsLoadOrStore() const {
342     return Mask(LoadStoreAnyFMask) == LoadStoreAnyFixed;
343   }
344 
345   bool IsLoad() const;
346   bool IsStore() const;
347 
IsLoadLiteral()348   bool IsLoadLiteral() const {
349     // This includes PRFM_lit.
350     return Mask(LoadLiteralFMask) == LoadLiteralFixed;
351   }
352 
IsMovn()353   bool IsMovn() const {
354     return (Mask(MoveWideImmediateMask) == MOVN_x) ||
355            (Mask(MoveWideImmediateMask) == MOVN_w);
356   }
357 
IsException()358   bool IsException() const { return Mask(ExceptionFMask) == ExceptionFixed; }
359 
IsPAuth()360   bool IsPAuth() const { return Mask(SystemPAuthFMask) == SystemPAuthFixed; }
361 
IsBti()362   bool IsBti() const {
363     if (Mask(SystemHintFMask) == SystemHintFixed) {
364       int imm_hint = GetImmHint();
365       switch (imm_hint) {
366         case BTI:
367         case BTI_c:
368         case BTI_j:
369         case BTI_jc:
370           return true;
371       }
372     }
373     return false;
374   }
375 
376   static int GetImmBranchRangeBitwidth(ImmBranchType branch_type);
377   VIXL_DEPRECATED(
378       "GetImmBranchRangeBitwidth",
ImmBranchRangeBitwidth(ImmBranchType branch_type)379       static int ImmBranchRangeBitwidth(ImmBranchType branch_type)) {
380     return GetImmBranchRangeBitwidth(branch_type);
381   }
382 
383   static int32_t GetImmBranchForwardRange(ImmBranchType branch_type);
384   VIXL_DEPRECATED(
385       "GetImmBranchForwardRange",
386       static int32_t ImmBranchForwardRange(ImmBranchType branch_type)) {
387     return GetImmBranchForwardRange(branch_type);
388   }
389 
390   static bool IsValidImmPCOffset(ImmBranchType branch_type, int64_t offset);
391 
392   // Indicate whether Rd can be the stack pointer or the zero register. This
393   // does not check that the instruction actually has an Rd field.
GetRdMode()394   Reg31Mode GetRdMode() const {
395     // The following instructions use sp or wsp as Rd:
396     //  Add/sub (immediate) when not setting the flags.
397     //  Add/sub (extended) when not setting the flags.
398     //  Logical (immediate) when not setting the flags.
399     // Otherwise, r31 is the zero register.
400     if (IsAddSubImmediate() || IsAddSubExtended()) {
401       if (Mask(AddSubSetFlagsBit)) {
402         return Reg31IsZeroRegister;
403       } else {
404         return Reg31IsStackPointer;
405       }
406     }
407     if (IsLogicalImmediate()) {
408       // Of the logical (immediate) instructions, only ANDS (and its aliases)
409       // can set the flags. The others can all write into sp.
410       // Note that some logical operations are not available to
411       // immediate-operand instructions, so we have to combine two masks here.
412       if (Mask(LogicalImmediateMask & LogicalOpMask) == ANDS) {
413         return Reg31IsZeroRegister;
414       } else {
415         return Reg31IsStackPointer;
416       }
417     }
418     return Reg31IsZeroRegister;
419   }
420   VIXL_DEPRECATED("GetRdMode", Reg31Mode RdMode() const) { return GetRdMode(); }
421 
422   // Indicate whether Rn can be the stack pointer or the zero register. This
423   // does not check that the instruction actually has an Rn field.
GetRnMode()424   Reg31Mode GetRnMode() const {
425     // The following instructions use sp or wsp as Rn:
426     //  All loads and stores.
427     //  Add/sub (immediate).
428     //  Add/sub (extended).
429     // Otherwise, r31 is the zero register.
430     if (IsLoadOrStore() || IsAddSubImmediate() || IsAddSubExtended()) {
431       return Reg31IsStackPointer;
432     }
433     return Reg31IsZeroRegister;
434   }
435   VIXL_DEPRECATED("GetRnMode", Reg31Mode RnMode() const) { return GetRnMode(); }
436 
GetBranchType()437   ImmBranchType GetBranchType() const {
438     if (IsCondBranchImm()) {
439       return CondBranchType;
440     } else if (IsUncondBranchImm()) {
441       return UncondBranchType;
442     } else if (IsCompareBranch()) {
443       return CompareBranchType;
444     } else if (IsTestBranch()) {
445       return TestBranchType;
446     } else {
447       return UnknownBranchType;
448     }
449   }
450   VIXL_DEPRECATED("GetBranchType", ImmBranchType BranchType() const) {
451     return GetBranchType();
452   }
453 
454   // Find the target of this instruction. 'this' may be a branch or a
455   // PC-relative addressing instruction.
456   const Instruction* GetImmPCOffsetTarget() const;
457   VIXL_DEPRECATED("GetImmPCOffsetTarget",
458                   const Instruction* ImmPCOffsetTarget() const) {
459     return GetImmPCOffsetTarget();
460   }
461 
462   // Patch a PC-relative offset to refer to 'target'. 'this' may be a branch or
463   // a PC-relative addressing instruction.
464   void SetImmPCOffsetTarget(const Instruction* target);
465   // Patch a literal load instruction to load from 'source'.
466   void SetImmLLiteral(const Instruction* source);
467 
468   // The range of a load literal instruction, expressed as 'instr +- range'.
469   // The range is actually the 'positive' range; the branch instruction can
470   // target [instr - range - kInstructionSize, instr + range].
471   static const int kLoadLiteralImmBitwidth = 19;
472   static const int kLoadLiteralRange =
473       (1 << kLoadLiteralImmBitwidth) / 2 - kInstructionSize;
474 
475   // Calculate the address of a literal referred to by a load-literal
476   // instruction, and return it as the specified type.
477   //
478   // The literal itself is safely mutable only if the backing buffer is safely
479   // mutable.
480   template <typename T>
GetLiteralAddress()481   T GetLiteralAddress() const {
482     uint64_t base_raw = reinterpret_cast<uint64_t>(this);
483     int64_t offset = GetImmLLiteral() * static_cast<int>(kLiteralEntrySize);
484     uint64_t address_raw = base_raw + offset;
485 
486     // Cast the address using a C-style cast. A reinterpret_cast would be
487     // appropriate, but it can't cast one integral type to another.
488     T address = (T)(address_raw);
489 
490     // Assert that the address can be represented by the specified type.
491     VIXL_ASSERT((uint64_t)(address) == address_raw);
492 
493     return address;
494   }
495   template <typename T>
496   VIXL_DEPRECATED("GetLiteralAddress", T LiteralAddress() const) {
497     return GetLiteralAddress<T>();
498   }
499 
GetLiteral32()500   uint32_t GetLiteral32() const {
501     uint32_t literal;
502     memcpy(&literal, GetLiteralAddress<const void*>(), sizeof(literal));
503     return literal;
504   }
505   VIXL_DEPRECATED("GetLiteral32", uint32_t Literal32() const) {
506     return GetLiteral32();
507   }
508 
GetLiteral64()509   uint64_t GetLiteral64() const {
510     uint64_t literal;
511     memcpy(&literal, GetLiteralAddress<const void*>(), sizeof(literal));
512     return literal;
513   }
514   VIXL_DEPRECATED("GetLiteral64", uint64_t Literal64() const) {
515     return GetLiteral64();
516   }
517 
GetLiteralFP32()518   float GetLiteralFP32() const { return RawbitsToFloat(GetLiteral32()); }
LiteralFP32()519   VIXL_DEPRECATED("GetLiteralFP32", float LiteralFP32() const) {
520     return GetLiteralFP32();
521   }
522 
GetLiteralFP64()523   double GetLiteralFP64() const { return RawbitsToDouble(GetLiteral64()); }
LiteralFP64()524   VIXL_DEPRECATED("GetLiteralFP64", double LiteralFP64() const) {
525     return GetLiteralFP64();
526   }
527 
GetNextInstruction()528   Instruction* GetNextInstruction() { return this + kInstructionSize; }
GetNextInstruction()529   const Instruction* GetNextInstruction() const {
530     return this + kInstructionSize;
531   }
532   VIXL_DEPRECATED("GetNextInstruction",
533                   const Instruction* NextInstruction() const) {
534     return GetNextInstruction();
535   }
536 
GetInstructionAtOffset(int64_t offset)537   const Instruction* GetInstructionAtOffset(int64_t offset) const {
538     VIXL_ASSERT(IsWordAligned(this + offset));
539     return this + offset;
540   }
541   VIXL_DEPRECATED("GetInstructionAtOffset",
542                   const Instruction* InstructionAtOffset(int64_t offset)
543                       const) {
544     return GetInstructionAtOffset(offset);
545   }
546 
547   template <typename T>
Cast(T src)548   static Instruction* Cast(T src) {
549     return reinterpret_cast<Instruction*>(src);
550   }
551 
552   template <typename T>
CastConst(T src)553   static const Instruction* CastConst(T src) {
554     return reinterpret_cast<const Instruction*>(src);
555   }
556 
557  private:
558   int GetImmBranch() const;
559 
560   static Float16 Imm8ToFloat16(uint32_t imm8);
561   static float Imm8ToFP32(uint32_t imm8);
562   static double Imm8ToFP64(uint32_t imm8);
563 
564   void SetPCRelImmTarget(const Instruction* target);
565   void SetBranchImmTarget(const Instruction* target);
566 };
567 
568 
569 // Functions for handling NEON vector format information.
570 enum VectorFormat {
571   kFormatUndefined = 0xffffffff,
572   kFormat8B = NEON_8B,
573   kFormat16B = NEON_16B,
574   kFormat4H = NEON_4H,
575   kFormat8H = NEON_8H,
576   kFormat2S = NEON_2S,
577   kFormat4S = NEON_4S,
578   kFormat1D = NEON_1D,
579   kFormat2D = NEON_2D,
580 
581   // Scalar formats. We add the scalar bit to distinguish between scalar and
582   // vector enumerations; the bit is always set in the encoding of scalar ops
583   // and always clear for vector ops. Although kFormatD and kFormat1D appear
584   // to be the same, their meaning is subtly different. The first is a scalar
585   // operation, the second a vector operation that only affects one lane.
586   kFormatB = NEON_B | NEONScalar,
587   kFormatH = NEON_H | NEONScalar,
588   kFormatS = NEON_S | NEONScalar,
589   kFormatD = NEON_D | NEONScalar,
590 
591   // An artificial value, used by simulator trace tests and a few oddball
592   // instructions (such as FMLAL).
593   kFormat2H = 0xfffffffe
594 };
595 
596 const int kMaxLanesPerVector = 16;
597 
598 VectorFormat VectorFormatHalfWidth(VectorFormat vform);
599 VectorFormat VectorFormatDoubleWidth(VectorFormat vform);
600 VectorFormat VectorFormatDoubleLanes(VectorFormat vform);
601 VectorFormat VectorFormatHalfLanes(VectorFormat vform);
602 VectorFormat ScalarFormatFromLaneSize(int lanesize);
603 VectorFormat VectorFormatHalfWidthDoubleLanes(VectorFormat vform);
604 VectorFormat VectorFormatFillQ(VectorFormat vform);
605 VectorFormat ScalarFormatFromFormat(VectorFormat vform);
606 unsigned RegisterSizeInBitsFromFormat(VectorFormat vform);
607 unsigned RegisterSizeInBytesFromFormat(VectorFormat vform);
608 // TODO: Make the return types of these functions consistent.
609 unsigned LaneSizeInBitsFromFormat(VectorFormat vform);
610 int LaneSizeInBytesFromFormat(VectorFormat vform);
611 int LaneSizeInBytesLog2FromFormat(VectorFormat vform);
612 int LaneCountFromFormat(VectorFormat vform);
613 int MaxLaneCountFromFormat(VectorFormat vform);
614 bool IsVectorFormat(VectorFormat vform);
615 int64_t MaxIntFromFormat(VectorFormat vform);
616 int64_t MinIntFromFormat(VectorFormat vform);
617 uint64_t MaxUintFromFormat(VectorFormat vform);
618 
619 
620 // clang-format off
621 enum NEONFormat {
622   NF_UNDEF = 0,
623   NF_8B    = 1,
624   NF_16B   = 2,
625   NF_4H    = 3,
626   NF_8H    = 4,
627   NF_2S    = 5,
628   NF_4S    = 6,
629   NF_1D    = 7,
630   NF_2D    = 8,
631   NF_B     = 9,
632   NF_H     = 10,
633   NF_S     = 11,
634   NF_D     = 12
635 };
636 // clang-format on
637 
638 static const unsigned kNEONFormatMaxBits = 6;
639 
640 struct NEONFormatMap {
641   // The bit positions in the instruction to consider.
642   uint8_t bits[kNEONFormatMaxBits];
643 
644   // Mapping from concatenated bits to format.
645   NEONFormat map[1 << kNEONFormatMaxBits];
646 };
647 
648 class NEONFormatDecoder {
649  public:
650   enum SubstitutionMode { kPlaceholder, kFormat };
651 
652   // Construct a format decoder with increasingly specific format maps for each
653   // subsitution. If no format map is specified, the default is the integer
654   // format map.
NEONFormatDecoder(const Instruction * instr)655   explicit NEONFormatDecoder(const Instruction* instr) {
656     instrbits_ = instr->GetInstructionBits();
657     SetFormatMaps(IntegerFormatMap());
658   }
NEONFormatDecoder(const Instruction * instr,const NEONFormatMap * format)659   NEONFormatDecoder(const Instruction* instr, const NEONFormatMap* format) {
660     instrbits_ = instr->GetInstructionBits();
661     SetFormatMaps(format);
662   }
NEONFormatDecoder(const Instruction * instr,const NEONFormatMap * format0,const NEONFormatMap * format1)663   NEONFormatDecoder(const Instruction* instr,
664                     const NEONFormatMap* format0,
665                     const NEONFormatMap* format1) {
666     instrbits_ = instr->GetInstructionBits();
667     SetFormatMaps(format0, format1);
668   }
NEONFormatDecoder(const Instruction * instr,const NEONFormatMap * format0,const NEONFormatMap * format1,const NEONFormatMap * format2)669   NEONFormatDecoder(const Instruction* instr,
670                     const NEONFormatMap* format0,
671                     const NEONFormatMap* format1,
672                     const NEONFormatMap* format2) {
673     instrbits_ = instr->GetInstructionBits();
674     SetFormatMaps(format0, format1, format2);
675   }
676 
677   // Set the format mapping for all or individual substitutions.
678   void SetFormatMaps(const NEONFormatMap* format0,
679                      const NEONFormatMap* format1 = NULL,
680                      const NEONFormatMap* format2 = NULL) {
681     VIXL_ASSERT(format0 != NULL);
682     formats_[0] = format0;
683     formats_[1] = (format1 == NULL) ? formats_[0] : format1;
684     formats_[2] = (format2 == NULL) ? formats_[1] : format2;
685   }
SetFormatMap(unsigned index,const NEONFormatMap * format)686   void SetFormatMap(unsigned index, const NEONFormatMap* format) {
687     VIXL_ASSERT(index <= ArrayLength(formats_));
688     VIXL_ASSERT(format != NULL);
689     formats_[index] = format;
690   }
691 
692   // Substitute %s in the input string with the placeholder string for each
693   // register, ie. "'B", "'H", etc.
SubstitutePlaceholders(const char * string)694   const char* SubstitutePlaceholders(const char* string) {
695     return Substitute(string, kPlaceholder, kPlaceholder, kPlaceholder);
696   }
697 
698   // Substitute %s in the input string with a new string based on the
699   // substitution mode.
700   const char* Substitute(const char* string,
701                          SubstitutionMode mode0 = kFormat,
702                          SubstitutionMode mode1 = kFormat,
703                          SubstitutionMode mode2 = kFormat) {
704     snprintf(form_buffer_,
705              sizeof(form_buffer_),
706              string,
707              GetSubstitute(0, mode0),
708              GetSubstitute(1, mode1),
709              GetSubstitute(2, mode2));
710     return form_buffer_;
711   }
712 
713   // Append a "2" to a mnemonic string based of the state of the Q bit.
Mnemonic(const char * mnemonic)714   const char* Mnemonic(const char* mnemonic) {
715     if ((instrbits_ & NEON_Q) != 0) {
716       snprintf(mne_buffer_, sizeof(mne_buffer_), "%s2", mnemonic);
717       return mne_buffer_;
718     }
719     return mnemonic;
720   }
721 
722   VectorFormat GetVectorFormat(int format_index = 0) {
723     return GetVectorFormat(formats_[format_index]);
724   }
725 
GetVectorFormat(const NEONFormatMap * format_map)726   VectorFormat GetVectorFormat(const NEONFormatMap* format_map) {
727     static const VectorFormat vform[] = {kFormatUndefined,
728                                          kFormat8B,
729                                          kFormat16B,
730                                          kFormat4H,
731                                          kFormat8H,
732                                          kFormat2S,
733                                          kFormat4S,
734                                          kFormat1D,
735                                          kFormat2D,
736                                          kFormatB,
737                                          kFormatH,
738                                          kFormatS,
739                                          kFormatD};
740     VIXL_ASSERT(GetNEONFormat(format_map) < ArrayLength(vform));
741     return vform[GetNEONFormat(format_map)];
742   }
743 
744   // Built in mappings for common cases.
745 
746   // The integer format map uses three bits (Q, size<1:0>) to encode the
747   // "standard" set of NEON integer vector formats.
IntegerFormatMap()748   static const NEONFormatMap* IntegerFormatMap() {
749     static const NEONFormatMap map =
750         {{23, 22, 30},
751          {NF_8B, NF_16B, NF_4H, NF_8H, NF_2S, NF_4S, NF_UNDEF, NF_2D}};
752     return &map;
753   }
754 
755   // The long integer format map uses two bits (size<1:0>) to encode the
756   // long set of NEON integer vector formats. These are used in narrow, wide
757   // and long operations.
LongIntegerFormatMap()758   static const NEONFormatMap* LongIntegerFormatMap() {
759     static const NEONFormatMap map = {{23, 22}, {NF_8H, NF_4S, NF_2D}};
760     return &map;
761   }
762 
763   // The FP format map uses two bits (Q, size<0>) to encode the NEON FP vector
764   // formats: NF_2S, NF_4S, NF_2D.
FPFormatMap()765   static const NEONFormatMap* FPFormatMap() {
766     // The FP format map assumes two bits (Q, size<0>) are used to encode the
767     // NEON FP vector formats: NF_2S, NF_4S, NF_2D.
768     static const NEONFormatMap map = {{22, 30},
769                                       {NF_2S, NF_4S, NF_UNDEF, NF_2D}};
770     return &map;
771   }
772 
773   // The FP16 format map uses one bit (Q) to encode the NEON vector format:
774   // NF_4H, NF_8H.
FP16FormatMap()775   static const NEONFormatMap* FP16FormatMap() {
776     static const NEONFormatMap map = {{30}, {NF_4H, NF_8H}};
777     return &map;
778   }
779 
780   // The load/store format map uses three bits (Q, 11, 10) to encode the
781   // set of NEON vector formats.
LoadStoreFormatMap()782   static const NEONFormatMap* LoadStoreFormatMap() {
783     static const NEONFormatMap map =
784         {{11, 10, 30},
785          {NF_8B, NF_16B, NF_4H, NF_8H, NF_2S, NF_4S, NF_1D, NF_2D}};
786     return &map;
787   }
788 
789   // The logical format map uses one bit (Q) to encode the NEON vector format:
790   // NF_8B, NF_16B.
LogicalFormatMap()791   static const NEONFormatMap* LogicalFormatMap() {
792     static const NEONFormatMap map = {{30}, {NF_8B, NF_16B}};
793     return &map;
794   }
795 
796   // The triangular format map uses between two and five bits to encode the NEON
797   // vector format:
798   // xxx10->8B, xxx11->16B, xx100->4H, xx101->8H
799   // x1000->2S, x1001->4S,  10001->2D, all others undefined.
TriangularFormatMap()800   static const NEONFormatMap* TriangularFormatMap() {
801     static const NEONFormatMap map =
802         {{19, 18, 17, 16, 30},
803          {NF_UNDEF, NF_UNDEF, NF_8B, NF_16B, NF_4H, NF_8H, NF_8B, NF_16B,
804           NF_2S,    NF_4S,    NF_8B, NF_16B, NF_4H, NF_8H, NF_8B, NF_16B,
805           NF_UNDEF, NF_2D,    NF_8B, NF_16B, NF_4H, NF_8H, NF_8B, NF_16B,
806           NF_2S,    NF_4S,    NF_8B, NF_16B, NF_4H, NF_8H, NF_8B, NF_16B}};
807     return &map;
808   }
809 
810   // The scalar format map uses two bits (size<1:0>) to encode the NEON scalar
811   // formats: NF_B, NF_H, NF_S, NF_D.
ScalarFormatMap()812   static const NEONFormatMap* ScalarFormatMap() {
813     static const NEONFormatMap map = {{23, 22}, {NF_B, NF_H, NF_S, NF_D}};
814     return &map;
815   }
816 
817   // The long scalar format map uses two bits (size<1:0>) to encode the longer
818   // NEON scalar formats: NF_H, NF_S, NF_D.
LongScalarFormatMap()819   static const NEONFormatMap* LongScalarFormatMap() {
820     static const NEONFormatMap map = {{23, 22}, {NF_H, NF_S, NF_D}};
821     return &map;
822   }
823 
824   // The FP scalar format map assumes one bit (size<0>) is used to encode the
825   // NEON FP scalar formats: NF_S, NF_D.
FPScalarFormatMap()826   static const NEONFormatMap* FPScalarFormatMap() {
827     static const NEONFormatMap map = {{22}, {NF_S, NF_D}};
828     return &map;
829   }
830 
831   // The FP scalar pairwise format map assumes two bits (U, size<0>) are used to
832   // encode the NEON FP scalar formats: NF_H, NF_S, NF_D.
FPScalarPairwiseFormatMap()833   static const NEONFormatMap* FPScalarPairwiseFormatMap() {
834     static const NEONFormatMap map = {{29, 22}, {NF_H, NF_UNDEF, NF_S, NF_D}};
835     return &map;
836   }
837 
838   // The triangular scalar format map uses between one and four bits to encode
839   // the NEON FP scalar formats:
840   // xxx1->B, xx10->H, x100->S, 1000->D, all others undefined.
TriangularScalarFormatMap()841   static const NEONFormatMap* TriangularScalarFormatMap() {
842     static const NEONFormatMap map = {{19, 18, 17, 16},
843                                       {NF_UNDEF,
844                                        NF_B,
845                                        NF_H,
846                                        NF_B,
847                                        NF_S,
848                                        NF_B,
849                                        NF_H,
850                                        NF_B,
851                                        NF_D,
852                                        NF_B,
853                                        NF_H,
854                                        NF_B,
855                                        NF_S,
856                                        NF_B,
857                                        NF_H,
858                                        NF_B}};
859     return &map;
860   }
861 
862  private:
863   // Get a pointer to a string that represents the format or placeholder for
864   // the specified substitution index, based on the format map and instruction.
GetSubstitute(int index,SubstitutionMode mode)865   const char* GetSubstitute(int index, SubstitutionMode mode) {
866     if (mode == kFormat) {
867       return NEONFormatAsString(GetNEONFormat(formats_[index]));
868     }
869     VIXL_ASSERT(mode == kPlaceholder);
870     return NEONFormatAsPlaceholder(GetNEONFormat(formats_[index]));
871   }
872 
873   // Get the NEONFormat enumerated value for bits obtained from the
874   // instruction based on the specified format mapping.
GetNEONFormat(const NEONFormatMap * format_map)875   NEONFormat GetNEONFormat(const NEONFormatMap* format_map) {
876     return format_map->map[PickBits(format_map->bits)];
877   }
878 
879   // Convert a NEONFormat into a string.
NEONFormatAsString(NEONFormat format)880   static const char* NEONFormatAsString(NEONFormat format) {
881     // clang-format off
882     static const char* formats[] = {
883       "undefined",
884       "8b", "16b", "4h", "8h", "2s", "4s", "1d", "2d",
885       "b", "h", "s", "d"
886     };
887     // clang-format on
888     VIXL_ASSERT(format < ArrayLength(formats));
889     return formats[format];
890   }
891 
892   // Convert a NEONFormat into a register placeholder string.
NEONFormatAsPlaceholder(NEONFormat format)893   static const char* NEONFormatAsPlaceholder(NEONFormat format) {
894     VIXL_ASSERT((format == NF_B) || (format == NF_H) || (format == NF_S) ||
895                 (format == NF_D) || (format == NF_UNDEF));
896     // clang-format off
897     static const char* formats[] = {
898       "undefined",
899       "undefined", "undefined", "undefined", "undefined",
900       "undefined", "undefined", "undefined", "undefined",
901       "'B", "'H", "'S", "'D"
902     };
903     // clang-format on
904     return formats[format];
905   }
906 
907   // Select bits from instrbits_ defined by the bits array, concatenate them,
908   // and return the value.
PickBits(const uint8_t bits[])909   uint8_t PickBits(const uint8_t bits[]) {
910     uint8_t result = 0;
911     for (unsigned b = 0; b < kNEONFormatMaxBits; b++) {
912       if (bits[b] == 0) break;
913       result <<= 1;
914       result |= ((instrbits_ & (1 << bits[b])) == 0) ? 0 : 1;
915     }
916     return result;
917   }
918 
919   Instr instrbits_;
920   const NEONFormatMap* formats_[3];
921   char form_buffer_[64];
922   char mne_buffer_[16];
923 };
924 }  // namespace aarch64
925 }  // namespace vixl
926 
927 #endif  // VIXL_AARCH64_INSTRUCTIONS_AARCH64_H_
928