blob: 4f3988ee2e882db95b9d237a51e9a5c4feb548c6 [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"
18#include "mirror/array-inl.h"
19
20namespace art {
21namespace x86 {
22
23// NOLINT on __ macro to suppress wrong warning/fix (misc-macro-parentheses) from clang-tidy.
24#define __ down_cast<X86Assembler*>(GetAssembler())-> // NOLINT
25
26void LocationsBuilderX86::VisitVecReplicateScalar(HVecReplicateScalar* instruction) {
27 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction);
28 switch (instruction->GetPackedType()) {
29 case Primitive::kPrimLong:
30 // Long needs extra temporary to load the register pair.
31 locations->AddTemp(Location::RequiresFpuRegister());
32 FALLTHROUGH_INTENDED;
33 case Primitive::kPrimBoolean:
34 case Primitive::kPrimByte:
35 case Primitive::kPrimChar:
36 case Primitive::kPrimShort:
37 case Primitive::kPrimInt:
38 locations->SetInAt(0, Location::RequiresRegister());
39 locations->SetOut(Location::RequiresFpuRegister());
40 break;
41 case Primitive::kPrimFloat:
42 case Primitive::kPrimDouble:
43 locations->SetInAt(0, Location::RequiresFpuRegister());
44 locations->SetOut(Location::SameAsFirstInput());
45 break;
46 default:
47 LOG(FATAL) << "Unsupported SIMD type";
48 UNREACHABLE();
49 }
50}
51
52void InstructionCodeGeneratorX86::VisitVecReplicateScalar(HVecReplicateScalar* instruction) {
53 LocationSummary* locations = instruction->GetLocations();
54 XmmRegister reg = locations->Out().AsFpuRegister<XmmRegister>();
55 switch (instruction->GetPackedType()) {
56 case Primitive::kPrimBoolean:
57 case Primitive::kPrimByte:
58 DCHECK_EQ(16u, instruction->GetVectorLength());
59 __ movd(reg, locations->InAt(0).AsRegister<Register>());
60 __ punpcklbw(reg, reg);
61 __ punpcklwd(reg, reg);
62 __ pshufd(reg, reg, Immediate(0));
63 break;
64 case Primitive::kPrimChar:
65 case Primitive::kPrimShort:
66 DCHECK_EQ(8u, instruction->GetVectorLength());
67 __ movd(reg, locations->InAt(0).AsRegister<Register>());
68 __ punpcklwd(reg, reg);
69 __ pshufd(reg, reg, Immediate(0));
70 break;
71 case Primitive::kPrimInt:
72 DCHECK_EQ(4u, instruction->GetVectorLength());
73 __ movd(reg, locations->InAt(0).AsRegister<Register>());
74 __ pshufd(reg, reg, Immediate(0));
75 break;
76 case Primitive::kPrimLong: {
77 XmmRegister tmp = locations->GetTemp(0).AsFpuRegister<XmmRegister>();
78 DCHECK_EQ(2u, instruction->GetVectorLength());
79 __ movd(reg, locations->InAt(0).AsRegisterPairLow<Register>());
80 __ movd(tmp, locations->InAt(0).AsRegisterPairHigh<Register>());
81 __ punpckldq(reg, tmp);
82 __ punpcklqdq(reg, reg);
83 break;
84 }
85 case Primitive::kPrimFloat:
86 DCHECK(locations->InAt(0).Equals(locations->Out()));
87 DCHECK_EQ(4u, instruction->GetVectorLength());
88 __ shufps(reg, reg, Immediate(0));
89 break;
90 case Primitive::kPrimDouble:
91 DCHECK(locations->InAt(0).Equals(locations->Out()));
92 DCHECK_EQ(2u, instruction->GetVectorLength());
93 __ shufpd(reg, reg, Immediate(0));
94 break;
95 default:
96 LOG(FATAL) << "Unsupported SIMD type";
97 UNREACHABLE();
98 }
99}
100
101void LocationsBuilderX86::VisitVecSetScalars(HVecSetScalars* instruction) {
102 LOG(FATAL) << "No SIMD for " << instruction->GetId();
103}
104
105void InstructionCodeGeneratorX86::VisitVecSetScalars(HVecSetScalars* instruction) {
106 LOG(FATAL) << "No SIMD for " << instruction->GetId();
107}
108
109void LocationsBuilderX86::VisitVecSumReduce(HVecSumReduce* instruction) {
110 LOG(FATAL) << "No SIMD for " << instruction->GetId();
111}
112
113void InstructionCodeGeneratorX86::VisitVecSumReduce(HVecSumReduce* instruction) {
114 LOG(FATAL) << "No SIMD for " << instruction->GetId();
115}
116
117// Helper to set up locations for vector unary operations.
118static void CreateVecUnOpLocations(ArenaAllocator* arena, HVecUnaryOperation* instruction) {
119 LocationSummary* locations = new (arena) LocationSummary(instruction);
120 switch (instruction->GetPackedType()) {
121 case Primitive::kPrimBoolean:
122 case Primitive::kPrimByte:
123 case Primitive::kPrimChar:
124 case Primitive::kPrimShort:
125 case Primitive::kPrimInt:
126 case Primitive::kPrimLong:
127 case Primitive::kPrimFloat:
128 case Primitive::kPrimDouble:
129 locations->SetInAt(0, Location::RequiresFpuRegister());
130 locations->SetOut(Location::RequiresFpuRegister());
131 break;
132 default:
133 LOG(FATAL) << "Unsupported SIMD type";
134 UNREACHABLE();
135 }
136}
137
138void LocationsBuilderX86::VisitVecCnv(HVecCnv* instruction) {
139 CreateVecUnOpLocations(GetGraph()->GetArena(), instruction);
140}
141
142void InstructionCodeGeneratorX86::VisitVecCnv(HVecCnv* instruction) {
143 LocationSummary* locations = instruction->GetLocations();
144 XmmRegister src = locations->InAt(0).AsFpuRegister<XmmRegister>();
145 XmmRegister dst = locations->Out().AsFpuRegister<XmmRegister>();
146 Primitive::Type from = instruction->GetInputType();
147 Primitive::Type to = instruction->GetResultType();
148 if (from == Primitive::kPrimInt && to == Primitive::kPrimFloat) {
149 DCHECK_EQ(4u, instruction->GetVectorLength());
150 __ cvtdq2ps(dst, src);
151 } else {
152 LOG(FATAL) << "Unsupported SIMD type";
153 }
154}
155
156void LocationsBuilderX86::VisitVecNeg(HVecNeg* instruction) {
157 CreateVecUnOpLocations(GetGraph()->GetArena(), instruction);
158}
159
160void InstructionCodeGeneratorX86::VisitVecNeg(HVecNeg* instruction) {
161 LocationSummary* locations = instruction->GetLocations();
162 XmmRegister src = locations->InAt(0).AsFpuRegister<XmmRegister>();
163 XmmRegister dst = locations->Out().AsFpuRegister<XmmRegister>();
164 switch (instruction->GetPackedType()) {
165 case Primitive::kPrimByte:
166 DCHECK_EQ(16u, instruction->GetVectorLength());
167 __ pxor(dst, dst);
168 __ psubb(dst, src);
169 break;
170 case Primitive::kPrimChar:
171 case Primitive::kPrimShort:
172 DCHECK_EQ(8u, instruction->GetVectorLength());
173 __ pxor(dst, dst);
174 __ psubw(dst, src);
175 break;
176 case Primitive::kPrimInt:
177 DCHECK_EQ(4u, instruction->GetVectorLength());
178 __ pxor(dst, dst);
179 __ psubd(dst, src);
180 break;
181 case Primitive::kPrimLong:
182 DCHECK_EQ(2u, instruction->GetVectorLength());
183 __ pxor(dst, dst);
184 __ psubq(dst, src);
185 break;
186 case Primitive::kPrimFloat:
187 DCHECK_EQ(4u, instruction->GetVectorLength());
188 __ xorps(dst, dst);
189 __ subps(dst, src);
190 break;
191 case Primitive::kPrimDouble:
192 DCHECK_EQ(2u, instruction->GetVectorLength());
193 __ xorpd(dst, dst);
194 __ subpd(dst, src);
195 break;
196 default:
197 LOG(FATAL) << "Unsupported SIMD type";
198 UNREACHABLE();
199 }
200}
201
202void LocationsBuilderX86::VisitVecNot(HVecNot* instruction) {
203 CreateVecUnOpLocations(GetGraph()->GetArena(), instruction);
204 // Boolean-not requires a temporary to construct the 16 x one.
205 if (instruction->GetPackedType() == Primitive::kPrimBoolean) {
206 instruction->GetLocations()->AddTemp(Location::RequiresFpuRegister());
207 }
208}
209
210void InstructionCodeGeneratorX86::VisitVecNot(HVecNot* instruction) {
211 LocationSummary* locations = instruction->GetLocations();
212 XmmRegister src = locations->InAt(0).AsFpuRegister<XmmRegister>();
213 XmmRegister dst = locations->Out().AsFpuRegister<XmmRegister>();
214 switch (instruction->GetPackedType()) {
215 case Primitive::kPrimBoolean: { // special case boolean-not
216 DCHECK_EQ(16u, instruction->GetVectorLength());
217 XmmRegister tmp = locations->GetTemp(0).AsFpuRegister<XmmRegister>();
218 __ pxor(dst, dst);
219 __ pcmpeqb(tmp, tmp); // all ones
220 __ psubb(dst, tmp); // 16 x one
221 __ pxor(dst, src);
222 break;
223 }
224 case Primitive::kPrimByte:
225 case Primitive::kPrimChar:
226 case Primitive::kPrimShort:
227 case Primitive::kPrimInt:
228 case Primitive::kPrimLong:
229 DCHECK_LE(2u, instruction->GetVectorLength());
230 DCHECK_LE(instruction->GetVectorLength(), 16u);
231 __ pcmpeqb(dst, dst); // all ones
232 __ pxor(dst, src);
233 break;
234 case Primitive::kPrimFloat:
235 DCHECK_EQ(4u, instruction->GetVectorLength());
236 __ pcmpeqb(dst, dst); // all ones
237 __ xorps(dst, src);
238 break;
239 case Primitive::kPrimDouble:
240 DCHECK_EQ(2u, instruction->GetVectorLength());
241 __ pcmpeqb(dst, dst); // all ones
242 __ xorpd(dst, src);
243 break;
244 default:
245 LOG(FATAL) << "Unsupported SIMD type";
246 UNREACHABLE();
247 }
248}
249
250// Helper to set up locations for vector binary operations.
251static void CreateVecBinOpLocations(ArenaAllocator* arena, HVecBinaryOperation* instruction) {
252 LocationSummary* locations = new (arena) LocationSummary(instruction);
253 switch (instruction->GetPackedType()) {
254 case Primitive::kPrimBoolean:
255 case Primitive::kPrimByte:
256 case Primitive::kPrimChar:
257 case Primitive::kPrimShort:
258 case Primitive::kPrimInt:
259 case Primitive::kPrimLong:
260 case Primitive::kPrimFloat:
261 case Primitive::kPrimDouble:
262 locations->SetInAt(0, Location::RequiresFpuRegister());
263 locations->SetInAt(1, Location::RequiresFpuRegister());
264 locations->SetOut(Location::SameAsFirstInput());
265 break;
266 default:
267 LOG(FATAL) << "Unsupported SIMD type";
268 UNREACHABLE();
269 }
270}
271
272void LocationsBuilderX86::VisitVecAdd(HVecAdd* instruction) {
273 CreateVecBinOpLocations(GetGraph()->GetArena(), instruction);
274}
275
276void InstructionCodeGeneratorX86::VisitVecAdd(HVecAdd* instruction) {
277 LocationSummary* locations = instruction->GetLocations();
278 DCHECK(locations->InAt(0).Equals(locations->Out()));
279 XmmRegister src = locations->InAt(1).AsFpuRegister<XmmRegister>();
280 XmmRegister dst = locations->Out().AsFpuRegister<XmmRegister>();
281 switch (instruction->GetPackedType()) {
282 case Primitive::kPrimByte:
283 DCHECK_EQ(16u, instruction->GetVectorLength());
284 __ paddb(dst, src);
285 break;
286 case Primitive::kPrimChar:
287 case Primitive::kPrimShort:
288 DCHECK_EQ(8u, instruction->GetVectorLength());
289 __ paddw(dst, src);
290 break;
291 case Primitive::kPrimInt:
292 DCHECK_EQ(4u, instruction->GetVectorLength());
293 __ paddd(dst, src);
294 break;
295 case Primitive::kPrimLong:
296 DCHECK_EQ(2u, instruction->GetVectorLength());
297 __ paddq(dst, src);
298 break;
299 case Primitive::kPrimFloat:
300 DCHECK_EQ(4u, instruction->GetVectorLength());
301 __ addps(dst, src);
302 break;
303 case Primitive::kPrimDouble:
304 DCHECK_EQ(2u, instruction->GetVectorLength());
305 __ addpd(dst, src);
306 break;
307 default:
308 LOG(FATAL) << "Unsupported SIMD type";
309 UNREACHABLE();
310 }
311}
312
313void LocationsBuilderX86::VisitVecSub(HVecSub* instruction) {
314 CreateVecBinOpLocations(GetGraph()->GetArena(), instruction);
315}
316
317void InstructionCodeGeneratorX86::VisitVecSub(HVecSub* instruction) {
318 LocationSummary* locations = instruction->GetLocations();
319 DCHECK(locations->InAt(0).Equals(locations->Out()));
320 XmmRegister src = locations->InAt(1).AsFpuRegister<XmmRegister>();
321 XmmRegister dst = locations->Out().AsFpuRegister<XmmRegister>();
322 switch (instruction->GetPackedType()) {
323 case Primitive::kPrimByte:
324 DCHECK_EQ(16u, instruction->GetVectorLength());
325 __ psubb(dst, src);
326 break;
327 case Primitive::kPrimChar:
328 case Primitive::kPrimShort:
329 DCHECK_EQ(8u, instruction->GetVectorLength());
330 __ psubw(dst, src);
331 break;
332 case Primitive::kPrimInt:
333 DCHECK_EQ(4u, instruction->GetVectorLength());
334 __ psubd(dst, src);
335 break;
336 case Primitive::kPrimLong:
337 DCHECK_EQ(2u, instruction->GetVectorLength());
338 __ psubq(dst, src);
339 break;
340 case Primitive::kPrimFloat:
341 DCHECK_EQ(4u, instruction->GetVectorLength());
342 __ subps(dst, src);
343 break;
344 case Primitive::kPrimDouble:
345 DCHECK_EQ(2u, instruction->GetVectorLength());
346 __ subpd(dst, src);
347 break;
348 default:
349 LOG(FATAL) << "Unsupported SIMD type";
350 UNREACHABLE();
351 }
352}
353
354void LocationsBuilderX86::VisitVecMul(HVecMul* instruction) {
355 CreateVecBinOpLocations(GetGraph()->GetArena(), instruction);
356}
357
358void InstructionCodeGeneratorX86::VisitVecMul(HVecMul* instruction) {
359 LocationSummary* locations = instruction->GetLocations();
360 DCHECK(locations->InAt(0).Equals(locations->Out()));
361 XmmRegister src = locations->InAt(1).AsFpuRegister<XmmRegister>();
362 XmmRegister dst = locations->Out().AsFpuRegister<XmmRegister>();
363 switch (instruction->GetPackedType()) {
364 case Primitive::kPrimChar:
365 case Primitive::kPrimShort:
366 DCHECK_EQ(8u, instruction->GetVectorLength());
367 __ pmullw(dst, src);
368 break;
369 case Primitive::kPrimInt:
370 DCHECK_EQ(4u, instruction->GetVectorLength());
371 __ pmulld(dst, src);
372 break;
373 case Primitive::kPrimFloat:
374 DCHECK_EQ(4u, instruction->GetVectorLength());
375 __ mulps(dst, src);
376 break;
377 case Primitive::kPrimDouble:
378 DCHECK_EQ(2u, instruction->GetVectorLength());
379 __ mulpd(dst, src);
380 break;
381 default:
382 LOG(FATAL) << "Unsupported SIMD type";
383 UNREACHABLE();
384 }
385}
386
387void LocationsBuilderX86::VisitVecDiv(HVecDiv* instruction) {
388 CreateVecBinOpLocations(GetGraph()->GetArena(), instruction);
389}
390
391void InstructionCodeGeneratorX86::VisitVecDiv(HVecDiv* instruction) {
392 LocationSummary* locations = instruction->GetLocations();
393 DCHECK(locations->InAt(0).Equals(locations->Out()));
394 XmmRegister src = locations->InAt(1).AsFpuRegister<XmmRegister>();
395 XmmRegister dst = locations->Out().AsFpuRegister<XmmRegister>();
396 switch (instruction->GetPackedType()) {
397 case Primitive::kPrimFloat:
398 DCHECK_EQ(4u, instruction->GetVectorLength());
399 __ divps(dst, src);
400 break;
401 case Primitive::kPrimDouble:
402 DCHECK_EQ(2u, instruction->GetVectorLength());
403 __ divpd(dst, src);
404 break;
405 default:
406 LOG(FATAL) << "Unsupported SIMD type";
407 UNREACHABLE();
408 }
409}
410
411void LocationsBuilderX86::VisitVecAnd(HVecAnd* instruction) {
412 CreateVecBinOpLocations(GetGraph()->GetArena(), instruction);
413}
414
415void InstructionCodeGeneratorX86::VisitVecAnd(HVecAnd* instruction) {
416 LocationSummary* locations = instruction->GetLocations();
417 DCHECK(locations->InAt(0).Equals(locations->Out()));
418 XmmRegister src = locations->InAt(1).AsFpuRegister<XmmRegister>();
419 XmmRegister dst = locations->Out().AsFpuRegister<XmmRegister>();
420 switch (instruction->GetPackedType()) {
421 case Primitive::kPrimBoolean:
422 case Primitive::kPrimByte:
423 case Primitive::kPrimChar:
424 case Primitive::kPrimShort:
425 case Primitive::kPrimInt:
426 case Primitive::kPrimLong:
427 DCHECK_LE(2u, instruction->GetVectorLength());
428 DCHECK_LE(instruction->GetVectorLength(), 16u);
429 __ pand(dst, src);
430 break;
431 case Primitive::kPrimFloat:
432 DCHECK_EQ(4u, instruction->GetVectorLength());
433 __ andps(dst, src);
434 break;
435 case Primitive::kPrimDouble:
436 DCHECK_EQ(2u, instruction->GetVectorLength());
437 __ andpd(dst, src);
438 break;
439 default:
440 LOG(FATAL) << "Unsupported SIMD type";
441 UNREACHABLE();
442 }
443}
444
445void LocationsBuilderX86::VisitVecAndNot(HVecAndNot* instruction) {
446 CreateVecBinOpLocations(GetGraph()->GetArena(), instruction);
447}
448
449void InstructionCodeGeneratorX86::VisitVecAndNot(HVecAndNot* instruction) {
450 LocationSummary* locations = instruction->GetLocations();
451 DCHECK(locations->InAt(0).Equals(locations->Out()));
452 XmmRegister src = locations->InAt(1).AsFpuRegister<XmmRegister>();
453 XmmRegister dst = locations->Out().AsFpuRegister<XmmRegister>();
454 switch (instruction->GetPackedType()) {
455 case Primitive::kPrimBoolean:
456 case Primitive::kPrimByte:
457 case Primitive::kPrimChar:
458 case Primitive::kPrimShort:
459 case Primitive::kPrimInt:
460 case Primitive::kPrimLong:
461 DCHECK_LE(2u, instruction->GetVectorLength());
462 DCHECK_LE(instruction->GetVectorLength(), 16u);
463 __ pandn(dst, src);
464 break;
465 case Primitive::kPrimFloat:
466 DCHECK_EQ(4u, instruction->GetVectorLength());
467 __ andnps(dst, src);
468 break;
469 case Primitive::kPrimDouble:
470 DCHECK_EQ(2u, instruction->GetVectorLength());
471 __ andnpd(dst, src);
472 break;
473 default:
474 LOG(FATAL) << "Unsupported SIMD type";
475 UNREACHABLE();
476 }
477}
478
479void LocationsBuilderX86::VisitVecOr(HVecOr* instruction) {
480 CreateVecBinOpLocations(GetGraph()->GetArena(), instruction);
481}
482
483void InstructionCodeGeneratorX86::VisitVecOr(HVecOr* instruction) {
484 LocationSummary* locations = instruction->GetLocations();
485 DCHECK(locations->InAt(0).Equals(locations->Out()));
486 XmmRegister src = locations->InAt(1).AsFpuRegister<XmmRegister>();
487 XmmRegister dst = locations->Out().AsFpuRegister<XmmRegister>();
488 switch (instruction->GetPackedType()) {
489 case Primitive::kPrimBoolean:
490 case Primitive::kPrimByte:
491 case Primitive::kPrimChar:
492 case Primitive::kPrimShort:
493 case Primitive::kPrimInt:
494 case Primitive::kPrimLong:
495 DCHECK_LE(2u, instruction->GetVectorLength());
496 DCHECK_LE(instruction->GetVectorLength(), 16u);
497 __ por(dst, src);
498 break;
499 case Primitive::kPrimFloat:
500 DCHECK_EQ(4u, instruction->GetVectorLength());
501 __ orps(dst, src);
502 break;
503 case Primitive::kPrimDouble:
504 DCHECK_EQ(2u, instruction->GetVectorLength());
505 __ orpd(dst, src);
506 break;
507 default:
508 LOG(FATAL) << "Unsupported SIMD type";
509 UNREACHABLE();
510 }
511}
512
513void LocationsBuilderX86::VisitVecXor(HVecXor* instruction) {
514 CreateVecBinOpLocations(GetGraph()->GetArena(), instruction);
515}
516
517void InstructionCodeGeneratorX86::VisitVecXor(HVecXor* instruction) {
518 LocationSummary* locations = instruction->GetLocations();
519 DCHECK(locations->InAt(0).Equals(locations->Out()));
520 XmmRegister src = locations->InAt(1).AsFpuRegister<XmmRegister>();
521 XmmRegister dst = locations->Out().AsFpuRegister<XmmRegister>();
522 switch (instruction->GetPackedType()) {
523 case Primitive::kPrimBoolean:
524 case Primitive::kPrimByte:
525 case Primitive::kPrimChar:
526 case Primitive::kPrimShort:
527 case Primitive::kPrimInt:
528 case Primitive::kPrimLong:
529 DCHECK_LE(2u, instruction->GetVectorLength());
530 DCHECK_LE(instruction->GetVectorLength(), 16u);
531 __ pxor(dst, src);
532 break;
533 case Primitive::kPrimFloat:
534 DCHECK_EQ(4u, instruction->GetVectorLength());
535 __ xorps(dst, src);
536 break;
537 case Primitive::kPrimDouble:
538 DCHECK_EQ(2u, instruction->GetVectorLength());
539 __ xorpd(dst, src);
540 break;
541 default:
542 LOG(FATAL) << "Unsupported SIMD type";
543 UNREACHABLE();
544 }
545}
546
547// Helper to set up locations for vector shift operations.
548static void CreateVecShiftLocations(ArenaAllocator* arena, HVecBinaryOperation* instruction) {
549 LocationSummary* locations = new (arena) LocationSummary(instruction);
550 switch (instruction->GetPackedType()) {
551 case Primitive::kPrimChar:
552 case Primitive::kPrimShort:
553 case Primitive::kPrimInt:
554 case Primitive::kPrimLong:
555 locations->SetInAt(0, Location::RequiresFpuRegister());
556 locations->SetInAt(1, Location::ConstantLocation(instruction->InputAt(1)->AsConstant()));
557 locations->SetOut(Location::SameAsFirstInput());
558 break;
559 default:
560 LOG(FATAL) << "Unsupported SIMD type";
561 UNREACHABLE();
562 }
563}
564
565void LocationsBuilderX86::VisitVecShl(HVecShl* instruction) {
566 CreateVecShiftLocations(GetGraph()->GetArena(), instruction);
567}
568
569void InstructionCodeGeneratorX86::VisitVecShl(HVecShl* instruction) {
570 LocationSummary* locations = instruction->GetLocations();
571 DCHECK(locations->InAt(0).Equals(locations->Out()));
572 int32_t value = locations->InAt(1).GetConstant()->AsIntConstant()->GetValue();
573 XmmRegister dst = locations->Out().AsFpuRegister<XmmRegister>();
574 switch (instruction->GetPackedType()) {
575 case Primitive::kPrimChar:
576 case Primitive::kPrimShort:
577 DCHECK_EQ(8u, instruction->GetVectorLength());
578 __ psllw(dst, Immediate(static_cast<uint8_t>(value)));
579 break;
580 case Primitive::kPrimInt:
581 DCHECK_EQ(4u, instruction->GetVectorLength());
582 __ pslld(dst, Immediate(static_cast<uint8_t>(value)));
583 break;
584 case Primitive::kPrimLong:
585 DCHECK_EQ(2u, instruction->GetVectorLength());
586 __ psllq(dst, Immediate(static_cast<uint8_t>(value)));
587 break;
588 default:
589 LOG(FATAL) << "Unsupported SIMD type";
590 UNREACHABLE();
591 }
592}
593
594void LocationsBuilderX86::VisitVecShr(HVecShr* instruction) {
595 CreateVecShiftLocations(GetGraph()->GetArena(), instruction);
596}
597
598void InstructionCodeGeneratorX86::VisitVecShr(HVecShr* instruction) {
599 LocationSummary* locations = instruction->GetLocations();
600 DCHECK(locations->InAt(0).Equals(locations->Out()));
601 int32_t value = locations->InAt(1).GetConstant()->AsIntConstant()->GetValue();
602 XmmRegister dst = locations->Out().AsFpuRegister<XmmRegister>();
603 switch (instruction->GetPackedType()) {
604 case Primitive::kPrimChar:
605 case Primitive::kPrimShort:
606 DCHECK_EQ(8u, instruction->GetVectorLength());
607 __ psraw(dst, Immediate(static_cast<uint8_t>(value)));
608 break;
609 case Primitive::kPrimInt:
610 DCHECK_EQ(4u, instruction->GetVectorLength());
611 __ psrad(dst, Immediate(static_cast<uint8_t>(value)));
612 break;
613 default:
614 LOG(FATAL) << "Unsupported SIMD type";
615 UNREACHABLE();
616 }
617}
618
619void LocationsBuilderX86::VisitVecUShr(HVecUShr* instruction) {
620 CreateVecShiftLocations(GetGraph()->GetArena(), instruction);
621}
622
623void InstructionCodeGeneratorX86::VisitVecUShr(HVecUShr* instruction) {
624 LocationSummary* locations = instruction->GetLocations();
625 DCHECK(locations->InAt(0).Equals(locations->Out()));
626 int32_t value = locations->InAt(1).GetConstant()->AsIntConstant()->GetValue();
627 XmmRegister dst = locations->Out().AsFpuRegister<XmmRegister>();
628 switch (instruction->GetPackedType()) {
629 case Primitive::kPrimChar:
630 case Primitive::kPrimShort:
631 DCHECK_EQ(8u, instruction->GetVectorLength());
632 __ psrlw(dst, Immediate(static_cast<uint8_t>(value)));
633 break;
634 case Primitive::kPrimInt:
635 DCHECK_EQ(4u, instruction->GetVectorLength());
636 __ psrld(dst, Immediate(static_cast<uint8_t>(value)));
637 break;
638 case Primitive::kPrimLong:
639 DCHECK_EQ(2u, instruction->GetVectorLength());
640 __ psrlq(dst, Immediate(static_cast<uint8_t>(value)));
641 break;
642 default:
643 LOG(FATAL) << "Unsupported SIMD type";
644 UNREACHABLE();
645 }
646}
647
648// Helper to set up locations for vector memory operations.
649static void CreateVecMemLocations(ArenaAllocator* arena,
650 HVecMemoryOperation* instruction,
651 bool is_load) {
652 LocationSummary* locations = new (arena) LocationSummary(instruction);
653 switch (instruction->GetPackedType()) {
654 case Primitive::kPrimBoolean:
655 case Primitive::kPrimByte:
656 case Primitive::kPrimChar:
657 case Primitive::kPrimShort:
658 case Primitive::kPrimInt:
659 case Primitive::kPrimLong:
660 case Primitive::kPrimFloat:
661 case Primitive::kPrimDouble:
662 locations->SetInAt(0, Location::RequiresRegister());
663 locations->SetInAt(1, Location::RegisterOrConstant(instruction->InputAt(1)));
664 if (is_load) {
665 locations->SetOut(Location::RequiresFpuRegister());
666 } else {
667 locations->SetInAt(2, Location::RequiresFpuRegister());
668 }
669 break;
670 default:
671 LOG(FATAL) << "Unsupported SIMD type";
672 UNREACHABLE();
673 }
674}
675
676// Helper to set up registers and address for vector memory operations.
677static Address CreateVecMemRegisters(HVecMemoryOperation* instruction,
678 Location* reg_loc,
679 bool is_load) {
680 LocationSummary* locations = instruction->GetLocations();
681 Location base = locations->InAt(0);
682 Location index = locations->InAt(1);
683 *reg_loc = is_load ? locations->Out() : locations->InAt(2);
684 size_t size = Primitive::ComponentSize(instruction->GetPackedType());
685 uint32_t offset = mirror::Array::DataOffset(size).Uint32Value();
686 ScaleFactor scale = TIMES_1;
687 switch (size) {
688 case 2: scale = TIMES_2; break;
689 case 4: scale = TIMES_4; break;
690 case 8: scale = TIMES_8; break;
691 default: break;
692 }
693 return CodeGeneratorX86::ArrayAddress(base.AsRegister<Register>(), index, scale, offset);
694}
695
696void LocationsBuilderX86::VisitVecLoad(HVecLoad* instruction) {
697 CreateVecMemLocations(GetGraph()->GetArena(), instruction, /*is_load*/ true);
698}
699
700void InstructionCodeGeneratorX86::VisitVecLoad(HVecLoad* instruction) {
701 Location reg_loc = Location::NoLocation();
702 Address address = CreateVecMemRegisters(instruction, &reg_loc, /*is_load*/ true);
703 XmmRegister reg = reg_loc.AsFpuRegister<XmmRegister>();
704 bool is_aligned16 = instruction->GetAlignment().IsAlignedAt(16);
705 switch (instruction->GetPackedType()) {
706 case Primitive::kPrimBoolean:
707 case Primitive::kPrimByte:
708 case Primitive::kPrimChar:
709 case Primitive::kPrimShort:
710 case Primitive::kPrimInt:
711 case Primitive::kPrimLong:
712 DCHECK_LE(2u, instruction->GetVectorLength());
713 DCHECK_LE(instruction->GetVectorLength(), 16u);
714 is_aligned16 ? __ movdqa(reg, address) : __ movdqu(reg, address);
715 break;
716 case Primitive::kPrimFloat:
717 DCHECK_EQ(4u, instruction->GetVectorLength());
718 is_aligned16 ? __ movaps(reg, address) : __ movups(reg, address);
719 break;
720 case Primitive::kPrimDouble:
721 DCHECK_EQ(2u, instruction->GetVectorLength());
722 is_aligned16 ? __ movapd(reg, address) : __ movupd(reg, address);
723 break;
724 default:
725 LOG(FATAL) << "Unsupported SIMD type";
726 UNREACHABLE();
727 }
728}
729
730void LocationsBuilderX86::VisitVecStore(HVecStore* instruction) {
731 CreateVecMemLocations(GetGraph()->GetArena(), instruction, /*is_load*/ false);
732}
733
734void InstructionCodeGeneratorX86::VisitVecStore(HVecStore* instruction) {
735 Location reg_loc = Location::NoLocation();
736 Address address = CreateVecMemRegisters(instruction, &reg_loc, /*is_load*/ false);
737 XmmRegister reg = reg_loc.AsFpuRegister<XmmRegister>();
738 bool is_aligned16 = instruction->GetAlignment().IsAlignedAt(16);
739 switch (instruction->GetPackedType()) {
740 case Primitive::kPrimBoolean:
741 case Primitive::kPrimByte:
742 case Primitive::kPrimChar:
743 case Primitive::kPrimShort:
744 case Primitive::kPrimInt:
745 case Primitive::kPrimLong:
746 DCHECK_LE(2u, instruction->GetVectorLength());
747 DCHECK_LE(instruction->GetVectorLength(), 16u);
748 is_aligned16 ? __ movdqa(address, reg) : __ movdqu(address, reg);
749 break;
750 case Primitive::kPrimFloat:
751 DCHECK_EQ(4u, instruction->GetVectorLength());
752 is_aligned16 ? __ movaps(address, reg) : __ movups(address, reg);
753 break;
754 case Primitive::kPrimDouble:
755 DCHECK_EQ(2u, instruction->GetVectorLength());
756 is_aligned16 ? __ movapd(address, reg) : __ movupd(address, reg);
757 break;
758 default:
759 LOG(FATAL) << "Unsupported SIMD type";
760 UNREACHABLE();
761 }
762}
763
764#undef __
765
766} // namespace x86
767} // namespace art