blob: 7d69773ae6631d0dabee2b4555b9cfb0dd302901 [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()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +010034 case DataType::Type::kBool:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +010035 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +010036 case DataType::Type::kInt8:
37 case DataType::Type::kUint16:
38 case DataType::Type::kInt16:
39 case DataType::Type::kInt32:
40 case DataType::Type::kInt64:
Goran Jakovljevic19680d32017-05-11 10:38:36 +020041 locations->SetInAt(0, Location::RequiresRegister());
42 locations->SetOut(Location::RequiresFpuRegister());
43 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +010044 case DataType::Type::kFloat32:
45 case DataType::Type::kFloat64:
Goran Jakovljevic19680d32017-05-11 10:38:36 +020046 locations->SetInAt(0, Location::RequiresFpuRegister());
47 locations->SetOut(Location::RequiresFpuRegister(), Location::kNoOutputOverlap);
48 break;
49 default:
50 LOG(FATAL) << "Unsupported SIMD type";
51 UNREACHABLE();
52 }
Aart Bikf8f5a162017-02-06 15:35:29 -080053}
54
55void InstructionCodeGeneratorMIPS64::VisitVecReplicateScalar(HVecReplicateScalar* instruction) {
Goran Jakovljevic19680d32017-05-11 10:38:36 +020056 LocationSummary* locations = instruction->GetLocations();
57 VectorRegister dst = VectorRegisterFrom(locations->Out());
58 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +010059 case DataType::Type::kBool:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +010060 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +010061 case DataType::Type::kInt8:
Goran Jakovljevic19680d32017-05-11 10:38:36 +020062 DCHECK_EQ(16u, instruction->GetVectorLength());
63 __ FillB(dst, locations->InAt(0).AsRegister<GpuRegister>());
64 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +010065 case DataType::Type::kUint16:
66 case DataType::Type::kInt16:
Goran Jakovljevic19680d32017-05-11 10:38:36 +020067 DCHECK_EQ(8u, instruction->GetVectorLength());
68 __ FillH(dst, locations->InAt(0).AsRegister<GpuRegister>());
69 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +010070 case DataType::Type::kInt32:
Goran Jakovljevic19680d32017-05-11 10:38:36 +020071 DCHECK_EQ(4u, instruction->GetVectorLength());
72 __ FillW(dst, locations->InAt(0).AsRegister<GpuRegister>());
73 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +010074 case DataType::Type::kInt64:
Goran Jakovljevic19680d32017-05-11 10:38:36 +020075 DCHECK_EQ(2u, instruction->GetVectorLength());
76 __ FillD(dst, locations->InAt(0).AsRegister<GpuRegister>());
77 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +010078 case DataType::Type::kFloat32:
Goran Jakovljevic19680d32017-05-11 10:38:36 +020079 DCHECK_EQ(4u, instruction->GetVectorLength());
80 __ ReplicateFPToVectorRegister(dst,
81 locations->InAt(0).AsFpuRegister<FpuRegister>(),
82 /* is_double */ false);
83 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +010084 case DataType::Type::kFloat64:
Goran Jakovljevic19680d32017-05-11 10:38:36 +020085 DCHECK_EQ(2u, instruction->GetVectorLength());
86 __ ReplicateFPToVectorRegister(dst,
87 locations->InAt(0).AsFpuRegister<FpuRegister>(),
88 /* is_double */ true);
89 break;
90 default:
91 LOG(FATAL) << "Unsupported SIMD type";
92 UNREACHABLE();
93 }
Aart Bikf8f5a162017-02-06 15:35:29 -080094}
95
Aart Bik0148de42017-09-05 09:25:01 -070096void LocationsBuilderMIPS64::VisitVecExtractScalar(HVecExtractScalar* instruction) {
Aart Bikf8f5a162017-02-06 15:35:29 -080097 LOG(FATAL) << "No SIMD for " << instruction->GetId();
98}
99
Aart Bik0148de42017-09-05 09:25:01 -0700100void InstructionCodeGeneratorMIPS64::VisitVecExtractScalar(HVecExtractScalar* instruction) {
Aart Bikf8f5a162017-02-06 15:35:29 -0800101 LOG(FATAL) << "No SIMD for " << instruction->GetId();
102}
103
104// Helper to set up locations for vector unary operations.
105static void CreateVecUnOpLocations(ArenaAllocator* arena, HVecUnaryOperation* instruction) {
106 LocationSummary* locations = new (arena) LocationSummary(instruction);
107 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100108 case DataType::Type::kBool:
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200109 locations->SetInAt(0, Location::RequiresFpuRegister());
110 locations->SetOut(Location::RequiresFpuRegister(),
111 instruction->IsVecNot() ? Location::kOutputOverlap
112 : Location::kNoOutputOverlap);
113 break;
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100114 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100115 case DataType::Type::kInt8:
116 case DataType::Type::kUint16:
117 case DataType::Type::kInt16:
118 case DataType::Type::kInt32:
119 case DataType::Type::kInt64:
120 case DataType::Type::kFloat32:
121 case DataType::Type::kFloat64:
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200122 locations->SetInAt(0, Location::RequiresFpuRegister());
123 locations->SetOut(Location::RequiresFpuRegister(),
124 (instruction->IsVecNeg() || instruction->IsVecAbs())
125 ? Location::kOutputOverlap
126 : Location::kNoOutputOverlap);
Aart Bikf8f5a162017-02-06 15:35:29 -0800127 break;
128 default:
129 LOG(FATAL) << "Unsupported SIMD type";
130 UNREACHABLE();
131 }
132}
133
Aart Bik0148de42017-09-05 09:25:01 -0700134void LocationsBuilderMIPS64::VisitVecReduce(HVecReduce* instruction) {
135 CreateVecUnOpLocations(GetGraph()->GetArena(), instruction);
136}
137
138void InstructionCodeGeneratorMIPS64::VisitVecReduce(HVecReduce* instruction) {
139 LOG(FATAL) << "No SIMD for " << instruction->GetId();
140}
141
Aart Bikf8f5a162017-02-06 15:35:29 -0800142void LocationsBuilderMIPS64::VisitVecCnv(HVecCnv* instruction) {
143 CreateVecUnOpLocations(GetGraph()->GetArena(), instruction);
144}
145
146void InstructionCodeGeneratorMIPS64::VisitVecCnv(HVecCnv* instruction) {
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200147 LocationSummary* locations = instruction->GetLocations();
148 VectorRegister src = VectorRegisterFrom(locations->InAt(0));
149 VectorRegister dst = VectorRegisterFrom(locations->Out());
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100150 DataType::Type from = instruction->GetInputType();
151 DataType::Type to = instruction->GetResultType();
152 if (from == DataType::Type::kInt32 && to == DataType::Type::kFloat32) {
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200153 DCHECK_EQ(4u, instruction->GetVectorLength());
154 __ Ffint_sW(dst, src);
155 } else {
156 LOG(FATAL) << "Unsupported SIMD type";
157 UNREACHABLE();
158 }
Aart Bikf8f5a162017-02-06 15:35:29 -0800159}
160
161void LocationsBuilderMIPS64::VisitVecNeg(HVecNeg* instruction) {
162 CreateVecUnOpLocations(GetGraph()->GetArena(), instruction);
163}
164
165void InstructionCodeGeneratorMIPS64::VisitVecNeg(HVecNeg* instruction) {
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200166 LocationSummary* locations = instruction->GetLocations();
167 VectorRegister src = VectorRegisterFrom(locations->InAt(0));
168 VectorRegister dst = VectorRegisterFrom(locations->Out());
169 switch (instruction->GetPackedType()) {
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100170 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100171 case DataType::Type::kInt8:
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200172 DCHECK_EQ(16u, instruction->GetVectorLength());
173 __ FillB(dst, ZERO);
174 __ SubvB(dst, dst, src);
175 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100176 case DataType::Type::kUint16:
177 case DataType::Type::kInt16:
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200178 DCHECK_EQ(8u, instruction->GetVectorLength());
179 __ FillH(dst, ZERO);
180 __ SubvH(dst, dst, src);
181 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100182 case DataType::Type::kInt32:
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200183 DCHECK_EQ(4u, instruction->GetVectorLength());
184 __ FillW(dst, ZERO);
185 __ SubvW(dst, dst, src);
186 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100187 case DataType::Type::kInt64:
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200188 DCHECK_EQ(2u, instruction->GetVectorLength());
189 __ FillD(dst, ZERO);
190 __ SubvD(dst, dst, src);
191 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100192 case DataType::Type::kFloat32:
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200193 DCHECK_EQ(4u, instruction->GetVectorLength());
194 __ FillW(dst, ZERO);
195 __ FsubW(dst, dst, src);
196 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100197 case DataType::Type::kFloat64:
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200198 DCHECK_EQ(2u, instruction->GetVectorLength());
199 __ FillD(dst, ZERO);
200 __ FsubD(dst, dst, src);
201 break;
202 default:
203 LOG(FATAL) << "Unsupported SIMD type";
204 UNREACHABLE();
205 }
Aart Bikf8f5a162017-02-06 15:35:29 -0800206}
207
Aart Bik6daebeb2017-04-03 14:35:41 -0700208void LocationsBuilderMIPS64::VisitVecAbs(HVecAbs* instruction) {
209 CreateVecUnOpLocations(GetGraph()->GetArena(), instruction);
210}
211
212void InstructionCodeGeneratorMIPS64::VisitVecAbs(HVecAbs* instruction) {
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200213 LocationSummary* locations = instruction->GetLocations();
214 VectorRegister src = VectorRegisterFrom(locations->InAt(0));
215 VectorRegister dst = VectorRegisterFrom(locations->Out());
216 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100217 case DataType::Type::kInt8:
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200218 DCHECK_EQ(16u, instruction->GetVectorLength());
219 __ FillB(dst, ZERO); // all zeroes
220 __ Add_aB(dst, dst, src); // dst = abs(0) + abs(src)
221 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100222 case DataType::Type::kInt16:
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200223 DCHECK_EQ(8u, instruction->GetVectorLength());
224 __ FillH(dst, ZERO); // all zeroes
225 __ Add_aH(dst, dst, src); // dst = abs(0) + abs(src)
226 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100227 case DataType::Type::kInt32:
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200228 DCHECK_EQ(4u, instruction->GetVectorLength());
229 __ FillW(dst, ZERO); // all zeroes
230 __ Add_aW(dst, dst, src); // dst = abs(0) + abs(src)
231 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100232 case DataType::Type::kInt64:
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200233 DCHECK_EQ(2u, instruction->GetVectorLength());
234 __ FillD(dst, ZERO); // all zeroes
235 __ Add_aD(dst, dst, src); // dst = abs(0) + abs(src)
236 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100237 case DataType::Type::kFloat32:
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200238 DCHECK_EQ(4u, instruction->GetVectorLength());
239 __ LdiW(dst, -1); // all ones
240 __ SrliW(dst, dst, 1);
241 __ AndV(dst, dst, src);
242 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100243 case DataType::Type::kFloat64:
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200244 DCHECK_EQ(2u, instruction->GetVectorLength());
245 __ LdiD(dst, -1); // all ones
246 __ SrliD(dst, dst, 1);
247 __ AndV(dst, dst, src);
248 break;
249 default:
250 LOG(FATAL) << "Unsupported SIMD type";
251 UNREACHABLE();
252 }
Aart Bik6daebeb2017-04-03 14:35:41 -0700253}
254
Aart Bikf8f5a162017-02-06 15:35:29 -0800255void LocationsBuilderMIPS64::VisitVecNot(HVecNot* instruction) {
256 CreateVecUnOpLocations(GetGraph()->GetArena(), instruction);
257}
258
259void InstructionCodeGeneratorMIPS64::VisitVecNot(HVecNot* instruction) {
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200260 LocationSummary* locations = instruction->GetLocations();
261 VectorRegister src = VectorRegisterFrom(locations->InAt(0));
262 VectorRegister dst = VectorRegisterFrom(locations->Out());
263 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100264 case DataType::Type::kBool: // special case boolean-not
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200265 DCHECK_EQ(16u, instruction->GetVectorLength());
266 __ LdiB(dst, 1);
267 __ XorV(dst, dst, src);
268 break;
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100269 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100270 case DataType::Type::kInt8:
271 case DataType::Type::kUint16:
272 case DataType::Type::kInt16:
273 case DataType::Type::kInt32:
274 case DataType::Type::kInt64:
275 case DataType::Type::kFloat32:
276 case DataType::Type::kFloat64:
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200277 DCHECK_LE(2u, instruction->GetVectorLength());
278 DCHECK_LE(instruction->GetVectorLength(), 16u);
279 __ NorV(dst, src, src); // lanes do not matter
280 break;
281 default:
282 LOG(FATAL) << "Unsupported SIMD type";
283 UNREACHABLE();
284 }
Aart Bikf8f5a162017-02-06 15:35:29 -0800285}
286
287// Helper to set up locations for vector binary operations.
288static void CreateVecBinOpLocations(ArenaAllocator* arena, HVecBinaryOperation* instruction) {
289 LocationSummary* locations = new (arena) LocationSummary(instruction);
290 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100291 case DataType::Type::kBool:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100292 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100293 case DataType::Type::kInt8:
294 case DataType::Type::kUint16:
295 case DataType::Type::kInt16:
296 case DataType::Type::kInt32:
297 case DataType::Type::kInt64:
298 case DataType::Type::kFloat32:
299 case DataType::Type::kFloat64:
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200300 locations->SetInAt(0, Location::RequiresFpuRegister());
301 locations->SetInAt(1, Location::RequiresFpuRegister());
302 locations->SetOut(Location::RequiresFpuRegister(), Location::kNoOutputOverlap);
Aart Bikf8f5a162017-02-06 15:35:29 -0800303 break;
304 default:
305 LOG(FATAL) << "Unsupported SIMD type";
306 UNREACHABLE();
307 }
308}
309
310void LocationsBuilderMIPS64::VisitVecAdd(HVecAdd* instruction) {
311 CreateVecBinOpLocations(GetGraph()->GetArena(), instruction);
312}
313
314void InstructionCodeGeneratorMIPS64::VisitVecAdd(HVecAdd* instruction) {
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200315 LocationSummary* locations = instruction->GetLocations();
316 VectorRegister lhs = VectorRegisterFrom(locations->InAt(0));
317 VectorRegister rhs = VectorRegisterFrom(locations->InAt(1));
318 VectorRegister dst = VectorRegisterFrom(locations->Out());
319 switch (instruction->GetPackedType()) {
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100320 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100321 case DataType::Type::kInt8:
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200322 DCHECK_EQ(16u, instruction->GetVectorLength());
323 __ AddvB(dst, lhs, rhs);
324 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100325 case DataType::Type::kUint16:
326 case DataType::Type::kInt16:
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200327 DCHECK_EQ(8u, instruction->GetVectorLength());
328 __ AddvH(dst, lhs, rhs);
329 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100330 case DataType::Type::kInt32:
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200331 DCHECK_EQ(4u, instruction->GetVectorLength());
332 __ AddvW(dst, lhs, rhs);
333 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100334 case DataType::Type::kInt64:
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200335 DCHECK_EQ(2u, instruction->GetVectorLength());
336 __ AddvD(dst, lhs, rhs);
337 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100338 case DataType::Type::kFloat32:
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200339 DCHECK_EQ(4u, instruction->GetVectorLength());
340 __ FaddW(dst, lhs, rhs);
341 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100342 case DataType::Type::kFloat64:
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200343 DCHECK_EQ(2u, instruction->GetVectorLength());
344 __ FaddD(dst, lhs, rhs);
345 break;
346 default:
347 LOG(FATAL) << "Unsupported SIMD type";
348 UNREACHABLE();
349 }
Aart Bikf8f5a162017-02-06 15:35:29 -0800350}
351
Aart Bikf3e61ee2017-04-12 17:09:20 -0700352void LocationsBuilderMIPS64::VisitVecHalvingAdd(HVecHalvingAdd* instruction) {
353 CreateVecBinOpLocations(GetGraph()->GetArena(), instruction);
354}
355
356void InstructionCodeGeneratorMIPS64::VisitVecHalvingAdd(HVecHalvingAdd* instruction) {
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200357 LocationSummary* locations = instruction->GetLocations();
358 VectorRegister lhs = VectorRegisterFrom(locations->InAt(0));
359 VectorRegister rhs = VectorRegisterFrom(locations->InAt(1));
360 VectorRegister dst = VectorRegisterFrom(locations->Out());
361 switch (instruction->GetPackedType()) {
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100362 case DataType::Type::kUint8:
363 DCHECK_EQ(16u, instruction->GetVectorLength());
364 instruction->IsRounded()
365 ? __ Aver_uB(dst, lhs, rhs)
366 : __ Ave_uB(dst, lhs, rhs);
367 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100368 case DataType::Type::kInt8:
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200369 DCHECK_EQ(16u, instruction->GetVectorLength());
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100370 instruction->IsRounded()
371 ? __ Aver_sB(dst, lhs, rhs)
372 : __ Ave_sB(dst, lhs, rhs);
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200373 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100374 case DataType::Type::kUint16:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100375 DCHECK_EQ(8u, instruction->GetVectorLength());
376 instruction->IsRounded()
377 ? __ Aver_uH(dst, lhs, rhs)
378 : __ Ave_uH(dst, lhs, rhs);
379 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100380 case DataType::Type::kInt16:
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200381 DCHECK_EQ(8u, instruction->GetVectorLength());
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100382 instruction->IsRounded()
383 ? __ Aver_sH(dst, lhs, rhs)
384 : __ Ave_sH(dst, lhs, rhs);
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200385 break;
386 default:
387 LOG(FATAL) << "Unsupported SIMD type";
388 UNREACHABLE();
389 }
Aart Bikf3e61ee2017-04-12 17:09:20 -0700390}
391
Aart Bikf8f5a162017-02-06 15:35:29 -0800392void LocationsBuilderMIPS64::VisitVecSub(HVecSub* instruction) {
393 CreateVecBinOpLocations(GetGraph()->GetArena(), instruction);
394}
395
396void InstructionCodeGeneratorMIPS64::VisitVecSub(HVecSub* instruction) {
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200397 LocationSummary* locations = instruction->GetLocations();
398 VectorRegister lhs = VectorRegisterFrom(locations->InAt(0));
399 VectorRegister rhs = VectorRegisterFrom(locations->InAt(1));
400 VectorRegister dst = VectorRegisterFrom(locations->Out());
401 switch (instruction->GetPackedType()) {
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100402 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100403 case DataType::Type::kInt8:
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200404 DCHECK_EQ(16u, instruction->GetVectorLength());
405 __ SubvB(dst, lhs, rhs);
406 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100407 case DataType::Type::kUint16:
408 case DataType::Type::kInt16:
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200409 DCHECK_EQ(8u, instruction->GetVectorLength());
410 __ SubvH(dst, lhs, rhs);
411 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100412 case DataType::Type::kInt32:
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200413 DCHECK_EQ(4u, instruction->GetVectorLength());
414 __ SubvW(dst, lhs, rhs);
415 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100416 case DataType::Type::kInt64:
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200417 DCHECK_EQ(2u, instruction->GetVectorLength());
418 __ SubvD(dst, lhs, rhs);
419 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100420 case DataType::Type::kFloat32:
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200421 DCHECK_EQ(4u, instruction->GetVectorLength());
422 __ FsubW(dst, lhs, rhs);
423 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100424 case DataType::Type::kFloat64:
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200425 DCHECK_EQ(2u, instruction->GetVectorLength());
426 __ FsubD(dst, lhs, rhs);
427 break;
428 default:
429 LOG(FATAL) << "Unsupported SIMD type";
430 UNREACHABLE();
431 }
Aart Bikf8f5a162017-02-06 15:35:29 -0800432}
433
434void LocationsBuilderMIPS64::VisitVecMul(HVecMul* instruction) {
435 CreateVecBinOpLocations(GetGraph()->GetArena(), instruction);
436}
437
438void InstructionCodeGeneratorMIPS64::VisitVecMul(HVecMul* instruction) {
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200439 LocationSummary* locations = instruction->GetLocations();
440 VectorRegister lhs = VectorRegisterFrom(locations->InAt(0));
441 VectorRegister rhs = VectorRegisterFrom(locations->InAt(1));
442 VectorRegister dst = VectorRegisterFrom(locations->Out());
443 switch (instruction->GetPackedType()) {
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100444 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100445 case DataType::Type::kInt8:
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200446 DCHECK_EQ(16u, instruction->GetVectorLength());
447 __ MulvB(dst, lhs, rhs);
448 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100449 case DataType::Type::kUint16:
450 case DataType::Type::kInt16:
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200451 DCHECK_EQ(8u, instruction->GetVectorLength());
452 __ MulvH(dst, lhs, rhs);
453 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100454 case DataType::Type::kInt32:
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200455 DCHECK_EQ(4u, instruction->GetVectorLength());
456 __ MulvW(dst, lhs, rhs);
457 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100458 case DataType::Type::kInt64:
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200459 DCHECK_EQ(2u, instruction->GetVectorLength());
460 __ MulvD(dst, lhs, rhs);
461 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100462 case DataType::Type::kFloat32:
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200463 DCHECK_EQ(4u, instruction->GetVectorLength());
464 __ FmulW(dst, lhs, rhs);
465 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100466 case DataType::Type::kFloat64:
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200467 DCHECK_EQ(2u, instruction->GetVectorLength());
468 __ FmulD(dst, lhs, rhs);
469 break;
470 default:
471 LOG(FATAL) << "Unsupported SIMD type";
472 UNREACHABLE();
473 }
Aart Bikf8f5a162017-02-06 15:35:29 -0800474}
475
476void LocationsBuilderMIPS64::VisitVecDiv(HVecDiv* instruction) {
477 CreateVecBinOpLocations(GetGraph()->GetArena(), instruction);
478}
479
480void InstructionCodeGeneratorMIPS64::VisitVecDiv(HVecDiv* instruction) {
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200481 LocationSummary* locations = instruction->GetLocations();
482 VectorRegister lhs = VectorRegisterFrom(locations->InAt(0));
483 VectorRegister rhs = VectorRegisterFrom(locations->InAt(1));
484 VectorRegister dst = VectorRegisterFrom(locations->Out());
485 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100486 case DataType::Type::kFloat32:
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200487 DCHECK_EQ(4u, instruction->GetVectorLength());
488 __ FdivW(dst, lhs, rhs);
489 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100490 case DataType::Type::kFloat64:
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200491 DCHECK_EQ(2u, instruction->GetVectorLength());
492 __ FdivD(dst, lhs, rhs);
493 break;
494 default:
495 LOG(FATAL) << "Unsupported SIMD type";
496 UNREACHABLE();
497 }
Aart Bikf8f5a162017-02-06 15:35:29 -0800498}
499
Aart Bikf3e61ee2017-04-12 17:09:20 -0700500void LocationsBuilderMIPS64::VisitVecMin(HVecMin* instruction) {
501 CreateVecBinOpLocations(GetGraph()->GetArena(), instruction);
502}
503
504void InstructionCodeGeneratorMIPS64::VisitVecMin(HVecMin* instruction) {
Goran Jakovljevic8fea1e12017-06-06 13:28:42 +0200505 LocationSummary* locations = instruction->GetLocations();
506 VectorRegister lhs = VectorRegisterFrom(locations->InAt(0));
507 VectorRegister rhs = VectorRegisterFrom(locations->InAt(1));
508 VectorRegister dst = VectorRegisterFrom(locations->Out());
509 switch (instruction->GetPackedType()) {
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100510 case DataType::Type::kUint8:
511 DCHECK_EQ(16u, instruction->GetVectorLength());
512 __ Min_uB(dst, lhs, rhs);
513 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100514 case DataType::Type::kInt8:
Goran Jakovljevic8fea1e12017-06-06 13:28:42 +0200515 DCHECK_EQ(16u, instruction->GetVectorLength());
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100516 __ Min_sB(dst, lhs, rhs);
Goran Jakovljevic8fea1e12017-06-06 13:28:42 +0200517 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100518 case DataType::Type::kUint16:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100519 DCHECK_EQ(8u, instruction->GetVectorLength());
520 __ Min_uH(dst, lhs, rhs);
521 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100522 case DataType::Type::kInt16:
Goran Jakovljevic8fea1e12017-06-06 13:28:42 +0200523 DCHECK_EQ(8u, instruction->GetVectorLength());
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100524 __ Min_sH(dst, lhs, rhs);
Goran Jakovljevic8fea1e12017-06-06 13:28:42 +0200525 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100526 case DataType::Type::kInt32:
Goran Jakovljevic8fea1e12017-06-06 13:28:42 +0200527 DCHECK_EQ(4u, instruction->GetVectorLength());
528 if (instruction->IsUnsigned()) {
529 __ Min_uW(dst, lhs, rhs);
530 } else {
531 __ Min_sW(dst, lhs, rhs);
532 }
533 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100534 case DataType::Type::kInt64:
Goran Jakovljevic8fea1e12017-06-06 13:28:42 +0200535 DCHECK_EQ(2u, instruction->GetVectorLength());
536 if (instruction->IsUnsigned()) {
537 __ Min_uD(dst, lhs, rhs);
538 } else {
539 __ Min_sD(dst, lhs, rhs);
540 }
541 break;
542 // When one of arguments is NaN, fmin.df returns other argument, but Java expects a NaN value.
543 // TODO: Fix min(x, NaN) cases for float and double.
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100544 case DataType::Type::kFloat32:
Goran Jakovljevic8fea1e12017-06-06 13:28:42 +0200545 DCHECK_EQ(4u, instruction->GetVectorLength());
546 DCHECK(!instruction->IsUnsigned());
547 __ FminW(dst, lhs, rhs);
548 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100549 case DataType::Type::kFloat64:
Goran Jakovljevic8fea1e12017-06-06 13:28:42 +0200550 DCHECK_EQ(2u, instruction->GetVectorLength());
551 DCHECK(!instruction->IsUnsigned());
552 __ FminD(dst, lhs, rhs);
553 break;
554 default:
555 LOG(FATAL) << "Unsupported SIMD type";
556 UNREACHABLE();
557 }
Aart Bikf3e61ee2017-04-12 17:09:20 -0700558}
559
560void LocationsBuilderMIPS64::VisitVecMax(HVecMax* instruction) {
561 CreateVecBinOpLocations(GetGraph()->GetArena(), instruction);
562}
563
564void InstructionCodeGeneratorMIPS64::VisitVecMax(HVecMax* instruction) {
Goran Jakovljevic8fea1e12017-06-06 13:28:42 +0200565 LocationSummary* locations = instruction->GetLocations();
566 VectorRegister lhs = VectorRegisterFrom(locations->InAt(0));
567 VectorRegister rhs = VectorRegisterFrom(locations->InAt(1));
568 VectorRegister dst = VectorRegisterFrom(locations->Out());
569 switch (instruction->GetPackedType()) {
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100570 case DataType::Type::kUint8:
571 DCHECK_EQ(16u, instruction->GetVectorLength());
572 __ Max_uB(dst, lhs, rhs);
573 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100574 case DataType::Type::kInt8:
Goran Jakovljevic8fea1e12017-06-06 13:28:42 +0200575 DCHECK_EQ(16u, instruction->GetVectorLength());
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100576 __ Max_sB(dst, lhs, rhs);
Goran Jakovljevic8fea1e12017-06-06 13:28:42 +0200577 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100578 case DataType::Type::kUint16:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100579 DCHECK_EQ(8u, instruction->GetVectorLength());
580 __ Max_uH(dst, lhs, rhs);
581 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100582 case DataType::Type::kInt16:
Goran Jakovljevic8fea1e12017-06-06 13:28:42 +0200583 DCHECK_EQ(8u, instruction->GetVectorLength());
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100584 __ Max_sH(dst, lhs, rhs);
Goran Jakovljevic8fea1e12017-06-06 13:28:42 +0200585 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100586 case DataType::Type::kInt32:
Goran Jakovljevic8fea1e12017-06-06 13:28:42 +0200587 DCHECK_EQ(4u, instruction->GetVectorLength());
588 if (instruction->IsUnsigned()) {
589 __ Max_uW(dst, lhs, rhs);
590 } else {
591 __ Max_sW(dst, lhs, rhs);
592 }
593 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100594 case DataType::Type::kInt64:
Goran Jakovljevic8fea1e12017-06-06 13:28:42 +0200595 DCHECK_EQ(2u, instruction->GetVectorLength());
596 if (instruction->IsUnsigned()) {
597 __ Max_uD(dst, lhs, rhs);
598 } else {
599 __ Max_sD(dst, lhs, rhs);
600 }
601 break;
602 // When one of arguments is NaN, fmax.df returns other argument, but Java expects a NaN value.
603 // TODO: Fix max(x, NaN) cases for float and double.
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100604 case DataType::Type::kFloat32:
Goran Jakovljevic8fea1e12017-06-06 13:28:42 +0200605 DCHECK_EQ(4u, instruction->GetVectorLength());
606 DCHECK(!instruction->IsUnsigned());
607 __ FmaxW(dst, lhs, rhs);
608 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100609 case DataType::Type::kFloat64:
Goran Jakovljevic8fea1e12017-06-06 13:28:42 +0200610 DCHECK_EQ(2u, instruction->GetVectorLength());
611 DCHECK(!instruction->IsUnsigned());
612 __ FmaxD(dst, lhs, rhs);
613 break;
614 default:
615 LOG(FATAL) << "Unsupported SIMD type";
616 UNREACHABLE();
617 }
Aart Bikf3e61ee2017-04-12 17:09:20 -0700618}
619
Aart Bikf8f5a162017-02-06 15:35:29 -0800620void LocationsBuilderMIPS64::VisitVecAnd(HVecAnd* instruction) {
621 CreateVecBinOpLocations(GetGraph()->GetArena(), instruction);
622}
623
624void InstructionCodeGeneratorMIPS64::VisitVecAnd(HVecAnd* instruction) {
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200625 LocationSummary* locations = instruction->GetLocations();
626 VectorRegister lhs = VectorRegisterFrom(locations->InAt(0));
627 VectorRegister rhs = VectorRegisterFrom(locations->InAt(1));
628 VectorRegister dst = VectorRegisterFrom(locations->Out());
629 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100630 case DataType::Type::kBool:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100631 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100632 case DataType::Type::kInt8:
633 case DataType::Type::kUint16:
634 case DataType::Type::kInt16:
635 case DataType::Type::kInt32:
636 case DataType::Type::kInt64:
637 case DataType::Type::kFloat32:
638 case DataType::Type::kFloat64:
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200639 DCHECK_LE(2u, instruction->GetVectorLength());
640 DCHECK_LE(instruction->GetVectorLength(), 16u);
641 __ AndV(dst, lhs, rhs); // lanes do not matter
642 break;
643 default:
644 LOG(FATAL) << "Unsupported SIMD type";
645 UNREACHABLE();
646 }
Aart Bikf8f5a162017-02-06 15:35:29 -0800647}
648
649void LocationsBuilderMIPS64::VisitVecAndNot(HVecAndNot* instruction) {
650 CreateVecBinOpLocations(GetGraph()->GetArena(), instruction);
651}
652
653void InstructionCodeGeneratorMIPS64::VisitVecAndNot(HVecAndNot* instruction) {
654 LOG(FATAL) << "No SIMD for " << instruction->GetId();
655}
656
657void LocationsBuilderMIPS64::VisitVecOr(HVecOr* instruction) {
658 CreateVecBinOpLocations(GetGraph()->GetArena(), instruction);
659}
660
661void InstructionCodeGeneratorMIPS64::VisitVecOr(HVecOr* instruction) {
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200662 LocationSummary* locations = instruction->GetLocations();
663 VectorRegister lhs = VectorRegisterFrom(locations->InAt(0));
664 VectorRegister rhs = VectorRegisterFrom(locations->InAt(1));
665 VectorRegister dst = VectorRegisterFrom(locations->Out());
666 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100667 case DataType::Type::kBool:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100668 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100669 case DataType::Type::kInt8:
670 case DataType::Type::kUint16:
671 case DataType::Type::kInt16:
672 case DataType::Type::kInt32:
673 case DataType::Type::kInt64:
674 case DataType::Type::kFloat32:
675 case DataType::Type::kFloat64:
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200676 DCHECK_LE(2u, instruction->GetVectorLength());
677 DCHECK_LE(instruction->GetVectorLength(), 16u);
678 __ OrV(dst, lhs, rhs); // lanes do not matter
679 break;
680 default:
681 LOG(FATAL) << "Unsupported SIMD type";
682 UNREACHABLE();
683 }
Aart Bikf8f5a162017-02-06 15:35:29 -0800684}
685
686void LocationsBuilderMIPS64::VisitVecXor(HVecXor* instruction) {
687 CreateVecBinOpLocations(GetGraph()->GetArena(), instruction);
688}
689
690void InstructionCodeGeneratorMIPS64::VisitVecXor(HVecXor* instruction) {
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200691 LocationSummary* locations = instruction->GetLocations();
692 VectorRegister lhs = VectorRegisterFrom(locations->InAt(0));
693 VectorRegister rhs = VectorRegisterFrom(locations->InAt(1));
694 VectorRegister dst = VectorRegisterFrom(locations->Out());
695 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100696 case DataType::Type::kBool:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100697 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100698 case DataType::Type::kInt8:
699 case DataType::Type::kUint16:
700 case DataType::Type::kInt16:
701 case DataType::Type::kInt32:
702 case DataType::Type::kInt64:
703 case DataType::Type::kFloat32:
704 case DataType::Type::kFloat64:
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200705 DCHECK_LE(2u, instruction->GetVectorLength());
706 DCHECK_LE(instruction->GetVectorLength(), 16u);
707 __ XorV(dst, lhs, rhs); // lanes do not matter
708 break;
709 default:
710 LOG(FATAL) << "Unsupported SIMD type";
711 UNREACHABLE();
712 }
Aart Bikf8f5a162017-02-06 15:35:29 -0800713}
714
715// Helper to set up locations for vector shift operations.
716static void CreateVecShiftLocations(ArenaAllocator* arena, HVecBinaryOperation* instruction) {
717 LocationSummary* locations = new (arena) LocationSummary(instruction);
718 switch (instruction->GetPackedType()) {
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100719 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100720 case DataType::Type::kInt8:
721 case DataType::Type::kUint16:
722 case DataType::Type::kInt16:
723 case DataType::Type::kInt32:
724 case DataType::Type::kInt64:
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200725 locations->SetInAt(0, Location::RequiresFpuRegister());
726 locations->SetInAt(1, Location::ConstantLocation(instruction->InputAt(1)->AsConstant()));
727 locations->SetOut(Location::RequiresFpuRegister(), Location::kNoOutputOverlap);
Aart Bikf8f5a162017-02-06 15:35:29 -0800728 break;
729 default:
730 LOG(FATAL) << "Unsupported SIMD type";
731 UNREACHABLE();
732 }
733}
734
735void LocationsBuilderMIPS64::VisitVecShl(HVecShl* instruction) {
736 CreateVecShiftLocations(GetGraph()->GetArena(), instruction);
737}
738
739void InstructionCodeGeneratorMIPS64::VisitVecShl(HVecShl* instruction) {
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200740 LocationSummary* locations = instruction->GetLocations();
741 VectorRegister lhs = VectorRegisterFrom(locations->InAt(0));
742 VectorRegister dst = VectorRegisterFrom(locations->Out());
743 int32_t value = locations->InAt(1).GetConstant()->AsIntConstant()->GetValue();
744 switch (instruction->GetPackedType()) {
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100745 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100746 case DataType::Type::kInt8:
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200747 DCHECK_EQ(16u, instruction->GetVectorLength());
748 __ SlliB(dst, lhs, value);
749 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100750 case DataType::Type::kUint16:
751 case DataType::Type::kInt16:
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200752 DCHECK_EQ(8u, instruction->GetVectorLength());
753 __ SlliH(dst, lhs, value);
754 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100755 case DataType::Type::kInt32:
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200756 DCHECK_EQ(4u, instruction->GetVectorLength());
757 __ SlliW(dst, lhs, value);
758 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100759 case DataType::Type::kInt64:
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200760 DCHECK_EQ(2u, instruction->GetVectorLength());
761 __ SlliD(dst, lhs, value);
762 break;
763 default:
764 LOG(FATAL) << "Unsupported SIMD type";
765 UNREACHABLE();
766 }
Aart Bikf8f5a162017-02-06 15:35:29 -0800767}
768
769void LocationsBuilderMIPS64::VisitVecShr(HVecShr* instruction) {
770 CreateVecShiftLocations(GetGraph()->GetArena(), instruction);
771}
772
773void InstructionCodeGeneratorMIPS64::VisitVecShr(HVecShr* instruction) {
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200774 LocationSummary* locations = instruction->GetLocations();
775 VectorRegister lhs = VectorRegisterFrom(locations->InAt(0));
776 VectorRegister dst = VectorRegisterFrom(locations->Out());
777 int32_t value = locations->InAt(1).GetConstant()->AsIntConstant()->GetValue();
778 switch (instruction->GetPackedType()) {
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100779 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100780 case DataType::Type::kInt8:
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200781 DCHECK_EQ(16u, instruction->GetVectorLength());
782 __ SraiB(dst, lhs, value);
783 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100784 case DataType::Type::kUint16:
785 case DataType::Type::kInt16:
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200786 DCHECK_EQ(8u, instruction->GetVectorLength());
787 __ SraiH(dst, lhs, value);
788 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100789 case DataType::Type::kInt32:
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200790 DCHECK_EQ(4u, instruction->GetVectorLength());
791 __ SraiW(dst, lhs, value);
792 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100793 case DataType::Type::kInt64:
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200794 DCHECK_EQ(2u, instruction->GetVectorLength());
795 __ SraiD(dst, lhs, value);
796 break;
797 default:
798 LOG(FATAL) << "Unsupported SIMD type";
799 UNREACHABLE();
800 }
Aart Bikf8f5a162017-02-06 15:35:29 -0800801}
802
803void LocationsBuilderMIPS64::VisitVecUShr(HVecUShr* instruction) {
804 CreateVecShiftLocations(GetGraph()->GetArena(), instruction);
805}
806
807void InstructionCodeGeneratorMIPS64::VisitVecUShr(HVecUShr* instruction) {
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200808 LocationSummary* locations = instruction->GetLocations();
809 VectorRegister lhs = VectorRegisterFrom(locations->InAt(0));
810 VectorRegister dst = VectorRegisterFrom(locations->Out());
811 int32_t value = locations->InAt(1).GetConstant()->AsIntConstant()->GetValue();
812 switch (instruction->GetPackedType()) {
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100813 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100814 case DataType::Type::kInt8:
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200815 DCHECK_EQ(16u, instruction->GetVectorLength());
816 __ SrliB(dst, lhs, value);
817 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100818 case DataType::Type::kUint16:
819 case DataType::Type::kInt16:
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200820 DCHECK_EQ(8u, instruction->GetVectorLength());
821 __ SrliH(dst, lhs, value);
822 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100823 case DataType::Type::kInt32:
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200824 DCHECK_EQ(4u, instruction->GetVectorLength());
825 __ SrliW(dst, lhs, value);
826 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100827 case DataType::Type::kInt64:
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200828 DCHECK_EQ(2u, instruction->GetVectorLength());
829 __ SrliD(dst, lhs, value);
830 break;
831 default:
832 LOG(FATAL) << "Unsupported SIMD type";
833 UNREACHABLE();
834 }
Aart Bikf8f5a162017-02-06 15:35:29 -0800835}
836
Aart Bik0148de42017-09-05 09:25:01 -0700837void LocationsBuilderMIPS64::VisitVecSetScalars(HVecSetScalars* instruction) {
838 LOG(FATAL) << "No SIMD for " << instruction->GetId();
839}
840
841void InstructionCodeGeneratorMIPS64::VisitVecSetScalars(HVecSetScalars* instruction) {
842 LOG(FATAL) << "No SIMD for " << instruction->GetId();
843}
844
Aart Bikdbbac8f2017-09-01 13:06:08 -0700845// Helper to set up locations for vector accumulations.
846static void CreateVecAccumLocations(ArenaAllocator* arena, HVecOperation* instruction) {
847 LocationSummary* locations = new (arena) LocationSummary(instruction);
848 switch (instruction->GetPackedType()) {
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100849 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100850 case DataType::Type::kInt8:
851 case DataType::Type::kUint16:
852 case DataType::Type::kInt16:
853 case DataType::Type::kInt32:
854 case DataType::Type::kInt64:
Aart Bikdbbac8f2017-09-01 13:06:08 -0700855 locations->SetInAt(0, Location::RequiresFpuRegister());
856 locations->SetInAt(1, Location::RequiresFpuRegister());
857 locations->SetInAt(2, Location::RequiresFpuRegister());
Lena Djokicbc5460b2017-07-20 16:07:36 +0200858 locations->SetOut(Location::SameAsFirstInput());
859 break;
860 default:
861 LOG(FATAL) << "Unsupported SIMD type";
862 UNREACHABLE();
863 }
Artem Serovf34dd202017-04-10 17:41:46 +0100864}
865
Aart Bikdbbac8f2017-09-01 13:06:08 -0700866void LocationsBuilderMIPS64::VisitVecMultiplyAccumulate(HVecMultiplyAccumulate* instruction) {
867 CreateVecAccumLocations(GetGraph()->GetArena(), instruction);
868}
869
870void InstructionCodeGeneratorMIPS64::VisitVecMultiplyAccumulate(HVecMultiplyAccumulate* instruction) {
871 LocationSummary* locations = instruction->GetLocations();
872 VectorRegister acc = VectorRegisterFrom(locations->InAt(0));
873 VectorRegister left = VectorRegisterFrom(locations->InAt(1));
874 VectorRegister right = VectorRegisterFrom(locations->InAt(2));
875 switch (instruction->GetPackedType()) {
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100876 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100877 case DataType::Type::kInt8:
Aart Bikdbbac8f2017-09-01 13:06:08 -0700878 DCHECK_EQ(16u, instruction->GetVectorLength());
879 if (instruction->GetOpKind() == HInstruction::kAdd) {
Lena Djokicbc5460b2017-07-20 16:07:36 +0200880 __ MaddvB(acc, left, right);
881 } else {
882 __ MsubvB(acc, left, right);
883 }
884 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100885 case DataType::Type::kUint16:
886 case DataType::Type::kInt16:
Aart Bikdbbac8f2017-09-01 13:06:08 -0700887 DCHECK_EQ(8u, instruction->GetVectorLength());
888 if (instruction->GetOpKind() == HInstruction::kAdd) {
Lena Djokicbc5460b2017-07-20 16:07:36 +0200889 __ MaddvH(acc, left, right);
890 } else {
891 __ MsubvH(acc, left, right);
892 }
893 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100894 case DataType::Type::kInt32:
Aart Bikdbbac8f2017-09-01 13:06:08 -0700895 DCHECK_EQ(4u, instruction->GetVectorLength());
896 if (instruction->GetOpKind() == HInstruction::kAdd) {
Lena Djokicbc5460b2017-07-20 16:07:36 +0200897 __ MaddvW(acc, left, right);
898 } else {
899 __ MsubvW(acc, left, right);
900 }
901 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100902 case DataType::Type::kInt64:
Aart Bikdbbac8f2017-09-01 13:06:08 -0700903 DCHECK_EQ(2u, instruction->GetVectorLength());
904 if (instruction->GetOpKind() == HInstruction::kAdd) {
Lena Djokicbc5460b2017-07-20 16:07:36 +0200905 __ MaddvD(acc, left, right);
906 } else {
907 __ MsubvD(acc, left, right);
908 }
909 break;
910 default:
911 LOG(FATAL) << "Unsupported SIMD type";
912 UNREACHABLE();
913 }
Artem Serovf34dd202017-04-10 17:41:46 +0100914}
915
Aart Bikdbbac8f2017-09-01 13:06:08 -0700916void LocationsBuilderMIPS64::VisitVecSADAccumulate(HVecSADAccumulate* instruction) {
917 CreateVecAccumLocations(GetGraph()->GetArena(), instruction);
918}
919
920void InstructionCodeGeneratorMIPS64::VisitVecSADAccumulate(HVecSADAccumulate* instruction) {
921 LOG(FATAL) << "No SIMD for " << instruction->GetId();
922 // TODO: implement this, location helper already filled out (shared with MulAcc).
923}
924
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200925// Helper to set up locations for vector memory operations.
926static void CreateVecMemLocations(ArenaAllocator* arena,
927 HVecMemoryOperation* instruction,
928 bool is_load) {
929 LocationSummary* locations = new (arena) LocationSummary(instruction);
930 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100931 case DataType::Type::kBool:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100932 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100933 case DataType::Type::kInt8:
934 case DataType::Type::kUint16:
935 case DataType::Type::kInt16:
936 case DataType::Type::kInt32:
937 case DataType::Type::kInt64:
938 case DataType::Type::kFloat32:
939 case DataType::Type::kFloat64:
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200940 locations->SetInAt(0, Location::RequiresRegister());
941 locations->SetInAt(1, Location::RegisterOrConstant(instruction->InputAt(1)));
942 if (is_load) {
943 locations->SetOut(Location::RequiresFpuRegister());
944 } else {
945 locations->SetInAt(2, Location::RequiresFpuRegister());
946 }
947 break;
948 default:
949 LOG(FATAL) << "Unsupported SIMD type";
950 UNREACHABLE();
951 }
952}
953
954// Helper to prepare register and offset for vector memory operations. Returns the offset and sets
955// the output parameter adjusted_base to the original base or to a reserved temporary register (AT).
956int32_t InstructionCodeGeneratorMIPS64::VecAddress(LocationSummary* locations,
957 size_t size,
958 /* out */ GpuRegister* adjusted_base) {
959 GpuRegister base = locations->InAt(0).AsRegister<GpuRegister>();
960 Location index = locations->InAt(1);
961 int scale = TIMES_1;
962 switch (size) {
963 case 2: scale = TIMES_2; break;
964 case 4: scale = TIMES_4; break;
965 case 8: scale = TIMES_8; break;
966 default: break;
967 }
968 int32_t offset = mirror::Array::DataOffset(size).Int32Value();
969
970 if (index.IsConstant()) {
971 offset += index.GetConstant()->AsIntConstant()->GetValue() << scale;
972 __ AdjustBaseOffsetAndElementSizeShift(base, offset, scale);
973 *adjusted_base = base;
974 } else {
975 GpuRegister index_reg = index.AsRegister<GpuRegister>();
976 if (scale != TIMES_1) {
977 __ Dlsa(AT, index_reg, base, scale);
978 } else {
979 __ Daddu(AT, base, index_reg);
980 }
981 *adjusted_base = AT;
982 }
983 return offset;
984}
985
Aart Bikf8f5a162017-02-06 15:35:29 -0800986void LocationsBuilderMIPS64::VisitVecLoad(HVecLoad* instruction) {
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200987 CreateVecMemLocations(GetGraph()->GetArena(), instruction, /* is_load */ true);
Aart Bikf8f5a162017-02-06 15:35:29 -0800988}
989
990void InstructionCodeGeneratorMIPS64::VisitVecLoad(HVecLoad* instruction) {
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200991 LocationSummary* locations = instruction->GetLocations();
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100992 size_t size = DataType::Size(instruction->GetPackedType());
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200993 VectorRegister reg = VectorRegisterFrom(locations->Out());
994 GpuRegister base;
995 int32_t offset = VecAddress(locations, size, &base);
996 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100997 case DataType::Type::kBool:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100998 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100999 case DataType::Type::kInt8:
Goran Jakovljevic19680d32017-05-11 10:38:36 +02001000 DCHECK_EQ(16u, instruction->GetVectorLength());
1001 __ LdB(reg, base, offset);
1002 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001003 case DataType::Type::kUint16:
1004 case DataType::Type::kInt16:
Goran Jakovljevic19680d32017-05-11 10:38:36 +02001005 // Loading 8-bytes (needed if dealing with compressed strings in StringCharAt) from unaligned
1006 // memory address may cause a trap to the kernel if the CPU doesn't directly support unaligned
1007 // loads and stores.
1008 // TODO: Implement support for StringCharAt.
1009 DCHECK(!instruction->IsStringCharAt());
1010 DCHECK_EQ(8u, instruction->GetVectorLength());
1011 __ LdH(reg, base, offset);
1012 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001013 case DataType::Type::kInt32:
1014 case DataType::Type::kFloat32:
Goran Jakovljevic19680d32017-05-11 10:38:36 +02001015 DCHECK_EQ(4u, instruction->GetVectorLength());
1016 __ LdW(reg, base, offset);
1017 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001018 case DataType::Type::kInt64:
1019 case DataType::Type::kFloat64:
Goran Jakovljevic19680d32017-05-11 10:38:36 +02001020 DCHECK_EQ(2u, instruction->GetVectorLength());
1021 __ LdD(reg, base, offset);
1022 break;
1023 default:
1024 LOG(FATAL) << "Unsupported SIMD type";
1025 UNREACHABLE();
1026 }
Aart Bikf8f5a162017-02-06 15:35:29 -08001027}
1028
1029void LocationsBuilderMIPS64::VisitVecStore(HVecStore* instruction) {
Goran Jakovljevic19680d32017-05-11 10:38:36 +02001030 CreateVecMemLocations(GetGraph()->GetArena(), instruction, /* is_load */ false);
Aart Bikf8f5a162017-02-06 15:35:29 -08001031}
1032
1033void InstructionCodeGeneratorMIPS64::VisitVecStore(HVecStore* instruction) {
Goran Jakovljevic19680d32017-05-11 10:38:36 +02001034 LocationSummary* locations = instruction->GetLocations();
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001035 size_t size = DataType::Size(instruction->GetPackedType());
Goran Jakovljevic19680d32017-05-11 10:38:36 +02001036 VectorRegister reg = VectorRegisterFrom(locations->InAt(2));
1037 GpuRegister base;
1038 int32_t offset = VecAddress(locations, size, &base);
1039 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001040 case DataType::Type::kBool:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +01001041 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001042 case DataType::Type::kInt8:
Goran Jakovljevic19680d32017-05-11 10:38:36 +02001043 DCHECK_EQ(16u, instruction->GetVectorLength());
1044 __ StB(reg, base, offset);
1045 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001046 case DataType::Type::kUint16:
1047 case DataType::Type::kInt16:
Goran Jakovljevic19680d32017-05-11 10:38:36 +02001048 DCHECK_EQ(8u, instruction->GetVectorLength());
1049 __ StH(reg, base, offset);
1050 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001051 case DataType::Type::kInt32:
1052 case DataType::Type::kFloat32:
Goran Jakovljevic19680d32017-05-11 10:38:36 +02001053 DCHECK_EQ(4u, instruction->GetVectorLength());
1054 __ StW(reg, base, offset);
1055 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001056 case DataType::Type::kInt64:
1057 case DataType::Type::kFloat64:
Goran Jakovljevic19680d32017-05-11 10:38:36 +02001058 DCHECK_EQ(2u, instruction->GetVectorLength());
1059 __ StD(reg, base, offset);
1060 break;
1061 default:
1062 LOG(FATAL) << "Unsupported SIMD type";
1063 UNREACHABLE();
1064 }
Aart Bikf8f5a162017-02-06 15:35:29 -08001065}
1066
1067#undef __
1068
1069} // namespace mips64
1070} // namespace art