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::Ins(GpuRegister rd, GpuRegister rt, int pos, int size) {
    434   CHECK(IsUint<5>(pos)) << pos;
    435   CHECK(IsUint<5>(size - 1)) << size;
    436   CHECK(IsUint<5>(pos + size - 1)) << pos << " + " << size;
    437   EmitR(0x1f, rt, rd, static_cast<GpuRegister>(pos + size - 1), pos, 0x04);
    438 }
    439 
    440 void Mips64Assembler::Dinsm(GpuRegister rt, GpuRegister rs, int pos, int size) {
    441   CHECK(IsUint<5>(pos)) << pos;
    442   CHECK(2 <= size && size <= 64) << size;
    443   CHECK(IsUint<5>(pos + size - 33)) << pos << " + " << size;
    444   EmitR(0x1f, rs, rt, static_cast<GpuRegister>(pos + size - 33), pos, 0x5);
    445 }
    446 
    447 void Mips64Assembler::Dinsu(GpuRegister rt, GpuRegister rs, int pos, int size) {
    448   CHECK(IsUint<5>(pos - 32)) << pos;
    449   CHECK(IsUint<5>(size - 1)) << size;
    450   CHECK(IsUint<5>(pos + size - 33)) << pos << " + " << size;
    451   EmitR(0x1f, rs, rt, static_cast<GpuRegister>(pos + size - 33), pos - 32, 0x6);
    452 }
    453 
    454 void Mips64Assembler::Dins(GpuRegister rt, GpuRegister rs, int pos, int size) {
    455   CHECK(IsUint<5>(pos)) << pos;
    456   CHECK(IsUint<5>(size - 1)) << size;
    457   CHECK(IsUint<5>(pos + size - 1)) << pos << " + " << size;
    458   EmitR(0x1f, rs, rt, static_cast<GpuRegister>(pos + size - 1), pos, 0x7);
    459 }
    460 
    461 void Mips64Assembler::DblIns(GpuRegister rt, GpuRegister rs, int pos, int size) {
    462   if (pos >= 32) {
    463     Dinsu(rt, rs, pos, size);
    464   } else if ((static_cast<int64_t>(pos) + size - 1) >= 32) {
    465     Dinsm(rt, rs, pos, size);
    466   } else {
    467     Dins(rt, rs, pos, size);
    468   }
    469 }
    470 
    471 void Mips64Assembler::Lsa(GpuRegister rd, GpuRegister rs, GpuRegister rt, int saPlusOne) {
    472   CHECK(1 <= saPlusOne && saPlusOne <= 4) << saPlusOne;
    473   int sa = saPlusOne - 1;
    474   EmitR(0x0, rs, rt, rd, sa, 0x05);
    475 }
    476 
    477 void Mips64Assembler::Dlsa(GpuRegister rd, GpuRegister rs, GpuRegister rt, int saPlusOne) {
    478   CHECK(1 <= saPlusOne && saPlusOne <= 4) << saPlusOne;
    479   int sa = saPlusOne - 1;
    480   EmitR(0x0, rs, rt, rd, sa, 0x15);
    481 }
    482 
    483 void Mips64Assembler::Wsbh(GpuRegister rd, GpuRegister rt) {
    484   EmitRtd(0x1f, rt, rd, 2, 0x20);
    485 }
    486 
    487 void Mips64Assembler::Sc(GpuRegister rt, GpuRegister base, int16_t imm9) {
    488   CHECK(IsInt<9>(imm9));
    489   EmitI(0x1f, base, rt, ((imm9 & 0x1FF) << 7) | 0x26);
    490 }
    491 
    492 void Mips64Assembler::Scd(GpuRegister rt, GpuRegister base, int16_t imm9) {
    493   CHECK(IsInt<9>(imm9));
    494   EmitI(0x1f, base, rt, ((imm9 & 0x1FF) << 7) | 0x27);
    495 }
    496 
    497 void Mips64Assembler::Ll(GpuRegister rt, GpuRegister base, int16_t imm9) {
    498   CHECK(IsInt<9>(imm9));
    499   EmitI(0x1f, base, rt, ((imm9 & 0x1FF) << 7) | 0x36);
    500 }
    501 
    502 void Mips64Assembler::Lld(GpuRegister rt, GpuRegister base, int16_t imm9) {
    503   CHECK(IsInt<9>(imm9));
    504   EmitI(0x1f, base, rt, ((imm9 & 0x1FF) << 7) | 0x37);
    505 }
    506 
    507 void Mips64Assembler::Sll(GpuRegister rd, GpuRegister rt, int shamt) {
    508   EmitR(0, static_cast<GpuRegister>(0), rt, rd, shamt, 0x00);
    509 }
    510 
    511 void Mips64Assembler::Srl(GpuRegister rd, GpuRegister rt, int shamt) {
    512   EmitR(0, static_cast<GpuRegister>(0), rt, rd, shamt, 0x02);
    513 }
    514 
    515 void Mips64Assembler::Rotr(GpuRegister rd, GpuRegister rt, int shamt) {
    516   EmitR(0, static_cast<GpuRegister>(1), rt, rd, shamt, 0x02);
    517 }
    518 
    519 void Mips64Assembler::Sra(GpuRegister rd, GpuRegister rt, int shamt) {
    520   EmitR(0, static_cast<GpuRegister>(0), rt, rd, shamt, 0x03);
    521 }
    522 
    523 void Mips64Assembler::Sllv(GpuRegister rd, GpuRegister rt, GpuRegister rs) {
    524   EmitR(0, rs, rt, rd, 0, 0x04);
    525 }
    526 
    527 void Mips64Assembler::Rotrv(GpuRegister rd, GpuRegister rt, GpuRegister rs) {
    528   EmitR(0, rs, rt, rd, 1, 0x06);
    529 }
    530 
    531 void Mips64Assembler::Srlv(GpuRegister rd, GpuRegister rt, GpuRegister rs) {
    532   EmitR(0, rs, rt, rd, 0, 0x06);
    533 }
    534 
    535 void Mips64Assembler::Srav(GpuRegister rd, GpuRegister rt, GpuRegister rs) {
    536   EmitR(0, rs, rt, rd, 0, 0x07);
    537 }
    538 
    539 void Mips64Assembler::Dsll(GpuRegister rd, GpuRegister rt, int shamt) {
    540   EmitR(0, static_cast<GpuRegister>(0), rt, rd, shamt, 0x38);
    541 }
    542 
    543 void Mips64Assembler::Dsrl(GpuRegister rd, GpuRegister rt, int shamt) {
    544   EmitR(0, static_cast<GpuRegister>(0), rt, rd, shamt, 0x3a);
    545 }
    546 
    547 void Mips64Assembler::Drotr(GpuRegister rd, GpuRegister rt, int shamt) {
    548   EmitR(0, static_cast<GpuRegister>(1), rt, rd, shamt, 0x3a);
    549 }
    550 
    551 void Mips64Assembler::Dsra(GpuRegister rd, GpuRegister rt, int shamt) {
    552   EmitR(0, static_cast<GpuRegister>(0), rt, rd, shamt, 0x3b);
    553 }
    554 
    555 void Mips64Assembler::Dsll32(GpuRegister rd, GpuRegister rt, int shamt) {
    556   EmitR(0, static_cast<GpuRegister>(0), rt, rd, shamt, 0x3c);
    557 }
    558 
    559 void Mips64Assembler::Dsrl32(GpuRegister rd, GpuRegister rt, int shamt) {
    560   EmitR(0, static_cast<GpuRegister>(0), rt, rd, shamt, 0x3e);
    561 }
    562 
    563 void Mips64Assembler::Drotr32(GpuRegister rd, GpuRegister rt, int shamt) {
    564   EmitR(0, static_cast<GpuRegister>(1), rt, rd, shamt, 0x3e);
    565 }
    566 
    567 void Mips64Assembler::Dsra32(GpuRegister rd, GpuRegister rt, int shamt) {
    568   EmitR(0, static_cast<GpuRegister>(0), rt, rd, shamt, 0x3f);
    569 }
    570 
    571 void Mips64Assembler::Dsllv(GpuRegister rd, GpuRegister rt, GpuRegister rs) {
    572   EmitR(0, rs, rt, rd, 0, 0x14);
    573 }
    574 
    575 void Mips64Assembler::Dsrlv(GpuRegister rd, GpuRegister rt, GpuRegister rs) {
    576   EmitR(0, rs, rt, rd, 0, 0x16);
    577 }
    578 
    579 void Mips64Assembler::Drotrv(GpuRegister rd, GpuRegister rt, GpuRegister rs) {
    580   EmitR(0, rs, rt, rd, 1, 0x16);
    581 }
    582 
    583 void Mips64Assembler::Dsrav(GpuRegister rd, GpuRegister rt, GpuRegister rs) {
    584   EmitR(0, rs, rt, rd, 0, 0x17);
    585 }
    586 
    587 void Mips64Assembler::Lb(GpuRegister rt, GpuRegister rs, uint16_t imm16) {
    588   EmitI(0x20, rs, rt, imm16);
    589 }
    590 
    591 void Mips64Assembler::Lh(GpuRegister rt, GpuRegister rs, uint16_t imm16) {
    592   EmitI(0x21, rs, rt, imm16);
    593 }
    594 
    595 void Mips64Assembler::Lw(GpuRegister rt, GpuRegister rs, uint16_t imm16) {
    596   EmitI(0x23, rs, rt, imm16);
    597 }
    598 
    599 void Mips64Assembler::Ld(GpuRegister rt, GpuRegister rs, uint16_t imm16) {
    600   EmitI(0x37, rs, rt, imm16);
    601 }
    602 
    603 void Mips64Assembler::Lbu(GpuRegister rt, GpuRegister rs, uint16_t imm16) {
    604   EmitI(0x24, rs, rt, imm16);
    605 }
    606 
    607 void Mips64Assembler::Lhu(GpuRegister rt, GpuRegister rs, uint16_t imm16) {
    608   EmitI(0x25, rs, rt, imm16);
    609 }
    610 
    611 void Mips64Assembler::Lwu(GpuRegister rt, GpuRegister rs, uint16_t imm16) {
    612   EmitI(0x27, rs, rt, imm16);
    613 }
    614 
    615 void Mips64Assembler::Lwpc(GpuRegister rs, uint32_t imm19) {
    616   CHECK(IsUint<19>(imm19)) << imm19;
    617   EmitI21(0x3B, rs, (0x01 << 19) | imm19);
    618 }
    619 
    620 void Mips64Assembler::Lwupc(GpuRegister rs, uint32_t imm19) {
    621   CHECK(IsUint<19>(imm19)) << imm19;
    622   EmitI21(0x3B, rs, (0x02 << 19) | imm19);
    623 }
    624 
    625 void Mips64Assembler::Ldpc(GpuRegister rs, uint32_t imm18) {
    626   CHECK(IsUint<18>(imm18)) << imm18;
    627   EmitI21(0x3B, rs, (0x06 << 18) | imm18);
    628 }
    629 
    630 void Mips64Assembler::Lui(GpuRegister rt, uint16_t imm16) {
    631   EmitI(0xf, static_cast<GpuRegister>(0), rt, imm16);
    632 }
    633 
    634 void Mips64Assembler::Aui(GpuRegister rt, GpuRegister rs, uint16_t imm16) {
    635   EmitI(0xf, rs, rt, imm16);
    636 }
    637 
    638 void Mips64Assembler::Daui(GpuRegister rt, GpuRegister rs, uint16_t imm16) {
    639   CHECK_NE(rs, ZERO);
    640   EmitI(0x1d, rs, rt, imm16);
    641 }
    642 
    643 void Mips64Assembler::Dahi(GpuRegister rs, uint16_t imm16) {
    644   EmitI(1, rs, static_cast<GpuRegister>(6), imm16);
    645 }
    646 
    647 void Mips64Assembler::Dati(GpuRegister rs, uint16_t imm16) {
    648   EmitI(1, rs, static_cast<GpuRegister>(0x1e), imm16);
    649 }
    650 
    651 void Mips64Assembler::Sync(uint32_t stype) {
    652   EmitR(0, static_cast<GpuRegister>(0), static_cast<GpuRegister>(0),
    653            static_cast<GpuRegister>(0), stype & 0x1f, 0xf);
    654 }
    655 
    656 void Mips64Assembler::Sb(GpuRegister rt, GpuRegister rs, uint16_t imm16) {
    657   EmitI(0x28, rs, rt, imm16);
    658 }
    659 
    660 void Mips64Assembler::Sh(GpuRegister rt, GpuRegister rs, uint16_t imm16) {
    661   EmitI(0x29, rs, rt, imm16);
    662 }
    663 
    664 void Mips64Assembler::Sw(GpuRegister rt, GpuRegister rs, uint16_t imm16) {
    665   EmitI(0x2b, rs, rt, imm16);
    666 }
    667 
    668 void Mips64Assembler::Sd(GpuRegister rt, GpuRegister rs, uint16_t imm16) {
    669   EmitI(0x3f, rs, rt, imm16);
    670 }
    671 
    672 void Mips64Assembler::Slt(GpuRegister rd, GpuRegister rs, GpuRegister rt) {
    673   EmitR(0, rs, rt, rd, 0, 0x2a);
    674 }
    675 
    676 void Mips64Assembler::Sltu(GpuRegister rd, GpuRegister rs, GpuRegister rt) {
    677   EmitR(0, rs, rt, rd, 0, 0x2b);
    678 }
    679 
    680 void Mips64Assembler::Slti(GpuRegister rt, GpuRegister rs, uint16_t imm16) {
    681   EmitI(0xa, rs, rt, imm16);
    682 }
    683 
    684 void Mips64Assembler::Sltiu(GpuRegister rt, GpuRegister rs, uint16_t imm16) {
    685   EmitI(0xb, rs, rt, imm16);
    686 }
    687 
    688 void Mips64Assembler::Seleqz(GpuRegister rd, GpuRegister rs, GpuRegister rt) {
    689   EmitR(0, rs, rt, rd, 0, 0x35);
    690 }
    691 
    692 void Mips64Assembler::Selnez(GpuRegister rd, GpuRegister rs, GpuRegister rt) {
    693   EmitR(0, rs, rt, rd, 0, 0x37);
    694 }
    695 
    696 void Mips64Assembler::Clz(GpuRegister rd, GpuRegister rs) {
    697   EmitRsd(0, rs, rd, 0x01, 0x10);
    698 }
    699 
    700 void Mips64Assembler::Clo(GpuRegister rd, GpuRegister rs) {
    701   EmitRsd(0, rs, rd, 0x01, 0x11);
    702 }
    703 
    704 void Mips64Assembler::Dclz(GpuRegister rd, GpuRegister rs) {
    705   EmitRsd(0, rs, rd, 0x01, 0x12);
    706 }
    707 
    708 void Mips64Assembler::Dclo(GpuRegister rd, GpuRegister rs) {
    709   EmitRsd(0, rs, rd, 0x01, 0x13);
    710 }
    711 
    712 void Mips64Assembler::Jalr(GpuRegister rd, GpuRegister rs) {
    713   EmitR(0, rs, static_cast<GpuRegister>(0), rd, 0, 0x09);
    714 }
    715 
    716 void Mips64Assembler::Jalr(GpuRegister rs) {
    717   Jalr(RA, rs);
    718 }
    719 
    720 void Mips64Assembler::Jr(GpuRegister rs) {
    721   Jalr(ZERO, rs);
    722 }
    723 
    724 void Mips64Assembler::Auipc(GpuRegister rs, uint16_t imm16) {
    725   EmitI(0x3B, rs, static_cast<GpuRegister>(0x1E), imm16);
    726 }
    727 
    728 void Mips64Assembler::Addiupc(GpuRegister rs, uint32_t imm19) {
    729   CHECK(IsUint<19>(imm19)) << imm19;
    730   EmitI21(0x3B, rs, imm19);
    731 }
    732 
    733 void Mips64Assembler::Bc(uint32_t imm26) {
    734   EmitI26(0x32, imm26);
    735 }
    736 
    737 void Mips64Assembler::Balc(uint32_t imm26) {
    738   EmitI26(0x3A, imm26);
    739 }
    740 
    741 void Mips64Assembler::Jic(GpuRegister rt, uint16_t imm16) {
    742   EmitI(0x36, static_cast<GpuRegister>(0), rt, imm16);
    743 }
    744 
    745 void Mips64Assembler::Jialc(GpuRegister rt, uint16_t imm16) {
    746   EmitI(0x3E, static_cast<GpuRegister>(0), rt, imm16);
    747 }
    748 
    749 void Mips64Assembler::Bltc(GpuRegister rs, GpuRegister rt, uint16_t imm16) {
    750   CHECK_NE(rs, ZERO);
    751   CHECK_NE(rt, ZERO);
    752   CHECK_NE(rs, rt);
    753   EmitI(0x17, rs, rt, imm16);
    754 }
    755 
    756 void Mips64Assembler::Bltzc(GpuRegister rt, uint16_t imm16) {
    757   CHECK_NE(rt, ZERO);
    758   EmitI(0x17, rt, rt, imm16);
    759 }
    760 
    761 void Mips64Assembler::Bgtzc(GpuRegister rt, uint16_t imm16) {
    762   CHECK_NE(rt, ZERO);
    763   EmitI(0x17, static_cast<GpuRegister>(0), rt, imm16);
    764 }
    765 
    766 void Mips64Assembler::Bgec(GpuRegister rs, GpuRegister rt, uint16_t imm16) {
    767   CHECK_NE(rs, ZERO);
    768   CHECK_NE(rt, ZERO);
    769   CHECK_NE(rs, rt);
    770   EmitI(0x16, rs, rt, imm16);
    771 }
    772 
    773 void Mips64Assembler::Bgezc(GpuRegister rt, uint16_t imm16) {
    774   CHECK_NE(rt, ZERO);
    775   EmitI(0x16, rt, rt, imm16);
    776 }
    777 
    778 void Mips64Assembler::Blezc(GpuRegister rt, uint16_t imm16) {
    779   CHECK_NE(rt, ZERO);
    780   EmitI(0x16, static_cast<GpuRegister>(0), rt, imm16);
    781 }
    782 
    783 void Mips64Assembler::Bltuc(GpuRegister rs, GpuRegister rt, uint16_t imm16) {
    784   CHECK_NE(rs, ZERO);
    785   CHECK_NE(rt, ZERO);
    786   CHECK_NE(rs, rt);
    787   EmitI(0x7, rs, rt, imm16);
    788 }
    789 
    790 void Mips64Assembler::Bgeuc(GpuRegister rs, GpuRegister rt, uint16_t imm16) {
    791   CHECK_NE(rs, ZERO);
    792   CHECK_NE(rt, ZERO);
    793   CHECK_NE(rs, rt);
    794   EmitI(0x6, rs, rt, imm16);
    795 }
    796 
    797 void Mips64Assembler::Beqc(GpuRegister rs, GpuRegister rt, uint16_t imm16) {
    798   CHECK_NE(rs, ZERO);
    799   CHECK_NE(rt, ZERO);
    800   CHECK_NE(rs, rt);
    801   EmitI(0x8, std::min(rs, rt), std::max(rs, rt), imm16);
    802 }
    803 
    804 void Mips64Assembler::Bnec(GpuRegister rs, GpuRegister rt, uint16_t imm16) {
    805   CHECK_NE(rs, ZERO);
    806   CHECK_NE(rt, ZERO);
    807   CHECK_NE(rs, rt);
    808   EmitI(0x18, std::min(rs, rt), std::max(rs, rt), imm16);
    809 }
    810 
    811 void Mips64Assembler::Beqzc(GpuRegister rs, uint32_t imm21) {
    812   CHECK_NE(rs, ZERO);
    813   EmitI21(0x36, rs, imm21);
    814 }
    815 
    816 void Mips64Assembler::Bnezc(GpuRegister rs, uint32_t imm21) {
    817   CHECK_NE(rs, ZERO);
    818   EmitI21(0x3E, rs, imm21);
    819 }
    820 
    821 void Mips64Assembler::Bc1eqz(FpuRegister ft, uint16_t imm16) {
    822   EmitFI(0x11, 0x9, ft, imm16);
    823 }
    824 
    825 void Mips64Assembler::Bc1nez(FpuRegister ft, uint16_t imm16) {
    826   EmitFI(0x11, 0xD, ft, imm16);
    827 }
    828 
    829 void Mips64Assembler::Beq(GpuRegister rs, GpuRegister rt, uint16_t imm16) {
    830   EmitI(0x4, rs, rt, imm16);
    831 }
    832 
    833 void Mips64Assembler::Bne(GpuRegister rs, GpuRegister rt, uint16_t imm16) {
    834   EmitI(0x5, rs, rt, imm16);
    835 }
    836 
    837 void Mips64Assembler::Beqz(GpuRegister rt, uint16_t imm16) {
    838   Beq(rt, ZERO, imm16);
    839 }
    840 
    841 void Mips64Assembler::Bnez(GpuRegister rt, uint16_t imm16) {
    842   Bne(rt, ZERO, imm16);
    843 }
    844 
    845 void Mips64Assembler::Bltz(GpuRegister rt, uint16_t imm16) {
    846   EmitI(0x1, rt, static_cast<GpuRegister>(0), imm16);
    847 }
    848 
    849 void Mips64Assembler::Bgez(GpuRegister rt, uint16_t imm16) {
    850   EmitI(0x1, rt, static_cast<GpuRegister>(0x1), imm16);
    851 }
    852 
    853 void Mips64Assembler::Blez(GpuRegister rt, uint16_t imm16) {
    854   EmitI(0x6, rt, static_cast<GpuRegister>(0), imm16);
    855 }
    856 
    857 void Mips64Assembler::Bgtz(GpuRegister rt, uint16_t imm16) {
    858   EmitI(0x7, rt, static_cast<GpuRegister>(0), imm16);
    859 }
    860 
    861 void Mips64Assembler::EmitBcondR6(BranchCondition cond,
    862                                   GpuRegister rs,
    863                                   GpuRegister rt,
    864                                   uint32_t imm16_21) {
    865   switch (cond) {
    866     case kCondLT:
    867       Bltc(rs, rt, imm16_21);
    868       break;
    869     case kCondGE:
    870       Bgec(rs, rt, imm16_21);
    871       break;
    872     case kCondLE:
    873       Bgec(rt, rs, imm16_21);
    874       break;
    875     case kCondGT:
    876       Bltc(rt, rs, imm16_21);
    877       break;
    878     case kCondLTZ:
    879       CHECK_EQ(rt, ZERO);
    880       Bltzc(rs, imm16_21);
    881       break;
    882     case kCondGEZ:
    883       CHECK_EQ(rt, ZERO);
    884       Bgezc(rs, imm16_21);
    885       break;
    886     case kCondLEZ:
    887       CHECK_EQ(rt, ZERO);
    888       Blezc(rs, imm16_21);
    889       break;
    890     case kCondGTZ:
    891       CHECK_EQ(rt, ZERO);
    892       Bgtzc(rs, imm16_21);
    893       break;
    894     case kCondEQ:
    895       Beqc(rs, rt, imm16_21);
    896       break;
    897     case kCondNE:
    898       Bnec(rs, rt, imm16_21);
    899       break;
    900     case kCondEQZ:
    901       CHECK_EQ(rt, ZERO);
    902       Beqzc(rs, imm16_21);
    903       break;
    904     case kCondNEZ:
    905       CHECK_EQ(rt, ZERO);
    906       Bnezc(rs, imm16_21);
    907       break;
    908     case kCondLTU:
    909       Bltuc(rs, rt, imm16_21);
    910       break;
    911     case kCondGEU:
    912       Bgeuc(rs, rt, imm16_21);
    913       break;
    914     case kCondF:
    915       CHECK_EQ(rt, ZERO);
    916       Bc1eqz(static_cast<FpuRegister>(rs), imm16_21);
    917       break;
    918     case kCondT:
    919       CHECK_EQ(rt, ZERO);
    920       Bc1nez(static_cast<FpuRegister>(rs), imm16_21);
    921       break;
    922     case kUncond:
    923       LOG(FATAL) << "Unexpected branch condition " << cond;
    924       UNREACHABLE();
    925   }
    926 }
    927 
    928 void Mips64Assembler::EmitBcondR2(BranchCondition cond,
    929                                   GpuRegister rs,
    930                                   GpuRegister rt,
    931                                   uint16_t imm16) {
    932   switch (cond) {
    933     case kCondLTZ:
    934       CHECK_EQ(rt, ZERO);
    935       Bltz(rs, imm16);
    936       break;
    937     case kCondGEZ:
    938       CHECK_EQ(rt, ZERO);
    939       Bgez(rs, imm16);
    940       break;
    941     case kCondLEZ:
    942       CHECK_EQ(rt, ZERO);
    943       Blez(rs, imm16);
    944       break;
    945     case kCondGTZ:
    946       CHECK_EQ(rt, ZERO);
    947       Bgtz(rs, imm16);
    948       break;
    949     case kCondEQ:
    950       Beq(rs, rt, imm16);
    951       break;
    952     case kCondNE:
    953       Bne(rs, rt, imm16);
    954       break;
    955     case kCondEQZ:
    956       CHECK_EQ(rt, ZERO);
    957       Beqz(rs, imm16);
    958       break;
    959     case kCondNEZ:
    960       CHECK_EQ(rt, ZERO);
    961       Bnez(rs, imm16);
    962       break;
    963     case kCondF:
    964     case kCondT:
    965     case kCondLT:
    966     case kCondGE:
    967     case kCondLE:
    968     case kCondGT:
    969     case kCondLTU:
    970     case kCondGEU:
    971     case kUncond:
    972       LOG(FATAL) << "Unexpected branch condition " << cond;
    973       UNREACHABLE();
    974   }
    975 }
    976 
    977 void Mips64Assembler::AddS(FpuRegister fd, FpuRegister fs, FpuRegister ft) {
    978   EmitFR(0x11, 0x10, ft, fs, fd, 0x0);
    979 }
    980 
    981 void Mips64Assembler::SubS(FpuRegister fd, FpuRegister fs, FpuRegister ft) {
    982   EmitFR(0x11, 0x10, ft, fs, fd, 0x1);
    983 }
    984 
    985 void Mips64Assembler::MulS(FpuRegister fd, FpuRegister fs, FpuRegister ft) {
    986   EmitFR(0x11, 0x10, ft, fs, fd, 0x2);
    987 }
    988 
    989 void Mips64Assembler::DivS(FpuRegister fd, FpuRegister fs, FpuRegister ft) {
    990   EmitFR(0x11, 0x10, ft, fs, fd, 0x3);
    991 }
    992 
    993 void Mips64Assembler::AddD(FpuRegister fd, FpuRegister fs, FpuRegister ft) {
    994   EmitFR(0x11, 0x11, ft, fs, fd, 0x0);
    995 }
    996 
    997 void Mips64Assembler::SubD(FpuRegister fd, FpuRegister fs, FpuRegister ft) {
    998   EmitFR(0x11, 0x11, ft, fs, fd, 0x1);
    999 }
   1000 
   1001 void Mips64Assembler::MulD(FpuRegister fd, FpuRegister fs, FpuRegister ft) {
   1002   EmitFR(0x11, 0x11, ft, fs, fd, 0x2);
   1003 }
   1004 
   1005 void Mips64Assembler::DivD(FpuRegister fd, FpuRegister fs, FpuRegister ft) {
   1006   EmitFR(0x11, 0x11, ft, fs, fd, 0x3);
   1007 }
   1008 
   1009 void Mips64Assembler::SqrtS(FpuRegister fd, FpuRegister fs) {
   1010   EmitFR(0x11, 0x10, static_cast<FpuRegister>(0), fs, fd, 0x4);
   1011 }
   1012 
   1013 void Mips64Assembler::SqrtD(FpuRegister fd, FpuRegister fs) {
   1014   EmitFR(0x11, 0x11, static_cast<FpuRegister>(0), fs, fd, 0x4);
   1015 }
   1016 
   1017 void Mips64Assembler::AbsS(FpuRegister fd, FpuRegister fs) {
   1018   EmitFR(0x11, 0x10, static_cast<FpuRegister>(0), fs, fd, 0x5);
   1019 }
   1020 
   1021 void Mips64Assembler::AbsD(FpuRegister fd, FpuRegister fs) {
   1022   EmitFR(0x11, 0x11, static_cast<FpuRegister>(0), fs, fd, 0x5);
   1023 }
   1024 
   1025 void Mips64Assembler::MovS(FpuRegister fd, FpuRegister fs) {
   1026   EmitFR(0x11, 0x10, static_cast<FpuRegister>(0), fs, fd, 0x6);
   1027 }
   1028 
   1029 void Mips64Assembler::MovD(FpuRegister fd, FpuRegister fs) {
   1030   EmitFR(0x11, 0x11, static_cast<FpuRegister>(0), fs, fd, 0x6);
   1031 }
   1032 
   1033 void Mips64Assembler::NegS(FpuRegister fd, FpuRegister fs) {
   1034   EmitFR(0x11, 0x10, static_cast<FpuRegister>(0), fs, fd, 0x7);
   1035 }
   1036 
   1037 void Mips64Assembler::NegD(FpuRegister fd, FpuRegister fs) {
   1038   EmitFR(0x11, 0x11, static_cast<FpuRegister>(0), fs, fd, 0x7);
   1039 }
   1040 
   1041 void Mips64Assembler::RoundLS(FpuRegister fd, FpuRegister fs) {
   1042   EmitFR(0x11, 0x10, static_cast<FpuRegister>(0), fs, fd, 0x8);
   1043 }
   1044 
   1045 void Mips64Assembler::RoundLD(FpuRegister fd, FpuRegister fs) {
   1046   EmitFR(0x11, 0x11, static_cast<FpuRegister>(0), fs, fd, 0x8);
   1047 }
   1048 
   1049 void Mips64Assembler::RoundWS(FpuRegister fd, FpuRegister fs) {
   1050   EmitFR(0x11, 0x10, static_cast<FpuRegister>(0), fs, fd, 0xc);
   1051 }
   1052 
   1053 void Mips64Assembler::RoundWD(FpuRegister fd, FpuRegister fs) {
   1054   EmitFR(0x11, 0x11, static_cast<FpuRegister>(0), fs, fd, 0xc);
   1055 }
   1056 
   1057 void Mips64Assembler::TruncLS(FpuRegister fd, FpuRegister fs) {
   1058   EmitFR(0x11, 0x10, static_cast<FpuRegister>(0), fs, fd, 0x9);
   1059 }
   1060 
   1061 void Mips64Assembler::TruncLD(FpuRegister fd, FpuRegister fs) {
   1062   EmitFR(0x11, 0x11, static_cast<FpuRegister>(0), fs, fd, 0x9);
   1063 }
   1064 
   1065 void Mips64Assembler::TruncWS(FpuRegister fd, FpuRegister fs) {
   1066   EmitFR(0x11, 0x10, static_cast<FpuRegister>(0), fs, fd, 0xd);
   1067 }
   1068 
   1069 void Mips64Assembler::TruncWD(FpuRegister fd, FpuRegister fs) {
   1070   EmitFR(0x11, 0x11, static_cast<FpuRegister>(0), fs, fd, 0xd);
   1071 }
   1072 
   1073 void Mips64Assembler::CeilLS(FpuRegister fd, FpuRegister fs) {
   1074   EmitFR(0x11, 0x10, static_cast<FpuRegister>(0), fs, fd, 0xa);
   1075 }
   1076 
   1077 void Mips64Assembler::CeilLD(FpuRegister fd, FpuRegister fs) {
   1078   EmitFR(0x11, 0x11, static_cast<FpuRegister>(0), fs, fd, 0xa);
   1079 }
   1080 
   1081 void Mips64Assembler::CeilWS(FpuRegister fd, FpuRegister fs) {
   1082   EmitFR(0x11, 0x10, static_cast<FpuRegister>(0), fs, fd, 0xe);
   1083 }
   1084 
   1085 void Mips64Assembler::CeilWD(FpuRegister fd, FpuRegister fs) {
   1086   EmitFR(0x11, 0x11, static_cast<FpuRegister>(0), fs, fd, 0xe);
   1087 }
   1088 
   1089 void Mips64Assembler::FloorLS(FpuRegister fd, FpuRegister fs) {
   1090   EmitFR(0x11, 0x10, static_cast<FpuRegister>(0), fs, fd, 0xb);
   1091 }
   1092 
   1093 void Mips64Assembler::FloorLD(FpuRegister fd, FpuRegister fs) {
   1094   EmitFR(0x11, 0x11, static_cast<FpuRegister>(0), fs, fd, 0xb);
   1095 }
   1096 
   1097 void Mips64Assembler::FloorWS(FpuRegister fd, FpuRegister fs) {
   1098   EmitFR(0x11, 0x10, static_cast<FpuRegister>(0), fs, fd, 0xf);
   1099 }
   1100 
   1101 void Mips64Assembler::FloorWD(FpuRegister fd, FpuRegister fs) {
   1102   EmitFR(0x11, 0x11, static_cast<FpuRegister>(0), fs, fd, 0xf);
   1103 }
   1104 
   1105 void Mips64Assembler::SelS(FpuRegister fd, FpuRegister fs, FpuRegister ft) {
   1106   EmitFR(0x11, 0x10, ft, fs, fd, 0x10);
   1107 }
   1108 
   1109 void Mips64Assembler::SelD(FpuRegister fd, FpuRegister fs, FpuRegister ft) {
   1110   EmitFR(0x11, 0x11, ft, fs, fd, 0x10);
   1111 }
   1112 
   1113 void Mips64Assembler::SeleqzS(FpuRegister fd, FpuRegister fs, FpuRegister ft) {
   1114   EmitFR(0x11, 0x10, ft, fs, fd, 0x14);
   1115 }
   1116 
   1117 void Mips64Assembler::SeleqzD(FpuRegister fd, FpuRegister fs, FpuRegister ft) {
   1118   EmitFR(0x11, 0x11, ft, fs, fd, 0x14);
   1119 }
   1120 
   1121 void Mips64Assembler::SelnezS(FpuRegister fd, FpuRegister fs, FpuRegister ft) {
   1122   EmitFR(0x11, 0x10, ft, fs, fd, 0x17);
   1123 }
   1124 
   1125 void Mips64Assembler::SelnezD(FpuRegister fd, FpuRegister fs, FpuRegister ft) {
   1126   EmitFR(0x11, 0x11, ft, fs, fd, 0x17);
   1127 }
   1128 
   1129 void Mips64Assembler::RintS(FpuRegister fd, FpuRegister fs) {
   1130   EmitFR(0x11, 0x10, static_cast<FpuRegister>(0), fs, fd, 0x1a);
   1131 }
   1132 
   1133 void Mips64Assembler::RintD(FpuRegister fd, FpuRegister fs) {
   1134   EmitFR(0x11, 0x11, static_cast<FpuRegister>(0), fs, fd, 0x1a);
   1135 }
   1136 
   1137 void Mips64Assembler::ClassS(FpuRegister fd, FpuRegister fs) {
   1138   EmitFR(0x11, 0x10, static_cast<FpuRegister>(0), fs, fd, 0x1b);
   1139 }
   1140 
   1141 void Mips64Assembler::ClassD(FpuRegister fd, FpuRegister fs) {
   1142   EmitFR(0x11, 0x11, static_cast<FpuRegister>(0), fs, fd, 0x1b);
   1143 }
   1144 
   1145 void Mips64Assembler::MinS(FpuRegister fd, FpuRegister fs, FpuRegister ft) {
   1146   EmitFR(0x11, 0x10, ft, fs, fd, 0x1c);
   1147 }
   1148 
   1149 void Mips64Assembler::MinD(FpuRegister fd, FpuRegister fs, FpuRegister ft) {
   1150   EmitFR(0x11, 0x11, ft, fs, fd, 0x1c);
   1151 }
   1152 
   1153 void Mips64Assembler::MaxS(FpuRegister fd, FpuRegister fs, FpuRegister ft) {
   1154   EmitFR(0x11, 0x10, ft, fs, fd, 0x1e);
   1155 }
   1156 
   1157 void Mips64Assembler::MaxD(FpuRegister fd, FpuRegister fs, FpuRegister ft) {
   1158   EmitFR(0x11, 0x11, ft, fs, fd, 0x1e);
   1159 }
   1160 
   1161 void Mips64Assembler::CmpUnS(FpuRegister fd, FpuRegister fs, FpuRegister ft) {
   1162   EmitFR(0x11, 0x14, ft, fs, fd, 0x01);
   1163 }
   1164 
   1165 void Mips64Assembler::CmpEqS(FpuRegister fd, FpuRegister fs, FpuRegister ft) {
   1166   EmitFR(0x11, 0x14, ft, fs, fd, 0x02);
   1167 }
   1168 
   1169 void Mips64Assembler::CmpUeqS(FpuRegister fd, FpuRegister fs, FpuRegister ft) {
   1170   EmitFR(0x11, 0x14, ft, fs, fd, 0x03);
   1171 }
   1172 
   1173 void Mips64Assembler::CmpLtS(FpuRegister fd, FpuRegister fs, FpuRegister ft) {
   1174   EmitFR(0x11, 0x14, ft, fs, fd, 0x04);
   1175 }
   1176 
   1177 void Mips64Assembler::CmpUltS(FpuRegister fd, FpuRegister fs, FpuRegister ft) {
   1178   EmitFR(0x11, 0x14, ft, fs, fd, 0x05);
   1179 }
   1180 
   1181 void Mips64Assembler::CmpLeS(FpuRegister fd, FpuRegister fs, FpuRegister ft) {
   1182   EmitFR(0x11, 0x14, ft, fs, fd, 0x06);
   1183 }
   1184 
   1185 void Mips64Assembler::CmpUleS(FpuRegister fd, FpuRegister fs, FpuRegister ft) {
   1186   EmitFR(0x11, 0x14, ft, fs, fd, 0x07);
   1187 }
   1188 
   1189 void Mips64Assembler::CmpOrS(FpuRegister fd, FpuRegister fs, FpuRegister ft) {
   1190   EmitFR(0x11, 0x14, ft, fs, fd, 0x11);
   1191 }
   1192 
   1193 void Mips64Assembler::CmpUneS(FpuRegister fd, FpuRegister fs, FpuRegister ft) {
   1194   EmitFR(0x11, 0x14, ft, fs, fd, 0x12);
   1195 }
   1196 
   1197 void Mips64Assembler::CmpNeS(FpuRegister fd, FpuRegister fs, FpuRegister ft) {
   1198   EmitFR(0x11, 0x14, ft, fs, fd, 0x13);
   1199 }
   1200 
   1201 void Mips64Assembler::CmpUnD(FpuRegister fd, FpuRegister fs, FpuRegister ft) {
   1202   EmitFR(0x11, 0x15, ft, fs, fd, 0x01);
   1203 }
   1204 
   1205 void Mips64Assembler::CmpEqD(FpuRegister fd, FpuRegister fs, FpuRegister ft) {
   1206   EmitFR(0x11, 0x15, ft, fs, fd, 0x02);
   1207 }
   1208 
   1209 void Mips64Assembler::CmpUeqD(FpuRegister fd, FpuRegister fs, FpuRegister ft) {
   1210   EmitFR(0x11, 0x15, ft, fs, fd, 0x03);
   1211 }
   1212 
   1213 void Mips64Assembler::CmpLtD(FpuRegister fd, FpuRegister fs, FpuRegister ft) {
   1214   EmitFR(0x11, 0x15, ft, fs, fd, 0x04);
   1215 }
   1216 
   1217 void Mips64Assembler::CmpUltD(FpuRegister fd, FpuRegister fs, FpuRegister ft) {
   1218   EmitFR(0x11, 0x15, ft, fs, fd, 0x05);
   1219 }
   1220 
   1221 void Mips64Assembler::CmpLeD(FpuRegister fd, FpuRegister fs, FpuRegister ft) {
   1222   EmitFR(0x11, 0x15, ft, fs, fd, 0x06);
   1223 }
   1224 
   1225 void Mips64Assembler::CmpUleD(FpuRegister fd, FpuRegister fs, FpuRegister ft) {
   1226   EmitFR(0x11, 0x15, ft, fs, fd, 0x07);
   1227 }
   1228 
   1229 void Mips64Assembler::CmpOrD(FpuRegister fd, FpuRegister fs, FpuRegister ft) {
   1230   EmitFR(0x11, 0x15, ft, fs, fd, 0x11);
   1231 }
   1232 
   1233 void Mips64Assembler::CmpUneD(FpuRegister fd, FpuRegister fs, FpuRegister ft) {
   1234   EmitFR(0x11, 0x15, ft, fs, fd, 0x12);
   1235 }
   1236 
   1237 void Mips64Assembler::CmpNeD(FpuRegister fd, FpuRegister fs, FpuRegister ft) {
   1238   EmitFR(0x11, 0x15, ft, fs, fd, 0x13);
   1239 }
   1240 
   1241 void Mips64Assembler::Cvtsw(FpuRegister fd, FpuRegister fs) {
   1242   EmitFR(0x11, 0x14, static_cast<FpuRegister>(0), fs, fd, 0x20);
   1243 }
   1244 
   1245 void Mips64Assembler::Cvtdw(FpuRegister fd, FpuRegister fs) {
   1246   EmitFR(0x11, 0x14, static_cast<FpuRegister>(0), fs, fd, 0x21);
   1247 }
   1248 
   1249 void Mips64Assembler::Cvtsd(FpuRegister fd, FpuRegister fs) {
   1250   EmitFR(0x11, 0x11, static_cast<FpuRegister>(0), fs, fd, 0x20);
   1251 }
   1252 
   1253 void Mips64Assembler::Cvtds(FpuRegister fd, FpuRegister fs) {
   1254   EmitFR(0x11, 0x10, static_cast<FpuRegister>(0), fs, fd, 0x21);
   1255 }
   1256 
   1257 void Mips64Assembler::Cvtsl(FpuRegister fd, FpuRegister fs) {
   1258   EmitFR(0x11, 0x15, static_cast<FpuRegister>(0), fs, fd, 0x20);
   1259 }
   1260 
   1261 void Mips64Assembler::Cvtdl(FpuRegister fd, FpuRegister fs) {
   1262   EmitFR(0x11, 0x15, static_cast<FpuRegister>(0), fs, fd, 0x21);
   1263 }
   1264 
   1265 void Mips64Assembler::Mfc1(GpuRegister rt, FpuRegister fs) {
   1266   EmitFR(0x11, 0x00, static_cast<FpuRegister>(rt), fs, static_cast<FpuRegister>(0), 0x0);
   1267 }
   1268 
   1269 void Mips64Assembler::Mfhc1(GpuRegister rt, FpuRegister fs) {
   1270   EmitFR(0x11, 0x03, static_cast<FpuRegister>(rt), fs, static_cast<FpuRegister>(0), 0x0);
   1271 }
   1272 
   1273 void Mips64Assembler::Mtc1(GpuRegister rt, FpuRegister fs) {
   1274   EmitFR(0x11, 0x04, static_cast<FpuRegister>(rt), fs, static_cast<FpuRegister>(0), 0x0);
   1275 }
   1276 
   1277 void Mips64Assembler::Mthc1(GpuRegister rt, FpuRegister fs) {
   1278   EmitFR(0x11, 0x07, static_cast<FpuRegister>(rt), fs, static_cast<FpuRegister>(0), 0x0);
   1279 }
   1280 
   1281 void Mips64Assembler::Dmfc1(GpuRegister rt, FpuRegister fs) {
   1282   EmitFR(0x11, 0x01, static_cast<FpuRegister>(rt), fs, static_cast<FpuRegister>(0), 0x0);
   1283 }
   1284 
   1285 void Mips64Assembler::Dmtc1(GpuRegister rt, FpuRegister fs) {
   1286   EmitFR(0x11, 0x05, static_cast<FpuRegister>(rt), fs, static_cast<FpuRegister>(0), 0x0);
   1287 }
   1288 
   1289 void Mips64Assembler::Lwc1(FpuRegister ft, GpuRegister rs, uint16_t imm16) {
   1290   EmitI(0x31, rs, static_cast<GpuRegister>(ft), imm16);
   1291 }
   1292 
   1293 void Mips64Assembler::Ldc1(FpuRegister ft, GpuRegister rs, uint16_t imm16) {
   1294   EmitI(0x35, rs, static_cast<GpuRegister>(ft), imm16);
   1295 }
   1296 
   1297 void Mips64Assembler::Swc1(FpuRegister ft, GpuRegister rs, uint16_t imm16) {
   1298   EmitI(0x39, rs, static_cast<GpuRegister>(ft), imm16);
   1299 }
   1300 
   1301 void Mips64Assembler::Sdc1(FpuRegister ft, GpuRegister rs, uint16_t imm16) {
   1302   EmitI(0x3d, rs, static_cast<GpuRegister>(ft), imm16);
   1303 }
   1304 
   1305 void Mips64Assembler::Break() {
   1306   EmitR(0, static_cast<GpuRegister>(0), static_cast<GpuRegister>(0),
   1307         static_cast<GpuRegister>(0), 0, 0xD);
   1308 }
   1309 
   1310 void Mips64Assembler::Nop() {
   1311   EmitR(0x0, static_cast<GpuRegister>(0), static_cast<GpuRegister>(0),
   1312         static_cast<GpuRegister>(0), 0, 0x0);
   1313 }
   1314 
   1315 void Mips64Assembler::Move(GpuRegister rd, GpuRegister rs) {
   1316   Or(rd, rs, ZERO);
   1317 }
   1318 
   1319 void Mips64Assembler::Clear(GpuRegister rd) {
   1320   Move(rd, ZERO);
   1321 }
   1322 
   1323 void Mips64Assembler::Not(GpuRegister rd, GpuRegister rs) {
   1324   Nor(rd, rs, ZERO);
   1325 }
   1326 
   1327 void Mips64Assembler::AndV(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   1328   CHECK(HasMsa());
   1329   EmitMsa3R(0x0, 0x0, wt, ws, wd, 0x1e);
   1330 }
   1331 
   1332 void Mips64Assembler::OrV(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   1333   CHECK(HasMsa());
   1334   EmitMsa3R(0x0, 0x1, wt, ws, wd, 0x1e);
   1335 }
   1336 
   1337 void Mips64Assembler::NorV(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   1338   CHECK(HasMsa());
   1339   EmitMsa3R(0x0, 0x2, wt, ws, wd, 0x1e);
   1340 }
   1341 
   1342 void Mips64Assembler::XorV(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   1343   CHECK(HasMsa());
   1344   EmitMsa3R(0x0, 0x3, wt, ws, wd, 0x1e);
   1345 }
   1346 
   1347 void Mips64Assembler::AddvB(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   1348   CHECK(HasMsa());
   1349   EmitMsa3R(0x0, 0x0, wt, ws, wd, 0xe);
   1350 }
   1351 
   1352 void Mips64Assembler::AddvH(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   1353   CHECK(HasMsa());
   1354   EmitMsa3R(0x0, 0x1, wt, ws, wd, 0xe);
   1355 }
   1356 
   1357 void Mips64Assembler::AddvW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   1358   CHECK(HasMsa());
   1359   EmitMsa3R(0x0, 0x2, wt, ws, wd, 0xe);
   1360 }
   1361 
   1362 void Mips64Assembler::AddvD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   1363   CHECK(HasMsa());
   1364   EmitMsa3R(0x0, 0x3, wt, ws, wd, 0xe);
   1365 }
   1366 
   1367 void Mips64Assembler::SubvB(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   1368   CHECK(HasMsa());
   1369   EmitMsa3R(0x1, 0x0, wt, ws, wd, 0xe);
   1370 }
   1371 
   1372 void Mips64Assembler::SubvH(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   1373   CHECK(HasMsa());
   1374   EmitMsa3R(0x1, 0x1, wt, ws, wd, 0xe);
   1375 }
   1376 
   1377 void Mips64Assembler::SubvW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   1378   CHECK(HasMsa());
   1379   EmitMsa3R(0x1, 0x2, wt, ws, wd, 0xe);
   1380 }
   1381 
   1382 void Mips64Assembler::SubvD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   1383   CHECK(HasMsa());
   1384   EmitMsa3R(0x1, 0x3, wt, ws, wd, 0xe);
   1385 }
   1386 
   1387 void Mips64Assembler::Asub_sB(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   1388   CHECK(HasMsa());
   1389   EmitMsa3R(0x4, 0x0, wt, ws, wd, 0x11);
   1390 }
   1391 
   1392 void Mips64Assembler::Asub_sH(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   1393   CHECK(HasMsa());
   1394   EmitMsa3R(0x4, 0x1, wt, ws, wd, 0x11);
   1395 }
   1396 
   1397 void Mips64Assembler::Asub_sW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   1398   CHECK(HasMsa());
   1399   EmitMsa3R(0x4, 0x2, wt, ws, wd, 0x11);
   1400 }
   1401 
   1402 void Mips64Assembler::Asub_sD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   1403   CHECK(HasMsa());
   1404   EmitMsa3R(0x4, 0x3, wt, ws, wd, 0x11);
   1405 }
   1406 
   1407 void Mips64Assembler::Asub_uB(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   1408   CHECK(HasMsa());
   1409   EmitMsa3R(0x5, 0x0, wt, ws, wd, 0x11);
   1410 }
   1411 
   1412 void Mips64Assembler::Asub_uH(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   1413   CHECK(HasMsa());
   1414   EmitMsa3R(0x5, 0x1, wt, ws, wd, 0x11);
   1415 }
   1416 
   1417 void Mips64Assembler::Asub_uW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   1418   CHECK(HasMsa());
   1419   EmitMsa3R(0x5, 0x2, wt, ws, wd, 0x11);
   1420 }
   1421 
   1422 void Mips64Assembler::Asub_uD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   1423   CHECK(HasMsa());
   1424   EmitMsa3R(0x5, 0x3, wt, ws, wd, 0x11);
   1425 }
   1426 
   1427 void Mips64Assembler::MulvB(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   1428   CHECK(HasMsa());
   1429   EmitMsa3R(0x0, 0x0, wt, ws, wd, 0x12);
   1430 }
   1431 
   1432 void Mips64Assembler::MulvH(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   1433   CHECK(HasMsa());
   1434   EmitMsa3R(0x0, 0x1, wt, ws, wd, 0x12);
   1435 }
   1436 
   1437 void Mips64Assembler::MulvW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   1438   CHECK(HasMsa());
   1439   EmitMsa3R(0x0, 0x2, wt, ws, wd, 0x12);
   1440 }
   1441 
   1442 void Mips64Assembler::MulvD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   1443   CHECK(HasMsa());
   1444   EmitMsa3R(0x0, 0x3, wt, ws, wd, 0x12);
   1445 }
   1446 
   1447 void Mips64Assembler::Div_sB(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   1448   CHECK(HasMsa());
   1449   EmitMsa3R(0x4, 0x0, wt, ws, wd, 0x12);
   1450 }
   1451 
   1452 void Mips64Assembler::Div_sH(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   1453   CHECK(HasMsa());
   1454   EmitMsa3R(0x4, 0x1, wt, ws, wd, 0x12);
   1455 }
   1456 
   1457 void Mips64Assembler::Div_sW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   1458   CHECK(HasMsa());
   1459   EmitMsa3R(0x4, 0x2, wt, ws, wd, 0x12);
   1460 }
   1461 
   1462 void Mips64Assembler::Div_sD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   1463   CHECK(HasMsa());
   1464   EmitMsa3R(0x4, 0x3, wt, ws, wd, 0x12);
   1465 }
   1466 
   1467 void Mips64Assembler::Div_uB(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   1468   CHECK(HasMsa());
   1469   EmitMsa3R(0x5, 0x0, wt, ws, wd, 0x12);
   1470 }
   1471 
   1472 void Mips64Assembler::Div_uH(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   1473   CHECK(HasMsa());
   1474   EmitMsa3R(0x5, 0x1, wt, ws, wd, 0x12);
   1475 }
   1476 
   1477 void Mips64Assembler::Div_uW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   1478   CHECK(HasMsa());
   1479   EmitMsa3R(0x5, 0x2, wt, ws, wd, 0x12);
   1480 }
   1481 
   1482 void Mips64Assembler::Div_uD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   1483   CHECK(HasMsa());
   1484   EmitMsa3R(0x5, 0x3, wt, ws, wd, 0x12);
   1485 }
   1486 
   1487 void Mips64Assembler::Mod_sB(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   1488   CHECK(HasMsa());
   1489   EmitMsa3R(0x6, 0x0, wt, ws, wd, 0x12);
   1490 }
   1491 
   1492 void Mips64Assembler::Mod_sH(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   1493   CHECK(HasMsa());
   1494   EmitMsa3R(0x6, 0x1, wt, ws, wd, 0x12);
   1495 }
   1496 
   1497 void Mips64Assembler::Mod_sW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   1498   CHECK(HasMsa());
   1499   EmitMsa3R(0x6, 0x2, wt, ws, wd, 0x12);
   1500 }
   1501 
   1502 void Mips64Assembler::Mod_sD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   1503   CHECK(HasMsa());
   1504   EmitMsa3R(0x6, 0x3, wt, ws, wd, 0x12);
   1505 }
   1506 
   1507 void Mips64Assembler::Mod_uB(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   1508   CHECK(HasMsa());
   1509   EmitMsa3R(0x7, 0x0, wt, ws, wd, 0x12);
   1510 }
   1511 
   1512 void Mips64Assembler::Mod_uH(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   1513   CHECK(HasMsa());
   1514   EmitMsa3R(0x7, 0x1, wt, ws, wd, 0x12);
   1515 }
   1516 
   1517 void Mips64Assembler::Mod_uW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   1518   CHECK(HasMsa());
   1519   EmitMsa3R(0x7, 0x2, wt, ws, wd, 0x12);
   1520 }
   1521 
   1522 void Mips64Assembler::Mod_uD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   1523   CHECK(HasMsa());
   1524   EmitMsa3R(0x7, 0x3, wt, ws, wd, 0x12);
   1525 }
   1526 
   1527 void Mips64Assembler::Add_aB(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   1528   CHECK(HasMsa());
   1529   EmitMsa3R(0x0, 0x0, wt, ws, wd, 0x10);
   1530 }
   1531 
   1532 void Mips64Assembler::Add_aH(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   1533   CHECK(HasMsa());
   1534   EmitMsa3R(0x0, 0x1, wt, ws, wd, 0x10);
   1535 }
   1536 
   1537 void Mips64Assembler::Add_aW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   1538   CHECK(HasMsa());
   1539   EmitMsa3R(0x0, 0x2, wt, ws, wd, 0x10);
   1540 }
   1541 
   1542 void Mips64Assembler::Add_aD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   1543   CHECK(HasMsa());
   1544   EmitMsa3R(0x0, 0x3, wt, ws, wd, 0x10);
   1545 }
   1546 
   1547 void Mips64Assembler::Ave_sB(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   1548   CHECK(HasMsa());
   1549   EmitMsa3R(0x4, 0x0, wt, ws, wd, 0x10);
   1550 }
   1551 
   1552 void Mips64Assembler::Ave_sH(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   1553   CHECK(HasMsa());
   1554   EmitMsa3R(0x4, 0x1, wt, ws, wd, 0x10);
   1555 }
   1556 
   1557 void Mips64Assembler::Ave_sW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   1558   CHECK(HasMsa());
   1559   EmitMsa3R(0x4, 0x2, wt, ws, wd, 0x10);
   1560 }
   1561 
   1562 void Mips64Assembler::Ave_sD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   1563   CHECK(HasMsa());
   1564   EmitMsa3R(0x4, 0x3, wt, ws, wd, 0x10);
   1565 }
   1566 
   1567 void Mips64Assembler::Ave_uB(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   1568   CHECK(HasMsa());
   1569   EmitMsa3R(0x5, 0x0, wt, ws, wd, 0x10);
   1570 }
   1571 
   1572 void Mips64Assembler::Ave_uH(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   1573   CHECK(HasMsa());
   1574   EmitMsa3R(0x5, 0x1, wt, ws, wd, 0x10);
   1575 }
   1576 
   1577 void Mips64Assembler::Ave_uW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   1578   CHECK(HasMsa());
   1579   EmitMsa3R(0x5, 0x2, wt, ws, wd, 0x10);
   1580 }
   1581 
   1582 void Mips64Assembler::Ave_uD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   1583   CHECK(HasMsa());
   1584   EmitMsa3R(0x5, 0x3, wt, ws, wd, 0x10);
   1585 }
   1586 
   1587 void Mips64Assembler::Aver_sB(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   1588   CHECK(HasMsa());
   1589   EmitMsa3R(0x6, 0x0, wt, ws, wd, 0x10);
   1590 }
   1591 
   1592 void Mips64Assembler::Aver_sH(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   1593   CHECK(HasMsa());
   1594   EmitMsa3R(0x6, 0x1, wt, ws, wd, 0x10);
   1595 }
   1596 
   1597 void Mips64Assembler::Aver_sW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   1598   CHECK(HasMsa());
   1599   EmitMsa3R(0x6, 0x2, wt, ws, wd, 0x10);
   1600 }
   1601 
   1602 void Mips64Assembler::Aver_sD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   1603   CHECK(HasMsa());
   1604   EmitMsa3R(0x6, 0x3, wt, ws, wd, 0x10);
   1605 }
   1606 
   1607 void Mips64Assembler::Aver_uB(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   1608   CHECK(HasMsa());
   1609   EmitMsa3R(0x7, 0x0, wt, ws, wd, 0x10);
   1610 }
   1611 
   1612 void Mips64Assembler::Aver_uH(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   1613   CHECK(HasMsa());
   1614   EmitMsa3R(0x7, 0x1, wt, ws, wd, 0x10);
   1615 }
   1616 
   1617 void Mips64Assembler::Aver_uW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   1618   CHECK(HasMsa());
   1619   EmitMsa3R(0x7, 0x2, wt, ws, wd, 0x10);
   1620 }
   1621 
   1622 void Mips64Assembler::Aver_uD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   1623   CHECK(HasMsa());
   1624   EmitMsa3R(0x7, 0x3, wt, ws, wd, 0x10);
   1625 }
   1626 
   1627 void Mips64Assembler::Max_sB(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   1628   CHECK(HasMsa());
   1629   EmitMsa3R(0x2, 0x0, wt, ws, wd, 0xe);
   1630 }
   1631 
   1632 void Mips64Assembler::Max_sH(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   1633   CHECK(HasMsa());
   1634   EmitMsa3R(0x2, 0x1, wt, ws, wd, 0xe);
   1635 }
   1636 
   1637 void Mips64Assembler::Max_sW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   1638   CHECK(HasMsa());
   1639   EmitMsa3R(0x2, 0x2, wt, ws, wd, 0xe);
   1640 }
   1641 
   1642 void Mips64Assembler::Max_sD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   1643   CHECK(HasMsa());
   1644   EmitMsa3R(0x2, 0x3, wt, ws, wd, 0xe);
   1645 }
   1646 
   1647 void Mips64Assembler::Max_uB(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   1648   CHECK(HasMsa());
   1649   EmitMsa3R(0x3, 0x0, wt, ws, wd, 0xe);
   1650 }
   1651 
   1652 void Mips64Assembler::Max_uH(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   1653   CHECK(HasMsa());
   1654   EmitMsa3R(0x3, 0x1, wt, ws, wd, 0xe);
   1655 }
   1656 
   1657 void Mips64Assembler::Max_uW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   1658   CHECK(HasMsa());
   1659   EmitMsa3R(0x3, 0x2, wt, ws, wd, 0xe);
   1660 }
   1661 
   1662 void Mips64Assembler::Max_uD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   1663   CHECK(HasMsa());
   1664   EmitMsa3R(0x3, 0x3, wt, ws, wd, 0xe);
   1665 }
   1666 
   1667 void Mips64Assembler::Min_sB(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   1668   CHECK(HasMsa());
   1669   EmitMsa3R(0x4, 0x0, wt, ws, wd, 0xe);
   1670 }
   1671 
   1672 void Mips64Assembler::Min_sH(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   1673   CHECK(HasMsa());
   1674   EmitMsa3R(0x4, 0x1, wt, ws, wd, 0xe);
   1675 }
   1676 
   1677 void Mips64Assembler::Min_sW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   1678   CHECK(HasMsa());
   1679   EmitMsa3R(0x4, 0x2, wt, ws, wd, 0xe);
   1680 }
   1681 
   1682 void Mips64Assembler::Min_sD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   1683   CHECK(HasMsa());
   1684   EmitMsa3R(0x4, 0x3, wt, ws, wd, 0xe);
   1685 }
   1686 
   1687 void Mips64Assembler::Min_uB(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   1688   CHECK(HasMsa());
   1689   EmitMsa3R(0x5, 0x0, wt, ws, wd, 0xe);
   1690 }
   1691 
   1692 void Mips64Assembler::Min_uH(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   1693   CHECK(HasMsa());
   1694   EmitMsa3R(0x5, 0x1, wt, ws, wd, 0xe);
   1695 }
   1696 
   1697 void Mips64Assembler::Min_uW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   1698   CHECK(HasMsa());
   1699   EmitMsa3R(0x5, 0x2, wt, ws, wd, 0xe);
   1700 }
   1701 
   1702 void Mips64Assembler::Min_uD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   1703   CHECK(HasMsa());
   1704   EmitMsa3R(0x5, 0x3, wt, ws, wd, 0xe);
   1705 }
   1706 
   1707 void Mips64Assembler::FaddW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   1708   CHECK(HasMsa());
   1709   EmitMsa3R(0x0, 0x0, wt, ws, wd, 0x1b);
   1710 }
   1711 
   1712 void Mips64Assembler::FaddD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   1713   CHECK(HasMsa());
   1714   EmitMsa3R(0x0, 0x1, wt, ws, wd, 0x1b);
   1715 }
   1716 
   1717 void Mips64Assembler::FsubW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   1718   CHECK(HasMsa());
   1719   EmitMsa3R(0x0, 0x2, wt, ws, wd, 0x1b);
   1720 }
   1721 
   1722 void Mips64Assembler::FsubD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   1723   CHECK(HasMsa());
   1724   EmitMsa3R(0x0, 0x3, wt, ws, wd, 0x1b);
   1725 }
   1726 
   1727 void Mips64Assembler::FmulW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   1728   CHECK(HasMsa());
   1729   EmitMsa3R(0x1, 0x0, wt, ws, wd, 0x1b);
   1730 }
   1731 
   1732 void Mips64Assembler::FmulD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   1733   CHECK(HasMsa());
   1734   EmitMsa3R(0x1, 0x1, wt, ws, wd, 0x1b);
   1735 }
   1736 
   1737 void Mips64Assembler::FdivW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   1738   CHECK(HasMsa());
   1739   EmitMsa3R(0x1, 0x2, wt, ws, wd, 0x1b);
   1740 }
   1741 
   1742 void Mips64Assembler::FdivD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   1743   CHECK(HasMsa());
   1744   EmitMsa3R(0x1, 0x3, wt, ws, wd, 0x1b);
   1745 }
   1746 
   1747 void Mips64Assembler::FmaxW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   1748   CHECK(HasMsa());
   1749   EmitMsa3R(0x7, 0x0, wt, ws, wd, 0x1b);
   1750 }
   1751 
   1752 void Mips64Assembler::FmaxD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   1753   CHECK(HasMsa());
   1754   EmitMsa3R(0x7, 0x1, wt, ws, wd, 0x1b);
   1755 }
   1756 
   1757 void Mips64Assembler::FminW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   1758   CHECK(HasMsa());
   1759   EmitMsa3R(0x6, 0x0, wt, ws, wd, 0x1b);
   1760 }
   1761 
   1762 void Mips64Assembler::FminD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   1763   CHECK(HasMsa());
   1764   EmitMsa3R(0x6, 0x1, wt, ws, wd, 0x1b);
   1765 }
   1766 
   1767 void Mips64Assembler::Ffint_sW(VectorRegister wd, VectorRegister ws) {
   1768   CHECK(HasMsa());
   1769   EmitMsa2RF(0x19e, 0x0, ws, wd, 0x1e);
   1770 }
   1771 
   1772 void Mips64Assembler::Ffint_sD(VectorRegister wd, VectorRegister ws) {
   1773   CHECK(HasMsa());
   1774   EmitMsa2RF(0x19e, 0x1, ws, wd, 0x1e);
   1775 }
   1776 
   1777 void Mips64Assembler::Ftint_sW(VectorRegister wd, VectorRegister ws) {
   1778   CHECK(HasMsa());
   1779   EmitMsa2RF(0x19c, 0x0, ws, wd, 0x1e);
   1780 }
   1781 
   1782 void Mips64Assembler::Ftint_sD(VectorRegister wd, VectorRegister ws) {
   1783   CHECK(HasMsa());
   1784   EmitMsa2RF(0x19c, 0x1, ws, wd, 0x1e);
   1785 }
   1786 
   1787 void Mips64Assembler::SllB(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   1788   CHECK(HasMsa());
   1789   EmitMsa3R(0x0, 0x0, wt, ws, wd, 0xd);
   1790 }
   1791 
   1792 void Mips64Assembler::SllH(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   1793   CHECK(HasMsa());
   1794   EmitMsa3R(0x0, 0x1, wt, ws, wd, 0xd);
   1795 }
   1796 
   1797 void Mips64Assembler::SllW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   1798   CHECK(HasMsa());
   1799   EmitMsa3R(0x0, 0x2, wt, ws, wd, 0xd);
   1800 }
   1801 
   1802 void Mips64Assembler::SllD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   1803   CHECK(HasMsa());
   1804   EmitMsa3R(0x0, 0x3, wt, ws, wd, 0xd);
   1805 }
   1806 
   1807 void Mips64Assembler::SraB(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   1808   CHECK(HasMsa());
   1809   EmitMsa3R(0x1, 0x0, wt, ws, wd, 0xd);
   1810 }
   1811 
   1812 void Mips64Assembler::SraH(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   1813   CHECK(HasMsa());
   1814   EmitMsa3R(0x1, 0x1, wt, ws, wd, 0xd);
   1815 }
   1816 
   1817 void Mips64Assembler::SraW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   1818   CHECK(HasMsa());
   1819   EmitMsa3R(0x1, 0x2, wt, ws, wd, 0xd);
   1820 }
   1821 
   1822 void Mips64Assembler::SraD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   1823   CHECK(HasMsa());
   1824   EmitMsa3R(0x1, 0x3, wt, ws, wd, 0xd);
   1825 }
   1826 
   1827 void Mips64Assembler::SrlB(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   1828   CHECK(HasMsa());
   1829   EmitMsa3R(0x2, 0x0, wt, ws, wd, 0xd);
   1830 }
   1831 
   1832 void Mips64Assembler::SrlH(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   1833   CHECK(HasMsa());
   1834   EmitMsa3R(0x2, 0x1, wt, ws, wd, 0xd);
   1835 }
   1836 
   1837 void Mips64Assembler::SrlW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   1838   CHECK(HasMsa());
   1839   EmitMsa3R(0x2, 0x2, wt, ws, wd, 0xd);
   1840 }
   1841 
   1842 void Mips64Assembler::SrlD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   1843   CHECK(HasMsa());
   1844   EmitMsa3R(0x2, 0x3, wt, ws, wd, 0xd);
   1845 }
   1846 
   1847 void Mips64Assembler::SlliB(VectorRegister wd, VectorRegister ws, int shamt3) {
   1848   CHECK(HasMsa());
   1849   CHECK(IsUint<3>(shamt3)) << shamt3;
   1850   EmitMsaBIT(0x0, shamt3 | kMsaDfMByteMask, ws, wd, 0x9);
   1851 }
   1852 
   1853 void Mips64Assembler::SlliH(VectorRegister wd, VectorRegister ws, int shamt4) {
   1854   CHECK(HasMsa());
   1855   CHECK(IsUint<4>(shamt4)) << shamt4;
   1856   EmitMsaBIT(0x0, shamt4 | kMsaDfMHalfwordMask, ws, wd, 0x9);
   1857 }
   1858 
   1859 void Mips64Assembler::SlliW(VectorRegister wd, VectorRegister ws, int shamt5) {
   1860   CHECK(HasMsa());
   1861   CHECK(IsUint<5>(shamt5)) << shamt5;
   1862   EmitMsaBIT(0x0, shamt5 | kMsaDfMWordMask, ws, wd, 0x9);
   1863 }
   1864 
   1865 void Mips64Assembler::SlliD(VectorRegister wd, VectorRegister ws, int shamt6) {
   1866   CHECK(HasMsa());
   1867   CHECK(IsUint<6>(shamt6)) << shamt6;
   1868   EmitMsaBIT(0x0, shamt6 | kMsaDfMDoublewordMask, ws, wd, 0x9);
   1869 }
   1870 
   1871 void Mips64Assembler::SraiB(VectorRegister wd, VectorRegister ws, int shamt3) {
   1872   CHECK(HasMsa());
   1873   CHECK(IsUint<3>(shamt3)) << shamt3;
   1874   EmitMsaBIT(0x1, shamt3 | kMsaDfMByteMask, ws, wd, 0x9);
   1875 }
   1876 
   1877 void Mips64Assembler::SraiH(VectorRegister wd, VectorRegister ws, int shamt4) {
   1878   CHECK(HasMsa());
   1879   CHECK(IsUint<4>(shamt4)) << shamt4;
   1880   EmitMsaBIT(0x1, shamt4 | kMsaDfMHalfwordMask, ws, wd, 0x9);
   1881 }
   1882 
   1883 void Mips64Assembler::SraiW(VectorRegister wd, VectorRegister ws, int shamt5) {
   1884   CHECK(HasMsa());
   1885   CHECK(IsUint<5>(shamt5)) << shamt5;
   1886   EmitMsaBIT(0x1, shamt5 | kMsaDfMWordMask, ws, wd, 0x9);
   1887 }
   1888 
   1889 void Mips64Assembler::SraiD(VectorRegister wd, VectorRegister ws, int shamt6) {
   1890   CHECK(HasMsa());
   1891   CHECK(IsUint<6>(shamt6)) << shamt6;
   1892   EmitMsaBIT(0x1, shamt6 | kMsaDfMDoublewordMask, ws, wd, 0x9);
   1893 }
   1894 
   1895 void Mips64Assembler::SrliB(VectorRegister wd, VectorRegister ws, int shamt3) {
   1896   CHECK(HasMsa());
   1897   CHECK(IsUint<3>(shamt3)) << shamt3;
   1898   EmitMsaBIT(0x2, shamt3 | kMsaDfMByteMask, ws, wd, 0x9);
   1899 }
   1900 
   1901 void Mips64Assembler::SrliH(VectorRegister wd, VectorRegister ws, int shamt4) {
   1902   CHECK(HasMsa());
   1903   CHECK(IsUint<4>(shamt4)) << shamt4;
   1904   EmitMsaBIT(0x2, shamt4 | kMsaDfMHalfwordMask, ws, wd, 0x9);
   1905 }
   1906 
   1907 void Mips64Assembler::SrliW(VectorRegister wd, VectorRegister ws, int shamt5) {
   1908   CHECK(HasMsa());
   1909   CHECK(IsUint<5>(shamt5)) << shamt5;
   1910   EmitMsaBIT(0x2, shamt5 | kMsaDfMWordMask, ws, wd, 0x9);
   1911 }
   1912 
   1913 void Mips64Assembler::SrliD(VectorRegister wd, VectorRegister ws, int shamt6) {
   1914   CHECK(HasMsa());
   1915   CHECK(IsUint<6>(shamt6)) << shamt6;
   1916   EmitMsaBIT(0x2, shamt6 | kMsaDfMDoublewordMask, ws, wd, 0x9);
   1917 }
   1918 
   1919 void Mips64Assembler::MoveV(VectorRegister wd, VectorRegister ws) {
   1920   CHECK(HasMsa());
   1921   EmitMsaBIT(0x1, 0x3e, ws, wd, 0x19);
   1922 }
   1923 
   1924 void Mips64Assembler::SplatiB(VectorRegister wd, VectorRegister ws, int n4) {
   1925   CHECK(HasMsa());
   1926   CHECK(IsUint<4>(n4)) << n4;
   1927   EmitMsaELM(0x1, n4 | kMsaDfNByteMask, ws, wd, 0x19);
   1928 }
   1929 
   1930 void Mips64Assembler::SplatiH(VectorRegister wd, VectorRegister ws, int n3) {
   1931   CHECK(HasMsa());
   1932   CHECK(IsUint<3>(n3)) << n3;
   1933   EmitMsaELM(0x1, n3 | kMsaDfNHalfwordMask, ws, wd, 0x19);
   1934 }
   1935 
   1936 void Mips64Assembler::SplatiW(VectorRegister wd, VectorRegister ws, int n2) {
   1937   CHECK(HasMsa());
   1938   CHECK(IsUint<2>(n2)) << n2;
   1939   EmitMsaELM(0x1, n2 | kMsaDfNWordMask, ws, wd, 0x19);
   1940 }
   1941 
   1942 void Mips64Assembler::SplatiD(VectorRegister wd, VectorRegister ws, int n1) {
   1943   CHECK(HasMsa());
   1944   CHECK(IsUint<1>(n1)) << n1;
   1945   EmitMsaELM(0x1, n1 | kMsaDfNDoublewordMask, ws, wd, 0x19);
   1946 }
   1947 
   1948 void Mips64Assembler::Copy_sB(GpuRegister rd, VectorRegister ws, int n4) {
   1949   CHECK(HasMsa());
   1950   CHECK(IsUint<4>(n4)) << n4;
   1951   EmitMsaELM(0x2, n4 | kMsaDfNByteMask, ws, static_cast<VectorRegister>(rd), 0x19);
   1952 }
   1953 
   1954 void Mips64Assembler::Copy_sH(GpuRegister rd, VectorRegister ws, int n3) {
   1955   CHECK(HasMsa());
   1956   CHECK(IsUint<3>(n3)) << n3;
   1957   EmitMsaELM(0x2, n3 | kMsaDfNHalfwordMask, ws, static_cast<VectorRegister>(rd), 0x19);
   1958 }
   1959 
   1960 void Mips64Assembler::Copy_sW(GpuRegister rd, VectorRegister ws, int n2) {
   1961   CHECK(HasMsa());
   1962   CHECK(IsUint<2>(n2)) << n2;
   1963   EmitMsaELM(0x2, n2 | kMsaDfNWordMask, ws, static_cast<VectorRegister>(rd), 0x19);
   1964 }
   1965 
   1966 void Mips64Assembler::Copy_sD(GpuRegister rd, VectorRegister ws, int n1) {
   1967   CHECK(HasMsa());
   1968   CHECK(IsUint<1>(n1)) << n1;
   1969   EmitMsaELM(0x2, n1 | kMsaDfNDoublewordMask, ws, static_cast<VectorRegister>(rd), 0x19);
   1970 }
   1971 
   1972 void Mips64Assembler::Copy_uB(GpuRegister rd, VectorRegister ws, int n4) {
   1973   CHECK(HasMsa());
   1974   CHECK(IsUint<4>(n4)) << n4;
   1975   EmitMsaELM(0x3, n4 | kMsaDfNByteMask, ws, static_cast<VectorRegister>(rd), 0x19);
   1976 }
   1977 
   1978 void Mips64Assembler::Copy_uH(GpuRegister rd, VectorRegister ws, int n3) {
   1979   CHECK(HasMsa());
   1980   CHECK(IsUint<3>(n3)) << n3;
   1981   EmitMsaELM(0x3, n3 | kMsaDfNHalfwordMask, ws, static_cast<VectorRegister>(rd), 0x19);
   1982 }
   1983 
   1984 void Mips64Assembler::Copy_uW(GpuRegister rd, VectorRegister ws, int n2) {
   1985   CHECK(HasMsa());
   1986   CHECK(IsUint<2>(n2)) << n2;
   1987   EmitMsaELM(0x3, n2 | kMsaDfNWordMask, ws, static_cast<VectorRegister>(rd), 0x19);
   1988 }
   1989 
   1990 void Mips64Assembler::InsertB(VectorRegister wd, GpuRegister rs, int n4) {
   1991   CHECK(HasMsa());
   1992   CHECK(IsUint<4>(n4)) << n4;
   1993   EmitMsaELM(0x4, n4 | kMsaDfNByteMask, static_cast<VectorRegister>(rs), wd, 0x19);
   1994 }
   1995 
   1996 void Mips64Assembler::InsertH(VectorRegister wd, GpuRegister rs, int n3) {
   1997   CHECK(HasMsa());
   1998   CHECK(IsUint<3>(n3)) << n3;
   1999   EmitMsaELM(0x4, n3 | kMsaDfNHalfwordMask, static_cast<VectorRegister>(rs), wd, 0x19);
   2000 }
   2001 
   2002 void Mips64Assembler::InsertW(VectorRegister wd, GpuRegister rs, int n2) {
   2003   CHECK(HasMsa());
   2004   CHECK(IsUint<2>(n2)) << n2;
   2005   EmitMsaELM(0x4, n2 | kMsaDfNWordMask, static_cast<VectorRegister>(rs), wd, 0x19);
   2006 }
   2007 
   2008 void Mips64Assembler::InsertD(VectorRegister wd, GpuRegister rs, int n1) {
   2009   CHECK(HasMsa());
   2010   CHECK(IsUint<1>(n1)) << n1;
   2011   EmitMsaELM(0x4, n1 | kMsaDfNDoublewordMask, static_cast<VectorRegister>(rs), wd, 0x19);
   2012 }
   2013 
   2014 void Mips64Assembler::FillB(VectorRegister wd, GpuRegister rs) {
   2015   CHECK(HasMsa());
   2016   EmitMsa2R(0xc0, 0x0, static_cast<VectorRegister>(rs), wd, 0x1e);
   2017 }
   2018 
   2019 void Mips64Assembler::FillH(VectorRegister wd, GpuRegister rs) {
   2020   CHECK(HasMsa());
   2021   EmitMsa2R(0xc0, 0x1, static_cast<VectorRegister>(rs), wd, 0x1e);
   2022 }
   2023 
   2024 void Mips64Assembler::FillW(VectorRegister wd, GpuRegister rs) {
   2025   CHECK(HasMsa());
   2026   EmitMsa2R(0xc0, 0x2, static_cast<VectorRegister>(rs), wd, 0x1e);
   2027 }
   2028 
   2029 void Mips64Assembler::FillD(VectorRegister wd, GpuRegister rs) {
   2030   CHECK(HasMsa());
   2031   EmitMsa2R(0xc0, 0x3, static_cast<VectorRegister>(rs), wd, 0x1e);
   2032 }
   2033 
   2034 void Mips64Assembler::LdiB(VectorRegister wd, int imm8) {
   2035   CHECK(HasMsa());
   2036   CHECK(IsInt<8>(imm8)) << imm8;
   2037   EmitMsaI10(0x6, 0x0, imm8 & kMsaS10Mask, wd, 0x7);
   2038 }
   2039 
   2040 void Mips64Assembler::LdiH(VectorRegister wd, int imm10) {
   2041   CHECK(HasMsa());
   2042   CHECK(IsInt<10>(imm10)) << imm10;
   2043   EmitMsaI10(0x6, 0x1, imm10 & kMsaS10Mask, wd, 0x7);
   2044 }
   2045 
   2046 void Mips64Assembler::LdiW(VectorRegister wd, int imm10) {
   2047   CHECK(HasMsa());
   2048   CHECK(IsInt<10>(imm10)) << imm10;
   2049   EmitMsaI10(0x6, 0x2, imm10 & kMsaS10Mask, wd, 0x7);
   2050 }
   2051 
   2052 void Mips64Assembler::LdiD(VectorRegister wd, int imm10) {
   2053   CHECK(HasMsa());
   2054   CHECK(IsInt<10>(imm10)) << imm10;
   2055   EmitMsaI10(0x6, 0x3, imm10 & kMsaS10Mask, wd, 0x7);
   2056 }
   2057 
   2058 void Mips64Assembler::LdB(VectorRegister wd, GpuRegister rs, int offset) {
   2059   CHECK(HasMsa());
   2060   CHECK(IsInt<10>(offset)) << offset;
   2061   EmitMsaMI10(offset & kMsaS10Mask, rs, wd, 0x8, 0x0);
   2062 }
   2063 
   2064 void Mips64Assembler::LdH(VectorRegister wd, GpuRegister rs, int offset) {
   2065   CHECK(HasMsa());
   2066   CHECK(IsInt<11>(offset)) << offset;
   2067   CHECK_ALIGNED(offset, kMips64HalfwordSize);
   2068   EmitMsaMI10((offset >> TIMES_2) & kMsaS10Mask, rs, wd, 0x8, 0x1);
   2069 }
   2070 
   2071 void Mips64Assembler::LdW(VectorRegister wd, GpuRegister rs, int offset) {
   2072   CHECK(HasMsa());
   2073   CHECK(IsInt<12>(offset)) << offset;
   2074   CHECK_ALIGNED(offset, kMips64WordSize);
   2075   EmitMsaMI10((offset >> TIMES_4) & kMsaS10Mask, rs, wd, 0x8, 0x2);
   2076 }
   2077 
   2078 void Mips64Assembler::LdD(VectorRegister wd, GpuRegister rs, int offset) {
   2079   CHECK(HasMsa());
   2080   CHECK(IsInt<13>(offset)) << offset;
   2081   CHECK_ALIGNED(offset, kMips64DoublewordSize);
   2082   EmitMsaMI10((offset >> TIMES_8) & kMsaS10Mask, rs, wd, 0x8, 0x3);
   2083 }
   2084 
   2085 void Mips64Assembler::StB(VectorRegister wd, GpuRegister rs, int offset) {
   2086   CHECK(HasMsa());
   2087   CHECK(IsInt<10>(offset)) << offset;
   2088   EmitMsaMI10(offset & kMsaS10Mask, rs, wd, 0x9, 0x0);
   2089 }
   2090 
   2091 void Mips64Assembler::StH(VectorRegister wd, GpuRegister rs, int offset) {
   2092   CHECK(HasMsa());
   2093   CHECK(IsInt<11>(offset)) << offset;
   2094   CHECK_ALIGNED(offset, kMips64HalfwordSize);
   2095   EmitMsaMI10((offset >> TIMES_2) & kMsaS10Mask, rs, wd, 0x9, 0x1);
   2096 }
   2097 
   2098 void Mips64Assembler::StW(VectorRegister wd, GpuRegister rs, int offset) {
   2099   CHECK(HasMsa());
   2100   CHECK(IsInt<12>(offset)) << offset;
   2101   CHECK_ALIGNED(offset, kMips64WordSize);
   2102   EmitMsaMI10((offset >> TIMES_4) & kMsaS10Mask, rs, wd, 0x9, 0x2);
   2103 }
   2104 
   2105 void Mips64Assembler::StD(VectorRegister wd, GpuRegister rs, int offset) {
   2106   CHECK(HasMsa());
   2107   CHECK(IsInt<13>(offset)) << offset;
   2108   CHECK_ALIGNED(offset, kMips64DoublewordSize);
   2109   EmitMsaMI10((offset >> TIMES_8) & kMsaS10Mask, rs, wd, 0x9, 0x3);
   2110 }
   2111 
   2112 void Mips64Assembler::IlvlB(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   2113   CHECK(HasMsa());
   2114   EmitMsa3R(0x4, 0x0, wt, ws, wd, 0x14);
   2115 }
   2116 
   2117 void Mips64Assembler::IlvlH(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   2118   CHECK(HasMsa());
   2119   EmitMsa3R(0x4, 0x1, wt, ws, wd, 0x14);
   2120 }
   2121 
   2122 void Mips64Assembler::IlvlW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   2123   CHECK(HasMsa());
   2124   EmitMsa3R(0x4, 0x2, wt, ws, wd, 0x14);
   2125 }
   2126 
   2127 void Mips64Assembler::IlvlD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   2128   CHECK(HasMsa());
   2129   EmitMsa3R(0x4, 0x3, wt, ws, wd, 0x14);
   2130 }
   2131 
   2132 void Mips64Assembler::IlvrB(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   2133   CHECK(HasMsa());
   2134   EmitMsa3R(0x5, 0x0, wt, ws, wd, 0x14);
   2135 }
   2136 
   2137 void Mips64Assembler::IlvrH(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   2138   CHECK(HasMsa());
   2139   EmitMsa3R(0x5, 0x1, wt, ws, wd, 0x14);
   2140 }
   2141 
   2142 void Mips64Assembler::IlvrW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   2143   CHECK(HasMsa());
   2144   EmitMsa3R(0x5, 0x2, wt, ws, wd, 0x14);
   2145 }
   2146 
   2147 void Mips64Assembler::IlvrD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   2148   CHECK(HasMsa());
   2149   EmitMsa3R(0x5, 0x3, wt, ws, wd, 0x14);
   2150 }
   2151 
   2152 void Mips64Assembler::IlvevB(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   2153   CHECK(HasMsa());
   2154   EmitMsa3R(0x6, 0x0, wt, ws, wd, 0x14);
   2155 }
   2156 
   2157 void Mips64Assembler::IlvevH(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   2158   CHECK(HasMsa());
   2159   EmitMsa3R(0x6, 0x1, wt, ws, wd, 0x14);
   2160 }
   2161 
   2162 void Mips64Assembler::IlvevW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   2163   CHECK(HasMsa());
   2164   EmitMsa3R(0x6, 0x2, wt, ws, wd, 0x14);
   2165 }
   2166 
   2167 void Mips64Assembler::IlvevD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   2168   CHECK(HasMsa());
   2169   EmitMsa3R(0x6, 0x3, wt, ws, wd, 0x14);
   2170 }
   2171 
   2172 void Mips64Assembler::IlvodB(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   2173   CHECK(HasMsa());
   2174   EmitMsa3R(0x7, 0x0, wt, ws, wd, 0x14);
   2175 }
   2176 
   2177 void Mips64Assembler::IlvodH(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   2178   CHECK(HasMsa());
   2179   EmitMsa3R(0x7, 0x1, wt, ws, wd, 0x14);
   2180 }
   2181 
   2182 void Mips64Assembler::IlvodW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   2183   CHECK(HasMsa());
   2184   EmitMsa3R(0x7, 0x2, wt, ws, wd, 0x14);
   2185 }
   2186 
   2187 void Mips64Assembler::IlvodD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   2188   CHECK(HasMsa());
   2189   EmitMsa3R(0x7, 0x3, wt, ws, wd, 0x14);
   2190 }
   2191 
   2192 void Mips64Assembler::MaddvB(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   2193   CHECK(HasMsa());
   2194   EmitMsa3R(0x1, 0x0, wt, ws, wd, 0x12);
   2195 }
   2196 
   2197 void Mips64Assembler::MaddvH(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   2198   CHECK(HasMsa());
   2199   EmitMsa3R(0x1, 0x1, wt, ws, wd, 0x12);
   2200 }
   2201 
   2202 void Mips64Assembler::MaddvW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   2203   CHECK(HasMsa());
   2204   EmitMsa3R(0x1, 0x2, wt, ws, wd, 0x12);
   2205 }
   2206 
   2207 void Mips64Assembler::MaddvD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   2208   CHECK(HasMsa());
   2209   EmitMsa3R(0x1, 0x3, wt, ws, wd, 0x12);
   2210 }
   2211 
   2212 void Mips64Assembler::MsubvB(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   2213   CHECK(HasMsa());
   2214   EmitMsa3R(0x2, 0x0, wt, ws, wd, 0x12);
   2215 }
   2216 
   2217 void Mips64Assembler::MsubvH(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   2218   CHECK(HasMsa());
   2219   EmitMsa3R(0x2, 0x1, wt, ws, wd, 0x12);
   2220 }
   2221 
   2222 void Mips64Assembler::MsubvW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   2223   CHECK(HasMsa());
   2224   EmitMsa3R(0x2, 0x2, wt, ws, wd, 0x12);
   2225 }
   2226 
   2227 void Mips64Assembler::MsubvD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   2228   CHECK(HasMsa());
   2229   EmitMsa3R(0x2, 0x3, wt, ws, wd, 0x12);
   2230 }
   2231 
   2232 void Mips64Assembler::FmaddW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   2233   CHECK(HasMsa());
   2234   EmitMsa3R(0x2, 0x0, wt, ws, wd, 0x1b);
   2235 }
   2236 
   2237 void Mips64Assembler::FmaddD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   2238   CHECK(HasMsa());
   2239   EmitMsa3R(0x2, 0x1, wt, ws, wd, 0x1b);
   2240 }
   2241 
   2242 void Mips64Assembler::FmsubW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   2243   CHECK(HasMsa());
   2244   EmitMsa3R(0x2, 0x2, wt, ws, wd, 0x1b);
   2245 }
   2246 
   2247 void Mips64Assembler::FmsubD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   2248   CHECK(HasMsa());
   2249   EmitMsa3R(0x2, 0x3, wt, ws, wd, 0x1b);
   2250 }
   2251 
   2252 void Mips64Assembler::Hadd_sH(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   2253   CHECK(HasMsa());
   2254   EmitMsa3R(0x4, 0x1, wt, ws, wd, 0x15);
   2255 }
   2256 
   2257 void Mips64Assembler::Hadd_sW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   2258   CHECK(HasMsa());
   2259   EmitMsa3R(0x4, 0x2, wt, ws, wd, 0x15);
   2260 }
   2261 
   2262 void Mips64Assembler::Hadd_sD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   2263   CHECK(HasMsa());
   2264   EmitMsa3R(0x4, 0x3, wt, ws, wd, 0x15);
   2265 }
   2266 
   2267 void Mips64Assembler::Hadd_uH(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   2268   CHECK(HasMsa());
   2269   EmitMsa3R(0x5, 0x1, wt, ws, wd, 0x15);
   2270 }
   2271 
   2272 void Mips64Assembler::Hadd_uW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   2273   CHECK(HasMsa());
   2274   EmitMsa3R(0x5, 0x2, wt, ws, wd, 0x15);
   2275 }
   2276 
   2277 void Mips64Assembler::Hadd_uD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   2278   CHECK(HasMsa());
   2279   EmitMsa3R(0x5, 0x3, wt, ws, wd, 0x15);
   2280 }
   2281 
   2282 void Mips64Assembler::ReplicateFPToVectorRegister(VectorRegister dst,
   2283                                                   FpuRegister src,
   2284                                                   bool is_double) {
   2285   // Float or double in FPU register Fx can be considered as 0th element in vector register Wx.
   2286   if (is_double) {
   2287     SplatiD(dst, static_cast<VectorRegister>(src), 0);
   2288   } else {
   2289     SplatiW(dst, static_cast<VectorRegister>(src), 0);
   2290   }
   2291 }
   2292 
   2293 void Mips64Assembler::LoadConst32(GpuRegister rd, int32_t value) {
   2294   TemplateLoadConst32(this, rd, value);
   2295 }
   2296 
   2297 // This function is only used for testing purposes.
   2298 void Mips64Assembler::RecordLoadConst64Path(int value ATTRIBUTE_UNUSED) {
   2299 }
   2300 
   2301 void Mips64Assembler::LoadConst64(GpuRegister rd, int64_t value) {
   2302   TemplateLoadConst64(this, rd, value);
   2303 }
   2304 
   2305 void Mips64Assembler::Addiu32(GpuRegister rt, GpuRegister rs, int32_t value) {
   2306   if (IsInt<16>(value)) {
   2307     Addiu(rt, rs, value);
   2308   } else {
   2309     int16_t high = High16Bits(value);
   2310     int16_t low = Low16Bits(value);
   2311     high += (low < 0) ? 1 : 0;  // Account for sign extension in addiu.
   2312     Aui(rt, rs, high);
   2313     if (low != 0) {
   2314       Addiu(rt, rt, low);
   2315     }
   2316   }
   2317 }
   2318 
   2319 // TODO: don't use rtmp, use daui, dahi, dati.
   2320 void Mips64Assembler::Daddiu64(GpuRegister rt, GpuRegister rs, int64_t value, GpuRegister rtmp) {
   2321   CHECK_NE(rs, rtmp);
   2322   if (IsInt<16>(value)) {
   2323     Daddiu(rt, rs, value);
   2324   } else {
   2325     LoadConst64(rtmp, value);
   2326     Daddu(rt, rs, rtmp);
   2327   }
   2328 }
   2329 
   2330 void Mips64Assembler::Branch::InitShortOrLong(Mips64Assembler::Branch::OffsetBits offset_size,
   2331                                               Mips64Assembler::Branch::Type short_type,
   2332                                               Mips64Assembler::Branch::Type long_type) {
   2333   type_ = (offset_size <= branch_info_[short_type].offset_size) ? short_type : long_type;
   2334 }
   2335 
   2336 void Mips64Assembler::Branch::InitializeType(Type initial_type, bool is_r6) {
   2337   OffsetBits offset_size_needed = GetOffsetSizeNeeded(location_, target_);
   2338   if (is_r6) {
   2339     // R6
   2340     switch (initial_type) {
   2341       case kLabel:
   2342       case kLiteral:
   2343       case kLiteralUnsigned:
   2344       case kLiteralLong:
   2345         CHECK(!IsResolved());
   2346         type_ = initial_type;
   2347         break;
   2348       case kCall:
   2349         InitShortOrLong(offset_size_needed, kCall, kLongCall);
   2350         break;
   2351       case kCondBranch:
   2352         switch (condition_) {
   2353           case kUncond:
   2354             InitShortOrLong(offset_size_needed, kUncondBranch, kLongUncondBranch);
   2355             break;
   2356           case kCondEQZ:
   2357           case kCondNEZ:
   2358             // Special case for beqzc/bnezc with longer offset than in other b<cond>c instructions.
   2359             type_ = (offset_size_needed <= kOffset23) ? kCondBranch : kLongCondBranch;
   2360             break;
   2361           default:
   2362             InitShortOrLong(offset_size_needed, kCondBranch, kLongCondBranch);
   2363             break;
   2364         }
   2365         break;
   2366       case kBareCall:
   2367         type_ = kBareCall;
   2368         CHECK_LE(offset_size_needed, GetOffsetSize());
   2369         break;
   2370       case kBareCondBranch:
   2371         type_ = (condition_ == kUncond) ? kBareUncondBranch : kBareCondBranch;
   2372         CHECK_LE(offset_size_needed, GetOffsetSize());
   2373         break;
   2374       default:
   2375         LOG(FATAL) << "Unexpected branch type " << initial_type;
   2376         UNREACHABLE();
   2377     }
   2378   } else {
   2379     // R2
   2380     CHECK_EQ(initial_type, kBareCondBranch);
   2381     switch (condition_) {
   2382       case kCondLTZ:
   2383       case kCondGEZ:
   2384       case kCondLEZ:
   2385       case kCondGTZ:
   2386       case kCondEQ:
   2387       case kCondNE:
   2388       case kCondEQZ:
   2389       case kCondNEZ:
   2390         break;
   2391       default:
   2392         LOG(FATAL) << "Unexpected R2 branch condition " << condition_;
   2393         UNREACHABLE();
   2394     }
   2395     type_ = kR2BareCondBranch;
   2396     CHECK_LE(offset_size_needed, GetOffsetSize());
   2397   }
   2398   old_type_ = type_;
   2399 }
   2400 
   2401 bool Mips64Assembler::Branch::IsNop(BranchCondition condition, GpuRegister lhs, GpuRegister rhs) {
   2402   switch (condition) {
   2403     case kCondLT:
   2404     case kCondGT:
   2405     case kCondNE:
   2406     case kCondLTU:
   2407       return lhs == rhs;
   2408     default:
   2409       return false;
   2410   }
   2411 }
   2412 
   2413 bool Mips64Assembler::Branch::IsUncond(BranchCondition condition,
   2414                                        GpuRegister lhs,
   2415                                        GpuRegister rhs) {
   2416   switch (condition) {
   2417     case kUncond:
   2418       return true;
   2419     case kCondGE:
   2420     case kCondLE:
   2421     case kCondEQ:
   2422     case kCondGEU:
   2423       return lhs == rhs;
   2424     default:
   2425       return false;
   2426   }
   2427 }
   2428 
   2429 Mips64Assembler::Branch::Branch(uint32_t location, uint32_t target, bool is_call, bool is_bare)
   2430     : old_location_(location),
   2431       location_(location),
   2432       target_(target),
   2433       lhs_reg_(ZERO),
   2434       rhs_reg_(ZERO),
   2435       condition_(kUncond) {
   2436   InitializeType(
   2437       (is_call ? (is_bare ? kBareCall : kCall) : (is_bare ? kBareCondBranch : kCondBranch)),
   2438       /* is_r6 */ true);
   2439 }
   2440 
   2441 Mips64Assembler::Branch::Branch(bool is_r6,
   2442                                 uint32_t location,
   2443                                 uint32_t target,
   2444                                 Mips64Assembler::BranchCondition condition,
   2445                                 GpuRegister lhs_reg,
   2446                                 GpuRegister rhs_reg,
   2447                                 bool is_bare)
   2448     : old_location_(location),
   2449       location_(location),
   2450       target_(target),
   2451       lhs_reg_(lhs_reg),
   2452       rhs_reg_(rhs_reg),
   2453       condition_(condition) {
   2454   CHECK_NE(condition, kUncond);
   2455   switch (condition) {
   2456     case kCondEQ:
   2457     case kCondNE:
   2458     case kCondLT:
   2459     case kCondGE:
   2460     case kCondLE:
   2461     case kCondGT:
   2462     case kCondLTU:
   2463     case kCondGEU:
   2464       CHECK_NE(lhs_reg, ZERO);
   2465       CHECK_NE(rhs_reg, ZERO);
   2466       break;
   2467     case kCondLTZ:
   2468     case kCondGEZ:
   2469     case kCondLEZ:
   2470     case kCondGTZ:
   2471     case kCondEQZ:
   2472     case kCondNEZ:
   2473       CHECK_NE(lhs_reg, ZERO);
   2474       CHECK_EQ(rhs_reg, ZERO);
   2475       break;
   2476     case kCondF:
   2477     case kCondT:
   2478       CHECK_EQ(rhs_reg, ZERO);
   2479       break;
   2480     case kUncond:
   2481       UNREACHABLE();
   2482   }
   2483   CHECK(!IsNop(condition, lhs_reg, rhs_reg));
   2484   if (IsUncond(condition, lhs_reg, rhs_reg)) {
   2485     // Branch condition is always true, make the branch unconditional.
   2486     condition_ = kUncond;
   2487   }
   2488   InitializeType((is_bare ? kBareCondBranch : kCondBranch), is_r6);
   2489 }
   2490 
   2491 Mips64Assembler::Branch::Branch(uint32_t location, GpuRegister dest_reg, Type label_or_literal_type)
   2492     : old_location_(location),
   2493       location_(location),
   2494       target_(kUnresolved),
   2495       lhs_reg_(dest_reg),
   2496       rhs_reg_(ZERO),
   2497       condition_(kUncond) {
   2498   CHECK_NE(dest_reg, ZERO);
   2499   InitializeType(label_or_literal_type, /* is_r6 */ true);
   2500 }
   2501 
   2502 Mips64Assembler::BranchCondition Mips64Assembler::Branch::OppositeCondition(
   2503     Mips64Assembler::BranchCondition cond) {
   2504   switch (cond) {
   2505     case kCondLT:
   2506       return kCondGE;
   2507     case kCondGE:
   2508       return kCondLT;
   2509     case kCondLE:
   2510       return kCondGT;
   2511     case kCondGT:
   2512       return kCondLE;
   2513     case kCondLTZ:
   2514       return kCondGEZ;
   2515     case kCondGEZ:
   2516       return kCondLTZ;
   2517     case kCondLEZ:
   2518       return kCondGTZ;
   2519     case kCondGTZ:
   2520       return kCondLEZ;
   2521     case kCondEQ:
   2522       return kCondNE;
   2523     case kCondNE:
   2524       return kCondEQ;
   2525     case kCondEQZ:
   2526       return kCondNEZ;
   2527     case kCondNEZ:
   2528       return kCondEQZ;
   2529     case kCondLTU:
   2530       return kCondGEU;
   2531     case kCondGEU:
   2532       return kCondLTU;
   2533     case kCondF:
   2534       return kCondT;
   2535     case kCondT:
   2536       return kCondF;
   2537     case kUncond:
   2538       LOG(FATAL) << "Unexpected branch condition " << cond;
   2539   }
   2540   UNREACHABLE();
   2541 }
   2542 
   2543 Mips64Assembler::Branch::Type Mips64Assembler::Branch::GetType() const {
   2544   return type_;
   2545 }
   2546 
   2547 Mips64Assembler::BranchCondition Mips64Assembler::Branch::GetCondition() const {
   2548   return condition_;
   2549 }
   2550 
   2551 GpuRegister Mips64Assembler::Branch::GetLeftRegister() const {
   2552   return lhs_reg_;
   2553 }
   2554 
   2555 GpuRegister Mips64Assembler::Branch::GetRightRegister() const {
   2556   return rhs_reg_;
   2557 }
   2558 
   2559 uint32_t Mips64Assembler::Branch::GetTarget() const {
   2560   return target_;
   2561 }
   2562 
   2563 uint32_t Mips64Assembler::Branch::GetLocation() const {
   2564   return location_;
   2565 }
   2566 
   2567 uint32_t Mips64Assembler::Branch::GetOldLocation() const {
   2568   return old_location_;
   2569 }
   2570 
   2571 uint32_t Mips64Assembler::Branch::GetLength() const {
   2572   return branch_info_[type_].length;
   2573 }
   2574 
   2575 uint32_t Mips64Assembler::Branch::GetOldLength() const {
   2576   return branch_info_[old_type_].length;
   2577 }
   2578 
   2579 uint32_t Mips64Assembler::Branch::GetSize() const {
   2580   return GetLength() * sizeof(uint32_t);
   2581 }
   2582 
   2583 uint32_t Mips64Assembler::Branch::GetOldSize() const {
   2584   return GetOldLength() * sizeof(uint32_t);
   2585 }
   2586 
   2587 uint32_t Mips64Assembler::Branch::GetEndLocation() const {
   2588   return GetLocation() + GetSize();
   2589 }
   2590 
   2591 uint32_t Mips64Assembler::Branch::GetOldEndLocation() const {
   2592   return GetOldLocation() + GetOldSize();
   2593 }
   2594 
   2595 bool Mips64Assembler::Branch::IsBare() const {
   2596   switch (type_) {
   2597     // R6 short branches (can't be promoted to long), forbidden/delay slots filled manually.
   2598     case kBareUncondBranch:
   2599     case kBareCondBranch:
   2600     case kBareCall:
   2601     // R2 short branches (can't be promoted to long), delay slots filled manually.
   2602     case kR2BareCondBranch:
   2603       return true;
   2604     default:
   2605       return false;
   2606   }
   2607 }
   2608 
   2609 bool Mips64Assembler::Branch::IsLong() const {
   2610   switch (type_) {
   2611     // R6 short branches (can be promoted to long).
   2612     case kUncondBranch:
   2613     case kCondBranch:
   2614     case kCall:
   2615     // R6 short branches (can't be promoted to long), forbidden/delay slots filled manually.
   2616     case kBareUncondBranch:
   2617     case kBareCondBranch:
   2618     case kBareCall:
   2619     // R2 short branches (can't be promoted to long), delay slots filled manually.
   2620     case kR2BareCondBranch:
   2621     // Near label.
   2622     case kLabel:
   2623     // Near literals.
   2624     case kLiteral:
   2625     case kLiteralUnsigned:
   2626     case kLiteralLong:
   2627       return false;
   2628     // Long branches.
   2629     case kLongUncondBranch:
   2630     case kLongCondBranch:
   2631     case kLongCall:
   2632     // Far label.
   2633     case kFarLabel:
   2634     // Far literals.
   2635     case kFarLiteral:
   2636     case kFarLiteralUnsigned:
   2637     case kFarLiteralLong:
   2638       return true;
   2639   }
   2640   UNREACHABLE();
   2641 }
   2642 
   2643 bool Mips64Assembler::Branch::IsResolved() const {
   2644   return target_ != kUnresolved;
   2645 }
   2646 
   2647 Mips64Assembler::Branch::OffsetBits Mips64Assembler::Branch::GetOffsetSize() const {
   2648   bool r6_cond_branch = (type_ == kCondBranch || type_ == kBareCondBranch);
   2649   OffsetBits offset_size =
   2650       (r6_cond_branch && (condition_ == kCondEQZ || condition_ == kCondNEZ))
   2651           ? kOffset23
   2652           : branch_info_[type_].offset_size;
   2653   return offset_size;
   2654 }
   2655 
   2656 Mips64Assembler::Branch::OffsetBits Mips64Assembler::Branch::GetOffsetSizeNeeded(uint32_t location,
   2657                                                                                  uint32_t target) {
   2658   // For unresolved targets assume the shortest encoding
   2659   // (later it will be made longer if needed).
   2660   if (target == kUnresolved)
   2661     return kOffset16;
   2662   int64_t distance = static_cast<int64_t>(target) - location;
   2663   // To simplify calculations in composite branches consisting of multiple instructions
   2664   // bump up the distance by a value larger than the max byte size of a composite branch.
   2665   distance += (distance >= 0) ? kMaxBranchSize : -kMaxBranchSize;
   2666   if (IsInt<kOffset16>(distance))
   2667     return kOffset16;
   2668   else if (IsInt<kOffset18>(distance))
   2669     return kOffset18;
   2670   else if (IsInt<kOffset21>(distance))
   2671     return kOffset21;
   2672   else if (IsInt<kOffset23>(distance))
   2673     return kOffset23;
   2674   else if (IsInt<kOffset28>(distance))
   2675     return kOffset28;
   2676   return kOffset32;
   2677 }
   2678 
   2679 void Mips64Assembler::Branch::Resolve(uint32_t target) {
   2680   target_ = target;
   2681 }
   2682 
   2683 void Mips64Assembler::Branch::Relocate(uint32_t expand_location, uint32_t delta) {
   2684   if (location_ > expand_location) {
   2685     location_ += delta;
   2686   }
   2687   if (!IsResolved()) {
   2688     return;  // Don't know the target yet.
   2689   }
   2690   if (target_ > expand_location) {
   2691     target_ += delta;
   2692   }
   2693 }
   2694 
   2695 void Mips64Assembler::Branch::PromoteToLong() {
   2696   CHECK(!IsBare());  // Bare branches do not promote.
   2697   switch (type_) {
   2698     // R6 short branches (can be promoted to long).
   2699     case kUncondBranch:
   2700       type_ = kLongUncondBranch;
   2701       break;
   2702     case kCondBranch:
   2703       type_ = kLongCondBranch;
   2704       break;
   2705     case kCall:
   2706       type_ = kLongCall;
   2707       break;
   2708     // Near label.
   2709     case kLabel:
   2710       type_ = kFarLabel;
   2711       break;
   2712     // Near literals.
   2713     case kLiteral:
   2714       type_ = kFarLiteral;
   2715       break;
   2716     case kLiteralUnsigned:
   2717       type_ = kFarLiteralUnsigned;
   2718       break;
   2719     case kLiteralLong:
   2720       type_ = kFarLiteralLong;
   2721       break;
   2722     default:
   2723       // Note: 'type_' is already long.
   2724       break;
   2725   }
   2726   CHECK(IsLong());
   2727 }
   2728 
   2729 uint32_t Mips64Assembler::Branch::PromoteIfNeeded(uint32_t max_short_distance) {
   2730   // If the branch is still unresolved or already long, nothing to do.
   2731   if (IsLong() || !IsResolved()) {
   2732     return 0;
   2733   }
   2734   // Promote the short branch to long if the offset size is too small
   2735   // to hold the distance between location_ and target_.
   2736   if (GetOffsetSizeNeeded(location_, target_) > GetOffsetSize()) {
   2737     PromoteToLong();
   2738     uint32_t old_size = GetOldSize();
   2739     uint32_t new_size = GetSize();
   2740     CHECK_GT(new_size, old_size);
   2741     return new_size - old_size;
   2742   }
   2743   // The following logic is for debugging/testing purposes.
   2744   // Promote some short branches to long when it's not really required.
   2745   if (UNLIKELY(max_short_distance != std::numeric_limits<uint32_t>::max() && !IsBare())) {
   2746     int64_t distance = static_cast<int64_t>(target_) - location_;
   2747     distance = (distance >= 0) ? distance : -distance;
   2748     if (distance >= max_short_distance) {
   2749       PromoteToLong();
   2750       uint32_t old_size = GetOldSize();
   2751       uint32_t new_size = GetSize();
   2752       CHECK_GT(new_size, old_size);
   2753       return new_size - old_size;
   2754     }
   2755   }
   2756   return 0;
   2757 }
   2758 
   2759 uint32_t Mips64Assembler::Branch::GetOffsetLocation() const {
   2760   return location_ + branch_info_[type_].instr_offset * sizeof(uint32_t);
   2761 }
   2762 
   2763 uint32_t Mips64Assembler::Branch::GetOffset() const {
   2764   CHECK(IsResolved());
   2765   uint32_t ofs_mask = 0xFFFFFFFF >> (32 - GetOffsetSize());
   2766   // Calculate the byte distance between instructions and also account for
   2767   // different PC-relative origins.
   2768   uint32_t offset_location = GetOffsetLocation();
   2769   if (type_ == kLiteralLong) {
   2770     // Special case for the ldpc instruction, whose address (PC) is rounded down to
   2771     // a multiple of 8 before adding the offset.
   2772     // Note, branch promotion has already taken care of aligning `target_` to an
   2773     // address that's a multiple of 8.
   2774     offset_location = RoundDown(offset_location, sizeof(uint64_t));
   2775   }
   2776   uint32_t offset = target_ - offset_location - branch_info_[type_].pc_org * sizeof(uint32_t);
   2777   // Prepare the offset for encoding into the instruction(s).
   2778   offset = (offset & ofs_mask) >> branch_info_[type_].offset_shift;
   2779   return offset;
   2780 }
   2781 
   2782 Mips64Assembler::Branch* Mips64Assembler::GetBranch(uint32_t branch_id) {
   2783   CHECK_LT(branch_id, branches_.size());
   2784   return &branches_[branch_id];
   2785 }
   2786 
   2787 const Mips64Assembler::Branch* Mips64Assembler::GetBranch(uint32_t branch_id) const {
   2788   CHECK_LT(branch_id, branches_.size());
   2789   return &branches_[branch_id];
   2790 }
   2791 
   2792 void Mips64Assembler::Bind(Mips64Label* label) {
   2793   CHECK(!label->IsBound());
   2794   uint32_t bound_pc = buffer_.Size();
   2795 
   2796   // Walk the list of branches referring to and preceding this label.
   2797   // Store the previously unknown target addresses in them.
   2798   while (label->IsLinked()) {
   2799     uint32_t branch_id = label->Position();
   2800     Branch* branch = GetBranch(branch_id);
   2801     branch->Resolve(bound_pc);
   2802 
   2803     uint32_t branch_location = branch->GetLocation();
   2804     // Extract the location of the previous branch in the list (walking the list backwards;
   2805     // the previous branch ID was stored in the space reserved for this branch).
   2806     uint32_t prev = buffer_.Load<uint32_t>(branch_location);
   2807 
   2808     // On to the previous branch in the list...
   2809     label->position_ = prev;
   2810   }
   2811 
   2812   // Now make the label object contain its own location (relative to the end of the preceding
   2813   // branch, if any; it will be used by the branches referring to and following this label).
   2814   label->prev_branch_id_plus_one_ = branches_.size();
   2815   if (label->prev_branch_id_plus_one_) {
   2816     uint32_t branch_id = label->prev_branch_id_plus_one_ - 1;
   2817     const Branch* branch = GetBranch(branch_id);
   2818     bound_pc -= branch->GetEndLocation();
   2819   }
   2820   label->BindTo(bound_pc);
   2821 }
   2822 
   2823 uint32_t Mips64Assembler::GetLabelLocation(const Mips64Label* label) const {
   2824   CHECK(label->IsBound());
   2825   uint32_t target = label->Position();
   2826   if (label->prev_branch_id_plus_one_) {
   2827     // Get label location based on the branch preceding it.
   2828     uint32_t branch_id = label->prev_branch_id_plus_one_ - 1;
   2829     const Branch* branch = GetBranch(branch_id);
   2830     target += branch->GetEndLocation();
   2831   }
   2832   return target;
   2833 }
   2834 
   2835 uint32_t Mips64Assembler::GetAdjustedPosition(uint32_t old_position) {
   2836   // We can reconstruct the adjustment by going through all the branches from the beginning
   2837   // up to the old_position. Since we expect AdjustedPosition() to be called in a loop
   2838   // with increasing old_position, we can use the data from last AdjustedPosition() to
   2839   // continue where we left off and the whole loop should be O(m+n) where m is the number
   2840   // of positions to adjust and n is the number of branches.
   2841   if (old_position < last_old_position_) {
   2842     last_position_adjustment_ = 0;
   2843     last_old_position_ = 0;
   2844     last_branch_id_ = 0;
   2845   }
   2846   while (last_branch_id_ != branches_.size()) {
   2847     const Branch* branch = GetBranch(last_branch_id_);
   2848     if (branch->GetLocation() >= old_position + last_position_adjustment_) {
   2849       break;
   2850     }
   2851     last_position_adjustment_ += branch->GetSize() - branch->GetOldSize();
   2852     ++last_branch_id_;
   2853   }
   2854   last_old_position_ = old_position;
   2855   return old_position + last_position_adjustment_;
   2856 }
   2857 
   2858 void Mips64Assembler::FinalizeLabeledBranch(Mips64Label* label) {
   2859   uint32_t length = branches_.back().GetLength();
   2860   if (!label->IsBound()) {
   2861     // Branch forward (to a following label), distance is unknown.
   2862     // The first branch forward will contain 0, serving as the terminator of
   2863     // the list of forward-reaching branches.
   2864     Emit(label->position_);
   2865     length--;
   2866     // Now make the label object point to this branch
   2867     // (this forms a linked list of branches preceding this label).
   2868     uint32_t branch_id = branches_.size() - 1;
   2869     label->LinkTo(branch_id);
   2870   }
   2871   // Reserve space for the branch.
   2872   while (length--) {
   2873     Nop();
   2874   }
   2875 }
   2876 
   2877 void Mips64Assembler::Buncond(Mips64Label* label, bool is_bare) {
   2878   uint32_t target = label->IsBound() ? GetLabelLocation(label) : Branch::kUnresolved;
   2879   branches_.emplace_back(buffer_.Size(), target, /* is_call */ false, is_bare);
   2880   FinalizeLabeledBranch(label);
   2881 }
   2882 
   2883 void Mips64Assembler::Bcond(Mips64Label* label,
   2884                             bool is_r6,
   2885                             bool is_bare,
   2886                             BranchCondition condition,
   2887                             GpuRegister lhs,
   2888                             GpuRegister rhs) {
   2889   // If lhs = rhs, this can be a NOP.
   2890   if (Branch::IsNop(condition, lhs, rhs)) {
   2891     return;
   2892   }
   2893   uint32_t target = label->IsBound() ? GetLabelLocation(label) : Branch::kUnresolved;
   2894   branches_.emplace_back(is_r6, buffer_.Size(), target, condition, lhs, rhs, is_bare);
   2895   FinalizeLabeledBranch(label);
   2896 }
   2897 
   2898 void Mips64Assembler::Call(Mips64Label* label, bool is_bare) {
   2899   uint32_t target = label->IsBound() ? GetLabelLocation(label) : Branch::kUnresolved;
   2900   branches_.emplace_back(buffer_.Size(), target, /* is_call */ true, is_bare);
   2901   FinalizeLabeledBranch(label);
   2902 }
   2903 
   2904 void Mips64Assembler::LoadLabelAddress(GpuRegister dest_reg, Mips64Label* label) {
   2905   // Label address loads are treated as pseudo branches since they require very similar handling.
   2906   DCHECK(!label->IsBound());
   2907   branches_.emplace_back(buffer_.Size(), dest_reg, Branch::kLabel);
   2908   FinalizeLabeledBranch(label);
   2909 }
   2910 
   2911 Literal* Mips64Assembler::NewLiteral(size_t size, const uint8_t* data) {
   2912   // We don't support byte and half-word literals.
   2913   if (size == 4u) {
   2914     literals_.emplace_back(size, data);
   2915     return &literals_.back();
   2916   } else {
   2917     DCHECK_EQ(size, 8u);
   2918     long_literals_.emplace_back(size, data);
   2919     return &long_literals_.back();
   2920   }
   2921 }
   2922 
   2923 void Mips64Assembler::LoadLiteral(GpuRegister dest_reg,
   2924                                   LoadOperandType load_type,
   2925                                   Literal* literal) {
   2926   // Literal loads are treated as pseudo branches since they require very similar handling.
   2927   Branch::Type literal_type;
   2928   switch (load_type) {
   2929     case kLoadWord:
   2930       DCHECK_EQ(literal->GetSize(), 4u);
   2931       literal_type = Branch::kLiteral;
   2932       break;
   2933     case kLoadUnsignedWord:
   2934       DCHECK_EQ(literal->GetSize(), 4u);
   2935       literal_type = Branch::kLiteralUnsigned;
   2936       break;
   2937     case kLoadDoubleword:
   2938       DCHECK_EQ(literal->GetSize(), 8u);
   2939       literal_type = Branch::kLiteralLong;
   2940       break;
   2941     default:
   2942       LOG(FATAL) << "Unexpected literal load type " << load_type;
   2943       UNREACHABLE();
   2944   }
   2945   Mips64Label* label = literal->GetLabel();
   2946   DCHECK(!label->IsBound());
   2947   branches_.emplace_back(buffer_.Size(), dest_reg, literal_type);
   2948   FinalizeLabeledBranch(label);
   2949 }
   2950 
   2951 JumpTable* Mips64Assembler::CreateJumpTable(std::vector<Mips64Label*>&& labels) {
   2952   jump_tables_.emplace_back(std::move(labels));
   2953   JumpTable* table = &jump_tables_.back();
   2954   DCHECK(!table->GetLabel()->IsBound());
   2955   return table;
   2956 }
   2957 
   2958 void Mips64Assembler::ReserveJumpTableSpace() {
   2959   if (!jump_tables_.empty()) {
   2960     for (JumpTable& table : jump_tables_) {
   2961       Mips64Label* label = table.GetLabel();
   2962       Bind(label);
   2963 
   2964       // Bulk ensure capacity, as this may be large.
   2965       size_t orig_size = buffer_.Size();
   2966       size_t required_capacity = orig_size + table.GetSize();
   2967       if (required_capacity > buffer_.Capacity()) {
   2968         buffer_.ExtendCapacity(required_capacity);
   2969       }
   2970 #ifndef NDEBUG
   2971       buffer_.has_ensured_capacity_ = true;
   2972 #endif
   2973 
   2974       // Fill the space with dummy data as the data is not final
   2975       // until the branches have been promoted. And we shouldn't
   2976       // be moving uninitialized data during branch promotion.
   2977       for (size_t cnt = table.GetData().size(), i = 0; i < cnt; i++) {
   2978         buffer_.Emit<uint32_t>(0x1abe1234u);
   2979       }
   2980 
   2981 #ifndef NDEBUG
   2982       buffer_.has_ensured_capacity_ = false;
   2983 #endif
   2984     }
   2985   }
   2986 }
   2987 
   2988 void Mips64Assembler::EmitJumpTables() {
   2989   if (!jump_tables_.empty()) {
   2990     CHECK(!overwriting_);
   2991     // Switch from appending instructions at the end of the buffer to overwriting
   2992     // existing instructions (here, jump tables) in the buffer.
   2993     overwriting_ = true;
   2994 
   2995     for (JumpTable& table : jump_tables_) {
   2996       Mips64Label* table_label = table.GetLabel();
   2997       uint32_t start = GetLabelLocation(table_label);
   2998       overwrite_location_ = start;
   2999 
   3000       for (Mips64Label* target : table.GetData()) {
   3001         CHECK_EQ(buffer_.Load<uint32_t>(overwrite_location_), 0x1abe1234u);
   3002         // The table will contain target addresses relative to the table start.
   3003         uint32_t offset = GetLabelLocation(target) - start;
   3004         Emit(offset);
   3005       }
   3006     }
   3007 
   3008     overwriting_ = false;
   3009   }
   3010 }
   3011 
   3012 void Mips64Assembler::EmitLiterals() {
   3013   if (!literals_.empty()) {
   3014     for (Literal& literal : literals_) {
   3015       Mips64Label* label = literal.GetLabel();
   3016       Bind(label);
   3017       AssemblerBuffer::EnsureCapacity ensured(&buffer_);
   3018       DCHECK_EQ(literal.GetSize(), 4u);
   3019       for (size_t i = 0, size = literal.GetSize(); i != size; ++i) {
   3020         buffer_.Emit<uint8_t>(literal.GetData()[i]);
   3021       }
   3022     }
   3023   }
   3024   if (!long_literals_.empty()) {
   3025     // Reserve 4 bytes for potential alignment. If after the branch promotion the 64-bit
   3026     // literals don't end up 8-byte-aligned, they will be moved down 4 bytes.
   3027     Emit(0);  // NOP.
   3028     for (Literal& literal : long_literals_) {
   3029       Mips64Label* label = literal.GetLabel();
   3030       Bind(label);
   3031       AssemblerBuffer::EnsureCapacity ensured(&buffer_);
   3032       DCHECK_EQ(literal.GetSize(), 8u);
   3033       for (size_t i = 0, size = literal.GetSize(); i != size; ++i) {
   3034         buffer_.Emit<uint8_t>(literal.GetData()[i]);
   3035       }
   3036     }
   3037   }
   3038 }
   3039 
   3040 void Mips64Assembler::PromoteBranches() {
   3041   // Promote short branches to long as necessary.
   3042   bool changed;
   3043   do {
   3044     changed = false;
   3045     for (auto& branch : branches_) {
   3046       CHECK(branch.IsResolved());
   3047       uint32_t delta = branch.PromoteIfNeeded();
   3048       // If this branch has been promoted and needs to expand in size,
   3049       // relocate all branches by the expansion size.
   3050       if (delta) {
   3051         changed = true;
   3052         uint32_t expand_location = branch.GetLocation();
   3053         for (auto& branch2 : branches_) {
   3054           branch2.Relocate(expand_location, delta);
   3055         }
   3056       }
   3057     }
   3058   } while (changed);
   3059 
   3060   // Account for branch expansion by resizing the code buffer
   3061   // and moving the code in it to its final location.
   3062   size_t branch_count = branches_.size();
   3063   if (branch_count > 0) {
   3064     // Resize.
   3065     Branch& last_branch = branches_[branch_count - 1];
   3066     uint32_t size_delta = last_branch.GetEndLocation() - last_branch.GetOldEndLocation();
   3067     uint32_t old_size = buffer_.Size();
   3068     buffer_.Resize(old_size + size_delta);
   3069     // Move the code residing between branch placeholders.
   3070     uint32_t end = old_size;
   3071     for (size_t i = branch_count; i > 0; ) {
   3072       Branch& branch = branches_[--i];
   3073       uint32_t size = end - branch.GetOldEndLocation();
   3074       buffer_.Move(branch.GetEndLocation(), branch.GetOldEndLocation(), size);
   3075       end = branch.GetOldLocation();
   3076     }
   3077   }
   3078 
   3079   // Align 64-bit literals by moving them down by 4 bytes if needed.
   3080   // This will reduce the PC-relative distance, which should be safe for both near and far literals.
   3081   if (!long_literals_.empty()) {
   3082     uint32_t first_literal_location = GetLabelLocation(long_literals_.front().GetLabel());
   3083     size_t lit_size = long_literals_.size() * sizeof(uint64_t);
   3084     size_t buf_size = buffer_.Size();
   3085     // 64-bit literals must be at the very end of the buffer.
   3086     CHECK_EQ(first_literal_location + lit_size, buf_size);
   3087     if (!IsAligned<sizeof(uint64_t)>(first_literal_location)) {
   3088       buffer_.Move(first_literal_location - sizeof(uint32_t), first_literal_location, lit_size);
   3089       // The 4 reserved bytes proved useless, reduce the buffer size.
   3090       buffer_.Resize(buf_size - sizeof(uint32_t));
   3091       // Reduce target addresses in literal and address loads by 4 bytes in order for correct
   3092       // offsets from PC to be generated.
   3093       for (auto& branch : branches_) {
   3094         uint32_t target = branch.GetTarget();
   3095         if (target >= first_literal_location) {
   3096           branch.Resolve(target - sizeof(uint32_t));
   3097         }
   3098       }
   3099       // If after this we ever call GetLabelLocation() to get the location of a 64-bit literal,
   3100       // we need to adjust the location of the literal's label as well.
   3101       for (Literal& literal : long_literals_) {
   3102         // Bound label's position is negative, hence incrementing it instead of decrementing.
   3103         literal.GetLabel()->position_ += sizeof(uint32_t);
   3104       }
   3105     }
   3106   }
   3107 }
   3108 
   3109 // Note: make sure branch_info_[] and EmitBranch() are kept synchronized.
   3110 const Mips64Assembler::Branch::BranchInfo Mips64Assembler::Branch::branch_info_[] = {
   3111   // R6 short branches (can be promoted to long).
   3112   {  1, 0, 1, Mips64Assembler::Branch::kOffset28, 2 },  // kUncondBranch
   3113   {  2, 0, 1, Mips64Assembler::Branch::kOffset18, 2 },  // kCondBranch
   3114                                                         // Exception: kOffset23 for beqzc/bnezc
   3115   {  1, 0, 1, Mips64Assembler::Branch::kOffset28, 2 },  // kCall
   3116   // R6 short branches (can't be promoted to long), forbidden/delay slots filled manually.
   3117   {  1, 0, 1, Mips64Assembler::Branch::kOffset28, 2 },  // kBareUncondBranch
   3118   {  1, 0, 1, Mips64Assembler::Branch::kOffset18, 2 },  // kBareCondBranch
   3119                                                         // Exception: kOffset23 for beqzc/bnezc
   3120   {  1, 0, 1, Mips64Assembler::Branch::kOffset28, 2 },  // kBareCall
   3121   // R2 short branches (can't be promoted to long), delay slots filled manually.
   3122   {  1, 0, 1, Mips64Assembler::Branch::kOffset18, 2 },  // kR2BareCondBranch
   3123   // Near label.
   3124   {  1, 0, 0, Mips64Assembler::Branch::kOffset21, 2 },  // kLabel
   3125   // Near literals.
   3126   {  1, 0, 0, Mips64Assembler::Branch::kOffset21, 2 },  // kLiteral
   3127   {  1, 0, 0, Mips64Assembler::Branch::kOffset21, 2 },  // kLiteralUnsigned
   3128   {  1, 0, 0, Mips64Assembler::Branch::kOffset21, 3 },  // kLiteralLong
   3129   // Long branches.
   3130   {  2, 0, 0, Mips64Assembler::Branch::kOffset32, 0 },  // kLongUncondBranch
   3131   {  3, 1, 0, Mips64Assembler::Branch::kOffset32, 0 },  // kLongCondBranch
   3132   {  2, 0, 0, Mips64Assembler::Branch::kOffset32, 0 },  // kLongCall
   3133   // Far label.
   3134   {  2, 0, 0, Mips64Assembler::Branch::kOffset32, 0 },  // kFarLabel
   3135   // Far literals.
   3136   {  2, 0, 0, Mips64Assembler::Branch::kOffset32, 0 },  // kFarLiteral
   3137   {  2, 0, 0, Mips64Assembler::Branch::kOffset32, 0 },  // kFarLiteralUnsigned
   3138   {  2, 0, 0, Mips64Assembler::Branch::kOffset32, 0 },  // kFarLiteralLong
   3139 };
   3140 
   3141 // Note: make sure branch_info_[] and EmitBranch() are kept synchronized.
   3142 void Mips64Assembler::EmitBranch(Mips64Assembler::Branch* branch) {
   3143   CHECK(overwriting_);
   3144   overwrite_location_ = branch->GetLocation();
   3145   uint32_t offset = branch->GetOffset();
   3146   BranchCondition condition = branch->GetCondition();
   3147   GpuRegister lhs = branch->GetLeftRegister();
   3148   GpuRegister rhs = branch->GetRightRegister();
   3149   switch (branch->GetType()) {
   3150     // Short branches.
   3151     case Branch::kUncondBranch:
   3152       CHECK_EQ(overwrite_location_, branch->GetOffsetLocation());
   3153       Bc(offset);
   3154       break;
   3155     case Branch::kCondBranch:
   3156       CHECK_EQ(overwrite_location_, branch->GetOffsetLocation());
   3157       EmitBcondR6(condition, lhs, rhs, offset);
   3158       Nop();  // TODO: improve by filling the forbidden/delay slot.
   3159       break;
   3160     case Branch::kCall:
   3161       CHECK_EQ(overwrite_location_, branch->GetOffsetLocation());
   3162       Balc(offset);
   3163       break;
   3164     case Branch::kBareUncondBranch:
   3165       CHECK_EQ(overwrite_location_, branch->GetOffsetLocation());
   3166       Bc(offset);
   3167       break;
   3168     case Branch::kBareCondBranch:
   3169       CHECK_EQ(overwrite_location_, branch->GetOffsetLocation());
   3170       EmitBcondR6(condition, lhs, rhs, offset);
   3171       break;
   3172     case Branch::kBareCall:
   3173       CHECK_EQ(overwrite_location_, branch->GetOffsetLocation());
   3174       Balc(offset);
   3175       break;
   3176     case Branch::kR2BareCondBranch:
   3177       CHECK_EQ(overwrite_location_, branch->GetOffsetLocation());
   3178       EmitBcondR2(condition, lhs, rhs, offset);
   3179       break;
   3180 
   3181     // Near label.
   3182     case Branch::kLabel:
   3183       CHECK_EQ(overwrite_location_, branch->GetOffsetLocation());
   3184       Addiupc(lhs, offset);
   3185       break;
   3186     // Near literals.
   3187     case Branch::kLiteral:
   3188       CHECK_EQ(overwrite_location_, branch->GetOffsetLocation());
   3189       Lwpc(lhs, offset);
   3190       break;
   3191     case Branch::kLiteralUnsigned:
   3192       CHECK_EQ(overwrite_location_, branch->GetOffsetLocation());
   3193       Lwupc(lhs, offset);
   3194       break;
   3195     case Branch::kLiteralLong:
   3196       CHECK_EQ(overwrite_location_, branch->GetOffsetLocation());
   3197       Ldpc(lhs, offset);
   3198       break;
   3199 
   3200     // Long branches.
   3201     case Branch::kLongUncondBranch:
   3202       offset += (offset & 0x8000) << 1;  // Account for sign extension in jic.
   3203       CHECK_EQ(overwrite_location_, branch->GetOffsetLocation());
   3204       Auipc(AT, High16Bits(offset));
   3205       Jic(AT, Low16Bits(offset));
   3206       break;
   3207     case Branch::kLongCondBranch:
   3208       EmitBcondR6(Branch::OppositeCondition(condition), lhs, rhs, 2);
   3209       offset += (offset & 0x8000) << 1;  // Account for sign extension in jic.
   3210       CHECK_EQ(overwrite_location_, branch->GetOffsetLocation());
   3211       Auipc(AT, High16Bits(offset));
   3212       Jic(AT, Low16Bits(offset));
   3213       break;
   3214     case Branch::kLongCall:
   3215       offset += (offset & 0x8000) << 1;  // Account for sign extension in jialc.
   3216       CHECK_EQ(overwrite_location_, branch->GetOffsetLocation());
   3217       Auipc(AT, High16Bits(offset));
   3218       Jialc(AT, Low16Bits(offset));
   3219       break;
   3220 
   3221     // Far label.
   3222     case Branch::kFarLabel:
   3223       offset += (offset & 0x8000) << 1;  // Account for sign extension in daddiu.
   3224       CHECK_EQ(overwrite_location_, branch->GetOffsetLocation());
   3225       Auipc(AT, High16Bits(offset));
   3226       Daddiu(lhs, AT, Low16Bits(offset));
   3227       break;
   3228     // Far literals.
   3229     case Branch::kFarLiteral:
   3230       offset += (offset & 0x8000) << 1;  // Account for sign extension in lw.
   3231       CHECK_EQ(overwrite_location_, branch->GetOffsetLocation());
   3232       Auipc(AT, High16Bits(offset));
   3233       Lw(lhs, AT, Low16Bits(offset));
   3234       break;
   3235     case Branch::kFarLiteralUnsigned:
   3236       offset += (offset & 0x8000) << 1;  // Account for sign extension in lwu.
   3237       CHECK_EQ(overwrite_location_, branch->GetOffsetLocation());
   3238       Auipc(AT, High16Bits(offset));
   3239       Lwu(lhs, AT, Low16Bits(offset));
   3240       break;
   3241     case Branch::kFarLiteralLong:
   3242       offset += (offset & 0x8000) << 1;  // Account for sign extension in ld.
   3243       CHECK_EQ(overwrite_location_, branch->GetOffsetLocation());
   3244       Auipc(AT, High16Bits(offset));
   3245       Ld(lhs, AT, Low16Bits(offset));
   3246       break;
   3247   }
   3248   CHECK_EQ(overwrite_location_, branch->GetEndLocation());
   3249   CHECK_LT(branch->GetSize(), static_cast<uint32_t>(Branch::kMaxBranchSize));
   3250 }
   3251 
   3252 void Mips64Assembler::Bc(Mips64Label* label, bool is_bare) {
   3253   Buncond(label, is_bare);
   3254 }
   3255 
   3256 void Mips64Assembler::Balc(Mips64Label* label, bool is_bare) {
   3257   Call(label, is_bare);
   3258 }
   3259 
   3260 void Mips64Assembler::Bltc(GpuRegister rs, GpuRegister rt, Mips64Label* label, bool is_bare) {
   3261   Bcond(label, /* is_r6 */ true, is_bare, kCondLT, rs, rt);
   3262 }
   3263 
   3264 void Mips64Assembler::Bltzc(GpuRegister rt, Mips64Label* label, bool is_bare) {
   3265   Bcond(label, /* is_r6 */ true, is_bare, kCondLTZ, rt);
   3266 }
   3267 
   3268 void Mips64Assembler::Bgtzc(GpuRegister rt, Mips64Label* label, bool is_bare) {
   3269   Bcond(label, /* is_r6 */ true, is_bare, kCondGTZ, rt);
   3270 }
   3271 
   3272 void Mips64Assembler::Bgec(GpuRegister rs, GpuRegister rt, Mips64Label* label, bool is_bare) {
   3273   Bcond(label, /* is_r6 */ true, is_bare, kCondGE, rs, rt);
   3274 }
   3275 
   3276 void Mips64Assembler::Bgezc(GpuRegister rt, Mips64Label* label, bool is_bare) {
   3277   Bcond(label, /* is_r6 */ true, is_bare, kCondGEZ, rt);
   3278 }
   3279 
   3280 void Mips64Assembler::Blezc(GpuRegister rt, Mips64Label* label, bool is_bare) {
   3281   Bcond(label, /* is_r6 */ true, is_bare, kCondLEZ, rt);
   3282 }
   3283 
   3284 void Mips64Assembler::Bltuc(GpuRegister rs, GpuRegister rt, Mips64Label* label, bool is_bare) {
   3285   Bcond(label, /* is_r6 */ true, is_bare, kCondLTU, rs, rt);
   3286 }
   3287 
   3288 void Mips64Assembler::Bgeuc(GpuRegister rs, GpuRegister rt, Mips64Label* label, bool is_bare) {
   3289   Bcond(label, /* is_r6 */ true, is_bare, kCondGEU, rs, rt);
   3290 }
   3291 
   3292 void Mips64Assembler::Beqc(GpuRegister rs, GpuRegister rt, Mips64Label* label, bool is_bare) {
   3293   Bcond(label, /* is_r6 */ true, is_bare, kCondEQ, rs, rt);
   3294 }
   3295 
   3296 void Mips64Assembler::Bnec(GpuRegister rs, GpuRegister rt, Mips64Label* label, bool is_bare) {
   3297   Bcond(label, /* is_r6 */ true, is_bare, kCondNE, rs, rt);
   3298 }
   3299 
   3300 void Mips64Assembler::Beqzc(GpuRegister rs, Mips64Label* label, bool is_bare) {
   3301   Bcond(label, /* is_r6 */ true, is_bare, kCondEQZ, rs);
   3302 }
   3303 
   3304 void Mips64Assembler::Bnezc(GpuRegister rs, Mips64Label* label, bool is_bare) {
   3305   Bcond(label, /* is_r6 */ true, is_bare, kCondNEZ, rs);
   3306 }
   3307 
   3308 void Mips64Assembler::Bc1eqz(FpuRegister ft, Mips64Label* label, bool is_bare) {
   3309   Bcond(label, /* is_r6 */ true, is_bare, kCondF, static_cast<GpuRegister>(ft), ZERO);
   3310 }
   3311 
   3312 void Mips64Assembler::Bc1nez(FpuRegister ft, Mips64Label* label, bool is_bare) {
   3313   Bcond(label, /* is_r6 */ true, is_bare, kCondT, static_cast<GpuRegister>(ft), ZERO);
   3314 }
   3315 
   3316 void Mips64Assembler::Bltz(GpuRegister rt, Mips64Label* label, bool is_bare) {
   3317   CHECK(is_bare);
   3318   Bcond(label, /* is_r6 */ false, is_bare, kCondLTZ, rt);
   3319 }
   3320 
   3321 void Mips64Assembler::Bgtz(GpuRegister rt, Mips64Label* label, bool is_bare) {
   3322   CHECK(is_bare);
   3323   Bcond(label, /* is_r6 */ false, is_bare, kCondGTZ, rt);
   3324 }
   3325 
   3326 void Mips64Assembler::Bgez(GpuRegister rt, Mips64Label* label, bool is_bare) {
   3327   CHECK(is_bare);
   3328   Bcond(label, /* is_r6 */ false, is_bare, kCondGEZ, rt);
   3329 }
   3330 
   3331 void Mips64Assembler::Blez(GpuRegister rt, Mips64Label* label, bool is_bare) {
   3332   CHECK(is_bare);
   3333   Bcond(label, /* is_r6 */ false, is_bare, kCondLEZ, rt);
   3334 }
   3335 
   3336 void Mips64Assembler::Beq(GpuRegister rs, GpuRegister rt, Mips64Label* label, bool is_bare) {
   3337   CHECK(is_bare);
   3338   Bcond(label, /* is_r6 */ false, is_bare, kCondEQ, rs, rt);
   3339 }
   3340 
   3341 void Mips64Assembler::Bne(GpuRegister rs, GpuRegister rt, Mips64Label* label, bool is_bare) {
   3342   CHECK(is_bare);
   3343   Bcond(label, /* is_r6 */ false, is_bare, kCondNE, rs, rt);
   3344 }
   3345 
   3346 void Mips64Assembler::Beqz(GpuRegister rs, Mips64Label* label, bool is_bare) {
   3347   CHECK(is_bare);
   3348   Bcond(label, /* is_r6 */ false, is_bare, kCondEQZ, rs);
   3349 }
   3350 
   3351 void Mips64Assembler::Bnez(GpuRegister rs, Mips64Label* label, bool is_bare) {
   3352   CHECK(is_bare);
   3353   Bcond(label, /* is_r6 */ false, is_bare, kCondNEZ, rs);
   3354 }
   3355 
   3356 void Mips64Assembler::AdjustBaseAndOffset(GpuRegister& base,
   3357                                           int32_t& offset,
   3358                                           bool is_doubleword) {
   3359   // This method is used to adjust the base register and offset pair
   3360   // for a load/store when the offset doesn't fit into int16_t.
   3361   // It is assumed that `base + offset` is sufficiently aligned for memory
   3362   // operands that are machine word in size or smaller. For doubleword-sized
   3363   // operands it's assumed that `base` is a multiple of 8, while `offset`
   3364   // may be a multiple of 4 (e.g. 4-byte-aligned long and double arguments
   3365   // and spilled variables on the stack accessed relative to the stack
   3366   // pointer register).
   3367   // We preserve the "alignment" of `offset` by adjusting it by a multiple of 8.
   3368   CHECK_NE(base, AT);  // Must not overwrite the register `base` while loading `offset`.
   3369 
   3370   bool doubleword_aligned = IsAligned<kMips64DoublewordSize>(offset);
   3371   bool two_accesses = is_doubleword && !doubleword_aligned;
   3372 
   3373   // IsInt<16> must be passed a signed value, hence the static cast below.
   3374   if (IsInt<16>(offset) &&
   3375       (!two_accesses || IsInt<16>(static_cast<int32_t>(offset + kMips64WordSize)))) {
   3376     // Nothing to do: `offset` (and, if needed, `offset + 4`) fits into int16_t.
   3377     return;
   3378   }
   3379 
   3380   // Remember the "(mis)alignment" of `offset`, it will be checked at the end.
   3381   uint32_t misalignment = offset & (kMips64DoublewordSize - 1);
   3382 
   3383   // First, see if `offset` can be represented as a sum of two 16-bit signed
   3384   // offsets. This can save an instruction.
   3385   // To simplify matters, only do this for a symmetric range of offsets from
   3386   // about -64KB to about +64KB, allowing further addition of 4 when accessing
   3387   // 64-bit variables with two 32-bit accesses.
   3388   constexpr int32_t kMinOffsetForSimpleAdjustment = 0x7ff8;  // Max int16_t that's a multiple of 8.
   3389   constexpr int32_t kMaxOffsetForSimpleAdjustment = 2 * kMinOffsetForSimpleAdjustment;
   3390 
   3391   if (0 <= offset && offset <= kMaxOffsetForSimpleAdjustment) {
   3392     Daddiu(AT, base, kMinOffsetForSimpleAdjustment);
   3393     offset -= kMinOffsetForSimpleAdjustment;
   3394   } else if (-kMaxOffsetForSimpleAdjustment <= offset && offset < 0) {
   3395     Daddiu(AT, base, -kMinOffsetForSimpleAdjustment);
   3396     offset += kMinOffsetForSimpleAdjustment;
   3397   } else {
   3398     // In more complex cases take advantage of the daui instruction, e.g.:
   3399     //    daui   AT, base, offset_high
   3400     //   [dahi   AT, 1]                       // When `offset` is close to +2GB.
   3401     //    lw     reg_lo, offset_low(AT)
   3402     //   [lw     reg_hi, (offset_low+4)(AT)]  // If misaligned 64-bit load.
   3403     // or when offset_low+4 overflows int16_t:
   3404     //    daui   AT, base, offset_high
   3405     //    daddiu AT, AT, 8
   3406     //    lw     reg_lo, (offset_low-8)(AT)
   3407     //    lw     reg_hi, (offset_low-4)(AT)
   3408     int16_t offset_low = Low16Bits(offset);
   3409     int32_t offset_low32 = offset_low;
   3410     int16_t offset_high = High16Bits(offset);
   3411     bool increment_hi16 = offset_low < 0;
   3412     bool overflow_hi16 = false;
   3413 
   3414     if (increment_hi16) {
   3415       offset_high++;
   3416       overflow_hi16 = (offset_high == -32768);
   3417     }
   3418     Daui(AT, base, offset_high);
   3419 
   3420     if (overflow_hi16) {
   3421       Dahi(AT, 1);
   3422     }
   3423 
   3424     if (two_accesses && !IsInt<16>(static_cast<int32_t>(offset_low32 + kMips64WordSize))) {
   3425       // Avoid overflow in the 16-bit offset of the load/store instruction when adding 4.
   3426       Daddiu(AT, AT, kMips64DoublewordSize);
   3427       offset_low32 -= kMips64DoublewordSize;
   3428     }
   3429 
   3430     offset = offset_low32;
   3431   }
   3432   base = AT;
   3433 
   3434   CHECK(IsInt<16>(offset));
   3435   if (two_accesses) {
   3436     CHECK(IsInt<16>(static_cast<int32_t>(offset + kMips64WordSize)));
   3437   }
   3438   CHECK_EQ(misalignment, offset & (kMips64DoublewordSize - 1));
   3439 }
   3440 
   3441 void Mips64Assembler::AdjustBaseOffsetAndElementSizeShift(GpuRegister& base,
   3442                                                           int32_t& offset,
   3443                                                           int& element_size_shift) {
   3444   // This method is used to adjust the base register, offset and element_size_shift
   3445   // for a vector load/store when the offset doesn't fit into allowed number of bits.
   3446   // MSA ld.df and st.df instructions take signed offsets as arguments, but maximum
   3447   // offset is dependant on the size of the data format df (10-bit offsets for ld.b,
   3448   // 11-bit for ld.h, 12-bit for ld.w and 13-bit for ld.d).
   3449   // If element_size_shift is non-negative at entry, it won't be changed, but offset
   3450   // will be checked for appropriate alignment. If negative at entry, it will be
   3451   // adjusted based on offset for maximum fit.
   3452   // It's assumed that `base` is a multiple of 8.
   3453 
   3454   CHECK_NE(base, AT);  // Must not overwrite the register `base` while loading `offset`.
   3455 
   3456   if (element_size_shift >= 0) {
   3457     CHECK_LE(element_size_shift, TIMES_8);
   3458     CHECK_GE(JAVASTYLE_CTZ(offset), element_size_shift);
   3459   } else if (IsAligned<kMips64DoublewordSize>(offset)) {
   3460     element_size_shift = TIMES_8;
   3461   } else if (IsAligned<kMips64WordSize>(offset)) {
   3462     element_size_shift = TIMES_4;
   3463   } else if (IsAligned<kMips64HalfwordSize>(offset)) {
   3464     element_size_shift = TIMES_2;
   3465   } else {
   3466     element_size_shift = TIMES_1;
   3467   }
   3468 
   3469   const int low_len = 10 + element_size_shift;  // How many low bits of `offset` ld.df/st.df
   3470                                                 // will take.
   3471   int16_t low = offset & ((1 << low_len) - 1);  // Isolate these bits.
   3472   low -= (low & (1 << (low_len - 1))) << 1;     // Sign-extend these bits.
   3473   if (low == offset) {
   3474     return;  // `offset` fits into ld.df/st.df.
   3475   }
   3476 
   3477   // First, see if `offset` can be represented as a sum of two signed offsets.
   3478   // This can save an instruction.
   3479 
   3480   // Max int16_t that's a multiple of element size.
   3481   const int32_t kMaxDeltaForSimpleAdjustment = 0x8000 - (1 << element_size_shift);
   3482   // Max ld.df/st.df offset that's a multiple of element size.
   3483   const int32_t kMaxLoadStoreOffset = 0x1ff << element_size_shift;
   3484   const int32_t kMaxOffsetForSimpleAdjustment = kMaxDeltaForSimpleAdjustment + kMaxLoadStoreOffset;
   3485 
   3486   if (IsInt<16>(offset)) {
   3487     Daddiu(AT, base, offset);
   3488     offset = 0;
   3489   } else if (0 <= offset && offset <= kMaxOffsetForSimpleAdjustment) {
   3490     Daddiu(AT, base, kMaxDeltaForSimpleAdjustment);
   3491     offset -= kMaxDeltaForSimpleAdjustment;
   3492   } else if (-kMaxOffsetForSimpleAdjustment <= offset && offset < 0) {
   3493     Daddiu(AT, base, -kMaxDeltaForSimpleAdjustment);
   3494     offset += kMaxDeltaForSimpleAdjustment;
   3495   } else {
   3496     // Let's treat `offset` as 64-bit to simplify handling of sign
   3497     // extensions in the instructions that supply its smaller signed parts.
   3498     //
   3499     // 16-bit or smaller parts of `offset`:
   3500     // |63  top  48|47  hi  32|31  upper  16|15  mid  13-10|12-9  low  0|
   3501     //
   3502     // Instructions that supply each part as a signed integer addend:
   3503     // |dati       |dahi      |daui         |daddiu        |ld.df/st.df |
   3504     //
   3505     // `top` is always 0, so dati isn't used.
   3506     // `hi` is 1 when `offset` is close to +2GB and 0 otherwise.
   3507     uint64_t tmp = static_cast<uint64_t>(offset) - low;  // Exclude `low` from the rest of `offset`
   3508                                                          // (accounts for sign of `low`).
   3509     tmp += (tmp & (UINT64_C(1) << 15)) << 1;  // Account for sign extension in daddiu.
   3510     tmp += (tmp & (UINT64_C(1) << 31)) << 1;  // Account for sign extension in daui.
   3511     int16_t mid = Low16Bits(tmp);
   3512     int16_t upper = High16Bits(tmp);
   3513     int16_t hi = Low16Bits(High32Bits(tmp));
   3514     Daui(AT, base, upper);
   3515     if (hi != 0) {
   3516       CHECK_EQ(hi, 1);
   3517       Dahi(AT, hi);
   3518     }
   3519     if (mid != 0) {
   3520       Daddiu(AT, AT, mid);
   3521     }
   3522     offset = low;
   3523   }
   3524   base = AT;
   3525   CHECK_GE(JAVASTYLE_CTZ(offset), element_size_shift);
   3526   CHECK(IsInt<10>(offset >> element_size_shift));
   3527 }
   3528 
   3529 void Mips64Assembler::LoadFromOffset(LoadOperandType type,
   3530                                      GpuRegister reg,
   3531                                      GpuRegister base,
   3532                                      int32_t offset) {
   3533   LoadFromOffset<>(type, reg, base, offset);
   3534 }
   3535 
   3536 void Mips64Assembler::LoadFpuFromOffset(LoadOperandType type,
   3537                                         FpuRegister reg,
   3538                                         GpuRegister base,
   3539                                         int32_t offset) {
   3540   LoadFpuFromOffset<>(type, reg, base, offset);
   3541 }
   3542 
   3543 void Mips64Assembler::EmitLoad(ManagedRegister m_dst, GpuRegister src_register, int32_t src_offset,
   3544                                size_t size) {
   3545   Mips64ManagedRegister dst = m_dst.AsMips64();
   3546   if (dst.IsNoRegister()) {
   3547     CHECK_EQ(0u, size) << dst;
   3548   } else if (dst.IsGpuRegister()) {
   3549     if (size == 4) {
   3550       LoadFromOffset(kLoadWord, dst.AsGpuRegister(), src_register, src_offset);
   3551     } else if (size == 8) {
   3552       CHECK_EQ(8u, size) << dst;
   3553       LoadFromOffset(kLoadDoubleword, dst.AsGpuRegister(), src_register, src_offset);
   3554     } else {
   3555       UNIMPLEMENTED(FATAL) << "We only support Load() of size 4 and 8";
   3556     }
   3557   } else if (dst.IsFpuRegister()) {
   3558     if (size == 4) {
   3559       CHECK_EQ(4u, size) << dst;
   3560       LoadFpuFromOffset(kLoadWord, dst.AsFpuRegister(), src_register, src_offset);
   3561     } else if (size == 8) {
   3562       CHECK_EQ(8u, size) << dst;
   3563       LoadFpuFromOffset(kLoadDoubleword, dst.AsFpuRegister(), src_register, src_offset);
   3564     } else {
   3565       UNIMPLEMENTED(FATAL) << "We only support Load() of size 4 and 8";
   3566     }
   3567   }
   3568 }
   3569 
   3570 void Mips64Assembler::StoreToOffset(StoreOperandType type,
   3571                                     GpuRegister reg,
   3572                                     GpuRegister base,
   3573                                     int32_t offset) {
   3574   StoreToOffset<>(type, reg, base, offset);
   3575 }
   3576 
   3577 void Mips64Assembler::StoreFpuToOffset(StoreOperandType type,
   3578                                        FpuRegister reg,
   3579                                        GpuRegister base,
   3580                                        int32_t offset) {
   3581   StoreFpuToOffset<>(type, reg, base, offset);
   3582 }
   3583 
   3584 static dwarf::Reg DWARFReg(GpuRegister reg) {
   3585   return dwarf::Reg::Mips64Core(static_cast<int>(reg));
   3586 }
   3587 
   3588 constexpr size_t kFramePointerSize = 8;
   3589 
   3590 void Mips64Assembler::BuildFrame(size_t frame_size,
   3591                                  ManagedRegister method_reg,
   3592                                  ArrayRef<const ManagedRegister> callee_save_regs,
   3593                                  const ManagedRegisterEntrySpills& entry_spills) {
   3594   CHECK_ALIGNED(frame_size, kStackAlignment);
   3595   DCHECK(!overwriting_);
   3596 
   3597   // Increase frame to required size.
   3598   IncreaseFrameSize(frame_size);
   3599 
   3600   // Push callee saves and return address
   3601   int stack_offset = frame_size - kFramePointerSize;
   3602   StoreToOffset(kStoreDoubleword, RA, SP, stack_offset);
   3603   cfi_.RelOffset(DWARFReg(RA), stack_offset);
   3604   for (int i = callee_save_regs.size() - 1; i >= 0; --i) {
   3605     stack_offset -= kFramePointerSize;
   3606     GpuRegister reg = callee_save_regs[i].AsMips64().AsGpuRegister();
   3607     StoreToOffset(kStoreDoubleword, reg, SP, stack_offset);
   3608     cfi_.RelOffset(DWARFReg(reg), stack_offset);
   3609   }
   3610 
   3611   // Write out Method*.
   3612   StoreToOffset(kStoreDoubleword, method_reg.AsMips64().AsGpuRegister(), SP, 0);
   3613 
   3614   // Write out entry spills.
   3615   int32_t offset = frame_size + kFramePointerSize;
   3616   for (size_t i = 0; i < entry_spills.size(); ++i) {
   3617     Mips64ManagedRegister reg = entry_spills[i].AsMips64();
   3618     ManagedRegisterSpill spill = entry_spills.at(i);
   3619     int32_t size = spill.getSize();
   3620     if (reg.IsNoRegister()) {
   3621       // only increment stack offset.
   3622       offset += size;
   3623     } else if (reg.IsFpuRegister()) {
   3624       StoreFpuToOffset((size == 4) ? kStoreWord : kStoreDoubleword,
   3625           reg.AsFpuRegister(), SP, offset);
   3626       offset += size;
   3627     } else if (reg.IsGpuRegister()) {
   3628       StoreToOffset((size == 4) ? kStoreWord : kStoreDoubleword,
   3629           reg.AsGpuRegister(), SP, offset);
   3630       offset += size;
   3631     }
   3632   }
   3633 }
   3634 
   3635 void Mips64Assembler::RemoveFrame(size_t frame_size,
   3636                                   ArrayRef<const ManagedRegister> callee_save_regs,
   3637                                   bool may_suspend ATTRIBUTE_UNUSED) {
   3638   CHECK_ALIGNED(frame_size, kStackAlignment);
   3639   DCHECK(!overwriting_);
   3640   cfi_.RememberState();
   3641 
   3642   // Pop callee saves and return address
   3643   int stack_offset = frame_size - (callee_save_regs.size() * kFramePointerSize) - kFramePointerSize;
   3644   for (size_t i = 0; i < callee_save_regs.size(); ++i) {
   3645     GpuRegister reg = callee_save_regs[i].AsMips64().AsGpuRegister();
   3646     LoadFromOffset(kLoadDoubleword, reg, SP, stack_offset);
   3647     cfi_.Restore(DWARFReg(reg));
   3648     stack_offset += kFramePointerSize;
   3649   }
   3650   LoadFromOffset(kLoadDoubleword, RA, SP, stack_offset);
   3651   cfi_.Restore(DWARFReg(RA));
   3652 
   3653   // Decrease frame to required size.
   3654   DecreaseFrameSize(frame_size);
   3655 
   3656   // Then jump to the return address.
   3657   Jr(RA);
   3658   Nop();
   3659 
   3660   // The CFI should be restored for any code that follows the exit block.
   3661   cfi_.RestoreState();
   3662   cfi_.DefCFAOffset(frame_size);
   3663 }
   3664 
   3665 void Mips64Assembler::IncreaseFrameSize(size_t adjust) {
   3666   CHECK_ALIGNED(adjust, kFramePointerSize);
   3667   DCHECK(!overwriting_);
   3668   Daddiu64(SP, SP, static_cast<int32_t>(-adjust));
   3669   cfi_.AdjustCFAOffset(adjust);
   3670 }
   3671 
   3672 void Mips64Assembler::DecreaseFrameSize(size_t adjust) {
   3673   CHECK_ALIGNED(adjust, kFramePointerSize);
   3674   DCHECK(!overwriting_);
   3675   Daddiu64(SP, SP, static_cast<int32_t>(adjust));
   3676   cfi_.AdjustCFAOffset(-adjust);
   3677 }
   3678 
   3679 void Mips64Assembler::Store(FrameOffset dest, ManagedRegister msrc, size_t size) {
   3680   Mips64ManagedRegister src = msrc.AsMips64();
   3681   if (src.IsNoRegister()) {
   3682     CHECK_EQ(0u, size);
   3683   } else if (src.IsGpuRegister()) {
   3684     CHECK(size == 4 || size == 8) << size;
   3685     if (size == 8) {
   3686       StoreToOffset(kStoreDoubleword, src.AsGpuRegister(), SP, dest.Int32Value());
   3687     } else if (size == 4) {
   3688       StoreToOffset(kStoreWord, src.AsGpuRegister(), SP, dest.Int32Value());
   3689     } else {
   3690       UNIMPLEMENTED(FATAL) << "We only support Store() of size 4 and 8";
   3691     }
   3692   } else if (src.IsFpuRegister()) {
   3693     CHECK(size == 4 || size == 8) << size;
   3694     if (size == 8) {
   3695       StoreFpuToOffset(kStoreDoubleword, src.AsFpuRegister(), SP, dest.Int32Value());
   3696     } else if (size == 4) {
   3697       StoreFpuToOffset(kStoreWord, src.AsFpuRegister(), SP, dest.Int32Value());
   3698     } else {
   3699       UNIMPLEMENTED(FATAL) << "We only support Store() of size 4 and 8";
   3700     }
   3701   }
   3702 }
   3703 
   3704 void Mips64Assembler::StoreRef(FrameOffset dest, ManagedRegister msrc) {
   3705   Mips64ManagedRegister src = msrc.AsMips64();
   3706   CHECK(src.IsGpuRegister());
   3707   StoreToOffset(kStoreWord, src.AsGpuRegister(), SP, dest.Int32Value());
   3708 }
   3709 
   3710 void Mips64Assembler::StoreRawPtr(FrameOffset dest, ManagedRegister msrc) {
   3711   Mips64ManagedRegister src = msrc.AsMips64();
   3712   CHECK(src.IsGpuRegister());
   3713   StoreToOffset(kStoreDoubleword, src.AsGpuRegister(), SP, dest.Int32Value());
   3714 }
   3715 
   3716 void Mips64Assembler::StoreImmediateToFrame(FrameOffset dest, uint32_t imm,
   3717                                             ManagedRegister mscratch) {
   3718   Mips64ManagedRegister scratch = mscratch.AsMips64();
   3719   CHECK(scratch.IsGpuRegister()) << scratch;
   3720   LoadConst32(scratch.AsGpuRegister(), imm);
   3721   StoreToOffset(kStoreWord, scratch.AsGpuRegister(), SP, dest.Int32Value());
   3722 }
   3723 
   3724 void Mips64Assembler::StoreStackOffsetToThread(ThreadOffset64 thr_offs,
   3725                                                FrameOffset fr_offs,
   3726                                                ManagedRegister mscratch) {
   3727   Mips64ManagedRegister scratch = mscratch.AsMips64();
   3728   CHECK(scratch.IsGpuRegister()) << scratch;
   3729   Daddiu64(scratch.AsGpuRegister(), SP, fr_offs.Int32Value());
   3730   StoreToOffset(kStoreDoubleword, scratch.AsGpuRegister(), S1, thr_offs.Int32Value());
   3731 }
   3732 
   3733 void Mips64Assembler::StoreStackPointerToThread(ThreadOffset64 thr_offs) {
   3734   StoreToOffset(kStoreDoubleword, SP, S1, thr_offs.Int32Value());
   3735 }
   3736 
   3737 void Mips64Assembler::StoreSpanning(FrameOffset dest, ManagedRegister msrc,
   3738                                     FrameOffset in_off, ManagedRegister mscratch) {
   3739   Mips64ManagedRegister src = msrc.AsMips64();
   3740   Mips64ManagedRegister scratch = mscratch.AsMips64();
   3741   StoreToOffset(kStoreDoubleword, src.AsGpuRegister(), SP, dest.Int32Value());
   3742   LoadFromOffset(kLoadDoubleword, scratch.AsGpuRegister(), SP, in_off.Int32Value());
   3743   StoreToOffset(kStoreDoubleword, scratch.AsGpuRegister(), SP, dest.Int32Value() + 8);
   3744 }
   3745 
   3746 void Mips64Assembler::Load(ManagedRegister mdest, FrameOffset src, size_t size) {
   3747   return EmitLoad(mdest, SP, src.Int32Value(), size);
   3748 }
   3749 
   3750 void Mips64Assembler::LoadFromThread(ManagedRegister mdest, ThreadOffset64 src, size_t size) {
   3751   return EmitLoad(mdest, S1, src.Int32Value(), size);
   3752 }
   3753 
   3754 void Mips64Assembler::LoadRef(ManagedRegister mdest, FrameOffset src) {
   3755   Mips64ManagedRegister dest = mdest.AsMips64();
   3756   CHECK(dest.IsGpuRegister());
   3757   LoadFromOffset(kLoadUnsignedWord, dest.AsGpuRegister(), SP, src.Int32Value());
   3758 }
   3759 
   3760 void Mips64Assembler::LoadRef(ManagedRegister mdest, ManagedRegister base, MemberOffset offs,
   3761                               bool unpoison_reference) {
   3762   Mips64ManagedRegister dest = mdest.AsMips64();
   3763   CHECK(dest.IsGpuRegister() && base.AsMips64().IsGpuRegister());
   3764   LoadFromOffset(kLoadUnsignedWord, dest.AsGpuRegister(),
   3765                  base.AsMips64().AsGpuRegister(), offs.Int32Value());
   3766   if (unpoison_reference) {
   3767     MaybeUnpoisonHeapReference(dest.AsGpuRegister());
   3768   }
   3769 }
   3770 
   3771 void Mips64Assembler::LoadRawPtr(ManagedRegister mdest, ManagedRegister base,
   3772                                  Offset offs) {
   3773   Mips64ManagedRegister dest = mdest.AsMips64();
   3774   CHECK(dest.IsGpuRegister() && base.AsMips64().IsGpuRegister());
   3775   LoadFromOffset(kLoadDoubleword, dest.AsGpuRegister(),
   3776                  base.AsMips64().AsGpuRegister(), offs.Int32Value());
   3777 }
   3778 
   3779 void Mips64Assembler::LoadRawPtrFromThread(ManagedRegister mdest, ThreadOffset64 offs) {
   3780   Mips64ManagedRegister dest = mdest.AsMips64();
   3781   CHECK(dest.IsGpuRegister());
   3782   LoadFromOffset(kLoadDoubleword, dest.AsGpuRegister(), S1, offs.Int32Value());
   3783 }
   3784 
   3785 void Mips64Assembler::SignExtend(ManagedRegister mreg ATTRIBUTE_UNUSED,
   3786                                  size_t size ATTRIBUTE_UNUSED) {
   3787   UNIMPLEMENTED(FATAL) << "No sign extension necessary for MIPS64";
   3788 }
   3789 
   3790 void Mips64Assembler::ZeroExtend(ManagedRegister mreg ATTRIBUTE_UNUSED,
   3791                                  size_t size ATTRIBUTE_UNUSED) {
   3792   UNIMPLEMENTED(FATAL) << "No zero extension necessary for MIPS64";
   3793 }
   3794 
   3795 void Mips64Assembler::Move(ManagedRegister mdest, ManagedRegister msrc, size_t size) {
   3796   Mips64ManagedRegister dest = mdest.AsMips64();
   3797   Mips64ManagedRegister src = msrc.AsMips64();
   3798   if (!dest.Equals(src)) {
   3799     if (dest.IsGpuRegister()) {
   3800       CHECK(src.IsGpuRegister()) << src;
   3801       Move(dest.AsGpuRegister(), src.AsGpuRegister());
   3802     } else if (dest.IsFpuRegister()) {
   3803       CHECK(src.IsFpuRegister()) << src;
   3804       if (size == 4) {
   3805         MovS(dest.AsFpuRegister(), src.AsFpuRegister());
   3806       } else if (size == 8) {
   3807         MovD(dest.AsFpuRegister(), src.AsFpuRegister());
   3808       } else {
   3809         UNIMPLEMENTED(FATAL) << "We only support Copy() of size 4 and 8";
   3810       }
   3811     }
   3812   }
   3813 }
   3814 
   3815 void Mips64Assembler::CopyRef(FrameOffset dest, FrameOffset src,
   3816                               ManagedRegister mscratch) {
   3817   Mips64ManagedRegister scratch = mscratch.AsMips64();
   3818   CHECK(scratch.IsGpuRegister()) << scratch;
   3819   LoadFromOffset(kLoadWord, scratch.AsGpuRegister(), SP, src.Int32Value());
   3820   StoreToOffset(kStoreWord, scratch.AsGpuRegister(), SP, dest.Int32Value());
   3821 }
   3822 
   3823 void Mips64Assembler::CopyRawPtrFromThread(FrameOffset fr_offs,
   3824                                            ThreadOffset64 thr_offs,
   3825                                            ManagedRegister mscratch) {
   3826   Mips64ManagedRegister scratch = mscratch.AsMips64();
   3827   CHECK(scratch.IsGpuRegister()) << scratch;
   3828   LoadFromOffset(kLoadDoubleword, scratch.AsGpuRegister(), S1, thr_offs.Int32Value());
   3829   StoreToOffset(kStoreDoubleword, scratch.AsGpuRegister(), SP, fr_offs.Int32Value());
   3830 }
   3831 
   3832 void Mips64Assembler::CopyRawPtrToThread(ThreadOffset64 thr_offs,
   3833                                          FrameOffset fr_offs,
   3834                                          ManagedRegister mscratch) {
   3835   Mips64ManagedRegister scratch = mscratch.AsMips64();
   3836   CHECK(scratch.IsGpuRegister()) << scratch;
   3837   LoadFromOffset(kLoadDoubleword, scratch.AsGpuRegister(),
   3838                  SP, fr_offs.Int32Value());
   3839   StoreToOffset(kStoreDoubleword, scratch.AsGpuRegister(),
   3840                 S1, thr_offs.Int32Value());
   3841 }
   3842 
   3843 void Mips64Assembler::Copy(FrameOffset dest, FrameOffset src,
   3844                            ManagedRegister mscratch, size_t size) {
   3845   Mips64ManagedRegister scratch = mscratch.AsMips64();
   3846   CHECK(scratch.IsGpuRegister()) << scratch;
   3847   CHECK(size == 4 || size == 8) << size;
   3848   if (size == 4) {
   3849     LoadFromOffset(kLoadWord, scratch.AsGpuRegister(), SP, src.Int32Value());
   3850     StoreToOffset(kStoreDoubleword, scratch.AsGpuRegister(), SP, dest.Int32Value());
   3851   } else if (size == 8) {
   3852     LoadFromOffset(kLoadDoubleword, scratch.AsGpuRegister(), SP, src.Int32Value());
   3853     StoreToOffset(kStoreDoubleword, scratch.AsGpuRegister(), SP, dest.Int32Value());
   3854   } else {
   3855     UNIMPLEMENTED(FATAL) << "We only support Copy() of size 4 and 8";
   3856   }
   3857 }
   3858 
   3859 void Mips64Assembler::Copy(FrameOffset dest, ManagedRegister src_base, Offset src_offset,
   3860                            ManagedRegister mscratch, size_t size) {
   3861   GpuRegister scratch = mscratch.AsMips64().AsGpuRegister();
   3862   CHECK(size == 4 || size == 8) << size;
   3863   if (size == 4) {
   3864     LoadFromOffset(kLoadWord, scratch, src_base.AsMips64().AsGpuRegister(),
   3865                    src_offset.Int32Value());
   3866     StoreToOffset(kStoreDoubleword, scratch, SP, dest.Int32Value());
   3867   } else if (size == 8) {
   3868     LoadFromOffset(kLoadDoubleword, scratch, src_base.AsMips64().AsGpuRegister(),
   3869                    src_offset.Int32Value());
   3870     StoreToOffset(kStoreDoubleword, scratch, SP, dest.Int32Value());
   3871   } else {
   3872     UNIMPLEMENTED(FATAL) << "We only support Copy() of size 4 and 8";
   3873   }
   3874 }
   3875 
   3876 void Mips64Assembler::Copy(ManagedRegister dest_base, Offset dest_offset, FrameOffset src,
   3877                            ManagedRegister mscratch, size_t size) {
   3878   GpuRegister scratch = mscratch.AsMips64().AsGpuRegister();
   3879   CHECK(size == 4 || size == 8) << size;
   3880   if (size == 4) {
   3881     LoadFromOffset(kLoadWord, scratch, SP, src.Int32Value());
   3882     StoreToOffset(kStoreDoubleword, scratch, dest_base.AsMips64().AsGpuRegister(),
   3883                   dest_offset.Int32Value());
   3884   } else if (size == 8) {
   3885     LoadFromOffset(kLoadDoubleword, scratch, SP, src.Int32Value());
   3886     StoreToOffset(kStoreDoubleword, scratch, dest_base.AsMips64().AsGpuRegister(),
   3887                   dest_offset.Int32Value());
   3888   } else {
   3889     UNIMPLEMENTED(FATAL) << "We only support Copy() of size 4 and 8";
   3890   }
   3891 }
   3892 
   3893 void Mips64Assembler::Copy(FrameOffset dest ATTRIBUTE_UNUSED,
   3894                            FrameOffset src_base ATTRIBUTE_UNUSED,
   3895                            Offset src_offset ATTRIBUTE_UNUSED,
   3896                            ManagedRegister mscratch ATTRIBUTE_UNUSED,
   3897                            size_t size ATTRIBUTE_UNUSED) {
   3898   UNIMPLEMENTED(FATAL) << "No MIPS64 implementation";
   3899 }
   3900 
   3901 void Mips64Assembler::Copy(ManagedRegister dest, Offset dest_offset,
   3902                            ManagedRegister src, Offset src_offset,
   3903                            ManagedRegister mscratch, size_t size) {
   3904   GpuRegister scratch = mscratch.AsMips64().AsGpuRegister();
   3905   CHECK(size == 4 || size == 8) << size;
   3906   if (size == 4) {
   3907     LoadFromOffset(kLoadWord, scratch, src.AsMips64().AsGpuRegister(), src_offset.Int32Value());
   3908     StoreToOffset(kStoreDoubleword, scratch, dest.AsMips64().AsGpuRegister(), dest_offset.Int32Value());
   3909   } else if (size == 8) {
   3910     LoadFromOffset(kLoadDoubleword, scratch, src.AsMips64().AsGpuRegister(),
   3911                    src_offset.Int32Value());
   3912     StoreToOffset(kStoreDoubleword, scratch, dest.AsMips64().AsGpuRegister(),
   3913                   dest_offset.Int32Value());
   3914   } else {
   3915     UNIMPLEMENTED(FATAL) << "We only support Copy() of size 4 and 8";
   3916   }
   3917 }
   3918 
   3919 void Mips64Assembler::Copy(FrameOffset dest ATTRIBUTE_UNUSED,
   3920                            Offset dest_offset ATTRIBUTE_UNUSED,
   3921                            FrameOffset src ATTRIBUTE_UNUSED,
   3922                            Offset src_offset ATTRIBUTE_UNUSED,
   3923                            ManagedRegister mscratch ATTRIBUTE_UNUSED,
   3924                            size_t size ATTRIBUTE_UNUSED) {
   3925   UNIMPLEMENTED(FATAL) << "No MIPS64 implementation";
   3926 }
   3927 
   3928 void Mips64Assembler::MemoryBarrier(ManagedRegister mreg ATTRIBUTE_UNUSED) {
   3929   // TODO: sync?
   3930   UNIMPLEMENTED(FATAL) << "No MIPS64 implementation";
   3931 }
   3932 
   3933 void Mips64Assembler::CreateHandleScopeEntry(ManagedRegister mout_reg,
   3934                                              FrameOffset handle_scope_offset,
   3935                                              ManagedRegister min_reg,
   3936                                              bool null_allowed) {
   3937   Mips64ManagedRegister out_reg = mout_reg.AsMips64();
   3938   Mips64ManagedRegister in_reg = min_reg.AsMips64();
   3939   CHECK(in_reg.IsNoRegister() || in_reg.IsGpuRegister()) << in_reg;
   3940   CHECK(out_reg.IsGpuRegister()) << out_reg;
   3941   if (null_allowed) {
   3942     Mips64Label null_arg;
   3943     // Null values get a handle scope entry value of 0.  Otherwise, the handle scope entry is
   3944     // the address in the handle scope holding the reference.
   3945     // e.g. out_reg = (handle == 0) ? 0 : (SP+handle_offset)
   3946     if (in_reg.IsNoRegister()) {
   3947       LoadFromOffset(kLoadUnsignedWord, out_reg.AsGpuRegister(),
   3948                      SP, handle_scope_offset.Int32Value());
   3949       in_reg = out_reg;
   3950     }
   3951     if (!out_reg.Equals(in_reg)) {
   3952       LoadConst32(out_reg.AsGpuRegister(), 0);
   3953     }
   3954     Beqzc(in_reg.AsGpuRegister(), &null_arg);
   3955     Daddiu64(out_reg.AsGpuRegister(), SP, handle_scope_offset.Int32Value());
   3956     Bind(&null_arg);
   3957   } else {
   3958     Daddiu64(out_reg.AsGpuRegister(), SP, handle_scope_offset.Int32Value());
   3959   }
   3960 }
   3961 
   3962 void Mips64Assembler::CreateHandleScopeEntry(FrameOffset out_off,
   3963                                              FrameOffset handle_scope_offset,
   3964                                              ManagedRegister mscratch,
   3965                                              bool null_allowed) {
   3966   Mips64ManagedRegister scratch = mscratch.AsMips64();
   3967   CHECK(scratch.IsGpuRegister()) << scratch;
   3968   if (null_allowed) {
   3969     Mips64Label null_arg;
   3970     LoadFromOffset(kLoadUnsignedWord, scratch.AsGpuRegister(), SP,
   3971                    handle_scope_offset.Int32Value());
   3972     // Null values get a handle scope entry value of 0.  Otherwise, the handle scope entry is
   3973     // the address in the handle scope holding the reference.
   3974     // e.g. scratch = (scratch == 0) ? 0 : (SP+handle_scope_offset)
   3975     Beqzc(scratch.AsGpuRegister(), &null_arg);
   3976     Daddiu64(scratch.AsGpuRegister(), SP, handle_scope_offset.Int32Value());
   3977     Bind(&null_arg);
   3978   } else {
   3979     Daddiu64(scratch.AsGpuRegister(), SP, handle_scope_offset.Int32Value());
   3980   }
   3981   StoreToOffset(kStoreDoubleword, scratch.AsGpuRegister(), SP, out_off.Int32Value());
   3982 }
   3983 
   3984 // Given a handle scope entry, load the associated reference.
   3985 void Mips64Assembler::LoadReferenceFromHandleScope(ManagedRegister mout_reg,
   3986                                                    ManagedRegister min_reg) {
   3987   Mips64ManagedRegister out_reg = mout_reg.AsMips64();
   3988   Mips64ManagedRegister in_reg = min_reg.AsMips64();
   3989   CHECK(out_reg.IsGpuRegister()) << out_reg;
   3990   CHECK(in_reg.IsGpuRegister()) << in_reg;
   3991   Mips64Label null_arg;
   3992   if (!out_reg.Equals(in_reg)) {
   3993     LoadConst32(out_reg.AsGpuRegister(), 0);
   3994   }
   3995   Beqzc(in_reg.AsGpuRegister(), &null_arg);
   3996   LoadFromOffset(kLoadDoubleword, out_reg.AsGpuRegister(),
   3997                  in_reg.AsGpuRegister(), 0);
   3998   Bind(&null_arg);
   3999 }
   4000 
   4001 void Mips64Assembler::VerifyObject(ManagedRegister src ATTRIBUTE_UNUSED,
   4002                                    bool could_be_null ATTRIBUTE_UNUSED) {
   4003   // TODO: not validating references
   4004 }
   4005 
   4006 void Mips64Assembler::VerifyObject(FrameOffset src ATTRIBUTE_UNUSED,
   4007                                    bool could_be_null ATTRIBUTE_UNUSED) {
   4008   // TODO: not validating references
   4009 }
   4010 
   4011 void Mips64Assembler::Call(ManagedRegister mbase, Offset offset, ManagedRegister mscratch) {
   4012   Mips64ManagedRegister base = mbase.AsMips64();
   4013   Mips64ManagedRegister scratch = mscratch.AsMips64();
   4014   CHECK(base.IsGpuRegister()) << base;
   4015   CHECK(scratch.IsGpuRegister()) << scratch;
   4016   LoadFromOffset(kLoadDoubleword, scratch.AsGpuRegister(),
   4017                  base.AsGpuRegister(), offset.Int32Value());
   4018   Jalr(scratch.AsGpuRegister());
   4019   Nop();
   4020   // TODO: place reference map on call
   4021 }
   4022 
   4023 void Mips64Assembler::Call(FrameOffset base, Offset offset, ManagedRegister mscratch) {
   4024   Mips64ManagedRegister scratch = mscratch.AsMips64();
   4025   CHECK(scratch.IsGpuRegister()) << scratch;
   4026   // Call *(*(SP + base) + offset)
   4027   LoadFromOffset(kLoadDoubleword, scratch.AsGpuRegister(),
   4028                  SP, base.Int32Value());
   4029   LoadFromOffset(kLoadDoubleword, scratch.AsGpuRegister(),
   4030                  scratch.AsGpuRegister(), offset.Int32Value());
   4031   Jalr(scratch.AsGpuRegister());
   4032   Nop();
   4033   // TODO: place reference map on call
   4034 }
   4035 
   4036 void Mips64Assembler::CallFromThread(ThreadOffset64 offset ATTRIBUTE_UNUSED,
   4037                                      ManagedRegister mscratch ATTRIBUTE_UNUSED) {
   4038   UNIMPLEMENTED(FATAL) << "No MIPS64 implementation";
   4039 }
   4040 
   4041 void Mips64Assembler::GetCurrentThread(ManagedRegister tr) {
   4042   Move(tr.AsMips64().AsGpuRegister(), S1);
   4043 }
   4044 
   4045 void Mips64Assembler::GetCurrentThread(FrameOffset offset,
   4046                                        ManagedRegister mscratch ATTRIBUTE_UNUSED) {
   4047   StoreToOffset(kStoreDoubleword, S1, SP, offset.Int32Value());
   4048 }
   4049 
   4050 void Mips64Assembler::ExceptionPoll(ManagedRegister mscratch, size_t stack_adjust) {
   4051   Mips64ManagedRegister scratch = mscratch.AsMips64();
   4052   exception_blocks_.emplace_back(scratch, stack_adjust);
   4053   LoadFromOffset(kLoadDoubleword,
   4054                  scratch.AsGpuRegister(),
   4055                  S1,
   4056                  Thread::ExceptionOffset<kMips64PointerSize>().Int32Value());
   4057   Bnezc(scratch.AsGpuRegister(), exception_blocks_.back().Entry());
   4058 }
   4059 
   4060 void Mips64Assembler::EmitExceptionPoll(Mips64ExceptionSlowPath* exception) {
   4061   Bind(exception->Entry());
   4062   if (exception->stack_adjust_ != 0) {  // Fix up the frame.
   4063     DecreaseFrameSize(exception->stack_adjust_);
   4064   }
   4065   // Pass exception object as argument.
   4066   // Don't care about preserving A0 as this call won't return.
   4067   CheckEntrypointTypes<kQuickDeliverException, void, mirror::Object*>();
   4068   Move(A0, exception->scratch_.AsGpuRegister());
   4069   // Set up call to Thread::Current()->pDeliverException
   4070   LoadFromOffset(kLoadDoubleword,
   4071                  T9,
   4072                  S1,
   4073                  QUICK_ENTRYPOINT_OFFSET(kMips64PointerSize, pDeliverException).Int32Value());
   4074   Jr(T9);
   4075   Nop();
   4076 
   4077   // Call never returns
   4078   Break();
   4079 }
   4080 
   4081 }  // namespace mips64
   4082 }  // namespace art
   4083