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