| 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 |