1 // Copyright 2017, 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_AARCH32_INSTRUCTIONS_AARCH32_H_ 28 #define VIXL_AARCH32_INSTRUCTIONS_AARCH32_H_ 29 30 extern "C" { 31 #include <stdint.h> 32 } 33 34 #include <algorithm> 35 #include <ostream> 36 37 #include "code-buffer-vixl.h" 38 #include "utils-vixl.h" 39 #include "aarch32/constants-aarch32.h" 40 41 #if !defined(__linux__) && defined(__arm__) 42 #define HARDFLOAT gnu__attribute__((noinline, pcs("aapcs-vfp"))) 43 #elif defined(_MSC_VER) 44 #define HARDFLOAT __declspec(noinline) 45 #else 46 #define HARDFLOAT __attribute__((noinline)) 47 #endif 48 49 namespace vixl { 50 namespace aarch32 { 51 52 class Operand; 53 class SOperand; 54 class DOperand; 55 class QOperand; 56 class MemOperand; 57 class AlignedMemOperand; 58 59 enum AddrMode { Offset = 0, PreIndex = 1, PostIndex = 2 }; 60 61 class CPURegister { 62 public: 63 enum RegisterType { 64 kNoRegister = 0, 65 kRRegister = 1, 66 kSRegister = 2, 67 kDRegister = 3, 68 kQRegister = 4 69 }; 70 71 private: 72 static const int kCodeBits = 5; 73 static const int kTypeBits = 4; 74 static const int kSizeBits = 8; 75 static const int kCodeShift = 0; 76 static const int kTypeShift = kCodeShift + kCodeBits; 77 static const int kSizeShift = kTypeShift + kTypeBits; 78 static const uint32_t kCodeMask = ((1 << kCodeBits) - 1) << kCodeShift; 79 static const uint32_t kTypeMask = ((1 << kTypeBits) - 1) << kTypeShift; 80 static const uint32_t kSizeMask = ((1 << kSizeBits) - 1) << kSizeShift; 81 uint32_t value_; 82 83 public: CPURegister(RegisterType type, uint32_t code, int size)84 constexpr CPURegister(RegisterType type, uint32_t code, int size) 85 : value_((type << kTypeShift) | (code << kCodeShift) | 86 (size << kSizeShift)) { 87 #ifdef VIXL_DEBUG 88 switch (type) { 89 case kNoRegister: 90 break; 91 case kRRegister: 92 VIXL_ASSERT(code < kNumberOfRegisters); 93 VIXL_ASSERT(size == kRegSizeInBits); 94 break; 95 case kSRegister: 96 VIXL_ASSERT(code < kNumberOfSRegisters); 97 VIXL_ASSERT(size == kSRegSizeInBits); 98 break; 99 case kDRegister: 100 VIXL_ASSERT(code < kMaxNumberOfDRegisters); 101 VIXL_ASSERT(size == kDRegSizeInBits); 102 break; 103 case kQRegister: 104 VIXL_ASSERT(code < kNumberOfQRegisters); 105 VIXL_ASSERT(size == kQRegSizeInBits); 106 break; 107 default: 108 VIXL_UNREACHABLE(); 109 break; 110 } 111 #endif 112 } 113 constexpr RegisterType GetType() const { 114 return static_cast<RegisterType>((value_ & kTypeMask) >> kTypeShift); 115 } 116 bool IsRegister() const { return GetType() == kRRegister; } 117 bool IsS() const { return GetType() == kSRegister; } 118 bool IsD() const { return GetType() == kDRegister; } 119 bool IsQ() const { return GetType() == kQRegister; } 120 bool IsVRegister() const { return IsS() || IsD() || IsQ(); } 121 bool IsFPRegister() const { return IsS() || IsD(); } 122 uint32_t GetCode() const { return (value_ & kCodeMask) >> kCodeShift; } 123 uint32_t GetReg() const { return value_; } 124 int GetSizeInBits() const { return (value_ & kSizeMask) >> kSizeShift; } 125 int GetRegSizeInBytes() const { 126 return (GetType() == kNoRegister) ? 0 : (GetSizeInBits() / 8); 127 } 128 bool Is64Bits() const { return GetSizeInBits() == 64; } 129 bool Is128Bits() const { return GetSizeInBits() == 128; } 130 bool IsSameFormat(CPURegister reg) { 131 return (value_ & ~kCodeMask) == (reg.value_ & ~kCodeMask); 132 } 133 bool Is(CPURegister ref) const { return GetReg() == ref.GetReg(); } 134 bool IsValid() const { return GetType() != kNoRegister; } 135 }; 136 137 class Register : public CPURegister { 138 public: 139 constexpr Register() : CPURegister(kNoRegister, 0, kRegSizeInBits) {} 140 explicit constexpr Register(uint32_t code) 141 : CPURegister(kRRegister, code % kNumberOfRegisters, kRegSizeInBits) { 142 VIXL_ASSERT(GetCode() < kNumberOfRegisters); 143 } 144 bool Is(Register ref) const { return GetCode() == ref.GetCode(); } 145 bool IsLow() const { return GetCode() < kNumberOfT32LowRegisters; } 146 bool IsLR() const { return GetCode() == kLrCode; } 147 bool IsPC() const { return GetCode() == kPcCode; } 148 bool IsSP() const { return GetCode() == kSpCode; } 149 }; 150 151 std::ostream& operator<<(std::ostream& os, const Register reg); 152 153 class RegisterOrAPSR_nzcv { 154 uint32_t code_; 155 156 public: 157 explicit RegisterOrAPSR_nzcv(uint32_t code) : code_(code) { 158 VIXL_ASSERT(code_ < kNumberOfRegisters); 159 } 160 bool IsAPSR_nzcv() const { return code_ == kPcCode; } 161 uint32_t GetCode() const { return code_; } 162 Register AsRegister() const { 163 VIXL_ASSERT(!IsAPSR_nzcv()); 164 return Register(code_); 165 } 166 }; 167 168 const RegisterOrAPSR_nzcv APSR_nzcv(kPcCode); 169 170 inline std::ostream& operator<<(std::ostream& os, 171 const RegisterOrAPSR_nzcv reg) { 172 if (reg.IsAPSR_nzcv()) return os << "APSR_nzcv"; 173 return os << reg.AsRegister(); 174 } 175 176 class SRegister; 177 class DRegister; 178 class QRegister; 179 180 class VRegister : public CPURegister { 181 public: 182 VRegister() : CPURegister(kNoRegister, 0, 0) {} 183 VRegister(RegisterType type, uint32_t code, int size) 184 : CPURegister(type, code, size) {} 185 186 SRegister S() const; 187 DRegister D() const; 188 QRegister Q() const; 189 }; 190 191 class SRegister : public VRegister { 192 public: 193 SRegister() : VRegister(kNoRegister, 0, kSRegSizeInBits) {} 194 explicit SRegister(uint32_t code) 195 : VRegister(kSRegister, code, kSRegSizeInBits) {} 196 uint32_t Encode(int single_bit_field, int four_bit_field_lowest_bit) const { 197 if (four_bit_field_lowest_bit == 0) { 198 return ((GetCode() & 0x1) << single_bit_field) | 199 ((GetCode() & 0x1e) >> 1); 200 } 201 return ((GetCode() & 0x1) << single_bit_field) | 202 ((GetCode() & 0x1e) << (four_bit_field_lowest_bit - 1)); 203 } 204 }; 205 206 inline unsigned ExtractSRegister(uint32_t instr, 207 int single_bit_field, 208 int four_bit_field_lowest_bit) { 209 VIXL_ASSERT(single_bit_field > 0); 210 if (four_bit_field_lowest_bit == 0) { 211 return ((instr << 1) & 0x1e) | ((instr >> single_bit_field) & 0x1); 212 } 213 return ((instr >> (four_bit_field_lowest_bit - 1)) & 0x1e) | 214 ((instr >> single_bit_field) & 0x1); 215 } 216 217 inline std::ostream& operator<<(std::ostream& os, const SRegister reg) { 218 return os << "s" << reg.GetCode(); 219 } 220 221 class DRegister : public VRegister { 222 public: 223 DRegister() : VRegister(kNoRegister, 0, kDRegSizeInBits) {} 224 explicit DRegister(uint32_t code) 225 : VRegister(kDRegister, code, kDRegSizeInBits) {} 226 SRegister GetLane(uint32_t lane) const { 227 uint32_t lane_count = kDRegSizeInBits / kSRegSizeInBits; 228 VIXL_ASSERT(lane < lane_count); 229 VIXL_ASSERT(GetCode() * lane_count < kNumberOfSRegisters); 230 return SRegister(GetCode() * lane_count + lane); 231 } 232 uint32_t Encode(int single_bit_field, int four_bit_field_lowest_bit) const { 233 VIXL_ASSERT(single_bit_field >= 4); 234 return ((GetCode() & 0x10) << (single_bit_field - 4)) | 235 ((GetCode() & 0xf) << four_bit_field_lowest_bit); 236 } 237 }; 238 239 inline unsigned ExtractDRegister(uint32_t instr, 240 int single_bit_field, 241 int four_bit_field_lowest_bit) { 242 VIXL_ASSERT(single_bit_field >= 4); 243 return ((instr >> (single_bit_field - 4)) & 0x10) | 244 ((instr >> four_bit_field_lowest_bit) & 0xf); 245 } 246 247 inline std::ostream& operator<<(std::ostream& os, const DRegister reg) { 248 return os << "d" << reg.GetCode(); 249 } 250 251 enum DataTypeType { 252 kDataTypeS = 0x100, 253 kDataTypeU = 0x200, 254 kDataTypeF = 0x300, 255 kDataTypeI = 0x400, 256 kDataTypeP = 0x500, 257 kDataTypeUntyped = 0x600 258 }; 259 const int kDataTypeSizeMask = 0x0ff; 260 const int kDataTypeTypeMask = 0x100; 261 enum DataTypeValue { 262 kDataTypeValueInvalid = 0x000, 263 kDataTypeValueNone = 0x001, // value used when dt is ignored. 264 S8 = kDataTypeS | 8, 265 S16 = kDataTypeS | 16, 266 S32 = kDataTypeS | 32, 267 S64 = kDataTypeS | 64, 268 U8 = kDataTypeU | 8, 269 U16 = kDataTypeU | 16, 270 U32 = kDataTypeU | 32, 271 U64 = kDataTypeU | 64, 272 F16 = kDataTypeF | 16, 273 F32 = kDataTypeF | 32, 274 F64 = kDataTypeF | 64, 275 I8 = kDataTypeI | 8, 276 I16 = kDataTypeI | 16, 277 I32 = kDataTypeI | 32, 278 I64 = kDataTypeI | 64, 279 P8 = kDataTypeP | 8, 280 P64 = kDataTypeP | 64, 281 Untyped8 = kDataTypeUntyped | 8, 282 Untyped16 = kDataTypeUntyped | 16, 283 Untyped32 = kDataTypeUntyped | 32, 284 Untyped64 = kDataTypeUntyped | 64 285 }; 286 287 class DataType { 288 DataTypeValue value_; 289 290 public: 291 explicit DataType(uint32_t size) 292 : value_(static_cast<DataTypeValue>(kDataTypeUntyped | size)) { 293 VIXL_ASSERT((size == 8) || (size == 16) || (size == 32) || (size == 64)); 294 } 295 // Users should be able to use "S8", "S6" and so forth to instantiate this 296 // class. 297 DataType(DataTypeValue value) : value_(value) {} // NOLINT(runtime/explicit) 298 DataTypeValue GetValue() const { return value_; } 299 DataTypeType GetType() const { 300 return static_cast<DataTypeType>(value_ & kDataTypeTypeMask); 301 } 302 uint32_t GetSize() const { return value_ & kDataTypeSizeMask; } 303 bool IsSize(uint32_t size) const { 304 return (value_ & kDataTypeSizeMask) == size; 305 } 306 const char* GetName() const; 307 bool Is(DataType type) const { return value_ == type.value_; } 308 bool Is(DataTypeValue value) const { return value_ == value; } 309 bool Is(DataTypeType type) const { return GetType() == type; } 310 bool IsNoneOr(DataTypeValue value) const { 311 return (value_ == value) || (value_ == kDataTypeValueNone); 312 } 313 bool Is(DataTypeType type, uint32_t size) const { 314 return value_ == static_cast<DataTypeValue>(type | size); 315 } 316 bool IsNoneOr(DataTypeType type, uint32_t size) const { 317 return Is(type, size) || Is(kDataTypeValueNone); 318 } 319 }; 320 321 inline std::ostream& operator<<(std::ostream& os, DataType dt) { 322 return os << dt.GetName(); 323 } 324 325 class DRegisterLane : public DRegister { 326 uint32_t lane_; 327 328 public: 329 DRegisterLane(DRegister reg, uint32_t lane) 330 : DRegister(reg.GetCode()), lane_(lane) {} 331 DRegisterLane(uint32_t code, uint32_t lane) : DRegister(code), lane_(lane) {} 332 uint32_t GetLane() const { return lane_; } 333 uint32_t EncodeX(DataType dt, 334 int single_bit_field, 335 int four_bit_field_lowest_bit) const { 336 VIXL_ASSERT(single_bit_field >= 4); 337 uint32_t value = lane_ << ((dt.GetSize() == 16) ? 3 : 4) | GetCode(); 338 return ((value & 0x10) << (single_bit_field - 4)) | 339 ((value & 0xf) << four_bit_field_lowest_bit); 340 } 341 }; 342 343 inline unsigned ExtractDRegisterAndLane(uint32_t instr, 344 DataType dt, 345 int single_bit_field, 346 int four_bit_field_lowest_bit, 347 int* lane) { 348 VIXL_ASSERT(single_bit_field >= 4); 349 uint32_t value = ((instr >> (single_bit_field - 4)) & 0x10) | 350 ((instr >> four_bit_field_lowest_bit) & 0xf); 351 if (dt.GetSize() == 16) { 352 *lane = value >> 3; 353 return value & 0x7; 354 } 355 *lane = value >> 4; 356 return value & 0xf; 357 } 358 359 inline std::ostream& operator<<(std::ostream& os, const DRegisterLane lane) { 360 os << "d" << lane.GetCode() << "["; 361 if (lane.GetLane() == static_cast<uint32_t>(-1)) return os << "??]"; 362 return os << lane.GetLane() << "]"; 363 } 364 365 class QRegister : public VRegister { 366 public: 367 QRegister() : VRegister(kNoRegister, 0, kQRegSizeInBits) {} 368 explicit QRegister(uint32_t code) 369 : VRegister(kQRegister, code, kQRegSizeInBits) {} 370 uint32_t Encode(int offset) { return GetCode() << offset; } 371 DRegister GetDLane(uint32_t lane) const { 372 uint32_t lane_count = kQRegSizeInBits / kDRegSizeInBits; 373 VIXL_ASSERT(lane < lane_count); 374 return DRegister(GetCode() * lane_count + lane); 375 } 376 DRegister GetLowDRegister() const { return DRegister(GetCode() * 2); } 377 DRegister GetHighDRegister() const { return DRegister(1 + GetCode() * 2); } 378 SRegister GetSLane(uint32_t lane) const { 379 uint32_t lane_count = kQRegSizeInBits / kSRegSizeInBits; 380 VIXL_ASSERT(lane < lane_count); 381 VIXL_ASSERT(GetCode() * lane_count < kNumberOfSRegisters); 382 return SRegister(GetCode() * lane_count + lane); 383 } 384 uint32_t Encode(int single_bit_field, int four_bit_field_lowest_bit) { 385 // Encode "code * 2". 386 VIXL_ASSERT(single_bit_field >= 3); 387 return ((GetCode() & 0x8) << (single_bit_field - 3)) | 388 ((GetCode() & 0x7) << (four_bit_field_lowest_bit + 1)); 389 } 390 }; 391 392 inline unsigned ExtractQRegister(uint32_t instr, 393 int single_bit_field, 394 int four_bit_field_lowest_bit) { 395 VIXL_ASSERT(single_bit_field >= 3); 396 return ((instr >> (single_bit_field - 3)) & 0x8) | 397 ((instr >> (four_bit_field_lowest_bit + 1)) & 0x7); 398 } 399 400 inline std::ostream& operator<<(std::ostream& os, const QRegister reg) { 401 return os << "q" << reg.GetCode(); 402 } 403 404 // clang-format off 405 #define AARCH32_REGISTER_CODE_LIST(R) \ 406 R(0) R(1) R(2) R(3) R(4) R(5) R(6) R(7) \ 407 R(8) R(9) R(10) R(11) R(12) R(13) R(14) R(15) 408 // clang-format on 409 #define DEFINE_REGISTER(N) const Register r##N(N); 410 AARCH32_REGISTER_CODE_LIST(DEFINE_REGISTER) 411 #undef DEFINE_REGISTER 412 #undef AARCH32_REGISTER_CODE_LIST 413 414 enum RegNum { kIPRegNum = 12, kSPRegNum = 13, kLRRegNum = 14, kPCRegNum = 15 }; 415 416 const Register ip(kIPRegNum); 417 const Register sp(kSPRegNum); 418 const Register pc(kPCRegNum); 419 const Register lr(kLRRegNum); 420 const Register NoReg; 421 const VRegister NoVReg; 422 423 // clang-format off 424 #define SREGISTER_CODE_LIST(R) \ 425 R(0) R(1) R(2) R(3) R(4) R(5) R(6) R(7) \ 426 R(8) R(9) R(10) R(11) R(12) R(13) R(14) R(15) \ 427 R(16) R(17) R(18) R(19) R(20) R(21) R(22) R(23) \ 428 R(24) R(25) R(26) R(27) R(28) R(29) R(30) R(31) 429 // clang-format on 430 #define DEFINE_REGISTER(N) const SRegister s##N(N); 431 SREGISTER_CODE_LIST(DEFINE_REGISTER) 432 #undef DEFINE_REGISTER 433 #undef SREGISTER_CODE_LIST 434 const SRegister NoSReg; 435 436 // clang-format off 437 #define DREGISTER_CODE_LIST(R) \ 438 R(0) R(1) R(2) R(3) R(4) R(5) R(6) R(7) \ 439 R(8) R(9) R(10) R(11) R(12) R(13) R(14) R(15) \ 440 R(16) R(17) R(18) R(19) R(20) R(21) R(22) R(23) \ 441 R(24) R(25) R(26) R(27) R(28) R(29) R(30) R(31) 442 // clang-format on 443 #define DEFINE_REGISTER(N) const DRegister d##N(N); 444 DREGISTER_CODE_LIST(DEFINE_REGISTER) 445 #undef DEFINE_REGISTER 446 #undef DREGISTER_CODE_LIST 447 const DRegister NoDReg; 448 449 // clang-format off 450 #define QREGISTER_CODE_LIST(R) \ 451 R(0) R(1) R(2) R(3) R(4) R(5) R(6) R(7) \ 452 R(8) R(9) R(10) R(11) R(12) R(13) R(14) R(15) 453 // clang-format on 454 #define DEFINE_REGISTER(N) const QRegister q##N(N); 455 QREGISTER_CODE_LIST(DEFINE_REGISTER) 456 #undef DEFINE_REGISTER 457 #undef QREGISTER_CODE_LIST 458 const QRegister NoQReg; 459 460 class RegisterList { 461 public: 462 constexpr RegisterList() : list_(0) {} 463 constexpr RegisterList(Register reg) // NOLINT(runtime/explicit) 464 : list_(RegisterToList(reg)) {} 465 constexpr RegisterList(Register reg1, Register reg2) 466 : list_(RegisterToList(reg1) | RegisterToList(reg2)) {} 467 constexpr RegisterList(Register reg1, Register reg2, Register reg3) 468 : list_(RegisterToList(reg1) | RegisterToList(reg2) | 469 RegisterToList(reg3)) {} 470 constexpr RegisterList(Register reg1, Register reg2, Register reg3, Register reg4) 471 : list_(RegisterToList(reg1) | RegisterToList(reg2) | 472 RegisterToList(reg3) | RegisterToList(reg4)) {} 473 explicit RegisterList(uint32_t list) : list_(list) {} 474 constexpr uint32_t GetList() const { return list_; } 475 void SetList(uint32_t list) { list_ = list; } 476 bool Includes(const Register& reg) const { 477 return (list_ & RegisterToList(reg)) != 0; 478 } 479 void Combine(const RegisterList& other) { list_ |= other.GetList(); } 480 void Combine(const Register& reg) { list_ |= RegisterToList(reg); } 481 void Remove(const RegisterList& other) { list_ &= ~other.GetList(); } 482 void Remove(const Register& reg) { list_ &= ~RegisterToList(reg); } 483 bool Overlaps(const RegisterList& other) const { 484 return (list_ & other.list_) != 0; 485 } 486 bool IsR0toR7orPC() const { 487 // True if all the registers from the list are not from r8-r14. 488 return (list_ & 0x7f00) == 0; 489 } 490 bool IsR0toR7orLR() const { 491 // True if all the registers from the list are not from r8-r13 nor from r15. 492 return (list_ & 0xbf00) == 0; 493 } 494 Register GetFirstAvailableRegister() const; 495 bool IsEmpty() const { return list_ == 0; } 496 bool IsSingleRegister() const { return IsPowerOf2(list_); } 497 int GetCount() const { return CountSetBits(list_); } 498 static RegisterList Union(const RegisterList& list_1, 499 const RegisterList& list_2) { 500 return RegisterList(list_1.list_ | list_2.list_); 501 } 502 static RegisterList Union(const RegisterList& list_1, 503 const RegisterList& list_2, 504 const RegisterList& list_3) { 505 return Union(list_1, Union(list_2, list_3)); 506 } 507 static RegisterList Union(const RegisterList& list_1, 508 const RegisterList& list_2, 509 const RegisterList& list_3, 510 const RegisterList& list_4) { 511 return Union(Union(list_1, list_2), Union(list_3, list_4)); 512 } 513 static RegisterList Intersection(const RegisterList& list_1, 514 const RegisterList& list_2) { 515 return RegisterList(list_1.list_ & list_2.list_); 516 } 517 static RegisterList Intersection(const RegisterList& list_1, 518 const RegisterList& list_2, 519 const RegisterList& list_3) { 520 return Intersection(list_1, Intersection(list_2, list_3)); 521 } 522 static RegisterList Intersection(const RegisterList& list_1, 523 const RegisterList& list_2, 524 const RegisterList& list_3, 525 const RegisterList& list_4) { 526 return Intersection(Intersection(list_1, list_2), 527 Intersection(list_3, list_4)); 528 } 529 530 private: 531 static constexpr uint32_t RegisterToList(Register reg) { 532 if (reg.GetType() == CPURegister::kNoRegister) { 533 return 0; 534 } else { 535 return UINT32_C(1) << reg.GetCode(); 536 } 537 } 538 539 // Bitfield representation of all registers in the list 540 // (1 for r0, 2 for r1, 4 for r2, ...). 541 uint32_t list_; 542 }; 543 544 inline uint32_t GetRegisterListEncoding(const RegisterList& registers, 545 int first, 546 int count) { 547 return (registers.GetList() >> first) & ((1 << count) - 1); 548 } 549 550 std::ostream& operator<<(std::ostream& os, RegisterList registers); 551 552 class VRegisterList { 553 public: 554 VRegisterList() : list_(0) {} 555 explicit VRegisterList(VRegister reg) : list_(RegisterToList(reg)) {} 556 VRegisterList(VRegister reg1, VRegister reg2) 557 : list_(RegisterToList(reg1) | RegisterToList(reg2)) {} 558 VRegisterList(VRegister reg1, VRegister reg2, VRegister reg3) 559 : list_(RegisterToList(reg1) | RegisterToList(reg2) | 560 RegisterToList(reg3)) {} 561 VRegisterList(VRegister reg1, VRegister reg2, VRegister reg3, VRegister reg4) 562 : list_(RegisterToList(reg1) | RegisterToList(reg2) | 563 RegisterToList(reg3) | RegisterToList(reg4)) {} 564 explicit VRegisterList(uint64_t list) : list_(list) {} 565 uint64_t GetList() const { return list_; } 566 int GetCount() const { return CountSetBits(list_); } 567 void SetList(uint64_t list) { list_ = list; } 568 // Because differently-sized V registers overlap with one another, there is no 569 // way to implement a single 'Includes' function in a way that is unsurprising 570 // for all existing uses. 571 bool IncludesAllOf(const VRegister& reg) const { 572 return (list_ & RegisterToList(reg)) == RegisterToList(reg); 573 } 574 bool IncludesAliasOf(const VRegister& reg) const { 575 return (list_ & RegisterToList(reg)) != 0; 576 } 577 void Combine(const VRegisterList& other) { list_ |= other.GetList(); } 578 void Combine(const VRegister& reg) { list_ |= RegisterToList(reg); } 579 void Remove(const VRegisterList& other) { list_ &= ~other.GetList(); } 580 void Remove(const VRegister& reg) { list_ &= ~RegisterToList(reg); } 581 bool Overlaps(const VRegisterList& other) const { 582 return (list_ & other.list_) != 0; 583 } 584 QRegister GetFirstAvailableQRegister() const; 585 DRegister GetFirstAvailableDRegister() const; 586 SRegister GetFirstAvailableSRegister() const; 587 bool IsEmpty() const { return list_ == 0; } 588 static VRegisterList Union(const VRegisterList& list_1, 589 const VRegisterList& list_2) { 590 return VRegisterList(list_1.list_ | list_2.list_); 591 } 592 static VRegisterList Union(const VRegisterList& list_1, 593 const VRegisterList& list_2, 594 const VRegisterList& list_3) { 595 return Union(list_1, Union(list_2, list_3)); 596 } 597 static VRegisterList Union(const VRegisterList& list_1, 598 const VRegisterList& list_2, 599 const VRegisterList& list_3, 600 const VRegisterList& list_4) { 601 return Union(Union(list_1, list_2), Union(list_3, list_4)); 602 } 603 static VRegisterList Intersection(const VRegisterList& list_1, 604 const VRegisterList& list_2) { 605 return VRegisterList(list_1.list_ & list_2.list_); 606 } 607 static VRegisterList Intersection(const VRegisterList& list_1, 608 const VRegisterList& list_2, 609 const VRegisterList& list_3) { 610 return Intersection(list_1, Intersection(list_2, list_3)); 611 } 612 static VRegisterList Intersection(const VRegisterList& list_1, 613 const VRegisterList& list_2, 614 const VRegisterList& list_3, 615 const VRegisterList& list_4) { 616 return Intersection(Intersection(list_1, list_2), 617 Intersection(list_3, list_4)); 618 } 619 620 private: 621 static uint64_t RegisterToList(VRegister reg) { 622 if (reg.GetType() == CPURegister::kNoRegister) { 623 return 0; 624 } else { 625 switch (reg.GetSizeInBits()) { 626 case kQRegSizeInBits: 627 return UINT64_C(0xf) << (reg.GetCode() * 4); 628 case kDRegSizeInBits: 629 return UINT64_C(0x3) << (reg.GetCode() * 2); 630 case kSRegSizeInBits: 631 return UINT64_C(0x1) << reg.GetCode(); 632 default: 633 VIXL_UNREACHABLE(); 634 return 0; 635 } 636 } 637 } 638 639 // Bitfield representation of all registers in the list. 640 // (0x3 for d0, 0xc0 for d1, 0x30 for d2, ...). We have one, two or four bits 641 // per register according to their size. This way we can make sure that we 642 // account for overlapping registers. 643 // A register is wholly included in this list only if all of its bits are set. 644 // A register is aliased by the list if at least one of its bits are set. 645 // The IncludesAllOf and IncludesAliasOf helpers are provided to make this 646 // distinction clear. 647 uint64_t list_; 648 }; 649 650 class SRegisterList { 651 SRegister first_; 652 int length_; 653 654 public: 655 explicit SRegisterList(SRegister reg) : first_(reg.GetCode()), length_(1) {} 656 SRegisterList(SRegister first, int length) 657 : first_(first.GetCode()), length_(length) { 658 VIXL_ASSERT(length >= 0); 659 } 660 SRegister GetSRegister(int n) const { 661 VIXL_ASSERT(n >= 0); 662 VIXL_ASSERT(n < length_); 663 return SRegister((first_.GetCode() + n) % kNumberOfSRegisters); 664 } 665 const SRegister& GetFirstSRegister() const { return first_; } 666 SRegister GetLastSRegister() const { return GetSRegister(length_ - 1); } 667 int GetLength() const { return length_; } 668 }; 669 670 std::ostream& operator<<(std::ostream& os, SRegisterList registers); 671 672 class DRegisterList { 673 DRegister first_; 674 int length_; 675 676 public: 677 explicit DRegisterList(DRegister reg) : first_(reg.GetCode()), length_(1) {} 678 DRegisterList(DRegister first, int length) 679 : first_(first.GetCode()), length_(length) { 680 VIXL_ASSERT(length >= 0); 681 } 682 DRegister GetDRegister(int n) const { 683 VIXL_ASSERT(n >= 0); 684 VIXL_ASSERT(n < length_); 685 return DRegister((first_.GetCode() + n) % kMaxNumberOfDRegisters); 686 } 687 const DRegister& GetFirstDRegister() const { return first_; } 688 DRegister GetLastDRegister() const { return GetDRegister(length_ - 1); } 689 int GetLength() const { return length_; } 690 }; 691 692 std::ostream& operator<<(std::ostream& os, DRegisterList registers); 693 694 enum SpacingType { kSingle, kDouble }; 695 696 enum TransferType { kMultipleLanes, kOneLane, kAllLanes }; 697 698 class NeonRegisterList { 699 DRegister first_; 700 SpacingType spacing_; 701 TransferType type_; 702 int lane_; 703 int length_; 704 705 public: 706 NeonRegisterList(DRegister reg, TransferType type) 707 : first_(reg.GetCode()), 708 spacing_(kSingle), 709 type_(type), 710 lane_(-1), 711 length_(1) { 712 VIXL_ASSERT(type_ != kOneLane); 713 } 714 NeonRegisterList(DRegister reg, int lane) 715 : first_(reg.GetCode()), 716 spacing_(kSingle), 717 type_(kOneLane), 718 lane_(lane), 719 length_(1) { 720 VIXL_ASSERT((lane_ >= 0) && (lane_ < 8)); 721 } 722 NeonRegisterList(DRegister first, 723 DRegister last, 724 SpacingType spacing, 725 TransferType type) 726 : first_(first.GetCode()), spacing_(spacing), type_(type), lane_(-1) { 727 VIXL_ASSERT(type != kOneLane); 728 VIXL_ASSERT(first.GetCode() <= last.GetCode()); 729 730 int range = last.GetCode() - first.GetCode(); 731 VIXL_ASSERT(IsSingleSpaced() || IsMultiple(range, 2)); 732 length_ = (IsDoubleSpaced() ? (range / 2) : range) + 1; 733 734 VIXL_ASSERT(length_ <= 4); 735 } 736 NeonRegisterList(DRegister first, 737 DRegister last, 738 SpacingType spacing, 739 int lane) 740 : first_(first.GetCode()), 741 spacing_(spacing), 742 type_(kOneLane), 743 lane_(lane) { 744 VIXL_ASSERT((lane >= 0) && (lane < 8)); 745 VIXL_ASSERT(first.GetCode() <= last.GetCode()); 746 747 int range = last.GetCode() - first.GetCode(); 748 VIXL_ASSERT(IsSingleSpaced() || IsMultiple(range, 2)); 749 length_ = (IsDoubleSpaced() ? (range / 2) : range) + 1; 750 751 VIXL_ASSERT(length_ <= 4); 752 } 753 DRegister GetDRegister(int n) const { 754 VIXL_ASSERT(n >= 0); 755 VIXL_ASSERT(n < length_); 756 unsigned code = first_.GetCode() + (IsDoubleSpaced() ? (2 * n) : n); 757 VIXL_ASSERT(code < kMaxNumberOfDRegisters); 758 return DRegister(code); 759 } 760 const DRegister& GetFirstDRegister() const { return first_; } 761 DRegister GetLastDRegister() const { return GetDRegister(length_ - 1); } 762 int GetLength() const { return length_; } 763 bool IsSingleSpaced() const { return spacing_ == kSingle; } 764 bool IsDoubleSpaced() const { return spacing_ == kDouble; } 765 bool IsTransferAllLanes() const { return type_ == kAllLanes; } 766 bool IsTransferOneLane() const { return type_ == kOneLane; } 767 bool IsTransferMultipleLanes() const { return type_ == kMultipleLanes; } 768 int GetTransferLane() const { return lane_; } 769 }; 770 771 std::ostream& operator<<(std::ostream& os, NeonRegisterList registers); 772 773 enum SpecialRegisterType { APSR = 0, CPSR = 0, SPSR = 1 }; 774 775 class SpecialRegister { 776 uint32_t reg_; 777 778 public: 779 explicit SpecialRegister(uint32_t reg) : reg_(reg) {} 780 SpecialRegister(SpecialRegisterType reg) // NOLINT(runtime/explicit) 781 : reg_(reg) {} 782 uint32_t GetReg() const { return reg_; } 783 const char* GetName() const; 784 bool Is(SpecialRegister value) const { return reg_ == value.reg_; } 785 bool Is(uint32_t value) const { return reg_ == value; } 786 bool IsNot(uint32_t value) const { return reg_ != value; } 787 }; 788 789 inline std::ostream& operator<<(std::ostream& os, SpecialRegister reg) { 790 return os << reg.GetName(); 791 } 792 793 enum BankedRegisterType { 794 R8_usr = 0x00, 795 R9_usr = 0x01, 796 R10_usr = 0x02, 797 R11_usr = 0x03, 798 R12_usr = 0x04, 799 SP_usr = 0x05, 800 LR_usr = 0x06, 801 R8_fiq = 0x08, 802 R9_fiq = 0x09, 803 R10_fiq = 0x0a, 804 R11_fiq = 0x0b, 805 R12_fiq = 0x0c, 806 SP_fiq = 0x0d, 807 LR_fiq = 0x0e, 808 LR_irq = 0x10, 809 SP_irq = 0x11, 810 LR_svc = 0x12, 811 SP_svc = 0x13, 812 LR_abt = 0x14, 813 SP_abt = 0x15, 814 LR_und = 0x16, 815 SP_und = 0x17, 816 LR_mon = 0x1c, 817 SP_mon = 0x1d, 818 ELR_hyp = 0x1e, 819 SP_hyp = 0x1f, 820 SPSR_fiq = 0x2e, 821 SPSR_irq = 0x30, 822 SPSR_svc = 0x32, 823 SPSR_abt = 0x34, 824 SPSR_und = 0x36, 825 SPSR_mon = 0x3c, 826 SPSR_hyp = 0x3e 827 }; 828 829 class BankedRegister { 830 uint32_t reg_; 831 832 public: 833 explicit BankedRegister(unsigned reg) : reg_(reg) {} 834 BankedRegister(BankedRegisterType reg) // NOLINT(runtime/explicit) 835 : reg_(reg) {} 836 uint32_t GetCode() const { return reg_; } 837 const char* GetName() const; 838 }; 839 840 inline std::ostream& operator<<(std::ostream& os, BankedRegister reg) { 841 return os << reg.GetName(); 842 } 843 844 enum MaskedSpecialRegisterType { 845 APSR_nzcvq = 0x08, 846 APSR_g = 0x04, 847 APSR_nzcvqg = 0x0c, 848 CPSR_c = 0x01, 849 CPSR_x = 0x02, 850 CPSR_xc = 0x03, 851 CPSR_s = APSR_g, 852 CPSR_sc = 0x05, 853 CPSR_sx = 0x06, 854 CPSR_sxc = 0x07, 855 CPSR_f = APSR_nzcvq, 856 CPSR_fc = 0x09, 857 CPSR_fx = 0x0a, 858 CPSR_fxc = 0x0b, 859 CPSR_fs = APSR_nzcvqg, 860 CPSR_fsc = 0x0d, 861 CPSR_fsx = 0x0e, 862 CPSR_fsxc = 0x0f, 863 SPSR_c = 0x11, 864 SPSR_x = 0x12, 865 SPSR_xc = 0x13, 866 SPSR_s = 0x14, 867 SPSR_sc = 0x15, 868 SPSR_sx = 0x16, 869 SPSR_sxc = 0x17, 870 SPSR_f = 0x18, 871 SPSR_fc = 0x19, 872 SPSR_fx = 0x1a, 873 SPSR_fxc = 0x1b, 874 SPSR_fs = 0x1c, 875 SPSR_fsc = 0x1d, 876 SPSR_fsx = 0x1e, 877 SPSR_fsxc = 0x1f 878 }; 879 880 class MaskedSpecialRegister { 881 uint32_t reg_; 882 883 public: 884 explicit MaskedSpecialRegister(uint32_t reg) : reg_(reg) { 885 VIXL_ASSERT(reg <= SPSR_fsxc); 886 } 887 MaskedSpecialRegister( 888 MaskedSpecialRegisterType reg) // NOLINT(runtime/explicit) 889 : reg_(reg) {} 890 uint32_t GetReg() const { return reg_; } 891 const char* GetName() const; 892 bool Is(MaskedSpecialRegister value) const { return reg_ == value.reg_; } 893 bool Is(uint32_t value) const { return reg_ == value; } 894 bool IsNot(uint32_t value) const { return reg_ != value; } 895 }; 896 897 inline std::ostream& operator<<(std::ostream& os, MaskedSpecialRegister reg) { 898 return os << reg.GetName(); 899 } 900 901 enum SpecialFPRegisterType { 902 FPSID = 0x0, 903 FPSCR = 0x1, 904 MVFR2 = 0x5, 905 MVFR1 = 0x6, 906 MVFR0 = 0x7, 907 FPEXC = 0x8 908 }; 909 910 class SpecialFPRegister { 911 uint32_t reg_; 912 913 public: 914 explicit SpecialFPRegister(uint32_t reg) : reg_(reg) { 915 #ifdef VIXL_DEBUG 916 switch (reg) { 917 case FPSID: 918 case FPSCR: 919 case MVFR2: 920 case MVFR1: 921 case MVFR0: 922 case FPEXC: 923 break; 924 default: 925 VIXL_UNREACHABLE(); 926 } 927 #endif 928 } 929 SpecialFPRegister(SpecialFPRegisterType reg) // NOLINT(runtime/explicit) 930 : reg_(reg) {} 931 uint32_t GetReg() const { return reg_; } 932 const char* GetName() const; 933 bool Is(SpecialFPRegister value) const { return reg_ == value.reg_; } 934 bool Is(uint32_t value) const { return reg_ == value; } 935 bool IsNot(uint32_t value) const { return reg_ != value; } 936 }; 937 938 inline std::ostream& operator<<(std::ostream& os, SpecialFPRegister reg) { 939 return os << reg.GetName(); 940 } 941 942 class CRegister { 943 uint32_t code_; 944 945 public: 946 explicit CRegister(uint32_t code) : code_(code) { 947 VIXL_ASSERT(code < kNumberOfRegisters); 948 } 949 uint32_t GetCode() const { return code_; } 950 bool Is(CRegister value) const { return code_ == value.code_; } 951 }; 952 953 inline std::ostream& operator<<(std::ostream& os, const CRegister reg) { 954 return os << "c" << reg.GetCode(); 955 } 956 957 // clang-format off 958 #define CREGISTER_CODE_LIST(R) \ 959 R(0) R(1) R(2) R(3) R(4) R(5) R(6) R(7) \ 960 R(8) R(9) R(10) R(11) R(12) R(13) R(14) R(15) 961 // clang-format on 962 #define DEFINE_CREGISTER(N) const CRegister c##N(N); 963 CREGISTER_CODE_LIST(DEFINE_CREGISTER) 964 965 enum CoprocessorName { p10 = 10, p11 = 11, p14 = 14, p15 = 15 }; 966 967 class Coprocessor { 968 uint32_t coproc_; 969 970 public: 971 explicit Coprocessor(uint32_t coproc) : coproc_(coproc) {} 972 Coprocessor(CoprocessorName coproc) // NOLINT(runtime/explicit) 973 : coproc_(static_cast<uint32_t>(coproc)) {} 974 bool Is(Coprocessor coproc) const { return coproc_ == coproc.coproc_; } 975 bool Is(CoprocessorName coproc) const { return coproc_ == coproc; } 976 uint32_t GetCoprocessor() const { return coproc_; } 977 }; 978 979 inline std::ostream& operator<<(std::ostream& os, Coprocessor coproc) { 980 return os << "p" << coproc.GetCoprocessor(); 981 } 982 983 enum ConditionType { 984 eq = 0, 985 ne = 1, 986 cs = 2, 987 cc = 3, 988 mi = 4, 989 pl = 5, 990 vs = 6, 991 vc = 7, 992 hi = 8, 993 ls = 9, 994 ge = 10, 995 lt = 11, 996 gt = 12, 997 le = 13, 998 al = 14, 999 hs = cs, 1000 lo = cc 1001 }; 1002 1003 class Condition { 1004 uint32_t condition_; 1005 static const uint32_t kNever = 15; 1006 static const uint32_t kMask = 0xf; 1007 static const uint32_t kNone = 0x10 | al; 1008 1009 public: 1010 static const Condition None() { return Condition(kNone); } 1011 static const Condition Never() { return Condition(kNever); } 1012 explicit Condition(uint32_t condition) : condition_(condition) { 1013 VIXL_ASSERT(condition <= kNone); 1014 } 1015 // Users should be able to use "eq", "ne" and so forth to instantiate this 1016 // class. 1017 Condition(ConditionType condition) // NOLINT(runtime/explicit) 1018 : condition_(condition) {} 1019 uint32_t GetCondition() const { return condition_ & kMask; } 1020 bool IsNone() const { return condition_ == kNone; } 1021 const char* GetName() const; 1022 bool Is(Condition value) const { return condition_ == value.condition_; } 1023 bool Is(uint32_t value) const { return condition_ == value; } 1024 bool IsNot(uint32_t value) const { return condition_ != value; } 1025 bool IsNever() const { return condition_ == kNever; } 1026 bool IsNotNever() const { return condition_ != kNever; } 1027 Condition Negate() const { 1028 VIXL_ASSERT(IsNot(al) && IsNot(kNever)); 1029 return Condition(condition_ ^ 1); 1030 } 1031 }; 1032 1033 inline std::ostream& operator<<(std::ostream& os, Condition condition) { 1034 return os << condition.GetName(); 1035 } 1036 1037 enum SignType { plus, minus }; 1038 1039 class Sign { 1040 public: 1041 Sign() : sign_(plus) {} 1042 Sign(SignType sign) : sign_(sign) {} // NOLINT(runtime/explicit) 1043 const char* GetName() const { return (IsPlus() ? "" : "-"); } 1044 bool IsPlus() const { return sign_ == plus; } 1045 bool IsMinus() const { return sign_ == minus; } 1046 int32_t ApplyTo(uint32_t value) { 1047 return IsPlus() ? value : UnsignedNegate(value); 1048 } 1049 1050 private: 1051 SignType sign_; 1052 }; 1053 1054 inline std::ostream& operator<<(std::ostream& os, Sign sign) { 1055 return os << sign.GetName(); 1056 } 1057 1058 enum ShiftType { LSL = 0x0, LSR = 0x1, ASR = 0x2, ROR = 0x3, RRX = 0x4 }; 1059 1060 class Shift { 1061 public: 1062 Shift() : shift_(LSL) {} 1063 Shift(ShiftType shift) : shift_(shift) {} // NOLINT(runtime/explicit) 1064 explicit Shift(uint32_t shift) : shift_(static_cast<ShiftType>(shift)) {} 1065 const Shift& GetShift() const { return *this; } 1066 ShiftType GetType() const { return shift_; } 1067 uint32_t GetValue() const { return shift_; } 1068 const char* GetName() const; 1069 bool IsLSL() const { return shift_ == LSL; } 1070 bool IsLSR() const { return shift_ == LSR; } 1071 bool IsASR() const { return shift_ == ASR; } 1072 bool IsROR() const { return shift_ == ROR; } 1073 bool IsRRX() const { return shift_ == RRX; } 1074 bool Is(Shift value) const { return shift_ == value.shift_; } 1075 bool IsNot(Shift value) const { return shift_ != value.shift_; } 1076 bool IsValidAmount(uint32_t amount) const; 1077 static const Shift NoShift; 1078 1079 protected: 1080 void SetType(ShiftType s) { shift_ = s; } 1081 1082 private: 1083 ShiftType shift_; 1084 }; 1085 1086 inline std::ostream& operator<<(std::ostream& os, Shift shift) { 1087 return os << shift.GetName(); 1088 } 1089 1090 class ImmediateShiftOperand : public Shift { 1091 public: 1092 // Constructor used for assembly. 1093 ImmediateShiftOperand(Shift shift, uint32_t amount) 1094 : Shift(shift), amount_(amount) { 1095 #ifdef VIXL_DEBUG 1096 switch (shift.GetType()) { 1097 case LSL: 1098 VIXL_ASSERT(amount <= 31); 1099 break; 1100 case ROR: 1101 VIXL_ASSERT(amount > 0); 1102 VIXL_ASSERT(amount <= 31); 1103 break; 1104 case LSR: 1105 case ASR: 1106 VIXL_ASSERT(amount > 0); 1107 VIXL_ASSERT(amount <= 32); 1108 break; 1109 case RRX: 1110 VIXL_ASSERT(amount == 0); 1111 break; 1112 default: 1113 VIXL_UNREACHABLE(); 1114 break; 1115 } 1116 #endif 1117 } 1118 // Constructor used for disassembly. 1119 ImmediateShiftOperand(int shift, int amount); 1120 uint32_t GetAmount() const { return amount_; } 1121 bool Is(const ImmediateShiftOperand& rhs) const { 1122 return amount_ == (rhs.amount_) && Shift::Is(*this); 1123 } 1124 1125 private: 1126 uint32_t amount_; 1127 }; 1128 1129 inline std::ostream& operator<<(std::ostream& os, 1130 ImmediateShiftOperand const& shift_operand) { 1131 if (shift_operand.IsLSL() && shift_operand.GetAmount() == 0) return os; 1132 if (shift_operand.IsRRX()) return os << ", rrx"; 1133 return os << ", " << shift_operand.GetName() << " #" 1134 << shift_operand.GetAmount(); 1135 } 1136 1137 class RegisterShiftOperand : public Shift { 1138 public: 1139 RegisterShiftOperand(ShiftType shift, Register shift_register) 1140 : Shift(shift), shift_register_(shift_register) { 1141 VIXL_ASSERT(!IsRRX() && shift_register_.IsValid()); 1142 } 1143 const Register GetShiftRegister() const { return shift_register_; } 1144 bool Is(const RegisterShiftOperand& rhs) const { 1145 return shift_register_.Is(rhs.shift_register_) && Shift::Is(*this); 1146 } 1147 1148 private: 1149 Register shift_register_; 1150 }; 1151 1152 inline std::ostream& operator<<(std::ostream& s, 1153 const RegisterShiftOperand& shift_operand) { 1154 return s << shift_operand.GetName() << " " 1155 << shift_operand.GetShiftRegister(); 1156 } 1157 1158 enum EncodingSizeType { Best, Narrow, Wide }; 1159 1160 class EncodingSize { 1161 uint32_t size_; 1162 1163 public: 1164 explicit EncodingSize(uint32_t size) : size_(size) {} 1165 EncodingSize(EncodingSizeType size) // NOLINT(runtime/explicit) 1166 : size_(size) {} 1167 uint32_t GetSize() const { return size_; } 1168 const char* GetName() const; 1169 bool IsBest() const { return size_ == Best; } 1170 bool IsNarrow() const { return size_ == Narrow; } 1171 bool IsWide() const { return size_ == Wide; } 1172 }; 1173 1174 inline std::ostream& operator<<(std::ostream& os, EncodingSize size) { 1175 return os << size.GetName(); 1176 } 1177 1178 enum WriteBackValue { NO_WRITE_BACK, WRITE_BACK }; 1179 1180 class WriteBack { 1181 WriteBackValue value_; 1182 1183 public: 1184 WriteBack(WriteBackValue value) // NOLINT(runtime/explicit) 1185 : value_(value) {} 1186 explicit WriteBack(int value) 1187 : value_((value == 0) ? NO_WRITE_BACK : WRITE_BACK) {} 1188 uint32_t GetWriteBackUint32() const { return (value_ == WRITE_BACK) ? 1 : 0; } 1189 bool DoesWriteBack() const { return value_ == WRITE_BACK; } 1190 }; 1191 1192 inline std::ostream& operator<<(std::ostream& os, WriteBack write_back) { 1193 if (write_back.DoesWriteBack()) return os << "!"; 1194 return os; 1195 } 1196 1197 class EncodingValue { 1198 bool valid_; 1199 uint32_t encoding_value_; 1200 1201 public: 1202 EncodingValue() { 1203 valid_ = false; 1204 encoding_value_ = 0; 1205 } 1206 bool IsValid() const { return valid_; } 1207 uint32_t GetEncodingValue() const { return encoding_value_; } 1208 void SetEncodingValue(uint32_t encoding_value) { 1209 valid_ = true; 1210 encoding_value_ = encoding_value; 1211 } 1212 }; 1213 1214 class EncodingValueAndImmediate : public EncodingValue { 1215 uint32_t encoded_immediate_; 1216 1217 public: 1218 EncodingValueAndImmediate() { encoded_immediate_ = 0; } 1219 uint32_t GetEncodedImmediate() const { return encoded_immediate_; } 1220 void SetEncodedImmediate(uint32_t encoded_immediate) { 1221 encoded_immediate_ = encoded_immediate; 1222 } 1223 }; 1224 1225 class ImmediateT32 : public EncodingValue { 1226 public: 1227 explicit ImmediateT32(uint32_t imm); 1228 static bool IsImmediateT32(uint32_t imm); 1229 static uint32_t Decode(uint32_t value); 1230 }; 1231 1232 class ImmediateA32 : public EncodingValue { 1233 public: 1234 explicit ImmediateA32(uint32_t imm); 1235 static bool IsImmediateA32(uint32_t imm); 1236 static uint32_t Decode(uint32_t value); 1237 }; 1238 1239 // Return the encoding value of a shift type. 1240 uint32_t TypeEncodingValue(Shift shift); 1241 // Return the encoding value for a shift amount depending on the shift type. 1242 uint32_t AmountEncodingValue(Shift shift, uint32_t amount); 1243 1244 enum MemoryBarrierType { 1245 OSHLD = 0x1, 1246 OSHST = 0x2, 1247 OSH = 0x3, 1248 NSHLD = 0x5, 1249 NSHST = 0x6, 1250 NSH = 0x7, 1251 ISHLD = 0x9, 1252 ISHST = 0xa, 1253 ISH = 0xb, 1254 LD = 0xd, 1255 ST = 0xe, 1256 SY = 0xf 1257 }; 1258 1259 class MemoryBarrier { 1260 MemoryBarrierType type_; 1261 1262 public: 1263 MemoryBarrier(MemoryBarrierType type) // NOLINT(runtime/explicit) 1264 : type_(type) {} 1265 MemoryBarrier(uint32_t type) // NOLINT(runtime/explicit) 1266 : type_(static_cast<MemoryBarrierType>(type)) { 1267 VIXL_ASSERT((type & 0x3) != 0); 1268 } 1269 MemoryBarrierType GetType() const { return type_; } 1270 const char* GetName() const; 1271 }; 1272 1273 inline std::ostream& operator<<(std::ostream& os, MemoryBarrier option) { 1274 return os << option.GetName(); 1275 } 1276 1277 enum InterruptFlagsType { 1278 F = 0x1, 1279 I = 0x2, 1280 IF = 0x3, 1281 A = 0x4, 1282 AF = 0x5, 1283 AI = 0x6, 1284 AIF = 0x7 1285 }; 1286 1287 class InterruptFlags { 1288 InterruptFlagsType type_; 1289 1290 public: 1291 InterruptFlags(InterruptFlagsType type) // NOLINT(runtime/explicit) 1292 : type_(type) {} 1293 InterruptFlags(uint32_t type) // NOLINT(runtime/explicit) 1294 : type_(static_cast<InterruptFlagsType>(type)) { 1295 VIXL_ASSERT(type <= 7); 1296 } 1297 InterruptFlagsType GetType() const { return type_; } 1298 const char* GetName() const; 1299 }; 1300 1301 inline std::ostream& operator<<(std::ostream& os, InterruptFlags option) { 1302 return os << option.GetName(); 1303 } 1304 1305 enum EndiannessType { LE = 0, BE = 1 }; 1306 1307 class Endianness { 1308 EndiannessType type_; 1309 1310 public: 1311 Endianness(EndiannessType type) : type_(type) {} // NOLINT(runtime/explicit) 1312 Endianness(uint32_t type) // NOLINT(runtime/explicit) 1313 : type_(static_cast<EndiannessType>(type)) { 1314 VIXL_ASSERT(type <= 1); 1315 } 1316 EndiannessType GetType() const { return type_; } 1317 const char* GetName() const; 1318 }; 1319 1320 inline std::ostream& operator<<(std::ostream& os, Endianness endian_specifier) { 1321 return os << endian_specifier.GetName(); 1322 } 1323 1324 enum AlignmentType { 1325 k16BitAlign = 0, 1326 k32BitAlign = 1, 1327 k64BitAlign = 2, 1328 k128BitAlign = 3, 1329 k256BitAlign = 4, 1330 kNoAlignment = 5, 1331 kBadAlignment = 6 1332 }; 1333 1334 class Alignment { 1335 AlignmentType align_; 1336 1337 public: 1338 Alignment(AlignmentType align) // NOLINT(runtime/explicit) 1339 : align_(align) {} 1340 Alignment(uint32_t align) // NOLINT(runtime/explicit) 1341 : align_(static_cast<AlignmentType>(align)) { 1342 VIXL_ASSERT(align <= static_cast<uint32_t>(k256BitAlign)); 1343 } 1344 AlignmentType GetType() const { return align_; } 1345 bool Is(AlignmentType type) { return align_ == type; } 1346 }; 1347 1348 inline std::ostream& operator<<(std::ostream& os, Alignment align) { 1349 if (align.GetType() == kBadAlignment) return os << " :??"; 1350 if (align.GetType() == kNoAlignment) return os; 1351 return os << " :" << (0x10 << static_cast<uint32_t>(align.GetType())); 1352 } 1353 1354 // Structure containing information on forward references. 1355 struct ReferenceInfo { 1356 int size; 1357 int min_offset; 1358 int max_offset; 1359 int alignment; // As a power of two. 1360 enum { kAlignPc, kDontAlignPc } pc_needs_aligning; 1361 }; 1362 1363 } // namespace aarch32 1364 } // namespace vixl 1365 1366 #endif // VIXL_AARCH32_INSTRUCTIONS_AARCH32_H_ 1367