blob: b3eb639142cb91af31705930001a0a70b5c33da7 [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
Artem Serovf34dd202017-04-10 17:41:46 +0100684void LocationsBuilderARM64::VisitVecMultiplyAccumulate(HVecMultiplyAccumulate* instr) {
685 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instr);
686 switch (instr->GetPackedType()) {
687 case Primitive::kPrimByte:
688 case Primitive::kPrimChar:
689 case Primitive::kPrimShort:
690 case Primitive::kPrimInt:
691 locations->SetInAt(
692 HVecMultiplyAccumulate::kInputAccumulatorIndex, Location::RequiresFpuRegister());
693 locations->SetInAt(
694 HVecMultiplyAccumulate::kInputMulLeftIndex, Location::RequiresFpuRegister());
695 locations->SetInAt(
696 HVecMultiplyAccumulate::kInputMulRightIndex, Location::RequiresFpuRegister());
697 DCHECK_EQ(HVecMultiplyAccumulate::kInputAccumulatorIndex, 0);
698 locations->SetOut(Location::SameAsFirstInput());
699 break;
700 default:
701 LOG(FATAL) << "Unsupported SIMD type";
702 UNREACHABLE();
703 }
704}
705
706// Some early revisions of the Cortex-A53 have an erratum (835769) whereby it is possible for a
707// 64-bit scalar multiply-accumulate instruction in AArch64 state to generate an incorrect result.
708// However vector MultiplyAccumulate instruction is not affected.
709void InstructionCodeGeneratorARM64::VisitVecMultiplyAccumulate(HVecMultiplyAccumulate* instr) {
710 LocationSummary* locations = instr->GetLocations();
711 VRegister acc = VRegisterFrom(locations->InAt(HVecMultiplyAccumulate::kInputAccumulatorIndex));
712 VRegister left = VRegisterFrom(locations->InAt(HVecMultiplyAccumulate::kInputMulLeftIndex));
713 VRegister right = VRegisterFrom(locations->InAt(HVecMultiplyAccumulate::kInputMulRightIndex));
714 switch (instr->GetPackedType()) {
715 case Primitive::kPrimByte:
716 DCHECK_EQ(16u, instr->GetVectorLength());
717 if (instr->GetOpKind() == HInstruction::kAdd) {
718 __ Mla(acc.V16B(), left.V16B(), right.V16B());
719 } else {
720 __ Mls(acc.V16B(), left.V16B(), right.V16B());
721 }
722 break;
723 case Primitive::kPrimChar:
724 case Primitive::kPrimShort:
725 DCHECK_EQ(8u, instr->GetVectorLength());
726 if (instr->GetOpKind() == HInstruction::kAdd) {
727 __ Mla(acc.V8H(), left.V8H(), right.V8H());
728 } else {
729 __ Mls(acc.V8H(), left.V8H(), right.V8H());
730 }
731 break;
732 case Primitive::kPrimInt:
733 DCHECK_EQ(4u, instr->GetVectorLength());
734 if (instr->GetOpKind() == HInstruction::kAdd) {
735 __ Mla(acc.V4S(), left.V4S(), right.V4S());
736 } else {
737 __ Mls(acc.V4S(), left.V4S(), right.V4S());
738 }
739 break;
740 default:
741 LOG(FATAL) << "Unsupported SIMD type";
742 }
743}
744
Aart Bikf8f5a162017-02-06 15:35:29 -0800745// Helper to set up locations for vector memory operations.
746static void CreateVecMemLocations(ArenaAllocator* arena,
747 HVecMemoryOperation* instruction,
748 bool is_load) {
749 LocationSummary* locations = new (arena) LocationSummary(instruction);
750 switch (instruction->GetPackedType()) {
751 case Primitive::kPrimBoolean:
752 case Primitive::kPrimByte:
753 case Primitive::kPrimChar:
754 case Primitive::kPrimShort:
755 case Primitive::kPrimInt:
Artem Serovb31f91f2017-04-05 11:31:19 +0100756 case Primitive::kPrimLong:
Aart Bikf8f5a162017-02-06 15:35:29 -0800757 case Primitive::kPrimFloat:
Artem Serovb31f91f2017-04-05 11:31:19 +0100758 case Primitive::kPrimDouble:
Aart Bikf8f5a162017-02-06 15:35:29 -0800759 locations->SetInAt(0, Location::RequiresRegister());
760 locations->SetInAt(1, Location::RegisterOrConstant(instruction->InputAt(1)));
761 if (is_load) {
762 locations->SetOut(Location::RequiresFpuRegister());
763 } else {
764 locations->SetInAt(2, Location::RequiresFpuRegister());
765 }
766 break;
767 default:
768 LOG(FATAL) << "Unsupported SIMD type";
769 UNREACHABLE();
770 }
771}
772
773// Helper to set up registers and address for vector memory operations.
774MemOperand InstructionCodeGeneratorARM64::CreateVecMemRegisters(
775 HVecMemoryOperation* instruction,
776 Location* reg_loc,
777 bool is_load) {
778 LocationSummary* locations = instruction->GetLocations();
779 Register base = InputRegisterAt(instruction, 0);
780 Location index = locations->InAt(1);
781 *reg_loc = is_load ? locations->Out() : locations->InAt(2);
782
783 Primitive::Type packed_type = instruction->GetPackedType();
784 uint32_t offset = mirror::Array::DataOffset(Primitive::ComponentSize(packed_type)).Uint32Value();
785 size_t shift = Primitive::ComponentSizeShift(packed_type);
786
787 UseScratchRegisterScope temps(GetVIXLAssembler());
788 Register temp = temps.AcquireSameSizeAs(base);
789 if (index.IsConstant()) {
790 offset += Int64ConstantFrom(index) << shift;
791 __ Add(temp, base, offset);
792 } else {
793 if (instruction->InputAt(0)->IsIntermediateAddress()) {
794 temp = base;
795 } else {
796 __ Add(temp, base, offset);
797 }
798 __ Add(temp.X(), temp.X(), Operand(XRegisterFrom(index), LSL, shift));
799 }
800 return HeapOperand(temp);
801}
802
803void LocationsBuilderARM64::VisitVecLoad(HVecLoad* instruction) {
804 CreateVecMemLocations(GetGraph()->GetArena(), instruction, /*is_load*/ true);
805}
806
807void InstructionCodeGeneratorARM64::VisitVecLoad(HVecLoad* instruction) {
808 Location reg_loc = Location::NoLocation();
809 MemOperand mem = CreateVecMemRegisters(instruction, &reg_loc, /*is_load*/ true);
Artem Serovb31f91f2017-04-05 11:31:19 +0100810 VRegister reg = VRegisterFrom(reg_loc);
Aart Bikf8f5a162017-02-06 15:35:29 -0800811 switch (instruction->GetPackedType()) {
812 case Primitive::kPrimBoolean:
813 case Primitive::kPrimByte:
Artem Serovd4bccf12017-04-03 18:47:32 +0100814 DCHECK_EQ(16u, instruction->GetVectorLength());
815 __ Ld1(reg.V16B(), mem);
Aart Bikf8f5a162017-02-06 15:35:29 -0800816 break;
817 case Primitive::kPrimChar:
818 case Primitive::kPrimShort:
Artem Serovd4bccf12017-04-03 18:47:32 +0100819 DCHECK_EQ(8u, instruction->GetVectorLength());
820 __ Ld1(reg.V8H(), mem);
Aart Bikf8f5a162017-02-06 15:35:29 -0800821 break;
822 case Primitive::kPrimInt:
823 case Primitive::kPrimFloat:
Artem Serovd4bccf12017-04-03 18:47:32 +0100824 DCHECK_EQ(4u, instruction->GetVectorLength());
825 __ Ld1(reg.V4S(), mem);
Aart Bikf8f5a162017-02-06 15:35:29 -0800826 break;
Artem Serovb31f91f2017-04-05 11:31:19 +0100827 case Primitive::kPrimLong:
828 case Primitive::kPrimDouble:
829 DCHECK_EQ(2u, instruction->GetVectorLength());
830 __ Ld1(reg.V2D(), mem);
831 break;
Aart Bikf8f5a162017-02-06 15:35:29 -0800832 default:
833 LOG(FATAL) << "Unsupported SIMD type";
834 UNREACHABLE();
835 }
836}
837
838void LocationsBuilderARM64::VisitVecStore(HVecStore* instruction) {
839 CreateVecMemLocations(GetGraph()->GetArena(), instruction, /*is_load*/ false);
840}
841
842void InstructionCodeGeneratorARM64::VisitVecStore(HVecStore* instruction) {
843 Location reg_loc = Location::NoLocation();
844 MemOperand mem = CreateVecMemRegisters(instruction, &reg_loc, /*is_load*/ false);
Artem Serovb31f91f2017-04-05 11:31:19 +0100845 VRegister reg = VRegisterFrom(reg_loc);
Aart Bikf8f5a162017-02-06 15:35:29 -0800846 switch (instruction->GetPackedType()) {
847 case Primitive::kPrimBoolean:
848 case Primitive::kPrimByte:
Artem Serovd4bccf12017-04-03 18:47:32 +0100849 DCHECK_EQ(16u, instruction->GetVectorLength());
850 __ St1(reg.V16B(), mem);
Aart Bikf8f5a162017-02-06 15:35:29 -0800851 break;
852 case Primitive::kPrimChar:
853 case Primitive::kPrimShort:
Artem Serovd4bccf12017-04-03 18:47:32 +0100854 DCHECK_EQ(8u, instruction->GetVectorLength());
855 __ St1(reg.V8H(), mem);
Aart Bikf8f5a162017-02-06 15:35:29 -0800856 break;
857 case Primitive::kPrimInt:
858 case Primitive::kPrimFloat:
Artem Serovd4bccf12017-04-03 18:47:32 +0100859 DCHECK_EQ(4u, instruction->GetVectorLength());
860 __ St1(reg.V4S(), mem);
Aart Bikf8f5a162017-02-06 15:35:29 -0800861 break;
Artem Serovb31f91f2017-04-05 11:31:19 +0100862 case Primitive::kPrimLong:
863 case Primitive::kPrimDouble:
864 DCHECK_EQ(2u, instruction->GetVectorLength());
865 __ St1(reg.V2D(), mem);
866 break;
Aart Bikf8f5a162017-02-06 15:35:29 -0800867 default:
868 LOG(FATAL) << "Unsupported SIMD type";
869 UNREACHABLE();
870 }
871}
872
873#undef __
874
875} // namespace arm64
876} // namespace art