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
35namespace vixl {
36namespace aarch64 {
37// ISA constants. --------------------------------------------------------------
38
39typedef uint32_t Instr;
40const unsigned kInstructionSize = 4;
41const unsigned kInstructionSizeLog2 = 2;
42const unsigned kLiteralEntrySize = 4;
43const unsigned kLiteralEntrySizeLog2 = 2;
44const 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.
48const unsigned kPageSize = 4 * KBytes;
49const unsigned kPageSizeLog2 = 12;
50
51const unsigned kBRegSize = 8;
52const unsigned kBRegSizeLog2 = 3;
53const unsigned kBRegSizeInBytes = kBRegSize / 8;
54const unsigned kBRegSizeInBytesLog2 = kBRegSizeLog2 - 3;
55const unsigned kHRegSize = 16;
56const unsigned kHRegSizeLog2 = 4;
57const unsigned kHRegSizeInBytes = kHRegSize / 8;
58const unsigned kHRegSizeInBytesLog2 = kHRegSizeLog2 - 3;
59const unsigned kWRegSize = 32;
60const unsigned kWRegSizeLog2 = 5;
61const unsigned kWRegSizeInBytes = kWRegSize / 8;
62const unsigned kWRegSizeInBytesLog2 = kWRegSizeLog2 - 3;
63const unsigned kXRegSize = 64;
64const unsigned kXRegSizeLog2 = 6;
65const unsigned kXRegSizeInBytes = kXRegSize / 8;
66const unsigned kXRegSizeInBytesLog2 = kXRegSizeLog2 - 3;
67const unsigned kSRegSize = 32;
68const unsigned kSRegSizeLog2 = 5;
69const unsigned kSRegSizeInBytes = kSRegSize / 8;
70const unsigned kSRegSizeInBytesLog2 = kSRegSizeLog2 - 3;
71const unsigned kDRegSize = 64;
72const unsigned kDRegSizeLog2 = 6;
73const unsigned kDRegSizeInBytes = kDRegSize / 8;
74const unsigned kDRegSizeInBytesLog2 = kDRegSizeLog2 - 3;
75const unsigned kQRegSize = 128;
76const unsigned kQRegSizeLog2 = 7;
77const unsigned kQRegSizeInBytes = kQRegSize / 8;
78const unsigned kQRegSizeInBytesLog2 = kQRegSizeLog2 - 3;
79const uint64_t kWRegMask = UINT64_C(0xffffffff);
80const uint64_t kXRegMask = UINT64_C(0xffffffffffffffff);
81const uint64_t kHRegMask = UINT64_C(0xffff);
82const uint64_t kSRegMask = UINT64_C(0xffffffff);
83const uint64_t kDRegMask = UINT64_C(0xffffffffffffffff);
84const uint64_t kHSignMask = UINT64_C(0x8000);
85const uint64_t kSSignMask = UINT64_C(0x80000000);
86const uint64_t kDSignMask = UINT64_C(0x8000000000000000);
87const uint64_t kWSignMask = UINT64_C(0x80000000);
88const uint64_t kXSignMask = UINT64_C(0x8000000000000000);
89const uint64_t kByteMask = UINT64_C(0xff);
90const uint64_t kHalfWordMask = UINT64_C(0xffff);
91const uint64_t kWordMask = UINT64_C(0xffffffff);
92const uint64_t kXMaxUInt = UINT64_C(0xffffffffffffffff);
93const uint64_t kWMaxUInt = UINT64_C(0xffffffff);
94const 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.
97const int64_t kXMaxInt = INT64_C(0x7fffffffffffffff);
98const int64_t kXMinInt = -kXMaxInt - 1;
99const int32_t kWMaxInt = INT32_C(0x7fffffff);
100const int32_t kWMinInt = -kWMaxInt - 1;
101const int16_t kHMaxInt = INT16_C(0x7fff);
102const int16_t kHMinInt = -kHMaxInt - 1;
103const unsigned kFpRegCode = 29;
104const unsigned kLinkRegCode = 30;
105const unsigned kSpRegCode = 31;
106const unsigned kZeroRegCode = 31;
107const unsigned kSPRegInternalCode = 63;
108const unsigned kRegCodeMask = 0x1f;
109
110const unsigned kAtomicAccessGranule = 16;
111
112const unsigned kAddressTagOffset = 56;
113const unsigned kAddressTagWidth = 8;
114const uint64_t kAddressTagMask = ((UINT64_C(1) << kAddressTagWidth) - 1)
115                                 << kAddressTagOffset;
116VIXL_STATIC_ASSERT(kAddressTagMask == UINT64_C(0xff00000000000000));
117
118const 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.
123const unsigned kZRegMinSize = 128;
124const unsigned kZRegMinSizeLog2 = 7;
125const unsigned kZRegMinSizeInBytes = kZRegMinSize / 8;
126const unsigned kZRegMinSizeInBytesLog2 = kZRegMinSizeLog2 - 3;
127const unsigned kZRegMaxSize = 2048;
128const unsigned kZRegMaxSizeLog2 = 11;
129const unsigned kZRegMaxSizeInBytes = kZRegMaxSize / 8;
130const unsigned kZRegMaxSizeInBytesLog2 = kZRegMaxSizeLog2 - 3;
131
132// The P register size depends on the Z register size.
133const unsigned kZRegBitsPerPRegBit = kBitsPerByte;
134const unsigned kZRegBitsPerPRegBitLog2 = 3;
135const unsigned kPRegMinSize = kZRegMinSize / kZRegBitsPerPRegBit;
136const unsigned kPRegMinSizeLog2 = kZRegMinSizeLog2 - 3;
137const unsigned kPRegMinSizeInBytes = kPRegMinSize / 8;
138const unsigned kPRegMinSizeInBytesLog2 = kPRegMinSizeLog2 - 3;
139const unsigned kPRegMaxSize = kZRegMaxSize / kZRegBitsPerPRegBit;
140const unsigned kPRegMaxSizeLog2 = kZRegMaxSizeLog2 - 3;
141const unsigned kPRegMaxSizeInBytes = kPRegMaxSize / 8;
142const unsigned kPRegMaxSizeInBytesLog2 = kPRegMaxSizeLog2 - 3;
143
144const unsigned kMTETagGranuleInBytes = 16;
145const unsigned kMTETagGranuleInBytesLog2 = 4;
146const unsigned kMTETagWidth = 4;
147
148// Make these moved float constants backwards compatible
149// with explicit vixl::aarch64:: namespace references.
150using vixl::kDoubleExponentBits;
151using vixl::kDoubleMantissaBits;
152using vixl::kFloat16ExponentBits;
153using vixl::kFloat16MantissaBits;
154using vixl::kFloatExponentBits;
155using vixl::kFloatMantissaBits;
156
157using vixl::kFP16NegativeInfinity;
158using vixl::kFP16PositiveInfinity;
159using vixl::kFP32NegativeInfinity;
160using vixl::kFP32PositiveInfinity;
161using vixl::kFP64NegativeInfinity;
162using vixl::kFP64PositiveInfinity;
163
164using vixl::kFP16DefaultNaN;
165using vixl::kFP32DefaultNaN;
166using vixl::kFP64DefaultNaN;
167
168unsigned CalcLSDataSize(LoadStoreOp op);
169unsigned CalcLSPairDataSize(LoadStorePairOp op);
170
171enum ImmBranchType {
172  UnknownBranchType = 0,
173  CondBranchType = 1,
174  UncondBranchType = 2,
175  CompareBranchType = 3,
176  TestBranchType = 4
177};
178
179enum AddrMode { Offset, PreIndex, PostIndex };
180
181enum Reg31Mode { Reg31IsStackPointer, Reg31IsZeroRegister };
182
183enum 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
227class Instruction {
228 public:
229  Instr GetInstructionBits() const {
230    return *(reinterpret_cast<const Instr*>(this));
231  }
232  VIXL_DEPRECATED("GetInstructionBits", Instr InstructionBits() const) {
233    return GetInstructionBits();
234  }
235
236  void SetInstructionBits(Instr new_instr) {
237    *(reinterpret_cast<Instr*>(this)) = new_instr;
238  }
239
240  int ExtractBit(int pos) const { return (GetInstructionBits() >> pos) & 1; }
241  VIXL_DEPRECATED("ExtractBit", int Bit(int pos) const) {
242    return ExtractBit(pos);
243  }
244
245  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
254  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>
274  uint32_t ExtractBits() const {
275    return Compress(M);
276  }
277
278  uint32_t ExtractBitsAbsent() const {
279    VIXL_UNREACHABLE();
280    return 0;
281  }
282
283  template <uint32_t M, uint32_t V>
284  uint32_t IsMaskedValue() const {
285    return (Mask(M) == V) ? 1 : 0;
286  }
287
288  uint32_t IsMaskedValueAbsent() const {
289    VIXL_UNREACHABLE();
290    return 0;
291  }
292
293  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
302  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>
314  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
321  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.
343  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.
354  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
412  Float16 GetSVEImmFP16() const { return Imm8ToFloat16(ExtractBits(12, 5)); }
413
414  float GetSVEImmFP32() const { return Imm8ToFP32(ExtractBits(12, 5)); }
415
416  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
422  unsigned GetSizeLS() const {
423    return CalcLSDataSize(static_cast<LoadStoreOp>(Mask(LoadStoreMask)));
424  }
425  VIXL_DEPRECATED("GetSizeLS", unsigned SizeLS() const) { return GetSizeLS(); }
426
427  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
435  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.
448  bool IsCondBranchImm() const {
449    return Mask(ConditionalBranchFMask) == ConditionalBranchFixed;
450  }
451
452  bool IsUncondBranchImm() const {
453    return Mask(UnconditionalBranchFMask) == UnconditionalBranchFixed;
454  }
455
456  bool IsCompareBranch() const {
457    return Mask(CompareBranchFMask) == CompareBranchFixed;
458  }
459
460  bool IsTestBranch() const { return Mask(TestBranchFMask) == TestBranchFixed; }
461
462  bool IsImmBranch() const { return GetBranchType() != UnknownBranchType; }
463
464  bool IsPCRelAddressing() const {
465    return Mask(PCRelAddressingFMask) == PCRelAddressingFixed;
466  }
467
468  bool IsLogicalImmediate() const {
469    return Mask(LogicalImmediateFMask) == LogicalImmediateFixed;
470  }
471
472  bool IsAddSubImmediate() const {
473    return Mask(AddSubImmediateFMask) == AddSubImmediateFixed;
474  }
475
476  bool IsAddSubExtended() const {
477    return Mask(AddSubExtendedFMask) == AddSubExtendedFixed;
478  }
479
480  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
491  bool IsLoadLiteral() const {
492    // This includes PRFM_lit.
493    return Mask(LoadLiteralFMask) == LoadLiteralFixed;
494  }
495
496  bool IsMovn() const {
497    return (Mask(MoveWideImmediateMask) == MOVN_x) ||
498           (Mask(MoveWideImmediateMask) == MOVN_w);
499  }
500
501  bool IsException() const { return Mask(ExceptionFMask) == ExceptionFixed; }
502
503  bool IsPAuth() const { return Mask(SystemPAuthFMask) == SystemPAuthFixed; }
504
505  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
519  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
526  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
534  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>
543  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.
596  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.
626  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
639  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>
683  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
702  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
711  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
720  float GetLiteralFP32() const { return RawbitsToFloat(GetLiteral32()); }
721  VIXL_DEPRECATED("GetLiteralFP32", float LiteralFP32() const) {
722    return GetLiteralFP32();
723  }
724
725  double GetLiteralFP64() const { return RawbitsToDouble(GetLiteral64()); }
726  VIXL_DEPRECATED("GetLiteralFP64", double LiteralFP64() const) {
727    return GetLiteralFP64();
728  }
729
730  Instruction* GetNextInstruction() { return this + kInstructionSize; }
731  const Instruction* GetNextInstruction() const {
732    return this + kInstructionSize;
733  }
734  VIXL_DEPRECATED("GetNextInstruction",
735                  const Instruction* NextInstruction() const) {
736    return GetNextInstruction();
737  }
738
739  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>
750  static Instruction* Cast(T src) {
751    return reinterpret_cast<Instruction*>(src);
752  }
753
754  template <typename T>
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
769const int kMaxLanesPerVector = 16;
770
771VectorFormat VectorFormatHalfWidth(VectorFormat vform);
772VectorFormat VectorFormatDoubleWidth(VectorFormat vform);
773VectorFormat VectorFormatDoubleLanes(VectorFormat vform);
774VectorFormat VectorFormatHalfLanes(VectorFormat vform);
775VectorFormat ScalarFormatFromLaneSize(int lane_size_in_bits);
776VectorFormat VectorFormatHalfWidthDoubleLanes(VectorFormat vform);
777VectorFormat VectorFormatFillQ(VectorFormat vform);
778VectorFormat ScalarFormatFromFormat(VectorFormat vform);
779VectorFormat SVEFormatFromLaneSizeInBits(int lane_size_in_bits);
780VectorFormat SVEFormatFromLaneSizeInBytes(int lane_size_in_bytes);
781VectorFormat SVEFormatFromLaneSizeInBytesLog2(int lane_size_in_bytes_log_2);
782unsigned RegisterSizeInBitsFromFormat(VectorFormat vform);
783unsigned RegisterSizeInBytesFromFormat(VectorFormat vform);
784bool IsSVEFormat(VectorFormat vform);
785// TODO: Make the return types of these functions consistent.
786unsigned LaneSizeInBitsFromFormat(VectorFormat vform);
787int LaneSizeInBytesFromFormat(VectorFormat vform);
788int LaneSizeInBytesLog2FromFormat(VectorFormat vform);
789int LaneCountFromFormat(VectorFormat vform);
790int MaxLaneCountFromFormat(VectorFormat vform);
791bool IsVectorFormat(VectorFormat vform);
792int64_t MaxIntFromFormat(VectorFormat vform);
793int64_t MinIntFromFormat(VectorFormat vform);
794uint64_t MaxUintFromFormat(VectorFormat vform);
795
796
797// clang-format off
798enum 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
815static const unsigned kNEONFormatMaxBits = 6;
816
817struct 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
825class 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.
832  explicit NEONFormatDecoder(const Instruction* instr) {
833    instrbits_ = instr->GetInstructionBits();
834    SetFormatMaps(IntegerFormatMap());
835  }
836  NEONFormatDecoder(const Instruction* instr, const NEONFormatMap* format) {
837    instrbits_ = instr->GetInstructionBits();
838    SetFormatMaps(format);
839  }
840  NEONFormatDecoder(const Instruction* instr,
841                    const NEONFormatMap* format0,
842                    const NEONFormatMap* format1) {
843    instrbits_ = instr->GetInstructionBits();
844    SetFormatMaps(format0, format1);
845  }
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.
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  }
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.
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.
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.
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
907  VectorFormat GetVectorFormat(int format_index = 0) {
908    return GetVectorFormat(formats_[format_index]);
909  }
910
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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