| OLD | NEW |
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, 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_ARM) | 10 #if defined(TARGET_ARCH_ARM) |
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 88 | 88 |
| 89 // The SimulatorDebugger class is used by the simulator while debugging | 89 // The SimulatorDebugger class is used by the simulator while debugging |
| 90 // simulated ARM code. | 90 // simulated ARM code. |
| 91 class SimulatorDebugger { | 91 class SimulatorDebugger { |
| 92 public: | 92 public: |
| 93 explicit SimulatorDebugger(Simulator* sim); | 93 explicit SimulatorDebugger(Simulator* sim); |
| 94 ~SimulatorDebugger(); | 94 ~SimulatorDebugger(); |
| 95 | 95 |
| 96 void Stop(Instr* instr, const char* message); | 96 void Stop(Instr* instr, const char* message); |
| 97 void Debug(); | 97 void Debug(); |
| 98 |
| 98 char* ReadLine(const char* prompt); | 99 char* ReadLine(const char* prompt); |
| 99 | 100 |
| 100 private: | 101 private: |
| 101 static const int32_t kSimulatorBreakpointInstr = // svc #kBreakpointSvcCode | 102 static const int32_t kSimulatorBreakpointInstr = // svc #kBreakpointSvcCode |
| 102 ((AL << kConditionShift) | (0xf << 24) | kBreakpointSvcCode); | 103 ((AL << kConditionShift) | (0xf << 24) | kBreakpointSvcCode); |
| 103 static const int32_t kNopInstr = // nop | 104 static const int32_t kNopInstr = // nop |
| 104 ((AL << kConditionShift) | (0x32 << 20) | (0xf << 12)); | 105 ((AL << kConditionShift) | (0x32 << 20) | (0xf << 12)); |
| 105 | 106 |
| 106 Simulator* sim_; | 107 Simulator* sim_; |
| 107 | 108 |
| (...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 286 void SimulatorDebugger::RedoBreakpoints() { | 287 void SimulatorDebugger::RedoBreakpoints() { |
| 287 if (sim_->break_pc_ != NULL) { | 288 if (sim_->break_pc_ != NULL) { |
| 288 sim_->break_pc_->SetInstructionBits(kSimulatorBreakpointInstr); | 289 sim_->break_pc_->SetInstructionBits(kSimulatorBreakpointInstr); |
| 289 } | 290 } |
| 290 } | 291 } |
| 291 | 292 |
| 292 | 293 |
| 293 void SimulatorDebugger::Debug() { | 294 void SimulatorDebugger::Debug() { |
| 294 intptr_t last_pc = -1; | 295 intptr_t last_pc = -1; |
| 295 bool done = false; | 296 bool done = false; |
| 296 bool decoded = true; | |
| 297 | 297 |
| 298 #define COMMAND_SIZE 63 | 298 #define COMMAND_SIZE 63 |
| 299 #define ARG_SIZE 255 | 299 #define ARG_SIZE 255 |
| 300 | 300 |
| 301 #define STR(a) #a | 301 #define STR(a) #a |
| 302 #define XSTR(a) STR(a) | 302 #define XSTR(a) STR(a) |
| 303 | 303 |
| 304 char cmd[COMMAND_SIZE + 1]; | 304 char cmd[COMMAND_SIZE + 1]; |
| 305 char arg1[ARG_SIZE + 1]; | 305 char arg1[ARG_SIZE + 1]; |
| 306 char arg2[ARG_SIZE + 1]; | 306 char arg2[ARG_SIZE + 1]; |
| 307 | 307 |
| 308 // make sure to have a proper terminating character if reaching the limit | 308 // make sure to have a proper terminating character if reaching the limit |
| 309 cmd[COMMAND_SIZE] = 0; | 309 cmd[COMMAND_SIZE] = 0; |
| 310 arg1[ARG_SIZE] = 0; | 310 arg1[ARG_SIZE] = 0; |
| 311 arg2[ARG_SIZE] = 0; | 311 arg2[ARG_SIZE] = 0; |
| 312 | 312 |
| 313 // Undo all set breakpoints while running in the debugger shell. This will | 313 // Undo all set breakpoints while running in the debugger shell. This will |
| 314 // make them invisible to all commands. | 314 // make them invisible to all commands. |
| 315 UndoBreakpoints(); | 315 UndoBreakpoints(); |
| 316 | 316 |
| 317 while (!done) { | 317 while (!done) { |
| 318 if (last_pc != sim_->get_pc()) { | 318 if (last_pc != sim_->get_pc()) { |
| 319 last_pc = sim_->get_pc(); | 319 last_pc = sim_->get_pc(); |
| 320 decoded = Disassembler::Disassemble(last_pc, last_pc + Instr::kInstrSize); | 320 Disassembler::Disassemble(last_pc, last_pc + Instr::kInstrSize); |
| 321 } | 321 } |
| 322 char* line = ReadLine("sim> "); | 322 char* line = ReadLine("sim> "); |
| 323 if (line == NULL) { | 323 if (line == NULL) { |
| 324 break; | 324 FATAL("ReadLine failed"); |
| 325 } else { | 325 } else { |
| 326 // Use sscanf to parse the individual parts of the command line. At the | 326 // Use sscanf to parse the individual parts of the command line. At the |
| 327 // moment no command expects more than two parameters. | 327 // moment no command expects more than two parameters. |
| 328 int args = SScanF(line, | 328 int args = SScanF(line, |
| 329 "%" XSTR(COMMAND_SIZE) "s " | 329 "%" XSTR(COMMAND_SIZE) "s " |
| 330 "%" XSTR(ARG_SIZE) "s " | 330 "%" XSTR(ARG_SIZE) "s " |
| 331 "%" XSTR(ARG_SIZE) "s", | 331 "%" XSTR(ARG_SIZE) "s", |
| 332 cmd, arg1, arg2); | 332 cmd, arg1, arg2); |
| 333 if ((strcmp(cmd, "h") == 0) || (strcmp(cmd, "help") == 0)) { | 333 if ((strcmp(cmd, "h") == 0) || (strcmp(cmd, "help") == 0)) { |
| 334 OS::Print("c/cont -- continue execution\n" | 334 OS::Print("c/cont -- continue execution\n" |
| (...skipping 11 matching lines...) Expand all Loading... |
| 346 "pf/printfloat <sreg or *addr> -- print float value\n" | 346 "pf/printfloat <sreg or *addr> -- print float value\n" |
| 347 "pd/printdouble <dreg or *addr> -- print double value\n" | 347 "pd/printdouble <dreg or *addr> -- print double value\n" |
| 348 "po/printobject <*reg or *addr> -- print object\n" | 348 "po/printobject <*reg or *addr> -- print object\n" |
| 349 "si/stepi -- single step an instruction\n" | 349 "si/stepi -- single step an instruction\n" |
| 350 "unstop -- if current pc is a stop instr make it a nop\n" | 350 "unstop -- if current pc is a stop instr make it a nop\n" |
| 351 "q/quit -- Quit the debugger and exit the program\n"); | 351 "q/quit -- Quit the debugger and exit the program\n"); |
| 352 } else if ((strcmp(cmd, "quit") == 0) || (strcmp(cmd, "q") == 0)) { | 352 } else if ((strcmp(cmd, "quit") == 0) || (strcmp(cmd, "q") == 0)) { |
| 353 OS::Print("Quitting\n"); | 353 OS::Print("Quitting\n"); |
| 354 OS::Exit(0); | 354 OS::Exit(0); |
| 355 } else if ((strcmp(cmd, "si") == 0) || (strcmp(cmd, "stepi") == 0)) { | 355 } else if ((strcmp(cmd, "si") == 0) || (strcmp(cmd, "stepi") == 0)) { |
| 356 if (decoded) { | 356 sim_->InstructionDecode(reinterpret_cast<Instr*>(sim_->get_pc())); |
| 357 sim_->InstructionDecode(reinterpret_cast<Instr*>(sim_->get_pc())); | |
| 358 } else { | |
| 359 OS::Print("Instruction could not be decoded. Stepping disabled.\n"); | |
| 360 } | |
| 361 } else if ((strcmp(cmd, "c") == 0) || (strcmp(cmd, "cont") == 0)) { | 357 } else if ((strcmp(cmd, "c") == 0) || (strcmp(cmd, "cont") == 0)) { |
| 362 if (decoded) { | 358 // Execute the one instruction we broke at with breakpoints disabled. |
| 363 // Execute the one instruction we broke at with breakpoints disabled. | 359 sim_->InstructionDecode(reinterpret_cast<Instr*>(sim_->get_pc())); |
| 364 sim_->InstructionDecode(reinterpret_cast<Instr*>(sim_->get_pc())); | 360 // Leave the debugger shell. |
| 365 // Leave the debugger shell. | 361 done = true; |
| 366 done = true; | |
| 367 } else { | |
| 368 OS::Print("Instruction could not be decoded. Cannot continue.\n"); | |
| 369 } | |
| 370 } else if ((strcmp(cmd, "p") == 0) || (strcmp(cmd, "print") == 0)) { | 362 } else if ((strcmp(cmd, "p") == 0) || (strcmp(cmd, "print") == 0)) { |
| 371 if (args == 2) { | 363 if (args == 2) { |
| 372 uint32_t value; | 364 uint32_t value; |
| 373 if (GetValue(arg1, &value)) { | 365 if (GetValue(arg1, &value)) { |
| 374 OS::Print("%s: %u 0x%x\n", arg1, value, value); | 366 OS::Print("%s: %u 0x%x\n", arg1, value, value); |
| 375 } else { | 367 } else { |
| 376 OS::Print("%s unrecognized\n", arg1); | 368 OS::Print("%s unrecognized\n", arg1); |
| 377 } | 369 } |
| 378 } else { | 370 } else { |
| 379 OS::Print("print <reg or value or *addr>\n"); | 371 OS::Print("print <reg or value or *addr>\n"); |
| (...skipping 458 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 838 char buffer[64]; | 830 char buffer[64]; |
| 839 snprintf(buffer, sizeof(buffer), | 831 snprintf(buffer, sizeof(buffer), |
| 840 "unaligned %s at 0x%"Px", pc=%p\n", msg, addr, instr); | 832 "unaligned %s at 0x%"Px", pc=%p\n", msg, addr, instr); |
| 841 SimulatorDebugger dbg(this); | 833 SimulatorDebugger dbg(this); |
| 842 dbg.Stop(instr, buffer); | 834 dbg.Stop(instr, buffer); |
| 843 // The debugger will return control in non-interactive mode. | 835 // The debugger will return control in non-interactive mode. |
| 844 FATAL("Cannot continue execution after unaligned access."); | 836 FATAL("Cannot continue execution after unaligned access."); |
| 845 } | 837 } |
| 846 | 838 |
| 847 | 839 |
| 840 void Simulator::UnimplementedInstruction(Instr* instr) { |
| 841 char buffer[64]; |
| 842 snprintf(buffer, sizeof(buffer), "Unimplemented instruction: pc=%p\n", instr); |
| 843 SimulatorDebugger dbg(this); |
| 844 dbg.Stop(instr, buffer); |
| 845 FATAL("Cannot continue execution after unimplemented instruction."); |
| 846 } |
| 847 |
| 848 |
| 848 int Simulator::ReadW(uword addr, Instr* instr) { | 849 int Simulator::ReadW(uword addr, Instr* instr) { |
| 849 static StatsCounter counter_read_w("Simulated word reads"); | 850 static StatsCounter counter_read_w("Simulated word reads"); |
| 850 counter_read_w.Increment(); | 851 counter_read_w.Increment(); |
| 851 if ((addr & 3) == 0) { | 852 if ((addr & 3) == 0) { |
| 852 intptr_t* ptr = reinterpret_cast<intptr_t*>(addr); | 853 intptr_t* ptr = reinterpret_cast<intptr_t*>(addr); |
| 853 return *ptr; | 854 return *ptr; |
| 854 } | 855 } |
| 855 UnalignedAccess("read", addr, instr); | 856 UnalignedAccess("read", addr, instr); |
| 856 return 0; | 857 return 0; |
| 857 } | 858 } |
| (...skipping 221 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1079 | 1080 |
| 1080 // Addressing Mode 1 - Data-processing operands: | 1081 // Addressing Mode 1 - Data-processing operands: |
| 1081 // Get the value based on the shifter_operand with register. | 1082 // Get the value based on the shifter_operand with register. |
| 1082 int32_t Simulator::GetShiftRm(Instr* instr, bool* carry_out) { | 1083 int32_t Simulator::GetShiftRm(Instr* instr, bool* carry_out) { |
| 1083 Shift shift = instr->ShiftField(); | 1084 Shift shift = instr->ShiftField(); |
| 1084 int shift_amount = instr->ShiftAmountField(); | 1085 int shift_amount = instr->ShiftAmountField(); |
| 1085 int32_t result = get_register(instr->RmField()); | 1086 int32_t result = get_register(instr->RmField()); |
| 1086 if (instr->Bit(4) == 0) { | 1087 if (instr->Bit(4) == 0) { |
| 1087 // by immediate | 1088 // by immediate |
| 1088 if ((shift == ROR) && (shift_amount == 0)) { | 1089 if ((shift == ROR) && (shift_amount == 0)) { |
| 1089 UNIMPLEMENTED(); | 1090 UnimplementedInstruction(instr); |
| 1090 return result; | |
| 1091 } else if (((shift == LSR) || (shift == ASR)) && (shift_amount == 0)) { | 1091 } else if (((shift == LSR) || (shift == ASR)) && (shift_amount == 0)) { |
| 1092 shift_amount = 32; | 1092 shift_amount = 32; |
| 1093 } | 1093 } |
| 1094 switch (shift) { | 1094 switch (shift) { |
| 1095 case ASR: { | 1095 case ASR: { |
| 1096 if (shift_amount == 0) { | 1096 if (shift_amount == 0) { |
| 1097 if (result < 0) { | 1097 if (result < 0) { |
| 1098 result = 0xffffffff; | 1098 result = 0xffffffff; |
| 1099 *carry_out = true; | 1099 *carry_out = true; |
| 1100 } else { | 1100 } else { |
| (...skipping 27 matching lines...) Expand all Loading... |
| 1128 uint32_t uresult = static_cast<uint32_t>(result); | 1128 uint32_t uresult = static_cast<uint32_t>(result); |
| 1129 uresult >>= (shift_amount - 1); | 1129 uresult >>= (shift_amount - 1); |
| 1130 *carry_out = (uresult & 1) == 1; | 1130 *carry_out = (uresult & 1) == 1; |
| 1131 uresult >>= 1; | 1131 uresult >>= 1; |
| 1132 result = static_cast<int32_t>(uresult); | 1132 result = static_cast<int32_t>(uresult); |
| 1133 } | 1133 } |
| 1134 break; | 1134 break; |
| 1135 } | 1135 } |
| 1136 | 1136 |
| 1137 case ROR: { | 1137 case ROR: { |
| 1138 UNIMPLEMENTED(); | 1138 UnimplementedInstruction(instr); |
| 1139 break; | 1139 break; |
| 1140 } | 1140 } |
| 1141 | 1141 |
| 1142 default: { | 1142 default: { |
| 1143 UNREACHABLE(); | 1143 UNREACHABLE(); |
| 1144 break; | 1144 break; |
| 1145 } | 1145 } |
| 1146 } | 1146 } |
| 1147 } else { | 1147 } else { |
| 1148 // by register | 1148 // by register |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1200 *carry_out = (result < 0); | 1200 *carry_out = (result < 0); |
| 1201 result = 0; | 1201 result = 0; |
| 1202 } else { | 1202 } else { |
| 1203 *carry_out = false; | 1203 *carry_out = false; |
| 1204 result = 0; | 1204 result = 0; |
| 1205 } | 1205 } |
| 1206 break; | 1206 break; |
| 1207 } | 1207 } |
| 1208 | 1208 |
| 1209 case ROR: { | 1209 case ROR: { |
| 1210 UNIMPLEMENTED(); | 1210 UnimplementedInstruction(instr); |
| 1211 break; | 1211 break; |
| 1212 } | 1212 } |
| 1213 | 1213 |
| 1214 default: { | 1214 default: { |
| 1215 UNREACHABLE(); | 1215 UNREACHABLE(); |
| 1216 break; | 1216 break; |
| 1217 } | 1217 } |
| 1218 } | 1218 } |
| 1219 } | 1219 } |
| 1220 return result; | 1220 return result; |
| (...skipping 246 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1467 case 7: { | 1467 case 7: { |
| 1468 if (instr->Bits(21, 2) == 0x1) { | 1468 if (instr->Bits(21, 2) == 0x1) { |
| 1469 // Format(instr, "bkpt'cond #'imm12_4"); | 1469 // Format(instr, "bkpt'cond #'imm12_4"); |
| 1470 SimulatorDebugger dbg(this); | 1470 SimulatorDebugger dbg(this); |
| 1471 set_pc(get_pc() + Instr::kInstrSize); | 1471 set_pc(get_pc() + Instr::kInstrSize); |
| 1472 char buffer[32]; | 1472 char buffer[32]; |
| 1473 snprintf(buffer, sizeof(buffer), "bkpt #0x%x", instr->BkptField()); | 1473 snprintf(buffer, sizeof(buffer), "bkpt #0x%x", instr->BkptField()); |
| 1474 dbg.Stop(instr, buffer); | 1474 dbg.Stop(instr, buffer); |
| 1475 } else { | 1475 } else { |
| 1476 // Format(instr, "smc'cond"); | 1476 // Format(instr, "smc'cond"); |
| 1477 UNIMPLEMENTED(); | 1477 UnimplementedInstruction(instr); |
| 1478 } | 1478 } |
| 1479 break; | 1479 break; |
| 1480 } | 1480 } |
| 1481 default: { | 1481 default: { |
| 1482 UNIMPLEMENTED(); | 1482 UnimplementedInstruction(instr); |
| 1483 break; | 1483 break; |
| 1484 } | 1484 } |
| 1485 } | 1485 } |
| 1486 } else if (instr->IsMultiplyOrSyncPrimitive()) { | 1486 } else if (instr->IsMultiplyOrSyncPrimitive()) { |
| 1487 if (instr->Bit(24) == 0) { | 1487 if (instr->Bit(24) == 0) { |
| 1488 // multiply instructions. | 1488 // multiply instructions. |
| 1489 Register rn = instr->RnField(); | 1489 Register rn = instr->RnField(); |
| 1490 Register rd = instr->RdField(); | 1490 Register rd = instr->RdField(); |
| 1491 Register rs = instr->RsField(); | 1491 Register rs = instr->RsField(); |
| 1492 Register rm = instr->RmField(); | 1492 Register rm = instr->RmField(); |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1532 // Collapse bits 0..31 into bit 32 so that 32-bit Z check works. | 1532 // Collapse bits 0..31 into bit 32 so that 32-bit Z check works. |
| 1533 hi_res |= 1; | 1533 hi_res |= 1; |
| 1534 } | 1534 } |
| 1535 ASSERT((result == 0) == (hi_res == 0)); // Z bit | 1535 ASSERT((result == 0) == (hi_res == 0)); // Z bit |
| 1536 ASSERT(((result & (1LL << 63)) != 0) == (hi_res < 0)); // N bit | 1536 ASSERT(((result & (1LL << 63)) != 0) == (hi_res < 0)); // N bit |
| 1537 SetNZFlags(hi_res); | 1537 SetNZFlags(hi_res); |
| 1538 } | 1538 } |
| 1539 break; | 1539 break; |
| 1540 } | 1540 } |
| 1541 default: { | 1541 default: { |
| 1542 UNIMPLEMENTED(); | 1542 UnimplementedInstruction(instr); |
| 1543 break; | 1543 break; |
| 1544 } | 1544 } |
| 1545 } | 1545 } |
| 1546 } else { | 1546 } else { |
| 1547 // synchronization primitives | 1547 // synchronization primitives |
| 1548 Register rd = instr->RdField(); | 1548 Register rd = instr->RdField(); |
| 1549 Register rn = instr->RnField(); | 1549 Register rn = instr->RnField(); |
| 1550 uword addr = get_register(rn); | 1550 uword addr = get_register(rn); |
| 1551 switch (instr->Bits(20, 4)) { | 1551 switch (instr->Bits(20, 4)) { |
| 1552 case 8: { | 1552 case 8: { |
| 1553 // Format(instr, "strex'cond 'rd, 'rm, ['rn]"); | 1553 // Format(instr, "strex'cond 'rd, 'rm, ['rn]"); |
| 1554 if (IsIllegalAddress(addr)) { | 1554 if (IsIllegalAddress(addr)) { |
| 1555 HandleIllegalAccess(addr, instr); | 1555 HandleIllegalAccess(addr, instr); |
| 1556 } else { | 1556 } else { |
| 1557 Register rm = instr->RmField(); | 1557 Register rm = instr->RmField(); |
| 1558 set_register(rd, WriteExclusiveW(addr, get_register(rm), instr)); | 1558 set_register(rd, WriteExclusiveW(addr, get_register(rm), instr)); |
| 1559 } | 1559 } |
| 1560 break; | 1560 break; |
| 1561 } | 1561 } |
| 1562 case 9: { | 1562 case 9: { |
| 1563 // Format(instr, "ldrex'cond 'rd, ['rn]"); | 1563 // Format(instr, "ldrex'cond 'rd, ['rn]"); |
| 1564 if (IsIllegalAddress(addr)) { | 1564 if (IsIllegalAddress(addr)) { |
| 1565 HandleIllegalAccess(addr, instr); | 1565 HandleIllegalAccess(addr, instr); |
| 1566 } else { | 1566 } else { |
| 1567 set_register(rd, ReadExclusiveW(addr, instr)); | 1567 set_register(rd, ReadExclusiveW(addr, instr)); |
| 1568 } | 1568 } |
| 1569 break; | 1569 break; |
| 1570 } | 1570 } |
| 1571 default: { | 1571 default: { |
| 1572 UNIMPLEMENTED(); | 1572 UnimplementedInstruction(instr); |
| 1573 break; | 1573 break; |
| 1574 } | 1574 } |
| 1575 } | 1575 } |
| 1576 } | 1576 } |
| 1577 } else if (instr->Bit(25) == 1) { | 1577 } else if (instr->Bit(25) == 1) { |
| 1578 // 16-bit immediate loads, msr (immediate), and hints | 1578 // 16-bit immediate loads, msr (immediate), and hints |
| 1579 switch (instr->Bits(20, 5)) { | 1579 switch (instr->Bits(20, 5)) { |
| 1580 case 16: | 1580 case 16: |
| 1581 case 20: { | 1581 case 20: { |
| 1582 uint16_t imm16 = instr->MovwField(); | 1582 uint16_t imm16 = instr->MovwField(); |
| 1583 Register rd = instr->RdField(); | 1583 Register rd = instr->RdField(); |
| 1584 if (instr->Bit(22) == 0) { | 1584 if (instr->Bit(22) == 0) { |
| 1585 // Format(instr, "movw'cond 'rd, #'imm4_12"); | 1585 // Format(instr, "movw'cond 'rd, #'imm4_12"); |
| 1586 set_register(rd, imm16); | 1586 set_register(rd, imm16); |
| 1587 } else { | 1587 } else { |
| 1588 // Format(instr, "movt'cond 'rd, #'imm4_12"); | 1588 // Format(instr, "movt'cond 'rd, #'imm4_12"); |
| 1589 set_register(rd, (get_register(rd) & 0xffff) | (imm16 << 16)); | 1589 set_register(rd, (get_register(rd) & 0xffff) | (imm16 << 16)); |
| 1590 } | 1590 } |
| 1591 break; | 1591 break; |
| 1592 } | 1592 } |
| 1593 case 18: { | 1593 case 18: { |
| 1594 if ((instr->Bits(16, 4) == 0) && (instr->Bits(0, 8) == 0)) { | 1594 if ((instr->Bits(16, 4) == 0) && (instr->Bits(0, 8) == 0)) { |
| 1595 // Format(instr, "nop'cond"); | 1595 // Format(instr, "nop'cond"); |
| 1596 } else { | 1596 } else { |
| 1597 UNIMPLEMENTED(); | 1597 UnimplementedInstruction(instr); |
| 1598 } | 1598 } |
| 1599 break; | 1599 break; |
| 1600 } | 1600 } |
| 1601 default: { | 1601 default: { |
| 1602 UNIMPLEMENTED(); | 1602 UnimplementedInstruction(instr); |
| 1603 break; | 1603 break; |
| 1604 } | 1604 } |
| 1605 } | 1605 } |
| 1606 } else { | 1606 } else { |
| 1607 // extra load/store instructions | 1607 // extra load/store instructions |
| 1608 Register rd = instr->RdField(); | 1608 Register rd = instr->RdField(); |
| 1609 Register rn = instr->RnField(); | 1609 Register rn = instr->RnField(); |
| 1610 int32_t rn_val = get_register(rn); | 1610 int32_t rn_val = get_register(rn); |
| 1611 uword addr = 0; | 1611 uword addr = 0; |
| 1612 bool write_back = false; | 1612 bool write_back = false; |
| (...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1720 int32_t val_high = get_register(rd1); | 1720 int32_t val_high = get_register(rd1); |
| 1721 WriteW(addr, val_low, instr); | 1721 WriteW(addr, val_low, instr); |
| 1722 WriteW(addr + 4, val_high, instr); | 1722 WriteW(addr + 4, val_high, instr); |
| 1723 } else { | 1723 } else { |
| 1724 int32_t val_low = ReadW(addr, instr); | 1724 int32_t val_low = ReadW(addr, instr); |
| 1725 int32_t val_high = ReadW(addr + 4, instr); | 1725 int32_t val_high = ReadW(addr + 4, instr); |
| 1726 set_register(rd, val_low); | 1726 set_register(rd, val_low); |
| 1727 set_register(rd1, val_high); | 1727 set_register(rd1, val_high); |
| 1728 } | 1728 } |
| 1729 } else { | 1729 } else { |
| 1730 UNIMPLEMENTED(); | 1730 UnimplementedInstruction(instr); |
| 1731 } | 1731 } |
| 1732 } | 1732 } |
| 1733 } | 1733 } |
| 1734 } else { | 1734 } else { |
| 1735 Register rd = instr->RdField(); | 1735 Register rd = instr->RdField(); |
| 1736 Register rn = instr->RnField(); | 1736 Register rn = instr->RnField(); |
| 1737 int32_t rn_val = get_register(rn); | 1737 int32_t rn_val = get_register(rn); |
| 1738 int32_t shifter_operand = 0; | 1738 int32_t shifter_operand = 0; |
| 1739 bool shifter_carry_out = 0; | 1739 bool shifter_carry_out = 0; |
| 1740 if (instr->TypeField() == 0) { | 1740 if (instr->TypeField() == 0) { |
| (...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1849 } | 1849 } |
| 1850 | 1850 |
| 1851 case TST: { | 1851 case TST: { |
| 1852 if (instr->HasS()) { | 1852 if (instr->HasS()) { |
| 1853 // Format(instr, "tst'cond 'rn, 'shift_rm"); | 1853 // Format(instr, "tst'cond 'rn, 'shift_rm"); |
| 1854 // Format(instr, "tst'cond 'rn, 'imm"); | 1854 // Format(instr, "tst'cond 'rn, 'imm"); |
| 1855 alu_out = rn_val & shifter_operand; | 1855 alu_out = rn_val & shifter_operand; |
| 1856 SetNZFlags(alu_out); | 1856 SetNZFlags(alu_out); |
| 1857 SetCFlag(shifter_carry_out); | 1857 SetCFlag(shifter_carry_out); |
| 1858 } else { | 1858 } else { |
| 1859 UNIMPLEMENTED(); | 1859 UnimplementedInstruction(instr); |
| 1860 } | 1860 } |
| 1861 break; | 1861 break; |
| 1862 } | 1862 } |
| 1863 | 1863 |
| 1864 case TEQ: { | 1864 case TEQ: { |
| 1865 if (instr->HasS()) { | 1865 if (instr->HasS()) { |
| 1866 // Format(instr, "teq'cond 'rn, 'shift_rm"); | 1866 // Format(instr, "teq'cond 'rn, 'shift_rm"); |
| 1867 // Format(instr, "teq'cond 'rn, 'imm"); | 1867 // Format(instr, "teq'cond 'rn, 'imm"); |
| 1868 alu_out = rn_val ^ shifter_operand; | 1868 alu_out = rn_val ^ shifter_operand; |
| 1869 SetNZFlags(alu_out); | 1869 SetNZFlags(alu_out); |
| 1870 SetCFlag(shifter_carry_out); | 1870 SetCFlag(shifter_carry_out); |
| 1871 } else { | 1871 } else { |
| 1872 UNIMPLEMENTED(); | 1872 UnimplementedInstruction(instr); |
| 1873 } | 1873 } |
| 1874 break; | 1874 break; |
| 1875 } | 1875 } |
| 1876 | 1876 |
| 1877 case CMP: { | 1877 case CMP: { |
| 1878 if (instr->HasS()) { | 1878 if (instr->HasS()) { |
| 1879 // Format(instr, "cmp'cond 'rn, 'shift_rm"); | 1879 // Format(instr, "cmp'cond 'rn, 'shift_rm"); |
| 1880 // Format(instr, "cmp'cond 'rn, 'imm"); | 1880 // Format(instr, "cmp'cond 'rn, 'imm"); |
| 1881 alu_out = rn_val - shifter_operand; | 1881 alu_out = rn_val - shifter_operand; |
| 1882 SetNZFlags(alu_out); | 1882 SetNZFlags(alu_out); |
| 1883 SetCFlag(!BorrowFrom(rn_val, shifter_operand)); | 1883 SetCFlag(!BorrowFrom(rn_val, shifter_operand)); |
| 1884 SetVFlag(OverflowFrom(alu_out, rn_val, shifter_operand, false)); | 1884 SetVFlag(OverflowFrom(alu_out, rn_val, shifter_operand, false)); |
| 1885 } else { | 1885 } else { |
| 1886 UNIMPLEMENTED(); | 1886 UnimplementedInstruction(instr); |
| 1887 } | 1887 } |
| 1888 break; | 1888 break; |
| 1889 } | 1889 } |
| 1890 | 1890 |
| 1891 case CMN: { | 1891 case CMN: { |
| 1892 if (instr->HasS()) { | 1892 if (instr->HasS()) { |
| 1893 // Format(instr, "cmn'cond 'rn, 'shift_rm"); | 1893 // Format(instr, "cmn'cond 'rn, 'shift_rm"); |
| 1894 // Format(instr, "cmn'cond 'rn, 'imm"); | 1894 // Format(instr, "cmn'cond 'rn, 'imm"); |
| 1895 alu_out = rn_val + shifter_operand; | 1895 alu_out = rn_val + shifter_operand; |
| 1896 SetNZFlags(alu_out); | 1896 SetNZFlags(alu_out); |
| 1897 SetCFlag(CarryFrom(rn_val, shifter_operand)); | 1897 SetCFlag(CarryFrom(rn_val, shifter_operand)); |
| 1898 SetVFlag(OverflowFrom(alu_out, rn_val, shifter_operand, true)); | 1898 SetVFlag(OverflowFrom(alu_out, rn_val, shifter_operand, true)); |
| 1899 } else { | 1899 } else { |
| 1900 UNIMPLEMENTED(); | 1900 UnimplementedInstruction(instr); |
| 1901 } | 1901 } |
| 1902 break; | 1902 break; |
| 1903 } | 1903 } |
| 1904 | 1904 |
| 1905 case ORR: { | 1905 case ORR: { |
| 1906 // Format(instr, "orr'cond's 'rd, 'rn, 'shift_rm"); | 1906 // Format(instr, "orr'cond's 'rd, 'rn, 'shift_rm"); |
| 1907 // Format(instr, "orr'cond's 'rd, 'rn, 'imm"); | 1907 // Format(instr, "orr'cond's 'rd, 'rn, 'imm"); |
| 1908 alu_out = rn_val | shifter_operand; | 1908 alu_out = rn_val | shifter_operand; |
| 1909 set_register(rd, alu_out); | 1909 set_register(rd, alu_out); |
| 1910 if (instr->HasS()) { | 1910 if (instr->HasS()) { |
| (...skipping 363 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2274 // Format(instr, "vstmd'cond'pu 'rn'w, 'dlist"); | 2274 // Format(instr, "vstmd'cond'pu 'rn'w, 'dlist"); |
| 2275 int64_t dd_val = bit_cast<int64_t, double>(get_dregister(dd)); | 2275 int64_t dd_val = bit_cast<int64_t, double>(get_dregister(dd)); |
| 2276 WriteW(addr, Utils::Low32Bits(dd_val), instr); | 2276 WriteW(addr, Utils::Low32Bits(dd_val), instr); |
| 2277 WriteW(addr + 4, Utils::High32Bits(dd_val), instr); | 2277 WriteW(addr + 4, Utils::High32Bits(dd_val), instr); |
| 2278 } | 2278 } |
| 2279 addr += 8; | 2279 addr += 8; |
| 2280 } | 2280 } |
| 2281 } | 2281 } |
| 2282 } | 2282 } |
| 2283 } else { | 2283 } else { |
| 2284 UNIMPLEMENTED(); | 2284 UnimplementedInstruction(instr); |
| 2285 } | 2285 } |
| 2286 } | 2286 } |
| 2287 | 2287 |
| 2288 | 2288 |
| 2289 void Simulator::DecodeType7(Instr* instr) { | 2289 void Simulator::DecodeType7(Instr* instr) { |
| 2290 if (instr->Bit(24) == 1) { | 2290 if (instr->Bit(24) == 1) { |
| 2291 // Format(instr, "svc #'svc"); | 2291 // Format(instr, "svc #'svc"); |
| 2292 SupervisorCall(instr); | 2292 SupervisorCall(instr); |
| 2293 } else if (instr->IsVFPDataProcessingOrSingleTransfer()) { | 2293 } else if (instr->IsVFPDataProcessingOrSingleTransfer()) { |
| 2294 if (instr->Bit(4) == 0) { | 2294 if (instr->Bit(4) == 0) { |
| (...skipping 15 matching lines...) Expand all Loading... |
| 2310 sd = kNoSRegister; | 2310 sd = kNoSRegister; |
| 2311 sn = kNoSRegister; | 2311 sn = kNoSRegister; |
| 2312 sm = kNoSRegister; | 2312 sm = kNoSRegister; |
| 2313 dd = instr->DdField(); | 2313 dd = instr->DdField(); |
| 2314 dn = instr->DnField(); | 2314 dn = instr->DnField(); |
| 2315 dm = instr->DmField(); | 2315 dm = instr->DmField(); |
| 2316 } | 2316 } |
| 2317 switch (instr->Bits(20, 4) & 0xb) { | 2317 switch (instr->Bits(20, 4) & 0xb) { |
| 2318 case 1: // vnmla, vnmls, vnmul | 2318 case 1: // vnmla, vnmls, vnmul |
| 2319 default: { | 2319 default: { |
| 2320 UNIMPLEMENTED(); | 2320 UnimplementedInstruction(instr); |
| 2321 break; | 2321 break; |
| 2322 } | 2322 } |
| 2323 case 0: { // vmla, vmls floating-point | 2323 case 0: { // vmla, vmls floating-point |
| 2324 if (instr->Bit(8) == 0) { | 2324 if (instr->Bit(8) == 0) { |
| 2325 float addend = get_sregister(sn) * get_sregister(sm); | 2325 float addend = get_sregister(sn) * get_sregister(sm); |
| 2326 float sd_val = get_sregister(sd); | 2326 float sd_val = get_sregister(sd); |
| 2327 if (instr->Bit(6) == 0) { | 2327 if (instr->Bit(6) == 0) { |
| 2328 // Format(instr, "vmlas'cond 'sd, 'sn, 'sm"); | 2328 // Format(instr, "vmlas'cond 'sd, 'sn, 'sm"); |
| 2329 } else { | 2329 } else { |
| 2330 // Format(instr, "vmlss'cond 'sd, 'sn, 'sm"); | 2330 // Format(instr, "vmlss'cond 'sd, 'sn, 'sm"); |
| (...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2412 if (instr->Bit(8) == 0) { | 2412 if (instr->Bit(8) == 0) { |
| 2413 // Format(instr, "vabss'cond 'sd, 'sm"); | 2413 // Format(instr, "vabss'cond 'sd, 'sm"); |
| 2414 set_sregister(sd, fabsf(get_sregister(sm))); | 2414 set_sregister(sd, fabsf(get_sregister(sm))); |
| 2415 } else { | 2415 } else { |
| 2416 // Format(instr, "vabsd'cond 'dd, 'dm"); | 2416 // Format(instr, "vabsd'cond 'dd, 'dm"); |
| 2417 set_dregister(dd, fabs(get_dregister(dm))); | 2417 set_dregister(dd, fabs(get_dregister(dm))); |
| 2418 } | 2418 } |
| 2419 break; | 2419 break; |
| 2420 } | 2420 } |
| 2421 default: { | 2421 default: { |
| 2422 UNIMPLEMENTED(); | 2422 UnimplementedInstruction(instr); |
| 2423 break; | 2423 break; |
| 2424 } | 2424 } |
| 2425 } | 2425 } |
| 2426 break; | 2426 break; |
| 2427 } | 2427 } |
| 2428 case 1: { // vneg, vsqrt | 2428 case 1: { // vneg, vsqrt |
| 2429 switch (instr->Bits(6, 2)) { | 2429 switch (instr->Bits(6, 2)) { |
| 2430 case 1: { // vneg | 2430 case 1: { // vneg |
| 2431 if (instr->Bit(8) == 0) { | 2431 if (instr->Bit(8) == 0) { |
| 2432 // Format(instr, "vnegs'cond 'sd, 'sm"); | 2432 // Format(instr, "vnegs'cond 'sd, 'sm"); |
| 2433 set_sregister(sd, -get_sregister(sm)); | 2433 set_sregister(sd, -get_sregister(sm)); |
| 2434 } else { | 2434 } else { |
| 2435 // Format(instr, "vnegd'cond 'dd, 'dm"); | 2435 // Format(instr, "vnegd'cond 'dd, 'dm"); |
| 2436 set_dregister(dd, -get_dregister(dm)); | 2436 set_dregister(dd, -get_dregister(dm)); |
| 2437 } | 2437 } |
| 2438 break; | 2438 break; |
| 2439 } | 2439 } |
| 2440 case 3: { // vsqrt | 2440 case 3: { // vsqrt |
| 2441 if (instr->Bit(8) == 0) { | 2441 if (instr->Bit(8) == 0) { |
| 2442 // Format(instr, "vsqrts'cond 'sd, 'sm"); | 2442 // Format(instr, "vsqrts'cond 'sd, 'sm"); |
| 2443 set_sregister(sd, sqrtf(get_sregister(sm))); | 2443 set_sregister(sd, sqrtf(get_sregister(sm))); |
| 2444 } else { | 2444 } else { |
| 2445 // Format(instr, "vsqrtd'cond 'dd, 'dm"); | 2445 // Format(instr, "vsqrtd'cond 'dd, 'dm"); |
| 2446 set_dregister(dd, sqrt(get_dregister(dm))); | 2446 set_dregister(dd, sqrt(get_dregister(dm))); |
| 2447 } | 2447 } |
| 2448 break; | 2448 break; |
| 2449 } | 2449 } |
| 2450 default: { | 2450 default: { |
| 2451 UNIMPLEMENTED(); | 2451 UnimplementedInstruction(instr); |
| 2452 break; | 2452 break; |
| 2453 } | 2453 } |
| 2454 } | 2454 } |
| 2455 break; | 2455 break; |
| 2456 } | 2456 } |
| 2457 case 4: // vcmp, vcmpe | 2457 case 4: // vcmp, vcmpe |
| 2458 case 5: { // vcmp #0.0, vcmpe #0.0 | 2458 case 5: { // vcmp #0.0, vcmpe #0.0 |
| 2459 if (instr->Bit(7) == 1) { // vcmpe | 2459 if (instr->Bit(7) == 1) { // vcmpe |
| 2460 UNIMPLEMENTED(); | 2460 UnimplementedInstruction(instr); |
| 2461 } else { | 2461 } else { |
| 2462 fp_n_flag_ = false; | 2462 fp_n_flag_ = false; |
| 2463 fp_z_flag_ = false; | 2463 fp_z_flag_ = false; |
| 2464 fp_c_flag_ = false; | 2464 fp_c_flag_ = false; |
| 2465 fp_v_flag_ = false; | 2465 fp_v_flag_ = false; |
| 2466 if (instr->Bit(8) == 0) { // vcmps | 2466 if (instr->Bit(8) == 0) { // vcmps |
| 2467 float sd_val = get_sregister(sd); | 2467 float sd_val = get_sregister(sd); |
| 2468 float sm_val; | 2468 float sm_val; |
| 2469 if (instr->Bit(16) == 0) { | 2469 if (instr->Bit(16) == 0) { |
| 2470 // Format(instr, "vcmps'cond 'sd, 'sm"); | 2470 // Format(instr, "vcmps'cond 'sd, 'sm"); |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2553 set_dregister(dd, dd_val); | 2553 set_dregister(dd, dd_val); |
| 2554 } | 2554 } |
| 2555 break; | 2555 break; |
| 2556 } | 2556 } |
| 2557 case 12: | 2557 case 12: |
| 2558 case 13: { // vcvt, vcvtr between floating-point and integer | 2558 case 13: { // vcvt, vcvtr between floating-point and integer |
| 2559 // We do not need to record exceptions in the FPSCR cumulative | 2559 // We do not need to record exceptions in the FPSCR cumulative |
| 2560 // flags, because we do not use them. | 2560 // flags, because we do not use them. |
| 2561 if (instr->Bit(7) == 0) { | 2561 if (instr->Bit(7) == 0) { |
| 2562 // We only support round-to-zero mode | 2562 // We only support round-to-zero mode |
| 2563 UNIMPLEMENTED(); | 2563 UnimplementedInstruction(instr); |
| 2564 break; | 2564 break; |
| 2565 } | 2565 } |
| 2566 int32_t id_val = 0; | 2566 int32_t id_val = 0; |
| 2567 uint32_t ud_val = 0; | 2567 uint32_t ud_val = 0; |
| 2568 if (instr->Bit(8) == 0) { | 2568 if (instr->Bit(8) == 0) { |
| 2569 float sm_val = get_sregister(sm); | 2569 float sm_val = get_sregister(sm); |
| 2570 if (instr->Bit(16) == 0) { | 2570 if (instr->Bit(16) == 0) { |
| 2571 // Format(instr, "vcvtus'cond 'sd, 'sm"); | 2571 // Format(instr, "vcvtus'cond 'sd, 'sm"); |
| 2572 if (sm_val >= INT_MAX) { | 2572 if (sm_val >= INT_MAX) { |
| 2573 ud_val = INT_MAX; | 2573 ud_val = INT_MAX; |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2617 break; | 2617 break; |
| 2618 } | 2618 } |
| 2619 case 2: // vcvtb, vcvtt | 2619 case 2: // vcvtb, vcvtt |
| 2620 case 3: // vcvtb, vcvtt | 2620 case 3: // vcvtb, vcvtt |
| 2621 case 9: // undefined | 2621 case 9: // undefined |
| 2622 case 10: // vcvt between floating-point and fixed-point | 2622 case 10: // vcvt between floating-point and fixed-point |
| 2623 case 11: // vcvt between floating-point and fixed-point | 2623 case 11: // vcvt between floating-point and fixed-point |
| 2624 case 14: // vcvt between floating-point and fixed-point | 2624 case 14: // vcvt between floating-point and fixed-point |
| 2625 case 15: // vcvt between floating-point and fixed-point | 2625 case 15: // vcvt between floating-point and fixed-point |
| 2626 default: { | 2626 default: { |
| 2627 UNIMPLEMENTED(); | 2627 UnimplementedInstruction(instr); |
| 2628 break; | 2628 break; |
| 2629 } | 2629 } |
| 2630 } | 2630 } |
| 2631 } | 2631 } |
| 2632 break; | 2632 break; |
| 2633 } | 2633 } |
| 2634 } else { | 2634 } else { |
| 2635 // 8, 16, or 32-bit Transfer between ARM Core and VFP | 2635 // 8, 16, or 32-bit Transfer between ARM Core and VFP |
| 2636 if ((instr->Bits(21, 3) == 0) && (instr->Bit(8) == 0)) { | 2636 if ((instr->Bits(21, 3) == 0) && (instr->Bit(8) == 0)) { |
| 2637 Register rd = instr->RdField(); | 2637 Register rd = instr->RdField(); |
| 2638 SRegister sn = instr->SnField(); | 2638 SRegister sn = instr->SnField(); |
| 2639 if (instr->Bit(20) == 0) { | 2639 if (instr->Bit(20) == 0) { |
| 2640 // Format(instr, "vmovs'cond 'sn, 'rd"); | 2640 // Format(instr, "vmovs'cond 'sn, 'rd"); |
| 2641 set_sregister(sn, bit_cast<float, int32_t>(get_register(rd))); | 2641 set_sregister(sn, bit_cast<float, int32_t>(get_register(rd))); |
| 2642 } else { | 2642 } else { |
| 2643 // Format(instr, "vmovr'cond 'rd, 'sn"); | 2643 // Format(instr, "vmovr'cond 'rd, 'sn"); |
| 2644 set_register(rd, bit_cast<int32_t, float>(get_sregister(sn))); | 2644 set_register(rd, bit_cast<int32_t, float>(get_sregister(sn))); |
| 2645 } | 2645 } |
| 2646 } else if ((instr->Bits(20, 4) == 0xf) && (instr->Bit(8) == 0) && | 2646 } else if ((instr->Bits(20, 4) == 0xf) && (instr->Bit(8) == 0) && |
| 2647 (instr->Bits(12, 4) == 0xf)) { | 2647 (instr->Bits(12, 4) == 0xf)) { |
| 2648 // Format(instr, "vmstat'cond"); | 2648 // Format(instr, "vmstat'cond"); |
| 2649 n_flag_ = fp_n_flag_; | 2649 n_flag_ = fp_n_flag_; |
| 2650 z_flag_ = fp_z_flag_; | 2650 z_flag_ = fp_z_flag_; |
| 2651 c_flag_ = fp_c_flag_; | 2651 c_flag_ = fp_c_flag_; |
| 2652 v_flag_ = fp_v_flag_; | 2652 v_flag_ = fp_v_flag_; |
| 2653 } else { | 2653 } else { |
| 2654 UNIMPLEMENTED(); | 2654 UnimplementedInstruction(instr); |
| 2655 } | 2655 } |
| 2656 } | 2656 } |
| 2657 } else if (instr->IsMrcIdIsar0()) { | 2657 } else if (instr->IsMrcIdIsar0()) { |
| 2658 // mrc of ID_ISAR0. | 2658 // mrc of ID_ISAR0. |
| 2659 Register rd = instr->RdField(); | 2659 Register rd = instr->RdField(); |
| 2660 if (CPUFeatures::integer_division_supported()) { | 2660 if (CPUFeatures::integer_division_supported()) { |
| 2661 set_register(rd, 0x02100010); // sim has sdiv, udiv, bkpt and clz. | 2661 set_register(rd, 0x02100010); // sim has sdiv, udiv, bkpt and clz. |
| 2662 } else { | 2662 } else { |
| 2663 set_register(rd, 0x00100010); // simulator has only bkpt and clz. | 2663 set_register(rd, 0x00100010); // simulator has only bkpt and clz. |
| 2664 } | 2664 } |
| 2665 } else { | 2665 } else { |
| 2666 UNIMPLEMENTED(); | 2666 UnimplementedInstruction(instr); |
| 2667 } | 2667 } |
| 2668 } | 2668 } |
| 2669 | 2669 |
| 2670 | 2670 |
| 2671 // Executes the current instruction. | 2671 // Executes the current instruction. |
| 2672 void Simulator::InstructionDecode(Instr* instr) { | 2672 void Simulator::InstructionDecode(Instr* instr) { |
| 2673 pc_modified_ = false; | 2673 pc_modified_ = false; |
| 2674 if (FLAG_trace_sim) { | 2674 if (FLAG_trace_sim) { |
| 2675 const uword start = reinterpret_cast<uword>(instr); | 2675 const uword start = reinterpret_cast<uword>(instr); |
| 2676 const uword end = start + Instr::kInstrSize; | 2676 const uword end = start + Instr::kInstrSize; |
| 2677 Disassembler::Disassemble(start, end); | 2677 Disassembler::Disassemble(start, end); |
| 2678 } | 2678 } |
| 2679 if (instr->ConditionField() == kSpecialCondition) { | 2679 if (instr->ConditionField() == kSpecialCondition) { |
| 2680 if (instr->InstructionBits() == static_cast<int32_t>(0xf57ff01f)) { | 2680 if (instr->InstructionBits() == static_cast<int32_t>(0xf57ff01f)) { |
| 2681 // Format(instr, "clrex"); | 2681 // Format(instr, "clrex"); |
| 2682 ClearExclusive(); | 2682 ClearExclusive(); |
| 2683 } else { | 2683 } else { |
| 2684 UNIMPLEMENTED(); | 2684 UnimplementedInstruction(instr); |
| 2685 } | 2685 } |
| 2686 } else if (ConditionallyExecute(instr)) { | 2686 } else if (ConditionallyExecute(instr)) { |
| 2687 switch (instr->TypeField()) { | 2687 switch (instr->TypeField()) { |
| 2688 case 0: | 2688 case 0: |
| 2689 case 1: { | 2689 case 1: { |
| 2690 DecodeType01(instr); | 2690 DecodeType01(instr); |
| 2691 break; | 2691 break; |
| 2692 } | 2692 } |
| 2693 case 2: { | 2693 case 2: { |
| 2694 DecodeType2(instr); | 2694 DecodeType2(instr); |
| (...skipping 13 matching lines...) Expand all Loading... |
| 2708 } | 2708 } |
| 2709 case 6: { | 2709 case 6: { |
| 2710 DecodeType6(instr); | 2710 DecodeType6(instr); |
| 2711 break; | 2711 break; |
| 2712 } | 2712 } |
| 2713 case 7: { | 2713 case 7: { |
| 2714 DecodeType7(instr); | 2714 DecodeType7(instr); |
| 2715 break; | 2715 break; |
| 2716 } | 2716 } |
| 2717 default: { | 2717 default: { |
| 2718 UNIMPLEMENTED(); | 2718 // Type field is three bits. |
| 2719 UNREACHABLE(); |
| 2719 break; | 2720 break; |
| 2720 } | 2721 } |
| 2721 } | 2722 } |
| 2722 } | 2723 } |
| 2723 if (!pc_modified_) { | 2724 if (!pc_modified_) { |
| 2724 set_register(PC, reinterpret_cast<int32_t>(instr) + Instr::kInstrSize); | 2725 set_register(PC, reinterpret_cast<int32_t>(instr) + Instr::kInstrSize); |
| 2725 } | 2726 } |
| 2726 } | 2727 } |
| 2727 | 2728 |
| 2728 | 2729 |
| (...skipping 20 matching lines...) Expand all Loading... |
| 2749 } | 2750 } |
| 2750 } else { | 2751 } else { |
| 2751 // FLAG_stop_sim_at is at the non-default value. Stop in the debugger when | 2752 // FLAG_stop_sim_at is at the non-default value. Stop in the debugger when |
| 2752 // we reach the particular instruction count. | 2753 // we reach the particular instruction count. |
| 2753 while (program_counter != kEndSimulatingPC) { | 2754 while (program_counter != kEndSimulatingPC) { |
| 2754 Instr* instr = reinterpret_cast<Instr*>(program_counter); | 2755 Instr* instr = reinterpret_cast<Instr*>(program_counter); |
| 2755 icount_++; | 2756 icount_++; |
| 2756 counter_instructions.Increment(); | 2757 counter_instructions.Increment(); |
| 2757 if (icount_ == FLAG_stop_sim_at) { | 2758 if (icount_ == FLAG_stop_sim_at) { |
| 2758 SimulatorDebugger dbg(this); | 2759 SimulatorDebugger dbg(this); |
| 2759 dbg.Debug(); | 2760 dbg.Stop(instr, "Instruction count reached"); |
| 2760 } else if (IsIllegalAddress(program_counter)) { | 2761 } else if (IsIllegalAddress(program_counter)) { |
| 2761 HandleIllegalAccess(program_counter, instr); | 2762 HandleIllegalAccess(program_counter, instr); |
| 2762 } else { | 2763 } else { |
| 2763 InstructionDecode(instr); | 2764 InstructionDecode(instr); |
| 2764 } | 2765 } |
| 2765 program_counter = get_pc(); | 2766 program_counter = get_pc(); |
| 2766 } | 2767 } |
| 2767 } | 2768 } |
| 2768 } | 2769 } |
| 2769 | 2770 |
| (...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2870 // isolate->ChangeStateToGeneratedCode(); | 2871 // isolate->ChangeStateToGeneratedCode(); |
| 2871 set_register(kExceptionObjectReg, bit_cast<int32_t>(object.raw())); | 2872 set_register(kExceptionObjectReg, bit_cast<int32_t>(object.raw())); |
| 2872 buf->Longjmp(); | 2873 buf->Longjmp(); |
| 2873 } | 2874 } |
| 2874 | 2875 |
| 2875 } // namespace dart | 2876 } // namespace dart |
| 2876 | 2877 |
| 2877 #endif // !defined(HOST_ARCH_ARM) | 2878 #endif // !defined(HOST_ARCH_ARM) |
| 2878 | 2879 |
| 2879 #endif // defined TARGET_ARCH_ARM | 2880 #endif // defined TARGET_ARCH_ARM |
| OLD | NEW |