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 uint32_t MipsAssembler::EmitMsa3R(int operation,
    408                                   int df,
    409                                   VectorRegister wt,
    410                                   VectorRegister ws,
    411                                   VectorRegister wd,
    412                                   int minor_opcode) {
    413   CHECK_NE(wt, kNoVectorRegister);
    414   CHECK_NE(ws, kNoVectorRegister);
    415   CHECK_NE(wd, kNoVectorRegister);
    416   uint32_t encoding = static_cast<uint32_t>(kMsaMajorOpcode) << kOpcodeShift |
    417                       operation << kMsaOperationShift |
    418                       df << kDfShift |
    419                       static_cast<uint32_t>(wt) << kWtShift |
    420                       static_cast<uint32_t>(ws) << kWsShift |
    421                       static_cast<uint32_t>(wd) << kWdShift |
    422                       minor_opcode;
    423   Emit(encoding);
    424   return encoding;
    425 }
    426 
    427 uint32_t MipsAssembler::EmitMsaBIT(int operation,
    428                                    int df_m,
    429                                    VectorRegister ws,
    430                                    VectorRegister wd,
    431                                    int minor_opcode) {
    432   CHECK_NE(ws, kNoVectorRegister);
    433   CHECK_NE(wd, kNoVectorRegister);
    434   uint32_t encoding = static_cast<uint32_t>(kMsaMajorOpcode) << kOpcodeShift |
    435                       operation << kMsaOperationShift |
    436                       df_m << kDfMShift |
    437                       static_cast<uint32_t>(ws) << kWsShift |
    438                       static_cast<uint32_t>(wd) << kWdShift |
    439                       minor_opcode;
    440   Emit(encoding);
    441   return encoding;
    442 }
    443 
    444 uint32_t MipsAssembler::EmitMsaELM(int operation,
    445                                    int df_n,
    446                                    VectorRegister ws,
    447                                    VectorRegister wd,
    448                                    int minor_opcode) {
    449   CHECK_NE(ws, kNoVectorRegister);
    450   CHECK_NE(wd, kNoVectorRegister);
    451   uint32_t encoding = static_cast<uint32_t>(kMsaMajorOpcode) << kOpcodeShift |
    452                       operation << kMsaELMOperationShift |
    453                       df_n << kDfNShift |
    454                       static_cast<uint32_t>(ws) << kWsShift |
    455                       static_cast<uint32_t>(wd) << kWdShift |
    456                       minor_opcode;
    457   Emit(encoding);
    458   return encoding;
    459 }
    460 
    461 uint32_t MipsAssembler::EmitMsaMI10(int s10,
    462                                     Register rs,
    463                                     VectorRegister wd,
    464                                     int minor_opcode,
    465                                     int df) {
    466   CHECK_NE(rs, kNoRegister);
    467   CHECK_NE(wd, kNoVectorRegister);
    468   CHECK(IsUint<10>(s10)) << s10;
    469   uint32_t encoding = static_cast<uint32_t>(kMsaMajorOpcode) << kOpcodeShift |
    470                       s10 << kS10Shift |
    471                       static_cast<uint32_t>(rs) << kWsShift |
    472                       static_cast<uint32_t>(wd) << kWdShift |
    473                       minor_opcode << kS10MinorShift |
    474                       df;
    475   Emit(encoding);
    476   return encoding;
    477 }
    478 
    479 uint32_t MipsAssembler::EmitMsaI10(int operation,
    480                                    int df,
    481                                    int i10,
    482                                    VectorRegister wd,
    483                                    int minor_opcode) {
    484   CHECK_NE(wd, kNoVectorRegister);
    485   CHECK(IsUint<10>(i10)) << i10;
    486   uint32_t encoding = static_cast<uint32_t>(kMsaMajorOpcode) << kOpcodeShift |
    487                       operation << kMsaOperationShift |
    488                       df << kDfShift |
    489                       i10 << kI10Shift |
    490                       static_cast<uint32_t>(wd) << kWdShift |
    491                       minor_opcode;
    492   Emit(encoding);
    493   return encoding;
    494 }
    495 
    496 uint32_t MipsAssembler::EmitMsa2R(int operation,
    497                                   int df,
    498                                   VectorRegister ws,
    499                                   VectorRegister wd,
    500                                   int minor_opcode) {
    501   CHECK_NE(ws, kNoVectorRegister);
    502   CHECK_NE(wd, kNoVectorRegister);
    503   uint32_t encoding = static_cast<uint32_t>(kMsaMajorOpcode) << kOpcodeShift |
    504                       operation << kMsa2ROperationShift |
    505                       df << kDf2RShift |
    506                       static_cast<uint32_t>(ws) << kWsShift |
    507                       static_cast<uint32_t>(wd) << kWdShift |
    508                       minor_opcode;
    509   Emit(encoding);
    510   return encoding;
    511 }
    512 
    513 uint32_t MipsAssembler::EmitMsa2RF(int operation,
    514                                    int df,
    515                                    VectorRegister ws,
    516                                    VectorRegister wd,
    517                                    int minor_opcode) {
    518   CHECK_NE(ws, kNoVectorRegister);
    519   CHECK_NE(wd, kNoVectorRegister);
    520   uint32_t encoding = static_cast<uint32_t>(kMsaMajorOpcode) << kOpcodeShift |
    521                       operation << kMsa2RFOperationShift |
    522                       df << kDf2RShift |
    523                       static_cast<uint32_t>(ws) << kWsShift |
    524                       static_cast<uint32_t>(wd) << kWdShift |
    525                       minor_opcode;
    526   Emit(encoding);
    527   return encoding;
    528 }
    529 
    530 void MipsAssembler::Addu(Register rd, Register rs, Register rt) {
    531   DsFsmInstrRrr(EmitR(0, rs, rt, rd, 0, 0x21), rd, rs, rt);
    532 }
    533 
    534 void MipsAssembler::Addiu(Register rt, Register rs, uint16_t imm16) {
    535   DsFsmInstrRrr(EmitI(0x9, rs, rt, imm16), rt, rs, rs);
    536 }
    537 
    538 void MipsAssembler::Subu(Register rd, Register rs, Register rt) {
    539   DsFsmInstrRrr(EmitR(0, rs, rt, rd, 0, 0x23), rd, rs, rt);
    540 }
    541 
    542 void MipsAssembler::MultR2(Register rs, Register rt) {
    543   CHECK(!IsR6());
    544   DsFsmInstrRrr(EmitR(0, rs, rt, static_cast<Register>(0), 0, 0x18), ZERO, rs, rt);
    545 }
    546 
    547 void MipsAssembler::MultuR2(Register rs, Register rt) {
    548   CHECK(!IsR6());
    549   DsFsmInstrRrr(EmitR(0, rs, rt, static_cast<Register>(0), 0, 0x19), ZERO, rs, rt);
    550 }
    551 
    552 void MipsAssembler::DivR2(Register rs, Register rt) {
    553   CHECK(!IsR6());
    554   DsFsmInstrRrr(EmitR(0, rs, rt, static_cast<Register>(0), 0, 0x1a), ZERO, rs, rt);
    555 }
    556 
    557 void MipsAssembler::DivuR2(Register rs, Register rt) {
    558   CHECK(!IsR6());
    559   DsFsmInstrRrr(EmitR(0, rs, rt, static_cast<Register>(0), 0, 0x1b), ZERO, rs, rt);
    560 }
    561 
    562 void MipsAssembler::MulR2(Register rd, Register rs, Register rt) {
    563   CHECK(!IsR6());
    564   DsFsmInstrRrr(EmitR(0x1c, rs, rt, rd, 0, 2), rd, rs, rt);
    565 }
    566 
    567 void MipsAssembler::DivR2(Register rd, Register rs, Register rt) {
    568   CHECK(!IsR6());
    569   DivR2(rs, rt);
    570   Mflo(rd);
    571 }
    572 
    573 void MipsAssembler::ModR2(Register rd, Register rs, Register rt) {
    574   CHECK(!IsR6());
    575   DivR2(rs, rt);
    576   Mfhi(rd);
    577 }
    578 
    579 void MipsAssembler::DivuR2(Register rd, Register rs, Register rt) {
    580   CHECK(!IsR6());
    581   DivuR2(rs, rt);
    582   Mflo(rd);
    583 }
    584 
    585 void MipsAssembler::ModuR2(Register rd, Register rs, Register rt) {
    586   CHECK(!IsR6());
    587   DivuR2(rs, rt);
    588   Mfhi(rd);
    589 }
    590 
    591 void MipsAssembler::MulR6(Register rd, Register rs, Register rt) {
    592   CHECK(IsR6());
    593   DsFsmInstrRrr(EmitR(0, rs, rt, rd, 2, 0x18), rd, rs, rt);
    594 }
    595 
    596 void MipsAssembler::MuhR6(Register rd, Register rs, Register rt) {
    597   CHECK(IsR6());
    598   DsFsmInstrRrr(EmitR(0, rs, rt, rd, 3, 0x18), rd, rs, rt);
    599 }
    600 
    601 void MipsAssembler::MuhuR6(Register rd, Register rs, Register rt) {
    602   CHECK(IsR6());
    603   DsFsmInstrRrr(EmitR(0, rs, rt, rd, 3, 0x19), rd, rs, rt);
    604 }
    605 
    606 void MipsAssembler::DivR6(Register rd, Register rs, Register rt) {
    607   CHECK(IsR6());
    608   DsFsmInstrRrr(EmitR(0, rs, rt, rd, 2, 0x1a), rd, rs, rt);
    609 }
    610 
    611 void MipsAssembler::ModR6(Register rd, Register rs, Register rt) {
    612   CHECK(IsR6());
    613   DsFsmInstrRrr(EmitR(0, rs, rt, rd, 3, 0x1a), rd, rs, rt);
    614 }
    615 
    616 void MipsAssembler::DivuR6(Register rd, Register rs, Register rt) {
    617   CHECK(IsR6());
    618   DsFsmInstrRrr(EmitR(0, rs, rt, rd, 2, 0x1b), rd, rs, rt);
    619 }
    620 
    621 void MipsAssembler::ModuR6(Register rd, Register rs, Register rt) {
    622   CHECK(IsR6());
    623   DsFsmInstrRrr(EmitR(0, rs, rt, rd, 3, 0x1b), rd, rs, rt);
    624 }
    625 
    626 void MipsAssembler::And(Register rd, Register rs, Register rt) {
    627   DsFsmInstrRrr(EmitR(0, rs, rt, rd, 0, 0x24), rd, rs, rt);
    628 }
    629 
    630 void MipsAssembler::Andi(Register rt, Register rs, uint16_t imm16) {
    631   DsFsmInstrRrr(EmitI(0xc, rs, rt, imm16), rt, rs, rs);
    632 }
    633 
    634 void MipsAssembler::Or(Register rd, Register rs, Register rt) {
    635   DsFsmInstrRrr(EmitR(0, rs, rt, rd, 0, 0x25), rd, rs, rt);
    636 }
    637 
    638 void MipsAssembler::Ori(Register rt, Register rs, uint16_t imm16) {
    639   DsFsmInstrRrr(EmitI(0xd, rs, rt, imm16), rt, rs, rs);
    640 }
    641 
    642 void MipsAssembler::Xor(Register rd, Register rs, Register rt) {
    643   DsFsmInstrRrr(EmitR(0, rs, rt, rd, 0, 0x26), rd, rs, rt);
    644 }
    645 
    646 void MipsAssembler::Xori(Register rt, Register rs, uint16_t imm16) {
    647   DsFsmInstrRrr(EmitI(0xe, rs, rt, imm16), rt, rs, rs);
    648 }
    649 
    650 void MipsAssembler::Nor(Register rd, Register rs, Register rt) {
    651   DsFsmInstrRrr(EmitR(0, rs, rt, rd, 0, 0x27), rd, rs, rt);
    652 }
    653 
    654 void MipsAssembler::Movz(Register rd, Register rs, Register rt) {
    655   CHECK(!IsR6());
    656   DsFsmInstrRrrr(EmitR(0, rs, rt, rd, 0, 0x0A), rd, rs, rt);
    657 }
    658 
    659 void MipsAssembler::Movn(Register rd, Register rs, Register rt) {
    660   CHECK(!IsR6());
    661   DsFsmInstrRrrr(EmitR(0, rs, rt, rd, 0, 0x0B), rd, rs, rt);
    662 }
    663 
    664 void MipsAssembler::Seleqz(Register rd, Register rs, Register rt) {
    665   CHECK(IsR6());
    666   DsFsmInstrRrr(EmitR(0, rs, rt, rd, 0, 0x35), rd, rs, rt);
    667 }
    668 
    669 void MipsAssembler::Selnez(Register rd, Register rs, Register rt) {
    670   CHECK(IsR6());
    671   DsFsmInstrRrr(EmitR(0, rs, rt, rd, 0, 0x37), rd, rs, rt);
    672 }
    673 
    674 void MipsAssembler::ClzR6(Register rd, Register rs) {
    675   CHECK(IsR6());
    676   DsFsmInstrRrr(EmitR(0, rs, static_cast<Register>(0), rd, 0x01, 0x10), rd, rs, rs);
    677 }
    678 
    679 void MipsAssembler::ClzR2(Register rd, Register rs) {
    680   CHECK(!IsR6());
    681   DsFsmInstrRrr(EmitR(0x1C, rs, rd, rd, 0, 0x20), rd, rs, rs);
    682 }
    683 
    684 void MipsAssembler::CloR6(Register rd, Register rs) {
    685   CHECK(IsR6());
    686   DsFsmInstrRrr(EmitR(0, rs, static_cast<Register>(0), rd, 0x01, 0x11), rd, rs, rs);
    687 }
    688 
    689 void MipsAssembler::CloR2(Register rd, Register rs) {
    690   CHECK(!IsR6());
    691   DsFsmInstrRrr(EmitR(0x1C, rs, rd, rd, 0, 0x21), rd, rs, rs);
    692 }
    693 
    694 void MipsAssembler::Seb(Register rd, Register rt) {
    695   DsFsmInstrRrr(EmitR(0x1f, static_cast<Register>(0), rt, rd, 0x10, 0x20), rd, rt, rt);
    696 }
    697 
    698 void MipsAssembler::Seh(Register rd, Register rt) {
    699   DsFsmInstrRrr(EmitR(0x1f, static_cast<Register>(0), rt, rd, 0x18, 0x20), rd, rt, rt);
    700 }
    701 
    702 void MipsAssembler::Wsbh(Register rd, Register rt) {
    703   DsFsmInstrRrr(EmitR(0x1f, static_cast<Register>(0), rt, rd, 2, 0x20), rd, rt, rt);
    704 }
    705 
    706 void MipsAssembler::Bitswap(Register rd, Register rt) {
    707   CHECK(IsR6());
    708   DsFsmInstrRrr(EmitR(0x1f, static_cast<Register>(0), rt, rd, 0x0, 0x20), rd, rt, rt);
    709 }
    710 
    711 void MipsAssembler::Sll(Register rd, Register rt, int shamt) {
    712   CHECK(IsUint<5>(shamt)) << shamt;
    713   DsFsmInstrRrr(EmitR(0, static_cast<Register>(0), rt, rd, shamt, 0x00), rd, rt, rt);
    714 }
    715 
    716 void MipsAssembler::Srl(Register rd, Register rt, int shamt) {
    717   CHECK(IsUint<5>(shamt)) << shamt;
    718   DsFsmInstrRrr(EmitR(0, static_cast<Register>(0), rt, rd, shamt, 0x02), rd, rt, rt);
    719 }
    720 
    721 void MipsAssembler::Rotr(Register rd, Register rt, int shamt) {
    722   CHECK(IsUint<5>(shamt)) << shamt;
    723   DsFsmInstrRrr(EmitR(0, static_cast<Register>(1), rt, rd, shamt, 0x02), rd, rt, rt);
    724 }
    725 
    726 void MipsAssembler::Sra(Register rd, Register rt, int shamt) {
    727   CHECK(IsUint<5>(shamt)) << shamt;
    728   DsFsmInstrRrr(EmitR(0, static_cast<Register>(0), rt, rd, shamt, 0x03), rd, rt, rt);
    729 }
    730 
    731 void MipsAssembler::Sllv(Register rd, Register rt, Register rs) {
    732   DsFsmInstrRrr(EmitR(0, rs, rt, rd, 0, 0x04), rd, rs, rt);
    733 }
    734 
    735 void MipsAssembler::Srlv(Register rd, Register rt, Register rs) {
    736   DsFsmInstrRrr(EmitR(0, rs, rt, rd, 0, 0x06), rd, rs, rt);
    737 }
    738 
    739 void MipsAssembler::Rotrv(Register rd, Register rt, Register rs) {
    740   DsFsmInstrRrr(EmitR(0, rs, rt, rd, 1, 0x06), rd, rs, rt);
    741 }
    742 
    743 void MipsAssembler::Srav(Register rd, Register rt, Register rs) {
    744   DsFsmInstrRrr(EmitR(0, rs, rt, rd, 0, 0x07), rd, rs, rt);
    745 }
    746 
    747 void MipsAssembler::Ext(Register rd, Register rt, int pos, int size) {
    748   CHECK(IsUint<5>(pos)) << pos;
    749   CHECK(0 < size && size <= 32) << size;
    750   CHECK(0 < pos + size && pos + size <= 32) << pos << " + " << size;
    751   DsFsmInstrRrr(EmitR(0x1f, rt, rd, static_cast<Register>(size - 1), pos, 0x00), rd, rt, rt);
    752 }
    753 
    754 void MipsAssembler::Ins(Register rd, Register rt, int pos, int size) {
    755   CHECK(IsUint<5>(pos)) << pos;
    756   CHECK(0 < size && size <= 32) << size;
    757   CHECK(0 < pos + size && pos + size <= 32) << pos << " + " << size;
    758   DsFsmInstrRrr(EmitR(0x1f, rt, rd, static_cast<Register>(pos + size - 1), pos, 0x04), rd, rd, rt);
    759 }
    760 
    761 void MipsAssembler::Lsa(Register rd, Register rs, Register rt, int saPlusOne) {
    762   CHECK(IsR6() || HasMsa());
    763   CHECK(1 <= saPlusOne && saPlusOne <= 4) << saPlusOne;
    764   int sa = saPlusOne - 1;
    765   DsFsmInstrRrr(EmitR(0x0, rs, rt, rd, sa, 0x05), rd, rs, rt);
    766 }
    767 
    768 void MipsAssembler::ShiftAndAdd(Register dst,
    769                                 Register src_idx,
    770                                 Register src_base,
    771                                 int shamt,
    772                                 Register tmp) {
    773   CHECK(0 <= shamt && shamt <= 4) << shamt;
    774   CHECK_NE(src_base, tmp);
    775   if (shamt == TIMES_1) {
    776     // Catch the special case where the shift amount is zero (0).
    777     Addu(dst, src_base, src_idx);
    778   } else if (IsR6() || HasMsa()) {
    779     Lsa(dst, src_idx, src_base, shamt);
    780   } else {
    781     Sll(tmp, src_idx, shamt);
    782     Addu(dst, src_base, tmp);
    783   }
    784 }
    785 
    786 void MipsAssembler::Lb(Register rt, Register rs, uint16_t imm16) {
    787   DsFsmInstrRrr(EmitI(0x20, rs, rt, imm16), rt, rs, rs);
    788 }
    789 
    790 void MipsAssembler::Lh(Register rt, Register rs, uint16_t imm16) {
    791   DsFsmInstrRrr(EmitI(0x21, rs, rt, imm16), rt, rs, rs);
    792 }
    793 
    794 void MipsAssembler::Lw(Register rt, Register rs, uint16_t imm16) {
    795   DsFsmInstrRrr(EmitI(0x23, rs, rt, imm16), rt, rs, rs);
    796 }
    797 
    798 void MipsAssembler::Lwl(Register rt, Register rs, uint16_t imm16) {
    799   CHECK(!IsR6());
    800   DsFsmInstrRrr(EmitI(0x22, rs, rt, imm16), rt, rt, rs);
    801 }
    802 
    803 void MipsAssembler::Lwr(Register rt, Register rs, uint16_t imm16) {
    804   CHECK(!IsR6());
    805   DsFsmInstrRrr(EmitI(0x26, rs, rt, imm16), rt, rt, rs);
    806 }
    807 
    808 void MipsAssembler::Lbu(Register rt, Register rs, uint16_t imm16) {
    809   DsFsmInstrRrr(EmitI(0x24, rs, rt, imm16), rt, rs, rs);
    810 }
    811 
    812 void MipsAssembler::Lhu(Register rt, Register rs, uint16_t imm16) {
    813   DsFsmInstrRrr(EmitI(0x25, rs, rt, imm16), rt, rs, rs);
    814 }
    815 
    816 void MipsAssembler::Lwpc(Register rs, uint32_t imm19) {
    817   CHECK(IsR6());
    818   CHECK(IsUint<19>(imm19)) << imm19;
    819   DsFsmInstrNop(EmitI21(0x3B, rs, (0x01 << 19) | imm19));
    820 }
    821 
    822 void MipsAssembler::Lui(Register rt, uint16_t imm16) {
    823   DsFsmInstrRrr(EmitI(0xf, static_cast<Register>(0), rt, imm16), rt, ZERO, ZERO);
    824 }
    825 
    826 void MipsAssembler::Aui(Register rt, Register rs, uint16_t imm16) {
    827   CHECK(IsR6());
    828   DsFsmInstrRrr(EmitI(0xf, rs, rt, imm16), rt, rt, rs);
    829 }
    830 
    831 void MipsAssembler::Sync(uint32_t stype) {
    832   DsFsmInstrNop(EmitR(0, ZERO, ZERO, ZERO, stype & 0x1f, 0xf));
    833 }
    834 
    835 void MipsAssembler::Mfhi(Register rd) {
    836   CHECK(!IsR6());
    837   DsFsmInstrRrr(EmitR(0, ZERO, ZERO, rd, 0, 0x10), rd, ZERO, ZERO);
    838 }
    839 
    840 void MipsAssembler::Mflo(Register rd) {
    841   CHECK(!IsR6());
    842   DsFsmInstrRrr(EmitR(0, ZERO, ZERO, rd, 0, 0x12), rd, ZERO, ZERO);
    843 }
    844 
    845 void MipsAssembler::Sb(Register rt, Register rs, uint16_t imm16) {
    846   DsFsmInstrRrr(EmitI(0x28, rs, rt, imm16), ZERO, rt, rs);
    847 }
    848 
    849 void MipsAssembler::Sh(Register rt, Register rs, uint16_t imm16) {
    850   DsFsmInstrRrr(EmitI(0x29, rs, rt, imm16), ZERO, rt, rs);
    851 }
    852 
    853 void MipsAssembler::Sw(Register rt, Register rs, uint16_t imm16) {
    854   DsFsmInstrRrr(EmitI(0x2b, rs, rt, imm16), ZERO, rt, rs);
    855 }
    856 
    857 void MipsAssembler::Swl(Register rt, Register rs, uint16_t imm16) {
    858   CHECK(!IsR6());
    859   DsFsmInstrRrr(EmitI(0x2a, rs, rt, imm16), ZERO, rt, rs);
    860 }
    861 
    862 void MipsAssembler::Swr(Register rt, Register rs, uint16_t imm16) {
    863   CHECK(!IsR6());
    864   DsFsmInstrRrr(EmitI(0x2e, rs, rt, imm16), ZERO, rt, rs);
    865 }
    866 
    867 void MipsAssembler::LlR2(Register rt, Register base, int16_t imm16) {
    868   CHECK(!IsR6());
    869   DsFsmInstrRrr(EmitI(0x30, base, rt, imm16), rt, base, base);
    870 }
    871 
    872 void MipsAssembler::ScR2(Register rt, Register base, int16_t imm16) {
    873   CHECK(!IsR6());
    874   DsFsmInstrRrr(EmitI(0x38, base, rt, imm16), rt, rt, base);
    875 }
    876 
    877 void MipsAssembler::LlR6(Register rt, Register base, int16_t imm9) {
    878   CHECK(IsR6());
    879   CHECK(IsInt<9>(imm9));
    880   DsFsmInstrRrr(EmitI(0x1f, base, rt, ((imm9 & 0x1ff) << 7) | 0x36), rt, base, base);
    881 }
    882 
    883 void MipsAssembler::ScR6(Register rt, Register base, int16_t imm9) {
    884   CHECK(IsR6());
    885   CHECK(IsInt<9>(imm9));
    886   DsFsmInstrRrr(EmitI(0x1f, base, rt, ((imm9 & 0x1ff) << 7) | 0x26), rt, rt, base);
    887 }
    888 
    889 void MipsAssembler::Slt(Register rd, Register rs, Register rt) {
    890   DsFsmInstrRrr(EmitR(0, rs, rt, rd, 0, 0x2a), rd, rs, rt);
    891 }
    892 
    893 void MipsAssembler::Sltu(Register rd, Register rs, Register rt) {
    894   DsFsmInstrRrr(EmitR(0, rs, rt, rd, 0, 0x2b), rd, rs, rt);
    895 }
    896 
    897 void MipsAssembler::Slti(Register rt, Register rs, uint16_t imm16) {
    898   DsFsmInstrRrr(EmitI(0xa, rs, rt, imm16), rt, rs, rs);
    899 }
    900 
    901 void MipsAssembler::Sltiu(Register rt, Register rs, uint16_t imm16) {
    902   DsFsmInstrRrr(EmitI(0xb, rs, rt, imm16), rt, rs, rs);
    903 }
    904 
    905 void MipsAssembler::B(uint16_t imm16) {
    906   DsFsmInstrNop(EmitI(0x4, static_cast<Register>(0), static_cast<Register>(0), imm16));
    907 }
    908 
    909 void MipsAssembler::Bal(uint16_t imm16) {
    910   DsFsmInstrNop(EmitI(0x1, static_cast<Register>(0), static_cast<Register>(0x11), imm16));
    911 }
    912 
    913 void MipsAssembler::Beq(Register rs, Register rt, uint16_t imm16) {
    914   DsFsmInstrNop(EmitI(0x4, rs, rt, imm16));
    915 }
    916 
    917 void MipsAssembler::Bne(Register rs, Register rt, uint16_t imm16) {
    918   DsFsmInstrNop(EmitI(0x5, rs, rt, imm16));
    919 }
    920 
    921 void MipsAssembler::Beqz(Register rt, uint16_t imm16) {
    922   Beq(ZERO, rt, imm16);
    923 }
    924 
    925 void MipsAssembler::Bnez(Register rt, uint16_t imm16) {
    926   Bne(ZERO, rt, imm16);
    927 }
    928 
    929 void MipsAssembler::Bltz(Register rt, uint16_t imm16) {
    930   DsFsmInstrNop(EmitI(0x1, rt, static_cast<Register>(0), imm16));
    931 }
    932 
    933 void MipsAssembler::Bgez(Register rt, uint16_t imm16) {
    934   DsFsmInstrNop(EmitI(0x1, rt, static_cast<Register>(0x1), imm16));
    935 }
    936 
    937 void MipsAssembler::Blez(Register rt, uint16_t imm16) {
    938   DsFsmInstrNop(EmitI(0x6, rt, static_cast<Register>(0), imm16));
    939 }
    940 
    941 void MipsAssembler::Bgtz(Register rt, uint16_t imm16) {
    942   DsFsmInstrNop(EmitI(0x7, rt, static_cast<Register>(0), imm16));
    943 }
    944 
    945 void MipsAssembler::Bc1f(uint16_t imm16) {
    946   Bc1f(0, imm16);
    947 }
    948 
    949 void MipsAssembler::Bc1f(int cc, uint16_t imm16) {
    950   CHECK(!IsR6());
    951   CHECK(IsUint<3>(cc)) << cc;
    952   DsFsmInstrNop(EmitI(0x11, static_cast<Register>(0x8), static_cast<Register>(cc << 2), imm16));
    953 }
    954 
    955 void MipsAssembler::Bc1t(uint16_t imm16) {
    956   Bc1t(0, imm16);
    957 }
    958 
    959 void MipsAssembler::Bc1t(int cc, uint16_t imm16) {
    960   CHECK(!IsR6());
    961   CHECK(IsUint<3>(cc)) << cc;
    962   DsFsmInstrNop(EmitI(0x11,
    963                       static_cast<Register>(0x8),
    964                       static_cast<Register>((cc << 2) | 1),
    965                       imm16));
    966 }
    967 
    968 void MipsAssembler::J(uint32_t addr26) {
    969   DsFsmInstrNop(EmitI26(0x2, addr26));
    970 }
    971 
    972 void MipsAssembler::Jal(uint32_t addr26) {
    973   DsFsmInstrNop(EmitI26(0x3, addr26));
    974 }
    975 
    976 void MipsAssembler::Jalr(Register rd, Register rs) {
    977   uint32_t last_instruction = delay_slot_.instruction_;
    978   bool exchange = (last_instruction != 0 &&
    979       (delay_slot_.gpr_outs_mask_ & (1u << rs)) == 0 &&
    980       ((delay_slot_.gpr_ins_mask_ | delay_slot_.gpr_outs_mask_) & (1u << rd)) == 0);
    981   if (exchange) {
    982     // The last instruction cannot be used in a different delay slot,
    983     // do not commit the label before it (if any).
    984     DsFsmDropLabel();
    985   }
    986   DsFsmInstrNop(EmitR(0, rs, static_cast<Register>(0), rd, 0, 0x09));
    987   if (exchange) {
    988     // Exchange the last two instructions in the assembler buffer.
    989     size_t size = buffer_.Size();
    990     CHECK_GE(size, 2 * sizeof(uint32_t));
    991     size_t pos1 = size - 2 * sizeof(uint32_t);
    992     size_t pos2 = size - sizeof(uint32_t);
    993     uint32_t instr1 = buffer_.Load<uint32_t>(pos1);
    994     uint32_t instr2 = buffer_.Load<uint32_t>(pos2);
    995     CHECK_EQ(instr1, last_instruction);
    996     buffer_.Store<uint32_t>(pos1, instr2);
    997     buffer_.Store<uint32_t>(pos2, instr1);
    998   } else if (reordering_) {
    999     Nop();
   1000   }
   1001 }
   1002 
   1003 void MipsAssembler::Jalr(Register rs) {
   1004   Jalr(RA, rs);
   1005 }
   1006 
   1007 void MipsAssembler::Jr(Register rs) {
   1008   Jalr(ZERO, rs);
   1009 }
   1010 
   1011 void MipsAssembler::Nal() {
   1012   DsFsmInstrNop(EmitI(0x1, static_cast<Register>(0), static_cast<Register>(0x10), 0));
   1013 }
   1014 
   1015 void MipsAssembler::Auipc(Register rs, uint16_t imm16) {
   1016   CHECK(IsR6());
   1017   DsFsmInstrNop(EmitI(0x3B, rs, static_cast<Register>(0x1E), imm16));
   1018 }
   1019 
   1020 void MipsAssembler::Addiupc(Register rs, uint32_t imm19) {
   1021   CHECK(IsR6());
   1022   CHECK(IsUint<19>(imm19)) << imm19;
   1023   DsFsmInstrNop(EmitI21(0x3B, rs, imm19));
   1024 }
   1025 
   1026 void MipsAssembler::Bc(uint32_t imm26) {
   1027   CHECK(IsR6());
   1028   DsFsmInstrNop(EmitI26(0x32, imm26));
   1029 }
   1030 
   1031 void MipsAssembler::Balc(uint32_t imm26) {
   1032   CHECK(IsR6());
   1033   DsFsmInstrNop(EmitI26(0x3A, imm26));
   1034 }
   1035 
   1036 void MipsAssembler::Jic(Register rt, uint16_t imm16) {
   1037   CHECK(IsR6());
   1038   DsFsmInstrNop(EmitI(0x36, static_cast<Register>(0), rt, imm16));
   1039 }
   1040 
   1041 void MipsAssembler::Jialc(Register rt, uint16_t imm16) {
   1042   CHECK(IsR6());
   1043   DsFsmInstrNop(EmitI(0x3E, static_cast<Register>(0), rt, imm16));
   1044 }
   1045 
   1046 void MipsAssembler::Bltc(Register rs, Register rt, uint16_t imm16) {
   1047   CHECK(IsR6());
   1048   CHECK_NE(rs, ZERO);
   1049   CHECK_NE(rt, ZERO);
   1050   CHECK_NE(rs, rt);
   1051   DsFsmInstrNop(EmitI(0x17, rs, rt, imm16));
   1052 }
   1053 
   1054 void MipsAssembler::Bltzc(Register rt, uint16_t imm16) {
   1055   CHECK(IsR6());
   1056   CHECK_NE(rt, ZERO);
   1057   DsFsmInstrNop(EmitI(0x17, rt, rt, imm16));
   1058 }
   1059 
   1060 void MipsAssembler::Bgtzc(Register rt, uint16_t imm16) {
   1061   CHECK(IsR6());
   1062   CHECK_NE(rt, ZERO);
   1063   DsFsmInstrNop(EmitI(0x17, static_cast<Register>(0), rt, imm16));
   1064 }
   1065 
   1066 void MipsAssembler::Bgec(Register rs, Register rt, uint16_t imm16) {
   1067   CHECK(IsR6());
   1068   CHECK_NE(rs, ZERO);
   1069   CHECK_NE(rt, ZERO);
   1070   CHECK_NE(rs, rt);
   1071   DsFsmInstrNop(EmitI(0x16, rs, rt, imm16));
   1072 }
   1073 
   1074 void MipsAssembler::Bgezc(Register rt, uint16_t imm16) {
   1075   CHECK(IsR6());
   1076   CHECK_NE(rt, ZERO);
   1077   DsFsmInstrNop(EmitI(0x16, rt, rt, imm16));
   1078 }
   1079 
   1080 void MipsAssembler::Blezc(Register rt, uint16_t imm16) {
   1081   CHECK(IsR6());
   1082   CHECK_NE(rt, ZERO);
   1083   DsFsmInstrNop(EmitI(0x16, static_cast<Register>(0), rt, imm16));
   1084 }
   1085 
   1086 void MipsAssembler::Bltuc(Register rs, Register rt, uint16_t imm16) {
   1087   CHECK(IsR6());
   1088   CHECK_NE(rs, ZERO);
   1089   CHECK_NE(rt, ZERO);
   1090   CHECK_NE(rs, rt);
   1091   DsFsmInstrNop(EmitI(0x7, rs, rt, imm16));
   1092 }
   1093 
   1094 void MipsAssembler::Bgeuc(Register rs, Register rt, uint16_t imm16) {
   1095   CHECK(IsR6());
   1096   CHECK_NE(rs, ZERO);
   1097   CHECK_NE(rt, ZERO);
   1098   CHECK_NE(rs, rt);
   1099   DsFsmInstrNop(EmitI(0x6, rs, rt, imm16));
   1100 }
   1101 
   1102 void MipsAssembler::Beqc(Register rs, Register rt, uint16_t imm16) {
   1103   CHECK(IsR6());
   1104   CHECK_NE(rs, ZERO);
   1105   CHECK_NE(rt, ZERO);
   1106   CHECK_NE(rs, rt);
   1107   DsFsmInstrNop(EmitI(0x8, std::min(rs, rt), std::max(rs, rt), imm16));
   1108 }
   1109 
   1110 void MipsAssembler::Bnec(Register rs, Register rt, uint16_t imm16) {
   1111   CHECK(IsR6());
   1112   CHECK_NE(rs, ZERO);
   1113   CHECK_NE(rt, ZERO);
   1114   CHECK_NE(rs, rt);
   1115   DsFsmInstrNop(EmitI(0x18, std::min(rs, rt), std::max(rs, rt), imm16));
   1116 }
   1117 
   1118 void MipsAssembler::Beqzc(Register rs, uint32_t imm21) {
   1119   CHECK(IsR6());
   1120   CHECK_NE(rs, ZERO);
   1121   DsFsmInstrNop(EmitI21(0x36, rs, imm21));
   1122 }
   1123 
   1124 void MipsAssembler::Bnezc(Register rs, uint32_t imm21) {
   1125   CHECK(IsR6());
   1126   CHECK_NE(rs, ZERO);
   1127   DsFsmInstrNop(EmitI21(0x3E, rs, imm21));
   1128 }
   1129 
   1130 void MipsAssembler::Bc1eqz(FRegister ft, uint16_t imm16) {
   1131   CHECK(IsR6());
   1132   DsFsmInstrNop(EmitFI(0x11, 0x9, ft, imm16));
   1133 }
   1134 
   1135 void MipsAssembler::Bc1nez(FRegister ft, uint16_t imm16) {
   1136   CHECK(IsR6());
   1137   DsFsmInstrNop(EmitFI(0x11, 0xD, ft, imm16));
   1138 }
   1139 
   1140 void MipsAssembler::EmitBcondR2(BranchCondition cond, Register rs, Register rt, uint16_t imm16) {
   1141   switch (cond) {
   1142     case kCondLTZ:
   1143       CHECK_EQ(rt, ZERO);
   1144       Bltz(rs, imm16);
   1145       break;
   1146     case kCondGEZ:
   1147       CHECK_EQ(rt, ZERO);
   1148       Bgez(rs, imm16);
   1149       break;
   1150     case kCondLEZ:
   1151       CHECK_EQ(rt, ZERO);
   1152       Blez(rs, imm16);
   1153       break;
   1154     case kCondGTZ:
   1155       CHECK_EQ(rt, ZERO);
   1156       Bgtz(rs, imm16);
   1157       break;
   1158     case kCondEQ:
   1159       Beq(rs, rt, imm16);
   1160       break;
   1161     case kCondNE:
   1162       Bne(rs, rt, imm16);
   1163       break;
   1164     case kCondEQZ:
   1165       CHECK_EQ(rt, ZERO);
   1166       Beqz(rs, imm16);
   1167       break;
   1168     case kCondNEZ:
   1169       CHECK_EQ(rt, ZERO);
   1170       Bnez(rs, imm16);
   1171       break;
   1172     case kCondF:
   1173       CHECK_EQ(rt, ZERO);
   1174       Bc1f(static_cast<int>(rs), imm16);
   1175       break;
   1176     case kCondT:
   1177       CHECK_EQ(rt, ZERO);
   1178       Bc1t(static_cast<int>(rs), imm16);
   1179       break;
   1180     case kCondLT:
   1181     case kCondGE:
   1182     case kCondLE:
   1183     case kCondGT:
   1184     case kCondLTU:
   1185     case kCondGEU:
   1186     case kUncond:
   1187       // We don't support synthetic R2 branches (preceded with slt[u]) at this level
   1188       // (R2 doesn't have branches to compare 2 registers using <, <=, >=, >).
   1189       LOG(FATAL) << "Unexpected branch condition " << cond;
   1190       UNREACHABLE();
   1191   }
   1192 }
   1193 
   1194 void MipsAssembler::EmitBcondR6(BranchCondition cond, Register rs, Register rt, uint32_t imm16_21) {
   1195   switch (cond) {
   1196     case kCondLT:
   1197       Bltc(rs, rt, imm16_21);
   1198       break;
   1199     case kCondGE:
   1200       Bgec(rs, rt, imm16_21);
   1201       break;
   1202     case kCondLE:
   1203       Bgec(rt, rs, imm16_21);
   1204       break;
   1205     case kCondGT:
   1206       Bltc(rt, rs, imm16_21);
   1207       break;
   1208     case kCondLTZ:
   1209       CHECK_EQ(rt, ZERO);
   1210       Bltzc(rs, imm16_21);
   1211       break;
   1212     case kCondGEZ:
   1213       CHECK_EQ(rt, ZERO);
   1214       Bgezc(rs, imm16_21);
   1215       break;
   1216     case kCondLEZ:
   1217       CHECK_EQ(rt, ZERO);
   1218       Blezc(rs, imm16_21);
   1219       break;
   1220     case kCondGTZ:
   1221       CHECK_EQ(rt, ZERO);
   1222       Bgtzc(rs, imm16_21);
   1223       break;
   1224     case kCondEQ:
   1225       Beqc(rs, rt, imm16_21);
   1226       break;
   1227     case kCondNE:
   1228       Bnec(rs, rt, imm16_21);
   1229       break;
   1230     case kCondEQZ:
   1231       CHECK_EQ(rt, ZERO);
   1232       Beqzc(rs, imm16_21);
   1233       break;
   1234     case kCondNEZ:
   1235       CHECK_EQ(rt, ZERO);
   1236       Bnezc(rs, imm16_21);
   1237       break;
   1238     case kCondLTU:
   1239       Bltuc(rs, rt, imm16_21);
   1240       break;
   1241     case kCondGEU:
   1242       Bgeuc(rs, rt, imm16_21);
   1243       break;
   1244     case kCondF:
   1245       CHECK_EQ(rt, ZERO);
   1246       Bc1eqz(static_cast<FRegister>(rs), imm16_21);
   1247       break;
   1248     case kCondT:
   1249       CHECK_EQ(rt, ZERO);
   1250       Bc1nez(static_cast<FRegister>(rs), imm16_21);
   1251       break;
   1252     case kUncond:
   1253       LOG(FATAL) << "Unexpected branch condition " << cond;
   1254       UNREACHABLE();
   1255   }
   1256 }
   1257 
   1258 void MipsAssembler::AddS(FRegister fd, FRegister fs, FRegister ft) {
   1259   DsFsmInstrFff(EmitFR(0x11, 0x10, ft, fs, fd, 0x0), fd, fs, ft);
   1260 }
   1261 
   1262 void MipsAssembler::SubS(FRegister fd, FRegister fs, FRegister ft) {
   1263   DsFsmInstrFff(EmitFR(0x11, 0x10, ft, fs, fd, 0x1), fd, fs, ft);
   1264 }
   1265 
   1266 void MipsAssembler::MulS(FRegister fd, FRegister fs, FRegister ft) {
   1267   DsFsmInstrFff(EmitFR(0x11, 0x10, ft, fs, fd, 0x2), fd, fs, ft);
   1268 }
   1269 
   1270 void MipsAssembler::DivS(FRegister fd, FRegister fs, FRegister ft) {
   1271   DsFsmInstrFff(EmitFR(0x11, 0x10, ft, fs, fd, 0x3), fd, fs, ft);
   1272 }
   1273 
   1274 void MipsAssembler::AddD(FRegister fd, FRegister fs, FRegister ft) {
   1275   DsFsmInstrFff(EmitFR(0x11, 0x11, ft, fs, fd, 0x0), fd, fs, ft);
   1276 }
   1277 
   1278 void MipsAssembler::SubD(FRegister fd, FRegister fs, FRegister ft) {
   1279   DsFsmInstrFff(EmitFR(0x11, 0x11, ft, fs, fd, 0x1), fd, fs, ft);
   1280 }
   1281 
   1282 void MipsAssembler::MulD(FRegister fd, FRegister fs, FRegister ft) {
   1283   DsFsmInstrFff(EmitFR(0x11, 0x11, ft, fs, fd, 0x2), fd, fs, ft);
   1284 }
   1285 
   1286 void MipsAssembler::DivD(FRegister fd, FRegister fs, FRegister ft) {
   1287   DsFsmInstrFff(EmitFR(0x11, 0x11, ft, fs, fd, 0x3), fd, fs, ft);
   1288 }
   1289 
   1290 void MipsAssembler::SqrtS(FRegister fd, FRegister fs) {
   1291   DsFsmInstrFff(EmitFR(0x11, 0x10, static_cast<FRegister>(0), fs, fd, 0x4), fd, fs, fs);
   1292 }
   1293 
   1294 void MipsAssembler::SqrtD(FRegister fd, FRegister fs) {
   1295   DsFsmInstrFff(EmitFR(0x11, 0x11, static_cast<FRegister>(0), fs, fd, 0x4), fd, fs, fs);
   1296 }
   1297 
   1298 void MipsAssembler::AbsS(FRegister fd, FRegister fs) {
   1299   DsFsmInstrFff(EmitFR(0x11, 0x10, static_cast<FRegister>(0), fs, fd, 0x5), fd, fs, fs);
   1300 }
   1301 
   1302 void MipsAssembler::AbsD(FRegister fd, FRegister fs) {
   1303   DsFsmInstrFff(EmitFR(0x11, 0x11, static_cast<FRegister>(0), fs, fd, 0x5), fd, fs, fs);
   1304 }
   1305 
   1306 void MipsAssembler::MovS(FRegister fd, FRegister fs) {
   1307   DsFsmInstrFff(EmitFR(0x11, 0x10, static_cast<FRegister>(0), fs, fd, 0x6), fd, fs, fs);
   1308 }
   1309 
   1310 void MipsAssembler::MovD(FRegister fd, FRegister fs) {
   1311   DsFsmInstrFff(EmitFR(0x11, 0x11, static_cast<FRegister>(0), fs, fd, 0x6), fd, fs, fs);
   1312 }
   1313 
   1314 void MipsAssembler::NegS(FRegister fd, FRegister fs) {
   1315   DsFsmInstrFff(EmitFR(0x11, 0x10, static_cast<FRegister>(0), fs, fd, 0x7), fd, fs, fs);
   1316 }
   1317 
   1318 void MipsAssembler::NegD(FRegister fd, FRegister fs) {
   1319   DsFsmInstrFff(EmitFR(0x11, 0x11, static_cast<FRegister>(0), fs, fd, 0x7), fd, fs, fs);
   1320 }
   1321 
   1322 void MipsAssembler::CunS(FRegister fs, FRegister ft) {
   1323   CunS(0, fs, ft);
   1324 }
   1325 
   1326 void MipsAssembler::CunS(int cc, FRegister fs, FRegister ft) {
   1327   CHECK(!IsR6());
   1328   CHECK(IsUint<3>(cc)) << cc;
   1329   DsFsmInstrCff(EmitFR(0x11, 0x10, ft, fs, static_cast<FRegister>(cc << 2), 0x31), cc, fs, ft);
   1330 }
   1331 
   1332 void MipsAssembler::CeqS(FRegister fs, FRegister ft) {
   1333   CeqS(0, fs, ft);
   1334 }
   1335 
   1336 void MipsAssembler::CeqS(int cc, FRegister fs, FRegister ft) {
   1337   CHECK(!IsR6());
   1338   CHECK(IsUint<3>(cc)) << cc;
   1339   DsFsmInstrCff(EmitFR(0x11, 0x10, ft, fs, static_cast<FRegister>(cc << 2), 0x32), cc, fs, ft);
   1340 }
   1341 
   1342 void MipsAssembler::CueqS(FRegister fs, FRegister ft) {
   1343   CueqS(0, fs, ft);
   1344 }
   1345 
   1346 void MipsAssembler::CueqS(int cc, FRegister fs, FRegister ft) {
   1347   CHECK(!IsR6());
   1348   CHECK(IsUint<3>(cc)) << cc;
   1349   DsFsmInstrCff(EmitFR(0x11, 0x10, ft, fs, static_cast<FRegister>(cc << 2), 0x33), cc, fs, ft);
   1350 }
   1351 
   1352 void MipsAssembler::ColtS(FRegister fs, FRegister ft) {
   1353   ColtS(0, fs, ft);
   1354 }
   1355 
   1356 void MipsAssembler::ColtS(int cc, FRegister fs, FRegister ft) {
   1357   CHECK(!IsR6());
   1358   CHECK(IsUint<3>(cc)) << cc;
   1359   DsFsmInstrCff(EmitFR(0x11, 0x10, ft, fs, static_cast<FRegister>(cc << 2), 0x34), cc, fs, ft);
   1360 }
   1361 
   1362 void MipsAssembler::CultS(FRegister fs, FRegister ft) {
   1363   CultS(0, fs, ft);
   1364 }
   1365 
   1366 void MipsAssembler::CultS(int cc, FRegister fs, FRegister ft) {
   1367   CHECK(!IsR6());
   1368   CHECK(IsUint<3>(cc)) << cc;
   1369   DsFsmInstrCff(EmitFR(0x11, 0x10, ft, fs, static_cast<FRegister>(cc << 2), 0x35), cc, fs, ft);
   1370 }
   1371 
   1372 void MipsAssembler::ColeS(FRegister fs, FRegister ft) {
   1373   ColeS(0, fs, ft);
   1374 }
   1375 
   1376 void MipsAssembler::ColeS(int cc, FRegister fs, FRegister ft) {
   1377   CHECK(!IsR6());
   1378   CHECK(IsUint<3>(cc)) << cc;
   1379   DsFsmInstrCff(EmitFR(0x11, 0x10, ft, fs, static_cast<FRegister>(cc << 2), 0x36), cc, fs, ft);
   1380 }
   1381 
   1382 void MipsAssembler::CuleS(FRegister fs, FRegister ft) {
   1383   CuleS(0, fs, ft);
   1384 }
   1385 
   1386 void MipsAssembler::CuleS(int cc, FRegister fs, FRegister ft) {
   1387   CHECK(!IsR6());
   1388   CHECK(IsUint<3>(cc)) << cc;
   1389   DsFsmInstrCff(EmitFR(0x11, 0x10, ft, fs, static_cast<FRegister>(cc << 2), 0x37), cc, fs, ft);
   1390 }
   1391 
   1392 void MipsAssembler::CunD(FRegister fs, FRegister ft) {
   1393   CunD(0, fs, ft);
   1394 }
   1395 
   1396 void MipsAssembler::CunD(int cc, FRegister fs, FRegister ft) {
   1397   CHECK(!IsR6());
   1398   CHECK(IsUint<3>(cc)) << cc;
   1399   DsFsmInstrCff(EmitFR(0x11, 0x11, ft, fs, static_cast<FRegister>(cc << 2), 0x31), cc, fs, ft);
   1400 }
   1401 
   1402 void MipsAssembler::CeqD(FRegister fs, FRegister ft) {
   1403   CeqD(0, fs, ft);
   1404 }
   1405 
   1406 void MipsAssembler::CeqD(int cc, FRegister fs, FRegister ft) {
   1407   CHECK(!IsR6());
   1408   CHECK(IsUint<3>(cc)) << cc;
   1409   DsFsmInstrCff(EmitFR(0x11, 0x11, ft, fs, static_cast<FRegister>(cc << 2), 0x32), cc, fs, ft);
   1410 }
   1411 
   1412 void MipsAssembler::CueqD(FRegister fs, FRegister ft) {
   1413   CueqD(0, fs, ft);
   1414 }
   1415 
   1416 void MipsAssembler::CueqD(int cc, FRegister fs, FRegister ft) {
   1417   CHECK(!IsR6());
   1418   CHECK(IsUint<3>(cc)) << cc;
   1419   DsFsmInstrCff(EmitFR(0x11, 0x11, ft, fs, static_cast<FRegister>(cc << 2), 0x33), cc, fs, ft);
   1420 }
   1421 
   1422 void MipsAssembler::ColtD(FRegister fs, FRegister ft) {
   1423   ColtD(0, fs, ft);
   1424 }
   1425 
   1426 void MipsAssembler::ColtD(int cc, FRegister fs, FRegister ft) {
   1427   CHECK(!IsR6());
   1428   CHECK(IsUint<3>(cc)) << cc;
   1429   DsFsmInstrCff(EmitFR(0x11, 0x11, ft, fs, static_cast<FRegister>(cc << 2), 0x34), cc, fs, ft);
   1430 }
   1431 
   1432 void MipsAssembler::CultD(FRegister fs, FRegister ft) {
   1433   CultD(0, fs, ft);
   1434 }
   1435 
   1436 void MipsAssembler::CultD(int cc, FRegister fs, FRegister ft) {
   1437   CHECK(!IsR6());
   1438   CHECK(IsUint<3>(cc)) << cc;
   1439   DsFsmInstrCff(EmitFR(0x11, 0x11, ft, fs, static_cast<FRegister>(cc << 2), 0x35), cc, fs, ft);
   1440 }
   1441 
   1442 void MipsAssembler::ColeD(FRegister fs, FRegister ft) {
   1443   ColeD(0, fs, ft);
   1444 }
   1445 
   1446 void MipsAssembler::ColeD(int cc, FRegister fs, FRegister ft) {
   1447   CHECK(!IsR6());
   1448   CHECK(IsUint<3>(cc)) << cc;
   1449   DsFsmInstrCff(EmitFR(0x11, 0x11, ft, fs, static_cast<FRegister>(cc << 2), 0x36), cc, fs, ft);
   1450 }
   1451 
   1452 void MipsAssembler::CuleD(FRegister fs, FRegister ft) {
   1453   CuleD(0, fs, ft);
   1454 }
   1455 
   1456 void MipsAssembler::CuleD(int cc, FRegister fs, FRegister ft) {
   1457   CHECK(!IsR6());
   1458   CHECK(IsUint<3>(cc)) << cc;
   1459   DsFsmInstrCff(EmitFR(0x11, 0x11, ft, fs, static_cast<FRegister>(cc << 2), 0x37), cc, fs, ft);
   1460 }
   1461 
   1462 void MipsAssembler::CmpUnS(FRegister fd, FRegister fs, FRegister ft) {
   1463   CHECK(IsR6());
   1464   DsFsmInstrFff(EmitFR(0x11, 0x14, ft, fs, fd, 0x01), fd, fs, ft);
   1465 }
   1466 
   1467 void MipsAssembler::CmpEqS(FRegister fd, FRegister fs, FRegister ft) {
   1468   CHECK(IsR6());
   1469   DsFsmInstrFff(EmitFR(0x11, 0x14, ft, fs, fd, 0x02), fd, fs, ft);
   1470 }
   1471 
   1472 void MipsAssembler::CmpUeqS(FRegister fd, FRegister fs, FRegister ft) {
   1473   CHECK(IsR6());
   1474   DsFsmInstrFff(EmitFR(0x11, 0x14, ft, fs, fd, 0x03), fd, fs, ft);
   1475 }
   1476 
   1477 void MipsAssembler::CmpLtS(FRegister fd, FRegister fs, FRegister ft) {
   1478   CHECK(IsR6());
   1479   DsFsmInstrFff(EmitFR(0x11, 0x14, ft, fs, fd, 0x04), fd, fs, ft);
   1480 }
   1481 
   1482 void MipsAssembler::CmpUltS(FRegister fd, FRegister fs, FRegister ft) {
   1483   CHECK(IsR6());
   1484   DsFsmInstrFff(EmitFR(0x11, 0x14, ft, fs, fd, 0x05), fd, fs, ft);
   1485 }
   1486 
   1487 void MipsAssembler::CmpLeS(FRegister fd, FRegister fs, FRegister ft) {
   1488   CHECK(IsR6());
   1489   DsFsmInstrFff(EmitFR(0x11, 0x14, ft, fs, fd, 0x06), fd, fs, ft);
   1490 }
   1491 
   1492 void MipsAssembler::CmpUleS(FRegister fd, FRegister fs, FRegister ft) {
   1493   CHECK(IsR6());
   1494   DsFsmInstrFff(EmitFR(0x11, 0x14, ft, fs, fd, 0x07), fd, fs, ft);
   1495 }
   1496 
   1497 void MipsAssembler::CmpOrS(FRegister fd, FRegister fs, FRegister ft) {
   1498   CHECK(IsR6());
   1499   DsFsmInstrFff(EmitFR(0x11, 0x14, ft, fs, fd, 0x11), fd, fs, ft);
   1500 }
   1501 
   1502 void MipsAssembler::CmpUneS(FRegister fd, FRegister fs, FRegister ft) {
   1503   CHECK(IsR6());
   1504   DsFsmInstrFff(EmitFR(0x11, 0x14, ft, fs, fd, 0x12), fd, fs, ft);
   1505 }
   1506 
   1507 void MipsAssembler::CmpNeS(FRegister fd, FRegister fs, FRegister ft) {
   1508   CHECK(IsR6());
   1509   DsFsmInstrFff(EmitFR(0x11, 0x14, ft, fs, fd, 0x13), fd, fs, ft);
   1510 }
   1511 
   1512 void MipsAssembler::CmpUnD(FRegister fd, FRegister fs, FRegister ft) {
   1513   CHECK(IsR6());
   1514   DsFsmInstrFff(EmitFR(0x11, 0x15, ft, fs, fd, 0x01), fd, fs, ft);
   1515 }
   1516 
   1517 void MipsAssembler::CmpEqD(FRegister fd, FRegister fs, FRegister ft) {
   1518   CHECK(IsR6());
   1519   DsFsmInstrFff(EmitFR(0x11, 0x15, ft, fs, fd, 0x02), fd, fs, ft);
   1520 }
   1521 
   1522 void MipsAssembler::CmpUeqD(FRegister fd, FRegister fs, FRegister ft) {
   1523   CHECK(IsR6());
   1524   DsFsmInstrFff(EmitFR(0x11, 0x15, ft, fs, fd, 0x03), fd, fs, ft);
   1525 }
   1526 
   1527 void MipsAssembler::CmpLtD(FRegister fd, FRegister fs, FRegister ft) {
   1528   CHECK(IsR6());
   1529   DsFsmInstrFff(EmitFR(0x11, 0x15, ft, fs, fd, 0x04), fd, fs, ft);
   1530 }
   1531 
   1532 void MipsAssembler::CmpUltD(FRegister fd, FRegister fs, FRegister ft) {
   1533   CHECK(IsR6());
   1534   DsFsmInstrFff(EmitFR(0x11, 0x15, ft, fs, fd, 0x05), fd, fs, ft);
   1535 }
   1536 
   1537 void MipsAssembler::CmpLeD(FRegister fd, FRegister fs, FRegister ft) {
   1538   CHECK(IsR6());
   1539   DsFsmInstrFff(EmitFR(0x11, 0x15, ft, fs, fd, 0x06), fd, fs, ft);
   1540 }
   1541 
   1542 void MipsAssembler::CmpUleD(FRegister fd, FRegister fs, FRegister ft) {
   1543   CHECK(IsR6());
   1544   DsFsmInstrFff(EmitFR(0x11, 0x15, ft, fs, fd, 0x07), fd, fs, ft);
   1545 }
   1546 
   1547 void MipsAssembler::CmpOrD(FRegister fd, FRegister fs, FRegister ft) {
   1548   CHECK(IsR6());
   1549   DsFsmInstrFff(EmitFR(0x11, 0x15, ft, fs, fd, 0x11), fd, fs, ft);
   1550 }
   1551 
   1552 void MipsAssembler::CmpUneD(FRegister fd, FRegister fs, FRegister ft) {
   1553   CHECK(IsR6());
   1554   DsFsmInstrFff(EmitFR(0x11, 0x15, ft, fs, fd, 0x12), fd, fs, ft);
   1555 }
   1556 
   1557 void MipsAssembler::CmpNeD(FRegister fd, FRegister fs, FRegister ft) {
   1558   CHECK(IsR6());
   1559   DsFsmInstrFff(EmitFR(0x11, 0x15, ft, fs, fd, 0x13), fd, fs, ft);
   1560 }
   1561 
   1562 void MipsAssembler::Movf(Register rd, Register rs, int cc) {
   1563   CHECK(!IsR6());
   1564   CHECK(IsUint<3>(cc)) << cc;
   1565   DsFsmInstrRrrc(EmitR(0, rs, static_cast<Register>(cc << 2), rd, 0, 0x01), rd, rs, cc);
   1566 }
   1567 
   1568 void MipsAssembler::Movt(Register rd, Register rs, int cc) {
   1569   CHECK(!IsR6());
   1570   CHECK(IsUint<3>(cc)) << cc;
   1571   DsFsmInstrRrrc(EmitR(0, rs, static_cast<Register>((cc << 2) | 1), rd, 0, 0x01), rd, rs, cc);
   1572 }
   1573 
   1574 void MipsAssembler::MovfS(FRegister fd, FRegister fs, int cc) {
   1575   CHECK(!IsR6());
   1576   CHECK(IsUint<3>(cc)) << cc;
   1577   DsFsmInstrFffc(EmitFR(0x11, 0x10, static_cast<FRegister>(cc << 2), fs, fd, 0x11), fd, fs, cc);
   1578 }
   1579 
   1580 void MipsAssembler::MovfD(FRegister fd, FRegister fs, int cc) {
   1581   CHECK(!IsR6());
   1582   CHECK(IsUint<3>(cc)) << cc;
   1583   DsFsmInstrFffc(EmitFR(0x11, 0x11, static_cast<FRegister>(cc << 2), fs, fd, 0x11), fd, fs, cc);
   1584 }
   1585 
   1586 void MipsAssembler::MovtS(FRegister fd, FRegister fs, int cc) {
   1587   CHECK(!IsR6());
   1588   CHECK(IsUint<3>(cc)) << cc;
   1589   DsFsmInstrFffc(EmitFR(0x11, 0x10, static_cast<FRegister>((cc << 2) | 1), fs, fd, 0x11),
   1590                  fd,
   1591                  fs,
   1592                  cc);
   1593 }
   1594 
   1595 void MipsAssembler::MovtD(FRegister fd, FRegister fs, int cc) {
   1596   CHECK(!IsR6());
   1597   CHECK(IsUint<3>(cc)) << cc;
   1598   DsFsmInstrFffc(EmitFR(0x11, 0x11, static_cast<FRegister>((cc << 2) | 1), fs, fd, 0x11),
   1599                  fd,
   1600                  fs,
   1601                  cc);
   1602 }
   1603 
   1604 void MipsAssembler::MovzS(FRegister fd, FRegister fs, Register rt) {
   1605   CHECK(!IsR6());
   1606   DsFsmInstrFffr(EmitFR(0x11, 0x10, static_cast<FRegister>(rt), fs, fd, 0x12), fd, fs, rt);
   1607 }
   1608 
   1609 void MipsAssembler::MovzD(FRegister fd, FRegister fs, Register rt) {
   1610   CHECK(!IsR6());
   1611   DsFsmInstrFffr(EmitFR(0x11, 0x11, static_cast<FRegister>(rt), fs, fd, 0x12), fd, fs, rt);
   1612 }
   1613 
   1614 void MipsAssembler::MovnS(FRegister fd, FRegister fs, Register rt) {
   1615   CHECK(!IsR6());
   1616   DsFsmInstrFffr(EmitFR(0x11, 0x10, static_cast<FRegister>(rt), fs, fd, 0x13), fd, fs, rt);
   1617 }
   1618 
   1619 void MipsAssembler::MovnD(FRegister fd, FRegister fs, Register rt) {
   1620   CHECK(!IsR6());
   1621   DsFsmInstrFffr(EmitFR(0x11, 0x11, static_cast<FRegister>(rt), fs, fd, 0x13), fd, fs, rt);
   1622 }
   1623 
   1624 void MipsAssembler::SelS(FRegister fd, FRegister fs, FRegister ft) {
   1625   CHECK(IsR6());
   1626   DsFsmInstrFfff(EmitFR(0x11, 0x10, ft, fs, fd, 0x10), fd, fs, ft);
   1627 }
   1628 
   1629 void MipsAssembler::SelD(FRegister fd, FRegister fs, FRegister ft) {
   1630   CHECK(IsR6());
   1631   DsFsmInstrFfff(EmitFR(0x11, 0x11, ft, fs, fd, 0x10), fd, fs, ft);
   1632 }
   1633 
   1634 void MipsAssembler::SeleqzS(FRegister fd, FRegister fs, FRegister ft) {
   1635   CHECK(IsR6());
   1636   DsFsmInstrFff(EmitFR(0x11, 0x10, ft, fs, fd, 0x14), fd, fs, ft);
   1637 }
   1638 
   1639 void MipsAssembler::SeleqzD(FRegister fd, FRegister fs, FRegister ft) {
   1640   CHECK(IsR6());
   1641   DsFsmInstrFff(EmitFR(0x11, 0x11, ft, fs, fd, 0x14), fd, fs, ft);
   1642 }
   1643 
   1644 void MipsAssembler::SelnezS(FRegister fd, FRegister fs, FRegister ft) {
   1645   CHECK(IsR6());
   1646   DsFsmInstrFff(EmitFR(0x11, 0x10, ft, fs, fd, 0x17), fd, fs, ft);
   1647 }
   1648 
   1649 void MipsAssembler::SelnezD(FRegister fd, FRegister fs, FRegister ft) {
   1650   CHECK(IsR6());
   1651   DsFsmInstrFff(EmitFR(0x11, 0x11, ft, fs, fd, 0x17), fd, fs, ft);
   1652 }
   1653 
   1654 void MipsAssembler::ClassS(FRegister fd, FRegister fs) {
   1655   CHECK(IsR6());
   1656   DsFsmInstrFff(EmitFR(0x11, 0x10, static_cast<FRegister>(0), fs, fd, 0x1b), fd, fs, fs);
   1657 }
   1658 
   1659 void MipsAssembler::ClassD(FRegister fd, FRegister fs) {
   1660   CHECK(IsR6());
   1661   DsFsmInstrFff(EmitFR(0x11, 0x11, static_cast<FRegister>(0), fs, fd, 0x1b), fd, fs, fs);
   1662 }
   1663 
   1664 void MipsAssembler::MinS(FRegister fd, FRegister fs, FRegister ft) {
   1665   CHECK(IsR6());
   1666   DsFsmInstrFff(EmitFR(0x11, 0x10, ft, fs, fd, 0x1c), fd, fs, ft);
   1667 }
   1668 
   1669 void MipsAssembler::MinD(FRegister fd, FRegister fs, FRegister ft) {
   1670   CHECK(IsR6());
   1671   DsFsmInstrFff(EmitFR(0x11, 0x11, ft, fs, fd, 0x1c), fd, fs, ft);
   1672 }
   1673 
   1674 void MipsAssembler::MaxS(FRegister fd, FRegister fs, FRegister ft) {
   1675   CHECK(IsR6());
   1676   DsFsmInstrFff(EmitFR(0x11, 0x10, ft, fs, fd, 0x1e), fd, fs, ft);
   1677 }
   1678 
   1679 void MipsAssembler::MaxD(FRegister fd, FRegister fs, FRegister ft) {
   1680   CHECK(IsR6());
   1681   DsFsmInstrFff(EmitFR(0x11, 0x11, ft, fs, fd, 0x1e), fd, fs, ft);
   1682 }
   1683 
   1684 void MipsAssembler::TruncLS(FRegister fd, FRegister fs) {
   1685   DsFsmInstrFff(EmitFR(0x11, 0x10, static_cast<FRegister>(0), fs, fd, 0x09), fd, fs, fs);
   1686 }
   1687 
   1688 void MipsAssembler::TruncLD(FRegister fd, FRegister fs) {
   1689   DsFsmInstrFff(EmitFR(0x11, 0x11, static_cast<FRegister>(0), fs, fd, 0x09), fd, fs, fs);
   1690 }
   1691 
   1692 void MipsAssembler::TruncWS(FRegister fd, FRegister fs) {
   1693   DsFsmInstrFff(EmitFR(0x11, 0x10, static_cast<FRegister>(0), fs, fd, 0x0D), fd, fs, fs);
   1694 }
   1695 
   1696 void MipsAssembler::TruncWD(FRegister fd, FRegister fs) {
   1697   DsFsmInstrFff(EmitFR(0x11, 0x11, static_cast<FRegister>(0), fs, fd, 0x0D), fd, fs, fs);
   1698 }
   1699 
   1700 void MipsAssembler::Cvtsw(FRegister fd, FRegister fs) {
   1701   DsFsmInstrFff(EmitFR(0x11, 0x14, static_cast<FRegister>(0), fs, fd, 0x20), fd, fs, fs);
   1702 }
   1703 
   1704 void MipsAssembler::Cvtdw(FRegister fd, FRegister fs) {
   1705   DsFsmInstrFff(EmitFR(0x11, 0x14, static_cast<FRegister>(0), fs, fd, 0x21), fd, fs, fs);
   1706 }
   1707 
   1708 void MipsAssembler::Cvtsd(FRegister fd, FRegister fs) {
   1709   DsFsmInstrFff(EmitFR(0x11, 0x11, static_cast<FRegister>(0), fs, fd, 0x20), fd, fs, fs);
   1710 }
   1711 
   1712 void MipsAssembler::Cvtds(FRegister fd, FRegister fs) {
   1713   DsFsmInstrFff(EmitFR(0x11, 0x10, static_cast<FRegister>(0), fs, fd, 0x21), fd, fs, fs);
   1714 }
   1715 
   1716 void MipsAssembler::Cvtsl(FRegister fd, FRegister fs) {
   1717   DsFsmInstrFff(EmitFR(0x11, 0x15, static_cast<FRegister>(0), fs, fd, 0x20), fd, fs, fs);
   1718 }
   1719 
   1720 void MipsAssembler::Cvtdl(FRegister fd, FRegister fs) {
   1721   DsFsmInstrFff(EmitFR(0x11, 0x15, static_cast<FRegister>(0), fs, fd, 0x21), fd, fs, fs);
   1722 }
   1723 
   1724 void MipsAssembler::FloorWS(FRegister fd, FRegister fs) {
   1725   DsFsmInstrFff(EmitFR(0x11, 0x10, static_cast<FRegister>(0), fs, fd, 0xf), fd, fs, fs);
   1726 }
   1727 
   1728 void MipsAssembler::FloorWD(FRegister fd, FRegister fs) {
   1729   DsFsmInstrFff(EmitFR(0x11, 0x11, static_cast<FRegister>(0), fs, fd, 0xf), fd, fs, fs);
   1730 }
   1731 
   1732 void MipsAssembler::Mfc1(Register rt, FRegister fs) {
   1733   DsFsmInstrRf(EmitFR(0x11, 0x00, static_cast<FRegister>(rt), fs, static_cast<FRegister>(0), 0x0),
   1734                rt,
   1735                fs);
   1736 }
   1737 
   1738 void MipsAssembler::Mtc1(Register rt, FRegister fs) {
   1739   DsFsmInstrFr(EmitFR(0x11, 0x04, static_cast<FRegister>(rt), fs, static_cast<FRegister>(0), 0x0),
   1740                fs,
   1741                rt);
   1742 }
   1743 
   1744 void MipsAssembler::Mfhc1(Register rt, FRegister fs) {
   1745   DsFsmInstrRf(EmitFR(0x11, 0x03, static_cast<FRegister>(rt), fs, static_cast<FRegister>(0), 0x0),
   1746                rt,
   1747                fs);
   1748 }
   1749 
   1750 void MipsAssembler::Mthc1(Register rt, FRegister fs) {
   1751   DsFsmInstrFr(EmitFR(0x11, 0x07, static_cast<FRegister>(rt), fs, static_cast<FRegister>(0), 0x0),
   1752                fs,
   1753                rt);
   1754 }
   1755 
   1756 void MipsAssembler::MoveFromFpuHigh(Register rt, FRegister fs) {
   1757   if (Is32BitFPU()) {
   1758     CHECK_EQ(fs % 2, 0) << fs;
   1759     Mfc1(rt, static_cast<FRegister>(fs + 1));
   1760   } else {
   1761     Mfhc1(rt, fs);
   1762   }
   1763 }
   1764 
   1765 void MipsAssembler::MoveToFpuHigh(Register rt, FRegister fs) {
   1766   if (Is32BitFPU()) {
   1767     CHECK_EQ(fs % 2, 0) << fs;
   1768     Mtc1(rt, static_cast<FRegister>(fs + 1));
   1769   } else {
   1770     Mthc1(rt, fs);
   1771   }
   1772 }
   1773 
   1774 void MipsAssembler::Lwc1(FRegister ft, Register rs, uint16_t imm16) {
   1775   DsFsmInstrFr(EmitI(0x31, rs, static_cast<Register>(ft), imm16), ft, rs);
   1776 }
   1777 
   1778 void MipsAssembler::Ldc1(FRegister ft, Register rs, uint16_t imm16) {
   1779   DsFsmInstrFr(EmitI(0x35, rs, static_cast<Register>(ft), imm16), ft, rs);
   1780 }
   1781 
   1782 void MipsAssembler::Swc1(FRegister ft, Register rs, uint16_t imm16) {
   1783   DsFsmInstrFR(EmitI(0x39, rs, static_cast<Register>(ft), imm16), ft, rs);
   1784 }
   1785 
   1786 void MipsAssembler::Sdc1(FRegister ft, Register rs, uint16_t imm16) {
   1787   DsFsmInstrFR(EmitI(0x3d, rs, static_cast<Register>(ft), imm16), ft, rs);
   1788 }
   1789 
   1790 void MipsAssembler::Break() {
   1791   DsFsmInstrNop(EmitR(0, ZERO, ZERO, ZERO, 0, 0xD));
   1792 }
   1793 
   1794 void MipsAssembler::Nop() {
   1795   DsFsmInstrNop(EmitR(0x0, ZERO, ZERO, ZERO, 0, 0x0));
   1796 }
   1797 
   1798 void MipsAssembler::NopIfNoReordering() {
   1799   if (!reordering_) {
   1800     Nop();
   1801   }
   1802 }
   1803 
   1804 void MipsAssembler::Move(Register rd, Register rs) {
   1805   Or(rd, rs, ZERO);
   1806 }
   1807 
   1808 void MipsAssembler::Clear(Register rd) {
   1809   Move(rd, ZERO);
   1810 }
   1811 
   1812 void MipsAssembler::Not(Register rd, Register rs) {
   1813   Nor(rd, rs, ZERO);
   1814 }
   1815 
   1816 void MipsAssembler::Push(Register rs) {
   1817   IncreaseFrameSize(kMipsWordSize);
   1818   Sw(rs, SP, 0);
   1819 }
   1820 
   1821 void MipsAssembler::Pop(Register rd) {
   1822   Lw(rd, SP, 0);
   1823   DecreaseFrameSize(kMipsWordSize);
   1824 }
   1825 
   1826 void MipsAssembler::PopAndReturn(Register rd, Register rt) {
   1827   bool reordering = SetReorder(false);
   1828   Lw(rd, SP, 0);
   1829   Jr(rt);
   1830   DecreaseFrameSize(kMipsWordSize);  // Single instruction in delay slot.
   1831   SetReorder(reordering);
   1832 }
   1833 
   1834 void MipsAssembler::AndV(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   1835   CHECK(HasMsa());
   1836   DsFsmInstrFff(EmitMsa3R(0x0, 0x0, wt, ws, wd, 0x1e),
   1837                 static_cast<FRegister>(wd),
   1838                 static_cast<FRegister>(ws),
   1839                 static_cast<FRegister>(wt));
   1840 }
   1841 
   1842 void MipsAssembler::OrV(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   1843   CHECK(HasMsa());
   1844   DsFsmInstrFff(EmitMsa3R(0x0, 0x1, wt, ws, wd, 0x1e),
   1845                 static_cast<FRegister>(wd),
   1846                 static_cast<FRegister>(ws),
   1847                 static_cast<FRegister>(wt));
   1848 }
   1849 
   1850 void MipsAssembler::NorV(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   1851   CHECK(HasMsa());
   1852   DsFsmInstrFff(EmitMsa3R(0x0, 0x2, wt, ws, wd, 0x1e),
   1853                 static_cast<FRegister>(wd),
   1854                 static_cast<FRegister>(ws),
   1855                 static_cast<FRegister>(wt));
   1856 }
   1857 
   1858 void MipsAssembler::XorV(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   1859   CHECK(HasMsa());
   1860   DsFsmInstrFff(EmitMsa3R(0x0, 0x3, wt, ws, wd, 0x1e),
   1861                 static_cast<FRegister>(wd),
   1862                 static_cast<FRegister>(ws),
   1863                 static_cast<FRegister>(wt));
   1864 }
   1865 
   1866 void MipsAssembler::AddvB(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   1867   CHECK(HasMsa());
   1868   DsFsmInstrFff(EmitMsa3R(0x0, 0x0, wt, ws, wd, 0xe),
   1869                 static_cast<FRegister>(wd),
   1870                 static_cast<FRegister>(ws),
   1871                 static_cast<FRegister>(wt));
   1872 }
   1873 
   1874 void MipsAssembler::AddvH(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   1875   CHECK(HasMsa());
   1876   DsFsmInstrFff(EmitMsa3R(0x0, 0x1, wt, ws, wd, 0xe),
   1877                 static_cast<FRegister>(wd),
   1878                 static_cast<FRegister>(ws),
   1879                 static_cast<FRegister>(wt));
   1880 }
   1881 
   1882 void MipsAssembler::AddvW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   1883   CHECK(HasMsa());
   1884   DsFsmInstrFff(EmitMsa3R(0x0, 0x2, wt, ws, wd, 0xe),
   1885                 static_cast<FRegister>(wd),
   1886                 static_cast<FRegister>(ws),
   1887                 static_cast<FRegister>(wt));
   1888 }
   1889 
   1890 void MipsAssembler::AddvD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   1891   CHECK(HasMsa());
   1892   DsFsmInstrFff(EmitMsa3R(0x0, 0x3, wt, ws, wd, 0xe),
   1893                 static_cast<FRegister>(wd),
   1894                 static_cast<FRegister>(ws),
   1895                 static_cast<FRegister>(wt));
   1896 }
   1897 
   1898 void MipsAssembler::SubvB(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   1899   CHECK(HasMsa());
   1900   DsFsmInstrFff(EmitMsa3R(0x1, 0x0, wt, ws, wd, 0xe),
   1901                 static_cast<FRegister>(wd),
   1902                 static_cast<FRegister>(ws),
   1903                 static_cast<FRegister>(wt));
   1904 }
   1905 
   1906 void MipsAssembler::SubvH(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   1907   CHECK(HasMsa());
   1908   DsFsmInstrFff(EmitMsa3R(0x1, 0x1, wt, ws, wd, 0xe),
   1909                 static_cast<FRegister>(wd),
   1910                 static_cast<FRegister>(ws),
   1911                 static_cast<FRegister>(wt));
   1912 }
   1913 
   1914 void MipsAssembler::SubvW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   1915   CHECK(HasMsa());
   1916   DsFsmInstrFff(EmitMsa3R(0x1, 0x2, wt, ws, wd, 0xe),
   1917                 static_cast<FRegister>(wd),
   1918                 static_cast<FRegister>(ws),
   1919                 static_cast<FRegister>(wt));
   1920 }
   1921 
   1922 void MipsAssembler::SubvD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   1923   CHECK(HasMsa());
   1924   DsFsmInstrFff(EmitMsa3R(0x1, 0x3, wt, ws, wd, 0xe),
   1925                 static_cast<FRegister>(wd),
   1926                 static_cast<FRegister>(ws),
   1927                 static_cast<FRegister>(wt));
   1928 }
   1929 
   1930 void MipsAssembler::MulvB(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   1931   CHECK(HasMsa());
   1932   DsFsmInstrFff(EmitMsa3R(0x0, 0x0, wt, ws, wd, 0x12),
   1933                 static_cast<FRegister>(wd),
   1934                 static_cast<FRegister>(ws),
   1935                 static_cast<FRegister>(wt));
   1936 }
   1937 
   1938 void MipsAssembler::MulvH(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   1939   CHECK(HasMsa());
   1940   DsFsmInstrFff(EmitMsa3R(0x0, 0x1, wt, ws, wd, 0x12),
   1941                 static_cast<FRegister>(wd),
   1942                 static_cast<FRegister>(ws),
   1943                 static_cast<FRegister>(wt));
   1944 }
   1945 
   1946 void MipsAssembler::MulvW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   1947   CHECK(HasMsa());
   1948   DsFsmInstrFff(EmitMsa3R(0x0, 0x2, wt, ws, wd, 0x12),
   1949                 static_cast<FRegister>(wd),
   1950                 static_cast<FRegister>(ws),
   1951                 static_cast<FRegister>(wt));
   1952 }
   1953 
   1954 void MipsAssembler::MulvD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   1955   CHECK(HasMsa());
   1956   DsFsmInstrFff(EmitMsa3R(0x0, 0x3, wt, ws, wd, 0x12),
   1957                 static_cast<FRegister>(wd),
   1958                 static_cast<FRegister>(ws),
   1959                 static_cast<FRegister>(wt));
   1960 }
   1961 
   1962 void MipsAssembler::Div_sB(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   1963   CHECK(HasMsa());
   1964   DsFsmInstrFff(EmitMsa3R(0x4, 0x0, wt, ws, wd, 0x12),
   1965                 static_cast<FRegister>(wd),
   1966                 static_cast<FRegister>(ws),
   1967                 static_cast<FRegister>(wt));
   1968 }
   1969 
   1970 void MipsAssembler::Div_sH(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   1971   CHECK(HasMsa());
   1972   DsFsmInstrFff(EmitMsa3R(0x4, 0x1, wt, ws, wd, 0x12),
   1973                 static_cast<FRegister>(wd),
   1974                 static_cast<FRegister>(ws),
   1975                 static_cast<FRegister>(wt));
   1976 }
   1977 
   1978 void MipsAssembler::Div_sW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   1979   CHECK(HasMsa());
   1980   DsFsmInstrFff(EmitMsa3R(0x4, 0x2, wt, ws, wd, 0x12),
   1981                 static_cast<FRegister>(wd),
   1982                 static_cast<FRegister>(ws),
   1983                 static_cast<FRegister>(wt));
   1984 }
   1985 
   1986 void MipsAssembler::Div_sD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   1987   CHECK(HasMsa());
   1988   DsFsmInstrFff(EmitMsa3R(0x4, 0x3, wt, ws, wd, 0x12),
   1989                 static_cast<FRegister>(wd),
   1990                 static_cast<FRegister>(ws),
   1991                 static_cast<FRegister>(wt));
   1992 }
   1993 
   1994 void MipsAssembler::Div_uB(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   1995   CHECK(HasMsa());
   1996   DsFsmInstrFff(EmitMsa3R(0x5, 0x0, wt, ws, wd, 0x12),
   1997                 static_cast<FRegister>(wd),
   1998                 static_cast<FRegister>(ws),
   1999                 static_cast<FRegister>(wt));
   2000 }
   2001 
   2002 void MipsAssembler::Div_uH(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   2003   CHECK(HasMsa());
   2004   DsFsmInstrFff(EmitMsa3R(0x5, 0x1, wt, ws, wd, 0x12),
   2005                 static_cast<FRegister>(wd),
   2006                 static_cast<FRegister>(ws),
   2007                 static_cast<FRegister>(wt));
   2008 }
   2009 
   2010 void MipsAssembler::Div_uW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   2011   CHECK(HasMsa());
   2012   DsFsmInstrFff(EmitMsa3R(0x5, 0x2, wt, ws, wd, 0x12),
   2013                 static_cast<FRegister>(wd),
   2014                 static_cast<FRegister>(ws),
   2015                 static_cast<FRegister>(wt));
   2016 }
   2017 
   2018 void MipsAssembler::Div_uD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   2019   CHECK(HasMsa());
   2020   DsFsmInstrFff(EmitMsa3R(0x5, 0x3, wt, ws, wd, 0x12),
   2021                 static_cast<FRegister>(wd),
   2022                 static_cast<FRegister>(ws),
   2023                 static_cast<FRegister>(wt));
   2024 }
   2025 
   2026 void MipsAssembler::Mod_sB(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   2027   CHECK(HasMsa());
   2028   DsFsmInstrFff(EmitMsa3R(0x6, 0x0, wt, ws, wd, 0x12),
   2029                 static_cast<FRegister>(wd),
   2030                 static_cast<FRegister>(ws),
   2031                 static_cast<FRegister>(wt));
   2032 }
   2033 
   2034 void MipsAssembler::Mod_sH(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   2035   CHECK(HasMsa());
   2036   DsFsmInstrFff(EmitMsa3R(0x6, 0x1, wt, ws, wd, 0x12),
   2037                 static_cast<FRegister>(wd),
   2038                 static_cast<FRegister>(ws),
   2039                 static_cast<FRegister>(wt));
   2040 }
   2041 
   2042 void MipsAssembler::Mod_sW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   2043   CHECK(HasMsa());
   2044   DsFsmInstrFff(EmitMsa3R(0x6, 0x2, wt, ws, wd, 0x12),
   2045                 static_cast<FRegister>(wd),
   2046                 static_cast<FRegister>(ws),
   2047                 static_cast<FRegister>(wt));
   2048 }
   2049 
   2050 void MipsAssembler::Mod_sD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   2051   CHECK(HasMsa());
   2052   DsFsmInstrFff(EmitMsa3R(0x6, 0x3, wt, ws, wd, 0x12),
   2053                 static_cast<FRegister>(wd),
   2054                 static_cast<FRegister>(ws),
   2055                 static_cast<FRegister>(wt));
   2056 }
   2057 
   2058 void MipsAssembler::Mod_uB(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   2059   CHECK(HasMsa());
   2060   DsFsmInstrFff(EmitMsa3R(0x7, 0x0, wt, ws, wd, 0x12),
   2061                 static_cast<FRegister>(wd),
   2062                 static_cast<FRegister>(ws),
   2063                 static_cast<FRegister>(wt));
   2064 }
   2065 
   2066 void MipsAssembler::Mod_uH(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   2067   CHECK(HasMsa());
   2068   DsFsmInstrFff(EmitMsa3R(0x7, 0x1, wt, ws, wd, 0x12),
   2069                 static_cast<FRegister>(wd),
   2070                 static_cast<FRegister>(ws),
   2071                 static_cast<FRegister>(wt));
   2072 }
   2073 
   2074 void MipsAssembler::Mod_uW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   2075   CHECK(HasMsa());
   2076   DsFsmInstrFff(EmitMsa3R(0x7, 0x2, wt, ws, wd, 0x12),
   2077                 static_cast<FRegister>(wd),
   2078                 static_cast<FRegister>(ws),
   2079                 static_cast<FRegister>(wt));
   2080 }
   2081 
   2082 void MipsAssembler::Mod_uD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   2083   CHECK(HasMsa());
   2084   DsFsmInstrFff(EmitMsa3R(0x7, 0x3, wt, ws, wd, 0x12),
   2085                 static_cast<FRegister>(wd),
   2086                 static_cast<FRegister>(ws),
   2087                 static_cast<FRegister>(wt));
   2088 }
   2089 
   2090 void MipsAssembler::Add_aB(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   2091   CHECK(HasMsa());
   2092   DsFsmInstrFff(EmitMsa3R(0x0, 0x0, wt, ws, wd, 0x10),
   2093                 static_cast<FRegister>(wd),
   2094                 static_cast<FRegister>(ws),
   2095                 static_cast<FRegister>(wt));
   2096 }
   2097 
   2098 void MipsAssembler::Add_aH(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   2099   CHECK(HasMsa());
   2100   DsFsmInstrFff(EmitMsa3R(0x0, 0x1, wt, ws, wd, 0x10),
   2101                 static_cast<FRegister>(wd),
   2102                 static_cast<FRegister>(ws),
   2103                 static_cast<FRegister>(wt));
   2104 }
   2105 
   2106 void MipsAssembler::Add_aW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   2107   CHECK(HasMsa());
   2108   DsFsmInstrFff(EmitMsa3R(0x0, 0x2, wt, ws, wd, 0x10),
   2109                 static_cast<FRegister>(wd),
   2110                 static_cast<FRegister>(ws),
   2111                 static_cast<FRegister>(wt));
   2112 }
   2113 
   2114 void MipsAssembler::Add_aD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   2115   CHECK(HasMsa());
   2116   DsFsmInstrFff(EmitMsa3R(0x0, 0x3, wt, ws, wd, 0x10),
   2117                 static_cast<FRegister>(wd),
   2118                 static_cast<FRegister>(ws),
   2119                 static_cast<FRegister>(wt));
   2120 }
   2121 
   2122 void MipsAssembler::Ave_sB(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   2123   CHECK(HasMsa());
   2124   DsFsmInstrFff(EmitMsa3R(0x4, 0x0, wt, ws, wd, 0x10),
   2125                 static_cast<FRegister>(wd),
   2126                 static_cast<FRegister>(ws),
   2127                 static_cast<FRegister>(wt));
   2128 }
   2129 
   2130 void MipsAssembler::Ave_sH(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   2131   CHECK(HasMsa());
   2132   DsFsmInstrFff(EmitMsa3R(0x4, 0x1, wt, ws, wd, 0x10),
   2133                 static_cast<FRegister>(wd),
   2134                 static_cast<FRegister>(ws),
   2135                 static_cast<FRegister>(wt));
   2136 }
   2137 
   2138 void MipsAssembler::Ave_sW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   2139   CHECK(HasMsa());
   2140   DsFsmInstrFff(EmitMsa3R(0x4, 0x2, wt, ws, wd, 0x10),
   2141                 static_cast<FRegister>(wd),
   2142                 static_cast<FRegister>(ws),
   2143                 static_cast<FRegister>(wt));
   2144 }
   2145 
   2146 void MipsAssembler::Ave_sD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   2147   CHECK(HasMsa());
   2148   DsFsmInstrFff(EmitMsa3R(0x4, 0x3, wt, ws, wd, 0x10),
   2149                 static_cast<FRegister>(wd),
   2150                 static_cast<FRegister>(ws),
   2151                 static_cast<FRegister>(wt));
   2152 }
   2153 
   2154 void MipsAssembler::Ave_uB(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   2155   CHECK(HasMsa());
   2156   DsFsmInstrFff(EmitMsa3R(0x5, 0x0, wt, ws, wd, 0x10),
   2157                 static_cast<FRegister>(wd),
   2158                 static_cast<FRegister>(ws),
   2159                 static_cast<FRegister>(wt));
   2160 }
   2161 
   2162 void MipsAssembler::Ave_uH(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   2163   CHECK(HasMsa());
   2164   DsFsmInstrFff(EmitMsa3R(0x5, 0x1, wt, ws, wd, 0x10),
   2165                 static_cast<FRegister>(wd),
   2166                 static_cast<FRegister>(ws),
   2167                 static_cast<FRegister>(wt));
   2168 }
   2169 
   2170 void MipsAssembler::Ave_uW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   2171   CHECK(HasMsa());
   2172   DsFsmInstrFff(EmitMsa3R(0x5, 0x2, wt, ws, wd, 0x10),
   2173                 static_cast<FRegister>(wd),
   2174                 static_cast<FRegister>(ws),
   2175                 static_cast<FRegister>(wt));
   2176 }
   2177 
   2178 void MipsAssembler::Ave_uD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   2179   CHECK(HasMsa());
   2180   DsFsmInstrFff(EmitMsa3R(0x5, 0x3, wt, ws, wd, 0x10),
   2181                 static_cast<FRegister>(wd),
   2182                 static_cast<FRegister>(ws),
   2183                 static_cast<FRegister>(wt));
   2184 }
   2185 
   2186 void MipsAssembler::Aver_sB(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   2187   CHECK(HasMsa());
   2188   DsFsmInstrFff(EmitMsa3R(0x6, 0x0, wt, ws, wd, 0x10),
   2189                 static_cast<FRegister>(wd),
   2190                 static_cast<FRegister>(ws),
   2191                 static_cast<FRegister>(wt));
   2192 }
   2193 
   2194 void MipsAssembler::Aver_sH(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   2195   CHECK(HasMsa());
   2196   DsFsmInstrFff(EmitMsa3R(0x6, 0x1, wt, ws, wd, 0x10),
   2197                 static_cast<FRegister>(wd),
   2198                 static_cast<FRegister>(ws),
   2199                 static_cast<FRegister>(wt));
   2200 }
   2201 
   2202 void MipsAssembler::Aver_sW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   2203   CHECK(HasMsa());
   2204   DsFsmInstrFff(EmitMsa3R(0x6, 0x2, wt, ws, wd, 0x10),
   2205                 static_cast<FRegister>(wd),
   2206                 static_cast<FRegister>(ws),
   2207                 static_cast<FRegister>(wt));
   2208 }
   2209 
   2210 void MipsAssembler::Aver_sD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   2211   CHECK(HasMsa());
   2212   DsFsmInstrFff(EmitMsa3R(0x6, 0x3, wt, ws, wd, 0x10),
   2213                 static_cast<FRegister>(wd),
   2214                 static_cast<FRegister>(ws),
   2215                 static_cast<FRegister>(wt));
   2216 }
   2217 
   2218 void MipsAssembler::Aver_uB(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   2219   CHECK(HasMsa());
   2220   DsFsmInstrFff(EmitMsa3R(0x7, 0x0, wt, ws, wd, 0x10),
   2221                 static_cast<FRegister>(wd),
   2222                 static_cast<FRegister>(ws),
   2223                 static_cast<FRegister>(wt));
   2224 }
   2225 
   2226 void MipsAssembler::Aver_uH(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   2227   CHECK(HasMsa());
   2228   DsFsmInstrFff(EmitMsa3R(0x7, 0x1, wt, ws, wd, 0x10),
   2229                 static_cast<FRegister>(wd),
   2230                 static_cast<FRegister>(ws),
   2231                 static_cast<FRegister>(wt));
   2232 }
   2233 
   2234 void MipsAssembler::Aver_uW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   2235   CHECK(HasMsa());
   2236   DsFsmInstrFff(EmitMsa3R(0x7, 0x2, wt, ws, wd, 0x10),
   2237                 static_cast<FRegister>(wd),
   2238                 static_cast<FRegister>(ws),
   2239                 static_cast<FRegister>(wt));
   2240 }
   2241 
   2242 void MipsAssembler::Aver_uD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   2243   CHECK(HasMsa());
   2244   DsFsmInstrFff(EmitMsa3R(0x7, 0x3, wt, ws, wd, 0x10),
   2245                 static_cast<FRegister>(wd),
   2246                 static_cast<FRegister>(ws),
   2247                 static_cast<FRegister>(wt));
   2248 }
   2249 
   2250 void MipsAssembler::Max_sB(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   2251   CHECK(HasMsa());
   2252   DsFsmInstrFff(EmitMsa3R(0x2, 0x0, wt, ws, wd, 0xe),
   2253                 static_cast<FRegister>(wd),
   2254                 static_cast<FRegister>(ws),
   2255                 static_cast<FRegister>(wt));
   2256 }
   2257 
   2258 void MipsAssembler::Max_sH(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   2259   CHECK(HasMsa());
   2260   DsFsmInstrFff(EmitMsa3R(0x2, 0x1, wt, ws, wd, 0xe),
   2261                 static_cast<FRegister>(wd),
   2262                 static_cast<FRegister>(ws),
   2263                 static_cast<FRegister>(wt));
   2264 }
   2265 
   2266 void MipsAssembler::Max_sW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   2267   CHECK(HasMsa());
   2268   DsFsmInstrFff(EmitMsa3R(0x2, 0x2, wt, ws, wd, 0xe),
   2269                 static_cast<FRegister>(wd),
   2270                 static_cast<FRegister>(ws),
   2271                 static_cast<FRegister>(wt));
   2272 }
   2273 
   2274 void MipsAssembler::Max_sD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   2275   CHECK(HasMsa());
   2276   DsFsmInstrFff(EmitMsa3R(0x2, 0x3, wt, ws, wd, 0xe),
   2277                 static_cast<FRegister>(wd),
   2278                 static_cast<FRegister>(ws),
   2279                 static_cast<FRegister>(wt));
   2280 }
   2281 
   2282 void MipsAssembler::Max_uB(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   2283   CHECK(HasMsa());
   2284   DsFsmInstrFff(EmitMsa3R(0x3, 0x0, wt, ws, wd, 0xe),
   2285                 static_cast<FRegister>(wd),
   2286                 static_cast<FRegister>(ws),
   2287                 static_cast<FRegister>(wt));
   2288 }
   2289 
   2290 void MipsAssembler::Max_uH(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   2291   CHECK(HasMsa());
   2292   DsFsmInstrFff(EmitMsa3R(0x3, 0x1, wt, ws, wd, 0xe),
   2293                 static_cast<FRegister>(wd),
   2294                 static_cast<FRegister>(ws),
   2295                 static_cast<FRegister>(wt));
   2296 }
   2297 
   2298 void MipsAssembler::Max_uW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   2299   CHECK(HasMsa());
   2300   DsFsmInstrFff(EmitMsa3R(0x3, 0x2, wt, ws, wd, 0xe),
   2301                 static_cast<FRegister>(wd),
   2302                 static_cast<FRegister>(ws),
   2303                 static_cast<FRegister>(wt));
   2304 }
   2305 
   2306 void MipsAssembler::Max_uD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   2307   CHECK(HasMsa());
   2308   DsFsmInstrFff(EmitMsa3R(0x3, 0x3, wt, ws, wd, 0xe),
   2309                 static_cast<FRegister>(wd),
   2310                 static_cast<FRegister>(ws),
   2311                 static_cast<FRegister>(wt));
   2312 }
   2313 
   2314 void MipsAssembler::Min_sB(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   2315   CHECK(HasMsa());
   2316   DsFsmInstrFff(EmitMsa3R(0x4, 0x0, wt, ws, wd, 0xe),
   2317                 static_cast<FRegister>(wd),
   2318                 static_cast<FRegister>(ws),
   2319                 static_cast<FRegister>(wt));
   2320 }
   2321 
   2322 void MipsAssembler::Min_sH(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   2323   CHECK(HasMsa());
   2324   DsFsmInstrFff(EmitMsa3R(0x4, 0x1, wt, ws, wd, 0xe),
   2325                 static_cast<FRegister>(wd),
   2326                 static_cast<FRegister>(ws),
   2327                 static_cast<FRegister>(wt));
   2328 }
   2329 
   2330 void MipsAssembler::Min_sW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   2331   CHECK(HasMsa());
   2332   DsFsmInstrFff(EmitMsa3R(0x4, 0x2, wt, ws, wd, 0xe),
   2333                 static_cast<FRegister>(wd),
   2334                 static_cast<FRegister>(ws),
   2335                 static_cast<FRegister>(wt));
   2336 }
   2337 
   2338 void MipsAssembler::Min_sD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   2339   CHECK(HasMsa());
   2340   DsFsmInstrFff(EmitMsa3R(0x4, 0x3, wt, ws, wd, 0xe),
   2341                 static_cast<FRegister>(wd),
   2342                 static_cast<FRegister>(ws),
   2343                 static_cast<FRegister>(wt));
   2344 }
   2345 
   2346 void MipsAssembler::Min_uB(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   2347   CHECK(HasMsa());
   2348   DsFsmInstrFff(EmitMsa3R(0x5, 0x0, wt, ws, wd, 0xe),
   2349                 static_cast<FRegister>(wd),
   2350                 static_cast<FRegister>(ws),
   2351                 static_cast<FRegister>(wt));
   2352 }
   2353 
   2354 void MipsAssembler::Min_uH(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   2355   CHECK(HasMsa());
   2356   DsFsmInstrFff(EmitMsa3R(0x5, 0x1, wt, ws, wd, 0xe),
   2357                 static_cast<FRegister>(wd),
   2358                 static_cast<FRegister>(ws),
   2359                 static_cast<FRegister>(wt));
   2360 }
   2361 
   2362 void MipsAssembler::Min_uW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   2363   CHECK(HasMsa());
   2364   DsFsmInstrFff(EmitMsa3R(0x5, 0x2, wt, ws, wd, 0xe),
   2365                 static_cast<FRegister>(wd),
   2366                 static_cast<FRegister>(ws),
   2367                 static_cast<FRegister>(wt));
   2368 }
   2369 
   2370 void MipsAssembler::Min_uD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   2371   CHECK(HasMsa());
   2372   DsFsmInstrFff(EmitMsa3R(0x5, 0x3, wt, ws, wd, 0xe),
   2373                 static_cast<FRegister>(wd),
   2374                 static_cast<FRegister>(ws),
   2375                 static_cast<FRegister>(wt));
   2376 }
   2377 
   2378 void MipsAssembler::FaddW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   2379   CHECK(HasMsa());
   2380   DsFsmInstrFff(EmitMsa3R(0x0, 0x0, wt, ws, wd, 0x1b),
   2381                 static_cast<FRegister>(wd),
   2382                 static_cast<FRegister>(ws),
   2383                 static_cast<FRegister>(wt));
   2384 }
   2385 
   2386 void MipsAssembler::FaddD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   2387   CHECK(HasMsa());
   2388   DsFsmInstrFff(EmitMsa3R(0x0, 0x1, wt, ws, wd, 0x1b),
   2389                 static_cast<FRegister>(wd),
   2390                 static_cast<FRegister>(ws),
   2391                 static_cast<FRegister>(wt));
   2392 }
   2393 
   2394 void MipsAssembler::FsubW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   2395   CHECK(HasMsa());
   2396   DsFsmInstrFff(EmitMsa3R(0x0, 0x2, wt, ws, wd, 0x1b),
   2397                 static_cast<FRegister>(wd),
   2398                 static_cast<FRegister>(ws),
   2399                 static_cast<FRegister>(wt));
   2400 }
   2401 
   2402 void MipsAssembler::FsubD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   2403   CHECK(HasMsa());
   2404   DsFsmInstrFff(EmitMsa3R(0x0, 0x3, wt, ws, wd, 0x1b),
   2405                 static_cast<FRegister>(wd),
   2406                 static_cast<FRegister>(ws),
   2407                 static_cast<FRegister>(wt));
   2408 }
   2409 
   2410 void MipsAssembler::FmulW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   2411   CHECK(HasMsa());
   2412   DsFsmInstrFff(EmitMsa3R(0x1, 0x0, wt, ws, wd, 0x1b),
   2413                 static_cast<FRegister>(wd),
   2414                 static_cast<FRegister>(ws),
   2415                 static_cast<FRegister>(wt));
   2416 }
   2417 
   2418 void MipsAssembler::FmulD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   2419   CHECK(HasMsa());
   2420   DsFsmInstrFff(EmitMsa3R(0x1, 0x1, wt, ws, wd, 0x1b),
   2421                 static_cast<FRegister>(wd),
   2422                 static_cast<FRegister>(ws),
   2423                 static_cast<FRegister>(wt));
   2424 }
   2425 
   2426 void MipsAssembler::FdivW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   2427   CHECK(HasMsa());
   2428   DsFsmInstrFff(EmitMsa3R(0x1, 0x2, wt, ws, wd, 0x1b),
   2429                 static_cast<FRegister>(wd),
   2430                 static_cast<FRegister>(ws),
   2431                 static_cast<FRegister>(wt));
   2432 }
   2433 
   2434 void MipsAssembler::FdivD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   2435   CHECK(HasMsa());
   2436   DsFsmInstrFff(EmitMsa3R(0x1, 0x3, wt, ws, wd, 0x1b),
   2437                 static_cast<FRegister>(wd),
   2438                 static_cast<FRegister>(ws),
   2439                 static_cast<FRegister>(wt));
   2440 }
   2441 
   2442 void MipsAssembler::FmaxW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   2443   CHECK(HasMsa());
   2444   DsFsmInstrFff(EmitMsa3R(0x7, 0x0, wt, ws, wd, 0x1b),
   2445                 static_cast<FRegister>(wd),
   2446                 static_cast<FRegister>(ws),
   2447                 static_cast<FRegister>(wt));
   2448 }
   2449 
   2450 void MipsAssembler::FmaxD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   2451   CHECK(HasMsa());
   2452   DsFsmInstrFff(EmitMsa3R(0x7, 0x1, wt, ws, wd, 0x1b),
   2453                 static_cast<FRegister>(wd),
   2454                 static_cast<FRegister>(ws),
   2455                 static_cast<FRegister>(wt));
   2456 }
   2457 
   2458 void MipsAssembler::FminW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   2459   CHECK(HasMsa());
   2460   DsFsmInstrFff(EmitMsa3R(0x6, 0x0, wt, ws, wd, 0x1b),
   2461                 static_cast<FRegister>(wd),
   2462                 static_cast<FRegister>(ws),
   2463                 static_cast<FRegister>(wt));
   2464 }
   2465 
   2466 void MipsAssembler::FminD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   2467   CHECK(HasMsa());
   2468   DsFsmInstrFff(EmitMsa3R(0x6, 0x1, wt, ws, wd, 0x1b),
   2469                 static_cast<FRegister>(wd),
   2470                 static_cast<FRegister>(ws),
   2471                 static_cast<FRegister>(wt));
   2472 }
   2473 
   2474 void MipsAssembler::Ffint_sW(VectorRegister wd, VectorRegister ws) {
   2475   CHECK(HasMsa());
   2476   DsFsmInstrFff(EmitMsa2RF(0x19e, 0x0, ws, wd, 0x1e),
   2477                 static_cast<FRegister>(wd),
   2478                 static_cast<FRegister>(ws),
   2479                 static_cast<FRegister>(ws));
   2480 }
   2481 
   2482 void MipsAssembler::Ffint_sD(VectorRegister wd, VectorRegister ws) {
   2483   CHECK(HasMsa());
   2484   DsFsmInstrFff(EmitMsa2RF(0x19e, 0x1, ws, wd, 0x1e),
   2485                 static_cast<FRegister>(wd),
   2486                 static_cast<FRegister>(ws),
   2487                 static_cast<FRegister>(ws));
   2488 }
   2489 
   2490 void MipsAssembler::Ftint_sW(VectorRegister wd, VectorRegister ws) {
   2491   CHECK(HasMsa());
   2492   DsFsmInstrFff(EmitMsa2RF(0x19c, 0x0, ws, wd, 0x1e),
   2493                 static_cast<FRegister>(wd),
   2494                 static_cast<FRegister>(ws),
   2495                 static_cast<FRegister>(ws));
   2496 }
   2497 
   2498 void MipsAssembler::Ftint_sD(VectorRegister wd, VectorRegister ws) {
   2499   CHECK(HasMsa());
   2500   DsFsmInstrFff(EmitMsa2RF(0x19c, 0x1, ws, wd, 0x1e),
   2501                 static_cast<FRegister>(wd),
   2502                 static_cast<FRegister>(ws),
   2503                 static_cast<FRegister>(ws));
   2504 }
   2505 
   2506 void MipsAssembler::SllB(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   2507   CHECK(HasMsa());
   2508   DsFsmInstrFff(EmitMsa3R(0x0, 0x0, wt, ws, wd, 0xd),
   2509                 static_cast<FRegister>(wd),
   2510                 static_cast<FRegister>(ws),
   2511                 static_cast<FRegister>(wt));
   2512 }
   2513 
   2514 void MipsAssembler::SllH(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   2515   CHECK(HasMsa());
   2516   DsFsmInstrFff(EmitMsa3R(0x0, 0x1, wt, ws, wd, 0xd),
   2517                 static_cast<FRegister>(wd),
   2518                 static_cast<FRegister>(ws),
   2519                 static_cast<FRegister>(wt));
   2520 }
   2521 
   2522 void MipsAssembler::SllW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   2523   CHECK(HasMsa());
   2524   DsFsmInstrFff(EmitMsa3R(0x0, 0x2, wt, ws, wd, 0xd),
   2525                 static_cast<FRegister>(wd),
   2526                 static_cast<FRegister>(ws),
   2527                 static_cast<FRegister>(wt));
   2528 }
   2529 
   2530 void MipsAssembler::SllD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   2531   CHECK(HasMsa());
   2532   DsFsmInstrFff(EmitMsa3R(0x0, 0x3, wt, ws, wd, 0xd),
   2533                 static_cast<FRegister>(wd),
   2534                 static_cast<FRegister>(ws),
   2535                 static_cast<FRegister>(wt));
   2536 }
   2537 
   2538 void MipsAssembler::SraB(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   2539   CHECK(HasMsa());
   2540   DsFsmInstrFff(EmitMsa3R(0x1, 0x0, wt, ws, wd, 0xd),
   2541                 static_cast<FRegister>(wd),
   2542                 static_cast<FRegister>(ws),
   2543                 static_cast<FRegister>(wt));
   2544 }
   2545 
   2546 void MipsAssembler::SraH(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   2547   CHECK(HasMsa());
   2548   DsFsmInstrFff(EmitMsa3R(0x1, 0x1, wt, ws, wd, 0xd),
   2549                 static_cast<FRegister>(wd),
   2550                 static_cast<FRegister>(ws),
   2551                 static_cast<FRegister>(wt));
   2552 }
   2553 
   2554 void MipsAssembler::SraW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   2555   CHECK(HasMsa());
   2556   DsFsmInstrFff(EmitMsa3R(0x1, 0x2, wt, ws, wd, 0xd),
   2557                 static_cast<FRegister>(wd),
   2558                 static_cast<FRegister>(ws),
   2559                 static_cast<FRegister>(wt));
   2560 }
   2561 
   2562 void MipsAssembler::SraD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   2563   CHECK(HasMsa());
   2564   DsFsmInstrFff(EmitMsa3R(0x1, 0x3, wt, ws, wd, 0xd),
   2565                 static_cast<FRegister>(wd),
   2566                 static_cast<FRegister>(ws),
   2567                 static_cast<FRegister>(wt));
   2568 }
   2569 
   2570 void MipsAssembler::SrlB(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   2571   CHECK(HasMsa());
   2572   DsFsmInstrFff(EmitMsa3R(0x2, 0x0, wt, ws, wd, 0xd),
   2573                 static_cast<FRegister>(wd),
   2574                 static_cast<FRegister>(ws),
   2575                 static_cast<FRegister>(wt));
   2576 }
   2577 
   2578 void MipsAssembler::SrlH(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   2579   CHECK(HasMsa());
   2580   DsFsmInstrFff(EmitMsa3R(0x2, 0x1, wt, ws, wd, 0xd),
   2581                 static_cast<FRegister>(wd),
   2582                 static_cast<FRegister>(ws),
   2583                 static_cast<FRegister>(wt));
   2584 }
   2585 
   2586 void MipsAssembler::SrlW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   2587   CHECK(HasMsa());
   2588   DsFsmInstrFff(EmitMsa3R(0x2, 0x2, wt, ws, wd, 0xd),
   2589                 static_cast<FRegister>(wd),
   2590                 static_cast<FRegister>(ws),
   2591                 static_cast<FRegister>(wt));
   2592 }
   2593 
   2594 void MipsAssembler::SrlD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   2595   CHECK(HasMsa());
   2596   DsFsmInstrFff(EmitMsa3R(0x2, 0x3, wt, ws, wd, 0xd),
   2597                 static_cast<FRegister>(wd),
   2598                 static_cast<FRegister>(ws),
   2599                 static_cast<FRegister>(wt));
   2600 }
   2601 
   2602 void MipsAssembler::SlliB(VectorRegister wd, VectorRegister ws, int shamt3) {
   2603   CHECK(HasMsa());
   2604   CHECK(IsUint<3>(shamt3)) << shamt3;
   2605   DsFsmInstrFff(EmitMsaBIT(0x0, shamt3 | kMsaDfMByteMask, ws, wd, 0x9),
   2606                 static_cast<FRegister>(wd),
   2607                 static_cast<FRegister>(ws),
   2608                 static_cast<FRegister>(ws));
   2609 }
   2610 
   2611 void MipsAssembler::SlliH(VectorRegister wd, VectorRegister ws, int shamt4) {
   2612   CHECK(HasMsa());
   2613   CHECK(IsUint<4>(shamt4)) << shamt4;
   2614   DsFsmInstrFff(EmitMsaBIT(0x0, shamt4 | kMsaDfMHalfwordMask, ws, wd, 0x9),
   2615                 static_cast<FRegister>(wd),
   2616                 static_cast<FRegister>(ws),
   2617                 static_cast<FRegister>(ws));
   2618 }
   2619 
   2620 void MipsAssembler::SlliW(VectorRegister wd, VectorRegister ws, int shamt5) {
   2621   CHECK(HasMsa());
   2622   CHECK(IsUint<5>(shamt5)) << shamt5;
   2623   DsFsmInstrFff(EmitMsaBIT(0x0, shamt5 | kMsaDfMWordMask, ws, wd, 0x9),
   2624                 static_cast<FRegister>(wd),
   2625                 static_cast<FRegister>(ws),
   2626                 static_cast<FRegister>(ws));
   2627 }
   2628 
   2629 void MipsAssembler::SlliD(VectorRegister wd, VectorRegister ws, int shamt6) {
   2630   CHECK(HasMsa());
   2631   CHECK(IsUint<6>(shamt6)) << shamt6;
   2632   DsFsmInstrFff(EmitMsaBIT(0x0, shamt6 | kMsaDfMDoublewordMask, ws, wd, 0x9),
   2633                 static_cast<FRegister>(wd),
   2634                 static_cast<FRegister>(ws),
   2635                 static_cast<FRegister>(ws));
   2636 }
   2637 
   2638 void MipsAssembler::SraiB(VectorRegister wd, VectorRegister ws, int shamt3) {
   2639   CHECK(HasMsa());
   2640   CHECK(IsUint<3>(shamt3)) << shamt3;
   2641   DsFsmInstrFff(EmitMsaBIT(0x1, shamt3 | kMsaDfMByteMask, ws, wd, 0x9),
   2642                 static_cast<FRegister>(wd),
   2643                 static_cast<FRegister>(ws),
   2644                 static_cast<FRegister>(ws));
   2645 }
   2646 
   2647 void MipsAssembler::SraiH(VectorRegister wd, VectorRegister ws, int shamt4) {
   2648   CHECK(HasMsa());
   2649   CHECK(IsUint<4>(shamt4)) << shamt4;
   2650   DsFsmInstrFff(EmitMsaBIT(0x1, shamt4 | kMsaDfMHalfwordMask, ws, wd, 0x9),
   2651                 static_cast<FRegister>(wd),
   2652                 static_cast<FRegister>(ws),
   2653                 static_cast<FRegister>(ws));
   2654 }
   2655 
   2656 void MipsAssembler::SraiW(VectorRegister wd, VectorRegister ws, int shamt5) {
   2657   CHECK(HasMsa());
   2658   CHECK(IsUint<5>(shamt5)) << shamt5;
   2659   DsFsmInstrFff(EmitMsaBIT(0x1, shamt5 | kMsaDfMWordMask, ws, wd, 0x9),
   2660                 static_cast<FRegister>(wd),
   2661                 static_cast<FRegister>(ws),
   2662                 static_cast<FRegister>(ws));
   2663 }
   2664 
   2665 void MipsAssembler::SraiD(VectorRegister wd, VectorRegister ws, int shamt6) {
   2666   CHECK(HasMsa());
   2667   CHECK(IsUint<6>(shamt6)) << shamt6;
   2668   DsFsmInstrFff(EmitMsaBIT(0x1, shamt6 | kMsaDfMDoublewordMask, ws, wd, 0x9),
   2669                 static_cast<FRegister>(wd),
   2670                 static_cast<FRegister>(ws),
   2671                 static_cast<FRegister>(ws));
   2672 }
   2673 
   2674 void MipsAssembler::SrliB(VectorRegister wd, VectorRegister ws, int shamt3) {
   2675   CHECK(HasMsa());
   2676   CHECK(IsUint<3>(shamt3)) << shamt3;
   2677   DsFsmInstrFff(EmitMsaBIT(0x2, shamt3 | kMsaDfMByteMask, ws, wd, 0x9),
   2678                 static_cast<FRegister>(wd),
   2679                 static_cast<FRegister>(ws),
   2680                 static_cast<FRegister>(ws));
   2681 }
   2682 
   2683 void MipsAssembler::SrliH(VectorRegister wd, VectorRegister ws, int shamt4) {
   2684   CHECK(HasMsa());
   2685   CHECK(IsUint<4>(shamt4)) << shamt4;
   2686   DsFsmInstrFff(EmitMsaBIT(0x2, shamt4 | kMsaDfMHalfwordMask, ws, wd, 0x9),
   2687                 static_cast<FRegister>(wd),
   2688                 static_cast<FRegister>(ws),
   2689                 static_cast<FRegister>(ws));
   2690 }
   2691 
   2692 void MipsAssembler::SrliW(VectorRegister wd, VectorRegister ws, int shamt5) {
   2693   CHECK(HasMsa());
   2694   CHECK(IsUint<5>(shamt5)) << shamt5;
   2695   DsFsmInstrFff(EmitMsaBIT(0x2, shamt5 | kMsaDfMWordMask, ws, wd, 0x9),
   2696                 static_cast<FRegister>(wd),
   2697                 static_cast<FRegister>(ws),
   2698                 static_cast<FRegister>(ws));
   2699 }
   2700 
   2701 void MipsAssembler::SrliD(VectorRegister wd, VectorRegister ws, int shamt6) {
   2702   CHECK(HasMsa());
   2703   CHECK(IsUint<6>(shamt6)) << shamt6;
   2704   DsFsmInstrFff(EmitMsaBIT(0x2, shamt6 | kMsaDfMDoublewordMask, ws, wd, 0x9),
   2705                 static_cast<FRegister>(wd),
   2706                 static_cast<FRegister>(ws),
   2707                 static_cast<FRegister>(ws));
   2708 }
   2709 
   2710 void MipsAssembler::MoveV(VectorRegister wd, VectorRegister ws) {
   2711   CHECK(HasMsa());
   2712   DsFsmInstrFff(EmitMsaBIT(0x1, 0x3e, ws, wd, 0x19),
   2713                 static_cast<FRegister>(wd),
   2714                 static_cast<FRegister>(ws),
   2715                 static_cast<FRegister>(ws));
   2716 }
   2717 
   2718 void MipsAssembler::SplatiB(VectorRegister wd, VectorRegister ws, int n4) {
   2719   CHECK(HasMsa());
   2720   CHECK(IsUint<4>(n4)) << n4;
   2721   DsFsmInstrFff(EmitMsaELM(0x1, n4 | kMsaDfNByteMask, ws, wd, 0x19),
   2722                 static_cast<FRegister>(wd),
   2723                 static_cast<FRegister>(ws),
   2724                 static_cast<FRegister>(ws));
   2725 }
   2726 
   2727 void MipsAssembler::SplatiH(VectorRegister wd, VectorRegister ws, int n3) {
   2728   CHECK(HasMsa());
   2729   CHECK(IsUint<3>(n3)) << n3;
   2730   DsFsmInstrFff(EmitMsaELM(0x1, n3 | kMsaDfNHalfwordMask, ws, wd, 0x19),
   2731                 static_cast<FRegister>(wd),
   2732                 static_cast<FRegister>(ws),
   2733                 static_cast<FRegister>(ws));
   2734 }
   2735 
   2736 void MipsAssembler::SplatiW(VectorRegister wd, VectorRegister ws, int n2) {
   2737   CHECK(HasMsa());
   2738   CHECK(IsUint<2>(n2)) << n2;
   2739   DsFsmInstrFff(EmitMsaELM(0x1, n2 | kMsaDfNWordMask, ws, wd, 0x19),
   2740                 static_cast<FRegister>(wd),
   2741                 static_cast<FRegister>(ws),
   2742                 static_cast<FRegister>(ws));
   2743 }
   2744 
   2745 void MipsAssembler::SplatiD(VectorRegister wd, VectorRegister ws, int n1) {
   2746   CHECK(HasMsa());
   2747   CHECK(IsUint<1>(n1)) << n1;
   2748   DsFsmInstrFff(EmitMsaELM(0x1, n1 | kMsaDfNDoublewordMask, ws, wd, 0x19),
   2749                 static_cast<FRegister>(wd),
   2750                 static_cast<FRegister>(ws),
   2751                 static_cast<FRegister>(ws));
   2752 }
   2753 
   2754 void MipsAssembler::FillB(VectorRegister wd, Register rs) {
   2755   CHECK(HasMsa());
   2756   DsFsmInstrFr(EmitMsa2R(0xc0, 0x0, static_cast<VectorRegister>(rs), wd, 0x1e),
   2757                static_cast<FRegister>(wd),
   2758                rs);
   2759 }
   2760 
   2761 void MipsAssembler::FillH(VectorRegister wd, Register rs) {
   2762   CHECK(HasMsa());
   2763   DsFsmInstrFr(EmitMsa2R(0xc0, 0x1, static_cast<VectorRegister>(rs), wd, 0x1e),
   2764                static_cast<FRegister>(wd),
   2765                rs);
   2766 }
   2767 
   2768 void MipsAssembler::FillW(VectorRegister wd, Register rs) {
   2769   CHECK(HasMsa());
   2770   DsFsmInstrFr(EmitMsa2R(0xc0, 0x2, static_cast<VectorRegister>(rs), wd, 0x1e),
   2771                static_cast<FRegister>(wd),
   2772                rs);
   2773 }
   2774 
   2775 void MipsAssembler::LdiB(VectorRegister wd, int imm8) {
   2776   CHECK(HasMsa());
   2777   CHECK(IsInt<8>(imm8)) << imm8;
   2778   DsFsmInstrFr(EmitMsaI10(0x6, 0x0, imm8 & kMsaS10Mask, wd, 0x7),
   2779                static_cast<FRegister>(wd),
   2780                ZERO);
   2781 }
   2782 
   2783 void MipsAssembler::LdiH(VectorRegister wd, int imm10) {
   2784   CHECK(HasMsa());
   2785   CHECK(IsInt<10>(imm10)) << imm10;
   2786   DsFsmInstrFr(EmitMsaI10(0x6, 0x1, imm10 & kMsaS10Mask, wd, 0x7),
   2787                static_cast<FRegister>(wd),
   2788                ZERO);
   2789 }
   2790 
   2791 void MipsAssembler::LdiW(VectorRegister wd, int imm10) {
   2792   CHECK(HasMsa());
   2793   CHECK(IsInt<10>(imm10)) << imm10;
   2794   DsFsmInstrFr(EmitMsaI10(0x6, 0x2, imm10 & kMsaS10Mask, wd, 0x7),
   2795                static_cast<FRegister>(wd),
   2796                ZERO);
   2797 }
   2798 
   2799 void MipsAssembler::LdiD(VectorRegister wd, int imm10) {
   2800   CHECK(HasMsa());
   2801   CHECK(IsInt<10>(imm10)) << imm10;
   2802   DsFsmInstrFr(EmitMsaI10(0x6, 0x3, imm10 & kMsaS10Mask, wd, 0x7),
   2803                static_cast<FRegister>(wd),
   2804                ZERO);
   2805 }
   2806 
   2807 void MipsAssembler::LdB(VectorRegister wd, Register rs, int offset) {
   2808   CHECK(HasMsa());
   2809   CHECK(IsInt<10>(offset)) << offset;
   2810   DsFsmInstrFr(EmitMsaMI10(offset & kMsaS10Mask, rs, wd, 0x8, 0x0),
   2811                static_cast<FRegister>(wd),
   2812                rs);
   2813 }
   2814 
   2815 void MipsAssembler::LdH(VectorRegister wd, Register rs, int offset) {
   2816   CHECK(HasMsa());
   2817   CHECK(IsInt<11>(offset)) << offset;
   2818   CHECK_ALIGNED(offset, kMipsHalfwordSize);
   2819   DsFsmInstrFr(EmitMsaMI10((offset >> TIMES_2) & kMsaS10Mask, rs, wd, 0x8, 0x1),
   2820                static_cast<FRegister>(wd),
   2821                rs);
   2822 }
   2823 
   2824 void MipsAssembler::LdW(VectorRegister wd, Register rs, int offset) {
   2825   CHECK(HasMsa());
   2826   CHECK(IsInt<12>(offset)) << offset;
   2827   CHECK_ALIGNED(offset, kMipsWordSize);
   2828   DsFsmInstrFr(EmitMsaMI10((offset >> TIMES_4) & kMsaS10Mask, rs, wd, 0x8, 0x2),
   2829                static_cast<FRegister>(wd),
   2830                rs);
   2831 }
   2832 
   2833 void MipsAssembler::LdD(VectorRegister wd, Register rs, int offset) {
   2834   CHECK(HasMsa());
   2835   CHECK(IsInt<13>(offset)) << offset;
   2836   CHECK_ALIGNED(offset, kMipsDoublewordSize);
   2837   DsFsmInstrFr(EmitMsaMI10((offset >> TIMES_8) & kMsaS10Mask, rs, wd, 0x8, 0x3),
   2838                static_cast<FRegister>(wd),
   2839                rs);
   2840 }
   2841 
   2842 void MipsAssembler::StB(VectorRegister wd, Register rs, int offset) {
   2843   CHECK(HasMsa());
   2844   CHECK(IsInt<10>(offset)) << offset;
   2845   DsFsmInstrFR(EmitMsaMI10(offset & kMsaS10Mask, rs, wd, 0x9, 0x0), static_cast<FRegister>(wd), rs);
   2846 }
   2847 
   2848 void MipsAssembler::StH(VectorRegister wd, Register rs, int offset) {
   2849   CHECK(HasMsa());
   2850   CHECK(IsInt<11>(offset)) << offset;
   2851   CHECK_ALIGNED(offset, kMipsHalfwordSize);
   2852   DsFsmInstrFR(EmitMsaMI10((offset >> TIMES_2) & kMsaS10Mask, rs, wd, 0x9, 0x1),
   2853                static_cast<FRegister>(wd),
   2854                rs);
   2855 }
   2856 
   2857 void MipsAssembler::StW(VectorRegister wd, Register rs, int offset) {
   2858   CHECK(HasMsa());
   2859   CHECK(IsInt<12>(offset)) << offset;
   2860   CHECK_ALIGNED(offset, kMipsWordSize);
   2861   DsFsmInstrFR(EmitMsaMI10((offset >> TIMES_4) & kMsaS10Mask, rs, wd, 0x9, 0x2),
   2862                static_cast<FRegister>(wd),
   2863                rs);
   2864 }
   2865 
   2866 void MipsAssembler::StD(VectorRegister wd, Register rs, int offset) {
   2867   CHECK(HasMsa());
   2868   CHECK(IsInt<13>(offset)) << offset;
   2869   CHECK_ALIGNED(offset, kMipsDoublewordSize);
   2870   DsFsmInstrFR(EmitMsaMI10((offset >> TIMES_8) & kMsaS10Mask, rs, wd, 0x9, 0x3),
   2871                static_cast<FRegister>(wd),
   2872                rs);
   2873 }
   2874 
   2875 void MipsAssembler::IlvrB(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   2876   CHECK(HasMsa());
   2877   DsFsmInstrFff(EmitMsa3R(0x5, 0x0, wt, ws, wd, 0x14),
   2878                 static_cast<FRegister>(wd),
   2879                 static_cast<FRegister>(ws),
   2880                 static_cast<FRegister>(wt));
   2881 }
   2882 
   2883 void MipsAssembler::IlvrH(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   2884   CHECK(HasMsa());
   2885   DsFsmInstrFff(EmitMsa3R(0x5, 0x1, wt, ws, wd, 0x14),
   2886                 static_cast<FRegister>(wd),
   2887                 static_cast<FRegister>(ws),
   2888                 static_cast<FRegister>(wt));
   2889 }
   2890 
   2891 void MipsAssembler::IlvrW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   2892   CHECK(HasMsa());
   2893   DsFsmInstrFff(EmitMsa3R(0x5, 0x2, wt, ws, wd, 0x14),
   2894                 static_cast<FRegister>(wd),
   2895                 static_cast<FRegister>(ws),
   2896                 static_cast<FRegister>(wt));
   2897 }
   2898 
   2899 void MipsAssembler::IlvrD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   2900   CHECK(HasMsa());
   2901   DsFsmInstrFff(EmitMsa3R(0x5, 0x3, wt, ws, wd, 0x14),
   2902                 static_cast<FRegister>(wd),
   2903                 static_cast<FRegister>(ws),
   2904                 static_cast<FRegister>(wt));
   2905 }
   2906 
   2907 void MipsAssembler::ReplicateFPToVectorRegister(VectorRegister dst,
   2908                                                 FRegister src,
   2909                                                 bool is_double) {
   2910   // Float or double in FPU register Fx can be considered as 0th element in vector register Wx.
   2911   if (is_double) {
   2912     SplatiD(dst, static_cast<VectorRegister>(src), 0);
   2913   } else {
   2914     SplatiW(dst, static_cast<VectorRegister>(src), 0);
   2915   }
   2916 }
   2917 
   2918 void MipsAssembler::LoadConst32(Register rd, int32_t value) {
   2919   if (IsUint<16>(value)) {
   2920     // Use OR with (unsigned) immediate to encode 16b unsigned int.
   2921     Ori(rd, ZERO, value);
   2922   } else if (IsInt<16>(value)) {
   2923     // Use ADD with (signed) immediate to encode 16b signed int.
   2924     Addiu(rd, ZERO, value);
   2925   } else {
   2926     Lui(rd, High16Bits(value));
   2927     if (value & 0xFFFF)
   2928       Ori(rd, rd, Low16Bits(value));
   2929   }
   2930 }
   2931 
   2932 void MipsAssembler::LoadConst64(Register reg_hi, Register reg_lo, int64_t value) {
   2933   uint32_t low = Low32Bits(value);
   2934   uint32_t high = High32Bits(value);
   2935   LoadConst32(reg_lo, low);
   2936   if (high != low) {
   2937     LoadConst32(reg_hi, high);
   2938   } else {
   2939     Move(reg_hi, reg_lo);
   2940   }
   2941 }
   2942 
   2943 void MipsAssembler::LoadSConst32(FRegister r, int32_t value, Register temp) {
   2944   if (value == 0) {
   2945     temp = ZERO;
   2946   } else {
   2947     LoadConst32(temp, value);
   2948   }
   2949   Mtc1(temp, r);
   2950 }
   2951 
   2952 void MipsAssembler::LoadDConst64(FRegister rd, int64_t value, Register temp) {
   2953   uint32_t low = Low32Bits(value);
   2954   uint32_t high = High32Bits(value);
   2955   if (low == 0) {
   2956     Mtc1(ZERO, rd);
   2957   } else {
   2958     LoadConst32(temp, low);
   2959     Mtc1(temp, rd);
   2960   }
   2961   if (high == 0) {
   2962     MoveToFpuHigh(ZERO, rd);
   2963   } else {
   2964     LoadConst32(temp, high);
   2965     MoveToFpuHigh(temp, rd);
   2966   }
   2967 }
   2968 
   2969 void MipsAssembler::Addiu32(Register rt, Register rs, int32_t value, Register temp) {
   2970   CHECK_NE(rs, temp);  // Must not overwrite the register `rs` while loading `value`.
   2971   if (IsInt<16>(value)) {
   2972     Addiu(rt, rs, value);
   2973   } else if (IsR6()) {
   2974     int16_t high = High16Bits(value);
   2975     int16_t low = Low16Bits(value);
   2976     high += (low < 0) ? 1 : 0;  // Account for sign extension in addiu.
   2977     if (low != 0) {
   2978       Aui(temp, rs, high);
   2979       Addiu(rt, temp, low);
   2980     } else {
   2981       Aui(rt, rs, high);
   2982     }
   2983   } else {
   2984     // Do not load the whole 32-bit `value` if it can be represented as
   2985     // a sum of two 16-bit signed values. This can save an instruction.
   2986     constexpr int32_t kMinValueForSimpleAdjustment = std::numeric_limits<int16_t>::min() * 2;
   2987     constexpr int32_t kMaxValueForSimpleAdjustment = std::numeric_limits<int16_t>::max() * 2;
   2988     if (0 <= value && value <= kMaxValueForSimpleAdjustment) {
   2989       Addiu(temp, rs, kMaxValueForSimpleAdjustment / 2);
   2990       Addiu(rt, temp, value - kMaxValueForSimpleAdjustment / 2);
   2991     } else if (kMinValueForSimpleAdjustment <= value && value < 0) {
   2992       Addiu(temp, rs, kMinValueForSimpleAdjustment / 2);
   2993       Addiu(rt, temp, value - kMinValueForSimpleAdjustment / 2);
   2994     } else {
   2995       // Now that all shorter options have been exhausted, load the full 32-bit value.
   2996       LoadConst32(temp, value);
   2997       Addu(rt, rs, temp);
   2998     }
   2999   }
   3000 }
   3001 
   3002 void MipsAssembler::Branch::InitShortOrLong(MipsAssembler::Branch::OffsetBits offset_size,
   3003                                             MipsAssembler::Branch::Type short_type,
   3004                                             MipsAssembler::Branch::Type long_type) {
   3005   type_ = (offset_size <= branch_info_[short_type].offset_size) ? short_type : long_type;
   3006 }
   3007 
   3008 void MipsAssembler::Branch::InitializeType(Type initial_type, bool is_r6) {
   3009   OffsetBits offset_size = GetOffsetSizeNeeded(location_, target_);
   3010   if (is_r6) {
   3011     // R6
   3012     switch (initial_type) {
   3013       case kLabel:
   3014         CHECK(!IsResolved());
   3015         type_ = kR6Label;
   3016         break;
   3017       case kLiteral:
   3018         CHECK(!IsResolved());
   3019         type_ = kR6Literal;
   3020         break;
   3021       case kCall:
   3022         InitShortOrLong(offset_size, kR6Call, kR6LongCall);
   3023         break;
   3024       case kCondBranch:
   3025         switch (condition_) {
   3026           case kUncond:
   3027             InitShortOrLong(offset_size, kR6UncondBranch, kR6LongUncondBranch);
   3028             break;
   3029           case kCondEQZ:
   3030           case kCondNEZ:
   3031             // Special case for beqzc/bnezc with longer offset than in other b<cond>c instructions.
   3032             type_ = (offset_size <= kOffset23) ? kR6CondBranch : kR6LongCondBranch;
   3033             break;
   3034           default:
   3035             InitShortOrLong(offset_size, kR6CondBranch, kR6LongCondBranch);
   3036             break;
   3037         }
   3038         break;
   3039       default:
   3040         LOG(FATAL) << "Unexpected branch type " << initial_type;
   3041         UNREACHABLE();
   3042     }
   3043   } else {
   3044     // R2
   3045     switch (initial_type) {
   3046       case kLabel:
   3047         CHECK(!IsResolved());
   3048         type_ = kLabel;
   3049         break;
   3050       case kLiteral:
   3051         CHECK(!IsResolved());
   3052         type_ = kLiteral;
   3053         break;
   3054       case kCall:
   3055         InitShortOrLong(offset_size, kCall, kLongCall);
   3056         break;
   3057       case kCondBranch:
   3058         switch (condition_) {
   3059           case kUncond:
   3060             InitShortOrLong(offset_size, kUncondBranch, kLongUncondBranch);
   3061             break;
   3062           default:
   3063             InitShortOrLong(offset_size, kCondBranch, kLongCondBranch);
   3064             break;
   3065         }
   3066         break;
   3067       default:
   3068         LOG(FATAL) << "Unexpected branch type " << initial_type;
   3069         UNREACHABLE();
   3070     }
   3071   }
   3072   old_type_ = type_;
   3073 }
   3074 
   3075 bool MipsAssembler::Branch::IsNop(BranchCondition condition, Register lhs, Register rhs) {
   3076   switch (condition) {
   3077     case kCondLT:
   3078     case kCondGT:
   3079     case kCondNE:
   3080     case kCondLTU:
   3081       return lhs == rhs;
   3082     default:
   3083       return false;
   3084   }
   3085 }
   3086 
   3087 bool MipsAssembler::Branch::IsUncond(BranchCondition condition, Register lhs, Register rhs) {
   3088   switch (condition) {
   3089     case kUncond:
   3090       return true;
   3091     case kCondGE:
   3092     case kCondLE:
   3093     case kCondEQ:
   3094     case kCondGEU:
   3095       return lhs == rhs;
   3096     default:
   3097       return false;
   3098   }
   3099 }
   3100 
   3101 MipsAssembler::Branch::Branch(bool is_r6, uint32_t location, uint32_t target, bool is_call)
   3102     : old_location_(location),
   3103       location_(location),
   3104       target_(target),
   3105       lhs_reg_(0),
   3106       rhs_reg_(0),
   3107       condition_(kUncond),
   3108       delayed_instruction_(kUnfilledDelaySlot) {
   3109   InitializeType((is_call ? kCall : kCondBranch), is_r6);
   3110 }
   3111 
   3112 MipsAssembler::Branch::Branch(bool is_r6,
   3113                               uint32_t location,
   3114                               uint32_t target,
   3115                               MipsAssembler::BranchCondition condition,
   3116                               Register lhs_reg,
   3117                               Register rhs_reg)
   3118     : old_location_(location),
   3119       location_(location),
   3120       target_(target),
   3121       lhs_reg_(lhs_reg),
   3122       rhs_reg_(rhs_reg),
   3123       condition_(condition),
   3124       delayed_instruction_(kUnfilledDelaySlot) {
   3125   CHECK_NE(condition, kUncond);
   3126   switch (condition) {
   3127     case kCondLT:
   3128     case kCondGE:
   3129     case kCondLE:
   3130     case kCondGT:
   3131     case kCondLTU:
   3132     case kCondGEU:
   3133       // We don't support synthetic R2 branches (preceded with slt[u]) at this level
   3134       // (R2 doesn't have branches to compare 2 registers using <, <=, >=, >).
   3135       // We leave this up to the caller.
   3136       CHECK(is_r6);
   3137       FALLTHROUGH_INTENDED;
   3138     case kCondEQ:
   3139     case kCondNE:
   3140       // Require registers other than 0 not only for R6, but also for R2 to catch errors.
   3141       // To compare with 0, use dedicated kCond*Z conditions.
   3142       CHECK_NE(lhs_reg, ZERO);
   3143       CHECK_NE(rhs_reg, ZERO);
   3144       break;
   3145     case kCondLTZ:
   3146     case kCondGEZ:
   3147     case kCondLEZ:
   3148     case kCondGTZ:
   3149     case kCondEQZ:
   3150     case kCondNEZ:
   3151       // Require registers other than 0 not only for R6, but also for R2 to catch errors.
   3152       CHECK_NE(lhs_reg, ZERO);
   3153       CHECK_EQ(rhs_reg, ZERO);
   3154       break;
   3155     case kCondF:
   3156     case kCondT:
   3157       CHECK_EQ(rhs_reg, ZERO);
   3158       break;
   3159     case kUncond:
   3160       UNREACHABLE();
   3161   }
   3162   CHECK(!IsNop(condition, lhs_reg, rhs_reg));
   3163   if (IsUncond(condition, lhs_reg, rhs_reg)) {
   3164     // Branch condition is always true, make the branch unconditional.
   3165     condition_ = kUncond;
   3166   }
   3167   InitializeType(kCondBranch, is_r6);
   3168 }
   3169 
   3170 MipsAssembler::Branch::Branch(bool is_r6,
   3171                               uint32_t location,
   3172                               Register dest_reg,
   3173                               Register base_reg,
   3174                               Type label_or_literal_type)
   3175     : old_location_(location),
   3176       location_(location),
   3177       target_(kUnresolved),
   3178       lhs_reg_(dest_reg),
   3179       rhs_reg_(base_reg),
   3180       condition_(kUncond),
   3181       delayed_instruction_(kUnfilledDelaySlot) {
   3182   CHECK_NE(dest_reg, ZERO);
   3183   if (is_r6) {
   3184     CHECK_EQ(base_reg, ZERO);
   3185   } else {
   3186     CHECK_NE(base_reg, ZERO);
   3187   }
   3188   InitializeType(label_or_literal_type, is_r6);
   3189 }
   3190 
   3191 MipsAssembler::BranchCondition MipsAssembler::Branch::OppositeCondition(
   3192     MipsAssembler::BranchCondition cond) {
   3193   switch (cond) {
   3194     case kCondLT:
   3195       return kCondGE;
   3196     case kCondGE:
   3197       return kCondLT;
   3198     case kCondLE:
   3199       return kCondGT;
   3200     case kCondGT:
   3201       return kCondLE;
   3202     case kCondLTZ:
   3203       return kCondGEZ;
   3204     case kCondGEZ:
   3205       return kCondLTZ;
   3206     case kCondLEZ:
   3207       return kCondGTZ;
   3208     case kCondGTZ:
   3209       return kCondLEZ;
   3210     case kCondEQ:
   3211       return kCondNE;
   3212     case kCondNE:
   3213       return kCondEQ;
   3214     case kCondEQZ:
   3215       return kCondNEZ;
   3216     case kCondNEZ:
   3217       return kCondEQZ;
   3218     case kCondLTU:
   3219       return kCondGEU;
   3220     case kCondGEU:
   3221       return kCondLTU;
   3222     case kCondF:
   3223       return kCondT;
   3224     case kCondT:
   3225       return kCondF;
   3226     case kUncond:
   3227       LOG(FATAL) << "Unexpected branch condition " << cond;
   3228   }
   3229   UNREACHABLE();
   3230 }
   3231 
   3232 MipsAssembler::Branch::Type MipsAssembler::Branch::GetType() const {
   3233   return type_;
   3234 }
   3235 
   3236 MipsAssembler::BranchCondition MipsAssembler::Branch::GetCondition() const {
   3237   return condition_;
   3238 }
   3239 
   3240 Register MipsAssembler::Branch::GetLeftRegister() const {
   3241   return static_cast<Register>(lhs_reg_);
   3242 }
   3243 
   3244 Register MipsAssembler::Branch::GetRightRegister() const {
   3245   return static_cast<Register>(rhs_reg_);
   3246 }
   3247 
   3248 uint32_t MipsAssembler::Branch::GetTarget() const {
   3249   return target_;
   3250 }
   3251 
   3252 uint32_t MipsAssembler::Branch::GetLocation() const {
   3253   return location_;
   3254 }
   3255 
   3256 uint32_t MipsAssembler::Branch::GetOldLocation() const {
   3257   return old_location_;
   3258 }
   3259 
   3260 uint32_t MipsAssembler::Branch::GetPrecedingInstructionLength(Type type) const {
   3261   // Short branches with delay slots always consist of two instructions, the branch
   3262   // and the delay slot, irrespective of whether the delay slot is filled with a
   3263   // useful instruction or not.
   3264   // Long composite branches may have a length longer by one instruction than
   3265   // specified in branch_info_[].length. This happens when an instruction is taken
   3266   // to fill the short branch delay slot, but the branch eventually becomes long
   3267   // and formally has no delay slot to fill. This instruction is placed at the
   3268   // beginning of the long composite branch and this needs to be accounted for in
   3269   // the branch length and the location of the offset encoded in the branch.
   3270   switch (type) {
   3271     case kLongUncondBranch:
   3272     case kLongCondBranch:
   3273     case kLongCall:
   3274     case kR6LongCondBranch:
   3275       return (delayed_instruction_ != kUnfilledDelaySlot &&
   3276           delayed_instruction_ != kUnfillableDelaySlot) ? 1 : 0;
   3277     default:
   3278       return 0;
   3279   }
   3280 }
   3281 
   3282 uint32_t MipsAssembler::Branch::GetPrecedingInstructionSize(Type type) const {
   3283   return GetPrecedingInstructionLength(type) * sizeof(uint32_t);
   3284 }
   3285 
   3286 uint32_t MipsAssembler::Branch::GetLength() const {
   3287   return GetPrecedingInstructionLength(type_) + branch_info_[type_].length;
   3288 }
   3289 
   3290 uint32_t MipsAssembler::Branch::GetOldLength() const {
   3291   return GetPrecedingInstructionLength(old_type_) + branch_info_[old_type_].length;
   3292 }
   3293 
   3294 uint32_t MipsAssembler::Branch::GetSize() const {
   3295   return GetLength() * sizeof(uint32_t);
   3296 }
   3297 
   3298 uint32_t MipsAssembler::Branch::GetOldSize() const {
   3299   return GetOldLength() * sizeof(uint32_t);
   3300 }
   3301 
   3302 uint32_t MipsAssembler::Branch::GetEndLocation() const {
   3303   return GetLocation() + GetSize();
   3304 }
   3305 
   3306 uint32_t MipsAssembler::Branch::GetOldEndLocation() const {
   3307   return GetOldLocation() + GetOldSize();
   3308 }
   3309 
   3310 bool MipsAssembler::Branch::IsLong() const {
   3311   switch (type_) {
   3312     // R2 short branches.
   3313     case kUncondBranch:
   3314     case kCondBranch:
   3315     case kCall:
   3316     // R2 near label.
   3317     case kLabel:
   3318     // R2 near literal.
   3319     case kLiteral:
   3320     // R6 short branches.
   3321     case kR6UncondBranch:
   3322     case kR6CondBranch:
   3323     case kR6Call:
   3324     // R6 near label.
   3325     case kR6Label:
   3326     // R6 near literal.
   3327     case kR6Literal:
   3328       return false;
   3329     // R2 long branches.
   3330     case kLongUncondBranch:
   3331     case kLongCondBranch:
   3332     case kLongCall:
   3333     // R2 far label.
   3334     case kFarLabel:
   3335     // R2 far literal.
   3336     case kFarLiteral:
   3337     // R6 long branches.
   3338     case kR6LongUncondBranch:
   3339     case kR6LongCondBranch:
   3340     case kR6LongCall:
   3341     // R6 far label.
   3342     case kR6FarLabel:
   3343     // R6 far literal.
   3344     case kR6FarLiteral:
   3345       return true;
   3346   }
   3347   UNREACHABLE();
   3348 }
   3349 
   3350 bool MipsAssembler::Branch::IsResolved() const {
   3351   return target_ != kUnresolved;
   3352 }
   3353 
   3354 MipsAssembler::Branch::OffsetBits MipsAssembler::Branch::GetOffsetSize() const {
   3355   OffsetBits offset_size =
   3356       (type_ == kR6CondBranch && (condition_ == kCondEQZ || condition_ == kCondNEZ))
   3357           ? kOffset23
   3358           : branch_info_[type_].offset_size;
   3359   return offset_size;
   3360 }
   3361 
   3362 MipsAssembler::Branch::OffsetBits MipsAssembler::Branch::GetOffsetSizeNeeded(uint32_t location,
   3363                                                                              uint32_t target) {
   3364   // For unresolved targets assume the shortest encoding
   3365   // (later it will be made longer if needed).
   3366   if (target == kUnresolved)
   3367     return kOffset16;
   3368   int64_t distance = static_cast<int64_t>(target) - location;
   3369   // To simplify calculations in composite branches consisting of multiple instructions
   3370   // bump up the distance by a value larger than the max byte size of a composite branch.
   3371   distance += (distance >= 0) ? kMaxBranchSize : -kMaxBranchSize;
   3372   if (IsInt<kOffset16>(distance))
   3373     return kOffset16;
   3374   else if (IsInt<kOffset18>(distance))
   3375     return kOffset18;
   3376   else if (IsInt<kOffset21>(distance))
   3377     return kOffset21;
   3378   else if (IsInt<kOffset23>(distance))
   3379     return kOffset23;
   3380   else if (IsInt<kOffset28>(distance))
   3381     return kOffset28;
   3382   return kOffset32;
   3383 }
   3384 
   3385 void MipsAssembler::Branch::Resolve(uint32_t target) {
   3386   target_ = target;
   3387 }
   3388 
   3389 void MipsAssembler::Branch::Relocate(uint32_t expand_location, uint32_t delta) {
   3390   if (location_ > expand_location) {
   3391     location_ += delta;
   3392   }
   3393   if (!IsResolved()) {
   3394     return;  // Don't know the target yet.
   3395   }
   3396   if (target_ > expand_location) {
   3397     target_ += delta;
   3398   }
   3399 }
   3400 
   3401 void MipsAssembler::Branch::PromoteToLong() {
   3402   switch (type_) {
   3403     // R2 short branches.
   3404     case kUncondBranch:
   3405       type_ = kLongUncondBranch;
   3406       break;
   3407     case kCondBranch:
   3408       type_ = kLongCondBranch;
   3409       break;
   3410     case kCall:
   3411       type_ = kLongCall;
   3412       break;
   3413     // R2 near label.
   3414     case kLabel:
   3415       type_ = kFarLabel;
   3416       break;
   3417     // R2 near literal.
   3418     case kLiteral:
   3419       type_ = kFarLiteral;
   3420       break;
   3421     // R6 short branches.
   3422     case kR6UncondBranch:
   3423       type_ = kR6LongUncondBranch;
   3424       break;
   3425     case kR6CondBranch:
   3426       type_ = kR6LongCondBranch;
   3427       break;
   3428     case kR6Call:
   3429       type_ = kR6LongCall;
   3430       break;
   3431     // R6 near label.
   3432     case kR6Label:
   3433       type_ = kR6FarLabel;
   3434       break;
   3435     // R6 near literal.
   3436     case kR6Literal:
   3437       type_ = kR6FarLiteral;
   3438       break;
   3439     default:
   3440       // Note: 'type_' is already long.
   3441       break;
   3442   }
   3443   CHECK(IsLong());
   3444 }
   3445 
   3446 uint32_t MipsAssembler::GetBranchLocationOrPcRelBase(const MipsAssembler::Branch* branch) const {
   3447   switch (branch->GetType()) {
   3448     case Branch::kLabel:
   3449     case Branch::kFarLabel:
   3450     case Branch::kLiteral:
   3451     case Branch::kFarLiteral:
   3452       return GetLabelLocation(&pc_rel_base_label_);
   3453     default:
   3454       return branch->GetLocation();
   3455   }
   3456 }
   3457 
   3458 uint32_t MipsAssembler::Branch::PromoteIfNeeded(uint32_t location, uint32_t max_short_distance) {
   3459   // `location` is either `GetLabelLocation(&pc_rel_base_label_)` for R2 labels/literals or
   3460   // `this->GetLocation()` for everything else.
   3461   // If the branch is still unresolved or already long, nothing to do.
   3462   if (IsLong() || !IsResolved()) {
   3463     return 0;
   3464   }
   3465   // Promote the short branch to long if the offset size is too small
   3466   // to hold the distance between location and target_.
   3467   if (GetOffsetSizeNeeded(location, target_) > GetOffsetSize()) {
   3468     PromoteToLong();
   3469     uint32_t old_size = GetOldSize();
   3470     uint32_t new_size = GetSize();
   3471     CHECK_GT(new_size, old_size);
   3472     return new_size - old_size;
   3473   }
   3474   // The following logic is for debugging/testing purposes.
   3475   // Promote some short branches to long when it's not really required.
   3476   if (UNLIKELY(max_short_distance != std::numeric_limits<uint32_t>::max())) {
   3477     int64_t distance = static_cast<int64_t>(target_) - location;
   3478     distance = (distance >= 0) ? distance : -distance;
   3479     if (distance >= max_short_distance) {
   3480       PromoteToLong();
   3481       uint32_t old_size = GetOldSize();
   3482       uint32_t new_size = GetSize();
   3483       CHECK_GT(new_size, old_size);
   3484       return new_size - old_size;
   3485     }
   3486   }
   3487   return 0;
   3488 }
   3489 
   3490 uint32_t MipsAssembler::Branch::GetOffsetLocation() const {
   3491   return location_ + GetPrecedingInstructionSize(type_) +
   3492       branch_info_[type_].instr_offset * sizeof(uint32_t);
   3493 }
   3494 
   3495 uint32_t MipsAssembler::GetBranchOrPcRelBaseForEncoding(const MipsAssembler::Branch* branch) const {
   3496   switch (branch->GetType()) {
   3497     case Branch::kLabel:
   3498     case Branch::kFarLabel:
   3499     case Branch::kLiteral:
   3500     case Branch::kFarLiteral:
   3501       return GetLabelLocation(&pc_rel_base_label_);
   3502     default:
   3503       return branch->GetOffsetLocation() +
   3504           Branch::branch_info_[branch->GetType()].pc_org * sizeof(uint32_t);
   3505   }
   3506 }
   3507 
   3508 uint32_t MipsAssembler::Branch::GetOffset(uint32_t location) const {
   3509   // `location` is either `GetLabelLocation(&pc_rel_base_label_)` for R2 labels/literals or
   3510   // `this->GetOffsetLocation() + branch_info_[this->GetType()].pc_org * sizeof(uint32_t)`
   3511   // for everything else.
   3512   CHECK(IsResolved());
   3513   uint32_t ofs_mask = 0xFFFFFFFF >> (32 - GetOffsetSize());
   3514   // Calculate the byte distance between instructions and also account for
   3515   // different PC-relative origins.
   3516   uint32_t offset = target_ - location;
   3517   // Prepare the offset for encoding into the instruction(s).
   3518   offset = (offset & ofs_mask) >> branch_info_[type_].offset_shift;
   3519   return offset;
   3520 }
   3521 
   3522 MipsAssembler::Branch* MipsAssembler::GetBranch(uint32_t branch_id) {
   3523   CHECK_LT(branch_id, branches_.size());
   3524   return &branches_[branch_id];
   3525 }
   3526 
   3527 const MipsAssembler::Branch* MipsAssembler::GetBranch(uint32_t branch_id) const {
   3528   CHECK_LT(branch_id, branches_.size());
   3529   return &branches_[branch_id];
   3530 }
   3531 
   3532 void MipsAssembler::Bind(MipsLabel* label) {
   3533   CHECK(!label->IsBound());
   3534   uint32_t bound_pc = buffer_.Size();
   3535 
   3536   // Make the delay slot FSM aware of the new label.
   3537   DsFsmLabel();
   3538 
   3539   // Walk the list of branches referring to and preceding this label.
   3540   // Store the previously unknown target addresses in them.
   3541   while (label->IsLinked()) {
   3542     uint32_t branch_id = label->Position();
   3543     Branch* branch = GetBranch(branch_id);
   3544     branch->Resolve(bound_pc);
   3545 
   3546     uint32_t branch_location = branch->GetLocation();
   3547     // Extract the location of the previous branch in the list (walking the list backwards;
   3548     // the previous branch ID was stored in the space reserved for this branch).
   3549     uint32_t prev = buffer_.Load<uint32_t>(branch_location);
   3550 
   3551     // On to the previous branch in the list...
   3552     label->position_ = prev;
   3553   }
   3554 
   3555   // Now make the label object contain its own location (relative to the end of the preceding
   3556   // branch, if any; it will be used by the branches referring to and following this label).
   3557   label->prev_branch_id_plus_one_ = branches_.size();
   3558   if (label->prev_branch_id_plus_one_) {
   3559     uint32_t branch_id = label->prev_branch_id_plus_one_ - 1;
   3560     const Branch* branch = GetBranch(branch_id);
   3561     bound_pc -= branch->GetEndLocation();
   3562   }
   3563   label->BindTo(bound_pc);
   3564 }
   3565 
   3566 uint32_t MipsAssembler::GetLabelLocation(const MipsLabel* label) const {
   3567   CHECK(label->IsBound());
   3568   uint32_t target = label->Position();
   3569   if (label->prev_branch_id_plus_one_) {
   3570     // Get label location based on the branch preceding it.
   3571     uint32_t branch_id = label->prev_branch_id_plus_one_ - 1;
   3572     const Branch* branch = GetBranch(branch_id);
   3573     target += branch->GetEndLocation();
   3574   }
   3575   return target;
   3576 }
   3577 
   3578 uint32_t MipsAssembler::GetAdjustedPosition(uint32_t old_position) {
   3579   // We can reconstruct the adjustment by going through all the branches from the beginning
   3580   // up to the old_position. Since we expect AdjustedPosition() to be called in a loop
   3581   // with increasing old_position, we can use the data from last AdjustedPosition() to
   3582   // continue where we left off and the whole loop should be O(m+n) where m is the number
   3583   // of positions to adjust and n is the number of branches.
   3584   if (old_position < last_old_position_) {
   3585     last_position_adjustment_ = 0;
   3586     last_old_position_ = 0;
   3587     last_branch_id_ = 0;
   3588   }
   3589   while (last_branch_id_ != branches_.size()) {
   3590     const Branch* branch = GetBranch(last_branch_id_);
   3591     if (branch->GetLocation() >= old_position + last_position_adjustment_) {
   3592       break;
   3593     }
   3594     last_position_adjustment_ += branch->GetSize() - branch->GetOldSize();
   3595     ++last_branch_id_;
   3596   }
   3597   last_old_position_ = old_position;
   3598   return old_position + last_position_adjustment_;
   3599 }
   3600 
   3601 void MipsAssembler::BindPcRelBaseLabel() {
   3602   Bind(&pc_rel_base_label_);
   3603 }
   3604 
   3605 uint32_t MipsAssembler::GetPcRelBaseLabelLocation() const {
   3606   return GetLabelLocation(&pc_rel_base_label_);
   3607 }
   3608 
   3609 void MipsAssembler::FinalizeLabeledBranch(MipsLabel* label) {
   3610   uint32_t length = branches_.back().GetLength();
   3611   // Commit the last branch target label (if any).
   3612   DsFsmCommitLabel();
   3613   if (!label->IsBound()) {
   3614     // Branch forward (to a following label), distance is unknown.
   3615     // The first branch forward will contain 0, serving as the terminator of
   3616     // the list of forward-reaching branches.
   3617     Emit(label->position_);
   3618     // Nothing for the delay slot (yet).
   3619     DsFsmInstrNop(0);
   3620     length--;
   3621     // Now make the label object point to this branch
   3622     // (this forms a linked list of branches preceding this label).
   3623     uint32_t branch_id = branches_.size() - 1;
   3624     label->LinkTo(branch_id);
   3625   }
   3626   // Reserve space for the branch.
   3627   while (length--) {
   3628     Nop();
   3629   }
   3630 }
   3631 
   3632 bool MipsAssembler::Branch::CanHaveDelayedInstruction(const DelaySlot& delay_slot) const {
   3633   if (delay_slot.instruction_ == 0) {
   3634     // NOP or no instruction for the delay slot.
   3635     return false;
   3636   }
   3637   switch (type_) {
   3638     // R2 unconditional branches.
   3639     case kUncondBranch:
   3640     case kLongUncondBranch:
   3641       // There are no register interdependencies.
   3642       return true;
   3643 
   3644     // R2 calls.
   3645     case kCall:
   3646     case kLongCall:
   3647       // Instructions depending on or modifying RA should not be moved into delay slots
   3648       // of branches modifying RA.
   3649       return ((delay_slot.gpr_ins_mask_ | delay_slot.gpr_outs_mask_) & (1u << RA)) == 0;
   3650 
   3651     // R2 conditional branches.
   3652     case kCondBranch:
   3653     case kLongCondBranch:
   3654       switch (condition_) {
   3655         // Branches with one GPR source.
   3656         case kCondLTZ:
   3657         case kCondGEZ:
   3658         case kCondLEZ:
   3659         case kCondGTZ:
   3660         case kCondEQZ:
   3661         case kCondNEZ:
   3662           return (delay_slot.gpr_outs_mask_ & (1u << lhs_reg_)) == 0;
   3663 
   3664         // Branches with two GPR sources.
   3665         case kCondEQ:
   3666         case kCondNE:
   3667           return (delay_slot.gpr_outs_mask_ & ((1u << lhs_reg_) | (1u << rhs_reg_))) == 0;
   3668 
   3669         // Branches with one FPU condition code source.
   3670         case kCondF:
   3671         case kCondT:
   3672           return (delay_slot.cc_outs_mask_ & (1u << lhs_reg_)) == 0;
   3673 
   3674         default:
   3675           // We don't support synthetic R2 branches (preceded with slt[u]) at this level
   3676           // (R2 doesn't have branches to compare 2 registers using <, <=, >=, >).
   3677           LOG(FATAL) << "Unexpected branch condition " << condition_;
   3678           UNREACHABLE();
   3679       }
   3680 
   3681     // R6 unconditional branches.
   3682     case kR6UncondBranch:
   3683     case kR6LongUncondBranch:
   3684     // R6 calls.
   3685     case kR6Call:
   3686     case kR6LongCall:
   3687       // There are no delay slots.
   3688       return false;
   3689 
   3690     // R6 conditional branches.
   3691     case kR6CondBranch:
   3692     case kR6LongCondBranch:
   3693       switch (condition_) {
   3694         // Branches with one FPU register source.
   3695         case kCondF:
   3696         case kCondT:
   3697           return (delay_slot.fpr_outs_mask_ & (1u << lhs_reg_)) == 0;
   3698         // Others have a forbidden slot instead of a delay slot.
   3699         default:
   3700           return false;
   3701       }
   3702 
   3703     // Literals.
   3704     default:
   3705       LOG(FATAL) << "Unexpected branch type " << type_;
   3706       UNREACHABLE();
   3707   }
   3708 }
   3709 
   3710 uint32_t MipsAssembler::Branch::GetDelayedInstruction() const {
   3711   return delayed_instruction_;
   3712 }
   3713 
   3714 void MipsAssembler::Branch::SetDelayedInstruction(uint32_t instruction) {
   3715   CHECK_NE(instruction, kUnfilledDelaySlot);
   3716   CHECK_EQ(delayed_instruction_, kUnfilledDelaySlot);
   3717   delayed_instruction_ = instruction;
   3718 }
   3719 
   3720 void MipsAssembler::Branch::DecrementLocations() {
   3721   // We first create a branch object, which gets its type and locations initialized,
   3722   // and then we check if the branch can actually have the preceding instruction moved
   3723   // into its delay slot. If it can, the branch locations need to be decremented.
   3724   //
   3725   // We could make the check before creating the branch object and avoid the location
   3726   // adjustment, but the check is cleaner when performed on an initialized branch
   3727   // object.
   3728   //
   3729   // If the branch is backwards (to a previously bound label), reducing the locations
   3730   // cannot cause a short branch to exceed its offset range because the offset reduces.
   3731   // And this is not at all a problem for a long branch backwards.
   3732   //
   3733   // If the branch is forward (not linked to any label yet), reducing the locations
   3734   // is harmless. The branch will be promoted to long if needed when the target is known.
   3735   CHECK_EQ(location_, old_location_);
   3736   CHECK_GE(old_location_, sizeof(uint32_t));
   3737   old_location_ -= sizeof(uint32_t);
   3738   location_ = old_location_;
   3739 }
   3740 
   3741 void MipsAssembler::MoveInstructionToDelaySlot(Branch& branch) {
   3742   if (branch.CanHaveDelayedInstruction(delay_slot_)) {
   3743     // The last instruction cannot be used in a different delay slot,
   3744     // do not commit the label before it (if any).
   3745     DsFsmDropLabel();
   3746     // Remove the last emitted instruction.
   3747     size_t size = buffer_.Size();
   3748     CHECK_GE(size, sizeof(uint32_t));
   3749     size -= sizeof(uint32_t);
   3750     CHECK_EQ(buffer_.Load<uint32_t>(size), delay_slot_.instruction_);
   3751     buffer_.Resize(size);
   3752     // Attach it to the branch and adjust the branch locations.
   3753     branch.DecrementLocations();
   3754     branch.SetDelayedInstruction(delay_slot_.instruction_);
   3755   } else if (!reordering_ && branch.GetType() == Branch::kUncondBranch) {
   3756     // If reordefing is disabled, prevent absorption of the target instruction.
   3757     branch.SetDelayedInstruction(Branch::kUnfillableDelaySlot);
   3758   }
   3759 }
   3760 
   3761 void MipsAssembler::Buncond(MipsLabel* label) {
   3762   uint32_t target = label->IsBound() ? GetLabelLocation(label) : Branch::kUnresolved;
   3763   branches_.emplace_back(IsR6(), buffer_.Size(), target, /* is_call */ false);
   3764   MoveInstructionToDelaySlot(branches_.back());
   3765   FinalizeLabeledBranch(label);
   3766 }
   3767 
   3768 void MipsAssembler::Bcond(MipsLabel* label, BranchCondition condition, Register lhs, Register rhs) {
   3769   // If lhs = rhs, this can be a NOP.
   3770   if (Branch::IsNop(condition, lhs, rhs)) {
   3771     return;
   3772   }
   3773   uint32_t target = label->IsBound() ? GetLabelLocation(label) : Branch::kUnresolved;
   3774   branches_.emplace_back(IsR6(), buffer_.Size(), target, condition, lhs, rhs);
   3775   MoveInstructionToDelaySlot(branches_.back());
   3776   FinalizeLabeledBranch(label);
   3777 }
   3778 
   3779 void MipsAssembler::Call(MipsLabel* label) {
   3780   uint32_t target = label->IsBound() ? GetLabelLocation(label) : Branch::kUnresolved;
   3781   branches_.emplace_back(IsR6(), buffer_.Size(), target, /* is_call */ true);
   3782   MoveInstructionToDelaySlot(branches_.back());
   3783   FinalizeLabeledBranch(label);
   3784 }
   3785 
   3786 void MipsAssembler::LoadLabelAddress(Register dest_reg, Register base_reg, MipsLabel* label) {
   3787   // Label address loads are treated as pseudo branches since they require very similar handling.
   3788   DCHECK(!label->IsBound());
   3789   branches_.emplace_back(IsR6(), buffer_.Size(), dest_reg, base_reg, Branch::kLabel);
   3790   FinalizeLabeledBranch(label);
   3791 }
   3792 
   3793 Literal* MipsAssembler::NewLiteral(size_t size, const uint8_t* data) {
   3794   DCHECK(size == 4u || size == 8u) << size;
   3795   literals_.emplace_back(size, data);
   3796   return &literals_.back();
   3797 }
   3798 
   3799 void MipsAssembler::LoadLiteral(Register dest_reg, Register base_reg, Literal* literal) {
   3800   // Literal loads are treated as pseudo branches since they require very similar handling.
   3801   DCHECK_EQ(literal->GetSize(), 4u);
   3802   MipsLabel* label = literal->GetLabel();
   3803   DCHECK(!label->IsBound());
   3804   branches_.emplace_back(IsR6(), buffer_.Size(), dest_reg, base_reg, Branch::kLiteral);
   3805   FinalizeLabeledBranch(label);
   3806 }
   3807 
   3808 JumpTable* MipsAssembler::CreateJumpTable(std::vector<MipsLabel*>&& labels) {
   3809   jump_tables_.emplace_back(std::move(labels));
   3810   JumpTable* table = &jump_tables_.back();
   3811   DCHECK(!table->GetLabel()->IsBound());
   3812   return table;
   3813 }
   3814 
   3815 void MipsAssembler::EmitLiterals() {
   3816   if (!literals_.empty()) {
   3817     // We don't support byte and half-word literals.
   3818     // TODO: proper alignment for 64-bit literals when they're implemented.
   3819     for (Literal& literal : literals_) {
   3820       MipsLabel* label = literal.GetLabel();
   3821       Bind(label);
   3822       AssemblerBuffer::EnsureCapacity ensured(&buffer_);
   3823       DCHECK(literal.GetSize() == 4u || literal.GetSize() == 8u);
   3824       for (size_t i = 0, size = literal.GetSize(); i != size; ++i) {
   3825         buffer_.Emit<uint8_t>(literal.GetData()[i]);
   3826       }
   3827     }
   3828   }
   3829 }
   3830 
   3831 void MipsAssembler::ReserveJumpTableSpace() {
   3832   if (!jump_tables_.empty()) {
   3833     for (JumpTable& table : jump_tables_) {
   3834       MipsLabel* label = table.GetLabel();
   3835       Bind(label);
   3836 
   3837       // Bulk ensure capacity, as this may be large.
   3838       size_t orig_size = buffer_.Size();
   3839       size_t required_capacity = orig_size + table.GetSize();
   3840       if (required_capacity > buffer_.Capacity()) {
   3841         buffer_.ExtendCapacity(required_capacity);
   3842       }
   3843 #ifndef NDEBUG
   3844       buffer_.has_ensured_capacity_ = true;
   3845 #endif
   3846 
   3847       // Fill the space with dummy data as the data is not final
   3848       // until the branches have been promoted. And we shouldn't
   3849       // be moving uninitialized data during branch promotion.
   3850       for (size_t cnt = table.GetData().size(), i = 0; i < cnt; i++) {
   3851         buffer_.Emit<uint32_t>(0x1abe1234u);
   3852       }
   3853 
   3854 #ifndef NDEBUG
   3855       buffer_.has_ensured_capacity_ = false;
   3856 #endif
   3857     }
   3858   }
   3859 }
   3860 
   3861 void MipsAssembler::EmitJumpTables() {
   3862   if (!jump_tables_.empty()) {
   3863     CHECK(!overwriting_);
   3864     // Switch from appending instructions at the end of the buffer to overwriting
   3865     // existing instructions (here, jump tables) in the buffer.
   3866     overwriting_ = true;
   3867 
   3868     for (JumpTable& table : jump_tables_) {
   3869       MipsLabel* table_label = table.GetLabel();
   3870       uint32_t start = GetLabelLocation(table_label);
   3871       overwrite_location_ = start;
   3872 
   3873       for (MipsLabel* target : table.GetData()) {
   3874         CHECK_EQ(buffer_.Load<uint32_t>(overwrite_location_), 0x1abe1234u);
   3875         // The table will contain target addresses relative to the table start.
   3876         uint32_t offset = GetLabelLocation(target) - start;
   3877         Emit(offset);
   3878       }
   3879     }
   3880 
   3881     overwriting_ = false;
   3882   }
   3883 }
   3884 
   3885 void MipsAssembler::PromoteBranches() {
   3886   // Promote short branches to long as necessary.
   3887   bool changed;
   3888   do {
   3889     changed = false;
   3890     for (auto& branch : branches_) {
   3891       CHECK(branch.IsResolved());
   3892       uint32_t base = GetBranchLocationOrPcRelBase(&branch);
   3893       uint32_t delta = branch.PromoteIfNeeded(base);
   3894       // If this branch has been promoted and needs to expand in size,
   3895       // relocate all branches by the expansion size.
   3896       if (delta) {
   3897         changed = true;
   3898         uint32_t expand_location = branch.GetLocation();
   3899         for (auto& branch2 : branches_) {
   3900           branch2.Relocate(expand_location, delta);
   3901         }
   3902       }
   3903     }
   3904   } while (changed);
   3905 
   3906   // Account for branch expansion by resizing the code buffer
   3907   // and moving the code in it to its final location.
   3908   size_t branch_count = branches_.size();
   3909   if (branch_count > 0) {
   3910     // Resize.
   3911     Branch& last_branch = branches_[branch_count - 1];
   3912     uint32_t size_delta = last_branch.GetEndLocation() - last_branch.GetOldEndLocation();
   3913     uint32_t old_size = buffer_.Size();
   3914     buffer_.Resize(old_size + size_delta);
   3915     // Move the code residing between branch placeholders.
   3916     uint32_t end = old_size;
   3917     for (size_t i = branch_count; i > 0; ) {
   3918       Branch& branch = branches_[--i];
   3919       CHECK_GE(end, branch.GetOldEndLocation());
   3920       uint32_t size = end - branch.GetOldEndLocation();
   3921       buffer_.Move(branch.GetEndLocation(), branch.GetOldEndLocation(), size);
   3922       end = branch.GetOldLocation();
   3923     }
   3924   }
   3925 }
   3926 
   3927 // Note: make sure branch_info_[] and EmitBranch() are kept synchronized.
   3928 const MipsAssembler::Branch::BranchInfo MipsAssembler::Branch::branch_info_[] = {
   3929   // R2 short branches.
   3930   {  2, 0, 1, MipsAssembler::Branch::kOffset18, 2 },  // kUncondBranch
   3931   {  2, 0, 1, MipsAssembler::Branch::kOffset18, 2 },  // kCondBranch
   3932   {  2, 0, 1, MipsAssembler::Branch::kOffset18, 2 },  // kCall
   3933   // R2 near label.
   3934   {  1, 0, 0, MipsAssembler::Branch::kOffset16, 0 },  // kLabel
   3935   // R2 near literal.
   3936   {  1, 0, 0, MipsAssembler::Branch::kOffset16, 0 },  // kLiteral
   3937   // R2 long branches.
   3938   {  9, 3, 1, MipsAssembler::Branch::kOffset32, 0 },  // kLongUncondBranch
   3939   { 10, 4, 1, MipsAssembler::Branch::kOffset32, 0 },  // kLongCondBranch
   3940   {  6, 1, 1, MipsAssembler::Branch::kOffset32, 0 },  // kLongCall
   3941   // R2 far label.
   3942   {  3, 0, 0, MipsAssembler::Branch::kOffset32, 0 },  // kFarLabel
   3943   // R2 far literal.
   3944   {  3, 0, 0, MipsAssembler::Branch::kOffset32, 0 },  // kFarLiteral
   3945   // R6 short branches.
   3946   {  1, 0, 1, MipsAssembler::Branch::kOffset28, 2 },  // kR6UncondBranch
   3947   {  2, 0, 1, MipsAssembler::Branch::kOffset18, 2 },  // kR6CondBranch
   3948                                                       // Exception: kOffset23 for beqzc/bnezc.
   3949   {  1, 0, 1, MipsAssembler::Branch::kOffset28, 2 },  // kR6Call
   3950   // R6 near label.
   3951   {  1, 0, 0, MipsAssembler::Branch::kOffset21, 2 },  // kR6Label
   3952   // R6 near literal.
   3953   {  1, 0, 0, MipsAssembler::Branch::kOffset21, 2 },  // kR6Literal
   3954   // R6 long branches.
   3955   {  2, 0, 0, MipsAssembler::Branch::kOffset32, 0 },  // kR6LongUncondBranch
   3956   {  3, 1, 0, MipsAssembler::Branch::kOffset32, 0 },  // kR6LongCondBranch
   3957   {  2, 0, 0, MipsAssembler::Branch::kOffset32, 0 },  // kR6LongCall
   3958   // R6 far label.
   3959   {  2, 0, 0, MipsAssembler::Branch::kOffset32, 0 },  // kR6FarLabel
   3960   // R6 far literal.
   3961   {  2, 0, 0, MipsAssembler::Branch::kOffset32, 0 },  // kR6FarLiteral
   3962 };
   3963 
   3964 // Note: make sure branch_info_[] and EmitBranch() are kept synchronized.
   3965 void MipsAssembler::EmitBranch(MipsAssembler::Branch* branch) {
   3966   CHECK_EQ(overwriting_, true);
   3967   overwrite_location_ = branch->GetLocation();
   3968   uint32_t offset = branch->GetOffset(GetBranchOrPcRelBaseForEncoding(branch));
   3969   BranchCondition condition = branch->GetCondition();
   3970   Register lhs = branch->GetLeftRegister();
   3971   Register rhs = branch->GetRightRegister();
   3972   uint32_t delayed_instruction = branch->GetDelayedInstruction();
   3973   switch (branch->GetType()) {
   3974     // R2 short branches.
   3975     case Branch::kUncondBranch:
   3976       if (delayed_instruction == Branch::kUnfillableDelaySlot) {
   3977         // The branch was created when reordering was disabled, do not absorb the target
   3978         // instruction.
   3979         delayed_instruction = 0;  // NOP.
   3980       } else if (delayed_instruction == Branch::kUnfilledDelaySlot) {
   3981         // Try to absorb the target instruction into the delay slot.
   3982         delayed_instruction = 0;  // NOP.
   3983         // Incrementing the signed 16-bit offset past the target instruction must not
   3984         // cause overflow into the negative subrange, check for the max offset.
   3985         if (offset != 0x7FFF) {
   3986           uint32_t target = branch->GetTarget();
   3987           if (std::binary_search(ds_fsm_target_pcs_.begin(), ds_fsm_target_pcs_.end(), target)) {
   3988             delayed_instruction = buffer_.Load<uint32_t>(target);
   3989             offset++;
   3990           }
   3991         }
   3992       }
   3993       CHECK_EQ(overwrite_location_, branch->GetOffsetLocation());
   3994       B(offset);
   3995       Emit(delayed_instruction);
   3996       break;
   3997     case Branch::kCondBranch:
   3998       DCHECK_NE(delayed_instruction, Branch::kUnfillableDelaySlot);
   3999       if (delayed_instruction == Branch::kUnfilledDelaySlot) {
   4000         delayed_instruction = 0;  // NOP.
   4001       }
   4002       CHECK_EQ(overwrite_location_, branch->GetOffsetLocation());
   4003       EmitBcondR2(condition, lhs, rhs, offset);
   4004       Emit(delayed_instruction);
   4005       break;
   4006     case Branch::kCall:
   4007       DCHECK_NE(delayed_instruction, Branch::kUnfillableDelaySlot);
   4008       if (delayed_instruction == Branch::kUnfilledDelaySlot) {
   4009         delayed_instruction = 0;  // NOP.
   4010       }
   4011       CHECK_EQ(overwrite_location_, branch->GetOffsetLocation());
   4012       Bal(offset);
   4013       Emit(delayed_instruction);
   4014       break;
   4015 
   4016     // R2 near label.
   4017     case Branch::kLabel:
   4018       DCHECK_EQ(delayed_instruction, Branch::kUnfilledDelaySlot);
   4019       CHECK_EQ(overwrite_location_, branch->GetOffsetLocation());
   4020       Addiu(lhs, rhs, offset);
   4021       break;
   4022     // R2 near literal.
   4023     case Branch::kLiteral:
   4024       DCHECK_EQ(delayed_instruction, Branch::kUnfilledDelaySlot);
   4025       CHECK_EQ(overwrite_location_, branch->GetOffsetLocation());
   4026       Lw(lhs, rhs, offset);
   4027       break;
   4028 
   4029     // R2 long branches.
   4030     case Branch::kLongUncondBranch:
   4031       // To get the value of the PC register we need to use the NAL instruction.
   4032       // NAL clobbers the RA register. However, RA must be preserved if the
   4033       // method is compiled without the entry/exit sequences that would take care
   4034       // of preserving RA (typically, leaf methods don't preserve RA explicitly).
   4035       // So, we need to preserve RA in some temporary storage ourselves. The AT
   4036       // register can't be used for this because we need it to load a constant
   4037       // which will be added to the value that NAL stores in RA. And we can't
   4038       // use T9 for this in the context of the JNI compiler, which uses it
   4039       // as a scratch register (see InterproceduralScratchRegister()).
   4040       // If we were to add a 32-bit constant to RA using two ADDIU instructions,
   4041       // we'd also need to use the ROTR instruction, which requires no less than
   4042       // MIPSR2.
   4043       // Perhaps, we could use T8 or one of R2's multiplier/divider registers
   4044       // (LO or HI) or even a floating-point register, but that doesn't seem
   4045       // like a nice solution. We may want this to work on both R6 and pre-R6.
   4046       // For now simply use the stack for RA. This should be OK since for the
   4047       // vast majority of code a short PC-relative branch is sufficient.
   4048       // TODO: can this be improved?
   4049       // TODO: consider generation of a shorter sequence when we know that RA
   4050       // is explicitly preserved by the method entry/exit code.
   4051       if (delayed_instruction != Branch::kUnfilledDelaySlot &&
   4052           delayed_instruction != Branch::kUnfillableDelaySlot) {
   4053         Emit(delayed_instruction);
   4054       }
   4055       Push(RA);
   4056       Nal();
   4057       CHECK_EQ(overwrite_location_, branch->GetOffsetLocation());
   4058       Lui(AT, High16Bits(offset));
   4059       Ori(AT, AT, Low16Bits(offset));
   4060       Addu(AT, AT, RA);
   4061       Lw(RA, SP, 0);
   4062       Jr(AT);
   4063       DecreaseFrameSize(kMipsWordSize);
   4064       break;
   4065     case Branch::kLongCondBranch:
   4066       // The comment on case 'Branch::kLongUncondBranch' applies here as well.
   4067       DCHECK_NE(delayed_instruction, Branch::kUnfillableDelaySlot);
   4068       if (delayed_instruction != Branch::kUnfilledDelaySlot) {
   4069         Emit(delayed_instruction);
   4070       }
   4071       // Note: the opposite condition branch encodes 8 as the distance, which is equal to the
   4072       // number of instructions skipped:
   4073       // (PUSH(IncreaseFrameSize(ADDIU) + SW) + NAL + LUI + ORI + ADDU + LW + JR).
   4074       EmitBcondR2(Branch::OppositeCondition(condition), lhs, rhs, 8);
   4075       Push(RA);
   4076       Nal();
   4077       CHECK_EQ(overwrite_location_, branch->GetOffsetLocation());
   4078       Lui(AT, High16Bits(offset));
   4079       Ori(AT, AT, Low16Bits(offset));
   4080       Addu(AT, AT, RA);
   4081       Lw(RA, SP, 0);
   4082       Jr(AT);
   4083       DecreaseFrameSize(kMipsWordSize);
   4084       break;
   4085     case Branch::kLongCall:
   4086       DCHECK_NE(delayed_instruction, Branch::kUnfillableDelaySlot);
   4087       if (delayed_instruction != Branch::kUnfilledDelaySlot) {
   4088         Emit(delayed_instruction);
   4089       }
   4090       Nal();
   4091       CHECK_EQ(overwrite_location_, branch->GetOffsetLocation());
   4092       Lui(AT, High16Bits(offset));
   4093       Ori(AT, AT, Low16Bits(offset));
   4094       Addu(AT, AT, RA);
   4095       Jalr(AT);
   4096       Nop();
   4097       break;
   4098 
   4099     // R2 far label.
   4100     case Branch::kFarLabel:
   4101       DCHECK_EQ(delayed_instruction, Branch::kUnfilledDelaySlot);
   4102       CHECK_EQ(overwrite_location_, branch->GetOffsetLocation());
   4103       Lui(AT, High16Bits(offset));
   4104       Ori(AT, AT, Low16Bits(offset));
   4105       Addu(lhs, AT, rhs);
   4106       break;
   4107     // R2 far literal.
   4108     case Branch::kFarLiteral:
   4109       DCHECK_EQ(delayed_instruction, Branch::kUnfilledDelaySlot);
   4110       offset += (offset & 0x8000) << 1;  // Account for sign extension in lw.
   4111       CHECK_EQ(overwrite_location_, branch->GetOffsetLocation());
   4112       Lui(AT, High16Bits(offset));
   4113       Addu(AT, AT, rhs);
   4114       Lw(lhs, AT, Low16Bits(offset));
   4115       break;
   4116 
   4117     // R6 short branches.
   4118     case Branch::kR6UncondBranch:
   4119       DCHECK_EQ(delayed_instruction, Branch::kUnfilledDelaySlot);
   4120       CHECK_EQ(overwrite_location_, branch->GetOffsetLocation());
   4121       Bc(offset);
   4122       break;
   4123     case Branch::kR6CondBranch:
   4124       CHECK_EQ(overwrite_location_, branch->GetOffsetLocation());
   4125       EmitBcondR6(condition, lhs, rhs, offset);
   4126       DCHECK_NE(delayed_instruction, Branch::kUnfillableDelaySlot);
   4127       if (delayed_instruction != Branch::kUnfilledDelaySlot) {
   4128         Emit(delayed_instruction);
   4129       } else {
   4130         // TODO: improve by filling the forbidden slot (IFF this is
   4131         // a forbidden and not a delay slot).
   4132         Nop();
   4133       }
   4134       break;
   4135     case Branch::kR6Call:
   4136       DCHECK_EQ(delayed_instruction, Branch::kUnfilledDelaySlot);
   4137       CHECK_EQ(overwrite_location_, branch->GetOffsetLocation());
   4138       Balc(offset);
   4139       break;
   4140 
   4141     // R6 near label.
   4142     case Branch::kR6Label:
   4143       DCHECK_EQ(delayed_instruction, Branch::kUnfilledDelaySlot);
   4144       CHECK_EQ(overwrite_location_, branch->GetOffsetLocation());
   4145       Addiupc(lhs, offset);
   4146       break;
   4147     // R6 near literal.
   4148     case Branch::kR6Literal:
   4149       DCHECK_EQ(delayed_instruction, Branch::kUnfilledDelaySlot);
   4150       CHECK_EQ(overwrite_location_, branch->GetOffsetLocation());
   4151       Lwpc(lhs, offset);
   4152       break;
   4153 
   4154     // R6 long branches.
   4155     case Branch::kR6LongUncondBranch:
   4156       DCHECK_EQ(delayed_instruction, Branch::kUnfilledDelaySlot);
   4157       offset += (offset & 0x8000) << 1;  // Account for sign extension in jic.
   4158       CHECK_EQ(overwrite_location_, branch->GetOffsetLocation());
   4159       Auipc(AT, High16Bits(offset));
   4160       Jic(AT, Low16Bits(offset));
   4161       break;
   4162     case Branch::kR6LongCondBranch:
   4163       DCHECK_NE(delayed_instruction, Branch::kUnfillableDelaySlot);
   4164       if (delayed_instruction != Branch::kUnfilledDelaySlot) {
   4165         Emit(delayed_instruction);
   4166       }
   4167       EmitBcondR6(Branch::OppositeCondition(condition), lhs, rhs, 2);
   4168       offset += (offset & 0x8000) << 1;  // Account for sign extension in jic.
   4169       CHECK_EQ(overwrite_location_, branch->GetOffsetLocation());
   4170       Auipc(AT, High16Bits(offset));
   4171       Jic(AT, Low16Bits(offset));
   4172       break;
   4173     case Branch::kR6LongCall:
   4174       DCHECK_EQ(delayed_instruction, Branch::kUnfilledDelaySlot);
   4175       offset += (offset & 0x8000) << 1;  // Account for sign extension in jialc.
   4176       CHECK_EQ(overwrite_location_, branch->GetOffsetLocation());
   4177       Auipc(AT, High16Bits(offset));
   4178       Jialc(AT, Low16Bits(offset));
   4179       break;
   4180 
   4181     // R6 far label.
   4182     case Branch::kR6FarLabel:
   4183       DCHECK_EQ(delayed_instruction, Branch::kUnfilledDelaySlot);
   4184       offset += (offset & 0x8000) << 1;  // Account for sign extension in addiu.
   4185       CHECK_EQ(overwrite_location_, branch->GetOffsetLocation());
   4186       Auipc(AT, High16Bits(offset));
   4187       Addiu(lhs, AT, Low16Bits(offset));
   4188       break;
   4189     // R6 far literal.
   4190     case Branch::kR6FarLiteral:
   4191       DCHECK_EQ(delayed_instruction, Branch::kUnfilledDelaySlot);
   4192       offset += (offset & 0x8000) << 1;  // Account for sign extension in lw.
   4193       CHECK_EQ(overwrite_location_, branch->GetOffsetLocation());
   4194       Auipc(AT, High16Bits(offset));
   4195       Lw(lhs, AT, Low16Bits(offset));
   4196       break;
   4197   }
   4198   CHECK_EQ(overwrite_location_, branch->GetEndLocation());
   4199   CHECK_LT(branch->GetSize(), static_cast<uint32_t>(Branch::kMaxBranchSize));
   4200 }
   4201 
   4202 void MipsAssembler::B(MipsLabel* label) {
   4203   Buncond(label);
   4204 }
   4205 
   4206 void MipsAssembler::Bal(MipsLabel* label) {
   4207   Call(label);
   4208 }
   4209 
   4210 void MipsAssembler::Beq(Register rs, Register rt, MipsLabel* label) {
   4211   Bcond(label, kCondEQ, rs, rt);
   4212 }
   4213 
   4214 void MipsAssembler::Bne(Register rs, Register rt, MipsLabel* label) {
   4215   Bcond(label, kCondNE, rs, rt);
   4216 }
   4217 
   4218 void MipsAssembler::Beqz(Register rt, MipsLabel* label) {
   4219   Bcond(label, kCondEQZ, rt);
   4220 }
   4221 
   4222 void MipsAssembler::Bnez(Register rt, MipsLabel* label) {
   4223   Bcond(label, kCondNEZ, rt);
   4224 }
   4225 
   4226 void MipsAssembler::Bltz(Register rt, MipsLabel* label) {
   4227   Bcond(label, kCondLTZ, rt);
   4228 }
   4229 
   4230 void MipsAssembler::Bgez(Register rt, MipsLabel* label) {
   4231   Bcond(label, kCondGEZ, rt);
   4232 }
   4233 
   4234 void MipsAssembler::Blez(Register rt, MipsLabel* label) {
   4235   Bcond(label, kCondLEZ, rt);
   4236 }
   4237 
   4238 void MipsAssembler::Bgtz(Register rt, MipsLabel* label) {
   4239   Bcond(label, kCondGTZ, rt);
   4240 }
   4241 
   4242 bool MipsAssembler::CanExchangeWithSlt(Register rs, Register rt) const {
   4243   // If the instruction modifies AT, `rs` or `rt`, it can't be exchanged with the slt[u]
   4244   // instruction because either slt[u] depends on `rs` or `rt` or the following
   4245   // conditional branch depends on AT set by slt[u].
   4246   // Likewise, if the instruction depends on AT, it can't be exchanged with slt[u]
   4247   // because slt[u] changes AT.
   4248   return (delay_slot_.instruction_ != 0 &&
   4249       (delay_slot_.gpr_outs_mask_ & ((1u << AT) | (1u << rs) | (1u << rt))) == 0 &&
   4250       (delay_slot_.gpr_ins_mask_ & (1u << AT)) == 0);
   4251 }
   4252 
   4253 void MipsAssembler::ExchangeWithSlt(const DelaySlot& forwarded_slot) {
   4254   // Exchange the last two instructions in the assembler buffer.
   4255   size_t size = buffer_.Size();
   4256   CHECK_GE(size, 2 * sizeof(uint32_t));
   4257   size_t pos1 = size - 2 * sizeof(uint32_t);
   4258   size_t pos2 = size - sizeof(uint32_t);
   4259   uint32_t instr1 = buffer_.Load<uint32_t>(pos1);
   4260   uint32_t instr2 = buffer_.Load<uint32_t>(pos2);
   4261   CHECK_EQ(instr1, forwarded_slot.instruction_);
   4262   CHECK_EQ(instr2, delay_slot_.instruction_);
   4263   buffer_.Store<uint32_t>(pos1, instr2);
   4264   buffer_.Store<uint32_t>(pos2, instr1);
   4265   // Set the current delay slot information to that of the last instruction
   4266   // in the buffer.
   4267   delay_slot_ = forwarded_slot;
   4268 }
   4269 
   4270 void MipsAssembler::GenerateSltForCondBranch(bool unsigned_slt, Register rs, Register rt) {
   4271   // If possible, exchange the slt[u] instruction with the preceding instruction,
   4272   // so it can fill the delay slot.
   4273   DelaySlot forwarded_slot = delay_slot_;
   4274   bool exchange = CanExchangeWithSlt(rs, rt);
   4275   if (exchange) {
   4276     // The last instruction cannot be used in a different delay slot,
   4277     // do not commit the label before it (if any).
   4278     DsFsmDropLabel();
   4279   }
   4280   if (unsigned_slt) {
   4281     Sltu(AT, rs, rt);
   4282   } else {
   4283     Slt(AT, rs, rt);
   4284   }
   4285   if (exchange) {
   4286     ExchangeWithSlt(forwarded_slot);
   4287   }
   4288 }
   4289 
   4290 void MipsAssembler::Blt(Register rs, Register rt, MipsLabel* label) {
   4291   if (IsR6()) {
   4292     Bcond(label, kCondLT, rs, rt);
   4293   } else if (!Branch::IsNop(kCondLT, rs, rt)) {
   4294     // Synthesize the instruction (not available on R2).
   4295     GenerateSltForCondBranch(/* unsigned_slt */ false, rs, rt);
   4296     Bnez(AT, label);
   4297   }
   4298 }
   4299 
   4300 void MipsAssembler::Bge(Register rs, Register rt, MipsLabel* label) {
   4301   if (IsR6()) {
   4302     Bcond(label, kCondGE, rs, rt);
   4303   } else if (Branch::IsUncond(kCondGE, rs, rt)) {
   4304     B(label);
   4305   } else {
   4306     // Synthesize the instruction (not available on R2).
   4307     GenerateSltForCondBranch(/* unsigned_slt */ false, rs, rt);
   4308     Beqz(AT, label);
   4309   }
   4310 }
   4311 
   4312 void MipsAssembler::Bltu(Register rs, Register rt, MipsLabel* label) {
   4313   if (IsR6()) {
   4314     Bcond(label, kCondLTU, rs, rt);
   4315   } else if (!Branch::IsNop(kCondLTU, rs, rt)) {
   4316     // Synthesize the instruction (not available on R2).
   4317     GenerateSltForCondBranch(/* unsigned_slt */ true, rs, rt);
   4318     Bnez(AT, label);
   4319   }
   4320 }
   4321 
   4322 void MipsAssembler::Bgeu(Register rs, Register rt, MipsLabel* label) {
   4323   if (IsR6()) {
   4324     Bcond(label, kCondGEU, rs, rt);
   4325   } else if (Branch::IsUncond(kCondGEU, rs, rt)) {
   4326     B(label);
   4327   } else {
   4328     // Synthesize the instruction (not available on R2).
   4329     GenerateSltForCondBranch(/* unsigned_slt */ true, rs, rt);
   4330     Beqz(AT, label);
   4331   }
   4332 }
   4333 
   4334 void MipsAssembler::Bc1f(MipsLabel* label) {
   4335   Bc1f(0, label);
   4336 }
   4337 
   4338 void MipsAssembler::Bc1f(int cc, MipsLabel* label) {
   4339   CHECK(IsUint<3>(cc)) << cc;
   4340   Bcond(label, kCondF, static_cast<Register>(cc), ZERO);
   4341 }
   4342 
   4343 void MipsAssembler::Bc1t(MipsLabel* label) {
   4344   Bc1t(0, label);
   4345 }
   4346 
   4347 void MipsAssembler::Bc1t(int cc, MipsLabel* label) {
   4348   CHECK(IsUint<3>(cc)) << cc;
   4349   Bcond(label, kCondT, static_cast<Register>(cc), ZERO);
   4350 }
   4351 
   4352 void MipsAssembler::Bc1eqz(FRegister ft, MipsLabel* label) {
   4353   Bcond(label, kCondF, static_cast<Register>(ft), ZERO);
   4354 }
   4355 
   4356 void MipsAssembler::Bc1nez(FRegister ft, MipsLabel* label) {
   4357   Bcond(label, kCondT, static_cast<Register>(ft), ZERO);
   4358 }
   4359 
   4360 void MipsAssembler::AdjustBaseAndOffset(Register& base,
   4361                                         int32_t& offset,
   4362                                         bool is_doubleword,
   4363                                         bool is_float) {
   4364   // This method is used to adjust the base register and offset pair
   4365   // for a load/store when the offset doesn't fit into int16_t.
   4366   // It is assumed that `base + offset` is sufficiently aligned for memory
   4367   // operands that are machine word in size or smaller. For doubleword-sized
   4368   // operands it's assumed that `base` is a multiple of 8, while `offset`
   4369   // may be a multiple of 4 (e.g. 4-byte-aligned long and double arguments
   4370   // and spilled variables on the stack accessed relative to the stack
   4371   // pointer register).
   4372   // We preserve the "alignment" of `offset` by adjusting it by a multiple of 8.
   4373   CHECK_NE(base, AT);  // Must not overwrite the register `base` while loading `offset`.
   4374 
   4375   bool doubleword_aligned = IsAligned<kMipsDoublewordSize>(offset);
   4376   bool two_accesses = is_doubleword && (!is_float || !doubleword_aligned);
   4377 
   4378   // IsInt<16> must be passed a signed value, hence the static cast below.
   4379   if (IsInt<16>(offset) &&
   4380       (!two_accesses || IsInt<16>(static_cast<int32_t>(offset + kMipsWordSize)))) {
   4381     // Nothing to do: `offset` (and, if needed, `offset + 4`) fits into int16_t.
   4382     return;
   4383   }
   4384 
   4385   // Remember the "(mis)alignment" of `offset`, it will be checked at the end.
   4386   uint32_t misalignment = offset & (kMipsDoublewordSize - 1);
   4387 
   4388   // Do not load the whole 32-bit `offset` if it can be represented as
   4389   // a sum of two 16-bit signed offsets. This can save an instruction or two.
   4390   // To simplify matters, only do this for a symmetric range of offsets from
   4391   // about -64KB to about +64KB, allowing further addition of 4 when accessing
   4392   // 64-bit variables with two 32-bit accesses.
   4393   constexpr int32_t kMinOffsetForSimpleAdjustment = 0x7ff8;  // Max int16_t that's a multiple of 8.
   4394   constexpr int32_t kMaxOffsetForSimpleAdjustment = 2 * kMinOffsetForSimpleAdjustment;
   4395   if (0 <= offset && offset <= kMaxOffsetForSimpleAdjustment) {
   4396     Addiu(AT, base, kMinOffsetForSimpleAdjustment);
   4397     offset -= kMinOffsetForSimpleAdjustment;
   4398   } else if (-kMaxOffsetForSimpleAdjustment <= offset && offset < 0) {
   4399     Addiu(AT, base, -kMinOffsetForSimpleAdjustment);
   4400     offset += kMinOffsetForSimpleAdjustment;
   4401   } else if (IsR6()) {
   4402     // On R6 take advantage of the aui instruction, e.g.:
   4403     //   aui   AT, base, offset_high
   4404     //   lw    reg_lo, offset_low(AT)
   4405     //   lw    reg_hi, (offset_low+4)(AT)
   4406     // or when offset_low+4 overflows int16_t:
   4407     //   aui   AT, base, offset_high
   4408     //   addiu AT, AT, 8
   4409     //   lw    reg_lo, (offset_low-8)(AT)
   4410     //   lw    reg_hi, (offset_low-4)(AT)
   4411     int16_t offset_high = High16Bits(offset);
   4412     int16_t offset_low = Low16Bits(offset);
   4413     offset_high += (offset_low < 0) ? 1 : 0;  // Account for offset sign extension in load/store.
   4414     Aui(AT, base, offset_high);
   4415     if (two_accesses && !IsInt<16>(static_cast<int32_t>(offset_low + kMipsWordSize))) {
   4416       // Avoid overflow in the 16-bit offset of the load/store instruction when adding 4.
   4417       Addiu(AT, AT, kMipsDoublewordSize);
   4418       offset_low -= kMipsDoublewordSize;
   4419     }
   4420     offset = offset_low;
   4421   } else {
   4422     // Do not load the whole 32-bit `offset` if it can be represented as
   4423     // a sum of three 16-bit signed offsets. This can save an instruction.
   4424     // To simplify matters, only do this for a symmetric range of offsets from
   4425     // about -96KB to about +96KB, allowing further addition of 4 when accessing
   4426     // 64-bit variables with two 32-bit accesses.
   4427     constexpr int32_t kMinOffsetForMediumAdjustment = 2 * kMinOffsetForSimpleAdjustment;
   4428     constexpr int32_t kMaxOffsetForMediumAdjustment = 3 * kMinOffsetForSimpleAdjustment;
   4429     if (0 <= offset && offset <= kMaxOffsetForMediumAdjustment) {
   4430       Addiu(AT, base, kMinOffsetForMediumAdjustment / 2);
   4431       Addiu(AT, AT, kMinOffsetForMediumAdjustment / 2);
   4432       offset -= kMinOffsetForMediumAdjustment;
   4433     } else if (-kMaxOffsetForMediumAdjustment <= offset && offset < 0) {
   4434       Addiu(AT, base, -kMinOffsetForMediumAdjustment / 2);
   4435       Addiu(AT, AT, -kMinOffsetForMediumAdjustment / 2);
   4436       offset += kMinOffsetForMediumAdjustment;
   4437     } else {
   4438       // Now that all shorter options have been exhausted, load the full 32-bit offset.
   4439       int32_t loaded_offset = RoundDown(offset, kMipsDoublewordSize);
   4440       LoadConst32(AT, loaded_offset);
   4441       Addu(AT, AT, base);
   4442       offset -= loaded_offset;
   4443     }
   4444   }
   4445   base = AT;
   4446 
   4447   CHECK(IsInt<16>(offset));
   4448   if (two_accesses) {
   4449     CHECK(IsInt<16>(static_cast<int32_t>(offset + kMipsWordSize)));
   4450   }
   4451   CHECK_EQ(misalignment, offset & (kMipsDoublewordSize - 1));
   4452 }
   4453 
   4454 void MipsAssembler::AdjustBaseOffsetAndElementSizeShift(Register& base,
   4455                                                         int32_t& offset,
   4456                                                         int& element_size_shift) {
   4457   // This method is used to adjust the base register, offset and element_size_shift
   4458   // for a vector load/store when the offset doesn't fit into allowed number of bits.
   4459   // MSA ld.df and st.df instructions take signed offsets as arguments, but maximum
   4460   // offset is dependant on the size of the data format df (10-bit offsets for ld.b,
   4461   // 11-bit for ld.h, 12-bit for ld.w and 13-bit for ld.d).
   4462   // If element_size_shift is non-negative at entry, it won't be changed, but offset
   4463   // will be checked for appropriate alignment. If negative at entry, it will be
   4464   // adjusted based on offset for maximum fit.
   4465   // It's assumed that `base` is a multiple of 8.
   4466   CHECK_NE(base, AT);  // Must not overwrite the register `base` while loading `offset`.
   4467 
   4468   if (element_size_shift >= 0) {
   4469     CHECK_LE(element_size_shift, TIMES_8);
   4470     CHECK_GE(JAVASTYLE_CTZ(offset), element_size_shift);
   4471   } else if (IsAligned<kMipsDoublewordSize>(offset)) {
   4472     element_size_shift = TIMES_8;
   4473   } else if (IsAligned<kMipsWordSize>(offset)) {
   4474     element_size_shift = TIMES_4;
   4475   } else if (IsAligned<kMipsHalfwordSize>(offset)) {
   4476     element_size_shift = TIMES_2;
   4477   } else {
   4478     element_size_shift = TIMES_1;
   4479   }
   4480 
   4481   const int low_len = 10 + element_size_shift;  // How many low bits of `offset` ld.df/st.df
   4482                                                 // will take.
   4483   int16_t low = offset & ((1 << low_len) - 1);  // Isolate these bits.
   4484   low -= (low & (1 << (low_len - 1))) << 1;     // Sign-extend these bits.
   4485   if (low == offset) {
   4486     return;  // `offset` fits into ld.df/st.df.
   4487   }
   4488 
   4489   // First, see if `offset` can be represented as a sum of two or three signed offsets.
   4490   // This can save an instruction or two.
   4491 
   4492   // Max int16_t that's a multiple of element size.
   4493   const int32_t kMaxDeltaForSimpleAdjustment = 0x8000 - (1 << element_size_shift);
   4494   // Max ld.df/st.df offset that's a multiple of element size.
   4495   const int32_t kMaxLoadStoreOffset = 0x1ff << element_size_shift;
   4496   const int32_t kMaxOffsetForSimpleAdjustment = kMaxDeltaForSimpleAdjustment + kMaxLoadStoreOffset;
   4497   const int32_t kMinOffsetForMediumAdjustment = 2 * kMaxDeltaForSimpleAdjustment;
   4498   const int32_t kMaxOffsetForMediumAdjustment = kMinOffsetForMediumAdjustment + kMaxLoadStoreOffset;
   4499 
   4500   if (IsInt<16>(offset)) {
   4501     Addiu(AT, base, offset);
   4502     offset = 0;
   4503   } else if (0 <= offset && offset <= kMaxOffsetForSimpleAdjustment) {
   4504     Addiu(AT, base, kMaxDeltaForSimpleAdjustment);
   4505     offset -= kMaxDeltaForSimpleAdjustment;
   4506   } else if (-kMaxOffsetForSimpleAdjustment <= offset && offset < 0) {
   4507     Addiu(AT, base, -kMaxDeltaForSimpleAdjustment);
   4508     offset += kMaxDeltaForSimpleAdjustment;
   4509   } else if (!IsR6() && 0 <= offset && offset <= kMaxOffsetForMediumAdjustment) {
   4510     Addiu(AT, base, kMaxDeltaForSimpleAdjustment);
   4511     if (offset <= kMinOffsetForMediumAdjustment) {
   4512       Addiu(AT, AT, offset - kMaxDeltaForSimpleAdjustment);
   4513       offset = 0;
   4514     } else {
   4515       Addiu(AT, AT, kMaxDeltaForSimpleAdjustment);
   4516       offset -= kMinOffsetForMediumAdjustment;
   4517     }
   4518   } else if (!IsR6() && -kMaxOffsetForMediumAdjustment <= offset && offset < 0) {
   4519     Addiu(AT, base, -kMaxDeltaForSimpleAdjustment);
   4520     if (-kMinOffsetForMediumAdjustment <= offset) {
   4521       Addiu(AT, AT, offset + kMaxDeltaForSimpleAdjustment);
   4522       offset = 0;
   4523     } else {
   4524       Addiu(AT, AT, -kMaxDeltaForSimpleAdjustment);
   4525       offset += kMinOffsetForMediumAdjustment;
   4526     }
   4527   } else {
   4528     // 16-bit or smaller parts of `offset`:
   4529     // |31  hi  16|15  mid  13-10|12-9  low  0|
   4530     //
   4531     // Instructions that supply each part as a signed integer addend:
   4532     // |aui       |addiu         |ld.df/st.df |
   4533     uint32_t tmp = static_cast<uint32_t>(offset) - low;  // Exclude `low` from the rest of `offset`
   4534                                                          // (accounts for sign of `low`).
   4535     tmp += (tmp & (UINT32_C(1) << 15)) << 1;  // Account for sign extension in addiu.
   4536     int16_t mid = Low16Bits(tmp);
   4537     int16_t hi = High16Bits(tmp);
   4538     if (IsR6()) {
   4539       Aui(AT, base, hi);
   4540     } else {
   4541       Lui(AT, hi);
   4542       Addu(AT, AT, base);
   4543     }
   4544     if (mid != 0) {
   4545       Addiu(AT, AT, mid);
   4546     }
   4547     offset = low;
   4548   }
   4549   base = AT;
   4550   CHECK_GE(JAVASTYLE_CTZ(offset), element_size_shift);
   4551   CHECK(IsInt<10>(offset >> element_size_shift));
   4552 }
   4553 
   4554 void MipsAssembler::LoadFromOffset(LoadOperandType type,
   4555                                    Register reg,
   4556                                    Register base,
   4557                                    int32_t offset) {
   4558   LoadFromOffset<>(type, reg, base, offset);
   4559 }
   4560 
   4561 void MipsAssembler::LoadSFromOffset(FRegister reg, Register base, int32_t offset) {
   4562   LoadSFromOffset<>(reg, base, offset);
   4563 }
   4564 
   4565 void MipsAssembler::LoadDFromOffset(FRegister reg, Register base, int32_t offset) {
   4566   LoadDFromOffset<>(reg, base, offset);
   4567 }
   4568 
   4569 void MipsAssembler::LoadQFromOffset(FRegister reg, Register base, int32_t offset) {
   4570   LoadQFromOffset<>(reg, base, offset);
   4571 }
   4572 
   4573 void MipsAssembler::EmitLoad(ManagedRegister m_dst, Register src_register, int32_t src_offset,
   4574                              size_t size) {
   4575   MipsManagedRegister dst = m_dst.AsMips();
   4576   if (dst.IsNoRegister()) {
   4577     CHECK_EQ(0u, size) << dst;
   4578   } else if (dst.IsCoreRegister()) {
   4579     CHECK_EQ(kMipsWordSize, size) << dst;
   4580     LoadFromOffset(kLoadWord, dst.AsCoreRegister(), src_register, src_offset);
   4581   } else if (dst.IsRegisterPair()) {
   4582     CHECK_EQ(kMipsDoublewordSize, size) << dst;
   4583     LoadFromOffset(kLoadDoubleword, dst.AsRegisterPairLow(), src_register, src_offset);
   4584   } else if (dst.IsFRegister()) {
   4585     if (size == kMipsWordSize) {
   4586       LoadSFromOffset(dst.AsFRegister(), src_register, src_offset);
   4587     } else {
   4588       CHECK_EQ(kMipsDoublewordSize, size) << dst;
   4589       LoadDFromOffset(dst.AsFRegister(), src_register, src_offset);
   4590     }
   4591   } else if (dst.IsDRegister()) {
   4592     CHECK_EQ(kMipsDoublewordSize, size) << dst;
   4593     LoadDFromOffset(dst.AsOverlappingDRegisterLow(), src_register, src_offset);
   4594   }
   4595 }
   4596 
   4597 void MipsAssembler::StoreToOffset(StoreOperandType type,
   4598                                   Register reg,
   4599                                   Register base,
   4600                                   int32_t offset) {
   4601   StoreToOffset<>(type, reg, base, offset);
   4602 }
   4603 
   4604 void MipsAssembler::StoreSToOffset(FRegister reg, Register base, int32_t offset) {
   4605   StoreSToOffset<>(reg, base, offset);
   4606 }
   4607 
   4608 void MipsAssembler::StoreDToOffset(FRegister reg, Register base, int32_t offset) {
   4609   StoreDToOffset<>(reg, base, offset);
   4610 }
   4611 
   4612 void MipsAssembler::StoreQToOffset(FRegister reg, Register base, int32_t offset) {
   4613   StoreQToOffset<>(reg, base, offset);
   4614 }
   4615 
   4616 static dwarf::Reg DWARFReg(Register reg) {
   4617   return dwarf::Reg::MipsCore(static_cast<int>(reg));
   4618 }
   4619 
   4620 constexpr size_t kFramePointerSize = 4;
   4621 
   4622 void MipsAssembler::BuildFrame(size_t frame_size,
   4623                                ManagedRegister method_reg,
   4624                                ArrayRef<const ManagedRegister> callee_save_regs,
   4625                                const ManagedRegisterEntrySpills& entry_spills) {
   4626   CHECK_ALIGNED(frame_size, kStackAlignment);
   4627   DCHECK(!overwriting_);
   4628 
   4629   // Increase frame to required size.
   4630   IncreaseFrameSize(frame_size);
   4631 
   4632   // Push callee saves and return address.
   4633   int stack_offset = frame_size - kFramePointerSize;
   4634   StoreToOffset(kStoreWord, RA, SP, stack_offset);
   4635   cfi_.RelOffset(DWARFReg(RA), stack_offset);
   4636   for (int i = callee_save_regs.size() - 1; i >= 0; --i) {
   4637     stack_offset -= kFramePointerSize;
   4638     Register reg = callee_save_regs[i].AsMips().AsCoreRegister();
   4639     StoreToOffset(kStoreWord, reg, SP, stack_offset);
   4640     cfi_.RelOffset(DWARFReg(reg), stack_offset);
   4641   }
   4642 
   4643   // Write out Method*.
   4644   StoreToOffset(kStoreWord, method_reg.AsMips().AsCoreRegister(), SP, 0);
   4645 
   4646   // Write out entry spills.
   4647   int32_t offset = frame_size + kFramePointerSize;
   4648   for (size_t i = 0; i < entry_spills.size(); ++i) {
   4649     MipsManagedRegister reg = entry_spills.at(i).AsMips();
   4650     if (reg.IsNoRegister()) {
   4651       ManagedRegisterSpill spill = entry_spills.at(i);
   4652       offset += spill.getSize();
   4653     } else if (reg.IsCoreRegister()) {
   4654       StoreToOffset(kStoreWord, reg.AsCoreRegister(), SP, offset);
   4655       offset += kMipsWordSize;
   4656     } else if (reg.IsFRegister()) {
   4657       StoreSToOffset(reg.AsFRegister(), SP, offset);
   4658       offset += kMipsWordSize;
   4659     } else if (reg.IsDRegister()) {
   4660       StoreDToOffset(reg.AsOverlappingDRegisterLow(), SP, offset);
   4661       offset += kMipsDoublewordSize;
   4662     }
   4663   }
   4664 }
   4665 
   4666 void MipsAssembler::RemoveFrame(size_t frame_size,
   4667                                 ArrayRef<const ManagedRegister> callee_save_regs) {
   4668   CHECK_ALIGNED(frame_size, kStackAlignment);
   4669   DCHECK(!overwriting_);
   4670   cfi_.RememberState();
   4671 
   4672   // Pop callee saves and return address.
   4673   int stack_offset = frame_size - (callee_save_regs.size() * kFramePointerSize) - kFramePointerSize;
   4674   for (size_t i = 0; i < callee_save_regs.size(); ++i) {
   4675     Register reg = callee_save_regs[i].AsMips().AsCoreRegister();
   4676     LoadFromOffset(kLoadWord, reg, SP, stack_offset);
   4677     cfi_.Restore(DWARFReg(reg));
   4678     stack_offset += kFramePointerSize;
   4679   }
   4680   LoadFromOffset(kLoadWord, RA, SP, stack_offset);
   4681   cfi_.Restore(DWARFReg(RA));
   4682 
   4683   // Adjust the stack pointer in the delay slot if doing so doesn't break CFI.
   4684   bool exchange = IsInt<16>(static_cast<int32_t>(frame_size));
   4685   bool reordering = SetReorder(false);
   4686   if (exchange) {
   4687     // Jump to the return address.
   4688     Jr(RA);
   4689     // Decrease frame to required size.
   4690     DecreaseFrameSize(frame_size);  // Single instruction in delay slot.
   4691   } else {
   4692     // Decrease frame to required size.
   4693     DecreaseFrameSize(frame_size);
   4694     // Jump to the return address.
   4695     Jr(RA);
   4696     Nop();  // In delay slot.
   4697   }
   4698   SetReorder(reordering);
   4699 
   4700   // The CFI should be restored for any code that follows the exit block.
   4701   cfi_.RestoreState();
   4702   cfi_.DefCFAOffset(frame_size);
   4703 }
   4704 
   4705 void MipsAssembler::IncreaseFrameSize(size_t adjust) {
   4706   CHECK_ALIGNED(adjust, kFramePointerSize);
   4707   Addiu32(SP, SP, -adjust);
   4708   cfi_.AdjustCFAOffset(adjust);
   4709   if (overwriting_) {
   4710     cfi_.OverrideDelayedPC(overwrite_location_);
   4711   }
   4712 }
   4713 
   4714 void MipsAssembler::DecreaseFrameSize(size_t adjust) {
   4715   CHECK_ALIGNED(adjust, kFramePointerSize);
   4716   Addiu32(SP, SP, adjust);
   4717   cfi_.AdjustCFAOffset(-adjust);
   4718   if (overwriting_) {
   4719     cfi_.OverrideDelayedPC(overwrite_location_);
   4720   }
   4721 }
   4722 
   4723 void MipsAssembler::Store(FrameOffset dest, ManagedRegister msrc, size_t size) {
   4724   MipsManagedRegister src = msrc.AsMips();
   4725   if (src.IsNoRegister()) {
   4726     CHECK_EQ(0u, size);
   4727   } else if (src.IsCoreRegister()) {
   4728     CHECK_EQ(kMipsWordSize, size);
   4729     StoreToOffset(kStoreWord, src.AsCoreRegister(), SP, dest.Int32Value());
   4730   } else if (src.IsRegisterPair()) {
   4731     CHECK_EQ(kMipsDoublewordSize, size);
   4732     StoreToOffset(kStoreWord, src.AsRegisterPairLow(), SP, dest.Int32Value());
   4733     StoreToOffset(kStoreWord, src.AsRegisterPairHigh(),
   4734                   SP, dest.Int32Value() + kMipsWordSize);
   4735   } else if (src.IsFRegister()) {
   4736     if (size == kMipsWordSize) {
   4737       StoreSToOffset(src.AsFRegister(), SP, dest.Int32Value());
   4738     } else {
   4739       CHECK_EQ(kMipsDoublewordSize, size);
   4740       StoreDToOffset(src.AsFRegister(), SP, dest.Int32Value());
   4741     }
   4742   } else if (src.IsDRegister()) {
   4743     CHECK_EQ(kMipsDoublewordSize, size);
   4744     StoreDToOffset(src.AsOverlappingDRegisterLow(), SP, dest.Int32Value());
   4745   }
   4746 }
   4747 
   4748 void MipsAssembler::StoreRef(FrameOffset dest, ManagedRegister msrc) {
   4749   MipsManagedRegister src = msrc.AsMips();
   4750   CHECK(src.IsCoreRegister());
   4751   StoreToOffset(kStoreWord, src.AsCoreRegister(), SP, dest.Int32Value());
   4752 }
   4753 
   4754 void MipsAssembler::StoreRawPtr(FrameOffset dest, ManagedRegister msrc) {
   4755   MipsManagedRegister src = msrc.AsMips();
   4756   CHECK(src.IsCoreRegister());
   4757   StoreToOffset(kStoreWord, src.AsCoreRegister(), SP, dest.Int32Value());
   4758 }
   4759 
   4760 void MipsAssembler::StoreImmediateToFrame(FrameOffset dest, uint32_t imm,
   4761                                           ManagedRegister mscratch) {
   4762   MipsManagedRegister scratch = mscratch.AsMips();
   4763   CHECK(scratch.IsCoreRegister()) << scratch;
   4764   LoadConst32(scratch.AsCoreRegister(), imm);
   4765   StoreToOffset(kStoreWord, scratch.AsCoreRegister(), SP, dest.Int32Value());
   4766 }
   4767 
   4768 void MipsAssembler::StoreStackOffsetToThread(ThreadOffset32 thr_offs,
   4769                                              FrameOffset fr_offs,
   4770                                              ManagedRegister mscratch) {
   4771   MipsManagedRegister scratch = mscratch.AsMips();
   4772   CHECK(scratch.IsCoreRegister()) << scratch;
   4773   Addiu32(scratch.AsCoreRegister(), SP, fr_offs.Int32Value());
   4774   StoreToOffset(kStoreWord, scratch.AsCoreRegister(),
   4775                 S1, thr_offs.Int32Value());
   4776 }
   4777 
   4778 void MipsAssembler::StoreStackPointerToThread(ThreadOffset32 thr_offs) {
   4779   StoreToOffset(kStoreWord, SP, S1, thr_offs.Int32Value());
   4780 }
   4781 
   4782 void MipsAssembler::StoreSpanning(FrameOffset dest, ManagedRegister msrc,
   4783                                   FrameOffset in_off, ManagedRegister mscratch) {
   4784   MipsManagedRegister src = msrc.AsMips();
   4785   MipsManagedRegister scratch = mscratch.AsMips();
   4786   StoreToOffset(kStoreWord, src.AsCoreRegister(), SP, dest.Int32Value());
   4787   LoadFromOffset(kLoadWord, scratch.AsCoreRegister(), SP, in_off.Int32Value());
   4788   StoreToOffset(kStoreWord, scratch.AsCoreRegister(), SP, dest.Int32Value() + kMipsWordSize);
   4789 }
   4790 
   4791 void MipsAssembler::Load(ManagedRegister mdest, FrameOffset src, size_t size) {
   4792   return EmitLoad(mdest, SP, src.Int32Value(), size);
   4793 }
   4794 
   4795 void MipsAssembler::LoadFromThread(ManagedRegister mdest, ThreadOffset32 src, size_t size) {
   4796   return EmitLoad(mdest, S1, src.Int32Value(), size);
   4797 }
   4798 
   4799 void MipsAssembler::LoadRef(ManagedRegister mdest, FrameOffset src) {
   4800   MipsManagedRegister dest = mdest.AsMips();
   4801   CHECK(dest.IsCoreRegister());
   4802   LoadFromOffset(kLoadWord, dest.AsCoreRegister(), SP, src.Int32Value());
   4803 }
   4804 
   4805 void MipsAssembler::LoadRef(ManagedRegister mdest, ManagedRegister base, MemberOffset offs,
   4806                             bool unpoison_reference) {
   4807   MipsManagedRegister dest = mdest.AsMips();
   4808   CHECK(dest.IsCoreRegister() && base.AsMips().IsCoreRegister());
   4809   LoadFromOffset(kLoadWord, dest.AsCoreRegister(),
   4810                  base.AsMips().AsCoreRegister(), offs.Int32Value());
   4811   if (unpoison_reference) {
   4812     MaybeUnpoisonHeapReference(dest.AsCoreRegister());
   4813   }
   4814 }
   4815 
   4816 void MipsAssembler::LoadRawPtr(ManagedRegister mdest, ManagedRegister base, Offset offs) {
   4817   MipsManagedRegister dest = mdest.AsMips();
   4818   CHECK(dest.IsCoreRegister() && base.AsMips().IsCoreRegister());
   4819   LoadFromOffset(kLoadWord, dest.AsCoreRegister(),
   4820                  base.AsMips().AsCoreRegister(), offs.Int32Value());
   4821 }
   4822 
   4823 void MipsAssembler::LoadRawPtrFromThread(ManagedRegister mdest, ThreadOffset32 offs) {
   4824   MipsManagedRegister dest = mdest.AsMips();
   4825   CHECK(dest.IsCoreRegister());
   4826   LoadFromOffset(kLoadWord, dest.AsCoreRegister(), S1, offs.Int32Value());
   4827 }
   4828 
   4829 void MipsAssembler::SignExtend(ManagedRegister /*mreg*/, size_t /*size*/) {
   4830   UNIMPLEMENTED(FATAL) << "no sign extension necessary for mips";
   4831 }
   4832 
   4833 void MipsAssembler::ZeroExtend(ManagedRegister /*mreg*/, size_t /*size*/) {
   4834   UNIMPLEMENTED(FATAL) << "no zero extension necessary for mips";
   4835 }
   4836 
   4837 void MipsAssembler::Move(ManagedRegister mdest, ManagedRegister msrc, size_t size) {
   4838   MipsManagedRegister dest = mdest.AsMips();
   4839   MipsManagedRegister src = msrc.AsMips();
   4840   if (!dest.Equals(src)) {
   4841     if (dest.IsCoreRegister()) {
   4842       CHECK(src.IsCoreRegister()) << src;
   4843       Move(dest.AsCoreRegister(), src.AsCoreRegister());
   4844     } else if (dest.IsFRegister()) {
   4845       CHECK(src.IsFRegister()) << src;
   4846       if (size == kMipsWordSize) {
   4847         MovS(dest.AsFRegister(), src.AsFRegister());
   4848       } else {
   4849         CHECK_EQ(kMipsDoublewordSize, size);
   4850         MovD(dest.AsFRegister(), src.AsFRegister());
   4851       }
   4852     } else if (dest.IsDRegister()) {
   4853       CHECK(src.IsDRegister()) << src;
   4854       MovD(dest.AsOverlappingDRegisterLow(), src.AsOverlappingDRegisterLow());
   4855     } else {
   4856       CHECK(dest.IsRegisterPair()) << dest;
   4857       CHECK(src.IsRegisterPair()) << src;
   4858       // Ensure that the first move doesn't clobber the input of the second.
   4859       if (src.AsRegisterPairHigh() != dest.AsRegisterPairLow()) {
   4860         Move(dest.AsRegisterPairLow(), src.AsRegisterPairLow());
   4861         Move(dest.AsRegisterPairHigh(), src.AsRegisterPairHigh());
   4862       } else {
   4863         Move(dest.AsRegisterPairHigh(), src.AsRegisterPairHigh());
   4864         Move(dest.AsRegisterPairLow(), src.AsRegisterPairLow());
   4865       }
   4866     }
   4867   }
   4868 }
   4869 
   4870 void MipsAssembler::CopyRef(FrameOffset dest, FrameOffset src, ManagedRegister mscratch) {
   4871   MipsManagedRegister scratch = mscratch.AsMips();
   4872   CHECK(scratch.IsCoreRegister()) << scratch;
   4873   LoadFromOffset(kLoadWord, scratch.AsCoreRegister(), SP, src.Int32Value());
   4874   StoreToOffset(kStoreWord, scratch.AsCoreRegister(), SP, dest.Int32Value());
   4875 }
   4876 
   4877 void MipsAssembler::CopyRawPtrFromThread(FrameOffset fr_offs,
   4878                                          ThreadOffset32 thr_offs,
   4879                                          ManagedRegister mscratch) {
   4880   MipsManagedRegister scratch = mscratch.AsMips();
   4881   CHECK(scratch.IsCoreRegister()) << scratch;
   4882   LoadFromOffset(kLoadWord, scratch.AsCoreRegister(),
   4883                  S1, thr_offs.Int32Value());
   4884   StoreToOffset(kStoreWord, scratch.AsCoreRegister(),
   4885                 SP, fr_offs.Int32Value());
   4886 }
   4887 
   4888 void MipsAssembler::CopyRawPtrToThread(ThreadOffset32 thr_offs,
   4889                                        FrameOffset fr_offs,
   4890                                        ManagedRegister mscratch) {
   4891   MipsManagedRegister scratch = mscratch.AsMips();
   4892   CHECK(scratch.IsCoreRegister()) << scratch;
   4893   LoadFromOffset(kLoadWord, scratch.AsCoreRegister(),
   4894                  SP, fr_offs.Int32Value());
   4895   StoreToOffset(kStoreWord, scratch.AsCoreRegister(),
   4896                 S1, thr_offs.Int32Value());
   4897 }
   4898 
   4899 void MipsAssembler::Copy(FrameOffset dest, FrameOffset src, ManagedRegister mscratch, size_t size) {
   4900   MipsManagedRegister scratch = mscratch.AsMips();
   4901   CHECK(scratch.IsCoreRegister()) << scratch;
   4902   CHECK(size == kMipsWordSize || size == kMipsDoublewordSize) << size;
   4903   if (size == kMipsWordSize) {
   4904     LoadFromOffset(kLoadWord, scratch.AsCoreRegister(), SP, src.Int32Value());
   4905     StoreToOffset(kStoreWord, scratch.AsCoreRegister(), SP, dest.Int32Value());
   4906   } else if (size == kMipsDoublewordSize) {
   4907     LoadFromOffset(kLoadWord, scratch.AsCoreRegister(), SP, src.Int32Value());
   4908     StoreToOffset(kStoreWord, scratch.AsCoreRegister(), SP, dest.Int32Value());
   4909     LoadFromOffset(kLoadWord, scratch.AsCoreRegister(), SP, src.Int32Value() + kMipsWordSize);
   4910     StoreToOffset(kStoreWord, scratch.AsCoreRegister(), SP, dest.Int32Value() + kMipsWordSize);
   4911   }
   4912 }
   4913 
   4914 void MipsAssembler::Copy(FrameOffset dest, ManagedRegister src_base, Offset src_offset,
   4915                          ManagedRegister mscratch, size_t size) {
   4916   Register scratch = mscratch.AsMips().AsCoreRegister();
   4917   CHECK_EQ(size, kMipsWordSize);
   4918   LoadFromOffset(kLoadWord, scratch, src_base.AsMips().AsCoreRegister(), src_offset.Int32Value());
   4919   StoreToOffset(kStoreWord, scratch, SP, dest.Int32Value());
   4920 }
   4921 
   4922 void MipsAssembler::Copy(ManagedRegister dest_base, Offset dest_offset, FrameOffset src,
   4923                          ManagedRegister mscratch, size_t size) {
   4924   Register scratch = mscratch.AsMips().AsCoreRegister();
   4925   CHECK_EQ(size, kMipsWordSize);
   4926   LoadFromOffset(kLoadWord, scratch, SP, src.Int32Value());
   4927   StoreToOffset(kStoreWord, scratch, dest_base.AsMips().AsCoreRegister(), dest_offset.Int32Value());
   4928 }
   4929 
   4930 void MipsAssembler::Copy(FrameOffset dest ATTRIBUTE_UNUSED,
   4931                          FrameOffset src_base ATTRIBUTE_UNUSED,
   4932                          Offset src_offset ATTRIBUTE_UNUSED,
   4933                          ManagedRegister mscratch ATTRIBUTE_UNUSED,
   4934                          size_t size ATTRIBUTE_UNUSED) {
   4935   UNIMPLEMENTED(FATAL) << "no MIPS implementation";
   4936 }
   4937 
   4938 void MipsAssembler::Copy(ManagedRegister dest, Offset dest_offset,
   4939                          ManagedRegister src, Offset src_offset,
   4940                          ManagedRegister mscratch, size_t size) {
   4941   CHECK_EQ(size, kMipsWordSize);
   4942   Register scratch = mscratch.AsMips().AsCoreRegister();
   4943   LoadFromOffset(kLoadWord, scratch, src.AsMips().AsCoreRegister(), src_offset.Int32Value());
   4944   StoreToOffset(kStoreWord, scratch, dest.AsMips().AsCoreRegister(), dest_offset.Int32Value());
   4945 }
   4946 
   4947 void MipsAssembler::Copy(FrameOffset dest ATTRIBUTE_UNUSED,
   4948                          Offset dest_offset ATTRIBUTE_UNUSED,
   4949                          FrameOffset src ATTRIBUTE_UNUSED,
   4950                          Offset src_offset ATTRIBUTE_UNUSED,
   4951                          ManagedRegister mscratch ATTRIBUTE_UNUSED,
   4952                          size_t size ATTRIBUTE_UNUSED) {
   4953   UNIMPLEMENTED(FATAL) << "no MIPS implementation";
   4954 }
   4955 
   4956 void MipsAssembler::MemoryBarrier(ManagedRegister) {
   4957   // TODO: sync?
   4958   UNIMPLEMENTED(FATAL) << "no MIPS implementation";
   4959 }
   4960 
   4961 void MipsAssembler::CreateHandleScopeEntry(ManagedRegister mout_reg,
   4962                                            FrameOffset handle_scope_offset,
   4963                                            ManagedRegister min_reg,
   4964                                            bool null_allowed) {
   4965   MipsManagedRegister out_reg = mout_reg.AsMips();
   4966   MipsManagedRegister in_reg = min_reg.AsMips();
   4967   CHECK(in_reg.IsNoRegister() || in_reg.IsCoreRegister()) << in_reg;
   4968   CHECK(out_reg.IsCoreRegister()) << out_reg;
   4969   if (null_allowed) {
   4970     MipsLabel null_arg;
   4971     // Null values get a handle scope entry value of 0.  Otherwise, the handle scope entry is
   4972     // the address in the handle scope holding the reference.
   4973     // E.g. out_reg = (handle == 0) ? 0 : (SP+handle_offset).
   4974     if (in_reg.IsNoRegister()) {
   4975       LoadFromOffset(kLoadWord, out_reg.AsCoreRegister(),
   4976                      SP, handle_scope_offset.Int32Value());
   4977       in_reg = out_reg;
   4978     }
   4979     if (!out_reg.Equals(in_reg)) {
   4980       LoadConst32(out_reg.AsCoreRegister(), 0);
   4981     }
   4982     Beqz(in_reg.AsCoreRegister(), &null_arg);
   4983     Addiu32(out_reg.AsCoreRegister(), SP, handle_scope_offset.Int32Value());
   4984     Bind(&null_arg);
   4985   } else {
   4986     Addiu32(out_reg.AsCoreRegister(), SP, handle_scope_offset.Int32Value());
   4987   }
   4988 }
   4989 
   4990 void MipsAssembler::CreateHandleScopeEntry(FrameOffset out_off,
   4991                                            FrameOffset handle_scope_offset,
   4992                                            ManagedRegister mscratch,
   4993                                            bool null_allowed) {
   4994   MipsManagedRegister scratch = mscratch.AsMips();
   4995   CHECK(scratch.IsCoreRegister()) << scratch;
   4996   if (null_allowed) {
   4997     MipsLabel null_arg;
   4998     LoadFromOffset(kLoadWord, scratch.AsCoreRegister(), SP, handle_scope_offset.Int32Value());
   4999     // Null values get a handle scope entry value of 0.  Otherwise, the handle scope entry is
   5000     // the address in the handle scope holding the reference.
   5001     // E.g. scratch = (scratch == 0) ? 0 : (SP+handle_scope_offset).
   5002     Beqz(scratch.AsCoreRegister(), &null_arg);
   5003     Addiu32(scratch.AsCoreRegister(), SP, handle_scope_offset.Int32Value());
   5004     Bind(&null_arg);
   5005   } else {
   5006     Addiu32(scratch.AsCoreRegister(), SP, handle_scope_offset.Int32Value());
   5007   }
   5008   StoreToOffset(kStoreWord, scratch.AsCoreRegister(), SP, out_off.Int32Value());
   5009 }
   5010 
   5011 // Given a handle scope entry, load the associated reference.
   5012 void MipsAssembler::LoadReferenceFromHandleScope(ManagedRegister mout_reg,
   5013                                                  ManagedRegister min_reg) {
   5014   MipsManagedRegister out_reg = mout_reg.AsMips();
   5015   MipsManagedRegister in_reg = min_reg.AsMips();
   5016   CHECK(out_reg.IsCoreRegister()) << out_reg;
   5017   CHECK(in_reg.IsCoreRegister()) << in_reg;
   5018   MipsLabel null_arg;
   5019   if (!out_reg.Equals(in_reg)) {
   5020     LoadConst32(out_reg.AsCoreRegister(), 0);
   5021   }
   5022   Beqz(in_reg.AsCoreRegister(), &null_arg);
   5023   LoadFromOffset(kLoadWord, out_reg.AsCoreRegister(),
   5024                  in_reg.AsCoreRegister(), 0);
   5025   Bind(&null_arg);
   5026 }
   5027 
   5028 void MipsAssembler::VerifyObject(ManagedRegister src ATTRIBUTE_UNUSED,
   5029                                  bool could_be_null ATTRIBUTE_UNUSED) {
   5030   // TODO: not validating references.
   5031 }
   5032 
   5033 void MipsAssembler::VerifyObject(FrameOffset src ATTRIBUTE_UNUSED,
   5034                                  bool could_be_null ATTRIBUTE_UNUSED) {
   5035   // TODO: not validating references.
   5036 }
   5037 
   5038 void MipsAssembler::Call(ManagedRegister mbase, Offset offset, ManagedRegister mscratch) {
   5039   MipsManagedRegister base = mbase.AsMips();
   5040   MipsManagedRegister scratch = mscratch.AsMips();
   5041   CHECK(base.IsCoreRegister()) << base;
   5042   CHECK(scratch.IsCoreRegister()) << scratch;
   5043   LoadFromOffset(kLoadWord, scratch.AsCoreRegister(),
   5044                  base.AsCoreRegister(), offset.Int32Value());
   5045   Jalr(scratch.AsCoreRegister());
   5046   NopIfNoReordering();
   5047   // TODO: place reference map on call.
   5048 }
   5049 
   5050 void MipsAssembler::Call(FrameOffset base, Offset offset, ManagedRegister mscratch) {
   5051   MipsManagedRegister scratch = mscratch.AsMips();
   5052   CHECK(scratch.IsCoreRegister()) << scratch;
   5053   // Call *(*(SP + base) + offset)
   5054   LoadFromOffset(kLoadWord, scratch.AsCoreRegister(), SP, base.Int32Value());
   5055   LoadFromOffset(kLoadWord, scratch.AsCoreRegister(),
   5056                  scratch.AsCoreRegister(), offset.Int32Value());
   5057   Jalr(scratch.AsCoreRegister());
   5058   NopIfNoReordering();
   5059   // TODO: place reference map on call.
   5060 }
   5061 
   5062 void MipsAssembler::CallFromThread(ThreadOffset32 offset ATTRIBUTE_UNUSED,
   5063                                    ManagedRegister mscratch ATTRIBUTE_UNUSED) {
   5064   UNIMPLEMENTED(FATAL) << "no mips implementation";
   5065 }
   5066 
   5067 void MipsAssembler::GetCurrentThread(ManagedRegister tr) {
   5068   Move(tr.AsMips().AsCoreRegister(), S1);
   5069 }
   5070 
   5071 void MipsAssembler::GetCurrentThread(FrameOffset offset,
   5072                                      ManagedRegister mscratch ATTRIBUTE_UNUSED) {
   5073   StoreToOffset(kStoreWord, S1, SP, offset.Int32Value());
   5074 }
   5075 
   5076 void MipsAssembler::ExceptionPoll(ManagedRegister mscratch, size_t stack_adjust) {
   5077   MipsManagedRegister scratch = mscratch.AsMips();
   5078   exception_blocks_.emplace_back(scratch, stack_adjust);
   5079   LoadFromOffset(kLoadWord, scratch.AsCoreRegister(),
   5080                  S1, Thread::ExceptionOffset<kMipsPointerSize>().Int32Value());
   5081   Bnez(scratch.AsCoreRegister(), exception_blocks_.back().Entry());
   5082 }
   5083 
   5084 void MipsAssembler::EmitExceptionPoll(MipsExceptionSlowPath* exception) {
   5085   Bind(exception->Entry());
   5086   if (exception->stack_adjust_ != 0) {  // Fix up the frame.
   5087     DecreaseFrameSize(exception->stack_adjust_);
   5088   }
   5089   // Pass exception object as argument.
   5090   // Don't care about preserving A0 as this call won't return.
   5091   CheckEntrypointTypes<kQuickDeliverException, void, mirror::Object*>();
   5092   Move(A0, exception->scratch_.AsCoreRegister());
   5093   // Set up call to Thread::Current()->pDeliverException.
   5094   LoadFromOffset(kLoadWord, T9, S1,
   5095     QUICK_ENTRYPOINT_OFFSET(kMipsPointerSize, pDeliverException).Int32Value());
   5096   Jr(T9);
   5097   NopIfNoReordering();
   5098 
   5099   // Call never returns.
   5100   Break();
   5101 }
   5102 
   5103 }  // namespace mips
   5104 }  // namespace art
   5105