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