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