blob: ad8128a5b160ca7c94da35ca965985771a9a3496 [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_x86.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
22namespace art {
23namespace x86 {
24
25// NOLINT on __ macro to suppress wrong warning/fix (misc-macro-parentheses) from clang-tidy.
26#define __ down_cast<X86Assembler*>(GetAssembler())-> // NOLINT
27
28void LocationsBuilderX86::VisitVecReplicateScalar(HVecReplicateScalar* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +010029 LocationSummary* locations = new (GetGraph()->GetAllocator()) LocationSummary(instruction);
Aart Bik0148de42017-09-05 09:25:01 -070030 HInstruction* input = instruction->InputAt(0);
31 bool is_zero = IsZeroBitPattern(input);
Aart Bikf8f5a162017-02-06 15:35:29 -080032 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +010033 case DataType::Type::kInt64:
Aart Bik0148de42017-09-05 09:25:01 -070034 // Long needs extra temporary to load from the register pair.
35 if (!is_zero) {
36 locations->AddTemp(Location::RequiresFpuRegister());
37 }
38 FALLTHROUGH_INTENDED;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +010039 case DataType::Type::kBool:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +010040 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +010041 case DataType::Type::kInt8:
42 case DataType::Type::kUint16:
43 case DataType::Type::kInt16:
44 case DataType::Type::kInt32:
Aart Bik0148de42017-09-05 09:25:01 -070045 locations->SetInAt(0, is_zero ? Location::ConstantLocation(input->AsConstant())
46 : Location::RequiresRegister());
47 locations->SetOut(Location::RequiresFpuRegister());
48 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +010049 case DataType::Type::kFloat32:
50 case DataType::Type::kFloat64:
Aart Bik0148de42017-09-05 09:25:01 -070051 locations->SetInAt(0, is_zero ? Location::ConstantLocation(input->AsConstant())
52 : Location::RequiresFpuRegister());
53 locations->SetOut(is_zero ? Location::RequiresFpuRegister()
54 : Location::SameAsFirstInput());
Aart Bik0148de42017-09-05 09:25:01 -070055 break;
56 default:
57 LOG(FATAL) << "Unsupported SIMD type";
58 UNREACHABLE();
59 }
60}
61
62void InstructionCodeGeneratorX86::VisitVecReplicateScalar(HVecReplicateScalar* instruction) {
63 LocationSummary* locations = instruction->GetLocations();
64 XmmRegister dst = locations->Out().AsFpuRegister<XmmRegister>();
65
66 // Shorthand for any type of zero.
67 if (IsZeroBitPattern(instruction->InputAt(0))) {
68 __ xorps(dst, dst);
69 return;
70 }
71
72 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +010073 case DataType::Type::kBool:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +010074 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +010075 case DataType::Type::kInt8:
Aart Bik0148de42017-09-05 09:25:01 -070076 DCHECK_EQ(16u, instruction->GetVectorLength());
77 __ movd(dst, locations->InAt(0).AsRegister<Register>());
78 __ punpcklbw(dst, dst);
79 __ punpcklwd(dst, dst);
80 __ pshufd(dst, dst, Immediate(0));
81 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +010082 case DataType::Type::kUint16:
83 case DataType::Type::kInt16:
Aart Bik0148de42017-09-05 09:25:01 -070084 DCHECK_EQ(8u, instruction->GetVectorLength());
85 __ movd(dst, locations->InAt(0).AsRegister<Register>());
86 __ punpcklwd(dst, dst);
87 __ pshufd(dst, dst, Immediate(0));
88 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +010089 case DataType::Type::kInt32:
Aart Bik0148de42017-09-05 09:25:01 -070090 DCHECK_EQ(4u, instruction->GetVectorLength());
91 __ movd(dst, locations->InAt(0).AsRegister<Register>());
92 __ pshufd(dst, dst, Immediate(0));
93 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +010094 case DataType::Type::kInt64: {
Aart Bik0148de42017-09-05 09:25:01 -070095 XmmRegister tmp = locations->GetTemp(0).AsFpuRegister<XmmRegister>();
96 DCHECK_EQ(2u, instruction->GetVectorLength());
97 __ movd(dst, locations->InAt(0).AsRegisterPairLow<Register>());
98 __ movd(tmp, locations->InAt(0).AsRegisterPairHigh<Register>());
99 __ punpckldq(dst, tmp);
100 __ punpcklqdq(dst, dst);
101 break;
102 }
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100103 case DataType::Type::kFloat32:
Aart Bik0148de42017-09-05 09:25:01 -0700104 DCHECK(locations->InAt(0).Equals(locations->Out()));
105 DCHECK_EQ(4u, instruction->GetVectorLength());
106 __ shufps(dst, dst, Immediate(0));
107 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100108 case DataType::Type::kFloat64:
Aart Bik0148de42017-09-05 09:25:01 -0700109 DCHECK(locations->InAt(0).Equals(locations->Out()));
110 DCHECK_EQ(2u, instruction->GetVectorLength());
111 __ shufpd(dst, dst, Immediate(0));
112 break;
113 default:
114 LOG(FATAL) << "Unsupported SIMD type";
115 UNREACHABLE();
116 }
117}
118
119void LocationsBuilderX86::VisitVecExtractScalar(HVecExtractScalar* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100120 LocationSummary* locations = new (GetGraph()->GetAllocator()) LocationSummary(instruction);
Aart Bik0148de42017-09-05 09:25:01 -0700121 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100122 case DataType::Type::kInt64:
Aart Bik0148de42017-09-05 09:25:01 -0700123 // Long needs extra temporary to store into the register pair.
Aart Bika57b4ee2017-08-30 21:21:41 +0000124 locations->AddTemp(Location::RequiresFpuRegister());
Aart Bik9879d0e2017-08-15 10:51:25 -0700125 FALLTHROUGH_INTENDED;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100126 case DataType::Type::kBool:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100127 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100128 case DataType::Type::kInt8:
129 case DataType::Type::kUint16:
130 case DataType::Type::kInt16:
131 case DataType::Type::kInt32:
Aart Bik0148de42017-09-05 09:25:01 -0700132 locations->SetInAt(0, Location::RequiresFpuRegister());
133 locations->SetOut(Location::RequiresRegister());
Aart Bik9879d0e2017-08-15 10:51:25 -0700134 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100135 case DataType::Type::kFloat32:
136 case DataType::Type::kFloat64:
Aart Bika57b4ee2017-08-30 21:21:41 +0000137 locations->SetInAt(0, Location::RequiresFpuRegister());
Aart Bik9879d0e2017-08-15 10:51:25 -0700138 locations->SetOut(Location::SameAsFirstInput());
139 break;
140 default:
141 LOG(FATAL) << "Unsupported SIMD type";
142 UNREACHABLE();
143 }
144}
145
Aart Bik0148de42017-09-05 09:25:01 -0700146void InstructionCodeGeneratorX86::VisitVecExtractScalar(HVecExtractScalar* instruction) {
Aart Bik9879d0e2017-08-15 10:51:25 -0700147 LocationSummary* locations = instruction->GetLocations();
Aart Bik0148de42017-09-05 09:25:01 -0700148 XmmRegister src = locations->InAt(0).AsFpuRegister<XmmRegister>();
Aart Bik9879d0e2017-08-15 10:51:25 -0700149 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100150 case DataType::Type::kBool:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100151 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100152 case DataType::Type::kInt8:
153 case DataType::Type::kUint16:
154 case DataType::Type::kInt16: // TODO: up to here, and?
Aart Bik0148de42017-09-05 09:25:01 -0700155 LOG(FATAL) << "Unsupported SIMD type";
156 UNREACHABLE();
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100157 case DataType::Type::kInt32:
Aart Bik0148de42017-09-05 09:25:01 -0700158 DCHECK_LE(4u, instruction->GetVectorLength());
159 DCHECK_LE(instruction->GetVectorLength(), 16u);
160 __ movd(locations->Out().AsRegister<Register>(), src);
Aart Bik9879d0e2017-08-15 10:51:25 -0700161 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100162 case DataType::Type::kInt64: {
Aart Bik9879d0e2017-08-15 10:51:25 -0700163 XmmRegister tmp = locations->GetTemp(0).AsFpuRegister<XmmRegister>();
164 DCHECK_EQ(2u, instruction->GetVectorLength());
Aart Bik0148de42017-09-05 09:25:01 -0700165 __ movd(locations->Out().AsRegisterPairLow<Register>(), src);
166 __ pshufd(tmp, src, Immediate(1));
167 __ movd(locations->Out().AsRegisterPairHigh<Register>(), tmp);
Aart Bik9879d0e2017-08-15 10:51:25 -0700168 break;
169 }
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100170 case DataType::Type::kFloat32:
171 case DataType::Type::kFloat64:
Aart Bik0148de42017-09-05 09:25:01 -0700172 DCHECK_LE(2u, instruction->GetVectorLength());
173 DCHECK_LE(instruction->GetVectorLength(), 4u);
174 DCHECK(locations->InAt(0).Equals(locations->Out())); // no code required
Aart Bik9879d0e2017-08-15 10:51:25 -0700175 break;
176 default:
177 LOG(FATAL) << "Unsupported SIMD type";
178 UNREACHABLE();
179 }
180}
181
Aart Bikf8f5a162017-02-06 15:35:29 -0800182// Helper to set up locations for vector unary operations.
Vladimir Markoe764d2e2017-10-05 14:35:55 +0100183static void CreateVecUnOpLocations(ArenaAllocator* allocator, HVecUnaryOperation* instruction) {
184 LocationSummary* locations = new (allocator) LocationSummary(instruction);
Aart Bikf8f5a162017-02-06 15:35:29 -0800185 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100186 case DataType::Type::kBool:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100187 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100188 case DataType::Type::kInt8:
189 case DataType::Type::kUint16:
190 case DataType::Type::kInt16:
191 case DataType::Type::kInt32:
192 case DataType::Type::kInt64:
193 case DataType::Type::kFloat32:
194 case DataType::Type::kFloat64:
Aart Bikf8f5a162017-02-06 15:35:29 -0800195 locations->SetInAt(0, Location::RequiresFpuRegister());
196 locations->SetOut(Location::RequiresFpuRegister());
197 break;
198 default:
199 LOG(FATAL) << "Unsupported SIMD type";
200 UNREACHABLE();
201 }
202}
203
Aart Bik0148de42017-09-05 09:25:01 -0700204void LocationsBuilderX86::VisitVecReduce(HVecReduce* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100205 CreateVecUnOpLocations(GetGraph()->GetAllocator(), instruction);
Aart Bik0148de42017-09-05 09:25:01 -0700206 // Long reduction or min/max require a temporary.
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100207 if (instruction->GetPackedType() == DataType::Type::kInt64 ||
Aart Bik0148de42017-09-05 09:25:01 -0700208 instruction->GetKind() == HVecReduce::kMin ||
209 instruction->GetKind() == HVecReduce::kMax) {
210 instruction->GetLocations()->AddTemp(Location::RequiresFpuRegister());
211 }
212}
213
214void InstructionCodeGeneratorX86::VisitVecReduce(HVecReduce* instruction) {
215 LocationSummary* locations = instruction->GetLocations();
216 XmmRegister src = locations->InAt(0).AsFpuRegister<XmmRegister>();
217 XmmRegister dst = locations->Out().AsFpuRegister<XmmRegister>();
218 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100219 case DataType::Type::kInt32:
Aart Bik0148de42017-09-05 09:25:01 -0700220 DCHECK_EQ(4u, instruction->GetVectorLength());
221 switch (instruction->GetKind()) {
222 case HVecReduce::kSum:
223 __ movaps(dst, src);
224 __ phaddd(dst, dst);
225 __ phaddd(dst, dst);
226 break;
227 case HVecReduce::kMin: {
228 XmmRegister tmp = locations->GetTemp(0).AsFpuRegister<XmmRegister>();
229 __ movaps(tmp, src);
230 __ movaps(dst, src);
231 __ psrldq(tmp, Immediate(8));
232 __ pminsd(dst, tmp);
233 __ psrldq(tmp, Immediate(4));
234 __ pminsd(dst, tmp);
235 break;
236 }
237 case HVecReduce::kMax: {
238 XmmRegister tmp = locations->GetTemp(0).AsFpuRegister<XmmRegister>();
239 __ movaps(tmp, src);
240 __ movaps(dst, src);
241 __ psrldq(tmp, Immediate(8));
242 __ pmaxsd(dst, tmp);
243 __ psrldq(tmp, Immediate(4));
244 __ pmaxsd(dst, tmp);
245 break;
246 }
247 }
248 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100249 case DataType::Type::kInt64: {
Aart Bik0148de42017-09-05 09:25:01 -0700250 DCHECK_EQ(2u, instruction->GetVectorLength());
251 XmmRegister tmp = locations->GetTemp(0).AsFpuRegister<XmmRegister>();
252 switch (instruction->GetKind()) {
253 case HVecReduce::kSum:
254 __ movaps(tmp, src);
255 __ movaps(dst, src);
256 __ punpckhqdq(tmp, tmp);
257 __ paddq(dst, tmp);
258 break;
259 case HVecReduce::kMin:
260 case HVecReduce::kMax:
261 LOG(FATAL) << "Unsupported SIMD type";
262 }
263 break;
264 }
265 default:
266 LOG(FATAL) << "Unsupported SIMD type";
267 UNREACHABLE();
268 }
269}
270
Aart Bikf8f5a162017-02-06 15:35:29 -0800271void LocationsBuilderX86::VisitVecCnv(HVecCnv* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100272 CreateVecUnOpLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikf8f5a162017-02-06 15:35:29 -0800273}
274
275void InstructionCodeGeneratorX86::VisitVecCnv(HVecCnv* instruction) {
276 LocationSummary* locations = instruction->GetLocations();
277 XmmRegister src = locations->InAt(0).AsFpuRegister<XmmRegister>();
278 XmmRegister dst = locations->Out().AsFpuRegister<XmmRegister>();
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100279 DataType::Type from = instruction->GetInputType();
280 DataType::Type to = instruction->GetResultType();
281 if (from == DataType::Type::kInt32 && to == DataType::Type::kFloat32) {
Aart Bikf8f5a162017-02-06 15:35:29 -0800282 DCHECK_EQ(4u, instruction->GetVectorLength());
283 __ cvtdq2ps(dst, src);
284 } else {
285 LOG(FATAL) << "Unsupported SIMD type";
286 }
287}
288
289void LocationsBuilderX86::VisitVecNeg(HVecNeg* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100290 CreateVecUnOpLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikf8f5a162017-02-06 15:35:29 -0800291}
292
293void InstructionCodeGeneratorX86::VisitVecNeg(HVecNeg* instruction) {
294 LocationSummary* locations = instruction->GetLocations();
295 XmmRegister src = locations->InAt(0).AsFpuRegister<XmmRegister>();
296 XmmRegister dst = locations->Out().AsFpuRegister<XmmRegister>();
297 switch (instruction->GetPackedType()) {
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100298 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100299 case DataType::Type::kInt8:
Aart Bikf8f5a162017-02-06 15:35:29 -0800300 DCHECK_EQ(16u, instruction->GetVectorLength());
301 __ pxor(dst, dst);
302 __ psubb(dst, src);
303 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100304 case DataType::Type::kUint16:
305 case DataType::Type::kInt16:
Aart Bikf8f5a162017-02-06 15:35:29 -0800306 DCHECK_EQ(8u, instruction->GetVectorLength());
307 __ pxor(dst, dst);
308 __ psubw(dst, src);
309 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100310 case DataType::Type::kInt32:
Aart Bikf8f5a162017-02-06 15:35:29 -0800311 DCHECK_EQ(4u, instruction->GetVectorLength());
312 __ pxor(dst, dst);
313 __ psubd(dst, src);
314 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100315 case DataType::Type::kInt64:
Aart Bikf8f5a162017-02-06 15:35:29 -0800316 DCHECK_EQ(2u, instruction->GetVectorLength());
317 __ pxor(dst, dst);
318 __ psubq(dst, src);
319 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100320 case DataType::Type::kFloat32:
Aart Bikf8f5a162017-02-06 15:35:29 -0800321 DCHECK_EQ(4u, instruction->GetVectorLength());
322 __ xorps(dst, dst);
323 __ subps(dst, src);
324 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100325 case DataType::Type::kFloat64:
Aart Bikf8f5a162017-02-06 15:35:29 -0800326 DCHECK_EQ(2u, instruction->GetVectorLength());
327 __ xorpd(dst, dst);
328 __ subpd(dst, src);
329 break;
330 default:
331 LOG(FATAL) << "Unsupported SIMD type";
332 UNREACHABLE();
333 }
334}
335
Aart Bik6daebeb2017-04-03 14:35:41 -0700336void LocationsBuilderX86::VisitVecAbs(HVecAbs* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100337 CreateVecUnOpLocations(GetGraph()->GetAllocator(), instruction);
Aart Bik472821b2017-04-27 17:23:51 -0700338 // Integral-abs requires a temporary for the comparison.
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100339 if (instruction->GetPackedType() == DataType::Type::kInt32) {
Aart Bik6daebeb2017-04-03 14:35:41 -0700340 instruction->GetLocations()->AddTemp(Location::RequiresFpuRegister());
341 }
342}
343
344void InstructionCodeGeneratorX86::VisitVecAbs(HVecAbs* instruction) {
345 LocationSummary* locations = instruction->GetLocations();
346 XmmRegister src = locations->InAt(0).AsFpuRegister<XmmRegister>();
347 XmmRegister dst = locations->Out().AsFpuRegister<XmmRegister>();
348 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100349 case DataType::Type::kInt32: {
Aart Bik6daebeb2017-04-03 14:35:41 -0700350 DCHECK_EQ(4u, instruction->GetVectorLength());
351 XmmRegister tmp = locations->GetTemp(0).AsFpuRegister<XmmRegister>();
352 __ movaps(dst, src);
353 __ pxor(tmp, tmp);
354 __ pcmpgtd(tmp, dst);
355 __ pxor(dst, tmp);
356 __ psubd(dst, tmp);
357 break;
358 }
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100359 case DataType::Type::kFloat32:
Aart Bik6daebeb2017-04-03 14:35:41 -0700360 DCHECK_EQ(4u, instruction->GetVectorLength());
361 __ pcmpeqb(dst, dst); // all ones
362 __ psrld(dst, Immediate(1));
363 __ andps(dst, src);
364 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100365 case DataType::Type::kFloat64:
Aart Bik6daebeb2017-04-03 14:35:41 -0700366 DCHECK_EQ(2u, instruction->GetVectorLength());
367 __ pcmpeqb(dst, dst); // all ones
368 __ psrlq(dst, Immediate(1));
369 __ andpd(dst, src);
370 break;
371 default:
372 LOG(FATAL) << "Unsupported SIMD type";
373 UNREACHABLE();
374 }
375}
376
Aart Bikf8f5a162017-02-06 15:35:29 -0800377void LocationsBuilderX86::VisitVecNot(HVecNot* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100378 CreateVecUnOpLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikf8f5a162017-02-06 15:35:29 -0800379 // Boolean-not requires a temporary to construct the 16 x one.
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100380 if (instruction->GetPackedType() == DataType::Type::kBool) {
Aart Bikf8f5a162017-02-06 15:35:29 -0800381 instruction->GetLocations()->AddTemp(Location::RequiresFpuRegister());
382 }
383}
384
385void InstructionCodeGeneratorX86::VisitVecNot(HVecNot* instruction) {
386 LocationSummary* locations = instruction->GetLocations();
387 XmmRegister src = locations->InAt(0).AsFpuRegister<XmmRegister>();
388 XmmRegister dst = locations->Out().AsFpuRegister<XmmRegister>();
389 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100390 case DataType::Type::kBool: { // special case boolean-not
Aart Bikf8f5a162017-02-06 15:35:29 -0800391 DCHECK_EQ(16u, instruction->GetVectorLength());
392 XmmRegister tmp = locations->GetTemp(0).AsFpuRegister<XmmRegister>();
393 __ pxor(dst, dst);
394 __ pcmpeqb(tmp, tmp); // all ones
395 __ psubb(dst, tmp); // 16 x one
396 __ pxor(dst, src);
397 break;
398 }
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100399 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100400 case DataType::Type::kInt8:
401 case DataType::Type::kUint16:
402 case DataType::Type::kInt16:
403 case DataType::Type::kInt32:
404 case DataType::Type::kInt64:
Aart Bikf8f5a162017-02-06 15:35:29 -0800405 DCHECK_LE(2u, instruction->GetVectorLength());
406 DCHECK_LE(instruction->GetVectorLength(), 16u);
407 __ pcmpeqb(dst, dst); // all ones
408 __ pxor(dst, src);
409 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100410 case DataType::Type::kFloat32:
Aart Bikf8f5a162017-02-06 15:35:29 -0800411 DCHECK_EQ(4u, instruction->GetVectorLength());
412 __ pcmpeqb(dst, dst); // all ones
413 __ xorps(dst, src);
414 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100415 case DataType::Type::kFloat64:
Aart Bikf8f5a162017-02-06 15:35:29 -0800416 DCHECK_EQ(2u, instruction->GetVectorLength());
417 __ pcmpeqb(dst, dst); // all ones
418 __ xorpd(dst, src);
419 break;
420 default:
421 LOG(FATAL) << "Unsupported SIMD type";
422 UNREACHABLE();
423 }
424}
425
426// Helper to set up locations for vector binary operations.
Vladimir Markoe764d2e2017-10-05 14:35:55 +0100427static void CreateVecBinOpLocations(ArenaAllocator* allocator, HVecBinaryOperation* instruction) {
428 LocationSummary* locations = new (allocator) LocationSummary(instruction);
Aart Bikf8f5a162017-02-06 15:35:29 -0800429 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100430 case DataType::Type::kBool:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100431 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100432 case DataType::Type::kInt8:
433 case DataType::Type::kUint16:
434 case DataType::Type::kInt16:
435 case DataType::Type::kInt32:
436 case DataType::Type::kInt64:
437 case DataType::Type::kFloat32:
438 case DataType::Type::kFloat64:
Aart Bikf8f5a162017-02-06 15:35:29 -0800439 locations->SetInAt(0, Location::RequiresFpuRegister());
440 locations->SetInAt(1, Location::RequiresFpuRegister());
441 locations->SetOut(Location::SameAsFirstInput());
442 break;
443 default:
444 LOG(FATAL) << "Unsupported SIMD type";
445 UNREACHABLE();
446 }
447}
448
449void LocationsBuilderX86::VisitVecAdd(HVecAdd* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100450 CreateVecBinOpLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikf8f5a162017-02-06 15:35:29 -0800451}
452
453void InstructionCodeGeneratorX86::VisitVecAdd(HVecAdd* instruction) {
454 LocationSummary* locations = instruction->GetLocations();
455 DCHECK(locations->InAt(0).Equals(locations->Out()));
456 XmmRegister src = locations->InAt(1).AsFpuRegister<XmmRegister>();
457 XmmRegister dst = locations->Out().AsFpuRegister<XmmRegister>();
458 switch (instruction->GetPackedType()) {
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100459 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100460 case DataType::Type::kInt8:
Aart Bikf8f5a162017-02-06 15:35:29 -0800461 DCHECK_EQ(16u, instruction->GetVectorLength());
462 __ paddb(dst, src);
463 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100464 case DataType::Type::kUint16:
465 case DataType::Type::kInt16:
Aart Bikf8f5a162017-02-06 15:35:29 -0800466 DCHECK_EQ(8u, instruction->GetVectorLength());
467 __ paddw(dst, src);
468 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100469 case DataType::Type::kInt32:
Aart Bikf8f5a162017-02-06 15:35:29 -0800470 DCHECK_EQ(4u, instruction->GetVectorLength());
471 __ paddd(dst, src);
472 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100473 case DataType::Type::kInt64:
Aart Bikf8f5a162017-02-06 15:35:29 -0800474 DCHECK_EQ(2u, instruction->GetVectorLength());
475 __ paddq(dst, src);
476 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100477 case DataType::Type::kFloat32:
Aart Bikf8f5a162017-02-06 15:35:29 -0800478 DCHECK_EQ(4u, instruction->GetVectorLength());
479 __ addps(dst, src);
480 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100481 case DataType::Type::kFloat64:
Aart Bikf8f5a162017-02-06 15:35:29 -0800482 DCHECK_EQ(2u, instruction->GetVectorLength());
483 __ addpd(dst, src);
484 break;
485 default:
486 LOG(FATAL) << "Unsupported SIMD type";
487 UNREACHABLE();
488 }
489}
490
Aart Bikf3e61ee2017-04-12 17:09:20 -0700491void LocationsBuilderX86::VisitVecHalvingAdd(HVecHalvingAdd* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100492 CreateVecBinOpLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikf3e61ee2017-04-12 17:09:20 -0700493}
494
495void InstructionCodeGeneratorX86::VisitVecHalvingAdd(HVecHalvingAdd* instruction) {
496 LocationSummary* locations = instruction->GetLocations();
497 DCHECK(locations->InAt(0).Equals(locations->Out()));
498 XmmRegister src = locations->InAt(1).AsFpuRegister<XmmRegister>();
499 XmmRegister dst = locations->Out().AsFpuRegister<XmmRegister>();
500
501 DCHECK(instruction->IsRounded());
Aart Bikf3e61ee2017-04-12 17:09:20 -0700502
503 switch (instruction->GetPackedType()) {
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100504 case DataType::Type::kUint8:
Aart Bikf3e61ee2017-04-12 17:09:20 -0700505 DCHECK_EQ(16u, instruction->GetVectorLength());
506 __ pavgb(dst, src);
507 return;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100508 case DataType::Type::kUint16:
Aart Bikf3e61ee2017-04-12 17:09:20 -0700509 DCHECK_EQ(8u, instruction->GetVectorLength());
510 __ pavgw(dst, src);
511 return;
512 default:
513 LOG(FATAL) << "Unsupported SIMD type";
514 UNREACHABLE();
515 }
516}
517
Aart Bikf8f5a162017-02-06 15:35:29 -0800518void LocationsBuilderX86::VisitVecSub(HVecSub* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100519 CreateVecBinOpLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikf8f5a162017-02-06 15:35:29 -0800520}
521
522void InstructionCodeGeneratorX86::VisitVecSub(HVecSub* instruction) {
523 LocationSummary* locations = instruction->GetLocations();
524 DCHECK(locations->InAt(0).Equals(locations->Out()));
525 XmmRegister src = locations->InAt(1).AsFpuRegister<XmmRegister>();
526 XmmRegister dst = locations->Out().AsFpuRegister<XmmRegister>();
527 switch (instruction->GetPackedType()) {
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100528 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100529 case DataType::Type::kInt8:
Aart Bikf8f5a162017-02-06 15:35:29 -0800530 DCHECK_EQ(16u, instruction->GetVectorLength());
531 __ psubb(dst, src);
532 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100533 case DataType::Type::kUint16:
534 case DataType::Type::kInt16:
Aart Bikf8f5a162017-02-06 15:35:29 -0800535 DCHECK_EQ(8u, instruction->GetVectorLength());
536 __ psubw(dst, src);
537 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100538 case DataType::Type::kInt32:
Aart Bikf8f5a162017-02-06 15:35:29 -0800539 DCHECK_EQ(4u, instruction->GetVectorLength());
540 __ psubd(dst, src);
541 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100542 case DataType::Type::kInt64:
Aart Bikf8f5a162017-02-06 15:35:29 -0800543 DCHECK_EQ(2u, instruction->GetVectorLength());
544 __ psubq(dst, src);
545 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100546 case DataType::Type::kFloat32:
Aart Bikf8f5a162017-02-06 15:35:29 -0800547 DCHECK_EQ(4u, instruction->GetVectorLength());
548 __ subps(dst, src);
549 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100550 case DataType::Type::kFloat64:
Aart Bikf8f5a162017-02-06 15:35:29 -0800551 DCHECK_EQ(2u, instruction->GetVectorLength());
552 __ subpd(dst, src);
553 break;
554 default:
555 LOG(FATAL) << "Unsupported SIMD type";
556 UNREACHABLE();
557 }
558}
559
560void LocationsBuilderX86::VisitVecMul(HVecMul* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100561 CreateVecBinOpLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikf8f5a162017-02-06 15:35:29 -0800562}
563
564void InstructionCodeGeneratorX86::VisitVecMul(HVecMul* instruction) {
565 LocationSummary* locations = instruction->GetLocations();
566 DCHECK(locations->InAt(0).Equals(locations->Out()));
567 XmmRegister src = locations->InAt(1).AsFpuRegister<XmmRegister>();
568 XmmRegister dst = locations->Out().AsFpuRegister<XmmRegister>();
569 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100570 case DataType::Type::kUint16:
571 case DataType::Type::kInt16:
Aart Bikf8f5a162017-02-06 15:35:29 -0800572 DCHECK_EQ(8u, instruction->GetVectorLength());
573 __ pmullw(dst, src);
574 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100575 case DataType::Type::kInt32:
Aart Bikf8f5a162017-02-06 15:35:29 -0800576 DCHECK_EQ(4u, instruction->GetVectorLength());
577 __ pmulld(dst, src);
578 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100579 case DataType::Type::kFloat32:
Aart Bikf8f5a162017-02-06 15:35:29 -0800580 DCHECK_EQ(4u, instruction->GetVectorLength());
581 __ mulps(dst, src);
582 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100583 case DataType::Type::kFloat64:
Aart Bikf8f5a162017-02-06 15:35:29 -0800584 DCHECK_EQ(2u, instruction->GetVectorLength());
585 __ mulpd(dst, src);
586 break;
587 default:
588 LOG(FATAL) << "Unsupported SIMD type";
589 UNREACHABLE();
590 }
591}
592
593void LocationsBuilderX86::VisitVecDiv(HVecDiv* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100594 CreateVecBinOpLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikf8f5a162017-02-06 15:35:29 -0800595}
596
597void InstructionCodeGeneratorX86::VisitVecDiv(HVecDiv* instruction) {
598 LocationSummary* locations = instruction->GetLocations();
599 DCHECK(locations->InAt(0).Equals(locations->Out()));
600 XmmRegister src = locations->InAt(1).AsFpuRegister<XmmRegister>();
601 XmmRegister dst = locations->Out().AsFpuRegister<XmmRegister>();
602 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100603 case DataType::Type::kFloat32:
Aart Bikf8f5a162017-02-06 15:35:29 -0800604 DCHECK_EQ(4u, instruction->GetVectorLength());
605 __ divps(dst, src);
606 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100607 case DataType::Type::kFloat64:
Aart Bikf8f5a162017-02-06 15:35:29 -0800608 DCHECK_EQ(2u, instruction->GetVectorLength());
609 __ divpd(dst, src);
610 break;
611 default:
612 LOG(FATAL) << "Unsupported SIMD type";
613 UNREACHABLE();
614 }
615}
616
Aart Bikf3e61ee2017-04-12 17:09:20 -0700617void LocationsBuilderX86::VisitVecMin(HVecMin* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100618 CreateVecBinOpLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikf3e61ee2017-04-12 17:09:20 -0700619}
620
621void InstructionCodeGeneratorX86::VisitVecMin(HVecMin* instruction) {
Aart Bikc8e93c72017-05-10 10:49:22 -0700622 LocationSummary* locations = instruction->GetLocations();
623 DCHECK(locations->InAt(0).Equals(locations->Out()));
624 XmmRegister src = locations->InAt(1).AsFpuRegister<XmmRegister>();
625 XmmRegister dst = locations->Out().AsFpuRegister<XmmRegister>();
626 switch (instruction->GetPackedType()) {
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100627 case DataType::Type::kUint8:
628 DCHECK_EQ(16u, instruction->GetVectorLength());
629 __ pminub(dst, src);
630 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100631 case DataType::Type::kInt8:
Aart Bikc8e93c72017-05-10 10:49:22 -0700632 DCHECK_EQ(16u, instruction->GetVectorLength());
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100633 __ pminsb(dst, src);
Aart Bikc8e93c72017-05-10 10:49:22 -0700634 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100635 case DataType::Type::kUint16:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100636 DCHECK_EQ(8u, instruction->GetVectorLength());
637 __ pminuw(dst, src);
638 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100639 case DataType::Type::kInt16:
Aart Bikc8e93c72017-05-10 10:49:22 -0700640 DCHECK_EQ(8u, instruction->GetVectorLength());
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100641 __ pminsw(dst, src);
Aart Bikc8e93c72017-05-10 10:49:22 -0700642 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100643 case DataType::Type::kInt32:
Aart Bikc8e93c72017-05-10 10:49:22 -0700644 DCHECK_EQ(4u, instruction->GetVectorLength());
645 if (instruction->IsUnsigned()) {
646 __ pminud(dst, src);
647 } else {
648 __ pminsd(dst, src);
649 }
650 break;
651 // Next cases are sloppy wrt 0.0 vs -0.0.
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100652 case DataType::Type::kFloat32:
Aart Bikc8e93c72017-05-10 10:49:22 -0700653 DCHECK_EQ(4u, instruction->GetVectorLength());
654 DCHECK(!instruction->IsUnsigned());
655 __ minps(dst, src);
656 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100657 case DataType::Type::kFloat64:
Aart Bikc8e93c72017-05-10 10:49:22 -0700658 DCHECK_EQ(2u, instruction->GetVectorLength());
659 DCHECK(!instruction->IsUnsigned());
660 __ minpd(dst, src);
661 break;
662 default:
663 LOG(FATAL) << "Unsupported SIMD type";
664 UNREACHABLE();
665 }
Aart Bikf3e61ee2017-04-12 17:09:20 -0700666}
667
668void LocationsBuilderX86::VisitVecMax(HVecMax* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100669 CreateVecBinOpLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikf3e61ee2017-04-12 17:09:20 -0700670}
671
672void InstructionCodeGeneratorX86::VisitVecMax(HVecMax* instruction) {
Aart Bikc8e93c72017-05-10 10:49:22 -0700673 LocationSummary* locations = instruction->GetLocations();
674 DCHECK(locations->InAt(0).Equals(locations->Out()));
675 XmmRegister src = locations->InAt(1).AsFpuRegister<XmmRegister>();
676 XmmRegister dst = locations->Out().AsFpuRegister<XmmRegister>();
677 switch (instruction->GetPackedType()) {
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100678 case DataType::Type::kUint8:
679 DCHECK_EQ(16u, instruction->GetVectorLength());
680 __ pmaxub(dst, src);
681 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100682 case DataType::Type::kInt8:
Aart Bikc8e93c72017-05-10 10:49:22 -0700683 DCHECK_EQ(16u, instruction->GetVectorLength());
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100684 __ pmaxsb(dst, src);
Aart Bikc8e93c72017-05-10 10:49:22 -0700685 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100686 case DataType::Type::kUint16:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100687 DCHECK_EQ(8u, instruction->GetVectorLength());
688 __ pmaxuw(dst, src);
689 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100690 case DataType::Type::kInt16:
Aart Bikc8e93c72017-05-10 10:49:22 -0700691 DCHECK_EQ(8u, instruction->GetVectorLength());
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100692 __ pmaxsw(dst, src);
Aart Bikc8e93c72017-05-10 10:49:22 -0700693 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100694 case DataType::Type::kInt32:
Aart Bikc8e93c72017-05-10 10:49:22 -0700695 DCHECK_EQ(4u, instruction->GetVectorLength());
696 if (instruction->IsUnsigned()) {
697 __ pmaxud(dst, src);
698 } else {
699 __ pmaxsd(dst, src);
700 }
701 break;
702 // Next cases are sloppy wrt 0.0 vs -0.0.
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100703 case DataType::Type::kFloat32:
Aart Bikc8e93c72017-05-10 10:49:22 -0700704 DCHECK_EQ(4u, instruction->GetVectorLength());
705 DCHECK(!instruction->IsUnsigned());
706 __ maxps(dst, src);
707 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100708 case DataType::Type::kFloat64:
Aart Bikc8e93c72017-05-10 10:49:22 -0700709 DCHECK_EQ(2u, instruction->GetVectorLength());
710 DCHECK(!instruction->IsUnsigned());
711 __ maxpd(dst, src);
712 break;
713 default:
714 LOG(FATAL) << "Unsupported SIMD type";
715 UNREACHABLE();
716 }
Aart Bikf3e61ee2017-04-12 17:09:20 -0700717}
718
Aart Bikf8f5a162017-02-06 15:35:29 -0800719void LocationsBuilderX86::VisitVecAnd(HVecAnd* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100720 CreateVecBinOpLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikf8f5a162017-02-06 15:35:29 -0800721}
722
723void InstructionCodeGeneratorX86::VisitVecAnd(HVecAnd* instruction) {
724 LocationSummary* locations = instruction->GetLocations();
725 DCHECK(locations->InAt(0).Equals(locations->Out()));
726 XmmRegister src = locations->InAt(1).AsFpuRegister<XmmRegister>();
727 XmmRegister dst = locations->Out().AsFpuRegister<XmmRegister>();
728 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100729 case DataType::Type::kBool:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100730 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100731 case DataType::Type::kInt8:
732 case DataType::Type::kUint16:
733 case DataType::Type::kInt16:
734 case DataType::Type::kInt32:
735 case DataType::Type::kInt64:
Aart Bikf8f5a162017-02-06 15:35:29 -0800736 DCHECK_LE(2u, instruction->GetVectorLength());
737 DCHECK_LE(instruction->GetVectorLength(), 16u);
738 __ pand(dst, src);
739 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100740 case DataType::Type::kFloat32:
Aart Bikf8f5a162017-02-06 15:35:29 -0800741 DCHECK_EQ(4u, instruction->GetVectorLength());
742 __ andps(dst, src);
743 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100744 case DataType::Type::kFloat64:
Aart Bikf8f5a162017-02-06 15:35:29 -0800745 DCHECK_EQ(2u, instruction->GetVectorLength());
746 __ andpd(dst, src);
747 break;
748 default:
749 LOG(FATAL) << "Unsupported SIMD type";
750 UNREACHABLE();
751 }
752}
753
754void LocationsBuilderX86::VisitVecAndNot(HVecAndNot* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100755 CreateVecBinOpLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikf8f5a162017-02-06 15:35:29 -0800756}
757
758void InstructionCodeGeneratorX86::VisitVecAndNot(HVecAndNot* instruction) {
759 LocationSummary* locations = instruction->GetLocations();
760 DCHECK(locations->InAt(0).Equals(locations->Out()));
761 XmmRegister src = locations->InAt(1).AsFpuRegister<XmmRegister>();
762 XmmRegister dst = locations->Out().AsFpuRegister<XmmRegister>();
763 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100764 case DataType::Type::kBool:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100765 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100766 case DataType::Type::kInt8:
767 case DataType::Type::kUint16:
768 case DataType::Type::kInt16:
769 case DataType::Type::kInt32:
770 case DataType::Type::kInt64:
Aart Bikf8f5a162017-02-06 15:35:29 -0800771 DCHECK_LE(2u, instruction->GetVectorLength());
772 DCHECK_LE(instruction->GetVectorLength(), 16u);
773 __ pandn(dst, src);
774 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100775 case DataType::Type::kFloat32:
Aart Bikf8f5a162017-02-06 15:35:29 -0800776 DCHECK_EQ(4u, instruction->GetVectorLength());
777 __ andnps(dst, src);
778 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100779 case DataType::Type::kFloat64:
Aart Bikf8f5a162017-02-06 15:35:29 -0800780 DCHECK_EQ(2u, instruction->GetVectorLength());
781 __ andnpd(dst, src);
782 break;
783 default:
784 LOG(FATAL) << "Unsupported SIMD type";
785 UNREACHABLE();
786 }
787}
788
789void LocationsBuilderX86::VisitVecOr(HVecOr* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100790 CreateVecBinOpLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikf8f5a162017-02-06 15:35:29 -0800791}
792
793void InstructionCodeGeneratorX86::VisitVecOr(HVecOr* instruction) {
794 LocationSummary* locations = instruction->GetLocations();
795 DCHECK(locations->InAt(0).Equals(locations->Out()));
796 XmmRegister src = locations->InAt(1).AsFpuRegister<XmmRegister>();
797 XmmRegister dst = locations->Out().AsFpuRegister<XmmRegister>();
798 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100799 case DataType::Type::kBool:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100800 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100801 case DataType::Type::kInt8:
802 case DataType::Type::kUint16:
803 case DataType::Type::kInt16:
804 case DataType::Type::kInt32:
805 case DataType::Type::kInt64:
Aart Bikf8f5a162017-02-06 15:35:29 -0800806 DCHECK_LE(2u, instruction->GetVectorLength());
807 DCHECK_LE(instruction->GetVectorLength(), 16u);
808 __ por(dst, src);
809 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100810 case DataType::Type::kFloat32:
Aart Bikf8f5a162017-02-06 15:35:29 -0800811 DCHECK_EQ(4u, instruction->GetVectorLength());
812 __ orps(dst, src);
813 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100814 case DataType::Type::kFloat64:
Aart Bikf8f5a162017-02-06 15:35:29 -0800815 DCHECK_EQ(2u, instruction->GetVectorLength());
816 __ orpd(dst, src);
817 break;
818 default:
819 LOG(FATAL) << "Unsupported SIMD type";
820 UNREACHABLE();
821 }
822}
823
824void LocationsBuilderX86::VisitVecXor(HVecXor* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100825 CreateVecBinOpLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikf8f5a162017-02-06 15:35:29 -0800826}
827
828void InstructionCodeGeneratorX86::VisitVecXor(HVecXor* instruction) {
829 LocationSummary* locations = instruction->GetLocations();
830 DCHECK(locations->InAt(0).Equals(locations->Out()));
831 XmmRegister src = locations->InAt(1).AsFpuRegister<XmmRegister>();
832 XmmRegister dst = locations->Out().AsFpuRegister<XmmRegister>();
833 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100834 case DataType::Type::kBool:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100835 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100836 case DataType::Type::kInt8:
837 case DataType::Type::kUint16:
838 case DataType::Type::kInt16:
839 case DataType::Type::kInt32:
840 case DataType::Type::kInt64:
Aart Bikf8f5a162017-02-06 15:35:29 -0800841 DCHECK_LE(2u, instruction->GetVectorLength());
842 DCHECK_LE(instruction->GetVectorLength(), 16u);
843 __ pxor(dst, src);
844 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100845 case DataType::Type::kFloat32:
Aart Bikf8f5a162017-02-06 15:35:29 -0800846 DCHECK_EQ(4u, instruction->GetVectorLength());
847 __ xorps(dst, src);
848 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100849 case DataType::Type::kFloat64:
Aart Bikf8f5a162017-02-06 15:35:29 -0800850 DCHECK_EQ(2u, instruction->GetVectorLength());
851 __ xorpd(dst, src);
852 break;
853 default:
854 LOG(FATAL) << "Unsupported SIMD type";
855 UNREACHABLE();
856 }
857}
858
859// Helper to set up locations for vector shift operations.
Vladimir Markoe764d2e2017-10-05 14:35:55 +0100860static void CreateVecShiftLocations(ArenaAllocator* allocator, HVecBinaryOperation* instruction) {
861 LocationSummary* locations = new (allocator) LocationSummary(instruction);
Aart Bikf8f5a162017-02-06 15:35:29 -0800862 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100863 case DataType::Type::kUint16:
864 case DataType::Type::kInt16:
865 case DataType::Type::kInt32:
866 case DataType::Type::kInt64:
Aart Bikf8f5a162017-02-06 15:35:29 -0800867 locations->SetInAt(0, Location::RequiresFpuRegister());
868 locations->SetInAt(1, Location::ConstantLocation(instruction->InputAt(1)->AsConstant()));
869 locations->SetOut(Location::SameAsFirstInput());
870 break;
871 default:
872 LOG(FATAL) << "Unsupported SIMD type";
873 UNREACHABLE();
874 }
875}
876
877void LocationsBuilderX86::VisitVecShl(HVecShl* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100878 CreateVecShiftLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikf8f5a162017-02-06 15:35:29 -0800879}
880
881void InstructionCodeGeneratorX86::VisitVecShl(HVecShl* instruction) {
882 LocationSummary* locations = instruction->GetLocations();
883 DCHECK(locations->InAt(0).Equals(locations->Out()));
884 int32_t value = locations->InAt(1).GetConstant()->AsIntConstant()->GetValue();
885 XmmRegister dst = locations->Out().AsFpuRegister<XmmRegister>();
886 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100887 case DataType::Type::kUint16:
888 case DataType::Type::kInt16:
Aart Bikf8f5a162017-02-06 15:35:29 -0800889 DCHECK_EQ(8u, instruction->GetVectorLength());
890 __ psllw(dst, Immediate(static_cast<uint8_t>(value)));
891 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100892 case DataType::Type::kInt32:
Aart Bikf8f5a162017-02-06 15:35:29 -0800893 DCHECK_EQ(4u, instruction->GetVectorLength());
894 __ pslld(dst, Immediate(static_cast<uint8_t>(value)));
895 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100896 case DataType::Type::kInt64:
Aart Bikf8f5a162017-02-06 15:35:29 -0800897 DCHECK_EQ(2u, instruction->GetVectorLength());
898 __ psllq(dst, Immediate(static_cast<uint8_t>(value)));
899 break;
900 default:
901 LOG(FATAL) << "Unsupported SIMD type";
902 UNREACHABLE();
903 }
904}
905
906void LocationsBuilderX86::VisitVecShr(HVecShr* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100907 CreateVecShiftLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikf8f5a162017-02-06 15:35:29 -0800908}
909
910void InstructionCodeGeneratorX86::VisitVecShr(HVecShr* instruction) {
911 LocationSummary* locations = instruction->GetLocations();
912 DCHECK(locations->InAt(0).Equals(locations->Out()));
913 int32_t value = locations->InAt(1).GetConstant()->AsIntConstant()->GetValue();
914 XmmRegister dst = locations->Out().AsFpuRegister<XmmRegister>();
915 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100916 case DataType::Type::kUint16:
917 case DataType::Type::kInt16:
Aart Bikf8f5a162017-02-06 15:35:29 -0800918 DCHECK_EQ(8u, instruction->GetVectorLength());
919 __ psraw(dst, Immediate(static_cast<uint8_t>(value)));
920 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100921 case DataType::Type::kInt32:
Aart Bikf8f5a162017-02-06 15:35:29 -0800922 DCHECK_EQ(4u, instruction->GetVectorLength());
923 __ psrad(dst, Immediate(static_cast<uint8_t>(value)));
924 break;
925 default:
926 LOG(FATAL) << "Unsupported SIMD type";
927 UNREACHABLE();
928 }
929}
930
931void LocationsBuilderX86::VisitVecUShr(HVecUShr* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100932 CreateVecShiftLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikf8f5a162017-02-06 15:35:29 -0800933}
934
935void InstructionCodeGeneratorX86::VisitVecUShr(HVecUShr* instruction) {
936 LocationSummary* locations = instruction->GetLocations();
937 DCHECK(locations->InAt(0).Equals(locations->Out()));
938 int32_t value = locations->InAt(1).GetConstant()->AsIntConstant()->GetValue();
939 XmmRegister dst = locations->Out().AsFpuRegister<XmmRegister>();
940 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100941 case DataType::Type::kUint16:
942 case DataType::Type::kInt16:
Aart Bikf8f5a162017-02-06 15:35:29 -0800943 DCHECK_EQ(8u, instruction->GetVectorLength());
944 __ psrlw(dst, Immediate(static_cast<uint8_t>(value)));
945 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100946 case DataType::Type::kInt32:
Aart Bikf8f5a162017-02-06 15:35:29 -0800947 DCHECK_EQ(4u, instruction->GetVectorLength());
948 __ psrld(dst, Immediate(static_cast<uint8_t>(value)));
949 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100950 case DataType::Type::kInt64:
Aart Bikf8f5a162017-02-06 15:35:29 -0800951 DCHECK_EQ(2u, instruction->GetVectorLength());
952 __ psrlq(dst, Immediate(static_cast<uint8_t>(value)));
953 break;
954 default:
955 LOG(FATAL) << "Unsupported SIMD type";
956 UNREACHABLE();
957 }
958}
959
Aart Bik0148de42017-09-05 09:25:01 -0700960void LocationsBuilderX86::VisitVecSetScalars(HVecSetScalars* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100961 LocationSummary* locations = new (GetGraph()->GetAllocator()) LocationSummary(instruction);
Aart Bik0148de42017-09-05 09:25:01 -0700962
963 DCHECK_EQ(1u, instruction->InputCount()); // only one input currently implemented
964
965 HInstruction* input = instruction->InputAt(0);
966 bool is_zero = IsZeroBitPattern(input);
967
968 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100969 case DataType::Type::kInt64:
Aart Bik0148de42017-09-05 09:25:01 -0700970 // Long needs extra temporary to load from register pairs.
971 if (!is_zero) {
972 locations->AddTemp(Location::RequiresFpuRegister());
973 }
974 FALLTHROUGH_INTENDED;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100975 case DataType::Type::kBool:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100976 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100977 case DataType::Type::kInt8:
978 case DataType::Type::kUint16:
979 case DataType::Type::kInt16:
980 case DataType::Type::kInt32:
Aart Bik0148de42017-09-05 09:25:01 -0700981 locations->SetInAt(0, is_zero ? Location::ConstantLocation(input->AsConstant())
982 : Location::RequiresRegister());
983 locations->SetOut(Location::RequiresFpuRegister());
984 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100985 case DataType::Type::kFloat32:
986 case DataType::Type::kFloat64:
Aart Bik0148de42017-09-05 09:25:01 -0700987 locations->SetInAt(0, is_zero ? Location::ConstantLocation(input->AsConstant())
988 : Location::RequiresFpuRegister());
989 locations->SetOut(Location::RequiresFpuRegister());
990 break;
991 default:
992 LOG(FATAL) << "Unsupported SIMD type";
993 UNREACHABLE();
994 }
995}
996
997void InstructionCodeGeneratorX86::VisitVecSetScalars(HVecSetScalars* instruction) {
998 LocationSummary* locations = instruction->GetLocations();
999 XmmRegister dst = locations->Out().AsFpuRegister<XmmRegister>();
1000
1001 DCHECK_EQ(1u, instruction->InputCount()); // only one input currently implemented
1002
1003 // Zero out all other elements first.
1004 __ xorps(dst, dst);
1005
1006 // Shorthand for any type of zero.
1007 if (IsZeroBitPattern(instruction->InputAt(0))) {
1008 return;
1009 }
1010
1011 // Set required elements.
1012 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001013 case DataType::Type::kBool:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +01001014 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001015 case DataType::Type::kInt8:
1016 case DataType::Type::kUint16:
1017 case DataType::Type::kInt16: // TODO: up to here, and?
Aart Bik0148de42017-09-05 09:25:01 -07001018 LOG(FATAL) << "Unsupported SIMD type";
1019 UNREACHABLE();
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001020 case DataType::Type::kInt32:
Aart Bik0148de42017-09-05 09:25:01 -07001021 DCHECK_EQ(4u, instruction->GetVectorLength());
1022 __ movd(dst, locations->InAt(0).AsRegister<Register>());
1023 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001024 case DataType::Type::kInt64: {
Aart Bik0148de42017-09-05 09:25:01 -07001025 XmmRegister tmp = locations->GetTemp(0).AsFpuRegister<XmmRegister>();
1026 DCHECK_EQ(2u, instruction->GetVectorLength());
1027 __ xorps(tmp, tmp);
1028 __ movd(dst, locations->InAt(0).AsRegisterPairLow<Register>());
1029 __ movd(tmp, locations->InAt(0).AsRegisterPairHigh<Register>());
1030 __ punpckldq(dst, tmp);
1031 break;
1032 }
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001033 case DataType::Type::kFloat32:
Aart Bik0148de42017-09-05 09:25:01 -07001034 DCHECK_EQ(4u, instruction->GetVectorLength());
1035 __ movss(dst, locations->InAt(1).AsFpuRegister<XmmRegister>());
1036 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001037 case DataType::Type::kFloat64:
Aart Bik0148de42017-09-05 09:25:01 -07001038 DCHECK_EQ(2u, instruction->GetVectorLength());
1039 __ movsd(dst, locations->InAt(1).AsFpuRegister<XmmRegister>());
1040 break;
1041 default:
1042 LOG(FATAL) << "Unsupported SIMD type";
1043 UNREACHABLE();
1044 }
1045}
1046
Aart Bikdbbac8f2017-09-01 13:06:08 -07001047// Helper to set up locations for vector accumulations.
Vladimir Markoe764d2e2017-10-05 14:35:55 +01001048static void CreateVecAccumLocations(ArenaAllocator* allocator, HVecOperation* instruction) {
1049 LocationSummary* locations = new (allocator) LocationSummary(instruction);
Aart Bikdbbac8f2017-09-01 13:06:08 -07001050 switch (instruction->GetPackedType()) {
Vladimir Markod5d2f2c2017-09-26 12:37:26 +01001051 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001052 case DataType::Type::kInt8:
1053 case DataType::Type::kUint16:
1054 case DataType::Type::kInt16:
1055 case DataType::Type::kInt32:
1056 case DataType::Type::kInt64:
Aart Bikdbbac8f2017-09-01 13:06:08 -07001057 locations->SetInAt(0, Location::RequiresFpuRegister());
1058 locations->SetInAt(1, Location::RequiresFpuRegister());
1059 locations->SetInAt(2, Location::RequiresFpuRegister());
1060 locations->SetOut(Location::SameAsFirstInput());
1061 break;
1062 default:
1063 LOG(FATAL) << "Unsupported SIMD type";
1064 UNREACHABLE();
1065 }
Artem Serovf34dd202017-04-10 17:41:46 +01001066}
1067
Aart Bikdbbac8f2017-09-01 13:06:08 -07001068void LocationsBuilderX86::VisitVecMultiplyAccumulate(HVecMultiplyAccumulate* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +01001069 CreateVecAccumLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikdbbac8f2017-09-01 13:06:08 -07001070}
1071
1072void InstructionCodeGeneratorX86::VisitVecMultiplyAccumulate(HVecMultiplyAccumulate* instruction) {
1073 // TODO: pmaddwd?
1074 LOG(FATAL) << "No SIMD for " << instruction->GetId();
1075}
1076
1077void LocationsBuilderX86::VisitVecSADAccumulate(HVecSADAccumulate* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +01001078 CreateVecAccumLocations(GetGraph()->GetAllocator(), instruction);
Aart Bikdbbac8f2017-09-01 13:06:08 -07001079}
1080
1081void InstructionCodeGeneratorX86::VisitVecSADAccumulate(HVecSADAccumulate* instruction) {
1082 // TODO: psadbw for unsigned?
1083 LOG(FATAL) << "No SIMD for " << instruction->GetId();
Artem Serovf34dd202017-04-10 17:41:46 +01001084}
1085
Aart Bikf8f5a162017-02-06 15:35:29 -08001086// Helper to set up locations for vector memory operations.
Vladimir Markoe764d2e2017-10-05 14:35:55 +01001087static void CreateVecMemLocations(ArenaAllocator* allocator,
Aart Bikf8f5a162017-02-06 15:35:29 -08001088 HVecMemoryOperation* instruction,
1089 bool is_load) {
Vladimir Markoe764d2e2017-10-05 14:35:55 +01001090 LocationSummary* locations = new (allocator) LocationSummary(instruction);
Aart Bikf8f5a162017-02-06 15:35:29 -08001091 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001092 case DataType::Type::kBool:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +01001093 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001094 case DataType::Type::kInt8:
1095 case DataType::Type::kUint16:
1096 case DataType::Type::kInt16:
1097 case DataType::Type::kInt32:
1098 case DataType::Type::kInt64:
1099 case DataType::Type::kFloat32:
1100 case DataType::Type::kFloat64:
Aart Bikf8f5a162017-02-06 15:35:29 -08001101 locations->SetInAt(0, Location::RequiresRegister());
1102 locations->SetInAt(1, Location::RegisterOrConstant(instruction->InputAt(1)));
1103 if (is_load) {
1104 locations->SetOut(Location::RequiresFpuRegister());
1105 } else {
1106 locations->SetInAt(2, Location::RequiresFpuRegister());
1107 }
1108 break;
1109 default:
1110 LOG(FATAL) << "Unsupported SIMD type";
1111 UNREACHABLE();
1112 }
1113}
1114
Aart Bik472821b2017-04-27 17:23:51 -07001115// Helper to construct address for vector memory operations.
1116static Address VecAddress(LocationSummary* locations, size_t size, bool is_string_char_at) {
Aart Bikf8f5a162017-02-06 15:35:29 -08001117 Location base = locations->InAt(0);
1118 Location index = locations->InAt(1);
Aart Bikf8f5a162017-02-06 15:35:29 -08001119 ScaleFactor scale = TIMES_1;
1120 switch (size) {
1121 case 2: scale = TIMES_2; break;
1122 case 4: scale = TIMES_4; break;
1123 case 8: scale = TIMES_8; break;
1124 default: break;
1125 }
Aart Bik0148de42017-09-05 09:25:01 -07001126 // Incorporate the string or array offset in the address computation.
Aart Bik472821b2017-04-27 17:23:51 -07001127 uint32_t offset = is_string_char_at
1128 ? mirror::String::ValueOffset().Uint32Value()
1129 : mirror::Array::DataOffset(size).Uint32Value();
Aart Bikf8f5a162017-02-06 15:35:29 -08001130 return CodeGeneratorX86::ArrayAddress(base.AsRegister<Register>(), index, scale, offset);
1131}
1132
1133void LocationsBuilderX86::VisitVecLoad(HVecLoad* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +01001134 CreateVecMemLocations(GetGraph()->GetAllocator(), instruction, /*is_load*/ true);
Aart Bik472821b2017-04-27 17:23:51 -07001135 // String load requires a temporary for the compressed load.
1136 if (mirror::kUseStringCompression && instruction->IsStringCharAt()) {
1137 instruction->GetLocations()->AddTemp(Location::RequiresFpuRegister());
1138 }
Aart Bikf8f5a162017-02-06 15:35:29 -08001139}
1140
1141void InstructionCodeGeneratorX86::VisitVecLoad(HVecLoad* instruction) {
Aart Bik472821b2017-04-27 17:23:51 -07001142 LocationSummary* locations = instruction->GetLocations();
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001143 size_t size = DataType::Size(instruction->GetPackedType());
Aart Bik472821b2017-04-27 17:23:51 -07001144 Address address = VecAddress(locations, size, instruction->IsStringCharAt());
1145 XmmRegister reg = locations->Out().AsFpuRegister<XmmRegister>();
Aart Bikf8f5a162017-02-06 15:35:29 -08001146 bool is_aligned16 = instruction->GetAlignment().IsAlignedAt(16);
1147 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001148 case DataType::Type::kUint16:
Aart Bik472821b2017-04-27 17:23:51 -07001149 DCHECK_EQ(8u, instruction->GetVectorLength());
1150 // Special handling of compressed/uncompressed string load.
1151 if (mirror::kUseStringCompression && instruction->IsStringCharAt()) {
1152 NearLabel done, not_compressed;
1153 XmmRegister tmp = locations->GetTemp(0).AsFpuRegister<XmmRegister>();
1154 // Test compression bit.
1155 static_assert(static_cast<uint32_t>(mirror::StringCompressionFlag::kCompressed) == 0u,
1156 "Expecting 0=compressed, 1=uncompressed");
1157 uint32_t count_offset = mirror::String::CountOffset().Uint32Value();
1158 __ testb(Address(locations->InAt(0).AsRegister<Register>(), count_offset), Immediate(1));
1159 __ j(kNotZero, &not_compressed);
1160 // Zero extend 8 compressed bytes into 8 chars.
Aart Bik0148de42017-09-05 09:25:01 -07001161 __ movsd(reg, VecAddress(locations, 1, instruction->IsStringCharAt()));
Aart Bik472821b2017-04-27 17:23:51 -07001162 __ pxor(tmp, tmp);
1163 __ punpcklbw(reg, tmp);
1164 __ jmp(&done);
1165 // Load 4 direct uncompressed chars.
1166 __ Bind(&not_compressed);
1167 is_aligned16 ? __ movdqa(reg, address) : __ movdqu(reg, address);
1168 __ Bind(&done);
1169 return;
1170 }
1171 FALLTHROUGH_INTENDED;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001172 case DataType::Type::kBool:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +01001173 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001174 case DataType::Type::kInt8:
1175 case DataType::Type::kInt16:
1176 case DataType::Type::kInt32:
1177 case DataType::Type::kInt64:
Aart Bikf8f5a162017-02-06 15:35:29 -08001178 DCHECK_LE(2u, instruction->GetVectorLength());
1179 DCHECK_LE(instruction->GetVectorLength(), 16u);
1180 is_aligned16 ? __ movdqa(reg, address) : __ movdqu(reg, address);
1181 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001182 case DataType::Type::kFloat32:
Aart Bikf8f5a162017-02-06 15:35:29 -08001183 DCHECK_EQ(4u, instruction->GetVectorLength());
1184 is_aligned16 ? __ movaps(reg, address) : __ movups(reg, address);
1185 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001186 case DataType::Type::kFloat64:
Aart Bikf8f5a162017-02-06 15:35:29 -08001187 DCHECK_EQ(2u, instruction->GetVectorLength());
1188 is_aligned16 ? __ movapd(reg, address) : __ movupd(reg, address);
1189 break;
1190 default:
1191 LOG(FATAL) << "Unsupported SIMD type";
1192 UNREACHABLE();
1193 }
1194}
1195
1196void LocationsBuilderX86::VisitVecStore(HVecStore* instruction) {
Vladimir Markoca6fff82017-10-03 14:49:14 +01001197 CreateVecMemLocations(GetGraph()->GetAllocator(), instruction, /*is_load*/ false);
Aart Bikf8f5a162017-02-06 15:35:29 -08001198}
1199
1200void InstructionCodeGeneratorX86::VisitVecStore(HVecStore* instruction) {
Aart Bik472821b2017-04-27 17:23:51 -07001201 LocationSummary* locations = instruction->GetLocations();
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001202 size_t size = DataType::Size(instruction->GetPackedType());
Aart Bik472821b2017-04-27 17:23:51 -07001203 Address address = VecAddress(locations, size, /*is_string_char_at*/ false);
1204 XmmRegister reg = locations->InAt(2).AsFpuRegister<XmmRegister>();
Aart Bikf8f5a162017-02-06 15:35:29 -08001205 bool is_aligned16 = instruction->GetAlignment().IsAlignedAt(16);
1206 switch (instruction->GetPackedType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001207 case DataType::Type::kBool:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +01001208 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001209 case DataType::Type::kInt8:
1210 case DataType::Type::kUint16:
1211 case DataType::Type::kInt16:
1212 case DataType::Type::kInt32:
1213 case DataType::Type::kInt64:
Aart Bikf8f5a162017-02-06 15:35:29 -08001214 DCHECK_LE(2u, instruction->GetVectorLength());
1215 DCHECK_LE(instruction->GetVectorLength(), 16u);
1216 is_aligned16 ? __ movdqa(address, reg) : __ movdqu(address, reg);
1217 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001218 case DataType::Type::kFloat32:
Aart Bikf8f5a162017-02-06 15:35:29 -08001219 DCHECK_EQ(4u, instruction->GetVectorLength());
1220 is_aligned16 ? __ movaps(address, reg) : __ movups(address, reg);
1221 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001222 case DataType::Type::kFloat64:
Aart Bikf8f5a162017-02-06 15:35:29 -08001223 DCHECK_EQ(2u, instruction->GetVectorLength());
1224 is_aligned16 ? __ movapd(address, reg) : __ movupd(address, reg);
1225 break;
1226 default:
1227 LOG(FATAL) << "Unsupported SIMD type";
1228 UNREACHABLE();
1229 }
1230}
1231
1232#undef __
1233
1234} // namespace x86
1235} // namespace art