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