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 are 6 // 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 distribution. 14 // 15 // - Neither the name of Sun Microsystems or the names of contributors may 16 // be used to endorse or promote products derived from this software without 17 // specific prior written permission. 18 // 19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS 20 // IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 21 // THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 23 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 24 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 25 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 26 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 27 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 28 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 29 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 31 // The original source code covered by the above license above has been 32 // modified significantly by Google Inc. 33 // Copyright 2012 the V8 project authors. All rights reserved. 34 35 #include "src/mips64/assembler-mips64.h" 36 37 #if V8_TARGET_ARCH_MIPS64 38 39 #include "src/base/cpu.h" 40 #include "src/code-stubs.h" 41 #include "src/deoptimizer.h" 42 #include "src/mips64/assembler-mips64-inl.h" 43 44 namespace v8 { 45 namespace internal { 46 47 48 // Get the CPU features enabled by the build. For cross compilation the 49 // preprocessor symbols CAN_USE_FPU_INSTRUCTIONS 50 // can be defined to enable FPU instructions when building the 51 // snapshot. 52 static unsigned CpuFeaturesImpliedByCompiler() { 53 unsigned answer = 0; 54 #ifdef CAN_USE_FPU_INSTRUCTIONS 55 answer |= 1u << FPU; 56 #endif // def CAN_USE_FPU_INSTRUCTIONS 57 58 // If the compiler is allowed to use FPU then we can use FPU too in our code 59 // generation even when generating snapshots. This won't work for cross 60 // compilation. 61 #if defined(__mips__) && defined(__mips_hard_float) && __mips_hard_float != 0 62 answer |= 1u << FPU; 63 #endif 64 65 return answer; 66 } 67 68 69 void CpuFeatures::ProbeImpl(bool cross_compile) { 70 supported_ |= CpuFeaturesImpliedByCompiler(); 71 72 // Only use statically determined features for cross compile (snapshot). 73 if (cross_compile) return; 74 75 // If the compiler is allowed to use fpu then we can use fpu too in our 76 // code generation. 77 #ifndef __mips__ 78 // For the simulator build, use FPU. 79 supported_ |= 1u << FPU; 80 #if defined(_MIPS_ARCH_MIPS64R6) && defined(_MIPS_MSA) 81 supported_ |= 1u << MIPS_SIMD; 82 #endif 83 #else 84 // Probe for additional features at runtime. 85 base::CPU cpu; 86 if (cpu.has_fpu()) supported_ |= 1u << FPU; 87 #if defined(_MIPS_ARCH_MIPS64R6) 88 #if defined(_MIPS_MSA) 89 supported_ |= 1u << MIPS_SIMD; 90 #else 91 if (cpu.has_msa()) supported_ |= 1u << MIPS_SIMD; 92 #endif 93 #endif 94 #endif 95 } 96 97 98 void CpuFeatures::PrintTarget() { } 99 void CpuFeatures::PrintFeatures() { } 100 101 102 int ToNumber(Register reg) { 103 DCHECK(reg.is_valid()); 104 const int kNumbers[] = { 105 0, // zero_reg 106 1, // at 107 2, // v0 108 3, // v1 109 4, // a0 110 5, // a1 111 6, // a2 112 7, // a3 113 8, // a4 114 9, // a5 115 10, // a6 116 11, // a7 117 12, // t0 118 13, // t1 119 14, // t2 120 15, // t3 121 16, // s0 122 17, // s1 123 18, // s2 124 19, // s3 125 20, // s4 126 21, // s5 127 22, // s6 128 23, // s7 129 24, // t8 130 25, // t9 131 26, // k0 132 27, // k1 133 28, // gp 134 29, // sp 135 30, // fp 136 31, // ra 137 }; 138 return kNumbers[reg.code()]; 139 } 140 141 142 Register ToRegister(int num) { 143 DCHECK(num >= 0 && num < kNumRegisters); 144 const Register kRegisters[] = { 145 zero_reg, 146 at, 147 v0, v1, 148 a0, a1, a2, a3, a4, a5, a6, a7, 149 t0, t1, t2, t3, 150 s0, s1, s2, s3, s4, s5, s6, s7, 151 t8, t9, 152 k0, k1, 153 gp, 154 sp, 155 fp, 156 ra 157 }; 158 return kRegisters[num]; 159 } 160 161 162 // ----------------------------------------------------------------------------- 163 // Implementation of RelocInfo. 164 165 const int RelocInfo::kApplyMask = 166 RelocInfo::ModeMask(RelocInfo::INTERNAL_REFERENCE) | 167 RelocInfo::ModeMask(RelocInfo::INTERNAL_REFERENCE_ENCODED); 168 169 bool RelocInfo::IsCodedSpecially() { 170 // The deserializer needs to know whether a pointer is specially coded. Being 171 // specially coded on MIPS means that it is a lui/ori instruction, and that is 172 // always the case inside code objects. 173 return true; 174 } 175 176 177 bool RelocInfo::IsInConstantPool() { 178 return false; 179 } 180 181 int RelocInfo::GetDeoptimizationId(Isolate* isolate, DeoptimizeKind kind) { 182 DCHECK(IsRuntimeEntry(rmode_)); 183 return Deoptimizer::GetDeoptimizationId(isolate, target_address(), kind); 184 } 185 186 void RelocInfo::set_js_to_wasm_address(Address address, 187 ICacheFlushMode icache_flush_mode) { 188 DCHECK_EQ(rmode_, JS_TO_WASM_CALL); 189 Assembler::set_target_address_at(pc_, constant_pool_, address, 190 icache_flush_mode); 191 } 192 193 Address RelocInfo::js_to_wasm_address() const { 194 DCHECK_EQ(rmode_, JS_TO_WASM_CALL); 195 return Assembler::target_address_at(pc_, constant_pool_); 196 } 197 198 uint32_t RelocInfo::wasm_call_tag() const { 199 DCHECK(rmode_ == WASM_CALL || rmode_ == WASM_STUB_CALL); 200 return static_cast<uint32_t>( 201 Assembler::target_address_at(pc_, constant_pool_)); 202 } 203 204 // ----------------------------------------------------------------------------- 205 // Implementation of Operand and MemOperand. 206 // See assembler-mips-inl.h for inlined constructors. 207 208 Operand::Operand(Handle<HeapObject> handle) 209 : rm_(no_reg), rmode_(RelocInfo::EMBEDDED_OBJECT) { 210 value_.immediate = static_cast<intptr_t>(handle.address()); 211 } 212 213 Operand Operand::EmbeddedNumber(double value) { 214 int32_t smi; 215 if (DoubleToSmiInteger(value, &smi)) return Operand(Smi::FromInt(smi)); 216 Operand result(0, RelocInfo::EMBEDDED_OBJECT); 217 result.is_heap_object_request_ = true; 218 result.value_.heap_object_request = HeapObjectRequest(value); 219 return result; 220 } 221 222 Operand Operand::EmbeddedCode(CodeStub* stub) { 223 Operand result(0, RelocInfo::CODE_TARGET); 224 result.is_heap_object_request_ = true; 225 result.value_.heap_object_request = HeapObjectRequest(stub); 226 return result; 227 } 228 229 MemOperand::MemOperand(Register rm, int32_t offset) : Operand(rm) { 230 offset_ = offset; 231 } 232 233 234 MemOperand::MemOperand(Register rm, int32_t unit, int32_t multiplier, 235 OffsetAddend offset_addend) 236 : Operand(rm) { 237 offset_ = unit * multiplier + offset_addend; 238 } 239 240 void Assembler::AllocateAndInstallRequestedHeapObjects(Isolate* isolate) { 241 for (auto& request : heap_object_requests_) { 242 Handle<HeapObject> object; 243 switch (request.kind()) { 244 case HeapObjectRequest::kHeapNumber: 245 object = 246 isolate->factory()->NewHeapNumber(request.heap_number(), TENURED); 247 break; 248 case HeapObjectRequest::kCodeStub: 249 request.code_stub()->set_isolate(isolate); 250 object = request.code_stub()->GetCode(); 251 break; 252 } 253 Address pc = reinterpret_cast<Address>(buffer_) + request.offset(); 254 set_target_value_at(pc, reinterpret_cast<uint64_t>(object.location())); 255 } 256 } 257 258 // ----------------------------------------------------------------------------- 259 // Specific instructions, constants, and masks. 260 261 // daddiu(sp, sp, 8) aka Pop() operation or part of Pop(r) 262 // operations as post-increment of sp. 263 const Instr kPopInstruction = DADDIU | (sp.code() << kRsShift) | 264 (sp.code() << kRtShift) | 265 (kPointerSize & kImm16Mask); // NOLINT 266 // daddiu(sp, sp, -8) part of Push(r) operation as pre-decrement of sp. 267 const Instr kPushInstruction = DADDIU | (sp.code() << kRsShift) | 268 (sp.code() << kRtShift) | 269 (-kPointerSize & kImm16Mask); // NOLINT 270 // Sd(r, MemOperand(sp, 0)) 271 const Instr kPushRegPattern = 272 SD | (sp.code() << kRsShift) | (0 & kImm16Mask); // NOLINT 273 // Ld(r, MemOperand(sp, 0)) 274 const Instr kPopRegPattern = 275 LD | (sp.code() << kRsShift) | (0 & kImm16Mask); // NOLINT 276 277 const Instr kLwRegFpOffsetPattern = 278 LW | (fp.code() << kRsShift) | (0 & kImm16Mask); // NOLINT 279 280 const Instr kSwRegFpOffsetPattern = 281 SW | (fp.code() << kRsShift) | (0 & kImm16Mask); // NOLINT 282 283 const Instr kLwRegFpNegOffsetPattern = 284 LW | (fp.code() << kRsShift) | (kNegOffset & kImm16Mask); // NOLINT 285 286 const Instr kSwRegFpNegOffsetPattern = 287 SW | (fp.code() << kRsShift) | (kNegOffset & kImm16Mask); // NOLINT 288 // A mask for the Rt register for push, pop, lw, sw instructions. 289 const Instr kRtMask = kRtFieldMask; 290 const Instr kLwSwInstrTypeMask = 0xFFE00000; 291 const Instr kLwSwInstrArgumentMask = ~kLwSwInstrTypeMask; 292 const Instr kLwSwOffsetMask = kImm16Mask; 293 294 Assembler::Assembler(const AssemblerOptions& options, void* buffer, 295 int buffer_size) 296 : AssemblerBase(options, buffer, buffer_size), 297 scratch_register_list_(at.bit()) { 298 reloc_info_writer.Reposition(buffer_ + buffer_size_, pc_); 299 300 last_trampoline_pool_end_ = 0; 301 no_trampoline_pool_before_ = 0; 302 trampoline_pool_blocked_nesting_ = 0; 303 // We leave space (16 * kTrampolineSlotsSize) 304 // for BlockTrampolinePoolScope buffer. 305 next_buffer_check_ = FLAG_force_long_branches 306 ? kMaxInt : kMaxBranchOffset - kTrampolineSlotsSize * 16; 307 internal_trampoline_exception_ = false; 308 last_bound_pos_ = 0; 309 310 trampoline_emitted_ = FLAG_force_long_branches; 311 unbound_labels_count_ = 0; 312 block_buffer_growth_ = false; 313 } 314 315 void Assembler::GetCode(Isolate* isolate, CodeDesc* desc) { 316 EmitForbiddenSlotInstruction(); 317 DCHECK(pc_ <= reloc_info_writer.pos()); // No overlap. 318 319 AllocateAndInstallRequestedHeapObjects(isolate); 320 321 // Set up code descriptor. 322 desc->buffer = buffer_; 323 desc->buffer_size = buffer_size_; 324 desc->instr_size = pc_offset(); 325 desc->reloc_size = 326 static_cast<int>((buffer_ + buffer_size_) - reloc_info_writer.pos()); 327 desc->origin = this; 328 desc->constant_pool_size = 0; 329 desc->unwinding_info_size = 0; 330 desc->unwinding_info = nullptr; 331 } 332 333 334 void Assembler::Align(int m) { 335 DCHECK(m >= 4 && base::bits::IsPowerOfTwo(m)); 336 EmitForbiddenSlotInstruction(); 337 while ((pc_offset() & (m - 1)) != 0) { 338 nop(); 339 } 340 } 341 342 343 void Assembler::CodeTargetAlign() { 344 // No advantage to aligning branch/call targets to more than 345 // single instruction, that I am aware of. 346 Align(4); 347 } 348 349 350 Register Assembler::GetRtReg(Instr instr) { 351 return Register::from_code((instr & kRtFieldMask) >> kRtShift); 352 } 353 354 355 Register Assembler::GetRsReg(Instr instr) { 356 return Register::from_code((instr & kRsFieldMask) >> kRsShift); 357 } 358 359 360 Register Assembler::GetRdReg(Instr instr) { 361 return Register::from_code((instr & kRdFieldMask) >> kRdShift); 362 } 363 364 365 uint32_t Assembler::GetRt(Instr instr) { 366 return (instr & kRtFieldMask) >> kRtShift; 367 } 368 369 370 uint32_t Assembler::GetRtField(Instr instr) { 371 return instr & kRtFieldMask; 372 } 373 374 375 uint32_t Assembler::GetRs(Instr instr) { 376 return (instr & kRsFieldMask) >> kRsShift; 377 } 378 379 380 uint32_t Assembler::GetRsField(Instr instr) { 381 return instr & kRsFieldMask; 382 } 383 384 385 uint32_t Assembler::GetRd(Instr instr) { 386 return (instr & kRdFieldMask) >> kRdShift; 387 } 388 389 390 uint32_t Assembler::GetRdField(Instr instr) { 391 return instr & kRdFieldMask; 392 } 393 394 395 uint32_t Assembler::GetSa(Instr instr) { 396 return (instr & kSaFieldMask) >> kSaShift; 397 } 398 399 400 uint32_t Assembler::GetSaField(Instr instr) { 401 return instr & kSaFieldMask; 402 } 403 404 405 uint32_t Assembler::GetOpcodeField(Instr instr) { 406 return instr & kOpcodeMask; 407 } 408 409 410 uint32_t Assembler::GetFunction(Instr instr) { 411 return (instr & kFunctionFieldMask) >> kFunctionShift; 412 } 413 414 415 uint32_t Assembler::GetFunctionField(Instr instr) { 416 return instr & kFunctionFieldMask; 417 } 418 419 420 uint32_t Assembler::GetImmediate16(Instr instr) { 421 return instr & kImm16Mask; 422 } 423 424 425 uint32_t Assembler::GetLabelConst(Instr instr) { 426 return instr & ~kImm16Mask; 427 } 428 429 430 bool Assembler::IsPop(Instr instr) { 431 return (instr & ~kRtMask) == kPopRegPattern; 432 } 433 434 435 bool Assembler::IsPush(Instr instr) { 436 return (instr & ~kRtMask) == kPushRegPattern; 437 } 438 439 440 bool Assembler::IsSwRegFpOffset(Instr instr) { 441 return ((instr & kLwSwInstrTypeMask) == kSwRegFpOffsetPattern); 442 } 443 444 445 bool Assembler::IsLwRegFpOffset(Instr instr) { 446 return ((instr & kLwSwInstrTypeMask) == kLwRegFpOffsetPattern); 447 } 448 449 450 bool Assembler::IsSwRegFpNegOffset(Instr instr) { 451 return ((instr & (kLwSwInstrTypeMask | kNegOffset)) == 452 kSwRegFpNegOffsetPattern); 453 } 454 455 456 bool Assembler::IsLwRegFpNegOffset(Instr instr) { 457 return ((instr & (kLwSwInstrTypeMask | kNegOffset)) == 458 kLwRegFpNegOffsetPattern); 459 } 460 461 462 // Labels refer to positions in the (to be) generated code. 463 // There are bound, linked, and unused labels. 464 // 465 // Bound labels refer to known positions in the already 466 // generated code. pos() is the position the label refers to. 467 // 468 // Linked labels refer to unknown positions in the code 469 // to be generated; pos() is the position of the last 470 // instruction using the label. 471 472 // The link chain is terminated by a value in the instruction of -1, 473 // which is an otherwise illegal value (branch -1 is inf loop). 474 // The instruction 16-bit offset field addresses 32-bit words, but in 475 // code is conv to an 18-bit value addressing bytes, hence the -4 value. 476 477 const int kEndOfChain = -4; 478 // Determines the end of the Jump chain (a subset of the label link chain). 479 const int kEndOfJumpChain = 0; 480 481 bool Assembler::IsMsaBranch(Instr instr) { 482 uint32_t opcode = GetOpcodeField(instr); 483 uint32_t rs_field = GetRsField(instr); 484 if (opcode == COP1) { 485 switch (rs_field) { 486 case BZ_V: 487 case BZ_B: 488 case BZ_H: 489 case BZ_W: 490 case BZ_D: 491 case BNZ_V: 492 case BNZ_B: 493 case BNZ_H: 494 case BNZ_W: 495 case BNZ_D: 496 return true; 497 default: 498 return false; 499 } 500 } else { 501 return false; 502 } 503 } 504 505 bool Assembler::IsBranch(Instr instr) { 506 uint32_t opcode = GetOpcodeField(instr); 507 uint32_t rt_field = GetRtField(instr); 508 uint32_t rs_field = GetRsField(instr); 509 // Checks if the instruction is a branch. 510 bool isBranch = 511 opcode == BEQ || opcode == BNE || opcode == BLEZ || opcode == BGTZ || 512 opcode == BEQL || opcode == BNEL || opcode == BLEZL || opcode == BGTZL || 513 (opcode == REGIMM && (rt_field == BLTZ || rt_field == BGEZ || 514 rt_field == BLTZAL || rt_field == BGEZAL)) || 515 (opcode == COP1 && rs_field == BC1) || // Coprocessor branch. 516 (opcode == COP1 && rs_field == BC1EQZ) || 517 (opcode == COP1 && rs_field == BC1NEZ) || IsMsaBranch(instr); 518 if (!isBranch && kArchVariant == kMips64r6) { 519 // All the 3 variants of POP10 (BOVC, BEQC, BEQZALC) and 520 // POP30 (BNVC, BNEC, BNEZALC) are branch ops. 521 isBranch |= opcode == POP10 || opcode == POP30 || opcode == BC || 522 opcode == BALC || 523 (opcode == POP66 && rs_field != 0) || // BEQZC 524 (opcode == POP76 && rs_field != 0); // BNEZC 525 } 526 return isBranch; 527 } 528 529 530 bool Assembler::IsBc(Instr instr) { 531 uint32_t opcode = GetOpcodeField(instr); 532 // Checks if the instruction is a BC or BALC. 533 return opcode == BC || opcode == BALC; 534 } 535 536 bool Assembler::IsNal(Instr instr) { 537 uint32_t opcode = GetOpcodeField(instr); 538 uint32_t rt_field = GetRtField(instr); 539 uint32_t rs_field = GetRsField(instr); 540 return opcode == REGIMM && rt_field == BLTZAL && rs_field == 0; 541 } 542 543 bool Assembler::IsBzc(Instr instr) { 544 uint32_t opcode = GetOpcodeField(instr); 545 // Checks if the instruction is BEQZC or BNEZC. 546 return (opcode == POP66 && GetRsField(instr) != 0) || 547 (opcode == POP76 && GetRsField(instr) != 0); 548 } 549 550 551 bool Assembler::IsEmittedConstant(Instr instr) { 552 uint32_t label_constant = GetLabelConst(instr); 553 return label_constant == 0; // Emitted label const in reg-exp engine. 554 } 555 556 557 bool Assembler::IsBeq(Instr instr) { 558 return GetOpcodeField(instr) == BEQ; 559 } 560 561 562 bool Assembler::IsBne(Instr instr) { 563 return GetOpcodeField(instr) == BNE; 564 } 565 566 567 bool Assembler::IsBeqzc(Instr instr) { 568 uint32_t opcode = GetOpcodeField(instr); 569 return opcode == POP66 && GetRsField(instr) != 0; 570 } 571 572 573 bool Assembler::IsBnezc(Instr instr) { 574 uint32_t opcode = GetOpcodeField(instr); 575 return opcode == POP76 && GetRsField(instr) != 0; 576 } 577 578 579 bool Assembler::IsBeqc(Instr instr) { 580 uint32_t opcode = GetOpcodeField(instr); 581 uint32_t rs = GetRsField(instr); 582 uint32_t rt = GetRtField(instr); 583 return opcode == POP10 && rs != 0 && rs < rt; // && rt != 0 584 } 585 586 587 bool Assembler::IsBnec(Instr instr) { 588 uint32_t opcode = GetOpcodeField(instr); 589 uint32_t rs = GetRsField(instr); 590 uint32_t rt = GetRtField(instr); 591 return opcode == POP30 && rs != 0 && rs < rt; // && rt != 0 592 } 593 594 bool Assembler::IsMov(Instr instr, Register rd, Register rs) { 595 uint32_t opcode = GetOpcodeField(instr); 596 uint32_t rd_field = GetRd(instr); 597 uint32_t rs_field = GetRs(instr); 598 uint32_t rt_field = GetRt(instr); 599 uint32_t rd_reg = static_cast<uint32_t>(rd.code()); 600 uint32_t rs_reg = static_cast<uint32_t>(rs.code()); 601 uint32_t function_field = GetFunctionField(instr); 602 // Checks if the instruction is a OR with zero_reg argument (aka MOV). 603 bool res = opcode == SPECIAL && function_field == OR && rd_field == rd_reg && 604 rs_field == rs_reg && rt_field == 0; 605 return res; 606 } 607 608 bool Assembler::IsJump(Instr instr) { 609 uint32_t opcode = GetOpcodeField(instr); 610 uint32_t rt_field = GetRtField(instr); 611 uint32_t rd_field = GetRdField(instr); 612 uint32_t function_field = GetFunctionField(instr); 613 // Checks if the instruction is a jump. 614 return opcode == J || opcode == JAL || 615 (opcode == SPECIAL && rt_field == 0 && 616 ((function_field == JALR) || (rd_field == 0 && (function_field == JR)))); 617 } 618 619 620 bool Assembler::IsJ(Instr instr) { 621 uint32_t opcode = GetOpcodeField(instr); 622 // Checks if the instruction is a jump. 623 return opcode == J; 624 } 625 626 627 bool Assembler::IsJal(Instr instr) { 628 return GetOpcodeField(instr) == JAL; 629 } 630 631 632 bool Assembler::IsJr(Instr instr) { 633 return GetOpcodeField(instr) == SPECIAL && GetFunctionField(instr) == JR; 634 } 635 636 637 bool Assembler::IsJalr(Instr instr) { 638 return GetOpcodeField(instr) == SPECIAL && GetFunctionField(instr) == JALR; 639 } 640 641 642 bool Assembler::IsLui(Instr instr) { 643 uint32_t opcode = GetOpcodeField(instr); 644 // Checks if the instruction is a load upper immediate. 645 return opcode == LUI; 646 } 647 648 649 bool Assembler::IsOri(Instr instr) { 650 uint32_t opcode = GetOpcodeField(instr); 651 // Checks if the instruction is a load upper immediate. 652 return opcode == ORI; 653 } 654 655 656 bool Assembler::IsNop(Instr instr, unsigned int type) { 657 // See Assembler::nop(type). 658 DCHECK_LT(type, 32); 659 uint32_t opcode = GetOpcodeField(instr); 660 uint32_t function = GetFunctionField(instr); 661 uint32_t rt = GetRt(instr); 662 uint32_t rd = GetRd(instr); 663 uint32_t sa = GetSa(instr); 664 665 // Traditional mips nop == sll(zero_reg, zero_reg, 0) 666 // When marking non-zero type, use sll(zero_reg, at, type) 667 // to avoid use of mips ssnop and ehb special encodings 668 // of the sll instruction. 669 670 Register nop_rt_reg = (type == 0) ? zero_reg : at; 671 bool ret = (opcode == SPECIAL && function == SLL && 672 rd == static_cast<uint32_t>(ToNumber(zero_reg)) && 673 rt == static_cast<uint32_t>(ToNumber(nop_rt_reg)) && 674 sa == type); 675 676 return ret; 677 } 678 679 680 int32_t Assembler::GetBranchOffset(Instr instr) { 681 DCHECK(IsBranch(instr)); 682 return (static_cast<int16_t>(instr & kImm16Mask)) << 2; 683 } 684 685 686 bool Assembler::IsLw(Instr instr) { 687 return (static_cast<uint32_t>(instr & kOpcodeMask) == LW); 688 } 689 690 691 int16_t Assembler::GetLwOffset(Instr instr) { 692 DCHECK(IsLw(instr)); 693 return ((instr & kImm16Mask)); 694 } 695 696 697 Instr Assembler::SetLwOffset(Instr instr, int16_t offset) { 698 DCHECK(IsLw(instr)); 699 700 // We actually create a new lw instruction based on the original one. 701 Instr temp_instr = LW | (instr & kRsFieldMask) | (instr & kRtFieldMask) 702 | (offset & kImm16Mask); 703 704 return temp_instr; 705 } 706 707 708 bool Assembler::IsSw(Instr instr) { 709 return (static_cast<uint32_t>(instr & kOpcodeMask) == SW); 710 } 711 712 713 Instr Assembler::SetSwOffset(Instr instr, int16_t offset) { 714 DCHECK(IsSw(instr)); 715 return ((instr & ~kImm16Mask) | (offset & kImm16Mask)); 716 } 717 718 719 bool Assembler::IsAddImmediate(Instr instr) { 720 return ((instr & kOpcodeMask) == ADDIU || (instr & kOpcodeMask) == DADDIU); 721 } 722 723 724 Instr Assembler::SetAddImmediateOffset(Instr instr, int16_t offset) { 725 DCHECK(IsAddImmediate(instr)); 726 return ((instr & ~kImm16Mask) | (offset & kImm16Mask)); 727 } 728 729 730 bool Assembler::IsAndImmediate(Instr instr) { 731 return GetOpcodeField(instr) == ANDI; 732 } 733 734 735 static Assembler::OffsetSize OffsetSizeInBits(Instr instr) { 736 if (kArchVariant == kMips64r6) { 737 if (Assembler::IsBc(instr)) { 738 return Assembler::OffsetSize::kOffset26; 739 } else if (Assembler::IsBzc(instr)) { 740 return Assembler::OffsetSize::kOffset21; 741 } 742 } 743 return Assembler::OffsetSize::kOffset16; 744 } 745 746 747 static inline int32_t AddBranchOffset(int pos, Instr instr) { 748 int bits = OffsetSizeInBits(instr); 749 const int32_t mask = (1 << bits) - 1; 750 bits = 32 - bits; 751 752 // Do NOT change this to <<2. We rely on arithmetic shifts here, assuming 753 // the compiler uses arithmetic shifts for signed integers. 754 int32_t imm = ((instr & mask) << bits) >> (bits - 2); 755 756 if (imm == kEndOfChain) { 757 // EndOfChain sentinel is returned directly, not relative to pc or pos. 758 return kEndOfChain; 759 } else { 760 return pos + Assembler::kBranchPCOffset + imm; 761 } 762 } 763 764 765 int Assembler::target_at(int pos, bool is_internal) { 766 if (is_internal) { 767 int64_t* p = reinterpret_cast<int64_t*>(buffer_ + pos); 768 int64_t address = *p; 769 if (address == kEndOfJumpChain) { 770 return kEndOfChain; 771 } else { 772 int64_t instr_address = reinterpret_cast<int64_t>(p); 773 DCHECK(instr_address - address < INT_MAX); 774 int delta = static_cast<int>(instr_address - address); 775 DCHECK(pos > delta); 776 return pos - delta; 777 } 778 } 779 Instr instr = instr_at(pos); 780 if ((instr & ~kImm16Mask) == 0) { 781 // Emitted label constant, not part of a branch. 782 if (instr == 0) { 783 return kEndOfChain; 784 } else { 785 int32_t imm18 =((instr & static_cast<int32_t>(kImm16Mask)) << 16) >> 14; 786 return (imm18 + pos); 787 } 788 } 789 // Check we have a branch or jump instruction. 790 DCHECK(IsBranch(instr) || IsJ(instr) || IsJal(instr) || IsLui(instr) || 791 IsMov(instr, t8, ra)); 792 // Do NOT change this to <<2. We rely on arithmetic shifts here, assuming 793 // the compiler uses arithmetic shifts for signed integers. 794 if (IsBranch(instr)) { 795 return AddBranchOffset(pos, instr); 796 } else if (IsMov(instr, t8, ra)) { 797 int32_t imm32; 798 Instr instr_lui = instr_at(pos + 2 * kInstrSize); 799 Instr instr_ori = instr_at(pos + 3 * kInstrSize); 800 DCHECK(IsLui(instr_lui)); 801 DCHECK(IsOri(instr_ori)); 802 imm32 = (instr_lui & static_cast<int32_t>(kImm16Mask)) << kLuiShift; 803 imm32 |= (instr_ori & static_cast<int32_t>(kImm16Mask)); 804 if (imm32 == kEndOfJumpChain) { 805 // EndOfChain sentinel is returned directly, not relative to pc or pos. 806 return kEndOfChain; 807 } 808 return pos + Assembler::kLongBranchPCOffset + imm32; 809 } else if (IsLui(instr)) { 810 if (IsNal(instr_at(pos + kInstrSize))) { 811 int32_t imm32; 812 Instr instr_lui = instr_at(pos + 0 * kInstrSize); 813 Instr instr_ori = instr_at(pos + 2 * kInstrSize); 814 DCHECK(IsLui(instr_lui)); 815 DCHECK(IsOri(instr_ori)); 816 imm32 = (instr_lui & static_cast<int32_t>(kImm16Mask)) << kLuiShift; 817 imm32 |= (instr_ori & static_cast<int32_t>(kImm16Mask)); 818 if (imm32 == kEndOfJumpChain) { 819 // EndOfChain sentinel is returned directly, not relative to pc or pos. 820 return kEndOfChain; 821 } 822 return pos + Assembler::kLongBranchPCOffset + imm32; 823 } else { 824 Instr instr_lui = instr_at(pos + 0 * kInstrSize); 825 Instr instr_ori = instr_at(pos + 1 * kInstrSize); 826 Instr instr_ori2 = instr_at(pos + 3 * kInstrSize); 827 DCHECK(IsOri(instr_ori)); 828 DCHECK(IsOri(instr_ori2)); 829 830 // TODO(plind) create named constants for shift values. 831 int64_t imm = static_cast<int64_t>(instr_lui & kImm16Mask) << 48; 832 imm |= static_cast<int64_t>(instr_ori & kImm16Mask) << 32; 833 imm |= static_cast<int64_t>(instr_ori2 & kImm16Mask) << 16; 834 // Sign extend address; 835 imm >>= 16; 836 837 if (imm == kEndOfJumpChain) { 838 // EndOfChain sentinel is returned directly, not relative to pc or pos. 839 return kEndOfChain; 840 } else { 841 uint64_t instr_address = reinterpret_cast<int64_t>(buffer_ + pos); 842 DCHECK(instr_address - imm < INT_MAX); 843 int delta = static_cast<int>(instr_address - imm); 844 DCHECK(pos > delta); 845 return pos - delta; 846 } 847 } 848 } else { 849 DCHECK(IsJ(instr) || IsJal(instr)); 850 int32_t imm28 = (instr & static_cast<int32_t>(kImm26Mask)) << 2; 851 if (imm28 == kEndOfJumpChain) { 852 // EndOfChain sentinel is returned directly, not relative to pc or pos. 853 return kEndOfChain; 854 } else { 855 // Sign extend 28-bit offset. 856 int32_t delta = static_cast<int32_t>((imm28 << 4) >> 4); 857 return pos + delta; 858 } 859 } 860 } 861 862 863 static inline Instr SetBranchOffset(int32_t pos, int32_t target_pos, 864 Instr instr) { 865 int32_t bits = OffsetSizeInBits(instr); 866 int32_t imm = target_pos - (pos + Assembler::kBranchPCOffset); 867 DCHECK_EQ(imm & 3, 0); 868 imm >>= 2; 869 870 const int32_t mask = (1 << bits) - 1; 871 instr &= ~mask; 872 DCHECK(is_intn(imm, bits)); 873 874 return instr | (imm & mask); 875 } 876 877 878 void Assembler::target_at_put(int pos, int target_pos, bool is_internal) { 879 if (is_internal) { 880 uint64_t imm = reinterpret_cast<uint64_t>(buffer_) + target_pos; 881 *reinterpret_cast<uint64_t*>(buffer_ + pos) = imm; 882 return; 883 } 884 Instr instr = instr_at(pos); 885 if ((instr & ~kImm16Mask) == 0) { 886 DCHECK(target_pos == kEndOfChain || target_pos >= 0); 887 // Emitted label constant, not part of a branch. 888 // Make label relative to Code* of generated Code object. 889 instr_at_put(pos, target_pos + (Code::kHeaderSize - kHeapObjectTag)); 890 return; 891 } 892 893 if (IsBranch(instr)) { 894 instr = SetBranchOffset(pos, target_pos, instr); 895 instr_at_put(pos, instr); 896 } else if (IsLui(instr)) { 897 if (IsNal(instr_at(pos + kInstrSize))) { 898 Instr instr_lui = instr_at(pos + 0 * kInstrSize); 899 Instr instr_ori = instr_at(pos + 2 * kInstrSize); 900 DCHECK(IsLui(instr_lui)); 901 DCHECK(IsOri(instr_ori)); 902 int32_t imm = target_pos - (pos + Assembler::kLongBranchPCOffset); 903 DCHECK_EQ(imm & 3, 0); 904 if (is_int16(imm + Assembler::kLongBranchPCOffset - 905 Assembler::kBranchPCOffset)) { 906 // Optimize by converting to regular branch and link with 16-bit 907 // offset. 908 Instr instr_b = REGIMM | BGEZAL; // Branch and link. 909 instr_b = SetBranchOffset(pos, target_pos, instr_b); 910 // Correct ra register to point to one instruction after jalr from 911 // TurboAssembler::BranchAndLinkLong. 912 Instr instr_a = DADDIU | ra.code() << kRsShift | ra.code() << kRtShift | 913 kOptimizedBranchAndLinkLongReturnOffset; 914 915 instr_at_put(pos, instr_b); 916 instr_at_put(pos + 1 * kInstrSize, instr_a); 917 } else { 918 instr_lui &= ~kImm16Mask; 919 instr_ori &= ~kImm16Mask; 920 921 instr_at_put(pos + 0 * kInstrSize, 922 instr_lui | ((imm >> kLuiShift) & kImm16Mask)); 923 instr_at_put(pos + 2 * kInstrSize, instr_ori | (imm & kImm16Mask)); 924 } 925 } else { 926 Instr instr_lui = instr_at(pos + 0 * kInstrSize); 927 Instr instr_ori = instr_at(pos + 1 * kInstrSize); 928 Instr instr_ori2 = instr_at(pos + 3 * kInstrSize); 929 DCHECK(IsOri(instr_ori)); 930 DCHECK(IsOri(instr_ori2)); 931 932 uint64_t imm = reinterpret_cast<uint64_t>(buffer_) + target_pos; 933 DCHECK_EQ(imm & 3, 0); 934 935 instr_lui &= ~kImm16Mask; 936 instr_ori &= ~kImm16Mask; 937 instr_ori2 &= ~kImm16Mask; 938 939 instr_at_put(pos + 0 * kInstrSize, 940 instr_lui | ((imm >> 32) & kImm16Mask)); 941 instr_at_put(pos + 1 * kInstrSize, 942 instr_ori | ((imm >> 16) & kImm16Mask)); 943 instr_at_put(pos + 3 * kInstrSize, instr_ori2 | (imm & kImm16Mask)); 944 } 945 } else if (IsMov(instr, t8, ra)) { 946 Instr instr_lui = instr_at(pos + 2 * kInstrSize); 947 Instr instr_ori = instr_at(pos + 3 * kInstrSize); 948 DCHECK(IsLui(instr_lui)); 949 DCHECK(IsOri(instr_ori)); 950 951 int32_t imm_short = target_pos - (pos + Assembler::kBranchPCOffset); 952 953 if (is_int16(imm_short)) { 954 // Optimize by converting to regular branch with 16-bit 955 // offset 956 Instr instr_b = BEQ; 957 instr_b = SetBranchOffset(pos, target_pos, instr_b); 958 959 Instr instr_j = instr_at(pos + 5 * kInstrSize); 960 Instr instr_branch_delay; 961 962 if (IsJump(instr_j)) { 963 instr_branch_delay = instr_at(pos + 6 * kInstrSize); 964 } else { 965 instr_branch_delay = instr_at(pos + 7 * kInstrSize); 966 } 967 instr_at_put(pos, instr_b); 968 instr_at_put(pos + 1 * kInstrSize, instr_branch_delay); 969 } else { 970 int32_t imm = target_pos - (pos + Assembler::kLongBranchPCOffset); 971 DCHECK_EQ(imm & 3, 0); 972 973 instr_lui &= ~kImm16Mask; 974 instr_ori &= ~kImm16Mask; 975 976 instr_at_put(pos + 2 * kInstrSize, 977 instr_lui | ((imm >> kLuiShift) & kImm16Mask)); 978 instr_at_put(pos + 3 * kInstrSize, instr_ori | (imm & kImm16Mask)); 979 } 980 } else if (IsJ(instr) || IsJal(instr)) { 981 int32_t imm28 = target_pos - pos; 982 DCHECK_EQ(imm28 & 3, 0); 983 984 uint32_t imm26 = static_cast<uint32_t>(imm28 >> 2); 985 DCHECK(is_uint26(imm26)); 986 // Place 26-bit signed offset with markings. 987 // When code is committed it will be resolved to j/jal. 988 int32_t mark = IsJ(instr) ? kJRawMark : kJalRawMark; 989 instr_at_put(pos, mark | (imm26 & kImm26Mask)); 990 } else { 991 int32_t imm28 = target_pos - pos; 992 DCHECK_EQ(imm28 & 3, 0); 993 994 uint32_t imm26 = static_cast<uint32_t>(imm28 >> 2); 995 DCHECK(is_uint26(imm26)); 996 // Place raw 26-bit signed offset. 997 // When code is committed it will be resolved to j/jal. 998 instr &= ~kImm26Mask; 999 instr_at_put(pos, instr | (imm26 & kImm26Mask)); 1000 } 1001 } 1002 1003 void Assembler::print(const Label* L) { 1004 if (L->is_unused()) { 1005 PrintF("unused label\n"); 1006 } else if (L->is_bound()) { 1007 PrintF("bound label to %d\n", L->pos()); 1008 } else if (L->is_linked()) { 1009 Label l; 1010 l.link_to(L->pos()); 1011 PrintF("unbound label"); 1012 while (l.is_linked()) { 1013 PrintF("@ %d ", l.pos()); 1014 Instr instr = instr_at(l.pos()); 1015 if ((instr & ~kImm16Mask) == 0) { 1016 PrintF("value\n"); 1017 } else { 1018 PrintF("%d\n", instr); 1019 } 1020 next(&l, is_internal_reference(&l)); 1021 } 1022 } else { 1023 PrintF("label in inconsistent state (pos = %d)\n", L->pos_); 1024 } 1025 } 1026 1027 1028 void Assembler::bind_to(Label* L, int pos) { 1029 DCHECK(0 <= pos && pos <= pc_offset()); // Must have valid binding position. 1030 int trampoline_pos = kInvalidSlotPos; 1031 bool is_internal = false; 1032 if (L->is_linked() && !trampoline_emitted_) { 1033 unbound_labels_count_--; 1034 if (!is_internal_reference(L)) { 1035 next_buffer_check_ += kTrampolineSlotsSize; 1036 } 1037 } 1038 1039 while (L->is_linked()) { 1040 int fixup_pos = L->pos(); 1041 int dist = pos - fixup_pos; 1042 is_internal = is_internal_reference(L); 1043 next(L, is_internal); // Call next before overwriting link with target at 1044 // fixup_pos. 1045 Instr instr = instr_at(fixup_pos); 1046 if (is_internal) { 1047 target_at_put(fixup_pos, pos, is_internal); 1048 } else { 1049 if (IsBranch(instr)) { 1050 int branch_offset = BranchOffset(instr); 1051 if (dist > branch_offset) { 1052 if (trampoline_pos == kInvalidSlotPos) { 1053 trampoline_pos = get_trampoline_entry(fixup_pos); 1054 CHECK_NE(trampoline_pos, kInvalidSlotPos); 1055 } 1056 CHECK((trampoline_pos - fixup_pos) <= branch_offset); 1057 target_at_put(fixup_pos, trampoline_pos, false); 1058 fixup_pos = trampoline_pos; 1059 } 1060 target_at_put(fixup_pos, pos, false); 1061 } else { 1062 DCHECK(IsJ(instr) || IsJal(instr) || IsLui(instr) || 1063 IsEmittedConstant(instr) || IsMov(instr, t8, ra)); 1064 target_at_put(fixup_pos, pos, false); 1065 } 1066 } 1067 } 1068 L->bind_to(pos); 1069 1070 // Keep track of the last bound label so we don't eliminate any instructions 1071 // before a bound label. 1072 if (pos > last_bound_pos_) 1073 last_bound_pos_ = pos; 1074 } 1075 1076 1077 void Assembler::bind(Label* L) { 1078 DCHECK(!L->is_bound()); // Label can only be bound once. 1079 bind_to(L, pc_offset()); 1080 } 1081 1082 1083 void Assembler::next(Label* L, bool is_internal) { 1084 DCHECK(L->is_linked()); 1085 int link = target_at(L->pos(), is_internal); 1086 if (link == kEndOfChain) { 1087 L->Unuse(); 1088 } else { 1089 DCHECK_GE(link, 0); 1090 L->link_to(link); 1091 } 1092 } 1093 1094 1095 bool Assembler::is_near(Label* L) { 1096 DCHECK(L->is_bound()); 1097 return pc_offset() - L->pos() < kMaxBranchOffset - 4 * kInstrSize; 1098 } 1099 1100 1101 bool Assembler::is_near(Label* L, OffsetSize bits) { 1102 if (L == nullptr || !L->is_bound()) return true; 1103 return ((pc_offset() - L->pos()) < 1104 (1 << (bits + 2 - 1)) - 1 - 5 * kInstrSize); 1105 } 1106 1107 1108 bool Assembler::is_near_branch(Label* L) { 1109 DCHECK(L->is_bound()); 1110 return kArchVariant == kMips64r6 ? is_near_r6(L) : is_near_pre_r6(L); 1111 } 1112 1113 1114 int Assembler::BranchOffset(Instr instr) { 1115 // At pre-R6 and for other R6 branches the offset is 16 bits. 1116 int bits = OffsetSize::kOffset16; 1117 1118 if (kArchVariant == kMips64r6) { 1119 uint32_t opcode = GetOpcodeField(instr); 1120 switch (opcode) { 1121 // Checks BC or BALC. 1122 case BC: 1123 case BALC: 1124 bits = OffsetSize::kOffset26; 1125 break; 1126 1127 // Checks BEQZC or BNEZC. 1128 case POP66: 1129 case POP76: 1130 if (GetRsField(instr) != 0) bits = OffsetSize::kOffset21; 1131 break; 1132 default: 1133 break; 1134 } 1135 } 1136 1137 return (1 << (bits + 2 - 1)) - 1; 1138 } 1139 1140 1141 // We have to use a temporary register for things that can be relocated even 1142 // if they can be encoded in the MIPS's 16 bits of immediate-offset instruction 1143 // space. There is no guarantee that the relocated location can be similarly 1144 // encoded. 1145 bool Assembler::MustUseReg(RelocInfo::Mode rmode) { 1146 return !RelocInfo::IsNone(rmode); 1147 } 1148 1149 void Assembler::GenInstrRegister(Opcode opcode, 1150 Register rs, 1151 Register rt, 1152 Register rd, 1153 uint16_t sa, 1154 SecondaryField func) { 1155 DCHECK(rd.is_valid() && rs.is_valid() && rt.is_valid() && is_uint5(sa)); 1156 Instr instr = opcode | (rs.code() << kRsShift) | (rt.code() << kRtShift) 1157 | (rd.code() << kRdShift) | (sa << kSaShift) | func; 1158 emit(instr); 1159 } 1160 1161 1162 void Assembler::GenInstrRegister(Opcode opcode, 1163 Register rs, 1164 Register rt, 1165 uint16_t msb, 1166 uint16_t lsb, 1167 SecondaryField func) { 1168 DCHECK(rs.is_valid() && rt.is_valid() && is_uint5(msb) && is_uint5(lsb)); 1169 Instr instr = opcode | (rs.code() << kRsShift) | (rt.code() << kRtShift) 1170 | (msb << kRdShift) | (lsb << kSaShift) | func; 1171 emit(instr); 1172 } 1173 1174 1175 void Assembler::GenInstrRegister(Opcode opcode, 1176 SecondaryField fmt, 1177 FPURegister ft, 1178 FPURegister fs, 1179 FPURegister fd, 1180 SecondaryField func) { 1181 DCHECK(fd.is_valid() && fs.is_valid() && ft.is_valid()); 1182 Instr instr = opcode | fmt | (ft.code() << kFtShift) | (fs.code() << kFsShift) 1183 | (fd.code() << kFdShift) | func; 1184 emit(instr); 1185 } 1186 1187 1188 void Assembler::GenInstrRegister(Opcode opcode, 1189 FPURegister fr, 1190 FPURegister ft, 1191 FPURegister fs, 1192 FPURegister fd, 1193 SecondaryField func) { 1194 DCHECK(fd.is_valid() && fr.is_valid() && fs.is_valid() && ft.is_valid()); 1195 Instr instr = opcode | (fr.code() << kFrShift) | (ft.code() << kFtShift) 1196 | (fs.code() << kFsShift) | (fd.code() << kFdShift) | func; 1197 emit(instr); 1198 } 1199 1200 1201 void Assembler::GenInstrRegister(Opcode opcode, 1202 SecondaryField fmt, 1203 Register rt, 1204 FPURegister fs, 1205 FPURegister fd, 1206 SecondaryField func) { 1207 DCHECK(fd.is_valid() && fs.is_valid() && rt.is_valid()); 1208 Instr instr = opcode | fmt | (rt.code() << kRtShift) 1209 | (fs.code() << kFsShift) | (fd.code() << kFdShift) | func; 1210 emit(instr); 1211 } 1212 1213 1214 void Assembler::GenInstrRegister(Opcode opcode, 1215 SecondaryField fmt, 1216 Register rt, 1217 FPUControlRegister fs, 1218 SecondaryField func) { 1219 DCHECK(fs.is_valid() && rt.is_valid()); 1220 Instr instr = 1221 opcode | fmt | (rt.code() << kRtShift) | (fs.code() << kFsShift) | func; 1222 emit(instr); 1223 } 1224 1225 1226 // Instructions with immediate value. 1227 // Registers are in the order of the instruction encoding, from left to right. 1228 void Assembler::GenInstrImmediate(Opcode opcode, Register rs, Register rt, 1229 int32_t j, 1230 CompactBranchType is_compact_branch) { 1231 DCHECK(rs.is_valid() && rt.is_valid() && (is_int16(j) || is_uint16(j))); 1232 Instr instr = opcode | (rs.code() << kRsShift) | (rt.code() << kRtShift) 1233 | (j & kImm16Mask); 1234 emit(instr, is_compact_branch); 1235 } 1236 1237 void Assembler::GenInstrImmediate(Opcode opcode, Register base, Register rt, 1238 int32_t offset9, int bit6, 1239 SecondaryField func) { 1240 DCHECK(base.is_valid() && rt.is_valid() && is_int9(offset9) && 1241 is_uint1(bit6)); 1242 Instr instr = opcode | (base.code() << kBaseShift) | (rt.code() << kRtShift) | 1243 ((offset9 << kImm9Shift) & kImm9Mask) | bit6 << kBit6Shift | 1244 func; 1245 emit(instr); 1246 } 1247 1248 void Assembler::GenInstrImmediate(Opcode opcode, Register rs, SecondaryField SF, 1249 int32_t j, 1250 CompactBranchType is_compact_branch) { 1251 DCHECK(rs.is_valid() && (is_int16(j) || is_uint16(j))); 1252 Instr instr = opcode | (rs.code() << kRsShift) | SF | (j & kImm16Mask); 1253 emit(instr, is_compact_branch); 1254 } 1255 1256 1257 void Assembler::GenInstrImmediate(Opcode opcode, Register rs, FPURegister ft, 1258 int32_t j, 1259 CompactBranchType is_compact_branch) { 1260 DCHECK(rs.is_valid() && ft.is_valid() && (is_int16(j) || is_uint16(j))); 1261 Instr instr = opcode | (rs.code() << kRsShift) | (ft.code() << kFtShift) 1262 | (j & kImm16Mask); 1263 emit(instr, is_compact_branch); 1264 } 1265 1266 1267 void Assembler::GenInstrImmediate(Opcode opcode, Register rs, int32_t offset21, 1268 CompactBranchType is_compact_branch) { 1269 DCHECK(rs.is_valid() && (is_int21(offset21))); 1270 Instr instr = opcode | (rs.code() << kRsShift) | (offset21 & kImm21Mask); 1271 emit(instr, is_compact_branch); 1272 } 1273 1274 1275 void Assembler::GenInstrImmediate(Opcode opcode, Register rs, 1276 uint32_t offset21) { 1277 DCHECK(rs.is_valid() && (is_uint21(offset21))); 1278 Instr instr = opcode | (rs.code() << kRsShift) | (offset21 & kImm21Mask); 1279 emit(instr); 1280 } 1281 1282 1283 void Assembler::GenInstrImmediate(Opcode opcode, int32_t offset26, 1284 CompactBranchType is_compact_branch) { 1285 DCHECK(is_int26(offset26)); 1286 Instr instr = opcode | (offset26 & kImm26Mask); 1287 emit(instr, is_compact_branch); 1288 } 1289 1290 1291 void Assembler::GenInstrJump(Opcode opcode, 1292 uint32_t address) { 1293 BlockTrampolinePoolScope block_trampoline_pool(this); 1294 DCHECK(is_uint26(address)); 1295 Instr instr = opcode | address; 1296 emit(instr); 1297 BlockTrampolinePoolFor(1); // For associated delay slot. 1298 } 1299 1300 // MSA instructions 1301 void Assembler::GenInstrMsaI8(SecondaryField operation, uint32_t imm8, 1302 MSARegister ws, MSARegister wd) { 1303 DCHECK((kArchVariant == kMips64r6) && IsEnabled(MIPS_SIMD)); 1304 DCHECK(ws.is_valid() && wd.is_valid() && is_uint8(imm8)); 1305 Instr instr = MSA | operation | ((imm8 & kImm8Mask) << kWtShift) | 1306 (ws.code() << kWsShift) | (wd.code() << kWdShift); 1307 emit(instr); 1308 } 1309 1310 void Assembler::GenInstrMsaI5(SecondaryField operation, SecondaryField df, 1311 int32_t imm5, MSARegister ws, MSARegister wd) { 1312 DCHECK((kArchVariant == kMips64r6) && IsEnabled(MIPS_SIMD)); 1313 DCHECK(ws.is_valid() && wd.is_valid()); 1314 DCHECK((operation == MAXI_S) || (operation == MINI_S) || 1315 (operation == CEQI) || (operation == CLTI_S) || 1316 (operation == CLEI_S) 1317 ? is_int5(imm5) 1318 : is_uint5(imm5)); 1319 Instr instr = MSA | operation | df | ((imm5 & kImm5Mask) << kWtShift) | 1320 (ws.code() << kWsShift) | (wd.code() << kWdShift); 1321 emit(instr); 1322 } 1323 1324 void Assembler::GenInstrMsaBit(SecondaryField operation, SecondaryField df, 1325 uint32_t m, MSARegister ws, MSARegister wd) { 1326 DCHECK((kArchVariant == kMips64r6) && IsEnabled(MIPS_SIMD)); 1327 DCHECK(ws.is_valid() && wd.is_valid() && is_valid_msa_df_m(df, m)); 1328 Instr instr = MSA | operation | df | (m << kWtShift) | 1329 (ws.code() << kWsShift) | (wd.code() << kWdShift); 1330 emit(instr); 1331 } 1332 1333 void Assembler::GenInstrMsaI10(SecondaryField operation, SecondaryField df, 1334 int32_t imm10, MSARegister wd) { 1335 DCHECK((kArchVariant == kMips64r6) && IsEnabled(MIPS_SIMD)); 1336 DCHECK(wd.is_valid() && is_int10(imm10)); 1337 Instr instr = MSA | operation | df | ((imm10 & kImm10Mask) << kWsShift) | 1338 (wd.code() << kWdShift); 1339 emit(instr); 1340 } 1341 1342 template <typename RegType> 1343 void Assembler::GenInstrMsa3R(SecondaryField operation, SecondaryField df, 1344 RegType t, MSARegister ws, MSARegister wd) { 1345 DCHECK((kArchVariant == kMips64r6) && IsEnabled(MIPS_SIMD)); 1346 DCHECK(t.is_valid() && ws.is_valid() && wd.is_valid()); 1347 Instr instr = MSA | operation | df | (t.code() << kWtShift) | 1348 (ws.code() << kWsShift) | (wd.code() << kWdShift); 1349 emit(instr); 1350 } 1351 1352 template <typename DstType, typename SrcType> 1353 void Assembler::GenInstrMsaElm(SecondaryField operation, SecondaryField df, 1354 uint32_t n, SrcType src, DstType dst) { 1355 DCHECK((kArchVariant == kMips64r6) && IsEnabled(MIPS_SIMD)); 1356 DCHECK(src.is_valid() && dst.is_valid() && is_valid_msa_df_n(df, n)); 1357 Instr instr = MSA | operation | df | (n << kWtShift) | 1358 (src.code() << kWsShift) | (dst.code() << kWdShift) | 1359 MSA_ELM_MINOR; 1360 emit(instr); 1361 } 1362 1363 void Assembler::GenInstrMsa3RF(SecondaryField operation, uint32_t df, 1364 MSARegister wt, MSARegister ws, MSARegister wd) { 1365 DCHECK((kArchVariant == kMips64r6) && IsEnabled(MIPS_SIMD)); 1366 DCHECK(wt.is_valid() && ws.is_valid() && wd.is_valid()); 1367 DCHECK_LT(df, 2); 1368 Instr instr = MSA | operation | (df << 21) | (wt.code() << kWtShift) | 1369 (ws.code() << kWsShift) | (wd.code() << kWdShift); 1370 emit(instr); 1371 } 1372 1373 void Assembler::GenInstrMsaVec(SecondaryField operation, MSARegister wt, 1374 MSARegister ws, MSARegister wd) { 1375 DCHECK((kArchVariant == kMips64r6) && IsEnabled(MIPS_SIMD)); 1376 DCHECK(wt.is_valid() && ws.is_valid() && wd.is_valid()); 1377 Instr instr = MSA | operation | (wt.code() << kWtShift) | 1378 (ws.code() << kWsShift) | (wd.code() << kWdShift) | 1379 MSA_VEC_2R_2RF_MINOR; 1380 emit(instr); 1381 } 1382 1383 void Assembler::GenInstrMsaMI10(SecondaryField operation, int32_t s10, 1384 Register rs, MSARegister wd) { 1385 DCHECK((kArchVariant == kMips64r6) && IsEnabled(MIPS_SIMD)); 1386 DCHECK(rs.is_valid() && wd.is_valid() && is_int10(s10)); 1387 Instr instr = MSA | operation | ((s10 & kImm10Mask) << kWtShift) | 1388 (rs.code() << kWsShift) | (wd.code() << kWdShift); 1389 emit(instr); 1390 } 1391 1392 void Assembler::GenInstrMsa2R(SecondaryField operation, SecondaryField df, 1393 MSARegister ws, MSARegister wd) { 1394 DCHECK((kArchVariant == kMips64r6) && IsEnabled(MIPS_SIMD)); 1395 DCHECK(ws.is_valid() && wd.is_valid()); 1396 Instr instr = MSA | MSA_2R_FORMAT | operation | df | (ws.code() << kWsShift) | 1397 (wd.code() << kWdShift) | MSA_VEC_2R_2RF_MINOR; 1398 emit(instr); 1399 } 1400 1401 void Assembler::GenInstrMsa2RF(SecondaryField operation, SecondaryField df, 1402 MSARegister ws, MSARegister wd) { 1403 DCHECK((kArchVariant == kMips64r6) && IsEnabled(MIPS_SIMD)); 1404 DCHECK(ws.is_valid() && wd.is_valid()); 1405 Instr instr = MSA | MSA_2RF_FORMAT | operation | df | 1406 (ws.code() << kWsShift) | (wd.code() << kWdShift) | 1407 MSA_VEC_2R_2RF_MINOR; 1408 emit(instr); 1409 } 1410 1411 void Assembler::GenInstrMsaBranch(SecondaryField operation, MSARegister wt, 1412 int32_t offset16) { 1413 DCHECK((kArchVariant == kMips64r6) && IsEnabled(MIPS_SIMD)); 1414 DCHECK(wt.is_valid() && is_int16(offset16)); 1415 BlockTrampolinePoolScope block_trampoline_pool(this); 1416 Instr instr = 1417 COP1 | operation | (wt.code() << kWtShift) | (offset16 & kImm16Mask); 1418 emit(instr); 1419 BlockTrampolinePoolFor(1); // For associated delay slot. 1420 } 1421 1422 // Returns the next free trampoline entry. 1423 int32_t Assembler::get_trampoline_entry(int32_t pos) { 1424 int32_t trampoline_entry = kInvalidSlotPos; 1425 if (!internal_trampoline_exception_) { 1426 if (trampoline_.start() > pos) { 1427 trampoline_entry = trampoline_.take_slot(); 1428 } 1429 1430 if (kInvalidSlotPos == trampoline_entry) { 1431 internal_trampoline_exception_ = true; 1432 } 1433 } 1434 return trampoline_entry; 1435 } 1436 1437 1438 uint64_t Assembler::jump_address(Label* L) { 1439 int64_t target_pos; 1440 if (L->is_bound()) { 1441 target_pos = L->pos(); 1442 } else { 1443 if (L->is_linked()) { 1444 target_pos = L->pos(); // L's link. 1445 L->link_to(pc_offset()); 1446 } else { 1447 L->link_to(pc_offset()); 1448 return kEndOfJumpChain; 1449 } 1450 } 1451 uint64_t imm = reinterpret_cast<uint64_t>(buffer_) + target_pos; 1452 DCHECK_EQ(imm & 3, 0); 1453 1454 return imm; 1455 } 1456 1457 1458 uint64_t Assembler::jump_offset(Label* L) { 1459 int64_t target_pos; 1460 int32_t pad = IsPrevInstrCompactBranch() ? kInstrSize : 0; 1461 1462 if (L->is_bound()) { 1463 target_pos = L->pos(); 1464 } else { 1465 if (L->is_linked()) { 1466 target_pos = L->pos(); // L's link. 1467 L->link_to(pc_offset() + pad); 1468 } else { 1469 L->link_to(pc_offset() + pad); 1470 return kEndOfJumpChain; 1471 } 1472 } 1473 int64_t imm = target_pos - (pc_offset() + pad); 1474 DCHECK_EQ(imm & 3, 0); 1475 1476 return static_cast<uint64_t>(imm); 1477 } 1478 1479 uint64_t Assembler::branch_long_offset(Label* L) { 1480 int64_t target_pos; 1481 1482 if (L->is_bound()) { 1483 target_pos = L->pos(); 1484 } else { 1485 if (L->is_linked()) { 1486 target_pos = L->pos(); // L's link. 1487 L->link_to(pc_offset()); 1488 } else { 1489 L->link_to(pc_offset()); 1490 return kEndOfJumpChain; 1491 } 1492 } 1493 int64_t offset = target_pos - (pc_offset() + kLongBranchPCOffset); 1494 DCHECK_EQ(offset & 3, 0); 1495 1496 return static_cast<uint64_t>(offset); 1497 } 1498 1499 int32_t Assembler::branch_offset_helper(Label* L, OffsetSize bits) { 1500 int32_t target_pos; 1501 int32_t pad = IsPrevInstrCompactBranch() ? kInstrSize : 0; 1502 1503 if (L->is_bound()) { 1504 target_pos = L->pos(); 1505 } else { 1506 if (L->is_linked()) { 1507 target_pos = L->pos(); 1508 L->link_to(pc_offset() + pad); 1509 } else { 1510 L->link_to(pc_offset() + pad); 1511 if (!trampoline_emitted_) { 1512 unbound_labels_count_++; 1513 next_buffer_check_ -= kTrampolineSlotsSize; 1514 } 1515 return kEndOfChain; 1516 } 1517 } 1518 1519 int32_t offset = target_pos - (pc_offset() + kBranchPCOffset + pad); 1520 DCHECK(is_intn(offset, bits + 2)); 1521 DCHECK_EQ(offset & 3, 0); 1522 1523 return offset; 1524 } 1525 1526 1527 void Assembler::label_at_put(Label* L, int at_offset) { 1528 int target_pos; 1529 if (L->is_bound()) { 1530 target_pos = L->pos(); 1531 instr_at_put(at_offset, target_pos + (Code::kHeaderSize - kHeapObjectTag)); 1532 } else { 1533 if (L->is_linked()) { 1534 target_pos = L->pos(); // L's link. 1535 int32_t imm18 = target_pos - at_offset; 1536 DCHECK_EQ(imm18 & 3, 0); 1537 int32_t imm16 = imm18 >> 2; 1538 DCHECK(is_int16(imm16)); 1539 instr_at_put(at_offset, (imm16 & kImm16Mask)); 1540 } else { 1541 target_pos = kEndOfChain; 1542 instr_at_put(at_offset, 0); 1543 if (!trampoline_emitted_) { 1544 unbound_labels_count_++; 1545 next_buffer_check_ -= kTrampolineSlotsSize; 1546 } 1547 } 1548 L->link_to(at_offset); 1549 } 1550 } 1551 1552 1553 //------- Branch and jump instructions -------- 1554 1555 void Assembler::b(int16_t offset) { 1556 beq(zero_reg, zero_reg, offset); 1557 } 1558 1559 1560 void Assembler::bal(int16_t offset) { 1561 bgezal(zero_reg, offset); 1562 } 1563 1564 1565 void Assembler::bc(int32_t offset) { 1566 DCHECK_EQ(kArchVariant, kMips64r6); 1567 GenInstrImmediate(BC, offset, CompactBranchType::COMPACT_BRANCH); 1568 } 1569 1570 1571 void Assembler::balc(int32_t offset) { 1572 DCHECK_EQ(kArchVariant, kMips64r6); 1573 GenInstrImmediate(BALC, offset, CompactBranchType::COMPACT_BRANCH); 1574 } 1575 1576 1577 void Assembler::beq(Register rs, Register rt, int16_t offset) { 1578 BlockTrampolinePoolScope block_trampoline_pool(this); 1579 GenInstrImmediate(BEQ, rs, rt, offset); 1580 BlockTrampolinePoolFor(1); // For associated delay slot. 1581 } 1582 1583 1584 void Assembler::bgez(Register rs, int16_t offset) { 1585 BlockTrampolinePoolScope block_trampoline_pool(this); 1586 GenInstrImmediate(REGIMM, rs, BGEZ, offset); 1587 BlockTrampolinePoolFor(1); // For associated delay slot. 1588 } 1589 1590 1591 void Assembler::bgezc(Register rt, int16_t offset) { 1592 DCHECK_EQ(kArchVariant, kMips64r6); 1593 DCHECK(rt != zero_reg); 1594 GenInstrImmediate(BLEZL, rt, rt, offset, CompactBranchType::COMPACT_BRANCH); 1595 } 1596 1597 1598 void Assembler::bgeuc(Register rs, Register rt, int16_t offset) { 1599 DCHECK_EQ(kArchVariant, kMips64r6); 1600 DCHECK(rs != zero_reg); 1601 DCHECK(rt != zero_reg); 1602 DCHECK(rs.code() != rt.code()); 1603 GenInstrImmediate(BLEZ, rs, rt, offset, CompactBranchType::COMPACT_BRANCH); 1604 } 1605 1606 1607 void Assembler::bgec(Register rs, Register rt, int16_t offset) { 1608 DCHECK_EQ(kArchVariant, kMips64r6); 1609 DCHECK(rs != zero_reg); 1610 DCHECK(rt != zero_reg); 1611 DCHECK(rs.code() != rt.code()); 1612 GenInstrImmediate(BLEZL, rs, rt, offset, CompactBranchType::COMPACT_BRANCH); 1613 } 1614 1615 1616 void Assembler::bgezal(Register rs, int16_t offset) { 1617 DCHECK(kArchVariant != kMips64r6 || rs == zero_reg); 1618 DCHECK(rs != ra); 1619 BlockTrampolinePoolScope block_trampoline_pool(this); 1620 GenInstrImmediate(REGIMM, rs, BGEZAL, offset); 1621 BlockTrampolinePoolFor(1); // For associated delay slot. 1622 } 1623 1624 1625 void Assembler::bgtz(Register rs, int16_t offset) { 1626 BlockTrampolinePoolScope block_trampoline_pool(this); 1627 GenInstrImmediate(BGTZ, rs, zero_reg, offset); 1628 BlockTrampolinePoolFor(1); // For associated delay slot. 1629 } 1630 1631 1632 void Assembler::bgtzc(Register rt, int16_t offset) { 1633 DCHECK_EQ(kArchVariant, kMips64r6); 1634 DCHECK(rt != zero_reg); 1635 GenInstrImmediate(BGTZL, zero_reg, rt, offset, 1636 CompactBranchType::COMPACT_BRANCH); 1637 } 1638 1639 1640 void Assembler::blez(Register rs, int16_t offset) { 1641 BlockTrampolinePoolScope block_trampoline_pool(this); 1642 GenInstrImmediate(BLEZ, rs, zero_reg, offset); 1643 BlockTrampolinePoolFor(1); // For associated delay slot. 1644 } 1645 1646 1647 void Assembler::blezc(Register rt, int16_t offset) { 1648 DCHECK_EQ(kArchVariant, kMips64r6); 1649 DCHECK(rt != zero_reg); 1650 GenInstrImmediate(BLEZL, zero_reg, rt, offset, 1651 CompactBranchType::COMPACT_BRANCH); 1652 } 1653 1654 1655 void Assembler::bltzc(Register rt, int16_t offset) { 1656 DCHECK_EQ(kArchVariant, kMips64r6); 1657 DCHECK(rt != zero_reg); 1658 GenInstrImmediate(BGTZL, rt, rt, offset, CompactBranchType::COMPACT_BRANCH); 1659 } 1660 1661 1662 void Assembler::bltuc(Register rs, Register rt, int16_t offset) { 1663 DCHECK_EQ(kArchVariant, kMips64r6); 1664 DCHECK(rs != zero_reg); 1665 DCHECK(rt != zero_reg); 1666 DCHECK(rs.code() != rt.code()); 1667 GenInstrImmediate(BGTZ, rs, rt, offset, CompactBranchType::COMPACT_BRANCH); 1668 } 1669 1670 1671 void Assembler::bltc(Register rs, Register rt, int16_t offset) { 1672 DCHECK_EQ(kArchVariant, kMips64r6); 1673 DCHECK(rs != zero_reg); 1674 DCHECK(rt != zero_reg); 1675 DCHECK(rs.code() != rt.code()); 1676 GenInstrImmediate(BGTZL, rs, rt, offset, CompactBranchType::COMPACT_BRANCH); 1677 } 1678 1679 1680 void Assembler::bltz(Register rs, int16_t offset) { 1681 BlockTrampolinePoolScope block_trampoline_pool(this); 1682 GenInstrImmediate(REGIMM, rs, BLTZ, offset); 1683 BlockTrampolinePoolFor(1); // For associated delay slot. 1684 } 1685 1686 1687 void Assembler::bltzal(Register rs, int16_t offset) { 1688 DCHECK(kArchVariant != kMips64r6 || rs == zero_reg); 1689 DCHECK(rs != ra); 1690 BlockTrampolinePoolScope block_trampoline_pool(this); 1691 GenInstrImmediate(REGIMM, rs, BLTZAL, offset); 1692 BlockTrampolinePoolFor(1); // For associated delay slot. 1693 } 1694 1695 1696 void Assembler::bne(Register rs, Register rt, int16_t offset) { 1697 BlockTrampolinePoolScope block_trampoline_pool(this); 1698 GenInstrImmediate(BNE, rs, rt, offset); 1699 BlockTrampolinePoolFor(1); // For associated delay slot. 1700 } 1701 1702 1703 void Assembler::bovc(Register rs, Register rt, int16_t offset) { 1704 DCHECK_EQ(kArchVariant, kMips64r6); 1705 if (rs.code() >= rt.code()) { 1706 GenInstrImmediate(ADDI, rs, rt, offset, CompactBranchType::COMPACT_BRANCH); 1707 } else { 1708 GenInstrImmediate(ADDI, rt, rs, offset, CompactBranchType::COMPACT_BRANCH); 1709 } 1710 } 1711 1712 1713 void Assembler::bnvc(Register rs, Register rt, int16_t offset) { 1714 DCHECK_EQ(kArchVariant, kMips64r6); 1715 if (rs.code() >= rt.code()) { 1716 GenInstrImmediate(DADDI, rs, rt, offset, CompactBranchType::COMPACT_BRANCH); 1717 } else { 1718 GenInstrImmediate(DADDI, rt, rs, offset, CompactBranchType::COMPACT_BRANCH); 1719 } 1720 } 1721 1722 1723 void Assembler::blezalc(Register rt, int16_t offset) { 1724 DCHECK_EQ(kArchVariant, kMips64r6); 1725 DCHECK(rt != zero_reg); 1726 DCHECK(rt != ra); 1727 GenInstrImmediate(BLEZ, zero_reg, rt, offset, 1728 CompactBranchType::COMPACT_BRANCH); 1729 } 1730 1731 1732 void Assembler::bgezalc(Register rt, int16_t offset) { 1733 DCHECK_EQ(kArchVariant, kMips64r6); 1734 DCHECK(rt != zero_reg); 1735 DCHECK(rt != ra); 1736 GenInstrImmediate(BLEZ, rt, rt, offset, CompactBranchType::COMPACT_BRANCH); 1737 } 1738 1739 1740 void Assembler::bgezall(Register rs, int16_t offset) { 1741 DCHECK_NE(kArchVariant, kMips64r6); 1742 DCHECK(rs != zero_reg); 1743 DCHECK(rs != ra); 1744 BlockTrampolinePoolScope block_trampoline_pool(this); 1745 GenInstrImmediate(REGIMM, rs, BGEZALL, offset); 1746 BlockTrampolinePoolFor(1); // For associated delay slot. 1747 } 1748 1749 1750 void Assembler::bltzalc(Register rt, int16_t offset) { 1751 DCHECK_EQ(kArchVariant, kMips64r6); 1752 DCHECK(rt != zero_reg); 1753 DCHECK(rt != ra); 1754 GenInstrImmediate(BGTZ, rt, rt, offset, CompactBranchType::COMPACT_BRANCH); 1755 } 1756 1757 1758 void Assembler::bgtzalc(Register rt, int16_t offset) { 1759 DCHECK_EQ(kArchVariant, kMips64r6); 1760 DCHECK(rt != zero_reg); 1761 DCHECK(rt != ra); 1762 GenInstrImmediate(BGTZ, zero_reg, rt, offset, 1763 CompactBranchType::COMPACT_BRANCH); 1764 } 1765 1766 1767 void Assembler::beqzalc(Register rt, int16_t offset) { 1768 DCHECK_EQ(kArchVariant, kMips64r6); 1769 DCHECK(rt != zero_reg); 1770 DCHECK(rt != ra); 1771 GenInstrImmediate(ADDI, zero_reg, rt, offset, 1772 CompactBranchType::COMPACT_BRANCH); 1773 } 1774 1775 1776 void Assembler::bnezalc(Register rt, int16_t offset) { 1777 DCHECK_EQ(kArchVariant, kMips64r6); 1778 DCHECK(rt != zero_reg); 1779 DCHECK(rt != ra); 1780 GenInstrImmediate(DADDI, zero_reg, rt, offset, 1781 CompactBranchType::COMPACT_BRANCH); 1782 } 1783 1784 1785 void Assembler::beqc(Register rs, Register rt, int16_t offset) { 1786 DCHECK_EQ(kArchVariant, kMips64r6); 1787 DCHECK(rs.code() != rt.code() && rs.code() != 0 && rt.code() != 0); 1788 if (rs.code() < rt.code()) { 1789 GenInstrImmediate(ADDI, rs, rt, offset, CompactBranchType::COMPACT_BRANCH); 1790 } else { 1791 GenInstrImmediate(ADDI, rt, rs, offset, CompactBranchType::COMPACT_BRANCH); 1792 } 1793 } 1794 1795 1796 void Assembler::beqzc(Register rs, int32_t offset) { 1797 DCHECK_EQ(kArchVariant, kMips64r6); 1798 DCHECK(rs != zero_reg); 1799 GenInstrImmediate(POP66, rs, offset, CompactBranchType::COMPACT_BRANCH); 1800 } 1801 1802 1803 void Assembler::bnec(Register rs, Register rt, int16_t offset) { 1804 DCHECK_EQ(kArchVariant, kMips64r6); 1805 DCHECK(rs.code() != rt.code() && rs.code() != 0 && rt.code() != 0); 1806 if (rs.code() < rt.code()) { 1807 GenInstrImmediate(DADDI, rs, rt, offset, CompactBranchType::COMPACT_BRANCH); 1808 } else { 1809 GenInstrImmediate(DADDI, rt, rs, offset, CompactBranchType::COMPACT_BRANCH); 1810 } 1811 } 1812 1813 1814 void Assembler::bnezc(Register rs, int32_t offset) { 1815 DCHECK_EQ(kArchVariant, kMips64r6); 1816 DCHECK(rs != zero_reg); 1817 GenInstrImmediate(POP76, rs, offset, CompactBranchType::COMPACT_BRANCH); 1818 } 1819 1820 1821 void Assembler::j(int64_t target) { 1822 BlockTrampolinePoolScope block_trampoline_pool(this); 1823 GenInstrJump(J, static_cast<uint32_t>(target >> 2) & kImm26Mask); 1824 BlockTrampolinePoolFor(1); // For associated delay slot. 1825 } 1826 1827 1828 void Assembler::j(Label* target) { 1829 uint64_t imm = jump_offset(target); 1830 if (target->is_bound()) { 1831 BlockTrampolinePoolScope block_trampoline_pool(this); 1832 GenInstrJump(static_cast<Opcode>(kJRawMark), 1833 static_cast<uint32_t>(imm >> 2) & kImm26Mask); 1834 BlockTrampolinePoolFor(1); // For associated delay slot. 1835 } else { 1836 j(imm); 1837 } 1838 } 1839 1840 1841 void Assembler::jal(Label* target) { 1842 uint64_t imm = jump_offset(target); 1843 if (target->is_bound()) { 1844 BlockTrampolinePoolScope block_trampoline_pool(this); 1845 GenInstrJump(static_cast<Opcode>(kJalRawMark), 1846 static_cast<uint32_t>(imm >> 2) & kImm26Mask); 1847 BlockTrampolinePoolFor(1); // For associated delay slot. 1848 } else { 1849 jal(imm); 1850 } 1851 } 1852 1853 1854 void Assembler::jr(Register rs) { 1855 if (kArchVariant != kMips64r6) { 1856 BlockTrampolinePoolScope block_trampoline_pool(this); 1857 GenInstrRegister(SPECIAL, rs, zero_reg, zero_reg, 0, JR); 1858 BlockTrampolinePoolFor(1); // For associated delay slot. 1859 } else { 1860 jalr(rs, zero_reg); 1861 } 1862 } 1863 1864 1865 void Assembler::jal(int64_t target) { 1866 BlockTrampolinePoolScope block_trampoline_pool(this); 1867 GenInstrJump(JAL, static_cast<uint32_t>(target >> 2) & kImm26Mask); 1868 BlockTrampolinePoolFor(1); // For associated delay slot. 1869 } 1870 1871 1872 void Assembler::jalr(Register rs, Register rd) { 1873 DCHECK(rs.code() != rd.code()); 1874 BlockTrampolinePoolScope block_trampoline_pool(this); 1875 GenInstrRegister(SPECIAL, rs, zero_reg, rd, 0, JALR); 1876 BlockTrampolinePoolFor(1); // For associated delay slot. 1877 } 1878 1879 1880 void Assembler::jic(Register rt, int16_t offset) { 1881 DCHECK_EQ(kArchVariant, kMips64r6); 1882 GenInstrImmediate(POP66, zero_reg, rt, offset); 1883 } 1884 1885 1886 void Assembler::jialc(Register rt, int16_t offset) { 1887 DCHECK_EQ(kArchVariant, kMips64r6); 1888 GenInstrImmediate(POP76, zero_reg, rt, offset); 1889 } 1890 1891 1892 // -------Data-processing-instructions--------- 1893 1894 // Arithmetic. 1895 1896 void Assembler::addu(Register rd, Register rs, Register rt) { 1897 GenInstrRegister(SPECIAL, rs, rt, rd, 0, ADDU); 1898 } 1899 1900 1901 void Assembler::addiu(Register rd, Register rs, int32_t j) { 1902 GenInstrImmediate(ADDIU, rs, rd, j); 1903 } 1904 1905 1906 void Assembler::subu(Register rd, Register rs, Register rt) { 1907 GenInstrRegister(SPECIAL, rs, rt, rd, 0, SUBU); 1908 } 1909 1910 1911 void Assembler::mul(Register rd, Register rs, Register rt) { 1912 if (kArchVariant == kMips64r6) { 1913 GenInstrRegister(SPECIAL, rs, rt, rd, MUL_OP, MUL_MUH); 1914 } else { 1915 GenInstrRegister(SPECIAL2, rs, rt, rd, 0, MUL); 1916 } 1917 } 1918 1919 1920 void Assembler::muh(Register rd, Register rs, Register rt) { 1921 DCHECK_EQ(kArchVariant, kMips64r6); 1922 GenInstrRegister(SPECIAL, rs, rt, rd, MUH_OP, MUL_MUH); 1923 } 1924 1925 1926 void Assembler::mulu(Register rd, Register rs, Register rt) { 1927 DCHECK_EQ(kArchVariant, kMips64r6); 1928 GenInstrRegister(SPECIAL, rs, rt, rd, MUL_OP, MUL_MUH_U); 1929 } 1930 1931 1932 void Assembler::muhu(Register rd, Register rs, Register rt) { 1933 DCHECK_EQ(kArchVariant, kMips64r6); 1934 GenInstrRegister(SPECIAL, rs, rt, rd, MUH_OP, MUL_MUH_U); 1935 } 1936 1937 1938 void Assembler::dmul(Register rd, Register rs, Register rt) { 1939 DCHECK_EQ(kArchVariant, kMips64r6); 1940 GenInstrRegister(SPECIAL, rs, rt, rd, MUL_OP, D_MUL_MUH); 1941 } 1942 1943 1944 void Assembler::dmuh(Register rd, Register rs, Register rt) { 1945 DCHECK_EQ(kArchVariant, kMips64r6); 1946 GenInstrRegister(SPECIAL, rs, rt, rd, MUH_OP, D_MUL_MUH); 1947 } 1948 1949 1950 void Assembler::dmulu(Register rd, Register rs, Register rt) { 1951 DCHECK_EQ(kArchVariant, kMips64r6); 1952 GenInstrRegister(SPECIAL, rs, rt, rd, MUL_OP, D_MUL_MUH_U); 1953 } 1954 1955 1956 void Assembler::dmuhu(Register rd, Register rs, Register rt) { 1957 DCHECK_EQ(kArchVariant, kMips64r6); 1958 GenInstrRegister(SPECIAL, rs, rt, rd, MUH_OP, D_MUL_MUH_U); 1959 } 1960 1961 1962 void Assembler::mult(Register rs, Register rt) { 1963 DCHECK_NE(kArchVariant, kMips64r6); 1964 GenInstrRegister(SPECIAL, rs, rt, zero_reg, 0, MULT); 1965 } 1966 1967 1968 void Assembler::multu(Register rs, Register rt) { 1969 DCHECK_NE(kArchVariant, kMips64r6); 1970 GenInstrRegister(SPECIAL, rs, rt, zero_reg, 0, MULTU); 1971 } 1972 1973 1974 void Assembler::daddiu(Register rd, Register rs, int32_t j) { 1975 GenInstrImmediate(DADDIU, rs, rd, j); 1976 } 1977 1978 1979 void Assembler::div(Register rs, Register rt) { 1980 GenInstrRegister(SPECIAL, rs, rt, zero_reg, 0, DIV); 1981 } 1982 1983 1984 void Assembler::div(Register rd, Register rs, Register rt) { 1985 DCHECK_EQ(kArchVariant, kMips64r6); 1986 GenInstrRegister(SPECIAL, rs, rt, rd, DIV_OP, DIV_MOD); 1987 } 1988 1989 1990 void Assembler::mod(Register rd, Register rs, Register rt) { 1991 DCHECK_EQ(kArchVariant, kMips64r6); 1992 GenInstrRegister(SPECIAL, rs, rt, rd, MOD_OP, DIV_MOD); 1993 } 1994 1995 1996 void Assembler::divu(Register rs, Register rt) { 1997 GenInstrRegister(SPECIAL, rs, rt, zero_reg, 0, DIVU); 1998 } 1999 2000 2001 void Assembler::divu(Register rd, Register rs, Register rt) { 2002 DCHECK_EQ(kArchVariant, kMips64r6); 2003 GenInstrRegister(SPECIAL, rs, rt, rd, DIV_OP, DIV_MOD_U); 2004 } 2005 2006 2007 void Assembler::modu(Register rd, Register rs, Register rt) { 2008 DCHECK_EQ(kArchVariant, kMips64r6); 2009 GenInstrRegister(SPECIAL, rs, rt, rd, MOD_OP, DIV_MOD_U); 2010 } 2011 2012 2013 void Assembler::daddu(Register rd, Register rs, Register rt) { 2014 GenInstrRegister(SPECIAL, rs, rt, rd, 0, DADDU); 2015 } 2016 2017 2018 void Assembler::dsubu(Register rd, Register rs, Register rt) { 2019 GenInstrRegister(SPECIAL, rs, rt, rd, 0, DSUBU); 2020 } 2021 2022 2023 void Assembler::dmult(Register rs, Register rt) { 2024 GenInstrRegister(SPECIAL, rs, rt, zero_reg, 0, DMULT); 2025 } 2026 2027 2028 void Assembler::dmultu(Register rs, Register rt) { 2029 GenInstrRegister(SPECIAL, rs, rt, zero_reg, 0, DMULTU); 2030 } 2031 2032 2033 void Assembler::ddiv(Register rs, Register rt) { 2034 GenInstrRegister(SPECIAL, rs, rt, zero_reg, 0, DDIV); 2035 } 2036 2037 2038 void Assembler::ddiv(Register rd, Register rs, Register rt) { 2039 DCHECK_EQ(kArchVariant, kMips64r6); 2040 GenInstrRegister(SPECIAL, rs, rt, rd, DIV_OP, D_DIV_MOD); 2041 } 2042 2043 2044 void Assembler::dmod(Register rd, Register rs, Register rt) { 2045 DCHECK_EQ(kArchVariant, kMips64r6); 2046 GenInstrRegister(SPECIAL, rs, rt, rd, MOD_OP, D_DIV_MOD); 2047 } 2048 2049 2050 void Assembler::ddivu(Register rs, Register rt) { 2051 GenInstrRegister(SPECIAL, rs, rt, zero_reg, 0, DDIVU); 2052 } 2053 2054 2055 void Assembler::ddivu(Register rd, Register rs, Register rt) { 2056 DCHECK_EQ(kArchVariant, kMips64r6); 2057 GenInstrRegister(SPECIAL, rs, rt, rd, DIV_OP, D_DIV_MOD_U); 2058 } 2059 2060 2061 void Assembler::dmodu(Register rd, Register rs, Register rt) { 2062 DCHECK_EQ(kArchVariant, kMips64r6); 2063 GenInstrRegister(SPECIAL, rs, rt, rd, MOD_OP, D_DIV_MOD_U); 2064 } 2065 2066 2067 // Logical. 2068 2069 void Assembler::and_(Register rd, Register rs, Register rt) { 2070 GenInstrRegister(SPECIAL, rs, rt, rd, 0, AND); 2071 } 2072 2073 2074 void Assembler::andi(Register rt, Register rs, int32_t j) { 2075 DCHECK(is_uint16(j)); 2076 GenInstrImmediate(ANDI, rs, rt, j); 2077 } 2078 2079 2080 void Assembler::or_(Register rd, Register rs, Register rt) { 2081 GenInstrRegister(SPECIAL, rs, rt, rd, 0, OR); 2082 } 2083 2084 2085 void Assembler::ori(Register rt, Register rs, int32_t j) { 2086 DCHECK(is_uint16(j)); 2087 GenInstrImmediate(ORI, rs, rt, j); 2088 } 2089 2090 2091 void Assembler::xor_(Register rd, Register rs, Register rt) { 2092 GenInstrRegister(SPECIAL, rs, rt, rd, 0, XOR); 2093 } 2094 2095 2096 void Assembler::xori(Register rt, Register rs, int32_t j) { 2097 DCHECK(is_uint16(j)); 2098 GenInstrImmediate(XORI, rs, rt, j); 2099 } 2100 2101 2102 void Assembler::nor(Register rd, Register rs, Register rt) { 2103 GenInstrRegister(SPECIAL, rs, rt, rd, 0, NOR); 2104 } 2105 2106 2107 // Shifts. 2108 void Assembler::sll(Register rd, 2109 Register rt, 2110 uint16_t sa, 2111 bool coming_from_nop) { 2112 // Don't allow nop instructions in the form sll zero_reg, zero_reg to be 2113 // generated using the sll instruction. They must be generated using 2114 // nop(int/NopMarkerTypes). 2115 DCHECK(coming_from_nop || (rd != zero_reg && rt != zero_reg)); 2116 GenInstrRegister(SPECIAL, zero_reg, rt, rd, sa & 0x1F, SLL); 2117 } 2118 2119 2120 void Assembler::sllv(Register rd, Register rt, Register rs) { 2121 GenInstrRegister(SPECIAL, rs, rt, rd, 0, SLLV); 2122 } 2123 2124 2125 void Assembler::srl(Register rd, Register rt, uint16_t sa) { 2126 GenInstrRegister(SPECIAL, zero_reg, rt, rd, sa & 0x1F, SRL); 2127 } 2128 2129 2130 void Assembler::srlv(Register rd, Register rt, Register rs) { 2131 GenInstrRegister(SPECIAL, rs, rt, rd, 0, SRLV); 2132 } 2133 2134 2135 void Assembler::sra(Register rd, Register rt, uint16_t sa) { 2136 GenInstrRegister(SPECIAL, zero_reg, rt, rd, sa & 0x1F, SRA); 2137 } 2138 2139 2140 void Assembler::srav(Register rd, Register rt, Register rs) { 2141 GenInstrRegister(SPECIAL, rs, rt, rd, 0, SRAV); 2142 } 2143 2144 2145 void Assembler::rotr(Register rd, Register rt, uint16_t sa) { 2146 // Should be called via MacroAssembler::Ror. 2147 DCHECK(rd.is_valid() && rt.is_valid() && is_uint5(sa)); 2148 DCHECK(kArchVariant == kMips64r2 || kArchVariant == kMips64r6); 2149 Instr instr = SPECIAL | (1 << kRsShift) | (rt.code() << kRtShift) 2150 | (rd.code() << kRdShift) | (sa << kSaShift) | SRL; 2151 emit(instr); 2152 } 2153 2154 2155 void Assembler::rotrv(Register rd, Register rt, Register rs) { 2156 // Should be called via MacroAssembler::Ror. 2157 DCHECK(rd.is_valid() && rt.is_valid() && rs.is_valid()); 2158 DCHECK(kArchVariant == kMips64r2 || kArchVariant == kMips64r6); 2159 Instr instr = SPECIAL | (rs.code() << kRsShift) | (rt.code() << kRtShift) 2160 | (rd.code() << kRdShift) | (1 << kSaShift) | SRLV; 2161 emit(instr); 2162 } 2163 2164 2165 void Assembler::dsll(Register rd, Register rt, uint16_t sa) { 2166 GenInstrRegister(SPECIAL, zero_reg, rt, rd, sa & 0x1F, DSLL); 2167 } 2168 2169 2170 void Assembler::dsllv(Register rd, Register rt, Register rs) { 2171 GenInstrRegister(SPECIAL, rs, rt, rd, 0, DSLLV); 2172 } 2173 2174 2175 void Assembler::dsrl(Register rd, Register rt, uint16_t sa) { 2176 GenInstrRegister(SPECIAL, zero_reg, rt, rd, sa & 0x1F, DSRL); 2177 } 2178 2179 2180 void Assembler::dsrlv(Register rd, Register rt, Register rs) { 2181 GenInstrRegister(SPECIAL, rs, rt, rd, 0, DSRLV); 2182 } 2183 2184 2185 void Assembler::drotr(Register rd, Register rt, uint16_t sa) { 2186 DCHECK(rd.is_valid() && rt.is_valid() && is_uint5(sa)); 2187 Instr instr = SPECIAL | (1 << kRsShift) | (rt.code() << kRtShift) 2188 | (rd.code() << kRdShift) | (sa << kSaShift) | DSRL; 2189 emit(instr); 2190 } 2191 2192 void Assembler::drotr32(Register rd, Register rt, uint16_t sa) { 2193 DCHECK(rd.is_valid() && rt.is_valid() && is_uint5(sa)); 2194 Instr instr = SPECIAL | (1 << kRsShift) | (rt.code() << kRtShift) | 2195 (rd.code() << kRdShift) | (sa << kSaShift) | DSRL32; 2196 emit(instr); 2197 } 2198 2199 void Assembler::drotrv(Register rd, Register rt, Register rs) { 2200 DCHECK(rd.is_valid() && rt.is_valid() && rs.is_valid() ); 2201 Instr instr = SPECIAL | (rs.code() << kRsShift) | (rt.code() << kRtShift) 2202 | (rd.code() << kRdShift) | (1 << kSaShift) | DSRLV; 2203 emit(instr); 2204 } 2205 2206 2207 void Assembler::dsra(Register rd, Register rt, uint16_t sa) { 2208 GenInstrRegister(SPECIAL, zero_reg, rt, rd, sa & 0x1F, DSRA); 2209 } 2210 2211 2212 void Assembler::dsrav(Register rd, Register rt, Register rs) { 2213 GenInstrRegister(SPECIAL, rs, rt, rd, 0, DSRAV); 2214 } 2215 2216 2217 void Assembler::dsll32(Register rd, Register rt, uint16_t sa) { 2218 GenInstrRegister(SPECIAL, zero_reg, rt, rd, sa & 0x1F, DSLL32); 2219 } 2220 2221 2222 void Assembler::dsrl32(Register rd, Register rt, uint16_t sa) { 2223 GenInstrRegister(SPECIAL, zero_reg, rt, rd, sa & 0x1F, DSRL32); 2224 } 2225 2226 2227 void Assembler::dsra32(Register rd, Register rt, uint16_t sa) { 2228 GenInstrRegister(SPECIAL, zero_reg, rt, rd, sa & 0x1F, DSRA32); 2229 } 2230 2231 2232 void Assembler::lsa(Register rd, Register rt, Register rs, uint8_t sa) { 2233 DCHECK(rd.is_valid() && rt.is_valid() && rs.is_valid()); 2234 DCHECK_LE(sa, 3); 2235 DCHECK_EQ(kArchVariant, kMips64r6); 2236 Instr instr = SPECIAL | rs.code() << kRsShift | rt.code() << kRtShift | 2237 rd.code() << kRdShift | sa << kSaShift | LSA; 2238 emit(instr); 2239 } 2240 2241 2242 void Assembler::dlsa(Register rd, Register rt, Register rs, uint8_t sa) { 2243 DCHECK(rd.is_valid() && rt.is_valid() && rs.is_valid()); 2244 DCHECK_LE(sa, 3); 2245 DCHECK_EQ(kArchVariant, kMips64r6); 2246 Instr instr = SPECIAL | rs.code() << kRsShift | rt.code() << kRtShift | 2247 rd.code() << kRdShift | sa << kSaShift | DLSA; 2248 emit(instr); 2249 } 2250 2251 2252 // ------------Memory-instructions------------- 2253 2254 void Assembler::AdjustBaseAndOffset(MemOperand& src, 2255 OffsetAccessType access_type, 2256 int second_access_add_to_offset) { 2257 // This method is used to adjust the base register and offset pair 2258 // for a load/store when the offset doesn't fit into int16_t. 2259 // It is assumed that 'base + offset' is sufficiently aligned for memory 2260 // operands that are machine word in size or smaller. For doubleword-sized 2261 // operands it's assumed that 'base' is a multiple of 8, while 'offset' 2262 // may be a multiple of 4 (e.g. 4-byte-aligned long and double arguments 2263 // and spilled variables on the stack accessed relative to the stack 2264 // pointer register). 2265 // We preserve the "alignment" of 'offset' by adjusting it by a multiple of 8. 2266 2267 bool doubleword_aligned = (src.offset() & (kDoubleSize - 1)) == 0; 2268 bool two_accesses = static_cast<bool>(access_type) || !doubleword_aligned; 2269 DCHECK_LE(second_access_add_to_offset, 7); // Must be <= 7. 2270 2271 // is_int16 must be passed a signed value, hence the static cast below. 2272 if (is_int16(src.offset()) && 2273 (!two_accesses || is_int16(static_cast<int32_t>( 2274 src.offset() + second_access_add_to_offset)))) { 2275 // Nothing to do: 'offset' (and, if needed, 'offset + 4', or other specified 2276 // value) fits into int16_t. 2277 return; 2278 } 2279 2280 DCHECK(src.rm() != 2281 at); // Must not overwrite the register 'base' while loading 'offset'. 2282 2283 #ifdef DEBUG 2284 // Remember the "(mis)alignment" of 'offset', it will be checked at the end. 2285 uint32_t misalignment = src.offset() & (kDoubleSize - 1); 2286 #endif 2287 2288 // Do not load the whole 32-bit 'offset' if it can be represented as 2289 // a sum of two 16-bit signed offsets. This can save an instruction or two. 2290 // To simplify matters, only do this for a symmetric range of offsets from 2291 // about -64KB to about +64KB, allowing further addition of 4 when accessing 2292 // 64-bit variables with two 32-bit accesses. 2293 constexpr int32_t kMinOffsetForSimpleAdjustment = 2294 0x7FF8; // Max int16_t that's a multiple of 8. 2295 constexpr int32_t kMaxOffsetForSimpleAdjustment = 2296 2 * kMinOffsetForSimpleAdjustment; 2297 2298 UseScratchRegisterScope temps(this); 2299 Register scratch = temps.Acquire(); 2300 if (0 <= src.offset() && src.offset() <= kMaxOffsetForSimpleAdjustment) { 2301 daddiu(scratch, src.rm(), kMinOffsetForSimpleAdjustment); 2302 src.offset_ -= kMinOffsetForSimpleAdjustment; 2303 } else if (-kMaxOffsetForSimpleAdjustment <= src.offset() && 2304 src.offset() < 0) { 2305 daddiu(scratch, src.rm(), -kMinOffsetForSimpleAdjustment); 2306 src.offset_ += kMinOffsetForSimpleAdjustment; 2307 } else if (kArchVariant == kMips64r6) { 2308 // On r6 take advantage of the daui instruction, e.g.: 2309 // daui at, base, offset_high 2310 // [dahi at, 1] // When `offset` is close to +2GB. 2311 // lw reg_lo, offset_low(at) 2312 // [lw reg_hi, (offset_low+4)(at)] // If misaligned 64-bit load. 2313 // or when offset_low+4 overflows int16_t: 2314 // daui at, base, offset_high 2315 // daddiu at, at, 8 2316 // lw reg_lo, (offset_low-8)(at) 2317 // lw reg_hi, (offset_low-4)(at) 2318 int16_t offset_low = static_cast<uint16_t>(src.offset()); 2319 int32_t offset_low32 = offset_low; 2320 int16_t offset_high = static_cast<uint16_t>(src.offset() >> 16); 2321 bool increment_hi16 = offset_low < 0; 2322 bool overflow_hi16 = false; 2323 2324 if (increment_hi16) { 2325 offset_high++; 2326 overflow_hi16 = (offset_high == -32768); 2327 } 2328 daui(scratch, src.rm(), static_cast<uint16_t>(offset_high)); 2329 2330 if (overflow_hi16) { 2331 dahi(scratch, 1); 2332 } 2333 2334 if (two_accesses && !is_int16(static_cast<int32_t>( 2335 offset_low32 + second_access_add_to_offset))) { 2336 // Avoid overflow in the 16-bit offset of the load/store instruction when 2337 // adding 4. 2338 daddiu(scratch, scratch, kDoubleSize); 2339 offset_low32 -= kDoubleSize; 2340 } 2341 2342 src.offset_ = offset_low32; 2343 } else { 2344 // Do not load the whole 32-bit 'offset' if it can be represented as 2345 // a sum of three 16-bit signed offsets. This can save an instruction. 2346 // To simplify matters, only do this for a symmetric range of offsets from 2347 // about -96KB to about +96KB, allowing further addition of 4 when accessing 2348 // 64-bit variables with two 32-bit accesses. 2349 constexpr int32_t kMinOffsetForMediumAdjustment = 2350 2 * kMinOffsetForSimpleAdjustment; 2351 constexpr int32_t kMaxOffsetForMediumAdjustment = 2352 3 * kMinOffsetForSimpleAdjustment; 2353 if (0 <= src.offset() && src.offset() <= kMaxOffsetForMediumAdjustment) { 2354 daddiu(scratch, src.rm(), kMinOffsetForMediumAdjustment / 2); 2355 daddiu(scratch, scratch, kMinOffsetForMediumAdjustment / 2); 2356 src.offset_ -= kMinOffsetForMediumAdjustment; 2357 } else if (-kMaxOffsetForMediumAdjustment <= src.offset() && 2358 src.offset() < 0) { 2359 daddiu(scratch, src.rm(), -kMinOffsetForMediumAdjustment / 2); 2360 daddiu(scratch, scratch, -kMinOffsetForMediumAdjustment / 2); 2361 src.offset_ += kMinOffsetForMediumAdjustment; 2362 } else { 2363 // Now that all shorter options have been exhausted, load the full 32-bit 2364 // offset. 2365 int32_t loaded_offset = RoundDown(src.offset(), kDoubleSize); 2366 lui(scratch, (loaded_offset >> kLuiShift) & kImm16Mask); 2367 ori(scratch, scratch, loaded_offset & kImm16Mask); // Load 32-bit offset. 2368 daddu(scratch, scratch, src.rm()); 2369 src.offset_ -= loaded_offset; 2370 } 2371 } 2372 src.rm_ = scratch; 2373 2374 DCHECK(is_int16(src.offset())); 2375 if (two_accesses) { 2376 DCHECK(is_int16( 2377 static_cast<int32_t>(src.offset() + second_access_add_to_offset))); 2378 } 2379 DCHECK(misalignment == (src.offset() & (kDoubleSize - 1))); 2380 } 2381 2382 void Assembler::lb(Register rd, const MemOperand& rs) { 2383 GenInstrImmediate(LB, rs.rm(), rd, rs.offset_); 2384 } 2385 2386 2387 void Assembler::lbu(Register rd, const MemOperand& rs) { 2388 GenInstrImmediate(LBU, rs.rm(), rd, rs.offset_); 2389 } 2390 2391 2392 void Assembler::lh(Register rd, const MemOperand& rs) { 2393 GenInstrImmediate(LH, rs.rm(), rd, rs.offset_); 2394 } 2395 2396 2397 void Assembler::lhu(Register rd, const MemOperand& rs) { 2398 GenInstrImmediate(LHU, rs.rm(), rd, rs.offset_); 2399 } 2400 2401 2402 void Assembler::lw(Register rd, const MemOperand& rs) { 2403 GenInstrImmediate(LW, rs.rm(), rd, rs.offset_); 2404 } 2405 2406 2407 void Assembler::lwu(Register rd, const MemOperand& rs) { 2408 GenInstrImmediate(LWU, rs.rm(), rd, rs.offset_); 2409 } 2410 2411 2412 void Assembler::lwl(Register rd, const MemOperand& rs) { 2413 DCHECK(is_int16(rs.offset_)); 2414 DCHECK_EQ(kArchVariant, kMips64r2); 2415 GenInstrImmediate(LWL, rs.rm(), rd, rs.offset_); 2416 } 2417 2418 2419 void Assembler::lwr(Register rd, const MemOperand& rs) { 2420 DCHECK(is_int16(rs.offset_)); 2421 DCHECK_EQ(kArchVariant, kMips64r2); 2422 GenInstrImmediate(LWR, rs.rm(), rd, rs.offset_); 2423 } 2424 2425 2426 void Assembler::sb(Register rd, const MemOperand& rs) { 2427 GenInstrImmediate(SB, rs.rm(), rd, rs.offset_); 2428 } 2429 2430 2431 void Assembler::sh(Register rd, const MemOperand& rs) { 2432 GenInstrImmediate(SH, rs.rm(), rd, rs.offset_); 2433 } 2434 2435 2436 void Assembler::sw(Register rd, const MemOperand& rs) { 2437 GenInstrImmediate(SW, rs.rm(), rd, rs.offset_); 2438 } 2439 2440 2441 void Assembler::swl(Register rd, const MemOperand& rs) { 2442 DCHECK(is_int16(rs.offset_)); 2443 DCHECK_EQ(kArchVariant, kMips64r2); 2444 GenInstrImmediate(SWL, rs.rm(), rd, rs.offset_); 2445 } 2446 2447 2448 void Assembler::swr(Register rd, const MemOperand& rs) { 2449 DCHECK(is_int16(rs.offset_)); 2450 DCHECK_EQ(kArchVariant, kMips64r2); 2451 GenInstrImmediate(SWR, rs.rm(), rd, rs.offset_); 2452 } 2453 2454 void Assembler::ll(Register rd, const MemOperand& rs) { 2455 if (kArchVariant == kMips64r6) { 2456 DCHECK(is_int9(rs.offset_)); 2457 GenInstrImmediate(SPECIAL3, rs.rm(), rd, rs.offset_, 0, LL_R6); 2458 } else { 2459 DCHECK_EQ(kArchVariant, kMips64r2); 2460 DCHECK(is_int16(rs.offset_)); 2461 GenInstrImmediate(LL, rs.rm(), rd, rs.offset_); 2462 } 2463 } 2464 2465 void Assembler::lld(Register rd, const MemOperand& rs) { 2466 if (kArchVariant == kMips64r6) { 2467 DCHECK(is_int9(rs.offset_)); 2468 GenInstrImmediate(SPECIAL3, rs.rm(), rd, rs.offset_, 0, LLD_R6); 2469 } else { 2470 DCHECK_EQ(kArchVariant, kMips64r2); 2471 DCHECK(is_int16(rs.offset_)); 2472 GenInstrImmediate(LLD, rs.rm(), rd, rs.offset_); 2473 } 2474 } 2475 2476 void Assembler::sc(Register rd, const MemOperand& rs) { 2477 if (kArchVariant == kMips64r6) { 2478 DCHECK(is_int9(rs.offset_)); 2479 GenInstrImmediate(SPECIAL3, rs.rm(), rd, rs.offset_, 0, SC_R6); 2480 } else { 2481 DCHECK_EQ(kArchVariant, kMips64r2); 2482 GenInstrImmediate(SC, rs.rm(), rd, rs.offset_); 2483 } 2484 } 2485 2486 void Assembler::scd(Register rd, const MemOperand& rs) { 2487 if (kArchVariant == kMips64r6) { 2488 DCHECK(is_int9(rs.offset_)); 2489 GenInstrImmediate(SPECIAL3, rs.rm(), rd, rs.offset_, 0, SCD_R6); 2490 } else { 2491 DCHECK_EQ(kArchVariant, kMips64r2); 2492 GenInstrImmediate(SCD, rs.rm(), rd, rs.offset_); 2493 } 2494 } 2495 2496 void Assembler::lui(Register rd, int32_t j) { 2497 DCHECK(is_uint16(j) || is_int16(j)); 2498 GenInstrImmediate(LUI, zero_reg, rd, j); 2499 } 2500 2501 2502 void Assembler::aui(Register rt, Register rs, int32_t j) { 2503 // This instruction uses same opcode as 'lui'. The difference in encoding is 2504 // 'lui' has zero reg. for rs field. 2505 DCHECK(is_uint16(j)); 2506 GenInstrImmediate(LUI, rs, rt, j); 2507 } 2508 2509 2510 void Assembler::daui(Register rt, Register rs, int32_t j) { 2511 DCHECK(is_uint16(j)); 2512 DCHECK(rs != zero_reg); 2513 GenInstrImmediate(DAUI, rs, rt, j); 2514 } 2515 2516 2517 void Assembler::dahi(Register rs, int32_t j) { 2518 DCHECK(is_uint16(j)); 2519 GenInstrImmediate(REGIMM, rs, DAHI, j); 2520 } 2521 2522 2523 void Assembler::dati(Register rs, int32_t j) { 2524 DCHECK(is_uint16(j)); 2525 GenInstrImmediate(REGIMM, rs, DATI, j); 2526 } 2527 2528 2529 void Assembler::ldl(Register rd, const MemOperand& rs) { 2530 DCHECK(is_int16(rs.offset_)); 2531 DCHECK_EQ(kArchVariant, kMips64r2); 2532 GenInstrImmediate(LDL, rs.rm(), rd, rs.offset_); 2533 } 2534 2535 2536 void Assembler::ldr(Register rd, const MemOperand& rs) { 2537 DCHECK(is_int16(rs.offset_)); 2538 DCHECK_EQ(kArchVariant, kMips64r2); 2539 GenInstrImmediate(LDR, rs.rm(), rd, rs.offset_); 2540 } 2541 2542 2543 void Assembler::sdl(Register rd, const MemOperand& rs) { 2544 DCHECK(is_int16(rs.offset_)); 2545 DCHECK_EQ(kArchVariant, kMips64r2); 2546 GenInstrImmediate(SDL, rs.rm(), rd, rs.offset_); 2547 } 2548 2549 2550 void Assembler::sdr(Register rd, const MemOperand& rs) { 2551 DCHECK(is_int16(rs.offset_)); 2552 DCHECK_EQ(kArchVariant, kMips64r2); 2553 GenInstrImmediate(SDR, rs.rm(), rd, rs.offset_); 2554 } 2555 2556 2557 void Assembler::ld(Register rd, const MemOperand& rs) { 2558 GenInstrImmediate(LD, rs.rm(), rd, rs.offset_); 2559 } 2560 2561 2562 void Assembler::sd(Register rd, const MemOperand& rs) { 2563 GenInstrImmediate(SD, rs.rm(), rd, rs.offset_); 2564 } 2565 2566 2567 // ---------PC-Relative instructions----------- 2568 2569 void Assembler::addiupc(Register rs, int32_t imm19) { 2570 DCHECK_EQ(kArchVariant, kMips64r6); 2571 DCHECK(rs.is_valid() && is_int19(imm19)); 2572 uint32_t imm21 = ADDIUPC << kImm19Bits | (imm19 & kImm19Mask); 2573 GenInstrImmediate(PCREL, rs, imm21); 2574 } 2575 2576 2577 void Assembler::lwpc(Register rs, int32_t offset19) { 2578 DCHECK_EQ(kArchVariant, kMips64r6); 2579 DCHECK(rs.is_valid() && is_int19(offset19)); 2580 uint32_t imm21 = LWPC << kImm19Bits | (offset19 & kImm19Mask); 2581 GenInstrImmediate(PCREL, rs, imm21); 2582 } 2583 2584 2585 void Assembler::lwupc(Register rs, int32_t offset19) { 2586 DCHECK_EQ(kArchVariant, kMips64r6); 2587 DCHECK(rs.is_valid() && is_int19(offset19)); 2588 uint32_t imm21 = LWUPC << kImm19Bits | (offset19 & kImm19Mask); 2589 GenInstrImmediate(PCREL, rs, imm21); 2590 } 2591 2592 2593 void Assembler::ldpc(Register rs, int32_t offset18) { 2594 DCHECK_EQ(kArchVariant, kMips64r6); 2595 DCHECK(rs.is_valid() && is_int18(offset18)); 2596 uint32_t imm21 = LDPC << kImm18Bits | (offset18 & kImm18Mask); 2597 GenInstrImmediate(PCREL, rs, imm21); 2598 } 2599 2600 2601 void Assembler::auipc(Register rs, int16_t imm16) { 2602 DCHECK_EQ(kArchVariant, kMips64r6); 2603 DCHECK(rs.is_valid()); 2604 uint32_t imm21 = AUIPC << kImm16Bits | (imm16 & kImm16Mask); 2605 GenInstrImmediate(PCREL, rs, imm21); 2606 } 2607 2608 2609 void Assembler::aluipc(Register rs, int16_t imm16) { 2610 DCHECK_EQ(kArchVariant, kMips64r6); 2611 DCHECK(rs.is_valid()); 2612 uint32_t imm21 = ALUIPC << kImm16Bits | (imm16 & kImm16Mask); 2613 GenInstrImmediate(PCREL, rs, imm21); 2614 } 2615 2616 2617 // -------------Misc-instructions-------------- 2618 2619 // Break / Trap instructions. 2620 void Assembler::break_(uint32_t code, bool break_as_stop) { 2621 DCHECK_EQ(code & ~0xFFFFF, 0); 2622 // We need to invalidate breaks that could be stops as well because the 2623 // simulator expects a char pointer after the stop instruction. 2624 // See constants-mips.h for explanation. 2625 DCHECK((break_as_stop && 2626 code <= kMaxStopCode && 2627 code > kMaxWatchpointCode) || 2628 (!break_as_stop && 2629 (code > kMaxStopCode || 2630 code <= kMaxWatchpointCode))); 2631 Instr break_instr = SPECIAL | BREAK | (code << 6); 2632 emit(break_instr); 2633 } 2634 2635 2636 void Assembler::stop(const char* msg, uint32_t code) { 2637 DCHECK_GT(code, kMaxWatchpointCode); 2638 DCHECK_LE(code, kMaxStopCode); 2639 #if defined(V8_HOST_ARCH_MIPS) || defined(V8_HOST_ARCH_MIPS64) 2640 break_(0x54321); 2641 #else // V8_HOST_ARCH_MIPS 2642 break_(code, true); 2643 #endif 2644 } 2645 2646 2647 void Assembler::tge(Register rs, Register rt, uint16_t code) { 2648 DCHECK(is_uint10(code)); 2649 Instr instr = SPECIAL | TGE | rs.code() << kRsShift 2650 | rt.code() << kRtShift | code << 6; 2651 emit(instr); 2652 } 2653 2654 2655 void Assembler::tgeu(Register rs, Register rt, uint16_t code) { 2656 DCHECK(is_uint10(code)); 2657 Instr instr = SPECIAL | TGEU | rs.code() << kRsShift 2658 | rt.code() << kRtShift | code << 6; 2659 emit(instr); 2660 } 2661 2662 2663 void Assembler::tlt(Register rs, Register rt, uint16_t code) { 2664 DCHECK(is_uint10(code)); 2665 Instr instr = 2666 SPECIAL | TLT | rs.code() << kRsShift | rt.code() << kRtShift | code << 6; 2667 emit(instr); 2668 } 2669 2670 2671 void Assembler::tltu(Register rs, Register rt, uint16_t code) { 2672 DCHECK(is_uint10(code)); 2673 Instr instr = 2674 SPECIAL | TLTU | rs.code() << kRsShift 2675 | rt.code() << kRtShift | code << 6; 2676 emit(instr); 2677 } 2678 2679 2680 void Assembler::teq(Register rs, Register rt, uint16_t code) { 2681 DCHECK(is_uint10(code)); 2682 Instr instr = 2683 SPECIAL | TEQ | rs.code() << kRsShift | rt.code() << kRtShift | code << 6; 2684 emit(instr); 2685 } 2686 2687 2688 void Assembler::tne(Register rs, Register rt, uint16_t code) { 2689 DCHECK(is_uint10(code)); 2690 Instr instr = 2691 SPECIAL | TNE | rs.code() << kRsShift | rt.code() << kRtShift | code << 6; 2692 emit(instr); 2693 } 2694 2695 void Assembler::sync() { 2696 Instr sync_instr = SPECIAL | SYNC; 2697 emit(sync_instr); 2698 } 2699 2700 // Move from HI/LO register. 2701 2702 void Assembler::mfhi(Register rd) { 2703 GenInstrRegister(SPECIAL, zero_reg, zero_reg, rd, 0, MFHI); 2704 } 2705 2706 2707 void Assembler::mflo(Register rd) { 2708 GenInstrRegister(SPECIAL, zero_reg, zero_reg, rd, 0, MFLO); 2709 } 2710 2711 2712 // Set on less than instructions. 2713 void Assembler::slt(Register rd, Register rs, Register rt) { 2714 GenInstrRegister(SPECIAL, rs, rt, rd, 0, SLT); 2715 } 2716 2717 2718 void Assembler::sltu(Register rd, Register rs, Register rt) { 2719 GenInstrRegister(SPECIAL, rs, rt, rd, 0, SLTU); 2720 } 2721 2722 2723 void Assembler::slti(Register rt, Register rs, int32_t j) { 2724 GenInstrImmediate(SLTI, rs, rt, j); 2725 } 2726 2727 2728 void Assembler::sltiu(Register rt, Register rs, int32_t j) { 2729 GenInstrImmediate(SLTIU, rs, rt, j); 2730 } 2731 2732 2733 // Conditional move. 2734 void Assembler::movz(Register rd, Register rs, Register rt) { 2735 GenInstrRegister(SPECIAL, rs, rt, rd, 0, MOVZ); 2736 } 2737 2738 2739 void Assembler::movn(Register rd, Register rs, Register rt) { 2740 GenInstrRegister(SPECIAL, rs, rt, rd, 0, MOVN); 2741 } 2742 2743 2744 void Assembler::movt(Register rd, Register rs, uint16_t cc) { 2745 Register rt = Register::from_code((cc & 0x0007) << 2 | 1); 2746 GenInstrRegister(SPECIAL, rs, rt, rd, 0, MOVCI); 2747 } 2748 2749 2750 void Assembler::movf(Register rd, Register rs, uint16_t cc) { 2751 Register rt = Register::from_code((cc & 0x0007) << 2 | 0); 2752 GenInstrRegister(SPECIAL, rs, rt, rd, 0, MOVCI); 2753 } 2754 2755 2756 void Assembler::min_s(FPURegister fd, FPURegister fs, FPURegister ft) { 2757 min(S, fd, fs, ft); 2758 } 2759 2760 2761 void Assembler::min_d(FPURegister fd, FPURegister fs, FPURegister ft) { 2762 min(D, fd, fs, ft); 2763 } 2764 2765 2766 void Assembler::max_s(FPURegister fd, FPURegister fs, FPURegister ft) { 2767 max(S, fd, fs, ft); 2768 } 2769 2770 2771 void Assembler::max_d(FPURegister fd, FPURegister fs, FPURegister ft) { 2772 max(D, fd, fs, ft); 2773 } 2774 2775 2776 void Assembler::mina_s(FPURegister fd, FPURegister fs, FPURegister ft) { 2777 mina(S, fd, fs, ft); 2778 } 2779 2780 2781 void Assembler::mina_d(FPURegister fd, FPURegister fs, FPURegister ft) { 2782 mina(D, fd, fs, ft); 2783 } 2784 2785 2786 void Assembler::maxa_s(FPURegister fd, FPURegister fs, FPURegister ft) { 2787 maxa(S, fd, fs, ft); 2788 } 2789 2790 2791 void Assembler::maxa_d(FPURegister fd, FPURegister fs, FPURegister ft) { 2792 maxa(D, fd, fs, ft); 2793 } 2794 2795 2796 void Assembler::max(SecondaryField fmt, FPURegister fd, FPURegister fs, 2797 FPURegister ft) { 2798 DCHECK_EQ(kArchVariant, kMips64r6); 2799 DCHECK((fmt == D) || (fmt == S)); 2800 GenInstrRegister(COP1, fmt, ft, fs, fd, MAX); 2801 } 2802 2803 2804 void Assembler::min(SecondaryField fmt, FPURegister fd, FPURegister fs, 2805 FPURegister ft) { 2806 DCHECK_EQ(kArchVariant, kMips64r6); 2807 DCHECK((fmt == D) || (fmt == S)); 2808 GenInstrRegister(COP1, fmt, ft, fs, fd, MIN); 2809 } 2810 2811 2812 // GPR. 2813 void Assembler::seleqz(Register rd, Register rs, Register rt) { 2814 DCHECK_EQ(kArchVariant, kMips64r6); 2815 GenInstrRegister(SPECIAL, rs, rt, rd, 0, SELEQZ_S); 2816 } 2817 2818 2819 // GPR. 2820 void Assembler::selnez(Register rd, Register rs, Register rt) { 2821 DCHECK_EQ(kArchVariant, kMips64r6); 2822 GenInstrRegister(SPECIAL, rs, rt, rd, 0, SELNEZ_S); 2823 } 2824 2825 2826 // Bit twiddling. 2827 void Assembler::clz(Register rd, Register rs) { 2828 if (kArchVariant != kMips64r6) { 2829 // clz instr requires same GPR number in 'rd' and 'rt' fields. 2830 GenInstrRegister(SPECIAL2, rs, rd, rd, 0, CLZ); 2831 } else { 2832 GenInstrRegister(SPECIAL, rs, zero_reg, rd, 1, CLZ_R6); 2833 } 2834 } 2835 2836 2837 void Assembler::dclz(Register rd, Register rs) { 2838 if (kArchVariant != kMips64r6) { 2839 // dclz instr requires same GPR number in 'rd' and 'rt' fields. 2840 GenInstrRegister(SPECIAL2, rs, rd, rd, 0, DCLZ); 2841 } else { 2842 GenInstrRegister(SPECIAL, rs, zero_reg, rd, 1, DCLZ_R6); 2843 } 2844 } 2845 2846 2847 void Assembler::ins_(Register rt, Register rs, uint16_t pos, uint16_t size) { 2848 // Should be called via MacroAssembler::Ins. 2849 // ins instr has 'rt' field as dest, and two uint5: msb, lsb. 2850 DCHECK((kArchVariant == kMips64r2) || (kArchVariant == kMips64r6)); 2851 GenInstrRegister(SPECIAL3, rs, rt, pos + size - 1, pos, INS); 2852 } 2853 2854 2855 void Assembler::dins_(Register rt, Register rs, uint16_t pos, uint16_t size) { 2856 // Should be called via MacroAssembler::Dins. 2857 // dins instr has 'rt' field as dest, and two uint5: msb, lsb. 2858 DCHECK(kArchVariant == kMips64r2 || kArchVariant == kMips64r6); 2859 GenInstrRegister(SPECIAL3, rs, rt, pos + size - 1, pos, DINS); 2860 } 2861 2862 void Assembler::dinsm_(Register rt, Register rs, uint16_t pos, uint16_t size) { 2863 // Should be called via MacroAssembler::Dins. 2864 // dinsm instr has 'rt' field as dest, and two uint5: msbminus32, lsb. 2865 DCHECK(kArchVariant == kMips64r2 || kArchVariant == kMips64r6); 2866 GenInstrRegister(SPECIAL3, rs, rt, pos + size - 1 - 32, pos, DINSM); 2867 } 2868 2869 void Assembler::dinsu_(Register rt, Register rs, uint16_t pos, uint16_t size) { 2870 // Should be called via MacroAssembler::Dins. 2871 // dinsu instr has 'rt' field as dest, and two uint5: msbminus32, lsbminus32. 2872 DCHECK(kArchVariant == kMips64r2 || kArchVariant == kMips64r6); 2873 GenInstrRegister(SPECIAL3, rs, rt, pos + size - 1 - 32, pos - 32, DINSU); 2874 } 2875 2876 void Assembler::ext_(Register rt, Register rs, uint16_t pos, uint16_t size) { 2877 // Should be called via MacroAssembler::Ext. 2878 // ext instr has 'rt' field as dest, and two uint5: msbd, lsb. 2879 DCHECK(kArchVariant == kMips64r2 || kArchVariant == kMips64r6); 2880 GenInstrRegister(SPECIAL3, rs, rt, size - 1, pos, EXT); 2881 } 2882 2883 2884 void Assembler::dext_(Register rt, Register rs, uint16_t pos, uint16_t size) { 2885 // Should be called via MacroAssembler::Dext. 2886 // dext instr has 'rt' field as dest, and two uint5: msbd, lsb. 2887 DCHECK(kArchVariant == kMips64r2 || kArchVariant == kMips64r6); 2888 GenInstrRegister(SPECIAL3, rs, rt, size - 1, pos, DEXT); 2889 } 2890 2891 void Assembler::dextm_(Register rt, Register rs, uint16_t pos, uint16_t size) { 2892 // Should be called via MacroAssembler::Dextm. 2893 // dextm instr has 'rt' field as dest, and two uint5: msbdminus32, lsb. 2894 DCHECK(kArchVariant == kMips64r2 || kArchVariant == kMips64r6); 2895 GenInstrRegister(SPECIAL3, rs, rt, size - 1 - 32, pos, DEXTM); 2896 } 2897 2898 void Assembler::dextu_(Register rt, Register rs, uint16_t pos, uint16_t size) { 2899 // Should be called via MacroAssembler::Dextu. 2900 // dextu instr has 'rt' field as dest, and two uint5: msbd, lsbminus32. 2901 DCHECK(kArchVariant == kMips64r2 || kArchVariant == kMips64r6); 2902 GenInstrRegister(SPECIAL3, rs, rt, size - 1, pos - 32, DEXTU); 2903 } 2904 2905 2906 void Assembler::bitswap(Register rd, Register rt) { 2907 DCHECK_EQ(kArchVariant, kMips64r6); 2908 GenInstrRegister(SPECIAL3, zero_reg, rt, rd, 0, BSHFL); 2909 } 2910 2911 2912 void Assembler::dbitswap(Register rd, Register rt) { 2913 DCHECK_EQ(kArchVariant, kMips64r6); 2914 GenInstrRegister(SPECIAL3, zero_reg, rt, rd, 0, DBSHFL); 2915 } 2916 2917 2918 void Assembler::pref(int32_t hint, const MemOperand& rs) { 2919 DCHECK(is_uint5(hint) && is_uint16(rs.offset_)); 2920 Instr instr = PREF | (rs.rm().code() << kRsShift) | (hint << kRtShift) 2921 | (rs.offset_); 2922 emit(instr); 2923 } 2924 2925 2926 void Assembler::align(Register rd, Register rs, Register rt, uint8_t bp) { 2927 DCHECK_EQ(kArchVariant, kMips64r6); 2928 DCHECK(is_uint3(bp)); 2929 uint16_t sa = (ALIGN << kBp2Bits) | bp; 2930 GenInstrRegister(SPECIAL3, rs, rt, rd, sa, BSHFL); 2931 } 2932 2933 2934 void Assembler::dalign(Register rd, Register rs, Register rt, uint8_t bp) { 2935 DCHECK_EQ(kArchVariant, kMips64r6); 2936 DCHECK(is_uint3(bp)); 2937 uint16_t sa = (DALIGN << kBp3Bits) | bp; 2938 GenInstrRegister(SPECIAL3, rs, rt, rd, sa, DBSHFL); 2939 } 2940 2941 void Assembler::wsbh(Register rd, Register rt) { 2942 DCHECK(kArchVariant == kMips64r2 || kArchVariant == kMips64r6); 2943 GenInstrRegister(SPECIAL3, zero_reg, rt, rd, WSBH, BSHFL); 2944 } 2945 2946 void Assembler::dsbh(Register rd, Register rt) { 2947 DCHECK(kArchVariant == kMips64r2 || kArchVariant == kMips64r6); 2948 GenInstrRegister(SPECIAL3, zero_reg, rt, rd, DSBH, DBSHFL); 2949 } 2950 2951 void Assembler::dshd(Register rd, Register rt) { 2952 DCHECK(kArchVariant == kMips64r2 || kArchVariant == kMips64r6); 2953 GenInstrRegister(SPECIAL3, zero_reg, rt, rd, DSHD, DBSHFL); 2954 } 2955 2956 void Assembler::seh(Register rd, Register rt) { 2957 DCHECK(kArchVariant == kMips64r2 || kArchVariant == kMips64r6); 2958 GenInstrRegister(SPECIAL3, zero_reg, rt, rd, SEH, BSHFL); 2959 } 2960 2961 void Assembler::seb(Register rd, Register rt) { 2962 DCHECK(kArchVariant == kMips64r2 || kArchVariant == kMips64r6); 2963 GenInstrRegister(SPECIAL3, zero_reg, rt, rd, SEB, BSHFL); 2964 } 2965 2966 // --------Coprocessor-instructions---------------- 2967 2968 // Load, store, move. 2969 void Assembler::lwc1(FPURegister fd, const MemOperand& src) { 2970 GenInstrImmediate(LWC1, src.rm(), fd, src.offset_); 2971 } 2972 2973 2974 void Assembler::ldc1(FPURegister fd, const MemOperand& src) { 2975 GenInstrImmediate(LDC1, src.rm(), fd, src.offset_); 2976 } 2977 2978 void Assembler::swc1(FPURegister fs, const MemOperand& src) { 2979 GenInstrImmediate(SWC1, src.rm(), fs, src.offset_); 2980 } 2981 2982 void Assembler::sdc1(FPURegister fs, const MemOperand& src) { 2983 GenInstrImmediate(SDC1, src.rm(), fs, src.offset_); 2984 } 2985 2986 2987 void Assembler::mtc1(Register rt, FPURegister fs) { 2988 GenInstrRegister(COP1, MTC1, rt, fs, f0); 2989 } 2990 2991 2992 void Assembler::mthc1(Register rt, FPURegister fs) { 2993 GenInstrRegister(COP1, MTHC1, rt, fs, f0); 2994 } 2995 2996 2997 void Assembler::dmtc1(Register rt, FPURegister fs) { 2998 GenInstrRegister(COP1, DMTC1, rt, fs, f0); 2999 } 3000 3001 3002 void Assembler::mfc1(Register rt, FPURegister fs) { 3003 GenInstrRegister(COP1, MFC1, rt, fs, f0); 3004 } 3005 3006 3007 void Assembler::mfhc1(Register rt, FPURegister fs) { 3008 GenInstrRegister(COP1, MFHC1, rt, fs, f0); 3009 } 3010 3011 3012 void Assembler::dmfc1(Register rt, FPURegister fs) { 3013 GenInstrRegister(COP1, DMFC1, rt, fs, f0); 3014 } 3015 3016 3017 void Assembler::ctc1(Register rt, FPUControlRegister fs) { 3018 GenInstrRegister(COP1, CTC1, rt, fs); 3019 } 3020 3021 3022 void Assembler::cfc1(Register rt, FPUControlRegister fs) { 3023 GenInstrRegister(COP1, CFC1, rt, fs); 3024 } 3025 3026 3027 void Assembler::sel(SecondaryField fmt, FPURegister fd, FPURegister fs, 3028 FPURegister ft) { 3029 DCHECK_EQ(kArchVariant, kMips64r6); 3030 DCHECK((fmt == D) || (fmt == S)); 3031 3032 GenInstrRegister(COP1, fmt, ft, fs, fd, SEL); 3033 } 3034 3035 3036 void Assembler::sel_s(FPURegister fd, FPURegister fs, FPURegister ft) { 3037 sel(S, fd, fs, ft); 3038 } 3039 3040 3041 void Assembler::sel_d(FPURegister fd, FPURegister fs, FPURegister ft) { 3042 sel(D, fd, fs, ft); 3043 } 3044 3045 3046 // FPR. 3047 void Assembler::seleqz(SecondaryField fmt, FPURegister fd, FPURegister fs, 3048 FPURegister ft) { 3049 DCHECK((fmt == D) || (fmt == S)); 3050 GenInstrRegister(COP1, fmt, ft, fs, fd, SELEQZ_C); 3051 } 3052 3053 3054 void Assembler::seleqz_d(FPURegister fd, FPURegister fs, FPURegister ft) { 3055 seleqz(D, fd, fs, ft); 3056 } 3057 3058 3059 void Assembler::seleqz_s(FPURegister fd, FPURegister fs, FPURegister ft) { 3060 seleqz(S, fd, fs, ft); 3061 } 3062 3063 3064 void Assembler::selnez_d(FPURegister fd, FPURegister fs, FPURegister ft) { 3065 selnez(D, fd, fs, ft); 3066 } 3067 3068 3069 void Assembler::selnez_s(FPURegister fd, FPURegister fs, FPURegister ft) { 3070 selnez(S, fd, fs, ft); 3071 } 3072 3073 3074 void Assembler::movz_s(FPURegister fd, FPURegister fs, Register rt) { 3075 DCHECK_EQ(kArchVariant, kMips64r2); 3076 GenInstrRegister(COP1, S, rt, fs, fd, MOVZ_C); 3077 } 3078 3079 3080 void Assembler::movz_d(FPURegister fd, FPURegister fs, Register rt) { 3081 DCHECK_EQ(kArchVariant, kMips64r2); 3082 GenInstrRegister(COP1, D, rt, fs, fd, MOVZ_C); 3083 } 3084 3085 3086 void Assembler::movt_s(FPURegister fd, FPURegister fs, uint16_t cc) { 3087 DCHECK_EQ(kArchVariant, kMips64r2); 3088 FPURegister ft = FPURegister::from_code((cc & 0x0007) << 2 | 1); 3089 GenInstrRegister(COP1, S, ft, fs, fd, MOVF); 3090 } 3091 3092 3093 void Assembler::movt_d(FPURegister fd, FPURegister fs, uint16_t cc) { 3094 DCHECK_EQ(kArchVariant, kMips64r2); 3095 FPURegister ft = FPURegister::from_code((cc & 0x0007) << 2 | 1); 3096 GenInstrRegister(COP1, D, ft, fs, fd, MOVF); 3097 } 3098 3099 3100 void Assembler::movf_s(FPURegister fd, FPURegister fs, uint16_t cc) { 3101 DCHECK_EQ(kArchVariant, kMips64r2); 3102 FPURegister ft = FPURegister::from_code((cc & 0x0007) << 2 | 0); 3103 GenInstrRegister(COP1, S, ft, fs, fd, MOVF); 3104 } 3105 3106 3107 void Assembler::movf_d(FPURegister fd, FPURegister fs, uint16_t cc) { 3108 DCHECK_EQ(kArchVariant, kMips64r2); 3109 FPURegister ft = FPURegister::from_code((cc & 0x0007) << 2 | 0); 3110 GenInstrRegister(COP1, D, ft, fs, fd, MOVF); 3111 } 3112 3113 3114 void Assembler::movn_s(FPURegister fd, FPURegister fs, Register rt) { 3115 DCHECK_EQ(kArchVariant, kMips64r2); 3116 GenInstrRegister(COP1, S, rt, fs, fd, MOVN_C); 3117 } 3118 3119 3120 void Assembler::movn_d(FPURegister fd, FPURegister fs, Register rt) { 3121 DCHECK_EQ(kArchVariant, kMips64r2); 3122 GenInstrRegister(COP1, D, rt, fs, fd, MOVN_C); 3123 } 3124 3125 3126 // FPR. 3127 void Assembler::selnez(SecondaryField fmt, FPURegister fd, FPURegister fs, 3128 FPURegister ft) { 3129 DCHECK_EQ(kArchVariant, kMips64r6); 3130 DCHECK((fmt == D) || (fmt == S)); 3131 GenInstrRegister(COP1, fmt, ft, fs, fd, SELNEZ_C); 3132 } 3133 3134 3135 // Arithmetic. 3136 3137 void Assembler::add_s(FPURegister fd, FPURegister fs, FPURegister ft) { 3138 GenInstrRegister(COP1, S, ft, fs, fd, ADD_D); 3139 } 3140 3141 3142 void Assembler::add_d(FPURegister fd, FPURegister fs, FPURegister ft) { 3143 GenInstrRegister(COP1, D, ft, fs, fd, ADD_D); 3144 } 3145 3146 3147 void Assembler::sub_s(FPURegister fd, FPURegister fs, FPURegister ft) { 3148 GenInstrRegister(COP1, S, ft, fs, fd, SUB_D); 3149 } 3150 3151 3152 void Assembler::sub_d(FPURegister fd, FPURegister fs, FPURegister ft) { 3153 GenInstrRegister(COP1, D, ft, fs, fd, SUB_D); 3154 } 3155 3156 3157 void Assembler::mul_s(FPURegister fd, FPURegister fs, FPURegister ft) { 3158 GenInstrRegister(COP1, S, ft, fs, fd, MUL_D); 3159 } 3160 3161 3162 void Assembler::mul_d(FPURegister fd, FPURegister fs, FPURegister ft) { 3163 GenInstrRegister(COP1, D, ft, fs, fd, MUL_D); 3164 } 3165 3166 void Assembler::madd_s(FPURegister fd, FPURegister fr, FPURegister fs, 3167 FPURegister ft) { 3168 // On Loongson 3A (MIPS64R2), MADD.S instruction is actually fused MADD.S and 3169 // this causes failure in some of the tests. Since this optimization is rarely 3170 // used, and not used at all on MIPS64R6, this isntruction is removed. 3171 UNREACHABLE(); 3172 } 3173 3174 void Assembler::madd_d(FPURegister fd, FPURegister fr, FPURegister fs, 3175 FPURegister ft) { 3176 // On Loongson 3A (MIPS64R2), MADD.D instruction is actually fused MADD.D and 3177 // this causes failure in some of the tests. Since this optimization is rarely 3178 // used, and not used at all on MIPS64R6, this isntruction is removed. 3179 UNREACHABLE(); 3180 } 3181 3182 void Assembler::msub_s(FPURegister fd, FPURegister fr, FPURegister fs, 3183 FPURegister ft) { 3184 // See explanation for instruction madd_s. 3185 UNREACHABLE(); 3186 } 3187 3188 void Assembler::msub_d(FPURegister fd, FPURegister fr, FPURegister fs, 3189 FPURegister ft) { 3190 // See explanation for instruction madd_d. 3191 UNREACHABLE(); 3192 } 3193 3194 void Assembler::maddf_s(FPURegister fd, FPURegister fs, FPURegister ft) { 3195 DCHECK_EQ(kArchVariant, kMips64r6); 3196 GenInstrRegister(COP1, S, ft, fs, fd, MADDF_S); 3197 } 3198 3199 void Assembler::maddf_d(FPURegister fd, FPURegister fs, FPURegister ft) { 3200 DCHECK_EQ(kArchVariant, kMips64r6); 3201 GenInstrRegister(COP1, D, ft, fs, fd, MADDF_D); 3202 } 3203 3204 void Assembler::msubf_s(FPURegister fd, FPURegister fs, FPURegister ft) { 3205 DCHECK_EQ(kArchVariant, kMips64r6); 3206 GenInstrRegister(COP1, S, ft, fs, fd, MSUBF_S); 3207 } 3208 3209 void Assembler::msubf_d(FPURegister fd, FPURegister fs, FPURegister ft) { 3210 DCHECK_EQ(kArchVariant, kMips64r6); 3211 GenInstrRegister(COP1, D, ft, fs, fd, MSUBF_D); 3212 } 3213 3214 void Assembler::div_s(FPURegister fd, FPURegister fs, FPURegister ft) { 3215 GenInstrRegister(COP1, S, ft, fs, fd, DIV_D); 3216 } 3217 3218 3219 void Assembler::div_d(FPURegister fd, FPURegister fs, FPURegister ft) { 3220 GenInstrRegister(COP1, D, ft, fs, fd, DIV_D); 3221 } 3222 3223 3224 void Assembler::abs_s(FPURegister fd, FPURegister fs) { 3225 GenInstrRegister(COP1, S, f0, fs, fd, ABS_D); 3226 } 3227 3228 3229 void Assembler::abs_d(FPURegister fd, FPURegister fs) { 3230 GenInstrRegister(COP1, D, f0, fs, fd, ABS_D); 3231 } 3232 3233 3234 void Assembler::mov_d(FPURegister fd, FPURegister fs) { 3235 GenInstrRegister(COP1, D, f0, fs, fd, MOV_D); 3236 } 3237 3238 3239 void Assembler::mov_s(FPURegister fd, FPURegister fs) { 3240 GenInstrRegister(COP1, S, f0, fs, fd, MOV_S); 3241 } 3242 3243 3244 void Assembler::neg_s(FPURegister fd, FPURegister fs) { 3245 GenInstrRegister(COP1, S, f0, fs, fd, NEG_D); 3246 } 3247 3248 3249 void Assembler::neg_d(FPURegister fd, FPURegister fs) { 3250 GenInstrRegister(COP1, D, f0, fs, fd, NEG_D); 3251 } 3252 3253 3254 void Assembler::sqrt_s(FPURegister fd, FPURegister fs) { 3255 GenInstrRegister(COP1, S, f0, fs, fd, SQRT_D); 3256 } 3257 3258 3259 void Assembler::sqrt_d(FPURegister fd, FPURegister fs) { 3260 GenInstrRegister(COP1, D, f0, fs, fd, SQRT_D); 3261 } 3262 3263 3264 void Assembler::rsqrt_s(FPURegister fd, FPURegister fs) { 3265 GenInstrRegister(COP1, S, f0, fs, fd, RSQRT_S); 3266 } 3267 3268 3269 void Assembler::rsqrt_d(FPURegister fd, FPURegister fs) { 3270 GenInstrRegister(COP1, D, f0, fs, fd, RSQRT_D); 3271 } 3272 3273 3274 void Assembler::recip_d(FPURegister fd, FPURegister fs) { 3275 GenInstrRegister(COP1, D, f0, fs, fd, RECIP_D); 3276 } 3277 3278 3279 void Assembler::recip_s(FPURegister fd, FPURegister fs) { 3280 GenInstrRegister(COP1, S, f0, fs, fd, RECIP_S); 3281 } 3282 3283 3284 // Conversions. 3285 void Assembler::cvt_w_s(FPURegister fd, FPURegister fs) { 3286 GenInstrRegister(COP1, S, f0, fs, fd, CVT_W_S); 3287 } 3288 3289 3290 void Assembler::cvt_w_d(FPURegister fd, FPURegister fs) { 3291 GenInstrRegister(COP1, D, f0, fs, fd, CVT_W_D); 3292 } 3293 3294 3295 void Assembler::trunc_w_s(FPURegister fd, FPURegister fs) { 3296 GenInstrRegister(COP1, S, f0, fs, fd, TRUNC_W_S); 3297 } 3298 3299 3300 void Assembler::trunc_w_d(FPURegister fd, FPURegister fs) { 3301 GenInstrRegister(COP1, D, f0, fs, fd, TRUNC_W_D); 3302 } 3303 3304 3305 void Assembler::round_w_s(FPURegister fd, FPURegister fs) { 3306 GenInstrRegister(COP1, S, f0, fs, fd, ROUND_W_S); 3307 } 3308 3309 3310 void Assembler::round_w_d(FPURegister fd, FPURegister fs) { 3311 GenInstrRegister(COP1, D, f0, fs, fd, ROUND_W_D); 3312 } 3313 3314 3315 void Assembler::floor_w_s(FPURegister fd, FPURegister fs) { 3316 GenInstrRegister(COP1, S, f0, fs, fd, FLOOR_W_S); 3317 } 3318 3319 3320 void Assembler::floor_w_d(FPURegister fd, FPURegister fs) { 3321 GenInstrRegister(COP1, D, f0, fs, fd, FLOOR_W_D); 3322 } 3323 3324 3325 void Assembler::ceil_w_s(FPURegister fd, FPURegister fs) { 3326 GenInstrRegister(COP1, S, f0, fs, fd, CEIL_W_S); 3327 } 3328 3329 3330 void Assembler::ceil_w_d(FPURegister fd, FPURegister fs) { 3331 GenInstrRegister(COP1, D, f0, fs, fd, CEIL_W_D); 3332 } 3333 3334 3335 void Assembler::rint_s(FPURegister fd, FPURegister fs) { rint(S, fd, fs); } 3336 3337 3338 void Assembler::rint_d(FPURegister fd, FPURegister fs) { rint(D, fd, fs); } 3339 3340 3341 void Assembler::rint(SecondaryField fmt, FPURegister fd, FPURegister fs) { 3342 DCHECK_EQ(kArchVariant, kMips64r6); 3343 GenInstrRegister(COP1, fmt, f0, fs, fd, RINT); 3344 } 3345 3346 3347 void Assembler::cvt_l_s(FPURegister fd, FPURegister fs) { 3348 DCHECK(kArchVariant == kMips64r2 || kArchVariant == kMips64r6); 3349 GenInstrRegister(COP1, S, f0, fs, fd, CVT_L_S); 3350 } 3351 3352 3353 void Assembler::cvt_l_d(FPURegister fd, FPURegister fs) { 3354 DCHECK(kArchVariant == kMips64r2 || kArchVariant == kMips64r6); 3355 GenInstrRegister(COP1, D, f0, fs, fd, CVT_L_D); 3356 } 3357 3358 3359 void Assembler::trunc_l_s(FPURegister fd, FPURegister fs) { 3360 DCHECK(kArchVariant == kMips64r2 || kArchVariant == kMips64r6); 3361 GenInstrRegister(COP1, S, f0, fs, fd, TRUNC_L_S); 3362 } 3363 3364 3365 void Assembler::trunc_l_d(FPURegister fd, FPURegister fs) { 3366 DCHECK(kArchVariant == kMips64r2 || kArchVariant == kMips64r6); 3367 GenInstrRegister(COP1, D, f0, fs, fd, TRUNC_L_D); 3368 } 3369 3370 3371 void Assembler::round_l_s(FPURegister fd, FPURegister fs) { 3372 GenInstrRegister(COP1, S, f0, fs, fd, ROUND_L_S); 3373 } 3374 3375 3376 void Assembler::round_l_d(FPURegister fd, FPURegister fs) { 3377 GenInstrRegister(COP1, D, f0, fs, fd, ROUND_L_D); 3378 } 3379 3380 3381 void Assembler::floor_l_s(FPURegister fd, FPURegister fs) { 3382 GenInstrRegister(COP1, S, f0, fs, fd, FLOOR_L_S); 3383 } 3384 3385 3386 void Assembler::floor_l_d(FPURegister fd, FPURegister fs) { 3387 GenInstrRegister(COP1, D, f0, fs, fd, FLOOR_L_D); 3388 } 3389 3390 3391 void Assembler::ceil_l_s(FPURegister fd, FPURegister fs) { 3392 GenInstrRegister(COP1, S, f0, fs, fd, CEIL_L_S); 3393 } 3394 3395 3396 void Assembler::ceil_l_d(FPURegister fd, FPURegister fs) { 3397 GenInstrRegister(COP1, D, f0, fs, fd, CEIL_L_D); 3398 } 3399 3400 3401 void Assembler::class_s(FPURegister fd, FPURegister fs) { 3402 DCHECK_EQ(kArchVariant, kMips64r6); 3403 GenInstrRegister(COP1, S, f0, fs, fd, CLASS_S); 3404 } 3405 3406 3407 void Assembler::class_d(FPURegister fd, FPURegister fs) { 3408 DCHECK_EQ(kArchVariant, kMips64r6); 3409 GenInstrRegister(COP1, D, f0, fs, fd, CLASS_D); 3410 } 3411 3412 3413 void Assembler::mina(SecondaryField fmt, FPURegister fd, FPURegister fs, 3414 FPURegister ft) { 3415 DCHECK_EQ(kArchVariant, kMips64r6); 3416 DCHECK((fmt == D) || (fmt == S)); 3417 GenInstrRegister(COP1, fmt, ft, fs, fd, MINA); 3418 } 3419 3420 3421 void Assembler::maxa(SecondaryField fmt, FPURegister fd, FPURegister fs, 3422 FPURegister ft) { 3423 DCHECK_EQ(kArchVariant, kMips64r6); 3424 DCHECK((fmt == D) || (fmt == S)); 3425 GenInstrRegister(COP1, fmt, ft, fs, fd, MAXA); 3426 } 3427 3428 3429 void Assembler::cvt_s_w(FPURegister fd, FPURegister fs) { 3430 GenInstrRegister(COP1, W, f0, fs, fd, CVT_S_W); 3431 } 3432 3433 3434 void Assembler::cvt_s_l(FPURegister fd, FPURegister fs) { 3435 DCHECK(kArchVariant == kMips64r2 || kArchVariant == kMips64r6); 3436 GenInstrRegister(COP1, L, f0, fs, fd, CVT_S_L); 3437 } 3438 3439 3440 void Assembler::cvt_s_d(FPURegister fd, FPURegister fs) { 3441 GenInstrRegister(COP1, D, f0, fs, fd, CVT_S_D); 3442 } 3443 3444 3445 void Assembler::cvt_d_w(FPURegister fd, FPURegister fs) { 3446 GenInstrRegister(COP1, W, f0, fs, fd, CVT_D_W); 3447 } 3448 3449 3450 void Assembler::cvt_d_l(FPURegister fd, FPURegister fs) { 3451 DCHECK(kArchVariant == kMips64r2 || kArchVariant == kMips64r6); 3452 GenInstrRegister(COP1, L, f0, fs, fd, CVT_D_L); 3453 } 3454 3455 3456 void Assembler::cvt_d_s(FPURegister fd, FPURegister fs) { 3457 GenInstrRegister(COP1, S, f0, fs, fd, CVT_D_S); 3458 } 3459 3460 3461 // Conditions for >= MIPSr6. 3462 void Assembler::cmp(FPUCondition cond, SecondaryField fmt, 3463 FPURegister fd, FPURegister fs, FPURegister ft) { 3464 DCHECK_EQ(kArchVariant, kMips64r6); 3465 DCHECK_EQ(fmt & ~(31 << kRsShift), 0); 3466 Instr instr = COP1 | fmt | ft.code() << kFtShift | 3467 fs.code() << kFsShift | fd.code() << kFdShift | (0 << 5) | cond; 3468 emit(instr); 3469 } 3470 3471 3472 void Assembler::cmp_s(FPUCondition cond, FPURegister fd, FPURegister fs, 3473 FPURegister ft) { 3474 cmp(cond, W, fd, fs, ft); 3475 } 3476 3477 void Assembler::cmp_d(FPUCondition cond, FPURegister fd, FPURegister fs, 3478 FPURegister ft) { 3479 cmp(cond, L, fd, fs, ft); 3480 } 3481 3482 3483 void Assembler::bc1eqz(int16_t offset, FPURegister ft) { 3484 DCHECK_EQ(kArchVariant, kMips64r6); 3485 BlockTrampolinePoolScope block_trampoline_pool(this); 3486 Instr instr = COP1 | BC1EQZ | ft.code() << kFtShift | (offset & kImm16Mask); 3487 emit(instr); 3488 BlockTrampolinePoolFor(1); // For associated delay slot. 3489 } 3490 3491 3492 void Assembler::bc1nez(int16_t offset, FPURegister ft) { 3493 DCHECK_EQ(kArchVariant, kMips64r6); 3494 BlockTrampolinePoolScope block_trampoline_pool(this); 3495 Instr instr = COP1 | BC1NEZ | ft.code() << kFtShift | (offset & kImm16Mask); 3496 emit(instr); 3497 BlockTrampolinePoolFor(1); // For associated delay slot. 3498 } 3499 3500 3501 // Conditions for < MIPSr6. 3502 void Assembler::c(FPUCondition cond, SecondaryField fmt, 3503 FPURegister fs, FPURegister ft, uint16_t cc) { 3504 DCHECK_NE(kArchVariant, kMips64r6); 3505 DCHECK(is_uint3(cc)); 3506 DCHECK(fmt == S || fmt == D); 3507 DCHECK_EQ(fmt & ~(31 << kRsShift), 0); 3508 Instr instr = COP1 | fmt | ft.code() << kFtShift | fs.code() << kFsShift 3509 | cc << 8 | 3 << 4 | cond; 3510 emit(instr); 3511 } 3512 3513 3514 void Assembler::c_s(FPUCondition cond, FPURegister fs, FPURegister ft, 3515 uint16_t cc) { 3516 c(cond, S, fs, ft, cc); 3517 } 3518 3519 3520 void Assembler::c_d(FPUCondition cond, FPURegister fs, FPURegister ft, 3521 uint16_t cc) { 3522 c(cond, D, fs, ft, cc); 3523 } 3524 3525 3526 void Assembler::fcmp(FPURegister src1, const double src2, 3527 FPUCondition cond) { 3528 DCHECK_EQ(src2, 0.0); 3529 mtc1(zero_reg, f14); 3530 cvt_d_w(f14, f14); 3531 c(cond, D, src1, f14, 0); 3532 } 3533 3534 3535 void Assembler::bc1f(int16_t offset, uint16_t cc) { 3536 BlockTrampolinePoolScope block_trampoline_pool(this); 3537 DCHECK(is_uint3(cc)); 3538 Instr instr = COP1 | BC1 | cc << 18 | 0 << 16 | (offset & kImm16Mask); 3539 emit(instr); 3540 BlockTrampolinePoolFor(1); // For associated delay slot. 3541 } 3542 3543 3544 void Assembler::bc1t(int16_t offset, uint16_t cc) { 3545 BlockTrampolinePoolScope block_trampoline_pool(this); 3546 DCHECK(is_uint3(cc)); 3547 Instr instr = COP1 | BC1 | cc << 18 | 1 << 16 | (offset & kImm16Mask); 3548 emit(instr); 3549 BlockTrampolinePoolFor(1); // For associated delay slot. 3550 } 3551 3552 // ---------- MSA instructions ------------ 3553 #define MSA_BRANCH_LIST(V) \ 3554 V(bz_v, BZ_V) \ 3555 V(bz_b, BZ_B) \ 3556 V(bz_h, BZ_H) \ 3557 V(bz_w, BZ_W) \ 3558 V(bz_d, BZ_D) \ 3559 V(bnz_v, BNZ_V) \ 3560 V(bnz_b, BNZ_B) \ 3561 V(bnz_h, BNZ_H) \ 3562 V(bnz_w, BNZ_W) \ 3563 V(bnz_d, BNZ_D) 3564 3565 #define MSA_BRANCH(name, opcode) \ 3566 void Assembler::name(MSARegister wt, int16_t offset) { \ 3567 GenInstrMsaBranch(opcode, wt, offset); \ 3568 } 3569 3570 MSA_BRANCH_LIST(MSA_BRANCH) 3571 #undef MSA_BRANCH 3572 #undef MSA_BRANCH_LIST 3573 3574 #define MSA_LD_ST_LIST(V) \ 3575 V(ld_b, LD_B) \ 3576 V(ld_h, LD_H) \ 3577 V(ld_w, LD_W) \ 3578 V(ld_d, LD_D) \ 3579 V(st_b, ST_B) \ 3580 V(st_h, ST_H) \ 3581 V(st_w, ST_W) \ 3582 V(st_d, ST_D) 3583 3584 #define MSA_LD_ST(name, opcode) \ 3585 void Assembler::name(MSARegister wd, const MemOperand& rs) { \ 3586 MemOperand source = rs; \ 3587 AdjustBaseAndOffset(source); \ 3588 if (is_int10(source.offset())) { \ 3589 GenInstrMsaMI10(opcode, source.offset(), source.rm(), wd); \ 3590 } else { \ 3591 UseScratchRegisterScope temps(this); \ 3592 Register scratch = temps.Acquire(); \ 3593 DCHECK(rs.rm() != scratch); \ 3594 daddiu(scratch, source.rm(), source.offset()); \ 3595 GenInstrMsaMI10(opcode, 0, scratch, wd); \ 3596 } \ 3597 } 3598 3599 MSA_LD_ST_LIST(MSA_LD_ST) 3600 #undef MSA_LD_ST 3601 #undef MSA_BRANCH_LIST 3602 3603 #define MSA_I10_LIST(V) \ 3604 V(ldi_b, I5_DF_b) \ 3605 V(ldi_h, I5_DF_h) \ 3606 V(ldi_w, I5_DF_w) \ 3607 V(ldi_d, I5_DF_d) 3608 3609 #define MSA_I10(name, format) \ 3610 void Assembler::name(MSARegister wd, int32_t imm10) { \ 3611 GenInstrMsaI10(LDI, format, imm10, wd); \ 3612 } 3613 MSA_I10_LIST(MSA_I10) 3614 #undef MSA_I10 3615 #undef MSA_I10_LIST 3616 3617 #define MSA_I5_LIST(V) \ 3618 V(addvi, ADDVI) \ 3619 V(subvi, SUBVI) \ 3620 V(maxi_s, MAXI_S) \ 3621 V(maxi_u, MAXI_U) \ 3622 V(mini_s, MINI_S) \ 3623 V(mini_u, MINI_U) \ 3624 V(ceqi, CEQI) \ 3625 V(clti_s, CLTI_S) \ 3626 V(clti_u, CLTI_U) \ 3627 V(clei_s, CLEI_S) \ 3628 V(clei_u, CLEI_U) 3629 3630 #define MSA_I5_FORMAT(name, opcode, format) \ 3631 void Assembler::name##_##format(MSARegister wd, MSARegister ws, \ 3632 uint32_t imm5) { \ 3633 GenInstrMsaI5(opcode, I5_DF_##format, imm5, ws, wd); \ 3634 } 3635 3636 #define MSA_I5(name, opcode) \ 3637 MSA_I5_FORMAT(name, opcode, b) \ 3638 MSA_I5_FORMAT(name, opcode, h) \ 3639 MSA_I5_FORMAT(name, opcode, w) \ 3640 MSA_I5_FORMAT(name, opcode, d) 3641 3642 MSA_I5_LIST(MSA_I5) 3643 #undef MSA_I5 3644 #undef MSA_I5_FORMAT 3645 #undef MSA_I5_LIST 3646 3647 #define MSA_I8_LIST(V) \ 3648 V(andi_b, ANDI_B) \ 3649 V(ori_b, ORI_B) \ 3650 V(nori_b, NORI_B) \ 3651 V(xori_b, XORI_B) \ 3652 V(bmnzi_b, BMNZI_B) \ 3653 V(bmzi_b, BMZI_B) \ 3654 V(bseli_b, BSELI_B) \ 3655 V(shf_b, SHF_B) \ 3656 V(shf_h, SHF_H) \ 3657 V(shf_w, SHF_W) 3658 3659 #define MSA_I8(name, opcode) \ 3660 void Assembler::name(MSARegister wd, MSARegister ws, uint32_t imm8) { \ 3661 GenInstrMsaI8(opcode, imm8, ws, wd); \ 3662 } 3663 3664 MSA_I8_LIST(MSA_I8) 3665 #undef MSA_I8 3666 #undef MSA_I8_LIST 3667 3668 #define MSA_VEC_LIST(V) \ 3669 V(and_v, AND_V) \ 3670 V(or_v, OR_V) \ 3671 V(nor_v, NOR_V) \ 3672 V(xor_v, XOR_V) \ 3673 V(bmnz_v, BMNZ_V) \ 3674 V(bmz_v, BMZ_V) \ 3675 V(bsel_v, BSEL_V) 3676 3677 #define MSA_VEC(name, opcode) \ 3678 void Assembler::name(MSARegister wd, MSARegister ws, MSARegister wt) { \ 3679 GenInstrMsaVec(opcode, wt, ws, wd); \ 3680 } 3681 3682 MSA_VEC_LIST(MSA_VEC) 3683 #undef MSA_VEC 3684 #undef MSA_VEC_LIST 3685 3686 #define MSA_2R_LIST(V) \ 3687 V(pcnt, PCNT) \ 3688 V(nloc, NLOC) \ 3689 V(nlzc, NLZC) 3690 3691 #define MSA_2R_FORMAT(name, opcode, format) \ 3692 void Assembler::name##_##format(MSARegister wd, MSARegister ws) { \ 3693 GenInstrMsa2R(opcode, MSA_2R_DF_##format, ws, wd); \ 3694 } 3695 3696 #define MSA_2R(name, opcode) \ 3697 MSA_2R_FORMAT(name, opcode, b) \ 3698 MSA_2R_FORMAT(name, opcode, h) \ 3699 MSA_2R_FORMAT(name, opcode, w) \ 3700 MSA_2R_FORMAT(name, opcode, d) 3701 3702 MSA_2R_LIST(MSA_2R) 3703 #undef MSA_2R 3704 #undef MSA_2R_FORMAT 3705 #undef MSA_2R_LIST 3706 3707 #define MSA_FILL(format) \ 3708 void Assembler::fill_##format(MSARegister wd, Register rs) { \ 3709 DCHECK((kArchVariant == kMips64r6) && IsEnabled(MIPS_SIMD)); \ 3710 DCHECK(rs.is_valid() && wd.is_valid()); \ 3711 Instr instr = MSA | MSA_2R_FORMAT | FILL | MSA_2R_DF_##format | \ 3712 (rs.code() << kWsShift) | (wd.code() << kWdShift) | \ 3713 MSA_VEC_2R_2RF_MINOR; \ 3714 emit(instr); \ 3715 } 3716 3717 MSA_FILL(b) 3718 MSA_FILL(h) 3719 MSA_FILL(w) 3720 MSA_FILL(d) 3721 #undef MSA_FILL 3722 3723 #define MSA_2RF_LIST(V) \ 3724 V(fclass, FCLASS) \ 3725 V(ftrunc_s, FTRUNC_S) \ 3726 V(ftrunc_u, FTRUNC_U) \ 3727 V(fsqrt, FSQRT) \ 3728 V(frsqrt, FRSQRT) \ 3729 V(frcp, FRCP) \ 3730 V(frint, FRINT) \ 3731 V(flog2, FLOG2) \ 3732 V(fexupl, FEXUPL) \ 3733 V(fexupr, FEXUPR) \ 3734 V(ffql, FFQL) \ 3735 V(ffqr, FFQR) \ 3736 V(ftint_s, FTINT_S) \ 3737 V(ftint_u, FTINT_U) \ 3738 V(ffint_s, FFINT_S) \ 3739 V(ffint_u, FFINT_U) 3740 3741 #define MSA_2RF_FORMAT(name, opcode, format) \ 3742 void Assembler::name##_##format(MSARegister wd, MSARegister ws) { \ 3743 GenInstrMsa2RF(opcode, MSA_2RF_DF_##format, ws, wd); \ 3744 } 3745 3746 #define MSA_2RF(name, opcode) \ 3747 MSA_2RF_FORMAT(name, opcode, w) \ 3748 MSA_2RF_FORMAT(name, opcode, d) 3749 3750 MSA_2RF_LIST(MSA_2RF) 3751 #undef MSA_2RF 3752 #undef MSA_2RF_FORMAT 3753 #undef MSA_2RF_LIST 3754 3755 #define MSA_3R_LIST(V) \ 3756 V(sll, SLL_MSA) \ 3757 V(sra, SRA_MSA) \ 3758 V(srl, SRL_MSA) \ 3759 V(bclr, BCLR) \ 3760 V(bset, BSET) \ 3761 V(bneg, BNEG) \ 3762 V(binsl, BINSL) \ 3763 V(binsr, BINSR) \ 3764 V(addv, ADDV) \ 3765 V(subv, SUBV) \ 3766 V(max_s, MAX_S) \ 3767 V(max_u, MAX_U) \ 3768 V(min_s, MIN_S) \ 3769 V(min_u, MIN_U) \ 3770 V(max_a, MAX_A) \ 3771 V(min_a, MIN_A) \ 3772 V(ceq, CEQ) \ 3773 V(clt_s, CLT_S) \ 3774 V(clt_u, CLT_U) \ 3775 V(cle_s, CLE_S) \ 3776 V(cle_u, CLE_U) \ 3777 V(add_a, ADD_A) \ 3778 V(adds_a, ADDS_A) \ 3779 V(adds_s, ADDS_S) \ 3780 V(adds_u, ADDS_U) \ 3781 V(ave_s, AVE_S) \ 3782 V(ave_u, AVE_U) \ 3783 V(aver_s, AVER_S) \ 3784 V(aver_u, AVER_U) \ 3785 V(subs_s, SUBS_S) \ 3786 V(subs_u, SUBS_U) \ 3787 V(subsus_u, SUBSUS_U) \ 3788 V(subsuu_s, SUBSUU_S) \ 3789 V(asub_s, ASUB_S) \ 3790 V(asub_u, ASUB_U) \ 3791 V(mulv, MULV) \ 3792 V(maddv, MADDV) \ 3793 V(msubv, MSUBV) \ 3794 V(div_s, DIV_S_MSA) \ 3795 V(div_u, DIV_U) \ 3796 V(mod_s, MOD_S) \ 3797 V(mod_u, MOD_U) \ 3798 V(dotp_s, DOTP_S) \ 3799 V(dotp_u, DOTP_U) \ 3800 V(dpadd_s, DPADD_S) \ 3801 V(dpadd_u, DPADD_U) \ 3802 V(dpsub_s, DPSUB_S) \ 3803 V(dpsub_u, DPSUB_U) \ 3804 V(pckev, PCKEV) \ 3805 V(pckod, PCKOD) \ 3806 V(ilvl, ILVL) \ 3807 V(ilvr, ILVR) \ 3808 V(ilvev, ILVEV) \ 3809 V(ilvod, ILVOD) \ 3810 V(vshf, VSHF) \ 3811 V(srar, SRAR) \ 3812 V(srlr, SRLR) \ 3813 V(hadd_s, HADD_S) \ 3814 V(hadd_u, HADD_U) \ 3815 V(hsub_s, HSUB_S) \ 3816 V(hsub_u, HSUB_U) 3817 3818 #define MSA_3R_FORMAT(name, opcode, format) \ 3819 void Assembler::name##_##format(MSARegister wd, MSARegister ws, \ 3820 MSARegister wt) { \ 3821 GenInstrMsa3R<MSARegister>(opcode, MSA_3R_DF_##format, wt, ws, wd); \ 3822 } 3823 3824 #define MSA_3R_FORMAT_SLD_SPLAT(name, opcode, format) \ 3825 void Assembler::name##_##format(MSARegister wd, MSARegister ws, \ 3826 Register rt) { \ 3827 GenInstrMsa3R<Register>(opcode, MSA_3R_DF_##format, rt, ws, wd); \ 3828 } 3829 3830 #define MSA_3R(name, opcode) \ 3831 MSA_3R_FORMAT(name, opcode, b) \ 3832 MSA_3R_FORMAT(name, opcode, h) \ 3833 MSA_3R_FORMAT(name, opcode, w) \ 3834 MSA_3R_FORMAT(name, opcode, d) 3835 3836 #define MSA_3R_SLD_SPLAT(name, opcode) \ 3837 MSA_3R_FORMAT_SLD_SPLAT(name, opcode, b) \ 3838 MSA_3R_FORMAT_SLD_SPLAT(name, opcode, h) \ 3839 MSA_3R_FORMAT_SLD_SPLAT(name, opcode, w) \ 3840 MSA_3R_FORMAT_SLD_SPLAT(name, opcode, d) 3841 3842 MSA_3R_LIST(MSA_3R) 3843 MSA_3R_SLD_SPLAT(sld, SLD) 3844 MSA_3R_SLD_SPLAT(splat, SPLAT) 3845 3846 #undef MSA_3R 3847 #undef MSA_3R_FORMAT 3848 #undef MSA_3R_FORMAT_SLD_SPLAT 3849 #undef MSA_3R_SLD_SPLAT 3850 #undef MSA_3R_LIST 3851 3852 #define MSA_3RF_LIST1(V) \ 3853 V(fcaf, FCAF) \ 3854 V(fcun, FCUN) \ 3855 V(fceq, FCEQ) \ 3856 V(fcueq, FCUEQ) \ 3857 V(fclt, FCLT) \ 3858 V(fcult, FCULT) \ 3859 V(fcle, FCLE) \ 3860 V(fcule, FCULE) \ 3861 V(fsaf, FSAF) \ 3862 V(fsun, FSUN) \ 3863 V(fseq, FSEQ) \ 3864 V(fsueq, FSUEQ) \ 3865 V(fslt, FSLT) \ 3866 V(fsult, FSULT) \ 3867 V(fsle, FSLE) \ 3868 V(fsule, FSULE) \ 3869 V(fadd, FADD) \ 3870 V(fsub, FSUB) \ 3871 V(fmul, FMUL) \ 3872 V(fdiv, FDIV) \ 3873 V(fmadd, FMADD) \ 3874 V(fmsub, FMSUB) \ 3875 V(fexp2, FEXP2) \ 3876 V(fmin, FMIN) \ 3877 V(fmin_a, FMIN_A) \ 3878 V(fmax, FMAX) \ 3879 V(fmax_a, FMAX_A) \ 3880 V(fcor, FCOR) \ 3881 V(fcune, FCUNE) \ 3882 V(fcne, FCNE) \ 3883 V(fsor, FSOR) \ 3884 V(fsune, FSUNE) \ 3885 V(fsne, FSNE) 3886 3887 #define MSA_3RF_LIST2(V) \ 3888 V(fexdo, FEXDO) \ 3889 V(ftq, FTQ) \ 3890 V(mul_q, MUL_Q) \ 3891 V(madd_q, MADD_Q) \ 3892 V(msub_q, MSUB_Q) \ 3893 V(mulr_q, MULR_Q) \ 3894 V(maddr_q, MADDR_Q) \ 3895 V(msubr_q, MSUBR_Q) 3896 3897 #define MSA_3RF_FORMAT(name, opcode, df, df_c) \ 3898 void Assembler::name##_##df(MSARegister wd, MSARegister ws, \ 3899 MSARegister wt) { \ 3900 GenInstrMsa3RF(opcode, df_c, wt, ws, wd); \ 3901 } 3902 3903 #define MSA_3RF_1(name, opcode) \ 3904 MSA_3RF_FORMAT(name, opcode, w, 0) \ 3905 MSA_3RF_FORMAT(name, opcode, d, 1) 3906 3907 #define MSA_3RF_2(name, opcode) \ 3908 MSA_3RF_FORMAT(name, opcode, h, 0) \ 3909 MSA_3RF_FORMAT(name, opcode, w, 1) 3910 3911 MSA_3RF_LIST1(MSA_3RF_1) 3912 MSA_3RF_LIST2(MSA_3RF_2) 3913 #undef MSA_3RF_1 3914 #undef MSA_3RF_2 3915 #undef MSA_3RF_FORMAT 3916 #undef MSA_3RF_LIST1 3917 #undef MSA_3RF_LIST2 3918 3919 void Assembler::sldi_b(MSARegister wd, MSARegister ws, uint32_t n) { 3920 GenInstrMsaElm<MSARegister, MSARegister>(SLDI, ELM_DF_B, n, ws, wd); 3921 } 3922 3923 void Assembler::sldi_h(MSARegister wd, MSARegister ws, uint32_t n) { 3924 GenInstrMsaElm<MSARegister, MSARegister>(SLDI, ELM_DF_H, n, ws, wd); 3925 } 3926 3927 void Assembler::sldi_w(MSARegister wd, MSARegister ws, uint32_t n) { 3928 GenInstrMsaElm<MSARegister, MSARegister>(SLDI, ELM_DF_W, n, ws, wd); 3929 } 3930 3931 void Assembler::sldi_d(MSARegister wd, MSARegister ws, uint32_t n) { 3932 GenInstrMsaElm<MSARegister, MSARegister>(SLDI, ELM_DF_D, n, ws, wd); 3933 } 3934 3935 void Assembler::splati_b(MSARegister wd, MSARegister ws, uint32_t n) { 3936 GenInstrMsaElm<MSARegister, MSARegister>(SPLATI, ELM_DF_B, n, ws, wd); 3937 } 3938 3939 void Assembler::splati_h(MSARegister wd, MSARegister ws, uint32_t n) { 3940 GenInstrMsaElm<MSARegister, MSARegister>(SPLATI, ELM_DF_H, n, ws, wd); 3941 } 3942 3943 void Assembler::splati_w(MSARegister wd, MSARegister ws, uint32_t n) { 3944 GenInstrMsaElm<MSARegister, MSARegister>(SPLATI, ELM_DF_W, n, ws, wd); 3945 } 3946 3947 void Assembler::splati_d(MSARegister wd, MSARegister ws, uint32_t n) { 3948 GenInstrMsaElm<MSARegister, MSARegister>(SPLATI, ELM_DF_D, n, ws, wd); 3949 } 3950 3951 void Assembler::copy_s_b(Register rd, MSARegister ws, uint32_t n) { 3952 GenInstrMsaElm<Register, MSARegister>(COPY_S, ELM_DF_B, n, ws, rd); 3953 } 3954 3955 void Assembler::copy_s_h(Register rd, MSARegister ws, uint32_t n) { 3956 GenInstrMsaElm<Register, MSARegister>(COPY_S, ELM_DF_H, n, ws, rd); 3957 } 3958 3959 void Assembler::copy_s_w(Register rd, MSARegister ws, uint32_t n) { 3960 GenInstrMsaElm<Register, MSARegister>(COPY_S, ELM_DF_W, n, ws, rd); 3961 } 3962 3963 void Assembler::copy_s_d(Register rd, MSARegister ws, uint32_t n) { 3964 GenInstrMsaElm<Register, MSARegister>(COPY_S, ELM_DF_D, n, ws, rd); 3965 } 3966 3967 void Assembler::copy_u_b(Register rd, MSARegister ws, uint32_t n) { 3968 GenInstrMsaElm<Register, MSARegister>(COPY_U, ELM_DF_B, n, ws, rd); 3969 } 3970 3971 void Assembler::copy_u_h(Register rd, MSARegister ws, uint32_t n) { 3972 GenInstrMsaElm<Register, MSARegister>(COPY_U, ELM_DF_H, n, ws, rd); 3973 } 3974 3975 void Assembler::copy_u_w(Register rd, MSARegister ws, uint32_t n) { 3976 GenInstrMsaElm<Register, MSARegister>(COPY_U, ELM_DF_W, n, ws, rd); 3977 } 3978 3979 void Assembler::insert_b(MSARegister wd, uint32_t n, Register rs) { 3980 GenInstrMsaElm<MSARegister, Register>(INSERT, ELM_DF_B, n, rs, wd); 3981 } 3982 3983 void Assembler::insert_h(MSARegister wd, uint32_t n, Register rs) { 3984 GenInstrMsaElm<MSARegister, Register>(INSERT, ELM_DF_H, n, rs, wd); 3985 } 3986 3987 void Assembler::insert_w(MSARegister wd, uint32_t n, Register rs) { 3988 GenInstrMsaElm<MSARegister, Register>(INSERT, ELM_DF_W, n, rs, wd); 3989 } 3990 3991 void Assembler::insert_d(MSARegister wd, uint32_t n, Register rs) { 3992 GenInstrMsaElm<MSARegister, Register>(INSERT, ELM_DF_D, n, rs, wd); 3993 } 3994 3995 void Assembler::insve_b(MSARegister wd, uint32_t n, MSARegister ws) { 3996 GenInstrMsaElm<MSARegister, MSARegister>(INSVE, ELM_DF_B, n, ws, wd); 3997 } 3998 3999 void Assembler::insve_h(MSARegister wd, uint32_t n, MSARegister ws) { 4000 GenInstrMsaElm<MSARegister, MSARegister>(INSVE, ELM_DF_H, n, ws, wd); 4001 } 4002 4003 void Assembler::insve_w(MSARegister wd, uint32_t n, MSARegister ws) { 4004 GenInstrMsaElm<MSARegister, MSARegister>(INSVE, ELM_DF_W, n, ws, wd); 4005 } 4006 4007 void Assembler::insve_d(MSARegister wd, uint32_t n, MSARegister ws) { 4008 GenInstrMsaElm<MSARegister, MSARegister>(INSVE, ELM_DF_D, n, ws, wd); 4009 } 4010 4011 void Assembler::move_v(MSARegister wd, MSARegister ws) { 4012 DCHECK((kArchVariant == kMips64r6) && IsEnabled(MIPS_SIMD)); 4013 DCHECK(ws.is_valid() && wd.is_valid()); 4014 Instr instr = MSA | MOVE_V | (ws.code() << kWsShift) | 4015 (wd.code() << kWdShift) | MSA_ELM_MINOR; 4016 emit(instr); 4017 } 4018 4019 void Assembler::ctcmsa(MSAControlRegister cd, Register rs) { 4020 DCHECK((kArchVariant == kMips64r6) && IsEnabled(MIPS_SIMD)); 4021 DCHECK(cd.is_valid() && rs.is_valid()); 4022 Instr instr = MSA | CTCMSA | (rs.code() << kWsShift) | 4023 (cd.code() << kWdShift) | MSA_ELM_MINOR; 4024 emit(instr); 4025 } 4026 4027 void Assembler::cfcmsa(Register rd, MSAControlRegister cs) { 4028 DCHECK((kArchVariant == kMips64r6) && IsEnabled(MIPS_SIMD)); 4029 DCHECK(rd.is_valid() && cs.is_valid()); 4030 Instr instr = MSA | CFCMSA | (cs.code() << kWsShift) | 4031 (rd.code() << kWdShift) | MSA_ELM_MINOR; 4032 emit(instr); 4033 } 4034 4035 #define MSA_BIT_LIST(V) \ 4036 V(slli, SLLI) \ 4037 V(srai, SRAI) \ 4038 V(srli, SRLI) \ 4039 V(bclri, BCLRI) \ 4040 V(bseti, BSETI) \ 4041 V(bnegi, BNEGI) \ 4042 V(binsli, BINSLI) \ 4043 V(binsri, BINSRI) \ 4044 V(sat_s, SAT_S) \ 4045 V(sat_u, SAT_U) \ 4046 V(srari, SRARI) \ 4047 V(srlri, SRLRI) 4048 4049 #define MSA_BIT_FORMAT(name, opcode, format) \ 4050 void Assembler::name##_##format(MSARegister wd, MSARegister ws, \ 4051 uint32_t m) { \ 4052 GenInstrMsaBit(opcode, BIT_DF_##format, m, ws, wd); \ 4053 } 4054 4055 #define MSA_BIT(name, opcode) \ 4056 MSA_BIT_FORMAT(name, opcode, b) \ 4057 MSA_BIT_FORMAT(name, opcode, h) \ 4058 MSA_BIT_FORMAT(name, opcode, w) \ 4059 MSA_BIT_FORMAT(name, opcode, d) 4060 4061 MSA_BIT_LIST(MSA_BIT) 4062 #undef MSA_BIT 4063 #undef MSA_BIT_FORMAT 4064 #undef MSA_BIT_LIST 4065 4066 int Assembler::RelocateInternalReference(RelocInfo::Mode rmode, Address pc, 4067 intptr_t pc_delta) { 4068 if (RelocInfo::IsInternalReference(rmode)) { 4069 int64_t* p = reinterpret_cast<int64_t*>(pc); 4070 if (*p == kEndOfJumpChain) { 4071 return 0; // Number of instructions patched. 4072 } 4073 *p += pc_delta; 4074 return 2; // Number of instructions patched. 4075 } 4076 Instr instr = instr_at(pc); 4077 DCHECK(RelocInfo::IsInternalReferenceEncoded(rmode)); 4078 if (IsLui(instr)) { 4079 Instr instr_lui = instr_at(pc + 0 * kInstrSize); 4080 Instr instr_ori = instr_at(pc + 1 * kInstrSize); 4081 Instr instr_ori2 = instr_at(pc + 3 * kInstrSize); 4082 DCHECK(IsOri(instr_ori)); 4083 DCHECK(IsOri(instr_ori2)); 4084 // TODO(plind): symbolic names for the shifts. 4085 int64_t imm = (instr_lui & static_cast<int64_t>(kImm16Mask)) << 48; 4086 imm |= (instr_ori & static_cast<int64_t>(kImm16Mask)) << 32; 4087 imm |= (instr_ori2 & static_cast<int64_t>(kImm16Mask)) << 16; 4088 // Sign extend address. 4089 imm >>= 16; 4090 4091 if (imm == kEndOfJumpChain) { 4092 return 0; // Number of instructions patched. 4093 } 4094 imm += pc_delta; 4095 DCHECK_EQ(imm & 3, 0); 4096 4097 instr_lui &= ~kImm16Mask; 4098 instr_ori &= ~kImm16Mask; 4099 instr_ori2 &= ~kImm16Mask; 4100 4101 instr_at_put(pc + 0 * kInstrSize, instr_lui | ((imm >> 32) & kImm16Mask)); 4102 instr_at_put(pc + 1 * kInstrSize, instr_ori | (imm >> 16 & kImm16Mask)); 4103 instr_at_put(pc + 3 * kInstrSize, instr_ori2 | (imm & kImm16Mask)); 4104 return 4; // Number of instructions patched. 4105 } else if (IsJ(instr) || IsJal(instr)) { 4106 // Regular j/jal relocation. 4107 uint32_t imm28 = (instr & static_cast<int32_t>(kImm26Mask)) << 2; 4108 imm28 += pc_delta; 4109 imm28 &= kImm28Mask; 4110 instr &= ~kImm26Mask; 4111 DCHECK_EQ(imm28 & 3, 0); 4112 uint32_t imm26 = static_cast<uint32_t>(imm28 >> 2); 4113 instr_at_put(pc, instr | (imm26 & kImm26Mask)); 4114 return 1; // Number of instructions patched. 4115 } else { 4116 DCHECK(((instr & kJumpRawMask) == kJRawMark) || 4117 ((instr & kJumpRawMask) == kJalRawMark)); 4118 // Unbox raw offset and emit j/jal. 4119 int32_t imm28 = (instr & static_cast<int32_t>(kImm26Mask)) << 2; 4120 // Sign extend 28-bit offset to 32-bit. 4121 imm28 = (imm28 << 4) >> 4; 4122 uint64_t target = 4123 static_cast<int64_t>(imm28) + reinterpret_cast<uint64_t>(pc); 4124 target &= kImm28Mask; 4125 DCHECK_EQ(imm28 & 3, 0); 4126 uint32_t imm26 = static_cast<uint32_t>(target >> 2); 4127 // Check markings whether to emit j or jal. 4128 uint32_t unbox = (instr & kJRawMark) ? J : JAL; 4129 instr_at_put(pc, unbox | (imm26 & kImm26Mask)); 4130 return 1; // Number of instructions patched. 4131 } 4132 } 4133 4134 4135 void Assembler::GrowBuffer() { 4136 if (!own_buffer_) FATAL("external code buffer is too small"); 4137 4138 // Compute new buffer size. 4139 CodeDesc desc; // the new buffer 4140 if (buffer_size_ < 1 * MB) { 4141 desc.buffer_size = 2*buffer_size_; 4142 } else { 4143 desc.buffer_size = buffer_size_ + 1*MB; 4144 } 4145 4146 // Some internal data structures overflow for very large buffers, 4147 // they must ensure that kMaximalBufferSize is not too large. 4148 if (desc.buffer_size > kMaximalBufferSize) { 4149 V8::FatalProcessOutOfMemory(nullptr, "Assembler::GrowBuffer"); 4150 } 4151 4152 // Set up new buffer. 4153 desc.buffer = NewArray<byte>(desc.buffer_size); 4154 desc.origin = this; 4155 4156 desc.instr_size = pc_offset(); 4157 desc.reloc_size = 4158 static_cast<int>((buffer_ + buffer_size_) - reloc_info_writer.pos()); 4159 4160 // Copy the data. 4161 intptr_t pc_delta = desc.buffer - buffer_; 4162 intptr_t rc_delta = (desc.buffer + desc.buffer_size) - 4163 (buffer_ + buffer_size_); 4164 MemMove(desc.buffer, buffer_, desc.instr_size); 4165 MemMove(reloc_info_writer.pos() + rc_delta, 4166 reloc_info_writer.pos(), desc.reloc_size); 4167 4168 // Switch buffers. 4169 DeleteArray(buffer_); 4170 buffer_ = desc.buffer; 4171 buffer_size_ = desc.buffer_size; 4172 pc_ += pc_delta; 4173 reloc_info_writer.Reposition(reloc_info_writer.pos() + rc_delta, 4174 reloc_info_writer.last_pc() + pc_delta); 4175 4176 // Relocate runtime entries. 4177 for (RelocIterator it(desc); !it.done(); it.next()) { 4178 RelocInfo::Mode rmode = it.rinfo()->rmode(); 4179 if (rmode == RelocInfo::INTERNAL_REFERENCE) { 4180 RelocateInternalReference(rmode, it.rinfo()->pc(), pc_delta); 4181 } 4182 } 4183 DCHECK(!overflow()); 4184 } 4185 4186 4187 void Assembler::db(uint8_t data) { 4188 CheckForEmitInForbiddenSlot(); 4189 EmitHelper(data); 4190 } 4191 4192 4193 void Assembler::dd(uint32_t data) { 4194 CheckForEmitInForbiddenSlot(); 4195 EmitHelper(data); 4196 } 4197 4198 4199 void Assembler::dq(uint64_t data) { 4200 CheckForEmitInForbiddenSlot(); 4201 EmitHelper(data); 4202 } 4203 4204 4205 void Assembler::dd(Label* label) { 4206 uint64_t data; 4207 CheckForEmitInForbiddenSlot(); 4208 if (label->is_bound()) { 4209 data = reinterpret_cast<uint64_t>(buffer_ + label->pos()); 4210 } else { 4211 data = jump_address(label); 4212 unbound_labels_count_++; 4213 internal_reference_positions_.insert(label->pos()); 4214 } 4215 RecordRelocInfo(RelocInfo::INTERNAL_REFERENCE); 4216 EmitHelper(data); 4217 } 4218 4219 4220 void Assembler::RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data) { 4221 // We do not try to reuse pool constants. 4222 RelocInfo rinfo(reinterpret_cast<Address>(pc_), rmode, data, nullptr); 4223 if (!RelocInfo::IsNone(rinfo.rmode())) { 4224 if (options().disable_reloc_info_for_patching) return; 4225 // Don't record external references unless the heap will be serialized. 4226 if (RelocInfo::IsOnlyForSerializer(rmode) && 4227 !options().record_reloc_info_for_serialization && !emit_debug_code()) { 4228 return; 4229 } 4230 DCHECK_GE(buffer_space(), kMaxRelocSize); // Too late to grow buffer here. 4231 reloc_info_writer.Write(&rinfo); 4232 } 4233 } 4234 4235 4236 void Assembler::BlockTrampolinePoolFor(int instructions) { 4237 CheckTrampolinePoolQuick(instructions); 4238 BlockTrampolinePoolBefore(pc_offset() + instructions * kInstrSize); 4239 } 4240 4241 4242 void Assembler::CheckTrampolinePool() { 4243 // Some small sequences of instructions must not be broken up by the 4244 // insertion of a trampoline pool; such sequences are protected by setting 4245 // either trampoline_pool_blocked_nesting_ or no_trampoline_pool_before_, 4246 // which are both checked here. Also, recursive calls to CheckTrampolinePool 4247 // are blocked by trampoline_pool_blocked_nesting_. 4248 if ((trampoline_pool_blocked_nesting_ > 0) || 4249 (pc_offset() < no_trampoline_pool_before_)) { 4250 // Emission is currently blocked; make sure we try again as soon as 4251 // possible. 4252 if (trampoline_pool_blocked_nesting_ > 0) { 4253 next_buffer_check_ = pc_offset() + kInstrSize; 4254 } else { 4255 next_buffer_check_ = no_trampoline_pool_before_; 4256 } 4257 return; 4258 } 4259 4260 DCHECK(!trampoline_emitted_); 4261 DCHECK_GE(unbound_labels_count_, 0); 4262 if (unbound_labels_count_ > 0) { 4263 // First we emit jump (2 instructions), then we emit trampoline pool. 4264 { BlockTrampolinePoolScope block_trampoline_pool(this); 4265 Label after_pool; 4266 if (kArchVariant == kMips64r6) { 4267 bc(&after_pool); 4268 } else { 4269 b(&after_pool); 4270 } 4271 nop(); 4272 4273 int pool_start = pc_offset(); 4274 for (int i = 0; i < unbound_labels_count_; i++) { 4275 { 4276 if (kArchVariant == kMips64r6) { 4277 bc(&after_pool); 4278 nop(); 4279 } else { 4280 or_(t8, ra, zero_reg); 4281 nal(); // Read PC into ra register. 4282 lui(t9, 0); // Branch delay slot. 4283 ori(t9, t9, 0); 4284 daddu(t9, ra, t9); 4285 or_(ra, t8, zero_reg); 4286 // Instruction jr will take or_ from the next trampoline. 4287 // in its branch delay slot. This is the expected behavior 4288 // in order to decrease size of trampoline pool. 4289 jr(t9); 4290 } 4291 } 4292 } 4293 nop(); 4294 bind(&after_pool); 4295 trampoline_ = Trampoline(pool_start, unbound_labels_count_); 4296 4297 trampoline_emitted_ = true; 4298 // As we are only going to emit trampoline once, we need to prevent any 4299 // further emission. 4300 next_buffer_check_ = kMaxInt; 4301 } 4302 } else { 4303 // Number of branches to unbound label at this point is zero, so we can 4304 // move next buffer check to maximum. 4305 next_buffer_check_ = pc_offset() + 4306 kMaxBranchOffset - kTrampolineSlotsSize * 16; 4307 } 4308 return; 4309 } 4310 4311 4312 Address Assembler::target_address_at(Address pc) { 4313 Instr instr0 = instr_at(pc); 4314 Instr instr1 = instr_at(pc + 1 * kInstrSize); 4315 Instr instr3 = instr_at(pc + 3 * kInstrSize); 4316 4317 // Interpret 4 instructions for address generated by li: See listing in 4318 // Assembler::set_target_address_at() just below. 4319 if ((GetOpcodeField(instr0) == LUI) && (GetOpcodeField(instr1) == ORI) && 4320 (GetOpcodeField(instr3) == ORI)) { 4321 // Assemble the 48 bit value. 4322 int64_t addr = static_cast<int64_t>( 4323 ((uint64_t)(GetImmediate16(instr0)) << 32) | 4324 ((uint64_t)(GetImmediate16(instr1)) << 16) | 4325 ((uint64_t)(GetImmediate16(instr3)))); 4326 4327 // Sign extend to get canonical address. 4328 addr = (addr << 16) >> 16; 4329 return static_cast<Address>(addr); 4330 } 4331 // We should never get here, force a bad address if we do. 4332 UNREACHABLE(); 4333 } 4334 4335 4336 // MIPS and ia32 use opposite encoding for qNaN and sNaN, such that ia32 4337 // qNaN is a MIPS sNaN, and ia32 sNaN is MIPS qNaN. If running from a heap 4338 // snapshot generated on ia32, the resulting MIPS sNaN must be quieted. 4339 // OS::nan_value() returns a qNaN. 4340 void Assembler::QuietNaN(HeapObject* object) { 4341 HeapNumber::cast(object)->set_value(std::numeric_limits<double>::quiet_NaN()); 4342 } 4343 4344 4345 // On Mips64, a target address is stored in a 4-instruction sequence: 4346 // 0: lui(rd, (j.imm64_ >> 32) & kImm16Mask); 4347 // 1: ori(rd, rd, (j.imm64_ >> 16) & kImm16Mask); 4348 // 2: dsll(rd, rd, 16); 4349 // 3: ori(rd, rd, j.imm32_ & kImm16Mask); 4350 // 4351 // Patching the address must replace all the lui & ori instructions, 4352 // and flush the i-cache. 4353 // 4354 // There is an optimization below, which emits a nop when the address 4355 // fits in just 16 bits. This is unlikely to help, and should be benchmarked, 4356 // and possibly removed. 4357 void Assembler::set_target_value_at(Address pc, uint64_t target, 4358 ICacheFlushMode icache_flush_mode) { 4359 // There is an optimization where only 4 instructions are used to load address 4360 // in code on MIP64 because only 48-bits of address is effectively used. 4361 // It relies on fact the upper [63:48] bits are not used for virtual address 4362 // translation and they have to be set according to value of bit 47 in order 4363 // get canonical address. 4364 Instr instr1 = instr_at(pc + kInstrSize); 4365 uint32_t rt_code = GetRt(instr1); 4366 uint32_t* p = reinterpret_cast<uint32_t*>(pc); 4367 4368 #ifdef DEBUG 4369 // Check we have the result from a li macro-instruction. 4370 Instr instr0 = instr_at(pc); 4371 Instr instr3 = instr_at(pc + kInstrSize * 3); 4372 DCHECK((GetOpcodeField(instr0) == LUI && GetOpcodeField(instr1) == ORI && 4373 GetOpcodeField(instr3) == ORI)); 4374 #endif 4375 4376 // Must use 4 instructions to insure patchable code. 4377 // lui rt, upper-16. 4378 // ori rt, rt, lower-16. 4379 // dsll rt, rt, 16. 4380 // ori rt rt, lower-16. 4381 *p = LUI | (rt_code << kRtShift) | ((target >> 32) & kImm16Mask); 4382 *(p + 1) = ORI | (rt_code << kRtShift) | (rt_code << kRsShift) | 4383 ((target >> 16) & kImm16Mask); 4384 *(p + 3) = ORI | (rt_code << kRsShift) | (rt_code << kRtShift) | 4385 (target & kImm16Mask); 4386 4387 if (icache_flush_mode != SKIP_ICACHE_FLUSH) { 4388 Assembler::FlushICache(pc, 4 * kInstrSize); 4389 } 4390 } 4391 4392 UseScratchRegisterScope::UseScratchRegisterScope(Assembler* assembler) 4393 : available_(assembler->GetScratchRegisterList()), 4394 old_available_(*available_) {} 4395 4396 UseScratchRegisterScope::~UseScratchRegisterScope() { 4397 *available_ = old_available_; 4398 } 4399 4400 Register UseScratchRegisterScope::Acquire() { 4401 DCHECK_NOT_NULL(available_); 4402 DCHECK_NE(*available_, 0); 4403 int index = static_cast<int>(base::bits::CountTrailingZeros32(*available_)); 4404 *available_ &= ~(1UL << index); 4405 4406 return Register::from_code(index); 4407 } 4408 4409 bool UseScratchRegisterScope::hasAvailable() const { return *available_ != 0; } 4410 4411 } // namespace internal 4412 } // namespace v8 4413 4414 #endif // V8_TARGET_ARCH_MIPS64 4415