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 // An artificial value, used by simulator trace tests and a few oddball 221 // instructions (such as FMLAL). 222 kFormat2H = 0xfffffffe 223 }; 224 225 // Instructions. --------------------------------------------------------------- 226 227 class Instruction { 228 public: GetInstructionBits() const229 Instr GetInstructionBits() const { 230 return *(reinterpret_cast<const Instr*>(this)); 231 } 232 VIXL_DEPRECATED("GetInstructionBits", Instr InstructionBits() const) { 233 return GetInstructionBits(); 234 } 235 SetInstructionBits(Instr new_instr)236 void SetInstructionBits(Instr new_instr) { 237 *(reinterpret_cast<Instr*>(this)) = new_instr; 238 } 239 ExtractBit(int pos) const240 int ExtractBit(int pos) const { return (GetInstructionBits() >> pos) & 1; } 241 VIXL_DEPRECATED("ExtractBit", int Bit(int pos) const) { 242 return ExtractBit(pos); 243 } 244 ExtractBits(int msb, int lsb) const245 uint32_t ExtractBits(int msb, int lsb) const { 246 return ExtractUnsignedBitfield32(msb, lsb, GetInstructionBits()); 247 } 248 VIXL_DEPRECATED("ExtractBits", uint32_t Bits(int msb, int lsb) const) { 249 return ExtractBits(msb, lsb); 250 } 251 252 // Compress bit extraction operation from Hacker's Delight. 253 // https://github.com/hcs0/Hackers-Delight/blob/master/compress.c.txt Compress(uint32_t mask) const254 uint32_t Compress(uint32_t mask) const { 255 uint32_t mk, mp, mv, t; 256 uint32_t x = GetInstructionBits() & mask; // Clear irrelevant bits. 257 mk = ~mask << 1; // We will count 0's to right. 258 for (int i = 0; i < 5; i++) { 259 mp = mk ^ (mk << 1); // Parallel suffix. 260 mp = mp ^ (mp << 2); 261 mp = mp ^ (mp << 4); 262 mp = mp ^ (mp << 8); 263 mp = mp ^ (mp << 16); 264 mv = mp & mask; // Bits to move. 265 mask = (mask ^ mv) | (mv >> (1 << i)); // Compress mask. 266 t = x & mv; 267 x = (x ^ t) | (t >> (1 << i)); // Compress x. 268 mk = mk & ~mp; 269 } 270 return x; 271 } 272 273 template <uint32_t M> ExtractBits() const274 uint32_t ExtractBits() const { 275 return Compress(M); 276 } 277 ExtractBitsAbsent() const278 uint32_t ExtractBitsAbsent() const { 279 VIXL_UNREACHABLE(); 280 return 0; 281 } 282 283 template <uint32_t M, uint32_t V> IsMaskedValue() const284 uint32_t IsMaskedValue() const { 285 return (Mask(M) == V) ? 1 : 0; 286 } 287 IsMaskedValueAbsent() const288 uint32_t IsMaskedValueAbsent() const { 289 VIXL_UNREACHABLE(); 290 return 0; 291 } 292 ExtractSignedBits(int msb, int lsb) const293 int32_t ExtractSignedBits(int msb, int lsb) const { 294 int32_t bits = *(reinterpret_cast<const int32_t*>(this)); 295 return ExtractSignedBitfield32(msb, lsb, bits); 296 } 297 VIXL_DEPRECATED("ExtractSignedBits", 298 int32_t SignedBits(int msb, int lsb) const) { 299 return ExtractSignedBits(msb, lsb); 300 } 301 Mask(uint32_t mask) const302 Instr Mask(uint32_t mask) const { 303 VIXL_ASSERT(mask != 0); 304 return GetInstructionBits() & mask; 305 } 306 307 #define DEFINE_GETTER(Name, HighBit, LowBit, Func) \ 308 int32_t Get##Name() const { return this->Func(HighBit, LowBit); } \ 309 VIXL_DEPRECATED("Get" #Name, int32_t Name() const) { return Get##Name(); } 310 INSTRUCTION_FIELDS_LIST(DEFINE_GETTER) 311 #undef DEFINE_GETTER 312 313 template <int msb, int lsb> GetRx() const314 int32_t GetRx() const { 315 // We don't have any register fields wider than five bits, so the result 316 // will always fit into an int32_t. 317 VIXL_ASSERT((msb - lsb + 1) <= 5); 318 return this->ExtractBits(msb, lsb); 319 } 320 GetSVEVectorFormat(int field_lsb = 22) const321 VectorFormat GetSVEVectorFormat(int field_lsb = 22) const { 322 VIXL_ASSERT((field_lsb >= 0) && (field_lsb <= 30)); 323 uint32_t instr = ExtractUnsignedBitfield32(field_lsb + 1, 324 field_lsb, 325 GetInstructionBits()) 326 << 22; 327 switch (instr & SVESizeFieldMask) { 328 case SVE_B: 329 return kFormatVnB; 330 case SVE_H: 331 return kFormatVnH; 332 case SVE_S: 333 return kFormatVnS; 334 case SVE_D: 335 return kFormatVnD; 336 } 337 VIXL_UNREACHABLE(); 338 return kFormatUndefined; 339 } 340 341 // ImmPCRel is a compound field (not present in INSTRUCTION_FIELDS_LIST), 342 // formed from ImmPCRelLo and ImmPCRelHi. GetImmPCRel() const343 int GetImmPCRel() const { 344 uint32_t hi = static_cast<uint32_t>(GetImmPCRelHi()); 345 uint32_t lo = GetImmPCRelLo(); 346 uint32_t offset = (hi << ImmPCRelLo_width) | lo; 347 int width = ImmPCRelLo_width + ImmPCRelHi_width; 348 return ExtractSignedBitfield32(width - 1, 0, offset); 349 } 350 VIXL_DEPRECATED("GetImmPCRel", int ImmPCRel() const) { return GetImmPCRel(); } 351 352 // ImmLSPAC is a compound field (not present in INSTRUCTION_FIELDS_LIST), 353 // formed from ImmLSPACLo and ImmLSPACHi. GetImmLSPAC() const354 int GetImmLSPAC() const { 355 uint32_t hi = static_cast<uint32_t>(GetImmLSPACHi()); 356 uint32_t lo = GetImmLSPACLo(); 357 uint32_t offset = (hi << ImmLSPACLo_width) | lo; 358 int width = ImmLSPACLo_width + ImmLSPACHi_width; 359 return ExtractSignedBitfield32(width - 1, 0, offset) << 3; 360 } 361 362 uint64_t GetImmLogical() const; 363 VIXL_DEPRECATED("GetImmLogical", uint64_t ImmLogical() const) { 364 return GetImmLogical(); 365 } 366 uint64_t GetSVEImmLogical() const; 367 int GetSVEBitwiseImmLaneSizeInBytesLog2() const; 368 uint64_t DecodeImmBitMask(int32_t n, 369 int32_t imm_s, 370 int32_t imm_r, 371 int32_t size) const; 372 373 std::pair<int, int> GetSVEPermuteIndexAndLaneSizeLog2() const; 374 375 std::pair<int, int> GetSVEMulZmAndIndex() const; 376 std::pair<int, int> GetSVEMulLongZmAndIndex() const; 377 378 std::pair<int, int> GetSVEImmShiftAndLaneSizeLog2(bool is_predicated) const; 379 380 int GetSVEExtractImmediate() const; 381 382 int GetSVEMsizeFromDtype(bool is_signed, int dtype_h_lsb = 23) const; 383 384 int GetSVEEsizeFromDtype(bool is_signed, int dtype_l_lsb = 21) const; 385 386 387 unsigned GetImmNEONabcdefgh() const; 388 VIXL_DEPRECATED("GetImmNEONabcdefgh", unsigned ImmNEONabcdefgh() const) { 389 return GetImmNEONabcdefgh(); 390 } 391 392 Float16 GetImmFP16() const; 393 394 float GetImmFP32() const; 395 VIXL_DEPRECATED("GetImmFP32", float ImmFP32() const) { return GetImmFP32(); } 396 397 double GetImmFP64() const; 398 VIXL_DEPRECATED("GetImmFP64", double ImmFP64() const) { return GetImmFP64(); } 399 400 Float16 GetImmNEONFP16() const; 401 402 float GetImmNEONFP32() const; 403 VIXL_DEPRECATED("GetImmNEONFP32", float ImmNEONFP32() const) { 404 return GetImmNEONFP32(); 405 } 406 407 double GetImmNEONFP64() const; 408 VIXL_DEPRECATED("GetImmNEONFP64", double ImmNEONFP64() const) { 409 return GetImmNEONFP64(); 410 } 411 GetSVEImmFP16() const412 Float16 GetSVEImmFP16() const { return Imm8ToFloat16(ExtractBits(12, 5)); } 413 GetSVEImmFP32() const414 float GetSVEImmFP32() const { return Imm8ToFP32(ExtractBits(12, 5)); } 415 GetSVEImmFP64() const416 double GetSVEImmFP64() const { return Imm8ToFP64(ExtractBits(12, 5)); } 417 418 static Float16 Imm8ToFloat16(uint32_t imm8); 419 static float Imm8ToFP32(uint32_t imm8); 420 static double Imm8ToFP64(uint32_t imm8); 421 GetSizeLS() const422 unsigned GetSizeLS() const { 423 return CalcLSDataSize(static_cast<LoadStoreOp>(Mask(LoadStoreMask))); 424 } 425 VIXL_DEPRECATED("GetSizeLS", unsigned SizeLS() const) { return GetSizeLS(); } 426 GetSizeLSPair() const427 unsigned GetSizeLSPair() const { 428 return CalcLSPairDataSize( 429 static_cast<LoadStorePairOp>(Mask(LoadStorePairMask))); 430 } 431 VIXL_DEPRECATED("GetSizeLSPair", unsigned SizeLSPair() const) { 432 return GetSizeLSPair(); 433 } 434 GetNEONLSIndex(int access_size_shift) const435 int GetNEONLSIndex(int access_size_shift) const { 436 int64_t q = GetNEONQ(); 437 int64_t s = GetNEONS(); 438 int64_t size = GetNEONLSSize(); 439 int64_t index = (q << 3) | (s << 2) | size; 440 return static_cast<int>(index >> access_size_shift); 441 } 442 VIXL_DEPRECATED("GetNEONLSIndex", 443 int NEONLSIndex(int access_size_shift) const) { 444 return GetNEONLSIndex(access_size_shift); 445 } 446 447 // Helpers. IsCondBranchImm() const448 bool IsCondBranchImm() const { 449 return Mask(ConditionalBranchFMask) == ConditionalBranchFixed; 450 } 451 IsUncondBranchImm() const452 bool IsUncondBranchImm() const { 453 return Mask(UnconditionalBranchFMask) == UnconditionalBranchFixed; 454 } 455 IsCompareBranch() const456 bool IsCompareBranch() const { 457 return Mask(CompareBranchFMask) == CompareBranchFixed; 458 } 459 IsTestBranch() const460 bool IsTestBranch() const { return Mask(TestBranchFMask) == TestBranchFixed; } 461 IsImmBranch() const462 bool IsImmBranch() const { return GetBranchType() != UnknownBranchType; } 463 IsPCRelAddressing() const464 bool IsPCRelAddressing() const { 465 return Mask(PCRelAddressingFMask) == PCRelAddressingFixed; 466 } 467 IsLogicalImmediate() const468 bool IsLogicalImmediate() const { 469 return Mask(LogicalImmediateFMask) == LogicalImmediateFixed; 470 } 471 IsAddSubImmediate() const472 bool IsAddSubImmediate() const { 473 return Mask(AddSubImmediateFMask) == AddSubImmediateFixed; 474 } 475 IsAddSubExtended() const476 bool IsAddSubExtended() const { 477 return Mask(AddSubExtendedFMask) == AddSubExtendedFixed; 478 } 479 IsLoadOrStore() const480 bool IsLoadOrStore() const { 481 return Mask(LoadStoreAnyFMask) == LoadStoreAnyFixed; 482 } 483 484 // True if `this` is valid immediately after the provided movprfx instruction. 485 bool CanTakeSVEMovprfx(uint32_t form_hash, Instruction const* movprfx) const; 486 bool CanTakeSVEMovprfx(const char* form, Instruction const* movprfx) const; 487 488 bool IsLoad() const; 489 bool IsStore() const; 490 IsLoadLiteral() const491 bool IsLoadLiteral() const { 492 // This includes PRFM_lit. 493 return Mask(LoadLiteralFMask) == LoadLiteralFixed; 494 } 495 IsMovn() const496 bool IsMovn() const { 497 return (Mask(MoveWideImmediateMask) == MOVN_x) || 498 (Mask(MoveWideImmediateMask) == MOVN_w); 499 } 500 IsException() const501 bool IsException() const { return Mask(ExceptionFMask) == ExceptionFixed; } 502 IsPAuth() const503 bool IsPAuth() const { return Mask(SystemPAuthFMask) == SystemPAuthFixed; } 504 IsBti() const505 bool IsBti() const { 506 if (Mask(SystemHintFMask) == SystemHintFixed) { 507 int imm_hint = GetImmHint(); 508 switch (imm_hint) { 509 case BTI: 510 case BTI_c: 511 case BTI_j: 512 case BTI_jc: 513 return true; 514 } 515 } 516 return false; 517 } 518 IsMOPSPrologueOf(const Instruction* instr, uint32_t mops_type) const519 bool IsMOPSPrologueOf(const Instruction* instr, uint32_t mops_type) const { 520 VIXL_ASSERT((mops_type == "set"_h) || (mops_type == "setg"_h) || 521 (mops_type == "cpy"_h)); 522 const int op_lsb = (mops_type == "cpy"_h) ? 22 : 14; 523 return GetInstructionBits() == instr->Mask(~(0x3U << op_lsb)); 524 } 525 IsMOPSMainOf(const Instruction* instr, uint32_t mops_type) const526 bool IsMOPSMainOf(const Instruction* instr, uint32_t mops_type) const { 527 VIXL_ASSERT((mops_type == "set"_h) || (mops_type == "setg"_h) || 528 (mops_type == "cpy"_h)); 529 const int op_lsb = (mops_type == "cpy"_h) ? 22 : 14; 530 return GetInstructionBits() == 531 (instr->Mask(~(0x3U << op_lsb)) | (0x1 << op_lsb)); 532 } 533 IsMOPSEpilogueOf(const Instruction* instr, uint32_t mops_type) const534 bool IsMOPSEpilogueOf(const Instruction* instr, uint32_t mops_type) const { 535 VIXL_ASSERT((mops_type == "set"_h) || (mops_type == "setg"_h) || 536 (mops_type == "cpy"_h)); 537 const int op_lsb = (mops_type == "cpy"_h) ? 22 : 14; 538 return GetInstructionBits() == 539 (instr->Mask(~(0x3U << op_lsb)) | (0x2 << op_lsb)); 540 } 541 542 template <uint32_t mops_type> IsConsistentMOPSTriplet() const543 bool IsConsistentMOPSTriplet() const { 544 VIXL_STATIC_ASSERT((mops_type == "set"_h) || (mops_type == "setg"_h) || 545 (mops_type == "cpy"_h)); 546 547 int64_t isize = static_cast<int64_t>(kInstructionSize); 548 const Instruction* prev2 = GetInstructionAtOffset(-2 * isize); 549 const Instruction* prev1 = GetInstructionAtOffset(-1 * isize); 550 const Instruction* next1 = GetInstructionAtOffset(1 * isize); 551 const Instruction* next2 = GetInstructionAtOffset(2 * isize); 552 553 // Use the encoding of the current instruction to determine the expected 554 // adjacent instructions. NB. this doesn't check if the nearby instructions 555 // are MOPS-type, but checks that they form a consistent triplet if they 556 // are. For example, 'mov x0, #0; mov x0, #512; mov x0, #1024' is a 557 // consistent triplet, but they are not MOPS instructions. 558 const int op_lsb = (mops_type == "cpy"_h) ? 22 : 14; 559 const uint32_t kMOPSOpfield = 0x3 << op_lsb; 560 const uint32_t kMOPSPrologue = 0; 561 const uint32_t kMOPSMain = 0x1 << op_lsb; 562 const uint32_t kMOPSEpilogue = 0x2 << op_lsb; 563 switch (Mask(kMOPSOpfield)) { 564 case kMOPSPrologue: 565 return next1->IsMOPSMainOf(this, mops_type) && 566 next2->IsMOPSEpilogueOf(this, mops_type); 567 case kMOPSMain: 568 return prev1->IsMOPSPrologueOf(this, mops_type) && 569 next1->IsMOPSEpilogueOf(this, mops_type); 570 case kMOPSEpilogue: 571 return prev2->IsMOPSPrologueOf(this, mops_type) && 572 prev1->IsMOPSMainOf(this, mops_type); 573 default: 574 VIXL_ABORT_WITH_MSG("Undefined MOPS operation\n"); 575 } 576 } 577 578 static int GetImmBranchRangeBitwidth(ImmBranchType branch_type); 579 VIXL_DEPRECATED( 580 "GetImmBranchRangeBitwidth", 581 static int ImmBranchRangeBitwidth(ImmBranchType branch_type)) { 582 return GetImmBranchRangeBitwidth(branch_type); 583 } 584 585 static int32_t GetImmBranchForwardRange(ImmBranchType branch_type); 586 VIXL_DEPRECATED( 587 "GetImmBranchForwardRange", 588 static int32_t ImmBranchForwardRange(ImmBranchType branch_type)) { 589 return GetImmBranchForwardRange(branch_type); 590 } 591 592 static bool IsValidImmPCOffset(ImmBranchType branch_type, int64_t offset); 593 594 // Indicate whether Rd can be the stack pointer or the zero register. This 595 // does not check that the instruction actually has an Rd field. GetRdMode() const596 Reg31Mode GetRdMode() const { 597 // The following instructions use sp or wsp as Rd: 598 // Add/sub (immediate) when not setting the flags. 599 // Add/sub (extended) when not setting the flags. 600 // Logical (immediate) when not setting the flags. 601 // Otherwise, r31 is the zero register. 602 if (IsAddSubImmediate() || IsAddSubExtended()) { 603 if (Mask(AddSubSetFlagsBit)) { 604 return Reg31IsZeroRegister; 605 } else { 606 return Reg31IsStackPointer; 607 } 608 } 609 if (IsLogicalImmediate()) { 610 // Of the logical (immediate) instructions, only ANDS (and its aliases) 611 // can set the flags. The others can all write into sp. 612 // Note that some logical operations are not available to 613 // immediate-operand instructions, so we have to combine two masks here. 614 if (Mask(LogicalImmediateMask & LogicalOpMask) == ANDS) { 615 return Reg31IsZeroRegister; 616 } else { 617 return Reg31IsStackPointer; 618 } 619 } 620 return Reg31IsZeroRegister; 621 } 622 VIXL_DEPRECATED("GetRdMode", Reg31Mode RdMode() const) { return GetRdMode(); } 623 624 // Indicate whether Rn can be the stack pointer or the zero register. This 625 // does not check that the instruction actually has an Rn field. GetRnMode() const626 Reg31Mode GetRnMode() const { 627 // The following instructions use sp or wsp as Rn: 628 // All loads and stores. 629 // Add/sub (immediate). 630 // Add/sub (extended). 631 // Otherwise, r31 is the zero register. 632 if (IsLoadOrStore() || IsAddSubImmediate() || IsAddSubExtended()) { 633 return Reg31IsStackPointer; 634 } 635 return Reg31IsZeroRegister; 636 } 637 VIXL_DEPRECATED("GetRnMode", Reg31Mode RnMode() const) { return GetRnMode(); } 638 GetBranchType() const639 ImmBranchType GetBranchType() const { 640 if (IsCondBranchImm()) { 641 return CondBranchType; 642 } else if (IsUncondBranchImm()) { 643 return UncondBranchType; 644 } else if (IsCompareBranch()) { 645 return CompareBranchType; 646 } else if (IsTestBranch()) { 647 return TestBranchType; 648 } else { 649 return UnknownBranchType; 650 } 651 } 652 VIXL_DEPRECATED("GetBranchType", ImmBranchType BranchType() const) { 653 return GetBranchType(); 654 } 655 656 // Find the target of this instruction. 'this' may be a branch or a 657 // PC-relative addressing instruction. 658 const Instruction* GetImmPCOffsetTarget() const; 659 VIXL_DEPRECATED("GetImmPCOffsetTarget", 660 const Instruction* ImmPCOffsetTarget() const) { 661 return GetImmPCOffsetTarget(); 662 } 663 664 // Patch a PC-relative offset to refer to 'target'. 'this' may be a branch or 665 // a PC-relative addressing instruction. 666 void SetImmPCOffsetTarget(const Instruction* target); 667 // Patch a literal load instruction to load from 'source'. 668 void SetImmLLiteral(const Instruction* source); 669 670 // The range of a load literal instruction, expressed as 'instr +- range'. 671 // The range is actually the 'positive' range; the branch instruction can 672 // target [instr - range - kInstructionSize, instr + range]. 673 static const int kLoadLiteralImmBitwidth = 19; 674 static const int kLoadLiteralRange = 675 (1 << kLoadLiteralImmBitwidth) / 2 - kInstructionSize; 676 677 // Calculate the address of a literal referred to by a load-literal 678 // instruction, and return it as the specified type. 679 // 680 // The literal itself is safely mutable only if the backing buffer is safely 681 // mutable. 682 template <typename T> GetLiteralAddress() const683 T GetLiteralAddress() const { 684 uint64_t base_raw = reinterpret_cast<uint64_t>(this); 685 int64_t offset = GetImmLLiteral() * static_cast<int>(kLiteralEntrySize); 686 uint64_t address_raw = base_raw + offset; 687 688 // Cast the address using a C-style cast. A reinterpret_cast would be 689 // appropriate, but it can't cast one integral type to another. 690 T address = (T)(address_raw); 691 692 // Assert that the address can be represented by the specified type. 693 VIXL_ASSERT((uint64_t)(address) == address_raw); 694 695 return address; 696 } 697 template <typename T> 698 VIXL_DEPRECATED("GetLiteralAddress", T LiteralAddress() const) { 699 return GetLiteralAddress<T>(); 700 } 701 GetLiteral32() const702 uint32_t GetLiteral32() const { 703 uint32_t literal; 704 memcpy(&literal, GetLiteralAddress<const void*>(), sizeof(literal)); 705 return literal; 706 } 707 VIXL_DEPRECATED("GetLiteral32", uint32_t Literal32() const) { 708 return GetLiteral32(); 709 } 710 GetLiteral64() const711 uint64_t GetLiteral64() const { 712 uint64_t literal; 713 memcpy(&literal, GetLiteralAddress<const void*>(), sizeof(literal)); 714 return literal; 715 } 716 VIXL_DEPRECATED("GetLiteral64", uint64_t Literal64() const) { 717 return GetLiteral64(); 718 } 719 GetLiteralFP32() const720 float GetLiteralFP32() const { return RawbitsToFloat(GetLiteral32()); } 721 VIXL_DEPRECATED("GetLiteralFP32", float LiteralFP32() const) { 722 return GetLiteralFP32(); 723 } 724 GetLiteralFP64() const725 double GetLiteralFP64() const { return RawbitsToDouble(GetLiteral64()); } 726 VIXL_DEPRECATED("GetLiteralFP64", double LiteralFP64() const) { 727 return GetLiteralFP64(); 728 } 729 GetNextInstruction()730 Instruction* GetNextInstruction() { return this + kInstructionSize; } GetNextInstruction() const731 const Instruction* GetNextInstruction() const { 732 return this + kInstructionSize; 733 } 734 VIXL_DEPRECATED("GetNextInstruction", 735 const Instruction* NextInstruction() const) { 736 return GetNextInstruction(); 737 } 738 GetInstructionAtOffset(int64_t offset) const739 const Instruction* GetInstructionAtOffset(int64_t offset) const { 740 VIXL_ASSERT(IsWordAligned(this + offset)); 741 return this + offset; 742 } 743 VIXL_DEPRECATED("GetInstructionAtOffset", 744 const Instruction* InstructionAtOffset(int64_t offset) 745 const) { 746 return GetInstructionAtOffset(offset); 747 } 748 749 template <typename T> Cast(T src)750 static Instruction* Cast(T src) { 751 return reinterpret_cast<Instruction*>(src); 752 } 753 754 template <typename T> CastConst(T src)755 static const Instruction* CastConst(T src) { 756 return reinterpret_cast<const Instruction*>(src); 757 } 758 759 private: 760 int GetImmBranch() const; 761 762 void SetPCRelImmTarget(const Instruction* target); 763 void SetBranchImmTarget(const Instruction* target); 764 }; 765 766 767 // Functions for handling NEON and SVE vector format information. 768 769 const int kMaxLanesPerVector = 16; 770 771 VectorFormat VectorFormatHalfWidth(VectorFormat vform); 772 VectorFormat VectorFormatDoubleWidth(VectorFormat vform); 773 VectorFormat VectorFormatDoubleLanes(VectorFormat vform); 774 VectorFormat VectorFormatHalfLanes(VectorFormat vform); 775 VectorFormat ScalarFormatFromLaneSize(int lane_size_in_bits); 776 VectorFormat VectorFormatHalfWidthDoubleLanes(VectorFormat vform); 777 VectorFormat VectorFormatFillQ(VectorFormat vform); 778 VectorFormat ScalarFormatFromFormat(VectorFormat vform); 779 VectorFormat SVEFormatFromLaneSizeInBits(int lane_size_in_bits); 780 VectorFormat SVEFormatFromLaneSizeInBytes(int lane_size_in_bytes); 781 VectorFormat SVEFormatFromLaneSizeInBytesLog2(int lane_size_in_bytes_log_2); 782 unsigned RegisterSizeInBitsFromFormat(VectorFormat vform); 783 unsigned RegisterSizeInBytesFromFormat(VectorFormat vform); 784 bool IsSVEFormat(VectorFormat vform); 785 // TODO: Make the return types of these functions consistent. 786 unsigned LaneSizeInBitsFromFormat(VectorFormat vform); 787 int LaneSizeInBytesFromFormat(VectorFormat vform); 788 int LaneSizeInBytesLog2FromFormat(VectorFormat vform); 789 int LaneCountFromFormat(VectorFormat vform); 790 int MaxLaneCountFromFormat(VectorFormat vform); 791 bool IsVectorFormat(VectorFormat vform); 792 int64_t MaxIntFromFormat(VectorFormat vform); 793 int64_t MinIntFromFormat(VectorFormat vform); 794 uint64_t MaxUintFromFormat(VectorFormat vform); 795 796 797 // clang-format off 798 enum NEONFormat { 799 NF_UNDEF = 0, 800 NF_8B = 1, 801 NF_16B = 2, 802 NF_4H = 3, 803 NF_8H = 4, 804 NF_2S = 5, 805 NF_4S = 6, 806 NF_1D = 7, 807 NF_2D = 8, 808 NF_B = 9, 809 NF_H = 10, 810 NF_S = 11, 811 NF_D = 12 812 }; 813 // clang-format on 814 815 static const unsigned kNEONFormatMaxBits = 6; 816 817 struct NEONFormatMap { 818 // The bit positions in the instruction to consider. 819 uint8_t bits[kNEONFormatMaxBits]; 820 821 // Mapping from concatenated bits to format. 822 NEONFormat map[1 << kNEONFormatMaxBits]; 823 }; 824 825 class NEONFormatDecoder { 826 public: 827 enum SubstitutionMode { kPlaceholder, kFormat }; 828 829 // Construct a format decoder with increasingly specific format maps for each 830 // substitution. If no format map is specified, the default is the integer 831 // format map. NEONFormatDecoder(const Instruction* instr)832 explicit NEONFormatDecoder(const Instruction* instr) { 833 instrbits_ = instr->GetInstructionBits(); 834 SetFormatMaps(IntegerFormatMap()); 835 } NEONFormatDecoder(const Instruction* instr, const NEONFormatMap* format)836 NEONFormatDecoder(const Instruction* instr, const NEONFormatMap* format) { 837 instrbits_ = instr->GetInstructionBits(); 838 SetFormatMaps(format); 839 } NEONFormatDecoder(const Instruction* instr, const NEONFormatMap* format0, const NEONFormatMap* format1)840 NEONFormatDecoder(const Instruction* instr, 841 const NEONFormatMap* format0, 842 const NEONFormatMap* format1) { 843 instrbits_ = instr->GetInstructionBits(); 844 SetFormatMaps(format0, format1); 845 } NEONFormatDecoder(const Instruction* instr, const NEONFormatMap* format0, const NEONFormatMap* format1, const NEONFormatMap* format2)846 NEONFormatDecoder(const Instruction* instr, 847 const NEONFormatMap* format0, 848 const NEONFormatMap* format1, 849 const NEONFormatMap* format2) { 850 instrbits_ = instr->GetInstructionBits(); 851 SetFormatMaps(format0, format1, format2); 852 } 853 854 // Set the format mapping for all or individual substitutions. SetFormatMaps(const NEONFormatMap* format0, const NEONFormatMap* format1 = NULL, const NEONFormatMap* format2 = NULL)855 void SetFormatMaps(const NEONFormatMap* format0, 856 const NEONFormatMap* format1 = NULL, 857 const NEONFormatMap* format2 = NULL) { 858 VIXL_ASSERT(format0 != NULL); 859 formats_[0] = format0; 860 formats_[1] = (format1 == NULL) ? formats_[0] : format1; 861 formats_[2] = (format2 == NULL) ? formats_[1] : format2; 862 } SetFormatMap(unsigned index, const NEONFormatMap* format)863 void SetFormatMap(unsigned index, const NEONFormatMap* format) { 864 VIXL_ASSERT(index <= ArrayLength(formats_)); 865 VIXL_ASSERT(format != NULL); 866 formats_[index] = format; 867 } 868 869 // Substitute %s in the input string with the placeholder string for each 870 // register, ie. "'B", "'H", etc. SubstitutePlaceholders(const char* string)871 const char* SubstitutePlaceholders(const char* string) { 872 return Substitute(string, kPlaceholder, kPlaceholder, kPlaceholder); 873 } 874 875 // Substitute %s in the input string with a new string based on the 876 // substitution mode. Substitute(const char* string, SubstitutionMode mode0 = kFormat, SubstitutionMode mode1 = kFormat, SubstitutionMode mode2 = kFormat)877 const char* Substitute(const char* string, 878 SubstitutionMode mode0 = kFormat, 879 SubstitutionMode mode1 = kFormat, 880 SubstitutionMode mode2 = kFormat) { 881 const char* subst0 = GetSubstitute(0, mode0); 882 const char* subst1 = GetSubstitute(1, mode1); 883 const char* subst2 = GetSubstitute(2, mode2); 884 885 if ((subst0 == NULL) || (subst1 == NULL) || (subst2 == NULL)) { 886 return NULL; 887 } 888 889 snprintf(form_buffer_, 890 sizeof(form_buffer_), 891 string, 892 subst0, 893 subst1, 894 subst2); 895 return form_buffer_; 896 } 897 898 // Append a "2" to a mnemonic string based on the state of the Q bit. Mnemonic(const char* mnemonic)899 const char* Mnemonic(const char* mnemonic) { 900 if ((mnemonic != NULL) && (instrbits_ & NEON_Q) != 0) { 901 snprintf(mne_buffer_, sizeof(mne_buffer_), "%s2", mnemonic); 902 return mne_buffer_; 903 } 904 return mnemonic; 905 } 906 GetVectorFormat(int format_index = 0)907 VectorFormat GetVectorFormat(int format_index = 0) { 908 return GetVectorFormat(formats_[format_index]); 909 } 910 GetVectorFormat(const NEONFormatMap* format_map)911 VectorFormat GetVectorFormat(const NEONFormatMap* format_map) { 912 static const VectorFormat vform[] = {kFormatUndefined, 913 kFormat8B, 914 kFormat16B, 915 kFormat4H, 916 kFormat8H, 917 kFormat2S, 918 kFormat4S, 919 kFormat1D, 920 kFormat2D, 921 kFormatB, 922 kFormatH, 923 kFormatS, 924 kFormatD}; 925 VIXL_ASSERT(GetNEONFormat(format_map) < ArrayLength(vform)); 926 return vform[GetNEONFormat(format_map)]; 927 } 928 929 // Built in mappings for common cases. 930 931 // The integer format map uses three bits (Q, size<1:0>) to encode the 932 // "standard" set of NEON integer vector formats. IntegerFormatMap()933 static const NEONFormatMap* IntegerFormatMap() { 934 static const NEONFormatMap map = 935 {{23, 22, 30}, 936 {NF_8B, NF_16B, NF_4H, NF_8H, NF_2S, NF_4S, NF_UNDEF, NF_2D}}; 937 return ↦ 938 } 939 940 // The long integer format map uses two bits (size<1:0>) to encode the 941 // long set of NEON integer vector formats. These are used in narrow, wide 942 // and long operations. LongIntegerFormatMap()943 static const NEONFormatMap* LongIntegerFormatMap() { 944 static const NEONFormatMap map = {{23, 22}, {NF_8H, NF_4S, NF_2D}}; 945 return ↦ 946 } 947 948 // The FP format map uses two bits (Q, size<0>) to encode the NEON FP vector 949 // formats: NF_2S, NF_4S, NF_2D. FPFormatMap()950 static const NEONFormatMap* FPFormatMap() { 951 // The FP format map assumes two bits (Q, size<0>) are used to encode the 952 // NEON FP vector formats: NF_2S, NF_4S, NF_2D. 953 static const NEONFormatMap map = {{22, 30}, 954 {NF_2S, NF_4S, NF_UNDEF, NF_2D}}; 955 return ↦ 956 } 957 958 // The FP16 format map uses one bit (Q) to encode the NEON vector format: 959 // NF_4H, NF_8H. FP16FormatMap()960 static const NEONFormatMap* FP16FormatMap() { 961 static const NEONFormatMap map = {{30}, {NF_4H, NF_8H}}; 962 return ↦ 963 } 964 965 // The load/store format map uses three bits (Q, 11, 10) to encode the 966 // set of NEON vector formats. LoadStoreFormatMap()967 static const NEONFormatMap* LoadStoreFormatMap() { 968 static const NEONFormatMap map = 969 {{11, 10, 30}, 970 {NF_8B, NF_16B, NF_4H, NF_8H, NF_2S, NF_4S, NF_1D, NF_2D}}; 971 return ↦ 972 } 973 974 // The logical format map uses one bit (Q) to encode the NEON vector format: 975 // NF_8B, NF_16B. LogicalFormatMap()976 static const NEONFormatMap* LogicalFormatMap() { 977 static const NEONFormatMap map = {{30}, {NF_8B, NF_16B}}; 978 return ↦ 979 } 980 981 // The triangular format map uses between two and five bits to encode the NEON 982 // vector format: 983 // xxx10->8B, xxx11->16B, xx100->4H, xx101->8H 984 // x1000->2S, x1001->4S, 10001->2D, all others undefined. TriangularFormatMap()985 static const NEONFormatMap* TriangularFormatMap() { 986 static const NEONFormatMap map = 987 {{19, 18, 17, 16, 30}, 988 {NF_UNDEF, NF_UNDEF, NF_8B, NF_16B, NF_4H, NF_8H, NF_8B, NF_16B, 989 NF_2S, NF_4S, NF_8B, NF_16B, NF_4H, NF_8H, NF_8B, NF_16B, 990 NF_UNDEF, NF_2D, NF_8B, NF_16B, NF_4H, NF_8H, NF_8B, NF_16B, 991 NF_2S, NF_4S, NF_8B, NF_16B, NF_4H, NF_8H, NF_8B, NF_16B}}; 992 return ↦ 993 } 994 995 // The shift immediate map uses between two and five bits to encode the NEON 996 // vector format: 997 // 00010->8B, 00011->16B, 001x0->4H, 001x1->8H, 998 // 01xx0->2S, 01xx1->4S, 1xxx1->2D, all others undefined. ShiftImmFormatMap()999 static const NEONFormatMap* ShiftImmFormatMap() { 1000 static const NEONFormatMap map = {{22, 21, 20, 19, 30}, 1001 {NF_UNDEF, NF_UNDEF, NF_8B, NF_16B, 1002 NF_4H, NF_8H, NF_4H, NF_8H, 1003 NF_2S, NF_4S, NF_2S, NF_4S, 1004 NF_2S, NF_4S, NF_2S, NF_4S, 1005 NF_UNDEF, NF_2D, NF_UNDEF, NF_2D, 1006 NF_UNDEF, NF_2D, NF_UNDEF, NF_2D, 1007 NF_UNDEF, NF_2D, NF_UNDEF, NF_2D, 1008 NF_UNDEF, NF_2D, NF_UNDEF, NF_2D}}; 1009 return ↦ 1010 } 1011 1012 // The shift long/narrow immediate map uses between two and four bits to 1013 // encode the NEON vector format: 1014 // 0001->8H, 001x->4S, 01xx->2D, all others undefined. ShiftLongNarrowImmFormatMap()1015 static const NEONFormatMap* ShiftLongNarrowImmFormatMap() { 1016 static const NEONFormatMap map = 1017 {{22, 21, 20, 19}, 1018 {NF_UNDEF, NF_8H, NF_4S, NF_4S, NF_2D, NF_2D, NF_2D, NF_2D}}; 1019 return ↦ 1020 } 1021 1022 // The scalar format map uses two bits (size<1:0>) to encode the NEON scalar 1023 // formats: NF_B, NF_H, NF_S, NF_D. ScalarFormatMap()1024 static const NEONFormatMap* ScalarFormatMap() { 1025 static const NEONFormatMap map = {{23, 22}, {NF_B, NF_H, NF_S, NF_D}}; 1026 return ↦ 1027 } 1028 1029 // The long scalar format map uses two bits (size<1:0>) to encode the longer 1030 // NEON scalar formats: NF_H, NF_S, NF_D. LongScalarFormatMap()1031 static const NEONFormatMap* LongScalarFormatMap() { 1032 static const NEONFormatMap map = {{23, 22}, {NF_H, NF_S, NF_D}}; 1033 return ↦ 1034 } 1035 1036 // The FP scalar format map assumes one bit (size<0>) is used to encode the 1037 // NEON FP scalar formats: NF_S, NF_D. FPScalarFormatMap()1038 static const NEONFormatMap* FPScalarFormatMap() { 1039 static const NEONFormatMap map = {{22}, {NF_S, NF_D}}; 1040 return ↦ 1041 } 1042 1043 // The FP scalar pairwise format map assumes two bits (U, size<0>) are used to 1044 // encode the NEON FP scalar formats: NF_H, NF_S, NF_D. FPScalarPairwiseFormatMap()1045 static const NEONFormatMap* FPScalarPairwiseFormatMap() { 1046 static const NEONFormatMap map = {{29, 22}, {NF_H, NF_UNDEF, NF_S, NF_D}}; 1047 return ↦ 1048 } 1049 1050 // The triangular scalar format map uses between one and four bits to encode 1051 // the NEON FP scalar formats: 1052 // xxx1->B, xx10->H, x100->S, 1000->D, all others undefined. TriangularScalarFormatMap()1053 static const NEONFormatMap* TriangularScalarFormatMap() { 1054 static const NEONFormatMap map = {{19, 18, 17, 16}, 1055 {NF_UNDEF, 1056 NF_B, 1057 NF_H, 1058 NF_B, 1059 NF_S, 1060 NF_B, 1061 NF_H, 1062 NF_B, 1063 NF_D, 1064 NF_B, 1065 NF_H, 1066 NF_B, 1067 NF_S, 1068 NF_B, 1069 NF_H, 1070 NF_B}}; 1071 return ↦ 1072 } 1073 1074 private: 1075 // Get a pointer to a string that represents the format or placeholder for 1076 // the specified substitution index, based on the format map and instruction. GetSubstitute(int index, SubstitutionMode mode)1077 const char* GetSubstitute(int index, SubstitutionMode mode) { 1078 if (mode == kFormat) { 1079 return NEONFormatAsString(GetNEONFormat(formats_[index])); 1080 } 1081 VIXL_ASSERT(mode == kPlaceholder); 1082 return NEONFormatAsPlaceholder(GetNEONFormat(formats_[index])); 1083 } 1084 1085 // Get the NEONFormat enumerated value for bits obtained from the 1086 // instruction based on the specified format mapping. GetNEONFormat(const NEONFormatMap* format_map)1087 NEONFormat GetNEONFormat(const NEONFormatMap* format_map) { 1088 return format_map->map[PickBits(format_map->bits)]; 1089 } 1090 1091 // Convert a NEONFormat into a string. NEONFormatAsString(NEONFormat format)1092 static const char* NEONFormatAsString(NEONFormat format) { 1093 // clang-format off 1094 static const char* formats[] = { 1095 NULL, 1096 "8b", "16b", "4h", "8h", "2s", "4s", "1d", "2d", 1097 "b", "h", "s", "d" 1098 }; 1099 // clang-format on 1100 VIXL_ASSERT(format < ArrayLength(formats)); 1101 return formats[format]; 1102 } 1103 1104 // Convert a NEONFormat into a register placeholder string. 1105 static const char* NEONFormatAsPlaceholder(NEONFormat format) { 1106 VIXL_ASSERT((format == NF_B) || (format == NF_H) || (format == NF_S) || 1107 (format == NF_D) || (format == NF_UNDEF)); 1108 // clang-format off 1109 static const char* formats[] = { 1110 NULL, 1111 NULL, NULL, NULL, NULL, 1112 NULL, NULL, NULL, NULL, 1113 "'B", "'H", "'S", "'D" 1114 }; 1115 // clang-format on 1116 return formats[format]; 1117 } 1118 1119 // Select bits from instrbits_ defined by the bits array, concatenate them, 1120 // and return the value. 1121 uint8_t PickBits(const uint8_t bits[]) { 1122 uint8_t result = 0; 1123 for (unsigned b = 0; b < kNEONFormatMaxBits; b++) { 1124 if (bits[b] == 0) break; 1125 result <<= 1; 1126 result |= ((instrbits_ & (1 << bits[b])) == 0) ? 0 : 1; 1127 } 1128 return result; 1129 } 1130 1131 Instr instrbits_; 1132 const NEONFormatMap* formats_[3]; 1133 char form_buffer_[64]; 1134 char mne_buffer_[16]; 1135 }; 1136 } // namespace aarch64 1137 } // namespace vixl 1138 1139 #endif // VIXL_AARCH64_INSTRUCTIONS_AARCH64_H_ 1140