Home | History | Annotate | Download | only in mips
      1 /*
      2  * Copyright (C) 2011 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #include "assembler_mips.h"
     18 
     19 #include "base/bit_utils.h"
     20 #include "base/casts.h"
     21 #include "entrypoints/quick/quick_entrypoints.h"
     22 #include "entrypoints/quick/quick_entrypoints_enum.h"
     23 #include "memory_region.h"
     24 #include "thread.h"
     25 
     26 namespace art {
     27 namespace mips {
     28 
     29 static_assert(static_cast<size_t>(kMipsPointerSize) == kMipsWordSize,
     30               "Unexpected Mips pointer size.");
     31 static_assert(kMipsPointerSize == PointerSize::k32, "Unexpected Mips pointer size.");
     32 
     33 
     34 std::ostream& operator<<(std::ostream& os, const DRegister& rhs) {
     35   if (rhs >= D0 && rhs < kNumberOfDRegisters) {
     36     os << "d" << static_cast<int>(rhs);
     37   } else {
     38     os << "DRegister[" << static_cast<int>(rhs) << "]";
     39   }
     40   return os;
     41 }
     42 
     43 MipsAssembler::DelaySlot::DelaySlot()
     44     : instruction_(0),
     45       gpr_outs_mask_(0),
     46       gpr_ins_mask_(0),
     47       fpr_outs_mask_(0),
     48       fpr_ins_mask_(0),
     49       cc_outs_mask_(0),
     50       cc_ins_mask_(0) {}
     51 
     52 void MipsAssembler::DsFsmInstr(uint32_t instruction,
     53                                uint32_t gpr_outs_mask,
     54                                uint32_t gpr_ins_mask,
     55                                uint32_t fpr_outs_mask,
     56                                uint32_t fpr_ins_mask,
     57                                uint32_t cc_outs_mask,
     58                                uint32_t cc_ins_mask) {
     59   if (!reordering_) {
     60     CHECK_EQ(ds_fsm_state_, kExpectingLabel);
     61     CHECK_EQ(delay_slot_.instruction_, 0u);
     62     return;
     63   }
     64   switch (ds_fsm_state_) {
     65     case kExpectingLabel:
     66       break;
     67     case kExpectingInstruction:
     68       CHECK_EQ(ds_fsm_target_pc_ + sizeof(uint32_t), buffer_.Size());
     69       // If the last instruction is not suitable for delay slots, drop
     70       // the PC of the label preceding it so that no unconditional branch
     71       // uses this instruction to fill its delay slot.
     72       if (instruction == 0) {
     73         DsFsmDropLabel();  // Sets ds_fsm_state_ = kExpectingLabel.
     74       } else {
     75         // Otherwise wait for another instruction or label before we can
     76         // commit the label PC. The label PC will be dropped if instead
     77         // of another instruction or label there's a call from the code
     78         // generator to CodePosition() to record the buffer size.
     79         // Instructions after which the buffer size is recorded cannot
     80         // be moved into delay slots or anywhere else because they may
     81         // trigger signals and the signal handlers expect these signals
     82         // to be coming from the instructions immediately preceding the
     83         // recorded buffer locations.
     84         ds_fsm_state_ = kExpectingCommit;
     85       }
     86       break;
     87     case kExpectingCommit:
     88       CHECK_EQ(ds_fsm_target_pc_ + 2 * sizeof(uint32_t), buffer_.Size());
     89       DsFsmCommitLabel();  // Sets ds_fsm_state_ = kExpectingLabel.
     90       break;
     91   }
     92   delay_slot_.instruction_ = instruction;
     93   delay_slot_.gpr_outs_mask_ = gpr_outs_mask & ~1u;  // Ignore register ZERO.
     94   delay_slot_.gpr_ins_mask_ = gpr_ins_mask & ~1u;  // Ignore register ZERO.
     95   delay_slot_.fpr_outs_mask_ = fpr_outs_mask;
     96   delay_slot_.fpr_ins_mask_ = fpr_ins_mask;
     97   delay_slot_.cc_outs_mask_ = cc_outs_mask;
     98   delay_slot_.cc_ins_mask_ = cc_ins_mask;
     99 }
    100 
    101 void MipsAssembler::DsFsmLabel() {
    102   if (!reordering_) {
    103     CHECK_EQ(ds_fsm_state_, kExpectingLabel);
    104     CHECK_EQ(delay_slot_.instruction_, 0u);
    105     return;
    106   }
    107   switch (ds_fsm_state_) {
    108     case kExpectingLabel:
    109       ds_fsm_target_pc_ = buffer_.Size();
    110       ds_fsm_state_ = kExpectingInstruction;
    111       break;
    112     case kExpectingInstruction:
    113       // Allow consecutive labels.
    114       CHECK_EQ(ds_fsm_target_pc_, buffer_.Size());
    115       break;
    116     case kExpectingCommit:
    117       CHECK_EQ(ds_fsm_target_pc_ + sizeof(uint32_t), buffer_.Size());
    118       DsFsmCommitLabel();
    119       ds_fsm_target_pc_ = buffer_.Size();
    120       ds_fsm_state_ = kExpectingInstruction;
    121       break;
    122   }
    123   // We cannot move instructions into delay slots across labels.
    124   delay_slot_.instruction_ = 0;
    125 }
    126 
    127 void MipsAssembler::DsFsmCommitLabel() {
    128   if (ds_fsm_state_ == kExpectingCommit) {
    129     ds_fsm_target_pcs_.emplace_back(ds_fsm_target_pc_);
    130   }
    131   ds_fsm_state_ = kExpectingLabel;
    132 }
    133 
    134 void MipsAssembler::DsFsmDropLabel() {
    135   ds_fsm_state_ = kExpectingLabel;
    136 }
    137 
    138 bool MipsAssembler::SetReorder(bool enable) {
    139   bool last_state = reordering_;
    140   if (last_state != enable) {
    141     DsFsmCommitLabel();
    142     DsFsmInstrNop(0);
    143   }
    144   reordering_ = enable;
    145   return last_state;
    146 }
    147 
    148 size_t MipsAssembler::CodePosition() {
    149   // The last instruction cannot be used in a delay slot, do not commit
    150   // the label before it (if any) and clear the delay slot.
    151   DsFsmDropLabel();
    152   DsFsmInstrNop(0);
    153   size_t size = buffer_.Size();
    154   // In theory we can get the following sequence:
    155   //   label1:
    156   //     instr
    157   //   label2: # label1 gets committed when label2 is seen
    158   //     CodePosition() call
    159   // and we need to uncommit label1.
    160   if (ds_fsm_target_pcs_.size() != 0 && ds_fsm_target_pcs_.back() + sizeof(uint32_t) == size) {
    161     ds_fsm_target_pcs_.pop_back();
    162   }
    163   return size;
    164 }
    165 
    166 void MipsAssembler::DsFsmInstrNop(uint32_t instruction ATTRIBUTE_UNUSED) {
    167   DsFsmInstr(0, 0, 0, 0, 0, 0, 0);
    168 }
    169 
    170 void MipsAssembler::DsFsmInstrRrr(uint32_t instruction, Register out, Register in1, Register in2) {
    171   DsFsmInstr(instruction, (1u << out), (1u << in1) | (1u << in2), 0, 0, 0, 0);
    172 }
    173 
    174 void MipsAssembler::DsFsmInstrRrrr(uint32_t instruction,
    175                                    Register in1_out,
    176                                    Register in2,
    177                                    Register in3) {
    178   DsFsmInstr(instruction, (1u << in1_out), (1u << in1_out) | (1u << in2) | (1u << in3), 0, 0, 0, 0);
    179 }
    180 
    181 void MipsAssembler::DsFsmInstrFff(uint32_t instruction,
    182                                   FRegister out,
    183                                   FRegister in1,
    184                                   FRegister in2) {
    185   DsFsmInstr(instruction, 0, 0, (1u << out), (1u << in1) | (1u << in2), 0, 0);
    186 }
    187 
    188 void MipsAssembler::DsFsmInstrFfff(uint32_t instruction,
    189                                    FRegister in1_out,
    190                                    FRegister in2,
    191                                    FRegister in3) {
    192   DsFsmInstr(instruction, 0, 0, (1u << in1_out), (1u << in1_out) | (1u << in2) | (1u << in3), 0, 0);
    193 }
    194 
    195 void MipsAssembler::DsFsmInstrFffr(uint32_t instruction,
    196                                    FRegister in1_out,
    197                                    FRegister in2,
    198                                    Register in3) {
    199   DsFsmInstr(instruction, 0, (1u << in3), (1u << in1_out), (1u << in1_out) | (1u << in2), 0, 0);
    200 }
    201 
    202 void MipsAssembler::DsFsmInstrRf(uint32_t instruction, Register out, FRegister in) {
    203   DsFsmInstr(instruction, (1u << out), 0, 0, (1u << in), 0, 0);
    204 }
    205 
    206 void MipsAssembler::DsFsmInstrFr(uint32_t instruction, FRegister out, Register in) {
    207   DsFsmInstr(instruction, 0, (1u << in), (1u << out), 0, 0, 0);
    208 }
    209 
    210 void MipsAssembler::DsFsmInstrFR(uint32_t instruction, FRegister in1, Register in2) {
    211   DsFsmInstr(instruction, 0, (1u << in2), 0, (1u << in1), 0, 0);
    212 }
    213 
    214 void MipsAssembler::DsFsmInstrCff(uint32_t instruction, int cc_out, FRegister in1, FRegister in2) {
    215   DsFsmInstr(instruction, 0, 0, 0, (1u << in1) | (1u << in2), (1 << cc_out), 0);
    216 }
    217 
    218 void MipsAssembler::DsFsmInstrRrrc(uint32_t instruction,
    219                                    Register in1_out,
    220                                    Register in2,
    221                                    int cc_in) {
    222   DsFsmInstr(instruction, (1u << in1_out), (1u << in1_out) | (1u << in2), 0, 0, 0, (1 << cc_in));
    223 }
    224 
    225 void MipsAssembler::DsFsmInstrFffc(uint32_t instruction,
    226                                    FRegister in1_out,
    227                                    FRegister in2,
    228                                    int cc_in) {
    229   DsFsmInstr(instruction, 0, 0, (1u << in1_out), (1u << in1_out) | (1u << in2), 0, (1 << cc_in));
    230 }
    231 
    232 void MipsAssembler::FinalizeCode() {
    233   for (auto& exception_block : exception_blocks_) {
    234     EmitExceptionPoll(&exception_block);
    235   }
    236   // Commit the last branch target label (if any) and disable instruction reordering.
    237   DsFsmCommitLabel();
    238   SetReorder(false);
    239   EmitLiterals();
    240   ReserveJumpTableSpace();
    241   PromoteBranches();
    242 }
    243 
    244 void MipsAssembler::FinalizeInstructions(const MemoryRegion& region) {
    245   size_t number_of_delayed_adjust_pcs = cfi().NumberOfDelayedAdvancePCs();
    246   EmitBranches();
    247   EmitJumpTables();
    248   Assembler::FinalizeInstructions(region);
    249   PatchCFI(number_of_delayed_adjust_pcs);
    250 }
    251 
    252 void MipsAssembler::PatchCFI(size_t number_of_delayed_adjust_pcs) {
    253   if (cfi().NumberOfDelayedAdvancePCs() == 0u) {
    254     DCHECK_EQ(number_of_delayed_adjust_pcs, 0u);
    255     return;
    256   }
    257 
    258   typedef DebugFrameOpCodeWriterForAssembler::DelayedAdvancePC DelayedAdvancePC;
    259   const auto data = cfi().ReleaseStreamAndPrepareForDelayedAdvancePC();
    260   const std::vector<uint8_t>& old_stream = data.first;
    261   const std::vector<DelayedAdvancePC>& advances = data.second;
    262 
    263   // PCs recorded before EmitBranches() need to be adjusted.
    264   // PCs recorded during EmitBranches() are already adjusted.
    265   // Both ranges are separately sorted but they may overlap.
    266   if (kIsDebugBuild) {
    267     auto cmp = [](const DelayedAdvancePC& lhs, const DelayedAdvancePC& rhs) {
    268       return lhs.pc < rhs.pc;
    269     };
    270     CHECK(std::is_sorted(advances.begin(), advances.begin() + number_of_delayed_adjust_pcs, cmp));
    271     CHECK(std::is_sorted(advances.begin() + number_of_delayed_adjust_pcs, advances.end(), cmp));
    272   }
    273 
    274   // Append initial CFI data if any.
    275   size_t size = advances.size();
    276   DCHECK_NE(size, 0u);
    277   cfi().AppendRawData(old_stream, 0u, advances[0].stream_pos);
    278   // Emit PC adjustments interleaved with the old CFI stream.
    279   size_t adjust_pos = 0u;
    280   size_t late_emit_pos = number_of_delayed_adjust_pcs;
    281   while (adjust_pos != number_of_delayed_adjust_pcs || late_emit_pos != size) {
    282     size_t adjusted_pc = (adjust_pos != number_of_delayed_adjust_pcs)
    283         ? GetAdjustedPosition(advances[adjust_pos].pc)
    284         : static_cast<size_t>(-1);
    285     size_t late_emit_pc = (late_emit_pos != size)
    286         ? advances[late_emit_pos].pc
    287         : static_cast<size_t>(-1);
    288     size_t advance_pc = std::min(adjusted_pc, late_emit_pc);
    289     DCHECK_NE(advance_pc, static_cast<size_t>(-1));
    290     size_t entry = (adjusted_pc <= late_emit_pc) ? adjust_pos : late_emit_pos;
    291     if (adjusted_pc <= late_emit_pc) {
    292       ++adjust_pos;
    293     } else {
    294       ++late_emit_pos;
    295     }
    296     cfi().AdvancePC(advance_pc);
    297     size_t end_pos = (entry + 1u == size) ? old_stream.size() : advances[entry + 1u].stream_pos;
    298     cfi().AppendRawData(old_stream, advances[entry].stream_pos, end_pos);
    299   }
    300 }
    301 
    302 void MipsAssembler::EmitBranches() {
    303   CHECK(!overwriting_);
    304   CHECK(!reordering_);
    305   // Now that everything has its final position in the buffer (the branches have
    306   // been promoted), adjust the target label PCs.
    307   for (size_t cnt = ds_fsm_target_pcs_.size(), i = 0; i < cnt; i++) {
    308     ds_fsm_target_pcs_[i] = GetAdjustedPosition(ds_fsm_target_pcs_[i]);
    309   }
    310   // Switch from appending instructions at the end of the buffer to overwriting
    311   // existing instructions (branch placeholders) in the buffer.
    312   overwriting_ = true;
    313   for (auto& branch : branches_) {
    314     EmitBranch(&branch);
    315   }
    316   overwriting_ = false;
    317 }
    318 
    319 void MipsAssembler::Emit(uint32_t value) {
    320   if (overwriting_) {
    321     // Branches to labels are emitted into their placeholders here.
    322     buffer_.Store<uint32_t>(overwrite_location_, value);
    323     overwrite_location_ += sizeof(uint32_t);
    324   } else {
    325     // Other instructions are simply appended at the end here.
    326     AssemblerBuffer::EnsureCapacity ensured(&buffer_);
    327     buffer_.Emit<uint32_t>(value);
    328   }
    329 }
    330 
    331 uint32_t MipsAssembler::EmitR(int opcode,
    332                               Register rs,
    333                               Register rt,
    334                               Register rd,
    335                               int shamt,
    336                               int funct) {
    337   CHECK_NE(rs, kNoRegister);
    338   CHECK_NE(rt, kNoRegister);
    339   CHECK_NE(rd, kNoRegister);
    340   uint32_t encoding = static_cast<uint32_t>(opcode) << kOpcodeShift |
    341                       static_cast<uint32_t>(rs) << kRsShift |
    342                       static_cast<uint32_t>(rt) << kRtShift |
    343                       static_cast<uint32_t>(rd) << kRdShift |
    344                       shamt << kShamtShift |
    345                       funct;
    346   Emit(encoding);
    347   return encoding;
    348 }
    349 
    350 uint32_t MipsAssembler::EmitI(int opcode, Register rs, Register rt, uint16_t imm) {
    351   CHECK_NE(rs, kNoRegister);
    352   CHECK_NE(rt, kNoRegister);
    353   uint32_t encoding = static_cast<uint32_t>(opcode) << kOpcodeShift |
    354                       static_cast<uint32_t>(rs) << kRsShift |
    355                       static_cast<uint32_t>(rt) << kRtShift |
    356                       imm;
    357   Emit(encoding);
    358   return encoding;
    359 }
    360 
    361 uint32_t MipsAssembler::EmitI21(int opcode, Register rs, uint32_t imm21) {
    362   CHECK_NE(rs, kNoRegister);
    363   CHECK(IsUint<21>(imm21)) << imm21;
    364   uint32_t encoding = static_cast<uint32_t>(opcode) << kOpcodeShift |
    365                       static_cast<uint32_t>(rs) << kRsShift |
    366                       imm21;
    367   Emit(encoding);
    368   return encoding;
    369 }
    370 
    371 uint32_t MipsAssembler::EmitI26(int opcode, uint32_t imm26) {
    372   CHECK(IsUint<26>(imm26)) << imm26;
    373   uint32_t encoding = static_cast<uint32_t>(opcode) << kOpcodeShift | imm26;
    374   Emit(encoding);
    375   return encoding;
    376 }
    377 
    378 uint32_t MipsAssembler::EmitFR(int opcode,
    379                                int fmt,
    380                                FRegister ft,
    381                                FRegister fs,
    382                                FRegister fd,
    383                                int funct) {
    384   CHECK_NE(ft, kNoFRegister);
    385   CHECK_NE(fs, kNoFRegister);
    386   CHECK_NE(fd, kNoFRegister);
    387   uint32_t encoding = static_cast<uint32_t>(opcode) << kOpcodeShift |
    388                       fmt << kFmtShift |
    389                       static_cast<uint32_t>(ft) << kFtShift |
    390                       static_cast<uint32_t>(fs) << kFsShift |
    391                       static_cast<uint32_t>(fd) << kFdShift |
    392                       funct;
    393   Emit(encoding);
    394   return encoding;
    395 }
    396 
    397 uint32_t MipsAssembler::EmitFI(int opcode, int fmt, FRegister ft, uint16_t imm) {
    398   CHECK_NE(ft, kNoFRegister);
    399   uint32_t encoding = static_cast<uint32_t>(opcode) << kOpcodeShift |
    400                       fmt << kFmtShift |
    401                       static_cast<uint32_t>(ft) << kFtShift |
    402                       imm;
    403   Emit(encoding);
    404   return encoding;
    405 }
    406 
    407 void MipsAssembler::Addu(Register rd, Register rs, Register rt) {
    408   DsFsmInstrRrr(EmitR(0, rs, rt, rd, 0, 0x21), rd, rs, rt);
    409 }
    410 
    411 void MipsAssembler::Addiu(Register rt, Register rs, uint16_t imm16) {
    412   DsFsmInstrRrr(EmitI(0x9, rs, rt, imm16), rt, rs, rs);
    413 }
    414 
    415 void MipsAssembler::Subu(Register rd, Register rs, Register rt) {
    416   DsFsmInstrRrr(EmitR(0, rs, rt, rd, 0, 0x23), rd, rs, rt);
    417 }
    418 
    419 void MipsAssembler::MultR2(Register rs, Register rt) {
    420   CHECK(!IsR6());
    421   DsFsmInstrRrr(EmitR(0, rs, rt, static_cast<Register>(0), 0, 0x18), ZERO, rs, rt);
    422 }
    423 
    424 void MipsAssembler::MultuR2(Register rs, Register rt) {
    425   CHECK(!IsR6());
    426   DsFsmInstrRrr(EmitR(0, rs, rt, static_cast<Register>(0), 0, 0x19), ZERO, rs, rt);
    427 }
    428 
    429 void MipsAssembler::DivR2(Register rs, Register rt) {
    430   CHECK(!IsR6());
    431   DsFsmInstrRrr(EmitR(0, rs, rt, static_cast<Register>(0), 0, 0x1a), ZERO, rs, rt);
    432 }
    433 
    434 void MipsAssembler::DivuR2(Register rs, Register rt) {
    435   CHECK(!IsR6());
    436   DsFsmInstrRrr(EmitR(0, rs, rt, static_cast<Register>(0), 0, 0x1b), ZERO, rs, rt);
    437 }
    438 
    439 void MipsAssembler::MulR2(Register rd, Register rs, Register rt) {
    440   CHECK(!IsR6());
    441   DsFsmInstrRrr(EmitR(0x1c, rs, rt, rd, 0, 2), rd, rs, rt);
    442 }
    443 
    444 void MipsAssembler::DivR2(Register rd, Register rs, Register rt) {
    445   CHECK(!IsR6());
    446   DivR2(rs, rt);
    447   Mflo(rd);
    448 }
    449 
    450 void MipsAssembler::ModR2(Register rd, Register rs, Register rt) {
    451   CHECK(!IsR6());
    452   DivR2(rs, rt);
    453   Mfhi(rd);
    454 }
    455 
    456 void MipsAssembler::DivuR2(Register rd, Register rs, Register rt) {
    457   CHECK(!IsR6());
    458   DivuR2(rs, rt);
    459   Mflo(rd);
    460 }
    461 
    462 void MipsAssembler::ModuR2(Register rd, Register rs, Register rt) {
    463   CHECK(!IsR6());
    464   DivuR2(rs, rt);
    465   Mfhi(rd);
    466 }
    467 
    468 void MipsAssembler::MulR6(Register rd, Register rs, Register rt) {
    469   CHECK(IsR6());
    470   DsFsmInstrRrr(EmitR(0, rs, rt, rd, 2, 0x18), rd, rs, rt);
    471 }
    472 
    473 void MipsAssembler::MuhR6(Register rd, Register rs, Register rt) {
    474   CHECK(IsR6());
    475   DsFsmInstrRrr(EmitR(0, rs, rt, rd, 3, 0x18), rd, rs, rt);
    476 }
    477 
    478 void MipsAssembler::MuhuR6(Register rd, Register rs, Register rt) {
    479   CHECK(IsR6());
    480   DsFsmInstrRrr(EmitR(0, rs, rt, rd, 3, 0x19), rd, rs, rt);
    481 }
    482 
    483 void MipsAssembler::DivR6(Register rd, Register rs, Register rt) {
    484   CHECK(IsR6());
    485   DsFsmInstrRrr(EmitR(0, rs, rt, rd, 2, 0x1a), rd, rs, rt);
    486 }
    487 
    488 void MipsAssembler::ModR6(Register rd, Register rs, Register rt) {
    489   CHECK(IsR6());
    490   DsFsmInstrRrr(EmitR(0, rs, rt, rd, 3, 0x1a), rd, rs, rt);
    491 }
    492 
    493 void MipsAssembler::DivuR6(Register rd, Register rs, Register rt) {
    494   CHECK(IsR6());
    495   DsFsmInstrRrr(EmitR(0, rs, rt, rd, 2, 0x1b), rd, rs, rt);
    496 }
    497 
    498 void MipsAssembler::ModuR6(Register rd, Register rs, Register rt) {
    499   CHECK(IsR6());
    500   DsFsmInstrRrr(EmitR(0, rs, rt, rd, 3, 0x1b), rd, rs, rt);
    501 }
    502 
    503 void MipsAssembler::And(Register rd, Register rs, Register rt) {
    504   DsFsmInstrRrr(EmitR(0, rs, rt, rd, 0, 0x24), rd, rs, rt);
    505 }
    506 
    507 void MipsAssembler::Andi(Register rt, Register rs, uint16_t imm16) {
    508   DsFsmInstrRrr(EmitI(0xc, rs, rt, imm16), rt, rs, rs);
    509 }
    510 
    511 void MipsAssembler::Or(Register rd, Register rs, Register rt) {
    512   DsFsmInstrRrr(EmitR(0, rs, rt, rd, 0, 0x25), rd, rs, rt);
    513 }
    514 
    515 void MipsAssembler::Ori(Register rt, Register rs, uint16_t imm16) {
    516   DsFsmInstrRrr(EmitI(0xd, rs, rt, imm16), rt, rs, rs);
    517 }
    518 
    519 void MipsAssembler::Xor(Register rd, Register rs, Register rt) {
    520   DsFsmInstrRrr(EmitR(0, rs, rt, rd, 0, 0x26), rd, rs, rt);
    521 }
    522 
    523 void MipsAssembler::Xori(Register rt, Register rs, uint16_t imm16) {
    524   DsFsmInstrRrr(EmitI(0xe, rs, rt, imm16), rt, rs, rs);
    525 }
    526 
    527 void MipsAssembler::Nor(Register rd, Register rs, Register rt) {
    528   DsFsmInstrRrr(EmitR(0, rs, rt, rd, 0, 0x27), rd, rs, rt);
    529 }
    530 
    531 void MipsAssembler::Movz(Register rd, Register rs, Register rt) {
    532   CHECK(!IsR6());
    533   DsFsmInstrRrrr(EmitR(0, rs, rt, rd, 0, 0x0A), rd, rs, rt);
    534 }
    535 
    536 void MipsAssembler::Movn(Register rd, Register rs, Register rt) {
    537   CHECK(!IsR6());
    538   DsFsmInstrRrrr(EmitR(0, rs, rt, rd, 0, 0x0B), rd, rs, rt);
    539 }
    540 
    541 void MipsAssembler::Seleqz(Register rd, Register rs, Register rt) {
    542   CHECK(IsR6());
    543   DsFsmInstrRrr(EmitR(0, rs, rt, rd, 0, 0x35), rd, rs, rt);
    544 }
    545 
    546 void MipsAssembler::Selnez(Register rd, Register rs, Register rt) {
    547   CHECK(IsR6());
    548   DsFsmInstrRrr(EmitR(0, rs, rt, rd, 0, 0x37), rd, rs, rt);
    549 }
    550 
    551 void MipsAssembler::ClzR6(Register rd, Register rs) {
    552   CHECK(IsR6());
    553   DsFsmInstrRrr(EmitR(0, rs, static_cast<Register>(0), rd, 0x01, 0x10), rd, rs, rs);
    554 }
    555 
    556 void MipsAssembler::ClzR2(Register rd, Register rs) {
    557   CHECK(!IsR6());
    558   DsFsmInstrRrr(EmitR(0x1C, rs, rd, rd, 0, 0x20), rd, rs, rs);
    559 }
    560 
    561 void MipsAssembler::CloR6(Register rd, Register rs) {
    562   CHECK(IsR6());
    563   DsFsmInstrRrr(EmitR(0, rs, static_cast<Register>(0), rd, 0x01, 0x11), rd, rs, rs);
    564 }
    565 
    566 void MipsAssembler::CloR2(Register rd, Register rs) {
    567   CHECK(!IsR6());
    568   DsFsmInstrRrr(EmitR(0x1C, rs, rd, rd, 0, 0x21), rd, rs, rs);
    569 }
    570 
    571 void MipsAssembler::Seb(Register rd, Register rt) {
    572   DsFsmInstrRrr(EmitR(0x1f, static_cast<Register>(0), rt, rd, 0x10, 0x20), rd, rt, rt);
    573 }
    574 
    575 void MipsAssembler::Seh(Register rd, Register rt) {
    576   DsFsmInstrRrr(EmitR(0x1f, static_cast<Register>(0), rt, rd, 0x18, 0x20), rd, rt, rt);
    577 }
    578 
    579 void MipsAssembler::Wsbh(Register rd, Register rt) {
    580   DsFsmInstrRrr(EmitR(0x1f, static_cast<Register>(0), rt, rd, 2, 0x20), rd, rt, rt);
    581 }
    582 
    583 void MipsAssembler::Bitswap(Register rd, Register rt) {
    584   CHECK(IsR6());
    585   DsFsmInstrRrr(EmitR(0x1f, static_cast<Register>(0), rt, rd, 0x0, 0x20), rd, rt, rt);
    586 }
    587 
    588 void MipsAssembler::Sll(Register rd, Register rt, int shamt) {
    589   CHECK(IsUint<5>(shamt)) << shamt;
    590   DsFsmInstrRrr(EmitR(0, static_cast<Register>(0), rt, rd, shamt, 0x00), rd, rt, rt);
    591 }
    592 
    593 void MipsAssembler::Srl(Register rd, Register rt, int shamt) {
    594   CHECK(IsUint<5>(shamt)) << shamt;
    595   DsFsmInstrRrr(EmitR(0, static_cast<Register>(0), rt, rd, shamt, 0x02), rd, rt, rt);
    596 }
    597 
    598 void MipsAssembler::Rotr(Register rd, Register rt, int shamt) {
    599   CHECK(IsUint<5>(shamt)) << shamt;
    600   DsFsmInstrRrr(EmitR(0, static_cast<Register>(1), rt, rd, shamt, 0x02), rd, rt, rt);
    601 }
    602 
    603 void MipsAssembler::Sra(Register rd, Register rt, int shamt) {
    604   CHECK(IsUint<5>(shamt)) << shamt;
    605   DsFsmInstrRrr(EmitR(0, static_cast<Register>(0), rt, rd, shamt, 0x03), rd, rt, rt);
    606 }
    607 
    608 void MipsAssembler::Sllv(Register rd, Register rt, Register rs) {
    609   DsFsmInstrRrr(EmitR(0, rs, rt, rd, 0, 0x04), rd, rs, rt);
    610 }
    611 
    612 void MipsAssembler::Srlv(Register rd, Register rt, Register rs) {
    613   DsFsmInstrRrr(EmitR(0, rs, rt, rd, 0, 0x06), rd, rs, rt);
    614 }
    615 
    616 void MipsAssembler::Rotrv(Register rd, Register rt, Register rs) {
    617   DsFsmInstrRrr(EmitR(0, rs, rt, rd, 1, 0x06), rd, rs, rt);
    618 }
    619 
    620 void MipsAssembler::Srav(Register rd, Register rt, Register rs) {
    621   DsFsmInstrRrr(EmitR(0, rs, rt, rd, 0, 0x07), rd, rs, rt);
    622 }
    623 
    624 void MipsAssembler::Ext(Register rd, Register rt, int pos, int size) {
    625   CHECK(IsUint<5>(pos)) << pos;
    626   CHECK(0 < size && size <= 32) << size;
    627   CHECK(0 < pos + size && pos + size <= 32) << pos << " + " << size;
    628   DsFsmInstrRrr(EmitR(0x1f, rt, rd, static_cast<Register>(size - 1), pos, 0x00), rd, rt, rt);
    629 }
    630 
    631 void MipsAssembler::Ins(Register rd, Register rt, int pos, int size) {
    632   CHECK(IsUint<5>(pos)) << pos;
    633   CHECK(0 < size && size <= 32) << size;
    634   CHECK(0 < pos + size && pos + size <= 32) << pos << " + " << size;
    635   DsFsmInstrRrr(EmitR(0x1f, rt, rd, static_cast<Register>(pos + size - 1), pos, 0x04), rd, rd, rt);
    636 }
    637 
    638 // TODO: This instruction is available in both R6 and MSA and it should be used when available.
    639 void MipsAssembler::Lsa(Register rd, Register rs, Register rt, int saPlusOne) {
    640   CHECK(IsR6());
    641   CHECK(1 <= saPlusOne && saPlusOne <= 4) << saPlusOne;
    642   int sa = saPlusOne - 1;
    643   DsFsmInstrRrr(EmitR(0x0, rs, rt, rd, sa, 0x05), rd, rs, rt);
    644 }
    645 
    646 void MipsAssembler::ShiftAndAdd(Register dst,
    647                                 Register src_idx,
    648                                 Register src_base,
    649                                 int shamt,
    650                                 Register tmp) {
    651   CHECK(0 <= shamt && shamt <= 4) << shamt;
    652   CHECK_NE(src_base, tmp);
    653   if (shamt == TIMES_1) {
    654     // Catch the special case where the shift amount is zero (0).
    655     Addu(dst, src_base, src_idx);
    656   } else if (IsR6()) {
    657     Lsa(dst, src_idx, src_base, shamt);
    658   } else {
    659     Sll(tmp, src_idx, shamt);
    660     Addu(dst, src_base, tmp);
    661   }
    662 }
    663 
    664 void MipsAssembler::Lb(Register rt, Register rs, uint16_t imm16) {
    665   DsFsmInstrRrr(EmitI(0x20, rs, rt, imm16), rt, rs, rs);
    666 }
    667 
    668 void MipsAssembler::Lh(Register rt, Register rs, uint16_t imm16) {
    669   DsFsmInstrRrr(EmitI(0x21, rs, rt, imm16), rt, rs, rs);
    670 }
    671 
    672 void MipsAssembler::Lw(Register rt, Register rs, uint16_t imm16) {
    673   DsFsmInstrRrr(EmitI(0x23, rs, rt, imm16), rt, rs, rs);
    674 }
    675 
    676 void MipsAssembler::Lwl(Register rt, Register rs, uint16_t imm16) {
    677   CHECK(!IsR6());
    678   DsFsmInstrRrr(EmitI(0x22, rs, rt, imm16), rt, rt, rs);
    679 }
    680 
    681 void MipsAssembler::Lwr(Register rt, Register rs, uint16_t imm16) {
    682   CHECK(!IsR6());
    683   DsFsmInstrRrr(EmitI(0x26, rs, rt, imm16), rt, rt, rs);
    684 }
    685 
    686 void MipsAssembler::Lbu(Register rt, Register rs, uint16_t imm16) {
    687   DsFsmInstrRrr(EmitI(0x24, rs, rt, imm16), rt, rs, rs);
    688 }
    689 
    690 void MipsAssembler::Lhu(Register rt, Register rs, uint16_t imm16) {
    691   DsFsmInstrRrr(EmitI(0x25, rs, rt, imm16), rt, rs, rs);
    692 }
    693 
    694 void MipsAssembler::Lwpc(Register rs, uint32_t imm19) {
    695   CHECK(IsR6());
    696   CHECK(IsUint<19>(imm19)) << imm19;
    697   DsFsmInstrNop(EmitI21(0x3B, rs, (0x01 << 19) | imm19));
    698 }
    699 
    700 void MipsAssembler::Lui(Register rt, uint16_t imm16) {
    701   DsFsmInstrRrr(EmitI(0xf, static_cast<Register>(0), rt, imm16), rt, ZERO, ZERO);
    702 }
    703 
    704 void MipsAssembler::Aui(Register rt, Register rs, uint16_t imm16) {
    705   CHECK(IsR6());
    706   DsFsmInstrRrr(EmitI(0xf, rs, rt, imm16), rt, rt, rs);
    707 }
    708 
    709 void MipsAssembler::Sync(uint32_t stype) {
    710   DsFsmInstrNop(EmitR(0, ZERO, ZERO, ZERO, stype & 0x1f, 0xf));
    711 }
    712 
    713 void MipsAssembler::Mfhi(Register rd) {
    714   CHECK(!IsR6());
    715   DsFsmInstrRrr(EmitR(0, ZERO, ZERO, rd, 0, 0x10), rd, ZERO, ZERO);
    716 }
    717 
    718 void MipsAssembler::Mflo(Register rd) {
    719   CHECK(!IsR6());
    720   DsFsmInstrRrr(EmitR(0, ZERO, ZERO, rd, 0, 0x12), rd, ZERO, ZERO);
    721 }
    722 
    723 void MipsAssembler::Sb(Register rt, Register rs, uint16_t imm16) {
    724   DsFsmInstrRrr(EmitI(0x28, rs, rt, imm16), ZERO, rt, rs);
    725 }
    726 
    727 void MipsAssembler::Sh(Register rt, Register rs, uint16_t imm16) {
    728   DsFsmInstrRrr(EmitI(0x29, rs, rt, imm16), ZERO, rt, rs);
    729 }
    730 
    731 void MipsAssembler::Sw(Register rt, Register rs, uint16_t imm16) {
    732   DsFsmInstrRrr(EmitI(0x2b, rs, rt, imm16), ZERO, rt, rs);
    733 }
    734 
    735 void MipsAssembler::Swl(Register rt, Register rs, uint16_t imm16) {
    736   CHECK(!IsR6());
    737   DsFsmInstrRrr(EmitI(0x2a, rs, rt, imm16), ZERO, rt, rs);
    738 }
    739 
    740 void MipsAssembler::Swr(Register rt, Register rs, uint16_t imm16) {
    741   CHECK(!IsR6());
    742   DsFsmInstrRrr(EmitI(0x2e, rs, rt, imm16), ZERO, rt, rs);
    743 }
    744 
    745 void MipsAssembler::LlR2(Register rt, Register base, int16_t imm16) {
    746   CHECK(!IsR6());
    747   DsFsmInstrRrr(EmitI(0x30, base, rt, imm16), rt, base, base);
    748 }
    749 
    750 void MipsAssembler::ScR2(Register rt, Register base, int16_t imm16) {
    751   CHECK(!IsR6());
    752   DsFsmInstrRrr(EmitI(0x38, base, rt, imm16), rt, rt, base);
    753 }
    754 
    755 void MipsAssembler::LlR6(Register rt, Register base, int16_t imm9) {
    756   CHECK(IsR6());
    757   CHECK(IsInt<9>(imm9));
    758   DsFsmInstrRrr(EmitI(0x1f, base, rt, ((imm9 & 0x1ff) << 7) | 0x36), rt, base, base);
    759 }
    760 
    761 void MipsAssembler::ScR6(Register rt, Register base, int16_t imm9) {
    762   CHECK(IsR6());
    763   CHECK(IsInt<9>(imm9));
    764   DsFsmInstrRrr(EmitI(0x1f, base, rt, ((imm9 & 0x1ff) << 7) | 0x26), rt, rt, base);
    765 }
    766 
    767 void MipsAssembler::Slt(Register rd, Register rs, Register rt) {
    768   DsFsmInstrRrr(EmitR(0, rs, rt, rd, 0, 0x2a), rd, rs, rt);
    769 }
    770 
    771 void MipsAssembler::Sltu(Register rd, Register rs, Register rt) {
    772   DsFsmInstrRrr(EmitR(0, rs, rt, rd, 0, 0x2b), rd, rs, rt);
    773 }
    774 
    775 void MipsAssembler::Slti(Register rt, Register rs, uint16_t imm16) {
    776   DsFsmInstrRrr(EmitI(0xa, rs, rt, imm16), rt, rs, rs);
    777 }
    778 
    779 void MipsAssembler::Sltiu(Register rt, Register rs, uint16_t imm16) {
    780   DsFsmInstrRrr(EmitI(0xb, rs, rt, imm16), rt, rs, rs);
    781 }
    782 
    783 void MipsAssembler::B(uint16_t imm16) {
    784   DsFsmInstrNop(EmitI(0x4, static_cast<Register>(0), static_cast<Register>(0), imm16));
    785 }
    786 
    787 void MipsAssembler::Bal(uint16_t imm16) {
    788   DsFsmInstrNop(EmitI(0x1, static_cast<Register>(0), static_cast<Register>(0x11), imm16));
    789 }
    790 
    791 void MipsAssembler::Beq(Register rs, Register rt, uint16_t imm16) {
    792   DsFsmInstrNop(EmitI(0x4, rs, rt, imm16));
    793 }
    794 
    795 void MipsAssembler::Bne(Register rs, Register rt, uint16_t imm16) {
    796   DsFsmInstrNop(EmitI(0x5, rs, rt, imm16));
    797 }
    798 
    799 void MipsAssembler::Beqz(Register rt, uint16_t imm16) {
    800   Beq(ZERO, rt, imm16);
    801 }
    802 
    803 void MipsAssembler::Bnez(Register rt, uint16_t imm16) {
    804   Bne(ZERO, rt, imm16);
    805 }
    806 
    807 void MipsAssembler::Bltz(Register rt, uint16_t imm16) {
    808   DsFsmInstrNop(EmitI(0x1, rt, static_cast<Register>(0), imm16));
    809 }
    810 
    811 void MipsAssembler::Bgez(Register rt, uint16_t imm16) {
    812   DsFsmInstrNop(EmitI(0x1, rt, static_cast<Register>(0x1), imm16));
    813 }
    814 
    815 void MipsAssembler::Blez(Register rt, uint16_t imm16) {
    816   DsFsmInstrNop(EmitI(0x6, rt, static_cast<Register>(0), imm16));
    817 }
    818 
    819 void MipsAssembler::Bgtz(Register rt, uint16_t imm16) {
    820   DsFsmInstrNop(EmitI(0x7, rt, static_cast<Register>(0), imm16));
    821 }
    822 
    823 void MipsAssembler::Bc1f(uint16_t imm16) {
    824   Bc1f(0, imm16);
    825 }
    826 
    827 void MipsAssembler::Bc1f(int cc, uint16_t imm16) {
    828   CHECK(!IsR6());
    829   CHECK(IsUint<3>(cc)) << cc;
    830   DsFsmInstrNop(EmitI(0x11, static_cast<Register>(0x8), static_cast<Register>(cc << 2), imm16));
    831 }
    832 
    833 void MipsAssembler::Bc1t(uint16_t imm16) {
    834   Bc1t(0, imm16);
    835 }
    836 
    837 void MipsAssembler::Bc1t(int cc, uint16_t imm16) {
    838   CHECK(!IsR6());
    839   CHECK(IsUint<3>(cc)) << cc;
    840   DsFsmInstrNop(EmitI(0x11,
    841                       static_cast<Register>(0x8),
    842                       static_cast<Register>((cc << 2) | 1),
    843                       imm16));
    844 }
    845 
    846 void MipsAssembler::J(uint32_t addr26) {
    847   DsFsmInstrNop(EmitI26(0x2, addr26));
    848 }
    849 
    850 void MipsAssembler::Jal(uint32_t addr26) {
    851   DsFsmInstrNop(EmitI26(0x3, addr26));
    852 }
    853 
    854 void MipsAssembler::Jalr(Register rd, Register rs) {
    855   uint32_t last_instruction = delay_slot_.instruction_;
    856   bool exchange = (last_instruction != 0 &&
    857       (delay_slot_.gpr_outs_mask_ & (1u << rs)) == 0 &&
    858       ((delay_slot_.gpr_ins_mask_ | delay_slot_.gpr_outs_mask_) & (1u << rd)) == 0);
    859   if (exchange) {
    860     // The last instruction cannot be used in a different delay slot,
    861     // do not commit the label before it (if any).
    862     DsFsmDropLabel();
    863   }
    864   DsFsmInstrNop(EmitR(0, rs, static_cast<Register>(0), rd, 0, 0x09));
    865   if (exchange) {
    866     // Exchange the last two instructions in the assembler buffer.
    867     size_t size = buffer_.Size();
    868     CHECK_GE(size, 2 * sizeof(uint32_t));
    869     size_t pos1 = size - 2 * sizeof(uint32_t);
    870     size_t pos2 = size - sizeof(uint32_t);
    871     uint32_t instr1 = buffer_.Load<uint32_t>(pos1);
    872     uint32_t instr2 = buffer_.Load<uint32_t>(pos2);
    873     CHECK_EQ(instr1, last_instruction);
    874     buffer_.Store<uint32_t>(pos1, instr2);
    875     buffer_.Store<uint32_t>(pos2, instr1);
    876   } else if (reordering_) {
    877     Nop();
    878   }
    879 }
    880 
    881 void MipsAssembler::Jalr(Register rs) {
    882   Jalr(RA, rs);
    883 }
    884 
    885 void MipsAssembler::Jr(Register rs) {
    886   Jalr(ZERO, rs);
    887 }
    888 
    889 void MipsAssembler::Nal() {
    890   DsFsmInstrNop(EmitI(0x1, static_cast<Register>(0), static_cast<Register>(0x10), 0));
    891 }
    892 
    893 void MipsAssembler::Auipc(Register rs, uint16_t imm16) {
    894   CHECK(IsR6());
    895   DsFsmInstrNop(EmitI(0x3B, rs, static_cast<Register>(0x1E), imm16));
    896 }
    897 
    898 void MipsAssembler::Addiupc(Register rs, uint32_t imm19) {
    899   CHECK(IsR6());
    900   CHECK(IsUint<19>(imm19)) << imm19;
    901   DsFsmInstrNop(EmitI21(0x3B, rs, imm19));
    902 }
    903 
    904 void MipsAssembler::Bc(uint32_t imm26) {
    905   CHECK(IsR6());
    906   DsFsmInstrNop(EmitI26(0x32, imm26));
    907 }
    908 
    909 void MipsAssembler::Balc(uint32_t imm26) {
    910   CHECK(IsR6());
    911   DsFsmInstrNop(EmitI26(0x3A, imm26));
    912 }
    913 
    914 void MipsAssembler::Jic(Register rt, uint16_t imm16) {
    915   CHECK(IsR6());
    916   DsFsmInstrNop(EmitI(0x36, static_cast<Register>(0), rt, imm16));
    917 }
    918 
    919 void MipsAssembler::Jialc(Register rt, uint16_t imm16) {
    920   CHECK(IsR6());
    921   DsFsmInstrNop(EmitI(0x3E, static_cast<Register>(0), rt, imm16));
    922 }
    923 
    924 void MipsAssembler::Bltc(Register rs, Register rt, uint16_t imm16) {
    925   CHECK(IsR6());
    926   CHECK_NE(rs, ZERO);
    927   CHECK_NE(rt, ZERO);
    928   CHECK_NE(rs, rt);
    929   DsFsmInstrNop(EmitI(0x17, rs, rt, imm16));
    930 }
    931 
    932 void MipsAssembler::Bltzc(Register rt, uint16_t imm16) {
    933   CHECK(IsR6());
    934   CHECK_NE(rt, ZERO);
    935   DsFsmInstrNop(EmitI(0x17, rt, rt, imm16));
    936 }
    937 
    938 void MipsAssembler::Bgtzc(Register rt, uint16_t imm16) {
    939   CHECK(IsR6());
    940   CHECK_NE(rt, ZERO);
    941   DsFsmInstrNop(EmitI(0x17, static_cast<Register>(0), rt, imm16));
    942 }
    943 
    944 void MipsAssembler::Bgec(Register rs, Register rt, uint16_t imm16) {
    945   CHECK(IsR6());
    946   CHECK_NE(rs, ZERO);
    947   CHECK_NE(rt, ZERO);
    948   CHECK_NE(rs, rt);
    949   DsFsmInstrNop(EmitI(0x16, rs, rt, imm16));
    950 }
    951 
    952 void MipsAssembler::Bgezc(Register rt, uint16_t imm16) {
    953   CHECK(IsR6());
    954   CHECK_NE(rt, ZERO);
    955   DsFsmInstrNop(EmitI(0x16, rt, rt, imm16));
    956 }
    957 
    958 void MipsAssembler::Blezc(Register rt, uint16_t imm16) {
    959   CHECK(IsR6());
    960   CHECK_NE(rt, ZERO);
    961   DsFsmInstrNop(EmitI(0x16, static_cast<Register>(0), rt, imm16));
    962 }
    963 
    964 void MipsAssembler::Bltuc(Register rs, Register rt, uint16_t imm16) {
    965   CHECK(IsR6());
    966   CHECK_NE(rs, ZERO);
    967   CHECK_NE(rt, ZERO);
    968   CHECK_NE(rs, rt);
    969   DsFsmInstrNop(EmitI(0x7, rs, rt, imm16));
    970 }
    971 
    972 void MipsAssembler::Bgeuc(Register rs, Register rt, uint16_t imm16) {
    973   CHECK(IsR6());
    974   CHECK_NE(rs, ZERO);
    975   CHECK_NE(rt, ZERO);
    976   CHECK_NE(rs, rt);
    977   DsFsmInstrNop(EmitI(0x6, rs, rt, imm16));
    978 }
    979 
    980 void MipsAssembler::Beqc(Register rs, Register rt, uint16_t imm16) {
    981   CHECK(IsR6());
    982   CHECK_NE(rs, ZERO);
    983   CHECK_NE(rt, ZERO);
    984   CHECK_NE(rs, rt);
    985   DsFsmInstrNop(EmitI(0x8, std::min(rs, rt), std::max(rs, rt), imm16));
    986 }
    987 
    988 void MipsAssembler::Bnec(Register rs, Register rt, uint16_t imm16) {
    989   CHECK(IsR6());
    990   CHECK_NE(rs, ZERO);
    991   CHECK_NE(rt, ZERO);
    992   CHECK_NE(rs, rt);
    993   DsFsmInstrNop(EmitI(0x18, std::min(rs, rt), std::max(rs, rt), imm16));
    994 }
    995 
    996 void MipsAssembler::Beqzc(Register rs, uint32_t imm21) {
    997   CHECK(IsR6());
    998   CHECK_NE(rs, ZERO);
    999   DsFsmInstrNop(EmitI21(0x36, rs, imm21));
   1000 }
   1001 
   1002 void MipsAssembler::Bnezc(Register rs, uint32_t imm21) {
   1003   CHECK(IsR6());
   1004   CHECK_NE(rs, ZERO);
   1005   DsFsmInstrNop(EmitI21(0x3E, rs, imm21));
   1006 }
   1007 
   1008 void MipsAssembler::Bc1eqz(FRegister ft, uint16_t imm16) {
   1009   CHECK(IsR6());
   1010   DsFsmInstrNop(EmitFI(0x11, 0x9, ft, imm16));
   1011 }
   1012 
   1013 void MipsAssembler::Bc1nez(FRegister ft, uint16_t imm16) {
   1014   CHECK(IsR6());
   1015   DsFsmInstrNop(EmitFI(0x11, 0xD, ft, imm16));
   1016 }
   1017 
   1018 void MipsAssembler::EmitBcondR2(BranchCondition cond, Register rs, Register rt, uint16_t imm16) {
   1019   switch (cond) {
   1020     case kCondLTZ:
   1021       CHECK_EQ(rt, ZERO);
   1022       Bltz(rs, imm16);
   1023       break;
   1024     case kCondGEZ:
   1025       CHECK_EQ(rt, ZERO);
   1026       Bgez(rs, imm16);
   1027       break;
   1028     case kCondLEZ:
   1029       CHECK_EQ(rt, ZERO);
   1030       Blez(rs, imm16);
   1031       break;
   1032     case kCondGTZ:
   1033       CHECK_EQ(rt, ZERO);
   1034       Bgtz(rs, imm16);
   1035       break;
   1036     case kCondEQ:
   1037       Beq(rs, rt, imm16);
   1038       break;
   1039     case kCondNE:
   1040       Bne(rs, rt, imm16);
   1041       break;
   1042     case kCondEQZ:
   1043       CHECK_EQ(rt, ZERO);
   1044       Beqz(rs, imm16);
   1045       break;
   1046     case kCondNEZ:
   1047       CHECK_EQ(rt, ZERO);
   1048       Bnez(rs, imm16);
   1049       break;
   1050     case kCondF:
   1051       CHECK_EQ(rt, ZERO);
   1052       Bc1f(static_cast<int>(rs), imm16);
   1053       break;
   1054     case kCondT:
   1055       CHECK_EQ(rt, ZERO);
   1056       Bc1t(static_cast<int>(rs), imm16);
   1057       break;
   1058     case kCondLT:
   1059     case kCondGE:
   1060     case kCondLE:
   1061     case kCondGT:
   1062     case kCondLTU:
   1063     case kCondGEU:
   1064     case kUncond:
   1065       // We don't support synthetic R2 branches (preceded with slt[u]) at this level
   1066       // (R2 doesn't have branches to compare 2 registers using <, <=, >=, >).
   1067       LOG(FATAL) << "Unexpected branch condition " << cond;
   1068       UNREACHABLE();
   1069   }
   1070 }
   1071 
   1072 void MipsAssembler::EmitBcondR6(BranchCondition cond, Register rs, Register rt, uint32_t imm16_21) {
   1073   switch (cond) {
   1074     case kCondLT:
   1075       Bltc(rs, rt, imm16_21);
   1076       break;
   1077     case kCondGE:
   1078       Bgec(rs, rt, imm16_21);
   1079       break;
   1080     case kCondLE:
   1081       Bgec(rt, rs, imm16_21);
   1082       break;
   1083     case kCondGT:
   1084       Bltc(rt, rs, imm16_21);
   1085       break;
   1086     case kCondLTZ:
   1087       CHECK_EQ(rt, ZERO);
   1088       Bltzc(rs, imm16_21);
   1089       break;
   1090     case kCondGEZ:
   1091       CHECK_EQ(rt, ZERO);
   1092       Bgezc(rs, imm16_21);
   1093       break;
   1094     case kCondLEZ:
   1095       CHECK_EQ(rt, ZERO);
   1096       Blezc(rs, imm16_21);
   1097       break;
   1098     case kCondGTZ:
   1099       CHECK_EQ(rt, ZERO);
   1100       Bgtzc(rs, imm16_21);
   1101       break;
   1102     case kCondEQ:
   1103       Beqc(rs, rt, imm16_21);
   1104       break;
   1105     case kCondNE:
   1106       Bnec(rs, rt, imm16_21);
   1107       break;
   1108     case kCondEQZ:
   1109       CHECK_EQ(rt, ZERO);
   1110       Beqzc(rs, imm16_21);
   1111       break;
   1112     case kCondNEZ:
   1113       CHECK_EQ(rt, ZERO);
   1114       Bnezc(rs, imm16_21);
   1115       break;
   1116     case kCondLTU:
   1117       Bltuc(rs, rt, imm16_21);
   1118       break;
   1119     case kCondGEU:
   1120       Bgeuc(rs, rt, imm16_21);
   1121       break;
   1122     case kCondF:
   1123       CHECK_EQ(rt, ZERO);
   1124       Bc1eqz(static_cast<FRegister>(rs), imm16_21);
   1125       break;
   1126     case kCondT:
   1127       CHECK_EQ(rt, ZERO);
   1128       Bc1nez(static_cast<FRegister>(rs), imm16_21);
   1129       break;
   1130     case kUncond:
   1131       LOG(FATAL) << "Unexpected branch condition " << cond;
   1132       UNREACHABLE();
   1133   }
   1134 }
   1135 
   1136 void MipsAssembler::AddS(FRegister fd, FRegister fs, FRegister ft) {
   1137   DsFsmInstrFff(EmitFR(0x11, 0x10, ft, fs, fd, 0x0), fd, fs, ft);
   1138 }
   1139 
   1140 void MipsAssembler::SubS(FRegister fd, FRegister fs, FRegister ft) {
   1141   DsFsmInstrFff(EmitFR(0x11, 0x10, ft, fs, fd, 0x1), fd, fs, ft);
   1142 }
   1143 
   1144 void MipsAssembler::MulS(FRegister fd, FRegister fs, FRegister ft) {
   1145   DsFsmInstrFff(EmitFR(0x11, 0x10, ft, fs, fd, 0x2), fd, fs, ft);
   1146 }
   1147 
   1148 void MipsAssembler::DivS(FRegister fd, FRegister fs, FRegister ft) {
   1149   DsFsmInstrFff(EmitFR(0x11, 0x10, ft, fs, fd, 0x3), fd, fs, ft);
   1150 }
   1151 
   1152 void MipsAssembler::AddD(FRegister fd, FRegister fs, FRegister ft) {
   1153   DsFsmInstrFff(EmitFR(0x11, 0x11, ft, fs, fd, 0x0), fd, fs, ft);
   1154 }
   1155 
   1156 void MipsAssembler::SubD(FRegister fd, FRegister fs, FRegister ft) {
   1157   DsFsmInstrFff(EmitFR(0x11, 0x11, ft, fs, fd, 0x1), fd, fs, ft);
   1158 }
   1159 
   1160 void MipsAssembler::MulD(FRegister fd, FRegister fs, FRegister ft) {
   1161   DsFsmInstrFff(EmitFR(0x11, 0x11, ft, fs, fd, 0x2), fd, fs, ft);
   1162 }
   1163 
   1164 void MipsAssembler::DivD(FRegister fd, FRegister fs, FRegister ft) {
   1165   DsFsmInstrFff(EmitFR(0x11, 0x11, ft, fs, fd, 0x3), fd, fs, ft);
   1166 }
   1167 
   1168 void MipsAssembler::SqrtS(FRegister fd, FRegister fs) {
   1169   DsFsmInstrFff(EmitFR(0x11, 0x10, static_cast<FRegister>(0), fs, fd, 0x4), fd, fs, fs);
   1170 }
   1171 
   1172 void MipsAssembler::SqrtD(FRegister fd, FRegister fs) {
   1173   DsFsmInstrFff(EmitFR(0x11, 0x11, static_cast<FRegister>(0), fs, fd, 0x4), fd, fs, fs);
   1174 }
   1175 
   1176 void MipsAssembler::AbsS(FRegister fd, FRegister fs) {
   1177   DsFsmInstrFff(EmitFR(0x11, 0x10, static_cast<FRegister>(0), fs, fd, 0x5), fd, fs, fs);
   1178 }
   1179 
   1180 void MipsAssembler::AbsD(FRegister fd, FRegister fs) {
   1181   DsFsmInstrFff(EmitFR(0x11, 0x11, static_cast<FRegister>(0), fs, fd, 0x5), fd, fs, fs);
   1182 }
   1183 
   1184 void MipsAssembler::MovS(FRegister fd, FRegister fs) {
   1185   DsFsmInstrFff(EmitFR(0x11, 0x10, static_cast<FRegister>(0), fs, fd, 0x6), fd, fs, fs);
   1186 }
   1187 
   1188 void MipsAssembler::MovD(FRegister fd, FRegister fs) {
   1189   DsFsmInstrFff(EmitFR(0x11, 0x11, static_cast<FRegister>(0), fs, fd, 0x6), fd, fs, fs);
   1190 }
   1191 
   1192 void MipsAssembler::NegS(FRegister fd, FRegister fs) {
   1193   DsFsmInstrFff(EmitFR(0x11, 0x10, static_cast<FRegister>(0), fs, fd, 0x7), fd, fs, fs);
   1194 }
   1195 
   1196 void MipsAssembler::NegD(FRegister fd, FRegister fs) {
   1197   DsFsmInstrFff(EmitFR(0x11, 0x11, static_cast<FRegister>(0), fs, fd, 0x7), fd, fs, fs);
   1198 }
   1199 
   1200 void MipsAssembler::CunS(FRegister fs, FRegister ft) {
   1201   CunS(0, fs, ft);
   1202 }
   1203 
   1204 void MipsAssembler::CunS(int cc, FRegister fs, FRegister ft) {
   1205   CHECK(!IsR6());
   1206   CHECK(IsUint<3>(cc)) << cc;
   1207   DsFsmInstrCff(EmitFR(0x11, 0x10, ft, fs, static_cast<FRegister>(cc << 2), 0x31), cc, fs, ft);
   1208 }
   1209 
   1210 void MipsAssembler::CeqS(FRegister fs, FRegister ft) {
   1211   CeqS(0, fs, ft);
   1212 }
   1213 
   1214 void MipsAssembler::CeqS(int cc, FRegister fs, FRegister ft) {
   1215   CHECK(!IsR6());
   1216   CHECK(IsUint<3>(cc)) << cc;
   1217   DsFsmInstrCff(EmitFR(0x11, 0x10, ft, fs, static_cast<FRegister>(cc << 2), 0x32), cc, fs, ft);
   1218 }
   1219 
   1220 void MipsAssembler::CueqS(FRegister fs, FRegister ft) {
   1221   CueqS(0, fs, ft);
   1222 }
   1223 
   1224 void MipsAssembler::CueqS(int cc, FRegister fs, FRegister ft) {
   1225   CHECK(!IsR6());
   1226   CHECK(IsUint<3>(cc)) << cc;
   1227   DsFsmInstrCff(EmitFR(0x11, 0x10, ft, fs, static_cast<FRegister>(cc << 2), 0x33), cc, fs, ft);
   1228 }
   1229 
   1230 void MipsAssembler::ColtS(FRegister fs, FRegister ft) {
   1231   ColtS(0, fs, ft);
   1232 }
   1233 
   1234 void MipsAssembler::ColtS(int cc, FRegister fs, FRegister ft) {
   1235   CHECK(!IsR6());
   1236   CHECK(IsUint<3>(cc)) << cc;
   1237   DsFsmInstrCff(EmitFR(0x11, 0x10, ft, fs, static_cast<FRegister>(cc << 2), 0x34), cc, fs, ft);
   1238 }
   1239 
   1240 void MipsAssembler::CultS(FRegister fs, FRegister ft) {
   1241   CultS(0, fs, ft);
   1242 }
   1243 
   1244 void MipsAssembler::CultS(int cc, FRegister fs, FRegister ft) {
   1245   CHECK(!IsR6());
   1246   CHECK(IsUint<3>(cc)) << cc;
   1247   DsFsmInstrCff(EmitFR(0x11, 0x10, ft, fs, static_cast<FRegister>(cc << 2), 0x35), cc, fs, ft);
   1248 }
   1249 
   1250 void MipsAssembler::ColeS(FRegister fs, FRegister ft) {
   1251   ColeS(0, fs, ft);
   1252 }
   1253 
   1254 void MipsAssembler::ColeS(int cc, FRegister fs, FRegister ft) {
   1255   CHECK(!IsR6());
   1256   CHECK(IsUint<3>(cc)) << cc;
   1257   DsFsmInstrCff(EmitFR(0x11, 0x10, ft, fs, static_cast<FRegister>(cc << 2), 0x36), cc, fs, ft);
   1258 }
   1259 
   1260 void MipsAssembler::CuleS(FRegister fs, FRegister ft) {
   1261   CuleS(0, fs, ft);
   1262 }
   1263 
   1264 void MipsAssembler::CuleS(int cc, FRegister fs, FRegister ft) {
   1265   CHECK(!IsR6());
   1266   CHECK(IsUint<3>(cc)) << cc;
   1267   DsFsmInstrCff(EmitFR(0x11, 0x10, ft, fs, static_cast<FRegister>(cc << 2), 0x37), cc, fs, ft);
   1268 }
   1269 
   1270 void MipsAssembler::CunD(FRegister fs, FRegister ft) {
   1271   CunD(0, fs, ft);
   1272 }
   1273 
   1274 void MipsAssembler::CunD(int cc, FRegister fs, FRegister ft) {
   1275   CHECK(!IsR6());
   1276   CHECK(IsUint<3>(cc)) << cc;
   1277   DsFsmInstrCff(EmitFR(0x11, 0x11, ft, fs, static_cast<FRegister>(cc << 2), 0x31), cc, fs, ft);
   1278 }
   1279 
   1280 void MipsAssembler::CeqD(FRegister fs, FRegister ft) {
   1281   CeqD(0, fs, ft);
   1282 }
   1283 
   1284 void MipsAssembler::CeqD(int cc, FRegister fs, FRegister ft) {
   1285   CHECK(!IsR6());
   1286   CHECK(IsUint<3>(cc)) << cc;
   1287   DsFsmInstrCff(EmitFR(0x11, 0x11, ft, fs, static_cast<FRegister>(cc << 2), 0x32), cc, fs, ft);
   1288 }
   1289 
   1290 void MipsAssembler::CueqD(FRegister fs, FRegister ft) {
   1291   CueqD(0, fs, ft);
   1292 }
   1293 
   1294 void MipsAssembler::CueqD(int cc, FRegister fs, FRegister ft) {
   1295   CHECK(!IsR6());
   1296   CHECK(IsUint<3>(cc)) << cc;
   1297   DsFsmInstrCff(EmitFR(0x11, 0x11, ft, fs, static_cast<FRegister>(cc << 2), 0x33), cc, fs, ft);
   1298 }
   1299 
   1300 void MipsAssembler::ColtD(FRegister fs, FRegister ft) {
   1301   ColtD(0, fs, ft);
   1302 }
   1303 
   1304 void MipsAssembler::ColtD(int cc, FRegister fs, FRegister ft) {
   1305   CHECK(!IsR6());
   1306   CHECK(IsUint<3>(cc)) << cc;
   1307   DsFsmInstrCff(EmitFR(0x11, 0x11, ft, fs, static_cast<FRegister>(cc << 2), 0x34), cc, fs, ft);
   1308 }
   1309 
   1310 void MipsAssembler::CultD(FRegister fs, FRegister ft) {
   1311   CultD(0, fs, ft);
   1312 }
   1313 
   1314 void MipsAssembler::CultD(int cc, FRegister fs, FRegister ft) {
   1315   CHECK(!IsR6());
   1316   CHECK(IsUint<3>(cc)) << cc;
   1317   DsFsmInstrCff(EmitFR(0x11, 0x11, ft, fs, static_cast<FRegister>(cc << 2), 0x35), cc, fs, ft);
   1318 }
   1319 
   1320 void MipsAssembler::ColeD(FRegister fs, FRegister ft) {
   1321   ColeD(0, fs, ft);
   1322 }
   1323 
   1324 void MipsAssembler::ColeD(int cc, FRegister fs, FRegister ft) {
   1325   CHECK(!IsR6());
   1326   CHECK(IsUint<3>(cc)) << cc;
   1327   DsFsmInstrCff(EmitFR(0x11, 0x11, ft, fs, static_cast<FRegister>(cc << 2), 0x36), cc, fs, ft);
   1328 }
   1329 
   1330 void MipsAssembler::CuleD(FRegister fs, FRegister ft) {
   1331   CuleD(0, fs, ft);
   1332 }
   1333 
   1334 void MipsAssembler::CuleD(int cc, FRegister fs, FRegister ft) {
   1335   CHECK(!IsR6());
   1336   CHECK(IsUint<3>(cc)) << cc;
   1337   DsFsmInstrCff(EmitFR(0x11, 0x11, ft, fs, static_cast<FRegister>(cc << 2), 0x37), cc, fs, ft);
   1338 }
   1339 
   1340 void MipsAssembler::CmpUnS(FRegister fd, FRegister fs, FRegister ft) {
   1341   CHECK(IsR6());
   1342   DsFsmInstrFff(EmitFR(0x11, 0x14, ft, fs, fd, 0x01), fd, fs, ft);
   1343 }
   1344 
   1345 void MipsAssembler::CmpEqS(FRegister fd, FRegister fs, FRegister ft) {
   1346   CHECK(IsR6());
   1347   DsFsmInstrFff(EmitFR(0x11, 0x14, ft, fs, fd, 0x02), fd, fs, ft);
   1348 }
   1349 
   1350 void MipsAssembler::CmpUeqS(FRegister fd, FRegister fs, FRegister ft) {
   1351   CHECK(IsR6());
   1352   DsFsmInstrFff(EmitFR(0x11, 0x14, ft, fs, fd, 0x03), fd, fs, ft);
   1353 }
   1354 
   1355 void MipsAssembler::CmpLtS(FRegister fd, FRegister fs, FRegister ft) {
   1356   CHECK(IsR6());
   1357   DsFsmInstrFff(EmitFR(0x11, 0x14, ft, fs, fd, 0x04), fd, fs, ft);
   1358 }
   1359 
   1360 void MipsAssembler::CmpUltS(FRegister fd, FRegister fs, FRegister ft) {
   1361   CHECK(IsR6());
   1362   DsFsmInstrFff(EmitFR(0x11, 0x14, ft, fs, fd, 0x05), fd, fs, ft);
   1363 }
   1364 
   1365 void MipsAssembler::CmpLeS(FRegister fd, FRegister fs, FRegister ft) {
   1366   CHECK(IsR6());
   1367   DsFsmInstrFff(EmitFR(0x11, 0x14, ft, fs, fd, 0x06), fd, fs, ft);
   1368 }
   1369 
   1370 void MipsAssembler::CmpUleS(FRegister fd, FRegister fs, FRegister ft) {
   1371   CHECK(IsR6());
   1372   DsFsmInstrFff(EmitFR(0x11, 0x14, ft, fs, fd, 0x07), fd, fs, ft);
   1373 }
   1374 
   1375 void MipsAssembler::CmpOrS(FRegister fd, FRegister fs, FRegister ft) {
   1376   CHECK(IsR6());
   1377   DsFsmInstrFff(EmitFR(0x11, 0x14, ft, fs, fd, 0x11), fd, fs, ft);
   1378 }
   1379 
   1380 void MipsAssembler::CmpUneS(FRegister fd, FRegister fs, FRegister ft) {
   1381   CHECK(IsR6());
   1382   DsFsmInstrFff(EmitFR(0x11, 0x14, ft, fs, fd, 0x12), fd, fs, ft);
   1383 }
   1384 
   1385 void MipsAssembler::CmpNeS(FRegister fd, FRegister fs, FRegister ft) {
   1386   CHECK(IsR6());
   1387   DsFsmInstrFff(EmitFR(0x11, 0x14, ft, fs, fd, 0x13), fd, fs, ft);
   1388 }
   1389 
   1390 void MipsAssembler::CmpUnD(FRegister fd, FRegister fs, FRegister ft) {
   1391   CHECK(IsR6());
   1392   DsFsmInstrFff(EmitFR(0x11, 0x15, ft, fs, fd, 0x01), fd, fs, ft);
   1393 }
   1394 
   1395 void MipsAssembler::CmpEqD(FRegister fd, FRegister fs, FRegister ft) {
   1396   CHECK(IsR6());
   1397   DsFsmInstrFff(EmitFR(0x11, 0x15, ft, fs, fd, 0x02), fd, fs, ft);
   1398 }
   1399 
   1400 void MipsAssembler::CmpUeqD(FRegister fd, FRegister fs, FRegister ft) {
   1401   CHECK(IsR6());
   1402   DsFsmInstrFff(EmitFR(0x11, 0x15, ft, fs, fd, 0x03), fd, fs, ft);
   1403 }
   1404 
   1405 void MipsAssembler::CmpLtD(FRegister fd, FRegister fs, FRegister ft) {
   1406   CHECK(IsR6());
   1407   DsFsmInstrFff(EmitFR(0x11, 0x15, ft, fs, fd, 0x04), fd, fs, ft);
   1408 }
   1409 
   1410 void MipsAssembler::CmpUltD(FRegister fd, FRegister fs, FRegister ft) {
   1411   CHECK(IsR6());
   1412   DsFsmInstrFff(EmitFR(0x11, 0x15, ft, fs, fd, 0x05), fd, fs, ft);
   1413 }
   1414 
   1415 void MipsAssembler::CmpLeD(FRegister fd, FRegister fs, FRegister ft) {
   1416   CHECK(IsR6());
   1417   DsFsmInstrFff(EmitFR(0x11, 0x15, ft, fs, fd, 0x06), fd, fs, ft);
   1418 }
   1419 
   1420 void MipsAssembler::CmpUleD(FRegister fd, FRegister fs, FRegister ft) {
   1421   CHECK(IsR6());
   1422   DsFsmInstrFff(EmitFR(0x11, 0x15, ft, fs, fd, 0x07), fd, fs, ft);
   1423 }
   1424 
   1425 void MipsAssembler::CmpOrD(FRegister fd, FRegister fs, FRegister ft) {
   1426   CHECK(IsR6());
   1427   DsFsmInstrFff(EmitFR(0x11, 0x15, ft, fs, fd, 0x11), fd, fs, ft);
   1428 }
   1429 
   1430 void MipsAssembler::CmpUneD(FRegister fd, FRegister fs, FRegister ft) {
   1431   CHECK(IsR6());
   1432   DsFsmInstrFff(EmitFR(0x11, 0x15, ft, fs, fd, 0x12), fd, fs, ft);
   1433 }
   1434 
   1435 void MipsAssembler::CmpNeD(FRegister fd, FRegister fs, FRegister ft) {
   1436   CHECK(IsR6());
   1437   DsFsmInstrFff(EmitFR(0x11, 0x15, ft, fs, fd, 0x13), fd, fs, ft);
   1438 }
   1439 
   1440 void MipsAssembler::Movf(Register rd, Register rs, int cc) {
   1441   CHECK(!IsR6());
   1442   CHECK(IsUint<3>(cc)) << cc;
   1443   DsFsmInstrRrrc(EmitR(0, rs, static_cast<Register>(cc << 2), rd, 0, 0x01), rd, rs, cc);
   1444 }
   1445 
   1446 void MipsAssembler::Movt(Register rd, Register rs, int cc) {
   1447   CHECK(!IsR6());
   1448   CHECK(IsUint<3>(cc)) << cc;
   1449   DsFsmInstrRrrc(EmitR(0, rs, static_cast<Register>((cc << 2) | 1), rd, 0, 0x01), rd, rs, cc);
   1450 }
   1451 
   1452 void MipsAssembler::MovfS(FRegister fd, FRegister fs, int cc) {
   1453   CHECK(!IsR6());
   1454   CHECK(IsUint<3>(cc)) << cc;
   1455   DsFsmInstrFffc(EmitFR(0x11, 0x10, static_cast<FRegister>(cc << 2), fs, fd, 0x11), fd, fs, cc);
   1456 }
   1457 
   1458 void MipsAssembler::MovfD(FRegister fd, FRegister fs, int cc) {
   1459   CHECK(!IsR6());
   1460   CHECK(IsUint<3>(cc)) << cc;
   1461   DsFsmInstrFffc(EmitFR(0x11, 0x11, static_cast<FRegister>(cc << 2), fs, fd, 0x11), fd, fs, cc);
   1462 }
   1463 
   1464 void MipsAssembler::MovtS(FRegister fd, FRegister fs, int cc) {
   1465   CHECK(!IsR6());
   1466   CHECK(IsUint<3>(cc)) << cc;
   1467   DsFsmInstrFffc(EmitFR(0x11, 0x10, static_cast<FRegister>((cc << 2) | 1), fs, fd, 0x11),
   1468                  fd,
   1469                  fs,
   1470                  cc);
   1471 }
   1472 
   1473 void MipsAssembler::MovtD(FRegister fd, FRegister fs, int cc) {
   1474   CHECK(!IsR6());
   1475   CHECK(IsUint<3>(cc)) << cc;
   1476   DsFsmInstrFffc(EmitFR(0x11, 0x11, static_cast<FRegister>((cc << 2) | 1), fs, fd, 0x11),
   1477                  fd,
   1478                  fs,
   1479                  cc);
   1480 }
   1481 
   1482 void MipsAssembler::MovzS(FRegister fd, FRegister fs, Register rt) {
   1483   CHECK(!IsR6());
   1484   DsFsmInstrFffr(EmitFR(0x11, 0x10, static_cast<FRegister>(rt), fs, fd, 0x12), fd, fs, rt);
   1485 }
   1486 
   1487 void MipsAssembler::MovzD(FRegister fd, FRegister fs, Register rt) {
   1488   CHECK(!IsR6());
   1489   DsFsmInstrFffr(EmitFR(0x11, 0x11, static_cast<FRegister>(rt), fs, fd, 0x12), fd, fs, rt);
   1490 }
   1491 
   1492 void MipsAssembler::MovnS(FRegister fd, FRegister fs, Register rt) {
   1493   CHECK(!IsR6());
   1494   DsFsmInstrFffr(EmitFR(0x11, 0x10, static_cast<FRegister>(rt), fs, fd, 0x13), fd, fs, rt);
   1495 }
   1496 
   1497 void MipsAssembler::MovnD(FRegister fd, FRegister fs, Register rt) {
   1498   CHECK(!IsR6());
   1499   DsFsmInstrFffr(EmitFR(0x11, 0x11, static_cast<FRegister>(rt), fs, fd, 0x13), fd, fs, rt);
   1500 }
   1501 
   1502 void MipsAssembler::SelS(FRegister fd, FRegister fs, FRegister ft) {
   1503   CHECK(IsR6());
   1504   DsFsmInstrFfff(EmitFR(0x11, 0x10, ft, fs, fd, 0x10), fd, fs, ft);
   1505 }
   1506 
   1507 void MipsAssembler::SelD(FRegister fd, FRegister fs, FRegister ft) {
   1508   CHECK(IsR6());
   1509   DsFsmInstrFfff(EmitFR(0x11, 0x11, ft, fs, fd, 0x10), fd, fs, ft);
   1510 }
   1511 
   1512 void MipsAssembler::SeleqzS(FRegister fd, FRegister fs, FRegister ft) {
   1513   CHECK(IsR6());
   1514   DsFsmInstrFff(EmitFR(0x11, 0x10, ft, fs, fd, 0x14), fd, fs, ft);
   1515 }
   1516 
   1517 void MipsAssembler::SeleqzD(FRegister fd, FRegister fs, FRegister ft) {
   1518   CHECK(IsR6());
   1519   DsFsmInstrFff(EmitFR(0x11, 0x11, ft, fs, fd, 0x14), fd, fs, ft);
   1520 }
   1521 
   1522 void MipsAssembler::SelnezS(FRegister fd, FRegister fs, FRegister ft) {
   1523   CHECK(IsR6());
   1524   DsFsmInstrFff(EmitFR(0x11, 0x10, ft, fs, fd, 0x17), fd, fs, ft);
   1525 }
   1526 
   1527 void MipsAssembler::SelnezD(FRegister fd, FRegister fs, FRegister ft) {
   1528   CHECK(IsR6());
   1529   DsFsmInstrFff(EmitFR(0x11, 0x11, ft, fs, fd, 0x17), fd, fs, ft);
   1530 }
   1531 
   1532 void MipsAssembler::ClassS(FRegister fd, FRegister fs) {
   1533   CHECK(IsR6());
   1534   DsFsmInstrFff(EmitFR(0x11, 0x10, static_cast<FRegister>(0), fs, fd, 0x1b), fd, fs, fs);
   1535 }
   1536 
   1537 void MipsAssembler::ClassD(FRegister fd, FRegister fs) {
   1538   CHECK(IsR6());
   1539   DsFsmInstrFff(EmitFR(0x11, 0x11, static_cast<FRegister>(0), fs, fd, 0x1b), fd, fs, fs);
   1540 }
   1541 
   1542 void MipsAssembler::MinS(FRegister fd, FRegister fs, FRegister ft) {
   1543   CHECK(IsR6());
   1544   DsFsmInstrFff(EmitFR(0x11, 0x10, ft, fs, fd, 0x1c), fd, fs, ft);
   1545 }
   1546 
   1547 void MipsAssembler::MinD(FRegister fd, FRegister fs, FRegister ft) {
   1548   CHECK(IsR6());
   1549   DsFsmInstrFff(EmitFR(0x11, 0x11, ft, fs, fd, 0x1c), fd, fs, ft);
   1550 }
   1551 
   1552 void MipsAssembler::MaxS(FRegister fd, FRegister fs, FRegister ft) {
   1553   CHECK(IsR6());
   1554   DsFsmInstrFff(EmitFR(0x11, 0x10, ft, fs, fd, 0x1e), fd, fs, ft);
   1555 }
   1556 
   1557 void MipsAssembler::MaxD(FRegister fd, FRegister fs, FRegister ft) {
   1558   CHECK(IsR6());
   1559   DsFsmInstrFff(EmitFR(0x11, 0x11, ft, fs, fd, 0x1e), fd, fs, ft);
   1560 }
   1561 
   1562 void MipsAssembler::TruncLS(FRegister fd, FRegister fs) {
   1563   DsFsmInstrFff(EmitFR(0x11, 0x10, static_cast<FRegister>(0), fs, fd, 0x09), fd, fs, fs);
   1564 }
   1565 
   1566 void MipsAssembler::TruncLD(FRegister fd, FRegister fs) {
   1567   DsFsmInstrFff(EmitFR(0x11, 0x11, static_cast<FRegister>(0), fs, fd, 0x09), fd, fs, fs);
   1568 }
   1569 
   1570 void MipsAssembler::TruncWS(FRegister fd, FRegister fs) {
   1571   DsFsmInstrFff(EmitFR(0x11, 0x10, static_cast<FRegister>(0), fs, fd, 0x0D), fd, fs, fs);
   1572 }
   1573 
   1574 void MipsAssembler::TruncWD(FRegister fd, FRegister fs) {
   1575   DsFsmInstrFff(EmitFR(0x11, 0x11, static_cast<FRegister>(0), fs, fd, 0x0D), fd, fs, fs);
   1576 }
   1577 
   1578 void MipsAssembler::Cvtsw(FRegister fd, FRegister fs) {
   1579   DsFsmInstrFff(EmitFR(0x11, 0x14, static_cast<FRegister>(0), fs, fd, 0x20), fd, fs, fs);
   1580 }
   1581 
   1582 void MipsAssembler::Cvtdw(FRegister fd, FRegister fs) {
   1583   DsFsmInstrFff(EmitFR(0x11, 0x14, static_cast<FRegister>(0), fs, fd, 0x21), fd, fs, fs);
   1584 }
   1585 
   1586 void MipsAssembler::Cvtsd(FRegister fd, FRegister fs) {
   1587   DsFsmInstrFff(EmitFR(0x11, 0x11, static_cast<FRegister>(0), fs, fd, 0x20), fd, fs, fs);
   1588 }
   1589 
   1590 void MipsAssembler::Cvtds(FRegister fd, FRegister fs) {
   1591   DsFsmInstrFff(EmitFR(0x11, 0x10, static_cast<FRegister>(0), fs, fd, 0x21), fd, fs, fs);
   1592 }
   1593 
   1594 void MipsAssembler::Cvtsl(FRegister fd, FRegister fs) {
   1595   DsFsmInstrFff(EmitFR(0x11, 0x15, static_cast<FRegister>(0), fs, fd, 0x20), fd, fs, fs);
   1596 }
   1597 
   1598 void MipsAssembler::Cvtdl(FRegister fd, FRegister fs) {
   1599   DsFsmInstrFff(EmitFR(0x11, 0x15, static_cast<FRegister>(0), fs, fd, 0x21), fd, fs, fs);
   1600 }
   1601 
   1602 void MipsAssembler::FloorWS(FRegister fd, FRegister fs) {
   1603   DsFsmInstrFff(EmitFR(0x11, 0x10, static_cast<FRegister>(0), fs, fd, 0xf), fd, fs, fs);
   1604 }
   1605 
   1606 void MipsAssembler::FloorWD(FRegister fd, FRegister fs) {
   1607   DsFsmInstrFff(EmitFR(0x11, 0x11, static_cast<FRegister>(0), fs, fd, 0xf), fd, fs, fs);
   1608 }
   1609 
   1610 void MipsAssembler::Mfc1(Register rt, FRegister fs) {
   1611   DsFsmInstrRf(EmitFR(0x11, 0x00, static_cast<FRegister>(rt), fs, static_cast<FRegister>(0), 0x0),
   1612                rt,
   1613                fs);
   1614 }
   1615 
   1616 void MipsAssembler::Mtc1(Register rt, FRegister fs) {
   1617   DsFsmInstrFr(EmitFR(0x11, 0x04, static_cast<FRegister>(rt), fs, static_cast<FRegister>(0), 0x0),
   1618                fs,
   1619                rt);
   1620 }
   1621 
   1622 void MipsAssembler::Mfhc1(Register rt, FRegister fs) {
   1623   DsFsmInstrRf(EmitFR(0x11, 0x03, static_cast<FRegister>(rt), fs, static_cast<FRegister>(0), 0x0),
   1624                rt,
   1625                fs);
   1626 }
   1627 
   1628 void MipsAssembler::Mthc1(Register rt, FRegister fs) {
   1629   DsFsmInstrFr(EmitFR(0x11, 0x07, static_cast<FRegister>(rt), fs, static_cast<FRegister>(0), 0x0),
   1630                fs,
   1631                rt);
   1632 }
   1633 
   1634 void MipsAssembler::MoveFromFpuHigh(Register rt, FRegister fs) {
   1635   if (Is32BitFPU()) {
   1636     CHECK_EQ(fs % 2, 0) << fs;
   1637     Mfc1(rt, static_cast<FRegister>(fs + 1));
   1638   } else {
   1639     Mfhc1(rt, fs);
   1640   }
   1641 }
   1642 
   1643 void MipsAssembler::MoveToFpuHigh(Register rt, FRegister fs) {
   1644   if (Is32BitFPU()) {
   1645     CHECK_EQ(fs % 2, 0) << fs;
   1646     Mtc1(rt, static_cast<FRegister>(fs + 1));
   1647   } else {
   1648     Mthc1(rt, fs);
   1649   }
   1650 }
   1651 
   1652 void MipsAssembler::Lwc1(FRegister ft, Register rs, uint16_t imm16) {
   1653   DsFsmInstrFr(EmitI(0x31, rs, static_cast<Register>(ft), imm16), ft, rs);
   1654 }
   1655 
   1656 void MipsAssembler::Ldc1(FRegister ft, Register rs, uint16_t imm16) {
   1657   DsFsmInstrFr(EmitI(0x35, rs, static_cast<Register>(ft), imm16), ft, rs);
   1658 }
   1659 
   1660 void MipsAssembler::Swc1(FRegister ft, Register rs, uint16_t imm16) {
   1661   DsFsmInstrFR(EmitI(0x39, rs, static_cast<Register>(ft), imm16), ft, rs);
   1662 }
   1663 
   1664 void MipsAssembler::Sdc1(FRegister ft, Register rs, uint16_t imm16) {
   1665   DsFsmInstrFR(EmitI(0x3d, rs, static_cast<Register>(ft), imm16), ft, rs);
   1666 }
   1667 
   1668 void MipsAssembler::Break() {
   1669   DsFsmInstrNop(EmitR(0, ZERO, ZERO, ZERO, 0, 0xD));
   1670 }
   1671 
   1672 void MipsAssembler::Nop() {
   1673   DsFsmInstrNop(EmitR(0x0, ZERO, ZERO, ZERO, 0, 0x0));
   1674 }
   1675 
   1676 void MipsAssembler::NopIfNoReordering() {
   1677   if (!reordering_) {
   1678     Nop();
   1679   }
   1680 }
   1681 
   1682 void MipsAssembler::Move(Register rd, Register rs) {
   1683   Or(rd, rs, ZERO);
   1684 }
   1685 
   1686 void MipsAssembler::Clear(Register rd) {
   1687   Move(rd, ZERO);
   1688 }
   1689 
   1690 void MipsAssembler::Not(Register rd, Register rs) {
   1691   Nor(rd, rs, ZERO);
   1692 }
   1693 
   1694 void MipsAssembler::Push(Register rs) {
   1695   IncreaseFrameSize(kMipsWordSize);
   1696   Sw(rs, SP, 0);
   1697 }
   1698 
   1699 void MipsAssembler::Pop(Register rd) {
   1700   Lw(rd, SP, 0);
   1701   DecreaseFrameSize(kMipsWordSize);
   1702 }
   1703 
   1704 void MipsAssembler::PopAndReturn(Register rd, Register rt) {
   1705   bool reordering = SetReorder(false);
   1706   Lw(rd, SP, 0);
   1707   Jr(rt);
   1708   DecreaseFrameSize(kMipsWordSize);  // Single instruction in delay slot.
   1709   SetReorder(reordering);
   1710 }
   1711 
   1712 void MipsAssembler::LoadConst32(Register rd, int32_t value) {
   1713   if (IsUint<16>(value)) {
   1714     // Use OR with (unsigned) immediate to encode 16b unsigned int.
   1715     Ori(rd, ZERO, value);
   1716   } else if (IsInt<16>(value)) {
   1717     // Use ADD with (signed) immediate to encode 16b signed int.
   1718     Addiu(rd, ZERO, value);
   1719   } else {
   1720     Lui(rd, High16Bits(value));
   1721     if (value & 0xFFFF)
   1722       Ori(rd, rd, Low16Bits(value));
   1723   }
   1724 }
   1725 
   1726 void MipsAssembler::LoadConst64(Register reg_hi, Register reg_lo, int64_t value) {
   1727   uint32_t low = Low32Bits(value);
   1728   uint32_t high = High32Bits(value);
   1729   LoadConst32(reg_lo, low);
   1730   if (high != low) {
   1731     LoadConst32(reg_hi, high);
   1732   } else {
   1733     Move(reg_hi, reg_lo);
   1734   }
   1735 }
   1736 
   1737 void MipsAssembler::LoadSConst32(FRegister r, int32_t value, Register temp) {
   1738   if (value == 0) {
   1739     temp = ZERO;
   1740   } else {
   1741     LoadConst32(temp, value);
   1742   }
   1743   Mtc1(temp, r);
   1744 }
   1745 
   1746 void MipsAssembler::LoadDConst64(FRegister rd, int64_t value, Register temp) {
   1747   uint32_t low = Low32Bits(value);
   1748   uint32_t high = High32Bits(value);
   1749   if (low == 0) {
   1750     Mtc1(ZERO, rd);
   1751   } else {
   1752     LoadConst32(temp, low);
   1753     Mtc1(temp, rd);
   1754   }
   1755   if (high == 0) {
   1756     MoveToFpuHigh(ZERO, rd);
   1757   } else {
   1758     LoadConst32(temp, high);
   1759     MoveToFpuHigh(temp, rd);
   1760   }
   1761 }
   1762 
   1763 void MipsAssembler::Addiu32(Register rt, Register rs, int32_t value, Register temp) {
   1764   CHECK_NE(rs, temp);  // Must not overwrite the register `rs` while loading `value`.
   1765   if (IsInt<16>(value)) {
   1766     Addiu(rt, rs, value);
   1767   } else if (IsR6()) {
   1768     int16_t high = High16Bits(value);
   1769     int16_t low = Low16Bits(value);
   1770     high += (low < 0) ? 1 : 0;  // Account for sign extension in addiu.
   1771     if (low != 0) {
   1772       Aui(temp, rs, high);
   1773       Addiu(rt, temp, low);
   1774     } else {
   1775       Aui(rt, rs, high);
   1776     }
   1777   } else {
   1778     // Do not load the whole 32-bit `value` if it can be represented as
   1779     // a sum of two 16-bit signed values. This can save an instruction.
   1780     constexpr int32_t kMinValueForSimpleAdjustment = std::numeric_limits<int16_t>::min() * 2;
   1781     constexpr int32_t kMaxValueForSimpleAdjustment = std::numeric_limits<int16_t>::max() * 2;
   1782     if (0 <= value && value <= kMaxValueForSimpleAdjustment) {
   1783       Addiu(temp, rs, kMaxValueForSimpleAdjustment / 2);
   1784       Addiu(rt, temp, value - kMaxValueForSimpleAdjustment / 2);
   1785     } else if (kMinValueForSimpleAdjustment <= value && value < 0) {
   1786       Addiu(temp, rs, kMinValueForSimpleAdjustment / 2);
   1787       Addiu(rt, temp, value - kMinValueForSimpleAdjustment / 2);
   1788     } else {
   1789       // Now that all shorter options have been exhausted, load the full 32-bit value.
   1790       LoadConst32(temp, value);
   1791       Addu(rt, rs, temp);
   1792     }
   1793   }
   1794 }
   1795 
   1796 void MipsAssembler::Branch::InitShortOrLong(MipsAssembler::Branch::OffsetBits offset_size,
   1797                                             MipsAssembler::Branch::Type short_type,
   1798                                             MipsAssembler::Branch::Type long_type) {
   1799   type_ = (offset_size <= branch_info_[short_type].offset_size) ? short_type : long_type;
   1800 }
   1801 
   1802 void MipsAssembler::Branch::InitializeType(Type initial_type, bool is_r6) {
   1803   OffsetBits offset_size = GetOffsetSizeNeeded(location_, target_);
   1804   if (is_r6) {
   1805     // R6
   1806     switch (initial_type) {
   1807       case kLabel:
   1808         CHECK(!IsResolved());
   1809         type_ = kR6Label;
   1810         break;
   1811       case kLiteral:
   1812         CHECK(!IsResolved());
   1813         type_ = kR6Literal;
   1814         break;
   1815       case kCall:
   1816         InitShortOrLong(offset_size, kR6Call, kR6LongCall);
   1817         break;
   1818       case kCondBranch:
   1819         switch (condition_) {
   1820           case kUncond:
   1821             InitShortOrLong(offset_size, kR6UncondBranch, kR6LongUncondBranch);
   1822             break;
   1823           case kCondEQZ:
   1824           case kCondNEZ:
   1825             // Special case for beqzc/bnezc with longer offset than in other b<cond>c instructions.
   1826             type_ = (offset_size <= kOffset23) ? kR6CondBranch : kR6LongCondBranch;
   1827             break;
   1828           default:
   1829             InitShortOrLong(offset_size, kR6CondBranch, kR6LongCondBranch);
   1830             break;
   1831         }
   1832         break;
   1833       default:
   1834         LOG(FATAL) << "Unexpected branch type " << initial_type;
   1835         UNREACHABLE();
   1836     }
   1837   } else {
   1838     // R2
   1839     switch (initial_type) {
   1840       case kLabel:
   1841         CHECK(!IsResolved());
   1842         type_ = kLabel;
   1843         break;
   1844       case kLiteral:
   1845         CHECK(!IsResolved());
   1846         type_ = kLiteral;
   1847         break;
   1848       case kCall:
   1849         InitShortOrLong(offset_size, kCall, kLongCall);
   1850         break;
   1851       case kCondBranch:
   1852         switch (condition_) {
   1853           case kUncond:
   1854             InitShortOrLong(offset_size, kUncondBranch, kLongUncondBranch);
   1855             break;
   1856           default:
   1857             InitShortOrLong(offset_size, kCondBranch, kLongCondBranch);
   1858             break;
   1859         }
   1860         break;
   1861       default:
   1862         LOG(FATAL) << "Unexpected branch type " << initial_type;
   1863         UNREACHABLE();
   1864     }
   1865   }
   1866   old_type_ = type_;
   1867 }
   1868 
   1869 bool MipsAssembler::Branch::IsNop(BranchCondition condition, Register lhs, Register rhs) {
   1870   switch (condition) {
   1871     case kCondLT:
   1872     case kCondGT:
   1873     case kCondNE:
   1874     case kCondLTU:
   1875       return lhs == rhs;
   1876     default:
   1877       return false;
   1878   }
   1879 }
   1880 
   1881 bool MipsAssembler::Branch::IsUncond(BranchCondition condition, Register lhs, Register rhs) {
   1882   switch (condition) {
   1883     case kUncond:
   1884       return true;
   1885     case kCondGE:
   1886     case kCondLE:
   1887     case kCondEQ:
   1888     case kCondGEU:
   1889       return lhs == rhs;
   1890     default:
   1891       return false;
   1892   }
   1893 }
   1894 
   1895 MipsAssembler::Branch::Branch(bool is_r6, uint32_t location, uint32_t target, bool is_call)
   1896     : old_location_(location),
   1897       location_(location),
   1898       target_(target),
   1899       lhs_reg_(0),
   1900       rhs_reg_(0),
   1901       condition_(kUncond),
   1902       delayed_instruction_(kUnfilledDelaySlot) {
   1903   InitializeType((is_call ? kCall : kCondBranch), is_r6);
   1904 }
   1905 
   1906 MipsAssembler::Branch::Branch(bool is_r6,
   1907                               uint32_t location,
   1908                               uint32_t target,
   1909                               MipsAssembler::BranchCondition condition,
   1910                               Register lhs_reg,
   1911                               Register rhs_reg)
   1912     : old_location_(location),
   1913       location_(location),
   1914       target_(target),
   1915       lhs_reg_(lhs_reg),
   1916       rhs_reg_(rhs_reg),
   1917       condition_(condition),
   1918       delayed_instruction_(kUnfilledDelaySlot) {
   1919   CHECK_NE(condition, kUncond);
   1920   switch (condition) {
   1921     case kCondLT:
   1922     case kCondGE:
   1923     case kCondLE:
   1924     case kCondGT:
   1925     case kCondLTU:
   1926     case kCondGEU:
   1927       // We don't support synthetic R2 branches (preceded with slt[u]) at this level
   1928       // (R2 doesn't have branches to compare 2 registers using <, <=, >=, >).
   1929       // We leave this up to the caller.
   1930       CHECK(is_r6);
   1931       FALLTHROUGH_INTENDED;
   1932     case kCondEQ:
   1933     case kCondNE:
   1934       // Require registers other than 0 not only for R6, but also for R2 to catch errors.
   1935       // To compare with 0, use dedicated kCond*Z conditions.
   1936       CHECK_NE(lhs_reg, ZERO);
   1937       CHECK_NE(rhs_reg, ZERO);
   1938       break;
   1939     case kCondLTZ:
   1940     case kCondGEZ:
   1941     case kCondLEZ:
   1942     case kCondGTZ:
   1943     case kCondEQZ:
   1944     case kCondNEZ:
   1945       // Require registers other than 0 not only for R6, but also for R2 to catch errors.
   1946       CHECK_NE(lhs_reg, ZERO);
   1947       CHECK_EQ(rhs_reg, ZERO);
   1948       break;
   1949     case kCondF:
   1950     case kCondT:
   1951       CHECK_EQ(rhs_reg, ZERO);
   1952       break;
   1953     case kUncond:
   1954       UNREACHABLE();
   1955   }
   1956   CHECK(!IsNop(condition, lhs_reg, rhs_reg));
   1957   if (IsUncond(condition, lhs_reg, rhs_reg)) {
   1958     // Branch condition is always true, make the branch unconditional.
   1959     condition_ = kUncond;
   1960   }
   1961   InitializeType(kCondBranch, is_r6);
   1962 }
   1963 
   1964 MipsAssembler::Branch::Branch(bool is_r6,
   1965                               uint32_t location,
   1966                               Register dest_reg,
   1967                               Register base_reg,
   1968                               Type label_or_literal_type)
   1969     : old_location_(location),
   1970       location_(location),
   1971       target_(kUnresolved),
   1972       lhs_reg_(dest_reg),
   1973       rhs_reg_(base_reg),
   1974       condition_(kUncond),
   1975       delayed_instruction_(kUnfilledDelaySlot) {
   1976   CHECK_NE(dest_reg, ZERO);
   1977   if (is_r6) {
   1978     CHECK_EQ(base_reg, ZERO);
   1979   } else {
   1980     CHECK_NE(base_reg, ZERO);
   1981   }
   1982   InitializeType(label_or_literal_type, is_r6);
   1983 }
   1984 
   1985 MipsAssembler::BranchCondition MipsAssembler::Branch::OppositeCondition(
   1986     MipsAssembler::BranchCondition cond) {
   1987   switch (cond) {
   1988     case kCondLT:
   1989       return kCondGE;
   1990     case kCondGE:
   1991       return kCondLT;
   1992     case kCondLE:
   1993       return kCondGT;
   1994     case kCondGT:
   1995       return kCondLE;
   1996     case kCondLTZ:
   1997       return kCondGEZ;
   1998     case kCondGEZ:
   1999       return kCondLTZ;
   2000     case kCondLEZ:
   2001       return kCondGTZ;
   2002     case kCondGTZ:
   2003       return kCondLEZ;
   2004     case kCondEQ:
   2005       return kCondNE;
   2006     case kCondNE:
   2007       return kCondEQ;
   2008     case kCondEQZ:
   2009       return kCondNEZ;
   2010     case kCondNEZ:
   2011       return kCondEQZ;
   2012     case kCondLTU:
   2013       return kCondGEU;
   2014     case kCondGEU:
   2015       return kCondLTU;
   2016     case kCondF:
   2017       return kCondT;
   2018     case kCondT:
   2019       return kCondF;
   2020     case kUncond:
   2021       LOG(FATAL) << "Unexpected branch condition " << cond;
   2022   }
   2023   UNREACHABLE();
   2024 }
   2025 
   2026 MipsAssembler::Branch::Type MipsAssembler::Branch::GetType() const {
   2027   return type_;
   2028 }
   2029 
   2030 MipsAssembler::BranchCondition MipsAssembler::Branch::GetCondition() const {
   2031   return condition_;
   2032 }
   2033 
   2034 Register MipsAssembler::Branch::GetLeftRegister() const {
   2035   return static_cast<Register>(lhs_reg_);
   2036 }
   2037 
   2038 Register MipsAssembler::Branch::GetRightRegister() const {
   2039   return static_cast<Register>(rhs_reg_);
   2040 }
   2041 
   2042 uint32_t MipsAssembler::Branch::GetTarget() const {
   2043   return target_;
   2044 }
   2045 
   2046 uint32_t MipsAssembler::Branch::GetLocation() const {
   2047   return location_;
   2048 }
   2049 
   2050 uint32_t MipsAssembler::Branch::GetOldLocation() const {
   2051   return old_location_;
   2052 }
   2053 
   2054 uint32_t MipsAssembler::Branch::GetPrecedingInstructionLength(Type type) const {
   2055   // Short branches with delay slots always consist of two instructions, the branch
   2056   // and the delay slot, irrespective of whether the delay slot is filled with a
   2057   // useful instruction or not.
   2058   // Long composite branches may have a length longer by one instruction than
   2059   // specified in branch_info_[].length. This happens when an instruction is taken
   2060   // to fill the short branch delay slot, but the branch eventually becomes long
   2061   // and formally has no delay slot to fill. This instruction is placed at the
   2062   // beginning of the long composite branch and this needs to be accounted for in
   2063   // the branch length and the location of the offset encoded in the branch.
   2064   switch (type) {
   2065     case kLongUncondBranch:
   2066     case kLongCondBranch:
   2067     case kLongCall:
   2068     case kR6LongCondBranch:
   2069       return (delayed_instruction_ != kUnfilledDelaySlot &&
   2070           delayed_instruction_ != kUnfillableDelaySlot) ? 1 : 0;
   2071     default:
   2072       return 0;
   2073   }
   2074 }
   2075 
   2076 uint32_t MipsAssembler::Branch::GetPrecedingInstructionSize(Type type) const {
   2077   return GetPrecedingInstructionLength(type) * sizeof(uint32_t);
   2078 }
   2079 
   2080 uint32_t MipsAssembler::Branch::GetLength() const {
   2081   return GetPrecedingInstructionLength(type_) + branch_info_[type_].length;
   2082 }
   2083 
   2084 uint32_t MipsAssembler::Branch::GetOldLength() const {
   2085   return GetPrecedingInstructionLength(old_type_) + branch_info_[old_type_].length;
   2086 }
   2087 
   2088 uint32_t MipsAssembler::Branch::GetSize() const {
   2089   return GetLength() * sizeof(uint32_t);
   2090 }
   2091 
   2092 uint32_t MipsAssembler::Branch::GetOldSize() const {
   2093   return GetOldLength() * sizeof(uint32_t);
   2094 }
   2095 
   2096 uint32_t MipsAssembler::Branch::GetEndLocation() const {
   2097   return GetLocation() + GetSize();
   2098 }
   2099 
   2100 uint32_t MipsAssembler::Branch::GetOldEndLocation() const {
   2101   return GetOldLocation() + GetOldSize();
   2102 }
   2103 
   2104 bool MipsAssembler::Branch::IsLong() const {
   2105   switch (type_) {
   2106     // R2 short branches.
   2107     case kUncondBranch:
   2108     case kCondBranch:
   2109     case kCall:
   2110     // R2 near label.
   2111     case kLabel:
   2112     // R2 near literal.
   2113     case kLiteral:
   2114     // R6 short branches.
   2115     case kR6UncondBranch:
   2116     case kR6CondBranch:
   2117     case kR6Call:
   2118     // R6 near label.
   2119     case kR6Label:
   2120     // R6 near literal.
   2121     case kR6Literal:
   2122       return false;
   2123     // R2 long branches.
   2124     case kLongUncondBranch:
   2125     case kLongCondBranch:
   2126     case kLongCall:
   2127     // R2 far label.
   2128     case kFarLabel:
   2129     // R2 far literal.
   2130     case kFarLiteral:
   2131     // R6 long branches.
   2132     case kR6LongUncondBranch:
   2133     case kR6LongCondBranch:
   2134     case kR6LongCall:
   2135     // R6 far label.
   2136     case kR6FarLabel:
   2137     // R6 far literal.
   2138     case kR6FarLiteral:
   2139       return true;
   2140   }
   2141   UNREACHABLE();
   2142 }
   2143 
   2144 bool MipsAssembler::Branch::IsResolved() const {
   2145   return target_ != kUnresolved;
   2146 }
   2147 
   2148 MipsAssembler::Branch::OffsetBits MipsAssembler::Branch::GetOffsetSize() const {
   2149   OffsetBits offset_size =
   2150       (type_ == kR6CondBranch && (condition_ == kCondEQZ || condition_ == kCondNEZ))
   2151           ? kOffset23
   2152           : branch_info_[type_].offset_size;
   2153   return offset_size;
   2154 }
   2155 
   2156 MipsAssembler::Branch::OffsetBits MipsAssembler::Branch::GetOffsetSizeNeeded(uint32_t location,
   2157                                                                              uint32_t target) {
   2158   // For unresolved targets assume the shortest encoding
   2159   // (later it will be made longer if needed).
   2160   if (target == kUnresolved)
   2161     return kOffset16;
   2162   int64_t distance = static_cast<int64_t>(target) - location;
   2163   // To simplify calculations in composite branches consisting of multiple instructions
   2164   // bump up the distance by a value larger than the max byte size of a composite branch.
   2165   distance += (distance >= 0) ? kMaxBranchSize : -kMaxBranchSize;
   2166   if (IsInt<kOffset16>(distance))
   2167     return kOffset16;
   2168   else if (IsInt<kOffset18>(distance))
   2169     return kOffset18;
   2170   else if (IsInt<kOffset21>(distance))
   2171     return kOffset21;
   2172   else if (IsInt<kOffset23>(distance))
   2173     return kOffset23;
   2174   else if (IsInt<kOffset28>(distance))
   2175     return kOffset28;
   2176   return kOffset32;
   2177 }
   2178 
   2179 void MipsAssembler::Branch::Resolve(uint32_t target) {
   2180   target_ = target;
   2181 }
   2182 
   2183 void MipsAssembler::Branch::Relocate(uint32_t expand_location, uint32_t delta) {
   2184   if (location_ > expand_location) {
   2185     location_ += delta;
   2186   }
   2187   if (!IsResolved()) {
   2188     return;  // Don't know the target yet.
   2189   }
   2190   if (target_ > expand_location) {
   2191     target_ += delta;
   2192   }
   2193 }
   2194 
   2195 void MipsAssembler::Branch::PromoteToLong() {
   2196   switch (type_) {
   2197     // R2 short branches.
   2198     case kUncondBranch:
   2199       type_ = kLongUncondBranch;
   2200       break;
   2201     case kCondBranch:
   2202       type_ = kLongCondBranch;
   2203       break;
   2204     case kCall:
   2205       type_ = kLongCall;
   2206       break;
   2207     // R2 near label.
   2208     case kLabel:
   2209       type_ = kFarLabel;
   2210       break;
   2211     // R2 near literal.
   2212     case kLiteral:
   2213       type_ = kFarLiteral;
   2214       break;
   2215     // R6 short branches.
   2216     case kR6UncondBranch:
   2217       type_ = kR6LongUncondBranch;
   2218       break;
   2219     case kR6CondBranch:
   2220       type_ = kR6LongCondBranch;
   2221       break;
   2222     case kR6Call:
   2223       type_ = kR6LongCall;
   2224       break;
   2225     // R6 near label.
   2226     case kR6Label:
   2227       type_ = kR6FarLabel;
   2228       break;
   2229     // R6 near literal.
   2230     case kR6Literal:
   2231       type_ = kR6FarLiteral;
   2232       break;
   2233     default:
   2234       // Note: 'type_' is already long.
   2235       break;
   2236   }
   2237   CHECK(IsLong());
   2238 }
   2239 
   2240 uint32_t MipsAssembler::GetBranchLocationOrPcRelBase(const MipsAssembler::Branch* branch) const {
   2241   switch (branch->GetType()) {
   2242     case Branch::kLabel:
   2243     case Branch::kFarLabel:
   2244     case Branch::kLiteral:
   2245     case Branch::kFarLiteral:
   2246       return GetLabelLocation(&pc_rel_base_label_);
   2247     default:
   2248       return branch->GetLocation();
   2249   }
   2250 }
   2251 
   2252 uint32_t MipsAssembler::Branch::PromoteIfNeeded(uint32_t location, uint32_t max_short_distance) {
   2253   // `location` is either `GetLabelLocation(&pc_rel_base_label_)` for R2 labels/literals or
   2254   // `this->GetLocation()` for everything else.
   2255   // If the branch is still unresolved or already long, nothing to do.
   2256   if (IsLong() || !IsResolved()) {
   2257     return 0;
   2258   }
   2259   // Promote the short branch to long if the offset size is too small
   2260   // to hold the distance between location and target_.
   2261   if (GetOffsetSizeNeeded(location, target_) > GetOffsetSize()) {
   2262     PromoteToLong();
   2263     uint32_t old_size = GetOldSize();
   2264     uint32_t new_size = GetSize();
   2265     CHECK_GT(new_size, old_size);
   2266     return new_size - old_size;
   2267   }
   2268   // The following logic is for debugging/testing purposes.
   2269   // Promote some short branches to long when it's not really required.
   2270   if (UNLIKELY(max_short_distance != std::numeric_limits<uint32_t>::max())) {
   2271     int64_t distance = static_cast<int64_t>(target_) - location;
   2272     distance = (distance >= 0) ? distance : -distance;
   2273     if (distance >= max_short_distance) {
   2274       PromoteToLong();
   2275       uint32_t old_size = GetOldSize();
   2276       uint32_t new_size = GetSize();
   2277       CHECK_GT(new_size, old_size);
   2278       return new_size - old_size;
   2279     }
   2280   }
   2281   return 0;
   2282 }
   2283 
   2284 uint32_t MipsAssembler::Branch::GetOffsetLocation() const {
   2285   return location_ + GetPrecedingInstructionSize(type_) +
   2286       branch_info_[type_].instr_offset * sizeof(uint32_t);
   2287 }
   2288 
   2289 uint32_t MipsAssembler::GetBranchOrPcRelBaseForEncoding(const MipsAssembler::Branch* branch) const {
   2290   switch (branch->GetType()) {
   2291     case Branch::kLabel:
   2292     case Branch::kFarLabel:
   2293     case Branch::kLiteral:
   2294     case Branch::kFarLiteral:
   2295       return GetLabelLocation(&pc_rel_base_label_);
   2296     default:
   2297       return branch->GetOffsetLocation() +
   2298           Branch::branch_info_[branch->GetType()].pc_org * sizeof(uint32_t);
   2299   }
   2300 }
   2301 
   2302 uint32_t MipsAssembler::Branch::GetOffset(uint32_t location) const {
   2303   // `location` is either `GetLabelLocation(&pc_rel_base_label_)` for R2 labels/literals or
   2304   // `this->GetOffsetLocation() + branch_info_[this->GetType()].pc_org * sizeof(uint32_t)`
   2305   // for everything else.
   2306   CHECK(IsResolved());
   2307   uint32_t ofs_mask = 0xFFFFFFFF >> (32 - GetOffsetSize());
   2308   // Calculate the byte distance between instructions and also account for
   2309   // different PC-relative origins.
   2310   uint32_t offset = target_ - location;
   2311   // Prepare the offset for encoding into the instruction(s).
   2312   offset = (offset & ofs_mask) >> branch_info_[type_].offset_shift;
   2313   return offset;
   2314 }
   2315 
   2316 MipsAssembler::Branch* MipsAssembler::GetBranch(uint32_t branch_id) {
   2317   CHECK_LT(branch_id, branches_.size());
   2318   return &branches_[branch_id];
   2319 }
   2320 
   2321 const MipsAssembler::Branch* MipsAssembler::GetBranch(uint32_t branch_id) const {
   2322   CHECK_LT(branch_id, branches_.size());
   2323   return &branches_[branch_id];
   2324 }
   2325 
   2326 void MipsAssembler::Bind(MipsLabel* label) {
   2327   CHECK(!label->IsBound());
   2328   uint32_t bound_pc = buffer_.Size();
   2329 
   2330   // Make the delay slot FSM aware of the new label.
   2331   DsFsmLabel();
   2332 
   2333   // Walk the list of branches referring to and preceding this label.
   2334   // Store the previously unknown target addresses in them.
   2335   while (label->IsLinked()) {
   2336     uint32_t branch_id = label->Position();
   2337     Branch* branch = GetBranch(branch_id);
   2338     branch->Resolve(bound_pc);
   2339 
   2340     uint32_t branch_location = branch->GetLocation();
   2341     // Extract the location of the previous branch in the list (walking the list backwards;
   2342     // the previous branch ID was stored in the space reserved for this branch).
   2343     uint32_t prev = buffer_.Load<uint32_t>(branch_location);
   2344 
   2345     // On to the previous branch in the list...
   2346     label->position_ = prev;
   2347   }
   2348 
   2349   // Now make the label object contain its own location (relative to the end of the preceding
   2350   // branch, if any; it will be used by the branches referring to and following this label).
   2351   label->prev_branch_id_plus_one_ = branches_.size();
   2352   if (label->prev_branch_id_plus_one_) {
   2353     uint32_t branch_id = label->prev_branch_id_plus_one_ - 1;
   2354     const Branch* branch = GetBranch(branch_id);
   2355     bound_pc -= branch->GetEndLocation();
   2356   }
   2357   label->BindTo(bound_pc);
   2358 }
   2359 
   2360 uint32_t MipsAssembler::GetLabelLocation(const MipsLabel* label) const {
   2361   CHECK(label->IsBound());
   2362   uint32_t target = label->Position();
   2363   if (label->prev_branch_id_plus_one_) {
   2364     // Get label location based on the branch preceding it.
   2365     uint32_t branch_id = label->prev_branch_id_plus_one_ - 1;
   2366     const Branch* branch = GetBranch(branch_id);
   2367     target += branch->GetEndLocation();
   2368   }
   2369   return target;
   2370 }
   2371 
   2372 uint32_t MipsAssembler::GetAdjustedPosition(uint32_t old_position) {
   2373   // We can reconstruct the adjustment by going through all the branches from the beginning
   2374   // up to the old_position. Since we expect AdjustedPosition() to be called in a loop
   2375   // with increasing old_position, we can use the data from last AdjustedPosition() to
   2376   // continue where we left off and the whole loop should be O(m+n) where m is the number
   2377   // of positions to adjust and n is the number of branches.
   2378   if (old_position < last_old_position_) {
   2379     last_position_adjustment_ = 0;
   2380     last_old_position_ = 0;
   2381     last_branch_id_ = 0;
   2382   }
   2383   while (last_branch_id_ != branches_.size()) {
   2384     const Branch* branch = GetBranch(last_branch_id_);
   2385     if (branch->GetLocation() >= old_position + last_position_adjustment_) {
   2386       break;
   2387     }
   2388     last_position_adjustment_ += branch->GetSize() - branch->GetOldSize();
   2389     ++last_branch_id_;
   2390   }
   2391   last_old_position_ = old_position;
   2392   return old_position + last_position_adjustment_;
   2393 }
   2394 
   2395 void MipsAssembler::BindPcRelBaseLabel() {
   2396   Bind(&pc_rel_base_label_);
   2397 }
   2398 
   2399 uint32_t MipsAssembler::GetPcRelBaseLabelLocation() const {
   2400   return GetLabelLocation(&pc_rel_base_label_);
   2401 }
   2402 
   2403 void MipsAssembler::FinalizeLabeledBranch(MipsLabel* label) {
   2404   uint32_t length = branches_.back().GetLength();
   2405   // Commit the last branch target label (if any).
   2406   DsFsmCommitLabel();
   2407   if (!label->IsBound()) {
   2408     // Branch forward (to a following label), distance is unknown.
   2409     // The first branch forward will contain 0, serving as the terminator of
   2410     // the list of forward-reaching branches.
   2411     Emit(label->position_);
   2412     // Nothing for the delay slot (yet).
   2413     DsFsmInstrNop(0);
   2414     length--;
   2415     // Now make the label object point to this branch
   2416     // (this forms a linked list of branches preceding this label).
   2417     uint32_t branch_id = branches_.size() - 1;
   2418     label->LinkTo(branch_id);
   2419   }
   2420   // Reserve space for the branch.
   2421   while (length--) {
   2422     Nop();
   2423   }
   2424 }
   2425 
   2426 bool MipsAssembler::Branch::CanHaveDelayedInstruction(const DelaySlot& delay_slot) const {
   2427   if (delay_slot.instruction_ == 0) {
   2428     // NOP or no instruction for the delay slot.
   2429     return false;
   2430   }
   2431   switch (type_) {
   2432     // R2 unconditional branches.
   2433     case kUncondBranch:
   2434     case kLongUncondBranch:
   2435       // There are no register interdependencies.
   2436       return true;
   2437 
   2438     // R2 calls.
   2439     case kCall:
   2440     case kLongCall:
   2441       // Instructions depending on or modifying RA should not be moved into delay slots
   2442       // of branches modifying RA.
   2443       return ((delay_slot.gpr_ins_mask_ | delay_slot.gpr_outs_mask_) & (1u << RA)) == 0;
   2444 
   2445     // R2 conditional branches.
   2446     case kCondBranch:
   2447     case kLongCondBranch:
   2448       switch (condition_) {
   2449         // Branches with one GPR source.
   2450         case kCondLTZ:
   2451         case kCondGEZ:
   2452         case kCondLEZ:
   2453         case kCondGTZ:
   2454         case kCondEQZ:
   2455         case kCondNEZ:
   2456           return (delay_slot.gpr_outs_mask_ & (1u << lhs_reg_)) == 0;
   2457 
   2458         // Branches with two GPR sources.
   2459         case kCondEQ:
   2460         case kCondNE:
   2461           return (delay_slot.gpr_outs_mask_ & ((1u << lhs_reg_) | (1u << rhs_reg_))) == 0;
   2462 
   2463         // Branches with one FPU condition code source.
   2464         case kCondF:
   2465         case kCondT:
   2466           return (delay_slot.cc_outs_mask_ & (1u << lhs_reg_)) == 0;
   2467 
   2468         default:
   2469           // We don't support synthetic R2 branches (preceded with slt[u]) at this level
   2470           // (R2 doesn't have branches to compare 2 registers using <, <=, >=, >).
   2471           LOG(FATAL) << "Unexpected branch condition " << condition_;
   2472           UNREACHABLE();
   2473       }
   2474 
   2475     // R6 unconditional branches.
   2476     case kR6UncondBranch:
   2477     case kR6LongUncondBranch:
   2478     // R6 calls.
   2479     case kR6Call:
   2480     case kR6LongCall:
   2481       // There are no delay slots.
   2482       return false;
   2483 
   2484     // R6 conditional branches.
   2485     case kR6CondBranch:
   2486     case kR6LongCondBranch:
   2487       switch (condition_) {
   2488         // Branches with one FPU register source.
   2489         case kCondF:
   2490         case kCondT:
   2491           return (delay_slot.fpr_outs_mask_ & (1u << lhs_reg_)) == 0;
   2492         // Others have a forbidden slot instead of a delay slot.
   2493         default:
   2494           return false;
   2495       }
   2496 
   2497     // Literals.
   2498     default:
   2499       LOG(FATAL) << "Unexpected branch type " << type_;
   2500       UNREACHABLE();
   2501   }
   2502 }
   2503 
   2504 uint32_t MipsAssembler::Branch::GetDelayedInstruction() const {
   2505   return delayed_instruction_;
   2506 }
   2507 
   2508 void MipsAssembler::Branch::SetDelayedInstruction(uint32_t instruction) {
   2509   CHECK_NE(instruction, kUnfilledDelaySlot);
   2510   CHECK_EQ(delayed_instruction_, kUnfilledDelaySlot);
   2511   delayed_instruction_ = instruction;
   2512 }
   2513 
   2514 void MipsAssembler::Branch::DecrementLocations() {
   2515   // We first create a branch object, which gets its type and locations initialized,
   2516   // and then we check if the branch can actually have the preceding instruction moved
   2517   // into its delay slot. If it can, the branch locations need to be decremented.
   2518   //
   2519   // We could make the check before creating the branch object and avoid the location
   2520   // adjustment, but the check is cleaner when performed on an initialized branch
   2521   // object.
   2522   //
   2523   // If the branch is backwards (to a previously bound label), reducing the locations
   2524   // cannot cause a short branch to exceed its offset range because the offset reduces.
   2525   // And this is not at all a problem for a long branch backwards.
   2526   //
   2527   // If the branch is forward (not linked to any label yet), reducing the locations
   2528   // is harmless. The branch will be promoted to long if needed when the target is known.
   2529   CHECK_EQ(location_, old_location_);
   2530   CHECK_GE(old_location_, sizeof(uint32_t));
   2531   old_location_ -= sizeof(uint32_t);
   2532   location_ = old_location_;
   2533 }
   2534 
   2535 void MipsAssembler::MoveInstructionToDelaySlot(Branch& branch) {
   2536   if (branch.CanHaveDelayedInstruction(delay_slot_)) {
   2537     // The last instruction cannot be used in a different delay slot,
   2538     // do not commit the label before it (if any).
   2539     DsFsmDropLabel();
   2540     // Remove the last emitted instruction.
   2541     size_t size = buffer_.Size();
   2542     CHECK_GE(size, sizeof(uint32_t));
   2543     size -= sizeof(uint32_t);
   2544     CHECK_EQ(buffer_.Load<uint32_t>(size), delay_slot_.instruction_);
   2545     buffer_.Resize(size);
   2546     // Attach it to the branch and adjust the branch locations.
   2547     branch.DecrementLocations();
   2548     branch.SetDelayedInstruction(delay_slot_.instruction_);
   2549   } else if (!reordering_ && branch.GetType() == Branch::kUncondBranch) {
   2550     // If reordefing is disabled, prevent absorption of the target instruction.
   2551     branch.SetDelayedInstruction(Branch::kUnfillableDelaySlot);
   2552   }
   2553 }
   2554 
   2555 void MipsAssembler::Buncond(MipsLabel* label) {
   2556   uint32_t target = label->IsBound() ? GetLabelLocation(label) : Branch::kUnresolved;
   2557   branches_.emplace_back(IsR6(), buffer_.Size(), target, /* is_call */ false);
   2558   MoveInstructionToDelaySlot(branches_.back());
   2559   FinalizeLabeledBranch(label);
   2560 }
   2561 
   2562 void MipsAssembler::Bcond(MipsLabel* label, BranchCondition condition, Register lhs, Register rhs) {
   2563   // If lhs = rhs, this can be a NOP.
   2564   if (Branch::IsNop(condition, lhs, rhs)) {
   2565     return;
   2566   }
   2567   uint32_t target = label->IsBound() ? GetLabelLocation(label) : Branch::kUnresolved;
   2568   branches_.emplace_back(IsR6(), buffer_.Size(), target, condition, lhs, rhs);
   2569   MoveInstructionToDelaySlot(branches_.back());
   2570   FinalizeLabeledBranch(label);
   2571 }
   2572 
   2573 void MipsAssembler::Call(MipsLabel* label) {
   2574   uint32_t target = label->IsBound() ? GetLabelLocation(label) : Branch::kUnresolved;
   2575   branches_.emplace_back(IsR6(), buffer_.Size(), target, /* is_call */ true);
   2576   MoveInstructionToDelaySlot(branches_.back());
   2577   FinalizeLabeledBranch(label);
   2578 }
   2579 
   2580 void MipsAssembler::LoadLabelAddress(Register dest_reg, Register base_reg, MipsLabel* label) {
   2581   // Label address loads are treated as pseudo branches since they require very similar handling.
   2582   DCHECK(!label->IsBound());
   2583   branches_.emplace_back(IsR6(), buffer_.Size(), dest_reg, base_reg, Branch::kLabel);
   2584   FinalizeLabeledBranch(label);
   2585 }
   2586 
   2587 Literal* MipsAssembler::NewLiteral(size_t size, const uint8_t* data) {
   2588   DCHECK(size == 4u || size == 8u) << size;
   2589   literals_.emplace_back(size, data);
   2590   return &literals_.back();
   2591 }
   2592 
   2593 void MipsAssembler::LoadLiteral(Register dest_reg, Register base_reg, Literal* literal) {
   2594   // Literal loads are treated as pseudo branches since they require very similar handling.
   2595   DCHECK_EQ(literal->GetSize(), 4u);
   2596   MipsLabel* label = literal->GetLabel();
   2597   DCHECK(!label->IsBound());
   2598   branches_.emplace_back(IsR6(), buffer_.Size(), dest_reg, base_reg, Branch::kLiteral);
   2599   FinalizeLabeledBranch(label);
   2600 }
   2601 
   2602 JumpTable* MipsAssembler::CreateJumpTable(std::vector<MipsLabel*>&& labels) {
   2603   jump_tables_.emplace_back(std::move(labels));
   2604   JumpTable* table = &jump_tables_.back();
   2605   DCHECK(!table->GetLabel()->IsBound());
   2606   return table;
   2607 }
   2608 
   2609 void MipsAssembler::EmitLiterals() {
   2610   if (!literals_.empty()) {
   2611     // We don't support byte and half-word literals.
   2612     // TODO: proper alignment for 64-bit literals when they're implemented.
   2613     for (Literal& literal : literals_) {
   2614       MipsLabel* label = literal.GetLabel();
   2615       Bind(label);
   2616       AssemblerBuffer::EnsureCapacity ensured(&buffer_);
   2617       DCHECK(literal.GetSize() == 4u || literal.GetSize() == 8u);
   2618       for (size_t i = 0, size = literal.GetSize(); i != size; ++i) {
   2619         buffer_.Emit<uint8_t>(literal.GetData()[i]);
   2620       }
   2621     }
   2622   }
   2623 }
   2624 
   2625 void MipsAssembler::ReserveJumpTableSpace() {
   2626   if (!jump_tables_.empty()) {
   2627     for (JumpTable& table : jump_tables_) {
   2628       MipsLabel* label = table.GetLabel();
   2629       Bind(label);
   2630 
   2631       // Bulk ensure capacity, as this may be large.
   2632       size_t orig_size = buffer_.Size();
   2633       size_t required_capacity = orig_size + table.GetSize();
   2634       if (required_capacity > buffer_.Capacity()) {
   2635         buffer_.ExtendCapacity(required_capacity);
   2636       }
   2637 #ifndef NDEBUG
   2638       buffer_.has_ensured_capacity_ = true;
   2639 #endif
   2640 
   2641       // Fill the space with dummy data as the data is not final
   2642       // until the branches have been promoted. And we shouldn't
   2643       // be moving uninitialized data during branch promotion.
   2644       for (size_t cnt = table.GetData().size(), i = 0; i < cnt; i++) {
   2645         buffer_.Emit<uint32_t>(0x1abe1234u);
   2646       }
   2647 
   2648 #ifndef NDEBUG
   2649       buffer_.has_ensured_capacity_ = false;
   2650 #endif
   2651     }
   2652   }
   2653 }
   2654 
   2655 void MipsAssembler::EmitJumpTables() {
   2656   if (!jump_tables_.empty()) {
   2657     CHECK(!overwriting_);
   2658     // Switch from appending instructions at the end of the buffer to overwriting
   2659     // existing instructions (here, jump tables) in the buffer.
   2660     overwriting_ = true;
   2661 
   2662     for (JumpTable& table : jump_tables_) {
   2663       MipsLabel* table_label = table.GetLabel();
   2664       uint32_t start = GetLabelLocation(table_label);
   2665       overwrite_location_ = start;
   2666 
   2667       for (MipsLabel* target : table.GetData()) {
   2668         CHECK_EQ(buffer_.Load<uint32_t>(overwrite_location_), 0x1abe1234u);
   2669         // The table will contain target addresses relative to the table start.
   2670         uint32_t offset = GetLabelLocation(target) - start;
   2671         Emit(offset);
   2672       }
   2673     }
   2674 
   2675     overwriting_ = false;
   2676   }
   2677 }
   2678 
   2679 void MipsAssembler::PromoteBranches() {
   2680   // Promote short branches to long as necessary.
   2681   bool changed;
   2682   do {
   2683     changed = false;
   2684     for (auto& branch : branches_) {
   2685       CHECK(branch.IsResolved());
   2686       uint32_t base = GetBranchLocationOrPcRelBase(&branch);
   2687       uint32_t delta = branch.PromoteIfNeeded(base);
   2688       // If this branch has been promoted and needs to expand in size,
   2689       // relocate all branches by the expansion size.
   2690       if (delta) {
   2691         changed = true;
   2692         uint32_t expand_location = branch.GetLocation();
   2693         for (auto& branch2 : branches_) {
   2694           branch2.Relocate(expand_location, delta);
   2695         }
   2696       }
   2697     }
   2698   } while (changed);
   2699 
   2700   // Account for branch expansion by resizing the code buffer
   2701   // and moving the code in it to its final location.
   2702   size_t branch_count = branches_.size();
   2703   if (branch_count > 0) {
   2704     // Resize.
   2705     Branch& last_branch = branches_[branch_count - 1];
   2706     uint32_t size_delta = last_branch.GetEndLocation() - last_branch.GetOldEndLocation();
   2707     uint32_t old_size = buffer_.Size();
   2708     buffer_.Resize(old_size + size_delta);
   2709     // Move the code residing between branch placeholders.
   2710     uint32_t end = old_size;
   2711     for (size_t i = branch_count; i > 0; ) {
   2712       Branch& branch = branches_[--i];
   2713       CHECK_GE(end, branch.GetOldEndLocation());
   2714       uint32_t size = end - branch.GetOldEndLocation();
   2715       buffer_.Move(branch.GetEndLocation(), branch.GetOldEndLocation(), size);
   2716       end = branch.GetOldLocation();
   2717     }
   2718   }
   2719 }
   2720 
   2721 // Note: make sure branch_info_[] and EmitBranch() are kept synchronized.
   2722 const MipsAssembler::Branch::BranchInfo MipsAssembler::Branch::branch_info_[] = {
   2723   // R2 short branches.
   2724   {  2, 0, 1, MipsAssembler::Branch::kOffset18, 2 },  // kUncondBranch
   2725   {  2, 0, 1, MipsAssembler::Branch::kOffset18, 2 },  // kCondBranch
   2726   {  2, 0, 1, MipsAssembler::Branch::kOffset18, 2 },  // kCall
   2727   // R2 near label.
   2728   {  1, 0, 0, MipsAssembler::Branch::kOffset16, 0 },  // kLabel
   2729   // R2 near literal.
   2730   {  1, 0, 0, MipsAssembler::Branch::kOffset16, 0 },  // kLiteral
   2731   // R2 long branches.
   2732   {  9, 3, 1, MipsAssembler::Branch::kOffset32, 0 },  // kLongUncondBranch
   2733   { 10, 4, 1, MipsAssembler::Branch::kOffset32, 0 },  // kLongCondBranch
   2734   {  6, 1, 1, MipsAssembler::Branch::kOffset32, 0 },  // kLongCall
   2735   // R2 far label.
   2736   {  3, 0, 0, MipsAssembler::Branch::kOffset32, 0 },  // kFarLabel
   2737   // R2 far literal.
   2738   {  3, 0, 0, MipsAssembler::Branch::kOffset32, 0 },  // kFarLiteral
   2739   // R6 short branches.
   2740   {  1, 0, 1, MipsAssembler::Branch::kOffset28, 2 },  // kR6UncondBranch
   2741   {  2, 0, 1, MipsAssembler::Branch::kOffset18, 2 },  // kR6CondBranch
   2742                                                       // Exception: kOffset23 for beqzc/bnezc.
   2743   {  1, 0, 1, MipsAssembler::Branch::kOffset28, 2 },  // kR6Call
   2744   // R6 near label.
   2745   {  1, 0, 0, MipsAssembler::Branch::kOffset21, 2 },  // kR6Label
   2746   // R6 near literal.
   2747   {  1, 0, 0, MipsAssembler::Branch::kOffset21, 2 },  // kR6Literal
   2748   // R6 long branches.
   2749   {  2, 0, 0, MipsAssembler::Branch::kOffset32, 0 },  // kR6LongUncondBranch
   2750   {  3, 1, 0, MipsAssembler::Branch::kOffset32, 0 },  // kR6LongCondBranch
   2751   {  2, 0, 0, MipsAssembler::Branch::kOffset32, 0 },  // kR6LongCall
   2752   // R6 far label.
   2753   {  2, 0, 0, MipsAssembler::Branch::kOffset32, 0 },  // kR6FarLabel
   2754   // R6 far literal.
   2755   {  2, 0, 0, MipsAssembler::Branch::kOffset32, 0 },  // kR6FarLiteral
   2756 };
   2757 
   2758 // Note: make sure branch_info_[] and EmitBranch() are kept synchronized.
   2759 void MipsAssembler::EmitBranch(MipsAssembler::Branch* branch) {
   2760   CHECK_EQ(overwriting_, true);
   2761   overwrite_location_ = branch->GetLocation();
   2762   uint32_t offset = branch->GetOffset(GetBranchOrPcRelBaseForEncoding(branch));
   2763   BranchCondition condition = branch->GetCondition();
   2764   Register lhs = branch->GetLeftRegister();
   2765   Register rhs = branch->GetRightRegister();
   2766   uint32_t delayed_instruction = branch->GetDelayedInstruction();
   2767   switch (branch->GetType()) {
   2768     // R2 short branches.
   2769     case Branch::kUncondBranch:
   2770       if (delayed_instruction == Branch::kUnfillableDelaySlot) {
   2771         // The branch was created when reordering was disabled, do not absorb the target
   2772         // instruction.
   2773         delayed_instruction = 0;  // NOP.
   2774       } else if (delayed_instruction == Branch::kUnfilledDelaySlot) {
   2775         // Try to absorb the target instruction into the delay slot.
   2776         delayed_instruction = 0;  // NOP.
   2777         // Incrementing the signed 16-bit offset past the target instruction must not
   2778         // cause overflow into the negative subrange, check for the max offset.
   2779         if (offset != 0x7FFF) {
   2780           uint32_t target = branch->GetTarget();
   2781           if (std::binary_search(ds_fsm_target_pcs_.begin(), ds_fsm_target_pcs_.end(), target)) {
   2782             delayed_instruction = buffer_.Load<uint32_t>(target);
   2783             offset++;
   2784           }
   2785         }
   2786       }
   2787       CHECK_EQ(overwrite_location_, branch->GetOffsetLocation());
   2788       B(offset);
   2789       Emit(delayed_instruction);
   2790       break;
   2791     case Branch::kCondBranch:
   2792       DCHECK_NE(delayed_instruction, Branch::kUnfillableDelaySlot);
   2793       if (delayed_instruction == Branch::kUnfilledDelaySlot) {
   2794         delayed_instruction = 0;  // NOP.
   2795       }
   2796       CHECK_EQ(overwrite_location_, branch->GetOffsetLocation());
   2797       EmitBcondR2(condition, lhs, rhs, offset);
   2798       Emit(delayed_instruction);
   2799       break;
   2800     case Branch::kCall:
   2801       DCHECK_NE(delayed_instruction, Branch::kUnfillableDelaySlot);
   2802       if (delayed_instruction == Branch::kUnfilledDelaySlot) {
   2803         delayed_instruction = 0;  // NOP.
   2804       }
   2805       CHECK_EQ(overwrite_location_, branch->GetOffsetLocation());
   2806       Bal(offset);
   2807       Emit(delayed_instruction);
   2808       break;
   2809 
   2810     // R2 near label.
   2811     case Branch::kLabel:
   2812       DCHECK_EQ(delayed_instruction, Branch::kUnfilledDelaySlot);
   2813       CHECK_EQ(overwrite_location_, branch->GetOffsetLocation());
   2814       Addiu(lhs, rhs, offset);
   2815       break;
   2816     // R2 near literal.
   2817     case Branch::kLiteral:
   2818       DCHECK_EQ(delayed_instruction, Branch::kUnfilledDelaySlot);
   2819       CHECK_EQ(overwrite_location_, branch->GetOffsetLocation());
   2820       Lw(lhs, rhs, offset);
   2821       break;
   2822 
   2823     // R2 long branches.
   2824     case Branch::kLongUncondBranch:
   2825       // To get the value of the PC register we need to use the NAL instruction.
   2826       // NAL clobbers the RA register. However, RA must be preserved if the
   2827       // method is compiled without the entry/exit sequences that would take care
   2828       // of preserving RA (typically, leaf methods don't preserve RA explicitly).
   2829       // So, we need to preserve RA in some temporary storage ourselves. The AT
   2830       // register can't be used for this because we need it to load a constant
   2831       // which will be added to the value that NAL stores in RA. And we can't
   2832       // use T9 for this in the context of the JNI compiler, which uses it
   2833       // as a scratch register (see InterproceduralScratchRegister()).
   2834       // If we were to add a 32-bit constant to RA using two ADDIU instructions,
   2835       // we'd also need to use the ROTR instruction, which requires no less than
   2836       // MIPSR2.
   2837       // Perhaps, we could use T8 or one of R2's multiplier/divider registers
   2838       // (LO or HI) or even a floating-point register, but that doesn't seem
   2839       // like a nice solution. We may want this to work on both R6 and pre-R6.
   2840       // For now simply use the stack for RA. This should be OK since for the
   2841       // vast majority of code a short PC-relative branch is sufficient.
   2842       // TODO: can this be improved?
   2843       // TODO: consider generation of a shorter sequence when we know that RA
   2844       // is explicitly preserved by the method entry/exit code.
   2845       if (delayed_instruction != Branch::kUnfilledDelaySlot &&
   2846           delayed_instruction != Branch::kUnfillableDelaySlot) {
   2847         Emit(delayed_instruction);
   2848       }
   2849       Push(RA);
   2850       Nal();
   2851       CHECK_EQ(overwrite_location_, branch->GetOffsetLocation());
   2852       Lui(AT, High16Bits(offset));
   2853       Ori(AT, AT, Low16Bits(offset));
   2854       Addu(AT, AT, RA);
   2855       Lw(RA, SP, 0);
   2856       Jr(AT);
   2857       DecreaseFrameSize(kMipsWordSize);
   2858       break;
   2859     case Branch::kLongCondBranch:
   2860       // The comment on case 'Branch::kLongUncondBranch' applies here as well.
   2861       DCHECK_NE(delayed_instruction, Branch::kUnfillableDelaySlot);
   2862       if (delayed_instruction != Branch::kUnfilledDelaySlot) {
   2863         Emit(delayed_instruction);
   2864       }
   2865       // Note: the opposite condition branch encodes 8 as the distance, which is equal to the
   2866       // number of instructions skipped:
   2867       // (PUSH(IncreaseFrameSize(ADDIU) + SW) + NAL + LUI + ORI + ADDU + LW + JR).
   2868       EmitBcondR2(Branch::OppositeCondition(condition), lhs, rhs, 8);
   2869       Push(RA);
   2870       Nal();
   2871       CHECK_EQ(overwrite_location_, branch->GetOffsetLocation());
   2872       Lui(AT, High16Bits(offset));
   2873       Ori(AT, AT, Low16Bits(offset));
   2874       Addu(AT, AT, RA);
   2875       Lw(RA, SP, 0);
   2876       Jr(AT);
   2877       DecreaseFrameSize(kMipsWordSize);
   2878       break;
   2879     case Branch::kLongCall:
   2880       DCHECK_NE(delayed_instruction, Branch::kUnfillableDelaySlot);
   2881       if (delayed_instruction != Branch::kUnfilledDelaySlot) {
   2882         Emit(delayed_instruction);
   2883       }
   2884       Nal();
   2885       CHECK_EQ(overwrite_location_, branch->GetOffsetLocation());
   2886       Lui(AT, High16Bits(offset));
   2887       Ori(AT, AT, Low16Bits(offset));
   2888       Addu(AT, AT, RA);
   2889       Jalr(AT);
   2890       Nop();
   2891       break;
   2892 
   2893     // R2 far label.
   2894     case Branch::kFarLabel:
   2895       DCHECK_EQ(delayed_instruction, Branch::kUnfilledDelaySlot);
   2896       CHECK_EQ(overwrite_location_, branch->GetOffsetLocation());
   2897       Lui(AT, High16Bits(offset));
   2898       Ori(AT, AT, Low16Bits(offset));
   2899       Addu(lhs, AT, rhs);
   2900       break;
   2901     // R2 far literal.
   2902     case Branch::kFarLiteral:
   2903       DCHECK_EQ(delayed_instruction, Branch::kUnfilledDelaySlot);
   2904       offset += (offset & 0x8000) << 1;  // Account for sign extension in lw.
   2905       CHECK_EQ(overwrite_location_, branch->GetOffsetLocation());
   2906       Lui(AT, High16Bits(offset));
   2907       Addu(AT, AT, rhs);
   2908       Lw(lhs, AT, Low16Bits(offset));
   2909       break;
   2910 
   2911     // R6 short branches.
   2912     case Branch::kR6UncondBranch:
   2913       DCHECK_EQ(delayed_instruction, Branch::kUnfilledDelaySlot);
   2914       CHECK_EQ(overwrite_location_, branch->GetOffsetLocation());
   2915       Bc(offset);
   2916       break;
   2917     case Branch::kR6CondBranch:
   2918       CHECK_EQ(overwrite_location_, branch->GetOffsetLocation());
   2919       EmitBcondR6(condition, lhs, rhs, offset);
   2920       DCHECK_NE(delayed_instruction, Branch::kUnfillableDelaySlot);
   2921       if (delayed_instruction != Branch::kUnfilledDelaySlot) {
   2922         Emit(delayed_instruction);
   2923       } else {
   2924         // TODO: improve by filling the forbidden slot (IFF this is
   2925         // a forbidden and not a delay slot).
   2926         Nop();
   2927       }
   2928       break;
   2929     case Branch::kR6Call:
   2930       DCHECK_EQ(delayed_instruction, Branch::kUnfilledDelaySlot);
   2931       CHECK_EQ(overwrite_location_, branch->GetOffsetLocation());
   2932       Balc(offset);
   2933       break;
   2934 
   2935     // R6 near label.
   2936     case Branch::kR6Label:
   2937       DCHECK_EQ(delayed_instruction, Branch::kUnfilledDelaySlot);
   2938       CHECK_EQ(overwrite_location_, branch->GetOffsetLocation());
   2939       Addiupc(lhs, offset);
   2940       break;
   2941     // R6 near literal.
   2942     case Branch::kR6Literal:
   2943       DCHECK_EQ(delayed_instruction, Branch::kUnfilledDelaySlot);
   2944       CHECK_EQ(overwrite_location_, branch->GetOffsetLocation());
   2945       Lwpc(lhs, offset);
   2946       break;
   2947 
   2948     // R6 long branches.
   2949     case Branch::kR6LongUncondBranch:
   2950       DCHECK_EQ(delayed_instruction, Branch::kUnfilledDelaySlot);
   2951       offset += (offset & 0x8000) << 1;  // Account for sign extension in jic.
   2952       CHECK_EQ(overwrite_location_, branch->GetOffsetLocation());
   2953       Auipc(AT, High16Bits(offset));
   2954       Jic(AT, Low16Bits(offset));
   2955       break;
   2956     case Branch::kR6LongCondBranch:
   2957       DCHECK_NE(delayed_instruction, Branch::kUnfillableDelaySlot);
   2958       if (delayed_instruction != Branch::kUnfilledDelaySlot) {
   2959         Emit(delayed_instruction);
   2960       }
   2961       EmitBcondR6(Branch::OppositeCondition(condition), lhs, rhs, 2);
   2962       offset += (offset & 0x8000) << 1;  // Account for sign extension in jic.
   2963       CHECK_EQ(overwrite_location_, branch->GetOffsetLocation());
   2964       Auipc(AT, High16Bits(offset));
   2965       Jic(AT, Low16Bits(offset));
   2966       break;
   2967     case Branch::kR6LongCall:
   2968       DCHECK_EQ(delayed_instruction, Branch::kUnfilledDelaySlot);
   2969       offset += (offset & 0x8000) << 1;  // Account for sign extension in jialc.
   2970       CHECK_EQ(overwrite_location_, branch->GetOffsetLocation());
   2971       Auipc(AT, High16Bits(offset));
   2972       Jialc(AT, Low16Bits(offset));
   2973       break;
   2974 
   2975     // R6 far label.
   2976     case Branch::kR6FarLabel:
   2977       DCHECK_EQ(delayed_instruction, Branch::kUnfilledDelaySlot);
   2978       offset += (offset & 0x8000) << 1;  // Account for sign extension in addiu.
   2979       CHECK_EQ(overwrite_location_, branch->GetOffsetLocation());
   2980       Auipc(AT, High16Bits(offset));
   2981       Addiu(lhs, AT, Low16Bits(offset));
   2982       break;
   2983     // R6 far literal.
   2984     case Branch::kR6FarLiteral:
   2985       DCHECK_EQ(delayed_instruction, Branch::kUnfilledDelaySlot);
   2986       offset += (offset & 0x8000) << 1;  // Account for sign extension in lw.
   2987       CHECK_EQ(overwrite_location_, branch->GetOffsetLocation());
   2988       Auipc(AT, High16Bits(offset));
   2989       Lw(lhs, AT, Low16Bits(offset));
   2990       break;
   2991   }
   2992   CHECK_EQ(overwrite_location_, branch->GetEndLocation());
   2993   CHECK_LT(branch->GetSize(), static_cast<uint32_t>(Branch::kMaxBranchSize));
   2994 }
   2995 
   2996 void MipsAssembler::B(MipsLabel* label) {
   2997   Buncond(label);
   2998 }
   2999 
   3000 void MipsAssembler::Bal(MipsLabel* label) {
   3001   Call(label);
   3002 }
   3003 
   3004 void MipsAssembler::Beq(Register rs, Register rt, MipsLabel* label) {
   3005   Bcond(label, kCondEQ, rs, rt);
   3006 }
   3007 
   3008 void MipsAssembler::Bne(Register rs, Register rt, MipsLabel* label) {
   3009   Bcond(label, kCondNE, rs, rt);
   3010 }
   3011 
   3012 void MipsAssembler::Beqz(Register rt, MipsLabel* label) {
   3013   Bcond(label, kCondEQZ, rt);
   3014 }
   3015 
   3016 void MipsAssembler::Bnez(Register rt, MipsLabel* label) {
   3017   Bcond(label, kCondNEZ, rt);
   3018 }
   3019 
   3020 void MipsAssembler::Bltz(Register rt, MipsLabel* label) {
   3021   Bcond(label, kCondLTZ, rt);
   3022 }
   3023 
   3024 void MipsAssembler::Bgez(Register rt, MipsLabel* label) {
   3025   Bcond(label, kCondGEZ, rt);
   3026 }
   3027 
   3028 void MipsAssembler::Blez(Register rt, MipsLabel* label) {
   3029   Bcond(label, kCondLEZ, rt);
   3030 }
   3031 
   3032 void MipsAssembler::Bgtz(Register rt, MipsLabel* label) {
   3033   Bcond(label, kCondGTZ, rt);
   3034 }
   3035 
   3036 bool MipsAssembler::CanExchangeWithSlt(Register rs, Register rt) const {
   3037   // If the instruction modifies AT, `rs` or `rt`, it can't be exchanged with the slt[u]
   3038   // instruction because either slt[u] depends on `rs` or `rt` or the following
   3039   // conditional branch depends on AT set by slt[u].
   3040   // Likewise, if the instruction depends on AT, it can't be exchanged with slt[u]
   3041   // because slt[u] changes AT.
   3042   return (delay_slot_.instruction_ != 0 &&
   3043       (delay_slot_.gpr_outs_mask_ & ((1u << AT) | (1u << rs) | (1u << rt))) == 0 &&
   3044       (delay_slot_.gpr_ins_mask_ & (1u << AT)) == 0);
   3045 }
   3046 
   3047 void MipsAssembler::ExchangeWithSlt(const DelaySlot& forwarded_slot) {
   3048   // Exchange the last two instructions in the assembler buffer.
   3049   size_t size = buffer_.Size();
   3050   CHECK_GE(size, 2 * sizeof(uint32_t));
   3051   size_t pos1 = size - 2 * sizeof(uint32_t);
   3052   size_t pos2 = size - sizeof(uint32_t);
   3053   uint32_t instr1 = buffer_.Load<uint32_t>(pos1);
   3054   uint32_t instr2 = buffer_.Load<uint32_t>(pos2);
   3055   CHECK_EQ(instr1, forwarded_slot.instruction_);
   3056   CHECK_EQ(instr2, delay_slot_.instruction_);
   3057   buffer_.Store<uint32_t>(pos1, instr2);
   3058   buffer_.Store<uint32_t>(pos2, instr1);
   3059   // Set the current delay slot information to that of the last instruction
   3060   // in the buffer.
   3061   delay_slot_ = forwarded_slot;
   3062 }
   3063 
   3064 void MipsAssembler::GenerateSltForCondBranch(bool unsigned_slt, Register rs, Register rt) {
   3065   // If possible, exchange the slt[u] instruction with the preceding instruction,
   3066   // so it can fill the delay slot.
   3067   DelaySlot forwarded_slot = delay_slot_;
   3068   bool exchange = CanExchangeWithSlt(rs, rt);
   3069   if (exchange) {
   3070     // The last instruction cannot be used in a different delay slot,
   3071     // do not commit the label before it (if any).
   3072     DsFsmDropLabel();
   3073   }
   3074   if (unsigned_slt) {
   3075     Sltu(AT, rs, rt);
   3076   } else {
   3077     Slt(AT, rs, rt);
   3078   }
   3079   if (exchange) {
   3080     ExchangeWithSlt(forwarded_slot);
   3081   }
   3082 }
   3083 
   3084 void MipsAssembler::Blt(Register rs, Register rt, MipsLabel* label) {
   3085   if (IsR6()) {
   3086     Bcond(label, kCondLT, rs, rt);
   3087   } else if (!Branch::IsNop(kCondLT, rs, rt)) {
   3088     // Synthesize the instruction (not available on R2).
   3089     GenerateSltForCondBranch(/* unsigned_slt */ false, rs, rt);
   3090     Bnez(AT, label);
   3091   }
   3092 }
   3093 
   3094 void MipsAssembler::Bge(Register rs, Register rt, MipsLabel* label) {
   3095   if (IsR6()) {
   3096     Bcond(label, kCondGE, rs, rt);
   3097   } else if (Branch::IsUncond(kCondGE, rs, rt)) {
   3098     B(label);
   3099   } else {
   3100     // Synthesize the instruction (not available on R2).
   3101     GenerateSltForCondBranch(/* unsigned_slt */ false, rs, rt);
   3102     Beqz(AT, label);
   3103   }
   3104 }
   3105 
   3106 void MipsAssembler::Bltu(Register rs, Register rt, MipsLabel* label) {
   3107   if (IsR6()) {
   3108     Bcond(label, kCondLTU, rs, rt);
   3109   } else if (!Branch::IsNop(kCondLTU, rs, rt)) {
   3110     // Synthesize the instruction (not available on R2).
   3111     GenerateSltForCondBranch(/* unsigned_slt */ true, rs, rt);
   3112     Bnez(AT, label);
   3113   }
   3114 }
   3115 
   3116 void MipsAssembler::Bgeu(Register rs, Register rt, MipsLabel* label) {
   3117   if (IsR6()) {
   3118     Bcond(label, kCondGEU, rs, rt);
   3119   } else if (Branch::IsUncond(kCondGEU, rs, rt)) {
   3120     B(label);
   3121   } else {
   3122     // Synthesize the instruction (not available on R2).
   3123     GenerateSltForCondBranch(/* unsigned_slt */ true, rs, rt);
   3124     Beqz(AT, label);
   3125   }
   3126 }
   3127 
   3128 void MipsAssembler::Bc1f(MipsLabel* label) {
   3129   Bc1f(0, label);
   3130 }
   3131 
   3132 void MipsAssembler::Bc1f(int cc, MipsLabel* label) {
   3133   CHECK(IsUint<3>(cc)) << cc;
   3134   Bcond(label, kCondF, static_cast<Register>(cc), ZERO);
   3135 }
   3136 
   3137 void MipsAssembler::Bc1t(MipsLabel* label) {
   3138   Bc1t(0, label);
   3139 }
   3140 
   3141 void MipsAssembler::Bc1t(int cc, MipsLabel* label) {
   3142   CHECK(IsUint<3>(cc)) << cc;
   3143   Bcond(label, kCondT, static_cast<Register>(cc), ZERO);
   3144 }
   3145 
   3146 void MipsAssembler::Bc1eqz(FRegister ft, MipsLabel* label) {
   3147   Bcond(label, kCondF, static_cast<Register>(ft), ZERO);
   3148 }
   3149 
   3150 void MipsAssembler::Bc1nez(FRegister ft, MipsLabel* label) {
   3151   Bcond(label, kCondT, static_cast<Register>(ft), ZERO);
   3152 }
   3153 
   3154 void MipsAssembler::AdjustBaseAndOffset(Register& base,
   3155                                         int32_t& offset,
   3156                                         bool is_doubleword,
   3157                                         bool is_float) {
   3158   // This method is used to adjust the base register and offset pair
   3159   // for a load/store when the offset doesn't fit into int16_t.
   3160   // It is assumed that `base + offset` is sufficiently aligned for memory
   3161   // operands that are machine word in size or smaller. For doubleword-sized
   3162   // operands it's assumed that `base` is a multiple of 8, while `offset`
   3163   // may be a multiple of 4 (e.g. 4-byte-aligned long and double arguments
   3164   // and spilled variables on the stack accessed relative to the stack
   3165   // pointer register).
   3166   // We preserve the "alignment" of `offset` by adjusting it by a multiple of 8.
   3167   CHECK_NE(base, AT);  // Must not overwrite the register `base` while loading `offset`.
   3168 
   3169   bool doubleword_aligned = IsAligned<kMipsDoublewordSize>(offset);
   3170   bool two_accesses = is_doubleword && (!is_float || !doubleword_aligned);
   3171 
   3172   // IsInt<16> must be passed a signed value, hence the static cast below.
   3173   if (IsInt<16>(offset) &&
   3174       (!two_accesses || IsInt<16>(static_cast<int32_t>(offset + kMipsWordSize)))) {
   3175     // Nothing to do: `offset` (and, if needed, `offset + 4`) fits into int16_t.
   3176     return;
   3177   }
   3178 
   3179   // Remember the "(mis)alignment" of `offset`, it will be checked at the end.
   3180   uint32_t misalignment = offset & (kMipsDoublewordSize - 1);
   3181 
   3182   // Do not load the whole 32-bit `offset` if it can be represented as
   3183   // a sum of two 16-bit signed offsets. This can save an instruction or two.
   3184   // To simplify matters, only do this for a symmetric range of offsets from
   3185   // about -64KB to about +64KB, allowing further addition of 4 when accessing
   3186   // 64-bit variables with two 32-bit accesses.
   3187   constexpr int32_t kMinOffsetForSimpleAdjustment = 0x7ff8;  // Max int16_t that's a multiple of 8.
   3188   constexpr int32_t kMaxOffsetForSimpleAdjustment = 2 * kMinOffsetForSimpleAdjustment;
   3189   if (0 <= offset && offset <= kMaxOffsetForSimpleAdjustment) {
   3190     Addiu(AT, base, kMinOffsetForSimpleAdjustment);
   3191     offset -= kMinOffsetForSimpleAdjustment;
   3192   } else if (-kMaxOffsetForSimpleAdjustment <= offset && offset < 0) {
   3193     Addiu(AT, base, -kMinOffsetForSimpleAdjustment);
   3194     offset += kMinOffsetForSimpleAdjustment;
   3195   } else if (IsR6()) {
   3196     // On R6 take advantage of the aui instruction, e.g.:
   3197     //   aui   AT, base, offset_high
   3198     //   lw    reg_lo, offset_low(AT)
   3199     //   lw    reg_hi, (offset_low+4)(AT)
   3200     // or when offset_low+4 overflows int16_t:
   3201     //   aui   AT, base, offset_high
   3202     //   addiu AT, AT, 8
   3203     //   lw    reg_lo, (offset_low-8)(AT)
   3204     //   lw    reg_hi, (offset_low-4)(AT)
   3205     int16_t offset_high = High16Bits(offset);
   3206     int16_t offset_low = Low16Bits(offset);
   3207     offset_high += (offset_low < 0) ? 1 : 0;  // Account for offset sign extension in load/store.
   3208     Aui(AT, base, offset_high);
   3209     if (two_accesses && !IsInt<16>(static_cast<int32_t>(offset_low + kMipsWordSize))) {
   3210       // Avoid overflow in the 16-bit offset of the load/store instruction when adding 4.
   3211       Addiu(AT, AT, kMipsDoublewordSize);
   3212       offset_low -= kMipsDoublewordSize;
   3213     }
   3214     offset = offset_low;
   3215   } else {
   3216     // Do not load the whole 32-bit `offset` if it can be represented as
   3217     // a sum of three 16-bit signed offsets. This can save an instruction.
   3218     // To simplify matters, only do this for a symmetric range of offsets from
   3219     // about -96KB to about +96KB, allowing further addition of 4 when accessing
   3220     // 64-bit variables with two 32-bit accesses.
   3221     constexpr int32_t kMinOffsetForMediumAdjustment = 2 * kMinOffsetForSimpleAdjustment;
   3222     constexpr int32_t kMaxOffsetForMediumAdjustment = 3 * kMinOffsetForSimpleAdjustment;
   3223     if (0 <= offset && offset <= kMaxOffsetForMediumAdjustment) {
   3224       Addiu(AT, base, kMinOffsetForMediumAdjustment / 2);
   3225       Addiu(AT, AT, kMinOffsetForMediumAdjustment / 2);
   3226       offset -= kMinOffsetForMediumAdjustment;
   3227     } else if (-kMaxOffsetForMediumAdjustment <= offset && offset < 0) {
   3228       Addiu(AT, base, -kMinOffsetForMediumAdjustment / 2);
   3229       Addiu(AT, AT, -kMinOffsetForMediumAdjustment / 2);
   3230       offset += kMinOffsetForMediumAdjustment;
   3231     } else {
   3232       // Now that all shorter options have been exhausted, load the full 32-bit offset.
   3233       int32_t loaded_offset = RoundDown(offset, kMipsDoublewordSize);
   3234       LoadConst32(AT, loaded_offset);
   3235       Addu(AT, AT, base);
   3236       offset -= loaded_offset;
   3237     }
   3238   }
   3239   base = AT;
   3240 
   3241   CHECK(IsInt<16>(offset));
   3242   if (two_accesses) {
   3243     CHECK(IsInt<16>(static_cast<int32_t>(offset + kMipsWordSize)));
   3244   }
   3245   CHECK_EQ(misalignment, offset & (kMipsDoublewordSize - 1));
   3246 }
   3247 
   3248 void MipsAssembler::LoadFromOffset(LoadOperandType type,
   3249                                    Register reg,
   3250                                    Register base,
   3251                                    int32_t offset) {
   3252   LoadFromOffset<>(type, reg, base, offset);
   3253 }
   3254 
   3255 void MipsAssembler::LoadSFromOffset(FRegister reg, Register base, int32_t offset) {
   3256   LoadSFromOffset<>(reg, base, offset);
   3257 }
   3258 
   3259 void MipsAssembler::LoadDFromOffset(FRegister reg, Register base, int32_t offset) {
   3260   LoadDFromOffset<>(reg, base, offset);
   3261 }
   3262 
   3263 void MipsAssembler::EmitLoad(ManagedRegister m_dst, Register src_register, int32_t src_offset,
   3264                              size_t size) {
   3265   MipsManagedRegister dst = m_dst.AsMips();
   3266   if (dst.IsNoRegister()) {
   3267     CHECK_EQ(0u, size) << dst;
   3268   } else if (dst.IsCoreRegister()) {
   3269     CHECK_EQ(kMipsWordSize, size) << dst;
   3270     LoadFromOffset(kLoadWord, dst.AsCoreRegister(), src_register, src_offset);
   3271   } else if (dst.IsRegisterPair()) {
   3272     CHECK_EQ(kMipsDoublewordSize, size) << dst;
   3273     LoadFromOffset(kLoadDoubleword, dst.AsRegisterPairLow(), src_register, src_offset);
   3274   } else if (dst.IsFRegister()) {
   3275     if (size == kMipsWordSize) {
   3276       LoadSFromOffset(dst.AsFRegister(), src_register, src_offset);
   3277     } else {
   3278       CHECK_EQ(kMipsDoublewordSize, size) << dst;
   3279       LoadDFromOffset(dst.AsFRegister(), src_register, src_offset);
   3280     }
   3281   } else if (dst.IsDRegister()) {
   3282     CHECK_EQ(kMipsDoublewordSize, size) << dst;
   3283     LoadDFromOffset(dst.AsOverlappingDRegisterLow(), src_register, src_offset);
   3284   }
   3285 }
   3286 
   3287 void MipsAssembler::StoreToOffset(StoreOperandType type,
   3288                                   Register reg,
   3289                                   Register base,
   3290                                   int32_t offset) {
   3291   StoreToOffset<>(type, reg, base, offset);
   3292 }
   3293 
   3294 void MipsAssembler::StoreSToOffset(FRegister reg, Register base, int32_t offset) {
   3295   StoreSToOffset<>(reg, base, offset);
   3296 }
   3297 
   3298 void MipsAssembler::StoreDToOffset(FRegister reg, Register base, int32_t offset) {
   3299   StoreDToOffset<>(reg, base, offset);
   3300 }
   3301 
   3302 static dwarf::Reg DWARFReg(Register reg) {
   3303   return dwarf::Reg::MipsCore(static_cast<int>(reg));
   3304 }
   3305 
   3306 constexpr size_t kFramePointerSize = 4;
   3307 
   3308 void MipsAssembler::BuildFrame(size_t frame_size,
   3309                                ManagedRegister method_reg,
   3310                                ArrayRef<const ManagedRegister> callee_save_regs,
   3311                                const ManagedRegisterEntrySpills& entry_spills) {
   3312   CHECK_ALIGNED(frame_size, kStackAlignment);
   3313   DCHECK(!overwriting_);
   3314 
   3315   // Increase frame to required size.
   3316   IncreaseFrameSize(frame_size);
   3317 
   3318   // Push callee saves and return address.
   3319   int stack_offset = frame_size - kFramePointerSize;
   3320   StoreToOffset(kStoreWord, RA, SP, stack_offset);
   3321   cfi_.RelOffset(DWARFReg(RA), stack_offset);
   3322   for (int i = callee_save_regs.size() - 1; i >= 0; --i) {
   3323     stack_offset -= kFramePointerSize;
   3324     Register reg = callee_save_regs[i].AsMips().AsCoreRegister();
   3325     StoreToOffset(kStoreWord, reg, SP, stack_offset);
   3326     cfi_.RelOffset(DWARFReg(reg), stack_offset);
   3327   }
   3328 
   3329   // Write out Method*.
   3330   StoreToOffset(kStoreWord, method_reg.AsMips().AsCoreRegister(), SP, 0);
   3331 
   3332   // Write out entry spills.
   3333   int32_t offset = frame_size + kFramePointerSize;
   3334   for (size_t i = 0; i < entry_spills.size(); ++i) {
   3335     MipsManagedRegister reg = entry_spills.at(i).AsMips();
   3336     if (reg.IsNoRegister()) {
   3337       ManagedRegisterSpill spill = entry_spills.at(i);
   3338       offset += spill.getSize();
   3339     } else if (reg.IsCoreRegister()) {
   3340       StoreToOffset(kStoreWord, reg.AsCoreRegister(), SP, offset);
   3341       offset += kMipsWordSize;
   3342     } else if (reg.IsFRegister()) {
   3343       StoreSToOffset(reg.AsFRegister(), SP, offset);
   3344       offset += kMipsWordSize;
   3345     } else if (reg.IsDRegister()) {
   3346       StoreDToOffset(reg.AsOverlappingDRegisterLow(), SP, offset);
   3347       offset += kMipsDoublewordSize;
   3348     }
   3349   }
   3350 }
   3351 
   3352 void MipsAssembler::RemoveFrame(size_t frame_size,
   3353                                 ArrayRef<const ManagedRegister> callee_save_regs) {
   3354   CHECK_ALIGNED(frame_size, kStackAlignment);
   3355   DCHECK(!overwriting_);
   3356   cfi_.RememberState();
   3357 
   3358   // Pop callee saves and return address.
   3359   int stack_offset = frame_size - (callee_save_regs.size() * kFramePointerSize) - kFramePointerSize;
   3360   for (size_t i = 0; i < callee_save_regs.size(); ++i) {
   3361     Register reg = callee_save_regs[i].AsMips().AsCoreRegister();
   3362     LoadFromOffset(kLoadWord, reg, SP, stack_offset);
   3363     cfi_.Restore(DWARFReg(reg));
   3364     stack_offset += kFramePointerSize;
   3365   }
   3366   LoadFromOffset(kLoadWord, RA, SP, stack_offset);
   3367   cfi_.Restore(DWARFReg(RA));
   3368 
   3369   // Adjust the stack pointer in the delay slot if doing so doesn't break CFI.
   3370   bool exchange = IsInt<16>(static_cast<int32_t>(frame_size));
   3371   bool reordering = SetReorder(false);
   3372   if (exchange) {
   3373     // Jump to the return address.
   3374     Jr(RA);
   3375     // Decrease frame to required size.
   3376     DecreaseFrameSize(frame_size);  // Single instruction in delay slot.
   3377   } else {
   3378     // Decrease frame to required size.
   3379     DecreaseFrameSize(frame_size);
   3380     // Jump to the return address.
   3381     Jr(RA);
   3382     Nop();  // In delay slot.
   3383   }
   3384   SetReorder(reordering);
   3385 
   3386   // The CFI should be restored for any code that follows the exit block.
   3387   cfi_.RestoreState();
   3388   cfi_.DefCFAOffset(frame_size);
   3389 }
   3390 
   3391 void MipsAssembler::IncreaseFrameSize(size_t adjust) {
   3392   CHECK_ALIGNED(adjust, kFramePointerSize);
   3393   Addiu32(SP, SP, -adjust);
   3394   cfi_.AdjustCFAOffset(adjust);
   3395   if (overwriting_) {
   3396     cfi_.OverrideDelayedPC(overwrite_location_);
   3397   }
   3398 }
   3399 
   3400 void MipsAssembler::DecreaseFrameSize(size_t adjust) {
   3401   CHECK_ALIGNED(adjust, kFramePointerSize);
   3402   Addiu32(SP, SP, adjust);
   3403   cfi_.AdjustCFAOffset(-adjust);
   3404   if (overwriting_) {
   3405     cfi_.OverrideDelayedPC(overwrite_location_);
   3406   }
   3407 }
   3408 
   3409 void MipsAssembler::Store(FrameOffset dest, ManagedRegister msrc, size_t size) {
   3410   MipsManagedRegister src = msrc.AsMips();
   3411   if (src.IsNoRegister()) {
   3412     CHECK_EQ(0u, size);
   3413   } else if (src.IsCoreRegister()) {
   3414     CHECK_EQ(kMipsWordSize, size);
   3415     StoreToOffset(kStoreWord, src.AsCoreRegister(), SP, dest.Int32Value());
   3416   } else if (src.IsRegisterPair()) {
   3417     CHECK_EQ(kMipsDoublewordSize, size);
   3418     StoreToOffset(kStoreWord, src.AsRegisterPairLow(), SP, dest.Int32Value());
   3419     StoreToOffset(kStoreWord, src.AsRegisterPairHigh(),
   3420                   SP, dest.Int32Value() + kMipsWordSize);
   3421   } else if (src.IsFRegister()) {
   3422     if (size == kMipsWordSize) {
   3423       StoreSToOffset(src.AsFRegister(), SP, dest.Int32Value());
   3424     } else {
   3425       CHECK_EQ(kMipsDoublewordSize, size);
   3426       StoreDToOffset(src.AsFRegister(), SP, dest.Int32Value());
   3427     }
   3428   } else if (src.IsDRegister()) {
   3429     CHECK_EQ(kMipsDoublewordSize, size);
   3430     StoreDToOffset(src.AsOverlappingDRegisterLow(), SP, dest.Int32Value());
   3431   }
   3432 }
   3433 
   3434 void MipsAssembler::StoreRef(FrameOffset dest, ManagedRegister msrc) {
   3435   MipsManagedRegister src = msrc.AsMips();
   3436   CHECK(src.IsCoreRegister());
   3437   StoreToOffset(kStoreWord, src.AsCoreRegister(), SP, dest.Int32Value());
   3438 }
   3439 
   3440 void MipsAssembler::StoreRawPtr(FrameOffset dest, ManagedRegister msrc) {
   3441   MipsManagedRegister src = msrc.AsMips();
   3442   CHECK(src.IsCoreRegister());
   3443   StoreToOffset(kStoreWord, src.AsCoreRegister(), SP, dest.Int32Value());
   3444 }
   3445 
   3446 void MipsAssembler::StoreImmediateToFrame(FrameOffset dest, uint32_t imm,
   3447                                           ManagedRegister mscratch) {
   3448   MipsManagedRegister scratch = mscratch.AsMips();
   3449   CHECK(scratch.IsCoreRegister()) << scratch;
   3450   LoadConst32(scratch.AsCoreRegister(), imm);
   3451   StoreToOffset(kStoreWord, scratch.AsCoreRegister(), SP, dest.Int32Value());
   3452 }
   3453 
   3454 void MipsAssembler::StoreStackOffsetToThread(ThreadOffset32 thr_offs,
   3455                                              FrameOffset fr_offs,
   3456                                              ManagedRegister mscratch) {
   3457   MipsManagedRegister scratch = mscratch.AsMips();
   3458   CHECK(scratch.IsCoreRegister()) << scratch;
   3459   Addiu32(scratch.AsCoreRegister(), SP, fr_offs.Int32Value());
   3460   StoreToOffset(kStoreWord, scratch.AsCoreRegister(),
   3461                 S1, thr_offs.Int32Value());
   3462 }
   3463 
   3464 void MipsAssembler::StoreStackPointerToThread(ThreadOffset32 thr_offs) {
   3465   StoreToOffset(kStoreWord, SP, S1, thr_offs.Int32Value());
   3466 }
   3467 
   3468 void MipsAssembler::StoreSpanning(FrameOffset dest, ManagedRegister msrc,
   3469                                   FrameOffset in_off, ManagedRegister mscratch) {
   3470   MipsManagedRegister src = msrc.AsMips();
   3471   MipsManagedRegister scratch = mscratch.AsMips();
   3472   StoreToOffset(kStoreWord, src.AsCoreRegister(), SP, dest.Int32Value());
   3473   LoadFromOffset(kLoadWord, scratch.AsCoreRegister(), SP, in_off.Int32Value());
   3474   StoreToOffset(kStoreWord, scratch.AsCoreRegister(), SP, dest.Int32Value() + kMipsWordSize);
   3475 }
   3476 
   3477 void MipsAssembler::Load(ManagedRegister mdest, FrameOffset src, size_t size) {
   3478   return EmitLoad(mdest, SP, src.Int32Value(), size);
   3479 }
   3480 
   3481 void MipsAssembler::LoadFromThread(ManagedRegister mdest, ThreadOffset32 src, size_t size) {
   3482   return EmitLoad(mdest, S1, src.Int32Value(), size);
   3483 }
   3484 
   3485 void MipsAssembler::LoadRef(ManagedRegister mdest, FrameOffset src) {
   3486   MipsManagedRegister dest = mdest.AsMips();
   3487   CHECK(dest.IsCoreRegister());
   3488   LoadFromOffset(kLoadWord, dest.AsCoreRegister(), SP, src.Int32Value());
   3489 }
   3490 
   3491 void MipsAssembler::LoadRef(ManagedRegister mdest, ManagedRegister base, MemberOffset offs,
   3492                             bool unpoison_reference) {
   3493   MipsManagedRegister dest = mdest.AsMips();
   3494   CHECK(dest.IsCoreRegister() && base.AsMips().IsCoreRegister());
   3495   LoadFromOffset(kLoadWord, dest.AsCoreRegister(),
   3496                  base.AsMips().AsCoreRegister(), offs.Int32Value());
   3497   if (unpoison_reference) {
   3498     MaybeUnpoisonHeapReference(dest.AsCoreRegister());
   3499   }
   3500 }
   3501 
   3502 void MipsAssembler::LoadRawPtr(ManagedRegister mdest, ManagedRegister base, Offset offs) {
   3503   MipsManagedRegister dest = mdest.AsMips();
   3504   CHECK(dest.IsCoreRegister() && base.AsMips().IsCoreRegister());
   3505   LoadFromOffset(kLoadWord, dest.AsCoreRegister(),
   3506                  base.AsMips().AsCoreRegister(), offs.Int32Value());
   3507 }
   3508 
   3509 void MipsAssembler::LoadRawPtrFromThread(ManagedRegister mdest, ThreadOffset32 offs) {
   3510   MipsManagedRegister dest = mdest.AsMips();
   3511   CHECK(dest.IsCoreRegister());
   3512   LoadFromOffset(kLoadWord, dest.AsCoreRegister(), S1, offs.Int32Value());
   3513 }
   3514 
   3515 void MipsAssembler::SignExtend(ManagedRegister /*mreg*/, size_t /*size*/) {
   3516   UNIMPLEMENTED(FATAL) << "no sign extension necessary for mips";
   3517 }
   3518 
   3519 void MipsAssembler::ZeroExtend(ManagedRegister /*mreg*/, size_t /*size*/) {
   3520   UNIMPLEMENTED(FATAL) << "no zero extension necessary for mips";
   3521 }
   3522 
   3523 void MipsAssembler::Move(ManagedRegister mdest, ManagedRegister msrc, size_t size) {
   3524   MipsManagedRegister dest = mdest.AsMips();
   3525   MipsManagedRegister src = msrc.AsMips();
   3526   if (!dest.Equals(src)) {
   3527     if (dest.IsCoreRegister()) {
   3528       CHECK(src.IsCoreRegister()) << src;
   3529       Move(dest.AsCoreRegister(), src.AsCoreRegister());
   3530     } else if (dest.IsFRegister()) {
   3531       CHECK(src.IsFRegister()) << src;
   3532       if (size == kMipsWordSize) {
   3533         MovS(dest.AsFRegister(), src.AsFRegister());
   3534       } else {
   3535         CHECK_EQ(kMipsDoublewordSize, size);
   3536         MovD(dest.AsFRegister(), src.AsFRegister());
   3537       }
   3538     } else if (dest.IsDRegister()) {
   3539       CHECK(src.IsDRegister()) << src;
   3540       MovD(dest.AsOverlappingDRegisterLow(), src.AsOverlappingDRegisterLow());
   3541     } else {
   3542       CHECK(dest.IsRegisterPair()) << dest;
   3543       CHECK(src.IsRegisterPair()) << src;
   3544       // Ensure that the first move doesn't clobber the input of the second.
   3545       if (src.AsRegisterPairHigh() != dest.AsRegisterPairLow()) {
   3546         Move(dest.AsRegisterPairLow(), src.AsRegisterPairLow());
   3547         Move(dest.AsRegisterPairHigh(), src.AsRegisterPairHigh());
   3548       } else {
   3549         Move(dest.AsRegisterPairHigh(), src.AsRegisterPairHigh());
   3550         Move(dest.AsRegisterPairLow(), src.AsRegisterPairLow());
   3551       }
   3552     }
   3553   }
   3554 }
   3555 
   3556 void MipsAssembler::CopyRef(FrameOffset dest, FrameOffset src, ManagedRegister mscratch) {
   3557   MipsManagedRegister scratch = mscratch.AsMips();
   3558   CHECK(scratch.IsCoreRegister()) << scratch;
   3559   LoadFromOffset(kLoadWord, scratch.AsCoreRegister(), SP, src.Int32Value());
   3560   StoreToOffset(kStoreWord, scratch.AsCoreRegister(), SP, dest.Int32Value());
   3561 }
   3562 
   3563 void MipsAssembler::CopyRawPtrFromThread(FrameOffset fr_offs,
   3564                                          ThreadOffset32 thr_offs,
   3565                                          ManagedRegister mscratch) {
   3566   MipsManagedRegister scratch = mscratch.AsMips();
   3567   CHECK(scratch.IsCoreRegister()) << scratch;
   3568   LoadFromOffset(kLoadWord, scratch.AsCoreRegister(),
   3569                  S1, thr_offs.Int32Value());
   3570   StoreToOffset(kStoreWord, scratch.AsCoreRegister(),
   3571                 SP, fr_offs.Int32Value());
   3572 }
   3573 
   3574 void MipsAssembler::CopyRawPtrToThread(ThreadOffset32 thr_offs,
   3575                                        FrameOffset fr_offs,
   3576                                        ManagedRegister mscratch) {
   3577   MipsManagedRegister scratch = mscratch.AsMips();
   3578   CHECK(scratch.IsCoreRegister()) << scratch;
   3579   LoadFromOffset(kLoadWord, scratch.AsCoreRegister(),
   3580                  SP, fr_offs.Int32Value());
   3581   StoreToOffset(kStoreWord, scratch.AsCoreRegister(),
   3582                 S1, thr_offs.Int32Value());
   3583 }
   3584 
   3585 void MipsAssembler::Copy(FrameOffset dest, FrameOffset src, ManagedRegister mscratch, size_t size) {
   3586   MipsManagedRegister scratch = mscratch.AsMips();
   3587   CHECK(scratch.IsCoreRegister()) << scratch;
   3588   CHECK(size == kMipsWordSize || size == kMipsDoublewordSize) << size;
   3589   if (size == kMipsWordSize) {
   3590     LoadFromOffset(kLoadWord, scratch.AsCoreRegister(), SP, src.Int32Value());
   3591     StoreToOffset(kStoreWord, scratch.AsCoreRegister(), SP, dest.Int32Value());
   3592   } else if (size == kMipsDoublewordSize) {
   3593     LoadFromOffset(kLoadWord, scratch.AsCoreRegister(), SP, src.Int32Value());
   3594     StoreToOffset(kStoreWord, scratch.AsCoreRegister(), SP, dest.Int32Value());
   3595     LoadFromOffset(kLoadWord, scratch.AsCoreRegister(), SP, src.Int32Value() + kMipsWordSize);
   3596     StoreToOffset(kStoreWord, scratch.AsCoreRegister(), SP, dest.Int32Value() + kMipsWordSize);
   3597   }
   3598 }
   3599 
   3600 void MipsAssembler::Copy(FrameOffset dest, ManagedRegister src_base, Offset src_offset,
   3601                          ManagedRegister mscratch, size_t size) {
   3602   Register scratch = mscratch.AsMips().AsCoreRegister();
   3603   CHECK_EQ(size, kMipsWordSize);
   3604   LoadFromOffset(kLoadWord, scratch, src_base.AsMips().AsCoreRegister(), src_offset.Int32Value());
   3605   StoreToOffset(kStoreWord, scratch, SP, dest.Int32Value());
   3606 }
   3607 
   3608 void MipsAssembler::Copy(ManagedRegister dest_base, Offset dest_offset, FrameOffset src,
   3609                          ManagedRegister mscratch, size_t size) {
   3610   Register scratch = mscratch.AsMips().AsCoreRegister();
   3611   CHECK_EQ(size, kMipsWordSize);
   3612   LoadFromOffset(kLoadWord, scratch, SP, src.Int32Value());
   3613   StoreToOffset(kStoreWord, scratch, dest_base.AsMips().AsCoreRegister(), dest_offset.Int32Value());
   3614 }
   3615 
   3616 void MipsAssembler::Copy(FrameOffset dest ATTRIBUTE_UNUSED,
   3617                          FrameOffset src_base ATTRIBUTE_UNUSED,
   3618                          Offset src_offset ATTRIBUTE_UNUSED,
   3619                          ManagedRegister mscratch ATTRIBUTE_UNUSED,
   3620                          size_t size ATTRIBUTE_UNUSED) {
   3621   UNIMPLEMENTED(FATAL) << "no MIPS implementation";
   3622 }
   3623 
   3624 void MipsAssembler::Copy(ManagedRegister dest, Offset dest_offset,
   3625                          ManagedRegister src, Offset src_offset,
   3626                          ManagedRegister mscratch, size_t size) {
   3627   CHECK_EQ(size, kMipsWordSize);
   3628   Register scratch = mscratch.AsMips().AsCoreRegister();
   3629   LoadFromOffset(kLoadWord, scratch, src.AsMips().AsCoreRegister(), src_offset.Int32Value());
   3630   StoreToOffset(kStoreWord, scratch, dest.AsMips().AsCoreRegister(), dest_offset.Int32Value());
   3631 }
   3632 
   3633 void MipsAssembler::Copy(FrameOffset dest ATTRIBUTE_UNUSED,
   3634                          Offset dest_offset ATTRIBUTE_UNUSED,
   3635                          FrameOffset src ATTRIBUTE_UNUSED,
   3636                          Offset src_offset ATTRIBUTE_UNUSED,
   3637                          ManagedRegister mscratch ATTRIBUTE_UNUSED,
   3638                          size_t size ATTRIBUTE_UNUSED) {
   3639   UNIMPLEMENTED(FATAL) << "no MIPS implementation";
   3640 }
   3641 
   3642 void MipsAssembler::MemoryBarrier(ManagedRegister) {
   3643   // TODO: sync?
   3644   UNIMPLEMENTED(FATAL) << "no MIPS implementation";
   3645 }
   3646 
   3647 void MipsAssembler::CreateHandleScopeEntry(ManagedRegister mout_reg,
   3648                                            FrameOffset handle_scope_offset,
   3649                                            ManagedRegister min_reg,
   3650                                            bool null_allowed) {
   3651   MipsManagedRegister out_reg = mout_reg.AsMips();
   3652   MipsManagedRegister in_reg = min_reg.AsMips();
   3653   CHECK(in_reg.IsNoRegister() || in_reg.IsCoreRegister()) << in_reg;
   3654   CHECK(out_reg.IsCoreRegister()) << out_reg;
   3655   if (null_allowed) {
   3656     MipsLabel null_arg;
   3657     // Null values get a handle scope entry value of 0.  Otherwise, the handle scope entry is
   3658     // the address in the handle scope holding the reference.
   3659     // E.g. out_reg = (handle == 0) ? 0 : (SP+handle_offset).
   3660     if (in_reg.IsNoRegister()) {
   3661       LoadFromOffset(kLoadWord, out_reg.AsCoreRegister(),
   3662                      SP, handle_scope_offset.Int32Value());
   3663       in_reg = out_reg;
   3664     }
   3665     if (!out_reg.Equals(in_reg)) {
   3666       LoadConst32(out_reg.AsCoreRegister(), 0);
   3667     }
   3668     Beqz(in_reg.AsCoreRegister(), &null_arg);
   3669     Addiu32(out_reg.AsCoreRegister(), SP, handle_scope_offset.Int32Value());
   3670     Bind(&null_arg);
   3671   } else {
   3672     Addiu32(out_reg.AsCoreRegister(), SP, handle_scope_offset.Int32Value());
   3673   }
   3674 }
   3675 
   3676 void MipsAssembler::CreateHandleScopeEntry(FrameOffset out_off,
   3677                                            FrameOffset handle_scope_offset,
   3678                                            ManagedRegister mscratch,
   3679                                            bool null_allowed) {
   3680   MipsManagedRegister scratch = mscratch.AsMips();
   3681   CHECK(scratch.IsCoreRegister()) << scratch;
   3682   if (null_allowed) {
   3683     MipsLabel null_arg;
   3684     LoadFromOffset(kLoadWord, scratch.AsCoreRegister(), SP, handle_scope_offset.Int32Value());
   3685     // Null values get a handle scope entry value of 0.  Otherwise, the handle scope entry is
   3686     // the address in the handle scope holding the reference.
   3687     // E.g. scratch = (scratch == 0) ? 0 : (SP+handle_scope_offset).
   3688     Beqz(scratch.AsCoreRegister(), &null_arg);
   3689     Addiu32(scratch.AsCoreRegister(), SP, handle_scope_offset.Int32Value());
   3690     Bind(&null_arg);
   3691   } else {
   3692     Addiu32(scratch.AsCoreRegister(), SP, handle_scope_offset.Int32Value());
   3693   }
   3694   StoreToOffset(kStoreWord, scratch.AsCoreRegister(), SP, out_off.Int32Value());
   3695 }
   3696 
   3697 // Given a handle scope entry, load the associated reference.
   3698 void MipsAssembler::LoadReferenceFromHandleScope(ManagedRegister mout_reg,
   3699                                                  ManagedRegister min_reg) {
   3700   MipsManagedRegister out_reg = mout_reg.AsMips();
   3701   MipsManagedRegister in_reg = min_reg.AsMips();
   3702   CHECK(out_reg.IsCoreRegister()) << out_reg;
   3703   CHECK(in_reg.IsCoreRegister()) << in_reg;
   3704   MipsLabel null_arg;
   3705   if (!out_reg.Equals(in_reg)) {
   3706     LoadConst32(out_reg.AsCoreRegister(), 0);
   3707   }
   3708   Beqz(in_reg.AsCoreRegister(), &null_arg);
   3709   LoadFromOffset(kLoadWord, out_reg.AsCoreRegister(),
   3710                  in_reg.AsCoreRegister(), 0);
   3711   Bind(&null_arg);
   3712 }
   3713 
   3714 void MipsAssembler::VerifyObject(ManagedRegister src ATTRIBUTE_UNUSED,
   3715                                  bool could_be_null ATTRIBUTE_UNUSED) {
   3716   // TODO: not validating references.
   3717 }
   3718 
   3719 void MipsAssembler::VerifyObject(FrameOffset src ATTRIBUTE_UNUSED,
   3720                                  bool could_be_null ATTRIBUTE_UNUSED) {
   3721   // TODO: not validating references.
   3722 }
   3723 
   3724 void MipsAssembler::Call(ManagedRegister mbase, Offset offset, ManagedRegister mscratch) {
   3725   MipsManagedRegister base = mbase.AsMips();
   3726   MipsManagedRegister scratch = mscratch.AsMips();
   3727   CHECK(base.IsCoreRegister()) << base;
   3728   CHECK(scratch.IsCoreRegister()) << scratch;
   3729   LoadFromOffset(kLoadWord, scratch.AsCoreRegister(),
   3730                  base.AsCoreRegister(), offset.Int32Value());
   3731   Jalr(scratch.AsCoreRegister());
   3732   NopIfNoReordering();
   3733   // TODO: place reference map on call.
   3734 }
   3735 
   3736 void MipsAssembler::Call(FrameOffset base, Offset offset, ManagedRegister mscratch) {
   3737   MipsManagedRegister scratch = mscratch.AsMips();
   3738   CHECK(scratch.IsCoreRegister()) << scratch;
   3739   // Call *(*(SP + base) + offset)
   3740   LoadFromOffset(kLoadWord, scratch.AsCoreRegister(), SP, base.Int32Value());
   3741   LoadFromOffset(kLoadWord, scratch.AsCoreRegister(),
   3742                  scratch.AsCoreRegister(), offset.Int32Value());
   3743   Jalr(scratch.AsCoreRegister());
   3744   NopIfNoReordering();
   3745   // TODO: place reference map on call.
   3746 }
   3747 
   3748 void MipsAssembler::CallFromThread(ThreadOffset32 offset ATTRIBUTE_UNUSED,
   3749                                    ManagedRegister mscratch ATTRIBUTE_UNUSED) {
   3750   UNIMPLEMENTED(FATAL) << "no mips implementation";
   3751 }
   3752 
   3753 void MipsAssembler::GetCurrentThread(ManagedRegister tr) {
   3754   Move(tr.AsMips().AsCoreRegister(), S1);
   3755 }
   3756 
   3757 void MipsAssembler::GetCurrentThread(FrameOffset offset,
   3758                                      ManagedRegister mscratch ATTRIBUTE_UNUSED) {
   3759   StoreToOffset(kStoreWord, S1, SP, offset.Int32Value());
   3760 }
   3761 
   3762 void MipsAssembler::ExceptionPoll(ManagedRegister mscratch, size_t stack_adjust) {
   3763   MipsManagedRegister scratch = mscratch.AsMips();
   3764   exception_blocks_.emplace_back(scratch, stack_adjust);
   3765   LoadFromOffset(kLoadWord, scratch.AsCoreRegister(),
   3766                  S1, Thread::ExceptionOffset<kMipsPointerSize>().Int32Value());
   3767   Bnez(scratch.AsCoreRegister(), exception_blocks_.back().Entry());
   3768 }
   3769 
   3770 void MipsAssembler::EmitExceptionPoll(MipsExceptionSlowPath* exception) {
   3771   Bind(exception->Entry());
   3772   if (exception->stack_adjust_ != 0) {  // Fix up the frame.
   3773     DecreaseFrameSize(exception->stack_adjust_);
   3774   }
   3775   // Pass exception object as argument.
   3776   // Don't care about preserving A0 as this call won't return.
   3777   CheckEntrypointTypes<kQuickDeliverException, void, mirror::Object*>();
   3778   Move(A0, exception->scratch_.AsCoreRegister());
   3779   // Set up call to Thread::Current()->pDeliverException.
   3780   LoadFromOffset(kLoadWord, T9, S1,
   3781     QUICK_ENTRYPOINT_OFFSET(kMipsPointerSize, pDeliverException).Int32Value());
   3782   Jr(T9);
   3783   NopIfNoReordering();
   3784 
   3785   // Call never returns.
   3786   Break();
   3787 }
   3788 
   3789 }  // namespace mips
   3790 }  // namespace art
   3791