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