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   // An artificial value, used by simulator trace tests and a few oddball
221   // instructions (such as FMLAL).
222   kFormat2H = 0xfffffffe
223 };
224 
225 // Instructions. ---------------------------------------------------------------
226 
227 class Instruction {
228  public:
GetInstructionBits() const229   Instr GetInstructionBits() const {
230     return *(reinterpret_cast<const Instr*>(this));
231   }
232   VIXL_DEPRECATED("GetInstructionBits", Instr InstructionBits() const) {
233     return GetInstructionBits();
234   }
235 
SetInstructionBits(Instr new_instr)236   void SetInstructionBits(Instr new_instr) {
237     *(reinterpret_cast<Instr*>(this)) = new_instr;
238   }
239 
ExtractBit(int pos) const240   int ExtractBit(int pos) const { return (GetInstructionBits() >> pos) & 1; }
241   VIXL_DEPRECATED("ExtractBit", int Bit(int pos) const) {
242     return ExtractBit(pos);
243   }
244 
ExtractBits(int msb, int lsb) const245   uint32_t ExtractBits(int msb, int lsb) const {
246     return ExtractUnsignedBitfield32(msb, lsb, GetInstructionBits());
247   }
248   VIXL_DEPRECATED("ExtractBits", uint32_t Bits(int msb, int lsb) const) {
249     return ExtractBits(msb, lsb);
250   }
251 
252   // Compress bit extraction operation from Hacker's Delight.
253   // https://github.com/hcs0/Hackers-Delight/blob/master/compress.c.txt
Compress(uint32_t mask) const254   uint32_t Compress(uint32_t mask) const {
255     uint32_t mk, mp, mv, t;
256     uint32_t x = GetInstructionBits() & mask;  // Clear irrelevant bits.
257     mk = ~mask << 1;                           // We will count 0's to right.
258     for (int i = 0; i < 5; i++) {
259       mp = mk ^ (mk << 1);  // Parallel suffix.
260       mp = mp ^ (mp << 2);
261       mp = mp ^ (mp << 4);
262       mp = mp ^ (mp << 8);
263       mp = mp ^ (mp << 16);
264       mv = mp & mask;                         // Bits to move.
265       mask = (mask ^ mv) | (mv >> (1 << i));  // Compress mask.
266       t = x & mv;
267       x = (x ^ t) | (t >> (1 << i));  // Compress x.
268       mk = mk & ~mp;
269     }
270     return x;
271   }
272 
273   template <uint32_t M>
ExtractBits() const274   uint32_t ExtractBits() const {
275     return Compress(M);
276   }
277 
ExtractBitsAbsent() const278   uint32_t ExtractBitsAbsent() const {
279     VIXL_UNREACHABLE();
280     return 0;
281   }
282 
283   template <uint32_t M, uint32_t V>
IsMaskedValue() const284   uint32_t IsMaskedValue() const {
285     return (Mask(M) == V) ? 1 : 0;
286   }
287 
IsMaskedValueAbsent() const288   uint32_t IsMaskedValueAbsent() const {
289     VIXL_UNREACHABLE();
290     return 0;
291   }
292 
ExtractSignedBits(int msb, int lsb) const293   int32_t ExtractSignedBits(int msb, int lsb) const {
294     int32_t bits = *(reinterpret_cast<const int32_t*>(this));
295     return ExtractSignedBitfield32(msb, lsb, bits);
296   }
297   VIXL_DEPRECATED("ExtractSignedBits",
298                   int32_t SignedBits(int msb, int lsb) const) {
299     return ExtractSignedBits(msb, lsb);
300   }
301 
Mask(uint32_t mask) const302   Instr Mask(uint32_t mask) const {
303     VIXL_ASSERT(mask != 0);
304     return GetInstructionBits() & mask;
305   }
306 
307 #define DEFINE_GETTER(Name, HighBit, LowBit, Func)                  \
308   int32_t Get##Name() const { return this->Func(HighBit, LowBit); } \
309   VIXL_DEPRECATED("Get" #Name, int32_t Name() const) { return Get##Name(); }
310   INSTRUCTION_FIELDS_LIST(DEFINE_GETTER)
311 #undef DEFINE_GETTER
312 
313   template <int msb, int lsb>
GetRx() const314   int32_t GetRx() const {
315     // We don't have any register fields wider than five bits, so the result
316     // will always fit into an int32_t.
317     VIXL_ASSERT((msb - lsb + 1) <= 5);
318     return this->ExtractBits(msb, lsb);
319   }
320 
GetSVEVectorFormat(int field_lsb = 22) const321   VectorFormat GetSVEVectorFormat(int field_lsb = 22) const {
322     VIXL_ASSERT((field_lsb >= 0) && (field_lsb <= 30));
323     uint32_t instr = ExtractUnsignedBitfield32(field_lsb + 1,
324                                                field_lsb,
325                                                GetInstructionBits())
326                      << 22;
327     switch (instr & SVESizeFieldMask) {
328       case SVE_B:
329         return kFormatVnB;
330       case SVE_H:
331         return kFormatVnH;
332       case SVE_S:
333         return kFormatVnS;
334       case SVE_D:
335         return kFormatVnD;
336     }
337     VIXL_UNREACHABLE();
338     return kFormatUndefined;
339   }
340 
341   // ImmPCRel is a compound field (not present in INSTRUCTION_FIELDS_LIST),
342   // formed from ImmPCRelLo and ImmPCRelHi.
GetImmPCRel() const343   int GetImmPCRel() const {
344     uint32_t hi = static_cast<uint32_t>(GetImmPCRelHi());
345     uint32_t lo = GetImmPCRelLo();
346     uint32_t offset = (hi << ImmPCRelLo_width) | lo;
347     int width = ImmPCRelLo_width + ImmPCRelHi_width;
348     return ExtractSignedBitfield32(width - 1, 0, offset);
349   }
350   VIXL_DEPRECATED("GetImmPCRel", int ImmPCRel() const) { return GetImmPCRel(); }
351 
352   // ImmLSPAC is a compound field (not present in INSTRUCTION_FIELDS_LIST),
353   // formed from ImmLSPACLo and ImmLSPACHi.
GetImmLSPAC() const354   int GetImmLSPAC() const {
355     uint32_t hi = static_cast<uint32_t>(GetImmLSPACHi());
356     uint32_t lo = GetImmLSPACLo();
357     uint32_t offset = (hi << ImmLSPACLo_width) | lo;
358     int width = ImmLSPACLo_width + ImmLSPACHi_width;
359     return ExtractSignedBitfield32(width - 1, 0, offset) << 3;
360   }
361 
362   uint64_t GetImmLogical() const;
363   VIXL_DEPRECATED("GetImmLogical", uint64_t ImmLogical() const) {
364     return GetImmLogical();
365   }
366   uint64_t GetSVEImmLogical() const;
367   int GetSVEBitwiseImmLaneSizeInBytesLog2() const;
368   uint64_t DecodeImmBitMask(int32_t n,
369                             int32_t imm_s,
370                             int32_t imm_r,
371                             int32_t size) const;
372 
373   std::pair<int, int> GetSVEPermuteIndexAndLaneSizeLog2() const;
374 
375   std::pair<int, int> GetSVEMulZmAndIndex() const;
376   std::pair<int, int> GetSVEMulLongZmAndIndex() const;
377 
378   std::pair<int, int> GetSVEImmShiftAndLaneSizeLog2(bool is_predicated) const;
379 
380   int GetSVEExtractImmediate() const;
381 
382   int GetSVEMsizeFromDtype(bool is_signed, int dtype_h_lsb = 23) const;
383 
384   int GetSVEEsizeFromDtype(bool is_signed, int dtype_l_lsb = 21) const;
385 
386 
387   unsigned GetImmNEONabcdefgh() const;
388   VIXL_DEPRECATED("GetImmNEONabcdefgh", unsigned ImmNEONabcdefgh() const) {
389     return GetImmNEONabcdefgh();
390   }
391 
392   Float16 GetImmFP16() const;
393 
394   float GetImmFP32() const;
395   VIXL_DEPRECATED("GetImmFP32", float ImmFP32() const) { return GetImmFP32(); }
396 
397   double GetImmFP64() const;
398   VIXL_DEPRECATED("GetImmFP64", double ImmFP64() const) { return GetImmFP64(); }
399 
400   Float16 GetImmNEONFP16() const;
401 
402   float GetImmNEONFP32() const;
403   VIXL_DEPRECATED("GetImmNEONFP32", float ImmNEONFP32() const) {
404     return GetImmNEONFP32();
405   }
406 
407   double GetImmNEONFP64() const;
408   VIXL_DEPRECATED("GetImmNEONFP64", double ImmNEONFP64() const) {
409     return GetImmNEONFP64();
410   }
411 
GetSVEImmFP16() const412   Float16 GetSVEImmFP16() const { return Imm8ToFloat16(ExtractBits(12, 5)); }
413 
GetSVEImmFP32() const414   float GetSVEImmFP32() const { return Imm8ToFP32(ExtractBits(12, 5)); }
415 
GetSVEImmFP64() const416   double GetSVEImmFP64() const { return Imm8ToFP64(ExtractBits(12, 5)); }
417 
418   static Float16 Imm8ToFloat16(uint32_t imm8);
419   static float Imm8ToFP32(uint32_t imm8);
420   static double Imm8ToFP64(uint32_t imm8);
421 
GetSizeLS() const422   unsigned GetSizeLS() const {
423     return CalcLSDataSize(static_cast<LoadStoreOp>(Mask(LoadStoreMask)));
424   }
425   VIXL_DEPRECATED("GetSizeLS", unsigned SizeLS() const) { return GetSizeLS(); }
426 
GetSizeLSPair() const427   unsigned GetSizeLSPair() const {
428     return CalcLSPairDataSize(
429         static_cast<LoadStorePairOp>(Mask(LoadStorePairMask)));
430   }
431   VIXL_DEPRECATED("GetSizeLSPair", unsigned SizeLSPair() const) {
432     return GetSizeLSPair();
433   }
434 
GetNEONLSIndex(int access_size_shift) const435   int GetNEONLSIndex(int access_size_shift) const {
436     int64_t q = GetNEONQ();
437     int64_t s = GetNEONS();
438     int64_t size = GetNEONLSSize();
439     int64_t index = (q << 3) | (s << 2) | size;
440     return static_cast<int>(index >> access_size_shift);
441   }
442   VIXL_DEPRECATED("GetNEONLSIndex",
443                   int NEONLSIndex(int access_size_shift) const) {
444     return GetNEONLSIndex(access_size_shift);
445   }
446 
447   // Helpers.
IsCondBranchImm() const448   bool IsCondBranchImm() const {
449     return Mask(ConditionalBranchFMask) == ConditionalBranchFixed;
450   }
451 
IsUncondBranchImm() const452   bool IsUncondBranchImm() const {
453     return Mask(UnconditionalBranchFMask) == UnconditionalBranchFixed;
454   }
455 
IsCompareBranch() const456   bool IsCompareBranch() const {
457     return Mask(CompareBranchFMask) == CompareBranchFixed;
458   }
459 
IsTestBranch() const460   bool IsTestBranch() const { return Mask(TestBranchFMask) == TestBranchFixed; }
461 
IsImmBranch() const462   bool IsImmBranch() const { return GetBranchType() != UnknownBranchType; }
463 
IsPCRelAddressing() const464   bool IsPCRelAddressing() const {
465     return Mask(PCRelAddressingFMask) == PCRelAddressingFixed;
466   }
467 
IsLogicalImmediate() const468   bool IsLogicalImmediate() const {
469     return Mask(LogicalImmediateFMask) == LogicalImmediateFixed;
470   }
471 
IsAddSubImmediate() const472   bool IsAddSubImmediate() const {
473     return Mask(AddSubImmediateFMask) == AddSubImmediateFixed;
474   }
475 
IsAddSubExtended() const476   bool IsAddSubExtended() const {
477     return Mask(AddSubExtendedFMask) == AddSubExtendedFixed;
478   }
479 
IsLoadOrStore() const480   bool IsLoadOrStore() const {
481     return Mask(LoadStoreAnyFMask) == LoadStoreAnyFixed;
482   }
483 
484   // True if `this` is valid immediately after the provided movprfx instruction.
485   bool CanTakeSVEMovprfx(uint32_t form_hash, Instruction const* movprfx) const;
486   bool CanTakeSVEMovprfx(const char* form, Instruction const* movprfx) const;
487 
488   bool IsLoad() const;
489   bool IsStore() const;
490 
IsLoadLiteral() const491   bool IsLoadLiteral() const {
492     // This includes PRFM_lit.
493     return Mask(LoadLiteralFMask) == LoadLiteralFixed;
494   }
495 
IsMovn() const496   bool IsMovn() const {
497     return (Mask(MoveWideImmediateMask) == MOVN_x) ||
498            (Mask(MoveWideImmediateMask) == MOVN_w);
499   }
500 
IsException() const501   bool IsException() const { return Mask(ExceptionFMask) == ExceptionFixed; }
502 
IsPAuth() const503   bool IsPAuth() const { return Mask(SystemPAuthFMask) == SystemPAuthFixed; }
504 
IsBti() const505   bool IsBti() const {
506     if (Mask(SystemHintFMask) == SystemHintFixed) {
507       int imm_hint = GetImmHint();
508       switch (imm_hint) {
509         case BTI:
510         case BTI_c:
511         case BTI_j:
512         case BTI_jc:
513           return true;
514       }
515     }
516     return false;
517   }
518 
IsMOPSPrologueOf(const Instruction* instr, uint32_t mops_type) const519   bool IsMOPSPrologueOf(const Instruction* instr, uint32_t mops_type) const {
520     VIXL_ASSERT((mops_type == "set"_h) || (mops_type == "setg"_h) ||
521                 (mops_type == "cpy"_h));
522     const int op_lsb = (mops_type == "cpy"_h) ? 22 : 14;
523     return GetInstructionBits() == instr->Mask(~(0x3U << op_lsb));
524   }
525 
IsMOPSMainOf(const Instruction* instr, uint32_t mops_type) const526   bool IsMOPSMainOf(const Instruction* instr, uint32_t mops_type) const {
527     VIXL_ASSERT((mops_type == "set"_h) || (mops_type == "setg"_h) ||
528                 (mops_type == "cpy"_h));
529     const int op_lsb = (mops_type == "cpy"_h) ? 22 : 14;
530     return GetInstructionBits() ==
531            (instr->Mask(~(0x3U << op_lsb)) | (0x1 << op_lsb));
532   }
533 
IsMOPSEpilogueOf(const Instruction* instr, uint32_t mops_type) const534   bool IsMOPSEpilogueOf(const Instruction* instr, uint32_t mops_type) const {
535     VIXL_ASSERT((mops_type == "set"_h) || (mops_type == "setg"_h) ||
536                 (mops_type == "cpy"_h));
537     const int op_lsb = (mops_type == "cpy"_h) ? 22 : 14;
538     return GetInstructionBits() ==
539            (instr->Mask(~(0x3U << op_lsb)) | (0x2 << op_lsb));
540   }
541 
542   template <uint32_t mops_type>
IsConsistentMOPSTriplet() const543   bool IsConsistentMOPSTriplet() const {
544     VIXL_STATIC_ASSERT((mops_type == "set"_h) || (mops_type == "setg"_h) ||
545                        (mops_type == "cpy"_h));
546 
547     int64_t isize = static_cast<int64_t>(kInstructionSize);
548     const Instruction* prev2 = GetInstructionAtOffset(-2 * isize);
549     const Instruction* prev1 = GetInstructionAtOffset(-1 * isize);
550     const Instruction* next1 = GetInstructionAtOffset(1 * isize);
551     const Instruction* next2 = GetInstructionAtOffset(2 * isize);
552 
553     // Use the encoding of the current instruction to determine the expected
554     // adjacent instructions. NB. this doesn't check if the nearby instructions
555     // are MOPS-type, but checks that they form a consistent triplet if they
556     // are. For example, 'mov x0, #0; mov x0, #512; mov x0, #1024' is a
557     // consistent triplet, but they are not MOPS instructions.
558     const int op_lsb = (mops_type == "cpy"_h) ? 22 : 14;
559     const uint32_t kMOPSOpfield = 0x3 << op_lsb;
560     const uint32_t kMOPSPrologue = 0;
561     const uint32_t kMOPSMain = 0x1 << op_lsb;
562     const uint32_t kMOPSEpilogue = 0x2 << op_lsb;
563     switch (Mask(kMOPSOpfield)) {
564       case kMOPSPrologue:
565         return next1->IsMOPSMainOf(this, mops_type) &&
566                next2->IsMOPSEpilogueOf(this, mops_type);
567       case kMOPSMain:
568         return prev1->IsMOPSPrologueOf(this, mops_type) &&
569                next1->IsMOPSEpilogueOf(this, mops_type);
570       case kMOPSEpilogue:
571         return prev2->IsMOPSPrologueOf(this, mops_type) &&
572                prev1->IsMOPSMainOf(this, mops_type);
573       default:
574         VIXL_ABORT_WITH_MSG("Undefined MOPS operation\n");
575     }
576   }
577 
578   static int GetImmBranchRangeBitwidth(ImmBranchType branch_type);
579   VIXL_DEPRECATED(
580       "GetImmBranchRangeBitwidth",
581       static int ImmBranchRangeBitwidth(ImmBranchType branch_type)) {
582     return GetImmBranchRangeBitwidth(branch_type);
583   }
584 
585   static int32_t GetImmBranchForwardRange(ImmBranchType branch_type);
586   VIXL_DEPRECATED(
587       "GetImmBranchForwardRange",
588       static int32_t ImmBranchForwardRange(ImmBranchType branch_type)) {
589     return GetImmBranchForwardRange(branch_type);
590   }
591 
592   static bool IsValidImmPCOffset(ImmBranchType branch_type, int64_t offset);
593 
594   // Indicate whether Rd can be the stack pointer or the zero register. This
595   // does not check that the instruction actually has an Rd field.
GetRdMode() const596   Reg31Mode GetRdMode() const {
597     // The following instructions use sp or wsp as Rd:
598     //  Add/sub (immediate) when not setting the flags.
599     //  Add/sub (extended) when not setting the flags.
600     //  Logical (immediate) when not setting the flags.
601     // Otherwise, r31 is the zero register.
602     if (IsAddSubImmediate() || IsAddSubExtended()) {
603       if (Mask(AddSubSetFlagsBit)) {
604         return Reg31IsZeroRegister;
605       } else {
606         return Reg31IsStackPointer;
607       }
608     }
609     if (IsLogicalImmediate()) {
610       // Of the logical (immediate) instructions, only ANDS (and its aliases)
611       // can set the flags. The others can all write into sp.
612       // Note that some logical operations are not available to
613       // immediate-operand instructions, so we have to combine two masks here.
614       if (Mask(LogicalImmediateMask & LogicalOpMask) == ANDS) {
615         return Reg31IsZeroRegister;
616       } else {
617         return Reg31IsStackPointer;
618       }
619     }
620     return Reg31IsZeroRegister;
621   }
622   VIXL_DEPRECATED("GetRdMode", Reg31Mode RdMode() const) { return GetRdMode(); }
623 
624   // Indicate whether Rn can be the stack pointer or the zero register. This
625   // does not check that the instruction actually has an Rn field.
GetRnMode() const626   Reg31Mode GetRnMode() const {
627     // The following instructions use sp or wsp as Rn:
628     //  All loads and stores.
629     //  Add/sub (immediate).
630     //  Add/sub (extended).
631     // Otherwise, r31 is the zero register.
632     if (IsLoadOrStore() || IsAddSubImmediate() || IsAddSubExtended()) {
633       return Reg31IsStackPointer;
634     }
635     return Reg31IsZeroRegister;
636   }
637   VIXL_DEPRECATED("GetRnMode", Reg31Mode RnMode() const) { return GetRnMode(); }
638 
GetBranchType() const639   ImmBranchType GetBranchType() const {
640     if (IsCondBranchImm()) {
641       return CondBranchType;
642     } else if (IsUncondBranchImm()) {
643       return UncondBranchType;
644     } else if (IsCompareBranch()) {
645       return CompareBranchType;
646     } else if (IsTestBranch()) {
647       return TestBranchType;
648     } else {
649       return UnknownBranchType;
650     }
651   }
652   VIXL_DEPRECATED("GetBranchType", ImmBranchType BranchType() const) {
653     return GetBranchType();
654   }
655 
656   // Find the target of this instruction. 'this' may be a branch or a
657   // PC-relative addressing instruction.
658   const Instruction* GetImmPCOffsetTarget() const;
659   VIXL_DEPRECATED("GetImmPCOffsetTarget",
660                   const Instruction* ImmPCOffsetTarget() const) {
661     return GetImmPCOffsetTarget();
662   }
663 
664   // Patch a PC-relative offset to refer to 'target'. 'this' may be a branch or
665   // a PC-relative addressing instruction.
666   void SetImmPCOffsetTarget(const Instruction* target);
667   // Patch a literal load instruction to load from 'source'.
668   void SetImmLLiteral(const Instruction* source);
669 
670   // The range of a load literal instruction, expressed as 'instr +- range'.
671   // The range is actually the 'positive' range; the branch instruction can
672   // target [instr - range - kInstructionSize, instr + range].
673   static const int kLoadLiteralImmBitwidth = 19;
674   static const int kLoadLiteralRange =
675       (1 << kLoadLiteralImmBitwidth) / 2 - kInstructionSize;
676 
677   // Calculate the address of a literal referred to by a load-literal
678   // instruction, and return it as the specified type.
679   //
680   // The literal itself is safely mutable only if the backing buffer is safely
681   // mutable.
682   template <typename T>
GetLiteralAddress() const683   T GetLiteralAddress() const {
684     uint64_t base_raw = reinterpret_cast<uint64_t>(this);
685     int64_t offset = GetImmLLiteral() * static_cast<int>(kLiteralEntrySize);
686     uint64_t address_raw = base_raw + offset;
687 
688     // Cast the address using a C-style cast. A reinterpret_cast would be
689     // appropriate, but it can't cast one integral type to another.
690     T address = (T)(address_raw);
691 
692     // Assert that the address can be represented by the specified type.
693     VIXL_ASSERT((uint64_t)(address) == address_raw);
694 
695     return address;
696   }
697   template <typename T>
698   VIXL_DEPRECATED("GetLiteralAddress", T LiteralAddress() const) {
699     return GetLiteralAddress<T>();
700   }
701 
GetLiteral32() const702   uint32_t GetLiteral32() const {
703     uint32_t literal;
704     memcpy(&literal, GetLiteralAddress<const void*>(), sizeof(literal));
705     return literal;
706   }
707   VIXL_DEPRECATED("GetLiteral32", uint32_t Literal32() const) {
708     return GetLiteral32();
709   }
710 
GetLiteral64() const711   uint64_t GetLiteral64() const {
712     uint64_t literal;
713     memcpy(&literal, GetLiteralAddress<const void*>(), sizeof(literal));
714     return literal;
715   }
716   VIXL_DEPRECATED("GetLiteral64", uint64_t Literal64() const) {
717     return GetLiteral64();
718   }
719 
GetLiteralFP32() const720   float GetLiteralFP32() const { return RawbitsToFloat(GetLiteral32()); }
721   VIXL_DEPRECATED("GetLiteralFP32", float LiteralFP32() const) {
722     return GetLiteralFP32();
723   }
724 
GetLiteralFP64() const725   double GetLiteralFP64() const { return RawbitsToDouble(GetLiteral64()); }
726   VIXL_DEPRECATED("GetLiteralFP64", double LiteralFP64() const) {
727     return GetLiteralFP64();
728   }
729 
GetNextInstruction()730   Instruction* GetNextInstruction() { return this + kInstructionSize; }
GetNextInstruction() const731   const Instruction* GetNextInstruction() const {
732     return this + kInstructionSize;
733   }
734   VIXL_DEPRECATED("GetNextInstruction",
735                   const Instruction* NextInstruction() const) {
736     return GetNextInstruction();
737   }
738 
GetInstructionAtOffset(int64_t offset) const739   const Instruction* GetInstructionAtOffset(int64_t offset) const {
740     VIXL_ASSERT(IsWordAligned(this + offset));
741     return this + offset;
742   }
743   VIXL_DEPRECATED("GetInstructionAtOffset",
744                   const Instruction* InstructionAtOffset(int64_t offset)
745                       const) {
746     return GetInstructionAtOffset(offset);
747   }
748 
749   template <typename T>
Cast(T src)750   static Instruction* Cast(T src) {
751     return reinterpret_cast<Instruction*>(src);
752   }
753 
754   template <typename T>
CastConst(T src)755   static const Instruction* CastConst(T src) {
756     return reinterpret_cast<const Instruction*>(src);
757   }
758 
759  private:
760   int GetImmBranch() const;
761 
762   void SetPCRelImmTarget(const Instruction* target);
763   void SetBranchImmTarget(const Instruction* target);
764 };
765 
766 
767 // Functions for handling NEON and SVE vector format information.
768 
769 const int kMaxLanesPerVector = 16;
770 
771 VectorFormat VectorFormatHalfWidth(VectorFormat vform);
772 VectorFormat VectorFormatDoubleWidth(VectorFormat vform);
773 VectorFormat VectorFormatDoubleLanes(VectorFormat vform);
774 VectorFormat VectorFormatHalfLanes(VectorFormat vform);
775 VectorFormat ScalarFormatFromLaneSize(int lane_size_in_bits);
776 VectorFormat VectorFormatHalfWidthDoubleLanes(VectorFormat vform);
777 VectorFormat VectorFormatFillQ(VectorFormat vform);
778 VectorFormat ScalarFormatFromFormat(VectorFormat vform);
779 VectorFormat SVEFormatFromLaneSizeInBits(int lane_size_in_bits);
780 VectorFormat SVEFormatFromLaneSizeInBytes(int lane_size_in_bytes);
781 VectorFormat SVEFormatFromLaneSizeInBytesLog2(int lane_size_in_bytes_log_2);
782 unsigned RegisterSizeInBitsFromFormat(VectorFormat vform);
783 unsigned RegisterSizeInBytesFromFormat(VectorFormat vform);
784 bool IsSVEFormat(VectorFormat vform);
785 // TODO: Make the return types of these functions consistent.
786 unsigned LaneSizeInBitsFromFormat(VectorFormat vform);
787 int LaneSizeInBytesFromFormat(VectorFormat vform);
788 int LaneSizeInBytesLog2FromFormat(VectorFormat vform);
789 int LaneCountFromFormat(VectorFormat vform);
790 int MaxLaneCountFromFormat(VectorFormat vform);
791 bool IsVectorFormat(VectorFormat vform);
792 int64_t MaxIntFromFormat(VectorFormat vform);
793 int64_t MinIntFromFormat(VectorFormat vform);
794 uint64_t MaxUintFromFormat(VectorFormat vform);
795 
796 
797 // clang-format off
798 enum NEONFormat {
799   NF_UNDEF = 0,
800   NF_8B    = 1,
801   NF_16B   = 2,
802   NF_4H    = 3,
803   NF_8H    = 4,
804   NF_2S    = 5,
805   NF_4S    = 6,
806   NF_1D    = 7,
807   NF_2D    = 8,
808   NF_B     = 9,
809   NF_H     = 10,
810   NF_S     = 11,
811   NF_D     = 12
812 };
813 // clang-format on
814 
815 static const unsigned kNEONFormatMaxBits = 6;
816 
817 struct NEONFormatMap {
818   // The bit positions in the instruction to consider.
819   uint8_t bits[kNEONFormatMaxBits];
820 
821   // Mapping from concatenated bits to format.
822   NEONFormat map[1 << kNEONFormatMaxBits];
823 };
824 
825 class NEONFormatDecoder {
826  public:
827   enum SubstitutionMode { kPlaceholder, kFormat };
828 
829   // Construct a format decoder with increasingly specific format maps for each
830   // substitution. If no format map is specified, the default is the integer
831   // format map.
NEONFormatDecoder(const Instruction* instr)832   explicit NEONFormatDecoder(const Instruction* instr) {
833     instrbits_ = instr->GetInstructionBits();
834     SetFormatMaps(IntegerFormatMap());
835   }
NEONFormatDecoder(const Instruction* instr, const NEONFormatMap* format)836   NEONFormatDecoder(const Instruction* instr, const NEONFormatMap* format) {
837     instrbits_ = instr->GetInstructionBits();
838     SetFormatMaps(format);
839   }
NEONFormatDecoder(const Instruction* instr, const NEONFormatMap* format0, const NEONFormatMap* format1)840   NEONFormatDecoder(const Instruction* instr,
841                     const NEONFormatMap* format0,
842                     const NEONFormatMap* format1) {
843     instrbits_ = instr->GetInstructionBits();
844     SetFormatMaps(format0, format1);
845   }
NEONFormatDecoder(const Instruction* instr, const NEONFormatMap* format0, const NEONFormatMap* format1, const NEONFormatMap* format2)846   NEONFormatDecoder(const Instruction* instr,
847                     const NEONFormatMap* format0,
848                     const NEONFormatMap* format1,
849                     const NEONFormatMap* format2) {
850     instrbits_ = instr->GetInstructionBits();
851     SetFormatMaps(format0, format1, format2);
852   }
853 
854   // Set the format mapping for all or individual substitutions.
SetFormatMaps(const NEONFormatMap* format0, const NEONFormatMap* format1 = NULL, const NEONFormatMap* format2 = NULL)855   void SetFormatMaps(const NEONFormatMap* format0,
856                      const NEONFormatMap* format1 = NULL,
857                      const NEONFormatMap* format2 = NULL) {
858     VIXL_ASSERT(format0 != NULL);
859     formats_[0] = format0;
860     formats_[1] = (format1 == NULL) ? formats_[0] : format1;
861     formats_[2] = (format2 == NULL) ? formats_[1] : format2;
862   }
SetFormatMap(unsigned index, const NEONFormatMap* format)863   void SetFormatMap(unsigned index, const NEONFormatMap* format) {
864     VIXL_ASSERT(index <= ArrayLength(formats_));
865     VIXL_ASSERT(format != NULL);
866     formats_[index] = format;
867   }
868 
869   // Substitute %s in the input string with the placeholder string for each
870   // register, ie. "'B", "'H", etc.
SubstitutePlaceholders(const char* string)871   const char* SubstitutePlaceholders(const char* string) {
872     return Substitute(string, kPlaceholder, kPlaceholder, kPlaceholder);
873   }
874 
875   // Substitute %s in the input string with a new string based on the
876   // substitution mode.
Substitute(const char* string, SubstitutionMode mode0 = kFormat, SubstitutionMode mode1 = kFormat, SubstitutionMode mode2 = kFormat)877   const char* Substitute(const char* string,
878                          SubstitutionMode mode0 = kFormat,
879                          SubstitutionMode mode1 = kFormat,
880                          SubstitutionMode mode2 = kFormat) {
881     const char* subst0 = GetSubstitute(0, mode0);
882     const char* subst1 = GetSubstitute(1, mode1);
883     const char* subst2 = GetSubstitute(2, mode2);
884 
885     if ((subst0 == NULL) || (subst1 == NULL) || (subst2 == NULL)) {
886       return NULL;
887     }
888 
889     snprintf(form_buffer_,
890              sizeof(form_buffer_),
891              string,
892              subst0,
893              subst1,
894              subst2);
895     return form_buffer_;
896   }
897 
898   // Append a "2" to a mnemonic string based on the state of the Q bit.
Mnemonic(const char* mnemonic)899   const char* Mnemonic(const char* mnemonic) {
900     if ((mnemonic != NULL) && (instrbits_ & NEON_Q) != 0) {
901       snprintf(mne_buffer_, sizeof(mne_buffer_), "%s2", mnemonic);
902       return mne_buffer_;
903     }
904     return mnemonic;
905   }
906 
GetVectorFormat(int format_index = 0)907   VectorFormat GetVectorFormat(int format_index = 0) {
908     return GetVectorFormat(formats_[format_index]);
909   }
910 
GetVectorFormat(const NEONFormatMap* format_map)911   VectorFormat GetVectorFormat(const NEONFormatMap* format_map) {
912     static const VectorFormat vform[] = {kFormatUndefined,
913                                          kFormat8B,
914                                          kFormat16B,
915                                          kFormat4H,
916                                          kFormat8H,
917                                          kFormat2S,
918                                          kFormat4S,
919                                          kFormat1D,
920                                          kFormat2D,
921                                          kFormatB,
922                                          kFormatH,
923                                          kFormatS,
924                                          kFormatD};
925     VIXL_ASSERT(GetNEONFormat(format_map) < ArrayLength(vform));
926     return vform[GetNEONFormat(format_map)];
927   }
928 
929   // Built in mappings for common cases.
930 
931   // The integer format map uses three bits (Q, size<1:0>) to encode the
932   // "standard" set of NEON integer vector formats.
IntegerFormatMap()933   static const NEONFormatMap* IntegerFormatMap() {
934     static const NEONFormatMap map =
935         {{23, 22, 30},
936          {NF_8B, NF_16B, NF_4H, NF_8H, NF_2S, NF_4S, NF_UNDEF, NF_2D}};
937     return &map;
938   }
939 
940   // The long integer format map uses two bits (size<1:0>) to encode the
941   // long set of NEON integer vector formats. These are used in narrow, wide
942   // and long operations.
LongIntegerFormatMap()943   static const NEONFormatMap* LongIntegerFormatMap() {
944     static const NEONFormatMap map = {{23, 22}, {NF_8H, NF_4S, NF_2D}};
945     return &map;
946   }
947 
948   // The FP format map uses two bits (Q, size<0>) to encode the NEON FP vector
949   // formats: NF_2S, NF_4S, NF_2D.
FPFormatMap()950   static const NEONFormatMap* FPFormatMap() {
951     // The FP format map assumes two bits (Q, size<0>) are used to encode the
952     // NEON FP vector formats: NF_2S, NF_4S, NF_2D.
953     static const NEONFormatMap map = {{22, 30},
954                                       {NF_2S, NF_4S, NF_UNDEF, NF_2D}};
955     return &map;
956   }
957 
958   // The FP16 format map uses one bit (Q) to encode the NEON vector format:
959   // NF_4H, NF_8H.
FP16FormatMap()960   static const NEONFormatMap* FP16FormatMap() {
961     static const NEONFormatMap map = {{30}, {NF_4H, NF_8H}};
962     return &map;
963   }
964 
965   // The load/store format map uses three bits (Q, 11, 10) to encode the
966   // set of NEON vector formats.
LoadStoreFormatMap()967   static const NEONFormatMap* LoadStoreFormatMap() {
968     static const NEONFormatMap map =
969         {{11, 10, 30},
970          {NF_8B, NF_16B, NF_4H, NF_8H, NF_2S, NF_4S, NF_1D, NF_2D}};
971     return &map;
972   }
973 
974   // The logical format map uses one bit (Q) to encode the NEON vector format:
975   // NF_8B, NF_16B.
LogicalFormatMap()976   static const NEONFormatMap* LogicalFormatMap() {
977     static const NEONFormatMap map = {{30}, {NF_8B, NF_16B}};
978     return &map;
979   }
980 
981   // The triangular format map uses between two and five bits to encode the NEON
982   // vector format:
983   // xxx10->8B, xxx11->16B, xx100->4H, xx101->8H
984   // x1000->2S, x1001->4S,  10001->2D, all others undefined.
TriangularFormatMap()985   static const NEONFormatMap* TriangularFormatMap() {
986     static const NEONFormatMap map =
987         {{19, 18, 17, 16, 30},
988          {NF_UNDEF, NF_UNDEF, NF_8B, NF_16B, NF_4H, NF_8H, NF_8B, NF_16B,
989           NF_2S,    NF_4S,    NF_8B, NF_16B, NF_4H, NF_8H, NF_8B, NF_16B,
990           NF_UNDEF, NF_2D,    NF_8B, NF_16B, NF_4H, NF_8H, NF_8B, NF_16B,
991           NF_2S,    NF_4S,    NF_8B, NF_16B, NF_4H, NF_8H, NF_8B, NF_16B}};
992     return &map;
993   }
994 
995   // The shift immediate map uses between two and five bits to encode the NEON
996   // vector format:
997   // 00010->8B, 00011->16B, 001x0->4H, 001x1->8H,
998   // 01xx0->2S, 01xx1->4S, 1xxx1->2D, all others undefined.
ShiftImmFormatMap()999   static const NEONFormatMap* ShiftImmFormatMap() {
1000     static const NEONFormatMap map = {{22, 21, 20, 19, 30},
1001                                       {NF_UNDEF, NF_UNDEF, NF_8B,    NF_16B,
1002                                        NF_4H,    NF_8H,    NF_4H,    NF_8H,
1003                                        NF_2S,    NF_4S,    NF_2S,    NF_4S,
1004                                        NF_2S,    NF_4S,    NF_2S,    NF_4S,
1005                                        NF_UNDEF, NF_2D,    NF_UNDEF, NF_2D,
1006                                        NF_UNDEF, NF_2D,    NF_UNDEF, NF_2D,
1007                                        NF_UNDEF, NF_2D,    NF_UNDEF, NF_2D,
1008                                        NF_UNDEF, NF_2D,    NF_UNDEF, NF_2D}};
1009     return &map;
1010   }
1011 
1012   // The shift long/narrow immediate map uses between two and four bits to
1013   // encode the NEON vector format:
1014   // 0001->8H, 001x->4S, 01xx->2D, all others undefined.
ShiftLongNarrowImmFormatMap()1015   static const NEONFormatMap* ShiftLongNarrowImmFormatMap() {
1016     static const NEONFormatMap map =
1017         {{22, 21, 20, 19},
1018          {NF_UNDEF, NF_8H, NF_4S, NF_4S, NF_2D, NF_2D, NF_2D, NF_2D}};
1019     return &map;
1020   }
1021 
1022   // The scalar format map uses two bits (size<1:0>) to encode the NEON scalar
1023   // formats: NF_B, NF_H, NF_S, NF_D.
ScalarFormatMap()1024   static const NEONFormatMap* ScalarFormatMap() {
1025     static const NEONFormatMap map = {{23, 22}, {NF_B, NF_H, NF_S, NF_D}};
1026     return &map;
1027   }
1028 
1029   // The long scalar format map uses two bits (size<1:0>) to encode the longer
1030   // NEON scalar formats: NF_H, NF_S, NF_D.
LongScalarFormatMap()1031   static const NEONFormatMap* LongScalarFormatMap() {
1032     static const NEONFormatMap map = {{23, 22}, {NF_H, NF_S, NF_D}};
1033     return &map;
1034   }
1035 
1036   // The FP scalar format map assumes one bit (size<0>) is used to encode the
1037   // NEON FP scalar formats: NF_S, NF_D.
FPScalarFormatMap()1038   static const NEONFormatMap* FPScalarFormatMap() {
1039     static const NEONFormatMap map = {{22}, {NF_S, NF_D}};
1040     return &map;
1041   }
1042 
1043   // The FP scalar pairwise format map assumes two bits (U, size<0>) are used to
1044   // encode the NEON FP scalar formats: NF_H, NF_S, NF_D.
FPScalarPairwiseFormatMap()1045   static const NEONFormatMap* FPScalarPairwiseFormatMap() {
1046     static const NEONFormatMap map = {{29, 22}, {NF_H, NF_UNDEF, NF_S, NF_D}};
1047     return &map;
1048   }
1049 
1050   // The triangular scalar format map uses between one and four bits to encode
1051   // the NEON FP scalar formats:
1052   // xxx1->B, xx10->H, x100->S, 1000->D, all others undefined.
TriangularScalarFormatMap()1053   static const NEONFormatMap* TriangularScalarFormatMap() {
1054     static const NEONFormatMap map = {{19, 18, 17, 16},
1055                                       {NF_UNDEF,
1056                                        NF_B,
1057                                        NF_H,
1058                                        NF_B,
1059                                        NF_S,
1060                                        NF_B,
1061                                        NF_H,
1062                                        NF_B,
1063                                        NF_D,
1064                                        NF_B,
1065                                        NF_H,
1066                                        NF_B,
1067                                        NF_S,
1068                                        NF_B,
1069                                        NF_H,
1070                                        NF_B}};
1071     return &map;
1072   }
1073 
1074  private:
1075   // Get a pointer to a string that represents the format or placeholder for
1076   // the specified substitution index, based on the format map and instruction.
GetSubstitute(int index, SubstitutionMode mode)1077   const char* GetSubstitute(int index, SubstitutionMode mode) {
1078     if (mode == kFormat) {
1079       return NEONFormatAsString(GetNEONFormat(formats_[index]));
1080     }
1081     VIXL_ASSERT(mode == kPlaceholder);
1082     return NEONFormatAsPlaceholder(GetNEONFormat(formats_[index]));
1083   }
1084 
1085   // Get the NEONFormat enumerated value for bits obtained from the
1086   // instruction based on the specified format mapping.
GetNEONFormat(const NEONFormatMap* format_map)1087   NEONFormat GetNEONFormat(const NEONFormatMap* format_map) {
1088     return format_map->map[PickBits(format_map->bits)];
1089   }
1090 
1091   // Convert a NEONFormat into a string.
NEONFormatAsString(NEONFormat format)1092   static const char* NEONFormatAsString(NEONFormat format) {
1093     // clang-format off
1094     static const char* formats[] = {
1095       NULL,
1096       "8b", "16b", "4h", "8h", "2s", "4s", "1d", "2d",
1097       "b", "h", "s", "d"
1098     };
1099     // clang-format on
1100     VIXL_ASSERT(format < ArrayLength(formats));
1101     return formats[format];
1102   }
1103 
1104   // Convert a NEONFormat into a register placeholder string.
1105   static const char* NEONFormatAsPlaceholder(NEONFormat format) {
1106     VIXL_ASSERT((format == NF_B) || (format == NF_H) || (format == NF_S) ||
1107                 (format == NF_D) || (format == NF_UNDEF));
1108     // clang-format off
1109     static const char* formats[] = {
1110       NULL,
1111       NULL, NULL, NULL, NULL,
1112       NULL, NULL, NULL, NULL,
1113       "'B", "'H", "'S", "'D"
1114     };
1115     // clang-format on
1116     return formats[format];
1117   }
1118 
1119   // Select bits from instrbits_ defined by the bits array, concatenate them,
1120   // and return the value.
1121   uint8_t PickBits(const uint8_t bits[]) {
1122     uint8_t result = 0;
1123     for (unsigned b = 0; b < kNEONFormatMaxBits; b++) {
1124       if (bits[b] == 0) break;
1125       result <<= 1;
1126       result |= ((instrbits_ & (1 << bits[b])) == 0) ? 0 : 1;
1127     }
1128     return result;
1129   }
1130 
1131   Instr instrbits_;
1132   const NEONFormatMap* formats_[3];
1133   char form_buffer_[64];
1134   char mne_buffer_[16];
1135 };
1136 }  // namespace aarch64
1137 }  // namespace vixl
1138 
1139 #endif  // VIXL_AARCH64_INSTRUCTIONS_AARCH64_H_
1140