1 // Copyright (c) 1994-2006 Sun Microsystems Inc. 2 // All Rights Reserved. 3 // 4 // Redistribution and use in source and binary forms, with or without 5 // modification, are permitted provided that the following conditions 6 // are met: 7 // 8 // - Redistributions of source code must retain the above copyright notice, 9 // this list of conditions and the following disclaimer. 10 // 11 // - Redistribution in binary form must reproduce the above copyright 12 // notice, this list of conditions and the following disclaimer in the 13 // documentation and/or other materials provided with the 14 // distribution. 15 // 16 // - Neither the name of Sun Microsystems or the names of contributors may 17 // be used to endorse or promote products derived from this software without 18 // specific prior written permission. 19 // 20 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 23 // FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 24 // COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 25 // INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 26 // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 27 // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 // HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 29 // STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 30 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 31 // OF THE POSSIBILITY OF SUCH DAMAGE. 32 33 // The original source code covered by the above license above has been 34 // modified significantly by Google Inc. 35 // Copyright 2014 the V8 project authors. All rights reserved. 36 37 // A light-weight PPC Assembler 38 // Generates user mode instructions for the PPC architecture up 39 40 #ifndef V8_PPC_ASSEMBLER_PPC_H_ 41 #define V8_PPC_ASSEMBLER_PPC_H_ 42 43 #include <stdio.h> 44 #include <vector> 45 46 #include "src/assembler.h" 47 #include "src/double.h" 48 #include "src/ppc/constants-ppc.h" 49 50 #if V8_HOST_ARCH_PPC && \ 51 (V8_OS_AIX || (V8_TARGET_ARCH_PPC64 && V8_TARGET_BIG_ENDIAN)) 52 #define ABI_USES_FUNCTION_DESCRIPTORS 1 53 #else 54 #define ABI_USES_FUNCTION_DESCRIPTORS 0 55 #endif 56 57 #if !V8_HOST_ARCH_PPC || V8_OS_AIX || V8_TARGET_ARCH_PPC64 58 #define ABI_PASSES_HANDLES_IN_REGS 1 59 #else 60 #define ABI_PASSES_HANDLES_IN_REGS 0 61 #endif 62 63 #if !V8_HOST_ARCH_PPC || !V8_TARGET_ARCH_PPC64 || V8_TARGET_LITTLE_ENDIAN 64 #define ABI_RETURNS_OBJECT_PAIRS_IN_REGS 1 65 #else 66 #define ABI_RETURNS_OBJECT_PAIRS_IN_REGS 0 67 #endif 68 69 #if !V8_HOST_ARCH_PPC || (V8_TARGET_ARCH_PPC64 && V8_TARGET_LITTLE_ENDIAN) 70 #define ABI_CALL_VIA_IP 1 71 #else 72 #define ABI_CALL_VIA_IP 0 73 #endif 74 75 #if !V8_HOST_ARCH_PPC || V8_OS_AIX || V8_TARGET_ARCH_PPC64 76 #define ABI_TOC_REGISTER 2 77 #else 78 #define ABI_TOC_REGISTER 13 79 #endif 80 81 #define INSTR_AND_DATA_CACHE_COHERENCY LWSYNC 82 83 namespace v8 { 84 namespace internal { 85 86 // clang-format off 87 #define GENERAL_REGISTERS(V) \ 88 V(r0) V(sp) V(r2) V(r3) V(r4) V(r5) V(r6) V(r7) \ 89 V(r8) V(r9) V(r10) V(r11) V(ip) V(r13) V(r14) V(r15) \ 90 V(r16) V(r17) V(r18) V(r19) V(r20) V(r21) V(r22) V(r23) \ 91 V(r24) V(r25) V(r26) V(r27) V(r28) V(r29) V(r30) V(fp) 92 93 #if V8_EMBEDDED_CONSTANT_POOL 94 #define ALLOCATABLE_GENERAL_REGISTERS(V) \ 95 V(r3) V(r4) V(r5) V(r6) V(r7) \ 96 V(r8) V(r9) V(r10) V(r14) V(r15) \ 97 V(r16) V(r17) V(r18) V(r19) V(r20) V(r21) V(r22) V(r23) \ 98 V(r24) V(r25) V(r26) V(r27) V(r30) 99 #else 100 #define ALLOCATABLE_GENERAL_REGISTERS(V) \ 101 V(r3) V(r4) V(r5) V(r6) V(r7) \ 102 V(r8) V(r9) V(r10) V(r14) V(r15) \ 103 V(r16) V(r17) V(r18) V(r19) V(r20) V(r21) V(r22) V(r23) \ 104 V(r24) V(r25) V(r26) V(r27) V(r28) V(r30) 105 #endif 106 107 #define LOW_DOUBLE_REGISTERS(V) \ 108 V(d0) V(d1) V(d2) V(d3) V(d4) V(d5) V(d6) V(d7) \ 109 V(d8) V(d9) V(d10) V(d11) V(d12) V(d13) V(d14) V(d15) 110 111 #define NON_LOW_DOUBLE_REGISTERS(V) \ 112 V(d16) V(d17) V(d18) V(d19) V(d20) V(d21) V(d22) V(d23) \ 113 V(d24) V(d25) V(d26) V(d27) V(d28) V(d29) V(d30) V(d31) 114 115 #define DOUBLE_REGISTERS(V) \ 116 LOW_DOUBLE_REGISTERS(V) NON_LOW_DOUBLE_REGISTERS(V) 117 118 #define FLOAT_REGISTERS DOUBLE_REGISTERS 119 #define SIMD128_REGISTERS DOUBLE_REGISTERS 120 121 #define ALLOCATABLE_DOUBLE_REGISTERS(V) \ 122 V(d1) V(d2) V(d3) V(d4) V(d5) V(d6) V(d7) \ 123 V(d8) V(d9) V(d10) V(d11) V(d12) V(d15) \ 124 V(d16) V(d17) V(d18) V(d19) V(d20) V(d21) V(d22) V(d23) \ 125 V(d24) V(d25) V(d26) V(d27) V(d28) V(d29) V(d30) V(d31) 126 127 #define C_REGISTERS(V) \ 128 V(cr0) V(cr1) V(cr2) V(cr3) V(cr4) V(cr5) V(cr6) V(cr7) \ 129 V(cr8) V(cr9) V(cr10) V(cr11) V(cr12) V(cr15) 130 // clang-format on 131 132 // Register list in load/store instructions 133 // Note that the bit values must match those used in actual instruction encoding 134 const int kNumRegs = 32; 135 136 // Caller-saved/arguments registers 137 const RegList kJSCallerSaved = 1 << 3 | // r3 a1 138 1 << 4 | // r4 a2 139 1 << 5 | // r5 a3 140 1 << 6 | // r6 a4 141 1 << 7 | // r7 a5 142 1 << 8 | // r8 a6 143 1 << 9 | // r9 a7 144 1 << 10 | // r10 a8 145 1 << 11; 146 147 const int kNumJSCallerSaved = 9; 148 149 // Return the code of the n-th caller-saved register available to JavaScript 150 // e.g. JSCallerSavedReg(0) returns r0.code() == 0 151 int JSCallerSavedCode(int n); 152 153 // Callee-saved registers preserved when switching from C to JavaScript 154 const RegList kCalleeSaved = 1 << 14 | // r14 155 1 << 15 | // r15 156 1 << 16 | // r16 157 1 << 17 | // r17 158 1 << 18 | // r18 159 1 << 19 | // r19 160 1 << 20 | // r20 161 1 << 21 | // r21 162 1 << 22 | // r22 163 1 << 23 | // r23 164 1 << 24 | // r24 165 1 << 25 | // r25 166 1 << 26 | // r26 167 1 << 27 | // r27 168 1 << 28 | // r28 169 1 << 29 | // r29 170 1 << 30 | // r20 171 1 << 31; // r31 172 173 const int kNumCalleeSaved = 18; 174 175 const RegList kCallerSavedDoubles = 1 << 0 | // d0 176 1 << 1 | // d1 177 1 << 2 | // d2 178 1 << 3 | // d3 179 1 << 4 | // d4 180 1 << 5 | // d5 181 1 << 6 | // d6 182 1 << 7 | // d7 183 1 << 8 | // d8 184 1 << 9 | // d9 185 1 << 10 | // d10 186 1 << 11 | // d11 187 1 << 12 | // d12 188 1 << 13; // d13 189 190 const int kNumCallerSavedDoubles = 14; 191 192 const RegList kCalleeSavedDoubles = 1 << 14 | // d14 193 1 << 15 | // d15 194 1 << 16 | // d16 195 1 << 17 | // d17 196 1 << 18 | // d18 197 1 << 19 | // d19 198 1 << 20 | // d20 199 1 << 21 | // d21 200 1 << 22 | // d22 201 1 << 23 | // d23 202 1 << 24 | // d24 203 1 << 25 | // d25 204 1 << 26 | // d26 205 1 << 27 | // d27 206 1 << 28 | // d28 207 1 << 29 | // d29 208 1 << 30 | // d30 209 1 << 31; // d31 210 211 const int kNumCalleeSavedDoubles = 18; 212 213 // Number of registers for which space is reserved in safepoints. Must be a 214 // multiple of 8. 215 const int kNumSafepointRegisters = 32; 216 217 // The following constants describe the stack frame linkage area as 218 // defined by the ABI. Note that kNumRequiredStackFrameSlots must 219 // satisfy alignment requirements (rounding up if required). 220 #if V8_TARGET_ARCH_PPC64 && V8_TARGET_LITTLE_ENDIAN 221 // [0] back chain 222 // [1] condition register save area 223 // [2] link register save area 224 // [3] TOC save area 225 // [4] Parameter1 save area 226 // ... 227 // [11] Parameter8 save area 228 // [12] Parameter9 slot (if necessary) 229 // ... 230 const int kNumRequiredStackFrameSlots = 12; 231 const int kStackFrameLRSlot = 2; 232 const int kStackFrameExtraParamSlot = 12; 233 #elif V8_OS_AIX || V8_TARGET_ARCH_PPC64 234 // [0] back chain 235 // [1] condition register save area 236 // [2] link register save area 237 // [3] reserved for compiler 238 // [4] reserved by binder 239 // [5] TOC save area 240 // [6] Parameter1 save area 241 // ... 242 // [13] Parameter8 save area 243 // [14] Parameter9 slot (if necessary) 244 // ... 245 #if V8_TARGET_ARCH_PPC64 246 const int kNumRequiredStackFrameSlots = 14; 247 #else 248 const int kNumRequiredStackFrameSlots = 16; 249 #endif 250 const int kStackFrameLRSlot = 2; 251 const int kStackFrameExtraParamSlot = 14; 252 #else 253 // [0] back chain 254 // [1] link register save area 255 // [2] Parameter9 slot (if necessary) 256 // ... 257 const int kNumRequiredStackFrameSlots = 4; 258 const int kStackFrameLRSlot = 1; 259 const int kStackFrameExtraParamSlot = 2; 260 #endif 261 262 // Define the list of registers actually saved at safepoints. 263 // Note that the number of saved registers may be smaller than the reserved 264 // space, i.e. kNumSafepointSavedRegisters <= kNumSafepointRegisters. 265 const RegList kSafepointSavedRegisters = kJSCallerSaved | kCalleeSaved; 266 const int kNumSafepointSavedRegisters = kNumJSCallerSaved + kNumCalleeSaved; 267 268 enum RegisterCode { 269 #define REGISTER_CODE(R) kRegCode_##R, 270 GENERAL_REGISTERS(REGISTER_CODE) 271 #undef REGISTER_CODE 272 kRegAfterLast 273 }; 274 275 class Register : public RegisterBase<Register, kRegAfterLast> { 276 public: 277 #if V8_TARGET_LITTLE_ENDIAN 278 static constexpr int kMantissaOffset = 0; 279 static constexpr int kExponentOffset = 4; 280 #else 281 static constexpr int kMantissaOffset = 4; 282 static constexpr int kExponentOffset = 0; 283 #endif 284 285 private: 286 friend class RegisterBase; 287 explicit constexpr Register(int code) : RegisterBase(code) {} 288 }; 289 290 ASSERT_TRIVIALLY_COPYABLE(Register); 291 static_assert(sizeof(Register) == sizeof(int), 292 "Register can efficiently be passed by value"); 293 294 #define DEFINE_REGISTER(R) \ 295 constexpr Register R = Register::from_code<kRegCode_##R>(); 296 GENERAL_REGISTERS(DEFINE_REGISTER) 297 #undef DEFINE_REGISTER 298 constexpr Register no_reg = Register::no_reg(); 299 300 // Aliases 301 constexpr Register kConstantPoolRegister = r28; // Constant pool. 302 constexpr Register kRootRegister = r29; // Roots array pointer. 303 constexpr Register cp = r30; // JavaScript context pointer. 304 305 constexpr bool kPadArguments = false; 306 constexpr bool kSimpleFPAliasing = true; 307 constexpr bool kSimdMaskRegisters = false; 308 309 enum DoubleRegisterCode { 310 #define REGISTER_CODE(R) kDoubleCode_##R, 311 DOUBLE_REGISTERS(REGISTER_CODE) 312 #undef REGISTER_CODE 313 kDoubleAfterLast 314 }; 315 316 // Double word FP register. 317 class DoubleRegister : public RegisterBase<DoubleRegister, kDoubleAfterLast> { 318 public: 319 // A few double registers are reserved: one as a scratch register and one to 320 // hold 0.0, that does not fit in the immediate field of vmov instructions. 321 // d14: 0.0 322 // d15: scratch register. 323 static constexpr int kSizeInBytes = 8; 324 inline static int NumRegisters(); 325 326 private: 327 friend class RegisterBase; 328 explicit constexpr DoubleRegister(int code) : RegisterBase(code) {} 329 }; 330 331 ASSERT_TRIVIALLY_COPYABLE(DoubleRegister); 332 static_assert(sizeof(DoubleRegister) == sizeof(int), 333 "DoubleRegister can efficiently be passed by value"); 334 335 typedef DoubleRegister FloatRegister; 336 337 // TODO(ppc) Define SIMD registers. 338 typedef DoubleRegister Simd128Register; 339 340 #define DEFINE_REGISTER(R) \ 341 constexpr DoubleRegister R = DoubleRegister::from_code<kDoubleCode_##R>(); 342 DOUBLE_REGISTERS(DEFINE_REGISTER) 343 #undef DEFINE_REGISTER 344 constexpr DoubleRegister no_dreg = DoubleRegister::no_reg(); 345 346 constexpr DoubleRegister kFirstCalleeSavedDoubleReg = d14; 347 constexpr DoubleRegister kLastCalleeSavedDoubleReg = d31; 348 constexpr DoubleRegister kDoubleRegZero = d14; 349 constexpr DoubleRegister kScratchDoubleReg = d13; 350 351 Register ToRegister(int num); 352 353 enum CRegisterCode { 354 #define REGISTER_CODE(R) kCCode_##R, 355 C_REGISTERS(REGISTER_CODE) 356 #undef REGISTER_CODE 357 kCAfterLast 358 }; 359 360 // Coprocessor register 361 class CRegister : public RegisterBase<CRegister, kCAfterLast> { 362 friend class RegisterBase; 363 explicit constexpr CRegister(int code) : RegisterBase(code) {} 364 }; 365 366 constexpr CRegister no_creg = CRegister::no_reg(); 367 #define DECLARE_C_REGISTER(R) \ 368 constexpr CRegister R = CRegister::from_code<kCCode_##R>(); 369 C_REGISTERS(DECLARE_C_REGISTER) 370 #undef DECLARE_C_REGISTER 371 372 // ----------------------------------------------------------------------------- 373 // Machine instruction Operands 374 375 // Class Operand represents a shifter operand in data processing instructions 376 class Operand BASE_EMBEDDED { 377 public: 378 // immediate 379 V8_INLINE explicit Operand(intptr_t immediate, 380 RelocInfo::Mode rmode = RelocInfo::NONE) 381 : rmode_(rmode) { 382 value_.immediate = immediate; 383 } 384 V8_INLINE static Operand Zero() { return Operand(static_cast<intptr_t>(0)); } 385 V8_INLINE explicit Operand(const ExternalReference& f) 386 : rmode_(RelocInfo::EXTERNAL_REFERENCE) { 387 value_.immediate = static_cast<intptr_t>(f.address()); 388 } 389 explicit Operand(Handle<HeapObject> handle); 390 V8_INLINE explicit Operand(Smi* value) : rmode_(RelocInfo::NONE) { 391 value_.immediate = reinterpret_cast<intptr_t>(value); 392 } 393 // rm 394 V8_INLINE explicit Operand(Register rm); 395 396 static Operand EmbeddedNumber(double number); // Smi or HeapNumber. 397 static Operand EmbeddedCode(CodeStub* stub); 398 399 // Return true if this is a register operand. 400 V8_INLINE bool is_reg() const { return rm_.is_valid(); } 401 402 bool must_output_reloc_info(const Assembler* assembler) const; 403 404 inline intptr_t immediate() const { 405 DCHECK(IsImmediate()); 406 DCHECK(!IsHeapObjectRequest()); 407 return value_.immediate; 408 } 409 bool IsImmediate() const { return !rm_.is_valid(); } 410 411 HeapObjectRequest heap_object_request() const { 412 DCHECK(IsHeapObjectRequest()); 413 return value_.heap_object_request; 414 } 415 416 Register rm() const { return rm_; } 417 418 bool IsHeapObjectRequest() const { 419 DCHECK_IMPLIES(is_heap_object_request_, IsImmediate()); 420 DCHECK_IMPLIES(is_heap_object_request_, 421 rmode_ == RelocInfo::EMBEDDED_OBJECT || 422 rmode_ == RelocInfo::CODE_TARGET); 423 return is_heap_object_request_; 424 } 425 426 private: 427 Register rm_ = no_reg; 428 union Value { 429 Value() {} 430 HeapObjectRequest heap_object_request; // if is_heap_object_request_ 431 intptr_t immediate; // otherwise 432 } value_; // valid if rm_ == no_reg 433 bool is_heap_object_request_ = false; 434 435 RelocInfo::Mode rmode_; 436 437 friend class Assembler; 438 friend class MacroAssembler; 439 }; 440 441 442 // Class MemOperand represents a memory operand in load and store instructions 443 // On PowerPC we have base register + 16bit signed value 444 // Alternatively we can have a 16bit signed value immediate 445 class MemOperand BASE_EMBEDDED { 446 public: 447 explicit MemOperand(Register rn, int32_t offset = 0); 448 449 explicit MemOperand(Register ra, Register rb); 450 451 int32_t offset() const { 452 return offset_; 453 } 454 455 // PowerPC - base register 456 Register ra() const { 457 return ra_; 458 } 459 460 Register rb() const { 461 return rb_; 462 } 463 464 private: 465 Register ra_; // base 466 int32_t offset_; // offset 467 Register rb_; // index 468 469 friend class Assembler; 470 }; 471 472 473 class DeferredRelocInfo { 474 public: 475 DeferredRelocInfo() {} 476 DeferredRelocInfo(int position, RelocInfo::Mode rmode, intptr_t data) 477 : position_(position), rmode_(rmode), data_(data) {} 478 479 int position() const { return position_; } 480 RelocInfo::Mode rmode() const { return rmode_; } 481 intptr_t data() const { return data_; } 482 483 private: 484 int position_; 485 RelocInfo::Mode rmode_; 486 intptr_t data_; 487 }; 488 489 490 class Assembler : public AssemblerBase { 491 public: 492 // Create an assembler. Instructions and relocation information are emitted 493 // into a buffer, with the instructions starting from the beginning and the 494 // relocation information starting from the end of the buffer. See CodeDesc 495 // for a detailed comment on the layout (globals.h). 496 // 497 // If the provided buffer is nullptr, the assembler allocates and grows its 498 // own buffer, and buffer_size determines the initial buffer size. The buffer 499 // is owned by the assembler and deallocated upon destruction of the 500 // assembler. 501 // 502 // If the provided buffer is not nullptr, the assembler uses the provided 503 // buffer for code generation and assumes its size to be buffer_size. If the 504 // buffer is too small, a fatal error occurs. No deallocation of the buffer is 505 // done upon destruction of the assembler. 506 Assembler(const AssemblerOptions& options, void* buffer, int buffer_size); 507 virtual ~Assembler() {} 508 509 // GetCode emits any pending (non-emitted) code and fills the descriptor 510 // desc. GetCode() is idempotent; it returns the same result if no other 511 // Assembler functions are invoked in between GetCode() calls. 512 void GetCode(Isolate* isolate, CodeDesc* desc); 513 514 // Label operations & relative jumps (PPUM Appendix D) 515 // 516 // Takes a branch opcode (cc) and a label (L) and generates 517 // either a backward branch or a forward branch and links it 518 // to the label fixup chain. Usage: 519 // 520 // Label L; // unbound label 521 // j(cc, &L); // forward branch to unbound label 522 // bind(&L); // bind label to the current pc 523 // j(cc, &L); // backward branch to bound label 524 // bind(&L); // illegal: a label may be bound only once 525 // 526 // Note: The same Label can be used for forward and backward branches 527 // but it may be bound only once. 528 529 void bind(Label* L); // binds an unbound label L to the current code position 530 531 // Links a label at the current pc_offset(). If already bound, returns the 532 // bound position. If already linked, returns the position of the prior link. 533 // Otherwise, returns the current pc_offset(). 534 int link(Label* L); 535 536 // Determines if Label is bound and near enough so that a single 537 // branch instruction can be used to reach it. 538 bool is_near(Label* L, Condition cond); 539 540 // Returns the branch offset to the given label from the current code position 541 // Links the label to the current position if it is still unbound 542 int branch_offset(Label* L) { 543 if (L->is_unused() && !trampoline_emitted_) { 544 TrackBranch(); 545 } 546 return link(L) - pc_offset(); 547 } 548 549 // Puts a labels target address at the given position. 550 // The high 8 bits are set to zero. 551 void label_at_put(Label* L, int at_offset); 552 553 V8_INLINE static bool IsConstantPoolLoadStart( 554 Address pc, ConstantPoolEntry::Access* access = nullptr); 555 V8_INLINE static bool IsConstantPoolLoadEnd( 556 Address pc, ConstantPoolEntry::Access* access = nullptr); 557 V8_INLINE static int GetConstantPoolOffset(Address pc, 558 ConstantPoolEntry::Access access, 559 ConstantPoolEntry::Type type); 560 V8_INLINE void PatchConstantPoolAccessInstruction( 561 int pc_offset, int offset, ConstantPoolEntry::Access access, 562 ConstantPoolEntry::Type type); 563 564 // Return the address in the constant pool of the code target address used by 565 // the branch/call instruction at pc, or the object in a mov. 566 V8_INLINE static Address target_constant_pool_address_at( 567 Address pc, Address constant_pool, ConstantPoolEntry::Access access, 568 ConstantPoolEntry::Type type); 569 570 // Read/Modify the code target address in the branch/call instruction at pc. 571 // The isolate argument is unused (and may be nullptr) when skipping flushing. 572 V8_INLINE static Address target_address_at(Address pc, Address constant_pool); 573 V8_INLINE static void set_target_address_at( 574 Address pc, Address constant_pool, Address target, 575 ICacheFlushMode icache_flush_mode = FLUSH_ICACHE_IF_NEEDED); 576 577 // Return the code target address at a call site from the return address 578 // of that call in the instruction stream. 579 inline static Address target_address_from_return_address(Address pc); 580 581 // Given the address of the beginning of a call, return the address 582 // in the instruction stream that the call will return to. 583 V8_INLINE static Address return_address_from_call_start(Address pc); 584 585 // This sets the branch destination. 586 // This is for calls and branches within generated code. 587 inline static void deserialization_set_special_target_at( 588 Address instruction_payload, Code* code, Address target); 589 590 // Get the size of the special target encoded at 'instruction_payload'. 591 inline static int deserialization_special_target_size( 592 Address instruction_payload); 593 594 // This sets the internal reference at the pc. 595 inline static void deserialization_set_target_internal_reference_at( 596 Address pc, Address target, 597 RelocInfo::Mode mode = RelocInfo::INTERNAL_REFERENCE); 598 599 // Here we are patching the address in the LUI/ORI instruction pair. 600 // These values are used in the serialization process and must be zero for 601 // PPC platform, as Code, Embedded Object or External-reference pointers 602 // are split across two consecutive instructions and don't exist separately 603 // in the code, so the serializer should not step forwards in memory after 604 // a target is resolved and written. 605 static constexpr int kSpecialTargetSize = 0; 606 607 // Number of instructions to load an address via a mov sequence. 608 #if V8_TARGET_ARCH_PPC64 609 static constexpr int kMovInstructionsConstantPool = 1; 610 static constexpr int kMovInstructionsNoConstantPool = 5; 611 #if defined(V8_PPC_TAGGING_OPT) 612 static constexpr int kTaggedLoadInstructions = 1; 613 #else 614 static constexpr int kTaggedLoadInstructions = 2; 615 #endif 616 #else 617 static constexpr int kMovInstructionsConstantPool = 1; 618 static constexpr int kMovInstructionsNoConstantPool = 2; 619 static constexpr int kTaggedLoadInstructions = 1; 620 #endif 621 static constexpr int kMovInstructions = FLAG_enable_embedded_constant_pool 622 ? kMovInstructionsConstantPool 623 : kMovInstructionsNoConstantPool; 624 625 // Distance between the instruction referring to the address of the call 626 // target and the return address. 627 628 // Call sequence is a FIXED_SEQUENCE: 629 // mov r8, @ call address 630 // mtlr r8 631 // blrl 632 // @ return address 633 static constexpr int kCallTargetAddressOffset = 634 (kMovInstructions + 2) * kInstrSize; 635 636 static inline int encode_crbit(const CRegister& cr, enum CRBit crbit) { 637 return ((cr.code() * CRWIDTH) + crbit); 638 } 639 640 #define DECLARE_PPC_X_INSTRUCTIONS_A_FORM(name, instr_name, instr_value) \ 641 inline void name(const Register rt, const Register ra, \ 642 const Register rb, const RCBit rc = LeaveRC) { \ 643 x_form(instr_name, rt, ra, rb, rc); \ 644 } 645 646 #define DECLARE_PPC_X_INSTRUCTIONS_B_FORM(name, instr_name, instr_value) \ 647 inline void name(const Register ra, const Register rs, \ 648 const Register rb, const RCBit rc = LeaveRC) { \ 649 x_form(instr_name, rs, ra, rb, rc); \ 650 } 651 652 #define DECLARE_PPC_X_INSTRUCTIONS_C_FORM(name, instr_name, instr_value) \ 653 inline void name(const Register dst, const Register src, \ 654 const RCBit rc = LeaveRC) { \ 655 x_form(instr_name, src, dst, r0, rc); \ 656 } 657 658 #define DECLARE_PPC_X_INSTRUCTIONS_D_FORM(name, instr_name, instr_value) \ 659 template <class R> \ 660 inline void name(const R rt, const Register ra, const Register rb, \ 661 const RCBit rc = LeaveRC) { \ 662 x_form(instr_name, rt.code(), ra.code(), rb.code(), rc); \ 663 } \ 664 template <class R> \ 665 inline void name(const R dst, const MemOperand& src) { \ 666 name(dst, src.ra(), src.rb()); \ 667 } 668 669 #define DECLARE_PPC_X_INSTRUCTIONS_E_FORM(name, instr_name, instr_value) \ 670 inline void name(const Register dst, const Register src, \ 671 const int sh, const RCBit rc = LeaveRC) { \ 672 x_form(instr_name, src.code(), dst.code(), sh, rc); \ 673 } 674 675 #define DECLARE_PPC_X_INSTRUCTIONS_F_FORM(name, instr_name, instr_value) \ 676 inline void name(const Register src1, const Register src2, \ 677 const CRegister cr = cr7, const RCBit rc = LeaveRC) { \ 678 x_form(instr_name, cr, src1, src2, rc); \ 679 } \ 680 inline void name##w(const Register src1, const Register src2, \ 681 const CRegister cr = cr7, const RCBit rc = LeaveRC) { \ 682 x_form(instr_name, cr.code() * B2, src1.code(), src2.code(), LeaveRC); \ 683 } 684 685 #define DECLARE_PPC_X_INSTRUCTIONS_EH_S_FORM(name, instr_name, instr_value) \ 686 inline void name(const Register dst, const MemOperand& src) { \ 687 x_form(instr_name, src.ra(), dst, src.rb(), SetEH); \ 688 } 689 #define DECLARE_PPC_X_INSTRUCTIONS_EH_L_FORM(name, instr_name, instr_value) \ 690 inline void name(const Register dst, const MemOperand& src) { \ 691 DCHECK(src.ra_ != r0); \ 692 x_form(instr_name, src.ra(), dst, src.rb(), SetEH); \ 693 } 694 695 inline void x_form(Instr instr, int f1, int f2, int f3, int rc) { 696 emit(instr | f1 * B21 | f2 * B16 | f3 * B11 | rc); 697 } 698 inline void x_form(Instr instr, Register rs, Register ra, Register rb, 699 RCBit rc) { 700 emit(instr | rs.code() * B21 | ra.code() * B16 | rb.code() * B11 | rc); 701 } 702 inline void x_form(Instr instr, Register ra, Register rs, Register rb, 703 EHBit eh = SetEH) { 704 emit(instr | rs.code() * B21 | ra.code() * B16 | rb.code() * B11 | eh); 705 } 706 inline void x_form(Instr instr, CRegister cr, Register s1, Register s2, 707 RCBit rc) { 708 #if V8_TARGET_ARCH_PPC64 709 int L = 1; 710 #else 711 int L = 0; 712 #endif 713 emit(instr | cr.code() * B23 | L * B21 | s1.code() * B16 | 714 s2.code() * B11 | rc); 715 } 716 717 PPC_X_OPCODE_A_FORM_LIST(DECLARE_PPC_X_INSTRUCTIONS_A_FORM) 718 PPC_X_OPCODE_B_FORM_LIST(DECLARE_PPC_X_INSTRUCTIONS_B_FORM) 719 PPC_X_OPCODE_C_FORM_LIST(DECLARE_PPC_X_INSTRUCTIONS_C_FORM) 720 PPC_X_OPCODE_D_FORM_LIST(DECLARE_PPC_X_INSTRUCTIONS_D_FORM) 721 PPC_X_OPCODE_E_FORM_LIST(DECLARE_PPC_X_INSTRUCTIONS_E_FORM) 722 PPC_X_OPCODE_F_FORM_LIST(DECLARE_PPC_X_INSTRUCTIONS_F_FORM) 723 PPC_X_OPCODE_EH_S_FORM_LIST(DECLARE_PPC_X_INSTRUCTIONS_EH_S_FORM) 724 PPC_X_OPCODE_EH_L_FORM_LIST(DECLARE_PPC_X_INSTRUCTIONS_EH_L_FORM) 725 726 inline void notx(Register dst, Register src, RCBit rc = LeaveRC) { 727 nor(dst, src, src, rc); 728 } 729 inline void lwax(Register rt, const MemOperand& src) { 730 #if V8_TARGET_ARCH_PPC64 731 Register ra = src.ra(); 732 Register rb = src.rb(); 733 DCHECK(ra != r0); 734 x_form(LWAX, rt, ra, rb, LeaveRC); 735 #else 736 lwzx(rt, src); 737 #endif 738 } 739 inline void extsw(Register rs, Register ra, RCBit rc = LeaveRC) { 740 #if V8_TARGET_ARCH_PPC64 741 emit(EXT2 | EXTSW | ra.code() * B21 | rs.code() * B16 | rc); 742 #else 743 // nop on 32-bit 744 DCHECK(rs == ra && rc == LeaveRC); 745 #endif 746 } 747 748 #undef DECLARE_PPC_X_INSTRUCTIONS_A_FORM 749 #undef DECLARE_PPC_X_INSTRUCTIONS_B_FORM 750 #undef DECLARE_PPC_X_INSTRUCTIONS_C_FORM 751 #undef DECLARE_PPC_X_INSTRUCTIONS_D_FORM 752 #undef DECLARE_PPC_X_INSTRUCTIONS_E_FORM 753 #undef DECLARE_PPC_X_INSTRUCTIONS_F_FORM 754 #undef DECLARE_PPC_X_INSTRUCTIONS_EH_S_FORM 755 #undef DECLARE_PPC_X_INSTRUCTIONS_EH_L_FORM 756 757 #define DECLARE_PPC_XX3_INSTRUCTIONS(name, instr_name, instr_value) \ 758 inline void name(const DoubleRegister rt, const DoubleRegister ra, \ 759 const DoubleRegister rb) { \ 760 xx3_form(instr_name, rt, ra, rb); \ 761 } 762 763 inline void xx3_form(Instr instr, DoubleRegister t, DoubleRegister a, 764 DoubleRegister b) { 765 int AX = ((a.code() & 0x20) >> 5) & 0x1; 766 int BX = ((b.code() & 0x20) >> 5) & 0x1; 767 int TX = ((t.code() & 0x20) >> 5) & 0x1; 768 769 emit(instr | (t.code() & 0x1F) * B21 | (a.code() & 0x1F) * B16 | 770 (b.code() & 0x1F) * B11 | AX * B2 | BX * B1 | TX); 771 } 772 773 PPC_XX3_OPCODE_LIST(DECLARE_PPC_XX3_INSTRUCTIONS) 774 #undef DECLARE_PPC_XX3_INSTRUCTIONS 775 776 // --------------------------------------------------------------------------- 777 // Code generation 778 779 // Insert the smallest number of nop instructions 780 // possible to align the pc offset to a multiple 781 // of m. m must be a power of 2 (>= 4). 782 void Align(int m); 783 // Insert the smallest number of zero bytes possible to align the pc offset 784 // to a mulitple of m. m must be a power of 2 (>= 2). 785 void DataAlign(int m); 786 // Aligns code to something that's optimal for a jump target for the platform. 787 void CodeTargetAlign(); 788 789 // Branch instructions 790 void bclr(BOfield bo, int condition_bit, LKBit lk); 791 void blr(); 792 void bc(int branch_offset, BOfield bo, int condition_bit, LKBit lk = LeaveLK); 793 void b(int branch_offset, LKBit lk); 794 795 void bcctr(BOfield bo, int condition_bit, LKBit lk); 796 void bctr(); 797 void bctrl(); 798 799 // Convenience branch instructions using labels 800 void b(Label* L, LKBit lk = LeaveLK) { b(branch_offset(L), lk); } 801 802 inline CRegister cmpi_optimization(CRegister cr) { 803 // Check whether the branch is preceded by an optimizable cmpi against 0. 804 // The cmpi can be deleted if it is also preceded by an instruction that 805 // sets the register used by the compare and supports a dot form. 806 unsigned int sradi_mask = kOpcodeMask | kExt2OpcodeVariant2Mask; 807 unsigned int srawi_mask = kOpcodeMask | kExt2OpcodeMask; 808 int pos = pc_offset(); 809 int cmpi_pos = pc_offset() - kInstrSize; 810 811 if (cmpi_pos > 0 && optimizable_cmpi_pos_ == cmpi_pos && 812 cmpi_cr_.code() == cr.code() && last_bound_pos_ != pos) { 813 int xpos = cmpi_pos - kInstrSize; 814 int xinstr = instr_at(xpos); 815 int cmpi_ra = (instr_at(cmpi_pos) & 0x1f0000) >> 16; 816 // ra is at the same bit position for the three cases below. 817 int ra = (xinstr & 0x1f0000) >> 16; 818 if (cmpi_ra == ra) { 819 if ((xinstr & sradi_mask) == (EXT2 | SRADIX)) { 820 cr = cr0; 821 instr_at_put(xpos, xinstr | SetRC); 822 pc_ -= kInstrSize; 823 } else if ((xinstr & srawi_mask) == (EXT2 | SRAWIX)) { 824 cr = cr0; 825 instr_at_put(xpos, xinstr | SetRC); 826 pc_ -= kInstrSize; 827 } else if ((xinstr & kOpcodeMask) == ANDIx) { 828 cr = cr0; 829 pc_ -= kInstrSize; 830 // nothing to do here since andi. records. 831 } 832 // didn't match one of the above, must keep cmpwi. 833 } 834 } 835 return cr; 836 } 837 838 void bc_short(Condition cond, Label* L, CRegister cr = cr7, 839 LKBit lk = LeaveLK) { 840 DCHECK(cond != al); 841 DCHECK(cr.code() >= 0 && cr.code() <= 7); 842 843 cr = cmpi_optimization(cr); 844 845 int b_offset = branch_offset(L); 846 847 switch (cond) { 848 case eq: 849 bc(b_offset, BT, encode_crbit(cr, CR_EQ), lk); 850 break; 851 case ne: 852 bc(b_offset, BF, encode_crbit(cr, CR_EQ), lk); 853 break; 854 case gt: 855 bc(b_offset, BT, encode_crbit(cr, CR_GT), lk); 856 break; 857 case le: 858 bc(b_offset, BF, encode_crbit(cr, CR_GT), lk); 859 break; 860 case lt: 861 bc(b_offset, BT, encode_crbit(cr, CR_LT), lk); 862 break; 863 case ge: 864 bc(b_offset, BF, encode_crbit(cr, CR_LT), lk); 865 break; 866 case unordered: 867 bc(b_offset, BT, encode_crbit(cr, CR_FU), lk); 868 break; 869 case ordered: 870 bc(b_offset, BF, encode_crbit(cr, CR_FU), lk); 871 break; 872 case overflow: 873 bc(b_offset, BT, encode_crbit(cr, CR_SO), lk); 874 break; 875 case nooverflow: 876 bc(b_offset, BF, encode_crbit(cr, CR_SO), lk); 877 break; 878 default: 879 UNIMPLEMENTED(); 880 } 881 } 882 883 void bclr(Condition cond, CRegister cr = cr7, LKBit lk = LeaveLK) { 884 DCHECK(cond != al); 885 DCHECK(cr.code() >= 0 && cr.code() <= 7); 886 887 cr = cmpi_optimization(cr); 888 889 switch (cond) { 890 case eq: 891 bclr(BT, encode_crbit(cr, CR_EQ), lk); 892 break; 893 case ne: 894 bclr(BF, encode_crbit(cr, CR_EQ), lk); 895 break; 896 case gt: 897 bclr(BT, encode_crbit(cr, CR_GT), lk); 898 break; 899 case le: 900 bclr(BF, encode_crbit(cr, CR_GT), lk); 901 break; 902 case lt: 903 bclr(BT, encode_crbit(cr, CR_LT), lk); 904 break; 905 case ge: 906 bclr(BF, encode_crbit(cr, CR_LT), lk); 907 break; 908 case unordered: 909 bclr(BT, encode_crbit(cr, CR_FU), lk); 910 break; 911 case ordered: 912 bclr(BF, encode_crbit(cr, CR_FU), lk); 913 break; 914 case overflow: 915 bclr(BT, encode_crbit(cr, CR_SO), lk); 916 break; 917 case nooverflow: 918 bclr(BF, encode_crbit(cr, CR_SO), lk); 919 break; 920 default: 921 UNIMPLEMENTED(); 922 } 923 } 924 925 void isel(Register rt, Register ra, Register rb, int cb); 926 void isel(Condition cond, Register rt, Register ra, Register rb, 927 CRegister cr = cr7) { 928 DCHECK(cond != al); 929 DCHECK(cr.code() >= 0 && cr.code() <= 7); 930 931 cr = cmpi_optimization(cr); 932 933 switch (cond) { 934 case eq: 935 isel(rt, ra, rb, encode_crbit(cr, CR_EQ)); 936 break; 937 case ne: 938 isel(rt, rb, ra, encode_crbit(cr, CR_EQ)); 939 break; 940 case gt: 941 isel(rt, ra, rb, encode_crbit(cr, CR_GT)); 942 break; 943 case le: 944 isel(rt, rb, ra, encode_crbit(cr, CR_GT)); 945 break; 946 case lt: 947 isel(rt, ra, rb, encode_crbit(cr, CR_LT)); 948 break; 949 case ge: 950 isel(rt, rb, ra, encode_crbit(cr, CR_LT)); 951 break; 952 case unordered: 953 isel(rt, ra, rb, encode_crbit(cr, CR_FU)); 954 break; 955 case ordered: 956 isel(rt, rb, ra, encode_crbit(cr, CR_FU)); 957 break; 958 case overflow: 959 isel(rt, ra, rb, encode_crbit(cr, CR_SO)); 960 break; 961 case nooverflow: 962 isel(rt, rb, ra, encode_crbit(cr, CR_SO)); 963 break; 964 default: 965 UNIMPLEMENTED(); 966 } 967 } 968 969 void b(Condition cond, Label* L, CRegister cr = cr7, LKBit lk = LeaveLK) { 970 if (cond == al) { 971 b(L, lk); 972 return; 973 } 974 975 if ((L->is_bound() && is_near(L, cond)) || !is_trampoline_emitted()) { 976 bc_short(cond, L, cr, lk); 977 return; 978 } 979 980 Label skip; 981 Condition neg_cond = NegateCondition(cond); 982 bc_short(neg_cond, &skip, cr); 983 b(L, lk); 984 bind(&skip); 985 } 986 987 void bne(Label* L, CRegister cr = cr7, LKBit lk = LeaveLK) { 988 b(ne, L, cr, lk); 989 } 990 void beq(Label* L, CRegister cr = cr7, LKBit lk = LeaveLK) { 991 b(eq, L, cr, lk); 992 } 993 void blt(Label* L, CRegister cr = cr7, LKBit lk = LeaveLK) { 994 b(lt, L, cr, lk); 995 } 996 void bge(Label* L, CRegister cr = cr7, LKBit lk = LeaveLK) { 997 b(ge, L, cr, lk); 998 } 999 void ble(Label* L, CRegister cr = cr7, LKBit lk = LeaveLK) { 1000 b(le, L, cr, lk); 1001 } 1002 void bgt(Label* L, CRegister cr = cr7, LKBit lk = LeaveLK) { 1003 b(gt, L, cr, lk); 1004 } 1005 void bunordered(Label* L, CRegister cr = cr7, LKBit lk = LeaveLK) { 1006 b(unordered, L, cr, lk); 1007 } 1008 void bordered(Label* L, CRegister cr = cr7, LKBit lk = LeaveLK) { 1009 b(ordered, L, cr, lk); 1010 } 1011 void boverflow(Label* L, CRegister cr = cr0, LKBit lk = LeaveLK) { 1012 b(overflow, L, cr, lk); 1013 } 1014 void bnooverflow(Label* L, CRegister cr = cr0, LKBit lk = LeaveLK) { 1015 b(nooverflow, L, cr, lk); 1016 } 1017 1018 // Decrement CTR; branch if CTR != 0 1019 void bdnz(Label* L, LKBit lk = LeaveLK) { 1020 bc(branch_offset(L), DCBNZ, 0, lk); 1021 } 1022 1023 // Data-processing instructions 1024 1025 void sub(Register dst, Register src1, Register src2, OEBit s = LeaveOE, 1026 RCBit r = LeaveRC); 1027 1028 void subc(Register dst, Register src1, Register src2, OEBit s = LeaveOE, 1029 RCBit r = LeaveRC); 1030 void sube(Register dst, Register src1, Register src2, OEBit s = LeaveOE, 1031 RCBit r = LeaveRC); 1032 1033 void subfic(Register dst, Register src, const Operand& imm); 1034 1035 void add(Register dst, Register src1, Register src2, OEBit s = LeaveOE, 1036 RCBit r = LeaveRC); 1037 1038 void addc(Register dst, Register src1, Register src2, OEBit o = LeaveOE, 1039 RCBit r = LeaveRC); 1040 void adde(Register dst, Register src1, Register src2, OEBit o = LeaveOE, 1041 RCBit r = LeaveRC); 1042 void addze(Register dst, Register src1, OEBit o = LeaveOE, RCBit r = LeaveRC); 1043 1044 void mullw(Register dst, Register src1, Register src2, OEBit o = LeaveOE, 1045 RCBit r = LeaveRC); 1046 1047 void mulhw(Register dst, Register src1, Register src2, RCBit r = LeaveRC); 1048 void mulhwu(Register dst, Register src1, Register src2, RCBit r = LeaveRC); 1049 1050 void divw(Register dst, Register src1, Register src2, OEBit o = LeaveOE, 1051 RCBit r = LeaveRC); 1052 void divwu(Register dst, Register src1, Register src2, OEBit o = LeaveOE, 1053 RCBit r = LeaveRC); 1054 1055 void addi(Register dst, Register src, const Operand& imm); 1056 void addis(Register dst, Register src, const Operand& imm); 1057 void addic(Register dst, Register src, const Operand& imm); 1058 1059 void andi(Register ra, Register rs, const Operand& imm); 1060 void andis(Register ra, Register rs, const Operand& imm); 1061 void ori(Register dst, Register src, const Operand& imm); 1062 void oris(Register dst, Register src, const Operand& imm); 1063 void xori(Register dst, Register src, const Operand& imm); 1064 void xoris(Register ra, Register rs, const Operand& imm); 1065 void cmpi(Register src1, const Operand& src2, CRegister cr = cr7); 1066 void cmpli(Register src1, const Operand& src2, CRegister cr = cr7); 1067 void cmpwi(Register src1, const Operand& src2, CRegister cr = cr7); 1068 void cmplwi(Register src1, const Operand& src2, CRegister cr = cr7); 1069 void li(Register dst, const Operand& src); 1070 void lis(Register dst, const Operand& imm); 1071 void mr(Register dst, Register src); 1072 1073 void lbz(Register dst, const MemOperand& src); 1074 void lhz(Register dst, const MemOperand& src); 1075 void lha(Register dst, const MemOperand& src); 1076 void lwz(Register dst, const MemOperand& src); 1077 void lwzu(Register dst, const MemOperand& src); 1078 void lwa(Register dst, const MemOperand& src); 1079 void stb(Register dst, const MemOperand& src); 1080 void sth(Register dst, const MemOperand& src); 1081 void stw(Register dst, const MemOperand& src); 1082 void stwu(Register dst, const MemOperand& src); 1083 void neg(Register rt, Register ra, OEBit o = LeaveOE, RCBit c = LeaveRC); 1084 1085 #if V8_TARGET_ARCH_PPC64 1086 void ld(Register rd, const MemOperand& src); 1087 void ldu(Register rd, const MemOperand& src); 1088 void std(Register rs, const MemOperand& src); 1089 void stdu(Register rs, const MemOperand& src); 1090 void rldic(Register dst, Register src, int sh, int mb, RCBit r = LeaveRC); 1091 void rldicl(Register dst, Register src, int sh, int mb, RCBit r = LeaveRC); 1092 void rldcl(Register ra, Register rs, Register rb, int mb, RCBit r = LeaveRC); 1093 void rldicr(Register dst, Register src, int sh, int me, RCBit r = LeaveRC); 1094 void rldimi(Register dst, Register src, int sh, int mb, RCBit r = LeaveRC); 1095 void sldi(Register dst, Register src, const Operand& val, RCBit rc = LeaveRC); 1096 void srdi(Register dst, Register src, const Operand& val, RCBit rc = LeaveRC); 1097 void clrrdi(Register dst, Register src, const Operand& val, 1098 RCBit rc = LeaveRC); 1099 void clrldi(Register dst, Register src, const Operand& val, 1100 RCBit rc = LeaveRC); 1101 void sradi(Register ra, Register rs, int sh, RCBit r = LeaveRC); 1102 void rotld(Register ra, Register rs, Register rb, RCBit r = LeaveRC); 1103 void rotldi(Register ra, Register rs, int sh, RCBit r = LeaveRC); 1104 void rotrdi(Register ra, Register rs, int sh, RCBit r = LeaveRC); 1105 void mulld(Register dst, Register src1, Register src2, OEBit o = LeaveOE, 1106 RCBit r = LeaveRC); 1107 void divd(Register dst, Register src1, Register src2, OEBit o = LeaveOE, 1108 RCBit r = LeaveRC); 1109 void divdu(Register dst, Register src1, Register src2, OEBit o = LeaveOE, 1110 RCBit r = LeaveRC); 1111 #endif 1112 1113 void rlwinm(Register ra, Register rs, int sh, int mb, int me, 1114 RCBit rc = LeaveRC); 1115 void rlwimi(Register ra, Register rs, int sh, int mb, int me, 1116 RCBit rc = LeaveRC); 1117 void rlwnm(Register ra, Register rs, Register rb, int mb, int me, 1118 RCBit rc = LeaveRC); 1119 void slwi(Register dst, Register src, const Operand& val, RCBit rc = LeaveRC); 1120 void srwi(Register dst, Register src, const Operand& val, RCBit rc = LeaveRC); 1121 void clrrwi(Register dst, Register src, const Operand& val, 1122 RCBit rc = LeaveRC); 1123 void clrlwi(Register dst, Register src, const Operand& val, 1124 RCBit rc = LeaveRC); 1125 void rotlw(Register ra, Register rs, Register rb, RCBit r = LeaveRC); 1126 void rotlwi(Register ra, Register rs, int sh, RCBit r = LeaveRC); 1127 void rotrwi(Register ra, Register rs, int sh, RCBit r = LeaveRC); 1128 1129 void subi(Register dst, Register src1, const Operand& src2); 1130 1131 void mov(Register dst, const Operand& src); 1132 void bitwise_mov(Register dst, intptr_t value); 1133 void bitwise_mov32(Register dst, int32_t value); 1134 void bitwise_add32(Register dst, Register src, int32_t value); 1135 1136 // Load the position of the label relative to the generated code object 1137 // pointer in a register. 1138 void mov_label_offset(Register dst, Label* label); 1139 1140 // dst = base + label position + delta 1141 void add_label_offset(Register dst, Register base, Label* label, 1142 int delta = 0); 1143 1144 // Load the address of the label in a register and associate with an 1145 // internal reference relocation. 1146 void mov_label_addr(Register dst, Label* label); 1147 1148 // Emit the address of the label (i.e. a jump table entry) and associate with 1149 // an internal reference relocation. 1150 void emit_label_addr(Label* label); 1151 1152 // Multiply instructions 1153 void mul(Register dst, Register src1, Register src2, OEBit s = LeaveOE, 1154 RCBit r = LeaveRC); 1155 1156 // Miscellaneous arithmetic instructions 1157 1158 // Special register access 1159 void crxor(int bt, int ba, int bb); 1160 void crclr(int bt) { crxor(bt, bt, bt); } 1161 void creqv(int bt, int ba, int bb); 1162 void crset(int bt) { creqv(bt, bt, bt); } 1163 void mflr(Register dst); 1164 void mtlr(Register src); 1165 void mtctr(Register src); 1166 void mtxer(Register src); 1167 void mcrfs(CRegister cr, FPSCRBit bit); 1168 void mfcr(Register dst); 1169 #if V8_TARGET_ARCH_PPC64 1170 void mffprd(Register dst, DoubleRegister src); 1171 void mffprwz(Register dst, DoubleRegister src); 1172 void mtfprd(DoubleRegister dst, Register src); 1173 void mtfprwz(DoubleRegister dst, Register src); 1174 void mtfprwa(DoubleRegister dst, Register src); 1175 #endif 1176 1177 void function_descriptor(); 1178 1179 // Exception-generating instructions and debugging support 1180 void stop(const char* msg, Condition cond = al, 1181 int32_t code = kDefaultStopCode, CRegister cr = cr7); 1182 1183 void bkpt(uint32_t imm16); // v5 and above 1184 1185 void dcbf(Register ra, Register rb); 1186 void sync(); 1187 void lwsync(); 1188 void icbi(Register ra, Register rb); 1189 void isync(); 1190 1191 // Support for floating point 1192 void lfd(const DoubleRegister frt, const MemOperand& src); 1193 void lfdu(const DoubleRegister frt, const MemOperand& src); 1194 void lfs(const DoubleRegister frt, const MemOperand& src); 1195 void lfsu(const DoubleRegister frt, const MemOperand& src); 1196 void stfd(const DoubleRegister frs, const MemOperand& src); 1197 void stfdu(const DoubleRegister frs, const MemOperand& src); 1198 void stfs(const DoubleRegister frs, const MemOperand& src); 1199 void stfsu(const DoubleRegister frs, const MemOperand& src); 1200 1201 void fadd(const DoubleRegister frt, const DoubleRegister fra, 1202 const DoubleRegister frb, RCBit rc = LeaveRC); 1203 void fsub(const DoubleRegister frt, const DoubleRegister fra, 1204 const DoubleRegister frb, RCBit rc = LeaveRC); 1205 void fdiv(const DoubleRegister frt, const DoubleRegister fra, 1206 const DoubleRegister frb, RCBit rc = LeaveRC); 1207 void fmul(const DoubleRegister frt, const DoubleRegister fra, 1208 const DoubleRegister frc, RCBit rc = LeaveRC); 1209 void fcmpu(const DoubleRegister fra, const DoubleRegister frb, 1210 CRegister cr = cr7); 1211 void fmr(const DoubleRegister frt, const DoubleRegister frb, 1212 RCBit rc = LeaveRC); 1213 void fctiwz(const DoubleRegister frt, const DoubleRegister frb); 1214 void fctiw(const DoubleRegister frt, const DoubleRegister frb); 1215 void frin(const DoubleRegister frt, const DoubleRegister frb, 1216 RCBit rc = LeaveRC); 1217 void friz(const DoubleRegister frt, const DoubleRegister frb, 1218 RCBit rc = LeaveRC); 1219 void frip(const DoubleRegister frt, const DoubleRegister frb, 1220 RCBit rc = LeaveRC); 1221 void frim(const DoubleRegister frt, const DoubleRegister frb, 1222 RCBit rc = LeaveRC); 1223 void frsp(const DoubleRegister frt, const DoubleRegister frb, 1224 RCBit rc = LeaveRC); 1225 void fcfid(const DoubleRegister frt, const DoubleRegister frb, 1226 RCBit rc = LeaveRC); 1227 void fcfidu(const DoubleRegister frt, const DoubleRegister frb, 1228 RCBit rc = LeaveRC); 1229 void fcfidus(const DoubleRegister frt, const DoubleRegister frb, 1230 RCBit rc = LeaveRC); 1231 void fcfids(const DoubleRegister frt, const DoubleRegister frb, 1232 RCBit rc = LeaveRC); 1233 void fctid(const DoubleRegister frt, const DoubleRegister frb, 1234 RCBit rc = LeaveRC); 1235 void fctidz(const DoubleRegister frt, const DoubleRegister frb, 1236 RCBit rc = LeaveRC); 1237 void fctidu(const DoubleRegister frt, const DoubleRegister frb, 1238 RCBit rc = LeaveRC); 1239 void fctiduz(const DoubleRegister frt, const DoubleRegister frb, 1240 RCBit rc = LeaveRC); 1241 void fsel(const DoubleRegister frt, const DoubleRegister fra, 1242 const DoubleRegister frc, const DoubleRegister frb, 1243 RCBit rc = LeaveRC); 1244 void fneg(const DoubleRegister frt, const DoubleRegister frb, 1245 RCBit rc = LeaveRC); 1246 void mtfsb0(FPSCRBit bit, RCBit rc = LeaveRC); 1247 void mtfsb1(FPSCRBit bit, RCBit rc = LeaveRC); 1248 void mtfsfi(int bf, int immediate, RCBit rc = LeaveRC); 1249 void mffs(const DoubleRegister frt, RCBit rc = LeaveRC); 1250 void mtfsf(const DoubleRegister frb, bool L = 1, int FLM = 0, bool W = 0, 1251 RCBit rc = LeaveRC); 1252 void fsqrt(const DoubleRegister frt, const DoubleRegister frb, 1253 RCBit rc = LeaveRC); 1254 void fabs(const DoubleRegister frt, const DoubleRegister frb, 1255 RCBit rc = LeaveRC); 1256 void fmadd(const DoubleRegister frt, const DoubleRegister fra, 1257 const DoubleRegister frc, const DoubleRegister frb, 1258 RCBit rc = LeaveRC); 1259 void fmsub(const DoubleRegister frt, const DoubleRegister fra, 1260 const DoubleRegister frc, const DoubleRegister frb, 1261 RCBit rc = LeaveRC); 1262 1263 // Pseudo instructions 1264 1265 // Different nop operations are used by the code generator to detect certain 1266 // states of the generated code. 1267 enum NopMarkerTypes { 1268 NON_MARKING_NOP = 0, 1269 GROUP_ENDING_NOP, 1270 DEBUG_BREAK_NOP, 1271 // IC markers. 1272 PROPERTY_ACCESS_INLINED, 1273 PROPERTY_ACCESS_INLINED_CONTEXT, 1274 PROPERTY_ACCESS_INLINED_CONTEXT_DONT_DELETE, 1275 // Helper values. 1276 LAST_CODE_MARKER, 1277 FIRST_IC_MARKER = PROPERTY_ACCESS_INLINED 1278 }; 1279 1280 void nop(int type = 0); // 0 is the default non-marking type. 1281 1282 void push(Register src) { 1283 #if V8_TARGET_ARCH_PPC64 1284 stdu(src, MemOperand(sp, -kPointerSize)); 1285 #else 1286 stwu(src, MemOperand(sp, -kPointerSize)); 1287 #endif 1288 } 1289 1290 void pop(Register dst) { 1291 #if V8_TARGET_ARCH_PPC64 1292 ld(dst, MemOperand(sp)); 1293 #else 1294 lwz(dst, MemOperand(sp)); 1295 #endif 1296 addi(sp, sp, Operand(kPointerSize)); 1297 } 1298 1299 void pop() { addi(sp, sp, Operand(kPointerSize)); } 1300 1301 // Jump unconditionally to given label. 1302 void jmp(Label* L) { b(L); } 1303 1304 // Check the code size generated from label to here. 1305 int SizeOfCodeGeneratedSince(Label* label) { 1306 return pc_offset() - label->pos(); 1307 } 1308 1309 // Check the number of instructions generated from label to here. 1310 int InstructionsGeneratedSince(Label* label) { 1311 return SizeOfCodeGeneratedSince(label) / kInstrSize; 1312 } 1313 1314 // Class for scoping postponing the trampoline pool generation. 1315 class BlockTrampolinePoolScope { 1316 public: 1317 explicit BlockTrampolinePoolScope(Assembler* assem) : assem_(assem) { 1318 assem_->StartBlockTrampolinePool(); 1319 } 1320 ~BlockTrampolinePoolScope() { assem_->EndBlockTrampolinePool(); } 1321 1322 private: 1323 Assembler* assem_; 1324 1325 DISALLOW_IMPLICIT_CONSTRUCTORS(BlockTrampolinePoolScope); 1326 }; 1327 1328 // Class for scoping disabling constant pool entry merging 1329 class BlockConstantPoolEntrySharingScope { 1330 public: 1331 explicit BlockConstantPoolEntrySharingScope(Assembler* assem) 1332 : assem_(assem) { 1333 assem_->StartBlockConstantPoolEntrySharing(); 1334 } 1335 ~BlockConstantPoolEntrySharingScope() { 1336 assem_->EndBlockConstantPoolEntrySharing(); 1337 } 1338 1339 private: 1340 Assembler* assem_; 1341 1342 DISALLOW_IMPLICIT_CONSTRUCTORS(BlockConstantPoolEntrySharingScope); 1343 }; 1344 1345 // Record a comment relocation entry that can be used by a disassembler. 1346 // Use --code-comments to enable. 1347 void RecordComment(const char* msg); 1348 1349 // Record a deoptimization reason that can be used by a log or cpu profiler. 1350 // Use --trace-deopt to enable. 1351 void RecordDeoptReason(DeoptimizeReason reason, SourcePosition position, 1352 int id); 1353 1354 // Writes a single byte or word of data in the code stream. Used 1355 // for inline tables, e.g., jump-tables. 1356 void db(uint8_t data); 1357 void dd(uint32_t data); 1358 void dq(uint64_t data); 1359 void dp(uintptr_t data); 1360 1361 // Read/patch instructions 1362 Instr instr_at(int pos) { return *reinterpret_cast<Instr*>(buffer_ + pos); } 1363 void instr_at_put(int pos, Instr instr) { 1364 *reinterpret_cast<Instr*>(buffer_ + pos) = instr; 1365 } 1366 static Instr instr_at(Address pc) { return *reinterpret_cast<Instr*>(pc); } 1367 static void instr_at_put(Address pc, Instr instr) { 1368 *reinterpret_cast<Instr*>(pc) = instr; 1369 } 1370 static Condition GetCondition(Instr instr); 1371 1372 static bool IsLis(Instr instr); 1373 static bool IsLi(Instr instr); 1374 static bool IsAddic(Instr instr); 1375 static bool IsOri(Instr instr); 1376 1377 static bool IsBranch(Instr instr); 1378 static Register GetRA(Instr instr); 1379 static Register GetRB(Instr instr); 1380 #if V8_TARGET_ARCH_PPC64 1381 static bool Is64BitLoadIntoR12(Instr instr1, Instr instr2, Instr instr3, 1382 Instr instr4, Instr instr5); 1383 #else 1384 static bool Is32BitLoadIntoR12(Instr instr1, Instr instr2); 1385 #endif 1386 1387 static bool IsCmpRegister(Instr instr); 1388 static bool IsCmpImmediate(Instr instr); 1389 static bool IsRlwinm(Instr instr); 1390 static bool IsAndi(Instr instr); 1391 #if V8_TARGET_ARCH_PPC64 1392 static bool IsRldicl(Instr instr); 1393 #endif 1394 static bool IsCrSet(Instr instr); 1395 static Register GetCmpImmediateRegister(Instr instr); 1396 static int GetCmpImmediateRawImmediate(Instr instr); 1397 static bool IsNop(Instr instr, int type = NON_MARKING_NOP); 1398 1399 // Postpone the generation of the trampoline pool for the specified number of 1400 // instructions. 1401 void BlockTrampolinePoolFor(int instructions); 1402 void CheckTrampolinePool(); 1403 1404 // For mov. Return the number of actual instructions required to 1405 // load the operand into a register. This can be anywhere from 1406 // one (constant pool small section) to five instructions (full 1407 // 64-bit sequence). 1408 // 1409 // The value returned is only valid as long as no entries are added to the 1410 // constant pool between this call and the actual instruction being emitted. 1411 int instructions_required_for_mov(Register dst, const Operand& src) const; 1412 1413 // Decide between using the constant pool vs. a mov immediate sequence. 1414 bool use_constant_pool_for_mov(Register dst, const Operand& src, 1415 bool canOptimize) const; 1416 1417 // The code currently calls CheckBuffer() too often. This has the side 1418 // effect of randomly growing the buffer in the middle of multi-instruction 1419 // sequences. 1420 // 1421 // This function allows outside callers to check and grow the buffer 1422 void EnsureSpaceFor(int space_needed); 1423 1424 int EmitConstantPool() { return constant_pool_builder_.Emit(this); } 1425 1426 bool ConstantPoolAccessIsInOverflow() const { 1427 return constant_pool_builder_.NextAccess(ConstantPoolEntry::INTPTR) == 1428 ConstantPoolEntry::OVERFLOWED; 1429 } 1430 1431 Label* ConstantPoolPosition() { 1432 return constant_pool_builder_.EmittedPosition(); 1433 } 1434 1435 void EmitRelocations(); 1436 1437 protected: 1438 int buffer_space() const { return reloc_info_writer.pos() - pc_; } 1439 1440 // Decode instruction(s) at pos and return backchain to previous 1441 // label reference or kEndOfChain. 1442 int target_at(int pos); 1443 1444 // Patch instruction(s) at pos to target target_pos (e.g. branch) 1445 void target_at_put(int pos, int target_pos, bool* is_branch = nullptr); 1446 1447 // Record reloc info for current pc_ 1448 void RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data = 0); 1449 ConstantPoolEntry::Access ConstantPoolAddEntry(RelocInfo::Mode rmode, 1450 intptr_t value) { 1451 bool sharing_ok = RelocInfo::IsNone(rmode) || 1452 (!options().record_reloc_info_for_serialization && 1453 RelocInfo::IsShareableRelocMode(rmode) && 1454 !is_constant_pool_entry_sharing_blocked()); 1455 return constant_pool_builder_.AddEntry(pc_offset(), value, sharing_ok); 1456 } 1457 ConstantPoolEntry::Access ConstantPoolAddEntry(Double value) { 1458 return constant_pool_builder_.AddEntry(pc_offset(), value); 1459 } 1460 1461 // Block the emission of the trampoline pool before pc_offset. 1462 void BlockTrampolinePoolBefore(int pc_offset) { 1463 if (no_trampoline_pool_before_ < pc_offset) 1464 no_trampoline_pool_before_ = pc_offset; 1465 } 1466 1467 void StartBlockTrampolinePool() { trampoline_pool_blocked_nesting_++; } 1468 void EndBlockTrampolinePool() { 1469 int count = --trampoline_pool_blocked_nesting_; 1470 if (count == 0) CheckTrampolinePoolQuick(); 1471 } 1472 bool is_trampoline_pool_blocked() const { 1473 return trampoline_pool_blocked_nesting_ > 0; 1474 } 1475 1476 void StartBlockConstantPoolEntrySharing() { 1477 constant_pool_entry_sharing_blocked_nesting_++; 1478 } 1479 void EndBlockConstantPoolEntrySharing() { 1480 constant_pool_entry_sharing_blocked_nesting_--; 1481 } 1482 bool is_constant_pool_entry_sharing_blocked() const { 1483 return constant_pool_entry_sharing_blocked_nesting_ > 0; 1484 } 1485 1486 bool has_exception() const { return internal_trampoline_exception_; } 1487 1488 bool is_trampoline_emitted() const { return trampoline_emitted_; } 1489 1490 // Code generation 1491 // The relocation writer's position is at least kGap bytes below the end of 1492 // the generated instructions. This is so that multi-instruction sequences do 1493 // not have to check for overflow. The same is true for writes of large 1494 // relocation info entries. 1495 static constexpr int kGap = 32; 1496 1497 RelocInfoWriter reloc_info_writer; 1498 1499 private: 1500 // Avoid overflows for displacements etc. 1501 static const int kMaximalBufferSize = 512 * MB; 1502 1503 // Repeated checking whether the trampoline pool should be emitted is rather 1504 // expensive. By default we only check again once a number of instructions 1505 // has been generated. 1506 int next_trampoline_check_; // pc offset of next buffer check. 1507 1508 // Emission of the trampoline pool may be blocked in some code sequences. 1509 int trampoline_pool_blocked_nesting_; // Block emission if this is not zero. 1510 int no_trampoline_pool_before_; // Block emission before this pc offset. 1511 1512 // Do not share constant pool entries. 1513 int constant_pool_entry_sharing_blocked_nesting_; 1514 1515 // Relocation info generation 1516 // Each relocation is encoded as a variable size value 1517 static constexpr int kMaxRelocSize = RelocInfoWriter::kMaxSize; 1518 std::vector<DeferredRelocInfo> relocations_; 1519 1520 // The bound position, before this we cannot do instruction elimination. 1521 int last_bound_pos_; 1522 // Optimizable cmpi information. 1523 int optimizable_cmpi_pos_; 1524 CRegister cmpi_cr_ = CRegister::no_reg(); 1525 1526 ConstantPoolBuilder constant_pool_builder_; 1527 1528 void CheckBuffer() { 1529 if (buffer_space() <= kGap) { 1530 GrowBuffer(); 1531 } 1532 } 1533 1534 void GrowBuffer(int needed = 0); 1535 // Code emission 1536 void emit(Instr x) { 1537 CheckBuffer(); 1538 *reinterpret_cast<Instr*>(pc_) = x; 1539 pc_ += kInstrSize; 1540 CheckTrampolinePoolQuick(); 1541 } 1542 void TrackBranch() { 1543 DCHECK(!trampoline_emitted_); 1544 int count = tracked_branch_count_++; 1545 if (count == 0) { 1546 // We leave space (kMaxBlockTrampolineSectionSize) 1547 // for BlockTrampolinePoolScope buffer. 1548 next_trampoline_check_ = 1549 pc_offset() + kMaxCondBranchReach - kMaxBlockTrampolineSectionSize; 1550 } else { 1551 next_trampoline_check_ -= kTrampolineSlotsSize; 1552 } 1553 } 1554 1555 inline void UntrackBranch(); 1556 void CheckTrampolinePoolQuick() { 1557 if (pc_offset() >= next_trampoline_check_) { 1558 CheckTrampolinePool(); 1559 } 1560 } 1561 1562 // Instruction generation 1563 void a_form(Instr instr, DoubleRegister frt, DoubleRegister fra, 1564 DoubleRegister frb, RCBit r); 1565 void d_form(Instr instr, Register rt, Register ra, const intptr_t val, 1566 bool signed_disp); 1567 void xo_form(Instr instr, Register rt, Register ra, Register rb, OEBit o, 1568 RCBit r); 1569 void md_form(Instr instr, Register ra, Register rs, int shift, int maskbit, 1570 RCBit r); 1571 void mds_form(Instr instr, Register ra, Register rs, Register rb, int maskbit, 1572 RCBit r); 1573 1574 // Labels 1575 void print(Label* L); 1576 int max_reach_from(int pos); 1577 void bind_to(Label* L, int pos); 1578 void next(Label* L); 1579 1580 class Trampoline { 1581 public: 1582 Trampoline() { 1583 next_slot_ = 0; 1584 free_slot_count_ = 0; 1585 } 1586 Trampoline(int start, int slot_count) { 1587 next_slot_ = start; 1588 free_slot_count_ = slot_count; 1589 } 1590 int take_slot() { 1591 int trampoline_slot = kInvalidSlotPos; 1592 if (free_slot_count_ <= 0) { 1593 // We have run out of space on trampolines. 1594 // Make sure we fail in debug mode, so we become aware of each case 1595 // when this happens. 1596 DCHECK(0); 1597 // Internal exception will be caught. 1598 } else { 1599 trampoline_slot = next_slot_; 1600 free_slot_count_--; 1601 next_slot_ += kTrampolineSlotsSize; 1602 } 1603 return trampoline_slot; 1604 } 1605 1606 private: 1607 int next_slot_; 1608 int free_slot_count_; 1609 }; 1610 1611 int32_t get_trampoline_entry(); 1612 int tracked_branch_count_; 1613 // If trampoline is emitted, generated code is becoming large. As 1614 // this is already a slow case which can possibly break our code 1615 // generation for the extreme case, we use this information to 1616 // trigger different mode of branch instruction generation, where we 1617 // no longer use a single branch instruction. 1618 bool trampoline_emitted_; 1619 static constexpr int kTrampolineSlotsSize = kInstrSize; 1620 static constexpr int kMaxCondBranchReach = (1 << (16 - 1)) - 1; 1621 static constexpr int kMaxBlockTrampolineSectionSize = 64 * kInstrSize; 1622 static constexpr int kInvalidSlotPos = -1; 1623 1624 Trampoline trampoline_; 1625 bool internal_trampoline_exception_; 1626 1627 void AllocateAndInstallRequestedHeapObjects(Isolate* isolate); 1628 1629 friend class RegExpMacroAssemblerPPC; 1630 friend class RelocInfo; 1631 friend class BlockTrampolinePoolScope; 1632 friend class EnsureSpace; 1633 }; 1634 1635 1636 class EnsureSpace BASE_EMBEDDED { 1637 public: 1638 explicit EnsureSpace(Assembler* assembler) { assembler->CheckBuffer(); } 1639 }; 1640 1641 class PatchingAssembler : public Assembler { 1642 public: 1643 PatchingAssembler(const AssemblerOptions& options, byte* address, 1644 int instructions); 1645 ~PatchingAssembler(); 1646 }; 1647 1648 } // namespace internal 1649 } // namespace v8 1650 1651 #endif // V8_PPC_ASSEMBLER_PPC_H_ 1652