blob: 9095ecdf16a4918949b289bb762bca7fe3d6d70e [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"
Andreas Gampe895f9222017-07-05 09:53:32 -070018
Aart Bikf8f5a162017-02-06 15:35:29 -080019#include "mirror/array-inl.h"
Andreas Gampe895f9222017-07-05 09:53:32 -070020#include "mirror/string.h"
Aart Bikf8f5a162017-02-06 15:35:29 -080021
22using namespace vixl::aarch64; // NOLINT(build/namespaces)
23
24namespace art {
25namespace arm64 {
26
Artem Serov8dfe7462017-06-01 14:28:48 +010027using helpers::ARM64EncodableConstantOrRegister;
28using helpers::Arm64CanEncodeConstantAsImmediate;
Aart Bik472821b2017-04-27 17:23:51 -070029using helpers::DRegisterFrom;
Artem Serovb31f91f2017-04-05 11:31:19 +010030using helpers::VRegisterFrom;
Aart Bikf8f5a162017-02-06 15:35:29 -080031using helpers::HeapOperand;
32using helpers::InputRegisterAt;
33using helpers::Int64ConstantFrom;
34using helpers::XRegisterFrom;
Artem Serov0225b772017-04-19 15:43:53 +010035using helpers::WRegisterFrom;
Aart Bikf8f5a162017-02-06 15:35:29 -080036
37#define __ GetVIXLAssembler()->
38
39void LocationsBuilderARM64::VisitVecReplicateScalar(HVecReplicateScalar* instruction) {
40 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction);
Artem Serov8dfe7462017-06-01 14:28:48 +010041 HInstruction* input = instruction->InputAt(0);
Aart Bikf8f5a162017-02-06 15:35:29 -080042 switch (instruction->GetPackedType()) {
43 case Primitive::kPrimBoolean:
44 case Primitive::kPrimByte:
45 case Primitive::kPrimChar:
46 case Primitive::kPrimShort:
47 case Primitive::kPrimInt:
Artem Serovb31f91f2017-04-05 11:31:19 +010048 case Primitive::kPrimLong:
Artem Serov8dfe7462017-06-01 14:28:48 +010049 locations->SetInAt(0, ARM64EncodableConstantOrRegister(input, instruction));
Aart Bikf8f5a162017-02-06 15:35:29 -080050 locations->SetOut(Location::RequiresFpuRegister());
51 break;
52 case Primitive::kPrimFloat:
Artem Serovb31f91f2017-04-05 11:31:19 +010053 case Primitive::kPrimDouble:
Artem Serov8dfe7462017-06-01 14:28:48 +010054 if (input->IsConstant() &&
55 Arm64CanEncodeConstantAsImmediate(input->AsConstant(), instruction)) {
56 locations->SetInAt(0, Location::ConstantLocation(input->AsConstant()));
57 locations->SetOut(Location::RequiresFpuRegister());
58 } else {
59 locations->SetInAt(0, Location::RequiresFpuRegister());
60 locations->SetOut(Location::RequiresFpuRegister(), Location::kNoOutputOverlap);
61 }
Aart Bikf8f5a162017-02-06 15:35:29 -080062 break;
63 default:
64 LOG(FATAL) << "Unsupported SIMD type";
65 UNREACHABLE();
66 }
67}
68
69void InstructionCodeGeneratorARM64::VisitVecReplicateScalar(HVecReplicateScalar* instruction) {
70 LocationSummary* locations = instruction->GetLocations();
Artem Serov8dfe7462017-06-01 14:28:48 +010071 Location src_loc = locations->InAt(0);
Artem Serovb31f91f2017-04-05 11:31:19 +010072 VRegister dst = VRegisterFrom(locations->Out());
Aart Bikf8f5a162017-02-06 15:35:29 -080073 switch (instruction->GetPackedType()) {
74 case Primitive::kPrimBoolean:
75 case Primitive::kPrimByte:
Artem Serovd4bccf12017-04-03 18:47:32 +010076 DCHECK_EQ(16u, instruction->GetVectorLength());
Artem Serov8dfe7462017-06-01 14:28:48 +010077 if (src_loc.IsConstant()) {
78 __ Movi(dst.V16B(), Int64ConstantFrom(src_loc));
79 } else {
80 __ Dup(dst.V16B(), InputRegisterAt(instruction, 0));
81 }
Aart Bikf8f5a162017-02-06 15:35:29 -080082 break;
83 case Primitive::kPrimChar:
84 case Primitive::kPrimShort:
Artem Serovd4bccf12017-04-03 18:47:32 +010085 DCHECK_EQ(8u, instruction->GetVectorLength());
Artem Serov8dfe7462017-06-01 14:28:48 +010086 if (src_loc.IsConstant()) {
87 __ Movi(dst.V8H(), Int64ConstantFrom(src_loc));
88 } else {
89 __ Dup(dst.V8H(), InputRegisterAt(instruction, 0));
90 }
Aart Bikf8f5a162017-02-06 15:35:29 -080091 break;
92 case Primitive::kPrimInt:
Artem Serovd4bccf12017-04-03 18:47:32 +010093 DCHECK_EQ(4u, instruction->GetVectorLength());
Artem Serov8dfe7462017-06-01 14:28:48 +010094 if (src_loc.IsConstant()) {
95 __ Movi(dst.V4S(), Int64ConstantFrom(src_loc));
96 } else {
97 __ Dup(dst.V4S(), InputRegisterAt(instruction, 0));
98 }
Aart Bikf8f5a162017-02-06 15:35:29 -080099 break;
Artem Serovb31f91f2017-04-05 11:31:19 +0100100 case Primitive::kPrimLong:
101 DCHECK_EQ(2u, instruction->GetVectorLength());
Artem Serov8dfe7462017-06-01 14:28:48 +0100102 if (src_loc.IsConstant()) {
103 __ Movi(dst.V2D(), Int64ConstantFrom(src_loc));
104 } else {
105 __ Dup(dst.V2D(), XRegisterFrom(src_loc));
106 }
Artem Serovb31f91f2017-04-05 11:31:19 +0100107 break;
Aart Bikf8f5a162017-02-06 15:35:29 -0800108 case Primitive::kPrimFloat:
Artem Serovd4bccf12017-04-03 18:47:32 +0100109 DCHECK_EQ(4u, instruction->GetVectorLength());
Artem Serov8dfe7462017-06-01 14:28:48 +0100110 if (src_loc.IsConstant()) {
111 __ Fmov(dst.V4S(), src_loc.GetConstant()->AsFloatConstant()->GetValue());
112 } else {
113 __ Dup(dst.V4S(), VRegisterFrom(src_loc).V4S(), 0);
114 }
Artem Serovb31f91f2017-04-05 11:31:19 +0100115 break;
116 case Primitive::kPrimDouble:
117 DCHECK_EQ(2u, instruction->GetVectorLength());
Artem Serov8dfe7462017-06-01 14:28:48 +0100118 if (src_loc.IsConstant()) {
119 __ Fmov(dst.V2D(), src_loc.GetConstant()->AsDoubleConstant()->GetValue());
120 } else {
121 __ Dup(dst.V2D(), VRegisterFrom(src_loc).V2D(), 0);
122 }
Aart Bikf8f5a162017-02-06 15:35:29 -0800123 break;
124 default:
125 LOG(FATAL) << "Unsupported SIMD type";
126 UNREACHABLE();
127 }
128}
129
130void LocationsBuilderARM64::VisitVecSetScalars(HVecSetScalars* instruction) {
131 LOG(FATAL) << "No SIMD for " << instruction->GetId();
132}
133
134void InstructionCodeGeneratorARM64::VisitVecSetScalars(HVecSetScalars* instruction) {
135 LOG(FATAL) << "No SIMD for " << instruction->GetId();
136}
137
138void LocationsBuilderARM64::VisitVecSumReduce(HVecSumReduce* instruction) {
139 LOG(FATAL) << "No SIMD for " << instruction->GetId();
140}
141
142void InstructionCodeGeneratorARM64::VisitVecSumReduce(HVecSumReduce* instruction) {
143 LOG(FATAL) << "No SIMD for " << instruction->GetId();
144}
145
146// Helper to set up locations for vector unary operations.
147static void CreateVecUnOpLocations(ArenaAllocator* arena, HVecUnaryOperation* instruction) {
148 LocationSummary* locations = new (arena) LocationSummary(instruction);
149 switch (instruction->GetPackedType()) {
150 case Primitive::kPrimBoolean:
151 locations->SetInAt(0, Location::RequiresFpuRegister());
152 locations->SetOut(Location::RequiresFpuRegister(),
153 instruction->IsVecNot() ? Location::kOutputOverlap
154 : Location::kNoOutputOverlap);
155 break;
156 case Primitive::kPrimByte:
157 case Primitive::kPrimChar:
158 case Primitive::kPrimShort:
159 case Primitive::kPrimInt:
Artem Serovb31f91f2017-04-05 11:31:19 +0100160 case Primitive::kPrimLong:
Aart Bikf8f5a162017-02-06 15:35:29 -0800161 case Primitive::kPrimFloat:
Artem Serovb31f91f2017-04-05 11:31:19 +0100162 case Primitive::kPrimDouble:
Aart Bikf8f5a162017-02-06 15:35:29 -0800163 locations->SetInAt(0, Location::RequiresFpuRegister());
164 locations->SetOut(Location::RequiresFpuRegister(), Location::kNoOutputOverlap);
165 break;
166 default:
167 LOG(FATAL) << "Unsupported SIMD type";
168 UNREACHABLE();
169 }
170}
171
172void LocationsBuilderARM64::VisitVecCnv(HVecCnv* instruction) {
173 CreateVecUnOpLocations(GetGraph()->GetArena(), instruction);
174}
175
176void InstructionCodeGeneratorARM64::VisitVecCnv(HVecCnv* instruction) {
177 LocationSummary* locations = instruction->GetLocations();
Artem Serovb31f91f2017-04-05 11:31:19 +0100178 VRegister src = VRegisterFrom(locations->InAt(0));
179 VRegister dst = VRegisterFrom(locations->Out());
Aart Bikf8f5a162017-02-06 15:35:29 -0800180 Primitive::Type from = instruction->GetInputType();
181 Primitive::Type to = instruction->GetResultType();
182 if (from == Primitive::kPrimInt && to == Primitive::kPrimFloat) {
Artem Serovd4bccf12017-04-03 18:47:32 +0100183 DCHECK_EQ(4u, instruction->GetVectorLength());
184 __ Scvtf(dst.V4S(), src.V4S());
Aart Bikf8f5a162017-02-06 15:35:29 -0800185 } else {
186 LOG(FATAL) << "Unsupported SIMD type";
187 }
188}
189
190void LocationsBuilderARM64::VisitVecNeg(HVecNeg* instruction) {
191 CreateVecUnOpLocations(GetGraph()->GetArena(), instruction);
192}
193
194void InstructionCodeGeneratorARM64::VisitVecNeg(HVecNeg* instruction) {
195 LocationSummary* locations = instruction->GetLocations();
Artem Serovb31f91f2017-04-05 11:31:19 +0100196 VRegister src = VRegisterFrom(locations->InAt(0));
197 VRegister dst = VRegisterFrom(locations->Out());
Aart Bikf8f5a162017-02-06 15:35:29 -0800198 switch (instruction->GetPackedType()) {
199 case Primitive::kPrimByte:
Artem Serovd4bccf12017-04-03 18:47:32 +0100200 DCHECK_EQ(16u, instruction->GetVectorLength());
201 __ Neg(dst.V16B(), src.V16B());
Aart Bikf8f5a162017-02-06 15:35:29 -0800202 break;
203 case Primitive::kPrimChar:
204 case Primitive::kPrimShort:
Artem Serovd4bccf12017-04-03 18:47:32 +0100205 DCHECK_EQ(8u, instruction->GetVectorLength());
206 __ Neg(dst.V8H(), src.V8H());
Aart Bikf8f5a162017-02-06 15:35:29 -0800207 break;
208 case Primitive::kPrimInt:
Artem Serovd4bccf12017-04-03 18:47:32 +0100209 DCHECK_EQ(4u, instruction->GetVectorLength());
210 __ Neg(dst.V4S(), src.V4S());
Aart Bikf8f5a162017-02-06 15:35:29 -0800211 break;
Artem Serovb31f91f2017-04-05 11:31:19 +0100212 case Primitive::kPrimLong:
213 DCHECK_EQ(2u, instruction->GetVectorLength());
214 __ Neg(dst.V2D(), src.V2D());
215 break;
Aart Bikf8f5a162017-02-06 15:35:29 -0800216 case Primitive::kPrimFloat:
Artem Serovd4bccf12017-04-03 18:47:32 +0100217 DCHECK_EQ(4u, instruction->GetVectorLength());
218 __ Fneg(dst.V4S(), src.V4S());
Aart Bikf8f5a162017-02-06 15:35:29 -0800219 break;
Artem Serovb31f91f2017-04-05 11:31:19 +0100220 case Primitive::kPrimDouble:
221 DCHECK_EQ(2u, instruction->GetVectorLength());
222 __ Fneg(dst.V2D(), src.V2D());
223 break;
Aart Bikf8f5a162017-02-06 15:35:29 -0800224 default:
225 LOG(FATAL) << "Unsupported SIMD type";
226 UNREACHABLE();
227 }
228}
229
Aart Bik6daebeb2017-04-03 14:35:41 -0700230void LocationsBuilderARM64::VisitVecAbs(HVecAbs* instruction) {
231 CreateVecUnOpLocations(GetGraph()->GetArena(), instruction);
232}
233
234void InstructionCodeGeneratorARM64::VisitVecAbs(HVecAbs* instruction) {
235 LocationSummary* locations = instruction->GetLocations();
Artem Serovb31f91f2017-04-05 11:31:19 +0100236 VRegister src = VRegisterFrom(locations->InAt(0));
237 VRegister dst = VRegisterFrom(locations->Out());
Aart Bik6daebeb2017-04-03 14:35:41 -0700238 switch (instruction->GetPackedType()) {
239 case Primitive::kPrimByte:
Artem Serovd4bccf12017-04-03 18:47:32 +0100240 DCHECK_EQ(16u, instruction->GetVectorLength());
241 __ Abs(dst.V16B(), src.V16B());
Aart Bik6daebeb2017-04-03 14:35:41 -0700242 break;
243 case Primitive::kPrimChar:
244 case Primitive::kPrimShort:
Artem Serovd4bccf12017-04-03 18:47:32 +0100245 DCHECK_EQ(8u, instruction->GetVectorLength());
246 __ Abs(dst.V8H(), src.V8H());
Aart Bik6daebeb2017-04-03 14:35:41 -0700247 break;
248 case Primitive::kPrimInt:
Artem Serovd4bccf12017-04-03 18:47:32 +0100249 DCHECK_EQ(4u, instruction->GetVectorLength());
250 __ Abs(dst.V4S(), src.V4S());
Aart Bik6daebeb2017-04-03 14:35:41 -0700251 break;
Artem Serovb31f91f2017-04-05 11:31:19 +0100252 case Primitive::kPrimLong:
253 DCHECK_EQ(2u, instruction->GetVectorLength());
254 __ Abs(dst.V2D(), src.V2D());
255 break;
Aart Bik6daebeb2017-04-03 14:35:41 -0700256 case Primitive::kPrimFloat:
Artem Serovd4bccf12017-04-03 18:47:32 +0100257 DCHECK_EQ(4u, instruction->GetVectorLength());
258 __ Fabs(dst.V4S(), src.V4S());
Aart Bik6daebeb2017-04-03 14:35:41 -0700259 break;
Artem Serovb31f91f2017-04-05 11:31:19 +0100260 case Primitive::kPrimDouble:
261 DCHECK_EQ(2u, instruction->GetVectorLength());
262 __ Fabs(dst.V2D(), src.V2D());
263 break;
Aart Bik6daebeb2017-04-03 14:35:41 -0700264 default:
265 LOG(FATAL) << "Unsupported SIMD type";
266 }
267}
268
Aart Bikf8f5a162017-02-06 15:35:29 -0800269void LocationsBuilderARM64::VisitVecNot(HVecNot* instruction) {
270 CreateVecUnOpLocations(GetGraph()->GetArena(), instruction);
271}
272
273void InstructionCodeGeneratorARM64::VisitVecNot(HVecNot* instruction) {
274 LocationSummary* locations = instruction->GetLocations();
Artem Serovb31f91f2017-04-05 11:31:19 +0100275 VRegister src = VRegisterFrom(locations->InAt(0));
276 VRegister dst = VRegisterFrom(locations->Out());
Aart Bikf8f5a162017-02-06 15:35:29 -0800277 switch (instruction->GetPackedType()) {
278 case Primitive::kPrimBoolean: // special case boolean-not
Artem Serovd4bccf12017-04-03 18:47:32 +0100279 DCHECK_EQ(16u, instruction->GetVectorLength());
280 __ Movi(dst.V16B(), 1);
281 __ Eor(dst.V16B(), dst.V16B(), src.V16B());
Aart Bikf8f5a162017-02-06 15:35:29 -0800282 break;
283 case Primitive::kPrimByte:
284 case Primitive::kPrimChar:
285 case Primitive::kPrimShort:
286 case Primitive::kPrimInt:
Artem Serovb31f91f2017-04-05 11:31:19 +0100287 case Primitive::kPrimLong:
Artem Serovd4bccf12017-04-03 18:47:32 +0100288 __ Not(dst.V16B(), src.V16B()); // lanes do not matter
Aart Bikf8f5a162017-02-06 15:35:29 -0800289 break;
290 default:
291 LOG(FATAL) << "Unsupported SIMD type";
292 UNREACHABLE();
293 }
294}
295
296// Helper to set up locations for vector binary operations.
297static void CreateVecBinOpLocations(ArenaAllocator* arena, HVecBinaryOperation* instruction) {
298 LocationSummary* locations = new (arena) LocationSummary(instruction);
299 switch (instruction->GetPackedType()) {
300 case Primitive::kPrimBoolean:
301 case Primitive::kPrimByte:
302 case Primitive::kPrimChar:
303 case Primitive::kPrimShort:
304 case Primitive::kPrimInt:
Artem Serovb31f91f2017-04-05 11:31:19 +0100305 case Primitive::kPrimLong:
Aart Bikf8f5a162017-02-06 15:35:29 -0800306 case Primitive::kPrimFloat:
Artem Serovb31f91f2017-04-05 11:31:19 +0100307 case Primitive::kPrimDouble:
Aart Bikf8f5a162017-02-06 15:35:29 -0800308 locations->SetInAt(0, Location::RequiresFpuRegister());
309 locations->SetInAt(1, Location::RequiresFpuRegister());
310 locations->SetOut(Location::RequiresFpuRegister(), Location::kNoOutputOverlap);
311 break;
312 default:
313 LOG(FATAL) << "Unsupported SIMD type";
314 UNREACHABLE();
315 }
316}
317
318void LocationsBuilderARM64::VisitVecAdd(HVecAdd* instruction) {
319 CreateVecBinOpLocations(GetGraph()->GetArena(), instruction);
320}
321
322void InstructionCodeGeneratorARM64::VisitVecAdd(HVecAdd* instruction) {
323 LocationSummary* locations = instruction->GetLocations();
Artem Serovb31f91f2017-04-05 11:31:19 +0100324 VRegister lhs = VRegisterFrom(locations->InAt(0));
325 VRegister rhs = VRegisterFrom(locations->InAt(1));
326 VRegister dst = VRegisterFrom(locations->Out());
Aart Bikf8f5a162017-02-06 15:35:29 -0800327 switch (instruction->GetPackedType()) {
328 case Primitive::kPrimByte:
Artem Serovd4bccf12017-04-03 18:47:32 +0100329 DCHECK_EQ(16u, instruction->GetVectorLength());
330 __ Add(dst.V16B(), lhs.V16B(), rhs.V16B());
Aart Bikf8f5a162017-02-06 15:35:29 -0800331 break;
332 case Primitive::kPrimChar:
333 case Primitive::kPrimShort:
Artem Serovd4bccf12017-04-03 18:47:32 +0100334 DCHECK_EQ(8u, instruction->GetVectorLength());
335 __ Add(dst.V8H(), lhs.V8H(), rhs.V8H());
Aart Bikf8f5a162017-02-06 15:35:29 -0800336 break;
337 case Primitive::kPrimInt:
Artem Serovd4bccf12017-04-03 18:47:32 +0100338 DCHECK_EQ(4u, instruction->GetVectorLength());
339 __ Add(dst.V4S(), lhs.V4S(), rhs.V4S());
Aart Bikf8f5a162017-02-06 15:35:29 -0800340 break;
Artem Serovb31f91f2017-04-05 11:31:19 +0100341 case Primitive::kPrimLong:
342 DCHECK_EQ(2u, instruction->GetVectorLength());
343 __ Add(dst.V2D(), lhs.V2D(), rhs.V2D());
344 break;
Aart Bikf8f5a162017-02-06 15:35:29 -0800345 case Primitive::kPrimFloat:
Artem Serovd4bccf12017-04-03 18:47:32 +0100346 DCHECK_EQ(4u, instruction->GetVectorLength());
347 __ Fadd(dst.V4S(), lhs.V4S(), rhs.V4S());
Aart Bikf8f5a162017-02-06 15:35:29 -0800348 break;
Artem Serovb31f91f2017-04-05 11:31:19 +0100349 case Primitive::kPrimDouble:
350 DCHECK_EQ(2u, instruction->GetVectorLength());
351 __ Fadd(dst.V2D(), lhs.V2D(), rhs.V2D());
352 break;
Aart Bikf8f5a162017-02-06 15:35:29 -0800353 default:
354 LOG(FATAL) << "Unsupported SIMD type";
355 UNREACHABLE();
356 }
357}
358
Aart Bikf3e61ee2017-04-12 17:09:20 -0700359void LocationsBuilderARM64::VisitVecHalvingAdd(HVecHalvingAdd* instruction) {
360 CreateVecBinOpLocations(GetGraph()->GetArena(), instruction);
361}
362
363void InstructionCodeGeneratorARM64::VisitVecHalvingAdd(HVecHalvingAdd* instruction) {
364 LocationSummary* locations = instruction->GetLocations();
365 VRegister lhs = VRegisterFrom(locations->InAt(0));
366 VRegister rhs = VRegisterFrom(locations->InAt(1));
367 VRegister dst = VRegisterFrom(locations->Out());
368 switch (instruction->GetPackedType()) {
369 case Primitive::kPrimByte:
370 DCHECK_EQ(16u, instruction->GetVectorLength());
371 if (instruction->IsUnsigned()) {
372 instruction->IsRounded()
373 ? __ Urhadd(dst.V16B(), lhs.V16B(), rhs.V16B())
374 : __ Uhadd(dst.V16B(), lhs.V16B(), rhs.V16B());
375 } else {
376 instruction->IsRounded()
377 ? __ Srhadd(dst.V16B(), lhs.V16B(), rhs.V16B())
378 : __ Shadd(dst.V16B(), lhs.V16B(), rhs.V16B());
379 }
380 break;
381 case Primitive::kPrimChar:
382 case Primitive::kPrimShort:
383 DCHECK_EQ(8u, instruction->GetVectorLength());
384 if (instruction->IsUnsigned()) {
385 instruction->IsRounded()
386 ? __ Urhadd(dst.V8H(), lhs.V8H(), rhs.V8H())
387 : __ Uhadd(dst.V8H(), lhs.V8H(), rhs.V8H());
388 } else {
389 instruction->IsRounded()
390 ? __ Srhadd(dst.V8H(), lhs.V8H(), rhs.V8H())
391 : __ Shadd(dst.V8H(), lhs.V8H(), rhs.V8H());
392 }
393 break;
394 default:
395 LOG(FATAL) << "Unsupported SIMD type";
396 UNREACHABLE();
397 }
398}
399
Aart Bikf8f5a162017-02-06 15:35:29 -0800400void LocationsBuilderARM64::VisitVecSub(HVecSub* instruction) {
401 CreateVecBinOpLocations(GetGraph()->GetArena(), instruction);
402}
403
404void InstructionCodeGeneratorARM64::VisitVecSub(HVecSub* instruction) {
405 LocationSummary* locations = instruction->GetLocations();
Artem Serovb31f91f2017-04-05 11:31:19 +0100406 VRegister lhs = VRegisterFrom(locations->InAt(0));
407 VRegister rhs = VRegisterFrom(locations->InAt(1));
408 VRegister dst = VRegisterFrom(locations->Out());
Aart Bikf8f5a162017-02-06 15:35:29 -0800409 switch (instruction->GetPackedType()) {
410 case Primitive::kPrimByte:
Artem Serovd4bccf12017-04-03 18:47:32 +0100411 DCHECK_EQ(16u, instruction->GetVectorLength());
412 __ Sub(dst.V16B(), lhs.V16B(), rhs.V16B());
Aart Bikf8f5a162017-02-06 15:35:29 -0800413 break;
414 case Primitive::kPrimChar:
415 case Primitive::kPrimShort:
Artem Serovd4bccf12017-04-03 18:47:32 +0100416 DCHECK_EQ(8u, instruction->GetVectorLength());
417 __ Sub(dst.V8H(), lhs.V8H(), rhs.V8H());
Aart Bikf8f5a162017-02-06 15:35:29 -0800418 break;
419 case Primitive::kPrimInt:
Artem Serovd4bccf12017-04-03 18:47:32 +0100420 DCHECK_EQ(4u, instruction->GetVectorLength());
421 __ Sub(dst.V4S(), lhs.V4S(), rhs.V4S());
Aart Bikf8f5a162017-02-06 15:35:29 -0800422 break;
Artem Serovb31f91f2017-04-05 11:31:19 +0100423 case Primitive::kPrimLong:
424 DCHECK_EQ(2u, instruction->GetVectorLength());
425 __ Sub(dst.V2D(), lhs.V2D(), rhs.V2D());
426 break;
Aart Bikf8f5a162017-02-06 15:35:29 -0800427 case Primitive::kPrimFloat:
Artem Serovd4bccf12017-04-03 18:47:32 +0100428 DCHECK_EQ(4u, instruction->GetVectorLength());
429 __ Fsub(dst.V4S(), lhs.V4S(), rhs.V4S());
Aart Bikf8f5a162017-02-06 15:35:29 -0800430 break;
Artem Serovb31f91f2017-04-05 11:31:19 +0100431 case Primitive::kPrimDouble:
432 DCHECK_EQ(2u, instruction->GetVectorLength());
433 __ Fsub(dst.V2D(), lhs.V2D(), rhs.V2D());
434 break;
Aart Bikf8f5a162017-02-06 15:35:29 -0800435 default:
436 LOG(FATAL) << "Unsupported SIMD type";
437 UNREACHABLE();
438 }
439}
440
441void LocationsBuilderARM64::VisitVecMul(HVecMul* instruction) {
442 CreateVecBinOpLocations(GetGraph()->GetArena(), instruction);
443}
444
445void InstructionCodeGeneratorARM64::VisitVecMul(HVecMul* instruction) {
446 LocationSummary* locations = instruction->GetLocations();
Artem Serovb31f91f2017-04-05 11:31:19 +0100447 VRegister lhs = VRegisterFrom(locations->InAt(0));
448 VRegister rhs = VRegisterFrom(locations->InAt(1));
449 VRegister dst = VRegisterFrom(locations->Out());
Aart Bikf8f5a162017-02-06 15:35:29 -0800450 switch (instruction->GetPackedType()) {
451 case Primitive::kPrimByte:
Artem Serovd4bccf12017-04-03 18:47:32 +0100452 DCHECK_EQ(16u, instruction->GetVectorLength());
453 __ Mul(dst.V16B(), lhs.V16B(), rhs.V16B());
Aart Bikf8f5a162017-02-06 15:35:29 -0800454 break;
455 case Primitive::kPrimChar:
456 case Primitive::kPrimShort:
Artem Serovd4bccf12017-04-03 18:47:32 +0100457 DCHECK_EQ(8u, instruction->GetVectorLength());
458 __ Mul(dst.V8H(), lhs.V8H(), rhs.V8H());
Aart Bikf8f5a162017-02-06 15:35:29 -0800459 break;
460 case Primitive::kPrimInt:
Artem Serovd4bccf12017-04-03 18:47:32 +0100461 DCHECK_EQ(4u, instruction->GetVectorLength());
462 __ Mul(dst.V4S(), lhs.V4S(), rhs.V4S());
Aart Bikf8f5a162017-02-06 15:35:29 -0800463 break;
464 case Primitive::kPrimFloat:
Artem Serovd4bccf12017-04-03 18:47:32 +0100465 DCHECK_EQ(4u, instruction->GetVectorLength());
466 __ Fmul(dst.V4S(), lhs.V4S(), rhs.V4S());
Aart Bikf8f5a162017-02-06 15:35:29 -0800467 break;
Artem Serovb31f91f2017-04-05 11:31:19 +0100468 case Primitive::kPrimDouble:
469 DCHECK_EQ(2u, instruction->GetVectorLength());
470 __ Fmul(dst.V2D(), lhs.V2D(), rhs.V2D());
471 break;
Aart Bikf8f5a162017-02-06 15:35:29 -0800472 default:
473 LOG(FATAL) << "Unsupported SIMD type";
474 UNREACHABLE();
475 }
476}
477
478void LocationsBuilderARM64::VisitVecDiv(HVecDiv* instruction) {
479 CreateVecBinOpLocations(GetGraph()->GetArena(), instruction);
480}
481
482void InstructionCodeGeneratorARM64::VisitVecDiv(HVecDiv* instruction) {
483 LocationSummary* locations = instruction->GetLocations();
Artem Serovb31f91f2017-04-05 11:31:19 +0100484 VRegister lhs = VRegisterFrom(locations->InAt(0));
485 VRegister rhs = VRegisterFrom(locations->InAt(1));
486 VRegister dst = VRegisterFrom(locations->Out());
Aart Bikf8f5a162017-02-06 15:35:29 -0800487 switch (instruction->GetPackedType()) {
488 case Primitive::kPrimFloat:
Artem Serovd4bccf12017-04-03 18:47:32 +0100489 DCHECK_EQ(4u, instruction->GetVectorLength());
490 __ Fdiv(dst.V4S(), lhs.V4S(), rhs.V4S());
Aart Bikf8f5a162017-02-06 15:35:29 -0800491 break;
Artem Serovb31f91f2017-04-05 11:31:19 +0100492 case Primitive::kPrimDouble:
493 DCHECK_EQ(2u, instruction->GetVectorLength());
494 __ Fdiv(dst.V2D(), lhs.V2D(), rhs.V2D());
495 break;
Aart Bikf8f5a162017-02-06 15:35:29 -0800496 default:
497 LOG(FATAL) << "Unsupported SIMD type";
498 UNREACHABLE();
499 }
500}
501
Aart Bikf3e61ee2017-04-12 17:09:20 -0700502void LocationsBuilderARM64::VisitVecMin(HVecMin* instruction) {
503 CreateVecBinOpLocations(GetGraph()->GetArena(), instruction);
504}
505
506void InstructionCodeGeneratorARM64::VisitVecMin(HVecMin* instruction) {
Aart Bikc8e93c72017-05-10 10:49:22 -0700507 LocationSummary* locations = instruction->GetLocations();
508 VRegister lhs = VRegisterFrom(locations->InAt(0));
509 VRegister rhs = VRegisterFrom(locations->InAt(1));
510 VRegister dst = VRegisterFrom(locations->Out());
511 switch (instruction->GetPackedType()) {
512 case Primitive::kPrimByte:
513 DCHECK_EQ(16u, instruction->GetVectorLength());
514 if (instruction->IsUnsigned()) {
515 __ Umin(dst.V16B(), lhs.V16B(), rhs.V16B());
516 } else {
517 __ Smin(dst.V16B(), lhs.V16B(), rhs.V16B());
518 }
519 break;
520 case Primitive::kPrimChar:
521 case Primitive::kPrimShort:
522 DCHECK_EQ(8u, instruction->GetVectorLength());
523 if (instruction->IsUnsigned()) {
524 __ Umin(dst.V8H(), lhs.V8H(), rhs.V8H());
525 } else {
526 __ Smin(dst.V8H(), lhs.V8H(), rhs.V8H());
527 }
528 break;
529 case Primitive::kPrimInt:
530 DCHECK_EQ(4u, instruction->GetVectorLength());
531 if (instruction->IsUnsigned()) {
532 __ Umin(dst.V4S(), lhs.V4S(), rhs.V4S());
533 } else {
534 __ Smin(dst.V4S(), lhs.V4S(), rhs.V4S());
535 }
536 break;
537 case Primitive::kPrimFloat:
538 DCHECK_EQ(4u, instruction->GetVectorLength());
539 DCHECK(!instruction->IsUnsigned());
540 __ Fmin(dst.V4S(), lhs.V4S(), rhs.V4S());
541 break;
542 case Primitive::kPrimDouble:
543 DCHECK_EQ(2u, instruction->GetVectorLength());
544 DCHECK(!instruction->IsUnsigned());
545 __ Fmin(dst.V2D(), lhs.V2D(), rhs.V2D());
546 break;
547 default:
548 LOG(FATAL) << "Unsupported SIMD type";
549 UNREACHABLE();
550 }
Aart Bikf3e61ee2017-04-12 17:09:20 -0700551}
552
553void LocationsBuilderARM64::VisitVecMax(HVecMax* instruction) {
554 CreateVecBinOpLocations(GetGraph()->GetArena(), instruction);
555}
556
557void InstructionCodeGeneratorARM64::VisitVecMax(HVecMax* instruction) {
Aart Bikc8e93c72017-05-10 10:49:22 -0700558 LocationSummary* locations = instruction->GetLocations();
559 VRegister lhs = VRegisterFrom(locations->InAt(0));
560 VRegister rhs = VRegisterFrom(locations->InAt(1));
561 VRegister dst = VRegisterFrom(locations->Out());
562 switch (instruction->GetPackedType()) {
563 case Primitive::kPrimByte:
564 DCHECK_EQ(16u, instruction->GetVectorLength());
565 if (instruction->IsUnsigned()) {
566 __ Umax(dst.V16B(), lhs.V16B(), rhs.V16B());
567 } else {
568 __ Smax(dst.V16B(), lhs.V16B(), rhs.V16B());
569 }
570 break;
571 case Primitive::kPrimChar:
572 case Primitive::kPrimShort:
573 DCHECK_EQ(8u, instruction->GetVectorLength());
574 if (instruction->IsUnsigned()) {
575 __ Umax(dst.V8H(), lhs.V8H(), rhs.V8H());
576 } else {
577 __ Smax(dst.V8H(), lhs.V8H(), rhs.V8H());
578 }
579 break;
580 case Primitive::kPrimInt:
581 DCHECK_EQ(4u, instruction->GetVectorLength());
582 if (instruction->IsUnsigned()) {
583 __ Umax(dst.V4S(), lhs.V4S(), rhs.V4S());
584 } else {
585 __ Smax(dst.V4S(), lhs.V4S(), rhs.V4S());
586 }
587 break;
588 case Primitive::kPrimFloat:
589 DCHECK_EQ(4u, instruction->GetVectorLength());
590 DCHECK(!instruction->IsUnsigned());
591 __ Fmax(dst.V4S(), lhs.V4S(), rhs.V4S());
592 break;
593 case Primitive::kPrimDouble:
594 DCHECK_EQ(2u, instruction->GetVectorLength());
595 DCHECK(!instruction->IsUnsigned());
596 __ Fmax(dst.V2D(), lhs.V2D(), rhs.V2D());
597 break;
598 default:
599 LOG(FATAL) << "Unsupported SIMD type";
600 UNREACHABLE();
601 }
Aart Bikf3e61ee2017-04-12 17:09:20 -0700602}
603
Aart Bikf8f5a162017-02-06 15:35:29 -0800604void LocationsBuilderARM64::VisitVecAnd(HVecAnd* instruction) {
605 CreateVecBinOpLocations(GetGraph()->GetArena(), instruction);
606}
607
608void InstructionCodeGeneratorARM64::VisitVecAnd(HVecAnd* instruction) {
609 LocationSummary* locations = instruction->GetLocations();
Artem Serovb31f91f2017-04-05 11:31:19 +0100610 VRegister lhs = VRegisterFrom(locations->InAt(0));
611 VRegister rhs = VRegisterFrom(locations->InAt(1));
612 VRegister dst = VRegisterFrom(locations->Out());
Aart Bikf8f5a162017-02-06 15:35:29 -0800613 switch (instruction->GetPackedType()) {
614 case Primitive::kPrimBoolean:
615 case Primitive::kPrimByte:
616 case Primitive::kPrimChar:
617 case Primitive::kPrimShort:
618 case Primitive::kPrimInt:
Artem Serovb31f91f2017-04-05 11:31:19 +0100619 case Primitive::kPrimLong:
Aart Bikf8f5a162017-02-06 15:35:29 -0800620 case Primitive::kPrimFloat:
Artem Serovb31f91f2017-04-05 11:31:19 +0100621 case Primitive::kPrimDouble:
Artem Serovd4bccf12017-04-03 18:47:32 +0100622 __ And(dst.V16B(), lhs.V16B(), rhs.V16B()); // lanes do not matter
Aart Bikf8f5a162017-02-06 15:35:29 -0800623 break;
624 default:
625 LOG(FATAL) << "Unsupported SIMD type";
626 UNREACHABLE();
627 }
628}
629
630void LocationsBuilderARM64::VisitVecAndNot(HVecAndNot* instruction) {
631 LOG(FATAL) << "Unsupported SIMD instruction " << instruction->GetId();
632}
633
634void InstructionCodeGeneratorARM64::VisitVecAndNot(HVecAndNot* instruction) {
635 LOG(FATAL) << "Unsupported SIMD instruction " << instruction->GetId();
636}
637
638void LocationsBuilderARM64::VisitVecOr(HVecOr* instruction) {
639 CreateVecBinOpLocations(GetGraph()->GetArena(), instruction);
640}
641
642void InstructionCodeGeneratorARM64::VisitVecOr(HVecOr* instruction) {
643 LocationSummary* locations = instruction->GetLocations();
Artem Serovb31f91f2017-04-05 11:31:19 +0100644 VRegister lhs = VRegisterFrom(locations->InAt(0));
645 VRegister rhs = VRegisterFrom(locations->InAt(1));
646 VRegister dst = VRegisterFrom(locations->Out());
Aart Bikf8f5a162017-02-06 15:35:29 -0800647 switch (instruction->GetPackedType()) {
648 case Primitive::kPrimBoolean:
649 case Primitive::kPrimByte:
650 case Primitive::kPrimChar:
651 case Primitive::kPrimShort:
652 case Primitive::kPrimInt:
Artem Serovb31f91f2017-04-05 11:31:19 +0100653 case Primitive::kPrimLong:
Aart Bikf8f5a162017-02-06 15:35:29 -0800654 case Primitive::kPrimFloat:
Artem Serovb31f91f2017-04-05 11:31:19 +0100655 case Primitive::kPrimDouble:
Artem Serovd4bccf12017-04-03 18:47:32 +0100656 __ Orr(dst.V16B(), lhs.V16B(), rhs.V16B()); // lanes do not matter
Aart Bikf8f5a162017-02-06 15:35:29 -0800657 break;
658 default:
659 LOG(FATAL) << "Unsupported SIMD type";
660 UNREACHABLE();
661 }
662}
663
664void LocationsBuilderARM64::VisitVecXor(HVecXor* instruction) {
665 CreateVecBinOpLocations(GetGraph()->GetArena(), instruction);
666}
667
668void InstructionCodeGeneratorARM64::VisitVecXor(HVecXor* instruction) {
669 LocationSummary* locations = instruction->GetLocations();
Artem Serovb31f91f2017-04-05 11:31:19 +0100670 VRegister lhs = VRegisterFrom(locations->InAt(0));
671 VRegister rhs = VRegisterFrom(locations->InAt(1));
672 VRegister dst = VRegisterFrom(locations->Out());
Aart Bikf8f5a162017-02-06 15:35:29 -0800673 switch (instruction->GetPackedType()) {
674 case Primitive::kPrimBoolean:
675 case Primitive::kPrimByte:
676 case Primitive::kPrimChar:
677 case Primitive::kPrimShort:
678 case Primitive::kPrimInt:
Artem Serovb31f91f2017-04-05 11:31:19 +0100679 case Primitive::kPrimLong:
Aart Bikf8f5a162017-02-06 15:35:29 -0800680 case Primitive::kPrimFloat:
Artem Serovb31f91f2017-04-05 11:31:19 +0100681 case Primitive::kPrimDouble:
Artem Serovd4bccf12017-04-03 18:47:32 +0100682 __ Eor(dst.V16B(), lhs.V16B(), rhs.V16B()); // lanes do not matter
Aart Bikf8f5a162017-02-06 15:35:29 -0800683 break;
684 default:
685 LOG(FATAL) << "Unsupported SIMD type";
686 UNREACHABLE();
687 }
688}
689
690// Helper to set up locations for vector shift operations.
691static void CreateVecShiftLocations(ArenaAllocator* arena, HVecBinaryOperation* instruction) {
692 LocationSummary* locations = new (arena) LocationSummary(instruction);
693 switch (instruction->GetPackedType()) {
694 case Primitive::kPrimByte:
695 case Primitive::kPrimChar:
696 case Primitive::kPrimShort:
697 case Primitive::kPrimInt:
Artem Serovb31f91f2017-04-05 11:31:19 +0100698 case Primitive::kPrimLong:
Aart Bikf8f5a162017-02-06 15:35:29 -0800699 locations->SetInAt(0, Location::RequiresFpuRegister());
700 locations->SetInAt(1, Location::ConstantLocation(instruction->InputAt(1)->AsConstant()));
701 locations->SetOut(Location::RequiresFpuRegister(), Location::kNoOutputOverlap);
702 break;
703 default:
704 LOG(FATAL) << "Unsupported SIMD type";
705 UNREACHABLE();
706 }
707}
708
709void LocationsBuilderARM64::VisitVecShl(HVecShl* instruction) {
710 CreateVecShiftLocations(GetGraph()->GetArena(), instruction);
711}
712
713void InstructionCodeGeneratorARM64::VisitVecShl(HVecShl* instruction) {
714 LocationSummary* locations = instruction->GetLocations();
Artem Serovb31f91f2017-04-05 11:31:19 +0100715 VRegister lhs = VRegisterFrom(locations->InAt(0));
716 VRegister dst = VRegisterFrom(locations->Out());
Aart Bikf8f5a162017-02-06 15:35:29 -0800717 int32_t value = locations->InAt(1).GetConstant()->AsIntConstant()->GetValue();
718 switch (instruction->GetPackedType()) {
719 case Primitive::kPrimByte:
Artem Serovd4bccf12017-04-03 18:47:32 +0100720 DCHECK_EQ(16u, instruction->GetVectorLength());
721 __ Shl(dst.V16B(), lhs.V16B(), value);
Aart Bikf8f5a162017-02-06 15:35:29 -0800722 break;
723 case Primitive::kPrimChar:
724 case Primitive::kPrimShort:
Artem Serovd4bccf12017-04-03 18:47:32 +0100725 DCHECK_EQ(8u, instruction->GetVectorLength());
726 __ Shl(dst.V8H(), lhs.V8H(), value);
Aart Bikf8f5a162017-02-06 15:35:29 -0800727 break;
728 case Primitive::kPrimInt:
Artem Serovd4bccf12017-04-03 18:47:32 +0100729 DCHECK_EQ(4u, instruction->GetVectorLength());
730 __ Shl(dst.V4S(), lhs.V4S(), value);
Aart Bikf8f5a162017-02-06 15:35:29 -0800731 break;
Artem Serovb31f91f2017-04-05 11:31:19 +0100732 case Primitive::kPrimLong:
733 DCHECK_EQ(2u, instruction->GetVectorLength());
734 __ Shl(dst.V2D(), lhs.V2D(), value);
735 break;
Aart Bikf8f5a162017-02-06 15:35:29 -0800736 default:
737 LOG(FATAL) << "Unsupported SIMD type";
738 UNREACHABLE();
739 }
740}
741
742void LocationsBuilderARM64::VisitVecShr(HVecShr* instruction) {
743 CreateVecShiftLocations(GetGraph()->GetArena(), instruction);
744}
745
746void InstructionCodeGeneratorARM64::VisitVecShr(HVecShr* instruction) {
747 LocationSummary* locations = instruction->GetLocations();
Artem Serovb31f91f2017-04-05 11:31:19 +0100748 VRegister lhs = VRegisterFrom(locations->InAt(0));
749 VRegister dst = VRegisterFrom(locations->Out());
Aart Bikf8f5a162017-02-06 15:35:29 -0800750 int32_t value = locations->InAt(1).GetConstant()->AsIntConstant()->GetValue();
751 switch (instruction->GetPackedType()) {
752 case Primitive::kPrimByte:
Artem Serovd4bccf12017-04-03 18:47:32 +0100753 DCHECK_EQ(16u, instruction->GetVectorLength());
754 __ Sshr(dst.V16B(), lhs.V16B(), value);
Aart Bikf8f5a162017-02-06 15:35:29 -0800755 break;
756 case Primitive::kPrimChar:
757 case Primitive::kPrimShort:
Artem Serovd4bccf12017-04-03 18:47:32 +0100758 DCHECK_EQ(8u, instruction->GetVectorLength());
759 __ Sshr(dst.V8H(), lhs.V8H(), value);
Aart Bikf8f5a162017-02-06 15:35:29 -0800760 break;
761 case Primitive::kPrimInt:
Artem Serovd4bccf12017-04-03 18:47:32 +0100762 DCHECK_EQ(4u, instruction->GetVectorLength());
763 __ Sshr(dst.V4S(), lhs.V4S(), value);
Aart Bikf8f5a162017-02-06 15:35:29 -0800764 break;
Artem Serovb31f91f2017-04-05 11:31:19 +0100765 case Primitive::kPrimLong:
766 DCHECK_EQ(2u, instruction->GetVectorLength());
767 __ Sshr(dst.V2D(), lhs.V2D(), value);
768 break;
Aart Bikf8f5a162017-02-06 15:35:29 -0800769 default:
770 LOG(FATAL) << "Unsupported SIMD type";
771 UNREACHABLE();
772 }
773}
774
775void LocationsBuilderARM64::VisitVecUShr(HVecUShr* instruction) {
776 CreateVecShiftLocations(GetGraph()->GetArena(), instruction);
777}
778
779void InstructionCodeGeneratorARM64::VisitVecUShr(HVecUShr* instruction) {
780 LocationSummary* locations = instruction->GetLocations();
Artem Serovb31f91f2017-04-05 11:31:19 +0100781 VRegister lhs = VRegisterFrom(locations->InAt(0));
782 VRegister dst = VRegisterFrom(locations->Out());
Aart Bikf8f5a162017-02-06 15:35:29 -0800783 int32_t value = locations->InAt(1).GetConstant()->AsIntConstant()->GetValue();
784 switch (instruction->GetPackedType()) {
785 case Primitive::kPrimByte:
Artem Serovd4bccf12017-04-03 18:47:32 +0100786 DCHECK_EQ(16u, instruction->GetVectorLength());
787 __ Ushr(dst.V16B(), lhs.V16B(), value);
Aart Bikf8f5a162017-02-06 15:35:29 -0800788 break;
789 case Primitive::kPrimChar:
790 case Primitive::kPrimShort:
Artem Serovd4bccf12017-04-03 18:47:32 +0100791 DCHECK_EQ(8u, instruction->GetVectorLength());
792 __ Ushr(dst.V8H(), lhs.V8H(), value);
Aart Bikf8f5a162017-02-06 15:35:29 -0800793 break;
794 case Primitive::kPrimInt:
Artem Serovd4bccf12017-04-03 18:47:32 +0100795 DCHECK_EQ(4u, instruction->GetVectorLength());
796 __ Ushr(dst.V4S(), lhs.V4S(), value);
Aart Bikf8f5a162017-02-06 15:35:29 -0800797 break;
Artem Serovb31f91f2017-04-05 11:31:19 +0100798 case Primitive::kPrimLong:
799 DCHECK_EQ(2u, instruction->GetVectorLength());
800 __ Ushr(dst.V2D(), lhs.V2D(), value);
801 break;
Aart Bikf8f5a162017-02-06 15:35:29 -0800802 default:
803 LOG(FATAL) << "Unsupported SIMD type";
804 UNREACHABLE();
805 }
806}
807
Artem Serovf34dd202017-04-10 17:41:46 +0100808void LocationsBuilderARM64::VisitVecMultiplyAccumulate(HVecMultiplyAccumulate* instr) {
809 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instr);
810 switch (instr->GetPackedType()) {
811 case Primitive::kPrimByte:
812 case Primitive::kPrimChar:
813 case Primitive::kPrimShort:
814 case Primitive::kPrimInt:
815 locations->SetInAt(
816 HVecMultiplyAccumulate::kInputAccumulatorIndex, Location::RequiresFpuRegister());
817 locations->SetInAt(
818 HVecMultiplyAccumulate::kInputMulLeftIndex, Location::RequiresFpuRegister());
819 locations->SetInAt(
820 HVecMultiplyAccumulate::kInputMulRightIndex, Location::RequiresFpuRegister());
821 DCHECK_EQ(HVecMultiplyAccumulate::kInputAccumulatorIndex, 0);
822 locations->SetOut(Location::SameAsFirstInput());
823 break;
824 default:
825 LOG(FATAL) << "Unsupported SIMD type";
826 UNREACHABLE();
827 }
828}
829
830// Some early revisions of the Cortex-A53 have an erratum (835769) whereby it is possible for a
831// 64-bit scalar multiply-accumulate instruction in AArch64 state to generate an incorrect result.
832// However vector MultiplyAccumulate instruction is not affected.
833void InstructionCodeGeneratorARM64::VisitVecMultiplyAccumulate(HVecMultiplyAccumulate* instr) {
834 LocationSummary* locations = instr->GetLocations();
835 VRegister acc = VRegisterFrom(locations->InAt(HVecMultiplyAccumulate::kInputAccumulatorIndex));
836 VRegister left = VRegisterFrom(locations->InAt(HVecMultiplyAccumulate::kInputMulLeftIndex));
837 VRegister right = VRegisterFrom(locations->InAt(HVecMultiplyAccumulate::kInputMulRightIndex));
838 switch (instr->GetPackedType()) {
839 case Primitive::kPrimByte:
840 DCHECK_EQ(16u, instr->GetVectorLength());
841 if (instr->GetOpKind() == HInstruction::kAdd) {
842 __ Mla(acc.V16B(), left.V16B(), right.V16B());
843 } else {
844 __ Mls(acc.V16B(), left.V16B(), right.V16B());
845 }
846 break;
847 case Primitive::kPrimChar:
848 case Primitive::kPrimShort:
849 DCHECK_EQ(8u, instr->GetVectorLength());
850 if (instr->GetOpKind() == HInstruction::kAdd) {
851 __ Mla(acc.V8H(), left.V8H(), right.V8H());
852 } else {
853 __ Mls(acc.V8H(), left.V8H(), right.V8H());
854 }
855 break;
856 case Primitive::kPrimInt:
857 DCHECK_EQ(4u, instr->GetVectorLength());
858 if (instr->GetOpKind() == HInstruction::kAdd) {
859 __ Mla(acc.V4S(), left.V4S(), right.V4S());
860 } else {
861 __ Mls(acc.V4S(), left.V4S(), right.V4S());
862 }
863 break;
864 default:
865 LOG(FATAL) << "Unsupported SIMD type";
866 }
867}
868
Aart Bikf8f5a162017-02-06 15:35:29 -0800869// Helper to set up locations for vector memory operations.
870static void CreateVecMemLocations(ArenaAllocator* arena,
871 HVecMemoryOperation* instruction,
872 bool is_load) {
873 LocationSummary* locations = new (arena) LocationSummary(instruction);
874 switch (instruction->GetPackedType()) {
875 case Primitive::kPrimBoolean:
876 case Primitive::kPrimByte:
877 case Primitive::kPrimChar:
878 case Primitive::kPrimShort:
879 case Primitive::kPrimInt:
Artem Serovb31f91f2017-04-05 11:31:19 +0100880 case Primitive::kPrimLong:
Aart Bikf8f5a162017-02-06 15:35:29 -0800881 case Primitive::kPrimFloat:
Artem Serovb31f91f2017-04-05 11:31:19 +0100882 case Primitive::kPrimDouble:
Aart Bikf8f5a162017-02-06 15:35:29 -0800883 locations->SetInAt(0, Location::RequiresRegister());
884 locations->SetInAt(1, Location::RegisterOrConstant(instruction->InputAt(1)));
885 if (is_load) {
886 locations->SetOut(Location::RequiresFpuRegister());
887 } else {
888 locations->SetInAt(2, Location::RequiresFpuRegister());
889 }
890 break;
891 default:
892 LOG(FATAL) << "Unsupported SIMD type";
893 UNREACHABLE();
894 }
895}
896
Aart Bik472821b2017-04-27 17:23:51 -0700897// Helper to set up locations for vector memory operations. Returns the memory operand and,
898// if used, sets the output parameter scratch to a temporary register used in this operand,
899// so that the client can release it right after the memory operand use.
900MemOperand InstructionCodeGeneratorARM64::VecAddress(
Aart Bikf8f5a162017-02-06 15:35:29 -0800901 HVecMemoryOperation* instruction,
Aart Bik472821b2017-04-27 17:23:51 -0700902 UseScratchRegisterScope* temps_scope,
903 size_t size,
904 bool is_string_char_at,
905 /*out*/ Register* scratch) {
Aart Bikf8f5a162017-02-06 15:35:29 -0800906 LocationSummary* locations = instruction->GetLocations();
907 Register base = InputRegisterAt(instruction, 0);
Artem Serove1811ed2017-04-27 16:50:47 +0100908
909 if (instruction->InputAt(1)->IsIntermediateAddressIndex()) {
910 DCHECK(!is_string_char_at);
911 return MemOperand(base.X(), InputRegisterAt(instruction, 1).X());
912 }
913
Aart Bikf8f5a162017-02-06 15:35:29 -0800914 Location index = locations->InAt(1);
Aart Bik472821b2017-04-27 17:23:51 -0700915 uint32_t offset = is_string_char_at
916 ? mirror::String::ValueOffset().Uint32Value()
917 : mirror::Array::DataOffset(size).Uint32Value();
918 size_t shift = ComponentSizeShiftWidth(size);
Aart Bikf8f5a162017-02-06 15:35:29 -0800919
Artem Serov0225b772017-04-19 15:43:53 +0100920 // HIntermediateAddress optimization is only applied for scalar ArrayGet and ArraySet.
921 DCHECK(!instruction->InputAt(0)->IsIntermediateAddress());
922
Aart Bikf8f5a162017-02-06 15:35:29 -0800923 if (index.IsConstant()) {
924 offset += Int64ConstantFrom(index) << shift;
Artem Serov0225b772017-04-19 15:43:53 +0100925 return HeapOperand(base, offset);
Aart Bikf8f5a162017-02-06 15:35:29 -0800926 } else {
Aart Bik472821b2017-04-27 17:23:51 -0700927 *scratch = temps_scope->AcquireSameSizeAs(base);
928 __ Add(*scratch, base, Operand(WRegisterFrom(index), LSL, shift));
929 return HeapOperand(*scratch, offset);
Aart Bikf8f5a162017-02-06 15:35:29 -0800930 }
Aart Bikf8f5a162017-02-06 15:35:29 -0800931}
932
933void LocationsBuilderARM64::VisitVecLoad(HVecLoad* instruction) {
934 CreateVecMemLocations(GetGraph()->GetArena(), instruction, /*is_load*/ true);
935}
936
937void InstructionCodeGeneratorARM64::VisitVecLoad(HVecLoad* instruction) {
Aart Bik472821b2017-04-27 17:23:51 -0700938 LocationSummary* locations = instruction->GetLocations();
939 size_t size = Primitive::ComponentSize(instruction->GetPackedType());
940 VRegister reg = VRegisterFrom(locations->Out());
Artem Serov0225b772017-04-19 15:43:53 +0100941 UseScratchRegisterScope temps(GetVIXLAssembler());
Aart Bik472821b2017-04-27 17:23:51 -0700942 Register scratch;
Artem Serov0225b772017-04-19 15:43:53 +0100943
Aart Bikf8f5a162017-02-06 15:35:29 -0800944 switch (instruction->GetPackedType()) {
Aart Bik472821b2017-04-27 17:23:51 -0700945 case Primitive::kPrimChar:
946 DCHECK_EQ(8u, instruction->GetVectorLength());
947 // Special handling of compressed/uncompressed string load.
948 if (mirror::kUseStringCompression && instruction->IsStringCharAt()) {
949 vixl::aarch64::Label uncompressed_load, done;
950 // Test compression bit.
951 static_assert(static_cast<uint32_t>(mirror::StringCompressionFlag::kCompressed) == 0u,
952 "Expecting 0=compressed, 1=uncompressed");
953 uint32_t count_offset = mirror::String::CountOffset().Uint32Value();
954 Register length = temps.AcquireW();
955 __ Ldr(length, HeapOperand(InputRegisterAt(instruction, 0), count_offset));
956 __ Tbnz(length.W(), 0, &uncompressed_load);
957 temps.Release(length); // no longer needed
958 // Zero extend 8 compressed bytes into 8 chars.
959 __ Ldr(DRegisterFrom(locations->Out()).V8B(),
960 VecAddress(instruction, &temps, 1, /*is_string_char_at*/ true, &scratch));
961 __ Uxtl(reg.V8H(), reg.V8B());
962 __ B(&done);
963 if (scratch.IsValid()) {
964 temps.Release(scratch); // if used, no longer needed
965 }
966 // Load 8 direct uncompressed chars.
967 __ Bind(&uncompressed_load);
968 __ Ldr(reg, VecAddress(instruction, &temps, size, /*is_string_char_at*/ true, &scratch));
969 __ Bind(&done);
970 return;
971 }
972 FALLTHROUGH_INTENDED;
Aart Bikf8f5a162017-02-06 15:35:29 -0800973 case Primitive::kPrimBoolean:
974 case Primitive::kPrimByte:
Aart Bikf8f5a162017-02-06 15:35:29 -0800975 case Primitive::kPrimShort:
Aart Bikf8f5a162017-02-06 15:35:29 -0800976 case Primitive::kPrimInt:
977 case Primitive::kPrimFloat:
Artem Serovb31f91f2017-04-05 11:31:19 +0100978 case Primitive::kPrimLong:
979 case Primitive::kPrimDouble:
Artem Serov0225b772017-04-19 15:43:53 +0100980 DCHECK_LE(2u, instruction->GetVectorLength());
981 DCHECK_LE(instruction->GetVectorLength(), 16u);
Aart Bik472821b2017-04-27 17:23:51 -0700982 __ Ldr(reg, VecAddress(instruction, &temps, size, instruction->IsStringCharAt(), &scratch));
Artem Serovb31f91f2017-04-05 11:31:19 +0100983 break;
Aart Bikf8f5a162017-02-06 15:35:29 -0800984 default:
985 LOG(FATAL) << "Unsupported SIMD type";
986 UNREACHABLE();
987 }
988}
989
990void LocationsBuilderARM64::VisitVecStore(HVecStore* instruction) {
991 CreateVecMemLocations(GetGraph()->GetArena(), instruction, /*is_load*/ false);
992}
993
994void InstructionCodeGeneratorARM64::VisitVecStore(HVecStore* instruction) {
Aart Bik472821b2017-04-27 17:23:51 -0700995 LocationSummary* locations = instruction->GetLocations();
996 size_t size = Primitive::ComponentSize(instruction->GetPackedType());
997 VRegister reg = VRegisterFrom(locations->InAt(2));
Artem Serov0225b772017-04-19 15:43:53 +0100998 UseScratchRegisterScope temps(GetVIXLAssembler());
Aart Bik472821b2017-04-27 17:23:51 -0700999 Register scratch;
Artem Serov0225b772017-04-19 15:43:53 +01001000
Aart Bikf8f5a162017-02-06 15:35:29 -08001001 switch (instruction->GetPackedType()) {
1002 case Primitive::kPrimBoolean:
1003 case Primitive::kPrimByte:
Aart Bikf8f5a162017-02-06 15:35:29 -08001004 case Primitive::kPrimChar:
1005 case Primitive::kPrimShort:
Aart Bikf8f5a162017-02-06 15:35:29 -08001006 case Primitive::kPrimInt:
1007 case Primitive::kPrimFloat:
Artem Serovb31f91f2017-04-05 11:31:19 +01001008 case Primitive::kPrimLong:
1009 case Primitive::kPrimDouble:
Artem Serov0225b772017-04-19 15:43:53 +01001010 DCHECK_LE(2u, instruction->GetVectorLength());
1011 DCHECK_LE(instruction->GetVectorLength(), 16u);
Aart Bik472821b2017-04-27 17:23:51 -07001012 __ Str(reg, VecAddress(instruction, &temps, size, /*is_string_char_at*/ false, &scratch));
Artem Serovb31f91f2017-04-05 11:31:19 +01001013 break;
Aart Bikf8f5a162017-02-06 15:35:29 -08001014 default:
1015 LOG(FATAL) << "Unsupported SIMD type";
1016 UNREACHABLE();
1017 }
1018}
1019
1020#undef __
1021
1022} // namespace arm64
1023} // namespace art