blob: 478bd24388603fa43eb2b646e75f6771c5727f8a [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
Aart Bik472821b2017-04-27 17:23:51 -070025using helpers::DRegisterFrom;
Artem Serovb31f91f2017-04-05 11:31:19 +010026using helpers::VRegisterFrom;
Aart Bikf8f5a162017-02-06 15:35:29 -080027using helpers::HeapOperand;
28using helpers::InputRegisterAt;
29using helpers::Int64ConstantFrom;
30using helpers::XRegisterFrom;
Artem Serov0225b772017-04-19 15:43:53 +010031using helpers::WRegisterFrom;
Aart Bikf8f5a162017-02-06 15:35:29 -080032
33#define __ GetVIXLAssembler()->
34
35void LocationsBuilderARM64::VisitVecReplicateScalar(HVecReplicateScalar* instruction) {
36 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction);
37 switch (instruction->GetPackedType()) {
38 case Primitive::kPrimBoolean:
39 case Primitive::kPrimByte:
40 case Primitive::kPrimChar:
41 case Primitive::kPrimShort:
42 case Primitive::kPrimInt:
Artem Serovb31f91f2017-04-05 11:31:19 +010043 case Primitive::kPrimLong:
Aart Bikf8f5a162017-02-06 15:35:29 -080044 locations->SetInAt(0, Location::RequiresRegister());
45 locations->SetOut(Location::RequiresFpuRegister());
46 break;
47 case Primitive::kPrimFloat:
Artem Serovb31f91f2017-04-05 11:31:19 +010048 case Primitive::kPrimDouble:
Aart Bikf8f5a162017-02-06 15:35:29 -080049 locations->SetInAt(0, Location::RequiresFpuRegister());
50 locations->SetOut(Location::RequiresFpuRegister(), Location::kNoOutputOverlap);
51 break;
52 default:
53 LOG(FATAL) << "Unsupported SIMD type";
54 UNREACHABLE();
55 }
56}
57
58void InstructionCodeGeneratorARM64::VisitVecReplicateScalar(HVecReplicateScalar* instruction) {
59 LocationSummary* locations = instruction->GetLocations();
Artem Serovb31f91f2017-04-05 11:31:19 +010060 VRegister dst = VRegisterFrom(locations->Out());
Aart Bikf8f5a162017-02-06 15:35:29 -080061 switch (instruction->GetPackedType()) {
62 case Primitive::kPrimBoolean:
63 case Primitive::kPrimByte:
Artem Serovd4bccf12017-04-03 18:47:32 +010064 DCHECK_EQ(16u, instruction->GetVectorLength());
65 __ Dup(dst.V16B(), InputRegisterAt(instruction, 0));
Aart Bikf8f5a162017-02-06 15:35:29 -080066 break;
67 case Primitive::kPrimChar:
68 case Primitive::kPrimShort:
Artem Serovd4bccf12017-04-03 18:47:32 +010069 DCHECK_EQ(8u, instruction->GetVectorLength());
70 __ Dup(dst.V8H(), InputRegisterAt(instruction, 0));
Aart Bikf8f5a162017-02-06 15:35:29 -080071 break;
72 case Primitive::kPrimInt:
Artem Serovd4bccf12017-04-03 18:47:32 +010073 DCHECK_EQ(4u, instruction->GetVectorLength());
74 __ Dup(dst.V4S(), InputRegisterAt(instruction, 0));
Aart Bikf8f5a162017-02-06 15:35:29 -080075 break;
Artem Serovb31f91f2017-04-05 11:31:19 +010076 case Primitive::kPrimLong:
77 DCHECK_EQ(2u, instruction->GetVectorLength());
78 __ Dup(dst.V2D(), XRegisterFrom(locations->InAt(0)));
79 break;
Aart Bikf8f5a162017-02-06 15:35:29 -080080 case Primitive::kPrimFloat:
Artem Serovd4bccf12017-04-03 18:47:32 +010081 DCHECK_EQ(4u, instruction->GetVectorLength());
Artem Serovb31f91f2017-04-05 11:31:19 +010082 __ Dup(dst.V4S(), VRegisterFrom(locations->InAt(0)).V4S(), 0);
83 break;
84 case Primitive::kPrimDouble:
85 DCHECK_EQ(2u, instruction->GetVectorLength());
86 __ Dup(dst.V2D(), VRegisterFrom(locations->InAt(0)).V2D(), 0);
Aart Bikf8f5a162017-02-06 15:35:29 -080087 break;
88 default:
89 LOG(FATAL) << "Unsupported SIMD type";
90 UNREACHABLE();
91 }
92}
93
94void LocationsBuilderARM64::VisitVecSetScalars(HVecSetScalars* instruction) {
95 LOG(FATAL) << "No SIMD for " << instruction->GetId();
96}
97
98void InstructionCodeGeneratorARM64::VisitVecSetScalars(HVecSetScalars* instruction) {
99 LOG(FATAL) << "No SIMD for " << instruction->GetId();
100}
101
102void LocationsBuilderARM64::VisitVecSumReduce(HVecSumReduce* instruction) {
103 LOG(FATAL) << "No SIMD for " << instruction->GetId();
104}
105
106void InstructionCodeGeneratorARM64::VisitVecSumReduce(HVecSumReduce* instruction) {
107 LOG(FATAL) << "No SIMD for " << instruction->GetId();
108}
109
110// Helper to set up locations for vector unary operations.
111static void CreateVecUnOpLocations(ArenaAllocator* arena, HVecUnaryOperation* instruction) {
112 LocationSummary* locations = new (arena) LocationSummary(instruction);
113 switch (instruction->GetPackedType()) {
114 case Primitive::kPrimBoolean:
115 locations->SetInAt(0, Location::RequiresFpuRegister());
116 locations->SetOut(Location::RequiresFpuRegister(),
117 instruction->IsVecNot() ? Location::kOutputOverlap
118 : Location::kNoOutputOverlap);
119 break;
120 case Primitive::kPrimByte:
121 case Primitive::kPrimChar:
122 case Primitive::kPrimShort:
123 case Primitive::kPrimInt:
Artem Serovb31f91f2017-04-05 11:31:19 +0100124 case Primitive::kPrimLong:
Aart Bikf8f5a162017-02-06 15:35:29 -0800125 case Primitive::kPrimFloat:
Artem Serovb31f91f2017-04-05 11:31:19 +0100126 case Primitive::kPrimDouble:
Aart Bikf8f5a162017-02-06 15:35:29 -0800127 locations->SetInAt(0, Location::RequiresFpuRegister());
128 locations->SetOut(Location::RequiresFpuRegister(), Location::kNoOutputOverlap);
129 break;
130 default:
131 LOG(FATAL) << "Unsupported SIMD type";
132 UNREACHABLE();
133 }
134}
135
136void LocationsBuilderARM64::VisitVecCnv(HVecCnv* instruction) {
137 CreateVecUnOpLocations(GetGraph()->GetArena(), instruction);
138}
139
140void InstructionCodeGeneratorARM64::VisitVecCnv(HVecCnv* instruction) {
141 LocationSummary* locations = instruction->GetLocations();
Artem Serovb31f91f2017-04-05 11:31:19 +0100142 VRegister src = VRegisterFrom(locations->InAt(0));
143 VRegister dst = VRegisterFrom(locations->Out());
Aart Bikf8f5a162017-02-06 15:35:29 -0800144 Primitive::Type from = instruction->GetInputType();
145 Primitive::Type to = instruction->GetResultType();
146 if (from == Primitive::kPrimInt && to == Primitive::kPrimFloat) {
Artem Serovd4bccf12017-04-03 18:47:32 +0100147 DCHECK_EQ(4u, instruction->GetVectorLength());
148 __ Scvtf(dst.V4S(), src.V4S());
Aart Bikf8f5a162017-02-06 15:35:29 -0800149 } else {
150 LOG(FATAL) << "Unsupported SIMD type";
151 }
152}
153
154void LocationsBuilderARM64::VisitVecNeg(HVecNeg* instruction) {
155 CreateVecUnOpLocations(GetGraph()->GetArena(), instruction);
156}
157
158void InstructionCodeGeneratorARM64::VisitVecNeg(HVecNeg* instruction) {
159 LocationSummary* locations = instruction->GetLocations();
Artem Serovb31f91f2017-04-05 11:31:19 +0100160 VRegister src = VRegisterFrom(locations->InAt(0));
161 VRegister dst = VRegisterFrom(locations->Out());
Aart Bikf8f5a162017-02-06 15:35:29 -0800162 switch (instruction->GetPackedType()) {
163 case Primitive::kPrimByte:
Artem Serovd4bccf12017-04-03 18:47:32 +0100164 DCHECK_EQ(16u, instruction->GetVectorLength());
165 __ Neg(dst.V16B(), src.V16B());
Aart Bikf8f5a162017-02-06 15:35:29 -0800166 break;
167 case Primitive::kPrimChar:
168 case Primitive::kPrimShort:
Artem Serovd4bccf12017-04-03 18:47:32 +0100169 DCHECK_EQ(8u, instruction->GetVectorLength());
170 __ Neg(dst.V8H(), src.V8H());
Aart Bikf8f5a162017-02-06 15:35:29 -0800171 break;
172 case Primitive::kPrimInt:
Artem Serovd4bccf12017-04-03 18:47:32 +0100173 DCHECK_EQ(4u, instruction->GetVectorLength());
174 __ Neg(dst.V4S(), src.V4S());
Aart Bikf8f5a162017-02-06 15:35:29 -0800175 break;
Artem Serovb31f91f2017-04-05 11:31:19 +0100176 case Primitive::kPrimLong:
177 DCHECK_EQ(2u, instruction->GetVectorLength());
178 __ Neg(dst.V2D(), src.V2D());
179 break;
Aart Bikf8f5a162017-02-06 15:35:29 -0800180 case Primitive::kPrimFloat:
Artem Serovd4bccf12017-04-03 18:47:32 +0100181 DCHECK_EQ(4u, instruction->GetVectorLength());
182 __ Fneg(dst.V4S(), src.V4S());
Aart Bikf8f5a162017-02-06 15:35:29 -0800183 break;
Artem Serovb31f91f2017-04-05 11:31:19 +0100184 case Primitive::kPrimDouble:
185 DCHECK_EQ(2u, instruction->GetVectorLength());
186 __ Fneg(dst.V2D(), src.V2D());
187 break;
Aart Bikf8f5a162017-02-06 15:35:29 -0800188 default:
189 LOG(FATAL) << "Unsupported SIMD type";
190 UNREACHABLE();
191 }
192}
193
Aart Bik6daebeb2017-04-03 14:35:41 -0700194void LocationsBuilderARM64::VisitVecAbs(HVecAbs* instruction) {
195 CreateVecUnOpLocations(GetGraph()->GetArena(), instruction);
196}
197
198void InstructionCodeGeneratorARM64::VisitVecAbs(HVecAbs* instruction) {
199 LocationSummary* locations = instruction->GetLocations();
Artem Serovb31f91f2017-04-05 11:31:19 +0100200 VRegister src = VRegisterFrom(locations->InAt(0));
201 VRegister dst = VRegisterFrom(locations->Out());
Aart Bik6daebeb2017-04-03 14:35:41 -0700202 switch (instruction->GetPackedType()) {
203 case Primitive::kPrimByte:
Artem Serovd4bccf12017-04-03 18:47:32 +0100204 DCHECK_EQ(16u, instruction->GetVectorLength());
205 __ Abs(dst.V16B(), src.V16B());
Aart Bik6daebeb2017-04-03 14:35:41 -0700206 break;
207 case Primitive::kPrimChar:
208 case Primitive::kPrimShort:
Artem Serovd4bccf12017-04-03 18:47:32 +0100209 DCHECK_EQ(8u, instruction->GetVectorLength());
210 __ Abs(dst.V8H(), src.V8H());
Aart Bik6daebeb2017-04-03 14:35:41 -0700211 break;
212 case Primitive::kPrimInt:
Artem Serovd4bccf12017-04-03 18:47:32 +0100213 DCHECK_EQ(4u, instruction->GetVectorLength());
214 __ Abs(dst.V4S(), src.V4S());
Aart Bik6daebeb2017-04-03 14:35:41 -0700215 break;
Artem Serovb31f91f2017-04-05 11:31:19 +0100216 case Primitive::kPrimLong:
217 DCHECK_EQ(2u, instruction->GetVectorLength());
218 __ Abs(dst.V2D(), src.V2D());
219 break;
Aart Bik6daebeb2017-04-03 14:35:41 -0700220 case Primitive::kPrimFloat:
Artem Serovd4bccf12017-04-03 18:47:32 +0100221 DCHECK_EQ(4u, instruction->GetVectorLength());
222 __ Fabs(dst.V4S(), src.V4S());
Aart Bik6daebeb2017-04-03 14:35:41 -0700223 break;
Artem Serovb31f91f2017-04-05 11:31:19 +0100224 case Primitive::kPrimDouble:
225 DCHECK_EQ(2u, instruction->GetVectorLength());
226 __ Fabs(dst.V2D(), src.V2D());
227 break;
Aart Bik6daebeb2017-04-03 14:35:41 -0700228 default:
229 LOG(FATAL) << "Unsupported SIMD type";
230 }
231}
232
Aart Bikf8f5a162017-02-06 15:35:29 -0800233void LocationsBuilderARM64::VisitVecNot(HVecNot* instruction) {
234 CreateVecUnOpLocations(GetGraph()->GetArena(), instruction);
235}
236
237void InstructionCodeGeneratorARM64::VisitVecNot(HVecNot* instruction) {
238 LocationSummary* locations = instruction->GetLocations();
Artem Serovb31f91f2017-04-05 11:31:19 +0100239 VRegister src = VRegisterFrom(locations->InAt(0));
240 VRegister dst = VRegisterFrom(locations->Out());
Aart Bikf8f5a162017-02-06 15:35:29 -0800241 switch (instruction->GetPackedType()) {
242 case Primitive::kPrimBoolean: // special case boolean-not
Artem Serovd4bccf12017-04-03 18:47:32 +0100243 DCHECK_EQ(16u, instruction->GetVectorLength());
244 __ Movi(dst.V16B(), 1);
245 __ Eor(dst.V16B(), dst.V16B(), src.V16B());
Aart Bikf8f5a162017-02-06 15:35:29 -0800246 break;
247 case Primitive::kPrimByte:
248 case Primitive::kPrimChar:
249 case Primitive::kPrimShort:
250 case Primitive::kPrimInt:
Artem Serovb31f91f2017-04-05 11:31:19 +0100251 case Primitive::kPrimLong:
Artem Serovd4bccf12017-04-03 18:47:32 +0100252 __ Not(dst.V16B(), src.V16B()); // lanes do not matter
Aart Bikf8f5a162017-02-06 15:35:29 -0800253 break;
254 default:
255 LOG(FATAL) << "Unsupported SIMD type";
256 UNREACHABLE();
257 }
258}
259
260// Helper to set up locations for vector binary operations.
261static void CreateVecBinOpLocations(ArenaAllocator* arena, HVecBinaryOperation* instruction) {
262 LocationSummary* locations = new (arena) LocationSummary(instruction);
263 switch (instruction->GetPackedType()) {
264 case Primitive::kPrimBoolean:
265 case Primitive::kPrimByte:
266 case Primitive::kPrimChar:
267 case Primitive::kPrimShort:
268 case Primitive::kPrimInt:
Artem Serovb31f91f2017-04-05 11:31:19 +0100269 case Primitive::kPrimLong:
Aart Bikf8f5a162017-02-06 15:35:29 -0800270 case Primitive::kPrimFloat:
Artem Serovb31f91f2017-04-05 11:31:19 +0100271 case Primitive::kPrimDouble:
Aart Bikf8f5a162017-02-06 15:35:29 -0800272 locations->SetInAt(0, Location::RequiresFpuRegister());
273 locations->SetInAt(1, Location::RequiresFpuRegister());
274 locations->SetOut(Location::RequiresFpuRegister(), Location::kNoOutputOverlap);
275 break;
276 default:
277 LOG(FATAL) << "Unsupported SIMD type";
278 UNREACHABLE();
279 }
280}
281
282void LocationsBuilderARM64::VisitVecAdd(HVecAdd* instruction) {
283 CreateVecBinOpLocations(GetGraph()->GetArena(), instruction);
284}
285
286void InstructionCodeGeneratorARM64::VisitVecAdd(HVecAdd* instruction) {
287 LocationSummary* locations = instruction->GetLocations();
Artem Serovb31f91f2017-04-05 11:31:19 +0100288 VRegister lhs = VRegisterFrom(locations->InAt(0));
289 VRegister rhs = VRegisterFrom(locations->InAt(1));
290 VRegister dst = VRegisterFrom(locations->Out());
Aart Bikf8f5a162017-02-06 15:35:29 -0800291 switch (instruction->GetPackedType()) {
292 case Primitive::kPrimByte:
Artem Serovd4bccf12017-04-03 18:47:32 +0100293 DCHECK_EQ(16u, instruction->GetVectorLength());
294 __ Add(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 __ Add(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 __ Add(dst.V4S(), lhs.V4S(), rhs.V4S());
Aart Bikf8f5a162017-02-06 15:35:29 -0800304 break;
Artem Serovb31f91f2017-04-05 11:31:19 +0100305 case Primitive::kPrimLong:
306 DCHECK_EQ(2u, instruction->GetVectorLength());
307 __ Add(dst.V2D(), lhs.V2D(), rhs.V2D());
308 break;
Aart Bikf8f5a162017-02-06 15:35:29 -0800309 case Primitive::kPrimFloat:
Artem Serovd4bccf12017-04-03 18:47:32 +0100310 DCHECK_EQ(4u, instruction->GetVectorLength());
311 __ Fadd(dst.V4S(), lhs.V4S(), rhs.V4S());
Aart Bikf8f5a162017-02-06 15:35:29 -0800312 break;
Artem Serovb31f91f2017-04-05 11:31:19 +0100313 case Primitive::kPrimDouble:
314 DCHECK_EQ(2u, instruction->GetVectorLength());
315 __ Fadd(dst.V2D(), lhs.V2D(), rhs.V2D());
316 break;
Aart Bikf8f5a162017-02-06 15:35:29 -0800317 default:
318 LOG(FATAL) << "Unsupported SIMD type";
319 UNREACHABLE();
320 }
321}
322
Aart Bikf3e61ee2017-04-12 17:09:20 -0700323void LocationsBuilderARM64::VisitVecHalvingAdd(HVecHalvingAdd* instruction) {
324 CreateVecBinOpLocations(GetGraph()->GetArena(), instruction);
325}
326
327void InstructionCodeGeneratorARM64::VisitVecHalvingAdd(HVecHalvingAdd* instruction) {
328 LocationSummary* locations = instruction->GetLocations();
329 VRegister lhs = VRegisterFrom(locations->InAt(0));
330 VRegister rhs = VRegisterFrom(locations->InAt(1));
331 VRegister dst = VRegisterFrom(locations->Out());
332 switch (instruction->GetPackedType()) {
333 case Primitive::kPrimByte:
334 DCHECK_EQ(16u, instruction->GetVectorLength());
335 if (instruction->IsUnsigned()) {
336 instruction->IsRounded()
337 ? __ Urhadd(dst.V16B(), lhs.V16B(), rhs.V16B())
338 : __ Uhadd(dst.V16B(), lhs.V16B(), rhs.V16B());
339 } else {
340 instruction->IsRounded()
341 ? __ Srhadd(dst.V16B(), lhs.V16B(), rhs.V16B())
342 : __ Shadd(dst.V16B(), lhs.V16B(), rhs.V16B());
343 }
344 break;
345 case Primitive::kPrimChar:
346 case Primitive::kPrimShort:
347 DCHECK_EQ(8u, instruction->GetVectorLength());
348 if (instruction->IsUnsigned()) {
349 instruction->IsRounded()
350 ? __ Urhadd(dst.V8H(), lhs.V8H(), rhs.V8H())
351 : __ Uhadd(dst.V8H(), lhs.V8H(), rhs.V8H());
352 } else {
353 instruction->IsRounded()
354 ? __ Srhadd(dst.V8H(), lhs.V8H(), rhs.V8H())
355 : __ Shadd(dst.V8H(), lhs.V8H(), rhs.V8H());
356 }
357 break;
358 default:
359 LOG(FATAL) << "Unsupported SIMD type";
360 UNREACHABLE();
361 }
362}
363
Aart Bikf8f5a162017-02-06 15:35:29 -0800364void LocationsBuilderARM64::VisitVecSub(HVecSub* instruction) {
365 CreateVecBinOpLocations(GetGraph()->GetArena(), instruction);
366}
367
368void InstructionCodeGeneratorARM64::VisitVecSub(HVecSub* instruction) {
369 LocationSummary* locations = instruction->GetLocations();
Artem Serovb31f91f2017-04-05 11:31:19 +0100370 VRegister lhs = VRegisterFrom(locations->InAt(0));
371 VRegister rhs = VRegisterFrom(locations->InAt(1));
372 VRegister dst = VRegisterFrom(locations->Out());
Aart Bikf8f5a162017-02-06 15:35:29 -0800373 switch (instruction->GetPackedType()) {
374 case Primitive::kPrimByte:
Artem Serovd4bccf12017-04-03 18:47:32 +0100375 DCHECK_EQ(16u, instruction->GetVectorLength());
376 __ Sub(dst.V16B(), lhs.V16B(), rhs.V16B());
Aart Bikf8f5a162017-02-06 15:35:29 -0800377 break;
378 case Primitive::kPrimChar:
379 case Primitive::kPrimShort:
Artem Serovd4bccf12017-04-03 18:47:32 +0100380 DCHECK_EQ(8u, instruction->GetVectorLength());
381 __ Sub(dst.V8H(), lhs.V8H(), rhs.V8H());
Aart Bikf8f5a162017-02-06 15:35:29 -0800382 break;
383 case Primitive::kPrimInt:
Artem Serovd4bccf12017-04-03 18:47:32 +0100384 DCHECK_EQ(4u, instruction->GetVectorLength());
385 __ Sub(dst.V4S(), lhs.V4S(), rhs.V4S());
Aart Bikf8f5a162017-02-06 15:35:29 -0800386 break;
Artem Serovb31f91f2017-04-05 11:31:19 +0100387 case Primitive::kPrimLong:
388 DCHECK_EQ(2u, instruction->GetVectorLength());
389 __ Sub(dst.V2D(), lhs.V2D(), rhs.V2D());
390 break;
Aart Bikf8f5a162017-02-06 15:35:29 -0800391 case Primitive::kPrimFloat:
Artem Serovd4bccf12017-04-03 18:47:32 +0100392 DCHECK_EQ(4u, instruction->GetVectorLength());
393 __ Fsub(dst.V4S(), lhs.V4S(), rhs.V4S());
Aart Bikf8f5a162017-02-06 15:35:29 -0800394 break;
Artem Serovb31f91f2017-04-05 11:31:19 +0100395 case Primitive::kPrimDouble:
396 DCHECK_EQ(2u, instruction->GetVectorLength());
397 __ Fsub(dst.V2D(), lhs.V2D(), rhs.V2D());
398 break;
Aart Bikf8f5a162017-02-06 15:35:29 -0800399 default:
400 LOG(FATAL) << "Unsupported SIMD type";
401 UNREACHABLE();
402 }
403}
404
405void LocationsBuilderARM64::VisitVecMul(HVecMul* instruction) {
406 CreateVecBinOpLocations(GetGraph()->GetArena(), instruction);
407}
408
409void InstructionCodeGeneratorARM64::VisitVecMul(HVecMul* instruction) {
410 LocationSummary* locations = instruction->GetLocations();
Artem Serovb31f91f2017-04-05 11:31:19 +0100411 VRegister lhs = VRegisterFrom(locations->InAt(0));
412 VRegister rhs = VRegisterFrom(locations->InAt(1));
413 VRegister dst = VRegisterFrom(locations->Out());
Aart Bikf8f5a162017-02-06 15:35:29 -0800414 switch (instruction->GetPackedType()) {
415 case Primitive::kPrimByte:
Artem Serovd4bccf12017-04-03 18:47:32 +0100416 DCHECK_EQ(16u, instruction->GetVectorLength());
417 __ Mul(dst.V16B(), lhs.V16B(), rhs.V16B());
Aart Bikf8f5a162017-02-06 15:35:29 -0800418 break;
419 case Primitive::kPrimChar:
420 case Primitive::kPrimShort:
Artem Serovd4bccf12017-04-03 18:47:32 +0100421 DCHECK_EQ(8u, instruction->GetVectorLength());
422 __ Mul(dst.V8H(), lhs.V8H(), rhs.V8H());
Aart Bikf8f5a162017-02-06 15:35:29 -0800423 break;
424 case Primitive::kPrimInt:
Artem Serovd4bccf12017-04-03 18:47:32 +0100425 DCHECK_EQ(4u, instruction->GetVectorLength());
426 __ Mul(dst.V4S(), lhs.V4S(), rhs.V4S());
Aart Bikf8f5a162017-02-06 15:35:29 -0800427 break;
428 case Primitive::kPrimFloat:
Artem Serovd4bccf12017-04-03 18:47:32 +0100429 DCHECK_EQ(4u, instruction->GetVectorLength());
430 __ Fmul(dst.V4S(), lhs.V4S(), rhs.V4S());
Aart Bikf8f5a162017-02-06 15:35:29 -0800431 break;
Artem Serovb31f91f2017-04-05 11:31:19 +0100432 case Primitive::kPrimDouble:
433 DCHECK_EQ(2u, instruction->GetVectorLength());
434 __ Fmul(dst.V2D(), lhs.V2D(), rhs.V2D());
435 break;
Aart Bikf8f5a162017-02-06 15:35:29 -0800436 default:
437 LOG(FATAL) << "Unsupported SIMD type";
438 UNREACHABLE();
439 }
440}
441
442void LocationsBuilderARM64::VisitVecDiv(HVecDiv* instruction) {
443 CreateVecBinOpLocations(GetGraph()->GetArena(), instruction);
444}
445
446void InstructionCodeGeneratorARM64::VisitVecDiv(HVecDiv* instruction) {
447 LocationSummary* locations = instruction->GetLocations();
Artem Serovb31f91f2017-04-05 11:31:19 +0100448 VRegister lhs = VRegisterFrom(locations->InAt(0));
449 VRegister rhs = VRegisterFrom(locations->InAt(1));
450 VRegister dst = VRegisterFrom(locations->Out());
Aart Bikf8f5a162017-02-06 15:35:29 -0800451 switch (instruction->GetPackedType()) {
452 case Primitive::kPrimFloat:
Artem Serovd4bccf12017-04-03 18:47:32 +0100453 DCHECK_EQ(4u, instruction->GetVectorLength());
454 __ Fdiv(dst.V4S(), lhs.V4S(), rhs.V4S());
Aart Bikf8f5a162017-02-06 15:35:29 -0800455 break;
Artem Serovb31f91f2017-04-05 11:31:19 +0100456 case Primitive::kPrimDouble:
457 DCHECK_EQ(2u, instruction->GetVectorLength());
458 __ Fdiv(dst.V2D(), lhs.V2D(), rhs.V2D());
459 break;
Aart Bikf8f5a162017-02-06 15:35:29 -0800460 default:
461 LOG(FATAL) << "Unsupported SIMD type";
462 UNREACHABLE();
463 }
464}
465
Aart Bikf3e61ee2017-04-12 17:09:20 -0700466void LocationsBuilderARM64::VisitVecMin(HVecMin* instruction) {
467 CreateVecBinOpLocations(GetGraph()->GetArena(), instruction);
468}
469
470void InstructionCodeGeneratorARM64::VisitVecMin(HVecMin* instruction) {
471 LOG(FATAL) << "Unsupported SIMD instruction " << instruction->GetId();
472}
473
474void LocationsBuilderARM64::VisitVecMax(HVecMax* instruction) {
475 CreateVecBinOpLocations(GetGraph()->GetArena(), instruction);
476}
477
478void InstructionCodeGeneratorARM64::VisitVecMax(HVecMax* instruction) {
479 LOG(FATAL) << "Unsupported SIMD instruction " << instruction->GetId();
480}
481
Aart Bikf8f5a162017-02-06 15:35:29 -0800482void LocationsBuilderARM64::VisitVecAnd(HVecAnd* instruction) {
483 CreateVecBinOpLocations(GetGraph()->GetArena(), instruction);
484}
485
486void InstructionCodeGeneratorARM64::VisitVecAnd(HVecAnd* instruction) {
487 LocationSummary* locations = instruction->GetLocations();
Artem Serovb31f91f2017-04-05 11:31:19 +0100488 VRegister lhs = VRegisterFrom(locations->InAt(0));
489 VRegister rhs = VRegisterFrom(locations->InAt(1));
490 VRegister dst = VRegisterFrom(locations->Out());
Aart Bikf8f5a162017-02-06 15:35:29 -0800491 switch (instruction->GetPackedType()) {
492 case Primitive::kPrimBoolean:
493 case Primitive::kPrimByte:
494 case Primitive::kPrimChar:
495 case Primitive::kPrimShort:
496 case Primitive::kPrimInt:
Artem Serovb31f91f2017-04-05 11:31:19 +0100497 case Primitive::kPrimLong:
Aart Bikf8f5a162017-02-06 15:35:29 -0800498 case Primitive::kPrimFloat:
Artem Serovb31f91f2017-04-05 11:31:19 +0100499 case Primitive::kPrimDouble:
Artem Serovd4bccf12017-04-03 18:47:32 +0100500 __ And(dst.V16B(), lhs.V16B(), rhs.V16B()); // lanes do not matter
Aart Bikf8f5a162017-02-06 15:35:29 -0800501 break;
502 default:
503 LOG(FATAL) << "Unsupported SIMD type";
504 UNREACHABLE();
505 }
506}
507
508void LocationsBuilderARM64::VisitVecAndNot(HVecAndNot* instruction) {
509 LOG(FATAL) << "Unsupported SIMD instruction " << instruction->GetId();
510}
511
512void InstructionCodeGeneratorARM64::VisitVecAndNot(HVecAndNot* instruction) {
513 LOG(FATAL) << "Unsupported SIMD instruction " << instruction->GetId();
514}
515
516void LocationsBuilderARM64::VisitVecOr(HVecOr* instruction) {
517 CreateVecBinOpLocations(GetGraph()->GetArena(), instruction);
518}
519
520void InstructionCodeGeneratorARM64::VisitVecOr(HVecOr* instruction) {
521 LocationSummary* locations = instruction->GetLocations();
Artem Serovb31f91f2017-04-05 11:31:19 +0100522 VRegister lhs = VRegisterFrom(locations->InAt(0));
523 VRegister rhs = VRegisterFrom(locations->InAt(1));
524 VRegister dst = VRegisterFrom(locations->Out());
Aart Bikf8f5a162017-02-06 15:35:29 -0800525 switch (instruction->GetPackedType()) {
526 case Primitive::kPrimBoolean:
527 case Primitive::kPrimByte:
528 case Primitive::kPrimChar:
529 case Primitive::kPrimShort:
530 case Primitive::kPrimInt:
Artem Serovb31f91f2017-04-05 11:31:19 +0100531 case Primitive::kPrimLong:
Aart Bikf8f5a162017-02-06 15:35:29 -0800532 case Primitive::kPrimFloat:
Artem Serovb31f91f2017-04-05 11:31:19 +0100533 case Primitive::kPrimDouble:
Artem Serovd4bccf12017-04-03 18:47:32 +0100534 __ Orr(dst.V16B(), lhs.V16B(), rhs.V16B()); // lanes do not matter
Aart Bikf8f5a162017-02-06 15:35:29 -0800535 break;
536 default:
537 LOG(FATAL) << "Unsupported SIMD type";
538 UNREACHABLE();
539 }
540}
541
542void LocationsBuilderARM64::VisitVecXor(HVecXor* instruction) {
543 CreateVecBinOpLocations(GetGraph()->GetArena(), instruction);
544}
545
546void InstructionCodeGeneratorARM64::VisitVecXor(HVecXor* instruction) {
547 LocationSummary* locations = instruction->GetLocations();
Artem Serovb31f91f2017-04-05 11:31:19 +0100548 VRegister lhs = VRegisterFrom(locations->InAt(0));
549 VRegister rhs = VRegisterFrom(locations->InAt(1));
550 VRegister dst = VRegisterFrom(locations->Out());
Aart Bikf8f5a162017-02-06 15:35:29 -0800551 switch (instruction->GetPackedType()) {
552 case Primitive::kPrimBoolean:
553 case Primitive::kPrimByte:
554 case Primitive::kPrimChar:
555 case Primitive::kPrimShort:
556 case Primitive::kPrimInt:
Artem Serovb31f91f2017-04-05 11:31:19 +0100557 case Primitive::kPrimLong:
Aart Bikf8f5a162017-02-06 15:35:29 -0800558 case Primitive::kPrimFloat:
Artem Serovb31f91f2017-04-05 11:31:19 +0100559 case Primitive::kPrimDouble:
Artem Serovd4bccf12017-04-03 18:47:32 +0100560 __ Eor(dst.V16B(), lhs.V16B(), rhs.V16B()); // lanes do not matter
Aart Bikf8f5a162017-02-06 15:35:29 -0800561 break;
562 default:
563 LOG(FATAL) << "Unsupported SIMD type";
564 UNREACHABLE();
565 }
566}
567
568// Helper to set up locations for vector shift operations.
569static void CreateVecShiftLocations(ArenaAllocator* arena, HVecBinaryOperation* instruction) {
570 LocationSummary* locations = new (arena) LocationSummary(instruction);
571 switch (instruction->GetPackedType()) {
572 case Primitive::kPrimByte:
573 case Primitive::kPrimChar:
574 case Primitive::kPrimShort:
575 case Primitive::kPrimInt:
Artem Serovb31f91f2017-04-05 11:31:19 +0100576 case Primitive::kPrimLong:
Aart Bikf8f5a162017-02-06 15:35:29 -0800577 locations->SetInAt(0, Location::RequiresFpuRegister());
578 locations->SetInAt(1, Location::ConstantLocation(instruction->InputAt(1)->AsConstant()));
579 locations->SetOut(Location::RequiresFpuRegister(), Location::kNoOutputOverlap);
580 break;
581 default:
582 LOG(FATAL) << "Unsupported SIMD type";
583 UNREACHABLE();
584 }
585}
586
587void LocationsBuilderARM64::VisitVecShl(HVecShl* instruction) {
588 CreateVecShiftLocations(GetGraph()->GetArena(), instruction);
589}
590
591void InstructionCodeGeneratorARM64::VisitVecShl(HVecShl* instruction) {
592 LocationSummary* locations = instruction->GetLocations();
Artem Serovb31f91f2017-04-05 11:31:19 +0100593 VRegister lhs = VRegisterFrom(locations->InAt(0));
594 VRegister dst = VRegisterFrom(locations->Out());
Aart Bikf8f5a162017-02-06 15:35:29 -0800595 int32_t value = locations->InAt(1).GetConstant()->AsIntConstant()->GetValue();
596 switch (instruction->GetPackedType()) {
597 case Primitive::kPrimByte:
Artem Serovd4bccf12017-04-03 18:47:32 +0100598 DCHECK_EQ(16u, instruction->GetVectorLength());
599 __ Shl(dst.V16B(), lhs.V16B(), value);
Aart Bikf8f5a162017-02-06 15:35:29 -0800600 break;
601 case Primitive::kPrimChar:
602 case Primitive::kPrimShort:
Artem Serovd4bccf12017-04-03 18:47:32 +0100603 DCHECK_EQ(8u, instruction->GetVectorLength());
604 __ Shl(dst.V8H(), lhs.V8H(), value);
Aart Bikf8f5a162017-02-06 15:35:29 -0800605 break;
606 case Primitive::kPrimInt:
Artem Serovd4bccf12017-04-03 18:47:32 +0100607 DCHECK_EQ(4u, instruction->GetVectorLength());
608 __ Shl(dst.V4S(), lhs.V4S(), value);
Aart Bikf8f5a162017-02-06 15:35:29 -0800609 break;
Artem Serovb31f91f2017-04-05 11:31:19 +0100610 case Primitive::kPrimLong:
611 DCHECK_EQ(2u, instruction->GetVectorLength());
612 __ Shl(dst.V2D(), lhs.V2D(), value);
613 break;
Aart Bikf8f5a162017-02-06 15:35:29 -0800614 default:
615 LOG(FATAL) << "Unsupported SIMD type";
616 UNREACHABLE();
617 }
618}
619
620void LocationsBuilderARM64::VisitVecShr(HVecShr* instruction) {
621 CreateVecShiftLocations(GetGraph()->GetArena(), instruction);
622}
623
624void InstructionCodeGeneratorARM64::VisitVecShr(HVecShr* instruction) {
625 LocationSummary* locations = instruction->GetLocations();
Artem Serovb31f91f2017-04-05 11:31:19 +0100626 VRegister lhs = VRegisterFrom(locations->InAt(0));
627 VRegister dst = VRegisterFrom(locations->Out());
Aart Bikf8f5a162017-02-06 15:35:29 -0800628 int32_t value = locations->InAt(1).GetConstant()->AsIntConstant()->GetValue();
629 switch (instruction->GetPackedType()) {
630 case Primitive::kPrimByte:
Artem Serovd4bccf12017-04-03 18:47:32 +0100631 DCHECK_EQ(16u, instruction->GetVectorLength());
632 __ Sshr(dst.V16B(), lhs.V16B(), value);
Aart Bikf8f5a162017-02-06 15:35:29 -0800633 break;
634 case Primitive::kPrimChar:
635 case Primitive::kPrimShort:
Artem Serovd4bccf12017-04-03 18:47:32 +0100636 DCHECK_EQ(8u, instruction->GetVectorLength());
637 __ Sshr(dst.V8H(), lhs.V8H(), value);
Aart Bikf8f5a162017-02-06 15:35:29 -0800638 break;
639 case Primitive::kPrimInt:
Artem Serovd4bccf12017-04-03 18:47:32 +0100640 DCHECK_EQ(4u, instruction->GetVectorLength());
641 __ Sshr(dst.V4S(), lhs.V4S(), value);
Aart Bikf8f5a162017-02-06 15:35:29 -0800642 break;
Artem Serovb31f91f2017-04-05 11:31:19 +0100643 case Primitive::kPrimLong:
644 DCHECK_EQ(2u, instruction->GetVectorLength());
645 __ Sshr(dst.V2D(), lhs.V2D(), value);
646 break;
Aart Bikf8f5a162017-02-06 15:35:29 -0800647 default:
648 LOG(FATAL) << "Unsupported SIMD type";
649 UNREACHABLE();
650 }
651}
652
653void LocationsBuilderARM64::VisitVecUShr(HVecUShr* instruction) {
654 CreateVecShiftLocations(GetGraph()->GetArena(), instruction);
655}
656
657void InstructionCodeGeneratorARM64::VisitVecUShr(HVecUShr* instruction) {
658 LocationSummary* locations = instruction->GetLocations();
Artem Serovb31f91f2017-04-05 11:31:19 +0100659 VRegister lhs = VRegisterFrom(locations->InAt(0));
660 VRegister dst = VRegisterFrom(locations->Out());
Aart Bikf8f5a162017-02-06 15:35:29 -0800661 int32_t value = locations->InAt(1).GetConstant()->AsIntConstant()->GetValue();
662 switch (instruction->GetPackedType()) {
663 case Primitive::kPrimByte:
Artem Serovd4bccf12017-04-03 18:47:32 +0100664 DCHECK_EQ(16u, instruction->GetVectorLength());
665 __ Ushr(dst.V16B(), lhs.V16B(), value);
Aart Bikf8f5a162017-02-06 15:35:29 -0800666 break;
667 case Primitive::kPrimChar:
668 case Primitive::kPrimShort:
Artem Serovd4bccf12017-04-03 18:47:32 +0100669 DCHECK_EQ(8u, instruction->GetVectorLength());
670 __ Ushr(dst.V8H(), lhs.V8H(), value);
Aart Bikf8f5a162017-02-06 15:35:29 -0800671 break;
672 case Primitive::kPrimInt:
Artem Serovd4bccf12017-04-03 18:47:32 +0100673 DCHECK_EQ(4u, instruction->GetVectorLength());
674 __ Ushr(dst.V4S(), lhs.V4S(), value);
Aart Bikf8f5a162017-02-06 15:35:29 -0800675 break;
Artem Serovb31f91f2017-04-05 11:31:19 +0100676 case Primitive::kPrimLong:
677 DCHECK_EQ(2u, instruction->GetVectorLength());
678 __ Ushr(dst.V2D(), lhs.V2D(), value);
679 break;
Aart Bikf8f5a162017-02-06 15:35:29 -0800680 default:
681 LOG(FATAL) << "Unsupported SIMD type";
682 UNREACHABLE();
683 }
684}
685
Artem Serovf34dd202017-04-10 17:41:46 +0100686void LocationsBuilderARM64::VisitVecMultiplyAccumulate(HVecMultiplyAccumulate* instr) {
687 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instr);
688 switch (instr->GetPackedType()) {
689 case Primitive::kPrimByte:
690 case Primitive::kPrimChar:
691 case Primitive::kPrimShort:
692 case Primitive::kPrimInt:
693 locations->SetInAt(
694 HVecMultiplyAccumulate::kInputAccumulatorIndex, Location::RequiresFpuRegister());
695 locations->SetInAt(
696 HVecMultiplyAccumulate::kInputMulLeftIndex, Location::RequiresFpuRegister());
697 locations->SetInAt(
698 HVecMultiplyAccumulate::kInputMulRightIndex, Location::RequiresFpuRegister());
699 DCHECK_EQ(HVecMultiplyAccumulate::kInputAccumulatorIndex, 0);
700 locations->SetOut(Location::SameAsFirstInput());
701 break;
702 default:
703 LOG(FATAL) << "Unsupported SIMD type";
704 UNREACHABLE();
705 }
706}
707
708// Some early revisions of the Cortex-A53 have an erratum (835769) whereby it is possible for a
709// 64-bit scalar multiply-accumulate instruction in AArch64 state to generate an incorrect result.
710// However vector MultiplyAccumulate instruction is not affected.
711void InstructionCodeGeneratorARM64::VisitVecMultiplyAccumulate(HVecMultiplyAccumulate* instr) {
712 LocationSummary* locations = instr->GetLocations();
713 VRegister acc = VRegisterFrom(locations->InAt(HVecMultiplyAccumulate::kInputAccumulatorIndex));
714 VRegister left = VRegisterFrom(locations->InAt(HVecMultiplyAccumulate::kInputMulLeftIndex));
715 VRegister right = VRegisterFrom(locations->InAt(HVecMultiplyAccumulate::kInputMulRightIndex));
716 switch (instr->GetPackedType()) {
717 case Primitive::kPrimByte:
718 DCHECK_EQ(16u, instr->GetVectorLength());
719 if (instr->GetOpKind() == HInstruction::kAdd) {
720 __ Mla(acc.V16B(), left.V16B(), right.V16B());
721 } else {
722 __ Mls(acc.V16B(), left.V16B(), right.V16B());
723 }
724 break;
725 case Primitive::kPrimChar:
726 case Primitive::kPrimShort:
727 DCHECK_EQ(8u, instr->GetVectorLength());
728 if (instr->GetOpKind() == HInstruction::kAdd) {
729 __ Mla(acc.V8H(), left.V8H(), right.V8H());
730 } else {
731 __ Mls(acc.V8H(), left.V8H(), right.V8H());
732 }
733 break;
734 case Primitive::kPrimInt:
735 DCHECK_EQ(4u, instr->GetVectorLength());
736 if (instr->GetOpKind() == HInstruction::kAdd) {
737 __ Mla(acc.V4S(), left.V4S(), right.V4S());
738 } else {
739 __ Mls(acc.V4S(), left.V4S(), right.V4S());
740 }
741 break;
742 default:
743 LOG(FATAL) << "Unsupported SIMD type";
744 }
745}
746
Aart Bikf8f5a162017-02-06 15:35:29 -0800747// Helper to set up locations for vector memory operations.
748static void CreateVecMemLocations(ArenaAllocator* arena,
749 HVecMemoryOperation* instruction,
750 bool is_load) {
751 LocationSummary* locations = new (arena) LocationSummary(instruction);
752 switch (instruction->GetPackedType()) {
753 case Primitive::kPrimBoolean:
754 case Primitive::kPrimByte:
755 case Primitive::kPrimChar:
756 case Primitive::kPrimShort:
757 case Primitive::kPrimInt:
Artem Serovb31f91f2017-04-05 11:31:19 +0100758 case Primitive::kPrimLong:
Aart Bikf8f5a162017-02-06 15:35:29 -0800759 case Primitive::kPrimFloat:
Artem Serovb31f91f2017-04-05 11:31:19 +0100760 case Primitive::kPrimDouble:
Aart Bikf8f5a162017-02-06 15:35:29 -0800761 locations->SetInAt(0, Location::RequiresRegister());
762 locations->SetInAt(1, Location::RegisterOrConstant(instruction->InputAt(1)));
763 if (is_load) {
764 locations->SetOut(Location::RequiresFpuRegister());
765 } else {
766 locations->SetInAt(2, Location::RequiresFpuRegister());
767 }
768 break;
769 default:
770 LOG(FATAL) << "Unsupported SIMD type";
771 UNREACHABLE();
772 }
773}
774
Aart Bik472821b2017-04-27 17:23:51 -0700775// Helper to set up locations for vector memory operations. Returns the memory operand and,
776// if used, sets the output parameter scratch to a temporary register used in this operand,
777// so that the client can release it right after the memory operand use.
778MemOperand InstructionCodeGeneratorARM64::VecAddress(
Aart Bikf8f5a162017-02-06 15:35:29 -0800779 HVecMemoryOperation* instruction,
Aart Bik472821b2017-04-27 17:23:51 -0700780 UseScratchRegisterScope* temps_scope,
781 size_t size,
782 bool is_string_char_at,
783 /*out*/ Register* scratch) {
Aart Bikf8f5a162017-02-06 15:35:29 -0800784 LocationSummary* locations = instruction->GetLocations();
785 Register base = InputRegisterAt(instruction, 0);
Artem Serove1811ed2017-04-27 16:50:47 +0100786
787 if (instruction->InputAt(1)->IsIntermediateAddressIndex()) {
788 DCHECK(!is_string_char_at);
789 return MemOperand(base.X(), InputRegisterAt(instruction, 1).X());
790 }
791
Aart Bikf8f5a162017-02-06 15:35:29 -0800792 Location index = locations->InAt(1);
Aart Bik472821b2017-04-27 17:23:51 -0700793 uint32_t offset = is_string_char_at
794 ? mirror::String::ValueOffset().Uint32Value()
795 : mirror::Array::DataOffset(size).Uint32Value();
796 size_t shift = ComponentSizeShiftWidth(size);
Aart Bikf8f5a162017-02-06 15:35:29 -0800797
Artem Serov0225b772017-04-19 15:43:53 +0100798 // HIntermediateAddress optimization is only applied for scalar ArrayGet and ArraySet.
799 DCHECK(!instruction->InputAt(0)->IsIntermediateAddress());
800
Aart Bikf8f5a162017-02-06 15:35:29 -0800801 if (index.IsConstant()) {
802 offset += Int64ConstantFrom(index) << shift;
Artem Serov0225b772017-04-19 15:43:53 +0100803 return HeapOperand(base, offset);
Aart Bikf8f5a162017-02-06 15:35:29 -0800804 } else {
Aart Bik472821b2017-04-27 17:23:51 -0700805 *scratch = temps_scope->AcquireSameSizeAs(base);
806 __ Add(*scratch, base, Operand(WRegisterFrom(index), LSL, shift));
807 return HeapOperand(*scratch, offset);
Aart Bikf8f5a162017-02-06 15:35:29 -0800808 }
Aart Bikf8f5a162017-02-06 15:35:29 -0800809}
810
811void LocationsBuilderARM64::VisitVecLoad(HVecLoad* instruction) {
812 CreateVecMemLocations(GetGraph()->GetArena(), instruction, /*is_load*/ true);
813}
814
815void InstructionCodeGeneratorARM64::VisitVecLoad(HVecLoad* instruction) {
Aart Bik472821b2017-04-27 17:23:51 -0700816 LocationSummary* locations = instruction->GetLocations();
817 size_t size = Primitive::ComponentSize(instruction->GetPackedType());
818 VRegister reg = VRegisterFrom(locations->Out());
Artem Serov0225b772017-04-19 15:43:53 +0100819 UseScratchRegisterScope temps(GetVIXLAssembler());
Aart Bik472821b2017-04-27 17:23:51 -0700820 Register scratch;
Artem Serov0225b772017-04-19 15:43:53 +0100821
Aart Bikf8f5a162017-02-06 15:35:29 -0800822 switch (instruction->GetPackedType()) {
Aart Bik472821b2017-04-27 17:23:51 -0700823 case Primitive::kPrimChar:
824 DCHECK_EQ(8u, instruction->GetVectorLength());
825 // Special handling of compressed/uncompressed string load.
826 if (mirror::kUseStringCompression && instruction->IsStringCharAt()) {
827 vixl::aarch64::Label uncompressed_load, done;
828 // Test compression bit.
829 static_assert(static_cast<uint32_t>(mirror::StringCompressionFlag::kCompressed) == 0u,
830 "Expecting 0=compressed, 1=uncompressed");
831 uint32_t count_offset = mirror::String::CountOffset().Uint32Value();
832 Register length = temps.AcquireW();
833 __ Ldr(length, HeapOperand(InputRegisterAt(instruction, 0), count_offset));
834 __ Tbnz(length.W(), 0, &uncompressed_load);
835 temps.Release(length); // no longer needed
836 // Zero extend 8 compressed bytes into 8 chars.
837 __ Ldr(DRegisterFrom(locations->Out()).V8B(),
838 VecAddress(instruction, &temps, 1, /*is_string_char_at*/ true, &scratch));
839 __ Uxtl(reg.V8H(), reg.V8B());
840 __ B(&done);
841 if (scratch.IsValid()) {
842 temps.Release(scratch); // if used, no longer needed
843 }
844 // Load 8 direct uncompressed chars.
845 __ Bind(&uncompressed_load);
846 __ Ldr(reg, VecAddress(instruction, &temps, size, /*is_string_char_at*/ true, &scratch));
847 __ Bind(&done);
848 return;
849 }
850 FALLTHROUGH_INTENDED;
Aart Bikf8f5a162017-02-06 15:35:29 -0800851 case Primitive::kPrimBoolean:
852 case Primitive::kPrimByte:
Aart Bikf8f5a162017-02-06 15:35:29 -0800853 case Primitive::kPrimShort:
Aart Bikf8f5a162017-02-06 15:35:29 -0800854 case Primitive::kPrimInt:
855 case Primitive::kPrimFloat:
Artem Serovb31f91f2017-04-05 11:31:19 +0100856 case Primitive::kPrimLong:
857 case Primitive::kPrimDouble:
Artem Serov0225b772017-04-19 15:43:53 +0100858 DCHECK_LE(2u, instruction->GetVectorLength());
859 DCHECK_LE(instruction->GetVectorLength(), 16u);
Aart Bik472821b2017-04-27 17:23:51 -0700860 __ Ldr(reg, VecAddress(instruction, &temps, size, instruction->IsStringCharAt(), &scratch));
Artem Serovb31f91f2017-04-05 11:31:19 +0100861 break;
Aart Bikf8f5a162017-02-06 15:35:29 -0800862 default:
863 LOG(FATAL) << "Unsupported SIMD type";
864 UNREACHABLE();
865 }
866}
867
868void LocationsBuilderARM64::VisitVecStore(HVecStore* instruction) {
869 CreateVecMemLocations(GetGraph()->GetArena(), instruction, /*is_load*/ false);
870}
871
872void InstructionCodeGeneratorARM64::VisitVecStore(HVecStore* instruction) {
Aart Bik472821b2017-04-27 17:23:51 -0700873 LocationSummary* locations = instruction->GetLocations();
874 size_t size = Primitive::ComponentSize(instruction->GetPackedType());
875 VRegister reg = VRegisterFrom(locations->InAt(2));
Artem Serov0225b772017-04-19 15:43:53 +0100876 UseScratchRegisterScope temps(GetVIXLAssembler());
Aart Bik472821b2017-04-27 17:23:51 -0700877 Register scratch;
Artem Serov0225b772017-04-19 15:43:53 +0100878
Aart Bikf8f5a162017-02-06 15:35:29 -0800879 switch (instruction->GetPackedType()) {
880 case Primitive::kPrimBoolean:
881 case Primitive::kPrimByte:
Aart Bikf8f5a162017-02-06 15:35:29 -0800882 case Primitive::kPrimChar:
883 case Primitive::kPrimShort:
Aart Bikf8f5a162017-02-06 15:35:29 -0800884 case Primitive::kPrimInt:
885 case Primitive::kPrimFloat:
Artem Serovb31f91f2017-04-05 11:31:19 +0100886 case Primitive::kPrimLong:
887 case Primitive::kPrimDouble:
Artem Serov0225b772017-04-19 15:43:53 +0100888 DCHECK_LE(2u, instruction->GetVectorLength());
889 DCHECK_LE(instruction->GetVectorLength(), 16u);
Aart Bik472821b2017-04-27 17:23:51 -0700890 __ Str(reg, VecAddress(instruction, &temps, size, /*is_string_char_at*/ false, &scratch));
Artem Serovb31f91f2017-04-05 11:31:19 +0100891 break;
Aart Bikf8f5a162017-02-06 15:35:29 -0800892 default:
893 LOG(FATAL) << "Unsupported SIMD type";
894 UNREACHABLE();
895 }
896}
897
898#undef __
899
900} // namespace arm64
901} // namespace art