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