Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(171)

Side by Side Diff: runtime/vm/simulator_arm.cc

Issue 12903006: Drops into Simulator Debugger only in a session that is already interactive. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 7 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « runtime/vm/simulator_arm.h ('k') | runtime/vm/simulator_mips.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « runtime/vm/simulator_arm.h ('k') | runtime/vm/simulator_mips.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698