blob: 6bf28ab1a3b2f4610849f9149029edbdc0e1aefd [file] [log] [blame]
Aart Bikf8f5a162017-02-06 15:35:29 -08001/*
2 * Copyright (C) 2017 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 "code_generator_mips.h"
Lena Djokic51765b02017-06-22 13:49:59 +020018#include "mirror/array-inl.h"
Aart Bikf8f5a162017-02-06 15:35:29 -080019
20namespace art {
21namespace mips {
22
23// NOLINT on __ macro to suppress wrong warning/fix (misc-macro-parentheses) from clang-tidy.
24#define __ down_cast<MipsAssembler*>(GetAssembler())-> // NOLINT
25
26void LocationsBuilderMIPS::VisitVecReplicateScalar(HVecReplicateScalar* instruction) {
Lena Djokic51765b02017-06-22 13:49:59 +020027 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction);
28 switch (instruction->GetPackedType()) {
29 case Primitive::kPrimBoolean:
30 case Primitive::kPrimByte:
31 case Primitive::kPrimChar:
32 case Primitive::kPrimShort:
33 case Primitive::kPrimInt:
34 case Primitive::kPrimLong:
35 locations->SetInAt(0, Location::RequiresRegister());
36 locations->SetOut(Location::RequiresFpuRegister());
37 break;
38 case Primitive::kPrimFloat:
39 case Primitive::kPrimDouble:
40 locations->SetInAt(0, Location::RequiresFpuRegister());
41 locations->SetOut(Location::RequiresFpuRegister(), Location::kNoOutputOverlap);
42 break;
43 default:
44 LOG(FATAL) << "Unsupported SIMD type";
45 UNREACHABLE();
46 }
Aart Bikf8f5a162017-02-06 15:35:29 -080047}
48
49void InstructionCodeGeneratorMIPS::VisitVecReplicateScalar(HVecReplicateScalar* instruction) {
Lena Djokic51765b02017-06-22 13:49:59 +020050 LocationSummary* locations = instruction->GetLocations();
51 VectorRegister dst = VectorRegisterFrom(locations->Out());
52 switch (instruction->GetPackedType()) {
53 case Primitive::kPrimBoolean:
54 case Primitive::kPrimByte:
55 DCHECK_EQ(16u, instruction->GetVectorLength());
56 __ FillB(dst, locations->InAt(0).AsRegister<Register>());
57 break;
58 case Primitive::kPrimChar:
59 case Primitive::kPrimShort:
60 DCHECK_EQ(8u, instruction->GetVectorLength());
61 __ FillH(dst, locations->InAt(0).AsRegister<Register>());
62 break;
63 case Primitive::kPrimInt:
64 DCHECK_EQ(4u, instruction->GetVectorLength());
65 __ FillW(dst, locations->InAt(0).AsRegister<Register>());
66 break;
67 case Primitive::kPrimLong:
68 DCHECK_EQ(2u, instruction->GetVectorLength());
69 __ Mtc1(locations->InAt(0).AsRegisterPairLow<Register>(), FTMP);
70 __ MoveToFpuHigh(locations->InAt(0).AsRegisterPairHigh<Register>(), FTMP);
71 __ ReplicateFPToVectorRegister(dst, FTMP, /* is_double */ true);
72 break;
73 case Primitive::kPrimFloat:
74 DCHECK_EQ(4u, instruction->GetVectorLength());
75 __ ReplicateFPToVectorRegister(dst,
76 locations->InAt(0).AsFpuRegister<FRegister>(),
77 /* is_double */ false);
78 break;
79 case Primitive::kPrimDouble:
80 DCHECK_EQ(2u, instruction->GetVectorLength());
81 __ ReplicateFPToVectorRegister(dst,
82 locations->InAt(0).AsFpuRegister<FRegister>(),
83 /* is_double */ true);
84 break;
85 default:
86 LOG(FATAL) << "Unsupported SIMD type";
87 UNREACHABLE();
88 }
Aart Bikf8f5a162017-02-06 15:35:29 -080089}
90
91void LocationsBuilderMIPS::VisitVecSetScalars(HVecSetScalars* instruction) {
92 LOG(FATAL) << "No SIMD for " << instruction->GetId();
93}
94
95void InstructionCodeGeneratorMIPS::VisitVecSetScalars(HVecSetScalars* instruction) {
96 LOG(FATAL) << "No SIMD for " << instruction->GetId();
97}
98
99void LocationsBuilderMIPS::VisitVecSumReduce(HVecSumReduce* instruction) {
100 LOG(FATAL) << "No SIMD for " << instruction->GetId();
101}
102
103void InstructionCodeGeneratorMIPS::VisitVecSumReduce(HVecSumReduce* instruction) {
104 LOG(FATAL) << "No SIMD for " << instruction->GetId();
105}
106
107// Helper to set up locations for vector unary operations.
108static void CreateVecUnOpLocations(ArenaAllocator* arena, HVecUnaryOperation* instruction) {
109 LocationSummary* locations = new (arena) LocationSummary(instruction);
110 switch (instruction->GetPackedType()) {
111 case Primitive::kPrimBoolean:
Lena Djokic51765b02017-06-22 13:49:59 +0200112 locations->SetInAt(0, Location::RequiresFpuRegister());
113 locations->SetOut(Location::RequiresFpuRegister(),
114 instruction->IsVecNot() ? Location::kOutputOverlap
115 : Location::kNoOutputOverlap);
116 break;
Aart Bikf8f5a162017-02-06 15:35:29 -0800117 case Primitive::kPrimByte:
118 case Primitive::kPrimChar:
119 case Primitive::kPrimShort:
120 case Primitive::kPrimInt:
Lena Djokic51765b02017-06-22 13:49:59 +0200121 case Primitive::kPrimLong:
Aart Bikf8f5a162017-02-06 15:35:29 -0800122 case Primitive::kPrimFloat:
123 case Primitive::kPrimDouble:
Lena Djokic51765b02017-06-22 13:49:59 +0200124 locations->SetInAt(0, Location::RequiresFpuRegister());
125 locations->SetOut(Location::RequiresFpuRegister(),
126 (instruction->IsVecNeg() || instruction->IsVecAbs())
127 ? Location::kOutputOverlap
128 : Location::kNoOutputOverlap);
Aart Bikf8f5a162017-02-06 15:35:29 -0800129 break;
130 default:
131 LOG(FATAL) << "Unsupported SIMD type";
132 UNREACHABLE();
133 }
134}
135
136void LocationsBuilderMIPS::VisitVecCnv(HVecCnv* instruction) {
137 CreateVecUnOpLocations(GetGraph()->GetArena(), instruction);
138}
139
140void InstructionCodeGeneratorMIPS::VisitVecCnv(HVecCnv* instruction) {
Lena Djokic51765b02017-06-22 13:49:59 +0200141 LocationSummary* locations = instruction->GetLocations();
142 VectorRegister src = VectorRegisterFrom(locations->InAt(0));
143 VectorRegister dst = VectorRegisterFrom(locations->Out());
144 Primitive::Type from = instruction->GetInputType();
145 Primitive::Type to = instruction->GetResultType();
146 if (from == Primitive::kPrimInt && to == Primitive::kPrimFloat) {
147 DCHECK_EQ(4u, instruction->GetVectorLength());
148 __ Ffint_sW(dst, src);
149 } else {
150 LOG(FATAL) << "Unsupported SIMD type";
151 }
Aart Bikf8f5a162017-02-06 15:35:29 -0800152}
153
154void LocationsBuilderMIPS::VisitVecNeg(HVecNeg* instruction) {
155 CreateVecUnOpLocations(GetGraph()->GetArena(), instruction);
156}
157
158void InstructionCodeGeneratorMIPS::VisitVecNeg(HVecNeg* instruction) {
Lena Djokic51765b02017-06-22 13:49:59 +0200159 LocationSummary* locations = instruction->GetLocations();
160 VectorRegister src = VectorRegisterFrom(locations->InAt(0));
161 VectorRegister dst = VectorRegisterFrom(locations->Out());
162 switch (instruction->GetPackedType()) {
163 case Primitive::kPrimByte:
164 DCHECK_EQ(16u, instruction->GetVectorLength());
165 __ FillB(dst, ZERO);
166 __ SubvB(dst, dst, src);
167 break;
168 case Primitive::kPrimChar:
169 case Primitive::kPrimShort:
170 DCHECK_EQ(8u, instruction->GetVectorLength());
171 __ FillH(dst, ZERO);
172 __ SubvH(dst, dst, src);
173 break;
174 case Primitive::kPrimInt:
175 DCHECK_EQ(4u, instruction->GetVectorLength());
176 __ FillW(dst, ZERO);
177 __ SubvW(dst, dst, src);
178 break;
179 case Primitive::kPrimLong:
180 DCHECK_EQ(2u, instruction->GetVectorLength());
181 __ FillW(dst, ZERO);
182 __ SubvD(dst, dst, src);
183 break;
184 case Primitive::kPrimFloat:
185 DCHECK_EQ(4u, instruction->GetVectorLength());
186 __ FillW(dst, ZERO);
187 __ FsubW(dst, dst, src);
188 break;
189 case Primitive::kPrimDouble:
190 DCHECK_EQ(2u, instruction->GetVectorLength());
191 __ FillW(dst, ZERO);
192 __ FsubD(dst, dst, src);
193 break;
194 default:
195 LOG(FATAL) << "Unsupported SIMD type";
196 UNREACHABLE();
197 }
Aart Bikf8f5a162017-02-06 15:35:29 -0800198}
199
Aart Bik6daebeb2017-04-03 14:35:41 -0700200void LocationsBuilderMIPS::VisitVecAbs(HVecAbs* instruction) {
201 CreateVecUnOpLocations(GetGraph()->GetArena(), instruction);
202}
203
204void InstructionCodeGeneratorMIPS::VisitVecAbs(HVecAbs* instruction) {
Lena Djokic51765b02017-06-22 13:49:59 +0200205 LocationSummary* locations = instruction->GetLocations();
206 VectorRegister src = VectorRegisterFrom(locations->InAt(0));
207 VectorRegister dst = VectorRegisterFrom(locations->Out());
208 switch (instruction->GetPackedType()) {
209 case Primitive::kPrimByte:
210 DCHECK_EQ(16u, instruction->GetVectorLength());
211 __ FillB(dst, ZERO); // all zeroes
212 __ Add_aB(dst, dst, src); // dst = abs(0) + abs(src)
213 break;
214 case Primitive::kPrimChar:
215 case Primitive::kPrimShort:
216 DCHECK_EQ(8u, instruction->GetVectorLength());
217 __ FillH(dst, ZERO); // all zeroes
218 __ Add_aH(dst, dst, src); // dst = abs(0) + abs(src)
219 break;
220 case Primitive::kPrimInt:
221 DCHECK_EQ(4u, instruction->GetVectorLength());
222 __ FillW(dst, ZERO); // all zeroes
223 __ Add_aW(dst, dst, src); // dst = abs(0) + abs(src)
224 break;
225 case Primitive::kPrimLong:
226 DCHECK_EQ(2u, instruction->GetVectorLength());
227 __ FillW(dst, ZERO); // all zeroes
228 __ Add_aD(dst, dst, src); // dst = abs(0) + abs(src)
229 break;
230 case Primitive::kPrimFloat:
231 DCHECK_EQ(4u, instruction->GetVectorLength());
232 __ LdiW(dst, -1); // all ones
233 __ SrliW(dst, dst, 1);
234 __ AndV(dst, dst, src);
235 break;
236 case Primitive::kPrimDouble:
237 DCHECK_EQ(2u, instruction->GetVectorLength());
238 __ LdiD(dst, -1); // all ones
239 __ SrliD(dst, dst, 1);
240 __ AndV(dst, dst, src);
241 break;
242 default:
243 LOG(FATAL) << "Unsupported SIMD type";
244 UNREACHABLE();
245 }
Aart Bik6daebeb2017-04-03 14:35:41 -0700246}
247
Aart Bikf8f5a162017-02-06 15:35:29 -0800248void LocationsBuilderMIPS::VisitVecNot(HVecNot* instruction) {
249 CreateVecUnOpLocations(GetGraph()->GetArena(), instruction);
250}
251
252void InstructionCodeGeneratorMIPS::VisitVecNot(HVecNot* instruction) {
Lena Djokic51765b02017-06-22 13:49:59 +0200253 LocationSummary* locations = instruction->GetLocations();
254 VectorRegister src = VectorRegisterFrom(locations->InAt(0));
255 VectorRegister dst = VectorRegisterFrom(locations->Out());
256 switch (instruction->GetPackedType()) {
257 case Primitive::kPrimBoolean: // special case boolean-not
258 DCHECK_EQ(16u, instruction->GetVectorLength());
259 __ LdiB(dst, 1);
260 __ XorV(dst, dst, src);
261 break;
262 case Primitive::kPrimByte:
263 case Primitive::kPrimChar:
264 case Primitive::kPrimShort:
265 case Primitive::kPrimInt:
266 case Primitive::kPrimLong:
267 case Primitive::kPrimFloat:
268 case Primitive::kPrimDouble:
269 DCHECK_LE(2u, instruction->GetVectorLength());
270 DCHECK_LE(instruction->GetVectorLength(), 16u);
271 __ NorV(dst, src, src); // lanes do not matter
272 break;
273 default:
274 LOG(FATAL) << "Unsupported SIMD type";
275 UNREACHABLE();
276 }
Aart Bikf8f5a162017-02-06 15:35:29 -0800277}
278
279// Helper to set up locations for vector binary operations.
280static void CreateVecBinOpLocations(ArenaAllocator* arena, HVecBinaryOperation* instruction) {
281 LocationSummary* locations = new (arena) LocationSummary(instruction);
282 switch (instruction->GetPackedType()) {
283 case Primitive::kPrimBoolean:
284 case Primitive::kPrimByte:
285 case Primitive::kPrimChar:
286 case Primitive::kPrimShort:
287 case Primitive::kPrimInt:
Lena Djokic51765b02017-06-22 13:49:59 +0200288 case Primitive::kPrimLong:
Aart Bikf8f5a162017-02-06 15:35:29 -0800289 case Primitive::kPrimFloat:
290 case Primitive::kPrimDouble:
Lena Djokic51765b02017-06-22 13:49:59 +0200291 locations->SetInAt(0, Location::RequiresFpuRegister());
292 locations->SetInAt(1, Location::RequiresFpuRegister());
293 locations->SetOut(Location::RequiresFpuRegister(), Location::kNoOutputOverlap);
Aart Bikf8f5a162017-02-06 15:35:29 -0800294 break;
295 default:
296 LOG(FATAL) << "Unsupported SIMD type";
297 UNREACHABLE();
298 }
299}
300
301void LocationsBuilderMIPS::VisitVecAdd(HVecAdd* instruction) {
302 CreateVecBinOpLocations(GetGraph()->GetArena(), instruction);
303}
304
305void InstructionCodeGeneratorMIPS::VisitVecAdd(HVecAdd* instruction) {
Lena Djokic51765b02017-06-22 13:49:59 +0200306 LocationSummary* locations = instruction->GetLocations();
307 VectorRegister lhs = VectorRegisterFrom(locations->InAt(0));
308 VectorRegister rhs = VectorRegisterFrom(locations->InAt(1));
309 VectorRegister dst = VectorRegisterFrom(locations->Out());
310 switch (instruction->GetPackedType()) {
311 case Primitive::kPrimByte:
312 DCHECK_EQ(16u, instruction->GetVectorLength());
313 __ AddvB(dst, lhs, rhs);
314 break;
315 case Primitive::kPrimChar:
316 case Primitive::kPrimShort:
317 DCHECK_EQ(8u, instruction->GetVectorLength());
318 __ AddvH(dst, lhs, rhs);
319 break;
320 case Primitive::kPrimInt:
321 DCHECK_EQ(4u, instruction->GetVectorLength());
322 __ AddvW(dst, lhs, rhs);
323 break;
324 case Primitive::kPrimLong:
325 DCHECK_EQ(2u, instruction->GetVectorLength());
326 __ AddvD(dst, lhs, rhs);
327 break;
328 case Primitive::kPrimFloat:
329 DCHECK_EQ(4u, instruction->GetVectorLength());
330 __ FaddW(dst, lhs, rhs);
331 break;
332 case Primitive::kPrimDouble:
333 DCHECK_EQ(2u, instruction->GetVectorLength());
334 __ FaddD(dst, lhs, rhs);
335 break;
336 default:
337 LOG(FATAL) << "Unsupported SIMD type";
338 UNREACHABLE();
339 }
Aart Bikf8f5a162017-02-06 15:35:29 -0800340}
341
Aart Bikf3e61ee2017-04-12 17:09:20 -0700342void LocationsBuilderMIPS::VisitVecHalvingAdd(HVecHalvingAdd* instruction) {
343 CreateVecBinOpLocations(GetGraph()->GetArena(), instruction);
344}
345
346void InstructionCodeGeneratorMIPS::VisitVecHalvingAdd(HVecHalvingAdd* instruction) {
Lena Djokic51765b02017-06-22 13:49:59 +0200347 LocationSummary* locations = instruction->GetLocations();
348 VectorRegister lhs = VectorRegisterFrom(locations->InAt(0));
349 VectorRegister rhs = VectorRegisterFrom(locations->InAt(1));
350 VectorRegister dst = VectorRegisterFrom(locations->Out());
351 switch (instruction->GetPackedType()) {
352 case Primitive::kPrimByte:
353 DCHECK_EQ(16u, instruction->GetVectorLength());
354 if (instruction->IsUnsigned()) {
355 instruction->IsRounded()
356 ? __ Aver_uB(dst, lhs, rhs)
357 : __ Ave_uB(dst, lhs, rhs);
358 } else {
359 instruction->IsRounded()
360 ? __ Aver_sB(dst, lhs, rhs)
361 : __ Ave_sB(dst, lhs, rhs);
362 }
363 break;
364 case Primitive::kPrimChar:
365 case Primitive::kPrimShort:
366 DCHECK_EQ(8u, instruction->GetVectorLength());
367 if (instruction->IsUnsigned()) {
368 instruction->IsRounded()
369 ? __ Aver_uH(dst, lhs, rhs)
370 : __ Ave_uH(dst, lhs, rhs);
371 } else {
372 instruction->IsRounded()
373 ? __ Aver_sH(dst, lhs, rhs)
374 : __ Ave_sH(dst, lhs, rhs);
375 }
376 break;
377 default:
378 LOG(FATAL) << "Unsupported SIMD type";
379 UNREACHABLE();
380 }
Aart Bikf3e61ee2017-04-12 17:09:20 -0700381}
382
Aart Bikf8f5a162017-02-06 15:35:29 -0800383void LocationsBuilderMIPS::VisitVecSub(HVecSub* instruction) {
384 CreateVecBinOpLocations(GetGraph()->GetArena(), instruction);
385}
386
387void InstructionCodeGeneratorMIPS::VisitVecSub(HVecSub* instruction) {
Lena Djokic51765b02017-06-22 13:49:59 +0200388 LocationSummary* locations = instruction->GetLocations();
389 VectorRegister lhs = VectorRegisterFrom(locations->InAt(0));
390 VectorRegister rhs = VectorRegisterFrom(locations->InAt(1));
391 VectorRegister dst = VectorRegisterFrom(locations->Out());
392 switch (instruction->GetPackedType()) {
393 case Primitive::kPrimByte:
394 DCHECK_EQ(16u, instruction->GetVectorLength());
395 __ SubvB(dst, lhs, rhs);
396 break;
397 case Primitive::kPrimChar:
398 case Primitive::kPrimShort:
399 DCHECK_EQ(8u, instruction->GetVectorLength());
400 __ SubvH(dst, lhs, rhs);
401 break;
402 case Primitive::kPrimInt:
403 DCHECK_EQ(4u, instruction->GetVectorLength());
404 __ SubvW(dst, lhs, rhs);
405 break;
406 case Primitive::kPrimLong:
407 DCHECK_EQ(2u, instruction->GetVectorLength());
408 __ SubvD(dst, lhs, rhs);
409 break;
410 case Primitive::kPrimFloat:
411 DCHECK_EQ(4u, instruction->GetVectorLength());
412 __ FsubW(dst, lhs, rhs);
413 break;
414 case Primitive::kPrimDouble:
415 DCHECK_EQ(2u, instruction->GetVectorLength());
416 __ FsubD(dst, lhs, rhs);
417 break;
418 default:
419 LOG(FATAL) << "Unsupported SIMD type";
420 UNREACHABLE();
421 }
Aart Bikf8f5a162017-02-06 15:35:29 -0800422}
423
424void LocationsBuilderMIPS::VisitVecMul(HVecMul* instruction) {
425 CreateVecBinOpLocations(GetGraph()->GetArena(), instruction);
426}
427
428void InstructionCodeGeneratorMIPS::VisitVecMul(HVecMul* instruction) {
Lena Djokic51765b02017-06-22 13:49:59 +0200429 LocationSummary* locations = instruction->GetLocations();
430 VectorRegister lhs = VectorRegisterFrom(locations->InAt(0));
431 VectorRegister rhs = VectorRegisterFrom(locations->InAt(1));
432 VectorRegister dst = VectorRegisterFrom(locations->Out());
433 switch (instruction->GetPackedType()) {
434 case Primitive::kPrimByte:
435 DCHECK_EQ(16u, instruction->GetVectorLength());
436 __ MulvB(dst, lhs, rhs);
437 break;
438 case Primitive::kPrimChar:
439 case Primitive::kPrimShort:
440 DCHECK_EQ(8u, instruction->GetVectorLength());
441 __ MulvH(dst, lhs, rhs);
442 break;
443 case Primitive::kPrimInt:
444 DCHECK_EQ(4u, instruction->GetVectorLength());
445 __ MulvW(dst, lhs, rhs);
446 break;
447 case Primitive::kPrimLong:
448 DCHECK_EQ(2u, instruction->GetVectorLength());
449 __ MulvD(dst, lhs, rhs);
450 break;
451 case Primitive::kPrimFloat:
452 DCHECK_EQ(4u, instruction->GetVectorLength());
453 __ FmulW(dst, lhs, rhs);
454 break;
455 case Primitive::kPrimDouble:
456 DCHECK_EQ(2u, instruction->GetVectorLength());
457 __ FmulD(dst, lhs, rhs);
458 break;
459 default:
460 LOG(FATAL) << "Unsupported SIMD type";
461 UNREACHABLE();
462 }
Aart Bikf8f5a162017-02-06 15:35:29 -0800463}
464
465void LocationsBuilderMIPS::VisitVecDiv(HVecDiv* instruction) {
466 CreateVecBinOpLocations(GetGraph()->GetArena(), instruction);
467}
468
469void InstructionCodeGeneratorMIPS::VisitVecDiv(HVecDiv* instruction) {
Lena Djokic51765b02017-06-22 13:49:59 +0200470 LocationSummary* locations = instruction->GetLocations();
471 VectorRegister lhs = VectorRegisterFrom(locations->InAt(0));
472 VectorRegister rhs = VectorRegisterFrom(locations->InAt(1));
473 VectorRegister dst = VectorRegisterFrom(locations->Out());
474 switch (instruction->GetPackedType()) {
475 case Primitive::kPrimFloat:
476 DCHECK_EQ(4u, instruction->GetVectorLength());
477 __ FdivW(dst, lhs, rhs);
478 break;
479 case Primitive::kPrimDouble:
480 DCHECK_EQ(2u, instruction->GetVectorLength());
481 __ FdivD(dst, lhs, rhs);
482 break;
483 default:
484 LOG(FATAL) << "Unsupported SIMD type";
485 UNREACHABLE();
486 }
Aart Bikf8f5a162017-02-06 15:35:29 -0800487}
488
Aart Bikf3e61ee2017-04-12 17:09:20 -0700489void LocationsBuilderMIPS::VisitVecMin(HVecMin* instruction) {
490 CreateVecBinOpLocations(GetGraph()->GetArena(), instruction);
491}
492
493void InstructionCodeGeneratorMIPS::VisitVecMin(HVecMin* instruction) {
Lena Djokic51765b02017-06-22 13:49:59 +0200494 LocationSummary* locations = instruction->GetLocations();
495 VectorRegister lhs = VectorRegisterFrom(locations->InAt(0));
496 VectorRegister rhs = VectorRegisterFrom(locations->InAt(1));
497 VectorRegister dst = VectorRegisterFrom(locations->Out());
498 switch (instruction->GetPackedType()) {
499 case Primitive::kPrimByte:
500 DCHECK_EQ(16u, instruction->GetVectorLength());
501 if (instruction->IsUnsigned()) {
502 __ Min_uB(dst, lhs, rhs);
503 } else {
504 __ Min_sB(dst, lhs, rhs);
505 }
506 break;
507 case Primitive::kPrimChar:
508 case Primitive::kPrimShort:
509 DCHECK_EQ(8u, instruction->GetVectorLength());
510 if (instruction->IsUnsigned()) {
511 __ Min_uH(dst, lhs, rhs);
512 } else {
513 __ Min_sH(dst, lhs, rhs);
514 }
515 break;
516 case Primitive::kPrimInt:
517 DCHECK_EQ(4u, instruction->GetVectorLength());
518 if (instruction->IsUnsigned()) {
519 __ Min_uW(dst, lhs, rhs);
520 } else {
521 __ Min_sW(dst, lhs, rhs);
522 }
523 break;
524 case Primitive::kPrimLong:
525 DCHECK_EQ(2u, instruction->GetVectorLength());
526 if (instruction->IsUnsigned()) {
527 __ Min_uD(dst, lhs, rhs);
528 } else {
529 __ Min_sD(dst, lhs, rhs);
530 }
531 break;
532 // When one of arguments is NaN, fmin.df returns other argument, but Java expects a NaN value.
533 // TODO: Fix min(x, NaN) cases for float and double.
534 case Primitive::kPrimFloat:
535 DCHECK_EQ(4u, instruction->GetVectorLength());
536 DCHECK(!instruction->IsUnsigned());
537 __ FminW(dst, lhs, rhs);
538 break;
539 case Primitive::kPrimDouble:
540 DCHECK_EQ(2u, instruction->GetVectorLength());
541 DCHECK(!instruction->IsUnsigned());
542 __ FminD(dst, lhs, rhs);
543 break;
544 default:
545 LOG(FATAL) << "Unsupported SIMD type";
546 UNREACHABLE();
547 }
Aart Bikf3e61ee2017-04-12 17:09:20 -0700548}
549
550void LocationsBuilderMIPS::VisitVecMax(HVecMax* instruction) {
551 CreateVecBinOpLocations(GetGraph()->GetArena(), instruction);
552}
553
554void InstructionCodeGeneratorMIPS::VisitVecMax(HVecMax* instruction) {
Lena Djokic51765b02017-06-22 13:49:59 +0200555 LocationSummary* locations = instruction->GetLocations();
556 VectorRegister lhs = VectorRegisterFrom(locations->InAt(0));
557 VectorRegister rhs = VectorRegisterFrom(locations->InAt(1));
558 VectorRegister dst = VectorRegisterFrom(locations->Out());
559 switch (instruction->GetPackedType()) {
560 case Primitive::kPrimByte:
561 DCHECK_EQ(16u, instruction->GetVectorLength());
562 if (instruction->IsUnsigned()) {
563 __ Max_uB(dst, lhs, rhs);
564 } else {
565 __ Max_sB(dst, lhs, rhs);
566 }
567 break;
568 case Primitive::kPrimChar:
569 case Primitive::kPrimShort:
570 DCHECK_EQ(8u, instruction->GetVectorLength());
571 if (instruction->IsUnsigned()) {
572 __ Max_uH(dst, lhs, rhs);
573 } else {
574 __ Max_sH(dst, lhs, rhs);
575 }
576 break;
577 case Primitive::kPrimInt:
578 DCHECK_EQ(4u, instruction->GetVectorLength());
579 if (instruction->IsUnsigned()) {
580 __ Max_uW(dst, lhs, rhs);
581 } else {
582 __ Max_sW(dst, lhs, rhs);
583 }
584 break;
585 case Primitive::kPrimLong:
586 DCHECK_EQ(2u, instruction->GetVectorLength());
587 if (instruction->IsUnsigned()) {
588 __ Max_uD(dst, lhs, rhs);
589 } else {
590 __ Max_sD(dst, lhs, rhs);
591 }
592 break;
593 // When one of arguments is NaN, fmax.df returns other argument, but Java expects a NaN value.
594 // TODO: Fix max(x, NaN) cases for float and double.
595 case Primitive::kPrimFloat:
596 DCHECK_EQ(4u, instruction->GetVectorLength());
597 DCHECK(!instruction->IsUnsigned());
598 __ FmaxW(dst, lhs, rhs);
599 break;
600 case Primitive::kPrimDouble:
601 DCHECK_EQ(2u, instruction->GetVectorLength());
602 DCHECK(!instruction->IsUnsigned());
603 __ FmaxD(dst, lhs, rhs);
604 break;
605 default:
606 LOG(FATAL) << "Unsupported SIMD type";
607 UNREACHABLE();
608 }
Aart Bikf3e61ee2017-04-12 17:09:20 -0700609}
610
Aart Bikf8f5a162017-02-06 15:35:29 -0800611void LocationsBuilderMIPS::VisitVecAnd(HVecAnd* instruction) {
612 CreateVecBinOpLocations(GetGraph()->GetArena(), instruction);
613}
614
615void InstructionCodeGeneratorMIPS::VisitVecAnd(HVecAnd* instruction) {
Lena Djokic51765b02017-06-22 13:49:59 +0200616 LocationSummary* locations = instruction->GetLocations();
617 VectorRegister lhs = VectorRegisterFrom(locations->InAt(0));
618 VectorRegister rhs = VectorRegisterFrom(locations->InAt(1));
619 VectorRegister dst = VectorRegisterFrom(locations->Out());
620 switch (instruction->GetPackedType()) {
621 case Primitive::kPrimBoolean:
622 case Primitive::kPrimByte:
623 case Primitive::kPrimChar:
624 case Primitive::kPrimShort:
625 case Primitive::kPrimInt:
626 case Primitive::kPrimLong:
627 case Primitive::kPrimFloat:
628 case Primitive::kPrimDouble:
629 DCHECK_LE(2u, instruction->GetVectorLength());
630 DCHECK_LE(instruction->GetVectorLength(), 16u);
631 __ AndV(dst, lhs, rhs); // lanes do not matter
632 break;
633 default:
634 LOG(FATAL) << "Unsupported SIMD type";
635 UNREACHABLE();
636 }
Aart Bikf8f5a162017-02-06 15:35:29 -0800637}
638
639void LocationsBuilderMIPS::VisitVecAndNot(HVecAndNot* instruction) {
640 CreateVecBinOpLocations(GetGraph()->GetArena(), instruction);
641}
642
643void InstructionCodeGeneratorMIPS::VisitVecAndNot(HVecAndNot* instruction) {
644 LOG(FATAL) << "No SIMD for " << instruction->GetId();
645}
646
647void LocationsBuilderMIPS::VisitVecOr(HVecOr* instruction) {
648 CreateVecBinOpLocations(GetGraph()->GetArena(), instruction);
649}
650
651void InstructionCodeGeneratorMIPS::VisitVecOr(HVecOr* instruction) {
Lena Djokic51765b02017-06-22 13:49:59 +0200652 LocationSummary* locations = instruction->GetLocations();
653 VectorRegister lhs = VectorRegisterFrom(locations->InAt(0));
654 VectorRegister rhs = VectorRegisterFrom(locations->InAt(1));
655 VectorRegister dst = VectorRegisterFrom(locations->Out());
656 switch (instruction->GetPackedType()) {
657 case Primitive::kPrimBoolean:
658 case Primitive::kPrimByte:
659 case Primitive::kPrimChar:
660 case Primitive::kPrimShort:
661 case Primitive::kPrimInt:
662 case Primitive::kPrimLong:
663 case Primitive::kPrimFloat:
664 case Primitive::kPrimDouble:
665 DCHECK_LE(2u, instruction->GetVectorLength());
666 DCHECK_LE(instruction->GetVectorLength(), 16u);
667 __ OrV(dst, lhs, rhs); // lanes do not matter
668 break;
669 default:
670 LOG(FATAL) << "Unsupported SIMD type";
671 UNREACHABLE();
672 }
Aart Bikf8f5a162017-02-06 15:35:29 -0800673}
674
675void LocationsBuilderMIPS::VisitVecXor(HVecXor* instruction) {
676 CreateVecBinOpLocations(GetGraph()->GetArena(), instruction);
677}
678
679void InstructionCodeGeneratorMIPS::VisitVecXor(HVecXor* instruction) {
Lena Djokic51765b02017-06-22 13:49:59 +0200680 LocationSummary* locations = instruction->GetLocations();
681 VectorRegister lhs = VectorRegisterFrom(locations->InAt(0));
682 VectorRegister rhs = VectorRegisterFrom(locations->InAt(1));
683 VectorRegister dst = VectorRegisterFrom(locations->Out());
684 switch (instruction->GetPackedType()) {
685 case Primitive::kPrimBoolean:
686 case Primitive::kPrimByte:
687 case Primitive::kPrimChar:
688 case Primitive::kPrimShort:
689 case Primitive::kPrimInt:
690 case Primitive::kPrimLong:
691 case Primitive::kPrimFloat:
692 case Primitive::kPrimDouble:
693 DCHECK_LE(2u, instruction->GetVectorLength());
694 DCHECK_LE(instruction->GetVectorLength(), 16u);
695 __ XorV(dst, lhs, rhs); // lanes do not matter
696 break;
697 default:
698 LOG(FATAL) << "Unsupported SIMD type";
699 UNREACHABLE();
700 }
Aart Bikf8f5a162017-02-06 15:35:29 -0800701}
702
703// Helper to set up locations for vector shift operations.
704static void CreateVecShiftLocations(ArenaAllocator* arena, HVecBinaryOperation* instruction) {
705 LocationSummary* locations = new (arena) LocationSummary(instruction);
706 switch (instruction->GetPackedType()) {
707 case Primitive::kPrimByte:
708 case Primitive::kPrimChar:
709 case Primitive::kPrimShort:
710 case Primitive::kPrimInt:
711 case Primitive::kPrimLong:
Lena Djokic51765b02017-06-22 13:49:59 +0200712 locations->SetInAt(0, Location::RequiresFpuRegister());
713 locations->SetInAt(1, Location::ConstantLocation(instruction->InputAt(1)->AsConstant()));
714 locations->SetOut(Location::RequiresFpuRegister(), Location::kNoOutputOverlap);
Aart Bikf8f5a162017-02-06 15:35:29 -0800715 break;
716 default:
717 LOG(FATAL) << "Unsupported SIMD type";
718 UNREACHABLE();
719 }
720}
721
722void LocationsBuilderMIPS::VisitVecShl(HVecShl* instruction) {
723 CreateVecShiftLocations(GetGraph()->GetArena(), instruction);
724}
725
726void InstructionCodeGeneratorMIPS::VisitVecShl(HVecShl* instruction) {
Lena Djokic51765b02017-06-22 13:49:59 +0200727 LocationSummary* locations = instruction->GetLocations();
728 VectorRegister lhs = VectorRegisterFrom(locations->InAt(0));
729 VectorRegister dst = VectorRegisterFrom(locations->Out());
730 int32_t value = locations->InAt(1).GetConstant()->AsIntConstant()->GetValue();
731 switch (instruction->GetPackedType()) {
732 case Primitive::kPrimByte:
733 DCHECK_EQ(16u, instruction->GetVectorLength());
734 __ SlliB(dst, lhs, value);
735 break;
736 case Primitive::kPrimChar:
737 case Primitive::kPrimShort:
738 DCHECK_EQ(8u, instruction->GetVectorLength());
739 __ SlliH(dst, lhs, value);
740 break;
741 case Primitive::kPrimInt:
742 DCHECK_EQ(4u, instruction->GetVectorLength());
743 __ SlliW(dst, lhs, value);
744 break;
745 case Primitive::kPrimLong:
746 DCHECK_EQ(2u, instruction->GetVectorLength());
747 __ SlliD(dst, lhs, value);
748 break;
749 default:
750 LOG(FATAL) << "Unsupported SIMD type";
751 UNREACHABLE();
752 }
Aart Bikf8f5a162017-02-06 15:35:29 -0800753}
754
755void LocationsBuilderMIPS::VisitVecShr(HVecShr* instruction) {
756 CreateVecShiftLocations(GetGraph()->GetArena(), instruction);
757}
758
759void InstructionCodeGeneratorMIPS::VisitVecShr(HVecShr* instruction) {
Lena Djokic51765b02017-06-22 13:49:59 +0200760 LocationSummary* locations = instruction->GetLocations();
761 VectorRegister lhs = VectorRegisterFrom(locations->InAt(0));
762 VectorRegister dst = VectorRegisterFrom(locations->Out());
763 int32_t value = locations->InAt(1).GetConstant()->AsIntConstant()->GetValue();
764 switch (instruction->GetPackedType()) {
765 case Primitive::kPrimByte:
766 DCHECK_EQ(16u, instruction->GetVectorLength());
767 __ SraiB(dst, lhs, value);
768 break;
769 case Primitive::kPrimChar:
770 case Primitive::kPrimShort:
771 DCHECK_EQ(8u, instruction->GetVectorLength());
772 __ SraiH(dst, lhs, value);
773 break;
774 case Primitive::kPrimInt:
775 DCHECK_EQ(4u, instruction->GetVectorLength());
776 __ SraiW(dst, lhs, value);
777 break;
778 case Primitive::kPrimLong:
779 DCHECK_EQ(2u, instruction->GetVectorLength());
780 __ SraiD(dst, lhs, value);
781 break;
782 default:
783 LOG(FATAL) << "Unsupported SIMD type";
784 UNREACHABLE();
785 }
Aart Bikf8f5a162017-02-06 15:35:29 -0800786}
787
788void LocationsBuilderMIPS::VisitVecUShr(HVecUShr* instruction) {
789 CreateVecShiftLocations(GetGraph()->GetArena(), instruction);
790}
791
792void InstructionCodeGeneratorMIPS::VisitVecUShr(HVecUShr* instruction) {
Lena Djokic51765b02017-06-22 13:49:59 +0200793 LocationSummary* locations = instruction->GetLocations();
794 VectorRegister lhs = VectorRegisterFrom(locations->InAt(0));
795 VectorRegister dst = VectorRegisterFrom(locations->Out());
796 int32_t value = locations->InAt(1).GetConstant()->AsIntConstant()->GetValue();
797 switch (instruction->GetPackedType()) {
798 case Primitive::kPrimByte:
799 DCHECK_EQ(16u, instruction->GetVectorLength());
800 __ SrliB(dst, lhs, value);
801 break;
802 case Primitive::kPrimChar:
803 case Primitive::kPrimShort:
804 DCHECK_EQ(8u, instruction->GetVectorLength());
805 __ SrliH(dst, lhs, value);
806 break;
807 case Primitive::kPrimInt:
808 DCHECK_EQ(4u, instruction->GetVectorLength());
809 __ SrliW(dst, lhs, value);
810 break;
811 case Primitive::kPrimLong:
812 DCHECK_EQ(2u, instruction->GetVectorLength());
813 __ SrliD(dst, lhs, value);
814 break;
815 default:
816 LOG(FATAL) << "Unsupported SIMD type";
817 UNREACHABLE();
818 }
Aart Bikf8f5a162017-02-06 15:35:29 -0800819}
820
Artem Serovf34dd202017-04-10 17:41:46 +0100821void LocationsBuilderMIPS::VisitVecMultiplyAccumulate(HVecMultiplyAccumulate* instr) {
Lena Djokicbc5460b2017-07-20 16:07:36 +0200822 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instr);
823 switch (instr->GetPackedType()) {
824 case Primitive::kPrimByte:
825 case Primitive::kPrimChar:
826 case Primitive::kPrimShort:
827 case Primitive::kPrimInt:
828 case Primitive::kPrimLong:
829 locations->SetInAt(
830 HVecMultiplyAccumulate::kInputAccumulatorIndex, Location::RequiresFpuRegister());
831 locations->SetInAt(
832 HVecMultiplyAccumulate::kInputMulLeftIndex, Location::RequiresFpuRegister());
833 locations->SetInAt(
834 HVecMultiplyAccumulate::kInputMulRightIndex, Location::RequiresFpuRegister());
835 DCHECK_EQ(HVecMultiplyAccumulate::kInputAccumulatorIndex, 0);
836 locations->SetOut(Location::SameAsFirstInput());
837 break;
838 default:
839 LOG(FATAL) << "Unsupported SIMD type";
840 UNREACHABLE();
841 }
Artem Serovf34dd202017-04-10 17:41:46 +0100842}
843
844void InstructionCodeGeneratorMIPS::VisitVecMultiplyAccumulate(HVecMultiplyAccumulate* instr) {
Lena Djokicbc5460b2017-07-20 16:07:36 +0200845 LocationSummary* locations = instr->GetLocations();
846 VectorRegister acc =
847 VectorRegisterFrom(locations->InAt(HVecMultiplyAccumulate::kInputAccumulatorIndex));
848 VectorRegister left =
849 VectorRegisterFrom(locations->InAt(HVecMultiplyAccumulate::kInputMulLeftIndex));
850 VectorRegister right =
851 VectorRegisterFrom(locations->InAt(HVecMultiplyAccumulate::kInputMulRightIndex));
852 switch (instr->GetPackedType()) {
853 case Primitive::kPrimByte:
854 DCHECK_EQ(16u, instr->GetVectorLength());
855 if (instr->GetOpKind() == HInstruction::kAdd) {
856 __ MaddvB(acc, left, right);
857 } else {
858 __ MsubvB(acc, left, right);
859 }
860 break;
861 case Primitive::kPrimChar:
862 case Primitive::kPrimShort:
863 DCHECK_EQ(8u, instr->GetVectorLength());
864 if (instr->GetOpKind() == HInstruction::kAdd) {
865 __ MaddvH(acc, left, right);
866 } else {
867 __ MsubvH(acc, left, right);
868 }
869 break;
870 case Primitive::kPrimInt:
871 DCHECK_EQ(4u, instr->GetVectorLength());
872 if (instr->GetOpKind() == HInstruction::kAdd) {
873 __ MaddvW(acc, left, right);
874 } else {
875 __ MsubvW(acc, left, right);
876 }
877 break;
878 case Primitive::kPrimLong:
879 DCHECK_EQ(2u, instr->GetVectorLength());
880 if (instr->GetOpKind() == HInstruction::kAdd) {
881 __ MaddvD(acc, left, right);
882 } else {
883 __ MsubvD(acc, left, right);
884 }
885 break;
886 default:
887 LOG(FATAL) << "Unsupported SIMD type";
888 UNREACHABLE();
889 }
Artem Serovf34dd202017-04-10 17:41:46 +0100890}
891
Lena Djokic51765b02017-06-22 13:49:59 +0200892// Helper to set up locations for vector memory operations.
893static void CreateVecMemLocations(ArenaAllocator* arena,
894 HVecMemoryOperation* instruction,
895 bool is_load) {
896 LocationSummary* locations = new (arena) LocationSummary(instruction);
897 switch (instruction->GetPackedType()) {
898 case Primitive::kPrimBoolean:
899 case Primitive::kPrimByte:
900 case Primitive::kPrimChar:
901 case Primitive::kPrimShort:
902 case Primitive::kPrimInt:
903 case Primitive::kPrimLong:
904 case Primitive::kPrimFloat:
905 case Primitive::kPrimDouble:
906 locations->SetInAt(0, Location::RequiresRegister());
907 locations->SetInAt(1, Location::RegisterOrConstant(instruction->InputAt(1)));
908 if (is_load) {
909 locations->SetOut(Location::RequiresFpuRegister());
910 } else {
911 locations->SetInAt(2, Location::RequiresFpuRegister());
912 }
913 break;
914 default:
915 LOG(FATAL) << "Unsupported SIMD type";
916 UNREACHABLE();
917 }
918}
919
920// Helper to prepare register and offset for vector memory operations. Returns the offset and sets
921// the output parameter adjusted_base to the original base or to a reserved temporary register (AT).
922int32_t InstructionCodeGeneratorMIPS::VecAddress(LocationSummary* locations,
923 size_t size,
924 /* out */ Register* adjusted_base) {
925 Register base = locations->InAt(0).AsRegister<Register>();
926 Location index = locations->InAt(1);
927 int scale = TIMES_1;
928 switch (size) {
929 case 2: scale = TIMES_2; break;
930 case 4: scale = TIMES_4; break;
931 case 8: scale = TIMES_8; break;
932 default: break;
933 }
934 int32_t offset = mirror::Array::DataOffset(size).Int32Value();
935
936 if (index.IsConstant()) {
937 offset += index.GetConstant()->AsIntConstant()->GetValue() << scale;
938 __ AdjustBaseOffsetAndElementSizeShift(base, offset, scale);
939 *adjusted_base = base;
940 } else {
941 Register index_reg = index.AsRegister<Register>();
942 if (scale != TIMES_1) {
943 __ Lsa(AT, index_reg, base, scale);
944 } else {
945 __ Addu(AT, base, index_reg);
946 }
947 *adjusted_base = AT;
948 }
949 return offset;
950}
951
Aart Bikf8f5a162017-02-06 15:35:29 -0800952void LocationsBuilderMIPS::VisitVecLoad(HVecLoad* instruction) {
Lena Djokic51765b02017-06-22 13:49:59 +0200953 CreateVecMemLocations(GetGraph()->GetArena(), instruction, /* is_load */ true);
Aart Bikf8f5a162017-02-06 15:35:29 -0800954}
955
956void InstructionCodeGeneratorMIPS::VisitVecLoad(HVecLoad* instruction) {
Lena Djokic51765b02017-06-22 13:49:59 +0200957 LocationSummary* locations = instruction->GetLocations();
958 size_t size = Primitive::ComponentSize(instruction->GetPackedType());
959 VectorRegister reg = VectorRegisterFrom(locations->Out());
960 Register base;
961 int32_t offset = VecAddress(locations, size, &base);
962 switch (instruction->GetPackedType()) {
963 case Primitive::kPrimBoolean:
964 case Primitive::kPrimByte:
965 DCHECK_EQ(16u, instruction->GetVectorLength());
966 __ LdB(reg, base, offset);
967 break;
968 case Primitive::kPrimChar:
969 case Primitive::kPrimShort:
970 // Loading 8-bytes (needed if dealing with compressed strings in StringCharAt) from unaligned
971 // memory address may cause a trap to the kernel if the CPU doesn't directly support unaligned
972 // loads and stores.
973 // TODO: Implement support for StringCharAt.
974 DCHECK(!instruction->IsStringCharAt());
975 DCHECK_EQ(8u, instruction->GetVectorLength());
976 __ LdH(reg, base, offset);
977 break;
978 case Primitive::kPrimInt:
979 case Primitive::kPrimFloat:
980 DCHECK_EQ(4u, instruction->GetVectorLength());
981 __ LdW(reg, base, offset);
982 break;
983 case Primitive::kPrimLong:
984 case Primitive::kPrimDouble:
985 DCHECK_EQ(2u, instruction->GetVectorLength());
986 __ LdD(reg, base, offset);
987 break;
988 default:
989 LOG(FATAL) << "Unsupported SIMD type";
990 UNREACHABLE();
991 }
Aart Bikf8f5a162017-02-06 15:35:29 -0800992}
993
994void LocationsBuilderMIPS::VisitVecStore(HVecStore* instruction) {
Lena Djokic51765b02017-06-22 13:49:59 +0200995 CreateVecMemLocations(GetGraph()->GetArena(), instruction, /* is_load */ false);
Aart Bikf8f5a162017-02-06 15:35:29 -0800996}
997
998void InstructionCodeGeneratorMIPS::VisitVecStore(HVecStore* instruction) {
Lena Djokic51765b02017-06-22 13:49:59 +0200999 LocationSummary* locations = instruction->GetLocations();
1000 size_t size = Primitive::ComponentSize(instruction->GetPackedType());
1001 VectorRegister reg = VectorRegisterFrom(locations->InAt(2));
1002 Register base;
1003 int32_t offset = VecAddress(locations, size, &base);
1004 switch (instruction->GetPackedType()) {
1005 case Primitive::kPrimBoolean:
1006 case Primitive::kPrimByte:
1007 DCHECK_EQ(16u, instruction->GetVectorLength());
1008 __ StB(reg, base, offset);
1009 break;
1010 case Primitive::kPrimChar:
1011 case Primitive::kPrimShort:
1012 DCHECK_EQ(8u, instruction->GetVectorLength());
1013 __ StH(reg, base, offset);
1014 break;
1015 case Primitive::kPrimInt:
1016 case Primitive::kPrimFloat:
1017 DCHECK_EQ(4u, instruction->GetVectorLength());
1018 __ StW(reg, base, offset);
1019 break;
1020 case Primitive::kPrimLong:
1021 case Primitive::kPrimDouble:
1022 DCHECK_EQ(2u, instruction->GetVectorLength());
1023 __ StD(reg, base, offset);
1024 break;
1025 default:
1026 LOG(FATAL) << "Unsupported SIMD type";
1027 UNREACHABLE();
1028 }
Aart Bikf8f5a162017-02-06 15:35:29 -08001029}
1030
1031#undef __
1032
1033} // namespace mips
1034} // namespace art