Changeset 65042 in webkit for trunk/JavaScriptCore/assembler/ARMv7Assembler.h
- Timestamp:
- Aug 9, 2010, 8:19:19 PM (15 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/JavaScriptCore/assembler/ARMv7Assembler.h
r64608 r65042 382 382 u.d = d; 383 383 384 int sign = (u.i >> 63);385 int exponent = (u.i >> 52) & 0x7ff;384 int sign = static_cast<int>(u.i >> 63); 385 int exponent = static_cast<int>(u.i >> 52) & 0x7ff; 386 386 uint64_t mantissa = u.i & 0x000fffffffffffffull; 387 387 … … 445 445 } m_u; 446 446 }; 447 448 447 449 448 class ARMv7Assembler { … … 477 476 ConditionLE, 478 477 ConditionAL, 479 478 480 479 ConditionCS = ConditionHS, 481 480 ConditionCC = ConditionLO, 482 481 } Condition; 483 482 483 enum JumpType { JumpNoCondition, JumpCondition, JumpFullSize }; 484 enum JumpLinkType { LinkInvalid, LinkShortJump, LinkConditionalShortJump, LinkLongJump, JumpTypeCount }; 485 static const int JumpSizes[JumpTypeCount]; 486 enum { JumpPaddingSize = 5 * sizeof(uint16_t) }; 487 class LinkRecord { 488 public: 489 LinkRecord(intptr_t from, intptr_t to, JumpType type, Condition condition) 490 : m_from(from) 491 , m_to(to) 492 , m_type(type) 493 , m_linkType(LinkInvalid) 494 , m_condition(condition) 495 { 496 } 497 intptr_t from() const { return m_from; } 498 void setFrom(intptr_t from) { m_from = from; } 499 intptr_t to() const { return m_to; } 500 JumpType type() const { return m_type; } 501 JumpLinkType linkType() const { return m_linkType; } 502 void setLinkType(JumpLinkType linkType) { ASSERT(m_linkType == LinkInvalid); m_linkType = linkType; } 503 Condition condition() const { return m_condition; } 504 private: 505 intptr_t m_from : 31; 506 intptr_t m_to : 31; 507 JumpType m_type : 2; 508 JumpLinkType m_linkType : 3; 509 Condition m_condition : 16; 510 }; 511 484 512 class JmpSrc { 485 513 friend class ARMv7Assembler; 486 514 friend class ARMInstructionFormatter; 515 friend class LinkBuffer; 487 516 public: 488 517 JmpSrc() … … 492 521 493 522 private: 494 JmpSrc(int offset )523 JmpSrc(int offset, JumpType type) 495 524 : m_offset(offset) 496 { 525 , m_condition(0xffff) 526 , m_type(type) 527 { 528 ASSERT(m_type != JumpCondition); 529 } 530 531 JmpSrc(int offset, JumpType type, Condition condition) 532 : m_offset(offset) 533 , m_condition(condition) 534 , m_type(type) 535 { 536 ASSERT(m_type == JumpCondition || m_type == JumpFullSize); 497 537 } 498 538 499 539 int m_offset; 540 Condition m_condition : 16; 541 JumpType m_type : 16; 542 500 543 }; 501 544 … … 503 546 friend class ARMv7Assembler; 504 547 friend class ARMInstructionFormatter; 548 friend class LinkBuffer; 505 549 public: 506 550 JmpDst() … … 525 569 526 570 private: 527 528 struct LinkRecord {529 LinkRecord(intptr_t from, intptr_t to)530 : from(from)531 , to(to)532 {533 }534 535 intptr_t from;536 intptr_t to;537 };538 571 539 572 // ARMv7, Appx-A.6.3 … … 740 773 741 774 public: 742 775 743 776 void add(RegisterID rd, RegisterID rn, ARMThumbImmediate imm) 744 777 { … … 879 912 m_formatter.twoWordOp12Reg4FourFours(OP_ASR_reg_T2, rn, FourFours(0xf, rd, 0, rm)); 880 913 } 881 914 882 915 // Only allowed in IT (if then) block if last instruction. 883 JmpSrc b( )916 JmpSrc b(JumpType type) 884 917 { 885 918 m_formatter.twoWordOp16Op16(OP_B_T4a, OP_B_T4b); 886 return JmpSrc(m_formatter.size() );919 return JmpSrc(m_formatter.size(), type); 887 920 } 888 921 889 922 // Only allowed in IT (if then) block if last instruction. 890 JmpSrc blx(RegisterID rm )923 JmpSrc blx(RegisterID rm, JumpType type) 891 924 { 892 925 ASSERT(rm != ARMRegisters::pc); 893 926 m_formatter.oneWordOp8RegReg143(OP_BLX, rm, (RegisterID)8); 894 return JmpSrc(m_formatter.size() );927 return JmpSrc(m_formatter.size(), type); 895 928 } 896 929 897 930 // Only allowed in IT (if then) block if last instruction. 898 JmpSrc bx(RegisterID rm )931 JmpSrc bx(RegisterID rm, JumpType type, Condition condition) 899 932 { 900 933 m_formatter.oneWordOp8RegReg143(OP_BX, rm, (RegisterID)0); 901 return JmpSrc(m_formatter.size()); 934 return JmpSrc(m_formatter.size(), type, condition); 935 } 936 937 JmpSrc bx(RegisterID rm, JumpType type) 938 { 939 m_formatter.oneWordOp8RegReg143(OP_BX, rm, (RegisterID)0); 940 return JmpSrc(m_formatter.size(), type); 902 941 } 903 942 … … 1618 1657 return dst.m_offset - src.m_offset; 1619 1658 } 1659 1660 int executableOffsetFor(int location) 1661 { 1662 if (!location) 1663 return 0; 1664 return static_cast<int32_t*>(m_formatter.data())[location / sizeof(int32_t) - 1]; 1665 } 1666 1667 int jumpSizeDelta(JumpLinkType jumpLinkType) { return JumpPaddingSize - JumpSizes[jumpLinkType]; } 1620 1668 1621 1669 // Assembler admin methods: … … 1626 1674 } 1627 1675 1628 void* executableCopy(ExecutablePool* allocator) 1629 { 1630 void* copy = m_formatter.executableCopy(allocator); 1631 if (!copy) 1632 return 0; 1633 1634 unsigned jumpCount = m_jumpsToLink.size(); 1635 for (unsigned i = 0; i < jumpCount; ++i) { 1636 uint16_t* location = reinterpret_cast<uint16_t*>(reinterpret_cast<intptr_t>(copy) + m_jumpsToLink[i].from); 1637 uint16_t* target = reinterpret_cast<uint16_t*>(reinterpret_cast<intptr_t>(copy) + m_jumpsToLink[i].to); 1638 linkJumpAbsolute(location, target); 1639 } 1640 m_jumpsToLink.clear(); 1641 1642 return copy; 1643 } 1644 1676 static bool linkRecordSourceComparator(const LinkRecord& a, const LinkRecord& b) 1677 { 1678 return a.from() < b.from(); 1679 } 1680 1681 JumpLinkType computeJumpType(LinkRecord& record, const uint8_t* from, const uint8_t* to) 1682 { 1683 if (record.type() >= JumpFullSize) { 1684 record.setLinkType(LinkLongJump); 1685 return LinkLongJump; 1686 } 1687 bool mayTriggerErrata = false; 1688 const uint16_t* shortJumpLocation = reinterpret_cast<const uint16_t*>(from - (JumpPaddingSize - JumpSizes[LinkShortJump])); 1689 if (!canBeShortJump(shortJumpLocation, to, mayTriggerErrata)) { 1690 record.setLinkType(LinkLongJump); 1691 return LinkLongJump; 1692 } 1693 if (mayTriggerErrata) { 1694 record.setLinkType(LinkLongJump); 1695 return LinkLongJump; 1696 } 1697 if (record.type() == JumpCondition) { 1698 record.setLinkType(LinkConditionalShortJump); 1699 return LinkConditionalShortJump; 1700 } 1701 record.setLinkType(LinkShortJump); 1702 return LinkShortJump; 1703 } 1704 1705 void recordLinkOffsets(int32_t regionStart, int32_t regionEnd, int32_t offset) 1706 { 1707 int32_t ptr = regionStart / sizeof(int32_t); 1708 const int32_t end = regionEnd / sizeof(int32_t); 1709 int32_t* offsets = static_cast<int32_t*>(m_formatter.data()); 1710 while (ptr < end) 1711 offsets[ptr++] = offset; 1712 } 1713 1714 Vector<LinkRecord>& jumpsToLink() 1715 { 1716 std::sort(m_jumpsToLink.begin(), m_jumpsToLink.end(), linkRecordSourceComparator); 1717 return m_jumpsToLink; 1718 } 1719 1720 void link(LinkRecord& record, uint8_t* from, uint8_t* to) 1721 { 1722 uint16_t* itttLocation; 1723 if (record.linkType() == LinkConditionalShortJump) { 1724 itttLocation = reinterpret_cast<uint16_t*>(from - JumpSizes[LinkConditionalShortJump] - 2); 1725 itttLocation[0] = ifThenElse(record.condition()) | OP_IT; 1726 } 1727 ASSERT(record.linkType() != LinkInvalid); 1728 if (record.linkType() != LinkLongJump) 1729 linkShortJump(reinterpret_cast<uint16_t*>(from), to); 1730 else 1731 linkLongJump(reinterpret_cast<uint16_t*>(from), to); 1732 } 1733 1734 void* unlinkedCode() { return m_formatter.data(); } 1735 1645 1736 static unsigned getCallReturnOffset(JmpSrc call) 1646 1737 { … … 1661 1752 ASSERT(to.m_offset != -1); 1662 1753 ASSERT(from.m_offset != -1); 1663 m_jumpsToLink.append(LinkRecord(from.m_offset, to.m_offset ));1754 m_jumpsToLink.append(LinkRecord(from.m_offset, to.m_offset, from.m_type, from.m_condition)); 1664 1755 } 1665 1756 … … 1864 1955 } 1865 1956 1866 static void linkJumpAbsolute(uint16_t* instruction, void* target) 1867 { 1868 // FIMXE: this should be up in the MacroAssembler layer. :-( 1869 const uint16_t JUMP_TEMPORARY_REGISTER = ARMRegisters::ip; 1870 1957 static bool canBeShortJump(const uint16_t* instruction, const void* target, bool& mayTriggerErrata) 1958 { 1871 1959 ASSERT(!(reinterpret_cast<intptr_t>(instruction) & 1)); 1872 1960 ASSERT(!(reinterpret_cast<intptr_t>(target) & 1)); 1873 1874 ASSERT( (isMOV_imm_T3(instruction - 5) && isMOVT(instruction - 3) && isBX(instruction - 1)) 1875 || (isNOP_T1(instruction - 5) && isNOP_T2(instruction - 4) && isB(instruction - 2)) ); 1876 1961 1877 1962 intptr_t relative = reinterpret_cast<intptr_t>(target) - (reinterpret_cast<intptr_t>(instruction)); 1878 1879 1963 // From Cortex-A8 errata: 1880 1964 // If the 32-bit Thumb-2 branch instruction spans two 4KiB regions and … … 1885 1969 // The instruction is spanning two pages if it ends at an address ending 0x002 1886 1970 bool spansTwo4K = ((reinterpret_cast<intptr_t>(instruction) & 0xfff) == 0x002); 1971 mayTriggerErrata = spansTwo4K; 1887 1972 // The target is in the first page if the jump branch back by [3..0x1002] bytes 1888 1973 bool targetInFirstPage = (relative >= -0x1002) && (relative < -2); 1889 1974 bool wouldTriggerA8Errata = spansTwo4K && targetInFirstPage; 1890 1891 if (((relative << 7) >> 7) == relative && !wouldTriggerA8Errata) { 1975 return ((relative << 7) >> 7) == relative && !wouldTriggerA8Errata; 1976 } 1977 1978 static void linkLongJump(uint16_t* instruction, void* target) 1979 { 1980 linkJumpAbsolute(instruction, target); 1981 } 1982 1983 static void linkShortJump(uint16_t* instruction, void* target) 1984 { 1985 // FIMXE: this should be up in the MacroAssembler layer. :-( 1986 ASSERT(!(reinterpret_cast<intptr_t>(instruction) & 1)); 1987 ASSERT(!(reinterpret_cast<intptr_t>(target) & 1)); 1988 1989 intptr_t relative = reinterpret_cast<intptr_t>(target) - (reinterpret_cast<intptr_t>(instruction)); 1990 bool scratch; 1991 UNUSED_PARAM(scratch); 1992 ASSERT(canBeShortJump(instruction, target, scratch)); 1993 // ARM encoding for the top two bits below the sign bit is 'peculiar'. 1994 if (relative >= 0) 1995 relative ^= 0xC00000; 1996 1997 // All branch offsets should be an even distance. 1998 ASSERT(!(relative & 1)); 1999 instruction[-2] = OP_B_T4a | ((relative & 0x1000000) >> 14) | ((relative & 0x3ff000) >> 12); 2000 instruction[-1] = OP_B_T4b | ((relative & 0x800000) >> 10) | ((relative & 0x400000) >> 11) | ((relative & 0xffe) >> 1); 2001 } 2002 2003 static void linkJumpAbsolute(uint16_t* instruction, void* target) 2004 { 2005 // FIMXE: this should be up in the MacroAssembler layer. :-( 2006 ASSERT(!(reinterpret_cast<intptr_t>(instruction) & 1)); 2007 ASSERT(!(reinterpret_cast<intptr_t>(target) & 1)); 2008 2009 ASSERT((isMOV_imm_T3(instruction - 5) && isMOVT(instruction - 3) && isBX(instruction - 1)) 2010 || (isNOP_T1(instruction - 5) && isNOP_T2(instruction - 4) && isB(instruction - 2))); 2011 2012 intptr_t relative = reinterpret_cast<intptr_t>(target) - (reinterpret_cast<intptr_t>(instruction)); 2013 bool scratch; 2014 if (canBeShortJump(instruction, target, scratch)) { 1892 2015 // ARM encoding for the top two bits below the sign bit is 'peculiar'. 1893 2016 if (relative >= 0) … … 1907 2030 instruction[-1] = OP_B_T4b | ((relative & 0x800000) >> 10) | ((relative & 0x400000) >> 11) | ((relative & 0xffe) >> 1); 1908 2031 } else { 2032 const uint16_t JUMP_TEMPORARY_REGISTER = ARMRegisters::ip; 1909 2033 ARMThumbImmediate lo16 = ARMThumbImmediate::makeUInt16(static_cast<uint16_t>(reinterpret_cast<uint32_t>(target) + 1)); 1910 2034 ARMThumbImmediate hi16 = ARMThumbImmediate::makeUInt16(static_cast<uint16_t>(reinterpret_cast<uint32_t>(target) >> 16)); … … 1921 2045 return op | (imm.m_value.i << 10) | imm.m_value.imm4; 1922 2046 } 2047 1923 2048 static uint16_t twoWordOp5i6Imm4Reg4EncodedImmSecond(uint16_t rd, ARMThumbImmediate imm) 1924 2049 { … … 2037 2162 2038 2163 Vector<LinkRecord> m_jumpsToLink; 2164 Vector<int32_t> m_offsets; 2039 2165 }; 2040 2166
Note:
See TracChangeset
for help on using the changeset viewer.