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

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

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