1 // Copyright 2013 the V8 project authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef V8_ARM64_ASSEMBLER_ARM64_H_ 6 #define V8_ARM64_ASSEMBLER_ARM64_H_ 7 8 #include <deque> 9 #include <list> 10 #include <map> 11 #include <vector> 12 13 #include "src/arm64/instructions-arm64.h" 14 #include "src/assembler.h" 15 #include "src/globals.h" 16 #include "src/utils.h" 17 18 19 namespace v8 { 20 namespace internal { 21 22 23 // ----------------------------------------------------------------------------- 24 // Registers. 25 // clang-format off 26 #define GENERAL_REGISTER_CODE_LIST(R) \ 27 R(0) R(1) R(2) R(3) R(4) R(5) R(6) R(7) \ 28 R(8) R(9) R(10) R(11) R(12) R(13) R(14) R(15) \ 29 R(16) R(17) R(18) R(19) R(20) R(21) R(22) R(23) \ 30 R(24) R(25) R(26) R(27) R(28) R(29) R(30) R(31) 31 32 #define GENERAL_REGISTERS(R) \ 33 R(x0) R(x1) R(x2) R(x3) R(x4) R(x5) R(x6) R(x7) \ 34 R(x8) R(x9) R(x10) R(x11) R(x12) R(x13) R(x14) R(x15) \ 35 R(x16) R(x17) R(x18) R(x19) R(x20) R(x21) R(x22) R(x23) \ 36 R(x24) R(x25) R(x26) R(x27) R(x28) R(x29) R(x30) R(x31) 37 38 #define ALLOCATABLE_GENERAL_REGISTERS(R) \ 39 R(x0) R(x1) R(x2) R(x3) R(x4) R(x5) R(x6) R(x7) \ 40 R(x8) R(x9) R(x10) R(x11) R(x12) R(x13) R(x14) R(x15) \ 41 R(x18) R(x19) R(x20) R(x21) R(x22) R(x23) R(x24) R(x27) 42 43 #define DOUBLE_REGISTERS(R) \ 44 R(d0) R(d1) R(d2) R(d3) R(d4) R(d5) R(d6) R(d7) \ 45 R(d8) R(d9) R(d10) R(d11) R(d12) R(d13) R(d14) R(d15) \ 46 R(d16) R(d17) R(d18) R(d19) R(d20) R(d21) R(d22) R(d23) \ 47 R(d24) R(d25) R(d26) R(d27) R(d28) R(d29) R(d30) R(d31) 48 49 #define ALLOCATABLE_DOUBLE_REGISTERS(R) \ 50 R(d0) R(d1) R(d2) R(d3) R(d4) R(d5) R(d6) R(d7) \ 51 R(d8) R(d9) R(d10) R(d11) R(d12) R(d13) R(d14) R(d16) \ 52 R(d17) R(d18) R(d19) R(d20) R(d21) R(d22) R(d23) R(d24) \ 53 R(d25) R(d26) R(d27) R(d28) 54 // clang-format on 55 56 static const int kRegListSizeInBits = sizeof(RegList) * kBitsPerByte; 57 58 59 // Some CPURegister methods can return Register and FPRegister types, so we 60 // need to declare them in advance. 61 struct Register; 62 struct FPRegister; 63 64 65 struct CPURegister { 66 enum Code { 67 #define REGISTER_CODE(R) kCode_##R, 68 GENERAL_REGISTERS(REGISTER_CODE) 69 #undef REGISTER_CODE 70 kAfterLast, 71 kCode_no_reg = -1 72 }; 73 74 enum RegisterType { 75 // The kInvalid value is used to detect uninitialized static instances, 76 // which are always zero-initialized before any constructors are called. 77 kInvalid = 0, 78 kRegister, 79 kFPRegister, 80 kNoRegister 81 }; 82 CreateCPURegister83 static CPURegister Create(int code, int size, RegisterType type) { 84 CPURegister r = {code, size, type}; 85 return r; 86 } 87 88 int code() const; 89 RegisterType type() const; 90 RegList Bit() const; 91 int SizeInBits() const; 92 int SizeInBytes() const; 93 bool Is32Bits() const; 94 bool Is64Bits() const; 95 bool IsValid() const; 96 bool IsValidOrNone() const; 97 bool IsValidRegister() const; 98 bool IsValidFPRegister() const; 99 bool IsNone() const; 100 bool Is(const CPURegister& other) const; 101 bool Aliases(const CPURegister& other) const; 102 103 bool IsZero() const; 104 bool IsSP() const; 105 106 bool IsRegister() const; 107 bool IsFPRegister() const; 108 109 Register X() const; 110 Register W() const; 111 FPRegister D() const; 112 FPRegister S() const; 113 114 bool IsSameSizeAndType(const CPURegister& other) const; 115 116 // V8 compatibility. isCPURegister117 bool is(const CPURegister& other) const { return Is(other); } is_validCPURegister118 bool is_valid() const { return IsValid(); } 119 120 int reg_code; 121 int reg_size; 122 RegisterType reg_type; 123 }; 124 125 126 struct Register : public CPURegister { CreateRegister127 static Register Create(int code, int size) { 128 return Register(CPURegister::Create(code, size, CPURegister::kRegister)); 129 } 130 RegisterRegister131 Register() { 132 reg_code = 0; 133 reg_size = 0; 134 reg_type = CPURegister::kNoRegister; 135 } 136 RegisterRegister137 explicit Register(const CPURegister& r) { 138 reg_code = r.reg_code; 139 reg_size = r.reg_size; 140 reg_type = r.reg_type; 141 DCHECK(IsValidOrNone()); 142 } 143 RegisterRegister144 Register(const Register& r) { // NOLINT(runtime/explicit) 145 reg_code = r.reg_code; 146 reg_size = r.reg_size; 147 reg_type = r.reg_type; 148 DCHECK(IsValidOrNone()); 149 } 150 151 const char* ToString(); 152 bool IsAllocatable() const; IsValidRegister153 bool IsValid() const { 154 DCHECK(IsRegister() || IsNone()); 155 return IsValidRegister(); 156 } 157 158 static Register XRegFromCode(unsigned code); 159 static Register WRegFromCode(unsigned code); 160 161 // Start of V8 compatibility section --------------------- 162 // These memebers are necessary for compilation. 163 // A few of them may be unused for now. 164 165 static const int kNumRegisters = kNumberOfRegisters; 166 STATIC_ASSERT(kNumRegisters == Code::kAfterLast); NumRegistersRegister167 static int NumRegisters() { return kNumRegisters; } 168 169 // We allow crankshaft to use the following registers: 170 // - x0 to x15 171 // - x18 to x24 172 // - x27 (also context) 173 // 174 // TODO(all): Register x25 is currently free and could be available for 175 // crankshaft, but we don't use it as we might use it as a per function 176 // literal pool pointer in the future. 177 // 178 // TODO(all): Consider storing cp in x25 to have only two ranges. 179 // We split allocatable registers in three ranges called 180 // - "low range" 181 // - "high range" 182 // - "context" 183 from_codeRegister184 static Register from_code(int code) { 185 // Always return an X register. 186 return Register::Create(code, kXRegSizeInBits); 187 } 188 189 // End of V8 compatibility section ----------------------- 190 }; 191 192 193 struct FPRegister : public CPURegister { 194 enum Code { 195 #define REGISTER_CODE(R) kCode_##R, 196 DOUBLE_REGISTERS(REGISTER_CODE) 197 #undef REGISTER_CODE 198 kAfterLast, 199 kCode_no_reg = -1 200 }; 201 CreateFPRegister202 static FPRegister Create(int code, int size) { 203 return FPRegister( 204 CPURegister::Create(code, size, CPURegister::kFPRegister)); 205 } 206 FPRegisterFPRegister207 FPRegister() { 208 reg_code = 0; 209 reg_size = 0; 210 reg_type = CPURegister::kNoRegister; 211 } 212 FPRegisterFPRegister213 explicit FPRegister(const CPURegister& r) { 214 reg_code = r.reg_code; 215 reg_size = r.reg_size; 216 reg_type = r.reg_type; 217 DCHECK(IsValidOrNone()); 218 } 219 FPRegisterFPRegister220 FPRegister(const FPRegister& r) { // NOLINT(runtime/explicit) 221 reg_code = r.reg_code; 222 reg_size = r.reg_size; 223 reg_type = r.reg_type; 224 DCHECK(IsValidOrNone()); 225 } 226 227 const char* ToString(); 228 bool IsAllocatable() const; IsValidFPRegister229 bool IsValid() const { 230 DCHECK(IsFPRegister() || IsNone()); 231 return IsValidFPRegister(); 232 } 233 234 static FPRegister SRegFromCode(unsigned code); 235 static FPRegister DRegFromCode(unsigned code); 236 237 // Start of V8 compatibility section --------------------- 238 static const int kMaxNumRegisters = kNumberOfFPRegisters; 239 STATIC_ASSERT(kMaxNumRegisters == Code::kAfterLast); 240 241 // Crankshaft can use all the FP registers except: 242 // - d15 which is used to keep the 0 double value 243 // - d30 which is used in crankshaft as a double scratch register 244 // - d31 which is used in the MacroAssembler as a double scratch register from_codeFPRegister245 static FPRegister from_code(int code) { 246 // Always return a D register. 247 return FPRegister::Create(code, kDRegSizeInBits); 248 } 249 // End of V8 compatibility section ----------------------- 250 }; 251 252 253 STATIC_ASSERT(sizeof(CPURegister) == sizeof(Register)); 254 STATIC_ASSERT(sizeof(CPURegister) == sizeof(FPRegister)); 255 256 257 #if defined(ARM64_DEFINE_REG_STATICS) 258 #define INITIALIZE_REGISTER(register_class, name, code, size, type) \ 259 const CPURegister init_##register_class##_##name = {code, size, type}; \ 260 const register_class& name = *reinterpret_cast<const register_class*>( \ 261 &init_##register_class##_##name) 262 #define ALIAS_REGISTER(register_class, alias, name) \ 263 const register_class& alias = *reinterpret_cast<const register_class*>( \ 264 &init_##register_class##_##name) 265 #else 266 #define INITIALIZE_REGISTER(register_class, name, code, size, type) \ 267 extern const register_class& name 268 #define ALIAS_REGISTER(register_class, alias, name) \ 269 extern const register_class& alias 270 #endif // defined(ARM64_DEFINE_REG_STATICS) 271 272 // No*Reg is used to indicate an unused argument, or an error case. Note that 273 // these all compare equal (using the Is() method). The Register and FPRegister 274 // variants are provided for convenience. 275 INITIALIZE_REGISTER(Register, NoReg, 0, 0, CPURegister::kNoRegister); 276 INITIALIZE_REGISTER(FPRegister, NoFPReg, 0, 0, CPURegister::kNoRegister); 277 INITIALIZE_REGISTER(CPURegister, NoCPUReg, 0, 0, CPURegister::kNoRegister); 278 279 // v8 compatibility. 280 INITIALIZE_REGISTER(Register, no_reg, 0, 0, CPURegister::kNoRegister); 281 282 #define DEFINE_REGISTERS(N) \ 283 INITIALIZE_REGISTER(Register, w##N, N, \ 284 kWRegSizeInBits, CPURegister::kRegister); \ 285 INITIALIZE_REGISTER(Register, x##N, N, \ 286 kXRegSizeInBits, CPURegister::kRegister); 287 GENERAL_REGISTER_CODE_LIST(DEFINE_REGISTERS) 288 #undef DEFINE_REGISTERS 289 290 INITIALIZE_REGISTER(Register, wcsp, kSPRegInternalCode, kWRegSizeInBits, 291 CPURegister::kRegister); 292 INITIALIZE_REGISTER(Register, csp, kSPRegInternalCode, kXRegSizeInBits, 293 CPURegister::kRegister); 294 295 #define DEFINE_FPREGISTERS(N) \ 296 INITIALIZE_REGISTER(FPRegister, s##N, N, \ 297 kSRegSizeInBits, CPURegister::kFPRegister); \ 298 INITIALIZE_REGISTER(FPRegister, d##N, N, \ 299 kDRegSizeInBits, CPURegister::kFPRegister); 300 GENERAL_REGISTER_CODE_LIST(DEFINE_FPREGISTERS) 301 #undef DEFINE_FPREGISTERS 302 303 #undef INITIALIZE_REGISTER 304 305 // Registers aliases. 306 ALIAS_REGISTER(Register, ip0, x16); 307 ALIAS_REGISTER(Register, ip1, x17); 308 ALIAS_REGISTER(Register, wip0, w16); 309 ALIAS_REGISTER(Register, wip1, w17); 310 // Root register. 311 ALIAS_REGISTER(Register, root, x26); 312 ALIAS_REGISTER(Register, rr, x26); 313 // Context pointer register. 314 ALIAS_REGISTER(Register, cp, x27); 315 // We use a register as a JS stack pointer to overcome the restriction on the 316 // architectural SP alignment. 317 // We chose x28 because it is contiguous with the other specific purpose 318 // registers. 319 STATIC_ASSERT(kJSSPCode == 28); 320 ALIAS_REGISTER(Register, jssp, x28); 321 ALIAS_REGISTER(Register, wjssp, w28); 322 ALIAS_REGISTER(Register, fp, x29); 323 ALIAS_REGISTER(Register, lr, x30); 324 ALIAS_REGISTER(Register, xzr, x31); 325 ALIAS_REGISTER(Register, wzr, w31); 326 327 // Keeps the 0 double value. 328 ALIAS_REGISTER(FPRegister, fp_zero, d15); 329 // Crankshaft double scratch register. 330 ALIAS_REGISTER(FPRegister, crankshaft_fp_scratch, d29); 331 // MacroAssembler double scratch registers. 332 ALIAS_REGISTER(FPRegister, fp_scratch, d30); 333 ALIAS_REGISTER(FPRegister, fp_scratch1, d30); 334 ALIAS_REGISTER(FPRegister, fp_scratch2, d31); 335 336 #undef ALIAS_REGISTER 337 338 339 Register GetAllocatableRegisterThatIsNotOneOf(Register reg1, 340 Register reg2 = NoReg, 341 Register reg3 = NoReg, 342 Register reg4 = NoReg); 343 344 345 // AreAliased returns true if any of the named registers overlap. Arguments set 346 // to NoReg are ignored. The system stack pointer may be specified. 347 bool AreAliased(const CPURegister& reg1, 348 const CPURegister& reg2, 349 const CPURegister& reg3 = NoReg, 350 const CPURegister& reg4 = NoReg, 351 const CPURegister& reg5 = NoReg, 352 const CPURegister& reg6 = NoReg, 353 const CPURegister& reg7 = NoReg, 354 const CPURegister& reg8 = NoReg); 355 356 // AreSameSizeAndType returns true if all of the specified registers have the 357 // same size, and are of the same type. The system stack pointer may be 358 // specified. Arguments set to NoReg are ignored, as are any subsequent 359 // arguments. At least one argument (reg1) must be valid (not NoCPUReg). 360 bool AreSameSizeAndType(const CPURegister& reg1, 361 const CPURegister& reg2, 362 const CPURegister& reg3 = NoCPUReg, 363 const CPURegister& reg4 = NoCPUReg, 364 const CPURegister& reg5 = NoCPUReg, 365 const CPURegister& reg6 = NoCPUReg, 366 const CPURegister& reg7 = NoCPUReg, 367 const CPURegister& reg8 = NoCPUReg); 368 369 370 typedef FPRegister DoubleRegister; 371 372 373 // ----------------------------------------------------------------------------- 374 // Lists of registers. 375 class CPURegList { 376 public: 377 explicit CPURegList(CPURegister reg1, 378 CPURegister reg2 = NoCPUReg, 379 CPURegister reg3 = NoCPUReg, 380 CPURegister reg4 = NoCPUReg) 381 : list_(reg1.Bit() | reg2.Bit() | reg3.Bit() | reg4.Bit()), 382 size_(reg1.SizeInBits()), type_(reg1.type()) { 383 DCHECK(AreSameSizeAndType(reg1, reg2, reg3, reg4)); 384 DCHECK(IsValid()); 385 } 386 CPURegList(CPURegister::RegisterType type,int size,RegList list)387 CPURegList(CPURegister::RegisterType type, int size, RegList list) 388 : list_(list), size_(size), type_(type) { 389 DCHECK(IsValid()); 390 } 391 CPURegList(CPURegister::RegisterType type,int size,int first_reg,int last_reg)392 CPURegList(CPURegister::RegisterType type, int size, int first_reg, 393 int last_reg) 394 : size_(size), type_(type) { 395 DCHECK(((type == CPURegister::kRegister) && 396 (last_reg < kNumberOfRegisters)) || 397 ((type == CPURegister::kFPRegister) && 398 (last_reg < kNumberOfFPRegisters))); 399 DCHECK(last_reg >= first_reg); 400 list_ = (1UL << (last_reg + 1)) - 1; 401 list_ &= ~((1UL << first_reg) - 1); 402 DCHECK(IsValid()); 403 } 404 type()405 CPURegister::RegisterType type() const { 406 DCHECK(IsValid()); 407 return type_; 408 } 409 list()410 RegList list() const { 411 DCHECK(IsValid()); 412 return list_; 413 } 414 set_list(RegList new_list)415 inline void set_list(RegList new_list) { 416 DCHECK(IsValid()); 417 list_ = new_list; 418 } 419 420 // Combine another CPURegList into this one. Registers that already exist in 421 // this list are left unchanged. The type and size of the registers in the 422 // 'other' list must match those in this list. 423 void Combine(const CPURegList& other); 424 425 // Remove every register in the other CPURegList from this one. Registers that 426 // do not exist in this list are ignored. The type of the registers in the 427 // 'other' list must match those in this list. 428 void Remove(const CPURegList& other); 429 430 // Variants of Combine and Remove which take CPURegisters. 431 void Combine(const CPURegister& other); 432 void Remove(const CPURegister& other1, 433 const CPURegister& other2 = NoCPUReg, 434 const CPURegister& other3 = NoCPUReg, 435 const CPURegister& other4 = NoCPUReg); 436 437 // Variants of Combine and Remove which take a single register by its code; 438 // the type and size of the register is inferred from this list. 439 void Combine(int code); 440 void Remove(int code); 441 442 // Remove all callee-saved registers from the list. This can be useful when 443 // preparing registers for an AAPCS64 function call, for example. 444 void RemoveCalleeSaved(); 445 446 CPURegister PopLowestIndex(); 447 CPURegister PopHighestIndex(); 448 449 // AAPCS64 callee-saved registers. 450 static CPURegList GetCalleeSaved(int size = kXRegSizeInBits); 451 static CPURegList GetCalleeSavedFP(int size = kDRegSizeInBits); 452 453 // AAPCS64 caller-saved registers. Note that this includes lr. 454 static CPURegList GetCallerSaved(int size = kXRegSizeInBits); 455 static CPURegList GetCallerSavedFP(int size = kDRegSizeInBits); 456 457 // Registers saved as safepoints. 458 static CPURegList GetSafepointSavedRegisters(); 459 IsEmpty()460 bool IsEmpty() const { 461 DCHECK(IsValid()); 462 return list_ == 0; 463 } 464 465 bool IncludesAliasOf(const CPURegister& other1, 466 const CPURegister& other2 = NoCPUReg, 467 const CPURegister& other3 = NoCPUReg, 468 const CPURegister& other4 = NoCPUReg) const { 469 DCHECK(IsValid()); 470 RegList list = 0; 471 if (!other1.IsNone() && (other1.type() == type_)) list |= other1.Bit(); 472 if (!other2.IsNone() && (other2.type() == type_)) list |= other2.Bit(); 473 if (!other3.IsNone() && (other3.type() == type_)) list |= other3.Bit(); 474 if (!other4.IsNone() && (other4.type() == type_)) list |= other4.Bit(); 475 return (list_ & list) != 0; 476 } 477 Count()478 int Count() const { 479 DCHECK(IsValid()); 480 return CountSetBits(list_, kRegListSizeInBits); 481 } 482 RegisterSizeInBits()483 int RegisterSizeInBits() const { 484 DCHECK(IsValid()); 485 return size_; 486 } 487 RegisterSizeInBytes()488 int RegisterSizeInBytes() const { 489 int size_in_bits = RegisterSizeInBits(); 490 DCHECK((size_in_bits % kBitsPerByte) == 0); 491 return size_in_bits / kBitsPerByte; 492 } 493 TotalSizeInBytes()494 int TotalSizeInBytes() const { 495 DCHECK(IsValid()); 496 return RegisterSizeInBytes() * Count(); 497 } 498 499 private: 500 RegList list_; 501 int size_; 502 CPURegister::RegisterType type_; 503 IsValid()504 bool IsValid() const { 505 const RegList kValidRegisters = 0x8000000ffffffff; 506 const RegList kValidFPRegisters = 0x0000000ffffffff; 507 switch (type_) { 508 case CPURegister::kRegister: 509 return (list_ & kValidRegisters) == list_; 510 case CPURegister::kFPRegister: 511 return (list_ & kValidFPRegisters) == list_; 512 case CPURegister::kNoRegister: 513 return list_ == 0; 514 default: 515 UNREACHABLE(); 516 return false; 517 } 518 } 519 }; 520 521 522 // AAPCS64 callee-saved registers. 523 #define kCalleeSaved CPURegList::GetCalleeSaved() 524 #define kCalleeSavedFP CPURegList::GetCalleeSavedFP() 525 526 527 // AAPCS64 caller-saved registers. Note that this includes lr. 528 #define kCallerSaved CPURegList::GetCallerSaved() 529 #define kCallerSavedFP CPURegList::GetCallerSavedFP() 530 531 // ----------------------------------------------------------------------------- 532 // Immediates. 533 class Immediate { 534 public: 535 template<typename T> 536 inline explicit Immediate(Handle<T> handle); 537 538 // This is allowed to be an implicit constructor because Immediate is 539 // a wrapper class that doesn't normally perform any type conversion. 540 template<typename T> 541 inline Immediate(T value); // NOLINT(runtime/explicit) 542 543 template<typename T> 544 inline Immediate(T value, RelocInfo::Mode rmode); 545 value()546 int64_t value() const { return value_; } rmode()547 RelocInfo::Mode rmode() const { return rmode_; } 548 549 private: 550 void InitializeHandle(Handle<Object> value); 551 552 int64_t value_; 553 RelocInfo::Mode rmode_; 554 }; 555 556 557 // ----------------------------------------------------------------------------- 558 // Operands. 559 const int kSmiShift = kSmiTagSize + kSmiShiftSize; 560 const uint64_t kSmiShiftMask = (1UL << kSmiShift) - 1; 561 562 // Represents an operand in a machine instruction. 563 class Operand { 564 // TODO(all): If necessary, study more in details which methods 565 // TODO(all): should be inlined or not. 566 public: 567 // rm, {<shift> {#<shift_amount>}} 568 // where <shift> is one of {LSL, LSR, ASR, ROR}. 569 // <shift_amount> is uint6_t. 570 // This is allowed to be an implicit constructor because Operand is 571 // a wrapper class that doesn't normally perform any type conversion. 572 inline Operand(Register reg, 573 Shift shift = LSL, 574 unsigned shift_amount = 0); // NOLINT(runtime/explicit) 575 576 // rm, <extend> {#<shift_amount>} 577 // where <extend> is one of {UXTB, UXTH, UXTW, UXTX, SXTB, SXTH, SXTW, SXTX}. 578 // <shift_amount> is uint2_t. 579 inline Operand(Register reg, 580 Extend extend, 581 unsigned shift_amount = 0); 582 583 template<typename T> 584 inline explicit Operand(Handle<T> handle); 585 586 // Implicit constructor for all int types, ExternalReference, and Smi. 587 template<typename T> 588 inline Operand(T t); // NOLINT(runtime/explicit) 589 590 // Implicit constructor for int types. 591 template<typename T> 592 inline Operand(T t, RelocInfo::Mode rmode); 593 594 inline bool IsImmediate() const; 595 inline bool IsShiftedRegister() const; 596 inline bool IsExtendedRegister() const; 597 inline bool IsZero() const; 598 599 // This returns an LSL shift (<= 4) operand as an equivalent extend operand, 600 // which helps in the encoding of instructions that use the stack pointer. 601 inline Operand ToExtendedRegister() const; 602 603 inline Immediate immediate() const; 604 inline int64_t ImmediateValue() const; 605 inline Register reg() const; 606 inline Shift shift() const; 607 inline Extend extend() const; 608 inline unsigned shift_amount() const; 609 610 // Relocation information. 611 bool NeedsRelocation(const Assembler* assembler) const; 612 613 // Helpers 614 inline static Operand UntagSmi(Register smi); 615 inline static Operand UntagSmiAndScale(Register smi, int scale); 616 617 private: 618 Immediate immediate_; 619 Register reg_; 620 Shift shift_; 621 Extend extend_; 622 unsigned shift_amount_; 623 }; 624 625 626 // MemOperand represents a memory operand in a load or store instruction. 627 class MemOperand { 628 public: 629 inline MemOperand(); 630 inline explicit MemOperand(Register base, 631 int64_t offset = 0, 632 AddrMode addrmode = Offset); 633 inline explicit MemOperand(Register base, 634 Register regoffset, 635 Shift shift = LSL, 636 unsigned shift_amount = 0); 637 inline explicit MemOperand(Register base, 638 Register regoffset, 639 Extend extend, 640 unsigned shift_amount = 0); 641 inline explicit MemOperand(Register base, 642 const Operand& offset, 643 AddrMode addrmode = Offset); 644 base()645 const Register& base() const { return base_; } regoffset()646 const Register& regoffset() const { return regoffset_; } offset()647 int64_t offset() const { return offset_; } addrmode()648 AddrMode addrmode() const { return addrmode_; } shift()649 Shift shift() const { return shift_; } extend()650 Extend extend() const { return extend_; } shift_amount()651 unsigned shift_amount() const { return shift_amount_; } 652 inline bool IsImmediateOffset() const; 653 inline bool IsRegisterOffset() const; 654 inline bool IsPreIndex() const; 655 inline bool IsPostIndex() const; 656 657 // For offset modes, return the offset as an Operand. This helper cannot 658 // handle indexed modes. 659 inline Operand OffsetAsOperand() const; 660 661 enum PairResult { 662 kNotPair, // Can't use a pair instruction. 663 kPairAB, // Can use a pair instruction (operandA has lower address). 664 kPairBA // Can use a pair instruction (operandB has lower address). 665 }; 666 // Check if two MemOperand are consistent for stp/ldp use. 667 static PairResult AreConsistentForPair(const MemOperand& operandA, 668 const MemOperand& operandB, 669 int access_size_log2 = kXRegSizeLog2); 670 671 private: 672 Register base_; 673 Register regoffset_; 674 int64_t offset_; 675 AddrMode addrmode_; 676 Shift shift_; 677 Extend extend_; 678 unsigned shift_amount_; 679 }; 680 681 682 class ConstPool { 683 public: ConstPool(Assembler * assm)684 explicit ConstPool(Assembler* assm) 685 : assm_(assm), 686 first_use_(-1), 687 shared_entries_count(0) {} 688 void RecordEntry(intptr_t data, RelocInfo::Mode mode); EntryCount()689 int EntryCount() const { 690 return shared_entries_count + static_cast<int>(unique_entries_.size()); 691 } IsEmpty()692 bool IsEmpty() const { 693 return shared_entries_.empty() && unique_entries_.empty(); 694 } 695 // Distance in bytes between the current pc and the first instruction 696 // using the pool. If there are no pending entries return kMaxInt. 697 int DistanceToFirstUse(); 698 // Offset after which instructions using the pool will be out of range. 699 int MaxPcOffset(); 700 // Maximum size the constant pool can be with current entries. It always 701 // includes alignment padding and branch over. 702 int WorstCaseSize(); 703 // Size in bytes of the literal pool *if* it is emitted at the current 704 // pc. The size will include the branch over the pool if it was requested. 705 int SizeIfEmittedAtCurrentPc(bool require_jump); 706 // Emit the literal pool at the current pc with a branch over the pool if 707 // requested. 708 void Emit(bool require_jump); 709 // Discard any pending pool entries. 710 void Clear(); 711 712 private: 713 bool CanBeShared(RelocInfo::Mode mode); 714 void EmitMarker(); 715 void EmitGuard(); 716 void EmitEntries(); 717 718 Assembler* assm_; 719 // Keep track of the first instruction requiring a constant pool entry 720 // since the previous constant pool was emitted. 721 int first_use_; 722 // values, pc offset(s) of entries which can be shared. 723 std::multimap<uint64_t, int> shared_entries_; 724 // Number of distinct literal in shared entries. 725 int shared_entries_count; 726 // values, pc offset of entries which cannot be shared. 727 std::vector<std::pair<uint64_t, int> > unique_entries_; 728 }; 729 730 731 // ----------------------------------------------------------------------------- 732 // Assembler. 733 734 class Assembler : public AssemblerBase { 735 public: 736 // Create an assembler. Instructions and relocation information are emitted 737 // into a buffer, with the instructions starting from the beginning and the 738 // relocation information starting from the end of the buffer. See CodeDesc 739 // for a detailed comment on the layout (globals.h). 740 // 741 // If the provided buffer is NULL, the assembler allocates and grows its own 742 // buffer, and buffer_size determines the initial buffer size. The buffer is 743 // owned by the assembler and deallocated upon destruction of the assembler. 744 // 745 // If the provided buffer is not NULL, the assembler uses the provided buffer 746 // for code generation and assumes its size to be buffer_size. If the buffer 747 // is too small, a fatal error occurs. No deallocation of the buffer is done 748 // upon destruction of the assembler. 749 Assembler(Isolate* arg_isolate, void* buffer, int buffer_size); 750 751 virtual ~Assembler(); 752 AbortedCodeGeneration()753 virtual void AbortedCodeGeneration() { 754 constpool_.Clear(); 755 } 756 757 // System functions --------------------------------------------------------- 758 // Start generating code from the beginning of the buffer, discarding any code 759 // and data that has already been emitted into the buffer. 760 // 761 // In order to avoid any accidental transfer of state, Reset DCHECKs that the 762 // constant pool is not blocked. 763 void Reset(); 764 765 // GetCode emits any pending (non-emitted) code and fills the descriptor 766 // desc. GetCode() is idempotent; it returns the same result if no other 767 // Assembler functions are invoked in between GetCode() calls. 768 // 769 // The descriptor (desc) can be NULL. In that case, the code is finalized as 770 // usual, but the descriptor is not populated. 771 void GetCode(CodeDesc* desc); 772 773 // Insert the smallest number of nop instructions 774 // possible to align the pc offset to a multiple 775 // of m. m must be a power of 2 (>= 4). 776 void Align(int m); 777 // Insert the smallest number of zero bytes possible to align the pc offset 778 // to a mulitple of m. m must be a power of 2 (>= 2). 779 void DataAlign(int m); 780 781 inline void Unreachable(); 782 783 // Label -------------------------------------------------------------------- 784 // Bind a label to the current pc. Note that labels can only be bound once, 785 // and if labels are linked to other instructions, they _must_ be bound 786 // before they go out of scope. 787 void bind(Label* label); 788 789 790 // RelocInfo and pools ------------------------------------------------------ 791 792 // Record relocation information for current pc_. 793 void RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data = 0); 794 795 // Return the address in the constant pool of the code target address used by 796 // the branch/call instruction at pc. 797 inline static Address target_pointer_address_at(Address pc); 798 799 // Read/Modify the code target address in the branch/call instruction at pc. 800 inline static Address target_address_at(Address pc, Address constant_pool); 801 inline static void set_target_address_at( 802 Isolate* isolate, Address pc, Address constant_pool, Address target, 803 ICacheFlushMode icache_flush_mode = FLUSH_ICACHE_IF_NEEDED); 804 static inline Address target_address_at(Address pc, Code* code); 805 static inline void set_target_address_at( 806 Isolate* isolate, Address pc, Code* code, Address target, 807 ICacheFlushMode icache_flush_mode = FLUSH_ICACHE_IF_NEEDED); 808 809 // Return the code target address at a call site from the return address of 810 // that call in the instruction stream. 811 inline static Address target_address_from_return_address(Address pc); 812 813 // Given the address of the beginning of a call, return the address in the 814 // instruction stream that call will return from. 815 inline static Address return_address_from_call_start(Address pc); 816 817 // This sets the branch destination (which is in the constant pool on ARM). 818 // This is for calls and branches within generated code. 819 inline static void deserialization_set_special_target_at( 820 Isolate* isolate, Address constant_pool_entry, Code* code, 821 Address target); 822 823 // This sets the internal reference at the pc. 824 inline static void deserialization_set_target_internal_reference_at( 825 Isolate* isolate, Address pc, Address target, 826 RelocInfo::Mode mode = RelocInfo::INTERNAL_REFERENCE); 827 828 // All addresses in the constant pool are the same size as pointers. 829 static const int kSpecialTargetSize = kPointerSize; 830 831 // The sizes of the call sequences emitted by MacroAssembler::Call. 832 // Wherever possible, use MacroAssembler::CallSize instead of these constants, 833 // as it will choose the correct value for a given relocation mode. 834 // 835 // Without relocation: 836 // movz temp, #(target & 0x000000000000ffff) 837 // movk temp, #(target & 0x00000000ffff0000) 838 // movk temp, #(target & 0x0000ffff00000000) 839 // blr temp 840 // 841 // With relocation: 842 // ldr temp, =target 843 // blr temp 844 static const int kCallSizeWithoutRelocation = 4 * kInstructionSize; 845 static const int kCallSizeWithRelocation = 2 * kInstructionSize; 846 847 // Size of the generated code in bytes SizeOfGeneratedCode()848 uint64_t SizeOfGeneratedCode() const { 849 DCHECK((pc_ >= buffer_) && (pc_ < (buffer_ + buffer_size_))); 850 return pc_ - buffer_; 851 } 852 853 // Return the code size generated from label to the current position. SizeOfCodeGeneratedSince(const Label * label)854 uint64_t SizeOfCodeGeneratedSince(const Label* label) { 855 DCHECK(label->is_bound()); 856 DCHECK(pc_offset() >= label->pos()); 857 DCHECK(pc_offset() < buffer_size_); 858 return pc_offset() - label->pos(); 859 } 860 861 // Check the size of the code generated since the given label. This function 862 // is used primarily to work around comparisons between signed and unsigned 863 // quantities, since V8 uses both. 864 // TODO(jbramley): Work out what sign to use for these things and if possible, 865 // change things to be consistent. AssertSizeOfCodeGeneratedSince(const Label * label,ptrdiff_t size)866 void AssertSizeOfCodeGeneratedSince(const Label* label, ptrdiff_t size) { 867 DCHECK(size >= 0); 868 DCHECK(static_cast<uint64_t>(size) == SizeOfCodeGeneratedSince(label)); 869 } 870 871 // Return the number of instructions generated from label to the 872 // current position. InstructionsGeneratedSince(const Label * label)873 uint64_t InstructionsGeneratedSince(const Label* label) { 874 return SizeOfCodeGeneratedSince(label) / kInstructionSize; 875 } 876 877 static const int kPatchDebugBreakSlotAddressOffset = 0; 878 879 // Number of instructions necessary to be able to later patch it to a call. 880 static const int kDebugBreakSlotInstructions = 5; 881 static const int kDebugBreakSlotLength = 882 kDebugBreakSlotInstructions * kInstructionSize; 883 884 // Prevent contant pool emission until EndBlockConstPool is called. 885 // Call to this function can be nested but must be followed by an equal 886 // number of call to EndBlockConstpool. 887 void StartBlockConstPool(); 888 889 // Resume constant pool emission. Need to be called as many time as 890 // StartBlockConstPool to have an effect. 891 void EndBlockConstPool(); 892 893 bool is_const_pool_blocked() const; 894 static bool IsConstantPoolAt(Instruction* instr); 895 static int ConstantPoolSizeAt(Instruction* instr); 896 // See Assembler::CheckConstPool for more info. 897 void EmitPoolGuard(); 898 899 // Prevent veneer pool emission until EndBlockVeneerPool is called. 900 // Call to this function can be nested but must be followed by an equal 901 // number of call to EndBlockConstpool. 902 void StartBlockVeneerPool(); 903 904 // Resume constant pool emission. Need to be called as many time as 905 // StartBlockVeneerPool to have an effect. 906 void EndBlockVeneerPool(); 907 is_veneer_pool_blocked()908 bool is_veneer_pool_blocked() const { 909 return veneer_pool_blocked_nesting_ > 0; 910 } 911 912 // Block/resume emission of constant pools and veneer pools. StartBlockPools()913 void StartBlockPools() { 914 StartBlockConstPool(); 915 StartBlockVeneerPool(); 916 } EndBlockPools()917 void EndBlockPools() { 918 EndBlockConstPool(); 919 EndBlockVeneerPool(); 920 } 921 922 // Debugging ---------------------------------------------------------------- positions_recorder()923 PositionsRecorder* positions_recorder() { return &positions_recorder_; } 924 void RecordComment(const char* msg); 925 926 // Record a deoptimization reason that can be used by a log or cpu profiler. 927 // Use --trace-deopt to enable. 928 void RecordDeoptReason(const int reason, const SourcePosition position); 929 930 int buffer_space() const; 931 932 // Mark generator continuation. 933 void RecordGeneratorContinuation(); 934 935 // Mark address of a debug break slot. 936 void RecordDebugBreakSlot(RelocInfo::Mode mode); 937 938 // Record the emission of a constant pool. 939 // 940 // The emission of constant and veneer pools depends on the size of the code 941 // generated and the number of RelocInfo recorded. 942 // The Debug mechanism needs to map code offsets between two versions of a 943 // function, compiled with and without debugger support (see for example 944 // Debug::PrepareForBreakPoints()). 945 // Compiling functions with debugger support generates additional code 946 // (DebugCodegen::GenerateSlot()). This may affect the emission of the pools 947 // and cause the version of the code with debugger support to have pools 948 // generated in different places. 949 // Recording the position and size of emitted pools allows to correctly 950 // compute the offset mappings between the different versions of a function in 951 // all situations. 952 // 953 // The parameter indicates the size of the pool (in bytes), including 954 // the marker and branch over the data. 955 void RecordConstPool(int size); 956 957 958 // Instruction set functions ------------------------------------------------ 959 960 // Branch / Jump instructions. 961 // For branches offsets are scaled, i.e. they in instrcutions not in bytes. 962 // Branch to register. 963 void br(const Register& xn); 964 965 // Branch-link to register. 966 void blr(const Register& xn); 967 968 // Branch to register with return hint. 969 void ret(const Register& xn = lr); 970 971 // Unconditional branch to label. 972 void b(Label* label); 973 974 // Conditional branch to label. 975 void b(Label* label, Condition cond); 976 977 // Unconditional branch to PC offset. 978 void b(int imm26); 979 980 // Conditional branch to PC offset. 981 void b(int imm19, Condition cond); 982 983 // Branch-link to label / pc offset. 984 void bl(Label* label); 985 void bl(int imm26); 986 987 // Compare and branch to label / pc offset if zero. 988 void cbz(const Register& rt, Label* label); 989 void cbz(const Register& rt, int imm19); 990 991 // Compare and branch to label / pc offset if not zero. 992 void cbnz(const Register& rt, Label* label); 993 void cbnz(const Register& rt, int imm19); 994 995 // Test bit and branch to label / pc offset if zero. 996 void tbz(const Register& rt, unsigned bit_pos, Label* label); 997 void tbz(const Register& rt, unsigned bit_pos, int imm14); 998 999 // Test bit and branch to label / pc offset if not zero. 1000 void tbnz(const Register& rt, unsigned bit_pos, Label* label); 1001 void tbnz(const Register& rt, unsigned bit_pos, int imm14); 1002 1003 // Address calculation instructions. 1004 // Calculate a PC-relative address. Unlike for branches the offset in adr is 1005 // unscaled (i.e. the result can be unaligned). 1006 void adr(const Register& rd, Label* label); 1007 void adr(const Register& rd, int imm21); 1008 1009 // Data Processing instructions. 1010 // Add. 1011 void add(const Register& rd, 1012 const Register& rn, 1013 const Operand& operand); 1014 1015 // Add and update status flags. 1016 void adds(const Register& rd, 1017 const Register& rn, 1018 const Operand& operand); 1019 1020 // Compare negative. 1021 void cmn(const Register& rn, const Operand& operand); 1022 1023 // Subtract. 1024 void sub(const Register& rd, 1025 const Register& rn, 1026 const Operand& operand); 1027 1028 // Subtract and update status flags. 1029 void subs(const Register& rd, 1030 const Register& rn, 1031 const Operand& operand); 1032 1033 // Compare. 1034 void cmp(const Register& rn, const Operand& operand); 1035 1036 // Negate. 1037 void neg(const Register& rd, 1038 const Operand& operand); 1039 1040 // Negate and update status flags. 1041 void negs(const Register& rd, 1042 const Operand& operand); 1043 1044 // Add with carry bit. 1045 void adc(const Register& rd, 1046 const Register& rn, 1047 const Operand& operand); 1048 1049 // Add with carry bit and update status flags. 1050 void adcs(const Register& rd, 1051 const Register& rn, 1052 const Operand& operand); 1053 1054 // Subtract with carry bit. 1055 void sbc(const Register& rd, 1056 const Register& rn, 1057 const Operand& operand); 1058 1059 // Subtract with carry bit and update status flags. 1060 void sbcs(const Register& rd, 1061 const Register& rn, 1062 const Operand& operand); 1063 1064 // Negate with carry bit. 1065 void ngc(const Register& rd, 1066 const Operand& operand); 1067 1068 // Negate with carry bit and update status flags. 1069 void ngcs(const Register& rd, 1070 const Operand& operand); 1071 1072 // Logical instructions. 1073 // Bitwise and (A & B). 1074 void and_(const Register& rd, 1075 const Register& rn, 1076 const Operand& operand); 1077 1078 // Bitwise and (A & B) and update status flags. 1079 void ands(const Register& rd, 1080 const Register& rn, 1081 const Operand& operand); 1082 1083 // Bit test, and set flags. 1084 void tst(const Register& rn, const Operand& operand); 1085 1086 // Bit clear (A & ~B). 1087 void bic(const Register& rd, 1088 const Register& rn, 1089 const Operand& operand); 1090 1091 // Bit clear (A & ~B) and update status flags. 1092 void bics(const Register& rd, 1093 const Register& rn, 1094 const Operand& operand); 1095 1096 // Bitwise or (A | B). 1097 void orr(const Register& rd, const Register& rn, const Operand& operand); 1098 1099 // Bitwise nor (A | ~B). 1100 void orn(const Register& rd, const Register& rn, const Operand& operand); 1101 1102 // Bitwise eor/xor (A ^ B). 1103 void eor(const Register& rd, const Register& rn, const Operand& operand); 1104 1105 // Bitwise enor/xnor (A ^ ~B). 1106 void eon(const Register& rd, const Register& rn, const Operand& operand); 1107 1108 // Logical shift left variable. 1109 void lslv(const Register& rd, const Register& rn, const Register& rm); 1110 1111 // Logical shift right variable. 1112 void lsrv(const Register& rd, const Register& rn, const Register& rm); 1113 1114 // Arithmetic shift right variable. 1115 void asrv(const Register& rd, const Register& rn, const Register& rm); 1116 1117 // Rotate right variable. 1118 void rorv(const Register& rd, const Register& rn, const Register& rm); 1119 1120 // Bitfield instructions. 1121 // Bitfield move. 1122 void bfm(const Register& rd, const Register& rn, int immr, int imms); 1123 1124 // Signed bitfield move. 1125 void sbfm(const Register& rd, const Register& rn, int immr, int imms); 1126 1127 // Unsigned bitfield move. 1128 void ubfm(const Register& rd, const Register& rn, int immr, int imms); 1129 1130 // Bfm aliases. 1131 // Bitfield insert. bfi(const Register & rd,const Register & rn,int lsb,int width)1132 void bfi(const Register& rd, const Register& rn, int lsb, int width) { 1133 DCHECK(width >= 1); 1134 DCHECK(lsb + width <= rn.SizeInBits()); 1135 bfm(rd, rn, (rd.SizeInBits() - lsb) & (rd.SizeInBits() - 1), width - 1); 1136 } 1137 1138 // Bitfield extract and insert low. bfxil(const Register & rd,const Register & rn,int lsb,int width)1139 void bfxil(const Register& rd, const Register& rn, int lsb, int width) { 1140 DCHECK(width >= 1); 1141 DCHECK(lsb + width <= rn.SizeInBits()); 1142 bfm(rd, rn, lsb, lsb + width - 1); 1143 } 1144 1145 // Sbfm aliases. 1146 // Arithmetic shift right. asr(const Register & rd,const Register & rn,int shift)1147 void asr(const Register& rd, const Register& rn, int shift) { 1148 DCHECK(shift < rd.SizeInBits()); 1149 sbfm(rd, rn, shift, rd.SizeInBits() - 1); 1150 } 1151 1152 // Signed bitfield insert in zero. sbfiz(const Register & rd,const Register & rn,int lsb,int width)1153 void sbfiz(const Register& rd, const Register& rn, int lsb, int width) { 1154 DCHECK(width >= 1); 1155 DCHECK(lsb + width <= rn.SizeInBits()); 1156 sbfm(rd, rn, (rd.SizeInBits() - lsb) & (rd.SizeInBits() - 1), width - 1); 1157 } 1158 1159 // Signed bitfield extract. sbfx(const Register & rd,const Register & rn,int lsb,int width)1160 void sbfx(const Register& rd, const Register& rn, int lsb, int width) { 1161 DCHECK(width >= 1); 1162 DCHECK(lsb + width <= rn.SizeInBits()); 1163 sbfm(rd, rn, lsb, lsb + width - 1); 1164 } 1165 1166 // Signed extend byte. sxtb(const Register & rd,const Register & rn)1167 void sxtb(const Register& rd, const Register& rn) { 1168 sbfm(rd, rn, 0, 7); 1169 } 1170 1171 // Signed extend halfword. sxth(const Register & rd,const Register & rn)1172 void sxth(const Register& rd, const Register& rn) { 1173 sbfm(rd, rn, 0, 15); 1174 } 1175 1176 // Signed extend word. sxtw(const Register & rd,const Register & rn)1177 void sxtw(const Register& rd, const Register& rn) { 1178 sbfm(rd, rn, 0, 31); 1179 } 1180 1181 // Ubfm aliases. 1182 // Logical shift left. lsl(const Register & rd,const Register & rn,int shift)1183 void lsl(const Register& rd, const Register& rn, int shift) { 1184 int reg_size = rd.SizeInBits(); 1185 DCHECK(shift < reg_size); 1186 ubfm(rd, rn, (reg_size - shift) % reg_size, reg_size - shift - 1); 1187 } 1188 1189 // Logical shift right. lsr(const Register & rd,const Register & rn,int shift)1190 void lsr(const Register& rd, const Register& rn, int shift) { 1191 DCHECK(shift < rd.SizeInBits()); 1192 ubfm(rd, rn, shift, rd.SizeInBits() - 1); 1193 } 1194 1195 // Unsigned bitfield insert in zero. ubfiz(const Register & rd,const Register & rn,int lsb,int width)1196 void ubfiz(const Register& rd, const Register& rn, int lsb, int width) { 1197 DCHECK(width >= 1); 1198 DCHECK(lsb + width <= rn.SizeInBits()); 1199 ubfm(rd, rn, (rd.SizeInBits() - lsb) & (rd.SizeInBits() - 1), width - 1); 1200 } 1201 1202 // Unsigned bitfield extract. ubfx(const Register & rd,const Register & rn,int lsb,int width)1203 void ubfx(const Register& rd, const Register& rn, int lsb, int width) { 1204 DCHECK(width >= 1); 1205 DCHECK(lsb + width <= rn.SizeInBits()); 1206 ubfm(rd, rn, lsb, lsb + width - 1); 1207 } 1208 1209 // Unsigned extend byte. uxtb(const Register & rd,const Register & rn)1210 void uxtb(const Register& rd, const Register& rn) { 1211 ubfm(rd, rn, 0, 7); 1212 } 1213 1214 // Unsigned extend halfword. uxth(const Register & rd,const Register & rn)1215 void uxth(const Register& rd, const Register& rn) { 1216 ubfm(rd, rn, 0, 15); 1217 } 1218 1219 // Unsigned extend word. uxtw(const Register & rd,const Register & rn)1220 void uxtw(const Register& rd, const Register& rn) { 1221 ubfm(rd, rn, 0, 31); 1222 } 1223 1224 // Extract. 1225 void extr(const Register& rd, const Register& rn, const Register& rm, 1226 int lsb); 1227 1228 // Conditional select: rd = cond ? rn : rm. 1229 void csel(const Register& rd, 1230 const Register& rn, 1231 const Register& rm, 1232 Condition cond); 1233 1234 // Conditional select increment: rd = cond ? rn : rm + 1. 1235 void csinc(const Register& rd, 1236 const Register& rn, 1237 const Register& rm, 1238 Condition cond); 1239 1240 // Conditional select inversion: rd = cond ? rn : ~rm. 1241 void csinv(const Register& rd, 1242 const Register& rn, 1243 const Register& rm, 1244 Condition cond); 1245 1246 // Conditional select negation: rd = cond ? rn : -rm. 1247 void csneg(const Register& rd, 1248 const Register& rn, 1249 const Register& rm, 1250 Condition cond); 1251 1252 // Conditional set: rd = cond ? 1 : 0. 1253 void cset(const Register& rd, Condition cond); 1254 1255 // Conditional set minus: rd = cond ? -1 : 0. 1256 void csetm(const Register& rd, Condition cond); 1257 1258 // Conditional increment: rd = cond ? rn + 1 : rn. 1259 void cinc(const Register& rd, const Register& rn, Condition cond); 1260 1261 // Conditional invert: rd = cond ? ~rn : rn. 1262 void cinv(const Register& rd, const Register& rn, Condition cond); 1263 1264 // Conditional negate: rd = cond ? -rn : rn. 1265 void cneg(const Register& rd, const Register& rn, Condition cond); 1266 1267 // Extr aliases. ror(const Register & rd,const Register & rs,unsigned shift)1268 void ror(const Register& rd, const Register& rs, unsigned shift) { 1269 extr(rd, rs, rs, shift); 1270 } 1271 1272 // Conditional comparison. 1273 // Conditional compare negative. 1274 void ccmn(const Register& rn, 1275 const Operand& operand, 1276 StatusFlags nzcv, 1277 Condition cond); 1278 1279 // Conditional compare. 1280 void ccmp(const Register& rn, 1281 const Operand& operand, 1282 StatusFlags nzcv, 1283 Condition cond); 1284 1285 // Multiplication. 1286 // 32 x 32 -> 32-bit and 64 x 64 -> 64-bit multiply. 1287 void mul(const Register& rd, const Register& rn, const Register& rm); 1288 1289 // 32 + 32 x 32 -> 32-bit and 64 + 64 x 64 -> 64-bit multiply accumulate. 1290 void madd(const Register& rd, 1291 const Register& rn, 1292 const Register& rm, 1293 const Register& ra); 1294 1295 // -(32 x 32) -> 32-bit and -(64 x 64) -> 64-bit multiply. 1296 void mneg(const Register& rd, const Register& rn, const Register& rm); 1297 1298 // 32 - 32 x 32 -> 32-bit and 64 - 64 x 64 -> 64-bit multiply subtract. 1299 void msub(const Register& rd, 1300 const Register& rn, 1301 const Register& rm, 1302 const Register& ra); 1303 1304 // 32 x 32 -> 64-bit multiply. 1305 void smull(const Register& rd, const Register& rn, const Register& rm); 1306 1307 // Xd = bits<127:64> of Xn * Xm. 1308 void smulh(const Register& rd, const Register& rn, const Register& rm); 1309 1310 // Signed 32 x 32 -> 64-bit multiply and accumulate. 1311 void smaddl(const Register& rd, 1312 const Register& rn, 1313 const Register& rm, 1314 const Register& ra); 1315 1316 // Unsigned 32 x 32 -> 64-bit multiply and accumulate. 1317 void umaddl(const Register& rd, 1318 const Register& rn, 1319 const Register& rm, 1320 const Register& ra); 1321 1322 // Signed 32 x 32 -> 64-bit multiply and subtract. 1323 void smsubl(const Register& rd, 1324 const Register& rn, 1325 const Register& rm, 1326 const Register& ra); 1327 1328 // Unsigned 32 x 32 -> 64-bit multiply and subtract. 1329 void umsubl(const Register& rd, 1330 const Register& rn, 1331 const Register& rm, 1332 const Register& ra); 1333 1334 // Signed integer divide. 1335 void sdiv(const Register& rd, const Register& rn, const Register& rm); 1336 1337 // Unsigned integer divide. 1338 void udiv(const Register& rd, const Register& rn, const Register& rm); 1339 1340 // Bit count, bit reverse and endian reverse. 1341 void rbit(const Register& rd, const Register& rn); 1342 void rev16(const Register& rd, const Register& rn); 1343 void rev32(const Register& rd, const Register& rn); 1344 void rev(const Register& rd, const Register& rn); 1345 void clz(const Register& rd, const Register& rn); 1346 void cls(const Register& rd, const Register& rn); 1347 1348 // Memory instructions. 1349 1350 // Load integer or FP register. 1351 void ldr(const CPURegister& rt, const MemOperand& src); 1352 1353 // Store integer or FP register. 1354 void str(const CPURegister& rt, const MemOperand& dst); 1355 1356 // Load word with sign extension. 1357 void ldrsw(const Register& rt, const MemOperand& src); 1358 1359 // Load byte. 1360 void ldrb(const Register& rt, const MemOperand& src); 1361 1362 // Store byte. 1363 void strb(const Register& rt, const MemOperand& dst); 1364 1365 // Load byte with sign extension. 1366 void ldrsb(const Register& rt, const MemOperand& src); 1367 1368 // Load half-word. 1369 void ldrh(const Register& rt, const MemOperand& src); 1370 1371 // Store half-word. 1372 void strh(const Register& rt, const MemOperand& dst); 1373 1374 // Load half-word with sign extension. 1375 void ldrsh(const Register& rt, const MemOperand& src); 1376 1377 // Load integer or FP register pair. 1378 void ldp(const CPURegister& rt, const CPURegister& rt2, 1379 const MemOperand& src); 1380 1381 // Store integer or FP register pair. 1382 void stp(const CPURegister& rt, const CPURegister& rt2, 1383 const MemOperand& dst); 1384 1385 // Load word pair with sign extension. 1386 void ldpsw(const Register& rt, const Register& rt2, const MemOperand& src); 1387 1388 // Load literal to register from a pc relative address. 1389 void ldr_pcrel(const CPURegister& rt, int imm19); 1390 1391 // Load literal to register. 1392 void ldr(const CPURegister& rt, const Immediate& imm); 1393 1394 // Move instructions. The default shift of -1 indicates that the move 1395 // instruction will calculate an appropriate 16-bit immediate and left shift 1396 // that is equal to the 64-bit immediate argument. If an explicit left shift 1397 // is specified (0, 16, 32 or 48), the immediate must be a 16-bit value. 1398 // 1399 // For movk, an explicit shift can be used to indicate which half word should 1400 // be overwritten, eg. movk(x0, 0, 0) will overwrite the least-significant 1401 // half word with zero, whereas movk(x0, 0, 48) will overwrite the 1402 // most-significant. 1403 1404 // Move and keep. 1405 void movk(const Register& rd, uint64_t imm, int shift = -1) { 1406 MoveWide(rd, imm, shift, MOVK); 1407 } 1408 1409 // Move with non-zero. 1410 void movn(const Register& rd, uint64_t imm, int shift = -1) { 1411 MoveWide(rd, imm, shift, MOVN); 1412 } 1413 1414 // Move with zero. 1415 void movz(const Register& rd, uint64_t imm, int shift = -1) { 1416 MoveWide(rd, imm, shift, MOVZ); 1417 } 1418 1419 // Misc instructions. 1420 // Monitor debug-mode breakpoint. 1421 void brk(int code); 1422 1423 // Halting debug-mode breakpoint. 1424 void hlt(int code); 1425 1426 // Move register to register. 1427 void mov(const Register& rd, const Register& rn); 1428 1429 // Move NOT(operand) to register. 1430 void mvn(const Register& rd, const Operand& operand); 1431 1432 // System instructions. 1433 // Move to register from system register. 1434 void mrs(const Register& rt, SystemRegister sysreg); 1435 1436 // Move from register to system register. 1437 void msr(SystemRegister sysreg, const Register& rt); 1438 1439 // System hint. 1440 void hint(SystemHint code); 1441 1442 // Data memory barrier 1443 void dmb(BarrierDomain domain, BarrierType type); 1444 1445 // Data synchronization barrier 1446 void dsb(BarrierDomain domain, BarrierType type); 1447 1448 // Instruction synchronization barrier 1449 void isb(); 1450 1451 // Alias for system instructions. nop()1452 void nop() { hint(NOP); } 1453 1454 // Different nop operations are used by the code generator to detect certain 1455 // states of the generated code. 1456 enum NopMarkerTypes { 1457 DEBUG_BREAK_NOP, 1458 INTERRUPT_CODE_NOP, 1459 ADR_FAR_NOP, 1460 FIRST_NOP_MARKER = DEBUG_BREAK_NOP, 1461 LAST_NOP_MARKER = ADR_FAR_NOP 1462 }; 1463 nop(NopMarkerTypes n)1464 void nop(NopMarkerTypes n) { 1465 DCHECK((FIRST_NOP_MARKER <= n) && (n <= LAST_NOP_MARKER)); 1466 mov(Register::XRegFromCode(n), Register::XRegFromCode(n)); 1467 } 1468 1469 // FP instructions. 1470 // Move immediate to FP register. 1471 void fmov(FPRegister fd, double imm); 1472 void fmov(FPRegister fd, float imm); 1473 1474 // Move FP register to register. 1475 void fmov(Register rd, FPRegister fn); 1476 1477 // Move register to FP register. 1478 void fmov(FPRegister fd, Register rn); 1479 1480 // Move FP register to FP register. 1481 void fmov(FPRegister fd, FPRegister fn); 1482 1483 // FP add. 1484 void fadd(const FPRegister& fd, const FPRegister& fn, const FPRegister& fm); 1485 1486 // FP subtract. 1487 void fsub(const FPRegister& fd, const FPRegister& fn, const FPRegister& fm); 1488 1489 // FP multiply. 1490 void fmul(const FPRegister& fd, const FPRegister& fn, const FPRegister& fm); 1491 1492 // FP fused multiply and add. 1493 void fmadd(const FPRegister& fd, 1494 const FPRegister& fn, 1495 const FPRegister& fm, 1496 const FPRegister& fa); 1497 1498 // FP fused multiply and subtract. 1499 void fmsub(const FPRegister& fd, 1500 const FPRegister& fn, 1501 const FPRegister& fm, 1502 const FPRegister& fa); 1503 1504 // FP fused multiply, add and negate. 1505 void fnmadd(const FPRegister& fd, 1506 const FPRegister& fn, 1507 const FPRegister& fm, 1508 const FPRegister& fa); 1509 1510 // FP fused multiply, subtract and negate. 1511 void fnmsub(const FPRegister& fd, 1512 const FPRegister& fn, 1513 const FPRegister& fm, 1514 const FPRegister& fa); 1515 1516 // FP divide. 1517 void fdiv(const FPRegister& fd, const FPRegister& fn, const FPRegister& fm); 1518 1519 // FP maximum. 1520 void fmax(const FPRegister& fd, const FPRegister& fn, const FPRegister& fm); 1521 1522 // FP minimum. 1523 void fmin(const FPRegister& fd, const FPRegister& fn, const FPRegister& fm); 1524 1525 // FP maximum. 1526 void fmaxnm(const FPRegister& fd, const FPRegister& fn, const FPRegister& fm); 1527 1528 // FP minimum. 1529 void fminnm(const FPRegister& fd, const FPRegister& fn, const FPRegister& fm); 1530 1531 // FP absolute. 1532 void fabs(const FPRegister& fd, const FPRegister& fn); 1533 1534 // FP negate. 1535 void fneg(const FPRegister& fd, const FPRegister& fn); 1536 1537 // FP square root. 1538 void fsqrt(const FPRegister& fd, const FPRegister& fn); 1539 1540 // FP round to integer (nearest with ties to away). 1541 void frinta(const FPRegister& fd, const FPRegister& fn); 1542 1543 // FP round to integer (toward minus infinity). 1544 void frintm(const FPRegister& fd, const FPRegister& fn); 1545 1546 // FP round to integer (nearest with ties to even). 1547 void frintn(const FPRegister& fd, const FPRegister& fn); 1548 1549 // FP round to integer (towards plus infinity). 1550 void frintp(const FPRegister& fd, const FPRegister& fn); 1551 1552 // FP round to integer (towards zero.) 1553 void frintz(const FPRegister& fd, const FPRegister& fn); 1554 1555 // FP compare registers. 1556 void fcmp(const FPRegister& fn, const FPRegister& fm); 1557 1558 // FP compare immediate. 1559 void fcmp(const FPRegister& fn, double value); 1560 1561 // FP conditional compare. 1562 void fccmp(const FPRegister& fn, 1563 const FPRegister& fm, 1564 StatusFlags nzcv, 1565 Condition cond); 1566 1567 // FP conditional select. 1568 void fcsel(const FPRegister& fd, 1569 const FPRegister& fn, 1570 const FPRegister& fm, 1571 Condition cond); 1572 1573 // Common FP Convert function 1574 void FPConvertToInt(const Register& rd, 1575 const FPRegister& fn, 1576 FPIntegerConvertOp op); 1577 1578 // FP convert between single and double precision. 1579 void fcvt(const FPRegister& fd, const FPRegister& fn); 1580 1581 // Convert FP to unsigned integer (nearest with ties to away). 1582 void fcvtau(const Register& rd, const FPRegister& fn); 1583 1584 // Convert FP to signed integer (nearest with ties to away). 1585 void fcvtas(const Register& rd, const FPRegister& fn); 1586 1587 // Convert FP to unsigned integer (round towards -infinity). 1588 void fcvtmu(const Register& rd, const FPRegister& fn); 1589 1590 // Convert FP to signed integer (round towards -infinity). 1591 void fcvtms(const Register& rd, const FPRegister& fn); 1592 1593 // Convert FP to unsigned integer (nearest with ties to even). 1594 void fcvtnu(const Register& rd, const FPRegister& fn); 1595 1596 // Convert FP to signed integer (nearest with ties to even). 1597 void fcvtns(const Register& rd, const FPRegister& fn); 1598 1599 // Convert FP to unsigned integer (round towards zero). 1600 void fcvtzu(const Register& rd, const FPRegister& fn); 1601 1602 // Convert FP to signed integer (rounf towards zero). 1603 void fcvtzs(const Register& rd, const FPRegister& fn); 1604 1605 // Convert signed integer or fixed point to FP. 1606 void scvtf(const FPRegister& fd, const Register& rn, unsigned fbits = 0); 1607 1608 // Convert unsigned integer or fixed point to FP. 1609 void ucvtf(const FPRegister& fd, const Register& rn, unsigned fbits = 0); 1610 1611 // Instruction functions used only for test, debug, and patching. 1612 // Emit raw instructions in the instruction stream. dci(Instr raw_inst)1613 void dci(Instr raw_inst) { Emit(raw_inst); } 1614 1615 // Emit 8 bits of data in the instruction stream. dc8(uint8_t data)1616 void dc8(uint8_t data) { EmitData(&data, sizeof(data)); } 1617 1618 // Emit 32 bits of data in the instruction stream. dc32(uint32_t data)1619 void dc32(uint32_t data) { EmitData(&data, sizeof(data)); } 1620 1621 // Emit 64 bits of data in the instruction stream. dc64(uint64_t data)1622 void dc64(uint64_t data) { EmitData(&data, sizeof(data)); } 1623 1624 // Emit an address in the instruction stream. 1625 void dcptr(Label* label); 1626 1627 // Copy a string into the instruction stream, including the terminating NULL 1628 // character. The instruction pointer (pc_) is then aligned correctly for 1629 // subsequent instructions. 1630 void EmitStringData(const char* string); 1631 1632 // Pseudo-instructions ------------------------------------------------------ 1633 1634 // Parameters are described in arm64/instructions-arm64.h. 1635 void debug(const char* message, uint32_t code, Instr params = BREAK); 1636 1637 // Required by V8. dd(uint32_t data)1638 void dd(uint32_t data) { dc32(data); } db(uint8_t data)1639 void db(uint8_t data) { dc8(data); } dq(uint64_t data)1640 void dq(uint64_t data) { dc64(data); } dp(uintptr_t data)1641 void dp(uintptr_t data) { dc64(data); } 1642 1643 // Code generation helpers -------------------------------------------------- 1644 IsConstPoolEmpty()1645 bool IsConstPoolEmpty() const { return constpool_.IsEmpty(); } 1646 pc()1647 Instruction* pc() const { return Instruction::Cast(pc_); } 1648 InstructionAt(ptrdiff_t offset)1649 Instruction* InstructionAt(ptrdiff_t offset) const { 1650 return reinterpret_cast<Instruction*>(buffer_ + offset); 1651 } 1652 InstructionOffset(Instruction * instr)1653 ptrdiff_t InstructionOffset(Instruction* instr) const { 1654 return reinterpret_cast<byte*>(instr) - buffer_; 1655 } 1656 1657 // Register encoding. Rd(CPURegister rd)1658 static Instr Rd(CPURegister rd) { 1659 DCHECK(rd.code() != kSPRegInternalCode); 1660 return rd.code() << Rd_offset; 1661 } 1662 Rn(CPURegister rn)1663 static Instr Rn(CPURegister rn) { 1664 DCHECK(rn.code() != kSPRegInternalCode); 1665 return rn.code() << Rn_offset; 1666 } 1667 Rm(CPURegister rm)1668 static Instr Rm(CPURegister rm) { 1669 DCHECK(rm.code() != kSPRegInternalCode); 1670 return rm.code() << Rm_offset; 1671 } 1672 Ra(CPURegister ra)1673 static Instr Ra(CPURegister ra) { 1674 DCHECK(ra.code() != kSPRegInternalCode); 1675 return ra.code() << Ra_offset; 1676 } 1677 Rt(CPURegister rt)1678 static Instr Rt(CPURegister rt) { 1679 DCHECK(rt.code() != kSPRegInternalCode); 1680 return rt.code() << Rt_offset; 1681 } 1682 Rt2(CPURegister rt2)1683 static Instr Rt2(CPURegister rt2) { 1684 DCHECK(rt2.code() != kSPRegInternalCode); 1685 return rt2.code() << Rt2_offset; 1686 } 1687 1688 // These encoding functions allow the stack pointer to be encoded, and 1689 // disallow the zero register. RdSP(Register rd)1690 static Instr RdSP(Register rd) { 1691 DCHECK(!rd.IsZero()); 1692 return (rd.code() & kRegCodeMask) << Rd_offset; 1693 } 1694 RnSP(Register rn)1695 static Instr RnSP(Register rn) { 1696 DCHECK(!rn.IsZero()); 1697 return (rn.code() & kRegCodeMask) << Rn_offset; 1698 } 1699 1700 // Flags encoding. 1701 inline static Instr Flags(FlagsUpdate S); 1702 inline static Instr Cond(Condition cond); 1703 1704 // PC-relative address encoding. 1705 inline static Instr ImmPCRelAddress(int imm21); 1706 1707 // Branch encoding. 1708 inline static Instr ImmUncondBranch(int imm26); 1709 inline static Instr ImmCondBranch(int imm19); 1710 inline static Instr ImmCmpBranch(int imm19); 1711 inline static Instr ImmTestBranch(int imm14); 1712 inline static Instr ImmTestBranchBit(unsigned bit_pos); 1713 1714 // Data Processing encoding. 1715 inline static Instr SF(Register rd); 1716 inline static Instr ImmAddSub(int imm); 1717 inline static Instr ImmS(unsigned imms, unsigned reg_size); 1718 inline static Instr ImmR(unsigned immr, unsigned reg_size); 1719 inline static Instr ImmSetBits(unsigned imms, unsigned reg_size); 1720 inline static Instr ImmRotate(unsigned immr, unsigned reg_size); 1721 inline static Instr ImmLLiteral(int imm19); 1722 inline static Instr BitN(unsigned bitn, unsigned reg_size); 1723 inline static Instr ShiftDP(Shift shift); 1724 inline static Instr ImmDPShift(unsigned amount); 1725 inline static Instr ExtendMode(Extend extend); 1726 inline static Instr ImmExtendShift(unsigned left_shift); 1727 inline static Instr ImmCondCmp(unsigned imm); 1728 inline static Instr Nzcv(StatusFlags nzcv); 1729 1730 static bool IsImmAddSub(int64_t immediate); 1731 static bool IsImmLogical(uint64_t value, 1732 unsigned width, 1733 unsigned* n, 1734 unsigned* imm_s, 1735 unsigned* imm_r); 1736 1737 // MemOperand offset encoding. 1738 inline static Instr ImmLSUnsigned(int imm12); 1739 inline static Instr ImmLS(int imm9); 1740 inline static Instr ImmLSPair(int imm7, LSDataSize size); 1741 inline static Instr ImmShiftLS(unsigned shift_amount); 1742 inline static Instr ImmException(int imm16); 1743 inline static Instr ImmSystemRegister(int imm15); 1744 inline static Instr ImmHint(int imm7); 1745 inline static Instr ImmBarrierDomain(int imm2); 1746 inline static Instr ImmBarrierType(int imm2); 1747 inline static LSDataSize CalcLSDataSize(LoadStoreOp op); 1748 1749 static bool IsImmLSUnscaled(int64_t offset); 1750 static bool IsImmLSScaled(int64_t offset, LSDataSize size); 1751 static bool IsImmLLiteral(int64_t offset); 1752 1753 // Move immediates encoding. 1754 inline static Instr ImmMoveWide(int imm); 1755 inline static Instr ShiftMoveWide(int shift); 1756 1757 // FP Immediates. 1758 static Instr ImmFP32(float imm); 1759 static Instr ImmFP64(double imm); 1760 inline static Instr FPScale(unsigned scale); 1761 1762 // FP register type. 1763 inline static Instr FPType(FPRegister fd); 1764 1765 // Class for scoping postponing the constant pool generation. 1766 class BlockConstPoolScope { 1767 public: BlockConstPoolScope(Assembler * assem)1768 explicit BlockConstPoolScope(Assembler* assem) : assem_(assem) { 1769 assem_->StartBlockConstPool(); 1770 } ~BlockConstPoolScope()1771 ~BlockConstPoolScope() { 1772 assem_->EndBlockConstPool(); 1773 } 1774 1775 private: 1776 Assembler* assem_; 1777 1778 DISALLOW_IMPLICIT_CONSTRUCTORS(BlockConstPoolScope); 1779 }; 1780 1781 // Check if is time to emit a constant pool. 1782 void CheckConstPool(bool force_emit, bool require_jump); 1783 PatchConstantPoolAccessInstruction(int pc_offset,int offset,ConstantPoolEntry::Access access,ConstantPoolEntry::Type type)1784 void PatchConstantPoolAccessInstruction(int pc_offset, int offset, 1785 ConstantPoolEntry::Access access, 1786 ConstantPoolEntry::Type type) { 1787 // No embedded constant pool support. 1788 UNREACHABLE(); 1789 } 1790 1791 // Returns true if we should emit a veneer as soon as possible for a branch 1792 // which can at most reach to specified pc. 1793 bool ShouldEmitVeneer(int max_reachable_pc, 1794 int margin = kVeneerDistanceMargin); 1795 bool ShouldEmitVeneers(int margin = kVeneerDistanceMargin) { 1796 return ShouldEmitVeneer(unresolved_branches_first_limit(), margin); 1797 } 1798 1799 // The maximum code size generated for a veneer. Currently one branch 1800 // instruction. This is for code size checking purposes, and can be extended 1801 // in the future for example if we decide to add nops between the veneers. 1802 static const int kMaxVeneerCodeSize = 1 * kInstructionSize; 1803 1804 void RecordVeneerPool(int location_offset, int size); 1805 // Emits veneers for branches that are approaching their maximum range. 1806 // If need_protection is true, the veneers are protected by a branch jumping 1807 // over the code. 1808 void EmitVeneers(bool force_emit, bool need_protection, 1809 int margin = kVeneerDistanceMargin); EmitVeneersGuard()1810 void EmitVeneersGuard() { EmitPoolGuard(); } 1811 // Checks whether veneers need to be emitted at this point. 1812 // If force_emit is set, a veneer is generated for *all* unresolved branches. 1813 void CheckVeneerPool(bool force_emit, bool require_jump, 1814 int margin = kVeneerDistanceMargin); 1815 1816 class BlockPoolsScope { 1817 public: BlockPoolsScope(Assembler * assem)1818 explicit BlockPoolsScope(Assembler* assem) : assem_(assem) { 1819 assem_->StartBlockPools(); 1820 } ~BlockPoolsScope()1821 ~BlockPoolsScope() { 1822 assem_->EndBlockPools(); 1823 } 1824 1825 private: 1826 Assembler* assem_; 1827 1828 DISALLOW_IMPLICIT_CONSTRUCTORS(BlockPoolsScope); 1829 }; 1830 1831 protected: 1832 inline const Register& AppropriateZeroRegFor(const CPURegister& reg) const; 1833 1834 void LoadStore(const CPURegister& rt, 1835 const MemOperand& addr, 1836 LoadStoreOp op); 1837 1838 void LoadStorePair(const CPURegister& rt, const CPURegister& rt2, 1839 const MemOperand& addr, LoadStorePairOp op); 1840 static bool IsImmLSPair(int64_t offset, LSDataSize size); 1841 1842 void Logical(const Register& rd, 1843 const Register& rn, 1844 const Operand& operand, 1845 LogicalOp op); 1846 void LogicalImmediate(const Register& rd, 1847 const Register& rn, 1848 unsigned n, 1849 unsigned imm_s, 1850 unsigned imm_r, 1851 LogicalOp op); 1852 1853 void ConditionalCompare(const Register& rn, 1854 const Operand& operand, 1855 StatusFlags nzcv, 1856 Condition cond, 1857 ConditionalCompareOp op); 1858 static bool IsImmConditionalCompare(int64_t immediate); 1859 1860 void AddSubWithCarry(const Register& rd, 1861 const Register& rn, 1862 const Operand& operand, 1863 FlagsUpdate S, 1864 AddSubWithCarryOp op); 1865 1866 // Functions for emulating operands not directly supported by the instruction 1867 // set. 1868 void EmitShift(const Register& rd, 1869 const Register& rn, 1870 Shift shift, 1871 unsigned amount); 1872 void EmitExtendShift(const Register& rd, 1873 const Register& rn, 1874 Extend extend, 1875 unsigned left_shift); 1876 1877 void AddSub(const Register& rd, 1878 const Register& rn, 1879 const Operand& operand, 1880 FlagsUpdate S, 1881 AddSubOp op); 1882 1883 static bool IsImmFP32(float imm); 1884 static bool IsImmFP64(double imm); 1885 1886 // Find an appropriate LoadStoreOp or LoadStorePairOp for the specified 1887 // registers. Only simple loads are supported; sign- and zero-extension (such 1888 // as in LDPSW_x or LDRB_w) are not supported. 1889 static inline LoadStoreOp LoadOpFor(const CPURegister& rt); 1890 static inline LoadStorePairOp LoadPairOpFor(const CPURegister& rt, 1891 const CPURegister& rt2); 1892 static inline LoadStoreOp StoreOpFor(const CPURegister& rt); 1893 static inline LoadStorePairOp StorePairOpFor(const CPURegister& rt, 1894 const CPURegister& rt2); 1895 static inline LoadLiteralOp LoadLiteralOpFor(const CPURegister& rt); 1896 1897 // Remove the specified branch from the unbound label link chain. 1898 // If available, a veneer for this label can be used for other branches in the 1899 // chain if the link chain cannot be fixed up without this branch. 1900 void RemoveBranchFromLabelLinkChain(Instruction* branch, 1901 Label* label, 1902 Instruction* label_veneer = NULL); 1903 1904 private: 1905 // Instruction helpers. 1906 void MoveWide(const Register& rd, 1907 uint64_t imm, 1908 int shift, 1909 MoveWideImmediateOp mov_op); 1910 void DataProcShiftedRegister(const Register& rd, 1911 const Register& rn, 1912 const Operand& operand, 1913 FlagsUpdate S, 1914 Instr op); 1915 void DataProcExtendedRegister(const Register& rd, 1916 const Register& rn, 1917 const Operand& operand, 1918 FlagsUpdate S, 1919 Instr op); 1920 void ConditionalSelect(const Register& rd, 1921 const Register& rn, 1922 const Register& rm, 1923 Condition cond, 1924 ConditionalSelectOp op); 1925 void DataProcessing1Source(const Register& rd, 1926 const Register& rn, 1927 DataProcessing1SourceOp op); 1928 void DataProcessing3Source(const Register& rd, 1929 const Register& rn, 1930 const Register& rm, 1931 const Register& ra, 1932 DataProcessing3SourceOp op); 1933 void FPDataProcessing1Source(const FPRegister& fd, 1934 const FPRegister& fn, 1935 FPDataProcessing1SourceOp op); 1936 void FPDataProcessing2Source(const FPRegister& fd, 1937 const FPRegister& fn, 1938 const FPRegister& fm, 1939 FPDataProcessing2SourceOp op); 1940 void FPDataProcessing3Source(const FPRegister& fd, 1941 const FPRegister& fn, 1942 const FPRegister& fm, 1943 const FPRegister& fa, 1944 FPDataProcessing3SourceOp op); 1945 1946 // Label helpers. 1947 1948 // Return an offset for a label-referencing instruction, typically a branch. 1949 int LinkAndGetByteOffsetTo(Label* label); 1950 1951 // This is the same as LinkAndGetByteOffsetTo, but return an offset 1952 // suitable for fields that take instruction offsets. 1953 inline int LinkAndGetInstructionOffsetTo(Label* label); 1954 1955 static const int kStartOfLabelLinkChain = 0; 1956 1957 // Verify that a label's link chain is intact. 1958 void CheckLabelLinkChain(Label const * label); 1959 1960 void RecordLiteral(int64_t imm, unsigned size); 1961 1962 // Postpone the generation of the constant pool for the specified number of 1963 // instructions. 1964 void BlockConstPoolFor(int instructions); 1965 1966 // Set how far from current pc the next constant pool check will be. SetNextConstPoolCheckIn(int instructions)1967 void SetNextConstPoolCheckIn(int instructions) { 1968 next_constant_pool_check_ = pc_offset() + instructions * kInstructionSize; 1969 } 1970 1971 // Emit the instruction at pc_. Emit(Instr instruction)1972 void Emit(Instr instruction) { 1973 STATIC_ASSERT(sizeof(*pc_) == 1); 1974 STATIC_ASSERT(sizeof(instruction) == kInstructionSize); 1975 DCHECK((pc_ + sizeof(instruction)) <= (buffer_ + buffer_size_)); 1976 1977 memcpy(pc_, &instruction, sizeof(instruction)); 1978 pc_ += sizeof(instruction); 1979 CheckBuffer(); 1980 } 1981 1982 // Emit data inline in the instruction stream. EmitData(void const * data,unsigned size)1983 void EmitData(void const * data, unsigned size) { 1984 DCHECK(sizeof(*pc_) == 1); 1985 DCHECK((pc_ + size) <= (buffer_ + buffer_size_)); 1986 1987 // TODO(all): Somehow register we have some data here. Then we can 1988 // disassemble it correctly. 1989 memcpy(pc_, data, size); 1990 pc_ += size; 1991 CheckBuffer(); 1992 } 1993 1994 void GrowBuffer(); 1995 void CheckBufferSpace(); 1996 void CheckBuffer(); 1997 1998 // Pc offset of the next constant pool check. 1999 int next_constant_pool_check_; 2000 2001 // Constant pool generation 2002 // Pools are emitted in the instruction stream. They are emitted when: 2003 // * the distance to the first use is above a pre-defined distance or 2004 // * the numbers of entries in the pool is above a pre-defined size or 2005 // * code generation is finished 2006 // If a pool needs to be emitted before code generation is finished a branch 2007 // over the emitted pool will be inserted. 2008 2009 // Constants in the pool may be addresses of functions that gets relocated; 2010 // if so, a relocation info entry is associated to the constant pool entry. 2011 2012 // Repeated checking whether the constant pool should be emitted is rather 2013 // expensive. By default we only check again once a number of instructions 2014 // has been generated. That also means that the sizing of the buffers is not 2015 // an exact science, and that we rely on some slop to not overrun buffers. 2016 static const int kCheckConstPoolInterval = 128; 2017 2018 // Distance to first use after a which a pool will be emitted. Pool entries 2019 // are accessed with pc relative load therefore this cannot be more than 2020 // 1 * MB. Since constant pool emission checks are interval based this value 2021 // is an approximation. 2022 static const int kApproxMaxDistToConstPool = 64 * KB; 2023 2024 // Number of pool entries after which a pool will be emitted. Since constant 2025 // pool emission checks are interval based this value is an approximation. 2026 static const int kApproxMaxPoolEntryCount = 512; 2027 2028 // Emission of the constant pool may be blocked in some code sequences. 2029 int const_pool_blocked_nesting_; // Block emission if this is not zero. 2030 int no_const_pool_before_; // Block emission before this pc offset. 2031 2032 // Emission of the veneer pools may be blocked in some code sequences. 2033 int veneer_pool_blocked_nesting_; // Block emission if this is not zero. 2034 2035 // Relocation info generation 2036 // Each relocation is encoded as a variable size value 2037 static const int kMaxRelocSize = RelocInfoWriter::kMaxSize; 2038 RelocInfoWriter reloc_info_writer; 2039 // Internal reference positions, required for (potential) patching in 2040 // GrowBuffer(); contains only those internal references whose labels 2041 // are already bound. 2042 std::deque<int> internal_reference_positions_; 2043 2044 // Relocation info records are also used during code generation as temporary 2045 // containers for constants and code target addresses until they are emitted 2046 // to the constant pool. These pending relocation info records are temporarily 2047 // stored in a separate buffer until a constant pool is emitted. 2048 // If every instruction in a long sequence is accessing the pool, we need one 2049 // pending relocation entry per instruction. 2050 2051 // The pending constant pool. 2052 ConstPool constpool_; 2053 2054 // Relocation for a type-recording IC has the AST id added to it. This 2055 // member variable is a way to pass the information from the call site to 2056 // the relocation info. 2057 TypeFeedbackId recorded_ast_id_; 2058 2059 inline TypeFeedbackId RecordedAstId(); 2060 inline void ClearRecordedAstId(); 2061 2062 protected: 2063 // Record the AST id of the CallIC being compiled, so that it can be placed 2064 // in the relocation information. SetRecordedAstId(TypeFeedbackId ast_id)2065 void SetRecordedAstId(TypeFeedbackId ast_id) { 2066 DCHECK(recorded_ast_id_.IsNone()); 2067 recorded_ast_id_ = ast_id; 2068 } 2069 2070 // Code generation 2071 // The relocation writer's position is at least kGap bytes below the end of 2072 // the generated instructions. This is so that multi-instruction sequences do 2073 // not have to check for overflow. The same is true for writes of large 2074 // relocation info entries, and debug strings encoded in the instruction 2075 // stream. 2076 static const int kGap = 128; 2077 2078 public: 2079 class FarBranchInfo { 2080 public: FarBranchInfo(int offset,Label * label)2081 FarBranchInfo(int offset, Label* label) 2082 : pc_offset_(offset), label_(label) {} 2083 // Offset of the branch in the code generation buffer. 2084 int pc_offset_; 2085 // The label branched to. 2086 Label* label_; 2087 }; 2088 2089 protected: 2090 // Information about unresolved (forward) branches. 2091 // The Assembler is only allowed to delete out-of-date information from here 2092 // after a label is bound. The MacroAssembler uses this information to 2093 // generate veneers. 2094 // 2095 // The second member gives information about the unresolved branch. The first 2096 // member of the pair is the maximum offset that the branch can reach in the 2097 // buffer. The map is sorted according to this reachable offset, allowing to 2098 // easily check when veneers need to be emitted. 2099 // Note that the maximum reachable offset (first member of the pairs) should 2100 // always be positive but has the same type as the return value for 2101 // pc_offset() for convenience. 2102 std::multimap<int, FarBranchInfo> unresolved_branches_; 2103 2104 // We generate a veneer for a branch if we reach within this distance of the 2105 // limit of the range. 2106 static const int kVeneerDistanceMargin = 1 * KB; 2107 // The factor of 2 is a finger in the air guess. With a default margin of 2108 // 1KB, that leaves us an addional 256 instructions to avoid generating a 2109 // protective branch. 2110 static const int kVeneerNoProtectionFactor = 2; 2111 static const int kVeneerDistanceCheckMargin = 2112 kVeneerNoProtectionFactor * kVeneerDistanceMargin; unresolved_branches_first_limit()2113 int unresolved_branches_first_limit() const { 2114 DCHECK(!unresolved_branches_.empty()); 2115 return unresolved_branches_.begin()->first; 2116 } 2117 // This is similar to next_constant_pool_check_ and helps reduce the overhead 2118 // of checking for veneer pools. 2119 // It is maintained to the closest unresolved branch limit minus the maximum 2120 // veneer margin (or kMaxInt if there are no unresolved branches). 2121 int next_veneer_pool_check_; 2122 2123 private: 2124 // If a veneer is emitted for a branch instruction, that instruction must be 2125 // removed from the associated label's link chain so that the assembler does 2126 // not later attempt (likely unsuccessfully) to patch it to branch directly to 2127 // the label. 2128 void DeleteUnresolvedBranchInfoForLabel(Label* label); 2129 // This function deletes the information related to the label by traversing 2130 // the label chain, and for each PC-relative instruction in the chain checking 2131 // if pending unresolved information exists. Its complexity is proportional to 2132 // the length of the label chain. 2133 void DeleteUnresolvedBranchInfoForLabelTraverse(Label* label); 2134 2135 private: 2136 PositionsRecorder positions_recorder_; 2137 friend class PositionsRecorder; 2138 friend class EnsureSpace; 2139 friend class ConstPool; 2140 }; 2141 2142 class PatchingAssembler : public Assembler { 2143 public: 2144 // Create an Assembler with a buffer starting at 'start'. 2145 // The buffer size is 2146 // size of instructions to patch + kGap 2147 // Where kGap is the distance from which the Assembler tries to grow the 2148 // buffer. 2149 // If more or fewer instructions than expected are generated or if some 2150 // relocation information takes space in the buffer, the PatchingAssembler 2151 // will crash trying to grow the buffer. PatchingAssembler(Isolate * isolate,Instruction * start,unsigned count)2152 PatchingAssembler(Isolate* isolate, Instruction* start, unsigned count) 2153 : Assembler(isolate, reinterpret_cast<byte*>(start), 2154 count * kInstructionSize + kGap) { 2155 StartBlockPools(); 2156 } 2157 PatchingAssembler(Isolate * isolate,byte * start,unsigned count)2158 PatchingAssembler(Isolate* isolate, byte* start, unsigned count) 2159 : Assembler(isolate, start, count * kInstructionSize + kGap) { 2160 // Block constant pool emission. 2161 StartBlockPools(); 2162 } 2163 ~PatchingAssembler()2164 ~PatchingAssembler() { 2165 // Const pool should still be blocked. 2166 DCHECK(is_const_pool_blocked()); 2167 EndBlockPools(); 2168 // Verify we have generated the number of instruction we expected. 2169 DCHECK((pc_offset() + kGap) == buffer_size_); 2170 // Verify no relocation information has been emitted. 2171 DCHECK(IsConstPoolEmpty()); 2172 // Flush the Instruction cache. 2173 size_t length = buffer_size_ - kGap; 2174 Assembler::FlushICache(isolate(), buffer_, length); 2175 } 2176 2177 // See definition of PatchAdrFar() for details. 2178 static const int kAdrFarPatchableNNops = 2; 2179 static const int kAdrFarPatchableNInstrs = kAdrFarPatchableNNops + 2; 2180 void PatchAdrFar(int64_t target_offset); 2181 }; 2182 2183 2184 class EnsureSpace BASE_EMBEDDED { 2185 public: EnsureSpace(Assembler * assembler)2186 explicit EnsureSpace(Assembler* assembler) { 2187 assembler->CheckBufferSpace(); 2188 } 2189 }; 2190 2191 } // namespace internal 2192 } // namespace v8 2193 2194 #endif // V8_ARM64_ASSEMBLER_ARM64_H_ 2195