| OLD | NEW |
| 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 #include <math.h> // for isnan. | 5 #include <math.h> // for isnan. |
| 6 #include <setjmp.h> | 6 #include <setjmp.h> |
| 7 #include <stdlib.h> | 7 #include <stdlib.h> |
| 8 | 8 |
| 9 #include "vm/globals.h" | 9 #include "vm/globals.h" |
| 10 #if defined(TARGET_ARCH_ARM64) | 10 #if defined(TARGET_ARCH_ARM64) |
| (...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 124 "r28", "r29", "r30", | 124 "r28", "r29", "r30", |
| 125 | 125 |
| 126 "ip0", "ip1", "pp", "ctx", "fp", "lr", "sp", "zr", | 126 "ip0", "ip1", "pp", "ctx", "fp", "lr", "sp", "zr", |
| 127 }; | 127 }; |
| 128 static const Register kRegisters[] = { | 128 static const Register kRegisters[] = { |
| 129 R0, R1, R2, R3, R4, R5, R6, R7, | 129 R0, R1, R2, R3, R4, R5, R6, R7, |
| 130 R8, R9, R10, R11, R12, R13, R14, R15, | 130 R8, R9, R10, R11, R12, R13, R14, R15, |
| 131 R16, R17, R18, R19, R20, R21, R22, R23, | 131 R16, R17, R18, R19, R20, R21, R22, R23, |
| 132 R24, R25, R26, R27, R28, R29, R30, | 132 R24, R25, R26, R27, R28, R29, R30, |
| 133 | 133 |
| 134 IP0, IP1, PP, CTX, FP, LR, SP, ZR, | 134 IP0, IP1, PP, CTX, FP, LR, R31, ZR, |
| 135 }; | 135 }; |
| 136 ASSERT(ARRAY_SIZE(kNames) == ARRAY_SIZE(kRegisters)); | 136 ASSERT(ARRAY_SIZE(kNames) == ARRAY_SIZE(kRegisters)); |
| 137 for (unsigned i = 0; i < ARRAY_SIZE(kNames); i++) { | 137 for (unsigned i = 0; i < ARRAY_SIZE(kNames); i++) { |
| 138 if (strcmp(kNames[i], name) == 0) { | 138 if (strcmp(kNames[i], name) == 0) { |
| 139 return kRegisters[i]; | 139 return kRegisters[i]; |
| 140 } | 140 } |
| 141 } | 141 } |
| 142 return kNoRegister; | 142 return kNoRegister; |
| 143 } | 143 } |
| 144 | 144 |
| 145 | 145 |
| 146 bool SimulatorDebugger::GetValue(char* desc, int64_t* value) { | 146 bool SimulatorDebugger::GetValue(char* desc, int64_t* value) { |
| 147 Register reg = LookupCpuRegisterByName(desc); | 147 Register reg = LookupCpuRegisterByName(desc); |
| 148 if (reg != kNoRegister) { | 148 if (reg != kNoRegister) { |
| 149 if (reg == ZR) { |
| 150 *value = 0; |
| 151 return true; |
| 152 } |
| 149 *value = sim_->get_register(reg); | 153 *value = sim_->get_register(reg); |
| 150 return true; | 154 return true; |
| 151 } | 155 } |
| 152 if (desc[0] == '*') { | 156 if (desc[0] == '*') { |
| 153 int64_t addr; | 157 int64_t addr; |
| 154 if (GetValue(desc + 1, &addr)) { | 158 if (GetValue(desc + 1, &addr)) { |
| 155 if (Simulator::IsIllegalAddress(addr)) { | 159 if (Simulator::IsIllegalAddress(addr)) { |
| 156 return false; | 160 return false; |
| 157 } | 161 } |
| 158 *value = *(reinterpret_cast<int64_t*>(addr)); | 162 *value = *(reinterpret_cast<int64_t*>(addr)); |
| (...skipping 426 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 585 dbg.Stop(instr, buffer); | 589 dbg.Stop(instr, buffer); |
| 586 // The debugger will return control in non-interactive mode. | 590 // The debugger will return control in non-interactive mode. |
| 587 FATAL("Cannot continue execution after illegal memory access."); | 591 FATAL("Cannot continue execution after illegal memory access."); |
| 588 } | 592 } |
| 589 | 593 |
| 590 | 594 |
| 591 // The ARMv8 manual advises that an unaligned access may generate a fault, | 595 // The ARMv8 manual advises that an unaligned access may generate a fault, |
| 592 // and if not, will likely take a number of additional cycles to execute, | 596 // and if not, will likely take a number of additional cycles to execute, |
| 593 // so let's just not generate any. | 597 // so let's just not generate any. |
| 594 void Simulator::UnalignedAccess(const char* msg, uword addr, Instr* instr) { | 598 void Simulator::UnalignedAccess(const char* msg, uword addr, Instr* instr) { |
| 595 char buffer[64]; | 599 char buffer[128]; |
| 596 snprintf(buffer, sizeof(buffer), | 600 snprintf(buffer, sizeof(buffer), |
| 597 "unaligned %s at 0x%" Px ", pc=%p\n", msg, addr, instr); | 601 "unaligned %s at 0x%" Px ", pc=%p\n", msg, addr, instr); |
| 598 SimulatorDebugger dbg(this); | 602 SimulatorDebugger dbg(this); |
| 599 dbg.Stop(instr, buffer); | 603 dbg.Stop(instr, buffer); |
| 600 // The debugger will not be able to single step past this instruction, but | 604 // The debugger will not be able to single step past this instruction, but |
| 601 // it will be possible to disassemble the code and inspect registers. | 605 // it will be possible to disassemble the code and inspect registers. |
| 602 FATAL("Cannot continue execution after unaligned access."); | 606 FATAL("Cannot continue execution after unaligned access."); |
| 603 } | 607 } |
| 604 | 608 |
| 605 | 609 |
| 606 void Simulator::UnimplementedInstruction(Instr* instr) { | 610 void Simulator::UnimplementedInstruction(Instr* instr) { |
| 607 char buffer[64]; | 611 char buffer[128]; |
| 608 snprintf(buffer, sizeof(buffer), "Unimplemented instruction: pc=%p\n", instr); | 612 snprintf(buffer, sizeof(buffer), |
| 613 "Unimplemented instruction: at %p, last_pc=0x%"Px"\n", |
| 614 instr, get_last_pc()); |
| 609 SimulatorDebugger dbg(this); | 615 SimulatorDebugger dbg(this); |
| 610 dbg.Stop(instr, buffer); | 616 dbg.Stop(instr, buffer); |
| 611 FATAL("Cannot continue execution after unimplemented instruction."); | 617 FATAL("Cannot continue execution after unimplemented instruction."); |
| 612 } | 618 } |
| 613 | 619 |
| 614 | 620 |
| 615 // Returns the top of the stack area to enable checking for stack pointer | 621 // Returns the top of the stack area to enable checking for stack pointer |
| 616 // validity. | 622 // validity. |
| 617 uword Simulator::StackTop() const { | 623 uword Simulator::StackTop() const { |
| 618 // To be safe in potential stack underflows we leave some buffer above and | 624 // To be safe in potential stack underflows we leave some buffer above and |
| (...skipping 384 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1003 } else { | 1009 } else { |
| 1004 // Format(instr, "cbnz'sf 'rt, 'dest19"); | 1010 // Format(instr, "cbnz'sf 'rt, 'dest19"); |
| 1005 if (rt_val != 0) { | 1011 if (rt_val != 0) { |
| 1006 set_pc(dest); | 1012 set_pc(dest); |
| 1007 } | 1013 } |
| 1008 } | 1014 } |
| 1009 } | 1015 } |
| 1010 | 1016 |
| 1011 | 1017 |
| 1012 bool Simulator::ConditionallyExecute(Instr* instr) { | 1018 bool Simulator::ConditionallyExecute(Instr* instr) { |
| 1013 switch (instr->ConditionField()) { | 1019 Condition cond; |
| 1020 if (instr->IsConditionalSelectOp()) { |
| 1021 cond = instr->SelectConditionField(); |
| 1022 } else { |
| 1023 cond = instr->ConditionField(); |
| 1024 } |
| 1025 switch (cond) { |
| 1014 case EQ: return z_flag_; | 1026 case EQ: return z_flag_; |
| 1015 case NE: return !z_flag_; | 1027 case NE: return !z_flag_; |
| 1016 case CS: return c_flag_; | 1028 case CS: return c_flag_; |
| 1017 case CC: return !c_flag_; | 1029 case CC: return !c_flag_; |
| 1018 case MI: return n_flag_; | 1030 case MI: return n_flag_; |
| 1019 case PL: return !n_flag_; | 1031 case PL: return !n_flag_; |
| 1020 case VS: return v_flag_; | 1032 case VS: return v_flag_; |
| 1021 case VC: return !v_flag_; | 1033 case VC: return !v_flag_; |
| 1022 case HI: return c_flag_ && !z_flag_; | 1034 case HI: return c_flag_ && !z_flag_; |
| 1023 case LS: return !c_flag_ || z_flag_; | 1035 case LS: return !c_flag_ || z_flag_; |
| (...skipping 787 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1811 const int32_t ra_val = get_wregister(ra, R31IsZR); | 1823 const int32_t ra_val = get_wregister(ra, R31IsZR); |
| 1812 const int32_t alu_out = ra_val + (rn_val * rm_val); | 1824 const int32_t alu_out = ra_val + (rn_val * rm_val); |
| 1813 set_wregister(rd, alu_out, R31IsZR); | 1825 set_wregister(rd, alu_out, R31IsZR); |
| 1814 } | 1826 } |
| 1815 } else { | 1827 } else { |
| 1816 UnimplementedInstruction(instr); | 1828 UnimplementedInstruction(instr); |
| 1817 } | 1829 } |
| 1818 } | 1830 } |
| 1819 | 1831 |
| 1820 | 1832 |
| 1833 void Simulator::DecodeConditionalSelect(Instr* instr) { |
| 1834 if ((instr->Bits(29, 2) == 0) && (instr->Bits(10, 2) == 0)) { |
| 1835 // Format(instr, "mov'sf'cond 'rd, 'rn, 'rm"); |
| 1836 const Register rd = instr->RdField(); |
| 1837 const Register rn = instr->RnField(); |
| 1838 const Register rm = instr->RmField(); |
| 1839 if (instr->SFField() == 1) { |
| 1840 int64_t res = 0; |
| 1841 if (ConditionallyExecute(instr)) { |
| 1842 res = get_register(rn, instr->RnMode()); |
| 1843 } else { |
| 1844 res = get_register(rm, R31IsZR); |
| 1845 } |
| 1846 set_register(rd, res, instr->RdMode()); |
| 1847 } else { |
| 1848 int32_t res = 0; |
| 1849 if (ConditionallyExecute(instr)) { |
| 1850 res = get_wregister(rn, instr->RnMode()); |
| 1851 } else { |
| 1852 res = get_wregister(rm, R31IsZR); |
| 1853 } |
| 1854 set_wregister(rd, res, instr->RdMode()); |
| 1855 } |
| 1856 |
| 1857 } else { |
| 1858 UnimplementedInstruction(instr); |
| 1859 } |
| 1860 } |
| 1861 |
| 1862 |
| 1821 void Simulator::DecodeDPRegister(Instr* instr) { | 1863 void Simulator::DecodeDPRegister(Instr* instr) { |
| 1822 if (instr->IsAddSubShiftExtOp()) { | 1864 if (instr->IsAddSubShiftExtOp()) { |
| 1823 DecodeAddSubShiftExt(instr); | 1865 DecodeAddSubShiftExt(instr); |
| 1824 } else if (instr->IsLogicalShiftOp()) { | 1866 } else if (instr->IsLogicalShiftOp()) { |
| 1825 DecodeLogicalShift(instr); | 1867 DecodeLogicalShift(instr); |
| 1826 } else if (instr->IsMiscDP2SourceOp()) { | 1868 } else if (instr->IsMiscDP2SourceOp()) { |
| 1827 DecodeMiscDP2Source(instr); | 1869 DecodeMiscDP2Source(instr); |
| 1828 } else if (instr->IsMiscDP3SourceOp()) { | 1870 } else if (instr->IsMiscDP3SourceOp()) { |
| 1829 DecodeMiscDP3Source(instr); | 1871 DecodeMiscDP3Source(instr); |
| 1872 } else if (instr->IsConditionalSelectOp()) { |
| 1873 DecodeConditionalSelect(instr); |
| 1830 } else { | 1874 } else { |
| 1831 UnimplementedInstruction(instr); | 1875 UnimplementedInstruction(instr); |
| 1832 } | 1876 } |
| 1833 } | 1877 } |
| 1834 | 1878 |
| 1835 | 1879 |
| 1836 void Simulator::DecodeDPSimd1(Instr* instr) { | 1880 void Simulator::DecodeDPSimd1(Instr* instr) { |
| 1837 UnimplementedInstruction(instr); | 1881 UnimplementedInstruction(instr); |
| 1838 } | 1882 } |
| 1839 | 1883 |
| (...skipping 15 matching lines...) Expand all Loading... |
| 1855 if (instr->IsDPImmediateOp()) { | 1899 if (instr->IsDPImmediateOp()) { |
| 1856 DecodeDPImmediate(instr); | 1900 DecodeDPImmediate(instr); |
| 1857 } else if (instr->IsCompareBranchOp()) { | 1901 } else if (instr->IsCompareBranchOp()) { |
| 1858 DecodeCompareBranch(instr); | 1902 DecodeCompareBranch(instr); |
| 1859 } else if (instr->IsLoadStoreOp()) { | 1903 } else if (instr->IsLoadStoreOp()) { |
| 1860 DecodeLoadStore(instr); | 1904 DecodeLoadStore(instr); |
| 1861 } else if (instr->IsDPRegisterOp()) { | 1905 } else if (instr->IsDPRegisterOp()) { |
| 1862 DecodeDPRegister(instr); | 1906 DecodeDPRegister(instr); |
| 1863 } else if (instr->IsDPSimd1Op()) { | 1907 } else if (instr->IsDPSimd1Op()) { |
| 1864 DecodeDPSimd1(instr); | 1908 DecodeDPSimd1(instr); |
| 1909 } else if (instr->IsDPSimd2Op()) { |
| 1910 DecodeDPSimd2(instr); |
| 1865 } else { | 1911 } else { |
| 1866 ASSERT(instr->IsDPSimd2Op()); | 1912 UnimplementedInstruction(instr); |
| 1867 DecodeDPSimd2(instr); | |
| 1868 } | 1913 } |
| 1869 | 1914 |
| 1870 if (!pc_modified_) { | 1915 if (!pc_modified_) { |
| 1871 set_pc(reinterpret_cast<int64_t>(instr) + Instr::kInstrSize); | 1916 set_pc(reinterpret_cast<int64_t>(instr) + Instr::kInstrSize); |
| 1872 } | 1917 } |
| 1873 } | 1918 } |
| 1874 | 1919 |
| 1875 | 1920 |
| 1876 void Simulator::Execute() { | 1921 void Simulator::Execute() { |
| 1877 // Get the PC to simulate. Cannot use the accessor here as we need the | 1922 // Get the PC to simulate. Cannot use the accessor here as we need the |
| (...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2002 int64_t return_value; | 2047 int64_t return_value; |
| 2003 return_value = get_register(R0); | 2048 return_value = get_register(R0); |
| 2004 return return_value; | 2049 return return_value; |
| 2005 } | 2050 } |
| 2006 | 2051 |
| 2007 } // namespace dart | 2052 } // namespace dart |
| 2008 | 2053 |
| 2009 #endif // !defined(HOST_ARCH_ARM64) | 2054 #endif // !defined(HOST_ARCH_ARM64) |
| 2010 | 2055 |
| 2011 #endif // defined TARGET_ARCH_ARM64 | 2056 #endif // defined TARGET_ARCH_ARM64 |
| OLD | NEW |