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