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