blob: de354b63a1568fe5451f0204bb083cef576d9c7f [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:
Aart Bik29aa0822018-03-08 11:28:00 -080050 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Goran Jakovljevic19680d32017-05-11 10:38:36 +020051 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:
Aart Bik29aa0822018-03-08 11:28:00 -080091 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Goran Jakovljevic19680d32017-05-11 10:38:36 +020092 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:
Aart Bik29aa0822018-03-08 11:28:00 -0800115 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Lena Djokice434c4f2017-10-23 16:40:22 +0200116 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:
Aart Bik29aa0822018-03-08 11:28:00 -0800139 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Lena Djokice434c4f2017-10-23 16:40:22 +0200140 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:
Aart Bik29aa0822018-03-08 11:28:00 -0800171 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Aart Bikf8f5a162017-02-06 15:35:29 -0800172 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:
Aart Bik29aa0822018-03-08 11:28:00 -0800226 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Lena Djokice434c4f2017-10-23 16:40:22 +0200227 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 {
Aart Bik29aa0822018-03-08 11:28:00 -0800245 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200246 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:
Aart Bik29aa0822018-03-08 11:28:00 -0800292 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200293 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:
Aart Bik29aa0822018-03-08 11:28:00 -0800339 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200340 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:
Aart Bik29aa0822018-03-08 11:28:00 -0800371 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200372 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:
Aart Bik29aa0822018-03-08 11:28:00 -0800394 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Aart Bikf8f5a162017-02-06 15:35:29 -0800395 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:
Aart Bik29aa0822018-03-08 11:28:00 -0800436 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200437 UNREACHABLE();
438 }
Aart Bikf8f5a162017-02-06 15:35:29 -0800439}
440
Aart Bik29aa0822018-03-08 11:28:00 -0800441void LocationsBuilderMIPS64::VisitVecSaturationAdd(HVecSaturationAdd* instruction) {
442 CreateVecBinOpLocations(GetGraph()->GetAllocator(), instruction);
443}
444
445void InstructionCodeGeneratorMIPS64::VisitVecSaturationAdd(HVecSaturationAdd* instruction) {
446 LOG(FATAL) << "Unsupported SIMD " << instruction->GetId();
447}
448
Aart Bikf3e61ee2017-04-12 17:09:20 -0700449void LocationsBuilderMIPS64::VisitVecHalvingAdd(HVecHalvingAdd* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100450 CreateVecBinOpLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikf3e61ee2017-04-12 17:09:20 -0700451}
452
453void InstructionCodeGeneratorMIPS64::VisitVecHalvingAdd(HVecHalvingAdd* instruction) {
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200454 LocationSummary* locations = instruction->GetLocations();
455 VectorRegister lhs = VectorRegisterFrom(locations->InAt(0));
456 VectorRegister rhs = VectorRegisterFrom(locations->InAt(1));
457 VectorRegister dst = VectorRegisterFrom(locations->Out());
458 switch (instruction->GetPackedType()) {
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100459 case DataType::Type::kUint8:
460 DCHECK_EQ(16u, instruction->GetVectorLength());
461 instruction->IsRounded()
462 ? __ Aver_uB(dst, lhs, rhs)
463 : __ Ave_uB(dst, lhs, rhs);
464 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100465 case DataType::Type::kInt8:
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200466 DCHECK_EQ(16u, instruction->GetVectorLength());
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100467 instruction->IsRounded()
468 ? __ Aver_sB(dst, lhs, rhs)
469 : __ Ave_sB(dst, lhs, rhs);
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200470 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100471 case DataType::Type::kUint16:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100472 DCHECK_EQ(8u, instruction->GetVectorLength());
473 instruction->IsRounded()
474 ? __ Aver_uH(dst, lhs, rhs)
475 : __ Ave_uH(dst, lhs, rhs);
476 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100477 case DataType::Type::kInt16:
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200478 DCHECK_EQ(8u, instruction->GetVectorLength());
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100479 instruction->IsRounded()
480 ? __ Aver_sH(dst, lhs, rhs)
481 : __ Ave_sH(dst, lhs, rhs);
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200482 break;
483 default:
Aart Bik29aa0822018-03-08 11:28:00 -0800484 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200485 UNREACHABLE();
486 }
Aart Bikf3e61ee2017-04-12 17:09:20 -0700487}
488
Aart Bikf8f5a162017-02-06 15:35:29 -0800489void LocationsBuilderMIPS64::VisitVecSub(HVecSub* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100490 CreateVecBinOpLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikf8f5a162017-02-06 15:35:29 -0800491}
492
493void InstructionCodeGeneratorMIPS64::VisitVecSub(HVecSub* instruction) {
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200494 LocationSummary* locations = instruction->GetLocations();
495 VectorRegister lhs = VectorRegisterFrom(locations->InAt(0));
496 VectorRegister rhs = VectorRegisterFrom(locations->InAt(1));
497 VectorRegister dst = VectorRegisterFrom(locations->Out());
498 switch (instruction->GetPackedType()) {
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100499 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100500 case DataType::Type::kInt8:
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200501 DCHECK_EQ(16u, instruction->GetVectorLength());
502 __ SubvB(dst, lhs, rhs);
503 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100504 case DataType::Type::kUint16:
505 case DataType::Type::kInt16:
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200506 DCHECK_EQ(8u, instruction->GetVectorLength());
507 __ SubvH(dst, lhs, rhs);
508 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100509 case DataType::Type::kInt32:
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200510 DCHECK_EQ(4u, instruction->GetVectorLength());
511 __ SubvW(dst, lhs, rhs);
512 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100513 case DataType::Type::kInt64:
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200514 DCHECK_EQ(2u, instruction->GetVectorLength());
515 __ SubvD(dst, lhs, rhs);
516 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100517 case DataType::Type::kFloat32:
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200518 DCHECK_EQ(4u, instruction->GetVectorLength());
519 __ FsubW(dst, lhs, rhs);
520 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100521 case DataType::Type::kFloat64:
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200522 DCHECK_EQ(2u, instruction->GetVectorLength());
523 __ FsubD(dst, lhs, rhs);
524 break;
525 default:
Aart Bik29aa0822018-03-08 11:28:00 -0800526 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200527 UNREACHABLE();
528 }
Aart Bikf8f5a162017-02-06 15:35:29 -0800529}
530
Aart Bik29aa0822018-03-08 11:28:00 -0800531void LocationsBuilderMIPS64::VisitVecSaturationSub(HVecSaturationSub* instruction) {
532 CreateVecBinOpLocations(GetGraph()->GetAllocator(), instruction);
533}
534
535void InstructionCodeGeneratorMIPS64::VisitVecSaturationSub(HVecSaturationSub* instruction) {
536 LOG(FATAL) << "Unsupported SIMD " << instruction->GetId();
537}
538
Aart Bikf8f5a162017-02-06 15:35:29 -0800539void LocationsBuilderMIPS64::VisitVecMul(HVecMul* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100540 CreateVecBinOpLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikf8f5a162017-02-06 15:35:29 -0800541}
542
543void InstructionCodeGeneratorMIPS64::VisitVecMul(HVecMul* instruction) {
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200544 LocationSummary* locations = instruction->GetLocations();
545 VectorRegister lhs = VectorRegisterFrom(locations->InAt(0));
546 VectorRegister rhs = VectorRegisterFrom(locations->InAt(1));
547 VectorRegister dst = VectorRegisterFrom(locations->Out());
548 switch (instruction->GetPackedType()) {
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100549 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100550 case DataType::Type::kInt8:
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200551 DCHECK_EQ(16u, instruction->GetVectorLength());
552 __ MulvB(dst, lhs, rhs);
553 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100554 case DataType::Type::kUint16:
555 case DataType::Type::kInt16:
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200556 DCHECK_EQ(8u, instruction->GetVectorLength());
557 __ MulvH(dst, lhs, rhs);
558 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100559 case DataType::Type::kInt32:
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200560 DCHECK_EQ(4u, instruction->GetVectorLength());
561 __ MulvW(dst, lhs, rhs);
562 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100563 case DataType::Type::kInt64:
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200564 DCHECK_EQ(2u, instruction->GetVectorLength());
565 __ MulvD(dst, lhs, rhs);
566 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100567 case DataType::Type::kFloat32:
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200568 DCHECK_EQ(4u, instruction->GetVectorLength());
569 __ FmulW(dst, lhs, rhs);
570 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100571 case DataType::Type::kFloat64:
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200572 DCHECK_EQ(2u, instruction->GetVectorLength());
573 __ FmulD(dst, lhs, rhs);
574 break;
575 default:
Aart Bik29aa0822018-03-08 11:28:00 -0800576 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200577 UNREACHABLE();
578 }
Aart Bikf8f5a162017-02-06 15:35:29 -0800579}
580
581void LocationsBuilderMIPS64::VisitVecDiv(HVecDiv* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100582 CreateVecBinOpLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikf8f5a162017-02-06 15:35:29 -0800583}
584
585void InstructionCodeGeneratorMIPS64::VisitVecDiv(HVecDiv* instruction) {
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200586 LocationSummary* locations = instruction->GetLocations();
587 VectorRegister lhs = VectorRegisterFrom(locations->InAt(0));
588 VectorRegister rhs = VectorRegisterFrom(locations->InAt(1));
589 VectorRegister dst = VectorRegisterFrom(locations->Out());
590 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100591 case DataType::Type::kFloat32:
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200592 DCHECK_EQ(4u, instruction->GetVectorLength());
593 __ FdivW(dst, lhs, rhs);
594 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100595 case DataType::Type::kFloat64:
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200596 DCHECK_EQ(2u, instruction->GetVectorLength());
597 __ FdivD(dst, lhs, rhs);
598 break;
599 default:
Aart Bik29aa0822018-03-08 11:28:00 -0800600 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200601 UNREACHABLE();
602 }
Aart Bikf8f5a162017-02-06 15:35:29 -0800603}
604
Aart Bikf3e61ee2017-04-12 17:09:20 -0700605void LocationsBuilderMIPS64::VisitVecMin(HVecMin* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100606 CreateVecBinOpLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikf3e61ee2017-04-12 17:09:20 -0700607}
608
609void InstructionCodeGeneratorMIPS64::VisitVecMin(HVecMin* instruction) {
Goran Jakovljevic8fea1e12017-06-06 13:28:42 +0200610 LocationSummary* locations = instruction->GetLocations();
611 VectorRegister lhs = VectorRegisterFrom(locations->InAt(0));
612 VectorRegister rhs = VectorRegisterFrom(locations->InAt(1));
613 VectorRegister dst = VectorRegisterFrom(locations->Out());
614 switch (instruction->GetPackedType()) {
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100615 case DataType::Type::kUint8:
616 DCHECK_EQ(16u, instruction->GetVectorLength());
617 __ Min_uB(dst, lhs, rhs);
618 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100619 case DataType::Type::kInt8:
Goran Jakovljevic8fea1e12017-06-06 13:28:42 +0200620 DCHECK_EQ(16u, instruction->GetVectorLength());
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100621 __ Min_sB(dst, lhs, rhs);
Goran Jakovljevic8fea1e12017-06-06 13:28:42 +0200622 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100623 case DataType::Type::kUint16:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100624 DCHECK_EQ(8u, instruction->GetVectorLength());
625 __ Min_uH(dst, lhs, rhs);
626 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100627 case DataType::Type::kInt16:
Goran Jakovljevic8fea1e12017-06-06 13:28:42 +0200628 DCHECK_EQ(8u, instruction->GetVectorLength());
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100629 __ Min_sH(dst, lhs, rhs);
Goran Jakovljevic8fea1e12017-06-06 13:28:42 +0200630 break;
Aart Bik66c158e2018-01-31 12:55:04 -0800631 case DataType::Type::kUint32:
632 DCHECK_EQ(4u, instruction->GetVectorLength());
633 __ Min_uW(dst, lhs, rhs);
634 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100635 case DataType::Type::kInt32:
Goran Jakovljevic8fea1e12017-06-06 13:28:42 +0200636 DCHECK_EQ(4u, instruction->GetVectorLength());
Aart Bik66c158e2018-01-31 12:55:04 -0800637 __ Min_sW(dst, lhs, rhs);
638 break;
639 case DataType::Type::kUint64:
640 DCHECK_EQ(2u, instruction->GetVectorLength());
641 __ Min_uD(dst, lhs, rhs);
Goran Jakovljevic8fea1e12017-06-06 13:28:42 +0200642 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100643 case DataType::Type::kInt64:
Goran Jakovljevic8fea1e12017-06-06 13:28:42 +0200644 DCHECK_EQ(2u, instruction->GetVectorLength());
Aart Bik66c158e2018-01-31 12:55:04 -0800645 __ Min_sD(dst, lhs, rhs);
Goran Jakovljevic8fea1e12017-06-06 13:28:42 +0200646 break;
647 // When one of arguments is NaN, fmin.df returns other argument, but Java expects a NaN value.
648 // TODO: Fix min(x, NaN) cases for float and double.
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100649 case DataType::Type::kFloat32:
Goran Jakovljevic8fea1e12017-06-06 13:28:42 +0200650 DCHECK_EQ(4u, instruction->GetVectorLength());
Goran Jakovljevic8fea1e12017-06-06 13:28:42 +0200651 __ FminW(dst, lhs, rhs);
652 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100653 case DataType::Type::kFloat64:
Goran Jakovljevic8fea1e12017-06-06 13:28:42 +0200654 DCHECK_EQ(2u, instruction->GetVectorLength());
Goran Jakovljevic8fea1e12017-06-06 13:28:42 +0200655 __ FminD(dst, lhs, rhs);
656 break;
657 default:
Aart Bik29aa0822018-03-08 11:28:00 -0800658 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Goran Jakovljevic8fea1e12017-06-06 13:28:42 +0200659 UNREACHABLE();
660 }
Aart Bikf3e61ee2017-04-12 17:09:20 -0700661}
662
663void LocationsBuilderMIPS64::VisitVecMax(HVecMax* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100664 CreateVecBinOpLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikf3e61ee2017-04-12 17:09:20 -0700665}
666
667void InstructionCodeGeneratorMIPS64::VisitVecMax(HVecMax* instruction) {
Goran Jakovljevic8fea1e12017-06-06 13:28:42 +0200668 LocationSummary* locations = instruction->GetLocations();
669 VectorRegister lhs = VectorRegisterFrom(locations->InAt(0));
670 VectorRegister rhs = VectorRegisterFrom(locations->InAt(1));
671 VectorRegister dst = VectorRegisterFrom(locations->Out());
672 switch (instruction->GetPackedType()) {
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100673 case DataType::Type::kUint8:
674 DCHECK_EQ(16u, instruction->GetVectorLength());
675 __ Max_uB(dst, lhs, rhs);
676 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100677 case DataType::Type::kInt8:
Goran Jakovljevic8fea1e12017-06-06 13:28:42 +0200678 DCHECK_EQ(16u, instruction->GetVectorLength());
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100679 __ Max_sB(dst, lhs, rhs);
Goran Jakovljevic8fea1e12017-06-06 13:28:42 +0200680 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100681 case DataType::Type::kUint16:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100682 DCHECK_EQ(8u, instruction->GetVectorLength());
683 __ Max_uH(dst, lhs, rhs);
684 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100685 case DataType::Type::kInt16:
Goran Jakovljevic8fea1e12017-06-06 13:28:42 +0200686 DCHECK_EQ(8u, instruction->GetVectorLength());
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100687 __ Max_sH(dst, lhs, rhs);
Goran Jakovljevic8fea1e12017-06-06 13:28:42 +0200688 break;
Aart Bik66c158e2018-01-31 12:55:04 -0800689 case DataType::Type::kUint32:
690 DCHECK_EQ(4u, instruction->GetVectorLength());
691 __ Max_uW(dst, lhs, rhs);
692 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100693 case DataType::Type::kInt32:
Goran Jakovljevic8fea1e12017-06-06 13:28:42 +0200694 DCHECK_EQ(4u, instruction->GetVectorLength());
Aart Bik66c158e2018-01-31 12:55:04 -0800695 __ Max_sW(dst, lhs, rhs);
696 break;
697 case DataType::Type::kUint64:
698 DCHECK_EQ(2u, instruction->GetVectorLength());
699 __ Max_uD(dst, lhs, rhs);
Goran Jakovljevic8fea1e12017-06-06 13:28:42 +0200700 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100701 case DataType::Type::kInt64:
Goran Jakovljevic8fea1e12017-06-06 13:28:42 +0200702 DCHECK_EQ(2u, instruction->GetVectorLength());
Aart Bik66c158e2018-01-31 12:55:04 -0800703 __ Max_sD(dst, lhs, rhs);
Goran Jakovljevic8fea1e12017-06-06 13:28:42 +0200704 break;
705 // When one of arguments is NaN, fmax.df returns other argument, but Java expects a NaN value.
706 // TODO: Fix max(x, NaN) cases for float and double.
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100707 case DataType::Type::kFloat32:
Goran Jakovljevic8fea1e12017-06-06 13:28:42 +0200708 DCHECK_EQ(4u, instruction->GetVectorLength());
Goran Jakovljevic8fea1e12017-06-06 13:28:42 +0200709 __ FmaxW(dst, lhs, rhs);
710 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100711 case DataType::Type::kFloat64:
Goran Jakovljevic8fea1e12017-06-06 13:28:42 +0200712 DCHECK_EQ(2u, instruction->GetVectorLength());
Goran Jakovljevic8fea1e12017-06-06 13:28:42 +0200713 __ FmaxD(dst, lhs, rhs);
714 break;
715 default:
Aart Bik29aa0822018-03-08 11:28:00 -0800716 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Goran Jakovljevic8fea1e12017-06-06 13:28:42 +0200717 UNREACHABLE();
718 }
Aart Bikf3e61ee2017-04-12 17:09:20 -0700719}
720
Aart Bikf8f5a162017-02-06 15:35:29 -0800721void LocationsBuilderMIPS64::VisitVecAnd(HVecAnd* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100722 CreateVecBinOpLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikf8f5a162017-02-06 15:35:29 -0800723}
724
725void InstructionCodeGeneratorMIPS64::VisitVecAnd(HVecAnd* instruction) {
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200726 LocationSummary* locations = instruction->GetLocations();
727 VectorRegister lhs = VectorRegisterFrom(locations->InAt(0));
728 VectorRegister rhs = VectorRegisterFrom(locations->InAt(1));
729 VectorRegister dst = VectorRegisterFrom(locations->Out());
730 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100731 case DataType::Type::kBool:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100732 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100733 case DataType::Type::kInt8:
734 case DataType::Type::kUint16:
735 case DataType::Type::kInt16:
736 case DataType::Type::kInt32:
737 case DataType::Type::kInt64:
738 case DataType::Type::kFloat32:
739 case DataType::Type::kFloat64:
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200740 DCHECK_LE(2u, instruction->GetVectorLength());
741 DCHECK_LE(instruction->GetVectorLength(), 16u);
742 __ AndV(dst, lhs, rhs); // lanes do not matter
743 break;
744 default:
Aart Bik29aa0822018-03-08 11:28:00 -0800745 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200746 UNREACHABLE();
747 }
Aart Bikf8f5a162017-02-06 15:35:29 -0800748}
749
750void LocationsBuilderMIPS64::VisitVecAndNot(HVecAndNot* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100751 CreateVecBinOpLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikf8f5a162017-02-06 15:35:29 -0800752}
753
754void InstructionCodeGeneratorMIPS64::VisitVecAndNot(HVecAndNot* instruction) {
755 LOG(FATAL) << "No SIMD for " << instruction->GetId();
756}
757
758void LocationsBuilderMIPS64::VisitVecOr(HVecOr* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100759 CreateVecBinOpLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikf8f5a162017-02-06 15:35:29 -0800760}
761
762void InstructionCodeGeneratorMIPS64::VisitVecOr(HVecOr* instruction) {
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200763 LocationSummary* locations = instruction->GetLocations();
764 VectorRegister lhs = VectorRegisterFrom(locations->InAt(0));
765 VectorRegister rhs = VectorRegisterFrom(locations->InAt(1));
766 VectorRegister dst = VectorRegisterFrom(locations->Out());
767 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100768 case DataType::Type::kBool:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100769 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100770 case DataType::Type::kInt8:
771 case DataType::Type::kUint16:
772 case DataType::Type::kInt16:
773 case DataType::Type::kInt32:
774 case DataType::Type::kInt64:
775 case DataType::Type::kFloat32:
776 case DataType::Type::kFloat64:
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200777 DCHECK_LE(2u, instruction->GetVectorLength());
778 DCHECK_LE(instruction->GetVectorLength(), 16u);
779 __ OrV(dst, lhs, rhs); // lanes do not matter
780 break;
781 default:
Aart Bik29aa0822018-03-08 11:28:00 -0800782 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200783 UNREACHABLE();
784 }
Aart Bikf8f5a162017-02-06 15:35:29 -0800785}
786
787void LocationsBuilderMIPS64::VisitVecXor(HVecXor* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100788 CreateVecBinOpLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikf8f5a162017-02-06 15:35:29 -0800789}
790
791void InstructionCodeGeneratorMIPS64::VisitVecXor(HVecXor* instruction) {
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200792 LocationSummary* locations = instruction->GetLocations();
793 VectorRegister lhs = VectorRegisterFrom(locations->InAt(0));
794 VectorRegister rhs = VectorRegisterFrom(locations->InAt(1));
795 VectorRegister dst = VectorRegisterFrom(locations->Out());
796 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100797 case DataType::Type::kBool:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100798 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100799 case DataType::Type::kInt8:
800 case DataType::Type::kUint16:
801 case DataType::Type::kInt16:
802 case DataType::Type::kInt32:
803 case DataType::Type::kInt64:
804 case DataType::Type::kFloat32:
805 case DataType::Type::kFloat64:
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200806 DCHECK_LE(2u, instruction->GetVectorLength());
807 DCHECK_LE(instruction->GetVectorLength(), 16u);
808 __ XorV(dst, lhs, rhs); // lanes do not matter
809 break;
810 default:
Aart Bik29aa0822018-03-08 11:28:00 -0800811 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200812 UNREACHABLE();
813 }
Aart Bikf8f5a162017-02-06 15:35:29 -0800814}
815
816// Helper to set up locations for vector shift operations.
Vladimir Markoe764d2e2017-10-05 14:35:55 +0100817static void CreateVecShiftLocations(ArenaAllocator* allocator, HVecBinaryOperation* instruction) {
818 LocationSummary* locations = new (allocator) LocationSummary(instruction);
Aart Bikf8f5a162017-02-06 15:35:29 -0800819 switch (instruction->GetPackedType()) {
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100820 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100821 case DataType::Type::kInt8:
822 case DataType::Type::kUint16:
823 case DataType::Type::kInt16:
824 case DataType::Type::kInt32:
825 case DataType::Type::kInt64:
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200826 locations->SetInAt(0, Location::RequiresFpuRegister());
827 locations->SetInAt(1, Location::ConstantLocation(instruction->InputAt(1)->AsConstant()));
828 locations->SetOut(Location::RequiresFpuRegister(), Location::kNoOutputOverlap);
Aart Bikf8f5a162017-02-06 15:35:29 -0800829 break;
830 default:
Aart Bik29aa0822018-03-08 11:28:00 -0800831 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Aart Bikf8f5a162017-02-06 15:35:29 -0800832 UNREACHABLE();
833 }
834}
835
836void LocationsBuilderMIPS64::VisitVecShl(HVecShl* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100837 CreateVecShiftLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikf8f5a162017-02-06 15:35:29 -0800838}
839
840void InstructionCodeGeneratorMIPS64::VisitVecShl(HVecShl* instruction) {
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200841 LocationSummary* locations = instruction->GetLocations();
842 VectorRegister lhs = VectorRegisterFrom(locations->InAt(0));
843 VectorRegister dst = VectorRegisterFrom(locations->Out());
844 int32_t value = locations->InAt(1).GetConstant()->AsIntConstant()->GetValue();
845 switch (instruction->GetPackedType()) {
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100846 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100847 case DataType::Type::kInt8:
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200848 DCHECK_EQ(16u, instruction->GetVectorLength());
849 __ SlliB(dst, lhs, value);
850 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100851 case DataType::Type::kUint16:
852 case DataType::Type::kInt16:
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200853 DCHECK_EQ(8u, instruction->GetVectorLength());
854 __ SlliH(dst, lhs, value);
855 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100856 case DataType::Type::kInt32:
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200857 DCHECK_EQ(4u, instruction->GetVectorLength());
858 __ SlliW(dst, lhs, value);
859 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100860 case DataType::Type::kInt64:
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200861 DCHECK_EQ(2u, instruction->GetVectorLength());
862 __ SlliD(dst, lhs, value);
863 break;
864 default:
Aart Bik29aa0822018-03-08 11:28:00 -0800865 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200866 UNREACHABLE();
867 }
Aart Bikf8f5a162017-02-06 15:35:29 -0800868}
869
870void LocationsBuilderMIPS64::VisitVecShr(HVecShr* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100871 CreateVecShiftLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikf8f5a162017-02-06 15:35:29 -0800872}
873
874void InstructionCodeGeneratorMIPS64::VisitVecShr(HVecShr* instruction) {
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200875 LocationSummary* locations = instruction->GetLocations();
876 VectorRegister lhs = VectorRegisterFrom(locations->InAt(0));
877 VectorRegister dst = VectorRegisterFrom(locations->Out());
878 int32_t value = locations->InAt(1).GetConstant()->AsIntConstant()->GetValue();
879 switch (instruction->GetPackedType()) {
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100880 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100881 case DataType::Type::kInt8:
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200882 DCHECK_EQ(16u, instruction->GetVectorLength());
883 __ SraiB(dst, lhs, value);
884 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100885 case DataType::Type::kUint16:
886 case DataType::Type::kInt16:
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200887 DCHECK_EQ(8u, instruction->GetVectorLength());
888 __ SraiH(dst, lhs, value);
889 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100890 case DataType::Type::kInt32:
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200891 DCHECK_EQ(4u, instruction->GetVectorLength());
892 __ SraiW(dst, lhs, value);
893 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100894 case DataType::Type::kInt64:
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200895 DCHECK_EQ(2u, instruction->GetVectorLength());
896 __ SraiD(dst, lhs, value);
897 break;
898 default:
Aart Bik29aa0822018-03-08 11:28:00 -0800899 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200900 UNREACHABLE();
901 }
Aart Bikf8f5a162017-02-06 15:35:29 -0800902}
903
904void LocationsBuilderMIPS64::VisitVecUShr(HVecUShr* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100905 CreateVecShiftLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikf8f5a162017-02-06 15:35:29 -0800906}
907
908void InstructionCodeGeneratorMIPS64::VisitVecUShr(HVecUShr* instruction) {
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200909 LocationSummary* locations = instruction->GetLocations();
910 VectorRegister lhs = VectorRegisterFrom(locations->InAt(0));
911 VectorRegister dst = VectorRegisterFrom(locations->Out());
912 int32_t value = locations->InAt(1).GetConstant()->AsIntConstant()->GetValue();
913 switch (instruction->GetPackedType()) {
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100914 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100915 case DataType::Type::kInt8:
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200916 DCHECK_EQ(16u, instruction->GetVectorLength());
917 __ SrliB(dst, lhs, value);
918 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100919 case DataType::Type::kUint16:
920 case DataType::Type::kInt16:
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200921 DCHECK_EQ(8u, instruction->GetVectorLength());
922 __ SrliH(dst, lhs, value);
923 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100924 case DataType::Type::kInt32:
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200925 DCHECK_EQ(4u, instruction->GetVectorLength());
926 __ SrliW(dst, lhs, value);
927 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100928 case DataType::Type::kInt64:
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200929 DCHECK_EQ(2u, instruction->GetVectorLength());
930 __ SrliD(dst, lhs, value);
931 break;
932 default:
Aart Bik29aa0822018-03-08 11:28:00 -0800933 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200934 UNREACHABLE();
935 }
Aart Bikf8f5a162017-02-06 15:35:29 -0800936}
937
Aart Bik0148de42017-09-05 09:25:01 -0700938void LocationsBuilderMIPS64::VisitVecSetScalars(HVecSetScalars* instruction) {
Lena Djokice434c4f2017-10-23 16:40:22 +0200939 LocationSummary* locations = new (GetGraph()->GetAllocator()) LocationSummary(instruction);
940
941 DCHECK_EQ(1u, instruction->InputCount()); // only one input currently implemented
942
943 HInstruction* input = instruction->InputAt(0);
944 bool is_zero = IsZeroBitPattern(input);
945
946 switch (instruction->GetPackedType()) {
947 case DataType::Type::kBool:
948 case DataType::Type::kUint8:
949 case DataType::Type::kInt8:
950 case DataType::Type::kUint16:
951 case DataType::Type::kInt16:
952 case DataType::Type::kInt32:
953 case DataType::Type::kInt64:
954 locations->SetInAt(0, is_zero ? Location::ConstantLocation(input->AsConstant())
955 : Location::RequiresRegister());
956 locations->SetOut(Location::RequiresFpuRegister());
957 break;
958 case DataType::Type::kFloat32:
959 case DataType::Type::kFloat64:
960 locations->SetInAt(0, is_zero ? Location::ConstantLocation(input->AsConstant())
961 : Location::RequiresFpuRegister());
962 locations->SetOut(Location::RequiresFpuRegister());
963 break;
964 default:
Aart Bik29aa0822018-03-08 11:28:00 -0800965 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Lena Djokice434c4f2017-10-23 16:40:22 +0200966 UNREACHABLE();
967 }
Aart Bik0148de42017-09-05 09:25:01 -0700968}
969
970void InstructionCodeGeneratorMIPS64::VisitVecSetScalars(HVecSetScalars* instruction) {
Lena Djokice434c4f2017-10-23 16:40:22 +0200971 LocationSummary* locations = instruction->GetLocations();
972 VectorRegister dst = VectorRegisterFrom(locations->Out());
973
974 DCHECK_EQ(1u, instruction->InputCount()); // only one input currently implemented
975
976 // Zero out all other elements first.
977 __ FillW(dst, ZERO);
978
979 // Shorthand for any type of zero.
980 if (IsZeroBitPattern(instruction->InputAt(0))) {
981 return;
982 }
983
984 // Set required elements.
985 switch (instruction->GetPackedType()) {
986 case DataType::Type::kBool:
987 case DataType::Type::kUint8:
988 case DataType::Type::kInt8:
989 DCHECK_EQ(16u, instruction->GetVectorLength());
990 __ InsertB(dst, locations->InAt(0).AsRegister<GpuRegister>(), 0);
991 break;
992 case DataType::Type::kUint16:
993 case DataType::Type::kInt16:
994 DCHECK_EQ(8u, instruction->GetVectorLength());
995 __ InsertH(dst, locations->InAt(0).AsRegister<GpuRegister>(), 0);
996 break;
997 case DataType::Type::kInt32:
998 DCHECK_EQ(4u, instruction->GetVectorLength());
999 __ InsertW(dst, locations->InAt(0).AsRegister<GpuRegister>(), 0);
1000 break;
1001 case DataType::Type::kInt64:
1002 DCHECK_EQ(2u, instruction->GetVectorLength());
1003 __ InsertD(dst, locations->InAt(0).AsRegister<GpuRegister>(), 0);
1004 break;
1005 default:
Aart Bik29aa0822018-03-08 11:28:00 -08001006 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Lena Djokice434c4f2017-10-23 16:40:22 +02001007 UNREACHABLE();
1008 }
Aart Bik0148de42017-09-05 09:25:01 -07001009}
1010
Aart Bikdbbac8f2017-09-01 13:06:08 -07001011// Helper to set up locations for vector accumulations.
Vladimir Markoe764d2e2017-10-05 14:35:55 +01001012static void CreateVecAccumLocations(ArenaAllocator* allocator, HVecOperation* instruction) {
1013 LocationSummary* locations = new (allocator) LocationSummary(instruction);
Aart Bikdbbac8f2017-09-01 13:06:08 -07001014 switch (instruction->GetPackedType()) {
Vladimir Markod5d2f2c2017-09-26 12:37:26 +01001015 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001016 case DataType::Type::kInt8:
1017 case DataType::Type::kUint16:
1018 case DataType::Type::kInt16:
1019 case DataType::Type::kInt32:
1020 case DataType::Type::kInt64:
Aart Bikdbbac8f2017-09-01 13:06:08 -07001021 locations->SetInAt(0, Location::RequiresFpuRegister());
1022 locations->SetInAt(1, Location::RequiresFpuRegister());
1023 locations->SetInAt(2, Location::RequiresFpuRegister());
Lena Djokicbc5460b2017-07-20 16:07:36 +02001024 locations->SetOut(Location::SameAsFirstInput());
1025 break;
1026 default:
Aart Bik29aa0822018-03-08 11:28:00 -08001027 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Lena Djokicbc5460b2017-07-20 16:07:36 +02001028 UNREACHABLE();
1029 }
Artem Serovf34dd202017-04-10 17:41:46 +01001030}
1031
Aart Bikdbbac8f2017-09-01 13:06:08 -07001032void LocationsBuilderMIPS64::VisitVecMultiplyAccumulate(HVecMultiplyAccumulate* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +01001033 CreateVecAccumLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikdbbac8f2017-09-01 13:06:08 -07001034}
1035
1036void InstructionCodeGeneratorMIPS64::VisitVecMultiplyAccumulate(HVecMultiplyAccumulate* instruction) {
1037 LocationSummary* locations = instruction->GetLocations();
1038 VectorRegister acc = VectorRegisterFrom(locations->InAt(0));
1039 VectorRegister left = VectorRegisterFrom(locations->InAt(1));
1040 VectorRegister right = VectorRegisterFrom(locations->InAt(2));
1041 switch (instruction->GetPackedType()) {
Vladimir Markod5d2f2c2017-09-26 12:37:26 +01001042 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001043 case DataType::Type::kInt8:
Aart Bikdbbac8f2017-09-01 13:06:08 -07001044 DCHECK_EQ(16u, instruction->GetVectorLength());
1045 if (instruction->GetOpKind() == HInstruction::kAdd) {
Lena Djokicbc5460b2017-07-20 16:07:36 +02001046 __ MaddvB(acc, left, right);
1047 } else {
1048 __ MsubvB(acc, left, right);
1049 }
1050 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001051 case DataType::Type::kUint16:
1052 case DataType::Type::kInt16:
Aart Bikdbbac8f2017-09-01 13:06:08 -07001053 DCHECK_EQ(8u, instruction->GetVectorLength());
1054 if (instruction->GetOpKind() == HInstruction::kAdd) {
Lena Djokicbc5460b2017-07-20 16:07:36 +02001055 __ MaddvH(acc, left, right);
1056 } else {
1057 __ MsubvH(acc, left, right);
1058 }
1059 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001060 case DataType::Type::kInt32:
Aart Bikdbbac8f2017-09-01 13:06:08 -07001061 DCHECK_EQ(4u, instruction->GetVectorLength());
1062 if (instruction->GetOpKind() == HInstruction::kAdd) {
Lena Djokicbc5460b2017-07-20 16:07:36 +02001063 __ MaddvW(acc, left, right);
1064 } else {
1065 __ MsubvW(acc, left, right);
1066 }
1067 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001068 case DataType::Type::kInt64:
Aart Bikdbbac8f2017-09-01 13:06:08 -07001069 DCHECK_EQ(2u, instruction->GetVectorLength());
1070 if (instruction->GetOpKind() == HInstruction::kAdd) {
Lena Djokicbc5460b2017-07-20 16:07:36 +02001071 __ MaddvD(acc, left, right);
1072 } else {
1073 __ MsubvD(acc, left, right);
1074 }
1075 break;
1076 default:
Aart Bik29aa0822018-03-08 11:28:00 -08001077 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Lena Djokicbc5460b2017-07-20 16:07:36 +02001078 UNREACHABLE();
1079 }
Artem Serovf34dd202017-04-10 17:41:46 +01001080}
1081
Aart Bikdbbac8f2017-09-01 13:06:08 -07001082void LocationsBuilderMIPS64::VisitVecSADAccumulate(HVecSADAccumulate* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +01001083 CreateVecAccumLocations(GetGraph()->GetAllocator(), instruction);
Lena Djokic38e380b2017-10-30 16:17:10 +01001084 LocationSummary* locations = instruction->GetLocations();
1085 // All conversions require at least one temporary register.
1086 locations->AddTemp(Location::RequiresFpuRegister());
1087 // Some conversions require a second temporary register.
1088 HVecOperation* a = instruction->InputAt(1)->AsVecOperation();
1089 HVecOperation* b = instruction->InputAt(2)->AsVecOperation();
1090 DCHECK_EQ(HVecOperation::ToSignedType(a->GetPackedType()),
1091 HVecOperation::ToSignedType(b->GetPackedType()));
1092 switch (a->GetPackedType()) {
1093 case DataType::Type::kInt32:
1094 if (instruction->GetPackedType() == DataType::Type::kInt32) {
1095 break;
1096 }
1097 FALLTHROUGH_INTENDED;
1098 case DataType::Type::kUint8:
1099 case DataType::Type::kInt8:
1100 case DataType::Type::kUint16:
1101 case DataType::Type::kInt16:
1102 locations->AddTemp(Location::RequiresFpuRegister());
1103 break;
1104 default:
1105 break;
1106 }
Aart Bikdbbac8f2017-09-01 13:06:08 -07001107}
1108
1109void InstructionCodeGeneratorMIPS64::VisitVecSADAccumulate(HVecSADAccumulate* instruction) {
Lena Djokic38e380b2017-10-30 16:17:10 +01001110 LocationSummary* locations = instruction->GetLocations();
1111 VectorRegister acc = VectorRegisterFrom(locations->InAt(0));
1112 VectorRegister left = VectorRegisterFrom(locations->InAt(1));
1113 VectorRegister right = VectorRegisterFrom(locations->InAt(2));
1114 VectorRegister tmp = static_cast<VectorRegister>(FTMP);
1115 VectorRegister tmp1 = VectorRegisterFrom(locations->GetTemp(0));
1116
1117 DCHECK(locations->InAt(0).Equals(locations->Out()));
1118
1119 // Handle all feasible acc_T += sad(a_S, b_S) type combinations (T x S).
1120 HVecOperation* a = instruction->InputAt(1)->AsVecOperation();
1121 HVecOperation* b = instruction->InputAt(2)->AsVecOperation();
1122 DCHECK_EQ(HVecOperation::ToSignedType(a->GetPackedType()),
1123 HVecOperation::ToSignedType(b->GetPackedType()));
1124 switch (a->GetPackedType()) {
1125 case DataType::Type::kUint8:
1126 case DataType::Type::kInt8:
1127 DCHECK_EQ(16u, a->GetVectorLength());
1128 switch (instruction->GetPackedType()) {
1129 case DataType::Type::kUint16:
1130 case DataType::Type::kInt16: {
1131 DCHECK_EQ(8u, instruction->GetVectorLength());
1132 VectorRegister tmp2 = VectorRegisterFrom(locations->GetTemp(1));
1133 __ FillB(tmp, ZERO);
1134 __ Hadd_sH(tmp1, left, tmp);
1135 __ Hadd_sH(tmp2, right, tmp);
1136 __ Asub_sH(tmp1, tmp1, tmp2);
1137 __ AddvH(acc, acc, tmp1);
1138 __ Hadd_sH(tmp1, tmp, left);
1139 __ Hadd_sH(tmp2, tmp, right);
1140 __ Asub_sH(tmp1, tmp1, tmp2);
1141 __ AddvH(acc, acc, tmp1);
1142 break;
1143 }
1144 case DataType::Type::kInt32: {
1145 DCHECK_EQ(4u, 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 __ AddvW(acc, acc, tmp1);
1153 __ Hadd_sH(tmp1, tmp, left);
1154 __ Hadd_sH(tmp2, tmp, right);
1155 __ Asub_sH(tmp1, tmp1, tmp2);
1156 __ Hadd_sW(tmp1, tmp1, tmp1);
1157 __ AddvW(acc, acc, tmp1);
1158 break;
1159 }
1160 case DataType::Type::kInt64: {
1161 DCHECK_EQ(2u, instruction->GetVectorLength());
1162 VectorRegister tmp2 = VectorRegisterFrom(locations->GetTemp(1));
1163 __ FillB(tmp, ZERO);
1164 __ Hadd_sH(tmp1, left, tmp);
1165 __ Hadd_sH(tmp2, right, tmp);
1166 __ Asub_sH(tmp1, tmp1, tmp2);
1167 __ Hadd_sW(tmp1, tmp1, tmp1);
1168 __ Hadd_sD(tmp1, tmp1, tmp1);
1169 __ AddvD(acc, acc, tmp1);
1170 __ Hadd_sH(tmp1, tmp, left);
1171 __ Hadd_sH(tmp2, tmp, right);
1172 __ Asub_sH(tmp1, tmp1, tmp2);
1173 __ Hadd_sW(tmp1, tmp1, tmp1);
1174 __ Hadd_sD(tmp1, tmp1, tmp1);
1175 __ AddvD(acc, acc, tmp1);
1176 break;
1177 }
1178 default:
Aart Bik29aa0822018-03-08 11:28:00 -08001179 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Lena Djokic38e380b2017-10-30 16:17:10 +01001180 UNREACHABLE();
1181 }
1182 break;
1183 case DataType::Type::kUint16:
1184 case DataType::Type::kInt16:
1185 DCHECK_EQ(8u, a->GetVectorLength());
1186 switch (instruction->GetPackedType()) {
1187 case DataType::Type::kInt32: {
1188 DCHECK_EQ(4u, instruction->GetVectorLength());
1189 VectorRegister tmp2 = VectorRegisterFrom(locations->GetTemp(1));
1190 __ FillH(tmp, ZERO);
1191 __ Hadd_sW(tmp1, left, tmp);
1192 __ Hadd_sW(tmp2, right, tmp);
1193 __ Asub_sW(tmp1, tmp1, tmp2);
1194 __ AddvW(acc, acc, tmp1);
1195 __ Hadd_sW(tmp1, tmp, left);
1196 __ Hadd_sW(tmp2, tmp, right);
1197 __ Asub_sW(tmp1, tmp1, tmp2);
1198 __ AddvW(acc, acc, tmp1);
1199 break;
1200 }
1201 case DataType::Type::kInt64: {
1202 DCHECK_EQ(2u, instruction->GetVectorLength());
1203 VectorRegister tmp2 = VectorRegisterFrom(locations->GetTemp(1));
1204 __ FillH(tmp, ZERO);
1205 __ Hadd_sW(tmp1, left, tmp);
1206 __ Hadd_sW(tmp2, right, tmp);
1207 __ Asub_sW(tmp1, tmp1, tmp2);
1208 __ Hadd_sD(tmp1, tmp1, tmp1);
1209 __ AddvD(acc, acc, tmp1);
1210 __ Hadd_sW(tmp1, tmp, left);
1211 __ Hadd_sW(tmp2, tmp, right);
1212 __ Asub_sW(tmp1, tmp1, tmp2);
1213 __ Hadd_sD(tmp1, tmp1, tmp1);
1214 __ AddvD(acc, acc, tmp1);
1215 break;
1216 }
1217 default:
Aart Bik29aa0822018-03-08 11:28:00 -08001218 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Lena Djokic38e380b2017-10-30 16:17:10 +01001219 UNREACHABLE();
1220 }
1221 break;
1222 case DataType::Type::kInt32:
1223 DCHECK_EQ(4u, a->GetVectorLength());
1224 switch (instruction->GetPackedType()) {
1225 case DataType::Type::kInt32: {
1226 DCHECK_EQ(4u, instruction->GetVectorLength());
1227 __ FillW(tmp, ZERO);
1228 __ SubvW(tmp1, left, right);
1229 __ Add_aW(tmp1, tmp1, tmp);
1230 __ AddvW(acc, acc, tmp1);
1231 break;
1232 }
1233 case DataType::Type::kInt64: {
1234 DCHECK_EQ(2u, instruction->GetVectorLength());
1235 VectorRegister tmp2 = VectorRegisterFrom(locations->GetTemp(1));
1236 __ FillW(tmp, ZERO);
1237 __ Hadd_sD(tmp1, left, tmp);
1238 __ Hadd_sD(tmp2, right, tmp);
1239 __ Asub_sD(tmp1, tmp1, tmp2);
1240 __ AddvD(acc, acc, tmp1);
1241 __ Hadd_sD(tmp1, tmp, left);
1242 __ Hadd_sD(tmp2, tmp, right);
1243 __ Asub_sD(tmp1, tmp1, tmp2);
1244 __ AddvD(acc, acc, tmp1);
1245 break;
1246 }
1247 default:
Aart Bik29aa0822018-03-08 11:28:00 -08001248 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Lena Djokic38e380b2017-10-30 16:17:10 +01001249 UNREACHABLE();
1250 }
1251 break;
1252 case DataType::Type::kInt64: {
1253 DCHECK_EQ(2u, a->GetVectorLength());
1254 switch (instruction->GetPackedType()) {
1255 case DataType::Type::kInt64: {
1256 DCHECK_EQ(2u, instruction->GetVectorLength());
1257 __ FillD(tmp, ZERO);
1258 __ SubvD(tmp1, left, right);
1259 __ Add_aD(tmp1, tmp1, tmp);
1260 __ AddvD(acc, acc, tmp1);
1261 break;
1262 }
1263 default:
Aart Bik29aa0822018-03-08 11:28:00 -08001264 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Lena Djokic38e380b2017-10-30 16:17:10 +01001265 UNREACHABLE();
1266 }
1267 break;
1268 }
1269 default:
Aart Bik29aa0822018-03-08 11:28:00 -08001270 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Lena Djokic38e380b2017-10-30 16:17:10 +01001271 UNREACHABLE();
1272 }
Aart Bikdbbac8f2017-09-01 13:06:08 -07001273}
1274
Goran Jakovljevic19680d32017-05-11 10:38:36 +02001275// Helper to set up locations for vector memory operations.
Vladimir Markoe764d2e2017-10-05 14:35:55 +01001276static void CreateVecMemLocations(ArenaAllocator* allocator,
Goran Jakovljevic19680d32017-05-11 10:38:36 +02001277 HVecMemoryOperation* instruction,
1278 bool is_load) {
Vladimir Markoe764d2e2017-10-05 14:35:55 +01001279 LocationSummary* locations = new (allocator) LocationSummary(instruction);
Goran Jakovljevic19680d32017-05-11 10:38:36 +02001280 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001281 case DataType::Type::kBool:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +01001282 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001283 case DataType::Type::kInt8:
1284 case DataType::Type::kUint16:
1285 case DataType::Type::kInt16:
1286 case DataType::Type::kInt32:
1287 case DataType::Type::kInt64:
1288 case DataType::Type::kFloat32:
1289 case DataType::Type::kFloat64:
Goran Jakovljevic19680d32017-05-11 10:38:36 +02001290 locations->SetInAt(0, Location::RequiresRegister());
1291 locations->SetInAt(1, Location::RegisterOrConstant(instruction->InputAt(1)));
1292 if (is_load) {
1293 locations->SetOut(Location::RequiresFpuRegister());
1294 } else {
1295 locations->SetInAt(2, Location::RequiresFpuRegister());
1296 }
1297 break;
1298 default:
Aart Bik29aa0822018-03-08 11:28:00 -08001299 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Goran Jakovljevic19680d32017-05-11 10:38:36 +02001300 UNREACHABLE();
1301 }
1302}
1303
1304// Helper to prepare register and offset for vector memory operations. Returns the offset and sets
1305// the output parameter adjusted_base to the original base or to a reserved temporary register (AT).
1306int32_t InstructionCodeGeneratorMIPS64::VecAddress(LocationSummary* locations,
1307 size_t size,
1308 /* out */ GpuRegister* adjusted_base) {
1309 GpuRegister base = locations->InAt(0).AsRegister<GpuRegister>();
1310 Location index = locations->InAt(1);
1311 int scale = TIMES_1;
1312 switch (size) {
1313 case 2: scale = TIMES_2; break;
1314 case 4: scale = TIMES_4; break;
1315 case 8: scale = TIMES_8; break;
1316 default: break;
1317 }
1318 int32_t offset = mirror::Array::DataOffset(size).Int32Value();
1319
1320 if (index.IsConstant()) {
1321 offset += index.GetConstant()->AsIntConstant()->GetValue() << scale;
1322 __ AdjustBaseOffsetAndElementSizeShift(base, offset, scale);
1323 *adjusted_base = base;
1324 } else {
1325 GpuRegister index_reg = index.AsRegister<GpuRegister>();
1326 if (scale != TIMES_1) {
1327 __ Dlsa(AT, index_reg, base, scale);
1328 } else {
1329 __ Daddu(AT, base, index_reg);
1330 }
1331 *adjusted_base = AT;
1332 }
1333 return offset;
1334}
1335
Aart Bikf8f5a162017-02-06 15:35:29 -08001336void LocationsBuilderMIPS64::VisitVecLoad(HVecLoad* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +01001337 CreateVecMemLocations(GetGraph()->GetAllocator(), instruction, /* is_load */ true);
Aart Bikf8f5a162017-02-06 15:35:29 -08001338}
1339
1340void InstructionCodeGeneratorMIPS64::VisitVecLoad(HVecLoad* instruction) {
Goran Jakovljevic19680d32017-05-11 10:38:36 +02001341 LocationSummary* locations = instruction->GetLocations();
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001342 size_t size = DataType::Size(instruction->GetPackedType());
Goran Jakovljevic19680d32017-05-11 10:38:36 +02001343 VectorRegister reg = VectorRegisterFrom(locations->Out());
1344 GpuRegister base;
1345 int32_t offset = VecAddress(locations, size, &base);
1346 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001347 case DataType::Type::kBool:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +01001348 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001349 case DataType::Type::kInt8:
Goran Jakovljevic19680d32017-05-11 10:38:36 +02001350 DCHECK_EQ(16u, instruction->GetVectorLength());
1351 __ LdB(reg, base, offset);
1352 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001353 case DataType::Type::kUint16:
1354 case DataType::Type::kInt16:
Goran Jakovljevic19680d32017-05-11 10:38:36 +02001355 // Loading 8-bytes (needed if dealing with compressed strings in StringCharAt) from unaligned
1356 // memory address may cause a trap to the kernel if the CPU doesn't directly support unaligned
1357 // loads and stores.
1358 // TODO: Implement support for StringCharAt.
1359 DCHECK(!instruction->IsStringCharAt());
1360 DCHECK_EQ(8u, instruction->GetVectorLength());
1361 __ LdH(reg, base, offset);
1362 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001363 case DataType::Type::kInt32:
1364 case DataType::Type::kFloat32:
Goran Jakovljevic19680d32017-05-11 10:38:36 +02001365 DCHECK_EQ(4u, instruction->GetVectorLength());
1366 __ LdW(reg, base, offset);
1367 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001368 case DataType::Type::kInt64:
1369 case DataType::Type::kFloat64:
Goran Jakovljevic19680d32017-05-11 10:38:36 +02001370 DCHECK_EQ(2u, instruction->GetVectorLength());
1371 __ LdD(reg, base, offset);
1372 break;
1373 default:
Aart Bik29aa0822018-03-08 11:28:00 -08001374 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Goran Jakovljevic19680d32017-05-11 10:38:36 +02001375 UNREACHABLE();
1376 }
Aart Bikf8f5a162017-02-06 15:35:29 -08001377}
1378
1379void LocationsBuilderMIPS64::VisitVecStore(HVecStore* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +01001380 CreateVecMemLocations(GetGraph()->GetAllocator(), instruction, /* is_load */ false);
Aart Bikf8f5a162017-02-06 15:35:29 -08001381}
1382
1383void InstructionCodeGeneratorMIPS64::VisitVecStore(HVecStore* instruction) {
Goran Jakovljevic19680d32017-05-11 10:38:36 +02001384 LocationSummary* locations = instruction->GetLocations();
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001385 size_t size = DataType::Size(instruction->GetPackedType());
Goran Jakovljevic19680d32017-05-11 10:38:36 +02001386 VectorRegister reg = VectorRegisterFrom(locations->InAt(2));
1387 GpuRegister base;
1388 int32_t offset = VecAddress(locations, size, &base);
1389 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001390 case DataType::Type::kBool:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +01001391 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001392 case DataType::Type::kInt8:
Goran Jakovljevic19680d32017-05-11 10:38:36 +02001393 DCHECK_EQ(16u, instruction->GetVectorLength());
1394 __ StB(reg, base, offset);
1395 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001396 case DataType::Type::kUint16:
1397 case DataType::Type::kInt16:
Goran Jakovljevic19680d32017-05-11 10:38:36 +02001398 DCHECK_EQ(8u, instruction->GetVectorLength());
1399 __ StH(reg, base, offset);
1400 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001401 case DataType::Type::kInt32:
1402 case DataType::Type::kFloat32:
Goran Jakovljevic19680d32017-05-11 10:38:36 +02001403 DCHECK_EQ(4u, instruction->GetVectorLength());
1404 __ StW(reg, base, offset);
1405 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001406 case DataType::Type::kInt64:
1407 case DataType::Type::kFloat64:
Goran Jakovljevic19680d32017-05-11 10:38:36 +02001408 DCHECK_EQ(2u, instruction->GetVectorLength());
1409 __ StD(reg, base, offset);
1410 break;
1411 default:
Aart Bik29aa0822018-03-08 11:28:00 -08001412 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Goran Jakovljevic19680d32017-05-11 10:38:36 +02001413 UNREACHABLE();
1414 }
Aart Bikf8f5a162017-02-06 15:35:29 -08001415}
1416
1417#undef __
1418
1419} // namespace mips64
1420} // namespace art