blob: 9ea55ec8d79d03379ed1d3a5e839fb8342f936bf [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) {
Vladimir Markoca6fff82017-10-03 14:49:14 +010032 LocationSummary* locations = new (GetGraph()->GetAllocator()) LocationSummary(instruction);
Goran Jakovljevic19680d32017-05-11 10:38:36 +020033 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) {
Lena Djokice434c4f2017-10-23 16:40:22 +020097 LocationSummary* locations = new (GetGraph()->GetAllocator()) LocationSummary(instruction);
98 switch (instruction->GetPackedType()) {
99 case DataType::Type::kBool:
100 case DataType::Type::kUint8:
101 case DataType::Type::kInt8:
102 case DataType::Type::kUint16:
103 case DataType::Type::kInt16:
104 case DataType::Type::kInt32:
105 case DataType::Type::kInt64:
106 locations->SetInAt(0, Location::RequiresFpuRegister());
107 locations->SetOut(Location::RequiresRegister());
108 break;
109 case DataType::Type::kFloat32:
110 case DataType::Type::kFloat64:
111 locations->SetInAt(0, Location::RequiresFpuRegister());
112 locations->SetOut(Location::SameAsFirstInput());
113 break;
114 default:
115 LOG(FATAL) << "Unsupported SIMD type";
116 UNREACHABLE();
117 }
Aart Bikf8f5a162017-02-06 15:35:29 -0800118}
119
Aart Bik0148de42017-09-05 09:25:01 -0700120void InstructionCodeGeneratorMIPS64::VisitVecExtractScalar(HVecExtractScalar* instruction) {
Lena Djokice434c4f2017-10-23 16:40:22 +0200121 LocationSummary* locations = instruction->GetLocations();
122 VectorRegister src = VectorRegisterFrom(locations->InAt(0));
123 switch (instruction->GetPackedType()) {
124 case DataType::Type::kInt32:
125 DCHECK_EQ(4u, instruction->GetVectorLength());
126 __ Copy_sW(locations->Out().AsRegister<GpuRegister>(), src, 0);
127 break;
128 case DataType::Type::kInt64:
129 DCHECK_EQ(2u, instruction->GetVectorLength());
130 __ Copy_sD(locations->Out().AsRegister<GpuRegister>(), src, 0);
131 break;
132 case DataType::Type::kFloat32:
133 case DataType::Type::kFloat64:
134 DCHECK_LE(2u, instruction->GetVectorLength());
135 DCHECK_LE(instruction->GetVectorLength(), 4u);
136 DCHECK(locations->InAt(0).Equals(locations->Out())); // no code required
137 break;
138 default:
139 LOG(FATAL) << "Unsupported SIMD type";
140 UNREACHABLE();
141 }
Aart Bikf8f5a162017-02-06 15:35:29 -0800142}
143
144// Helper to set up locations for vector unary operations.
Vladimir Markoe764d2e2017-10-05 14:35:55 +0100145static void CreateVecUnOpLocations(ArenaAllocator* allocator, HVecUnaryOperation* instruction) {
146 LocationSummary* locations = new (allocator) LocationSummary(instruction);
Lena Djokice434c4f2017-10-23 16:40:22 +0200147 DataType::Type type = instruction->GetPackedType();
148 switch (type) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100149 case DataType::Type::kBool:
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200150 locations->SetInAt(0, Location::RequiresFpuRegister());
151 locations->SetOut(Location::RequiresFpuRegister(),
152 instruction->IsVecNot() ? Location::kOutputOverlap
153 : Location::kNoOutputOverlap);
154 break;
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100155 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100156 case DataType::Type::kInt8:
157 case DataType::Type::kUint16:
158 case DataType::Type::kInt16:
159 case DataType::Type::kInt32:
160 case DataType::Type::kInt64:
161 case DataType::Type::kFloat32:
162 case DataType::Type::kFloat64:
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200163 locations->SetInAt(0, Location::RequiresFpuRegister());
164 locations->SetOut(Location::RequiresFpuRegister(),
Lena Djokice434c4f2017-10-23 16:40:22 +0200165 (instruction->IsVecNeg() || instruction->IsVecAbs() ||
166 (instruction->IsVecReduce() && type == DataType::Type::kInt64))
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200167 ? Location::kOutputOverlap
168 : Location::kNoOutputOverlap);
Aart Bikf8f5a162017-02-06 15:35:29 -0800169 break;
170 default:
171 LOG(FATAL) << "Unsupported SIMD type";
172 UNREACHABLE();
173 }
174}
175
Aart Bik0148de42017-09-05 09:25:01 -0700176void LocationsBuilderMIPS64::VisitVecReduce(HVecReduce* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100177 CreateVecUnOpLocations(GetGraph()->GetAllocator(), instruction);
Aart Bik0148de42017-09-05 09:25:01 -0700178}
179
180void InstructionCodeGeneratorMIPS64::VisitVecReduce(HVecReduce* instruction) {
Lena Djokice434c4f2017-10-23 16:40:22 +0200181 LocationSummary* locations = instruction->GetLocations();
182 VectorRegister src = VectorRegisterFrom(locations->InAt(0));
183 VectorRegister dst = VectorRegisterFrom(locations->Out());
184 VectorRegister tmp = static_cast<VectorRegister>(FTMP);
185 switch (instruction->GetPackedType()) {
186 case DataType::Type::kInt32:
187 DCHECK_EQ(4u, instruction->GetVectorLength());
188 switch (instruction->GetKind()) {
189 case HVecReduce::kSum:
190 __ Hadd_sD(tmp, src, src);
191 __ IlvlD(dst, tmp, tmp);
192 __ AddvW(dst, dst, tmp);
193 break;
194 case HVecReduce::kMin:
195 __ IlvodW(tmp, src, src);
196 __ Min_sW(tmp, src, tmp);
197 __ IlvlW(dst, tmp, tmp);
198 __ Min_sW(dst, dst, tmp);
199 break;
200 case HVecReduce::kMax:
201 __ IlvodW(tmp, src, src);
202 __ Max_sW(tmp, src, tmp);
203 __ IlvlW(dst, tmp, tmp);
204 __ Max_sW(dst, dst, tmp);
205 break;
206 }
207 break;
208 case DataType::Type::kInt64:
209 DCHECK_EQ(2u, instruction->GetVectorLength());
210 switch (instruction->GetKind()) {
211 case HVecReduce::kSum:
212 __ IlvlD(dst, src, src);
213 __ AddvD(dst, dst, src);
214 break;
215 case HVecReduce::kMin:
216 __ IlvlD(dst, src, src);
217 __ Min_sD(dst, dst, src);
218 break;
219 case HVecReduce::kMax:
220 __ IlvlD(dst, src, src);
221 __ Max_sD(dst, dst, src);
222 break;
223 }
224 break;
225 default:
226 LOG(FATAL) << "Unsupported SIMD type";
227 UNREACHABLE();
228 }
Aart Bik0148de42017-09-05 09:25:01 -0700229}
230
Aart Bikf8f5a162017-02-06 15:35:29 -0800231void LocationsBuilderMIPS64::VisitVecCnv(HVecCnv* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100232 CreateVecUnOpLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikf8f5a162017-02-06 15:35:29 -0800233}
234
235void InstructionCodeGeneratorMIPS64::VisitVecCnv(HVecCnv* instruction) {
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200236 LocationSummary* locations = instruction->GetLocations();
237 VectorRegister src = VectorRegisterFrom(locations->InAt(0));
238 VectorRegister dst = VectorRegisterFrom(locations->Out());
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100239 DataType::Type from = instruction->GetInputType();
240 DataType::Type to = instruction->GetResultType();
241 if (from == DataType::Type::kInt32 && to == DataType::Type::kFloat32) {
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200242 DCHECK_EQ(4u, instruction->GetVectorLength());
243 __ Ffint_sW(dst, src);
244 } else {
245 LOG(FATAL) << "Unsupported SIMD type";
246 UNREACHABLE();
247 }
Aart Bikf8f5a162017-02-06 15:35:29 -0800248}
249
250void LocationsBuilderMIPS64::VisitVecNeg(HVecNeg* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100251 CreateVecUnOpLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikf8f5a162017-02-06 15:35:29 -0800252}
253
254void InstructionCodeGeneratorMIPS64::VisitVecNeg(HVecNeg* instruction) {
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200255 LocationSummary* locations = instruction->GetLocations();
256 VectorRegister src = VectorRegisterFrom(locations->InAt(0));
257 VectorRegister dst = VectorRegisterFrom(locations->Out());
258 switch (instruction->GetPackedType()) {
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100259 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100260 case DataType::Type::kInt8:
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200261 DCHECK_EQ(16u, instruction->GetVectorLength());
262 __ FillB(dst, ZERO);
263 __ SubvB(dst, dst, src);
264 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100265 case DataType::Type::kUint16:
266 case DataType::Type::kInt16:
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200267 DCHECK_EQ(8u, instruction->GetVectorLength());
268 __ FillH(dst, ZERO);
269 __ SubvH(dst, dst, src);
270 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100271 case DataType::Type::kInt32:
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200272 DCHECK_EQ(4u, instruction->GetVectorLength());
273 __ FillW(dst, ZERO);
274 __ SubvW(dst, dst, src);
275 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100276 case DataType::Type::kInt64:
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200277 DCHECK_EQ(2u, instruction->GetVectorLength());
278 __ FillD(dst, ZERO);
279 __ SubvD(dst, dst, src);
280 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100281 case DataType::Type::kFloat32:
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200282 DCHECK_EQ(4u, instruction->GetVectorLength());
283 __ FillW(dst, ZERO);
284 __ FsubW(dst, dst, src);
285 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100286 case DataType::Type::kFloat64:
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200287 DCHECK_EQ(2u, instruction->GetVectorLength());
288 __ FillD(dst, ZERO);
289 __ FsubD(dst, dst, src);
290 break;
291 default:
292 LOG(FATAL) << "Unsupported SIMD type";
293 UNREACHABLE();
294 }
Aart Bikf8f5a162017-02-06 15:35:29 -0800295}
296
Aart Bik6daebeb2017-04-03 14:35:41 -0700297void LocationsBuilderMIPS64::VisitVecAbs(HVecAbs* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100298 CreateVecUnOpLocations(GetGraph()->GetAllocator(), instruction);
Aart Bik6daebeb2017-04-03 14:35:41 -0700299}
300
301void InstructionCodeGeneratorMIPS64::VisitVecAbs(HVecAbs* instruction) {
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200302 LocationSummary* locations = instruction->GetLocations();
303 VectorRegister src = VectorRegisterFrom(locations->InAt(0));
304 VectorRegister dst = VectorRegisterFrom(locations->Out());
305 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100306 case DataType::Type::kInt8:
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200307 DCHECK_EQ(16u, instruction->GetVectorLength());
308 __ FillB(dst, ZERO); // all zeroes
309 __ Add_aB(dst, dst, src); // dst = abs(0) + abs(src)
310 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100311 case DataType::Type::kInt16:
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200312 DCHECK_EQ(8u, instruction->GetVectorLength());
313 __ FillH(dst, ZERO); // all zeroes
314 __ Add_aH(dst, dst, src); // dst = abs(0) + abs(src)
315 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100316 case DataType::Type::kInt32:
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200317 DCHECK_EQ(4u, instruction->GetVectorLength());
318 __ FillW(dst, ZERO); // all zeroes
319 __ Add_aW(dst, dst, src); // dst = abs(0) + abs(src)
320 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100321 case DataType::Type::kInt64:
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200322 DCHECK_EQ(2u, instruction->GetVectorLength());
323 __ FillD(dst, ZERO); // all zeroes
324 __ Add_aD(dst, dst, src); // dst = abs(0) + abs(src)
325 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100326 case DataType::Type::kFloat32:
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200327 DCHECK_EQ(4u, instruction->GetVectorLength());
328 __ LdiW(dst, -1); // all ones
329 __ SrliW(dst, dst, 1);
330 __ AndV(dst, dst, src);
331 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100332 case DataType::Type::kFloat64:
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200333 DCHECK_EQ(2u, instruction->GetVectorLength());
334 __ LdiD(dst, -1); // all ones
335 __ SrliD(dst, dst, 1);
336 __ AndV(dst, dst, src);
337 break;
338 default:
339 LOG(FATAL) << "Unsupported SIMD type";
340 UNREACHABLE();
341 }
Aart Bik6daebeb2017-04-03 14:35:41 -0700342}
343
Aart Bikf8f5a162017-02-06 15:35:29 -0800344void LocationsBuilderMIPS64::VisitVecNot(HVecNot* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100345 CreateVecUnOpLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikf8f5a162017-02-06 15:35:29 -0800346}
347
348void InstructionCodeGeneratorMIPS64::VisitVecNot(HVecNot* instruction) {
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200349 LocationSummary* locations = instruction->GetLocations();
350 VectorRegister src = VectorRegisterFrom(locations->InAt(0));
351 VectorRegister dst = VectorRegisterFrom(locations->Out());
352 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100353 case DataType::Type::kBool: // special case boolean-not
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200354 DCHECK_EQ(16u, instruction->GetVectorLength());
355 __ LdiB(dst, 1);
356 __ XorV(dst, dst, src);
357 break;
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100358 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100359 case DataType::Type::kInt8:
360 case DataType::Type::kUint16:
361 case DataType::Type::kInt16:
362 case DataType::Type::kInt32:
363 case DataType::Type::kInt64:
364 case DataType::Type::kFloat32:
365 case DataType::Type::kFloat64:
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200366 DCHECK_LE(2u, instruction->GetVectorLength());
367 DCHECK_LE(instruction->GetVectorLength(), 16u);
368 __ NorV(dst, src, src); // lanes do not matter
369 break;
370 default:
371 LOG(FATAL) << "Unsupported SIMD type";
372 UNREACHABLE();
373 }
Aart Bikf8f5a162017-02-06 15:35:29 -0800374}
375
376// Helper to set up locations for vector binary operations.
Vladimir Markoe764d2e2017-10-05 14:35:55 +0100377static void CreateVecBinOpLocations(ArenaAllocator* allocator, HVecBinaryOperation* instruction) {
378 LocationSummary* locations = new (allocator) LocationSummary(instruction);
Aart Bikf8f5a162017-02-06 15:35:29 -0800379 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100380 case DataType::Type::kBool:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100381 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100382 case DataType::Type::kInt8:
383 case DataType::Type::kUint16:
384 case DataType::Type::kInt16:
385 case DataType::Type::kInt32:
386 case DataType::Type::kInt64:
387 case DataType::Type::kFloat32:
388 case DataType::Type::kFloat64:
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200389 locations->SetInAt(0, Location::RequiresFpuRegister());
390 locations->SetInAt(1, Location::RequiresFpuRegister());
391 locations->SetOut(Location::RequiresFpuRegister(), Location::kNoOutputOverlap);
Aart Bikf8f5a162017-02-06 15:35:29 -0800392 break;
393 default:
394 LOG(FATAL) << "Unsupported SIMD type";
395 UNREACHABLE();
396 }
397}
398
399void LocationsBuilderMIPS64::VisitVecAdd(HVecAdd* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100400 CreateVecBinOpLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikf8f5a162017-02-06 15:35:29 -0800401}
402
403void InstructionCodeGeneratorMIPS64::VisitVecAdd(HVecAdd* instruction) {
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200404 LocationSummary* locations = instruction->GetLocations();
405 VectorRegister lhs = VectorRegisterFrom(locations->InAt(0));
406 VectorRegister rhs = VectorRegisterFrom(locations->InAt(1));
407 VectorRegister dst = VectorRegisterFrom(locations->Out());
408 switch (instruction->GetPackedType()) {
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100409 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100410 case DataType::Type::kInt8:
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200411 DCHECK_EQ(16u, instruction->GetVectorLength());
412 __ AddvB(dst, lhs, rhs);
413 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100414 case DataType::Type::kUint16:
415 case DataType::Type::kInt16:
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200416 DCHECK_EQ(8u, instruction->GetVectorLength());
417 __ AddvH(dst, lhs, rhs);
418 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100419 case DataType::Type::kInt32:
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200420 DCHECK_EQ(4u, instruction->GetVectorLength());
421 __ AddvW(dst, lhs, rhs);
422 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100423 case DataType::Type::kInt64:
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200424 DCHECK_EQ(2u, instruction->GetVectorLength());
425 __ AddvD(dst, lhs, rhs);
426 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100427 case DataType::Type::kFloat32:
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200428 DCHECK_EQ(4u, instruction->GetVectorLength());
429 __ FaddW(dst, lhs, rhs);
430 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100431 case DataType::Type::kFloat64:
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200432 DCHECK_EQ(2u, instruction->GetVectorLength());
433 __ FaddD(dst, lhs, rhs);
434 break;
435 default:
436 LOG(FATAL) << "Unsupported SIMD type";
437 UNREACHABLE();
438 }
Aart Bikf8f5a162017-02-06 15:35:29 -0800439}
440
Aart Bikf3e61ee2017-04-12 17:09:20 -0700441void LocationsBuilderMIPS64::VisitVecHalvingAdd(HVecHalvingAdd* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100442 CreateVecBinOpLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikf3e61ee2017-04-12 17:09:20 -0700443}
444
445void InstructionCodeGeneratorMIPS64::VisitVecHalvingAdd(HVecHalvingAdd* instruction) {
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200446 LocationSummary* locations = instruction->GetLocations();
447 VectorRegister lhs = VectorRegisterFrom(locations->InAt(0));
448 VectorRegister rhs = VectorRegisterFrom(locations->InAt(1));
449 VectorRegister dst = VectorRegisterFrom(locations->Out());
450 switch (instruction->GetPackedType()) {
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100451 case DataType::Type::kUint8:
452 DCHECK_EQ(16u, instruction->GetVectorLength());
453 instruction->IsRounded()
454 ? __ Aver_uB(dst, lhs, rhs)
455 : __ Ave_uB(dst, lhs, rhs);
456 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100457 case DataType::Type::kInt8:
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200458 DCHECK_EQ(16u, instruction->GetVectorLength());
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100459 instruction->IsRounded()
460 ? __ Aver_sB(dst, lhs, rhs)
461 : __ Ave_sB(dst, lhs, rhs);
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200462 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100463 case DataType::Type::kUint16:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100464 DCHECK_EQ(8u, instruction->GetVectorLength());
465 instruction->IsRounded()
466 ? __ Aver_uH(dst, lhs, rhs)
467 : __ Ave_uH(dst, lhs, rhs);
468 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100469 case DataType::Type::kInt16:
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200470 DCHECK_EQ(8u, instruction->GetVectorLength());
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100471 instruction->IsRounded()
472 ? __ Aver_sH(dst, lhs, rhs)
473 : __ Ave_sH(dst, lhs, rhs);
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200474 break;
475 default:
476 LOG(FATAL) << "Unsupported SIMD type";
477 UNREACHABLE();
478 }
Aart Bikf3e61ee2017-04-12 17:09:20 -0700479}
480
Aart Bikf8f5a162017-02-06 15:35:29 -0800481void LocationsBuilderMIPS64::VisitVecSub(HVecSub* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100482 CreateVecBinOpLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikf8f5a162017-02-06 15:35:29 -0800483}
484
485void InstructionCodeGeneratorMIPS64::VisitVecSub(HVecSub* instruction) {
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200486 LocationSummary* locations = instruction->GetLocations();
487 VectorRegister lhs = VectorRegisterFrom(locations->InAt(0));
488 VectorRegister rhs = VectorRegisterFrom(locations->InAt(1));
489 VectorRegister dst = VectorRegisterFrom(locations->Out());
490 switch (instruction->GetPackedType()) {
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100491 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100492 case DataType::Type::kInt8:
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200493 DCHECK_EQ(16u, instruction->GetVectorLength());
494 __ SubvB(dst, lhs, rhs);
495 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100496 case DataType::Type::kUint16:
497 case DataType::Type::kInt16:
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200498 DCHECK_EQ(8u, instruction->GetVectorLength());
499 __ SubvH(dst, lhs, rhs);
500 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100501 case DataType::Type::kInt32:
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200502 DCHECK_EQ(4u, instruction->GetVectorLength());
503 __ SubvW(dst, lhs, rhs);
504 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100505 case DataType::Type::kInt64:
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200506 DCHECK_EQ(2u, instruction->GetVectorLength());
507 __ SubvD(dst, lhs, rhs);
508 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100509 case DataType::Type::kFloat32:
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200510 DCHECK_EQ(4u, instruction->GetVectorLength());
511 __ FsubW(dst, lhs, rhs);
512 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100513 case DataType::Type::kFloat64:
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200514 DCHECK_EQ(2u, instruction->GetVectorLength());
515 __ FsubD(dst, lhs, rhs);
516 break;
517 default:
518 LOG(FATAL) << "Unsupported SIMD type";
519 UNREACHABLE();
520 }
Aart Bikf8f5a162017-02-06 15:35:29 -0800521}
522
523void LocationsBuilderMIPS64::VisitVecMul(HVecMul* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100524 CreateVecBinOpLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikf8f5a162017-02-06 15:35:29 -0800525}
526
527void InstructionCodeGeneratorMIPS64::VisitVecMul(HVecMul* instruction) {
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200528 LocationSummary* locations = instruction->GetLocations();
529 VectorRegister lhs = VectorRegisterFrom(locations->InAt(0));
530 VectorRegister rhs = VectorRegisterFrom(locations->InAt(1));
531 VectorRegister dst = VectorRegisterFrom(locations->Out());
532 switch (instruction->GetPackedType()) {
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100533 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100534 case DataType::Type::kInt8:
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200535 DCHECK_EQ(16u, instruction->GetVectorLength());
536 __ MulvB(dst, lhs, rhs);
537 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100538 case DataType::Type::kUint16:
539 case DataType::Type::kInt16:
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200540 DCHECK_EQ(8u, instruction->GetVectorLength());
541 __ MulvH(dst, lhs, rhs);
542 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100543 case DataType::Type::kInt32:
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200544 DCHECK_EQ(4u, instruction->GetVectorLength());
545 __ MulvW(dst, lhs, rhs);
546 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100547 case DataType::Type::kInt64:
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200548 DCHECK_EQ(2u, instruction->GetVectorLength());
549 __ MulvD(dst, lhs, rhs);
550 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100551 case DataType::Type::kFloat32:
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200552 DCHECK_EQ(4u, instruction->GetVectorLength());
553 __ FmulW(dst, lhs, rhs);
554 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100555 case DataType::Type::kFloat64:
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200556 DCHECK_EQ(2u, instruction->GetVectorLength());
557 __ FmulD(dst, lhs, rhs);
558 break;
559 default:
560 LOG(FATAL) << "Unsupported SIMD type";
561 UNREACHABLE();
562 }
Aart Bikf8f5a162017-02-06 15:35:29 -0800563}
564
565void LocationsBuilderMIPS64::VisitVecDiv(HVecDiv* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100566 CreateVecBinOpLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikf8f5a162017-02-06 15:35:29 -0800567}
568
569void InstructionCodeGeneratorMIPS64::VisitVecDiv(HVecDiv* instruction) {
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200570 LocationSummary* locations = instruction->GetLocations();
571 VectorRegister lhs = VectorRegisterFrom(locations->InAt(0));
572 VectorRegister rhs = VectorRegisterFrom(locations->InAt(1));
573 VectorRegister dst = VectorRegisterFrom(locations->Out());
574 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100575 case DataType::Type::kFloat32:
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200576 DCHECK_EQ(4u, instruction->GetVectorLength());
577 __ FdivW(dst, lhs, rhs);
578 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100579 case DataType::Type::kFloat64:
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200580 DCHECK_EQ(2u, instruction->GetVectorLength());
581 __ FdivD(dst, lhs, rhs);
582 break;
583 default:
584 LOG(FATAL) << "Unsupported SIMD type";
585 UNREACHABLE();
586 }
Aart Bikf8f5a162017-02-06 15:35:29 -0800587}
588
Aart Bikf3e61ee2017-04-12 17:09:20 -0700589void LocationsBuilderMIPS64::VisitVecMin(HVecMin* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100590 CreateVecBinOpLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikf3e61ee2017-04-12 17:09:20 -0700591}
592
593void InstructionCodeGeneratorMIPS64::VisitVecMin(HVecMin* instruction) {
Goran Jakovljevic8fea1e12017-06-06 13:28:42 +0200594 LocationSummary* locations = instruction->GetLocations();
595 VectorRegister lhs = VectorRegisterFrom(locations->InAt(0));
596 VectorRegister rhs = VectorRegisterFrom(locations->InAt(1));
597 VectorRegister dst = VectorRegisterFrom(locations->Out());
598 switch (instruction->GetPackedType()) {
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100599 case DataType::Type::kUint8:
600 DCHECK_EQ(16u, instruction->GetVectorLength());
601 __ Min_uB(dst, lhs, rhs);
602 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100603 case DataType::Type::kInt8:
Goran Jakovljevic8fea1e12017-06-06 13:28:42 +0200604 DCHECK_EQ(16u, instruction->GetVectorLength());
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100605 __ Min_sB(dst, lhs, rhs);
Goran Jakovljevic8fea1e12017-06-06 13:28:42 +0200606 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100607 case DataType::Type::kUint16:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100608 DCHECK_EQ(8u, instruction->GetVectorLength());
609 __ Min_uH(dst, lhs, rhs);
610 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100611 case DataType::Type::kInt16:
Goran Jakovljevic8fea1e12017-06-06 13:28:42 +0200612 DCHECK_EQ(8u, instruction->GetVectorLength());
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100613 __ Min_sH(dst, lhs, rhs);
Goran Jakovljevic8fea1e12017-06-06 13:28:42 +0200614 break;
Aart Bik66c158e2018-01-31 12:55:04 -0800615 case DataType::Type::kUint32:
616 DCHECK_EQ(4u, instruction->GetVectorLength());
617 __ Min_uW(dst, lhs, rhs);
618 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100619 case DataType::Type::kInt32:
Goran Jakovljevic8fea1e12017-06-06 13:28:42 +0200620 DCHECK_EQ(4u, instruction->GetVectorLength());
Aart Bik66c158e2018-01-31 12:55:04 -0800621 __ Min_sW(dst, lhs, rhs);
622 break;
623 case DataType::Type::kUint64:
624 DCHECK_EQ(2u, instruction->GetVectorLength());
625 __ Min_uD(dst, lhs, rhs);
Goran Jakovljevic8fea1e12017-06-06 13:28:42 +0200626 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100627 case DataType::Type::kInt64:
Goran Jakovljevic8fea1e12017-06-06 13:28:42 +0200628 DCHECK_EQ(2u, instruction->GetVectorLength());
Aart Bik66c158e2018-01-31 12:55:04 -0800629 __ Min_sD(dst, lhs, rhs);
Goran Jakovljevic8fea1e12017-06-06 13:28:42 +0200630 break;
631 // When one of arguments is NaN, fmin.df returns other argument, but Java expects a NaN value.
632 // TODO: Fix min(x, NaN) cases for float and double.
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100633 case DataType::Type::kFloat32:
Goran Jakovljevic8fea1e12017-06-06 13:28:42 +0200634 DCHECK_EQ(4u, instruction->GetVectorLength());
Goran Jakovljevic8fea1e12017-06-06 13:28:42 +0200635 __ FminW(dst, lhs, rhs);
636 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100637 case DataType::Type::kFloat64:
Goran Jakovljevic8fea1e12017-06-06 13:28:42 +0200638 DCHECK_EQ(2u, instruction->GetVectorLength());
Goran Jakovljevic8fea1e12017-06-06 13:28:42 +0200639 __ FminD(dst, lhs, rhs);
640 break;
641 default:
642 LOG(FATAL) << "Unsupported SIMD type";
643 UNREACHABLE();
644 }
Aart Bikf3e61ee2017-04-12 17:09:20 -0700645}
646
647void LocationsBuilderMIPS64::VisitVecMax(HVecMax* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100648 CreateVecBinOpLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikf3e61ee2017-04-12 17:09:20 -0700649}
650
651void InstructionCodeGeneratorMIPS64::VisitVecMax(HVecMax* instruction) {
Goran Jakovljevic8fea1e12017-06-06 13:28:42 +0200652 LocationSummary* locations = instruction->GetLocations();
653 VectorRegister lhs = VectorRegisterFrom(locations->InAt(0));
654 VectorRegister rhs = VectorRegisterFrom(locations->InAt(1));
655 VectorRegister dst = VectorRegisterFrom(locations->Out());
656 switch (instruction->GetPackedType()) {
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100657 case DataType::Type::kUint8:
658 DCHECK_EQ(16u, instruction->GetVectorLength());
659 __ Max_uB(dst, lhs, rhs);
660 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100661 case DataType::Type::kInt8:
Goran Jakovljevic8fea1e12017-06-06 13:28:42 +0200662 DCHECK_EQ(16u, instruction->GetVectorLength());
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100663 __ Max_sB(dst, lhs, rhs);
Goran Jakovljevic8fea1e12017-06-06 13:28:42 +0200664 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100665 case DataType::Type::kUint16:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100666 DCHECK_EQ(8u, instruction->GetVectorLength());
667 __ Max_uH(dst, lhs, rhs);
668 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100669 case DataType::Type::kInt16:
Goran Jakovljevic8fea1e12017-06-06 13:28:42 +0200670 DCHECK_EQ(8u, instruction->GetVectorLength());
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100671 __ Max_sH(dst, lhs, rhs);
Goran Jakovljevic8fea1e12017-06-06 13:28:42 +0200672 break;
Aart Bik66c158e2018-01-31 12:55:04 -0800673 case DataType::Type::kUint32:
674 DCHECK_EQ(4u, instruction->GetVectorLength());
675 __ Max_uW(dst, lhs, rhs);
676 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100677 case DataType::Type::kInt32:
Goran Jakovljevic8fea1e12017-06-06 13:28:42 +0200678 DCHECK_EQ(4u, instruction->GetVectorLength());
Aart Bik66c158e2018-01-31 12:55:04 -0800679 __ Max_sW(dst, lhs, rhs);
680 break;
681 case DataType::Type::kUint64:
682 DCHECK_EQ(2u, instruction->GetVectorLength());
683 __ Max_uD(dst, lhs, rhs);
Goran Jakovljevic8fea1e12017-06-06 13:28:42 +0200684 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100685 case DataType::Type::kInt64:
Goran Jakovljevic8fea1e12017-06-06 13:28:42 +0200686 DCHECK_EQ(2u, instruction->GetVectorLength());
Aart Bik66c158e2018-01-31 12:55:04 -0800687 __ Max_sD(dst, lhs, rhs);
Goran Jakovljevic8fea1e12017-06-06 13:28:42 +0200688 break;
689 // When one of arguments is NaN, fmax.df returns other argument, but Java expects a NaN value.
690 // TODO: Fix max(x, NaN) cases for float and double.
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100691 case DataType::Type::kFloat32:
Goran Jakovljevic8fea1e12017-06-06 13:28:42 +0200692 DCHECK_EQ(4u, instruction->GetVectorLength());
Goran Jakovljevic8fea1e12017-06-06 13:28:42 +0200693 __ FmaxW(dst, lhs, rhs);
694 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100695 case DataType::Type::kFloat64:
Goran Jakovljevic8fea1e12017-06-06 13:28:42 +0200696 DCHECK_EQ(2u, instruction->GetVectorLength());
Goran Jakovljevic8fea1e12017-06-06 13:28:42 +0200697 __ FmaxD(dst, lhs, rhs);
698 break;
699 default:
700 LOG(FATAL) << "Unsupported SIMD type";
701 UNREACHABLE();
702 }
Aart Bikf3e61ee2017-04-12 17:09:20 -0700703}
704
Aart Bikf8f5a162017-02-06 15:35:29 -0800705void LocationsBuilderMIPS64::VisitVecAnd(HVecAnd* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100706 CreateVecBinOpLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikf8f5a162017-02-06 15:35:29 -0800707}
708
709void InstructionCodeGeneratorMIPS64::VisitVecAnd(HVecAnd* instruction) {
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200710 LocationSummary* locations = instruction->GetLocations();
711 VectorRegister lhs = VectorRegisterFrom(locations->InAt(0));
712 VectorRegister rhs = VectorRegisterFrom(locations->InAt(1));
713 VectorRegister dst = VectorRegisterFrom(locations->Out());
714 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100715 case DataType::Type::kBool:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100716 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100717 case DataType::Type::kInt8:
718 case DataType::Type::kUint16:
719 case DataType::Type::kInt16:
720 case DataType::Type::kInt32:
721 case DataType::Type::kInt64:
722 case DataType::Type::kFloat32:
723 case DataType::Type::kFloat64:
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200724 DCHECK_LE(2u, instruction->GetVectorLength());
725 DCHECK_LE(instruction->GetVectorLength(), 16u);
726 __ AndV(dst, lhs, rhs); // lanes do not matter
727 break;
728 default:
729 LOG(FATAL) << "Unsupported SIMD type";
730 UNREACHABLE();
731 }
Aart Bikf8f5a162017-02-06 15:35:29 -0800732}
733
734void LocationsBuilderMIPS64::VisitVecAndNot(HVecAndNot* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100735 CreateVecBinOpLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikf8f5a162017-02-06 15:35:29 -0800736}
737
738void InstructionCodeGeneratorMIPS64::VisitVecAndNot(HVecAndNot* instruction) {
739 LOG(FATAL) << "No SIMD for " << instruction->GetId();
740}
741
742void LocationsBuilderMIPS64::VisitVecOr(HVecOr* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100743 CreateVecBinOpLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikf8f5a162017-02-06 15:35:29 -0800744}
745
746void InstructionCodeGeneratorMIPS64::VisitVecOr(HVecOr* instruction) {
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200747 LocationSummary* locations = instruction->GetLocations();
748 VectorRegister lhs = VectorRegisterFrom(locations->InAt(0));
749 VectorRegister rhs = VectorRegisterFrom(locations->InAt(1));
750 VectorRegister dst = VectorRegisterFrom(locations->Out());
751 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100752 case DataType::Type::kBool:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100753 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100754 case DataType::Type::kInt8:
755 case DataType::Type::kUint16:
756 case DataType::Type::kInt16:
757 case DataType::Type::kInt32:
758 case DataType::Type::kInt64:
759 case DataType::Type::kFloat32:
760 case DataType::Type::kFloat64:
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200761 DCHECK_LE(2u, instruction->GetVectorLength());
762 DCHECK_LE(instruction->GetVectorLength(), 16u);
763 __ OrV(dst, lhs, rhs); // lanes do not matter
764 break;
765 default:
766 LOG(FATAL) << "Unsupported SIMD type";
767 UNREACHABLE();
768 }
Aart Bikf8f5a162017-02-06 15:35:29 -0800769}
770
771void LocationsBuilderMIPS64::VisitVecXor(HVecXor* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100772 CreateVecBinOpLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikf8f5a162017-02-06 15:35:29 -0800773}
774
775void InstructionCodeGeneratorMIPS64::VisitVecXor(HVecXor* instruction) {
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200776 LocationSummary* locations = instruction->GetLocations();
777 VectorRegister lhs = VectorRegisterFrom(locations->InAt(0));
778 VectorRegister rhs = VectorRegisterFrom(locations->InAt(1));
779 VectorRegister dst = VectorRegisterFrom(locations->Out());
780 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100781 case DataType::Type::kBool:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100782 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100783 case DataType::Type::kInt8:
784 case DataType::Type::kUint16:
785 case DataType::Type::kInt16:
786 case DataType::Type::kInt32:
787 case DataType::Type::kInt64:
788 case DataType::Type::kFloat32:
789 case DataType::Type::kFloat64:
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200790 DCHECK_LE(2u, instruction->GetVectorLength());
791 DCHECK_LE(instruction->GetVectorLength(), 16u);
792 __ XorV(dst, lhs, rhs); // lanes do not matter
793 break;
794 default:
795 LOG(FATAL) << "Unsupported SIMD type";
796 UNREACHABLE();
797 }
Aart Bikf8f5a162017-02-06 15:35:29 -0800798}
799
800// Helper to set up locations for vector shift operations.
Vladimir Markoe764d2e2017-10-05 14:35:55 +0100801static void CreateVecShiftLocations(ArenaAllocator* allocator, HVecBinaryOperation* instruction) {
802 LocationSummary* locations = new (allocator) LocationSummary(instruction);
Aart Bikf8f5a162017-02-06 15:35:29 -0800803 switch (instruction->GetPackedType()) {
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100804 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100805 case DataType::Type::kInt8:
806 case DataType::Type::kUint16:
807 case DataType::Type::kInt16:
808 case DataType::Type::kInt32:
809 case DataType::Type::kInt64:
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200810 locations->SetInAt(0, Location::RequiresFpuRegister());
811 locations->SetInAt(1, Location::ConstantLocation(instruction->InputAt(1)->AsConstant()));
812 locations->SetOut(Location::RequiresFpuRegister(), Location::kNoOutputOverlap);
Aart Bikf8f5a162017-02-06 15:35:29 -0800813 break;
814 default:
815 LOG(FATAL) << "Unsupported SIMD type";
816 UNREACHABLE();
817 }
818}
819
820void LocationsBuilderMIPS64::VisitVecShl(HVecShl* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100821 CreateVecShiftLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikf8f5a162017-02-06 15:35:29 -0800822}
823
824void InstructionCodeGeneratorMIPS64::VisitVecShl(HVecShl* instruction) {
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200825 LocationSummary* locations = instruction->GetLocations();
826 VectorRegister lhs = VectorRegisterFrom(locations->InAt(0));
827 VectorRegister dst = VectorRegisterFrom(locations->Out());
828 int32_t value = locations->InAt(1).GetConstant()->AsIntConstant()->GetValue();
829 switch (instruction->GetPackedType()) {
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100830 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100831 case DataType::Type::kInt8:
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200832 DCHECK_EQ(16u, instruction->GetVectorLength());
833 __ SlliB(dst, lhs, value);
834 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100835 case DataType::Type::kUint16:
836 case DataType::Type::kInt16:
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200837 DCHECK_EQ(8u, instruction->GetVectorLength());
838 __ SlliH(dst, lhs, value);
839 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100840 case DataType::Type::kInt32:
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200841 DCHECK_EQ(4u, instruction->GetVectorLength());
842 __ SlliW(dst, lhs, value);
843 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100844 case DataType::Type::kInt64:
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200845 DCHECK_EQ(2u, instruction->GetVectorLength());
846 __ SlliD(dst, lhs, value);
847 break;
848 default:
849 LOG(FATAL) << "Unsupported SIMD type";
850 UNREACHABLE();
851 }
Aart Bikf8f5a162017-02-06 15:35:29 -0800852}
853
854void LocationsBuilderMIPS64::VisitVecShr(HVecShr* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100855 CreateVecShiftLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikf8f5a162017-02-06 15:35:29 -0800856}
857
858void InstructionCodeGeneratorMIPS64::VisitVecShr(HVecShr* instruction) {
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200859 LocationSummary* locations = instruction->GetLocations();
860 VectorRegister lhs = VectorRegisterFrom(locations->InAt(0));
861 VectorRegister dst = VectorRegisterFrom(locations->Out());
862 int32_t value = locations->InAt(1).GetConstant()->AsIntConstant()->GetValue();
863 switch (instruction->GetPackedType()) {
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100864 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100865 case DataType::Type::kInt8:
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200866 DCHECK_EQ(16u, instruction->GetVectorLength());
867 __ SraiB(dst, lhs, value);
868 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100869 case DataType::Type::kUint16:
870 case DataType::Type::kInt16:
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200871 DCHECK_EQ(8u, instruction->GetVectorLength());
872 __ SraiH(dst, lhs, value);
873 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100874 case DataType::Type::kInt32:
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200875 DCHECK_EQ(4u, instruction->GetVectorLength());
876 __ SraiW(dst, lhs, value);
877 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100878 case DataType::Type::kInt64:
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200879 DCHECK_EQ(2u, instruction->GetVectorLength());
880 __ SraiD(dst, lhs, value);
881 break;
882 default:
883 LOG(FATAL) << "Unsupported SIMD type";
884 UNREACHABLE();
885 }
Aart Bikf8f5a162017-02-06 15:35:29 -0800886}
887
888void LocationsBuilderMIPS64::VisitVecUShr(HVecUShr* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100889 CreateVecShiftLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikf8f5a162017-02-06 15:35:29 -0800890}
891
892void InstructionCodeGeneratorMIPS64::VisitVecUShr(HVecUShr* instruction) {
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200893 LocationSummary* locations = instruction->GetLocations();
894 VectorRegister lhs = VectorRegisterFrom(locations->InAt(0));
895 VectorRegister dst = VectorRegisterFrom(locations->Out());
896 int32_t value = locations->InAt(1).GetConstant()->AsIntConstant()->GetValue();
897 switch (instruction->GetPackedType()) {
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100898 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100899 case DataType::Type::kInt8:
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200900 DCHECK_EQ(16u, instruction->GetVectorLength());
901 __ SrliB(dst, lhs, value);
902 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100903 case DataType::Type::kUint16:
904 case DataType::Type::kInt16:
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200905 DCHECK_EQ(8u, instruction->GetVectorLength());
906 __ SrliH(dst, lhs, value);
907 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100908 case DataType::Type::kInt32:
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200909 DCHECK_EQ(4u, instruction->GetVectorLength());
910 __ SrliW(dst, lhs, value);
911 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100912 case DataType::Type::kInt64:
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200913 DCHECK_EQ(2u, instruction->GetVectorLength());
914 __ SrliD(dst, lhs, value);
915 break;
916 default:
917 LOG(FATAL) << "Unsupported SIMD type";
918 UNREACHABLE();
919 }
Aart Bikf8f5a162017-02-06 15:35:29 -0800920}
921
Aart Bik0148de42017-09-05 09:25:01 -0700922void LocationsBuilderMIPS64::VisitVecSetScalars(HVecSetScalars* instruction) {
Lena Djokice434c4f2017-10-23 16:40:22 +0200923 LocationSummary* locations = new (GetGraph()->GetAllocator()) LocationSummary(instruction);
924
925 DCHECK_EQ(1u, instruction->InputCount()); // only one input currently implemented
926
927 HInstruction* input = instruction->InputAt(0);
928 bool is_zero = IsZeroBitPattern(input);
929
930 switch (instruction->GetPackedType()) {
931 case DataType::Type::kBool:
932 case DataType::Type::kUint8:
933 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 locations->SetInAt(0, is_zero ? Location::ConstantLocation(input->AsConstant())
939 : Location::RequiresRegister());
940 locations->SetOut(Location::RequiresFpuRegister());
941 break;
942 case DataType::Type::kFloat32:
943 case DataType::Type::kFloat64:
944 locations->SetInAt(0, is_zero ? Location::ConstantLocation(input->AsConstant())
945 : Location::RequiresFpuRegister());
946 locations->SetOut(Location::RequiresFpuRegister());
947 break;
948 default:
949 LOG(FATAL) << "Unsupported SIMD type";
950 UNREACHABLE();
951 }
Aart Bik0148de42017-09-05 09:25:01 -0700952}
953
954void InstructionCodeGeneratorMIPS64::VisitVecSetScalars(HVecSetScalars* instruction) {
Lena Djokice434c4f2017-10-23 16:40:22 +0200955 LocationSummary* locations = instruction->GetLocations();
956 VectorRegister dst = VectorRegisterFrom(locations->Out());
957
958 DCHECK_EQ(1u, instruction->InputCount()); // only one input currently implemented
959
960 // Zero out all other elements first.
961 __ FillW(dst, ZERO);
962
963 // Shorthand for any type of zero.
964 if (IsZeroBitPattern(instruction->InputAt(0))) {
965 return;
966 }
967
968 // Set required elements.
969 switch (instruction->GetPackedType()) {
970 case DataType::Type::kBool:
971 case DataType::Type::kUint8:
972 case DataType::Type::kInt8:
973 DCHECK_EQ(16u, instruction->GetVectorLength());
974 __ InsertB(dst, locations->InAt(0).AsRegister<GpuRegister>(), 0);
975 break;
976 case DataType::Type::kUint16:
977 case DataType::Type::kInt16:
978 DCHECK_EQ(8u, instruction->GetVectorLength());
979 __ InsertH(dst, locations->InAt(0).AsRegister<GpuRegister>(), 0);
980 break;
981 case DataType::Type::kInt32:
982 DCHECK_EQ(4u, instruction->GetVectorLength());
983 __ InsertW(dst, locations->InAt(0).AsRegister<GpuRegister>(), 0);
984 break;
985 case DataType::Type::kInt64:
986 DCHECK_EQ(2u, instruction->GetVectorLength());
987 __ InsertD(dst, locations->InAt(0).AsRegister<GpuRegister>(), 0);
988 break;
989 default:
990 LOG(FATAL) << "Unsupported SIMD type";
991 UNREACHABLE();
992 }
Aart Bik0148de42017-09-05 09:25:01 -0700993}
994
Aart Bikdbbac8f2017-09-01 13:06:08 -0700995// Helper to set up locations for vector accumulations.
Vladimir Markoe764d2e2017-10-05 14:35:55 +0100996static void CreateVecAccumLocations(ArenaAllocator* allocator, HVecOperation* instruction) {
997 LocationSummary* locations = new (allocator) LocationSummary(instruction);
Aart Bikdbbac8f2017-09-01 13:06:08 -0700998 switch (instruction->GetPackedType()) {
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100999 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001000 case DataType::Type::kInt8:
1001 case DataType::Type::kUint16:
1002 case DataType::Type::kInt16:
1003 case DataType::Type::kInt32:
1004 case DataType::Type::kInt64:
Aart Bikdbbac8f2017-09-01 13:06:08 -07001005 locations->SetInAt(0, Location::RequiresFpuRegister());
1006 locations->SetInAt(1, Location::RequiresFpuRegister());
1007 locations->SetInAt(2, Location::RequiresFpuRegister());
Lena Djokicbc5460b2017-07-20 16:07:36 +02001008 locations->SetOut(Location::SameAsFirstInput());
1009 break;
1010 default:
1011 LOG(FATAL) << "Unsupported SIMD type";
1012 UNREACHABLE();
1013 }
Artem Serovf34dd202017-04-10 17:41:46 +01001014}
1015
Aart Bikdbbac8f2017-09-01 13:06:08 -07001016void LocationsBuilderMIPS64::VisitVecMultiplyAccumulate(HVecMultiplyAccumulate* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +01001017 CreateVecAccumLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikdbbac8f2017-09-01 13:06:08 -07001018}
1019
1020void InstructionCodeGeneratorMIPS64::VisitVecMultiplyAccumulate(HVecMultiplyAccumulate* instruction) {
1021 LocationSummary* locations = instruction->GetLocations();
1022 VectorRegister acc = VectorRegisterFrom(locations->InAt(0));
1023 VectorRegister left = VectorRegisterFrom(locations->InAt(1));
1024 VectorRegister right = VectorRegisterFrom(locations->InAt(2));
1025 switch (instruction->GetPackedType()) {
Vladimir Markod5d2f2c2017-09-26 12:37:26 +01001026 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001027 case DataType::Type::kInt8:
Aart Bikdbbac8f2017-09-01 13:06:08 -07001028 DCHECK_EQ(16u, instruction->GetVectorLength());
1029 if (instruction->GetOpKind() == HInstruction::kAdd) {
Lena Djokicbc5460b2017-07-20 16:07:36 +02001030 __ MaddvB(acc, left, right);
1031 } else {
1032 __ MsubvB(acc, left, right);
1033 }
1034 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001035 case DataType::Type::kUint16:
1036 case DataType::Type::kInt16:
Aart Bikdbbac8f2017-09-01 13:06:08 -07001037 DCHECK_EQ(8u, instruction->GetVectorLength());
1038 if (instruction->GetOpKind() == HInstruction::kAdd) {
Lena Djokicbc5460b2017-07-20 16:07:36 +02001039 __ MaddvH(acc, left, right);
1040 } else {
1041 __ MsubvH(acc, left, right);
1042 }
1043 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001044 case DataType::Type::kInt32:
Aart Bikdbbac8f2017-09-01 13:06:08 -07001045 DCHECK_EQ(4u, instruction->GetVectorLength());
1046 if (instruction->GetOpKind() == HInstruction::kAdd) {
Lena Djokicbc5460b2017-07-20 16:07:36 +02001047 __ MaddvW(acc, left, right);
1048 } else {
1049 __ MsubvW(acc, left, right);
1050 }
1051 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001052 case DataType::Type::kInt64:
Aart Bikdbbac8f2017-09-01 13:06:08 -07001053 DCHECK_EQ(2u, instruction->GetVectorLength());
1054 if (instruction->GetOpKind() == HInstruction::kAdd) {
Lena Djokicbc5460b2017-07-20 16:07:36 +02001055 __ MaddvD(acc, left, right);
1056 } else {
1057 __ MsubvD(acc, left, right);
1058 }
1059 break;
1060 default:
1061 LOG(FATAL) << "Unsupported SIMD type";
1062 UNREACHABLE();
1063 }
Artem Serovf34dd202017-04-10 17:41:46 +01001064}
1065
Aart Bikdbbac8f2017-09-01 13:06:08 -07001066void LocationsBuilderMIPS64::VisitVecSADAccumulate(HVecSADAccumulate* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +01001067 CreateVecAccumLocations(GetGraph()->GetAllocator(), instruction);
Lena Djokic38e380b2017-10-30 16:17:10 +01001068 LocationSummary* locations = instruction->GetLocations();
1069 // All conversions require at least one temporary register.
1070 locations->AddTemp(Location::RequiresFpuRegister());
1071 // Some conversions require a second temporary register.
1072 HVecOperation* a = instruction->InputAt(1)->AsVecOperation();
1073 HVecOperation* b = instruction->InputAt(2)->AsVecOperation();
1074 DCHECK_EQ(HVecOperation::ToSignedType(a->GetPackedType()),
1075 HVecOperation::ToSignedType(b->GetPackedType()));
1076 switch (a->GetPackedType()) {
1077 case DataType::Type::kInt32:
1078 if (instruction->GetPackedType() == DataType::Type::kInt32) {
1079 break;
1080 }
1081 FALLTHROUGH_INTENDED;
1082 case DataType::Type::kUint8:
1083 case DataType::Type::kInt8:
1084 case DataType::Type::kUint16:
1085 case DataType::Type::kInt16:
1086 locations->AddTemp(Location::RequiresFpuRegister());
1087 break;
1088 default:
1089 break;
1090 }
Aart Bikdbbac8f2017-09-01 13:06:08 -07001091}
1092
1093void InstructionCodeGeneratorMIPS64::VisitVecSADAccumulate(HVecSADAccumulate* instruction) {
Lena Djokic38e380b2017-10-30 16:17:10 +01001094 LocationSummary* locations = instruction->GetLocations();
1095 VectorRegister acc = VectorRegisterFrom(locations->InAt(0));
1096 VectorRegister left = VectorRegisterFrom(locations->InAt(1));
1097 VectorRegister right = VectorRegisterFrom(locations->InAt(2));
1098 VectorRegister tmp = static_cast<VectorRegister>(FTMP);
1099 VectorRegister tmp1 = VectorRegisterFrom(locations->GetTemp(0));
1100
1101 DCHECK(locations->InAt(0).Equals(locations->Out()));
1102
1103 // Handle all feasible acc_T += sad(a_S, b_S) type combinations (T x S).
1104 HVecOperation* a = instruction->InputAt(1)->AsVecOperation();
1105 HVecOperation* b = instruction->InputAt(2)->AsVecOperation();
1106 DCHECK_EQ(HVecOperation::ToSignedType(a->GetPackedType()),
1107 HVecOperation::ToSignedType(b->GetPackedType()));
1108 switch (a->GetPackedType()) {
1109 case DataType::Type::kUint8:
1110 case DataType::Type::kInt8:
1111 DCHECK_EQ(16u, a->GetVectorLength());
1112 switch (instruction->GetPackedType()) {
1113 case DataType::Type::kUint16:
1114 case DataType::Type::kInt16: {
1115 DCHECK_EQ(8u, instruction->GetVectorLength());
1116 VectorRegister tmp2 = VectorRegisterFrom(locations->GetTemp(1));
1117 __ FillB(tmp, ZERO);
1118 __ Hadd_sH(tmp1, left, tmp);
1119 __ Hadd_sH(tmp2, right, tmp);
1120 __ Asub_sH(tmp1, tmp1, tmp2);
1121 __ AddvH(acc, acc, tmp1);
1122 __ Hadd_sH(tmp1, tmp, left);
1123 __ Hadd_sH(tmp2, tmp, right);
1124 __ Asub_sH(tmp1, tmp1, tmp2);
1125 __ AddvH(acc, acc, tmp1);
1126 break;
1127 }
1128 case DataType::Type::kInt32: {
1129 DCHECK_EQ(4u, instruction->GetVectorLength());
1130 VectorRegister tmp2 = VectorRegisterFrom(locations->GetTemp(1));
1131 __ FillB(tmp, ZERO);
1132 __ Hadd_sH(tmp1, left, tmp);
1133 __ Hadd_sH(tmp2, right, tmp);
1134 __ Asub_sH(tmp1, tmp1, tmp2);
1135 __ Hadd_sW(tmp1, tmp1, tmp1);
1136 __ AddvW(acc, acc, tmp1);
1137 __ Hadd_sH(tmp1, tmp, left);
1138 __ Hadd_sH(tmp2, tmp, right);
1139 __ Asub_sH(tmp1, tmp1, tmp2);
1140 __ Hadd_sW(tmp1, tmp1, tmp1);
1141 __ AddvW(acc, acc, tmp1);
1142 break;
1143 }
1144 case DataType::Type::kInt64: {
1145 DCHECK_EQ(2u, instruction->GetVectorLength());
1146 VectorRegister tmp2 = VectorRegisterFrom(locations->GetTemp(1));
1147 __ FillB(tmp, ZERO);
1148 __ Hadd_sH(tmp1, left, tmp);
1149 __ Hadd_sH(tmp2, right, tmp);
1150 __ Asub_sH(tmp1, tmp1, tmp2);
1151 __ Hadd_sW(tmp1, tmp1, tmp1);
1152 __ Hadd_sD(tmp1, tmp1, tmp1);
1153 __ AddvD(acc, acc, tmp1);
1154 __ Hadd_sH(tmp1, tmp, left);
1155 __ Hadd_sH(tmp2, tmp, right);
1156 __ Asub_sH(tmp1, tmp1, tmp2);
1157 __ Hadd_sW(tmp1, tmp1, tmp1);
1158 __ Hadd_sD(tmp1, tmp1, tmp1);
1159 __ AddvD(acc, acc, tmp1);
1160 break;
1161 }
1162 default:
1163 LOG(FATAL) << "Unsupported SIMD type";
1164 UNREACHABLE();
1165 }
1166 break;
1167 case DataType::Type::kUint16:
1168 case DataType::Type::kInt16:
1169 DCHECK_EQ(8u, a->GetVectorLength());
1170 switch (instruction->GetPackedType()) {
1171 case DataType::Type::kInt32: {
1172 DCHECK_EQ(4u, instruction->GetVectorLength());
1173 VectorRegister tmp2 = VectorRegisterFrom(locations->GetTemp(1));
1174 __ FillH(tmp, ZERO);
1175 __ Hadd_sW(tmp1, left, tmp);
1176 __ Hadd_sW(tmp2, right, tmp);
1177 __ Asub_sW(tmp1, tmp1, tmp2);
1178 __ AddvW(acc, acc, tmp1);
1179 __ Hadd_sW(tmp1, tmp, left);
1180 __ Hadd_sW(tmp2, tmp, right);
1181 __ Asub_sW(tmp1, tmp1, tmp2);
1182 __ AddvW(acc, acc, tmp1);
1183 break;
1184 }
1185 case DataType::Type::kInt64: {
1186 DCHECK_EQ(2u, instruction->GetVectorLength());
1187 VectorRegister tmp2 = VectorRegisterFrom(locations->GetTemp(1));
1188 __ FillH(tmp, ZERO);
1189 __ Hadd_sW(tmp1, left, tmp);
1190 __ Hadd_sW(tmp2, right, tmp);
1191 __ Asub_sW(tmp1, tmp1, tmp2);
1192 __ Hadd_sD(tmp1, tmp1, tmp1);
1193 __ AddvD(acc, acc, tmp1);
1194 __ Hadd_sW(tmp1, tmp, left);
1195 __ Hadd_sW(tmp2, tmp, right);
1196 __ Asub_sW(tmp1, tmp1, tmp2);
1197 __ Hadd_sD(tmp1, tmp1, tmp1);
1198 __ AddvD(acc, acc, tmp1);
1199 break;
1200 }
1201 default:
1202 LOG(FATAL) << "Unsupported SIMD type";
1203 UNREACHABLE();
1204 }
1205 break;
1206 case DataType::Type::kInt32:
1207 DCHECK_EQ(4u, a->GetVectorLength());
1208 switch (instruction->GetPackedType()) {
1209 case DataType::Type::kInt32: {
1210 DCHECK_EQ(4u, instruction->GetVectorLength());
1211 __ FillW(tmp, ZERO);
1212 __ SubvW(tmp1, left, right);
1213 __ Add_aW(tmp1, tmp1, tmp);
1214 __ AddvW(acc, acc, tmp1);
1215 break;
1216 }
1217 case DataType::Type::kInt64: {
1218 DCHECK_EQ(2u, instruction->GetVectorLength());
1219 VectorRegister tmp2 = VectorRegisterFrom(locations->GetTemp(1));
1220 __ FillW(tmp, ZERO);
1221 __ Hadd_sD(tmp1, left, tmp);
1222 __ Hadd_sD(tmp2, right, tmp);
1223 __ Asub_sD(tmp1, tmp1, tmp2);
1224 __ AddvD(acc, acc, tmp1);
1225 __ Hadd_sD(tmp1, tmp, left);
1226 __ Hadd_sD(tmp2, tmp, right);
1227 __ Asub_sD(tmp1, tmp1, tmp2);
1228 __ AddvD(acc, acc, tmp1);
1229 break;
1230 }
1231 default:
1232 LOG(FATAL) << "Unsupported SIMD type";
1233 UNREACHABLE();
1234 }
1235 break;
1236 case DataType::Type::kInt64: {
1237 DCHECK_EQ(2u, a->GetVectorLength());
1238 switch (instruction->GetPackedType()) {
1239 case DataType::Type::kInt64: {
1240 DCHECK_EQ(2u, instruction->GetVectorLength());
1241 __ FillD(tmp, ZERO);
1242 __ SubvD(tmp1, left, right);
1243 __ Add_aD(tmp1, tmp1, tmp);
1244 __ AddvD(acc, acc, tmp1);
1245 break;
1246 }
1247 default:
1248 LOG(FATAL) << "Unsupported SIMD type";
1249 UNREACHABLE();
1250 }
1251 break;
1252 }
1253 default:
1254 LOG(FATAL) << "Unsupported SIMD type";
1255 UNREACHABLE();
1256 }
Aart Bikdbbac8f2017-09-01 13:06:08 -07001257}
1258
Goran Jakovljevic19680d32017-05-11 10:38:36 +02001259// Helper to set up locations for vector memory operations.
Vladimir Markoe764d2e2017-10-05 14:35:55 +01001260static void CreateVecMemLocations(ArenaAllocator* allocator,
Goran Jakovljevic19680d32017-05-11 10:38:36 +02001261 HVecMemoryOperation* instruction,
1262 bool is_load) {
Vladimir Markoe764d2e2017-10-05 14:35:55 +01001263 LocationSummary* locations = new (allocator) LocationSummary(instruction);
Goran Jakovljevic19680d32017-05-11 10:38:36 +02001264 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001265 case DataType::Type::kBool:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +01001266 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001267 case DataType::Type::kInt8:
1268 case DataType::Type::kUint16:
1269 case DataType::Type::kInt16:
1270 case DataType::Type::kInt32:
1271 case DataType::Type::kInt64:
1272 case DataType::Type::kFloat32:
1273 case DataType::Type::kFloat64:
Goran Jakovljevic19680d32017-05-11 10:38:36 +02001274 locations->SetInAt(0, Location::RequiresRegister());
1275 locations->SetInAt(1, Location::RegisterOrConstant(instruction->InputAt(1)));
1276 if (is_load) {
1277 locations->SetOut(Location::RequiresFpuRegister());
1278 } else {
1279 locations->SetInAt(2, Location::RequiresFpuRegister());
1280 }
1281 break;
1282 default:
1283 LOG(FATAL) << "Unsupported SIMD type";
1284 UNREACHABLE();
1285 }
1286}
1287
1288// Helper to prepare register and offset for vector memory operations. Returns the offset and sets
1289// the output parameter adjusted_base to the original base or to a reserved temporary register (AT).
1290int32_t InstructionCodeGeneratorMIPS64::VecAddress(LocationSummary* locations,
1291 size_t size,
1292 /* out */ GpuRegister* adjusted_base) {
1293 GpuRegister base = locations->InAt(0).AsRegister<GpuRegister>();
1294 Location index = locations->InAt(1);
1295 int scale = TIMES_1;
1296 switch (size) {
1297 case 2: scale = TIMES_2; break;
1298 case 4: scale = TIMES_4; break;
1299 case 8: scale = TIMES_8; break;
1300 default: break;
1301 }
1302 int32_t offset = mirror::Array::DataOffset(size).Int32Value();
1303
1304 if (index.IsConstant()) {
1305 offset += index.GetConstant()->AsIntConstant()->GetValue() << scale;
1306 __ AdjustBaseOffsetAndElementSizeShift(base, offset, scale);
1307 *adjusted_base = base;
1308 } else {
1309 GpuRegister index_reg = index.AsRegister<GpuRegister>();
1310 if (scale != TIMES_1) {
1311 __ Dlsa(AT, index_reg, base, scale);
1312 } else {
1313 __ Daddu(AT, base, index_reg);
1314 }
1315 *adjusted_base = AT;
1316 }
1317 return offset;
1318}
1319
Aart Bikf8f5a162017-02-06 15:35:29 -08001320void LocationsBuilderMIPS64::VisitVecLoad(HVecLoad* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +01001321 CreateVecMemLocations(GetGraph()->GetAllocator(), instruction, /* is_load */ true);
Aart Bikf8f5a162017-02-06 15:35:29 -08001322}
1323
1324void InstructionCodeGeneratorMIPS64::VisitVecLoad(HVecLoad* instruction) {
Goran Jakovljevic19680d32017-05-11 10:38:36 +02001325 LocationSummary* locations = instruction->GetLocations();
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001326 size_t size = DataType::Size(instruction->GetPackedType());
Goran Jakovljevic19680d32017-05-11 10:38:36 +02001327 VectorRegister reg = VectorRegisterFrom(locations->Out());
1328 GpuRegister base;
1329 int32_t offset = VecAddress(locations, size, &base);
1330 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001331 case DataType::Type::kBool:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +01001332 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001333 case DataType::Type::kInt8:
Goran Jakovljevic19680d32017-05-11 10:38:36 +02001334 DCHECK_EQ(16u, instruction->GetVectorLength());
1335 __ LdB(reg, base, offset);
1336 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001337 case DataType::Type::kUint16:
1338 case DataType::Type::kInt16:
Goran Jakovljevic19680d32017-05-11 10:38:36 +02001339 // Loading 8-bytes (needed if dealing with compressed strings in StringCharAt) from unaligned
1340 // memory address may cause a trap to the kernel if the CPU doesn't directly support unaligned
1341 // loads and stores.
1342 // TODO: Implement support for StringCharAt.
1343 DCHECK(!instruction->IsStringCharAt());
1344 DCHECK_EQ(8u, instruction->GetVectorLength());
1345 __ LdH(reg, base, offset);
1346 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001347 case DataType::Type::kInt32:
1348 case DataType::Type::kFloat32:
Goran Jakovljevic19680d32017-05-11 10:38:36 +02001349 DCHECK_EQ(4u, instruction->GetVectorLength());
1350 __ LdW(reg, base, offset);
1351 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001352 case DataType::Type::kInt64:
1353 case DataType::Type::kFloat64:
Goran Jakovljevic19680d32017-05-11 10:38:36 +02001354 DCHECK_EQ(2u, instruction->GetVectorLength());
1355 __ LdD(reg, base, offset);
1356 break;
1357 default:
1358 LOG(FATAL) << "Unsupported SIMD type";
1359 UNREACHABLE();
1360 }
Aart Bikf8f5a162017-02-06 15:35:29 -08001361}
1362
1363void LocationsBuilderMIPS64::VisitVecStore(HVecStore* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +01001364 CreateVecMemLocations(GetGraph()->GetAllocator(), instruction, /* is_load */ false);
Aart Bikf8f5a162017-02-06 15:35:29 -08001365}
1366
1367void InstructionCodeGeneratorMIPS64::VisitVecStore(HVecStore* instruction) {
Goran Jakovljevic19680d32017-05-11 10:38:36 +02001368 LocationSummary* locations = instruction->GetLocations();
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001369 size_t size = DataType::Size(instruction->GetPackedType());
Goran Jakovljevic19680d32017-05-11 10:38:36 +02001370 VectorRegister reg = VectorRegisterFrom(locations->InAt(2));
1371 GpuRegister base;
1372 int32_t offset = VecAddress(locations, size, &base);
1373 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001374 case DataType::Type::kBool:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +01001375 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001376 case DataType::Type::kInt8:
Goran Jakovljevic19680d32017-05-11 10:38:36 +02001377 DCHECK_EQ(16u, instruction->GetVectorLength());
1378 __ StB(reg, base, offset);
1379 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001380 case DataType::Type::kUint16:
1381 case DataType::Type::kInt16:
Goran Jakovljevic19680d32017-05-11 10:38:36 +02001382 DCHECK_EQ(8u, instruction->GetVectorLength());
1383 __ StH(reg, base, offset);
1384 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001385 case DataType::Type::kInt32:
1386 case DataType::Type::kFloat32:
Goran Jakovljevic19680d32017-05-11 10:38:36 +02001387 DCHECK_EQ(4u, instruction->GetVectorLength());
1388 __ StW(reg, base, offset);
1389 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001390 case DataType::Type::kInt64:
1391 case DataType::Type::kFloat64:
Goran Jakovljevic19680d32017-05-11 10:38:36 +02001392 DCHECK_EQ(2u, instruction->GetVectorLength());
1393 __ StD(reg, base, offset);
1394 break;
1395 default:
1396 LOG(FATAL) << "Unsupported SIMD type";
1397 UNREACHABLE();
1398 }
Aart Bikf8f5a162017-02-06 15:35:29 -08001399}
1400
1401#undef __
1402
1403} // namespace mips64
1404} // namespace art