| OLD | NEW |
| 1 // Copyright 2010 the V8 project authors. All rights reserved. | 1 // Copyright 2010 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 |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 68 | 68 |
| 69 private: | 69 private: |
| 70 static const instr_t kBreakpointInstr = | 70 static const instr_t kBreakpointInstr = |
| 71 ((AL << 28) | (7 << 25) | (1 << 24) | break_point); | 71 ((AL << 28) | (7 << 25) | (1 << 24) | break_point); |
| 72 static const instr_t kNopInstr = | 72 static const instr_t kNopInstr = |
| 73 ((AL << 28) | (13 << 21)); | 73 ((AL << 28) | (13 << 21)); |
| 74 | 74 |
| 75 Simulator* sim_; | 75 Simulator* sim_; |
| 76 | 76 |
| 77 int32_t GetRegisterValue(int regnum); | 77 int32_t GetRegisterValue(int regnum); |
| 78 double GetVFPDoubleRegisterValue(int regnum); |
| 78 bool GetValue(const char* desc, int32_t* value); | 79 bool GetValue(const char* desc, int32_t* value); |
| 79 bool GetVFPSingleValue(const char* desc, float* value); | 80 bool GetVFPSingleValue(const char* desc, float* value); |
| 80 bool GetVFPDoubleValue(const char* desc, double* value); | 81 bool GetVFPDoubleValue(const char* desc, double* value); |
| 81 | 82 |
| 82 // Set or delete a breakpoint. Returns true if successful. | 83 // Set or delete a breakpoint. Returns true if successful. |
| 83 bool SetBreakpoint(Instr* breakpc); | 84 bool SetBreakpoint(Instr* breakpc); |
| 84 bool DeleteBreakpoint(Instr* breakpc); | 85 bool DeleteBreakpoint(Instr* breakpc); |
| 85 | 86 |
| 86 // Undo and redo all breakpoints. This is needed to bracket disassembly and | 87 // Undo and redo all breakpoints. This is needed to bracket disassembly and |
| 87 // execution to skip past breakpoints when run from the debugger. | 88 // execution to skip past breakpoints when run from the debugger. |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 162 | 163 |
| 163 int32_t Debugger::GetRegisterValue(int regnum) { | 164 int32_t Debugger::GetRegisterValue(int regnum) { |
| 164 if (regnum == kPCRegister) { | 165 if (regnum == kPCRegister) { |
| 165 return sim_->get_pc(); | 166 return sim_->get_pc(); |
| 166 } else { | 167 } else { |
| 167 return sim_->get_register(regnum); | 168 return sim_->get_register(regnum); |
| 168 } | 169 } |
| 169 } | 170 } |
| 170 | 171 |
| 171 | 172 |
| 173 double Debugger::GetVFPDoubleRegisterValue(int regnum) { |
| 174 return sim_->get_double_from_d_register(regnum); |
| 175 } |
| 176 |
| 177 |
| 172 bool Debugger::GetValue(const char* desc, int32_t* value) { | 178 bool Debugger::GetValue(const char* desc, int32_t* value) { |
| 173 int regnum = Registers::Number(desc); | 179 int regnum = Registers::Number(desc); |
| 174 if (regnum != kNoRegister) { | 180 if (regnum != kNoRegister) { |
| 175 *value = GetRegisterValue(regnum); | 181 *value = GetRegisterValue(regnum); |
| 176 return true; | 182 return true; |
| 177 } else { | 183 } else { |
| 178 if (strncmp(desc, "0x", 2) == 0) { | 184 if (strncmp(desc, "0x", 2) == 0) { |
| 179 return SScanF(desc + 2, "%x", reinterpret_cast<uint32_t*>(value)) == 1; | 185 return SScanF(desc + 2, "%x", reinterpret_cast<uint32_t*>(value)) == 1; |
| 180 } else { | 186 } else { |
| 181 return SScanF(desc, "%u", reinterpret_cast<uint32_t*>(value)) == 1; | 187 return SScanF(desc, "%u", reinterpret_cast<uint32_t*>(value)) == 1; |
| (...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 303 } else if ((strcmp(cmd, "p") == 0) || (strcmp(cmd, "print") == 0)) { | 309 } else if ((strcmp(cmd, "p") == 0) || (strcmp(cmd, "print") == 0)) { |
| 304 if (argc == 2) { | 310 if (argc == 2) { |
| 305 int32_t value; | 311 int32_t value; |
| 306 float svalue; | 312 float svalue; |
| 307 double dvalue; | 313 double dvalue; |
| 308 if (strcmp(arg1, "all") == 0) { | 314 if (strcmp(arg1, "all") == 0) { |
| 309 for (int i = 0; i < kNumRegisters; i++) { | 315 for (int i = 0; i < kNumRegisters; i++) { |
| 310 value = GetRegisterValue(i); | 316 value = GetRegisterValue(i); |
| 311 PrintF("%3s: 0x%08x %10d\n", Registers::Name(i), value, value); | 317 PrintF("%3s: 0x%08x %10d\n", Registers::Name(i), value, value); |
| 312 } | 318 } |
| 319 for (int i = 0; i < kNumVFPDoubleRegisters; i++) { |
| 320 dvalue = GetVFPDoubleRegisterValue(i); |
| 321 PrintF("%3s: %f\n", |
| 322 VFPRegisters::Name(i, true), dvalue); |
| 323 } |
| 313 } else { | 324 } else { |
| 314 if (GetValue(arg1, &value)) { | 325 if (GetValue(arg1, &value)) { |
| 315 PrintF("%s: 0x%08x %d \n", arg1, value, value); | 326 PrintF("%s: 0x%08x %d \n", arg1, value, value); |
| 316 } else if (GetVFPSingleValue(arg1, &svalue)) { | 327 } else if (GetVFPSingleValue(arg1, &svalue)) { |
| 317 PrintF("%s: %f \n", arg1, svalue); | 328 PrintF("%s: %f \n", arg1, svalue); |
| 318 } else if (GetVFPDoubleValue(arg1, &dvalue)) { | 329 } else if (GetVFPDoubleValue(arg1, &dvalue)) { |
| 319 PrintF("%s: %f \n", arg1, dvalue); | 330 PrintF("%s: %f \n", arg1, dvalue); |
| 320 } else { | 331 } else { |
| 321 PrintF("%s unrecognized\n", arg1); | 332 PrintF("%s unrecognized\n", arg1); |
| 322 } | 333 } |
| (...skipping 508 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 831 } | 842 } |
| 832 | 843 |
| 833 | 844 |
| 834 // Raw access to the PC register. | 845 // Raw access to the PC register. |
| 835 void Simulator::set_pc(int32_t value) { | 846 void Simulator::set_pc(int32_t value) { |
| 836 pc_modified_ = true; | 847 pc_modified_ = true; |
| 837 registers_[pc] = value; | 848 registers_[pc] = value; |
| 838 } | 849 } |
| 839 | 850 |
| 840 | 851 |
| 852 bool Simulator::has_bad_pc() const { |
| 853 return ((registers_[pc] == bad_lr) || (registers_[pc] == end_sim_pc)); |
| 854 } |
| 855 |
| 856 |
| 841 // Raw access to the PC register without the special adjustment when reading. | 857 // Raw access to the PC register without the special adjustment when reading. |
| 842 int32_t Simulator::get_pc() const { | 858 int32_t Simulator::get_pc() const { |
| 843 return registers_[pc]; | 859 return registers_[pc]; |
| 844 } | 860 } |
| 845 | 861 |
| 846 | 862 |
| 847 // Getting from and setting into VFP registers. | 863 // Getting from and setting into VFP registers. |
| 848 void Simulator::set_s_register(int sreg, unsigned int value) { | 864 void Simulator::set_s_register(int sreg, unsigned int value) { |
| 849 ASSERT((sreg >= 0) && (sreg < num_s_registers)); | 865 ASSERT((sreg >= 0) && (sreg < num_s_registers)); |
| 850 vfp_register[sreg] = value; | 866 vfp_register[sreg] = value; |
| (...skipping 653 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1504 | 1520 |
| 1505 // Calls into the V8 runtime are based on this very simple interface. | 1521 // Calls into the V8 runtime are based on this very simple interface. |
| 1506 // Note: To be able to return two values from some calls the code in runtime.cc | 1522 // Note: To be able to return two values from some calls the code in runtime.cc |
| 1507 // uses the ObjectPair which is essentially two 32-bit values stuffed into a | 1523 // uses the ObjectPair which is essentially two 32-bit values stuffed into a |
| 1508 // 64-bit value. With the code below we assume that all runtime calls return | 1524 // 64-bit value. With the code below we assume that all runtime calls return |
| 1509 // 64 bits of result. If they don't, the r1 result register contains a bogus | 1525 // 64 bits of result. If they don't, the r1 result register contains a bogus |
| 1510 // value, which is fine because it is caller-saved. | 1526 // value, which is fine because it is caller-saved. |
| 1511 typedef int64_t (*SimulatorRuntimeCall)(int32_t arg0, | 1527 typedef int64_t (*SimulatorRuntimeCall)(int32_t arg0, |
| 1512 int32_t arg1, | 1528 int32_t arg1, |
| 1513 int32_t arg2, | 1529 int32_t arg2, |
| 1514 int32_t arg3); | 1530 int32_t arg3, |
| 1531 int32_t arg4); |
| 1515 typedef double (*SimulatorRuntimeFPCall)(int32_t arg0, | 1532 typedef double (*SimulatorRuntimeFPCall)(int32_t arg0, |
| 1516 int32_t arg1, | 1533 int32_t arg1, |
| 1517 int32_t arg2, | 1534 int32_t arg2, |
| 1518 int32_t arg3); | 1535 int32_t arg3); |
| 1519 | 1536 |
| 1520 | 1537 |
| 1521 // Software interrupt instructions are used by the simulator to call into the | 1538 // Software interrupt instructions are used by the simulator to call into the |
| 1522 // C-based V8 runtime. | 1539 // C-based V8 runtime. |
| 1523 void Simulator::SoftwareInterrupt(Instr* instr) { | 1540 void Simulator::SoftwareInterrupt(Instr* instr) { |
| 1524 int svc = instr->SvcField(); | 1541 int svc = instr->SvcField(); |
| 1525 switch (svc) { | 1542 switch (svc) { |
| 1526 case call_rt_redirected: { | 1543 case call_rt_redirected: { |
| 1527 // Check if stack is aligned. Error if not aligned is reported below to | 1544 // Check if stack is aligned. Error if not aligned is reported below to |
| 1528 // include information on the function called. | 1545 // include information on the function called. |
| 1529 bool stack_aligned = | 1546 bool stack_aligned = |
| 1530 (get_register(sp) | 1547 (get_register(sp) |
| 1531 & (::v8::internal::FLAG_sim_stack_alignment - 1)) == 0; | 1548 & (::v8::internal::FLAG_sim_stack_alignment - 1)) == 0; |
| 1532 Redirection* redirection = Redirection::FromSwiInstruction(instr); | 1549 Redirection* redirection = Redirection::FromSwiInstruction(instr); |
| 1533 int32_t arg0 = get_register(r0); | 1550 int32_t arg0 = get_register(r0); |
| 1534 int32_t arg1 = get_register(r1); | 1551 int32_t arg1 = get_register(r1); |
| 1535 int32_t arg2 = get_register(r2); | 1552 int32_t arg2 = get_register(r2); |
| 1536 int32_t arg3 = get_register(r3); | 1553 int32_t arg3 = get_register(r3); |
| 1554 int32_t* stack_pointer = reinterpret_cast<int32_t*>(get_register(sp)); |
| 1555 int32_t arg4 = *stack_pointer; |
| 1537 // This is dodgy but it works because the C entry stubs are never moved. | 1556 // This is dodgy but it works because the C entry stubs are never moved. |
| 1538 // See comment in codegen-arm.cc and bug 1242173. | 1557 // See comment in codegen-arm.cc and bug 1242173. |
| 1539 int32_t saved_lr = get_register(lr); | 1558 int32_t saved_lr = get_register(lr); |
| 1540 if (redirection->fp_return()) { | 1559 if (redirection->fp_return()) { |
| 1541 intptr_t external = | 1560 intptr_t external = |
| 1542 reinterpret_cast<intptr_t>(redirection->external_function()); | 1561 reinterpret_cast<intptr_t>(redirection->external_function()); |
| 1543 SimulatorRuntimeFPCall target = | 1562 SimulatorRuntimeFPCall target = |
| 1544 reinterpret_cast<SimulatorRuntimeFPCall>(external); | 1563 reinterpret_cast<SimulatorRuntimeFPCall>(external); |
| 1545 if (::v8::internal::FLAG_trace_sim || !stack_aligned) { | 1564 if (::v8::internal::FLAG_trace_sim || !stack_aligned) { |
| 1546 double x, y; | 1565 double x, y; |
| 1547 GetFpArgs(&x, &y); | 1566 GetFpArgs(&x, &y); |
| 1548 PrintF("Call to host function at %p with args %f, %f", | 1567 PrintF("Call to host function at %p with args %f, %f", |
| 1549 FUNCTION_ADDR(target), x, y); | 1568 FUNCTION_ADDR(target), x, y); |
| 1550 if (!stack_aligned) { | 1569 if (!stack_aligned) { |
| 1551 PrintF(" with unaligned stack %08x\n", get_register(sp)); | 1570 PrintF(" with unaligned stack %08x\n", get_register(sp)); |
| 1552 } | 1571 } |
| 1553 PrintF("\n"); | 1572 PrintF("\n"); |
| 1554 } | 1573 } |
| 1555 CHECK(stack_aligned); | 1574 CHECK(stack_aligned); |
| 1556 double result = target(arg0, arg1, arg2, arg3); | 1575 double result = target(arg0, arg1, arg2, arg3); |
| 1557 SetFpResult(result); | 1576 SetFpResult(result); |
| 1558 } else { | 1577 } else { |
| 1559 intptr_t external = | 1578 intptr_t external = |
| 1560 reinterpret_cast<int32_t>(redirection->external_function()); | 1579 reinterpret_cast<int32_t>(redirection->external_function()); |
| 1561 SimulatorRuntimeCall target = | 1580 SimulatorRuntimeCall target = |
| 1562 reinterpret_cast<SimulatorRuntimeCall>(external); | 1581 reinterpret_cast<SimulatorRuntimeCall>(external); |
| 1563 if (::v8::internal::FLAG_trace_sim || !stack_aligned) { | 1582 if (::v8::internal::FLAG_trace_sim || !stack_aligned) { |
| 1564 PrintF( | 1583 PrintF( |
| 1565 "Call to host function at %p with args %08x, %08x, %08x, %08x", | 1584 "Call to host function at %p args %08x, %08x, %08x, %08x, %0xc", |
| 1566 FUNCTION_ADDR(target), | 1585 FUNCTION_ADDR(target), |
| 1567 arg0, | 1586 arg0, |
| 1568 arg1, | 1587 arg1, |
| 1569 arg2, | 1588 arg2, |
| 1570 arg3); | 1589 arg3, |
| 1590 arg4); |
| 1571 if (!stack_aligned) { | 1591 if (!stack_aligned) { |
| 1572 PrintF(" with unaligned stack %08x\n", get_register(sp)); | 1592 PrintF(" with unaligned stack %08x\n", get_register(sp)); |
| 1573 } | 1593 } |
| 1574 PrintF("\n"); | 1594 PrintF("\n"); |
| 1575 } | 1595 } |
| 1576 CHECK(stack_aligned); | 1596 CHECK(stack_aligned); |
| 1577 int64_t result = target(arg0, arg1, arg2, arg3); | 1597 int64_t result = target(arg0, arg1, arg2, arg3, arg4); |
| 1578 int32_t lo_res = static_cast<int32_t>(result); | 1598 int32_t lo_res = static_cast<int32_t>(result); |
| 1579 int32_t hi_res = static_cast<int32_t>(result >> 32); | 1599 int32_t hi_res = static_cast<int32_t>(result >> 32); |
| 1580 if (::v8::internal::FLAG_trace_sim) { | 1600 if (::v8::internal::FLAG_trace_sim) { |
| 1581 PrintF("Returned %08x\n", lo_res); | 1601 PrintF("Returned %08x\n", lo_res); |
| 1582 } | 1602 } |
| 1583 set_register(r0, lo_res); | 1603 set_register(r0, lo_res); |
| 1584 set_register(r1, hi_res); | 1604 set_register(r1, hi_res); |
| 1585 } | 1605 } |
| 1586 set_register(lr, saved_lr); | 1606 set_register(lr, saved_lr); |
| 1587 set_pc(get_register(lr)); | 1607 set_pc(get_register(lr)); |
| (...skipping 314 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1902 switch (instr->Bits(7, 4)) { | 1922 switch (instr->Bits(7, 4)) { |
| 1903 case BX: | 1923 case BX: |
| 1904 set_pc(get_register(rm)); | 1924 set_pc(get_register(rm)); |
| 1905 break; | 1925 break; |
| 1906 case BLX: { | 1926 case BLX: { |
| 1907 uint32_t old_pc = get_pc(); | 1927 uint32_t old_pc = get_pc(); |
| 1908 set_pc(get_register(rm)); | 1928 set_pc(get_register(rm)); |
| 1909 set_register(lr, old_pc + Instr::kInstrSize); | 1929 set_register(lr, old_pc + Instr::kInstrSize); |
| 1910 break; | 1930 break; |
| 1911 } | 1931 } |
| 1912 case BKPT: | 1932 case BKPT: { |
| 1913 v8::internal::OS::DebugBreak(); | 1933 Debugger dbg(this); |
| 1934 PrintF("Simulator hit BKPT.\n"); |
| 1935 dbg.Debug(); |
| 1914 break; | 1936 break; |
| 1937 } |
| 1915 default: | 1938 default: |
| 1916 UNIMPLEMENTED(); | 1939 UNIMPLEMENTED(); |
| 1917 } | 1940 } |
| 1918 } else if (instr->Bits(22, 21) == 3) { | 1941 } else if (instr->Bits(22, 21) == 3) { |
| 1919 int rm = instr->RmField(); | 1942 int rm = instr->RmField(); |
| 1920 int rd = instr->RdField(); | 1943 int rd = instr->RdField(); |
| 1921 switch (instr->Bits(7, 4)) { | 1944 switch (instr->Bits(7, 4)) { |
| 1922 case CLZ: { | 1945 case CLZ: { |
| 1923 uint32_t bits = get_register(rm); | 1946 uint32_t bits = get_register(rm); |
| 1924 int leading_zeros = 0; | 1947 int leading_zeros = 0; |
| (...skipping 1097 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3022 uintptr_t address = *stack_slot; | 3045 uintptr_t address = *stack_slot; |
| 3023 set_register(sp, current_sp + sizeof(uintptr_t)); | 3046 set_register(sp, current_sp + sizeof(uintptr_t)); |
| 3024 return address; | 3047 return address; |
| 3025 } | 3048 } |
| 3026 | 3049 |
| 3027 } } // namespace assembler::arm | 3050 } } // namespace assembler::arm |
| 3028 | 3051 |
| 3029 #endif // USE_SIMULATOR | 3052 #endif // USE_SIMULATOR |
| 3030 | 3053 |
| 3031 #endif // V8_TARGET_ARCH_ARM | 3054 #endif // V8_TARGET_ARCH_ARM |
| OLD | NEW |