blob: a41adca02cd2d2c8258831cc5fc6bba2ad341c88 [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) {
Aart Bikc8e93c72017-05-10 10:49:22 -0700471 LocationSummary* locations = instruction->GetLocations();
472 VRegister lhs = VRegisterFrom(locations->InAt(0));
473 VRegister rhs = VRegisterFrom(locations->InAt(1));
474 VRegister dst = VRegisterFrom(locations->Out());
475 switch (instruction->GetPackedType()) {
476 case Primitive::kPrimByte:
477 DCHECK_EQ(16u, instruction->GetVectorLength());
478 if (instruction->IsUnsigned()) {
479 __ Umin(dst.V16B(), lhs.V16B(), rhs.V16B());
480 } else {
481 __ Smin(dst.V16B(), lhs.V16B(), rhs.V16B());
482 }
483 break;
484 case Primitive::kPrimChar:
485 case Primitive::kPrimShort:
486 DCHECK_EQ(8u, instruction->GetVectorLength());
487 if (instruction->IsUnsigned()) {
488 __ Umin(dst.V8H(), lhs.V8H(), rhs.V8H());
489 } else {
490 __ Smin(dst.V8H(), lhs.V8H(), rhs.V8H());
491 }
492 break;
493 case Primitive::kPrimInt:
494 DCHECK_EQ(4u, instruction->GetVectorLength());
495 if (instruction->IsUnsigned()) {
496 __ Umin(dst.V4S(), lhs.V4S(), rhs.V4S());
497 } else {
498 __ Smin(dst.V4S(), lhs.V4S(), rhs.V4S());
499 }
500 break;
501 case Primitive::kPrimFloat:
502 DCHECK_EQ(4u, instruction->GetVectorLength());
503 DCHECK(!instruction->IsUnsigned());
504 __ Fmin(dst.V4S(), lhs.V4S(), rhs.V4S());
505 break;
506 case Primitive::kPrimDouble:
507 DCHECK_EQ(2u, instruction->GetVectorLength());
508 DCHECK(!instruction->IsUnsigned());
509 __ Fmin(dst.V2D(), lhs.V2D(), rhs.V2D());
510 break;
511 default:
512 LOG(FATAL) << "Unsupported SIMD type";
513 UNREACHABLE();
514 }
Aart Bikf3e61ee2017-04-12 17:09:20 -0700515}
516
517void LocationsBuilderARM64::VisitVecMax(HVecMax* instruction) {
518 CreateVecBinOpLocations(GetGraph()->GetArena(), instruction);
519}
520
521void InstructionCodeGeneratorARM64::VisitVecMax(HVecMax* instruction) {
Aart Bikc8e93c72017-05-10 10:49:22 -0700522 LocationSummary* locations = instruction->GetLocations();
523 VRegister lhs = VRegisterFrom(locations->InAt(0));
524 VRegister rhs = VRegisterFrom(locations->InAt(1));
525 VRegister dst = VRegisterFrom(locations->Out());
526 switch (instruction->GetPackedType()) {
527 case Primitive::kPrimByte:
528 DCHECK_EQ(16u, instruction->GetVectorLength());
529 if (instruction->IsUnsigned()) {
530 __ Umax(dst.V16B(), lhs.V16B(), rhs.V16B());
531 } else {
532 __ Smax(dst.V16B(), lhs.V16B(), rhs.V16B());
533 }
534 break;
535 case Primitive::kPrimChar:
536 case Primitive::kPrimShort:
537 DCHECK_EQ(8u, instruction->GetVectorLength());
538 if (instruction->IsUnsigned()) {
539 __ Umax(dst.V8H(), lhs.V8H(), rhs.V8H());
540 } else {
541 __ Smax(dst.V8H(), lhs.V8H(), rhs.V8H());
542 }
543 break;
544 case Primitive::kPrimInt:
545 DCHECK_EQ(4u, instruction->GetVectorLength());
546 if (instruction->IsUnsigned()) {
547 __ Umax(dst.V4S(), lhs.V4S(), rhs.V4S());
548 } else {
549 __ Smax(dst.V4S(), lhs.V4S(), rhs.V4S());
550 }
551 break;
552 case Primitive::kPrimFloat:
553 DCHECK_EQ(4u, instruction->GetVectorLength());
554 DCHECK(!instruction->IsUnsigned());
555 __ Fmax(dst.V4S(), lhs.V4S(), rhs.V4S());
556 break;
557 case Primitive::kPrimDouble:
558 DCHECK_EQ(2u, instruction->GetVectorLength());
559 DCHECK(!instruction->IsUnsigned());
560 __ Fmax(dst.V2D(), lhs.V2D(), rhs.V2D());
561 break;
562 default:
563 LOG(FATAL) << "Unsupported SIMD type";
564 UNREACHABLE();
565 }
Aart Bikf3e61ee2017-04-12 17:09:20 -0700566}
567
Aart Bikf8f5a162017-02-06 15:35:29 -0800568void LocationsBuilderARM64::VisitVecAnd(HVecAnd* instruction) {
569 CreateVecBinOpLocations(GetGraph()->GetArena(), instruction);
570}
571
572void InstructionCodeGeneratorARM64::VisitVecAnd(HVecAnd* instruction) {
573 LocationSummary* locations = instruction->GetLocations();
Artem Serovb31f91f2017-04-05 11:31:19 +0100574 VRegister lhs = VRegisterFrom(locations->InAt(0));
575 VRegister rhs = VRegisterFrom(locations->InAt(1));
576 VRegister dst = VRegisterFrom(locations->Out());
Aart Bikf8f5a162017-02-06 15:35:29 -0800577 switch (instruction->GetPackedType()) {
578 case Primitive::kPrimBoolean:
579 case Primitive::kPrimByte:
580 case Primitive::kPrimChar:
581 case Primitive::kPrimShort:
582 case Primitive::kPrimInt:
Artem Serovb31f91f2017-04-05 11:31:19 +0100583 case Primitive::kPrimLong:
Aart Bikf8f5a162017-02-06 15:35:29 -0800584 case Primitive::kPrimFloat:
Artem Serovb31f91f2017-04-05 11:31:19 +0100585 case Primitive::kPrimDouble:
Artem Serovd4bccf12017-04-03 18:47:32 +0100586 __ And(dst.V16B(), lhs.V16B(), rhs.V16B()); // lanes do not matter
Aart Bikf8f5a162017-02-06 15:35:29 -0800587 break;
588 default:
589 LOG(FATAL) << "Unsupported SIMD type";
590 UNREACHABLE();
591 }
592}
593
594void LocationsBuilderARM64::VisitVecAndNot(HVecAndNot* instruction) {
595 LOG(FATAL) << "Unsupported SIMD instruction " << instruction->GetId();
596}
597
598void InstructionCodeGeneratorARM64::VisitVecAndNot(HVecAndNot* instruction) {
599 LOG(FATAL) << "Unsupported SIMD instruction " << instruction->GetId();
600}
601
602void LocationsBuilderARM64::VisitVecOr(HVecOr* instruction) {
603 CreateVecBinOpLocations(GetGraph()->GetArena(), instruction);
604}
605
606void InstructionCodeGeneratorARM64::VisitVecOr(HVecOr* instruction) {
607 LocationSummary* locations = instruction->GetLocations();
Artem Serovb31f91f2017-04-05 11:31:19 +0100608 VRegister lhs = VRegisterFrom(locations->InAt(0));
609 VRegister rhs = VRegisterFrom(locations->InAt(1));
610 VRegister dst = VRegisterFrom(locations->Out());
Aart Bikf8f5a162017-02-06 15:35:29 -0800611 switch (instruction->GetPackedType()) {
612 case Primitive::kPrimBoolean:
613 case Primitive::kPrimByte:
614 case Primitive::kPrimChar:
615 case Primitive::kPrimShort:
616 case Primitive::kPrimInt:
Artem Serovb31f91f2017-04-05 11:31:19 +0100617 case Primitive::kPrimLong:
Aart Bikf8f5a162017-02-06 15:35:29 -0800618 case Primitive::kPrimFloat:
Artem Serovb31f91f2017-04-05 11:31:19 +0100619 case Primitive::kPrimDouble:
Artem Serovd4bccf12017-04-03 18:47:32 +0100620 __ Orr(dst.V16B(), lhs.V16B(), rhs.V16B()); // lanes do not matter
Aart Bikf8f5a162017-02-06 15:35:29 -0800621 break;
622 default:
623 LOG(FATAL) << "Unsupported SIMD type";
624 UNREACHABLE();
625 }
626}
627
628void LocationsBuilderARM64::VisitVecXor(HVecXor* instruction) {
629 CreateVecBinOpLocations(GetGraph()->GetArena(), instruction);
630}
631
632void InstructionCodeGeneratorARM64::VisitVecXor(HVecXor* instruction) {
633 LocationSummary* locations = instruction->GetLocations();
Artem Serovb31f91f2017-04-05 11:31:19 +0100634 VRegister lhs = VRegisterFrom(locations->InAt(0));
635 VRegister rhs = VRegisterFrom(locations->InAt(1));
636 VRegister dst = VRegisterFrom(locations->Out());
Aart Bikf8f5a162017-02-06 15:35:29 -0800637 switch (instruction->GetPackedType()) {
638 case Primitive::kPrimBoolean:
639 case Primitive::kPrimByte:
640 case Primitive::kPrimChar:
641 case Primitive::kPrimShort:
642 case Primitive::kPrimInt:
Artem Serovb31f91f2017-04-05 11:31:19 +0100643 case Primitive::kPrimLong:
Aart Bikf8f5a162017-02-06 15:35:29 -0800644 case Primitive::kPrimFloat:
Artem Serovb31f91f2017-04-05 11:31:19 +0100645 case Primitive::kPrimDouble:
Artem Serovd4bccf12017-04-03 18:47:32 +0100646 __ Eor(dst.V16B(), lhs.V16B(), rhs.V16B()); // lanes do not matter
Aart Bikf8f5a162017-02-06 15:35:29 -0800647 break;
648 default:
649 LOG(FATAL) << "Unsupported SIMD type";
650 UNREACHABLE();
651 }
652}
653
654// Helper to set up locations for vector shift operations.
655static void CreateVecShiftLocations(ArenaAllocator* arena, HVecBinaryOperation* instruction) {
656 LocationSummary* locations = new (arena) LocationSummary(instruction);
657 switch (instruction->GetPackedType()) {
658 case Primitive::kPrimByte:
659 case Primitive::kPrimChar:
660 case Primitive::kPrimShort:
661 case Primitive::kPrimInt:
Artem Serovb31f91f2017-04-05 11:31:19 +0100662 case Primitive::kPrimLong:
Aart Bikf8f5a162017-02-06 15:35:29 -0800663 locations->SetInAt(0, Location::RequiresFpuRegister());
664 locations->SetInAt(1, Location::ConstantLocation(instruction->InputAt(1)->AsConstant()));
665 locations->SetOut(Location::RequiresFpuRegister(), Location::kNoOutputOverlap);
666 break;
667 default:
668 LOG(FATAL) << "Unsupported SIMD type";
669 UNREACHABLE();
670 }
671}
672
673void LocationsBuilderARM64::VisitVecShl(HVecShl* instruction) {
674 CreateVecShiftLocations(GetGraph()->GetArena(), instruction);
675}
676
677void InstructionCodeGeneratorARM64::VisitVecShl(HVecShl* instruction) {
678 LocationSummary* locations = instruction->GetLocations();
Artem Serovb31f91f2017-04-05 11:31:19 +0100679 VRegister lhs = VRegisterFrom(locations->InAt(0));
680 VRegister dst = VRegisterFrom(locations->Out());
Aart Bikf8f5a162017-02-06 15:35:29 -0800681 int32_t value = locations->InAt(1).GetConstant()->AsIntConstant()->GetValue();
682 switch (instruction->GetPackedType()) {
683 case Primitive::kPrimByte:
Artem Serovd4bccf12017-04-03 18:47:32 +0100684 DCHECK_EQ(16u, instruction->GetVectorLength());
685 __ Shl(dst.V16B(), lhs.V16B(), value);
Aart Bikf8f5a162017-02-06 15:35:29 -0800686 break;
687 case Primitive::kPrimChar:
688 case Primitive::kPrimShort:
Artem Serovd4bccf12017-04-03 18:47:32 +0100689 DCHECK_EQ(8u, instruction->GetVectorLength());
690 __ Shl(dst.V8H(), lhs.V8H(), value);
Aart Bikf8f5a162017-02-06 15:35:29 -0800691 break;
692 case Primitive::kPrimInt:
Artem Serovd4bccf12017-04-03 18:47:32 +0100693 DCHECK_EQ(4u, instruction->GetVectorLength());
694 __ Shl(dst.V4S(), lhs.V4S(), value);
Aart Bikf8f5a162017-02-06 15:35:29 -0800695 break;
Artem Serovb31f91f2017-04-05 11:31:19 +0100696 case Primitive::kPrimLong:
697 DCHECK_EQ(2u, instruction->GetVectorLength());
698 __ Shl(dst.V2D(), lhs.V2D(), value);
699 break;
Aart Bikf8f5a162017-02-06 15:35:29 -0800700 default:
701 LOG(FATAL) << "Unsupported SIMD type";
702 UNREACHABLE();
703 }
704}
705
706void LocationsBuilderARM64::VisitVecShr(HVecShr* instruction) {
707 CreateVecShiftLocations(GetGraph()->GetArena(), instruction);
708}
709
710void InstructionCodeGeneratorARM64::VisitVecShr(HVecShr* instruction) {
711 LocationSummary* locations = instruction->GetLocations();
Artem Serovb31f91f2017-04-05 11:31:19 +0100712 VRegister lhs = VRegisterFrom(locations->InAt(0));
713 VRegister dst = VRegisterFrom(locations->Out());
Aart Bikf8f5a162017-02-06 15:35:29 -0800714 int32_t value = locations->InAt(1).GetConstant()->AsIntConstant()->GetValue();
715 switch (instruction->GetPackedType()) {
716 case Primitive::kPrimByte:
Artem Serovd4bccf12017-04-03 18:47:32 +0100717 DCHECK_EQ(16u, instruction->GetVectorLength());
718 __ Sshr(dst.V16B(), lhs.V16B(), value);
Aart Bikf8f5a162017-02-06 15:35:29 -0800719 break;
720 case Primitive::kPrimChar:
721 case Primitive::kPrimShort:
Artem Serovd4bccf12017-04-03 18:47:32 +0100722 DCHECK_EQ(8u, instruction->GetVectorLength());
723 __ Sshr(dst.V8H(), lhs.V8H(), value);
Aart Bikf8f5a162017-02-06 15:35:29 -0800724 break;
725 case Primitive::kPrimInt:
Artem Serovd4bccf12017-04-03 18:47:32 +0100726 DCHECK_EQ(4u, instruction->GetVectorLength());
727 __ Sshr(dst.V4S(), lhs.V4S(), value);
Aart Bikf8f5a162017-02-06 15:35:29 -0800728 break;
Artem Serovb31f91f2017-04-05 11:31:19 +0100729 case Primitive::kPrimLong:
730 DCHECK_EQ(2u, instruction->GetVectorLength());
731 __ Sshr(dst.V2D(), lhs.V2D(), value);
732 break;
Aart Bikf8f5a162017-02-06 15:35:29 -0800733 default:
734 LOG(FATAL) << "Unsupported SIMD type";
735 UNREACHABLE();
736 }
737}
738
739void LocationsBuilderARM64::VisitVecUShr(HVecUShr* instruction) {
740 CreateVecShiftLocations(GetGraph()->GetArena(), instruction);
741}
742
743void InstructionCodeGeneratorARM64::VisitVecUShr(HVecUShr* instruction) {
744 LocationSummary* locations = instruction->GetLocations();
Artem Serovb31f91f2017-04-05 11:31:19 +0100745 VRegister lhs = VRegisterFrom(locations->InAt(0));
746 VRegister dst = VRegisterFrom(locations->Out());
Aart Bikf8f5a162017-02-06 15:35:29 -0800747 int32_t value = locations->InAt(1).GetConstant()->AsIntConstant()->GetValue();
748 switch (instruction->GetPackedType()) {
749 case Primitive::kPrimByte:
Artem Serovd4bccf12017-04-03 18:47:32 +0100750 DCHECK_EQ(16u, instruction->GetVectorLength());
751 __ Ushr(dst.V16B(), lhs.V16B(), value);
Aart Bikf8f5a162017-02-06 15:35:29 -0800752 break;
753 case Primitive::kPrimChar:
754 case Primitive::kPrimShort:
Artem Serovd4bccf12017-04-03 18:47:32 +0100755 DCHECK_EQ(8u, instruction->GetVectorLength());
756 __ Ushr(dst.V8H(), lhs.V8H(), value);
Aart Bikf8f5a162017-02-06 15:35:29 -0800757 break;
758 case Primitive::kPrimInt:
Artem Serovd4bccf12017-04-03 18:47:32 +0100759 DCHECK_EQ(4u, instruction->GetVectorLength());
760 __ Ushr(dst.V4S(), lhs.V4S(), value);
Aart Bikf8f5a162017-02-06 15:35:29 -0800761 break;
Artem Serovb31f91f2017-04-05 11:31:19 +0100762 case Primitive::kPrimLong:
763 DCHECK_EQ(2u, instruction->GetVectorLength());
764 __ Ushr(dst.V2D(), lhs.V2D(), value);
765 break;
Aart Bikf8f5a162017-02-06 15:35:29 -0800766 default:
767 LOG(FATAL) << "Unsupported SIMD type";
768 UNREACHABLE();
769 }
770}
771
Artem Serovf34dd202017-04-10 17:41:46 +0100772void LocationsBuilderARM64::VisitVecMultiplyAccumulate(HVecMultiplyAccumulate* instr) {
773 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instr);
774 switch (instr->GetPackedType()) {
775 case Primitive::kPrimByte:
776 case Primitive::kPrimChar:
777 case Primitive::kPrimShort:
778 case Primitive::kPrimInt:
779 locations->SetInAt(
780 HVecMultiplyAccumulate::kInputAccumulatorIndex, Location::RequiresFpuRegister());
781 locations->SetInAt(
782 HVecMultiplyAccumulate::kInputMulLeftIndex, Location::RequiresFpuRegister());
783 locations->SetInAt(
784 HVecMultiplyAccumulate::kInputMulRightIndex, Location::RequiresFpuRegister());
785 DCHECK_EQ(HVecMultiplyAccumulate::kInputAccumulatorIndex, 0);
786 locations->SetOut(Location::SameAsFirstInput());
787 break;
788 default:
789 LOG(FATAL) << "Unsupported SIMD type";
790 UNREACHABLE();
791 }
792}
793
794// Some early revisions of the Cortex-A53 have an erratum (835769) whereby it is possible for a
795// 64-bit scalar multiply-accumulate instruction in AArch64 state to generate an incorrect result.
796// However vector MultiplyAccumulate instruction is not affected.
797void InstructionCodeGeneratorARM64::VisitVecMultiplyAccumulate(HVecMultiplyAccumulate* instr) {
798 LocationSummary* locations = instr->GetLocations();
799 VRegister acc = VRegisterFrom(locations->InAt(HVecMultiplyAccumulate::kInputAccumulatorIndex));
800 VRegister left = VRegisterFrom(locations->InAt(HVecMultiplyAccumulate::kInputMulLeftIndex));
801 VRegister right = VRegisterFrom(locations->InAt(HVecMultiplyAccumulate::kInputMulRightIndex));
802 switch (instr->GetPackedType()) {
803 case Primitive::kPrimByte:
804 DCHECK_EQ(16u, instr->GetVectorLength());
805 if (instr->GetOpKind() == HInstruction::kAdd) {
806 __ Mla(acc.V16B(), left.V16B(), right.V16B());
807 } else {
808 __ Mls(acc.V16B(), left.V16B(), right.V16B());
809 }
810 break;
811 case Primitive::kPrimChar:
812 case Primitive::kPrimShort:
813 DCHECK_EQ(8u, instr->GetVectorLength());
814 if (instr->GetOpKind() == HInstruction::kAdd) {
815 __ Mla(acc.V8H(), left.V8H(), right.V8H());
816 } else {
817 __ Mls(acc.V8H(), left.V8H(), right.V8H());
818 }
819 break;
820 case Primitive::kPrimInt:
821 DCHECK_EQ(4u, instr->GetVectorLength());
822 if (instr->GetOpKind() == HInstruction::kAdd) {
823 __ Mla(acc.V4S(), left.V4S(), right.V4S());
824 } else {
825 __ Mls(acc.V4S(), left.V4S(), right.V4S());
826 }
827 break;
828 default:
829 LOG(FATAL) << "Unsupported SIMD type";
830 }
831}
832
Aart Bikf8f5a162017-02-06 15:35:29 -0800833// Helper to set up locations for vector memory operations.
834static void CreateVecMemLocations(ArenaAllocator* arena,
835 HVecMemoryOperation* instruction,
836 bool is_load) {
837 LocationSummary* locations = new (arena) LocationSummary(instruction);
838 switch (instruction->GetPackedType()) {
839 case Primitive::kPrimBoolean:
840 case Primitive::kPrimByte:
841 case Primitive::kPrimChar:
842 case Primitive::kPrimShort:
843 case Primitive::kPrimInt:
Artem Serovb31f91f2017-04-05 11:31:19 +0100844 case Primitive::kPrimLong:
Aart Bikf8f5a162017-02-06 15:35:29 -0800845 case Primitive::kPrimFloat:
Artem Serovb31f91f2017-04-05 11:31:19 +0100846 case Primitive::kPrimDouble:
Aart Bikf8f5a162017-02-06 15:35:29 -0800847 locations->SetInAt(0, Location::RequiresRegister());
848 locations->SetInAt(1, Location::RegisterOrConstant(instruction->InputAt(1)));
849 if (is_load) {
850 locations->SetOut(Location::RequiresFpuRegister());
851 } else {
852 locations->SetInAt(2, Location::RequiresFpuRegister());
853 }
854 break;
855 default:
856 LOG(FATAL) << "Unsupported SIMD type";
857 UNREACHABLE();
858 }
859}
860
Aart Bik472821b2017-04-27 17:23:51 -0700861// Helper to set up locations for vector memory operations. Returns the memory operand and,
862// if used, sets the output parameter scratch to a temporary register used in this operand,
863// so that the client can release it right after the memory operand use.
864MemOperand InstructionCodeGeneratorARM64::VecAddress(
Aart Bikf8f5a162017-02-06 15:35:29 -0800865 HVecMemoryOperation* instruction,
Aart Bik472821b2017-04-27 17:23:51 -0700866 UseScratchRegisterScope* temps_scope,
867 size_t size,
868 bool is_string_char_at,
869 /*out*/ Register* scratch) {
Aart Bikf8f5a162017-02-06 15:35:29 -0800870 LocationSummary* locations = instruction->GetLocations();
871 Register base = InputRegisterAt(instruction, 0);
Artem Serove1811ed2017-04-27 16:50:47 +0100872
873 if (instruction->InputAt(1)->IsIntermediateAddressIndex()) {
874 DCHECK(!is_string_char_at);
875 return MemOperand(base.X(), InputRegisterAt(instruction, 1).X());
876 }
877
Aart Bikf8f5a162017-02-06 15:35:29 -0800878 Location index = locations->InAt(1);
Aart Bik472821b2017-04-27 17:23:51 -0700879 uint32_t offset = is_string_char_at
880 ? mirror::String::ValueOffset().Uint32Value()
881 : mirror::Array::DataOffset(size).Uint32Value();
882 size_t shift = ComponentSizeShiftWidth(size);
Aart Bikf8f5a162017-02-06 15:35:29 -0800883
Artem Serov0225b772017-04-19 15:43:53 +0100884 // HIntermediateAddress optimization is only applied for scalar ArrayGet and ArraySet.
885 DCHECK(!instruction->InputAt(0)->IsIntermediateAddress());
886
Aart Bikf8f5a162017-02-06 15:35:29 -0800887 if (index.IsConstant()) {
888 offset += Int64ConstantFrom(index) << shift;
Artem Serov0225b772017-04-19 15:43:53 +0100889 return HeapOperand(base, offset);
Aart Bikf8f5a162017-02-06 15:35:29 -0800890 } else {
Aart Bik472821b2017-04-27 17:23:51 -0700891 *scratch = temps_scope->AcquireSameSizeAs(base);
892 __ Add(*scratch, base, Operand(WRegisterFrom(index), LSL, shift));
893 return HeapOperand(*scratch, offset);
Aart Bikf8f5a162017-02-06 15:35:29 -0800894 }
Aart Bikf8f5a162017-02-06 15:35:29 -0800895}
896
897void LocationsBuilderARM64::VisitVecLoad(HVecLoad* instruction) {
898 CreateVecMemLocations(GetGraph()->GetArena(), instruction, /*is_load*/ true);
899}
900
901void InstructionCodeGeneratorARM64::VisitVecLoad(HVecLoad* instruction) {
Aart Bik472821b2017-04-27 17:23:51 -0700902 LocationSummary* locations = instruction->GetLocations();
903 size_t size = Primitive::ComponentSize(instruction->GetPackedType());
904 VRegister reg = VRegisterFrom(locations->Out());
Artem Serov0225b772017-04-19 15:43:53 +0100905 UseScratchRegisterScope temps(GetVIXLAssembler());
Aart Bik472821b2017-04-27 17:23:51 -0700906 Register scratch;
Artem Serov0225b772017-04-19 15:43:53 +0100907
Aart Bikf8f5a162017-02-06 15:35:29 -0800908 switch (instruction->GetPackedType()) {
Aart Bik472821b2017-04-27 17:23:51 -0700909 case Primitive::kPrimChar:
910 DCHECK_EQ(8u, instruction->GetVectorLength());
911 // Special handling of compressed/uncompressed string load.
912 if (mirror::kUseStringCompression && instruction->IsStringCharAt()) {
913 vixl::aarch64::Label uncompressed_load, done;
914 // Test compression bit.
915 static_assert(static_cast<uint32_t>(mirror::StringCompressionFlag::kCompressed) == 0u,
916 "Expecting 0=compressed, 1=uncompressed");
917 uint32_t count_offset = mirror::String::CountOffset().Uint32Value();
918 Register length = temps.AcquireW();
919 __ Ldr(length, HeapOperand(InputRegisterAt(instruction, 0), count_offset));
920 __ Tbnz(length.W(), 0, &uncompressed_load);
921 temps.Release(length); // no longer needed
922 // Zero extend 8 compressed bytes into 8 chars.
923 __ Ldr(DRegisterFrom(locations->Out()).V8B(),
924 VecAddress(instruction, &temps, 1, /*is_string_char_at*/ true, &scratch));
925 __ Uxtl(reg.V8H(), reg.V8B());
926 __ B(&done);
927 if (scratch.IsValid()) {
928 temps.Release(scratch); // if used, no longer needed
929 }
930 // Load 8 direct uncompressed chars.
931 __ Bind(&uncompressed_load);
932 __ Ldr(reg, VecAddress(instruction, &temps, size, /*is_string_char_at*/ true, &scratch));
933 __ Bind(&done);
934 return;
935 }
936 FALLTHROUGH_INTENDED;
Aart Bikf8f5a162017-02-06 15:35:29 -0800937 case Primitive::kPrimBoolean:
938 case Primitive::kPrimByte:
Aart Bikf8f5a162017-02-06 15:35:29 -0800939 case Primitive::kPrimShort:
Aart Bikf8f5a162017-02-06 15:35:29 -0800940 case Primitive::kPrimInt:
941 case Primitive::kPrimFloat:
Artem Serovb31f91f2017-04-05 11:31:19 +0100942 case Primitive::kPrimLong:
943 case Primitive::kPrimDouble:
Artem Serov0225b772017-04-19 15:43:53 +0100944 DCHECK_LE(2u, instruction->GetVectorLength());
945 DCHECK_LE(instruction->GetVectorLength(), 16u);
Aart Bik472821b2017-04-27 17:23:51 -0700946 __ Ldr(reg, VecAddress(instruction, &temps, size, instruction->IsStringCharAt(), &scratch));
Artem Serovb31f91f2017-04-05 11:31:19 +0100947 break;
Aart Bikf8f5a162017-02-06 15:35:29 -0800948 default:
949 LOG(FATAL) << "Unsupported SIMD type";
950 UNREACHABLE();
951 }
952}
953
954void LocationsBuilderARM64::VisitVecStore(HVecStore* instruction) {
955 CreateVecMemLocations(GetGraph()->GetArena(), instruction, /*is_load*/ false);
956}
957
958void InstructionCodeGeneratorARM64::VisitVecStore(HVecStore* instruction) {
Aart Bik472821b2017-04-27 17:23:51 -0700959 LocationSummary* locations = instruction->GetLocations();
960 size_t size = Primitive::ComponentSize(instruction->GetPackedType());
961 VRegister reg = VRegisterFrom(locations->InAt(2));
Artem Serov0225b772017-04-19 15:43:53 +0100962 UseScratchRegisterScope temps(GetVIXLAssembler());
Aart Bik472821b2017-04-27 17:23:51 -0700963 Register scratch;
Artem Serov0225b772017-04-19 15:43:53 +0100964
Aart Bikf8f5a162017-02-06 15:35:29 -0800965 switch (instruction->GetPackedType()) {
966 case Primitive::kPrimBoolean:
967 case Primitive::kPrimByte:
Aart Bikf8f5a162017-02-06 15:35:29 -0800968 case Primitive::kPrimChar:
969 case Primitive::kPrimShort:
Aart Bikf8f5a162017-02-06 15:35:29 -0800970 case Primitive::kPrimInt:
971 case Primitive::kPrimFloat:
Artem Serovb31f91f2017-04-05 11:31:19 +0100972 case Primitive::kPrimLong:
973 case Primitive::kPrimDouble:
Artem Serov0225b772017-04-19 15:43:53 +0100974 DCHECK_LE(2u, instruction->GetVectorLength());
975 DCHECK_LE(instruction->GetVectorLength(), 16u);
Aart Bik472821b2017-04-27 17:23:51 -0700976 __ Str(reg, VecAddress(instruction, &temps, size, /*is_string_char_at*/ false, &scratch));
Artem Serovb31f91f2017-04-05 11:31:19 +0100977 break;
Aart Bikf8f5a162017-02-06 15:35:29 -0800978 default:
979 LOG(FATAL) << "Unsupported SIMD type";
980 UNREACHABLE();
981 }
982}
983
984#undef __
985
986} // namespace arm64
987} // namespace art