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