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 #include <stdlib.h> | 5 #include <stdlib.h> |
6 #include <cmath> | 6 #include <cmath> |
7 #include <cstdarg> | 7 #include <cstdarg> |
8 #include "src/v8.h" | 8 #include "src/v8.h" |
9 | 9 |
10 #if V8_TARGET_ARCH_ARM64 | 10 #if V8_TARGET_ARCH_ARM64 |
(...skipping 1122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1133 } | 1133 } |
1134 | 1134 |
1135 | 1135 |
1136 void Simulator::PrintProcessorState() { | 1136 void Simulator::PrintProcessorState() { |
1137 PrintSystemRegisters(); | 1137 PrintSystemRegisters(); |
1138 PrintRegisters(); | 1138 PrintRegisters(); |
1139 PrintFPRegisters(); | 1139 PrintFPRegisters(); |
1140 } | 1140 } |
1141 | 1141 |
1142 | 1142 |
1143 void Simulator::PrintWrite(uint8_t* address, | 1143 void Simulator::PrintWrite(uintptr_t address, uint64_t value, |
1144 uint64_t value, | |
1145 unsigned num_bytes) { | 1144 unsigned num_bytes) { |
1146 // The template is "# value -> address". The template is not directly used | 1145 // The template is "# value -> address". The format string is not used |
1147 // in the printf since compilers tend to struggle with the parametrized | 1146 // directly in the printf because some compilers struggle with the |
1148 // width (%0*). | 1147 // parametrized width field (%0*). |
1149 const char* format = "# %s0x%0*" PRIx64 "%s -> %s0x%016" PRIx64 "%s\n"; | 1148 const char* format = "# %s0x%0*" PRIx64 "%s -> %s0x%016" PRIxPTR "%s\n"; |
1150 fprintf(stream_, | 1149 fprintf(stream_, |
1151 format, | 1150 format, |
1152 clr_memory_value, | 1151 clr_memory_value, |
1153 num_bytes * 2, // The width in hexa characters. | 1152 num_bytes * 2, // The width in hexadecimal characters. |
1154 value, | 1153 value, |
1155 clr_normal, | 1154 clr_normal, |
1156 clr_memory_address, | 1155 clr_memory_address, |
1157 address, | 1156 address, |
1158 clr_normal); | 1157 clr_normal); |
1159 } | 1158 } |
1160 | 1159 |
1161 | 1160 |
1162 // Visitors--------------------------------------------------------------------- | 1161 // Visitors--------------------------------------------------------------------- |
1163 | 1162 |
(...skipping 294 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1458 LoadStoreHelper(instr, offset, Offset); | 1457 LoadStoreHelper(instr, offset, Offset); |
1459 } | 1458 } |
1460 | 1459 |
1461 | 1460 |
1462 void Simulator::LoadStoreHelper(Instruction* instr, | 1461 void Simulator::LoadStoreHelper(Instruction* instr, |
1463 int64_t offset, | 1462 int64_t offset, |
1464 AddrMode addrmode) { | 1463 AddrMode addrmode) { |
1465 unsigned srcdst = instr->Rt(); | 1464 unsigned srcdst = instr->Rt(); |
1466 unsigned addr_reg = instr->Rn(); | 1465 unsigned addr_reg = instr->Rn(); |
1467 uint8_t* address = LoadStoreAddress(addr_reg, offset, addrmode); | 1466 uint8_t* address = LoadStoreAddress(addr_reg, offset, addrmode); |
1468 int num_bytes = 1 << instr->SizeLS(); | |
1469 uint8_t* stack = NULL; | 1467 uint8_t* stack = NULL; |
1470 | 1468 |
1471 // Handle the writeback for stores before the store. On a CPU the writeback | 1469 // Handle the writeback for stores before the store. On a CPU the writeback |
1472 // and the store are atomic, but when running on the simulator it is possible | 1470 // and the store are atomic, but when running on the simulator it is possible |
1473 // to be interrupted in between. The simulator is not thread safe and V8 does | 1471 // to be interrupted in between. The simulator is not thread safe and V8 does |
1474 // not require it to be to run JavaScript therefore the profiler may sample | 1472 // not require it to be to run JavaScript therefore the profiler may sample |
1475 // the "simulated" CPU in the middle of load/store with writeback. The code | 1473 // the "simulated" CPU in the middle of load/store with writeback. The code |
1476 // below ensures that push operations are safe even when interrupted: the | 1474 // below ensures that push operations are safe even when interrupted: the |
1477 // stack pointer will be decremented before adding an element to the stack. | 1475 // stack pointer will be decremented before adding an element to the stack. |
1478 if (instr->IsStore()) { | 1476 if (instr->IsStore()) { |
1479 LoadStoreWriteBack(addr_reg, offset, addrmode); | 1477 LoadStoreWriteBack(addr_reg, offset, addrmode); |
1480 | 1478 |
1481 // For store the address post writeback is used to check access below the | 1479 // For store the address post writeback is used to check access below the |
1482 // stack. | 1480 // stack. |
1483 stack = reinterpret_cast<uint8_t*>(sp()); | 1481 stack = reinterpret_cast<uint8_t*>(sp()); |
1484 } | 1482 } |
1485 | 1483 |
1486 LoadStoreOp op = static_cast<LoadStoreOp>(instr->Mask(LoadStoreOpMask)); | 1484 LoadStoreOp op = static_cast<LoadStoreOp>(instr->Mask(LoadStoreOpMask)); |
1487 switch (op) { | 1485 switch (op) { |
1488 case LDRB_w: | 1486 case LDRB_w: set_wreg(srcdst, MemoryRead<uint8_t>(address)); break; |
1489 case LDRH_w: | 1487 case LDRH_w: set_wreg(srcdst, MemoryRead<uint16_t>(address)); break; |
1490 case LDR_w: | 1488 case LDR_w: set_wreg(srcdst, MemoryRead<uint32_t>(address)); break; |
1491 case LDR_x: set_xreg(srcdst, MemoryRead(address, num_bytes)); break; | 1489 case LDR_x: set_xreg(srcdst, MemoryRead<uint64_t>(address)); break; |
1492 case STRB_w: | 1490 case LDRSB_w: set_wreg(srcdst, MemoryRead<int8_t>(address)); break; |
1493 case STRH_w: | 1491 case LDRSH_w: set_wreg(srcdst, MemoryRead<int16_t>(address)); break; |
1494 case STR_w: | 1492 case LDRSB_x: set_xreg(srcdst, MemoryRead<int8_t>(address)); break; |
1495 case STR_x: MemoryWrite(address, xreg(srcdst), num_bytes); break; | 1493 case LDRSH_x: set_xreg(srcdst, MemoryRead<int16_t>(address)); break; |
1496 case LDRSB_w: { | 1494 case LDRSW_x: set_xreg(srcdst, MemoryRead<int32_t>(address)); break; |
1497 set_wreg(srcdst, ExtendValue<int32_t>(MemoryRead8(address), SXTB)); | 1495 case LDR_s: set_sreg(srcdst, MemoryRead<float>(address)); break; |
1498 break; | 1496 case LDR_d: set_dreg(srcdst, MemoryRead<double>(address)); break; |
1499 } | 1497 |
1500 case LDRSB_x: { | 1498 case STRB_w: MemoryWrite<uint8_t>(address, wreg(srcdst)); break; |
1501 set_xreg(srcdst, ExtendValue<int64_t>(MemoryRead8(address), SXTB)); | 1499 case STRH_w: MemoryWrite<uint16_t>(address, wreg(srcdst)); break; |
1502 break; | 1500 case STR_w: MemoryWrite<uint32_t>(address, wreg(srcdst)); break; |
1503 } | 1501 case STR_x: MemoryWrite<uint64_t>(address, xreg(srcdst)); break; |
1504 case LDRSH_w: { | 1502 case STR_s: MemoryWrite<float>(address, sreg(srcdst)); break; |
1505 set_wreg(srcdst, ExtendValue<int32_t>(MemoryRead16(address), SXTH)); | 1503 case STR_d: MemoryWrite<double>(address, dreg(srcdst)); break; |
jbramley
2014/09/03 10:51:26
`git cl format` doesn't like these one-line cases.
| |
1506 break; | 1504 |
1507 } | |
1508 case LDRSH_x: { | |
1509 set_xreg(srcdst, ExtendValue<int64_t>(MemoryRead16(address), SXTH)); | |
1510 break; | |
1511 } | |
1512 case LDRSW_x: { | |
1513 set_xreg(srcdst, ExtendValue<int64_t>(MemoryRead32(address), SXTW)); | |
1514 break; | |
1515 } | |
1516 case LDR_s: set_sreg(srcdst, MemoryReadFP32(address)); break; | |
1517 case LDR_d: set_dreg(srcdst, MemoryReadFP64(address)); break; | |
1518 case STR_s: MemoryWriteFP32(address, sreg(srcdst)); break; | |
1519 case STR_d: MemoryWriteFP64(address, dreg(srcdst)); break; | |
1520 default: UNIMPLEMENTED(); | 1505 default: UNIMPLEMENTED(); |
1521 } | 1506 } |
1522 | 1507 |
1523 // Handle the writeback for loads after the load to ensure safe pop | 1508 // Handle the writeback for loads after the load to ensure safe pop |
1524 // operation even when interrupted in the middle of it. The stack pointer | 1509 // operation even when interrupted in the middle of it. The stack pointer |
1525 // is only updated after the load so pop(fp) will never break the invariant | 1510 // is only updated after the load so pop(fp) will never break the invariant |
1526 // sp <= fp expected while walking the stack in the sampler. | 1511 // sp <= fp expected while walking the stack in the sampler. |
1527 if (instr->IsLoad()) { | 1512 if (instr->IsLoad()) { |
1528 // For loads the address pre writeback is used to check access below the | 1513 // For loads the address pre writeback is used to check access below the |
1529 // stack. | 1514 // stack. |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1583 } | 1568 } |
1584 | 1569 |
1585 LoadStorePairOp op = | 1570 LoadStorePairOp op = |
1586 static_cast<LoadStorePairOp>(instr->Mask(LoadStorePairMask)); | 1571 static_cast<LoadStorePairOp>(instr->Mask(LoadStorePairMask)); |
1587 | 1572 |
1588 // 'rt' and 'rt2' can only be aliased for stores. | 1573 // 'rt' and 'rt2' can only be aliased for stores. |
1589 DCHECK(((op & LoadStorePairLBit) == 0) || (rt != rt2)); | 1574 DCHECK(((op & LoadStorePairLBit) == 0) || (rt != rt2)); |
1590 | 1575 |
1591 switch (op) { | 1576 switch (op) { |
1592 case LDP_w: { | 1577 case LDP_w: { |
1593 set_wreg(rt, MemoryRead32(address)); | 1578 set_wreg(rt, MemoryRead<uint32_t>(address)); |
1594 set_wreg(rt2, MemoryRead32(address + kWRegSize)); | 1579 set_wreg(rt2, MemoryRead<uint32_t>(address + kWRegSize)); |
1595 break; | 1580 break; |
1596 } | 1581 } |
1597 case LDP_s: { | 1582 case LDP_s: { |
1598 set_sreg(rt, MemoryReadFP32(address)); | 1583 set_sreg(rt, MemoryRead<float>(address)); |
1599 set_sreg(rt2, MemoryReadFP32(address + kSRegSize)); | 1584 set_sreg(rt2, MemoryRead<float>(address + kSRegSize)); |
1600 break; | 1585 break; |
1601 } | 1586 } |
1602 case LDP_x: { | 1587 case LDP_x: { |
1603 set_xreg(rt, MemoryRead64(address)); | 1588 set_xreg(rt, MemoryRead<uint64_t>(address)); |
1604 set_xreg(rt2, MemoryRead64(address + kXRegSize)); | 1589 set_xreg(rt2, MemoryRead<uint64_t>(address + kXRegSize)); |
1605 break; | 1590 break; |
1606 } | 1591 } |
1607 case LDP_d: { | 1592 case LDP_d: { |
1608 set_dreg(rt, MemoryReadFP64(address)); | 1593 set_dreg(rt, MemoryRead<double>(address)); |
1609 set_dreg(rt2, MemoryReadFP64(address + kDRegSize)); | 1594 set_dreg(rt2, MemoryRead<double>(address + kDRegSize)); |
1610 break; | 1595 break; |
1611 } | 1596 } |
1612 case LDPSW_x: { | 1597 case LDPSW_x: { |
1613 set_xreg(rt, ExtendValue<int64_t>(MemoryRead32(address), SXTW)); | 1598 set_xreg(rt, MemoryRead<int32_t>(address)); |
1614 set_xreg(rt2, ExtendValue<int64_t>( | 1599 set_xreg(rt2, MemoryRead<int32_t>(address + kWRegSize)); |
1615 MemoryRead32(address + kWRegSize), SXTW)); | |
1616 break; | 1600 break; |
1617 } | 1601 } |
1618 case STP_w: { | 1602 case STP_w: { |
1619 MemoryWrite32(address, wreg(rt)); | 1603 MemoryWrite<uint32_t>(address, wreg(rt)); |
1620 MemoryWrite32(address + kWRegSize, wreg(rt2)); | 1604 MemoryWrite<uint32_t>(address + kWRegSize, wreg(rt2)); |
1621 break; | 1605 break; |
1622 } | 1606 } |
1623 case STP_s: { | 1607 case STP_s: { |
1624 MemoryWriteFP32(address, sreg(rt)); | 1608 MemoryWrite<float>(address, sreg(rt)); |
1625 MemoryWriteFP32(address + kSRegSize, sreg(rt2)); | 1609 MemoryWrite<float>(address + kSRegSize, sreg(rt2)); |
1626 break; | 1610 break; |
1627 } | 1611 } |
1628 case STP_x: { | 1612 case STP_x: { |
1629 MemoryWrite64(address, xreg(rt)); | 1613 MemoryWrite<uint64_t>(address, xreg(rt)); |
1630 MemoryWrite64(address + kXRegSize, xreg(rt2)); | 1614 MemoryWrite<uint64_t>(address + kXRegSize, xreg(rt2)); |
1631 break; | 1615 break; |
1632 } | 1616 } |
1633 case STP_d: { | 1617 case STP_d: { |
1634 MemoryWriteFP64(address, dreg(rt)); | 1618 MemoryWrite<double>(address, dreg(rt)); |
1635 MemoryWriteFP64(address + kDRegSize, dreg(rt2)); | 1619 MemoryWrite<double>(address + kDRegSize, dreg(rt2)); |
1636 break; | 1620 break; |
1637 } | 1621 } |
1638 default: UNREACHABLE(); | 1622 default: UNREACHABLE(); |
1639 } | 1623 } |
1640 | 1624 |
1641 // Handle the writeback for loads after the load to ensure safe pop | 1625 // Handle the writeback for loads after the load to ensure safe pop |
1642 // operation even when interrupted in the middle of it. The stack pointer | 1626 // operation even when interrupted in the middle of it. The stack pointer |
1643 // is only updated after the load so pop(fp) will never break the invariant | 1627 // is only updated after the load so pop(fp) will never break the invariant |
1644 // sp <= fp expected while walking the stack in the sampler. | 1628 // sp <= fp expected while walking the stack in the sampler. |
1645 if (instr->IsLoad()) { | 1629 if (instr->IsLoad()) { |
1646 // For loads the address pre writeback is used to check access below the | 1630 // For loads the address pre writeback is used to check access below the |
1647 // stack. | 1631 // stack. |
1648 stack = reinterpret_cast<uint8_t*>(sp()); | 1632 stack = reinterpret_cast<uint8_t*>(sp()); |
1649 | 1633 |
1650 LoadStoreWriteBack(addr_reg, offset, addrmode); | 1634 LoadStoreWriteBack(addr_reg, offset, addrmode); |
1651 } | 1635 } |
1652 | 1636 |
1653 // Accesses below the stack pointer (but above the platform stack limit) are | 1637 // Accesses below the stack pointer (but above the platform stack limit) are |
1654 // not allowed in the ABI. | 1638 // not allowed in the ABI. |
1655 CheckMemoryAccess(address, stack); | 1639 CheckMemoryAccess(address, stack); |
1656 } | 1640 } |
1657 | 1641 |
1658 | 1642 |
1659 void Simulator::VisitLoadLiteral(Instruction* instr) { | 1643 void Simulator::VisitLoadLiteral(Instruction* instr) { |
1660 uint8_t* address = instr->LiteralAddress(); | 1644 uint8_t* address = instr->LiteralAddress(); |
1661 unsigned rt = instr->Rt(); | 1645 unsigned rt = instr->Rt(); |
1662 | 1646 |
1663 switch (instr->Mask(LoadLiteralMask)) { | 1647 switch (instr->Mask(LoadLiteralMask)) { |
1664 case LDR_w_lit: set_wreg(rt, MemoryRead32(address)); break; | 1648 case LDR_w_lit: set_wreg(rt, MemoryRead<uint32_t>(address)); break; |
1665 case LDR_x_lit: set_xreg(rt, MemoryRead64(address)); break; | 1649 case LDR_x_lit: set_xreg(rt, MemoryRead<uint64_t>(address)); break; |
1666 case LDR_s_lit: set_sreg(rt, MemoryReadFP32(address)); break; | 1650 case LDR_s_lit: set_sreg(rt, MemoryRead<float>(address)); break; |
1667 case LDR_d_lit: set_dreg(rt, MemoryReadFP64(address)); break; | 1651 case LDR_d_lit: set_dreg(rt, MemoryRead<double>(address)); break; |
1668 default: UNREACHABLE(); | 1652 default: UNREACHABLE(); |
1669 } | 1653 } |
1670 } | 1654 } |
1671 | 1655 |
1672 | 1656 |
1673 uint8_t* Simulator::LoadStoreAddress(unsigned addr_reg, | 1657 uint8_t* Simulator::LoadStoreAddress(unsigned addr_reg, |
1674 int64_t offset, | 1658 int64_t offset, |
1675 AddrMode addrmode) { | 1659 AddrMode addrmode) { |
1676 const unsigned kSPRegCode = kSPRegInternalCode & kRegCodeMask; | 1660 const unsigned kSPRegCode = kSPRegInternalCode & kRegCodeMask; |
1677 int64_t address = xreg(addr_reg, Reg31IsStackPointer); | 1661 int64_t address = xreg(addr_reg, Reg31IsStackPointer); |
(...skipping 28 matching lines...) Expand all Loading... | |
1706 fprintf(stream_, "ACCESS BELOW STACK POINTER:\n"); | 1690 fprintf(stream_, "ACCESS BELOW STACK POINTER:\n"); |
1707 fprintf(stream_, " sp is here: 0x%16p\n", stack); | 1691 fprintf(stream_, " sp is here: 0x%16p\n", stack); |
1708 fprintf(stream_, " access was here: 0x%16p\n", address); | 1692 fprintf(stream_, " access was here: 0x%16p\n", address); |
1709 fprintf(stream_, " stack limit is here: 0x%16p\n", stack_limit_); | 1693 fprintf(stream_, " stack limit is here: 0x%16p\n", stack_limit_); |
1710 fprintf(stream_, "\n"); | 1694 fprintf(stream_, "\n"); |
1711 FATAL("ACCESS BELOW STACK POINTER"); | 1695 FATAL("ACCESS BELOW STACK POINTER"); |
1712 } | 1696 } |
1713 } | 1697 } |
1714 | 1698 |
1715 | 1699 |
1716 uint64_t Simulator::MemoryRead(uint8_t* address, unsigned num_bytes) { | |
1717 DCHECK(address != NULL); | |
1718 DCHECK((num_bytes > 0) && (num_bytes <= sizeof(uint64_t))); | |
1719 uint64_t read = 0; | |
1720 memcpy(&read, address, num_bytes); | |
1721 return read; | |
1722 } | |
1723 | |
1724 | |
1725 uint8_t Simulator::MemoryRead8(uint8_t* address) { | |
1726 return MemoryRead(address, sizeof(uint8_t)); | |
1727 } | |
1728 | |
1729 | |
1730 uint16_t Simulator::MemoryRead16(uint8_t* address) { | |
1731 return MemoryRead(address, sizeof(uint16_t)); | |
1732 } | |
1733 | |
1734 | |
1735 uint32_t Simulator::MemoryRead32(uint8_t* address) { | |
1736 return MemoryRead(address, sizeof(uint32_t)); | |
1737 } | |
1738 | |
1739 | |
1740 float Simulator::MemoryReadFP32(uint8_t* address) { | |
1741 return rawbits_to_float(MemoryRead32(address)); | |
1742 } | |
1743 | |
1744 | |
1745 uint64_t Simulator::MemoryRead64(uint8_t* address) { | |
1746 return MemoryRead(address, sizeof(uint64_t)); | |
1747 } | |
1748 | |
1749 | |
1750 double Simulator::MemoryReadFP64(uint8_t* address) { | |
1751 return rawbits_to_double(MemoryRead64(address)); | |
1752 } | |
1753 | |
1754 | |
1755 void Simulator::MemoryWrite(uint8_t* address, | |
1756 uint64_t value, | |
1757 unsigned num_bytes) { | |
1758 DCHECK(address != NULL); | |
1759 DCHECK((num_bytes > 0) && (num_bytes <= sizeof(uint64_t))); | |
1760 | |
1761 LogWrite(address, value, num_bytes); | |
1762 memcpy(address, &value, num_bytes); | |
1763 } | |
1764 | |
1765 | |
1766 void Simulator::MemoryWrite32(uint8_t* address, uint32_t value) { | |
1767 MemoryWrite(address, value, sizeof(uint32_t)); | |
1768 } | |
1769 | |
1770 | |
1771 void Simulator::MemoryWriteFP32(uint8_t* address, float value) { | |
1772 MemoryWrite32(address, float_to_rawbits(value)); | |
1773 } | |
1774 | |
1775 | |
1776 void Simulator::MemoryWrite64(uint8_t* address, uint64_t value) { | |
1777 MemoryWrite(address, value, sizeof(uint64_t)); | |
1778 } | |
1779 | |
1780 | |
1781 void Simulator::MemoryWriteFP64(uint8_t* address, double value) { | |
1782 MemoryWrite64(address, double_to_rawbits(value)); | |
1783 } | |
1784 | |
1785 | |
1786 void Simulator::VisitMoveWideImmediate(Instruction* instr) { | 1700 void Simulator::VisitMoveWideImmediate(Instruction* instr) { |
1787 MoveWideImmediateOp mov_op = | 1701 MoveWideImmediateOp mov_op = |
1788 static_cast<MoveWideImmediateOp>(instr->Mask(MoveWideImmediateMask)); | 1702 static_cast<MoveWideImmediateOp>(instr->Mask(MoveWideImmediateMask)); |
1789 int64_t new_xn_val = 0; | 1703 int64_t new_xn_val = 0; |
1790 | 1704 |
1791 bool is_64_bits = instr->SixtyFourBits() == 1; | 1705 bool is_64_bits = instr->SixtyFourBits() == 1; |
1792 // Shift is limited for W operations. | 1706 // Shift is limited for W operations. |
1793 DCHECK(is_64_bits || (instr->ShiftMoveWide() < 2)); | 1707 DCHECK(is_64_bits || (instr->ShiftMoveWide() < 2)); |
1794 | 1708 |
1795 // Get the shifted immediate. | 1709 // Get the shifted immediate. |
(...skipping 1933 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3729 | 3643 |
3730 delete[] format; | 3644 delete[] format; |
3731 } | 3645 } |
3732 | 3646 |
3733 | 3647 |
3734 #endif // USE_SIMULATOR | 3648 #endif // USE_SIMULATOR |
3735 | 3649 |
3736 } } // namespace v8::internal | 3650 } } // namespace v8::internal |
3737 | 3651 |
3738 #endif // V8_TARGET_ARCH_ARM64 | 3652 #endif // V8_TARGET_ARCH_ARM64 |
OLD | NEW |