OLD | NEW |
1 // Copyright 2009 the V8 project authors. All rights reserved. | 1 // Copyright 2009 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
11 // with the distribution. | 11 // with the distribution. |
12 // * Neither the name of Google Inc. nor the names of its | 12 // * Neither the name of Google Inc. nor the names of its |
13 // contributors may be used to endorse or promote products derived | 13 // contributors may be used to endorse or promote products derived |
14 // from this software without specific prior written permission. | 14 // from this software without specific prior written permission. |
15 // | 15 // |
16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | 16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | 17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | 18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | 19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | 20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | 21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
27 | 27 |
28 #include <stdlib.h> | 28 #include <stdlib.h> |
29 | 29 #include <cstdarg> |
30 #include "v8.h" | 30 #include "v8.h" |
31 | 31 |
32 #include "disasm.h" | 32 #include "disasm.h" |
33 #include "assembler.h" | 33 #include "assembler.h" |
34 #include "arm/constants-arm.h" | 34 #include "arm/constants-arm.h" |
35 #include "arm/simulator-arm.h" | 35 #include "arm/simulator-arm.h" |
36 | 36 |
37 #if !defined(__arm__) | 37 #if !defined(__arm__) |
38 | 38 |
39 // Only build the simulator if not compiling for real ARM hardware. | 39 // Only build the simulator if not compiling for real ARM hardware. |
(...skipping 1369 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1409 SetCFlag(!BorrowFrom(rn_val, shifter_operand)); | 1409 SetCFlag(!BorrowFrom(rn_val, shifter_operand)); |
1410 SetVFlag(OverflowFrom(alu_out, rn_val, shifter_operand, false)); | 1410 SetVFlag(OverflowFrom(alu_out, rn_val, shifter_operand, false)); |
1411 } else { | 1411 } else { |
1412 UNIMPLEMENTED(); | 1412 UNIMPLEMENTED(); |
1413 } | 1413 } |
1414 break; | 1414 break; |
1415 } | 1415 } |
1416 | 1416 |
1417 case CMN: { | 1417 case CMN: { |
1418 if (instr->HasS()) { | 1418 if (instr->HasS()) { |
1419 Format(instr, "cmn'cond 'rn, 'shift_rm"); | 1419 // Format(instr, "cmn'cond 'rn, 'shift_rm"); |
1420 Format(instr, "cmn'cond 'rn, 'imm"); | 1420 // Format(instr, "cmn'cond 'rn, 'imm"); |
| 1421 alu_out = rn_val + shifter_operand; |
| 1422 SetNZFlags(alu_out); |
| 1423 SetCFlag(!CarryFrom(rn_val, shifter_operand)); |
| 1424 SetVFlag(OverflowFrom(alu_out, rn_val, shifter_operand, true)); |
1421 } else { | 1425 } else { |
1422 ASSERT(type == 0); | 1426 ASSERT(type == 0); |
1423 int rm = instr->RmField(); | 1427 int rm = instr->RmField(); |
1424 int rd = instr->RdField(); | 1428 int rd = instr->RdField(); |
1425 switch (instr->Bits(7, 4)) { | 1429 switch (instr->Bits(7, 4)) { |
1426 case CLZ: { | 1430 case CLZ: { |
1427 uint32_t bits = get_register(rm); | 1431 uint32_t bits = get_register(rm); |
1428 int leading_zeros = 0; | 1432 int leading_zeros = 0; |
1429 if (bits == 0) { | 1433 if (bits == 0) { |
1430 leading_zeros = 32; | 1434 leading_zeros = 32; |
(...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1559 if (instr->HasL()) { | 1563 if (instr->HasL()) { |
1560 set_register(rd, ReadW(addr, instr)); | 1564 set_register(rd, ReadW(addr, instr)); |
1561 } else { | 1565 } else { |
1562 WriteW(addr, get_register(rd), instr); | 1566 WriteW(addr, get_register(rd), instr); |
1563 } | 1567 } |
1564 } | 1568 } |
1565 } | 1569 } |
1566 | 1570 |
1567 | 1571 |
1568 void Simulator::DecodeType3(Instr* instr) { | 1572 void Simulator::DecodeType3(Instr* instr) { |
| 1573 ASSERT(instr->Bit(4) == 0); |
1569 int rd = instr->RdField(); | 1574 int rd = instr->RdField(); |
1570 int rn = instr->RnField(); | 1575 int rn = instr->RnField(); |
1571 int32_t rn_val = get_register(rn); | 1576 int32_t rn_val = get_register(rn); |
1572 bool shifter_carry_out = 0; | 1577 bool shifter_carry_out = 0; |
1573 int32_t shifter_operand = GetShiftRm(instr, &shifter_carry_out); | 1578 int32_t shifter_operand = GetShiftRm(instr, &shifter_carry_out); |
1574 int32_t addr = 0; | 1579 int32_t addr = 0; |
1575 switch (instr->PUField()) { | 1580 switch (instr->PUField()) { |
1576 case 0: { | 1581 case 0: { |
1577 ASSERT(!instr->HasW()); | 1582 ASSERT(!instr->HasW()); |
1578 Format(instr, "'memop'cond'b 'rd, ['rn], -'shift_rm"); | 1583 Format(instr, "'memop'cond'b 'rd, ['rn], -'shift_rm"); |
(...skipping 19 matching lines...) Expand all Loading... |
1598 set_register(rn, addr); | 1603 set_register(rn, addr); |
1599 } | 1604 } |
1600 break; | 1605 break; |
1601 } | 1606 } |
1602 default: { | 1607 default: { |
1603 UNREACHABLE(); | 1608 UNREACHABLE(); |
1604 break; | 1609 break; |
1605 } | 1610 } |
1606 } | 1611 } |
1607 if (instr->HasB()) { | 1612 if (instr->HasB()) { |
1608 UNIMPLEMENTED(); | 1613 if (instr->HasL()) { |
| 1614 uint8_t byte = ReadB(addr); |
| 1615 set_register(rd, byte); |
| 1616 } else { |
| 1617 UNIMPLEMENTED(); |
| 1618 } |
1609 } else { | 1619 } else { |
1610 if (instr->HasL()) { | 1620 if (instr->HasL()) { |
1611 set_register(rd, ReadW(addr, instr)); | 1621 set_register(rd, ReadW(addr, instr)); |
1612 } else { | 1622 } else { |
1613 WriteW(addr, get_register(rd), instr); | 1623 WriteW(addr, get_register(rd), instr); |
1614 } | 1624 } |
1615 } | 1625 } |
1616 } | 1626 } |
1617 | 1627 |
1618 | 1628 |
(...skipping 28 matching lines...) Expand all Loading... |
1647 void Simulator::DecodeType7(Instr* instr) { | 1657 void Simulator::DecodeType7(Instr* instr) { |
1648 if (instr->Bit(24) == 1) { | 1658 if (instr->Bit(24) == 1) { |
1649 // Format(instr, "swi 'swi"); | 1659 // Format(instr, "swi 'swi"); |
1650 SoftwareInterrupt(instr); | 1660 SoftwareInterrupt(instr); |
1651 } else { | 1661 } else { |
1652 UNIMPLEMENTED(); | 1662 UNIMPLEMENTED(); |
1653 } | 1663 } |
1654 } | 1664 } |
1655 | 1665 |
1656 | 1666 |
| 1667 void Simulator::DecodeUnconditional(Instr* instr) { |
| 1668 if (instr->Bits(7, 4) == 0x0B && instr->Bits(27, 25) == 0 && instr->HasL()) { |
| 1669 // Load halfword instruction, either register or immediate offset. |
| 1670 int rd = instr->RdField(); |
| 1671 int rn = instr->RnField(); |
| 1672 int32_t rn_val = get_register(rn); |
| 1673 int32_t addr = 0; |
| 1674 int32_t offset; |
| 1675 if (instr->Bit(22) == 0) { |
| 1676 // Register offset. |
| 1677 int rm = instr->RmField(); |
| 1678 offset = get_register(rm); |
| 1679 } else { |
| 1680 // Immediate offset |
| 1681 offset = instr->Bits(3, 0) + (instr->Bits(11, 8) << 4); |
| 1682 } |
| 1683 switch (instr->PUField()) { |
| 1684 case 0: { |
| 1685 // Post index, negative. |
| 1686 ASSERT(!instr->HasW()); |
| 1687 addr = rn_val; |
| 1688 rn_val -= offset; |
| 1689 set_register(rn, rn_val); |
| 1690 break; |
| 1691 } |
| 1692 case 1: { |
| 1693 // Post index, positive. |
| 1694 ASSERT(!instr->HasW()); |
| 1695 addr = rn_val; |
| 1696 rn_val += offset; |
| 1697 set_register(rn, rn_val); |
| 1698 break; |
| 1699 } |
| 1700 case 2: { |
| 1701 // Pre index or offset, negative. |
| 1702 rn_val -= offset; |
| 1703 addr = rn_val; |
| 1704 if (instr->HasW()) { |
| 1705 set_register(rn, rn_val); |
| 1706 } |
| 1707 break; |
| 1708 } |
| 1709 case 3: { |
| 1710 // Pre index or offset, positive. |
| 1711 rn_val += offset; |
| 1712 addr = rn_val; |
| 1713 if (instr->HasW()) { |
| 1714 set_register(rn, rn_val); |
| 1715 } |
| 1716 break; |
| 1717 } |
| 1718 default: { |
| 1719 // The PU field is a 2-bit field. |
| 1720 UNREACHABLE(); |
| 1721 break; |
| 1722 } |
| 1723 } |
| 1724 // Not sign extending, so load as unsigned. |
| 1725 uint16_t halfword = ReadH(addr, instr); |
| 1726 set_register(rd, halfword); |
| 1727 } else { |
| 1728 UNIMPLEMENTED(); |
| 1729 } |
| 1730 } |
| 1731 |
| 1732 |
1657 // Executes the current instruction. | 1733 // Executes the current instruction. |
1658 void Simulator::InstructionDecode(Instr* instr) { | 1734 void Simulator::InstructionDecode(Instr* instr) { |
1659 pc_modified_ = false; | 1735 pc_modified_ = false; |
1660 if (instr->ConditionField() == special_condition) { | |
1661 Debugger dbg(this); | |
1662 dbg.Stop(instr); | |
1663 return; | |
1664 } | |
1665 if (::v8::internal::FLAG_trace_sim) { | 1736 if (::v8::internal::FLAG_trace_sim) { |
1666 disasm::NameConverter converter; | 1737 disasm::NameConverter converter; |
1667 disasm::Disassembler dasm(converter); | 1738 disasm::Disassembler dasm(converter); |
1668 // use a reasonably large buffer | 1739 // use a reasonably large buffer |
1669 v8::internal::EmbeddedVector<char, 256> buffer; | 1740 v8::internal::EmbeddedVector<char, 256> buffer; |
1670 dasm.InstructionDecode(buffer, | 1741 dasm.InstructionDecode(buffer, |
1671 reinterpret_cast<byte*>(instr)); | 1742 reinterpret_cast<byte*>(instr)); |
1672 PrintF(" 0x%x %s\n", instr, buffer.start()); | 1743 PrintF(" 0x%x %s\n", instr, buffer.start()); |
1673 } | 1744 } |
1674 if (ConditionallyExecute(instr)) { | 1745 if (instr->ConditionField() == special_condition) { |
| 1746 DecodeUnconditional(instr); |
| 1747 } else if (ConditionallyExecute(instr)) { |
1675 switch (instr->TypeField()) { | 1748 switch (instr->TypeField()) { |
1676 case 0: | 1749 case 0: |
1677 case 1: { | 1750 case 1: { |
1678 DecodeType01(instr); | 1751 DecodeType01(instr); |
1679 break; | 1752 break; |
1680 } | 1753 } |
1681 case 2: { | 1754 case 2: { |
1682 DecodeType2(instr); | 1755 DecodeType2(instr); |
1683 break; | 1756 break; |
1684 } | 1757 } |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1740 dbg.Debug(); | 1813 dbg.Debug(); |
1741 } else { | 1814 } else { |
1742 InstructionDecode(instr); | 1815 InstructionDecode(instr); |
1743 } | 1816 } |
1744 program_counter = get_pc(); | 1817 program_counter = get_pc(); |
1745 } | 1818 } |
1746 } | 1819 } |
1747 } | 1820 } |
1748 | 1821 |
1749 | 1822 |
1750 Object* Simulator::Call(int32_t entry, int32_t p0, int32_t p1, int32_t p2, | 1823 int32_t Simulator::Call(byte* entry, int argument_count, ...) { |
1751 int32_t p3, int32_t p4) { | 1824 va_list parameters; |
1752 // Setup parameters | 1825 va_start(parameters, argument_count); |
1753 set_register(r0, p0); | 1826 // Setup arguments |
1754 set_register(r1, p1); | 1827 |
1755 set_register(r2, p2); | 1828 // First four arguments passed in registers. |
1756 set_register(r3, p3); | 1829 ASSERT(argument_count >= 4); |
1757 intptr_t* stack_pointer = reinterpret_cast<intptr_t*>(get_register(sp)); | 1830 set_register(r0, va_arg(parameters, int32_t)); |
1758 *(--stack_pointer) = p4; | 1831 set_register(r1, va_arg(parameters, int32_t)); |
1759 set_register(sp, reinterpret_cast<int32_t>(stack_pointer)); | 1832 set_register(r2, va_arg(parameters, int32_t)); |
| 1833 set_register(r3, va_arg(parameters, int32_t)); |
| 1834 |
| 1835 // Remaining arguments passed on stack. |
| 1836 int original_stack = get_register(sp); |
| 1837 // Compute position of stack on entry to generated code. |
| 1838 int entry_stack = (original_stack - (argument_count - 4) * sizeof(int32_t)); |
| 1839 if (OS::ActivationFrameAlignment() != 0) { |
| 1840 entry_stack &= -OS::ActivationFrameAlignment(); |
| 1841 } |
| 1842 // Store remaining arguments on stack, from low to high memory. |
| 1843 intptr_t* stack_argument = reinterpret_cast<intptr_t*>(entry_stack); |
| 1844 for (int i = 4; i < argument_count; i++) { |
| 1845 stack_argument[i - 4] = va_arg(parameters, int32_t); |
| 1846 } |
| 1847 va_end(parameters); |
| 1848 set_register(sp, entry_stack); |
1760 | 1849 |
1761 // Prepare to execute the code at entry | 1850 // Prepare to execute the code at entry |
1762 set_register(pc, entry); | 1851 set_register(pc, reinterpret_cast<int32_t>(entry)); |
1763 // Put down marker for end of simulation. The simulator will stop simulation | 1852 // Put down marker for end of simulation. The simulator will stop simulation |
1764 // when the PC reaches this value. By saving the "end simulation" value into | 1853 // when the PC reaches this value. By saving the "end simulation" value into |
1765 // the LR the simulation stops when returning to this call point. | 1854 // the LR the simulation stops when returning to this call point. |
1766 set_register(lr, end_sim_pc); | 1855 set_register(lr, end_sim_pc); |
1767 | 1856 |
1768 // Remember the values of callee-saved registers. | 1857 // Remember the values of callee-saved registers. |
1769 // The code below assumes that r9 is not used as sb (static base) in | 1858 // The code below assumes that r9 is not used as sb (static base) in |
1770 // simulator code and therefore is regarded as a callee-saved register. | 1859 // simulator code and therefore is regarded as a callee-saved register. |
1771 int32_t r4_val = get_register(r4); | 1860 int32_t r4_val = get_register(r4); |
1772 int32_t r5_val = get_register(r5); | 1861 int32_t r5_val = get_register(r5); |
(...skipping 13 matching lines...) Expand all Loading... |
1786 set_register(r7, callee_saved_value); | 1875 set_register(r7, callee_saved_value); |
1787 set_register(r8, callee_saved_value); | 1876 set_register(r8, callee_saved_value); |
1788 set_register(r9, callee_saved_value); | 1877 set_register(r9, callee_saved_value); |
1789 set_register(r10, callee_saved_value); | 1878 set_register(r10, callee_saved_value); |
1790 set_register(r11, callee_saved_value); | 1879 set_register(r11, callee_saved_value); |
1791 | 1880 |
1792 // Start the simulation | 1881 // Start the simulation |
1793 Execute(); | 1882 Execute(); |
1794 | 1883 |
1795 // Check that the callee-saved registers have been preserved. | 1884 // Check that the callee-saved registers have been preserved. |
1796 CHECK_EQ(get_register(r4), callee_saved_value); | 1885 CHECK_EQ(callee_saved_value, get_register(r4)); |
1797 CHECK_EQ(get_register(r5), callee_saved_value); | 1886 CHECK_EQ(callee_saved_value, get_register(r5)); |
1798 CHECK_EQ(get_register(r6), callee_saved_value); | 1887 CHECK_EQ(callee_saved_value, get_register(r6)); |
1799 CHECK_EQ(get_register(r7), callee_saved_value); | 1888 CHECK_EQ(callee_saved_value, get_register(r7)); |
1800 CHECK_EQ(get_register(r8), callee_saved_value); | 1889 CHECK_EQ(callee_saved_value, get_register(r8)); |
1801 CHECK_EQ(get_register(r9), callee_saved_value); | 1890 CHECK_EQ(callee_saved_value, get_register(r9)); |
1802 CHECK_EQ(get_register(r10), callee_saved_value); | 1891 CHECK_EQ(callee_saved_value, get_register(r10)); |
1803 CHECK_EQ(get_register(r11), callee_saved_value); | 1892 CHECK_EQ(callee_saved_value, get_register(r11)); |
1804 | 1893 |
1805 // Restore callee-saved registers with the original value. | 1894 // Restore callee-saved registers with the original value. |
1806 set_register(r4, r4_val); | 1895 set_register(r4, r4_val); |
1807 set_register(r5, r5_val); | 1896 set_register(r5, r5_val); |
1808 set_register(r6, r6_val); | 1897 set_register(r6, r6_val); |
1809 set_register(r7, r7_val); | 1898 set_register(r7, r7_val); |
1810 set_register(r8, r8_val); | 1899 set_register(r8, r8_val); |
1811 set_register(r9, r9_val); | 1900 set_register(r9, r9_val); |
1812 set_register(r10, r10_val); | 1901 set_register(r10, r10_val); |
1813 set_register(r11, r11_val); | 1902 set_register(r11, r11_val); |
1814 | 1903 |
1815 int result = get_register(r0); | 1904 // Pop stack passed arguments. |
1816 return reinterpret_cast<Object*>(result); | 1905 CHECK_EQ(entry_stack, get_register(sp)); |
| 1906 set_register(sp, original_stack); |
| 1907 |
| 1908 int32_t result = get_register(r0); |
| 1909 return result; |
1817 } | 1910 } |
1818 | 1911 |
1819 } } // namespace assembler::arm | 1912 } } // namespace assembler::arm |
1820 | 1913 |
1821 #endif // !defined(__arm__) | 1914 #endif // !defined(__arm__) |
OLD | NEW |