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