1 /*
2 * Copyright (C) 2014 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include "assembler_mips64.h"
18
19 #include "base/bit_utils.h"
20 #include "base/casts.h"
21 #include "entrypoints/quick/quick_entrypoints.h"
22 #include "entrypoints/quick/quick_entrypoints_enum.h"
23 #include "memory_region.h"
24 #include "thread.h"
25
26 namespace art {
27 namespace mips64 {
28
29 static_assert(static_cast<size_t>(kMips64PointerSize) == kMips64DoublewordSize,
30 "Unexpected Mips64 pointer size.");
31 static_assert(kMips64PointerSize == PointerSize::k64, "Unexpected Mips64 pointer size.");
32
33
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 typedef DebugFrameOpCodeWriterForAssembler::DelayedAdvancePC DelayedAdvancePC;
56 const auto data = cfi().ReleaseStreamAndPrepareForDelayedAdvancePC();
57 const std::vector<uint8_t>& old_stream = data.first;
58 const std::vector<DelayedAdvancePC>& advances = data.second;
59
60 // Refill our data buffer with patched opcodes.
61 cfi().ReserveCFIStream(old_stream.size() + advances.size() + 16);
62 size_t stream_pos = 0;
63 for (const DelayedAdvancePC& advance : advances) {
64 DCHECK_GE(advance.stream_pos, stream_pos);
65 // Copy old data up to the point where advance was issued.
66 cfi().AppendRawData(old_stream, stream_pos, advance.stream_pos);
67 stream_pos = advance.stream_pos;
68 // Insert the advance command with its final offset.
69 size_t final_pc = GetAdjustedPosition(advance.pc);
70 cfi().AdvancePC(final_pc);
71 }
72 // Copy the final segment if any.
73 cfi().AppendRawData(old_stream, stream_pos, old_stream.size());
74 }
75
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
ReplicateFPToVectorRegister(VectorRegister dst,FpuRegister src,bool is_double)2282 void Mips64Assembler::ReplicateFPToVectorRegister(VectorRegister dst,
2283 FpuRegister src,
2284 bool is_double) {
2285 // Float or double in FPU register Fx can be considered as 0th element in vector register Wx.
2286 if (is_double) {
2287 SplatiD(dst, static_cast<VectorRegister>(src), 0);
2288 } else {
2289 SplatiW(dst, static_cast<VectorRegister>(src), 0);
2290 }
2291 }
2292
LoadConst32(GpuRegister rd,int32_t value)2293 void Mips64Assembler::LoadConst32(GpuRegister rd, int32_t value) {
2294 TemplateLoadConst32(this, rd, value);
2295 }
2296
2297 // This function is only used for testing purposes.
RecordLoadConst64Path(int value ATTRIBUTE_UNUSED)2298 void Mips64Assembler::RecordLoadConst64Path(int value ATTRIBUTE_UNUSED) {
2299 }
2300
LoadConst64(GpuRegister rd,int64_t value)2301 void Mips64Assembler::LoadConst64(GpuRegister rd, int64_t value) {
2302 TemplateLoadConst64(this, rd, value);
2303 }
2304
Addiu32(GpuRegister rt,GpuRegister rs,int32_t value)2305 void Mips64Assembler::Addiu32(GpuRegister rt, GpuRegister rs, int32_t value) {
2306 if (IsInt<16>(value)) {
2307 Addiu(rt, rs, value);
2308 } else {
2309 int16_t high = High16Bits(value);
2310 int16_t low = Low16Bits(value);
2311 high += (low < 0) ? 1 : 0; // Account for sign extension in addiu.
2312 Aui(rt, rs, high);
2313 if (low != 0) {
2314 Addiu(rt, rt, low);
2315 }
2316 }
2317 }
2318
2319 // TODO: don't use rtmp, use daui, dahi, dati.
Daddiu64(GpuRegister rt,GpuRegister rs,int64_t value,GpuRegister rtmp)2320 void Mips64Assembler::Daddiu64(GpuRegister rt, GpuRegister rs, int64_t value, GpuRegister rtmp) {
2321 CHECK_NE(rs, rtmp);
2322 if (IsInt<16>(value)) {
2323 Daddiu(rt, rs, value);
2324 } else {
2325 LoadConst64(rtmp, value);
2326 Daddu(rt, rs, rtmp);
2327 }
2328 }
2329
InitShortOrLong(Mips64Assembler::Branch::OffsetBits offset_size,Mips64Assembler::Branch::Type short_type,Mips64Assembler::Branch::Type long_type)2330 void Mips64Assembler::Branch::InitShortOrLong(Mips64Assembler::Branch::OffsetBits offset_size,
2331 Mips64Assembler::Branch::Type short_type,
2332 Mips64Assembler::Branch::Type long_type) {
2333 type_ = (offset_size <= branch_info_[short_type].offset_size) ? short_type : long_type;
2334 }
2335
InitializeType(Type initial_type,bool is_r6)2336 void Mips64Assembler::Branch::InitializeType(Type initial_type, bool is_r6) {
2337 OffsetBits offset_size_needed = GetOffsetSizeNeeded(location_, target_);
2338 if (is_r6) {
2339 // R6
2340 switch (initial_type) {
2341 case kLabel:
2342 case kLiteral:
2343 case kLiteralUnsigned:
2344 case kLiteralLong:
2345 CHECK(!IsResolved());
2346 type_ = initial_type;
2347 break;
2348 case kCall:
2349 InitShortOrLong(offset_size_needed, kCall, kLongCall);
2350 break;
2351 case kCondBranch:
2352 switch (condition_) {
2353 case kUncond:
2354 InitShortOrLong(offset_size_needed, kUncondBranch, kLongUncondBranch);
2355 break;
2356 case kCondEQZ:
2357 case kCondNEZ:
2358 // Special case for beqzc/bnezc with longer offset than in other b<cond>c instructions.
2359 type_ = (offset_size_needed <= kOffset23) ? kCondBranch : kLongCondBranch;
2360 break;
2361 default:
2362 InitShortOrLong(offset_size_needed, kCondBranch, kLongCondBranch);
2363 break;
2364 }
2365 break;
2366 case kBareCall:
2367 type_ = kBareCall;
2368 CHECK_LE(offset_size_needed, GetOffsetSize());
2369 break;
2370 case kBareCondBranch:
2371 type_ = (condition_ == kUncond) ? kBareUncondBranch : kBareCondBranch;
2372 CHECK_LE(offset_size_needed, GetOffsetSize());
2373 break;
2374 default:
2375 LOG(FATAL) << "Unexpected branch type " << initial_type;
2376 UNREACHABLE();
2377 }
2378 } else {
2379 // R2
2380 CHECK_EQ(initial_type, kBareCondBranch);
2381 switch (condition_) {
2382 case kCondLTZ:
2383 case kCondGEZ:
2384 case kCondLEZ:
2385 case kCondGTZ:
2386 case kCondEQ:
2387 case kCondNE:
2388 case kCondEQZ:
2389 case kCondNEZ:
2390 break;
2391 default:
2392 LOG(FATAL) << "Unexpected R2 branch condition " << condition_;
2393 UNREACHABLE();
2394 }
2395 type_ = kR2BareCondBranch;
2396 CHECK_LE(offset_size_needed, GetOffsetSize());
2397 }
2398 old_type_ = type_;
2399 }
2400
IsNop(BranchCondition condition,GpuRegister lhs,GpuRegister rhs)2401 bool Mips64Assembler::Branch::IsNop(BranchCondition condition, GpuRegister lhs, GpuRegister rhs) {
2402 switch (condition) {
2403 case kCondLT:
2404 case kCondGT:
2405 case kCondNE:
2406 case kCondLTU:
2407 return lhs == rhs;
2408 default:
2409 return false;
2410 }
2411 }
2412
IsUncond(BranchCondition condition,GpuRegister lhs,GpuRegister rhs)2413 bool Mips64Assembler::Branch::IsUncond(BranchCondition condition,
2414 GpuRegister lhs,
2415 GpuRegister rhs) {
2416 switch (condition) {
2417 case kUncond:
2418 return true;
2419 case kCondGE:
2420 case kCondLE:
2421 case kCondEQ:
2422 case kCondGEU:
2423 return lhs == rhs;
2424 default:
2425 return false;
2426 }
2427 }
2428
Branch(uint32_t location,uint32_t target,bool is_call,bool is_bare)2429 Mips64Assembler::Branch::Branch(uint32_t location, uint32_t target, bool is_call, bool is_bare)
2430 : old_location_(location),
2431 location_(location),
2432 target_(target),
2433 lhs_reg_(ZERO),
2434 rhs_reg_(ZERO),
2435 condition_(kUncond) {
2436 InitializeType(
2437 (is_call ? (is_bare ? kBareCall : kCall) : (is_bare ? kBareCondBranch : kCondBranch)),
2438 /* is_r6 */ true);
2439 }
2440
Branch(bool is_r6,uint32_t location,uint32_t target,Mips64Assembler::BranchCondition condition,GpuRegister lhs_reg,GpuRegister rhs_reg,bool is_bare)2441 Mips64Assembler::Branch::Branch(bool is_r6,
2442 uint32_t location,
2443 uint32_t target,
2444 Mips64Assembler::BranchCondition condition,
2445 GpuRegister lhs_reg,
2446 GpuRegister rhs_reg,
2447 bool is_bare)
2448 : old_location_(location),
2449 location_(location),
2450 target_(target),
2451 lhs_reg_(lhs_reg),
2452 rhs_reg_(rhs_reg),
2453 condition_(condition) {
2454 CHECK_NE(condition, kUncond);
2455 switch (condition) {
2456 case kCondEQ:
2457 case kCondNE:
2458 case kCondLT:
2459 case kCondGE:
2460 case kCondLE:
2461 case kCondGT:
2462 case kCondLTU:
2463 case kCondGEU:
2464 CHECK_NE(lhs_reg, ZERO);
2465 CHECK_NE(rhs_reg, ZERO);
2466 break;
2467 case kCondLTZ:
2468 case kCondGEZ:
2469 case kCondLEZ:
2470 case kCondGTZ:
2471 case kCondEQZ:
2472 case kCondNEZ:
2473 CHECK_NE(lhs_reg, ZERO);
2474 CHECK_EQ(rhs_reg, ZERO);
2475 break;
2476 case kCondF:
2477 case kCondT:
2478 CHECK_EQ(rhs_reg, ZERO);
2479 break;
2480 case kUncond:
2481 UNREACHABLE();
2482 }
2483 CHECK(!IsNop(condition, lhs_reg, rhs_reg));
2484 if (IsUncond(condition, lhs_reg, rhs_reg)) {
2485 // Branch condition is always true, make the branch unconditional.
2486 condition_ = kUncond;
2487 }
2488 InitializeType((is_bare ? kBareCondBranch : kCondBranch), is_r6);
2489 }
2490
Branch(uint32_t location,GpuRegister dest_reg,Type label_or_literal_type)2491 Mips64Assembler::Branch::Branch(uint32_t location, GpuRegister dest_reg, Type label_or_literal_type)
2492 : old_location_(location),
2493 location_(location),
2494 target_(kUnresolved),
2495 lhs_reg_(dest_reg),
2496 rhs_reg_(ZERO),
2497 condition_(kUncond) {
2498 CHECK_NE(dest_reg, ZERO);
2499 InitializeType(label_or_literal_type, /* is_r6 */ true);
2500 }
2501
OppositeCondition(Mips64Assembler::BranchCondition cond)2502 Mips64Assembler::BranchCondition Mips64Assembler::Branch::OppositeCondition(
2503 Mips64Assembler::BranchCondition cond) {
2504 switch (cond) {
2505 case kCondLT:
2506 return kCondGE;
2507 case kCondGE:
2508 return kCondLT;
2509 case kCondLE:
2510 return kCondGT;
2511 case kCondGT:
2512 return kCondLE;
2513 case kCondLTZ:
2514 return kCondGEZ;
2515 case kCondGEZ:
2516 return kCondLTZ;
2517 case kCondLEZ:
2518 return kCondGTZ;
2519 case kCondGTZ:
2520 return kCondLEZ;
2521 case kCondEQ:
2522 return kCondNE;
2523 case kCondNE:
2524 return kCondEQ;
2525 case kCondEQZ:
2526 return kCondNEZ;
2527 case kCondNEZ:
2528 return kCondEQZ;
2529 case kCondLTU:
2530 return kCondGEU;
2531 case kCondGEU:
2532 return kCondLTU;
2533 case kCondF:
2534 return kCondT;
2535 case kCondT:
2536 return kCondF;
2537 case kUncond:
2538 LOG(FATAL) << "Unexpected branch condition " << cond;
2539 }
2540 UNREACHABLE();
2541 }
2542
GetType() const2543 Mips64Assembler::Branch::Type Mips64Assembler::Branch::GetType() const {
2544 return type_;
2545 }
2546
GetCondition() const2547 Mips64Assembler::BranchCondition Mips64Assembler::Branch::GetCondition() const {
2548 return condition_;
2549 }
2550
GetLeftRegister() const2551 GpuRegister Mips64Assembler::Branch::GetLeftRegister() const {
2552 return lhs_reg_;
2553 }
2554
GetRightRegister() const2555 GpuRegister Mips64Assembler::Branch::GetRightRegister() const {
2556 return rhs_reg_;
2557 }
2558
GetTarget() const2559 uint32_t Mips64Assembler::Branch::GetTarget() const {
2560 return target_;
2561 }
2562
GetLocation() const2563 uint32_t Mips64Assembler::Branch::GetLocation() const {
2564 return location_;
2565 }
2566
GetOldLocation() const2567 uint32_t Mips64Assembler::Branch::GetOldLocation() const {
2568 return old_location_;
2569 }
2570
GetLength() const2571 uint32_t Mips64Assembler::Branch::GetLength() const {
2572 return branch_info_[type_].length;
2573 }
2574
GetOldLength() const2575 uint32_t Mips64Assembler::Branch::GetOldLength() const {
2576 return branch_info_[old_type_].length;
2577 }
2578
GetSize() const2579 uint32_t Mips64Assembler::Branch::GetSize() const {
2580 return GetLength() * sizeof(uint32_t);
2581 }
2582
GetOldSize() const2583 uint32_t Mips64Assembler::Branch::GetOldSize() const {
2584 return GetOldLength() * sizeof(uint32_t);
2585 }
2586
GetEndLocation() const2587 uint32_t Mips64Assembler::Branch::GetEndLocation() const {
2588 return GetLocation() + GetSize();
2589 }
2590
GetOldEndLocation() const2591 uint32_t Mips64Assembler::Branch::GetOldEndLocation() const {
2592 return GetOldLocation() + GetOldSize();
2593 }
2594
IsBare() const2595 bool Mips64Assembler::Branch::IsBare() const {
2596 switch (type_) {
2597 // R6 short branches (can't be promoted to long), forbidden/delay slots filled manually.
2598 case kBareUncondBranch:
2599 case kBareCondBranch:
2600 case kBareCall:
2601 // R2 short branches (can't be promoted to long), delay slots filled manually.
2602 case kR2BareCondBranch:
2603 return true;
2604 default:
2605 return false;
2606 }
2607 }
2608
IsLong() const2609 bool Mips64Assembler::Branch::IsLong() const {
2610 switch (type_) {
2611 // R6 short branches (can be promoted to long).
2612 case kUncondBranch:
2613 case kCondBranch:
2614 case kCall:
2615 // R6 short branches (can't be promoted to long), forbidden/delay slots filled manually.
2616 case kBareUncondBranch:
2617 case kBareCondBranch:
2618 case kBareCall:
2619 // R2 short branches (can't be promoted to long), delay slots filled manually.
2620 case kR2BareCondBranch:
2621 // Near label.
2622 case kLabel:
2623 // Near literals.
2624 case kLiteral:
2625 case kLiteralUnsigned:
2626 case kLiteralLong:
2627 return false;
2628 // Long branches.
2629 case kLongUncondBranch:
2630 case kLongCondBranch:
2631 case kLongCall:
2632 // Far label.
2633 case kFarLabel:
2634 // Far literals.
2635 case kFarLiteral:
2636 case kFarLiteralUnsigned:
2637 case kFarLiteralLong:
2638 return true;
2639 }
2640 UNREACHABLE();
2641 }
2642
IsResolved() const2643 bool Mips64Assembler::Branch::IsResolved() const {
2644 return target_ != kUnresolved;
2645 }
2646
GetOffsetSize() const2647 Mips64Assembler::Branch::OffsetBits Mips64Assembler::Branch::GetOffsetSize() const {
2648 bool r6_cond_branch = (type_ == kCondBranch || type_ == kBareCondBranch);
2649 OffsetBits offset_size =
2650 (r6_cond_branch && (condition_ == kCondEQZ || condition_ == kCondNEZ))
2651 ? kOffset23
2652 : branch_info_[type_].offset_size;
2653 return offset_size;
2654 }
2655
GetOffsetSizeNeeded(uint32_t location,uint32_t target)2656 Mips64Assembler::Branch::OffsetBits Mips64Assembler::Branch::GetOffsetSizeNeeded(uint32_t location,
2657 uint32_t target) {
2658 // For unresolved targets assume the shortest encoding
2659 // (later it will be made longer if needed).
2660 if (target == kUnresolved)
2661 return kOffset16;
2662 int64_t distance = static_cast<int64_t>(target) - location;
2663 // To simplify calculations in composite branches consisting of multiple instructions
2664 // bump up the distance by a value larger than the max byte size of a composite branch.
2665 distance += (distance >= 0) ? kMaxBranchSize : -kMaxBranchSize;
2666 if (IsInt<kOffset16>(distance))
2667 return kOffset16;
2668 else if (IsInt<kOffset18>(distance))
2669 return kOffset18;
2670 else if (IsInt<kOffset21>(distance))
2671 return kOffset21;
2672 else if (IsInt<kOffset23>(distance))
2673 return kOffset23;
2674 else if (IsInt<kOffset28>(distance))
2675 return kOffset28;
2676 return kOffset32;
2677 }
2678
Resolve(uint32_t target)2679 void Mips64Assembler::Branch::Resolve(uint32_t target) {
2680 target_ = target;
2681 }
2682
Relocate(uint32_t expand_location,uint32_t delta)2683 void Mips64Assembler::Branch::Relocate(uint32_t expand_location, uint32_t delta) {
2684 if (location_ > expand_location) {
2685 location_ += delta;
2686 }
2687 if (!IsResolved()) {
2688 return; // Don't know the target yet.
2689 }
2690 if (target_ > expand_location) {
2691 target_ += delta;
2692 }
2693 }
2694
PromoteToLong()2695 void Mips64Assembler::Branch::PromoteToLong() {
2696 CHECK(!IsBare()); // Bare branches do not promote.
2697 switch (type_) {
2698 // R6 short branches (can be promoted to long).
2699 case kUncondBranch:
2700 type_ = kLongUncondBranch;
2701 break;
2702 case kCondBranch:
2703 type_ = kLongCondBranch;
2704 break;
2705 case kCall:
2706 type_ = kLongCall;
2707 break;
2708 // Near label.
2709 case kLabel:
2710 type_ = kFarLabel;
2711 break;
2712 // Near literals.
2713 case kLiteral:
2714 type_ = kFarLiteral;
2715 break;
2716 case kLiteralUnsigned:
2717 type_ = kFarLiteralUnsigned;
2718 break;
2719 case kLiteralLong:
2720 type_ = kFarLiteralLong;
2721 break;
2722 default:
2723 // Note: 'type_' is already long.
2724 break;
2725 }
2726 CHECK(IsLong());
2727 }
2728
PromoteIfNeeded(uint32_t max_short_distance)2729 uint32_t Mips64Assembler::Branch::PromoteIfNeeded(uint32_t max_short_distance) {
2730 // If the branch is still unresolved or already long, nothing to do.
2731 if (IsLong() || !IsResolved()) {
2732 return 0;
2733 }
2734 // Promote the short branch to long if the offset size is too small
2735 // to hold the distance between location_ and target_.
2736 if (GetOffsetSizeNeeded(location_, target_) > GetOffsetSize()) {
2737 PromoteToLong();
2738 uint32_t old_size = GetOldSize();
2739 uint32_t new_size = GetSize();
2740 CHECK_GT(new_size, old_size);
2741 return new_size - old_size;
2742 }
2743 // The following logic is for debugging/testing purposes.
2744 // Promote some short branches to long when it's not really required.
2745 if (UNLIKELY(max_short_distance != std::numeric_limits<uint32_t>::max() && !IsBare())) {
2746 int64_t distance = static_cast<int64_t>(target_) - location_;
2747 distance = (distance >= 0) ? distance : -distance;
2748 if (distance >= max_short_distance) {
2749 PromoteToLong();
2750 uint32_t old_size = GetOldSize();
2751 uint32_t new_size = GetSize();
2752 CHECK_GT(new_size, old_size);
2753 return new_size - old_size;
2754 }
2755 }
2756 return 0;
2757 }
2758
GetOffsetLocation() const2759 uint32_t Mips64Assembler::Branch::GetOffsetLocation() const {
2760 return location_ + branch_info_[type_].instr_offset * sizeof(uint32_t);
2761 }
2762
GetOffset() const2763 uint32_t Mips64Assembler::Branch::GetOffset() const {
2764 CHECK(IsResolved());
2765 uint32_t ofs_mask = 0xFFFFFFFF >> (32 - GetOffsetSize());
2766 // Calculate the byte distance between instructions and also account for
2767 // different PC-relative origins.
2768 uint32_t offset_location = GetOffsetLocation();
2769 if (type_ == kLiteralLong) {
2770 // Special case for the ldpc instruction, whose address (PC) is rounded down to
2771 // a multiple of 8 before adding the offset.
2772 // Note, branch promotion has already taken care of aligning `target_` to an
2773 // address that's a multiple of 8.
2774 offset_location = RoundDown(offset_location, sizeof(uint64_t));
2775 }
2776 uint32_t offset = target_ - offset_location - branch_info_[type_].pc_org * sizeof(uint32_t);
2777 // Prepare the offset for encoding into the instruction(s).
2778 offset = (offset & ofs_mask) >> branch_info_[type_].offset_shift;
2779 return offset;
2780 }
2781
GetBranch(uint32_t branch_id)2782 Mips64Assembler::Branch* Mips64Assembler::GetBranch(uint32_t branch_id) {
2783 CHECK_LT(branch_id, branches_.size());
2784 return &branches_[branch_id];
2785 }
2786
GetBranch(uint32_t branch_id) const2787 const Mips64Assembler::Branch* Mips64Assembler::GetBranch(uint32_t branch_id) const {
2788 CHECK_LT(branch_id, branches_.size());
2789 return &branches_[branch_id];
2790 }
2791
Bind(Mips64Label * label)2792 void Mips64Assembler::Bind(Mips64Label* label) {
2793 CHECK(!label->IsBound());
2794 uint32_t bound_pc = buffer_.Size();
2795
2796 // Walk the list of branches referring to and preceding this label.
2797 // Store the previously unknown target addresses in them.
2798 while (label->IsLinked()) {
2799 uint32_t branch_id = label->Position();
2800 Branch* branch = GetBranch(branch_id);
2801 branch->Resolve(bound_pc);
2802
2803 uint32_t branch_location = branch->GetLocation();
2804 // Extract the location of the previous branch in the list (walking the list backwards;
2805 // the previous branch ID was stored in the space reserved for this branch).
2806 uint32_t prev = buffer_.Load<uint32_t>(branch_location);
2807
2808 // On to the previous branch in the list...
2809 label->position_ = prev;
2810 }
2811
2812 // Now make the label object contain its own location (relative to the end of the preceding
2813 // branch, if any; it will be used by the branches referring to and following this label).
2814 label->prev_branch_id_plus_one_ = branches_.size();
2815 if (label->prev_branch_id_plus_one_) {
2816 uint32_t branch_id = label->prev_branch_id_plus_one_ - 1;
2817 const Branch* branch = GetBranch(branch_id);
2818 bound_pc -= branch->GetEndLocation();
2819 }
2820 label->BindTo(bound_pc);
2821 }
2822
GetLabelLocation(const Mips64Label * label) const2823 uint32_t Mips64Assembler::GetLabelLocation(const Mips64Label* label) const {
2824 CHECK(label->IsBound());
2825 uint32_t target = label->Position();
2826 if (label->prev_branch_id_plus_one_) {
2827 // Get label location based on the branch preceding it.
2828 uint32_t branch_id = label->prev_branch_id_plus_one_ - 1;
2829 const Branch* branch = GetBranch(branch_id);
2830 target += branch->GetEndLocation();
2831 }
2832 return target;
2833 }
2834
GetAdjustedPosition(uint32_t old_position)2835 uint32_t Mips64Assembler::GetAdjustedPosition(uint32_t old_position) {
2836 // We can reconstruct the adjustment by going through all the branches from the beginning
2837 // up to the old_position. Since we expect AdjustedPosition() to be called in a loop
2838 // with increasing old_position, we can use the data from last AdjustedPosition() to
2839 // continue where we left off and the whole loop should be O(m+n) where m is the number
2840 // of positions to adjust and n is the number of branches.
2841 if (old_position < last_old_position_) {
2842 last_position_adjustment_ = 0;
2843 last_old_position_ = 0;
2844 last_branch_id_ = 0;
2845 }
2846 while (last_branch_id_ != branches_.size()) {
2847 const Branch* branch = GetBranch(last_branch_id_);
2848 if (branch->GetLocation() >= old_position + last_position_adjustment_) {
2849 break;
2850 }
2851 last_position_adjustment_ += branch->GetSize() - branch->GetOldSize();
2852 ++last_branch_id_;
2853 }
2854 last_old_position_ = old_position;
2855 return old_position + last_position_adjustment_;
2856 }
2857
FinalizeLabeledBranch(Mips64Label * label)2858 void Mips64Assembler::FinalizeLabeledBranch(Mips64Label* label) {
2859 uint32_t length = branches_.back().GetLength();
2860 if (!label->IsBound()) {
2861 // Branch forward (to a following label), distance is unknown.
2862 // The first branch forward will contain 0, serving as the terminator of
2863 // the list of forward-reaching branches.
2864 Emit(label->position_);
2865 length--;
2866 // Now make the label object point to this branch
2867 // (this forms a linked list of branches preceding this label).
2868 uint32_t branch_id = branches_.size() - 1;
2869 label->LinkTo(branch_id);
2870 }
2871 // Reserve space for the branch.
2872 while (length--) {
2873 Nop();
2874 }
2875 }
2876
Buncond(Mips64Label * label,bool is_bare)2877 void Mips64Assembler::Buncond(Mips64Label* label, bool is_bare) {
2878 uint32_t target = label->IsBound() ? GetLabelLocation(label) : Branch::kUnresolved;
2879 branches_.emplace_back(buffer_.Size(), target, /* is_call */ false, is_bare);
2880 FinalizeLabeledBranch(label);
2881 }
2882
Bcond(Mips64Label * label,bool is_r6,bool is_bare,BranchCondition condition,GpuRegister lhs,GpuRegister rhs)2883 void Mips64Assembler::Bcond(Mips64Label* label,
2884 bool is_r6,
2885 bool is_bare,
2886 BranchCondition condition,
2887 GpuRegister lhs,
2888 GpuRegister rhs) {
2889 // If lhs = rhs, this can be a NOP.
2890 if (Branch::IsNop(condition, lhs, rhs)) {
2891 return;
2892 }
2893 uint32_t target = label->IsBound() ? GetLabelLocation(label) : Branch::kUnresolved;
2894 branches_.emplace_back(is_r6, buffer_.Size(), target, condition, lhs, rhs, is_bare);
2895 FinalizeLabeledBranch(label);
2896 }
2897
Call(Mips64Label * label,bool is_bare)2898 void Mips64Assembler::Call(Mips64Label* label, bool is_bare) {
2899 uint32_t target = label->IsBound() ? GetLabelLocation(label) : Branch::kUnresolved;
2900 branches_.emplace_back(buffer_.Size(), target, /* is_call */ true, is_bare);
2901 FinalizeLabeledBranch(label);
2902 }
2903
LoadLabelAddress(GpuRegister dest_reg,Mips64Label * label)2904 void Mips64Assembler::LoadLabelAddress(GpuRegister dest_reg, Mips64Label* label) {
2905 // Label address loads are treated as pseudo branches since they require very similar handling.
2906 DCHECK(!label->IsBound());
2907 branches_.emplace_back(buffer_.Size(), dest_reg, Branch::kLabel);
2908 FinalizeLabeledBranch(label);
2909 }
2910
NewLiteral(size_t size,const uint8_t * data)2911 Literal* Mips64Assembler::NewLiteral(size_t size, const uint8_t* data) {
2912 // We don't support byte and half-word literals.
2913 if (size == 4u) {
2914 literals_.emplace_back(size, data);
2915 return &literals_.back();
2916 } else {
2917 DCHECK_EQ(size, 8u);
2918 long_literals_.emplace_back(size, data);
2919 return &long_literals_.back();
2920 }
2921 }
2922
LoadLiteral(GpuRegister dest_reg,LoadOperandType load_type,Literal * literal)2923 void Mips64Assembler::LoadLiteral(GpuRegister dest_reg,
2924 LoadOperandType load_type,
2925 Literal* literal) {
2926 // Literal loads are treated as pseudo branches since they require very similar handling.
2927 Branch::Type literal_type;
2928 switch (load_type) {
2929 case kLoadWord:
2930 DCHECK_EQ(literal->GetSize(), 4u);
2931 literal_type = Branch::kLiteral;
2932 break;
2933 case kLoadUnsignedWord:
2934 DCHECK_EQ(literal->GetSize(), 4u);
2935 literal_type = Branch::kLiteralUnsigned;
2936 break;
2937 case kLoadDoubleword:
2938 DCHECK_EQ(literal->GetSize(), 8u);
2939 literal_type = Branch::kLiteralLong;
2940 break;
2941 default:
2942 LOG(FATAL) << "Unexpected literal load type " << load_type;
2943 UNREACHABLE();
2944 }
2945 Mips64Label* label = literal->GetLabel();
2946 DCHECK(!label->IsBound());
2947 branches_.emplace_back(buffer_.Size(), dest_reg, literal_type);
2948 FinalizeLabeledBranch(label);
2949 }
2950
CreateJumpTable(std::vector<Mips64Label * > && labels)2951 JumpTable* Mips64Assembler::CreateJumpTable(std::vector<Mips64Label*>&& labels) {
2952 jump_tables_.emplace_back(std::move(labels));
2953 JumpTable* table = &jump_tables_.back();
2954 DCHECK(!table->GetLabel()->IsBound());
2955 return table;
2956 }
2957
ReserveJumpTableSpace()2958 void Mips64Assembler::ReserveJumpTableSpace() {
2959 if (!jump_tables_.empty()) {
2960 for (JumpTable& table : jump_tables_) {
2961 Mips64Label* label = table.GetLabel();
2962 Bind(label);
2963
2964 // Bulk ensure capacity, as this may be large.
2965 size_t orig_size = buffer_.Size();
2966 size_t required_capacity = orig_size + table.GetSize();
2967 if (required_capacity > buffer_.Capacity()) {
2968 buffer_.ExtendCapacity(required_capacity);
2969 }
2970 #ifndef NDEBUG
2971 buffer_.has_ensured_capacity_ = true;
2972 #endif
2973
2974 // Fill the space with dummy data as the data is not final
2975 // until the branches have been promoted. And we shouldn't
2976 // be moving uninitialized data during branch promotion.
2977 for (size_t cnt = table.GetData().size(), i = 0; i < cnt; i++) {
2978 buffer_.Emit<uint32_t>(0x1abe1234u);
2979 }
2980
2981 #ifndef NDEBUG
2982 buffer_.has_ensured_capacity_ = false;
2983 #endif
2984 }
2985 }
2986 }
2987
EmitJumpTables()2988 void Mips64Assembler::EmitJumpTables() {
2989 if (!jump_tables_.empty()) {
2990 CHECK(!overwriting_);
2991 // Switch from appending instructions at the end of the buffer to overwriting
2992 // existing instructions (here, jump tables) in the buffer.
2993 overwriting_ = true;
2994
2995 for (JumpTable& table : jump_tables_) {
2996 Mips64Label* table_label = table.GetLabel();
2997 uint32_t start = GetLabelLocation(table_label);
2998 overwrite_location_ = start;
2999
3000 for (Mips64Label* target : table.GetData()) {
3001 CHECK_EQ(buffer_.Load<uint32_t>(overwrite_location_), 0x1abe1234u);
3002 // The table will contain target addresses relative to the table start.
3003 uint32_t offset = GetLabelLocation(target) - start;
3004 Emit(offset);
3005 }
3006 }
3007
3008 overwriting_ = false;
3009 }
3010 }
3011
EmitLiterals()3012 void Mips64Assembler::EmitLiterals() {
3013 if (!literals_.empty()) {
3014 for (Literal& literal : literals_) {
3015 Mips64Label* label = literal.GetLabel();
3016 Bind(label);
3017 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
3018 DCHECK_EQ(literal.GetSize(), 4u);
3019 for (size_t i = 0, size = literal.GetSize(); i != size; ++i) {
3020 buffer_.Emit<uint8_t>(literal.GetData()[i]);
3021 }
3022 }
3023 }
3024 if (!long_literals_.empty()) {
3025 // Reserve 4 bytes for potential alignment. If after the branch promotion the 64-bit
3026 // literals don't end up 8-byte-aligned, they will be moved down 4 bytes.
3027 Emit(0); // NOP.
3028 for (Literal& literal : long_literals_) {
3029 Mips64Label* label = literal.GetLabel();
3030 Bind(label);
3031 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
3032 DCHECK_EQ(literal.GetSize(), 8u);
3033 for (size_t i = 0, size = literal.GetSize(); i != size; ++i) {
3034 buffer_.Emit<uint8_t>(literal.GetData()[i]);
3035 }
3036 }
3037 }
3038 }
3039
PromoteBranches()3040 void Mips64Assembler::PromoteBranches() {
3041 // Promote short branches to long as necessary.
3042 bool changed;
3043 do {
3044 changed = false;
3045 for (auto& branch : branches_) {
3046 CHECK(branch.IsResolved());
3047 uint32_t delta = branch.PromoteIfNeeded();
3048 // If this branch has been promoted and needs to expand in size,
3049 // relocate all branches by the expansion size.
3050 if (delta) {
3051 changed = true;
3052 uint32_t expand_location = branch.GetLocation();
3053 for (auto& branch2 : branches_) {
3054 branch2.Relocate(expand_location, delta);
3055 }
3056 }
3057 }
3058 } while (changed);
3059
3060 // Account for branch expansion by resizing the code buffer
3061 // and moving the code in it to its final location.
3062 size_t branch_count = branches_.size();
3063 if (branch_count > 0) {
3064 // Resize.
3065 Branch& last_branch = branches_[branch_count - 1];
3066 uint32_t size_delta = last_branch.GetEndLocation() - last_branch.GetOldEndLocation();
3067 uint32_t old_size = buffer_.Size();
3068 buffer_.Resize(old_size + size_delta);
3069 // Move the code residing between branch placeholders.
3070 uint32_t end = old_size;
3071 for (size_t i = branch_count; i > 0; ) {
3072 Branch& branch = branches_[--i];
3073 uint32_t size = end - branch.GetOldEndLocation();
3074 buffer_.Move(branch.GetEndLocation(), branch.GetOldEndLocation(), size);
3075 end = branch.GetOldLocation();
3076 }
3077 }
3078
3079 // Align 64-bit literals by moving them down by 4 bytes if needed.
3080 // This will reduce the PC-relative distance, which should be safe for both near and far literals.
3081 if (!long_literals_.empty()) {
3082 uint32_t first_literal_location = GetLabelLocation(long_literals_.front().GetLabel());
3083 size_t lit_size = long_literals_.size() * sizeof(uint64_t);
3084 size_t buf_size = buffer_.Size();
3085 // 64-bit literals must be at the very end of the buffer.
3086 CHECK_EQ(first_literal_location + lit_size, buf_size);
3087 if (!IsAligned<sizeof(uint64_t)>(first_literal_location)) {
3088 buffer_.Move(first_literal_location - sizeof(uint32_t), first_literal_location, lit_size);
3089 // The 4 reserved bytes proved useless, reduce the buffer size.
3090 buffer_.Resize(buf_size - sizeof(uint32_t));
3091 // Reduce target addresses in literal and address loads by 4 bytes in order for correct
3092 // offsets from PC to be generated.
3093 for (auto& branch : branches_) {
3094 uint32_t target = branch.GetTarget();
3095 if (target >= first_literal_location) {
3096 branch.Resolve(target - sizeof(uint32_t));
3097 }
3098 }
3099 // If after this we ever call GetLabelLocation() to get the location of a 64-bit literal,
3100 // we need to adjust the location of the literal's label as well.
3101 for (Literal& literal : long_literals_) {
3102 // Bound label's position is negative, hence incrementing it instead of decrementing.
3103 literal.GetLabel()->position_ += sizeof(uint32_t);
3104 }
3105 }
3106 }
3107 }
3108
3109 // Note: make sure branch_info_[] and EmitBranch() are kept synchronized.
3110 const Mips64Assembler::Branch::BranchInfo Mips64Assembler::Branch::branch_info_[] = {
3111 // R6 short branches (can be promoted to long).
3112 { 1, 0, 1, Mips64Assembler::Branch::kOffset28, 2 }, // kUncondBranch
3113 { 2, 0, 1, Mips64Assembler::Branch::kOffset18, 2 }, // kCondBranch
3114 // Exception: kOffset23 for beqzc/bnezc
3115 { 1, 0, 1, Mips64Assembler::Branch::kOffset28, 2 }, // kCall
3116 // R6 short branches (can't be promoted to long), forbidden/delay slots filled manually.
3117 { 1, 0, 1, Mips64Assembler::Branch::kOffset28, 2 }, // kBareUncondBranch
3118 { 1, 0, 1, Mips64Assembler::Branch::kOffset18, 2 }, // kBareCondBranch
3119 // Exception: kOffset23 for beqzc/bnezc
3120 { 1, 0, 1, Mips64Assembler::Branch::kOffset28, 2 }, // kBareCall
3121 // R2 short branches (can't be promoted to long), delay slots filled manually.
3122 { 1, 0, 1, Mips64Assembler::Branch::kOffset18, 2 }, // kR2BareCondBranch
3123 // Near label.
3124 { 1, 0, 0, Mips64Assembler::Branch::kOffset21, 2 }, // kLabel
3125 // Near literals.
3126 { 1, 0, 0, Mips64Assembler::Branch::kOffset21, 2 }, // kLiteral
3127 { 1, 0, 0, Mips64Assembler::Branch::kOffset21, 2 }, // kLiteralUnsigned
3128 { 1, 0, 0, Mips64Assembler::Branch::kOffset21, 3 }, // kLiteralLong
3129 // Long branches.
3130 { 2, 0, 0, Mips64Assembler::Branch::kOffset32, 0 }, // kLongUncondBranch
3131 { 3, 1, 0, Mips64Assembler::Branch::kOffset32, 0 }, // kLongCondBranch
3132 { 2, 0, 0, Mips64Assembler::Branch::kOffset32, 0 }, // kLongCall
3133 // Far label.
3134 { 2, 0, 0, Mips64Assembler::Branch::kOffset32, 0 }, // kFarLabel
3135 // Far literals.
3136 { 2, 0, 0, Mips64Assembler::Branch::kOffset32, 0 }, // kFarLiteral
3137 { 2, 0, 0, Mips64Assembler::Branch::kOffset32, 0 }, // kFarLiteralUnsigned
3138 { 2, 0, 0, Mips64Assembler::Branch::kOffset32, 0 }, // kFarLiteralLong
3139 };
3140
3141 // Note: make sure branch_info_[] and EmitBranch() are kept synchronized.
EmitBranch(Mips64Assembler::Branch * branch)3142 void Mips64Assembler::EmitBranch(Mips64Assembler::Branch* branch) {
3143 CHECK(overwriting_);
3144 overwrite_location_ = branch->GetLocation();
3145 uint32_t offset = branch->GetOffset();
3146 BranchCondition condition = branch->GetCondition();
3147 GpuRegister lhs = branch->GetLeftRegister();
3148 GpuRegister rhs = branch->GetRightRegister();
3149 switch (branch->GetType()) {
3150 // Short branches.
3151 case Branch::kUncondBranch:
3152 CHECK_EQ(overwrite_location_, branch->GetOffsetLocation());
3153 Bc(offset);
3154 break;
3155 case Branch::kCondBranch:
3156 CHECK_EQ(overwrite_location_, branch->GetOffsetLocation());
3157 EmitBcondR6(condition, lhs, rhs, offset);
3158 Nop(); // TODO: improve by filling the forbidden/delay slot.
3159 break;
3160 case Branch::kCall:
3161 CHECK_EQ(overwrite_location_, branch->GetOffsetLocation());
3162 Balc(offset);
3163 break;
3164 case Branch::kBareUncondBranch:
3165 CHECK_EQ(overwrite_location_, branch->GetOffsetLocation());
3166 Bc(offset);
3167 break;
3168 case Branch::kBareCondBranch:
3169 CHECK_EQ(overwrite_location_, branch->GetOffsetLocation());
3170 EmitBcondR6(condition, lhs, rhs, offset);
3171 break;
3172 case Branch::kBareCall:
3173 CHECK_EQ(overwrite_location_, branch->GetOffsetLocation());
3174 Balc(offset);
3175 break;
3176 case Branch::kR2BareCondBranch:
3177 CHECK_EQ(overwrite_location_, branch->GetOffsetLocation());
3178 EmitBcondR2(condition, lhs, rhs, offset);
3179 break;
3180
3181 // Near label.
3182 case Branch::kLabel:
3183 CHECK_EQ(overwrite_location_, branch->GetOffsetLocation());
3184 Addiupc(lhs, offset);
3185 break;
3186 // Near literals.
3187 case Branch::kLiteral:
3188 CHECK_EQ(overwrite_location_, branch->GetOffsetLocation());
3189 Lwpc(lhs, offset);
3190 break;
3191 case Branch::kLiteralUnsigned:
3192 CHECK_EQ(overwrite_location_, branch->GetOffsetLocation());
3193 Lwupc(lhs, offset);
3194 break;
3195 case Branch::kLiteralLong:
3196 CHECK_EQ(overwrite_location_, branch->GetOffsetLocation());
3197 Ldpc(lhs, offset);
3198 break;
3199
3200 // Long branches.
3201 case Branch::kLongUncondBranch:
3202 offset += (offset & 0x8000) << 1; // Account for sign extension in jic.
3203 CHECK_EQ(overwrite_location_, branch->GetOffsetLocation());
3204 Auipc(AT, High16Bits(offset));
3205 Jic(AT, Low16Bits(offset));
3206 break;
3207 case Branch::kLongCondBranch:
3208 EmitBcondR6(Branch::OppositeCondition(condition), lhs, rhs, 2);
3209 offset += (offset & 0x8000) << 1; // Account for sign extension in jic.
3210 CHECK_EQ(overwrite_location_, branch->GetOffsetLocation());
3211 Auipc(AT, High16Bits(offset));
3212 Jic(AT, Low16Bits(offset));
3213 break;
3214 case Branch::kLongCall:
3215 offset += (offset & 0x8000) << 1; // Account for sign extension in jialc.
3216 CHECK_EQ(overwrite_location_, branch->GetOffsetLocation());
3217 Auipc(AT, High16Bits(offset));
3218 Jialc(AT, Low16Bits(offset));
3219 break;
3220
3221 // Far label.
3222 case Branch::kFarLabel:
3223 offset += (offset & 0x8000) << 1; // Account for sign extension in daddiu.
3224 CHECK_EQ(overwrite_location_, branch->GetOffsetLocation());
3225 Auipc(AT, High16Bits(offset));
3226 Daddiu(lhs, AT, Low16Bits(offset));
3227 break;
3228 // Far literals.
3229 case Branch::kFarLiteral:
3230 offset += (offset & 0x8000) << 1; // Account for sign extension in lw.
3231 CHECK_EQ(overwrite_location_, branch->GetOffsetLocation());
3232 Auipc(AT, High16Bits(offset));
3233 Lw(lhs, AT, Low16Bits(offset));
3234 break;
3235 case Branch::kFarLiteralUnsigned:
3236 offset += (offset & 0x8000) << 1; // Account for sign extension in lwu.
3237 CHECK_EQ(overwrite_location_, branch->GetOffsetLocation());
3238 Auipc(AT, High16Bits(offset));
3239 Lwu(lhs, AT, Low16Bits(offset));
3240 break;
3241 case Branch::kFarLiteralLong:
3242 offset += (offset & 0x8000) << 1; // Account for sign extension in ld.
3243 CHECK_EQ(overwrite_location_, branch->GetOffsetLocation());
3244 Auipc(AT, High16Bits(offset));
3245 Ld(lhs, AT, Low16Bits(offset));
3246 break;
3247 }
3248 CHECK_EQ(overwrite_location_, branch->GetEndLocation());
3249 CHECK_LT(branch->GetSize(), static_cast<uint32_t>(Branch::kMaxBranchSize));
3250 }
3251
Bc(Mips64Label * label,bool is_bare)3252 void Mips64Assembler::Bc(Mips64Label* label, bool is_bare) {
3253 Buncond(label, is_bare);
3254 }
3255
Balc(Mips64Label * label,bool is_bare)3256 void Mips64Assembler::Balc(Mips64Label* label, bool is_bare) {
3257 Call(label, is_bare);
3258 }
3259
Bltc(GpuRegister rs,GpuRegister rt,Mips64Label * label,bool is_bare)3260 void Mips64Assembler::Bltc(GpuRegister rs, GpuRegister rt, Mips64Label* label, bool is_bare) {
3261 Bcond(label, /* is_r6 */ true, is_bare, kCondLT, rs, rt);
3262 }
3263
Bltzc(GpuRegister rt,Mips64Label * label,bool is_bare)3264 void Mips64Assembler::Bltzc(GpuRegister rt, Mips64Label* label, bool is_bare) {
3265 Bcond(label, /* is_r6 */ true, is_bare, kCondLTZ, rt);
3266 }
3267
Bgtzc(GpuRegister rt,Mips64Label * label,bool is_bare)3268 void Mips64Assembler::Bgtzc(GpuRegister rt, Mips64Label* label, bool is_bare) {
3269 Bcond(label, /* is_r6 */ true, is_bare, kCondGTZ, rt);
3270 }
3271
Bgec(GpuRegister rs,GpuRegister rt,Mips64Label * label,bool is_bare)3272 void Mips64Assembler::Bgec(GpuRegister rs, GpuRegister rt, Mips64Label* label, bool is_bare) {
3273 Bcond(label, /* is_r6 */ true, is_bare, kCondGE, rs, rt);
3274 }
3275
Bgezc(GpuRegister rt,Mips64Label * label,bool is_bare)3276 void Mips64Assembler::Bgezc(GpuRegister rt, Mips64Label* label, bool is_bare) {
3277 Bcond(label, /* is_r6 */ true, is_bare, kCondGEZ, rt);
3278 }
3279
Blezc(GpuRegister rt,Mips64Label * label,bool is_bare)3280 void Mips64Assembler::Blezc(GpuRegister rt, Mips64Label* label, bool is_bare) {
3281 Bcond(label, /* is_r6 */ true, is_bare, kCondLEZ, rt);
3282 }
3283
Bltuc(GpuRegister rs,GpuRegister rt,Mips64Label * label,bool is_bare)3284 void Mips64Assembler::Bltuc(GpuRegister rs, GpuRegister rt, Mips64Label* label, bool is_bare) {
3285 Bcond(label, /* is_r6 */ true, is_bare, kCondLTU, rs, rt);
3286 }
3287
Bgeuc(GpuRegister rs,GpuRegister rt,Mips64Label * label,bool is_bare)3288 void Mips64Assembler::Bgeuc(GpuRegister rs, GpuRegister rt, Mips64Label* label, bool is_bare) {
3289 Bcond(label, /* is_r6 */ true, is_bare, kCondGEU, rs, rt);
3290 }
3291
Beqc(GpuRegister rs,GpuRegister rt,Mips64Label * label,bool is_bare)3292 void Mips64Assembler::Beqc(GpuRegister rs, GpuRegister rt, Mips64Label* label, bool is_bare) {
3293 Bcond(label, /* is_r6 */ true, is_bare, kCondEQ, rs, rt);
3294 }
3295
Bnec(GpuRegister rs,GpuRegister rt,Mips64Label * label,bool is_bare)3296 void Mips64Assembler::Bnec(GpuRegister rs, GpuRegister rt, Mips64Label* label, bool is_bare) {
3297 Bcond(label, /* is_r6 */ true, is_bare, kCondNE, rs, rt);
3298 }
3299
Beqzc(GpuRegister rs,Mips64Label * label,bool is_bare)3300 void Mips64Assembler::Beqzc(GpuRegister rs, Mips64Label* label, bool is_bare) {
3301 Bcond(label, /* is_r6 */ true, is_bare, kCondEQZ, rs);
3302 }
3303
Bnezc(GpuRegister rs,Mips64Label * label,bool is_bare)3304 void Mips64Assembler::Bnezc(GpuRegister rs, Mips64Label* label, bool is_bare) {
3305 Bcond(label, /* is_r6 */ true, is_bare, kCondNEZ, rs);
3306 }
3307
Bc1eqz(FpuRegister ft,Mips64Label * label,bool is_bare)3308 void Mips64Assembler::Bc1eqz(FpuRegister ft, Mips64Label* label, bool is_bare) {
3309 Bcond(label, /* is_r6 */ true, is_bare, kCondF, static_cast<GpuRegister>(ft), ZERO);
3310 }
3311
Bc1nez(FpuRegister ft,Mips64Label * label,bool is_bare)3312 void Mips64Assembler::Bc1nez(FpuRegister ft, Mips64Label* label, bool is_bare) {
3313 Bcond(label, /* is_r6 */ true, is_bare, kCondT, static_cast<GpuRegister>(ft), ZERO);
3314 }
3315
Bltz(GpuRegister rt,Mips64Label * label,bool is_bare)3316 void Mips64Assembler::Bltz(GpuRegister rt, Mips64Label* label, bool is_bare) {
3317 CHECK(is_bare);
3318 Bcond(label, /* is_r6 */ false, is_bare, kCondLTZ, rt);
3319 }
3320
Bgtz(GpuRegister rt,Mips64Label * label,bool is_bare)3321 void Mips64Assembler::Bgtz(GpuRegister rt, Mips64Label* label, bool is_bare) {
3322 CHECK(is_bare);
3323 Bcond(label, /* is_r6 */ false, is_bare, kCondGTZ, rt);
3324 }
3325
Bgez(GpuRegister rt,Mips64Label * label,bool is_bare)3326 void Mips64Assembler::Bgez(GpuRegister rt, Mips64Label* label, bool is_bare) {
3327 CHECK(is_bare);
3328 Bcond(label, /* is_r6 */ false, is_bare, kCondGEZ, rt);
3329 }
3330
Blez(GpuRegister rt,Mips64Label * label,bool is_bare)3331 void Mips64Assembler::Blez(GpuRegister rt, Mips64Label* label, bool is_bare) {
3332 CHECK(is_bare);
3333 Bcond(label, /* is_r6 */ false, is_bare, kCondLEZ, rt);
3334 }
3335
Beq(GpuRegister rs,GpuRegister rt,Mips64Label * label,bool is_bare)3336 void Mips64Assembler::Beq(GpuRegister rs, GpuRegister rt, Mips64Label* label, bool is_bare) {
3337 CHECK(is_bare);
3338 Bcond(label, /* is_r6 */ false, is_bare, kCondEQ, rs, rt);
3339 }
3340
Bne(GpuRegister rs,GpuRegister rt,Mips64Label * label,bool is_bare)3341 void Mips64Assembler::Bne(GpuRegister rs, GpuRegister rt, Mips64Label* label, bool is_bare) {
3342 CHECK(is_bare);
3343 Bcond(label, /* is_r6 */ false, is_bare, kCondNE, rs, rt);
3344 }
3345
Beqz(GpuRegister rs,Mips64Label * label,bool is_bare)3346 void Mips64Assembler::Beqz(GpuRegister rs, Mips64Label* label, bool is_bare) {
3347 CHECK(is_bare);
3348 Bcond(label, /* is_r6 */ false, is_bare, kCondEQZ, rs);
3349 }
3350
Bnez(GpuRegister rs,Mips64Label * label,bool is_bare)3351 void Mips64Assembler::Bnez(GpuRegister rs, Mips64Label* label, bool is_bare) {
3352 CHECK(is_bare);
3353 Bcond(label, /* is_r6 */ false, is_bare, kCondNEZ, rs);
3354 }
3355
AdjustBaseAndOffset(GpuRegister & base,int32_t & offset,bool is_doubleword)3356 void Mips64Assembler::AdjustBaseAndOffset(GpuRegister& base,
3357 int32_t& offset,
3358 bool is_doubleword) {
3359 // This method is used to adjust the base register and offset pair
3360 // for a load/store when the offset doesn't fit into int16_t.
3361 // It is assumed that `base + offset` is sufficiently aligned for memory
3362 // operands that are machine word in size or smaller. For doubleword-sized
3363 // operands it's assumed that `base` is a multiple of 8, while `offset`
3364 // may be a multiple of 4 (e.g. 4-byte-aligned long and double arguments
3365 // and spilled variables on the stack accessed relative to the stack
3366 // pointer register).
3367 // We preserve the "alignment" of `offset` by adjusting it by a multiple of 8.
3368 CHECK_NE(base, AT); // Must not overwrite the register `base` while loading `offset`.
3369
3370 bool doubleword_aligned = IsAligned<kMips64DoublewordSize>(offset);
3371 bool two_accesses = is_doubleword && !doubleword_aligned;
3372
3373 // IsInt<16> must be passed a signed value, hence the static cast below.
3374 if (IsInt<16>(offset) &&
3375 (!two_accesses || IsInt<16>(static_cast<int32_t>(offset + kMips64WordSize)))) {
3376 // Nothing to do: `offset` (and, if needed, `offset + 4`) fits into int16_t.
3377 return;
3378 }
3379
3380 // Remember the "(mis)alignment" of `offset`, it will be checked at the end.
3381 uint32_t misalignment = offset & (kMips64DoublewordSize - 1);
3382
3383 // First, see if `offset` can be represented as a sum of two 16-bit signed
3384 // offsets. This can save an instruction.
3385 // To simplify matters, only do this for a symmetric range of offsets from
3386 // about -64KB to about +64KB, allowing further addition of 4 when accessing
3387 // 64-bit variables with two 32-bit accesses.
3388 constexpr int32_t kMinOffsetForSimpleAdjustment = 0x7ff8; // Max int16_t that's a multiple of 8.
3389 constexpr int32_t kMaxOffsetForSimpleAdjustment = 2 * kMinOffsetForSimpleAdjustment;
3390
3391 if (0 <= offset && offset <= kMaxOffsetForSimpleAdjustment) {
3392 Daddiu(AT, base, kMinOffsetForSimpleAdjustment);
3393 offset -= kMinOffsetForSimpleAdjustment;
3394 } else if (-kMaxOffsetForSimpleAdjustment <= offset && offset < 0) {
3395 Daddiu(AT, base, -kMinOffsetForSimpleAdjustment);
3396 offset += kMinOffsetForSimpleAdjustment;
3397 } else {
3398 // In more complex cases take advantage of the daui instruction, e.g.:
3399 // daui AT, base, offset_high
3400 // [dahi AT, 1] // When `offset` is close to +2GB.
3401 // lw reg_lo, offset_low(AT)
3402 // [lw reg_hi, (offset_low+4)(AT)] // If misaligned 64-bit load.
3403 // or when offset_low+4 overflows int16_t:
3404 // daui AT, base, offset_high
3405 // daddiu AT, AT, 8
3406 // lw reg_lo, (offset_low-8)(AT)
3407 // lw reg_hi, (offset_low-4)(AT)
3408 int16_t offset_low = Low16Bits(offset);
3409 int32_t offset_low32 = offset_low;
3410 int16_t offset_high = High16Bits(offset);
3411 bool increment_hi16 = offset_low < 0;
3412 bool overflow_hi16 = false;
3413
3414 if (increment_hi16) {
3415 offset_high++;
3416 overflow_hi16 = (offset_high == -32768);
3417 }
3418 Daui(AT, base, offset_high);
3419
3420 if (overflow_hi16) {
3421 Dahi(AT, 1);
3422 }
3423
3424 if (two_accesses && !IsInt<16>(static_cast<int32_t>(offset_low32 + kMips64WordSize))) {
3425 // Avoid overflow in the 16-bit offset of the load/store instruction when adding 4.
3426 Daddiu(AT, AT, kMips64DoublewordSize);
3427 offset_low32 -= kMips64DoublewordSize;
3428 }
3429
3430 offset = offset_low32;
3431 }
3432 base = AT;
3433
3434 CHECK(IsInt<16>(offset));
3435 if (two_accesses) {
3436 CHECK(IsInt<16>(static_cast<int32_t>(offset + kMips64WordSize)));
3437 }
3438 CHECK_EQ(misalignment, offset & (kMips64DoublewordSize - 1));
3439 }
3440
AdjustBaseOffsetAndElementSizeShift(GpuRegister & base,int32_t & offset,int & element_size_shift)3441 void Mips64Assembler::AdjustBaseOffsetAndElementSizeShift(GpuRegister& base,
3442 int32_t& offset,
3443 int& element_size_shift) {
3444 // This method is used to adjust the base register, offset and element_size_shift
3445 // for a vector load/store when the offset doesn't fit into allowed number of bits.
3446 // MSA ld.df and st.df instructions take signed offsets as arguments, but maximum
3447 // offset is dependant on the size of the data format df (10-bit offsets for ld.b,
3448 // 11-bit for ld.h, 12-bit for ld.w and 13-bit for ld.d).
3449 // If element_size_shift is non-negative at entry, it won't be changed, but offset
3450 // will be checked for appropriate alignment. If negative at entry, it will be
3451 // adjusted based on offset for maximum fit.
3452 // It's assumed that `base` is a multiple of 8.
3453
3454 CHECK_NE(base, AT); // Must not overwrite the register `base` while loading `offset`.
3455
3456 if (element_size_shift >= 0) {
3457 CHECK_LE(element_size_shift, TIMES_8);
3458 CHECK_GE(JAVASTYLE_CTZ(offset), element_size_shift);
3459 } else if (IsAligned<kMips64DoublewordSize>(offset)) {
3460 element_size_shift = TIMES_8;
3461 } else if (IsAligned<kMips64WordSize>(offset)) {
3462 element_size_shift = TIMES_4;
3463 } else if (IsAligned<kMips64HalfwordSize>(offset)) {
3464 element_size_shift = TIMES_2;
3465 } else {
3466 element_size_shift = TIMES_1;
3467 }
3468
3469 const int low_len = 10 + element_size_shift; // How many low bits of `offset` ld.df/st.df
3470 // will take.
3471 int16_t low = offset & ((1 << low_len) - 1); // Isolate these bits.
3472 low -= (low & (1 << (low_len - 1))) << 1; // Sign-extend these bits.
3473 if (low == offset) {
3474 return; // `offset` fits into ld.df/st.df.
3475 }
3476
3477 // First, see if `offset` can be represented as a sum of two signed offsets.
3478 // This can save an instruction.
3479
3480 // Max int16_t that's a multiple of element size.
3481 const int32_t kMaxDeltaForSimpleAdjustment = 0x8000 - (1 << element_size_shift);
3482 // Max ld.df/st.df offset that's a multiple of element size.
3483 const int32_t kMaxLoadStoreOffset = 0x1ff << element_size_shift;
3484 const int32_t kMaxOffsetForSimpleAdjustment = kMaxDeltaForSimpleAdjustment + kMaxLoadStoreOffset;
3485
3486 if (IsInt<16>(offset)) {
3487 Daddiu(AT, base, offset);
3488 offset = 0;
3489 } else if (0 <= offset && offset <= kMaxOffsetForSimpleAdjustment) {
3490 Daddiu(AT, base, kMaxDeltaForSimpleAdjustment);
3491 offset -= kMaxDeltaForSimpleAdjustment;
3492 } else if (-kMaxOffsetForSimpleAdjustment <= offset && offset < 0) {
3493 Daddiu(AT, base, -kMaxDeltaForSimpleAdjustment);
3494 offset += kMaxDeltaForSimpleAdjustment;
3495 } else {
3496 // Let's treat `offset` as 64-bit to simplify handling of sign
3497 // extensions in the instructions that supply its smaller signed parts.
3498 //
3499 // 16-bit or smaller parts of `offset`:
3500 // |63 top 48|47 hi 32|31 upper 16|15 mid 13-10|12-9 low 0|
3501 //
3502 // Instructions that supply each part as a signed integer addend:
3503 // |dati |dahi |daui |daddiu |ld.df/st.df |
3504 //
3505 // `top` is always 0, so dati isn't used.
3506 // `hi` is 1 when `offset` is close to +2GB and 0 otherwise.
3507 uint64_t tmp = static_cast<uint64_t>(offset) - low; // Exclude `low` from the rest of `offset`
3508 // (accounts for sign of `low`).
3509 tmp += (tmp & (UINT64_C(1) << 15)) << 1; // Account for sign extension in daddiu.
3510 tmp += (tmp & (UINT64_C(1) << 31)) << 1; // Account for sign extension in daui.
3511 int16_t mid = Low16Bits(tmp);
3512 int16_t upper = High16Bits(tmp);
3513 int16_t hi = Low16Bits(High32Bits(tmp));
3514 Daui(AT, base, upper);
3515 if (hi != 0) {
3516 CHECK_EQ(hi, 1);
3517 Dahi(AT, hi);
3518 }
3519 if (mid != 0) {
3520 Daddiu(AT, AT, mid);
3521 }
3522 offset = low;
3523 }
3524 base = AT;
3525 CHECK_GE(JAVASTYLE_CTZ(offset), element_size_shift);
3526 CHECK(IsInt<10>(offset >> element_size_shift));
3527 }
3528
LoadFromOffset(LoadOperandType type,GpuRegister reg,GpuRegister base,int32_t offset)3529 void Mips64Assembler::LoadFromOffset(LoadOperandType type,
3530 GpuRegister reg,
3531 GpuRegister base,
3532 int32_t offset) {
3533 LoadFromOffset<>(type, reg, base, offset);
3534 }
3535
LoadFpuFromOffset(LoadOperandType type,FpuRegister reg,GpuRegister base,int32_t offset)3536 void Mips64Assembler::LoadFpuFromOffset(LoadOperandType type,
3537 FpuRegister reg,
3538 GpuRegister base,
3539 int32_t offset) {
3540 LoadFpuFromOffset<>(type, reg, base, offset);
3541 }
3542
EmitLoad(ManagedRegister m_dst,GpuRegister src_register,int32_t src_offset,size_t size)3543 void Mips64Assembler::EmitLoad(ManagedRegister m_dst, GpuRegister src_register, int32_t src_offset,
3544 size_t size) {
3545 Mips64ManagedRegister dst = m_dst.AsMips64();
3546 if (dst.IsNoRegister()) {
3547 CHECK_EQ(0u, size) << dst;
3548 } else if (dst.IsGpuRegister()) {
3549 if (size == 4) {
3550 LoadFromOffset(kLoadWord, dst.AsGpuRegister(), src_register, src_offset);
3551 } else if (size == 8) {
3552 CHECK_EQ(8u, size) << dst;
3553 LoadFromOffset(kLoadDoubleword, dst.AsGpuRegister(), src_register, src_offset);
3554 } else {
3555 UNIMPLEMENTED(FATAL) << "We only support Load() of size 4 and 8";
3556 }
3557 } else if (dst.IsFpuRegister()) {
3558 if (size == 4) {
3559 CHECK_EQ(4u, size) << dst;
3560 LoadFpuFromOffset(kLoadWord, dst.AsFpuRegister(), src_register, src_offset);
3561 } else if (size == 8) {
3562 CHECK_EQ(8u, size) << dst;
3563 LoadFpuFromOffset(kLoadDoubleword, dst.AsFpuRegister(), src_register, src_offset);
3564 } else {
3565 UNIMPLEMENTED(FATAL) << "We only support Load() of size 4 and 8";
3566 }
3567 }
3568 }
3569
StoreToOffset(StoreOperandType type,GpuRegister reg,GpuRegister base,int32_t offset)3570 void Mips64Assembler::StoreToOffset(StoreOperandType type,
3571 GpuRegister reg,
3572 GpuRegister base,
3573 int32_t offset) {
3574 StoreToOffset<>(type, reg, base, offset);
3575 }
3576
StoreFpuToOffset(StoreOperandType type,FpuRegister reg,GpuRegister base,int32_t offset)3577 void Mips64Assembler::StoreFpuToOffset(StoreOperandType type,
3578 FpuRegister reg,
3579 GpuRegister base,
3580 int32_t offset) {
3581 StoreFpuToOffset<>(type, reg, base, offset);
3582 }
3583
DWARFReg(GpuRegister reg)3584 static dwarf::Reg DWARFReg(GpuRegister reg) {
3585 return dwarf::Reg::Mips64Core(static_cast<int>(reg));
3586 }
3587
3588 constexpr size_t kFramePointerSize = 8;
3589
BuildFrame(size_t frame_size,ManagedRegister method_reg,ArrayRef<const ManagedRegister> callee_save_regs,const ManagedRegisterEntrySpills & entry_spills)3590 void Mips64Assembler::BuildFrame(size_t frame_size,
3591 ManagedRegister method_reg,
3592 ArrayRef<const ManagedRegister> callee_save_regs,
3593 const ManagedRegisterEntrySpills& entry_spills) {
3594 CHECK_ALIGNED(frame_size, kStackAlignment);
3595 DCHECK(!overwriting_);
3596
3597 // Increase frame to required size.
3598 IncreaseFrameSize(frame_size);
3599
3600 // Push callee saves and return address
3601 int stack_offset = frame_size - kFramePointerSize;
3602 StoreToOffset(kStoreDoubleword, RA, SP, stack_offset);
3603 cfi_.RelOffset(DWARFReg(RA), stack_offset);
3604 for (int i = callee_save_regs.size() - 1; i >= 0; --i) {
3605 stack_offset -= kFramePointerSize;
3606 GpuRegister reg = callee_save_regs[i].AsMips64().AsGpuRegister();
3607 StoreToOffset(kStoreDoubleword, reg, SP, stack_offset);
3608 cfi_.RelOffset(DWARFReg(reg), stack_offset);
3609 }
3610
3611 // Write out Method*.
3612 StoreToOffset(kStoreDoubleword, method_reg.AsMips64().AsGpuRegister(), SP, 0);
3613
3614 // Write out entry spills.
3615 int32_t offset = frame_size + kFramePointerSize;
3616 for (size_t i = 0; i < entry_spills.size(); ++i) {
3617 Mips64ManagedRegister reg = entry_spills[i].AsMips64();
3618 ManagedRegisterSpill spill = entry_spills.at(i);
3619 int32_t size = spill.getSize();
3620 if (reg.IsNoRegister()) {
3621 // only increment stack offset.
3622 offset += size;
3623 } else if (reg.IsFpuRegister()) {
3624 StoreFpuToOffset((size == 4) ? kStoreWord : kStoreDoubleword,
3625 reg.AsFpuRegister(), SP, offset);
3626 offset += size;
3627 } else if (reg.IsGpuRegister()) {
3628 StoreToOffset((size == 4) ? kStoreWord : kStoreDoubleword,
3629 reg.AsGpuRegister(), SP, offset);
3630 offset += size;
3631 }
3632 }
3633 }
3634
RemoveFrame(size_t frame_size,ArrayRef<const ManagedRegister> callee_save_regs,bool may_suspend ATTRIBUTE_UNUSED)3635 void Mips64Assembler::RemoveFrame(size_t frame_size,
3636 ArrayRef<const ManagedRegister> callee_save_regs,
3637 bool may_suspend ATTRIBUTE_UNUSED) {
3638 CHECK_ALIGNED(frame_size, kStackAlignment);
3639 DCHECK(!overwriting_);
3640 cfi_.RememberState();
3641
3642 // Pop callee saves and return address
3643 int stack_offset = frame_size - (callee_save_regs.size() * kFramePointerSize) - kFramePointerSize;
3644 for (size_t i = 0; i < callee_save_regs.size(); ++i) {
3645 GpuRegister reg = callee_save_regs[i].AsMips64().AsGpuRegister();
3646 LoadFromOffset(kLoadDoubleword, reg, SP, stack_offset);
3647 cfi_.Restore(DWARFReg(reg));
3648 stack_offset += kFramePointerSize;
3649 }
3650 LoadFromOffset(kLoadDoubleword, RA, SP, stack_offset);
3651 cfi_.Restore(DWARFReg(RA));
3652
3653 // Decrease frame to required size.
3654 DecreaseFrameSize(frame_size);
3655
3656 // Then jump to the return address.
3657 Jr(RA);
3658 Nop();
3659
3660 // The CFI should be restored for any code that follows the exit block.
3661 cfi_.RestoreState();
3662 cfi_.DefCFAOffset(frame_size);
3663 }
3664
IncreaseFrameSize(size_t adjust)3665 void Mips64Assembler::IncreaseFrameSize(size_t adjust) {
3666 CHECK_ALIGNED(adjust, kFramePointerSize);
3667 DCHECK(!overwriting_);
3668 Daddiu64(SP, SP, static_cast<int32_t>(-adjust));
3669 cfi_.AdjustCFAOffset(adjust);
3670 }
3671
DecreaseFrameSize(size_t adjust)3672 void Mips64Assembler::DecreaseFrameSize(size_t adjust) {
3673 CHECK_ALIGNED(adjust, kFramePointerSize);
3674 DCHECK(!overwriting_);
3675 Daddiu64(SP, SP, static_cast<int32_t>(adjust));
3676 cfi_.AdjustCFAOffset(-adjust);
3677 }
3678
Store(FrameOffset dest,ManagedRegister msrc,size_t size)3679 void Mips64Assembler::Store(FrameOffset dest, ManagedRegister msrc, size_t size) {
3680 Mips64ManagedRegister src = msrc.AsMips64();
3681 if (src.IsNoRegister()) {
3682 CHECK_EQ(0u, size);
3683 } else if (src.IsGpuRegister()) {
3684 CHECK(size == 4 || size == 8) << size;
3685 if (size == 8) {
3686 StoreToOffset(kStoreDoubleword, src.AsGpuRegister(), SP, dest.Int32Value());
3687 } else if (size == 4) {
3688 StoreToOffset(kStoreWord, src.AsGpuRegister(), SP, dest.Int32Value());
3689 } else {
3690 UNIMPLEMENTED(FATAL) << "We only support Store() of size 4 and 8";
3691 }
3692 } else if (src.IsFpuRegister()) {
3693 CHECK(size == 4 || size == 8) << size;
3694 if (size == 8) {
3695 StoreFpuToOffset(kStoreDoubleword, src.AsFpuRegister(), SP, dest.Int32Value());
3696 } else if (size == 4) {
3697 StoreFpuToOffset(kStoreWord, src.AsFpuRegister(), SP, dest.Int32Value());
3698 } else {
3699 UNIMPLEMENTED(FATAL) << "We only support Store() of size 4 and 8";
3700 }
3701 }
3702 }
3703
StoreRef(FrameOffset dest,ManagedRegister msrc)3704 void Mips64Assembler::StoreRef(FrameOffset dest, ManagedRegister msrc) {
3705 Mips64ManagedRegister src = msrc.AsMips64();
3706 CHECK(src.IsGpuRegister());
3707 StoreToOffset(kStoreWord, src.AsGpuRegister(), SP, dest.Int32Value());
3708 }
3709
StoreRawPtr(FrameOffset dest,ManagedRegister msrc)3710 void Mips64Assembler::StoreRawPtr(FrameOffset dest, ManagedRegister msrc) {
3711 Mips64ManagedRegister src = msrc.AsMips64();
3712 CHECK(src.IsGpuRegister());
3713 StoreToOffset(kStoreDoubleword, src.AsGpuRegister(), SP, dest.Int32Value());
3714 }
3715
StoreImmediateToFrame(FrameOffset dest,uint32_t imm,ManagedRegister mscratch)3716 void Mips64Assembler::StoreImmediateToFrame(FrameOffset dest, uint32_t imm,
3717 ManagedRegister mscratch) {
3718 Mips64ManagedRegister scratch = mscratch.AsMips64();
3719 CHECK(scratch.IsGpuRegister()) << scratch;
3720 LoadConst32(scratch.AsGpuRegister(), imm);
3721 StoreToOffset(kStoreWord, scratch.AsGpuRegister(), SP, dest.Int32Value());
3722 }
3723
StoreStackOffsetToThread(ThreadOffset64 thr_offs,FrameOffset fr_offs,ManagedRegister mscratch)3724 void Mips64Assembler::StoreStackOffsetToThread(ThreadOffset64 thr_offs,
3725 FrameOffset fr_offs,
3726 ManagedRegister mscratch) {
3727 Mips64ManagedRegister scratch = mscratch.AsMips64();
3728 CHECK(scratch.IsGpuRegister()) << scratch;
3729 Daddiu64(scratch.AsGpuRegister(), SP, fr_offs.Int32Value());
3730 StoreToOffset(kStoreDoubleword, scratch.AsGpuRegister(), S1, thr_offs.Int32Value());
3731 }
3732
StoreStackPointerToThread(ThreadOffset64 thr_offs)3733 void Mips64Assembler::StoreStackPointerToThread(ThreadOffset64 thr_offs) {
3734 StoreToOffset(kStoreDoubleword, SP, S1, thr_offs.Int32Value());
3735 }
3736
StoreSpanning(FrameOffset dest,ManagedRegister msrc,FrameOffset in_off,ManagedRegister mscratch)3737 void Mips64Assembler::StoreSpanning(FrameOffset dest, ManagedRegister msrc,
3738 FrameOffset in_off, ManagedRegister mscratch) {
3739 Mips64ManagedRegister src = msrc.AsMips64();
3740 Mips64ManagedRegister scratch = mscratch.AsMips64();
3741 StoreToOffset(kStoreDoubleword, src.AsGpuRegister(), SP, dest.Int32Value());
3742 LoadFromOffset(kLoadDoubleword, scratch.AsGpuRegister(), SP, in_off.Int32Value());
3743 StoreToOffset(kStoreDoubleword, scratch.AsGpuRegister(), SP, dest.Int32Value() + 8);
3744 }
3745
Load(ManagedRegister mdest,FrameOffset src,size_t size)3746 void Mips64Assembler::Load(ManagedRegister mdest, FrameOffset src, size_t size) {
3747 return EmitLoad(mdest, SP, src.Int32Value(), size);
3748 }
3749
LoadFromThread(ManagedRegister mdest,ThreadOffset64 src,size_t size)3750 void Mips64Assembler::LoadFromThread(ManagedRegister mdest, ThreadOffset64 src, size_t size) {
3751 return EmitLoad(mdest, S1, src.Int32Value(), size);
3752 }
3753
LoadRef(ManagedRegister mdest,FrameOffset src)3754 void Mips64Assembler::LoadRef(ManagedRegister mdest, FrameOffset src) {
3755 Mips64ManagedRegister dest = mdest.AsMips64();
3756 CHECK(dest.IsGpuRegister());
3757 LoadFromOffset(kLoadUnsignedWord, dest.AsGpuRegister(), SP, src.Int32Value());
3758 }
3759
LoadRef(ManagedRegister mdest,ManagedRegister base,MemberOffset offs,bool unpoison_reference)3760 void Mips64Assembler::LoadRef(ManagedRegister mdest, ManagedRegister base, MemberOffset offs,
3761 bool unpoison_reference) {
3762 Mips64ManagedRegister dest = mdest.AsMips64();
3763 CHECK(dest.IsGpuRegister() && base.AsMips64().IsGpuRegister());
3764 LoadFromOffset(kLoadUnsignedWord, dest.AsGpuRegister(),
3765 base.AsMips64().AsGpuRegister(), offs.Int32Value());
3766 if (unpoison_reference) {
3767 MaybeUnpoisonHeapReference(dest.AsGpuRegister());
3768 }
3769 }
3770
LoadRawPtr(ManagedRegister mdest,ManagedRegister base,Offset offs)3771 void Mips64Assembler::LoadRawPtr(ManagedRegister mdest, ManagedRegister base,
3772 Offset offs) {
3773 Mips64ManagedRegister dest = mdest.AsMips64();
3774 CHECK(dest.IsGpuRegister() && base.AsMips64().IsGpuRegister());
3775 LoadFromOffset(kLoadDoubleword, dest.AsGpuRegister(),
3776 base.AsMips64().AsGpuRegister(), offs.Int32Value());
3777 }
3778
LoadRawPtrFromThread(ManagedRegister mdest,ThreadOffset64 offs)3779 void Mips64Assembler::LoadRawPtrFromThread(ManagedRegister mdest, ThreadOffset64 offs) {
3780 Mips64ManagedRegister dest = mdest.AsMips64();
3781 CHECK(dest.IsGpuRegister());
3782 LoadFromOffset(kLoadDoubleword, dest.AsGpuRegister(), S1, offs.Int32Value());
3783 }
3784
SignExtend(ManagedRegister mreg ATTRIBUTE_UNUSED,size_t size ATTRIBUTE_UNUSED)3785 void Mips64Assembler::SignExtend(ManagedRegister mreg ATTRIBUTE_UNUSED,
3786 size_t size ATTRIBUTE_UNUSED) {
3787 UNIMPLEMENTED(FATAL) << "No sign extension necessary for MIPS64";
3788 }
3789
ZeroExtend(ManagedRegister mreg ATTRIBUTE_UNUSED,size_t size ATTRIBUTE_UNUSED)3790 void Mips64Assembler::ZeroExtend(ManagedRegister mreg ATTRIBUTE_UNUSED,
3791 size_t size ATTRIBUTE_UNUSED) {
3792 UNIMPLEMENTED(FATAL) << "No zero extension necessary for MIPS64";
3793 }
3794
Move(ManagedRegister mdest,ManagedRegister msrc,size_t size)3795 void Mips64Assembler::Move(ManagedRegister mdest, ManagedRegister msrc, size_t size) {
3796 Mips64ManagedRegister dest = mdest.AsMips64();
3797 Mips64ManagedRegister src = msrc.AsMips64();
3798 if (!dest.Equals(src)) {
3799 if (dest.IsGpuRegister()) {
3800 CHECK(src.IsGpuRegister()) << src;
3801 Move(dest.AsGpuRegister(), src.AsGpuRegister());
3802 } else if (dest.IsFpuRegister()) {
3803 CHECK(src.IsFpuRegister()) << src;
3804 if (size == 4) {
3805 MovS(dest.AsFpuRegister(), src.AsFpuRegister());
3806 } else if (size == 8) {
3807 MovD(dest.AsFpuRegister(), src.AsFpuRegister());
3808 } else {
3809 UNIMPLEMENTED(FATAL) << "We only support Copy() of size 4 and 8";
3810 }
3811 }
3812 }
3813 }
3814
CopyRef(FrameOffset dest,FrameOffset src,ManagedRegister mscratch)3815 void Mips64Assembler::CopyRef(FrameOffset dest, FrameOffset src,
3816 ManagedRegister mscratch) {
3817 Mips64ManagedRegister scratch = mscratch.AsMips64();
3818 CHECK(scratch.IsGpuRegister()) << scratch;
3819 LoadFromOffset(kLoadWord, scratch.AsGpuRegister(), SP, src.Int32Value());
3820 StoreToOffset(kStoreWord, scratch.AsGpuRegister(), SP, dest.Int32Value());
3821 }
3822
CopyRawPtrFromThread(FrameOffset fr_offs,ThreadOffset64 thr_offs,ManagedRegister mscratch)3823 void Mips64Assembler::CopyRawPtrFromThread(FrameOffset fr_offs,
3824 ThreadOffset64 thr_offs,
3825 ManagedRegister mscratch) {
3826 Mips64ManagedRegister scratch = mscratch.AsMips64();
3827 CHECK(scratch.IsGpuRegister()) << scratch;
3828 LoadFromOffset(kLoadDoubleword, scratch.AsGpuRegister(), S1, thr_offs.Int32Value());
3829 StoreToOffset(kStoreDoubleword, scratch.AsGpuRegister(), SP, fr_offs.Int32Value());
3830 }
3831
CopyRawPtrToThread(ThreadOffset64 thr_offs,FrameOffset fr_offs,ManagedRegister mscratch)3832 void Mips64Assembler::CopyRawPtrToThread(ThreadOffset64 thr_offs,
3833 FrameOffset fr_offs,
3834 ManagedRegister mscratch) {
3835 Mips64ManagedRegister scratch = mscratch.AsMips64();
3836 CHECK(scratch.IsGpuRegister()) << scratch;
3837 LoadFromOffset(kLoadDoubleword, scratch.AsGpuRegister(),
3838 SP, fr_offs.Int32Value());
3839 StoreToOffset(kStoreDoubleword, scratch.AsGpuRegister(),
3840 S1, thr_offs.Int32Value());
3841 }
3842
Copy(FrameOffset dest,FrameOffset src,ManagedRegister mscratch,size_t size)3843 void Mips64Assembler::Copy(FrameOffset dest, FrameOffset src,
3844 ManagedRegister mscratch, size_t size) {
3845 Mips64ManagedRegister scratch = mscratch.AsMips64();
3846 CHECK(scratch.IsGpuRegister()) << scratch;
3847 CHECK(size == 4 || size == 8) << size;
3848 if (size == 4) {
3849 LoadFromOffset(kLoadWord, scratch.AsGpuRegister(), SP, src.Int32Value());
3850 StoreToOffset(kStoreDoubleword, scratch.AsGpuRegister(), SP, dest.Int32Value());
3851 } else if (size == 8) {
3852 LoadFromOffset(kLoadDoubleword, scratch.AsGpuRegister(), SP, src.Int32Value());
3853 StoreToOffset(kStoreDoubleword, scratch.AsGpuRegister(), SP, dest.Int32Value());
3854 } else {
3855 UNIMPLEMENTED(FATAL) << "We only support Copy() of size 4 and 8";
3856 }
3857 }
3858
Copy(FrameOffset dest,ManagedRegister src_base,Offset src_offset,ManagedRegister mscratch,size_t size)3859 void Mips64Assembler::Copy(FrameOffset dest, ManagedRegister src_base, Offset src_offset,
3860 ManagedRegister mscratch, size_t size) {
3861 GpuRegister scratch = mscratch.AsMips64().AsGpuRegister();
3862 CHECK(size == 4 || size == 8) << size;
3863 if (size == 4) {
3864 LoadFromOffset(kLoadWord, scratch, src_base.AsMips64().AsGpuRegister(),
3865 src_offset.Int32Value());
3866 StoreToOffset(kStoreDoubleword, scratch, SP, dest.Int32Value());
3867 } else if (size == 8) {
3868 LoadFromOffset(kLoadDoubleword, scratch, src_base.AsMips64().AsGpuRegister(),
3869 src_offset.Int32Value());
3870 StoreToOffset(kStoreDoubleword, scratch, SP, dest.Int32Value());
3871 } else {
3872 UNIMPLEMENTED(FATAL) << "We only support Copy() of size 4 and 8";
3873 }
3874 }
3875
Copy(ManagedRegister dest_base,Offset dest_offset,FrameOffset src,ManagedRegister mscratch,size_t size)3876 void Mips64Assembler::Copy(ManagedRegister dest_base, Offset dest_offset, FrameOffset src,
3877 ManagedRegister mscratch, size_t size) {
3878 GpuRegister scratch = mscratch.AsMips64().AsGpuRegister();
3879 CHECK(size == 4 || size == 8) << size;
3880 if (size == 4) {
3881 LoadFromOffset(kLoadWord, scratch, SP, src.Int32Value());
3882 StoreToOffset(kStoreDoubleword, scratch, dest_base.AsMips64().AsGpuRegister(),
3883 dest_offset.Int32Value());
3884 } else if (size == 8) {
3885 LoadFromOffset(kLoadDoubleword, scratch, SP, src.Int32Value());
3886 StoreToOffset(kStoreDoubleword, scratch, dest_base.AsMips64().AsGpuRegister(),
3887 dest_offset.Int32Value());
3888 } else {
3889 UNIMPLEMENTED(FATAL) << "We only support Copy() of size 4 and 8";
3890 }
3891 }
3892
Copy(FrameOffset dest ATTRIBUTE_UNUSED,FrameOffset src_base ATTRIBUTE_UNUSED,Offset src_offset ATTRIBUTE_UNUSED,ManagedRegister mscratch ATTRIBUTE_UNUSED,size_t size ATTRIBUTE_UNUSED)3893 void Mips64Assembler::Copy(FrameOffset dest ATTRIBUTE_UNUSED,
3894 FrameOffset src_base ATTRIBUTE_UNUSED,
3895 Offset src_offset ATTRIBUTE_UNUSED,
3896 ManagedRegister mscratch ATTRIBUTE_UNUSED,
3897 size_t size ATTRIBUTE_UNUSED) {
3898 UNIMPLEMENTED(FATAL) << "No MIPS64 implementation";
3899 }
3900
Copy(ManagedRegister dest,Offset dest_offset,ManagedRegister src,Offset src_offset,ManagedRegister mscratch,size_t size)3901 void Mips64Assembler::Copy(ManagedRegister dest, Offset dest_offset,
3902 ManagedRegister src, Offset src_offset,
3903 ManagedRegister mscratch, size_t size) {
3904 GpuRegister scratch = mscratch.AsMips64().AsGpuRegister();
3905 CHECK(size == 4 || size == 8) << size;
3906 if (size == 4) {
3907 LoadFromOffset(kLoadWord, scratch, src.AsMips64().AsGpuRegister(), src_offset.Int32Value());
3908 StoreToOffset(kStoreDoubleword, scratch, dest.AsMips64().AsGpuRegister(), dest_offset.Int32Value());
3909 } else if (size == 8) {
3910 LoadFromOffset(kLoadDoubleword, scratch, src.AsMips64().AsGpuRegister(),
3911 src_offset.Int32Value());
3912 StoreToOffset(kStoreDoubleword, scratch, dest.AsMips64().AsGpuRegister(),
3913 dest_offset.Int32Value());
3914 } else {
3915 UNIMPLEMENTED(FATAL) << "We only support Copy() of size 4 and 8";
3916 }
3917 }
3918
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)3919 void Mips64Assembler::Copy(FrameOffset dest ATTRIBUTE_UNUSED,
3920 Offset dest_offset ATTRIBUTE_UNUSED,
3921 FrameOffset src ATTRIBUTE_UNUSED,
3922 Offset src_offset ATTRIBUTE_UNUSED,
3923 ManagedRegister mscratch ATTRIBUTE_UNUSED,
3924 size_t size ATTRIBUTE_UNUSED) {
3925 UNIMPLEMENTED(FATAL) << "No MIPS64 implementation";
3926 }
3927
MemoryBarrier(ManagedRegister mreg ATTRIBUTE_UNUSED)3928 void Mips64Assembler::MemoryBarrier(ManagedRegister mreg ATTRIBUTE_UNUSED) {
3929 // TODO: sync?
3930 UNIMPLEMENTED(FATAL) << "No MIPS64 implementation";
3931 }
3932
CreateHandleScopeEntry(ManagedRegister mout_reg,FrameOffset handle_scope_offset,ManagedRegister min_reg,bool null_allowed)3933 void Mips64Assembler::CreateHandleScopeEntry(ManagedRegister mout_reg,
3934 FrameOffset handle_scope_offset,
3935 ManagedRegister min_reg,
3936 bool null_allowed) {
3937 Mips64ManagedRegister out_reg = mout_reg.AsMips64();
3938 Mips64ManagedRegister in_reg = min_reg.AsMips64();
3939 CHECK(in_reg.IsNoRegister() || in_reg.IsGpuRegister()) << in_reg;
3940 CHECK(out_reg.IsGpuRegister()) << out_reg;
3941 if (null_allowed) {
3942 Mips64Label null_arg;
3943 // Null values get a handle scope entry value of 0. Otherwise, the handle scope entry is
3944 // the address in the handle scope holding the reference.
3945 // e.g. out_reg = (handle == 0) ? 0 : (SP+handle_offset)
3946 if (in_reg.IsNoRegister()) {
3947 LoadFromOffset(kLoadUnsignedWord, out_reg.AsGpuRegister(),
3948 SP, handle_scope_offset.Int32Value());
3949 in_reg = out_reg;
3950 }
3951 if (!out_reg.Equals(in_reg)) {
3952 LoadConst32(out_reg.AsGpuRegister(), 0);
3953 }
3954 Beqzc(in_reg.AsGpuRegister(), &null_arg);
3955 Daddiu64(out_reg.AsGpuRegister(), SP, handle_scope_offset.Int32Value());
3956 Bind(&null_arg);
3957 } else {
3958 Daddiu64(out_reg.AsGpuRegister(), SP, handle_scope_offset.Int32Value());
3959 }
3960 }
3961
CreateHandleScopeEntry(FrameOffset out_off,FrameOffset handle_scope_offset,ManagedRegister mscratch,bool null_allowed)3962 void Mips64Assembler::CreateHandleScopeEntry(FrameOffset out_off,
3963 FrameOffset handle_scope_offset,
3964 ManagedRegister mscratch,
3965 bool null_allowed) {
3966 Mips64ManagedRegister scratch = mscratch.AsMips64();
3967 CHECK(scratch.IsGpuRegister()) << scratch;
3968 if (null_allowed) {
3969 Mips64Label null_arg;
3970 LoadFromOffset(kLoadUnsignedWord, scratch.AsGpuRegister(), SP,
3971 handle_scope_offset.Int32Value());
3972 // Null values get a handle scope entry value of 0. Otherwise, the handle scope entry is
3973 // the address in the handle scope holding the reference.
3974 // e.g. scratch = (scratch == 0) ? 0 : (SP+handle_scope_offset)
3975 Beqzc(scratch.AsGpuRegister(), &null_arg);
3976 Daddiu64(scratch.AsGpuRegister(), SP, handle_scope_offset.Int32Value());
3977 Bind(&null_arg);
3978 } else {
3979 Daddiu64(scratch.AsGpuRegister(), SP, handle_scope_offset.Int32Value());
3980 }
3981 StoreToOffset(kStoreDoubleword, scratch.AsGpuRegister(), SP, out_off.Int32Value());
3982 }
3983
3984 // Given a handle scope entry, load the associated reference.
LoadReferenceFromHandleScope(ManagedRegister mout_reg,ManagedRegister min_reg)3985 void Mips64Assembler::LoadReferenceFromHandleScope(ManagedRegister mout_reg,
3986 ManagedRegister min_reg) {
3987 Mips64ManagedRegister out_reg = mout_reg.AsMips64();
3988 Mips64ManagedRegister in_reg = min_reg.AsMips64();
3989 CHECK(out_reg.IsGpuRegister()) << out_reg;
3990 CHECK(in_reg.IsGpuRegister()) << in_reg;
3991 Mips64Label null_arg;
3992 if (!out_reg.Equals(in_reg)) {
3993 LoadConst32(out_reg.AsGpuRegister(), 0);
3994 }
3995 Beqzc(in_reg.AsGpuRegister(), &null_arg);
3996 LoadFromOffset(kLoadDoubleword, out_reg.AsGpuRegister(),
3997 in_reg.AsGpuRegister(), 0);
3998 Bind(&null_arg);
3999 }
4000
VerifyObject(ManagedRegister src ATTRIBUTE_UNUSED,bool could_be_null ATTRIBUTE_UNUSED)4001 void Mips64Assembler::VerifyObject(ManagedRegister src ATTRIBUTE_UNUSED,
4002 bool could_be_null ATTRIBUTE_UNUSED) {
4003 // TODO: not validating references
4004 }
4005
VerifyObject(FrameOffset src ATTRIBUTE_UNUSED,bool could_be_null ATTRIBUTE_UNUSED)4006 void Mips64Assembler::VerifyObject(FrameOffset src ATTRIBUTE_UNUSED,
4007 bool could_be_null ATTRIBUTE_UNUSED) {
4008 // TODO: not validating references
4009 }
4010
Call(ManagedRegister mbase,Offset offset,ManagedRegister mscratch)4011 void Mips64Assembler::Call(ManagedRegister mbase, Offset offset, ManagedRegister mscratch) {
4012 Mips64ManagedRegister base = mbase.AsMips64();
4013 Mips64ManagedRegister scratch = mscratch.AsMips64();
4014 CHECK(base.IsGpuRegister()) << base;
4015 CHECK(scratch.IsGpuRegister()) << scratch;
4016 LoadFromOffset(kLoadDoubleword, scratch.AsGpuRegister(),
4017 base.AsGpuRegister(), offset.Int32Value());
4018 Jalr(scratch.AsGpuRegister());
4019 Nop();
4020 // TODO: place reference map on call
4021 }
4022
Call(FrameOffset base,Offset offset,ManagedRegister mscratch)4023 void Mips64Assembler::Call(FrameOffset base, Offset offset, ManagedRegister mscratch) {
4024 Mips64ManagedRegister scratch = mscratch.AsMips64();
4025 CHECK(scratch.IsGpuRegister()) << scratch;
4026 // Call *(*(SP + base) + offset)
4027 LoadFromOffset(kLoadDoubleword, scratch.AsGpuRegister(),
4028 SP, base.Int32Value());
4029 LoadFromOffset(kLoadDoubleword, scratch.AsGpuRegister(),
4030 scratch.AsGpuRegister(), offset.Int32Value());
4031 Jalr(scratch.AsGpuRegister());
4032 Nop();
4033 // TODO: place reference map on call
4034 }
4035
CallFromThread(ThreadOffset64 offset ATTRIBUTE_UNUSED,ManagedRegister mscratch ATTRIBUTE_UNUSED)4036 void Mips64Assembler::CallFromThread(ThreadOffset64 offset ATTRIBUTE_UNUSED,
4037 ManagedRegister mscratch ATTRIBUTE_UNUSED) {
4038 UNIMPLEMENTED(FATAL) << "No MIPS64 implementation";
4039 }
4040
GetCurrentThread(ManagedRegister tr)4041 void Mips64Assembler::GetCurrentThread(ManagedRegister tr) {
4042 Move(tr.AsMips64().AsGpuRegister(), S1);
4043 }
4044
GetCurrentThread(FrameOffset offset,ManagedRegister mscratch ATTRIBUTE_UNUSED)4045 void Mips64Assembler::GetCurrentThread(FrameOffset offset,
4046 ManagedRegister mscratch ATTRIBUTE_UNUSED) {
4047 StoreToOffset(kStoreDoubleword, S1, SP, offset.Int32Value());
4048 }
4049
ExceptionPoll(ManagedRegister mscratch,size_t stack_adjust)4050 void Mips64Assembler::ExceptionPoll(ManagedRegister mscratch, size_t stack_adjust) {
4051 Mips64ManagedRegister scratch = mscratch.AsMips64();
4052 exception_blocks_.emplace_back(scratch, stack_adjust);
4053 LoadFromOffset(kLoadDoubleword,
4054 scratch.AsGpuRegister(),
4055 S1,
4056 Thread::ExceptionOffset<kMips64PointerSize>().Int32Value());
4057 Bnezc(scratch.AsGpuRegister(), exception_blocks_.back().Entry());
4058 }
4059
EmitExceptionPoll(Mips64ExceptionSlowPath * exception)4060 void Mips64Assembler::EmitExceptionPoll(Mips64ExceptionSlowPath* exception) {
4061 Bind(exception->Entry());
4062 if (exception->stack_adjust_ != 0) { // Fix up the frame.
4063 DecreaseFrameSize(exception->stack_adjust_);
4064 }
4065 // Pass exception object as argument.
4066 // Don't care about preserving A0 as this call won't return.
4067 CheckEntrypointTypes<kQuickDeliverException, void, mirror::Object*>();
4068 Move(A0, exception->scratch_.AsGpuRegister());
4069 // Set up call to Thread::Current()->pDeliverException
4070 LoadFromOffset(kLoadDoubleword,
4071 T9,
4072 S1,
4073 QUICK_ENTRYPOINT_OFFSET(kMips64PointerSize, pDeliverException).Int32Value());
4074 Jr(T9);
4075 Nop();
4076
4077 // Call never returns
4078 Break();
4079 }
4080
4081 } // namespace mips64
4082 } // namespace art
4083