Chromium Code Reviews| 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 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 86 }; | 86 }; |
| 87 | 87 |
| 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 // Enter interactive debugging, and attach to the simulator. | |
| 97 void Attach(Instr* instr, const char *message); | |
| 98 | |
| 99 // Enter interactive debugging if debugging is already attached to | |
| 100 // the simulator, and otherwise return immediately. | |
| 96 void Stop(Instr* instr, const char* message); | 101 void Stop(Instr* instr, const char* message); |
| 97 void Debug(); | 102 void Debug(); |
| 103 | |
| 98 char* ReadLine(const char* prompt); | 104 char* ReadLine(const char* prompt); |
| 99 | 105 |
| 100 private: | 106 private: |
| 101 static const int32_t kSimulatorBreakpointInstr = // svc #kBreakpointSvcCode | 107 static const int32_t kSimulatorBreakpointInstr = // svc #kBreakpointSvcCode |
| 102 ((AL << kConditionShift) | (0xf << 24) | kBreakpointSvcCode); | 108 ((AL << kConditionShift) | (0xf << 24) | kBreakpointSvcCode); |
| 103 static const int32_t kNopInstr = // nop | 109 static const int32_t kNopInstr = // nop |
| 104 ((AL << kConditionShift) | (0x32 << 20) | (0xf << 12)); | 110 ((AL << kConditionShift) | (0x32 << 20) | (0xf << 12)); |
| 105 | 111 |
| 106 Simulator* sim_; | 112 Simulator* sim_; |
| 107 | 113 |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 122 | 128 |
| 123 SimulatorDebugger::SimulatorDebugger(Simulator* sim) { | 129 SimulatorDebugger::SimulatorDebugger(Simulator* sim) { |
| 124 sim_ = sim; | 130 sim_ = sim; |
| 125 } | 131 } |
| 126 | 132 |
| 127 | 133 |
| 128 SimulatorDebugger::~SimulatorDebugger() { | 134 SimulatorDebugger::~SimulatorDebugger() { |
| 129 } | 135 } |
| 130 | 136 |
| 131 | 137 |
| 138 void SimulatorDebugger::Attach(Instr* instr, const char* message) { | |
| 139 sim_->set_debugger_attached(true); | |
| 140 Stop(instr, message); | |
| 141 } | |
| 142 | |
| 143 | |
| 132 void SimulatorDebugger::Stop(Instr* instr, const char* message) { | 144 void SimulatorDebugger::Stop(Instr* instr, const char* message) { |
| 133 OS::Print("Simulator hit %s\n", message); | 145 OS::Print("Simulator hit %s\n", message); |
| 134 Debug(); | 146 Debug(); |
| 135 } | 147 } |
| 136 | 148 |
| 137 | 149 |
| 138 static Register LookupCpuRegisterByName(const char* name) { | 150 static Register LookupCpuRegisterByName(const char* name) { |
| 139 static const char* kNames[] = { | 151 static const char* kNames[] = { |
| 140 "r0", "r1", "r2", "r3", | 152 "r0", "r1", "r2", "r3", |
| 141 "r4", "r5", "r6", "r7", | 153 "r4", "r5", "r6", "r7", |
| (...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 286 void SimulatorDebugger::RedoBreakpoints() { | 298 void SimulatorDebugger::RedoBreakpoints() { |
| 287 if (sim_->break_pc_ != NULL) { | 299 if (sim_->break_pc_ != NULL) { |
| 288 sim_->break_pc_->SetInstructionBits(kSimulatorBreakpointInstr); | 300 sim_->break_pc_->SetInstructionBits(kSimulatorBreakpointInstr); |
| 289 } | 301 } |
| 290 } | 302 } |
| 291 | 303 |
| 292 | 304 |
| 293 void SimulatorDebugger::Debug() { | 305 void SimulatorDebugger::Debug() { |
| 294 intptr_t last_pc = -1; | 306 intptr_t last_pc = -1; |
| 295 bool done = false; | 307 bool done = false; |
| 296 bool decoded = true; | |
| 297 | 308 |
| 298 #define COMMAND_SIZE 63 | 309 #define COMMAND_SIZE 63 |
| 299 #define ARG_SIZE 255 | 310 #define ARG_SIZE 255 |
| 300 | 311 |
| 301 #define STR(a) #a | 312 #define STR(a) #a |
| 302 #define XSTR(a) STR(a) | 313 #define XSTR(a) STR(a) |
| 303 | 314 |
| 304 char cmd[COMMAND_SIZE + 1]; | 315 char cmd[COMMAND_SIZE + 1]; |
| 305 char arg1[ARG_SIZE + 1]; | 316 char arg1[ARG_SIZE + 1]; |
| 306 char arg2[ARG_SIZE + 1]; | 317 char arg2[ARG_SIZE + 1]; |
| 307 | 318 |
| 319 // If the simulator does not already have debugging attached, then return--- | |
| 320 // we aren't in interactive mode. | |
| 321 if (!sim_->debugger_attached()) { | |
| 322 return; | |
| 323 } | |
| 324 | |
| 308 // make sure to have a proper terminating character if reaching the limit | 325 // make sure to have a proper terminating character if reaching the limit |
| 309 cmd[COMMAND_SIZE] = 0; | 326 cmd[COMMAND_SIZE] = 0; |
| 310 arg1[ARG_SIZE] = 0; | 327 arg1[ARG_SIZE] = 0; |
| 311 arg2[ARG_SIZE] = 0; | 328 arg2[ARG_SIZE] = 0; |
| 312 | 329 |
| 313 // Undo all set breakpoints while running in the debugger shell. This will | 330 // Undo all set breakpoints while running in the debugger shell. This will |
| 314 // make them invisible to all commands. | 331 // make them invisible to all commands. |
| 315 UndoBreakpoints(); | 332 UndoBreakpoints(); |
| 316 | 333 |
| 317 while (!done) { | 334 while (!done) { |
| 318 if (last_pc != sim_->get_pc()) { | 335 if (last_pc != sim_->get_pc()) { |
| 319 last_pc = sim_->get_pc(); | 336 last_pc = sim_->get_pc(); |
| 320 decoded = Disassembler::Disassemble(last_pc, last_pc + Instr::kInstrSize); | 337 Disassembler::Disassemble(last_pc, last_pc + Instr::kInstrSize); |
| 321 } | 338 } |
| 322 char* line = ReadLine("sim> "); | 339 char* line = ReadLine("sim> "); |
| 323 if (line == NULL) { | 340 if (line == NULL) { |
| 324 break; | 341 break; |
| 325 } else { | 342 } else { |
| 326 // Use sscanf to parse the individual parts of the command line. At the | 343 // Use sscanf to parse the individual parts of the command line. At the |
| 327 // moment no command expects more than two parameters. | 344 // moment no command expects more than two parameters. |
| 328 int args = SScanF(line, | 345 int args = SScanF(line, |
| 329 "%" XSTR(COMMAND_SIZE) "s " | 346 "%" XSTR(COMMAND_SIZE) "s " |
| 330 "%" XSTR(ARG_SIZE) "s " | 347 "%" XSTR(ARG_SIZE) "s " |
| (...skipping 15 matching lines...) Expand all Loading... | |
| 346 "pf/printfloat <sreg or *addr> -- print float value\n" | 363 "pf/printfloat <sreg or *addr> -- print float value\n" |
| 347 "pd/printdouble <dreg or *addr> -- print double value\n" | 364 "pd/printdouble <dreg or *addr> -- print double value\n" |
| 348 "po/printobject <*reg or *addr> -- print object\n" | 365 "po/printobject <*reg or *addr> -- print object\n" |
| 349 "si/stepi -- single step an instruction\n" | 366 "si/stepi -- single step an instruction\n" |
| 350 "unstop -- if current pc is a stop instr make it a nop\n" | 367 "unstop -- if current pc is a stop instr make it a nop\n" |
| 351 "q/quit -- Quit the debugger and exit the program\n"); | 368 "q/quit -- Quit the debugger and exit the program\n"); |
| 352 } else if ((strcmp(cmd, "quit") == 0) || (strcmp(cmd, "q") == 0)) { | 369 } else if ((strcmp(cmd, "quit") == 0) || (strcmp(cmd, "q") == 0)) { |
| 353 OS::Print("Quitting\n"); | 370 OS::Print("Quitting\n"); |
| 354 OS::Exit(0); | 371 OS::Exit(0); |
| 355 } else if ((strcmp(cmd, "si") == 0) || (strcmp(cmd, "stepi") == 0)) { | 372 } else if ((strcmp(cmd, "si") == 0) || (strcmp(cmd, "stepi") == 0)) { |
| 356 if (decoded) { | 373 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)) { | 374 } else if ((strcmp(cmd, "c") == 0) || (strcmp(cmd, "cont") == 0)) { |
| 362 if (decoded) { | 375 // Execute the one instruction we broke at with breakpoints disabled. |
| 363 // Execute the one instruction we broke at with breakpoints disabled. | 376 sim_->InstructionDecode(reinterpret_cast<Instr*>(sim_->get_pc())); |
| 364 sim_->InstructionDecode(reinterpret_cast<Instr*>(sim_->get_pc())); | 377 // Leave the debugger shell. |
| 365 // Leave the debugger shell. | 378 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)) { | 379 } else if ((strcmp(cmd, "p") == 0) || (strcmp(cmd, "print") == 0)) { |
| 371 if (args == 2) { | 380 if (args == 2) { |
| 372 uint32_t value; | 381 uint32_t value; |
| 373 if (GetValue(arg1, &value)) { | 382 if (GetValue(arg1, &value)) { |
| 374 OS::Print("%s: %u 0x%x\n", arg1, value, value); | 383 OS::Print("%s: %u 0x%x\n", arg1, value, value); |
| 375 } else { | 384 } else { |
| 376 OS::Print("%s unrecognized\n", arg1); | 385 OS::Print("%s unrecognized\n", arg1); |
| 377 } | 386 } |
| 378 } else { | 387 } else { |
| 379 OS::Print("print <reg or value or *addr>\n"); | 388 OS::Print("print <reg or value or *addr>\n"); |
| (...skipping 281 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 661 // Since VFP registers are overlapping, single-precision registers should | 670 // Since VFP registers are overlapping, single-precision registers should |
| 662 // already be initialized. | 671 // already be initialized. |
| 663 ASSERT(2*kNumberOfDRegisters >= kNumberOfSRegisters); | 672 ASSERT(2*kNumberOfDRegisters >= kNumberOfSRegisters); |
| 664 for (int i = 0; i < kNumberOfSRegisters; i++) { | 673 for (int i = 0; i < kNumberOfSRegisters; i++) { |
| 665 ASSERT(sregisters_[i] == 0.0); | 674 ASSERT(sregisters_[i] == 0.0); |
| 666 } | 675 } |
| 667 fp_n_flag_ = false; | 676 fp_n_flag_ = false; |
| 668 fp_z_flag_ = false; | 677 fp_z_flag_ = false; |
| 669 fp_c_flag_ = false; | 678 fp_c_flag_ = false; |
| 670 fp_v_flag_ = false; | 679 fp_v_flag_ = false; |
| 680 | |
| 681 debugger_attached_ = false; | |
| 671 } | 682 } |
| 672 | 683 |
| 673 | 684 |
| 674 Simulator::~Simulator() { | 685 Simulator::~Simulator() { |
| 675 delete[] stack_; | 686 delete[] stack_; |
| 676 Isolate* isolate = Isolate::Current(); | 687 Isolate* isolate = Isolate::Current(); |
| 677 if (isolate != NULL) { | 688 if (isolate != NULL) { |
| 678 isolate->set_simulator(NULL); | 689 isolate->set_simulator(NULL); |
| 679 } | 690 } |
| 680 } | 691 } |
| (...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 838 char buffer[64]; | 849 char buffer[64]; |
| 839 snprintf(buffer, sizeof(buffer), | 850 snprintf(buffer, sizeof(buffer), |
| 840 "unaligned %s at 0x%"Px", pc=%p\n", msg, addr, instr); | 851 "unaligned %s at 0x%"Px", pc=%p\n", msg, addr, instr); |
| 841 SimulatorDebugger dbg(this); | 852 SimulatorDebugger dbg(this); |
| 842 dbg.Stop(instr, buffer); | 853 dbg.Stop(instr, buffer); |
| 843 // The debugger will return control in non-interactive mode. | 854 // The debugger will return control in non-interactive mode. |
| 844 FATAL("Cannot continue execution after unaligned access."); | 855 FATAL("Cannot continue execution after unaligned access."); |
| 845 } | 856 } |
| 846 | 857 |
| 847 | 858 |
| 859 void Simulator::UnimplementedInstruction(Instr* instr) { | |
| 860 char buffer[64]; | |
| 861 snprintf(buffer, sizeof(buffer), "Unimplemented instruction: pc=%p\n", instr); | |
| 862 SimulatorDebugger dbg(this); | |
| 863 dbg.Stop(instr, buffer); | |
| 864 FATAL("Cannot continue execution after unimplemented instruction."); | |
| 865 } | |
| 866 | |
| 867 | |
| 848 int Simulator::ReadW(uword addr, Instr* instr) { | 868 int Simulator::ReadW(uword addr, Instr* instr) { |
| 849 static StatsCounter counter_read_w("Simulated word reads"); | 869 static StatsCounter counter_read_w("Simulated word reads"); |
| 850 counter_read_w.Increment(); | 870 counter_read_w.Increment(); |
| 851 if ((addr & 3) == 0) { | 871 if ((addr & 3) == 0) { |
| 852 intptr_t* ptr = reinterpret_cast<intptr_t*>(addr); | 872 intptr_t* ptr = reinterpret_cast<intptr_t*>(addr); |
| 853 return *ptr; | 873 return *ptr; |
| 854 } | 874 } |
| 855 UnalignedAccess("read", addr, instr); | 875 UnalignedAccess("read", addr, instr); |
| 856 return 0; | 876 return 0; |
| 857 } | 877 } |
| (...skipping 221 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1079 | 1099 |
| 1080 // Addressing Mode 1 - Data-processing operands: | 1100 // Addressing Mode 1 - Data-processing operands: |
| 1081 // Get the value based on the shifter_operand with register. | 1101 // Get the value based on the shifter_operand with register. |
| 1082 int32_t Simulator::GetShiftRm(Instr* instr, bool* carry_out) { | 1102 int32_t Simulator::GetShiftRm(Instr* instr, bool* carry_out) { |
| 1083 Shift shift = instr->ShiftField(); | 1103 Shift shift = instr->ShiftField(); |
| 1084 int shift_amount = instr->ShiftAmountField(); | 1104 int shift_amount = instr->ShiftAmountField(); |
| 1085 int32_t result = get_register(instr->RmField()); | 1105 int32_t result = get_register(instr->RmField()); |
| 1086 if (instr->Bit(4) == 0) { | 1106 if (instr->Bit(4) == 0) { |
| 1087 // by immediate | 1107 // by immediate |
| 1088 if ((shift == ROR) && (shift_amount == 0)) { | 1108 if ((shift == ROR) && (shift_amount == 0)) { |
| 1089 UNIMPLEMENTED(); | 1109 UnimplementedInstruction(instr); |
| 1090 return result; | |
| 1091 } else if (((shift == LSR) || (shift == ASR)) && (shift_amount == 0)) { | 1110 } else if (((shift == LSR) || (shift == ASR)) && (shift_amount == 0)) { |
| 1092 shift_amount = 32; | 1111 shift_amount = 32; |
| 1093 } | 1112 } |
| 1094 switch (shift) { | 1113 switch (shift) { |
| 1095 case ASR: { | 1114 case ASR: { |
| 1096 if (shift_amount == 0) { | 1115 if (shift_amount == 0) { |
| 1097 if (result < 0) { | 1116 if (result < 0) { |
| 1098 result = 0xffffffff; | 1117 result = 0xffffffff; |
| 1099 *carry_out = true; | 1118 *carry_out = true; |
| 1100 } else { | 1119 } else { |
| (...skipping 27 matching lines...) Expand all Loading... | |
| 1128 uint32_t uresult = static_cast<uint32_t>(result); | 1147 uint32_t uresult = static_cast<uint32_t>(result); |
| 1129 uresult >>= (shift_amount - 1); | 1148 uresult >>= (shift_amount - 1); |
| 1130 *carry_out = (uresult & 1) == 1; | 1149 *carry_out = (uresult & 1) == 1; |
| 1131 uresult >>= 1; | 1150 uresult >>= 1; |
| 1132 result = static_cast<int32_t>(uresult); | 1151 result = static_cast<int32_t>(uresult); |
| 1133 } | 1152 } |
| 1134 break; | 1153 break; |
| 1135 } | 1154 } |
| 1136 | 1155 |
| 1137 case ROR: { | 1156 case ROR: { |
| 1138 UNIMPLEMENTED(); | 1157 UnimplementedInstruction(instr); |
| 1139 break; | 1158 break; |
| 1140 } | 1159 } |
| 1141 | 1160 |
| 1142 default: { | 1161 default: { |
| 1143 UNREACHABLE(); | 1162 UNREACHABLE(); |
| 1144 break; | 1163 break; |
| 1145 } | 1164 } |
| 1146 } | 1165 } |
| 1147 } else { | 1166 } else { |
| 1148 // by register | 1167 // by register |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1200 *carry_out = (result < 0); | 1219 *carry_out = (result < 0); |
| 1201 result = 0; | 1220 result = 0; |
| 1202 } else { | 1221 } else { |
| 1203 *carry_out = false; | 1222 *carry_out = false; |
| 1204 result = 0; | 1223 result = 0; |
| 1205 } | 1224 } |
| 1206 break; | 1225 break; |
| 1207 } | 1226 } |
| 1208 | 1227 |
| 1209 case ROR: { | 1228 case ROR: { |
| 1210 UNIMPLEMENTED(); | 1229 UnimplementedInstruction(instr); |
| 1211 break; | 1230 break; |
| 1212 } | 1231 } |
| 1213 | 1232 |
| 1214 default: { | 1233 default: { |
| 1215 UNREACHABLE(); | 1234 UNREACHABLE(); |
| 1216 break; | 1235 break; |
| 1217 } | 1236 } |
| 1218 } | 1237 } |
| 1219 } | 1238 } |
| 1220 return result; | 1239 return result; |
| (...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1384 #endif // VFPv3_D32 | 1403 #endif // VFPv3_D32 |
| 1385 | 1404 |
| 1386 // Return. | 1405 // Return. |
| 1387 set_pc(saved_lr); | 1406 set_pc(saved_lr); |
| 1388 } | 1407 } |
| 1389 | 1408 |
| 1390 break; | 1409 break; |
| 1391 } | 1410 } |
| 1392 case kBreakpointSvcCode: { | 1411 case kBreakpointSvcCode: { |
| 1393 SimulatorDebugger dbg(this); | 1412 SimulatorDebugger dbg(this); |
| 1394 dbg.Stop(instr, "breakpoint"); | 1413 set_debugger_attached(true); |
| 1414 dbg.Attach(instr, "breakpoint"); | |
| 1395 break; | 1415 break; |
| 1396 } | 1416 } |
| 1397 case kStopMessageSvcCode: { | 1417 case kStopMessageSvcCode: { |
| 1398 SimulatorDebugger dbg(this); | 1418 SimulatorDebugger dbg(this); |
| 1399 const char* message = *reinterpret_cast<const char**>( | 1419 const char* message = *reinterpret_cast<const char**>( |
| 1400 reinterpret_cast<intptr_t>(instr) - Instr::kInstrSize); | 1420 reinterpret_cast<intptr_t>(instr) - Instr::kInstrSize); |
| 1401 set_pc(get_pc() + Instr::kInstrSize); | 1421 set_pc(get_pc() + Instr::kInstrSize); |
| 1402 dbg.Stop(instr, message); | 1422 dbg.Attach(instr, message); |
|
Ivan Posva
2013/03/21 18:23:36
What will happen if a test with nobody watching on
| |
| 1403 break; | 1423 break; |
| 1404 } | 1424 } |
| 1405 case kWordSpillMarkerSvcCode: { | 1425 case kWordSpillMarkerSvcCode: { |
| 1406 static StatsCounter counter_spill_w("Simulated word spills"); | 1426 static StatsCounter counter_spill_w("Simulated word spills"); |
| 1407 counter_spill_w.Increment(); | 1427 counter_spill_w.Increment(); |
| 1408 break; | 1428 break; |
| 1409 } | 1429 } |
| 1410 case kDWordSpillMarkerSvcCode: { | 1430 case kDWordSpillMarkerSvcCode: { |
| 1411 static StatsCounter counter_spill_d("Simulated double word spills"); | 1431 static StatsCounter counter_spill_d("Simulated double word spills"); |
| 1412 counter_spill_d.Increment(); | 1432 counter_spill_d.Increment(); |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1464 set_pc(rm_val); | 1484 set_pc(rm_val); |
| 1465 break; | 1485 break; |
| 1466 } | 1486 } |
| 1467 case 7: { | 1487 case 7: { |
| 1468 if (instr->Bits(21, 2) == 0x1) { | 1488 if (instr->Bits(21, 2) == 0x1) { |
| 1469 // Format(instr, "bkpt'cond #'imm12_4"); | 1489 // Format(instr, "bkpt'cond #'imm12_4"); |
| 1470 SimulatorDebugger dbg(this); | 1490 SimulatorDebugger dbg(this); |
| 1471 set_pc(get_pc() + Instr::kInstrSize); | 1491 set_pc(get_pc() + Instr::kInstrSize); |
| 1472 char buffer[32]; | 1492 char buffer[32]; |
| 1473 snprintf(buffer, sizeof(buffer), "bkpt #0x%x", instr->BkptField()); | 1493 snprintf(buffer, sizeof(buffer), "bkpt #0x%x", instr->BkptField()); |
| 1474 dbg.Stop(instr, buffer); | 1494 dbg.Attach(instr, buffer); |
| 1475 } else { | 1495 } else { |
| 1476 // Format(instr, "smc'cond"); | 1496 // Format(instr, "smc'cond"); |
| 1477 UNIMPLEMENTED(); | 1497 UnimplementedInstruction(instr); |
| 1478 } | 1498 } |
| 1479 break; | 1499 break; |
| 1480 } | 1500 } |
| 1481 default: { | 1501 default: { |
| 1482 UNIMPLEMENTED(); | 1502 UnimplementedInstruction(instr); |
| 1483 break; | 1503 break; |
| 1484 } | 1504 } |
| 1485 } | 1505 } |
| 1486 } else if (instr->IsMultiplyOrSyncPrimitive()) { | 1506 } else if (instr->IsMultiplyOrSyncPrimitive()) { |
| 1487 if (instr->Bit(24) == 0) { | 1507 if (instr->Bit(24) == 0) { |
| 1488 // multiply instructions. | 1508 // multiply instructions. |
| 1489 Register rn = instr->RnField(); | 1509 Register rn = instr->RnField(); |
| 1490 Register rd = instr->RdField(); | 1510 Register rd = instr->RdField(); |
| 1491 Register rs = instr->RsField(); | 1511 Register rs = instr->RsField(); |
| 1492 Register rm = instr->RmField(); | 1512 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. | 1552 // Collapse bits 0..31 into bit 32 so that 32-bit Z check works. |
| 1533 hi_res |= 1; | 1553 hi_res |= 1; |
| 1534 } | 1554 } |
| 1535 ASSERT((result == 0) == (hi_res == 0)); // Z bit | 1555 ASSERT((result == 0) == (hi_res == 0)); // Z bit |
| 1536 ASSERT(((result & (1LL << 63)) != 0) == (hi_res < 0)); // N bit | 1556 ASSERT(((result & (1LL << 63)) != 0) == (hi_res < 0)); // N bit |
| 1537 SetNZFlags(hi_res); | 1557 SetNZFlags(hi_res); |
| 1538 } | 1558 } |
| 1539 break; | 1559 break; |
| 1540 } | 1560 } |
| 1541 default: { | 1561 default: { |
| 1542 UNIMPLEMENTED(); | 1562 UnimplementedInstruction(instr); |
| 1543 break; | 1563 break; |
| 1544 } | 1564 } |
| 1545 } | 1565 } |
| 1546 } else { | 1566 } else { |
| 1547 // synchronization primitives | 1567 // synchronization primitives |
| 1548 Register rd = instr->RdField(); | 1568 Register rd = instr->RdField(); |
| 1549 Register rn = instr->RnField(); | 1569 Register rn = instr->RnField(); |
| 1550 uword addr = get_register(rn); | 1570 uword addr = get_register(rn); |
| 1551 switch (instr->Bits(20, 4)) { | 1571 switch (instr->Bits(20, 4)) { |
| 1552 case 8: { | 1572 case 8: { |
| 1553 // Format(instr, "strex'cond 'rd, 'rm, ['rn]"); | 1573 // Format(instr, "strex'cond 'rd, 'rm, ['rn]"); |
| 1554 if (IsIllegalAddress(addr)) { | 1574 if (IsIllegalAddress(addr)) { |
| 1555 HandleIllegalAccess(addr, instr); | 1575 HandleIllegalAccess(addr, instr); |
| 1556 } else { | 1576 } else { |
| 1557 Register rm = instr->RmField(); | 1577 Register rm = instr->RmField(); |
| 1558 set_register(rd, WriteExclusiveW(addr, get_register(rm), instr)); | 1578 set_register(rd, WriteExclusiveW(addr, get_register(rm), instr)); |
| 1559 } | 1579 } |
| 1560 break; | 1580 break; |
| 1561 } | 1581 } |
| 1562 case 9: { | 1582 case 9: { |
| 1563 // Format(instr, "ldrex'cond 'rd, ['rn]"); | 1583 // Format(instr, "ldrex'cond 'rd, ['rn]"); |
| 1564 if (IsIllegalAddress(addr)) { | 1584 if (IsIllegalAddress(addr)) { |
| 1565 HandleIllegalAccess(addr, instr); | 1585 HandleIllegalAccess(addr, instr); |
| 1566 } else { | 1586 } else { |
| 1567 set_register(rd, ReadExclusiveW(addr, instr)); | 1587 set_register(rd, ReadExclusiveW(addr, instr)); |
| 1568 } | 1588 } |
| 1569 break; | 1589 break; |
| 1570 } | 1590 } |
| 1571 default: { | 1591 default: { |
| 1572 UNIMPLEMENTED(); | 1592 UnimplementedInstruction(instr); |
| 1573 break; | 1593 break; |
| 1574 } | 1594 } |
| 1575 } | 1595 } |
| 1576 } | 1596 } |
| 1577 } else if (instr->Bit(25) == 1) { | 1597 } else if (instr->Bit(25) == 1) { |
| 1578 // 16-bit immediate loads, msr (immediate), and hints | 1598 // 16-bit immediate loads, msr (immediate), and hints |
| 1579 switch (instr->Bits(20, 5)) { | 1599 switch (instr->Bits(20, 5)) { |
| 1580 case 16: | 1600 case 16: |
| 1581 case 20: { | 1601 case 20: { |
| 1582 uint16_t imm16 = instr->MovwField(); | 1602 uint16_t imm16 = instr->MovwField(); |
| 1583 Register rd = instr->RdField(); | 1603 Register rd = instr->RdField(); |
| 1584 if (instr->Bit(22) == 0) { | 1604 if (instr->Bit(22) == 0) { |
| 1585 // Format(instr, "movw'cond 'rd, #'imm4_12"); | 1605 // Format(instr, "movw'cond 'rd, #'imm4_12"); |
| 1586 set_register(rd, imm16); | 1606 set_register(rd, imm16); |
| 1587 } else { | 1607 } else { |
| 1588 // Format(instr, "movt'cond 'rd, #'imm4_12"); | 1608 // Format(instr, "movt'cond 'rd, #'imm4_12"); |
| 1589 set_register(rd, (get_register(rd) & 0xffff) | (imm16 << 16)); | 1609 set_register(rd, (get_register(rd) & 0xffff) | (imm16 << 16)); |
| 1590 } | 1610 } |
| 1591 break; | 1611 break; |
| 1592 } | 1612 } |
| 1593 case 18: { | 1613 case 18: { |
| 1594 if ((instr->Bits(16, 4) == 0) && (instr->Bits(0, 8) == 0)) { | 1614 if ((instr->Bits(16, 4) == 0) && (instr->Bits(0, 8) == 0)) { |
| 1595 // Format(instr, "nop'cond"); | 1615 // Format(instr, "nop'cond"); |
| 1596 } else { | 1616 } else { |
| 1597 UNIMPLEMENTED(); | 1617 UnimplementedInstruction(instr); |
| 1598 } | 1618 } |
| 1599 break; | 1619 break; |
| 1600 } | 1620 } |
| 1601 default: { | 1621 default: { |
| 1602 UNIMPLEMENTED(); | 1622 UnimplementedInstruction(instr); |
| 1603 break; | 1623 break; |
| 1604 } | 1624 } |
| 1605 } | 1625 } |
| 1606 } else { | 1626 } else { |
| 1607 // extra load/store instructions | 1627 // extra load/store instructions |
| 1608 Register rd = instr->RdField(); | 1628 Register rd = instr->RdField(); |
| 1609 Register rn = instr->RnField(); | 1629 Register rn = instr->RnField(); |
| 1610 int32_t rn_val = get_register(rn); | 1630 int32_t rn_val = get_register(rn); |
| 1611 uword addr = 0; | 1631 uword addr = 0; |
| 1612 bool write_back = false; | 1632 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); | 1740 int32_t val_high = get_register(rd1); |
| 1721 WriteW(addr, val_low, instr); | 1741 WriteW(addr, val_low, instr); |
| 1722 WriteW(addr + 4, val_high, instr); | 1742 WriteW(addr + 4, val_high, instr); |
| 1723 } else { | 1743 } else { |
| 1724 int32_t val_low = ReadW(addr, instr); | 1744 int32_t val_low = ReadW(addr, instr); |
| 1725 int32_t val_high = ReadW(addr + 4, instr); | 1745 int32_t val_high = ReadW(addr + 4, instr); |
| 1726 set_register(rd, val_low); | 1746 set_register(rd, val_low); |
| 1727 set_register(rd1, val_high); | 1747 set_register(rd1, val_high); |
| 1728 } | 1748 } |
| 1729 } else { | 1749 } else { |
| 1730 UNIMPLEMENTED(); | 1750 UnimplementedInstruction(instr); |
| 1731 } | 1751 } |
| 1732 } | 1752 } |
| 1733 } | 1753 } |
| 1734 } else { | 1754 } else { |
| 1735 Register rd = instr->RdField(); | 1755 Register rd = instr->RdField(); |
| 1736 Register rn = instr->RnField(); | 1756 Register rn = instr->RnField(); |
| 1737 int32_t rn_val = get_register(rn); | 1757 int32_t rn_val = get_register(rn); |
| 1738 int32_t shifter_operand = 0; | 1758 int32_t shifter_operand = 0; |
| 1739 bool shifter_carry_out = 0; | 1759 bool shifter_carry_out = 0; |
| 1740 if (instr->TypeField() == 0) { | 1760 if (instr->TypeField() == 0) { |
| (...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1849 } | 1869 } |
| 1850 | 1870 |
| 1851 case TST: { | 1871 case TST: { |
| 1852 if (instr->HasS()) { | 1872 if (instr->HasS()) { |
| 1853 // Format(instr, "tst'cond 'rn, 'shift_rm"); | 1873 // Format(instr, "tst'cond 'rn, 'shift_rm"); |
| 1854 // Format(instr, "tst'cond 'rn, 'imm"); | 1874 // Format(instr, "tst'cond 'rn, 'imm"); |
| 1855 alu_out = rn_val & shifter_operand; | 1875 alu_out = rn_val & shifter_operand; |
| 1856 SetNZFlags(alu_out); | 1876 SetNZFlags(alu_out); |
| 1857 SetCFlag(shifter_carry_out); | 1877 SetCFlag(shifter_carry_out); |
| 1858 } else { | 1878 } else { |
| 1859 UNIMPLEMENTED(); | 1879 UnimplementedInstruction(instr); |
| 1860 } | 1880 } |
| 1861 break; | 1881 break; |
| 1862 } | 1882 } |
| 1863 | 1883 |
| 1864 case TEQ: { | 1884 case TEQ: { |
| 1865 if (instr->HasS()) { | 1885 if (instr->HasS()) { |
| 1866 // Format(instr, "teq'cond 'rn, 'shift_rm"); | 1886 // Format(instr, "teq'cond 'rn, 'shift_rm"); |
| 1867 // Format(instr, "teq'cond 'rn, 'imm"); | 1887 // Format(instr, "teq'cond 'rn, 'imm"); |
| 1868 alu_out = rn_val ^ shifter_operand; | 1888 alu_out = rn_val ^ shifter_operand; |
| 1869 SetNZFlags(alu_out); | 1889 SetNZFlags(alu_out); |
| 1870 SetCFlag(shifter_carry_out); | 1890 SetCFlag(shifter_carry_out); |
| 1871 } else { | 1891 } else { |
| 1872 UNIMPLEMENTED(); | 1892 UnimplementedInstruction(instr); |
| 1873 } | 1893 } |
| 1874 break; | 1894 break; |
| 1875 } | 1895 } |
| 1876 | 1896 |
| 1877 case CMP: { | 1897 case CMP: { |
| 1878 if (instr->HasS()) { | 1898 if (instr->HasS()) { |
| 1879 // Format(instr, "cmp'cond 'rn, 'shift_rm"); | 1899 // Format(instr, "cmp'cond 'rn, 'shift_rm"); |
| 1880 // Format(instr, "cmp'cond 'rn, 'imm"); | 1900 // Format(instr, "cmp'cond 'rn, 'imm"); |
| 1881 alu_out = rn_val - shifter_operand; | 1901 alu_out = rn_val - shifter_operand; |
| 1882 SetNZFlags(alu_out); | 1902 SetNZFlags(alu_out); |
| 1883 SetCFlag(!BorrowFrom(rn_val, shifter_operand)); | 1903 SetCFlag(!BorrowFrom(rn_val, shifter_operand)); |
| 1884 SetVFlag(OverflowFrom(alu_out, rn_val, shifter_operand, false)); | 1904 SetVFlag(OverflowFrom(alu_out, rn_val, shifter_operand, false)); |
| 1885 } else { | 1905 } else { |
| 1886 UNIMPLEMENTED(); | 1906 UnimplementedInstruction(instr); |
| 1887 } | 1907 } |
| 1888 break; | 1908 break; |
| 1889 } | 1909 } |
| 1890 | 1910 |
| 1891 case CMN: { | 1911 case CMN: { |
| 1892 if (instr->HasS()) { | 1912 if (instr->HasS()) { |
| 1893 // Format(instr, "cmn'cond 'rn, 'shift_rm"); | 1913 // Format(instr, "cmn'cond 'rn, 'shift_rm"); |
| 1894 // Format(instr, "cmn'cond 'rn, 'imm"); | 1914 // Format(instr, "cmn'cond 'rn, 'imm"); |
| 1895 alu_out = rn_val + shifter_operand; | 1915 alu_out = rn_val + shifter_operand; |
| 1896 SetNZFlags(alu_out); | 1916 SetNZFlags(alu_out); |
| 1897 SetCFlag(CarryFrom(rn_val, shifter_operand)); | 1917 SetCFlag(CarryFrom(rn_val, shifter_operand)); |
| 1898 SetVFlag(OverflowFrom(alu_out, rn_val, shifter_operand, true)); | 1918 SetVFlag(OverflowFrom(alu_out, rn_val, shifter_operand, true)); |
| 1899 } else { | 1919 } else { |
| 1900 UNIMPLEMENTED(); | 1920 UnimplementedInstruction(instr); |
| 1901 } | 1921 } |
| 1902 break; | 1922 break; |
| 1903 } | 1923 } |
| 1904 | 1924 |
| 1905 case ORR: { | 1925 case ORR: { |
| 1906 // Format(instr, "orr'cond's 'rd, 'rn, 'shift_rm"); | 1926 // Format(instr, "orr'cond's 'rd, 'rn, 'shift_rm"); |
| 1907 // Format(instr, "orr'cond's 'rd, 'rn, 'imm"); | 1927 // Format(instr, "orr'cond's 'rd, 'rn, 'imm"); |
| 1908 alu_out = rn_val | shifter_operand; | 1928 alu_out = rn_val | shifter_operand; |
| 1909 set_register(rd, alu_out); | 1929 set_register(rd, alu_out); |
| 1910 if (instr->HasS()) { | 1930 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"); | 2294 // Format(instr, "vstmd'cond'pu 'rn'w, 'dlist"); |
| 2275 int64_t dd_val = bit_cast<int64_t, double>(get_dregister(dd)); | 2295 int64_t dd_val = bit_cast<int64_t, double>(get_dregister(dd)); |
| 2276 WriteW(addr, Utils::Low32Bits(dd_val), instr); | 2296 WriteW(addr, Utils::Low32Bits(dd_val), instr); |
| 2277 WriteW(addr + 4, Utils::High32Bits(dd_val), instr); | 2297 WriteW(addr + 4, Utils::High32Bits(dd_val), instr); |
| 2278 } | 2298 } |
| 2279 addr += 8; | 2299 addr += 8; |
| 2280 } | 2300 } |
| 2281 } | 2301 } |
| 2282 } | 2302 } |
| 2283 } else { | 2303 } else { |
| 2284 UNIMPLEMENTED(); | 2304 UnimplementedInstruction(instr); |
| 2285 } | 2305 } |
| 2286 } | 2306 } |
| 2287 | 2307 |
| 2288 | 2308 |
| 2289 void Simulator::DecodeType7(Instr* instr) { | 2309 void Simulator::DecodeType7(Instr* instr) { |
| 2290 if (instr->Bit(24) == 1) { | 2310 if (instr->Bit(24) == 1) { |
| 2291 // Format(instr, "svc #'svc"); | 2311 // Format(instr, "svc #'svc"); |
| 2292 SupervisorCall(instr); | 2312 SupervisorCall(instr); |
| 2293 } else if (instr->IsVFPDataProcessingOrSingleTransfer()) { | 2313 } else if (instr->IsVFPDataProcessingOrSingleTransfer()) { |
| 2294 if (instr->Bit(4) == 0) { | 2314 if (instr->Bit(4) == 0) { |
| (...skipping 15 matching lines...) Expand all Loading... | |
| 2310 sd = kNoSRegister; | 2330 sd = kNoSRegister; |
| 2311 sn = kNoSRegister; | 2331 sn = kNoSRegister; |
| 2312 sm = kNoSRegister; | 2332 sm = kNoSRegister; |
| 2313 dd = instr->DdField(); | 2333 dd = instr->DdField(); |
| 2314 dn = instr->DnField(); | 2334 dn = instr->DnField(); |
| 2315 dm = instr->DmField(); | 2335 dm = instr->DmField(); |
| 2316 } | 2336 } |
| 2317 switch (instr->Bits(20, 4) & 0xb) { | 2337 switch (instr->Bits(20, 4) & 0xb) { |
| 2318 case 1: // vnmla, vnmls, vnmul | 2338 case 1: // vnmla, vnmls, vnmul |
| 2319 default: { | 2339 default: { |
| 2320 UNIMPLEMENTED(); | 2340 UnimplementedInstruction(instr); |
| 2321 break; | 2341 break; |
| 2322 } | 2342 } |
| 2323 case 0: { // vmla, vmls floating-point | 2343 case 0: { // vmla, vmls floating-point |
| 2324 if (instr->Bit(8) == 0) { | 2344 if (instr->Bit(8) == 0) { |
| 2325 float addend = get_sregister(sn) * get_sregister(sm); | 2345 float addend = get_sregister(sn) * get_sregister(sm); |
| 2326 float sd_val = get_sregister(sd); | 2346 float sd_val = get_sregister(sd); |
| 2327 if (instr->Bit(6) == 0) { | 2347 if (instr->Bit(6) == 0) { |
| 2328 // Format(instr, "vmlas'cond 'sd, 'sn, 'sm"); | 2348 // Format(instr, "vmlas'cond 'sd, 'sn, 'sm"); |
| 2329 } else { | 2349 } else { |
| 2330 // Format(instr, "vmlss'cond 'sd, 'sn, 'sm"); | 2350 // 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) { | 2432 if (instr->Bit(8) == 0) { |
| 2413 // Format(instr, "vabss'cond 'sd, 'sm"); | 2433 // Format(instr, "vabss'cond 'sd, 'sm"); |
| 2414 set_sregister(sd, fabsf(get_sregister(sm))); | 2434 set_sregister(sd, fabsf(get_sregister(sm))); |
| 2415 } else { | 2435 } else { |
| 2416 // Format(instr, "vabsd'cond 'dd, 'dm"); | 2436 // Format(instr, "vabsd'cond 'dd, 'dm"); |
| 2417 set_dregister(dd, fabs(get_dregister(dm))); | 2437 set_dregister(dd, fabs(get_dregister(dm))); |
| 2418 } | 2438 } |
| 2419 break; | 2439 break; |
| 2420 } | 2440 } |
| 2421 default: { | 2441 default: { |
| 2422 UNIMPLEMENTED(); | 2442 UnimplementedInstruction(instr); |
| 2423 break; | 2443 break; |
| 2424 } | 2444 } |
| 2425 } | 2445 } |
| 2426 break; | 2446 break; |
| 2427 } | 2447 } |
| 2428 case 1: { // vneg, vsqrt | 2448 case 1: { // vneg, vsqrt |
| 2429 switch (instr->Bits(6, 2)) { | 2449 switch (instr->Bits(6, 2)) { |
| 2430 case 1: { // vneg | 2450 case 1: { // vneg |
| 2431 if (instr->Bit(8) == 0) { | 2451 if (instr->Bit(8) == 0) { |
| 2432 // Format(instr, "vnegs'cond 'sd, 'sm"); | 2452 // Format(instr, "vnegs'cond 'sd, 'sm"); |
| 2433 set_sregister(sd, -get_sregister(sm)); | 2453 set_sregister(sd, -get_sregister(sm)); |
| 2434 } else { | 2454 } else { |
| 2435 // Format(instr, "vnegd'cond 'dd, 'dm"); | 2455 // Format(instr, "vnegd'cond 'dd, 'dm"); |
| 2436 set_dregister(dd, -get_dregister(dm)); | 2456 set_dregister(dd, -get_dregister(dm)); |
| 2437 } | 2457 } |
| 2438 break; | 2458 break; |
| 2439 } | 2459 } |
| 2440 case 3: { // vsqrt | 2460 case 3: { // vsqrt |
| 2441 if (instr->Bit(8) == 0) { | 2461 if (instr->Bit(8) == 0) { |
| 2442 // Format(instr, "vsqrts'cond 'sd, 'sm"); | 2462 // Format(instr, "vsqrts'cond 'sd, 'sm"); |
| 2443 set_sregister(sd, sqrtf(get_sregister(sm))); | 2463 set_sregister(sd, sqrtf(get_sregister(sm))); |
| 2444 } else { | 2464 } else { |
| 2445 // Format(instr, "vsqrtd'cond 'dd, 'dm"); | 2465 // Format(instr, "vsqrtd'cond 'dd, 'dm"); |
| 2446 set_dregister(dd, sqrt(get_dregister(dm))); | 2466 set_dregister(dd, sqrt(get_dregister(dm))); |
| 2447 } | 2467 } |
| 2448 break; | 2468 break; |
| 2449 } | 2469 } |
| 2450 default: { | 2470 default: { |
| 2451 UNIMPLEMENTED(); | 2471 UnimplementedInstruction(instr); |
| 2452 break; | 2472 break; |
| 2453 } | 2473 } |
| 2454 } | 2474 } |
| 2455 break; | 2475 break; |
| 2456 } | 2476 } |
| 2457 case 4: // vcmp, vcmpe | 2477 case 4: // vcmp, vcmpe |
| 2458 case 5: { // vcmp #0.0, vcmpe #0.0 | 2478 case 5: { // vcmp #0.0, vcmpe #0.0 |
| 2459 if (instr->Bit(7) == 1) { // vcmpe | 2479 if (instr->Bit(7) == 1) { // vcmpe |
| 2460 UNIMPLEMENTED(); | 2480 UnimplementedInstruction(instr); |
| 2461 } else { | 2481 } else { |
| 2462 fp_n_flag_ = false; | 2482 fp_n_flag_ = false; |
| 2463 fp_z_flag_ = false; | 2483 fp_z_flag_ = false; |
| 2464 fp_c_flag_ = false; | 2484 fp_c_flag_ = false; |
| 2465 fp_v_flag_ = false; | 2485 fp_v_flag_ = false; |
| 2466 if (instr->Bit(8) == 0) { // vcmps | 2486 if (instr->Bit(8) == 0) { // vcmps |
| 2467 float sd_val = get_sregister(sd); | 2487 float sd_val = get_sregister(sd); |
| 2468 float sm_val; | 2488 float sm_val; |
| 2469 if (instr->Bit(16) == 0) { | 2489 if (instr->Bit(16) == 0) { |
| 2470 // Format(instr, "vcmps'cond 'sd, 'sm"); | 2490 // 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); | 2573 set_dregister(dd, dd_val); |
| 2554 } | 2574 } |
| 2555 break; | 2575 break; |
| 2556 } | 2576 } |
| 2557 case 12: | 2577 case 12: |
| 2558 case 13: { // vcvt, vcvtr between floating-point and integer | 2578 case 13: { // vcvt, vcvtr between floating-point and integer |
| 2559 // We do not need to record exceptions in the FPSCR cumulative | 2579 // We do not need to record exceptions in the FPSCR cumulative |
| 2560 // flags, because we do not use them. | 2580 // flags, because we do not use them. |
| 2561 if (instr->Bit(7) == 0) { | 2581 if (instr->Bit(7) == 0) { |
| 2562 // We only support round-to-zero mode | 2582 // We only support round-to-zero mode |
| 2563 UNIMPLEMENTED(); | 2583 UnimplementedInstruction(instr); |
| 2564 break; | 2584 break; |
| 2565 } | 2585 } |
| 2566 int32_t id_val = 0; | 2586 int32_t id_val = 0; |
| 2567 uint32_t ud_val = 0; | 2587 uint32_t ud_val = 0; |
| 2568 if (instr->Bit(8) == 0) { | 2588 if (instr->Bit(8) == 0) { |
| 2569 float sm_val = get_sregister(sm); | 2589 float sm_val = get_sregister(sm); |
| 2570 if (instr->Bit(16) == 0) { | 2590 if (instr->Bit(16) == 0) { |
| 2571 // Format(instr, "vcvtus'cond 'sd, 'sm"); | 2591 // Format(instr, "vcvtus'cond 'sd, 'sm"); |
| 2572 if (sm_val >= INT_MAX) { | 2592 if (sm_val >= INT_MAX) { |
| 2573 ud_val = INT_MAX; | 2593 ud_val = INT_MAX; |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2617 break; | 2637 break; |
| 2618 } | 2638 } |
| 2619 case 2: // vcvtb, vcvtt | 2639 case 2: // vcvtb, vcvtt |
| 2620 case 3: // vcvtb, vcvtt | 2640 case 3: // vcvtb, vcvtt |
| 2621 case 9: // undefined | 2641 case 9: // undefined |
| 2622 case 10: // vcvt between floating-point and fixed-point | 2642 case 10: // vcvt between floating-point and fixed-point |
| 2623 case 11: // vcvt between floating-point and fixed-point | 2643 case 11: // vcvt between floating-point and fixed-point |
| 2624 case 14: // vcvt between floating-point and fixed-point | 2644 case 14: // vcvt between floating-point and fixed-point |
| 2625 case 15: // vcvt between floating-point and fixed-point | 2645 case 15: // vcvt between floating-point and fixed-point |
| 2626 default: { | 2646 default: { |
| 2627 UNIMPLEMENTED(); | 2647 UnimplementedInstruction(instr); |
| 2628 break; | 2648 break; |
| 2629 } | 2649 } |
| 2630 } | 2650 } |
| 2631 } | 2651 } |
| 2632 break; | 2652 break; |
| 2633 } | 2653 } |
| 2634 } else { | 2654 } else { |
| 2635 // 8, 16, or 32-bit Transfer between ARM Core and VFP | 2655 // 8, 16, or 32-bit Transfer between ARM Core and VFP |
| 2636 if ((instr->Bits(21, 3) == 0) && (instr->Bit(8) == 0)) { | 2656 if ((instr->Bits(21, 3) == 0) && (instr->Bit(8) == 0)) { |
| 2637 Register rd = instr->RdField(); | 2657 Register rd = instr->RdField(); |
| 2638 SRegister sn = instr->SnField(); | 2658 SRegister sn = instr->SnField(); |
| 2639 if (instr->Bit(20) == 0) { | 2659 if (instr->Bit(20) == 0) { |
| 2640 // Format(instr, "vmovs'cond 'sn, 'rd"); | 2660 // Format(instr, "vmovs'cond 'sn, 'rd"); |
| 2641 set_sregister(sn, bit_cast<float, int32_t>(get_register(rd))); | 2661 set_sregister(sn, bit_cast<float, int32_t>(get_register(rd))); |
| 2642 } else { | 2662 } else { |
| 2643 // Format(instr, "vmovr'cond 'rd, 'sn"); | 2663 // Format(instr, "vmovr'cond 'rd, 'sn"); |
| 2644 set_register(rd, bit_cast<int32_t, float>(get_sregister(sn))); | 2664 set_register(rd, bit_cast<int32_t, float>(get_sregister(sn))); |
| 2645 } | 2665 } |
| 2646 } else if ((instr->Bits(20, 4) == 0xf) && (instr->Bit(8) == 0) && | 2666 } else if ((instr->Bits(20, 4) == 0xf) && (instr->Bit(8) == 0) && |
| 2647 (instr->Bits(12, 4) == 0xf)) { | 2667 (instr->Bits(12, 4) == 0xf)) { |
| 2648 // Format(instr, "vmstat'cond"); | 2668 // Format(instr, "vmstat'cond"); |
| 2649 n_flag_ = fp_n_flag_; | 2669 n_flag_ = fp_n_flag_; |
| 2650 z_flag_ = fp_z_flag_; | 2670 z_flag_ = fp_z_flag_; |
| 2651 c_flag_ = fp_c_flag_; | 2671 c_flag_ = fp_c_flag_; |
| 2652 v_flag_ = fp_v_flag_; | 2672 v_flag_ = fp_v_flag_; |
| 2653 } else { | 2673 } else { |
| 2654 UNIMPLEMENTED(); | 2674 UnimplementedInstruction(instr); |
| 2655 } | 2675 } |
| 2656 } | 2676 } |
| 2657 } else if (instr->IsMrcIdIsar0()) { | 2677 } else if (instr->IsMrcIdIsar0()) { |
| 2658 // mrc of ID_ISAR0. | 2678 // mrc of ID_ISAR0. |
| 2659 Register rd = instr->RdField(); | 2679 Register rd = instr->RdField(); |
| 2660 if (CPUFeatures::integer_division_supported()) { | 2680 if (CPUFeatures::integer_division_supported()) { |
| 2661 set_register(rd, 0x02100010); // sim has sdiv, udiv, bkpt and clz. | 2681 set_register(rd, 0x02100010); // sim has sdiv, udiv, bkpt and clz. |
| 2662 } else { | 2682 } else { |
| 2663 set_register(rd, 0x00100010); // simulator has only bkpt and clz. | 2683 set_register(rd, 0x00100010); // simulator has only bkpt and clz. |
| 2664 } | 2684 } |
| 2665 } else { | 2685 } else { |
| 2666 UNIMPLEMENTED(); | 2686 UnimplementedInstruction(instr); |
| 2667 } | 2687 } |
| 2668 } | 2688 } |
| 2669 | 2689 |
| 2670 | 2690 |
| 2671 // Executes the current instruction. | 2691 // Executes the current instruction. |
| 2672 void Simulator::InstructionDecode(Instr* instr) { | 2692 void Simulator::InstructionDecode(Instr* instr) { |
| 2673 pc_modified_ = false; | 2693 pc_modified_ = false; |
| 2674 if (FLAG_trace_sim) { | 2694 if (FLAG_trace_sim) { |
| 2675 const uword start = reinterpret_cast<uword>(instr); | 2695 const uword start = reinterpret_cast<uword>(instr); |
| 2676 const uword end = start + Instr::kInstrSize; | 2696 const uword end = start + Instr::kInstrSize; |
| 2677 Disassembler::Disassemble(start, end); | 2697 Disassembler::Disassemble(start, end); |
| 2678 } | 2698 } |
| 2679 if (instr->ConditionField() == kSpecialCondition) { | 2699 if (instr->ConditionField() == kSpecialCondition) { |
| 2680 if (instr->InstructionBits() == static_cast<int32_t>(0xf57ff01f)) { | 2700 if (instr->InstructionBits() == static_cast<int32_t>(0xf57ff01f)) { |
| 2681 // Format(instr, "clrex"); | 2701 // Format(instr, "clrex"); |
| 2682 ClearExclusive(); | 2702 ClearExclusive(); |
| 2683 } else { | 2703 } else { |
| 2684 UNIMPLEMENTED(); | 2704 UnimplementedInstruction(instr); |
| 2685 } | 2705 } |
| 2686 } else if (ConditionallyExecute(instr)) { | 2706 } else if (ConditionallyExecute(instr)) { |
| 2687 switch (instr->TypeField()) { | 2707 switch (instr->TypeField()) { |
| 2688 case 0: | 2708 case 0: |
| 2689 case 1: { | 2709 case 1: { |
| 2690 DecodeType01(instr); | 2710 DecodeType01(instr); |
| 2691 break; | 2711 break; |
| 2692 } | 2712 } |
| 2693 case 2: { | 2713 case 2: { |
| 2694 DecodeType2(instr); | 2714 DecodeType2(instr); |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 2708 } | 2728 } |
| 2709 case 6: { | 2729 case 6: { |
| 2710 DecodeType6(instr); | 2730 DecodeType6(instr); |
| 2711 break; | 2731 break; |
| 2712 } | 2732 } |
| 2713 case 7: { | 2733 case 7: { |
| 2714 DecodeType7(instr); | 2734 DecodeType7(instr); |
| 2715 break; | 2735 break; |
| 2716 } | 2736 } |
| 2717 default: { | 2737 default: { |
| 2718 UNIMPLEMENTED(); | 2738 // Type field is three bits. |
| 2739 UNREACHABLE(); | |
| 2719 break; | 2740 break; |
| 2720 } | 2741 } |
| 2721 } | 2742 } |
| 2722 } | 2743 } |
| 2723 if (!pc_modified_) { | 2744 if (!pc_modified_) { |
| 2724 set_register(PC, reinterpret_cast<int32_t>(instr) + Instr::kInstrSize); | 2745 set_register(PC, reinterpret_cast<int32_t>(instr) + Instr::kInstrSize); |
| 2725 } | 2746 } |
| 2726 } | 2747 } |
| 2727 | 2748 |
| 2728 | 2749 |
| (...skipping 20 matching lines...) Expand all Loading... | |
| 2749 } | 2770 } |
| 2750 } else { | 2771 } else { |
| 2751 // FLAG_stop_sim_at is at the non-default value. Stop in the debugger when | 2772 // FLAG_stop_sim_at is at the non-default value. Stop in the debugger when |
| 2752 // we reach the particular instruction count. | 2773 // we reach the particular instruction count. |
| 2753 while (program_counter != kEndSimulatingPC) { | 2774 while (program_counter != kEndSimulatingPC) { |
| 2754 Instr* instr = reinterpret_cast<Instr*>(program_counter); | 2775 Instr* instr = reinterpret_cast<Instr*>(program_counter); |
| 2755 icount_++; | 2776 icount_++; |
| 2756 counter_instructions.Increment(); | 2777 counter_instructions.Increment(); |
| 2757 if (icount_ == FLAG_stop_sim_at) { | 2778 if (icount_ == FLAG_stop_sim_at) { |
| 2758 SimulatorDebugger dbg(this); | 2779 SimulatorDebugger dbg(this); |
| 2759 dbg.Debug(); | 2780 dbg.Attach(instr, "Instruction count reached"); |
| 2760 } else if (IsIllegalAddress(program_counter)) { | 2781 } else if (IsIllegalAddress(program_counter)) { |
| 2761 HandleIllegalAccess(program_counter, instr); | 2782 HandleIllegalAccess(program_counter, instr); |
| 2762 } else { | 2783 } else { |
| 2763 InstructionDecode(instr); | 2784 InstructionDecode(instr); |
| 2764 } | 2785 } |
| 2765 program_counter = get_pc(); | 2786 program_counter = get_pc(); |
| 2766 } | 2787 } |
| 2767 } | 2788 } |
| 2768 } | 2789 } |
| 2769 | 2790 |
| (...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2870 // isolate->ChangeStateToGeneratedCode(); | 2891 // isolate->ChangeStateToGeneratedCode(); |
| 2871 set_register(kExceptionObjectReg, bit_cast<int32_t>(object.raw())); | 2892 set_register(kExceptionObjectReg, bit_cast<int32_t>(object.raw())); |
| 2872 buf->Longjmp(); | 2893 buf->Longjmp(); |
| 2873 } | 2894 } |
| 2874 | 2895 |
| 2875 } // namespace dart | 2896 } // namespace dart |
| 2876 | 2897 |
| 2877 #endif // !defined(HOST_ARCH_ARM) | 2898 #endif // !defined(HOST_ARCH_ARM) |
| 2878 | 2899 |
| 2879 #endif // defined TARGET_ARCH_ARM | 2900 #endif // defined TARGET_ARCH_ARM |
| OLD | NEW |