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 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
328 // xzr and Register are not defined in that header. Consider adding | 341 // xzr and Register are not defined in that header. Consider adding |
329 // instructions-arm64-inl.h to work around this. | 342 // instructions-arm64-inl.h to work around this. |
330 uint64_t InstructionSequence::InlineData() const { | 343 uint64_t InstructionSequence::InlineData() const { |
331 DCHECK(IsInlineData()); | 344 DCHECK(IsInlineData()); |
332 uint64_t payload = ImmMoveWide(); | 345 uint64_t payload = ImmMoveWide(); |
333 // TODO(all): If we extend ::InlineData() to support bigger data, we need | 346 // TODO(all): If we extend ::InlineData() to support bigger data, we need |
334 // to update this method too. | 347 // to update this method too. |
335 return payload; | 348 return payload; |
336 } | 349 } |
337 | 350 |
338 | 351 VectorFormat VectorFormatHalfWidth(VectorFormat vform) { |
| 352 DCHECK(vform == kFormat8H || vform == kFormat4S || vform == kFormat2D || |
| 353 vform == kFormatH || vform == kFormatS || vform == kFormatD); |
| 354 switch (vform) { |
| 355 case kFormat8H: |
| 356 return kFormat8B; |
| 357 case kFormat4S: |
| 358 return kFormat4H; |
| 359 case kFormat2D: |
| 360 return kFormat2S; |
| 361 case kFormatH: |
| 362 return kFormatB; |
| 363 case kFormatS: |
| 364 return kFormatH; |
| 365 case kFormatD: |
| 366 return kFormatS; |
| 367 default: |
| 368 UNREACHABLE(); |
| 369 return kFormatUndefined; |
| 370 } |
| 371 } |
| 372 |
| 373 VectorFormat VectorFormatDoubleWidth(VectorFormat vform) { |
| 374 DCHECK(vform == kFormat8B || vform == kFormat4H || vform == kFormat2S || |
| 375 vform == kFormatB || vform == kFormatH || vform == kFormatS); |
| 376 switch (vform) { |
| 377 case kFormat8B: |
| 378 return kFormat8H; |
| 379 case kFormat4H: |
| 380 return kFormat4S; |
| 381 case kFormat2S: |
| 382 return kFormat2D; |
| 383 case kFormatB: |
| 384 return kFormatH; |
| 385 case kFormatH: |
| 386 return kFormatS; |
| 387 case kFormatS: |
| 388 return kFormatD; |
| 389 default: |
| 390 UNREACHABLE(); |
| 391 return kFormatUndefined; |
| 392 } |
| 393 } |
| 394 |
| 395 VectorFormat VectorFormatFillQ(VectorFormat vform) { |
| 396 switch (vform) { |
| 397 case kFormatB: |
| 398 case kFormat8B: |
| 399 case kFormat16B: |
| 400 return kFormat16B; |
| 401 case kFormatH: |
| 402 case kFormat4H: |
| 403 case kFormat8H: |
| 404 return kFormat8H; |
| 405 case kFormatS: |
| 406 case kFormat2S: |
| 407 case kFormat4S: |
| 408 return kFormat4S; |
| 409 case kFormatD: |
| 410 case kFormat1D: |
| 411 case kFormat2D: |
| 412 return kFormat2D; |
| 413 default: |
| 414 UNREACHABLE(); |
| 415 return kFormatUndefined; |
| 416 } |
| 417 } |
| 418 |
| 419 VectorFormat VectorFormatHalfWidthDoubleLanes(VectorFormat vform) { |
| 420 switch (vform) { |
| 421 case kFormat4H: |
| 422 return kFormat8B; |
| 423 case kFormat8H: |
| 424 return kFormat16B; |
| 425 case kFormat2S: |
| 426 return kFormat4H; |
| 427 case kFormat4S: |
| 428 return kFormat8H; |
| 429 case kFormat1D: |
| 430 return kFormat2S; |
| 431 case kFormat2D: |
| 432 return kFormat4S; |
| 433 default: |
| 434 UNREACHABLE(); |
| 435 return kFormatUndefined; |
| 436 } |
| 437 } |
| 438 |
| 439 VectorFormat VectorFormatDoubleLanes(VectorFormat vform) { |
| 440 DCHECK(vform == kFormat8B || vform == kFormat4H || vform == kFormat2S); |
| 441 switch (vform) { |
| 442 case kFormat8B: |
| 443 return kFormat16B; |
| 444 case kFormat4H: |
| 445 return kFormat8H; |
| 446 case kFormat2S: |
| 447 return kFormat4S; |
| 448 default: |
| 449 UNREACHABLE(); |
| 450 return kFormatUndefined; |
| 451 } |
| 452 } |
| 453 |
| 454 VectorFormat VectorFormatHalfLanes(VectorFormat vform) { |
| 455 DCHECK(vform == kFormat16B || vform == kFormat8H || vform == kFormat4S); |
| 456 switch (vform) { |
| 457 case kFormat16B: |
| 458 return kFormat8B; |
| 459 case kFormat8H: |
| 460 return kFormat4H; |
| 461 case kFormat4S: |
| 462 return kFormat2S; |
| 463 default: |
| 464 UNREACHABLE(); |
| 465 return kFormatUndefined; |
| 466 } |
| 467 } |
| 468 |
| 469 VectorFormat ScalarFormatFromLaneSize(int laneSize) { |
| 470 switch (laneSize) { |
| 471 case 8: |
| 472 return kFormatB; |
| 473 case 16: |
| 474 return kFormatH; |
| 475 case 32: |
| 476 return kFormatS; |
| 477 case 64: |
| 478 return kFormatD; |
| 479 default: |
| 480 UNREACHABLE(); |
| 481 return kFormatUndefined; |
| 482 } |
| 483 } |
| 484 |
| 485 VectorFormat ScalarFormatFromFormat(VectorFormat vform) { |
| 486 return ScalarFormatFromLaneSize(LaneSizeInBitsFromFormat(vform)); |
| 487 } |
| 488 |
| 489 unsigned RegisterSizeInBytesFromFormat(VectorFormat vform) { |
| 490 return RegisterSizeInBitsFromFormat(vform) / 8; |
| 491 } |
| 492 |
| 493 unsigned RegisterSizeInBitsFromFormat(VectorFormat vform) { |
| 494 DCHECK_NE(vform, kFormatUndefined); |
| 495 switch (vform) { |
| 496 case kFormatB: |
| 497 return kBRegSizeInBits; |
| 498 case kFormatH: |
| 499 return kHRegSizeInBits; |
| 500 case kFormatS: |
| 501 return kSRegSizeInBits; |
| 502 case kFormatD: |
| 503 return kDRegSizeInBits; |
| 504 case kFormat8B: |
| 505 case kFormat4H: |
| 506 case kFormat2S: |
| 507 case kFormat1D: |
| 508 return kDRegSizeInBits; |
| 509 default: |
| 510 return kQRegSizeInBits; |
| 511 } |
| 512 } |
| 513 |
| 514 unsigned LaneSizeInBitsFromFormat(VectorFormat vform) { |
| 515 DCHECK_NE(vform, kFormatUndefined); |
| 516 switch (vform) { |
| 517 case kFormatB: |
| 518 case kFormat8B: |
| 519 case kFormat16B: |
| 520 return 8; |
| 521 case kFormatH: |
| 522 case kFormat4H: |
| 523 case kFormat8H: |
| 524 return 16; |
| 525 case kFormatS: |
| 526 case kFormat2S: |
| 527 case kFormat4S: |
| 528 return 32; |
| 529 case kFormatD: |
| 530 case kFormat1D: |
| 531 case kFormat2D: |
| 532 return 64; |
| 533 default: |
| 534 UNREACHABLE(); |
| 535 return 0; |
| 536 } |
| 537 } |
| 538 |
| 539 int LaneSizeInBytesFromFormat(VectorFormat vform) { |
| 540 return LaneSizeInBitsFromFormat(vform) / 8; |
| 541 } |
| 542 |
| 543 int LaneSizeInBytesLog2FromFormat(VectorFormat vform) { |
| 544 DCHECK_NE(vform, kFormatUndefined); |
| 545 switch (vform) { |
| 546 case kFormatB: |
| 547 case kFormat8B: |
| 548 case kFormat16B: |
| 549 return 0; |
| 550 case kFormatH: |
| 551 case kFormat4H: |
| 552 case kFormat8H: |
| 553 return 1; |
| 554 case kFormatS: |
| 555 case kFormat2S: |
| 556 case kFormat4S: |
| 557 return 2; |
| 558 case kFormatD: |
| 559 case kFormat1D: |
| 560 case kFormat2D: |
| 561 return 3; |
| 562 default: |
| 563 UNREACHABLE(); |
| 564 return 0; |
| 565 } |
| 566 } |
| 567 |
| 568 int LaneCountFromFormat(VectorFormat vform) { |
| 569 DCHECK_NE(vform, kFormatUndefined); |
| 570 switch (vform) { |
| 571 case kFormat16B: |
| 572 return 16; |
| 573 case kFormat8B: |
| 574 case kFormat8H: |
| 575 return 8; |
| 576 case kFormat4H: |
| 577 case kFormat4S: |
| 578 return 4; |
| 579 case kFormat2S: |
| 580 case kFormat2D: |
| 581 return 2; |
| 582 case kFormat1D: |
| 583 case kFormatB: |
| 584 case kFormatH: |
| 585 case kFormatS: |
| 586 case kFormatD: |
| 587 return 1; |
| 588 default: |
| 589 UNREACHABLE(); |
| 590 return 0; |
| 591 } |
| 592 } |
| 593 |
| 594 int MaxLaneCountFromFormat(VectorFormat vform) { |
| 595 DCHECK_NE(vform, kFormatUndefined); |
| 596 switch (vform) { |
| 597 case kFormatB: |
| 598 case kFormat8B: |
| 599 case kFormat16B: |
| 600 return 16; |
| 601 case kFormatH: |
| 602 case kFormat4H: |
| 603 case kFormat8H: |
| 604 return 8; |
| 605 case kFormatS: |
| 606 case kFormat2S: |
| 607 case kFormat4S: |
| 608 return 4; |
| 609 case kFormatD: |
| 610 case kFormat1D: |
| 611 case kFormat2D: |
| 612 return 2; |
| 613 default: |
| 614 UNREACHABLE(); |
| 615 return 0; |
| 616 } |
| 617 } |
| 618 |
| 619 // Does 'vform' indicate a vector format or a scalar format? |
| 620 bool IsVectorFormat(VectorFormat vform) { |
| 621 DCHECK_NE(vform, kFormatUndefined); |
| 622 switch (vform) { |
| 623 case kFormatB: |
| 624 case kFormatH: |
| 625 case kFormatS: |
| 626 case kFormatD: |
| 627 return false; |
| 628 default: |
| 629 return true; |
| 630 } |
| 631 } |
| 632 |
| 633 int64_t MaxIntFromFormat(VectorFormat vform) { |
| 634 return INT64_MAX >> (64 - LaneSizeInBitsFromFormat(vform)); |
| 635 } |
| 636 |
| 637 int64_t MinIntFromFormat(VectorFormat vform) { |
| 638 return INT64_MIN >> (64 - LaneSizeInBitsFromFormat(vform)); |
| 639 } |
| 640 |
| 641 uint64_t MaxUintFromFormat(VectorFormat vform) { |
| 642 return UINT64_MAX >> (64 - LaneSizeInBitsFromFormat(vform)); |
| 643 } |
339 } // namespace internal | 644 } // namespace internal |
340 } // namespace v8 | 645 } // namespace v8 |
341 | 646 |
342 #endif // V8_TARGET_ARCH_ARM64 | 647 #endif // V8_TARGET_ARCH_ARM64 |
OLD | NEW |