cachepc-qemu

Fork of AMDESE/qemu with changes for cachepc side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-qemu
Log | Files | Refs | Submodules | LICENSE | sfeed.txt

instructions-a64.h (25740B)


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