1 // Copyright 2015, VIXL authors 2 // All rights reserved. 3 // 4 // Redistribution and use in source and binary forms, with or without 5 // modification, are permitted provided that the following conditions are met: 6 // 7 // * Redistributions of source code must retain the above copyright notice, 8 // this list of conditions and the following disclaimer. 9 // * Redistributions in binary form must reproduce the above copyright notice, 10 // this list of conditions and the following disclaimer in the documentation 11 // and/or other materials provided with the distribution. 12 // * Neither the name of ARM Limited nor the names of its contributors may be 13 // used to endorse or promote products derived from this software without 14 // specific prior written permission. 15 // 16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS CONTRIBUTORS "AS IS" AND 17 // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE 20 // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 22 // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 23 // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 24 // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 25 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 27 #ifndef VIXL_AARCH64_INSTRUCTIONS_AARCH64_H_ 28 #define VIXL_AARCH64_INSTRUCTIONS_AARCH64_H_ 29 30 #include "../globals-vixl.h" 31 #include "../utils-vixl.h" 32 33 #include "constants-aarch64.h" 34 35 namespace vixl { 36 namespace aarch64 { 37 // ISA constants. -------------------------------------------------------------- 38 39 typedef uint32_t Instr; 40 const unsigned kInstructionSize = 4; 41 const unsigned kInstructionSizeLog2 = 2; 42 const unsigned kLiteralEntrySize = 4; 43 const unsigned kLiteralEntrySizeLog2 = 2; 44 const unsigned kMaxLoadLiteralRange = 1 * MBytes; 45 46 // This is the nominal page size (as used by the adrp instruction); the actual 47 // size of the memory pages allocated by the kernel is likely to differ. 48 const unsigned kPageSize = 4 * KBytes; 49 const unsigned kPageSizeLog2 = 12; 50 51 const unsigned kBRegSize = 8; 52 const unsigned kBRegSizeLog2 = 3; 53 const unsigned kBRegSizeInBytes = kBRegSize / 8; 54 const unsigned kBRegSizeInBytesLog2 = kBRegSizeLog2 - 3; 55 const unsigned kHRegSize = 16; 56 const unsigned kHRegSizeLog2 = 4; 57 const unsigned kHRegSizeInBytes = kHRegSize / 8; 58 const unsigned kHRegSizeInBytesLog2 = kHRegSizeLog2 - 3; 59 const unsigned kWRegSize = 32; 60 const unsigned kWRegSizeLog2 = 5; 61 const unsigned kWRegSizeInBytes = kWRegSize / 8; 62 const unsigned kWRegSizeInBytesLog2 = kWRegSizeLog2 - 3; 63 const unsigned kXRegSize = 64; 64 const unsigned kXRegSizeLog2 = 6; 65 const unsigned kXRegSizeInBytes = kXRegSize / 8; 66 const unsigned kXRegSizeInBytesLog2 = kXRegSizeLog2 - 3; 67 const unsigned kSRegSize = 32; 68 const unsigned kSRegSizeLog2 = 5; 69 const unsigned kSRegSizeInBytes = kSRegSize / 8; 70 const unsigned kSRegSizeInBytesLog2 = kSRegSizeLog2 - 3; 71 const unsigned kDRegSize = 64; 72 const unsigned kDRegSizeLog2 = 6; 73 const unsigned kDRegSizeInBytes = kDRegSize / 8; 74 const unsigned kDRegSizeInBytesLog2 = kDRegSizeLog2 - 3; 75 const unsigned kQRegSize = 128; 76 const unsigned kQRegSizeLog2 = 7; 77 const unsigned kQRegSizeInBytes = kQRegSize / 8; 78 const unsigned kQRegSizeInBytesLog2 = kQRegSizeLog2 - 3; 79 const uint64_t kWRegMask = UINT64_C(0xffffffff); 80 const uint64_t kXRegMask = UINT64_C(0xffffffffffffffff); 81 const uint64_t kHRegMask = UINT64_C(0xffff); 82 const uint64_t kSRegMask = UINT64_C(0xffffffff); 83 const uint64_t kDRegMask = UINT64_C(0xffffffffffffffff); 84 const uint64_t kHSignMask = UINT64_C(0x8000); 85 const uint64_t kSSignMask = UINT64_C(0x80000000); 86 const uint64_t kDSignMask = UINT64_C(0x8000000000000000); 87 const uint64_t kWSignMask = UINT64_C(0x80000000); 88 const uint64_t kXSignMask = UINT64_C(0x8000000000000000); 89 const uint64_t kByteMask = UINT64_C(0xff); 90 const uint64_t kHalfWordMask = UINT64_C(0xffff); 91 const uint64_t kWordMask = UINT64_C(0xffffffff); 92 const uint64_t kXMaxUInt = UINT64_C(0xffffffffffffffff); 93 const uint64_t kWMaxUInt = UINT64_C(0xffffffff); 94 const uint64_t kHMaxUInt = UINT64_C(0xffff); 95 // Define k*MinInt with "-k*MaxInt - 1", because the hexadecimal representation 96 // (e.g. "INT32_C(0x80000000)") has implementation-defined behaviour. 97 const int64_t kXMaxInt = INT64_C(0x7fffffffffffffff); 98 const int64_t kXMinInt = -kXMaxInt - 1; 99 const int32_t kWMaxInt = INT32_C(0x7fffffff); 100 const int32_t kWMinInt = -kWMaxInt - 1; 101 const int16_t kHMaxInt = INT16_C(0x7fff); 102 const int16_t kHMinInt = -kHMaxInt - 1; 103 const unsigned kFpRegCode = 29; 104 const unsigned kLinkRegCode = 30; 105 const unsigned kSpRegCode = 31; 106 const unsigned kZeroRegCode = 31; 107 const unsigned kSPRegInternalCode = 63; 108 const unsigned kRegCodeMask = 0x1f; 109 110 const unsigned kAtomicAccessGranule = 16; 111 112 const unsigned kAddressTagOffset = 56; 113 const unsigned kAddressTagWidth = 8; 114 const uint64_t kAddressTagMask = ((UINT64_C(1) << kAddressTagWidth) - 1) 115 << kAddressTagOffset; 116 VIXL_STATIC_ASSERT(kAddressTagMask == UINT64_C(0xff00000000000000)); 117 118 const uint64_t kTTBRMask = UINT64_C(1) << 55; 119 120 // We can't define a static kZRegSize because the size depends on the 121 // implementation. However, it is sometimes useful to know the minimum and 122 // maximum possible sizes. 123 const unsigned kZRegMinSize = 128; 124 const unsigned kZRegMinSizeLog2 = 7; 125 const unsigned kZRegMinSizeInBytes = kZRegMinSize / 8; 126 const unsigned kZRegMinSizeInBytesLog2 = kZRegMinSizeLog2 - 3; 127 const unsigned kZRegMaxSize = 2048; 128 const unsigned kZRegMaxSizeLog2 = 11; 129 const unsigned kZRegMaxSizeInBytes = kZRegMaxSize / 8; 130 const unsigned kZRegMaxSizeInBytesLog2 = kZRegMaxSizeLog2 - 3; 131 132 // The P register size depends on the Z register size. 133 const unsigned kZRegBitsPerPRegBit = kBitsPerByte; 134 const unsigned kZRegBitsPerPRegBitLog2 = 3; 135 const unsigned kPRegMinSize = kZRegMinSize / kZRegBitsPerPRegBit; 136 const unsigned kPRegMinSizeLog2 = kZRegMinSizeLog2 - 3; 137 const unsigned kPRegMinSizeInBytes = kPRegMinSize / 8; 138 const unsigned kPRegMinSizeInBytesLog2 = kPRegMinSizeLog2 - 3; 139 const unsigned kPRegMaxSize = kZRegMaxSize / kZRegBitsPerPRegBit; 140 const unsigned kPRegMaxSizeLog2 = kZRegMaxSizeLog2 - 3; 141 const unsigned kPRegMaxSizeInBytes = kPRegMaxSize / 8; 142 const unsigned kPRegMaxSizeInBytesLog2 = kPRegMaxSizeLog2 - 3; 143 144 const unsigned kMTETagGranuleInBytes = 16; 145 const unsigned kMTETagGranuleInBytesLog2 = 4; 146 const unsigned kMTETagWidth = 4; 147 148 // Make these moved float constants backwards compatible 149 // with explicit vixl::aarch64:: namespace references. 150 using vixl::kDoubleExponentBits; 151 using vixl::kDoubleMantissaBits; 152 using vixl::kFloat16ExponentBits; 153 using vixl::kFloat16MantissaBits; 154 using vixl::kFloatExponentBits; 155 using vixl::kFloatMantissaBits; 156 157 using vixl::kFP16NegativeInfinity; 158 using vixl::kFP16PositiveInfinity; 159 using vixl::kFP32NegativeInfinity; 160 using vixl::kFP32PositiveInfinity; 161 using vixl::kFP64NegativeInfinity; 162 using vixl::kFP64PositiveInfinity; 163 164 using vixl::kFP16DefaultNaN; 165 using vixl::kFP32DefaultNaN; 166 using vixl::kFP64DefaultNaN; 167 168 unsigned CalcLSDataSize(LoadStoreOp op); 169 unsigned CalcLSPairDataSize(LoadStorePairOp op); 170 171 enum ImmBranchType { 172 UnknownBranchType = 0, 173 CondBranchType = 1, 174 UncondBranchType = 2, 175 CompareBranchType = 3, 176 TestBranchType = 4 177 }; 178 179 enum AddrMode { Offset, PreIndex, PostIndex }; 180 181 enum Reg31Mode { Reg31IsStackPointer, Reg31IsZeroRegister }; 182 183 enum VectorFormat { 184 kFormatUndefined = 0xffffffff, 185 kFormat8B = NEON_8B, 186 kFormat16B = NEON_16B, 187 kFormat4H = NEON_4H, 188 kFormat8H = NEON_8H, 189 kFormat2S = NEON_2S, 190 kFormat4S = NEON_4S, 191 kFormat1D = NEON_1D, 192 kFormat2D = NEON_2D, 193 194 // Scalar formats. We add the scalar bit to distinguish between scalar and 195 // vector enumerations; the bit is always set in the encoding of scalar ops 196 // and always clear for vector ops. Although kFormatD and kFormat1D appear 197 // to be the same, their meaning is subtly different. The first is a scalar 198 // operation, the second a vector operation that only affects one lane. 199 kFormatB = NEON_B | NEONScalar, 200 kFormatH = NEON_H | NEONScalar, 201 kFormatS = NEON_S | NEONScalar, 202 kFormatD = NEON_D | NEONScalar, 203 204 // An artificial value, used to distinguish from NEON format category. 205 kFormatSVE = 0x0000fffd, 206 // Artificial values. Q and O lane sizes aren't encoded in the usual size 207 // field. 208 kFormatSVEQ = 0x00080000, 209 kFormatSVEO = 0x00040000, 210 211 // Vector element width of SVE register with the unknown lane count since 212 // the vector length is implementation dependent. 213 kFormatVnB = SVE_B | kFormatSVE, 214 kFormatVnH = SVE_H | kFormatSVE, 215 kFormatVnS = SVE_S | kFormatSVE, 216 kFormatVnD = SVE_D | kFormatSVE, 217 kFormatVnQ = kFormatSVEQ | kFormatSVE, 218 kFormatVnO = kFormatSVEO | kFormatSVE, 219 220 // Artificial values, used by simulator trace tests and a few oddball 221 // instructions (such as FMLAL). 222 kFormat2H = 0xfffffffe, 223 kFormat1Q = 0xfffffffd 224 }; 225 226 // Instructions. --------------------------------------------------------------- 227 228 class Instruction { 229 public: GetInstructionBits()230 Instr GetInstructionBits() const { 231 return *(reinterpret_cast<const Instr*>(this)); 232 } 233 VIXL_DEPRECATED("GetInstructionBits", Instr InstructionBits() const) { 234 return GetInstructionBits(); 235 } 236 SetInstructionBits(Instr new_instr)237 void SetInstructionBits(Instr new_instr) { 238 *(reinterpret_cast<Instr*>(this)) = new_instr; 239 } 240 ExtractBit(int pos)241 int ExtractBit(int pos) const { return (GetInstructionBits() >> pos) & 1; } Bit(int pos)242 VIXL_DEPRECATED("ExtractBit", int Bit(int pos) const) { 243 return ExtractBit(pos); 244 } 245 ExtractBits(int msb,int lsb)246 uint32_t ExtractBits(int msb, int lsb) const { 247 return ExtractUnsignedBitfield32(msb, lsb, GetInstructionBits()); 248 } 249 VIXL_DEPRECATED("ExtractBits", uint32_t Bits(int msb, int lsb) const) { 250 return ExtractBits(msb, lsb); 251 } 252 253 // Compress bit extraction operation from Hacker's Delight. 254 // https://github.com/hcs0/Hackers-Delight/blob/master/compress.c.txt Compress(uint32_t mask)255 uint32_t Compress(uint32_t mask) const { 256 uint32_t mk, mp, mv, t; 257 uint32_t x = GetInstructionBits() & mask; // Clear irrelevant bits. 258 mk = ~mask << 1; // We will count 0's to right. 259 for (int i = 0; i < 5; i++) { 260 mp = mk ^ (mk << 1); // Parallel suffix. 261 mp = mp ^ (mp << 2); 262 mp = mp ^ (mp << 4); 263 mp = mp ^ (mp << 8); 264 mp = mp ^ (mp << 16); 265 mv = mp & mask; // Bits to move. 266 mask = (mask ^ mv) | (mv >> (1 << i)); // Compress mask. 267 t = x & mv; 268 x = (x ^ t) | (t >> (1 << i)); // Compress x. 269 mk = mk & ~mp; 270 } 271 return x; 272 } 273 274 template <uint32_t M> ExtractBits()275 uint32_t ExtractBits() const { 276 return Compress(M); 277 } 278 ExtractBitsAbsent()279 uint32_t ExtractBitsAbsent() const { 280 VIXL_UNREACHABLE(); 281 return 0; 282 } 283 284 template <uint32_t M, uint32_t V> IsMaskedValue()285 uint32_t IsMaskedValue() const { 286 return (Mask(M) == V) ? 1 : 0; 287 } 288 IsMaskedValueAbsent()289 uint32_t IsMaskedValueAbsent() const { 290 VIXL_UNREACHABLE(); 291 return 0; 292 } 293 ExtractSignedBits(int msb,int lsb)294 int32_t ExtractSignedBits(int msb, int lsb) const { 295 int32_t bits = *(reinterpret_cast<const int32_t*>(this)); 296 return ExtractSignedBitfield32(msb, lsb, bits); 297 } 298 VIXL_DEPRECATED("ExtractSignedBits", 299 int32_t SignedBits(int msb, int lsb) const) { 300 return ExtractSignedBits(msb, lsb); 301 } 302 Mask(uint32_t mask)303 Instr Mask(uint32_t mask) const { 304 VIXL_ASSERT(mask != 0); 305 return GetInstructionBits() & mask; 306 } 307 308 #define DEFINE_GETTER(Name, HighBit, LowBit, Func) \ 309 int32_t Get##Name() const { return this->Func(HighBit, LowBit); } \ 310 VIXL_DEPRECATED("Get" #Name, int32_t Name() const) { return Get##Name(); } INSTRUCTION_FIELDS_LIST(DEFINE_GETTER)311 INSTRUCTION_FIELDS_LIST(DEFINE_GETTER) 312 #undef DEFINE_GETTER 313 314 template <int msb, int lsb> 315 int32_t GetRx() const { 316 // We don't have any register fields wider than five bits, so the result 317 // will always fit into an int32_t. 318 VIXL_ASSERT((msb - lsb + 1) <= 5); 319 return this->ExtractBits(msb, lsb); 320 } 321 322 VectorFormat GetSVEVectorFormat(int field_lsb = 22) const { 323 VIXL_ASSERT((field_lsb >= 0) && (field_lsb <= 30)); 324 uint32_t instr = ExtractUnsignedBitfield32(field_lsb + 1, 325 field_lsb, 326 GetInstructionBits()) 327 << 22; 328 switch (instr & SVESizeFieldMask) { 329 case SVE_B: 330 return kFormatVnB; 331 case SVE_H: 332 return kFormatVnH; 333 case SVE_S: 334 return kFormatVnS; 335 case SVE_D: 336 return kFormatVnD; 337 } 338 VIXL_UNREACHABLE(); 339 return kFormatUndefined; 340 } 341 342 // ImmPCRel is a compound field (not present in INSTRUCTION_FIELDS_LIST), 343 // formed from ImmPCRelLo and ImmPCRelHi. GetImmPCRel()344 int GetImmPCRel() const { 345 uint32_t hi = static_cast<uint32_t>(GetImmPCRelHi()); 346 uint32_t lo = GetImmPCRelLo(); 347 uint32_t offset = (hi << ImmPCRelLo_width) | lo; 348 int width = ImmPCRelLo_width + ImmPCRelHi_width; 349 return ExtractSignedBitfield32(width - 1, 0, offset); 350 } ImmPCRel()351 VIXL_DEPRECATED("GetImmPCRel", int ImmPCRel() const) { return GetImmPCRel(); } 352 353 // ImmLSPAC is a compound field (not present in INSTRUCTION_FIELDS_LIST), 354 // formed from ImmLSPACLo and ImmLSPACHi. GetImmLSPAC()355 int GetImmLSPAC() const { 356 uint32_t hi = static_cast<uint32_t>(GetImmLSPACHi()); 357 uint32_t lo = GetImmLSPACLo(); 358 uint32_t offset = (hi << ImmLSPACLo_width) | lo; 359 int width = ImmLSPACLo_width + ImmLSPACHi_width; 360 return ExtractSignedBitfield32(width - 1, 0, offset) << 3; 361 } 362 363 uint64_t GetImmLogical() const; 364 VIXL_DEPRECATED("GetImmLogical", uint64_t ImmLogical() const) { 365 return GetImmLogical(); 366 } 367 uint64_t GetSVEImmLogical() const; 368 int GetSVEBitwiseImmLaneSizeInBytesLog2() const; 369 uint64_t DecodeImmBitMask(int32_t n, 370 int32_t imm_s, 371 int32_t imm_r, 372 int32_t size) const; 373 374 std::pair<int, int> GetSVEPermuteIndexAndLaneSizeLog2() const; 375 376 std::pair<int, int> GetNEONMulRmAndIndex() const; 377 std::pair<int, int> GetSVEMulZmAndIndex() const; 378 std::pair<int, int> GetSVEMulLongZmAndIndex() const; 379 380 std::pair<int, int> GetSVEImmShiftAndLaneSizeLog2(bool is_predicated) const; 381 382 int GetSVEExtractImmediate() const; 383 384 int GetSVEMsizeFromDtype(bool is_signed, int dtype_h_lsb = 23) const; 385 386 int GetSVEEsizeFromDtype(bool is_signed, int dtype_l_lsb = 21) const; 387 388 389 unsigned GetImmNEONabcdefgh() const; ImmNEONabcdefgh()390 VIXL_DEPRECATED("GetImmNEONabcdefgh", unsigned ImmNEONabcdefgh() const) { 391 return GetImmNEONabcdefgh(); 392 } 393 394 Float16 GetImmFP16() const; 395 396 float GetImmFP32() const; ImmFP32()397 VIXL_DEPRECATED("GetImmFP32", float ImmFP32() const) { return GetImmFP32(); } 398 399 double GetImmFP64() const; ImmFP64()400 VIXL_DEPRECATED("GetImmFP64", double ImmFP64() const) { return GetImmFP64(); } 401 402 Float16 GetImmNEONFP16() const; 403 404 float GetImmNEONFP32() const; ImmNEONFP32()405 VIXL_DEPRECATED("GetImmNEONFP32", float ImmNEONFP32() const) { 406 return GetImmNEONFP32(); 407 } 408 409 double GetImmNEONFP64() const; ImmNEONFP64()410 VIXL_DEPRECATED("GetImmNEONFP64", double ImmNEONFP64() const) { 411 return GetImmNEONFP64(); 412 } 413 GetSVEImmFP16()414 Float16 GetSVEImmFP16() const { return Imm8ToFloat16(ExtractBits(12, 5)); } 415 GetSVEImmFP32()416 float GetSVEImmFP32() const { return Imm8ToFP32(ExtractBits(12, 5)); } 417 GetSVEImmFP64()418 double GetSVEImmFP64() const { return Imm8ToFP64(ExtractBits(12, 5)); } 419 420 static Float16 Imm8ToFloat16(uint32_t imm8); 421 static float Imm8ToFP32(uint32_t imm8); 422 static double Imm8ToFP64(uint32_t imm8); 423 GetSizeLS()424 unsigned GetSizeLS() const { 425 return CalcLSDataSize(static_cast<LoadStoreOp>(Mask(LoadStoreMask))); 426 } SizeLS()427 VIXL_DEPRECATED("GetSizeLS", unsigned SizeLS() const) { return GetSizeLS(); } 428 GetSizeLSPair()429 unsigned GetSizeLSPair() const { 430 return CalcLSPairDataSize( 431 static_cast<LoadStorePairOp>(Mask(LoadStorePairMask))); 432 } SizeLSPair()433 VIXL_DEPRECATED("GetSizeLSPair", unsigned SizeLSPair() const) { 434 return GetSizeLSPair(); 435 } 436 GetNEONLSIndex(int access_size_shift)437 int GetNEONLSIndex(int access_size_shift) const { 438 int64_t q = GetNEONQ(); 439 int64_t s = GetNEONS(); 440 int64_t size = GetNEONLSSize(); 441 int64_t index = (q << 3) | (s << 2) | size; 442 return static_cast<int>(index >> access_size_shift); 443 } 444 VIXL_DEPRECATED("GetNEONLSIndex", NEONLSIndex(int access_size_shift)445 int NEONLSIndex(int access_size_shift) const) { 446 return GetNEONLSIndex(access_size_shift); 447 } 448 449 // Helpers. IsCondBranchImm()450 bool IsCondBranchImm() const { 451 return Mask(ConditionalBranchFMask) == ConditionalBranchFixed; 452 } 453 IsUncondBranchImm()454 bool IsUncondBranchImm() const { 455 return Mask(UnconditionalBranchFMask) == UnconditionalBranchFixed; 456 } 457 IsCompareBranch()458 bool IsCompareBranch() const { 459 return Mask(CompareBranchFMask) == CompareBranchFixed; 460 } 461 IsTestBranch()462 bool IsTestBranch() const { return Mask(TestBranchFMask) == TestBranchFixed; } 463 IsImmBranch()464 bool IsImmBranch() const { return GetBranchType() != UnknownBranchType; } 465 IsPCRelAddressing()466 bool IsPCRelAddressing() const { 467 return Mask(PCRelAddressingFMask) == PCRelAddressingFixed; 468 } 469 IsLogicalImmediate()470 bool IsLogicalImmediate() const { 471 return Mask(LogicalImmediateFMask) == LogicalImmediateFixed; 472 } 473 IsAddSubImmediate()474 bool IsAddSubImmediate() const { 475 return Mask(AddSubImmediateFMask) == AddSubImmediateFixed; 476 } 477 IsAddSubExtended()478 bool IsAddSubExtended() const { 479 return Mask(AddSubExtendedFMask) == AddSubExtendedFixed; 480 } 481 IsLoadOrStore()482 bool IsLoadOrStore() const { 483 return Mask(LoadStoreAnyFMask) == LoadStoreAnyFixed; 484 } 485 486 // True if `this` is valid immediately after the provided movprfx instruction. 487 bool CanTakeSVEMovprfx(uint32_t form_hash, Instruction const* movprfx) const; 488 bool CanTakeSVEMovprfx(const char* form, Instruction const* movprfx) const; 489 490 bool IsLoad() const; 491 bool IsStore() const; 492 IsLoadLiteral()493 bool IsLoadLiteral() const { 494 // This includes PRFM_lit. 495 return Mask(LoadLiteralFMask) == LoadLiteralFixed; 496 } 497 IsMovn()498 bool IsMovn() const { 499 return (Mask(MoveWideImmediateMask) == MOVN_x) || 500 (Mask(MoveWideImmediateMask) == MOVN_w); 501 } 502 IsException()503 bool IsException() const { return Mask(ExceptionFMask) == ExceptionFixed; } 504 IsPAuth()505 bool IsPAuth() const { return Mask(SystemPAuthFMask) == SystemPAuthFixed; } 506 IsBti()507 bool IsBti() const { 508 if (Mask(SystemHintFMask) == SystemHintFixed) { 509 int imm_hint = GetImmHint(); 510 switch (imm_hint) { 511 case BTI: 512 case BTI_c: 513 case BTI_j: 514 case BTI_jc: 515 return true; 516 } 517 } 518 return false; 519 } 520 IsMOPSPrologueOf(const Instruction * instr,uint32_t mops_type)521 bool IsMOPSPrologueOf(const Instruction* instr, uint32_t mops_type) const { 522 VIXL_ASSERT((mops_type == "set"_h) || (mops_type == "setg"_h) || 523 (mops_type == "cpy"_h)); 524 const int op_lsb = (mops_type == "cpy"_h) ? 22 : 14; 525 return GetInstructionBits() == instr->Mask(~(0x3U << op_lsb)); 526 } 527 IsMOPSMainOf(const Instruction * instr,uint32_t mops_type)528 bool IsMOPSMainOf(const Instruction* instr, uint32_t mops_type) const { 529 VIXL_ASSERT((mops_type == "set"_h) || (mops_type == "setg"_h) || 530 (mops_type == "cpy"_h)); 531 const int op_lsb = (mops_type == "cpy"_h) ? 22 : 14; 532 return GetInstructionBits() == 533 (instr->Mask(~(0x3U << op_lsb)) | (0x1 << op_lsb)); 534 } 535 IsMOPSEpilogueOf(const Instruction * instr,uint32_t mops_type)536 bool IsMOPSEpilogueOf(const Instruction* instr, uint32_t mops_type) const { 537 VIXL_ASSERT((mops_type == "set"_h) || (mops_type == "setg"_h) || 538 (mops_type == "cpy"_h)); 539 const int op_lsb = (mops_type == "cpy"_h) ? 22 : 14; 540 return GetInstructionBits() == 541 (instr->Mask(~(0x3U << op_lsb)) | (0x2 << op_lsb)); 542 } 543 544 template <uint32_t mops_type> IsConsistentMOPSTriplet()545 bool IsConsistentMOPSTriplet() const { 546 VIXL_STATIC_ASSERT((mops_type == "set"_h) || (mops_type == "setg"_h) || 547 (mops_type == "cpy"_h)); 548 549 int64_t isize = static_cast<int64_t>(kInstructionSize); 550 const Instruction* prev2 = GetInstructionAtOffset(-2 * isize); 551 const Instruction* prev1 = GetInstructionAtOffset(-1 * isize); 552 const Instruction* next1 = GetInstructionAtOffset(1 * isize); 553 const Instruction* next2 = GetInstructionAtOffset(2 * isize); 554 555 // Use the encoding of the current instruction to determine the expected 556 // adjacent instructions. NB. this doesn't check if the nearby instructions 557 // are MOPS-type, but checks that they form a consistent triplet if they 558 // are. For example, 'mov x0, #0; mov x0, #512; mov x0, #1024' is a 559 // consistent triplet, but they are not MOPS instructions. 560 const int op_lsb = (mops_type == "cpy"_h) ? 22 : 14; 561 const uint32_t kMOPSOpfield = 0x3 << op_lsb; 562 const uint32_t kMOPSPrologue = 0; 563 const uint32_t kMOPSMain = 0x1 << op_lsb; 564 const uint32_t kMOPSEpilogue = 0x2 << op_lsb; 565 switch (Mask(kMOPSOpfield)) { 566 case kMOPSPrologue: 567 return next1->IsMOPSMainOf(this, mops_type) && 568 next2->IsMOPSEpilogueOf(this, mops_type); 569 case kMOPSMain: 570 return prev1->IsMOPSPrologueOf(this, mops_type) && 571 next1->IsMOPSEpilogueOf(this, mops_type); 572 case kMOPSEpilogue: 573 return prev2->IsMOPSPrologueOf(this, mops_type) && 574 prev1->IsMOPSMainOf(this, mops_type); 575 default: 576 VIXL_ABORT_WITH_MSG("Undefined MOPS operation\n"); 577 } 578 } 579 580 static int GetImmBranchRangeBitwidth(ImmBranchType branch_type); 581 VIXL_DEPRECATED( 582 "GetImmBranchRangeBitwidth", ImmBranchRangeBitwidth(ImmBranchType branch_type)583 static int ImmBranchRangeBitwidth(ImmBranchType branch_type)) { 584 return GetImmBranchRangeBitwidth(branch_type); 585 } 586 587 static int32_t GetImmBranchForwardRange(ImmBranchType branch_type); 588 VIXL_DEPRECATED( 589 "GetImmBranchForwardRange", 590 static int32_t ImmBranchForwardRange(ImmBranchType branch_type)) { 591 return GetImmBranchForwardRange(branch_type); 592 } 593 594 static bool IsValidImmPCOffset(ImmBranchType branch_type, int64_t offset); 595 596 // Indicate whether Rd can be the stack pointer or the zero register. This 597 // does not check that the instruction actually has an Rd field. GetRdMode()598 Reg31Mode GetRdMode() const { 599 // The following instructions use sp or wsp as Rd: 600 // Add/sub (immediate) when not setting the flags. 601 // Add/sub (extended) when not setting the flags. 602 // Logical (immediate) when not setting the flags. 603 // Otherwise, r31 is the zero register. 604 if (IsAddSubImmediate() || IsAddSubExtended()) { 605 if (Mask(AddSubSetFlagsBit)) { 606 return Reg31IsZeroRegister; 607 } else { 608 return Reg31IsStackPointer; 609 } 610 } 611 if (IsLogicalImmediate()) { 612 // Of the logical (immediate) instructions, only ANDS (and its aliases) 613 // can set the flags. The others can all write into sp. 614 // Note that some logical operations are not available to 615 // immediate-operand instructions, so we have to combine two masks here. 616 if (Mask(LogicalImmediateMask & LogicalOpMask) == ANDS) { 617 return Reg31IsZeroRegister; 618 } else { 619 return Reg31IsStackPointer; 620 } 621 } 622 return Reg31IsZeroRegister; 623 } 624 VIXL_DEPRECATED("GetRdMode", Reg31Mode RdMode() const) { return GetRdMode(); } 625 626 // Indicate whether Rn can be the stack pointer or the zero register. This 627 // does not check that the instruction actually has an Rn field. GetRnMode()628 Reg31Mode GetRnMode() const { 629 // The following instructions use sp or wsp as Rn: 630 // All loads and stores. 631 // Add/sub (immediate). 632 // Add/sub (extended). 633 // Otherwise, r31 is the zero register. 634 if (IsLoadOrStore() || IsAddSubImmediate() || IsAddSubExtended()) { 635 return Reg31IsStackPointer; 636 } 637 return Reg31IsZeroRegister; 638 } 639 VIXL_DEPRECATED("GetRnMode", Reg31Mode RnMode() const) { return GetRnMode(); } 640 GetBranchType()641 ImmBranchType GetBranchType() const { 642 if (IsCondBranchImm()) { 643 return CondBranchType; 644 } else if (IsUncondBranchImm()) { 645 return UncondBranchType; 646 } else if (IsCompareBranch()) { 647 return CompareBranchType; 648 } else if (IsTestBranch()) { 649 return TestBranchType; 650 } else { 651 return UnknownBranchType; 652 } 653 } 654 VIXL_DEPRECATED("GetBranchType", ImmBranchType BranchType() const) { 655 return GetBranchType(); 656 } 657 658 // Find the target of this instruction. 'this' may be a branch or a 659 // PC-relative addressing instruction. 660 const Instruction* GetImmPCOffsetTarget() const; 661 VIXL_DEPRECATED("GetImmPCOffsetTarget", 662 const Instruction* ImmPCOffsetTarget() const) { 663 return GetImmPCOffsetTarget(); 664 } 665 666 // Patch a PC-relative offset to refer to 'target'. 'this' may be a branch or 667 // a PC-relative addressing instruction. 668 void SetImmPCOffsetTarget(const Instruction* target); 669 // Patch a literal load instruction to load from 'source'. 670 void SetImmLLiteral(const Instruction* source); 671 672 // The range of a load literal instruction, expressed as 'instr +- range'. 673 // The range is actually the 'positive' range; the branch instruction can 674 // target [instr - range - kInstructionSize, instr + range]. 675 static const int kLoadLiteralImmBitwidth = 19; 676 static const int kLoadLiteralRange = 677 (1 << kLoadLiteralImmBitwidth) / 2 - kInstructionSize; 678 679 // Calculate the address of a literal referred to by a load-literal 680 // instruction, and return it as the specified type. 681 // 682 // The literal itself is safely mutable only if the backing buffer is safely 683 // mutable. 684 template <typename T> GetLiteralAddress()685 T GetLiteralAddress() const { 686 uint64_t base_raw = reinterpret_cast<uint64_t>(this); 687 int64_t offset = GetImmLLiteral() * static_cast<int>(kLiteralEntrySize); 688 uint64_t address_raw = base_raw + offset; 689 690 // Cast the address using a C-style cast. A reinterpret_cast would be 691 // appropriate, but it can't cast one integral type to another. 692 T address = (T)(address_raw); 693 694 // Assert that the address can be represented by the specified type. 695 VIXL_ASSERT((uint64_t)(address) == address_raw); 696 697 return address; 698 } 699 template <typename T> 700 VIXL_DEPRECATED("GetLiteralAddress", T LiteralAddress() const) { 701 return GetLiteralAddress<T>(); 702 } 703 GetLiteral32()704 uint32_t GetLiteral32() const { 705 uint32_t literal; 706 memcpy(&literal, GetLiteralAddress<const void*>(), sizeof(literal)); 707 return literal; 708 } 709 VIXL_DEPRECATED("GetLiteral32", uint32_t Literal32() const) { 710 return GetLiteral32(); 711 } 712 GetLiteral64()713 uint64_t GetLiteral64() const { 714 uint64_t literal; 715 memcpy(&literal, GetLiteralAddress<const void*>(), sizeof(literal)); 716 return literal; 717 } 718 VIXL_DEPRECATED("GetLiteral64", uint64_t Literal64() const) { 719 return GetLiteral64(); 720 } 721 GetLiteralFP32()722 float GetLiteralFP32() const { return RawbitsToFloat(GetLiteral32()); } LiteralFP32()723 VIXL_DEPRECATED("GetLiteralFP32", float LiteralFP32() const) { 724 return GetLiteralFP32(); 725 } 726 GetLiteralFP64()727 double GetLiteralFP64() const { return RawbitsToDouble(GetLiteral64()); } LiteralFP64()728 VIXL_DEPRECATED("GetLiteralFP64", double LiteralFP64() const) { 729 return GetLiteralFP64(); 730 } 731 GetNextInstruction()732 Instruction* GetNextInstruction() { return this + kInstructionSize; } GetNextInstruction()733 const Instruction* GetNextInstruction() const { 734 return this + kInstructionSize; 735 } 736 VIXL_DEPRECATED("GetNextInstruction", 737 const Instruction* NextInstruction() const) { 738 return GetNextInstruction(); 739 } 740 GetInstructionAtOffset(int64_t offset)741 const Instruction* GetInstructionAtOffset(int64_t offset) const { 742 VIXL_ASSERT(IsWordAligned(this + offset)); 743 return this + offset; 744 } 745 VIXL_DEPRECATED("GetInstructionAtOffset", 746 const Instruction* InstructionAtOffset(int64_t offset) 747 const) { 748 return GetInstructionAtOffset(offset); 749 } 750 751 template <typename T> Cast(T src)752 static Instruction* Cast(T src) { 753 return reinterpret_cast<Instruction*>(src); 754 } 755 756 template <typename T> CastConst(T src)757 static const Instruction* CastConst(T src) { 758 return reinterpret_cast<const Instruction*>(src); 759 } 760 761 private: 762 int GetImmBranch() const; 763 764 void SetPCRelImmTarget(const Instruction* target); 765 void SetBranchImmTarget(const Instruction* target); 766 }; 767 768 769 // Functions for handling NEON and SVE vector format information. 770 771 const int kMaxLanesPerVector = 16; 772 773 VectorFormat VectorFormatHalfWidth(VectorFormat vform); 774 VectorFormat VectorFormatDoubleWidth(VectorFormat vform); 775 VectorFormat VectorFormatDoubleLanes(VectorFormat vform); 776 VectorFormat VectorFormatHalfLanes(VectorFormat vform); 777 VectorFormat ScalarFormatFromLaneSize(int lane_size_in_bits); 778 VectorFormat VectorFormatHalfWidthDoubleLanes(VectorFormat vform); 779 VectorFormat VectorFormatFillQ(VectorFormat vform); 780 VectorFormat ScalarFormatFromFormat(VectorFormat vform); 781 VectorFormat SVEFormatFromLaneSizeInBits(int lane_size_in_bits); 782 VectorFormat SVEFormatFromLaneSizeInBytes(int lane_size_in_bytes); 783 VectorFormat SVEFormatFromLaneSizeInBytesLog2(int lane_size_in_bytes_log_2); 784 unsigned RegisterSizeInBitsFromFormat(VectorFormat vform); 785 unsigned RegisterSizeInBytesFromFormat(VectorFormat vform); 786 bool IsSVEFormat(VectorFormat vform); 787 // TODO: Make the return types of these functions consistent. 788 unsigned LaneSizeInBitsFromFormat(VectorFormat vform); 789 int LaneSizeInBytesFromFormat(VectorFormat vform); 790 int LaneSizeInBytesLog2FromFormat(VectorFormat vform); 791 int LaneCountFromFormat(VectorFormat vform); 792 int MaxLaneCountFromFormat(VectorFormat vform); 793 bool IsVectorFormat(VectorFormat vform); 794 int64_t MaxIntFromFormat(VectorFormat vform); 795 int64_t MinIntFromFormat(VectorFormat vform); 796 uint64_t MaxUintFromFormat(VectorFormat vform); 797 798 799 // clang-format off 800 enum NEONFormat { 801 NF_UNDEF = 0, 802 NF_8B = 1, 803 NF_16B = 2, 804 NF_4H = 3, 805 NF_8H = 4, 806 NF_2S = 5, 807 NF_4S = 6, 808 NF_1D = 7, 809 NF_2D = 8, 810 NF_B = 9, 811 NF_H = 10, 812 NF_S = 11, 813 NF_D = 12 814 }; 815 // clang-format on 816 817 static const unsigned kNEONFormatMaxBits = 6; 818 819 struct NEONFormatMap { 820 // The bit positions in the instruction to consider. 821 uint8_t bits[kNEONFormatMaxBits]; 822 823 // Mapping from concatenated bits to format. 824 NEONFormat map[1 << kNEONFormatMaxBits]; 825 }; 826 827 class NEONFormatDecoder { 828 public: 829 enum SubstitutionMode { kPlaceholder, kFormat }; 830 831 // Construct a format decoder with increasingly specific format maps for each 832 // substitution. If no format map is specified, the default is the integer 833 // format map. NEONFormatDecoder(const Instruction * instr)834 explicit NEONFormatDecoder(const Instruction* instr) { 835 instrbits_ = instr->GetInstructionBits(); 836 SetFormatMaps(IntegerFormatMap()); 837 } NEONFormatDecoder(const Instruction * instr,const NEONFormatMap * format)838 NEONFormatDecoder(const Instruction* instr, const NEONFormatMap* format) { 839 instrbits_ = instr->GetInstructionBits(); 840 SetFormatMaps(format); 841 } NEONFormatDecoder(const Instruction * instr,const NEONFormatMap * format0,const NEONFormatMap * format1)842 NEONFormatDecoder(const Instruction* instr, 843 const NEONFormatMap* format0, 844 const NEONFormatMap* format1) { 845 instrbits_ = instr->GetInstructionBits(); 846 SetFormatMaps(format0, format1); 847 } NEONFormatDecoder(const Instruction * instr,const NEONFormatMap * format0,const NEONFormatMap * format1,const NEONFormatMap * format2)848 NEONFormatDecoder(const Instruction* instr, 849 const NEONFormatMap* format0, 850 const NEONFormatMap* format1, 851 const NEONFormatMap* format2) { 852 instrbits_ = instr->GetInstructionBits(); 853 SetFormatMaps(format0, format1, format2); 854 } 855 856 // Set the format mapping for all or individual substitutions. 857 void SetFormatMaps(const NEONFormatMap* format0, 858 const NEONFormatMap* format1 = NULL, 859 const NEONFormatMap* format2 = NULL, 860 const NEONFormatMap* format3 = NULL) { 861 VIXL_ASSERT(format0 != NULL); 862 formats_[0] = format0; 863 formats_[1] = (format1 == NULL) ? formats_[0] : format1; 864 formats_[2] = (format2 == NULL) ? formats_[1] : format2; 865 formats_[3] = (format3 == NULL) ? formats_[2] : format3; 866 } SetFormatMap(unsigned index,const NEONFormatMap * format)867 void SetFormatMap(unsigned index, const NEONFormatMap* format) { 868 VIXL_ASSERT(index <= ArrayLength(formats_)); 869 VIXL_ASSERT(format != NULL); 870 formats_[index] = format; 871 } 872 873 // Substitute %s in the input string with the placeholder string for each 874 // register, ie. "'B", "'H", etc. SubstitutePlaceholders(const char * string)875 const char* SubstitutePlaceholders(const char* string) { 876 return Substitute(string, kPlaceholder, kPlaceholder, kPlaceholder); 877 } 878 879 // Substitute %s in the input string with a new string based on the 880 // substitution mode. 881 const char* Substitute(const char* string, 882 SubstitutionMode mode0 = kFormat, 883 SubstitutionMode mode1 = kFormat, 884 SubstitutionMode mode2 = kFormat, 885 SubstitutionMode mode3 = kFormat) { 886 const char* subst0 = GetSubstitute(0, mode0); 887 const char* subst1 = GetSubstitute(1, mode1); 888 const char* subst2 = GetSubstitute(2, mode2); 889 const char* subst3 = GetSubstitute(3, mode3); 890 891 if ((subst0 == NULL) || (subst1 == NULL) || (subst2 == NULL) || 892 (subst3 == NULL)) { 893 return NULL; 894 } 895 896 snprintf(form_buffer_, 897 sizeof(form_buffer_), 898 string, 899 subst0, 900 subst1, 901 subst2, 902 subst3); 903 return form_buffer_; 904 } 905 906 // Append a "2" to a mnemonic string based on the state of the Q bit. Mnemonic(const char * mnemonic)907 const char* Mnemonic(const char* mnemonic) { 908 if ((mnemonic != NULL) && (instrbits_ & NEON_Q) != 0) { 909 snprintf(mne_buffer_, sizeof(mne_buffer_), "%s2", mnemonic); 910 return mne_buffer_; 911 } 912 return mnemonic; 913 } 914 915 VectorFormat GetVectorFormat(int format_index = 0) { 916 return GetVectorFormat(formats_[format_index]); 917 } 918 GetVectorFormat(const NEONFormatMap * format_map)919 VectorFormat GetVectorFormat(const NEONFormatMap* format_map) { 920 static const VectorFormat vform[] = {kFormatUndefined, 921 kFormat8B, 922 kFormat16B, 923 kFormat4H, 924 kFormat8H, 925 kFormat2S, 926 kFormat4S, 927 kFormat1D, 928 kFormat2D, 929 kFormatB, 930 kFormatH, 931 kFormatS, 932 kFormatD}; 933 VIXL_ASSERT(GetNEONFormat(format_map) < ArrayLength(vform)); 934 return vform[GetNEONFormat(format_map)]; 935 } 936 937 // Built in mappings for common cases. 938 939 // The integer format map uses three bits (Q, size<1:0>) to encode the 940 // "standard" set of NEON integer vector formats. IntegerFormatMap()941 static const NEONFormatMap* IntegerFormatMap() { 942 static const NEONFormatMap map = 943 {{23, 22, 30}, 944 {NF_8B, NF_16B, NF_4H, NF_8H, NF_2S, NF_4S, NF_UNDEF, NF_2D}}; 945 return ↦ 946 } 947 948 // The long integer format map uses two bits (size<1:0>) to encode the 949 // long set of NEON integer vector formats. These are used in narrow, wide 950 // and long operations. LongIntegerFormatMap()951 static const NEONFormatMap* LongIntegerFormatMap() { 952 static const NEONFormatMap map = {{23, 22}, {NF_8H, NF_4S, NF_2D}}; 953 return ↦ 954 } 955 956 // The FP format map uses two bits (Q, size<0>) to encode the NEON FP vector 957 // formats: NF_2S, NF_4S, NF_2D. FPFormatMap()958 static const NEONFormatMap* FPFormatMap() { 959 // The FP format map assumes two bits (Q, size<0>) are used to encode the 960 // NEON FP vector formats: NF_2S, NF_4S, NF_2D. 961 static const NEONFormatMap map = {{22, 30}, 962 {NF_2S, NF_4S, NF_UNDEF, NF_2D}}; 963 return ↦ 964 } 965 966 // The FP16 format map uses one bit (Q) to encode the NEON vector format: 967 // NF_4H, NF_8H. FP16FormatMap()968 static const NEONFormatMap* FP16FormatMap() { 969 static const NEONFormatMap map = {{30}, {NF_4H, NF_8H}}; 970 return ↦ 971 } 972 973 // The load/store format map uses three bits (Q, 11, 10) to encode the 974 // set of NEON vector formats. LoadStoreFormatMap()975 static const NEONFormatMap* LoadStoreFormatMap() { 976 static const NEONFormatMap map = 977 {{11, 10, 30}, 978 {NF_8B, NF_16B, NF_4H, NF_8H, NF_2S, NF_4S, NF_1D, NF_2D}}; 979 return ↦ 980 } 981 982 // The logical format map uses one bit (Q) to encode the NEON vector format: 983 // NF_8B, NF_16B. LogicalFormatMap()984 static const NEONFormatMap* LogicalFormatMap() { 985 static const NEONFormatMap map = {{30}, {NF_8B, NF_16B}}; 986 return ↦ 987 } 988 989 // The triangular format map uses between two and five bits to encode the NEON 990 // vector format: 991 // xxx10->8B, xxx11->16B, xx100->4H, xx101->8H 992 // x1000->2S, x1001->4S, 10001->2D, all others undefined. TriangularFormatMap()993 static const NEONFormatMap* TriangularFormatMap() { 994 static const NEONFormatMap map = 995 {{19, 18, 17, 16, 30}, 996 {NF_UNDEF, NF_UNDEF, NF_8B, NF_16B, NF_4H, NF_8H, NF_8B, NF_16B, 997 NF_2S, NF_4S, NF_8B, NF_16B, NF_4H, NF_8H, NF_8B, NF_16B, 998 NF_UNDEF, NF_2D, NF_8B, NF_16B, NF_4H, NF_8H, NF_8B, NF_16B, 999 NF_2S, NF_4S, NF_8B, NF_16B, NF_4H, NF_8H, NF_8B, NF_16B}}; 1000 return ↦ 1001 } 1002 1003 // The shift immediate map uses between two and five bits to encode the NEON 1004 // vector format: 1005 // 00010->8B, 00011->16B, 001x0->4H, 001x1->8H, 1006 // 01xx0->2S, 01xx1->4S, 1xxx1->2D, all others undefined. ShiftImmFormatMap()1007 static const NEONFormatMap* ShiftImmFormatMap() { 1008 static const NEONFormatMap map = {{22, 21, 20, 19, 30}, 1009 {NF_UNDEF, NF_UNDEF, NF_8B, NF_16B, 1010 NF_4H, NF_8H, NF_4H, NF_8H, 1011 NF_2S, NF_4S, NF_2S, NF_4S, 1012 NF_2S, NF_4S, NF_2S, NF_4S, 1013 NF_UNDEF, NF_2D, NF_UNDEF, NF_2D, 1014 NF_UNDEF, NF_2D, NF_UNDEF, NF_2D, 1015 NF_UNDEF, NF_2D, NF_UNDEF, NF_2D, 1016 NF_UNDEF, NF_2D, NF_UNDEF, NF_2D}}; 1017 return ↦ 1018 } 1019 1020 // The shift long/narrow immediate map uses between two and four bits to 1021 // encode the NEON vector format: 1022 // 0001->8H, 001x->4S, 01xx->2D, all others undefined. ShiftLongNarrowImmFormatMap()1023 static const NEONFormatMap* ShiftLongNarrowImmFormatMap() { 1024 static const NEONFormatMap map = 1025 {{22, 21, 20, 19}, 1026 {NF_UNDEF, NF_8H, NF_4S, NF_4S, NF_2D, NF_2D, NF_2D, NF_2D}}; 1027 return ↦ 1028 } 1029 1030 // The scalar format map uses two bits (size<1:0>) to encode the NEON scalar 1031 // formats: NF_B, NF_H, NF_S, NF_D. ScalarFormatMap()1032 static const NEONFormatMap* ScalarFormatMap() { 1033 static const NEONFormatMap map = {{23, 22}, {NF_B, NF_H, NF_S, NF_D}}; 1034 return ↦ 1035 } 1036 1037 // The long scalar format map uses two bits (size<1:0>) to encode the longer 1038 // NEON scalar formats: NF_H, NF_S, NF_D. LongScalarFormatMap()1039 static const NEONFormatMap* LongScalarFormatMap() { 1040 static const NEONFormatMap map = {{23, 22}, {NF_H, NF_S, NF_D}}; 1041 return ↦ 1042 } 1043 1044 // The FP scalar format map assumes one bit (size<0>) is used to encode the 1045 // NEON FP scalar formats: NF_S, NF_D. FPScalarFormatMap()1046 static const NEONFormatMap* FPScalarFormatMap() { 1047 static const NEONFormatMap map = {{22}, {NF_S, NF_D}}; 1048 return ↦ 1049 } 1050 1051 // The FP scalar pairwise format map assumes two bits (U, size<0>) are used to 1052 // encode the NEON FP scalar formats: NF_H, NF_S, NF_D. FPScalarPairwiseFormatMap()1053 static const NEONFormatMap* FPScalarPairwiseFormatMap() { 1054 static const NEONFormatMap map = {{29, 22}, {NF_H, NF_UNDEF, NF_S, NF_D}}; 1055 return ↦ 1056 } 1057 1058 // The triangular scalar format map uses between one and four bits to encode 1059 // the NEON FP scalar formats: 1060 // xxx1->B, xx10->H, x100->S, 1000->D, all others undefined. TriangularScalarFormatMap()1061 static const NEONFormatMap* TriangularScalarFormatMap() { 1062 static const NEONFormatMap map = {{19, 18, 17, 16}, 1063 {NF_UNDEF, 1064 NF_B, 1065 NF_H, 1066 NF_B, 1067 NF_S, 1068 NF_B, 1069 NF_H, 1070 NF_B, 1071 NF_D, 1072 NF_B, 1073 NF_H, 1074 NF_B, 1075 NF_S, 1076 NF_B, 1077 NF_H, 1078 NF_B}}; 1079 return ↦ 1080 } 1081 1082 private: 1083 // Get a pointer to a string that represents the format or placeholder for 1084 // the specified substitution index, based on the format map and instruction. GetSubstitute(int index,SubstitutionMode mode)1085 const char* GetSubstitute(int index, SubstitutionMode mode) { 1086 if (mode == kFormat) { 1087 return NEONFormatAsString(GetNEONFormat(formats_[index])); 1088 } 1089 VIXL_ASSERT(mode == kPlaceholder); 1090 return NEONFormatAsPlaceholder(GetNEONFormat(formats_[index])); 1091 } 1092 1093 // Get the NEONFormat enumerated value for bits obtained from the 1094 // instruction based on the specified format mapping. GetNEONFormat(const NEONFormatMap * format_map)1095 NEONFormat GetNEONFormat(const NEONFormatMap* format_map) { 1096 return format_map->map[PickBits(format_map->bits)]; 1097 } 1098 1099 // Convert a NEONFormat into a string. NEONFormatAsString(NEONFormat format)1100 static const char* NEONFormatAsString(NEONFormat format) { 1101 // clang-format off 1102 static const char* formats[] = { 1103 NULL, 1104 "8b", "16b", "4h", "8h", "2s", "4s", "1d", "2d", 1105 "b", "h", "s", "d" 1106 }; 1107 // clang-format on 1108 VIXL_ASSERT(format < ArrayLength(formats)); 1109 return formats[format]; 1110 } 1111 1112 // Convert a NEONFormat into a register placeholder string. NEONFormatAsPlaceholder(NEONFormat format)1113 static const char* NEONFormatAsPlaceholder(NEONFormat format) { 1114 VIXL_ASSERT((format == NF_B) || (format == NF_H) || (format == NF_S) || 1115 (format == NF_D) || (format == NF_UNDEF)); 1116 // clang-format off 1117 static const char* formats[] = { 1118 NULL, 1119 NULL, NULL, NULL, NULL, 1120 NULL, NULL, NULL, NULL, 1121 "'B", "'H", "'S", "'D" 1122 }; 1123 // clang-format on 1124 return formats[format]; 1125 } 1126 1127 // Select bits from instrbits_ defined by the bits array, concatenate them, 1128 // and return the value. PickBits(const uint8_t bits[])1129 uint8_t PickBits(const uint8_t bits[]) { 1130 uint8_t result = 0; 1131 for (unsigned b = 0; b < kNEONFormatMaxBits; b++) { 1132 if (bits[b] == 0) break; 1133 result <<= 1; 1134 result |= ((instrbits_ & (1 << bits[b])) == 0) ? 0 : 1; 1135 } 1136 return result; 1137 } 1138 1139 Instr instrbits_; 1140 const NEONFormatMap* formats_[4]; 1141 char form_buffer_[64]; 1142 char mne_buffer_[16]; 1143 }; 1144 } // namespace aarch64 1145 } // namespace vixl 1146 1147 #endif // VIXL_AARCH64_INSTRUCTIONS_AARCH64_H_ 1148