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