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/ppc/constants-ppc.h" 48 49 #if V8_HOST_ARCH_PPC && \ 50 (V8_OS_AIX || (V8_TARGET_ARCH_PPC64 && V8_TARGET_BIG_ENDIAN)) 51 #define ABI_USES_FUNCTION_DESCRIPTORS 1 52 #else 53 #define ABI_USES_FUNCTION_DESCRIPTORS 0 54 #endif 55 56 #if !V8_HOST_ARCH_PPC || V8_OS_AIX || V8_TARGET_ARCH_PPC64 57 #define ABI_PASSES_HANDLES_IN_REGS 1 58 #else 59 #define ABI_PASSES_HANDLES_IN_REGS 0 60 #endif 61 62 #if !V8_HOST_ARCH_PPC || !V8_TARGET_ARCH_PPC64 || V8_TARGET_LITTLE_ENDIAN 63 #define ABI_RETURNS_OBJECT_PAIRS_IN_REGS 1 64 #else 65 #define ABI_RETURNS_OBJECT_PAIRS_IN_REGS 0 66 #endif 67 68 #if !V8_HOST_ARCH_PPC || (V8_TARGET_ARCH_PPC64 && V8_TARGET_LITTLE_ENDIAN) 69 #define ABI_CALL_VIA_IP 1 70 #else 71 #define ABI_CALL_VIA_IP 0 72 #endif 73 74 #if !V8_HOST_ARCH_PPC || V8_OS_AIX || V8_TARGET_ARCH_PPC64 75 #define ABI_TOC_REGISTER 2 76 #else 77 #define ABI_TOC_REGISTER 13 78 #endif 79 80 #define INSTR_AND_DATA_CACHE_COHERENCY LWSYNC 81 82 namespace v8 { 83 namespace internal { 84 85 // clang-format off 86 #define GENERAL_REGISTERS(V) \ 87 V(r0) V(sp) V(r2) V(r3) V(r4) V(r5) V(r6) V(r7) \ 88 V(r8) V(r9) V(r10) V(r11) V(ip) V(r13) V(r14) V(r15) \ 89 V(r16) V(r17) V(r18) V(r19) V(r20) V(r21) V(r22) V(r23) \ 90 V(r24) V(r25) V(r26) V(r27) V(r28) V(r29) V(r30) V(fp) 91 92 #if V8_EMBEDDED_CONSTANT_POOL 93 #define ALLOCATABLE_GENERAL_REGISTERS(V) \ 94 V(r3) V(r4) V(r5) V(r6) V(r7) \ 95 V(r8) V(r9) V(r10) V(r14) V(r15) \ 96 V(r16) V(r17) V(r18) V(r19) V(r20) V(r21) V(r22) V(r23) \ 97 V(r24) V(r25) V(r26) V(r27) V(r30) 98 #else 99 #define ALLOCATABLE_GENERAL_REGISTERS(V) \ 100 V(r3) V(r4) V(r5) V(r6) V(r7) \ 101 V(r8) V(r9) V(r10) V(r14) V(r15) \ 102 V(r16) V(r17) V(r18) V(r19) V(r20) V(r21) V(r22) V(r23) \ 103 V(r24) V(r25) V(r26) V(r27) V(r28) V(r30) 104 #endif 105 106 #define DOUBLE_REGISTERS(V) \ 107 V(d0) V(d1) V(d2) V(d3) V(d4) V(d5) V(d6) V(d7) \ 108 V(d8) V(d9) V(d10) V(d11) V(d12) V(d13) V(d14) V(d15) \ 109 V(d16) V(d17) V(d18) V(d19) V(d20) V(d21) V(d22) V(d23) \ 110 V(d24) V(d25) V(d26) V(d27) V(d28) V(d29) V(d30) V(d31) 111 112 #define FLOAT_REGISTERS DOUBLE_REGISTERS 113 114 #define ALLOCATABLE_DOUBLE_REGISTERS(V) \ 115 V(d1) V(d2) V(d3) V(d4) V(d5) V(d6) V(d7) \ 116 V(d8) V(d9) V(d10) V(d11) V(d12) V(d15) \ 117 V(d16) V(d17) V(d18) V(d19) V(d20) V(d21) V(d22) V(d23) \ 118 V(d24) V(d25) V(d26) V(d27) V(d28) V(d29) V(d30) V(d31) 119 // clang-format on 120 121 // CPU Registers. 122 // 123 // 1) We would prefer to use an enum, but enum values are assignment- 124 // compatible with int, which has caused code-generation bugs. 125 // 126 // 2) We would prefer to use a class instead of a struct but we don't like 127 // the register initialization to depend on the particular initialization 128 // order (which appears to be different on OS X, Linux, and Windows for the 129 // installed versions of C++ we tried). Using a struct permits C-style 130 // "initialization". Also, the Register objects cannot be const as this 131 // forces initialization stubs in MSVC, making us dependent on initialization 132 // order. 133 // 134 // 3) By not using an enum, we are possibly preventing the compiler from 135 // doing certain constant folds, which may significantly reduce the 136 // code generated for some assembly instructions (because they boil down 137 // to a few constants). If this is a problem, we could change the code 138 // such that we use an enum in optimized mode, and the struct in debug 139 // mode. This way we get the compile-time error checking in debug mode 140 // and best performance in optimized code. 141 142 struct Register { 143 enum Code { 144 #define REGISTER_CODE(R) kCode_##R, 145 GENERAL_REGISTERS(REGISTER_CODE) 146 #undef REGISTER_CODE 147 kAfterLast, 148 kCode_no_reg = -1 149 }; 150 151 static const int kNumRegisters = Code::kAfterLast; 152 153 #define REGISTER_COUNT(R) 1 + 154 static const int kNumAllocatable = 155 ALLOCATABLE_GENERAL_REGISTERS(REGISTER_COUNT)0; 156 #undef REGISTER_COUNT 157 158 #define REGISTER_BIT(R) 1 << kCode_##R | 159 static const RegList kAllocatable = 160 ALLOCATABLE_GENERAL_REGISTERS(REGISTER_BIT)0; 161 #undef REGISTER_BIT 162 from_codeRegister163 static Register from_code(int code) { 164 DCHECK(code >= 0); 165 DCHECK(code < kNumRegisters); 166 Register r = {code}; 167 return r; 168 } is_validRegister169 bool is_valid() const { return 0 <= reg_code && reg_code < kNumRegisters; } isRegister170 bool is(Register reg) const { return reg_code == reg.reg_code; } codeRegister171 int code() const { 172 DCHECK(is_valid()); 173 return reg_code; 174 } bitRegister175 int bit() const { 176 DCHECK(is_valid()); 177 return 1 << reg_code; 178 } set_codeRegister179 void set_code(int code) { 180 reg_code = code; 181 DCHECK(is_valid()); 182 } 183 184 #if V8_TARGET_LITTLE_ENDIAN 185 static const int kMantissaOffset = 0; 186 static const int kExponentOffset = 4; 187 #else 188 static const int kMantissaOffset = 4; 189 static const int kExponentOffset = 0; 190 #endif 191 192 // Unfortunately we can't make this private in a struct. 193 int reg_code; 194 }; 195 196 #define DECLARE_REGISTER(R) const Register R = {Register::kCode_##R}; 197 GENERAL_REGISTERS(DECLARE_REGISTER) 198 #undef DECLARE_REGISTER 199 const Register no_reg = {Register::kCode_no_reg}; 200 201 // Aliases 202 const Register kLithiumScratch = r11; // lithium scratch. 203 const Register kConstantPoolRegister = r28; // Constant pool. 204 const Register kRootRegister = r29; // Roots array pointer. 205 const Register cp = r30; // JavaScript context pointer. 206 207 static const bool kSimpleFPAliasing = true; 208 209 // Double word FP register. 210 struct DoubleRegister { 211 enum Code { 212 #define REGISTER_CODE(R) kCode_##R, 213 DOUBLE_REGISTERS(REGISTER_CODE) 214 #undef REGISTER_CODE 215 kAfterLast, 216 kCode_no_reg = -1 217 }; 218 219 static const int kNumRegisters = Code::kAfterLast; 220 static const int kMaxNumRegisters = kNumRegisters; 221 is_validDoubleRegister222 bool is_valid() const { return 0 <= reg_code && reg_code < kNumRegisters; } isDoubleRegister223 bool is(DoubleRegister reg) const { return reg_code == reg.reg_code; } codeDoubleRegister224 int code() const { 225 DCHECK(is_valid()); 226 return reg_code; 227 } bitDoubleRegister228 int bit() const { 229 DCHECK(is_valid()); 230 return 1 << reg_code; 231 } 232 from_codeDoubleRegister233 static DoubleRegister from_code(int code) { 234 DoubleRegister r = {code}; 235 return r; 236 } 237 238 int reg_code; 239 }; 240 241 typedef DoubleRegister FloatRegister; 242 243 // TODO(ppc) Define SIMD registers. 244 typedef DoubleRegister Simd128Register; 245 246 #define DECLARE_REGISTER(R) \ 247 const DoubleRegister R = {DoubleRegister::kCode_##R}; 248 DOUBLE_REGISTERS(DECLARE_REGISTER) 249 #undef DECLARE_REGISTER 250 const Register no_dreg = {Register::kCode_no_reg}; 251 252 // Aliases for double registers. Defined using #define instead of 253 // "static const DoubleRegister&" because Clang complains otherwise when a 254 // compilation unit that includes this header doesn't use the variables. 255 #define kFirstCalleeSavedDoubleReg d14 256 #define kLastCalleeSavedDoubleReg d31 257 #define kDoubleRegZero d14 258 #define kScratchDoubleReg d13 259 260 Register ToRegister(int num); 261 262 // Coprocessor register 263 struct CRegister { is_validCRegister264 bool is_valid() const { return 0 <= reg_code && reg_code < 8; } isCRegister265 bool is(CRegister creg) const { return reg_code == creg.reg_code; } codeCRegister266 int code() const { 267 DCHECK(is_valid()); 268 return reg_code; 269 } bitCRegister270 int bit() const { 271 DCHECK(is_valid()); 272 return 1 << reg_code; 273 } 274 275 // Unfortunately we can't make this private in a struct. 276 int reg_code; 277 }; 278 279 280 const CRegister no_creg = {-1}; 281 282 const CRegister cr0 = {0}; 283 const CRegister cr1 = {1}; 284 const CRegister cr2 = {2}; 285 const CRegister cr3 = {3}; 286 const CRegister cr4 = {4}; 287 const CRegister cr5 = {5}; 288 const CRegister cr6 = {6}; 289 const CRegister cr7 = {7}; 290 291 // ----------------------------------------------------------------------------- 292 // Machine instruction Operands 293 294 #if V8_TARGET_ARCH_PPC64 295 const RelocInfo::Mode kRelocInfo_NONEPTR = RelocInfo::NONE64; 296 #else 297 const RelocInfo::Mode kRelocInfo_NONEPTR = RelocInfo::NONE32; 298 #endif 299 300 // Class Operand represents a shifter operand in data processing instructions 301 class Operand BASE_EMBEDDED { 302 public: 303 // immediate 304 INLINE(explicit Operand(intptr_t immediate, 305 RelocInfo::Mode rmode = kRelocInfo_NONEPTR)); INLINE(static Operand Zero ())306 INLINE(static Operand Zero()) { return Operand(static_cast<intptr_t>(0)); } 307 INLINE(explicit Operand(const ExternalReference& f)); 308 explicit Operand(Handle<Object> handle); 309 INLINE(explicit Operand(Smi* value)); 310 311 // rm 312 INLINE(explicit Operand(Register rm)); 313 314 // Return true if this is a register operand. 315 INLINE(bool is_reg() const); 316 317 bool must_output_reloc_info(const Assembler* assembler) const; 318 immediate()319 inline intptr_t immediate() const { 320 DCHECK(!rm_.is_valid()); 321 return imm_; 322 } 323 rm()324 Register rm() const { return rm_; } 325 326 private: 327 Register rm_; 328 intptr_t imm_; // valid if rm_ == no_reg 329 RelocInfo::Mode rmode_; 330 331 friend class Assembler; 332 friend class MacroAssembler; 333 }; 334 335 336 // Class MemOperand represents a memory operand in load and store instructions 337 // On PowerPC we have base register + 16bit signed value 338 // Alternatively we can have a 16bit signed value immediate 339 class MemOperand BASE_EMBEDDED { 340 public: 341 explicit MemOperand(Register rn, int32_t offset = 0); 342 343 explicit MemOperand(Register ra, Register rb); 344 offset()345 int32_t offset() const { 346 DCHECK(rb_.is(no_reg)); 347 return offset_; 348 } 349 350 // PowerPC - base register ra()351 Register ra() const { 352 DCHECK(!ra_.is(no_reg)); 353 return ra_; 354 } 355 rb()356 Register rb() const { 357 DCHECK(offset_ == 0 && !rb_.is(no_reg)); 358 return rb_; 359 } 360 361 private: 362 Register ra_; // base 363 int32_t offset_; // offset 364 Register rb_; // index 365 366 friend class Assembler; 367 }; 368 369 370 class DeferredRelocInfo { 371 public: DeferredRelocInfo()372 DeferredRelocInfo() {} DeferredRelocInfo(int position,RelocInfo::Mode rmode,intptr_t data)373 DeferredRelocInfo(int position, RelocInfo::Mode rmode, intptr_t data) 374 : position_(position), rmode_(rmode), data_(data) {} 375 position()376 int position() const { return position_; } rmode()377 RelocInfo::Mode rmode() const { return rmode_; } data()378 intptr_t data() const { return data_; } 379 380 private: 381 int position_; 382 RelocInfo::Mode rmode_; 383 intptr_t data_; 384 }; 385 386 387 class Assembler : public AssemblerBase { 388 public: 389 // Create an assembler. Instructions and relocation information are emitted 390 // into a buffer, with the instructions starting from the beginning and the 391 // relocation information starting from the end of the buffer. See CodeDesc 392 // for a detailed comment on the layout (globals.h). 393 // 394 // If the provided buffer is NULL, the assembler allocates and grows its own 395 // buffer, and buffer_size determines the initial buffer size. The buffer is 396 // owned by the assembler and deallocated upon destruction of the assembler. 397 // 398 // If the provided buffer is not NULL, the assembler uses the provided buffer 399 // for code generation and assumes its size to be buffer_size. If the buffer 400 // is too small, a fatal error occurs. No deallocation of the buffer is done 401 // upon destruction of the assembler. 402 Assembler(Isolate* isolate, void* buffer, int buffer_size); ~Assembler()403 virtual ~Assembler() {} 404 405 // GetCode emits any pending (non-emitted) code and fills the descriptor 406 // desc. GetCode() is idempotent; it returns the same result if no other 407 // Assembler functions are invoked in between GetCode() calls. 408 void GetCode(CodeDesc* desc); 409 410 // Label operations & relative jumps (PPUM Appendix D) 411 // 412 // Takes a branch opcode (cc) and a label (L) and generates 413 // either a backward branch or a forward branch and links it 414 // to the label fixup chain. Usage: 415 // 416 // Label L; // unbound label 417 // j(cc, &L); // forward branch to unbound label 418 // bind(&L); // bind label to the current pc 419 // j(cc, &L); // backward branch to bound label 420 // bind(&L); // illegal: a label may be bound only once 421 // 422 // Note: The same Label can be used for forward and backward branches 423 // but it may be bound only once. 424 425 void bind(Label* L); // binds an unbound label L to the current code position 426 427 // Links a label at the current pc_offset(). If already bound, returns the 428 // bound position. If already linked, returns the position of the prior link. 429 // Otherwise, returns the current pc_offset(). 430 int link(Label* L); 431 432 // Determines if Label is bound and near enough so that a single 433 // branch instruction can be used to reach it. 434 bool is_near(Label* L, Condition cond); 435 436 // Returns the branch offset to the given label from the current code position 437 // Links the label to the current position if it is still unbound branch_offset(Label * L)438 int branch_offset(Label* L) { 439 if (L->is_unused() && !trampoline_emitted_) { 440 TrackBranch(); 441 } 442 return link(L) - pc_offset(); 443 } 444 445 // Puts a labels target address at the given position. 446 // The high 8 bits are set to zero. 447 void label_at_put(Label* L, int at_offset); 448 449 INLINE(static bool IsConstantPoolLoadStart( 450 Address pc, ConstantPoolEntry::Access* access = nullptr)); 451 INLINE(static bool IsConstantPoolLoadEnd( 452 Address pc, ConstantPoolEntry::Access* access = nullptr)); 453 INLINE(static int GetConstantPoolOffset(Address pc, 454 ConstantPoolEntry::Access access, 455 ConstantPoolEntry::Type type)); 456 INLINE(void PatchConstantPoolAccessInstruction( 457 int pc_offset, int offset, ConstantPoolEntry::Access access, 458 ConstantPoolEntry::Type type)); 459 460 // Return the address in the constant pool of the code target address used by 461 // the branch/call instruction at pc, or the object in a mov. 462 INLINE(static Address target_constant_pool_address_at( 463 Address pc, Address constant_pool, ConstantPoolEntry::Access access, 464 ConstantPoolEntry::Type type)); 465 466 // Read/Modify the code target address in the branch/call instruction at pc. 467 INLINE(static Address target_address_at(Address pc, Address constant_pool)); 468 INLINE(static void set_target_address_at( 469 Isolate* isolate, Address pc, Address constant_pool, Address target, 470 ICacheFlushMode icache_flush_mode = FLUSH_ICACHE_IF_NEEDED)); INLINE(static Address target_address_at (Address pc,Code * code))471 INLINE(static Address target_address_at(Address pc, Code* code)) { 472 Address constant_pool = code ? code->constant_pool() : NULL; 473 return target_address_at(pc, constant_pool); 474 } INLINE(static void set_target_address_at (Isolate * isolate,Address pc,Code * code,Address target,ICacheFlushMode icache_flush_mode=FLUSH_ICACHE_IF_NEEDED))475 INLINE(static void set_target_address_at( 476 Isolate* isolate, Address pc, Code* code, Address target, 477 ICacheFlushMode icache_flush_mode = FLUSH_ICACHE_IF_NEEDED)) { 478 Address constant_pool = code ? code->constant_pool() : NULL; 479 set_target_address_at(isolate, pc, constant_pool, target, 480 icache_flush_mode); 481 } 482 483 // Return the code target address at a call site from the return address 484 // of that call in the instruction stream. 485 inline static Address target_address_from_return_address(Address pc); 486 487 // Given the address of the beginning of a call, return the address 488 // in the instruction stream that the call will return to. 489 INLINE(static Address return_address_from_call_start(Address pc)); 490 491 // This sets the branch destination. 492 // This is for calls and branches within generated code. 493 inline static void deserialization_set_special_target_at( 494 Isolate* isolate, Address instruction_payload, Code* code, 495 Address target); 496 497 // This sets the internal reference at the pc. 498 inline static void deserialization_set_target_internal_reference_at( 499 Isolate* isolate, Address pc, Address target, 500 RelocInfo::Mode mode = RelocInfo::INTERNAL_REFERENCE); 501 502 // Size of an instruction. 503 static const int kInstrSize = sizeof(Instr); 504 505 // Here we are patching the address in the LUI/ORI instruction pair. 506 // These values are used in the serialization process and must be zero for 507 // PPC platform, as Code, Embedded Object or External-reference pointers 508 // are split across two consecutive instructions and don't exist separately 509 // in the code, so the serializer should not step forwards in memory after 510 // a target is resolved and written. 511 static const int kSpecialTargetSize = 0; 512 513 // Number of instructions to load an address via a mov sequence. 514 #if V8_TARGET_ARCH_PPC64 515 static const int kMovInstructionsConstantPool = 1; 516 static const int kMovInstructionsNoConstantPool = 5; 517 #if defined(V8_PPC_TAGGING_OPT) 518 static const int kTaggedLoadInstructions = 1; 519 #else 520 static const int kTaggedLoadInstructions = 2; 521 #endif 522 #else 523 static const int kMovInstructionsConstantPool = 1; 524 static const int kMovInstructionsNoConstantPool = 2; 525 static const int kTaggedLoadInstructions = 1; 526 #endif 527 static const int kMovInstructions = FLAG_enable_embedded_constant_pool 528 ? kMovInstructionsConstantPool 529 : kMovInstructionsNoConstantPool; 530 531 // Distance between the instruction referring to the address of the call 532 // target and the return address. 533 534 // Call sequence is a FIXED_SEQUENCE: 535 // mov r8, @ call address 536 // mtlr r8 537 // blrl 538 // @ return address 539 static const int kCallTargetAddressOffset = 540 (kMovInstructions + 2) * kInstrSize; 541 542 // Distance between start of patched debug break slot and the emitted address 543 // to jump to. 544 // Patched debug break slot code is a FIXED_SEQUENCE: 545 // mov r0, <address> 546 // mtlr r0 547 // blrl 548 static const int kPatchDebugBreakSlotAddressOffset = 0 * kInstrSize; 549 550 // This is the length of the code sequence from SetDebugBreakAtSlot() 551 // FIXED_SEQUENCE 552 static const int kDebugBreakSlotInstructions = 553 kMovInstructionsNoConstantPool + 2; 554 static const int kDebugBreakSlotLength = 555 kDebugBreakSlotInstructions * kInstrSize; 556 encode_crbit(const CRegister & cr,enum CRBit crbit)557 static inline int encode_crbit(const CRegister& cr, enum CRBit crbit) { 558 return ((cr.code() * CRWIDTH) + crbit); 559 } 560 561 // --------------------------------------------------------------------------- 562 // Code generation 563 564 // Insert the smallest number of nop instructions 565 // possible to align the pc offset to a multiple 566 // of m. m must be a power of 2 (>= 4). 567 void Align(int m); 568 // Insert the smallest number of zero bytes possible to align the pc offset 569 // to a mulitple of m. m must be a power of 2 (>= 2). 570 void DataAlign(int m); 571 // Aligns code to something that's optimal for a jump target for the platform. 572 void CodeTargetAlign(); 573 574 // Branch instructions 575 void bclr(BOfield bo, int condition_bit, LKBit lk); 576 void blr(); 577 void bc(int branch_offset, BOfield bo, int condition_bit, LKBit lk = LeaveLK); 578 void b(int branch_offset, LKBit lk); 579 580 void bcctr(BOfield bo, int condition_bit, LKBit lk); 581 void bctr(); 582 void bctrl(); 583 584 // Convenience branch instructions using labels 585 void b(Label* L, LKBit lk = LeaveLK) { b(branch_offset(L), lk); } 586 cmpi_optimization(CRegister cr)587 inline CRegister cmpi_optimization(CRegister cr) { 588 // Check whether the branch is preceeded by an optimizable cmpi against 0. 589 // The cmpi can be deleted if it is also preceeded by an instruction that 590 // sets the register used by the compare and supports a dot form. 591 unsigned int sradi_mask = kOpcodeMask | kExt2OpcodeVariant2Mask; 592 unsigned int srawi_mask = kOpcodeMask | kExt2OpcodeMask; 593 int pos = pc_offset(); 594 int cmpi_pos = pc_offset() - kInstrSize; 595 596 if (cmpi_pos > 0 && optimizable_cmpi_pos_ == cmpi_pos && 597 cmpi_cr_.code() == cr.code() && last_bound_pos_ != pos) { 598 int xpos = cmpi_pos - kInstrSize; 599 int xinstr = instr_at(xpos); 600 int cmpi_ra = (instr_at(cmpi_pos) & 0x1f0000) >> 16; 601 // ra is at the same bit position for the three cases below. 602 int ra = (xinstr & 0x1f0000) >> 16; 603 if (cmpi_ra == ra) { 604 if ((xinstr & sradi_mask) == (EXT2 | SRADIX)) { 605 cr = cr0; 606 instr_at_put(xpos, xinstr | SetRC); 607 pc_ -= kInstrSize; 608 } else if ((xinstr & srawi_mask) == (EXT2 | SRAWIX)) { 609 cr = cr0; 610 instr_at_put(xpos, xinstr | SetRC); 611 pc_ -= kInstrSize; 612 } else if ((xinstr & kOpcodeMask) == ANDIx) { 613 cr = cr0; 614 pc_ -= kInstrSize; 615 // nothing to do here since andi. records. 616 } 617 // didn't match one of the above, must keep cmpwi. 618 } 619 } 620 return cr; 621 } 622 623 void bc_short(Condition cond, Label* L, CRegister cr = cr7, 624 LKBit lk = LeaveLK) { 625 DCHECK(cond != al); 626 DCHECK(cr.code() >= 0 && cr.code() <= 7); 627 628 cr = cmpi_optimization(cr); 629 630 int b_offset = branch_offset(L); 631 632 switch (cond) { 633 case eq: 634 bc(b_offset, BT, encode_crbit(cr, CR_EQ), lk); 635 break; 636 case ne: 637 bc(b_offset, BF, encode_crbit(cr, CR_EQ), lk); 638 break; 639 case gt: 640 bc(b_offset, BT, encode_crbit(cr, CR_GT), lk); 641 break; 642 case le: 643 bc(b_offset, BF, encode_crbit(cr, CR_GT), lk); 644 break; 645 case lt: 646 bc(b_offset, BT, encode_crbit(cr, CR_LT), lk); 647 break; 648 case ge: 649 bc(b_offset, BF, encode_crbit(cr, CR_LT), lk); 650 break; 651 case unordered: 652 bc(b_offset, BT, encode_crbit(cr, CR_FU), lk); 653 break; 654 case ordered: 655 bc(b_offset, BF, encode_crbit(cr, CR_FU), lk); 656 break; 657 case overflow: 658 bc(b_offset, BT, encode_crbit(cr, CR_SO), lk); 659 break; 660 case nooverflow: 661 bc(b_offset, BF, encode_crbit(cr, CR_SO), lk); 662 break; 663 default: 664 UNIMPLEMENTED(); 665 } 666 } 667 668 void bclr(Condition cond, CRegister cr = cr7, LKBit lk = LeaveLK) { 669 DCHECK(cond != al); 670 DCHECK(cr.code() >= 0 && cr.code() <= 7); 671 672 cr = cmpi_optimization(cr); 673 674 switch (cond) { 675 case eq: 676 bclr(BT, encode_crbit(cr, CR_EQ), lk); 677 break; 678 case ne: 679 bclr(BF, encode_crbit(cr, CR_EQ), lk); 680 break; 681 case gt: 682 bclr(BT, encode_crbit(cr, CR_GT), lk); 683 break; 684 case le: 685 bclr(BF, encode_crbit(cr, CR_GT), lk); 686 break; 687 case lt: 688 bclr(BT, encode_crbit(cr, CR_LT), lk); 689 break; 690 case ge: 691 bclr(BF, encode_crbit(cr, CR_LT), lk); 692 break; 693 case unordered: 694 bclr(BT, encode_crbit(cr, CR_FU), lk); 695 break; 696 case ordered: 697 bclr(BF, encode_crbit(cr, CR_FU), lk); 698 break; 699 case overflow: 700 bclr(BT, encode_crbit(cr, CR_SO), lk); 701 break; 702 case nooverflow: 703 bclr(BF, encode_crbit(cr, CR_SO), lk); 704 break; 705 default: 706 UNIMPLEMENTED(); 707 } 708 } 709 710 void isel(Register rt, Register ra, Register rb, int cb); 711 void isel(Condition cond, Register rt, Register ra, Register rb, 712 CRegister cr = cr7) { 713 DCHECK(cond != al); 714 DCHECK(cr.code() >= 0 && cr.code() <= 7); 715 716 cr = cmpi_optimization(cr); 717 718 switch (cond) { 719 case eq: 720 isel(rt, ra, rb, encode_crbit(cr, CR_EQ)); 721 break; 722 case ne: 723 isel(rt, rb, ra, encode_crbit(cr, CR_EQ)); 724 break; 725 case gt: 726 isel(rt, ra, rb, encode_crbit(cr, CR_GT)); 727 break; 728 case le: 729 isel(rt, rb, ra, encode_crbit(cr, CR_GT)); 730 break; 731 case lt: 732 isel(rt, ra, rb, encode_crbit(cr, CR_LT)); 733 break; 734 case ge: 735 isel(rt, rb, ra, encode_crbit(cr, CR_LT)); 736 break; 737 case unordered: 738 isel(rt, ra, rb, encode_crbit(cr, CR_FU)); 739 break; 740 case ordered: 741 isel(rt, rb, ra, encode_crbit(cr, CR_FU)); 742 break; 743 case overflow: 744 isel(rt, ra, rb, encode_crbit(cr, CR_SO)); 745 break; 746 case nooverflow: 747 isel(rt, rb, ra, encode_crbit(cr, CR_SO)); 748 break; 749 default: 750 UNIMPLEMENTED(); 751 } 752 } 753 754 void b(Condition cond, Label* L, CRegister cr = cr7, LKBit lk = LeaveLK) { 755 if (cond == al) { 756 b(L, lk); 757 return; 758 } 759 760 if ((L->is_bound() && is_near(L, cond)) || !is_trampoline_emitted()) { 761 bc_short(cond, L, cr, lk); 762 return; 763 } 764 765 Label skip; 766 Condition neg_cond = NegateCondition(cond); 767 bc_short(neg_cond, &skip, cr); 768 b(L, lk); 769 bind(&skip); 770 } 771 772 void bne(Label* L, CRegister cr = cr7, LKBit lk = LeaveLK) { 773 b(ne, L, cr, lk); 774 } 775 void beq(Label* L, CRegister cr = cr7, LKBit lk = LeaveLK) { 776 b(eq, L, cr, lk); 777 } 778 void blt(Label* L, CRegister cr = cr7, LKBit lk = LeaveLK) { 779 b(lt, L, cr, lk); 780 } 781 void bge(Label* L, CRegister cr = cr7, LKBit lk = LeaveLK) { 782 b(ge, L, cr, lk); 783 } 784 void ble(Label* L, CRegister cr = cr7, LKBit lk = LeaveLK) { 785 b(le, L, cr, lk); 786 } 787 void bgt(Label* L, CRegister cr = cr7, LKBit lk = LeaveLK) { 788 b(gt, L, cr, lk); 789 } 790 void bunordered(Label* L, CRegister cr = cr7, LKBit lk = LeaveLK) { 791 b(unordered, L, cr, lk); 792 } 793 void bordered(Label* L, CRegister cr = cr7, LKBit lk = LeaveLK) { 794 b(ordered, L, cr, lk); 795 } 796 void boverflow(Label* L, CRegister cr = cr0, LKBit lk = LeaveLK) { 797 b(overflow, L, cr, lk); 798 } 799 void bnooverflow(Label* L, CRegister cr = cr0, LKBit lk = LeaveLK) { 800 b(nooverflow, L, cr, lk); 801 } 802 803 // Decrement CTR; branch if CTR != 0 804 void bdnz(Label* L, LKBit lk = LeaveLK) { 805 bc(branch_offset(L), DCBNZ, 0, lk); 806 } 807 808 // Data-processing instructions 809 810 void sub(Register dst, Register src1, Register src2, OEBit s = LeaveOE, 811 RCBit r = LeaveRC); 812 813 void subc(Register dst, Register src1, Register src2, OEBit s = LeaveOE, 814 RCBit r = LeaveRC); 815 void sube(Register dst, Register src1, Register src2, OEBit s = LeaveOE, 816 RCBit r = LeaveRC); 817 818 void subfic(Register dst, Register src, const Operand& imm); 819 820 void add(Register dst, Register src1, Register src2, OEBit s = LeaveOE, 821 RCBit r = LeaveRC); 822 823 void addc(Register dst, Register src1, Register src2, OEBit o = LeaveOE, 824 RCBit r = LeaveRC); 825 void adde(Register dst, Register src1, Register src2, OEBit o = LeaveOE, 826 RCBit r = LeaveRC); 827 void addze(Register dst, Register src1, OEBit o = LeaveOE, RCBit r = LeaveRC); 828 829 void mullw(Register dst, Register src1, Register src2, OEBit o = LeaveOE, 830 RCBit r = LeaveRC); 831 832 void mulhw(Register dst, Register src1, Register src2, RCBit r = LeaveRC); 833 void mulhwu(Register dst, Register src1, Register src2, RCBit r = LeaveRC); 834 835 void divw(Register dst, Register src1, Register src2, OEBit o = LeaveOE, 836 RCBit r = LeaveRC); 837 void divwu(Register dst, Register src1, Register src2, OEBit o = LeaveOE, 838 RCBit r = LeaveRC); 839 840 void addi(Register dst, Register src, const Operand& imm); 841 void addis(Register dst, Register src, const Operand& imm); 842 void addic(Register dst, Register src, const Operand& imm); 843 844 void and_(Register dst, Register src1, Register src2, RCBit rc = LeaveRC); 845 void andc(Register dst, Register src1, Register src2, RCBit rc = LeaveRC); 846 void andi(Register ra, Register rs, const Operand& imm); 847 void andis(Register ra, Register rs, const Operand& imm); 848 void nor(Register dst, Register src1, Register src2, RCBit r = LeaveRC); 849 void notx(Register dst, Register src, RCBit r = LeaveRC); 850 void ori(Register dst, Register src, const Operand& imm); 851 void oris(Register dst, Register src, const Operand& imm); 852 void orx(Register dst, Register src1, Register src2, RCBit rc = LeaveRC); 853 void orc(Register dst, Register src1, Register src2, RCBit rc = LeaveRC); 854 void xori(Register dst, Register src, const Operand& imm); 855 void xoris(Register ra, Register rs, const Operand& imm); 856 void xor_(Register dst, Register src1, Register src2, RCBit rc = LeaveRC); 857 void cmpi(Register src1, const Operand& src2, CRegister cr = cr7); 858 void cmpli(Register src1, const Operand& src2, CRegister cr = cr7); 859 void cmpwi(Register src1, const Operand& src2, CRegister cr = cr7); 860 void cmplwi(Register src1, const Operand& src2, CRegister cr = cr7); 861 void li(Register dst, const Operand& src); 862 void lis(Register dst, const Operand& imm); 863 void mr(Register dst, Register src); 864 865 void lbz(Register dst, const MemOperand& src); 866 void lbzx(Register dst, const MemOperand& src); 867 void lbzux(Register dst, const MemOperand& src); 868 void lhz(Register dst, const MemOperand& src); 869 void lhzx(Register dst, const MemOperand& src); 870 void lhzux(Register dst, const MemOperand& src); 871 void lha(Register dst, const MemOperand& src); 872 void lhax(Register dst, const MemOperand& src); 873 void lwz(Register dst, const MemOperand& src); 874 void lwzu(Register dst, const MemOperand& src); 875 void lwzx(Register dst, const MemOperand& src); 876 void lwzux(Register dst, const MemOperand& src); 877 void lwa(Register dst, const MemOperand& src); 878 void lwax(Register dst, const MemOperand& src); 879 void stb(Register dst, const MemOperand& src); 880 void stbx(Register dst, const MemOperand& src); 881 void stbux(Register dst, const MemOperand& src); 882 void sth(Register dst, const MemOperand& src); 883 void sthx(Register dst, const MemOperand& src); 884 void sthux(Register dst, const MemOperand& src); 885 void stw(Register dst, const MemOperand& src); 886 void stwu(Register dst, const MemOperand& src); 887 void stwx(Register rs, const MemOperand& src); 888 void stwux(Register rs, const MemOperand& src); 889 890 void extsb(Register rs, Register ra, RCBit r = LeaveRC); 891 void extsh(Register rs, Register ra, RCBit r = LeaveRC); 892 void extsw(Register rs, Register ra, RCBit r = LeaveRC); 893 894 void neg(Register rt, Register ra, OEBit o = LeaveOE, RCBit c = LeaveRC); 895 896 #if V8_TARGET_ARCH_PPC64 897 void ld(Register rd, const MemOperand& src); 898 void ldx(Register rd, const MemOperand& src); 899 void ldu(Register rd, const MemOperand& src); 900 void ldux(Register rd, const MemOperand& src); 901 void std(Register rs, const MemOperand& src); 902 void stdx(Register rs, const MemOperand& src); 903 void stdu(Register rs, const MemOperand& src); 904 void stdux(Register rs, const MemOperand& src); 905 void rldic(Register dst, Register src, int sh, int mb, RCBit r = LeaveRC); 906 void rldicl(Register dst, Register src, int sh, int mb, RCBit r = LeaveRC); 907 void rldcl(Register ra, Register rs, Register rb, int mb, RCBit r = LeaveRC); 908 void rldicr(Register dst, Register src, int sh, int me, RCBit r = LeaveRC); 909 void rldimi(Register dst, Register src, int sh, int mb, RCBit r = LeaveRC); 910 void sldi(Register dst, Register src, const Operand& val, RCBit rc = LeaveRC); 911 void srdi(Register dst, Register src, const Operand& val, RCBit rc = LeaveRC); 912 void clrrdi(Register dst, Register src, const Operand& val, 913 RCBit rc = LeaveRC); 914 void clrldi(Register dst, Register src, const Operand& val, 915 RCBit rc = LeaveRC); 916 void sradi(Register ra, Register rs, int sh, RCBit r = LeaveRC); 917 void srd(Register dst, Register src1, Register src2, RCBit r = LeaveRC); 918 void sld(Register dst, Register src1, Register src2, RCBit r = LeaveRC); 919 void srad(Register dst, Register src1, Register src2, RCBit r = LeaveRC); 920 void rotld(Register ra, Register rs, Register rb, RCBit r = LeaveRC); 921 void rotldi(Register ra, Register rs, int sh, RCBit r = LeaveRC); 922 void rotrdi(Register ra, Register rs, int sh, RCBit r = LeaveRC); 923 void cntlzd_(Register dst, Register src, RCBit rc = LeaveRC); 924 void popcntd(Register dst, Register src); 925 void mulld(Register dst, Register src1, Register src2, OEBit o = LeaveOE, 926 RCBit r = LeaveRC); 927 void divd(Register dst, Register src1, Register src2, OEBit o = LeaveOE, 928 RCBit r = LeaveRC); 929 void divdu(Register dst, Register src1, Register src2, OEBit o = LeaveOE, 930 RCBit r = LeaveRC); 931 #endif 932 933 void rlwinm(Register ra, Register rs, int sh, int mb, int me, 934 RCBit rc = LeaveRC); 935 void rlwimi(Register ra, Register rs, int sh, int mb, int me, 936 RCBit rc = LeaveRC); 937 void rlwnm(Register ra, Register rs, Register rb, int mb, int me, 938 RCBit rc = LeaveRC); 939 void slwi(Register dst, Register src, const Operand& val, RCBit rc = LeaveRC); 940 void srwi(Register dst, Register src, const Operand& val, RCBit rc = LeaveRC); 941 void clrrwi(Register dst, Register src, const Operand& val, 942 RCBit rc = LeaveRC); 943 void clrlwi(Register dst, Register src, const Operand& val, 944 RCBit rc = LeaveRC); 945 void srawi(Register ra, Register rs, int sh, RCBit r = LeaveRC); 946 void srw(Register dst, Register src1, Register src2, RCBit r = LeaveRC); 947 void slw(Register dst, Register src1, Register src2, RCBit r = LeaveRC); 948 void sraw(Register dst, Register src1, Register src2, RCBit r = LeaveRC); 949 void rotlw(Register ra, Register rs, Register rb, RCBit r = LeaveRC); 950 void rotlwi(Register ra, Register rs, int sh, RCBit r = LeaveRC); 951 void rotrwi(Register ra, Register rs, int sh, RCBit r = LeaveRC); 952 953 void cntlzw_(Register dst, Register src, RCBit rc = LeaveRC); 954 void popcntw(Register dst, Register src); 955 956 void subi(Register dst, Register src1, const Operand& src2); 957 958 void cmp(Register src1, Register src2, CRegister cr = cr7); 959 void cmpl(Register src1, Register src2, CRegister cr = cr7); 960 void cmpw(Register src1, Register src2, CRegister cr = cr7); 961 void cmplw(Register src1, Register src2, CRegister cr = cr7); 962 963 void mov(Register dst, const Operand& src); 964 void bitwise_mov(Register dst, intptr_t value); 965 void bitwise_mov32(Register dst, int32_t value); 966 void bitwise_add32(Register dst, Register src, int32_t value); 967 968 // Load the position of the label relative to the generated code object 969 // pointer in a register. 970 void mov_label_offset(Register dst, Label* label); 971 972 // dst = base + label position + delta 973 void add_label_offset(Register dst, Register base, Label* label, 974 int delta = 0); 975 976 // Load the address of the label in a register and associate with an 977 // internal reference relocation. 978 void mov_label_addr(Register dst, Label* label); 979 980 // Emit the address of the label (i.e. a jump table entry) and associate with 981 // an internal reference relocation. 982 void emit_label_addr(Label* label); 983 984 // Multiply instructions 985 void mul(Register dst, Register src1, Register src2, OEBit s = LeaveOE, 986 RCBit r = LeaveRC); 987 988 // Miscellaneous arithmetic instructions 989 990 // Special register access 991 void crxor(int bt, int ba, int bb); crclr(int bt)992 void crclr(int bt) { crxor(bt, bt, bt); } 993 void creqv(int bt, int ba, int bb); crset(int bt)994 void crset(int bt) { creqv(bt, bt, bt); } 995 void mflr(Register dst); 996 void mtlr(Register src); 997 void mtctr(Register src); 998 void mtxer(Register src); 999 void mcrfs(CRegister cr, FPSCRBit bit); 1000 void mfcr(Register dst); 1001 #if V8_TARGET_ARCH_PPC64 1002 void mffprd(Register dst, DoubleRegister src); 1003 void mffprwz(Register dst, DoubleRegister src); 1004 void mtfprd(DoubleRegister dst, Register src); 1005 void mtfprwz(DoubleRegister dst, Register src); 1006 void mtfprwa(DoubleRegister dst, Register src); 1007 #endif 1008 1009 void function_descriptor(); 1010 1011 // Exception-generating instructions and debugging support 1012 void stop(const char* msg, Condition cond = al, 1013 int32_t code = kDefaultStopCode, CRegister cr = cr7); 1014 1015 void bkpt(uint32_t imm16); // v5 and above 1016 1017 void dcbf(Register ra, Register rb); 1018 void sync(); 1019 void lwsync(); 1020 void icbi(Register ra, Register rb); 1021 void isync(); 1022 1023 // Support for floating point 1024 void lfd(const DoubleRegister frt, const MemOperand& src); 1025 void lfdu(const DoubleRegister frt, const MemOperand& src); 1026 void lfdx(const DoubleRegister frt, const MemOperand& src); 1027 void lfdux(const DoubleRegister frt, const MemOperand& src); 1028 void lfs(const DoubleRegister frt, const MemOperand& src); 1029 void lfsu(const DoubleRegister frt, const MemOperand& src); 1030 void lfsx(const DoubleRegister frt, const MemOperand& src); 1031 void lfsux(const DoubleRegister frt, const MemOperand& src); 1032 void stfd(const DoubleRegister frs, const MemOperand& src); 1033 void stfdu(const DoubleRegister frs, const MemOperand& src); 1034 void stfdx(const DoubleRegister frs, const MemOperand& src); 1035 void stfdux(const DoubleRegister frs, const MemOperand& src); 1036 void stfs(const DoubleRegister frs, const MemOperand& src); 1037 void stfsu(const DoubleRegister frs, const MemOperand& src); 1038 void stfsx(const DoubleRegister frs, const MemOperand& src); 1039 void stfsux(const DoubleRegister frs, const MemOperand& src); 1040 1041 void fadd(const DoubleRegister frt, const DoubleRegister fra, 1042 const DoubleRegister frb, RCBit rc = LeaveRC); 1043 void fsub(const DoubleRegister frt, const DoubleRegister fra, 1044 const DoubleRegister frb, RCBit rc = LeaveRC); 1045 void fdiv(const DoubleRegister frt, const DoubleRegister fra, 1046 const DoubleRegister frb, RCBit rc = LeaveRC); 1047 void fmul(const DoubleRegister frt, const DoubleRegister fra, 1048 const DoubleRegister frc, RCBit rc = LeaveRC); 1049 void fcmpu(const DoubleRegister fra, const DoubleRegister frb, 1050 CRegister cr = cr7); 1051 void fmr(const DoubleRegister frt, const DoubleRegister frb, 1052 RCBit rc = LeaveRC); 1053 void fctiwz(const DoubleRegister frt, const DoubleRegister frb); 1054 void fctiw(const DoubleRegister frt, const DoubleRegister frb); 1055 void frin(const DoubleRegister frt, const DoubleRegister frb, 1056 RCBit rc = LeaveRC); 1057 void friz(const DoubleRegister frt, const DoubleRegister frb, 1058 RCBit rc = LeaveRC); 1059 void frip(const DoubleRegister frt, const DoubleRegister frb, 1060 RCBit rc = LeaveRC); 1061 void frim(const DoubleRegister frt, const DoubleRegister frb, 1062 RCBit rc = LeaveRC); 1063 void frsp(const DoubleRegister frt, const DoubleRegister frb, 1064 RCBit rc = LeaveRC); 1065 void fcfid(const DoubleRegister frt, const DoubleRegister frb, 1066 RCBit rc = LeaveRC); 1067 void fcfidu(const DoubleRegister frt, const DoubleRegister frb, 1068 RCBit rc = LeaveRC); 1069 void fcfidus(const DoubleRegister frt, const DoubleRegister frb, 1070 RCBit rc = LeaveRC); 1071 void fcfids(const DoubleRegister frt, const DoubleRegister frb, 1072 RCBit rc = LeaveRC); 1073 void fctid(const DoubleRegister frt, const DoubleRegister frb, 1074 RCBit rc = LeaveRC); 1075 void fctidz(const DoubleRegister frt, const DoubleRegister frb, 1076 RCBit rc = LeaveRC); 1077 void fctidu(const DoubleRegister frt, const DoubleRegister frb, 1078 RCBit rc = LeaveRC); 1079 void fctiduz(const DoubleRegister frt, const DoubleRegister frb, 1080 RCBit rc = LeaveRC); 1081 void fsel(const DoubleRegister frt, const DoubleRegister fra, 1082 const DoubleRegister frc, const DoubleRegister frb, 1083 RCBit rc = LeaveRC); 1084 void fneg(const DoubleRegister frt, const DoubleRegister frb, 1085 RCBit rc = LeaveRC); 1086 void mtfsb0(FPSCRBit bit, RCBit rc = LeaveRC); 1087 void mtfsb1(FPSCRBit bit, RCBit rc = LeaveRC); 1088 void mtfsfi(int bf, int immediate, RCBit rc = LeaveRC); 1089 void mffs(const DoubleRegister frt, RCBit rc = LeaveRC); 1090 void mtfsf(const DoubleRegister frb, bool L = 1, int FLM = 0, bool W = 0, 1091 RCBit rc = LeaveRC); 1092 void fsqrt(const DoubleRegister frt, const DoubleRegister frb, 1093 RCBit rc = LeaveRC); 1094 void fabs(const DoubleRegister frt, const DoubleRegister frb, 1095 RCBit rc = LeaveRC); 1096 void fmadd(const DoubleRegister frt, const DoubleRegister fra, 1097 const DoubleRegister frc, const DoubleRegister frb, 1098 RCBit rc = LeaveRC); 1099 void fmsub(const DoubleRegister frt, const DoubleRegister fra, 1100 const DoubleRegister frc, const DoubleRegister frb, 1101 RCBit rc = LeaveRC); 1102 1103 // Pseudo instructions 1104 1105 // Different nop operations are used by the code generator to detect certain 1106 // states of the generated code. 1107 enum NopMarkerTypes { 1108 NON_MARKING_NOP = 0, 1109 GROUP_ENDING_NOP, 1110 DEBUG_BREAK_NOP, 1111 // IC markers. 1112 PROPERTY_ACCESS_INLINED, 1113 PROPERTY_ACCESS_INLINED_CONTEXT, 1114 PROPERTY_ACCESS_INLINED_CONTEXT_DONT_DELETE, 1115 // Helper values. 1116 LAST_CODE_MARKER, 1117 FIRST_IC_MARKER = PROPERTY_ACCESS_INLINED 1118 }; 1119 1120 void nop(int type = 0); // 0 is the default non-marking type. 1121 push(Register src)1122 void push(Register src) { 1123 #if V8_TARGET_ARCH_PPC64 1124 stdu(src, MemOperand(sp, -kPointerSize)); 1125 #else 1126 stwu(src, MemOperand(sp, -kPointerSize)); 1127 #endif 1128 } 1129 pop(Register dst)1130 void pop(Register dst) { 1131 #if V8_TARGET_ARCH_PPC64 1132 ld(dst, MemOperand(sp)); 1133 #else 1134 lwz(dst, MemOperand(sp)); 1135 #endif 1136 addi(sp, sp, Operand(kPointerSize)); 1137 } 1138 pop()1139 void pop() { addi(sp, sp, Operand(kPointerSize)); } 1140 1141 // Jump unconditionally to given label. jmp(Label * L)1142 void jmp(Label* L) { b(L); } 1143 1144 // Check the code size generated from label to here. SizeOfCodeGeneratedSince(Label * label)1145 int SizeOfCodeGeneratedSince(Label* label) { 1146 return pc_offset() - label->pos(); 1147 } 1148 1149 // Check the number of instructions generated from label to here. InstructionsGeneratedSince(Label * label)1150 int InstructionsGeneratedSince(Label* label) { 1151 return SizeOfCodeGeneratedSince(label) / kInstrSize; 1152 } 1153 1154 // Class for scoping postponing the trampoline pool generation. 1155 class BlockTrampolinePoolScope { 1156 public: BlockTrampolinePoolScope(Assembler * assem)1157 explicit BlockTrampolinePoolScope(Assembler* assem) : assem_(assem) { 1158 assem_->StartBlockTrampolinePool(); 1159 } ~BlockTrampolinePoolScope()1160 ~BlockTrampolinePoolScope() { assem_->EndBlockTrampolinePool(); } 1161 1162 private: 1163 Assembler* assem_; 1164 1165 DISALLOW_IMPLICIT_CONSTRUCTORS(BlockTrampolinePoolScope); 1166 }; 1167 1168 // Class for scoping disabling constant pool entry merging 1169 class BlockConstantPoolEntrySharingScope { 1170 public: BlockConstantPoolEntrySharingScope(Assembler * assem)1171 explicit BlockConstantPoolEntrySharingScope(Assembler* assem) 1172 : assem_(assem) { 1173 assem_->StartBlockConstantPoolEntrySharing(); 1174 } ~BlockConstantPoolEntrySharingScope()1175 ~BlockConstantPoolEntrySharingScope() { 1176 assem_->EndBlockConstantPoolEntrySharing(); 1177 } 1178 1179 private: 1180 Assembler* assem_; 1181 1182 DISALLOW_IMPLICIT_CONSTRUCTORS(BlockConstantPoolEntrySharingScope); 1183 }; 1184 1185 // Debugging 1186 1187 // Mark generator continuation. 1188 void RecordGeneratorContinuation(); 1189 1190 // Mark address of a debug break slot. 1191 void RecordDebugBreakSlot(RelocInfo::Mode mode); 1192 1193 // Record the AST id of the CallIC being compiled, so that it can be placed 1194 // in the relocation information. SetRecordedAstId(TypeFeedbackId ast_id)1195 void SetRecordedAstId(TypeFeedbackId ast_id) { 1196 // Causes compiler to fail 1197 // DCHECK(recorded_ast_id_.IsNone()); 1198 recorded_ast_id_ = ast_id; 1199 } 1200 RecordedAstId()1201 TypeFeedbackId RecordedAstId() { 1202 // Causes compiler to fail 1203 // DCHECK(!recorded_ast_id_.IsNone()); 1204 return recorded_ast_id_; 1205 } 1206 ClearRecordedAstId()1207 void ClearRecordedAstId() { recorded_ast_id_ = TypeFeedbackId::None(); } 1208 1209 // Record a comment relocation entry that can be used by a disassembler. 1210 // Use --code-comments to enable. 1211 void RecordComment(const char* msg); 1212 1213 // Record a deoptimization reason that can be used by a log or cpu profiler. 1214 // Use --trace-deopt to enable. 1215 void RecordDeoptReason(const int reason, int raw_position, int id); 1216 1217 // Writes a single byte or word of data in the code stream. Used 1218 // for inline tables, e.g., jump-tables. 1219 void db(uint8_t data); 1220 void dd(uint32_t data); 1221 void dq(uint64_t data); 1222 void dp(uintptr_t data); 1223 positions_recorder()1224 AssemblerPositionsRecorder* positions_recorder() { 1225 return &positions_recorder_; 1226 } 1227 1228 // Read/patch instructions instr_at(int pos)1229 Instr instr_at(int pos) { return *reinterpret_cast<Instr*>(buffer_ + pos); } instr_at_put(int pos,Instr instr)1230 void instr_at_put(int pos, Instr instr) { 1231 *reinterpret_cast<Instr*>(buffer_ + pos) = instr; 1232 } instr_at(byte * pc)1233 static Instr instr_at(byte* pc) { return *reinterpret_cast<Instr*>(pc); } instr_at_put(byte * pc,Instr instr)1234 static void instr_at_put(byte* pc, Instr instr) { 1235 *reinterpret_cast<Instr*>(pc) = instr; 1236 } 1237 static Condition GetCondition(Instr instr); 1238 1239 static bool IsLis(Instr instr); 1240 static bool IsLi(Instr instr); 1241 static bool IsAddic(Instr instr); 1242 static bool IsOri(Instr instr); 1243 1244 static bool IsBranch(Instr instr); 1245 static Register GetRA(Instr instr); 1246 static Register GetRB(Instr instr); 1247 #if V8_TARGET_ARCH_PPC64 1248 static bool Is64BitLoadIntoR12(Instr instr1, Instr instr2, Instr instr3, 1249 Instr instr4, Instr instr5); 1250 #else 1251 static bool Is32BitLoadIntoR12(Instr instr1, Instr instr2); 1252 #endif 1253 1254 static bool IsCmpRegister(Instr instr); 1255 static bool IsCmpImmediate(Instr instr); 1256 static bool IsRlwinm(Instr instr); 1257 static bool IsAndi(Instr instr); 1258 #if V8_TARGET_ARCH_PPC64 1259 static bool IsRldicl(Instr instr); 1260 #endif 1261 static bool IsCrSet(Instr instr); 1262 static Register GetCmpImmediateRegister(Instr instr); 1263 static int GetCmpImmediateRawImmediate(Instr instr); 1264 static bool IsNop(Instr instr, int type = NON_MARKING_NOP); 1265 1266 // Postpone the generation of the trampoline pool for the specified number of 1267 // instructions. 1268 void BlockTrampolinePoolFor(int instructions); 1269 void CheckTrampolinePool(); 1270 1271 // For mov. Return the number of actual instructions required to 1272 // load the operand into a register. This can be anywhere from 1273 // one (constant pool small section) to five instructions (full 1274 // 64-bit sequence). 1275 // 1276 // The value returned is only valid as long as no entries are added to the 1277 // constant pool between this call and the actual instruction being emitted. 1278 int instructions_required_for_mov(Register dst, const Operand& src) const; 1279 1280 // Decide between using the constant pool vs. a mov immediate sequence. 1281 bool use_constant_pool_for_mov(Register dst, const Operand& src, 1282 bool canOptimize) const; 1283 1284 // The code currently calls CheckBuffer() too often. This has the side 1285 // effect of randomly growing the buffer in the middle of multi-instruction 1286 // sequences. 1287 // 1288 // This function allows outside callers to check and grow the buffer 1289 void EnsureSpaceFor(int space_needed); 1290 EmitConstantPool()1291 int EmitConstantPool() { return constant_pool_builder_.Emit(this); } 1292 ConstantPoolAccessIsInOverflow()1293 bool ConstantPoolAccessIsInOverflow() const { 1294 return constant_pool_builder_.NextAccess(ConstantPoolEntry::INTPTR) == 1295 ConstantPoolEntry::OVERFLOWED; 1296 } 1297 ConstantPoolPosition()1298 Label* ConstantPoolPosition() { 1299 return constant_pool_builder_.EmittedPosition(); 1300 } 1301 1302 void EmitRelocations(); 1303 1304 protected: 1305 // Relocation for a type-recording IC has the AST id added to it. This 1306 // member variable is a way to pass the information from the call site to 1307 // the relocation info. 1308 TypeFeedbackId recorded_ast_id_; 1309 buffer_space()1310 int buffer_space() const { return reloc_info_writer.pos() - pc_; } 1311 1312 // Decode instruction(s) at pos and return backchain to previous 1313 // label reference or kEndOfChain. 1314 int target_at(int pos); 1315 1316 // Patch instruction(s) at pos to target target_pos (e.g. branch) 1317 void target_at_put(int pos, int target_pos, bool* is_branch = nullptr); 1318 1319 // Record reloc info for current pc_ 1320 void RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data = 0); ConstantPoolAddEntry(RelocInfo::Mode rmode,intptr_t value)1321 ConstantPoolEntry::Access ConstantPoolAddEntry(RelocInfo::Mode rmode, 1322 intptr_t value) { 1323 bool sharing_ok = RelocInfo::IsNone(rmode) || 1324 !(serializer_enabled() || rmode < RelocInfo::CELL || 1325 is_constant_pool_entry_sharing_blocked()); 1326 return constant_pool_builder_.AddEntry(pc_offset(), value, sharing_ok); 1327 } ConstantPoolAddEntry(double value)1328 ConstantPoolEntry::Access ConstantPoolAddEntry(double value) { 1329 return constant_pool_builder_.AddEntry(pc_offset(), value); 1330 } 1331 1332 // Block the emission of the trampoline pool before pc_offset. BlockTrampolinePoolBefore(int pc_offset)1333 void BlockTrampolinePoolBefore(int pc_offset) { 1334 if (no_trampoline_pool_before_ < pc_offset) 1335 no_trampoline_pool_before_ = pc_offset; 1336 } 1337 StartBlockTrampolinePool()1338 void StartBlockTrampolinePool() { trampoline_pool_blocked_nesting_++; } EndBlockTrampolinePool()1339 void EndBlockTrampolinePool() { 1340 int count = --trampoline_pool_blocked_nesting_; 1341 if (count == 0) CheckTrampolinePoolQuick(); 1342 } is_trampoline_pool_blocked()1343 bool is_trampoline_pool_blocked() const { 1344 return trampoline_pool_blocked_nesting_ > 0; 1345 } 1346 StartBlockConstantPoolEntrySharing()1347 void StartBlockConstantPoolEntrySharing() { 1348 constant_pool_entry_sharing_blocked_nesting_++; 1349 } EndBlockConstantPoolEntrySharing()1350 void EndBlockConstantPoolEntrySharing() { 1351 constant_pool_entry_sharing_blocked_nesting_--; 1352 } is_constant_pool_entry_sharing_blocked()1353 bool is_constant_pool_entry_sharing_blocked() const { 1354 return constant_pool_entry_sharing_blocked_nesting_ > 0; 1355 } 1356 has_exception()1357 bool has_exception() const { return internal_trampoline_exception_; } 1358 is_trampoline_emitted()1359 bool is_trampoline_emitted() const { return trampoline_emitted_; } 1360 1361 private: 1362 // Code generation 1363 // The relocation writer's position is at least kGap bytes below the end of 1364 // the generated instructions. This is so that multi-instruction sequences do 1365 // not have to check for overflow. The same is true for writes of large 1366 // relocation info entries. 1367 static const int kGap = 32; 1368 1369 // Repeated checking whether the trampoline pool should be emitted is rather 1370 // expensive. By default we only check again once a number of instructions 1371 // has been generated. 1372 int next_trampoline_check_; // pc offset of next buffer check. 1373 1374 // Emission of the trampoline pool may be blocked in some code sequences. 1375 int trampoline_pool_blocked_nesting_; // Block emission if this is not zero. 1376 int no_trampoline_pool_before_; // Block emission before this pc offset. 1377 1378 // Do not share constant pool entries. 1379 int constant_pool_entry_sharing_blocked_nesting_; 1380 1381 // Relocation info generation 1382 // Each relocation is encoded as a variable size value 1383 static const int kMaxRelocSize = RelocInfoWriter::kMaxSize; 1384 RelocInfoWriter reloc_info_writer; 1385 std::vector<DeferredRelocInfo> relocations_; 1386 1387 // The bound position, before this we cannot do instruction elimination. 1388 int last_bound_pos_; 1389 // Optimizable cmpi information. 1390 int optimizable_cmpi_pos_; 1391 CRegister cmpi_cr_; 1392 1393 ConstantPoolBuilder constant_pool_builder_; 1394 1395 // Code emission 1396 inline void CheckBuffer(); 1397 void GrowBuffer(int needed = 0); 1398 inline void emit(Instr x); 1399 inline void TrackBranch(); 1400 inline void UntrackBranch(); 1401 inline void CheckTrampolinePoolQuick(); 1402 1403 // Instruction generation 1404 void a_form(Instr instr, DoubleRegister frt, DoubleRegister fra, 1405 DoubleRegister frb, RCBit r); 1406 void d_form(Instr instr, Register rt, Register ra, const intptr_t val, 1407 bool signed_disp); 1408 void x_form(Instr instr, Register ra, Register rs, Register rb, RCBit r); 1409 void xo_form(Instr instr, Register rt, Register ra, Register rb, OEBit o, 1410 RCBit r); 1411 void md_form(Instr instr, Register ra, Register rs, int shift, int maskbit, 1412 RCBit r); 1413 void mds_form(Instr instr, Register ra, Register rs, Register rb, int maskbit, 1414 RCBit r); 1415 1416 // Labels 1417 void print(Label* L); 1418 int max_reach_from(int pos); 1419 void bind_to(Label* L, int pos); 1420 void next(Label* L); 1421 1422 class Trampoline { 1423 public: Trampoline()1424 Trampoline() { 1425 next_slot_ = 0; 1426 free_slot_count_ = 0; 1427 } Trampoline(int start,int slot_count)1428 Trampoline(int start, int slot_count) { 1429 next_slot_ = start; 1430 free_slot_count_ = slot_count; 1431 } take_slot()1432 int take_slot() { 1433 int trampoline_slot = kInvalidSlotPos; 1434 if (free_slot_count_ <= 0) { 1435 // We have run out of space on trampolines. 1436 // Make sure we fail in debug mode, so we become aware of each case 1437 // when this happens. 1438 DCHECK(0); 1439 // Internal exception will be caught. 1440 } else { 1441 trampoline_slot = next_slot_; 1442 free_slot_count_--; 1443 next_slot_ += kTrampolineSlotsSize; 1444 } 1445 return trampoline_slot; 1446 } 1447 1448 private: 1449 int next_slot_; 1450 int free_slot_count_; 1451 }; 1452 1453 int32_t get_trampoline_entry(); 1454 int tracked_branch_count_; 1455 // If trampoline is emitted, generated code is becoming large. As 1456 // this is already a slow case which can possibly break our code 1457 // generation for the extreme case, we use this information to 1458 // trigger different mode of branch instruction generation, where we 1459 // no longer use a single branch instruction. 1460 bool trampoline_emitted_; 1461 static const int kTrampolineSlotsSize = kInstrSize; 1462 static const int kMaxCondBranchReach = (1 << (16 - 1)) - 1; 1463 static const int kMaxBlockTrampolineSectionSize = 64 * kInstrSize; 1464 static const int kInvalidSlotPos = -1; 1465 1466 Trampoline trampoline_; 1467 bool internal_trampoline_exception_; 1468 1469 friend class RegExpMacroAssemblerPPC; 1470 friend class RelocInfo; 1471 friend class CodePatcher; 1472 friend class BlockTrampolinePoolScope; 1473 AssemblerPositionsRecorder positions_recorder_; 1474 friend class AssemblerPositionsRecorder; 1475 friend class EnsureSpace; 1476 }; 1477 1478 1479 class EnsureSpace BASE_EMBEDDED { 1480 public: EnsureSpace(Assembler * assembler)1481 explicit EnsureSpace(Assembler* assembler) { assembler->CheckBuffer(); } 1482 }; 1483 } // namespace internal 1484 } // namespace v8 1485 1486 #endif // V8_PPC_ASSEMBLER_PPC_H_ 1487