OLD | NEW |
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(LoadStoreMask)); | 24 LoadStoreOp op = static_cast<LoadStoreOp>(Mask(LoadStoreOpMask)); |
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: | |
37 case LDR_s: | 35 case LDR_s: |
38 case LDR_d: | 36 case LDR_d: return true; |
39 case LDR_q: | |
40 return true; | |
41 default: return false; | 37 default: return false; |
42 } | 38 } |
43 } | 39 } |
44 } | 40 } |
45 | 41 |
46 | 42 |
47 bool Instruction::IsStore() const { | 43 bool Instruction::IsStore() const { |
48 if (Mask(LoadStoreAnyFMask) != LoadStoreAnyFixed) { | 44 if (Mask(LoadStoreAnyFMask) != LoadStoreAnyFixed) { |
49 return false; | 45 return false; |
50 } | 46 } |
51 | 47 |
52 if (Mask(LoadStorePairAnyFMask) == LoadStorePairAnyFixed) { | 48 if (Mask(LoadStorePairAnyFMask) == LoadStorePairAnyFixed) { |
53 return Mask(LoadStorePairLBit) == 0; | 49 return Mask(LoadStorePairLBit) == 0; |
54 } else { | 50 } else { |
55 LoadStoreOp op = static_cast<LoadStoreOp>(Mask(LoadStoreMask)); | 51 LoadStoreOp op = static_cast<LoadStoreOp>(Mask(LoadStoreOpMask)); |
56 switch (op) { | 52 switch (op) { |
57 case STRB_w: | 53 case STRB_w: |
58 case STRH_w: | 54 case STRH_w: |
59 case STR_w: | 55 case STR_w: |
60 case STR_x: | 56 case STR_x: |
61 case STR_b: | |
62 case STR_h: | |
63 case STR_s: | 57 case STR_s: |
64 case STR_d: | 58 case STR_d: return true; |
65 case STR_q: | |
66 return true; | |
67 default: return false; | 59 default: return false; |
68 } | 60 } |
69 } | 61 } |
70 } | 62 } |
71 | 63 |
72 | 64 |
73 static uint64_t RotateRight(uint64_t value, | 65 static uint64_t RotateRight(uint64_t value, |
74 unsigned int rotate, | 66 unsigned int rotate, |
75 unsigned int width) { | 67 unsigned int width) { |
76 DCHECK(width <= 64); | 68 DCHECK(width <= 64); |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
140 return RepeatBitsAcrossReg(reg_size, | 132 return RepeatBitsAcrossReg(reg_size, |
141 RotateRight(bits, imm_r & mask, width), | 133 RotateRight(bits, imm_r & mask, width), |
142 width); | 134 width); |
143 } | 135 } |
144 } | 136 } |
145 } | 137 } |
146 UNREACHABLE(); | 138 UNREACHABLE(); |
147 return 0; | 139 return 0; |
148 } | 140 } |
149 | 141 |
150 uint32_t Instruction::ImmNEONabcdefgh() const { | 142 |
151 return ImmNEONabc() << 5 | ImmNEONdefgh(); | 143 float Instruction::ImmFP32() { |
| 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); |
152 } | 154 } |
153 | 155 |
154 float Instruction::ImmFP32() { return Imm8ToFP32(ImmFP()); } | |
155 | 156 |
156 double Instruction::ImmFP64() { return Imm8ToFP64(ImmFP()); } | 157 double Instruction::ImmFP64() { |
| 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); |
157 | 167 |
158 float Instruction::ImmNEONFP32() const { return Imm8ToFP32(ImmNEONabcdefgh()); } | 168 return rawbits_to_double(result); |
159 | |
160 double Instruction::ImmNEONFP64() const { | |
161 return Imm8ToFP64(ImmNEONabcdefgh()); | |
162 } | 169 } |
163 | 170 |
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 } | |
177 | 171 |
178 unsigned CalcLSPairDataSize(LoadStorePairOp op) { | 172 LSDataSize 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."); | |
181 switch (op) { | 173 switch (op) { |
182 case STP_q: | |
183 case LDP_q: | |
184 return kQRegSizeLog2; | |
185 case STP_x: | 174 case STP_x: |
186 case LDP_x: | 175 case LDP_x: |
187 case STP_d: | 176 case STP_d: |
188 case LDP_d: | 177 case LDP_d: return LSDoubleWord; |
189 return kXRegSizeLog2; | 178 default: return LSWord; |
190 default: | |
191 return kWRegSizeLog2; | |
192 } | 179 } |
193 } | 180 } |
194 | 181 |
195 | 182 |
196 int64_t Instruction::ImmPCOffset() { | 183 int64_t Instruction::ImmPCOffset() { |
197 int64_t offset; | 184 int64_t offset; |
198 if (IsPCRelAddressing()) { | 185 if (IsPCRelAddressing()) { |
199 // PC-relative addressing. Only ADR is supported. | 186 // PC-relative addressing. Only ADR is supported. |
200 offset = ImmPCRel(); | 187 offset = ImmPCRel(); |
201 } else if (BranchType() != UnknownBranchType) { | 188 } else if (BranchType() != UnknownBranchType) { |
(...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
340 // xzr and Register are not defined in that header. Consider adding | 327 // xzr and Register are not defined in that header. Consider adding |
341 // instructions-arm64-inl.h to work around this. | 328 // instructions-arm64-inl.h to work around this. |
342 uint64_t InstructionSequence::InlineData() const { | 329 uint64_t InstructionSequence::InlineData() const { |
343 DCHECK(IsInlineData()); | 330 DCHECK(IsInlineData()); |
344 uint64_t payload = ImmMoveWide(); | 331 uint64_t payload = ImmMoveWide(); |
345 // TODO(all): If we extend ::InlineData() to support bigger data, we need | 332 // TODO(all): If we extend ::InlineData() to support bigger data, we need |
346 // to update this method too. | 333 // to update this method too. |
347 return payload; | 334 return payload; |
348 } | 335 } |
349 | 336 |
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 | 337 |
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 } | |
760 } // namespace internal | 338 } // namespace internal |
761 } // namespace v8 | 339 } // namespace v8 |
762 | 340 |
763 #endif // V8_TARGET_ARCH_ARM64 | 341 #endif // V8_TARGET_ARCH_ARM64 |
OLD | NEW |