blob: df0e1485d69202722ea12a0ede99e21ce524230d [file] [log] [blame]
Aart Bikf8f5a162017-02-06 15:35:29 -08001/*
2 * Copyright (C) 2017 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "code_generator_mips.h"
Lena Djokic51765b02017-06-22 13:49:59 +020018#include "mirror/array-inl.h"
Aart Bikf8f5a162017-02-06 15:35:29 -080019
20namespace art {
21namespace mips {
22
23// NOLINT on __ macro to suppress wrong warning/fix (misc-macro-parentheses) from clang-tidy.
24#define __ down_cast<MipsAssembler*>(GetAssembler())-> // NOLINT
25
26void LocationsBuilderMIPS::VisitVecReplicateScalar(HVecReplicateScalar* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +010027 LocationSummary* locations = new (GetGraph()->GetAllocator()) LocationSummary(instruction);
Lena Djokic51765b02017-06-22 13:49:59 +020028 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +010029 case DataType::Type::kBool:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +010030 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +010031 case DataType::Type::kInt8:
32 case DataType::Type::kUint16:
33 case DataType::Type::kInt16:
34 case DataType::Type::kInt32:
35 case DataType::Type::kInt64:
Lena Djokic51765b02017-06-22 13:49:59 +020036 locations->SetInAt(0, Location::RequiresRegister());
37 locations->SetOut(Location::RequiresFpuRegister());
38 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +010039 case DataType::Type::kFloat32:
40 case DataType::Type::kFloat64:
Lena Djokic51765b02017-06-22 13:49:59 +020041 locations->SetInAt(0, Location::RequiresFpuRegister());
42 locations->SetOut(Location::RequiresFpuRegister(), Location::kNoOutputOverlap);
43 break;
44 default:
Aart Bik29aa0822018-03-08 11:28:00 -080045 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Lena Djokic51765b02017-06-22 13:49:59 +020046 UNREACHABLE();
47 }
Aart Bikf8f5a162017-02-06 15:35:29 -080048}
49
50void InstructionCodeGeneratorMIPS::VisitVecReplicateScalar(HVecReplicateScalar* instruction) {
Lena Djokic51765b02017-06-22 13:49:59 +020051 LocationSummary* locations = instruction->GetLocations();
52 VectorRegister dst = VectorRegisterFrom(locations->Out());
53 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +010054 case DataType::Type::kBool:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +010055 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +010056 case DataType::Type::kInt8:
Lena Djokic51765b02017-06-22 13:49:59 +020057 DCHECK_EQ(16u, instruction->GetVectorLength());
58 __ FillB(dst, locations->InAt(0).AsRegister<Register>());
59 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +010060 case DataType::Type::kUint16:
61 case DataType::Type::kInt16:
Lena Djokic51765b02017-06-22 13:49:59 +020062 DCHECK_EQ(8u, instruction->GetVectorLength());
63 __ FillH(dst, locations->InAt(0).AsRegister<Register>());
64 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +010065 case DataType::Type::kInt32:
Lena Djokic51765b02017-06-22 13:49:59 +020066 DCHECK_EQ(4u, instruction->GetVectorLength());
67 __ FillW(dst, locations->InAt(0).AsRegister<Register>());
68 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +010069 case DataType::Type::kInt64:
Lena Djokic51765b02017-06-22 13:49:59 +020070 DCHECK_EQ(2u, instruction->GetVectorLength());
Goran Jakovljevic7a0222e2017-11-08 10:16:37 +010071 __ InsertW(static_cast<VectorRegister>(FTMP),
72 locations->InAt(0).AsRegisterPairLow<Register>(),
73 0);
74 __ InsertW(static_cast<VectorRegister>(FTMP),
75 locations->InAt(0).AsRegisterPairHigh<Register>(),
76 1);
Lena Djokic51765b02017-06-22 13:49:59 +020077 __ ReplicateFPToVectorRegister(dst, FTMP, /* is_double */ true);
78 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +010079 case DataType::Type::kFloat32:
Lena Djokic51765b02017-06-22 13:49:59 +020080 DCHECK_EQ(4u, instruction->GetVectorLength());
81 __ ReplicateFPToVectorRegister(dst,
82 locations->InAt(0).AsFpuRegister<FRegister>(),
83 /* is_double */ false);
84 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +010085 case DataType::Type::kFloat64:
Lena Djokic51765b02017-06-22 13:49:59 +020086 DCHECK_EQ(2u, instruction->GetVectorLength());
87 __ ReplicateFPToVectorRegister(dst,
88 locations->InAt(0).AsFpuRegister<FRegister>(),
89 /* is_double */ true);
90 break;
91 default:
Aart Bik29aa0822018-03-08 11:28:00 -080092 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Lena Djokic51765b02017-06-22 13:49:59 +020093 UNREACHABLE();
94 }
Aart Bikf8f5a162017-02-06 15:35:29 -080095}
96
Aart Bik0148de42017-09-05 09:25:01 -070097void LocationsBuilderMIPS::VisitVecExtractScalar(HVecExtractScalar* instruction) {
Lena Djokice434c4f2017-10-23 16:40:22 +020098 LocationSummary* locations = new (GetGraph()->GetAllocator()) LocationSummary(instruction);
99 switch (instruction->GetPackedType()) {
100 case DataType::Type::kBool:
101 case DataType::Type::kUint8:
102 case DataType::Type::kInt8:
103 case DataType::Type::kUint16:
104 case DataType::Type::kInt16:
105 case DataType::Type::kInt32:
106 case DataType::Type::kInt64:
107 locations->SetInAt(0, Location::RequiresFpuRegister());
108 locations->SetOut(Location::RequiresRegister());
109 break;
110 case DataType::Type::kFloat32:
111 case DataType::Type::kFloat64:
112 locations->SetInAt(0, Location::RequiresFpuRegister());
113 locations->SetOut(Location::SameAsFirstInput());
114 break;
115 default:
Aart Bik29aa0822018-03-08 11:28:00 -0800116 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Lena Djokice434c4f2017-10-23 16:40:22 +0200117 UNREACHABLE();
118 }
Aart Bikf8f5a162017-02-06 15:35:29 -0800119}
120
Aart Bik0148de42017-09-05 09:25:01 -0700121void InstructionCodeGeneratorMIPS::VisitVecExtractScalar(HVecExtractScalar* instruction) {
Lena Djokice434c4f2017-10-23 16:40:22 +0200122 LocationSummary* locations = instruction->GetLocations();
123 VectorRegister src = VectorRegisterFrom(locations->InAt(0));
124 switch (instruction->GetPackedType()) {
125 case DataType::Type::kInt32:
126 DCHECK_EQ(4u, instruction->GetVectorLength());
127 __ Copy_sW(locations->Out().AsRegister<Register>(), src, 0);
128 break;
129 case DataType::Type::kInt64:
130 DCHECK_EQ(2u, instruction->GetVectorLength());
Goran Jakovljevic7a0222e2017-11-08 10:16:37 +0100131 __ Copy_sW(locations->Out().AsRegisterPairLow<Register>(), src, 0);
132 __ Copy_sW(locations->Out().AsRegisterPairHigh<Register>(), src, 1);
Lena Djokice434c4f2017-10-23 16:40:22 +0200133 break;
134 case DataType::Type::kFloat32:
135 case DataType::Type::kFloat64:
136 DCHECK_LE(2u, instruction->GetVectorLength());
137 DCHECK_LE(instruction->GetVectorLength(), 4u);
138 DCHECK(locations->InAt(0).Equals(locations->Out())); // no code required
139 break;
140 default:
Aart Bik29aa0822018-03-08 11:28:00 -0800141 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Lena Djokice434c4f2017-10-23 16:40:22 +0200142 UNREACHABLE();
143 }
Aart Bikf8f5a162017-02-06 15:35:29 -0800144}
145
146// Helper to set up locations for vector unary operations.
Vladimir Markoe764d2e2017-10-05 14:35:55 +0100147static void CreateVecUnOpLocations(ArenaAllocator* allocator, HVecUnaryOperation* instruction) {
148 LocationSummary* locations = new (allocator) LocationSummary(instruction);
Lena Djokice434c4f2017-10-23 16:40:22 +0200149 DataType::Type type = instruction->GetPackedType();
150 switch (type) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100151 case DataType::Type::kBool:
Lena Djokic51765b02017-06-22 13:49:59 +0200152 locations->SetInAt(0, Location::RequiresFpuRegister());
153 locations->SetOut(Location::RequiresFpuRegister(),
154 instruction->IsVecNot() ? Location::kOutputOverlap
155 : Location::kNoOutputOverlap);
156 break;
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100157 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100158 case DataType::Type::kInt8:
159 case DataType::Type::kUint16:
160 case DataType::Type::kInt16:
161 case DataType::Type::kInt32:
162 case DataType::Type::kInt64:
163 case DataType::Type::kFloat32:
164 case DataType::Type::kFloat64:
Lena Djokic51765b02017-06-22 13:49:59 +0200165 locations->SetInAt(0, Location::RequiresFpuRegister());
166 locations->SetOut(Location::RequiresFpuRegister(),
Lena Djokice434c4f2017-10-23 16:40:22 +0200167 (instruction->IsVecNeg() || instruction->IsVecAbs() ||
168 (instruction->IsVecReduce() && type == DataType::Type::kInt64))
Lena Djokic51765b02017-06-22 13:49:59 +0200169 ? Location::kOutputOverlap
170 : Location::kNoOutputOverlap);
Aart Bikf8f5a162017-02-06 15:35:29 -0800171 break;
172 default:
Aart Bik29aa0822018-03-08 11:28:00 -0800173 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Aart Bikf8f5a162017-02-06 15:35:29 -0800174 UNREACHABLE();
175 }
176}
177
Aart Bik0148de42017-09-05 09:25:01 -0700178void LocationsBuilderMIPS::VisitVecReduce(HVecReduce* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100179 CreateVecUnOpLocations(GetGraph()->GetAllocator(), instruction);
Aart Bik0148de42017-09-05 09:25:01 -0700180}
181
182void InstructionCodeGeneratorMIPS::VisitVecReduce(HVecReduce* instruction) {
Lena Djokice434c4f2017-10-23 16:40:22 +0200183 LocationSummary* locations = instruction->GetLocations();
184 VectorRegister src = VectorRegisterFrom(locations->InAt(0));
185 VectorRegister dst = VectorRegisterFrom(locations->Out());
186 VectorRegister tmp = static_cast<VectorRegister>(FTMP);
187 switch (instruction->GetPackedType()) {
188 case DataType::Type::kInt32:
189 DCHECK_EQ(4u, instruction->GetVectorLength());
190 switch (instruction->GetKind()) {
191 case HVecReduce::kSum:
192 __ Hadd_sD(tmp, src, src);
193 __ IlvlD(dst, tmp, tmp);
194 __ AddvW(dst, dst, tmp);
195 break;
196 case HVecReduce::kMin:
197 __ IlvodW(tmp, src, src);
198 __ Min_sW(tmp, src, tmp);
199 __ IlvlW(dst, tmp, tmp);
200 __ Min_sW(dst, dst, tmp);
201 break;
202 case HVecReduce::kMax:
203 __ IlvodW(tmp, src, src);
204 __ Max_sW(tmp, src, tmp);
205 __ IlvlW(dst, tmp, tmp);
206 __ Max_sW(dst, dst, tmp);
207 break;
208 }
209 break;
210 case DataType::Type::kInt64:
211 DCHECK_EQ(2u, instruction->GetVectorLength());
212 switch (instruction->GetKind()) {
213 case HVecReduce::kSum:
214 __ IlvlD(dst, src, src);
215 __ AddvD(dst, dst, src);
216 break;
217 case HVecReduce::kMin:
218 __ IlvlD(dst, src, src);
219 __ Min_sD(dst, dst, src);
220 break;
221 case HVecReduce::kMax:
222 __ IlvlD(dst, src, src);
223 __ Max_sD(dst, dst, src);
224 break;
225 }
226 break;
227 default:
Aart Bik29aa0822018-03-08 11:28:00 -0800228 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Lena Djokice434c4f2017-10-23 16:40:22 +0200229 UNREACHABLE();
230 }
Aart Bik0148de42017-09-05 09:25:01 -0700231}
232
Aart Bikf8f5a162017-02-06 15:35:29 -0800233void LocationsBuilderMIPS::VisitVecCnv(HVecCnv* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100234 CreateVecUnOpLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikf8f5a162017-02-06 15:35:29 -0800235}
236
237void InstructionCodeGeneratorMIPS::VisitVecCnv(HVecCnv* instruction) {
Lena Djokic51765b02017-06-22 13:49:59 +0200238 LocationSummary* locations = instruction->GetLocations();
239 VectorRegister src = VectorRegisterFrom(locations->InAt(0));
240 VectorRegister dst = VectorRegisterFrom(locations->Out());
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100241 DataType::Type from = instruction->GetInputType();
242 DataType::Type to = instruction->GetResultType();
243 if (from == DataType::Type::kInt32 && to == DataType::Type::kFloat32) {
Lena Djokic51765b02017-06-22 13:49:59 +0200244 DCHECK_EQ(4u, instruction->GetVectorLength());
245 __ Ffint_sW(dst, src);
246 } else {
Aart Bik29aa0822018-03-08 11:28:00 -0800247 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Lena Djokic51765b02017-06-22 13:49:59 +0200248 }
Aart Bikf8f5a162017-02-06 15:35:29 -0800249}
250
251void LocationsBuilderMIPS::VisitVecNeg(HVecNeg* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100252 CreateVecUnOpLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikf8f5a162017-02-06 15:35:29 -0800253}
254
255void InstructionCodeGeneratorMIPS::VisitVecNeg(HVecNeg* instruction) {
Lena Djokic51765b02017-06-22 13:49:59 +0200256 LocationSummary* locations = instruction->GetLocations();
257 VectorRegister src = VectorRegisterFrom(locations->InAt(0));
258 VectorRegister dst = VectorRegisterFrom(locations->Out());
259 switch (instruction->GetPackedType()) {
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100260 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100261 case DataType::Type::kInt8:
Lena Djokic51765b02017-06-22 13:49:59 +0200262 DCHECK_EQ(16u, instruction->GetVectorLength());
263 __ FillB(dst, ZERO);
264 __ SubvB(dst, dst, src);
265 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100266 case DataType::Type::kUint16:
267 case DataType::Type::kInt16:
Lena Djokic51765b02017-06-22 13:49:59 +0200268 DCHECK_EQ(8u, instruction->GetVectorLength());
269 __ FillH(dst, ZERO);
270 __ SubvH(dst, dst, src);
271 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100272 case DataType::Type::kInt32:
Lena Djokic51765b02017-06-22 13:49:59 +0200273 DCHECK_EQ(4u, instruction->GetVectorLength());
274 __ FillW(dst, ZERO);
275 __ SubvW(dst, dst, src);
276 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100277 case DataType::Type::kInt64:
Lena Djokic51765b02017-06-22 13:49:59 +0200278 DCHECK_EQ(2u, instruction->GetVectorLength());
279 __ FillW(dst, ZERO);
280 __ SubvD(dst, dst, src);
281 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100282 case DataType::Type::kFloat32:
Lena Djokic51765b02017-06-22 13:49:59 +0200283 DCHECK_EQ(4u, instruction->GetVectorLength());
284 __ FillW(dst, ZERO);
285 __ FsubW(dst, dst, src);
286 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100287 case DataType::Type::kFloat64:
Lena Djokic51765b02017-06-22 13:49:59 +0200288 DCHECK_EQ(2u, instruction->GetVectorLength());
289 __ FillW(dst, ZERO);
290 __ FsubD(dst, dst, src);
291 break;
292 default:
Aart Bik29aa0822018-03-08 11:28:00 -0800293 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Lena Djokic51765b02017-06-22 13:49:59 +0200294 UNREACHABLE();
295 }
Aart Bikf8f5a162017-02-06 15:35:29 -0800296}
297
Aart Bik6daebeb2017-04-03 14:35:41 -0700298void LocationsBuilderMIPS::VisitVecAbs(HVecAbs* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100299 CreateVecUnOpLocations(GetGraph()->GetAllocator(), instruction);
Aart Bik6daebeb2017-04-03 14:35:41 -0700300}
301
302void InstructionCodeGeneratorMIPS::VisitVecAbs(HVecAbs* instruction) {
Lena Djokic51765b02017-06-22 13:49:59 +0200303 LocationSummary* locations = instruction->GetLocations();
304 VectorRegister src = VectorRegisterFrom(locations->InAt(0));
305 VectorRegister dst = VectorRegisterFrom(locations->Out());
306 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100307 case DataType::Type::kInt8:
Lena Djokic51765b02017-06-22 13:49:59 +0200308 DCHECK_EQ(16u, instruction->GetVectorLength());
309 __ FillB(dst, ZERO); // all zeroes
310 __ Add_aB(dst, dst, src); // dst = abs(0) + abs(src)
311 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100312 case DataType::Type::kInt16:
Lena Djokic51765b02017-06-22 13:49:59 +0200313 DCHECK_EQ(8u, instruction->GetVectorLength());
314 __ FillH(dst, ZERO); // all zeroes
315 __ Add_aH(dst, dst, src); // dst = abs(0) + abs(src)
316 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100317 case DataType::Type::kInt32:
Lena Djokic51765b02017-06-22 13:49:59 +0200318 DCHECK_EQ(4u, instruction->GetVectorLength());
319 __ FillW(dst, ZERO); // all zeroes
320 __ Add_aW(dst, dst, src); // dst = abs(0) + abs(src)
321 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100322 case DataType::Type::kInt64:
Lena Djokic51765b02017-06-22 13:49:59 +0200323 DCHECK_EQ(2u, instruction->GetVectorLength());
324 __ FillW(dst, ZERO); // all zeroes
325 __ Add_aD(dst, dst, src); // dst = abs(0) + abs(src)
326 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100327 case DataType::Type::kFloat32:
Lena Djokic51765b02017-06-22 13:49:59 +0200328 DCHECK_EQ(4u, instruction->GetVectorLength());
329 __ LdiW(dst, -1); // all ones
330 __ SrliW(dst, dst, 1);
331 __ AndV(dst, dst, src);
332 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100333 case DataType::Type::kFloat64:
Lena Djokic51765b02017-06-22 13:49:59 +0200334 DCHECK_EQ(2u, instruction->GetVectorLength());
335 __ LdiD(dst, -1); // all ones
336 __ SrliD(dst, dst, 1);
337 __ AndV(dst, dst, src);
338 break;
339 default:
Aart Bik29aa0822018-03-08 11:28:00 -0800340 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Lena Djokic51765b02017-06-22 13:49:59 +0200341 UNREACHABLE();
342 }
Aart Bik6daebeb2017-04-03 14:35:41 -0700343}
344
Aart Bikf8f5a162017-02-06 15:35:29 -0800345void LocationsBuilderMIPS::VisitVecNot(HVecNot* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100346 CreateVecUnOpLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikf8f5a162017-02-06 15:35:29 -0800347}
348
349void InstructionCodeGeneratorMIPS::VisitVecNot(HVecNot* instruction) {
Lena Djokic51765b02017-06-22 13:49:59 +0200350 LocationSummary* locations = instruction->GetLocations();
351 VectorRegister src = VectorRegisterFrom(locations->InAt(0));
352 VectorRegister dst = VectorRegisterFrom(locations->Out());
353 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100354 case DataType::Type::kBool: // special case boolean-not
Lena Djokic51765b02017-06-22 13:49:59 +0200355 DCHECK_EQ(16u, instruction->GetVectorLength());
356 __ LdiB(dst, 1);
357 __ XorV(dst, dst, src);
358 break;
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100359 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100360 case DataType::Type::kInt8:
361 case DataType::Type::kUint16:
362 case DataType::Type::kInt16:
363 case DataType::Type::kInt32:
364 case DataType::Type::kInt64:
365 case DataType::Type::kFloat32:
366 case DataType::Type::kFloat64:
Lena Djokic51765b02017-06-22 13:49:59 +0200367 DCHECK_LE(2u, instruction->GetVectorLength());
368 DCHECK_LE(instruction->GetVectorLength(), 16u);
369 __ NorV(dst, src, src); // lanes do not matter
370 break;
371 default:
Aart Bik29aa0822018-03-08 11:28:00 -0800372 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Lena Djokic51765b02017-06-22 13:49:59 +0200373 UNREACHABLE();
374 }
Aart Bikf8f5a162017-02-06 15:35:29 -0800375}
376
377// Helper to set up locations for vector binary operations.
Vladimir Markoe764d2e2017-10-05 14:35:55 +0100378static void CreateVecBinOpLocations(ArenaAllocator* allocator, HVecBinaryOperation* instruction) {
379 LocationSummary* locations = new (allocator) LocationSummary(instruction);
Aart Bikf8f5a162017-02-06 15:35:29 -0800380 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100381 case DataType::Type::kBool:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100382 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100383 case DataType::Type::kInt8:
384 case DataType::Type::kUint16:
385 case DataType::Type::kInt16:
386 case DataType::Type::kInt32:
387 case DataType::Type::kInt64:
388 case DataType::Type::kFloat32:
389 case DataType::Type::kFloat64:
Lena Djokic51765b02017-06-22 13:49:59 +0200390 locations->SetInAt(0, Location::RequiresFpuRegister());
391 locations->SetInAt(1, Location::RequiresFpuRegister());
392 locations->SetOut(Location::RequiresFpuRegister(), Location::kNoOutputOverlap);
Aart Bikf8f5a162017-02-06 15:35:29 -0800393 break;
394 default:
Aart Bik29aa0822018-03-08 11:28:00 -0800395 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Aart Bikf8f5a162017-02-06 15:35:29 -0800396 UNREACHABLE();
397 }
398}
399
400void LocationsBuilderMIPS::VisitVecAdd(HVecAdd* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100401 CreateVecBinOpLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikf8f5a162017-02-06 15:35:29 -0800402}
403
404void InstructionCodeGeneratorMIPS::VisitVecAdd(HVecAdd* instruction) {
Lena Djokic51765b02017-06-22 13:49:59 +0200405 LocationSummary* locations = instruction->GetLocations();
406 VectorRegister lhs = VectorRegisterFrom(locations->InAt(0));
407 VectorRegister rhs = VectorRegisterFrom(locations->InAt(1));
408 VectorRegister dst = VectorRegisterFrom(locations->Out());
409 switch (instruction->GetPackedType()) {
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100410 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100411 case DataType::Type::kInt8:
Lena Djokic51765b02017-06-22 13:49:59 +0200412 DCHECK_EQ(16u, instruction->GetVectorLength());
413 __ AddvB(dst, lhs, rhs);
414 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100415 case DataType::Type::kUint16:
416 case DataType::Type::kInt16:
Lena Djokic51765b02017-06-22 13:49:59 +0200417 DCHECK_EQ(8u, instruction->GetVectorLength());
418 __ AddvH(dst, lhs, rhs);
419 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100420 case DataType::Type::kInt32:
Lena Djokic51765b02017-06-22 13:49:59 +0200421 DCHECK_EQ(4u, instruction->GetVectorLength());
422 __ AddvW(dst, lhs, rhs);
423 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100424 case DataType::Type::kInt64:
Lena Djokic51765b02017-06-22 13:49:59 +0200425 DCHECK_EQ(2u, instruction->GetVectorLength());
426 __ AddvD(dst, lhs, rhs);
427 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100428 case DataType::Type::kFloat32:
Lena Djokic51765b02017-06-22 13:49:59 +0200429 DCHECK_EQ(4u, instruction->GetVectorLength());
430 __ FaddW(dst, lhs, rhs);
431 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100432 case DataType::Type::kFloat64:
Lena Djokic51765b02017-06-22 13:49:59 +0200433 DCHECK_EQ(2u, instruction->GetVectorLength());
434 __ FaddD(dst, lhs, rhs);
435 break;
436 default:
Aart Bik29aa0822018-03-08 11:28:00 -0800437 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Lena Djokic51765b02017-06-22 13:49:59 +0200438 UNREACHABLE();
439 }
Aart Bikf8f5a162017-02-06 15:35:29 -0800440}
441
Aart Bik29aa0822018-03-08 11:28:00 -0800442void LocationsBuilderMIPS::VisitVecSaturationAdd(HVecSaturationAdd* instruction) {
443 CreateVecBinOpLocations(GetGraph()->GetAllocator(), instruction);
444}
445
446void InstructionCodeGeneratorMIPS::VisitVecSaturationAdd(HVecSaturationAdd* instruction) {
447 LOG(FATAL) << "Unsupported SIMD " << instruction->GetId();
448}
449
Aart Bikf3e61ee2017-04-12 17:09:20 -0700450void LocationsBuilderMIPS::VisitVecHalvingAdd(HVecHalvingAdd* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100451 CreateVecBinOpLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikf3e61ee2017-04-12 17:09:20 -0700452}
453
454void InstructionCodeGeneratorMIPS::VisitVecHalvingAdd(HVecHalvingAdd* instruction) {
Lena Djokic51765b02017-06-22 13:49:59 +0200455 LocationSummary* locations = instruction->GetLocations();
456 VectorRegister lhs = VectorRegisterFrom(locations->InAt(0));
457 VectorRegister rhs = VectorRegisterFrom(locations->InAt(1));
458 VectorRegister dst = VectorRegisterFrom(locations->Out());
459 switch (instruction->GetPackedType()) {
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100460 case DataType::Type::kUint8:
461 DCHECK_EQ(16u, instruction->GetVectorLength());
462 instruction->IsRounded()
463 ? __ Aver_uB(dst, lhs, rhs)
464 : __ Ave_uB(dst, lhs, rhs);
465 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100466 case DataType::Type::kInt8:
Lena Djokic51765b02017-06-22 13:49:59 +0200467 DCHECK_EQ(16u, instruction->GetVectorLength());
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100468 instruction->IsRounded()
469 ? __ Aver_sB(dst, lhs, rhs)
470 : __ Ave_sB(dst, lhs, rhs);
Lena Djokic51765b02017-06-22 13:49:59 +0200471 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100472 case DataType::Type::kUint16:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100473 DCHECK_EQ(8u, instruction->GetVectorLength());
474 instruction->IsRounded()
475 ? __ Aver_uH(dst, lhs, rhs)
476 : __ Ave_uH(dst, lhs, rhs);
477 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100478 case DataType::Type::kInt16:
Lena Djokic51765b02017-06-22 13:49:59 +0200479 DCHECK_EQ(8u, instruction->GetVectorLength());
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100480 instruction->IsRounded()
481 ? __ Aver_sH(dst, lhs, rhs)
482 : __ Ave_sH(dst, lhs, rhs);
Lena Djokic51765b02017-06-22 13:49:59 +0200483 break;
484 default:
Aart Bik29aa0822018-03-08 11:28:00 -0800485 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Lena Djokic51765b02017-06-22 13:49:59 +0200486 UNREACHABLE();
487 }
Aart Bikf3e61ee2017-04-12 17:09:20 -0700488}
489
Aart Bikf8f5a162017-02-06 15:35:29 -0800490void LocationsBuilderMIPS::VisitVecSub(HVecSub* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100491 CreateVecBinOpLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikf8f5a162017-02-06 15:35:29 -0800492}
493
494void InstructionCodeGeneratorMIPS::VisitVecSub(HVecSub* instruction) {
Lena Djokic51765b02017-06-22 13:49:59 +0200495 LocationSummary* locations = instruction->GetLocations();
496 VectorRegister lhs = VectorRegisterFrom(locations->InAt(0));
497 VectorRegister rhs = VectorRegisterFrom(locations->InAt(1));
498 VectorRegister dst = VectorRegisterFrom(locations->Out());
499 switch (instruction->GetPackedType()) {
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100500 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100501 case DataType::Type::kInt8:
Lena Djokic51765b02017-06-22 13:49:59 +0200502 DCHECK_EQ(16u, instruction->GetVectorLength());
503 __ SubvB(dst, lhs, rhs);
504 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100505 case DataType::Type::kUint16:
506 case DataType::Type::kInt16:
Lena Djokic51765b02017-06-22 13:49:59 +0200507 DCHECK_EQ(8u, instruction->GetVectorLength());
508 __ SubvH(dst, lhs, rhs);
509 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100510 case DataType::Type::kInt32:
Lena Djokic51765b02017-06-22 13:49:59 +0200511 DCHECK_EQ(4u, instruction->GetVectorLength());
512 __ SubvW(dst, lhs, rhs);
513 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100514 case DataType::Type::kInt64:
Lena Djokic51765b02017-06-22 13:49:59 +0200515 DCHECK_EQ(2u, instruction->GetVectorLength());
516 __ SubvD(dst, lhs, rhs);
517 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100518 case DataType::Type::kFloat32:
Lena Djokic51765b02017-06-22 13:49:59 +0200519 DCHECK_EQ(4u, instruction->GetVectorLength());
520 __ FsubW(dst, lhs, rhs);
521 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100522 case DataType::Type::kFloat64:
Lena Djokic51765b02017-06-22 13:49:59 +0200523 DCHECK_EQ(2u, instruction->GetVectorLength());
524 __ FsubD(dst, lhs, rhs);
525 break;
526 default:
Aart Bik29aa0822018-03-08 11:28:00 -0800527 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Lena Djokic51765b02017-06-22 13:49:59 +0200528 UNREACHABLE();
529 }
Aart Bikf8f5a162017-02-06 15:35:29 -0800530}
531
Aart Bik29aa0822018-03-08 11:28:00 -0800532void LocationsBuilderMIPS::VisitVecSaturationSub(HVecSaturationSub* instruction) {
533 CreateVecBinOpLocations(GetGraph()->GetAllocator(), instruction);
534}
535
536void InstructionCodeGeneratorMIPS::VisitVecSaturationSub(HVecSaturationSub* instruction) {
537 LOG(FATAL) << "Unsupported SIMD " << instruction->GetId();
538}
539
Aart Bikf8f5a162017-02-06 15:35:29 -0800540void LocationsBuilderMIPS::VisitVecMul(HVecMul* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100541 CreateVecBinOpLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikf8f5a162017-02-06 15:35:29 -0800542}
543
544void InstructionCodeGeneratorMIPS::VisitVecMul(HVecMul* instruction) {
Lena Djokic51765b02017-06-22 13:49:59 +0200545 LocationSummary* locations = instruction->GetLocations();
546 VectorRegister lhs = VectorRegisterFrom(locations->InAt(0));
547 VectorRegister rhs = VectorRegisterFrom(locations->InAt(1));
548 VectorRegister dst = VectorRegisterFrom(locations->Out());
549 switch (instruction->GetPackedType()) {
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100550 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100551 case DataType::Type::kInt8:
Lena Djokic51765b02017-06-22 13:49:59 +0200552 DCHECK_EQ(16u, instruction->GetVectorLength());
553 __ MulvB(dst, lhs, rhs);
554 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100555 case DataType::Type::kUint16:
556 case DataType::Type::kInt16:
Lena Djokic51765b02017-06-22 13:49:59 +0200557 DCHECK_EQ(8u, instruction->GetVectorLength());
558 __ MulvH(dst, lhs, rhs);
559 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100560 case DataType::Type::kInt32:
Lena Djokic51765b02017-06-22 13:49:59 +0200561 DCHECK_EQ(4u, instruction->GetVectorLength());
562 __ MulvW(dst, lhs, rhs);
563 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100564 case DataType::Type::kInt64:
Lena Djokic51765b02017-06-22 13:49:59 +0200565 DCHECK_EQ(2u, instruction->GetVectorLength());
566 __ MulvD(dst, lhs, rhs);
567 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100568 case DataType::Type::kFloat32:
Lena Djokic51765b02017-06-22 13:49:59 +0200569 DCHECK_EQ(4u, instruction->GetVectorLength());
570 __ FmulW(dst, lhs, rhs);
571 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100572 case DataType::Type::kFloat64:
Lena Djokic51765b02017-06-22 13:49:59 +0200573 DCHECK_EQ(2u, instruction->GetVectorLength());
574 __ FmulD(dst, lhs, rhs);
575 break;
576 default:
Aart Bik29aa0822018-03-08 11:28:00 -0800577 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Lena Djokic51765b02017-06-22 13:49:59 +0200578 UNREACHABLE();
579 }
Aart Bikf8f5a162017-02-06 15:35:29 -0800580}
581
582void LocationsBuilderMIPS::VisitVecDiv(HVecDiv* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100583 CreateVecBinOpLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikf8f5a162017-02-06 15:35:29 -0800584}
585
586void InstructionCodeGeneratorMIPS::VisitVecDiv(HVecDiv* instruction) {
Lena Djokic51765b02017-06-22 13:49:59 +0200587 LocationSummary* locations = instruction->GetLocations();
588 VectorRegister lhs = VectorRegisterFrom(locations->InAt(0));
589 VectorRegister rhs = VectorRegisterFrom(locations->InAt(1));
590 VectorRegister dst = VectorRegisterFrom(locations->Out());
591 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100592 case DataType::Type::kFloat32:
Lena Djokic51765b02017-06-22 13:49:59 +0200593 DCHECK_EQ(4u, instruction->GetVectorLength());
594 __ FdivW(dst, lhs, rhs);
595 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100596 case DataType::Type::kFloat64:
Lena Djokic51765b02017-06-22 13:49:59 +0200597 DCHECK_EQ(2u, instruction->GetVectorLength());
598 __ FdivD(dst, lhs, rhs);
599 break;
600 default:
Aart Bik29aa0822018-03-08 11:28:00 -0800601 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Lena Djokic51765b02017-06-22 13:49:59 +0200602 UNREACHABLE();
603 }
Aart Bikf8f5a162017-02-06 15:35:29 -0800604}
605
Aart Bikf3e61ee2017-04-12 17:09:20 -0700606void LocationsBuilderMIPS::VisitVecMin(HVecMin* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100607 CreateVecBinOpLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikf3e61ee2017-04-12 17:09:20 -0700608}
609
610void InstructionCodeGeneratorMIPS::VisitVecMin(HVecMin* instruction) {
Lena Djokic51765b02017-06-22 13:49:59 +0200611 LocationSummary* locations = instruction->GetLocations();
612 VectorRegister lhs = VectorRegisterFrom(locations->InAt(0));
613 VectorRegister rhs = VectorRegisterFrom(locations->InAt(1));
614 VectorRegister dst = VectorRegisterFrom(locations->Out());
615 switch (instruction->GetPackedType()) {
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100616 case DataType::Type::kUint8:
617 DCHECK_EQ(16u, instruction->GetVectorLength());
618 __ Min_uB(dst, lhs, rhs);
619 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100620 case DataType::Type::kInt8:
Lena Djokic51765b02017-06-22 13:49:59 +0200621 DCHECK_EQ(16u, instruction->GetVectorLength());
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100622 __ Min_sB(dst, lhs, rhs);
Lena Djokic51765b02017-06-22 13:49:59 +0200623 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100624 case DataType::Type::kUint16:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100625 DCHECK_EQ(8u, instruction->GetVectorLength());
626 __ Min_uH(dst, lhs, rhs);
627 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100628 case DataType::Type::kInt16:
Lena Djokic51765b02017-06-22 13:49:59 +0200629 DCHECK_EQ(8u, instruction->GetVectorLength());
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100630 __ Min_sH(dst, lhs, rhs);
Lena Djokic51765b02017-06-22 13:49:59 +0200631 break;
Aart Bik66c158e2018-01-31 12:55:04 -0800632 case DataType::Type::kUint32:
633 DCHECK_EQ(4u, instruction->GetVectorLength());
634 __ Min_uW(dst, lhs, rhs);
635 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100636 case DataType::Type::kInt32:
Lena Djokic51765b02017-06-22 13:49:59 +0200637 DCHECK_EQ(4u, instruction->GetVectorLength());
Aart Bik66c158e2018-01-31 12:55:04 -0800638 __ Min_sW(dst, lhs, rhs);
639 break;
640 case DataType::Type::kUint64:
641 DCHECK_EQ(2u, instruction->GetVectorLength());
642 __ Min_uD(dst, lhs, rhs);
Lena Djokic51765b02017-06-22 13:49:59 +0200643 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100644 case DataType::Type::kInt64:
Lena Djokic51765b02017-06-22 13:49:59 +0200645 DCHECK_EQ(2u, instruction->GetVectorLength());
Aart Bik66c158e2018-01-31 12:55:04 -0800646 __ Min_sD(dst, lhs, rhs);
Lena Djokic51765b02017-06-22 13:49:59 +0200647 break;
648 // When one of arguments is NaN, fmin.df returns other argument, but Java expects a NaN value.
649 // TODO: Fix min(x, NaN) cases for float and double.
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100650 case DataType::Type::kFloat32:
Lena Djokic51765b02017-06-22 13:49:59 +0200651 DCHECK_EQ(4u, instruction->GetVectorLength());
Lena Djokic51765b02017-06-22 13:49:59 +0200652 __ FminW(dst, lhs, rhs);
653 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100654 case DataType::Type::kFloat64:
Lena Djokic51765b02017-06-22 13:49:59 +0200655 DCHECK_EQ(2u, instruction->GetVectorLength());
Lena Djokic51765b02017-06-22 13:49:59 +0200656 __ FminD(dst, lhs, rhs);
657 break;
658 default:
Aart Bik29aa0822018-03-08 11:28:00 -0800659 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Lena Djokic51765b02017-06-22 13:49:59 +0200660 UNREACHABLE();
661 }
Aart Bikf3e61ee2017-04-12 17:09:20 -0700662}
663
664void LocationsBuilderMIPS::VisitVecMax(HVecMax* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100665 CreateVecBinOpLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikf3e61ee2017-04-12 17:09:20 -0700666}
667
668void InstructionCodeGeneratorMIPS::VisitVecMax(HVecMax* instruction) {
Lena Djokic51765b02017-06-22 13:49:59 +0200669 LocationSummary* locations = instruction->GetLocations();
670 VectorRegister lhs = VectorRegisterFrom(locations->InAt(0));
671 VectorRegister rhs = VectorRegisterFrom(locations->InAt(1));
672 VectorRegister dst = VectorRegisterFrom(locations->Out());
673 switch (instruction->GetPackedType()) {
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100674 case DataType::Type::kUint8:
675 DCHECK_EQ(16u, instruction->GetVectorLength());
676 __ Max_uB(dst, lhs, rhs);
677 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100678 case DataType::Type::kInt8:
Lena Djokic51765b02017-06-22 13:49:59 +0200679 DCHECK_EQ(16u, instruction->GetVectorLength());
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100680 __ Max_sB(dst, lhs, rhs);
Lena Djokic51765b02017-06-22 13:49:59 +0200681 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100682 case DataType::Type::kUint16:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100683 DCHECK_EQ(8u, instruction->GetVectorLength());
684 __ Max_uH(dst, lhs, rhs);
685 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100686 case DataType::Type::kInt16:
Lena Djokic51765b02017-06-22 13:49:59 +0200687 DCHECK_EQ(8u, instruction->GetVectorLength());
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100688 __ Max_sH(dst, lhs, rhs);
Lena Djokic51765b02017-06-22 13:49:59 +0200689 break;
Aart Bik66c158e2018-01-31 12:55:04 -0800690 case DataType::Type::kUint32:
691 DCHECK_EQ(4u, instruction->GetVectorLength());
692 __ Max_uW(dst, lhs, rhs);
693 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100694 case DataType::Type::kInt32:
Lena Djokic51765b02017-06-22 13:49:59 +0200695 DCHECK_EQ(4u, instruction->GetVectorLength());
Aart Bik66c158e2018-01-31 12:55:04 -0800696 __ Max_sW(dst, lhs, rhs);
697 break;
698 case DataType::Type::kUint64:
699 DCHECK_EQ(2u, instruction->GetVectorLength());
700 __ Max_uD(dst, lhs, rhs);
Lena Djokic51765b02017-06-22 13:49:59 +0200701 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100702 case DataType::Type::kInt64:
Lena Djokic51765b02017-06-22 13:49:59 +0200703 DCHECK_EQ(2u, instruction->GetVectorLength());
Aart Bik66c158e2018-01-31 12:55:04 -0800704 __ Max_sD(dst, lhs, rhs);
Lena Djokic51765b02017-06-22 13:49:59 +0200705 break;
706 // When one of arguments is NaN, fmax.df returns other argument, but Java expects a NaN value.
707 // TODO: Fix max(x, NaN) cases for float and double.
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100708 case DataType::Type::kFloat32:
Lena Djokic51765b02017-06-22 13:49:59 +0200709 DCHECK_EQ(4u, instruction->GetVectorLength());
Lena Djokic51765b02017-06-22 13:49:59 +0200710 __ FmaxW(dst, lhs, rhs);
711 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100712 case DataType::Type::kFloat64:
Lena Djokic51765b02017-06-22 13:49:59 +0200713 DCHECK_EQ(2u, instruction->GetVectorLength());
Lena Djokic51765b02017-06-22 13:49:59 +0200714 __ FmaxD(dst, lhs, rhs);
715 break;
716 default:
Aart Bik29aa0822018-03-08 11:28:00 -0800717 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Lena Djokic51765b02017-06-22 13:49:59 +0200718 UNREACHABLE();
719 }
Aart Bikf3e61ee2017-04-12 17:09:20 -0700720}
721
Aart Bikf8f5a162017-02-06 15:35:29 -0800722void LocationsBuilderMIPS::VisitVecAnd(HVecAnd* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100723 CreateVecBinOpLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikf8f5a162017-02-06 15:35:29 -0800724}
725
726void InstructionCodeGeneratorMIPS::VisitVecAnd(HVecAnd* instruction) {
Lena Djokic51765b02017-06-22 13:49:59 +0200727 LocationSummary* locations = instruction->GetLocations();
728 VectorRegister lhs = VectorRegisterFrom(locations->InAt(0));
729 VectorRegister rhs = VectorRegisterFrom(locations->InAt(1));
730 VectorRegister dst = VectorRegisterFrom(locations->Out());
731 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100732 case DataType::Type::kBool:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100733 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100734 case DataType::Type::kInt8:
735 case DataType::Type::kUint16:
736 case DataType::Type::kInt16:
737 case DataType::Type::kInt32:
738 case DataType::Type::kInt64:
739 case DataType::Type::kFloat32:
740 case DataType::Type::kFloat64:
Lena Djokic51765b02017-06-22 13:49:59 +0200741 DCHECK_LE(2u, instruction->GetVectorLength());
742 DCHECK_LE(instruction->GetVectorLength(), 16u);
743 __ AndV(dst, lhs, rhs); // lanes do not matter
744 break;
745 default:
Aart Bik29aa0822018-03-08 11:28:00 -0800746 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Lena Djokic51765b02017-06-22 13:49:59 +0200747 UNREACHABLE();
748 }
Aart Bikf8f5a162017-02-06 15:35:29 -0800749}
750
751void LocationsBuilderMIPS::VisitVecAndNot(HVecAndNot* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100752 CreateVecBinOpLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikf8f5a162017-02-06 15:35:29 -0800753}
754
755void InstructionCodeGeneratorMIPS::VisitVecAndNot(HVecAndNot* instruction) {
756 LOG(FATAL) << "No SIMD for " << instruction->GetId();
757}
758
759void LocationsBuilderMIPS::VisitVecOr(HVecOr* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100760 CreateVecBinOpLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikf8f5a162017-02-06 15:35:29 -0800761}
762
763void InstructionCodeGeneratorMIPS::VisitVecOr(HVecOr* instruction) {
Lena Djokic51765b02017-06-22 13:49:59 +0200764 LocationSummary* locations = instruction->GetLocations();
765 VectorRegister lhs = VectorRegisterFrom(locations->InAt(0));
766 VectorRegister rhs = VectorRegisterFrom(locations->InAt(1));
767 VectorRegister dst = VectorRegisterFrom(locations->Out());
768 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100769 case DataType::Type::kBool:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100770 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100771 case DataType::Type::kInt8:
772 case DataType::Type::kUint16:
773 case DataType::Type::kInt16:
774 case DataType::Type::kInt32:
775 case DataType::Type::kInt64:
776 case DataType::Type::kFloat32:
777 case DataType::Type::kFloat64:
Lena Djokic51765b02017-06-22 13:49:59 +0200778 DCHECK_LE(2u, instruction->GetVectorLength());
779 DCHECK_LE(instruction->GetVectorLength(), 16u);
780 __ OrV(dst, lhs, rhs); // lanes do not matter
781 break;
782 default:
Aart Bik29aa0822018-03-08 11:28:00 -0800783 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Lena Djokic51765b02017-06-22 13:49:59 +0200784 UNREACHABLE();
785 }
Aart Bikf8f5a162017-02-06 15:35:29 -0800786}
787
788void LocationsBuilderMIPS::VisitVecXor(HVecXor* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100789 CreateVecBinOpLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikf8f5a162017-02-06 15:35:29 -0800790}
791
792void InstructionCodeGeneratorMIPS::VisitVecXor(HVecXor* instruction) {
Lena Djokic51765b02017-06-22 13:49:59 +0200793 LocationSummary* locations = instruction->GetLocations();
794 VectorRegister lhs = VectorRegisterFrom(locations->InAt(0));
795 VectorRegister rhs = VectorRegisterFrom(locations->InAt(1));
796 VectorRegister dst = VectorRegisterFrom(locations->Out());
797 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100798 case DataType::Type::kBool:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100799 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100800 case DataType::Type::kInt8:
801 case DataType::Type::kUint16:
802 case DataType::Type::kInt16:
803 case DataType::Type::kInt32:
804 case DataType::Type::kInt64:
805 case DataType::Type::kFloat32:
806 case DataType::Type::kFloat64:
Lena Djokic51765b02017-06-22 13:49:59 +0200807 DCHECK_LE(2u, instruction->GetVectorLength());
808 DCHECK_LE(instruction->GetVectorLength(), 16u);
809 __ XorV(dst, lhs, rhs); // lanes do not matter
810 break;
811 default:
Aart Bik29aa0822018-03-08 11:28:00 -0800812 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Lena Djokic51765b02017-06-22 13:49:59 +0200813 UNREACHABLE();
814 }
Aart Bikf8f5a162017-02-06 15:35:29 -0800815}
816
817// Helper to set up locations for vector shift operations.
Vladimir Markoe764d2e2017-10-05 14:35:55 +0100818static void CreateVecShiftLocations(ArenaAllocator* allocator, HVecBinaryOperation* instruction) {
819 LocationSummary* locations = new (allocator) LocationSummary(instruction);
Aart Bikf8f5a162017-02-06 15:35:29 -0800820 switch (instruction->GetPackedType()) {
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100821 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100822 case DataType::Type::kInt8:
823 case DataType::Type::kUint16:
824 case DataType::Type::kInt16:
825 case DataType::Type::kInt32:
826 case DataType::Type::kInt64:
Lena Djokic51765b02017-06-22 13:49:59 +0200827 locations->SetInAt(0, Location::RequiresFpuRegister());
828 locations->SetInAt(1, Location::ConstantLocation(instruction->InputAt(1)->AsConstant()));
829 locations->SetOut(Location::RequiresFpuRegister(), Location::kNoOutputOverlap);
Aart Bikf8f5a162017-02-06 15:35:29 -0800830 break;
831 default:
Aart Bik29aa0822018-03-08 11:28:00 -0800832 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Aart Bikf8f5a162017-02-06 15:35:29 -0800833 UNREACHABLE();
834 }
835}
836
837void LocationsBuilderMIPS::VisitVecShl(HVecShl* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100838 CreateVecShiftLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikf8f5a162017-02-06 15:35:29 -0800839}
840
841void InstructionCodeGeneratorMIPS::VisitVecShl(HVecShl* instruction) {
Lena Djokic51765b02017-06-22 13:49:59 +0200842 LocationSummary* locations = instruction->GetLocations();
843 VectorRegister lhs = VectorRegisterFrom(locations->InAt(0));
844 VectorRegister dst = VectorRegisterFrom(locations->Out());
845 int32_t value = locations->InAt(1).GetConstant()->AsIntConstant()->GetValue();
846 switch (instruction->GetPackedType()) {
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100847 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100848 case DataType::Type::kInt8:
Lena Djokic51765b02017-06-22 13:49:59 +0200849 DCHECK_EQ(16u, instruction->GetVectorLength());
850 __ SlliB(dst, lhs, value);
851 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100852 case DataType::Type::kUint16:
853 case DataType::Type::kInt16:
Lena Djokic51765b02017-06-22 13:49:59 +0200854 DCHECK_EQ(8u, instruction->GetVectorLength());
855 __ SlliH(dst, lhs, value);
856 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100857 case DataType::Type::kInt32:
Lena Djokic51765b02017-06-22 13:49:59 +0200858 DCHECK_EQ(4u, instruction->GetVectorLength());
859 __ SlliW(dst, lhs, value);
860 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100861 case DataType::Type::kInt64:
Lena Djokic51765b02017-06-22 13:49:59 +0200862 DCHECK_EQ(2u, instruction->GetVectorLength());
863 __ SlliD(dst, lhs, value);
864 break;
865 default:
Aart Bik29aa0822018-03-08 11:28:00 -0800866 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Lena Djokic51765b02017-06-22 13:49:59 +0200867 UNREACHABLE();
868 }
Aart Bikf8f5a162017-02-06 15:35:29 -0800869}
870
871void LocationsBuilderMIPS::VisitVecShr(HVecShr* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100872 CreateVecShiftLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikf8f5a162017-02-06 15:35:29 -0800873}
874
875void InstructionCodeGeneratorMIPS::VisitVecShr(HVecShr* instruction) {
Lena Djokic51765b02017-06-22 13:49:59 +0200876 LocationSummary* locations = instruction->GetLocations();
877 VectorRegister lhs = VectorRegisterFrom(locations->InAt(0));
878 VectorRegister dst = VectorRegisterFrom(locations->Out());
879 int32_t value = locations->InAt(1).GetConstant()->AsIntConstant()->GetValue();
880 switch (instruction->GetPackedType()) {
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100881 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100882 case DataType::Type::kInt8:
Lena Djokic51765b02017-06-22 13:49:59 +0200883 DCHECK_EQ(16u, instruction->GetVectorLength());
884 __ SraiB(dst, lhs, value);
885 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100886 case DataType::Type::kUint16:
887 case DataType::Type::kInt16:
Lena Djokic51765b02017-06-22 13:49:59 +0200888 DCHECK_EQ(8u, instruction->GetVectorLength());
889 __ SraiH(dst, lhs, value);
890 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100891 case DataType::Type::kInt32:
Lena Djokic51765b02017-06-22 13:49:59 +0200892 DCHECK_EQ(4u, instruction->GetVectorLength());
893 __ SraiW(dst, lhs, value);
894 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100895 case DataType::Type::kInt64:
Lena Djokic51765b02017-06-22 13:49:59 +0200896 DCHECK_EQ(2u, instruction->GetVectorLength());
897 __ SraiD(dst, lhs, value);
898 break;
899 default:
Aart Bik29aa0822018-03-08 11:28:00 -0800900 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Lena Djokic51765b02017-06-22 13:49:59 +0200901 UNREACHABLE();
902 }
Aart Bikf8f5a162017-02-06 15:35:29 -0800903}
904
905void LocationsBuilderMIPS::VisitVecUShr(HVecUShr* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100906 CreateVecShiftLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikf8f5a162017-02-06 15:35:29 -0800907}
908
909void InstructionCodeGeneratorMIPS::VisitVecUShr(HVecUShr* instruction) {
Lena Djokic51765b02017-06-22 13:49:59 +0200910 LocationSummary* locations = instruction->GetLocations();
911 VectorRegister lhs = VectorRegisterFrom(locations->InAt(0));
912 VectorRegister dst = VectorRegisterFrom(locations->Out());
913 int32_t value = locations->InAt(1).GetConstant()->AsIntConstant()->GetValue();
914 switch (instruction->GetPackedType()) {
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100915 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100916 case DataType::Type::kInt8:
Lena Djokic51765b02017-06-22 13:49:59 +0200917 DCHECK_EQ(16u, instruction->GetVectorLength());
918 __ SrliB(dst, lhs, value);
919 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100920 case DataType::Type::kUint16:
921 case DataType::Type::kInt16:
Lena Djokic51765b02017-06-22 13:49:59 +0200922 DCHECK_EQ(8u, instruction->GetVectorLength());
923 __ SrliH(dst, lhs, value);
924 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100925 case DataType::Type::kInt32:
Lena Djokic51765b02017-06-22 13:49:59 +0200926 DCHECK_EQ(4u, instruction->GetVectorLength());
927 __ SrliW(dst, lhs, value);
928 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100929 case DataType::Type::kInt64:
Lena Djokic51765b02017-06-22 13:49:59 +0200930 DCHECK_EQ(2u, instruction->GetVectorLength());
931 __ SrliD(dst, lhs, value);
932 break;
933 default:
Aart Bik29aa0822018-03-08 11:28:00 -0800934 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Lena Djokic51765b02017-06-22 13:49:59 +0200935 UNREACHABLE();
936 }
Aart Bikf8f5a162017-02-06 15:35:29 -0800937}
938
Aart Bik0148de42017-09-05 09:25:01 -0700939void LocationsBuilderMIPS::VisitVecSetScalars(HVecSetScalars* instruction) {
Lena Djokice434c4f2017-10-23 16:40:22 +0200940 LocationSummary* locations = new (GetGraph()->GetAllocator()) LocationSummary(instruction);
941
942 DCHECK_EQ(1u, instruction->InputCount()); // only one input currently implemented
943
944 HInstruction* input = instruction->InputAt(0);
945 bool is_zero = IsZeroBitPattern(input);
946
947 switch (instruction->GetPackedType()) {
948 case DataType::Type::kBool:
949 case DataType::Type::kUint8:
950 case DataType::Type::kInt8:
951 case DataType::Type::kUint16:
952 case DataType::Type::kInt16:
953 case DataType::Type::kInt32:
954 case DataType::Type::kInt64:
955 locations->SetInAt(0, is_zero ? Location::ConstantLocation(input->AsConstant())
956 : Location::RequiresRegister());
957 locations->SetOut(Location::RequiresFpuRegister());
958 break;
959 case DataType::Type::kFloat32:
960 case DataType::Type::kFloat64:
961 locations->SetInAt(0, is_zero ? Location::ConstantLocation(input->AsConstant())
962 : Location::RequiresFpuRegister());
963 locations->SetOut(Location::RequiresFpuRegister());
964 break;
965 default:
Aart Bik29aa0822018-03-08 11:28:00 -0800966 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Lena Djokice434c4f2017-10-23 16:40:22 +0200967 UNREACHABLE();
968 }
Aart Bik0148de42017-09-05 09:25:01 -0700969}
970
971void InstructionCodeGeneratorMIPS::VisitVecSetScalars(HVecSetScalars* instruction) {
Lena Djokice434c4f2017-10-23 16:40:22 +0200972 LocationSummary* locations = instruction->GetLocations();
973 VectorRegister dst = VectorRegisterFrom(locations->Out());
974
975 DCHECK_EQ(1u, instruction->InputCount()); // only one input currently implemented
976
977 // Zero out all other elements first.
978 __ FillW(dst, ZERO);
979
980 // Shorthand for any type of zero.
981 if (IsZeroBitPattern(instruction->InputAt(0))) {
982 return;
983 }
984
985 // Set required elements.
986 switch (instruction->GetPackedType()) {
987 case DataType::Type::kBool:
988 case DataType::Type::kUint8:
989 case DataType::Type::kInt8:
990 DCHECK_EQ(16u, instruction->GetVectorLength());
991 __ InsertB(dst, locations->InAt(0).AsRegister<Register>(), 0);
992 break;
993 case DataType::Type::kUint16:
994 case DataType::Type::kInt16:
995 DCHECK_EQ(8u, instruction->GetVectorLength());
996 __ InsertH(dst, locations->InAt(0).AsRegister<Register>(), 0);
997 break;
998 case DataType::Type::kInt32:
999 DCHECK_EQ(4u, instruction->GetVectorLength());
1000 __ InsertW(dst, locations->InAt(0).AsRegister<Register>(), 0);
1001 break;
1002 case DataType::Type::kInt64:
1003 DCHECK_EQ(2u, instruction->GetVectorLength());
Goran Jakovljevic7a0222e2017-11-08 10:16:37 +01001004 __ InsertW(dst, locations->InAt(0).AsRegisterPairLow<Register>(), 0);
1005 __ InsertW(dst, locations->InAt(0).AsRegisterPairHigh<Register>(), 1);
Lena Djokice434c4f2017-10-23 16:40:22 +02001006 break;
1007 default:
Aart Bik29aa0822018-03-08 11:28:00 -08001008 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Lena Djokice434c4f2017-10-23 16:40:22 +02001009 UNREACHABLE();
1010 }
Aart Bik0148de42017-09-05 09:25:01 -07001011}
1012
Aart Bikdbbac8f2017-09-01 13:06:08 -07001013// Helper to set up locations for vector accumulations.
Vladimir Markoe764d2e2017-10-05 14:35:55 +01001014static void CreateVecAccumLocations(ArenaAllocator* allocator, HVecOperation* instruction) {
1015 LocationSummary* locations = new (allocator) LocationSummary(instruction);
Aart Bikdbbac8f2017-09-01 13:06:08 -07001016 switch (instruction->GetPackedType()) {
Vladimir Markod5d2f2c2017-09-26 12:37:26 +01001017 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001018 case DataType::Type::kInt8:
1019 case DataType::Type::kUint16:
1020 case DataType::Type::kInt16:
1021 case DataType::Type::kInt32:
1022 case DataType::Type::kInt64:
Aart Bikdbbac8f2017-09-01 13:06:08 -07001023 locations->SetInAt(0, Location::RequiresFpuRegister());
1024 locations->SetInAt(1, Location::RequiresFpuRegister());
1025 locations->SetInAt(2, Location::RequiresFpuRegister());
Lena Djokicbc5460b2017-07-20 16:07:36 +02001026 locations->SetOut(Location::SameAsFirstInput());
1027 break;
1028 default:
Aart Bik29aa0822018-03-08 11:28:00 -08001029 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Lena Djokicbc5460b2017-07-20 16:07:36 +02001030 UNREACHABLE();
1031 }
Artem Serovf34dd202017-04-10 17:41:46 +01001032}
1033
Aart Bikdbbac8f2017-09-01 13:06:08 -07001034void LocationsBuilderMIPS::VisitVecMultiplyAccumulate(HVecMultiplyAccumulate* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +01001035 CreateVecAccumLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikdbbac8f2017-09-01 13:06:08 -07001036}
1037
1038void InstructionCodeGeneratorMIPS::VisitVecMultiplyAccumulate(HVecMultiplyAccumulate* instruction) {
1039 LocationSummary* locations = instruction->GetLocations();
1040 VectorRegister acc = VectorRegisterFrom(locations->InAt(0));
1041 VectorRegister left = VectorRegisterFrom(locations->InAt(1));
1042 VectorRegister right = VectorRegisterFrom(locations->InAt(2));
1043 switch (instruction->GetPackedType()) {
Vladimir Markod5d2f2c2017-09-26 12:37:26 +01001044 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001045 case DataType::Type::kInt8:
Aart Bikdbbac8f2017-09-01 13:06:08 -07001046 DCHECK_EQ(16u, instruction->GetVectorLength());
1047 if (instruction->GetOpKind() == HInstruction::kAdd) {
Lena Djokicbc5460b2017-07-20 16:07:36 +02001048 __ MaddvB(acc, left, right);
1049 } else {
1050 __ MsubvB(acc, left, right);
1051 }
1052 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001053 case DataType::Type::kUint16:
1054 case DataType::Type::kInt16:
Aart Bikdbbac8f2017-09-01 13:06:08 -07001055 DCHECK_EQ(8u, instruction->GetVectorLength());
1056 if (instruction->GetOpKind() == HInstruction::kAdd) {
Lena Djokicbc5460b2017-07-20 16:07:36 +02001057 __ MaddvH(acc, left, right);
1058 } else {
1059 __ MsubvH(acc, left, right);
1060 }
1061 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001062 case DataType::Type::kInt32:
Aart Bikdbbac8f2017-09-01 13:06:08 -07001063 DCHECK_EQ(4u, instruction->GetVectorLength());
1064 if (instruction->GetOpKind() == HInstruction::kAdd) {
Lena Djokicbc5460b2017-07-20 16:07:36 +02001065 __ MaddvW(acc, left, right);
1066 } else {
1067 __ MsubvW(acc, left, right);
1068 }
1069 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001070 case DataType::Type::kInt64:
Aart Bikdbbac8f2017-09-01 13:06:08 -07001071 DCHECK_EQ(2u, instruction->GetVectorLength());
1072 if (instruction->GetOpKind() == HInstruction::kAdd) {
Lena Djokicbc5460b2017-07-20 16:07:36 +02001073 __ MaddvD(acc, left, right);
1074 } else {
1075 __ MsubvD(acc, left, right);
1076 }
1077 break;
1078 default:
Aart Bik29aa0822018-03-08 11:28:00 -08001079 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Lena Djokicbc5460b2017-07-20 16:07:36 +02001080 UNREACHABLE();
1081 }
Artem Serovf34dd202017-04-10 17:41:46 +01001082}
1083
Aart Bikdbbac8f2017-09-01 13:06:08 -07001084void LocationsBuilderMIPS::VisitVecSADAccumulate(HVecSADAccumulate* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +01001085 CreateVecAccumLocations(GetGraph()->GetAllocator(), instruction);
Lena Djokic38e380b2017-10-30 16:17:10 +01001086 LocationSummary* locations = instruction->GetLocations();
1087 // All conversions require at least one temporary register.
1088 locations->AddTemp(Location::RequiresFpuRegister());
1089 // Some conversions require a second temporary register.
1090 HVecOperation* a = instruction->InputAt(1)->AsVecOperation();
1091 HVecOperation* b = instruction->InputAt(2)->AsVecOperation();
1092 DCHECK_EQ(HVecOperation::ToSignedType(a->GetPackedType()),
1093 HVecOperation::ToSignedType(b->GetPackedType()));
1094 switch (a->GetPackedType()) {
1095 case DataType::Type::kInt32:
1096 if (instruction->GetPackedType() == DataType::Type::kInt32) {
1097 break;
1098 }
1099 FALLTHROUGH_INTENDED;
1100 case DataType::Type::kUint8:
1101 case DataType::Type::kInt8:
1102 case DataType::Type::kUint16:
1103 case DataType::Type::kInt16:
1104 locations->AddTemp(Location::RequiresFpuRegister());
1105 break;
1106 default:
1107 break;
1108 }
Aart Bikdbbac8f2017-09-01 13:06:08 -07001109}
1110
1111void InstructionCodeGeneratorMIPS::VisitVecSADAccumulate(HVecSADAccumulate* instruction) {
Lena Djokic38e380b2017-10-30 16:17:10 +01001112 LocationSummary* locations = instruction->GetLocations();
1113 VectorRegister acc = VectorRegisterFrom(locations->InAt(0));
1114 VectorRegister left = VectorRegisterFrom(locations->InAt(1));
1115 VectorRegister right = VectorRegisterFrom(locations->InAt(2));
1116 VectorRegister tmp = static_cast<VectorRegister>(FTMP);
1117 VectorRegister tmp1 = VectorRegisterFrom(locations->GetTemp(0));
1118
1119 DCHECK(locations->InAt(0).Equals(locations->Out()));
1120
1121 // Handle all feasible acc_T += sad(a_S, b_S) type combinations (T x S).
1122 HVecOperation* a = instruction->InputAt(1)->AsVecOperation();
1123 HVecOperation* b = instruction->InputAt(2)->AsVecOperation();
1124 DCHECK_EQ(HVecOperation::ToSignedType(a->GetPackedType()),
1125 HVecOperation::ToSignedType(b->GetPackedType()));
1126 switch (a->GetPackedType()) {
1127 case DataType::Type::kUint8:
1128 case DataType::Type::kInt8:
1129 DCHECK_EQ(16u, a->GetVectorLength());
1130 switch (instruction->GetPackedType()) {
1131 case DataType::Type::kUint16:
1132 case DataType::Type::kInt16: {
1133 DCHECK_EQ(8u, instruction->GetVectorLength());
1134 VectorRegister tmp2 = VectorRegisterFrom(locations->GetTemp(1));
1135 __ FillB(tmp, ZERO);
1136 __ Hadd_sH(tmp1, left, tmp);
1137 __ Hadd_sH(tmp2, right, tmp);
1138 __ Asub_sH(tmp1, tmp1, tmp2);
1139 __ AddvH(acc, acc, tmp1);
1140 __ Hadd_sH(tmp1, tmp, left);
1141 __ Hadd_sH(tmp2, tmp, right);
1142 __ Asub_sH(tmp1, tmp1, tmp2);
1143 __ AddvH(acc, acc, tmp1);
1144 break;
1145 }
1146 case DataType::Type::kInt32: {
1147 DCHECK_EQ(4u, instruction->GetVectorLength());
1148 VectorRegister tmp2 = VectorRegisterFrom(locations->GetTemp(1));
1149 __ FillB(tmp, ZERO);
1150 __ Hadd_sH(tmp1, left, tmp);
1151 __ Hadd_sH(tmp2, right, tmp);
1152 __ Asub_sH(tmp1, tmp1, tmp2);
1153 __ Hadd_sW(tmp1, tmp1, tmp1);
1154 __ AddvW(acc, acc, tmp1);
1155 __ Hadd_sH(tmp1, tmp, left);
1156 __ Hadd_sH(tmp2, tmp, right);
1157 __ Asub_sH(tmp1, tmp1, tmp2);
1158 __ Hadd_sW(tmp1, tmp1, tmp1);
1159 __ AddvW(acc, acc, tmp1);
1160 break;
1161 }
1162 case DataType::Type::kInt64: {
1163 DCHECK_EQ(2u, instruction->GetVectorLength());
1164 VectorRegister tmp2 = VectorRegisterFrom(locations->GetTemp(1));
1165 __ FillB(tmp, ZERO);
1166 __ Hadd_sH(tmp1, left, tmp);
1167 __ Hadd_sH(tmp2, right, tmp);
1168 __ Asub_sH(tmp1, tmp1, tmp2);
1169 __ Hadd_sW(tmp1, tmp1, tmp1);
1170 __ Hadd_sD(tmp1, tmp1, tmp1);
1171 __ AddvD(acc, acc, tmp1);
1172 __ Hadd_sH(tmp1, tmp, left);
1173 __ Hadd_sH(tmp2, tmp, right);
1174 __ Asub_sH(tmp1, tmp1, tmp2);
1175 __ Hadd_sW(tmp1, tmp1, tmp1);
1176 __ Hadd_sD(tmp1, tmp1, tmp1);
1177 __ AddvD(acc, acc, tmp1);
1178 break;
1179 }
1180 default:
Aart Bik29aa0822018-03-08 11:28:00 -08001181 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Lena Djokic38e380b2017-10-30 16:17:10 +01001182 UNREACHABLE();
1183 }
1184 break;
1185 case DataType::Type::kUint16:
1186 case DataType::Type::kInt16:
1187 DCHECK_EQ(8u, a->GetVectorLength());
1188 switch (instruction->GetPackedType()) {
1189 case DataType::Type::kInt32: {
1190 DCHECK_EQ(4u, instruction->GetVectorLength());
1191 VectorRegister tmp2 = VectorRegisterFrom(locations->GetTemp(1));
1192 __ FillH(tmp, ZERO);
1193 __ Hadd_sW(tmp1, left, tmp);
1194 __ Hadd_sW(tmp2, right, tmp);
1195 __ Asub_sW(tmp1, tmp1, tmp2);
1196 __ AddvW(acc, acc, tmp1);
1197 __ Hadd_sW(tmp1, tmp, left);
1198 __ Hadd_sW(tmp2, tmp, right);
1199 __ Asub_sW(tmp1, tmp1, tmp2);
1200 __ AddvW(acc, acc, tmp1);
1201 break;
1202 }
1203 case DataType::Type::kInt64: {
1204 DCHECK_EQ(2u, instruction->GetVectorLength());
1205 VectorRegister tmp2 = VectorRegisterFrom(locations->GetTemp(1));
1206 __ FillH(tmp, ZERO);
1207 __ Hadd_sW(tmp1, left, tmp);
1208 __ Hadd_sW(tmp2, right, tmp);
1209 __ Asub_sW(tmp1, tmp1, tmp2);
1210 __ Hadd_sD(tmp1, tmp1, tmp1);
1211 __ AddvD(acc, acc, tmp1);
1212 __ Hadd_sW(tmp1, tmp, left);
1213 __ Hadd_sW(tmp2, tmp, right);
1214 __ Asub_sW(tmp1, tmp1, tmp2);
1215 __ Hadd_sD(tmp1, tmp1, tmp1);
1216 __ AddvD(acc, acc, tmp1);
1217 break;
1218 }
1219 default:
Aart Bik29aa0822018-03-08 11:28:00 -08001220 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Lena Djokic38e380b2017-10-30 16:17:10 +01001221 UNREACHABLE();
1222 }
1223 break;
1224 case DataType::Type::kInt32:
1225 DCHECK_EQ(4u, a->GetVectorLength());
1226 switch (instruction->GetPackedType()) {
1227 case DataType::Type::kInt32: {
1228 DCHECK_EQ(4u, instruction->GetVectorLength());
1229 __ FillW(tmp, ZERO);
1230 __ SubvW(tmp1, left, right);
1231 __ Add_aW(tmp1, tmp1, tmp);
1232 __ AddvW(acc, acc, tmp1);
1233 break;
1234 }
1235 case DataType::Type::kInt64: {
1236 DCHECK_EQ(2u, instruction->GetVectorLength());
1237 VectorRegister tmp2 = VectorRegisterFrom(locations->GetTemp(1));
1238 __ FillW(tmp, ZERO);
1239 __ Hadd_sD(tmp1, left, tmp);
1240 __ Hadd_sD(tmp2, right, tmp);
1241 __ Asub_sD(tmp1, tmp1, tmp2);
1242 __ AddvD(acc, acc, tmp1);
1243 __ Hadd_sD(tmp1, tmp, left);
1244 __ Hadd_sD(tmp2, tmp, right);
1245 __ Asub_sD(tmp1, tmp1, tmp2);
1246 __ AddvD(acc, acc, tmp1);
1247 break;
1248 }
1249 default:
Aart Bik29aa0822018-03-08 11:28:00 -08001250 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Lena Djokic38e380b2017-10-30 16:17:10 +01001251 UNREACHABLE();
1252 }
1253 break;
1254 case DataType::Type::kInt64: {
1255 DCHECK_EQ(2u, a->GetVectorLength());
1256 switch (instruction->GetPackedType()) {
1257 case DataType::Type::kInt64: {
1258 DCHECK_EQ(2u, instruction->GetVectorLength());
1259 __ FillW(tmp, ZERO);
1260 __ SubvD(tmp1, left, right);
1261 __ Add_aD(tmp1, tmp1, tmp);
1262 __ AddvD(acc, acc, tmp1);
1263 break;
1264 }
1265 default:
Aart Bik29aa0822018-03-08 11:28:00 -08001266 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Lena Djokic38e380b2017-10-30 16:17:10 +01001267 UNREACHABLE();
1268 }
1269 break;
1270 }
1271 default:
Aart Bik29aa0822018-03-08 11:28:00 -08001272 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Lena Djokic38e380b2017-10-30 16:17:10 +01001273 UNREACHABLE();
1274 }
Aart Bikdbbac8f2017-09-01 13:06:08 -07001275}
1276
Lena Djokic51765b02017-06-22 13:49:59 +02001277// Helper to set up locations for vector memory operations.
Vladimir Markoe764d2e2017-10-05 14:35:55 +01001278static void CreateVecMemLocations(ArenaAllocator* allocator,
Lena Djokic51765b02017-06-22 13:49:59 +02001279 HVecMemoryOperation* instruction,
1280 bool is_load) {
Vladimir Markoe764d2e2017-10-05 14:35:55 +01001281 LocationSummary* locations = new (allocator) LocationSummary(instruction);
Lena Djokic51765b02017-06-22 13:49:59 +02001282 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001283 case DataType::Type::kBool:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +01001284 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001285 case DataType::Type::kInt8:
1286 case DataType::Type::kUint16:
1287 case DataType::Type::kInt16:
1288 case DataType::Type::kInt32:
1289 case DataType::Type::kInt64:
1290 case DataType::Type::kFloat32:
1291 case DataType::Type::kFloat64:
Lena Djokic51765b02017-06-22 13:49:59 +02001292 locations->SetInAt(0, Location::RequiresRegister());
1293 locations->SetInAt(1, Location::RegisterOrConstant(instruction->InputAt(1)));
1294 if (is_load) {
1295 locations->SetOut(Location::RequiresFpuRegister());
1296 } else {
1297 locations->SetInAt(2, Location::RequiresFpuRegister());
1298 }
1299 break;
1300 default:
Aart Bik29aa0822018-03-08 11:28:00 -08001301 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Lena Djokic51765b02017-06-22 13:49:59 +02001302 UNREACHABLE();
1303 }
1304}
1305
1306// Helper to prepare register and offset for vector memory operations. Returns the offset and sets
1307// the output parameter adjusted_base to the original base or to a reserved temporary register (AT).
1308int32_t InstructionCodeGeneratorMIPS::VecAddress(LocationSummary* locations,
1309 size_t size,
1310 /* out */ Register* adjusted_base) {
1311 Register base = locations->InAt(0).AsRegister<Register>();
1312 Location index = locations->InAt(1);
1313 int scale = TIMES_1;
1314 switch (size) {
1315 case 2: scale = TIMES_2; break;
1316 case 4: scale = TIMES_4; break;
1317 case 8: scale = TIMES_8; break;
1318 default: break;
1319 }
1320 int32_t offset = mirror::Array::DataOffset(size).Int32Value();
1321
1322 if (index.IsConstant()) {
1323 offset += index.GetConstant()->AsIntConstant()->GetValue() << scale;
1324 __ AdjustBaseOffsetAndElementSizeShift(base, offset, scale);
1325 *adjusted_base = base;
1326 } else {
1327 Register index_reg = index.AsRegister<Register>();
1328 if (scale != TIMES_1) {
1329 __ Lsa(AT, index_reg, base, scale);
1330 } else {
1331 __ Addu(AT, base, index_reg);
1332 }
1333 *adjusted_base = AT;
1334 }
1335 return offset;
1336}
1337
Aart Bikf8f5a162017-02-06 15:35:29 -08001338void LocationsBuilderMIPS::VisitVecLoad(HVecLoad* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +01001339 CreateVecMemLocations(GetGraph()->GetAllocator(), instruction, /* is_load */ true);
Aart Bikf8f5a162017-02-06 15:35:29 -08001340}
1341
1342void InstructionCodeGeneratorMIPS::VisitVecLoad(HVecLoad* instruction) {
Lena Djokic51765b02017-06-22 13:49:59 +02001343 LocationSummary* locations = instruction->GetLocations();
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001344 size_t size = DataType::Size(instruction->GetPackedType());
Lena Djokic51765b02017-06-22 13:49:59 +02001345 VectorRegister reg = VectorRegisterFrom(locations->Out());
1346 Register base;
1347 int32_t offset = VecAddress(locations, size, &base);
1348 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001349 case DataType::Type::kBool:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +01001350 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001351 case DataType::Type::kInt8:
Lena Djokic51765b02017-06-22 13:49:59 +02001352 DCHECK_EQ(16u, instruction->GetVectorLength());
1353 __ LdB(reg, base, offset);
1354 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001355 case DataType::Type::kUint16:
1356 case DataType::Type::kInt16:
Lena Djokic51765b02017-06-22 13:49:59 +02001357 // Loading 8-bytes (needed if dealing with compressed strings in StringCharAt) from unaligned
1358 // memory address may cause a trap to the kernel if the CPU doesn't directly support unaligned
1359 // loads and stores.
1360 // TODO: Implement support for StringCharAt.
1361 DCHECK(!instruction->IsStringCharAt());
1362 DCHECK_EQ(8u, instruction->GetVectorLength());
1363 __ LdH(reg, base, offset);
1364 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001365 case DataType::Type::kInt32:
1366 case DataType::Type::kFloat32:
Lena Djokic51765b02017-06-22 13:49:59 +02001367 DCHECK_EQ(4u, instruction->GetVectorLength());
1368 __ LdW(reg, base, offset);
1369 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001370 case DataType::Type::kInt64:
1371 case DataType::Type::kFloat64:
Lena Djokic51765b02017-06-22 13:49:59 +02001372 DCHECK_EQ(2u, instruction->GetVectorLength());
1373 __ LdD(reg, base, offset);
1374 break;
1375 default:
Aart Bik29aa0822018-03-08 11:28:00 -08001376 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Lena Djokic51765b02017-06-22 13:49:59 +02001377 UNREACHABLE();
1378 }
Aart Bikf8f5a162017-02-06 15:35:29 -08001379}
1380
1381void LocationsBuilderMIPS::VisitVecStore(HVecStore* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +01001382 CreateVecMemLocations(GetGraph()->GetAllocator(), instruction, /* is_load */ false);
Aart Bikf8f5a162017-02-06 15:35:29 -08001383}
1384
1385void InstructionCodeGeneratorMIPS::VisitVecStore(HVecStore* instruction) {
Lena Djokic51765b02017-06-22 13:49:59 +02001386 LocationSummary* locations = instruction->GetLocations();
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001387 size_t size = DataType::Size(instruction->GetPackedType());
Lena Djokic51765b02017-06-22 13:49:59 +02001388 VectorRegister reg = VectorRegisterFrom(locations->InAt(2));
1389 Register base;
1390 int32_t offset = VecAddress(locations, size, &base);
1391 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001392 case DataType::Type::kBool:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +01001393 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001394 case DataType::Type::kInt8:
Lena Djokic51765b02017-06-22 13:49:59 +02001395 DCHECK_EQ(16u, instruction->GetVectorLength());
1396 __ StB(reg, base, offset);
1397 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001398 case DataType::Type::kUint16:
1399 case DataType::Type::kInt16:
Lena Djokic51765b02017-06-22 13:49:59 +02001400 DCHECK_EQ(8u, instruction->GetVectorLength());
1401 __ StH(reg, base, offset);
1402 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001403 case DataType::Type::kInt32:
1404 case DataType::Type::kFloat32:
Lena Djokic51765b02017-06-22 13:49:59 +02001405 DCHECK_EQ(4u, instruction->GetVectorLength());
1406 __ StW(reg, base, offset);
1407 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001408 case DataType::Type::kInt64:
1409 case DataType::Type::kFloat64:
Lena Djokic51765b02017-06-22 13:49:59 +02001410 DCHECK_EQ(2u, instruction->GetVectorLength());
1411 __ StD(reg, base, offset);
1412 break;
1413 default:
Aart Bik29aa0822018-03-08 11:28:00 -08001414 LOG(FATAL) << "Unsupported SIMD type: " << instruction->GetPackedType();
Lena Djokic51765b02017-06-22 13:49:59 +02001415 UNREACHABLE();
1416 }
Aart Bikf8f5a162017-02-06 15:35:29 -08001417}
1418
1419#undef __
1420
1421} // namespace mips
1422} // namespace art