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 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
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 Loading... |
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 |
OLD | NEW |