| OLD | NEW |
| 1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 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 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 119 | 119 |
| 120 static void InitializeCoverage() { | 120 static void InitializeCoverage() { |
| 121 char* file_name = getenv("V8_GENERATED_CODE_COVERAGE_LOG"); | 121 char* file_name = getenv("V8_GENERATED_CODE_COVERAGE_LOG"); |
| 122 if (file_name != NULL) { | 122 if (file_name != NULL) { |
| 123 coverage_log = fopen(file_name, "aw+"); | 123 coverage_log = fopen(file_name, "aw+"); |
| 124 } | 124 } |
| 125 } | 125 } |
| 126 | 126 |
| 127 | 127 |
| 128 void MipsDebugger::Stop(Instruction* instr) { | 128 void MipsDebugger::Stop(Instruction* instr) { |
| 129 UNIMPLEMENTED_MIPS(); | 129 // Get the stop code. |
| 130 char* str = reinterpret_cast<char*>(instr->InstructionBits()); | 130 uint32_t code = instr->Bits(25, 6); |
| 131 if (strlen(str) > 0) { | 131 // Retrieve the encoded address, which comes just after this stop. |
| 132 char** msg_address = |
| 133 reinterpret_cast<char**>(sim_->get_pc() + Instr::kInstrSize); |
| 134 char* msg = *msg_address; |
| 135 ASSERT(msg != NULL); |
| 136 |
| 137 // Update this stop description. |
| 138 if (!watched_stops[code].desc) { |
| 139 watched_stops[code].desc = msg; |
| 140 } |
| 141 |
| 142 if (strlen(msg) > 0) { |
| 132 if (coverage_log != NULL) { | 143 if (coverage_log != NULL) { |
| 133 fprintf(coverage_log, "%s\n", str); | 144 fprintf(coverage_log, "%s\n", str); |
| 134 fflush(coverage_log); | 145 fflush(coverage_log); |
| 135 } | 146 } |
| 136 instr->SetInstructionBits(0x0); // Overwrite with nop. | 147 // Overwrite the instruction and address with nops. |
| 148 instr->SetInstructionBits(kNopInstr); |
| 149 reinterpret_cast<Instr*>(msg_address)->SetInstructionBits(kNopInstr); |
| 137 } | 150 } |
| 138 sim_->set_pc(sim_->get_pc() + Instruction::kInstrSize); | 151 sim_->set_pc(sim_->get_pc() + 2 * Instruction::kInstructionSize); |
| 139 } | 152 } |
| 140 | 153 |
| 141 | 154 |
| 142 #else // GENERATED_CODE_COVERAGE | 155 #else // GENERATED_CODE_COVERAGE |
| 143 | 156 |
| 144 #define UNSUPPORTED() printf("Unsupported instruction.\n"); | 157 #define UNSUPPORTED() printf("Unsupported instruction.\n"); |
| 145 | 158 |
| 146 static void InitializeCoverage() {} | 159 static void InitializeCoverage() {} |
| 147 | 160 |
| 148 | 161 |
| 149 void MipsDebugger::Stop(Instruction* instr) { | 162 void MipsDebugger::Stop(Instruction* instr) { |
| 150 const char* str = reinterpret_cast<char*>(instr->InstructionBits()); | 163 // Get the stop code. |
| 151 PrintF("Simulator hit %s\n", str); | 164 uint32_t code = instr->Bits(25, 6); |
| 152 sim_->set_pc(sim_->get_pc() + Instruction::kInstrSize); | 165 // Retrieve the encoded address, which comes just after this stop. |
| 166 char* msg = *reinterpret_cast<char**>(sim_->get_pc() + |
| 167 Instruction::kInstrSize); |
| 168 // Update this stop description. |
| 169 if (!sim_->watched_stops[code].desc) { |
| 170 sim_->watched_stops[code].desc = msg; |
| 171 } |
| 172 PrintF("Simulator hit %s (%u)\n", msg, code); |
| 173 sim_->set_pc(sim_->get_pc() + 2 * Instruction::kInstrSize); |
| 153 Debug(); | 174 Debug(); |
| 154 } | 175 } |
| 155 #endif // GENERATED_CODE_COVERAGE | 176 #endif // GENERATED_CODE_COVERAGE |
| 156 | 177 |
| 157 | 178 |
| 158 int32_t MipsDebugger::GetRegisterValue(int regnum) { | 179 int32_t MipsDebugger::GetRegisterValue(int regnum) { |
| 159 if (regnum == kNumSimuRegisters) { | 180 if (regnum == kNumSimuRegisters) { |
| 160 return sim_->get_pc(); | 181 return sim_->get_pc(); |
| 161 } else { | 182 } else { |
| 162 return sim_->get_register(regnum); | 183 return sim_->get_register(regnum); |
| (...skipping 415 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 578 } | 599 } |
| 579 } else { | 600 } else { |
| 580 PrintF("break <address>\n"); | 601 PrintF("break <address>\n"); |
| 581 } | 602 } |
| 582 } else if (strcmp(cmd, "del") == 0) { | 603 } else if (strcmp(cmd, "del") == 0) { |
| 583 if (!DeleteBreakpoint(NULL)) { | 604 if (!DeleteBreakpoint(NULL)) { |
| 584 PrintF("deleting breakpoint failed\n"); | 605 PrintF("deleting breakpoint failed\n"); |
| 585 } | 606 } |
| 586 } else if (strcmp(cmd, "flags") == 0) { | 607 } else if (strcmp(cmd, "flags") == 0) { |
| 587 PrintF("No flags on MIPS !\n"); | 608 PrintF("No flags on MIPS !\n"); |
| 588 } else if (strcmp(cmd, "unstop") == 0) { | 609 } else if (strcmp(cmd, "stop") == 0) { |
| 589 PrintF("Unstop command not implemented on MIPS."); | 610 int32_t value; |
| 611 intptr_t stop_pc = sim_->get_pc() - |
| 612 2 * Instruction::kInstrSize; |
| 613 Instruction* stop_instr = reinterpret_cast<Instruction*>(stop_pc); |
| 614 Instruction* msg_address = |
| 615 reinterpret_cast<Instruction*>(stop_pc + |
| 616 Instruction::kInstrSize); |
| 617 if ((argc == 2) && (strcmp(arg1, "unstop") == 0)) { |
| 618 // Remove the current stop. |
| 619 if (sim_->IsStopInstruction(stop_instr)) { |
| 620 stop_instr->SetInstructionBits(kNopInstr); |
| 621 msg_address->SetInstructionBits(kNopInstr); |
| 622 } else { |
| 623 PrintF("Not at debugger stop.\n"); |
| 624 } |
| 625 } else if (argc == 3) { |
| 626 // Print information about all/the specified breakpoint(s). |
| 627 if (strcmp(arg1, "info") == 0) { |
| 628 if (strcmp(arg2, "all") == 0) { |
| 629 PrintF("Stop information:\n"); |
| 630 for (uint32_t i = kMaxWatchpointCode + 1; |
| 631 i <= kMaxStopCode; |
| 632 i++) { |
| 633 sim_->PrintStopInfo(i); |
| 634 } |
| 635 } else if (GetValue(arg2, &value)) { |
| 636 sim_->PrintStopInfo(value); |
| 637 } else { |
| 638 PrintF("Unrecognized argument.\n"); |
| 639 } |
| 640 } else if (strcmp(arg1, "enable") == 0) { |
| 641 // Enable all/the specified breakpoint(s). |
| 642 if (strcmp(arg2, "all") == 0) { |
| 643 for (uint32_t i = kMaxWatchpointCode + 1; |
| 644 i <= kMaxStopCode; |
| 645 i++) { |
| 646 sim_->EnableStop(i); |
| 647 } |
| 648 } else if (GetValue(arg2, &value)) { |
| 649 sim_->EnableStop(value); |
| 650 } else { |
| 651 PrintF("Unrecognized argument.\n"); |
| 652 } |
| 653 } else if (strcmp(arg1, "disable") == 0) { |
| 654 // Disable all/the specified breakpoint(s). |
| 655 if (strcmp(arg2, "all") == 0) { |
| 656 for (uint32_t i = kMaxWatchpointCode + 1; |
| 657 i <= kMaxStopCode; |
| 658 i++) { |
| 659 sim_->DisableStop(i); |
| 660 } |
| 661 } else if (GetValue(arg2, &value)) { |
| 662 sim_->DisableStop(value); |
| 663 } else { |
| 664 PrintF("Unrecognized argument.\n"); |
| 665 } |
| 666 } |
| 667 } else { |
| 668 PrintF("Wrong usage. Use help command for more information.\n"); |
| 669 } |
| 590 } else if ((strcmp(cmd, "stat") == 0) || (strcmp(cmd, "st") == 0)) { | 670 } else if ((strcmp(cmd, "stat") == 0) || (strcmp(cmd, "st") == 0)) { |
| 591 // Print registers and disassemble. | 671 // Print registers and disassemble. |
| 592 PrintAllRegs(); | 672 PrintAllRegs(); |
| 593 PrintF("\n"); | 673 PrintF("\n"); |
| 594 | 674 |
| 595 disasm::NameConverter converter; | 675 disasm::NameConverter converter; |
| 596 disasm::Disassembler dasm(converter); | 676 disasm::Disassembler dasm(converter); |
| 597 // Use a reasonably large buffer. | 677 // Use a reasonably large buffer. |
| 598 v8::internal::EmbeddedVector<char, 256> buffer; | 678 v8::internal::EmbeddedVector<char, 256> buffer; |
| 599 | 679 |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 645 PrintF("disasm [<address/register>]\n"); | 725 PrintF("disasm [<address/register>]\n"); |
| 646 PrintF("disasm [[<address/register>] <instructions>]\n"); | 726 PrintF("disasm [[<address/register>] <instructions>]\n"); |
| 647 PrintF(" disassemble code, default is 10 instructions\n"); | 727 PrintF(" disassemble code, default is 10 instructions\n"); |
| 648 PrintF(" from pc (alias 'di')\n"); | 728 PrintF(" from pc (alias 'di')\n"); |
| 649 PrintF("gdb\n"); | 729 PrintF("gdb\n"); |
| 650 PrintF(" enter gdb\n"); | 730 PrintF(" enter gdb\n"); |
| 651 PrintF("break <address>\n"); | 731 PrintF("break <address>\n"); |
| 652 PrintF(" set a break point on the address\n"); | 732 PrintF(" set a break point on the address\n"); |
| 653 PrintF("del\n"); | 733 PrintF("del\n"); |
| 654 PrintF(" delete the breakpoint\n"); | 734 PrintF(" delete the breakpoint\n"); |
| 655 PrintF("unstop\n"); | 735 PrintF("stop feature:\n"); |
| 656 PrintF(" ignore the stop instruction at the current location"); | 736 PrintF(" Description:\n"); |
| 657 PrintF(" from now on\n"); | 737 PrintF(" Stops are debug instructions inserted by\n"); |
| 738 PrintF(" the Assembler::stop() function.\n"); |
| 739 PrintF(" When hitting a stop, the Simulator will\n"); |
| 740 PrintF(" stop and and give control to the Debugger.\n"); |
| 741 PrintF(" All stop codes are watched:\n"); |
| 742 PrintF(" - They can be enabled / disabled: the Simulator\n"); |
| 743 PrintF(" will / won't stop when hitting them.\n"); |
| 744 PrintF(" - The Simulator keeps track of how many times they \n"); |
| 745 PrintF(" are met. (See the info command.) Going over a\n"); |
| 746 PrintF(" disabled stop still increases its counter. \n"); |
| 747 PrintF(" Commands:\n"); |
| 748 PrintF(" stop info all/<code> : print infos about number <code>\n"); |
| 749 PrintF(" or all stop(s).\n"); |
| 750 PrintF(" stop enable/disable all/<code> : enables / disables\n"); |
| 751 PrintF(" all or number <code> stop(s)\n"); |
| 752 PrintF(" stop unstop\n"); |
| 753 PrintF(" ignore the stop instruction at the current location\n"); |
| 754 PrintF(" from now on\n"); |
| 658 } else { | 755 } else { |
| 659 PrintF("Unknown command: %s\n", cmd); | 756 PrintF("Unknown command: %s\n", cmd); |
| 660 } | 757 } |
| 661 } | 758 } |
| 662 DeleteArray(line); | 759 DeleteArray(line); |
| 663 } | 760 } |
| 664 | 761 |
| 665 // Add all the breakpoints back to stop execution and enter the debugger | 762 // Add all the breakpoints back to stop execution and enter the debugger |
| 666 // shell when hit. | 763 // shell when hit. |
| 667 RedoBreakpoints(); | 764 RedoBreakpoints(); |
| (...skipping 387 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1055 | 1152 |
| 1056 | 1153 |
| 1057 bool Simulator::test_fcsr_bit(uint32_t cc) { | 1154 bool Simulator::test_fcsr_bit(uint32_t cc) { |
| 1058 return FCSR_ & (1 << cc); | 1155 return FCSR_ & (1 << cc); |
| 1059 } | 1156 } |
| 1060 | 1157 |
| 1061 | 1158 |
| 1062 // Sets the rounding error codes in FCSR based on the result of the rounding. | 1159 // Sets the rounding error codes in FCSR based on the result of the rounding. |
| 1063 // Returns true if the operation was invalid. | 1160 // Returns true if the operation was invalid. |
| 1064 bool Simulator::set_fcsr_round_error(double original, double rounded) { | 1161 bool Simulator::set_fcsr_round_error(double original, double rounded) { |
| 1065 if (!isfinite(original) || | 1162 bool ret = false; |
| 1066 rounded > LONG_MAX || | 1163 |
| 1067 rounded < LONG_MIN) { | 1164 if (!isfinite(original) || !isfinite(rounded)) { |
| 1068 set_fcsr_bit(6, true); // Invalid operation. | 1165 set_fcsr_bit(kFCSRInvalidOpFlagBit, true); |
| 1069 return true; | 1166 ret = true; |
| 1070 } else if (original != static_cast<double>(rounded)) { | |
| 1071 set_fcsr_bit(2, true); // Inexact. | |
| 1072 } | 1167 } |
| 1073 return false; | 1168 |
| 1169 if (original != rounded) { |
| 1170 set_fcsr_bit(kFCSRInexactFlagBit, true); |
| 1171 } |
| 1172 |
| 1173 if (rounded < DBL_MIN && rounded > -DBL_MIN && rounded != 0) { |
| 1174 set_fcsr_bit(kFCSRUnderflowFlagBit, true); |
| 1175 ret = true; |
| 1176 } |
| 1177 |
| 1178 if (rounded > INT_MAX || rounded < INT_MIN) { |
| 1179 set_fcsr_bit(kFCSROverflowFlagBit, true); |
| 1180 // The reference is not really clear but it seems this is required: |
| 1181 set_fcsr_bit(kFCSRInvalidOpFlagBit, true); |
| 1182 ret = true; |
| 1183 } |
| 1184 |
| 1185 return ret; |
| 1074 } | 1186 } |
| 1075 | 1187 |
| 1076 | 1188 |
| 1077 // Raw access to the PC register. | 1189 // Raw access to the PC register. |
| 1078 void Simulator::set_pc(int32_t value) { | 1190 void Simulator::set_pc(int32_t value) { |
| 1079 pc_modified_ = true; | 1191 pc_modified_ = true; |
| 1080 registers_[pc] = value; | 1192 registers_[pc] = value; |
| 1081 } | 1193 } |
| 1082 | 1194 |
| 1083 | 1195 |
| (...skipping 197 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1281 typedef v8::Handle<v8::Value> (*SimulatorRuntimeDirectGetterCall)(int32_t arg0, | 1393 typedef v8::Handle<v8::Value> (*SimulatorRuntimeDirectGetterCall)(int32_t arg0, |
| 1282 int32_t arg1); | 1394 int32_t arg1); |
| 1283 | 1395 |
| 1284 // Software interrupt instructions are used by the simulator to call into the | 1396 // Software interrupt instructions are used by the simulator to call into the |
| 1285 // C-based V8 runtime. They are also used for debugging with simulator. | 1397 // C-based V8 runtime. They are also used for debugging with simulator. |
| 1286 void Simulator::SoftwareInterrupt(Instruction* instr) { | 1398 void Simulator::SoftwareInterrupt(Instruction* instr) { |
| 1287 // There are several instructions that could get us here, | 1399 // There are several instructions that could get us here, |
| 1288 // the break_ instruction, or several variants of traps. All | 1400 // the break_ instruction, or several variants of traps. All |
| 1289 // Are "SPECIAL" class opcode, and are distinuished by function. | 1401 // Are "SPECIAL" class opcode, and are distinuished by function. |
| 1290 int32_t func = instr->FunctionFieldRaw(); | 1402 int32_t func = instr->FunctionFieldRaw(); |
| 1291 int32_t code = (func == BREAK) ? instr->Bits(25, 6) : -1; | 1403 uint32_t code = (func == BREAK) ? instr->Bits(25, 6) : -1; |
| 1292 | 1404 |
| 1293 // We first check if we met a call_rt_redirected. | 1405 // We first check if we met a call_rt_redirected. |
| 1294 if (instr->InstructionBits() == rtCallRedirInstr) { | 1406 if (instr->InstructionBits() == rtCallRedirInstr) { |
| 1295 Redirection* redirection = Redirection::FromSwiInstruction(instr); | 1407 Redirection* redirection = Redirection::FromSwiInstruction(instr); |
| 1296 int32_t arg0 = get_register(a0); | 1408 int32_t arg0 = get_register(a0); |
| 1297 int32_t arg1 = get_register(a1); | 1409 int32_t arg1 = get_register(a1); |
| 1298 int32_t arg2 = get_register(a2); | 1410 int32_t arg2 = get_register(a2); |
| 1299 int32_t arg3 = get_register(a3); | 1411 int32_t arg3 = get_register(a3); |
| 1300 int32_t arg4 = 0; | 1412 int32_t arg4 = 0; |
| 1301 int32_t arg5 = 0; | 1413 int32_t arg5 = 0; |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1365 switch (redirection->type()) { | 1477 switch (redirection->type()) { |
| 1366 case ExternalReference::BUILTIN_FP_FP_CALL: | 1478 case ExternalReference::BUILTIN_FP_FP_CALL: |
| 1367 case ExternalReference::BUILTIN_COMPARE_CALL: | 1479 case ExternalReference::BUILTIN_COMPARE_CALL: |
| 1368 GetFpArgs(&dval0, &dval1); | 1480 GetFpArgs(&dval0, &dval1); |
| 1369 PrintF("Call to host function at %p with args %f, %f", | 1481 PrintF("Call to host function at %p with args %f, %f", |
| 1370 FUNCTION_ADDR(target), dval0, dval1); | 1482 FUNCTION_ADDR(target), dval0, dval1); |
| 1371 break; | 1483 break; |
| 1372 case ExternalReference::BUILTIN_FP_CALL: | 1484 case ExternalReference::BUILTIN_FP_CALL: |
| 1373 GetFpArgs(&dval0); | 1485 GetFpArgs(&dval0); |
| 1374 PrintF("Call to host function at %p with arg %f", | 1486 PrintF("Call to host function at %p with arg %f", |
| 1375 FUNCTION_ADDR(target), dval1); | 1487 FUNCTION_ADDR(target), dval0); |
| 1376 break; | 1488 break; |
| 1377 case ExternalReference::BUILTIN_FP_INT_CALL: | 1489 case ExternalReference::BUILTIN_FP_INT_CALL: |
| 1378 GetFpArgs(&dval0, &ival); | 1490 GetFpArgs(&dval0, &ival); |
| 1379 PrintF("Call to host function at %p with args %f, %d", | 1491 PrintF("Call to host function at %p with args %f, %d", |
| 1380 FUNCTION_ADDR(target), dval0, ival); | 1492 FUNCTION_ADDR(target), dval0, ival); |
| 1381 break; | 1493 break; |
| 1382 default: | 1494 default: |
| 1383 UNREACHABLE(); | 1495 UNREACHABLE(); |
| 1384 break; | 1496 break; |
| 1385 } | 1497 } |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1433 int64_t result = target(arg0, arg1, arg2, arg3, arg4, arg5); | 1545 int64_t result = target(arg0, arg1, arg2, arg3, arg4, arg5); |
| 1434 set_register(v0, static_cast<int32_t>(result)); | 1546 set_register(v0, static_cast<int32_t>(result)); |
| 1435 set_register(v1, static_cast<int32_t>(result >> 32)); | 1547 set_register(v1, static_cast<int32_t>(result >> 32)); |
| 1436 } | 1548 } |
| 1437 if (::v8::internal::FLAG_trace_sim) { | 1549 if (::v8::internal::FLAG_trace_sim) { |
| 1438 PrintF("Returned %08x : %08x\n", get_register(v1), get_register(v0)); | 1550 PrintF("Returned %08x : %08x\n", get_register(v1), get_register(v0)); |
| 1439 } | 1551 } |
| 1440 set_register(ra, saved_ra); | 1552 set_register(ra, saved_ra); |
| 1441 set_pc(get_register(ra)); | 1553 set_pc(get_register(ra)); |
| 1442 | 1554 |
| 1443 } else if (func == BREAK && code >= 0 && code < 32) { | 1555 } else if (func == BREAK && code <= kMaxStopCode) { |
| 1444 // First 32 break_ codes interpreted as debug-markers/watchpoints. | 1556 if (IsWatchpoint(code)) { |
| 1445 MipsDebugger dbg(this); | 1557 PrintWatchpoint(code); |
| 1446 ++break_count_; | 1558 } else { |
| 1447 PrintF("\n---- break %d marker: %3d (instr count: %8d) ----------" | 1559 IncreaseStopCounter(code); |
| 1448 "----------------------------------", | 1560 HandleStop(code, instr); |
| 1449 code, break_count_, icount_); | 1561 } |
| 1450 dbg.PrintAllRegs(); // Print registers and continue running. | |
| 1451 } else { | 1562 } else { |
| 1452 // All remaining break_ codes, and all traps are handled here. | 1563 // All remaining break_ codes, and all traps are handled here. |
| 1453 MipsDebugger dbg(this); | 1564 MipsDebugger dbg(this); |
| 1454 dbg.Debug(); | 1565 dbg.Debug(); |
| 1455 } | 1566 } |
| 1456 } | 1567 } |
| 1457 | 1568 |
| 1458 | 1569 |
| 1570 // Stop helper functions. |
| 1571 bool Simulator::IsWatchpoint(uint32_t code) { |
| 1572 return (code <= kMaxWatchpointCode); |
| 1573 } |
| 1574 |
| 1575 |
| 1576 void Simulator::PrintWatchpoint(uint32_t code) { |
| 1577 MipsDebugger dbg(this); |
| 1578 ++break_count_; |
| 1579 PrintF("\n---- break %d marker: %3d (instr count: %8d) ----------" |
| 1580 "----------------------------------", |
| 1581 code, break_count_, icount_); |
| 1582 dbg.PrintAllRegs(); // Print registers and continue running. |
| 1583 } |
| 1584 |
| 1585 |
| 1586 void Simulator::HandleStop(uint32_t code, Instruction* instr) { |
| 1587 // Stop if it is enabled, otherwise go on jumping over the stop |
| 1588 // and the message address. |
| 1589 if (IsEnabledStop(code)) { |
| 1590 MipsDebugger dbg(this); |
| 1591 dbg.Stop(instr); |
| 1592 } else { |
| 1593 set_pc(get_pc() + 2 * Instruction::kInstrSize); |
| 1594 } |
| 1595 } |
| 1596 |
| 1597 |
| 1598 bool Simulator::IsStopInstruction(Instruction* instr) { |
| 1599 int32_t func = instr->FunctionFieldRaw(); |
| 1600 uint32_t code = static_cast<uint32_t>(instr->Bits(25, 6)); |
| 1601 return (func == BREAK) && code > kMaxWatchpointCode && code <= kMaxStopCode; |
| 1602 } |
| 1603 |
| 1604 |
| 1605 bool Simulator::IsEnabledStop(uint32_t code) { |
| 1606 ASSERT(code <= kMaxStopCode); |
| 1607 ASSERT(code > kMaxWatchpointCode); |
| 1608 return !(watched_stops[code].count & kStopDisabledBit); |
| 1609 } |
| 1610 |
| 1611 |
| 1612 void Simulator::EnableStop(uint32_t code) { |
| 1613 if (!IsEnabledStop(code)) { |
| 1614 watched_stops[code].count &= ~kStopDisabledBit; |
| 1615 } |
| 1616 } |
| 1617 |
| 1618 |
| 1619 void Simulator::DisableStop(uint32_t code) { |
| 1620 if (IsEnabledStop(code)) { |
| 1621 watched_stops[code].count |= kStopDisabledBit; |
| 1622 } |
| 1623 } |
| 1624 |
| 1625 |
| 1626 void Simulator::IncreaseStopCounter(uint32_t code) { |
| 1627 ASSERT(code <= kMaxStopCode); |
| 1628 if ((watched_stops[code].count & ~(1 << 31)) == 0x7fffffff) { |
| 1629 PrintF("Stop counter for code %i has overflowed.\n" |
| 1630 "Enabling this code and reseting the counter to 0.\n", code); |
| 1631 watched_stops[code].count = 0; |
| 1632 EnableStop(code); |
| 1633 } else { |
| 1634 watched_stops[code].count++; |
| 1635 } |
| 1636 } |
| 1637 |
| 1638 |
| 1639 // Print a stop status. |
| 1640 void Simulator::PrintStopInfo(uint32_t code) { |
| 1641 if (code <= kMaxWatchpointCode) { |
| 1642 PrintF("That is a watchpoint, not a stop.\n"); |
| 1643 return; |
| 1644 } else if (code > kMaxStopCode) { |
| 1645 PrintF("Code too large, only %u stops can be used\n", kMaxStopCode + 1); |
| 1646 return; |
| 1647 } |
| 1648 const char* state = IsEnabledStop(code) ? "Enabled" : "Disabled"; |
| 1649 int32_t count = watched_stops[code].count & ~kStopDisabledBit; |
| 1650 // Don't print the state of unused breakpoints. |
| 1651 if (count != 0) { |
| 1652 if (watched_stops[code].desc) { |
| 1653 PrintF("stop %i - 0x%x: \t%s, \tcounter = %i, \t%s\n", |
| 1654 code, code, state, count, watched_stops[code].desc); |
| 1655 } else { |
| 1656 PrintF("stop %i - 0x%x: \t%s, \tcounter = %i\n", |
| 1657 code, code, state, count); |
| 1658 } |
| 1659 } |
| 1660 } |
| 1661 |
| 1662 |
| 1459 void Simulator::SignalExceptions() { | 1663 void Simulator::SignalExceptions() { |
| 1460 for (int i = 1; i < kNumExceptions; i++) { | 1664 for (int i = 1; i < kNumExceptions; i++) { |
| 1461 if (exceptions[i] != 0) { | 1665 if (exceptions[i] != 0) { |
| 1462 V8_Fatal(__FILE__, __LINE__, "Error: Exception %i raised.", i); | 1666 V8_Fatal(__FILE__, __LINE__, "Error: Exception %i raised.", i); |
| 1463 } | 1667 } |
| 1464 } | 1668 } |
| 1465 } | 1669 } |
| 1466 | 1670 |
| 1467 | 1671 |
| 1468 // Handle execution based on instruction types. | 1672 // Handle execution based on instruction types. |
| (...skipping 389 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1858 double rounded = fs > 0 ? floor(fs + 0.5) : ceil(fs - 0.5); | 2062 double rounded = fs > 0 ? floor(fs + 0.5) : ceil(fs - 0.5); |
| 1859 int32_t result = static_cast<int32_t>(rounded); | 2063 int32_t result = static_cast<int32_t>(rounded); |
| 1860 set_fpu_register(fd_reg, result); | 2064 set_fpu_register(fd_reg, result); |
| 1861 if (set_fcsr_round_error(fs, rounded)) { | 2065 if (set_fcsr_round_error(fs, rounded)) { |
| 1862 set_fpu_register(fd_reg, kFPUInvalidResult); | 2066 set_fpu_register(fd_reg, kFPUInvalidResult); |
| 1863 } | 2067 } |
| 1864 } | 2068 } |
| 1865 break; | 2069 break; |
| 1866 case TRUNC_W_D: // Truncate double to word (round towards 0). | 2070 case TRUNC_W_D: // Truncate double to word (round towards 0). |
| 1867 { | 2071 { |
| 1868 int32_t result = static_cast<int32_t>(fs); | 2072 double rounded = trunc(fs); |
| 2073 int32_t result = static_cast<int32_t>(rounded); |
| 1869 set_fpu_register(fd_reg, result); | 2074 set_fpu_register(fd_reg, result); |
| 1870 if (set_fcsr_round_error(fs, static_cast<double>(result))) { | 2075 if (set_fcsr_round_error(fs, rounded)) { |
| 1871 set_fpu_register(fd_reg, kFPUInvalidResult); | 2076 set_fpu_register(fd_reg, kFPUInvalidResult); |
| 1872 } | 2077 } |
| 1873 } | 2078 } |
| 1874 break; | 2079 break; |
| 1875 case FLOOR_W_D: // Round double to word towards negative infinity. | 2080 case FLOOR_W_D: // Round double to word towards negative infinity. |
| 1876 { | 2081 { |
| 1877 double rounded = floor(fs); | 2082 double rounded = floor(fs); |
| 1878 int32_t result = static_cast<int32_t>(rounded); | 2083 int32_t result = static_cast<int32_t>(rounded); |
| 1879 set_fpu_register(fd_reg, result); | 2084 set_fpu_register(fd_reg, result); |
| 1880 if (set_fcsr_round_error(fs, rounded)) { | 2085 if (set_fcsr_round_error(fs, rounded)) { |
| 1881 set_fpu_register(fd_reg, kFPUInvalidResult); | 2086 set_fpu_register(fd_reg, kFPUInvalidResult); |
| 1882 } | 2087 } |
| 1883 } | 2088 } |
| 1884 break; | 2089 break; |
| 1885 case CEIL_W_D: // Round double to word towards positive infinity. | 2090 case CEIL_W_D: // Round double to word towards positive infinity. |
| 1886 { | 2091 { |
| 1887 double rounded = ceil(fs); | 2092 double rounded = ceil(fs); |
| 1888 int32_t result = static_cast<int32_t>(rounded); | 2093 int32_t result = static_cast<int32_t>(rounded); |
| 1889 set_fpu_register(fd_reg, result); | 2094 set_fpu_register(fd_reg, result); |
| 1890 if (set_fcsr_round_error(fs, rounded)) { | 2095 if (set_fcsr_round_error(fs, rounded)) { |
| 1891 set_fpu_register(fd_reg, kFPUInvalidResult); | 2096 set_fpu_register(fd_reg, kFPUInvalidResult); |
| 1892 } | 2097 } |
| 1893 } | 2098 } |
| 1894 break; | 2099 break; |
| 1895 case CVT_S_D: // Convert double to float (single). | 2100 case CVT_S_D: // Convert double to float (single). |
| 1896 set_fpu_register_float(fd_reg, static_cast<float>(fs)); | 2101 set_fpu_register_float(fd_reg, static_cast<float>(fs)); |
| 1897 break; | 2102 break; |
| 1898 case CVT_L_D: // Mips32r2: Truncate double to 64-bit long-word. | 2103 case CVT_L_D: { // Mips32r2: Truncate double to 64-bit long-word. |
| 1899 i64 = static_cast<int64_t>(fs); | 2104 double rounded = trunc(fs); |
| 2105 i64 = static_cast<int64_t>(rounded); |
| 1900 set_fpu_register(fd_reg, i64 & 0xffffffff); | 2106 set_fpu_register(fd_reg, i64 & 0xffffffff); |
| 1901 set_fpu_register(fd_reg + 1, i64 >> 32); | 2107 set_fpu_register(fd_reg + 1, i64 >> 32); |
| 1902 break; | 2108 break; |
| 1903 case TRUNC_L_D: // Mips32r2 instruction. | 2109 } |
| 1904 i64 = static_cast<int64_t>(fs); | 2110 case TRUNC_L_D: { // Mips32r2 instruction. |
| 2111 double rounded = trunc(fs); |
| 2112 i64 = static_cast<int64_t>(rounded); |
| 1905 set_fpu_register(fd_reg, i64 & 0xffffffff); | 2113 set_fpu_register(fd_reg, i64 & 0xffffffff); |
| 1906 set_fpu_register(fd_reg + 1, i64 >> 32); | 2114 set_fpu_register(fd_reg + 1, i64 >> 32); |
| 1907 break; | 2115 break; |
| 2116 } |
| 1908 case ROUND_L_D: { // Mips32r2 instruction. | 2117 case ROUND_L_D: { // Mips32r2 instruction. |
| 1909 double rounded = fs > 0 ? floor(fs + 0.5) : ceil(fs - 0.5); | 2118 double rounded = fs > 0 ? floor(fs + 0.5) : ceil(fs - 0.5); |
| 1910 i64 = static_cast<int64_t>(rounded); | 2119 i64 = static_cast<int64_t>(rounded); |
| 1911 set_fpu_register(fd_reg, i64 & 0xffffffff); | 2120 set_fpu_register(fd_reg, i64 & 0xffffffff); |
| 1912 set_fpu_register(fd_reg + 1, i64 >> 32); | 2121 set_fpu_register(fd_reg + 1, i64 >> 32); |
| 1913 break; | 2122 break; |
| 1914 } | 2123 } |
| 1915 case FLOOR_L_D: // Mips32r2 instruction. | 2124 case FLOOR_L_D: // Mips32r2 instruction. |
| 1916 i64 = static_cast<int64_t>(floor(fs)); | 2125 i64 = static_cast<int64_t>(floor(fs)); |
| 1917 set_fpu_register(fd_reg, i64 & 0xffffffff); | 2126 set_fpu_register(fd_reg, i64 & 0xffffffff); |
| (...skipping 694 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2612 } | 2821 } |
| 2613 | 2822 |
| 2614 | 2823 |
| 2615 #undef UNSUPPORTED | 2824 #undef UNSUPPORTED |
| 2616 | 2825 |
| 2617 } } // namespace v8::internal | 2826 } } // namespace v8::internal |
| 2618 | 2827 |
| 2619 #endif // USE_SIMULATOR | 2828 #endif // USE_SIMULATOR |
| 2620 | 2829 |
| 2621 #endif // V8_TARGET_ARCH_MIPS | 2830 #endif // V8_TARGET_ARCH_MIPS |
| OLD | NEW |