blob: 11c5e380fe9b2497aede7eb91d8fd8bd1cac7432 [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
25using helpers::DRegisterFrom;
26using 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:
41 locations->SetInAt(0, Location::RequiresRegister());
42 locations->SetOut(Location::RequiresFpuRegister());
43 break;
44 case Primitive::kPrimFloat:
45 locations->SetInAt(0, Location::RequiresFpuRegister());
46 locations->SetOut(Location::RequiresFpuRegister(), Location::kNoOutputOverlap);
47 break;
48 default:
49 LOG(FATAL) << "Unsupported SIMD type";
50 UNREACHABLE();
51 }
52}
53
54void InstructionCodeGeneratorARM64::VisitVecReplicateScalar(HVecReplicateScalar* instruction) {
55 LocationSummary* locations = instruction->GetLocations();
56 FPRegister dst = DRegisterFrom(locations->Out());
57 switch (instruction->GetPackedType()) {
58 case Primitive::kPrimBoolean:
59 case Primitive::kPrimByte:
Artem Serovd4bccf12017-04-03 18:47:32 +010060 DCHECK_EQ(16u, instruction->GetVectorLength());
61 __ Dup(dst.V16B(), InputRegisterAt(instruction, 0));
Aart Bikf8f5a162017-02-06 15:35:29 -080062 break;
63 case Primitive::kPrimChar:
64 case Primitive::kPrimShort:
Artem Serovd4bccf12017-04-03 18:47:32 +010065 DCHECK_EQ(8u, instruction->GetVectorLength());
66 __ Dup(dst.V8H(), InputRegisterAt(instruction, 0));
Aart Bikf8f5a162017-02-06 15:35:29 -080067 break;
68 case Primitive::kPrimInt:
Artem Serovd4bccf12017-04-03 18:47:32 +010069 DCHECK_EQ(4u, instruction->GetVectorLength());
70 __ Dup(dst.V4S(), InputRegisterAt(instruction, 0));
Aart Bikf8f5a162017-02-06 15:35:29 -080071 break;
72 case Primitive::kPrimFloat:
Artem Serovd4bccf12017-04-03 18:47:32 +010073 DCHECK_EQ(4u, instruction->GetVectorLength());
74 __ Dup(dst.V4S(), DRegisterFrom(locations->InAt(0)).V4S(), 0);
Aart Bikf8f5a162017-02-06 15:35:29 -080075 break;
76 default:
77 LOG(FATAL) << "Unsupported SIMD type";
78 UNREACHABLE();
79 }
80}
81
82void LocationsBuilderARM64::VisitVecSetScalars(HVecSetScalars* instruction) {
83 LOG(FATAL) << "No SIMD for " << instruction->GetId();
84}
85
86void InstructionCodeGeneratorARM64::VisitVecSetScalars(HVecSetScalars* instruction) {
87 LOG(FATAL) << "No SIMD for " << instruction->GetId();
88}
89
90void LocationsBuilderARM64::VisitVecSumReduce(HVecSumReduce* instruction) {
91 LOG(FATAL) << "No SIMD for " << instruction->GetId();
92}
93
94void InstructionCodeGeneratorARM64::VisitVecSumReduce(HVecSumReduce* instruction) {
95 LOG(FATAL) << "No SIMD for " << instruction->GetId();
96}
97
98// Helper to set up locations for vector unary operations.
99static void CreateVecUnOpLocations(ArenaAllocator* arena, HVecUnaryOperation* instruction) {
100 LocationSummary* locations = new (arena) LocationSummary(instruction);
101 switch (instruction->GetPackedType()) {
102 case Primitive::kPrimBoolean:
103 locations->SetInAt(0, Location::RequiresFpuRegister());
104 locations->SetOut(Location::RequiresFpuRegister(),
105 instruction->IsVecNot() ? Location::kOutputOverlap
106 : Location::kNoOutputOverlap);
107 break;
108 case Primitive::kPrimByte:
109 case Primitive::kPrimChar:
110 case Primitive::kPrimShort:
111 case Primitive::kPrimInt:
112 case Primitive::kPrimFloat:
113 locations->SetInAt(0, Location::RequiresFpuRegister());
114 locations->SetOut(Location::RequiresFpuRegister(), Location::kNoOutputOverlap);
115 break;
116 default:
117 LOG(FATAL) << "Unsupported SIMD type";
118 UNREACHABLE();
119 }
120}
121
122void LocationsBuilderARM64::VisitVecCnv(HVecCnv* instruction) {
123 CreateVecUnOpLocations(GetGraph()->GetArena(), instruction);
124}
125
126void InstructionCodeGeneratorARM64::VisitVecCnv(HVecCnv* instruction) {
127 LocationSummary* locations = instruction->GetLocations();
128 FPRegister src = DRegisterFrom(locations->InAt(0));
129 FPRegister dst = DRegisterFrom(locations->Out());
130 Primitive::Type from = instruction->GetInputType();
131 Primitive::Type to = instruction->GetResultType();
132 if (from == Primitive::kPrimInt && to == Primitive::kPrimFloat) {
Artem Serovd4bccf12017-04-03 18:47:32 +0100133 DCHECK_EQ(4u, instruction->GetVectorLength());
134 __ Scvtf(dst.V4S(), src.V4S());
Aart Bikf8f5a162017-02-06 15:35:29 -0800135 } else {
136 LOG(FATAL) << "Unsupported SIMD type";
137 }
138}
139
140void LocationsBuilderARM64::VisitVecNeg(HVecNeg* instruction) {
141 CreateVecUnOpLocations(GetGraph()->GetArena(), instruction);
142}
143
144void InstructionCodeGeneratorARM64::VisitVecNeg(HVecNeg* instruction) {
145 LocationSummary* locations = instruction->GetLocations();
146 FPRegister src = DRegisterFrom(locations->InAt(0));
147 FPRegister dst = DRegisterFrom(locations->Out());
148 switch (instruction->GetPackedType()) {
149 case Primitive::kPrimByte:
Artem Serovd4bccf12017-04-03 18:47:32 +0100150 DCHECK_EQ(16u, instruction->GetVectorLength());
151 __ Neg(dst.V16B(), src.V16B());
Aart Bikf8f5a162017-02-06 15:35:29 -0800152 break;
153 case Primitive::kPrimChar:
154 case Primitive::kPrimShort:
Artem Serovd4bccf12017-04-03 18:47:32 +0100155 DCHECK_EQ(8u, instruction->GetVectorLength());
156 __ Neg(dst.V8H(), src.V8H());
Aart Bikf8f5a162017-02-06 15:35:29 -0800157 break;
158 case Primitive::kPrimInt:
Artem Serovd4bccf12017-04-03 18:47:32 +0100159 DCHECK_EQ(4u, instruction->GetVectorLength());
160 __ Neg(dst.V4S(), src.V4S());
Aart Bikf8f5a162017-02-06 15:35:29 -0800161 break;
162 case Primitive::kPrimFloat:
Artem Serovd4bccf12017-04-03 18:47:32 +0100163 DCHECK_EQ(4u, instruction->GetVectorLength());
164 __ Fneg(dst.V4S(), src.V4S());
Aart Bikf8f5a162017-02-06 15:35:29 -0800165 break;
166 default:
167 LOG(FATAL) << "Unsupported SIMD type";
168 UNREACHABLE();
169 }
170}
171
Aart Bik6daebeb2017-04-03 14:35:41 -0700172void LocationsBuilderARM64::VisitVecAbs(HVecAbs* instruction) {
173 CreateVecUnOpLocations(GetGraph()->GetArena(), instruction);
174}
175
176void InstructionCodeGeneratorARM64::VisitVecAbs(HVecAbs* instruction) {
177 LocationSummary* locations = instruction->GetLocations();
178 FPRegister src = DRegisterFrom(locations->InAt(0));
179 FPRegister dst = DRegisterFrom(locations->Out());
180 switch (instruction->GetPackedType()) {
181 case Primitive::kPrimByte:
Artem Serovd4bccf12017-04-03 18:47:32 +0100182 DCHECK_EQ(16u, instruction->GetVectorLength());
183 __ Abs(dst.V16B(), src.V16B());
Aart Bik6daebeb2017-04-03 14:35:41 -0700184 break;
185 case Primitive::kPrimChar:
186 case Primitive::kPrimShort:
Artem Serovd4bccf12017-04-03 18:47:32 +0100187 DCHECK_EQ(8u, instruction->GetVectorLength());
188 __ Abs(dst.V8H(), src.V8H());
Aart Bik6daebeb2017-04-03 14:35:41 -0700189 break;
190 case Primitive::kPrimInt:
Artem Serovd4bccf12017-04-03 18:47:32 +0100191 DCHECK_EQ(4u, instruction->GetVectorLength());
192 __ Abs(dst.V4S(), src.V4S());
Aart Bik6daebeb2017-04-03 14:35:41 -0700193 break;
194 case Primitive::kPrimFloat:
Artem Serovd4bccf12017-04-03 18:47:32 +0100195 DCHECK_EQ(4u, instruction->GetVectorLength());
196 __ Fabs(dst.V4S(), src.V4S());
Aart Bik6daebeb2017-04-03 14:35:41 -0700197 break;
198 default:
199 LOG(FATAL) << "Unsupported SIMD type";
200 }
201}
202
Aart Bikf8f5a162017-02-06 15:35:29 -0800203void LocationsBuilderARM64::VisitVecNot(HVecNot* instruction) {
204 CreateVecUnOpLocations(GetGraph()->GetArena(), instruction);
205}
206
207void InstructionCodeGeneratorARM64::VisitVecNot(HVecNot* instruction) {
208 LocationSummary* locations = instruction->GetLocations();
209 FPRegister src = DRegisterFrom(locations->InAt(0));
210 FPRegister dst = DRegisterFrom(locations->Out());
211 switch (instruction->GetPackedType()) {
212 case Primitive::kPrimBoolean: // special case boolean-not
Artem Serovd4bccf12017-04-03 18:47:32 +0100213 DCHECK_EQ(16u, instruction->GetVectorLength());
214 __ Movi(dst.V16B(), 1);
215 __ Eor(dst.V16B(), dst.V16B(), src.V16B());
Aart Bikf8f5a162017-02-06 15:35:29 -0800216 break;
217 case Primitive::kPrimByte:
218 case Primitive::kPrimChar:
219 case Primitive::kPrimShort:
220 case Primitive::kPrimInt:
Artem Serovd4bccf12017-04-03 18:47:32 +0100221 __ Not(dst.V16B(), src.V16B()); // lanes do not matter
Aart Bikf8f5a162017-02-06 15:35:29 -0800222 break;
223 default:
224 LOG(FATAL) << "Unsupported SIMD type";
225 UNREACHABLE();
226 }
227}
228
229// Helper to set up locations for vector binary operations.
230static void CreateVecBinOpLocations(ArenaAllocator* arena, HVecBinaryOperation* instruction) {
231 LocationSummary* locations = new (arena) LocationSummary(instruction);
232 switch (instruction->GetPackedType()) {
233 case Primitive::kPrimBoolean:
234 case Primitive::kPrimByte:
235 case Primitive::kPrimChar:
236 case Primitive::kPrimShort:
237 case Primitive::kPrimInt:
238 case Primitive::kPrimFloat:
239 locations->SetInAt(0, Location::RequiresFpuRegister());
240 locations->SetInAt(1, Location::RequiresFpuRegister());
241 locations->SetOut(Location::RequiresFpuRegister(), Location::kNoOutputOverlap);
242 break;
243 default:
244 LOG(FATAL) << "Unsupported SIMD type";
245 UNREACHABLE();
246 }
247}
248
249void LocationsBuilderARM64::VisitVecAdd(HVecAdd* instruction) {
250 CreateVecBinOpLocations(GetGraph()->GetArena(), instruction);
251}
252
253void InstructionCodeGeneratorARM64::VisitVecAdd(HVecAdd* instruction) {
254 LocationSummary* locations = instruction->GetLocations();
255 FPRegister lhs = DRegisterFrom(locations->InAt(0));
256 FPRegister rhs = DRegisterFrom(locations->InAt(1));
257 FPRegister dst = DRegisterFrom(locations->Out());
258 switch (instruction->GetPackedType()) {
259 case Primitive::kPrimByte:
Artem Serovd4bccf12017-04-03 18:47:32 +0100260 DCHECK_EQ(16u, instruction->GetVectorLength());
261 __ Add(dst.V16B(), lhs.V16B(), rhs.V16B());
Aart Bikf8f5a162017-02-06 15:35:29 -0800262 break;
263 case Primitive::kPrimChar:
264 case Primitive::kPrimShort:
Artem Serovd4bccf12017-04-03 18:47:32 +0100265 DCHECK_EQ(8u, instruction->GetVectorLength());
266 __ Add(dst.V8H(), lhs.V8H(), rhs.V8H());
Aart Bikf8f5a162017-02-06 15:35:29 -0800267 break;
268 case Primitive::kPrimInt:
Artem Serovd4bccf12017-04-03 18:47:32 +0100269 DCHECK_EQ(4u, instruction->GetVectorLength());
270 __ Add(dst.V4S(), lhs.V4S(), rhs.V4S());
Aart Bikf8f5a162017-02-06 15:35:29 -0800271 break;
272 case Primitive::kPrimFloat:
Artem Serovd4bccf12017-04-03 18:47:32 +0100273 DCHECK_EQ(4u, instruction->GetVectorLength());
274 __ Fadd(dst.V4S(), lhs.V4S(), rhs.V4S());
Aart Bikf8f5a162017-02-06 15:35:29 -0800275 break;
276 default:
277 LOG(FATAL) << "Unsupported SIMD type";
278 UNREACHABLE();
279 }
280}
281
282void LocationsBuilderARM64::VisitVecSub(HVecSub* instruction) {
283 CreateVecBinOpLocations(GetGraph()->GetArena(), instruction);
284}
285
286void InstructionCodeGeneratorARM64::VisitVecSub(HVecSub* instruction) {
287 LocationSummary* locations = instruction->GetLocations();
288 FPRegister lhs = DRegisterFrom(locations->InAt(0));
289 FPRegister rhs = DRegisterFrom(locations->InAt(1));
290 FPRegister dst = DRegisterFrom(locations->Out());
291 switch (instruction->GetPackedType()) {
292 case Primitive::kPrimByte:
Artem Serovd4bccf12017-04-03 18:47:32 +0100293 DCHECK_EQ(16u, instruction->GetVectorLength());
294 __ Sub(dst.V16B(), lhs.V16B(), rhs.V16B());
Aart Bikf8f5a162017-02-06 15:35:29 -0800295 break;
296 case Primitive::kPrimChar:
297 case Primitive::kPrimShort:
Artem Serovd4bccf12017-04-03 18:47:32 +0100298 DCHECK_EQ(8u, instruction->GetVectorLength());
299 __ Sub(dst.V8H(), lhs.V8H(), rhs.V8H());
Aart Bikf8f5a162017-02-06 15:35:29 -0800300 break;
301 case Primitive::kPrimInt:
Artem Serovd4bccf12017-04-03 18:47:32 +0100302 DCHECK_EQ(4u, instruction->GetVectorLength());
303 __ Sub(dst.V4S(), lhs.V4S(), rhs.V4S());
Aart Bikf8f5a162017-02-06 15:35:29 -0800304 break;
305 case Primitive::kPrimFloat:
Artem Serovd4bccf12017-04-03 18:47:32 +0100306 DCHECK_EQ(4u, instruction->GetVectorLength());
307 __ Fsub(dst.V4S(), lhs.V4S(), rhs.V4S());
Aart Bikf8f5a162017-02-06 15:35:29 -0800308 break;
309 default:
310 LOG(FATAL) << "Unsupported SIMD type";
311 UNREACHABLE();
312 }
313}
314
315void LocationsBuilderARM64::VisitVecMul(HVecMul* instruction) {
316 CreateVecBinOpLocations(GetGraph()->GetArena(), instruction);
317}
318
319void InstructionCodeGeneratorARM64::VisitVecMul(HVecMul* instruction) {
320 LocationSummary* locations = instruction->GetLocations();
321 FPRegister lhs = DRegisterFrom(locations->InAt(0));
322 FPRegister rhs = DRegisterFrom(locations->InAt(1));
323 FPRegister dst = DRegisterFrom(locations->Out());
324 switch (instruction->GetPackedType()) {
325 case Primitive::kPrimByte:
Artem Serovd4bccf12017-04-03 18:47:32 +0100326 DCHECK_EQ(16u, instruction->GetVectorLength());
327 __ Mul(dst.V16B(), lhs.V16B(), rhs.V16B());
Aart Bikf8f5a162017-02-06 15:35:29 -0800328 break;
329 case Primitive::kPrimChar:
330 case Primitive::kPrimShort:
Artem Serovd4bccf12017-04-03 18:47:32 +0100331 DCHECK_EQ(8u, instruction->GetVectorLength());
332 __ Mul(dst.V8H(), lhs.V8H(), rhs.V8H());
Aart Bikf8f5a162017-02-06 15:35:29 -0800333 break;
334 case Primitive::kPrimInt:
Artem Serovd4bccf12017-04-03 18:47:32 +0100335 DCHECK_EQ(4u, instruction->GetVectorLength());
336 __ Mul(dst.V4S(), lhs.V4S(), rhs.V4S());
Aart Bikf8f5a162017-02-06 15:35:29 -0800337 break;
338 case Primitive::kPrimFloat:
Artem Serovd4bccf12017-04-03 18:47:32 +0100339 DCHECK_EQ(4u, instruction->GetVectorLength());
340 __ Fmul(dst.V4S(), lhs.V4S(), rhs.V4S());
Aart Bikf8f5a162017-02-06 15:35:29 -0800341 break;
342 default:
343 LOG(FATAL) << "Unsupported SIMD type";
344 UNREACHABLE();
345 }
346}
347
348void LocationsBuilderARM64::VisitVecDiv(HVecDiv* instruction) {
349 CreateVecBinOpLocations(GetGraph()->GetArena(), instruction);
350}
351
352void InstructionCodeGeneratorARM64::VisitVecDiv(HVecDiv* instruction) {
353 LocationSummary* locations = instruction->GetLocations();
354 FPRegister lhs = DRegisterFrom(locations->InAt(0));
355 FPRegister rhs = DRegisterFrom(locations->InAt(1));
356 FPRegister dst = DRegisterFrom(locations->Out());
357 switch (instruction->GetPackedType()) {
358 case Primitive::kPrimFloat:
Artem Serovd4bccf12017-04-03 18:47:32 +0100359 DCHECK_EQ(4u, instruction->GetVectorLength());
360 __ Fdiv(dst.V4S(), lhs.V4S(), rhs.V4S());
Aart Bikf8f5a162017-02-06 15:35:29 -0800361 break;
362 default:
363 LOG(FATAL) << "Unsupported SIMD type";
364 UNREACHABLE();
365 }
366}
367
368void LocationsBuilderARM64::VisitVecAnd(HVecAnd* instruction) {
369 CreateVecBinOpLocations(GetGraph()->GetArena(), instruction);
370}
371
372void InstructionCodeGeneratorARM64::VisitVecAnd(HVecAnd* instruction) {
373 LocationSummary* locations = instruction->GetLocations();
374 FPRegister lhs = DRegisterFrom(locations->InAt(0));
375 FPRegister rhs = DRegisterFrom(locations->InAt(1));
376 FPRegister dst = DRegisterFrom(locations->Out());
377 switch (instruction->GetPackedType()) {
378 case Primitive::kPrimBoolean:
379 case Primitive::kPrimByte:
380 case Primitive::kPrimChar:
381 case Primitive::kPrimShort:
382 case Primitive::kPrimInt:
383 case Primitive::kPrimFloat:
Artem Serovd4bccf12017-04-03 18:47:32 +0100384 __ And(dst.V16B(), lhs.V16B(), rhs.V16B()); // lanes do not matter
Aart Bikf8f5a162017-02-06 15:35:29 -0800385 break;
386 default:
387 LOG(FATAL) << "Unsupported SIMD type";
388 UNREACHABLE();
389 }
390}
391
392void LocationsBuilderARM64::VisitVecAndNot(HVecAndNot* instruction) {
393 LOG(FATAL) << "Unsupported SIMD instruction " << instruction->GetId();
394}
395
396void InstructionCodeGeneratorARM64::VisitVecAndNot(HVecAndNot* instruction) {
397 LOG(FATAL) << "Unsupported SIMD instruction " << instruction->GetId();
398}
399
400void LocationsBuilderARM64::VisitVecOr(HVecOr* instruction) {
401 CreateVecBinOpLocations(GetGraph()->GetArena(), instruction);
402}
403
404void InstructionCodeGeneratorARM64::VisitVecOr(HVecOr* instruction) {
405 LocationSummary* locations = instruction->GetLocations();
406 FPRegister lhs = DRegisterFrom(locations->InAt(0));
407 FPRegister rhs = DRegisterFrom(locations->InAt(1));
408 FPRegister dst = DRegisterFrom(locations->Out());
409 switch (instruction->GetPackedType()) {
410 case Primitive::kPrimBoolean:
411 case Primitive::kPrimByte:
412 case Primitive::kPrimChar:
413 case Primitive::kPrimShort:
414 case Primitive::kPrimInt:
415 case Primitive::kPrimFloat:
Artem Serovd4bccf12017-04-03 18:47:32 +0100416 __ Orr(dst.V16B(), lhs.V16B(), rhs.V16B()); // lanes do not matter
Aart Bikf8f5a162017-02-06 15:35:29 -0800417 break;
418 default:
419 LOG(FATAL) << "Unsupported SIMD type";
420 UNREACHABLE();
421 }
422}
423
424void LocationsBuilderARM64::VisitVecXor(HVecXor* instruction) {
425 CreateVecBinOpLocations(GetGraph()->GetArena(), instruction);
426}
427
428void InstructionCodeGeneratorARM64::VisitVecXor(HVecXor* instruction) {
429 LocationSummary* locations = instruction->GetLocations();
430 FPRegister lhs = DRegisterFrom(locations->InAt(0));
431 FPRegister rhs = DRegisterFrom(locations->InAt(1));
432 FPRegister dst = DRegisterFrom(locations->Out());
433 switch (instruction->GetPackedType()) {
434 case Primitive::kPrimBoolean:
435 case Primitive::kPrimByte:
436 case Primitive::kPrimChar:
437 case Primitive::kPrimShort:
438 case Primitive::kPrimInt:
439 case Primitive::kPrimFloat:
Artem Serovd4bccf12017-04-03 18:47:32 +0100440 __ Eor(dst.V16B(), lhs.V16B(), rhs.V16B()); // lanes do not matter
Aart Bikf8f5a162017-02-06 15:35:29 -0800441 break;
442 default:
443 LOG(FATAL) << "Unsupported SIMD type";
444 UNREACHABLE();
445 }
446}
447
448// Helper to set up locations for vector shift operations.
449static void CreateVecShiftLocations(ArenaAllocator* arena, HVecBinaryOperation* instruction) {
450 LocationSummary* locations = new (arena) LocationSummary(instruction);
451 switch (instruction->GetPackedType()) {
452 case Primitive::kPrimByte:
453 case Primitive::kPrimChar:
454 case Primitive::kPrimShort:
455 case Primitive::kPrimInt:
456 locations->SetInAt(0, Location::RequiresFpuRegister());
457 locations->SetInAt(1, Location::ConstantLocation(instruction->InputAt(1)->AsConstant()));
458 locations->SetOut(Location::RequiresFpuRegister(), Location::kNoOutputOverlap);
459 break;
460 default:
461 LOG(FATAL) << "Unsupported SIMD type";
462 UNREACHABLE();
463 }
464}
465
466void LocationsBuilderARM64::VisitVecShl(HVecShl* instruction) {
467 CreateVecShiftLocations(GetGraph()->GetArena(), instruction);
468}
469
470void InstructionCodeGeneratorARM64::VisitVecShl(HVecShl* instruction) {
471 LocationSummary* locations = instruction->GetLocations();
472 FPRegister lhs = DRegisterFrom(locations->InAt(0));
473 FPRegister dst = DRegisterFrom(locations->Out());
474 int32_t value = locations->InAt(1).GetConstant()->AsIntConstant()->GetValue();
475 switch (instruction->GetPackedType()) {
476 case Primitive::kPrimByte:
Artem Serovd4bccf12017-04-03 18:47:32 +0100477 DCHECK_EQ(16u, instruction->GetVectorLength());
478 __ Shl(dst.V16B(), lhs.V16B(), value);
Aart Bikf8f5a162017-02-06 15:35:29 -0800479 break;
480 case Primitive::kPrimChar:
481 case Primitive::kPrimShort:
Artem Serovd4bccf12017-04-03 18:47:32 +0100482 DCHECK_EQ(8u, instruction->GetVectorLength());
483 __ Shl(dst.V8H(), lhs.V8H(), value);
Aart Bikf8f5a162017-02-06 15:35:29 -0800484 break;
485 case Primitive::kPrimInt:
Artem Serovd4bccf12017-04-03 18:47:32 +0100486 DCHECK_EQ(4u, instruction->GetVectorLength());
487 __ Shl(dst.V4S(), lhs.V4S(), value);
Aart Bikf8f5a162017-02-06 15:35:29 -0800488 break;
489 default:
490 LOG(FATAL) << "Unsupported SIMD type";
491 UNREACHABLE();
492 }
493}
494
495void LocationsBuilderARM64::VisitVecShr(HVecShr* instruction) {
496 CreateVecShiftLocations(GetGraph()->GetArena(), instruction);
497}
498
499void InstructionCodeGeneratorARM64::VisitVecShr(HVecShr* instruction) {
500 LocationSummary* locations = instruction->GetLocations();
501 FPRegister lhs = DRegisterFrom(locations->InAt(0));
502 FPRegister dst = DRegisterFrom(locations->Out());
503 int32_t value = locations->InAt(1).GetConstant()->AsIntConstant()->GetValue();
504 switch (instruction->GetPackedType()) {
505 case Primitive::kPrimByte:
Artem Serovd4bccf12017-04-03 18:47:32 +0100506 DCHECK_EQ(16u, instruction->GetVectorLength());
507 __ Sshr(dst.V16B(), lhs.V16B(), value);
Aart Bikf8f5a162017-02-06 15:35:29 -0800508 break;
509 case Primitive::kPrimChar:
510 case Primitive::kPrimShort:
Artem Serovd4bccf12017-04-03 18:47:32 +0100511 DCHECK_EQ(8u, instruction->GetVectorLength());
512 __ Sshr(dst.V8H(), lhs.V8H(), value);
Aart Bikf8f5a162017-02-06 15:35:29 -0800513 break;
514 case Primitive::kPrimInt:
Artem Serovd4bccf12017-04-03 18:47:32 +0100515 DCHECK_EQ(4u, instruction->GetVectorLength());
516 __ Sshr(dst.V4S(), lhs.V4S(), value);
Aart Bikf8f5a162017-02-06 15:35:29 -0800517 break;
518 default:
519 LOG(FATAL) << "Unsupported SIMD type";
520 UNREACHABLE();
521 }
522}
523
524void LocationsBuilderARM64::VisitVecUShr(HVecUShr* instruction) {
525 CreateVecShiftLocations(GetGraph()->GetArena(), instruction);
526}
527
528void InstructionCodeGeneratorARM64::VisitVecUShr(HVecUShr* instruction) {
529 LocationSummary* locations = instruction->GetLocations();
530 FPRegister lhs = DRegisterFrom(locations->InAt(0));
531 FPRegister dst = DRegisterFrom(locations->Out());
532 int32_t value = locations->InAt(1).GetConstant()->AsIntConstant()->GetValue();
533 switch (instruction->GetPackedType()) {
534 case Primitive::kPrimByte:
Artem Serovd4bccf12017-04-03 18:47:32 +0100535 DCHECK_EQ(16u, instruction->GetVectorLength());
536 __ Ushr(dst.V16B(), lhs.V16B(), value);
Aart Bikf8f5a162017-02-06 15:35:29 -0800537 break;
538 case Primitive::kPrimChar:
539 case Primitive::kPrimShort:
Artem Serovd4bccf12017-04-03 18:47:32 +0100540 DCHECK_EQ(8u, instruction->GetVectorLength());
541 __ Ushr(dst.V8H(), lhs.V8H(), value);
Aart Bikf8f5a162017-02-06 15:35:29 -0800542 break;
543 case Primitive::kPrimInt:
Artem Serovd4bccf12017-04-03 18:47:32 +0100544 DCHECK_EQ(4u, instruction->GetVectorLength());
545 __ Ushr(dst.V4S(), lhs.V4S(), value);
Aart Bikf8f5a162017-02-06 15:35:29 -0800546 break;
547 default:
548 LOG(FATAL) << "Unsupported SIMD type";
549 UNREACHABLE();
550 }
551}
552
553// Helper to set up locations for vector memory operations.
554static void CreateVecMemLocations(ArenaAllocator* arena,
555 HVecMemoryOperation* instruction,
556 bool is_load) {
557 LocationSummary* locations = new (arena) LocationSummary(instruction);
558 switch (instruction->GetPackedType()) {
559 case Primitive::kPrimBoolean:
560 case Primitive::kPrimByte:
561 case Primitive::kPrimChar:
562 case Primitive::kPrimShort:
563 case Primitive::kPrimInt:
564 case Primitive::kPrimFloat:
565 locations->SetInAt(0, Location::RequiresRegister());
566 locations->SetInAt(1, Location::RegisterOrConstant(instruction->InputAt(1)));
567 if (is_load) {
568 locations->SetOut(Location::RequiresFpuRegister());
569 } else {
570 locations->SetInAt(2, Location::RequiresFpuRegister());
571 }
572 break;
573 default:
574 LOG(FATAL) << "Unsupported SIMD type";
575 UNREACHABLE();
576 }
577}
578
579// Helper to set up registers and address for vector memory operations.
580MemOperand InstructionCodeGeneratorARM64::CreateVecMemRegisters(
581 HVecMemoryOperation* instruction,
582 Location* reg_loc,
583 bool is_load) {
584 LocationSummary* locations = instruction->GetLocations();
585 Register base = InputRegisterAt(instruction, 0);
586 Location index = locations->InAt(1);
587 *reg_loc = is_load ? locations->Out() : locations->InAt(2);
588
589 Primitive::Type packed_type = instruction->GetPackedType();
590 uint32_t offset = mirror::Array::DataOffset(Primitive::ComponentSize(packed_type)).Uint32Value();
591 size_t shift = Primitive::ComponentSizeShift(packed_type);
592
593 UseScratchRegisterScope temps(GetVIXLAssembler());
594 Register temp = temps.AcquireSameSizeAs(base);
595 if (index.IsConstant()) {
596 offset += Int64ConstantFrom(index) << shift;
597 __ Add(temp, base, offset);
598 } else {
599 if (instruction->InputAt(0)->IsIntermediateAddress()) {
600 temp = base;
601 } else {
602 __ Add(temp, base, offset);
603 }
604 __ Add(temp.X(), temp.X(), Operand(XRegisterFrom(index), LSL, shift));
605 }
606 return HeapOperand(temp);
607}
608
609void LocationsBuilderARM64::VisitVecLoad(HVecLoad* instruction) {
610 CreateVecMemLocations(GetGraph()->GetArena(), instruction, /*is_load*/ true);
611}
612
613void InstructionCodeGeneratorARM64::VisitVecLoad(HVecLoad* instruction) {
614 Location reg_loc = Location::NoLocation();
615 MemOperand mem = CreateVecMemRegisters(instruction, &reg_loc, /*is_load*/ true);
616 FPRegister reg = DRegisterFrom(reg_loc);
617 switch (instruction->GetPackedType()) {
618 case Primitive::kPrimBoolean:
619 case Primitive::kPrimByte:
Artem Serovd4bccf12017-04-03 18:47:32 +0100620 DCHECK_EQ(16u, instruction->GetVectorLength());
621 __ Ld1(reg.V16B(), mem);
Aart Bikf8f5a162017-02-06 15:35:29 -0800622 break;
623 case Primitive::kPrimChar:
624 case Primitive::kPrimShort:
Artem Serovd4bccf12017-04-03 18:47:32 +0100625 DCHECK_EQ(8u, instruction->GetVectorLength());
626 __ Ld1(reg.V8H(), mem);
Aart Bikf8f5a162017-02-06 15:35:29 -0800627 break;
628 case Primitive::kPrimInt:
629 case Primitive::kPrimFloat:
Artem Serovd4bccf12017-04-03 18:47:32 +0100630 DCHECK_EQ(4u, instruction->GetVectorLength());
631 __ Ld1(reg.V4S(), mem);
Aart Bikf8f5a162017-02-06 15:35:29 -0800632 break;
633 default:
634 LOG(FATAL) << "Unsupported SIMD type";
635 UNREACHABLE();
636 }
637}
638
639void LocationsBuilderARM64::VisitVecStore(HVecStore* instruction) {
640 CreateVecMemLocations(GetGraph()->GetArena(), instruction, /*is_load*/ false);
641}
642
643void InstructionCodeGeneratorARM64::VisitVecStore(HVecStore* instruction) {
644 Location reg_loc = Location::NoLocation();
645 MemOperand mem = CreateVecMemRegisters(instruction, &reg_loc, /*is_load*/ false);
646 FPRegister reg = DRegisterFrom(reg_loc);
647 switch (instruction->GetPackedType()) {
648 case Primitive::kPrimBoolean:
649 case Primitive::kPrimByte:
Artem Serovd4bccf12017-04-03 18:47:32 +0100650 DCHECK_EQ(16u, instruction->GetVectorLength());
651 __ St1(reg.V16B(), mem);
Aart Bikf8f5a162017-02-06 15:35:29 -0800652 break;
653 case Primitive::kPrimChar:
654 case Primitive::kPrimShort:
Artem Serovd4bccf12017-04-03 18:47:32 +0100655 DCHECK_EQ(8u, instruction->GetVectorLength());
656 __ St1(reg.V8H(), mem);
Aart Bikf8f5a162017-02-06 15:35:29 -0800657 break;
658 case Primitive::kPrimInt:
659 case Primitive::kPrimFloat:
Artem Serovd4bccf12017-04-03 18:47:32 +0100660 DCHECK_EQ(4u, instruction->GetVectorLength());
661 __ St1(reg.V4S(), mem);
Aart Bikf8f5a162017-02-06 15:35:29 -0800662 break;
663 default:
664 LOG(FATAL) << "Unsupported SIMD type";
665 UNREACHABLE();
666 }
667}
668
669#undef __
670
671} // namespace arm64
672} // namespace art