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