Home | History | Annotate | Download | only in mips64
      1 /*
      2  * Copyright (C) 2014 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_mips64.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 mips64 {
     28 
     29 static_assert(static_cast<size_t>(kMips64PointerSize) == kMips64DoublewordSize,
     30               "Unexpected Mips64 pointer size.");
     31 static_assert(kMips64PointerSize == PointerSize::k64, "Unexpected Mips64 pointer size.");
     32 
     33 
     34 void Mips64Assembler::FinalizeCode() {
     35   for (auto& exception_block : exception_blocks_) {
     36     EmitExceptionPoll(&exception_block);
     37   }
     38   ReserveJumpTableSpace();
     39   EmitLiterals();
     40   PromoteBranches();
     41 }
     42 
     43 void Mips64Assembler::FinalizeInstructions(const MemoryRegion& region) {
     44   EmitBranches();
     45   EmitJumpTables();
     46   Assembler::FinalizeInstructions(region);
     47   PatchCFI();
     48 }
     49 
     50 void Mips64Assembler::PatchCFI() {
     51   if (cfi().NumberOfDelayedAdvancePCs() == 0u) {
     52     return;
     53   }
     54 
     55   typedef DebugFrameOpCodeWriterForAssembler::DelayedAdvancePC DelayedAdvancePC;
     56   const auto data = cfi().ReleaseStreamAndPrepareForDelayedAdvancePC();
     57   const std::vector<uint8_t>& old_stream = data.first;
     58   const std::vector<DelayedAdvancePC>& advances = data.second;
     59 
     60   // Refill our data buffer with patched opcodes.
     61   cfi().ReserveCFIStream(old_stream.size() + advances.size() + 16);
     62   size_t stream_pos = 0;
     63   for (const DelayedAdvancePC& advance : advances) {
     64     DCHECK_GE(advance.stream_pos, stream_pos);
     65     // Copy old data up to the point where advance was issued.
     66     cfi().AppendRawData(old_stream, stream_pos, advance.stream_pos);
     67     stream_pos = advance.stream_pos;
     68     // Insert the advance command with its final offset.
     69     size_t final_pc = GetAdjustedPosition(advance.pc);
     70     cfi().AdvancePC(final_pc);
     71   }
     72   // Copy the final segment if any.
     73   cfi().AppendRawData(old_stream, stream_pos, old_stream.size());
     74 }
     75 
     76 void Mips64Assembler::EmitBranches() {
     77   CHECK(!overwriting_);
     78   // Switch from appending instructions at the end of the buffer to overwriting
     79   // existing instructions (branch placeholders) in the buffer.
     80   overwriting_ = true;
     81   for (auto& branch : branches_) {
     82     EmitBranch(&branch);
     83   }
     84   overwriting_ = false;
     85 }
     86 
     87 void Mips64Assembler::Emit(uint32_t value) {
     88   if (overwriting_) {
     89     // Branches to labels are emitted into their placeholders here.
     90     buffer_.Store<uint32_t>(overwrite_location_, value);
     91     overwrite_location_ += sizeof(uint32_t);
     92   } else {
     93     // Other instructions are simply appended at the end here.
     94     AssemblerBuffer::EnsureCapacity ensured(&buffer_);
     95     buffer_.Emit<uint32_t>(value);
     96   }
     97 }
     98 
     99 void Mips64Assembler::EmitR(int opcode, GpuRegister rs, GpuRegister rt, GpuRegister rd,
    100                             int shamt, int funct) {
    101   CHECK_NE(rs, kNoGpuRegister);
    102   CHECK_NE(rt, kNoGpuRegister);
    103   CHECK_NE(rd, kNoGpuRegister);
    104   uint32_t encoding = static_cast<uint32_t>(opcode) << kOpcodeShift |
    105                       static_cast<uint32_t>(rs) << kRsShift |
    106                       static_cast<uint32_t>(rt) << kRtShift |
    107                       static_cast<uint32_t>(rd) << kRdShift |
    108                       shamt << kShamtShift |
    109                       funct;
    110   Emit(encoding);
    111 }
    112 
    113 void Mips64Assembler::EmitRsd(int opcode, GpuRegister rs, GpuRegister rd,
    114                               int shamt, int funct) {
    115   CHECK_NE(rs, kNoGpuRegister);
    116   CHECK_NE(rd, kNoGpuRegister);
    117   uint32_t encoding = static_cast<uint32_t>(opcode) << kOpcodeShift |
    118                       static_cast<uint32_t>(rs) << kRsShift |
    119                       static_cast<uint32_t>(ZERO) << kRtShift |
    120                       static_cast<uint32_t>(rd) << kRdShift |
    121                       shamt << kShamtShift |
    122                       funct;
    123   Emit(encoding);
    124 }
    125 
    126 void Mips64Assembler::EmitRtd(int opcode, GpuRegister rt, GpuRegister rd,
    127                               int shamt, int funct) {
    128   CHECK_NE(rt, kNoGpuRegister);
    129   CHECK_NE(rd, kNoGpuRegister);
    130   uint32_t encoding = static_cast<uint32_t>(opcode) << kOpcodeShift |
    131                       static_cast<uint32_t>(ZERO) << kRsShift |
    132                       static_cast<uint32_t>(rt) << kRtShift |
    133                       static_cast<uint32_t>(rd) << kRdShift |
    134                       shamt << kShamtShift |
    135                       funct;
    136   Emit(encoding);
    137 }
    138 
    139 void Mips64Assembler::EmitI(int opcode, GpuRegister rs, GpuRegister rt, uint16_t imm) {
    140   CHECK_NE(rs, kNoGpuRegister);
    141   CHECK_NE(rt, kNoGpuRegister);
    142   uint32_t encoding = static_cast<uint32_t>(opcode) << kOpcodeShift |
    143                       static_cast<uint32_t>(rs) << kRsShift |
    144                       static_cast<uint32_t>(rt) << kRtShift |
    145                       imm;
    146   Emit(encoding);
    147 }
    148 
    149 void Mips64Assembler::EmitI21(int opcode, GpuRegister rs, uint32_t imm21) {
    150   CHECK_NE(rs, kNoGpuRegister);
    151   CHECK(IsUint<21>(imm21)) << imm21;
    152   uint32_t encoding = static_cast<uint32_t>(opcode) << kOpcodeShift |
    153                       static_cast<uint32_t>(rs) << kRsShift |
    154                       imm21;
    155   Emit(encoding);
    156 }
    157 
    158 void Mips64Assembler::EmitI26(int opcode, uint32_t imm26) {
    159   CHECK(IsUint<26>(imm26)) << imm26;
    160   uint32_t encoding = static_cast<uint32_t>(opcode) << kOpcodeShift | imm26;
    161   Emit(encoding);
    162 }
    163 
    164 void Mips64Assembler::EmitFR(int opcode, int fmt, FpuRegister ft, FpuRegister fs, FpuRegister fd,
    165                              int funct) {
    166   CHECK_NE(ft, kNoFpuRegister);
    167   CHECK_NE(fs, kNoFpuRegister);
    168   CHECK_NE(fd, kNoFpuRegister);
    169   uint32_t encoding = static_cast<uint32_t>(opcode) << kOpcodeShift |
    170                       fmt << kFmtShift |
    171                       static_cast<uint32_t>(ft) << kFtShift |
    172                       static_cast<uint32_t>(fs) << kFsShift |
    173                       static_cast<uint32_t>(fd) << kFdShift |
    174                       funct;
    175   Emit(encoding);
    176 }
    177 
    178 void Mips64Assembler::EmitFI(int opcode, int fmt, FpuRegister ft, uint16_t imm) {
    179   CHECK_NE(ft, kNoFpuRegister);
    180   uint32_t encoding = static_cast<uint32_t>(opcode) << kOpcodeShift |
    181                       fmt << kFmtShift |
    182                       static_cast<uint32_t>(ft) << kFtShift |
    183                       imm;
    184   Emit(encoding);
    185 }
    186 
    187 void Mips64Assembler::EmitMsa3R(int operation,
    188                                 int df,
    189                                 VectorRegister wt,
    190                                 VectorRegister ws,
    191                                 VectorRegister wd,
    192                                 int minor_opcode) {
    193   CHECK_NE(wt, kNoVectorRegister);
    194   CHECK_NE(ws, kNoVectorRegister);
    195   CHECK_NE(wd, kNoVectorRegister);
    196   uint32_t encoding = static_cast<uint32_t>(kMsaMajorOpcode) << kOpcodeShift |
    197                       operation << kMsaOperationShift |
    198                       df << kDfShift |
    199                       static_cast<uint32_t>(wt) << kWtShift |
    200                       static_cast<uint32_t>(ws) << kWsShift |
    201                       static_cast<uint32_t>(wd) << kWdShift |
    202                       minor_opcode;
    203   Emit(encoding);
    204 }
    205 
    206 void Mips64Assembler::EmitMsaBIT(int operation,
    207                                  int df_m,
    208                                  VectorRegister ws,
    209                                  VectorRegister wd,
    210                                  int minor_opcode) {
    211   CHECK_NE(ws, kNoVectorRegister);
    212   CHECK_NE(wd, kNoVectorRegister);
    213   uint32_t encoding = static_cast<uint32_t>(kMsaMajorOpcode) << kOpcodeShift |
    214                       operation << kMsaOperationShift |
    215                       df_m << kDfMShift |
    216                       static_cast<uint32_t>(ws) << kWsShift |
    217                       static_cast<uint32_t>(wd) << kWdShift |
    218                       minor_opcode;
    219   Emit(encoding);
    220 }
    221 
    222 void Mips64Assembler::EmitMsaELM(int operation,
    223                                  int df_n,
    224                                  VectorRegister ws,
    225                                  VectorRegister wd,
    226                                  int minor_opcode) {
    227   CHECK_NE(ws, kNoVectorRegister);
    228   CHECK_NE(wd, kNoVectorRegister);
    229   uint32_t encoding = static_cast<uint32_t>(kMsaMajorOpcode) << kOpcodeShift |
    230                       operation << kMsaELMOperationShift |
    231                       df_n << kDfNShift |
    232                       static_cast<uint32_t>(ws) << kWsShift |
    233                       static_cast<uint32_t>(wd) << kWdShift |
    234                       minor_opcode;
    235   Emit(encoding);
    236 }
    237 
    238 void Mips64Assembler::EmitMsaMI10(int s10,
    239                                   GpuRegister rs,
    240                                   VectorRegister wd,
    241                                   int minor_opcode,
    242                                   int df) {
    243   CHECK_NE(rs, kNoGpuRegister);
    244   CHECK_NE(wd, kNoVectorRegister);
    245   CHECK(IsUint<10>(s10)) << s10;
    246   uint32_t encoding = static_cast<uint32_t>(kMsaMajorOpcode) << kOpcodeShift |
    247                       s10 << kS10Shift |
    248                       static_cast<uint32_t>(rs) << kWsShift |
    249                       static_cast<uint32_t>(wd) << kWdShift |
    250                       minor_opcode << kS10MinorShift |
    251                       df;
    252   Emit(encoding);
    253 }
    254 
    255 void Mips64Assembler::EmitMsaI10(int operation,
    256                                  int df,
    257                                  int i10,
    258                                  VectorRegister wd,
    259                                  int minor_opcode) {
    260   CHECK_NE(wd, kNoVectorRegister);
    261   CHECK(IsUint<10>(i10)) << i10;
    262   uint32_t encoding = static_cast<uint32_t>(kMsaMajorOpcode) << kOpcodeShift |
    263                       operation << kMsaOperationShift |
    264                       df << kDfShift |
    265                       i10 << kI10Shift |
    266                       static_cast<uint32_t>(wd) << kWdShift |
    267                       minor_opcode;
    268   Emit(encoding);
    269 }
    270 
    271 void Mips64Assembler::EmitMsa2R(int operation,
    272                                 int df,
    273                                 VectorRegister ws,
    274                                 VectorRegister wd,
    275                                 int minor_opcode) {
    276   CHECK_NE(ws, kNoVectorRegister);
    277   CHECK_NE(wd, kNoVectorRegister);
    278   uint32_t encoding = static_cast<uint32_t>(kMsaMajorOpcode) << kOpcodeShift |
    279                       operation << kMsa2ROperationShift |
    280                       df << kDf2RShift |
    281                       static_cast<uint32_t>(ws) << kWsShift |
    282                       static_cast<uint32_t>(wd) << kWdShift |
    283                       minor_opcode;
    284   Emit(encoding);
    285 }
    286 
    287 void Mips64Assembler::EmitMsa2RF(int operation,
    288                                  int df,
    289                                  VectorRegister ws,
    290                                  VectorRegister wd,
    291                                  int minor_opcode) {
    292   CHECK_NE(ws, kNoVectorRegister);
    293   CHECK_NE(wd, kNoVectorRegister);
    294   uint32_t encoding = static_cast<uint32_t>(kMsaMajorOpcode) << kOpcodeShift |
    295                       operation << kMsa2RFOperationShift |
    296                       df << kDf2RShift |
    297                       static_cast<uint32_t>(ws) << kWsShift |
    298                       static_cast<uint32_t>(wd) << kWdShift |
    299                       minor_opcode;
    300   Emit(encoding);
    301 }
    302 
    303 void Mips64Assembler::Addu(GpuRegister rd, GpuRegister rs, GpuRegister rt) {
    304   EmitR(0, rs, rt, rd, 0, 0x21);
    305 }
    306 
    307 void Mips64Assembler::Addiu(GpuRegister rt, GpuRegister rs, uint16_t imm16) {
    308   EmitI(0x9, rs, rt, imm16);
    309 }
    310 
    311 void Mips64Assembler::Daddu(GpuRegister rd, GpuRegister rs, GpuRegister rt) {
    312   EmitR(0, rs, rt, rd, 0, 0x2d);
    313 }
    314 
    315 void Mips64Assembler::Daddiu(GpuRegister rt, GpuRegister rs, uint16_t imm16) {
    316   EmitI(0x19, rs, rt, imm16);
    317 }
    318 
    319 void Mips64Assembler::Subu(GpuRegister rd, GpuRegister rs, GpuRegister rt) {
    320   EmitR(0, rs, rt, rd, 0, 0x23);
    321 }
    322 
    323 void Mips64Assembler::Dsubu(GpuRegister rd, GpuRegister rs, GpuRegister rt) {
    324   EmitR(0, rs, rt, rd, 0, 0x2f);
    325 }
    326 
    327 void Mips64Assembler::MulR6(GpuRegister rd, GpuRegister rs, GpuRegister rt) {
    328   EmitR(0, rs, rt, rd, 2, 0x18);
    329 }
    330 
    331 void Mips64Assembler::MuhR6(GpuRegister rd, GpuRegister rs, GpuRegister rt) {
    332   EmitR(0, rs, rt, rd, 3, 0x18);
    333 }
    334 
    335 void Mips64Assembler::DivR6(GpuRegister rd, GpuRegister rs, GpuRegister rt) {
    336   EmitR(0, rs, rt, rd, 2, 0x1a);
    337 }
    338 
    339 void Mips64Assembler::ModR6(GpuRegister rd, GpuRegister rs, GpuRegister rt) {
    340   EmitR(0, rs, rt, rd, 3, 0x1a);
    341 }
    342 
    343 void Mips64Assembler::DivuR6(GpuRegister rd, GpuRegister rs, GpuRegister rt) {
    344   EmitR(0, rs, rt, rd, 2, 0x1b);
    345 }
    346 
    347 void Mips64Assembler::ModuR6(GpuRegister rd, GpuRegister rs, GpuRegister rt) {
    348   EmitR(0, rs, rt, rd, 3, 0x1b);
    349 }
    350 
    351 void Mips64Assembler::Dmul(GpuRegister rd, GpuRegister rs, GpuRegister rt) {
    352   EmitR(0, rs, rt, rd, 2, 0x1c);
    353 }
    354 
    355 void Mips64Assembler::Dmuh(GpuRegister rd, GpuRegister rs, GpuRegister rt) {
    356   EmitR(0, rs, rt, rd, 3, 0x1c);
    357 }
    358 
    359 void Mips64Assembler::Ddiv(GpuRegister rd, GpuRegister rs, GpuRegister rt) {
    360   EmitR(0, rs, rt, rd, 2, 0x1e);
    361 }
    362 
    363 void Mips64Assembler::Dmod(GpuRegister rd, GpuRegister rs, GpuRegister rt) {
    364   EmitR(0, rs, rt, rd, 3, 0x1e);
    365 }
    366 
    367 void Mips64Assembler::Ddivu(GpuRegister rd, GpuRegister rs, GpuRegister rt) {
    368   EmitR(0, rs, rt, rd, 2, 0x1f);
    369 }
    370 
    371 void Mips64Assembler::Dmodu(GpuRegister rd, GpuRegister rs, GpuRegister rt) {
    372   EmitR(0, rs, rt, rd, 3, 0x1f);
    373 }
    374 
    375 void Mips64Assembler::And(GpuRegister rd, GpuRegister rs, GpuRegister rt) {
    376   EmitR(0, rs, rt, rd, 0, 0x24);
    377 }
    378 
    379 void Mips64Assembler::Andi(GpuRegister rt, GpuRegister rs, uint16_t imm16) {
    380   EmitI(0xc, rs, rt, imm16);
    381 }
    382 
    383 void Mips64Assembler::Or(GpuRegister rd, GpuRegister rs, GpuRegister rt) {
    384   EmitR(0, rs, rt, rd, 0, 0x25);
    385 }
    386 
    387 void Mips64Assembler::Ori(GpuRegister rt, GpuRegister rs, uint16_t imm16) {
    388   EmitI(0xd, rs, rt, imm16);
    389 }
    390 
    391 void Mips64Assembler::Xor(GpuRegister rd, GpuRegister rs, GpuRegister rt) {
    392   EmitR(0, rs, rt, rd, 0, 0x26);
    393 }
    394 
    395 void Mips64Assembler::Xori(GpuRegister rt, GpuRegister rs, uint16_t imm16) {
    396   EmitI(0xe, rs, rt, imm16);
    397 }
    398 
    399 void Mips64Assembler::Nor(GpuRegister rd, GpuRegister rs, GpuRegister rt) {
    400   EmitR(0, rs, rt, rd, 0, 0x27);
    401 }
    402 
    403 void Mips64Assembler::Bitswap(GpuRegister rd, GpuRegister rt) {
    404   EmitRtd(0x1f, rt, rd, 0x0, 0x20);
    405 }
    406 
    407 void Mips64Assembler::Dbitswap(GpuRegister rd, GpuRegister rt) {
    408   EmitRtd(0x1f, rt, rd, 0x0, 0x24);
    409 }
    410 
    411 void Mips64Assembler::Seb(GpuRegister rd, GpuRegister rt) {
    412   EmitR(0x1f, static_cast<GpuRegister>(0), rt, rd, 0x10, 0x20);
    413 }
    414 
    415 void Mips64Assembler::Seh(GpuRegister rd, GpuRegister rt) {
    416   EmitR(0x1f, static_cast<GpuRegister>(0), rt, rd, 0x18, 0x20);
    417 }
    418 
    419 void Mips64Assembler::Dsbh(GpuRegister rd, GpuRegister rt) {
    420   EmitRtd(0x1f, rt, rd, 0x2, 0x24);
    421 }
    422 
    423 void Mips64Assembler::Dshd(GpuRegister rd, GpuRegister rt) {
    424   EmitRtd(0x1f, rt, rd, 0x5, 0x24);
    425 }
    426 
    427 void Mips64Assembler::Dext(GpuRegister rt, GpuRegister rs, int pos, int size) {
    428   CHECK(IsUint<5>(pos)) << pos;
    429   CHECK(IsUint<5>(size - 1)) << size;
    430   EmitR(0x1f, rs, rt, static_cast<GpuRegister>(size - 1), pos, 0x3);
    431 }
    432 
    433 void Mips64Assembler::Dinsu(GpuRegister rt, GpuRegister rs, int pos, int size) {
    434   CHECK(IsUint<5>(pos - 32)) << pos;
    435   CHECK(IsUint<5>(size - 1)) << size;
    436   CHECK(IsUint<5>(pos + size - 33)) << pos << " + " << size;
    437   EmitR(0x1f, rs, rt, static_cast<GpuRegister>(pos + size - 33), pos - 32, 0x6);
    438 }
    439 
    440 void Mips64Assembler::Lsa(GpuRegister rd, GpuRegister rs, GpuRegister rt, int saPlusOne) {
    441   CHECK(1 <= saPlusOne && saPlusOne <= 4) << saPlusOne;
    442   int sa = saPlusOne - 1;
    443   EmitR(0x0, rs, rt, rd, sa, 0x05);
    444 }
    445 
    446 void Mips64Assembler::Dlsa(GpuRegister rd, GpuRegister rs, GpuRegister rt, int saPlusOne) {
    447   CHECK(1 <= saPlusOne && saPlusOne <= 4) << saPlusOne;
    448   int sa = saPlusOne - 1;
    449   EmitR(0x0, rs, rt, rd, sa, 0x15);
    450 }
    451 
    452 void Mips64Assembler::Wsbh(GpuRegister rd, GpuRegister rt) {
    453   EmitRtd(0x1f, rt, rd, 2, 0x20);
    454 }
    455 
    456 void Mips64Assembler::Sc(GpuRegister rt, GpuRegister base, int16_t imm9) {
    457   CHECK(IsInt<9>(imm9));
    458   EmitI(0x1f, base, rt, ((imm9 & 0x1FF) << 7) | 0x26);
    459 }
    460 
    461 void Mips64Assembler::Scd(GpuRegister rt, GpuRegister base, int16_t imm9) {
    462   CHECK(IsInt<9>(imm9));
    463   EmitI(0x1f, base, rt, ((imm9 & 0x1FF) << 7) | 0x27);
    464 }
    465 
    466 void Mips64Assembler::Ll(GpuRegister rt, GpuRegister base, int16_t imm9) {
    467   CHECK(IsInt<9>(imm9));
    468   EmitI(0x1f, base, rt, ((imm9 & 0x1FF) << 7) | 0x36);
    469 }
    470 
    471 void Mips64Assembler::Lld(GpuRegister rt, GpuRegister base, int16_t imm9) {
    472   CHECK(IsInt<9>(imm9));
    473   EmitI(0x1f, base, rt, ((imm9 & 0x1FF) << 7) | 0x37);
    474 }
    475 
    476 void Mips64Assembler::Sll(GpuRegister rd, GpuRegister rt, int shamt) {
    477   EmitR(0, static_cast<GpuRegister>(0), rt, rd, shamt, 0x00);
    478 }
    479 
    480 void Mips64Assembler::Srl(GpuRegister rd, GpuRegister rt, int shamt) {
    481   EmitR(0, static_cast<GpuRegister>(0), rt, rd, shamt, 0x02);
    482 }
    483 
    484 void Mips64Assembler::Rotr(GpuRegister rd, GpuRegister rt, int shamt) {
    485   EmitR(0, static_cast<GpuRegister>(1), rt, rd, shamt, 0x02);
    486 }
    487 
    488 void Mips64Assembler::Sra(GpuRegister rd, GpuRegister rt, int shamt) {
    489   EmitR(0, static_cast<GpuRegister>(0), rt, rd, shamt, 0x03);
    490 }
    491 
    492 void Mips64Assembler::Sllv(GpuRegister rd, GpuRegister rt, GpuRegister rs) {
    493   EmitR(0, rs, rt, rd, 0, 0x04);
    494 }
    495 
    496 void Mips64Assembler::Rotrv(GpuRegister rd, GpuRegister rt, GpuRegister rs) {
    497   EmitR(0, rs, rt, rd, 1, 0x06);
    498 }
    499 
    500 void Mips64Assembler::Srlv(GpuRegister rd, GpuRegister rt, GpuRegister rs) {
    501   EmitR(0, rs, rt, rd, 0, 0x06);
    502 }
    503 
    504 void Mips64Assembler::Srav(GpuRegister rd, GpuRegister rt, GpuRegister rs) {
    505   EmitR(0, rs, rt, rd, 0, 0x07);
    506 }
    507 
    508 void Mips64Assembler::Dsll(GpuRegister rd, GpuRegister rt, int shamt) {
    509   EmitR(0, static_cast<GpuRegister>(0), rt, rd, shamt, 0x38);
    510 }
    511 
    512 void Mips64Assembler::Dsrl(GpuRegister rd, GpuRegister rt, int shamt) {
    513   EmitR(0, static_cast<GpuRegister>(0), rt, rd, shamt, 0x3a);
    514 }
    515 
    516 void Mips64Assembler::Drotr(GpuRegister rd, GpuRegister rt, int shamt) {
    517   EmitR(0, static_cast<GpuRegister>(1), rt, rd, shamt, 0x3a);
    518 }
    519 
    520 void Mips64Assembler::Dsra(GpuRegister rd, GpuRegister rt, int shamt) {
    521   EmitR(0, static_cast<GpuRegister>(0), rt, rd, shamt, 0x3b);
    522 }
    523 
    524 void Mips64Assembler::Dsll32(GpuRegister rd, GpuRegister rt, int shamt) {
    525   EmitR(0, static_cast<GpuRegister>(0), rt, rd, shamt, 0x3c);
    526 }
    527 
    528 void Mips64Assembler::Dsrl32(GpuRegister rd, GpuRegister rt, int shamt) {
    529   EmitR(0, static_cast<GpuRegister>(0), rt, rd, shamt, 0x3e);
    530 }
    531 
    532 void Mips64Assembler::Drotr32(GpuRegister rd, GpuRegister rt, int shamt) {
    533   EmitR(0, static_cast<GpuRegister>(1), rt, rd, shamt, 0x3e);
    534 }
    535 
    536 void Mips64Assembler::Dsra32(GpuRegister rd, GpuRegister rt, int shamt) {
    537   EmitR(0, static_cast<GpuRegister>(0), rt, rd, shamt, 0x3f);
    538 }
    539 
    540 void Mips64Assembler::Dsllv(GpuRegister rd, GpuRegister rt, GpuRegister rs) {
    541   EmitR(0, rs, rt, rd, 0, 0x14);
    542 }
    543 
    544 void Mips64Assembler::Dsrlv(GpuRegister rd, GpuRegister rt, GpuRegister rs) {
    545   EmitR(0, rs, rt, rd, 0, 0x16);
    546 }
    547 
    548 void Mips64Assembler::Drotrv(GpuRegister rd, GpuRegister rt, GpuRegister rs) {
    549   EmitR(0, rs, rt, rd, 1, 0x16);
    550 }
    551 
    552 void Mips64Assembler::Dsrav(GpuRegister rd, GpuRegister rt, GpuRegister rs) {
    553   EmitR(0, rs, rt, rd, 0, 0x17);
    554 }
    555 
    556 void Mips64Assembler::Lb(GpuRegister rt, GpuRegister rs, uint16_t imm16) {
    557   EmitI(0x20, rs, rt, imm16);
    558 }
    559 
    560 void Mips64Assembler::Lh(GpuRegister rt, GpuRegister rs, uint16_t imm16) {
    561   EmitI(0x21, rs, rt, imm16);
    562 }
    563 
    564 void Mips64Assembler::Lw(GpuRegister rt, GpuRegister rs, uint16_t imm16) {
    565   EmitI(0x23, rs, rt, imm16);
    566 }
    567 
    568 void Mips64Assembler::Ld(GpuRegister rt, GpuRegister rs, uint16_t imm16) {
    569   EmitI(0x37, rs, rt, imm16);
    570 }
    571 
    572 void Mips64Assembler::Lbu(GpuRegister rt, GpuRegister rs, uint16_t imm16) {
    573   EmitI(0x24, rs, rt, imm16);
    574 }
    575 
    576 void Mips64Assembler::Lhu(GpuRegister rt, GpuRegister rs, uint16_t imm16) {
    577   EmitI(0x25, rs, rt, imm16);
    578 }
    579 
    580 void Mips64Assembler::Lwu(GpuRegister rt, GpuRegister rs, uint16_t imm16) {
    581   EmitI(0x27, rs, rt, imm16);
    582 }
    583 
    584 void Mips64Assembler::Lwpc(GpuRegister rs, uint32_t imm19) {
    585   CHECK(IsUint<19>(imm19)) << imm19;
    586   EmitI21(0x3B, rs, (0x01 << 19) | imm19);
    587 }
    588 
    589 void Mips64Assembler::Lwupc(GpuRegister rs, uint32_t imm19) {
    590   CHECK(IsUint<19>(imm19)) << imm19;
    591   EmitI21(0x3B, rs, (0x02 << 19) | imm19);
    592 }
    593 
    594 void Mips64Assembler::Ldpc(GpuRegister rs, uint32_t imm18) {
    595   CHECK(IsUint<18>(imm18)) << imm18;
    596   EmitI21(0x3B, rs, (0x06 << 18) | imm18);
    597 }
    598 
    599 void Mips64Assembler::Lui(GpuRegister rt, uint16_t imm16) {
    600   EmitI(0xf, static_cast<GpuRegister>(0), rt, imm16);
    601 }
    602 
    603 void Mips64Assembler::Aui(GpuRegister rt, GpuRegister rs, uint16_t imm16) {
    604   EmitI(0xf, rs, rt, imm16);
    605 }
    606 
    607 void Mips64Assembler::Daui(GpuRegister rt, GpuRegister rs, uint16_t imm16) {
    608   CHECK_NE(rs, ZERO);
    609   EmitI(0x1d, rs, rt, imm16);
    610 }
    611 
    612 void Mips64Assembler::Dahi(GpuRegister rs, uint16_t imm16) {
    613   EmitI(1, rs, static_cast<GpuRegister>(6), imm16);
    614 }
    615 
    616 void Mips64Assembler::Dati(GpuRegister rs, uint16_t imm16) {
    617   EmitI(1, rs, static_cast<GpuRegister>(0x1e), imm16);
    618 }
    619 
    620 void Mips64Assembler::Sync(uint32_t stype) {
    621   EmitR(0, static_cast<GpuRegister>(0), static_cast<GpuRegister>(0),
    622            static_cast<GpuRegister>(0), stype & 0x1f, 0xf);
    623 }
    624 
    625 void Mips64Assembler::Sb(GpuRegister rt, GpuRegister rs, uint16_t imm16) {
    626   EmitI(0x28, rs, rt, imm16);
    627 }
    628 
    629 void Mips64Assembler::Sh(GpuRegister rt, GpuRegister rs, uint16_t imm16) {
    630   EmitI(0x29, rs, rt, imm16);
    631 }
    632 
    633 void Mips64Assembler::Sw(GpuRegister rt, GpuRegister rs, uint16_t imm16) {
    634   EmitI(0x2b, rs, rt, imm16);
    635 }
    636 
    637 void Mips64Assembler::Sd(GpuRegister rt, GpuRegister rs, uint16_t imm16) {
    638   EmitI(0x3f, rs, rt, imm16);
    639 }
    640 
    641 void Mips64Assembler::Slt(GpuRegister rd, GpuRegister rs, GpuRegister rt) {
    642   EmitR(0, rs, rt, rd, 0, 0x2a);
    643 }
    644 
    645 void Mips64Assembler::Sltu(GpuRegister rd, GpuRegister rs, GpuRegister rt) {
    646   EmitR(0, rs, rt, rd, 0, 0x2b);
    647 }
    648 
    649 void Mips64Assembler::Slti(GpuRegister rt, GpuRegister rs, uint16_t imm16) {
    650   EmitI(0xa, rs, rt, imm16);
    651 }
    652 
    653 void Mips64Assembler::Sltiu(GpuRegister rt, GpuRegister rs, uint16_t imm16) {
    654   EmitI(0xb, rs, rt, imm16);
    655 }
    656 
    657 void Mips64Assembler::Seleqz(GpuRegister rd, GpuRegister rs, GpuRegister rt) {
    658   EmitR(0, rs, rt, rd, 0, 0x35);
    659 }
    660 
    661 void Mips64Assembler::Selnez(GpuRegister rd, GpuRegister rs, GpuRegister rt) {
    662   EmitR(0, rs, rt, rd, 0, 0x37);
    663 }
    664 
    665 void Mips64Assembler::Clz(GpuRegister rd, GpuRegister rs) {
    666   EmitRsd(0, rs, rd, 0x01, 0x10);
    667 }
    668 
    669 void Mips64Assembler::Clo(GpuRegister rd, GpuRegister rs) {
    670   EmitRsd(0, rs, rd, 0x01, 0x11);
    671 }
    672 
    673 void Mips64Assembler::Dclz(GpuRegister rd, GpuRegister rs) {
    674   EmitRsd(0, rs, rd, 0x01, 0x12);
    675 }
    676 
    677 void Mips64Assembler::Dclo(GpuRegister rd, GpuRegister rs) {
    678   EmitRsd(0, rs, rd, 0x01, 0x13);
    679 }
    680 
    681 void Mips64Assembler::Jalr(GpuRegister rd, GpuRegister rs) {
    682   EmitR(0, rs, static_cast<GpuRegister>(0), rd, 0, 0x09);
    683 }
    684 
    685 void Mips64Assembler::Jalr(GpuRegister rs) {
    686   Jalr(RA, rs);
    687 }
    688 
    689 void Mips64Assembler::Jr(GpuRegister rs) {
    690   Jalr(ZERO, rs);
    691 }
    692 
    693 void Mips64Assembler::Auipc(GpuRegister rs, uint16_t imm16) {
    694   EmitI(0x3B, rs, static_cast<GpuRegister>(0x1E), imm16);
    695 }
    696 
    697 void Mips64Assembler::Addiupc(GpuRegister rs, uint32_t imm19) {
    698   CHECK(IsUint<19>(imm19)) << imm19;
    699   EmitI21(0x3B, rs, imm19);
    700 }
    701 
    702 void Mips64Assembler::Bc(uint32_t imm26) {
    703   EmitI26(0x32, imm26);
    704 }
    705 
    706 void Mips64Assembler::Balc(uint32_t imm26) {
    707   EmitI26(0x3A, imm26);
    708 }
    709 
    710 void Mips64Assembler::Jic(GpuRegister rt, uint16_t imm16) {
    711   EmitI(0x36, static_cast<GpuRegister>(0), rt, imm16);
    712 }
    713 
    714 void Mips64Assembler::Jialc(GpuRegister rt, uint16_t imm16) {
    715   EmitI(0x3E, static_cast<GpuRegister>(0), rt, imm16);
    716 }
    717 
    718 void Mips64Assembler::Bltc(GpuRegister rs, GpuRegister rt, uint16_t imm16) {
    719   CHECK_NE(rs, ZERO);
    720   CHECK_NE(rt, ZERO);
    721   CHECK_NE(rs, rt);
    722   EmitI(0x17, rs, rt, imm16);
    723 }
    724 
    725 void Mips64Assembler::Bltzc(GpuRegister rt, uint16_t imm16) {
    726   CHECK_NE(rt, ZERO);
    727   EmitI(0x17, rt, rt, imm16);
    728 }
    729 
    730 void Mips64Assembler::Bgtzc(GpuRegister rt, uint16_t imm16) {
    731   CHECK_NE(rt, ZERO);
    732   EmitI(0x17, static_cast<GpuRegister>(0), rt, imm16);
    733 }
    734 
    735 void Mips64Assembler::Bgec(GpuRegister rs, GpuRegister rt, uint16_t imm16) {
    736   CHECK_NE(rs, ZERO);
    737   CHECK_NE(rt, ZERO);
    738   CHECK_NE(rs, rt);
    739   EmitI(0x16, rs, rt, imm16);
    740 }
    741 
    742 void Mips64Assembler::Bgezc(GpuRegister rt, uint16_t imm16) {
    743   CHECK_NE(rt, ZERO);
    744   EmitI(0x16, rt, rt, imm16);
    745 }
    746 
    747 void Mips64Assembler::Blezc(GpuRegister rt, uint16_t imm16) {
    748   CHECK_NE(rt, ZERO);
    749   EmitI(0x16, static_cast<GpuRegister>(0), rt, imm16);
    750 }
    751 
    752 void Mips64Assembler::Bltuc(GpuRegister rs, GpuRegister rt, uint16_t imm16) {
    753   CHECK_NE(rs, ZERO);
    754   CHECK_NE(rt, ZERO);
    755   CHECK_NE(rs, rt);
    756   EmitI(0x7, rs, rt, imm16);
    757 }
    758 
    759 void Mips64Assembler::Bgeuc(GpuRegister rs, GpuRegister rt, uint16_t imm16) {
    760   CHECK_NE(rs, ZERO);
    761   CHECK_NE(rt, ZERO);
    762   CHECK_NE(rs, rt);
    763   EmitI(0x6, rs, rt, imm16);
    764 }
    765 
    766 void Mips64Assembler::Beqc(GpuRegister rs, GpuRegister rt, uint16_t imm16) {
    767   CHECK_NE(rs, ZERO);
    768   CHECK_NE(rt, ZERO);
    769   CHECK_NE(rs, rt);
    770   EmitI(0x8, std::min(rs, rt), std::max(rs, rt), imm16);
    771 }
    772 
    773 void Mips64Assembler::Bnec(GpuRegister rs, GpuRegister rt, uint16_t imm16) {
    774   CHECK_NE(rs, ZERO);
    775   CHECK_NE(rt, ZERO);
    776   CHECK_NE(rs, rt);
    777   EmitI(0x18, std::min(rs, rt), std::max(rs, rt), imm16);
    778 }
    779 
    780 void Mips64Assembler::Beqzc(GpuRegister rs, uint32_t imm21) {
    781   CHECK_NE(rs, ZERO);
    782   EmitI21(0x36, rs, imm21);
    783 }
    784 
    785 void Mips64Assembler::Bnezc(GpuRegister rs, uint32_t imm21) {
    786   CHECK_NE(rs, ZERO);
    787   EmitI21(0x3E, rs, imm21);
    788 }
    789 
    790 void Mips64Assembler::Bc1eqz(FpuRegister ft, uint16_t imm16) {
    791   EmitFI(0x11, 0x9, ft, imm16);
    792 }
    793 
    794 void Mips64Assembler::Bc1nez(FpuRegister ft, uint16_t imm16) {
    795   EmitFI(0x11, 0xD, ft, imm16);
    796 }
    797 
    798 void Mips64Assembler::EmitBcondc(BranchCondition cond,
    799                                  GpuRegister rs,
    800                                  GpuRegister rt,
    801                                  uint32_t imm16_21) {
    802   switch (cond) {
    803     case kCondLT:
    804       Bltc(rs, rt, imm16_21);
    805       break;
    806     case kCondGE:
    807       Bgec(rs, rt, imm16_21);
    808       break;
    809     case kCondLE:
    810       Bgec(rt, rs, imm16_21);
    811       break;
    812     case kCondGT:
    813       Bltc(rt, rs, imm16_21);
    814       break;
    815     case kCondLTZ:
    816       CHECK_EQ(rt, ZERO);
    817       Bltzc(rs, imm16_21);
    818       break;
    819     case kCondGEZ:
    820       CHECK_EQ(rt, ZERO);
    821       Bgezc(rs, imm16_21);
    822       break;
    823     case kCondLEZ:
    824       CHECK_EQ(rt, ZERO);
    825       Blezc(rs, imm16_21);
    826       break;
    827     case kCondGTZ:
    828       CHECK_EQ(rt, ZERO);
    829       Bgtzc(rs, imm16_21);
    830       break;
    831     case kCondEQ:
    832       Beqc(rs, rt, imm16_21);
    833       break;
    834     case kCondNE:
    835       Bnec(rs, rt, imm16_21);
    836       break;
    837     case kCondEQZ:
    838       CHECK_EQ(rt, ZERO);
    839       Beqzc(rs, imm16_21);
    840       break;
    841     case kCondNEZ:
    842       CHECK_EQ(rt, ZERO);
    843       Bnezc(rs, imm16_21);
    844       break;
    845     case kCondLTU:
    846       Bltuc(rs, rt, imm16_21);
    847       break;
    848     case kCondGEU:
    849       Bgeuc(rs, rt, imm16_21);
    850       break;
    851     case kCondF:
    852       CHECK_EQ(rt, ZERO);
    853       Bc1eqz(static_cast<FpuRegister>(rs), imm16_21);
    854       break;
    855     case kCondT:
    856       CHECK_EQ(rt, ZERO);
    857       Bc1nez(static_cast<FpuRegister>(rs), imm16_21);
    858       break;
    859     case kUncond:
    860       LOG(FATAL) << "Unexpected branch condition " << cond;
    861       UNREACHABLE();
    862   }
    863 }
    864 
    865 void Mips64Assembler::AddS(FpuRegister fd, FpuRegister fs, FpuRegister ft) {
    866   EmitFR(0x11, 0x10, ft, fs, fd, 0x0);
    867 }
    868 
    869 void Mips64Assembler::SubS(FpuRegister fd, FpuRegister fs, FpuRegister ft) {
    870   EmitFR(0x11, 0x10, ft, fs, fd, 0x1);
    871 }
    872 
    873 void Mips64Assembler::MulS(FpuRegister fd, FpuRegister fs, FpuRegister ft) {
    874   EmitFR(0x11, 0x10, ft, fs, fd, 0x2);
    875 }
    876 
    877 void Mips64Assembler::DivS(FpuRegister fd, FpuRegister fs, FpuRegister ft) {
    878   EmitFR(0x11, 0x10, ft, fs, fd, 0x3);
    879 }
    880 
    881 void Mips64Assembler::AddD(FpuRegister fd, FpuRegister fs, FpuRegister ft) {
    882   EmitFR(0x11, 0x11, ft, fs, fd, 0x0);
    883 }
    884 
    885 void Mips64Assembler::SubD(FpuRegister fd, FpuRegister fs, FpuRegister ft) {
    886   EmitFR(0x11, 0x11, ft, fs, fd, 0x1);
    887 }
    888 
    889 void Mips64Assembler::MulD(FpuRegister fd, FpuRegister fs, FpuRegister ft) {
    890   EmitFR(0x11, 0x11, ft, fs, fd, 0x2);
    891 }
    892 
    893 void Mips64Assembler::DivD(FpuRegister fd, FpuRegister fs, FpuRegister ft) {
    894   EmitFR(0x11, 0x11, ft, fs, fd, 0x3);
    895 }
    896 
    897 void Mips64Assembler::SqrtS(FpuRegister fd, FpuRegister fs) {
    898   EmitFR(0x11, 0x10, static_cast<FpuRegister>(0), fs, fd, 0x4);
    899 }
    900 
    901 void Mips64Assembler::SqrtD(FpuRegister fd, FpuRegister fs) {
    902   EmitFR(0x11, 0x11, static_cast<FpuRegister>(0), fs, fd, 0x4);
    903 }
    904 
    905 void Mips64Assembler::AbsS(FpuRegister fd, FpuRegister fs) {
    906   EmitFR(0x11, 0x10, static_cast<FpuRegister>(0), fs, fd, 0x5);
    907 }
    908 
    909 void Mips64Assembler::AbsD(FpuRegister fd, FpuRegister fs) {
    910   EmitFR(0x11, 0x11, static_cast<FpuRegister>(0), fs, fd, 0x5);
    911 }
    912 
    913 void Mips64Assembler::MovS(FpuRegister fd, FpuRegister fs) {
    914   EmitFR(0x11, 0x10, static_cast<FpuRegister>(0), fs, fd, 0x6);
    915 }
    916 
    917 void Mips64Assembler::MovD(FpuRegister fd, FpuRegister fs) {
    918   EmitFR(0x11, 0x11, static_cast<FpuRegister>(0), fs, fd, 0x6);
    919 }
    920 
    921 void Mips64Assembler::NegS(FpuRegister fd, FpuRegister fs) {
    922   EmitFR(0x11, 0x10, static_cast<FpuRegister>(0), fs, fd, 0x7);
    923 }
    924 
    925 void Mips64Assembler::NegD(FpuRegister fd, FpuRegister fs) {
    926   EmitFR(0x11, 0x11, static_cast<FpuRegister>(0), fs, fd, 0x7);
    927 }
    928 
    929 void Mips64Assembler::RoundLS(FpuRegister fd, FpuRegister fs) {
    930   EmitFR(0x11, 0x10, static_cast<FpuRegister>(0), fs, fd, 0x8);
    931 }
    932 
    933 void Mips64Assembler::RoundLD(FpuRegister fd, FpuRegister fs) {
    934   EmitFR(0x11, 0x11, static_cast<FpuRegister>(0), fs, fd, 0x8);
    935 }
    936 
    937 void Mips64Assembler::RoundWS(FpuRegister fd, FpuRegister fs) {
    938   EmitFR(0x11, 0x10, static_cast<FpuRegister>(0), fs, fd, 0xc);
    939 }
    940 
    941 void Mips64Assembler::RoundWD(FpuRegister fd, FpuRegister fs) {
    942   EmitFR(0x11, 0x11, static_cast<FpuRegister>(0), fs, fd, 0xc);
    943 }
    944 
    945 void Mips64Assembler::TruncLS(FpuRegister fd, FpuRegister fs) {
    946   EmitFR(0x11, 0x10, static_cast<FpuRegister>(0), fs, fd, 0x9);
    947 }
    948 
    949 void Mips64Assembler::TruncLD(FpuRegister fd, FpuRegister fs) {
    950   EmitFR(0x11, 0x11, static_cast<FpuRegister>(0), fs, fd, 0x9);
    951 }
    952 
    953 void Mips64Assembler::TruncWS(FpuRegister fd, FpuRegister fs) {
    954   EmitFR(0x11, 0x10, static_cast<FpuRegister>(0), fs, fd, 0xd);
    955 }
    956 
    957 void Mips64Assembler::TruncWD(FpuRegister fd, FpuRegister fs) {
    958   EmitFR(0x11, 0x11, static_cast<FpuRegister>(0), fs, fd, 0xd);
    959 }
    960 
    961 void Mips64Assembler::CeilLS(FpuRegister fd, FpuRegister fs) {
    962   EmitFR(0x11, 0x10, static_cast<FpuRegister>(0), fs, fd, 0xa);
    963 }
    964 
    965 void Mips64Assembler::CeilLD(FpuRegister fd, FpuRegister fs) {
    966   EmitFR(0x11, 0x11, static_cast<FpuRegister>(0), fs, fd, 0xa);
    967 }
    968 
    969 void Mips64Assembler::CeilWS(FpuRegister fd, FpuRegister fs) {
    970   EmitFR(0x11, 0x10, static_cast<FpuRegister>(0), fs, fd, 0xe);
    971 }
    972 
    973 void Mips64Assembler::CeilWD(FpuRegister fd, FpuRegister fs) {
    974   EmitFR(0x11, 0x11, static_cast<FpuRegister>(0), fs, fd, 0xe);
    975 }
    976 
    977 void Mips64Assembler::FloorLS(FpuRegister fd, FpuRegister fs) {
    978   EmitFR(0x11, 0x10, static_cast<FpuRegister>(0), fs, fd, 0xb);
    979 }
    980 
    981 void Mips64Assembler::FloorLD(FpuRegister fd, FpuRegister fs) {
    982   EmitFR(0x11, 0x11, static_cast<FpuRegister>(0), fs, fd, 0xb);
    983 }
    984 
    985 void Mips64Assembler::FloorWS(FpuRegister fd, FpuRegister fs) {
    986   EmitFR(0x11, 0x10, static_cast<FpuRegister>(0), fs, fd, 0xf);
    987 }
    988 
    989 void Mips64Assembler::FloorWD(FpuRegister fd, FpuRegister fs) {
    990   EmitFR(0x11, 0x11, static_cast<FpuRegister>(0), fs, fd, 0xf);
    991 }
    992 
    993 void Mips64Assembler::SelS(FpuRegister fd, FpuRegister fs, FpuRegister ft) {
    994   EmitFR(0x11, 0x10, ft, fs, fd, 0x10);
    995 }
    996 
    997 void Mips64Assembler::SelD(FpuRegister fd, FpuRegister fs, FpuRegister ft) {
    998   EmitFR(0x11, 0x11, ft, fs, fd, 0x10);
    999 }
   1000 
   1001 void Mips64Assembler::RintS(FpuRegister fd, FpuRegister fs) {
   1002   EmitFR(0x11, 0x10, static_cast<FpuRegister>(0), fs, fd, 0x1a);
   1003 }
   1004 
   1005 void Mips64Assembler::RintD(FpuRegister fd, FpuRegister fs) {
   1006   EmitFR(0x11, 0x11, static_cast<FpuRegister>(0), fs, fd, 0x1a);
   1007 }
   1008 
   1009 void Mips64Assembler::ClassS(FpuRegister fd, FpuRegister fs) {
   1010   EmitFR(0x11, 0x10, static_cast<FpuRegister>(0), fs, fd, 0x1b);
   1011 }
   1012 
   1013 void Mips64Assembler::ClassD(FpuRegister fd, FpuRegister fs) {
   1014   EmitFR(0x11, 0x11, static_cast<FpuRegister>(0), fs, fd, 0x1b);
   1015 }
   1016 
   1017 void Mips64Assembler::MinS(FpuRegister fd, FpuRegister fs, FpuRegister ft) {
   1018   EmitFR(0x11, 0x10, ft, fs, fd, 0x1c);
   1019 }
   1020 
   1021 void Mips64Assembler::MinD(FpuRegister fd, FpuRegister fs, FpuRegister ft) {
   1022   EmitFR(0x11, 0x11, ft, fs, fd, 0x1c);
   1023 }
   1024 
   1025 void Mips64Assembler::MaxS(FpuRegister fd, FpuRegister fs, FpuRegister ft) {
   1026   EmitFR(0x11, 0x10, ft, fs, fd, 0x1e);
   1027 }
   1028 
   1029 void Mips64Assembler::MaxD(FpuRegister fd, FpuRegister fs, FpuRegister ft) {
   1030   EmitFR(0x11, 0x11, ft, fs, fd, 0x1e);
   1031 }
   1032 
   1033 void Mips64Assembler::CmpUnS(FpuRegister fd, FpuRegister fs, FpuRegister ft) {
   1034   EmitFR(0x11, 0x14, ft, fs, fd, 0x01);
   1035 }
   1036 
   1037 void Mips64Assembler::CmpEqS(FpuRegister fd, FpuRegister fs, FpuRegister ft) {
   1038   EmitFR(0x11, 0x14, ft, fs, fd, 0x02);
   1039 }
   1040 
   1041 void Mips64Assembler::CmpUeqS(FpuRegister fd, FpuRegister fs, FpuRegister ft) {
   1042   EmitFR(0x11, 0x14, ft, fs, fd, 0x03);
   1043 }
   1044 
   1045 void Mips64Assembler::CmpLtS(FpuRegister fd, FpuRegister fs, FpuRegister ft) {
   1046   EmitFR(0x11, 0x14, ft, fs, fd, 0x04);
   1047 }
   1048 
   1049 void Mips64Assembler::CmpUltS(FpuRegister fd, FpuRegister fs, FpuRegister ft) {
   1050   EmitFR(0x11, 0x14, ft, fs, fd, 0x05);
   1051 }
   1052 
   1053 void Mips64Assembler::CmpLeS(FpuRegister fd, FpuRegister fs, FpuRegister ft) {
   1054   EmitFR(0x11, 0x14, ft, fs, fd, 0x06);
   1055 }
   1056 
   1057 void Mips64Assembler::CmpUleS(FpuRegister fd, FpuRegister fs, FpuRegister ft) {
   1058   EmitFR(0x11, 0x14, ft, fs, fd, 0x07);
   1059 }
   1060 
   1061 void Mips64Assembler::CmpOrS(FpuRegister fd, FpuRegister fs, FpuRegister ft) {
   1062   EmitFR(0x11, 0x14, ft, fs, fd, 0x11);
   1063 }
   1064 
   1065 void Mips64Assembler::CmpUneS(FpuRegister fd, FpuRegister fs, FpuRegister ft) {
   1066   EmitFR(0x11, 0x14, ft, fs, fd, 0x12);
   1067 }
   1068 
   1069 void Mips64Assembler::CmpNeS(FpuRegister fd, FpuRegister fs, FpuRegister ft) {
   1070   EmitFR(0x11, 0x14, ft, fs, fd, 0x13);
   1071 }
   1072 
   1073 void Mips64Assembler::CmpUnD(FpuRegister fd, FpuRegister fs, FpuRegister ft) {
   1074   EmitFR(0x11, 0x15, ft, fs, fd, 0x01);
   1075 }
   1076 
   1077 void Mips64Assembler::CmpEqD(FpuRegister fd, FpuRegister fs, FpuRegister ft) {
   1078   EmitFR(0x11, 0x15, ft, fs, fd, 0x02);
   1079 }
   1080 
   1081 void Mips64Assembler::CmpUeqD(FpuRegister fd, FpuRegister fs, FpuRegister ft) {
   1082   EmitFR(0x11, 0x15, ft, fs, fd, 0x03);
   1083 }
   1084 
   1085 void Mips64Assembler::CmpLtD(FpuRegister fd, FpuRegister fs, FpuRegister ft) {
   1086   EmitFR(0x11, 0x15, ft, fs, fd, 0x04);
   1087 }
   1088 
   1089 void Mips64Assembler::CmpUltD(FpuRegister fd, FpuRegister fs, FpuRegister ft) {
   1090   EmitFR(0x11, 0x15, ft, fs, fd, 0x05);
   1091 }
   1092 
   1093 void Mips64Assembler::CmpLeD(FpuRegister fd, FpuRegister fs, FpuRegister ft) {
   1094   EmitFR(0x11, 0x15, ft, fs, fd, 0x06);
   1095 }
   1096 
   1097 void Mips64Assembler::CmpUleD(FpuRegister fd, FpuRegister fs, FpuRegister ft) {
   1098   EmitFR(0x11, 0x15, ft, fs, fd, 0x07);
   1099 }
   1100 
   1101 void Mips64Assembler::CmpOrD(FpuRegister fd, FpuRegister fs, FpuRegister ft) {
   1102   EmitFR(0x11, 0x15, ft, fs, fd, 0x11);
   1103 }
   1104 
   1105 void Mips64Assembler::CmpUneD(FpuRegister fd, FpuRegister fs, FpuRegister ft) {
   1106   EmitFR(0x11, 0x15, ft, fs, fd, 0x12);
   1107 }
   1108 
   1109 void Mips64Assembler::CmpNeD(FpuRegister fd, FpuRegister fs, FpuRegister ft) {
   1110   EmitFR(0x11, 0x15, ft, fs, fd, 0x13);
   1111 }
   1112 
   1113 void Mips64Assembler::Cvtsw(FpuRegister fd, FpuRegister fs) {
   1114   EmitFR(0x11, 0x14, static_cast<FpuRegister>(0), fs, fd, 0x20);
   1115 }
   1116 
   1117 void Mips64Assembler::Cvtdw(FpuRegister fd, FpuRegister fs) {
   1118   EmitFR(0x11, 0x14, static_cast<FpuRegister>(0), fs, fd, 0x21);
   1119 }
   1120 
   1121 void Mips64Assembler::Cvtsd(FpuRegister fd, FpuRegister fs) {
   1122   EmitFR(0x11, 0x11, static_cast<FpuRegister>(0), fs, fd, 0x20);
   1123 }
   1124 
   1125 void Mips64Assembler::Cvtds(FpuRegister fd, FpuRegister fs) {
   1126   EmitFR(0x11, 0x10, static_cast<FpuRegister>(0), fs, fd, 0x21);
   1127 }
   1128 
   1129 void Mips64Assembler::Cvtsl(FpuRegister fd, FpuRegister fs) {
   1130   EmitFR(0x11, 0x15, static_cast<FpuRegister>(0), fs, fd, 0x20);
   1131 }
   1132 
   1133 void Mips64Assembler::Cvtdl(FpuRegister fd, FpuRegister fs) {
   1134   EmitFR(0x11, 0x15, static_cast<FpuRegister>(0), fs, fd, 0x21);
   1135 }
   1136 
   1137 void Mips64Assembler::Mfc1(GpuRegister rt, FpuRegister fs) {
   1138   EmitFR(0x11, 0x00, static_cast<FpuRegister>(rt), fs, static_cast<FpuRegister>(0), 0x0);
   1139 }
   1140 
   1141 void Mips64Assembler::Mfhc1(GpuRegister rt, FpuRegister fs) {
   1142   EmitFR(0x11, 0x03, static_cast<FpuRegister>(rt), fs, static_cast<FpuRegister>(0), 0x0);
   1143 }
   1144 
   1145 void Mips64Assembler::Mtc1(GpuRegister rt, FpuRegister fs) {
   1146   EmitFR(0x11, 0x04, static_cast<FpuRegister>(rt), fs, static_cast<FpuRegister>(0), 0x0);
   1147 }
   1148 
   1149 void Mips64Assembler::Mthc1(GpuRegister rt, FpuRegister fs) {
   1150   EmitFR(0x11, 0x07, static_cast<FpuRegister>(rt), fs, static_cast<FpuRegister>(0), 0x0);
   1151 }
   1152 
   1153 void Mips64Assembler::Dmfc1(GpuRegister rt, FpuRegister fs) {
   1154   EmitFR(0x11, 0x01, static_cast<FpuRegister>(rt), fs, static_cast<FpuRegister>(0), 0x0);
   1155 }
   1156 
   1157 void Mips64Assembler::Dmtc1(GpuRegister rt, FpuRegister fs) {
   1158   EmitFR(0x11, 0x05, static_cast<FpuRegister>(rt), fs, static_cast<FpuRegister>(0), 0x0);
   1159 }
   1160 
   1161 void Mips64Assembler::Lwc1(FpuRegister ft, GpuRegister rs, uint16_t imm16) {
   1162   EmitI(0x31, rs, static_cast<GpuRegister>(ft), imm16);
   1163 }
   1164 
   1165 void Mips64Assembler::Ldc1(FpuRegister ft, GpuRegister rs, uint16_t imm16) {
   1166   EmitI(0x35, rs, static_cast<GpuRegister>(ft), imm16);
   1167 }
   1168 
   1169 void Mips64Assembler::Swc1(FpuRegister ft, GpuRegister rs, uint16_t imm16) {
   1170   EmitI(0x39, rs, static_cast<GpuRegister>(ft), imm16);
   1171 }
   1172 
   1173 void Mips64Assembler::Sdc1(FpuRegister ft, GpuRegister rs, uint16_t imm16) {
   1174   EmitI(0x3d, rs, static_cast<GpuRegister>(ft), imm16);
   1175 }
   1176 
   1177 void Mips64Assembler::Break() {
   1178   EmitR(0, static_cast<GpuRegister>(0), static_cast<GpuRegister>(0),
   1179         static_cast<GpuRegister>(0), 0, 0xD);
   1180 }
   1181 
   1182 void Mips64Assembler::Nop() {
   1183   EmitR(0x0, static_cast<GpuRegister>(0), static_cast<GpuRegister>(0),
   1184         static_cast<GpuRegister>(0), 0, 0x0);
   1185 }
   1186 
   1187 void Mips64Assembler::Move(GpuRegister rd, GpuRegister rs) {
   1188   Or(rd, rs, ZERO);
   1189 }
   1190 
   1191 void Mips64Assembler::Clear(GpuRegister rd) {
   1192   Move(rd, ZERO);
   1193 }
   1194 
   1195 void Mips64Assembler::Not(GpuRegister rd, GpuRegister rs) {
   1196   Nor(rd, rs, ZERO);
   1197 }
   1198 
   1199 void Mips64Assembler::AndV(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   1200   CHECK(HasMsa());
   1201   EmitMsa3R(0x0, 0x0, wt, ws, wd, 0x1e);
   1202 }
   1203 
   1204 void Mips64Assembler::OrV(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   1205   CHECK(HasMsa());
   1206   EmitMsa3R(0x0, 0x1, wt, ws, wd, 0x1e);
   1207 }
   1208 
   1209 void Mips64Assembler::NorV(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   1210   CHECK(HasMsa());
   1211   EmitMsa3R(0x0, 0x2, wt, ws, wd, 0x1e);
   1212 }
   1213 
   1214 void Mips64Assembler::XorV(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   1215   CHECK(HasMsa());
   1216   EmitMsa3R(0x0, 0x3, wt, ws, wd, 0x1e);
   1217 }
   1218 
   1219 void Mips64Assembler::AddvB(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   1220   CHECK(HasMsa());
   1221   EmitMsa3R(0x0, 0x0, wt, ws, wd, 0xe);
   1222 }
   1223 
   1224 void Mips64Assembler::AddvH(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   1225   CHECK(HasMsa());
   1226   EmitMsa3R(0x0, 0x1, wt, ws, wd, 0xe);
   1227 }
   1228 
   1229 void Mips64Assembler::AddvW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   1230   CHECK(HasMsa());
   1231   EmitMsa3R(0x0, 0x2, wt, ws, wd, 0xe);
   1232 }
   1233 
   1234 void Mips64Assembler::AddvD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   1235   CHECK(HasMsa());
   1236   EmitMsa3R(0x0, 0x3, wt, ws, wd, 0xe);
   1237 }
   1238 
   1239 void Mips64Assembler::SubvB(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   1240   CHECK(HasMsa());
   1241   EmitMsa3R(0x1, 0x0, wt, ws, wd, 0xe);
   1242 }
   1243 
   1244 void Mips64Assembler::SubvH(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   1245   CHECK(HasMsa());
   1246   EmitMsa3R(0x1, 0x1, wt, ws, wd, 0xe);
   1247 }
   1248 
   1249 void Mips64Assembler::SubvW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   1250   CHECK(HasMsa());
   1251   EmitMsa3R(0x1, 0x2, wt, ws, wd, 0xe);
   1252 }
   1253 
   1254 void Mips64Assembler::SubvD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   1255   CHECK(HasMsa());
   1256   EmitMsa3R(0x1, 0x3, wt, ws, wd, 0xe);
   1257 }
   1258 
   1259 void Mips64Assembler::MulvB(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   1260   CHECK(HasMsa());
   1261   EmitMsa3R(0x0, 0x0, wt, ws, wd, 0x12);
   1262 }
   1263 
   1264 void Mips64Assembler::MulvH(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   1265   CHECK(HasMsa());
   1266   EmitMsa3R(0x0, 0x1, wt, ws, wd, 0x12);
   1267 }
   1268 
   1269 void Mips64Assembler::MulvW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   1270   CHECK(HasMsa());
   1271   EmitMsa3R(0x0, 0x2, wt, ws, wd, 0x12);
   1272 }
   1273 
   1274 void Mips64Assembler::MulvD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   1275   CHECK(HasMsa());
   1276   EmitMsa3R(0x0, 0x3, wt, ws, wd, 0x12);
   1277 }
   1278 
   1279 void Mips64Assembler::Div_sB(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   1280   CHECK(HasMsa());
   1281   EmitMsa3R(0x4, 0x0, wt, ws, wd, 0x12);
   1282 }
   1283 
   1284 void Mips64Assembler::Div_sH(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   1285   CHECK(HasMsa());
   1286   EmitMsa3R(0x4, 0x1, wt, ws, wd, 0x12);
   1287 }
   1288 
   1289 void Mips64Assembler::Div_sW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   1290   CHECK(HasMsa());
   1291   EmitMsa3R(0x4, 0x2, wt, ws, wd, 0x12);
   1292 }
   1293 
   1294 void Mips64Assembler::Div_sD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   1295   CHECK(HasMsa());
   1296   EmitMsa3R(0x4, 0x3, wt, ws, wd, 0x12);
   1297 }
   1298 
   1299 void Mips64Assembler::Div_uB(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   1300   CHECK(HasMsa());
   1301   EmitMsa3R(0x5, 0x0, wt, ws, wd, 0x12);
   1302 }
   1303 
   1304 void Mips64Assembler::Div_uH(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   1305   CHECK(HasMsa());
   1306   EmitMsa3R(0x5, 0x1, wt, ws, wd, 0x12);
   1307 }
   1308 
   1309 void Mips64Assembler::Div_uW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   1310   CHECK(HasMsa());
   1311   EmitMsa3R(0x5, 0x2, wt, ws, wd, 0x12);
   1312 }
   1313 
   1314 void Mips64Assembler::Div_uD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   1315   CHECK(HasMsa());
   1316   EmitMsa3R(0x5, 0x3, wt, ws, wd, 0x12);
   1317 }
   1318 
   1319 void Mips64Assembler::Mod_sB(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   1320   CHECK(HasMsa());
   1321   EmitMsa3R(0x6, 0x0, wt, ws, wd, 0x12);
   1322 }
   1323 
   1324 void Mips64Assembler::Mod_sH(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   1325   CHECK(HasMsa());
   1326   EmitMsa3R(0x6, 0x1, wt, ws, wd, 0x12);
   1327 }
   1328 
   1329 void Mips64Assembler::Mod_sW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   1330   CHECK(HasMsa());
   1331   EmitMsa3R(0x6, 0x2, wt, ws, wd, 0x12);
   1332 }
   1333 
   1334 void Mips64Assembler::Mod_sD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   1335   CHECK(HasMsa());
   1336   EmitMsa3R(0x6, 0x3, wt, ws, wd, 0x12);
   1337 }
   1338 
   1339 void Mips64Assembler::Mod_uB(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   1340   CHECK(HasMsa());
   1341   EmitMsa3R(0x7, 0x0, wt, ws, wd, 0x12);
   1342 }
   1343 
   1344 void Mips64Assembler::Mod_uH(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   1345   CHECK(HasMsa());
   1346   EmitMsa3R(0x7, 0x1, wt, ws, wd, 0x12);
   1347 }
   1348 
   1349 void Mips64Assembler::Mod_uW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   1350   CHECK(HasMsa());
   1351   EmitMsa3R(0x7, 0x2, wt, ws, wd, 0x12);
   1352 }
   1353 
   1354 void Mips64Assembler::Mod_uD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   1355   CHECK(HasMsa());
   1356   EmitMsa3R(0x7, 0x3, wt, ws, wd, 0x12);
   1357 }
   1358 
   1359 void Mips64Assembler::FaddW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   1360   CHECK(HasMsa());
   1361   EmitMsa3R(0x0, 0x0, wt, ws, wd, 0x1b);
   1362 }
   1363 
   1364 void Mips64Assembler::FaddD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   1365   CHECK(HasMsa());
   1366   EmitMsa3R(0x0, 0x1, wt, ws, wd, 0x1b);
   1367 }
   1368 
   1369 void Mips64Assembler::FsubW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   1370   CHECK(HasMsa());
   1371   EmitMsa3R(0x0, 0x2, wt, ws, wd, 0x1b);
   1372 }
   1373 
   1374 void Mips64Assembler::FsubD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   1375   CHECK(HasMsa());
   1376   EmitMsa3R(0x0, 0x3, wt, ws, wd, 0x1b);
   1377 }
   1378 
   1379 void Mips64Assembler::FmulW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   1380   CHECK(HasMsa());
   1381   EmitMsa3R(0x1, 0x0, wt, ws, wd, 0x1b);
   1382 }
   1383 
   1384 void Mips64Assembler::FmulD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   1385   CHECK(HasMsa());
   1386   EmitMsa3R(0x1, 0x1, wt, ws, wd, 0x1b);
   1387 }
   1388 
   1389 void Mips64Assembler::FdivW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   1390   CHECK(HasMsa());
   1391   EmitMsa3R(0x1, 0x2, wt, ws, wd, 0x1b);
   1392 }
   1393 
   1394 void Mips64Assembler::FdivD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   1395   CHECK(HasMsa());
   1396   EmitMsa3R(0x1, 0x3, wt, ws, wd, 0x1b);
   1397 }
   1398 
   1399 void Mips64Assembler::Ffint_sW(VectorRegister wd, VectorRegister ws) {
   1400   CHECK(HasMsa());
   1401   EmitMsa2RF(0x19e, 0x0, ws, wd, 0x1e);
   1402 }
   1403 
   1404 void Mips64Assembler::Ffint_sD(VectorRegister wd, VectorRegister ws) {
   1405   CHECK(HasMsa());
   1406   EmitMsa2RF(0x19e, 0x1, ws, wd, 0x1e);
   1407 }
   1408 
   1409 void Mips64Assembler::Ftint_sW(VectorRegister wd, VectorRegister ws) {
   1410   CHECK(HasMsa());
   1411   EmitMsa2RF(0x19c, 0x0, ws, wd, 0x1e);
   1412 }
   1413 
   1414 void Mips64Assembler::Ftint_sD(VectorRegister wd, VectorRegister ws) {
   1415   CHECK(HasMsa());
   1416   EmitMsa2RF(0x19c, 0x1, ws, wd, 0x1e);
   1417 }
   1418 
   1419 void Mips64Assembler::SllB(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   1420   CHECK(HasMsa());
   1421   EmitMsa3R(0x0, 0x0, wt, ws, wd, 0xd);
   1422 }
   1423 
   1424 void Mips64Assembler::SllH(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   1425   CHECK(HasMsa());
   1426   EmitMsa3R(0x0, 0x1, wt, ws, wd, 0xd);
   1427 }
   1428 
   1429 void Mips64Assembler::SllW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   1430   CHECK(HasMsa());
   1431   EmitMsa3R(0x0, 0x2, wt, ws, wd, 0xd);
   1432 }
   1433 
   1434 void Mips64Assembler::SllD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   1435   CHECK(HasMsa());
   1436   EmitMsa3R(0x0, 0x3, wt, ws, wd, 0xd);
   1437 }
   1438 
   1439 void Mips64Assembler::SraB(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   1440   CHECK(HasMsa());
   1441   EmitMsa3R(0x1, 0x0, wt, ws, wd, 0xd);
   1442 }
   1443 
   1444 void Mips64Assembler::SraH(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   1445   CHECK(HasMsa());
   1446   EmitMsa3R(0x1, 0x1, wt, ws, wd, 0xd);
   1447 }
   1448 
   1449 void Mips64Assembler::SraW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   1450   CHECK(HasMsa());
   1451   EmitMsa3R(0x1, 0x2, wt, ws, wd, 0xd);
   1452 }
   1453 
   1454 void Mips64Assembler::SraD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   1455   CHECK(HasMsa());
   1456   EmitMsa3R(0x1, 0x3, wt, ws, wd, 0xd);
   1457 }
   1458 
   1459 void Mips64Assembler::SrlB(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   1460   CHECK(HasMsa());
   1461   EmitMsa3R(0x2, 0x0, wt, ws, wd, 0xd);
   1462 }
   1463 
   1464 void Mips64Assembler::SrlH(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   1465   CHECK(HasMsa());
   1466   EmitMsa3R(0x2, 0x1, wt, ws, wd, 0xd);
   1467 }
   1468 
   1469 void Mips64Assembler::SrlW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   1470   CHECK(HasMsa());
   1471   EmitMsa3R(0x2, 0x2, wt, ws, wd, 0xd);
   1472 }
   1473 
   1474 void Mips64Assembler::SrlD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   1475   CHECK(HasMsa());
   1476   EmitMsa3R(0x2, 0x3, wt, ws, wd, 0xd);
   1477 }
   1478 
   1479 void Mips64Assembler::SlliB(VectorRegister wd, VectorRegister ws, int shamt3) {
   1480   CHECK(HasMsa());
   1481   CHECK(IsUint<3>(shamt3)) << shamt3;
   1482   EmitMsaBIT(0x0, shamt3 | kMsaDfMByteMask, ws, wd, 0x9);
   1483 }
   1484 
   1485 void Mips64Assembler::SlliH(VectorRegister wd, VectorRegister ws, int shamt4) {
   1486   CHECK(HasMsa());
   1487   CHECK(IsUint<4>(shamt4)) << shamt4;
   1488   EmitMsaBIT(0x0, shamt4 | kMsaDfMHalfwordMask, ws, wd, 0x9);
   1489 }
   1490 
   1491 void Mips64Assembler::SlliW(VectorRegister wd, VectorRegister ws, int shamt5) {
   1492   CHECK(HasMsa());
   1493   CHECK(IsUint<5>(shamt5)) << shamt5;
   1494   EmitMsaBIT(0x0, shamt5 | kMsaDfMWordMask, ws, wd, 0x9);
   1495 }
   1496 
   1497 void Mips64Assembler::SlliD(VectorRegister wd, VectorRegister ws, int shamt6) {
   1498   CHECK(HasMsa());
   1499   CHECK(IsUint<6>(shamt6)) << shamt6;
   1500   EmitMsaBIT(0x0, shamt6 | kMsaDfMDoublewordMask, ws, wd, 0x9);
   1501 }
   1502 
   1503 void Mips64Assembler::SraiB(VectorRegister wd, VectorRegister ws, int shamt3) {
   1504   CHECK(HasMsa());
   1505   CHECK(IsUint<3>(shamt3)) << shamt3;
   1506   EmitMsaBIT(0x1, shamt3 | kMsaDfMByteMask, ws, wd, 0x9);
   1507 }
   1508 
   1509 void Mips64Assembler::SraiH(VectorRegister wd, VectorRegister ws, int shamt4) {
   1510   CHECK(HasMsa());
   1511   CHECK(IsUint<4>(shamt4)) << shamt4;
   1512   EmitMsaBIT(0x1, shamt4 | kMsaDfMHalfwordMask, ws, wd, 0x9);
   1513 }
   1514 
   1515 void Mips64Assembler::SraiW(VectorRegister wd, VectorRegister ws, int shamt5) {
   1516   CHECK(HasMsa());
   1517   CHECK(IsUint<5>(shamt5)) << shamt5;
   1518   EmitMsaBIT(0x1, shamt5 | kMsaDfMWordMask, ws, wd, 0x9);
   1519 }
   1520 
   1521 void Mips64Assembler::SraiD(VectorRegister wd, VectorRegister ws, int shamt6) {
   1522   CHECK(HasMsa());
   1523   CHECK(IsUint<6>(shamt6)) << shamt6;
   1524   EmitMsaBIT(0x1, shamt6 | kMsaDfMDoublewordMask, ws, wd, 0x9);
   1525 }
   1526 
   1527 void Mips64Assembler::SrliB(VectorRegister wd, VectorRegister ws, int shamt3) {
   1528   CHECK(HasMsa());
   1529   CHECK(IsUint<3>(shamt3)) << shamt3;
   1530   EmitMsaBIT(0x2, shamt3 | kMsaDfMByteMask, ws, wd, 0x9);
   1531 }
   1532 
   1533 void Mips64Assembler::SrliH(VectorRegister wd, VectorRegister ws, int shamt4) {
   1534   CHECK(HasMsa());
   1535   CHECK(IsUint<4>(shamt4)) << shamt4;
   1536   EmitMsaBIT(0x2, shamt4 | kMsaDfMHalfwordMask, ws, wd, 0x9);
   1537 }
   1538 
   1539 void Mips64Assembler::SrliW(VectorRegister wd, VectorRegister ws, int shamt5) {
   1540   CHECK(HasMsa());
   1541   CHECK(IsUint<5>(shamt5)) << shamt5;
   1542   EmitMsaBIT(0x2, shamt5 | kMsaDfMWordMask, ws, wd, 0x9);
   1543 }
   1544 
   1545 void Mips64Assembler::SrliD(VectorRegister wd, VectorRegister ws, int shamt6) {
   1546   CHECK(HasMsa());
   1547   CHECK(IsUint<6>(shamt6)) << shamt6;
   1548   EmitMsaBIT(0x2, shamt6 | kMsaDfMDoublewordMask, ws, wd, 0x9);
   1549 }
   1550 
   1551 void Mips64Assembler::MoveV(VectorRegister wd, VectorRegister ws) {
   1552   CHECK(HasMsa());
   1553   EmitMsaBIT(0x1, 0x3e, ws, wd, 0x19);
   1554 }
   1555 
   1556 void Mips64Assembler::SplatiB(VectorRegister wd, VectorRegister ws, int n4) {
   1557   CHECK(HasMsa());
   1558   CHECK(IsUint<4>(n4)) << n4;
   1559   EmitMsaELM(0x1, n4 | kMsaDfNByteMask, ws, wd, 0x19);
   1560 }
   1561 
   1562 void Mips64Assembler::SplatiH(VectorRegister wd, VectorRegister ws, int n3) {
   1563   CHECK(HasMsa());
   1564   CHECK(IsUint<3>(n3)) << n3;
   1565   EmitMsaELM(0x1, n3 | kMsaDfNHalfwordMask, ws, wd, 0x19);
   1566 }
   1567 
   1568 void Mips64Assembler::SplatiW(VectorRegister wd, VectorRegister ws, int n2) {
   1569   CHECK(HasMsa());
   1570   CHECK(IsUint<2>(n2)) << n2;
   1571   EmitMsaELM(0x1, n2 | kMsaDfNWordMask, ws, wd, 0x19);
   1572 }
   1573 
   1574 void Mips64Assembler::SplatiD(VectorRegister wd, VectorRegister ws, int n1) {
   1575   CHECK(HasMsa());
   1576   CHECK(IsUint<1>(n1)) << n1;
   1577   EmitMsaELM(0x1, n1 | kMsaDfNDoublewordMask, ws, wd, 0x19);
   1578 }
   1579 
   1580 void Mips64Assembler::FillB(VectorRegister wd, GpuRegister rs) {
   1581   CHECK(HasMsa());
   1582   EmitMsa2R(0xc0, 0x0, static_cast<VectorRegister>(rs), wd, 0x1e);
   1583 }
   1584 
   1585 void Mips64Assembler::FillH(VectorRegister wd, GpuRegister rs) {
   1586   CHECK(HasMsa());
   1587   EmitMsa2R(0xc0, 0x1, static_cast<VectorRegister>(rs), wd, 0x1e);
   1588 }
   1589 
   1590 void Mips64Assembler::FillW(VectorRegister wd, GpuRegister rs) {
   1591   CHECK(HasMsa());
   1592   EmitMsa2R(0xc0, 0x2, static_cast<VectorRegister>(rs), wd, 0x1e);
   1593 }
   1594 
   1595 void Mips64Assembler::FillD(VectorRegister wd, GpuRegister rs) {
   1596   CHECK(HasMsa());
   1597   EmitMsa2R(0xc0, 0x3, static_cast<VectorRegister>(rs), wd, 0x1e);
   1598 }
   1599 
   1600 void Mips64Assembler::LdiB(VectorRegister wd, int imm8) {
   1601   CHECK(HasMsa());
   1602   CHECK(IsInt<8>(imm8)) << imm8;
   1603   EmitMsaI10(0x6, 0x0, imm8 & kMsaS10Mask, wd, 0x7);
   1604 }
   1605 
   1606 void Mips64Assembler::LdiH(VectorRegister wd, int imm10) {
   1607   CHECK(HasMsa());
   1608   CHECK(IsInt<10>(imm10)) << imm10;
   1609   EmitMsaI10(0x6, 0x1, imm10 & kMsaS10Mask, wd, 0x7);
   1610 }
   1611 
   1612 void Mips64Assembler::LdiW(VectorRegister wd, int imm10) {
   1613   CHECK(HasMsa());
   1614   CHECK(IsInt<10>(imm10)) << imm10;
   1615   EmitMsaI10(0x6, 0x2, imm10 & kMsaS10Mask, wd, 0x7);
   1616 }
   1617 
   1618 void Mips64Assembler::LdiD(VectorRegister wd, int imm10) {
   1619   CHECK(HasMsa());
   1620   CHECK(IsInt<10>(imm10)) << imm10;
   1621   EmitMsaI10(0x6, 0x3, imm10 & kMsaS10Mask, wd, 0x7);
   1622 }
   1623 
   1624 void Mips64Assembler::LdB(VectorRegister wd, GpuRegister rs, int offset) {
   1625   CHECK(HasMsa());
   1626   CHECK(IsInt<10>(offset)) << offset;
   1627   EmitMsaMI10(offset & kMsaS10Mask, rs, wd, 0x8, 0x0);
   1628 }
   1629 
   1630 void Mips64Assembler::LdH(VectorRegister wd, GpuRegister rs, int offset) {
   1631   CHECK(HasMsa());
   1632   CHECK(IsInt<11>(offset)) << offset;
   1633   CHECK_ALIGNED(offset, kMips64HalfwordSize);
   1634   EmitMsaMI10((offset >> TIMES_2) & kMsaS10Mask, rs, wd, 0x8, 0x1);
   1635 }
   1636 
   1637 void Mips64Assembler::LdW(VectorRegister wd, GpuRegister rs, int offset) {
   1638   CHECK(HasMsa());
   1639   CHECK(IsInt<12>(offset)) << offset;
   1640   CHECK_ALIGNED(offset, kMips64WordSize);
   1641   EmitMsaMI10((offset >> TIMES_4) & kMsaS10Mask, rs, wd, 0x8, 0x2);
   1642 }
   1643 
   1644 void Mips64Assembler::LdD(VectorRegister wd, GpuRegister rs, int offset) {
   1645   CHECK(HasMsa());
   1646   CHECK(IsInt<13>(offset)) << offset;
   1647   CHECK_ALIGNED(offset, kMips64DoublewordSize);
   1648   EmitMsaMI10((offset >> TIMES_8) & kMsaS10Mask, rs, wd, 0x8, 0x3);
   1649 }
   1650 
   1651 void Mips64Assembler::StB(VectorRegister wd, GpuRegister rs, int offset) {
   1652   CHECK(HasMsa());
   1653   CHECK(IsInt<10>(offset)) << offset;
   1654   EmitMsaMI10(offset & kMsaS10Mask, rs, wd, 0x9, 0x0);
   1655 }
   1656 
   1657 void Mips64Assembler::StH(VectorRegister wd, GpuRegister rs, int offset) {
   1658   CHECK(HasMsa());
   1659   CHECK(IsInt<11>(offset)) << offset;
   1660   CHECK_ALIGNED(offset, kMips64HalfwordSize);
   1661   EmitMsaMI10((offset >> TIMES_2) & kMsaS10Mask, rs, wd, 0x9, 0x1);
   1662 }
   1663 
   1664 void Mips64Assembler::StW(VectorRegister wd, GpuRegister rs, int offset) {
   1665   CHECK(HasMsa());
   1666   CHECK(IsInt<12>(offset)) << offset;
   1667   CHECK_ALIGNED(offset, kMips64WordSize);
   1668   EmitMsaMI10((offset >> TIMES_4) & kMsaS10Mask, rs, wd, 0x9, 0x2);
   1669 }
   1670 
   1671 void Mips64Assembler::StD(VectorRegister wd, GpuRegister rs, int offset) {
   1672   CHECK(HasMsa());
   1673   CHECK(IsInt<13>(offset)) << offset;
   1674   CHECK_ALIGNED(offset, kMips64DoublewordSize);
   1675   EmitMsaMI10((offset >> TIMES_8) & kMsaS10Mask, rs, wd, 0x9, 0x3);
   1676 }
   1677 
   1678 void Mips64Assembler::LoadConst32(GpuRegister rd, int32_t value) {
   1679   TemplateLoadConst32(this, rd, value);
   1680 }
   1681 
   1682 // This function is only used for testing purposes.
   1683 void Mips64Assembler::RecordLoadConst64Path(int value ATTRIBUTE_UNUSED) {
   1684 }
   1685 
   1686 void Mips64Assembler::LoadConst64(GpuRegister rd, int64_t value) {
   1687   TemplateLoadConst64(this, rd, value);
   1688 }
   1689 
   1690 void Mips64Assembler::Addiu32(GpuRegister rt, GpuRegister rs, int32_t value) {
   1691   if (IsInt<16>(value)) {
   1692     Addiu(rt, rs, value);
   1693   } else {
   1694     int16_t high = High16Bits(value);
   1695     int16_t low = Low16Bits(value);
   1696     high += (low < 0) ? 1 : 0;  // Account for sign extension in addiu.
   1697     Aui(rt, rs, high);
   1698     if (low != 0) {
   1699       Addiu(rt, rt, low);
   1700     }
   1701   }
   1702 }
   1703 
   1704 // TODO: don't use rtmp, use daui, dahi, dati.
   1705 void Mips64Assembler::Daddiu64(GpuRegister rt, GpuRegister rs, int64_t value, GpuRegister rtmp) {
   1706   CHECK_NE(rs, rtmp);
   1707   if (IsInt<16>(value)) {
   1708     Daddiu(rt, rs, value);
   1709   } else {
   1710     LoadConst64(rtmp, value);
   1711     Daddu(rt, rs, rtmp);
   1712   }
   1713 }
   1714 
   1715 void Mips64Assembler::Branch::InitShortOrLong(Mips64Assembler::Branch::OffsetBits offset_size,
   1716                                               Mips64Assembler::Branch::Type short_type,
   1717                                               Mips64Assembler::Branch::Type long_type) {
   1718   type_ = (offset_size <= branch_info_[short_type].offset_size) ? short_type : long_type;
   1719 }
   1720 
   1721 void Mips64Assembler::Branch::InitializeType(Type initial_type) {
   1722   OffsetBits offset_size = GetOffsetSizeNeeded(location_, target_);
   1723   switch (initial_type) {
   1724     case kLabel:
   1725     case kLiteral:
   1726     case kLiteralUnsigned:
   1727     case kLiteralLong:
   1728       CHECK(!IsResolved());
   1729       type_ = initial_type;
   1730       break;
   1731     case kCall:
   1732       InitShortOrLong(offset_size, kCall, kLongCall);
   1733       break;
   1734     case kCondBranch:
   1735       switch (condition_) {
   1736         case kUncond:
   1737           InitShortOrLong(offset_size, kUncondBranch, kLongUncondBranch);
   1738           break;
   1739         case kCondEQZ:
   1740         case kCondNEZ:
   1741           // Special case for beqzc/bnezc with longer offset than in other b<cond>c instructions.
   1742           type_ = (offset_size <= kOffset23) ? kCondBranch : kLongCondBranch;
   1743           break;
   1744         default:
   1745           InitShortOrLong(offset_size, kCondBranch, kLongCondBranch);
   1746           break;
   1747       }
   1748       break;
   1749     default:
   1750       LOG(FATAL) << "Unexpected branch type " << initial_type;
   1751       UNREACHABLE();
   1752   }
   1753   old_type_ = type_;
   1754 }
   1755 
   1756 bool Mips64Assembler::Branch::IsNop(BranchCondition condition, GpuRegister lhs, GpuRegister rhs) {
   1757   switch (condition) {
   1758     case kCondLT:
   1759     case kCondGT:
   1760     case kCondNE:
   1761     case kCondLTU:
   1762       return lhs == rhs;
   1763     default:
   1764       return false;
   1765   }
   1766 }
   1767 
   1768 bool Mips64Assembler::Branch::IsUncond(BranchCondition condition,
   1769                                        GpuRegister lhs,
   1770                                        GpuRegister rhs) {
   1771   switch (condition) {
   1772     case kUncond:
   1773       return true;
   1774     case kCondGE:
   1775     case kCondLE:
   1776     case kCondEQ:
   1777     case kCondGEU:
   1778       return lhs == rhs;
   1779     default:
   1780       return false;
   1781   }
   1782 }
   1783 
   1784 Mips64Assembler::Branch::Branch(uint32_t location, uint32_t target, bool is_call)
   1785     : old_location_(location),
   1786       location_(location),
   1787       target_(target),
   1788       lhs_reg_(ZERO),
   1789       rhs_reg_(ZERO),
   1790       condition_(kUncond) {
   1791   InitializeType(is_call ? kCall : kCondBranch);
   1792 }
   1793 
   1794 Mips64Assembler::Branch::Branch(uint32_t location,
   1795                                 uint32_t target,
   1796                                 Mips64Assembler::BranchCondition condition,
   1797                                 GpuRegister lhs_reg,
   1798                                 GpuRegister rhs_reg)
   1799     : old_location_(location),
   1800       location_(location),
   1801       target_(target),
   1802       lhs_reg_(lhs_reg),
   1803       rhs_reg_(rhs_reg),
   1804       condition_(condition) {
   1805   CHECK_NE(condition, kUncond);
   1806   switch (condition) {
   1807     case kCondEQ:
   1808     case kCondNE:
   1809     case kCondLT:
   1810     case kCondGE:
   1811     case kCondLE:
   1812     case kCondGT:
   1813     case kCondLTU:
   1814     case kCondGEU:
   1815       CHECK_NE(lhs_reg, ZERO);
   1816       CHECK_NE(rhs_reg, ZERO);
   1817       break;
   1818     case kCondLTZ:
   1819     case kCondGEZ:
   1820     case kCondLEZ:
   1821     case kCondGTZ:
   1822     case kCondEQZ:
   1823     case kCondNEZ:
   1824       CHECK_NE(lhs_reg, ZERO);
   1825       CHECK_EQ(rhs_reg, ZERO);
   1826       break;
   1827     case kCondF:
   1828     case kCondT:
   1829       CHECK_EQ(rhs_reg, ZERO);
   1830       break;
   1831     case kUncond:
   1832       UNREACHABLE();
   1833   }
   1834   CHECK(!IsNop(condition, lhs_reg, rhs_reg));
   1835   if (IsUncond(condition, lhs_reg, rhs_reg)) {
   1836     // Branch condition is always true, make the branch unconditional.
   1837     condition_ = kUncond;
   1838   }
   1839   InitializeType(kCondBranch);
   1840 }
   1841 
   1842 Mips64Assembler::Branch::Branch(uint32_t location, GpuRegister dest_reg, Type label_or_literal_type)
   1843     : old_location_(location),
   1844       location_(location),
   1845       target_(kUnresolved),
   1846       lhs_reg_(dest_reg),
   1847       rhs_reg_(ZERO),
   1848       condition_(kUncond) {
   1849   CHECK_NE(dest_reg, ZERO);
   1850   InitializeType(label_or_literal_type);
   1851 }
   1852 
   1853 Mips64Assembler::BranchCondition Mips64Assembler::Branch::OppositeCondition(
   1854     Mips64Assembler::BranchCondition cond) {
   1855   switch (cond) {
   1856     case kCondLT:
   1857       return kCondGE;
   1858     case kCondGE:
   1859       return kCondLT;
   1860     case kCondLE:
   1861       return kCondGT;
   1862     case kCondGT:
   1863       return kCondLE;
   1864     case kCondLTZ:
   1865       return kCondGEZ;
   1866     case kCondGEZ:
   1867       return kCondLTZ;
   1868     case kCondLEZ:
   1869       return kCondGTZ;
   1870     case kCondGTZ:
   1871       return kCondLEZ;
   1872     case kCondEQ:
   1873       return kCondNE;
   1874     case kCondNE:
   1875       return kCondEQ;
   1876     case kCondEQZ:
   1877       return kCondNEZ;
   1878     case kCondNEZ:
   1879       return kCondEQZ;
   1880     case kCondLTU:
   1881       return kCondGEU;
   1882     case kCondGEU:
   1883       return kCondLTU;
   1884     case kCondF:
   1885       return kCondT;
   1886     case kCondT:
   1887       return kCondF;
   1888     case kUncond:
   1889       LOG(FATAL) << "Unexpected branch condition " << cond;
   1890   }
   1891   UNREACHABLE();
   1892 }
   1893 
   1894 Mips64Assembler::Branch::Type Mips64Assembler::Branch::GetType() const {
   1895   return type_;
   1896 }
   1897 
   1898 Mips64Assembler::BranchCondition Mips64Assembler::Branch::GetCondition() const {
   1899   return condition_;
   1900 }
   1901 
   1902 GpuRegister Mips64Assembler::Branch::GetLeftRegister() const {
   1903   return lhs_reg_;
   1904 }
   1905 
   1906 GpuRegister Mips64Assembler::Branch::GetRightRegister() const {
   1907   return rhs_reg_;
   1908 }
   1909 
   1910 uint32_t Mips64Assembler::Branch::GetTarget() const {
   1911   return target_;
   1912 }
   1913 
   1914 uint32_t Mips64Assembler::Branch::GetLocation() const {
   1915   return location_;
   1916 }
   1917 
   1918 uint32_t Mips64Assembler::Branch::GetOldLocation() const {
   1919   return old_location_;
   1920 }
   1921 
   1922 uint32_t Mips64Assembler::Branch::GetLength() const {
   1923   return branch_info_[type_].length;
   1924 }
   1925 
   1926 uint32_t Mips64Assembler::Branch::GetOldLength() const {
   1927   return branch_info_[old_type_].length;
   1928 }
   1929 
   1930 uint32_t Mips64Assembler::Branch::GetSize() const {
   1931   return GetLength() * sizeof(uint32_t);
   1932 }
   1933 
   1934 uint32_t Mips64Assembler::Branch::GetOldSize() const {
   1935   return GetOldLength() * sizeof(uint32_t);
   1936 }
   1937 
   1938 uint32_t Mips64Assembler::Branch::GetEndLocation() const {
   1939   return GetLocation() + GetSize();
   1940 }
   1941 
   1942 uint32_t Mips64Assembler::Branch::GetOldEndLocation() const {
   1943   return GetOldLocation() + GetOldSize();
   1944 }
   1945 
   1946 bool Mips64Assembler::Branch::IsLong() const {
   1947   switch (type_) {
   1948     // Short branches.
   1949     case kUncondBranch:
   1950     case kCondBranch:
   1951     case kCall:
   1952     // Near label.
   1953     case kLabel:
   1954     // Near literals.
   1955     case kLiteral:
   1956     case kLiteralUnsigned:
   1957     case kLiteralLong:
   1958       return false;
   1959     // Long branches.
   1960     case kLongUncondBranch:
   1961     case kLongCondBranch:
   1962     case kLongCall:
   1963     // Far label.
   1964     case kFarLabel:
   1965     // Far literals.
   1966     case kFarLiteral:
   1967     case kFarLiteralUnsigned:
   1968     case kFarLiteralLong:
   1969       return true;
   1970   }
   1971   UNREACHABLE();
   1972 }
   1973 
   1974 bool Mips64Assembler::Branch::IsResolved() const {
   1975   return target_ != kUnresolved;
   1976 }
   1977 
   1978 Mips64Assembler::Branch::OffsetBits Mips64Assembler::Branch::GetOffsetSize() const {
   1979   OffsetBits offset_size =
   1980       (type_ == kCondBranch && (condition_ == kCondEQZ || condition_ == kCondNEZ))
   1981           ? kOffset23
   1982           : branch_info_[type_].offset_size;
   1983   return offset_size;
   1984 }
   1985 
   1986 Mips64Assembler::Branch::OffsetBits Mips64Assembler::Branch::GetOffsetSizeNeeded(uint32_t location,
   1987                                                                                  uint32_t target) {
   1988   // For unresolved targets assume the shortest encoding
   1989   // (later it will be made longer if needed).
   1990   if (target == kUnresolved)
   1991     return kOffset16;
   1992   int64_t distance = static_cast<int64_t>(target) - location;
   1993   // To simplify calculations in composite branches consisting of multiple instructions
   1994   // bump up the distance by a value larger than the max byte size of a composite branch.
   1995   distance += (distance >= 0) ? kMaxBranchSize : -kMaxBranchSize;
   1996   if (IsInt<kOffset16>(distance))
   1997     return kOffset16;
   1998   else if (IsInt<kOffset18>(distance))
   1999     return kOffset18;
   2000   else if (IsInt<kOffset21>(distance))
   2001     return kOffset21;
   2002   else if (IsInt<kOffset23>(distance))
   2003     return kOffset23;
   2004   else if (IsInt<kOffset28>(distance))
   2005     return kOffset28;
   2006   return kOffset32;
   2007 }
   2008 
   2009 void Mips64Assembler::Branch::Resolve(uint32_t target) {
   2010   target_ = target;
   2011 }
   2012 
   2013 void Mips64Assembler::Branch::Relocate(uint32_t expand_location, uint32_t delta) {
   2014   if (location_ > expand_location) {
   2015     location_ += delta;
   2016   }
   2017   if (!IsResolved()) {
   2018     return;  // Don't know the target yet.
   2019   }
   2020   if (target_ > expand_location) {
   2021     target_ += delta;
   2022   }
   2023 }
   2024 
   2025 void Mips64Assembler::Branch::PromoteToLong() {
   2026   switch (type_) {
   2027     // Short branches.
   2028     case kUncondBranch:
   2029       type_ = kLongUncondBranch;
   2030       break;
   2031     case kCondBranch:
   2032       type_ = kLongCondBranch;
   2033       break;
   2034     case kCall:
   2035       type_ = kLongCall;
   2036       break;
   2037     // Near label.
   2038     case kLabel:
   2039       type_ = kFarLabel;
   2040       break;
   2041     // Near literals.
   2042     case kLiteral:
   2043       type_ = kFarLiteral;
   2044       break;
   2045     case kLiteralUnsigned:
   2046       type_ = kFarLiteralUnsigned;
   2047       break;
   2048     case kLiteralLong:
   2049       type_ = kFarLiteralLong;
   2050       break;
   2051     default:
   2052       // Note: 'type_' is already long.
   2053       break;
   2054   }
   2055   CHECK(IsLong());
   2056 }
   2057 
   2058 uint32_t Mips64Assembler::Branch::PromoteIfNeeded(uint32_t max_short_distance) {
   2059   // If the branch is still unresolved or already long, nothing to do.
   2060   if (IsLong() || !IsResolved()) {
   2061     return 0;
   2062   }
   2063   // Promote the short branch to long if the offset size is too small
   2064   // to hold the distance between location_ and target_.
   2065   if (GetOffsetSizeNeeded(location_, target_) > GetOffsetSize()) {
   2066     PromoteToLong();
   2067     uint32_t old_size = GetOldSize();
   2068     uint32_t new_size = GetSize();
   2069     CHECK_GT(new_size, old_size);
   2070     return new_size - old_size;
   2071   }
   2072   // The following logic is for debugging/testing purposes.
   2073   // Promote some short branches to long when it's not really required.
   2074   if (UNLIKELY(max_short_distance != std::numeric_limits<uint32_t>::max())) {
   2075     int64_t distance = static_cast<int64_t>(target_) - location_;
   2076     distance = (distance >= 0) ? distance : -distance;
   2077     if (distance >= max_short_distance) {
   2078       PromoteToLong();
   2079       uint32_t old_size = GetOldSize();
   2080       uint32_t new_size = GetSize();
   2081       CHECK_GT(new_size, old_size);
   2082       return new_size - old_size;
   2083     }
   2084   }
   2085   return 0;
   2086 }
   2087 
   2088 uint32_t Mips64Assembler::Branch::GetOffsetLocation() const {
   2089   return location_ + branch_info_[type_].instr_offset * sizeof(uint32_t);
   2090 }
   2091 
   2092 uint32_t Mips64Assembler::Branch::GetOffset() const {
   2093   CHECK(IsResolved());
   2094   uint32_t ofs_mask = 0xFFFFFFFF >> (32 - GetOffsetSize());
   2095   // Calculate the byte distance between instructions and also account for
   2096   // different PC-relative origins.
   2097   uint32_t offset_location = GetOffsetLocation();
   2098   if (type_ == kLiteralLong) {
   2099     // Special case for the ldpc instruction, whose address (PC) is rounded down to
   2100     // a multiple of 8 before adding the offset.
   2101     // Note, branch promotion has already taken care of aligning `target_` to an
   2102     // address that's a multiple of 8.
   2103     offset_location = RoundDown(offset_location, sizeof(uint64_t));
   2104   }
   2105   uint32_t offset = target_ - offset_location - branch_info_[type_].pc_org * sizeof(uint32_t);
   2106   // Prepare the offset for encoding into the instruction(s).
   2107   offset = (offset & ofs_mask) >> branch_info_[type_].offset_shift;
   2108   return offset;
   2109 }
   2110 
   2111 Mips64Assembler::Branch* Mips64Assembler::GetBranch(uint32_t branch_id) {
   2112   CHECK_LT(branch_id, branches_.size());
   2113   return &branches_[branch_id];
   2114 }
   2115 
   2116 const Mips64Assembler::Branch* Mips64Assembler::GetBranch(uint32_t branch_id) const {
   2117   CHECK_LT(branch_id, branches_.size());
   2118   return &branches_[branch_id];
   2119 }
   2120 
   2121 void Mips64Assembler::Bind(Mips64Label* label) {
   2122   CHECK(!label->IsBound());
   2123   uint32_t bound_pc = buffer_.Size();
   2124 
   2125   // Walk the list of branches referring to and preceding this label.
   2126   // Store the previously unknown target addresses in them.
   2127   while (label->IsLinked()) {
   2128     uint32_t branch_id = label->Position();
   2129     Branch* branch = GetBranch(branch_id);
   2130     branch->Resolve(bound_pc);
   2131 
   2132     uint32_t branch_location = branch->GetLocation();
   2133     // Extract the location of the previous branch in the list (walking the list backwards;
   2134     // the previous branch ID was stored in the space reserved for this branch).
   2135     uint32_t prev = buffer_.Load<uint32_t>(branch_location);
   2136 
   2137     // On to the previous branch in the list...
   2138     label->position_ = prev;
   2139   }
   2140 
   2141   // Now make the label object contain its own location (relative to the end of the preceding
   2142   // branch, if any; it will be used by the branches referring to and following this label).
   2143   label->prev_branch_id_plus_one_ = branches_.size();
   2144   if (label->prev_branch_id_plus_one_) {
   2145     uint32_t branch_id = label->prev_branch_id_plus_one_ - 1;
   2146     const Branch* branch = GetBranch(branch_id);
   2147     bound_pc -= branch->GetEndLocation();
   2148   }
   2149   label->BindTo(bound_pc);
   2150 }
   2151 
   2152 uint32_t Mips64Assembler::GetLabelLocation(const Mips64Label* label) const {
   2153   CHECK(label->IsBound());
   2154   uint32_t target = label->Position();
   2155   if (label->prev_branch_id_plus_one_) {
   2156     // Get label location based on the branch preceding it.
   2157     uint32_t branch_id = label->prev_branch_id_plus_one_ - 1;
   2158     const Branch* branch = GetBranch(branch_id);
   2159     target += branch->GetEndLocation();
   2160   }
   2161   return target;
   2162 }
   2163 
   2164 uint32_t Mips64Assembler::GetAdjustedPosition(uint32_t old_position) {
   2165   // We can reconstruct the adjustment by going through all the branches from the beginning
   2166   // up to the old_position. Since we expect AdjustedPosition() to be called in a loop
   2167   // with increasing old_position, we can use the data from last AdjustedPosition() to
   2168   // continue where we left off and the whole loop should be O(m+n) where m is the number
   2169   // of positions to adjust and n is the number of branches.
   2170   if (old_position < last_old_position_) {
   2171     last_position_adjustment_ = 0;
   2172     last_old_position_ = 0;
   2173     last_branch_id_ = 0;
   2174   }
   2175   while (last_branch_id_ != branches_.size()) {
   2176     const Branch* branch = GetBranch(last_branch_id_);
   2177     if (branch->GetLocation() >= old_position + last_position_adjustment_) {
   2178       break;
   2179     }
   2180     last_position_adjustment_ += branch->GetSize() - branch->GetOldSize();
   2181     ++last_branch_id_;
   2182   }
   2183   last_old_position_ = old_position;
   2184   return old_position + last_position_adjustment_;
   2185 }
   2186 
   2187 void Mips64Assembler::FinalizeLabeledBranch(Mips64Label* label) {
   2188   uint32_t length = branches_.back().GetLength();
   2189   if (!label->IsBound()) {
   2190     // Branch forward (to a following label), distance is unknown.
   2191     // The first branch forward will contain 0, serving as the terminator of
   2192     // the list of forward-reaching branches.
   2193     Emit(label->position_);
   2194     length--;
   2195     // Now make the label object point to this branch
   2196     // (this forms a linked list of branches preceding this label).
   2197     uint32_t branch_id = branches_.size() - 1;
   2198     label->LinkTo(branch_id);
   2199   }
   2200   // Reserve space for the branch.
   2201   while (length--) {
   2202     Nop();
   2203   }
   2204 }
   2205 
   2206 void Mips64Assembler::Buncond(Mips64Label* label) {
   2207   uint32_t target = label->IsBound() ? GetLabelLocation(label) : Branch::kUnresolved;
   2208   branches_.emplace_back(buffer_.Size(), target, /* is_call */ false);
   2209   FinalizeLabeledBranch(label);
   2210 }
   2211 
   2212 void Mips64Assembler::Bcond(Mips64Label* label,
   2213                             BranchCondition condition,
   2214                             GpuRegister lhs,
   2215                             GpuRegister rhs) {
   2216   // If lhs = rhs, this can be a NOP.
   2217   if (Branch::IsNop(condition, lhs, rhs)) {
   2218     return;
   2219   }
   2220   uint32_t target = label->IsBound() ? GetLabelLocation(label) : Branch::kUnresolved;
   2221   branches_.emplace_back(buffer_.Size(), target, condition, lhs, rhs);
   2222   FinalizeLabeledBranch(label);
   2223 }
   2224 
   2225 void Mips64Assembler::Call(Mips64Label* label) {
   2226   uint32_t target = label->IsBound() ? GetLabelLocation(label) : Branch::kUnresolved;
   2227   branches_.emplace_back(buffer_.Size(), target, /* is_call */ true);
   2228   FinalizeLabeledBranch(label);
   2229 }
   2230 
   2231 void Mips64Assembler::LoadLabelAddress(GpuRegister dest_reg, Mips64Label* label) {
   2232   // Label address loads are treated as pseudo branches since they require very similar handling.
   2233   DCHECK(!label->IsBound());
   2234   branches_.emplace_back(buffer_.Size(), dest_reg, Branch::kLabel);
   2235   FinalizeLabeledBranch(label);
   2236 }
   2237 
   2238 Literal* Mips64Assembler::NewLiteral(size_t size, const uint8_t* data) {
   2239   // We don't support byte and half-word literals.
   2240   if (size == 4u) {
   2241     literals_.emplace_back(size, data);
   2242     return &literals_.back();
   2243   } else {
   2244     DCHECK_EQ(size, 8u);
   2245     long_literals_.emplace_back(size, data);
   2246     return &long_literals_.back();
   2247   }
   2248 }
   2249 
   2250 void Mips64Assembler::LoadLiteral(GpuRegister dest_reg,
   2251                                   LoadOperandType load_type,
   2252                                   Literal* literal) {
   2253   // Literal loads are treated as pseudo branches since they require very similar handling.
   2254   Branch::Type literal_type;
   2255   switch (load_type) {
   2256     case kLoadWord:
   2257       DCHECK_EQ(literal->GetSize(), 4u);
   2258       literal_type = Branch::kLiteral;
   2259       break;
   2260     case kLoadUnsignedWord:
   2261       DCHECK_EQ(literal->GetSize(), 4u);
   2262       literal_type = Branch::kLiteralUnsigned;
   2263       break;
   2264     case kLoadDoubleword:
   2265       DCHECK_EQ(literal->GetSize(), 8u);
   2266       literal_type = Branch::kLiteralLong;
   2267       break;
   2268     default:
   2269       LOG(FATAL) << "Unexpected literal load type " << load_type;
   2270       UNREACHABLE();
   2271   }
   2272   Mips64Label* label = literal->GetLabel();
   2273   DCHECK(!label->IsBound());
   2274   branches_.emplace_back(buffer_.Size(), dest_reg, literal_type);
   2275   FinalizeLabeledBranch(label);
   2276 }
   2277 
   2278 JumpTable* Mips64Assembler::CreateJumpTable(std::vector<Mips64Label*>&& labels) {
   2279   jump_tables_.emplace_back(std::move(labels));
   2280   JumpTable* table = &jump_tables_.back();
   2281   DCHECK(!table->GetLabel()->IsBound());
   2282   return table;
   2283 }
   2284 
   2285 void Mips64Assembler::ReserveJumpTableSpace() {
   2286   if (!jump_tables_.empty()) {
   2287     for (JumpTable& table : jump_tables_) {
   2288       Mips64Label* label = table.GetLabel();
   2289       Bind(label);
   2290 
   2291       // Bulk ensure capacity, as this may be large.
   2292       size_t orig_size = buffer_.Size();
   2293       size_t required_capacity = orig_size + table.GetSize();
   2294       if (required_capacity > buffer_.Capacity()) {
   2295         buffer_.ExtendCapacity(required_capacity);
   2296       }
   2297 #ifndef NDEBUG
   2298       buffer_.has_ensured_capacity_ = true;
   2299 #endif
   2300 
   2301       // Fill the space with dummy data as the data is not final
   2302       // until the branches have been promoted. And we shouldn't
   2303       // be moving uninitialized data during branch promotion.
   2304       for (size_t cnt = table.GetData().size(), i = 0; i < cnt; i++) {
   2305         buffer_.Emit<uint32_t>(0x1abe1234u);
   2306       }
   2307 
   2308 #ifndef NDEBUG
   2309       buffer_.has_ensured_capacity_ = false;
   2310 #endif
   2311     }
   2312   }
   2313 }
   2314 
   2315 void Mips64Assembler::EmitJumpTables() {
   2316   if (!jump_tables_.empty()) {
   2317     CHECK(!overwriting_);
   2318     // Switch from appending instructions at the end of the buffer to overwriting
   2319     // existing instructions (here, jump tables) in the buffer.
   2320     overwriting_ = true;
   2321 
   2322     for (JumpTable& table : jump_tables_) {
   2323       Mips64Label* table_label = table.GetLabel();
   2324       uint32_t start = GetLabelLocation(table_label);
   2325       overwrite_location_ = start;
   2326 
   2327       for (Mips64Label* target : table.GetData()) {
   2328         CHECK_EQ(buffer_.Load<uint32_t>(overwrite_location_), 0x1abe1234u);
   2329         // The table will contain target addresses relative to the table start.
   2330         uint32_t offset = GetLabelLocation(target) - start;
   2331         Emit(offset);
   2332       }
   2333     }
   2334 
   2335     overwriting_ = false;
   2336   }
   2337 }
   2338 
   2339 void Mips64Assembler::EmitLiterals() {
   2340   if (!literals_.empty()) {
   2341     for (Literal& literal : literals_) {
   2342       Mips64Label* label = literal.GetLabel();
   2343       Bind(label);
   2344       AssemblerBuffer::EnsureCapacity ensured(&buffer_);
   2345       DCHECK_EQ(literal.GetSize(), 4u);
   2346       for (size_t i = 0, size = literal.GetSize(); i != size; ++i) {
   2347         buffer_.Emit<uint8_t>(literal.GetData()[i]);
   2348       }
   2349     }
   2350   }
   2351   if (!long_literals_.empty()) {
   2352     // Reserve 4 bytes for potential alignment. If after the branch promotion the 64-bit
   2353     // literals don't end up 8-byte-aligned, they will be moved down 4 bytes.
   2354     Emit(0);  // NOP.
   2355     for (Literal& literal : long_literals_) {
   2356       Mips64Label* label = literal.GetLabel();
   2357       Bind(label);
   2358       AssemblerBuffer::EnsureCapacity ensured(&buffer_);
   2359       DCHECK_EQ(literal.GetSize(), 8u);
   2360       for (size_t i = 0, size = literal.GetSize(); i != size; ++i) {
   2361         buffer_.Emit<uint8_t>(literal.GetData()[i]);
   2362       }
   2363     }
   2364   }
   2365 }
   2366 
   2367 void Mips64Assembler::PromoteBranches() {
   2368   // Promote short branches to long as necessary.
   2369   bool changed;
   2370   do {
   2371     changed = false;
   2372     for (auto& branch : branches_) {
   2373       CHECK(branch.IsResolved());
   2374       uint32_t delta = branch.PromoteIfNeeded();
   2375       // If this branch has been promoted and needs to expand in size,
   2376       // relocate all branches by the expansion size.
   2377       if (delta) {
   2378         changed = true;
   2379         uint32_t expand_location = branch.GetLocation();
   2380         for (auto& branch2 : branches_) {
   2381           branch2.Relocate(expand_location, delta);
   2382         }
   2383       }
   2384     }
   2385   } while (changed);
   2386 
   2387   // Account for branch expansion by resizing the code buffer
   2388   // and moving the code in it to its final location.
   2389   size_t branch_count = branches_.size();
   2390   if (branch_count > 0) {
   2391     // Resize.
   2392     Branch& last_branch = branches_[branch_count - 1];
   2393     uint32_t size_delta = last_branch.GetEndLocation() - last_branch.GetOldEndLocation();
   2394     uint32_t old_size = buffer_.Size();
   2395     buffer_.Resize(old_size + size_delta);
   2396     // Move the code residing between branch placeholders.
   2397     uint32_t end = old_size;
   2398     for (size_t i = branch_count; i > 0; ) {
   2399       Branch& branch = branches_[--i];
   2400       uint32_t size = end - branch.GetOldEndLocation();
   2401       buffer_.Move(branch.GetEndLocation(), branch.GetOldEndLocation(), size);
   2402       end = branch.GetOldLocation();
   2403     }
   2404   }
   2405 
   2406   // Align 64-bit literals by moving them down by 4 bytes if needed.
   2407   // This will reduce the PC-relative distance, which should be safe for both near and far literals.
   2408   if (!long_literals_.empty()) {
   2409     uint32_t first_literal_location = GetLabelLocation(long_literals_.front().GetLabel());
   2410     size_t lit_size = long_literals_.size() * sizeof(uint64_t);
   2411     size_t buf_size = buffer_.Size();
   2412     // 64-bit literals must be at the very end of the buffer.
   2413     CHECK_EQ(first_literal_location + lit_size, buf_size);
   2414     if (!IsAligned<sizeof(uint64_t)>(first_literal_location)) {
   2415       buffer_.Move(first_literal_location - sizeof(uint32_t), first_literal_location, lit_size);
   2416       // The 4 reserved bytes proved useless, reduce the buffer size.
   2417       buffer_.Resize(buf_size - sizeof(uint32_t));
   2418       // Reduce target addresses in literal and address loads by 4 bytes in order for correct
   2419       // offsets from PC to be generated.
   2420       for (auto& branch : branches_) {
   2421         uint32_t target = branch.GetTarget();
   2422         if (target >= first_literal_location) {
   2423           branch.Resolve(target - sizeof(uint32_t));
   2424         }
   2425       }
   2426       // If after this we ever call GetLabelLocation() to get the location of a 64-bit literal,
   2427       // we need to adjust the location of the literal's label as well.
   2428       for (Literal& literal : long_literals_) {
   2429         // Bound label's position is negative, hence incrementing it instead of decrementing.
   2430         literal.GetLabel()->position_ += sizeof(uint32_t);
   2431       }
   2432     }
   2433   }
   2434 }
   2435 
   2436 // Note: make sure branch_info_[] and EmitBranch() are kept synchronized.
   2437 const Mips64Assembler::Branch::BranchInfo Mips64Assembler::Branch::branch_info_[] = {
   2438   // Short branches.
   2439   {  1, 0, 1, Mips64Assembler::Branch::kOffset28, 2 },  // kUncondBranch
   2440   {  2, 0, 1, Mips64Assembler::Branch::kOffset18, 2 },  // kCondBranch
   2441                                                         // Exception: kOffset23 for beqzc/bnezc
   2442   {  1, 0, 1, Mips64Assembler::Branch::kOffset28, 2 },  // kCall
   2443   // Near label.
   2444   {  1, 0, 0, Mips64Assembler::Branch::kOffset21, 2 },  // kLabel
   2445   // Near literals.
   2446   {  1, 0, 0, Mips64Assembler::Branch::kOffset21, 2 },  // kLiteral
   2447   {  1, 0, 0, Mips64Assembler::Branch::kOffset21, 2 },  // kLiteralUnsigned
   2448   {  1, 0, 0, Mips64Assembler::Branch::kOffset21, 3 },  // kLiteralLong
   2449   // Long branches.
   2450   {  2, 0, 0, Mips64Assembler::Branch::kOffset32, 0 },  // kLongUncondBranch
   2451   {  3, 1, 0, Mips64Assembler::Branch::kOffset32, 0 },  // kLongCondBranch
   2452   {  2, 0, 0, Mips64Assembler::Branch::kOffset32, 0 },  // kLongCall
   2453   // Far label.
   2454   {  2, 0, 0, Mips64Assembler::Branch::kOffset32, 0 },  // kFarLabel
   2455   // Far literals.
   2456   {  2, 0, 0, Mips64Assembler::Branch::kOffset32, 0 },  // kFarLiteral
   2457   {  2, 0, 0, Mips64Assembler::Branch::kOffset32, 0 },  // kFarLiteralUnsigned
   2458   {  2, 0, 0, Mips64Assembler::Branch::kOffset32, 0 },  // kFarLiteralLong
   2459 };
   2460 
   2461 // Note: make sure branch_info_[] and EmitBranch() are kept synchronized.
   2462 void Mips64Assembler::EmitBranch(Mips64Assembler::Branch* branch) {
   2463   CHECK(overwriting_);
   2464   overwrite_location_ = branch->GetLocation();
   2465   uint32_t offset = branch->GetOffset();
   2466   BranchCondition condition = branch->GetCondition();
   2467   GpuRegister lhs = branch->GetLeftRegister();
   2468   GpuRegister rhs = branch->GetRightRegister();
   2469   switch (branch->GetType()) {
   2470     // Short branches.
   2471     case Branch::kUncondBranch:
   2472       CHECK_EQ(overwrite_location_, branch->GetOffsetLocation());
   2473       Bc(offset);
   2474       break;
   2475     case Branch::kCondBranch:
   2476       CHECK_EQ(overwrite_location_, branch->GetOffsetLocation());
   2477       EmitBcondc(condition, lhs, rhs, offset);
   2478       Nop();  // TODO: improve by filling the forbidden/delay slot.
   2479       break;
   2480     case Branch::kCall:
   2481       CHECK_EQ(overwrite_location_, branch->GetOffsetLocation());
   2482       Balc(offset);
   2483       break;
   2484 
   2485     // Near label.
   2486     case Branch::kLabel:
   2487       CHECK_EQ(overwrite_location_, branch->GetOffsetLocation());
   2488       Addiupc(lhs, offset);
   2489       break;
   2490     // Near literals.
   2491     case Branch::kLiteral:
   2492       CHECK_EQ(overwrite_location_, branch->GetOffsetLocation());
   2493       Lwpc(lhs, offset);
   2494       break;
   2495     case Branch::kLiteralUnsigned:
   2496       CHECK_EQ(overwrite_location_, branch->GetOffsetLocation());
   2497       Lwupc(lhs, offset);
   2498       break;
   2499     case Branch::kLiteralLong:
   2500       CHECK_EQ(overwrite_location_, branch->GetOffsetLocation());
   2501       Ldpc(lhs, offset);
   2502       break;
   2503 
   2504     // Long branches.
   2505     case Branch::kLongUncondBranch:
   2506       offset += (offset & 0x8000) << 1;  // Account for sign extension in jic.
   2507       CHECK_EQ(overwrite_location_, branch->GetOffsetLocation());
   2508       Auipc(AT, High16Bits(offset));
   2509       Jic(AT, Low16Bits(offset));
   2510       break;
   2511     case Branch::kLongCondBranch:
   2512       EmitBcondc(Branch::OppositeCondition(condition), lhs, rhs, 2);
   2513       offset += (offset & 0x8000) << 1;  // Account for sign extension in jic.
   2514       CHECK_EQ(overwrite_location_, branch->GetOffsetLocation());
   2515       Auipc(AT, High16Bits(offset));
   2516       Jic(AT, Low16Bits(offset));
   2517       break;
   2518     case Branch::kLongCall:
   2519       offset += (offset & 0x8000) << 1;  // Account for sign extension in jialc.
   2520       CHECK_EQ(overwrite_location_, branch->GetOffsetLocation());
   2521       Auipc(AT, High16Bits(offset));
   2522       Jialc(AT, Low16Bits(offset));
   2523       break;
   2524 
   2525     // Far label.
   2526     case Branch::kFarLabel:
   2527       offset += (offset & 0x8000) << 1;  // Account for sign extension in daddiu.
   2528       CHECK_EQ(overwrite_location_, branch->GetOffsetLocation());
   2529       Auipc(AT, High16Bits(offset));
   2530       Daddiu(lhs, AT, Low16Bits(offset));
   2531       break;
   2532     // Far literals.
   2533     case Branch::kFarLiteral:
   2534       offset += (offset & 0x8000) << 1;  // Account for sign extension in lw.
   2535       CHECK_EQ(overwrite_location_, branch->GetOffsetLocation());
   2536       Auipc(AT, High16Bits(offset));
   2537       Lw(lhs, AT, Low16Bits(offset));
   2538       break;
   2539     case Branch::kFarLiteralUnsigned:
   2540       offset += (offset & 0x8000) << 1;  // Account for sign extension in lwu.
   2541       CHECK_EQ(overwrite_location_, branch->GetOffsetLocation());
   2542       Auipc(AT, High16Bits(offset));
   2543       Lwu(lhs, AT, Low16Bits(offset));
   2544       break;
   2545     case Branch::kFarLiteralLong:
   2546       offset += (offset & 0x8000) << 1;  // Account for sign extension in ld.
   2547       CHECK_EQ(overwrite_location_, branch->GetOffsetLocation());
   2548       Auipc(AT, High16Bits(offset));
   2549       Ld(lhs, AT, Low16Bits(offset));
   2550       break;
   2551   }
   2552   CHECK_EQ(overwrite_location_, branch->GetEndLocation());
   2553   CHECK_LT(branch->GetSize(), static_cast<uint32_t>(Branch::kMaxBranchSize));
   2554 }
   2555 
   2556 void Mips64Assembler::Bc(Mips64Label* label) {
   2557   Buncond(label);
   2558 }
   2559 
   2560 void Mips64Assembler::Balc(Mips64Label* label) {
   2561   Call(label);
   2562 }
   2563 
   2564 void Mips64Assembler::Bltc(GpuRegister rs, GpuRegister rt, Mips64Label* label) {
   2565   Bcond(label, kCondLT, rs, rt);
   2566 }
   2567 
   2568 void Mips64Assembler::Bltzc(GpuRegister rt, Mips64Label* label) {
   2569   Bcond(label, kCondLTZ, rt);
   2570 }
   2571 
   2572 void Mips64Assembler::Bgtzc(GpuRegister rt, Mips64Label* label) {
   2573   Bcond(label, kCondGTZ, rt);
   2574 }
   2575 
   2576 void Mips64Assembler::Bgec(GpuRegister rs, GpuRegister rt, Mips64Label* label) {
   2577   Bcond(label, kCondGE, rs, rt);
   2578 }
   2579 
   2580 void Mips64Assembler::Bgezc(GpuRegister rt, Mips64Label* label) {
   2581   Bcond(label, kCondGEZ, rt);
   2582 }
   2583 
   2584 void Mips64Assembler::Blezc(GpuRegister rt, Mips64Label* label) {
   2585   Bcond(label, kCondLEZ, rt);
   2586 }
   2587 
   2588 void Mips64Assembler::Bltuc(GpuRegister rs, GpuRegister rt, Mips64Label* label) {
   2589   Bcond(label, kCondLTU, rs, rt);
   2590 }
   2591 
   2592 void Mips64Assembler::Bgeuc(GpuRegister rs, GpuRegister rt, Mips64Label* label) {
   2593   Bcond(label, kCondGEU, rs, rt);
   2594 }
   2595 
   2596 void Mips64Assembler::Beqc(GpuRegister rs, GpuRegister rt, Mips64Label* label) {
   2597   Bcond(label, kCondEQ, rs, rt);
   2598 }
   2599 
   2600 void Mips64Assembler::Bnec(GpuRegister rs, GpuRegister rt, Mips64Label* label) {
   2601   Bcond(label, kCondNE, rs, rt);
   2602 }
   2603 
   2604 void Mips64Assembler::Beqzc(GpuRegister rs, Mips64Label* label) {
   2605   Bcond(label, kCondEQZ, rs);
   2606 }
   2607 
   2608 void Mips64Assembler::Bnezc(GpuRegister rs, Mips64Label* label) {
   2609   Bcond(label, kCondNEZ, rs);
   2610 }
   2611 
   2612 void Mips64Assembler::Bc1eqz(FpuRegister ft, Mips64Label* label) {
   2613   Bcond(label, kCondF, static_cast<GpuRegister>(ft), ZERO);
   2614 }
   2615 
   2616 void Mips64Assembler::Bc1nez(FpuRegister ft, Mips64Label* label) {
   2617   Bcond(label, kCondT, static_cast<GpuRegister>(ft), ZERO);
   2618 }
   2619 
   2620 void Mips64Assembler::AdjustBaseAndOffset(GpuRegister& base,
   2621                                           int32_t& offset,
   2622                                           bool is_doubleword) {
   2623   // This method is used to adjust the base register and offset pair
   2624   // for a load/store when the offset doesn't fit into int16_t.
   2625   // It is assumed that `base + offset` is sufficiently aligned for memory
   2626   // operands that are machine word in size or smaller. For doubleword-sized
   2627   // operands it's assumed that `base` is a multiple of 8, while `offset`
   2628   // may be a multiple of 4 (e.g. 4-byte-aligned long and double arguments
   2629   // and spilled variables on the stack accessed relative to the stack
   2630   // pointer register).
   2631   // We preserve the "alignment" of `offset` by adjusting it by a multiple of 8.
   2632   CHECK_NE(base, AT);  // Must not overwrite the register `base` while loading `offset`.
   2633 
   2634   bool doubleword_aligned = IsAligned<kMips64DoublewordSize>(offset);
   2635   bool two_accesses = is_doubleword && !doubleword_aligned;
   2636 
   2637   // IsInt<16> must be passed a signed value, hence the static cast below.
   2638   if (IsInt<16>(offset) &&
   2639       (!two_accesses || IsInt<16>(static_cast<int32_t>(offset + kMips64WordSize)))) {
   2640     // Nothing to do: `offset` (and, if needed, `offset + 4`) fits into int16_t.
   2641     return;
   2642   }
   2643 
   2644   // Remember the "(mis)alignment" of `offset`, it will be checked at the end.
   2645   uint32_t misalignment = offset & (kMips64DoublewordSize - 1);
   2646 
   2647   // First, see if `offset` can be represented as a sum of two 16-bit signed
   2648   // offsets. This can save an instruction.
   2649   // To simplify matters, only do this for a symmetric range of offsets from
   2650   // about -64KB to about +64KB, allowing further addition of 4 when accessing
   2651   // 64-bit variables with two 32-bit accesses.
   2652   constexpr int32_t kMinOffsetForSimpleAdjustment = 0x7ff8;  // Max int16_t that's a multiple of 8.
   2653   constexpr int32_t kMaxOffsetForSimpleAdjustment = 2 * kMinOffsetForSimpleAdjustment;
   2654 
   2655   if (0 <= offset && offset <= kMaxOffsetForSimpleAdjustment) {
   2656     Daddiu(AT, base, kMinOffsetForSimpleAdjustment);
   2657     offset -= kMinOffsetForSimpleAdjustment;
   2658   } else if (-kMaxOffsetForSimpleAdjustment <= offset && offset < 0) {
   2659     Daddiu(AT, base, -kMinOffsetForSimpleAdjustment);
   2660     offset += kMinOffsetForSimpleAdjustment;
   2661   } else {
   2662     // In more complex cases take advantage of the daui instruction, e.g.:
   2663     //    daui   AT, base, offset_high
   2664     //   [dahi   AT, 1]                       // When `offset` is close to +2GB.
   2665     //    lw     reg_lo, offset_low(AT)
   2666     //   [lw     reg_hi, (offset_low+4)(AT)]  // If misaligned 64-bit load.
   2667     // or when offset_low+4 overflows int16_t:
   2668     //    daui   AT, base, offset_high
   2669     //    daddiu AT, AT, 8
   2670     //    lw     reg_lo, (offset_low-8)(AT)
   2671     //    lw     reg_hi, (offset_low-4)(AT)
   2672     int16_t offset_low = Low16Bits(offset);
   2673     int32_t offset_low32 = offset_low;
   2674     int16_t offset_high = High16Bits(offset);
   2675     bool increment_hi16 = offset_low < 0;
   2676     bool overflow_hi16 = false;
   2677 
   2678     if (increment_hi16) {
   2679       offset_high++;
   2680       overflow_hi16 = (offset_high == -32768);
   2681     }
   2682     Daui(AT, base, offset_high);
   2683 
   2684     if (overflow_hi16) {
   2685       Dahi(AT, 1);
   2686     }
   2687 
   2688     if (two_accesses && !IsInt<16>(static_cast<int32_t>(offset_low32 + kMips64WordSize))) {
   2689       // Avoid overflow in the 16-bit offset of the load/store instruction when adding 4.
   2690       Daddiu(AT, AT, kMips64DoublewordSize);
   2691       offset_low32 -= kMips64DoublewordSize;
   2692     }
   2693 
   2694     offset = offset_low32;
   2695   }
   2696   base = AT;
   2697 
   2698   CHECK(IsInt<16>(offset));
   2699   if (two_accesses) {
   2700     CHECK(IsInt<16>(static_cast<int32_t>(offset + kMips64WordSize)));
   2701   }
   2702   CHECK_EQ(misalignment, offset & (kMips64DoublewordSize - 1));
   2703 }
   2704 
   2705 void Mips64Assembler::LoadFromOffset(LoadOperandType type,
   2706                                      GpuRegister reg,
   2707                                      GpuRegister base,
   2708                                      int32_t offset) {
   2709   LoadFromOffset<>(type, reg, base, offset);
   2710 }
   2711 
   2712 void Mips64Assembler::LoadFpuFromOffset(LoadOperandType type,
   2713                                         FpuRegister reg,
   2714                                         GpuRegister base,
   2715                                         int32_t offset) {
   2716   LoadFpuFromOffset<>(type, reg, base, offset);
   2717 }
   2718 
   2719 void Mips64Assembler::EmitLoad(ManagedRegister m_dst, GpuRegister src_register, int32_t src_offset,
   2720                                size_t size) {
   2721   Mips64ManagedRegister dst = m_dst.AsMips64();
   2722   if (dst.IsNoRegister()) {
   2723     CHECK_EQ(0u, size) << dst;
   2724   } else if (dst.IsGpuRegister()) {
   2725     if (size == 4) {
   2726       LoadFromOffset(kLoadWord, dst.AsGpuRegister(), src_register, src_offset);
   2727     } else if (size == 8) {
   2728       CHECK_EQ(8u, size) << dst;
   2729       LoadFromOffset(kLoadDoubleword, dst.AsGpuRegister(), src_register, src_offset);
   2730     } else {
   2731       UNIMPLEMENTED(FATAL) << "We only support Load() of size 4 and 8";
   2732     }
   2733   } else if (dst.IsFpuRegister()) {
   2734     if (size == 4) {
   2735       CHECK_EQ(4u, size) << dst;
   2736       LoadFpuFromOffset(kLoadWord, dst.AsFpuRegister(), src_register, src_offset);
   2737     } else if (size == 8) {
   2738       CHECK_EQ(8u, size) << dst;
   2739       LoadFpuFromOffset(kLoadDoubleword, dst.AsFpuRegister(), src_register, src_offset);
   2740     } else {
   2741       UNIMPLEMENTED(FATAL) << "We only support Load() of size 4 and 8";
   2742     }
   2743   }
   2744 }
   2745 
   2746 void Mips64Assembler::StoreToOffset(StoreOperandType type,
   2747                                     GpuRegister reg,
   2748                                     GpuRegister base,
   2749                                     int32_t offset) {
   2750   StoreToOffset<>(type, reg, base, offset);
   2751 }
   2752 
   2753 void Mips64Assembler::StoreFpuToOffset(StoreOperandType type,
   2754                                        FpuRegister reg,
   2755                                        GpuRegister base,
   2756                                        int32_t offset) {
   2757   StoreFpuToOffset<>(type, reg, base, offset);
   2758 }
   2759 
   2760 static dwarf::Reg DWARFReg(GpuRegister reg) {
   2761   return dwarf::Reg::Mips64Core(static_cast<int>(reg));
   2762 }
   2763 
   2764 constexpr size_t kFramePointerSize = 8;
   2765 
   2766 void Mips64Assembler::BuildFrame(size_t frame_size,
   2767                                  ManagedRegister method_reg,
   2768                                  ArrayRef<const ManagedRegister> callee_save_regs,
   2769                                  const ManagedRegisterEntrySpills& entry_spills) {
   2770   CHECK_ALIGNED(frame_size, kStackAlignment);
   2771   DCHECK(!overwriting_);
   2772 
   2773   // Increase frame to required size.
   2774   IncreaseFrameSize(frame_size);
   2775 
   2776   // Push callee saves and return address
   2777   int stack_offset = frame_size - kFramePointerSize;
   2778   StoreToOffset(kStoreDoubleword, RA, SP, stack_offset);
   2779   cfi_.RelOffset(DWARFReg(RA), stack_offset);
   2780   for (int i = callee_save_regs.size() - 1; i >= 0; --i) {
   2781     stack_offset -= kFramePointerSize;
   2782     GpuRegister reg = callee_save_regs[i].AsMips64().AsGpuRegister();
   2783     StoreToOffset(kStoreDoubleword, reg, SP, stack_offset);
   2784     cfi_.RelOffset(DWARFReg(reg), stack_offset);
   2785   }
   2786 
   2787   // Write out Method*.
   2788   StoreToOffset(kStoreDoubleword, method_reg.AsMips64().AsGpuRegister(), SP, 0);
   2789 
   2790   // Write out entry spills.
   2791   int32_t offset = frame_size + kFramePointerSize;
   2792   for (size_t i = 0; i < entry_spills.size(); ++i) {
   2793     Mips64ManagedRegister reg = entry_spills[i].AsMips64();
   2794     ManagedRegisterSpill spill = entry_spills.at(i);
   2795     int32_t size = spill.getSize();
   2796     if (reg.IsNoRegister()) {
   2797       // only increment stack offset.
   2798       offset += size;
   2799     } else if (reg.IsFpuRegister()) {
   2800       StoreFpuToOffset((size == 4) ? kStoreWord : kStoreDoubleword,
   2801           reg.AsFpuRegister(), SP, offset);
   2802       offset += size;
   2803     } else if (reg.IsGpuRegister()) {
   2804       StoreToOffset((size == 4) ? kStoreWord : kStoreDoubleword,
   2805           reg.AsGpuRegister(), SP, offset);
   2806       offset += size;
   2807     }
   2808   }
   2809 }
   2810 
   2811 void Mips64Assembler::RemoveFrame(size_t frame_size,
   2812                                   ArrayRef<const ManagedRegister> callee_save_regs) {
   2813   CHECK_ALIGNED(frame_size, kStackAlignment);
   2814   DCHECK(!overwriting_);
   2815   cfi_.RememberState();
   2816 
   2817   // Pop callee saves and return address
   2818   int stack_offset = frame_size - (callee_save_regs.size() * kFramePointerSize) - kFramePointerSize;
   2819   for (size_t i = 0; i < callee_save_regs.size(); ++i) {
   2820     GpuRegister reg = callee_save_regs[i].AsMips64().AsGpuRegister();
   2821     LoadFromOffset(kLoadDoubleword, reg, SP, stack_offset);
   2822     cfi_.Restore(DWARFReg(reg));
   2823     stack_offset += kFramePointerSize;
   2824   }
   2825   LoadFromOffset(kLoadDoubleword, RA, SP, stack_offset);
   2826   cfi_.Restore(DWARFReg(RA));
   2827 
   2828   // Decrease frame to required size.
   2829   DecreaseFrameSize(frame_size);
   2830 
   2831   // Then jump to the return address.
   2832   Jr(RA);
   2833   Nop();
   2834 
   2835   // The CFI should be restored for any code that follows the exit block.
   2836   cfi_.RestoreState();
   2837   cfi_.DefCFAOffset(frame_size);
   2838 }
   2839 
   2840 void Mips64Assembler::IncreaseFrameSize(size_t adjust) {
   2841   CHECK_ALIGNED(adjust, kFramePointerSize);
   2842   DCHECK(!overwriting_);
   2843   Daddiu64(SP, SP, static_cast<int32_t>(-adjust));
   2844   cfi_.AdjustCFAOffset(adjust);
   2845 }
   2846 
   2847 void Mips64Assembler::DecreaseFrameSize(size_t adjust) {
   2848   CHECK_ALIGNED(adjust, kFramePointerSize);
   2849   DCHECK(!overwriting_);
   2850   Daddiu64(SP, SP, static_cast<int32_t>(adjust));
   2851   cfi_.AdjustCFAOffset(-adjust);
   2852 }
   2853 
   2854 void Mips64Assembler::Store(FrameOffset dest, ManagedRegister msrc, size_t size) {
   2855   Mips64ManagedRegister src = msrc.AsMips64();
   2856   if (src.IsNoRegister()) {
   2857     CHECK_EQ(0u, size);
   2858   } else if (src.IsGpuRegister()) {
   2859     CHECK(size == 4 || size == 8) << size;
   2860     if (size == 8) {
   2861       StoreToOffset(kStoreDoubleword, src.AsGpuRegister(), SP, dest.Int32Value());
   2862     } else if (size == 4) {
   2863       StoreToOffset(kStoreWord, src.AsGpuRegister(), SP, dest.Int32Value());
   2864     } else {
   2865       UNIMPLEMENTED(FATAL) << "We only support Store() of size 4 and 8";
   2866     }
   2867   } else if (src.IsFpuRegister()) {
   2868     CHECK(size == 4 || size == 8) << size;
   2869     if (size == 8) {
   2870       StoreFpuToOffset(kStoreDoubleword, src.AsFpuRegister(), SP, dest.Int32Value());
   2871     } else if (size == 4) {
   2872       StoreFpuToOffset(kStoreWord, src.AsFpuRegister(), SP, dest.Int32Value());
   2873     } else {
   2874       UNIMPLEMENTED(FATAL) << "We only support Store() of size 4 and 8";
   2875     }
   2876   }
   2877 }
   2878 
   2879 void Mips64Assembler::StoreRef(FrameOffset dest, ManagedRegister msrc) {
   2880   Mips64ManagedRegister src = msrc.AsMips64();
   2881   CHECK(src.IsGpuRegister());
   2882   StoreToOffset(kStoreWord, src.AsGpuRegister(), SP, dest.Int32Value());
   2883 }
   2884 
   2885 void Mips64Assembler::StoreRawPtr(FrameOffset dest, ManagedRegister msrc) {
   2886   Mips64ManagedRegister src = msrc.AsMips64();
   2887   CHECK(src.IsGpuRegister());
   2888   StoreToOffset(kStoreDoubleword, src.AsGpuRegister(), SP, dest.Int32Value());
   2889 }
   2890 
   2891 void Mips64Assembler::StoreImmediateToFrame(FrameOffset dest, uint32_t imm,
   2892                                             ManagedRegister mscratch) {
   2893   Mips64ManagedRegister scratch = mscratch.AsMips64();
   2894   CHECK(scratch.IsGpuRegister()) << scratch;
   2895   LoadConst32(scratch.AsGpuRegister(), imm);
   2896   StoreToOffset(kStoreWord, scratch.AsGpuRegister(), SP, dest.Int32Value());
   2897 }
   2898 
   2899 void Mips64Assembler::StoreStackOffsetToThread(ThreadOffset64 thr_offs,
   2900                                                FrameOffset fr_offs,
   2901                                                ManagedRegister mscratch) {
   2902   Mips64ManagedRegister scratch = mscratch.AsMips64();
   2903   CHECK(scratch.IsGpuRegister()) << scratch;
   2904   Daddiu64(scratch.AsGpuRegister(), SP, fr_offs.Int32Value());
   2905   StoreToOffset(kStoreDoubleword, scratch.AsGpuRegister(), S1, thr_offs.Int32Value());
   2906 }
   2907 
   2908 void Mips64Assembler::StoreStackPointerToThread(ThreadOffset64 thr_offs) {
   2909   StoreToOffset(kStoreDoubleword, SP, S1, thr_offs.Int32Value());
   2910 }
   2911 
   2912 void Mips64Assembler::StoreSpanning(FrameOffset dest, ManagedRegister msrc,
   2913                                     FrameOffset in_off, ManagedRegister mscratch) {
   2914   Mips64ManagedRegister src = msrc.AsMips64();
   2915   Mips64ManagedRegister scratch = mscratch.AsMips64();
   2916   StoreToOffset(kStoreDoubleword, src.AsGpuRegister(), SP, dest.Int32Value());
   2917   LoadFromOffset(kLoadDoubleword, scratch.AsGpuRegister(), SP, in_off.Int32Value());
   2918   StoreToOffset(kStoreDoubleword, scratch.AsGpuRegister(), SP, dest.Int32Value() + 8);
   2919 }
   2920 
   2921 void Mips64Assembler::Load(ManagedRegister mdest, FrameOffset src, size_t size) {
   2922   return EmitLoad(mdest, SP, src.Int32Value(), size);
   2923 }
   2924 
   2925 void Mips64Assembler::LoadFromThread(ManagedRegister mdest, ThreadOffset64 src, size_t size) {
   2926   return EmitLoad(mdest, S1, src.Int32Value(), size);
   2927 }
   2928 
   2929 void Mips64Assembler::LoadRef(ManagedRegister mdest, FrameOffset src) {
   2930   Mips64ManagedRegister dest = mdest.AsMips64();
   2931   CHECK(dest.IsGpuRegister());
   2932   LoadFromOffset(kLoadUnsignedWord, dest.AsGpuRegister(), SP, src.Int32Value());
   2933 }
   2934 
   2935 void Mips64Assembler::LoadRef(ManagedRegister mdest, ManagedRegister base, MemberOffset offs,
   2936                               bool unpoison_reference) {
   2937   Mips64ManagedRegister dest = mdest.AsMips64();
   2938   CHECK(dest.IsGpuRegister() && base.AsMips64().IsGpuRegister());
   2939   LoadFromOffset(kLoadUnsignedWord, dest.AsGpuRegister(),
   2940                  base.AsMips64().AsGpuRegister(), offs.Int32Value());
   2941   if (unpoison_reference) {
   2942     MaybeUnpoisonHeapReference(dest.AsGpuRegister());
   2943   }
   2944 }
   2945 
   2946 void Mips64Assembler::LoadRawPtr(ManagedRegister mdest, ManagedRegister base,
   2947                                  Offset offs) {
   2948   Mips64ManagedRegister dest = mdest.AsMips64();
   2949   CHECK(dest.IsGpuRegister() && base.AsMips64().IsGpuRegister());
   2950   LoadFromOffset(kLoadDoubleword, dest.AsGpuRegister(),
   2951                  base.AsMips64().AsGpuRegister(), offs.Int32Value());
   2952 }
   2953 
   2954 void Mips64Assembler::LoadRawPtrFromThread(ManagedRegister mdest, ThreadOffset64 offs) {
   2955   Mips64ManagedRegister dest = mdest.AsMips64();
   2956   CHECK(dest.IsGpuRegister());
   2957   LoadFromOffset(kLoadDoubleword, dest.AsGpuRegister(), S1, offs.Int32Value());
   2958 }
   2959 
   2960 void Mips64Assembler::SignExtend(ManagedRegister mreg ATTRIBUTE_UNUSED,
   2961                                  size_t size ATTRIBUTE_UNUSED) {
   2962   UNIMPLEMENTED(FATAL) << "No sign extension necessary for MIPS64";
   2963 }
   2964 
   2965 void Mips64Assembler::ZeroExtend(ManagedRegister mreg ATTRIBUTE_UNUSED,
   2966                                  size_t size ATTRIBUTE_UNUSED) {
   2967   UNIMPLEMENTED(FATAL) << "No zero extension necessary for MIPS64";
   2968 }
   2969 
   2970 void Mips64Assembler::Move(ManagedRegister mdest, ManagedRegister msrc, size_t size) {
   2971   Mips64ManagedRegister dest = mdest.AsMips64();
   2972   Mips64ManagedRegister src = msrc.AsMips64();
   2973   if (!dest.Equals(src)) {
   2974     if (dest.IsGpuRegister()) {
   2975       CHECK(src.IsGpuRegister()) << src;
   2976       Move(dest.AsGpuRegister(), src.AsGpuRegister());
   2977     } else if (dest.IsFpuRegister()) {
   2978       CHECK(src.IsFpuRegister()) << src;
   2979       if (size == 4) {
   2980         MovS(dest.AsFpuRegister(), src.AsFpuRegister());
   2981       } else if (size == 8) {
   2982         MovD(dest.AsFpuRegister(), src.AsFpuRegister());
   2983       } else {
   2984         UNIMPLEMENTED(FATAL) << "We only support Copy() of size 4 and 8";
   2985       }
   2986     }
   2987   }
   2988 }
   2989 
   2990 void Mips64Assembler::CopyRef(FrameOffset dest, FrameOffset src,
   2991                               ManagedRegister mscratch) {
   2992   Mips64ManagedRegister scratch = mscratch.AsMips64();
   2993   CHECK(scratch.IsGpuRegister()) << scratch;
   2994   LoadFromOffset(kLoadWord, scratch.AsGpuRegister(), SP, src.Int32Value());
   2995   StoreToOffset(kStoreWord, scratch.AsGpuRegister(), SP, dest.Int32Value());
   2996 }
   2997 
   2998 void Mips64Assembler::CopyRawPtrFromThread(FrameOffset fr_offs,
   2999                                            ThreadOffset64 thr_offs,
   3000                                            ManagedRegister mscratch) {
   3001   Mips64ManagedRegister scratch = mscratch.AsMips64();
   3002   CHECK(scratch.IsGpuRegister()) << scratch;
   3003   LoadFromOffset(kLoadDoubleword, scratch.AsGpuRegister(), S1, thr_offs.Int32Value());
   3004   StoreToOffset(kStoreDoubleword, scratch.AsGpuRegister(), SP, fr_offs.Int32Value());
   3005 }
   3006 
   3007 void Mips64Assembler::CopyRawPtrToThread(ThreadOffset64 thr_offs,
   3008                                          FrameOffset fr_offs,
   3009                                          ManagedRegister mscratch) {
   3010   Mips64ManagedRegister scratch = mscratch.AsMips64();
   3011   CHECK(scratch.IsGpuRegister()) << scratch;
   3012   LoadFromOffset(kLoadDoubleword, scratch.AsGpuRegister(),
   3013                  SP, fr_offs.Int32Value());
   3014   StoreToOffset(kStoreDoubleword, scratch.AsGpuRegister(),
   3015                 S1, thr_offs.Int32Value());
   3016 }
   3017 
   3018 void Mips64Assembler::Copy(FrameOffset dest, FrameOffset src,
   3019                            ManagedRegister mscratch, size_t size) {
   3020   Mips64ManagedRegister scratch = mscratch.AsMips64();
   3021   CHECK(scratch.IsGpuRegister()) << scratch;
   3022   CHECK(size == 4 || size == 8) << size;
   3023   if (size == 4) {
   3024     LoadFromOffset(kLoadWord, scratch.AsGpuRegister(), SP, src.Int32Value());
   3025     StoreToOffset(kStoreDoubleword, scratch.AsGpuRegister(), SP, dest.Int32Value());
   3026   } else if (size == 8) {
   3027     LoadFromOffset(kLoadDoubleword, scratch.AsGpuRegister(), SP, src.Int32Value());
   3028     StoreToOffset(kStoreDoubleword, scratch.AsGpuRegister(), SP, dest.Int32Value());
   3029   } else {
   3030     UNIMPLEMENTED(FATAL) << "We only support Copy() of size 4 and 8";
   3031   }
   3032 }
   3033 
   3034 void Mips64Assembler::Copy(FrameOffset dest, ManagedRegister src_base, Offset src_offset,
   3035                            ManagedRegister mscratch, size_t size) {
   3036   GpuRegister scratch = mscratch.AsMips64().AsGpuRegister();
   3037   CHECK(size == 4 || size == 8) << size;
   3038   if (size == 4) {
   3039     LoadFromOffset(kLoadWord, scratch, src_base.AsMips64().AsGpuRegister(),
   3040                    src_offset.Int32Value());
   3041     StoreToOffset(kStoreDoubleword, scratch, SP, dest.Int32Value());
   3042   } else if (size == 8) {
   3043     LoadFromOffset(kLoadDoubleword, scratch, src_base.AsMips64().AsGpuRegister(),
   3044                    src_offset.Int32Value());
   3045     StoreToOffset(kStoreDoubleword, scratch, SP, dest.Int32Value());
   3046   } else {
   3047     UNIMPLEMENTED(FATAL) << "We only support Copy() of size 4 and 8";
   3048   }
   3049 }
   3050 
   3051 void Mips64Assembler::Copy(ManagedRegister dest_base, Offset dest_offset, FrameOffset src,
   3052                            ManagedRegister mscratch, size_t size) {
   3053   GpuRegister scratch = mscratch.AsMips64().AsGpuRegister();
   3054   CHECK(size == 4 || size == 8) << size;
   3055   if (size == 4) {
   3056     LoadFromOffset(kLoadWord, scratch, SP, src.Int32Value());
   3057     StoreToOffset(kStoreDoubleword, scratch, dest_base.AsMips64().AsGpuRegister(),
   3058                   dest_offset.Int32Value());
   3059   } else if (size == 8) {
   3060     LoadFromOffset(kLoadDoubleword, scratch, SP, src.Int32Value());
   3061     StoreToOffset(kStoreDoubleword, scratch, dest_base.AsMips64().AsGpuRegister(),
   3062                   dest_offset.Int32Value());
   3063   } else {
   3064     UNIMPLEMENTED(FATAL) << "We only support Copy() of size 4 and 8";
   3065   }
   3066 }
   3067 
   3068 void Mips64Assembler::Copy(FrameOffset dest ATTRIBUTE_UNUSED,
   3069                            FrameOffset src_base ATTRIBUTE_UNUSED,
   3070                            Offset src_offset ATTRIBUTE_UNUSED,
   3071                            ManagedRegister mscratch ATTRIBUTE_UNUSED,
   3072                            size_t size ATTRIBUTE_UNUSED) {
   3073   UNIMPLEMENTED(FATAL) << "No MIPS64 implementation";
   3074 }
   3075 
   3076 void Mips64Assembler::Copy(ManagedRegister dest, Offset dest_offset,
   3077                            ManagedRegister src, Offset src_offset,
   3078                            ManagedRegister mscratch, size_t size) {
   3079   GpuRegister scratch = mscratch.AsMips64().AsGpuRegister();
   3080   CHECK(size == 4 || size == 8) << size;
   3081   if (size == 4) {
   3082     LoadFromOffset(kLoadWord, scratch, src.AsMips64().AsGpuRegister(), src_offset.Int32Value());
   3083     StoreToOffset(kStoreDoubleword, scratch, dest.AsMips64().AsGpuRegister(), dest_offset.Int32Value());
   3084   } else if (size == 8) {
   3085     LoadFromOffset(kLoadDoubleword, scratch, src.AsMips64().AsGpuRegister(),
   3086                    src_offset.Int32Value());
   3087     StoreToOffset(kStoreDoubleword, scratch, dest.AsMips64().AsGpuRegister(),
   3088                   dest_offset.Int32Value());
   3089   } else {
   3090     UNIMPLEMENTED(FATAL) << "We only support Copy() of size 4 and 8";
   3091   }
   3092 }
   3093 
   3094 void Mips64Assembler::Copy(FrameOffset dest ATTRIBUTE_UNUSED,
   3095                            Offset dest_offset ATTRIBUTE_UNUSED,
   3096                            FrameOffset src ATTRIBUTE_UNUSED,
   3097                            Offset src_offset ATTRIBUTE_UNUSED,
   3098                            ManagedRegister mscratch ATTRIBUTE_UNUSED,
   3099                            size_t size ATTRIBUTE_UNUSED) {
   3100   UNIMPLEMENTED(FATAL) << "No MIPS64 implementation";
   3101 }
   3102 
   3103 void Mips64Assembler::MemoryBarrier(ManagedRegister mreg ATTRIBUTE_UNUSED) {
   3104   // TODO: sync?
   3105   UNIMPLEMENTED(FATAL) << "No MIPS64 implementation";
   3106 }
   3107 
   3108 void Mips64Assembler::CreateHandleScopeEntry(ManagedRegister mout_reg,
   3109                                              FrameOffset handle_scope_offset,
   3110                                              ManagedRegister min_reg,
   3111                                              bool null_allowed) {
   3112   Mips64ManagedRegister out_reg = mout_reg.AsMips64();
   3113   Mips64ManagedRegister in_reg = min_reg.AsMips64();
   3114   CHECK(in_reg.IsNoRegister() || in_reg.IsGpuRegister()) << in_reg;
   3115   CHECK(out_reg.IsGpuRegister()) << out_reg;
   3116   if (null_allowed) {
   3117     Mips64Label null_arg;
   3118     // Null values get a handle scope entry value of 0.  Otherwise, the handle scope entry is
   3119     // the address in the handle scope holding the reference.
   3120     // e.g. out_reg = (handle == 0) ? 0 : (SP+handle_offset)
   3121     if (in_reg.IsNoRegister()) {
   3122       LoadFromOffset(kLoadUnsignedWord, out_reg.AsGpuRegister(),
   3123                      SP, handle_scope_offset.Int32Value());
   3124       in_reg = out_reg;
   3125     }
   3126     if (!out_reg.Equals(in_reg)) {
   3127       LoadConst32(out_reg.AsGpuRegister(), 0);
   3128     }
   3129     Beqzc(in_reg.AsGpuRegister(), &null_arg);
   3130     Daddiu64(out_reg.AsGpuRegister(), SP, handle_scope_offset.Int32Value());
   3131     Bind(&null_arg);
   3132   } else {
   3133     Daddiu64(out_reg.AsGpuRegister(), SP, handle_scope_offset.Int32Value());
   3134   }
   3135 }
   3136 
   3137 void Mips64Assembler::CreateHandleScopeEntry(FrameOffset out_off,
   3138                                              FrameOffset handle_scope_offset,
   3139                                              ManagedRegister mscratch,
   3140                                              bool null_allowed) {
   3141   Mips64ManagedRegister scratch = mscratch.AsMips64();
   3142   CHECK(scratch.IsGpuRegister()) << scratch;
   3143   if (null_allowed) {
   3144     Mips64Label null_arg;
   3145     LoadFromOffset(kLoadUnsignedWord, scratch.AsGpuRegister(), SP,
   3146                    handle_scope_offset.Int32Value());
   3147     // Null values get a handle scope entry value of 0.  Otherwise, the handle scope entry is
   3148     // the address in the handle scope holding the reference.
   3149     // e.g. scratch = (scratch == 0) ? 0 : (SP+handle_scope_offset)
   3150     Beqzc(scratch.AsGpuRegister(), &null_arg);
   3151     Daddiu64(scratch.AsGpuRegister(), SP, handle_scope_offset.Int32Value());
   3152     Bind(&null_arg);
   3153   } else {
   3154     Daddiu64(scratch.AsGpuRegister(), SP, handle_scope_offset.Int32Value());
   3155   }
   3156   StoreToOffset(kStoreDoubleword, scratch.AsGpuRegister(), SP, out_off.Int32Value());
   3157 }
   3158 
   3159 // Given a handle scope entry, load the associated reference.
   3160 void Mips64Assembler::LoadReferenceFromHandleScope(ManagedRegister mout_reg,
   3161                                                    ManagedRegister min_reg) {
   3162   Mips64ManagedRegister out_reg = mout_reg.AsMips64();
   3163   Mips64ManagedRegister in_reg = min_reg.AsMips64();
   3164   CHECK(out_reg.IsGpuRegister()) << out_reg;
   3165   CHECK(in_reg.IsGpuRegister()) << in_reg;
   3166   Mips64Label null_arg;
   3167   if (!out_reg.Equals(in_reg)) {
   3168     LoadConst32(out_reg.AsGpuRegister(), 0);
   3169   }
   3170   Beqzc(in_reg.AsGpuRegister(), &null_arg);
   3171   LoadFromOffset(kLoadDoubleword, out_reg.AsGpuRegister(),
   3172                  in_reg.AsGpuRegister(), 0);
   3173   Bind(&null_arg);
   3174 }
   3175 
   3176 void Mips64Assembler::VerifyObject(ManagedRegister src ATTRIBUTE_UNUSED,
   3177                                    bool could_be_null ATTRIBUTE_UNUSED) {
   3178   // TODO: not validating references
   3179 }
   3180 
   3181 void Mips64Assembler::VerifyObject(FrameOffset src ATTRIBUTE_UNUSED,
   3182                                    bool could_be_null ATTRIBUTE_UNUSED) {
   3183   // TODO: not validating references
   3184 }
   3185 
   3186 void Mips64Assembler::Call(ManagedRegister mbase, Offset offset, ManagedRegister mscratch) {
   3187   Mips64ManagedRegister base = mbase.AsMips64();
   3188   Mips64ManagedRegister scratch = mscratch.AsMips64();
   3189   CHECK(base.IsGpuRegister()) << base;
   3190   CHECK(scratch.IsGpuRegister()) << scratch;
   3191   LoadFromOffset(kLoadDoubleword, scratch.AsGpuRegister(),
   3192                  base.AsGpuRegister(), offset.Int32Value());
   3193   Jalr(scratch.AsGpuRegister());
   3194   Nop();
   3195   // TODO: place reference map on call
   3196 }
   3197 
   3198 void Mips64Assembler::Call(FrameOffset base, Offset offset, ManagedRegister mscratch) {
   3199   Mips64ManagedRegister scratch = mscratch.AsMips64();
   3200   CHECK(scratch.IsGpuRegister()) << scratch;
   3201   // Call *(*(SP + base) + offset)
   3202   LoadFromOffset(kLoadDoubleword, scratch.AsGpuRegister(),
   3203                  SP, base.Int32Value());
   3204   LoadFromOffset(kLoadDoubleword, scratch.AsGpuRegister(),
   3205                  scratch.AsGpuRegister(), offset.Int32Value());
   3206   Jalr(scratch.AsGpuRegister());
   3207   Nop();
   3208   // TODO: place reference map on call
   3209 }
   3210 
   3211 void Mips64Assembler::CallFromThread(ThreadOffset64 offset ATTRIBUTE_UNUSED,
   3212                                      ManagedRegister mscratch ATTRIBUTE_UNUSED) {
   3213   UNIMPLEMENTED(FATAL) << "No MIPS64 implementation";
   3214 }
   3215 
   3216 void Mips64Assembler::GetCurrentThread(ManagedRegister tr) {
   3217   Move(tr.AsMips64().AsGpuRegister(), S1);
   3218 }
   3219 
   3220 void Mips64Assembler::GetCurrentThread(FrameOffset offset,
   3221                                        ManagedRegister mscratch ATTRIBUTE_UNUSED) {
   3222   StoreToOffset(kStoreDoubleword, S1, SP, offset.Int32Value());
   3223 }
   3224 
   3225 void Mips64Assembler::ExceptionPoll(ManagedRegister mscratch, size_t stack_adjust) {
   3226   Mips64ManagedRegister scratch = mscratch.AsMips64();
   3227   exception_blocks_.emplace_back(scratch, stack_adjust);
   3228   LoadFromOffset(kLoadDoubleword,
   3229                  scratch.AsGpuRegister(),
   3230                  S1,
   3231                  Thread::ExceptionOffset<kMips64PointerSize>().Int32Value());
   3232   Bnezc(scratch.AsGpuRegister(), exception_blocks_.back().Entry());
   3233 }
   3234 
   3235 void Mips64Assembler::EmitExceptionPoll(Mips64ExceptionSlowPath* exception) {
   3236   Bind(exception->Entry());
   3237   if (exception->stack_adjust_ != 0) {  // Fix up the frame.
   3238     DecreaseFrameSize(exception->stack_adjust_);
   3239   }
   3240   // Pass exception object as argument.
   3241   // Don't care about preserving A0 as this call won't return.
   3242   CheckEntrypointTypes<kQuickDeliverException, void, mirror::Object*>();
   3243   Move(A0, exception->scratch_.AsGpuRegister());
   3244   // Set up call to Thread::Current()->pDeliverException
   3245   LoadFromOffset(kLoadDoubleword,
   3246                  T9,
   3247                  S1,
   3248                  QUICK_ENTRYPOINT_OFFSET(kMips64PointerSize, pDeliverException).Int32Value());
   3249   Jr(T9);
   3250   Nop();
   3251 
   3252   // Call never returns
   3253   Break();
   3254 }
   3255 
   3256 }  // namespace mips64
   3257 }  // namespace art
   3258