Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 #ifndef VM_CONSTANTS_ARM64_H_ | 5 #ifndef VM_CONSTANTS_ARM64_H_ |
| 6 #define VM_CONSTANTS_ARM64_H_ | 6 #define VM_CONSTANTS_ARM64_H_ |
| 7 | 7 |
| 8 #include "platform/assert.h" | 8 #include "platform/assert.h" |
| 9 | 9 |
| 10 namespace dart { | 10 namespace dart { |
| (...skipping 281 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 292 }; | 292 }; |
| 293 | 293 |
| 294 // C3.4.1 | 294 // C3.4.1 |
| 295 enum AddSubImmOp { | 295 enum AddSubImmOp { |
| 296 AddSubImmMask = 0x1f000000, | 296 AddSubImmMask = 0x1f000000, |
| 297 AddSubImmFixed = DPImmediateFixed | B24, | 297 AddSubImmFixed = DPImmediateFixed | B24, |
| 298 ADDI = AddSubImmFixed, | 298 ADDI = AddSubImmFixed, |
| 299 SUBI = AddSubImmFixed | B30, | 299 SUBI = AddSubImmFixed | B30, |
| 300 }; | 300 }; |
| 301 | 301 |
| 302 // C3.4.4 | |
| 303 enum LogicalImmOp { | |
| 304 LogicalImmMask = 0x1f800000, | |
| 305 LogicalImmFixed = DPImmediateFixed | B25, | |
| 306 ANDI = LogicalImmFixed, | |
| 307 ORRI = LogicalImmFixed | B29, | |
| 308 EORI = LogicalImmFixed | B30, | |
| 309 ANDIS = LogicalImmFixed | B30 | B29, | |
| 310 }; | |
| 311 | |
| 302 // C3.4.5 | 312 // C3.4.5 |
| 303 enum MoveWideOp { | 313 enum MoveWideOp { |
| 304 MoveWideMask = 0x1f800000, | 314 MoveWideMask = 0x1f800000, |
| 305 MoveWideFixed = DPImmediateFixed | B25 | B23, | 315 MoveWideFixed = DPImmediateFixed | B25 | B23, |
| 306 MOVN = MoveWideFixed, | 316 MOVN = MoveWideFixed, |
| 307 MOVZ = MoveWideFixed | B30, | 317 MOVZ = MoveWideFixed | B30, |
| 308 MOVK = MoveWideFixed | B30 | B29, | 318 MOVK = MoveWideFixed | B30 | B29, |
| 309 }; | 319 }; |
| 310 | 320 |
| 311 | |
| 312 // C3.5.1 | 321 // C3.5.1 |
| 313 enum AddSubShiftExtOp { | 322 enum AddSubShiftExtOp { |
| 314 AddSubShiftExtMask = 0x1f000000, | 323 AddSubShiftExtMask = 0x1f000000, |
| 315 AddSubShiftExtFixed = DPRegisterFixed | B24, | 324 AddSubShiftExtFixed = DPRegisterFixed | B24, |
| 316 ADD = AddSubShiftExtFixed, | 325 ADD = AddSubShiftExtFixed, |
| 317 SUB = AddSubShiftExtFixed | B30, | 326 SUB = AddSubShiftExtFixed | B30, |
| 318 }; | 327 }; |
| 319 | 328 |
| 329 enum LogicalShiftOp { | |
| 330 LogicalShiftMask = 0x1f000000, | |
| 331 LogicalShiftFixed = DPRegisterFixed, | |
| 332 AND = LogicalShiftFixed, | |
| 333 BIC = LogicalShiftFixed | B21, | |
| 334 ORR = LogicalShiftFixed | B29, | |
| 335 ORN = LogicalShiftFixed | B29 | B21, | |
| 336 EOR = LogicalShiftFixed | B30, | |
| 337 EON = LogicalShiftFixed | B30 | B21, | |
| 338 ANDS = LogicalShiftFixed | B30 | B29, | |
| 339 BICS = LogicalShiftFixed | B30 | B29 | B21, | |
| 340 }; | |
| 341 | |
| 320 #define APPLY_OP_LIST(_V) \ | 342 #define APPLY_OP_LIST(_V) \ |
| 321 _V(DPImmediate) \ | 343 _V(DPImmediate) \ |
| 322 _V(CompareBranch) \ | 344 _V(CompareBranch) \ |
| 323 _V(LoadStore) \ | 345 _V(LoadStore) \ |
| 324 _V(DPRegister) \ | 346 _V(DPRegister) \ |
| 325 _V(DPSimd1) \ | 347 _V(DPSimd1) \ |
| 326 _V(DPSimd2) \ | 348 _V(DPSimd2) \ |
| 327 _V(ExceptionGen) \ | 349 _V(ExceptionGen) \ |
| 328 _V(System) \ | 350 _V(System) \ |
| 329 _V(LoadStoreReg) \ | 351 _V(LoadStoreReg) \ |
| 330 _V(UnconditionalBranchReg) \ | 352 _V(UnconditionalBranchReg) \ |
| 331 _V(AddSubImm) \ | 353 _V(AddSubImm) \ |
| 354 _V(LogicalImm) \ | |
| 332 _V(MoveWide) \ | 355 _V(MoveWide) \ |
| 333 _V(AddSubShiftExt) \ | 356 _V(AddSubShiftExt) \ |
| 357 _V(LogicalShift) \ | |
| 334 | 358 |
| 335 | 359 |
| 336 enum Shift { | 360 enum Shift { |
| 337 kNoShift = -1, | 361 kNoShift = -1, |
| 338 LSL = 0, // Logical shift left | 362 LSL = 0, // Logical shift left |
| 339 LSR = 1, // Logical shift right | 363 LSR = 1, // Logical shift right |
| 340 ASR = 2, // Arithmetic shift right | 364 ASR = 2, // Arithmetic shift right |
| 341 ROR = 3, // Rotate right | 365 ROR = 3, // Rotate right |
| 342 kMaxShift = 4, | 366 kMaxShift = 4, |
| 343 }; | 367 }; |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 395 kImm6Bits = 6, | 419 kImm6Bits = 6, |
| 396 kImm9Shift = 12, | 420 kImm9Shift = 12, |
| 397 kImm9Bits = 9, | 421 kImm9Bits = 9, |
| 398 kImm12Shift = 10, | 422 kImm12Shift = 10, |
| 399 kImm12Bits = 12, | 423 kImm12Bits = 12, |
| 400 kImm12ShiftShift = 22, | 424 kImm12ShiftShift = 22, |
| 401 kImm12ShiftBits = 2, | 425 kImm12ShiftBits = 2, |
| 402 kImm16Shift = 5, | 426 kImm16Shift = 5, |
| 403 kImm16Bits = 16, | 427 kImm16Bits = 16, |
| 404 | 428 |
| 429 // Bitfield immediates. | |
| 430 kNShift = 22, | |
| 431 kNBits = 1, | |
| 432 kImmRShift = 16, | |
| 433 kImmRBits = 6, | |
| 434 kImmSShift = 10, | |
| 435 kImmSBits = 6, | |
| 436 | |
| 405 kHWShift = 21, | 437 kHWShift = 21, |
| 406 kHWBits = 2, | 438 kHWBits = 2, |
| 407 | 439 |
| 408 // Shift and Extend. | 440 // Shift and Extend. |
| 409 kShiftExtendShift = 21, | 441 kAddShiftExtendShift = 21, |
| 410 kShiftExtendBits = 1, | 442 kAddShiftExtendBits = 1, |
| 411 kShiftTypeShift = 22, | 443 kShiftTypeShift = 22, |
| 412 kShiftTypeBits = 2, | 444 kShiftTypeBits = 2, |
| 413 kExtendTypeShift = 13, | 445 kExtendTypeShift = 13, |
| 414 kExtendTypeBits = 3, | 446 kExtendTypeBits = 3, |
| 415 | 447 |
| 416 // Hint Fields. | 448 // Hint Fields. |
| 417 kHintCRmShift = 8, | 449 kHintCRmShift = 8, |
| 418 kHintCRmBits = 4, | 450 kHintCRmBits = 4, |
| 419 kHintOp2Shift = 5, | 451 kHintOp2Shift = 5, |
| 420 kHintOp2Bits = 3, | 452 kHintOp2Bits = 3, |
| 421 }; | 453 }; |
| 422 | 454 |
| 423 | 455 |
| 424 const uint32_t kImmExceptionIsRedirectedCall = 0xca11; | 456 const uint32_t kImmExceptionIsRedirectedCall = 0xca11; |
| 425 const uint32_t kImmExceptionIsUnreachable = 0xdebf; | 457 const uint32_t kImmExceptionIsUnreachable = 0xdebf; |
| 426 const uint32_t kImmExceptionIsPrintf = 0xdeb1; | 458 const uint32_t kImmExceptionIsPrintf = 0xdeb1; |
| 427 const uint32_t kImmExceptionIsDebug = 0xdeb0; | 459 const uint32_t kImmExceptionIsDebug = 0xdeb0; |
| 428 | 460 |
| 461 // Helper functions for decoding logical immediates. | |
| 462 static inline uint64_t RotateRight( | |
| 463 uint64_t value, uint8_t rotate, uint8_t width) { | |
| 464 ASSERT(width <= 64); | |
| 465 rotate &= 63; | |
| 466 return ((value & ((1UL << rotate) - 1UL)) << (width - rotate)) | | |
| 467 (value >> rotate); | |
| 468 } | |
| 469 | |
| 470 static inline uint64_t RepeatBitsAcrossReg( | |
| 471 uint8_t reg_size, uint64_t value, uint8_t width) { | |
| 472 ASSERT((width == 2) || (width == 4) || (width == 8) || (width == 16) || | |
| 473 (width == 32)); | |
| 474 ASSERT((reg_size == kWRegSizeInBits) || (reg_size == kXRegSizeInBits)); | |
| 475 uint64_t result = value & ((1UL << width) - 1UL); | |
| 476 for (unsigned i = width; i < reg_size; i *= 2) { | |
| 477 result |= (result << i); | |
| 478 } | |
| 479 return result; | |
| 480 } | |
| 481 | |
| 429 // The class Instr enables access to individual fields defined in the ARM | 482 // The class Instr enables access to individual fields defined in the ARM |
| 430 // architecture instruction set encoding as described in figure A3-1. | 483 // architecture instruction set encoding as described in figure A3-1. |
| 431 // | 484 // |
| 432 // Example: Test whether the instruction at ptr sets the condition code bits. | 485 // Example: Test whether the instruction at ptr sets the condition code bits. |
| 433 // | 486 // |
| 434 // bool InstructionSetsConditionCodes(byte* ptr) { | 487 // bool InstructionSetsConditionCodes(byte* ptr) { |
| 435 // Instr* instr = Instr::At(ptr); | 488 // Instr* instr = Instr::At(ptr); |
| 436 // int type = instr->TypeField(); | 489 // int type = instr->TypeField(); |
| 437 // return ((type == 0) || (type == 1)) && instr->HasS(); | 490 // return ((type == 0) || (type == 1)) && instr->HasS(); |
| 438 // } | 491 // } |
| (...skipping 24 matching lines...) Expand all Loading... | |
| 463 // Read one particular bit out of the instruction bits. | 516 // Read one particular bit out of the instruction bits. |
| 464 inline int Bit(int nr) const { | 517 inline int Bit(int nr) const { |
| 465 return (InstructionBits() >> nr) & 1; | 518 return (InstructionBits() >> nr) & 1; |
| 466 } | 519 } |
| 467 | 520 |
| 468 // Read a bit field out of the instruction bits. | 521 // Read a bit field out of the instruction bits. |
| 469 inline int Bits(int shift, int count) const { | 522 inline int Bits(int shift, int count) const { |
| 470 return (InstructionBits() >> shift) & ((1 << count) - 1); | 523 return (InstructionBits() >> shift) & ((1 << count) - 1); |
| 471 } | 524 } |
| 472 | 525 |
| 473 | 526 inline int NField() const { return Bit(22); } |
| 474 inline int SField() const { return Bit(kSShift); } | 527 inline int SField() const { return Bit(kSShift); } |
| 475 inline int SFField() const { return Bit(kSFShift); } | 528 inline int SFField() const { return Bit(kSFShift); } |
| 476 inline int SzField() const { return Bits(kSzShift, kSzBits); } | 529 inline int SzField() const { return Bits(kSzShift, kSzBits); } |
| 477 inline Register RdField() const { return static_cast<Register>( | 530 inline Register RdField() const { return static_cast<Register>( |
| 478 Bits(kRdShift, kRdBits)); } | 531 Bits(kRdShift, kRdBits)); } |
| 479 inline Register RnField() const { return static_cast<Register>( | 532 inline Register RnField() const { return static_cast<Register>( |
| 480 Bits(kRnShift, kRnBits)); } | 533 Bits(kRnShift, kRnBits)); } |
| 481 inline Register RaField() const { return static_cast<Register>( | 534 inline Register RaField() const { return static_cast<Register>( |
| 482 Bits(kRaShift, kRaBits)); } | 535 Bits(kRaShift, kRaBits)); } |
| 483 inline Register RmField() const { return static_cast<Register>( | 536 inline Register RmField() const { return static_cast<Register>( |
| 484 Bits(kRmShift, kRmBits)); } | 537 Bits(kRmShift, kRmBits)); } |
| 485 inline Register RtField() const { return static_cast<Register>( | 538 inline Register RtField() const { return static_cast<Register>( |
| 486 Bits(kRtShift, kRtBits)); } | 539 Bits(kRtShift, kRtBits)); } |
| 487 | 540 |
| 488 // Immediates | 541 // Immediates |
| 489 inline int Imm3Field() const { return Bits(kImm3Shift, kImm3Bits); } | 542 inline int Imm3Field() const { return Bits(kImm3Shift, kImm3Bits); } |
| 490 inline int Imm6Field() const { return Bits(kImm6Shift, kImm6Bits); } | 543 inline int Imm6Field() const { return Bits(kImm6Shift, kImm6Bits); } |
| 544 | |
| 491 inline int Imm9Field() const { return Bits(kImm9Shift, kImm9Bits); } | 545 inline int Imm9Field() const { return Bits(kImm9Shift, kImm9Bits); } |
| 492 // Sign-extended Imm9Field() | 546 // Sign-extended Imm9Field() |
| 493 inline int64_t SImm9Field() const { | 547 inline int64_t SImm9Field() const { |
| 494 return (static_cast<int32_t>(Imm9Field()) << 23) >> 23; } | 548 return (static_cast<int32_t>(Imm9Field()) << 23) >> 23; } |
| 549 | |
| 495 inline int Imm12Field() const { return Bits(kImm12Shift, kImm12Bits); } | 550 inline int Imm12Field() const { return Bits(kImm12Shift, kImm12Bits); } |
| 496 inline int Imm16Field() const { return Bits(kImm16Shift, kImm16Bits); } | |
| 497 | |
| 498 inline int Imm12ShiftField() const { | 551 inline int Imm12ShiftField() const { |
| 499 return Bits(kImm12ShiftShift, kImm12ShiftBits); } | 552 return Bits(kImm12ShiftShift, kImm12ShiftBits); } |
| 553 | |
| 554 inline int Imm16Field() const { return Bits(kImm16Shift, kImm16Bits); } | |
| 500 inline int HWField() const { return Bits(kHWShift, kHWBits); } | 555 inline int HWField() const { return Bits(kHWShift, kHWBits); } |
| 501 | 556 |
| 557 inline int ImmRField() const { return Bits(kImmRShift, kImmRBits); } | |
| 558 inline int ImmSField() const { return Bits(kImmSShift, kImmSBits); } | |
| 559 | |
| 502 // Shift and Extend. | 560 // Shift and Extend. |
| 503 inline bool IsShift() const { return (Bit(kShiftExtendShift) == 0); } | 561 inline bool IsShift() const { |
| 504 inline bool IsExtend() const { return (Bit(kShiftExtendShift) == 1); } | 562 return IsLogicalShiftOp() || (Bit(kAddShiftExtendShift) == 0); |
| 563 } | |
| 564 inline bool IsExtend() const { | |
| 565 return !IsLogicalShiftOp() && (Bit(kAddShiftExtendShift) == 1); | |
| 566 } | |
| 505 inline Shift ShiftTypeField() const { | 567 inline Shift ShiftTypeField() const { |
| 506 return static_cast<Shift>(Bits(kShiftTypeShift, kShiftTypeBits)); } | 568 return static_cast<Shift>(Bits(kShiftTypeShift, kShiftTypeBits)); } |
| 507 inline Extend ExtendTypeField() const { | 569 inline Extend ExtendTypeField() const { |
| 508 return static_cast<Extend>(Bits(kExtendTypeShift, kExtendTypeBits)); } | 570 return static_cast<Extend>(Bits(kExtendTypeShift, kExtendTypeBits)); } |
| 509 inline int ShiftAmountField() const { return Imm6Field(); } | 571 inline int ShiftAmountField() const { return Imm6Field(); } |
| 510 inline int ExtShiftAmountField() const { return Imm3Field(); } | 572 inline int ExtShiftAmountField() const { return Imm3Field(); } |
| 511 | 573 |
| 512 // Instruction identification. | 574 // Instruction identification. |
| 513 #define IS_OP(op) \ | 575 #define IS_OP(op) \ |
| 514 inline bool Is##op##Op() const { \ | 576 inline bool Is##op##Op() const { \ |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 546 // Add/sub (extended). | 608 // Add/sub (extended). |
| 547 // Otherwise, r31 is ZR. | 609 // Otherwise, r31 is ZR. |
| 548 if (IsLoadStoreOp() || | 610 if (IsLoadStoreOp() || |
| 549 IsAddSubImmOp() || | 611 IsAddSubImmOp() || |
| 550 (IsAddSubShiftExtOp() && IsExtend())) { | 612 (IsAddSubShiftExtOp() && IsExtend())) { |
| 551 return R31IsSP; | 613 return R31IsSP; |
| 552 } | 614 } |
| 553 return R31IsZR; | 615 return R31IsZR; |
| 554 } | 616 } |
| 555 | 617 |
| 618 // Logical immediates can't encode zero, so a return value of zero is used to | |
| 619 // indicate a failure case. Specifically, where the constraints on imm_s are | |
| 620 // not met. | |
| 621 uint64_t ImmLogical() { | |
| 622 const uint8_t reg_size = | |
| 623 SFField() == 1 ? kXRegSizeInBits : kWRegSizeInBits; | |
| 624 const int64_t n = NField(); | |
| 625 const int64_t imm_s = ImmSField(); | |
| 626 const int64_t imm_r = ImmRField(); | |
| 627 | |
| 628 // An integer is constructed from the n, imm_s and imm_r bits according to | |
| 629 // the following table: | |
|
regis
2014/04/09 20:49:49
What is the relation between the resulting integer
| |
| 630 // | |
| 631 // N imms immr size S R | |
| 632 // 1 ssssss rrrrrr 64 UInt(ssssss) UInt(rrrrrr) | |
| 633 // 0 0sssss xrrrrr 32 UInt(sssss) UInt(rrrrr) | |
| 634 // 0 10ssss xxrrrr 16 UInt(ssss) UInt(rrrr) | |
| 635 // 0 110sss xxxrrr 8 UInt(sss) UInt(rrr) | |
| 636 // 0 1110ss xxxxrr 4 UInt(ss) UInt(rr) | |
| 637 // 0 11110s xxxxxr 2 UInt(s) UInt(r) | |
| 638 // (s bits must not be all set) | |
| 639 // | |
| 640 // A pattern is constructed of size bits, where the least significant S+1 | |
| 641 // bits are set. The pattern is rotated right by R, and repeated across a | |
| 642 // 32 or 64-bit value, depending on destination register width. | |
|
regis
2014/04/09 20:49:49
I see now.
| |
| 643 | |
| 644 if (n == 1) { | |
| 645 if (imm_s == 0x3F) { | |
| 646 return 0; | |
| 647 } | |
| 648 uint64_t bits = (1UL << (imm_s + 1)) - 1; | |
| 649 return RotateRight(bits, imm_r, 64); | |
| 650 } else { | |
| 651 if ((imm_s >> 1) == 0x1F) { | |
| 652 return 0; | |
| 653 } | |
| 654 for (int width = 0x20; width >= 0x2; width >>= 1) { | |
| 655 if ((imm_s & width) == 0) { | |
| 656 int mask = width - 1; | |
| 657 if ((imm_s & mask) == mask) { | |
| 658 return 0; | |
| 659 } | |
| 660 uint64_t bits = (1UL << ((imm_s & mask) + 1)) - 1; | |
| 661 return RepeatBitsAcrossReg(reg_size, | |
| 662 RotateRight(bits, imm_r & mask, width), | |
| 663 width); | |
| 664 } | |
| 665 } | |
| 666 } | |
| 667 UNREACHABLE(); | |
| 668 return 0; | |
| 669 } | |
| 670 | |
| 556 // Instructions are read out of a code stream. The only way to get a | 671 // Instructions are read out of a code stream. The only way to get a |
| 557 // reference to an instruction is to convert a pointer. There is no way | 672 // reference to an instruction is to convert a pointer. There is no way |
| 558 // to allocate or create instances of class Instr. | 673 // to allocate or create instances of class Instr. |
| 559 // Use the At(pc) function to create references to Instr. | 674 // Use the At(pc) function to create references to Instr. |
| 560 static Instr* At(uword pc) { return reinterpret_cast<Instr*>(pc); } | 675 static Instr* At(uword pc) { return reinterpret_cast<Instr*>(pc); } |
| 561 | 676 |
| 562 private: | 677 private: |
| 563 DISALLOW_ALLOCATION(); | 678 DISALLOW_ALLOCATION(); |
| 564 DISALLOW_IMPLICIT_CONSTRUCTORS(Instr); | 679 DISALLOW_IMPLICIT_CONSTRUCTORS(Instr); |
| 565 }; | 680 }; |
| 566 | 681 |
| 567 } // namespace dart | 682 } // namespace dart |
| 568 | 683 |
| 569 #endif // VM_CONSTANTS_ARM64_H_ | 684 #endif // VM_CONSTANTS_ARM64_H_ |
| OLD | NEW |