Changeset 50255 in webkit for trunk/JavaScriptCore/assembler/ARMv7Assembler.h
- Timestamp:
- Oct 28, 2009, 6:40:09 PM (16 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/JavaScriptCore/assembler/ARMv7Assembler.h
r48525 r50255 408 408 class ARMv7Assembler { 409 409 public: 410 ~ARMv7Assembler() 411 { 412 ASSERT(m_jumpsToLink.isEmpty()); 413 } 414 410 415 typedef ARMRegisters::RegisterID RegisterID; 411 416 typedef ARMRegisters::FPRegisterID FPRegisterID; … … 477 482 478 483 private: 484 485 struct LinkRecord { 486 LinkRecord(intptr_t from, intptr_t to) 487 : from(from) 488 , to(to) 489 { 490 } 491 492 intptr_t from; 493 intptr_t to; 494 }; 479 495 480 496 // ARMv7, Appx-A.6.3 … … 575 591 OP_BKPT = 0xBE00, 576 592 OP_IT = 0xBF00, 593 OP_NOP_T1 = 0xBF00, 577 594 } OpcodeID; 578 595 … … 609 626 OP_SUB_imm_T4 = 0xF2A0, 610 627 OP_MOVT = 0xF2C0, 628 OP_NOP_T2a = 0xF3AF, 611 629 OP_LDRH_reg_T2 = 0xF830, 612 630 OP_LDRH_imm_T3 = 0xF830, … … 627 645 typedef enum { 628 646 OP_B_T4b = 0x9000, 647 OP_NOP_T2b = 0x8000, 629 648 } OpcodeID2; 630 649 … … 1482 1501 { 1483 1502 void* copy = m_formatter.executableCopy(allocator); 1503 1504 unsigned jumpCount = m_jumpsToLink.size(); 1505 for (unsigned i = 0; i < jumpCount; ++i) { 1506 uint16_t* location = reinterpret_cast<uint16_t*>(reinterpret_cast<intptr_t>(copy) + m_jumpsToLink[i].from); 1507 uint16_t* target = reinterpret_cast<uint16_t*>(reinterpret_cast<intptr_t>(copy) + m_jumpsToLink[i].to); 1508 linkJumpAbsolute(location, target); 1509 } 1510 m_jumpsToLink.clear(); 1511 1484 1512 ASSERT(copy); 1485 1513 return copy; … … 1504 1532 ASSERT(to.m_offset != -1); 1505 1533 ASSERT(from.m_offset != -1); 1506 1507 uint16_t* location = reinterpret_cast<uint16_t*>(reinterpret_cast<intptr_t>(m_formatter.data()) + from.m_offset); 1508 intptr_t relative = to.m_offset - from.m_offset; 1509 1510 linkWithOffset(location, relative); 1534 m_jumpsToLink.append(LinkRecord(from.m_offset, to.m_offset)); 1511 1535 } 1512 1536 … … 1516 1540 1517 1541 uint16_t* location = reinterpret_cast<uint16_t*>(reinterpret_cast<intptr_t>(code) + from.m_offset); 1518 intptr_t relative = reinterpret_cast<intptr_t>(to) - reinterpret_cast<intptr_t>(location); 1519 1520 linkWithOffset(location, relative); 1542 linkJumpAbsolute(location, to); 1521 1543 } 1522 1544 … … 1542 1564 ASSERT(!(reinterpret_cast<intptr_t>(to) & 1)); 1543 1565 1544 intptr_t relative = reinterpret_cast<intptr_t>(to) - reinterpret_cast<intptr_t>(from); 1545 linkWithOffset(reinterpret_cast<uint16_t*>(from), relative); 1546 1547 ExecutableAllocator::cacheFlush(reinterpret_cast<uint16_t*>(from) - 2, 2 * sizeof(uint16_t)); 1566 linkJumpAbsolute(reinterpret_cast<uint16_t*>(from), to); 1567 1568 ExecutableAllocator::cacheFlush(reinterpret_cast<uint16_t*>(from) - 5, 5 * sizeof(uint16_t)); 1548 1569 } 1549 1570 … … 1614 1635 { 1615 1636 uint16_t* location = reinterpret_cast<uint16_t*>(code); 1616 1617 uint16_t lo16 = value; 1618 uint16_t hi16 = value >> 16;1619 1620 spliceHi5(location - 4, lo16);1621 spliceLo11(location - 3, lo16);1622 spliceHi5(location - 2, hi16);1623 spliceLo11(location - 1, hi16);1637 ASSERT(isMOV_imm_T3(location - 4) && isMOVT(location - 2)); 1638 1639 ARMThumbImmediate lo16 = ARMThumbImmediate::makeUInt16(static_cast<uint16_t>(value)); 1640 ARMThumbImmediate hi16 = ARMThumbImmediate::makeUInt16(static_cast<uint16_t>(value >> 16)); 1641 location[-4] = twoWordOp5i6Imm4Reg4EncodedImmFirst(OP_MOV_imm_T3, lo16); 1642 location[-3] = twoWordOp5i6Imm4Reg4EncodedImmSecond((location[-3] >> 8) & 0xf, lo16); 1643 location[-2] = twoWordOp5i6Imm4Reg4EncodedImmFirst(OP_MOVT, hi16); 1644 location[-1] = twoWordOp5i6Imm4Reg4EncodedImmSecond((location[-1] >> 8) & 0xf, hi16); 1624 1645 1625 1646 ExecutableAllocator::cacheFlush(location - 4, 4 * sizeof(uint16_t)); … … 1631 1652 } 1632 1653 1633 // Linking & patching: 1634 // This method assumes that the JmpSrc being linked is a T4 b instruction. 1635 static void linkWithOffset(uint16_t* instruction, intptr_t relative) 1636 { 1637 // Currently branches > 16m = mostly deathy. 1638 if (((relative << 7) >> 7) != relative) { 1639 // FIXME: This CRASH means we cannot turn the JIT on by default on arm-v7. 1640 fprintf(stderr, "Error: Cannot link T4b.\n"); 1641 CRASH(); 1642 } 1643 1644 // ARM encoding for the top two bits below the sign bit is 'peculiar'. 1645 if (relative >= 0) 1646 relative ^= 0xC00000; 1647 1648 // All branch offsets should be an even distance. 1649 ASSERT(!(relative & 1)); 1650 1651 int word1 = ((relative & 0x1000000) >> 14) | ((relative & 0x3ff000) >> 12); 1652 int word2 = ((relative & 0x800000) >> 10) | ((relative & 0x400000) >> 11) | ((relative & 0xffe) >> 1); 1653 1654 instruction[-2] = OP_B_T4a | word1; 1655 instruction[-1] = OP_B_T4b | word2; 1656 } 1657 1658 // These functions can be used to splice 16-bit immediates back into previously generated instructions. 1659 static void spliceHi5(uint16_t* where, uint16_t what) 1660 { 1661 uint16_t pattern = (what >> 12) | ((what & 0x0800) >> 1); 1662 *where = (*where & 0xFBF0) | pattern; 1663 } 1664 static void spliceLo11(uint16_t* where, uint16_t what) 1665 { 1666 uint16_t pattern = ((what & 0x0700) << 4) | (what & 0x00FF); 1667 *where = (*where & 0x8F00) | pattern; 1654 static bool isB(void* address) 1655 { 1656 uint16_t* instruction = static_cast<uint16_t*>(address); 1657 return ((instruction[0] & 0xf800) == OP_B_T4a) && ((instruction[1] & 0xd000) == OP_B_T4b); 1658 } 1659 1660 static bool isBX(void* address) 1661 { 1662 uint16_t* instruction = static_cast<uint16_t*>(address); 1663 return (instruction[0] & 0xff87) == OP_BX; 1664 } 1665 1666 static bool isMOV_imm_T3(void* address) 1667 { 1668 uint16_t* instruction = static_cast<uint16_t*>(address); 1669 return ((instruction[0] & 0xFBF0) == OP_MOV_imm_T3) && ((instruction[1] & 0x8000) == 0); 1670 } 1671 1672 static bool isMOVT(void* address) 1673 { 1674 uint16_t* instruction = static_cast<uint16_t*>(address); 1675 return ((instruction[0] & 0xFBF0) == OP_MOVT) && ((instruction[1] & 0x8000) == 0); 1676 } 1677 1678 static bool isNOP_T1(void* address) 1679 { 1680 uint16_t* instruction = static_cast<uint16_t*>(address); 1681 return instruction[0] == OP_NOP_T1; 1682 } 1683 1684 static bool isNOP_T2(void* address) 1685 { 1686 uint16_t* instruction = static_cast<uint16_t*>(address); 1687 return (instruction[0] == OP_NOP_T2a) && (instruction[1] == OP_NOP_T2b); 1688 } 1689 1690 static void linkJumpAbsolute(uint16_t* instruction, void* target) 1691 { 1692 // FIMXE: this should be up in the MacroAssembler layer. :-( 1693 const uint16_t JUMP_TEMPORARY_REGISTER = ARMRegisters::ip; 1694 1695 ASSERT(!(reinterpret_cast<intptr_t>(instruction) & 1)); 1696 ASSERT(!(reinterpret_cast<intptr_t>(target) & 1)); 1697 1698 ASSERT( (isMOV_imm_T3(instruction - 5) && isMOVT(instruction - 3) && isBX(instruction - 1)) 1699 || (isNOP_T1(instruction - 5) && isNOP_T2(instruction - 4) && isB(instruction - 2)) ); 1700 1701 intptr_t relative = reinterpret_cast<intptr_t>(target) - (reinterpret_cast<intptr_t>(instruction)); 1702 if (((relative << 7) >> 7) == relative) { 1703 // ARM encoding for the top two bits below the sign bit is 'peculiar'. 1704 if (relative >= 0) 1705 relative ^= 0xC00000; 1706 1707 // All branch offsets should be an even distance. 1708 ASSERT(!(relative & 1)); 1709 // There may be a better way to fix this, but right now put the NOPs first, since in the 1710 // case of an conditional branch this will be coming after an ITTT predicating *three* 1711 // instructions! Looking backwards to modify the ITTT to an IT is not easy, due to 1712 // variable wdith encoding - the previous instruction might *look* like an ITTT but 1713 // actually be the second half of a 2-word op. 1714 instruction[-5] = OP_NOP_T1; 1715 instruction[-4] = OP_NOP_T2a; 1716 instruction[-3] = OP_NOP_T2b; 1717 instruction[-2] = OP_B_T4a | ((relative & 0x1000000) >> 14) | ((relative & 0x3ff000) >> 12); 1718 instruction[-1] = OP_B_T4b | ((relative & 0x800000) >> 10) | ((relative & 0x400000) >> 11) | ((relative & 0xffe) >> 1); 1719 } else { 1720 ARMThumbImmediate lo16 = ARMThumbImmediate::makeUInt16(static_cast<uint16_t>(reinterpret_cast<uint32_t>(target) + 1)); 1721 ARMThumbImmediate hi16 = ARMThumbImmediate::makeUInt16(static_cast<uint16_t>(reinterpret_cast<uint32_t>(target) >> 16)); 1722 instruction[-5] = twoWordOp5i6Imm4Reg4EncodedImmFirst(OP_MOV_imm_T3, lo16); 1723 instruction[-4] = twoWordOp5i6Imm4Reg4EncodedImmSecond(JUMP_TEMPORARY_REGISTER, lo16); 1724 instruction[-3] = twoWordOp5i6Imm4Reg4EncodedImmFirst(OP_MOVT, hi16); 1725 instruction[-2] = twoWordOp5i6Imm4Reg4EncodedImmSecond(JUMP_TEMPORARY_REGISTER, hi16); 1726 instruction[-1] = OP_BX | (JUMP_TEMPORARY_REGISTER << 3); 1727 } 1728 } 1729 1730 static uint16_t twoWordOp5i6Imm4Reg4EncodedImmFirst(uint16_t op, ARMThumbImmediate imm) 1731 { 1732 return op | (imm.m_value.i << 10) | imm.m_value.imm4; 1733 } 1734 static uint16_t twoWordOp5i6Imm4Reg4EncodedImmSecond(uint16_t rd, ARMThumbImmediate imm) 1735 { 1736 return (imm.m_value.imm3 << 12) | (rd << 8) | imm.m_value.imm8; 1668 1737 } 1669 1738 … … 1724 1793 void twoWordOp5i6Imm4Reg4EncodedImm(OpcodeID1 op, int imm4, RegisterID rd, ARMThumbImmediate imm) 1725 1794 { 1726 m_buffer.putShort(op | (imm.m_value.i << 10) | imm4); 1727 m_buffer.putShort((imm.m_value.imm3 << 12) | (rd << 8) | imm.m_value.imm8); 1795 ARMThumbImmediate newImm = imm; 1796 newImm.m_value.imm4 = imm4; 1797 1798 m_buffer.putShort(ARMv7Assembler::twoWordOp5i6Imm4Reg4EncodedImmFirst(op, newImm)); 1799 m_buffer.putShort(ARMv7Assembler::twoWordOp5i6Imm4Reg4EncodedImmSecond(rd, newImm)); 1728 1800 } 1729 1801 … … 1750 1822 AssemblerBuffer m_buffer; 1751 1823 } m_formatter; 1824 1825 Vector<LinkRecord> m_jumpsToLink; 1752 1826 }; 1753 1827
Note:
See TracChangeset
for help on using the changeset viewer.