blob: bf56877499a5b10f0875915f85487a3c57b9c4c2 [file] [log] [blame]
Andreas Gampe57b34292015-01-14 15:45:59 -08001/*
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
Vladimir Marko80afd022015-05-19 18:08:00 +010019#include "base/bit_utils.h"
Andreas Gampe57b34292015-01-14 15:45:59 -080020#include "base/casts.h"
21#include "entrypoints/quick/quick_entrypoints.h"
Alexey Frunzea0e87b02015-09-24 22:57:20 -070022#include "entrypoints/quick/quick_entrypoints_enum.h"
Andreas Gampe57b34292015-01-14 15:45:59 -080023#include "memory_region.h"
24#include "thread.h"
25
26namespace art {
27namespace mips64 {
28
Andreas Gampe542451c2016-07-26 09:02:02 -070029static_assert(static_cast<size_t>(kMips64PointerSize) == kMips64DoublewordSize,
30 "Unexpected Mips64 pointer size.");
31static_assert(kMips64PointerSize == PointerSize::k64, "Unexpected Mips64 pointer size.");
32
33
Alexey Frunzea0e87b02015-09-24 22:57:20 -070034void Mips64Assembler::FinalizeCode() {
35 for (auto& exception_block : exception_blocks_) {
36 EmitExceptionPoll(&exception_block);
37 }
Alexey Frunze0960ac52016-12-20 17:24:59 -080038 ReserveJumpTableSpace();
Alexey Frunze19f6c692016-11-30 19:19:55 -080039 EmitLiterals();
Alexey Frunzea0e87b02015-09-24 22:57:20 -070040 PromoteBranches();
41}
42
43void Mips64Assembler::FinalizeInstructions(const MemoryRegion& region) {
44 EmitBranches();
Alexey Frunze0960ac52016-12-20 17:24:59 -080045 EmitJumpTables();
Alexey Frunzea0e87b02015-09-24 22:57:20 -070046 Assembler::FinalizeInstructions(region);
47 PatchCFI();
48}
49
50void 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
76void 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
Alexey Frunze4dda3372015-06-01 18:31:49 -070087void Mips64Assembler::Emit(uint32_t value) {
Alexey Frunzea0e87b02015-09-24 22:57:20 -070088 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 }
Andreas Gampe57b34292015-01-14 15:45:59 -080097}
98
99void 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);
Alexey Frunze4dda3372015-06-01 18:31:49 -0700104 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;
Andreas Gampe57b34292015-01-14 15:45:59 -0800110 Emit(encoding);
111}
112
Chris Larsen2fadd7b2015-08-14 14:56:10 -0700113void 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
126void 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
Andreas Gampe57b34292015-01-14 15:45:59 -0800139void Mips64Assembler::EmitI(int opcode, GpuRegister rs, GpuRegister rt, uint16_t imm) {
140 CHECK_NE(rs, kNoGpuRegister);
141 CHECK_NE(rt, kNoGpuRegister);
Alexey Frunze4dda3372015-06-01 18:31:49 -0700142 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;
Andreas Gampe57b34292015-01-14 15:45:59 -0800146 Emit(encoding);
147}
148
Alexey Frunze4dda3372015-06-01 18:31:49 -0700149void Mips64Assembler::EmitI21(int opcode, GpuRegister rs, uint32_t imm21) {
150 CHECK_NE(rs, kNoGpuRegister);
Alexey Frunzea0e87b02015-09-24 22:57:20 -0700151 CHECK(IsUint<21>(imm21)) << imm21;
Alexey Frunze4dda3372015-06-01 18:31:49 -0700152 uint32_t encoding = static_cast<uint32_t>(opcode) << kOpcodeShift |
153 static_cast<uint32_t>(rs) << kRsShift |
Alexey Frunzea0e87b02015-09-24 22:57:20 -0700154 imm21;
Alexey Frunze4dda3372015-06-01 18:31:49 -0700155 Emit(encoding);
156}
157
Alexey Frunzea0e87b02015-09-24 22:57:20 -0700158void Mips64Assembler::EmitI26(int opcode, uint32_t imm26) {
159 CHECK(IsUint<26>(imm26)) << imm26;
160 uint32_t encoding = static_cast<uint32_t>(opcode) << kOpcodeShift | imm26;
Andreas Gampe57b34292015-01-14 15:45:59 -0800161 Emit(encoding);
162}
163
164void Mips64Assembler::EmitFR(int opcode, int fmt, FpuRegister ft, FpuRegister fs, FpuRegister fd,
Alexey Frunze4dda3372015-06-01 18:31:49 -0700165 int funct) {
Andreas Gampe57b34292015-01-14 15:45:59 -0800166 CHECK_NE(ft, kNoFpuRegister);
167 CHECK_NE(fs, kNoFpuRegister);
168 CHECK_NE(fd, kNoFpuRegister);
Alexey Frunze4dda3372015-06-01 18:31:49 -0700169 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;
Andreas Gampe57b34292015-01-14 15:45:59 -0800175 Emit(encoding);
176}
177
Alexey Frunze4dda3372015-06-01 18:31:49 -0700178void 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;
Andreas Gampe57b34292015-01-14 15:45:59 -0800184 Emit(encoding);
185}
186
Goran Jakovljevic5a9e51d2017-03-16 16:11:43 +0000187void 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
206void 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
222void 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
238void 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
Goran Jakovljevic3f444032017-03-31 14:38:20 +0200255void 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
Goran Jakovljevic5a9e51d2017-03-16 16:11:43 +0000271void 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
287void 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
Andreas Gampe57b34292015-01-14 15:45:59 -0800303void Mips64Assembler::Addu(GpuRegister rd, GpuRegister rs, GpuRegister rt) {
304 EmitR(0, rs, rt, rd, 0, 0x21);
305}
306
307void Mips64Assembler::Addiu(GpuRegister rt, GpuRegister rs, uint16_t imm16) {
308 EmitI(0x9, rs, rt, imm16);
309}
310
Alexey Frunze4dda3372015-06-01 18:31:49 -0700311void Mips64Assembler::Daddu(GpuRegister rd, GpuRegister rs, GpuRegister rt) {
312 EmitR(0, rs, rt, rd, 0, 0x2d);
313}
314
Andreas Gampe57b34292015-01-14 15:45:59 -0800315void Mips64Assembler::Daddiu(GpuRegister rt, GpuRegister rs, uint16_t imm16) {
316 EmitI(0x19, rs, rt, imm16);
317}
318
Andreas Gampe57b34292015-01-14 15:45:59 -0800319void Mips64Assembler::Subu(GpuRegister rd, GpuRegister rs, GpuRegister rt) {
320 EmitR(0, rs, rt, rd, 0, 0x23);
321}
322
Alexey Frunze4dda3372015-06-01 18:31:49 -0700323void Mips64Assembler::Dsubu(GpuRegister rd, GpuRegister rs, GpuRegister rt) {
324 EmitR(0, rs, rt, rd, 0, 0x2f);
325}
326
Alexey Frunze4dda3372015-06-01 18:31:49 -0700327void Mips64Assembler::MulR6(GpuRegister rd, GpuRegister rs, GpuRegister rt) {
328 EmitR(0, rs, rt, rd, 2, 0x18);
329}
330
Alexey Frunzec857c742015-09-23 15:12:39 -0700331void Mips64Assembler::MuhR6(GpuRegister rd, GpuRegister rs, GpuRegister rt) {
332 EmitR(0, rs, rt, rd, 3, 0x18);
333}
334
Alexey Frunze4dda3372015-06-01 18:31:49 -0700335void Mips64Assembler::DivR6(GpuRegister rd, GpuRegister rs, GpuRegister rt) {
336 EmitR(0, rs, rt, rd, 2, 0x1a);
337}
338
339void Mips64Assembler::ModR6(GpuRegister rd, GpuRegister rs, GpuRegister rt) {
340 EmitR(0, rs, rt, rd, 3, 0x1a);
341}
342
343void Mips64Assembler::DivuR6(GpuRegister rd, GpuRegister rs, GpuRegister rt) {
344 EmitR(0, rs, rt, rd, 2, 0x1b);
345}
346
347void Mips64Assembler::ModuR6(GpuRegister rd, GpuRegister rs, GpuRegister rt) {
348 EmitR(0, rs, rt, rd, 3, 0x1b);
349}
350
351void Mips64Assembler::Dmul(GpuRegister rd, GpuRegister rs, GpuRegister rt) {
352 EmitR(0, rs, rt, rd, 2, 0x1c);
353}
354
Alexey Frunzec857c742015-09-23 15:12:39 -0700355void Mips64Assembler::Dmuh(GpuRegister rd, GpuRegister rs, GpuRegister rt) {
356 EmitR(0, rs, rt, rd, 3, 0x1c);
357}
358
Alexey Frunze4dda3372015-06-01 18:31:49 -0700359void Mips64Assembler::Ddiv(GpuRegister rd, GpuRegister rs, GpuRegister rt) {
360 EmitR(0, rs, rt, rd, 2, 0x1e);
361}
362
363void Mips64Assembler::Dmod(GpuRegister rd, GpuRegister rs, GpuRegister rt) {
364 EmitR(0, rs, rt, rd, 3, 0x1e);
365}
366
367void Mips64Assembler::Ddivu(GpuRegister rd, GpuRegister rs, GpuRegister rt) {
368 EmitR(0, rs, rt, rd, 2, 0x1f);
369}
370
371void Mips64Assembler::Dmodu(GpuRegister rd, GpuRegister rs, GpuRegister rt) {
372 EmitR(0, rs, rt, rd, 3, 0x1f);
373}
374
Andreas Gampe57b34292015-01-14 15:45:59 -0800375void Mips64Assembler::And(GpuRegister rd, GpuRegister rs, GpuRegister rt) {
376 EmitR(0, rs, rt, rd, 0, 0x24);
377}
378
379void Mips64Assembler::Andi(GpuRegister rt, GpuRegister rs, uint16_t imm16) {
380 EmitI(0xc, rs, rt, imm16);
381}
382
383void Mips64Assembler::Or(GpuRegister rd, GpuRegister rs, GpuRegister rt) {
384 EmitR(0, rs, rt, rd, 0, 0x25);
385}
386
387void Mips64Assembler::Ori(GpuRegister rt, GpuRegister rs, uint16_t imm16) {
388 EmitI(0xd, rs, rt, imm16);
389}
390
391void Mips64Assembler::Xor(GpuRegister rd, GpuRegister rs, GpuRegister rt) {
392 EmitR(0, rs, rt, rd, 0, 0x26);
393}
394
395void Mips64Assembler::Xori(GpuRegister rt, GpuRegister rs, uint16_t imm16) {
396 EmitI(0xe, rs, rt, imm16);
397}
398
399void Mips64Assembler::Nor(GpuRegister rd, GpuRegister rs, GpuRegister rt) {
400 EmitR(0, rs, rt, rd, 0, 0x27);
401}
402
Chris Larsen2fadd7b2015-08-14 14:56:10 -0700403void Mips64Assembler::Bitswap(GpuRegister rd, GpuRegister rt) {
404 EmitRtd(0x1f, rt, rd, 0x0, 0x20);
405}
406
407void Mips64Assembler::Dbitswap(GpuRegister rd, GpuRegister rt) {
408 EmitRtd(0x1f, rt, rd, 0x0, 0x24);
409}
410
Alexey Frunze4dda3372015-06-01 18:31:49 -0700411void Mips64Assembler::Seb(GpuRegister rd, GpuRegister rt) {
412 EmitR(0x1f, static_cast<GpuRegister>(0), rt, rd, 0x10, 0x20);
Andreas Gampe57b34292015-01-14 15:45:59 -0800413}
414
Alexey Frunze4dda3372015-06-01 18:31:49 -0700415void Mips64Assembler::Seh(GpuRegister rd, GpuRegister rt) {
416 EmitR(0x1f, static_cast<GpuRegister>(0), rt, rd, 0x18, 0x20);
Andreas Gampe57b34292015-01-14 15:45:59 -0800417}
418
Chris Larsen2fadd7b2015-08-14 14:56:10 -0700419void Mips64Assembler::Dsbh(GpuRegister rd, GpuRegister rt) {
420 EmitRtd(0x1f, rt, rd, 0x2, 0x24);
421}
422
423void Mips64Assembler::Dshd(GpuRegister rd, GpuRegister rt) {
424 EmitRtd(0x1f, rt, rd, 0x5, 0x24);
425}
426
Lazar Trsicd9672662015-09-03 17:33:01 +0200427void 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
433void 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);
Andreas Gampe57b34292015-01-14 15:45:59 -0800438}
439
Chris Larsene3660592016-11-09 11:13:42 -0800440void 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
446void 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
Chris Larsen2fadd7b2015-08-14 14:56:10 -0700452void Mips64Assembler::Wsbh(GpuRegister rd, GpuRegister rt) {
453 EmitRtd(0x1f, rt, rd, 2, 0x20);
454}
455
456void Mips64Assembler::Sc(GpuRegister rt, GpuRegister base, int16_t imm9) {
Lazar Trsicd9672662015-09-03 17:33:01 +0200457 CHECK(IsInt<9>(imm9));
Chris Larsen2fadd7b2015-08-14 14:56:10 -0700458 EmitI(0x1f, base, rt, ((imm9 & 0x1FF) << 7) | 0x26);
459}
460
461void Mips64Assembler::Scd(GpuRegister rt, GpuRegister base, int16_t imm9) {
Lazar Trsicd9672662015-09-03 17:33:01 +0200462 CHECK(IsInt<9>(imm9));
Chris Larsen2fadd7b2015-08-14 14:56:10 -0700463 EmitI(0x1f, base, rt, ((imm9 & 0x1FF) << 7) | 0x27);
464}
465
466void Mips64Assembler::Ll(GpuRegister rt, GpuRegister base, int16_t imm9) {
Lazar Trsicd9672662015-09-03 17:33:01 +0200467 CHECK(IsInt<9>(imm9));
Chris Larsen2fadd7b2015-08-14 14:56:10 -0700468 EmitI(0x1f, base, rt, ((imm9 & 0x1FF) << 7) | 0x36);
469}
470
471void Mips64Assembler::Lld(GpuRegister rt, GpuRegister base, int16_t imm9) {
Lazar Trsicd9672662015-09-03 17:33:01 +0200472 CHECK(IsInt<9>(imm9));
Chris Larsen2fadd7b2015-08-14 14:56:10 -0700473 EmitI(0x1f, base, rt, ((imm9 & 0x1FF) << 7) | 0x37);
474}
475
Alexey Frunze4dda3372015-06-01 18:31:49 -0700476void Mips64Assembler::Sll(GpuRegister rd, GpuRegister rt, int shamt) {
477 EmitR(0, static_cast<GpuRegister>(0), rt, rd, shamt, 0x00);
478}
479
480void Mips64Assembler::Srl(GpuRegister rd, GpuRegister rt, int shamt) {
481 EmitR(0, static_cast<GpuRegister>(0), rt, rd, shamt, 0x02);
482}
483
Chris Larsen2fadd7b2015-08-14 14:56:10 -0700484void Mips64Assembler::Rotr(GpuRegister rd, GpuRegister rt, int shamt) {
485 EmitR(0, static_cast<GpuRegister>(1), rt, rd, shamt, 0x02);
486}
487
Alexey Frunze4dda3372015-06-01 18:31:49 -0700488void Mips64Assembler::Sra(GpuRegister rd, GpuRegister rt, int shamt) {
489 EmitR(0, static_cast<GpuRegister>(0), rt, rd, shamt, 0x03);
490}
491
492void Mips64Assembler::Sllv(GpuRegister rd, GpuRegister rt, GpuRegister rs) {
Andreas Gampe57b34292015-01-14 15:45:59 -0800493 EmitR(0, rs, rt, rd, 0, 0x04);
494}
495
Chris Larsen9aebff22015-09-22 17:54:15 -0700496void Mips64Assembler::Rotrv(GpuRegister rd, GpuRegister rt, GpuRegister rs) {
497 EmitR(0, rs, rt, rd, 1, 0x06);
498}
499
Alexey Frunze4dda3372015-06-01 18:31:49 -0700500void Mips64Assembler::Srlv(GpuRegister rd, GpuRegister rt, GpuRegister rs) {
Andreas Gampe57b34292015-01-14 15:45:59 -0800501 EmitR(0, rs, rt, rd, 0, 0x06);
502}
503
Alexey Frunze4dda3372015-06-01 18:31:49 -0700504void Mips64Assembler::Srav(GpuRegister rd, GpuRegister rt, GpuRegister rs) {
Andreas Gampe57b34292015-01-14 15:45:59 -0800505 EmitR(0, rs, rt, rd, 0, 0x07);
506}
507
Alexey Frunze4dda3372015-06-01 18:31:49 -0700508void Mips64Assembler::Dsll(GpuRegister rd, GpuRegister rt, int shamt) {
509 EmitR(0, static_cast<GpuRegister>(0), rt, rd, shamt, 0x38);
510}
511
512void Mips64Assembler::Dsrl(GpuRegister rd, GpuRegister rt, int shamt) {
513 EmitR(0, static_cast<GpuRegister>(0), rt, rd, shamt, 0x3a);
514}
515
Chris Larsen9aebff22015-09-22 17:54:15 -0700516void Mips64Assembler::Drotr(GpuRegister rd, GpuRegister rt, int shamt) {
517 EmitR(0, static_cast<GpuRegister>(1), rt, rd, shamt, 0x3a);
518}
519
Alexey Frunze4dda3372015-06-01 18:31:49 -0700520void Mips64Assembler::Dsra(GpuRegister rd, GpuRegister rt, int shamt) {
521 EmitR(0, static_cast<GpuRegister>(0), rt, rd, shamt, 0x3b);
522}
523
524void Mips64Assembler::Dsll32(GpuRegister rd, GpuRegister rt, int shamt) {
525 EmitR(0, static_cast<GpuRegister>(0), rt, rd, shamt, 0x3c);
526}
527
528void Mips64Assembler::Dsrl32(GpuRegister rd, GpuRegister rt, int shamt) {
529 EmitR(0, static_cast<GpuRegister>(0), rt, rd, shamt, 0x3e);
530}
531
Chris Larsen9aebff22015-09-22 17:54:15 -0700532void Mips64Assembler::Drotr32(GpuRegister rd, GpuRegister rt, int shamt) {
533 EmitR(0, static_cast<GpuRegister>(1), rt, rd, shamt, 0x3e);
534}
535
Alexey Frunze4dda3372015-06-01 18:31:49 -0700536void Mips64Assembler::Dsra32(GpuRegister rd, GpuRegister rt, int shamt) {
537 EmitR(0, static_cast<GpuRegister>(0), rt, rd, shamt, 0x3f);
538}
539
540void Mips64Assembler::Dsllv(GpuRegister rd, GpuRegister rt, GpuRegister rs) {
541 EmitR(0, rs, rt, rd, 0, 0x14);
542}
543
544void Mips64Assembler::Dsrlv(GpuRegister rd, GpuRegister rt, GpuRegister rs) {
545 EmitR(0, rs, rt, rd, 0, 0x16);
546}
547
Chris Larsen9aebff22015-09-22 17:54:15 -0700548void Mips64Assembler::Drotrv(GpuRegister rd, GpuRegister rt, GpuRegister rs) {
549 EmitR(0, rs, rt, rd, 1, 0x16);
550}
551
Alexey Frunze4dda3372015-06-01 18:31:49 -0700552void Mips64Assembler::Dsrav(GpuRegister rd, GpuRegister rt, GpuRegister rs) {
553 EmitR(0, rs, rt, rd, 0, 0x17);
554}
555
Andreas Gampe57b34292015-01-14 15:45:59 -0800556void Mips64Assembler::Lb(GpuRegister rt, GpuRegister rs, uint16_t imm16) {
557 EmitI(0x20, rs, rt, imm16);
558}
559
560void Mips64Assembler::Lh(GpuRegister rt, GpuRegister rs, uint16_t imm16) {
561 EmitI(0x21, rs, rt, imm16);
562}
563
564void Mips64Assembler::Lw(GpuRegister rt, GpuRegister rs, uint16_t imm16) {
565 EmitI(0x23, rs, rt, imm16);
566}
567
568void Mips64Assembler::Ld(GpuRegister rt, GpuRegister rs, uint16_t imm16) {
569 EmitI(0x37, rs, rt, imm16);
570}
571
572void Mips64Assembler::Lbu(GpuRegister rt, GpuRegister rs, uint16_t imm16) {
573 EmitI(0x24, rs, rt, imm16);
574}
575
576void Mips64Assembler::Lhu(GpuRegister rt, GpuRegister rs, uint16_t imm16) {
577 EmitI(0x25, rs, rt, imm16);
578}
579
Douglas Leungd90957f2015-04-30 19:22:49 -0700580void Mips64Assembler::Lwu(GpuRegister rt, GpuRegister rs, uint16_t imm16) {
581 EmitI(0x27, rs, rt, imm16);
582}
583
Alexey Frunze19f6c692016-11-30 19:19:55 -0800584void Mips64Assembler::Lwpc(GpuRegister rs, uint32_t imm19) {
585 CHECK(IsUint<19>(imm19)) << imm19;
586 EmitI21(0x3B, rs, (0x01 << 19) | imm19);
587}
588
589void Mips64Assembler::Lwupc(GpuRegister rs, uint32_t imm19) {
590 CHECK(IsUint<19>(imm19)) << imm19;
591 EmitI21(0x3B, rs, (0x02 << 19) | imm19);
592}
593
594void Mips64Assembler::Ldpc(GpuRegister rs, uint32_t imm18) {
595 CHECK(IsUint<18>(imm18)) << imm18;
596 EmitI21(0x3B, rs, (0x06 << 18) | imm18);
597}
598
Andreas Gampe57b34292015-01-14 15:45:59 -0800599void Mips64Assembler::Lui(GpuRegister rt, uint16_t imm16) {
600 EmitI(0xf, static_cast<GpuRegister>(0), rt, imm16);
601}
602
Alexey Frunze0960ac52016-12-20 17:24:59 -0800603void Mips64Assembler::Aui(GpuRegister rt, GpuRegister rs, uint16_t imm16) {
604 EmitI(0xf, rs, rt, imm16);
605}
606
Alexey Frunzec061de12017-02-14 13:27:23 -0800607void Mips64Assembler::Daui(GpuRegister rt, GpuRegister rs, uint16_t imm16) {
608 CHECK_NE(rs, ZERO);
609 EmitI(0x1d, rs, rt, imm16);
610}
611
Alexey Frunze4dda3372015-06-01 18:31:49 -0700612void Mips64Assembler::Dahi(GpuRegister rs, uint16_t imm16) {
613 EmitI(1, rs, static_cast<GpuRegister>(6), imm16);
614}
615
616void Mips64Assembler::Dati(GpuRegister rs, uint16_t imm16) {
617 EmitI(1, rs, static_cast<GpuRegister>(0x1e), imm16);
618}
619
620void 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
Andreas Gampe57b34292015-01-14 15:45:59 -0800625void Mips64Assembler::Sb(GpuRegister rt, GpuRegister rs, uint16_t imm16) {
626 EmitI(0x28, rs, rt, imm16);
627}
628
629void Mips64Assembler::Sh(GpuRegister rt, GpuRegister rs, uint16_t imm16) {
630 EmitI(0x29, rs, rt, imm16);
631}
632
633void Mips64Assembler::Sw(GpuRegister rt, GpuRegister rs, uint16_t imm16) {
634 EmitI(0x2b, rs, rt, imm16);
635}
636
637void Mips64Assembler::Sd(GpuRegister rt, GpuRegister rs, uint16_t imm16) {
638 EmitI(0x3f, rs, rt, imm16);
639}
640
641void Mips64Assembler::Slt(GpuRegister rd, GpuRegister rs, GpuRegister rt) {
642 EmitR(0, rs, rt, rd, 0, 0x2a);
643}
644
645void Mips64Assembler::Sltu(GpuRegister rd, GpuRegister rs, GpuRegister rt) {
646 EmitR(0, rs, rt, rd, 0, 0x2b);
647}
648
649void Mips64Assembler::Slti(GpuRegister rt, GpuRegister rs, uint16_t imm16) {
650 EmitI(0xa, rs, rt, imm16);
651}
652
653void Mips64Assembler::Sltiu(GpuRegister rt, GpuRegister rs, uint16_t imm16) {
654 EmitI(0xb, rs, rt, imm16);
655}
656
Chris Larsen2fadd7b2015-08-14 14:56:10 -0700657void Mips64Assembler::Seleqz(GpuRegister rd, GpuRegister rs, GpuRegister rt) {
658 EmitR(0, rs, rt, rd, 0, 0x35);
659}
660
661void Mips64Assembler::Selnez(GpuRegister rd, GpuRegister rs, GpuRegister rt) {
662 EmitR(0, rs, rt, rd, 0, 0x37);
663}
664
665void Mips64Assembler::Clz(GpuRegister rd, GpuRegister rs) {
666 EmitRsd(0, rs, rd, 0x01, 0x10);
667}
668
669void Mips64Assembler::Clo(GpuRegister rd, GpuRegister rs) {
670 EmitRsd(0, rs, rd, 0x01, 0x11);
671}
672
673void Mips64Assembler::Dclz(GpuRegister rd, GpuRegister rs) {
674 EmitRsd(0, rs, rd, 0x01, 0x12);
675}
676
677void Mips64Assembler::Dclo(GpuRegister rd, GpuRegister rs) {
678 EmitRsd(0, rs, rd, 0x01, 0x13);
679}
680
Alexey Frunze4dda3372015-06-01 18:31:49 -0700681void Mips64Assembler::Jalr(GpuRegister rd, GpuRegister rs) {
682 EmitR(0, rs, static_cast<GpuRegister>(0), rd, 0, 0x09);
Andreas Gampe57b34292015-01-14 15:45:59 -0800683}
684
685void Mips64Assembler::Jalr(GpuRegister rs) {
Alexey Frunze4dda3372015-06-01 18:31:49 -0700686 Jalr(RA, rs);
687}
688
689void Mips64Assembler::Jr(GpuRegister rs) {
690 Jalr(ZERO, rs);
691}
692
693void Mips64Assembler::Auipc(GpuRegister rs, uint16_t imm16) {
694 EmitI(0x3B, rs, static_cast<GpuRegister>(0x1E), imm16);
695}
696
Alexey Frunzea0e87b02015-09-24 22:57:20 -0700697void Mips64Assembler::Addiupc(GpuRegister rs, uint32_t imm19) {
698 CHECK(IsUint<19>(imm19)) << imm19;
699 EmitI21(0x3B, rs, imm19);
700}
701
702void Mips64Assembler::Bc(uint32_t imm26) {
703 EmitI26(0x32, imm26);
704}
705
Alexey Frunze19f6c692016-11-30 19:19:55 -0800706void Mips64Assembler::Balc(uint32_t imm26) {
707 EmitI26(0x3A, imm26);
708}
709
Alexey Frunze4dda3372015-06-01 18:31:49 -0700710void Mips64Assembler::Jic(GpuRegister rt, uint16_t imm16) {
711 EmitI(0x36, static_cast<GpuRegister>(0), rt, imm16);
712}
713
714void Mips64Assembler::Jialc(GpuRegister rt, uint16_t imm16) {
715 EmitI(0x3E, static_cast<GpuRegister>(0), rt, imm16);
716}
717
718void 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
725void Mips64Assembler::Bltzc(GpuRegister rt, uint16_t imm16) {
726 CHECK_NE(rt, ZERO);
727 EmitI(0x17, rt, rt, imm16);
728}
729
730void Mips64Assembler::Bgtzc(GpuRegister rt, uint16_t imm16) {
731 CHECK_NE(rt, ZERO);
732 EmitI(0x17, static_cast<GpuRegister>(0), rt, imm16);
733}
734
735void 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
742void Mips64Assembler::Bgezc(GpuRegister rt, uint16_t imm16) {
743 CHECK_NE(rt, ZERO);
744 EmitI(0x16, rt, rt, imm16);
745}
746
747void Mips64Assembler::Blezc(GpuRegister rt, uint16_t imm16) {
748 CHECK_NE(rt, ZERO);
749 EmitI(0x16, static_cast<GpuRegister>(0), rt, imm16);
750}
751
752void 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
759void 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
766void Mips64Assembler::Beqc(GpuRegister rs, GpuRegister rt, uint16_t imm16) {
767 CHECK_NE(rs, ZERO);
768 CHECK_NE(rt, ZERO);
769 CHECK_NE(rs, rt);
Alexey Frunzea0e87b02015-09-24 22:57:20 -0700770 EmitI(0x8, std::min(rs, rt), std::max(rs, rt), imm16);
Alexey Frunze4dda3372015-06-01 18:31:49 -0700771}
772
773void Mips64Assembler::Bnec(GpuRegister rs, GpuRegister rt, uint16_t imm16) {
774 CHECK_NE(rs, ZERO);
775 CHECK_NE(rt, ZERO);
776 CHECK_NE(rs, rt);
Alexey Frunzea0e87b02015-09-24 22:57:20 -0700777 EmitI(0x18, std::min(rs, rt), std::max(rs, rt), imm16);
Alexey Frunze4dda3372015-06-01 18:31:49 -0700778}
779
780void Mips64Assembler::Beqzc(GpuRegister rs, uint32_t imm21) {
781 CHECK_NE(rs, ZERO);
782 EmitI21(0x36, rs, imm21);
783}
784
785void Mips64Assembler::Bnezc(GpuRegister rs, uint32_t imm21) {
786 CHECK_NE(rs, ZERO);
787 EmitI21(0x3E, rs, imm21);
Andreas Gampe57b34292015-01-14 15:45:59 -0800788}
789
Alexey Frunze299a9392015-12-08 16:08:02 -0800790void Mips64Assembler::Bc1eqz(FpuRegister ft, uint16_t imm16) {
791 EmitFI(0x11, 0x9, ft, imm16);
792}
793
794void Mips64Assembler::Bc1nez(FpuRegister ft, uint16_t imm16) {
795 EmitFI(0x11, 0xD, ft, imm16);
796}
797
Alexey Frunze0cab6562017-07-25 15:19:36 -0700798void Mips64Assembler::Beq(GpuRegister rs, GpuRegister rt, uint16_t imm16) {
799 EmitI(0x4, rs, rt, imm16);
Alexey Frunze4147fcc2017-06-17 19:57:27 -0700800}
801
Alexey Frunze0cab6562017-07-25 15:19:36 -0700802void Mips64Assembler::Bne(GpuRegister rs, GpuRegister rt, uint16_t imm16) {
803 EmitI(0x5, rs, rt, imm16);
804}
805
806void Mips64Assembler::Beqz(GpuRegister rt, uint16_t imm16) {
807 Beq(rt, ZERO, imm16);
808}
809
810void Mips64Assembler::Bnez(GpuRegister rt, uint16_t imm16) {
811 Bne(rt, ZERO, imm16);
812}
813
814void Mips64Assembler::Bltz(GpuRegister rt, uint16_t imm16) {
815 EmitI(0x1, rt, static_cast<GpuRegister>(0), imm16);
816}
817
818void Mips64Assembler::Bgez(GpuRegister rt, uint16_t imm16) {
819 EmitI(0x1, rt, static_cast<GpuRegister>(0x1), imm16);
820}
821
822void Mips64Assembler::Blez(GpuRegister rt, uint16_t imm16) {
823 EmitI(0x6, rt, static_cast<GpuRegister>(0), imm16);
824}
825
826void Mips64Assembler::Bgtz(GpuRegister rt, uint16_t imm16) {
827 EmitI(0x7, rt, static_cast<GpuRegister>(0), imm16);
828}
829
830void Mips64Assembler::EmitBcondR6(BranchCondition cond,
831 GpuRegister rs,
832 GpuRegister rt,
833 uint32_t imm16_21) {
Alexey Frunzea0e87b02015-09-24 22:57:20 -0700834 switch (cond) {
835 case kCondLT:
836 Bltc(rs, rt, imm16_21);
837 break;
838 case kCondGE:
839 Bgec(rs, rt, imm16_21);
840 break;
841 case kCondLE:
842 Bgec(rt, rs, imm16_21);
843 break;
844 case kCondGT:
845 Bltc(rt, rs, imm16_21);
846 break;
847 case kCondLTZ:
848 CHECK_EQ(rt, ZERO);
849 Bltzc(rs, imm16_21);
850 break;
851 case kCondGEZ:
852 CHECK_EQ(rt, ZERO);
853 Bgezc(rs, imm16_21);
854 break;
855 case kCondLEZ:
856 CHECK_EQ(rt, ZERO);
857 Blezc(rs, imm16_21);
858 break;
859 case kCondGTZ:
860 CHECK_EQ(rt, ZERO);
861 Bgtzc(rs, imm16_21);
862 break;
863 case kCondEQ:
864 Beqc(rs, rt, imm16_21);
865 break;
866 case kCondNE:
867 Bnec(rs, rt, imm16_21);
868 break;
869 case kCondEQZ:
870 CHECK_EQ(rt, ZERO);
871 Beqzc(rs, imm16_21);
872 break;
873 case kCondNEZ:
874 CHECK_EQ(rt, ZERO);
875 Bnezc(rs, imm16_21);
876 break;
877 case kCondLTU:
878 Bltuc(rs, rt, imm16_21);
879 break;
880 case kCondGEU:
881 Bgeuc(rs, rt, imm16_21);
882 break;
Alexey Frunze299a9392015-12-08 16:08:02 -0800883 case kCondF:
884 CHECK_EQ(rt, ZERO);
885 Bc1eqz(static_cast<FpuRegister>(rs), imm16_21);
886 break;
887 case kCondT:
888 CHECK_EQ(rt, ZERO);
889 Bc1nez(static_cast<FpuRegister>(rs), imm16_21);
890 break;
Alexey Frunzea0e87b02015-09-24 22:57:20 -0700891 case kUncond:
892 LOG(FATAL) << "Unexpected branch condition " << cond;
893 UNREACHABLE();
894 }
895}
896
Alexey Frunze0cab6562017-07-25 15:19:36 -0700897void Mips64Assembler::EmitBcondR2(BranchCondition cond,
898 GpuRegister rs,
899 GpuRegister rt,
900 uint16_t imm16) {
901 switch (cond) {
902 case kCondLTZ:
903 CHECK_EQ(rt, ZERO);
904 Bltz(rs, imm16);
905 break;
906 case kCondGEZ:
907 CHECK_EQ(rt, ZERO);
908 Bgez(rs, imm16);
909 break;
910 case kCondLEZ:
911 CHECK_EQ(rt, ZERO);
912 Blez(rs, imm16);
913 break;
914 case kCondGTZ:
915 CHECK_EQ(rt, ZERO);
916 Bgtz(rs, imm16);
917 break;
918 case kCondEQ:
919 Beq(rs, rt, imm16);
920 break;
921 case kCondNE:
922 Bne(rs, rt, imm16);
923 break;
924 case kCondEQZ:
925 CHECK_EQ(rt, ZERO);
926 Beqz(rs, imm16);
927 break;
928 case kCondNEZ:
929 CHECK_EQ(rt, ZERO);
930 Bnez(rs, imm16);
931 break;
932 case kCondF:
933 case kCondT:
934 case kCondLT:
935 case kCondGE:
936 case kCondLE:
937 case kCondGT:
938 case kCondLTU:
939 case kCondGEU:
940 case kUncond:
941 LOG(FATAL) << "Unexpected branch condition " << cond;
942 UNREACHABLE();
943 }
944}
945
Andreas Gampe57b34292015-01-14 15:45:59 -0800946void Mips64Assembler::AddS(FpuRegister fd, FpuRegister fs, FpuRegister ft) {
947 EmitFR(0x11, 0x10, ft, fs, fd, 0x0);
948}
949
950void Mips64Assembler::SubS(FpuRegister fd, FpuRegister fs, FpuRegister ft) {
951 EmitFR(0x11, 0x10, ft, fs, fd, 0x1);
952}
953
954void Mips64Assembler::MulS(FpuRegister fd, FpuRegister fs, FpuRegister ft) {
955 EmitFR(0x11, 0x10, ft, fs, fd, 0x2);
956}
957
958void Mips64Assembler::DivS(FpuRegister fd, FpuRegister fs, FpuRegister ft) {
959 EmitFR(0x11, 0x10, ft, fs, fd, 0x3);
960}
961
962void Mips64Assembler::AddD(FpuRegister fd, FpuRegister fs, FpuRegister ft) {
Alexey Frunze4dda3372015-06-01 18:31:49 -0700963 EmitFR(0x11, 0x11, ft, fs, fd, 0x0);
Andreas Gampe57b34292015-01-14 15:45:59 -0800964}
965
966void Mips64Assembler::SubD(FpuRegister fd, FpuRegister fs, FpuRegister ft) {
Alexey Frunze4dda3372015-06-01 18:31:49 -0700967 EmitFR(0x11, 0x11, ft, fs, fd, 0x1);
Andreas Gampe57b34292015-01-14 15:45:59 -0800968}
969
970void Mips64Assembler::MulD(FpuRegister fd, FpuRegister fs, FpuRegister ft) {
Alexey Frunze4dda3372015-06-01 18:31:49 -0700971 EmitFR(0x11, 0x11, ft, fs, fd, 0x2);
Andreas Gampe57b34292015-01-14 15:45:59 -0800972}
973
974void Mips64Assembler::DivD(FpuRegister fd, FpuRegister fs, FpuRegister ft) {
Alexey Frunze4dda3372015-06-01 18:31:49 -0700975 EmitFR(0x11, 0x11, ft, fs, fd, 0x3);
Andreas Gampe57b34292015-01-14 15:45:59 -0800976}
977
Chris Larsen2fadd7b2015-08-14 14:56:10 -0700978void Mips64Assembler::SqrtS(FpuRegister fd, FpuRegister fs) {
979 EmitFR(0x11, 0x10, static_cast<FpuRegister>(0), fs, fd, 0x4);
980}
981
982void Mips64Assembler::SqrtD(FpuRegister fd, FpuRegister fs) {
983 EmitFR(0x11, 0x11, static_cast<FpuRegister>(0), fs, fd, 0x4);
984}
985
986void Mips64Assembler::AbsS(FpuRegister fd, FpuRegister fs) {
987 EmitFR(0x11, 0x10, static_cast<FpuRegister>(0), fs, fd, 0x5);
988}
989
990void Mips64Assembler::AbsD(FpuRegister fd, FpuRegister fs) {
991 EmitFR(0x11, 0x11, static_cast<FpuRegister>(0), fs, fd, 0x5);
992}
993
Andreas Gampe57b34292015-01-14 15:45:59 -0800994void Mips64Assembler::MovS(FpuRegister fd, FpuRegister fs) {
995 EmitFR(0x11, 0x10, static_cast<FpuRegister>(0), fs, fd, 0x6);
996}
997
998void Mips64Assembler::MovD(FpuRegister fd, FpuRegister fs) {
Alexey Frunze4dda3372015-06-01 18:31:49 -0700999 EmitFR(0x11, 0x11, static_cast<FpuRegister>(0), fs, fd, 0x6);
1000}
1001
1002void Mips64Assembler::NegS(FpuRegister fd, FpuRegister fs) {
1003 EmitFR(0x11, 0x10, static_cast<FpuRegister>(0), fs, fd, 0x7);
1004}
1005
1006void Mips64Assembler::NegD(FpuRegister fd, FpuRegister fs) {
1007 EmitFR(0x11, 0x11, static_cast<FpuRegister>(0), fs, fd, 0x7);
1008}
1009
Chris Larsen2fadd7b2015-08-14 14:56:10 -07001010void Mips64Assembler::RoundLS(FpuRegister fd, FpuRegister fs) {
1011 EmitFR(0x11, 0x10, static_cast<FpuRegister>(0), fs, fd, 0x8);
1012}
1013
1014void Mips64Assembler::RoundLD(FpuRegister fd, FpuRegister fs) {
1015 EmitFR(0x11, 0x11, static_cast<FpuRegister>(0), fs, fd, 0x8);
1016}
1017
1018void Mips64Assembler::RoundWS(FpuRegister fd, FpuRegister fs) {
1019 EmitFR(0x11, 0x10, static_cast<FpuRegister>(0), fs, fd, 0xc);
1020}
1021
1022void Mips64Assembler::RoundWD(FpuRegister fd, FpuRegister fs) {
1023 EmitFR(0x11, 0x11, static_cast<FpuRegister>(0), fs, fd, 0xc);
1024}
1025
Alexey Frunzebaf60b72015-12-22 15:15:03 -08001026void Mips64Assembler::TruncLS(FpuRegister fd, FpuRegister fs) {
1027 EmitFR(0x11, 0x10, static_cast<FpuRegister>(0), fs, fd, 0x9);
1028}
1029
1030void Mips64Assembler::TruncLD(FpuRegister fd, FpuRegister fs) {
1031 EmitFR(0x11, 0x11, static_cast<FpuRegister>(0), fs, fd, 0x9);
1032}
1033
1034void Mips64Assembler::TruncWS(FpuRegister fd, FpuRegister fs) {
1035 EmitFR(0x11, 0x10, static_cast<FpuRegister>(0), fs, fd, 0xd);
1036}
1037
1038void Mips64Assembler::TruncWD(FpuRegister fd, FpuRegister fs) {
1039 EmitFR(0x11, 0x11, static_cast<FpuRegister>(0), fs, fd, 0xd);
1040}
1041
Chris Larsen2fadd7b2015-08-14 14:56:10 -07001042void Mips64Assembler::CeilLS(FpuRegister fd, FpuRegister fs) {
1043 EmitFR(0x11, 0x10, static_cast<FpuRegister>(0), fs, fd, 0xa);
1044}
1045
1046void Mips64Assembler::CeilLD(FpuRegister fd, FpuRegister fs) {
1047 EmitFR(0x11, 0x11, static_cast<FpuRegister>(0), fs, fd, 0xa);
1048}
1049
1050void Mips64Assembler::CeilWS(FpuRegister fd, FpuRegister fs) {
1051 EmitFR(0x11, 0x10, static_cast<FpuRegister>(0), fs, fd, 0xe);
1052}
1053
1054void Mips64Assembler::CeilWD(FpuRegister fd, FpuRegister fs) {
1055 EmitFR(0x11, 0x11, static_cast<FpuRegister>(0), fs, fd, 0xe);
1056}
1057
1058void Mips64Assembler::FloorLS(FpuRegister fd, FpuRegister fs) {
1059 EmitFR(0x11, 0x10, static_cast<FpuRegister>(0), fs, fd, 0xb);
1060}
1061
1062void Mips64Assembler::FloorLD(FpuRegister fd, FpuRegister fs) {
1063 EmitFR(0x11, 0x11, static_cast<FpuRegister>(0), fs, fd, 0xb);
1064}
1065
1066void Mips64Assembler::FloorWS(FpuRegister fd, FpuRegister fs) {
1067 EmitFR(0x11, 0x10, static_cast<FpuRegister>(0), fs, fd, 0xf);
1068}
1069
1070void Mips64Assembler::FloorWD(FpuRegister fd, FpuRegister fs) {
1071 EmitFR(0x11, 0x11, static_cast<FpuRegister>(0), fs, fd, 0xf);
1072}
1073
1074void Mips64Assembler::SelS(FpuRegister fd, FpuRegister fs, FpuRegister ft) {
1075 EmitFR(0x11, 0x10, ft, fs, fd, 0x10);
1076}
1077
1078void Mips64Assembler::SelD(FpuRegister fd, FpuRegister fs, FpuRegister ft) {
1079 EmitFR(0x11, 0x11, ft, fs, fd, 0x10);
1080}
1081
Goran Jakovljevic2dec9272017-08-02 11:41:26 +02001082void Mips64Assembler::SeleqzS(FpuRegister fd, FpuRegister fs, FpuRegister ft) {
1083 EmitFR(0x11, 0x10, ft, fs, fd, 0x14);
1084}
1085
1086void Mips64Assembler::SeleqzD(FpuRegister fd, FpuRegister fs, FpuRegister ft) {
1087 EmitFR(0x11, 0x11, ft, fs, fd, 0x14);
1088}
1089
1090void Mips64Assembler::SelnezS(FpuRegister fd, FpuRegister fs, FpuRegister ft) {
1091 EmitFR(0x11, 0x10, ft, fs, fd, 0x17);
1092}
1093
1094void Mips64Assembler::SelnezD(FpuRegister fd, FpuRegister fs, FpuRegister ft) {
1095 EmitFR(0x11, 0x11, ft, fs, fd, 0x17);
1096}
1097
Chris Larsen2fadd7b2015-08-14 14:56:10 -07001098void Mips64Assembler::RintS(FpuRegister fd, FpuRegister fs) {
1099 EmitFR(0x11, 0x10, static_cast<FpuRegister>(0), fs, fd, 0x1a);
1100}
1101
1102void Mips64Assembler::RintD(FpuRegister fd, FpuRegister fs) {
1103 EmitFR(0x11, 0x11, static_cast<FpuRegister>(0), fs, fd, 0x1a);
1104}
1105
1106void Mips64Assembler::ClassS(FpuRegister fd, FpuRegister fs) {
1107 EmitFR(0x11, 0x10, static_cast<FpuRegister>(0), fs, fd, 0x1b);
1108}
1109
1110void Mips64Assembler::ClassD(FpuRegister fd, FpuRegister fs) {
1111 EmitFR(0x11, 0x11, static_cast<FpuRegister>(0), fs, fd, 0x1b);
1112}
1113
1114void Mips64Assembler::MinS(FpuRegister fd, FpuRegister fs, FpuRegister ft) {
1115 EmitFR(0x11, 0x10, ft, fs, fd, 0x1c);
1116}
1117
1118void Mips64Assembler::MinD(FpuRegister fd, FpuRegister fs, FpuRegister ft) {
1119 EmitFR(0x11, 0x11, ft, fs, fd, 0x1c);
1120}
1121
1122void Mips64Assembler::MaxS(FpuRegister fd, FpuRegister fs, FpuRegister ft) {
1123 EmitFR(0x11, 0x10, ft, fs, fd, 0x1e);
1124}
1125
1126void Mips64Assembler::MaxD(FpuRegister fd, FpuRegister fs, FpuRegister ft) {
1127 EmitFR(0x11, 0x11, ft, fs, fd, 0x1e);
1128}
1129
Alexey Frunze299a9392015-12-08 16:08:02 -08001130void Mips64Assembler::CmpUnS(FpuRegister fd, FpuRegister fs, FpuRegister ft) {
1131 EmitFR(0x11, 0x14, ft, fs, fd, 0x01);
1132}
1133
1134void Mips64Assembler::CmpEqS(FpuRegister fd, FpuRegister fs, FpuRegister ft) {
1135 EmitFR(0x11, 0x14, ft, fs, fd, 0x02);
1136}
1137
1138void Mips64Assembler::CmpUeqS(FpuRegister fd, FpuRegister fs, FpuRegister ft) {
1139 EmitFR(0x11, 0x14, ft, fs, fd, 0x03);
1140}
1141
1142void Mips64Assembler::CmpLtS(FpuRegister fd, FpuRegister fs, FpuRegister ft) {
1143 EmitFR(0x11, 0x14, ft, fs, fd, 0x04);
1144}
1145
1146void Mips64Assembler::CmpUltS(FpuRegister fd, FpuRegister fs, FpuRegister ft) {
1147 EmitFR(0x11, 0x14, ft, fs, fd, 0x05);
1148}
1149
1150void Mips64Assembler::CmpLeS(FpuRegister fd, FpuRegister fs, FpuRegister ft) {
1151 EmitFR(0x11, 0x14, ft, fs, fd, 0x06);
1152}
1153
1154void Mips64Assembler::CmpUleS(FpuRegister fd, FpuRegister fs, FpuRegister ft) {
1155 EmitFR(0x11, 0x14, ft, fs, fd, 0x07);
1156}
1157
1158void Mips64Assembler::CmpOrS(FpuRegister fd, FpuRegister fs, FpuRegister ft) {
1159 EmitFR(0x11, 0x14, ft, fs, fd, 0x11);
1160}
1161
1162void Mips64Assembler::CmpUneS(FpuRegister fd, FpuRegister fs, FpuRegister ft) {
1163 EmitFR(0x11, 0x14, ft, fs, fd, 0x12);
1164}
1165
1166void Mips64Assembler::CmpNeS(FpuRegister fd, FpuRegister fs, FpuRegister ft) {
1167 EmitFR(0x11, 0x14, ft, fs, fd, 0x13);
1168}
1169
1170void Mips64Assembler::CmpUnD(FpuRegister fd, FpuRegister fs, FpuRegister ft) {
1171 EmitFR(0x11, 0x15, ft, fs, fd, 0x01);
1172}
1173
1174void Mips64Assembler::CmpEqD(FpuRegister fd, FpuRegister fs, FpuRegister ft) {
1175 EmitFR(0x11, 0x15, ft, fs, fd, 0x02);
1176}
1177
1178void Mips64Assembler::CmpUeqD(FpuRegister fd, FpuRegister fs, FpuRegister ft) {
1179 EmitFR(0x11, 0x15, ft, fs, fd, 0x03);
1180}
1181
1182void Mips64Assembler::CmpLtD(FpuRegister fd, FpuRegister fs, FpuRegister ft) {
1183 EmitFR(0x11, 0x15, ft, fs, fd, 0x04);
1184}
1185
1186void Mips64Assembler::CmpUltD(FpuRegister fd, FpuRegister fs, FpuRegister ft) {
1187 EmitFR(0x11, 0x15, ft, fs, fd, 0x05);
1188}
1189
1190void Mips64Assembler::CmpLeD(FpuRegister fd, FpuRegister fs, FpuRegister ft) {
1191 EmitFR(0x11, 0x15, ft, fs, fd, 0x06);
1192}
1193
1194void Mips64Assembler::CmpUleD(FpuRegister fd, FpuRegister fs, FpuRegister ft) {
1195 EmitFR(0x11, 0x15, ft, fs, fd, 0x07);
1196}
1197
1198void Mips64Assembler::CmpOrD(FpuRegister fd, FpuRegister fs, FpuRegister ft) {
1199 EmitFR(0x11, 0x15, ft, fs, fd, 0x11);
1200}
1201
1202void Mips64Assembler::CmpUneD(FpuRegister fd, FpuRegister fs, FpuRegister ft) {
1203 EmitFR(0x11, 0x15, ft, fs, fd, 0x12);
1204}
1205
1206void Mips64Assembler::CmpNeD(FpuRegister fd, FpuRegister fs, FpuRegister ft) {
1207 EmitFR(0x11, 0x15, ft, fs, fd, 0x13);
1208}
1209
Alexey Frunze4dda3372015-06-01 18:31:49 -07001210void Mips64Assembler::Cvtsw(FpuRegister fd, FpuRegister fs) {
1211 EmitFR(0x11, 0x14, static_cast<FpuRegister>(0), fs, fd, 0x20);
1212}
1213
1214void Mips64Assembler::Cvtdw(FpuRegister fd, FpuRegister fs) {
1215 EmitFR(0x11, 0x14, static_cast<FpuRegister>(0), fs, fd, 0x21);
1216}
1217
1218void Mips64Assembler::Cvtsd(FpuRegister fd, FpuRegister fs) {
1219 EmitFR(0x11, 0x11, static_cast<FpuRegister>(0), fs, fd, 0x20);
1220}
1221
1222void Mips64Assembler::Cvtds(FpuRegister fd, FpuRegister fs) {
1223 EmitFR(0x11, 0x10, static_cast<FpuRegister>(0), fs, fd, 0x21);
Andreas Gampe57b34292015-01-14 15:45:59 -08001224}
1225
Chris Larsen51417632015-10-02 13:24:25 -07001226void Mips64Assembler::Cvtsl(FpuRegister fd, FpuRegister fs) {
1227 EmitFR(0x11, 0x15, static_cast<FpuRegister>(0), fs, fd, 0x20);
1228}
1229
Chris Larsen2fadd7b2015-08-14 14:56:10 -07001230void Mips64Assembler::Cvtdl(FpuRegister fd, FpuRegister fs) {
1231 EmitFR(0x11, 0x15, static_cast<FpuRegister>(0), fs, fd, 0x21);
1232}
1233
Andreas Gampe57b34292015-01-14 15:45:59 -08001234void Mips64Assembler::Mfc1(GpuRegister rt, FpuRegister fs) {
1235 EmitFR(0x11, 0x00, static_cast<FpuRegister>(rt), fs, static_cast<FpuRegister>(0), 0x0);
1236}
1237
Lazar Trsicd9672662015-09-03 17:33:01 +02001238void Mips64Assembler::Mfhc1(GpuRegister rt, FpuRegister fs) {
1239 EmitFR(0x11, 0x03, static_cast<FpuRegister>(rt), fs, static_cast<FpuRegister>(0), 0x0);
1240}
1241
Alexey Frunze4dda3372015-06-01 18:31:49 -07001242void Mips64Assembler::Mtc1(GpuRegister rt, FpuRegister fs) {
1243 EmitFR(0x11, 0x04, static_cast<FpuRegister>(rt), fs, static_cast<FpuRegister>(0), 0x0);
1244}
1245
Lazar Trsicd9672662015-09-03 17:33:01 +02001246void Mips64Assembler::Mthc1(GpuRegister rt, FpuRegister fs) {
1247 EmitFR(0x11, 0x07, static_cast<FpuRegister>(rt), fs, static_cast<FpuRegister>(0), 0x0);
1248}
1249
Alexey Frunze4dda3372015-06-01 18:31:49 -07001250void Mips64Assembler::Dmfc1(GpuRegister rt, FpuRegister fs) {
1251 EmitFR(0x11, 0x01, static_cast<FpuRegister>(rt), fs, static_cast<FpuRegister>(0), 0x0);
1252}
1253
1254void Mips64Assembler::Dmtc1(GpuRegister rt, FpuRegister fs) {
1255 EmitFR(0x11, 0x05, static_cast<FpuRegister>(rt), fs, static_cast<FpuRegister>(0), 0x0);
Andreas Gampe57b34292015-01-14 15:45:59 -08001256}
1257
1258void Mips64Assembler::Lwc1(FpuRegister ft, GpuRegister rs, uint16_t imm16) {
1259 EmitI(0x31, rs, static_cast<GpuRegister>(ft), imm16);
1260}
1261
1262void Mips64Assembler::Ldc1(FpuRegister ft, GpuRegister rs, uint16_t imm16) {
1263 EmitI(0x35, rs, static_cast<GpuRegister>(ft), imm16);
1264}
1265
1266void Mips64Assembler::Swc1(FpuRegister ft, GpuRegister rs, uint16_t imm16) {
1267 EmitI(0x39, rs, static_cast<GpuRegister>(ft), imm16);
1268}
1269
1270void Mips64Assembler::Sdc1(FpuRegister ft, GpuRegister rs, uint16_t imm16) {
1271 EmitI(0x3d, rs, static_cast<GpuRegister>(ft), imm16);
1272}
1273
1274void Mips64Assembler::Break() {
1275 EmitR(0, static_cast<GpuRegister>(0), static_cast<GpuRegister>(0),
1276 static_cast<GpuRegister>(0), 0, 0xD);
1277}
1278
1279void Mips64Assembler::Nop() {
1280 EmitR(0x0, static_cast<GpuRegister>(0), static_cast<GpuRegister>(0),
1281 static_cast<GpuRegister>(0), 0, 0x0);
1282}
1283
Alexey Frunze4dda3372015-06-01 18:31:49 -07001284void Mips64Assembler::Move(GpuRegister rd, GpuRegister rs) {
1285 Or(rd, rs, ZERO);
Andreas Gampe57b34292015-01-14 15:45:59 -08001286}
1287
Alexey Frunze4dda3372015-06-01 18:31:49 -07001288void Mips64Assembler::Clear(GpuRegister rd) {
1289 Move(rd, ZERO);
Andreas Gampe57b34292015-01-14 15:45:59 -08001290}
1291
Alexey Frunze4dda3372015-06-01 18:31:49 -07001292void Mips64Assembler::Not(GpuRegister rd, GpuRegister rs) {
1293 Nor(rd, rs, ZERO);
Andreas Gampe57b34292015-01-14 15:45:59 -08001294}
1295
Goran Jakovljevic5a9e51d2017-03-16 16:11:43 +00001296void Mips64Assembler::AndV(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
Goran Jakovljevic27af9372017-03-15 15:31:34 +01001297 CHECK(HasMsa());
Goran Jakovljevic5a9e51d2017-03-16 16:11:43 +00001298 EmitMsa3R(0x0, 0x0, wt, ws, wd, 0x1e);
1299}
1300
1301void Mips64Assembler::OrV(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
Goran Jakovljevic27af9372017-03-15 15:31:34 +01001302 CHECK(HasMsa());
Goran Jakovljevic5a9e51d2017-03-16 16:11:43 +00001303 EmitMsa3R(0x0, 0x1, wt, ws, wd, 0x1e);
1304}
1305
1306void Mips64Assembler::NorV(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
Goran Jakovljevic27af9372017-03-15 15:31:34 +01001307 CHECK(HasMsa());
Goran Jakovljevic5a9e51d2017-03-16 16:11:43 +00001308 EmitMsa3R(0x0, 0x2, wt, ws, wd, 0x1e);
1309}
1310
1311void Mips64Assembler::XorV(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
Goran Jakovljevic27af9372017-03-15 15:31:34 +01001312 CHECK(HasMsa());
Goran Jakovljevic5a9e51d2017-03-16 16:11:43 +00001313 EmitMsa3R(0x0, 0x3, wt, ws, wd, 0x1e);
1314}
1315
1316void Mips64Assembler::AddvB(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
Goran Jakovljevic27af9372017-03-15 15:31:34 +01001317 CHECK(HasMsa());
Goran Jakovljevic5a9e51d2017-03-16 16:11:43 +00001318 EmitMsa3R(0x0, 0x0, wt, ws, wd, 0xe);
1319}
1320
1321void Mips64Assembler::AddvH(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
Goran Jakovljevic27af9372017-03-15 15:31:34 +01001322 CHECK(HasMsa());
Goran Jakovljevic5a9e51d2017-03-16 16:11:43 +00001323 EmitMsa3R(0x0, 0x1, wt, ws, wd, 0xe);
1324}
1325
1326void Mips64Assembler::AddvW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
Goran Jakovljevic27af9372017-03-15 15:31:34 +01001327 CHECK(HasMsa());
Goran Jakovljevic5a9e51d2017-03-16 16:11:43 +00001328 EmitMsa3R(0x0, 0x2, wt, ws, wd, 0xe);
1329}
1330
1331void Mips64Assembler::AddvD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
Goran Jakovljevic27af9372017-03-15 15:31:34 +01001332 CHECK(HasMsa());
Goran Jakovljevic5a9e51d2017-03-16 16:11:43 +00001333 EmitMsa3R(0x0, 0x3, wt, ws, wd, 0xe);
1334}
1335
1336void Mips64Assembler::SubvB(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
Goran Jakovljevic27af9372017-03-15 15:31:34 +01001337 CHECK(HasMsa());
Goran Jakovljevic5a9e51d2017-03-16 16:11:43 +00001338 EmitMsa3R(0x1, 0x0, wt, ws, wd, 0xe);
1339}
1340
1341void Mips64Assembler::SubvH(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
Goran Jakovljevic27af9372017-03-15 15:31:34 +01001342 CHECK(HasMsa());
Goran Jakovljevic5a9e51d2017-03-16 16:11:43 +00001343 EmitMsa3R(0x1, 0x1, wt, ws, wd, 0xe);
1344}
1345
1346void Mips64Assembler::SubvW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
Goran Jakovljevic27af9372017-03-15 15:31:34 +01001347 CHECK(HasMsa());
Goran Jakovljevic5a9e51d2017-03-16 16:11:43 +00001348 EmitMsa3R(0x1, 0x2, wt, ws, wd, 0xe);
1349}
1350
1351void Mips64Assembler::SubvD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
Goran Jakovljevic27af9372017-03-15 15:31:34 +01001352 CHECK(HasMsa());
Goran Jakovljevic5a9e51d2017-03-16 16:11:43 +00001353 EmitMsa3R(0x1, 0x3, wt, ws, wd, 0xe);
1354}
1355
Lena Djokic72aba712017-10-30 15:47:20 +01001356void Mips64Assembler::Asub_sB(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
1357 CHECK(HasMsa());
1358 EmitMsa3R(0x4, 0x0, wt, ws, wd, 0x11);
1359}
1360
1361void Mips64Assembler::Asub_sH(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
1362 CHECK(HasMsa());
1363 EmitMsa3R(0x4, 0x1, wt, ws, wd, 0x11);
1364}
1365
1366void Mips64Assembler::Asub_sW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
1367 CHECK(HasMsa());
1368 EmitMsa3R(0x4, 0x2, wt, ws, wd, 0x11);
1369}
1370
1371void Mips64Assembler::Asub_sD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
1372 CHECK(HasMsa());
1373 EmitMsa3R(0x4, 0x3, wt, ws, wd, 0x11);
1374}
1375
1376void Mips64Assembler::Asub_uB(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
1377 CHECK(HasMsa());
1378 EmitMsa3R(0x5, 0x0, wt, ws, wd, 0x11);
1379}
1380
1381void Mips64Assembler::Asub_uH(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
1382 CHECK(HasMsa());
1383 EmitMsa3R(0x5, 0x1, wt, ws, wd, 0x11);
1384}
1385
1386void Mips64Assembler::Asub_uW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
1387 CHECK(HasMsa());
1388 EmitMsa3R(0x5, 0x2, wt, ws, wd, 0x11);
1389}
1390
1391void Mips64Assembler::Asub_uD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
1392 CHECK(HasMsa());
1393 EmitMsa3R(0x5, 0x3, wt, ws, wd, 0x11);
1394}
1395
Goran Jakovljevic5a9e51d2017-03-16 16:11:43 +00001396void Mips64Assembler::MulvB(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
Goran Jakovljevic27af9372017-03-15 15:31:34 +01001397 CHECK(HasMsa());
Goran Jakovljevic5a9e51d2017-03-16 16:11:43 +00001398 EmitMsa3R(0x0, 0x0, wt, ws, wd, 0x12);
1399}
1400
1401void Mips64Assembler::MulvH(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
Goran Jakovljevic27af9372017-03-15 15:31:34 +01001402 CHECK(HasMsa());
Goran Jakovljevic5a9e51d2017-03-16 16:11:43 +00001403 EmitMsa3R(0x0, 0x1, wt, ws, wd, 0x12);
1404}
1405
1406void Mips64Assembler::MulvW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
Goran Jakovljevic27af9372017-03-15 15:31:34 +01001407 CHECK(HasMsa());
Goran Jakovljevic5a9e51d2017-03-16 16:11:43 +00001408 EmitMsa3R(0x0, 0x2, wt, ws, wd, 0x12);
1409}
1410
1411void Mips64Assembler::MulvD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
Goran Jakovljevic27af9372017-03-15 15:31:34 +01001412 CHECK(HasMsa());
Goran Jakovljevic5a9e51d2017-03-16 16:11:43 +00001413 EmitMsa3R(0x0, 0x3, wt, ws, wd, 0x12);
1414}
1415
1416void Mips64Assembler::Div_sB(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
Goran Jakovljevic27af9372017-03-15 15:31:34 +01001417 CHECK(HasMsa());
Goran Jakovljevic5a9e51d2017-03-16 16:11:43 +00001418 EmitMsa3R(0x4, 0x0, wt, ws, wd, 0x12);
1419}
1420
1421void Mips64Assembler::Div_sH(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
Goran Jakovljevic27af9372017-03-15 15:31:34 +01001422 CHECK(HasMsa());
Goran Jakovljevic5a9e51d2017-03-16 16:11:43 +00001423 EmitMsa3R(0x4, 0x1, wt, ws, wd, 0x12);
1424}
1425
1426void Mips64Assembler::Div_sW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
Goran Jakovljevic27af9372017-03-15 15:31:34 +01001427 CHECK(HasMsa());
Goran Jakovljevic5a9e51d2017-03-16 16:11:43 +00001428 EmitMsa3R(0x4, 0x2, wt, ws, wd, 0x12);
1429}
1430
1431void Mips64Assembler::Div_sD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
Goran Jakovljevic27af9372017-03-15 15:31:34 +01001432 CHECK(HasMsa());
Goran Jakovljevic5a9e51d2017-03-16 16:11:43 +00001433 EmitMsa3R(0x4, 0x3, wt, ws, wd, 0x12);
1434}
1435
1436void Mips64Assembler::Div_uB(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
Goran Jakovljevic27af9372017-03-15 15:31:34 +01001437 CHECK(HasMsa());
Goran Jakovljevic5a9e51d2017-03-16 16:11:43 +00001438 EmitMsa3R(0x5, 0x0, wt, ws, wd, 0x12);
1439}
1440
1441void Mips64Assembler::Div_uH(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
Goran Jakovljevic27af9372017-03-15 15:31:34 +01001442 CHECK(HasMsa());
Goran Jakovljevic5a9e51d2017-03-16 16:11:43 +00001443 EmitMsa3R(0x5, 0x1, wt, ws, wd, 0x12);
1444}
1445
1446void Mips64Assembler::Div_uW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
Goran Jakovljevic27af9372017-03-15 15:31:34 +01001447 CHECK(HasMsa());
Goran Jakovljevic5a9e51d2017-03-16 16:11:43 +00001448 EmitMsa3R(0x5, 0x2, wt, ws, wd, 0x12);
1449}
1450
1451void Mips64Assembler::Div_uD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
Goran Jakovljevic27af9372017-03-15 15:31:34 +01001452 CHECK(HasMsa());
Goran Jakovljevic5a9e51d2017-03-16 16:11:43 +00001453 EmitMsa3R(0x5, 0x3, wt, ws, wd, 0x12);
1454}
1455
1456void Mips64Assembler::Mod_sB(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
Goran Jakovljevic27af9372017-03-15 15:31:34 +01001457 CHECK(HasMsa());
Goran Jakovljevic5a9e51d2017-03-16 16:11:43 +00001458 EmitMsa3R(0x6, 0x0, wt, ws, wd, 0x12);
1459}
1460
1461void Mips64Assembler::Mod_sH(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
Goran Jakovljevic27af9372017-03-15 15:31:34 +01001462 CHECK(HasMsa());
Goran Jakovljevic5a9e51d2017-03-16 16:11:43 +00001463 EmitMsa3R(0x6, 0x1, wt, ws, wd, 0x12);
1464}
1465
1466void Mips64Assembler::Mod_sW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
Goran Jakovljevic27af9372017-03-15 15:31:34 +01001467 CHECK(HasMsa());
Goran Jakovljevic5a9e51d2017-03-16 16:11:43 +00001468 EmitMsa3R(0x6, 0x2, wt, ws, wd, 0x12);
1469}
1470
1471void Mips64Assembler::Mod_sD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
Goran Jakovljevic27af9372017-03-15 15:31:34 +01001472 CHECK(HasMsa());
Goran Jakovljevic5a9e51d2017-03-16 16:11:43 +00001473 EmitMsa3R(0x6, 0x3, wt, ws, wd, 0x12);
1474}
1475
1476void Mips64Assembler::Mod_uB(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
Goran Jakovljevic27af9372017-03-15 15:31:34 +01001477 CHECK(HasMsa());
Goran Jakovljevic5a9e51d2017-03-16 16:11:43 +00001478 EmitMsa3R(0x7, 0x0, wt, ws, wd, 0x12);
1479}
1480
1481void Mips64Assembler::Mod_uH(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
Goran Jakovljevic27af9372017-03-15 15:31:34 +01001482 CHECK(HasMsa());
Goran Jakovljevic5a9e51d2017-03-16 16:11:43 +00001483 EmitMsa3R(0x7, 0x1, wt, ws, wd, 0x12);
1484}
1485
1486void Mips64Assembler::Mod_uW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
Goran Jakovljevic27af9372017-03-15 15:31:34 +01001487 CHECK(HasMsa());
Goran Jakovljevic5a9e51d2017-03-16 16:11:43 +00001488 EmitMsa3R(0x7, 0x2, wt, ws, wd, 0x12);
1489}
1490
1491void Mips64Assembler::Mod_uD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
Goran Jakovljevic27af9372017-03-15 15:31:34 +01001492 CHECK(HasMsa());
Goran Jakovljevic5a9e51d2017-03-16 16:11:43 +00001493 EmitMsa3R(0x7, 0x3, wt, ws, wd, 0x12);
1494}
1495
Goran Jakovljevic80248d72017-04-20 11:55:47 +02001496void Mips64Assembler::Add_aB(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
1497 CHECK(HasMsa());
1498 EmitMsa3R(0x0, 0x0, wt, ws, wd, 0x10);
1499}
1500
1501void Mips64Assembler::Add_aH(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
1502 CHECK(HasMsa());
1503 EmitMsa3R(0x0, 0x1, wt, ws, wd, 0x10);
1504}
1505
1506void Mips64Assembler::Add_aW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
1507 CHECK(HasMsa());
1508 EmitMsa3R(0x0, 0x2, wt, ws, wd, 0x10);
1509}
1510
1511void Mips64Assembler::Add_aD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
1512 CHECK(HasMsa());
1513 EmitMsa3R(0x0, 0x3, wt, ws, wd, 0x10);
1514}
1515
1516void Mips64Assembler::Ave_sB(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
1517 CHECK(HasMsa());
1518 EmitMsa3R(0x4, 0x0, wt, ws, wd, 0x10);
1519}
1520
1521void Mips64Assembler::Ave_sH(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
1522 CHECK(HasMsa());
1523 EmitMsa3R(0x4, 0x1, wt, ws, wd, 0x10);
1524}
1525
1526void Mips64Assembler::Ave_sW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
1527 CHECK(HasMsa());
1528 EmitMsa3R(0x4, 0x2, wt, ws, wd, 0x10);
1529}
1530
1531void Mips64Assembler::Ave_sD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
1532 CHECK(HasMsa());
1533 EmitMsa3R(0x4, 0x3, wt, ws, wd, 0x10);
1534}
1535
1536void Mips64Assembler::Ave_uB(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
1537 CHECK(HasMsa());
1538 EmitMsa3R(0x5, 0x0, wt, ws, wd, 0x10);
1539}
1540
1541void Mips64Assembler::Ave_uH(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
1542 CHECK(HasMsa());
1543 EmitMsa3R(0x5, 0x1, wt, ws, wd, 0x10);
1544}
1545
1546void Mips64Assembler::Ave_uW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
1547 CHECK(HasMsa());
1548 EmitMsa3R(0x5, 0x2, wt, ws, wd, 0x10);
1549}
1550
1551void Mips64Assembler::Ave_uD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
1552 CHECK(HasMsa());
1553 EmitMsa3R(0x5, 0x3, wt, ws, wd, 0x10);
1554}
1555
1556void Mips64Assembler::Aver_sB(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
1557 CHECK(HasMsa());
1558 EmitMsa3R(0x6, 0x0, wt, ws, wd, 0x10);
1559}
1560
1561void Mips64Assembler::Aver_sH(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
1562 CHECK(HasMsa());
1563 EmitMsa3R(0x6, 0x1, wt, ws, wd, 0x10);
1564}
1565
1566void Mips64Assembler::Aver_sW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
1567 CHECK(HasMsa());
1568 EmitMsa3R(0x6, 0x2, wt, ws, wd, 0x10);
1569}
1570
1571void Mips64Assembler::Aver_sD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
1572 CHECK(HasMsa());
1573 EmitMsa3R(0x6, 0x3, wt, ws, wd, 0x10);
1574}
1575
1576void Mips64Assembler::Aver_uB(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
1577 CHECK(HasMsa());
1578 EmitMsa3R(0x7, 0x0, wt, ws, wd, 0x10);
1579}
1580
1581void Mips64Assembler::Aver_uH(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
1582 CHECK(HasMsa());
1583 EmitMsa3R(0x7, 0x1, wt, ws, wd, 0x10);
1584}
1585
1586void Mips64Assembler::Aver_uW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
1587 CHECK(HasMsa());
1588 EmitMsa3R(0x7, 0x2, wt, ws, wd, 0x10);
1589}
1590
1591void Mips64Assembler::Aver_uD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
1592 CHECK(HasMsa());
1593 EmitMsa3R(0x7, 0x3, wt, ws, wd, 0x10);
1594}
1595
Goran Jakovljevic658263e2017-06-07 09:35:53 +02001596void Mips64Assembler::Max_sB(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
1597 CHECK(HasMsa());
1598 EmitMsa3R(0x2, 0x0, wt, ws, wd, 0xe);
1599}
1600
1601void Mips64Assembler::Max_sH(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
1602 CHECK(HasMsa());
1603 EmitMsa3R(0x2, 0x1, wt, ws, wd, 0xe);
1604}
1605
1606void Mips64Assembler::Max_sW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
1607 CHECK(HasMsa());
1608 EmitMsa3R(0x2, 0x2, wt, ws, wd, 0xe);
1609}
1610
1611void Mips64Assembler::Max_sD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
1612 CHECK(HasMsa());
1613 EmitMsa3R(0x2, 0x3, wt, ws, wd, 0xe);
1614}
1615
1616void Mips64Assembler::Max_uB(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
1617 CHECK(HasMsa());
1618 EmitMsa3R(0x3, 0x0, wt, ws, wd, 0xe);
1619}
1620
1621void Mips64Assembler::Max_uH(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
1622 CHECK(HasMsa());
1623 EmitMsa3R(0x3, 0x1, wt, ws, wd, 0xe);
1624}
1625
1626void Mips64Assembler::Max_uW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
1627 CHECK(HasMsa());
1628 EmitMsa3R(0x3, 0x2, wt, ws, wd, 0xe);
1629}
1630
1631void Mips64Assembler::Max_uD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
1632 CHECK(HasMsa());
1633 EmitMsa3R(0x3, 0x3, wt, ws, wd, 0xe);
1634}
1635
1636void Mips64Assembler::Min_sB(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
1637 CHECK(HasMsa());
1638 EmitMsa3R(0x4, 0x0, wt, ws, wd, 0xe);
1639}
1640
1641void Mips64Assembler::Min_sH(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
1642 CHECK(HasMsa());
1643 EmitMsa3R(0x4, 0x1, wt, ws, wd, 0xe);
1644}
1645
1646void Mips64Assembler::Min_sW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
1647 CHECK(HasMsa());
1648 EmitMsa3R(0x4, 0x2, wt, ws, wd, 0xe);
1649}
1650
1651void Mips64Assembler::Min_sD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
1652 CHECK(HasMsa());
1653 EmitMsa3R(0x4, 0x3, wt, ws, wd, 0xe);
1654}
1655
1656void Mips64Assembler::Min_uB(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
1657 CHECK(HasMsa());
1658 EmitMsa3R(0x5, 0x0, wt, ws, wd, 0xe);
1659}
1660
1661void Mips64Assembler::Min_uH(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
1662 CHECK(HasMsa());
1663 EmitMsa3R(0x5, 0x1, wt, ws, wd, 0xe);
1664}
1665
1666void Mips64Assembler::Min_uW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
1667 CHECK(HasMsa());
1668 EmitMsa3R(0x5, 0x2, wt, ws, wd, 0xe);
1669}
1670
1671void Mips64Assembler::Min_uD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
1672 CHECK(HasMsa());
1673 EmitMsa3R(0x5, 0x3, wt, ws, wd, 0xe);
1674}
1675
Goran Jakovljevic5a9e51d2017-03-16 16:11:43 +00001676void Mips64Assembler::FaddW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
Goran Jakovljevic27af9372017-03-15 15:31:34 +01001677 CHECK(HasMsa());
Goran Jakovljevic5a9e51d2017-03-16 16:11:43 +00001678 EmitMsa3R(0x0, 0x0, wt, ws, wd, 0x1b);
1679}
1680
1681void Mips64Assembler::FaddD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
Goran Jakovljevic27af9372017-03-15 15:31:34 +01001682 CHECK(HasMsa());
Goran Jakovljevic5a9e51d2017-03-16 16:11:43 +00001683 EmitMsa3R(0x0, 0x1, wt, ws, wd, 0x1b);
1684}
1685
1686void Mips64Assembler::FsubW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
Goran Jakovljevic27af9372017-03-15 15:31:34 +01001687 CHECK(HasMsa());
Goran Jakovljevic5a9e51d2017-03-16 16:11:43 +00001688 EmitMsa3R(0x0, 0x2, wt, ws, wd, 0x1b);
1689}
1690
1691void Mips64Assembler::FsubD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
Goran Jakovljevic27af9372017-03-15 15:31:34 +01001692 CHECK(HasMsa());
Goran Jakovljevic5a9e51d2017-03-16 16:11:43 +00001693 EmitMsa3R(0x0, 0x3, wt, ws, wd, 0x1b);
1694}
1695
1696void Mips64Assembler::FmulW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
Goran Jakovljevic27af9372017-03-15 15:31:34 +01001697 CHECK(HasMsa());
Goran Jakovljevic5a9e51d2017-03-16 16:11:43 +00001698 EmitMsa3R(0x1, 0x0, wt, ws, wd, 0x1b);
1699}
1700
1701void Mips64Assembler::FmulD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
Goran Jakovljevic27af9372017-03-15 15:31:34 +01001702 CHECK(HasMsa());
Goran Jakovljevic5a9e51d2017-03-16 16:11:43 +00001703 EmitMsa3R(0x1, 0x1, wt, ws, wd, 0x1b);
1704}
1705
1706void Mips64Assembler::FdivW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
Goran Jakovljevic27af9372017-03-15 15:31:34 +01001707 CHECK(HasMsa());
Goran Jakovljevic5a9e51d2017-03-16 16:11:43 +00001708 EmitMsa3R(0x1, 0x2, wt, ws, wd, 0x1b);
1709}
1710
1711void Mips64Assembler::FdivD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
Goran Jakovljevic27af9372017-03-15 15:31:34 +01001712 CHECK(HasMsa());
Goran Jakovljevic5a9e51d2017-03-16 16:11:43 +00001713 EmitMsa3R(0x1, 0x3, wt, ws, wd, 0x1b);
1714}
1715
Goran Jakovljevic658263e2017-06-07 09:35:53 +02001716void Mips64Assembler::FmaxW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
1717 CHECK(HasMsa());
1718 EmitMsa3R(0x7, 0x0, wt, ws, wd, 0x1b);
1719}
1720
1721void Mips64Assembler::FmaxD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
1722 CHECK(HasMsa());
1723 EmitMsa3R(0x7, 0x1, wt, ws, wd, 0x1b);
1724}
1725
1726void Mips64Assembler::FminW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
1727 CHECK(HasMsa());
1728 EmitMsa3R(0x6, 0x0, wt, ws, wd, 0x1b);
1729}
1730
1731void Mips64Assembler::FminD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
1732 CHECK(HasMsa());
1733 EmitMsa3R(0x6, 0x1, wt, ws, wd, 0x1b);
1734}
1735
Goran Jakovljevic5a9e51d2017-03-16 16:11:43 +00001736void Mips64Assembler::Ffint_sW(VectorRegister wd, VectorRegister ws) {
Goran Jakovljevic27af9372017-03-15 15:31:34 +01001737 CHECK(HasMsa());
Goran Jakovljevic5a9e51d2017-03-16 16:11:43 +00001738 EmitMsa2RF(0x19e, 0x0, ws, wd, 0x1e);
1739}
1740
1741void Mips64Assembler::Ffint_sD(VectorRegister wd, VectorRegister ws) {
Goran Jakovljevic27af9372017-03-15 15:31:34 +01001742 CHECK(HasMsa());
Goran Jakovljevic5a9e51d2017-03-16 16:11:43 +00001743 EmitMsa2RF(0x19e, 0x1, ws, wd, 0x1e);
1744}
1745
1746void Mips64Assembler::Ftint_sW(VectorRegister wd, VectorRegister ws) {
Goran Jakovljevic27af9372017-03-15 15:31:34 +01001747 CHECK(HasMsa());
Goran Jakovljevic5a9e51d2017-03-16 16:11:43 +00001748 EmitMsa2RF(0x19c, 0x0, ws, wd, 0x1e);
1749}
1750
1751void Mips64Assembler::Ftint_sD(VectorRegister wd, VectorRegister ws) {
Goran Jakovljevic27af9372017-03-15 15:31:34 +01001752 CHECK(HasMsa());
Goran Jakovljevic5a9e51d2017-03-16 16:11:43 +00001753 EmitMsa2RF(0x19c, 0x1, ws, wd, 0x1e);
1754}
1755
1756void Mips64Assembler::SllB(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
Goran Jakovljevic27af9372017-03-15 15:31:34 +01001757 CHECK(HasMsa());
Goran Jakovljevic5a9e51d2017-03-16 16:11:43 +00001758 EmitMsa3R(0x0, 0x0, wt, ws, wd, 0xd);
1759}
1760
1761void Mips64Assembler::SllH(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
Goran Jakovljevic27af9372017-03-15 15:31:34 +01001762 CHECK(HasMsa());
Goran Jakovljevic5a9e51d2017-03-16 16:11:43 +00001763 EmitMsa3R(0x0, 0x1, wt, ws, wd, 0xd);
1764}
1765
1766void Mips64Assembler::SllW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
Goran Jakovljevic27af9372017-03-15 15:31:34 +01001767 CHECK(HasMsa());
Goran Jakovljevic5a9e51d2017-03-16 16:11:43 +00001768 EmitMsa3R(0x0, 0x2, wt, ws, wd, 0xd);
1769}
1770
1771void Mips64Assembler::SllD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
Goran Jakovljevic27af9372017-03-15 15:31:34 +01001772 CHECK(HasMsa());
Goran Jakovljevic5a9e51d2017-03-16 16:11:43 +00001773 EmitMsa3R(0x0, 0x3, wt, ws, wd, 0xd);
1774}
1775
1776void Mips64Assembler::SraB(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
Goran Jakovljevic27af9372017-03-15 15:31:34 +01001777 CHECK(HasMsa());
Goran Jakovljevic5a9e51d2017-03-16 16:11:43 +00001778 EmitMsa3R(0x1, 0x0, wt, ws, wd, 0xd);
1779}
1780
1781void Mips64Assembler::SraH(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
Goran Jakovljevic27af9372017-03-15 15:31:34 +01001782 CHECK(HasMsa());
Goran Jakovljevic5a9e51d2017-03-16 16:11:43 +00001783 EmitMsa3R(0x1, 0x1, wt, ws, wd, 0xd);
1784}
1785
1786void Mips64Assembler::SraW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
Goran Jakovljevic27af9372017-03-15 15:31:34 +01001787 CHECK(HasMsa());
Goran Jakovljevic5a9e51d2017-03-16 16:11:43 +00001788 EmitMsa3R(0x1, 0x2, wt, ws, wd, 0xd);
1789}
1790
1791void Mips64Assembler::SraD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
Goran Jakovljevic27af9372017-03-15 15:31:34 +01001792 CHECK(HasMsa());
Goran Jakovljevic5a9e51d2017-03-16 16:11:43 +00001793 EmitMsa3R(0x1, 0x3, wt, ws, wd, 0xd);
1794}
1795
1796void Mips64Assembler::SrlB(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
Goran Jakovljevic27af9372017-03-15 15:31:34 +01001797 CHECK(HasMsa());
Goran Jakovljevic5a9e51d2017-03-16 16:11:43 +00001798 EmitMsa3R(0x2, 0x0, wt, ws, wd, 0xd);
1799}
1800
1801void Mips64Assembler::SrlH(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
Goran Jakovljevic27af9372017-03-15 15:31:34 +01001802 CHECK(HasMsa());
Goran Jakovljevic5a9e51d2017-03-16 16:11:43 +00001803 EmitMsa3R(0x2, 0x1, wt, ws, wd, 0xd);
1804}
1805
1806void Mips64Assembler::SrlW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
Goran Jakovljevic27af9372017-03-15 15:31:34 +01001807 CHECK(HasMsa());
Goran Jakovljevic5a9e51d2017-03-16 16:11:43 +00001808 EmitMsa3R(0x2, 0x2, wt, ws, wd, 0xd);
1809}
1810
1811void Mips64Assembler::SrlD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
Goran Jakovljevic27af9372017-03-15 15:31:34 +01001812 CHECK(HasMsa());
Goran Jakovljevic5a9e51d2017-03-16 16:11:43 +00001813 EmitMsa3R(0x2, 0x3, wt, ws, wd, 0xd);
1814}
1815
1816void Mips64Assembler::SlliB(VectorRegister wd, VectorRegister ws, int shamt3) {
Goran Jakovljevic27af9372017-03-15 15:31:34 +01001817 CHECK(HasMsa());
Goran Jakovljevic5a9e51d2017-03-16 16:11:43 +00001818 CHECK(IsUint<3>(shamt3)) << shamt3;
1819 EmitMsaBIT(0x0, shamt3 | kMsaDfMByteMask, ws, wd, 0x9);
1820}
1821
1822void Mips64Assembler::SlliH(VectorRegister wd, VectorRegister ws, int shamt4) {
Goran Jakovljevic27af9372017-03-15 15:31:34 +01001823 CHECK(HasMsa());
Goran Jakovljevic5a9e51d2017-03-16 16:11:43 +00001824 CHECK(IsUint<4>(shamt4)) << shamt4;
1825 EmitMsaBIT(0x0, shamt4 | kMsaDfMHalfwordMask, ws, wd, 0x9);
1826}
1827
1828void Mips64Assembler::SlliW(VectorRegister wd, VectorRegister ws, int shamt5) {
Goran Jakovljevic27af9372017-03-15 15:31:34 +01001829 CHECK(HasMsa());
Goran Jakovljevic5a9e51d2017-03-16 16:11:43 +00001830 CHECK(IsUint<5>(shamt5)) << shamt5;
1831 EmitMsaBIT(0x0, shamt5 | kMsaDfMWordMask, ws, wd, 0x9);
1832}
1833
1834void Mips64Assembler::SlliD(VectorRegister wd, VectorRegister ws, int shamt6) {
Goran Jakovljevic27af9372017-03-15 15:31:34 +01001835 CHECK(HasMsa());
Goran Jakovljevic5a9e51d2017-03-16 16:11:43 +00001836 CHECK(IsUint<6>(shamt6)) << shamt6;
1837 EmitMsaBIT(0x0, shamt6 | kMsaDfMDoublewordMask, ws, wd, 0x9);
1838}
1839
1840void Mips64Assembler::SraiB(VectorRegister wd, VectorRegister ws, int shamt3) {
Goran Jakovljevic27af9372017-03-15 15:31:34 +01001841 CHECK(HasMsa());
Goran Jakovljevic5a9e51d2017-03-16 16:11:43 +00001842 CHECK(IsUint<3>(shamt3)) << shamt3;
1843 EmitMsaBIT(0x1, shamt3 | kMsaDfMByteMask, ws, wd, 0x9);
1844}
1845
1846void Mips64Assembler::SraiH(VectorRegister wd, VectorRegister ws, int shamt4) {
Goran Jakovljevic27af9372017-03-15 15:31:34 +01001847 CHECK(HasMsa());
Goran Jakovljevic5a9e51d2017-03-16 16:11:43 +00001848 CHECK(IsUint<4>(shamt4)) << shamt4;
1849 EmitMsaBIT(0x1, shamt4 | kMsaDfMHalfwordMask, ws, wd, 0x9);
1850}
1851
1852void Mips64Assembler::SraiW(VectorRegister wd, VectorRegister ws, int shamt5) {
Goran Jakovljevic27af9372017-03-15 15:31:34 +01001853 CHECK(HasMsa());
Goran Jakovljevic5a9e51d2017-03-16 16:11:43 +00001854 CHECK(IsUint<5>(shamt5)) << shamt5;
1855 EmitMsaBIT(0x1, shamt5 | kMsaDfMWordMask, ws, wd, 0x9);
1856}
1857
1858void Mips64Assembler::SraiD(VectorRegister wd, VectorRegister ws, int shamt6) {
Goran Jakovljevic27af9372017-03-15 15:31:34 +01001859 CHECK(HasMsa());
Goran Jakovljevic5a9e51d2017-03-16 16:11:43 +00001860 CHECK(IsUint<6>(shamt6)) << shamt6;
1861 EmitMsaBIT(0x1, shamt6 | kMsaDfMDoublewordMask, ws, wd, 0x9);
1862}
1863
1864void Mips64Assembler::SrliB(VectorRegister wd, VectorRegister ws, int shamt3) {
Goran Jakovljevic27af9372017-03-15 15:31:34 +01001865 CHECK(HasMsa());
Goran Jakovljevic5a9e51d2017-03-16 16:11:43 +00001866 CHECK(IsUint<3>(shamt3)) << shamt3;
1867 EmitMsaBIT(0x2, shamt3 | kMsaDfMByteMask, ws, wd, 0x9);
1868}
1869
1870void Mips64Assembler::SrliH(VectorRegister wd, VectorRegister ws, int shamt4) {
Goran Jakovljevic27af9372017-03-15 15:31:34 +01001871 CHECK(HasMsa());
Goran Jakovljevic5a9e51d2017-03-16 16:11:43 +00001872 CHECK(IsUint<4>(shamt4)) << shamt4;
1873 EmitMsaBIT(0x2, shamt4 | kMsaDfMHalfwordMask, ws, wd, 0x9);
1874}
1875
1876void Mips64Assembler::SrliW(VectorRegister wd, VectorRegister ws, int shamt5) {
Goran Jakovljevic27af9372017-03-15 15:31:34 +01001877 CHECK(HasMsa());
Goran Jakovljevic5a9e51d2017-03-16 16:11:43 +00001878 CHECK(IsUint<5>(shamt5)) << shamt5;
1879 EmitMsaBIT(0x2, shamt5 | kMsaDfMWordMask, ws, wd, 0x9);
1880}
1881
1882void Mips64Assembler::SrliD(VectorRegister wd, VectorRegister ws, int shamt6) {
Goran Jakovljevic27af9372017-03-15 15:31:34 +01001883 CHECK(HasMsa());
Goran Jakovljevic5a9e51d2017-03-16 16:11:43 +00001884 CHECK(IsUint<6>(shamt6)) << shamt6;
1885 EmitMsaBIT(0x2, shamt6 | kMsaDfMDoublewordMask, ws, wd, 0x9);
1886}
1887
1888void Mips64Assembler::MoveV(VectorRegister wd, VectorRegister ws) {
Goran Jakovljevic27af9372017-03-15 15:31:34 +01001889 CHECK(HasMsa());
Goran Jakovljevic5a9e51d2017-03-16 16:11:43 +00001890 EmitMsaBIT(0x1, 0x3e, ws, wd, 0x19);
1891}
1892
1893void Mips64Assembler::SplatiB(VectorRegister wd, VectorRegister ws, int n4) {
Goran Jakovljevic27af9372017-03-15 15:31:34 +01001894 CHECK(HasMsa());
Goran Jakovljevic5a9e51d2017-03-16 16:11:43 +00001895 CHECK(IsUint<4>(n4)) << n4;
1896 EmitMsaELM(0x1, n4 | kMsaDfNByteMask, ws, wd, 0x19);
1897}
1898
1899void Mips64Assembler::SplatiH(VectorRegister wd, VectorRegister ws, int n3) {
Goran Jakovljevic27af9372017-03-15 15:31:34 +01001900 CHECK(HasMsa());
Goran Jakovljevic5a9e51d2017-03-16 16:11:43 +00001901 CHECK(IsUint<3>(n3)) << n3;
1902 EmitMsaELM(0x1, n3 | kMsaDfNHalfwordMask, ws, wd, 0x19);
1903}
1904
1905void Mips64Assembler::SplatiW(VectorRegister wd, VectorRegister ws, int n2) {
Goran Jakovljevic27af9372017-03-15 15:31:34 +01001906 CHECK(HasMsa());
Goran Jakovljevic5a9e51d2017-03-16 16:11:43 +00001907 CHECK(IsUint<2>(n2)) << n2;
1908 EmitMsaELM(0x1, n2 | kMsaDfNWordMask, ws, wd, 0x19);
1909}
1910
1911void Mips64Assembler::SplatiD(VectorRegister wd, VectorRegister ws, int n1) {
Goran Jakovljevic27af9372017-03-15 15:31:34 +01001912 CHECK(HasMsa());
Goran Jakovljevic5a9e51d2017-03-16 16:11:43 +00001913 CHECK(IsUint<1>(n1)) << n1;
1914 EmitMsaELM(0x1, n1 | kMsaDfNDoublewordMask, ws, wd, 0x19);
1915}
1916
Lena Djokic3309c012017-10-13 14:34:32 +02001917void Mips64Assembler::Copy_sB(GpuRegister rd, VectorRegister ws, int n4) {
1918 CHECK(HasMsa());
1919 CHECK(IsUint<4>(n4)) << n4;
1920 EmitMsaELM(0x2, n4 | kMsaDfNByteMask, ws, static_cast<VectorRegister>(rd), 0x19);
1921}
1922
1923void Mips64Assembler::Copy_sH(GpuRegister rd, VectorRegister ws, int n3) {
1924 CHECK(HasMsa());
1925 CHECK(IsUint<3>(n3)) << n3;
1926 EmitMsaELM(0x2, n3 | kMsaDfNHalfwordMask, ws, static_cast<VectorRegister>(rd), 0x19);
1927}
1928
1929void Mips64Assembler::Copy_sW(GpuRegister rd, VectorRegister ws, int n2) {
1930 CHECK(HasMsa());
1931 CHECK(IsUint<2>(n2)) << n2;
1932 EmitMsaELM(0x2, n2 | kMsaDfNWordMask, ws, static_cast<VectorRegister>(rd), 0x19);
1933}
1934
1935void Mips64Assembler::Copy_sD(GpuRegister rd, VectorRegister ws, int n1) {
1936 CHECK(HasMsa());
1937 CHECK(IsUint<1>(n1)) << n1;
1938 EmitMsaELM(0x2, n1 | kMsaDfNDoublewordMask, ws, static_cast<VectorRegister>(rd), 0x19);
1939}
1940
1941void Mips64Assembler::Copy_uB(GpuRegister rd, VectorRegister ws, int n4) {
1942 CHECK(HasMsa());
1943 CHECK(IsUint<4>(n4)) << n4;
1944 EmitMsaELM(0x3, n4 | kMsaDfNByteMask, ws, static_cast<VectorRegister>(rd), 0x19);
1945}
1946
1947void Mips64Assembler::Copy_uH(GpuRegister rd, VectorRegister ws, int n3) {
1948 CHECK(HasMsa());
1949 CHECK(IsUint<3>(n3)) << n3;
1950 EmitMsaELM(0x3, n3 | kMsaDfNHalfwordMask, ws, static_cast<VectorRegister>(rd), 0x19);
1951}
1952
1953void Mips64Assembler::Copy_uW(GpuRegister rd, VectorRegister ws, int n2) {
1954 CHECK(HasMsa());
1955 CHECK(IsUint<2>(n2)) << n2;
1956 EmitMsaELM(0x3, n2 | kMsaDfNWordMask, ws, static_cast<VectorRegister>(rd), 0x19);
1957}
1958
1959void Mips64Assembler::InsertB(VectorRegister wd, GpuRegister rs, int n4) {
1960 CHECK(HasMsa());
1961 CHECK(IsUint<4>(n4)) << n4;
1962 EmitMsaELM(0x4, n4 | kMsaDfNByteMask, static_cast<VectorRegister>(rs), wd, 0x19);
1963}
1964
1965void Mips64Assembler::InsertH(VectorRegister wd, GpuRegister rs, int n3) {
1966 CHECK(HasMsa());
1967 CHECK(IsUint<3>(n3)) << n3;
1968 EmitMsaELM(0x4, n3 | kMsaDfNHalfwordMask, static_cast<VectorRegister>(rs), wd, 0x19);
1969}
1970
1971void Mips64Assembler::InsertW(VectorRegister wd, GpuRegister rs, int n2) {
1972 CHECK(HasMsa());
1973 CHECK(IsUint<2>(n2)) << n2;
1974 EmitMsaELM(0x4, n2 | kMsaDfNWordMask, static_cast<VectorRegister>(rs), wd, 0x19);
1975}
1976
1977void Mips64Assembler::InsertD(VectorRegister wd, GpuRegister rs, int n1) {
1978 CHECK(HasMsa());
1979 CHECK(IsUint<1>(n1)) << n1;
1980 EmitMsaELM(0x4, n1 | kMsaDfNDoublewordMask, static_cast<VectorRegister>(rs), wd, 0x19);
1981}
1982
Goran Jakovljevic5a9e51d2017-03-16 16:11:43 +00001983void Mips64Assembler::FillB(VectorRegister wd, GpuRegister rs) {
Goran Jakovljevic27af9372017-03-15 15:31:34 +01001984 CHECK(HasMsa());
Goran Jakovljevic5a9e51d2017-03-16 16:11:43 +00001985 EmitMsa2R(0xc0, 0x0, static_cast<VectorRegister>(rs), wd, 0x1e);
1986}
1987
1988void Mips64Assembler::FillH(VectorRegister wd, GpuRegister rs) {
Goran Jakovljevic27af9372017-03-15 15:31:34 +01001989 CHECK(HasMsa());
Goran Jakovljevic5a9e51d2017-03-16 16:11:43 +00001990 EmitMsa2R(0xc0, 0x1, static_cast<VectorRegister>(rs), wd, 0x1e);
1991}
1992
1993void Mips64Assembler::FillW(VectorRegister wd, GpuRegister rs) {
Goran Jakovljevic27af9372017-03-15 15:31:34 +01001994 CHECK(HasMsa());
Goran Jakovljevic5a9e51d2017-03-16 16:11:43 +00001995 EmitMsa2R(0xc0, 0x2, static_cast<VectorRegister>(rs), wd, 0x1e);
1996}
1997
1998void Mips64Assembler::FillD(VectorRegister wd, GpuRegister rs) {
Goran Jakovljevic27af9372017-03-15 15:31:34 +01001999 CHECK(HasMsa());
Goran Jakovljevic5a9e51d2017-03-16 16:11:43 +00002000 EmitMsa2R(0xc0, 0x3, static_cast<VectorRegister>(rs), wd, 0x1e);
2001}
2002
Goran Jakovljevic3f444032017-03-31 14:38:20 +02002003void Mips64Assembler::LdiB(VectorRegister wd, int imm8) {
2004 CHECK(HasMsa());
2005 CHECK(IsInt<8>(imm8)) << imm8;
2006 EmitMsaI10(0x6, 0x0, imm8 & kMsaS10Mask, wd, 0x7);
2007}
2008
2009void Mips64Assembler::LdiH(VectorRegister wd, int imm10) {
2010 CHECK(HasMsa());
2011 CHECK(IsInt<10>(imm10)) << imm10;
2012 EmitMsaI10(0x6, 0x1, imm10 & kMsaS10Mask, wd, 0x7);
2013}
2014
2015void Mips64Assembler::LdiW(VectorRegister wd, int imm10) {
2016 CHECK(HasMsa());
2017 CHECK(IsInt<10>(imm10)) << imm10;
2018 EmitMsaI10(0x6, 0x2, imm10 & kMsaS10Mask, wd, 0x7);
2019}
2020
2021void Mips64Assembler::LdiD(VectorRegister wd, int imm10) {
2022 CHECK(HasMsa());
2023 CHECK(IsInt<10>(imm10)) << imm10;
2024 EmitMsaI10(0x6, 0x3, imm10 & kMsaS10Mask, wd, 0x7);
2025}
2026
Goran Jakovljevic5a9e51d2017-03-16 16:11:43 +00002027void Mips64Assembler::LdB(VectorRegister wd, GpuRegister rs, int offset) {
Goran Jakovljevic27af9372017-03-15 15:31:34 +01002028 CHECK(HasMsa());
Goran Jakovljevic5a9e51d2017-03-16 16:11:43 +00002029 CHECK(IsInt<10>(offset)) << offset;
2030 EmitMsaMI10(offset & kMsaS10Mask, rs, wd, 0x8, 0x0);
2031}
2032
2033void Mips64Assembler::LdH(VectorRegister wd, GpuRegister rs, int offset) {
Goran Jakovljevic27af9372017-03-15 15:31:34 +01002034 CHECK(HasMsa());
Goran Jakovljevic5a9e51d2017-03-16 16:11:43 +00002035 CHECK(IsInt<11>(offset)) << offset;
2036 CHECK_ALIGNED(offset, kMips64HalfwordSize);
2037 EmitMsaMI10((offset >> TIMES_2) & kMsaS10Mask, rs, wd, 0x8, 0x1);
2038}
2039
2040void Mips64Assembler::LdW(VectorRegister wd, GpuRegister rs, int offset) {
Goran Jakovljevic27af9372017-03-15 15:31:34 +01002041 CHECK(HasMsa());
Goran Jakovljevic5a9e51d2017-03-16 16:11:43 +00002042 CHECK(IsInt<12>(offset)) << offset;
2043 CHECK_ALIGNED(offset, kMips64WordSize);
2044 EmitMsaMI10((offset >> TIMES_4) & kMsaS10Mask, rs, wd, 0x8, 0x2);
2045}
2046
2047void Mips64Assembler::LdD(VectorRegister wd, GpuRegister rs, int offset) {
Goran Jakovljevic27af9372017-03-15 15:31:34 +01002048 CHECK(HasMsa());
Goran Jakovljevic5a9e51d2017-03-16 16:11:43 +00002049 CHECK(IsInt<13>(offset)) << offset;
2050 CHECK_ALIGNED(offset, kMips64DoublewordSize);
2051 EmitMsaMI10((offset >> TIMES_8) & kMsaS10Mask, rs, wd, 0x8, 0x3);
2052}
2053
2054void Mips64Assembler::StB(VectorRegister wd, GpuRegister rs, int offset) {
Goran Jakovljevic27af9372017-03-15 15:31:34 +01002055 CHECK(HasMsa());
Goran Jakovljevic5a9e51d2017-03-16 16:11:43 +00002056 CHECK(IsInt<10>(offset)) << offset;
2057 EmitMsaMI10(offset & kMsaS10Mask, rs, wd, 0x9, 0x0);
2058}
2059
2060void Mips64Assembler::StH(VectorRegister wd, GpuRegister rs, int offset) {
Goran Jakovljevic27af9372017-03-15 15:31:34 +01002061 CHECK(HasMsa());
Goran Jakovljevic5a9e51d2017-03-16 16:11:43 +00002062 CHECK(IsInt<11>(offset)) << offset;
2063 CHECK_ALIGNED(offset, kMips64HalfwordSize);
2064 EmitMsaMI10((offset >> TIMES_2) & kMsaS10Mask, rs, wd, 0x9, 0x1);
2065}
2066
2067void Mips64Assembler::StW(VectorRegister wd, GpuRegister rs, int offset) {
Goran Jakovljevic27af9372017-03-15 15:31:34 +01002068 CHECK(HasMsa());
Goran Jakovljevic5a9e51d2017-03-16 16:11:43 +00002069 CHECK(IsInt<12>(offset)) << offset;
2070 CHECK_ALIGNED(offset, kMips64WordSize);
2071 EmitMsaMI10((offset >> TIMES_4) & kMsaS10Mask, rs, wd, 0x9, 0x2);
2072}
2073
2074void Mips64Assembler::StD(VectorRegister wd, GpuRegister rs, int offset) {
Goran Jakovljevic27af9372017-03-15 15:31:34 +01002075 CHECK(HasMsa());
Goran Jakovljevic5a9e51d2017-03-16 16:11:43 +00002076 CHECK(IsInt<13>(offset)) << offset;
2077 CHECK_ALIGNED(offset, kMips64DoublewordSize);
2078 EmitMsaMI10((offset >> TIMES_8) & kMsaS10Mask, rs, wd, 0x9, 0x3);
2079}
2080
Lena Djokic3309c012017-10-13 14:34:32 +02002081void Mips64Assembler::IlvlB(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
2082 CHECK(HasMsa());
2083 EmitMsa3R(0x4, 0x0, wt, ws, wd, 0x14);
2084}
2085
2086void Mips64Assembler::IlvlH(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
2087 CHECK(HasMsa());
2088 EmitMsa3R(0x4, 0x1, wt, ws, wd, 0x14);
2089}
2090
2091void Mips64Assembler::IlvlW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
2092 CHECK(HasMsa());
2093 EmitMsa3R(0x4, 0x2, wt, ws, wd, 0x14);
2094}
2095
2096void Mips64Assembler::IlvlD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
2097 CHECK(HasMsa());
2098 EmitMsa3R(0x4, 0x3, wt, ws, wd, 0x14);
2099}
2100
Goran Jakovljevic38370112017-05-10 14:30:28 +02002101void Mips64Assembler::IlvrB(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
2102 CHECK(HasMsa());
2103 EmitMsa3R(0x5, 0x0, wt, ws, wd, 0x14);
2104}
2105
2106void Mips64Assembler::IlvrH(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
2107 CHECK(HasMsa());
2108 EmitMsa3R(0x5, 0x1, wt, ws, wd, 0x14);
2109}
2110
2111void Mips64Assembler::IlvrW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
2112 CHECK(HasMsa());
2113 EmitMsa3R(0x5, 0x2, wt, ws, wd, 0x14);
2114}
2115
2116void Mips64Assembler::IlvrD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
2117 CHECK(HasMsa());
2118 EmitMsa3R(0x5, 0x3, wt, ws, wd, 0x14);
2119}
2120
Lena Djokic3309c012017-10-13 14:34:32 +02002121void Mips64Assembler::IlvevB(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
2122 CHECK(HasMsa());
2123 EmitMsa3R(0x6, 0x0, wt, ws, wd, 0x14);
2124}
2125
2126void Mips64Assembler::IlvevH(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
2127 CHECK(HasMsa());
2128 EmitMsa3R(0x6, 0x1, wt, ws, wd, 0x14);
2129}
2130
2131void Mips64Assembler::IlvevW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
2132 CHECK(HasMsa());
2133 EmitMsa3R(0x6, 0x2, wt, ws, wd, 0x14);
2134}
2135
2136void Mips64Assembler::IlvevD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
2137 CHECK(HasMsa());
2138 EmitMsa3R(0x6, 0x3, wt, ws, wd, 0x14);
2139}
2140
2141void Mips64Assembler::IlvodB(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
2142 CHECK(HasMsa());
2143 EmitMsa3R(0x7, 0x0, wt, ws, wd, 0x14);
2144}
2145
2146void Mips64Assembler::IlvodH(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
2147 CHECK(HasMsa());
2148 EmitMsa3R(0x7, 0x1, wt, ws, wd, 0x14);
2149}
2150
2151void Mips64Assembler::IlvodW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
2152 CHECK(HasMsa());
2153 EmitMsa3R(0x7, 0x2, wt, ws, wd, 0x14);
2154}
2155
2156void Mips64Assembler::IlvodD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
2157 CHECK(HasMsa());
2158 EmitMsa3R(0x7, 0x3, wt, ws, wd, 0x14);
2159}
2160
Lena Djokicb3d79e42017-07-25 11:20:52 +02002161void Mips64Assembler::MaddvB(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
2162 CHECK(HasMsa());
2163 EmitMsa3R(0x1, 0x0, wt, ws, wd, 0x12);
2164}
2165
2166void Mips64Assembler::MaddvH(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
2167 CHECK(HasMsa());
2168 EmitMsa3R(0x1, 0x1, wt, ws, wd, 0x12);
2169}
2170
2171void Mips64Assembler::MaddvW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
2172 CHECK(HasMsa());
2173 EmitMsa3R(0x1, 0x2, wt, ws, wd, 0x12);
2174}
2175
2176void Mips64Assembler::MaddvD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
2177 CHECK(HasMsa());
2178 EmitMsa3R(0x1, 0x3, wt, ws, wd, 0x12);
2179}
2180
2181void Mips64Assembler::MsubvB(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
2182 CHECK(HasMsa());
2183 EmitMsa3R(0x2, 0x0, wt, ws, wd, 0x12);
2184}
2185
2186void Mips64Assembler::MsubvH(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
2187 CHECK(HasMsa());
2188 EmitMsa3R(0x2, 0x1, wt, ws, wd, 0x12);
2189}
2190
2191void Mips64Assembler::MsubvW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
2192 CHECK(HasMsa());
2193 EmitMsa3R(0x2, 0x2, wt, ws, wd, 0x12);
2194}
2195
2196void Mips64Assembler::MsubvD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
2197 CHECK(HasMsa());
2198 EmitMsa3R(0x2, 0x3, wt, ws, wd, 0x12);
2199}
2200
2201void Mips64Assembler::FmaddW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
2202 CHECK(HasMsa());
2203 EmitMsa3R(0x2, 0x0, wt, ws, wd, 0x1b);
2204}
2205
2206void Mips64Assembler::FmaddD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
2207 CHECK(HasMsa());
2208 EmitMsa3R(0x2, 0x1, wt, ws, wd, 0x1b);
2209}
2210
2211void Mips64Assembler::FmsubW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
2212 CHECK(HasMsa());
2213 EmitMsa3R(0x2, 0x2, wt, ws, wd, 0x1b);
2214}
2215
2216void Mips64Assembler::FmsubD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
2217 CHECK(HasMsa());
2218 EmitMsa3R(0x2, 0x3, wt, ws, wd, 0x1b);
2219}
2220
Lena Djokic3309c012017-10-13 14:34:32 +02002221void Mips64Assembler::Hadd_sH(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
2222 CHECK(HasMsa());
2223 EmitMsa3R(0x4, 0x1, wt, ws, wd, 0x15);
2224}
2225
2226void Mips64Assembler::Hadd_sW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
2227 CHECK(HasMsa());
2228 EmitMsa3R(0x4, 0x2, wt, ws, wd, 0x15);
2229}
2230
2231void Mips64Assembler::Hadd_sD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
2232 CHECK(HasMsa());
2233 EmitMsa3R(0x4, 0x3, wt, ws, wd, 0x15);
2234}
2235
2236void Mips64Assembler::Hadd_uH(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
2237 CHECK(HasMsa());
2238 EmitMsa3R(0x5, 0x1, wt, ws, wd, 0x15);
2239}
2240
2241void Mips64Assembler::Hadd_uW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
2242 CHECK(HasMsa());
2243 EmitMsa3R(0x5, 0x2, wt, ws, wd, 0x15);
2244}
2245
2246void Mips64Assembler::Hadd_uD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
2247 CHECK(HasMsa());
2248 EmitMsa3R(0x5, 0x3, wt, ws, wd, 0x15);
2249}
2250
Goran Jakovljevic19680d32017-05-11 10:38:36 +02002251void Mips64Assembler::ReplicateFPToVectorRegister(VectorRegister dst,
2252 FpuRegister src,
2253 bool is_double) {
2254 // Float or double in FPU register Fx can be considered as 0th element in vector register Wx.
2255 if (is_double) {
2256 SplatiD(dst, static_cast<VectorRegister>(src), 0);
2257 } else {
2258 SplatiW(dst, static_cast<VectorRegister>(src), 0);
2259 }
2260}
2261
Alexey Frunze4dda3372015-06-01 18:31:49 -07002262void Mips64Assembler::LoadConst32(GpuRegister rd, int32_t value) {
Chris Larsenc733dca2016-05-13 16:11:47 -07002263 TemplateLoadConst32(this, rd, value);
2264}
2265
2266// This function is only used for testing purposes.
2267void Mips64Assembler::RecordLoadConst64Path(int value ATTRIBUTE_UNUSED) {
Andreas Gampe57b34292015-01-14 15:45:59 -08002268}
2269
Alexey Frunze4dda3372015-06-01 18:31:49 -07002270void Mips64Assembler::LoadConst64(GpuRegister rd, int64_t value) {
Chris Larsenc733dca2016-05-13 16:11:47 -07002271 TemplateLoadConst64(this, rd, value);
Andreas Gampe57b34292015-01-14 15:45:59 -08002272}
2273
Alexey Frunze0960ac52016-12-20 17:24:59 -08002274void Mips64Assembler::Addiu32(GpuRegister rt, GpuRegister rs, int32_t value) {
2275 if (IsInt<16>(value)) {
2276 Addiu(rt, rs, value);
2277 } else {
2278 int16_t high = High16Bits(value);
2279 int16_t low = Low16Bits(value);
2280 high += (low < 0) ? 1 : 0; // Account for sign extension in addiu.
2281 Aui(rt, rs, high);
2282 if (low != 0) {
2283 Addiu(rt, rt, low);
2284 }
2285 }
2286}
2287
Alexey Frunze15958152017-02-09 19:08:30 -08002288// TODO: don't use rtmp, use daui, dahi, dati.
Alexey Frunze4dda3372015-06-01 18:31:49 -07002289void Mips64Assembler::Daddiu64(GpuRegister rt, GpuRegister rs, int64_t value, GpuRegister rtmp) {
Chris Larsen5863f852017-03-23 15:41:37 -07002290 CHECK_NE(rs, rtmp);
Alexey Frunze4dda3372015-06-01 18:31:49 -07002291 if (IsInt<16>(value)) {
2292 Daddiu(rt, rs, value);
2293 } else {
2294 LoadConst64(rtmp, value);
2295 Daddu(rt, rs, rtmp);
2296 }
Andreas Gampe57b34292015-01-14 15:45:59 -08002297}
2298
Alexey Frunzea0e87b02015-09-24 22:57:20 -07002299void Mips64Assembler::Branch::InitShortOrLong(Mips64Assembler::Branch::OffsetBits offset_size,
2300 Mips64Assembler::Branch::Type short_type,
2301 Mips64Assembler::Branch::Type long_type) {
2302 type_ = (offset_size <= branch_info_[short_type].offset_size) ? short_type : long_type;
2303}
Alexey Frunze4dda3372015-06-01 18:31:49 -07002304
Alexey Frunze0cab6562017-07-25 15:19:36 -07002305void Mips64Assembler::Branch::InitializeType(Type initial_type, bool is_r6) {
2306 OffsetBits offset_size_needed = GetOffsetSizeNeeded(location_, target_);
2307 if (is_r6) {
2308 // R6
2309 switch (initial_type) {
2310 case kLabel:
2311 case kLiteral:
2312 case kLiteralUnsigned:
2313 case kLiteralLong:
2314 CHECK(!IsResolved());
2315 type_ = initial_type;
2316 break;
2317 case kCall:
2318 InitShortOrLong(offset_size_needed, kCall, kLongCall);
2319 break;
2320 case kCondBranch:
2321 switch (condition_) {
2322 case kUncond:
2323 InitShortOrLong(offset_size_needed, kUncondBranch, kLongUncondBranch);
2324 break;
2325 case kCondEQZ:
2326 case kCondNEZ:
2327 // Special case for beqzc/bnezc with longer offset than in other b<cond>c instructions.
2328 type_ = (offset_size_needed <= kOffset23) ? kCondBranch : kLongCondBranch;
2329 break;
2330 default:
2331 InitShortOrLong(offset_size_needed, kCondBranch, kLongCondBranch);
2332 break;
2333 }
2334 break;
2335 case kBareCall:
2336 type_ = kBareCall;
2337 CHECK_LE(offset_size_needed, GetOffsetSize());
2338 break;
2339 case kBareCondBranch:
2340 type_ = (condition_ == kUncond) ? kBareUncondBranch : kBareCondBranch;
2341 CHECK_LE(offset_size_needed, GetOffsetSize());
2342 break;
2343 default:
2344 LOG(FATAL) << "Unexpected branch type " << initial_type;
2345 UNREACHABLE();
2346 }
2347 } else {
2348 // R2
2349 CHECK_EQ(initial_type, kBareCondBranch);
2350 switch (condition_) {
2351 case kCondLTZ:
2352 case kCondGEZ:
2353 case kCondLEZ:
2354 case kCondGTZ:
2355 case kCondEQ:
2356 case kCondNE:
2357 case kCondEQZ:
2358 case kCondNEZ:
2359 break;
2360 default:
2361 LOG(FATAL) << "Unexpected R2 branch condition " << condition_;
2362 UNREACHABLE();
2363 }
2364 type_ = kR2BareCondBranch;
2365 CHECK_LE(offset_size_needed, GetOffsetSize());
Alexey Frunzea0e87b02015-09-24 22:57:20 -07002366 }
2367 old_type_ = type_;
2368}
2369
2370bool Mips64Assembler::Branch::IsNop(BranchCondition condition, GpuRegister lhs, GpuRegister rhs) {
2371 switch (condition) {
2372 case kCondLT:
2373 case kCondGT:
2374 case kCondNE:
2375 case kCondLTU:
2376 return lhs == rhs;
2377 default:
2378 return false;
2379 }
2380}
2381
2382bool Mips64Assembler::Branch::IsUncond(BranchCondition condition,
2383 GpuRegister lhs,
2384 GpuRegister rhs) {
2385 switch (condition) {
2386 case kUncond:
2387 return true;
2388 case kCondGE:
2389 case kCondLE:
2390 case kCondEQ:
2391 case kCondGEU:
2392 return lhs == rhs;
2393 default:
2394 return false;
2395 }
2396}
2397
Alexey Frunze0cab6562017-07-25 15:19:36 -07002398Mips64Assembler::Branch::Branch(uint32_t location, uint32_t target, bool is_call, bool is_bare)
Alexey Frunzea0e87b02015-09-24 22:57:20 -07002399 : old_location_(location),
2400 location_(location),
2401 target_(target),
2402 lhs_reg_(ZERO),
2403 rhs_reg_(ZERO),
2404 condition_(kUncond) {
Alexey Frunze0cab6562017-07-25 15:19:36 -07002405 InitializeType(
2406 (is_call ? (is_bare ? kBareCall : kCall) : (is_bare ? kBareCondBranch : kCondBranch)),
2407 /* is_r6 */ true);
Alexey Frunzea0e87b02015-09-24 22:57:20 -07002408}
2409
Alexey Frunze0cab6562017-07-25 15:19:36 -07002410Mips64Assembler::Branch::Branch(bool is_r6,
2411 uint32_t location,
Alexey Frunzea0e87b02015-09-24 22:57:20 -07002412 uint32_t target,
2413 Mips64Assembler::BranchCondition condition,
2414 GpuRegister lhs_reg,
Alexey Frunze0cab6562017-07-25 15:19:36 -07002415 GpuRegister rhs_reg,
2416 bool is_bare)
Alexey Frunzea0e87b02015-09-24 22:57:20 -07002417 : old_location_(location),
2418 location_(location),
2419 target_(target),
2420 lhs_reg_(lhs_reg),
2421 rhs_reg_(rhs_reg),
2422 condition_(condition) {
2423 CHECK_NE(condition, kUncond);
2424 switch (condition) {
2425 case kCondEQ:
2426 case kCondNE:
2427 case kCondLT:
2428 case kCondGE:
2429 case kCondLE:
2430 case kCondGT:
2431 case kCondLTU:
2432 case kCondGEU:
2433 CHECK_NE(lhs_reg, ZERO);
2434 CHECK_NE(rhs_reg, ZERO);
2435 break;
2436 case kCondLTZ:
2437 case kCondGEZ:
2438 case kCondLEZ:
2439 case kCondGTZ:
2440 case kCondEQZ:
2441 case kCondNEZ:
2442 CHECK_NE(lhs_reg, ZERO);
2443 CHECK_EQ(rhs_reg, ZERO);
2444 break;
Alexey Frunze299a9392015-12-08 16:08:02 -08002445 case kCondF:
2446 case kCondT:
2447 CHECK_EQ(rhs_reg, ZERO);
2448 break;
Alexey Frunzea0e87b02015-09-24 22:57:20 -07002449 case kUncond:
2450 UNREACHABLE();
2451 }
2452 CHECK(!IsNop(condition, lhs_reg, rhs_reg));
2453 if (IsUncond(condition, lhs_reg, rhs_reg)) {
2454 // Branch condition is always true, make the branch unconditional.
2455 condition_ = kUncond;
2456 }
Alexey Frunze0cab6562017-07-25 15:19:36 -07002457 InitializeType((is_bare ? kBareCondBranch : kCondBranch), is_r6);
Alexey Frunzea0e87b02015-09-24 22:57:20 -07002458}
2459
Alexey Frunze19f6c692016-11-30 19:19:55 -08002460Mips64Assembler::Branch::Branch(uint32_t location, GpuRegister dest_reg, Type label_or_literal_type)
Alexey Frunzea0e87b02015-09-24 22:57:20 -07002461 : old_location_(location),
2462 location_(location),
Alexey Frunze19f6c692016-11-30 19:19:55 -08002463 target_(kUnresolved),
2464 lhs_reg_(dest_reg),
Alexey Frunzea0e87b02015-09-24 22:57:20 -07002465 rhs_reg_(ZERO),
2466 condition_(kUncond) {
Alexey Frunze19f6c692016-11-30 19:19:55 -08002467 CHECK_NE(dest_reg, ZERO);
Alexey Frunze0cab6562017-07-25 15:19:36 -07002468 InitializeType(label_or_literal_type, /* is_r6 */ true);
Alexey Frunzea0e87b02015-09-24 22:57:20 -07002469}
2470
2471Mips64Assembler::BranchCondition Mips64Assembler::Branch::OppositeCondition(
2472 Mips64Assembler::BranchCondition cond) {
2473 switch (cond) {
2474 case kCondLT:
2475 return kCondGE;
2476 case kCondGE:
2477 return kCondLT;
2478 case kCondLE:
2479 return kCondGT;
2480 case kCondGT:
2481 return kCondLE;
2482 case kCondLTZ:
2483 return kCondGEZ;
2484 case kCondGEZ:
2485 return kCondLTZ;
2486 case kCondLEZ:
2487 return kCondGTZ;
2488 case kCondGTZ:
2489 return kCondLEZ;
2490 case kCondEQ:
2491 return kCondNE;
2492 case kCondNE:
2493 return kCondEQ;
2494 case kCondEQZ:
2495 return kCondNEZ;
2496 case kCondNEZ:
2497 return kCondEQZ;
2498 case kCondLTU:
2499 return kCondGEU;
2500 case kCondGEU:
2501 return kCondLTU;
Alexey Frunze299a9392015-12-08 16:08:02 -08002502 case kCondF:
2503 return kCondT;
2504 case kCondT:
2505 return kCondF;
Alexey Frunzea0e87b02015-09-24 22:57:20 -07002506 case kUncond:
2507 LOG(FATAL) << "Unexpected branch condition " << cond;
2508 }
2509 UNREACHABLE();
2510}
2511
2512Mips64Assembler::Branch::Type Mips64Assembler::Branch::GetType() const {
2513 return type_;
2514}
2515
2516Mips64Assembler::BranchCondition Mips64Assembler::Branch::GetCondition() const {
2517 return condition_;
2518}
2519
2520GpuRegister Mips64Assembler::Branch::GetLeftRegister() const {
2521 return lhs_reg_;
2522}
2523
2524GpuRegister Mips64Assembler::Branch::GetRightRegister() const {
2525 return rhs_reg_;
2526}
2527
2528uint32_t Mips64Assembler::Branch::GetTarget() const {
2529 return target_;
2530}
2531
2532uint32_t Mips64Assembler::Branch::GetLocation() const {
2533 return location_;
2534}
2535
2536uint32_t Mips64Assembler::Branch::GetOldLocation() const {
2537 return old_location_;
2538}
2539
2540uint32_t Mips64Assembler::Branch::GetLength() const {
2541 return branch_info_[type_].length;
2542}
2543
2544uint32_t Mips64Assembler::Branch::GetOldLength() const {
2545 return branch_info_[old_type_].length;
2546}
2547
2548uint32_t Mips64Assembler::Branch::GetSize() const {
2549 return GetLength() * sizeof(uint32_t);
2550}
2551
2552uint32_t Mips64Assembler::Branch::GetOldSize() const {
2553 return GetOldLength() * sizeof(uint32_t);
2554}
2555
2556uint32_t Mips64Assembler::Branch::GetEndLocation() const {
2557 return GetLocation() + GetSize();
2558}
2559
2560uint32_t Mips64Assembler::Branch::GetOldEndLocation() const {
2561 return GetOldLocation() + GetOldSize();
2562}
2563
Alexey Frunze0cab6562017-07-25 15:19:36 -07002564bool Mips64Assembler::Branch::IsBare() const {
2565 switch (type_) {
2566 // R6 short branches (can't be promoted to long), forbidden/delay slots filled manually.
2567 case kBareUncondBranch:
2568 case kBareCondBranch:
2569 case kBareCall:
2570 // R2 short branches (can't be promoted to long), delay slots filled manually.
2571 case kR2BareCondBranch:
2572 return true;
2573 default:
2574 return false;
2575 }
2576}
2577
Alexey Frunzea0e87b02015-09-24 22:57:20 -07002578bool Mips64Assembler::Branch::IsLong() const {
2579 switch (type_) {
Alexey Frunze0cab6562017-07-25 15:19:36 -07002580 // R6 short branches (can be promoted to long).
Alexey Frunzea0e87b02015-09-24 22:57:20 -07002581 case kUncondBranch:
2582 case kCondBranch:
2583 case kCall:
Alexey Frunze0cab6562017-07-25 15:19:36 -07002584 // R6 short branches (can't be promoted to long), forbidden/delay slots filled manually.
2585 case kBareUncondBranch:
2586 case kBareCondBranch:
2587 case kBareCall:
2588 // R2 short branches (can't be promoted to long), delay slots filled manually.
2589 case kR2BareCondBranch:
Alexey Frunze19f6c692016-11-30 19:19:55 -08002590 // Near label.
2591 case kLabel:
2592 // Near literals.
2593 case kLiteral:
2594 case kLiteralUnsigned:
2595 case kLiteralLong:
Alexey Frunzea0e87b02015-09-24 22:57:20 -07002596 return false;
2597 // Long branches.
2598 case kLongUncondBranch:
2599 case kLongCondBranch:
2600 case kLongCall:
Alexey Frunze19f6c692016-11-30 19:19:55 -08002601 // Far label.
2602 case kFarLabel:
2603 // Far literals.
2604 case kFarLiteral:
2605 case kFarLiteralUnsigned:
2606 case kFarLiteralLong:
Alexey Frunzea0e87b02015-09-24 22:57:20 -07002607 return true;
2608 }
2609 UNREACHABLE();
2610}
2611
2612bool Mips64Assembler::Branch::IsResolved() const {
2613 return target_ != kUnresolved;
2614}
2615
2616Mips64Assembler::Branch::OffsetBits Mips64Assembler::Branch::GetOffsetSize() const {
Alexey Frunze0cab6562017-07-25 15:19:36 -07002617 bool r6_cond_branch = (type_ == kCondBranch || type_ == kBareCondBranch);
Alexey Frunzea0e87b02015-09-24 22:57:20 -07002618 OffsetBits offset_size =
Alexey Frunze0cab6562017-07-25 15:19:36 -07002619 (r6_cond_branch && (condition_ == kCondEQZ || condition_ == kCondNEZ))
Alexey Frunzea0e87b02015-09-24 22:57:20 -07002620 ? kOffset23
2621 : branch_info_[type_].offset_size;
2622 return offset_size;
2623}
2624
2625Mips64Assembler::Branch::OffsetBits Mips64Assembler::Branch::GetOffsetSizeNeeded(uint32_t location,
2626 uint32_t target) {
2627 // For unresolved targets assume the shortest encoding
2628 // (later it will be made longer if needed).
2629 if (target == kUnresolved)
2630 return kOffset16;
2631 int64_t distance = static_cast<int64_t>(target) - location;
2632 // To simplify calculations in composite branches consisting of multiple instructions
2633 // bump up the distance by a value larger than the max byte size of a composite branch.
2634 distance += (distance >= 0) ? kMaxBranchSize : -kMaxBranchSize;
2635 if (IsInt<kOffset16>(distance))
2636 return kOffset16;
2637 else if (IsInt<kOffset18>(distance))
2638 return kOffset18;
2639 else if (IsInt<kOffset21>(distance))
2640 return kOffset21;
2641 else if (IsInt<kOffset23>(distance))
2642 return kOffset23;
2643 else if (IsInt<kOffset28>(distance))
2644 return kOffset28;
2645 return kOffset32;
2646}
2647
2648void Mips64Assembler::Branch::Resolve(uint32_t target) {
2649 target_ = target;
2650}
2651
2652void Mips64Assembler::Branch::Relocate(uint32_t expand_location, uint32_t delta) {
2653 if (location_ > expand_location) {
2654 location_ += delta;
2655 }
2656 if (!IsResolved()) {
2657 return; // Don't know the target yet.
2658 }
2659 if (target_ > expand_location) {
2660 target_ += delta;
2661 }
2662}
2663
2664void Mips64Assembler::Branch::PromoteToLong() {
Alexey Frunze0cab6562017-07-25 15:19:36 -07002665 CHECK(!IsBare()); // Bare branches do not promote.
Alexey Frunzea0e87b02015-09-24 22:57:20 -07002666 switch (type_) {
Alexey Frunze0cab6562017-07-25 15:19:36 -07002667 // R6 short branches (can be promoted to long).
Alexey Frunzea0e87b02015-09-24 22:57:20 -07002668 case kUncondBranch:
2669 type_ = kLongUncondBranch;
2670 break;
2671 case kCondBranch:
2672 type_ = kLongCondBranch;
2673 break;
2674 case kCall:
2675 type_ = kLongCall;
2676 break;
Alexey Frunze19f6c692016-11-30 19:19:55 -08002677 // Near label.
2678 case kLabel:
2679 type_ = kFarLabel;
2680 break;
2681 // Near literals.
2682 case kLiteral:
2683 type_ = kFarLiteral;
2684 break;
2685 case kLiteralUnsigned:
2686 type_ = kFarLiteralUnsigned;
2687 break;
2688 case kLiteralLong:
2689 type_ = kFarLiteralLong;
2690 break;
Alexey Frunzea0e87b02015-09-24 22:57:20 -07002691 default:
2692 // Note: 'type_' is already long.
2693 break;
2694 }
2695 CHECK(IsLong());
2696}
2697
2698uint32_t Mips64Assembler::Branch::PromoteIfNeeded(uint32_t max_short_distance) {
2699 // If the branch is still unresolved or already long, nothing to do.
2700 if (IsLong() || !IsResolved()) {
2701 return 0;
2702 }
2703 // Promote the short branch to long if the offset size is too small
2704 // to hold the distance between location_ and target_.
2705 if (GetOffsetSizeNeeded(location_, target_) > GetOffsetSize()) {
2706 PromoteToLong();
2707 uint32_t old_size = GetOldSize();
2708 uint32_t new_size = GetSize();
2709 CHECK_GT(new_size, old_size);
2710 return new_size - old_size;
2711 }
2712 // The following logic is for debugging/testing purposes.
2713 // Promote some short branches to long when it's not really required.
Alexey Frunze0cab6562017-07-25 15:19:36 -07002714 if (UNLIKELY(max_short_distance != std::numeric_limits<uint32_t>::max() && !IsBare())) {
Alexey Frunzea0e87b02015-09-24 22:57:20 -07002715 int64_t distance = static_cast<int64_t>(target_) - location_;
2716 distance = (distance >= 0) ? distance : -distance;
2717 if (distance >= max_short_distance) {
2718 PromoteToLong();
2719 uint32_t old_size = GetOldSize();
2720 uint32_t new_size = GetSize();
2721 CHECK_GT(new_size, old_size);
2722 return new_size - old_size;
2723 }
2724 }
2725 return 0;
2726}
2727
2728uint32_t Mips64Assembler::Branch::GetOffsetLocation() const {
2729 return location_ + branch_info_[type_].instr_offset * sizeof(uint32_t);
2730}
2731
2732uint32_t Mips64Assembler::Branch::GetOffset() const {
2733 CHECK(IsResolved());
2734 uint32_t ofs_mask = 0xFFFFFFFF >> (32 - GetOffsetSize());
2735 // Calculate the byte distance between instructions and also account for
2736 // different PC-relative origins.
Alexey Frunze19f6c692016-11-30 19:19:55 -08002737 uint32_t offset_location = GetOffsetLocation();
2738 if (type_ == kLiteralLong) {
2739 // Special case for the ldpc instruction, whose address (PC) is rounded down to
2740 // a multiple of 8 before adding the offset.
2741 // Note, branch promotion has already taken care of aligning `target_` to an
2742 // address that's a multiple of 8.
2743 offset_location = RoundDown(offset_location, sizeof(uint64_t));
2744 }
2745 uint32_t offset = target_ - offset_location - branch_info_[type_].pc_org * sizeof(uint32_t);
Alexey Frunzea0e87b02015-09-24 22:57:20 -07002746 // Prepare the offset for encoding into the instruction(s).
2747 offset = (offset & ofs_mask) >> branch_info_[type_].offset_shift;
2748 return offset;
2749}
2750
2751Mips64Assembler::Branch* Mips64Assembler::GetBranch(uint32_t branch_id) {
2752 CHECK_LT(branch_id, branches_.size());
2753 return &branches_[branch_id];
2754}
2755
2756const Mips64Assembler::Branch* Mips64Assembler::GetBranch(uint32_t branch_id) const {
2757 CHECK_LT(branch_id, branches_.size());
2758 return &branches_[branch_id];
2759}
2760
2761void Mips64Assembler::Bind(Mips64Label* label) {
Alexey Frunze4dda3372015-06-01 18:31:49 -07002762 CHECK(!label->IsBound());
Alexey Frunzea0e87b02015-09-24 22:57:20 -07002763 uint32_t bound_pc = buffer_.Size();
Alexey Frunze4dda3372015-06-01 18:31:49 -07002764
Alexey Frunzea0e87b02015-09-24 22:57:20 -07002765 // Walk the list of branches referring to and preceding this label.
2766 // Store the previously unknown target addresses in them.
Alexey Frunze4dda3372015-06-01 18:31:49 -07002767 while (label->IsLinked()) {
Alexey Frunzea0e87b02015-09-24 22:57:20 -07002768 uint32_t branch_id = label->Position();
2769 Branch* branch = GetBranch(branch_id);
2770 branch->Resolve(bound_pc);
Alexey Frunze4dda3372015-06-01 18:31:49 -07002771
Alexey Frunzea0e87b02015-09-24 22:57:20 -07002772 uint32_t branch_location = branch->GetLocation();
2773 // Extract the location of the previous branch in the list (walking the list backwards;
2774 // the previous branch ID was stored in the space reserved for this branch).
2775 uint32_t prev = buffer_.Load<uint32_t>(branch_location);
Alexey Frunze4dda3372015-06-01 18:31:49 -07002776
2777 // On to the previous branch in the list...
2778 label->position_ = prev;
2779 }
2780
Alexey Frunzea0e87b02015-09-24 22:57:20 -07002781 // Now make the label object contain its own location (relative to the end of the preceding
2782 // branch, if any; it will be used by the branches referring to and following this label).
2783 label->prev_branch_id_plus_one_ = branches_.size();
2784 if (label->prev_branch_id_plus_one_) {
2785 uint32_t branch_id = label->prev_branch_id_plus_one_ - 1;
2786 const Branch* branch = GetBranch(branch_id);
2787 bound_pc -= branch->GetEndLocation();
2788 }
Alexey Frunze4dda3372015-06-01 18:31:49 -07002789 label->BindTo(bound_pc);
2790}
2791
Alexey Frunze19f6c692016-11-30 19:19:55 -08002792uint32_t Mips64Assembler::GetLabelLocation(const Mips64Label* label) const {
Alexey Frunzea0e87b02015-09-24 22:57:20 -07002793 CHECK(label->IsBound());
2794 uint32_t target = label->Position();
2795 if (label->prev_branch_id_plus_one_) {
2796 // Get label location based on the branch preceding it.
2797 uint32_t branch_id = label->prev_branch_id_plus_one_ - 1;
2798 const Branch* branch = GetBranch(branch_id);
2799 target += branch->GetEndLocation();
2800 }
2801 return target;
2802}
2803
2804uint32_t Mips64Assembler::GetAdjustedPosition(uint32_t old_position) {
2805 // We can reconstruct the adjustment by going through all the branches from the beginning
2806 // up to the old_position. Since we expect AdjustedPosition() to be called in a loop
2807 // with increasing old_position, we can use the data from last AdjustedPosition() to
2808 // continue where we left off and the whole loop should be O(m+n) where m is the number
2809 // of positions to adjust and n is the number of branches.
2810 if (old_position < last_old_position_) {
2811 last_position_adjustment_ = 0;
2812 last_old_position_ = 0;
2813 last_branch_id_ = 0;
2814 }
2815 while (last_branch_id_ != branches_.size()) {
2816 const Branch* branch = GetBranch(last_branch_id_);
2817 if (branch->GetLocation() >= old_position + last_position_adjustment_) {
2818 break;
2819 }
2820 last_position_adjustment_ += branch->GetSize() - branch->GetOldSize();
2821 ++last_branch_id_;
2822 }
2823 last_old_position_ = old_position;
2824 return old_position + last_position_adjustment_;
2825}
2826
2827void Mips64Assembler::FinalizeLabeledBranch(Mips64Label* label) {
2828 uint32_t length = branches_.back().GetLength();
2829 if (!label->IsBound()) {
2830 // Branch forward (to a following label), distance is unknown.
2831 // The first branch forward will contain 0, serving as the terminator of
2832 // the list of forward-reaching branches.
2833 Emit(label->position_);
2834 length--;
2835 // Now make the label object point to this branch
2836 // (this forms a linked list of branches preceding this label).
2837 uint32_t branch_id = branches_.size() - 1;
2838 label->LinkTo(branch_id);
2839 }
2840 // Reserve space for the branch.
2841 while (length--) {
2842 Nop();
Alexey Frunze4dda3372015-06-01 18:31:49 -07002843 }
2844}
2845
Alexey Frunze0cab6562017-07-25 15:19:36 -07002846void Mips64Assembler::Buncond(Mips64Label* label, bool is_bare) {
Alexey Frunzea0e87b02015-09-24 22:57:20 -07002847 uint32_t target = label->IsBound() ? GetLabelLocation(label) : Branch::kUnresolved;
Alexey Frunze0cab6562017-07-25 15:19:36 -07002848 branches_.emplace_back(buffer_.Size(), target, /* is_call */ false, is_bare);
Alexey Frunzea0e87b02015-09-24 22:57:20 -07002849 FinalizeLabeledBranch(label);
2850}
2851
2852void Mips64Assembler::Bcond(Mips64Label* label,
Alexey Frunze0cab6562017-07-25 15:19:36 -07002853 bool is_r6,
2854 bool is_bare,
Alexey Frunzea0e87b02015-09-24 22:57:20 -07002855 BranchCondition condition,
2856 GpuRegister lhs,
2857 GpuRegister rhs) {
2858 // If lhs = rhs, this can be a NOP.
2859 if (Branch::IsNop(condition, lhs, rhs)) {
2860 return;
2861 }
2862 uint32_t target = label->IsBound() ? GetLabelLocation(label) : Branch::kUnresolved;
Alexey Frunze0cab6562017-07-25 15:19:36 -07002863 branches_.emplace_back(is_r6, buffer_.Size(), target, condition, lhs, rhs, is_bare);
Alexey Frunzea0e87b02015-09-24 22:57:20 -07002864 FinalizeLabeledBranch(label);
2865}
2866
Alexey Frunze0cab6562017-07-25 15:19:36 -07002867void Mips64Assembler::Call(Mips64Label* label, bool is_bare) {
Alexey Frunzea0e87b02015-09-24 22:57:20 -07002868 uint32_t target = label->IsBound() ? GetLabelLocation(label) : Branch::kUnresolved;
Alexey Frunze0cab6562017-07-25 15:19:36 -07002869 branches_.emplace_back(buffer_.Size(), target, /* is_call */ true, is_bare);
Alexey Frunzea0e87b02015-09-24 22:57:20 -07002870 FinalizeLabeledBranch(label);
2871}
2872
Alexey Frunze19f6c692016-11-30 19:19:55 -08002873void Mips64Assembler::LoadLabelAddress(GpuRegister dest_reg, Mips64Label* label) {
2874 // Label address loads are treated as pseudo branches since they require very similar handling.
2875 DCHECK(!label->IsBound());
2876 branches_.emplace_back(buffer_.Size(), dest_reg, Branch::kLabel);
2877 FinalizeLabeledBranch(label);
2878}
2879
2880Literal* Mips64Assembler::NewLiteral(size_t size, const uint8_t* data) {
2881 // We don't support byte and half-word literals.
2882 if (size == 4u) {
2883 literals_.emplace_back(size, data);
2884 return &literals_.back();
2885 } else {
2886 DCHECK_EQ(size, 8u);
2887 long_literals_.emplace_back(size, data);
2888 return &long_literals_.back();
2889 }
2890}
2891
2892void Mips64Assembler::LoadLiteral(GpuRegister dest_reg,
2893 LoadOperandType load_type,
2894 Literal* literal) {
2895 // Literal loads are treated as pseudo branches since they require very similar handling.
2896 Branch::Type literal_type;
2897 switch (load_type) {
2898 case kLoadWord:
2899 DCHECK_EQ(literal->GetSize(), 4u);
2900 literal_type = Branch::kLiteral;
2901 break;
2902 case kLoadUnsignedWord:
2903 DCHECK_EQ(literal->GetSize(), 4u);
2904 literal_type = Branch::kLiteralUnsigned;
2905 break;
2906 case kLoadDoubleword:
2907 DCHECK_EQ(literal->GetSize(), 8u);
2908 literal_type = Branch::kLiteralLong;
2909 break;
2910 default:
2911 LOG(FATAL) << "Unexpected literal load type " << load_type;
2912 UNREACHABLE();
2913 }
2914 Mips64Label* label = literal->GetLabel();
2915 DCHECK(!label->IsBound());
2916 branches_.emplace_back(buffer_.Size(), dest_reg, literal_type);
2917 FinalizeLabeledBranch(label);
2918}
2919
Alexey Frunze0960ac52016-12-20 17:24:59 -08002920JumpTable* Mips64Assembler::CreateJumpTable(std::vector<Mips64Label*>&& labels) {
2921 jump_tables_.emplace_back(std::move(labels));
2922 JumpTable* table = &jump_tables_.back();
2923 DCHECK(!table->GetLabel()->IsBound());
2924 return table;
2925}
2926
2927void Mips64Assembler::ReserveJumpTableSpace() {
2928 if (!jump_tables_.empty()) {
2929 for (JumpTable& table : jump_tables_) {
2930 Mips64Label* label = table.GetLabel();
2931 Bind(label);
2932
2933 // Bulk ensure capacity, as this may be large.
2934 size_t orig_size = buffer_.Size();
2935 size_t required_capacity = orig_size + table.GetSize();
2936 if (required_capacity > buffer_.Capacity()) {
2937 buffer_.ExtendCapacity(required_capacity);
2938 }
2939#ifndef NDEBUG
2940 buffer_.has_ensured_capacity_ = true;
2941#endif
2942
2943 // Fill the space with dummy data as the data is not final
2944 // until the branches have been promoted. And we shouldn't
2945 // be moving uninitialized data during branch promotion.
2946 for (size_t cnt = table.GetData().size(), i = 0; i < cnt; i++) {
2947 buffer_.Emit<uint32_t>(0x1abe1234u);
2948 }
2949
2950#ifndef NDEBUG
2951 buffer_.has_ensured_capacity_ = false;
2952#endif
2953 }
2954 }
2955}
2956
2957void Mips64Assembler::EmitJumpTables() {
2958 if (!jump_tables_.empty()) {
2959 CHECK(!overwriting_);
2960 // Switch from appending instructions at the end of the buffer to overwriting
2961 // existing instructions (here, jump tables) in the buffer.
2962 overwriting_ = true;
2963
2964 for (JumpTable& table : jump_tables_) {
2965 Mips64Label* table_label = table.GetLabel();
2966 uint32_t start = GetLabelLocation(table_label);
2967 overwrite_location_ = start;
2968
2969 for (Mips64Label* target : table.GetData()) {
2970 CHECK_EQ(buffer_.Load<uint32_t>(overwrite_location_), 0x1abe1234u);
2971 // The table will contain target addresses relative to the table start.
2972 uint32_t offset = GetLabelLocation(target) - start;
2973 Emit(offset);
2974 }
2975 }
2976
2977 overwriting_ = false;
2978 }
2979}
2980
Alexey Frunze19f6c692016-11-30 19:19:55 -08002981void Mips64Assembler::EmitLiterals() {
2982 if (!literals_.empty()) {
2983 for (Literal& literal : literals_) {
2984 Mips64Label* label = literal.GetLabel();
2985 Bind(label);
2986 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
2987 DCHECK_EQ(literal.GetSize(), 4u);
2988 for (size_t i = 0, size = literal.GetSize(); i != size; ++i) {
2989 buffer_.Emit<uint8_t>(literal.GetData()[i]);
2990 }
2991 }
2992 }
2993 if (!long_literals_.empty()) {
2994 // Reserve 4 bytes for potential alignment. If after the branch promotion the 64-bit
2995 // literals don't end up 8-byte-aligned, they will be moved down 4 bytes.
2996 Emit(0); // NOP.
2997 for (Literal& literal : long_literals_) {
2998 Mips64Label* label = literal.GetLabel();
2999 Bind(label);
3000 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
3001 DCHECK_EQ(literal.GetSize(), 8u);
3002 for (size_t i = 0, size = literal.GetSize(); i != size; ++i) {
3003 buffer_.Emit<uint8_t>(literal.GetData()[i]);
3004 }
3005 }
3006 }
3007}
3008
Alexey Frunzea0e87b02015-09-24 22:57:20 -07003009void Mips64Assembler::PromoteBranches() {
3010 // Promote short branches to long as necessary.
3011 bool changed;
3012 do {
3013 changed = false;
3014 for (auto& branch : branches_) {
3015 CHECK(branch.IsResolved());
3016 uint32_t delta = branch.PromoteIfNeeded();
3017 // If this branch has been promoted and needs to expand in size,
3018 // relocate all branches by the expansion size.
3019 if (delta) {
3020 changed = true;
3021 uint32_t expand_location = branch.GetLocation();
3022 for (auto& branch2 : branches_) {
3023 branch2.Relocate(expand_location, delta);
3024 }
3025 }
3026 }
3027 } while (changed);
3028
3029 // Account for branch expansion by resizing the code buffer
3030 // and moving the code in it to its final location.
3031 size_t branch_count = branches_.size();
3032 if (branch_count > 0) {
3033 // Resize.
3034 Branch& last_branch = branches_[branch_count - 1];
3035 uint32_t size_delta = last_branch.GetEndLocation() - last_branch.GetOldEndLocation();
3036 uint32_t old_size = buffer_.Size();
3037 buffer_.Resize(old_size + size_delta);
3038 // Move the code residing between branch placeholders.
3039 uint32_t end = old_size;
3040 for (size_t i = branch_count; i > 0; ) {
3041 Branch& branch = branches_[--i];
3042 uint32_t size = end - branch.GetOldEndLocation();
3043 buffer_.Move(branch.GetEndLocation(), branch.GetOldEndLocation(), size);
3044 end = branch.GetOldLocation();
3045 }
Alexey Frunze4dda3372015-06-01 18:31:49 -07003046 }
Alexey Frunze19f6c692016-11-30 19:19:55 -08003047
3048 // Align 64-bit literals by moving them down by 4 bytes if needed.
3049 // This will reduce the PC-relative distance, which should be safe for both near and far literals.
3050 if (!long_literals_.empty()) {
3051 uint32_t first_literal_location = GetLabelLocation(long_literals_.front().GetLabel());
3052 size_t lit_size = long_literals_.size() * sizeof(uint64_t);
3053 size_t buf_size = buffer_.Size();
3054 // 64-bit literals must be at the very end of the buffer.
3055 CHECK_EQ(first_literal_location + lit_size, buf_size);
3056 if (!IsAligned<sizeof(uint64_t)>(first_literal_location)) {
3057 buffer_.Move(first_literal_location - sizeof(uint32_t), first_literal_location, lit_size);
3058 // The 4 reserved bytes proved useless, reduce the buffer size.
3059 buffer_.Resize(buf_size - sizeof(uint32_t));
3060 // Reduce target addresses in literal and address loads by 4 bytes in order for correct
3061 // offsets from PC to be generated.
3062 for (auto& branch : branches_) {
3063 uint32_t target = branch.GetTarget();
3064 if (target >= first_literal_location) {
3065 branch.Resolve(target - sizeof(uint32_t));
3066 }
3067 }
3068 // If after this we ever call GetLabelLocation() to get the location of a 64-bit literal,
3069 // we need to adjust the location of the literal's label as well.
3070 for (Literal& literal : long_literals_) {
3071 // Bound label's position is negative, hence incrementing it instead of decrementing.
3072 literal.GetLabel()->position_ += sizeof(uint32_t);
3073 }
3074 }
3075 }
Alexey Frunze4dda3372015-06-01 18:31:49 -07003076}
3077
Alexey Frunzea0e87b02015-09-24 22:57:20 -07003078// Note: make sure branch_info_[] and EmitBranch() are kept synchronized.
3079const Mips64Assembler::Branch::BranchInfo Mips64Assembler::Branch::branch_info_[] = {
Alexey Frunze0cab6562017-07-25 15:19:36 -07003080 // R6 short branches (can be promoted to long).
Alexey Frunzea0e87b02015-09-24 22:57:20 -07003081 { 1, 0, 1, Mips64Assembler::Branch::kOffset28, 2 }, // kUncondBranch
3082 { 2, 0, 1, Mips64Assembler::Branch::kOffset18, 2 }, // kCondBranch
3083 // Exception: kOffset23 for beqzc/bnezc
Alexey Frunze19f6c692016-11-30 19:19:55 -08003084 { 1, 0, 1, Mips64Assembler::Branch::kOffset28, 2 }, // kCall
Alexey Frunze0cab6562017-07-25 15:19:36 -07003085 // R6 short branches (can't be promoted to long), forbidden/delay slots filled manually.
3086 { 1, 0, 1, Mips64Assembler::Branch::kOffset28, 2 }, // kBareUncondBranch
3087 { 1, 0, 1, Mips64Assembler::Branch::kOffset18, 2 }, // kBareCondBranch
3088 // Exception: kOffset23 for beqzc/bnezc
3089 { 1, 0, 1, Mips64Assembler::Branch::kOffset28, 2 }, // kBareCall
3090 // R2 short branches (can't be promoted to long), delay slots filled manually.
3091 { 1, 0, 1, Mips64Assembler::Branch::kOffset18, 2 }, // kR2BareCondBranch
Alexey Frunze19f6c692016-11-30 19:19:55 -08003092 // Near label.
3093 { 1, 0, 0, Mips64Assembler::Branch::kOffset21, 2 }, // kLabel
3094 // Near literals.
3095 { 1, 0, 0, Mips64Assembler::Branch::kOffset21, 2 }, // kLiteral
3096 { 1, 0, 0, Mips64Assembler::Branch::kOffset21, 2 }, // kLiteralUnsigned
3097 { 1, 0, 0, Mips64Assembler::Branch::kOffset21, 3 }, // kLiteralLong
Alexey Frunzea0e87b02015-09-24 22:57:20 -07003098 // Long branches.
3099 { 2, 0, 0, Mips64Assembler::Branch::kOffset32, 0 }, // kLongUncondBranch
3100 { 3, 1, 0, Mips64Assembler::Branch::kOffset32, 0 }, // kLongCondBranch
Alexey Frunze19f6c692016-11-30 19:19:55 -08003101 { 2, 0, 0, Mips64Assembler::Branch::kOffset32, 0 }, // kLongCall
3102 // Far label.
3103 { 2, 0, 0, Mips64Assembler::Branch::kOffset32, 0 }, // kFarLabel
3104 // Far literals.
3105 { 2, 0, 0, Mips64Assembler::Branch::kOffset32, 0 }, // kFarLiteral
3106 { 2, 0, 0, Mips64Assembler::Branch::kOffset32, 0 }, // kFarLiteralUnsigned
3107 { 2, 0, 0, Mips64Assembler::Branch::kOffset32, 0 }, // kFarLiteralLong
Alexey Frunzea0e87b02015-09-24 22:57:20 -07003108};
3109
3110// Note: make sure branch_info_[] and EmitBranch() are kept synchronized.
3111void Mips64Assembler::EmitBranch(Mips64Assembler::Branch* branch) {
3112 CHECK(overwriting_);
3113 overwrite_location_ = branch->GetLocation();
3114 uint32_t offset = branch->GetOffset();
3115 BranchCondition condition = branch->GetCondition();
3116 GpuRegister lhs = branch->GetLeftRegister();
3117 GpuRegister rhs = branch->GetRightRegister();
3118 switch (branch->GetType()) {
3119 // Short branches.
3120 case Branch::kUncondBranch:
3121 CHECK_EQ(overwrite_location_, branch->GetOffsetLocation());
3122 Bc(offset);
3123 break;
3124 case Branch::kCondBranch:
3125 CHECK_EQ(overwrite_location_, branch->GetOffsetLocation());
Alexey Frunze0cab6562017-07-25 15:19:36 -07003126 EmitBcondR6(condition, lhs, rhs, offset);
Alexey Frunze299a9392015-12-08 16:08:02 -08003127 Nop(); // TODO: improve by filling the forbidden/delay slot.
Alexey Frunzea0e87b02015-09-24 22:57:20 -07003128 break;
3129 case Branch::kCall:
3130 CHECK_EQ(overwrite_location_, branch->GetOffsetLocation());
Alexey Frunze19f6c692016-11-30 19:19:55 -08003131 Balc(offset);
3132 break;
Alexey Frunze0cab6562017-07-25 15:19:36 -07003133 case Branch::kBareUncondBranch:
3134 CHECK_EQ(overwrite_location_, branch->GetOffsetLocation());
3135 Bc(offset);
3136 break;
3137 case Branch::kBareCondBranch:
3138 CHECK_EQ(overwrite_location_, branch->GetOffsetLocation());
3139 EmitBcondR6(condition, lhs, rhs, offset);
3140 break;
3141 case Branch::kBareCall:
3142 CHECK_EQ(overwrite_location_, branch->GetOffsetLocation());
3143 Balc(offset);
3144 break;
3145 case Branch::kR2BareCondBranch:
3146 CHECK_EQ(overwrite_location_, branch->GetOffsetLocation());
3147 EmitBcondR2(condition, lhs, rhs, offset);
3148 break;
Alexey Frunze19f6c692016-11-30 19:19:55 -08003149
3150 // Near label.
3151 case Branch::kLabel:
3152 CHECK_EQ(overwrite_location_, branch->GetOffsetLocation());
Alexey Frunzea0e87b02015-09-24 22:57:20 -07003153 Addiupc(lhs, offset);
Alexey Frunze19f6c692016-11-30 19:19:55 -08003154 break;
3155 // Near literals.
3156 case Branch::kLiteral:
3157 CHECK_EQ(overwrite_location_, branch->GetOffsetLocation());
3158 Lwpc(lhs, offset);
3159 break;
3160 case Branch::kLiteralUnsigned:
3161 CHECK_EQ(overwrite_location_, branch->GetOffsetLocation());
3162 Lwupc(lhs, offset);
3163 break;
3164 case Branch::kLiteralLong:
3165 CHECK_EQ(overwrite_location_, branch->GetOffsetLocation());
3166 Ldpc(lhs, offset);
Alexey Frunzea0e87b02015-09-24 22:57:20 -07003167 break;
3168
3169 // Long branches.
3170 case Branch::kLongUncondBranch:
3171 offset += (offset & 0x8000) << 1; // Account for sign extension in jic.
3172 CHECK_EQ(overwrite_location_, branch->GetOffsetLocation());
3173 Auipc(AT, High16Bits(offset));
3174 Jic(AT, Low16Bits(offset));
3175 break;
3176 case Branch::kLongCondBranch:
Alexey Frunze0cab6562017-07-25 15:19:36 -07003177 EmitBcondR6(Branch::OppositeCondition(condition), lhs, rhs, 2);
Alexey Frunzea0e87b02015-09-24 22:57:20 -07003178 offset += (offset & 0x8000) << 1; // Account for sign extension in jic.
3179 CHECK_EQ(overwrite_location_, branch->GetOffsetLocation());
3180 Auipc(AT, High16Bits(offset));
3181 Jic(AT, Low16Bits(offset));
3182 break;
3183 case Branch::kLongCall:
Alexey Frunze19f6c692016-11-30 19:19:55 -08003184 offset += (offset & 0x8000) << 1; // Account for sign extension in jialc.
Alexey Frunzea0e87b02015-09-24 22:57:20 -07003185 CHECK_EQ(overwrite_location_, branch->GetOffsetLocation());
Alexey Frunze19f6c692016-11-30 19:19:55 -08003186 Auipc(AT, High16Bits(offset));
3187 Jialc(AT, Low16Bits(offset));
3188 break;
3189
3190 // Far label.
3191 case Branch::kFarLabel:
Alexey Frunzef63f5692016-12-13 17:43:11 -08003192 offset += (offset & 0x8000) << 1; // Account for sign extension in daddiu.
Alexey Frunze19f6c692016-11-30 19:19:55 -08003193 CHECK_EQ(overwrite_location_, branch->GetOffsetLocation());
3194 Auipc(AT, High16Bits(offset));
Alexey Frunzef63f5692016-12-13 17:43:11 -08003195 Daddiu(lhs, AT, Low16Bits(offset));
Alexey Frunze19f6c692016-11-30 19:19:55 -08003196 break;
3197 // Far literals.
3198 case Branch::kFarLiteral:
3199 offset += (offset & 0x8000) << 1; // Account for sign extension in lw.
3200 CHECK_EQ(overwrite_location_, branch->GetOffsetLocation());
3201 Auipc(AT, High16Bits(offset));
3202 Lw(lhs, AT, Low16Bits(offset));
3203 break;
3204 case Branch::kFarLiteralUnsigned:
3205 offset += (offset & 0x8000) << 1; // Account for sign extension in lwu.
3206 CHECK_EQ(overwrite_location_, branch->GetOffsetLocation());
3207 Auipc(AT, High16Bits(offset));
3208 Lwu(lhs, AT, Low16Bits(offset));
3209 break;
3210 case Branch::kFarLiteralLong:
3211 offset += (offset & 0x8000) << 1; // Account for sign extension in ld.
3212 CHECK_EQ(overwrite_location_, branch->GetOffsetLocation());
3213 Auipc(AT, High16Bits(offset));
3214 Ld(lhs, AT, Low16Bits(offset));
Alexey Frunzea0e87b02015-09-24 22:57:20 -07003215 break;
3216 }
3217 CHECK_EQ(overwrite_location_, branch->GetEndLocation());
3218 CHECK_LT(branch->GetSize(), static_cast<uint32_t>(Branch::kMaxBranchSize));
Alexey Frunze4dda3372015-06-01 18:31:49 -07003219}
3220
Alexey Frunze0cab6562017-07-25 15:19:36 -07003221void Mips64Assembler::Bc(Mips64Label* label, bool is_bare) {
3222 Buncond(label, is_bare);
Alexey Frunze4dda3372015-06-01 18:31:49 -07003223}
3224
Alexey Frunze0cab6562017-07-25 15:19:36 -07003225void Mips64Assembler::Balc(Mips64Label* label, bool is_bare) {
3226 Call(label, is_bare);
Alexey Frunze4dda3372015-06-01 18:31:49 -07003227}
3228
Alexey Frunze0cab6562017-07-25 15:19:36 -07003229void Mips64Assembler::Bltc(GpuRegister rs, GpuRegister rt, Mips64Label* label, bool is_bare) {
3230 Bcond(label, /* is_r6 */ true, is_bare, kCondLT, rs, rt);
Alexey Frunze4dda3372015-06-01 18:31:49 -07003231}
3232
Alexey Frunze0cab6562017-07-25 15:19:36 -07003233void Mips64Assembler::Bltzc(GpuRegister rt, Mips64Label* label, bool is_bare) {
3234 Bcond(label, /* is_r6 */ true, is_bare, kCondLTZ, rt);
Alexey Frunze4dda3372015-06-01 18:31:49 -07003235}
3236
Alexey Frunze0cab6562017-07-25 15:19:36 -07003237void Mips64Assembler::Bgtzc(GpuRegister rt, Mips64Label* label, bool is_bare) {
3238 Bcond(label, /* is_r6 */ true, is_bare, kCondGTZ, rt);
Alexey Frunze4dda3372015-06-01 18:31:49 -07003239}
3240
Alexey Frunze0cab6562017-07-25 15:19:36 -07003241void Mips64Assembler::Bgec(GpuRegister rs, GpuRegister rt, Mips64Label* label, bool is_bare) {
3242 Bcond(label, /* is_r6 */ true, is_bare, kCondGE, rs, rt);
Alexey Frunze4dda3372015-06-01 18:31:49 -07003243}
3244
Alexey Frunze0cab6562017-07-25 15:19:36 -07003245void Mips64Assembler::Bgezc(GpuRegister rt, Mips64Label* label, bool is_bare) {
3246 Bcond(label, /* is_r6 */ true, is_bare, kCondGEZ, rt);
Alexey Frunze4dda3372015-06-01 18:31:49 -07003247}
3248
Alexey Frunze0cab6562017-07-25 15:19:36 -07003249void Mips64Assembler::Blezc(GpuRegister rt, Mips64Label* label, bool is_bare) {
3250 Bcond(label, /* is_r6 */ true, is_bare, kCondLEZ, rt);
Alexey Frunze4dda3372015-06-01 18:31:49 -07003251}
3252
Alexey Frunze0cab6562017-07-25 15:19:36 -07003253void Mips64Assembler::Bltuc(GpuRegister rs, GpuRegister rt, Mips64Label* label, bool is_bare) {
3254 Bcond(label, /* is_r6 */ true, is_bare, kCondLTU, rs, rt);
Alexey Frunze4dda3372015-06-01 18:31:49 -07003255}
3256
Alexey Frunze0cab6562017-07-25 15:19:36 -07003257void Mips64Assembler::Bgeuc(GpuRegister rs, GpuRegister rt, Mips64Label* label, bool is_bare) {
3258 Bcond(label, /* is_r6 */ true, is_bare, kCondGEU, rs, rt);
Alexey Frunze4dda3372015-06-01 18:31:49 -07003259}
3260
Alexey Frunze0cab6562017-07-25 15:19:36 -07003261void Mips64Assembler::Beqc(GpuRegister rs, GpuRegister rt, Mips64Label* label, bool is_bare) {
3262 Bcond(label, /* is_r6 */ true, is_bare, kCondEQ, rs, rt);
Alexey Frunzea0e87b02015-09-24 22:57:20 -07003263}
3264
Alexey Frunze0cab6562017-07-25 15:19:36 -07003265void Mips64Assembler::Bnec(GpuRegister rs, GpuRegister rt, Mips64Label* label, bool is_bare) {
3266 Bcond(label, /* is_r6 */ true, is_bare, kCondNE, rs, rt);
Alexey Frunzea0e87b02015-09-24 22:57:20 -07003267}
3268
Alexey Frunze0cab6562017-07-25 15:19:36 -07003269void Mips64Assembler::Beqzc(GpuRegister rs, Mips64Label* label, bool is_bare) {
3270 Bcond(label, /* is_r6 */ true, is_bare, kCondEQZ, rs);
Alexey Frunzea0e87b02015-09-24 22:57:20 -07003271}
3272
Alexey Frunze0cab6562017-07-25 15:19:36 -07003273void Mips64Assembler::Bnezc(GpuRegister rs, Mips64Label* label, bool is_bare) {
3274 Bcond(label, /* is_r6 */ true, is_bare, kCondNEZ, rs);
Andreas Gampe57b34292015-01-14 15:45:59 -08003275}
3276
Alexey Frunze0cab6562017-07-25 15:19:36 -07003277void Mips64Assembler::Bc1eqz(FpuRegister ft, Mips64Label* label, bool is_bare) {
3278 Bcond(label, /* is_r6 */ true, is_bare, kCondF, static_cast<GpuRegister>(ft), ZERO);
Alexey Frunze299a9392015-12-08 16:08:02 -08003279}
3280
Alexey Frunze0cab6562017-07-25 15:19:36 -07003281void Mips64Assembler::Bc1nez(FpuRegister ft, Mips64Label* label, bool is_bare) {
3282 Bcond(label, /* is_r6 */ true, is_bare, kCondT, static_cast<GpuRegister>(ft), ZERO);
3283}
3284
3285void Mips64Assembler::Bltz(GpuRegister rt, Mips64Label* label, bool is_bare) {
3286 CHECK(is_bare);
3287 Bcond(label, /* is_r6 */ false, is_bare, kCondLTZ, rt);
3288}
3289
3290void Mips64Assembler::Bgtz(GpuRegister rt, Mips64Label* label, bool is_bare) {
3291 CHECK(is_bare);
3292 Bcond(label, /* is_r6 */ false, is_bare, kCondGTZ, rt);
3293}
3294
3295void Mips64Assembler::Bgez(GpuRegister rt, Mips64Label* label, bool is_bare) {
3296 CHECK(is_bare);
3297 Bcond(label, /* is_r6 */ false, is_bare, kCondGEZ, rt);
3298}
3299
3300void Mips64Assembler::Blez(GpuRegister rt, Mips64Label* label, bool is_bare) {
3301 CHECK(is_bare);
3302 Bcond(label, /* is_r6 */ false, is_bare, kCondLEZ, rt);
3303}
3304
3305void Mips64Assembler::Beq(GpuRegister rs, GpuRegister rt, Mips64Label* label, bool is_bare) {
3306 CHECK(is_bare);
3307 Bcond(label, /* is_r6 */ false, is_bare, kCondEQ, rs, rt);
3308}
3309
3310void Mips64Assembler::Bne(GpuRegister rs, GpuRegister rt, Mips64Label* label, bool is_bare) {
3311 CHECK(is_bare);
3312 Bcond(label, /* is_r6 */ false, is_bare, kCondNE, rs, rt);
3313}
3314
3315void Mips64Assembler::Beqz(GpuRegister rs, Mips64Label* label, bool is_bare) {
3316 CHECK(is_bare);
3317 Bcond(label, /* is_r6 */ false, is_bare, kCondEQZ, rs);
3318}
3319
3320void Mips64Assembler::Bnez(GpuRegister rs, Mips64Label* label, bool is_bare) {
3321 CHECK(is_bare);
3322 Bcond(label, /* is_r6 */ false, is_bare, kCondNEZ, rs);
Alexey Frunze299a9392015-12-08 16:08:02 -08003323}
3324
Chris Larsenc3fec0c2016-12-15 11:44:14 -08003325void Mips64Assembler::AdjustBaseAndOffset(GpuRegister& base,
3326 int32_t& offset,
3327 bool is_doubleword) {
3328 // This method is used to adjust the base register and offset pair
3329 // for a load/store when the offset doesn't fit into int16_t.
3330 // It is assumed that `base + offset` is sufficiently aligned for memory
3331 // operands that are machine word in size or smaller. For doubleword-sized
3332 // operands it's assumed that `base` is a multiple of 8, while `offset`
3333 // may be a multiple of 4 (e.g. 4-byte-aligned long and double arguments
3334 // and spilled variables on the stack accessed relative to the stack
3335 // pointer register).
3336 // We preserve the "alignment" of `offset` by adjusting it by a multiple of 8.
3337 CHECK_NE(base, AT); // Must not overwrite the register `base` while loading `offset`.
3338
3339 bool doubleword_aligned = IsAligned<kMips64DoublewordSize>(offset);
3340 bool two_accesses = is_doubleword && !doubleword_aligned;
3341
3342 // IsInt<16> must be passed a signed value, hence the static cast below.
3343 if (IsInt<16>(offset) &&
3344 (!two_accesses || IsInt<16>(static_cast<int32_t>(offset + kMips64WordSize)))) {
3345 // Nothing to do: `offset` (and, if needed, `offset + 4`) fits into int16_t.
3346 return;
3347 }
3348
3349 // Remember the "(mis)alignment" of `offset`, it will be checked at the end.
3350 uint32_t misalignment = offset & (kMips64DoublewordSize - 1);
3351
3352 // First, see if `offset` can be represented as a sum of two 16-bit signed
3353 // offsets. This can save an instruction.
3354 // To simplify matters, only do this for a symmetric range of offsets from
3355 // about -64KB to about +64KB, allowing further addition of 4 when accessing
3356 // 64-bit variables with two 32-bit accesses.
3357 constexpr int32_t kMinOffsetForSimpleAdjustment = 0x7ff8; // Max int16_t that's a multiple of 8.
3358 constexpr int32_t kMaxOffsetForSimpleAdjustment = 2 * kMinOffsetForSimpleAdjustment;
3359
3360 if (0 <= offset && offset <= kMaxOffsetForSimpleAdjustment) {
3361 Daddiu(AT, base, kMinOffsetForSimpleAdjustment);
3362 offset -= kMinOffsetForSimpleAdjustment;
3363 } else if (-kMaxOffsetForSimpleAdjustment <= offset && offset < 0) {
3364 Daddiu(AT, base, -kMinOffsetForSimpleAdjustment);
3365 offset += kMinOffsetForSimpleAdjustment;
3366 } else {
3367 // In more complex cases take advantage of the daui instruction, e.g.:
3368 // daui AT, base, offset_high
3369 // [dahi AT, 1] // When `offset` is close to +2GB.
3370 // lw reg_lo, offset_low(AT)
3371 // [lw reg_hi, (offset_low+4)(AT)] // If misaligned 64-bit load.
3372 // or when offset_low+4 overflows int16_t:
3373 // daui AT, base, offset_high
3374 // daddiu AT, AT, 8
3375 // lw reg_lo, (offset_low-8)(AT)
3376 // lw reg_hi, (offset_low-4)(AT)
3377 int16_t offset_low = Low16Bits(offset);
3378 int32_t offset_low32 = offset_low;
3379 int16_t offset_high = High16Bits(offset);
3380 bool increment_hi16 = offset_low < 0;
3381 bool overflow_hi16 = false;
3382
3383 if (increment_hi16) {
3384 offset_high++;
3385 overflow_hi16 = (offset_high == -32768);
3386 }
3387 Daui(AT, base, offset_high);
3388
3389 if (overflow_hi16) {
3390 Dahi(AT, 1);
3391 }
3392
3393 if (two_accesses && !IsInt<16>(static_cast<int32_t>(offset_low32 + kMips64WordSize))) {
3394 // Avoid overflow in the 16-bit offset of the load/store instruction when adding 4.
3395 Daddiu(AT, AT, kMips64DoublewordSize);
3396 offset_low32 -= kMips64DoublewordSize;
3397 }
3398
3399 offset = offset_low32;
3400 }
3401 base = AT;
3402
3403 CHECK(IsInt<16>(offset));
3404 if (two_accesses) {
3405 CHECK(IsInt<16>(static_cast<int32_t>(offset + kMips64WordSize)));
3406 }
3407 CHECK_EQ(misalignment, offset & (kMips64DoublewordSize - 1));
3408}
3409
Goran Jakovljevicd8b6a532017-04-20 11:42:30 +02003410void Mips64Assembler::AdjustBaseOffsetAndElementSizeShift(GpuRegister& base,
3411 int32_t& offset,
3412 int& element_size_shift) {
3413 // This method is used to adjust the base register, offset and element_size_shift
3414 // for a vector load/store when the offset doesn't fit into allowed number of bits.
3415 // MSA ld.df and st.df instructions take signed offsets as arguments, but maximum
3416 // offset is dependant on the size of the data format df (10-bit offsets for ld.b,
3417 // 11-bit for ld.h, 12-bit for ld.w and 13-bit for ld.d).
3418 // If element_size_shift is non-negative at entry, it won't be changed, but offset
3419 // will be checked for appropriate alignment. If negative at entry, it will be
3420 // adjusted based on offset for maximum fit.
3421 // It's assumed that `base` is a multiple of 8.
3422
3423 CHECK_NE(base, AT); // Must not overwrite the register `base` while loading `offset`.
3424
3425 if (element_size_shift >= 0) {
3426 CHECK_LE(element_size_shift, TIMES_8);
3427 CHECK_GE(JAVASTYLE_CTZ(offset), element_size_shift);
3428 } else if (IsAligned<kMips64DoublewordSize>(offset)) {
3429 element_size_shift = TIMES_8;
3430 } else if (IsAligned<kMips64WordSize>(offset)) {
3431 element_size_shift = TIMES_4;
3432 } else if (IsAligned<kMips64HalfwordSize>(offset)) {
3433 element_size_shift = TIMES_2;
3434 } else {
3435 element_size_shift = TIMES_1;
3436 }
3437
3438 const int low_len = 10 + element_size_shift; // How many low bits of `offset` ld.df/st.df
3439 // will take.
3440 int16_t low = offset & ((1 << low_len) - 1); // Isolate these bits.
3441 low -= (low & (1 << (low_len - 1))) << 1; // Sign-extend these bits.
3442 if (low == offset) {
3443 return; // `offset` fits into ld.df/st.df.
3444 }
3445
3446 // First, see if `offset` can be represented as a sum of two signed offsets.
3447 // This can save an instruction.
3448
3449 // Max int16_t that's a multiple of element size.
3450 const int32_t kMaxDeltaForSimpleAdjustment = 0x8000 - (1 << element_size_shift);
3451 // Max ld.df/st.df offset that's a multiple of element size.
3452 const int32_t kMaxLoadStoreOffset = 0x1ff << element_size_shift;
3453 const int32_t kMaxOffsetForSimpleAdjustment = kMaxDeltaForSimpleAdjustment + kMaxLoadStoreOffset;
3454
3455 if (IsInt<16>(offset)) {
3456 Daddiu(AT, base, offset);
3457 offset = 0;
3458 } else if (0 <= offset && offset <= kMaxOffsetForSimpleAdjustment) {
3459 Daddiu(AT, base, kMaxDeltaForSimpleAdjustment);
3460 offset -= kMaxDeltaForSimpleAdjustment;
3461 } else if (-kMaxOffsetForSimpleAdjustment <= offset && offset < 0) {
3462 Daddiu(AT, base, -kMaxDeltaForSimpleAdjustment);
3463 offset += kMaxDeltaForSimpleAdjustment;
3464 } else {
3465 // Let's treat `offset` as 64-bit to simplify handling of sign
3466 // extensions in the instructions that supply its smaller signed parts.
3467 //
3468 // 16-bit or smaller parts of `offset`:
3469 // |63 top 48|47 hi 32|31 upper 16|15 mid 13-10|12-9 low 0|
3470 //
3471 // Instructions that supply each part as a signed integer addend:
3472 // |dati |dahi |daui |daddiu |ld.df/st.df |
3473 //
3474 // `top` is always 0, so dati isn't used.
3475 // `hi` is 1 when `offset` is close to +2GB and 0 otherwise.
3476 uint64_t tmp = static_cast<uint64_t>(offset) - low; // Exclude `low` from the rest of `offset`
3477 // (accounts for sign of `low`).
3478 tmp += (tmp & (UINT64_C(1) << 15)) << 1; // Account for sign extension in daddiu.
3479 tmp += (tmp & (UINT64_C(1) << 31)) << 1; // Account for sign extension in daui.
3480 int16_t mid = Low16Bits(tmp);
3481 int16_t upper = High16Bits(tmp);
3482 int16_t hi = Low16Bits(High32Bits(tmp));
3483 Daui(AT, base, upper);
3484 if (hi != 0) {
3485 CHECK_EQ(hi, 1);
3486 Dahi(AT, hi);
3487 }
3488 if (mid != 0) {
3489 Daddiu(AT, AT, mid);
3490 }
3491 offset = low;
3492 }
3493 base = AT;
3494 CHECK_GE(JAVASTYLE_CTZ(offset), element_size_shift);
3495 CHECK(IsInt<10>(offset >> element_size_shift));
3496}
3497
Tijana Jakovljevic57433862017-01-17 16:59:03 +01003498void Mips64Assembler::LoadFromOffset(LoadOperandType type,
3499 GpuRegister reg,
3500 GpuRegister base,
Andreas Gampe57b34292015-01-14 15:45:59 -08003501 int32_t offset) {
Tijana Jakovljevic57433862017-01-17 16:59:03 +01003502 LoadFromOffset<>(type, reg, base, offset);
Andreas Gampe57b34292015-01-14 15:45:59 -08003503}
3504
Tijana Jakovljevic57433862017-01-17 16:59:03 +01003505void Mips64Assembler::LoadFpuFromOffset(LoadOperandType type,
3506 FpuRegister reg,
3507 GpuRegister base,
Andreas Gampe57b34292015-01-14 15:45:59 -08003508 int32_t offset) {
Tijana Jakovljevic57433862017-01-17 16:59:03 +01003509 LoadFpuFromOffset<>(type, reg, base, offset);
Andreas Gampe57b34292015-01-14 15:45:59 -08003510}
3511
3512void Mips64Assembler::EmitLoad(ManagedRegister m_dst, GpuRegister src_register, int32_t src_offset,
3513 size_t size) {
3514 Mips64ManagedRegister dst = m_dst.AsMips64();
3515 if (dst.IsNoRegister()) {
3516 CHECK_EQ(0u, size) << dst;
3517 } else if (dst.IsGpuRegister()) {
3518 if (size == 4) {
Andreas Gampe57b34292015-01-14 15:45:59 -08003519 LoadFromOffset(kLoadWord, dst.AsGpuRegister(), src_register, src_offset);
3520 } else if (size == 8) {
3521 CHECK_EQ(8u, size) << dst;
3522 LoadFromOffset(kLoadDoubleword, dst.AsGpuRegister(), src_register, src_offset);
3523 } else {
3524 UNIMPLEMENTED(FATAL) << "We only support Load() of size 4 and 8";
3525 }
3526 } else if (dst.IsFpuRegister()) {
3527 if (size == 4) {
3528 CHECK_EQ(4u, size) << dst;
3529 LoadFpuFromOffset(kLoadWord, dst.AsFpuRegister(), src_register, src_offset);
3530 } else if (size == 8) {
3531 CHECK_EQ(8u, size) << dst;
3532 LoadFpuFromOffset(kLoadDoubleword, dst.AsFpuRegister(), src_register, src_offset);
3533 } else {
3534 UNIMPLEMENTED(FATAL) << "We only support Load() of size 4 and 8";
3535 }
3536 }
3537}
3538
Tijana Jakovljevic57433862017-01-17 16:59:03 +01003539void Mips64Assembler::StoreToOffset(StoreOperandType type,
3540 GpuRegister reg,
3541 GpuRegister base,
Andreas Gampe57b34292015-01-14 15:45:59 -08003542 int32_t offset) {
Tijana Jakovljevic57433862017-01-17 16:59:03 +01003543 StoreToOffset<>(type, reg, base, offset);
Andreas Gampe57b34292015-01-14 15:45:59 -08003544}
3545
Tijana Jakovljevic57433862017-01-17 16:59:03 +01003546void Mips64Assembler::StoreFpuToOffset(StoreOperandType type,
3547 FpuRegister reg,
3548 GpuRegister base,
Andreas Gampe57b34292015-01-14 15:45:59 -08003549 int32_t offset) {
Tijana Jakovljevic57433862017-01-17 16:59:03 +01003550 StoreFpuToOffset<>(type, reg, base, offset);
Andreas Gampe57b34292015-01-14 15:45:59 -08003551}
3552
David Srbeckydd973932015-04-07 20:29:48 +01003553static dwarf::Reg DWARFReg(GpuRegister reg) {
3554 return dwarf::Reg::Mips64Core(static_cast<int>(reg));
3555}
3556
Andreas Gampe57b34292015-01-14 15:45:59 -08003557constexpr size_t kFramePointerSize = 8;
3558
Vladimir Marko32248382016-05-19 10:37:24 +01003559void Mips64Assembler::BuildFrame(size_t frame_size,
3560 ManagedRegister method_reg,
3561 ArrayRef<const ManagedRegister> callee_save_regs,
Andreas Gampe57b34292015-01-14 15:45:59 -08003562 const ManagedRegisterEntrySpills& entry_spills) {
3563 CHECK_ALIGNED(frame_size, kStackAlignment);
Alexey Frunzea0e87b02015-09-24 22:57:20 -07003564 DCHECK(!overwriting_);
Andreas Gampe57b34292015-01-14 15:45:59 -08003565
3566 // Increase frame to required size.
3567 IncreaseFrameSize(frame_size);
3568
3569 // Push callee saves and return address
3570 int stack_offset = frame_size - kFramePointerSize;
3571 StoreToOffset(kStoreDoubleword, RA, SP, stack_offset);
David Srbeckydd973932015-04-07 20:29:48 +01003572 cfi_.RelOffset(DWARFReg(RA), stack_offset);
Andreas Gampe57b34292015-01-14 15:45:59 -08003573 for (int i = callee_save_regs.size() - 1; i >= 0; --i) {
3574 stack_offset -= kFramePointerSize;
Vladimir Marko32248382016-05-19 10:37:24 +01003575 GpuRegister reg = callee_save_regs[i].AsMips64().AsGpuRegister();
Andreas Gampe57b34292015-01-14 15:45:59 -08003576 StoreToOffset(kStoreDoubleword, reg, SP, stack_offset);
David Srbeckydd973932015-04-07 20:29:48 +01003577 cfi_.RelOffset(DWARFReg(reg), stack_offset);
Andreas Gampe57b34292015-01-14 15:45:59 -08003578 }
3579
3580 // Write out Method*.
Mathieu Chartiere401d142015-04-22 13:56:20 -07003581 StoreToOffset(kStoreDoubleword, method_reg.AsMips64().AsGpuRegister(), SP, 0);
Andreas Gampe57b34292015-01-14 15:45:59 -08003582
3583 // Write out entry spills.
Mathieu Chartiere401d142015-04-22 13:56:20 -07003584 int32_t offset = frame_size + kFramePointerSize;
Andreas Gampe57b34292015-01-14 15:45:59 -08003585 for (size_t i = 0; i < entry_spills.size(); ++i) {
Vladimir Marko32248382016-05-19 10:37:24 +01003586 Mips64ManagedRegister reg = entry_spills[i].AsMips64();
Andreas Gampe57b34292015-01-14 15:45:59 -08003587 ManagedRegisterSpill spill = entry_spills.at(i);
3588 int32_t size = spill.getSize();
3589 if (reg.IsNoRegister()) {
3590 // only increment stack offset.
3591 offset += size;
3592 } else if (reg.IsFpuRegister()) {
Alexey Frunze4dda3372015-06-01 18:31:49 -07003593 StoreFpuToOffset((size == 4) ? kStoreWord : kStoreDoubleword,
3594 reg.AsFpuRegister(), SP, offset);
Andreas Gampe57b34292015-01-14 15:45:59 -08003595 offset += size;
3596 } else if (reg.IsGpuRegister()) {
Alexey Frunze4dda3372015-06-01 18:31:49 -07003597 StoreToOffset((size == 4) ? kStoreWord : kStoreDoubleword,
3598 reg.AsGpuRegister(), SP, offset);
Andreas Gampe57b34292015-01-14 15:45:59 -08003599 offset += size;
3600 }
3601 }
3602}
3603
3604void Mips64Assembler::RemoveFrame(size_t frame_size,
Roland Levillain0d127e12017-07-05 17:01:11 +01003605 ArrayRef<const ManagedRegister> callee_save_regs,
3606 bool may_suspend ATTRIBUTE_UNUSED) {
Andreas Gampe57b34292015-01-14 15:45:59 -08003607 CHECK_ALIGNED(frame_size, kStackAlignment);
Alexey Frunzea0e87b02015-09-24 22:57:20 -07003608 DCHECK(!overwriting_);
David Srbeckydd973932015-04-07 20:29:48 +01003609 cfi_.RememberState();
Andreas Gampe57b34292015-01-14 15:45:59 -08003610
3611 // Pop callee saves and return address
3612 int stack_offset = frame_size - (callee_save_regs.size() * kFramePointerSize) - kFramePointerSize;
3613 for (size_t i = 0; i < callee_save_regs.size(); ++i) {
Vladimir Marko32248382016-05-19 10:37:24 +01003614 GpuRegister reg = callee_save_regs[i].AsMips64().AsGpuRegister();
Andreas Gampe57b34292015-01-14 15:45:59 -08003615 LoadFromOffset(kLoadDoubleword, reg, SP, stack_offset);
David Srbeckydd973932015-04-07 20:29:48 +01003616 cfi_.Restore(DWARFReg(reg));
Andreas Gampe57b34292015-01-14 15:45:59 -08003617 stack_offset += kFramePointerSize;
3618 }
3619 LoadFromOffset(kLoadDoubleword, RA, SP, stack_offset);
David Srbeckydd973932015-04-07 20:29:48 +01003620 cfi_.Restore(DWARFReg(RA));
Andreas Gampe57b34292015-01-14 15:45:59 -08003621
3622 // Decrease frame to required size.
3623 DecreaseFrameSize(frame_size);
3624
3625 // Then jump to the return address.
3626 Jr(RA);
Alexey Frunzea0e87b02015-09-24 22:57:20 -07003627 Nop();
David Srbeckydd973932015-04-07 20:29:48 +01003628
3629 // The CFI should be restored for any code that follows the exit block.
3630 cfi_.RestoreState();
3631 cfi_.DefCFAOffset(frame_size);
Andreas Gampe57b34292015-01-14 15:45:59 -08003632}
3633
3634void Mips64Assembler::IncreaseFrameSize(size_t adjust) {
Alexey Frunze4dda3372015-06-01 18:31:49 -07003635 CHECK_ALIGNED(adjust, kFramePointerSize);
Alexey Frunzea0e87b02015-09-24 22:57:20 -07003636 DCHECK(!overwriting_);
Alexey Frunze4dda3372015-06-01 18:31:49 -07003637 Daddiu64(SP, SP, static_cast<int32_t>(-adjust));
David Srbeckydd973932015-04-07 20:29:48 +01003638 cfi_.AdjustCFAOffset(adjust);
Andreas Gampe57b34292015-01-14 15:45:59 -08003639}
3640
3641void Mips64Assembler::DecreaseFrameSize(size_t adjust) {
Alexey Frunze4dda3372015-06-01 18:31:49 -07003642 CHECK_ALIGNED(adjust, kFramePointerSize);
Alexey Frunzea0e87b02015-09-24 22:57:20 -07003643 DCHECK(!overwriting_);
Alexey Frunze4dda3372015-06-01 18:31:49 -07003644 Daddiu64(SP, SP, static_cast<int32_t>(adjust));
David Srbeckydd973932015-04-07 20:29:48 +01003645 cfi_.AdjustCFAOffset(-adjust);
Andreas Gampe57b34292015-01-14 15:45:59 -08003646}
3647
3648void Mips64Assembler::Store(FrameOffset dest, ManagedRegister msrc, size_t size) {
3649 Mips64ManagedRegister src = msrc.AsMips64();
3650 if (src.IsNoRegister()) {
3651 CHECK_EQ(0u, size);
3652 } else if (src.IsGpuRegister()) {
3653 CHECK(size == 4 || size == 8) << size;
3654 if (size == 8) {
3655 StoreToOffset(kStoreDoubleword, src.AsGpuRegister(), SP, dest.Int32Value());
3656 } else if (size == 4) {
3657 StoreToOffset(kStoreWord, src.AsGpuRegister(), SP, dest.Int32Value());
3658 } else {
3659 UNIMPLEMENTED(FATAL) << "We only support Store() of size 4 and 8";
3660 }
3661 } else if (src.IsFpuRegister()) {
3662 CHECK(size == 4 || size == 8) << size;
3663 if (size == 8) {
3664 StoreFpuToOffset(kStoreDoubleword, src.AsFpuRegister(), SP, dest.Int32Value());
3665 } else if (size == 4) {
3666 StoreFpuToOffset(kStoreWord, src.AsFpuRegister(), SP, dest.Int32Value());
3667 } else {
3668 UNIMPLEMENTED(FATAL) << "We only support Store() of size 4 and 8";
3669 }
3670 }
3671}
3672
3673void Mips64Assembler::StoreRef(FrameOffset dest, ManagedRegister msrc) {
3674 Mips64ManagedRegister src = msrc.AsMips64();
3675 CHECK(src.IsGpuRegister());
3676 StoreToOffset(kStoreWord, src.AsGpuRegister(), SP, dest.Int32Value());
3677}
3678
3679void Mips64Assembler::StoreRawPtr(FrameOffset dest, ManagedRegister msrc) {
3680 Mips64ManagedRegister src = msrc.AsMips64();
3681 CHECK(src.IsGpuRegister());
3682 StoreToOffset(kStoreDoubleword, src.AsGpuRegister(), SP, dest.Int32Value());
3683}
3684
3685void Mips64Assembler::StoreImmediateToFrame(FrameOffset dest, uint32_t imm,
3686 ManagedRegister mscratch) {
3687 Mips64ManagedRegister scratch = mscratch.AsMips64();
3688 CHECK(scratch.IsGpuRegister()) << scratch;
Alexey Frunze4dda3372015-06-01 18:31:49 -07003689 LoadConst32(scratch.AsGpuRegister(), imm);
Andreas Gampe57b34292015-01-14 15:45:59 -08003690 StoreToOffset(kStoreWord, scratch.AsGpuRegister(), SP, dest.Int32Value());
3691}
3692
Andreas Gampe3b165bc2016-08-01 22:07:04 -07003693void Mips64Assembler::StoreStackOffsetToThread(ThreadOffset64 thr_offs,
3694 FrameOffset fr_offs,
3695 ManagedRegister mscratch) {
Andreas Gampe57b34292015-01-14 15:45:59 -08003696 Mips64ManagedRegister scratch = mscratch.AsMips64();
3697 CHECK(scratch.IsGpuRegister()) << scratch;
Alexey Frunze4dda3372015-06-01 18:31:49 -07003698 Daddiu64(scratch.AsGpuRegister(), SP, fr_offs.Int32Value());
Andreas Gampe57b34292015-01-14 15:45:59 -08003699 StoreToOffset(kStoreDoubleword, scratch.AsGpuRegister(), S1, thr_offs.Int32Value());
3700}
3701
Andreas Gampe3b165bc2016-08-01 22:07:04 -07003702void Mips64Assembler::StoreStackPointerToThread(ThreadOffset64 thr_offs) {
Andreas Gampe57b34292015-01-14 15:45:59 -08003703 StoreToOffset(kStoreDoubleword, SP, S1, thr_offs.Int32Value());
3704}
3705
3706void Mips64Assembler::StoreSpanning(FrameOffset dest, ManagedRegister msrc,
3707 FrameOffset in_off, ManagedRegister mscratch) {
3708 Mips64ManagedRegister src = msrc.AsMips64();
3709 Mips64ManagedRegister scratch = mscratch.AsMips64();
3710 StoreToOffset(kStoreDoubleword, src.AsGpuRegister(), SP, dest.Int32Value());
3711 LoadFromOffset(kLoadDoubleword, scratch.AsGpuRegister(), SP, in_off.Int32Value());
3712 StoreToOffset(kStoreDoubleword, scratch.AsGpuRegister(), SP, dest.Int32Value() + 8);
3713}
3714
3715void Mips64Assembler::Load(ManagedRegister mdest, FrameOffset src, size_t size) {
3716 return EmitLoad(mdest, SP, src.Int32Value(), size);
3717}
3718
Andreas Gampe3b165bc2016-08-01 22:07:04 -07003719void Mips64Assembler::LoadFromThread(ManagedRegister mdest, ThreadOffset64 src, size_t size) {
Andreas Gampe57b34292015-01-14 15:45:59 -08003720 return EmitLoad(mdest, S1, src.Int32Value(), size);
3721}
3722
3723void Mips64Assembler::LoadRef(ManagedRegister mdest, FrameOffset src) {
3724 Mips64ManagedRegister dest = mdest.AsMips64();
3725 CHECK(dest.IsGpuRegister());
Douglas Leungd90957f2015-04-30 19:22:49 -07003726 LoadFromOffset(kLoadUnsignedWord, dest.AsGpuRegister(), SP, src.Int32Value());
Andreas Gampe57b34292015-01-14 15:45:59 -08003727}
3728
Mathieu Chartiere401d142015-04-22 13:56:20 -07003729void Mips64Assembler::LoadRef(ManagedRegister mdest, ManagedRegister base, MemberOffset offs,
Roland Levillain4d027112015-07-01 15:41:14 +01003730 bool unpoison_reference) {
Andreas Gampe57b34292015-01-14 15:45:59 -08003731 Mips64ManagedRegister dest = mdest.AsMips64();
Douglas Leungd90957f2015-04-30 19:22:49 -07003732 CHECK(dest.IsGpuRegister() && base.AsMips64().IsGpuRegister());
3733 LoadFromOffset(kLoadUnsignedWord, dest.AsGpuRegister(),
Andreas Gampe57b34292015-01-14 15:45:59 -08003734 base.AsMips64().AsGpuRegister(), offs.Int32Value());
Alexey Frunzec061de12017-02-14 13:27:23 -08003735 if (unpoison_reference) {
3736 MaybeUnpoisonHeapReference(dest.AsGpuRegister());
Andreas Gampe57b34292015-01-14 15:45:59 -08003737 }
3738}
3739
3740void Mips64Assembler::LoadRawPtr(ManagedRegister mdest, ManagedRegister base,
Alexey Frunze4dda3372015-06-01 18:31:49 -07003741 Offset offs) {
Andreas Gampe57b34292015-01-14 15:45:59 -08003742 Mips64ManagedRegister dest = mdest.AsMips64();
Alexey Frunze4dda3372015-06-01 18:31:49 -07003743 CHECK(dest.IsGpuRegister() && base.AsMips64().IsGpuRegister());
Andreas Gampe57b34292015-01-14 15:45:59 -08003744 LoadFromOffset(kLoadDoubleword, dest.AsGpuRegister(),
3745 base.AsMips64().AsGpuRegister(), offs.Int32Value());
3746}
3747
Andreas Gampe3b165bc2016-08-01 22:07:04 -07003748void Mips64Assembler::LoadRawPtrFromThread(ManagedRegister mdest, ThreadOffset64 offs) {
Andreas Gampe57b34292015-01-14 15:45:59 -08003749 Mips64ManagedRegister dest = mdest.AsMips64();
3750 CHECK(dest.IsGpuRegister());
3751 LoadFromOffset(kLoadDoubleword, dest.AsGpuRegister(), S1, offs.Int32Value());
3752}
3753
Alexey Frunzea0e87b02015-09-24 22:57:20 -07003754void Mips64Assembler::SignExtend(ManagedRegister mreg ATTRIBUTE_UNUSED,
3755 size_t size ATTRIBUTE_UNUSED) {
3756 UNIMPLEMENTED(FATAL) << "No sign extension necessary for MIPS64";
Andreas Gampe57b34292015-01-14 15:45:59 -08003757}
3758
Alexey Frunzea0e87b02015-09-24 22:57:20 -07003759void Mips64Assembler::ZeroExtend(ManagedRegister mreg ATTRIBUTE_UNUSED,
3760 size_t size ATTRIBUTE_UNUSED) {
3761 UNIMPLEMENTED(FATAL) << "No zero extension necessary for MIPS64";
Andreas Gampe57b34292015-01-14 15:45:59 -08003762}
3763
3764void Mips64Assembler::Move(ManagedRegister mdest, ManagedRegister msrc, size_t size) {
3765 Mips64ManagedRegister dest = mdest.AsMips64();
3766 Mips64ManagedRegister src = msrc.AsMips64();
3767 if (!dest.Equals(src)) {
3768 if (dest.IsGpuRegister()) {
3769 CHECK(src.IsGpuRegister()) << src;
3770 Move(dest.AsGpuRegister(), src.AsGpuRegister());
3771 } else if (dest.IsFpuRegister()) {
3772 CHECK(src.IsFpuRegister()) << src;
3773 if (size == 4) {
3774 MovS(dest.AsFpuRegister(), src.AsFpuRegister());
3775 } else if (size == 8) {
3776 MovD(dest.AsFpuRegister(), src.AsFpuRegister());
3777 } else {
3778 UNIMPLEMENTED(FATAL) << "We only support Copy() of size 4 and 8";
3779 }
3780 }
3781 }
3782}
3783
3784void Mips64Assembler::CopyRef(FrameOffset dest, FrameOffset src,
3785 ManagedRegister mscratch) {
3786 Mips64ManagedRegister scratch = mscratch.AsMips64();
3787 CHECK(scratch.IsGpuRegister()) << scratch;
3788 LoadFromOffset(kLoadWord, scratch.AsGpuRegister(), SP, src.Int32Value());
3789 StoreToOffset(kStoreWord, scratch.AsGpuRegister(), SP, dest.Int32Value());
3790}
3791
Andreas Gampe3b165bc2016-08-01 22:07:04 -07003792void Mips64Assembler::CopyRawPtrFromThread(FrameOffset fr_offs,
3793 ThreadOffset64 thr_offs,
3794 ManagedRegister mscratch) {
Andreas Gampe57b34292015-01-14 15:45:59 -08003795 Mips64ManagedRegister scratch = mscratch.AsMips64();
3796 CHECK(scratch.IsGpuRegister()) << scratch;
3797 LoadFromOffset(kLoadDoubleword, scratch.AsGpuRegister(), S1, thr_offs.Int32Value());
3798 StoreToOffset(kStoreDoubleword, scratch.AsGpuRegister(), SP, fr_offs.Int32Value());
3799}
3800
Andreas Gampe3b165bc2016-08-01 22:07:04 -07003801void Mips64Assembler::CopyRawPtrToThread(ThreadOffset64 thr_offs,
3802 FrameOffset fr_offs,
3803 ManagedRegister mscratch) {
Andreas Gampe57b34292015-01-14 15:45:59 -08003804 Mips64ManagedRegister scratch = mscratch.AsMips64();
3805 CHECK(scratch.IsGpuRegister()) << scratch;
3806 LoadFromOffset(kLoadDoubleword, scratch.AsGpuRegister(),
3807 SP, fr_offs.Int32Value());
3808 StoreToOffset(kStoreDoubleword, scratch.AsGpuRegister(),
3809 S1, thr_offs.Int32Value());
3810}
3811
3812void Mips64Assembler::Copy(FrameOffset dest, FrameOffset src,
3813 ManagedRegister mscratch, size_t size) {
3814 Mips64ManagedRegister scratch = mscratch.AsMips64();
3815 CHECK(scratch.IsGpuRegister()) << scratch;
3816 CHECK(size == 4 || size == 8) << size;
3817 if (size == 4) {
3818 LoadFromOffset(kLoadWord, scratch.AsGpuRegister(), SP, src.Int32Value());
Lazar Trsicf652d602015-06-24 16:30:21 +02003819 StoreToOffset(kStoreDoubleword, scratch.AsGpuRegister(), SP, dest.Int32Value());
Andreas Gampe57b34292015-01-14 15:45:59 -08003820 } else if (size == 8) {
3821 LoadFromOffset(kLoadDoubleword, scratch.AsGpuRegister(), SP, src.Int32Value());
3822 StoreToOffset(kStoreDoubleword, scratch.AsGpuRegister(), SP, dest.Int32Value());
3823 } else {
3824 UNIMPLEMENTED(FATAL) << "We only support Copy() of size 4 and 8";
3825 }
3826}
3827
3828void Mips64Assembler::Copy(FrameOffset dest, ManagedRegister src_base, Offset src_offset,
Alexey Frunze4dda3372015-06-01 18:31:49 -07003829 ManagedRegister mscratch, size_t size) {
Andreas Gampe57b34292015-01-14 15:45:59 -08003830 GpuRegister scratch = mscratch.AsMips64().AsGpuRegister();
3831 CHECK(size == 4 || size == 8) << size;
3832 if (size == 4) {
3833 LoadFromOffset(kLoadWord, scratch, src_base.AsMips64().AsGpuRegister(),
3834 src_offset.Int32Value());
Lazar Trsicf652d602015-06-24 16:30:21 +02003835 StoreToOffset(kStoreDoubleword, scratch, SP, dest.Int32Value());
Andreas Gampe57b34292015-01-14 15:45:59 -08003836 } else if (size == 8) {
3837 LoadFromOffset(kLoadDoubleword, scratch, src_base.AsMips64().AsGpuRegister(),
3838 src_offset.Int32Value());
3839 StoreToOffset(kStoreDoubleword, scratch, SP, dest.Int32Value());
3840 } else {
3841 UNIMPLEMENTED(FATAL) << "We only support Copy() of size 4 and 8";
3842 }
3843}
3844
3845void Mips64Assembler::Copy(ManagedRegister dest_base, Offset dest_offset, FrameOffset src,
Alexey Frunze4dda3372015-06-01 18:31:49 -07003846 ManagedRegister mscratch, size_t size) {
Andreas Gampe57b34292015-01-14 15:45:59 -08003847 GpuRegister scratch = mscratch.AsMips64().AsGpuRegister();
3848 CHECK(size == 4 || size == 8) << size;
3849 if (size == 4) {
3850 LoadFromOffset(kLoadWord, scratch, SP, src.Int32Value());
Lazar Trsicf652d602015-06-24 16:30:21 +02003851 StoreToOffset(kStoreDoubleword, scratch, dest_base.AsMips64().AsGpuRegister(),
Andreas Gampe57b34292015-01-14 15:45:59 -08003852 dest_offset.Int32Value());
3853 } else if (size == 8) {
3854 LoadFromOffset(kLoadDoubleword, scratch, SP, src.Int32Value());
3855 StoreToOffset(kStoreDoubleword, scratch, dest_base.AsMips64().AsGpuRegister(),
3856 dest_offset.Int32Value());
3857 } else {
3858 UNIMPLEMENTED(FATAL) << "We only support Copy() of size 4 and 8";
3859 }
3860}
3861
Alexey Frunzea0e87b02015-09-24 22:57:20 -07003862void Mips64Assembler::Copy(FrameOffset dest ATTRIBUTE_UNUSED,
3863 FrameOffset src_base ATTRIBUTE_UNUSED,
3864 Offset src_offset ATTRIBUTE_UNUSED,
3865 ManagedRegister mscratch ATTRIBUTE_UNUSED,
3866 size_t size ATTRIBUTE_UNUSED) {
3867 UNIMPLEMENTED(FATAL) << "No MIPS64 implementation";
Andreas Gampe57b34292015-01-14 15:45:59 -08003868}
3869
3870void Mips64Assembler::Copy(ManagedRegister dest, Offset dest_offset,
Alexey Frunze4dda3372015-06-01 18:31:49 -07003871 ManagedRegister src, Offset src_offset,
3872 ManagedRegister mscratch, size_t size) {
Andreas Gampe57b34292015-01-14 15:45:59 -08003873 GpuRegister scratch = mscratch.AsMips64().AsGpuRegister();
3874 CHECK(size == 4 || size == 8) << size;
3875 if (size == 4) {
3876 LoadFromOffset(kLoadWord, scratch, src.AsMips64().AsGpuRegister(), src_offset.Int32Value());
Lazar Trsicf652d602015-06-24 16:30:21 +02003877 StoreToOffset(kStoreDoubleword, scratch, dest.AsMips64().AsGpuRegister(), dest_offset.Int32Value());
Andreas Gampe57b34292015-01-14 15:45:59 -08003878 } else if (size == 8) {
3879 LoadFromOffset(kLoadDoubleword, scratch, src.AsMips64().AsGpuRegister(),
3880 src_offset.Int32Value());
3881 StoreToOffset(kStoreDoubleword, scratch, dest.AsMips64().AsGpuRegister(),
3882 dest_offset.Int32Value());
3883 } else {
3884 UNIMPLEMENTED(FATAL) << "We only support Copy() of size 4 and 8";
3885 }
3886}
3887
Alexey Frunzea0e87b02015-09-24 22:57:20 -07003888void Mips64Assembler::Copy(FrameOffset dest ATTRIBUTE_UNUSED,
3889 Offset dest_offset ATTRIBUTE_UNUSED,
3890 FrameOffset src ATTRIBUTE_UNUSED,
3891 Offset src_offset ATTRIBUTE_UNUSED,
3892 ManagedRegister mscratch ATTRIBUTE_UNUSED,
3893 size_t size ATTRIBUTE_UNUSED) {
3894 UNIMPLEMENTED(FATAL) << "No MIPS64 implementation";
Andreas Gampe57b34292015-01-14 15:45:59 -08003895}
3896
Alexey Frunzea0e87b02015-09-24 22:57:20 -07003897void Mips64Assembler::MemoryBarrier(ManagedRegister mreg ATTRIBUTE_UNUSED) {
Alexey Frunze4dda3372015-06-01 18:31:49 -07003898 // TODO: sync?
Alexey Frunzea0e87b02015-09-24 22:57:20 -07003899 UNIMPLEMENTED(FATAL) << "No MIPS64 implementation";
Andreas Gampe57b34292015-01-14 15:45:59 -08003900}
3901
3902void Mips64Assembler::CreateHandleScopeEntry(ManagedRegister mout_reg,
Alexey Frunze4dda3372015-06-01 18:31:49 -07003903 FrameOffset handle_scope_offset,
3904 ManagedRegister min_reg,
3905 bool null_allowed) {
Andreas Gampe57b34292015-01-14 15:45:59 -08003906 Mips64ManagedRegister out_reg = mout_reg.AsMips64();
3907 Mips64ManagedRegister in_reg = min_reg.AsMips64();
3908 CHECK(in_reg.IsNoRegister() || in_reg.IsGpuRegister()) << in_reg;
3909 CHECK(out_reg.IsGpuRegister()) << out_reg;
3910 if (null_allowed) {
Alexey Frunzea0e87b02015-09-24 22:57:20 -07003911 Mips64Label null_arg;
Andreas Gampe57b34292015-01-14 15:45:59 -08003912 // Null values get a handle scope entry value of 0. Otherwise, the handle scope entry is
3913 // the address in the handle scope holding the reference.
3914 // e.g. out_reg = (handle == 0) ? 0 : (SP+handle_offset)
3915 if (in_reg.IsNoRegister()) {
Douglas Leungd90957f2015-04-30 19:22:49 -07003916 LoadFromOffset(kLoadUnsignedWord, out_reg.AsGpuRegister(),
Andreas Gampe57b34292015-01-14 15:45:59 -08003917 SP, handle_scope_offset.Int32Value());
3918 in_reg = out_reg;
3919 }
3920 if (!out_reg.Equals(in_reg)) {
Alexey Frunze4dda3372015-06-01 18:31:49 -07003921 LoadConst32(out_reg.AsGpuRegister(), 0);
Andreas Gampe57b34292015-01-14 15:45:59 -08003922 }
Alexey Frunze4dda3372015-06-01 18:31:49 -07003923 Beqzc(in_reg.AsGpuRegister(), &null_arg);
3924 Daddiu64(out_reg.AsGpuRegister(), SP, handle_scope_offset.Int32Value());
3925 Bind(&null_arg);
Andreas Gampe57b34292015-01-14 15:45:59 -08003926 } else {
Alexey Frunze4dda3372015-06-01 18:31:49 -07003927 Daddiu64(out_reg.AsGpuRegister(), SP, handle_scope_offset.Int32Value());
Andreas Gampe57b34292015-01-14 15:45:59 -08003928 }
3929}
3930
3931void Mips64Assembler::CreateHandleScopeEntry(FrameOffset out_off,
Alexey Frunze4dda3372015-06-01 18:31:49 -07003932 FrameOffset handle_scope_offset,
3933 ManagedRegister mscratch,
3934 bool null_allowed) {
Andreas Gampe57b34292015-01-14 15:45:59 -08003935 Mips64ManagedRegister scratch = mscratch.AsMips64();
3936 CHECK(scratch.IsGpuRegister()) << scratch;
3937 if (null_allowed) {
Alexey Frunzea0e87b02015-09-24 22:57:20 -07003938 Mips64Label null_arg;
Douglas Leungd90957f2015-04-30 19:22:49 -07003939 LoadFromOffset(kLoadUnsignedWord, scratch.AsGpuRegister(), SP,
Andreas Gampe57b34292015-01-14 15:45:59 -08003940 handle_scope_offset.Int32Value());
3941 // Null values get a handle scope entry value of 0. Otherwise, the handle scope entry is
3942 // the address in the handle scope holding the reference.
3943 // e.g. scratch = (scratch == 0) ? 0 : (SP+handle_scope_offset)
Alexey Frunze4dda3372015-06-01 18:31:49 -07003944 Beqzc(scratch.AsGpuRegister(), &null_arg);
3945 Daddiu64(scratch.AsGpuRegister(), SP, handle_scope_offset.Int32Value());
3946 Bind(&null_arg);
Andreas Gampe57b34292015-01-14 15:45:59 -08003947 } else {
Alexey Frunze4dda3372015-06-01 18:31:49 -07003948 Daddiu64(scratch.AsGpuRegister(), SP, handle_scope_offset.Int32Value());
Andreas Gampe57b34292015-01-14 15:45:59 -08003949 }
3950 StoreToOffset(kStoreDoubleword, scratch.AsGpuRegister(), SP, out_off.Int32Value());
3951}
3952
3953// Given a handle scope entry, load the associated reference.
3954void Mips64Assembler::LoadReferenceFromHandleScope(ManagedRegister mout_reg,
Alexey Frunze4dda3372015-06-01 18:31:49 -07003955 ManagedRegister min_reg) {
Andreas Gampe57b34292015-01-14 15:45:59 -08003956 Mips64ManagedRegister out_reg = mout_reg.AsMips64();
3957 Mips64ManagedRegister in_reg = min_reg.AsMips64();
3958 CHECK(out_reg.IsGpuRegister()) << out_reg;
3959 CHECK(in_reg.IsGpuRegister()) << in_reg;
Alexey Frunzea0e87b02015-09-24 22:57:20 -07003960 Mips64Label null_arg;
Andreas Gampe57b34292015-01-14 15:45:59 -08003961 if (!out_reg.Equals(in_reg)) {
Alexey Frunze4dda3372015-06-01 18:31:49 -07003962 LoadConst32(out_reg.AsGpuRegister(), 0);
Andreas Gampe57b34292015-01-14 15:45:59 -08003963 }
Alexey Frunze4dda3372015-06-01 18:31:49 -07003964 Beqzc(in_reg.AsGpuRegister(), &null_arg);
Andreas Gampe57b34292015-01-14 15:45:59 -08003965 LoadFromOffset(kLoadDoubleword, out_reg.AsGpuRegister(),
3966 in_reg.AsGpuRegister(), 0);
Alexey Frunze4dda3372015-06-01 18:31:49 -07003967 Bind(&null_arg);
Andreas Gampe57b34292015-01-14 15:45:59 -08003968}
3969
Alexey Frunzea0e87b02015-09-24 22:57:20 -07003970void Mips64Assembler::VerifyObject(ManagedRegister src ATTRIBUTE_UNUSED,
3971 bool could_be_null ATTRIBUTE_UNUSED) {
Andreas Gampe57b34292015-01-14 15:45:59 -08003972 // TODO: not validating references
3973}
3974
Alexey Frunzea0e87b02015-09-24 22:57:20 -07003975void Mips64Assembler::VerifyObject(FrameOffset src ATTRIBUTE_UNUSED,
3976 bool could_be_null ATTRIBUTE_UNUSED) {
Andreas Gampe57b34292015-01-14 15:45:59 -08003977 // TODO: not validating references
3978}
3979
3980void Mips64Assembler::Call(ManagedRegister mbase, Offset offset, ManagedRegister mscratch) {
3981 Mips64ManagedRegister base = mbase.AsMips64();
3982 Mips64ManagedRegister scratch = mscratch.AsMips64();
3983 CHECK(base.IsGpuRegister()) << base;
3984 CHECK(scratch.IsGpuRegister()) << scratch;
3985 LoadFromOffset(kLoadDoubleword, scratch.AsGpuRegister(),
3986 base.AsGpuRegister(), offset.Int32Value());
3987 Jalr(scratch.AsGpuRegister());
Alexey Frunzea0e87b02015-09-24 22:57:20 -07003988 Nop();
Andreas Gampe57b34292015-01-14 15:45:59 -08003989 // TODO: place reference map on call
3990}
3991
3992void Mips64Assembler::Call(FrameOffset base, Offset offset, ManagedRegister mscratch) {
3993 Mips64ManagedRegister scratch = mscratch.AsMips64();
3994 CHECK(scratch.IsGpuRegister()) << scratch;
3995 // Call *(*(SP + base) + offset)
Mathieu Chartiere401d142015-04-22 13:56:20 -07003996 LoadFromOffset(kLoadDoubleword, scratch.AsGpuRegister(),
Andreas Gampe57b34292015-01-14 15:45:59 -08003997 SP, base.Int32Value());
3998 LoadFromOffset(kLoadDoubleword, scratch.AsGpuRegister(),
3999 scratch.AsGpuRegister(), offset.Int32Value());
4000 Jalr(scratch.AsGpuRegister());
Alexey Frunzea0e87b02015-09-24 22:57:20 -07004001 Nop();
Andreas Gampe57b34292015-01-14 15:45:59 -08004002 // TODO: place reference map on call
4003}
4004
Andreas Gampe3b165bc2016-08-01 22:07:04 -07004005void Mips64Assembler::CallFromThread(ThreadOffset64 offset ATTRIBUTE_UNUSED,
4006 ManagedRegister mscratch ATTRIBUTE_UNUSED) {
Alexey Frunzea0e87b02015-09-24 22:57:20 -07004007 UNIMPLEMENTED(FATAL) << "No MIPS64 implementation";
Andreas Gampe57b34292015-01-14 15:45:59 -08004008}
4009
4010void Mips64Assembler::GetCurrentThread(ManagedRegister tr) {
4011 Move(tr.AsMips64().AsGpuRegister(), S1);
4012}
4013
4014void Mips64Assembler::GetCurrentThread(FrameOffset offset,
Alexey Frunzea0e87b02015-09-24 22:57:20 -07004015 ManagedRegister mscratch ATTRIBUTE_UNUSED) {
Andreas Gampe57b34292015-01-14 15:45:59 -08004016 StoreToOffset(kStoreDoubleword, S1, SP, offset.Int32Value());
4017}
4018
4019void Mips64Assembler::ExceptionPoll(ManagedRegister mscratch, size_t stack_adjust) {
4020 Mips64ManagedRegister scratch = mscratch.AsMips64();
Alexey Frunzea0e87b02015-09-24 22:57:20 -07004021 exception_blocks_.emplace_back(scratch, stack_adjust);
4022 LoadFromOffset(kLoadDoubleword,
4023 scratch.AsGpuRegister(),
4024 S1,
Andreas Gampe542451c2016-07-26 09:02:02 -07004025 Thread::ExceptionOffset<kMips64PointerSize>().Int32Value());
Alexey Frunzea0e87b02015-09-24 22:57:20 -07004026 Bnezc(scratch.AsGpuRegister(), exception_blocks_.back().Entry());
Andreas Gampe57b34292015-01-14 15:45:59 -08004027}
4028
Alexey Frunzea0e87b02015-09-24 22:57:20 -07004029void Mips64Assembler::EmitExceptionPoll(Mips64ExceptionSlowPath* exception) {
4030 Bind(exception->Entry());
4031 if (exception->stack_adjust_ != 0) { // Fix up the frame.
4032 DecreaseFrameSize(exception->stack_adjust_);
Andreas Gampe57b34292015-01-14 15:45:59 -08004033 }
Alexey Frunzea0e87b02015-09-24 22:57:20 -07004034 // Pass exception object as argument.
4035 // Don't care about preserving A0 as this call won't return.
4036 CheckEntrypointTypes<kQuickDeliverException, void, mirror::Object*>();
4037 Move(A0, exception->scratch_.AsGpuRegister());
Andreas Gampe57b34292015-01-14 15:45:59 -08004038 // Set up call to Thread::Current()->pDeliverException
Alexey Frunzea0e87b02015-09-24 22:57:20 -07004039 LoadFromOffset(kLoadDoubleword,
4040 T9,
4041 S1,
Andreas Gampe542451c2016-07-26 09:02:02 -07004042 QUICK_ENTRYPOINT_OFFSET(kMips64PointerSize, pDeliverException).Int32Value());
Alexey Frunzea0e87b02015-09-24 22:57:20 -07004043 Jr(T9);
4044 Nop();
4045
Andreas Gampe57b34292015-01-14 15:45:59 -08004046 // Call never returns
Alexey Frunzea0e87b02015-09-24 22:57:20 -07004047 Break();
Andreas Gampe57b34292015-01-14 15:45:59 -08004048}
4049
4050} // namespace mips64
4051} // namespace art