blob: f422b9fc8b84de2cd99fb749822b2e59ccbf7973 [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 Serov8dfe7462017-06-01 14:28:48 +010025using helpers::ARM64EncodableConstantOrRegister;
26using helpers::Arm64CanEncodeConstantAsImmediate;
Aart Bik472821b2017-04-27 17:23:51 -070027using helpers::DRegisterFrom;
Artem Serovb31f91f2017-04-05 11:31:19 +010028using helpers::VRegisterFrom;
Aart Bikf8f5a162017-02-06 15:35:29 -080029using helpers::HeapOperand;
30using helpers::InputRegisterAt;
31using helpers::Int64ConstantFrom;
32using helpers::XRegisterFrom;
Artem Serov0225b772017-04-19 15:43:53 +010033using helpers::WRegisterFrom;
Aart Bikf8f5a162017-02-06 15:35:29 -080034
35#define __ GetVIXLAssembler()->
36
37void LocationsBuilderARM64::VisitVecReplicateScalar(HVecReplicateScalar* instruction) {
38 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction);
Artem Serov8dfe7462017-06-01 14:28:48 +010039 HInstruction* input = instruction->InputAt(0);
Aart Bikf8f5a162017-02-06 15:35:29 -080040 switch (instruction->GetPackedType()) {
41 case Primitive::kPrimBoolean:
42 case Primitive::kPrimByte:
43 case Primitive::kPrimChar:
44 case Primitive::kPrimShort:
45 case Primitive::kPrimInt:
Artem Serovb31f91f2017-04-05 11:31:19 +010046 case Primitive::kPrimLong:
Artem Serov8dfe7462017-06-01 14:28:48 +010047 locations->SetInAt(0, ARM64EncodableConstantOrRegister(input, instruction));
Aart Bikf8f5a162017-02-06 15:35:29 -080048 locations->SetOut(Location::RequiresFpuRegister());
49 break;
50 case Primitive::kPrimFloat:
Artem Serovb31f91f2017-04-05 11:31:19 +010051 case Primitive::kPrimDouble:
Artem Serov8dfe7462017-06-01 14:28:48 +010052 if (input->IsConstant() &&
53 Arm64CanEncodeConstantAsImmediate(input->AsConstant(), instruction)) {
54 locations->SetInAt(0, Location::ConstantLocation(input->AsConstant()));
55 locations->SetOut(Location::RequiresFpuRegister());
56 } else {
57 locations->SetInAt(0, Location::RequiresFpuRegister());
58 locations->SetOut(Location::RequiresFpuRegister(), Location::kNoOutputOverlap);
59 }
Aart Bikf8f5a162017-02-06 15:35:29 -080060 break;
61 default:
62 LOG(FATAL) << "Unsupported SIMD type";
63 UNREACHABLE();
64 }
65}
66
67void InstructionCodeGeneratorARM64::VisitVecReplicateScalar(HVecReplicateScalar* instruction) {
68 LocationSummary* locations = instruction->GetLocations();
Artem Serov8dfe7462017-06-01 14:28:48 +010069 Location src_loc = locations->InAt(0);
Artem Serovb31f91f2017-04-05 11:31:19 +010070 VRegister dst = VRegisterFrom(locations->Out());
Aart Bikf8f5a162017-02-06 15:35:29 -080071 switch (instruction->GetPackedType()) {
72 case Primitive::kPrimBoolean:
73 case Primitive::kPrimByte:
Artem Serovd4bccf12017-04-03 18:47:32 +010074 DCHECK_EQ(16u, instruction->GetVectorLength());
Artem Serov8dfe7462017-06-01 14:28:48 +010075 if (src_loc.IsConstant()) {
76 __ Movi(dst.V16B(), Int64ConstantFrom(src_loc));
77 } else {
78 __ Dup(dst.V16B(), InputRegisterAt(instruction, 0));
79 }
Aart Bikf8f5a162017-02-06 15:35:29 -080080 break;
81 case Primitive::kPrimChar:
82 case Primitive::kPrimShort:
Artem Serovd4bccf12017-04-03 18:47:32 +010083 DCHECK_EQ(8u, instruction->GetVectorLength());
Artem Serov8dfe7462017-06-01 14:28:48 +010084 if (src_loc.IsConstant()) {
85 __ Movi(dst.V8H(), Int64ConstantFrom(src_loc));
86 } else {
87 __ Dup(dst.V8H(), InputRegisterAt(instruction, 0));
88 }
Aart Bikf8f5a162017-02-06 15:35:29 -080089 break;
90 case Primitive::kPrimInt:
Artem Serovd4bccf12017-04-03 18:47:32 +010091 DCHECK_EQ(4u, instruction->GetVectorLength());
Artem Serov8dfe7462017-06-01 14:28:48 +010092 if (src_loc.IsConstant()) {
93 __ Movi(dst.V4S(), Int64ConstantFrom(src_loc));
94 } else {
95 __ Dup(dst.V4S(), InputRegisterAt(instruction, 0));
96 }
Aart Bikf8f5a162017-02-06 15:35:29 -080097 break;
Artem Serovb31f91f2017-04-05 11:31:19 +010098 case Primitive::kPrimLong:
99 DCHECK_EQ(2u, instruction->GetVectorLength());
Artem Serov8dfe7462017-06-01 14:28:48 +0100100 if (src_loc.IsConstant()) {
101 __ Movi(dst.V2D(), Int64ConstantFrom(src_loc));
102 } else {
103 __ Dup(dst.V2D(), XRegisterFrom(src_loc));
104 }
Artem Serovb31f91f2017-04-05 11:31:19 +0100105 break;
Aart Bikf8f5a162017-02-06 15:35:29 -0800106 case Primitive::kPrimFloat:
Artem Serovd4bccf12017-04-03 18:47:32 +0100107 DCHECK_EQ(4u, instruction->GetVectorLength());
Artem Serov8dfe7462017-06-01 14:28:48 +0100108 if (src_loc.IsConstant()) {
109 __ Fmov(dst.V4S(), src_loc.GetConstant()->AsFloatConstant()->GetValue());
110 } else {
111 __ Dup(dst.V4S(), VRegisterFrom(src_loc).V4S(), 0);
112 }
Artem Serovb31f91f2017-04-05 11:31:19 +0100113 break;
114 case Primitive::kPrimDouble:
115 DCHECK_EQ(2u, instruction->GetVectorLength());
Artem Serov8dfe7462017-06-01 14:28:48 +0100116 if (src_loc.IsConstant()) {
117 __ Fmov(dst.V2D(), src_loc.GetConstant()->AsDoubleConstant()->GetValue());
118 } else {
119 __ Dup(dst.V2D(), VRegisterFrom(src_loc).V2D(), 0);
120 }
Aart Bikf8f5a162017-02-06 15:35:29 -0800121 break;
122 default:
123 LOG(FATAL) << "Unsupported SIMD type";
124 UNREACHABLE();
125 }
126}
127
128void LocationsBuilderARM64::VisitVecSetScalars(HVecSetScalars* instruction) {
129 LOG(FATAL) << "No SIMD for " << instruction->GetId();
130}
131
132void InstructionCodeGeneratorARM64::VisitVecSetScalars(HVecSetScalars* instruction) {
133 LOG(FATAL) << "No SIMD for " << instruction->GetId();
134}
135
136void LocationsBuilderARM64::VisitVecSumReduce(HVecSumReduce* instruction) {
137 LOG(FATAL) << "No SIMD for " << instruction->GetId();
138}
139
140void InstructionCodeGeneratorARM64::VisitVecSumReduce(HVecSumReduce* instruction) {
141 LOG(FATAL) << "No SIMD for " << instruction->GetId();
142}
143
144// Helper to set up locations for vector unary operations.
145static void CreateVecUnOpLocations(ArenaAllocator* arena, HVecUnaryOperation* instruction) {
146 LocationSummary* locations = new (arena) LocationSummary(instruction);
147 switch (instruction->GetPackedType()) {
148 case Primitive::kPrimBoolean:
149 locations->SetInAt(0, Location::RequiresFpuRegister());
150 locations->SetOut(Location::RequiresFpuRegister(),
151 instruction->IsVecNot() ? Location::kOutputOverlap
152 : Location::kNoOutputOverlap);
153 break;
154 case Primitive::kPrimByte:
155 case Primitive::kPrimChar:
156 case Primitive::kPrimShort:
157 case Primitive::kPrimInt:
Artem Serovb31f91f2017-04-05 11:31:19 +0100158 case Primitive::kPrimLong:
Aart Bikf8f5a162017-02-06 15:35:29 -0800159 case Primitive::kPrimFloat:
Artem Serovb31f91f2017-04-05 11:31:19 +0100160 case Primitive::kPrimDouble:
Aart Bikf8f5a162017-02-06 15:35:29 -0800161 locations->SetInAt(0, Location::RequiresFpuRegister());
162 locations->SetOut(Location::RequiresFpuRegister(), Location::kNoOutputOverlap);
163 break;
164 default:
165 LOG(FATAL) << "Unsupported SIMD type";
166 UNREACHABLE();
167 }
168}
169
170void LocationsBuilderARM64::VisitVecCnv(HVecCnv* instruction) {
171 CreateVecUnOpLocations(GetGraph()->GetArena(), instruction);
172}
173
174void InstructionCodeGeneratorARM64::VisitVecCnv(HVecCnv* instruction) {
175 LocationSummary* locations = instruction->GetLocations();
Artem Serovb31f91f2017-04-05 11:31:19 +0100176 VRegister src = VRegisterFrom(locations->InAt(0));
177 VRegister dst = VRegisterFrom(locations->Out());
Aart Bikf8f5a162017-02-06 15:35:29 -0800178 Primitive::Type from = instruction->GetInputType();
179 Primitive::Type to = instruction->GetResultType();
180 if (from == Primitive::kPrimInt && to == Primitive::kPrimFloat) {
Artem Serovd4bccf12017-04-03 18:47:32 +0100181 DCHECK_EQ(4u, instruction->GetVectorLength());
182 __ Scvtf(dst.V4S(), src.V4S());
Aart Bikf8f5a162017-02-06 15:35:29 -0800183 } else {
184 LOG(FATAL) << "Unsupported SIMD type";
185 }
186}
187
188void LocationsBuilderARM64::VisitVecNeg(HVecNeg* instruction) {
189 CreateVecUnOpLocations(GetGraph()->GetArena(), instruction);
190}
191
192void InstructionCodeGeneratorARM64::VisitVecNeg(HVecNeg* instruction) {
193 LocationSummary* locations = instruction->GetLocations();
Artem Serovb31f91f2017-04-05 11:31:19 +0100194 VRegister src = VRegisterFrom(locations->InAt(0));
195 VRegister dst = VRegisterFrom(locations->Out());
Aart Bikf8f5a162017-02-06 15:35:29 -0800196 switch (instruction->GetPackedType()) {
197 case Primitive::kPrimByte:
Artem Serovd4bccf12017-04-03 18:47:32 +0100198 DCHECK_EQ(16u, instruction->GetVectorLength());
199 __ Neg(dst.V16B(), src.V16B());
Aart Bikf8f5a162017-02-06 15:35:29 -0800200 break;
201 case Primitive::kPrimChar:
202 case Primitive::kPrimShort:
Artem Serovd4bccf12017-04-03 18:47:32 +0100203 DCHECK_EQ(8u, instruction->GetVectorLength());
204 __ Neg(dst.V8H(), src.V8H());
Aart Bikf8f5a162017-02-06 15:35:29 -0800205 break;
206 case Primitive::kPrimInt:
Artem Serovd4bccf12017-04-03 18:47:32 +0100207 DCHECK_EQ(4u, instruction->GetVectorLength());
208 __ Neg(dst.V4S(), src.V4S());
Aart Bikf8f5a162017-02-06 15:35:29 -0800209 break;
Artem Serovb31f91f2017-04-05 11:31:19 +0100210 case Primitive::kPrimLong:
211 DCHECK_EQ(2u, instruction->GetVectorLength());
212 __ Neg(dst.V2D(), src.V2D());
213 break;
Aart Bikf8f5a162017-02-06 15:35:29 -0800214 case Primitive::kPrimFloat:
Artem Serovd4bccf12017-04-03 18:47:32 +0100215 DCHECK_EQ(4u, instruction->GetVectorLength());
216 __ Fneg(dst.V4S(), src.V4S());
Aart Bikf8f5a162017-02-06 15:35:29 -0800217 break;
Artem Serovb31f91f2017-04-05 11:31:19 +0100218 case Primitive::kPrimDouble:
219 DCHECK_EQ(2u, instruction->GetVectorLength());
220 __ Fneg(dst.V2D(), src.V2D());
221 break;
Aart Bikf8f5a162017-02-06 15:35:29 -0800222 default:
223 LOG(FATAL) << "Unsupported SIMD type";
224 UNREACHABLE();
225 }
226}
227
Aart Bik6daebeb2017-04-03 14:35:41 -0700228void LocationsBuilderARM64::VisitVecAbs(HVecAbs* instruction) {
229 CreateVecUnOpLocations(GetGraph()->GetArena(), instruction);
230}
231
232void InstructionCodeGeneratorARM64::VisitVecAbs(HVecAbs* instruction) {
233 LocationSummary* locations = instruction->GetLocations();
Artem Serovb31f91f2017-04-05 11:31:19 +0100234 VRegister src = VRegisterFrom(locations->InAt(0));
235 VRegister dst = VRegisterFrom(locations->Out());
Aart Bik6daebeb2017-04-03 14:35:41 -0700236 switch (instruction->GetPackedType()) {
237 case Primitive::kPrimByte:
Artem Serovd4bccf12017-04-03 18:47:32 +0100238 DCHECK_EQ(16u, instruction->GetVectorLength());
239 __ Abs(dst.V16B(), src.V16B());
Aart Bik6daebeb2017-04-03 14:35:41 -0700240 break;
241 case Primitive::kPrimChar:
242 case Primitive::kPrimShort:
Artem Serovd4bccf12017-04-03 18:47:32 +0100243 DCHECK_EQ(8u, instruction->GetVectorLength());
244 __ Abs(dst.V8H(), src.V8H());
Aart Bik6daebeb2017-04-03 14:35:41 -0700245 break;
246 case Primitive::kPrimInt:
Artem Serovd4bccf12017-04-03 18:47:32 +0100247 DCHECK_EQ(4u, instruction->GetVectorLength());
248 __ Abs(dst.V4S(), src.V4S());
Aart Bik6daebeb2017-04-03 14:35:41 -0700249 break;
Artem Serovb31f91f2017-04-05 11:31:19 +0100250 case Primitive::kPrimLong:
251 DCHECK_EQ(2u, instruction->GetVectorLength());
252 __ Abs(dst.V2D(), src.V2D());
253 break;
Aart Bik6daebeb2017-04-03 14:35:41 -0700254 case Primitive::kPrimFloat:
Artem Serovd4bccf12017-04-03 18:47:32 +0100255 DCHECK_EQ(4u, instruction->GetVectorLength());
256 __ Fabs(dst.V4S(), src.V4S());
Aart Bik6daebeb2017-04-03 14:35:41 -0700257 break;
Artem Serovb31f91f2017-04-05 11:31:19 +0100258 case Primitive::kPrimDouble:
259 DCHECK_EQ(2u, instruction->GetVectorLength());
260 __ Fabs(dst.V2D(), src.V2D());
261 break;
Aart Bik6daebeb2017-04-03 14:35:41 -0700262 default:
263 LOG(FATAL) << "Unsupported SIMD type";
264 }
265}
266
Aart Bikf8f5a162017-02-06 15:35:29 -0800267void LocationsBuilderARM64::VisitVecNot(HVecNot* instruction) {
268 CreateVecUnOpLocations(GetGraph()->GetArena(), instruction);
269}
270
271void InstructionCodeGeneratorARM64::VisitVecNot(HVecNot* instruction) {
272 LocationSummary* locations = instruction->GetLocations();
Artem Serovb31f91f2017-04-05 11:31:19 +0100273 VRegister src = VRegisterFrom(locations->InAt(0));
274 VRegister dst = VRegisterFrom(locations->Out());
Aart Bikf8f5a162017-02-06 15:35:29 -0800275 switch (instruction->GetPackedType()) {
276 case Primitive::kPrimBoolean: // special case boolean-not
Artem Serovd4bccf12017-04-03 18:47:32 +0100277 DCHECK_EQ(16u, instruction->GetVectorLength());
278 __ Movi(dst.V16B(), 1);
279 __ Eor(dst.V16B(), dst.V16B(), src.V16B());
Aart Bikf8f5a162017-02-06 15:35:29 -0800280 break;
281 case Primitive::kPrimByte:
282 case Primitive::kPrimChar:
283 case Primitive::kPrimShort:
284 case Primitive::kPrimInt:
Artem Serovb31f91f2017-04-05 11:31:19 +0100285 case Primitive::kPrimLong:
Artem Serovd4bccf12017-04-03 18:47:32 +0100286 __ Not(dst.V16B(), src.V16B()); // lanes do not matter
Aart Bikf8f5a162017-02-06 15:35:29 -0800287 break;
288 default:
289 LOG(FATAL) << "Unsupported SIMD type";
290 UNREACHABLE();
291 }
292}
293
294// Helper to set up locations for vector binary operations.
295static void CreateVecBinOpLocations(ArenaAllocator* arena, HVecBinaryOperation* instruction) {
296 LocationSummary* locations = new (arena) LocationSummary(instruction);
297 switch (instruction->GetPackedType()) {
298 case Primitive::kPrimBoolean:
299 case Primitive::kPrimByte:
300 case Primitive::kPrimChar:
301 case Primitive::kPrimShort:
302 case Primitive::kPrimInt:
Artem Serovb31f91f2017-04-05 11:31:19 +0100303 case Primitive::kPrimLong:
Aart Bikf8f5a162017-02-06 15:35:29 -0800304 case Primitive::kPrimFloat:
Artem Serovb31f91f2017-04-05 11:31:19 +0100305 case Primitive::kPrimDouble:
Aart Bikf8f5a162017-02-06 15:35:29 -0800306 locations->SetInAt(0, Location::RequiresFpuRegister());
307 locations->SetInAt(1, Location::RequiresFpuRegister());
308 locations->SetOut(Location::RequiresFpuRegister(), Location::kNoOutputOverlap);
309 break;
310 default:
311 LOG(FATAL) << "Unsupported SIMD type";
312 UNREACHABLE();
313 }
314}
315
316void LocationsBuilderARM64::VisitVecAdd(HVecAdd* instruction) {
317 CreateVecBinOpLocations(GetGraph()->GetArena(), instruction);
318}
319
320void InstructionCodeGeneratorARM64::VisitVecAdd(HVecAdd* instruction) {
321 LocationSummary* locations = instruction->GetLocations();
Artem Serovb31f91f2017-04-05 11:31:19 +0100322 VRegister lhs = VRegisterFrom(locations->InAt(0));
323 VRegister rhs = VRegisterFrom(locations->InAt(1));
324 VRegister dst = VRegisterFrom(locations->Out());
Aart Bikf8f5a162017-02-06 15:35:29 -0800325 switch (instruction->GetPackedType()) {
326 case Primitive::kPrimByte:
Artem Serovd4bccf12017-04-03 18:47:32 +0100327 DCHECK_EQ(16u, instruction->GetVectorLength());
328 __ Add(dst.V16B(), lhs.V16B(), rhs.V16B());
Aart Bikf8f5a162017-02-06 15:35:29 -0800329 break;
330 case Primitive::kPrimChar:
331 case Primitive::kPrimShort:
Artem Serovd4bccf12017-04-03 18:47:32 +0100332 DCHECK_EQ(8u, instruction->GetVectorLength());
333 __ Add(dst.V8H(), lhs.V8H(), rhs.V8H());
Aart Bikf8f5a162017-02-06 15:35:29 -0800334 break;
335 case Primitive::kPrimInt:
Artem Serovd4bccf12017-04-03 18:47:32 +0100336 DCHECK_EQ(4u, instruction->GetVectorLength());
337 __ Add(dst.V4S(), lhs.V4S(), rhs.V4S());
Aart Bikf8f5a162017-02-06 15:35:29 -0800338 break;
Artem Serovb31f91f2017-04-05 11:31:19 +0100339 case Primitive::kPrimLong:
340 DCHECK_EQ(2u, instruction->GetVectorLength());
341 __ Add(dst.V2D(), lhs.V2D(), rhs.V2D());
342 break;
Aart Bikf8f5a162017-02-06 15:35:29 -0800343 case Primitive::kPrimFloat:
Artem Serovd4bccf12017-04-03 18:47:32 +0100344 DCHECK_EQ(4u, instruction->GetVectorLength());
345 __ Fadd(dst.V4S(), lhs.V4S(), rhs.V4S());
Aart Bikf8f5a162017-02-06 15:35:29 -0800346 break;
Artem Serovb31f91f2017-04-05 11:31:19 +0100347 case Primitive::kPrimDouble:
348 DCHECK_EQ(2u, instruction->GetVectorLength());
349 __ Fadd(dst.V2D(), lhs.V2D(), rhs.V2D());
350 break;
Aart Bikf8f5a162017-02-06 15:35:29 -0800351 default:
352 LOG(FATAL) << "Unsupported SIMD type";
353 UNREACHABLE();
354 }
355}
356
Aart Bikf3e61ee2017-04-12 17:09:20 -0700357void LocationsBuilderARM64::VisitVecHalvingAdd(HVecHalvingAdd* instruction) {
358 CreateVecBinOpLocations(GetGraph()->GetArena(), instruction);
359}
360
361void InstructionCodeGeneratorARM64::VisitVecHalvingAdd(HVecHalvingAdd* instruction) {
362 LocationSummary* locations = instruction->GetLocations();
363 VRegister lhs = VRegisterFrom(locations->InAt(0));
364 VRegister rhs = VRegisterFrom(locations->InAt(1));
365 VRegister dst = VRegisterFrom(locations->Out());
366 switch (instruction->GetPackedType()) {
367 case Primitive::kPrimByte:
368 DCHECK_EQ(16u, instruction->GetVectorLength());
369 if (instruction->IsUnsigned()) {
370 instruction->IsRounded()
371 ? __ Urhadd(dst.V16B(), lhs.V16B(), rhs.V16B())
372 : __ Uhadd(dst.V16B(), lhs.V16B(), rhs.V16B());
373 } else {
374 instruction->IsRounded()
375 ? __ Srhadd(dst.V16B(), lhs.V16B(), rhs.V16B())
376 : __ Shadd(dst.V16B(), lhs.V16B(), rhs.V16B());
377 }
378 break;
379 case Primitive::kPrimChar:
380 case Primitive::kPrimShort:
381 DCHECK_EQ(8u, instruction->GetVectorLength());
382 if (instruction->IsUnsigned()) {
383 instruction->IsRounded()
384 ? __ Urhadd(dst.V8H(), lhs.V8H(), rhs.V8H())
385 : __ Uhadd(dst.V8H(), lhs.V8H(), rhs.V8H());
386 } else {
387 instruction->IsRounded()
388 ? __ Srhadd(dst.V8H(), lhs.V8H(), rhs.V8H())
389 : __ Shadd(dst.V8H(), lhs.V8H(), rhs.V8H());
390 }
391 break;
392 default:
393 LOG(FATAL) << "Unsupported SIMD type";
394 UNREACHABLE();
395 }
396}
397
Aart Bikf8f5a162017-02-06 15:35:29 -0800398void LocationsBuilderARM64::VisitVecSub(HVecSub* instruction) {
399 CreateVecBinOpLocations(GetGraph()->GetArena(), instruction);
400}
401
402void InstructionCodeGeneratorARM64::VisitVecSub(HVecSub* instruction) {
403 LocationSummary* locations = instruction->GetLocations();
Artem Serovb31f91f2017-04-05 11:31:19 +0100404 VRegister lhs = VRegisterFrom(locations->InAt(0));
405 VRegister rhs = VRegisterFrom(locations->InAt(1));
406 VRegister dst = VRegisterFrom(locations->Out());
Aart Bikf8f5a162017-02-06 15:35:29 -0800407 switch (instruction->GetPackedType()) {
408 case Primitive::kPrimByte:
Artem Serovd4bccf12017-04-03 18:47:32 +0100409 DCHECK_EQ(16u, instruction->GetVectorLength());
410 __ Sub(dst.V16B(), lhs.V16B(), rhs.V16B());
Aart Bikf8f5a162017-02-06 15:35:29 -0800411 break;
412 case Primitive::kPrimChar:
413 case Primitive::kPrimShort:
Artem Serovd4bccf12017-04-03 18:47:32 +0100414 DCHECK_EQ(8u, instruction->GetVectorLength());
415 __ Sub(dst.V8H(), lhs.V8H(), rhs.V8H());
Aart Bikf8f5a162017-02-06 15:35:29 -0800416 break;
417 case Primitive::kPrimInt:
Artem Serovd4bccf12017-04-03 18:47:32 +0100418 DCHECK_EQ(4u, instruction->GetVectorLength());
419 __ Sub(dst.V4S(), lhs.V4S(), rhs.V4S());
Aart Bikf8f5a162017-02-06 15:35:29 -0800420 break;
Artem Serovb31f91f2017-04-05 11:31:19 +0100421 case Primitive::kPrimLong:
422 DCHECK_EQ(2u, instruction->GetVectorLength());
423 __ Sub(dst.V2D(), lhs.V2D(), rhs.V2D());
424 break;
Aart Bikf8f5a162017-02-06 15:35:29 -0800425 case Primitive::kPrimFloat:
Artem Serovd4bccf12017-04-03 18:47:32 +0100426 DCHECK_EQ(4u, instruction->GetVectorLength());
427 __ Fsub(dst.V4S(), lhs.V4S(), rhs.V4S());
Aart Bikf8f5a162017-02-06 15:35:29 -0800428 break;
Artem Serovb31f91f2017-04-05 11:31:19 +0100429 case Primitive::kPrimDouble:
430 DCHECK_EQ(2u, instruction->GetVectorLength());
431 __ Fsub(dst.V2D(), lhs.V2D(), rhs.V2D());
432 break;
Aart Bikf8f5a162017-02-06 15:35:29 -0800433 default:
434 LOG(FATAL) << "Unsupported SIMD type";
435 UNREACHABLE();
436 }
437}
438
439void LocationsBuilderARM64::VisitVecMul(HVecMul* instruction) {
440 CreateVecBinOpLocations(GetGraph()->GetArena(), instruction);
441}
442
443void InstructionCodeGeneratorARM64::VisitVecMul(HVecMul* instruction) {
444 LocationSummary* locations = instruction->GetLocations();
Artem Serovb31f91f2017-04-05 11:31:19 +0100445 VRegister lhs = VRegisterFrom(locations->InAt(0));
446 VRegister rhs = VRegisterFrom(locations->InAt(1));
447 VRegister dst = VRegisterFrom(locations->Out());
Aart Bikf8f5a162017-02-06 15:35:29 -0800448 switch (instruction->GetPackedType()) {
449 case Primitive::kPrimByte:
Artem Serovd4bccf12017-04-03 18:47:32 +0100450 DCHECK_EQ(16u, instruction->GetVectorLength());
451 __ Mul(dst.V16B(), lhs.V16B(), rhs.V16B());
Aart Bikf8f5a162017-02-06 15:35:29 -0800452 break;
453 case Primitive::kPrimChar:
454 case Primitive::kPrimShort:
Artem Serovd4bccf12017-04-03 18:47:32 +0100455 DCHECK_EQ(8u, instruction->GetVectorLength());
456 __ Mul(dst.V8H(), lhs.V8H(), rhs.V8H());
Aart Bikf8f5a162017-02-06 15:35:29 -0800457 break;
458 case Primitive::kPrimInt:
Artem Serovd4bccf12017-04-03 18:47:32 +0100459 DCHECK_EQ(4u, instruction->GetVectorLength());
460 __ Mul(dst.V4S(), lhs.V4S(), rhs.V4S());
Aart Bikf8f5a162017-02-06 15:35:29 -0800461 break;
462 case Primitive::kPrimFloat:
Artem Serovd4bccf12017-04-03 18:47:32 +0100463 DCHECK_EQ(4u, instruction->GetVectorLength());
464 __ Fmul(dst.V4S(), lhs.V4S(), rhs.V4S());
Aart Bikf8f5a162017-02-06 15:35:29 -0800465 break;
Artem Serovb31f91f2017-04-05 11:31:19 +0100466 case Primitive::kPrimDouble:
467 DCHECK_EQ(2u, instruction->GetVectorLength());
468 __ Fmul(dst.V2D(), lhs.V2D(), rhs.V2D());
469 break;
Aart Bikf8f5a162017-02-06 15:35:29 -0800470 default:
471 LOG(FATAL) << "Unsupported SIMD type";
472 UNREACHABLE();
473 }
474}
475
476void LocationsBuilderARM64::VisitVecDiv(HVecDiv* instruction) {
477 CreateVecBinOpLocations(GetGraph()->GetArena(), instruction);
478}
479
480void InstructionCodeGeneratorARM64::VisitVecDiv(HVecDiv* instruction) {
481 LocationSummary* locations = instruction->GetLocations();
Artem Serovb31f91f2017-04-05 11:31:19 +0100482 VRegister lhs = VRegisterFrom(locations->InAt(0));
483 VRegister rhs = VRegisterFrom(locations->InAt(1));
484 VRegister dst = VRegisterFrom(locations->Out());
Aart Bikf8f5a162017-02-06 15:35:29 -0800485 switch (instruction->GetPackedType()) {
486 case Primitive::kPrimFloat:
Artem Serovd4bccf12017-04-03 18:47:32 +0100487 DCHECK_EQ(4u, instruction->GetVectorLength());
488 __ Fdiv(dst.V4S(), lhs.V4S(), rhs.V4S());
Aart Bikf8f5a162017-02-06 15:35:29 -0800489 break;
Artem Serovb31f91f2017-04-05 11:31:19 +0100490 case Primitive::kPrimDouble:
491 DCHECK_EQ(2u, instruction->GetVectorLength());
492 __ Fdiv(dst.V2D(), lhs.V2D(), rhs.V2D());
493 break;
Aart Bikf8f5a162017-02-06 15:35:29 -0800494 default:
495 LOG(FATAL) << "Unsupported SIMD type";
496 UNREACHABLE();
497 }
498}
499
Aart Bikf3e61ee2017-04-12 17:09:20 -0700500void LocationsBuilderARM64::VisitVecMin(HVecMin* instruction) {
501 CreateVecBinOpLocations(GetGraph()->GetArena(), instruction);
502}
503
504void InstructionCodeGeneratorARM64::VisitVecMin(HVecMin* instruction) {
Aart Bikc8e93c72017-05-10 10:49:22 -0700505 LocationSummary* locations = instruction->GetLocations();
506 VRegister lhs = VRegisterFrom(locations->InAt(0));
507 VRegister rhs = VRegisterFrom(locations->InAt(1));
508 VRegister dst = VRegisterFrom(locations->Out());
509 switch (instruction->GetPackedType()) {
510 case Primitive::kPrimByte:
511 DCHECK_EQ(16u, instruction->GetVectorLength());
512 if (instruction->IsUnsigned()) {
513 __ Umin(dst.V16B(), lhs.V16B(), rhs.V16B());
514 } else {
515 __ Smin(dst.V16B(), lhs.V16B(), rhs.V16B());
516 }
517 break;
518 case Primitive::kPrimChar:
519 case Primitive::kPrimShort:
520 DCHECK_EQ(8u, instruction->GetVectorLength());
521 if (instruction->IsUnsigned()) {
522 __ Umin(dst.V8H(), lhs.V8H(), rhs.V8H());
523 } else {
524 __ Smin(dst.V8H(), lhs.V8H(), rhs.V8H());
525 }
526 break;
527 case Primitive::kPrimInt:
528 DCHECK_EQ(4u, instruction->GetVectorLength());
529 if (instruction->IsUnsigned()) {
530 __ Umin(dst.V4S(), lhs.V4S(), rhs.V4S());
531 } else {
532 __ Smin(dst.V4S(), lhs.V4S(), rhs.V4S());
533 }
534 break;
535 case Primitive::kPrimFloat:
536 DCHECK_EQ(4u, instruction->GetVectorLength());
537 DCHECK(!instruction->IsUnsigned());
538 __ Fmin(dst.V4S(), lhs.V4S(), rhs.V4S());
539 break;
540 case Primitive::kPrimDouble:
541 DCHECK_EQ(2u, instruction->GetVectorLength());
542 DCHECK(!instruction->IsUnsigned());
543 __ Fmin(dst.V2D(), lhs.V2D(), rhs.V2D());
544 break;
545 default:
546 LOG(FATAL) << "Unsupported SIMD type";
547 UNREACHABLE();
548 }
Aart Bikf3e61ee2017-04-12 17:09:20 -0700549}
550
551void LocationsBuilderARM64::VisitVecMax(HVecMax* instruction) {
552 CreateVecBinOpLocations(GetGraph()->GetArena(), instruction);
553}
554
555void InstructionCodeGeneratorARM64::VisitVecMax(HVecMax* instruction) {
Aart Bikc8e93c72017-05-10 10:49:22 -0700556 LocationSummary* locations = instruction->GetLocations();
557 VRegister lhs = VRegisterFrom(locations->InAt(0));
558 VRegister rhs = VRegisterFrom(locations->InAt(1));
559 VRegister dst = VRegisterFrom(locations->Out());
560 switch (instruction->GetPackedType()) {
561 case Primitive::kPrimByte:
562 DCHECK_EQ(16u, instruction->GetVectorLength());
563 if (instruction->IsUnsigned()) {
564 __ Umax(dst.V16B(), lhs.V16B(), rhs.V16B());
565 } else {
566 __ Smax(dst.V16B(), lhs.V16B(), rhs.V16B());
567 }
568 break;
569 case Primitive::kPrimChar:
570 case Primitive::kPrimShort:
571 DCHECK_EQ(8u, instruction->GetVectorLength());
572 if (instruction->IsUnsigned()) {
573 __ Umax(dst.V8H(), lhs.V8H(), rhs.V8H());
574 } else {
575 __ Smax(dst.V8H(), lhs.V8H(), rhs.V8H());
576 }
577 break;
578 case Primitive::kPrimInt:
579 DCHECK_EQ(4u, instruction->GetVectorLength());
580 if (instruction->IsUnsigned()) {
581 __ Umax(dst.V4S(), lhs.V4S(), rhs.V4S());
582 } else {
583 __ Smax(dst.V4S(), lhs.V4S(), rhs.V4S());
584 }
585 break;
586 case Primitive::kPrimFloat:
587 DCHECK_EQ(4u, instruction->GetVectorLength());
588 DCHECK(!instruction->IsUnsigned());
589 __ Fmax(dst.V4S(), lhs.V4S(), rhs.V4S());
590 break;
591 case Primitive::kPrimDouble:
592 DCHECK_EQ(2u, instruction->GetVectorLength());
593 DCHECK(!instruction->IsUnsigned());
594 __ Fmax(dst.V2D(), lhs.V2D(), rhs.V2D());
595 break;
596 default:
597 LOG(FATAL) << "Unsupported SIMD type";
598 UNREACHABLE();
599 }
Aart Bikf3e61ee2017-04-12 17:09:20 -0700600}
601
Aart Bikf8f5a162017-02-06 15:35:29 -0800602void LocationsBuilderARM64::VisitVecAnd(HVecAnd* instruction) {
603 CreateVecBinOpLocations(GetGraph()->GetArena(), instruction);
604}
605
606void InstructionCodeGeneratorARM64::VisitVecAnd(HVecAnd* 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 __ And(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::VisitVecAndNot(HVecAndNot* instruction) {
629 LOG(FATAL) << "Unsupported SIMD instruction " << instruction->GetId();
630}
631
632void InstructionCodeGeneratorARM64::VisitVecAndNot(HVecAndNot* instruction) {
633 LOG(FATAL) << "Unsupported SIMD instruction " << instruction->GetId();
634}
635
636void LocationsBuilderARM64::VisitVecOr(HVecOr* instruction) {
637 CreateVecBinOpLocations(GetGraph()->GetArena(), instruction);
638}
639
640void InstructionCodeGeneratorARM64::VisitVecOr(HVecOr* instruction) {
641 LocationSummary* locations = instruction->GetLocations();
Artem Serovb31f91f2017-04-05 11:31:19 +0100642 VRegister lhs = VRegisterFrom(locations->InAt(0));
643 VRegister rhs = VRegisterFrom(locations->InAt(1));
644 VRegister dst = VRegisterFrom(locations->Out());
Aart Bikf8f5a162017-02-06 15:35:29 -0800645 switch (instruction->GetPackedType()) {
646 case Primitive::kPrimBoolean:
647 case Primitive::kPrimByte:
648 case Primitive::kPrimChar:
649 case Primitive::kPrimShort:
650 case Primitive::kPrimInt:
Artem Serovb31f91f2017-04-05 11:31:19 +0100651 case Primitive::kPrimLong:
Aart Bikf8f5a162017-02-06 15:35:29 -0800652 case Primitive::kPrimFloat:
Artem Serovb31f91f2017-04-05 11:31:19 +0100653 case Primitive::kPrimDouble:
Artem Serovd4bccf12017-04-03 18:47:32 +0100654 __ Orr(dst.V16B(), lhs.V16B(), rhs.V16B()); // lanes do not matter
Aart Bikf8f5a162017-02-06 15:35:29 -0800655 break;
656 default:
657 LOG(FATAL) << "Unsupported SIMD type";
658 UNREACHABLE();
659 }
660}
661
662void LocationsBuilderARM64::VisitVecXor(HVecXor* instruction) {
663 CreateVecBinOpLocations(GetGraph()->GetArena(), instruction);
664}
665
666void InstructionCodeGeneratorARM64::VisitVecXor(HVecXor* instruction) {
667 LocationSummary* locations = instruction->GetLocations();
Artem Serovb31f91f2017-04-05 11:31:19 +0100668 VRegister lhs = VRegisterFrom(locations->InAt(0));
669 VRegister rhs = VRegisterFrom(locations->InAt(1));
670 VRegister dst = VRegisterFrom(locations->Out());
Aart Bikf8f5a162017-02-06 15:35:29 -0800671 switch (instruction->GetPackedType()) {
672 case Primitive::kPrimBoolean:
673 case Primitive::kPrimByte:
674 case Primitive::kPrimChar:
675 case Primitive::kPrimShort:
676 case Primitive::kPrimInt:
Artem Serovb31f91f2017-04-05 11:31:19 +0100677 case Primitive::kPrimLong:
Aart Bikf8f5a162017-02-06 15:35:29 -0800678 case Primitive::kPrimFloat:
Artem Serovb31f91f2017-04-05 11:31:19 +0100679 case Primitive::kPrimDouble:
Artem Serovd4bccf12017-04-03 18:47:32 +0100680 __ Eor(dst.V16B(), lhs.V16B(), rhs.V16B()); // lanes do not matter
Aart Bikf8f5a162017-02-06 15:35:29 -0800681 break;
682 default:
683 LOG(FATAL) << "Unsupported SIMD type";
684 UNREACHABLE();
685 }
686}
687
688// Helper to set up locations for vector shift operations.
689static void CreateVecShiftLocations(ArenaAllocator* arena, HVecBinaryOperation* instruction) {
690 LocationSummary* locations = new (arena) LocationSummary(instruction);
691 switch (instruction->GetPackedType()) {
692 case Primitive::kPrimByte:
693 case Primitive::kPrimChar:
694 case Primitive::kPrimShort:
695 case Primitive::kPrimInt:
Artem Serovb31f91f2017-04-05 11:31:19 +0100696 case Primitive::kPrimLong:
Aart Bikf8f5a162017-02-06 15:35:29 -0800697 locations->SetInAt(0, Location::RequiresFpuRegister());
698 locations->SetInAt(1, Location::ConstantLocation(instruction->InputAt(1)->AsConstant()));
699 locations->SetOut(Location::RequiresFpuRegister(), Location::kNoOutputOverlap);
700 break;
701 default:
702 LOG(FATAL) << "Unsupported SIMD type";
703 UNREACHABLE();
704 }
705}
706
707void LocationsBuilderARM64::VisitVecShl(HVecShl* instruction) {
708 CreateVecShiftLocations(GetGraph()->GetArena(), instruction);
709}
710
711void InstructionCodeGeneratorARM64::VisitVecShl(HVecShl* instruction) {
712 LocationSummary* locations = instruction->GetLocations();
Artem Serovb31f91f2017-04-05 11:31:19 +0100713 VRegister lhs = VRegisterFrom(locations->InAt(0));
714 VRegister dst = VRegisterFrom(locations->Out());
Aart Bikf8f5a162017-02-06 15:35:29 -0800715 int32_t value = locations->InAt(1).GetConstant()->AsIntConstant()->GetValue();
716 switch (instruction->GetPackedType()) {
717 case Primitive::kPrimByte:
Artem Serovd4bccf12017-04-03 18:47:32 +0100718 DCHECK_EQ(16u, instruction->GetVectorLength());
719 __ Shl(dst.V16B(), lhs.V16B(), value);
Aart Bikf8f5a162017-02-06 15:35:29 -0800720 break;
721 case Primitive::kPrimChar:
722 case Primitive::kPrimShort:
Artem Serovd4bccf12017-04-03 18:47:32 +0100723 DCHECK_EQ(8u, instruction->GetVectorLength());
724 __ Shl(dst.V8H(), lhs.V8H(), value);
Aart Bikf8f5a162017-02-06 15:35:29 -0800725 break;
726 case Primitive::kPrimInt:
Artem Serovd4bccf12017-04-03 18:47:32 +0100727 DCHECK_EQ(4u, instruction->GetVectorLength());
728 __ Shl(dst.V4S(), lhs.V4S(), value);
Aart Bikf8f5a162017-02-06 15:35:29 -0800729 break;
Artem Serovb31f91f2017-04-05 11:31:19 +0100730 case Primitive::kPrimLong:
731 DCHECK_EQ(2u, instruction->GetVectorLength());
732 __ Shl(dst.V2D(), lhs.V2D(), value);
733 break;
Aart Bikf8f5a162017-02-06 15:35:29 -0800734 default:
735 LOG(FATAL) << "Unsupported SIMD type";
736 UNREACHABLE();
737 }
738}
739
740void LocationsBuilderARM64::VisitVecShr(HVecShr* instruction) {
741 CreateVecShiftLocations(GetGraph()->GetArena(), instruction);
742}
743
744void InstructionCodeGeneratorARM64::VisitVecShr(HVecShr* instruction) {
745 LocationSummary* locations = instruction->GetLocations();
Artem Serovb31f91f2017-04-05 11:31:19 +0100746 VRegister lhs = VRegisterFrom(locations->InAt(0));
747 VRegister dst = VRegisterFrom(locations->Out());
Aart Bikf8f5a162017-02-06 15:35:29 -0800748 int32_t value = locations->InAt(1).GetConstant()->AsIntConstant()->GetValue();
749 switch (instruction->GetPackedType()) {
750 case Primitive::kPrimByte:
Artem Serovd4bccf12017-04-03 18:47:32 +0100751 DCHECK_EQ(16u, instruction->GetVectorLength());
752 __ Sshr(dst.V16B(), lhs.V16B(), value);
Aart Bikf8f5a162017-02-06 15:35:29 -0800753 break;
754 case Primitive::kPrimChar:
755 case Primitive::kPrimShort:
Artem Serovd4bccf12017-04-03 18:47:32 +0100756 DCHECK_EQ(8u, instruction->GetVectorLength());
757 __ Sshr(dst.V8H(), lhs.V8H(), value);
Aart Bikf8f5a162017-02-06 15:35:29 -0800758 break;
759 case Primitive::kPrimInt:
Artem Serovd4bccf12017-04-03 18:47:32 +0100760 DCHECK_EQ(4u, instruction->GetVectorLength());
761 __ Sshr(dst.V4S(), lhs.V4S(), value);
Aart Bikf8f5a162017-02-06 15:35:29 -0800762 break;
Artem Serovb31f91f2017-04-05 11:31:19 +0100763 case Primitive::kPrimLong:
764 DCHECK_EQ(2u, instruction->GetVectorLength());
765 __ Sshr(dst.V2D(), lhs.V2D(), value);
766 break;
Aart Bikf8f5a162017-02-06 15:35:29 -0800767 default:
768 LOG(FATAL) << "Unsupported SIMD type";
769 UNREACHABLE();
770 }
771}
772
773void LocationsBuilderARM64::VisitVecUShr(HVecUShr* instruction) {
774 CreateVecShiftLocations(GetGraph()->GetArena(), instruction);
775}
776
777void InstructionCodeGeneratorARM64::VisitVecUShr(HVecUShr* instruction) {
778 LocationSummary* locations = instruction->GetLocations();
Artem Serovb31f91f2017-04-05 11:31:19 +0100779 VRegister lhs = VRegisterFrom(locations->InAt(0));
780 VRegister dst = VRegisterFrom(locations->Out());
Aart Bikf8f5a162017-02-06 15:35:29 -0800781 int32_t value = locations->InAt(1).GetConstant()->AsIntConstant()->GetValue();
782 switch (instruction->GetPackedType()) {
783 case Primitive::kPrimByte:
Artem Serovd4bccf12017-04-03 18:47:32 +0100784 DCHECK_EQ(16u, instruction->GetVectorLength());
785 __ Ushr(dst.V16B(), lhs.V16B(), value);
Aart Bikf8f5a162017-02-06 15:35:29 -0800786 break;
787 case Primitive::kPrimChar:
788 case Primitive::kPrimShort:
Artem Serovd4bccf12017-04-03 18:47:32 +0100789 DCHECK_EQ(8u, instruction->GetVectorLength());
790 __ Ushr(dst.V8H(), lhs.V8H(), value);
Aart Bikf8f5a162017-02-06 15:35:29 -0800791 break;
792 case Primitive::kPrimInt:
Artem Serovd4bccf12017-04-03 18:47:32 +0100793 DCHECK_EQ(4u, instruction->GetVectorLength());
794 __ Ushr(dst.V4S(), lhs.V4S(), value);
Aart Bikf8f5a162017-02-06 15:35:29 -0800795 break;
Artem Serovb31f91f2017-04-05 11:31:19 +0100796 case Primitive::kPrimLong:
797 DCHECK_EQ(2u, instruction->GetVectorLength());
798 __ Ushr(dst.V2D(), lhs.V2D(), value);
799 break;
Aart Bikf8f5a162017-02-06 15:35:29 -0800800 default:
801 LOG(FATAL) << "Unsupported SIMD type";
802 UNREACHABLE();
803 }
804}
805
Artem Serovf34dd202017-04-10 17:41:46 +0100806void LocationsBuilderARM64::VisitVecMultiplyAccumulate(HVecMultiplyAccumulate* instr) {
807 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instr);
808 switch (instr->GetPackedType()) {
809 case Primitive::kPrimByte:
810 case Primitive::kPrimChar:
811 case Primitive::kPrimShort:
812 case Primitive::kPrimInt:
813 locations->SetInAt(
814 HVecMultiplyAccumulate::kInputAccumulatorIndex, Location::RequiresFpuRegister());
815 locations->SetInAt(
816 HVecMultiplyAccumulate::kInputMulLeftIndex, Location::RequiresFpuRegister());
817 locations->SetInAt(
818 HVecMultiplyAccumulate::kInputMulRightIndex, Location::RequiresFpuRegister());
819 DCHECK_EQ(HVecMultiplyAccumulate::kInputAccumulatorIndex, 0);
820 locations->SetOut(Location::SameAsFirstInput());
821 break;
822 default:
823 LOG(FATAL) << "Unsupported SIMD type";
824 UNREACHABLE();
825 }
826}
827
828// Some early revisions of the Cortex-A53 have an erratum (835769) whereby it is possible for a
829// 64-bit scalar multiply-accumulate instruction in AArch64 state to generate an incorrect result.
830// However vector MultiplyAccumulate instruction is not affected.
831void InstructionCodeGeneratorARM64::VisitVecMultiplyAccumulate(HVecMultiplyAccumulate* instr) {
832 LocationSummary* locations = instr->GetLocations();
833 VRegister acc = VRegisterFrom(locations->InAt(HVecMultiplyAccumulate::kInputAccumulatorIndex));
834 VRegister left = VRegisterFrom(locations->InAt(HVecMultiplyAccumulate::kInputMulLeftIndex));
835 VRegister right = VRegisterFrom(locations->InAt(HVecMultiplyAccumulate::kInputMulRightIndex));
836 switch (instr->GetPackedType()) {
837 case Primitive::kPrimByte:
838 DCHECK_EQ(16u, instr->GetVectorLength());
839 if (instr->GetOpKind() == HInstruction::kAdd) {
840 __ Mla(acc.V16B(), left.V16B(), right.V16B());
841 } else {
842 __ Mls(acc.V16B(), left.V16B(), right.V16B());
843 }
844 break;
845 case Primitive::kPrimChar:
846 case Primitive::kPrimShort:
847 DCHECK_EQ(8u, instr->GetVectorLength());
848 if (instr->GetOpKind() == HInstruction::kAdd) {
849 __ Mla(acc.V8H(), left.V8H(), right.V8H());
850 } else {
851 __ Mls(acc.V8H(), left.V8H(), right.V8H());
852 }
853 break;
854 case Primitive::kPrimInt:
855 DCHECK_EQ(4u, instr->GetVectorLength());
856 if (instr->GetOpKind() == HInstruction::kAdd) {
857 __ Mla(acc.V4S(), left.V4S(), right.V4S());
858 } else {
859 __ Mls(acc.V4S(), left.V4S(), right.V4S());
860 }
861 break;
862 default:
863 LOG(FATAL) << "Unsupported SIMD type";
864 }
865}
866
Aart Bikf8f5a162017-02-06 15:35:29 -0800867// Helper to set up locations for vector memory operations.
868static void CreateVecMemLocations(ArenaAllocator* arena,
869 HVecMemoryOperation* instruction,
870 bool is_load) {
871 LocationSummary* locations = new (arena) LocationSummary(instruction);
872 switch (instruction->GetPackedType()) {
873 case Primitive::kPrimBoolean:
874 case Primitive::kPrimByte:
875 case Primitive::kPrimChar:
876 case Primitive::kPrimShort:
877 case Primitive::kPrimInt:
Artem Serovb31f91f2017-04-05 11:31:19 +0100878 case Primitive::kPrimLong:
Aart Bikf8f5a162017-02-06 15:35:29 -0800879 case Primitive::kPrimFloat:
Artem Serovb31f91f2017-04-05 11:31:19 +0100880 case Primitive::kPrimDouble:
Aart Bikf8f5a162017-02-06 15:35:29 -0800881 locations->SetInAt(0, Location::RequiresRegister());
882 locations->SetInAt(1, Location::RegisterOrConstant(instruction->InputAt(1)));
883 if (is_load) {
884 locations->SetOut(Location::RequiresFpuRegister());
885 } else {
886 locations->SetInAt(2, Location::RequiresFpuRegister());
887 }
888 break;
889 default:
890 LOG(FATAL) << "Unsupported SIMD type";
891 UNREACHABLE();
892 }
893}
894
Aart Bik472821b2017-04-27 17:23:51 -0700895// Helper to set up locations for vector memory operations. Returns the memory operand and,
896// if used, sets the output parameter scratch to a temporary register used in this operand,
897// so that the client can release it right after the memory operand use.
898MemOperand InstructionCodeGeneratorARM64::VecAddress(
Aart Bikf8f5a162017-02-06 15:35:29 -0800899 HVecMemoryOperation* instruction,
Aart Bik472821b2017-04-27 17:23:51 -0700900 UseScratchRegisterScope* temps_scope,
901 size_t size,
902 bool is_string_char_at,
903 /*out*/ Register* scratch) {
Aart Bikf8f5a162017-02-06 15:35:29 -0800904 LocationSummary* locations = instruction->GetLocations();
905 Register base = InputRegisterAt(instruction, 0);
Artem Serove1811ed2017-04-27 16:50:47 +0100906
907 if (instruction->InputAt(1)->IsIntermediateAddressIndex()) {
908 DCHECK(!is_string_char_at);
909 return MemOperand(base.X(), InputRegisterAt(instruction, 1).X());
910 }
911
Aart Bikf8f5a162017-02-06 15:35:29 -0800912 Location index = locations->InAt(1);
Aart Bik472821b2017-04-27 17:23:51 -0700913 uint32_t offset = is_string_char_at
914 ? mirror::String::ValueOffset().Uint32Value()
915 : mirror::Array::DataOffset(size).Uint32Value();
916 size_t shift = ComponentSizeShiftWidth(size);
Aart Bikf8f5a162017-02-06 15:35:29 -0800917
Artem Serov0225b772017-04-19 15:43:53 +0100918 // HIntermediateAddress optimization is only applied for scalar ArrayGet and ArraySet.
919 DCHECK(!instruction->InputAt(0)->IsIntermediateAddress());
920
Aart Bikf8f5a162017-02-06 15:35:29 -0800921 if (index.IsConstant()) {
922 offset += Int64ConstantFrom(index) << shift;
Artem Serov0225b772017-04-19 15:43:53 +0100923 return HeapOperand(base, offset);
Aart Bikf8f5a162017-02-06 15:35:29 -0800924 } else {
Aart Bik472821b2017-04-27 17:23:51 -0700925 *scratch = temps_scope->AcquireSameSizeAs(base);
926 __ Add(*scratch, base, Operand(WRegisterFrom(index), LSL, shift));
927 return HeapOperand(*scratch, offset);
Aart Bikf8f5a162017-02-06 15:35:29 -0800928 }
Aart Bikf8f5a162017-02-06 15:35:29 -0800929}
930
931void LocationsBuilderARM64::VisitVecLoad(HVecLoad* instruction) {
932 CreateVecMemLocations(GetGraph()->GetArena(), instruction, /*is_load*/ true);
933}
934
935void InstructionCodeGeneratorARM64::VisitVecLoad(HVecLoad* instruction) {
Aart Bik472821b2017-04-27 17:23:51 -0700936 LocationSummary* locations = instruction->GetLocations();
937 size_t size = Primitive::ComponentSize(instruction->GetPackedType());
938 VRegister reg = VRegisterFrom(locations->Out());
Artem Serov0225b772017-04-19 15:43:53 +0100939 UseScratchRegisterScope temps(GetVIXLAssembler());
Aart Bik472821b2017-04-27 17:23:51 -0700940 Register scratch;
Artem Serov0225b772017-04-19 15:43:53 +0100941
Aart Bikf8f5a162017-02-06 15:35:29 -0800942 switch (instruction->GetPackedType()) {
Aart Bik472821b2017-04-27 17:23:51 -0700943 case Primitive::kPrimChar:
944 DCHECK_EQ(8u, instruction->GetVectorLength());
945 // Special handling of compressed/uncompressed string load.
946 if (mirror::kUseStringCompression && instruction->IsStringCharAt()) {
947 vixl::aarch64::Label uncompressed_load, done;
948 // Test compression bit.
949 static_assert(static_cast<uint32_t>(mirror::StringCompressionFlag::kCompressed) == 0u,
950 "Expecting 0=compressed, 1=uncompressed");
951 uint32_t count_offset = mirror::String::CountOffset().Uint32Value();
952 Register length = temps.AcquireW();
953 __ Ldr(length, HeapOperand(InputRegisterAt(instruction, 0), count_offset));
954 __ Tbnz(length.W(), 0, &uncompressed_load);
955 temps.Release(length); // no longer needed
956 // Zero extend 8 compressed bytes into 8 chars.
957 __ Ldr(DRegisterFrom(locations->Out()).V8B(),
958 VecAddress(instruction, &temps, 1, /*is_string_char_at*/ true, &scratch));
959 __ Uxtl(reg.V8H(), reg.V8B());
960 __ B(&done);
961 if (scratch.IsValid()) {
962 temps.Release(scratch); // if used, no longer needed
963 }
964 // Load 8 direct uncompressed chars.
965 __ Bind(&uncompressed_load);
966 __ Ldr(reg, VecAddress(instruction, &temps, size, /*is_string_char_at*/ true, &scratch));
967 __ Bind(&done);
968 return;
969 }
970 FALLTHROUGH_INTENDED;
Aart Bikf8f5a162017-02-06 15:35:29 -0800971 case Primitive::kPrimBoolean:
972 case Primitive::kPrimByte:
Aart Bikf8f5a162017-02-06 15:35:29 -0800973 case Primitive::kPrimShort:
Aart Bikf8f5a162017-02-06 15:35:29 -0800974 case Primitive::kPrimInt:
975 case Primitive::kPrimFloat:
Artem Serovb31f91f2017-04-05 11:31:19 +0100976 case Primitive::kPrimLong:
977 case Primitive::kPrimDouble:
Artem Serov0225b772017-04-19 15:43:53 +0100978 DCHECK_LE(2u, instruction->GetVectorLength());
979 DCHECK_LE(instruction->GetVectorLength(), 16u);
Aart Bik472821b2017-04-27 17:23:51 -0700980 __ Ldr(reg, VecAddress(instruction, &temps, size, instruction->IsStringCharAt(), &scratch));
Artem Serovb31f91f2017-04-05 11:31:19 +0100981 break;
Aart Bikf8f5a162017-02-06 15:35:29 -0800982 default:
983 LOG(FATAL) << "Unsupported SIMD type";
984 UNREACHABLE();
985 }
986}
987
988void LocationsBuilderARM64::VisitVecStore(HVecStore* instruction) {
989 CreateVecMemLocations(GetGraph()->GetArena(), instruction, /*is_load*/ false);
990}
991
992void InstructionCodeGeneratorARM64::VisitVecStore(HVecStore* instruction) {
Aart Bik472821b2017-04-27 17:23:51 -0700993 LocationSummary* locations = instruction->GetLocations();
994 size_t size = Primitive::ComponentSize(instruction->GetPackedType());
995 VRegister reg = VRegisterFrom(locations->InAt(2));
Artem Serov0225b772017-04-19 15:43:53 +0100996 UseScratchRegisterScope temps(GetVIXLAssembler());
Aart Bik472821b2017-04-27 17:23:51 -0700997 Register scratch;
Artem Serov0225b772017-04-19 15:43:53 +0100998
Aart Bikf8f5a162017-02-06 15:35:29 -0800999 switch (instruction->GetPackedType()) {
1000 case Primitive::kPrimBoolean:
1001 case Primitive::kPrimByte:
Aart Bikf8f5a162017-02-06 15:35:29 -08001002 case Primitive::kPrimChar:
1003 case Primitive::kPrimShort:
Aart Bikf8f5a162017-02-06 15:35:29 -08001004 case Primitive::kPrimInt:
1005 case Primitive::kPrimFloat:
Artem Serovb31f91f2017-04-05 11:31:19 +01001006 case Primitive::kPrimLong:
1007 case Primitive::kPrimDouble:
Artem Serov0225b772017-04-19 15:43:53 +01001008 DCHECK_LE(2u, instruction->GetVectorLength());
1009 DCHECK_LE(instruction->GetVectorLength(), 16u);
Aart Bik472821b2017-04-27 17:23:51 -07001010 __ Str(reg, VecAddress(instruction, &temps, size, /*is_string_char_at*/ false, &scratch));
Artem Serovb31f91f2017-04-05 11:31:19 +01001011 break;
Aart Bikf8f5a162017-02-06 15:35:29 -08001012 default:
1013 LOG(FATAL) << "Unsupported SIMD type";
1014 UNREACHABLE();
1015 }
1016}
1017
1018#undef __
1019
1020} // namespace arm64
1021} // namespace art