Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(229)

Side by Side Diff: src/arm64/instructions-arm64.cc

Issue 2622643005: ARM64: Add NEON support (Closed)
Patch Set: Restore AreConsecutive change Created 3 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2013 the V8 project authors. All rights reserved. 1 // Copyright 2013 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #if V8_TARGET_ARCH_ARM64 5 #if V8_TARGET_ARCH_ARM64
6 6
7 #define ARM64_DEFINE_FP_STATICS 7 #define ARM64_DEFINE_FP_STATICS
8 8
9 #include "src/arm64/assembler-arm64-inl.h" 9 #include "src/arm64/assembler-arm64-inl.h"
10 #include "src/arm64/instructions-arm64.h" 10 #include "src/arm64/instructions-arm64.h"
11 11
12 namespace v8 { 12 namespace v8 {
13 namespace internal { 13 namespace internal {
14 14
15 15
16 bool Instruction::IsLoad() const { 16 bool Instruction::IsLoad() const {
17 if (Mask(LoadStoreAnyFMask) != LoadStoreAnyFixed) { 17 if (Mask(LoadStoreAnyFMask) != LoadStoreAnyFixed) {
18 return false; 18 return false;
19 } 19 }
20 20
21 if (Mask(LoadStorePairAnyFMask) == LoadStorePairAnyFixed) { 21 if (Mask(LoadStorePairAnyFMask) == LoadStorePairAnyFixed) {
22 return Mask(LoadStorePairLBit) != 0; 22 return Mask(LoadStorePairLBit) != 0;
23 } else { 23 } else {
24 LoadStoreOp op = static_cast<LoadStoreOp>(Mask(LoadStoreOpMask)); 24 LoadStoreOp op = static_cast<LoadStoreOp>(Mask(LoadStoreMask));
25 switch (op) { 25 switch (op) {
26 case LDRB_w: 26 case LDRB_w:
27 case LDRH_w: 27 case LDRH_w:
28 case LDR_w: 28 case LDR_w:
29 case LDR_x: 29 case LDR_x:
30 case LDRSB_w: 30 case LDRSB_w:
31 case LDRSB_x: 31 case LDRSB_x:
32 case LDRSH_w: 32 case LDRSH_w:
33 case LDRSH_x: 33 case LDRSH_x:
34 case LDRSW_x: 34 case LDRSW_x:
35 case LDR_b:
36 case LDR_h:
35 case LDR_s: 37 case LDR_s:
36 case LDR_d: return true; 38 case LDR_d:
39 case LDR_q:
40 return true;
37 default: return false; 41 default: return false;
38 } 42 }
39 } 43 }
40 } 44 }
41 45
42 46
43 bool Instruction::IsStore() const { 47 bool Instruction::IsStore() const {
44 if (Mask(LoadStoreAnyFMask) != LoadStoreAnyFixed) { 48 if (Mask(LoadStoreAnyFMask) != LoadStoreAnyFixed) {
45 return false; 49 return false;
46 } 50 }
47 51
48 if (Mask(LoadStorePairAnyFMask) == LoadStorePairAnyFixed) { 52 if (Mask(LoadStorePairAnyFMask) == LoadStorePairAnyFixed) {
49 return Mask(LoadStorePairLBit) == 0; 53 return Mask(LoadStorePairLBit) == 0;
50 } else { 54 } else {
51 LoadStoreOp op = static_cast<LoadStoreOp>(Mask(LoadStoreOpMask)); 55 LoadStoreOp op = static_cast<LoadStoreOp>(Mask(LoadStoreMask));
52 switch (op) { 56 switch (op) {
53 case STRB_w: 57 case STRB_w:
54 case STRH_w: 58 case STRH_w:
55 case STR_w: 59 case STR_w:
56 case STR_x: 60 case STR_x:
61 case STR_b:
62 case STR_h:
57 case STR_s: 63 case STR_s:
58 case STR_d: return true; 64 case STR_d:
65 case STR_q:
66 return true;
59 default: return false; 67 default: return false;
60 } 68 }
61 } 69 }
62 } 70 }
63 71
64 72
65 static uint64_t RotateRight(uint64_t value, 73 static uint64_t RotateRight(uint64_t value,
66 unsigned int rotate, 74 unsigned int rotate,
67 unsigned int width) { 75 unsigned int width) {
68 DCHECK(width <= 64); 76 DCHECK(width <= 64);
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
132 return RepeatBitsAcrossReg(reg_size, 140 return RepeatBitsAcrossReg(reg_size,
133 RotateRight(bits, imm_r & mask, width), 141 RotateRight(bits, imm_r & mask, width),
134 width); 142 width);
135 } 143 }
136 } 144 }
137 } 145 }
138 UNREACHABLE(); 146 UNREACHABLE();
139 return 0; 147 return 0;
140 } 148 }
141 149
142 150 uint32_t Instruction::ImmNEONabcdefgh() const {
143 float Instruction::ImmFP32() { 151 return ImmNEONabc() << 5 | ImmNEONdefgh();
144 // ImmFP: abcdefgh (8 bits)
145 // Single: aBbb.bbbc.defg.h000.0000.0000.0000.0000 (32 bits)
146 // where B is b ^ 1
147 uint32_t bits = ImmFP();
148 uint32_t bit7 = (bits >> 7) & 0x1;
149 uint32_t bit6 = (bits >> 6) & 0x1;
150 uint32_t bit5_to_0 = bits & 0x3f;
151 uint32_t result = (bit7 << 31) | ((32 - bit6) << 25) | (bit5_to_0 << 19);
152
153 return rawbits_to_float(result);
154 } 152 }
155 153
154 float Instruction::ImmFP32() { return Imm8ToFP32(ImmFP()); }
156 155
157 double Instruction::ImmFP64() { 156 double Instruction::ImmFP64() { return Imm8ToFP64(ImmFP()); }
158 // ImmFP: abcdefgh (8 bits)
159 // Double: aBbb.bbbb.bbcd.efgh.0000.0000.0000.0000
160 // 0000.0000.0000.0000.0000.0000.0000.0000 (64 bits)
161 // where B is b ^ 1
162 uint32_t bits = ImmFP();
163 uint64_t bit7 = (bits >> 7) & 0x1;
164 uint64_t bit6 = (bits >> 6) & 0x1;
165 uint64_t bit5_to_0 = bits & 0x3f;
166 uint64_t result = (bit7 << 63) | ((256 - bit6) << 54) | (bit5_to_0 << 48);
167 157
168 return rawbits_to_double(result); 158 float Instruction::ImmNEONFP32() const { return Imm8ToFP32(ImmNEONabcdefgh()); }
159
160 double Instruction::ImmNEONFP64() const {
161 return Imm8ToFP64(ImmNEONabcdefgh());
169 } 162 }
170 163
164 unsigned CalcLSDataSize(LoadStoreOp op) {
165 DCHECK_EQ(static_cast<unsigned>(LSSize_offset + LSSize_width),
166 kInstructionSize * 8);
167 unsigned size = static_cast<Instr>(op) >> LSSize_offset;
168 if ((op & LSVector_mask) != 0) {
169 // Vector register memory operations encode the access size in the "size"
170 // and "opc" fields.
171 if ((size == 0) && ((op & LSOpc_mask) >> LSOpc_offset) >= 2) {
172 size = kQRegSizeLog2;
173 }
174 }
175 return size;
176 }
171 177
172 LSDataSize CalcLSPairDataSize(LoadStorePairOp op) { 178 unsigned CalcLSPairDataSize(LoadStorePairOp op) {
179 static_assert(kXRegSize == kDRegSize, "X and D registers must be same size.");
180 static_assert(kWRegSize == kSRegSize, "W and S registers must be same size.");
173 switch (op) { 181 switch (op) {
182 case STP_q:
183 case LDP_q:
184 return kQRegSizeLog2;
174 case STP_x: 185 case STP_x:
175 case LDP_x: 186 case LDP_x:
176 case STP_d: 187 case STP_d:
177 case LDP_d: return LSDoubleWord; 188 case LDP_d:
178 default: return LSWord; 189 return kXRegSizeLog2;
190 default:
191 return kWRegSizeLog2;
179 } 192 }
180 } 193 }
181 194
182 195
183 int64_t Instruction::ImmPCOffset() { 196 int64_t Instruction::ImmPCOffset() {
184 int64_t offset; 197 int64_t offset;
185 if (IsPCRelAddressing()) { 198 if (IsPCRelAddressing()) {
186 // PC-relative addressing. Only ADR is supported. 199 // PC-relative addressing. Only ADR is supported.
187 offset = ImmPCRel(); 200 offset = ImmPCRel();
188 } else if (BranchType() != UnknownBranchType) { 201 } else if (BranchType() != UnknownBranchType) {
(...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after
328 // xzr and Register are not defined in that header. Consider adding 341 // xzr and Register are not defined in that header. Consider adding
329 // instructions-arm64-inl.h to work around this. 342 // instructions-arm64-inl.h to work around this.
330 uint64_t InstructionSequence::InlineData() const { 343 uint64_t InstructionSequence::InlineData() const {
331 DCHECK(IsInlineData()); 344 DCHECK(IsInlineData());
332 uint64_t payload = ImmMoveWide(); 345 uint64_t payload = ImmMoveWide();
333 // TODO(all): If we extend ::InlineData() to support bigger data, we need 346 // TODO(all): If we extend ::InlineData() to support bigger data, we need
334 // to update this method too. 347 // to update this method too.
335 return payload; 348 return payload;
336 } 349 }
337 350
338 351 VectorFormat VectorFormatHalfWidth(VectorFormat vform) {
352 DCHECK(vform == kFormat8H || vform == kFormat4S || vform == kFormat2D ||
353 vform == kFormatH || vform == kFormatS || vform == kFormatD);
354 switch (vform) {
355 case kFormat8H:
356 return kFormat8B;
357 case kFormat4S:
358 return kFormat4H;
359 case kFormat2D:
360 return kFormat2S;
361 case kFormatH:
362 return kFormatB;
363 case kFormatS:
364 return kFormatH;
365 case kFormatD:
366 return kFormatS;
367 default:
368 UNREACHABLE();
369 return kFormatUndefined;
370 }
371 }
372
373 VectorFormat VectorFormatDoubleWidth(VectorFormat vform) {
374 DCHECK(vform == kFormat8B || vform == kFormat4H || vform == kFormat2S ||
375 vform == kFormatB || vform == kFormatH || vform == kFormatS);
376 switch (vform) {
377 case kFormat8B:
378 return kFormat8H;
379 case kFormat4H:
380 return kFormat4S;
381 case kFormat2S:
382 return kFormat2D;
383 case kFormatB:
384 return kFormatH;
385 case kFormatH:
386 return kFormatS;
387 case kFormatS:
388 return kFormatD;
389 default:
390 UNREACHABLE();
391 return kFormatUndefined;
392 }
393 }
394
395 VectorFormat VectorFormatFillQ(VectorFormat vform) {
396 switch (vform) {
397 case kFormatB:
398 case kFormat8B:
399 case kFormat16B:
400 return kFormat16B;
401 case kFormatH:
402 case kFormat4H:
403 case kFormat8H:
404 return kFormat8H;
405 case kFormatS:
406 case kFormat2S:
407 case kFormat4S:
408 return kFormat4S;
409 case kFormatD:
410 case kFormat1D:
411 case kFormat2D:
412 return kFormat2D;
413 default:
414 UNREACHABLE();
415 return kFormatUndefined;
416 }
417 }
418
419 VectorFormat VectorFormatHalfWidthDoubleLanes(VectorFormat vform) {
420 switch (vform) {
421 case kFormat4H:
422 return kFormat8B;
423 case kFormat8H:
424 return kFormat16B;
425 case kFormat2S:
426 return kFormat4H;
427 case kFormat4S:
428 return kFormat8H;
429 case kFormat1D:
430 return kFormat2S;
431 case kFormat2D:
432 return kFormat4S;
433 default:
434 UNREACHABLE();
435 return kFormatUndefined;
436 }
437 }
438
439 VectorFormat VectorFormatDoubleLanes(VectorFormat vform) {
440 DCHECK(vform == kFormat8B || vform == kFormat4H || vform == kFormat2S);
441 switch (vform) {
442 case kFormat8B:
443 return kFormat16B;
444 case kFormat4H:
445 return kFormat8H;
446 case kFormat2S:
447 return kFormat4S;
448 default:
449 UNREACHABLE();
450 return kFormatUndefined;
451 }
452 }
453
454 VectorFormat VectorFormatHalfLanes(VectorFormat vform) {
455 DCHECK(vform == kFormat16B || vform == kFormat8H || vform == kFormat4S);
456 switch (vform) {
457 case kFormat16B:
458 return kFormat8B;
459 case kFormat8H:
460 return kFormat4H;
461 case kFormat4S:
462 return kFormat2S;
463 default:
464 UNREACHABLE();
465 return kFormatUndefined;
466 }
467 }
468
469 VectorFormat ScalarFormatFromLaneSize(int laneSize) {
470 switch (laneSize) {
471 case 8:
472 return kFormatB;
473 case 16:
474 return kFormatH;
475 case 32:
476 return kFormatS;
477 case 64:
478 return kFormatD;
479 default:
480 UNREACHABLE();
481 return kFormatUndefined;
482 }
483 }
484
485 VectorFormat ScalarFormatFromFormat(VectorFormat vform) {
486 return ScalarFormatFromLaneSize(LaneSizeInBitsFromFormat(vform));
487 }
488
489 unsigned RegisterSizeInBytesFromFormat(VectorFormat vform) {
490 return RegisterSizeInBitsFromFormat(vform) / 8;
491 }
492
493 unsigned RegisterSizeInBitsFromFormat(VectorFormat vform) {
494 DCHECK_NE(vform, kFormatUndefined);
495 switch (vform) {
496 case kFormatB:
497 return kBRegSizeInBits;
498 case kFormatH:
499 return kHRegSizeInBits;
500 case kFormatS:
501 return kSRegSizeInBits;
502 case kFormatD:
503 return kDRegSizeInBits;
504 case kFormat8B:
505 case kFormat4H:
506 case kFormat2S:
507 case kFormat1D:
508 return kDRegSizeInBits;
509 default:
510 return kQRegSizeInBits;
511 }
512 }
513
514 unsigned LaneSizeInBitsFromFormat(VectorFormat vform) {
515 DCHECK_NE(vform, kFormatUndefined);
516 switch (vform) {
517 case kFormatB:
518 case kFormat8B:
519 case kFormat16B:
520 return 8;
521 case kFormatH:
522 case kFormat4H:
523 case kFormat8H:
524 return 16;
525 case kFormatS:
526 case kFormat2S:
527 case kFormat4S:
528 return 32;
529 case kFormatD:
530 case kFormat1D:
531 case kFormat2D:
532 return 64;
533 default:
534 UNREACHABLE();
535 return 0;
536 }
537 }
538
539 int LaneSizeInBytesFromFormat(VectorFormat vform) {
540 return LaneSizeInBitsFromFormat(vform) / 8;
541 }
542
543 int LaneSizeInBytesLog2FromFormat(VectorFormat vform) {
544 DCHECK_NE(vform, kFormatUndefined);
545 switch (vform) {
546 case kFormatB:
547 case kFormat8B:
548 case kFormat16B:
549 return 0;
550 case kFormatH:
551 case kFormat4H:
552 case kFormat8H:
553 return 1;
554 case kFormatS:
555 case kFormat2S:
556 case kFormat4S:
557 return 2;
558 case kFormatD:
559 case kFormat1D:
560 case kFormat2D:
561 return 3;
562 default:
563 UNREACHABLE();
564 return 0;
565 }
566 }
567
568 int LaneCountFromFormat(VectorFormat vform) {
569 DCHECK_NE(vform, kFormatUndefined);
570 switch (vform) {
571 case kFormat16B:
572 return 16;
573 case kFormat8B:
574 case kFormat8H:
575 return 8;
576 case kFormat4H:
577 case kFormat4S:
578 return 4;
579 case kFormat2S:
580 case kFormat2D:
581 return 2;
582 case kFormat1D:
583 case kFormatB:
584 case kFormatH:
585 case kFormatS:
586 case kFormatD:
587 return 1;
588 default:
589 UNREACHABLE();
590 return 0;
591 }
592 }
593
594 int MaxLaneCountFromFormat(VectorFormat vform) {
595 DCHECK_NE(vform, kFormatUndefined);
596 switch (vform) {
597 case kFormatB:
598 case kFormat8B:
599 case kFormat16B:
600 return 16;
601 case kFormatH:
602 case kFormat4H:
603 case kFormat8H:
604 return 8;
605 case kFormatS:
606 case kFormat2S:
607 case kFormat4S:
608 return 4;
609 case kFormatD:
610 case kFormat1D:
611 case kFormat2D:
612 return 2;
613 default:
614 UNREACHABLE();
615 return 0;
616 }
617 }
618
619 // Does 'vform' indicate a vector format or a scalar format?
620 bool IsVectorFormat(VectorFormat vform) {
621 DCHECK_NE(vform, kFormatUndefined);
622 switch (vform) {
623 case kFormatB:
624 case kFormatH:
625 case kFormatS:
626 case kFormatD:
627 return false;
628 default:
629 return true;
630 }
631 }
632
633 int64_t MaxIntFromFormat(VectorFormat vform) {
634 return INT64_MAX >> (64 - LaneSizeInBitsFromFormat(vform));
635 }
636
637 int64_t MinIntFromFormat(VectorFormat vform) {
638 return INT64_MIN >> (64 - LaneSizeInBitsFromFormat(vform));
639 }
640
641 uint64_t MaxUintFromFormat(VectorFormat vform) {
642 return UINT64_MAX >> (64 - LaneSizeInBitsFromFormat(vform));
643 }
644
645 NEONFormatDecoder::NEONFormatDecoder(const Instruction* instr) {
646 instrbits_ = instr->InstructionBits();
647 SetFormatMaps(IntegerFormatMap());
648 }
649
650 NEONFormatDecoder::NEONFormatDecoder(const Instruction* instr,
651 const NEONFormatMap* format) {
652 instrbits_ = instr->InstructionBits();
653 SetFormatMaps(format);
654 }
655
656 NEONFormatDecoder::NEONFormatDecoder(const Instruction* instr,
657 const NEONFormatMap* format0,
658 const NEONFormatMap* format1) {
659 instrbits_ = instr->InstructionBits();
660 SetFormatMaps(format0, format1);
661 }
662
663 NEONFormatDecoder::NEONFormatDecoder(const Instruction* instr,
664 const NEONFormatMap* format0,
665 const NEONFormatMap* format1,
666 const NEONFormatMap* format2) {
667 instrbits_ = instr->InstructionBits();
668 SetFormatMaps(format0, format1, format2);
669 }
670
671 void NEONFormatDecoder::SetFormatMaps(const NEONFormatMap* format0,
672 const NEONFormatMap* format1,
673 const NEONFormatMap* format2) {
674 DCHECK_NOT_NULL(format0);
675 formats_[0] = format0;
676 formats_[1] = (format1 == NULL) ? formats_[0] : format1;
677 formats_[2] = (format2 == NULL) ? formats_[1] : format2;
678 }
679
680 void NEONFormatDecoder::SetFormatMap(unsigned index,
681 const NEONFormatMap* format) {
682 DCHECK_LT(index, arraysize(formats_));
683 DCHECK_NOT_NULL(format);
684 formats_[index] = format;
685 }
686
687 const char* NEONFormatDecoder::SubstitutePlaceholders(const char* string) {
688 return Substitute(string, kPlaceholder, kPlaceholder, kPlaceholder);
689 }
690
691 const char* NEONFormatDecoder::Substitute(const char* string,
692 SubstitutionMode mode0,
693 SubstitutionMode mode1,
694 SubstitutionMode mode2) {
695 snprintf(form_buffer_, sizeof(form_buffer_), string, GetSubstitute(0, mode0),
696 GetSubstitute(1, mode1), GetSubstitute(2, mode2));
697 return form_buffer_;
698 }
699
700 const char* NEONFormatDecoder::Mnemonic(const char* mnemonic) {
701 if ((instrbits_ & NEON_Q) != 0) {
702 snprintf(mne_buffer_, sizeof(mne_buffer_), "%s2", mnemonic);
703 return mne_buffer_;
704 }
705 return mnemonic;
706 }
707
708 VectorFormat NEONFormatDecoder::GetVectorFormat(int format_index) {
709 return GetVectorFormat(formats_[format_index]);
710 }
711
712 VectorFormat NEONFormatDecoder::GetVectorFormat(
713 const NEONFormatMap* format_map) {
714 static const VectorFormat vform[] = {
715 kFormatUndefined, kFormat8B, kFormat16B, kFormat4H, kFormat8H,
716 kFormat2S, kFormat4S, kFormat1D, kFormat2D, kFormatB,
717 kFormatH, kFormatS, kFormatD};
718 DCHECK_LT(GetNEONFormat(format_map), arraysize(vform));
719 return vform[GetNEONFormat(format_map)];
720 }
721
722 const char* NEONFormatDecoder::GetSubstitute(int index, SubstitutionMode mode) {
723 if (mode == kFormat) {
724 return NEONFormatAsString(GetNEONFormat(formats_[index]));
725 }
726 DCHECK_EQ(mode, kPlaceholder);
727 return NEONFormatAsPlaceholder(GetNEONFormat(formats_[index]));
728 }
729
730 NEONFormat NEONFormatDecoder::GetNEONFormat(const NEONFormatMap* format_map) {
731 return format_map->map[PickBits(format_map->bits)];
732 }
733
734 const char* NEONFormatDecoder::NEONFormatAsString(NEONFormat format) {
735 static const char* formats[] = {"undefined", "8b", "16b", "4h", "8h",
736 "2s", "4s", "1d", "2d", "b",
737 "h", "s", "d"};
738 DCHECK_LT(format, arraysize(formats));
739 return formats[format];
740 }
741
742 const char* NEONFormatDecoder::NEONFormatAsPlaceholder(NEONFormat format) {
743 DCHECK((format == NF_B) || (format == NF_H) || (format == NF_S) ||
744 (format == NF_D) || (format == NF_UNDEF));
745 static const char* formats[] = {
746 "undefined", "undefined", "undefined", "undefined", "undefined",
747 "undefined", "undefined", "undefined", "undefined", "'B",
748 "'H", "'S", "'D"};
749 return formats[format];
750 }
751
752 uint8_t NEONFormatDecoder::PickBits(const uint8_t bits[]) {
753 uint8_t result = 0;
754 for (unsigned b = 0; b < kNEONFormatMaxBits; b++) {
755 if (bits[b] == 0) break;
756 result <<= 1;
757 result |= ((instrbits_ & (1 << bits[b])) == 0) ? 0 : 1;
758 }
759 return result;
760 }
339 } // namespace internal 761 } // namespace internal
340 } // namespace v8 762 } // namespace v8
341 763
342 #endif // V8_TARGET_ARCH_ARM64 764 #endif // V8_TARGET_ARCH_ARM64
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698