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/mips/assembler-mips-inl.h"
     42 
     43 namespace v8 {
     44 namespace internal {
     45 
     46 // Get the CPU features enabled by the build. For cross compilation the
     47 // preprocessor symbols CAN_USE_FPU_INSTRUCTIONS
     48 // can be defined to enable FPU instructions when building the
     49 // snapshot.
     50 static unsigned CpuFeaturesImpliedByCompiler() {
     51   unsigned answer = 0;
     52 #ifdef CAN_USE_FPU_INSTRUCTIONS
     53   answer |= 1u << FPU;
     54 #endif  // def CAN_USE_FPU_INSTRUCTIONS
     55 
     56   // If the compiler is allowed to use FPU then we can use FPU too in our code
     57   // generation even when generating snapshots.  This won't work for cross
     58   // compilation.
     59 #if defined(__mips__) && defined(__mips_hard_float) && __mips_hard_float != 0
     60   answer |= 1u << FPU;
     61 #endif
     62 
     63   return answer;
     64 }
     65 
     66 
     67 void CpuFeatures::ProbeImpl(bool cross_compile) {
     68   supported_ |= CpuFeaturesImpliedByCompiler();
     69 
     70   // Only use statically determined features for cross compile (snapshot).
     71   if (cross_compile) return;
     72 
     73   // If the compiler is allowed to use fpu then we can use fpu too in our
     74   // code generation.
     75 #ifndef __mips__
     76   // For the simulator build, use FPU.
     77   supported_ |= 1u << FPU;
     78 #if defined(_MIPS_ARCH_MIPS32R6)
     79   // FP64 mode is implied on r6.
     80   supported_ |= 1u << FP64FPU;
     81 #endif
     82 #if defined(FPU_MODE_FP64)
     83   supported_ |= 1u << FP64FPU;
     84 #endif
     85 #else
     86   // Probe for additional features at runtime.
     87   base::CPU cpu;
     88   if (cpu.has_fpu()) supported_ |= 1u << FPU;
     89 #if defined(FPU_MODE_FPXX)
     90   if (cpu.is_fp64_mode()) supported_ |= 1u << FP64FPU;
     91 #elif defined(FPU_MODE_FP64)
     92   supported_ |= 1u << FP64FPU;
     93 #endif
     94 #if defined(_MIPS_ARCH_MIPS32RX)
     95   if (cpu.architecture() == 6) {
     96     supported_ |= 1u << MIPSr6;
     97   } else if (cpu.architecture() == 2) {
     98     supported_ |= 1u << MIPSr1;
     99     supported_ |= 1u << MIPSr2;
    100   } else {
    101     supported_ |= 1u << MIPSr1;
    102   }
    103 #endif
    104 #endif
    105 }
    106 
    107 
    108 void CpuFeatures::PrintTarget() { }
    109 void CpuFeatures::PrintFeatures() { }
    110 
    111 
    112 int ToNumber(Register reg) {
    113   DCHECK(reg.is_valid());
    114   const int kNumbers[] = {
    115     0,    // zero_reg
    116     1,    // at
    117     2,    // v0
    118     3,    // v1
    119     4,    // a0
    120     5,    // a1
    121     6,    // a2
    122     7,    // a3
    123     8,    // t0
    124     9,    // t1
    125     10,   // t2
    126     11,   // t3
    127     12,   // t4
    128     13,   // t5
    129     14,   // t6
    130     15,   // t7
    131     16,   // s0
    132     17,   // s1
    133     18,   // s2
    134     19,   // s3
    135     20,   // s4
    136     21,   // s5
    137     22,   // s6
    138     23,   // s7
    139     24,   // t8
    140     25,   // t9
    141     26,   // k0
    142     27,   // k1
    143     28,   // gp
    144     29,   // sp
    145     30,   // fp
    146     31,   // ra
    147   };
    148   return kNumbers[reg.code()];
    149 }
    150 
    151 
    152 Register ToRegister(int num) {
    153   DCHECK(num >= 0 && num < kNumRegisters);
    154   const Register kRegisters[] = {
    155     zero_reg,
    156     at,
    157     v0, v1,
    158     a0, a1, a2, a3,
    159     t0, t1, t2, t3, t4, t5, t6, t7,
    160     s0, s1, s2, s3, s4, s5, s6, s7,
    161     t8, t9,
    162     k0, k1,
    163     gp,
    164     sp,
    165     fp,
    166     ra
    167   };
    168   return kRegisters[num];
    169 }
    170 
    171 
    172 // -----------------------------------------------------------------------------
    173 // Implementation of RelocInfo.
    174 
    175 const int RelocInfo::kApplyMask = RelocInfo::kCodeTargetMask |
    176                                   1 << RelocInfo::INTERNAL_REFERENCE |
    177                                   1 << RelocInfo::INTERNAL_REFERENCE_ENCODED;
    178 
    179 
    180 bool RelocInfo::IsCodedSpecially() {
    181   // The deserializer needs to know whether a pointer is specially coded.  Being
    182   // specially coded on MIPS means that it is a lui/ori instruction, and that is
    183   // always the case inside code objects.
    184   return true;
    185 }
    186 
    187 
    188 bool RelocInfo::IsInConstantPool() {
    189   return false;
    190 }
    191 
    192 Address RelocInfo::wasm_memory_reference() {
    193   DCHECK(IsWasmMemoryReference(rmode_));
    194   return Assembler::target_address_at(pc_, host_);
    195 }
    196 
    197 Address RelocInfo::wasm_global_reference() {
    198   DCHECK(IsWasmGlobalReference(rmode_));
    199   return Assembler::target_address_at(pc_, host_);
    200 }
    201 
    202 uint32_t RelocInfo::wasm_memory_size_reference() {
    203   DCHECK(IsWasmMemorySizeReference(rmode_));
    204   return reinterpret_cast<uint32_t>(Assembler::target_address_at(pc_, host_));
    205 }
    206 
    207 uint32_t RelocInfo::wasm_function_table_size_reference() {
    208   DCHECK(IsWasmFunctionTableSizeReference(rmode_));
    209   return reinterpret_cast<uint32_t>(Assembler::target_address_at(pc_, host_));
    210 }
    211 
    212 void RelocInfo::unchecked_update_wasm_memory_reference(
    213     Address address, ICacheFlushMode flush_mode) {
    214   Assembler::set_target_address_at(isolate_, pc_, host_, address, flush_mode);
    215 }
    216 
    217 void RelocInfo::unchecked_update_wasm_size(uint32_t size,
    218                                            ICacheFlushMode flush_mode) {
    219   Assembler::set_target_address_at(isolate_, pc_, host_,
    220                                    reinterpret_cast<Address>(size), flush_mode);
    221 }
    222 
    223 // -----------------------------------------------------------------------------
    224 // Implementation of Operand and MemOperand.
    225 // See assembler-mips-inl.h for inlined constructors.
    226 
    227 Operand::Operand(Handle<Object> handle) {
    228   AllowDeferredHandleDereference using_raw_address;
    229   rm_ = no_reg;
    230   // Verify all Objects referred by code are NOT in new space.
    231   Object* obj = *handle;
    232   if (obj->IsHeapObject()) {
    233     imm32_ = reinterpret_cast<intptr_t>(handle.location());
    234     rmode_ = RelocInfo::EMBEDDED_OBJECT;
    235   } else {
    236     // No relocation needed.
    237     imm32_ = reinterpret_cast<intptr_t>(obj);
    238     rmode_ = RelocInfo::NONE32;
    239   }
    240 }
    241 
    242 
    243 MemOperand::MemOperand(Register rm, int32_t offset) : Operand(rm) {
    244   offset_ = offset;
    245 }
    246 
    247 
    248 MemOperand::MemOperand(Register rm, int32_t unit, int32_t multiplier,
    249                        OffsetAddend offset_addend) : Operand(rm) {
    250   offset_ = unit * multiplier + offset_addend;
    251 }
    252 
    253 
    254 // -----------------------------------------------------------------------------
    255 // Specific instructions, constants, and masks.
    256 
    257 static const int kNegOffset = 0x00008000;
    258 // addiu(sp, sp, 4) aka Pop() operation or part of Pop(r)
    259 // operations as post-increment of sp.
    260 const Instr kPopInstruction = ADDIU | (Register::kCode_sp << kRsShift) |
    261                               (Register::kCode_sp << kRtShift) |
    262                               (kPointerSize & kImm16Mask);  // NOLINT
    263 // addiu(sp, sp, -4) part of Push(r) operation as pre-decrement of sp.
    264 const Instr kPushInstruction = ADDIU | (Register::kCode_sp << kRsShift) |
    265                                (Register::kCode_sp << kRtShift) |
    266                                (-kPointerSize & kImm16Mask);  // NOLINT
    267 // sw(r, MemOperand(sp, 0))
    268 const Instr kPushRegPattern =
    269     SW | (Register::kCode_sp << kRsShift) | (0 & kImm16Mask);  // NOLINT
    270 //  lw(r, MemOperand(sp, 0))
    271 const Instr kPopRegPattern =
    272     LW | (Register::kCode_sp << kRsShift) | (0 & kImm16Mask);  // NOLINT
    273 
    274 const Instr kLwRegFpOffsetPattern =
    275     LW | (Register::kCode_fp << kRsShift) | (0 & kImm16Mask);  // NOLINT
    276 
    277 const Instr kSwRegFpOffsetPattern =
    278     SW | (Register::kCode_fp << kRsShift) | (0 & kImm16Mask);  // NOLINT
    279 
    280 const Instr kLwRegFpNegOffsetPattern = LW | (Register::kCode_fp << kRsShift) |
    281                                        (kNegOffset & kImm16Mask);  // NOLINT
    282 
    283 const Instr kSwRegFpNegOffsetPattern = SW | (Register::kCode_fp << kRsShift) |
    284                                        (kNegOffset & kImm16Mask);  // NOLINT
    285 // A mask for the Rt register for push, pop, lw, sw instructions.
    286 const Instr kRtMask = kRtFieldMask;
    287 const Instr kLwSwInstrTypeMask = 0xffe00000;
    288 const Instr kLwSwInstrArgumentMask  = ~kLwSwInstrTypeMask;
    289 const Instr kLwSwOffsetMask = kImm16Mask;
    290 
    291 Assembler::Assembler(Isolate* isolate, void* buffer, int buffer_size)
    292     : AssemblerBase(isolate, buffer, buffer_size),
    293       recorded_ast_id_(TypeFeedbackId::None()) {
    294   reloc_info_writer.Reposition(buffer_ + buffer_size_, pc_);
    295 
    296   last_trampoline_pool_end_ = 0;
    297   no_trampoline_pool_before_ = 0;
    298   trampoline_pool_blocked_nesting_ = 0;
    299   // We leave space (16 * kTrampolineSlotsSize)
    300   // for BlockTrampolinePoolScope buffer.
    301   next_buffer_check_ = FLAG_force_long_branches
    302       ? kMaxInt : kMaxBranchOffset - kTrampolineSlotsSize * 16;
    303   internal_trampoline_exception_ = false;
    304   last_bound_pos_ = 0;
    305 
    306   trampoline_emitted_ = FLAG_force_long_branches;
    307   unbound_labels_count_ = 0;
    308   block_buffer_growth_ = false;
    309 
    310   ClearRecordedAstId();
    311 }
    312 
    313 
    314 void Assembler::GetCode(CodeDesc* desc) {
    315   EmitForbiddenSlotInstruction();
    316   DCHECK(pc_ <= reloc_info_writer.pos());  // No overlap.
    317   // Set up code descriptor.
    318   desc->buffer = buffer_;
    319   desc->buffer_size = buffer_size_;
    320   desc->instr_size = pc_offset();
    321   desc->reloc_size = (buffer_ + buffer_size_) - reloc_info_writer.pos();
    322   desc->origin = this;
    323   desc->constant_pool_size = 0;
    324   desc->unwinding_info_size = 0;
    325   desc->unwinding_info = nullptr;
    326 }
    327 
    328 
    329 void Assembler::Align(int m) {
    330   DCHECK(m >= 4 && base::bits::IsPowerOfTwo32(m));
    331   EmitForbiddenSlotInstruction();
    332   while ((pc_offset() & (m - 1)) != 0) {
    333     nop();
    334   }
    335 }
    336 
    337 
    338 void Assembler::CodeTargetAlign() {
    339   // No advantage to aligning branch/call targets to more than
    340   // single instruction, that I am aware of.
    341   Align(4);
    342 }
    343 
    344 
    345 Register Assembler::GetRtReg(Instr instr) {
    346   Register rt;
    347   rt.reg_code = (instr & kRtFieldMask) >> kRtShift;
    348   return rt;
    349 }
    350 
    351 
    352 Register Assembler::GetRsReg(Instr instr) {
    353   Register rs;
    354   rs.reg_code = (instr & kRsFieldMask) >> kRsShift;
    355   return rs;
    356 }
    357 
    358 
    359 Register Assembler::GetRdReg(Instr instr) {
    360   Register rd;
    361   rd.reg_code = (instr & kRdFieldMask) >> kRdShift;
    362   return rd;
    363 }
    364 
    365 
    366 uint32_t Assembler::GetRt(Instr instr) {
    367   return (instr & kRtFieldMask) >> kRtShift;
    368 }
    369 
    370 
    371 uint32_t Assembler::GetRtField(Instr instr) {
    372   return instr & kRtFieldMask;
    373 }
    374 
    375 
    376 uint32_t Assembler::GetRs(Instr instr) {
    377   return (instr & kRsFieldMask) >> kRsShift;
    378 }
    379 
    380 
    381 uint32_t Assembler::GetRsField(Instr instr) {
    382   return instr & kRsFieldMask;
    383 }
    384 
    385 
    386 uint32_t Assembler::GetRd(Instr instr) {
    387   return  (instr & kRdFieldMask) >> kRdShift;
    388 }
    389 
    390 
    391 uint32_t Assembler::GetRdField(Instr instr) {
    392   return  instr & kRdFieldMask;
    393 }
    394 
    395 
    396 uint32_t Assembler::GetSa(Instr instr) {
    397   return (instr & kSaFieldMask) >> kSaShift;
    398 }
    399 
    400 
    401 uint32_t Assembler::GetSaField(Instr instr) {
    402   return instr & kSaFieldMask;
    403 }
    404 
    405 
    406 uint32_t Assembler::GetOpcodeField(Instr instr) {
    407   return instr & kOpcodeMask;
    408 }
    409 
    410 
    411 uint32_t Assembler::GetFunction(Instr instr) {
    412   return (instr & kFunctionFieldMask) >> kFunctionShift;
    413 }
    414 
    415 
    416 uint32_t Assembler::GetFunctionField(Instr instr) {
    417   return instr & kFunctionFieldMask;
    418 }
    419 
    420 
    421 uint32_t Assembler::GetImmediate16(Instr instr) {
    422   return instr & kImm16Mask;
    423 }
    424 
    425 
    426 uint32_t Assembler::GetLabelConst(Instr instr) {
    427   return instr & ~kImm16Mask;
    428 }
    429 
    430 
    431 bool Assembler::IsPop(Instr instr) {
    432   return (instr & ~kRtMask) == kPopRegPattern;
    433 }
    434 
    435 
    436 bool Assembler::IsPush(Instr instr) {
    437   return (instr & ~kRtMask) == kPushRegPattern;
    438 }
    439 
    440 
    441 bool Assembler::IsSwRegFpOffset(Instr instr) {
    442   return ((instr & kLwSwInstrTypeMask) == kSwRegFpOffsetPattern);
    443 }
    444 
    445 
    446 bool Assembler::IsLwRegFpOffset(Instr instr) {
    447   return ((instr & kLwSwInstrTypeMask) == kLwRegFpOffsetPattern);
    448 }
    449 
    450 
    451 bool Assembler::IsSwRegFpNegOffset(Instr instr) {
    452   return ((instr & (kLwSwInstrTypeMask | kNegOffset)) ==
    453           kSwRegFpNegOffsetPattern);
    454 }
    455 
    456 
    457 bool Assembler::IsLwRegFpNegOffset(Instr instr) {
    458   return ((instr & (kLwSwInstrTypeMask | kNegOffset)) ==
    459           kLwRegFpNegOffsetPattern);
    460 }
    461 
    462 
    463 // Labels refer to positions in the (to be) generated code.
    464 // There are bound, linked, and unused labels.
    465 //
    466 // Bound labels refer to known positions in the already
    467 // generated code. pos() is the position the label refers to.
    468 //
    469 // Linked labels refer to unknown positions in the code
    470 // to be generated; pos() is the position of the last
    471 // instruction using the label.
    472 
    473 // The link chain is terminated by a value in the instruction of -1,
    474 // which is an otherwise illegal value (branch -1 is inf loop).
    475 // The instruction 16-bit offset field addresses 32-bit words, but in
    476 // code is conv to an 18-bit value addressing bytes, hence the -4 value.
    477 
    478 const int kEndOfChain = -4;
    479 // Determines the end of the Jump chain (a subset of the label link chain).
    480 const int kEndOfJumpChain = 0;
    481 
    482 
    483 bool Assembler::IsBranch(Instr instr) {
    484   uint32_t opcode   = GetOpcodeField(instr);
    485   uint32_t rt_field = GetRtField(instr);
    486   uint32_t rs_field = GetRsField(instr);
    487   // Checks if the instruction is a branch.
    488   bool isBranch =
    489       opcode == BEQ || opcode == BNE || opcode == BLEZ || opcode == BGTZ ||
    490       opcode == BEQL || opcode == BNEL || opcode == BLEZL || opcode == BGTZL ||
    491       (opcode == REGIMM && (rt_field == BLTZ || rt_field == BGEZ ||
    492                             rt_field == BLTZAL || rt_field == BGEZAL)) ||
    493       (opcode == COP1 && rs_field == BC1) ||  // Coprocessor branch.
    494       (opcode == COP1 && rs_field == BC1EQZ) ||
    495       (opcode == COP1 && rs_field == BC1NEZ);
    496   if (!isBranch && IsMipsArchVariant(kMips32r6)) {
    497     // All the 3 variants of POP10 (BOVC, BEQC, BEQZALC) and
    498     // POP30 (BNVC, BNEC, BNEZALC) are branch ops.
    499     isBranch |= opcode == POP10 || opcode == POP30 || opcode == BC ||
    500                 opcode == BALC ||
    501                 (opcode == POP66 && rs_field != 0) ||  // BEQZC
    502                 (opcode == POP76 && rs_field != 0);    // BNEZC
    503   }
    504   return isBranch;
    505 }
    506 
    507 
    508 bool Assembler::IsBc(Instr instr) {
    509   uint32_t opcode = GetOpcodeField(instr);
    510   // Checks if the instruction is a BC or BALC.
    511   return opcode == BC || opcode == BALC;
    512 }
    513 
    514 
    515 bool Assembler::IsBzc(Instr instr) {
    516   uint32_t opcode = GetOpcodeField(instr);
    517   // Checks if the instruction is BEQZC or BNEZC.
    518   return (opcode == POP66 && GetRsField(instr) != 0) ||
    519          (opcode == POP76 && GetRsField(instr) != 0);
    520 }
    521 
    522 
    523 bool Assembler::IsEmittedConstant(Instr instr) {
    524   uint32_t label_constant = GetLabelConst(instr);
    525   return label_constant == 0;  // Emitted label const in reg-exp engine.
    526 }
    527 
    528 
    529 bool Assembler::IsBeq(Instr instr) {
    530   return GetOpcodeField(instr) == BEQ;
    531 }
    532 
    533 
    534 bool Assembler::IsBne(Instr instr) {
    535   return GetOpcodeField(instr) == BNE;
    536 }
    537 
    538 
    539 bool Assembler::IsBeqzc(Instr instr) {
    540   uint32_t opcode = GetOpcodeField(instr);
    541   return opcode == POP66 && GetRsField(instr) != 0;
    542 }
    543 
    544 
    545 bool Assembler::IsBnezc(Instr instr) {
    546   uint32_t opcode = GetOpcodeField(instr);
    547   return opcode == POP76 && GetRsField(instr) != 0;
    548 }
    549 
    550 
    551 bool Assembler::IsBeqc(Instr instr) {
    552   uint32_t opcode = GetOpcodeField(instr);
    553   uint32_t rs = GetRsField(instr);
    554   uint32_t rt = GetRtField(instr);
    555   return opcode == POP10 && rs != 0 && rs < rt;  // && rt != 0
    556 }
    557 
    558 
    559 bool Assembler::IsBnec(Instr instr) {
    560   uint32_t opcode = GetOpcodeField(instr);
    561   uint32_t rs = GetRsField(instr);
    562   uint32_t rt = GetRtField(instr);
    563   return opcode == POP30 && rs != 0 && rs < rt;  // && rt != 0
    564 }
    565 
    566 bool Assembler::IsJicOrJialc(Instr instr) {
    567   uint32_t opcode = GetOpcodeField(instr);
    568   uint32_t rs = GetRsField(instr);
    569   return (opcode == POP66 || opcode == POP76) && rs == 0;
    570 }
    571 
    572 bool Assembler::IsJump(Instr instr) {
    573   uint32_t opcode   = GetOpcodeField(instr);
    574   uint32_t rt_field = GetRtField(instr);
    575   uint32_t rd_field = GetRdField(instr);
    576   uint32_t function_field = GetFunctionField(instr);
    577   // Checks if the instruction is a jump.
    578   return opcode == J || opcode == JAL ||
    579       (opcode == SPECIAL && rt_field == 0 &&
    580       ((function_field == JALR) || (rd_field == 0 && (function_field == JR))));
    581 }
    582 
    583 bool Assembler::IsJ(Instr instr) {
    584   uint32_t opcode = GetOpcodeField(instr);
    585   // Checks if the instruction is a jump.
    586   return opcode == J;
    587 }
    588 
    589 
    590 bool Assembler::IsJal(Instr instr) {
    591   return GetOpcodeField(instr) == JAL;
    592 }
    593 
    594 
    595 bool Assembler::IsJr(Instr instr) {
    596   if (!IsMipsArchVariant(kMips32r6))  {
    597     return GetOpcodeField(instr) == SPECIAL && GetFunctionField(instr) == JR;
    598   } else {
    599     return GetOpcodeField(instr) == SPECIAL &&
    600         GetRdField(instr) == 0  && GetFunctionField(instr) == JALR;
    601   }
    602 }
    603 
    604 
    605 bool Assembler::IsJalr(Instr instr) {
    606   return GetOpcodeField(instr) == SPECIAL &&
    607          GetRdField(instr) != 0  && GetFunctionField(instr) == JALR;
    608 }
    609 
    610 
    611 bool Assembler::IsLui(Instr instr) {
    612   uint32_t opcode = GetOpcodeField(instr);
    613   // Checks if the instruction is a load upper immediate.
    614   return opcode == LUI;
    615 }
    616 
    617 
    618 bool Assembler::IsOri(Instr instr) {
    619   uint32_t opcode = GetOpcodeField(instr);
    620   // Checks if the instruction is a load upper immediate.
    621   return opcode == ORI;
    622 }
    623 
    624 
    625 bool Assembler::IsNop(Instr instr, unsigned int type) {
    626   // See Assembler::nop(type).
    627   DCHECK(type < 32);
    628   uint32_t opcode = GetOpcodeField(instr);
    629   uint32_t function = GetFunctionField(instr);
    630   uint32_t rt = GetRt(instr);
    631   uint32_t rd = GetRd(instr);
    632   uint32_t sa = GetSa(instr);
    633 
    634   // Traditional mips nop == sll(zero_reg, zero_reg, 0)
    635   // When marking non-zero type, use sll(zero_reg, at, type)
    636   // to avoid use of mips ssnop and ehb special encodings
    637   // of the sll instruction.
    638 
    639   Register nop_rt_reg = (type == 0) ? zero_reg : at;
    640   bool ret = (opcode == SPECIAL && function == SLL &&
    641               rd == static_cast<uint32_t>(ToNumber(zero_reg)) &&
    642               rt == static_cast<uint32_t>(ToNumber(nop_rt_reg)) &&
    643               sa == type);
    644 
    645   return ret;
    646 }
    647 
    648 
    649 int32_t Assembler::GetBranchOffset(Instr instr) {
    650   DCHECK(IsBranch(instr));
    651   return (static_cast<int16_t>(instr & kImm16Mask)) << 2;
    652 }
    653 
    654 
    655 bool Assembler::IsLw(Instr instr) {
    656   return (static_cast<uint32_t>(instr & kOpcodeMask) == LW);
    657 }
    658 
    659 
    660 int16_t Assembler::GetLwOffset(Instr instr) {
    661   DCHECK(IsLw(instr));
    662   return ((instr & kImm16Mask));
    663 }
    664 
    665 
    666 Instr Assembler::SetLwOffset(Instr instr, int16_t offset) {
    667   DCHECK(IsLw(instr));
    668 
    669   // We actually create a new lw instruction based on the original one.
    670   Instr temp_instr = LW | (instr & kRsFieldMask) | (instr & kRtFieldMask)
    671       | (offset & kImm16Mask);
    672 
    673   return temp_instr;
    674 }
    675 
    676 
    677 bool Assembler::IsSw(Instr instr) {
    678   return (static_cast<uint32_t>(instr & kOpcodeMask) == SW);
    679 }
    680 
    681 
    682 Instr Assembler::SetSwOffset(Instr instr, int16_t offset) {
    683   DCHECK(IsSw(instr));
    684   return ((instr & ~kImm16Mask) | (offset & kImm16Mask));
    685 }
    686 
    687 
    688 bool Assembler::IsAddImmediate(Instr instr) {
    689   return ((instr & kOpcodeMask) == ADDIU);
    690 }
    691 
    692 
    693 Instr Assembler::SetAddImmediateOffset(Instr instr, int16_t offset) {
    694   DCHECK(IsAddImmediate(instr));
    695   return ((instr & ~kImm16Mask) | (offset & kImm16Mask));
    696 }
    697 
    698 
    699 bool Assembler::IsAndImmediate(Instr instr) {
    700   return GetOpcodeField(instr) == ANDI;
    701 }
    702 
    703 
    704 static Assembler::OffsetSize OffsetSizeInBits(Instr instr) {
    705   if (IsMipsArchVariant(kMips32r6)) {
    706     if (Assembler::IsBc(instr)) {
    707       return Assembler::OffsetSize::kOffset26;
    708     } else if (Assembler::IsBzc(instr)) {
    709       return Assembler::OffsetSize::kOffset21;
    710     }
    711   }
    712   return Assembler::OffsetSize::kOffset16;
    713 }
    714 
    715 
    716 static inline int32_t AddBranchOffset(int pos, Instr instr) {
    717   int bits = OffsetSizeInBits(instr);
    718   const int32_t mask = (1 << bits) - 1;
    719   bits = 32 - bits;
    720 
    721   // Do NOT change this to <<2. We rely on arithmetic shifts here, assuming
    722   // the compiler uses arithmetic shifts for signed integers.
    723   int32_t imm = ((instr & mask) << bits) >> (bits - 2);
    724 
    725   if (imm == kEndOfChain) {
    726     // EndOfChain sentinel is returned directly, not relative to pc or pos.
    727     return kEndOfChain;
    728   } else {
    729     return pos + Assembler::kBranchPCOffset + imm;
    730   }
    731 }
    732 
    733 uint32_t Assembler::CreateTargetAddress(Instr instr_lui, Instr instr_jic) {
    734   DCHECK(IsLui(instr_lui) && IsJicOrJialc(instr_jic));
    735   int16_t jic_offset = GetImmediate16(instr_jic);
    736   int16_t lui_offset = GetImmediate16(instr_lui);
    737 
    738   if (jic_offset < 0) {
    739     lui_offset += kImm16Mask;
    740   }
    741   uint32_t lui_offset_u = (static_cast<uint32_t>(lui_offset)) << kLuiShift;
    742   uint32_t jic_offset_u = static_cast<uint32_t>(jic_offset) & kImm16Mask;
    743 
    744   return lui_offset_u | jic_offset_u;
    745 }
    746 
    747 // Use just lui and jic instructions. Insert lower part of the target address in
    748 // jic offset part. Since jic sign-extends offset and then add it with register,
    749 // before that addition, difference between upper part of the target address and
    750 // upper part of the sign-extended offset (0xffff or 0x0000), will be inserted
    751 // in jic register with lui instruction.
    752 void Assembler::UnpackTargetAddress(uint32_t address, int16_t& lui_offset,
    753                                     int16_t& jic_offset) {
    754   lui_offset = (address & kHiMask) >> kLuiShift;
    755   jic_offset = address & kLoMask;
    756 
    757   if (jic_offset < 0) {
    758     lui_offset -= kImm16Mask;
    759   }
    760 }
    761 
    762 void Assembler::UnpackTargetAddressUnsigned(uint32_t address,
    763                                             uint32_t& lui_offset,
    764                                             uint32_t& jic_offset) {
    765   int16_t lui_offset16 = (address & kHiMask) >> kLuiShift;
    766   int16_t jic_offset16 = address & kLoMask;
    767 
    768   if (jic_offset16 < 0) {
    769     lui_offset16 -= kImm16Mask;
    770   }
    771   lui_offset = static_cast<uint32_t>(lui_offset16) & kImm16Mask;
    772   jic_offset = static_cast<uint32_t>(jic_offset16) & kImm16Mask;
    773 }
    774 
    775 int Assembler::target_at(int pos, bool is_internal) {
    776   Instr instr = instr_at(pos);
    777   if (is_internal) {
    778     if (instr == 0) {
    779       return kEndOfChain;
    780     } else {
    781       int32_t instr_address = reinterpret_cast<int32_t>(buffer_ + pos);
    782       int delta = static_cast<int>(instr_address - instr);
    783       DCHECK(pos > delta);
    784       return pos - delta;
    785     }
    786   }
    787   if ((instr & ~kImm16Mask) == 0) {
    788     // Emitted label constant, not part of a branch.
    789     if (instr == 0) {
    790        return kEndOfChain;
    791      } else {
    792        int32_t imm18 =((instr & static_cast<int32_t>(kImm16Mask)) << 16) >> 14;
    793        return (imm18 + pos);
    794      }
    795   }
    796   // Check we have a branch or jump instruction.
    797   DCHECK(IsBranch(instr) || IsLui(instr));
    798   if (IsBranch(instr)) {
    799     return AddBranchOffset(pos, instr);
    800   } else {
    801     Instr instr1 = instr_at(pos + 0 * Assembler::kInstrSize);
    802     Instr instr2 = instr_at(pos + 1 * Assembler::kInstrSize);
    803     DCHECK(IsOri(instr2) || IsJicOrJialc(instr2));
    804     int32_t imm;
    805     if (IsJicOrJialc(instr2)) {
    806       imm = CreateTargetAddress(instr1, instr2);
    807     } else {
    808       imm = (instr1 & static_cast<int32_t>(kImm16Mask)) << kLuiShift;
    809       imm |= (instr2 & static_cast<int32_t>(kImm16Mask));
    810     }
    811 
    812     if (imm == kEndOfJumpChain) {
    813       // EndOfChain sentinel is returned directly, not relative to pc or pos.
    814       return kEndOfChain;
    815     } else {
    816       uint32_t instr_address = reinterpret_cast<int32_t>(buffer_ + pos);
    817       int32_t delta = instr_address - imm;
    818       DCHECK(pos > delta);
    819       return pos - delta;
    820     }
    821   }
    822   return 0;
    823 }
    824 
    825 
    826 static inline Instr SetBranchOffset(int32_t pos, int32_t target_pos,
    827                                     Instr instr) {
    828   int32_t bits = OffsetSizeInBits(instr);
    829   int32_t imm = target_pos - (pos + Assembler::kBranchPCOffset);
    830   DCHECK((imm & 3) == 0);
    831   imm >>= 2;
    832 
    833   const int32_t mask = (1 << bits) - 1;
    834   instr &= ~mask;
    835   DCHECK(is_intn(imm, bits));
    836 
    837   return instr | (imm & mask);
    838 }
    839 
    840 
    841 void Assembler::target_at_put(int32_t pos, int32_t target_pos,
    842                               bool is_internal) {
    843   Instr instr = instr_at(pos);
    844 
    845   if (is_internal) {
    846     uint32_t imm = reinterpret_cast<uint32_t>(buffer_) + target_pos;
    847     instr_at_put(pos, imm);
    848     return;
    849   }
    850   if ((instr & ~kImm16Mask) == 0) {
    851     DCHECK(target_pos == kEndOfChain || target_pos >= 0);
    852     // Emitted label constant, not part of a branch.
    853     // Make label relative to Code* of generated Code object.
    854     instr_at_put(pos, target_pos + (Code::kHeaderSize - kHeapObjectTag));
    855     return;
    856   }
    857 
    858   DCHECK(IsBranch(instr) || IsLui(instr));
    859   if (IsBranch(instr)) {
    860     instr = SetBranchOffset(pos, target_pos, instr);
    861     instr_at_put(pos, instr);
    862   } else {
    863     Instr instr1 = instr_at(pos + 0 * Assembler::kInstrSize);
    864     Instr instr2 = instr_at(pos + 1 * Assembler::kInstrSize);
    865     DCHECK(IsOri(instr2) || IsJicOrJialc(instr2));
    866     uint32_t imm = reinterpret_cast<uint32_t>(buffer_) + target_pos;
    867     DCHECK((imm & 3) == 0);
    868     DCHECK(IsLui(instr1) && (IsJicOrJialc(instr2) || IsOri(instr2)));
    869     instr1 &= ~kImm16Mask;
    870     instr2 &= ~kImm16Mask;
    871 
    872     if (IsJicOrJialc(instr2)) {
    873       uint32_t lui_offset_u, jic_offset_u;
    874       UnpackTargetAddressUnsigned(imm, lui_offset_u, jic_offset_u);
    875       instr_at_put(pos + 0 * Assembler::kInstrSize, instr1 | lui_offset_u);
    876       instr_at_put(pos + 1 * Assembler::kInstrSize, instr2 | jic_offset_u);
    877     } else {
    878       instr_at_put(pos + 0 * Assembler::kInstrSize,
    879                    instr1 | ((imm & kHiMask) >> kLuiShift));
    880       instr_at_put(pos + 1 * Assembler::kInstrSize,
    881                    instr2 | (imm & kImm16Mask));
    882     }
    883   }
    884 }
    885 
    886 
    887 void Assembler::print(Label* L) {
    888   if (L->is_unused()) {
    889     PrintF("unused label\n");
    890   } else if (L->is_bound()) {
    891     PrintF("bound label to %d\n", L->pos());
    892   } else if (L->is_linked()) {
    893     Label l = *L;
    894     PrintF("unbound label");
    895     while (l.is_linked()) {
    896       PrintF("@ %d ", l.pos());
    897       Instr instr = instr_at(l.pos());
    898       if ((instr & ~kImm16Mask) == 0) {
    899         PrintF("value\n");
    900       } else {
    901         PrintF("%d\n", instr);
    902       }
    903       next(&l, is_internal_reference(&l));
    904     }
    905   } else {
    906     PrintF("label in inconsistent state (pos = %d)\n", L->pos_);
    907   }
    908 }
    909 
    910 
    911 void Assembler::bind_to(Label* L, int pos) {
    912   DCHECK(0 <= pos && pos <= pc_offset());  // Must have valid binding position.
    913   int32_t trampoline_pos = kInvalidSlotPos;
    914   bool is_internal = false;
    915   if (L->is_linked() && !trampoline_emitted_) {
    916     unbound_labels_count_--;
    917     if (!is_internal_reference(L)) {
    918       next_buffer_check_ += kTrampolineSlotsSize;
    919     }
    920   }
    921 
    922   while (L->is_linked()) {
    923     int32_t fixup_pos = L->pos();
    924     int32_t dist = pos - fixup_pos;
    925     is_internal = is_internal_reference(L);
    926     next(L, is_internal);  // Call next before overwriting link with target at
    927                            // fixup_pos.
    928     Instr instr = instr_at(fixup_pos);
    929     if (is_internal) {
    930       target_at_put(fixup_pos, pos, is_internal);
    931     } else {
    932       if (IsBranch(instr)) {
    933         int branch_offset = BranchOffset(instr);
    934         if (dist > branch_offset) {
    935           if (trampoline_pos == kInvalidSlotPos) {
    936             trampoline_pos = get_trampoline_entry(fixup_pos);
    937             CHECK(trampoline_pos != kInvalidSlotPos);
    938           }
    939           CHECK((trampoline_pos - fixup_pos) <= branch_offset);
    940           target_at_put(fixup_pos, trampoline_pos, false);
    941           fixup_pos = trampoline_pos;
    942         }
    943         target_at_put(fixup_pos, pos, false);
    944       } else {
    945         target_at_put(fixup_pos, pos, false);
    946       }
    947     }
    948   }
    949   L->bind_to(pos);
    950 
    951   // Keep track of the last bound label so we don't eliminate any instructions
    952   // before a bound label.
    953   if (pos > last_bound_pos_)
    954     last_bound_pos_ = pos;
    955 }
    956 
    957 
    958 void Assembler::bind(Label* L) {
    959   DCHECK(!L->is_bound());  // Label can only be bound once.
    960   bind_to(L, pc_offset());
    961 }
    962 
    963 
    964 void Assembler::next(Label* L, bool is_internal) {
    965   DCHECK(L->is_linked());
    966   int link = target_at(L->pos(), is_internal);
    967   if (link == kEndOfChain) {
    968     L->Unuse();
    969   } else {
    970     DCHECK(link >= 0);
    971     L->link_to(link);
    972   }
    973 }
    974 
    975 
    976 bool Assembler::is_near(Label* L) {
    977   DCHECK(L->is_bound());
    978   return pc_offset() - L->pos() < kMaxBranchOffset - 4 * kInstrSize;
    979 }
    980 
    981 
    982 bool Assembler::is_near(Label* L, OffsetSize bits) {
    983   if (L == nullptr || !L->is_bound()) return true;
    984   return pc_offset() - L->pos() < (1 << (bits + 2 - 1)) - 1 - 5 * kInstrSize;
    985 }
    986 
    987 
    988 bool Assembler::is_near_branch(Label* L) {
    989   DCHECK(L->is_bound());
    990   return IsMipsArchVariant(kMips32r6) ? is_near_r6(L) : is_near_pre_r6(L);
    991 }
    992 
    993 
    994 int Assembler::BranchOffset(Instr instr) {
    995   // At pre-R6 and for other R6 branches the offset is 16 bits.
    996   int bits = OffsetSize::kOffset16;
    997 
    998   if (IsMipsArchVariant(kMips32r6)) {
    999     uint32_t opcode = GetOpcodeField(instr);
   1000     switch (opcode) {
   1001       // Checks BC or BALC.
   1002       case BC:
   1003       case BALC:
   1004         bits = OffsetSize::kOffset26;
   1005         break;
   1006 
   1007       // Checks BEQZC or BNEZC.
   1008       case POP66:
   1009       case POP76:
   1010         if (GetRsField(instr) != 0) bits = OffsetSize::kOffset21;
   1011         break;
   1012       default:
   1013         break;
   1014     }
   1015   }
   1016 
   1017   return (1 << (bits + 2 - 1)) - 1;
   1018 }
   1019 
   1020 
   1021 // We have to use a temporary register for things that can be relocated even
   1022 // if they can be encoded in the MIPS's 16 bits of immediate-offset instruction
   1023 // space.  There is no guarantee that the relocated location can be similarly
   1024 // encoded.
   1025 bool Assembler::MustUseReg(RelocInfo::Mode rmode) {
   1026   return !RelocInfo::IsNone(rmode);
   1027 }
   1028 
   1029 void Assembler::GenInstrRegister(Opcode opcode,
   1030                                  Register rs,
   1031                                  Register rt,
   1032                                  Register rd,
   1033                                  uint16_t sa,
   1034                                  SecondaryField func) {
   1035   DCHECK(rd.is_valid() && rs.is_valid() && rt.is_valid() && is_uint5(sa));
   1036   Instr instr = opcode | (rs.code() << kRsShift) | (rt.code() << kRtShift)
   1037       | (rd.code() << kRdShift) | (sa << kSaShift) | func;
   1038   emit(instr);
   1039 }
   1040 
   1041 
   1042 void Assembler::GenInstrRegister(Opcode opcode,
   1043                                  Register rs,
   1044                                  Register rt,
   1045                                  uint16_t msb,
   1046                                  uint16_t lsb,
   1047                                  SecondaryField func) {
   1048   DCHECK(rs.is_valid() && rt.is_valid() && is_uint5(msb) && is_uint5(lsb));
   1049   Instr instr = opcode | (rs.code() << kRsShift) | (rt.code() << kRtShift)
   1050       | (msb << kRdShift) | (lsb << kSaShift) | func;
   1051   emit(instr);
   1052 }
   1053 
   1054 
   1055 void Assembler::GenInstrRegister(Opcode opcode,
   1056                                  SecondaryField fmt,
   1057                                  FPURegister ft,
   1058                                  FPURegister fs,
   1059                                  FPURegister fd,
   1060                                  SecondaryField func) {
   1061   DCHECK(fd.is_valid() && fs.is_valid() && ft.is_valid());
   1062   Instr instr = opcode | fmt | (ft.code() << kFtShift) | (fs.code() << kFsShift)
   1063       | (fd.code() << kFdShift) | func;
   1064   emit(instr);
   1065 }
   1066 
   1067 
   1068 void Assembler::GenInstrRegister(Opcode opcode,
   1069                                  FPURegister fr,
   1070                                  FPURegister ft,
   1071                                  FPURegister fs,
   1072                                  FPURegister fd,
   1073                                  SecondaryField func) {
   1074   DCHECK(fd.is_valid() && fr.is_valid() && fs.is_valid() && ft.is_valid());
   1075   Instr instr = opcode | (fr.code() << kFrShift) | (ft.code() << kFtShift)
   1076       | (fs.code() << kFsShift) | (fd.code() << kFdShift) | func;
   1077   emit(instr);
   1078 }
   1079 
   1080 
   1081 void Assembler::GenInstrRegister(Opcode opcode,
   1082                                  SecondaryField fmt,
   1083                                  Register rt,
   1084                                  FPURegister fs,
   1085                                  FPURegister fd,
   1086                                  SecondaryField func) {
   1087   DCHECK(fd.is_valid() && fs.is_valid() && rt.is_valid());
   1088   Instr instr = opcode | fmt | (rt.code() << kRtShift)
   1089       | (fs.code() << kFsShift) | (fd.code() << kFdShift) | func;
   1090   emit(instr);
   1091 }
   1092 
   1093 
   1094 void Assembler::GenInstrRegister(Opcode opcode,
   1095                                  SecondaryField fmt,
   1096                                  Register rt,
   1097                                  FPUControlRegister fs,
   1098                                  SecondaryField func) {
   1099   DCHECK(fs.is_valid() && rt.is_valid());
   1100   Instr instr =
   1101       opcode | fmt | (rt.code() << kRtShift) | (fs.code() << kFsShift) | func;
   1102   emit(instr);
   1103 }
   1104 
   1105 
   1106 // Instructions with immediate value.
   1107 // Registers are in the order of the instruction encoding, from left to right.
   1108 void Assembler::GenInstrImmediate(Opcode opcode, Register rs, Register rt,
   1109                                   int32_t j,
   1110                                   CompactBranchType is_compact_branch) {
   1111   DCHECK(rs.is_valid() && rt.is_valid() && (is_int16(j) || is_uint16(j)));
   1112   Instr instr = opcode | (rs.code() << kRsShift) | (rt.code() << kRtShift)
   1113       | (j & kImm16Mask);
   1114   emit(instr, is_compact_branch);
   1115 }
   1116 
   1117 
   1118 void Assembler::GenInstrImmediate(Opcode opcode, Register rs, SecondaryField SF,
   1119                                   int32_t j,
   1120                                   CompactBranchType is_compact_branch) {
   1121   DCHECK(rs.is_valid() && (is_int16(j) || is_uint16(j)));
   1122   Instr instr = opcode | (rs.code() << kRsShift) | SF | (j & kImm16Mask);
   1123   emit(instr, is_compact_branch);
   1124 }
   1125 
   1126 
   1127 void Assembler::GenInstrImmediate(Opcode opcode, Register rs, FPURegister ft,
   1128                                   int32_t j,
   1129                                   CompactBranchType is_compact_branch) {
   1130   DCHECK(rs.is_valid() && ft.is_valid() && (is_int16(j) || is_uint16(j)));
   1131   Instr instr = opcode | (rs.code() << kRsShift) | (ft.code() << kFtShift)
   1132       | (j & kImm16Mask);
   1133   emit(instr, is_compact_branch);
   1134 }
   1135 
   1136 
   1137 void Assembler::GenInstrImmediate(Opcode opcode, Register rs, int32_t offset21,
   1138                                   CompactBranchType is_compact_branch) {
   1139   DCHECK(rs.is_valid() && (is_int21(offset21)));
   1140   Instr instr = opcode | (rs.code() << kRsShift) | (offset21 & kImm21Mask);
   1141   emit(instr, is_compact_branch);
   1142 }
   1143 
   1144 
   1145 void Assembler::GenInstrImmediate(Opcode opcode, Register rs,
   1146                                   uint32_t offset21) {
   1147   DCHECK(rs.is_valid() && (is_uint21(offset21)));
   1148   Instr instr = opcode | (rs.code() << kRsShift) | (offset21 & kImm21Mask);
   1149   emit(instr);
   1150 }
   1151 
   1152 
   1153 void Assembler::GenInstrImmediate(Opcode opcode, int32_t offset26,
   1154                                   CompactBranchType is_compact_branch) {
   1155   DCHECK(is_int26(offset26));
   1156   Instr instr = opcode | (offset26 & kImm26Mask);
   1157   emit(instr, is_compact_branch);
   1158 }
   1159 
   1160 
   1161 void Assembler::GenInstrJump(Opcode opcode,
   1162                              uint32_t address) {
   1163   BlockTrampolinePoolScope block_trampoline_pool(this);
   1164   DCHECK(is_uint26(address));
   1165   Instr instr = opcode | address;
   1166   emit(instr);
   1167   BlockTrampolinePoolFor(1);  // For associated delay slot.
   1168 }
   1169 
   1170 
   1171 // Returns the next free trampoline entry.
   1172 int32_t Assembler::get_trampoline_entry(int32_t pos) {
   1173   int32_t trampoline_entry = kInvalidSlotPos;
   1174 
   1175   if (!internal_trampoline_exception_) {
   1176     if (trampoline_.start() > pos) {
   1177      trampoline_entry = trampoline_.take_slot();
   1178     }
   1179 
   1180     if (kInvalidSlotPos == trampoline_entry) {
   1181       internal_trampoline_exception_ = true;
   1182     }
   1183   }
   1184   return trampoline_entry;
   1185 }
   1186 
   1187 
   1188 uint32_t Assembler::jump_address(Label* L) {
   1189   int32_t target_pos;
   1190 
   1191   if (L->is_bound()) {
   1192     target_pos = L->pos();
   1193   } else {
   1194     if (L->is_linked()) {
   1195       target_pos = L->pos();  // L's link.
   1196       L->link_to(pc_offset());
   1197     } else {
   1198       L->link_to(pc_offset());
   1199       return kEndOfJumpChain;
   1200     }
   1201   }
   1202 
   1203   uint32_t imm = reinterpret_cast<uint32_t>(buffer_) + target_pos;
   1204   DCHECK((imm & 3) == 0);
   1205 
   1206   return imm;
   1207 }
   1208 
   1209 
   1210 int32_t Assembler::branch_offset_helper(Label* L, OffsetSize bits) {
   1211   int32_t target_pos;
   1212   int32_t pad = IsPrevInstrCompactBranch() ? kInstrSize : 0;
   1213 
   1214   if (L->is_bound()) {
   1215     target_pos = L->pos();
   1216   } else {
   1217     if (L->is_linked()) {
   1218       target_pos = L->pos();
   1219       L->link_to(pc_offset() + pad);
   1220     } else {
   1221       L->link_to(pc_offset() + pad);
   1222       if (!trampoline_emitted_) {
   1223         unbound_labels_count_++;
   1224         next_buffer_check_ -= kTrampolineSlotsSize;
   1225       }
   1226       return kEndOfChain;
   1227     }
   1228   }
   1229 
   1230   int32_t offset = target_pos - (pc_offset() + kBranchPCOffset + pad);
   1231   DCHECK(is_intn(offset, bits + 2));
   1232   DCHECK((offset & 3) == 0);
   1233 
   1234   return offset;
   1235 }
   1236 
   1237 
   1238 void Assembler::label_at_put(Label* L, int at_offset) {
   1239   int target_pos;
   1240   if (L->is_bound()) {
   1241     target_pos = L->pos();
   1242     instr_at_put(at_offset, target_pos + (Code::kHeaderSize - kHeapObjectTag));
   1243   } else {
   1244     if (L->is_linked()) {
   1245       target_pos = L->pos();  // L's link.
   1246       int32_t imm18 = target_pos - at_offset;
   1247       DCHECK((imm18 & 3) == 0);
   1248       int32_t imm16 = imm18 >> 2;
   1249       DCHECK(is_int16(imm16));
   1250       instr_at_put(at_offset, (imm16 & kImm16Mask));
   1251     } else {
   1252       target_pos = kEndOfChain;
   1253       instr_at_put(at_offset, 0);
   1254       if (!trampoline_emitted_) {
   1255         unbound_labels_count_++;
   1256         next_buffer_check_ -= kTrampolineSlotsSize;
   1257       }
   1258     }
   1259     L->link_to(at_offset);
   1260   }
   1261 }
   1262 
   1263 
   1264 //------- Branch and jump instructions --------
   1265 
   1266 void Assembler::b(int16_t offset) {
   1267   beq(zero_reg, zero_reg, offset);
   1268 }
   1269 
   1270 
   1271 void Assembler::bal(int16_t offset) {
   1272   bgezal(zero_reg, offset);
   1273 }
   1274 
   1275 
   1276 void Assembler::bc(int32_t offset) {
   1277   DCHECK(IsMipsArchVariant(kMips32r6));
   1278   GenInstrImmediate(BC, offset, CompactBranchType::COMPACT_BRANCH);
   1279 }
   1280 
   1281 
   1282 void Assembler::balc(int32_t offset) {
   1283   DCHECK(IsMipsArchVariant(kMips32r6));
   1284   GenInstrImmediate(BALC, offset, CompactBranchType::COMPACT_BRANCH);
   1285 }
   1286 
   1287 
   1288 void Assembler::beq(Register rs, Register rt, int16_t offset) {
   1289   BlockTrampolinePoolScope block_trampoline_pool(this);
   1290   GenInstrImmediate(BEQ, rs, rt, offset);
   1291   BlockTrampolinePoolFor(1);  // For associated delay slot.
   1292 }
   1293 
   1294 
   1295 void Assembler::bgez(Register rs, int16_t offset) {
   1296   BlockTrampolinePoolScope block_trampoline_pool(this);
   1297   GenInstrImmediate(REGIMM, rs, BGEZ, offset);
   1298   BlockTrampolinePoolFor(1);  // For associated delay slot.
   1299 }
   1300 
   1301 
   1302 void Assembler::bgezc(Register rt, int16_t offset) {
   1303   DCHECK(IsMipsArchVariant(kMips32r6));
   1304   DCHECK(!(rt.is(zero_reg)));
   1305   GenInstrImmediate(BLEZL, rt, rt, offset, CompactBranchType::COMPACT_BRANCH);
   1306 }
   1307 
   1308 
   1309 void Assembler::bgeuc(Register rs, Register rt, int16_t offset) {
   1310   DCHECK(IsMipsArchVariant(kMips32r6));
   1311   DCHECK(!(rs.is(zero_reg)));
   1312   DCHECK(!(rt.is(zero_reg)));
   1313   DCHECK(rs.code() != rt.code());
   1314   GenInstrImmediate(BLEZ, rs, rt, offset, CompactBranchType::COMPACT_BRANCH);
   1315 }
   1316 
   1317 
   1318 void Assembler::bgec(Register rs, Register rt, int16_t offset) {
   1319   DCHECK(IsMipsArchVariant(kMips32r6));
   1320   DCHECK(!(rs.is(zero_reg)));
   1321   DCHECK(!(rt.is(zero_reg)));
   1322   DCHECK(rs.code() != rt.code());
   1323   GenInstrImmediate(BLEZL, rs, rt, offset, CompactBranchType::COMPACT_BRANCH);
   1324 }
   1325 
   1326 
   1327 void Assembler::bgezal(Register rs, int16_t offset) {
   1328   DCHECK(!IsMipsArchVariant(kMips32r6) || rs.is(zero_reg));
   1329   BlockTrampolinePoolScope block_trampoline_pool(this);
   1330   GenInstrImmediate(REGIMM, rs, BGEZAL, offset);
   1331   BlockTrampolinePoolFor(1);  // For associated delay slot.
   1332 }
   1333 
   1334 
   1335 void Assembler::bgtz(Register rs, int16_t offset) {
   1336   BlockTrampolinePoolScope block_trampoline_pool(this);
   1337   GenInstrImmediate(BGTZ, rs, zero_reg, offset);
   1338   BlockTrampolinePoolFor(1);  // For associated delay slot.
   1339 }
   1340 
   1341 
   1342 void Assembler::bgtzc(Register rt, int16_t offset) {
   1343   DCHECK(IsMipsArchVariant(kMips32r6));
   1344   DCHECK(!(rt.is(zero_reg)));
   1345   GenInstrImmediate(BGTZL, zero_reg, rt, offset,
   1346                     CompactBranchType::COMPACT_BRANCH);
   1347 }
   1348 
   1349 
   1350 void Assembler::blez(Register rs, int16_t offset) {
   1351   BlockTrampolinePoolScope block_trampoline_pool(this);
   1352   GenInstrImmediate(BLEZ, rs, zero_reg, offset);
   1353   BlockTrampolinePoolFor(1);  // For associated delay slot.
   1354 }
   1355 
   1356 
   1357 void Assembler::blezc(Register rt, int16_t offset) {
   1358   DCHECK(IsMipsArchVariant(kMips32r6));
   1359   DCHECK(!(rt.is(zero_reg)));
   1360   GenInstrImmediate(BLEZL, zero_reg, rt, offset,
   1361                     CompactBranchType::COMPACT_BRANCH);
   1362 }
   1363 
   1364 
   1365 void Assembler::bltzc(Register rt, int16_t offset) {
   1366   DCHECK(IsMipsArchVariant(kMips32r6));
   1367   DCHECK(!rt.is(zero_reg));
   1368   GenInstrImmediate(BGTZL, rt, rt, offset, CompactBranchType::COMPACT_BRANCH);
   1369 }
   1370 
   1371 
   1372 void Assembler::bltuc(Register rs, Register rt, int16_t offset) {
   1373   DCHECK(IsMipsArchVariant(kMips32r6));
   1374   DCHECK(!(rs.is(zero_reg)));
   1375   DCHECK(!(rt.is(zero_reg)));
   1376   DCHECK(rs.code() != rt.code());
   1377   GenInstrImmediate(BGTZ, rs, rt, offset, CompactBranchType::COMPACT_BRANCH);
   1378 }
   1379 
   1380 
   1381 void Assembler::bltc(Register rs, Register rt, int16_t offset) {
   1382   DCHECK(IsMipsArchVariant(kMips32r6));
   1383   DCHECK(!rs.is(zero_reg));
   1384   DCHECK(!rt.is(zero_reg));
   1385   DCHECK(rs.code() != rt.code());
   1386   GenInstrImmediate(BGTZL, rs, rt, offset, CompactBranchType::COMPACT_BRANCH);
   1387 }
   1388 
   1389 
   1390 void Assembler::bltz(Register rs, int16_t offset) {
   1391   BlockTrampolinePoolScope block_trampoline_pool(this);
   1392   GenInstrImmediate(REGIMM, rs, BLTZ, offset);
   1393   BlockTrampolinePoolFor(1);  // For associated delay slot.
   1394 }
   1395 
   1396 
   1397 void Assembler::bltzal(Register rs, int16_t offset) {
   1398   DCHECK(!IsMipsArchVariant(kMips32r6) || rs.is(zero_reg));
   1399   BlockTrampolinePoolScope block_trampoline_pool(this);
   1400   GenInstrImmediate(REGIMM, rs, BLTZAL, offset);
   1401   BlockTrampolinePoolFor(1);  // For associated delay slot.
   1402 }
   1403 
   1404 
   1405 void Assembler::bne(Register rs, Register rt, int16_t offset) {
   1406   BlockTrampolinePoolScope block_trampoline_pool(this);
   1407   GenInstrImmediate(BNE, rs, rt, offset);
   1408   BlockTrampolinePoolFor(1);  // For associated delay slot.
   1409 }
   1410 
   1411 
   1412 void Assembler::bovc(Register rs, Register rt, int16_t offset) {
   1413   DCHECK(IsMipsArchVariant(kMips32r6));
   1414   if (rs.code() >= rt.code()) {
   1415     GenInstrImmediate(ADDI, rs, rt, offset, CompactBranchType::COMPACT_BRANCH);
   1416   } else {
   1417     GenInstrImmediate(ADDI, rt, rs, offset, CompactBranchType::COMPACT_BRANCH);
   1418   }
   1419 }
   1420 
   1421 
   1422 void Assembler::bnvc(Register rs, Register rt, int16_t offset) {
   1423   DCHECK(IsMipsArchVariant(kMips32r6));
   1424   if (rs.code() >= rt.code()) {
   1425     GenInstrImmediate(DADDI, rs, rt, offset, CompactBranchType::COMPACT_BRANCH);
   1426   } else {
   1427     GenInstrImmediate(DADDI, rt, rs, offset, CompactBranchType::COMPACT_BRANCH);
   1428   }
   1429 }
   1430 
   1431 
   1432 void Assembler::blezalc(Register rt, int16_t offset) {
   1433   DCHECK(IsMipsArchVariant(kMips32r6));
   1434   DCHECK(!(rt.is(zero_reg)));
   1435   GenInstrImmediate(BLEZ, zero_reg, rt, offset,
   1436                     CompactBranchType::COMPACT_BRANCH);
   1437 }
   1438 
   1439 
   1440 void Assembler::bgezalc(Register rt, int16_t offset) {
   1441   DCHECK(IsMipsArchVariant(kMips32r6));
   1442   DCHECK(!(rt.is(zero_reg)));
   1443   GenInstrImmediate(BLEZ, rt, rt, offset, CompactBranchType::COMPACT_BRANCH);
   1444 }
   1445 
   1446 
   1447 void Assembler::bgezall(Register rs, int16_t offset) {
   1448   DCHECK(!IsMipsArchVariant(kMips32r6));
   1449   DCHECK(!(rs.is(zero_reg)));
   1450   BlockTrampolinePoolScope block_trampoline_pool(this);
   1451   GenInstrImmediate(REGIMM, rs, BGEZALL, offset);
   1452   BlockTrampolinePoolFor(1);  // For associated delay slot.
   1453 }
   1454 
   1455 
   1456 void Assembler::bltzalc(Register rt, int16_t offset) {
   1457   DCHECK(IsMipsArchVariant(kMips32r6));
   1458   DCHECK(!(rt.is(zero_reg)));
   1459   GenInstrImmediate(BGTZ, rt, rt, offset, CompactBranchType::COMPACT_BRANCH);
   1460 }
   1461 
   1462 
   1463 void Assembler::bgtzalc(Register rt, int16_t offset) {
   1464   DCHECK(IsMipsArchVariant(kMips32r6));
   1465   DCHECK(!(rt.is(zero_reg)));
   1466   GenInstrImmediate(BGTZ, zero_reg, rt, offset,
   1467                     CompactBranchType::COMPACT_BRANCH);
   1468 }
   1469 
   1470 
   1471 void Assembler::beqzalc(Register rt, int16_t offset) {
   1472   DCHECK(IsMipsArchVariant(kMips32r6));
   1473   DCHECK(!(rt.is(zero_reg)));
   1474   GenInstrImmediate(ADDI, zero_reg, rt, offset,
   1475                     CompactBranchType::COMPACT_BRANCH);
   1476 }
   1477 
   1478 
   1479 void Assembler::bnezalc(Register rt, int16_t offset) {
   1480   DCHECK(IsMipsArchVariant(kMips32r6));
   1481   DCHECK(!(rt.is(zero_reg)));
   1482   GenInstrImmediate(DADDI, zero_reg, rt, offset,
   1483                     CompactBranchType::COMPACT_BRANCH);
   1484 }
   1485 
   1486 
   1487 void Assembler::beqc(Register rs, Register rt, int16_t offset) {
   1488   DCHECK(IsMipsArchVariant(kMips32r6));
   1489   DCHECK(rs.code() != rt.code() && rs.code() != 0 && rt.code() != 0);
   1490   if (rs.code() < rt.code()) {
   1491     GenInstrImmediate(ADDI, rs, rt, offset, CompactBranchType::COMPACT_BRANCH);
   1492   } else {
   1493     GenInstrImmediate(ADDI, rt, rs, offset, CompactBranchType::COMPACT_BRANCH);
   1494   }
   1495 }
   1496 
   1497 
   1498 void Assembler::beqzc(Register rs, int32_t offset) {
   1499   DCHECK(IsMipsArchVariant(kMips32r6));
   1500   DCHECK(!(rs.is(zero_reg)));
   1501   GenInstrImmediate(POP66, rs, offset, CompactBranchType::COMPACT_BRANCH);
   1502 }
   1503 
   1504 
   1505 void Assembler::bnec(Register rs, Register rt, int16_t offset) {
   1506   DCHECK(IsMipsArchVariant(kMips32r6));
   1507   DCHECK(rs.code() != rt.code() && rs.code() != 0 && rt.code() != 0);
   1508   if (rs.code() < rt.code()) {
   1509     GenInstrImmediate(DADDI, rs, rt, offset, CompactBranchType::COMPACT_BRANCH);
   1510   } else {
   1511     GenInstrImmediate(DADDI, rt, rs, offset, CompactBranchType::COMPACT_BRANCH);
   1512   }
   1513 }
   1514 
   1515 
   1516 void Assembler::bnezc(Register rs, int32_t offset) {
   1517   DCHECK(IsMipsArchVariant(kMips32r6));
   1518   DCHECK(!(rs.is(zero_reg)));
   1519   GenInstrImmediate(POP76, rs, offset, CompactBranchType::COMPACT_BRANCH);
   1520 }
   1521 
   1522 
   1523 void Assembler::j(int32_t target) {
   1524 #if DEBUG
   1525   // Get pc of delay slot.
   1526   uint32_t ipc = reinterpret_cast<uint32_t>(pc_ + 1 * kInstrSize);
   1527   bool in_range = ((ipc ^ static_cast<uint32_t>(target)) >>
   1528                    (kImm26Bits + kImmFieldShift)) == 0;
   1529   DCHECK(in_range && ((target & 3) == 0));
   1530 #endif
   1531   BlockTrampolinePoolScope block_trampoline_pool(this);
   1532   GenInstrJump(J, (target >> 2) & kImm26Mask);
   1533   BlockTrampolinePoolFor(1);  // For associated delay slot.
   1534 }
   1535 
   1536 
   1537 void Assembler::jr(Register rs) {
   1538   if (!IsMipsArchVariant(kMips32r6)) {
   1539     BlockTrampolinePoolScope block_trampoline_pool(this);
   1540     GenInstrRegister(SPECIAL, rs, zero_reg, zero_reg, 0, JR);
   1541     BlockTrampolinePoolFor(1);  // For associated delay slot.
   1542   } else {
   1543     jalr(rs, zero_reg);
   1544   }
   1545 }
   1546 
   1547 
   1548 void Assembler::jal(int32_t target) {
   1549 #ifdef DEBUG
   1550   // Get pc of delay slot.
   1551   uint32_t ipc = reinterpret_cast<uint32_t>(pc_ + 1 * kInstrSize);
   1552   bool in_range = ((ipc ^ static_cast<uint32_t>(target)) >>
   1553                    (kImm26Bits + kImmFieldShift)) == 0;
   1554   DCHECK(in_range && ((target & 3) == 0));
   1555 #endif
   1556   BlockTrampolinePoolScope block_trampoline_pool(this);
   1557   GenInstrJump(JAL, (target >> 2) & kImm26Mask);
   1558   BlockTrampolinePoolFor(1);  // For associated delay slot.
   1559 }
   1560 
   1561 
   1562 void Assembler::jalr(Register rs, Register rd) {
   1563   DCHECK(rs.code() != rd.code());
   1564   BlockTrampolinePoolScope block_trampoline_pool(this);
   1565   GenInstrRegister(SPECIAL, rs, zero_reg, rd, 0, JALR);
   1566   BlockTrampolinePoolFor(1);  // For associated delay slot.
   1567 }
   1568 
   1569 
   1570 void Assembler::jic(Register rt, int16_t offset) {
   1571   DCHECK(IsMipsArchVariant(kMips32r6));
   1572   GenInstrImmediate(POP66, zero_reg, rt, offset);
   1573 }
   1574 
   1575 
   1576 void Assembler::jialc(Register rt, int16_t offset) {
   1577   DCHECK(IsMipsArchVariant(kMips32r6));
   1578   GenInstrImmediate(POP76, zero_reg, rt, offset);
   1579 }
   1580 
   1581 
   1582 // -------Data-processing-instructions---------
   1583 
   1584 // Arithmetic.
   1585 
   1586 void Assembler::addu(Register rd, Register rs, Register rt) {
   1587   GenInstrRegister(SPECIAL, rs, rt, rd, 0, ADDU);
   1588 }
   1589 
   1590 
   1591 void Assembler::addiu(Register rd, Register rs, int32_t j) {
   1592   GenInstrImmediate(ADDIU, rs, rd, j);
   1593 }
   1594 
   1595 
   1596 void Assembler::subu(Register rd, Register rs, Register rt) {
   1597   GenInstrRegister(SPECIAL, rs, rt, rd, 0, SUBU);
   1598 }
   1599 
   1600 
   1601 void Assembler::mul(Register rd, Register rs, Register rt) {
   1602   if (!IsMipsArchVariant(kMips32r6)) {
   1603     GenInstrRegister(SPECIAL2, rs, rt, rd, 0, MUL);
   1604   } else {
   1605     GenInstrRegister(SPECIAL, rs, rt, rd, MUL_OP, MUL_MUH);
   1606   }
   1607 }
   1608 
   1609 
   1610 void Assembler::mulu(Register rd, Register rs, Register rt) {
   1611   DCHECK(IsMipsArchVariant(kMips32r6));
   1612   GenInstrRegister(SPECIAL, rs, rt, rd, MUL_OP, MUL_MUH_U);
   1613 }
   1614 
   1615 
   1616 void Assembler::muh(Register rd, Register rs, Register rt) {
   1617   DCHECK(IsMipsArchVariant(kMips32r6));
   1618   GenInstrRegister(SPECIAL, rs, rt, rd, MUH_OP, MUL_MUH);
   1619 }
   1620 
   1621 
   1622 void Assembler::muhu(Register rd, Register rs, Register rt) {
   1623   DCHECK(IsMipsArchVariant(kMips32r6));
   1624   GenInstrRegister(SPECIAL, rs, rt, rd, MUH_OP, MUL_MUH_U);
   1625 }
   1626 
   1627 
   1628 void Assembler::mod(Register rd, Register rs, Register rt) {
   1629   DCHECK(IsMipsArchVariant(kMips32r6));
   1630   GenInstrRegister(SPECIAL, rs, rt, rd, MOD_OP, DIV_MOD);
   1631 }
   1632 
   1633 
   1634 void Assembler::modu(Register rd, Register rs, Register rt) {
   1635   DCHECK(IsMipsArchVariant(kMips32r6));
   1636   GenInstrRegister(SPECIAL, rs, rt, rd, MOD_OP, DIV_MOD_U);
   1637 }
   1638 
   1639 
   1640 void Assembler::mult(Register rs, Register rt) {
   1641   GenInstrRegister(SPECIAL, rs, rt, zero_reg, 0, MULT);
   1642 }
   1643 
   1644 
   1645 void Assembler::multu(Register rs, Register rt) {
   1646   GenInstrRegister(SPECIAL, rs, rt, zero_reg, 0, MULTU);
   1647 }
   1648 
   1649 
   1650 void Assembler::div(Register rs, Register rt) {
   1651   GenInstrRegister(SPECIAL, rs, rt, zero_reg, 0, DIV);
   1652 }
   1653 
   1654 
   1655 void Assembler::div(Register rd, Register rs, Register rt) {
   1656   DCHECK(IsMipsArchVariant(kMips32r6));
   1657   GenInstrRegister(SPECIAL, rs, rt, rd, DIV_OP, DIV_MOD);
   1658 }
   1659 
   1660 
   1661 void Assembler::divu(Register rs, Register rt) {
   1662   GenInstrRegister(SPECIAL, rs, rt, zero_reg, 0, DIVU);
   1663 }
   1664 
   1665 
   1666 void Assembler::divu(Register rd, Register rs, Register rt) {
   1667   DCHECK(IsMipsArchVariant(kMips32r6));
   1668   GenInstrRegister(SPECIAL, rs, rt, rd, DIV_OP, DIV_MOD_U);
   1669 }
   1670 
   1671 
   1672 // Logical.
   1673 
   1674 void Assembler::and_(Register rd, Register rs, Register rt) {
   1675   GenInstrRegister(SPECIAL, rs, rt, rd, 0, AND);
   1676 }
   1677 
   1678 
   1679 void Assembler::andi(Register rt, Register rs, int32_t j) {
   1680   DCHECK(is_uint16(j));
   1681   GenInstrImmediate(ANDI, rs, rt, j);
   1682 }
   1683 
   1684 
   1685 void Assembler::or_(Register rd, Register rs, Register rt) {
   1686   GenInstrRegister(SPECIAL, rs, rt, rd, 0, OR);
   1687 }
   1688 
   1689 
   1690 void Assembler::ori(Register rt, Register rs, int32_t j) {
   1691   DCHECK(is_uint16(j));
   1692   GenInstrImmediate(ORI, rs, rt, j);
   1693 }
   1694 
   1695 
   1696 void Assembler::xor_(Register rd, Register rs, Register rt) {
   1697   GenInstrRegister(SPECIAL, rs, rt, rd, 0, XOR);
   1698 }
   1699 
   1700 
   1701 void Assembler::xori(Register rt, Register rs, int32_t j) {
   1702   DCHECK(is_uint16(j));
   1703   GenInstrImmediate(XORI, rs, rt, j);
   1704 }
   1705 
   1706 
   1707 void Assembler::nor(Register rd, Register rs, Register rt) {
   1708   GenInstrRegister(SPECIAL, rs, rt, rd, 0, NOR);
   1709 }
   1710 
   1711 
   1712 // Shifts.
   1713 void Assembler::sll(Register rd,
   1714                     Register rt,
   1715                     uint16_t sa,
   1716                     bool coming_from_nop) {
   1717   // Don't allow nop instructions in the form sll zero_reg, zero_reg to be
   1718   // generated using the sll instruction. They must be generated using
   1719   // nop(int/NopMarkerTypes) or MarkCode(int/NopMarkerTypes) pseudo
   1720   // instructions.
   1721   DCHECK(coming_from_nop || !(rd.is(zero_reg) && rt.is(zero_reg)));
   1722   GenInstrRegister(SPECIAL, zero_reg, rt, rd, sa & 0x1F, SLL);
   1723 }
   1724 
   1725 
   1726 void Assembler::sllv(Register rd, Register rt, Register rs) {
   1727   GenInstrRegister(SPECIAL, rs, rt, rd, 0, SLLV);
   1728 }
   1729 
   1730 
   1731 void Assembler::srl(Register rd, Register rt, uint16_t sa) {
   1732   GenInstrRegister(SPECIAL, zero_reg, rt, rd, sa & 0x1F, SRL);
   1733 }
   1734 
   1735 
   1736 void Assembler::srlv(Register rd, Register rt, Register rs) {
   1737   GenInstrRegister(SPECIAL, rs, rt, rd, 0, SRLV);
   1738 }
   1739 
   1740 
   1741 void Assembler::sra(Register rd, Register rt, uint16_t sa) {
   1742   GenInstrRegister(SPECIAL, zero_reg, rt, rd, sa & 0x1F, SRA);
   1743 }
   1744 
   1745 
   1746 void Assembler::srav(Register rd, Register rt, Register rs) {
   1747   GenInstrRegister(SPECIAL, rs, rt, rd, 0, SRAV);
   1748 }
   1749 
   1750 
   1751 void Assembler::rotr(Register rd, Register rt, uint16_t sa) {
   1752   // Should be called via MacroAssembler::Ror.
   1753   DCHECK(rd.is_valid() && rt.is_valid() && is_uint5(sa));
   1754   DCHECK(IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6));
   1755   Instr instr = SPECIAL | (1 << kRsShift) | (rt.code() << kRtShift)
   1756       | (rd.code() << kRdShift) | (sa << kSaShift) | SRL;
   1757   emit(instr);
   1758 }
   1759 
   1760 
   1761 void Assembler::rotrv(Register rd, Register rt, Register rs) {
   1762   // Should be called via MacroAssembler::Ror.
   1763   DCHECK(rd.is_valid() && rt.is_valid() && rs.is_valid());
   1764   DCHECK(IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6));
   1765   Instr instr = SPECIAL | (rs.code() << kRsShift) | (rt.code() << kRtShift)
   1766      | (rd.code() << kRdShift) | (1 << kSaShift) | SRLV;
   1767   emit(instr);
   1768 }
   1769 
   1770 
   1771 void Assembler::lsa(Register rd, Register rt, Register rs, uint8_t sa) {
   1772   DCHECK(rd.is_valid() && rt.is_valid() && rs.is_valid());
   1773   DCHECK(sa <= 3);
   1774   DCHECK(IsMipsArchVariant(kMips32r6));
   1775   Instr instr = SPECIAL | rs.code() << kRsShift | rt.code() << kRtShift |
   1776                 rd.code() << kRdShift | sa << kSaShift | LSA;
   1777   emit(instr);
   1778 }
   1779 
   1780 
   1781 // ------------Memory-instructions-------------
   1782 
   1783 // Helper for base-reg + offset, when offset is larger than int16.
   1784 void Assembler::LoadRegPlusOffsetToAt(const MemOperand& src) {
   1785   DCHECK(!src.rm().is(at));
   1786   if (IsMipsArchVariant(kMips32r6)) {
   1787     int32_t hi = (src.offset_ >> kLuiShift) & kImm16Mask;
   1788     if (src.offset_ & kNegOffset) {
   1789       hi += 1;
   1790     }
   1791     aui(at, src.rm(), hi);
   1792     addiu(at, at, src.offset_ & kImm16Mask);
   1793   } else {
   1794     lui(at, (src.offset_ >> kLuiShift) & kImm16Mask);
   1795     ori(at, at, src.offset_ & kImm16Mask);  // Load 32-bit offset.
   1796     addu(at, at, src.rm());                 // Add base register.
   1797   }
   1798 }
   1799 
   1800 // Helper for base-reg + upper part of offset, when offset is larger than int16.
   1801 // Loads higher part of the offset to AT register.
   1802 // Returns lower part of the offset to be used as offset
   1803 // in Load/Store instructions
   1804 int32_t Assembler::LoadRegPlusUpperOffsetPartToAt(const MemOperand& src) {
   1805   DCHECK(!src.rm().is(at));
   1806   int32_t hi = (src.offset_ >> kLuiShift) & kImm16Mask;
   1807   // If the highest bit of the lower part of the offset is 1, this would make
   1808   // the offset in the load/store instruction negative. We need to compensate
   1809   // for this by adding 1 to the upper part of the offset.
   1810   if (src.offset_ & kNegOffset) {
   1811     hi += 1;
   1812   }
   1813 
   1814   if (IsMipsArchVariant(kMips32r6)) {
   1815     aui(at, src.rm(), hi);
   1816   } else {
   1817     lui(at, hi);
   1818     addu(at, at, src.rm());
   1819   }
   1820   return (src.offset_ & kImm16Mask);
   1821 }
   1822 
   1823 // Helper for loading base-reg + upper offset's part to AT reg when we are using
   1824 // two 32-bit loads/stores instead of one 64-bit
   1825 int32_t Assembler::LoadUpperOffsetForTwoMemoryAccesses(const MemOperand& src) {
   1826   DCHECK(!src.rm().is(at));
   1827   if (is_int16((src.offset_ & kImm16Mask) + kIntSize)) {
   1828     // Only if lower part of offset + kIntSize fits in 16bits
   1829     return LoadRegPlusUpperOffsetPartToAt(src);
   1830   }
   1831   // In case offset's lower part + kIntSize doesn't fit in 16bits,
   1832   // load reg + hole offset to AT
   1833   LoadRegPlusOffsetToAt(src);
   1834   return 0;
   1835 }
   1836 
   1837 void Assembler::lb(Register rd, const MemOperand& rs) {
   1838   if (is_int16(rs.offset_)) {
   1839     GenInstrImmediate(LB, rs.rm(), rd, rs.offset_);
   1840   } else {  // Offset > 16 bits, use multiple instructions to load.
   1841     int32_t off16 = LoadRegPlusUpperOffsetPartToAt(rs);
   1842     GenInstrImmediate(LB, at, rd, off16);
   1843   }
   1844 }
   1845 
   1846 
   1847 void Assembler::lbu(Register rd, const MemOperand& rs) {
   1848   if (is_int16(rs.offset_)) {
   1849     GenInstrImmediate(LBU, rs.rm(), rd, rs.offset_);
   1850   } else {  // Offset > 16 bits, use multiple instructions to load.
   1851     int32_t off16 = LoadRegPlusUpperOffsetPartToAt(rs);
   1852     GenInstrImmediate(LBU, at, rd, off16);
   1853   }
   1854 }
   1855 
   1856 
   1857 void Assembler::lh(Register rd, const MemOperand& rs) {
   1858   if (is_int16(rs.offset_)) {
   1859     GenInstrImmediate(LH, rs.rm(), rd, rs.offset_);
   1860   } else {  // Offset > 16 bits, use multiple instructions to load.
   1861     int32_t off16 = LoadRegPlusUpperOffsetPartToAt(rs);
   1862     GenInstrImmediate(LH, at, rd, off16);
   1863   }
   1864 }
   1865 
   1866 
   1867 void Assembler::lhu(Register rd, const MemOperand& rs) {
   1868   if (is_int16(rs.offset_)) {
   1869     GenInstrImmediate(LHU, rs.rm(), rd, rs.offset_);
   1870   } else {  // Offset > 16 bits, use multiple instructions to load.
   1871     int32_t off16 = LoadRegPlusUpperOffsetPartToAt(rs);
   1872     GenInstrImmediate(LHU, at, rd, off16);
   1873   }
   1874 }
   1875 
   1876 
   1877 void Assembler::lw(Register rd, const MemOperand& rs) {
   1878   if (is_int16(rs.offset_)) {
   1879     GenInstrImmediate(LW, rs.rm(), rd, rs.offset_);
   1880   } else {  // Offset > 16 bits, use multiple instructions to load.
   1881     int32_t off16 = LoadRegPlusUpperOffsetPartToAt(rs);
   1882     GenInstrImmediate(LW, at, rd, off16);
   1883   }
   1884 }
   1885 
   1886 
   1887 void Assembler::lwl(Register rd, const MemOperand& rs) {
   1888   DCHECK(is_int16(rs.offset_));
   1889   DCHECK(IsMipsArchVariant(kLoongson) || IsMipsArchVariant(kMips32r1) ||
   1890          IsMipsArchVariant(kMips32r2));
   1891   GenInstrImmediate(LWL, rs.rm(), rd, rs.offset_);
   1892 }
   1893 
   1894 
   1895 void Assembler::lwr(Register rd, const MemOperand& rs) {
   1896   DCHECK(is_int16(rs.offset_));
   1897   DCHECK(IsMipsArchVariant(kLoongson) || IsMipsArchVariant(kMips32r1) ||
   1898          IsMipsArchVariant(kMips32r2));
   1899   GenInstrImmediate(LWR, rs.rm(), rd, rs.offset_);
   1900 }
   1901 
   1902 
   1903 void Assembler::sb(Register rd, const MemOperand& rs) {
   1904   if (is_int16(rs.offset_)) {
   1905     GenInstrImmediate(SB, rs.rm(), rd, rs.offset_);
   1906   } else {  // Offset > 16 bits, use multiple instructions to store.
   1907     int32_t off16 = LoadRegPlusUpperOffsetPartToAt(rs);
   1908     GenInstrImmediate(SB, at, rd, off16);
   1909   }
   1910 }
   1911 
   1912 
   1913 void Assembler::sh(Register rd, const MemOperand& rs) {
   1914   if (is_int16(rs.offset_)) {
   1915     GenInstrImmediate(SH, rs.rm(), rd, rs.offset_);
   1916   } else {  // Offset > 16 bits, use multiple instructions to store.
   1917     int32_t off16 = LoadRegPlusUpperOffsetPartToAt(rs);
   1918     GenInstrImmediate(SH, at, rd, off16);
   1919   }
   1920 }
   1921 
   1922 
   1923 void Assembler::sw(Register rd, const MemOperand& rs) {
   1924   if (is_int16(rs.offset_)) {
   1925     GenInstrImmediate(SW, rs.rm(), rd, rs.offset_);
   1926   } else {  // Offset > 16 bits, use multiple instructions to store.
   1927     int32_t off16 = LoadRegPlusUpperOffsetPartToAt(rs);
   1928     GenInstrImmediate(SW, at, rd, off16);
   1929   }
   1930 }
   1931 
   1932 
   1933 void Assembler::swl(Register rd, const MemOperand& rs) {
   1934   DCHECK(is_int16(rs.offset_));
   1935   DCHECK(IsMipsArchVariant(kLoongson) || IsMipsArchVariant(kMips32r1) ||
   1936          IsMipsArchVariant(kMips32r2));
   1937   GenInstrImmediate(SWL, rs.rm(), rd, rs.offset_);
   1938 }
   1939 
   1940 
   1941 void Assembler::swr(Register rd, const MemOperand& rs) {
   1942   DCHECK(is_int16(rs.offset_));
   1943   DCHECK(IsMipsArchVariant(kLoongson) || IsMipsArchVariant(kMips32r1) ||
   1944          IsMipsArchVariant(kMips32r2));
   1945   GenInstrImmediate(SWR, rs.rm(), rd, rs.offset_);
   1946 }
   1947 
   1948 
   1949 void Assembler::lui(Register rd, int32_t j) {
   1950   DCHECK(is_uint16(j));
   1951   GenInstrImmediate(LUI, zero_reg, rd, j);
   1952 }
   1953 
   1954 
   1955 void Assembler::aui(Register rt, Register rs, int32_t j) {
   1956   // This instruction uses same opcode as 'lui'. The difference in encoding is
   1957   // 'lui' has zero reg. for rs field.
   1958   DCHECK(!(rs.is(zero_reg)));
   1959   DCHECK(is_uint16(j));
   1960   GenInstrImmediate(LUI, rs, rt, j);
   1961 }
   1962 
   1963 // ---------PC-Relative instructions-----------
   1964 
   1965 void Assembler::addiupc(Register rs, int32_t imm19) {
   1966   DCHECK(IsMipsArchVariant(kMips32r6));
   1967   DCHECK(rs.is_valid() && is_int19(imm19));
   1968   uint32_t imm21 = ADDIUPC << kImm19Bits | (imm19 & kImm19Mask);
   1969   GenInstrImmediate(PCREL, rs, imm21);
   1970 }
   1971 
   1972 
   1973 void Assembler::lwpc(Register rs, int32_t offset19) {
   1974   DCHECK(IsMipsArchVariant(kMips32r6));
   1975   DCHECK(rs.is_valid() && is_int19(offset19));
   1976   uint32_t imm21 = LWPC << kImm19Bits | (offset19 & kImm19Mask);
   1977   GenInstrImmediate(PCREL, rs, imm21);
   1978 }
   1979 
   1980 
   1981 void Assembler::auipc(Register rs, int16_t imm16) {
   1982   DCHECK(IsMipsArchVariant(kMips32r6));
   1983   DCHECK(rs.is_valid());
   1984   uint32_t imm21 = AUIPC << kImm16Bits | (imm16 & kImm16Mask);
   1985   GenInstrImmediate(PCREL, rs, imm21);
   1986 }
   1987 
   1988 
   1989 void Assembler::aluipc(Register rs, int16_t imm16) {
   1990   DCHECK(IsMipsArchVariant(kMips32r6));
   1991   DCHECK(rs.is_valid());
   1992   uint32_t imm21 = ALUIPC << kImm16Bits | (imm16 & kImm16Mask);
   1993   GenInstrImmediate(PCREL, rs, imm21);
   1994 }
   1995 
   1996 
   1997 // -------------Misc-instructions--------------
   1998 
   1999 // Break / Trap instructions.
   2000 void Assembler::break_(uint32_t code, bool break_as_stop) {
   2001   DCHECK((code & ~0xfffff) == 0);
   2002   // We need to invalidate breaks that could be stops as well because the
   2003   // simulator expects a char pointer after the stop instruction.
   2004   // See constants-mips.h for explanation.
   2005   DCHECK((break_as_stop &&
   2006           code <= kMaxStopCode &&
   2007           code > kMaxWatchpointCode) ||
   2008          (!break_as_stop &&
   2009           (code > kMaxStopCode ||
   2010            code <= kMaxWatchpointCode)));
   2011   Instr break_instr = SPECIAL | BREAK | (code << 6);
   2012   emit(break_instr);
   2013 }
   2014 
   2015 
   2016 void Assembler::stop(const char* msg, uint32_t code) {
   2017   DCHECK(code > kMaxWatchpointCode);
   2018   DCHECK(code <= kMaxStopCode);
   2019 #if V8_HOST_ARCH_MIPS
   2020   break_(0x54321);
   2021 #else  // V8_HOST_ARCH_MIPS
   2022   BlockTrampolinePoolFor(2);
   2023   // The Simulator will handle the stop instruction and get the message address.
   2024   // On MIPS stop() is just a special kind of break_().
   2025   break_(code, true);
   2026   // Do not embed the message string address! We used to do this, but that
   2027   // made snapshots created from position-independent executable builds
   2028   // non-deterministic.
   2029   // TODO(yangguo): remove this field entirely.
   2030   nop();
   2031 #endif
   2032 }
   2033 
   2034 
   2035 void Assembler::tge(Register rs, Register rt, uint16_t code) {
   2036   DCHECK(is_uint10(code));
   2037   Instr instr = SPECIAL | TGE | rs.code() << kRsShift
   2038       | rt.code() << kRtShift | code << 6;
   2039   emit(instr);
   2040 }
   2041 
   2042 
   2043 void Assembler::tgeu(Register rs, Register rt, uint16_t code) {
   2044   DCHECK(is_uint10(code));
   2045   Instr instr = SPECIAL | TGEU | rs.code() << kRsShift
   2046       | rt.code() << kRtShift | code << 6;
   2047   emit(instr);
   2048 }
   2049 
   2050 
   2051 void Assembler::tlt(Register rs, Register rt, uint16_t code) {
   2052   DCHECK(is_uint10(code));
   2053   Instr instr =
   2054       SPECIAL | TLT | rs.code() << kRsShift | rt.code() << kRtShift | code << 6;
   2055   emit(instr);
   2056 }
   2057 
   2058 
   2059 void Assembler::tltu(Register rs, Register rt, uint16_t code) {
   2060   DCHECK(is_uint10(code));
   2061   Instr instr =
   2062       SPECIAL | TLTU | rs.code() << kRsShift
   2063       | rt.code() << kRtShift | code << 6;
   2064   emit(instr);
   2065 }
   2066 
   2067 
   2068 void Assembler::teq(Register rs, Register rt, uint16_t code) {
   2069   DCHECK(is_uint10(code));
   2070   Instr instr =
   2071       SPECIAL | TEQ | rs.code() << kRsShift | rt.code() << kRtShift | code << 6;
   2072   emit(instr);
   2073 }
   2074 
   2075 
   2076 void Assembler::tne(Register rs, Register rt, uint16_t code) {
   2077   DCHECK(is_uint10(code));
   2078   Instr instr =
   2079       SPECIAL | TNE | rs.code() << kRsShift | rt.code() << kRtShift | code << 6;
   2080   emit(instr);
   2081 }
   2082 
   2083 void Assembler::sync() {
   2084   Instr sync_instr = SPECIAL | SYNC;
   2085   emit(sync_instr);
   2086 }
   2087 
   2088 // Move from HI/LO register.
   2089 
   2090 void Assembler::mfhi(Register rd) {
   2091   GenInstrRegister(SPECIAL, zero_reg, zero_reg, rd, 0, MFHI);
   2092 }
   2093 
   2094 
   2095 void Assembler::mflo(Register rd) {
   2096   GenInstrRegister(SPECIAL, zero_reg, zero_reg, rd, 0, MFLO);
   2097 }
   2098 
   2099 
   2100 // Set on less than instructions.
   2101 void Assembler::slt(Register rd, Register rs, Register rt) {
   2102   GenInstrRegister(SPECIAL, rs, rt, rd, 0, SLT);
   2103 }
   2104 
   2105 
   2106 void Assembler::sltu(Register rd, Register rs, Register rt) {
   2107   GenInstrRegister(SPECIAL, rs, rt, rd, 0, SLTU);
   2108 }
   2109 
   2110 
   2111 void Assembler::slti(Register rt, Register rs, int32_t j) {
   2112   GenInstrImmediate(SLTI, rs, rt, j);
   2113 }
   2114 
   2115 
   2116 void Assembler::sltiu(Register rt, Register rs, int32_t j) {
   2117   GenInstrImmediate(SLTIU, rs, rt, j);
   2118 }
   2119 
   2120 
   2121 // Conditional move.
   2122 void Assembler::movz(Register rd, Register rs, Register rt) {
   2123   GenInstrRegister(SPECIAL, rs, rt, rd, 0, MOVZ);
   2124 }
   2125 
   2126 
   2127 void Assembler::movn(Register rd, Register rs, Register rt) {
   2128   GenInstrRegister(SPECIAL, rs, rt, rd, 0, MOVN);
   2129 }
   2130 
   2131 
   2132 void Assembler::movt(Register rd, Register rs, uint16_t cc) {
   2133   Register rt;
   2134   rt.reg_code = (cc & 0x0007) << 2 | 1;
   2135   GenInstrRegister(SPECIAL, rs, rt, rd, 0, MOVCI);
   2136 }
   2137 
   2138 
   2139 void Assembler::movf(Register rd, Register rs, uint16_t cc) {
   2140   Register rt;
   2141   rt.reg_code = (cc & 0x0007) << 2 | 0;
   2142   GenInstrRegister(SPECIAL, rs, rt, rd, 0, MOVCI);
   2143 }
   2144 
   2145 
   2146 void Assembler::seleqz(Register rd, Register rs, Register rt) {
   2147   DCHECK(IsMipsArchVariant(kMips32r6));
   2148   GenInstrRegister(SPECIAL, rs, rt, rd, 0, SELEQZ_S);
   2149 }
   2150 
   2151 
   2152 // Bit twiddling.
   2153 void Assembler::clz(Register rd, Register rs) {
   2154   if (!IsMipsArchVariant(kMips32r6)) {
   2155     // Clz instr requires same GPR number in 'rd' and 'rt' fields.
   2156     GenInstrRegister(SPECIAL2, rs, rd, rd, 0, CLZ);
   2157   } else {
   2158     GenInstrRegister(SPECIAL, rs, zero_reg, rd, 1, CLZ_R6);
   2159   }
   2160 }
   2161 
   2162 
   2163 void Assembler::ins_(Register rt, Register rs, uint16_t pos, uint16_t size) {
   2164   // Should be called via MacroAssembler::Ins.
   2165   // Ins instr has 'rt' field as dest, and two uint5: msb, lsb.
   2166   DCHECK(IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6));
   2167   GenInstrRegister(SPECIAL3, rs, rt, pos + size - 1, pos, INS);
   2168 }
   2169 
   2170 
   2171 void Assembler::ext_(Register rt, Register rs, uint16_t pos, uint16_t size) {
   2172   // Should be called via MacroAssembler::Ext.
   2173   // Ext instr has 'rt' field as dest, and two uint5: msb, lsb.
   2174   DCHECK(IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6));
   2175   GenInstrRegister(SPECIAL3, rs, rt, size - 1, pos, EXT);
   2176 }
   2177 
   2178 
   2179 void Assembler::bitswap(Register rd, Register rt) {
   2180   DCHECK(IsMipsArchVariant(kMips32r6));
   2181   GenInstrRegister(SPECIAL3, zero_reg, rt, rd, 0, BSHFL);
   2182 }
   2183 
   2184 
   2185 void Assembler::pref(int32_t hint, const MemOperand& rs) {
   2186   DCHECK(!IsMipsArchVariant(kLoongson));
   2187   DCHECK(is_uint5(hint) && is_uint16(rs.offset_));
   2188   Instr instr = PREF | (rs.rm().code() << kRsShift) | (hint << kRtShift)
   2189       | (rs.offset_);
   2190   emit(instr);
   2191 }
   2192 
   2193 
   2194 void Assembler::align(Register rd, Register rs, Register rt, uint8_t bp) {
   2195   DCHECK(IsMipsArchVariant(kMips32r6));
   2196   DCHECK(is_uint3(bp));
   2197   uint16_t sa = (ALIGN << kBp2Bits) | bp;
   2198   GenInstrRegister(SPECIAL3, rs, rt, rd, sa, BSHFL);
   2199 }
   2200 
   2201 // Byte swap.
   2202 void Assembler::wsbh(Register rd, Register rt) {
   2203   DCHECK(IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6));
   2204   GenInstrRegister(SPECIAL3, zero_reg, rt, rd, WSBH, BSHFL);
   2205 }
   2206 
   2207 void Assembler::seh(Register rd, Register rt) {
   2208   DCHECK(IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6));
   2209   GenInstrRegister(SPECIAL3, zero_reg, rt, rd, SEH, BSHFL);
   2210 }
   2211 
   2212 void Assembler::seb(Register rd, Register rt) {
   2213   DCHECK(IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6));
   2214   GenInstrRegister(SPECIAL3, zero_reg, rt, rd, SEB, BSHFL);
   2215 }
   2216 
   2217 // --------Coprocessor-instructions----------------
   2218 
   2219 // Load, store, move.
   2220 void Assembler::lwc1(FPURegister fd, const MemOperand& src) {
   2221   if (is_int16(src.offset_)) {
   2222     GenInstrImmediate(LWC1, src.rm(), fd, src.offset_);
   2223   } else {  // Offset > 16 bits, use multiple instructions to load.
   2224     int32_t off16 = LoadRegPlusUpperOffsetPartToAt(src);
   2225     GenInstrImmediate(LWC1, at, fd, off16);
   2226   }
   2227 }
   2228 
   2229 
   2230 void Assembler::ldc1(FPURegister fd, const MemOperand& src) {
   2231   // Workaround for non-8-byte alignment of HeapNumber, convert 64-bit
   2232   // load to two 32-bit loads.
   2233   if (IsFp32Mode()) {  // fp32 mode.
   2234     if (is_int16(src.offset_) && is_int16(src.offset_ + kIntSize)) {
   2235       GenInstrImmediate(LWC1, src.rm(), fd,
   2236                         src.offset_ + Register::kMantissaOffset);
   2237       FPURegister nextfpreg;
   2238       nextfpreg.setcode(fd.code() + 1);
   2239       GenInstrImmediate(LWC1, src.rm(), nextfpreg,
   2240                         src.offset_ + Register::kExponentOffset);
   2241     } else {  // Offset > 16 bits, use multiple instructions to load.
   2242       int32_t off16 = LoadUpperOffsetForTwoMemoryAccesses(src);
   2243       GenInstrImmediate(LWC1, at, fd, off16 + Register::kMantissaOffset);
   2244       FPURegister nextfpreg;
   2245       nextfpreg.setcode(fd.code() + 1);
   2246       GenInstrImmediate(LWC1, at, nextfpreg, off16 + Register::kExponentOffset);
   2247     }
   2248   } else {
   2249     DCHECK(IsFp64Mode() || IsFpxxMode());
   2250     // Currently we support FPXX and FP64 on Mips32r2 and Mips32r6
   2251     DCHECK(IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6));
   2252     if (is_int16(src.offset_) && is_int16(src.offset_ + kIntSize)) {
   2253       GenInstrImmediate(LWC1, src.rm(), fd,
   2254                         src.offset_ + Register::kMantissaOffset);
   2255       GenInstrImmediate(LW, src.rm(), at,
   2256                         src.offset_ + Register::kExponentOffset);
   2257       mthc1(at, fd);
   2258     } else {  // Offset > 16 bits, use multiple instructions to load.
   2259       int32_t off16 = LoadUpperOffsetForTwoMemoryAccesses(src);
   2260       GenInstrImmediate(LWC1, at, fd, off16 + Register::kMantissaOffset);
   2261       GenInstrImmediate(LW, at, at, off16 + Register::kExponentOffset);
   2262       mthc1(at, fd);
   2263     }
   2264   }
   2265 }
   2266 
   2267 
   2268 void Assembler::swc1(FPURegister fd, const MemOperand& src) {
   2269   if (is_int16(src.offset_)) {
   2270     GenInstrImmediate(SWC1, src.rm(), fd, src.offset_);
   2271   } else {  // Offset > 16 bits, use multiple instructions to load.
   2272     int32_t off16 = LoadRegPlusUpperOffsetPartToAt(src);
   2273     GenInstrImmediate(SWC1, at, fd, off16);
   2274   }
   2275 }
   2276 
   2277 
   2278 void Assembler::sdc1(FPURegister fd, const MemOperand& src) {
   2279   // Workaround for non-8-byte alignment of HeapNumber, convert 64-bit
   2280   // store to two 32-bit stores.
   2281   DCHECK(!src.rm().is(at));
   2282   DCHECK(!src.rm().is(t8));
   2283   if (IsFp32Mode()) {  // fp32 mode.
   2284     if (is_int16(src.offset_) && is_int16(src.offset_ + kIntSize)) {
   2285       GenInstrImmediate(SWC1, src.rm(), fd,
   2286                         src.offset_ + Register::kMantissaOffset);
   2287       FPURegister nextfpreg;
   2288       nextfpreg.setcode(fd.code() + 1);
   2289       GenInstrImmediate(SWC1, src.rm(), nextfpreg,
   2290                         src.offset_ + Register::kExponentOffset);
   2291     } else {  // Offset > 16 bits, use multiple instructions to load.
   2292       int32_t off16 = LoadUpperOffsetForTwoMemoryAccesses(src);
   2293       GenInstrImmediate(SWC1, at, fd, off16 + Register::kMantissaOffset);
   2294       FPURegister nextfpreg;
   2295       nextfpreg.setcode(fd.code() + 1);
   2296       GenInstrImmediate(SWC1, at, nextfpreg, off16 + Register::kExponentOffset);
   2297     }
   2298   } else {
   2299     DCHECK(IsFp64Mode() || IsFpxxMode());
   2300     // Currently we support FPXX and FP64 on Mips32r2 and Mips32r6
   2301     DCHECK(IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6));
   2302     if (is_int16(src.offset_) && is_int16(src.offset_ + kIntSize)) {
   2303       GenInstrImmediate(SWC1, src.rm(), fd,
   2304                         src.offset_ + Register::kMantissaOffset);
   2305       mfhc1(at, fd);
   2306       GenInstrImmediate(SW, src.rm(), at,
   2307                         src.offset_ + Register::kExponentOffset);
   2308     } else {  // Offset > 16 bits, use multiple instructions to load.
   2309       int32_t off16 = LoadUpperOffsetForTwoMemoryAccesses(src);
   2310       GenInstrImmediate(SWC1, at, fd, off16 + Register::kMantissaOffset);
   2311       mfhc1(t8, fd);
   2312       GenInstrImmediate(SW, at, t8, off16 + Register::kExponentOffset);
   2313     }
   2314   }
   2315 }
   2316 
   2317 
   2318 void Assembler::mtc1(Register rt, FPURegister fs) {
   2319   GenInstrRegister(COP1, MTC1, rt, fs, f0);
   2320 }
   2321 
   2322 
   2323 void Assembler::mthc1(Register rt, FPURegister fs) {
   2324   GenInstrRegister(COP1, MTHC1, rt, fs, f0);
   2325 }
   2326 
   2327 
   2328 void Assembler::mfc1(Register rt, FPURegister fs) {
   2329   GenInstrRegister(COP1, MFC1, rt, fs, f0);
   2330 }
   2331 
   2332 
   2333 void Assembler::mfhc1(Register rt, FPURegister fs) {
   2334   GenInstrRegister(COP1, MFHC1, rt, fs, f0);
   2335 }
   2336 
   2337 
   2338 void Assembler::ctc1(Register rt, FPUControlRegister fs) {
   2339   GenInstrRegister(COP1, CTC1, rt, fs);
   2340 }
   2341 
   2342 
   2343 void Assembler::cfc1(Register rt, FPUControlRegister fs) {
   2344   GenInstrRegister(COP1, CFC1, rt, fs);
   2345 }
   2346 
   2347 
   2348 void Assembler::DoubleAsTwoUInt32(double d, uint32_t* lo, uint32_t* hi) {
   2349   uint64_t i;
   2350   memcpy(&i, &d, 8);
   2351 
   2352   *lo = i & 0xffffffff;
   2353   *hi = i >> 32;
   2354 }
   2355 
   2356 
   2357 void Assembler::movn_s(FPURegister fd, FPURegister fs, Register rt) {
   2358   DCHECK(!IsMipsArchVariant(kMips32r6));
   2359   GenInstrRegister(COP1, S, rt, fs, fd, MOVN_C);
   2360 }
   2361 
   2362 
   2363 void Assembler::movn_d(FPURegister fd, FPURegister fs, Register rt) {
   2364   DCHECK(!IsMipsArchVariant(kMips32r6));
   2365   GenInstrRegister(COP1, D, rt, fs, fd, MOVN_C);
   2366 }
   2367 
   2368 
   2369 void Assembler::sel(SecondaryField fmt, FPURegister fd, FPURegister fs,
   2370                     FPURegister ft) {
   2371   DCHECK(IsMipsArchVariant(kMips32r6));
   2372   DCHECK((fmt == D) || (fmt == S));
   2373 
   2374   GenInstrRegister(COP1, fmt, ft, fs, fd, SEL);
   2375 }
   2376 
   2377 
   2378 void Assembler::sel_s(FPURegister fd, FPURegister fs, FPURegister ft) {
   2379   sel(S, fd, fs, ft);
   2380 }
   2381 
   2382 
   2383 void Assembler::sel_d(FPURegister fd, FPURegister fs, FPURegister ft) {
   2384   sel(D, fd, fs, ft);
   2385 }
   2386 
   2387 
   2388 void Assembler::seleqz(SecondaryField fmt, FPURegister fd, FPURegister fs,
   2389                        FPURegister ft) {
   2390   DCHECK(IsMipsArchVariant(kMips32r6));
   2391   DCHECK((fmt == D) || (fmt == S));
   2392   GenInstrRegister(COP1, fmt, ft, fs, fd, SELEQZ_C);
   2393 }
   2394 
   2395 
   2396 void Assembler::selnez(Register rd, Register rs, Register rt) {
   2397   DCHECK(IsMipsArchVariant(kMips32r6));
   2398   GenInstrRegister(SPECIAL, rs, rt, rd, 0, SELNEZ_S);
   2399 }
   2400 
   2401 
   2402 void Assembler::selnez(SecondaryField fmt, FPURegister fd, FPURegister fs,
   2403                        FPURegister ft) {
   2404   DCHECK(IsMipsArchVariant(kMips32r6));
   2405   DCHECK((fmt == D) || (fmt == S));
   2406   GenInstrRegister(COP1, fmt, ft, fs, fd, SELNEZ_C);
   2407 }
   2408 
   2409 
   2410 void Assembler::seleqz_d(FPURegister fd, FPURegister fs, FPURegister ft) {
   2411   seleqz(D, fd, fs, ft);
   2412 }
   2413 
   2414 
   2415 void Assembler::seleqz_s(FPURegister fd, FPURegister fs, FPURegister ft) {
   2416   seleqz(S, fd, fs, ft);
   2417 }
   2418 
   2419 
   2420 void Assembler::selnez_d(FPURegister fd, FPURegister fs, FPURegister ft) {
   2421   selnez(D, fd, fs, ft);
   2422 }
   2423 
   2424 
   2425 void Assembler::selnez_s(FPURegister fd, FPURegister fs, FPURegister ft) {
   2426   selnez(S, fd, fs, ft);
   2427 }
   2428 
   2429 
   2430 void Assembler::movz_s(FPURegister fd, FPURegister fs, Register rt) {
   2431   DCHECK(!IsMipsArchVariant(kMips32r6));
   2432   GenInstrRegister(COP1, S, rt, fs, fd, MOVZ_C);
   2433 }
   2434 
   2435 
   2436 void Assembler::movz_d(FPURegister fd, FPURegister fs, Register rt) {
   2437   DCHECK(!IsMipsArchVariant(kMips32r6));
   2438   GenInstrRegister(COP1, D, rt, fs, fd, MOVZ_C);
   2439 }
   2440 
   2441 
   2442 void Assembler::movt_s(FPURegister fd, FPURegister fs, uint16_t cc) {
   2443   DCHECK(!IsMipsArchVariant(kMips32r6));
   2444   FPURegister ft;
   2445   ft.reg_code = (cc & 0x0007) << 2 | 1;
   2446   GenInstrRegister(COP1, S, ft, fs, fd, MOVF);
   2447 }
   2448 
   2449 
   2450 void Assembler::movt_d(FPURegister fd, FPURegister fs, uint16_t cc) {
   2451   DCHECK(!IsMipsArchVariant(kMips32r6));
   2452   FPURegister ft;
   2453   ft.reg_code = (cc & 0x0007) << 2 | 1;
   2454   GenInstrRegister(COP1, D, ft, fs, fd, MOVF);
   2455 }
   2456 
   2457 
   2458 void Assembler::movf_s(FPURegister fd, FPURegister fs, uint16_t cc) {
   2459   DCHECK(!IsMipsArchVariant(kMips32r6));
   2460   FPURegister ft;
   2461   ft.reg_code = (cc & 0x0007) << 2 | 0;
   2462   GenInstrRegister(COP1, S, ft, fs, fd, MOVF);
   2463 }
   2464 
   2465 
   2466 void Assembler::movf_d(FPURegister fd, FPURegister fs, uint16_t cc) {
   2467   DCHECK(!IsMipsArchVariant(kMips32r6));
   2468   FPURegister ft;
   2469   ft.reg_code = (cc & 0x0007) << 2 | 0;
   2470   GenInstrRegister(COP1, D, ft, fs, fd, MOVF);
   2471 }
   2472 
   2473 
   2474 // Arithmetic.
   2475 
   2476 void Assembler::add_s(FPURegister fd, FPURegister fs, FPURegister ft) {
   2477   GenInstrRegister(COP1, S, ft, fs, fd, ADD_S);
   2478 }
   2479 
   2480 
   2481 void Assembler::add_d(FPURegister fd, FPURegister fs, FPURegister ft) {
   2482   GenInstrRegister(COP1, D, ft, fs, fd, ADD_D);
   2483 }
   2484 
   2485 
   2486 void Assembler::sub_s(FPURegister fd, FPURegister fs, FPURegister ft) {
   2487   GenInstrRegister(COP1, S, ft, fs, fd, SUB_S);
   2488 }
   2489 
   2490 
   2491 void Assembler::sub_d(FPURegister fd, FPURegister fs, FPURegister ft) {
   2492   GenInstrRegister(COP1, D, ft, fs, fd, SUB_D);
   2493 }
   2494 
   2495 
   2496 void Assembler::mul_s(FPURegister fd, FPURegister fs, FPURegister ft) {
   2497   GenInstrRegister(COP1, S, ft, fs, fd, MUL_S);
   2498 }
   2499 
   2500 
   2501 void Assembler::mul_d(FPURegister fd, FPURegister fs, FPURegister ft) {
   2502   GenInstrRegister(COP1, D, ft, fs, fd, MUL_D);
   2503 }
   2504 
   2505 void Assembler::madd_s(FPURegister fd, FPURegister fr, FPURegister fs,
   2506                        FPURegister ft) {
   2507   DCHECK(IsMipsArchVariant(kMips32r2));
   2508   GenInstrRegister(COP1X, fr, ft, fs, fd, MADD_S);
   2509 }
   2510 
   2511 void Assembler::madd_d(FPURegister fd, FPURegister fr, FPURegister fs,
   2512     FPURegister ft) {
   2513   DCHECK(IsMipsArchVariant(kMips32r2));
   2514   GenInstrRegister(COP1X, fr, ft, fs, fd, MADD_D);
   2515 }
   2516 
   2517 void Assembler::msub_s(FPURegister fd, FPURegister fr, FPURegister fs,
   2518                        FPURegister ft) {
   2519   DCHECK(IsMipsArchVariant(kMips32r2));
   2520   GenInstrRegister(COP1X, fr, ft, fs, fd, MSUB_S);
   2521 }
   2522 
   2523 void Assembler::msub_d(FPURegister fd, FPURegister fr, FPURegister fs,
   2524                        FPURegister ft) {
   2525   DCHECK(IsMipsArchVariant(kMips32r2));
   2526   GenInstrRegister(COP1X, fr, ft, fs, fd, MSUB_D);
   2527 }
   2528 
   2529 void Assembler::maddf_s(FPURegister fd, FPURegister fs, FPURegister ft) {
   2530   DCHECK(IsMipsArchVariant(kMips32r6));
   2531   GenInstrRegister(COP1, S, ft, fs, fd, MADDF_S);
   2532 }
   2533 
   2534 void Assembler::maddf_d(FPURegister fd, FPURegister fs, FPURegister ft) {
   2535   DCHECK(IsMipsArchVariant(kMips32r6));
   2536   GenInstrRegister(COP1, D, ft, fs, fd, MADDF_D);
   2537 }
   2538 
   2539 void Assembler::msubf_s(FPURegister fd, FPURegister fs, FPURegister ft) {
   2540   DCHECK(IsMipsArchVariant(kMips32r6));
   2541   GenInstrRegister(COP1, S, ft, fs, fd, MSUBF_S);
   2542 }
   2543 
   2544 void Assembler::msubf_d(FPURegister fd, FPURegister fs, FPURegister ft) {
   2545   DCHECK(IsMipsArchVariant(kMips32r6));
   2546   GenInstrRegister(COP1, D, ft, fs, fd, MSUBF_D);
   2547 }
   2548 
   2549 void Assembler::div_s(FPURegister fd, FPURegister fs, FPURegister ft) {
   2550   GenInstrRegister(COP1, S, ft, fs, fd, DIV_S);
   2551 }
   2552 
   2553 
   2554 void Assembler::div_d(FPURegister fd, FPURegister fs, FPURegister ft) {
   2555   GenInstrRegister(COP1, D, ft, fs, fd, DIV_D);
   2556 }
   2557 
   2558 
   2559 void Assembler::abs_s(FPURegister fd, FPURegister fs) {
   2560   GenInstrRegister(COP1, S, f0, fs, fd, ABS_S);
   2561 }
   2562 
   2563 
   2564 void Assembler::abs_d(FPURegister fd, FPURegister fs) {
   2565   GenInstrRegister(COP1, D, f0, fs, fd, ABS_D);
   2566 }
   2567 
   2568 
   2569 void Assembler::mov_d(FPURegister fd, FPURegister fs) {
   2570   GenInstrRegister(COP1, D, f0, fs, fd, MOV_D);
   2571 }
   2572 
   2573 
   2574 void Assembler::mov_s(FPURegister fd, FPURegister fs) {
   2575   GenInstrRegister(COP1, S, f0, fs, fd, MOV_S);
   2576 }
   2577 
   2578 
   2579 void Assembler::neg_s(FPURegister fd, FPURegister fs) {
   2580   GenInstrRegister(COP1, S, f0, fs, fd, NEG_S);
   2581 }
   2582 
   2583 
   2584 void Assembler::neg_d(FPURegister fd, FPURegister fs) {
   2585   GenInstrRegister(COP1, D, f0, fs, fd, NEG_D);
   2586 }
   2587 
   2588 
   2589 void Assembler::sqrt_s(FPURegister fd, FPURegister fs) {
   2590   GenInstrRegister(COP1, S, f0, fs, fd, SQRT_S);
   2591 }
   2592 
   2593 
   2594 void Assembler::sqrt_d(FPURegister fd, FPURegister fs) {
   2595   GenInstrRegister(COP1, D, f0, fs, fd, SQRT_D);
   2596 }
   2597 
   2598 
   2599 void Assembler::rsqrt_s(FPURegister fd, FPURegister fs) {
   2600   DCHECK(IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6));
   2601   GenInstrRegister(COP1, S, f0, fs, fd, RSQRT_S);
   2602 }
   2603 
   2604 
   2605 void Assembler::rsqrt_d(FPURegister fd, FPURegister fs) {
   2606   DCHECK(IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6));
   2607   GenInstrRegister(COP1, D, f0, fs, fd, RSQRT_D);
   2608 }
   2609 
   2610 
   2611 void Assembler::recip_d(FPURegister fd, FPURegister fs) {
   2612   DCHECK(IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6));
   2613   GenInstrRegister(COP1, D, f0, fs, fd, RECIP_D);
   2614 }
   2615 
   2616 
   2617 void Assembler::recip_s(FPURegister fd, FPURegister fs) {
   2618   DCHECK(IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6));
   2619   GenInstrRegister(COP1, S, f0, fs, fd, RECIP_S);
   2620 }
   2621 
   2622 
   2623 // Conversions.
   2624 
   2625 void Assembler::cvt_w_s(FPURegister fd, FPURegister fs) {
   2626   GenInstrRegister(COP1, S, f0, fs, fd, CVT_W_S);
   2627 }
   2628 
   2629 
   2630 void Assembler::cvt_w_d(FPURegister fd, FPURegister fs) {
   2631   GenInstrRegister(COP1, D, f0, fs, fd, CVT_W_D);
   2632 }
   2633 
   2634 
   2635 void Assembler::trunc_w_s(FPURegister fd, FPURegister fs) {
   2636   GenInstrRegister(COP1, S, f0, fs, fd, TRUNC_W_S);
   2637 }
   2638 
   2639 
   2640 void Assembler::trunc_w_d(FPURegister fd, FPURegister fs) {
   2641   GenInstrRegister(COP1, D, f0, fs, fd, TRUNC_W_D);
   2642 }
   2643 
   2644 
   2645 void Assembler::round_w_s(FPURegister fd, FPURegister fs) {
   2646   GenInstrRegister(COP1, S, f0, fs, fd, ROUND_W_S);
   2647 }
   2648 
   2649 
   2650 void Assembler::round_w_d(FPURegister fd, FPURegister fs) {
   2651   GenInstrRegister(COP1, D, f0, fs, fd, ROUND_W_D);
   2652 }
   2653 
   2654 
   2655 void Assembler::floor_w_s(FPURegister fd, FPURegister fs) {
   2656   GenInstrRegister(COP1, S, f0, fs, fd, FLOOR_W_S);
   2657 }
   2658 
   2659 
   2660 void Assembler::floor_w_d(FPURegister fd, FPURegister fs) {
   2661   GenInstrRegister(COP1, D, f0, fs, fd, FLOOR_W_D);
   2662 }
   2663 
   2664 
   2665 void Assembler::ceil_w_s(FPURegister fd, FPURegister fs) {
   2666   GenInstrRegister(COP1, S, f0, fs, fd, CEIL_W_S);
   2667 }
   2668 
   2669 
   2670 void Assembler::ceil_w_d(FPURegister fd, FPURegister fs) {
   2671   GenInstrRegister(COP1, D, f0, fs, fd, CEIL_W_D);
   2672 }
   2673 
   2674 
   2675 void Assembler::rint_s(FPURegister fd, FPURegister fs) { rint(S, fd, fs); }
   2676 
   2677 
   2678 void Assembler::rint(SecondaryField fmt, FPURegister fd, FPURegister fs) {
   2679   DCHECK(IsMipsArchVariant(kMips32r6));
   2680   DCHECK((fmt == D) || (fmt == S));
   2681   GenInstrRegister(COP1, fmt, f0, fs, fd, RINT);
   2682 }
   2683 
   2684 
   2685 void Assembler::rint_d(FPURegister fd, FPURegister fs) { rint(D, fd, fs); }
   2686 
   2687 
   2688 void Assembler::cvt_l_s(FPURegister fd, FPURegister fs) {
   2689   DCHECK((IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)) &&
   2690          IsFp64Mode());
   2691   GenInstrRegister(COP1, S, f0, fs, fd, CVT_L_S);
   2692 }
   2693 
   2694 
   2695 void Assembler::cvt_l_d(FPURegister fd, FPURegister fs) {
   2696   DCHECK((IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)) &&
   2697          IsFp64Mode());
   2698   GenInstrRegister(COP1, D, f0, fs, fd, CVT_L_D);
   2699 }
   2700 
   2701 
   2702 void Assembler::trunc_l_s(FPURegister fd, FPURegister fs) {
   2703   DCHECK((IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)) &&
   2704          IsFp64Mode());
   2705   GenInstrRegister(COP1, S, f0, fs, fd, TRUNC_L_S);
   2706 }
   2707 
   2708 
   2709 void Assembler::trunc_l_d(FPURegister fd, FPURegister fs) {
   2710   DCHECK((IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)) &&
   2711          IsFp64Mode());
   2712   GenInstrRegister(COP1, D, f0, fs, fd, TRUNC_L_D);
   2713 }
   2714 
   2715 
   2716 void Assembler::round_l_s(FPURegister fd, FPURegister fs) {
   2717   DCHECK((IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)) &&
   2718          IsFp64Mode());
   2719   GenInstrRegister(COP1, S, f0, fs, fd, ROUND_L_S);
   2720 }
   2721 
   2722 
   2723 void Assembler::round_l_d(FPURegister fd, FPURegister fs) {
   2724   DCHECK((IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)) &&
   2725          IsFp64Mode());
   2726   GenInstrRegister(COP1, D, f0, fs, fd, ROUND_L_D);
   2727 }
   2728 
   2729 
   2730 void Assembler::floor_l_s(FPURegister fd, FPURegister fs) {
   2731   DCHECK((IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)) &&
   2732          IsFp64Mode());
   2733   GenInstrRegister(COP1, S, f0, fs, fd, FLOOR_L_S);
   2734 }
   2735 
   2736 
   2737 void Assembler::floor_l_d(FPURegister fd, FPURegister fs) {
   2738   DCHECK((IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)) &&
   2739          IsFp64Mode());
   2740   GenInstrRegister(COP1, D, f0, fs, fd, FLOOR_L_D);
   2741 }
   2742 
   2743 
   2744 void Assembler::ceil_l_s(FPURegister fd, FPURegister fs) {
   2745   DCHECK((IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)) &&
   2746          IsFp64Mode());
   2747   GenInstrRegister(COP1, S, f0, fs, fd, CEIL_L_S);
   2748 }
   2749 
   2750 
   2751 void Assembler::ceil_l_d(FPURegister fd, FPURegister fs) {
   2752   DCHECK((IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)) &&
   2753          IsFp64Mode());
   2754   GenInstrRegister(COP1, D, f0, fs, fd, CEIL_L_D);
   2755 }
   2756 
   2757 
   2758 void Assembler::class_s(FPURegister fd, FPURegister fs) {
   2759   DCHECK(IsMipsArchVariant(kMips32r6));
   2760   GenInstrRegister(COP1, S, f0, fs, fd, CLASS_S);
   2761 }
   2762 
   2763 
   2764 void Assembler::class_d(FPURegister fd, FPURegister fs) {
   2765   DCHECK(IsMipsArchVariant(kMips32r6));
   2766   GenInstrRegister(COP1, D, f0, fs, fd, CLASS_D);
   2767 }
   2768 
   2769 
   2770 void Assembler::min(SecondaryField fmt, FPURegister fd, FPURegister fs,
   2771                     FPURegister ft) {
   2772   DCHECK(IsMipsArchVariant(kMips32r6));
   2773   DCHECK((fmt == D) || (fmt == S));
   2774   GenInstrRegister(COP1, fmt, ft, fs, fd, MIN);
   2775 }
   2776 
   2777 
   2778 void Assembler::mina(SecondaryField fmt, FPURegister fd, FPURegister fs,
   2779                      FPURegister ft) {
   2780   DCHECK(IsMipsArchVariant(kMips32r6));
   2781   DCHECK((fmt == D) || (fmt == S));
   2782   GenInstrRegister(COP1, fmt, ft, fs, fd, MINA);
   2783 }
   2784 
   2785 
   2786 void Assembler::max(SecondaryField fmt, FPURegister fd, FPURegister fs,
   2787                     FPURegister ft) {
   2788   DCHECK(IsMipsArchVariant(kMips32r6));
   2789   DCHECK((fmt == D) || (fmt == S));
   2790   GenInstrRegister(COP1, fmt, ft, fs, fd, MAX);
   2791 }
   2792 
   2793 
   2794 void Assembler::maxa(SecondaryField fmt, FPURegister fd, FPURegister fs,
   2795                      FPURegister ft) {
   2796   DCHECK(IsMipsArchVariant(kMips32r6));
   2797   DCHECK((fmt == D) || (fmt == S));
   2798   GenInstrRegister(COP1, fmt, ft, fs, fd, MAXA);
   2799 }
   2800 
   2801 
   2802 void Assembler::min_s(FPURegister fd, FPURegister fs, FPURegister ft) {
   2803   min(S, fd, fs, ft);
   2804 }
   2805 
   2806 
   2807 void Assembler::min_d(FPURegister fd, FPURegister fs, FPURegister ft) {
   2808   min(D, fd, fs, ft);
   2809 }
   2810 
   2811 
   2812 void Assembler::max_s(FPURegister fd, FPURegister fs, FPURegister ft) {
   2813   max(S, fd, fs, ft);
   2814 }
   2815 
   2816 
   2817 void Assembler::max_d(FPURegister fd, FPURegister fs, FPURegister ft) {
   2818   max(D, fd, fs, ft);
   2819 }
   2820 
   2821 
   2822 void Assembler::mina_s(FPURegister fd, FPURegister fs, FPURegister ft) {
   2823   mina(S, fd, fs, ft);
   2824 }
   2825 
   2826 
   2827 void Assembler::mina_d(FPURegister fd, FPURegister fs, FPURegister ft) {
   2828   mina(D, fd, fs, ft);
   2829 }
   2830 
   2831 
   2832 void Assembler::maxa_s(FPURegister fd, FPURegister fs, FPURegister ft) {
   2833   maxa(S, fd, fs, ft);
   2834 }
   2835 
   2836 
   2837 void Assembler::maxa_d(FPURegister fd, FPURegister fs, FPURegister ft) {
   2838   maxa(D, fd, fs, ft);
   2839 }
   2840 
   2841 
   2842 void Assembler::cvt_s_w(FPURegister fd, FPURegister fs) {
   2843   GenInstrRegister(COP1, W, f0, fs, fd, CVT_S_W);
   2844 }
   2845 
   2846 
   2847 void Assembler::cvt_s_l(FPURegister fd, FPURegister fs) {
   2848   DCHECK((IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)) &&
   2849          IsFp64Mode());
   2850   GenInstrRegister(COP1, L, f0, fs, fd, CVT_S_L);
   2851 }
   2852 
   2853 
   2854 void Assembler::cvt_s_d(FPURegister fd, FPURegister fs) {
   2855   GenInstrRegister(COP1, D, f0, fs, fd, CVT_S_D);
   2856 }
   2857 
   2858 
   2859 void Assembler::cvt_d_w(FPURegister fd, FPURegister fs) {
   2860   GenInstrRegister(COP1, W, f0, fs, fd, CVT_D_W);
   2861 }
   2862 
   2863 
   2864 void Assembler::cvt_d_l(FPURegister fd, FPURegister fs) {
   2865   DCHECK((IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)) &&
   2866          IsFp64Mode());
   2867   GenInstrRegister(COP1, L, f0, fs, fd, CVT_D_L);
   2868 }
   2869 
   2870 
   2871 void Assembler::cvt_d_s(FPURegister fd, FPURegister fs) {
   2872   GenInstrRegister(COP1, S, f0, fs, fd, CVT_D_S);
   2873 }
   2874 
   2875 
   2876 // Conditions for >= MIPSr6.
   2877 void Assembler::cmp(FPUCondition cond, SecondaryField fmt,
   2878     FPURegister fd, FPURegister fs, FPURegister ft) {
   2879   DCHECK(IsMipsArchVariant(kMips32r6));
   2880   DCHECK((fmt & ~(31 << kRsShift)) == 0);
   2881   Instr instr = COP1 | fmt | ft.code() << kFtShift |
   2882       fs.code() << kFsShift | fd.code() << kFdShift | (0 << 5) | cond;
   2883   emit(instr);
   2884 }
   2885 
   2886 
   2887 void Assembler::cmp_s(FPUCondition cond, FPURegister fd, FPURegister fs,
   2888                       FPURegister ft) {
   2889   cmp(cond, W, fd, fs, ft);
   2890 }
   2891 
   2892 void Assembler::cmp_d(FPUCondition cond, FPURegister fd, FPURegister fs,
   2893                       FPURegister ft) {
   2894   cmp(cond, L, fd, fs, ft);
   2895 }
   2896 
   2897 
   2898 void Assembler::bc1eqz(int16_t offset, FPURegister ft) {
   2899   DCHECK(IsMipsArchVariant(kMips32r6));
   2900   Instr instr = COP1 | BC1EQZ | ft.code() << kFtShift | (offset & kImm16Mask);
   2901   emit(instr);
   2902 }
   2903 
   2904 
   2905 void Assembler::bc1nez(int16_t offset, FPURegister ft) {
   2906   DCHECK(IsMipsArchVariant(kMips32r6));
   2907   Instr instr = COP1 | BC1NEZ | ft.code() << kFtShift | (offset & kImm16Mask);
   2908   emit(instr);
   2909 }
   2910 
   2911 
   2912 // Conditions for < MIPSr6.
   2913 void Assembler::c(FPUCondition cond, SecondaryField fmt,
   2914     FPURegister fs, FPURegister ft, uint16_t cc) {
   2915   DCHECK(is_uint3(cc));
   2916   DCHECK(fmt == S || fmt == D);
   2917   DCHECK((fmt & ~(31 << kRsShift)) == 0);
   2918   Instr instr = COP1 | fmt | ft.code() << 16 | fs.code() << kFsShift
   2919       | cc << 8 | 3 << 4 | cond;
   2920   emit(instr);
   2921 }
   2922 
   2923 
   2924 void Assembler::c_s(FPUCondition cond, FPURegister fs, FPURegister ft,
   2925                     uint16_t cc) {
   2926   c(cond, S, fs, ft, cc);
   2927 }
   2928 
   2929 
   2930 void Assembler::c_d(FPUCondition cond, FPURegister fs, FPURegister ft,
   2931                     uint16_t cc) {
   2932   c(cond, D, fs, ft, cc);
   2933 }
   2934 
   2935 
   2936 void Assembler::fcmp(FPURegister src1, const double src2,
   2937       FPUCondition cond) {
   2938   DCHECK(src2 == 0.0);
   2939   mtc1(zero_reg, f14);
   2940   cvt_d_w(f14, f14);
   2941   c(cond, D, src1, f14, 0);
   2942 }
   2943 
   2944 
   2945 void Assembler::bc1f(int16_t offset, uint16_t cc) {
   2946   DCHECK(is_uint3(cc));
   2947   Instr instr = COP1 | BC1 | cc << 18 | 0 << 16 | (offset & kImm16Mask);
   2948   emit(instr);
   2949 }
   2950 
   2951 
   2952 void Assembler::bc1t(int16_t offset, uint16_t cc) {
   2953   DCHECK(is_uint3(cc));
   2954   Instr instr = COP1 | BC1 | cc << 18 | 1 << 16 | (offset & kImm16Mask);
   2955   emit(instr);
   2956 }
   2957 
   2958 
   2959 int Assembler::RelocateInternalReference(RelocInfo::Mode rmode, byte* pc,
   2960                                          intptr_t pc_delta) {
   2961   Instr instr = instr_at(pc);
   2962 
   2963   if (RelocInfo::IsInternalReference(rmode)) {
   2964     int32_t* p = reinterpret_cast<int32_t*>(pc);
   2965     if (*p == 0) {
   2966       return 0;  // Number of instructions patched.
   2967     }
   2968     *p += pc_delta;
   2969     return 1;  // Number of instructions patched.
   2970   } else {
   2971     DCHECK(RelocInfo::IsInternalReferenceEncoded(rmode));
   2972     if (IsLui(instr)) {
   2973       Instr instr1 = instr_at(pc + 0 * Assembler::kInstrSize);
   2974       Instr instr2 = instr_at(pc + 1 * Assembler::kInstrSize);
   2975       DCHECK(IsOri(instr2) || IsJicOrJialc(instr2));
   2976       int32_t imm;
   2977       if (IsJicOrJialc(instr2)) {
   2978         imm = CreateTargetAddress(instr1, instr2);
   2979       } else {
   2980         imm = (instr1 & static_cast<int32_t>(kImm16Mask)) << kLuiShift;
   2981         imm |= (instr2 & static_cast<int32_t>(kImm16Mask));
   2982       }
   2983 
   2984       if (imm == kEndOfJumpChain) {
   2985         return 0;  // Number of instructions patched.
   2986       }
   2987       imm += pc_delta;
   2988       DCHECK((imm & 3) == 0);
   2989       instr1 &= ~kImm16Mask;
   2990       instr2 &= ~kImm16Mask;
   2991 
   2992       if (IsJicOrJialc(instr2)) {
   2993         uint32_t lui_offset_u, jic_offset_u;
   2994         Assembler::UnpackTargetAddressUnsigned(imm, lui_offset_u, jic_offset_u);
   2995         instr_at_put(pc + 0 * Assembler::kInstrSize, instr1 | lui_offset_u);
   2996         instr_at_put(pc + 1 * Assembler::kInstrSize, instr2 | jic_offset_u);
   2997       } else {
   2998         instr_at_put(pc + 0 * Assembler::kInstrSize,
   2999                      instr1 | ((imm >> kLuiShift) & kImm16Mask));
   3000         instr_at_put(pc + 1 * Assembler::kInstrSize,
   3001                      instr2 | (imm & kImm16Mask));
   3002       }
   3003       return 2;  // Number of instructions patched.
   3004     } else {
   3005       UNREACHABLE();
   3006       return 0;
   3007     }
   3008   }
   3009 }
   3010 
   3011 
   3012 void Assembler::GrowBuffer() {
   3013   if (!own_buffer_) FATAL("external code buffer is too small");
   3014 
   3015   // Compute new buffer size.
   3016   CodeDesc desc;  // The new buffer.
   3017   if (buffer_size_ < 1 * MB) {
   3018     desc.buffer_size = 2*buffer_size_;
   3019   } else {
   3020     desc.buffer_size = buffer_size_ + 1*MB;
   3021   }
   3022   CHECK_GT(desc.buffer_size, 0);  // No overflow.
   3023 
   3024   // Set up new buffer.
   3025   desc.buffer = NewArray<byte>(desc.buffer_size);
   3026   desc.origin = this;
   3027 
   3028   desc.instr_size = pc_offset();
   3029   desc.reloc_size = (buffer_ + buffer_size_) - reloc_info_writer.pos();
   3030 
   3031   // Copy the data.
   3032   int pc_delta = desc.buffer - buffer_;
   3033   int rc_delta = (desc.buffer + desc.buffer_size) - (buffer_ + buffer_size_);
   3034   MemMove(desc.buffer, buffer_, desc.instr_size);
   3035   MemMove(reloc_info_writer.pos() + rc_delta, reloc_info_writer.pos(),
   3036           desc.reloc_size);
   3037 
   3038   // Switch buffers.
   3039   DeleteArray(buffer_);
   3040   buffer_ = desc.buffer;
   3041   buffer_size_ = desc.buffer_size;
   3042   pc_ += pc_delta;
   3043   reloc_info_writer.Reposition(reloc_info_writer.pos() + rc_delta,
   3044                                reloc_info_writer.last_pc() + pc_delta);
   3045 
   3046   // Relocate runtime entries.
   3047   for (RelocIterator it(desc); !it.done(); it.next()) {
   3048     RelocInfo::Mode rmode = it.rinfo()->rmode();
   3049     if (rmode == RelocInfo::INTERNAL_REFERENCE_ENCODED ||
   3050         rmode == RelocInfo::INTERNAL_REFERENCE) {
   3051       byte* p = reinterpret_cast<byte*>(it.rinfo()->pc());
   3052       RelocateInternalReference(rmode, p, pc_delta);
   3053     }
   3054   }
   3055   DCHECK(!overflow());
   3056 }
   3057 
   3058 
   3059 void Assembler::db(uint8_t data) {
   3060   CheckForEmitInForbiddenSlot();
   3061   EmitHelper(data);
   3062 }
   3063 
   3064 
   3065 void Assembler::dd(uint32_t data) {
   3066   CheckForEmitInForbiddenSlot();
   3067   EmitHelper(data);
   3068 }
   3069 
   3070 
   3071 void Assembler::dq(uint64_t data) {
   3072   CheckForEmitInForbiddenSlot();
   3073   EmitHelper(data);
   3074 }
   3075 
   3076 
   3077 void Assembler::dd(Label* label) {
   3078   uint32_t data;
   3079   CheckForEmitInForbiddenSlot();
   3080   if (label->is_bound()) {
   3081     data = reinterpret_cast<uint32_t>(buffer_ + label->pos());
   3082   } else {
   3083     data = jump_address(label);
   3084     unbound_labels_count_++;
   3085     internal_reference_positions_.insert(label->pos());
   3086   }
   3087   RecordRelocInfo(RelocInfo::INTERNAL_REFERENCE);
   3088   EmitHelper(data);
   3089 }
   3090 
   3091 
   3092 void Assembler::RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data) {
   3093   // We do not try to reuse pool constants.
   3094   RelocInfo rinfo(isolate(), pc_, rmode, data, NULL);
   3095   if (rmode >= RelocInfo::COMMENT &&
   3096       rmode <= RelocInfo::DEBUG_BREAK_SLOT_AT_TAIL_CALL) {
   3097     // Adjust code for new modes.
   3098     DCHECK(RelocInfo::IsDebugBreakSlot(rmode) || RelocInfo::IsComment(rmode));
   3099     // These modes do not need an entry in the constant pool.
   3100   }
   3101   if (!RelocInfo::IsNone(rinfo.rmode())) {
   3102     // Don't record external references unless the heap will be serialized.
   3103     if (rmode == RelocInfo::EXTERNAL_REFERENCE &&
   3104         !serializer_enabled() && !emit_debug_code()) {
   3105       return;
   3106     }
   3107     DCHECK(buffer_space() >= kMaxRelocSize);  // Too late to grow buffer here.
   3108     if (rmode == RelocInfo::CODE_TARGET_WITH_ID) {
   3109       RelocInfo reloc_info_with_ast_id(isolate(), pc_, rmode,
   3110                                        RecordedAstId().ToInt(), NULL);
   3111       ClearRecordedAstId();
   3112       reloc_info_writer.Write(&reloc_info_with_ast_id);
   3113     } else {
   3114       reloc_info_writer.Write(&rinfo);
   3115     }
   3116   }
   3117 }
   3118 
   3119 
   3120 void Assembler::BlockTrampolinePoolFor(int instructions) {
   3121   CheckTrampolinePoolQuick(instructions);
   3122   BlockTrampolinePoolBefore(pc_offset() + instructions * kInstrSize);
   3123 }
   3124 
   3125 
   3126 void Assembler::CheckTrampolinePool() {
   3127   // Some small sequences of instructions must not be broken up by the
   3128   // insertion of a trampoline pool; such sequences are protected by setting
   3129   // either trampoline_pool_blocked_nesting_ or no_trampoline_pool_before_,
   3130   // which are both checked here. Also, recursive calls to CheckTrampolinePool
   3131   // are blocked by trampoline_pool_blocked_nesting_.
   3132   if ((trampoline_pool_blocked_nesting_ > 0) ||
   3133       (pc_offset() < no_trampoline_pool_before_)) {
   3134     // Emission is currently blocked; make sure we try again as soon as
   3135     // possible.
   3136     if (trampoline_pool_blocked_nesting_ > 0) {
   3137       next_buffer_check_ = pc_offset() + kInstrSize;
   3138     } else {
   3139       next_buffer_check_ = no_trampoline_pool_before_;
   3140     }
   3141     return;
   3142   }
   3143 
   3144   DCHECK(!trampoline_emitted_);
   3145   DCHECK(unbound_labels_count_ >= 0);
   3146   if (unbound_labels_count_ > 0) {
   3147     // First we emit jump (2 instructions), then we emit trampoline pool.
   3148     { BlockTrampolinePoolScope block_trampoline_pool(this);
   3149       Label after_pool;
   3150       if (IsMipsArchVariant(kMips32r6)) {
   3151         bc(&after_pool);
   3152       } else {
   3153         b(&after_pool);
   3154         nop();
   3155       }
   3156 
   3157       int pool_start = pc_offset();
   3158       if (IsMipsArchVariant(kMips32r6)) {
   3159         for (int i = 0; i < unbound_labels_count_; i++) {
   3160           uint32_t imm32;
   3161           imm32 = jump_address(&after_pool);
   3162           uint32_t lui_offset, jic_offset;
   3163           UnpackTargetAddressUnsigned(imm32, lui_offset, jic_offset);
   3164           {
   3165             BlockGrowBufferScope block_buf_growth(this);
   3166             // Buffer growth (and relocation) must be blocked for internal
   3167             // references until associated instructions are emitted and
   3168             // available to be patched.
   3169             RecordRelocInfo(RelocInfo::INTERNAL_REFERENCE_ENCODED);
   3170             lui(at, lui_offset);
   3171             jic(at, jic_offset);
   3172           }
   3173           CheckBuffer();
   3174         }
   3175       } else {
   3176         for (int i = 0; i < unbound_labels_count_; i++) {
   3177           uint32_t imm32;
   3178           imm32 = jump_address(&after_pool);
   3179           {
   3180             BlockGrowBufferScope block_buf_growth(this);
   3181             // Buffer growth (and relocation) must be blocked for internal
   3182             // references until associated instructions are emitted and
   3183             // available to be patched.
   3184             RecordRelocInfo(RelocInfo::INTERNAL_REFERENCE_ENCODED);
   3185             lui(at, (imm32 & kHiMask) >> kLuiShift);
   3186             ori(at, at, (imm32 & kImm16Mask));
   3187           }
   3188           CheckBuffer();
   3189           jr(at);
   3190           nop();
   3191         }
   3192       }
   3193       bind(&after_pool);
   3194       trampoline_ = Trampoline(pool_start, unbound_labels_count_);
   3195 
   3196       trampoline_emitted_ = true;
   3197       // As we are only going to emit trampoline once, we need to prevent any
   3198       // further emission.
   3199       next_buffer_check_ = kMaxInt;
   3200     }
   3201   } else {
   3202     // Number of branches to unbound label at this point is zero, so we can
   3203     // move next buffer check to maximum.
   3204     next_buffer_check_ = pc_offset() +
   3205         kMaxBranchOffset - kTrampolineSlotsSize * 16;
   3206   }
   3207   return;
   3208 }
   3209 
   3210 
   3211 Address Assembler::target_address_at(Address pc) {
   3212   Instr instr1 = instr_at(pc);
   3213   Instr instr2 = instr_at(pc + kInstrSize);
   3214   // Interpret 2 instructions generated by li: lui/ori
   3215   if (IsLui(instr1) && IsOri(instr2)) {
   3216     // Assemble the 32 bit value.
   3217     return reinterpret_cast<Address>((GetImmediate16(instr1) << kLuiShift) |
   3218                                      GetImmediate16(instr2));
   3219   }
   3220 
   3221   // We should never get here, force a bad address if we do.
   3222   UNREACHABLE();
   3223   return (Address)0x0;
   3224 }
   3225 
   3226 
   3227 // MIPS and ia32 use opposite encoding for qNaN and sNaN, such that ia32
   3228 // qNaN is a MIPS sNaN, and ia32 sNaN is MIPS qNaN. If running from a heap
   3229 // snapshot generated on ia32, the resulting MIPS sNaN must be quieted.
   3230 // OS::nan_value() returns a qNaN.
   3231 void Assembler::QuietNaN(HeapObject* object) {
   3232   HeapNumber::cast(object)->set_value(std::numeric_limits<double>::quiet_NaN());
   3233 }
   3234 
   3235 
   3236 // On Mips, a target address is stored in a lui/ori instruction pair, each
   3237 // of which load 16 bits of the 32-bit address to a register.
   3238 // Patching the address must replace both instr, and flush the i-cache.
   3239 // On r6, target address is stored in a lui/jic pair, and both instr have to be
   3240 // patched.
   3241 //
   3242 // There is an optimization below, which emits a nop when the address
   3243 // fits in just 16 bits. This is unlikely to help, and should be benchmarked,
   3244 // and possibly removed.
   3245 void Assembler::set_target_address_at(Isolate* isolate, Address pc,
   3246                                       Address target,
   3247                                       ICacheFlushMode icache_flush_mode) {
   3248   Instr instr2 = instr_at(pc + kInstrSize);
   3249   uint32_t rt_code = GetRtField(instr2);
   3250   uint32_t* p = reinterpret_cast<uint32_t*>(pc);
   3251   uint32_t itarget = reinterpret_cast<uint32_t>(target);
   3252 
   3253 #ifdef DEBUG
   3254   // Check we have the result from a li macro-instruction, using instr pair.
   3255   Instr instr1 = instr_at(pc);
   3256   CHECK(IsLui(instr1) && (IsOri(instr2) || IsJicOrJialc(instr2)));
   3257 #endif
   3258 
   3259   if (IsJicOrJialc(instr2)) {
   3260     // Must use 2 instructions to insure patchable code => use lui and jic
   3261     uint32_t lui_offset, jic_offset;
   3262     Assembler::UnpackTargetAddressUnsigned(itarget, lui_offset, jic_offset);
   3263 
   3264     *p &= ~kImm16Mask;
   3265     *(p + 1) &= ~kImm16Mask;
   3266 
   3267     *p |= lui_offset;
   3268     *(p + 1) |= jic_offset;
   3269 
   3270   } else {
   3271     // Must use 2 instructions to insure patchable code => just use lui and ori.
   3272     // lui rt, upper-16.
   3273     // ori rt rt, lower-16.
   3274     *p = LUI | rt_code | ((itarget & kHiMask) >> kLuiShift);
   3275     *(p + 1) = ORI | rt_code | (rt_code << 5) | (itarget & kImm16Mask);
   3276   }
   3277 
   3278   if (icache_flush_mode != SKIP_ICACHE_FLUSH) {
   3279     Assembler::FlushICache(isolate, pc, 2 * sizeof(int32_t));
   3280   }
   3281 }
   3282 
   3283 }  // namespace internal
   3284 }  // namespace v8
   3285 
   3286 #endif  // V8_TARGET_ARCH_MIPS
   3287