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