Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(481)

Side by Side Diff: src/arm64/simulator-arm64.cc

Issue 536923002: ARM64: Use templates for simulated memory accesses. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 6 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/arm64/simulator-arm64.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « src/arm64/simulator-arm64.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698