blob: 2dfccfff85cdf1fbe7c0755df8247123f1687354 [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_arm64.h"
18#include "mirror/array-inl.h"
19
20using namespace vixl::aarch64; // NOLINT(build/namespaces)
21
22namespace art {
23namespace arm64 {
24
Artem Serovb31f91f2017-04-05 11:31:19 +010025using helpers::VRegisterFrom;
Aart Bikf8f5a162017-02-06 15:35:29 -080026using helpers::HeapOperand;
27using helpers::InputRegisterAt;
28using helpers::Int64ConstantFrom;
29using helpers::XRegisterFrom;
30
31#define __ GetVIXLAssembler()->
32
33void LocationsBuilderARM64::VisitVecReplicateScalar(HVecReplicateScalar* instruction) {
34 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction);
35 switch (instruction->GetPackedType()) {
36 case Primitive::kPrimBoolean:
37 case Primitive::kPrimByte:
38 case Primitive::kPrimChar:
39 case Primitive::kPrimShort:
40 case Primitive::kPrimInt:
Artem Serovb31f91f2017-04-05 11:31:19 +010041 case Primitive::kPrimLong:
Aart Bikf8f5a162017-02-06 15:35:29 -080042 locations->SetInAt(0, Location::RequiresRegister());
43 locations->SetOut(Location::RequiresFpuRegister());
44 break;
45 case Primitive::kPrimFloat:
Artem Serovb31f91f2017-04-05 11:31:19 +010046 case Primitive::kPrimDouble:
Aart Bikf8f5a162017-02-06 15:35:29 -080047 locations->SetInAt(0, Location::RequiresFpuRegister());
48 locations->SetOut(Location::RequiresFpuRegister(), Location::kNoOutputOverlap);
49 break;
50 default:
51 LOG(FATAL) << "Unsupported SIMD type";
52 UNREACHABLE();
53 }
54}
55
56void InstructionCodeGeneratorARM64::VisitVecReplicateScalar(HVecReplicateScalar* instruction) {
57 LocationSummary* locations = instruction->GetLocations();
Artem Serovb31f91f2017-04-05 11:31:19 +010058 VRegister dst = VRegisterFrom(locations->Out());
Aart Bikf8f5a162017-02-06 15:35:29 -080059 switch (instruction->GetPackedType()) {
60 case Primitive::kPrimBoolean:
61 case Primitive::kPrimByte:
Artem Serovd4bccf12017-04-03 18:47:32 +010062 DCHECK_EQ(16u, instruction->GetVectorLength());
63 __ Dup(dst.V16B(), InputRegisterAt(instruction, 0));
Aart Bikf8f5a162017-02-06 15:35:29 -080064 break;
65 case Primitive::kPrimChar:
66 case Primitive::kPrimShort:
Artem Serovd4bccf12017-04-03 18:47:32 +010067 DCHECK_EQ(8u, instruction->GetVectorLength());
68 __ Dup(dst.V8H(), InputRegisterAt(instruction, 0));
Aart Bikf8f5a162017-02-06 15:35:29 -080069 break;
70 case Primitive::kPrimInt:
Artem Serovd4bccf12017-04-03 18:47:32 +010071 DCHECK_EQ(4u, instruction->GetVectorLength());
72 __ Dup(dst.V4S(), InputRegisterAt(instruction, 0));
Aart Bikf8f5a162017-02-06 15:35:29 -080073 break;
Artem Serovb31f91f2017-04-05 11:31:19 +010074 case Primitive::kPrimLong:
75 DCHECK_EQ(2u, instruction->GetVectorLength());
76 __ Dup(dst.V2D(), XRegisterFrom(locations->InAt(0)));
77 break;
Aart Bikf8f5a162017-02-06 15:35:29 -080078 case Primitive::kPrimFloat:
Artem Serovd4bccf12017-04-03 18:47:32 +010079 DCHECK_EQ(4u, instruction->GetVectorLength());
Artem Serovb31f91f2017-04-05 11:31:19 +010080 __ Dup(dst.V4S(), VRegisterFrom(locations->InAt(0)).V4S(), 0);
81 break;
82 case Primitive::kPrimDouble:
83 DCHECK_EQ(2u, instruction->GetVectorLength());
84 __ Dup(dst.V2D(), VRegisterFrom(locations->InAt(0)).V2D(), 0);
Aart Bikf8f5a162017-02-06 15:35:29 -080085 break;
86 default:
87 LOG(FATAL) << "Unsupported SIMD type";
88 UNREACHABLE();
89 }
90}
91
92void LocationsBuilderARM64::VisitVecSetScalars(HVecSetScalars* instruction) {
93 LOG(FATAL) << "No SIMD for " << instruction->GetId();
94}
95
96void InstructionCodeGeneratorARM64::VisitVecSetScalars(HVecSetScalars* instruction) {
97 LOG(FATAL) << "No SIMD for " << instruction->GetId();
98}
99
100void LocationsBuilderARM64::VisitVecSumReduce(HVecSumReduce* instruction) {
101 LOG(FATAL) << "No SIMD for " << instruction->GetId();
102}
103
104void InstructionCodeGeneratorARM64::VisitVecSumReduce(HVecSumReduce* instruction) {
105 LOG(FATAL) << "No SIMD for " << instruction->GetId();
106}
107
108// Helper to set up locations for vector unary operations.
109static void CreateVecUnOpLocations(ArenaAllocator* arena, HVecUnaryOperation* instruction) {
110 LocationSummary* locations = new (arena) LocationSummary(instruction);
111 switch (instruction->GetPackedType()) {
112 case Primitive::kPrimBoolean:
113 locations->SetInAt(0, Location::RequiresFpuRegister());
114 locations->SetOut(Location::RequiresFpuRegister(),
115 instruction->IsVecNot() ? Location::kOutputOverlap
116 : Location::kNoOutputOverlap);
117 break;
118 case Primitive::kPrimByte:
119 case Primitive::kPrimChar:
120 case Primitive::kPrimShort:
121 case Primitive::kPrimInt:
Artem Serovb31f91f2017-04-05 11:31:19 +0100122 case Primitive::kPrimLong:
Aart Bikf8f5a162017-02-06 15:35:29 -0800123 case Primitive::kPrimFloat:
Artem Serovb31f91f2017-04-05 11:31:19 +0100124 case Primitive::kPrimDouble:
Aart Bikf8f5a162017-02-06 15:35:29 -0800125 locations->SetInAt(0, Location::RequiresFpuRegister());
126 locations->SetOut(Location::RequiresFpuRegister(), Location::kNoOutputOverlap);
127 break;
128 default:
129 LOG(FATAL) << "Unsupported SIMD type";
130 UNREACHABLE();
131 }
132}
133
134void LocationsBuilderARM64::VisitVecCnv(HVecCnv* instruction) {
135 CreateVecUnOpLocations(GetGraph()->GetArena(), instruction);
136}
137
138void InstructionCodeGeneratorARM64::VisitVecCnv(HVecCnv* instruction) {
139 LocationSummary* locations = instruction->GetLocations();
Artem Serovb31f91f2017-04-05 11:31:19 +0100140 VRegister src = VRegisterFrom(locations->InAt(0));
141 VRegister dst = VRegisterFrom(locations->Out());
Aart Bikf8f5a162017-02-06 15:35:29 -0800142 Primitive::Type from = instruction->GetInputType();
143 Primitive::Type to = instruction->GetResultType();
144 if (from == Primitive::kPrimInt && to == Primitive::kPrimFloat) {
Artem Serovd4bccf12017-04-03 18:47:32 +0100145 DCHECK_EQ(4u, instruction->GetVectorLength());
146 __ Scvtf(dst.V4S(), src.V4S());
Aart Bikf8f5a162017-02-06 15:35:29 -0800147 } else {
148 LOG(FATAL) << "Unsupported SIMD type";
149 }
150}
151
152void LocationsBuilderARM64::VisitVecNeg(HVecNeg* instruction) {
153 CreateVecUnOpLocations(GetGraph()->GetArena(), instruction);
154}
155
156void InstructionCodeGeneratorARM64::VisitVecNeg(HVecNeg* instruction) {
157 LocationSummary* locations = instruction->GetLocations();
Artem Serovb31f91f2017-04-05 11:31:19 +0100158 VRegister src = VRegisterFrom(locations->InAt(0));
159 VRegister dst = VRegisterFrom(locations->Out());
Aart Bikf8f5a162017-02-06 15:35:29 -0800160 switch (instruction->GetPackedType()) {
161 case Primitive::kPrimByte:
Artem Serovd4bccf12017-04-03 18:47:32 +0100162 DCHECK_EQ(16u, instruction->GetVectorLength());
163 __ Neg(dst.V16B(), src.V16B());
Aart Bikf8f5a162017-02-06 15:35:29 -0800164 break;
165 case Primitive::kPrimChar:
166 case Primitive::kPrimShort:
Artem Serovd4bccf12017-04-03 18:47:32 +0100167 DCHECK_EQ(8u, instruction->GetVectorLength());
168 __ Neg(dst.V8H(), src.V8H());
Aart Bikf8f5a162017-02-06 15:35:29 -0800169 break;
170 case Primitive::kPrimInt:
Artem Serovd4bccf12017-04-03 18:47:32 +0100171 DCHECK_EQ(4u, instruction->GetVectorLength());
172 __ Neg(dst.V4S(), src.V4S());
Aart Bikf8f5a162017-02-06 15:35:29 -0800173 break;
Artem Serovb31f91f2017-04-05 11:31:19 +0100174 case Primitive::kPrimLong:
175 DCHECK_EQ(2u, instruction->GetVectorLength());
176 __ Neg(dst.V2D(), src.V2D());
177 break;
Aart Bikf8f5a162017-02-06 15:35:29 -0800178 case Primitive::kPrimFloat:
Artem Serovd4bccf12017-04-03 18:47:32 +0100179 DCHECK_EQ(4u, instruction->GetVectorLength());
180 __ Fneg(dst.V4S(), src.V4S());
Aart Bikf8f5a162017-02-06 15:35:29 -0800181 break;
Artem Serovb31f91f2017-04-05 11:31:19 +0100182 case Primitive::kPrimDouble:
183 DCHECK_EQ(2u, instruction->GetVectorLength());
184 __ Fneg(dst.V2D(), src.V2D());
185 break;
Aart Bikf8f5a162017-02-06 15:35:29 -0800186 default:
187 LOG(FATAL) << "Unsupported SIMD type";
188 UNREACHABLE();
189 }
190}
191
Aart Bik6daebeb2017-04-03 14:35:41 -0700192void LocationsBuilderARM64::VisitVecAbs(HVecAbs* instruction) {
193 CreateVecUnOpLocations(GetGraph()->GetArena(), instruction);
194}
195
196void InstructionCodeGeneratorARM64::VisitVecAbs(HVecAbs* instruction) {
197 LocationSummary* locations = instruction->GetLocations();
Artem Serovb31f91f2017-04-05 11:31:19 +0100198 VRegister src = VRegisterFrom(locations->InAt(0));
199 VRegister dst = VRegisterFrom(locations->Out());
Aart Bik6daebeb2017-04-03 14:35:41 -0700200 switch (instruction->GetPackedType()) {
201 case Primitive::kPrimByte:
Artem Serovd4bccf12017-04-03 18:47:32 +0100202 DCHECK_EQ(16u, instruction->GetVectorLength());
203 __ Abs(dst.V16B(), src.V16B());
Aart Bik6daebeb2017-04-03 14:35:41 -0700204 break;
205 case Primitive::kPrimChar:
206 case Primitive::kPrimShort:
Artem Serovd4bccf12017-04-03 18:47:32 +0100207 DCHECK_EQ(8u, instruction->GetVectorLength());
208 __ Abs(dst.V8H(), src.V8H());
Aart Bik6daebeb2017-04-03 14:35:41 -0700209 break;
210 case Primitive::kPrimInt:
Artem Serovd4bccf12017-04-03 18:47:32 +0100211 DCHECK_EQ(4u, instruction->GetVectorLength());
212 __ Abs(dst.V4S(), src.V4S());
Aart Bik6daebeb2017-04-03 14:35:41 -0700213 break;
Artem Serovb31f91f2017-04-05 11:31:19 +0100214 case Primitive::kPrimLong:
215 DCHECK_EQ(2u, instruction->GetVectorLength());
216 __ Abs(dst.V2D(), src.V2D());
217 break;
Aart Bik6daebeb2017-04-03 14:35:41 -0700218 case Primitive::kPrimFloat:
Artem Serovd4bccf12017-04-03 18:47:32 +0100219 DCHECK_EQ(4u, instruction->GetVectorLength());
220 __ Fabs(dst.V4S(), src.V4S());
Aart Bik6daebeb2017-04-03 14:35:41 -0700221 break;
Artem Serovb31f91f2017-04-05 11:31:19 +0100222 case Primitive::kPrimDouble:
223 DCHECK_EQ(2u, instruction->GetVectorLength());
224 __ Fabs(dst.V2D(), src.V2D());
225 break;
Aart Bik6daebeb2017-04-03 14:35:41 -0700226 default:
227 LOG(FATAL) << "Unsupported SIMD type";
228 }
229}
230
Aart Bikf8f5a162017-02-06 15:35:29 -0800231void LocationsBuilderARM64::VisitVecNot(HVecNot* instruction) {
232 CreateVecUnOpLocations(GetGraph()->GetArena(), instruction);
233}
234
235void InstructionCodeGeneratorARM64::VisitVecNot(HVecNot* instruction) {
236 LocationSummary* locations = instruction->GetLocations();
Artem Serovb31f91f2017-04-05 11:31:19 +0100237 VRegister src = VRegisterFrom(locations->InAt(0));
238 VRegister dst = VRegisterFrom(locations->Out());
Aart Bikf8f5a162017-02-06 15:35:29 -0800239 switch (instruction->GetPackedType()) {
240 case Primitive::kPrimBoolean: // special case boolean-not
Artem Serovd4bccf12017-04-03 18:47:32 +0100241 DCHECK_EQ(16u, instruction->GetVectorLength());
242 __ Movi(dst.V16B(), 1);
243 __ Eor(dst.V16B(), dst.V16B(), src.V16B());
Aart Bikf8f5a162017-02-06 15:35:29 -0800244 break;
245 case Primitive::kPrimByte:
246 case Primitive::kPrimChar:
247 case Primitive::kPrimShort:
248 case Primitive::kPrimInt:
Artem Serovb31f91f2017-04-05 11:31:19 +0100249 case Primitive::kPrimLong:
Artem Serovd4bccf12017-04-03 18:47:32 +0100250 __ Not(dst.V16B(), src.V16B()); // lanes do not matter
Aart Bikf8f5a162017-02-06 15:35:29 -0800251 break;
252 default:
253 LOG(FATAL) << "Unsupported SIMD type";
254 UNREACHABLE();
255 }
256}
257
258// Helper to set up locations for vector binary operations.
259static void CreateVecBinOpLocations(ArenaAllocator* arena, HVecBinaryOperation* instruction) {
260 LocationSummary* locations = new (arena) LocationSummary(instruction);
261 switch (instruction->GetPackedType()) {
262 case Primitive::kPrimBoolean:
263 case Primitive::kPrimByte:
264 case Primitive::kPrimChar:
265 case Primitive::kPrimShort:
266 case Primitive::kPrimInt:
Artem Serovb31f91f2017-04-05 11:31:19 +0100267 case Primitive::kPrimLong:
Aart Bikf8f5a162017-02-06 15:35:29 -0800268 case Primitive::kPrimFloat:
Artem Serovb31f91f2017-04-05 11:31:19 +0100269 case Primitive::kPrimDouble:
Aart Bikf8f5a162017-02-06 15:35:29 -0800270 locations->SetInAt(0, Location::RequiresFpuRegister());
271 locations->SetInAt(1, Location::RequiresFpuRegister());
272 locations->SetOut(Location::RequiresFpuRegister(), Location::kNoOutputOverlap);
273 break;
274 default:
275 LOG(FATAL) << "Unsupported SIMD type";
276 UNREACHABLE();
277 }
278}
279
280void LocationsBuilderARM64::VisitVecAdd(HVecAdd* instruction) {
281 CreateVecBinOpLocations(GetGraph()->GetArena(), instruction);
282}
283
284void InstructionCodeGeneratorARM64::VisitVecAdd(HVecAdd* instruction) {
285 LocationSummary* locations = instruction->GetLocations();
Artem Serovb31f91f2017-04-05 11:31:19 +0100286 VRegister lhs = VRegisterFrom(locations->InAt(0));
287 VRegister rhs = VRegisterFrom(locations->InAt(1));
288 VRegister dst = VRegisterFrom(locations->Out());
Aart Bikf8f5a162017-02-06 15:35:29 -0800289 switch (instruction->GetPackedType()) {
290 case Primitive::kPrimByte:
Artem Serovd4bccf12017-04-03 18:47:32 +0100291 DCHECK_EQ(16u, instruction->GetVectorLength());
292 __ Add(dst.V16B(), lhs.V16B(), rhs.V16B());
Aart Bikf8f5a162017-02-06 15:35:29 -0800293 break;
294 case Primitive::kPrimChar:
295 case Primitive::kPrimShort:
Artem Serovd4bccf12017-04-03 18:47:32 +0100296 DCHECK_EQ(8u, instruction->GetVectorLength());
297 __ Add(dst.V8H(), lhs.V8H(), rhs.V8H());
Aart Bikf8f5a162017-02-06 15:35:29 -0800298 break;
299 case Primitive::kPrimInt:
Artem Serovd4bccf12017-04-03 18:47:32 +0100300 DCHECK_EQ(4u, instruction->GetVectorLength());
301 __ Add(dst.V4S(), lhs.V4S(), rhs.V4S());
Aart Bikf8f5a162017-02-06 15:35:29 -0800302 break;
Artem Serovb31f91f2017-04-05 11:31:19 +0100303 case Primitive::kPrimLong:
304 DCHECK_EQ(2u, instruction->GetVectorLength());
305 __ Add(dst.V2D(), lhs.V2D(), rhs.V2D());
306 break;
Aart Bikf8f5a162017-02-06 15:35:29 -0800307 case Primitive::kPrimFloat:
Artem Serovd4bccf12017-04-03 18:47:32 +0100308 DCHECK_EQ(4u, instruction->GetVectorLength());
309 __ Fadd(dst.V4S(), lhs.V4S(), rhs.V4S());
Aart Bikf8f5a162017-02-06 15:35:29 -0800310 break;
Artem Serovb31f91f2017-04-05 11:31:19 +0100311 case Primitive::kPrimDouble:
312 DCHECK_EQ(2u, instruction->GetVectorLength());
313 __ Fadd(dst.V2D(), lhs.V2D(), rhs.V2D());
314 break;
Aart Bikf8f5a162017-02-06 15:35:29 -0800315 default:
316 LOG(FATAL) << "Unsupported SIMD type";
317 UNREACHABLE();
318 }
319}
320
Aart Bikf3e61ee2017-04-12 17:09:20 -0700321void LocationsBuilderARM64::VisitVecHalvingAdd(HVecHalvingAdd* instruction) {
322 CreateVecBinOpLocations(GetGraph()->GetArena(), instruction);
323}
324
325void InstructionCodeGeneratorARM64::VisitVecHalvingAdd(HVecHalvingAdd* instruction) {
326 LocationSummary* locations = instruction->GetLocations();
327 VRegister lhs = VRegisterFrom(locations->InAt(0));
328 VRegister rhs = VRegisterFrom(locations->InAt(1));
329 VRegister dst = VRegisterFrom(locations->Out());
330 switch (instruction->GetPackedType()) {
331 case Primitive::kPrimByte:
332 DCHECK_EQ(16u, instruction->GetVectorLength());
333 if (instruction->IsUnsigned()) {
334 instruction->IsRounded()
335 ? __ Urhadd(dst.V16B(), lhs.V16B(), rhs.V16B())
336 : __ Uhadd(dst.V16B(), lhs.V16B(), rhs.V16B());
337 } else {
338 instruction->IsRounded()
339 ? __ Srhadd(dst.V16B(), lhs.V16B(), rhs.V16B())
340 : __ Shadd(dst.V16B(), lhs.V16B(), rhs.V16B());
341 }
342 break;
343 case Primitive::kPrimChar:
344 case Primitive::kPrimShort:
345 DCHECK_EQ(8u, instruction->GetVectorLength());
346 if (instruction->IsUnsigned()) {
347 instruction->IsRounded()
348 ? __ Urhadd(dst.V8H(), lhs.V8H(), rhs.V8H())
349 : __ Uhadd(dst.V8H(), lhs.V8H(), rhs.V8H());
350 } else {
351 instruction->IsRounded()
352 ? __ Srhadd(dst.V8H(), lhs.V8H(), rhs.V8H())
353 : __ Shadd(dst.V8H(), lhs.V8H(), rhs.V8H());
354 }
355 break;
356 default:
357 LOG(FATAL) << "Unsupported SIMD type";
358 UNREACHABLE();
359 }
360}
361
Aart Bikf8f5a162017-02-06 15:35:29 -0800362void LocationsBuilderARM64::VisitVecSub(HVecSub* instruction) {
363 CreateVecBinOpLocations(GetGraph()->GetArena(), instruction);
364}
365
366void InstructionCodeGeneratorARM64::VisitVecSub(HVecSub* instruction) {
367 LocationSummary* locations = instruction->GetLocations();
Artem Serovb31f91f2017-04-05 11:31:19 +0100368 VRegister lhs = VRegisterFrom(locations->InAt(0));
369 VRegister rhs = VRegisterFrom(locations->InAt(1));
370 VRegister dst = VRegisterFrom(locations->Out());
Aart Bikf8f5a162017-02-06 15:35:29 -0800371 switch (instruction->GetPackedType()) {
372 case Primitive::kPrimByte:
Artem Serovd4bccf12017-04-03 18:47:32 +0100373 DCHECK_EQ(16u, instruction->GetVectorLength());
374 __ Sub(dst.V16B(), lhs.V16B(), rhs.V16B());
Aart Bikf8f5a162017-02-06 15:35:29 -0800375 break;
376 case Primitive::kPrimChar:
377 case Primitive::kPrimShort:
Artem Serovd4bccf12017-04-03 18:47:32 +0100378 DCHECK_EQ(8u, instruction->GetVectorLength());
379 __ Sub(dst.V8H(), lhs.V8H(), rhs.V8H());
Aart Bikf8f5a162017-02-06 15:35:29 -0800380 break;
381 case Primitive::kPrimInt:
Artem Serovd4bccf12017-04-03 18:47:32 +0100382 DCHECK_EQ(4u, instruction->GetVectorLength());
383 __ Sub(dst.V4S(), lhs.V4S(), rhs.V4S());
Aart Bikf8f5a162017-02-06 15:35:29 -0800384 break;
Artem Serovb31f91f2017-04-05 11:31:19 +0100385 case Primitive::kPrimLong:
386 DCHECK_EQ(2u, instruction->GetVectorLength());
387 __ Sub(dst.V2D(), lhs.V2D(), rhs.V2D());
388 break;
Aart Bikf8f5a162017-02-06 15:35:29 -0800389 case Primitive::kPrimFloat:
Artem Serovd4bccf12017-04-03 18:47:32 +0100390 DCHECK_EQ(4u, instruction->GetVectorLength());
391 __ Fsub(dst.V4S(), lhs.V4S(), rhs.V4S());
Aart Bikf8f5a162017-02-06 15:35:29 -0800392 break;
Artem Serovb31f91f2017-04-05 11:31:19 +0100393 case Primitive::kPrimDouble:
394 DCHECK_EQ(2u, instruction->GetVectorLength());
395 __ Fsub(dst.V2D(), lhs.V2D(), rhs.V2D());
396 break;
Aart Bikf8f5a162017-02-06 15:35:29 -0800397 default:
398 LOG(FATAL) << "Unsupported SIMD type";
399 UNREACHABLE();
400 }
401}
402
403void LocationsBuilderARM64::VisitVecMul(HVecMul* instruction) {
404 CreateVecBinOpLocations(GetGraph()->GetArena(), instruction);
405}
406
407void InstructionCodeGeneratorARM64::VisitVecMul(HVecMul* instruction) {
408 LocationSummary* locations = instruction->GetLocations();
Artem Serovb31f91f2017-04-05 11:31:19 +0100409 VRegister lhs = VRegisterFrom(locations->InAt(0));
410 VRegister rhs = VRegisterFrom(locations->InAt(1));
411 VRegister dst = VRegisterFrom(locations->Out());
Aart Bikf8f5a162017-02-06 15:35:29 -0800412 switch (instruction->GetPackedType()) {
413 case Primitive::kPrimByte:
Artem Serovd4bccf12017-04-03 18:47:32 +0100414 DCHECK_EQ(16u, instruction->GetVectorLength());
415 __ Mul(dst.V16B(), lhs.V16B(), rhs.V16B());
Aart Bikf8f5a162017-02-06 15:35:29 -0800416 break;
417 case Primitive::kPrimChar:
418 case Primitive::kPrimShort:
Artem Serovd4bccf12017-04-03 18:47:32 +0100419 DCHECK_EQ(8u, instruction->GetVectorLength());
420 __ Mul(dst.V8H(), lhs.V8H(), rhs.V8H());
Aart Bikf8f5a162017-02-06 15:35:29 -0800421 break;
422 case Primitive::kPrimInt:
Artem Serovd4bccf12017-04-03 18:47:32 +0100423 DCHECK_EQ(4u, instruction->GetVectorLength());
424 __ Mul(dst.V4S(), lhs.V4S(), rhs.V4S());
Aart Bikf8f5a162017-02-06 15:35:29 -0800425 break;
426 case Primitive::kPrimFloat:
Artem Serovd4bccf12017-04-03 18:47:32 +0100427 DCHECK_EQ(4u, instruction->GetVectorLength());
428 __ Fmul(dst.V4S(), lhs.V4S(), rhs.V4S());
Aart Bikf8f5a162017-02-06 15:35:29 -0800429 break;
Artem Serovb31f91f2017-04-05 11:31:19 +0100430 case Primitive::kPrimDouble:
431 DCHECK_EQ(2u, instruction->GetVectorLength());
432 __ Fmul(dst.V2D(), lhs.V2D(), rhs.V2D());
433 break;
Aart Bikf8f5a162017-02-06 15:35:29 -0800434 default:
435 LOG(FATAL) << "Unsupported SIMD type";
436 UNREACHABLE();
437 }
438}
439
440void LocationsBuilderARM64::VisitVecDiv(HVecDiv* instruction) {
441 CreateVecBinOpLocations(GetGraph()->GetArena(), instruction);
442}
443
444void InstructionCodeGeneratorARM64::VisitVecDiv(HVecDiv* instruction) {
445 LocationSummary* locations = instruction->GetLocations();
Artem Serovb31f91f2017-04-05 11:31:19 +0100446 VRegister lhs = VRegisterFrom(locations->InAt(0));
447 VRegister rhs = VRegisterFrom(locations->InAt(1));
448 VRegister dst = VRegisterFrom(locations->Out());
Aart Bikf8f5a162017-02-06 15:35:29 -0800449 switch (instruction->GetPackedType()) {
450 case Primitive::kPrimFloat:
Artem Serovd4bccf12017-04-03 18:47:32 +0100451 DCHECK_EQ(4u, instruction->GetVectorLength());
452 __ Fdiv(dst.V4S(), lhs.V4S(), rhs.V4S());
Aart Bikf8f5a162017-02-06 15:35:29 -0800453 break;
Artem Serovb31f91f2017-04-05 11:31:19 +0100454 case Primitive::kPrimDouble:
455 DCHECK_EQ(2u, instruction->GetVectorLength());
456 __ Fdiv(dst.V2D(), lhs.V2D(), rhs.V2D());
457 break;
Aart Bikf8f5a162017-02-06 15:35:29 -0800458 default:
459 LOG(FATAL) << "Unsupported SIMD type";
460 UNREACHABLE();
461 }
462}
463
Aart Bikf3e61ee2017-04-12 17:09:20 -0700464void LocationsBuilderARM64::VisitVecMin(HVecMin* instruction) {
465 CreateVecBinOpLocations(GetGraph()->GetArena(), instruction);
466}
467
468void InstructionCodeGeneratorARM64::VisitVecMin(HVecMin* instruction) {
469 LOG(FATAL) << "Unsupported SIMD instruction " << instruction->GetId();
470}
471
472void LocationsBuilderARM64::VisitVecMax(HVecMax* instruction) {
473 CreateVecBinOpLocations(GetGraph()->GetArena(), instruction);
474}
475
476void InstructionCodeGeneratorARM64::VisitVecMax(HVecMax* instruction) {
477 LOG(FATAL) << "Unsupported SIMD instruction " << instruction->GetId();
478}
479
Aart Bikf8f5a162017-02-06 15:35:29 -0800480void LocationsBuilderARM64::VisitVecAnd(HVecAnd* instruction) {
481 CreateVecBinOpLocations(GetGraph()->GetArena(), instruction);
482}
483
484void InstructionCodeGeneratorARM64::VisitVecAnd(HVecAnd* instruction) {
485 LocationSummary* locations = instruction->GetLocations();
Artem Serovb31f91f2017-04-05 11:31:19 +0100486 VRegister lhs = VRegisterFrom(locations->InAt(0));
487 VRegister rhs = VRegisterFrom(locations->InAt(1));
488 VRegister dst = VRegisterFrom(locations->Out());
Aart Bikf8f5a162017-02-06 15:35:29 -0800489 switch (instruction->GetPackedType()) {
490 case Primitive::kPrimBoolean:
491 case Primitive::kPrimByte:
492 case Primitive::kPrimChar:
493 case Primitive::kPrimShort:
494 case Primitive::kPrimInt:
Artem Serovb31f91f2017-04-05 11:31:19 +0100495 case Primitive::kPrimLong:
Aart Bikf8f5a162017-02-06 15:35:29 -0800496 case Primitive::kPrimFloat:
Artem Serovb31f91f2017-04-05 11:31:19 +0100497 case Primitive::kPrimDouble:
Artem Serovd4bccf12017-04-03 18:47:32 +0100498 __ And(dst.V16B(), lhs.V16B(), rhs.V16B()); // lanes do not matter
Aart Bikf8f5a162017-02-06 15:35:29 -0800499 break;
500 default:
501 LOG(FATAL) << "Unsupported SIMD type";
502 UNREACHABLE();
503 }
504}
505
506void LocationsBuilderARM64::VisitVecAndNot(HVecAndNot* instruction) {
507 LOG(FATAL) << "Unsupported SIMD instruction " << instruction->GetId();
508}
509
510void InstructionCodeGeneratorARM64::VisitVecAndNot(HVecAndNot* instruction) {
511 LOG(FATAL) << "Unsupported SIMD instruction " << instruction->GetId();
512}
513
514void LocationsBuilderARM64::VisitVecOr(HVecOr* instruction) {
515 CreateVecBinOpLocations(GetGraph()->GetArena(), instruction);
516}
517
518void InstructionCodeGeneratorARM64::VisitVecOr(HVecOr* instruction) {
519 LocationSummary* locations = instruction->GetLocations();
Artem Serovb31f91f2017-04-05 11:31:19 +0100520 VRegister lhs = VRegisterFrom(locations->InAt(0));
521 VRegister rhs = VRegisterFrom(locations->InAt(1));
522 VRegister dst = VRegisterFrom(locations->Out());
Aart Bikf8f5a162017-02-06 15:35:29 -0800523 switch (instruction->GetPackedType()) {
524 case Primitive::kPrimBoolean:
525 case Primitive::kPrimByte:
526 case Primitive::kPrimChar:
527 case Primitive::kPrimShort:
528 case Primitive::kPrimInt:
Artem Serovb31f91f2017-04-05 11:31:19 +0100529 case Primitive::kPrimLong:
Aart Bikf8f5a162017-02-06 15:35:29 -0800530 case Primitive::kPrimFloat:
Artem Serovb31f91f2017-04-05 11:31:19 +0100531 case Primitive::kPrimDouble:
Artem Serovd4bccf12017-04-03 18:47:32 +0100532 __ Orr(dst.V16B(), lhs.V16B(), rhs.V16B()); // lanes do not matter
Aart Bikf8f5a162017-02-06 15:35:29 -0800533 break;
534 default:
535 LOG(FATAL) << "Unsupported SIMD type";
536 UNREACHABLE();
537 }
538}
539
540void LocationsBuilderARM64::VisitVecXor(HVecXor* instruction) {
541 CreateVecBinOpLocations(GetGraph()->GetArena(), instruction);
542}
543
544void InstructionCodeGeneratorARM64::VisitVecXor(HVecXor* instruction) {
545 LocationSummary* locations = instruction->GetLocations();
Artem Serovb31f91f2017-04-05 11:31:19 +0100546 VRegister lhs = VRegisterFrom(locations->InAt(0));
547 VRegister rhs = VRegisterFrom(locations->InAt(1));
548 VRegister dst = VRegisterFrom(locations->Out());
Aart Bikf8f5a162017-02-06 15:35:29 -0800549 switch (instruction->GetPackedType()) {
550 case Primitive::kPrimBoolean:
551 case Primitive::kPrimByte:
552 case Primitive::kPrimChar:
553 case Primitive::kPrimShort:
554 case Primitive::kPrimInt:
Artem Serovb31f91f2017-04-05 11:31:19 +0100555 case Primitive::kPrimLong:
Aart Bikf8f5a162017-02-06 15:35:29 -0800556 case Primitive::kPrimFloat:
Artem Serovb31f91f2017-04-05 11:31:19 +0100557 case Primitive::kPrimDouble:
Artem Serovd4bccf12017-04-03 18:47:32 +0100558 __ Eor(dst.V16B(), lhs.V16B(), rhs.V16B()); // lanes do not matter
Aart Bikf8f5a162017-02-06 15:35:29 -0800559 break;
560 default:
561 LOG(FATAL) << "Unsupported SIMD type";
562 UNREACHABLE();
563 }
564}
565
566// Helper to set up locations for vector shift operations.
567static void CreateVecShiftLocations(ArenaAllocator* arena, HVecBinaryOperation* instruction) {
568 LocationSummary* locations = new (arena) LocationSummary(instruction);
569 switch (instruction->GetPackedType()) {
570 case Primitive::kPrimByte:
571 case Primitive::kPrimChar:
572 case Primitive::kPrimShort:
573 case Primitive::kPrimInt:
Artem Serovb31f91f2017-04-05 11:31:19 +0100574 case Primitive::kPrimLong:
Aart Bikf8f5a162017-02-06 15:35:29 -0800575 locations->SetInAt(0, Location::RequiresFpuRegister());
576 locations->SetInAt(1, Location::ConstantLocation(instruction->InputAt(1)->AsConstant()));
577 locations->SetOut(Location::RequiresFpuRegister(), Location::kNoOutputOverlap);
578 break;
579 default:
580 LOG(FATAL) << "Unsupported SIMD type";
581 UNREACHABLE();
582 }
583}
584
585void LocationsBuilderARM64::VisitVecShl(HVecShl* instruction) {
586 CreateVecShiftLocations(GetGraph()->GetArena(), instruction);
587}
588
589void InstructionCodeGeneratorARM64::VisitVecShl(HVecShl* instruction) {
590 LocationSummary* locations = instruction->GetLocations();
Artem Serovb31f91f2017-04-05 11:31:19 +0100591 VRegister lhs = VRegisterFrom(locations->InAt(0));
592 VRegister dst = VRegisterFrom(locations->Out());
Aart Bikf8f5a162017-02-06 15:35:29 -0800593 int32_t value = locations->InAt(1).GetConstant()->AsIntConstant()->GetValue();
594 switch (instruction->GetPackedType()) {
595 case Primitive::kPrimByte:
Artem Serovd4bccf12017-04-03 18:47:32 +0100596 DCHECK_EQ(16u, instruction->GetVectorLength());
597 __ Shl(dst.V16B(), lhs.V16B(), value);
Aart Bikf8f5a162017-02-06 15:35:29 -0800598 break;
599 case Primitive::kPrimChar:
600 case Primitive::kPrimShort:
Artem Serovd4bccf12017-04-03 18:47:32 +0100601 DCHECK_EQ(8u, instruction->GetVectorLength());
602 __ Shl(dst.V8H(), lhs.V8H(), value);
Aart Bikf8f5a162017-02-06 15:35:29 -0800603 break;
604 case Primitive::kPrimInt:
Artem Serovd4bccf12017-04-03 18:47:32 +0100605 DCHECK_EQ(4u, instruction->GetVectorLength());
606 __ Shl(dst.V4S(), lhs.V4S(), value);
Aart Bikf8f5a162017-02-06 15:35:29 -0800607 break;
Artem Serovb31f91f2017-04-05 11:31:19 +0100608 case Primitive::kPrimLong:
609 DCHECK_EQ(2u, instruction->GetVectorLength());
610 __ Shl(dst.V2D(), lhs.V2D(), value);
611 break;
Aart Bikf8f5a162017-02-06 15:35:29 -0800612 default:
613 LOG(FATAL) << "Unsupported SIMD type";
614 UNREACHABLE();
615 }
616}
617
618void LocationsBuilderARM64::VisitVecShr(HVecShr* instruction) {
619 CreateVecShiftLocations(GetGraph()->GetArena(), instruction);
620}
621
622void InstructionCodeGeneratorARM64::VisitVecShr(HVecShr* instruction) {
623 LocationSummary* locations = instruction->GetLocations();
Artem Serovb31f91f2017-04-05 11:31:19 +0100624 VRegister lhs = VRegisterFrom(locations->InAt(0));
625 VRegister dst = VRegisterFrom(locations->Out());
Aart Bikf8f5a162017-02-06 15:35:29 -0800626 int32_t value = locations->InAt(1).GetConstant()->AsIntConstant()->GetValue();
627 switch (instruction->GetPackedType()) {
628 case Primitive::kPrimByte:
Artem Serovd4bccf12017-04-03 18:47:32 +0100629 DCHECK_EQ(16u, instruction->GetVectorLength());
630 __ Sshr(dst.V16B(), lhs.V16B(), value);
Aart Bikf8f5a162017-02-06 15:35:29 -0800631 break;
632 case Primitive::kPrimChar:
633 case Primitive::kPrimShort:
Artem Serovd4bccf12017-04-03 18:47:32 +0100634 DCHECK_EQ(8u, instruction->GetVectorLength());
635 __ Sshr(dst.V8H(), lhs.V8H(), value);
Aart Bikf8f5a162017-02-06 15:35:29 -0800636 break;
637 case Primitive::kPrimInt:
Artem Serovd4bccf12017-04-03 18:47:32 +0100638 DCHECK_EQ(4u, instruction->GetVectorLength());
639 __ Sshr(dst.V4S(), lhs.V4S(), value);
Aart Bikf8f5a162017-02-06 15:35:29 -0800640 break;
Artem Serovb31f91f2017-04-05 11:31:19 +0100641 case Primitive::kPrimLong:
642 DCHECK_EQ(2u, instruction->GetVectorLength());
643 __ Sshr(dst.V2D(), lhs.V2D(), value);
644 break;
Aart Bikf8f5a162017-02-06 15:35:29 -0800645 default:
646 LOG(FATAL) << "Unsupported SIMD type";
647 UNREACHABLE();
648 }
649}
650
651void LocationsBuilderARM64::VisitVecUShr(HVecUShr* instruction) {
652 CreateVecShiftLocations(GetGraph()->GetArena(), instruction);
653}
654
655void InstructionCodeGeneratorARM64::VisitVecUShr(HVecUShr* instruction) {
656 LocationSummary* locations = instruction->GetLocations();
Artem Serovb31f91f2017-04-05 11:31:19 +0100657 VRegister lhs = VRegisterFrom(locations->InAt(0));
658 VRegister dst = VRegisterFrom(locations->Out());
Aart Bikf8f5a162017-02-06 15:35:29 -0800659 int32_t value = locations->InAt(1).GetConstant()->AsIntConstant()->GetValue();
660 switch (instruction->GetPackedType()) {
661 case Primitive::kPrimByte:
Artem Serovd4bccf12017-04-03 18:47:32 +0100662 DCHECK_EQ(16u, instruction->GetVectorLength());
663 __ Ushr(dst.V16B(), lhs.V16B(), value);
Aart Bikf8f5a162017-02-06 15:35:29 -0800664 break;
665 case Primitive::kPrimChar:
666 case Primitive::kPrimShort:
Artem Serovd4bccf12017-04-03 18:47:32 +0100667 DCHECK_EQ(8u, instruction->GetVectorLength());
668 __ Ushr(dst.V8H(), lhs.V8H(), value);
Aart Bikf8f5a162017-02-06 15:35:29 -0800669 break;
670 case Primitive::kPrimInt:
Artem Serovd4bccf12017-04-03 18:47:32 +0100671 DCHECK_EQ(4u, instruction->GetVectorLength());
672 __ Ushr(dst.V4S(), lhs.V4S(), value);
Aart Bikf8f5a162017-02-06 15:35:29 -0800673 break;
Artem Serovb31f91f2017-04-05 11:31:19 +0100674 case Primitive::kPrimLong:
675 DCHECK_EQ(2u, instruction->GetVectorLength());
676 __ Ushr(dst.V2D(), lhs.V2D(), value);
677 break;
Aart Bikf8f5a162017-02-06 15:35:29 -0800678 default:
679 LOG(FATAL) << "Unsupported SIMD type";
680 UNREACHABLE();
681 }
682}
683
684// Helper to set up locations for vector memory operations.
685static void CreateVecMemLocations(ArenaAllocator* arena,
686 HVecMemoryOperation* instruction,
687 bool is_load) {
688 LocationSummary* locations = new (arena) LocationSummary(instruction);
689 switch (instruction->GetPackedType()) {
690 case Primitive::kPrimBoolean:
691 case Primitive::kPrimByte:
692 case Primitive::kPrimChar:
693 case Primitive::kPrimShort:
694 case Primitive::kPrimInt:
Artem Serovb31f91f2017-04-05 11:31:19 +0100695 case Primitive::kPrimLong:
Aart Bikf8f5a162017-02-06 15:35:29 -0800696 case Primitive::kPrimFloat:
Artem Serovb31f91f2017-04-05 11:31:19 +0100697 case Primitive::kPrimDouble:
Aart Bikf8f5a162017-02-06 15:35:29 -0800698 locations->SetInAt(0, Location::RequiresRegister());
699 locations->SetInAt(1, Location::RegisterOrConstant(instruction->InputAt(1)));
700 if (is_load) {
701 locations->SetOut(Location::RequiresFpuRegister());
702 } else {
703 locations->SetInAt(2, Location::RequiresFpuRegister());
704 }
705 break;
706 default:
707 LOG(FATAL) << "Unsupported SIMD type";
708 UNREACHABLE();
709 }
710}
711
712// Helper to set up registers and address for vector memory operations.
713MemOperand InstructionCodeGeneratorARM64::CreateVecMemRegisters(
714 HVecMemoryOperation* instruction,
715 Location* reg_loc,
716 bool is_load) {
717 LocationSummary* locations = instruction->GetLocations();
718 Register base = InputRegisterAt(instruction, 0);
719 Location index = locations->InAt(1);
720 *reg_loc = is_load ? locations->Out() : locations->InAt(2);
721
722 Primitive::Type packed_type = instruction->GetPackedType();
723 uint32_t offset = mirror::Array::DataOffset(Primitive::ComponentSize(packed_type)).Uint32Value();
724 size_t shift = Primitive::ComponentSizeShift(packed_type);
725
726 UseScratchRegisterScope temps(GetVIXLAssembler());
727 Register temp = temps.AcquireSameSizeAs(base);
728 if (index.IsConstant()) {
729 offset += Int64ConstantFrom(index) << shift;
730 __ Add(temp, base, offset);
731 } else {
732 if (instruction->InputAt(0)->IsIntermediateAddress()) {
733 temp = base;
734 } else {
735 __ Add(temp, base, offset);
736 }
737 __ Add(temp.X(), temp.X(), Operand(XRegisterFrom(index), LSL, shift));
738 }
739 return HeapOperand(temp);
740}
741
742void LocationsBuilderARM64::VisitVecLoad(HVecLoad* instruction) {
743 CreateVecMemLocations(GetGraph()->GetArena(), instruction, /*is_load*/ true);
744}
745
746void InstructionCodeGeneratorARM64::VisitVecLoad(HVecLoad* instruction) {
747 Location reg_loc = Location::NoLocation();
748 MemOperand mem = CreateVecMemRegisters(instruction, &reg_loc, /*is_load*/ true);
Artem Serovb31f91f2017-04-05 11:31:19 +0100749 VRegister reg = VRegisterFrom(reg_loc);
Aart Bikf8f5a162017-02-06 15:35:29 -0800750 switch (instruction->GetPackedType()) {
751 case Primitive::kPrimBoolean:
752 case Primitive::kPrimByte:
Artem Serovd4bccf12017-04-03 18:47:32 +0100753 DCHECK_EQ(16u, instruction->GetVectorLength());
754 __ Ld1(reg.V16B(), mem);
Aart Bikf8f5a162017-02-06 15:35:29 -0800755 break;
756 case Primitive::kPrimChar:
757 case Primitive::kPrimShort:
Artem Serovd4bccf12017-04-03 18:47:32 +0100758 DCHECK_EQ(8u, instruction->GetVectorLength());
759 __ Ld1(reg.V8H(), mem);
Aart Bikf8f5a162017-02-06 15:35:29 -0800760 break;
761 case Primitive::kPrimInt:
762 case Primitive::kPrimFloat:
Artem Serovd4bccf12017-04-03 18:47:32 +0100763 DCHECK_EQ(4u, instruction->GetVectorLength());
764 __ Ld1(reg.V4S(), mem);
Aart Bikf8f5a162017-02-06 15:35:29 -0800765 break;
Artem Serovb31f91f2017-04-05 11:31:19 +0100766 case Primitive::kPrimLong:
767 case Primitive::kPrimDouble:
768 DCHECK_EQ(2u, instruction->GetVectorLength());
769 __ Ld1(reg.V2D(), mem);
770 break;
Aart Bikf8f5a162017-02-06 15:35:29 -0800771 default:
772 LOG(FATAL) << "Unsupported SIMD type";
773 UNREACHABLE();
774 }
775}
776
777void LocationsBuilderARM64::VisitVecStore(HVecStore* instruction) {
778 CreateVecMemLocations(GetGraph()->GetArena(), instruction, /*is_load*/ false);
779}
780
781void InstructionCodeGeneratorARM64::VisitVecStore(HVecStore* instruction) {
782 Location reg_loc = Location::NoLocation();
783 MemOperand mem = CreateVecMemRegisters(instruction, &reg_loc, /*is_load*/ false);
Artem Serovb31f91f2017-04-05 11:31:19 +0100784 VRegister reg = VRegisterFrom(reg_loc);
Aart Bikf8f5a162017-02-06 15:35:29 -0800785 switch (instruction->GetPackedType()) {
786 case Primitive::kPrimBoolean:
787 case Primitive::kPrimByte:
Artem Serovd4bccf12017-04-03 18:47:32 +0100788 DCHECK_EQ(16u, instruction->GetVectorLength());
789 __ St1(reg.V16B(), mem);
Aart Bikf8f5a162017-02-06 15:35:29 -0800790 break;
791 case Primitive::kPrimChar:
792 case Primitive::kPrimShort:
Artem Serovd4bccf12017-04-03 18:47:32 +0100793 DCHECK_EQ(8u, instruction->GetVectorLength());
794 __ St1(reg.V8H(), mem);
Aart Bikf8f5a162017-02-06 15:35:29 -0800795 break;
796 case Primitive::kPrimInt:
797 case Primitive::kPrimFloat:
Artem Serovd4bccf12017-04-03 18:47:32 +0100798 DCHECK_EQ(4u, instruction->GetVectorLength());
799 __ St1(reg.V4S(), mem);
Aart Bikf8f5a162017-02-06 15:35:29 -0800800 break;
Artem Serovb31f91f2017-04-05 11:31:19 +0100801 case Primitive::kPrimLong:
802 case Primitive::kPrimDouble:
803 DCHECK_EQ(2u, instruction->GetVectorLength());
804 __ St1(reg.V2D(), mem);
805 break;
Aart Bikf8f5a162017-02-06 15:35:29 -0800806 default:
807 LOG(FATAL) << "Unsupported SIMD type";
808 UNREACHABLE();
809 }
810}
811
812#undef __
813
814} // namespace arm64
815} // namespace art