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 #include "src/ppc/assembler-ppc.h" 38 39 #if V8_TARGET_ARCH_PPC 40 41 #include "src/base/bits.h" 42 #include "src/base/cpu.h" 43 #include "src/code-stubs.h" 44 #include "src/deoptimizer.h" 45 #include "src/macro-assembler.h" 46 #include "src/ppc/assembler-ppc-inl.h" 47 48 namespace v8 { 49 namespace internal { 50 51 // Get the CPU features enabled by the build. 52 static unsigned CpuFeaturesImpliedByCompiler() { 53 unsigned answer = 0; 54 return answer; 55 } 56 57 58 void CpuFeatures::ProbeImpl(bool cross_compile) { 59 supported_ |= CpuFeaturesImpliedByCompiler(); 60 icache_line_size_ = 128; 61 62 // Only use statically determined features for cross compile (snapshot). 63 if (cross_compile) return; 64 65 // Detect whether frim instruction is supported (POWER5+) 66 // For now we will just check for processors we know do not 67 // support it 68 #ifndef USE_SIMULATOR 69 // Probe for additional features at runtime. 70 base::CPU cpu; 71 if (cpu.part() == base::CPU::PPC_POWER9) { 72 supported_ |= (1u << MODULO); 73 } 74 #if V8_TARGET_ARCH_PPC64 75 if (cpu.part() == base::CPU::PPC_POWER8) { 76 supported_ |= (1u << FPR_GPR_MOV); 77 } 78 #endif 79 if (cpu.part() == base::CPU::PPC_POWER6 || 80 cpu.part() == base::CPU::PPC_POWER7 || 81 cpu.part() == base::CPU::PPC_POWER8) { 82 supported_ |= (1u << LWSYNC); 83 } 84 if (cpu.part() == base::CPU::PPC_POWER7 || 85 cpu.part() == base::CPU::PPC_POWER8) { 86 supported_ |= (1u << ISELECT); 87 supported_ |= (1u << VSX); 88 } 89 #if V8_OS_LINUX 90 if (!(cpu.part() == base::CPU::PPC_G5 || cpu.part() == base::CPU::PPC_G4)) { 91 // Assume support 92 supported_ |= (1u << FPU); 93 } 94 if (cpu.icache_line_size() != base::CPU::UNKNOWN_CACHE_LINE_SIZE) { 95 icache_line_size_ = cpu.icache_line_size(); 96 } 97 #elif V8_OS_AIX 98 // Assume support FP support and default cache line size 99 supported_ |= (1u << FPU); 100 #endif 101 #else // Simulator 102 supported_ |= (1u << FPU); 103 supported_ |= (1u << LWSYNC); 104 supported_ |= (1u << ISELECT); 105 supported_ |= (1u << VSX); 106 supported_ |= (1u << MODULO); 107 #if V8_TARGET_ARCH_PPC64 108 supported_ |= (1u << FPR_GPR_MOV); 109 #endif 110 #endif 111 } 112 113 114 void CpuFeatures::PrintTarget() { 115 const char* ppc_arch = nullptr; 116 117 #if V8_TARGET_ARCH_PPC64 118 ppc_arch = "ppc64"; 119 #else 120 ppc_arch = "ppc"; 121 #endif 122 123 printf("target %s\n", ppc_arch); 124 } 125 126 127 void CpuFeatures::PrintFeatures() { 128 printf("FPU=%d\n", CpuFeatures::IsSupported(FPU)); 129 } 130 131 132 Register ToRegister(int num) { 133 DCHECK(num >= 0 && num < kNumRegisters); 134 const Register kRegisters[] = {r0, sp, r2, r3, r4, r5, r6, r7, 135 r8, r9, r10, r11, ip, r13, r14, r15, 136 r16, r17, r18, r19, r20, r21, r22, r23, 137 r24, r25, r26, r27, r28, r29, r30, fp}; 138 return kRegisters[num]; 139 } 140 141 142 // ----------------------------------------------------------------------------- 143 // Implementation of RelocInfo 144 145 const int RelocInfo::kApplyMask = 146 RelocInfo::ModeMask(RelocInfo::INTERNAL_REFERENCE) | 147 RelocInfo::ModeMask(RelocInfo::INTERNAL_REFERENCE_ENCODED); 148 149 bool RelocInfo::IsCodedSpecially() { 150 // The deserializer needs to know whether a pointer is specially 151 // coded. Being specially coded on PPC means that it is a lis/ori 152 // instruction sequence or is a constant pool entry, and these are 153 // always the case inside code objects. 154 return true; 155 } 156 157 158 bool RelocInfo::IsInConstantPool() { 159 if (FLAG_enable_embedded_constant_pool && constant_pool_ != kNullAddress) { 160 return Assembler::IsConstantPoolLoadStart(pc_); 161 } 162 return false; 163 } 164 165 int RelocInfo::GetDeoptimizationId(Isolate* isolate, DeoptimizeKind kind) { 166 DCHECK(IsRuntimeEntry(rmode_)); 167 return Deoptimizer::GetDeoptimizationId(isolate, target_address(), kind); 168 } 169 170 void RelocInfo::set_js_to_wasm_address(Address address, 171 ICacheFlushMode icache_flush_mode) { 172 DCHECK_EQ(rmode_, JS_TO_WASM_CALL); 173 Assembler::set_target_address_at(pc_, constant_pool_, address, 174 icache_flush_mode); 175 } 176 177 Address RelocInfo::js_to_wasm_address() const { 178 DCHECK_EQ(rmode_, JS_TO_WASM_CALL); 179 return Assembler::target_address_at(pc_, constant_pool_); 180 } 181 182 uint32_t RelocInfo::wasm_call_tag() const { 183 DCHECK(rmode_ == WASM_CALL || rmode_ == WASM_STUB_CALL); 184 return static_cast<uint32_t>( 185 Assembler::target_address_at(pc_, constant_pool_)); 186 } 187 188 // ----------------------------------------------------------------------------- 189 // Implementation of Operand and MemOperand 190 // See assembler-ppc-inl.h for inlined constructors 191 192 Operand::Operand(Handle<HeapObject> handle) { 193 rm_ = no_reg; 194 value_.immediate = static_cast<intptr_t>(handle.address()); 195 rmode_ = RelocInfo::EMBEDDED_OBJECT; 196 } 197 198 Operand Operand::EmbeddedNumber(double value) { 199 int32_t smi; 200 if (DoubleToSmiInteger(value, &smi)) return Operand(Smi::FromInt(smi)); 201 Operand result(0, RelocInfo::EMBEDDED_OBJECT); 202 result.is_heap_object_request_ = true; 203 result.value_.heap_object_request = HeapObjectRequest(value); 204 return result; 205 } 206 207 Operand Operand::EmbeddedCode(CodeStub* stub) { 208 Operand result(0, RelocInfo::CODE_TARGET); 209 result.is_heap_object_request_ = true; 210 result.value_.heap_object_request = HeapObjectRequest(stub); 211 return result; 212 } 213 214 MemOperand::MemOperand(Register rn, int32_t offset) 215 : ra_(rn), offset_(offset), rb_(no_reg) {} 216 217 MemOperand::MemOperand(Register ra, Register rb) 218 : ra_(ra), offset_(0), rb_(rb) {} 219 220 void Assembler::AllocateAndInstallRequestedHeapObjects(Isolate* isolate) { 221 for (auto& request : heap_object_requests_) { 222 Handle<HeapObject> object; 223 switch (request.kind()) { 224 case HeapObjectRequest::kHeapNumber: 225 object = 226 isolate->factory()->NewHeapNumber(request.heap_number(), TENURED); 227 break; 228 case HeapObjectRequest::kCodeStub: 229 request.code_stub()->set_isolate(isolate); 230 object = request.code_stub()->GetCode(); 231 break; 232 } 233 Address pc = reinterpret_cast<Address>(buffer_) + request.offset(); 234 Address constant_pool = kNullAddress; 235 set_target_address_at(pc, constant_pool, 236 reinterpret_cast<Address>(object.location()), 237 SKIP_ICACHE_FLUSH); 238 } 239 } 240 241 // ----------------------------------------------------------------------------- 242 // Specific instructions, constants, and masks. 243 244 Assembler::Assembler(const AssemblerOptions& options, void* buffer, 245 int buffer_size) 246 : AssemblerBase(options, buffer, buffer_size), 247 constant_pool_builder_(kLoadPtrMaxReachBits, kLoadDoubleMaxReachBits) { 248 reloc_info_writer.Reposition(buffer_ + buffer_size_, pc_); 249 250 no_trampoline_pool_before_ = 0; 251 trampoline_pool_blocked_nesting_ = 0; 252 constant_pool_entry_sharing_blocked_nesting_ = 0; 253 next_trampoline_check_ = kMaxInt; 254 internal_trampoline_exception_ = false; 255 last_bound_pos_ = 0; 256 optimizable_cmpi_pos_ = -1; 257 trampoline_emitted_ = FLAG_force_long_branches; 258 tracked_branch_count_ = 0; 259 relocations_.reserve(128); 260 } 261 262 void Assembler::GetCode(Isolate* isolate, CodeDesc* desc) { 263 // Emit constant pool if necessary. 264 int constant_pool_offset = EmitConstantPool(); 265 266 EmitRelocations(); 267 AllocateAndInstallRequestedHeapObjects(isolate); 268 269 // Set up code descriptor. 270 desc->buffer = buffer_; 271 desc->buffer_size = buffer_size_; 272 desc->instr_size = pc_offset(); 273 desc->reloc_size = (buffer_ + buffer_size_) - reloc_info_writer.pos(); 274 desc->constant_pool_size = 275 (constant_pool_offset ? desc->instr_size - constant_pool_offset : 0); 276 desc->origin = this; 277 desc->unwinding_info_size = 0; 278 desc->unwinding_info = nullptr; 279 } 280 281 282 void Assembler::Align(int m) { 283 DCHECK(m >= 4 && base::bits::IsPowerOfTwo(m)); 284 DCHECK_EQ(pc_offset() & (kInstrSize - 1), 0); 285 while ((pc_offset() & (m - 1)) != 0) { 286 nop(); 287 } 288 } 289 290 291 void Assembler::CodeTargetAlign() { Align(8); } 292 293 294 Condition Assembler::GetCondition(Instr instr) { 295 switch (instr & kCondMask) { 296 case BT: 297 return eq; 298 case BF: 299 return ne; 300 default: 301 UNIMPLEMENTED(); 302 } 303 return al; 304 } 305 306 307 bool Assembler::IsLis(Instr instr) { 308 return ((instr & kOpcodeMask) == ADDIS) && GetRA(instr) == r0; 309 } 310 311 312 bool Assembler::IsLi(Instr instr) { 313 return ((instr & kOpcodeMask) == ADDI) && GetRA(instr) == r0; 314 } 315 316 317 bool Assembler::IsAddic(Instr instr) { return (instr & kOpcodeMask) == ADDIC; } 318 319 320 bool Assembler::IsOri(Instr instr) { return (instr & kOpcodeMask) == ORI; } 321 322 323 bool Assembler::IsBranch(Instr instr) { return ((instr & kOpcodeMask) == BCX); } 324 325 326 Register Assembler::GetRA(Instr instr) { 327 return Register::from_code(Instruction::RAValue(instr)); 328 } 329 330 331 Register Assembler::GetRB(Instr instr) { 332 return Register::from_code(Instruction::RBValue(instr)); 333 } 334 335 336 #if V8_TARGET_ARCH_PPC64 337 // This code assumes a FIXED_SEQUENCE for 64bit loads (lis/ori) 338 bool Assembler::Is64BitLoadIntoR12(Instr instr1, Instr instr2, Instr instr3, 339 Instr instr4, Instr instr5) { 340 // Check the instructions are indeed a five part load (into r12) 341 // 3d800000 lis r12, 0 342 // 618c0000 ori r12, r12, 0 343 // 798c07c6 rldicr r12, r12, 32, 31 344 // 658c00c3 oris r12, r12, 195 345 // 618ccd40 ori r12, r12, 52544 346 return (((instr1 >> 16) == 0x3D80) && ((instr2 >> 16) == 0x618C) && 347 (instr3 == 0x798C07C6) && ((instr4 >> 16) == 0x658C) && 348 ((instr5 >> 16) == 0x618C)); 349 } 350 #else 351 // This code assumes a FIXED_SEQUENCE for 32bit loads (lis/ori) 352 bool Assembler::Is32BitLoadIntoR12(Instr instr1, Instr instr2) { 353 // Check the instruction is indeed a two part load (into r12) 354 // 3d802553 lis r12, 9555 355 // 618c5000 ori r12, r12, 20480 356 return (((instr1 >> 16) == 0x3D80) && ((instr2 >> 16) == 0x618C)); 357 } 358 #endif 359 360 361 bool Assembler::IsCmpRegister(Instr instr) { 362 return (((instr & kOpcodeMask) == EXT2) && 363 ((EXT2 | (instr & kExt2OpcodeMask)) == CMP)); 364 } 365 366 367 bool Assembler::IsRlwinm(Instr instr) { 368 return ((instr & kOpcodeMask) == RLWINMX); 369 } 370 371 372 bool Assembler::IsAndi(Instr instr) { return ((instr & kOpcodeMask) == ANDIx); } 373 374 375 #if V8_TARGET_ARCH_PPC64 376 bool Assembler::IsRldicl(Instr instr) { 377 return (((instr & kOpcodeMask) == EXT5) && 378 ((EXT5 | (instr & kExt5OpcodeMask)) == RLDICL)); 379 } 380 #endif 381 382 383 bool Assembler::IsCmpImmediate(Instr instr) { 384 return ((instr & kOpcodeMask) == CMPI); 385 } 386 387 388 bool Assembler::IsCrSet(Instr instr) { 389 return (((instr & kOpcodeMask) == EXT1) && 390 ((EXT1 | (instr & kExt1OpcodeMask)) == CREQV)); 391 } 392 393 394 Register Assembler::GetCmpImmediateRegister(Instr instr) { 395 DCHECK(IsCmpImmediate(instr)); 396 return GetRA(instr); 397 } 398 399 400 int Assembler::GetCmpImmediateRawImmediate(Instr instr) { 401 DCHECK(IsCmpImmediate(instr)); 402 return instr & kOff16Mask; 403 } 404 405 406 // Labels refer to positions in the (to be) generated code. 407 // There are bound, linked, and unused labels. 408 // 409 // Bound labels refer to known positions in the already 410 // generated code. pos() is the position the label refers to. 411 // 412 // Linked labels refer to unknown positions in the code 413 // to be generated; pos() is the position of the last 414 // instruction using the label. 415 416 417 // The link chain is terminated by a negative code position (must be aligned) 418 const int kEndOfChain = -4; 419 420 421 // Dummy opcodes for unbound label mov instructions or jump table entries. 422 enum { 423 kUnboundMovLabelOffsetOpcode = 0 << 26, 424 kUnboundAddLabelOffsetOpcode = 1 << 26, 425 kUnboundAddLabelLongOffsetOpcode = 2 << 26, 426 kUnboundMovLabelAddrOpcode = 3 << 26, 427 kUnboundJumpTableEntryOpcode = 4 << 26 428 }; 429 430 int Assembler::target_at(int pos) { 431 Instr instr = instr_at(pos); 432 // check which type of branch this is 16 or 26 bit offset 433 uint32_t opcode = instr & kOpcodeMask; 434 int link; 435 switch (opcode) { 436 case BX: 437 link = SIGN_EXT_IMM26(instr & kImm26Mask); 438 link &= ~(kAAMask | kLKMask); // discard AA|LK bits if present 439 break; 440 case BCX: 441 link = SIGN_EXT_IMM16((instr & kImm16Mask)); 442 link &= ~(kAAMask | kLKMask); // discard AA|LK bits if present 443 break; 444 case kUnboundMovLabelOffsetOpcode: 445 case kUnboundAddLabelOffsetOpcode: 446 case kUnboundAddLabelLongOffsetOpcode: 447 case kUnboundMovLabelAddrOpcode: 448 case kUnboundJumpTableEntryOpcode: 449 link = SIGN_EXT_IMM26(instr & kImm26Mask); 450 link <<= 2; 451 break; 452 default: 453 DCHECK(false); 454 return -1; 455 } 456 457 if (link == 0) return kEndOfChain; 458 return pos + link; 459 } 460 461 462 void Assembler::target_at_put(int pos, int target_pos, bool* is_branch) { 463 Instr instr = instr_at(pos); 464 uint32_t opcode = instr & kOpcodeMask; 465 466 if (is_branch != nullptr) { 467 *is_branch = (opcode == BX || opcode == BCX); 468 } 469 470 switch (opcode) { 471 case BX: { 472 int imm26 = target_pos - pos; 473 CHECK(is_int26(imm26) && (imm26 & (kAAMask | kLKMask)) == 0); 474 if (imm26 == kInstrSize && !(instr & kLKMask)) { 475 // Branch to next instr without link. 476 instr = ORI; // nop: ori, 0,0,0 477 } else { 478 instr &= ((~kImm26Mask) | kAAMask | kLKMask); 479 instr |= (imm26 & kImm26Mask); 480 } 481 instr_at_put(pos, instr); 482 break; 483 } 484 case BCX: { 485 int imm16 = target_pos - pos; 486 CHECK(is_int16(imm16) && (imm16 & (kAAMask | kLKMask)) == 0); 487 if (imm16 == kInstrSize && !(instr & kLKMask)) { 488 // Branch to next instr without link. 489 instr = ORI; // nop: ori, 0,0,0 490 } else { 491 instr &= ((~kImm16Mask) | kAAMask | kLKMask); 492 instr |= (imm16 & kImm16Mask); 493 } 494 instr_at_put(pos, instr); 495 break; 496 } 497 case kUnboundMovLabelOffsetOpcode: { 498 // Load the position of the label relative to the generated code object 499 // pointer in a register. 500 Register dst = Register::from_code(instr_at(pos + kInstrSize)); 501 int32_t offset = target_pos + (Code::kHeaderSize - kHeapObjectTag); 502 PatchingAssembler patcher(options(), 503 reinterpret_cast<byte*>(buffer_ + pos), 2); 504 patcher.bitwise_mov32(dst, offset); 505 break; 506 } 507 case kUnboundAddLabelLongOffsetOpcode: 508 case kUnboundAddLabelOffsetOpcode: { 509 // dst = base + position + immediate 510 Instr operands = instr_at(pos + kInstrSize); 511 Register dst = Register::from_code((operands >> 27) & 0x1F); 512 Register base = Register::from_code((operands >> 22) & 0x1F); 513 int32_t delta = (opcode == kUnboundAddLabelLongOffsetOpcode) 514 ? static_cast<int32_t>(instr_at(pos + 2 * kInstrSize)) 515 : (SIGN_EXT_IMM22(operands & kImm22Mask)); 516 int32_t offset = target_pos + delta; 517 PatchingAssembler patcher( 518 options(), reinterpret_cast<byte*>(buffer_ + pos), 519 2 + static_cast<int32_t>(opcode == kUnboundAddLabelLongOffsetOpcode)); 520 patcher.bitwise_add32(dst, base, offset); 521 if (opcode == kUnboundAddLabelLongOffsetOpcode) patcher.nop(); 522 break; 523 } 524 case kUnboundMovLabelAddrOpcode: { 525 // Load the address of the label in a register. 526 Register dst = Register::from_code(instr_at(pos + kInstrSize)); 527 PatchingAssembler patcher(options(), 528 reinterpret_cast<byte*>(buffer_ + pos), 529 kMovInstructionsNoConstantPool); 530 // Keep internal references relative until EmitRelocations. 531 patcher.bitwise_mov(dst, target_pos); 532 break; 533 } 534 case kUnboundJumpTableEntryOpcode: { 535 PatchingAssembler patcher(options(), 536 reinterpret_cast<byte*>(buffer_ + pos), 537 kPointerSize / kInstrSize); 538 // Keep internal references relative until EmitRelocations. 539 patcher.dp(target_pos); 540 break; 541 } 542 default: 543 DCHECK(false); 544 break; 545 } 546 } 547 548 549 int Assembler::max_reach_from(int pos) { 550 Instr instr = instr_at(pos); 551 uint32_t opcode = instr & kOpcodeMask; 552 553 // check which type of branch this is 16 or 26 bit offset 554 switch (opcode) { 555 case BX: 556 return 26; 557 case BCX: 558 return 16; 559 case kUnboundMovLabelOffsetOpcode: 560 case kUnboundAddLabelOffsetOpcode: 561 case kUnboundMovLabelAddrOpcode: 562 case kUnboundJumpTableEntryOpcode: 563 return 0; // no limit on reach 564 } 565 566 DCHECK(false); 567 return 0; 568 } 569 570 571 void Assembler::bind_to(Label* L, int pos) { 572 DCHECK(0 <= pos && pos <= pc_offset()); // must have a valid binding position 573 int32_t trampoline_pos = kInvalidSlotPos; 574 bool is_branch = false; 575 while (L->is_linked()) { 576 int fixup_pos = L->pos(); 577 int32_t offset = pos - fixup_pos; 578 int maxReach = max_reach_from(fixup_pos); 579 next(L); // call next before overwriting link with target at fixup_pos 580 if (maxReach && is_intn(offset, maxReach) == false) { 581 if (trampoline_pos == kInvalidSlotPos) { 582 trampoline_pos = get_trampoline_entry(); 583 CHECK_NE(trampoline_pos, kInvalidSlotPos); 584 target_at_put(trampoline_pos, pos); 585 } 586 target_at_put(fixup_pos, trampoline_pos); 587 } else { 588 target_at_put(fixup_pos, pos, &is_branch); 589 } 590 } 591 L->bind_to(pos); 592 593 if (!trampoline_emitted_ && is_branch) { 594 UntrackBranch(); 595 } 596 597 // Keep track of the last bound label so we don't eliminate any instructions 598 // before a bound label. 599 if (pos > last_bound_pos_) last_bound_pos_ = pos; 600 } 601 602 603 void Assembler::bind(Label* L) { 604 DCHECK(!L->is_bound()); // label can only be bound once 605 bind_to(L, pc_offset()); 606 } 607 608 609 void Assembler::next(Label* L) { 610 DCHECK(L->is_linked()); 611 int link = target_at(L->pos()); 612 if (link == kEndOfChain) { 613 L->Unuse(); 614 } else { 615 DCHECK_GE(link, 0); 616 L->link_to(link); 617 } 618 } 619 620 621 bool Assembler::is_near(Label* L, Condition cond) { 622 DCHECK(L->is_bound()); 623 if (L->is_bound() == false) return false; 624 625 int maxReach = ((cond == al) ? 26 : 16); 626 int offset = L->pos() - pc_offset(); 627 628 return is_intn(offset, maxReach); 629 } 630 631 632 void Assembler::a_form(Instr instr, DoubleRegister frt, DoubleRegister fra, 633 DoubleRegister frb, RCBit r) { 634 emit(instr | frt.code() * B21 | fra.code() * B16 | frb.code() * B11 | r); 635 } 636 637 638 void Assembler::d_form(Instr instr, Register rt, Register ra, 639 const intptr_t val, bool signed_disp) { 640 if (signed_disp) { 641 if (!is_int16(val)) { 642 PrintF("val = %" V8PRIdPTR ", 0x%" V8PRIxPTR "\n", val, val); 643 } 644 CHECK(is_int16(val)); 645 } else { 646 if (!is_uint16(val)) { 647 PrintF("val = %" V8PRIdPTR ", 0x%" V8PRIxPTR 648 ", is_unsigned_imm16(val)=%d, kImm16Mask=0x%x\n", 649 val, val, is_uint16(val), kImm16Mask); 650 } 651 CHECK(is_uint16(val)); 652 } 653 emit(instr | rt.code() * B21 | ra.code() * B16 | (kImm16Mask & val)); 654 } 655 656 void Assembler::xo_form(Instr instr, Register rt, Register ra, Register rb, 657 OEBit o, RCBit r) { 658 emit(instr | rt.code() * B21 | ra.code() * B16 | rb.code() * B11 | o | r); 659 } 660 661 void Assembler::md_form(Instr instr, Register ra, Register rs, int shift, 662 int maskbit, RCBit r) { 663 int sh0_4 = shift & 0x1F; 664 int sh5 = (shift >> 5) & 0x1; 665 int m0_4 = maskbit & 0x1F; 666 int m5 = (maskbit >> 5) & 0x1; 667 668 emit(instr | rs.code() * B21 | ra.code() * B16 | sh0_4 * B11 | m0_4 * B6 | 669 m5 * B5 | sh5 * B1 | r); 670 } 671 672 673 void Assembler::mds_form(Instr instr, Register ra, Register rs, Register rb, 674 int maskbit, RCBit r) { 675 int m0_4 = maskbit & 0x1F; 676 int m5 = (maskbit >> 5) & 0x1; 677 678 emit(instr | rs.code() * B21 | ra.code() * B16 | rb.code() * B11 | m0_4 * B6 | 679 m5 * B5 | r); 680 } 681 682 683 // Returns the next free trampoline entry. 684 int32_t Assembler::get_trampoline_entry() { 685 int32_t trampoline_entry = kInvalidSlotPos; 686 687 if (!internal_trampoline_exception_) { 688 trampoline_entry = trampoline_.take_slot(); 689 690 if (kInvalidSlotPos == trampoline_entry) { 691 internal_trampoline_exception_ = true; 692 } 693 } 694 return trampoline_entry; 695 } 696 697 698 int Assembler::link(Label* L) { 699 int position; 700 if (L->is_bound()) { 701 position = L->pos(); 702 } else { 703 if (L->is_linked()) { 704 position = L->pos(); // L's link 705 } else { 706 // was: target_pos = kEndOfChain; 707 // However, using self to mark the first reference 708 // should avoid most instances of branch offset overflow. See 709 // target_at() for where this is converted back to kEndOfChain. 710 position = pc_offset(); 711 } 712 L->link_to(pc_offset()); 713 } 714 715 return position; 716 } 717 718 719 // Branch instructions. 720 721 722 void Assembler::bclr(BOfield bo, int condition_bit, LKBit lk) { 723 emit(EXT1 | bo | condition_bit * B16 | BCLRX | lk); 724 } 725 726 727 void Assembler::bcctr(BOfield bo, int condition_bit, LKBit lk) { 728 emit(EXT1 | bo | condition_bit * B16 | BCCTRX | lk); 729 } 730 731 732 // Pseudo op - branch to link register 733 void Assembler::blr() { bclr(BA, 0, LeaveLK); } 734 735 736 // Pseudo op - branch to count register -- used for "jump" 737 void Assembler::bctr() { bcctr(BA, 0, LeaveLK); } 738 739 740 void Assembler::bctrl() { bcctr(BA, 0, SetLK); } 741 742 743 void Assembler::bc(int branch_offset, BOfield bo, int condition_bit, LKBit lk) { 744 int imm16 = branch_offset; 745 CHECK(is_int16(imm16) && (imm16 & (kAAMask | kLKMask)) == 0); 746 emit(BCX | bo | condition_bit * B16 | (imm16 & kImm16Mask) | lk); 747 } 748 749 750 void Assembler::b(int branch_offset, LKBit lk) { 751 int imm26 = branch_offset; 752 CHECK(is_int26(imm26) && (imm26 & (kAAMask | kLKMask)) == 0); 753 emit(BX | (imm26 & kImm26Mask) | lk); 754 } 755 756 757 void Assembler::xori(Register dst, Register src, const Operand& imm) { 758 d_form(XORI, src, dst, imm.immediate(), false); 759 } 760 761 762 void Assembler::xoris(Register ra, Register rs, const Operand& imm) { 763 d_form(XORIS, rs, ra, imm.immediate(), false); 764 } 765 766 767 void Assembler::rlwinm(Register ra, Register rs, int sh, int mb, int me, 768 RCBit rc) { 769 sh &= 0x1F; 770 mb &= 0x1F; 771 me &= 0x1F; 772 emit(RLWINMX | rs.code() * B21 | ra.code() * B16 | sh * B11 | mb * B6 | 773 me << 1 | rc); 774 } 775 776 777 void Assembler::rlwnm(Register ra, Register rs, Register rb, int mb, int me, 778 RCBit rc) { 779 mb &= 0x1F; 780 me &= 0x1F; 781 emit(RLWNMX | rs.code() * B21 | ra.code() * B16 | rb.code() * B11 | mb * B6 | 782 me << 1 | rc); 783 } 784 785 786 void Assembler::rlwimi(Register ra, Register rs, int sh, int mb, int me, 787 RCBit rc) { 788 sh &= 0x1F; 789 mb &= 0x1F; 790 me &= 0x1F; 791 emit(RLWIMIX | rs.code() * B21 | ra.code() * B16 | sh * B11 | mb * B6 | 792 me << 1 | rc); 793 } 794 795 796 void Assembler::slwi(Register dst, Register src, const Operand& val, RCBit rc) { 797 DCHECK((32 > val.immediate()) && (val.immediate() >= 0)); 798 rlwinm(dst, src, val.immediate(), 0, 31 - val.immediate(), rc); 799 } 800 801 802 void Assembler::srwi(Register dst, Register src, const Operand& val, RCBit rc) { 803 DCHECK((32 > val.immediate()) && (val.immediate() >= 0)); 804 rlwinm(dst, src, 32 - val.immediate(), val.immediate(), 31, rc); 805 } 806 807 808 void Assembler::clrrwi(Register dst, Register src, const Operand& val, 809 RCBit rc) { 810 DCHECK((32 > val.immediate()) && (val.immediate() >= 0)); 811 rlwinm(dst, src, 0, 0, 31 - val.immediate(), rc); 812 } 813 814 815 void Assembler::clrlwi(Register dst, Register src, const Operand& val, 816 RCBit rc) { 817 DCHECK((32 > val.immediate()) && (val.immediate() >= 0)); 818 rlwinm(dst, src, 0, val.immediate(), 31, rc); 819 } 820 821 822 void Assembler::rotlw(Register ra, Register rs, Register rb, RCBit r) { 823 rlwnm(ra, rs, rb, 0, 31, r); 824 } 825 826 827 void Assembler::rotlwi(Register ra, Register rs, int sh, RCBit r) { 828 rlwinm(ra, rs, sh, 0, 31, r); 829 } 830 831 832 void Assembler::rotrwi(Register ra, Register rs, int sh, RCBit r) { 833 rlwinm(ra, rs, 32 - sh, 0, 31, r); 834 } 835 836 837 void Assembler::subi(Register dst, Register src, const Operand& imm) { 838 addi(dst, src, Operand(-(imm.immediate()))); 839 } 840 841 void Assembler::addc(Register dst, Register src1, Register src2, OEBit o, 842 RCBit r) { 843 xo_form(EXT2 | ADDCX, dst, src1, src2, o, r); 844 } 845 846 void Assembler::adde(Register dst, Register src1, Register src2, OEBit o, 847 RCBit r) { 848 xo_form(EXT2 | ADDEX, dst, src1, src2, o, r); 849 } 850 851 void Assembler::addze(Register dst, Register src1, OEBit o, RCBit r) { 852 // a special xo_form 853 emit(EXT2 | ADDZEX | dst.code() * B21 | src1.code() * B16 | o | r); 854 } 855 856 857 void Assembler::sub(Register dst, Register src1, Register src2, OEBit o, 858 RCBit r) { 859 xo_form(EXT2 | SUBFX, dst, src2, src1, o, r); 860 } 861 862 void Assembler::subc(Register dst, Register src1, Register src2, OEBit o, 863 RCBit r) { 864 xo_form(EXT2 | SUBFCX, dst, src2, src1, o, r); 865 } 866 867 void Assembler::sube(Register dst, Register src1, Register src2, OEBit o, 868 RCBit r) { 869 xo_form(EXT2 | SUBFEX, dst, src2, src1, o, r); 870 } 871 872 void Assembler::subfic(Register dst, Register src, const Operand& imm) { 873 d_form(SUBFIC, dst, src, imm.immediate(), true); 874 } 875 876 877 void Assembler::add(Register dst, Register src1, Register src2, OEBit o, 878 RCBit r) { 879 xo_form(EXT2 | ADDX, dst, src1, src2, o, r); 880 } 881 882 883 // Multiply low word 884 void Assembler::mullw(Register dst, Register src1, Register src2, OEBit o, 885 RCBit r) { 886 xo_form(EXT2 | MULLW, dst, src1, src2, o, r); 887 } 888 889 890 // Multiply hi word 891 void Assembler::mulhw(Register dst, Register src1, Register src2, RCBit r) { 892 xo_form(EXT2 | MULHWX, dst, src1, src2, LeaveOE, r); 893 } 894 895 896 // Multiply hi word unsigned 897 void Assembler::mulhwu(Register dst, Register src1, Register src2, RCBit r) { 898 xo_form(EXT2 | MULHWUX, dst, src1, src2, LeaveOE, r); 899 } 900 901 902 // Divide word 903 void Assembler::divw(Register dst, Register src1, Register src2, OEBit o, 904 RCBit r) { 905 xo_form(EXT2 | DIVW, dst, src1, src2, o, r); 906 } 907 908 909 // Divide word unsigned 910 void Assembler::divwu(Register dst, Register src1, Register src2, OEBit o, 911 RCBit r) { 912 xo_form(EXT2 | DIVWU, dst, src1, src2, o, r); 913 } 914 915 916 void Assembler::addi(Register dst, Register src, const Operand& imm) { 917 DCHECK(src != r0); // use li instead to show intent 918 d_form(ADDI, dst, src, imm.immediate(), true); 919 } 920 921 922 void Assembler::addis(Register dst, Register src, const Operand& imm) { 923 DCHECK(src != r0); // use lis instead to show intent 924 d_form(ADDIS, dst, src, imm.immediate(), true); 925 } 926 927 928 void Assembler::addic(Register dst, Register src, const Operand& imm) { 929 d_form(ADDIC, dst, src, imm.immediate(), true); 930 } 931 932 933 void Assembler::andi(Register ra, Register rs, const Operand& imm) { 934 d_form(ANDIx, rs, ra, imm.immediate(), false); 935 } 936 937 938 void Assembler::andis(Register ra, Register rs, const Operand& imm) { 939 d_form(ANDISx, rs, ra, imm.immediate(), false); 940 } 941 942 943 void Assembler::ori(Register ra, Register rs, const Operand& imm) { 944 d_form(ORI, rs, ra, imm.immediate(), false); 945 } 946 947 948 void Assembler::oris(Register dst, Register src, const Operand& imm) { 949 d_form(ORIS, src, dst, imm.immediate(), false); 950 } 951 952 953 void Assembler::cmpi(Register src1, const Operand& src2, CRegister cr) { 954 intptr_t imm16 = src2.immediate(); 955 #if V8_TARGET_ARCH_PPC64 956 int L = 1; 957 #else 958 int L = 0; 959 #endif 960 DCHECK(is_int16(imm16)); 961 DCHECK(cr.code() >= 0 && cr.code() <= 7); 962 imm16 &= kImm16Mask; 963 emit(CMPI | cr.code() * B23 | L * B21 | src1.code() * B16 | imm16); 964 } 965 966 967 void Assembler::cmpli(Register src1, const Operand& src2, CRegister cr) { 968 uintptr_t uimm16 = src2.immediate(); 969 #if V8_TARGET_ARCH_PPC64 970 int L = 1; 971 #else 972 int L = 0; 973 #endif 974 DCHECK(is_uint16(uimm16)); 975 DCHECK(cr.code() >= 0 && cr.code() <= 7); 976 uimm16 &= kImm16Mask; 977 emit(CMPLI | cr.code() * B23 | L * B21 | src1.code() * B16 | uimm16); 978 } 979 980 981 void Assembler::cmpwi(Register src1, const Operand& src2, CRegister cr) { 982 intptr_t imm16 = src2.immediate(); 983 int L = 0; 984 int pos = pc_offset(); 985 DCHECK(is_int16(imm16)); 986 DCHECK(cr.code() >= 0 && cr.code() <= 7); 987 imm16 &= kImm16Mask; 988 989 // For cmpwi against 0, save postition and cr for later examination 990 // of potential optimization. 991 if (imm16 == 0 && pos > 0 && last_bound_pos_ != pos) { 992 optimizable_cmpi_pos_ = pos; 993 cmpi_cr_ = cr; 994 } 995 emit(CMPI | cr.code() * B23 | L * B21 | src1.code() * B16 | imm16); 996 } 997 998 999 void Assembler::cmplwi(Register src1, const Operand& src2, CRegister cr) { 1000 uintptr_t uimm16 = src2.immediate(); 1001 int L = 0; 1002 DCHECK(is_uint16(uimm16)); 1003 DCHECK(cr.code() >= 0 && cr.code() <= 7); 1004 uimm16 &= kImm16Mask; 1005 emit(CMPLI | cr.code() * B23 | L * B21 | src1.code() * B16 | uimm16); 1006 } 1007 1008 1009 void Assembler::isel(Register rt, Register ra, Register rb, int cb) { 1010 emit(EXT2 | ISEL | rt.code() * B21 | ra.code() * B16 | rb.code() * B11 | 1011 cb * B6); 1012 } 1013 1014 1015 // Pseudo op - load immediate 1016 void Assembler::li(Register dst, const Operand& imm) { 1017 d_form(ADDI, dst, r0, imm.immediate(), true); 1018 } 1019 1020 1021 void Assembler::lis(Register dst, const Operand& imm) { 1022 d_form(ADDIS, dst, r0, imm.immediate(), true); 1023 } 1024 1025 1026 // Pseudo op - move register 1027 void Assembler::mr(Register dst, Register src) { 1028 // actually or(dst, src, src) 1029 orx(dst, src, src); 1030 } 1031 1032 1033 void Assembler::lbz(Register dst, const MemOperand& src) { 1034 DCHECK(src.ra_ != r0); 1035 d_form(LBZ, dst, src.ra(), src.offset(), true); 1036 } 1037 1038 1039 void Assembler::lhz(Register dst, const MemOperand& src) { 1040 DCHECK(src.ra_ != r0); 1041 d_form(LHZ, dst, src.ra(), src.offset(), true); 1042 } 1043 1044 1045 void Assembler::lwz(Register dst, const MemOperand& src) { 1046 DCHECK(src.ra_ != r0); 1047 d_form(LWZ, dst, src.ra(), src.offset(), true); 1048 } 1049 1050 1051 void Assembler::lwzu(Register dst, const MemOperand& src) { 1052 DCHECK(src.ra_ != r0); 1053 d_form(LWZU, dst, src.ra(), src.offset(), true); 1054 } 1055 1056 1057 void Assembler::lha(Register dst, const MemOperand& src) { 1058 DCHECK(src.ra_ != r0); 1059 d_form(LHA, dst, src.ra(), src.offset(), true); 1060 } 1061 1062 1063 void Assembler::lwa(Register dst, const MemOperand& src) { 1064 #if V8_TARGET_ARCH_PPC64 1065 int offset = src.offset(); 1066 DCHECK(src.ra_ != r0); 1067 CHECK(!(offset & 3) && is_int16(offset)); 1068 offset = kImm16Mask & offset; 1069 emit(LD | dst.code() * B21 | src.ra().code() * B16 | offset | 2); 1070 #else 1071 lwz(dst, src); 1072 #endif 1073 } 1074 1075 void Assembler::stb(Register dst, const MemOperand& src) { 1076 DCHECK(src.ra_ != r0); 1077 d_form(STB, dst, src.ra(), src.offset(), true); 1078 } 1079 1080 1081 void Assembler::sth(Register dst, const MemOperand& src) { 1082 DCHECK(src.ra_ != r0); 1083 d_form(STH, dst, src.ra(), src.offset(), true); 1084 } 1085 1086 1087 void Assembler::stw(Register dst, const MemOperand& src) { 1088 DCHECK(src.ra_ != r0); 1089 d_form(STW, dst, src.ra(), src.offset(), true); 1090 } 1091 1092 1093 void Assembler::stwu(Register dst, const MemOperand& src) { 1094 DCHECK(src.ra_ != r0); 1095 d_form(STWU, dst, src.ra(), src.offset(), true); 1096 } 1097 1098 1099 void Assembler::neg(Register rt, Register ra, OEBit o, RCBit r) { 1100 emit(EXT2 | NEGX | rt.code() * B21 | ra.code() * B16 | o | r); 1101 } 1102 1103 1104 #if V8_TARGET_ARCH_PPC64 1105 // 64bit specific instructions 1106 void Assembler::ld(Register rd, const MemOperand& src) { 1107 int offset = src.offset(); 1108 DCHECK(src.ra_ != r0); 1109 CHECK(!(offset & 3) && is_int16(offset)); 1110 offset = kImm16Mask & offset; 1111 emit(LD | rd.code() * B21 | src.ra().code() * B16 | offset); 1112 } 1113 1114 1115 void Assembler::ldu(Register rd, const MemOperand& src) { 1116 int offset = src.offset(); 1117 DCHECK(src.ra_ != r0); 1118 CHECK(!(offset & 3) && is_int16(offset)); 1119 offset = kImm16Mask & offset; 1120 emit(LD | rd.code() * B21 | src.ra().code() * B16 | offset | 1); 1121 } 1122 1123 1124 void Assembler::std(Register rs, const MemOperand& src) { 1125 int offset = src.offset(); 1126 DCHECK(src.ra_ != r0); 1127 CHECK(!(offset & 3) && is_int16(offset)); 1128 offset = kImm16Mask & offset; 1129 emit(STD | rs.code() * B21 | src.ra().code() * B16 | offset); 1130 } 1131 1132 1133 void Assembler::stdu(Register rs, const MemOperand& src) { 1134 int offset = src.offset(); 1135 DCHECK(src.ra_ != r0); 1136 CHECK(!(offset & 3) && is_int16(offset)); 1137 offset = kImm16Mask & offset; 1138 emit(STD | rs.code() * B21 | src.ra().code() * B16 | offset | 1); 1139 } 1140 1141 1142 void Assembler::rldic(Register ra, Register rs, int sh, int mb, RCBit r) { 1143 md_form(EXT5 | RLDIC, ra, rs, sh, mb, r); 1144 } 1145 1146 1147 void Assembler::rldicl(Register ra, Register rs, int sh, int mb, RCBit r) { 1148 md_form(EXT5 | RLDICL, ra, rs, sh, mb, r); 1149 } 1150 1151 1152 void Assembler::rldcl(Register ra, Register rs, Register rb, int mb, RCBit r) { 1153 mds_form(EXT5 | RLDCL, ra, rs, rb, mb, r); 1154 } 1155 1156 1157 void Assembler::rldicr(Register ra, Register rs, int sh, int me, RCBit r) { 1158 md_form(EXT5 | RLDICR, ra, rs, sh, me, r); 1159 } 1160 1161 1162 void Assembler::sldi(Register dst, Register src, const Operand& val, RCBit rc) { 1163 DCHECK((64 > val.immediate()) && (val.immediate() >= 0)); 1164 rldicr(dst, src, val.immediate(), 63 - val.immediate(), rc); 1165 } 1166 1167 1168 void Assembler::srdi(Register dst, Register src, const Operand& val, RCBit rc) { 1169 DCHECK((64 > val.immediate()) && (val.immediate() >= 0)); 1170 rldicl(dst, src, 64 - val.immediate(), val.immediate(), rc); 1171 } 1172 1173 1174 void Assembler::clrrdi(Register dst, Register src, const Operand& val, 1175 RCBit rc) { 1176 DCHECK((64 > val.immediate()) && (val.immediate() >= 0)); 1177 rldicr(dst, src, 0, 63 - val.immediate(), rc); 1178 } 1179 1180 1181 void Assembler::clrldi(Register dst, Register src, const Operand& val, 1182 RCBit rc) { 1183 DCHECK((64 > val.immediate()) && (val.immediate() >= 0)); 1184 rldicl(dst, src, 0, val.immediate(), rc); 1185 } 1186 1187 1188 void Assembler::rldimi(Register ra, Register rs, int sh, int mb, RCBit r) { 1189 md_form(EXT5 | RLDIMI, ra, rs, sh, mb, r); 1190 } 1191 1192 1193 void Assembler::sradi(Register ra, Register rs, int sh, RCBit r) { 1194 int sh0_4 = sh & 0x1F; 1195 int sh5 = (sh >> 5) & 0x1; 1196 1197 emit(EXT2 | SRADIX | rs.code() * B21 | ra.code() * B16 | sh0_4 * B11 | 1198 sh5 * B1 | r); 1199 } 1200 1201 1202 void Assembler::rotld(Register ra, Register rs, Register rb, RCBit r) { 1203 rldcl(ra, rs, rb, 0, r); 1204 } 1205 1206 1207 void Assembler::rotldi(Register ra, Register rs, int sh, RCBit r) { 1208 rldicl(ra, rs, sh, 0, r); 1209 } 1210 1211 1212 void Assembler::rotrdi(Register ra, Register rs, int sh, RCBit r) { 1213 rldicl(ra, rs, 64 - sh, 0, r); 1214 } 1215 1216 1217 void Assembler::mulld(Register dst, Register src1, Register src2, OEBit o, 1218 RCBit r) { 1219 xo_form(EXT2 | MULLD, dst, src1, src2, o, r); 1220 } 1221 1222 1223 void Assembler::divd(Register dst, Register src1, Register src2, OEBit o, 1224 RCBit r) { 1225 xo_form(EXT2 | DIVD, dst, src1, src2, o, r); 1226 } 1227 1228 1229 void Assembler::divdu(Register dst, Register src1, Register src2, OEBit o, 1230 RCBit r) { 1231 xo_form(EXT2 | DIVDU, dst, src1, src2, o, r); 1232 } 1233 #endif 1234 1235 1236 // Function descriptor for AIX. 1237 // Code address skips the function descriptor "header". 1238 // TOC and static chain are ignored and set to 0. 1239 void Assembler::function_descriptor() { 1240 if (ABI_USES_FUNCTION_DESCRIPTORS) { 1241 Label instructions; 1242 DCHECK_EQ(pc_offset(), 0); 1243 emit_label_addr(&instructions); 1244 dp(0); 1245 dp(0); 1246 bind(&instructions); 1247 } 1248 } 1249 1250 1251 int Assembler::instructions_required_for_mov(Register dst, 1252 const Operand& src) const { 1253 bool canOptimize = 1254 !(src.must_output_reloc_info(this) || is_trampoline_pool_blocked()); 1255 if (use_constant_pool_for_mov(dst, src, canOptimize)) { 1256 if (ConstantPoolAccessIsInOverflow()) { 1257 return kMovInstructionsConstantPool + 1; 1258 } 1259 return kMovInstructionsConstantPool; 1260 } 1261 DCHECK(!canOptimize); 1262 return kMovInstructionsNoConstantPool; 1263 } 1264 1265 1266 bool Assembler::use_constant_pool_for_mov(Register dst, const Operand& src, 1267 bool canOptimize) const { 1268 if (!FLAG_enable_embedded_constant_pool || !is_constant_pool_available()) { 1269 // If there is no constant pool available, we must use a mov 1270 // immediate sequence. 1271 return false; 1272 } 1273 intptr_t value = src.immediate(); 1274 #if V8_TARGET_ARCH_PPC64 1275 bool allowOverflow = !((canOptimize && is_int32(value)) || dst == r0); 1276 #else 1277 bool allowOverflow = !(canOptimize || dst == r0); 1278 #endif 1279 if (canOptimize && is_int16(value)) { 1280 // Prefer a single-instruction load-immediate. 1281 return false; 1282 } 1283 if (!allowOverflow && ConstantPoolAccessIsInOverflow()) { 1284 // Prefer non-relocatable two-instruction bitwise-mov32 over 1285 // overflow sequence. 1286 return false; 1287 } 1288 1289 return true; 1290 } 1291 1292 1293 void Assembler::EnsureSpaceFor(int space_needed) { 1294 if (buffer_space() <= (kGap + space_needed)) { 1295 GrowBuffer(space_needed); 1296 } 1297 } 1298 1299 1300 bool Operand::must_output_reloc_info(const Assembler* assembler) const { 1301 if (rmode_ == RelocInfo::EXTERNAL_REFERENCE) { 1302 if (assembler != nullptr && assembler->predictable_code_size()) return true; 1303 return assembler->options().record_reloc_info_for_serialization; 1304 } else if (RelocInfo::IsNone(rmode_)) { 1305 return false; 1306 } 1307 return true; 1308 } 1309 1310 1311 // Primarily used for loading constants 1312 // This should really move to be in macro-assembler as it 1313 // is really a pseudo instruction 1314 // Some usages of this intend for a FIXED_SEQUENCE to be used 1315 // Todo - break this dependency so we can optimize mov() in general 1316 // and only use the generic version when we require a fixed sequence 1317 void Assembler::mov(Register dst, const Operand& src) { 1318 intptr_t value; 1319 if (src.IsHeapObjectRequest()) { 1320 RequestHeapObject(src.heap_object_request()); 1321 value = 0; 1322 } else { 1323 value = src.immediate(); 1324 } 1325 bool relocatable = src.must_output_reloc_info(this); 1326 bool canOptimize; 1327 1328 canOptimize = 1329 !(relocatable || (is_trampoline_pool_blocked() && !is_int16(value))); 1330 1331 if (!src.IsHeapObjectRequest() && 1332 use_constant_pool_for_mov(dst, src, canOptimize)) { 1333 DCHECK(is_constant_pool_available()); 1334 if (relocatable) { 1335 RecordRelocInfo(src.rmode_); 1336 } 1337 ConstantPoolEntry::Access access = ConstantPoolAddEntry(src.rmode_, value); 1338 #if V8_TARGET_ARCH_PPC64 1339 if (access == ConstantPoolEntry::OVERFLOWED) { 1340 addis(dst, kConstantPoolRegister, Operand::Zero()); 1341 ld(dst, MemOperand(dst, 0)); 1342 } else { 1343 ld(dst, MemOperand(kConstantPoolRegister, 0)); 1344 } 1345 #else 1346 if (access == ConstantPoolEntry::OVERFLOWED) { 1347 addis(dst, kConstantPoolRegister, Operand::Zero()); 1348 lwz(dst, MemOperand(dst, 0)); 1349 } else { 1350 lwz(dst, MemOperand(kConstantPoolRegister, 0)); 1351 } 1352 #endif 1353 return; 1354 } 1355 1356 if (canOptimize) { 1357 if (is_int16(value)) { 1358 li(dst, Operand(value)); 1359 } else { 1360 uint16_t u16; 1361 #if V8_TARGET_ARCH_PPC64 1362 if (is_int32(value)) { 1363 #endif 1364 lis(dst, Operand(value >> 16)); 1365 #if V8_TARGET_ARCH_PPC64 1366 } else { 1367 if (is_int48(value)) { 1368 li(dst, Operand(value >> 32)); 1369 } else { 1370 lis(dst, Operand(value >> 48)); 1371 u16 = ((value >> 32) & 0xFFFF); 1372 if (u16) { 1373 ori(dst, dst, Operand(u16)); 1374 } 1375 } 1376 sldi(dst, dst, Operand(32)); 1377 u16 = ((value >> 16) & 0xFFFF); 1378 if (u16) { 1379 oris(dst, dst, Operand(u16)); 1380 } 1381 } 1382 #endif 1383 u16 = (value & 0xFFFF); 1384 if (u16) { 1385 ori(dst, dst, Operand(u16)); 1386 } 1387 } 1388 return; 1389 } 1390 1391 DCHECK(!canOptimize); 1392 if (relocatable) { 1393 RecordRelocInfo(src.rmode_); 1394 } 1395 bitwise_mov(dst, value); 1396 } 1397 1398 1399 void Assembler::bitwise_mov(Register dst, intptr_t value) { 1400 BlockTrampolinePoolScope block_trampoline_pool(this); 1401 #if V8_TARGET_ARCH_PPC64 1402 int32_t hi_32 = static_cast<int32_t>(value >> 32); 1403 int32_t lo_32 = static_cast<int32_t>(value); 1404 int hi_word = static_cast<int>(hi_32 >> 16); 1405 int lo_word = static_cast<int>(hi_32 & 0xFFFF); 1406 lis(dst, Operand(SIGN_EXT_IMM16(hi_word))); 1407 ori(dst, dst, Operand(lo_word)); 1408 sldi(dst, dst, Operand(32)); 1409 hi_word = static_cast<int>(((lo_32 >> 16) & 0xFFFF)); 1410 lo_word = static_cast<int>(lo_32 & 0xFFFF); 1411 oris(dst, dst, Operand(hi_word)); 1412 ori(dst, dst, Operand(lo_word)); 1413 #else 1414 int hi_word = static_cast<int>(value >> 16); 1415 int lo_word = static_cast<int>(value & 0xFFFF); 1416 lis(dst, Operand(SIGN_EXT_IMM16(hi_word))); 1417 ori(dst, dst, Operand(lo_word)); 1418 #endif 1419 } 1420 1421 1422 void Assembler::bitwise_mov32(Register dst, int32_t value) { 1423 BlockTrampolinePoolScope block_trampoline_pool(this); 1424 int hi_word = static_cast<int>(value >> 16); 1425 int lo_word = static_cast<int>(value & 0xFFFF); 1426 lis(dst, Operand(SIGN_EXT_IMM16(hi_word))); 1427 ori(dst, dst, Operand(lo_word)); 1428 } 1429 1430 1431 void Assembler::bitwise_add32(Register dst, Register src, int32_t value) { 1432 BlockTrampolinePoolScope block_trampoline_pool(this); 1433 if (is_int16(value)) { 1434 addi(dst, src, Operand(value)); 1435 nop(); 1436 } else { 1437 int hi_word = static_cast<int>(value >> 16); 1438 int lo_word = static_cast<int>(value & 0xFFFF); 1439 if (lo_word & 0x8000) hi_word++; 1440 addis(dst, src, Operand(SIGN_EXT_IMM16(hi_word))); 1441 addic(dst, dst, Operand(SIGN_EXT_IMM16(lo_word))); 1442 } 1443 } 1444 1445 1446 void Assembler::mov_label_offset(Register dst, Label* label) { 1447 int position = link(label); 1448 if (label->is_bound()) { 1449 // Load the position of the label relative to the generated code object. 1450 mov(dst, Operand(position + Code::kHeaderSize - kHeapObjectTag)); 1451 } else { 1452 // Encode internal reference to unbound label. We use a dummy opcode 1453 // such that it won't collide with any opcode that might appear in the 1454 // label's chain. Encode the destination register in the 2nd instruction. 1455 int link = position - pc_offset(); 1456 DCHECK_EQ(0, link & 3); 1457 link >>= 2; 1458 DCHECK(is_int26(link)); 1459 1460 // When the label is bound, these instructions will be patched 1461 // with a 2 instruction mov sequence that will load the 1462 // destination register with the position of the label from the 1463 // beginning of the code. 1464 // 1465 // target_at extracts the link and target_at_put patches the instructions. 1466 BlockTrampolinePoolScope block_trampoline_pool(this); 1467 emit(kUnboundMovLabelOffsetOpcode | (link & kImm26Mask)); 1468 emit(dst.code()); 1469 } 1470 } 1471 1472 1473 void Assembler::add_label_offset(Register dst, Register base, Label* label, 1474 int delta) { 1475 int position = link(label); 1476 if (label->is_bound()) { 1477 // dst = base + position + delta 1478 position += delta; 1479 bitwise_add32(dst, base, position); 1480 } else { 1481 // Encode internal reference to unbound label. We use a dummy opcode 1482 // such that it won't collide with any opcode that might appear in the 1483 // label's chain. Encode the operands in the 2nd instruction. 1484 int link = position - pc_offset(); 1485 DCHECK_EQ(0, link & 3); 1486 link >>= 2; 1487 DCHECK(is_int26(link)); 1488 BlockTrampolinePoolScope block_trampoline_pool(this); 1489 1490 emit((is_int22(delta) ? kUnboundAddLabelOffsetOpcode 1491 : kUnboundAddLabelLongOffsetOpcode) | 1492 (link & kImm26Mask)); 1493 emit(dst.code() * B27 | base.code() * B22 | (delta & kImm22Mask)); 1494 1495 if (!is_int22(delta)) { 1496 emit(delta); 1497 } 1498 } 1499 } 1500 1501 1502 void Assembler::mov_label_addr(Register dst, Label* label) { 1503 CheckBuffer(); 1504 RecordRelocInfo(RelocInfo::INTERNAL_REFERENCE_ENCODED); 1505 int position = link(label); 1506 if (label->is_bound()) { 1507 // Keep internal references relative until EmitRelocations. 1508 bitwise_mov(dst, position); 1509 } else { 1510 // Encode internal reference to unbound label. We use a dummy opcode 1511 // such that it won't collide with any opcode that might appear in the 1512 // label's chain. Encode the destination register in the 2nd instruction. 1513 int link = position - pc_offset(); 1514 DCHECK_EQ(0, link & 3); 1515 link >>= 2; 1516 DCHECK(is_int26(link)); 1517 1518 // When the label is bound, these instructions will be patched 1519 // with a multi-instruction mov sequence that will load the 1520 // destination register with the address of the label. 1521 // 1522 // target_at extracts the link and target_at_put patches the instructions. 1523 BlockTrampolinePoolScope block_trampoline_pool(this); 1524 emit(kUnboundMovLabelAddrOpcode | (link & kImm26Mask)); 1525 emit(dst.code()); 1526 DCHECK_GE(kMovInstructionsNoConstantPool, 2); 1527 for (int i = 0; i < kMovInstructionsNoConstantPool - 2; i++) nop(); 1528 } 1529 } 1530 1531 1532 void Assembler::emit_label_addr(Label* label) { 1533 CheckBuffer(); 1534 RecordRelocInfo(RelocInfo::INTERNAL_REFERENCE); 1535 int position = link(label); 1536 if (label->is_bound()) { 1537 // Keep internal references relative until EmitRelocations. 1538 dp(position); 1539 } else { 1540 // Encode internal reference to unbound label. We use a dummy opcode 1541 // such that it won't collide with any opcode that might appear in the 1542 // label's chain. 1543 int link = position - pc_offset(); 1544 DCHECK_EQ(0, link & 3); 1545 link >>= 2; 1546 DCHECK(is_int26(link)); 1547 1548 // When the label is bound, the instruction(s) will be patched 1549 // as a jump table entry containing the label address. target_at extracts 1550 // the link and target_at_put patches the instruction(s). 1551 BlockTrampolinePoolScope block_trampoline_pool(this); 1552 emit(kUnboundJumpTableEntryOpcode | (link & kImm26Mask)); 1553 #if V8_TARGET_ARCH_PPC64 1554 nop(); 1555 #endif 1556 } 1557 } 1558 1559 1560 // Special register instructions 1561 void Assembler::crxor(int bt, int ba, int bb) { 1562 emit(EXT1 | CRXOR | bt * B21 | ba * B16 | bb * B11); 1563 } 1564 1565 1566 void Assembler::creqv(int bt, int ba, int bb) { 1567 emit(EXT1 | CREQV | bt * B21 | ba * B16 | bb * B11); 1568 } 1569 1570 1571 void Assembler::mflr(Register dst) { 1572 emit(EXT2 | MFSPR | dst.code() * B21 | 256 << 11); // Ignore RC bit 1573 } 1574 1575 1576 void Assembler::mtlr(Register src) { 1577 emit(EXT2 | MTSPR | src.code() * B21 | 256 << 11); // Ignore RC bit 1578 } 1579 1580 1581 void Assembler::mtctr(Register src) { 1582 emit(EXT2 | MTSPR | src.code() * B21 | 288 << 11); // Ignore RC bit 1583 } 1584 1585 1586 void Assembler::mtxer(Register src) { 1587 emit(EXT2 | MTSPR | src.code() * B21 | 32 << 11); 1588 } 1589 1590 1591 void Assembler::mcrfs(CRegister cr, FPSCRBit bit) { 1592 DCHECK_LT(static_cast<int>(bit), 32); 1593 int bf = cr.code(); 1594 int bfa = bit / CRWIDTH; 1595 emit(EXT4 | MCRFS | bf * B23 | bfa * B18); 1596 } 1597 1598 1599 void Assembler::mfcr(Register dst) { emit(EXT2 | MFCR | dst.code() * B21); } 1600 1601 1602 #if V8_TARGET_ARCH_PPC64 1603 void Assembler::mffprd(Register dst, DoubleRegister src) { 1604 emit(EXT2 | MFVSRD | src.code() * B21 | dst.code() * B16); 1605 } 1606 1607 1608 void Assembler::mffprwz(Register dst, DoubleRegister src) { 1609 emit(EXT2 | MFVSRWZ | src.code() * B21 | dst.code() * B16); 1610 } 1611 1612 1613 void Assembler::mtfprd(DoubleRegister dst, Register src) { 1614 emit(EXT2 | MTVSRD | dst.code() * B21 | src.code() * B16); 1615 } 1616 1617 1618 void Assembler::mtfprwz(DoubleRegister dst, Register src) { 1619 emit(EXT2 | MTVSRWZ | dst.code() * B21 | src.code() * B16); 1620 } 1621 1622 1623 void Assembler::mtfprwa(DoubleRegister dst, Register src) { 1624 emit(EXT2 | MTVSRWA | dst.code() * B21 | src.code() * B16); 1625 } 1626 #endif 1627 1628 1629 // Exception-generating instructions and debugging support. 1630 // Stops with a non-negative code less than kNumOfWatchedStops support 1631 // enabling/disabling and a counter feature. See simulator-ppc.h . 1632 void Assembler::stop(const char* msg, Condition cond, int32_t code, 1633 CRegister cr) { 1634 if (cond != al) { 1635 Label skip; 1636 b(NegateCondition(cond), &skip, cr); 1637 bkpt(0); 1638 bind(&skip); 1639 } else { 1640 bkpt(0); 1641 } 1642 } 1643 1644 void Assembler::bkpt(uint32_t imm16) { emit(0x7D821008); } 1645 1646 void Assembler::dcbf(Register ra, Register rb) { 1647 emit(EXT2 | DCBF | ra.code() * B16 | rb.code() * B11); 1648 } 1649 1650 1651 void Assembler::sync() { emit(EXT2 | SYNC); } 1652 1653 1654 void Assembler::lwsync() { emit(EXT2 | SYNC | 1 * B21); } 1655 1656 1657 void Assembler::icbi(Register ra, Register rb) { 1658 emit(EXT2 | ICBI | ra.code() * B16 | rb.code() * B11); 1659 } 1660 1661 1662 void Assembler::isync() { emit(EXT1 | ISYNC); } 1663 1664 1665 // Floating point support 1666 1667 void Assembler::lfd(const DoubleRegister frt, const MemOperand& src) { 1668 int offset = src.offset(); 1669 Register ra = src.ra(); 1670 DCHECK(ra != r0); 1671 CHECK(is_int16(offset)); 1672 int imm16 = offset & kImm16Mask; 1673 // could be x_form instruction with some casting magic 1674 emit(LFD | frt.code() * B21 | ra.code() * B16 | imm16); 1675 } 1676 1677 1678 void Assembler::lfdu(const DoubleRegister frt, const MemOperand& src) { 1679 int offset = src.offset(); 1680 Register ra = src.ra(); 1681 DCHECK(ra != r0); 1682 CHECK(is_int16(offset)); 1683 int imm16 = offset & kImm16Mask; 1684 // could be x_form instruction with some casting magic 1685 emit(LFDU | frt.code() * B21 | ra.code() * B16 | imm16); 1686 } 1687 1688 1689 void Assembler::lfs(const DoubleRegister frt, const MemOperand& src) { 1690 int offset = src.offset(); 1691 Register ra = src.ra(); 1692 CHECK(is_int16(offset)); 1693 DCHECK(ra != r0); 1694 int imm16 = offset & kImm16Mask; 1695 // could be x_form instruction with some casting magic 1696 emit(LFS | frt.code() * B21 | ra.code() * B16 | imm16); 1697 } 1698 1699 1700 void Assembler::lfsu(const DoubleRegister frt, const MemOperand& src) { 1701 int offset = src.offset(); 1702 Register ra = src.ra(); 1703 CHECK(is_int16(offset)); 1704 DCHECK(ra != r0); 1705 int imm16 = offset & kImm16Mask; 1706 // could be x_form instruction with some casting magic 1707 emit(LFSU | frt.code() * B21 | ra.code() * B16 | imm16); 1708 } 1709 1710 1711 void Assembler::stfd(const DoubleRegister frs, const MemOperand& src) { 1712 int offset = src.offset(); 1713 Register ra = src.ra(); 1714 CHECK(is_int16(offset)); 1715 DCHECK(ra != r0); 1716 int imm16 = offset & kImm16Mask; 1717 // could be x_form instruction with some casting magic 1718 emit(STFD | frs.code() * B21 | ra.code() * B16 | imm16); 1719 } 1720 1721 1722 void Assembler::stfdu(const DoubleRegister frs, const MemOperand& src) { 1723 int offset = src.offset(); 1724 Register ra = src.ra(); 1725 CHECK(is_int16(offset)); 1726 DCHECK(ra != r0); 1727 int imm16 = offset & kImm16Mask; 1728 // could be x_form instruction with some casting magic 1729 emit(STFDU | frs.code() * B21 | ra.code() * B16 | imm16); 1730 } 1731 1732 1733 void Assembler::stfs(const DoubleRegister frs, const MemOperand& src) { 1734 int offset = src.offset(); 1735 Register ra = src.ra(); 1736 CHECK(is_int16(offset)); 1737 DCHECK(ra != r0); 1738 int imm16 = offset & kImm16Mask; 1739 // could be x_form instruction with some casting magic 1740 emit(STFS | frs.code() * B21 | ra.code() * B16 | imm16); 1741 } 1742 1743 1744 void Assembler::stfsu(const DoubleRegister frs, const MemOperand& src) { 1745 int offset = src.offset(); 1746 Register ra = src.ra(); 1747 CHECK(is_int16(offset)); 1748 DCHECK(ra != r0); 1749 int imm16 = offset & kImm16Mask; 1750 // could be x_form instruction with some casting magic 1751 emit(STFSU | frs.code() * B21 | ra.code() * B16 | imm16); 1752 } 1753 1754 1755 void Assembler::fsub(const DoubleRegister frt, const DoubleRegister fra, 1756 const DoubleRegister frb, RCBit rc) { 1757 a_form(EXT4 | FSUB, frt, fra, frb, rc); 1758 } 1759 1760 1761 void Assembler::fadd(const DoubleRegister frt, const DoubleRegister fra, 1762 const DoubleRegister frb, RCBit rc) { 1763 a_form(EXT4 | FADD, frt, fra, frb, rc); 1764 } 1765 1766 1767 void Assembler::fmul(const DoubleRegister frt, const DoubleRegister fra, 1768 const DoubleRegister frc, RCBit rc) { 1769 emit(EXT4 | FMUL | frt.code() * B21 | fra.code() * B16 | frc.code() * B6 | 1770 rc); 1771 } 1772 1773 1774 void Assembler::fdiv(const DoubleRegister frt, const DoubleRegister fra, 1775 const DoubleRegister frb, RCBit rc) { 1776 a_form(EXT4 | FDIV, frt, fra, frb, rc); 1777 } 1778 1779 1780 void Assembler::fcmpu(const DoubleRegister fra, const DoubleRegister frb, 1781 CRegister cr) { 1782 DCHECK(cr.code() >= 0 && cr.code() <= 7); 1783 emit(EXT4 | FCMPU | cr.code() * B23 | fra.code() * B16 | frb.code() * B11); 1784 } 1785 1786 1787 void Assembler::fmr(const DoubleRegister frt, const DoubleRegister frb, 1788 RCBit rc) { 1789 emit(EXT4 | FMR | frt.code() * B21 | frb.code() * B11 | rc); 1790 } 1791 1792 1793 void Assembler::fctiwz(const DoubleRegister frt, const DoubleRegister frb) { 1794 emit(EXT4 | FCTIWZ | frt.code() * B21 | frb.code() * B11); 1795 } 1796 1797 1798 void Assembler::fctiw(const DoubleRegister frt, const DoubleRegister frb) { 1799 emit(EXT4 | FCTIW | frt.code() * B21 | frb.code() * B11); 1800 } 1801 1802 1803 void Assembler::frin(const DoubleRegister frt, const DoubleRegister frb, 1804 RCBit rc) { 1805 emit(EXT4 | FRIN | frt.code() * B21 | frb.code() * B11 | rc); 1806 } 1807 1808 1809 void Assembler::friz(const DoubleRegister frt, const DoubleRegister frb, 1810 RCBit rc) { 1811 emit(EXT4 | FRIZ | frt.code() * B21 | frb.code() * B11 | rc); 1812 } 1813 1814 1815 void Assembler::frip(const DoubleRegister frt, const DoubleRegister frb, 1816 RCBit rc) { 1817 emit(EXT4 | FRIP | frt.code() * B21 | frb.code() * B11 | rc); 1818 } 1819 1820 1821 void Assembler::frim(const DoubleRegister frt, const DoubleRegister frb, 1822 RCBit rc) { 1823 emit(EXT4 | FRIM | frt.code() * B21 | frb.code() * B11 | rc); 1824 } 1825 1826 1827 void Assembler::frsp(const DoubleRegister frt, const DoubleRegister frb, 1828 RCBit rc) { 1829 emit(EXT4 | FRSP | frt.code() * B21 | frb.code() * B11 | rc); 1830 } 1831 1832 1833 void Assembler::fcfid(const DoubleRegister frt, const DoubleRegister frb, 1834 RCBit rc) { 1835 emit(EXT4 | FCFID | frt.code() * B21 | frb.code() * B11 | rc); 1836 } 1837 1838 1839 void Assembler::fcfidu(const DoubleRegister frt, const DoubleRegister frb, 1840 RCBit rc) { 1841 emit(EXT4 | FCFIDU | frt.code() * B21 | frb.code() * B11 | rc); 1842 } 1843 1844 1845 void Assembler::fcfidus(const DoubleRegister frt, const DoubleRegister frb, 1846 RCBit rc) { 1847 emit(EXT3 | FCFIDUS | frt.code() * B21 | frb.code() * B11 | rc); 1848 } 1849 1850 1851 void Assembler::fcfids(const DoubleRegister frt, const DoubleRegister frb, 1852 RCBit rc) { 1853 emit(EXT3 | FCFIDS | frt.code() * B21 | frb.code() * B11 | rc); 1854 } 1855 1856 1857 void Assembler::fctid(const DoubleRegister frt, const DoubleRegister frb, 1858 RCBit rc) { 1859 emit(EXT4 | FCTID | frt.code() * B21 | frb.code() * B11 | rc); 1860 } 1861 1862 1863 void Assembler::fctidz(const DoubleRegister frt, const DoubleRegister frb, 1864 RCBit rc) { 1865 emit(EXT4 | FCTIDZ | frt.code() * B21 | frb.code() * B11 | rc); 1866 } 1867 1868 1869 void Assembler::fctidu(const DoubleRegister frt, const DoubleRegister frb, 1870 RCBit rc) { 1871 emit(EXT4 | FCTIDU | frt.code() * B21 | frb.code() * B11 | rc); 1872 } 1873 1874 1875 void Assembler::fctiduz(const DoubleRegister frt, const DoubleRegister frb, 1876 RCBit rc) { 1877 emit(EXT4 | FCTIDUZ | frt.code() * B21 | frb.code() * B11 | rc); 1878 } 1879 1880 1881 void Assembler::fsel(const DoubleRegister frt, const DoubleRegister fra, 1882 const DoubleRegister frc, const DoubleRegister frb, 1883 RCBit rc) { 1884 emit(EXT4 | FSEL | frt.code() * B21 | fra.code() * B16 | frb.code() * B11 | 1885 frc.code() * B6 | rc); 1886 } 1887 1888 1889 void Assembler::fneg(const DoubleRegister frt, const DoubleRegister frb, 1890 RCBit rc) { 1891 emit(EXT4 | FNEG | frt.code() * B21 | frb.code() * B11 | rc); 1892 } 1893 1894 1895 void Assembler::mtfsb0(FPSCRBit bit, RCBit rc) { 1896 DCHECK_LT(static_cast<int>(bit), 32); 1897 int bt = bit; 1898 emit(EXT4 | MTFSB0 | bt * B21 | rc); 1899 } 1900 1901 1902 void Assembler::mtfsb1(FPSCRBit bit, RCBit rc) { 1903 DCHECK_LT(static_cast<int>(bit), 32); 1904 int bt = bit; 1905 emit(EXT4 | MTFSB1 | bt * B21 | rc); 1906 } 1907 1908 1909 void Assembler::mtfsfi(int bf, int immediate, RCBit rc) { 1910 emit(EXT4 | MTFSFI | bf * B23 | immediate * B12 | rc); 1911 } 1912 1913 1914 void Assembler::mffs(const DoubleRegister frt, RCBit rc) { 1915 emit(EXT4 | MFFS | frt.code() * B21 | rc); 1916 } 1917 1918 1919 void Assembler::mtfsf(const DoubleRegister frb, bool L, int FLM, bool W, 1920 RCBit rc) { 1921 emit(EXT4 | MTFSF | frb.code() * B11 | W * B16 | FLM * B17 | L * B25 | rc); 1922 } 1923 1924 1925 void Assembler::fsqrt(const DoubleRegister frt, const DoubleRegister frb, 1926 RCBit rc) { 1927 emit(EXT4 | FSQRT | frt.code() * B21 | frb.code() * B11 | rc); 1928 } 1929 1930 1931 void Assembler::fabs(const DoubleRegister frt, const DoubleRegister frb, 1932 RCBit rc) { 1933 emit(EXT4 | FABS | frt.code() * B21 | frb.code() * B11 | rc); 1934 } 1935 1936 1937 void Assembler::fmadd(const DoubleRegister frt, const DoubleRegister fra, 1938 const DoubleRegister frc, const DoubleRegister frb, 1939 RCBit rc) { 1940 emit(EXT4 | FMADD | frt.code() * B21 | fra.code() * B16 | frb.code() * B11 | 1941 frc.code() * B6 | rc); 1942 } 1943 1944 1945 void Assembler::fmsub(const DoubleRegister frt, const DoubleRegister fra, 1946 const DoubleRegister frc, const DoubleRegister frb, 1947 RCBit rc) { 1948 emit(EXT4 | FMSUB | frt.code() * B21 | fra.code() * B16 | frb.code() * B11 | 1949 frc.code() * B6 | rc); 1950 } 1951 1952 // Pseudo instructions. 1953 void Assembler::nop(int type) { 1954 Register reg = r0; 1955 switch (type) { 1956 case NON_MARKING_NOP: 1957 reg = r0; 1958 break; 1959 case GROUP_ENDING_NOP: 1960 reg = r2; 1961 break; 1962 case DEBUG_BREAK_NOP: 1963 reg = r3; 1964 break; 1965 default: 1966 UNIMPLEMENTED(); 1967 } 1968 1969 ori(reg, reg, Operand::Zero()); 1970 } 1971 1972 1973 bool Assembler::IsNop(Instr instr, int type) { 1974 int reg = 0; 1975 switch (type) { 1976 case NON_MARKING_NOP: 1977 reg = 0; 1978 break; 1979 case GROUP_ENDING_NOP: 1980 reg = 2; 1981 break; 1982 case DEBUG_BREAK_NOP: 1983 reg = 3; 1984 break; 1985 default: 1986 UNIMPLEMENTED(); 1987 } 1988 return instr == (ORI | reg * B21 | reg * B16); 1989 } 1990 1991 1992 void Assembler::GrowBuffer(int needed) { 1993 if (!own_buffer_) FATAL("external code buffer is too small"); 1994 1995 // Compute new buffer size. 1996 CodeDesc desc; // the new buffer 1997 if (buffer_size_ < 4 * KB) { 1998 desc.buffer_size = 4 * KB; 1999 } else if (buffer_size_ < 1 * MB) { 2000 desc.buffer_size = 2 * buffer_size_; 2001 } else { 2002 desc.buffer_size = buffer_size_ + 1 * MB; 2003 } 2004 int space = buffer_space() + (desc.buffer_size - buffer_size_); 2005 if (space < needed) { 2006 desc.buffer_size += needed - space; 2007 } 2008 2009 // Some internal data structures overflow for very large buffers, 2010 // they must ensure that kMaximalBufferSize is not too large. 2011 if (desc.buffer_size > kMaximalBufferSize) { 2012 V8::FatalProcessOutOfMemory(nullptr, "Assembler::GrowBuffer"); 2013 } 2014 2015 // Set up new buffer. 2016 desc.buffer = NewArray<byte>(desc.buffer_size); 2017 desc.origin = this; 2018 2019 desc.instr_size = pc_offset(); 2020 desc.reloc_size = (buffer_ + buffer_size_) - reloc_info_writer.pos(); 2021 2022 // Copy the data. 2023 intptr_t pc_delta = desc.buffer - buffer_; 2024 intptr_t rc_delta = 2025 (desc.buffer + desc.buffer_size) - (buffer_ + buffer_size_); 2026 memmove(desc.buffer, buffer_, desc.instr_size); 2027 memmove(reloc_info_writer.pos() + rc_delta, reloc_info_writer.pos(), 2028 desc.reloc_size); 2029 2030 // Switch buffers. 2031 DeleteArray(buffer_); 2032 buffer_ = desc.buffer; 2033 buffer_size_ = desc.buffer_size; 2034 pc_ += pc_delta; 2035 reloc_info_writer.Reposition(reloc_info_writer.pos() + rc_delta, 2036 reloc_info_writer.last_pc() + pc_delta); 2037 2038 // Nothing else to do here since we keep all internal references and 2039 // deferred relocation entries relative to the buffer (until 2040 // EmitRelocations). 2041 } 2042 2043 2044 void Assembler::db(uint8_t data) { 2045 CheckBuffer(); 2046 *reinterpret_cast<uint8_t*>(pc_) = data; 2047 pc_ += sizeof(uint8_t); 2048 } 2049 2050 2051 void Assembler::dd(uint32_t data) { 2052 CheckBuffer(); 2053 *reinterpret_cast<uint32_t*>(pc_) = data; 2054 pc_ += sizeof(uint32_t); 2055 } 2056 2057 2058 void Assembler::dq(uint64_t value) { 2059 CheckBuffer(); 2060 *reinterpret_cast<uint64_t*>(pc_) = value; 2061 pc_ += sizeof(uint64_t); 2062 } 2063 2064 2065 void Assembler::dp(uintptr_t data) { 2066 CheckBuffer(); 2067 *reinterpret_cast<uintptr_t*>(pc_) = data; 2068 pc_ += sizeof(uintptr_t); 2069 } 2070 2071 2072 void Assembler::RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data) { 2073 if (options().disable_reloc_info_for_patching) return; 2074 if (RelocInfo::IsNone(rmode) || 2075 // Don't record external references unless the heap will be serialized. 2076 (RelocInfo::IsOnlyForSerializer(rmode) && 2077 !options().record_reloc_info_for_serialization && !emit_debug_code())) { 2078 return; 2079 } 2080 DeferredRelocInfo rinfo(pc_offset(), rmode, data); 2081 relocations_.push_back(rinfo); 2082 } 2083 2084 2085 void Assembler::EmitRelocations() { 2086 EnsureSpaceFor(relocations_.size() * kMaxRelocSize); 2087 2088 for (std::vector<DeferredRelocInfo>::iterator it = relocations_.begin(); 2089 it != relocations_.end(); it++) { 2090 RelocInfo::Mode rmode = it->rmode(); 2091 Address pc = reinterpret_cast<Address>(buffer_) + it->position(); 2092 RelocInfo rinfo(pc, rmode, it->data(), nullptr); 2093 2094 // Fix up internal references now that they are guaranteed to be bound. 2095 if (RelocInfo::IsInternalReference(rmode)) { 2096 // Jump table entry 2097 intptr_t pos = static_cast<intptr_t>(Memory<Address>(pc)); 2098 Memory<Address>(pc) = reinterpret_cast<Address>(buffer_) + pos; 2099 } else if (RelocInfo::IsInternalReferenceEncoded(rmode)) { 2100 // mov sequence 2101 intptr_t pos = static_cast<intptr_t>(target_address_at(pc, kNullAddress)); 2102 set_target_address_at(pc, 0, reinterpret_cast<Address>(buffer_) + pos, 2103 SKIP_ICACHE_FLUSH); 2104 } 2105 2106 reloc_info_writer.Write(&rinfo); 2107 } 2108 } 2109 2110 2111 void Assembler::BlockTrampolinePoolFor(int instructions) { 2112 BlockTrampolinePoolBefore(pc_offset() + instructions * kInstrSize); 2113 } 2114 2115 2116 void Assembler::CheckTrampolinePool() { 2117 // Some small sequences of instructions must not be broken up by the 2118 // insertion of a trampoline pool; such sequences are protected by setting 2119 // either trampoline_pool_blocked_nesting_ or no_trampoline_pool_before_, 2120 // which are both checked here. Also, recursive calls to CheckTrampolinePool 2121 // are blocked by trampoline_pool_blocked_nesting_. 2122 if (trampoline_pool_blocked_nesting_ > 0) return; 2123 if (pc_offset() < no_trampoline_pool_before_) { 2124 next_trampoline_check_ = no_trampoline_pool_before_; 2125 return; 2126 } 2127 2128 DCHECK(!trampoline_emitted_); 2129 if (tracked_branch_count_ > 0) { 2130 int size = tracked_branch_count_ * kInstrSize; 2131 2132 // As we are only going to emit trampoline once, we need to prevent any 2133 // further emission. 2134 trampoline_emitted_ = true; 2135 next_trampoline_check_ = kMaxInt; 2136 2137 // First we emit jump, then we emit trampoline pool. 2138 b(size + kInstrSize, LeaveLK); 2139 for (int i = size; i > 0; i -= kInstrSize) { 2140 b(i, LeaveLK); 2141 } 2142 2143 trampoline_ = Trampoline(pc_offset() - size, tracked_branch_count_); 2144 } 2145 } 2146 2147 PatchingAssembler::PatchingAssembler(const AssemblerOptions& options, 2148 byte* address, int instructions) 2149 : Assembler(options, address, instructions * kInstrSize + kGap) { 2150 DCHECK_EQ(reloc_info_writer.pos(), buffer_ + buffer_size_); 2151 } 2152 2153 PatchingAssembler::~PatchingAssembler() { 2154 // Check that the code was patched as expected. 2155 DCHECK_EQ(pc_, buffer_ + buffer_size_ - kGap); 2156 DCHECK_EQ(reloc_info_writer.pos(), buffer_ + buffer_size_); 2157 } 2158 2159 } // namespace internal 2160 } // namespace v8 2161 2162 #endif // V8_TARGET_ARCH_PPC 2163