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 std::ostream& operator<<(std::ostream& os, const DRegister& rhs) {
     30   if (rhs >= D0 && rhs < kNumberOfDRegisters) {
     31     os << "d" << static_cast<int>(rhs);
     32   } else {
     33     os << "DRegister[" << static_cast<int>(rhs) << "]";
     34   }
     35   return os;
     36 }
     37 
     38 void MipsAssembler::FinalizeCode() {
     39   for (auto& exception_block : exception_blocks_) {
     40     EmitExceptionPoll(&exception_block);
     41   }
     42   PromoteBranches();
     43 }
     44 
     45 void MipsAssembler::FinalizeInstructions(const MemoryRegion& region) {
     46   size_t number_of_delayed_adjust_pcs = cfi().NumberOfDelayedAdvancePCs();
     47   EmitBranches();
     48   Assembler::FinalizeInstructions(region);
     49   PatchCFI(number_of_delayed_adjust_pcs);
     50 }
     51 
     52 void MipsAssembler::PatchCFI(size_t number_of_delayed_adjust_pcs) {
     53   if (cfi().NumberOfDelayedAdvancePCs() == 0u) {
     54     DCHECK_EQ(number_of_delayed_adjust_pcs, 0u);
     55     return;
     56   }
     57 
     58   typedef DebugFrameOpCodeWriterForAssembler::DelayedAdvancePC DelayedAdvancePC;
     59   const auto data = cfi().ReleaseStreamAndPrepareForDelayedAdvancePC();
     60   const std::vector<uint8_t>& old_stream = data.first;
     61   const std::vector<DelayedAdvancePC>& advances = data.second;
     62 
     63   // PCs recorded before EmitBranches() need to be adjusted.
     64   // PCs recorded during EmitBranches() are already adjusted.
     65   // Both ranges are separately sorted but they may overlap.
     66   if (kIsDebugBuild) {
     67     auto cmp = [](const DelayedAdvancePC& lhs, const DelayedAdvancePC& rhs) {
     68       return lhs.pc < rhs.pc;
     69     };
     70     CHECK(std::is_sorted(advances.begin(), advances.begin() + number_of_delayed_adjust_pcs, cmp));
     71     CHECK(std::is_sorted(advances.begin() + number_of_delayed_adjust_pcs, advances.end(), cmp));
     72   }
     73 
     74   // Append initial CFI data if any.
     75   size_t size = advances.size();
     76   DCHECK_NE(size, 0u);
     77   cfi().AppendRawData(old_stream, 0u, advances[0].stream_pos);
     78   // Emit PC adjustments interleaved with the old CFI stream.
     79   size_t adjust_pos = 0u;
     80   size_t late_emit_pos = number_of_delayed_adjust_pcs;
     81   while (adjust_pos != number_of_delayed_adjust_pcs || late_emit_pos != size) {
     82     size_t adjusted_pc = (adjust_pos != number_of_delayed_adjust_pcs)
     83         ? GetAdjustedPosition(advances[adjust_pos].pc)
     84         : static_cast<size_t>(-1);
     85     size_t late_emit_pc = (late_emit_pos != size)
     86         ? advances[late_emit_pos].pc
     87         : static_cast<size_t>(-1);
     88     size_t advance_pc = std::min(adjusted_pc, late_emit_pc);
     89     DCHECK_NE(advance_pc, static_cast<size_t>(-1));
     90     size_t entry = (adjusted_pc <= late_emit_pc) ? adjust_pos : late_emit_pos;
     91     if (adjusted_pc <= late_emit_pc) {
     92       ++adjust_pos;
     93     } else {
     94       ++late_emit_pos;
     95     }
     96     cfi().AdvancePC(advance_pc);
     97     size_t end_pos = (entry + 1u == size) ? old_stream.size() : advances[entry + 1u].stream_pos;
     98     cfi().AppendRawData(old_stream, advances[entry].stream_pos, end_pos);
     99   }
    100 }
    101 
    102 void MipsAssembler::EmitBranches() {
    103   CHECK(!overwriting_);
    104   // Switch from appending instructions at the end of the buffer to overwriting
    105   // existing instructions (branch placeholders) in the buffer.
    106   overwriting_ = true;
    107   for (auto& branch : branches_) {
    108     EmitBranch(&branch);
    109   }
    110   overwriting_ = false;
    111 }
    112 
    113 void MipsAssembler::Emit(uint32_t value) {
    114   if (overwriting_) {
    115     // Branches to labels are emitted into their placeholders here.
    116     buffer_.Store<uint32_t>(overwrite_location_, value);
    117     overwrite_location_ += sizeof(uint32_t);
    118   } else {
    119     // Other instructions are simply appended at the end here.
    120     AssemblerBuffer::EnsureCapacity ensured(&buffer_);
    121     buffer_.Emit<uint32_t>(value);
    122   }
    123 }
    124 
    125 void MipsAssembler::EmitR(int opcode, Register rs, Register rt, Register rd, int shamt, int funct) {
    126   CHECK_NE(rs, kNoRegister);
    127   CHECK_NE(rt, kNoRegister);
    128   CHECK_NE(rd, kNoRegister);
    129   uint32_t encoding = static_cast<uint32_t>(opcode) << kOpcodeShift |
    130                       static_cast<uint32_t>(rs) << kRsShift |
    131                       static_cast<uint32_t>(rt) << kRtShift |
    132                       static_cast<uint32_t>(rd) << kRdShift |
    133                       shamt << kShamtShift |
    134                       funct;
    135   Emit(encoding);
    136 }
    137 
    138 void MipsAssembler::EmitI(int opcode, Register rs, Register rt, uint16_t imm) {
    139   CHECK_NE(rs, kNoRegister);
    140   CHECK_NE(rt, kNoRegister);
    141   uint32_t encoding = static_cast<uint32_t>(opcode) << kOpcodeShift |
    142                       static_cast<uint32_t>(rs) << kRsShift |
    143                       static_cast<uint32_t>(rt) << kRtShift |
    144                       imm;
    145   Emit(encoding);
    146 }
    147 
    148 void MipsAssembler::EmitI21(int opcode, Register rs, uint32_t imm21) {
    149   CHECK_NE(rs, kNoRegister);
    150   CHECK(IsUint<21>(imm21)) << imm21;
    151   uint32_t encoding = static_cast<uint32_t>(opcode) << kOpcodeShift |
    152                       static_cast<uint32_t>(rs) << kRsShift |
    153                       imm21;
    154   Emit(encoding);
    155 }
    156 
    157 void MipsAssembler::EmitI26(int opcode, uint32_t imm26) {
    158   CHECK(IsUint<26>(imm26)) << imm26;
    159   uint32_t encoding = static_cast<uint32_t>(opcode) << kOpcodeShift | imm26;
    160   Emit(encoding);
    161 }
    162 
    163 void MipsAssembler::EmitFR(int opcode, int fmt, FRegister ft, FRegister fs, FRegister fd,
    164                            int funct) {
    165   CHECK_NE(ft, kNoFRegister);
    166   CHECK_NE(fs, kNoFRegister);
    167   CHECK_NE(fd, kNoFRegister);
    168   uint32_t encoding = static_cast<uint32_t>(opcode) << kOpcodeShift |
    169                       fmt << kFmtShift |
    170                       static_cast<uint32_t>(ft) << kFtShift |
    171                       static_cast<uint32_t>(fs) << kFsShift |
    172                       static_cast<uint32_t>(fd) << kFdShift |
    173                       funct;
    174   Emit(encoding);
    175 }
    176 
    177 void MipsAssembler::EmitFI(int opcode, int fmt, FRegister ft, uint16_t imm) {
    178   CHECK_NE(ft, kNoFRegister);
    179   uint32_t encoding = static_cast<uint32_t>(opcode) << kOpcodeShift |
    180                       fmt << kFmtShift |
    181                       static_cast<uint32_t>(ft) << kFtShift |
    182                       imm;
    183   Emit(encoding);
    184 }
    185 
    186 void MipsAssembler::Addu(Register rd, Register rs, Register rt) {
    187   EmitR(0, rs, rt, rd, 0, 0x21);
    188 }
    189 
    190 void MipsAssembler::Addiu(Register rt, Register rs, uint16_t imm16) {
    191   EmitI(0x9, rs, rt, imm16);
    192 }
    193 
    194 void MipsAssembler::Subu(Register rd, Register rs, Register rt) {
    195   EmitR(0, rs, rt, rd, 0, 0x23);
    196 }
    197 
    198 void MipsAssembler::MultR2(Register rs, Register rt) {
    199   CHECK(!IsR6());
    200   EmitR(0, rs, rt, static_cast<Register>(0), 0, 0x18);
    201 }
    202 
    203 void MipsAssembler::MultuR2(Register rs, Register rt) {
    204   CHECK(!IsR6());
    205   EmitR(0, rs, rt, static_cast<Register>(0), 0, 0x19);
    206 }
    207 
    208 void MipsAssembler::DivR2(Register rs, Register rt) {
    209   CHECK(!IsR6());
    210   EmitR(0, rs, rt, static_cast<Register>(0), 0, 0x1a);
    211 }
    212 
    213 void MipsAssembler::DivuR2(Register rs, Register rt) {
    214   CHECK(!IsR6());
    215   EmitR(0, rs, rt, static_cast<Register>(0), 0, 0x1b);
    216 }
    217 
    218 void MipsAssembler::MulR2(Register rd, Register rs, Register rt) {
    219   CHECK(!IsR6());
    220   EmitR(0x1c, rs, rt, rd, 0, 2);
    221 }
    222 
    223 void MipsAssembler::DivR2(Register rd, Register rs, Register rt) {
    224   CHECK(!IsR6());
    225   DivR2(rs, rt);
    226   Mflo(rd);
    227 }
    228 
    229 void MipsAssembler::ModR2(Register rd, Register rs, Register rt) {
    230   CHECK(!IsR6());
    231   DivR2(rs, rt);
    232   Mfhi(rd);
    233 }
    234 
    235 void MipsAssembler::DivuR2(Register rd, Register rs, Register rt) {
    236   CHECK(!IsR6());
    237   DivuR2(rs, rt);
    238   Mflo(rd);
    239 }
    240 
    241 void MipsAssembler::ModuR2(Register rd, Register rs, Register rt) {
    242   CHECK(!IsR6());
    243   DivuR2(rs, rt);
    244   Mfhi(rd);
    245 }
    246 
    247 void MipsAssembler::MulR6(Register rd, Register rs, Register rt) {
    248   CHECK(IsR6());
    249   EmitR(0, rs, rt, rd, 2, 0x18);
    250 }
    251 
    252 void MipsAssembler::MuhR6(Register rd, Register rs, Register rt) {
    253   CHECK(IsR6());
    254   EmitR(0, rs, rt, rd, 3, 0x18);
    255 }
    256 
    257 void MipsAssembler::MuhuR6(Register rd, Register rs, Register rt) {
    258   CHECK(IsR6());
    259   EmitR(0, rs, rt, rd, 3, 0x19);
    260 }
    261 
    262 void MipsAssembler::DivR6(Register rd, Register rs, Register rt) {
    263   CHECK(IsR6());
    264   EmitR(0, rs, rt, rd, 2, 0x1a);
    265 }
    266 
    267 void MipsAssembler::ModR6(Register rd, Register rs, Register rt) {
    268   CHECK(IsR6());
    269   EmitR(0, rs, rt, rd, 3, 0x1a);
    270 }
    271 
    272 void MipsAssembler::DivuR6(Register rd, Register rs, Register rt) {
    273   CHECK(IsR6());
    274   EmitR(0, rs, rt, rd, 2, 0x1b);
    275 }
    276 
    277 void MipsAssembler::ModuR6(Register rd, Register rs, Register rt) {
    278   CHECK(IsR6());
    279   EmitR(0, rs, rt, rd, 3, 0x1b);
    280 }
    281 
    282 void MipsAssembler::And(Register rd, Register rs, Register rt) {
    283   EmitR(0, rs, rt, rd, 0, 0x24);
    284 }
    285 
    286 void MipsAssembler::Andi(Register rt, Register rs, uint16_t imm16) {
    287   EmitI(0xc, rs, rt, imm16);
    288 }
    289 
    290 void MipsAssembler::Or(Register rd, Register rs, Register rt) {
    291   EmitR(0, rs, rt, rd, 0, 0x25);
    292 }
    293 
    294 void MipsAssembler::Ori(Register rt, Register rs, uint16_t imm16) {
    295   EmitI(0xd, rs, rt, imm16);
    296 }
    297 
    298 void MipsAssembler::Xor(Register rd, Register rs, Register rt) {
    299   EmitR(0, rs, rt, rd, 0, 0x26);
    300 }
    301 
    302 void MipsAssembler::Xori(Register rt, Register rs, uint16_t imm16) {
    303   EmitI(0xe, rs, rt, imm16);
    304 }
    305 
    306 void MipsAssembler::Nor(Register rd, Register rs, Register rt) {
    307   EmitR(0, rs, rt, rd, 0, 0x27);
    308 }
    309 
    310 void MipsAssembler::Movz(Register rd, Register rs, Register rt) {
    311   CHECK(!IsR6());
    312   EmitR(0, rs, rt, rd, 0, 0x0A);
    313 }
    314 
    315 void MipsAssembler::Movn(Register rd, Register rs, Register rt) {
    316   CHECK(!IsR6());
    317   EmitR(0, rs, rt, rd, 0, 0x0B);
    318 }
    319 
    320 void MipsAssembler::Seleqz(Register rd, Register rs, Register rt) {
    321   CHECK(IsR6());
    322   EmitR(0, rs, rt, rd, 0, 0x35);
    323 }
    324 
    325 void MipsAssembler::Selnez(Register rd, Register rs, Register rt) {
    326   CHECK(IsR6());
    327   EmitR(0, rs, rt, rd, 0, 0x37);
    328 }
    329 
    330 void MipsAssembler::ClzR6(Register rd, Register rs) {
    331   CHECK(IsR6());
    332   EmitR(0, rs, static_cast<Register>(0), rd, 0x01, 0x10);
    333 }
    334 
    335 void MipsAssembler::ClzR2(Register rd, Register rs) {
    336   CHECK(!IsR6());
    337   EmitR(0x1C, rs, rd, rd, 0, 0x20);
    338 }
    339 
    340 void MipsAssembler::CloR6(Register rd, Register rs) {
    341   CHECK(IsR6());
    342   EmitR(0, rs, static_cast<Register>(0), rd, 0x01, 0x11);
    343 }
    344 
    345 void MipsAssembler::CloR2(Register rd, Register rs) {
    346   CHECK(!IsR6());
    347   EmitR(0x1C, rs, rd, rd, 0, 0x21);
    348 }
    349 
    350 void MipsAssembler::Seb(Register rd, Register rt) {
    351   EmitR(0x1f, static_cast<Register>(0), rt, rd, 0x10, 0x20);
    352 }
    353 
    354 void MipsAssembler::Seh(Register rd, Register rt) {
    355   EmitR(0x1f, static_cast<Register>(0), rt, rd, 0x18, 0x20);
    356 }
    357 
    358 void MipsAssembler::Wsbh(Register rd, Register rt) {
    359   EmitR(0x1f, static_cast<Register>(0), rt, rd, 2, 0x20);
    360 }
    361 
    362 void MipsAssembler::Bitswap(Register rd, Register rt) {
    363   CHECK(IsR6());
    364   EmitR(0x1f, static_cast<Register>(0), rt, rd, 0x0, 0x20);
    365 }
    366 
    367 void MipsAssembler::Sll(Register rd, Register rt, int shamt) {
    368   CHECK(IsUint<5>(shamt)) << shamt;
    369   EmitR(0, static_cast<Register>(0), rt, rd, shamt, 0x00);
    370 }
    371 
    372 void MipsAssembler::Srl(Register rd, Register rt, int shamt) {
    373   CHECK(IsUint<5>(shamt)) << shamt;
    374   EmitR(0, static_cast<Register>(0), rt, rd, shamt, 0x02);
    375 }
    376 
    377 void MipsAssembler::Rotr(Register rd, Register rt, int shamt) {
    378   CHECK(IsUint<5>(shamt)) << shamt;
    379   EmitR(0, static_cast<Register>(1), rt, rd, shamt, 0x02);
    380 }
    381 
    382 void MipsAssembler::Sra(Register rd, Register rt, int shamt) {
    383   CHECK(IsUint<5>(shamt)) << shamt;
    384   EmitR(0, static_cast<Register>(0), rt, rd, shamt, 0x03);
    385 }
    386 
    387 void MipsAssembler::Sllv(Register rd, Register rt, Register rs) {
    388   EmitR(0, rs, rt, rd, 0, 0x04);
    389 }
    390 
    391 void MipsAssembler::Srlv(Register rd, Register rt, Register rs) {
    392   EmitR(0, rs, rt, rd, 0, 0x06);
    393 }
    394 
    395 void MipsAssembler::Rotrv(Register rd, Register rt, Register rs) {
    396   EmitR(0, rs, rt, rd, 1, 0x06);
    397 }
    398 
    399 void MipsAssembler::Srav(Register rd, Register rt, Register rs) {
    400   EmitR(0, rs, rt, rd, 0, 0x07);
    401 }
    402 
    403 void MipsAssembler::Ext(Register rd, Register rt, int pos, int size) {
    404   CHECK(IsUint<5>(pos)) << pos;
    405   CHECK(0 < size && size <= 32) << size;
    406   CHECK(0 < pos + size && pos + size <= 32) << pos << " + " << size;
    407   EmitR(0x1f, rt, rd, static_cast<Register>(size - 1), pos, 0x00);
    408 }
    409 
    410 void MipsAssembler::Ins(Register rd, Register rt, int pos, int size) {
    411   CHECK(IsUint<5>(pos)) << pos;
    412   CHECK(0 < size && size <= 32) << size;
    413   CHECK(0 < pos + size && pos + size <= 32) << pos << " + " << size;
    414   EmitR(0x1f, rt, rd, static_cast<Register>(pos + size - 1), pos, 0x04);
    415 }
    416 
    417 void MipsAssembler::Lb(Register rt, Register rs, uint16_t imm16) {
    418   EmitI(0x20, rs, rt, imm16);
    419 }
    420 
    421 void MipsAssembler::Lh(Register rt, Register rs, uint16_t imm16) {
    422   EmitI(0x21, rs, rt, imm16);
    423 }
    424 
    425 void MipsAssembler::Lw(Register rt, Register rs, uint16_t imm16) {
    426   EmitI(0x23, rs, rt, imm16);
    427 }
    428 
    429 void MipsAssembler::Lwl(Register rt, Register rs, uint16_t imm16) {
    430   CHECK(!IsR6());
    431   EmitI(0x22, rs, rt, imm16);
    432 }
    433 
    434 void MipsAssembler::Lwr(Register rt, Register rs, uint16_t imm16) {
    435   CHECK(!IsR6());
    436   EmitI(0x26, rs, rt, imm16);
    437 }
    438 
    439 void MipsAssembler::Lbu(Register rt, Register rs, uint16_t imm16) {
    440   EmitI(0x24, rs, rt, imm16);
    441 }
    442 
    443 void MipsAssembler::Lhu(Register rt, Register rs, uint16_t imm16) {
    444   EmitI(0x25, rs, rt, imm16);
    445 }
    446 
    447 void MipsAssembler::Lui(Register rt, uint16_t imm16) {
    448   EmitI(0xf, static_cast<Register>(0), rt, imm16);
    449 }
    450 
    451 void MipsAssembler::Sync(uint32_t stype) {
    452   EmitR(0, static_cast<Register>(0), static_cast<Register>(0), static_cast<Register>(0),
    453         stype & 0x1f, 0xf);
    454 }
    455 
    456 void MipsAssembler::Mfhi(Register rd) {
    457   CHECK(!IsR6());
    458   EmitR(0, static_cast<Register>(0), static_cast<Register>(0), rd, 0, 0x10);
    459 }
    460 
    461 void MipsAssembler::Mflo(Register rd) {
    462   CHECK(!IsR6());
    463   EmitR(0, static_cast<Register>(0), static_cast<Register>(0), rd, 0, 0x12);
    464 }
    465 
    466 void MipsAssembler::Sb(Register rt, Register rs, uint16_t imm16) {
    467   EmitI(0x28, rs, rt, imm16);
    468 }
    469 
    470 void MipsAssembler::Sh(Register rt, Register rs, uint16_t imm16) {
    471   EmitI(0x29, rs, rt, imm16);
    472 }
    473 
    474 void MipsAssembler::Sw(Register rt, Register rs, uint16_t imm16) {
    475   EmitI(0x2b, rs, rt, imm16);
    476 }
    477 
    478 void MipsAssembler::Swl(Register rt, Register rs, uint16_t imm16) {
    479   CHECK(!IsR6());
    480   EmitI(0x2a, rs, rt, imm16);
    481 }
    482 
    483 void MipsAssembler::Swr(Register rt, Register rs, uint16_t imm16) {
    484   CHECK(!IsR6());
    485   EmitI(0x2e, rs, rt, imm16);
    486 }
    487 
    488 void MipsAssembler::LlR2(Register rt, Register base, int16_t imm16) {
    489   CHECK(!IsR6());
    490   EmitI(0x30, base, rt, imm16);
    491 }
    492 
    493 void MipsAssembler::ScR2(Register rt, Register base, int16_t imm16) {
    494   CHECK(!IsR6());
    495   EmitI(0x38, base, rt, imm16);
    496 }
    497 
    498 void MipsAssembler::LlR6(Register rt, Register base, int16_t imm9) {
    499   CHECK(IsR6());
    500   CHECK(IsInt<9>(imm9));
    501   EmitI(0x1f, base, rt, ((imm9 & 0x1ff) << 7) | 0x36);
    502 }
    503 
    504 void MipsAssembler::ScR6(Register rt, Register base, int16_t imm9) {
    505   CHECK(IsR6());
    506   CHECK(IsInt<9>(imm9));
    507   EmitI(0x1f, base, rt, ((imm9 & 0x1ff) << 7) | 0x26);
    508 }
    509 
    510 void MipsAssembler::Slt(Register rd, Register rs, Register rt) {
    511   EmitR(0, rs, rt, rd, 0, 0x2a);
    512 }
    513 
    514 void MipsAssembler::Sltu(Register rd, Register rs, Register rt) {
    515   EmitR(0, rs, rt, rd, 0, 0x2b);
    516 }
    517 
    518 void MipsAssembler::Slti(Register rt, Register rs, uint16_t imm16) {
    519   EmitI(0xa, rs, rt, imm16);
    520 }
    521 
    522 void MipsAssembler::Sltiu(Register rt, Register rs, uint16_t imm16) {
    523   EmitI(0xb, rs, rt, imm16);
    524 }
    525 
    526 void MipsAssembler::B(uint16_t imm16) {
    527   EmitI(0x4, static_cast<Register>(0), static_cast<Register>(0), imm16);
    528 }
    529 
    530 void MipsAssembler::Beq(Register rs, Register rt, uint16_t imm16) {
    531   EmitI(0x4, rs, rt, imm16);
    532 }
    533 
    534 void MipsAssembler::Bne(Register rs, Register rt, uint16_t imm16) {
    535   EmitI(0x5, rs, rt, imm16);
    536 }
    537 
    538 void MipsAssembler::Beqz(Register rt, uint16_t imm16) {
    539   Beq(ZERO, rt, imm16);
    540 }
    541 
    542 void MipsAssembler::Bnez(Register rt, uint16_t imm16) {
    543   Bne(ZERO, rt, imm16);
    544 }
    545 
    546 void MipsAssembler::Bltz(Register rt, uint16_t imm16) {
    547   EmitI(0x1, rt, static_cast<Register>(0), imm16);
    548 }
    549 
    550 void MipsAssembler::Bgez(Register rt, uint16_t imm16) {
    551   EmitI(0x1, rt, static_cast<Register>(0x1), imm16);
    552 }
    553 
    554 void MipsAssembler::Blez(Register rt, uint16_t imm16) {
    555   EmitI(0x6, rt, static_cast<Register>(0), imm16);
    556 }
    557 
    558 void MipsAssembler::Bgtz(Register rt, uint16_t imm16) {
    559   EmitI(0x7, rt, static_cast<Register>(0), imm16);
    560 }
    561 
    562 void MipsAssembler::Bc1f(uint16_t imm16) {
    563   Bc1f(0, imm16);
    564 }
    565 
    566 void MipsAssembler::Bc1f(int cc, uint16_t imm16) {
    567   CHECK(!IsR6());
    568   CHECK(IsUint<3>(cc)) << cc;
    569   EmitI(0x11, static_cast<Register>(0x8), static_cast<Register>(cc << 2), imm16);
    570 }
    571 
    572 void MipsAssembler::Bc1t(uint16_t imm16) {
    573   Bc1t(0, imm16);
    574 }
    575 
    576 void MipsAssembler::Bc1t(int cc, uint16_t imm16) {
    577   CHECK(!IsR6());
    578   CHECK(IsUint<3>(cc)) << cc;
    579   EmitI(0x11, static_cast<Register>(0x8), static_cast<Register>((cc << 2) | 1), imm16);
    580 }
    581 
    582 void MipsAssembler::J(uint32_t addr26) {
    583   EmitI26(0x2, addr26);
    584 }
    585 
    586 void MipsAssembler::Jal(uint32_t addr26) {
    587   EmitI26(0x3, addr26);
    588 }
    589 
    590 void MipsAssembler::Jalr(Register rd, Register rs) {
    591   EmitR(0, rs, static_cast<Register>(0), rd, 0, 0x09);
    592 }
    593 
    594 void MipsAssembler::Jalr(Register rs) {
    595   Jalr(RA, rs);
    596 }
    597 
    598 void MipsAssembler::Jr(Register rs) {
    599   Jalr(ZERO, rs);
    600 }
    601 
    602 void MipsAssembler::Nal() {
    603   EmitI(0x1, static_cast<Register>(0), static_cast<Register>(0x10), 0);
    604 }
    605 
    606 void MipsAssembler::Auipc(Register rs, uint16_t imm16) {
    607   CHECK(IsR6());
    608   EmitI(0x3B, rs, static_cast<Register>(0x1E), imm16);
    609 }
    610 
    611 void MipsAssembler::Addiupc(Register rs, uint32_t imm19) {
    612   CHECK(IsR6());
    613   CHECK(IsUint<19>(imm19)) << imm19;
    614   EmitI21(0x3B, rs, imm19);
    615 }
    616 
    617 void MipsAssembler::Bc(uint32_t imm26) {
    618   CHECK(IsR6());
    619   EmitI26(0x32, imm26);
    620 }
    621 
    622 void MipsAssembler::Jic(Register rt, uint16_t imm16) {
    623   CHECK(IsR6());
    624   EmitI(0x36, static_cast<Register>(0), rt, imm16);
    625 }
    626 
    627 void MipsAssembler::Jialc(Register rt, uint16_t imm16) {
    628   CHECK(IsR6());
    629   EmitI(0x3E, static_cast<Register>(0), rt, imm16);
    630 }
    631 
    632 void MipsAssembler::Bltc(Register rs, Register rt, uint16_t imm16) {
    633   CHECK(IsR6());
    634   CHECK_NE(rs, ZERO);
    635   CHECK_NE(rt, ZERO);
    636   CHECK_NE(rs, rt);
    637   EmitI(0x17, rs, rt, imm16);
    638 }
    639 
    640 void MipsAssembler::Bltzc(Register rt, uint16_t imm16) {
    641   CHECK(IsR6());
    642   CHECK_NE(rt, ZERO);
    643   EmitI(0x17, rt, rt, imm16);
    644 }
    645 
    646 void MipsAssembler::Bgtzc(Register rt, uint16_t imm16) {
    647   CHECK(IsR6());
    648   CHECK_NE(rt, ZERO);
    649   EmitI(0x17, static_cast<Register>(0), rt, imm16);
    650 }
    651 
    652 void MipsAssembler::Bgec(Register rs, Register rt, uint16_t imm16) {
    653   CHECK(IsR6());
    654   CHECK_NE(rs, ZERO);
    655   CHECK_NE(rt, ZERO);
    656   CHECK_NE(rs, rt);
    657   EmitI(0x16, rs, rt, imm16);
    658 }
    659 
    660 void MipsAssembler::Bgezc(Register rt, uint16_t imm16) {
    661   CHECK(IsR6());
    662   CHECK_NE(rt, ZERO);
    663   EmitI(0x16, rt, rt, imm16);
    664 }
    665 
    666 void MipsAssembler::Blezc(Register rt, uint16_t imm16) {
    667   CHECK(IsR6());
    668   CHECK_NE(rt, ZERO);
    669   EmitI(0x16, static_cast<Register>(0), rt, imm16);
    670 }
    671 
    672 void MipsAssembler::Bltuc(Register rs, Register rt, uint16_t imm16) {
    673   CHECK(IsR6());
    674   CHECK_NE(rs, ZERO);
    675   CHECK_NE(rt, ZERO);
    676   CHECK_NE(rs, rt);
    677   EmitI(0x7, rs, rt, imm16);
    678 }
    679 
    680 void MipsAssembler::Bgeuc(Register rs, Register rt, uint16_t imm16) {
    681   CHECK(IsR6());
    682   CHECK_NE(rs, ZERO);
    683   CHECK_NE(rt, ZERO);
    684   CHECK_NE(rs, rt);
    685   EmitI(0x6, rs, rt, imm16);
    686 }
    687 
    688 void MipsAssembler::Beqc(Register rs, Register rt, uint16_t imm16) {
    689   CHECK(IsR6());
    690   CHECK_NE(rs, ZERO);
    691   CHECK_NE(rt, ZERO);
    692   CHECK_NE(rs, rt);
    693   EmitI(0x8, std::min(rs, rt), std::max(rs, rt), imm16);
    694 }
    695 
    696 void MipsAssembler::Bnec(Register rs, Register rt, uint16_t imm16) {
    697   CHECK(IsR6());
    698   CHECK_NE(rs, ZERO);
    699   CHECK_NE(rt, ZERO);
    700   CHECK_NE(rs, rt);
    701   EmitI(0x18, std::min(rs, rt), std::max(rs, rt), imm16);
    702 }
    703 
    704 void MipsAssembler::Beqzc(Register rs, uint32_t imm21) {
    705   CHECK(IsR6());
    706   CHECK_NE(rs, ZERO);
    707   EmitI21(0x36, rs, imm21);
    708 }
    709 
    710 void MipsAssembler::Bnezc(Register rs, uint32_t imm21) {
    711   CHECK(IsR6());
    712   CHECK_NE(rs, ZERO);
    713   EmitI21(0x3E, rs, imm21);
    714 }
    715 
    716 void MipsAssembler::Bc1eqz(FRegister ft, uint16_t imm16) {
    717   CHECK(IsR6());
    718   EmitFI(0x11, 0x9, ft, imm16);
    719 }
    720 
    721 void MipsAssembler::Bc1nez(FRegister ft, uint16_t imm16) {
    722   CHECK(IsR6());
    723   EmitFI(0x11, 0xD, ft, imm16);
    724 }
    725 
    726 void MipsAssembler::EmitBcondR2(BranchCondition cond, Register rs, Register rt, uint16_t imm16) {
    727   switch (cond) {
    728     case kCondLTZ:
    729       CHECK_EQ(rt, ZERO);
    730       Bltz(rs, imm16);
    731       break;
    732     case kCondGEZ:
    733       CHECK_EQ(rt, ZERO);
    734       Bgez(rs, imm16);
    735       break;
    736     case kCondLEZ:
    737       CHECK_EQ(rt, ZERO);
    738       Blez(rs, imm16);
    739       break;
    740     case kCondGTZ:
    741       CHECK_EQ(rt, ZERO);
    742       Bgtz(rs, imm16);
    743       break;
    744     case kCondEQ:
    745       Beq(rs, rt, imm16);
    746       break;
    747     case kCondNE:
    748       Bne(rs, rt, imm16);
    749       break;
    750     case kCondEQZ:
    751       CHECK_EQ(rt, ZERO);
    752       Beqz(rs, imm16);
    753       break;
    754     case kCondNEZ:
    755       CHECK_EQ(rt, ZERO);
    756       Bnez(rs, imm16);
    757       break;
    758     case kCondF:
    759       CHECK_EQ(rt, ZERO);
    760       Bc1f(static_cast<int>(rs), imm16);
    761       break;
    762     case kCondT:
    763       CHECK_EQ(rt, ZERO);
    764       Bc1t(static_cast<int>(rs), imm16);
    765       break;
    766     case kCondLT:
    767     case kCondGE:
    768     case kCondLE:
    769     case kCondGT:
    770     case kCondLTU:
    771     case kCondGEU:
    772     case kUncond:
    773       // We don't support synthetic R2 branches (preceded with slt[u]) at this level
    774       // (R2 doesn't have branches to compare 2 registers using <, <=, >=, >).
    775       LOG(FATAL) << "Unexpected branch condition " << cond;
    776       UNREACHABLE();
    777   }
    778 }
    779 
    780 void MipsAssembler::EmitBcondR6(BranchCondition cond, Register rs, Register rt, uint32_t imm16_21) {
    781   switch (cond) {
    782     case kCondLT:
    783       Bltc(rs, rt, imm16_21);
    784       break;
    785     case kCondGE:
    786       Bgec(rs, rt, imm16_21);
    787       break;
    788     case kCondLE:
    789       Bgec(rt, rs, imm16_21);
    790       break;
    791     case kCondGT:
    792       Bltc(rt, rs, imm16_21);
    793       break;
    794     case kCondLTZ:
    795       CHECK_EQ(rt, ZERO);
    796       Bltzc(rs, imm16_21);
    797       break;
    798     case kCondGEZ:
    799       CHECK_EQ(rt, ZERO);
    800       Bgezc(rs, imm16_21);
    801       break;
    802     case kCondLEZ:
    803       CHECK_EQ(rt, ZERO);
    804       Blezc(rs, imm16_21);
    805       break;
    806     case kCondGTZ:
    807       CHECK_EQ(rt, ZERO);
    808       Bgtzc(rs, imm16_21);
    809       break;
    810     case kCondEQ:
    811       Beqc(rs, rt, imm16_21);
    812       break;
    813     case kCondNE:
    814       Bnec(rs, rt, imm16_21);
    815       break;
    816     case kCondEQZ:
    817       CHECK_EQ(rt, ZERO);
    818       Beqzc(rs, imm16_21);
    819       break;
    820     case kCondNEZ:
    821       CHECK_EQ(rt, ZERO);
    822       Bnezc(rs, imm16_21);
    823       break;
    824     case kCondLTU:
    825       Bltuc(rs, rt, imm16_21);
    826       break;
    827     case kCondGEU:
    828       Bgeuc(rs, rt, imm16_21);
    829       break;
    830     case kCondF:
    831       CHECK_EQ(rt, ZERO);
    832       Bc1eqz(static_cast<FRegister>(rs), imm16_21);
    833       break;
    834     case kCondT:
    835       CHECK_EQ(rt, ZERO);
    836       Bc1nez(static_cast<FRegister>(rs), imm16_21);
    837       break;
    838     case kUncond:
    839       LOG(FATAL) << "Unexpected branch condition " << cond;
    840       UNREACHABLE();
    841   }
    842 }
    843 
    844 void MipsAssembler::AddS(FRegister fd, FRegister fs, FRegister ft) {
    845   EmitFR(0x11, 0x10, ft, fs, fd, 0x0);
    846 }
    847 
    848 void MipsAssembler::SubS(FRegister fd, FRegister fs, FRegister ft) {
    849   EmitFR(0x11, 0x10, ft, fs, fd, 0x1);
    850 }
    851 
    852 void MipsAssembler::MulS(FRegister fd, FRegister fs, FRegister ft) {
    853   EmitFR(0x11, 0x10, ft, fs, fd, 0x2);
    854 }
    855 
    856 void MipsAssembler::DivS(FRegister fd, FRegister fs, FRegister ft) {
    857   EmitFR(0x11, 0x10, ft, fs, fd, 0x3);
    858 }
    859 
    860 void MipsAssembler::AddD(FRegister fd, FRegister fs, FRegister ft) {
    861   EmitFR(0x11, 0x11, ft, fs, fd, 0x0);
    862 }
    863 
    864 void MipsAssembler::SubD(FRegister fd, FRegister fs, FRegister ft) {
    865   EmitFR(0x11, 0x11, ft, fs, fd, 0x1);
    866 }
    867 
    868 void MipsAssembler::MulD(FRegister fd, FRegister fs, FRegister ft) {
    869   EmitFR(0x11, 0x11, ft, fs, fd, 0x2);
    870 }
    871 
    872 void MipsAssembler::DivD(FRegister fd, FRegister fs, FRegister ft) {
    873   EmitFR(0x11, 0x11, ft, fs, fd, 0x3);
    874 }
    875 
    876 void MipsAssembler::SqrtS(FRegister fd, FRegister fs) {
    877   EmitFR(0x11, 0x10, static_cast<FRegister>(0), fs, fd, 0x4);
    878 }
    879 
    880 void MipsAssembler::SqrtD(FRegister fd, FRegister fs) {
    881   EmitFR(0x11, 0x11, static_cast<FRegister>(0), fs, fd, 0x4);
    882 }
    883 
    884 void MipsAssembler::AbsS(FRegister fd, FRegister fs) {
    885   EmitFR(0x11, 0x10, static_cast<FRegister>(0), fs, fd, 0x5);
    886 }
    887 
    888 void MipsAssembler::AbsD(FRegister fd, FRegister fs) {
    889   EmitFR(0x11, 0x11, static_cast<FRegister>(0), fs, fd, 0x5);
    890 }
    891 
    892 void MipsAssembler::MovS(FRegister fd, FRegister fs) {
    893   EmitFR(0x11, 0x10, static_cast<FRegister>(0), fs, fd, 0x6);
    894 }
    895 
    896 void MipsAssembler::MovD(FRegister fd, FRegister fs) {
    897   EmitFR(0x11, 0x11, static_cast<FRegister>(0), fs, fd, 0x6);
    898 }
    899 
    900 void MipsAssembler::NegS(FRegister fd, FRegister fs) {
    901   EmitFR(0x11, 0x10, static_cast<FRegister>(0), fs, fd, 0x7);
    902 }
    903 
    904 void MipsAssembler::NegD(FRegister fd, FRegister fs) {
    905   EmitFR(0x11, 0x11, static_cast<FRegister>(0), fs, fd, 0x7);
    906 }
    907 
    908 void MipsAssembler::CunS(FRegister fs, FRegister ft) {
    909   CunS(0, fs, ft);
    910 }
    911 
    912 void MipsAssembler::CunS(int cc, FRegister fs, FRegister ft) {
    913   CHECK(!IsR6());
    914   CHECK(IsUint<3>(cc)) << cc;
    915   EmitFR(0x11, 0x10, ft, fs, static_cast<FRegister>(cc << 2), 0x31);
    916 }
    917 
    918 void MipsAssembler::CeqS(FRegister fs, FRegister ft) {
    919   CeqS(0, fs, ft);
    920 }
    921 
    922 void MipsAssembler::CeqS(int cc, FRegister fs, FRegister ft) {
    923   CHECK(!IsR6());
    924   CHECK(IsUint<3>(cc)) << cc;
    925   EmitFR(0x11, 0x10, ft, fs, static_cast<FRegister>(cc << 2), 0x32);
    926 }
    927 
    928 void MipsAssembler::CueqS(FRegister fs, FRegister ft) {
    929   CueqS(0, fs, ft);
    930 }
    931 
    932 void MipsAssembler::CueqS(int cc, FRegister fs, FRegister ft) {
    933   CHECK(!IsR6());
    934   CHECK(IsUint<3>(cc)) << cc;
    935   EmitFR(0x11, 0x10, ft, fs, static_cast<FRegister>(cc << 2), 0x33);
    936 }
    937 
    938 void MipsAssembler::ColtS(FRegister fs, FRegister ft) {
    939   ColtS(0, fs, ft);
    940 }
    941 
    942 void MipsAssembler::ColtS(int cc, FRegister fs, FRegister ft) {
    943   CHECK(!IsR6());
    944   CHECK(IsUint<3>(cc)) << cc;
    945   EmitFR(0x11, 0x10, ft, fs, static_cast<FRegister>(cc << 2), 0x34);
    946 }
    947 
    948 void MipsAssembler::CultS(FRegister fs, FRegister ft) {
    949   CultS(0, fs, ft);
    950 }
    951 
    952 void MipsAssembler::CultS(int cc, FRegister fs, FRegister ft) {
    953   CHECK(!IsR6());
    954   CHECK(IsUint<3>(cc)) << cc;
    955   EmitFR(0x11, 0x10, ft, fs, static_cast<FRegister>(cc << 2), 0x35);
    956 }
    957 
    958 void MipsAssembler::ColeS(FRegister fs, FRegister ft) {
    959   ColeS(0, fs, ft);
    960 }
    961 
    962 void MipsAssembler::ColeS(int cc, FRegister fs, FRegister ft) {
    963   CHECK(!IsR6());
    964   CHECK(IsUint<3>(cc)) << cc;
    965   EmitFR(0x11, 0x10, ft, fs, static_cast<FRegister>(cc << 2), 0x36);
    966 }
    967 
    968 void MipsAssembler::CuleS(FRegister fs, FRegister ft) {
    969   CuleS(0, fs, ft);
    970 }
    971 
    972 void MipsAssembler::CuleS(int cc, FRegister fs, FRegister ft) {
    973   CHECK(!IsR6());
    974   CHECK(IsUint<3>(cc)) << cc;
    975   EmitFR(0x11, 0x10, ft, fs, static_cast<FRegister>(cc << 2), 0x37);
    976 }
    977 
    978 void MipsAssembler::CunD(FRegister fs, FRegister ft) {
    979   CunD(0, fs, ft);
    980 }
    981 
    982 void MipsAssembler::CunD(int cc, FRegister fs, FRegister ft) {
    983   CHECK(!IsR6());
    984   CHECK(IsUint<3>(cc)) << cc;
    985   EmitFR(0x11, 0x11, ft, fs, static_cast<FRegister>(cc << 2), 0x31);
    986 }
    987 
    988 void MipsAssembler::CeqD(FRegister fs, FRegister ft) {
    989   CeqD(0, fs, ft);
    990 }
    991 
    992 void MipsAssembler::CeqD(int cc, FRegister fs, FRegister ft) {
    993   CHECK(!IsR6());
    994   CHECK(IsUint<3>(cc)) << cc;
    995   EmitFR(0x11, 0x11, ft, fs, static_cast<FRegister>(cc << 2), 0x32);
    996 }
    997 
    998 void MipsAssembler::CueqD(FRegister fs, FRegister ft) {
    999   CueqD(0, fs, ft);
   1000 }
   1001 
   1002 void MipsAssembler::CueqD(int cc, FRegister fs, FRegister ft) {
   1003   CHECK(!IsR6());
   1004   CHECK(IsUint<3>(cc)) << cc;
   1005   EmitFR(0x11, 0x11, ft, fs, static_cast<FRegister>(cc << 2), 0x33);
   1006 }
   1007 
   1008 void MipsAssembler::ColtD(FRegister fs, FRegister ft) {
   1009   ColtD(0, fs, ft);
   1010 }
   1011 
   1012 void MipsAssembler::ColtD(int cc, FRegister fs, FRegister ft) {
   1013   CHECK(!IsR6());
   1014   CHECK(IsUint<3>(cc)) << cc;
   1015   EmitFR(0x11, 0x11, ft, fs, static_cast<FRegister>(cc << 2), 0x34);
   1016 }
   1017 
   1018 void MipsAssembler::CultD(FRegister fs, FRegister ft) {
   1019   CultD(0, fs, ft);
   1020 }
   1021 
   1022 void MipsAssembler::CultD(int cc, FRegister fs, FRegister ft) {
   1023   CHECK(!IsR6());
   1024   CHECK(IsUint<3>(cc)) << cc;
   1025   EmitFR(0x11, 0x11, ft, fs, static_cast<FRegister>(cc << 2), 0x35);
   1026 }
   1027 
   1028 void MipsAssembler::ColeD(FRegister fs, FRegister ft) {
   1029   ColeD(0, fs, ft);
   1030 }
   1031 
   1032 void MipsAssembler::ColeD(int cc, FRegister fs, FRegister ft) {
   1033   CHECK(!IsR6());
   1034   CHECK(IsUint<3>(cc)) << cc;
   1035   EmitFR(0x11, 0x11, ft, fs, static_cast<FRegister>(cc << 2), 0x36);
   1036 }
   1037 
   1038 void MipsAssembler::CuleD(FRegister fs, FRegister ft) {
   1039   CuleD(0, fs, ft);
   1040 }
   1041 
   1042 void MipsAssembler::CuleD(int cc, FRegister fs, FRegister ft) {
   1043   CHECK(!IsR6());
   1044   CHECK(IsUint<3>(cc)) << cc;
   1045   EmitFR(0x11, 0x11, ft, fs, static_cast<FRegister>(cc << 2), 0x37);
   1046 }
   1047 
   1048 void MipsAssembler::CmpUnS(FRegister fd, FRegister fs, FRegister ft) {
   1049   CHECK(IsR6());
   1050   EmitFR(0x11, 0x14, ft, fs, fd, 0x01);
   1051 }
   1052 
   1053 void MipsAssembler::CmpEqS(FRegister fd, FRegister fs, FRegister ft) {
   1054   CHECK(IsR6());
   1055   EmitFR(0x11, 0x14, ft, fs, fd, 0x02);
   1056 }
   1057 
   1058 void MipsAssembler::CmpUeqS(FRegister fd, FRegister fs, FRegister ft) {
   1059   CHECK(IsR6());
   1060   EmitFR(0x11, 0x14, ft, fs, fd, 0x03);
   1061 }
   1062 
   1063 void MipsAssembler::CmpLtS(FRegister fd, FRegister fs, FRegister ft) {
   1064   CHECK(IsR6());
   1065   EmitFR(0x11, 0x14, ft, fs, fd, 0x04);
   1066 }
   1067 
   1068 void MipsAssembler::CmpUltS(FRegister fd, FRegister fs, FRegister ft) {
   1069   CHECK(IsR6());
   1070   EmitFR(0x11, 0x14, ft, fs, fd, 0x05);
   1071 }
   1072 
   1073 void MipsAssembler::CmpLeS(FRegister fd, FRegister fs, FRegister ft) {
   1074   CHECK(IsR6());
   1075   EmitFR(0x11, 0x14, ft, fs, fd, 0x06);
   1076 }
   1077 
   1078 void MipsAssembler::CmpUleS(FRegister fd, FRegister fs, FRegister ft) {
   1079   CHECK(IsR6());
   1080   EmitFR(0x11, 0x14, ft, fs, fd, 0x07);
   1081 }
   1082 
   1083 void MipsAssembler::CmpOrS(FRegister fd, FRegister fs, FRegister ft) {
   1084   CHECK(IsR6());
   1085   EmitFR(0x11, 0x14, ft, fs, fd, 0x11);
   1086 }
   1087 
   1088 void MipsAssembler::CmpUneS(FRegister fd, FRegister fs, FRegister ft) {
   1089   CHECK(IsR6());
   1090   EmitFR(0x11, 0x14, ft, fs, fd, 0x12);
   1091 }
   1092 
   1093 void MipsAssembler::CmpNeS(FRegister fd, FRegister fs, FRegister ft) {
   1094   CHECK(IsR6());
   1095   EmitFR(0x11, 0x14, ft, fs, fd, 0x13);
   1096 }
   1097 
   1098 void MipsAssembler::CmpUnD(FRegister fd, FRegister fs, FRegister ft) {
   1099   CHECK(IsR6());
   1100   EmitFR(0x11, 0x15, ft, fs, fd, 0x01);
   1101 }
   1102 
   1103 void MipsAssembler::CmpEqD(FRegister fd, FRegister fs, FRegister ft) {
   1104   CHECK(IsR6());
   1105   EmitFR(0x11, 0x15, ft, fs, fd, 0x02);
   1106 }
   1107 
   1108 void MipsAssembler::CmpUeqD(FRegister fd, FRegister fs, FRegister ft) {
   1109   CHECK(IsR6());
   1110   EmitFR(0x11, 0x15, ft, fs, fd, 0x03);
   1111 }
   1112 
   1113 void MipsAssembler::CmpLtD(FRegister fd, FRegister fs, FRegister ft) {
   1114   CHECK(IsR6());
   1115   EmitFR(0x11, 0x15, ft, fs, fd, 0x04);
   1116 }
   1117 
   1118 void MipsAssembler::CmpUltD(FRegister fd, FRegister fs, FRegister ft) {
   1119   CHECK(IsR6());
   1120   EmitFR(0x11, 0x15, ft, fs, fd, 0x05);
   1121 }
   1122 
   1123 void MipsAssembler::CmpLeD(FRegister fd, FRegister fs, FRegister ft) {
   1124   CHECK(IsR6());
   1125   EmitFR(0x11, 0x15, ft, fs, fd, 0x06);
   1126 }
   1127 
   1128 void MipsAssembler::CmpUleD(FRegister fd, FRegister fs, FRegister ft) {
   1129   CHECK(IsR6());
   1130   EmitFR(0x11, 0x15, ft, fs, fd, 0x07);
   1131 }
   1132 
   1133 void MipsAssembler::CmpOrD(FRegister fd, FRegister fs, FRegister ft) {
   1134   CHECK(IsR6());
   1135   EmitFR(0x11, 0x15, ft, fs, fd, 0x11);
   1136 }
   1137 
   1138 void MipsAssembler::CmpUneD(FRegister fd, FRegister fs, FRegister ft) {
   1139   CHECK(IsR6());
   1140   EmitFR(0x11, 0x15, ft, fs, fd, 0x12);
   1141 }
   1142 
   1143 void MipsAssembler::CmpNeD(FRegister fd, FRegister fs, FRegister ft) {
   1144   CHECK(IsR6());
   1145   EmitFR(0x11, 0x15, ft, fs, fd, 0x13);
   1146 }
   1147 
   1148 void MipsAssembler::Movf(Register rd, Register rs, int cc) {
   1149   CHECK(!IsR6());
   1150   CHECK(IsUint<3>(cc)) << cc;
   1151   EmitR(0, rs, static_cast<Register>(cc << 2), rd, 0, 0x01);
   1152 }
   1153 
   1154 void MipsAssembler::Movt(Register rd, Register rs, int cc) {
   1155   CHECK(!IsR6());
   1156   CHECK(IsUint<3>(cc)) << cc;
   1157   EmitR(0, rs, static_cast<Register>((cc << 2) | 1), rd, 0, 0x01);
   1158 }
   1159 
   1160 void MipsAssembler::MovfS(FRegister fd, FRegister fs, int cc) {
   1161   CHECK(!IsR6());
   1162   CHECK(IsUint<3>(cc)) << cc;
   1163   EmitFR(0x11, 0x10, static_cast<FRegister>(cc << 2), fs, fd, 0x11);
   1164 }
   1165 
   1166 void MipsAssembler::MovfD(FRegister fd, FRegister fs, int cc) {
   1167   CHECK(!IsR6());
   1168   CHECK(IsUint<3>(cc)) << cc;
   1169   EmitFR(0x11, 0x11, static_cast<FRegister>(cc << 2), fs, fd, 0x11);
   1170 }
   1171 
   1172 void MipsAssembler::MovtS(FRegister fd, FRegister fs, int cc) {
   1173   CHECK(!IsR6());
   1174   CHECK(IsUint<3>(cc)) << cc;
   1175   EmitFR(0x11, 0x10, static_cast<FRegister>((cc << 2) | 1), fs, fd, 0x11);
   1176 }
   1177 
   1178 void MipsAssembler::MovtD(FRegister fd, FRegister fs, int cc) {
   1179   CHECK(!IsR6());
   1180   CHECK(IsUint<3>(cc)) << cc;
   1181   EmitFR(0x11, 0x11, static_cast<FRegister>((cc << 2) | 1), fs, fd, 0x11);
   1182 }
   1183 
   1184 void MipsAssembler::SelS(FRegister fd, FRegister fs, FRegister ft) {
   1185   CHECK(IsR6());
   1186   EmitFR(0x11, 0x10, ft, fs, fd, 0x10);
   1187 }
   1188 
   1189 void MipsAssembler::SelD(FRegister fd, FRegister fs, FRegister ft) {
   1190   CHECK(IsR6());
   1191   EmitFR(0x11, 0x11, ft, fs, fd, 0x10);
   1192 }
   1193 
   1194 void MipsAssembler::ClassS(FRegister fd, FRegister fs) {
   1195   CHECK(IsR6());
   1196   EmitFR(0x11, 0x10, static_cast<FRegister>(0), fs, fd, 0x1b);
   1197 }
   1198 
   1199 void MipsAssembler::ClassD(FRegister fd, FRegister fs) {
   1200   CHECK(IsR6());
   1201   EmitFR(0x11, 0x11, static_cast<FRegister>(0), fs, fd, 0x1b);
   1202 }
   1203 
   1204 void MipsAssembler::MinS(FRegister fd, FRegister fs, FRegister ft) {
   1205   CHECK(IsR6());
   1206   EmitFR(0x11, 0x10, ft, fs, fd, 0x1c);
   1207 }
   1208 
   1209 void MipsAssembler::MinD(FRegister fd, FRegister fs, FRegister ft) {
   1210   CHECK(IsR6());
   1211   EmitFR(0x11, 0x11, ft, fs, fd, 0x1c);
   1212 }
   1213 
   1214 void MipsAssembler::MaxS(FRegister fd, FRegister fs, FRegister ft) {
   1215   CHECK(IsR6());
   1216   EmitFR(0x11, 0x10, ft, fs, fd, 0x1e);
   1217 }
   1218 
   1219 void MipsAssembler::MaxD(FRegister fd, FRegister fs, FRegister ft) {
   1220   CHECK(IsR6());
   1221   EmitFR(0x11, 0x11, ft, fs, fd, 0x1e);
   1222 }
   1223 
   1224 void MipsAssembler::TruncLS(FRegister fd, FRegister fs) {
   1225   EmitFR(0x11, 0x10, static_cast<FRegister>(0), fs, fd, 0x09);
   1226 }
   1227 
   1228 void MipsAssembler::TruncLD(FRegister fd, FRegister fs) {
   1229   EmitFR(0x11, 0x11, static_cast<FRegister>(0), fs, fd, 0x09);
   1230 }
   1231 
   1232 void MipsAssembler::TruncWS(FRegister fd, FRegister fs) {
   1233   EmitFR(0x11, 0x10, static_cast<FRegister>(0), fs, fd, 0x0D);
   1234 }
   1235 
   1236 void MipsAssembler::TruncWD(FRegister fd, FRegister fs) {
   1237   EmitFR(0x11, 0x11, static_cast<FRegister>(0), fs, fd, 0x0D);
   1238 }
   1239 
   1240 void MipsAssembler::Cvtsw(FRegister fd, FRegister fs) {
   1241   EmitFR(0x11, 0x14, static_cast<FRegister>(0), fs, fd, 0x20);
   1242 }
   1243 
   1244 void MipsAssembler::Cvtdw(FRegister fd, FRegister fs) {
   1245   EmitFR(0x11, 0x14, static_cast<FRegister>(0), fs, fd, 0x21);
   1246 }
   1247 
   1248 void MipsAssembler::Cvtsd(FRegister fd, FRegister fs) {
   1249   EmitFR(0x11, 0x11, static_cast<FRegister>(0), fs, fd, 0x20);
   1250 }
   1251 
   1252 void MipsAssembler::Cvtds(FRegister fd, FRegister fs) {
   1253   EmitFR(0x11, 0x10, static_cast<FRegister>(0), fs, fd, 0x21);
   1254 }
   1255 
   1256 void MipsAssembler::Cvtsl(FRegister fd, FRegister fs) {
   1257   EmitFR(0x11, 0x15, static_cast<FRegister>(0), fs, fd, 0x20);
   1258 }
   1259 
   1260 void MipsAssembler::Cvtdl(FRegister fd, FRegister fs) {
   1261   EmitFR(0x11, 0x15, static_cast<FRegister>(0), fs, fd, 0x21);
   1262 }
   1263 
   1264 void MipsAssembler::FloorWS(FRegister fd, FRegister fs) {
   1265   EmitFR(0x11, 0x10, static_cast<FRegister>(0), fs, fd, 0xf);
   1266 }
   1267 
   1268 void MipsAssembler::FloorWD(FRegister fd, FRegister fs) {
   1269   EmitFR(0x11, 0x11, static_cast<FRegister>(0), fs, fd, 0xf);
   1270 }
   1271 
   1272 void MipsAssembler::Mfc1(Register rt, FRegister fs) {
   1273   EmitFR(0x11, 0x00, static_cast<FRegister>(rt), fs, static_cast<FRegister>(0), 0x0);
   1274 }
   1275 
   1276 void MipsAssembler::Mtc1(Register rt, FRegister fs) {
   1277   EmitFR(0x11, 0x04, static_cast<FRegister>(rt), fs, static_cast<FRegister>(0), 0x0);
   1278 }
   1279 
   1280 void MipsAssembler::Mfhc1(Register rt, FRegister fs) {
   1281   EmitFR(0x11, 0x03, static_cast<FRegister>(rt), fs, static_cast<FRegister>(0), 0x0);
   1282 }
   1283 
   1284 void MipsAssembler::Mthc1(Register rt, FRegister fs) {
   1285   EmitFR(0x11, 0x07, static_cast<FRegister>(rt), fs, static_cast<FRegister>(0), 0x0);
   1286 }
   1287 
   1288 void MipsAssembler::MoveFromFpuHigh(Register rt, FRegister fs) {
   1289   if (Is32BitFPU()) {
   1290     CHECK_EQ(fs % 2, 0) << fs;
   1291     Mfc1(rt, static_cast<FRegister>(fs + 1));
   1292   } else {
   1293     Mfhc1(rt, fs);
   1294   }
   1295 }
   1296 
   1297 void MipsAssembler::MoveToFpuHigh(Register rt, FRegister fs) {
   1298   if (Is32BitFPU()) {
   1299     CHECK_EQ(fs % 2, 0) << fs;
   1300     Mtc1(rt, static_cast<FRegister>(fs + 1));
   1301   } else {
   1302     Mthc1(rt, fs);
   1303   }
   1304 }
   1305 
   1306 void MipsAssembler::Lwc1(FRegister ft, Register rs, uint16_t imm16) {
   1307   EmitI(0x31, rs, static_cast<Register>(ft), imm16);
   1308 }
   1309 
   1310 void MipsAssembler::Ldc1(FRegister ft, Register rs, uint16_t imm16) {
   1311   EmitI(0x35, rs, static_cast<Register>(ft), imm16);
   1312 }
   1313 
   1314 void MipsAssembler::Swc1(FRegister ft, Register rs, uint16_t imm16) {
   1315   EmitI(0x39, rs, static_cast<Register>(ft), imm16);
   1316 }
   1317 
   1318 void MipsAssembler::Sdc1(FRegister ft, Register rs, uint16_t imm16) {
   1319   EmitI(0x3d, rs, static_cast<Register>(ft), imm16);
   1320 }
   1321 
   1322 void MipsAssembler::Break() {
   1323   EmitR(0, static_cast<Register>(0), static_cast<Register>(0),
   1324         static_cast<Register>(0), 0, 0xD);
   1325 }
   1326 
   1327 void MipsAssembler::Nop() {
   1328   EmitR(0x0, static_cast<Register>(0), static_cast<Register>(0), static_cast<Register>(0), 0, 0x0);
   1329 }
   1330 
   1331 void MipsAssembler::Move(Register rd, Register rs) {
   1332   Or(rd, rs, ZERO);
   1333 }
   1334 
   1335 void MipsAssembler::Clear(Register rd) {
   1336   Move(rd, ZERO);
   1337 }
   1338 
   1339 void MipsAssembler::Not(Register rd, Register rs) {
   1340   Nor(rd, rs, ZERO);
   1341 }
   1342 
   1343 void MipsAssembler::Push(Register rs) {
   1344   IncreaseFrameSize(kMipsWordSize);
   1345   Sw(rs, SP, 0);
   1346 }
   1347 
   1348 void MipsAssembler::Pop(Register rd) {
   1349   Lw(rd, SP, 0);
   1350   DecreaseFrameSize(kMipsWordSize);
   1351 }
   1352 
   1353 void MipsAssembler::PopAndReturn(Register rd, Register rt) {
   1354   Lw(rd, SP, 0);
   1355   Jr(rt);
   1356   DecreaseFrameSize(kMipsWordSize);
   1357 }
   1358 
   1359 void MipsAssembler::LoadConst32(Register rd, int32_t value) {
   1360   if (IsUint<16>(value)) {
   1361     // Use OR with (unsigned) immediate to encode 16b unsigned int.
   1362     Ori(rd, ZERO, value);
   1363   } else if (IsInt<16>(value)) {
   1364     // Use ADD with (signed) immediate to encode 16b signed int.
   1365     Addiu(rd, ZERO, value);
   1366   } else {
   1367     Lui(rd, High16Bits(value));
   1368     if (value & 0xFFFF)
   1369       Ori(rd, rd, Low16Bits(value));
   1370   }
   1371 }
   1372 
   1373 void MipsAssembler::LoadConst64(Register reg_hi, Register reg_lo, int64_t value) {
   1374   uint32_t low = Low32Bits(value);
   1375   uint32_t high = High32Bits(value);
   1376   LoadConst32(reg_lo, low);
   1377   if (high != low) {
   1378     LoadConst32(reg_hi, high);
   1379   } else {
   1380     Move(reg_hi, reg_lo);
   1381   }
   1382 }
   1383 
   1384 void MipsAssembler::StoreConst32ToOffset(int32_t value,
   1385                                          Register base,
   1386                                          int32_t offset,
   1387                                          Register temp) {
   1388   if (!IsInt<16>(offset)) {
   1389     CHECK_NE(temp, AT);  //  Must not use AT as temp, as not to overwrite the loaded value.
   1390     LoadConst32(AT, offset);
   1391     Addu(AT, AT, base);
   1392     base = AT;
   1393     offset = 0;
   1394   }
   1395   if (value == 0) {
   1396     temp = ZERO;
   1397   } else {
   1398     LoadConst32(temp, value);
   1399   }
   1400   Sw(temp, base, offset);
   1401 }
   1402 
   1403 void MipsAssembler::StoreConst64ToOffset(int64_t value,
   1404                                          Register base,
   1405                                          int32_t offset,
   1406                                          Register temp) {
   1407   // IsInt<16> must be passed a signed value.
   1408   if (!IsInt<16>(offset) || !IsInt<16>(static_cast<int32_t>(offset + kMipsWordSize))) {
   1409     CHECK_NE(temp, AT);  //  Must not use AT as temp, as not to overwrite the loaded value.
   1410     LoadConst32(AT, offset);
   1411     Addu(AT, AT, base);
   1412     base = AT;
   1413     offset = 0;
   1414   }
   1415   uint32_t low = Low32Bits(value);
   1416   uint32_t high = High32Bits(value);
   1417   if (low == 0) {
   1418     Sw(ZERO, base, offset);
   1419   } else {
   1420     LoadConst32(temp, low);
   1421     Sw(temp, base, offset);
   1422   }
   1423   if (high == 0) {
   1424     Sw(ZERO, base, offset + kMipsWordSize);
   1425   } else {
   1426     if (high != low) {
   1427       LoadConst32(temp, high);
   1428     }
   1429     Sw(temp, base, offset + kMipsWordSize);
   1430   }
   1431 }
   1432 
   1433 void MipsAssembler::LoadSConst32(FRegister r, int32_t value, Register temp) {
   1434   if (value == 0) {
   1435     temp = ZERO;
   1436   } else {
   1437     LoadConst32(temp, value);
   1438   }
   1439   Mtc1(temp, r);
   1440 }
   1441 
   1442 void MipsAssembler::LoadDConst64(FRegister rd, int64_t value, Register temp) {
   1443   uint32_t low = Low32Bits(value);
   1444   uint32_t high = High32Bits(value);
   1445   if (low == 0) {
   1446     Mtc1(ZERO, rd);
   1447   } else {
   1448     LoadConst32(temp, low);
   1449     Mtc1(temp, rd);
   1450   }
   1451   if (high == 0) {
   1452     MoveToFpuHigh(ZERO, rd);
   1453   } else {
   1454     LoadConst32(temp, high);
   1455     MoveToFpuHigh(temp, rd);
   1456   }
   1457 }
   1458 
   1459 void MipsAssembler::Addiu32(Register rt, Register rs, int32_t value, Register temp) {
   1460   if (IsInt<16>(value)) {
   1461     Addiu(rt, rs, value);
   1462   } else {
   1463     LoadConst32(temp, value);
   1464     Addu(rt, rs, temp);
   1465   }
   1466 }
   1467 
   1468 void MipsAssembler::Branch::InitShortOrLong(MipsAssembler::Branch::OffsetBits offset_size,
   1469                                             MipsAssembler::Branch::Type short_type,
   1470                                             MipsAssembler::Branch::Type long_type) {
   1471   type_ = (offset_size <= branch_info_[short_type].offset_size) ? short_type : long_type;
   1472 }
   1473 
   1474 void MipsAssembler::Branch::InitializeType(bool is_call, bool is_r6) {
   1475   OffsetBits offset_size = GetOffsetSizeNeeded(location_, target_);
   1476   if (is_r6) {
   1477     // R6
   1478     if (is_call) {
   1479       InitShortOrLong(offset_size, kR6Call, kR6LongCall);
   1480     } else if (condition_ == kUncond) {
   1481       InitShortOrLong(offset_size, kR6UncondBranch, kR6LongUncondBranch);
   1482     } else {
   1483       if (condition_ == kCondEQZ || condition_ == kCondNEZ) {
   1484         // Special case for beqzc/bnezc with longer offset than in other b<cond>c instructions.
   1485         type_ = (offset_size <= kOffset23) ? kR6CondBranch : kR6LongCondBranch;
   1486       } else {
   1487         InitShortOrLong(offset_size, kR6CondBranch, kR6LongCondBranch);
   1488       }
   1489     }
   1490   } else {
   1491     // R2
   1492     if (is_call) {
   1493       InitShortOrLong(offset_size, kCall, kLongCall);
   1494     } else if (condition_ == kUncond) {
   1495       InitShortOrLong(offset_size, kUncondBranch, kLongUncondBranch);
   1496     } else {
   1497       InitShortOrLong(offset_size, kCondBranch, kLongCondBranch);
   1498     }
   1499   }
   1500   old_type_ = type_;
   1501 }
   1502 
   1503 bool MipsAssembler::Branch::IsNop(BranchCondition condition, Register lhs, Register rhs) {
   1504   switch (condition) {
   1505     case kCondLT:
   1506     case kCondGT:
   1507     case kCondNE:
   1508     case kCondLTU:
   1509       return lhs == rhs;
   1510     default:
   1511       return false;
   1512   }
   1513 }
   1514 
   1515 bool MipsAssembler::Branch::IsUncond(BranchCondition condition, Register lhs, Register rhs) {
   1516   switch (condition) {
   1517     case kUncond:
   1518       return true;
   1519     case kCondGE:
   1520     case kCondLE:
   1521     case kCondEQ:
   1522     case kCondGEU:
   1523       return lhs == rhs;
   1524     default:
   1525       return false;
   1526   }
   1527 }
   1528 
   1529 MipsAssembler::Branch::Branch(bool is_r6, uint32_t location, uint32_t target)
   1530     : old_location_(location),
   1531       location_(location),
   1532       target_(target),
   1533       lhs_reg_(0),
   1534       rhs_reg_(0),
   1535       condition_(kUncond) {
   1536   InitializeType(false, is_r6);
   1537 }
   1538 
   1539 MipsAssembler::Branch::Branch(bool is_r6,
   1540                               uint32_t location,
   1541                               uint32_t target,
   1542                               MipsAssembler::BranchCondition condition,
   1543                               Register lhs_reg,
   1544                               Register rhs_reg)
   1545     : old_location_(location),
   1546       location_(location),
   1547       target_(target),
   1548       lhs_reg_(lhs_reg),
   1549       rhs_reg_(rhs_reg),
   1550       condition_(condition) {
   1551   CHECK_NE(condition, kUncond);
   1552   switch (condition) {
   1553     case kCondLT:
   1554     case kCondGE:
   1555     case kCondLE:
   1556     case kCondGT:
   1557     case kCondLTU:
   1558     case kCondGEU:
   1559       // We don't support synthetic R2 branches (preceded with slt[u]) at this level
   1560       // (R2 doesn't have branches to compare 2 registers using <, <=, >=, >).
   1561       // We leave this up to the caller.
   1562       CHECK(is_r6);
   1563       FALLTHROUGH_INTENDED;
   1564     case kCondEQ:
   1565     case kCondNE:
   1566       // Require registers other than 0 not only for R6, but also for R2 to catch errors.
   1567       // To compare with 0, use dedicated kCond*Z conditions.
   1568       CHECK_NE(lhs_reg, ZERO);
   1569       CHECK_NE(rhs_reg, ZERO);
   1570       break;
   1571     case kCondLTZ:
   1572     case kCondGEZ:
   1573     case kCondLEZ:
   1574     case kCondGTZ:
   1575     case kCondEQZ:
   1576     case kCondNEZ:
   1577       // Require registers other than 0 not only for R6, but also for R2 to catch errors.
   1578       CHECK_NE(lhs_reg, ZERO);
   1579       CHECK_EQ(rhs_reg, ZERO);
   1580       break;
   1581     case kCondF:
   1582     case kCondT:
   1583       CHECK_EQ(rhs_reg, ZERO);
   1584       break;
   1585     case kUncond:
   1586       UNREACHABLE();
   1587   }
   1588   CHECK(!IsNop(condition, lhs_reg, rhs_reg));
   1589   if (IsUncond(condition, lhs_reg, rhs_reg)) {
   1590     // Branch condition is always true, make the branch unconditional.
   1591     condition_ = kUncond;
   1592   }
   1593   InitializeType(false, is_r6);
   1594 }
   1595 
   1596 MipsAssembler::Branch::Branch(bool is_r6, uint32_t location, uint32_t target, Register indirect_reg)
   1597     : old_location_(location),
   1598       location_(location),
   1599       target_(target),
   1600       lhs_reg_(indirect_reg),
   1601       rhs_reg_(0),
   1602       condition_(kUncond) {
   1603   CHECK_NE(indirect_reg, ZERO);
   1604   CHECK_NE(indirect_reg, AT);
   1605   InitializeType(true, is_r6);
   1606 }
   1607 
   1608 MipsAssembler::BranchCondition MipsAssembler::Branch::OppositeCondition(
   1609     MipsAssembler::BranchCondition cond) {
   1610   switch (cond) {
   1611     case kCondLT:
   1612       return kCondGE;
   1613     case kCondGE:
   1614       return kCondLT;
   1615     case kCondLE:
   1616       return kCondGT;
   1617     case kCondGT:
   1618       return kCondLE;
   1619     case kCondLTZ:
   1620       return kCondGEZ;
   1621     case kCondGEZ:
   1622       return kCondLTZ;
   1623     case kCondLEZ:
   1624       return kCondGTZ;
   1625     case kCondGTZ:
   1626       return kCondLEZ;
   1627     case kCondEQ:
   1628       return kCondNE;
   1629     case kCondNE:
   1630       return kCondEQ;
   1631     case kCondEQZ:
   1632       return kCondNEZ;
   1633     case kCondNEZ:
   1634       return kCondEQZ;
   1635     case kCondLTU:
   1636       return kCondGEU;
   1637     case kCondGEU:
   1638       return kCondLTU;
   1639     case kCondF:
   1640       return kCondT;
   1641     case kCondT:
   1642       return kCondF;
   1643     case kUncond:
   1644       LOG(FATAL) << "Unexpected branch condition " << cond;
   1645   }
   1646   UNREACHABLE();
   1647 }
   1648 
   1649 MipsAssembler::Branch::Type MipsAssembler::Branch::GetType() const {
   1650   return type_;
   1651 }
   1652 
   1653 MipsAssembler::BranchCondition MipsAssembler::Branch::GetCondition() const {
   1654   return condition_;
   1655 }
   1656 
   1657 Register MipsAssembler::Branch::GetLeftRegister() const {
   1658   return static_cast<Register>(lhs_reg_);
   1659 }
   1660 
   1661 Register MipsAssembler::Branch::GetRightRegister() const {
   1662   return static_cast<Register>(rhs_reg_);
   1663 }
   1664 
   1665 uint32_t MipsAssembler::Branch::GetTarget() const {
   1666   return target_;
   1667 }
   1668 
   1669 uint32_t MipsAssembler::Branch::GetLocation() const {
   1670   return location_;
   1671 }
   1672 
   1673 uint32_t MipsAssembler::Branch::GetOldLocation() const {
   1674   return old_location_;
   1675 }
   1676 
   1677 uint32_t MipsAssembler::Branch::GetLength() const {
   1678   return branch_info_[type_].length;
   1679 }
   1680 
   1681 uint32_t MipsAssembler::Branch::GetOldLength() const {
   1682   return branch_info_[old_type_].length;
   1683 }
   1684 
   1685 uint32_t MipsAssembler::Branch::GetSize() const {
   1686   return GetLength() * sizeof(uint32_t);
   1687 }
   1688 
   1689 uint32_t MipsAssembler::Branch::GetOldSize() const {
   1690   return GetOldLength() * sizeof(uint32_t);
   1691 }
   1692 
   1693 uint32_t MipsAssembler::Branch::GetEndLocation() const {
   1694   return GetLocation() + GetSize();
   1695 }
   1696 
   1697 uint32_t MipsAssembler::Branch::GetOldEndLocation() const {
   1698   return GetOldLocation() + GetOldSize();
   1699 }
   1700 
   1701 bool MipsAssembler::Branch::IsLong() const {
   1702   switch (type_) {
   1703     // R2 short branches.
   1704     case kUncondBranch:
   1705     case kCondBranch:
   1706     case kCall:
   1707     // R6 short branches.
   1708     case kR6UncondBranch:
   1709     case kR6CondBranch:
   1710     case kR6Call:
   1711       return false;
   1712     // R2 long branches.
   1713     case kLongUncondBranch:
   1714     case kLongCondBranch:
   1715     case kLongCall:
   1716     // R6 long branches.
   1717     case kR6LongUncondBranch:
   1718     case kR6LongCondBranch:
   1719     case kR6LongCall:
   1720       return true;
   1721   }
   1722   UNREACHABLE();
   1723 }
   1724 
   1725 bool MipsAssembler::Branch::IsResolved() const {
   1726   return target_ != kUnresolved;
   1727 }
   1728 
   1729 MipsAssembler::Branch::OffsetBits MipsAssembler::Branch::GetOffsetSize() const {
   1730   OffsetBits offset_size =
   1731       (type_ == kR6CondBranch && (condition_ == kCondEQZ || condition_ == kCondNEZ))
   1732           ? kOffset23
   1733           : branch_info_[type_].offset_size;
   1734   return offset_size;
   1735 }
   1736 
   1737 MipsAssembler::Branch::OffsetBits MipsAssembler::Branch::GetOffsetSizeNeeded(uint32_t location,
   1738                                                                              uint32_t target) {
   1739   // For unresolved targets assume the shortest encoding
   1740   // (later it will be made longer if needed).
   1741   if (target == kUnresolved)
   1742     return kOffset16;
   1743   int64_t distance = static_cast<int64_t>(target) - location;
   1744   // To simplify calculations in composite branches consisting of multiple instructions
   1745   // bump up the distance by a value larger than the max byte size of a composite branch.
   1746   distance += (distance >= 0) ? kMaxBranchSize : -kMaxBranchSize;
   1747   if (IsInt<kOffset16>(distance))
   1748     return kOffset16;
   1749   else if (IsInt<kOffset18>(distance))
   1750     return kOffset18;
   1751   else if (IsInt<kOffset21>(distance))
   1752     return kOffset21;
   1753   else if (IsInt<kOffset23>(distance))
   1754     return kOffset23;
   1755   else if (IsInt<kOffset28>(distance))
   1756     return kOffset28;
   1757   return kOffset32;
   1758 }
   1759 
   1760 void MipsAssembler::Branch::Resolve(uint32_t target) {
   1761   target_ = target;
   1762 }
   1763 
   1764 void MipsAssembler::Branch::Relocate(uint32_t expand_location, uint32_t delta) {
   1765   if (location_ > expand_location) {
   1766     location_ += delta;
   1767   }
   1768   if (!IsResolved()) {
   1769     return;  // Don't know the target yet.
   1770   }
   1771   if (target_ > expand_location) {
   1772     target_ += delta;
   1773   }
   1774 }
   1775 
   1776 void MipsAssembler::Branch::PromoteToLong() {
   1777   switch (type_) {
   1778     // R2 short branches.
   1779     case kUncondBranch:
   1780       type_ = kLongUncondBranch;
   1781       break;
   1782     case kCondBranch:
   1783       type_ = kLongCondBranch;
   1784       break;
   1785     case kCall:
   1786       type_ = kLongCall;
   1787       break;
   1788     // R6 short branches.
   1789     case kR6UncondBranch:
   1790       type_ = kR6LongUncondBranch;
   1791       break;
   1792     case kR6CondBranch:
   1793       type_ = kR6LongCondBranch;
   1794       break;
   1795     case kR6Call:
   1796       type_ = kR6LongCall;
   1797       break;
   1798     default:
   1799       // Note: 'type_' is already long.
   1800       break;
   1801   }
   1802   CHECK(IsLong());
   1803 }
   1804 
   1805 uint32_t MipsAssembler::Branch::PromoteIfNeeded(uint32_t max_short_distance) {
   1806   // If the branch is still unresolved or already long, nothing to do.
   1807   if (IsLong() || !IsResolved()) {
   1808     return 0;
   1809   }
   1810   // Promote the short branch to long if the offset size is too small
   1811   // to hold the distance between location_ and target_.
   1812   if (GetOffsetSizeNeeded(location_, target_) > GetOffsetSize()) {
   1813     PromoteToLong();
   1814     uint32_t old_size = GetOldSize();
   1815     uint32_t new_size = GetSize();
   1816     CHECK_GT(new_size, old_size);
   1817     return new_size - old_size;
   1818   }
   1819   // The following logic is for debugging/testing purposes.
   1820   // Promote some short branches to long when it's not really required.
   1821   if (UNLIKELY(max_short_distance != std::numeric_limits<uint32_t>::max())) {
   1822     int64_t distance = static_cast<int64_t>(target_) - location_;
   1823     distance = (distance >= 0) ? distance : -distance;
   1824     if (distance >= max_short_distance) {
   1825       PromoteToLong();
   1826       uint32_t old_size = GetOldSize();
   1827       uint32_t new_size = GetSize();
   1828       CHECK_GT(new_size, old_size);
   1829       return new_size - old_size;
   1830     }
   1831   }
   1832   return 0;
   1833 }
   1834 
   1835 uint32_t MipsAssembler::Branch::GetOffsetLocation() const {
   1836   return location_ + branch_info_[type_].instr_offset * sizeof(uint32_t);
   1837 }
   1838 
   1839 uint32_t MipsAssembler::Branch::GetOffset() const {
   1840   CHECK(IsResolved());
   1841   uint32_t ofs_mask = 0xFFFFFFFF >> (32 - GetOffsetSize());
   1842   // Calculate the byte distance between instructions and also account for
   1843   // different PC-relative origins.
   1844   uint32_t offset = target_ - GetOffsetLocation() - branch_info_[type_].pc_org * sizeof(uint32_t);
   1845   // Prepare the offset for encoding into the instruction(s).
   1846   offset = (offset & ofs_mask) >> branch_info_[type_].offset_shift;
   1847   return offset;
   1848 }
   1849 
   1850 MipsAssembler::Branch* MipsAssembler::GetBranch(uint32_t branch_id) {
   1851   CHECK_LT(branch_id, branches_.size());
   1852   return &branches_[branch_id];
   1853 }
   1854 
   1855 const MipsAssembler::Branch* MipsAssembler::GetBranch(uint32_t branch_id) const {
   1856   CHECK_LT(branch_id, branches_.size());
   1857   return &branches_[branch_id];
   1858 }
   1859 
   1860 void MipsAssembler::Bind(MipsLabel* label) {
   1861   CHECK(!label->IsBound());
   1862   uint32_t bound_pc = buffer_.Size();
   1863 
   1864   // Walk the list of branches referring to and preceding this label.
   1865   // Store the previously unknown target addresses in them.
   1866   while (label->IsLinked()) {
   1867     uint32_t branch_id = label->Position();
   1868     Branch* branch = GetBranch(branch_id);
   1869     branch->Resolve(bound_pc);
   1870 
   1871     uint32_t branch_location = branch->GetLocation();
   1872     // Extract the location of the previous branch in the list (walking the list backwards;
   1873     // the previous branch ID was stored in the space reserved for this branch).
   1874     uint32_t prev = buffer_.Load<uint32_t>(branch_location);
   1875 
   1876     // On to the previous branch in the list...
   1877     label->position_ = prev;
   1878   }
   1879 
   1880   // Now make the label object contain its own location (relative to the end of the preceding
   1881   // branch, if any; it will be used by the branches referring to and following this label).
   1882   label->prev_branch_id_plus_one_ = branches_.size();
   1883   if (label->prev_branch_id_plus_one_) {
   1884     uint32_t branch_id = label->prev_branch_id_plus_one_ - 1;
   1885     const Branch* branch = GetBranch(branch_id);
   1886     bound_pc -= branch->GetEndLocation();
   1887   }
   1888   label->BindTo(bound_pc);
   1889 }
   1890 
   1891 uint32_t MipsAssembler::GetLabelLocation(MipsLabel* label) const {
   1892   CHECK(label->IsBound());
   1893   uint32_t target = label->Position();
   1894   if (label->prev_branch_id_plus_one_) {
   1895     // Get label location based on the branch preceding it.
   1896     uint32_t branch_id = label->prev_branch_id_plus_one_ - 1;
   1897     const Branch* branch = GetBranch(branch_id);
   1898     target += branch->GetEndLocation();
   1899   }
   1900   return target;
   1901 }
   1902 
   1903 uint32_t MipsAssembler::GetAdjustedPosition(uint32_t old_position) {
   1904   // We can reconstruct the adjustment by going through all the branches from the beginning
   1905   // up to the old_position. Since we expect AdjustedPosition() to be called in a loop
   1906   // with increasing old_position, we can use the data from last AdjustedPosition() to
   1907   // continue where we left off and the whole loop should be O(m+n) where m is the number
   1908   // of positions to adjust and n is the number of branches.
   1909   if (old_position < last_old_position_) {
   1910     last_position_adjustment_ = 0;
   1911     last_old_position_ = 0;
   1912     last_branch_id_ = 0;
   1913   }
   1914   while (last_branch_id_ != branches_.size()) {
   1915     const Branch* branch = GetBranch(last_branch_id_);
   1916     if (branch->GetLocation() >= old_position + last_position_adjustment_) {
   1917       break;
   1918     }
   1919     last_position_adjustment_ += branch->GetSize() - branch->GetOldSize();
   1920     ++last_branch_id_;
   1921   }
   1922   last_old_position_ = old_position;
   1923   return old_position + last_position_adjustment_;
   1924 }
   1925 
   1926 void MipsAssembler::FinalizeLabeledBranch(MipsLabel* label) {
   1927   uint32_t length = branches_.back().GetLength();
   1928   if (!label->IsBound()) {
   1929     // Branch forward (to a following label), distance is unknown.
   1930     // The first branch forward will contain 0, serving as the terminator of
   1931     // the list of forward-reaching branches.
   1932     Emit(label->position_);
   1933     length--;
   1934     // Now make the label object point to this branch
   1935     // (this forms a linked list of branches preceding this label).
   1936     uint32_t branch_id = branches_.size() - 1;
   1937     label->LinkTo(branch_id);
   1938   }
   1939   // Reserve space for the branch.
   1940   while (length--) {
   1941     Nop();
   1942   }
   1943 }
   1944 
   1945 void MipsAssembler::Buncond(MipsLabel* label) {
   1946   uint32_t target = label->IsBound() ? GetLabelLocation(label) : Branch::kUnresolved;
   1947   branches_.emplace_back(IsR6(), buffer_.Size(), target);
   1948   FinalizeLabeledBranch(label);
   1949 }
   1950 
   1951 void MipsAssembler::Bcond(MipsLabel* label, BranchCondition condition, Register lhs, Register rhs) {
   1952   // If lhs = rhs, this can be a NOP.
   1953   if (Branch::IsNop(condition, lhs, rhs)) {
   1954     return;
   1955   }
   1956   uint32_t target = label->IsBound() ? GetLabelLocation(label) : Branch::kUnresolved;
   1957   branches_.emplace_back(IsR6(), buffer_.Size(), target, condition, lhs, rhs);
   1958   FinalizeLabeledBranch(label);
   1959 }
   1960 
   1961 void MipsAssembler::Call(MipsLabel* label, Register indirect_reg) {
   1962   uint32_t target = label->IsBound() ? GetLabelLocation(label) : Branch::kUnresolved;
   1963   branches_.emplace_back(IsR6(), buffer_.Size(), target, indirect_reg);
   1964   FinalizeLabeledBranch(label);
   1965 }
   1966 
   1967 void MipsAssembler::PromoteBranches() {
   1968   // Promote short branches to long as necessary.
   1969   bool changed;
   1970   do {
   1971     changed = false;
   1972     for (auto& branch : branches_) {
   1973       CHECK(branch.IsResolved());
   1974       uint32_t delta = branch.PromoteIfNeeded();
   1975       // If this branch has been promoted and needs to expand in size,
   1976       // relocate all branches by the expansion size.
   1977       if (delta) {
   1978         changed = true;
   1979         uint32_t expand_location = branch.GetLocation();
   1980         for (auto& branch2 : branches_) {
   1981           branch2.Relocate(expand_location, delta);
   1982         }
   1983       }
   1984     }
   1985   } while (changed);
   1986 
   1987   // Account for branch expansion by resizing the code buffer
   1988   // and moving the code in it to its final location.
   1989   size_t branch_count = branches_.size();
   1990   if (branch_count > 0) {
   1991     // Resize.
   1992     Branch& last_branch = branches_[branch_count - 1];
   1993     uint32_t size_delta = last_branch.GetEndLocation() - last_branch.GetOldEndLocation();
   1994     uint32_t old_size = buffer_.Size();
   1995     buffer_.Resize(old_size + size_delta);
   1996     // Move the code residing between branch placeholders.
   1997     uint32_t end = old_size;
   1998     for (size_t i = branch_count; i > 0; ) {
   1999       Branch& branch = branches_[--i];
   2000       uint32_t size = end - branch.GetOldEndLocation();
   2001       buffer_.Move(branch.GetEndLocation(), branch.GetOldEndLocation(), size);
   2002       end = branch.GetOldLocation();
   2003     }
   2004   }
   2005 }
   2006 
   2007 // Note: make sure branch_info_[] and EmitBranch() are kept synchronized.
   2008 const MipsAssembler::Branch::BranchInfo MipsAssembler::Branch::branch_info_[] = {
   2009   // R2 short branches.
   2010   {  2, 0, 1, MipsAssembler::Branch::kOffset18, 2 },  // kUncondBranch
   2011   {  2, 0, 1, MipsAssembler::Branch::kOffset18, 2 },  // kCondBranch
   2012   {  5, 2, 0, MipsAssembler::Branch::kOffset16, 0 },  // kCall
   2013   // R2 long branches.
   2014   {  9, 3, 1, MipsAssembler::Branch::kOffset32, 0 },  // kLongUncondBranch
   2015   { 10, 4, 1, MipsAssembler::Branch::kOffset32, 0 },  // kLongCondBranch
   2016   {  6, 1, 1, MipsAssembler::Branch::kOffset32, 0 },  // kLongCall
   2017   // R6 short branches.
   2018   {  1, 0, 1, MipsAssembler::Branch::kOffset28, 2 },  // kR6UncondBranch
   2019   {  2, 0, 1, MipsAssembler::Branch::kOffset18, 2 },  // kR6CondBranch
   2020                                                       // Exception: kOffset23 for beqzc/bnezc.
   2021   {  2, 0, 0, MipsAssembler::Branch::kOffset21, 2 },  // kR6Call
   2022   // R6 long branches.
   2023   {  2, 0, 0, MipsAssembler::Branch::kOffset32, 0 },  // kR6LongUncondBranch
   2024   {  3, 1, 0, MipsAssembler::Branch::kOffset32, 0 },  // kR6LongCondBranch
   2025   {  3, 0, 0, MipsAssembler::Branch::kOffset32, 0 },  // kR6LongCall
   2026 };
   2027 
   2028 // Note: make sure branch_info_[] and mitBranch() are kept synchronized.
   2029 void MipsAssembler::EmitBranch(MipsAssembler::Branch* branch) {
   2030   CHECK_EQ(overwriting_, true);
   2031   overwrite_location_ = branch->GetLocation();
   2032   uint32_t offset = branch->GetOffset();
   2033   BranchCondition condition = branch->GetCondition();
   2034   Register lhs = branch->GetLeftRegister();
   2035   Register rhs = branch->GetRightRegister();
   2036   switch (branch->GetType()) {
   2037     // R2 short branches.
   2038     case Branch::kUncondBranch:
   2039       CHECK_EQ(overwrite_location_, branch->GetOffsetLocation());
   2040       B(offset);
   2041       Nop();  // TODO: improve by filling the delay slot.
   2042       break;
   2043     case Branch::kCondBranch:
   2044       CHECK_EQ(overwrite_location_, branch->GetOffsetLocation());
   2045       EmitBcondR2(condition, lhs, rhs, offset);
   2046       Nop();  // TODO: improve by filling the delay slot.
   2047       break;
   2048     case Branch::kCall:
   2049       Nal();
   2050       Nop();  // TODO: is this NOP really needed here?
   2051       CHECK_EQ(overwrite_location_, branch->GetOffsetLocation());
   2052       Addiu(lhs, RA, offset);
   2053       Jalr(lhs);
   2054       Nop();
   2055       break;
   2056 
   2057     // R2 long branches.
   2058     case Branch::kLongUncondBranch:
   2059       // To get the value of the PC register we need to use the NAL instruction.
   2060       // NAL clobbers the RA register. However, RA must be preserved if the
   2061       // method is compiled without the entry/exit sequences that would take care
   2062       // of preserving RA (typically, leaf methods don't preserve RA explicitly).
   2063       // So, we need to preserve RA in some temporary storage ourselves. The AT
   2064       // register can't be used for this because we need it to load a constant
   2065       // which will be added to the value that NAL stores in RA. And we can't
   2066       // use T9 for this in the context of the JNI compiler, which uses it
   2067       // as a scratch register (see InterproceduralScratchRegister()).
   2068       // If we were to add a 32-bit constant to RA using two ADDIU instructions,
   2069       // we'd also need to use the ROTR instruction, which requires no less than
   2070       // MIPSR2.
   2071       // Perhaps, we could use T8 or one of R2's multiplier/divider registers
   2072       // (LO or HI) or even a floating-point register, but that doesn't seem
   2073       // like a nice solution. We may want this to work on both R6 and pre-R6.
   2074       // For now simply use the stack for RA. This should be OK since for the
   2075       // vast majority of code a short PC-relative branch is sufficient.
   2076       // TODO: can this be improved?
   2077       Push(RA);
   2078       Nal();
   2079       CHECK_EQ(overwrite_location_, branch->GetOffsetLocation());
   2080       Lui(AT, High16Bits(offset));
   2081       Ori(AT, AT, Low16Bits(offset));
   2082       Addu(AT, AT, RA);
   2083       Lw(RA, SP, 0);
   2084       Jr(AT);
   2085       DecreaseFrameSize(kMipsWordSize);
   2086       break;
   2087     case Branch::kLongCondBranch:
   2088       // The comment on case 'Branch::kLongUncondBranch' applies here as well.
   2089       // Note: the opposite condition branch encodes 8 as the distance, which is equal to the
   2090       // number of instructions skipped:
   2091       // (PUSH(IncreaseFrameSize(ADDIU) + SW) + NAL + LUI + ORI + ADDU + LW + JR).
   2092       EmitBcondR2(Branch::OppositeCondition(condition), lhs, rhs, 8);
   2093       Push(RA);
   2094       Nal();
   2095       CHECK_EQ(overwrite_location_, branch->GetOffsetLocation());
   2096       Lui(AT, High16Bits(offset));
   2097       Ori(AT, AT, Low16Bits(offset));
   2098       Addu(AT, AT, RA);
   2099       Lw(RA, SP, 0);
   2100       Jr(AT);
   2101       DecreaseFrameSize(kMipsWordSize);
   2102       break;
   2103     case Branch::kLongCall:
   2104       Nal();
   2105       CHECK_EQ(overwrite_location_, branch->GetOffsetLocation());
   2106       Lui(AT, High16Bits(offset));
   2107       Ori(AT, AT, Low16Bits(offset));
   2108       Addu(lhs, AT, RA);
   2109       Jalr(lhs);
   2110       Nop();
   2111       break;
   2112 
   2113     // R6 short branches.
   2114     case Branch::kR6UncondBranch:
   2115       CHECK_EQ(overwrite_location_, branch->GetOffsetLocation());
   2116       Bc(offset);
   2117       break;
   2118     case Branch::kR6CondBranch:
   2119       CHECK_EQ(overwrite_location_, branch->GetOffsetLocation());
   2120       EmitBcondR6(condition, lhs, rhs, offset);
   2121       Nop();  // TODO: improve by filling the forbidden/delay slot.
   2122       break;
   2123     case Branch::kR6Call:
   2124       CHECK_EQ(overwrite_location_, branch->GetOffsetLocation());
   2125       Addiupc(lhs, offset);
   2126       Jialc(lhs, 0);
   2127       break;
   2128 
   2129     // R6 long branches.
   2130     case Branch::kR6LongUncondBranch:
   2131       offset += (offset & 0x8000) << 1;  // Account for sign extension in jic.
   2132       CHECK_EQ(overwrite_location_, branch->GetOffsetLocation());
   2133       Auipc(AT, High16Bits(offset));
   2134       Jic(AT, Low16Bits(offset));
   2135       break;
   2136     case Branch::kR6LongCondBranch:
   2137       EmitBcondR6(Branch::OppositeCondition(condition), lhs, rhs, 2);
   2138       offset += (offset & 0x8000) << 1;  // Account for sign extension in jic.
   2139       CHECK_EQ(overwrite_location_, branch->GetOffsetLocation());
   2140       Auipc(AT, High16Bits(offset));
   2141       Jic(AT, Low16Bits(offset));
   2142       break;
   2143     case Branch::kR6LongCall:
   2144       offset += (offset & 0x8000) << 1;  // Account for sign extension in addiu.
   2145       CHECK_EQ(overwrite_location_, branch->GetOffsetLocation());
   2146       Auipc(lhs, High16Bits(offset));
   2147       Addiu(lhs, lhs, Low16Bits(offset));
   2148       Jialc(lhs, 0);
   2149       break;
   2150   }
   2151   CHECK_EQ(overwrite_location_, branch->GetEndLocation());
   2152   CHECK_LT(branch->GetSize(), static_cast<uint32_t>(Branch::kMaxBranchSize));
   2153 }
   2154 
   2155 void MipsAssembler::B(MipsLabel* label) {
   2156   Buncond(label);
   2157 }
   2158 
   2159 void MipsAssembler::Jalr(MipsLabel* label, Register indirect_reg) {
   2160   Call(label, indirect_reg);
   2161 }
   2162 
   2163 void MipsAssembler::Beq(Register rs, Register rt, MipsLabel* label) {
   2164   Bcond(label, kCondEQ, rs, rt);
   2165 }
   2166 
   2167 void MipsAssembler::Bne(Register rs, Register rt, MipsLabel* label) {
   2168   Bcond(label, kCondNE, rs, rt);
   2169 }
   2170 
   2171 void MipsAssembler::Beqz(Register rt, MipsLabel* label) {
   2172   Bcond(label, kCondEQZ, rt);
   2173 }
   2174 
   2175 void MipsAssembler::Bnez(Register rt, MipsLabel* label) {
   2176   Bcond(label, kCondNEZ, rt);
   2177 }
   2178 
   2179 void MipsAssembler::Bltz(Register rt, MipsLabel* label) {
   2180   Bcond(label, kCondLTZ, rt);
   2181 }
   2182 
   2183 void MipsAssembler::Bgez(Register rt, MipsLabel* label) {
   2184   Bcond(label, kCondGEZ, rt);
   2185 }
   2186 
   2187 void MipsAssembler::Blez(Register rt, MipsLabel* label) {
   2188   Bcond(label, kCondLEZ, rt);
   2189 }
   2190 
   2191 void MipsAssembler::Bgtz(Register rt, MipsLabel* label) {
   2192   Bcond(label, kCondGTZ, rt);
   2193 }
   2194 
   2195 void MipsAssembler::Blt(Register rs, Register rt, MipsLabel* label) {
   2196   if (IsR6()) {
   2197     Bcond(label, kCondLT, rs, rt);
   2198   } else if (!Branch::IsNop(kCondLT, rs, rt)) {
   2199     // Synthesize the instruction (not available on R2).
   2200     Slt(AT, rs, rt);
   2201     Bnez(AT, label);
   2202   }
   2203 }
   2204 
   2205 void MipsAssembler::Bge(Register rs, Register rt, MipsLabel* label) {
   2206   if (IsR6()) {
   2207     Bcond(label, kCondGE, rs, rt);
   2208   } else if (Branch::IsUncond(kCondGE, rs, rt)) {
   2209     B(label);
   2210   } else {
   2211     // Synthesize the instruction (not available on R2).
   2212     Slt(AT, rs, rt);
   2213     Beqz(AT, label);
   2214   }
   2215 }
   2216 
   2217 void MipsAssembler::Bltu(Register rs, Register rt, MipsLabel* label) {
   2218   if (IsR6()) {
   2219     Bcond(label, kCondLTU, rs, rt);
   2220   } else if (!Branch::IsNop(kCondLTU, rs, rt)) {
   2221     // Synthesize the instruction (not available on R2).
   2222     Sltu(AT, rs, rt);
   2223     Bnez(AT, label);
   2224   }
   2225 }
   2226 
   2227 void MipsAssembler::Bgeu(Register rs, Register rt, MipsLabel* label) {
   2228   if (IsR6()) {
   2229     Bcond(label, kCondGEU, rs, rt);
   2230   } else if (Branch::IsUncond(kCondGEU, rs, rt)) {
   2231     B(label);
   2232   } else {
   2233     // Synthesize the instruction (not available on R2).
   2234     Sltu(AT, rs, rt);
   2235     Beqz(AT, label);
   2236   }
   2237 }
   2238 
   2239 void MipsAssembler::Bc1f(MipsLabel* label) {
   2240   Bc1f(0, label);
   2241 }
   2242 
   2243 void MipsAssembler::Bc1f(int cc, MipsLabel* label) {
   2244   CHECK(IsUint<3>(cc)) << cc;
   2245   Bcond(label, kCondF, static_cast<Register>(cc), ZERO);
   2246 }
   2247 
   2248 void MipsAssembler::Bc1t(MipsLabel* label) {
   2249   Bc1t(0, label);
   2250 }
   2251 
   2252 void MipsAssembler::Bc1t(int cc, MipsLabel* label) {
   2253   CHECK(IsUint<3>(cc)) << cc;
   2254   Bcond(label, kCondT, static_cast<Register>(cc), ZERO);
   2255 }
   2256 
   2257 void MipsAssembler::Bc1eqz(FRegister ft, MipsLabel* label) {
   2258   Bcond(label, kCondF, static_cast<Register>(ft), ZERO);
   2259 }
   2260 
   2261 void MipsAssembler::Bc1nez(FRegister ft, MipsLabel* label) {
   2262   Bcond(label, kCondT, static_cast<Register>(ft), ZERO);
   2263 }
   2264 
   2265 void MipsAssembler::LoadFromOffset(LoadOperandType type, Register reg, Register base,
   2266                                    int32_t offset) {
   2267   // IsInt<16> must be passed a signed value.
   2268   if (!IsInt<16>(offset) ||
   2269       (type == kLoadDoubleword && !IsInt<16>(static_cast<int32_t>(offset + kMipsWordSize)))) {
   2270     LoadConst32(AT, offset);
   2271     Addu(AT, AT, base);
   2272     base = AT;
   2273     offset = 0;
   2274   }
   2275 
   2276   switch (type) {
   2277     case kLoadSignedByte:
   2278       Lb(reg, base, offset);
   2279       break;
   2280     case kLoadUnsignedByte:
   2281       Lbu(reg, base, offset);
   2282       break;
   2283     case kLoadSignedHalfword:
   2284       Lh(reg, base, offset);
   2285       break;
   2286     case kLoadUnsignedHalfword:
   2287       Lhu(reg, base, offset);
   2288       break;
   2289     case kLoadWord:
   2290       Lw(reg, base, offset);
   2291       break;
   2292     case kLoadDoubleword:
   2293       if (reg == base) {
   2294         // This will clobber the base when loading the lower register. Since we have to load the
   2295         // higher register as well, this will fail. Solution: reverse the order.
   2296         Lw(static_cast<Register>(reg + 1), base, offset + kMipsWordSize);
   2297         Lw(reg, base, offset);
   2298       } else {
   2299         Lw(reg, base, offset);
   2300         Lw(static_cast<Register>(reg + 1), base, offset + kMipsWordSize);
   2301       }
   2302       break;
   2303     default:
   2304       LOG(FATAL) << "UNREACHABLE";
   2305   }
   2306 }
   2307 
   2308 void MipsAssembler::LoadSFromOffset(FRegister reg, Register base, int32_t offset) {
   2309   if (!IsInt<16>(offset)) {
   2310     LoadConst32(AT, offset);
   2311     Addu(AT, AT, base);
   2312     base = AT;
   2313     offset = 0;
   2314   }
   2315 
   2316   Lwc1(reg, base, offset);
   2317 }
   2318 
   2319 void MipsAssembler::LoadDFromOffset(FRegister reg, Register base, int32_t offset) {
   2320   // IsInt<16> must be passed a signed value.
   2321   if (!IsInt<16>(offset) ||
   2322       (!IsAligned<kMipsDoublewordSize>(offset) &&
   2323        !IsInt<16>(static_cast<int32_t>(offset + kMipsWordSize)))) {
   2324     LoadConst32(AT, offset);
   2325     Addu(AT, AT, base);
   2326     base = AT;
   2327     offset = 0;
   2328   }
   2329 
   2330   if (offset & 0x7) {
   2331     if (Is32BitFPU()) {
   2332       Lwc1(reg, base, offset);
   2333       Lwc1(static_cast<FRegister>(reg + 1), base, offset + kMipsWordSize);
   2334     } else {
   2335       // 64-bit FPU.
   2336       Lwc1(reg, base, offset);
   2337       Lw(T8, base, offset + kMipsWordSize);
   2338       Mthc1(T8, reg);
   2339     }
   2340   } else {
   2341     Ldc1(reg, base, offset);
   2342   }
   2343 }
   2344 
   2345 void MipsAssembler::EmitLoad(ManagedRegister m_dst, Register src_register, int32_t src_offset,
   2346                              size_t size) {
   2347   MipsManagedRegister dst = m_dst.AsMips();
   2348   if (dst.IsNoRegister()) {
   2349     CHECK_EQ(0u, size) << dst;
   2350   } else if (dst.IsCoreRegister()) {
   2351     CHECK_EQ(kMipsWordSize, size) << dst;
   2352     LoadFromOffset(kLoadWord, dst.AsCoreRegister(), src_register, src_offset);
   2353   } else if (dst.IsRegisterPair()) {
   2354     CHECK_EQ(kMipsDoublewordSize, size) << dst;
   2355     LoadFromOffset(kLoadDoubleword, dst.AsRegisterPairLow(), src_register, src_offset);
   2356   } else if (dst.IsFRegister()) {
   2357     if (size == kMipsWordSize) {
   2358       LoadSFromOffset(dst.AsFRegister(), src_register, src_offset);
   2359     } else {
   2360       CHECK_EQ(kMipsDoublewordSize, size) << dst;
   2361       LoadDFromOffset(dst.AsFRegister(), src_register, src_offset);
   2362     }
   2363   }
   2364 }
   2365 
   2366 void MipsAssembler::StoreToOffset(StoreOperandType type, Register reg, Register base,
   2367                                   int32_t offset) {
   2368   // IsInt<16> must be passed a signed value.
   2369   if (!IsInt<16>(offset) ||
   2370       (type == kStoreDoubleword && !IsInt<16>(static_cast<int32_t>(offset + kMipsWordSize)))) {
   2371     LoadConst32(AT, offset);
   2372     Addu(AT, AT, base);
   2373     base = AT;
   2374     offset = 0;
   2375   }
   2376 
   2377   switch (type) {
   2378     case kStoreByte:
   2379       Sb(reg, base, offset);
   2380       break;
   2381     case kStoreHalfword:
   2382       Sh(reg, base, offset);
   2383       break;
   2384     case kStoreWord:
   2385       Sw(reg, base, offset);
   2386       break;
   2387     case kStoreDoubleword:
   2388       CHECK_NE(reg, base);
   2389       CHECK_NE(static_cast<Register>(reg + 1), base);
   2390       Sw(reg, base, offset);
   2391       Sw(static_cast<Register>(reg + 1), base, offset + kMipsWordSize);
   2392       break;
   2393     default:
   2394       LOG(FATAL) << "UNREACHABLE";
   2395   }
   2396 }
   2397 
   2398 void MipsAssembler::StoreSToOffset(FRegister reg, Register base, int32_t offset) {
   2399   if (!IsInt<16>(offset)) {
   2400     LoadConst32(AT, offset);
   2401     Addu(AT, AT, base);
   2402     base = AT;
   2403     offset = 0;
   2404   }
   2405 
   2406   Swc1(reg, base, offset);
   2407 }
   2408 
   2409 void MipsAssembler::StoreDToOffset(FRegister reg, Register base, int32_t offset) {
   2410   // IsInt<16> must be passed a signed value.
   2411   if (!IsInt<16>(offset) ||
   2412       (!IsAligned<kMipsDoublewordSize>(offset) &&
   2413        !IsInt<16>(static_cast<int32_t>(offset + kMipsWordSize)))) {
   2414     LoadConst32(AT, offset);
   2415     Addu(AT, AT, base);
   2416     base = AT;
   2417     offset = 0;
   2418   }
   2419 
   2420   if (offset & 0x7) {
   2421     if (Is32BitFPU()) {
   2422       Swc1(reg, base, offset);
   2423       Swc1(static_cast<FRegister>(reg + 1), base, offset + kMipsWordSize);
   2424     } else {
   2425       // 64-bit FPU.
   2426       Mfhc1(T8, reg);
   2427       Swc1(reg, base, offset);
   2428       Sw(T8, base, offset + kMipsWordSize);
   2429     }
   2430   } else {
   2431     Sdc1(reg, base, offset);
   2432   }
   2433 }
   2434 
   2435 static dwarf::Reg DWARFReg(Register reg) {
   2436   return dwarf::Reg::MipsCore(static_cast<int>(reg));
   2437 }
   2438 
   2439 constexpr size_t kFramePointerSize = 4;
   2440 
   2441 void MipsAssembler::BuildFrame(size_t frame_size, ManagedRegister method_reg,
   2442                                const std::vector<ManagedRegister>& callee_save_regs,
   2443                                const ManagedRegisterEntrySpills& entry_spills) {
   2444   CHECK_ALIGNED(frame_size, kStackAlignment);
   2445   DCHECK(!overwriting_);
   2446 
   2447   // Increase frame to required size.
   2448   IncreaseFrameSize(frame_size);
   2449 
   2450   // Push callee saves and return address.
   2451   int stack_offset = frame_size - kFramePointerSize;
   2452   StoreToOffset(kStoreWord, RA, SP, stack_offset);
   2453   cfi_.RelOffset(DWARFReg(RA), stack_offset);
   2454   for (int i = callee_save_regs.size() - 1; i >= 0; --i) {
   2455     stack_offset -= kFramePointerSize;
   2456     Register reg = callee_save_regs.at(i).AsMips().AsCoreRegister();
   2457     StoreToOffset(kStoreWord, reg, SP, stack_offset);
   2458     cfi_.RelOffset(DWARFReg(reg), stack_offset);
   2459   }
   2460 
   2461   // Write out Method*.
   2462   StoreToOffset(kStoreWord, method_reg.AsMips().AsCoreRegister(), SP, 0);
   2463 
   2464   // Write out entry spills.
   2465   int32_t offset = frame_size + kFramePointerSize;
   2466   for (size_t i = 0; i < entry_spills.size(); ++i) {
   2467     MipsManagedRegister reg = entry_spills.at(i).AsMips();
   2468     if (reg.IsNoRegister()) {
   2469       ManagedRegisterSpill spill = entry_spills.at(i);
   2470       offset += spill.getSize();
   2471     } else if (reg.IsCoreRegister()) {
   2472       StoreToOffset(kStoreWord, reg.AsCoreRegister(), SP, offset);
   2473       offset += kMipsWordSize;
   2474     } else if (reg.IsFRegister()) {
   2475       StoreSToOffset(reg.AsFRegister(), SP, offset);
   2476       offset += kMipsWordSize;
   2477     } else if (reg.IsDRegister()) {
   2478       StoreDToOffset(reg.AsOverlappingDRegisterLow(), SP, offset);
   2479       offset += kMipsDoublewordSize;
   2480     }
   2481   }
   2482 }
   2483 
   2484 void MipsAssembler::RemoveFrame(size_t frame_size,
   2485                                 const std::vector<ManagedRegister>& callee_save_regs) {
   2486   CHECK_ALIGNED(frame_size, kStackAlignment);
   2487   DCHECK(!overwriting_);
   2488   cfi_.RememberState();
   2489 
   2490   // Pop callee saves and return address.
   2491   int stack_offset = frame_size - (callee_save_regs.size() * kFramePointerSize) - kFramePointerSize;
   2492   for (size_t i = 0; i < callee_save_regs.size(); ++i) {
   2493     Register reg = callee_save_regs.at(i).AsMips().AsCoreRegister();
   2494     LoadFromOffset(kLoadWord, reg, SP, stack_offset);
   2495     cfi_.Restore(DWARFReg(reg));
   2496     stack_offset += kFramePointerSize;
   2497   }
   2498   LoadFromOffset(kLoadWord, RA, SP, stack_offset);
   2499   cfi_.Restore(DWARFReg(RA));
   2500 
   2501   // Decrease frame to required size.
   2502   DecreaseFrameSize(frame_size);
   2503 
   2504   // Then jump to the return address.
   2505   Jr(RA);
   2506   Nop();
   2507 
   2508   // The CFI should be restored for any code that follows the exit block.
   2509   cfi_.RestoreState();
   2510   cfi_.DefCFAOffset(frame_size);
   2511 }
   2512 
   2513 void MipsAssembler::IncreaseFrameSize(size_t adjust) {
   2514   CHECK_ALIGNED(adjust, kFramePointerSize);
   2515   Addiu32(SP, SP, -adjust);
   2516   cfi_.AdjustCFAOffset(adjust);
   2517   if (overwriting_) {
   2518     cfi_.OverrideDelayedPC(overwrite_location_);
   2519   }
   2520 }
   2521 
   2522 void MipsAssembler::DecreaseFrameSize(size_t adjust) {
   2523   CHECK_ALIGNED(adjust, kFramePointerSize);
   2524   Addiu32(SP, SP, adjust);
   2525   cfi_.AdjustCFAOffset(-adjust);
   2526   if (overwriting_) {
   2527     cfi_.OverrideDelayedPC(overwrite_location_);
   2528   }
   2529 }
   2530 
   2531 void MipsAssembler::Store(FrameOffset dest, ManagedRegister msrc, size_t size) {
   2532   MipsManagedRegister src = msrc.AsMips();
   2533   if (src.IsNoRegister()) {
   2534     CHECK_EQ(0u, size);
   2535   } else if (src.IsCoreRegister()) {
   2536     CHECK_EQ(kMipsWordSize, size);
   2537     StoreToOffset(kStoreWord, src.AsCoreRegister(), SP, dest.Int32Value());
   2538   } else if (src.IsRegisterPair()) {
   2539     CHECK_EQ(kMipsDoublewordSize, size);
   2540     StoreToOffset(kStoreWord, src.AsRegisterPairLow(), SP, dest.Int32Value());
   2541     StoreToOffset(kStoreWord, src.AsRegisterPairHigh(),
   2542                   SP, dest.Int32Value() + kMipsWordSize);
   2543   } else if (src.IsFRegister()) {
   2544     if (size == kMipsWordSize) {
   2545       StoreSToOffset(src.AsFRegister(), SP, dest.Int32Value());
   2546     } else {
   2547       CHECK_EQ(kMipsDoublewordSize, size);
   2548       StoreDToOffset(src.AsFRegister(), SP, dest.Int32Value());
   2549     }
   2550   }
   2551 }
   2552 
   2553 void MipsAssembler::StoreRef(FrameOffset dest, ManagedRegister msrc) {
   2554   MipsManagedRegister src = msrc.AsMips();
   2555   CHECK(src.IsCoreRegister());
   2556   StoreToOffset(kStoreWord, src.AsCoreRegister(), SP, dest.Int32Value());
   2557 }
   2558 
   2559 void MipsAssembler::StoreRawPtr(FrameOffset dest, ManagedRegister msrc) {
   2560   MipsManagedRegister src = msrc.AsMips();
   2561   CHECK(src.IsCoreRegister());
   2562   StoreToOffset(kStoreWord, src.AsCoreRegister(), SP, dest.Int32Value());
   2563 }
   2564 
   2565 void MipsAssembler::StoreImmediateToFrame(FrameOffset dest, uint32_t imm,
   2566                                           ManagedRegister mscratch) {
   2567   MipsManagedRegister scratch = mscratch.AsMips();
   2568   CHECK(scratch.IsCoreRegister()) << scratch;
   2569   LoadConst32(scratch.AsCoreRegister(), imm);
   2570   StoreToOffset(kStoreWord, scratch.AsCoreRegister(), SP, dest.Int32Value());
   2571 }
   2572 
   2573 void MipsAssembler::StoreImmediateToThread32(ThreadOffset<kMipsWordSize> dest, uint32_t imm,
   2574                                              ManagedRegister mscratch) {
   2575   MipsManagedRegister scratch = mscratch.AsMips();
   2576   CHECK(scratch.IsCoreRegister()) << scratch;
   2577   // Is this function even referenced anywhere else in the code?
   2578   LoadConst32(scratch.AsCoreRegister(), imm);
   2579   StoreToOffset(kStoreWord, scratch.AsCoreRegister(), S1, dest.Int32Value());
   2580 }
   2581 
   2582 void MipsAssembler::StoreStackOffsetToThread32(ThreadOffset<kMipsWordSize> thr_offs,
   2583                                                FrameOffset fr_offs,
   2584                                                ManagedRegister mscratch) {
   2585   MipsManagedRegister scratch = mscratch.AsMips();
   2586   CHECK(scratch.IsCoreRegister()) << scratch;
   2587   Addiu32(scratch.AsCoreRegister(), SP, fr_offs.Int32Value());
   2588   StoreToOffset(kStoreWord, scratch.AsCoreRegister(),
   2589                 S1, thr_offs.Int32Value());
   2590 }
   2591 
   2592 void MipsAssembler::StoreStackPointerToThread32(ThreadOffset<kMipsWordSize> thr_offs) {
   2593   StoreToOffset(kStoreWord, SP, S1, thr_offs.Int32Value());
   2594 }
   2595 
   2596 void MipsAssembler::StoreSpanning(FrameOffset dest, ManagedRegister msrc,
   2597                                   FrameOffset in_off, ManagedRegister mscratch) {
   2598   MipsManagedRegister src = msrc.AsMips();
   2599   MipsManagedRegister scratch = mscratch.AsMips();
   2600   StoreToOffset(kStoreWord, src.AsCoreRegister(), SP, dest.Int32Value());
   2601   LoadFromOffset(kLoadWord, scratch.AsCoreRegister(), SP, in_off.Int32Value());
   2602   StoreToOffset(kStoreWord, scratch.AsCoreRegister(), SP, dest.Int32Value() + kMipsWordSize);
   2603 }
   2604 
   2605 void MipsAssembler::Load(ManagedRegister mdest, FrameOffset src, size_t size) {
   2606   return EmitLoad(mdest, SP, src.Int32Value(), size);
   2607 }
   2608 
   2609 void MipsAssembler::LoadFromThread32(ManagedRegister mdest,
   2610                                      ThreadOffset<kMipsWordSize> src, size_t size) {
   2611   return EmitLoad(mdest, S1, src.Int32Value(), size);
   2612 }
   2613 
   2614 void MipsAssembler::LoadRef(ManagedRegister mdest, FrameOffset src) {
   2615   MipsManagedRegister dest = mdest.AsMips();
   2616   CHECK(dest.IsCoreRegister());
   2617   LoadFromOffset(kLoadWord, dest.AsCoreRegister(), SP, src.Int32Value());
   2618 }
   2619 
   2620 void MipsAssembler::LoadRef(ManagedRegister mdest, ManagedRegister base, MemberOffset offs,
   2621                             bool unpoison_reference) {
   2622   MipsManagedRegister dest = mdest.AsMips();
   2623   CHECK(dest.IsCoreRegister() && base.AsMips().IsCoreRegister());
   2624   LoadFromOffset(kLoadWord, dest.AsCoreRegister(),
   2625                  base.AsMips().AsCoreRegister(), offs.Int32Value());
   2626   if (kPoisonHeapReferences && unpoison_reference) {
   2627     Subu(dest.AsCoreRegister(), ZERO, dest.AsCoreRegister());
   2628   }
   2629 }
   2630 
   2631 void MipsAssembler::LoadRawPtr(ManagedRegister mdest, ManagedRegister base, Offset offs) {
   2632   MipsManagedRegister dest = mdest.AsMips();
   2633   CHECK(dest.IsCoreRegister() && base.AsMips().IsCoreRegister());
   2634   LoadFromOffset(kLoadWord, dest.AsCoreRegister(),
   2635                  base.AsMips().AsCoreRegister(), offs.Int32Value());
   2636 }
   2637 
   2638 void MipsAssembler::LoadRawPtrFromThread32(ManagedRegister mdest,
   2639                                            ThreadOffset<kMipsWordSize> offs) {
   2640   MipsManagedRegister dest = mdest.AsMips();
   2641   CHECK(dest.IsCoreRegister());
   2642   LoadFromOffset(kLoadWord, dest.AsCoreRegister(), S1, offs.Int32Value());
   2643 }
   2644 
   2645 void MipsAssembler::SignExtend(ManagedRegister /*mreg*/, size_t /*size*/) {
   2646   UNIMPLEMENTED(FATAL) << "no sign extension necessary for mips";
   2647 }
   2648 
   2649 void MipsAssembler::ZeroExtend(ManagedRegister /*mreg*/, size_t /*size*/) {
   2650   UNIMPLEMENTED(FATAL) << "no zero extension necessary for mips";
   2651 }
   2652 
   2653 void MipsAssembler::Move(ManagedRegister mdest, ManagedRegister msrc, size_t size) {
   2654   MipsManagedRegister dest = mdest.AsMips();
   2655   MipsManagedRegister src = msrc.AsMips();
   2656   if (!dest.Equals(src)) {
   2657     if (dest.IsCoreRegister()) {
   2658       CHECK(src.IsCoreRegister()) << src;
   2659       Move(dest.AsCoreRegister(), src.AsCoreRegister());
   2660     } else if (dest.IsFRegister()) {
   2661       CHECK(src.IsFRegister()) << src;
   2662       if (size == kMipsWordSize) {
   2663         MovS(dest.AsFRegister(), src.AsFRegister());
   2664       } else {
   2665         CHECK_EQ(kMipsDoublewordSize, size);
   2666         MovD(dest.AsFRegister(), src.AsFRegister());
   2667       }
   2668     } else if (dest.IsDRegister()) {
   2669       CHECK(src.IsDRegister()) << src;
   2670       MovD(dest.AsOverlappingDRegisterLow(), src.AsOverlappingDRegisterLow());
   2671     } else {
   2672       CHECK(dest.IsRegisterPair()) << dest;
   2673       CHECK(src.IsRegisterPair()) << src;
   2674       // Ensure that the first move doesn't clobber the input of the second.
   2675       if (src.AsRegisterPairHigh() != dest.AsRegisterPairLow()) {
   2676         Move(dest.AsRegisterPairLow(), src.AsRegisterPairLow());
   2677         Move(dest.AsRegisterPairHigh(), src.AsRegisterPairHigh());
   2678       } else {
   2679         Move(dest.AsRegisterPairHigh(), src.AsRegisterPairHigh());
   2680         Move(dest.AsRegisterPairLow(), src.AsRegisterPairLow());
   2681       }
   2682     }
   2683   }
   2684 }
   2685 
   2686 void MipsAssembler::CopyRef(FrameOffset dest, FrameOffset src, ManagedRegister mscratch) {
   2687   MipsManagedRegister scratch = mscratch.AsMips();
   2688   CHECK(scratch.IsCoreRegister()) << scratch;
   2689   LoadFromOffset(kLoadWord, scratch.AsCoreRegister(), SP, src.Int32Value());
   2690   StoreToOffset(kStoreWord, scratch.AsCoreRegister(), SP, dest.Int32Value());
   2691 }
   2692 
   2693 void MipsAssembler::CopyRawPtrFromThread32(FrameOffset fr_offs,
   2694                                            ThreadOffset<kMipsWordSize> thr_offs,
   2695                                            ManagedRegister mscratch) {
   2696   MipsManagedRegister scratch = mscratch.AsMips();
   2697   CHECK(scratch.IsCoreRegister()) << scratch;
   2698   LoadFromOffset(kLoadWord, scratch.AsCoreRegister(),
   2699                  S1, thr_offs.Int32Value());
   2700   StoreToOffset(kStoreWord, scratch.AsCoreRegister(),
   2701                 SP, fr_offs.Int32Value());
   2702 }
   2703 
   2704 void MipsAssembler::CopyRawPtrToThread32(ThreadOffset<kMipsWordSize> thr_offs,
   2705                                          FrameOffset fr_offs,
   2706                                          ManagedRegister mscratch) {
   2707   MipsManagedRegister scratch = mscratch.AsMips();
   2708   CHECK(scratch.IsCoreRegister()) << scratch;
   2709   LoadFromOffset(kLoadWord, scratch.AsCoreRegister(),
   2710                  SP, fr_offs.Int32Value());
   2711   StoreToOffset(kStoreWord, scratch.AsCoreRegister(),
   2712                 S1, thr_offs.Int32Value());
   2713 }
   2714 
   2715 void MipsAssembler::Copy(FrameOffset dest, FrameOffset src, ManagedRegister mscratch, size_t size) {
   2716   MipsManagedRegister scratch = mscratch.AsMips();
   2717   CHECK(scratch.IsCoreRegister()) << scratch;
   2718   CHECK(size == kMipsWordSize || size == kMipsDoublewordSize) << size;
   2719   if (size == kMipsWordSize) {
   2720     LoadFromOffset(kLoadWord, scratch.AsCoreRegister(), SP, src.Int32Value());
   2721     StoreToOffset(kStoreWord, scratch.AsCoreRegister(), SP, dest.Int32Value());
   2722   } else if (size == kMipsDoublewordSize) {
   2723     LoadFromOffset(kLoadWord, scratch.AsCoreRegister(), SP, src.Int32Value());
   2724     StoreToOffset(kStoreWord, scratch.AsCoreRegister(), SP, dest.Int32Value());
   2725     LoadFromOffset(kLoadWord, scratch.AsCoreRegister(), SP, src.Int32Value() + kMipsWordSize);
   2726     StoreToOffset(kStoreWord, scratch.AsCoreRegister(), SP, dest.Int32Value() + kMipsWordSize);
   2727   }
   2728 }
   2729 
   2730 void MipsAssembler::Copy(FrameOffset dest, ManagedRegister src_base, Offset src_offset,
   2731                          ManagedRegister mscratch, size_t size) {
   2732   Register scratch = mscratch.AsMips().AsCoreRegister();
   2733   CHECK_EQ(size, kMipsWordSize);
   2734   LoadFromOffset(kLoadWord, scratch, src_base.AsMips().AsCoreRegister(), src_offset.Int32Value());
   2735   StoreToOffset(kStoreWord, scratch, SP, dest.Int32Value());
   2736 }
   2737 
   2738 void MipsAssembler::Copy(ManagedRegister dest_base, Offset dest_offset, FrameOffset src,
   2739                          ManagedRegister mscratch, size_t size) {
   2740   Register scratch = mscratch.AsMips().AsCoreRegister();
   2741   CHECK_EQ(size, kMipsWordSize);
   2742   LoadFromOffset(kLoadWord, scratch, SP, src.Int32Value());
   2743   StoreToOffset(kStoreWord, scratch, dest_base.AsMips().AsCoreRegister(), dest_offset.Int32Value());
   2744 }
   2745 
   2746 void MipsAssembler::Copy(FrameOffset dest ATTRIBUTE_UNUSED,
   2747                          FrameOffset src_base ATTRIBUTE_UNUSED,
   2748                          Offset src_offset ATTRIBUTE_UNUSED,
   2749                          ManagedRegister mscratch ATTRIBUTE_UNUSED,
   2750                          size_t size ATTRIBUTE_UNUSED) {
   2751   UNIMPLEMENTED(FATAL) << "no MIPS implementation";
   2752 }
   2753 
   2754 void MipsAssembler::Copy(ManagedRegister dest, Offset dest_offset,
   2755                          ManagedRegister src, Offset src_offset,
   2756                          ManagedRegister mscratch, size_t size) {
   2757   CHECK_EQ(size, kMipsWordSize);
   2758   Register scratch = mscratch.AsMips().AsCoreRegister();
   2759   LoadFromOffset(kLoadWord, scratch, src.AsMips().AsCoreRegister(), src_offset.Int32Value());
   2760   StoreToOffset(kStoreWord, scratch, dest.AsMips().AsCoreRegister(), dest_offset.Int32Value());
   2761 }
   2762 
   2763 void MipsAssembler::Copy(FrameOffset dest ATTRIBUTE_UNUSED,
   2764                          Offset dest_offset ATTRIBUTE_UNUSED,
   2765                          FrameOffset src ATTRIBUTE_UNUSED,
   2766                          Offset src_offset ATTRIBUTE_UNUSED,
   2767                          ManagedRegister mscratch ATTRIBUTE_UNUSED,
   2768                          size_t size ATTRIBUTE_UNUSED) {
   2769   UNIMPLEMENTED(FATAL) << "no MIPS implementation";
   2770 }
   2771 
   2772 void MipsAssembler::MemoryBarrier(ManagedRegister) {
   2773   // TODO: sync?
   2774   UNIMPLEMENTED(FATAL) << "no MIPS implementation";
   2775 }
   2776 
   2777 void MipsAssembler::CreateHandleScopeEntry(ManagedRegister mout_reg,
   2778                                            FrameOffset handle_scope_offset,
   2779                                            ManagedRegister min_reg,
   2780                                            bool null_allowed) {
   2781   MipsManagedRegister out_reg = mout_reg.AsMips();
   2782   MipsManagedRegister in_reg = min_reg.AsMips();
   2783   CHECK(in_reg.IsNoRegister() || in_reg.IsCoreRegister()) << in_reg;
   2784   CHECK(out_reg.IsCoreRegister()) << out_reg;
   2785   if (null_allowed) {
   2786     MipsLabel null_arg;
   2787     // Null values get a handle scope entry value of 0.  Otherwise, the handle scope entry is
   2788     // the address in the handle scope holding the reference.
   2789     // E.g. out_reg = (handle == 0) ? 0 : (SP+handle_offset).
   2790     if (in_reg.IsNoRegister()) {
   2791       LoadFromOffset(kLoadWord, out_reg.AsCoreRegister(),
   2792                      SP, handle_scope_offset.Int32Value());
   2793       in_reg = out_reg;
   2794     }
   2795     if (!out_reg.Equals(in_reg)) {
   2796       LoadConst32(out_reg.AsCoreRegister(), 0);
   2797     }
   2798     Beqz(in_reg.AsCoreRegister(), &null_arg);
   2799     Addiu32(out_reg.AsCoreRegister(), SP, handle_scope_offset.Int32Value());
   2800     Bind(&null_arg);
   2801   } else {
   2802     Addiu32(out_reg.AsCoreRegister(), SP, handle_scope_offset.Int32Value());
   2803   }
   2804 }
   2805 
   2806 void MipsAssembler::CreateHandleScopeEntry(FrameOffset out_off,
   2807                                            FrameOffset handle_scope_offset,
   2808                                            ManagedRegister mscratch,
   2809                                            bool null_allowed) {
   2810   MipsManagedRegister scratch = mscratch.AsMips();
   2811   CHECK(scratch.IsCoreRegister()) << scratch;
   2812   if (null_allowed) {
   2813     MipsLabel null_arg;
   2814     LoadFromOffset(kLoadWord, scratch.AsCoreRegister(), SP, handle_scope_offset.Int32Value());
   2815     // Null values get a handle scope entry value of 0.  Otherwise, the handle scope entry is
   2816     // the address in the handle scope holding the reference.
   2817     // E.g. scratch = (scratch == 0) ? 0 : (SP+handle_scope_offset).
   2818     Beqz(scratch.AsCoreRegister(), &null_arg);
   2819     Addiu32(scratch.AsCoreRegister(), SP, handle_scope_offset.Int32Value());
   2820     Bind(&null_arg);
   2821   } else {
   2822     Addiu32(scratch.AsCoreRegister(), SP, handle_scope_offset.Int32Value());
   2823   }
   2824   StoreToOffset(kStoreWord, scratch.AsCoreRegister(), SP, out_off.Int32Value());
   2825 }
   2826 
   2827 // Given a handle scope entry, load the associated reference.
   2828 void MipsAssembler::LoadReferenceFromHandleScope(ManagedRegister mout_reg,
   2829                                                  ManagedRegister min_reg) {
   2830   MipsManagedRegister out_reg = mout_reg.AsMips();
   2831   MipsManagedRegister in_reg = min_reg.AsMips();
   2832   CHECK(out_reg.IsCoreRegister()) << out_reg;
   2833   CHECK(in_reg.IsCoreRegister()) << in_reg;
   2834   MipsLabel null_arg;
   2835   if (!out_reg.Equals(in_reg)) {
   2836     LoadConst32(out_reg.AsCoreRegister(), 0);
   2837   }
   2838   Beqz(in_reg.AsCoreRegister(), &null_arg);
   2839   LoadFromOffset(kLoadWord, out_reg.AsCoreRegister(),
   2840                  in_reg.AsCoreRegister(), 0);
   2841   Bind(&null_arg);
   2842 }
   2843 
   2844 void MipsAssembler::VerifyObject(ManagedRegister src ATTRIBUTE_UNUSED,
   2845                                  bool could_be_null ATTRIBUTE_UNUSED) {
   2846   // TODO: not validating references.
   2847 }
   2848 
   2849 void MipsAssembler::VerifyObject(FrameOffset src ATTRIBUTE_UNUSED,
   2850                                  bool could_be_null ATTRIBUTE_UNUSED) {
   2851   // TODO: not validating references.
   2852 }
   2853 
   2854 void MipsAssembler::Call(ManagedRegister mbase, Offset offset, ManagedRegister mscratch) {
   2855   MipsManagedRegister base = mbase.AsMips();
   2856   MipsManagedRegister scratch = mscratch.AsMips();
   2857   CHECK(base.IsCoreRegister()) << base;
   2858   CHECK(scratch.IsCoreRegister()) << scratch;
   2859   LoadFromOffset(kLoadWord, scratch.AsCoreRegister(),
   2860                  base.AsCoreRegister(), offset.Int32Value());
   2861   Jalr(scratch.AsCoreRegister());
   2862   Nop();
   2863   // TODO: place reference map on call.
   2864 }
   2865 
   2866 void MipsAssembler::Call(FrameOffset base, Offset offset, ManagedRegister mscratch) {
   2867   MipsManagedRegister scratch = mscratch.AsMips();
   2868   CHECK(scratch.IsCoreRegister()) << scratch;
   2869   // Call *(*(SP + base) + offset)
   2870   LoadFromOffset(kLoadWord, scratch.AsCoreRegister(), SP, base.Int32Value());
   2871   LoadFromOffset(kLoadWord, scratch.AsCoreRegister(),
   2872                  scratch.AsCoreRegister(), offset.Int32Value());
   2873   Jalr(scratch.AsCoreRegister());
   2874   Nop();
   2875   // TODO: place reference map on call.
   2876 }
   2877 
   2878 void MipsAssembler::CallFromThread32(ThreadOffset<kMipsWordSize> offset ATTRIBUTE_UNUSED,
   2879                                      ManagedRegister mscratch ATTRIBUTE_UNUSED) {
   2880   UNIMPLEMENTED(FATAL) << "no mips implementation";
   2881 }
   2882 
   2883 void MipsAssembler::GetCurrentThread(ManagedRegister tr) {
   2884   Move(tr.AsMips().AsCoreRegister(), S1);
   2885 }
   2886 
   2887 void MipsAssembler::GetCurrentThread(FrameOffset offset,
   2888                                      ManagedRegister mscratch ATTRIBUTE_UNUSED) {
   2889   StoreToOffset(kStoreWord, S1, SP, offset.Int32Value());
   2890 }
   2891 
   2892 void MipsAssembler::ExceptionPoll(ManagedRegister mscratch, size_t stack_adjust) {
   2893   MipsManagedRegister scratch = mscratch.AsMips();
   2894   exception_blocks_.emplace_back(scratch, stack_adjust);
   2895   LoadFromOffset(kLoadWord, scratch.AsCoreRegister(),
   2896                  S1, Thread::ExceptionOffset<kMipsWordSize>().Int32Value());
   2897   // TODO: on MIPS32R6 prefer Bnezc(scratch.AsCoreRegister(), slow.Entry());
   2898   // as the NAL instruction (occurring in long R2 branches) may become deprecated.
   2899   // For now use common for R2 and R6 instructions as this code must execute on both.
   2900   Bnez(scratch.AsCoreRegister(), exception_blocks_.back().Entry());
   2901 }
   2902 
   2903 void MipsAssembler::EmitExceptionPoll(MipsExceptionSlowPath* exception) {
   2904   Bind(exception->Entry());
   2905   if (exception->stack_adjust_ != 0) {  // Fix up the frame.
   2906     DecreaseFrameSize(exception->stack_adjust_);
   2907   }
   2908   // Pass exception object as argument.
   2909   // Don't care about preserving A0 as this call won't return.
   2910   CheckEntrypointTypes<kQuickDeliverException, void, mirror::Object*>();
   2911   Move(A0, exception->scratch_.AsCoreRegister());
   2912   // Set up call to Thread::Current()->pDeliverException.
   2913   LoadFromOffset(kLoadWord, T9, S1,
   2914     QUICK_ENTRYPOINT_OFFSET(kMipsWordSize, pDeliverException).Int32Value());
   2915   Jr(T9);
   2916   Nop();
   2917 
   2918   // Call never returns.
   2919   Break();
   2920 }
   2921 
   2922 }  // namespace mips
   2923 }  // namespace art
   2924