• 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 kHSignMask = UINT64_C(0x8000);
85 const uint64_t kSSignMask = UINT64_C(0x80000000);
86 const uint64_t kDSignMask = UINT64_C(0x8000000000000000);
87 const uint64_t kWSignMask = UINT64_C(0x80000000);
88 const uint64_t kXSignMask = UINT64_C(0x8000000000000000);
89 const uint64_t kByteMask = UINT64_C(0xff);
90 const uint64_t kHalfWordMask = UINT64_C(0xffff);
91 const uint64_t kWordMask = UINT64_C(0xffffffff);
92 const uint64_t kXMaxUInt = UINT64_C(0xffffffffffffffff);
93 const uint64_t kWMaxUInt = UINT64_C(0xffffffff);
94 const uint64_t kHMaxUInt = UINT64_C(0xffff);
95 // Define k*MinInt with "-k*MaxInt - 1", because the hexadecimal representation
96 // (e.g. "INT32_C(0x80000000)") has implementation-defined behaviour.
97 const int64_t kXMaxInt = INT64_C(0x7fffffffffffffff);
98 const int64_t kXMinInt = -kXMaxInt - 1;
99 const int32_t kWMaxInt = INT32_C(0x7fffffff);
100 const int32_t kWMinInt = -kWMaxInt - 1;
101 const int16_t kHMaxInt = INT16_C(0x7fff);
102 const int16_t kHMinInt = -kHMaxInt - 1;
103 const unsigned kFpRegCode = 29;
104 const unsigned kLinkRegCode = 30;
105 const unsigned kSpRegCode = 31;
106 const unsigned kZeroRegCode = 31;
107 const unsigned kSPRegInternalCode = 63;
108 const unsigned kRegCodeMask = 0x1f;
109 
110 const unsigned kAtomicAccessGranule = 16;
111 
112 const unsigned kAddressTagOffset = 56;
113 const unsigned kAddressTagWidth = 8;
114 const uint64_t kAddressTagMask = ((UINT64_C(1) << kAddressTagWidth) - 1)
115                                  << kAddressTagOffset;
116 VIXL_STATIC_ASSERT(kAddressTagMask == UINT64_C(0xff00000000000000));
117 
118 const uint64_t kTTBRMask = UINT64_C(1) << 55;
119 
120 // We can't define a static kZRegSize because the size depends on the
121 // implementation. However, it is sometimes useful to know the minimum and
122 // maximum possible sizes.
123 const unsigned kZRegMinSize = 128;
124 const unsigned kZRegMinSizeLog2 = 7;
125 const unsigned kZRegMinSizeInBytes = kZRegMinSize / 8;
126 const unsigned kZRegMinSizeInBytesLog2 = kZRegMinSizeLog2 - 3;
127 const unsigned kZRegMaxSize = 2048;
128 const unsigned kZRegMaxSizeLog2 = 11;
129 const unsigned kZRegMaxSizeInBytes = kZRegMaxSize / 8;
130 const unsigned kZRegMaxSizeInBytesLog2 = kZRegMaxSizeLog2 - 3;
131 
132 // The P register size depends on the Z register size.
133 const unsigned kZRegBitsPerPRegBit = kBitsPerByte;
134 const unsigned kZRegBitsPerPRegBitLog2 = 3;
135 const unsigned kPRegMinSize = kZRegMinSize / kZRegBitsPerPRegBit;
136 const unsigned kPRegMinSizeLog2 = kZRegMinSizeLog2 - 3;
137 const unsigned kPRegMinSizeInBytes = kPRegMinSize / 8;
138 const unsigned kPRegMinSizeInBytesLog2 = kPRegMinSizeLog2 - 3;
139 const unsigned kPRegMaxSize = kZRegMaxSize / kZRegBitsPerPRegBit;
140 const unsigned kPRegMaxSizeLog2 = kZRegMaxSizeLog2 - 3;
141 const unsigned kPRegMaxSizeInBytes = kPRegMaxSize / 8;
142 const unsigned kPRegMaxSizeInBytesLog2 = kPRegMaxSizeLog2 - 3;
143 
144 const unsigned kMTETagGranuleInBytes = 16;
145 const unsigned kMTETagGranuleInBytesLog2 = 4;
146 const unsigned kMTETagWidth = 4;
147 
148 // Make these moved float constants backwards compatible
149 // with explicit vixl::aarch64:: namespace references.
150 using vixl::kDoubleExponentBits;
151 using vixl::kDoubleMantissaBits;
152 using vixl::kFloat16ExponentBits;
153 using vixl::kFloat16MantissaBits;
154 using vixl::kFloatExponentBits;
155 using vixl::kFloatMantissaBits;
156 
157 using vixl::kFP16NegativeInfinity;
158 using vixl::kFP16PositiveInfinity;
159 using vixl::kFP32NegativeInfinity;
160 using vixl::kFP32PositiveInfinity;
161 using vixl::kFP64NegativeInfinity;
162 using vixl::kFP64PositiveInfinity;
163 
164 using vixl::kFP16DefaultNaN;
165 using vixl::kFP32DefaultNaN;
166 using vixl::kFP64DefaultNaN;
167 
168 unsigned CalcLSDataSize(LoadStoreOp op);
169 unsigned CalcLSPairDataSize(LoadStorePairOp op);
170 
171 enum ImmBranchType {
172   UnknownBranchType = 0,
173   CondBranchType = 1,
174   UncondBranchType = 2,
175   CompareBranchType = 3,
176   TestBranchType = 4
177 };
178 
179 enum AddrMode { Offset, PreIndex, PostIndex };
180 
181 enum Reg31Mode { Reg31IsStackPointer, Reg31IsZeroRegister };
182 
183 enum VectorFormat {
184   kFormatUndefined = 0xffffffff,
185   kFormat8B = NEON_8B,
186   kFormat16B = NEON_16B,
187   kFormat4H = NEON_4H,
188   kFormat8H = NEON_8H,
189   kFormat2S = NEON_2S,
190   kFormat4S = NEON_4S,
191   kFormat1D = NEON_1D,
192   kFormat2D = NEON_2D,
193 
194   // Scalar formats. We add the scalar bit to distinguish between scalar and
195   // vector enumerations; the bit is always set in the encoding of scalar ops
196   // and always clear for vector ops. Although kFormatD and kFormat1D appear
197   // to be the same, their meaning is subtly different. The first is a scalar
198   // operation, the second a vector operation that only affects one lane.
199   kFormatB = NEON_B | NEONScalar,
200   kFormatH = NEON_H | NEONScalar,
201   kFormatS = NEON_S | NEONScalar,
202   kFormatD = NEON_D | NEONScalar,
203 
204   // An artificial value, used to distinguish from NEON format category.
205   kFormatSVE = 0x0000fffd,
206   // Artificial values. Q and O lane sizes aren't encoded in the usual size
207   // field.
208   kFormatSVEQ = 0x00080000,
209   kFormatSVEO = 0x00040000,
210 
211   // Vector element width of SVE register with the unknown lane count since
212   // the vector length is implementation dependent.
213   kFormatVnB = SVE_B | kFormatSVE,
214   kFormatVnH = SVE_H | kFormatSVE,
215   kFormatVnS = SVE_S | kFormatSVE,
216   kFormatVnD = SVE_D | kFormatSVE,
217   kFormatVnQ = kFormatSVEQ | kFormatSVE,
218   kFormatVnO = kFormatSVEO | kFormatSVE,
219 
220   // Artificial values, used by simulator trace tests and a few oddball
221   // instructions (such as FMLAL).
222   kFormat2H = 0xfffffffe,
223   kFormat1Q = 0xfffffffd
224 };
225 
226 // Instructions. ---------------------------------------------------------------
227 
228 class Instruction {
229  public:
GetInstructionBits()230   Instr GetInstructionBits() const {
231     return *(reinterpret_cast<const Instr*>(this));
232   }
233   VIXL_DEPRECATED("GetInstructionBits", Instr InstructionBits() const) {
234     return GetInstructionBits();
235   }
236 
SetInstructionBits(Instr new_instr)237   void SetInstructionBits(Instr new_instr) {
238     *(reinterpret_cast<Instr*>(this)) = new_instr;
239   }
240 
ExtractBit(int pos)241   int ExtractBit(int pos) const { return (GetInstructionBits() >> pos) & 1; }
Bit(int pos)242   VIXL_DEPRECATED("ExtractBit", int Bit(int pos) const) {
243     return ExtractBit(pos);
244   }
245 
ExtractBits(int msb,int lsb)246   uint32_t ExtractBits(int msb, int lsb) const {
247     return ExtractUnsignedBitfield32(msb, lsb, GetInstructionBits());
248   }
249   VIXL_DEPRECATED("ExtractBits", uint32_t Bits(int msb, int lsb) const) {
250     return ExtractBits(msb, lsb);
251   }
252 
253   // Compress bit extraction operation from Hacker's Delight.
254   // https://github.com/hcs0/Hackers-Delight/blob/master/compress.c.txt
Compress(uint32_t mask)255   uint32_t Compress(uint32_t mask) const {
256     uint32_t mk, mp, mv, t;
257     uint32_t x = GetInstructionBits() & mask;  // Clear irrelevant bits.
258     mk = ~mask << 1;                           // We will count 0's to right.
259     for (int i = 0; i < 5; i++) {
260       mp = mk ^ (mk << 1);  // Parallel suffix.
261       mp = mp ^ (mp << 2);
262       mp = mp ^ (mp << 4);
263       mp = mp ^ (mp << 8);
264       mp = mp ^ (mp << 16);
265       mv = mp & mask;                         // Bits to move.
266       mask = (mask ^ mv) | (mv >> (1 << i));  // Compress mask.
267       t = x & mv;
268       x = (x ^ t) | (t >> (1 << i));  // Compress x.
269       mk = mk & ~mp;
270     }
271     return x;
272   }
273 
274   template <uint32_t M>
ExtractBits()275   uint32_t ExtractBits() const {
276     return Compress(M);
277   }
278 
ExtractBitsAbsent()279   uint32_t ExtractBitsAbsent() const {
280     VIXL_UNREACHABLE();
281     return 0;
282   }
283 
284   template <uint32_t M, uint32_t V>
IsMaskedValue()285   uint32_t IsMaskedValue() const {
286     return (Mask(M) == V) ? 1 : 0;
287   }
288 
IsMaskedValueAbsent()289   uint32_t IsMaskedValueAbsent() const {
290     VIXL_UNREACHABLE();
291     return 0;
292   }
293 
ExtractSignedBits(int msb,int lsb)294   int32_t ExtractSignedBits(int msb, int lsb) const {
295     int32_t bits = *(reinterpret_cast<const int32_t*>(this));
296     return ExtractSignedBitfield32(msb, lsb, bits);
297   }
298   VIXL_DEPRECATED("ExtractSignedBits",
299                   int32_t SignedBits(int msb, int lsb) const) {
300     return ExtractSignedBits(msb, lsb);
301   }
302 
Mask(uint32_t mask)303   Instr Mask(uint32_t mask) const {
304     VIXL_ASSERT(mask != 0);
305     return GetInstructionBits() & mask;
306   }
307 
308 #define DEFINE_GETTER(Name, HighBit, LowBit, Func)                  \
309   int32_t Get##Name() const { return this->Func(HighBit, LowBit); } \
310   VIXL_DEPRECATED("Get" #Name, int32_t Name() const) { return Get##Name(); }
INSTRUCTION_FIELDS_LIST(DEFINE_GETTER)311   INSTRUCTION_FIELDS_LIST(DEFINE_GETTER)
312 #undef DEFINE_GETTER
313 
314   template <int msb, int lsb>
315   int32_t GetRx() const {
316     // We don't have any register fields wider than five bits, so the result
317     // will always fit into an int32_t.
318     VIXL_ASSERT((msb - lsb + 1) <= 5);
319     return this->ExtractBits(msb, lsb);
320   }
321 
322   VectorFormat GetSVEVectorFormat(int field_lsb = 22) const {
323     VIXL_ASSERT((field_lsb >= 0) && (field_lsb <= 30));
324     uint32_t instr = ExtractUnsignedBitfield32(field_lsb + 1,
325                                                field_lsb,
326                                                GetInstructionBits())
327                      << 22;
328     switch (instr & SVESizeFieldMask) {
329       case SVE_B:
330         return kFormatVnB;
331       case SVE_H:
332         return kFormatVnH;
333       case SVE_S:
334         return kFormatVnS;
335       case SVE_D:
336         return kFormatVnD;
337     }
338     VIXL_UNREACHABLE();
339     return kFormatUndefined;
340   }
341 
342   // ImmPCRel is a compound field (not present in INSTRUCTION_FIELDS_LIST),
343   // formed from ImmPCRelLo and ImmPCRelHi.
GetImmPCRel()344   int GetImmPCRel() const {
345     uint32_t hi = static_cast<uint32_t>(GetImmPCRelHi());
346     uint32_t lo = GetImmPCRelLo();
347     uint32_t offset = (hi << ImmPCRelLo_width) | lo;
348     int width = ImmPCRelLo_width + ImmPCRelHi_width;
349     return ExtractSignedBitfield32(width - 1, 0, offset);
350   }
ImmPCRel()351   VIXL_DEPRECATED("GetImmPCRel", int ImmPCRel() const) { return GetImmPCRel(); }
352 
353   // ImmLSPAC is a compound field (not present in INSTRUCTION_FIELDS_LIST),
354   // formed from ImmLSPACLo and ImmLSPACHi.
GetImmLSPAC()355   int GetImmLSPAC() const {
356     uint32_t hi = static_cast<uint32_t>(GetImmLSPACHi());
357     uint32_t lo = GetImmLSPACLo();
358     uint32_t offset = (hi << ImmLSPACLo_width) | lo;
359     int width = ImmLSPACLo_width + ImmLSPACHi_width;
360     return ExtractSignedBitfield32(width - 1, 0, offset) << 3;
361   }
362 
363   uint64_t GetImmLogical() const;
364   VIXL_DEPRECATED("GetImmLogical", uint64_t ImmLogical() const) {
365     return GetImmLogical();
366   }
367   uint64_t GetSVEImmLogical() const;
368   int GetSVEBitwiseImmLaneSizeInBytesLog2() const;
369   uint64_t DecodeImmBitMask(int32_t n,
370                             int32_t imm_s,
371                             int32_t imm_r,
372                             int32_t size) const;
373 
374   std::pair<int, int> GetSVEPermuteIndexAndLaneSizeLog2() const;
375 
376   std::pair<int, int> GetNEONMulRmAndIndex() const;
377   std::pair<int, int> GetSVEMulZmAndIndex() const;
378   std::pair<int, int> GetSVEMulLongZmAndIndex() const;
379 
380   std::pair<int, int> GetSVEImmShiftAndLaneSizeLog2(bool is_predicated) const;
381 
382   int GetSVEExtractImmediate() const;
383 
384   int GetSVEMsizeFromDtype(bool is_signed, int dtype_h_lsb = 23) const;
385 
386   int GetSVEEsizeFromDtype(bool is_signed, int dtype_l_lsb = 21) const;
387 
388 
389   unsigned GetImmNEONabcdefgh() const;
ImmNEONabcdefgh()390   VIXL_DEPRECATED("GetImmNEONabcdefgh", unsigned ImmNEONabcdefgh() const) {
391     return GetImmNEONabcdefgh();
392   }
393 
394   Float16 GetImmFP16() const;
395 
396   float GetImmFP32() const;
ImmFP32()397   VIXL_DEPRECATED("GetImmFP32", float ImmFP32() const) { return GetImmFP32(); }
398 
399   double GetImmFP64() const;
ImmFP64()400   VIXL_DEPRECATED("GetImmFP64", double ImmFP64() const) { return GetImmFP64(); }
401 
402   Float16 GetImmNEONFP16() const;
403 
404   float GetImmNEONFP32() const;
ImmNEONFP32()405   VIXL_DEPRECATED("GetImmNEONFP32", float ImmNEONFP32() const) {
406     return GetImmNEONFP32();
407   }
408 
409   double GetImmNEONFP64() const;
ImmNEONFP64()410   VIXL_DEPRECATED("GetImmNEONFP64", double ImmNEONFP64() const) {
411     return GetImmNEONFP64();
412   }
413 
GetSVEImmFP16()414   Float16 GetSVEImmFP16() const { return Imm8ToFloat16(ExtractBits(12, 5)); }
415 
GetSVEImmFP32()416   float GetSVEImmFP32() const { return Imm8ToFP32(ExtractBits(12, 5)); }
417 
GetSVEImmFP64()418   double GetSVEImmFP64() const { return Imm8ToFP64(ExtractBits(12, 5)); }
419 
420   static Float16 Imm8ToFloat16(uint32_t imm8);
421   static float Imm8ToFP32(uint32_t imm8);
422   static double Imm8ToFP64(uint32_t imm8);
423 
GetSizeLS()424   unsigned GetSizeLS() const {
425     return CalcLSDataSize(static_cast<LoadStoreOp>(Mask(LoadStoreMask)));
426   }
SizeLS()427   VIXL_DEPRECATED("GetSizeLS", unsigned SizeLS() const) { return GetSizeLS(); }
428 
GetSizeLSPair()429   unsigned GetSizeLSPair() const {
430     return CalcLSPairDataSize(
431         static_cast<LoadStorePairOp>(Mask(LoadStorePairMask)));
432   }
SizeLSPair()433   VIXL_DEPRECATED("GetSizeLSPair", unsigned SizeLSPair() const) {
434     return GetSizeLSPair();
435   }
436 
GetNEONLSIndex(int access_size_shift)437   int GetNEONLSIndex(int access_size_shift) const {
438     int64_t q = GetNEONQ();
439     int64_t s = GetNEONS();
440     int64_t size = GetNEONLSSize();
441     int64_t index = (q << 3) | (s << 2) | size;
442     return static_cast<int>(index >> access_size_shift);
443   }
444   VIXL_DEPRECATED("GetNEONLSIndex",
NEONLSIndex(int access_size_shift)445                   int NEONLSIndex(int access_size_shift) const) {
446     return GetNEONLSIndex(access_size_shift);
447   }
448 
449   // Helpers.
IsCondBranchImm()450   bool IsCondBranchImm() const {
451     return Mask(ConditionalBranchFMask) == ConditionalBranchFixed;
452   }
453 
IsUncondBranchImm()454   bool IsUncondBranchImm() const {
455     return Mask(UnconditionalBranchFMask) == UnconditionalBranchFixed;
456   }
457 
IsCompareBranch()458   bool IsCompareBranch() const {
459     return Mask(CompareBranchFMask) == CompareBranchFixed;
460   }
461 
IsTestBranch()462   bool IsTestBranch() const { return Mask(TestBranchFMask) == TestBranchFixed; }
463 
IsImmBranch()464   bool IsImmBranch() const { return GetBranchType() != UnknownBranchType; }
465 
IsPCRelAddressing()466   bool IsPCRelAddressing() const {
467     return Mask(PCRelAddressingFMask) == PCRelAddressingFixed;
468   }
469 
IsLogicalImmediate()470   bool IsLogicalImmediate() const {
471     return Mask(LogicalImmediateFMask) == LogicalImmediateFixed;
472   }
473 
IsAddSubImmediate()474   bool IsAddSubImmediate() const {
475     return Mask(AddSubImmediateFMask) == AddSubImmediateFixed;
476   }
477 
IsAddSubExtended()478   bool IsAddSubExtended() const {
479     return Mask(AddSubExtendedFMask) == AddSubExtendedFixed;
480   }
481 
IsLoadOrStore()482   bool IsLoadOrStore() const {
483     return Mask(LoadStoreAnyFMask) == LoadStoreAnyFixed;
484   }
485 
486   // True if `this` is valid immediately after the provided movprfx instruction.
487   bool CanTakeSVEMovprfx(uint32_t form_hash, Instruction const* movprfx) const;
488   bool CanTakeSVEMovprfx(const char* form, Instruction const* movprfx) const;
489 
490   bool IsLoad() const;
491   bool IsStore() const;
492 
IsLoadLiteral()493   bool IsLoadLiteral() const {
494     // This includes PRFM_lit.
495     return Mask(LoadLiteralFMask) == LoadLiteralFixed;
496   }
497 
IsMovn()498   bool IsMovn() const {
499     return (Mask(MoveWideImmediateMask) == MOVN_x) ||
500            (Mask(MoveWideImmediateMask) == MOVN_w);
501   }
502 
IsException()503   bool IsException() const { return Mask(ExceptionFMask) == ExceptionFixed; }
504 
IsPAuth()505   bool IsPAuth() const { return Mask(SystemPAuthFMask) == SystemPAuthFixed; }
506 
IsBti()507   bool IsBti() const {
508     if (Mask(SystemHintFMask) == SystemHintFixed) {
509       int imm_hint = GetImmHint();
510       switch (imm_hint) {
511         case BTI:
512         case BTI_c:
513         case BTI_j:
514         case BTI_jc:
515           return true;
516       }
517     }
518     return false;
519   }
520 
IsMOPSPrologueOf(const Instruction * instr,uint32_t mops_type)521   bool IsMOPSPrologueOf(const Instruction* instr, uint32_t mops_type) const {
522     VIXL_ASSERT((mops_type == "set"_h) || (mops_type == "setg"_h) ||
523                 (mops_type == "cpy"_h));
524     const int op_lsb = (mops_type == "cpy"_h) ? 22 : 14;
525     return GetInstructionBits() == instr->Mask(~(0x3U << op_lsb));
526   }
527 
IsMOPSMainOf(const Instruction * instr,uint32_t mops_type)528   bool IsMOPSMainOf(const Instruction* instr, uint32_t mops_type) const {
529     VIXL_ASSERT((mops_type == "set"_h) || (mops_type == "setg"_h) ||
530                 (mops_type == "cpy"_h));
531     const int op_lsb = (mops_type == "cpy"_h) ? 22 : 14;
532     return GetInstructionBits() ==
533            (instr->Mask(~(0x3U << op_lsb)) | (0x1 << op_lsb));
534   }
535 
IsMOPSEpilogueOf(const Instruction * instr,uint32_t mops_type)536   bool IsMOPSEpilogueOf(const Instruction* instr, uint32_t mops_type) const {
537     VIXL_ASSERT((mops_type == "set"_h) || (mops_type == "setg"_h) ||
538                 (mops_type == "cpy"_h));
539     const int op_lsb = (mops_type == "cpy"_h) ? 22 : 14;
540     return GetInstructionBits() ==
541            (instr->Mask(~(0x3U << op_lsb)) | (0x2 << op_lsb));
542   }
543 
544   template <uint32_t mops_type>
IsConsistentMOPSTriplet()545   bool IsConsistentMOPSTriplet() const {
546     VIXL_STATIC_ASSERT((mops_type == "set"_h) || (mops_type == "setg"_h) ||
547                        (mops_type == "cpy"_h));
548 
549     int64_t isize = static_cast<int64_t>(kInstructionSize);
550     const Instruction* prev2 = GetInstructionAtOffset(-2 * isize);
551     const Instruction* prev1 = GetInstructionAtOffset(-1 * isize);
552     const Instruction* next1 = GetInstructionAtOffset(1 * isize);
553     const Instruction* next2 = GetInstructionAtOffset(2 * isize);
554 
555     // Use the encoding of the current instruction to determine the expected
556     // adjacent instructions. NB. this doesn't check if the nearby instructions
557     // are MOPS-type, but checks that they form a consistent triplet if they
558     // are. For example, 'mov x0, #0; mov x0, #512; mov x0, #1024' is a
559     // consistent triplet, but they are not MOPS instructions.
560     const int op_lsb = (mops_type == "cpy"_h) ? 22 : 14;
561     const uint32_t kMOPSOpfield = 0x3 << op_lsb;
562     const uint32_t kMOPSPrologue = 0;
563     const uint32_t kMOPSMain = 0x1 << op_lsb;
564     const uint32_t kMOPSEpilogue = 0x2 << op_lsb;
565     switch (Mask(kMOPSOpfield)) {
566       case kMOPSPrologue:
567         return next1->IsMOPSMainOf(this, mops_type) &&
568                next2->IsMOPSEpilogueOf(this, mops_type);
569       case kMOPSMain:
570         return prev1->IsMOPSPrologueOf(this, mops_type) &&
571                next1->IsMOPSEpilogueOf(this, mops_type);
572       case kMOPSEpilogue:
573         return prev2->IsMOPSPrologueOf(this, mops_type) &&
574                prev1->IsMOPSMainOf(this, mops_type);
575       default:
576         VIXL_ABORT_WITH_MSG("Undefined MOPS operation\n");
577     }
578   }
579 
580   static int GetImmBranchRangeBitwidth(ImmBranchType branch_type);
581   VIXL_DEPRECATED(
582       "GetImmBranchRangeBitwidth",
ImmBranchRangeBitwidth(ImmBranchType branch_type)583       static int ImmBranchRangeBitwidth(ImmBranchType branch_type)) {
584     return GetImmBranchRangeBitwidth(branch_type);
585   }
586 
587   static int32_t GetImmBranchForwardRange(ImmBranchType branch_type);
588   VIXL_DEPRECATED(
589       "GetImmBranchForwardRange",
590       static int32_t ImmBranchForwardRange(ImmBranchType branch_type)) {
591     return GetImmBranchForwardRange(branch_type);
592   }
593 
594   static bool IsValidImmPCOffset(ImmBranchType branch_type, int64_t offset);
595 
596   // Indicate whether Rd can be the stack pointer or the zero register. This
597   // does not check that the instruction actually has an Rd field.
GetRdMode()598   Reg31Mode GetRdMode() const {
599     // The following instructions use sp or wsp as Rd:
600     //  Add/sub (immediate) when not setting the flags.
601     //  Add/sub (extended) when not setting the flags.
602     //  Logical (immediate) when not setting the flags.
603     // Otherwise, r31 is the zero register.
604     if (IsAddSubImmediate() || IsAddSubExtended()) {
605       if (Mask(AddSubSetFlagsBit)) {
606         return Reg31IsZeroRegister;
607       } else {
608         return Reg31IsStackPointer;
609       }
610     }
611     if (IsLogicalImmediate()) {
612       // Of the logical (immediate) instructions, only ANDS (and its aliases)
613       // can set the flags. The others can all write into sp.
614       // Note that some logical operations are not available to
615       // immediate-operand instructions, so we have to combine two masks here.
616       if (Mask(LogicalImmediateMask & LogicalOpMask) == ANDS) {
617         return Reg31IsZeroRegister;
618       } else {
619         return Reg31IsStackPointer;
620       }
621     }
622     return Reg31IsZeroRegister;
623   }
624   VIXL_DEPRECATED("GetRdMode", Reg31Mode RdMode() const) { return GetRdMode(); }
625 
626   // Indicate whether Rn can be the stack pointer or the zero register. This
627   // does not check that the instruction actually has an Rn field.
GetRnMode()628   Reg31Mode GetRnMode() const {
629     // The following instructions use sp or wsp as Rn:
630     //  All loads and stores.
631     //  Add/sub (immediate).
632     //  Add/sub (extended).
633     // Otherwise, r31 is the zero register.
634     if (IsLoadOrStore() || IsAddSubImmediate() || IsAddSubExtended()) {
635       return Reg31IsStackPointer;
636     }
637     return Reg31IsZeroRegister;
638   }
639   VIXL_DEPRECATED("GetRnMode", Reg31Mode RnMode() const) { return GetRnMode(); }
640 
GetBranchType()641   ImmBranchType GetBranchType() const {
642     if (IsCondBranchImm()) {
643       return CondBranchType;
644     } else if (IsUncondBranchImm()) {
645       return UncondBranchType;
646     } else if (IsCompareBranch()) {
647       return CompareBranchType;
648     } else if (IsTestBranch()) {
649       return TestBranchType;
650     } else {
651       return UnknownBranchType;
652     }
653   }
654   VIXL_DEPRECATED("GetBranchType", ImmBranchType BranchType() const) {
655     return GetBranchType();
656   }
657 
658   // Find the target of this instruction. 'this' may be a branch or a
659   // PC-relative addressing instruction.
660   const Instruction* GetImmPCOffsetTarget() const;
661   VIXL_DEPRECATED("GetImmPCOffsetTarget",
662                   const Instruction* ImmPCOffsetTarget() const) {
663     return GetImmPCOffsetTarget();
664   }
665 
666   // Patch a PC-relative offset to refer to 'target'. 'this' may be a branch or
667   // a PC-relative addressing instruction.
668   void SetImmPCOffsetTarget(const Instruction* target);
669   // Patch a literal load instruction to load from 'source'.
670   void SetImmLLiteral(const Instruction* source);
671 
672   // The range of a load literal instruction, expressed as 'instr +- range'.
673   // The range is actually the 'positive' range; the branch instruction can
674   // target [instr - range - kInstructionSize, instr + range].
675   static const int kLoadLiteralImmBitwidth = 19;
676   static const int kLoadLiteralRange =
677       (1 << kLoadLiteralImmBitwidth) / 2 - kInstructionSize;
678 
679   // Calculate the address of a literal referred to by a load-literal
680   // instruction, and return it as the specified type.
681   //
682   // The literal itself is safely mutable only if the backing buffer is safely
683   // mutable.
684   template <typename T>
GetLiteralAddress()685   T GetLiteralAddress() const {
686     uint64_t base_raw = reinterpret_cast<uint64_t>(this);
687     int64_t offset = GetImmLLiteral() * static_cast<int>(kLiteralEntrySize);
688     uint64_t address_raw = base_raw + offset;
689 
690     // Cast the address using a C-style cast. A reinterpret_cast would be
691     // appropriate, but it can't cast one integral type to another.
692     T address = (T)(address_raw);
693 
694     // Assert that the address can be represented by the specified type.
695     VIXL_ASSERT((uint64_t)(address) == address_raw);
696 
697     return address;
698   }
699   template <typename T>
700   VIXL_DEPRECATED("GetLiteralAddress", T LiteralAddress() const) {
701     return GetLiteralAddress<T>();
702   }
703 
GetLiteral32()704   uint32_t GetLiteral32() const {
705     uint32_t literal;
706     memcpy(&literal, GetLiteralAddress<const void*>(), sizeof(literal));
707     return literal;
708   }
709   VIXL_DEPRECATED("GetLiteral32", uint32_t Literal32() const) {
710     return GetLiteral32();
711   }
712 
GetLiteral64()713   uint64_t GetLiteral64() const {
714     uint64_t literal;
715     memcpy(&literal, GetLiteralAddress<const void*>(), sizeof(literal));
716     return literal;
717   }
718   VIXL_DEPRECATED("GetLiteral64", uint64_t Literal64() const) {
719     return GetLiteral64();
720   }
721 
GetLiteralFP32()722   float GetLiteralFP32() const { return RawbitsToFloat(GetLiteral32()); }
LiteralFP32()723   VIXL_DEPRECATED("GetLiteralFP32", float LiteralFP32() const) {
724     return GetLiteralFP32();
725   }
726 
GetLiteralFP64()727   double GetLiteralFP64() const { return RawbitsToDouble(GetLiteral64()); }
LiteralFP64()728   VIXL_DEPRECATED("GetLiteralFP64", double LiteralFP64() const) {
729     return GetLiteralFP64();
730   }
731 
GetNextInstruction()732   Instruction* GetNextInstruction() { return this + kInstructionSize; }
GetNextInstruction()733   const Instruction* GetNextInstruction() const {
734     return this + kInstructionSize;
735   }
736   VIXL_DEPRECATED("GetNextInstruction",
737                   const Instruction* NextInstruction() const) {
738     return GetNextInstruction();
739   }
740 
GetInstructionAtOffset(int64_t offset)741   const Instruction* GetInstructionAtOffset(int64_t offset) const {
742     VIXL_ASSERT(IsWordAligned(this + offset));
743     return this + offset;
744   }
745   VIXL_DEPRECATED("GetInstructionAtOffset",
746                   const Instruction* InstructionAtOffset(int64_t offset)
747                       const) {
748     return GetInstructionAtOffset(offset);
749   }
750 
751   template <typename T>
Cast(T src)752   static Instruction* Cast(T src) {
753     return reinterpret_cast<Instruction*>(src);
754   }
755 
756   template <typename T>
CastConst(T src)757   static const Instruction* CastConst(T src) {
758     return reinterpret_cast<const Instruction*>(src);
759   }
760 
761  private:
762   int GetImmBranch() const;
763 
764   void SetPCRelImmTarget(const Instruction* target);
765   void SetBranchImmTarget(const Instruction* target);
766 };
767 
768 
769 // Functions for handling NEON and SVE vector format information.
770 
771 const int kMaxLanesPerVector = 16;
772 
773 VectorFormat VectorFormatHalfWidth(VectorFormat vform);
774 VectorFormat VectorFormatDoubleWidth(VectorFormat vform);
775 VectorFormat VectorFormatDoubleLanes(VectorFormat vform);
776 VectorFormat VectorFormatHalfLanes(VectorFormat vform);
777 VectorFormat ScalarFormatFromLaneSize(int lane_size_in_bits);
778 VectorFormat VectorFormatHalfWidthDoubleLanes(VectorFormat vform);
779 VectorFormat VectorFormatFillQ(VectorFormat vform);
780 VectorFormat ScalarFormatFromFormat(VectorFormat vform);
781 VectorFormat SVEFormatFromLaneSizeInBits(int lane_size_in_bits);
782 VectorFormat SVEFormatFromLaneSizeInBytes(int lane_size_in_bytes);
783 VectorFormat SVEFormatFromLaneSizeInBytesLog2(int lane_size_in_bytes_log_2);
784 unsigned RegisterSizeInBitsFromFormat(VectorFormat vform);
785 unsigned RegisterSizeInBytesFromFormat(VectorFormat vform);
786 bool IsSVEFormat(VectorFormat vform);
787 // TODO: Make the return types of these functions consistent.
788 unsigned LaneSizeInBitsFromFormat(VectorFormat vform);
789 int LaneSizeInBytesFromFormat(VectorFormat vform);
790 int LaneSizeInBytesLog2FromFormat(VectorFormat vform);
791 int LaneCountFromFormat(VectorFormat vform);
792 int MaxLaneCountFromFormat(VectorFormat vform);
793 bool IsVectorFormat(VectorFormat vform);
794 int64_t MaxIntFromFormat(VectorFormat vform);
795 int64_t MinIntFromFormat(VectorFormat vform);
796 uint64_t MaxUintFromFormat(VectorFormat vform);
797 
798 
799 // clang-format off
800 enum NEONFormat {
801   NF_UNDEF = 0,
802   NF_8B    = 1,
803   NF_16B   = 2,
804   NF_4H    = 3,
805   NF_8H    = 4,
806   NF_2S    = 5,
807   NF_4S    = 6,
808   NF_1D    = 7,
809   NF_2D    = 8,
810   NF_B     = 9,
811   NF_H     = 10,
812   NF_S     = 11,
813   NF_D     = 12
814 };
815 // clang-format on
816 
817 static const unsigned kNEONFormatMaxBits = 6;
818 
819 struct NEONFormatMap {
820   // The bit positions in the instruction to consider.
821   uint8_t bits[kNEONFormatMaxBits];
822 
823   // Mapping from concatenated bits to format.
824   NEONFormat map[1 << kNEONFormatMaxBits];
825 };
826 
827 class NEONFormatDecoder {
828  public:
829   enum SubstitutionMode { kPlaceholder, kFormat };
830 
831   // Construct a format decoder with increasingly specific format maps for each
832   // substitution. If no format map is specified, the default is the integer
833   // format map.
NEONFormatDecoder(const Instruction * instr)834   explicit NEONFormatDecoder(const Instruction* instr) {
835     instrbits_ = instr->GetInstructionBits();
836     SetFormatMaps(IntegerFormatMap());
837   }
NEONFormatDecoder(const Instruction * instr,const NEONFormatMap * format)838   NEONFormatDecoder(const Instruction* instr, const NEONFormatMap* format) {
839     instrbits_ = instr->GetInstructionBits();
840     SetFormatMaps(format);
841   }
NEONFormatDecoder(const Instruction * instr,const NEONFormatMap * format0,const NEONFormatMap * format1)842   NEONFormatDecoder(const Instruction* instr,
843                     const NEONFormatMap* format0,
844                     const NEONFormatMap* format1) {
845     instrbits_ = instr->GetInstructionBits();
846     SetFormatMaps(format0, format1);
847   }
NEONFormatDecoder(const Instruction * instr,const NEONFormatMap * format0,const NEONFormatMap * format1,const NEONFormatMap * format2)848   NEONFormatDecoder(const Instruction* instr,
849                     const NEONFormatMap* format0,
850                     const NEONFormatMap* format1,
851                     const NEONFormatMap* format2) {
852     instrbits_ = instr->GetInstructionBits();
853     SetFormatMaps(format0, format1, format2);
854   }
855 
856   // Set the format mapping for all or individual substitutions.
857   void SetFormatMaps(const NEONFormatMap* format0,
858                      const NEONFormatMap* format1 = NULL,
859                      const NEONFormatMap* format2 = NULL,
860                      const NEONFormatMap* format3 = NULL) {
861     VIXL_ASSERT(format0 != NULL);
862     formats_[0] = format0;
863     formats_[1] = (format1 == NULL) ? formats_[0] : format1;
864     formats_[2] = (format2 == NULL) ? formats_[1] : format2;
865     formats_[3] = (format3 == NULL) ? formats_[2] : format3;
866   }
SetFormatMap(unsigned index,const NEONFormatMap * format)867   void SetFormatMap(unsigned index, const NEONFormatMap* format) {
868     VIXL_ASSERT(index <= ArrayLength(formats_));
869     VIXL_ASSERT(format != NULL);
870     formats_[index] = format;
871   }
872 
873   // Substitute %s in the input string with the placeholder string for each
874   // register, ie. "'B", "'H", etc.
SubstitutePlaceholders(const char * string)875   const char* SubstitutePlaceholders(const char* string) {
876     return Substitute(string, kPlaceholder, kPlaceholder, kPlaceholder);
877   }
878 
879   // Substitute %s in the input string with a new string based on the
880   // substitution mode.
881   const char* Substitute(const char* string,
882                          SubstitutionMode mode0 = kFormat,
883                          SubstitutionMode mode1 = kFormat,
884                          SubstitutionMode mode2 = kFormat,
885                          SubstitutionMode mode3 = kFormat) {
886     const char* subst0 = GetSubstitute(0, mode0);
887     const char* subst1 = GetSubstitute(1, mode1);
888     const char* subst2 = GetSubstitute(2, mode2);
889     const char* subst3 = GetSubstitute(3, mode3);
890 
891     if ((subst0 == NULL) || (subst1 == NULL) || (subst2 == NULL) ||
892         (subst3 == NULL)) {
893       return NULL;
894     }
895 
896     snprintf(form_buffer_,
897              sizeof(form_buffer_),
898              string,
899              subst0,
900              subst1,
901              subst2,
902              subst3);
903     return form_buffer_;
904   }
905 
906   // Append a "2" to a mnemonic string based on the state of the Q bit.
Mnemonic(const char * mnemonic)907   const char* Mnemonic(const char* mnemonic) {
908     if ((mnemonic != NULL) && (instrbits_ & NEON_Q) != 0) {
909       snprintf(mne_buffer_, sizeof(mne_buffer_), "%s2", mnemonic);
910       return mne_buffer_;
911     }
912     return mnemonic;
913   }
914 
915   VectorFormat GetVectorFormat(int format_index = 0) {
916     return GetVectorFormat(formats_[format_index]);
917   }
918 
GetVectorFormat(const NEONFormatMap * format_map)919   VectorFormat GetVectorFormat(const NEONFormatMap* format_map) {
920     static const VectorFormat vform[] = {kFormatUndefined,
921                                          kFormat8B,
922                                          kFormat16B,
923                                          kFormat4H,
924                                          kFormat8H,
925                                          kFormat2S,
926                                          kFormat4S,
927                                          kFormat1D,
928                                          kFormat2D,
929                                          kFormatB,
930                                          kFormatH,
931                                          kFormatS,
932                                          kFormatD};
933     VIXL_ASSERT(GetNEONFormat(format_map) < ArrayLength(vform));
934     return vform[GetNEONFormat(format_map)];
935   }
936 
937   // Built in mappings for common cases.
938 
939   // The integer format map uses three bits (Q, size<1:0>) to encode the
940   // "standard" set of NEON integer vector formats.
IntegerFormatMap()941   static const NEONFormatMap* IntegerFormatMap() {
942     static const NEONFormatMap map =
943         {{23, 22, 30},
944          {NF_8B, NF_16B, NF_4H, NF_8H, NF_2S, NF_4S, NF_UNDEF, NF_2D}};
945     return &map;
946   }
947 
948   // The long integer format map uses two bits (size<1:0>) to encode the
949   // long set of NEON integer vector formats. These are used in narrow, wide
950   // and long operations.
LongIntegerFormatMap()951   static const NEONFormatMap* LongIntegerFormatMap() {
952     static const NEONFormatMap map = {{23, 22}, {NF_8H, NF_4S, NF_2D}};
953     return &map;
954   }
955 
956   // The FP format map uses two bits (Q, size<0>) to encode the NEON FP vector
957   // formats: NF_2S, NF_4S, NF_2D.
FPFormatMap()958   static const NEONFormatMap* FPFormatMap() {
959     // The FP format map assumes two bits (Q, size<0>) are used to encode the
960     // NEON FP vector formats: NF_2S, NF_4S, NF_2D.
961     static const NEONFormatMap map = {{22, 30},
962                                       {NF_2S, NF_4S, NF_UNDEF, NF_2D}};
963     return &map;
964   }
965 
966   // The FP16 format map uses one bit (Q) to encode the NEON vector format:
967   // NF_4H, NF_8H.
FP16FormatMap()968   static const NEONFormatMap* FP16FormatMap() {
969     static const NEONFormatMap map = {{30}, {NF_4H, NF_8H}};
970     return &map;
971   }
972 
973   // The load/store format map uses three bits (Q, 11, 10) to encode the
974   // set of NEON vector formats.
LoadStoreFormatMap()975   static const NEONFormatMap* LoadStoreFormatMap() {
976     static const NEONFormatMap map =
977         {{11, 10, 30},
978          {NF_8B, NF_16B, NF_4H, NF_8H, NF_2S, NF_4S, NF_1D, NF_2D}};
979     return &map;
980   }
981 
982   // The logical format map uses one bit (Q) to encode the NEON vector format:
983   // NF_8B, NF_16B.
LogicalFormatMap()984   static const NEONFormatMap* LogicalFormatMap() {
985     static const NEONFormatMap map = {{30}, {NF_8B, NF_16B}};
986     return &map;
987   }
988 
989   // The triangular format map uses between two and five bits to encode the NEON
990   // vector format:
991   // xxx10->8B, xxx11->16B, xx100->4H, xx101->8H
992   // x1000->2S, x1001->4S,  10001->2D, all others undefined.
TriangularFormatMap()993   static const NEONFormatMap* TriangularFormatMap() {
994     static const NEONFormatMap map =
995         {{19, 18, 17, 16, 30},
996          {NF_UNDEF, NF_UNDEF, NF_8B, NF_16B, NF_4H, NF_8H, NF_8B, NF_16B,
997           NF_2S,    NF_4S,    NF_8B, NF_16B, NF_4H, NF_8H, NF_8B, NF_16B,
998           NF_UNDEF, NF_2D,    NF_8B, NF_16B, NF_4H, NF_8H, NF_8B, NF_16B,
999           NF_2S,    NF_4S,    NF_8B, NF_16B, NF_4H, NF_8H, NF_8B, NF_16B}};
1000     return &map;
1001   }
1002 
1003   // The shift immediate map uses between two and five bits to encode the NEON
1004   // vector format:
1005   // 00010->8B, 00011->16B, 001x0->4H, 001x1->8H,
1006   // 01xx0->2S, 01xx1->4S, 1xxx1->2D, all others undefined.
ShiftImmFormatMap()1007   static const NEONFormatMap* ShiftImmFormatMap() {
1008     static const NEONFormatMap map = {{22, 21, 20, 19, 30},
1009                                       {NF_UNDEF, NF_UNDEF, NF_8B,    NF_16B,
1010                                        NF_4H,    NF_8H,    NF_4H,    NF_8H,
1011                                        NF_2S,    NF_4S,    NF_2S,    NF_4S,
1012                                        NF_2S,    NF_4S,    NF_2S,    NF_4S,
1013                                        NF_UNDEF, NF_2D,    NF_UNDEF, NF_2D,
1014                                        NF_UNDEF, NF_2D,    NF_UNDEF, NF_2D,
1015                                        NF_UNDEF, NF_2D,    NF_UNDEF, NF_2D,
1016                                        NF_UNDEF, NF_2D,    NF_UNDEF, NF_2D}};
1017     return &map;
1018   }
1019 
1020   // The shift long/narrow immediate map uses between two and four bits to
1021   // encode the NEON vector format:
1022   // 0001->8H, 001x->4S, 01xx->2D, all others undefined.
ShiftLongNarrowImmFormatMap()1023   static const NEONFormatMap* ShiftLongNarrowImmFormatMap() {
1024     static const NEONFormatMap map =
1025         {{22, 21, 20, 19},
1026          {NF_UNDEF, NF_8H, NF_4S, NF_4S, NF_2D, NF_2D, NF_2D, NF_2D}};
1027     return &map;
1028   }
1029 
1030   // The scalar format map uses two bits (size<1:0>) to encode the NEON scalar
1031   // formats: NF_B, NF_H, NF_S, NF_D.
ScalarFormatMap()1032   static const NEONFormatMap* ScalarFormatMap() {
1033     static const NEONFormatMap map = {{23, 22}, {NF_B, NF_H, NF_S, NF_D}};
1034     return &map;
1035   }
1036 
1037   // The long scalar format map uses two bits (size<1:0>) to encode the longer
1038   // NEON scalar formats: NF_H, NF_S, NF_D.
LongScalarFormatMap()1039   static const NEONFormatMap* LongScalarFormatMap() {
1040     static const NEONFormatMap map = {{23, 22}, {NF_H, NF_S, NF_D}};
1041     return &map;
1042   }
1043 
1044   // The FP scalar format map assumes one bit (size<0>) is used to encode the
1045   // NEON FP scalar formats: NF_S, NF_D.
FPScalarFormatMap()1046   static const NEONFormatMap* FPScalarFormatMap() {
1047     static const NEONFormatMap map = {{22}, {NF_S, NF_D}};
1048     return &map;
1049   }
1050 
1051   // The FP scalar pairwise format map assumes two bits (U, size<0>) are used to
1052   // encode the NEON FP scalar formats: NF_H, NF_S, NF_D.
FPScalarPairwiseFormatMap()1053   static const NEONFormatMap* FPScalarPairwiseFormatMap() {
1054     static const NEONFormatMap map = {{29, 22}, {NF_H, NF_UNDEF, NF_S, NF_D}};
1055     return &map;
1056   }
1057 
1058   // The triangular scalar format map uses between one and four bits to encode
1059   // the NEON FP scalar formats:
1060   // xxx1->B, xx10->H, x100->S, 1000->D, all others undefined.
TriangularScalarFormatMap()1061   static const NEONFormatMap* TriangularScalarFormatMap() {
1062     static const NEONFormatMap map = {{19, 18, 17, 16},
1063                                       {NF_UNDEF,
1064                                        NF_B,
1065                                        NF_H,
1066                                        NF_B,
1067                                        NF_S,
1068                                        NF_B,
1069                                        NF_H,
1070                                        NF_B,
1071                                        NF_D,
1072                                        NF_B,
1073                                        NF_H,
1074                                        NF_B,
1075                                        NF_S,
1076                                        NF_B,
1077                                        NF_H,
1078                                        NF_B}};
1079     return &map;
1080   }
1081 
1082  private:
1083   // Get a pointer to a string that represents the format or placeholder for
1084   // the specified substitution index, based on the format map and instruction.
GetSubstitute(int index,SubstitutionMode mode)1085   const char* GetSubstitute(int index, SubstitutionMode mode) {
1086     if (mode == kFormat) {
1087       return NEONFormatAsString(GetNEONFormat(formats_[index]));
1088     }
1089     VIXL_ASSERT(mode == kPlaceholder);
1090     return NEONFormatAsPlaceholder(GetNEONFormat(formats_[index]));
1091   }
1092 
1093   // Get the NEONFormat enumerated value for bits obtained from the
1094   // instruction based on the specified format mapping.
GetNEONFormat(const NEONFormatMap * format_map)1095   NEONFormat GetNEONFormat(const NEONFormatMap* format_map) {
1096     return format_map->map[PickBits(format_map->bits)];
1097   }
1098 
1099   // Convert a NEONFormat into a string.
NEONFormatAsString(NEONFormat format)1100   static const char* NEONFormatAsString(NEONFormat format) {
1101     // clang-format off
1102     static const char* formats[] = {
1103       NULL,
1104       "8b", "16b", "4h", "8h", "2s", "4s", "1d", "2d",
1105       "b", "h", "s", "d"
1106     };
1107     // clang-format on
1108     VIXL_ASSERT(format < ArrayLength(formats));
1109     return formats[format];
1110   }
1111 
1112   // Convert a NEONFormat into a register placeholder string.
NEONFormatAsPlaceholder(NEONFormat format)1113   static const char* NEONFormatAsPlaceholder(NEONFormat format) {
1114     VIXL_ASSERT((format == NF_B) || (format == NF_H) || (format == NF_S) ||
1115                 (format == NF_D) || (format == NF_UNDEF));
1116     // clang-format off
1117     static const char* formats[] = {
1118       NULL,
1119       NULL, NULL, NULL, NULL,
1120       NULL, NULL, NULL, NULL,
1121       "'B", "'H", "'S", "'D"
1122     };
1123     // clang-format on
1124     return formats[format];
1125   }
1126 
1127   // Select bits from instrbits_ defined by the bits array, concatenate them,
1128   // and return the value.
PickBits(const uint8_t bits[])1129   uint8_t PickBits(const uint8_t bits[]) {
1130     uint8_t result = 0;
1131     for (unsigned b = 0; b < kNEONFormatMaxBits; b++) {
1132       if (bits[b] == 0) break;
1133       result <<= 1;
1134       result |= ((instrbits_ & (1 << bits[b])) == 0) ? 0 : 1;
1135     }
1136     return result;
1137   }
1138 
1139   Instr instrbits_;
1140   const NEONFormatMap* formats_[4];
1141   char form_buffer_[64];
1142   char mne_buffer_[16];
1143 };
1144 }  // namespace aarch64
1145 }  // namespace vixl
1146 
1147 #endif  // VIXL_AARCH64_INSTRUCTIONS_AARCH64_H_
1148