blob: e8c515761c26e0f5225b0a3da0a544b511c68579 [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) {
Lena Djokic51765b02017-06-22 13:49:59 +020027 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction);
28 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());
71 __ Mtc1(locations->InAt(0).AsRegisterPairLow<Register>(), FTMP);
72 __ MoveToFpuHigh(locations->InAt(0).AsRegisterPairHigh<Register>(), FTMP);
73 __ ReplicateFPToVectorRegister(dst, FTMP, /* is_double */ true);
74 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +010075 case DataType::Type::kFloat32:
Lena Djokic51765b02017-06-22 13:49:59 +020076 DCHECK_EQ(4u, instruction->GetVectorLength());
77 __ ReplicateFPToVectorRegister(dst,
78 locations->InAt(0).AsFpuRegister<FRegister>(),
79 /* is_double */ false);
80 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +010081 case DataType::Type::kFloat64:
Lena Djokic51765b02017-06-22 13:49:59 +020082 DCHECK_EQ(2u, instruction->GetVectorLength());
83 __ ReplicateFPToVectorRegister(dst,
84 locations->InAt(0).AsFpuRegister<FRegister>(),
85 /* is_double */ true);
86 break;
87 default:
88 LOG(FATAL) << "Unsupported SIMD type";
89 UNREACHABLE();
90 }
Aart Bikf8f5a162017-02-06 15:35:29 -080091}
92
Aart Bik0148de42017-09-05 09:25:01 -070093void LocationsBuilderMIPS::VisitVecExtractScalar(HVecExtractScalar* instruction) {
Aart Bikf8f5a162017-02-06 15:35:29 -080094 LOG(FATAL) << "No SIMD for " << instruction->GetId();
95}
96
Aart Bik0148de42017-09-05 09:25:01 -070097void InstructionCodeGeneratorMIPS::VisitVecExtractScalar(HVecExtractScalar* instruction) {
Aart Bikf8f5a162017-02-06 15:35:29 -080098 LOG(FATAL) << "No SIMD for " << instruction->GetId();
99}
100
101// Helper to set up locations for vector unary operations.
102static void CreateVecUnOpLocations(ArenaAllocator* arena, HVecUnaryOperation* instruction) {
103 LocationSummary* locations = new (arena) LocationSummary(instruction);
104 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100105 case DataType::Type::kBool:
Lena Djokic51765b02017-06-22 13:49:59 +0200106 locations->SetInAt(0, Location::RequiresFpuRegister());
107 locations->SetOut(Location::RequiresFpuRegister(),
108 instruction->IsVecNot() ? Location::kOutputOverlap
109 : Location::kNoOutputOverlap);
110 break;
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100111 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100112 case DataType::Type::kInt8:
113 case DataType::Type::kUint16:
114 case DataType::Type::kInt16:
115 case DataType::Type::kInt32:
116 case DataType::Type::kInt64:
117 case DataType::Type::kFloat32:
118 case DataType::Type::kFloat64:
Lena Djokic51765b02017-06-22 13:49:59 +0200119 locations->SetInAt(0, Location::RequiresFpuRegister());
120 locations->SetOut(Location::RequiresFpuRegister(),
121 (instruction->IsVecNeg() || instruction->IsVecAbs())
122 ? Location::kOutputOverlap
123 : Location::kNoOutputOverlap);
Aart Bikf8f5a162017-02-06 15:35:29 -0800124 break;
125 default:
126 LOG(FATAL) << "Unsupported SIMD type";
127 UNREACHABLE();
128 }
129}
130
Aart Bik0148de42017-09-05 09:25:01 -0700131void LocationsBuilderMIPS::VisitVecReduce(HVecReduce* instruction) {
132 CreateVecUnOpLocations(GetGraph()->GetArena(), instruction);
133}
134
135void InstructionCodeGeneratorMIPS::VisitVecReduce(HVecReduce* instruction) {
136 LOG(FATAL) << "No SIMD for " << instruction->GetId();
137}
138
Aart Bikf8f5a162017-02-06 15:35:29 -0800139void LocationsBuilderMIPS::VisitVecCnv(HVecCnv* instruction) {
140 CreateVecUnOpLocations(GetGraph()->GetArena(), instruction);
141}
142
143void InstructionCodeGeneratorMIPS::VisitVecCnv(HVecCnv* instruction) {
Lena Djokic51765b02017-06-22 13:49:59 +0200144 LocationSummary* locations = instruction->GetLocations();
145 VectorRegister src = VectorRegisterFrom(locations->InAt(0));
146 VectorRegister dst = VectorRegisterFrom(locations->Out());
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100147 DataType::Type from = instruction->GetInputType();
148 DataType::Type to = instruction->GetResultType();
149 if (from == DataType::Type::kInt32 && to == DataType::Type::kFloat32) {
Lena Djokic51765b02017-06-22 13:49:59 +0200150 DCHECK_EQ(4u, instruction->GetVectorLength());
151 __ Ffint_sW(dst, src);
152 } else {
153 LOG(FATAL) << "Unsupported SIMD type";
154 }
Aart Bikf8f5a162017-02-06 15:35:29 -0800155}
156
157void LocationsBuilderMIPS::VisitVecNeg(HVecNeg* instruction) {
158 CreateVecUnOpLocations(GetGraph()->GetArena(), instruction);
159}
160
161void InstructionCodeGeneratorMIPS::VisitVecNeg(HVecNeg* instruction) {
Lena Djokic51765b02017-06-22 13:49:59 +0200162 LocationSummary* locations = instruction->GetLocations();
163 VectorRegister src = VectorRegisterFrom(locations->InAt(0));
164 VectorRegister dst = VectorRegisterFrom(locations->Out());
165 switch (instruction->GetPackedType()) {
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100166 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100167 case DataType::Type::kInt8:
Lena Djokic51765b02017-06-22 13:49:59 +0200168 DCHECK_EQ(16u, instruction->GetVectorLength());
169 __ FillB(dst, ZERO);
170 __ SubvB(dst, dst, src);
171 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100172 case DataType::Type::kUint16:
173 case DataType::Type::kInt16:
Lena Djokic51765b02017-06-22 13:49:59 +0200174 DCHECK_EQ(8u, instruction->GetVectorLength());
175 __ FillH(dst, ZERO);
176 __ SubvH(dst, dst, src);
177 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100178 case DataType::Type::kInt32:
Lena Djokic51765b02017-06-22 13:49:59 +0200179 DCHECK_EQ(4u, instruction->GetVectorLength());
180 __ FillW(dst, ZERO);
181 __ SubvW(dst, dst, src);
182 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100183 case DataType::Type::kInt64:
Lena Djokic51765b02017-06-22 13:49:59 +0200184 DCHECK_EQ(2u, instruction->GetVectorLength());
185 __ FillW(dst, ZERO);
186 __ SubvD(dst, dst, src);
187 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100188 case DataType::Type::kFloat32:
Lena Djokic51765b02017-06-22 13:49:59 +0200189 DCHECK_EQ(4u, instruction->GetVectorLength());
190 __ FillW(dst, ZERO);
191 __ FsubW(dst, dst, src);
192 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100193 case DataType::Type::kFloat64:
Lena Djokic51765b02017-06-22 13:49:59 +0200194 DCHECK_EQ(2u, instruction->GetVectorLength());
195 __ FillW(dst, ZERO);
196 __ FsubD(dst, dst, src);
197 break;
198 default:
199 LOG(FATAL) << "Unsupported SIMD type";
200 UNREACHABLE();
201 }
Aart Bikf8f5a162017-02-06 15:35:29 -0800202}
203
Aart Bik6daebeb2017-04-03 14:35:41 -0700204void LocationsBuilderMIPS::VisitVecAbs(HVecAbs* instruction) {
205 CreateVecUnOpLocations(GetGraph()->GetArena(), instruction);
206}
207
208void InstructionCodeGeneratorMIPS::VisitVecAbs(HVecAbs* instruction) {
Lena Djokic51765b02017-06-22 13:49:59 +0200209 LocationSummary* locations = instruction->GetLocations();
210 VectorRegister src = VectorRegisterFrom(locations->InAt(0));
211 VectorRegister dst = VectorRegisterFrom(locations->Out());
212 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100213 case DataType::Type::kInt8:
Lena Djokic51765b02017-06-22 13:49:59 +0200214 DCHECK_EQ(16u, instruction->GetVectorLength());
215 __ FillB(dst, ZERO); // all zeroes
216 __ Add_aB(dst, dst, src); // dst = abs(0) + abs(src)
217 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100218 case DataType::Type::kInt16:
Lena Djokic51765b02017-06-22 13:49:59 +0200219 DCHECK_EQ(8u, instruction->GetVectorLength());
220 __ FillH(dst, ZERO); // all zeroes
221 __ Add_aH(dst, dst, src); // dst = abs(0) + abs(src)
222 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100223 case DataType::Type::kInt32:
Lena Djokic51765b02017-06-22 13:49:59 +0200224 DCHECK_EQ(4u, instruction->GetVectorLength());
225 __ FillW(dst, ZERO); // all zeroes
226 __ Add_aW(dst, dst, src); // dst = abs(0) + abs(src)
227 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100228 case DataType::Type::kInt64:
Lena Djokic51765b02017-06-22 13:49:59 +0200229 DCHECK_EQ(2u, instruction->GetVectorLength());
230 __ FillW(dst, ZERO); // all zeroes
231 __ Add_aD(dst, dst, src); // dst = abs(0) + abs(src)
232 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100233 case DataType::Type::kFloat32:
Lena Djokic51765b02017-06-22 13:49:59 +0200234 DCHECK_EQ(4u, instruction->GetVectorLength());
235 __ LdiW(dst, -1); // all ones
236 __ SrliW(dst, dst, 1);
237 __ AndV(dst, dst, src);
238 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100239 case DataType::Type::kFloat64:
Lena Djokic51765b02017-06-22 13:49:59 +0200240 DCHECK_EQ(2u, instruction->GetVectorLength());
241 __ LdiD(dst, -1); // all ones
242 __ SrliD(dst, dst, 1);
243 __ AndV(dst, dst, src);
244 break;
245 default:
246 LOG(FATAL) << "Unsupported SIMD type";
247 UNREACHABLE();
248 }
Aart Bik6daebeb2017-04-03 14:35:41 -0700249}
250
Aart Bikf8f5a162017-02-06 15:35:29 -0800251void LocationsBuilderMIPS::VisitVecNot(HVecNot* instruction) {
252 CreateVecUnOpLocations(GetGraph()->GetArena(), instruction);
253}
254
255void InstructionCodeGeneratorMIPS::VisitVecNot(HVecNot* 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 Marko0ebe0d82017-09-21 22:50:39 +0100260 case DataType::Type::kBool: // special case boolean-not
Lena Djokic51765b02017-06-22 13:49:59 +0200261 DCHECK_EQ(16u, instruction->GetVectorLength());
262 __ LdiB(dst, 1);
263 __ XorV(dst, dst, src);
264 break;
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100265 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100266 case DataType::Type::kInt8:
267 case DataType::Type::kUint16:
268 case DataType::Type::kInt16:
269 case DataType::Type::kInt32:
270 case DataType::Type::kInt64:
271 case DataType::Type::kFloat32:
272 case DataType::Type::kFloat64:
Lena Djokic51765b02017-06-22 13:49:59 +0200273 DCHECK_LE(2u, instruction->GetVectorLength());
274 DCHECK_LE(instruction->GetVectorLength(), 16u);
275 __ NorV(dst, src, src); // lanes do not matter
276 break;
277 default:
278 LOG(FATAL) << "Unsupported SIMD type";
279 UNREACHABLE();
280 }
Aart Bikf8f5a162017-02-06 15:35:29 -0800281}
282
283// Helper to set up locations for vector binary operations.
284static void CreateVecBinOpLocations(ArenaAllocator* arena, HVecBinaryOperation* instruction) {
285 LocationSummary* locations = new (arena) LocationSummary(instruction);
286 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100287 case DataType::Type::kBool:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100288 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100289 case DataType::Type::kInt8:
290 case DataType::Type::kUint16:
291 case DataType::Type::kInt16:
292 case DataType::Type::kInt32:
293 case DataType::Type::kInt64:
294 case DataType::Type::kFloat32:
295 case DataType::Type::kFloat64:
Lena Djokic51765b02017-06-22 13:49:59 +0200296 locations->SetInAt(0, Location::RequiresFpuRegister());
297 locations->SetInAt(1, Location::RequiresFpuRegister());
298 locations->SetOut(Location::RequiresFpuRegister(), Location::kNoOutputOverlap);
Aart Bikf8f5a162017-02-06 15:35:29 -0800299 break;
300 default:
301 LOG(FATAL) << "Unsupported SIMD type";
302 UNREACHABLE();
303 }
304}
305
306void LocationsBuilderMIPS::VisitVecAdd(HVecAdd* instruction) {
307 CreateVecBinOpLocations(GetGraph()->GetArena(), instruction);
308}
309
310void InstructionCodeGeneratorMIPS::VisitVecAdd(HVecAdd* instruction) {
Lena Djokic51765b02017-06-22 13:49:59 +0200311 LocationSummary* locations = instruction->GetLocations();
312 VectorRegister lhs = VectorRegisterFrom(locations->InAt(0));
313 VectorRegister rhs = VectorRegisterFrom(locations->InAt(1));
314 VectorRegister dst = VectorRegisterFrom(locations->Out());
315 switch (instruction->GetPackedType()) {
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100316 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100317 case DataType::Type::kInt8:
Lena Djokic51765b02017-06-22 13:49:59 +0200318 DCHECK_EQ(16u, instruction->GetVectorLength());
319 __ AddvB(dst, lhs, rhs);
320 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100321 case DataType::Type::kUint16:
322 case DataType::Type::kInt16:
Lena Djokic51765b02017-06-22 13:49:59 +0200323 DCHECK_EQ(8u, instruction->GetVectorLength());
324 __ AddvH(dst, lhs, rhs);
325 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100326 case DataType::Type::kInt32:
Lena Djokic51765b02017-06-22 13:49:59 +0200327 DCHECK_EQ(4u, instruction->GetVectorLength());
328 __ AddvW(dst, lhs, rhs);
329 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100330 case DataType::Type::kInt64:
Lena Djokic51765b02017-06-22 13:49:59 +0200331 DCHECK_EQ(2u, instruction->GetVectorLength());
332 __ AddvD(dst, lhs, rhs);
333 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100334 case DataType::Type::kFloat32:
Lena Djokic51765b02017-06-22 13:49:59 +0200335 DCHECK_EQ(4u, instruction->GetVectorLength());
336 __ FaddW(dst, lhs, rhs);
337 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100338 case DataType::Type::kFloat64:
Lena Djokic51765b02017-06-22 13:49:59 +0200339 DCHECK_EQ(2u, instruction->GetVectorLength());
340 __ FaddD(dst, lhs, rhs);
341 break;
342 default:
343 LOG(FATAL) << "Unsupported SIMD type";
344 UNREACHABLE();
345 }
Aart Bikf8f5a162017-02-06 15:35:29 -0800346}
347
Aart Bikf3e61ee2017-04-12 17:09:20 -0700348void LocationsBuilderMIPS::VisitVecHalvingAdd(HVecHalvingAdd* instruction) {
349 CreateVecBinOpLocations(GetGraph()->GetArena(), instruction);
350}
351
352void InstructionCodeGeneratorMIPS::VisitVecHalvingAdd(HVecHalvingAdd* instruction) {
Lena Djokic51765b02017-06-22 13:49:59 +0200353 LocationSummary* locations = instruction->GetLocations();
354 VectorRegister lhs = VectorRegisterFrom(locations->InAt(0));
355 VectorRegister rhs = VectorRegisterFrom(locations->InAt(1));
356 VectorRegister dst = VectorRegisterFrom(locations->Out());
357 switch (instruction->GetPackedType()) {
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100358 case DataType::Type::kUint8:
359 DCHECK_EQ(16u, instruction->GetVectorLength());
360 instruction->IsRounded()
361 ? __ Aver_uB(dst, lhs, rhs)
362 : __ Ave_uB(dst, lhs, rhs);
363 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100364 case DataType::Type::kInt8:
Lena Djokic51765b02017-06-22 13:49:59 +0200365 DCHECK_EQ(16u, instruction->GetVectorLength());
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100366 instruction->IsRounded()
367 ? __ Aver_sB(dst, lhs, rhs)
368 : __ Ave_sB(dst, lhs, rhs);
Lena Djokic51765b02017-06-22 13:49:59 +0200369 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100370 case DataType::Type::kUint16:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100371 DCHECK_EQ(8u, instruction->GetVectorLength());
372 instruction->IsRounded()
373 ? __ Aver_uH(dst, lhs, rhs)
374 : __ Ave_uH(dst, lhs, rhs);
375 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100376 case DataType::Type::kInt16:
Lena Djokic51765b02017-06-22 13:49:59 +0200377 DCHECK_EQ(8u, instruction->GetVectorLength());
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100378 instruction->IsRounded()
379 ? __ Aver_sH(dst, lhs, rhs)
380 : __ Ave_sH(dst, lhs, rhs);
Lena Djokic51765b02017-06-22 13:49:59 +0200381 break;
382 default:
383 LOG(FATAL) << "Unsupported SIMD type";
384 UNREACHABLE();
385 }
Aart Bikf3e61ee2017-04-12 17:09:20 -0700386}
387
Aart Bikf8f5a162017-02-06 15:35:29 -0800388void LocationsBuilderMIPS::VisitVecSub(HVecSub* instruction) {
389 CreateVecBinOpLocations(GetGraph()->GetArena(), instruction);
390}
391
392void InstructionCodeGeneratorMIPS::VisitVecSub(HVecSub* instruction) {
Lena Djokic51765b02017-06-22 13:49:59 +0200393 LocationSummary* locations = instruction->GetLocations();
394 VectorRegister lhs = VectorRegisterFrom(locations->InAt(0));
395 VectorRegister rhs = VectorRegisterFrom(locations->InAt(1));
396 VectorRegister dst = VectorRegisterFrom(locations->Out());
397 switch (instruction->GetPackedType()) {
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100398 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100399 case DataType::Type::kInt8:
Lena Djokic51765b02017-06-22 13:49:59 +0200400 DCHECK_EQ(16u, instruction->GetVectorLength());
401 __ SubvB(dst, lhs, rhs);
402 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100403 case DataType::Type::kUint16:
404 case DataType::Type::kInt16:
Lena Djokic51765b02017-06-22 13:49:59 +0200405 DCHECK_EQ(8u, instruction->GetVectorLength());
406 __ SubvH(dst, lhs, rhs);
407 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100408 case DataType::Type::kInt32:
Lena Djokic51765b02017-06-22 13:49:59 +0200409 DCHECK_EQ(4u, instruction->GetVectorLength());
410 __ SubvW(dst, lhs, rhs);
411 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100412 case DataType::Type::kInt64:
Lena Djokic51765b02017-06-22 13:49:59 +0200413 DCHECK_EQ(2u, instruction->GetVectorLength());
414 __ SubvD(dst, lhs, rhs);
415 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100416 case DataType::Type::kFloat32:
Lena Djokic51765b02017-06-22 13:49:59 +0200417 DCHECK_EQ(4u, instruction->GetVectorLength());
418 __ FsubW(dst, lhs, rhs);
419 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100420 case DataType::Type::kFloat64:
Lena Djokic51765b02017-06-22 13:49:59 +0200421 DCHECK_EQ(2u, instruction->GetVectorLength());
422 __ FsubD(dst, lhs, rhs);
423 break;
424 default:
425 LOG(FATAL) << "Unsupported SIMD type";
426 UNREACHABLE();
427 }
Aart Bikf8f5a162017-02-06 15:35:29 -0800428}
429
430void LocationsBuilderMIPS::VisitVecMul(HVecMul* instruction) {
431 CreateVecBinOpLocations(GetGraph()->GetArena(), instruction);
432}
433
434void InstructionCodeGeneratorMIPS::VisitVecMul(HVecMul* instruction) {
Lena Djokic51765b02017-06-22 13:49:59 +0200435 LocationSummary* locations = instruction->GetLocations();
436 VectorRegister lhs = VectorRegisterFrom(locations->InAt(0));
437 VectorRegister rhs = VectorRegisterFrom(locations->InAt(1));
438 VectorRegister dst = VectorRegisterFrom(locations->Out());
439 switch (instruction->GetPackedType()) {
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100440 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100441 case DataType::Type::kInt8:
Lena Djokic51765b02017-06-22 13:49:59 +0200442 DCHECK_EQ(16u, instruction->GetVectorLength());
443 __ MulvB(dst, lhs, rhs);
444 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100445 case DataType::Type::kUint16:
446 case DataType::Type::kInt16:
Lena Djokic51765b02017-06-22 13:49:59 +0200447 DCHECK_EQ(8u, instruction->GetVectorLength());
448 __ MulvH(dst, lhs, rhs);
449 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100450 case DataType::Type::kInt32:
Lena Djokic51765b02017-06-22 13:49:59 +0200451 DCHECK_EQ(4u, instruction->GetVectorLength());
452 __ MulvW(dst, lhs, rhs);
453 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100454 case DataType::Type::kInt64:
Lena Djokic51765b02017-06-22 13:49:59 +0200455 DCHECK_EQ(2u, instruction->GetVectorLength());
456 __ MulvD(dst, lhs, rhs);
457 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100458 case DataType::Type::kFloat32:
Lena Djokic51765b02017-06-22 13:49:59 +0200459 DCHECK_EQ(4u, instruction->GetVectorLength());
460 __ FmulW(dst, lhs, rhs);
461 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100462 case DataType::Type::kFloat64:
Lena Djokic51765b02017-06-22 13:49:59 +0200463 DCHECK_EQ(2u, instruction->GetVectorLength());
464 __ FmulD(dst, lhs, rhs);
465 break;
466 default:
467 LOG(FATAL) << "Unsupported SIMD type";
468 UNREACHABLE();
469 }
Aart Bikf8f5a162017-02-06 15:35:29 -0800470}
471
472void LocationsBuilderMIPS::VisitVecDiv(HVecDiv* instruction) {
473 CreateVecBinOpLocations(GetGraph()->GetArena(), instruction);
474}
475
476void InstructionCodeGeneratorMIPS::VisitVecDiv(HVecDiv* instruction) {
Lena Djokic51765b02017-06-22 13:49:59 +0200477 LocationSummary* locations = instruction->GetLocations();
478 VectorRegister lhs = VectorRegisterFrom(locations->InAt(0));
479 VectorRegister rhs = VectorRegisterFrom(locations->InAt(1));
480 VectorRegister dst = VectorRegisterFrom(locations->Out());
481 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100482 case DataType::Type::kFloat32:
Lena Djokic51765b02017-06-22 13:49:59 +0200483 DCHECK_EQ(4u, instruction->GetVectorLength());
484 __ FdivW(dst, lhs, rhs);
485 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100486 case DataType::Type::kFloat64:
Lena Djokic51765b02017-06-22 13:49:59 +0200487 DCHECK_EQ(2u, instruction->GetVectorLength());
488 __ FdivD(dst, lhs, rhs);
489 break;
490 default:
491 LOG(FATAL) << "Unsupported SIMD type";
492 UNREACHABLE();
493 }
Aart Bikf8f5a162017-02-06 15:35:29 -0800494}
495
Aart Bikf3e61ee2017-04-12 17:09:20 -0700496void LocationsBuilderMIPS::VisitVecMin(HVecMin* instruction) {
497 CreateVecBinOpLocations(GetGraph()->GetArena(), instruction);
498}
499
500void InstructionCodeGeneratorMIPS::VisitVecMin(HVecMin* instruction) {
Lena Djokic51765b02017-06-22 13:49:59 +0200501 LocationSummary* locations = instruction->GetLocations();
502 VectorRegister lhs = VectorRegisterFrom(locations->InAt(0));
503 VectorRegister rhs = VectorRegisterFrom(locations->InAt(1));
504 VectorRegister dst = VectorRegisterFrom(locations->Out());
505 switch (instruction->GetPackedType()) {
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100506 case DataType::Type::kUint8:
507 DCHECK_EQ(16u, instruction->GetVectorLength());
508 __ Min_uB(dst, lhs, rhs);
509 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100510 case DataType::Type::kInt8:
Lena Djokic51765b02017-06-22 13:49:59 +0200511 DCHECK_EQ(16u, instruction->GetVectorLength());
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100512 __ Min_sB(dst, lhs, rhs);
Lena Djokic51765b02017-06-22 13:49:59 +0200513 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100514 case DataType::Type::kUint16:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100515 DCHECK_EQ(8u, instruction->GetVectorLength());
516 __ Min_uH(dst, lhs, rhs);
517 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100518 case DataType::Type::kInt16:
Lena Djokic51765b02017-06-22 13:49:59 +0200519 DCHECK_EQ(8u, instruction->GetVectorLength());
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100520 __ Min_sH(dst, lhs, rhs);
Lena Djokic51765b02017-06-22 13:49:59 +0200521 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100522 case DataType::Type::kInt32:
Lena Djokic51765b02017-06-22 13:49:59 +0200523 DCHECK_EQ(4u, instruction->GetVectorLength());
524 if (instruction->IsUnsigned()) {
525 __ Min_uW(dst, lhs, rhs);
526 } else {
527 __ Min_sW(dst, lhs, rhs);
528 }
529 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100530 case DataType::Type::kInt64:
Lena Djokic51765b02017-06-22 13:49:59 +0200531 DCHECK_EQ(2u, instruction->GetVectorLength());
532 if (instruction->IsUnsigned()) {
533 __ Min_uD(dst, lhs, rhs);
534 } else {
535 __ Min_sD(dst, lhs, rhs);
536 }
537 break;
538 // When one of arguments is NaN, fmin.df returns other argument, but Java expects a NaN value.
539 // TODO: Fix min(x, NaN) cases for float and double.
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100540 case DataType::Type::kFloat32:
Lena Djokic51765b02017-06-22 13:49:59 +0200541 DCHECK_EQ(4u, instruction->GetVectorLength());
542 DCHECK(!instruction->IsUnsigned());
543 __ FminW(dst, lhs, rhs);
544 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100545 case DataType::Type::kFloat64:
Lena Djokic51765b02017-06-22 13:49:59 +0200546 DCHECK_EQ(2u, instruction->GetVectorLength());
547 DCHECK(!instruction->IsUnsigned());
548 __ FminD(dst, lhs, rhs);
549 break;
550 default:
551 LOG(FATAL) << "Unsupported SIMD type";
552 UNREACHABLE();
553 }
Aart Bikf3e61ee2017-04-12 17:09:20 -0700554}
555
556void LocationsBuilderMIPS::VisitVecMax(HVecMax* instruction) {
557 CreateVecBinOpLocations(GetGraph()->GetArena(), instruction);
558}
559
560void InstructionCodeGeneratorMIPS::VisitVecMax(HVecMax* instruction) {
Lena Djokic51765b02017-06-22 13:49:59 +0200561 LocationSummary* locations = instruction->GetLocations();
562 VectorRegister lhs = VectorRegisterFrom(locations->InAt(0));
563 VectorRegister rhs = VectorRegisterFrom(locations->InAt(1));
564 VectorRegister dst = VectorRegisterFrom(locations->Out());
565 switch (instruction->GetPackedType()) {
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100566 case DataType::Type::kUint8:
567 DCHECK_EQ(16u, instruction->GetVectorLength());
568 __ Max_uB(dst, lhs, rhs);
569 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100570 case DataType::Type::kInt8:
Lena Djokic51765b02017-06-22 13:49:59 +0200571 DCHECK_EQ(16u, instruction->GetVectorLength());
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100572 __ Max_sB(dst, lhs, rhs);
Lena Djokic51765b02017-06-22 13:49:59 +0200573 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100574 case DataType::Type::kUint16:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100575 DCHECK_EQ(8u, instruction->GetVectorLength());
576 __ Max_uH(dst, lhs, rhs);
577 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100578 case DataType::Type::kInt16:
Lena Djokic51765b02017-06-22 13:49:59 +0200579 DCHECK_EQ(8u, instruction->GetVectorLength());
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100580 __ Max_sH(dst, lhs, rhs);
Lena Djokic51765b02017-06-22 13:49:59 +0200581 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100582 case DataType::Type::kInt32:
Lena Djokic51765b02017-06-22 13:49:59 +0200583 DCHECK_EQ(4u, instruction->GetVectorLength());
584 if (instruction->IsUnsigned()) {
585 __ Max_uW(dst, lhs, rhs);
586 } else {
587 __ Max_sW(dst, lhs, rhs);
588 }
589 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100590 case DataType::Type::kInt64:
Lena Djokic51765b02017-06-22 13:49:59 +0200591 DCHECK_EQ(2u, instruction->GetVectorLength());
592 if (instruction->IsUnsigned()) {
593 __ Max_uD(dst, lhs, rhs);
594 } else {
595 __ Max_sD(dst, lhs, rhs);
596 }
597 break;
598 // When one of arguments is NaN, fmax.df returns other argument, but Java expects a NaN value.
599 // TODO: Fix max(x, NaN) cases for float and double.
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100600 case DataType::Type::kFloat32:
Lena Djokic51765b02017-06-22 13:49:59 +0200601 DCHECK_EQ(4u, instruction->GetVectorLength());
602 DCHECK(!instruction->IsUnsigned());
603 __ FmaxW(dst, lhs, rhs);
604 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100605 case DataType::Type::kFloat64:
Lena Djokic51765b02017-06-22 13:49:59 +0200606 DCHECK_EQ(2u, instruction->GetVectorLength());
607 DCHECK(!instruction->IsUnsigned());
608 __ FmaxD(dst, lhs, rhs);
609 break;
610 default:
611 LOG(FATAL) << "Unsupported SIMD type";
612 UNREACHABLE();
613 }
Aart Bikf3e61ee2017-04-12 17:09:20 -0700614}
615
Aart Bikf8f5a162017-02-06 15:35:29 -0800616void LocationsBuilderMIPS::VisitVecAnd(HVecAnd* instruction) {
617 CreateVecBinOpLocations(GetGraph()->GetArena(), instruction);
618}
619
620void InstructionCodeGeneratorMIPS::VisitVecAnd(HVecAnd* instruction) {
Lena Djokic51765b02017-06-22 13:49:59 +0200621 LocationSummary* locations = instruction->GetLocations();
622 VectorRegister lhs = VectorRegisterFrom(locations->InAt(0));
623 VectorRegister rhs = VectorRegisterFrom(locations->InAt(1));
624 VectorRegister dst = VectorRegisterFrom(locations->Out());
625 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100626 case DataType::Type::kBool:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100627 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100628 case DataType::Type::kInt8:
629 case DataType::Type::kUint16:
630 case DataType::Type::kInt16:
631 case DataType::Type::kInt32:
632 case DataType::Type::kInt64:
633 case DataType::Type::kFloat32:
634 case DataType::Type::kFloat64:
Lena Djokic51765b02017-06-22 13:49:59 +0200635 DCHECK_LE(2u, instruction->GetVectorLength());
636 DCHECK_LE(instruction->GetVectorLength(), 16u);
637 __ AndV(dst, lhs, rhs); // lanes do not matter
638 break;
639 default:
640 LOG(FATAL) << "Unsupported SIMD type";
641 UNREACHABLE();
642 }
Aart Bikf8f5a162017-02-06 15:35:29 -0800643}
644
645void LocationsBuilderMIPS::VisitVecAndNot(HVecAndNot* instruction) {
646 CreateVecBinOpLocations(GetGraph()->GetArena(), instruction);
647}
648
649void InstructionCodeGeneratorMIPS::VisitVecAndNot(HVecAndNot* instruction) {
650 LOG(FATAL) << "No SIMD for " << instruction->GetId();
651}
652
653void LocationsBuilderMIPS::VisitVecOr(HVecOr* instruction) {
654 CreateVecBinOpLocations(GetGraph()->GetArena(), instruction);
655}
656
657void InstructionCodeGeneratorMIPS::VisitVecOr(HVecOr* instruction) {
Lena Djokic51765b02017-06-22 13:49:59 +0200658 LocationSummary* locations = instruction->GetLocations();
659 VectorRegister lhs = VectorRegisterFrom(locations->InAt(0));
660 VectorRegister rhs = VectorRegisterFrom(locations->InAt(1));
661 VectorRegister dst = VectorRegisterFrom(locations->Out());
662 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100663 case DataType::Type::kBool:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100664 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100665 case DataType::Type::kInt8:
666 case DataType::Type::kUint16:
667 case DataType::Type::kInt16:
668 case DataType::Type::kInt32:
669 case DataType::Type::kInt64:
670 case DataType::Type::kFloat32:
671 case DataType::Type::kFloat64:
Lena Djokic51765b02017-06-22 13:49:59 +0200672 DCHECK_LE(2u, instruction->GetVectorLength());
673 DCHECK_LE(instruction->GetVectorLength(), 16u);
674 __ OrV(dst, lhs, rhs); // lanes do not matter
675 break;
676 default:
677 LOG(FATAL) << "Unsupported SIMD type";
678 UNREACHABLE();
679 }
Aart Bikf8f5a162017-02-06 15:35:29 -0800680}
681
682void LocationsBuilderMIPS::VisitVecXor(HVecXor* instruction) {
683 CreateVecBinOpLocations(GetGraph()->GetArena(), instruction);
684}
685
686void InstructionCodeGeneratorMIPS::VisitVecXor(HVecXor* instruction) {
Lena Djokic51765b02017-06-22 13:49:59 +0200687 LocationSummary* locations = instruction->GetLocations();
688 VectorRegister lhs = VectorRegisterFrom(locations->InAt(0));
689 VectorRegister rhs = VectorRegisterFrom(locations->InAt(1));
690 VectorRegister dst = VectorRegisterFrom(locations->Out());
691 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100692 case DataType::Type::kBool:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100693 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100694 case DataType::Type::kInt8:
695 case DataType::Type::kUint16:
696 case DataType::Type::kInt16:
697 case DataType::Type::kInt32:
698 case DataType::Type::kInt64:
699 case DataType::Type::kFloat32:
700 case DataType::Type::kFloat64:
Lena Djokic51765b02017-06-22 13:49:59 +0200701 DCHECK_LE(2u, instruction->GetVectorLength());
702 DCHECK_LE(instruction->GetVectorLength(), 16u);
703 __ XorV(dst, lhs, rhs); // lanes do not matter
704 break;
705 default:
706 LOG(FATAL) << "Unsupported SIMD type";
707 UNREACHABLE();
708 }
Aart Bikf8f5a162017-02-06 15:35:29 -0800709}
710
711// Helper to set up locations for vector shift operations.
712static void CreateVecShiftLocations(ArenaAllocator* arena, HVecBinaryOperation* instruction) {
713 LocationSummary* locations = new (arena) LocationSummary(instruction);
714 switch (instruction->GetPackedType()) {
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100715 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100716 case DataType::Type::kInt8:
717 case DataType::Type::kUint16:
718 case DataType::Type::kInt16:
719 case DataType::Type::kInt32:
720 case DataType::Type::kInt64:
Lena Djokic51765b02017-06-22 13:49:59 +0200721 locations->SetInAt(0, Location::RequiresFpuRegister());
722 locations->SetInAt(1, Location::ConstantLocation(instruction->InputAt(1)->AsConstant()));
723 locations->SetOut(Location::RequiresFpuRegister(), Location::kNoOutputOverlap);
Aart Bikf8f5a162017-02-06 15:35:29 -0800724 break;
725 default:
726 LOG(FATAL) << "Unsupported SIMD type";
727 UNREACHABLE();
728 }
729}
730
731void LocationsBuilderMIPS::VisitVecShl(HVecShl* instruction) {
732 CreateVecShiftLocations(GetGraph()->GetArena(), instruction);
733}
734
735void InstructionCodeGeneratorMIPS::VisitVecShl(HVecShl* instruction) {
Lena Djokic51765b02017-06-22 13:49:59 +0200736 LocationSummary* locations = instruction->GetLocations();
737 VectorRegister lhs = VectorRegisterFrom(locations->InAt(0));
738 VectorRegister dst = VectorRegisterFrom(locations->Out());
739 int32_t value = locations->InAt(1).GetConstant()->AsIntConstant()->GetValue();
740 switch (instruction->GetPackedType()) {
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100741 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100742 case DataType::Type::kInt8:
Lena Djokic51765b02017-06-22 13:49:59 +0200743 DCHECK_EQ(16u, instruction->GetVectorLength());
744 __ SlliB(dst, lhs, value);
745 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100746 case DataType::Type::kUint16:
747 case DataType::Type::kInt16:
Lena Djokic51765b02017-06-22 13:49:59 +0200748 DCHECK_EQ(8u, instruction->GetVectorLength());
749 __ SlliH(dst, lhs, value);
750 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100751 case DataType::Type::kInt32:
Lena Djokic51765b02017-06-22 13:49:59 +0200752 DCHECK_EQ(4u, instruction->GetVectorLength());
753 __ SlliW(dst, lhs, value);
754 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100755 case DataType::Type::kInt64:
Lena Djokic51765b02017-06-22 13:49:59 +0200756 DCHECK_EQ(2u, instruction->GetVectorLength());
757 __ SlliD(dst, lhs, value);
758 break;
759 default:
760 LOG(FATAL) << "Unsupported SIMD type";
761 UNREACHABLE();
762 }
Aart Bikf8f5a162017-02-06 15:35:29 -0800763}
764
765void LocationsBuilderMIPS::VisitVecShr(HVecShr* instruction) {
766 CreateVecShiftLocations(GetGraph()->GetArena(), instruction);
767}
768
769void InstructionCodeGeneratorMIPS::VisitVecShr(HVecShr* instruction) {
Lena Djokic51765b02017-06-22 13:49:59 +0200770 LocationSummary* locations = instruction->GetLocations();
771 VectorRegister lhs = VectorRegisterFrom(locations->InAt(0));
772 VectorRegister dst = VectorRegisterFrom(locations->Out());
773 int32_t value = locations->InAt(1).GetConstant()->AsIntConstant()->GetValue();
774 switch (instruction->GetPackedType()) {
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100775 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100776 case DataType::Type::kInt8:
Lena Djokic51765b02017-06-22 13:49:59 +0200777 DCHECK_EQ(16u, instruction->GetVectorLength());
778 __ SraiB(dst, lhs, value);
779 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100780 case DataType::Type::kUint16:
781 case DataType::Type::kInt16:
Lena Djokic51765b02017-06-22 13:49:59 +0200782 DCHECK_EQ(8u, instruction->GetVectorLength());
783 __ SraiH(dst, lhs, value);
784 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100785 case DataType::Type::kInt32:
Lena Djokic51765b02017-06-22 13:49:59 +0200786 DCHECK_EQ(4u, instruction->GetVectorLength());
787 __ SraiW(dst, lhs, value);
788 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100789 case DataType::Type::kInt64:
Lena Djokic51765b02017-06-22 13:49:59 +0200790 DCHECK_EQ(2u, instruction->GetVectorLength());
791 __ SraiD(dst, lhs, value);
792 break;
793 default:
794 LOG(FATAL) << "Unsupported SIMD type";
795 UNREACHABLE();
796 }
Aart Bikf8f5a162017-02-06 15:35:29 -0800797}
798
799void LocationsBuilderMIPS::VisitVecUShr(HVecUShr* instruction) {
800 CreateVecShiftLocations(GetGraph()->GetArena(), instruction);
801}
802
803void InstructionCodeGeneratorMIPS::VisitVecUShr(HVecUShr* instruction) {
Lena Djokic51765b02017-06-22 13:49:59 +0200804 LocationSummary* locations = instruction->GetLocations();
805 VectorRegister lhs = VectorRegisterFrom(locations->InAt(0));
806 VectorRegister dst = VectorRegisterFrom(locations->Out());
807 int32_t value = locations->InAt(1).GetConstant()->AsIntConstant()->GetValue();
808 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:
Lena Djokic51765b02017-06-22 13:49:59 +0200811 DCHECK_EQ(16u, instruction->GetVectorLength());
812 __ SrliB(dst, lhs, value);
813 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100814 case DataType::Type::kUint16:
815 case DataType::Type::kInt16:
Lena Djokic51765b02017-06-22 13:49:59 +0200816 DCHECK_EQ(8u, instruction->GetVectorLength());
817 __ SrliH(dst, lhs, value);
818 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100819 case DataType::Type::kInt32:
Lena Djokic51765b02017-06-22 13:49:59 +0200820 DCHECK_EQ(4u, instruction->GetVectorLength());
821 __ SrliW(dst, lhs, value);
822 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100823 case DataType::Type::kInt64:
Lena Djokic51765b02017-06-22 13:49:59 +0200824 DCHECK_EQ(2u, instruction->GetVectorLength());
825 __ SrliD(dst, lhs, value);
826 break;
827 default:
828 LOG(FATAL) << "Unsupported SIMD type";
829 UNREACHABLE();
830 }
Aart Bikf8f5a162017-02-06 15:35:29 -0800831}
832
Aart Bik0148de42017-09-05 09:25:01 -0700833void LocationsBuilderMIPS::VisitVecSetScalars(HVecSetScalars* instruction) {
834 LOG(FATAL) << "No SIMD for " << instruction->GetId();
835}
836
837void InstructionCodeGeneratorMIPS::VisitVecSetScalars(HVecSetScalars* instruction) {
838 LOG(FATAL) << "No SIMD for " << instruction->GetId();
839}
840
Aart Bikdbbac8f2017-09-01 13:06:08 -0700841// Helper to set up locations for vector accumulations.
842static void CreateVecAccumLocations(ArenaAllocator* arena, HVecOperation* instruction) {
843 LocationSummary* locations = new (arena) LocationSummary(instruction);
844 switch (instruction->GetPackedType()) {
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100845 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100846 case DataType::Type::kInt8:
847 case DataType::Type::kUint16:
848 case DataType::Type::kInt16:
849 case DataType::Type::kInt32:
850 case DataType::Type::kInt64:
Aart Bikdbbac8f2017-09-01 13:06:08 -0700851 locations->SetInAt(0, Location::RequiresFpuRegister());
852 locations->SetInAt(1, Location::RequiresFpuRegister());
853 locations->SetInAt(2, Location::RequiresFpuRegister());
Lena Djokicbc5460b2017-07-20 16:07:36 +0200854 locations->SetOut(Location::SameAsFirstInput());
855 break;
856 default:
857 LOG(FATAL) << "Unsupported SIMD type";
858 UNREACHABLE();
859 }
Artem Serovf34dd202017-04-10 17:41:46 +0100860}
861
Aart Bikdbbac8f2017-09-01 13:06:08 -0700862void LocationsBuilderMIPS::VisitVecMultiplyAccumulate(HVecMultiplyAccumulate* instruction) {
863 CreateVecAccumLocations(GetGraph()->GetArena(), instruction);
864}
865
866void InstructionCodeGeneratorMIPS::VisitVecMultiplyAccumulate(HVecMultiplyAccumulate* instruction) {
867 LocationSummary* locations = instruction->GetLocations();
868 VectorRegister acc = VectorRegisterFrom(locations->InAt(0));
869 VectorRegister left = VectorRegisterFrom(locations->InAt(1));
870 VectorRegister right = VectorRegisterFrom(locations->InAt(2));
871 switch (instruction->GetPackedType()) {
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100872 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100873 case DataType::Type::kInt8:
Aart Bikdbbac8f2017-09-01 13:06:08 -0700874 DCHECK_EQ(16u, instruction->GetVectorLength());
875 if (instruction->GetOpKind() == HInstruction::kAdd) {
Lena Djokicbc5460b2017-07-20 16:07:36 +0200876 __ MaddvB(acc, left, right);
877 } else {
878 __ MsubvB(acc, left, right);
879 }
880 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100881 case DataType::Type::kUint16:
882 case DataType::Type::kInt16:
Aart Bikdbbac8f2017-09-01 13:06:08 -0700883 DCHECK_EQ(8u, instruction->GetVectorLength());
884 if (instruction->GetOpKind() == HInstruction::kAdd) {
Lena Djokicbc5460b2017-07-20 16:07:36 +0200885 __ MaddvH(acc, left, right);
886 } else {
887 __ MsubvH(acc, left, right);
888 }
889 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100890 case DataType::Type::kInt32:
Aart Bikdbbac8f2017-09-01 13:06:08 -0700891 DCHECK_EQ(4u, instruction->GetVectorLength());
892 if (instruction->GetOpKind() == HInstruction::kAdd) {
Lena Djokicbc5460b2017-07-20 16:07:36 +0200893 __ MaddvW(acc, left, right);
894 } else {
895 __ MsubvW(acc, left, right);
896 }
897 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100898 case DataType::Type::kInt64:
Aart Bikdbbac8f2017-09-01 13:06:08 -0700899 DCHECK_EQ(2u, instruction->GetVectorLength());
900 if (instruction->GetOpKind() == HInstruction::kAdd) {
Lena Djokicbc5460b2017-07-20 16:07:36 +0200901 __ MaddvD(acc, left, right);
902 } else {
903 __ MsubvD(acc, left, right);
904 }
905 break;
906 default:
907 LOG(FATAL) << "Unsupported SIMD type";
908 UNREACHABLE();
909 }
Artem Serovf34dd202017-04-10 17:41:46 +0100910}
911
Aart Bikdbbac8f2017-09-01 13:06:08 -0700912void LocationsBuilderMIPS::VisitVecSADAccumulate(HVecSADAccumulate* instruction) {
913 CreateVecAccumLocations(GetGraph()->GetArena(), instruction);
914}
915
916void InstructionCodeGeneratorMIPS::VisitVecSADAccumulate(HVecSADAccumulate* instruction) {
917 LOG(FATAL) << "No SIMD for " << instruction->GetId();
918 // TODO: implement this, location helper already filled out (shared with MulAcc).
919}
920
Lena Djokic51765b02017-06-22 13:49:59 +0200921// Helper to set up locations for vector memory operations.
922static void CreateVecMemLocations(ArenaAllocator* arena,
923 HVecMemoryOperation* instruction,
924 bool is_load) {
925 LocationSummary* locations = new (arena) LocationSummary(instruction);
926 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100927 case DataType::Type::kBool:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100928 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100929 case DataType::Type::kInt8:
930 case DataType::Type::kUint16:
931 case DataType::Type::kInt16:
932 case DataType::Type::kInt32:
933 case DataType::Type::kInt64:
934 case DataType::Type::kFloat32:
935 case DataType::Type::kFloat64:
Lena Djokic51765b02017-06-22 13:49:59 +0200936 locations->SetInAt(0, Location::RequiresRegister());
937 locations->SetInAt(1, Location::RegisterOrConstant(instruction->InputAt(1)));
938 if (is_load) {
939 locations->SetOut(Location::RequiresFpuRegister());
940 } else {
941 locations->SetInAt(2, Location::RequiresFpuRegister());
942 }
943 break;
944 default:
945 LOG(FATAL) << "Unsupported SIMD type";
946 UNREACHABLE();
947 }
948}
949
950// Helper to prepare register and offset for vector memory operations. Returns the offset and sets
951// the output parameter adjusted_base to the original base or to a reserved temporary register (AT).
952int32_t InstructionCodeGeneratorMIPS::VecAddress(LocationSummary* locations,
953 size_t size,
954 /* out */ Register* adjusted_base) {
955 Register base = locations->InAt(0).AsRegister<Register>();
956 Location index = locations->InAt(1);
957 int scale = TIMES_1;
958 switch (size) {
959 case 2: scale = TIMES_2; break;
960 case 4: scale = TIMES_4; break;
961 case 8: scale = TIMES_8; break;
962 default: break;
963 }
964 int32_t offset = mirror::Array::DataOffset(size).Int32Value();
965
966 if (index.IsConstant()) {
967 offset += index.GetConstant()->AsIntConstant()->GetValue() << scale;
968 __ AdjustBaseOffsetAndElementSizeShift(base, offset, scale);
969 *adjusted_base = base;
970 } else {
971 Register index_reg = index.AsRegister<Register>();
972 if (scale != TIMES_1) {
973 __ Lsa(AT, index_reg, base, scale);
974 } else {
975 __ Addu(AT, base, index_reg);
976 }
977 *adjusted_base = AT;
978 }
979 return offset;
980}
981
Aart Bikf8f5a162017-02-06 15:35:29 -0800982void LocationsBuilderMIPS::VisitVecLoad(HVecLoad* instruction) {
Lena Djokic51765b02017-06-22 13:49:59 +0200983 CreateVecMemLocations(GetGraph()->GetArena(), instruction, /* is_load */ true);
Aart Bikf8f5a162017-02-06 15:35:29 -0800984}
985
986void InstructionCodeGeneratorMIPS::VisitVecLoad(HVecLoad* instruction) {
Lena Djokic51765b02017-06-22 13:49:59 +0200987 LocationSummary* locations = instruction->GetLocations();
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100988 size_t size = DataType::Size(instruction->GetPackedType());
Lena Djokic51765b02017-06-22 13:49:59 +0200989 VectorRegister reg = VectorRegisterFrom(locations->Out());
990 Register base;
991 int32_t offset = VecAddress(locations, size, &base);
992 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100993 case DataType::Type::kBool:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100994 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100995 case DataType::Type::kInt8:
Lena Djokic51765b02017-06-22 13:49:59 +0200996 DCHECK_EQ(16u, instruction->GetVectorLength());
997 __ LdB(reg, base, offset);
998 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100999 case DataType::Type::kUint16:
1000 case DataType::Type::kInt16:
Lena Djokic51765b02017-06-22 13:49:59 +02001001 // Loading 8-bytes (needed if dealing with compressed strings in StringCharAt) from unaligned
1002 // memory address may cause a trap to the kernel if the CPU doesn't directly support unaligned
1003 // loads and stores.
1004 // TODO: Implement support for StringCharAt.
1005 DCHECK(!instruction->IsStringCharAt());
1006 DCHECK_EQ(8u, instruction->GetVectorLength());
1007 __ LdH(reg, base, offset);
1008 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001009 case DataType::Type::kInt32:
1010 case DataType::Type::kFloat32:
Lena Djokic51765b02017-06-22 13:49:59 +02001011 DCHECK_EQ(4u, instruction->GetVectorLength());
1012 __ LdW(reg, base, offset);
1013 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001014 case DataType::Type::kInt64:
1015 case DataType::Type::kFloat64:
Lena Djokic51765b02017-06-22 13:49:59 +02001016 DCHECK_EQ(2u, instruction->GetVectorLength());
1017 __ LdD(reg, base, offset);
1018 break;
1019 default:
1020 LOG(FATAL) << "Unsupported SIMD type";
1021 UNREACHABLE();
1022 }
Aart Bikf8f5a162017-02-06 15:35:29 -08001023}
1024
1025void LocationsBuilderMIPS::VisitVecStore(HVecStore* instruction) {
Lena Djokic51765b02017-06-22 13:49:59 +02001026 CreateVecMemLocations(GetGraph()->GetArena(), instruction, /* is_load */ false);
Aart Bikf8f5a162017-02-06 15:35:29 -08001027}
1028
1029void InstructionCodeGeneratorMIPS::VisitVecStore(HVecStore* instruction) {
Lena Djokic51765b02017-06-22 13:49:59 +02001030 LocationSummary* locations = instruction->GetLocations();
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001031 size_t size = DataType::Size(instruction->GetPackedType());
Lena Djokic51765b02017-06-22 13:49:59 +02001032 VectorRegister reg = VectorRegisterFrom(locations->InAt(2));
1033 Register base;
1034 int32_t offset = VecAddress(locations, size, &base);
1035 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001036 case DataType::Type::kBool:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +01001037 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001038 case DataType::Type::kInt8:
Lena Djokic51765b02017-06-22 13:49:59 +02001039 DCHECK_EQ(16u, instruction->GetVectorLength());
1040 __ StB(reg, base, offset);
1041 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001042 case DataType::Type::kUint16:
1043 case DataType::Type::kInt16:
Lena Djokic51765b02017-06-22 13:49:59 +02001044 DCHECK_EQ(8u, instruction->GetVectorLength());
1045 __ StH(reg, base, offset);
1046 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001047 case DataType::Type::kInt32:
1048 case DataType::Type::kFloat32:
Lena Djokic51765b02017-06-22 13:49:59 +02001049 DCHECK_EQ(4u, instruction->GetVectorLength());
1050 __ StW(reg, base, offset);
1051 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001052 case DataType::Type::kInt64:
1053 case DataType::Type::kFloat64:
Lena Djokic51765b02017-06-22 13:49:59 +02001054 DCHECK_EQ(2u, instruction->GetVectorLength());
1055 __ StD(reg, base, offset);
1056 break;
1057 default:
1058 LOG(FATAL) << "Unsupported SIMD type";
1059 UNREACHABLE();
1060 }
Aart Bikf8f5a162017-02-06 15:35:29 -08001061}
1062
1063#undef __
1064
1065} // namespace mips
1066} // namespace art