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(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 Loading... |
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 Loading... |
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 |
OLD | NEW |