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

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

Issue 2812573003: Reland "ARM64: Add NEON support" (Closed)
Patch Set: Add trace directory to gitignore Created 3 years, 8 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
« no previous file with comments | « src/arm64/instructions-arm64.h ('k') | src/arm64/instrument-arm64.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 138 matching lines...) Expand 10 before | Expand all | Expand 10 after
327 // xzr and Register are not defined in that header. Consider adding 340 // xzr and Register are not defined in that header. Consider adding
328 // instructions-arm64-inl.h to work around this. 341 // instructions-arm64-inl.h to work around this.
329 uint64_t InstructionSequence::InlineData() const { 342 uint64_t InstructionSequence::InlineData() const {
330 DCHECK(IsInlineData()); 343 DCHECK(IsInlineData());
331 uint64_t payload = ImmMoveWide(); 344 uint64_t payload = ImmMoveWide();
332 // TODO(all): If we extend ::InlineData() to support bigger data, we need 345 // TODO(all): If we extend ::InlineData() to support bigger data, we need
333 // to update this method too. 346 // to update this method too.
334 return payload; 347 return payload;
335 } 348 }
336 349
337 350 VectorFormat VectorFormatHalfWidth(VectorFormat vform) {
351 DCHECK(vform == kFormat8H || vform == kFormat4S || vform == kFormat2D ||
352 vform == kFormatH || vform == kFormatS || vform == kFormatD);
353 switch (vform) {
354 case kFormat8H:
355 return kFormat8B;
356 case kFormat4S:
357 return kFormat4H;
358 case kFormat2D:
359 return kFormat2S;
360 case kFormatH:
361 return kFormatB;
362 case kFormatS:
363 return kFormatH;
364 case kFormatD:
365 return kFormatS;
366 default:
367 UNREACHABLE();
368 return kFormatUndefined;
369 }
370 }
371
372 VectorFormat VectorFormatDoubleWidth(VectorFormat vform) {
373 DCHECK(vform == kFormat8B || vform == kFormat4H || vform == kFormat2S ||
374 vform == kFormatB || vform == kFormatH || vform == kFormatS);
375 switch (vform) {
376 case kFormat8B:
377 return kFormat8H;
378 case kFormat4H:
379 return kFormat4S;
380 case kFormat2S:
381 return kFormat2D;
382 case kFormatB:
383 return kFormatH;
384 case kFormatH:
385 return kFormatS;
386 case kFormatS:
387 return kFormatD;
388 default:
389 UNREACHABLE();
390 return kFormatUndefined;
391 }
392 }
393
394 VectorFormat VectorFormatFillQ(VectorFormat vform) {
395 switch (vform) {
396 case kFormatB:
397 case kFormat8B:
398 case kFormat16B:
399 return kFormat16B;
400 case kFormatH:
401 case kFormat4H:
402 case kFormat8H:
403 return kFormat8H;
404 case kFormatS:
405 case kFormat2S:
406 case kFormat4S:
407 return kFormat4S;
408 case kFormatD:
409 case kFormat1D:
410 case kFormat2D:
411 return kFormat2D;
412 default:
413 UNREACHABLE();
414 return kFormatUndefined;
415 }
416 }
417
418 VectorFormat VectorFormatHalfWidthDoubleLanes(VectorFormat vform) {
419 switch (vform) {
420 case kFormat4H:
421 return kFormat8B;
422 case kFormat8H:
423 return kFormat16B;
424 case kFormat2S:
425 return kFormat4H;
426 case kFormat4S:
427 return kFormat8H;
428 case kFormat1D:
429 return kFormat2S;
430 case kFormat2D:
431 return kFormat4S;
432 default:
433 UNREACHABLE();
434 return kFormatUndefined;
435 }
436 }
437
438 VectorFormat VectorFormatDoubleLanes(VectorFormat vform) {
439 DCHECK(vform == kFormat8B || vform == kFormat4H || vform == kFormat2S);
440 switch (vform) {
441 case kFormat8B:
442 return kFormat16B;
443 case kFormat4H:
444 return kFormat8H;
445 case kFormat2S:
446 return kFormat4S;
447 default:
448 UNREACHABLE();
449 return kFormatUndefined;
450 }
451 }
452
453 VectorFormat VectorFormatHalfLanes(VectorFormat vform) {
454 DCHECK(vform == kFormat16B || vform == kFormat8H || vform == kFormat4S);
455 switch (vform) {
456 case kFormat16B:
457 return kFormat8B;
458 case kFormat8H:
459 return kFormat4H;
460 case kFormat4S:
461 return kFormat2S;
462 default:
463 UNREACHABLE();
464 return kFormatUndefined;
465 }
466 }
467
468 VectorFormat ScalarFormatFromLaneSize(int laneSize) {
469 switch (laneSize) {
470 case 8:
471 return kFormatB;
472 case 16:
473 return kFormatH;
474 case 32:
475 return kFormatS;
476 case 64:
477 return kFormatD;
478 default:
479 UNREACHABLE();
480 return kFormatUndefined;
481 }
482 }
483
484 VectorFormat ScalarFormatFromFormat(VectorFormat vform) {
485 return ScalarFormatFromLaneSize(LaneSizeInBitsFromFormat(vform));
486 }
487
488 unsigned RegisterSizeInBytesFromFormat(VectorFormat vform) {
489 return RegisterSizeInBitsFromFormat(vform) / 8;
490 }
491
492 unsigned RegisterSizeInBitsFromFormat(VectorFormat vform) {
493 DCHECK_NE(vform, kFormatUndefined);
494 switch (vform) {
495 case kFormatB:
496 return kBRegSizeInBits;
497 case kFormatH:
498 return kHRegSizeInBits;
499 case kFormatS:
500 return kSRegSizeInBits;
501 case kFormatD:
502 return kDRegSizeInBits;
503 case kFormat8B:
504 case kFormat4H:
505 case kFormat2S:
506 case kFormat1D:
507 return kDRegSizeInBits;
508 default:
509 return kQRegSizeInBits;
510 }
511 }
512
513 unsigned LaneSizeInBitsFromFormat(VectorFormat vform) {
514 DCHECK_NE(vform, kFormatUndefined);
515 switch (vform) {
516 case kFormatB:
517 case kFormat8B:
518 case kFormat16B:
519 return 8;
520 case kFormatH:
521 case kFormat4H:
522 case kFormat8H:
523 return 16;
524 case kFormatS:
525 case kFormat2S:
526 case kFormat4S:
527 return 32;
528 case kFormatD:
529 case kFormat1D:
530 case kFormat2D:
531 return 64;
532 default:
533 UNREACHABLE();
534 return 0;
535 }
536 }
537
538 int LaneSizeInBytesFromFormat(VectorFormat vform) {
539 return LaneSizeInBitsFromFormat(vform) / 8;
540 }
541
542 int LaneSizeInBytesLog2FromFormat(VectorFormat vform) {
543 DCHECK_NE(vform, kFormatUndefined);
544 switch (vform) {
545 case kFormatB:
546 case kFormat8B:
547 case kFormat16B:
548 return 0;
549 case kFormatH:
550 case kFormat4H:
551 case kFormat8H:
552 return 1;
553 case kFormatS:
554 case kFormat2S:
555 case kFormat4S:
556 return 2;
557 case kFormatD:
558 case kFormat1D:
559 case kFormat2D:
560 return 3;
561 default:
562 UNREACHABLE();
563 return 0;
564 }
565 }
566
567 int LaneCountFromFormat(VectorFormat vform) {
568 DCHECK_NE(vform, kFormatUndefined);
569 switch (vform) {
570 case kFormat16B:
571 return 16;
572 case kFormat8B:
573 case kFormat8H:
574 return 8;
575 case kFormat4H:
576 case kFormat4S:
577 return 4;
578 case kFormat2S:
579 case kFormat2D:
580 return 2;
581 case kFormat1D:
582 case kFormatB:
583 case kFormatH:
584 case kFormatS:
585 case kFormatD:
586 return 1;
587 default:
588 UNREACHABLE();
589 return 0;
590 }
591 }
592
593 int MaxLaneCountFromFormat(VectorFormat vform) {
594 DCHECK_NE(vform, kFormatUndefined);
595 switch (vform) {
596 case kFormatB:
597 case kFormat8B:
598 case kFormat16B:
599 return 16;
600 case kFormatH:
601 case kFormat4H:
602 case kFormat8H:
603 return 8;
604 case kFormatS:
605 case kFormat2S:
606 case kFormat4S:
607 return 4;
608 case kFormatD:
609 case kFormat1D:
610 case kFormat2D:
611 return 2;
612 default:
613 UNREACHABLE();
614 return 0;
615 }
616 }
617
618 // Does 'vform' indicate a vector format or a scalar format?
619 bool IsVectorFormat(VectorFormat vform) {
620 DCHECK_NE(vform, kFormatUndefined);
621 switch (vform) {
622 case kFormatB:
623 case kFormatH:
624 case kFormatS:
625 case kFormatD:
626 return false;
627 default:
628 return true;
629 }
630 }
631
632 int64_t MaxIntFromFormat(VectorFormat vform) {
633 return INT64_MAX >> (64 - LaneSizeInBitsFromFormat(vform));
634 }
635
636 int64_t MinIntFromFormat(VectorFormat vform) {
637 return INT64_MIN >> (64 - LaneSizeInBitsFromFormat(vform));
638 }
639
640 uint64_t MaxUintFromFormat(VectorFormat vform) {
641 return UINT64_MAX >> (64 - LaneSizeInBitsFromFormat(vform));
642 }
643
644 NEONFormatDecoder::NEONFormatDecoder(const Instruction* instr) {
645 instrbits_ = instr->InstructionBits();
646 SetFormatMaps(IntegerFormatMap());
647 }
648
649 NEONFormatDecoder::NEONFormatDecoder(const Instruction* instr,
650 const NEONFormatMap* format) {
651 instrbits_ = instr->InstructionBits();
652 SetFormatMaps(format);
653 }
654
655 NEONFormatDecoder::NEONFormatDecoder(const Instruction* instr,
656 const NEONFormatMap* format0,
657 const NEONFormatMap* format1) {
658 instrbits_ = instr->InstructionBits();
659 SetFormatMaps(format0, format1);
660 }
661
662 NEONFormatDecoder::NEONFormatDecoder(const Instruction* instr,
663 const NEONFormatMap* format0,
664 const NEONFormatMap* format1,
665 const NEONFormatMap* format2) {
666 instrbits_ = instr->InstructionBits();
667 SetFormatMaps(format0, format1, format2);
668 }
669
670 void NEONFormatDecoder::SetFormatMaps(const NEONFormatMap* format0,
671 const NEONFormatMap* format1,
672 const NEONFormatMap* format2) {
673 DCHECK_NOT_NULL(format0);
674 formats_[0] = format0;
675 formats_[1] = (format1 == NULL) ? formats_[0] : format1;
676 formats_[2] = (format2 == NULL) ? formats_[1] : format2;
677 }
678
679 void NEONFormatDecoder::SetFormatMap(unsigned index,
680 const NEONFormatMap* format) {
681 DCHECK_LT(index, arraysize(formats_));
682 DCHECK_NOT_NULL(format);
683 formats_[index] = format;
684 }
685
686 const char* NEONFormatDecoder::SubstitutePlaceholders(const char* string) {
687 return Substitute(string, kPlaceholder, kPlaceholder, kPlaceholder);
688 }
689
690 const char* NEONFormatDecoder::Substitute(const char* string,
691 SubstitutionMode mode0,
692 SubstitutionMode mode1,
693 SubstitutionMode mode2) {
694 snprintf(form_buffer_, sizeof(form_buffer_), string, GetSubstitute(0, mode0),
695 GetSubstitute(1, mode1), GetSubstitute(2, mode2));
696 return form_buffer_;
697 }
698
699 const char* NEONFormatDecoder::Mnemonic(const char* mnemonic) {
700 if ((instrbits_ & NEON_Q) != 0) {
701 snprintf(mne_buffer_, sizeof(mne_buffer_), "%s2", mnemonic);
702 return mne_buffer_;
703 }
704 return mnemonic;
705 }
706
707 VectorFormat NEONFormatDecoder::GetVectorFormat(int format_index) {
708 return GetVectorFormat(formats_[format_index]);
709 }
710
711 VectorFormat NEONFormatDecoder::GetVectorFormat(
712 const NEONFormatMap* format_map) {
713 static const VectorFormat vform[] = {
714 kFormatUndefined, kFormat8B, kFormat16B, kFormat4H, kFormat8H,
715 kFormat2S, kFormat4S, kFormat1D, kFormat2D, kFormatB,
716 kFormatH, kFormatS, kFormatD};
717 DCHECK_LT(GetNEONFormat(format_map), arraysize(vform));
718 return vform[GetNEONFormat(format_map)];
719 }
720
721 const char* NEONFormatDecoder::GetSubstitute(int index, SubstitutionMode mode) {
722 if (mode == kFormat) {
723 return NEONFormatAsString(GetNEONFormat(formats_[index]));
724 }
725 DCHECK_EQ(mode, kPlaceholder);
726 return NEONFormatAsPlaceholder(GetNEONFormat(formats_[index]));
727 }
728
729 NEONFormat NEONFormatDecoder::GetNEONFormat(const NEONFormatMap* format_map) {
730 return format_map->map[PickBits(format_map->bits)];
731 }
732
733 const char* NEONFormatDecoder::NEONFormatAsString(NEONFormat format) {
734 static const char* formats[] = {"undefined", "8b", "16b", "4h", "8h",
735 "2s", "4s", "1d", "2d", "b",
736 "h", "s", "d"};
737 DCHECK_LT(format, arraysize(formats));
738 return formats[format];
739 }
740
741 const char* NEONFormatDecoder::NEONFormatAsPlaceholder(NEONFormat format) {
742 DCHECK((format == NF_B) || (format == NF_H) || (format == NF_S) ||
743 (format == NF_D) || (format == NF_UNDEF));
744 static const char* formats[] = {
745 "undefined", "undefined", "undefined", "undefined", "undefined",
746 "undefined", "undefined", "undefined", "undefined", "'B",
747 "'H", "'S", "'D"};
748 return formats[format];
749 }
750
751 uint8_t NEONFormatDecoder::PickBits(const uint8_t bits[]) {
752 uint8_t result = 0;
753 for (unsigned b = 0; b < kNEONFormatMaxBits; b++) {
754 if (bits[b] == 0) break;
755 result <<= 1;
756 result |= ((instrbits_ & (1 << bits[b])) == 0) ? 0 : 1;
757 }
758 return result;
759 }
338 } // namespace internal 760 } // namespace internal
339 } // namespace v8 761 } // namespace v8
340 762
341 #endif // V8_TARGET_ARCH_ARM64 763 #endif // V8_TARGET_ARCH_ARM64
OLDNEW
« no previous file with comments | « src/arm64/instructions-arm64.h ('k') | src/arm64/instrument-arm64.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698