blob: 3cf150a6b81cdb8d53889ef86886f4787c95b318 [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:
45 LOG(FATAL) << "Unsupported SIMD type";
46 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:
92 LOG(FATAL) << "Unsupported SIMD type";
93 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:
116 LOG(FATAL) << "Unsupported SIMD type";
117 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:
141 LOG(FATAL) << "Unsupported SIMD type";
142 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:
173 LOG(FATAL) << "Unsupported SIMD type";
174 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:
228 LOG(FATAL) << "Unsupported SIMD type";
229 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 {
247 LOG(FATAL) << "Unsupported SIMD type";
248 }
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:
293 LOG(FATAL) << "Unsupported SIMD type";
294 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:
340 LOG(FATAL) << "Unsupported SIMD type";
341 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:
372 LOG(FATAL) << "Unsupported SIMD type";
373 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:
395 LOG(FATAL) << "Unsupported SIMD type";
396 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:
437 LOG(FATAL) << "Unsupported SIMD type";
438 UNREACHABLE();
439 }
Aart Bikf8f5a162017-02-06 15:35:29 -0800440}
441
Aart Bikf3e61ee2017-04-12 17:09:20 -0700442void LocationsBuilderMIPS::VisitVecHalvingAdd(HVecHalvingAdd* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100443 CreateVecBinOpLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikf3e61ee2017-04-12 17:09:20 -0700444}
445
446void InstructionCodeGeneratorMIPS::VisitVecHalvingAdd(HVecHalvingAdd* instruction) {
Lena Djokic51765b02017-06-22 13:49:59 +0200447 LocationSummary* locations = instruction->GetLocations();
448 VectorRegister lhs = VectorRegisterFrom(locations->InAt(0));
449 VectorRegister rhs = VectorRegisterFrom(locations->InAt(1));
450 VectorRegister dst = VectorRegisterFrom(locations->Out());
451 switch (instruction->GetPackedType()) {
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100452 case DataType::Type::kUint8:
453 DCHECK_EQ(16u, instruction->GetVectorLength());
454 instruction->IsRounded()
455 ? __ Aver_uB(dst, lhs, rhs)
456 : __ Ave_uB(dst, lhs, rhs);
457 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100458 case DataType::Type::kInt8:
Lena Djokic51765b02017-06-22 13:49:59 +0200459 DCHECK_EQ(16u, instruction->GetVectorLength());
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100460 instruction->IsRounded()
461 ? __ Aver_sB(dst, lhs, rhs)
462 : __ Ave_sB(dst, lhs, rhs);
Lena Djokic51765b02017-06-22 13:49:59 +0200463 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100464 case DataType::Type::kUint16:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100465 DCHECK_EQ(8u, instruction->GetVectorLength());
466 instruction->IsRounded()
467 ? __ Aver_uH(dst, lhs, rhs)
468 : __ Ave_uH(dst, lhs, rhs);
469 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100470 case DataType::Type::kInt16:
Lena Djokic51765b02017-06-22 13:49:59 +0200471 DCHECK_EQ(8u, instruction->GetVectorLength());
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100472 instruction->IsRounded()
473 ? __ Aver_sH(dst, lhs, rhs)
474 : __ Ave_sH(dst, lhs, rhs);
Lena Djokic51765b02017-06-22 13:49:59 +0200475 break;
476 default:
477 LOG(FATAL) << "Unsupported SIMD type";
478 UNREACHABLE();
479 }
Aart Bikf3e61ee2017-04-12 17:09:20 -0700480}
481
Aart Bikf8f5a162017-02-06 15:35:29 -0800482void LocationsBuilderMIPS::VisitVecSub(HVecSub* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100483 CreateVecBinOpLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikf8f5a162017-02-06 15:35:29 -0800484}
485
486void InstructionCodeGeneratorMIPS::VisitVecSub(HVecSub* instruction) {
Lena Djokic51765b02017-06-22 13:49:59 +0200487 LocationSummary* locations = instruction->GetLocations();
488 VectorRegister lhs = VectorRegisterFrom(locations->InAt(0));
489 VectorRegister rhs = VectorRegisterFrom(locations->InAt(1));
490 VectorRegister dst = VectorRegisterFrom(locations->Out());
491 switch (instruction->GetPackedType()) {
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100492 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100493 case DataType::Type::kInt8:
Lena Djokic51765b02017-06-22 13:49:59 +0200494 DCHECK_EQ(16u, instruction->GetVectorLength());
495 __ SubvB(dst, lhs, rhs);
496 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100497 case DataType::Type::kUint16:
498 case DataType::Type::kInt16:
Lena Djokic51765b02017-06-22 13:49:59 +0200499 DCHECK_EQ(8u, instruction->GetVectorLength());
500 __ SubvH(dst, lhs, rhs);
501 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100502 case DataType::Type::kInt32:
Lena Djokic51765b02017-06-22 13:49:59 +0200503 DCHECK_EQ(4u, instruction->GetVectorLength());
504 __ SubvW(dst, lhs, rhs);
505 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100506 case DataType::Type::kInt64:
Lena Djokic51765b02017-06-22 13:49:59 +0200507 DCHECK_EQ(2u, instruction->GetVectorLength());
508 __ SubvD(dst, lhs, rhs);
509 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100510 case DataType::Type::kFloat32:
Lena Djokic51765b02017-06-22 13:49:59 +0200511 DCHECK_EQ(4u, instruction->GetVectorLength());
512 __ FsubW(dst, lhs, rhs);
513 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100514 case DataType::Type::kFloat64:
Lena Djokic51765b02017-06-22 13:49:59 +0200515 DCHECK_EQ(2u, instruction->GetVectorLength());
516 __ FsubD(dst, lhs, rhs);
517 break;
518 default:
519 LOG(FATAL) << "Unsupported SIMD type";
520 UNREACHABLE();
521 }
Aart Bikf8f5a162017-02-06 15:35:29 -0800522}
523
524void LocationsBuilderMIPS::VisitVecMul(HVecMul* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100525 CreateVecBinOpLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikf8f5a162017-02-06 15:35:29 -0800526}
527
528void InstructionCodeGeneratorMIPS::VisitVecMul(HVecMul* instruction) {
Lena Djokic51765b02017-06-22 13:49:59 +0200529 LocationSummary* locations = instruction->GetLocations();
530 VectorRegister lhs = VectorRegisterFrom(locations->InAt(0));
531 VectorRegister rhs = VectorRegisterFrom(locations->InAt(1));
532 VectorRegister dst = VectorRegisterFrom(locations->Out());
533 switch (instruction->GetPackedType()) {
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100534 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100535 case DataType::Type::kInt8:
Lena Djokic51765b02017-06-22 13:49:59 +0200536 DCHECK_EQ(16u, instruction->GetVectorLength());
537 __ MulvB(dst, lhs, rhs);
538 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100539 case DataType::Type::kUint16:
540 case DataType::Type::kInt16:
Lena Djokic51765b02017-06-22 13:49:59 +0200541 DCHECK_EQ(8u, instruction->GetVectorLength());
542 __ MulvH(dst, lhs, rhs);
543 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100544 case DataType::Type::kInt32:
Lena Djokic51765b02017-06-22 13:49:59 +0200545 DCHECK_EQ(4u, instruction->GetVectorLength());
546 __ MulvW(dst, lhs, rhs);
547 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100548 case DataType::Type::kInt64:
Lena Djokic51765b02017-06-22 13:49:59 +0200549 DCHECK_EQ(2u, instruction->GetVectorLength());
550 __ MulvD(dst, lhs, rhs);
551 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100552 case DataType::Type::kFloat32:
Lena Djokic51765b02017-06-22 13:49:59 +0200553 DCHECK_EQ(4u, instruction->GetVectorLength());
554 __ FmulW(dst, lhs, rhs);
555 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100556 case DataType::Type::kFloat64:
Lena Djokic51765b02017-06-22 13:49:59 +0200557 DCHECK_EQ(2u, instruction->GetVectorLength());
558 __ FmulD(dst, lhs, rhs);
559 break;
560 default:
561 LOG(FATAL) << "Unsupported SIMD type";
562 UNREACHABLE();
563 }
Aart Bikf8f5a162017-02-06 15:35:29 -0800564}
565
566void LocationsBuilderMIPS::VisitVecDiv(HVecDiv* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100567 CreateVecBinOpLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikf8f5a162017-02-06 15:35:29 -0800568}
569
570void InstructionCodeGeneratorMIPS::VisitVecDiv(HVecDiv* instruction) {
Lena Djokic51765b02017-06-22 13:49:59 +0200571 LocationSummary* locations = instruction->GetLocations();
572 VectorRegister lhs = VectorRegisterFrom(locations->InAt(0));
573 VectorRegister rhs = VectorRegisterFrom(locations->InAt(1));
574 VectorRegister dst = VectorRegisterFrom(locations->Out());
575 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100576 case DataType::Type::kFloat32:
Lena Djokic51765b02017-06-22 13:49:59 +0200577 DCHECK_EQ(4u, instruction->GetVectorLength());
578 __ FdivW(dst, lhs, rhs);
579 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100580 case DataType::Type::kFloat64:
Lena Djokic51765b02017-06-22 13:49:59 +0200581 DCHECK_EQ(2u, instruction->GetVectorLength());
582 __ FdivD(dst, lhs, rhs);
583 break;
584 default:
585 LOG(FATAL) << "Unsupported SIMD type";
586 UNREACHABLE();
587 }
Aart Bikf8f5a162017-02-06 15:35:29 -0800588}
589
Aart Bikf3e61ee2017-04-12 17:09:20 -0700590void LocationsBuilderMIPS::VisitVecMin(HVecMin* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100591 CreateVecBinOpLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikf3e61ee2017-04-12 17:09:20 -0700592}
593
594void InstructionCodeGeneratorMIPS::VisitVecMin(HVecMin* instruction) {
Lena Djokic51765b02017-06-22 13:49:59 +0200595 LocationSummary* locations = instruction->GetLocations();
596 VectorRegister lhs = VectorRegisterFrom(locations->InAt(0));
597 VectorRegister rhs = VectorRegisterFrom(locations->InAt(1));
598 VectorRegister dst = VectorRegisterFrom(locations->Out());
599 switch (instruction->GetPackedType()) {
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100600 case DataType::Type::kUint8:
601 DCHECK_EQ(16u, instruction->GetVectorLength());
602 __ Min_uB(dst, lhs, rhs);
603 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100604 case DataType::Type::kInt8:
Lena Djokic51765b02017-06-22 13:49:59 +0200605 DCHECK_EQ(16u, instruction->GetVectorLength());
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100606 __ Min_sB(dst, lhs, rhs);
Lena Djokic51765b02017-06-22 13:49:59 +0200607 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100608 case DataType::Type::kUint16:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100609 DCHECK_EQ(8u, instruction->GetVectorLength());
610 __ Min_uH(dst, lhs, rhs);
611 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100612 case DataType::Type::kInt16:
Lena Djokic51765b02017-06-22 13:49:59 +0200613 DCHECK_EQ(8u, instruction->GetVectorLength());
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100614 __ Min_sH(dst, lhs, rhs);
Lena Djokic51765b02017-06-22 13:49:59 +0200615 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100616 case DataType::Type::kInt32:
Lena Djokic51765b02017-06-22 13:49:59 +0200617 DCHECK_EQ(4u, instruction->GetVectorLength());
618 if (instruction->IsUnsigned()) {
619 __ Min_uW(dst, lhs, rhs);
620 } else {
621 __ Min_sW(dst, lhs, rhs);
622 }
623 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100624 case DataType::Type::kInt64:
Lena Djokic51765b02017-06-22 13:49:59 +0200625 DCHECK_EQ(2u, instruction->GetVectorLength());
626 if (instruction->IsUnsigned()) {
627 __ Min_uD(dst, lhs, rhs);
628 } else {
629 __ Min_sD(dst, lhs, rhs);
630 }
631 break;
632 // When one of arguments is NaN, fmin.df returns other argument, but Java expects a NaN value.
633 // TODO: Fix min(x, NaN) cases for float and double.
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100634 case DataType::Type::kFloat32:
Lena Djokic51765b02017-06-22 13:49:59 +0200635 DCHECK_EQ(4u, instruction->GetVectorLength());
636 DCHECK(!instruction->IsUnsigned());
637 __ FminW(dst, lhs, rhs);
638 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100639 case DataType::Type::kFloat64:
Lena Djokic51765b02017-06-22 13:49:59 +0200640 DCHECK_EQ(2u, instruction->GetVectorLength());
641 DCHECK(!instruction->IsUnsigned());
642 __ FminD(dst, lhs, rhs);
643 break;
644 default:
645 LOG(FATAL) << "Unsupported SIMD type";
646 UNREACHABLE();
647 }
Aart Bikf3e61ee2017-04-12 17:09:20 -0700648}
649
650void LocationsBuilderMIPS::VisitVecMax(HVecMax* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100651 CreateVecBinOpLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikf3e61ee2017-04-12 17:09:20 -0700652}
653
654void InstructionCodeGeneratorMIPS::VisitVecMax(HVecMax* instruction) {
Lena Djokic51765b02017-06-22 13:49:59 +0200655 LocationSummary* locations = instruction->GetLocations();
656 VectorRegister lhs = VectorRegisterFrom(locations->InAt(0));
657 VectorRegister rhs = VectorRegisterFrom(locations->InAt(1));
658 VectorRegister dst = VectorRegisterFrom(locations->Out());
659 switch (instruction->GetPackedType()) {
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100660 case DataType::Type::kUint8:
661 DCHECK_EQ(16u, instruction->GetVectorLength());
662 __ Max_uB(dst, lhs, rhs);
663 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100664 case DataType::Type::kInt8:
Lena Djokic51765b02017-06-22 13:49:59 +0200665 DCHECK_EQ(16u, instruction->GetVectorLength());
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100666 __ Max_sB(dst, lhs, rhs);
Lena Djokic51765b02017-06-22 13:49:59 +0200667 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100668 case DataType::Type::kUint16:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100669 DCHECK_EQ(8u, instruction->GetVectorLength());
670 __ Max_uH(dst, lhs, rhs);
671 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100672 case DataType::Type::kInt16:
Lena Djokic51765b02017-06-22 13:49:59 +0200673 DCHECK_EQ(8u, instruction->GetVectorLength());
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100674 __ Max_sH(dst, lhs, rhs);
Lena Djokic51765b02017-06-22 13:49:59 +0200675 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100676 case DataType::Type::kInt32:
Lena Djokic51765b02017-06-22 13:49:59 +0200677 DCHECK_EQ(4u, instruction->GetVectorLength());
678 if (instruction->IsUnsigned()) {
679 __ Max_uW(dst, lhs, rhs);
680 } else {
681 __ Max_sW(dst, lhs, rhs);
682 }
683 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100684 case DataType::Type::kInt64:
Lena Djokic51765b02017-06-22 13:49:59 +0200685 DCHECK_EQ(2u, instruction->GetVectorLength());
686 if (instruction->IsUnsigned()) {
687 __ Max_uD(dst, lhs, rhs);
688 } else {
689 __ Max_sD(dst, lhs, rhs);
690 }
691 break;
692 // When one of arguments is NaN, fmax.df returns other argument, but Java expects a NaN value.
693 // TODO: Fix max(x, NaN) cases for float and double.
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100694 case DataType::Type::kFloat32:
Lena Djokic51765b02017-06-22 13:49:59 +0200695 DCHECK_EQ(4u, instruction->GetVectorLength());
696 DCHECK(!instruction->IsUnsigned());
697 __ FmaxW(dst, lhs, rhs);
698 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100699 case DataType::Type::kFloat64:
Lena Djokic51765b02017-06-22 13:49:59 +0200700 DCHECK_EQ(2u, instruction->GetVectorLength());
701 DCHECK(!instruction->IsUnsigned());
702 __ FmaxD(dst, lhs, rhs);
703 break;
704 default:
705 LOG(FATAL) << "Unsupported SIMD type";
706 UNREACHABLE();
707 }
Aart Bikf3e61ee2017-04-12 17:09:20 -0700708}
709
Aart Bikf8f5a162017-02-06 15:35:29 -0800710void LocationsBuilderMIPS::VisitVecAnd(HVecAnd* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100711 CreateVecBinOpLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikf8f5a162017-02-06 15:35:29 -0800712}
713
714void InstructionCodeGeneratorMIPS::VisitVecAnd(HVecAnd* instruction) {
Lena Djokic51765b02017-06-22 13:49:59 +0200715 LocationSummary* locations = instruction->GetLocations();
716 VectorRegister lhs = VectorRegisterFrom(locations->InAt(0));
717 VectorRegister rhs = VectorRegisterFrom(locations->InAt(1));
718 VectorRegister dst = VectorRegisterFrom(locations->Out());
719 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100720 case DataType::Type::kBool:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100721 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100722 case DataType::Type::kInt8:
723 case DataType::Type::kUint16:
724 case DataType::Type::kInt16:
725 case DataType::Type::kInt32:
726 case DataType::Type::kInt64:
727 case DataType::Type::kFloat32:
728 case DataType::Type::kFloat64:
Lena Djokic51765b02017-06-22 13:49:59 +0200729 DCHECK_LE(2u, instruction->GetVectorLength());
730 DCHECK_LE(instruction->GetVectorLength(), 16u);
731 __ AndV(dst, lhs, rhs); // lanes do not matter
732 break;
733 default:
734 LOG(FATAL) << "Unsupported SIMD type";
735 UNREACHABLE();
736 }
Aart Bikf8f5a162017-02-06 15:35:29 -0800737}
738
739void LocationsBuilderMIPS::VisitVecAndNot(HVecAndNot* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100740 CreateVecBinOpLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikf8f5a162017-02-06 15:35:29 -0800741}
742
743void InstructionCodeGeneratorMIPS::VisitVecAndNot(HVecAndNot* instruction) {
744 LOG(FATAL) << "No SIMD for " << instruction->GetId();
745}
746
747void LocationsBuilderMIPS::VisitVecOr(HVecOr* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100748 CreateVecBinOpLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikf8f5a162017-02-06 15:35:29 -0800749}
750
751void InstructionCodeGeneratorMIPS::VisitVecOr(HVecOr* instruction) {
Lena Djokic51765b02017-06-22 13:49:59 +0200752 LocationSummary* locations = instruction->GetLocations();
753 VectorRegister lhs = VectorRegisterFrom(locations->InAt(0));
754 VectorRegister rhs = VectorRegisterFrom(locations->InAt(1));
755 VectorRegister dst = VectorRegisterFrom(locations->Out());
756 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100757 case DataType::Type::kBool:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100758 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100759 case DataType::Type::kInt8:
760 case DataType::Type::kUint16:
761 case DataType::Type::kInt16:
762 case DataType::Type::kInt32:
763 case DataType::Type::kInt64:
764 case DataType::Type::kFloat32:
765 case DataType::Type::kFloat64:
Lena Djokic51765b02017-06-22 13:49:59 +0200766 DCHECK_LE(2u, instruction->GetVectorLength());
767 DCHECK_LE(instruction->GetVectorLength(), 16u);
768 __ OrV(dst, lhs, rhs); // lanes do not matter
769 break;
770 default:
771 LOG(FATAL) << "Unsupported SIMD type";
772 UNREACHABLE();
773 }
Aart Bikf8f5a162017-02-06 15:35:29 -0800774}
775
776void LocationsBuilderMIPS::VisitVecXor(HVecXor* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100777 CreateVecBinOpLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikf8f5a162017-02-06 15:35:29 -0800778}
779
780void InstructionCodeGeneratorMIPS::VisitVecXor(HVecXor* instruction) {
Lena Djokic51765b02017-06-22 13:49:59 +0200781 LocationSummary* locations = instruction->GetLocations();
782 VectorRegister lhs = VectorRegisterFrom(locations->InAt(0));
783 VectorRegister rhs = VectorRegisterFrom(locations->InAt(1));
784 VectorRegister dst = VectorRegisterFrom(locations->Out());
785 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100786 case DataType::Type::kBool:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100787 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100788 case DataType::Type::kInt8:
789 case DataType::Type::kUint16:
790 case DataType::Type::kInt16:
791 case DataType::Type::kInt32:
792 case DataType::Type::kInt64:
793 case DataType::Type::kFloat32:
794 case DataType::Type::kFloat64:
Lena Djokic51765b02017-06-22 13:49:59 +0200795 DCHECK_LE(2u, instruction->GetVectorLength());
796 DCHECK_LE(instruction->GetVectorLength(), 16u);
797 __ XorV(dst, lhs, rhs); // lanes do not matter
798 break;
799 default:
800 LOG(FATAL) << "Unsupported SIMD type";
801 UNREACHABLE();
802 }
Aart Bikf8f5a162017-02-06 15:35:29 -0800803}
804
805// Helper to set up locations for vector shift operations.
Vladimir Markoe764d2e2017-10-05 14:35:55 +0100806static void CreateVecShiftLocations(ArenaAllocator* allocator, HVecBinaryOperation* instruction) {
807 LocationSummary* locations = new (allocator) LocationSummary(instruction);
Aart Bikf8f5a162017-02-06 15:35:29 -0800808 switch (instruction->GetPackedType()) {
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100809 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100810 case DataType::Type::kInt8:
811 case DataType::Type::kUint16:
812 case DataType::Type::kInt16:
813 case DataType::Type::kInt32:
814 case DataType::Type::kInt64:
Lena Djokic51765b02017-06-22 13:49:59 +0200815 locations->SetInAt(0, Location::RequiresFpuRegister());
816 locations->SetInAt(1, Location::ConstantLocation(instruction->InputAt(1)->AsConstant()));
817 locations->SetOut(Location::RequiresFpuRegister(), Location::kNoOutputOverlap);
Aart Bikf8f5a162017-02-06 15:35:29 -0800818 break;
819 default:
820 LOG(FATAL) << "Unsupported SIMD type";
821 UNREACHABLE();
822 }
823}
824
825void LocationsBuilderMIPS::VisitVecShl(HVecShl* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100826 CreateVecShiftLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikf8f5a162017-02-06 15:35:29 -0800827}
828
829void InstructionCodeGeneratorMIPS::VisitVecShl(HVecShl* instruction) {
Lena Djokic51765b02017-06-22 13:49:59 +0200830 LocationSummary* locations = instruction->GetLocations();
831 VectorRegister lhs = VectorRegisterFrom(locations->InAt(0));
832 VectorRegister dst = VectorRegisterFrom(locations->Out());
833 int32_t value = locations->InAt(1).GetConstant()->AsIntConstant()->GetValue();
834 switch (instruction->GetPackedType()) {
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100835 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100836 case DataType::Type::kInt8:
Lena Djokic51765b02017-06-22 13:49:59 +0200837 DCHECK_EQ(16u, instruction->GetVectorLength());
838 __ SlliB(dst, lhs, value);
839 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100840 case DataType::Type::kUint16:
841 case DataType::Type::kInt16:
Lena Djokic51765b02017-06-22 13:49:59 +0200842 DCHECK_EQ(8u, instruction->GetVectorLength());
843 __ SlliH(dst, lhs, value);
844 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100845 case DataType::Type::kInt32:
Lena Djokic51765b02017-06-22 13:49:59 +0200846 DCHECK_EQ(4u, instruction->GetVectorLength());
847 __ SlliW(dst, lhs, value);
848 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100849 case DataType::Type::kInt64:
Lena Djokic51765b02017-06-22 13:49:59 +0200850 DCHECK_EQ(2u, instruction->GetVectorLength());
851 __ SlliD(dst, lhs, value);
852 break;
853 default:
854 LOG(FATAL) << "Unsupported SIMD type";
855 UNREACHABLE();
856 }
Aart Bikf8f5a162017-02-06 15:35:29 -0800857}
858
859void LocationsBuilderMIPS::VisitVecShr(HVecShr* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100860 CreateVecShiftLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikf8f5a162017-02-06 15:35:29 -0800861}
862
863void InstructionCodeGeneratorMIPS::VisitVecShr(HVecShr* instruction) {
Lena Djokic51765b02017-06-22 13:49:59 +0200864 LocationSummary* locations = instruction->GetLocations();
865 VectorRegister lhs = VectorRegisterFrom(locations->InAt(0));
866 VectorRegister dst = VectorRegisterFrom(locations->Out());
867 int32_t value = locations->InAt(1).GetConstant()->AsIntConstant()->GetValue();
868 switch (instruction->GetPackedType()) {
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100869 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100870 case DataType::Type::kInt8:
Lena Djokic51765b02017-06-22 13:49:59 +0200871 DCHECK_EQ(16u, instruction->GetVectorLength());
872 __ SraiB(dst, lhs, value);
873 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100874 case DataType::Type::kUint16:
875 case DataType::Type::kInt16:
Lena Djokic51765b02017-06-22 13:49:59 +0200876 DCHECK_EQ(8u, instruction->GetVectorLength());
877 __ SraiH(dst, lhs, value);
878 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100879 case DataType::Type::kInt32:
Lena Djokic51765b02017-06-22 13:49:59 +0200880 DCHECK_EQ(4u, instruction->GetVectorLength());
881 __ SraiW(dst, lhs, value);
882 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100883 case DataType::Type::kInt64:
Lena Djokic51765b02017-06-22 13:49:59 +0200884 DCHECK_EQ(2u, instruction->GetVectorLength());
885 __ SraiD(dst, lhs, value);
886 break;
887 default:
888 LOG(FATAL) << "Unsupported SIMD type";
889 UNREACHABLE();
890 }
Aart Bikf8f5a162017-02-06 15:35:29 -0800891}
892
893void LocationsBuilderMIPS::VisitVecUShr(HVecUShr* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100894 CreateVecShiftLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikf8f5a162017-02-06 15:35:29 -0800895}
896
897void InstructionCodeGeneratorMIPS::VisitVecUShr(HVecUShr* instruction) {
Lena Djokic51765b02017-06-22 13:49:59 +0200898 LocationSummary* locations = instruction->GetLocations();
899 VectorRegister lhs = VectorRegisterFrom(locations->InAt(0));
900 VectorRegister dst = VectorRegisterFrom(locations->Out());
901 int32_t value = locations->InAt(1).GetConstant()->AsIntConstant()->GetValue();
902 switch (instruction->GetPackedType()) {
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100903 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100904 case DataType::Type::kInt8:
Lena Djokic51765b02017-06-22 13:49:59 +0200905 DCHECK_EQ(16u, instruction->GetVectorLength());
906 __ SrliB(dst, lhs, value);
907 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100908 case DataType::Type::kUint16:
909 case DataType::Type::kInt16:
Lena Djokic51765b02017-06-22 13:49:59 +0200910 DCHECK_EQ(8u, instruction->GetVectorLength());
911 __ SrliH(dst, lhs, value);
912 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100913 case DataType::Type::kInt32:
Lena Djokic51765b02017-06-22 13:49:59 +0200914 DCHECK_EQ(4u, instruction->GetVectorLength());
915 __ SrliW(dst, lhs, value);
916 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100917 case DataType::Type::kInt64:
Lena Djokic51765b02017-06-22 13:49:59 +0200918 DCHECK_EQ(2u, instruction->GetVectorLength());
919 __ SrliD(dst, lhs, value);
920 break;
921 default:
922 LOG(FATAL) << "Unsupported SIMD type";
923 UNREACHABLE();
924 }
Aart Bikf8f5a162017-02-06 15:35:29 -0800925}
926
Aart Bik0148de42017-09-05 09:25:01 -0700927void LocationsBuilderMIPS::VisitVecSetScalars(HVecSetScalars* instruction) {
Lena Djokice434c4f2017-10-23 16:40:22 +0200928 LocationSummary* locations = new (GetGraph()->GetAllocator()) LocationSummary(instruction);
929
930 DCHECK_EQ(1u, instruction->InputCount()); // only one input currently implemented
931
932 HInstruction* input = instruction->InputAt(0);
933 bool is_zero = IsZeroBitPattern(input);
934
935 switch (instruction->GetPackedType()) {
936 case DataType::Type::kBool:
937 case DataType::Type::kUint8:
938 case DataType::Type::kInt8:
939 case DataType::Type::kUint16:
940 case DataType::Type::kInt16:
941 case DataType::Type::kInt32:
942 case DataType::Type::kInt64:
943 locations->SetInAt(0, is_zero ? Location::ConstantLocation(input->AsConstant())
944 : Location::RequiresRegister());
945 locations->SetOut(Location::RequiresFpuRegister());
946 break;
947 case DataType::Type::kFloat32:
948 case DataType::Type::kFloat64:
949 locations->SetInAt(0, is_zero ? Location::ConstantLocation(input->AsConstant())
950 : Location::RequiresFpuRegister());
951 locations->SetOut(Location::RequiresFpuRegister());
952 break;
953 default:
954 LOG(FATAL) << "Unsupported SIMD type";
955 UNREACHABLE();
956 }
Aart Bik0148de42017-09-05 09:25:01 -0700957}
958
959void InstructionCodeGeneratorMIPS::VisitVecSetScalars(HVecSetScalars* instruction) {
Lena Djokice434c4f2017-10-23 16:40:22 +0200960 LocationSummary* locations = instruction->GetLocations();
961 VectorRegister dst = VectorRegisterFrom(locations->Out());
962
963 DCHECK_EQ(1u, instruction->InputCount()); // only one input currently implemented
964
965 // Zero out all other elements first.
966 __ FillW(dst, ZERO);
967
968 // Shorthand for any type of zero.
969 if (IsZeroBitPattern(instruction->InputAt(0))) {
970 return;
971 }
972
973 // Set required elements.
974 switch (instruction->GetPackedType()) {
975 case DataType::Type::kBool:
976 case DataType::Type::kUint8:
977 case DataType::Type::kInt8:
978 DCHECK_EQ(16u, instruction->GetVectorLength());
979 __ InsertB(dst, locations->InAt(0).AsRegister<Register>(), 0);
980 break;
981 case DataType::Type::kUint16:
982 case DataType::Type::kInt16:
983 DCHECK_EQ(8u, instruction->GetVectorLength());
984 __ InsertH(dst, locations->InAt(0).AsRegister<Register>(), 0);
985 break;
986 case DataType::Type::kInt32:
987 DCHECK_EQ(4u, instruction->GetVectorLength());
988 __ InsertW(dst, locations->InAt(0).AsRegister<Register>(), 0);
989 break;
990 case DataType::Type::kInt64:
991 DCHECK_EQ(2u, instruction->GetVectorLength());
Goran Jakovljevic7a0222e2017-11-08 10:16:37 +0100992 __ InsertW(dst, locations->InAt(0).AsRegisterPairLow<Register>(), 0);
993 __ InsertW(dst, locations->InAt(0).AsRegisterPairHigh<Register>(), 1);
Lena Djokice434c4f2017-10-23 16:40:22 +0200994 break;
995 default:
996 LOG(FATAL) << "Unsupported SIMD type";
997 UNREACHABLE();
998 }
Aart Bik0148de42017-09-05 09:25:01 -0700999}
1000
Aart Bikdbbac8f2017-09-01 13:06:08 -07001001// Helper to set up locations for vector accumulations.
Vladimir Markoe764d2e2017-10-05 14:35:55 +01001002static void CreateVecAccumLocations(ArenaAllocator* allocator, HVecOperation* instruction) {
1003 LocationSummary* locations = new (allocator) LocationSummary(instruction);
Aart Bikdbbac8f2017-09-01 13:06:08 -07001004 switch (instruction->GetPackedType()) {
Vladimir Markod5d2f2c2017-09-26 12:37:26 +01001005 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001006 case DataType::Type::kInt8:
1007 case DataType::Type::kUint16:
1008 case DataType::Type::kInt16:
1009 case DataType::Type::kInt32:
1010 case DataType::Type::kInt64:
Aart Bikdbbac8f2017-09-01 13:06:08 -07001011 locations->SetInAt(0, Location::RequiresFpuRegister());
1012 locations->SetInAt(1, Location::RequiresFpuRegister());
1013 locations->SetInAt(2, Location::RequiresFpuRegister());
Lena Djokicbc5460b2017-07-20 16:07:36 +02001014 locations->SetOut(Location::SameAsFirstInput());
1015 break;
1016 default:
1017 LOG(FATAL) << "Unsupported SIMD type";
1018 UNREACHABLE();
1019 }
Artem Serovf34dd202017-04-10 17:41:46 +01001020}
1021
Aart Bikdbbac8f2017-09-01 13:06:08 -07001022void LocationsBuilderMIPS::VisitVecMultiplyAccumulate(HVecMultiplyAccumulate* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +01001023 CreateVecAccumLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikdbbac8f2017-09-01 13:06:08 -07001024}
1025
1026void InstructionCodeGeneratorMIPS::VisitVecMultiplyAccumulate(HVecMultiplyAccumulate* instruction) {
1027 LocationSummary* locations = instruction->GetLocations();
1028 VectorRegister acc = VectorRegisterFrom(locations->InAt(0));
1029 VectorRegister left = VectorRegisterFrom(locations->InAt(1));
1030 VectorRegister right = VectorRegisterFrom(locations->InAt(2));
1031 switch (instruction->GetPackedType()) {
Vladimir Markod5d2f2c2017-09-26 12:37:26 +01001032 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001033 case DataType::Type::kInt8:
Aart Bikdbbac8f2017-09-01 13:06:08 -07001034 DCHECK_EQ(16u, instruction->GetVectorLength());
1035 if (instruction->GetOpKind() == HInstruction::kAdd) {
Lena Djokicbc5460b2017-07-20 16:07:36 +02001036 __ MaddvB(acc, left, right);
1037 } else {
1038 __ MsubvB(acc, left, right);
1039 }
1040 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001041 case DataType::Type::kUint16:
1042 case DataType::Type::kInt16:
Aart Bikdbbac8f2017-09-01 13:06:08 -07001043 DCHECK_EQ(8u, instruction->GetVectorLength());
1044 if (instruction->GetOpKind() == HInstruction::kAdd) {
Lena Djokicbc5460b2017-07-20 16:07:36 +02001045 __ MaddvH(acc, left, right);
1046 } else {
1047 __ MsubvH(acc, left, right);
1048 }
1049 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001050 case DataType::Type::kInt32:
Aart Bikdbbac8f2017-09-01 13:06:08 -07001051 DCHECK_EQ(4u, instruction->GetVectorLength());
1052 if (instruction->GetOpKind() == HInstruction::kAdd) {
Lena Djokicbc5460b2017-07-20 16:07:36 +02001053 __ MaddvW(acc, left, right);
1054 } else {
1055 __ MsubvW(acc, left, right);
1056 }
1057 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001058 case DataType::Type::kInt64:
Aart Bikdbbac8f2017-09-01 13:06:08 -07001059 DCHECK_EQ(2u, instruction->GetVectorLength());
1060 if (instruction->GetOpKind() == HInstruction::kAdd) {
Lena Djokicbc5460b2017-07-20 16:07:36 +02001061 __ MaddvD(acc, left, right);
1062 } else {
1063 __ MsubvD(acc, left, right);
1064 }
1065 break;
1066 default:
1067 LOG(FATAL) << "Unsupported SIMD type";
1068 UNREACHABLE();
1069 }
Artem Serovf34dd202017-04-10 17:41:46 +01001070}
1071
Aart Bikdbbac8f2017-09-01 13:06:08 -07001072void LocationsBuilderMIPS::VisitVecSADAccumulate(HVecSADAccumulate* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +01001073 CreateVecAccumLocations(GetGraph()->GetAllocator(), instruction);
Lena Djokic38e380b2017-10-30 16:17:10 +01001074 LocationSummary* locations = instruction->GetLocations();
1075 // All conversions require at least one temporary register.
1076 locations->AddTemp(Location::RequiresFpuRegister());
1077 // Some conversions require a second temporary register.
1078 HVecOperation* a = instruction->InputAt(1)->AsVecOperation();
1079 HVecOperation* b = instruction->InputAt(2)->AsVecOperation();
1080 DCHECK_EQ(HVecOperation::ToSignedType(a->GetPackedType()),
1081 HVecOperation::ToSignedType(b->GetPackedType()));
1082 switch (a->GetPackedType()) {
1083 case DataType::Type::kInt32:
1084 if (instruction->GetPackedType() == DataType::Type::kInt32) {
1085 break;
1086 }
1087 FALLTHROUGH_INTENDED;
1088 case DataType::Type::kUint8:
1089 case DataType::Type::kInt8:
1090 case DataType::Type::kUint16:
1091 case DataType::Type::kInt16:
1092 locations->AddTemp(Location::RequiresFpuRegister());
1093 break;
1094 default:
1095 break;
1096 }
Aart Bikdbbac8f2017-09-01 13:06:08 -07001097}
1098
1099void InstructionCodeGeneratorMIPS::VisitVecSADAccumulate(HVecSADAccumulate* instruction) {
Lena Djokic38e380b2017-10-30 16:17:10 +01001100 LocationSummary* locations = instruction->GetLocations();
1101 VectorRegister acc = VectorRegisterFrom(locations->InAt(0));
1102 VectorRegister left = VectorRegisterFrom(locations->InAt(1));
1103 VectorRegister right = VectorRegisterFrom(locations->InAt(2));
1104 VectorRegister tmp = static_cast<VectorRegister>(FTMP);
1105 VectorRegister tmp1 = VectorRegisterFrom(locations->GetTemp(0));
1106
1107 DCHECK(locations->InAt(0).Equals(locations->Out()));
1108
1109 // Handle all feasible acc_T += sad(a_S, b_S) type combinations (T x S).
1110 HVecOperation* a = instruction->InputAt(1)->AsVecOperation();
1111 HVecOperation* b = instruction->InputAt(2)->AsVecOperation();
1112 DCHECK_EQ(HVecOperation::ToSignedType(a->GetPackedType()),
1113 HVecOperation::ToSignedType(b->GetPackedType()));
1114 switch (a->GetPackedType()) {
1115 case DataType::Type::kUint8:
1116 case DataType::Type::kInt8:
1117 DCHECK_EQ(16u, a->GetVectorLength());
1118 switch (instruction->GetPackedType()) {
1119 case DataType::Type::kUint16:
1120 case DataType::Type::kInt16: {
1121 DCHECK_EQ(8u, instruction->GetVectorLength());
1122 VectorRegister tmp2 = VectorRegisterFrom(locations->GetTemp(1));
1123 __ FillB(tmp, ZERO);
1124 __ Hadd_sH(tmp1, left, tmp);
1125 __ Hadd_sH(tmp2, right, tmp);
1126 __ Asub_sH(tmp1, tmp1, tmp2);
1127 __ AddvH(acc, acc, tmp1);
1128 __ Hadd_sH(tmp1, tmp, left);
1129 __ Hadd_sH(tmp2, tmp, right);
1130 __ Asub_sH(tmp1, tmp1, tmp2);
1131 __ AddvH(acc, acc, tmp1);
1132 break;
1133 }
1134 case DataType::Type::kInt32: {
1135 DCHECK_EQ(4u, instruction->GetVectorLength());
1136 VectorRegister tmp2 = VectorRegisterFrom(locations->GetTemp(1));
1137 __ FillB(tmp, ZERO);
1138 __ Hadd_sH(tmp1, left, tmp);
1139 __ Hadd_sH(tmp2, right, tmp);
1140 __ Asub_sH(tmp1, tmp1, tmp2);
1141 __ Hadd_sW(tmp1, tmp1, tmp1);
1142 __ AddvW(acc, acc, tmp1);
1143 __ Hadd_sH(tmp1, tmp, left);
1144 __ Hadd_sH(tmp2, tmp, right);
1145 __ Asub_sH(tmp1, tmp1, tmp2);
1146 __ Hadd_sW(tmp1, tmp1, tmp1);
1147 __ AddvW(acc, acc, tmp1);
1148 break;
1149 }
1150 case DataType::Type::kInt64: {
1151 DCHECK_EQ(2u, instruction->GetVectorLength());
1152 VectorRegister tmp2 = VectorRegisterFrom(locations->GetTemp(1));
1153 __ FillB(tmp, ZERO);
1154 __ Hadd_sH(tmp1, left, tmp);
1155 __ Hadd_sH(tmp2, right, tmp);
1156 __ Asub_sH(tmp1, tmp1, tmp2);
1157 __ Hadd_sW(tmp1, tmp1, tmp1);
1158 __ Hadd_sD(tmp1, tmp1, tmp1);
1159 __ AddvD(acc, acc, tmp1);
1160 __ Hadd_sH(tmp1, tmp, left);
1161 __ Hadd_sH(tmp2, tmp, right);
1162 __ Asub_sH(tmp1, tmp1, tmp2);
1163 __ Hadd_sW(tmp1, tmp1, tmp1);
1164 __ Hadd_sD(tmp1, tmp1, tmp1);
1165 __ AddvD(acc, acc, tmp1);
1166 break;
1167 }
1168 default:
1169 LOG(FATAL) << "Unsupported SIMD type";
1170 UNREACHABLE();
1171 }
1172 break;
1173 case DataType::Type::kUint16:
1174 case DataType::Type::kInt16:
1175 DCHECK_EQ(8u, a->GetVectorLength());
1176 switch (instruction->GetPackedType()) {
1177 case DataType::Type::kInt32: {
1178 DCHECK_EQ(4u, instruction->GetVectorLength());
1179 VectorRegister tmp2 = VectorRegisterFrom(locations->GetTemp(1));
1180 __ FillH(tmp, ZERO);
1181 __ Hadd_sW(tmp1, left, tmp);
1182 __ Hadd_sW(tmp2, right, tmp);
1183 __ Asub_sW(tmp1, tmp1, tmp2);
1184 __ AddvW(acc, acc, tmp1);
1185 __ Hadd_sW(tmp1, tmp, left);
1186 __ Hadd_sW(tmp2, tmp, right);
1187 __ Asub_sW(tmp1, tmp1, tmp2);
1188 __ AddvW(acc, acc, tmp1);
1189 break;
1190 }
1191 case DataType::Type::kInt64: {
1192 DCHECK_EQ(2u, instruction->GetVectorLength());
1193 VectorRegister tmp2 = VectorRegisterFrom(locations->GetTemp(1));
1194 __ FillH(tmp, ZERO);
1195 __ Hadd_sW(tmp1, left, tmp);
1196 __ Hadd_sW(tmp2, right, tmp);
1197 __ Asub_sW(tmp1, tmp1, tmp2);
1198 __ Hadd_sD(tmp1, tmp1, tmp1);
1199 __ AddvD(acc, acc, tmp1);
1200 __ Hadd_sW(tmp1, tmp, left);
1201 __ Hadd_sW(tmp2, tmp, right);
1202 __ Asub_sW(tmp1, tmp1, tmp2);
1203 __ Hadd_sD(tmp1, tmp1, tmp1);
1204 __ AddvD(acc, acc, tmp1);
1205 break;
1206 }
1207 default:
1208 LOG(FATAL) << "Unsupported SIMD type";
1209 UNREACHABLE();
1210 }
1211 break;
1212 case DataType::Type::kInt32:
1213 DCHECK_EQ(4u, a->GetVectorLength());
1214 switch (instruction->GetPackedType()) {
1215 case DataType::Type::kInt32: {
1216 DCHECK_EQ(4u, instruction->GetVectorLength());
1217 __ FillW(tmp, ZERO);
1218 __ SubvW(tmp1, left, right);
1219 __ Add_aW(tmp1, tmp1, tmp);
1220 __ AddvW(acc, acc, tmp1);
1221 break;
1222 }
1223 case DataType::Type::kInt64: {
1224 DCHECK_EQ(2u, instruction->GetVectorLength());
1225 VectorRegister tmp2 = VectorRegisterFrom(locations->GetTemp(1));
1226 __ FillW(tmp, ZERO);
1227 __ Hadd_sD(tmp1, left, tmp);
1228 __ Hadd_sD(tmp2, right, tmp);
1229 __ Asub_sD(tmp1, tmp1, tmp2);
1230 __ AddvD(acc, acc, tmp1);
1231 __ Hadd_sD(tmp1, tmp, left);
1232 __ Hadd_sD(tmp2, tmp, right);
1233 __ Asub_sD(tmp1, tmp1, tmp2);
1234 __ AddvD(acc, acc, tmp1);
1235 break;
1236 }
1237 default:
1238 LOG(FATAL) << "Unsupported SIMD type";
1239 UNREACHABLE();
1240 }
1241 break;
1242 case DataType::Type::kInt64: {
1243 DCHECK_EQ(2u, a->GetVectorLength());
1244 switch (instruction->GetPackedType()) {
1245 case DataType::Type::kInt64: {
1246 DCHECK_EQ(2u, instruction->GetVectorLength());
1247 __ FillW(tmp, ZERO);
1248 __ SubvD(tmp1, left, right);
1249 __ Add_aD(tmp1, tmp1, tmp);
1250 __ AddvD(acc, acc, tmp1);
1251 break;
1252 }
1253 default:
1254 LOG(FATAL) << "Unsupported SIMD type";
1255 UNREACHABLE();
1256 }
1257 break;
1258 }
1259 default:
1260 LOG(FATAL) << "Unsupported SIMD type";
1261 UNREACHABLE();
1262 }
Aart Bikdbbac8f2017-09-01 13:06:08 -07001263}
1264
Lena Djokic51765b02017-06-22 13:49:59 +02001265// Helper to set up locations for vector memory operations.
Vladimir Markoe764d2e2017-10-05 14:35:55 +01001266static void CreateVecMemLocations(ArenaAllocator* allocator,
Lena Djokic51765b02017-06-22 13:49:59 +02001267 HVecMemoryOperation* instruction,
1268 bool is_load) {
Vladimir Markoe764d2e2017-10-05 14:35:55 +01001269 LocationSummary* locations = new (allocator) LocationSummary(instruction);
Lena Djokic51765b02017-06-22 13:49:59 +02001270 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001271 case DataType::Type::kBool:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +01001272 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001273 case DataType::Type::kInt8:
1274 case DataType::Type::kUint16:
1275 case DataType::Type::kInt16:
1276 case DataType::Type::kInt32:
1277 case DataType::Type::kInt64:
1278 case DataType::Type::kFloat32:
1279 case DataType::Type::kFloat64:
Lena Djokic51765b02017-06-22 13:49:59 +02001280 locations->SetInAt(0, Location::RequiresRegister());
1281 locations->SetInAt(1, Location::RegisterOrConstant(instruction->InputAt(1)));
1282 if (is_load) {
1283 locations->SetOut(Location::RequiresFpuRegister());
1284 } else {
1285 locations->SetInAt(2, Location::RequiresFpuRegister());
1286 }
1287 break;
1288 default:
1289 LOG(FATAL) << "Unsupported SIMD type";
1290 UNREACHABLE();
1291 }
1292}
1293
1294// Helper to prepare register and offset for vector memory operations. Returns the offset and sets
1295// the output parameter adjusted_base to the original base or to a reserved temporary register (AT).
1296int32_t InstructionCodeGeneratorMIPS::VecAddress(LocationSummary* locations,
1297 size_t size,
1298 /* out */ Register* adjusted_base) {
1299 Register base = locations->InAt(0).AsRegister<Register>();
1300 Location index = locations->InAt(1);
1301 int scale = TIMES_1;
1302 switch (size) {
1303 case 2: scale = TIMES_2; break;
1304 case 4: scale = TIMES_4; break;
1305 case 8: scale = TIMES_8; break;
1306 default: break;
1307 }
1308 int32_t offset = mirror::Array::DataOffset(size).Int32Value();
1309
1310 if (index.IsConstant()) {
1311 offset += index.GetConstant()->AsIntConstant()->GetValue() << scale;
1312 __ AdjustBaseOffsetAndElementSizeShift(base, offset, scale);
1313 *adjusted_base = base;
1314 } else {
1315 Register index_reg = index.AsRegister<Register>();
1316 if (scale != TIMES_1) {
1317 __ Lsa(AT, index_reg, base, scale);
1318 } else {
1319 __ Addu(AT, base, index_reg);
1320 }
1321 *adjusted_base = AT;
1322 }
1323 return offset;
1324}
1325
Aart Bikf8f5a162017-02-06 15:35:29 -08001326void LocationsBuilderMIPS::VisitVecLoad(HVecLoad* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +01001327 CreateVecMemLocations(GetGraph()->GetAllocator(), instruction, /* is_load */ true);
Aart Bikf8f5a162017-02-06 15:35:29 -08001328}
1329
1330void InstructionCodeGeneratorMIPS::VisitVecLoad(HVecLoad* instruction) {
Lena Djokic51765b02017-06-22 13:49:59 +02001331 LocationSummary* locations = instruction->GetLocations();
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001332 size_t size = DataType::Size(instruction->GetPackedType());
Lena Djokic51765b02017-06-22 13:49:59 +02001333 VectorRegister reg = VectorRegisterFrom(locations->Out());
1334 Register base;
1335 int32_t offset = VecAddress(locations, size, &base);
1336 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001337 case DataType::Type::kBool:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +01001338 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001339 case DataType::Type::kInt8:
Lena Djokic51765b02017-06-22 13:49:59 +02001340 DCHECK_EQ(16u, instruction->GetVectorLength());
1341 __ LdB(reg, base, offset);
1342 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001343 case DataType::Type::kUint16:
1344 case DataType::Type::kInt16:
Lena Djokic51765b02017-06-22 13:49:59 +02001345 // Loading 8-bytes (needed if dealing with compressed strings in StringCharAt) from unaligned
1346 // memory address may cause a trap to the kernel if the CPU doesn't directly support unaligned
1347 // loads and stores.
1348 // TODO: Implement support for StringCharAt.
1349 DCHECK(!instruction->IsStringCharAt());
1350 DCHECK_EQ(8u, instruction->GetVectorLength());
1351 __ LdH(reg, base, offset);
1352 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001353 case DataType::Type::kInt32:
1354 case DataType::Type::kFloat32:
Lena Djokic51765b02017-06-22 13:49:59 +02001355 DCHECK_EQ(4u, instruction->GetVectorLength());
1356 __ LdW(reg, base, offset);
1357 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001358 case DataType::Type::kInt64:
1359 case DataType::Type::kFloat64:
Lena Djokic51765b02017-06-22 13:49:59 +02001360 DCHECK_EQ(2u, instruction->GetVectorLength());
1361 __ LdD(reg, base, offset);
1362 break;
1363 default:
1364 LOG(FATAL) << "Unsupported SIMD type";
1365 UNREACHABLE();
1366 }
Aart Bikf8f5a162017-02-06 15:35:29 -08001367}
1368
1369void LocationsBuilderMIPS::VisitVecStore(HVecStore* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +01001370 CreateVecMemLocations(GetGraph()->GetAllocator(), instruction, /* is_load */ false);
Aart Bikf8f5a162017-02-06 15:35:29 -08001371}
1372
1373void InstructionCodeGeneratorMIPS::VisitVecStore(HVecStore* instruction) {
Lena Djokic51765b02017-06-22 13:49:59 +02001374 LocationSummary* locations = instruction->GetLocations();
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001375 size_t size = DataType::Size(instruction->GetPackedType());
Lena Djokic51765b02017-06-22 13:49:59 +02001376 VectorRegister reg = VectorRegisterFrom(locations->InAt(2));
1377 Register base;
1378 int32_t offset = VecAddress(locations, size, &base);
1379 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001380 case DataType::Type::kBool:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +01001381 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001382 case DataType::Type::kInt8:
Lena Djokic51765b02017-06-22 13:49:59 +02001383 DCHECK_EQ(16u, instruction->GetVectorLength());
1384 __ StB(reg, base, offset);
1385 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001386 case DataType::Type::kUint16:
1387 case DataType::Type::kInt16:
Lena Djokic51765b02017-06-22 13:49:59 +02001388 DCHECK_EQ(8u, instruction->GetVectorLength());
1389 __ StH(reg, base, offset);
1390 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001391 case DataType::Type::kInt32:
1392 case DataType::Type::kFloat32:
Lena Djokic51765b02017-06-22 13:49:59 +02001393 DCHECK_EQ(4u, instruction->GetVectorLength());
1394 __ StW(reg, base, offset);
1395 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001396 case DataType::Type::kInt64:
1397 case DataType::Type::kFloat64:
Lena Djokic51765b02017-06-22 13:49:59 +02001398 DCHECK_EQ(2u, instruction->GetVectorLength());
1399 __ StD(reg, base, offset);
1400 break;
1401 default:
1402 LOG(FATAL) << "Unsupported SIMD type";
1403 UNREACHABLE();
1404 }
Aart Bikf8f5a162017-02-06 15:35:29 -08001405}
1406
1407#undef __
1408
1409} // namespace mips
1410} // namespace art