Home | History | Annotate | Download | only in a64
      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 
     34 namespace vixl {
     35 // ISA constants. --------------------------------------------------------------
     36 
     37 typedef uint32_t Instr;
     38 const unsigned kInstructionSize = 4;
     39 const unsigned kInstructionSizeLog2 = 2;
     40 const unsigned kLiteralEntrySize = 4;
     41 const unsigned kLiteralEntrySizeLog2 = 2;
     42 const 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.
     46 const unsigned kPageSize = 4 * KBytes;
     47 const unsigned kPageSizeLog2 = 12;
     48 
     49 const unsigned kBRegSize = 8;
     50 const unsigned kBRegSizeLog2 = 3;
     51 const unsigned kBRegSizeInBytes = kBRegSize / 8;
     52 const unsigned kBRegSizeInBytesLog2 = kBRegSizeLog2 - 3;
     53 const unsigned kHRegSize = 16;
     54 const unsigned kHRegSizeLog2 = 4;
     55 const unsigned kHRegSizeInBytes = kHRegSize / 8;
     56 const unsigned kHRegSizeInBytesLog2 = kHRegSizeLog2 - 3;
     57 const unsigned kWRegSize = 32;
     58 const unsigned kWRegSizeLog2 = 5;
     59 const unsigned kWRegSizeInBytes = kWRegSize / 8;
     60 const unsigned kWRegSizeInBytesLog2 = kWRegSizeLog2 - 3;
     61 const unsigned kXRegSize = 64;
     62 const unsigned kXRegSizeLog2 = 6;
     63 const unsigned kXRegSizeInBytes = kXRegSize / 8;
     64 const unsigned kXRegSizeInBytesLog2 = kXRegSizeLog2 - 3;
     65 const unsigned kSRegSize = 32;
     66 const unsigned kSRegSizeLog2 = 5;
     67 const unsigned kSRegSizeInBytes = kSRegSize / 8;
     68 const unsigned kSRegSizeInBytesLog2 = kSRegSizeLog2 - 3;
     69 const unsigned kDRegSize = 64;
     70 const unsigned kDRegSizeLog2 = 6;
     71 const unsigned kDRegSizeInBytes = kDRegSize / 8;
     72 const unsigned kDRegSizeInBytesLog2 = kDRegSizeLog2 - 3;
     73 const unsigned kQRegSize = 128;
     74 const unsigned kQRegSizeLog2 = 7;
     75 const unsigned kQRegSizeInBytes = kQRegSize / 8;
     76 const unsigned kQRegSizeInBytesLog2 = kQRegSizeLog2 - 3;
     77 const uint64_t kWRegMask = UINT64_C(0xffffffff);
     78 const uint64_t kXRegMask = UINT64_C(0xffffffffffffffff);
     79 const uint64_t kSRegMask = UINT64_C(0xffffffff);
     80 const uint64_t kDRegMask = UINT64_C(0xffffffffffffffff);
     81 const uint64_t kSSignMask = UINT64_C(0x80000000);
     82 const uint64_t kDSignMask = UINT64_C(0x8000000000000000);
     83 const uint64_t kWSignMask = UINT64_C(0x80000000);
     84 const uint64_t kXSignMask = UINT64_C(0x8000000000000000);
     85 const uint64_t kByteMask = UINT64_C(0xff);
     86 const uint64_t kHalfWordMask = UINT64_C(0xffff);
     87 const uint64_t kWordMask = UINT64_C(0xffffffff);
     88 const uint64_t kXMaxUInt = UINT64_C(0xffffffffffffffff);
     89 const uint64_t kWMaxUInt = UINT64_C(0xffffffff);
     90 const int64_t kXMaxInt = INT64_C(0x7fffffffffffffff);
     91 const int64_t kXMinInt = INT64_C(0x8000000000000000);
     92 const int32_t kWMaxInt = INT32_C(0x7fffffff);
     93 const int32_t kWMinInt = INT32_C(0x80000000);
     94 const unsigned kLinkRegCode = 30;
     95 const unsigned kZeroRegCode = 31;
     96 const unsigned kSPRegInternalCode = 63;
     97 const unsigned kRegCodeMask = 0x1f;
     98 
     99 const unsigned kAddressTagOffset = 56;
    100 const unsigned kAddressTagWidth = 8;
    101 const uint64_t kAddressTagMask =
    102     ((UINT64_C(1) << kAddressTagWidth) - 1) << kAddressTagOffset;
    103 VIXL_STATIC_ASSERT(kAddressTagMask == UINT64_C(0xff00000000000000));
    104 
    105 // AArch64 floating-point specifics. These match IEEE-754.
    106 const unsigned kDoubleMantissaBits = 52;
    107 const unsigned kDoubleExponentBits = 11;
    108 const unsigned kFloatMantissaBits = 23;
    109 const unsigned kFloatExponentBits = 8;
    110 const unsigned kFloat16MantissaBits = 10;
    111 const unsigned kFloat16ExponentBits = 5;
    112 
    113 // Floating-point infinity values.
    114 extern const float16 kFP16PositiveInfinity;
    115 extern const float16 kFP16NegativeInfinity;
    116 extern const float kFP32PositiveInfinity;
    117 extern const float kFP32NegativeInfinity;
    118 extern const double kFP64PositiveInfinity;
    119 extern const double kFP64NegativeInfinity;
    120 
    121 // The default NaN values (for FPCR.DN=1).
    122 extern const float16 kFP16DefaultNaN;
    123 extern const float kFP32DefaultNaN;
    124 extern const double kFP64DefaultNaN;
    125 
    126 unsigned CalcLSDataSize(LoadStoreOp op);
    127 unsigned CalcLSPairDataSize(LoadStorePairOp op);
    128 
    129 enum ImmBranchType {
    130   UnknownBranchType = 0,
    131   CondBranchType    = 1,
    132   UncondBranchType  = 2,
    133   CompareBranchType = 3,
    134   TestBranchType    = 4
    135 };
    136 
    137 enum AddrMode {
    138   Offset,
    139   PreIndex,
    140   PostIndex
    141 };
    142 
    143 enum 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 
    156 enum Reg31Mode {
    157   Reg31IsStackPointer,
    158   Reg31IsZeroRegister
    159 };
    160 
    161 // Instructions. ---------------------------------------------------------------
    162 
    163 class 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.
    430 enum 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 
    452 VectorFormat VectorFormatHalfWidth(const VectorFormat vform);
    453 VectorFormat VectorFormatDoubleWidth(const VectorFormat vform);
    454 VectorFormat VectorFormatDoubleLanes(const VectorFormat vform);
    455 VectorFormat VectorFormatHalfLanes(const VectorFormat vform);
    456 VectorFormat ScalarFormatFromLaneSize(int lanesize);
    457 VectorFormat VectorFormatHalfWidthDoubleLanes(const VectorFormat vform);
    458 VectorFormat VectorFormatFillQ(const VectorFormat vform);
    459 unsigned RegisterSizeInBitsFromFormat(VectorFormat vform);
    460 unsigned RegisterSizeInBytesFromFormat(VectorFormat vform);
    461 // TODO: Make the return types of these functions consistent.
    462 unsigned LaneSizeInBitsFromFormat(VectorFormat vform);
    463 int LaneSizeInBytesFromFormat(VectorFormat vform);
    464 int LaneSizeInBytesLog2FromFormat(VectorFormat vform);
    465 int LaneCountFromFormat(VectorFormat vform);
    466 int MaxLaneCountFromFormat(VectorFormat vform);
    467 bool IsVectorFormat(VectorFormat vform);
    468 int64_t MaxIntFromFormat(VectorFormat vform);
    469 int64_t MinIntFromFormat(VectorFormat vform);
    470 uint64_t MaxUintFromFormat(VectorFormat vform);
    471 
    472 
    473 enum 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 
    489 static const unsigned kNEONFormatMaxBits = 6;
    490 
    491 struct 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 
    499 class 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_
    758