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 <setjmp.h> // NOLINT | 5 #include <setjmp.h> // NOLINT |
6 #include <stdlib.h> | 6 #include <stdlib.h> |
7 | 7 |
8 #include "vm/globals.h" | 8 #include "vm/globals.h" |
9 #if defined(TARGET_ARCH_ARM) | 9 #if defined(TARGET_ARCH_ARM) |
10 | 10 |
11 // Only build the simulator if not compiling for real ARM hardware. | 11 // Only build the simulator if not compiling for real ARM hardware. |
12 #if defined(USING_SIMULATOR) | 12 #if defined(USING_SIMULATOR) |
13 | 13 |
14 #include "vm/simulator.h" | 14 #include "vm/simulator.h" |
15 | 15 |
16 #include "vm/assembler.h" | 16 #include "vm/assembler.h" |
17 #include "vm/constants_arm.h" | 17 #include "vm/constants_arm.h" |
18 #include "vm/cpu.h" | 18 #include "vm/cpu.h" |
19 #include "vm/disassembler.h" | 19 #include "vm/disassembler.h" |
20 #include "vm/lockers.h" | 20 #include "vm/lockers.h" |
21 #include "vm/native_arguments.h" | 21 #include "vm/native_arguments.h" |
22 #include "vm/stack_frame.h" | 22 #include "vm/stack_frame.h" |
23 #include "vm/os_thread.h" | 23 #include "vm/os_thread.h" |
24 | 24 |
25 namespace dart { | 25 namespace dart { |
26 | 26 |
27 DEFINE_FLAG(uint64_t, trace_sim_after, ULLONG_MAX, | 27 DEFINE_FLAG(uint64_t, |
| 28 trace_sim_after, |
| 29 ULLONG_MAX, |
28 "Trace simulator execution after instruction count reached."); | 30 "Trace simulator execution after instruction count reached."); |
29 DEFINE_FLAG(uint64_t, stop_sim_at, ULLONG_MAX, | 31 DEFINE_FLAG(uint64_t, |
| 32 stop_sim_at, |
| 33 ULLONG_MAX, |
30 "Instruction address or instruction count to stop simulator at."); | 34 "Instruction address or instruction count to stop simulator at."); |
31 | 35 |
32 | 36 |
33 // This macro provides a platform independent use of sscanf. The reason for | 37 // This macro provides a platform independent use of sscanf. The reason for |
34 // SScanF not being implemented in a platform independent way through | 38 // SScanF not being implemented in a platform independent way through |
35 // OS in the same way as SNPrint is that the Windows C Run-Time | 39 // OS in the same way as SNPrint is that the Windows C Run-Time |
36 // Library does not provide vsscanf. | 40 // Library does not provide vsscanf. |
37 #define SScanF sscanf // NOLINT | 41 #define SScanF sscanf // NOLINT |
38 | 42 |
39 | 43 |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
89 | 93 |
90 private: | 94 private: |
91 Simulator* sim_; | 95 Simulator* sim_; |
92 | 96 |
93 bool GetValue(char* desc, uint32_t* value); | 97 bool GetValue(char* desc, uint32_t* value); |
94 bool GetFValue(char* desc, float* value); | 98 bool GetFValue(char* desc, float* value); |
95 bool GetDValue(char* desc, double* value); | 99 bool GetDValue(char* desc, double* value); |
96 | 100 |
97 static TokenPosition GetApproximateTokenIndex(const Code& code, uword pc); | 101 static TokenPosition GetApproximateTokenIndex(const Code& code, uword pc); |
98 | 102 |
99 static void PrintDartFrame(uword pc, uword fp, uword sp, | 103 static void PrintDartFrame(uword pc, |
| 104 uword fp, |
| 105 uword sp, |
100 const Function& function, | 106 const Function& function, |
101 TokenPosition token_pos, | 107 TokenPosition token_pos, |
102 bool is_optimized, | 108 bool is_optimized, |
103 bool is_inlined); | 109 bool is_inlined); |
104 void PrintBacktrace(); | 110 void PrintBacktrace(); |
105 | 111 |
106 // Set or delete a breakpoint. Returns true if successful. | 112 // Set or delete a breakpoint. Returns true if successful. |
107 bool SetBreakpoint(Instr* breakpc); | 113 bool SetBreakpoint(Instr* breakpc); |
108 bool DeleteBreakpoint(Instr* breakpc); | 114 bool DeleteBreakpoint(Instr* breakpc); |
109 | 115 |
110 // Undo and redo all breakpoints. This is needed to bracket disassembly and | 116 // Undo and redo all breakpoints. This is needed to bracket disassembly and |
111 // execution to skip past breakpoints when run from the debugger. | 117 // execution to skip past breakpoints when run from the debugger. |
112 void UndoBreakpoints(); | 118 void UndoBreakpoints(); |
113 void RedoBreakpoints(); | 119 void RedoBreakpoints(); |
114 }; | 120 }; |
115 | 121 |
116 | 122 |
117 SimulatorDebugger::SimulatorDebugger(Simulator* sim) { | 123 SimulatorDebugger::SimulatorDebugger(Simulator* sim) { |
118 sim_ = sim; | 124 sim_ = sim; |
119 } | 125 } |
120 | 126 |
121 | 127 |
122 SimulatorDebugger::~SimulatorDebugger() { | 128 SimulatorDebugger::~SimulatorDebugger() {} |
123 } | |
124 | 129 |
125 | 130 |
126 void SimulatorDebugger::Stop(Instr* instr, const char* message) { | 131 void SimulatorDebugger::Stop(Instr* instr, const char* message) { |
127 OS::Print("Simulator hit %s\n", message); | 132 OS::Print("Simulator hit %s\n", message); |
128 Debug(); | 133 Debug(); |
129 } | 134 } |
130 | 135 |
131 | 136 |
132 static Register LookupCpuRegisterByName(const char* name) { | 137 static Register LookupCpuRegisterByName(const char* name) { |
133 static const char* kNames[] = { | 138 static const char* kNames[] = {"r0", "r1", "r2", "r3", "r4", "r5", |
134 "r0", "r1", "r2", "r3", | 139 "r6", "r7", "r8", "r9", "r10", "r11", |
135 "r4", "r5", "r6", "r7", | 140 "r12", "r13", "r14", "r15", "pc", "lr", |
136 "r8", "r9", "r10", "r11", | 141 "sp", "ip", "fp", "pp", "ctx"}; |
137 "r12", "r13", "r14", "r15", | 142 static const Register kRegisters[] = {R0, R1, R2, R3, R4, R5, R6, R7, |
138 "pc", "lr", "sp", "ip", | 143 R8, R9, R10, R11, R12, R13, R14, R15, |
139 "fp", "pp", "ctx" | 144 PC, LR, SP, IP, FP, PP, CTX}; |
140 }; | |
141 static const Register kRegisters[] = { | |
142 R0, R1, R2, R3, | |
143 R4, R5, R6, R7, | |
144 R8, R9, R10, R11, | |
145 R12, R13, R14, R15, | |
146 PC, LR, SP, IP, | |
147 FP, PP, CTX | |
148 }; | |
149 ASSERT(ARRAY_SIZE(kNames) == ARRAY_SIZE(kRegisters)); | 145 ASSERT(ARRAY_SIZE(kNames) == ARRAY_SIZE(kRegisters)); |
150 for (unsigned i = 0; i < ARRAY_SIZE(kNames); i++) { | 146 for (unsigned i = 0; i < ARRAY_SIZE(kNames); i++) { |
151 if (strcmp(kNames[i], name) == 0) { | 147 if (strcmp(kNames[i], name) == 0) { |
152 return kRegisters[i]; | 148 return kRegisters[i]; |
153 } | 149 } |
154 } | 150 } |
155 return kNoRegister; | 151 return kNoRegister; |
156 } | 152 } |
157 | 153 |
158 | 154 |
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
238 } | 234 } |
239 *value = *(reinterpret_cast<double*>(addr)); | 235 *value = *(reinterpret_cast<double*>(addr)); |
240 return true; | 236 return true; |
241 } | 237 } |
242 } | 238 } |
243 return false; | 239 return false; |
244 } | 240 } |
245 | 241 |
246 | 242 |
247 TokenPosition SimulatorDebugger::GetApproximateTokenIndex(const Code& code, | 243 TokenPosition SimulatorDebugger::GetApproximateTokenIndex(const Code& code, |
248 uword pc) { | 244 uword pc) { |
249 TokenPosition token_pos = TokenPosition::kNoSource; | 245 TokenPosition token_pos = TokenPosition::kNoSource; |
250 uword pc_offset = pc - code.PayloadStart(); | 246 uword pc_offset = pc - code.PayloadStart(); |
251 const PcDescriptors& descriptors = | 247 const PcDescriptors& descriptors = |
252 PcDescriptors::Handle(code.pc_descriptors()); | 248 PcDescriptors::Handle(code.pc_descriptors()); |
253 PcDescriptors::Iterator iter(descriptors, RawPcDescriptors::kAnyKind); | 249 PcDescriptors::Iterator iter(descriptors, RawPcDescriptors::kAnyKind); |
254 while (iter.MoveNext()) { | 250 while (iter.MoveNext()) { |
255 if (iter.PcOffset() == pc_offset) { | 251 if (iter.PcOffset() == pc_offset) { |
256 return iter.TokenPos(); | 252 return iter.TokenPos(); |
257 } else if (!token_pos.IsReal() && (iter.PcOffset() > pc_offset)) { | 253 } else if (!token_pos.IsReal() && (iter.PcOffset() > pc_offset)) { |
258 token_pos = iter.TokenPos(); | 254 token_pos = iter.TokenPos(); |
259 } | 255 } |
260 } | 256 } |
261 return token_pos; | 257 return token_pos; |
262 } | 258 } |
263 | 259 |
264 | 260 |
265 void SimulatorDebugger::PrintDartFrame(uword pc, uword fp, uword sp, | 261 void SimulatorDebugger::PrintDartFrame(uword pc, |
| 262 uword fp, |
| 263 uword sp, |
266 const Function& function, | 264 const Function& function, |
267 TokenPosition token_pos, | 265 TokenPosition token_pos, |
268 bool is_optimized, | 266 bool is_optimized, |
269 bool is_inlined) { | 267 bool is_inlined) { |
270 const Script& script = Script::Handle(function.script()); | 268 const Script& script = Script::Handle(function.script()); |
271 const String& func_name = String::Handle(function.QualifiedScrubbedName()); | 269 const String& func_name = String::Handle(function.QualifiedScrubbedName()); |
272 const String& url = String::Handle(script.url()); | 270 const String& url = String::Handle(script.url()); |
273 intptr_t line = -1; | 271 intptr_t line = -1; |
274 intptr_t column = -1; | 272 intptr_t column = -1; |
275 if (token_pos.IsReal()) { | 273 if (token_pos.IsReal()) { |
276 script.GetTokenLocation(token_pos, &line, &column); | 274 script.GetTokenLocation(token_pos, &line, &column); |
277 } | 275 } |
278 OS::Print("pc=0x%" Px " fp=0x%" Px " sp=0x%" Px " %s%s (%s:%" Pd | 276 OS::Print( |
279 ":%" Pd ")\n", | 277 "pc=0x%" Px " fp=0x%" Px " sp=0x%" Px " %s%s (%s:%" Pd ":%" Pd ")\n", pc, |
280 pc, fp, sp, | 278 fp, sp, is_optimized ? (is_inlined ? "inlined " : "optimized ") : "", |
281 is_optimized ? (is_inlined ? "inlined " : "optimized ") : "", | 279 func_name.ToCString(), url.ToCString(), line, column); |
282 func_name.ToCString(), | |
283 url.ToCString(), | |
284 line, column); | |
285 } | 280 } |
286 | 281 |
287 | 282 |
288 void SimulatorDebugger::PrintBacktrace() { | 283 void SimulatorDebugger::PrintBacktrace() { |
289 StackFrameIterator frames(sim_->get_register(FP), | 284 StackFrameIterator frames(sim_->get_register(FP), sim_->get_register(SP), |
290 sim_->get_register(SP), | |
291 sim_->get_pc(), | 285 sim_->get_pc(), |
292 StackFrameIterator::kDontValidateFrames); | 286 StackFrameIterator::kDontValidateFrames); |
293 StackFrame* frame = frames.NextFrame(); | 287 StackFrame* frame = frames.NextFrame(); |
294 ASSERT(frame != NULL); | 288 ASSERT(frame != NULL); |
295 Function& function = Function::Handle(); | 289 Function& function = Function::Handle(); |
296 Function& inlined_function = Function::Handle(); | 290 Function& inlined_function = Function::Handle(); |
297 Code& code = Code::Handle(); | 291 Code& code = Code::Handle(); |
298 Code& unoptimized_code = Code::Handle(); | 292 Code& unoptimized_code = Code::Handle(); |
299 while (frame != NULL) { | 293 while (frame != NULL) { |
300 if (frame->IsDartFrame()) { | 294 if (frame->IsDartFrame()) { |
301 code = frame->LookupDartCode(); | 295 code = frame->LookupDartCode(); |
302 function = code.function(); | 296 function = code.function(); |
303 if (code.is_optimized()) { | 297 if (code.is_optimized()) { |
304 // For optimized frames, extract all the inlined functions if any | 298 // For optimized frames, extract all the inlined functions if any |
305 // into the stack trace. | 299 // into the stack trace. |
306 InlinedFunctionsIterator it(code, frame->pc()); | 300 InlinedFunctionsIterator it(code, frame->pc()); |
307 while (!it.Done()) { | 301 while (!it.Done()) { |
308 // Print each inlined frame with its pc in the corresponding | 302 // Print each inlined frame with its pc in the corresponding |
309 // unoptimized frame. | 303 // unoptimized frame. |
310 inlined_function = it.function(); | 304 inlined_function = it.function(); |
311 unoptimized_code = it.code(); | 305 unoptimized_code = it.code(); |
312 uword unoptimized_pc = it.pc(); | 306 uword unoptimized_pc = it.pc(); |
313 it.Advance(); | 307 it.Advance(); |
314 if (!it.Done()) { | 308 if (!it.Done()) { |
315 PrintDartFrame(unoptimized_pc, frame->fp(), frame->sp(), | 309 PrintDartFrame( |
316 inlined_function, | 310 unoptimized_pc, frame->fp(), frame->sp(), inlined_function, |
317 GetApproximateTokenIndex(unoptimized_code, | 311 GetApproximateTokenIndex(unoptimized_code, unoptimized_pc), |
318 unoptimized_pc), | 312 true, true); |
319 true, true); | |
320 } | 313 } |
321 } | 314 } |
322 // Print the optimized inlining frame below. | 315 // Print the optimized inlining frame below. |
323 } | 316 } |
324 PrintDartFrame(frame->pc(), frame->fp(), frame->sp(), | 317 PrintDartFrame(frame->pc(), frame->fp(), frame->sp(), function, |
325 function, | |
326 GetApproximateTokenIndex(code, frame->pc()), | 318 GetApproximateTokenIndex(code, frame->pc()), |
327 code.is_optimized(), false); | 319 code.is_optimized(), false); |
328 } else { | 320 } else { |
329 OS::Print("pc=0x%" Px " fp=0x%" Px " sp=0x%" Px " %s frame\n", | 321 OS::Print("pc=0x%" Px " fp=0x%" Px " sp=0x%" Px " %s frame\n", |
330 frame->pc(), frame->fp(), frame->sp(), | 322 frame->pc(), frame->fp(), frame->sp(), |
331 frame->IsEntryFrame() ? "entry" : | 323 frame->IsEntryFrame() |
332 frame->IsExitFrame() ? "exit" : | 324 ? "entry" |
333 frame->IsStubFrame() ? "stub" : "invalid"); | 325 : frame->IsExitFrame() |
| 326 ? "exit" |
| 327 : frame->IsStubFrame() ? "stub" : "invalid"); |
334 } | 328 } |
335 frame = frames.NextFrame(); | 329 frame = frames.NextFrame(); |
336 } | 330 } |
337 } | 331 } |
338 | 332 |
339 | 333 |
340 bool SimulatorDebugger::SetBreakpoint(Instr* breakpc) { | 334 bool SimulatorDebugger::SetBreakpoint(Instr* breakpc) { |
341 // Check if a breakpoint can be set. If not return without any side-effects. | 335 // Check if a breakpoint can be set. If not return without any side-effects. |
342 if (sim_->break_pc_ != NULL) { | 336 if (sim_->break_pc_ != NULL) { |
343 return false; | 337 return false; |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
418 FATAL("ReadLine failed"); | 412 FATAL("ReadLine failed"); |
419 } else { | 413 } else { |
420 // Use sscanf to parse the individual parts of the command line. At the | 414 // Use sscanf to parse the individual parts of the command line. At the |
421 // moment no command expects more than two parameters. | 415 // moment no command expects more than two parameters. |
422 int args = SScanF(line, | 416 int args = SScanF(line, |
423 "%" XSTR(COMMAND_SIZE) "s " | 417 "%" XSTR(COMMAND_SIZE) "s " |
424 "%" XSTR(ARG_SIZE) "s " | 418 "%" XSTR(ARG_SIZE) "s " |
425 "%" XSTR(ARG_SIZE) "s", | 419 "%" XSTR(ARG_SIZE) "s", |
426 cmd, arg1, arg2); | 420 cmd, arg1, arg2); |
427 if ((strcmp(cmd, "h") == 0) || (strcmp(cmd, "help") == 0)) { | 421 if ((strcmp(cmd, "h") == 0) || (strcmp(cmd, "help") == 0)) { |
428 OS::Print("c/cont -- continue execution\n" | 422 OS::Print( |
429 "disasm -- disassemble instrs at current pc location\n" | 423 "c/cont -- continue execution\n" |
430 " other variants are:\n" | 424 "disasm -- disassemble instrs at current pc location\n" |
431 " disasm <address>\n" | 425 " other variants are:\n" |
432 " disasm <address> <number_of_instructions>\n" | 426 " disasm <address>\n" |
433 " by default 10 instrs are disassembled\n" | 427 " disasm <address> <number_of_instructions>\n" |
434 "del -- delete breakpoints\n" | 428 " by default 10 instrs are disassembled\n" |
435 "flags -- print flag values\n" | 429 "del -- delete breakpoints\n" |
436 "gdb -- transfer control to gdb\n" | 430 "flags -- print flag values\n" |
437 "h/help -- print this help string\n" | 431 "gdb -- transfer control to gdb\n" |
438 "break <address> -- set break point at specified address\n" | 432 "h/help -- print this help string\n" |
439 "p/print <reg or icount or value or *addr> -- print integer\n" | 433 "break <address> -- set break point at specified address\n" |
440 "ps/printsingle <sreg or *addr> -- print float value\n" | 434 "p/print <reg or icount or value or *addr> -- print integer\n" |
441 "pd/printdouble <dreg or *addr> -- print double value\n" | 435 "ps/printsingle <sreg or *addr> -- print float value\n" |
442 "po/printobject <*reg or *addr> -- print object\n" | 436 "pd/printdouble <dreg or *addr> -- print double value\n" |
443 "si/stepi -- single step an instruction\n" | 437 "po/printobject <*reg or *addr> -- print object\n" |
444 "trace -- toggle execution tracing mode\n" | 438 "si/stepi -- single step an instruction\n" |
445 "bt -- print backtrace\n" | 439 "trace -- toggle execution tracing mode\n" |
446 "unstop -- if current pc is a stop instr make it a nop\n" | 440 "bt -- print backtrace\n" |
447 "q/quit -- Quit the debugger and exit the program\n"); | 441 "unstop -- if current pc is a stop instr make it a nop\n" |
| 442 "q/quit -- Quit the debugger and exit the program\n"); |
448 } else if ((strcmp(cmd, "quit") == 0) || (strcmp(cmd, "q") == 0)) { | 443 } else if ((strcmp(cmd, "quit") == 0) || (strcmp(cmd, "q") == 0)) { |
449 OS::Print("Quitting\n"); | 444 OS::Print("Quitting\n"); |
450 OS::Exit(0); | 445 OS::Exit(0); |
451 } else if ((strcmp(cmd, "si") == 0) || (strcmp(cmd, "stepi") == 0)) { | 446 } else if ((strcmp(cmd, "si") == 0) || (strcmp(cmd, "stepi") == 0)) { |
452 sim_->InstructionDecode(reinterpret_cast<Instr*>(sim_->get_pc())); | 447 sim_->InstructionDecode(reinterpret_cast<Instr*>(sim_->get_pc())); |
453 } else if ((strcmp(cmd, "c") == 0) || (strcmp(cmd, "cont") == 0)) { | 448 } else if ((strcmp(cmd, "c") == 0) || (strcmp(cmd, "cont") == 0)) { |
454 // Execute the one instruction we broke at with breakpoints disabled. | 449 // Execute the one instruction we broke at with breakpoints disabled. |
455 sim_->InstructionDecode(reinterpret_cast<Instr*>(sim_->get_pc())); | 450 sim_->InstructionDecode(reinterpret_cast<Instr*>(sim_->get_pc())); |
456 // Leave the debugger shell. | 451 // Leave the debugger shell. |
457 done = true; | 452 done = true; |
(...skipping 23 matching lines...) Expand all Loading... |
481 } | 476 } |
482 } else { | 477 } else { |
483 OS::Print("printfloat <sreg or *addr>\n"); | 478 OS::Print("printfloat <sreg or *addr>\n"); |
484 } | 479 } |
485 } else if ((strcmp(cmd, "pd") == 0) || | 480 } else if ((strcmp(cmd, "pd") == 0) || |
486 (strcmp(cmd, "printdouble") == 0)) { | 481 (strcmp(cmd, "printdouble") == 0)) { |
487 if (args == 2) { | 482 if (args == 2) { |
488 double dvalue; | 483 double dvalue; |
489 if (GetDValue(arg1, &dvalue)) { | 484 if (GetDValue(arg1, &dvalue)) { |
490 uint64_t long_value = bit_cast<uint64_t, double>(dvalue); | 485 uint64_t long_value = bit_cast<uint64_t, double>(dvalue); |
491 OS::Print("%s: %llu 0x%llx %.8g\n", | 486 OS::Print("%s: %llu 0x%llx %.8g\n", arg1, long_value, long_value, |
492 arg1, long_value, long_value, dvalue); | 487 dvalue); |
493 } else { | 488 } else { |
494 OS::Print("%s unrecognized\n", arg1); | 489 OS::Print("%s unrecognized\n", arg1); |
495 } | 490 } |
496 } else { | 491 } else { |
497 OS::Print("printdouble <dreg or *addr>\n"); | 492 OS::Print("printdouble <dreg or *addr>\n"); |
498 } | 493 } |
499 } else if ((strcmp(cmd, "po") == 0) || | 494 } else if ((strcmp(cmd, "po") == 0) || |
500 (strcmp(cmd, "printobject") == 0)) { | 495 (strcmp(cmd, "printobject") == 0)) { |
501 if (args == 2) { | 496 if (args == 2) { |
502 uint32_t value; | 497 uint32_t value; |
503 // Make the dereferencing '*' optional. | 498 // Make the dereferencing '*' optional. |
504 if (((arg1[0] == '*') && GetValue(arg1 + 1, &value)) || | 499 if (((arg1[0] == '*') && GetValue(arg1 + 1, &value)) || |
505 GetValue(arg1, &value)) { | 500 GetValue(arg1, &value)) { |
506 if (Isolate::Current()->heap()->Contains(value)) { | 501 if (Isolate::Current()->heap()->Contains(value)) { |
507 OS::Print("%s: \n", arg1); | 502 OS::Print("%s: \n", arg1); |
508 #if defined(DEBUG) | 503 #if defined(DEBUG) |
509 const Object& obj = Object::Handle( | 504 const Object& obj = |
510 reinterpret_cast<RawObject*>(value)); | 505 Object::Handle(reinterpret_cast<RawObject*>(value)); |
511 obj.Print(); | 506 obj.Print(); |
512 #endif // defined(DEBUG) | 507 #endif // defined(DEBUG) |
513 } else { | 508 } else { |
514 OS::Print("0x%x is not an object reference\n", value); | 509 OS::Print("0x%x is not an object reference\n", value); |
515 } | 510 } |
516 } else { | 511 } else { |
517 OS::Print("%s unrecognized\n", arg1); | 512 OS::Print("%s unrecognized\n", arg1); |
518 } | 513 } |
519 } else { | 514 } else { |
520 OS::Print("printobject <*reg or *addr>\n"); | 515 OS::Print("printobject <*reg or *addr>\n"); |
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
634 OS::Print("%s", prompt); | 629 OS::Print("%s", prompt); |
635 while (keep_going) { | 630 while (keep_going) { |
636 if (fgets(line_buf, sizeof(line_buf), stdin) == NULL) { | 631 if (fgets(line_buf, sizeof(line_buf), stdin) == NULL) { |
637 // fgets got an error. Just give up. | 632 // fgets got an error. Just give up. |
638 if (result != NULL) { | 633 if (result != NULL) { |
639 delete[] result; | 634 delete[] result; |
640 } | 635 } |
641 return NULL; | 636 return NULL; |
642 } | 637 } |
643 intptr_t len = strlen(line_buf); | 638 intptr_t len = strlen(line_buf); |
644 if (len > 1 && | 639 if (len > 1 && line_buf[len - 2] == '\\' && line_buf[len - 1] == '\n') { |
645 line_buf[len - 2] == '\\' && | |
646 line_buf[len - 1] == '\n') { | |
647 // When we read a line that ends with a "\" we remove the escape and | 640 // When we read a line that ends with a "\" we remove the escape and |
648 // append the remainder. | 641 // append the remainder. |
649 line_buf[len - 2] = '\n'; | 642 line_buf[len - 2] = '\n'; |
650 line_buf[len - 1] = 0; | 643 line_buf[len - 1] = 0; |
651 len -= 1; | 644 len -= 1; |
652 } else if ((len > 0) && (line_buf[len - 1] == '\n')) { | 645 } else if ((len > 0) && (line_buf[len - 1] == '\n')) { |
653 // Since we read a new line we are done reading the line. This | 646 // Since we read a new line we are done reading the line. This |
654 // will exit the loop after copying this buffer into the result. | 647 // will exit the loop after copying this buffer into the result. |
655 keep_going = false; | 648 keep_going = false; |
656 } | 649 } |
(...skipping 25 matching lines...) Expand all Loading... |
682 offset += len; | 675 offset += len; |
683 } | 676 } |
684 ASSERT(result != NULL); | 677 ASSERT(result != NULL); |
685 result[offset] = '\0'; | 678 result[offset] = '\0'; |
686 return result; | 679 return result; |
687 } | 680 } |
688 | 681 |
689 | 682 |
690 // Synchronization primitives support. | 683 // Synchronization primitives support. |
691 Mutex* Simulator::exclusive_access_lock_ = NULL; | 684 Mutex* Simulator::exclusive_access_lock_ = NULL; |
692 Simulator::AddressTag Simulator::exclusive_access_state_[kNumAddressTags] = | 685 Simulator::AddressTag Simulator::exclusive_access_state_[kNumAddressTags] = { |
693 {{NULL, 0}}; | 686 {NULL, 0}}; |
694 int Simulator::next_address_tag_ = 0; | 687 int Simulator::next_address_tag_ = 0; |
695 | 688 |
696 | 689 |
697 void Simulator::InitOnce() { | 690 void Simulator::InitOnce() { |
698 // Setup exclusive access state lock. | 691 // Setup exclusive access state lock. |
699 exclusive_access_lock_ = new Mutex(); | 692 exclusive_access_lock_ = new Mutex(); |
700 } | 693 } |
701 | 694 |
702 | 695 |
703 Simulator::Simulator() { | 696 Simulator::Simulator() { |
704 // Setup simulator support first. Some of this information is needed to | 697 // Setup simulator support first. Some of this information is needed to |
705 // setup the architecture state. | 698 // setup the architecture state. |
706 // We allocate the stack here, the size is computed as the sum of | 699 // We allocate the stack here, the size is computed as the sum of |
707 // the size specified by the user and the buffer space needed for | 700 // the size specified by the user and the buffer space needed for |
708 // handling stack overflow exceptions. To be safe in potential | 701 // handling stack overflow exceptions. To be safe in potential |
709 // stack underflows we also add some underflow buffer space. | 702 // stack underflows we also add some underflow buffer space. |
710 stack_ = new char[(OSThread::GetSpecifiedStackSize() + | 703 stack_ = |
711 OSThread::kStackSizeBuffer + | 704 new char[(OSThread::GetSpecifiedStackSize() + OSThread::kStackSizeBuffer + |
712 kSimulatorStackUnderflowSize)]; | 705 kSimulatorStackUnderflowSize)]; |
713 pc_modified_ = false; | 706 pc_modified_ = false; |
714 icount_ = 0; | 707 icount_ = 0; |
715 break_pc_ = NULL; | 708 break_pc_ = NULL; |
716 break_instr_ = 0; | 709 break_instr_ = 0; |
717 last_setjmp_buffer_ = NULL; | 710 last_setjmp_buffer_ = NULL; |
718 top_exit_frame_info_ = 0; | 711 top_exit_frame_info_ = 0; |
719 | 712 |
720 // Setup architecture state. | 713 // Setup architecture state. |
721 // All registers are initialized to zero to start with. | 714 // All registers are initialized to zero to start with. |
722 for (int i = 0; i < kNumberOfCpuRegisters; i++) { | 715 for (int i = 0; i < kNumberOfCpuRegisters; i++) { |
(...skipping 11 matching lines...) Expand all Loading... |
734 // access violation if the simulator ever tries to execute it. | 727 // access violation if the simulator ever tries to execute it. |
735 registers_[PC] = kBadLR; | 728 registers_[PC] = kBadLR; |
736 registers_[LR] = kBadLR; | 729 registers_[LR] = kBadLR; |
737 | 730 |
738 // All double-precision registers are initialized to zero. | 731 // All double-precision registers are initialized to zero. |
739 for (int i = 0; i < kNumberOfDRegisters; i++) { | 732 for (int i = 0; i < kNumberOfDRegisters; i++) { |
740 dregisters_[i] = 0; | 733 dregisters_[i] = 0; |
741 } | 734 } |
742 // Since VFP registers are overlapping, single-precision registers should | 735 // Since VFP registers are overlapping, single-precision registers should |
743 // already be initialized. | 736 // already be initialized. |
744 ASSERT(2*kNumberOfDRegisters >= kNumberOfSRegisters); | 737 ASSERT(2 * kNumberOfDRegisters >= kNumberOfSRegisters); |
745 for (int i = 0; i < kNumberOfSRegisters; i++) { | 738 for (int i = 0; i < kNumberOfSRegisters; i++) { |
746 ASSERT(sregisters_[i] == 0.0); | 739 ASSERT(sregisters_[i] == 0.0); |
747 } | 740 } |
748 fp_n_flag_ = false; | 741 fp_n_flag_ = false; |
749 fp_z_flag_ = false; | 742 fp_z_flag_ = false; |
750 fp_c_flag_ = false; | 743 fp_c_flag_ = false; |
751 fp_v_flag_ = false; | 744 fp_v_flag_ = false; |
752 } | 745 } |
753 | 746 |
754 | 747 |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
813 int argument_count) | 806 int argument_count) |
814 : external_function_(external_function), | 807 : external_function_(external_function), |
815 call_kind_(call_kind), | 808 call_kind_(call_kind), |
816 argument_count_(argument_count), | 809 argument_count_(argument_count), |
817 svc_instruction_(Instr::kSimulatorRedirectInstruction) { | 810 svc_instruction_(Instr::kSimulatorRedirectInstruction) { |
818 // Atomically prepend this element to the front of the global list. | 811 // Atomically prepend this element to the front of the global list. |
819 // Note: Since elements are never removed, there is no ABA issue. | 812 // Note: Since elements are never removed, there is no ABA issue. |
820 Redirection* list_head = list_; | 813 Redirection* list_head = list_; |
821 do { | 814 do { |
822 next_ = list_head; | 815 next_ = list_head; |
823 list_head = reinterpret_cast<Redirection*>( | 816 list_head = |
824 AtomicOperations::CompareAndSwapWord( | 817 reinterpret_cast<Redirection*>(AtomicOperations::CompareAndSwapWord( |
825 reinterpret_cast<uword*>(&list_), | 818 reinterpret_cast<uword*>(&list_), reinterpret_cast<uword>(next_), |
826 reinterpret_cast<uword>(next_), | |
827 reinterpret_cast<uword>(this))); | 819 reinterpret_cast<uword>(this))); |
828 } while (list_head != next_); | 820 } while (list_head != next_); |
829 } | 821 } |
830 | 822 |
831 uword external_function_; | 823 uword external_function_; |
832 Simulator::CallKind call_kind_; | 824 Simulator::CallKind call_kind_; |
833 int argument_count_; | 825 int argument_count_; |
834 uint32_t svc_instruction_; | 826 uint32_t svc_instruction_; |
835 Redirection* next_; | 827 Redirection* next_; |
836 static Redirection* list_; | 828 static Redirection* list_; |
(...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
973 return dregisters_[reg]; | 965 return dregisters_[reg]; |
974 } | 966 } |
975 | 967 |
976 | 968 |
977 void Simulator::HandleIllegalAccess(uword addr, Instr* instr) { | 969 void Simulator::HandleIllegalAccess(uword addr, Instr* instr) { |
978 uword fault_pc = get_pc(); | 970 uword fault_pc = get_pc(); |
979 // The debugger will not be able to single step past this instruction, but | 971 // The debugger will not be able to single step past this instruction, but |
980 // it will be possible to disassemble the code and inspect registers. | 972 // it will be possible to disassemble the code and inspect registers. |
981 char buffer[128]; | 973 char buffer[128]; |
982 snprintf(buffer, sizeof(buffer), | 974 snprintf(buffer, sizeof(buffer), |
983 "illegal memory access at 0x%" Px ", pc=0x%" Px "\n", | 975 "illegal memory access at 0x%" Px ", pc=0x%" Px "\n", addr, |
984 addr, fault_pc); | 976 fault_pc); |
985 SimulatorDebugger dbg(this); | 977 SimulatorDebugger dbg(this); |
986 dbg.Stop(instr, buffer); | 978 dbg.Stop(instr, buffer); |
987 // The debugger will return control in non-interactive mode. | 979 // The debugger will return control in non-interactive mode. |
988 FATAL("Cannot continue execution after illegal memory access."); | 980 FATAL("Cannot continue execution after illegal memory access."); |
989 } | 981 } |
990 | 982 |
991 | 983 |
992 // Processor versions prior to ARMv7 could not do unaligned reads and writes. | 984 // Processor versions prior to ARMv7 could not do unaligned reads and writes. |
993 // On some ARM platforms an interrupt is caused. On others it does a funky | 985 // On some ARM platforms an interrupt is caused. On others it does a funky |
994 // rotation thing. However, from version v7, unaligned access is supported. | 986 // rotation thing. However, from version v7, unaligned access is supported. |
995 // Note that simulator runs have the runtime system running directly on the host | 987 // Note that simulator runs have the runtime system running directly on the host |
996 // system and only generated code is executed in the simulator. Since the host | 988 // system and only generated code is executed in the simulator. Since the host |
997 // is typically IA32 we will get the correct ARMv7-like behaviour on unaligned | 989 // is typically IA32 we will get the correct ARMv7-like behaviour on unaligned |
998 // accesses, but we should actually not generate code accessing unaligned data, | 990 // accesses, but we should actually not generate code accessing unaligned data, |
999 // so we still want to know and abort if we encounter such code. | 991 // so we still want to know and abort if we encounter such code. |
1000 void Simulator::UnalignedAccess(const char* msg, uword addr, Instr* instr) { | 992 void Simulator::UnalignedAccess(const char* msg, uword addr, Instr* instr) { |
1001 // The debugger will not be able to single step past this instruction, but | 993 // The debugger will not be able to single step past this instruction, but |
1002 // it will be possible to disassemble the code and inspect registers. | 994 // it will be possible to disassemble the code and inspect registers. |
1003 char buffer[64]; | 995 char buffer[64]; |
1004 snprintf(buffer, sizeof(buffer), | 996 snprintf(buffer, sizeof(buffer), "unaligned %s at 0x%" Px ", pc=%p\n", msg, |
1005 "unaligned %s at 0x%" Px ", pc=%p\n", msg, addr, instr); | 997 addr, instr); |
1006 SimulatorDebugger dbg(this); | 998 SimulatorDebugger dbg(this); |
1007 dbg.Stop(instr, buffer); | 999 dbg.Stop(instr, buffer); |
1008 // The debugger will return control in non-interactive mode. | 1000 // The debugger will return control in non-interactive mode. |
1009 FATAL("Cannot continue execution after unaligned access."); | 1001 FATAL("Cannot continue execution after unaligned access."); |
1010 } | 1002 } |
1011 | 1003 |
1012 | 1004 |
1013 void Simulator::UnimplementedInstruction(Instr* instr) { | 1005 void Simulator::UnimplementedInstruction(Instr* instr) { |
1014 char buffer[64]; | 1006 char buffer[64]; |
1015 snprintf(buffer, sizeof(buffer), "Unimplemented instruction: pc=%p\n", instr); | 1007 snprintf(buffer, sizeof(buffer), "Unimplemented instruction: pc=%p\n", instr); |
(...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1187 static_cast<uword>(new_value)); | 1179 static_cast<uword>(new_value)); |
1188 } | 1180 } |
1189 | 1181 |
1190 | 1182 |
1191 // Returns the top of the stack area to enable checking for stack pointer | 1183 // Returns the top of the stack area to enable checking for stack pointer |
1192 // validity. | 1184 // validity. |
1193 uword Simulator::StackTop() const { | 1185 uword Simulator::StackTop() const { |
1194 // To be safe in potential stack underflows we leave some buffer above and | 1186 // To be safe in potential stack underflows we leave some buffer above and |
1195 // set the stack top. | 1187 // set the stack top. |
1196 return StackBase() + | 1188 return StackBase() + |
1197 (OSThread::GetSpecifiedStackSize() + OSThread::kStackSizeBuffer); | 1189 (OSThread::GetSpecifiedStackSize() + OSThread::kStackSizeBuffer); |
1198 } | 1190 } |
1199 | 1191 |
1200 | 1192 |
1201 bool Simulator::IsTracingExecution() const { | 1193 bool Simulator::IsTracingExecution() const { |
1202 return icount_ > FLAG_trace_sim_after; | 1194 return icount_ > FLAG_trace_sim_after; |
1203 } | 1195 } |
1204 | 1196 |
1205 | 1197 |
1206 // Unsupported instructions use Format to print an error and stop execution. | 1198 // Unsupported instructions use Format to print an error and stop execution. |
1207 void Simulator::Format(Instr* instr, const char* format) { | 1199 void Simulator::Format(Instr* instr, const char* format) { |
1208 OS::Print("Simulator found unsupported instruction:\n 0x%p: %s\n", | 1200 OS::Print("Simulator found unsupported instruction:\n 0x%p: %s\n", instr, |
1209 instr, | |
1210 format); | 1201 format); |
1211 UNIMPLEMENTED(); | 1202 UNIMPLEMENTED(); |
1212 } | 1203 } |
1213 | 1204 |
1214 | 1205 |
1215 // Checks if the current instruction should be executed based on its | 1206 // Checks if the current instruction should be executed based on its |
1216 // condition bits. | 1207 // condition bits. |
1217 bool Simulator::ConditionallyExecute(Instr* instr) { | 1208 bool Simulator::ConditionallyExecute(Instr* instr) { |
1218 switch (instr->ConditionField()) { | 1209 switch (instr->ConditionField()) { |
1219 case EQ: return z_flag_; | 1210 case EQ: |
1220 case NE: return !z_flag_; | 1211 return z_flag_; |
1221 case CS: return c_flag_; | 1212 case NE: |
1222 case CC: return !c_flag_; | 1213 return !z_flag_; |
1223 case MI: return n_flag_; | 1214 case CS: |
1224 case PL: return !n_flag_; | 1215 return c_flag_; |
1225 case VS: return v_flag_; | 1216 case CC: |
1226 case VC: return !v_flag_; | 1217 return !c_flag_; |
1227 case HI: return c_flag_ && !z_flag_; | 1218 case MI: |
1228 case LS: return !c_flag_ || z_flag_; | 1219 return n_flag_; |
1229 case GE: return n_flag_ == v_flag_; | 1220 case PL: |
1230 case LT: return n_flag_ != v_flag_; | 1221 return !n_flag_; |
1231 case GT: return !z_flag_ && (n_flag_ == v_flag_); | 1222 case VS: |
1232 case LE: return z_flag_ || (n_flag_ != v_flag_); | 1223 return v_flag_; |
1233 case AL: return true; | 1224 case VC: |
1234 default: UNREACHABLE(); | 1225 return !v_flag_; |
| 1226 case HI: |
| 1227 return c_flag_ && !z_flag_; |
| 1228 case LS: |
| 1229 return !c_flag_ || z_flag_; |
| 1230 case GE: |
| 1231 return n_flag_ == v_flag_; |
| 1232 case LT: |
| 1233 return n_flag_ != v_flag_; |
| 1234 case GT: |
| 1235 return !z_flag_ && (n_flag_ == v_flag_); |
| 1236 case LE: |
| 1237 return z_flag_ || (n_flag_ != v_flag_); |
| 1238 case AL: |
| 1239 return true; |
| 1240 default: |
| 1241 UNREACHABLE(); |
1235 } | 1242 } |
1236 return false; | 1243 return false; |
1237 } | 1244 } |
1238 | 1245 |
1239 | 1246 |
1240 // Calculate and set the Negative and Zero flags. | 1247 // Calculate and set the Negative and Zero flags. |
1241 void Simulator::SetNZFlags(int32_t val) { | 1248 void Simulator::SetNZFlags(int32_t val) { |
1242 n_flag_ = (val < 0); | 1249 n_flag_ = (val < 0); |
1243 z_flag_ = (val == 0); | 1250 z_flag_ = (val == 0); |
1244 } | 1251 } |
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1334 } | 1341 } |
1335 | 1342 |
1336 default: { | 1343 default: { |
1337 UNREACHABLE(); | 1344 UNREACHABLE(); |
1338 break; | 1345 break; |
1339 } | 1346 } |
1340 } | 1347 } |
1341 } else { | 1348 } else { |
1342 // by register | 1349 // by register |
1343 Register rs = instr->RsField(); | 1350 Register rs = instr->RsField(); |
1344 shift_amount = get_register(rs) &0xff; | 1351 shift_amount = get_register(rs) & 0xff; |
1345 switch (shift) { | 1352 switch (shift) { |
1346 case ASR: { | 1353 case ASR: { |
1347 if (shift_amount == 0) { | 1354 if (shift_amount == 0) { |
1348 *carry_out = c_flag_; | 1355 *carry_out = c_flag_; |
1349 } else if (shift_amount < 32) { | 1356 } else if (shift_amount < 32) { |
1350 result >>= (shift_amount - 1); | 1357 result >>= (shift_amount - 1); |
1351 *carry_out = (result & 1) == 1; | 1358 *carry_out = (result & 1) == 1; |
1352 result >>= 1; | 1359 result >>= 1; |
1353 } else { | 1360 } else { |
1354 ASSERT(shift_amount >= 32); | 1361 ASSERT(shift_amount >= 32); |
(...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1502 } | 1509 } |
1503 ASSERT(end_address == address); | 1510 ASSERT(end_address == address); |
1504 } | 1511 } |
1505 } | 1512 } |
1506 | 1513 |
1507 | 1514 |
1508 // Calls into the Dart runtime are based on this interface. | 1515 // Calls into the Dart runtime are based on this interface. |
1509 typedef void (*SimulatorRuntimeCall)(NativeArguments arguments); | 1516 typedef void (*SimulatorRuntimeCall)(NativeArguments arguments); |
1510 | 1517 |
1511 // Calls to leaf Dart runtime functions are based on this interface. | 1518 // Calls to leaf Dart runtime functions are based on this interface. |
1512 typedef int32_t (*SimulatorLeafRuntimeCall)( | 1519 typedef int32_t (*SimulatorLeafRuntimeCall)(int32_t r0, |
1513 int32_t r0, int32_t r1, int32_t r2, int32_t r3); | 1520 int32_t r1, |
| 1521 int32_t r2, |
| 1522 int32_t r3); |
1514 | 1523 |
1515 // Calls to leaf float Dart runtime functions are based on this interface. | 1524 // Calls to leaf float Dart runtime functions are based on this interface. |
1516 typedef double (*SimulatorLeafFloatRuntimeCall)(double d0, double d1); | 1525 typedef double (*SimulatorLeafFloatRuntimeCall)(double d0, double d1); |
1517 | 1526 |
1518 // Calls to native Dart functions are based on this interface. | 1527 // Calls to native Dart functions are based on this interface. |
1519 typedef void (*SimulatorBootstrapNativeCall)(NativeArguments* arguments); | 1528 typedef void (*SimulatorBootstrapNativeCall)(NativeArguments* arguments); |
1520 typedef void (*SimulatorNativeCall)(NativeArguments* arguments, uword target); | 1529 typedef void (*SimulatorNativeCall)(NativeArguments* arguments, uword target); |
1521 | 1530 |
1522 | 1531 |
1523 void Simulator::SupervisorCall(Instr* instr) { | 1532 void Simulator::SupervisorCall(Instr* instr) { |
(...skipping 11 matching lines...) Expand all Loading... |
1535 } | 1544 } |
1536 | 1545 |
1537 if ((redirection->call_kind() == kRuntimeCall) || | 1546 if ((redirection->call_kind() == kRuntimeCall) || |
1538 (redirection->call_kind() == kBootstrapNativeCall) || | 1547 (redirection->call_kind() == kBootstrapNativeCall) || |
1539 (redirection->call_kind() == kNativeCall)) { | 1548 (redirection->call_kind() == kNativeCall)) { |
1540 // Set the top_exit_frame_info of this simulator to the native stack. | 1549 // Set the top_exit_frame_info of this simulator to the native stack. |
1541 set_top_exit_frame_info(Thread::GetCurrentStackPointer()); | 1550 set_top_exit_frame_info(Thread::GetCurrentStackPointer()); |
1542 } | 1551 } |
1543 if (redirection->call_kind() == kRuntimeCall) { | 1552 if (redirection->call_kind() == kRuntimeCall) { |
1544 NativeArguments arguments; | 1553 NativeArguments arguments; |
1545 ASSERT(sizeof(NativeArguments) == 4*kWordSize); | 1554 ASSERT(sizeof(NativeArguments) == 4 * kWordSize); |
1546 arguments.thread_ = reinterpret_cast<Thread*>(get_register(R0)); | 1555 arguments.thread_ = reinterpret_cast<Thread*>(get_register(R0)); |
1547 arguments.argc_tag_ = get_register(R1); | 1556 arguments.argc_tag_ = get_register(R1); |
1548 arguments.argv_ = reinterpret_cast<RawObject**>(get_register(R2)); | 1557 arguments.argv_ = reinterpret_cast<RawObject**>(get_register(R2)); |
1549 arguments.retval_ = reinterpret_cast<RawObject**>(get_register(R3)); | 1558 arguments.retval_ = reinterpret_cast<RawObject**>(get_register(R3)); |
1550 SimulatorRuntimeCall target = | 1559 SimulatorRuntimeCall target = |
1551 reinterpret_cast<SimulatorRuntimeCall>(external); | 1560 reinterpret_cast<SimulatorRuntimeCall>(external); |
1552 target(arguments); | 1561 target(arguments); |
1553 set_register(R0, icount_); // Zap result register from void function. | 1562 set_register(R0, icount_); // Zap result register from void function. |
1554 set_register(R1, icount_); | 1563 set_register(R1, icount_); |
1555 } else if (redirection->call_kind() == kLeafRuntimeCall) { | 1564 } else if (redirection->call_kind() == kLeafRuntimeCall) { |
1556 ASSERT((0 <= redirection->argument_count()) && | 1565 ASSERT((0 <= redirection->argument_count()) && |
1557 (redirection->argument_count() <= 4)); | 1566 (redirection->argument_count() <= 4)); |
1558 int32_t r0 = get_register(R0); | 1567 int32_t r0 = get_register(R0); |
1559 int32_t r1 = get_register(R1); | 1568 int32_t r1 = get_register(R1); |
1560 int32_t r2 = get_register(R2); | 1569 int32_t r2 = get_register(R2); |
1561 int32_t r3 = get_register(R3); | 1570 int32_t r3 = get_register(R3); |
1562 SimulatorLeafRuntimeCall target = | 1571 SimulatorLeafRuntimeCall target = |
1563 reinterpret_cast<SimulatorLeafRuntimeCall>(external); | 1572 reinterpret_cast<SimulatorLeafRuntimeCall>(external); |
1564 r0 = target(r0, r1, r2, r3); | 1573 r0 = target(r0, r1, r2, r3); |
1565 set_register(R0, r0); // Set returned result from function. | 1574 set_register(R0, r0); // Set returned result from function. |
1566 set_register(R1, icount_); // Zap unused result register. | 1575 set_register(R1, icount_); // Zap unused result register. |
1567 } else if (redirection->call_kind() == kLeafFloatRuntimeCall) { | 1576 } else if (redirection->call_kind() == kLeafFloatRuntimeCall) { |
1568 ASSERT((0 <= redirection->argument_count()) && | 1577 ASSERT((0 <= redirection->argument_count()) && |
1569 (redirection->argument_count() <= 2)); | 1578 (redirection->argument_count() <= 2)); |
1570 SimulatorLeafFloatRuntimeCall target = | 1579 SimulatorLeafFloatRuntimeCall target = |
1571 reinterpret_cast<SimulatorLeafFloatRuntimeCall>(external); | 1580 reinterpret_cast<SimulatorLeafFloatRuntimeCall>(external); |
1572 if (TargetCPUFeatures::hardfp_supported()) { | 1581 if (TargetCPUFeatures::hardfp_supported()) { |
1573 // If we're doing "hardfp", the double arguments are already in the | 1582 // If we're doing "hardfp", the double arguments are already in the |
1574 // floating point registers. | 1583 // floating point registers. |
1575 double d0 = get_dregister(D0); | 1584 double d0 = get_dregister(D0); |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1620 set_register(R2, icount_); | 1629 set_register(R2, icount_); |
1621 set_register(R3, icount_); | 1630 set_register(R3, icount_); |
1622 set_register(IP, icount_); | 1631 set_register(IP, icount_); |
1623 set_register(LR, icount_); | 1632 set_register(LR, icount_); |
1624 if (TargetCPUFeatures::vfp_supported()) { | 1633 if (TargetCPUFeatures::vfp_supported()) { |
1625 double zap_dvalue = static_cast<double>(icount_); | 1634 double zap_dvalue = static_cast<double>(icount_); |
1626 // Do not zap D0, as it may contain a float result. | 1635 // Do not zap D0, as it may contain a float result. |
1627 for (int i = D1; i <= D7; i++) { | 1636 for (int i = D1; i <= D7; i++) { |
1628 set_dregister(static_cast<DRegister>(i), zap_dvalue); | 1637 set_dregister(static_cast<DRegister>(i), zap_dvalue); |
1629 } | 1638 } |
1630 // The above loop also zaps overlapping registers S2-S15. | 1639 // The above loop also zaps overlapping registers S2-S15. |
1631 // Registers D8-D15 (overlapping with S16-S31) are preserved. | 1640 // Registers D8-D15 (overlapping with S16-S31) are preserved. |
1632 #if defined(VFPv3_D32) | 1641 #if defined(VFPv3_D32) |
1633 for (int i = D16; i <= D31; i++) { | 1642 for (int i = D16; i <= D31; i++) { |
1634 set_dregister(static_cast<DRegister>(i), zap_dvalue); | 1643 set_dregister(static_cast<DRegister>(i), zap_dvalue); |
1635 } | 1644 } |
1636 #endif | 1645 #endif |
1637 } | 1646 } |
1638 | 1647 |
1639 // Return. | 1648 // Return. |
1640 set_pc(saved_lr); | 1649 set_pc(saved_lr); |
1641 } else { | 1650 } else { |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1712 reinterpret_cast<intptr_t>(instr) - Instr::kInstrSize); | 1721 reinterpret_cast<intptr_t>(instr) - Instr::kInstrSize); |
1713 set_pc(get_pc() + Instr::kInstrSize); | 1722 set_pc(get_pc() + Instr::kInstrSize); |
1714 dbg.Stop(instr, message); | 1723 dbg.Stop(instr, message); |
1715 } else { | 1724 } else { |
1716 char buffer[32]; | 1725 char buffer[32]; |
1717 snprintf(buffer, sizeof(buffer), "bkpt #0x%x", imm); | 1726 snprintf(buffer, sizeof(buffer), "bkpt #0x%x", imm); |
1718 set_pc(get_pc() + Instr::kInstrSize); | 1727 set_pc(get_pc() + Instr::kInstrSize); |
1719 dbg.Stop(instr, buffer); | 1728 dbg.Stop(instr, buffer); |
1720 } | 1729 } |
1721 } else { | 1730 } else { |
1722 // Format(instr, "smc'cond"); | 1731 // Format(instr, "smc'cond"); |
1723 UnimplementedInstruction(instr); | 1732 UnimplementedInstruction(instr); |
1724 } | 1733 } |
1725 break; | 1734 break; |
1726 } | 1735 } |
1727 default: { | 1736 default: { |
1728 UnimplementedInstruction(instr); | 1737 UnimplementedInstruction(instr); |
1729 break; | 1738 break; |
1730 } | 1739 } |
1731 } | 1740 } |
1732 } else if (instr->IsMultiplyOrSyncPrimitive()) { | 1741 } else if (instr->IsMultiplyOrSyncPrimitive()) { |
1733 if (instr->Bit(24) == 0) { | 1742 if (instr->Bit(24) == 0) { |
1734 // multiply instructions. | 1743 // multiply instructions. |
1735 Register rn = instr->RnField(); | 1744 Register rn = instr->RnField(); |
1736 Register rd = instr->RdField(); | 1745 Register rd = instr->RdField(); |
1737 Register rs = instr->RsField(); | 1746 Register rs = instr->RsField(); |
1738 Register rm = instr->RmField(); | 1747 Register rm = instr->RmField(); |
1739 int32_t rm_val = get_register(rm); | 1748 int32_t rm_val = get_register(rm); |
1740 int32_t rs_val = get_register(rs); | 1749 int32_t rs_val = get_register(rs); |
1741 int32_t rd_val = 0; | 1750 int32_t rd_val = 0; |
1742 switch (instr->Bits(21, 3)) { | 1751 switch (instr->Bits(21, 3)) { |
1743 case 1: | 1752 case 1: |
1744 // Registers rd, rn, rm, ra are encoded as rn, rm, rs, rd. | 1753 // Registers rd, rn, rm, ra are encoded as rn, rm, rs, rd. |
1745 // Format(instr, "mla'cond's 'rn, 'rm, 'rs, 'rd"); | 1754 // Format(instr, "mla'cond's 'rn, 'rm, 'rs, 'rd"); |
1746 case 3: { | 1755 case 3: { |
1747 // Registers rd, rn, rm, ra are encoded as rn, rm, rs, rd. | 1756 // Registers rd, rn, rm, ra are encoded as rn, rm, rs, rd. |
1748 // Format(instr, "mls'cond's 'rn, 'rm, 'rs, 'rd"); | 1757 // Format(instr, "mls'cond's 'rn, 'rm, 'rs, 'rd"); |
1749 rd_val = get_register(rd); | 1758 rd_val = get_register(rd); |
1750 // fall through | 1759 // fall through |
1751 } | 1760 } |
1752 case 0: { | 1761 case 0: { |
1753 // Registers rd, rn, rm are encoded as rn, rm, rs. | 1762 // Registers rd, rn, rm are encoded as rn, rm, rs. |
1754 // Format(instr, "mul'cond's 'rn, 'rm, 'rs"); | 1763 // Format(instr, "mul'cond's 'rn, 'rm, 'rs"); |
1755 int32_t alu_out = rm_val * rs_val; | 1764 int32_t alu_out = rm_val * rs_val; |
1756 if (instr->Bits(21, 3) == 3) { // mls | 1765 if (instr->Bits(21, 3) == 3) { // mls |
1757 if (TargetCPUFeatures::arm_version() != ARMv7) { | 1766 if (TargetCPUFeatures::arm_version() != ARMv7) { |
1758 UnimplementedInstruction(instr); | 1767 UnimplementedInstruction(instr); |
1759 break; | 1768 break; |
1760 } | 1769 } |
1761 alu_out = -alu_out; | 1770 alu_out = -alu_out; |
1762 } | 1771 } |
1763 alu_out += rd_val; | 1772 alu_out += rd_val; |
1764 set_register(rn, alu_out); | 1773 set_register(rn, alu_out); |
1765 if (instr->HasS()) { | 1774 if (instr->HasS()) { |
1766 SetNZFlags(alu_out); | 1775 SetNZFlags(alu_out); |
1767 } | 1776 } |
1768 break; | 1777 break; |
1769 } | 1778 } |
1770 case 4: | 1779 case 4: |
1771 // Registers rd_lo, rd_hi, rn, rm are encoded as rd, rn, rm, rs. | 1780 // Registers rd_lo, rd_hi, rn, rm are encoded as rd, rn, rm, rs. |
1772 // Format(instr, "umull'cond's 'rd, 'rn, 'rm, 'rs"); | 1781 // Format(instr, "umull'cond's 'rd, 'rn, 'rm, 'rs"); |
1773 case 6: { | 1782 case 6: { |
1774 // Registers rd_lo, rd_hi, rn, rm are encoded as rd, rn, rm, rs. | 1783 // Registers rd_lo, rd_hi, rn, rm are encoded as rd, rn, rm, rs. |
1775 // Format(instr, "smull'cond's 'rd, 'rn, 'rm, 'rs"); | 1784 // Format(instr, "smull'cond's 'rd, 'rn, 'rm, 'rs"); |
1776 int64_t result; | 1785 int64_t result; |
1777 if (instr->Bits(21, 3) == 4) { // umull | 1786 if (instr->Bits(21, 3) == 4) { // umull |
1778 uint64_t left_op = static_cast<uint32_t>(rm_val); | 1787 uint64_t left_op = static_cast<uint32_t>(rm_val); |
1779 uint64_t right_op = static_cast<uint32_t>(rs_val); | 1788 uint64_t right_op = static_cast<uint32_t>(rs_val); |
1780 result = left_op * right_op; // Unsigned multiplication. | 1789 result = left_op * right_op; // Unsigned multiplication. |
1781 } else { // smull | 1790 } else { // smull |
1782 int64_t left_op = static_cast<int32_t>(rm_val); | 1791 int64_t left_op = static_cast<int32_t>(rm_val); |
1783 int64_t right_op = static_cast<int32_t>(rs_val); | 1792 int64_t right_op = static_cast<int32_t>(rs_val); |
1784 result = left_op * right_op; // Signed multiplication. | 1793 result = left_op * right_op; // Signed multiplication. |
1785 } | 1794 } |
1786 int32_t hi_res = Utils::High32Bits(result); | 1795 int32_t hi_res = Utils::High32Bits(result); |
1787 int32_t lo_res = Utils::Low32Bits(result); | 1796 int32_t lo_res = Utils::Low32Bits(result); |
1788 set_register(rd, lo_res); | 1797 set_register(rd, lo_res); |
1789 set_register(rn, hi_res); | 1798 set_register(rn, hi_res); |
1790 if (instr->HasS()) { | 1799 if (instr->HasS()) { |
1791 if (lo_res != 0) { | 1800 if (lo_res != 0) { |
1792 // Collapse bits 0..31 into bit 32 so that 32-bit Z check works. | 1801 // Collapse bits 0..31 into bit 32 so that 32-bit Z check works. |
1793 hi_res |= 1; | 1802 hi_res |= 1; |
1794 } | 1803 } |
1795 ASSERT((result == 0) == (hi_res == 0)); // Z bit | 1804 ASSERT((result == 0) == (hi_res == 0)); // Z bit |
1796 ASSERT(((result & (1LL << 63)) != 0) == (hi_res < 0)); // N bit | 1805 ASSERT(((result & (1LL << 63)) != 0) == (hi_res < 0)); // N bit |
1797 SetNZFlags(hi_res); | 1806 SetNZFlags(hi_res); |
1798 } | 1807 } |
1799 break; | 1808 break; |
1800 } | 1809 } |
1801 case 2: | 1810 case 2: |
1802 // Registers rd_lo, rd_hi, rn, rm are encoded as rd, rn, rm, rs. | 1811 // Registers rd_lo, rd_hi, rn, rm are encoded as rd, rn, rm, rs. |
1803 // Format(instr, "umaal'cond's 'rd, 'rn, 'rm, 'rs"); | 1812 // Format(instr, "umaal'cond's 'rd, 'rn, 'rm, 'rs"); |
1804 if (TargetCPUFeatures::arm_version() == ARMv5TE) { | 1813 if (TargetCPUFeatures::arm_version() == ARMv5TE) { |
1805 // umaal is only in ARMv6 and above. | 1814 // umaal is only in ARMv6 and above. |
1806 UnimplementedInstruction(instr); | 1815 UnimplementedInstruction(instr); |
1807 } | 1816 } |
1808 case 5: | 1817 case 5: |
1809 // Registers rd_lo, rd_hi, rn, rm are encoded as rd, rn, rm, rs. | 1818 // Registers rd_lo, rd_hi, rn, rm are encoded as rd, rn, rm, rs. |
1810 // Format(instr, "umlal'cond's 'rd, 'rn, 'rm, 'rs"); | 1819 // Format(instr, "umlal'cond's 'rd, 'rn, 'rm, 'rs"); |
1811 case 7: { | 1820 case 7: { |
1812 // Registers rd_lo, rd_hi, rn, rm are encoded as rd, rn, rm, rs. | 1821 // Registers rd_lo, rd_hi, rn, rm are encoded as rd, rn, rm, rs. |
1813 // Format(instr, "smlal'cond's 'rd, 'rn, 'rm, 'rs"); | 1822 // Format(instr, "smlal'cond's 'rd, 'rn, 'rm, 'rs"); |
1814 int32_t rd_lo_val = get_register(rd); | 1823 int32_t rd_lo_val = get_register(rd); |
1815 int32_t rd_hi_val = get_register(rn); | 1824 int32_t rd_hi_val = get_register(rn); |
1816 uint32_t accum_lo = static_cast<uint32_t>(rd_lo_val); | 1825 uint32_t accum_lo = static_cast<uint32_t>(rd_lo_val); |
1817 int32_t accum_hi = static_cast<int32_t>(rd_hi_val); | 1826 int32_t accum_hi = static_cast<int32_t>(rd_hi_val); |
1818 int64_t accum = Utils::LowHighTo64Bits(accum_lo, accum_hi); | 1827 int64_t accum = Utils::LowHighTo64Bits(accum_lo, accum_hi); |
1819 int64_t result; | 1828 int64_t result; |
1820 if (instr->Bits(21, 3) == 5) { // umlal | 1829 if (instr->Bits(21, 3) == 5) { // umlal |
1821 uint64_t left_op = static_cast<uint32_t>(rm_val); | 1830 uint64_t left_op = static_cast<uint32_t>(rm_val); |
1822 uint64_t right_op = static_cast<uint32_t>(rs_val); | 1831 uint64_t right_op = static_cast<uint32_t>(rs_val); |
1823 result = accum + left_op * right_op; // Unsigned multiplication. | 1832 result = accum + left_op * right_op; // Unsigned multiplication. |
1824 } else if (instr->Bits(21, 3) == 7) { // smlal | 1833 } else if (instr->Bits(21, 3) == 7) { // smlal |
1825 int64_t left_op = static_cast<int32_t>(rm_val); | 1834 int64_t left_op = static_cast<int32_t>(rm_val); |
1826 int64_t right_op = static_cast<int32_t>(rs_val); | 1835 int64_t right_op = static_cast<int32_t>(rs_val); |
1827 result = accum + left_op * right_op; // Signed multiplication. | 1836 result = accum + left_op * right_op; // Signed multiplication. |
1828 } else { | 1837 } else { |
1829 ASSERT(instr->Bits(21, 3) == 2); // umaal | 1838 ASSERT(instr->Bits(21, 3) == 2); // umaal |
1830 ASSERT(!instr->HasS()); | 1839 ASSERT(!instr->HasS()); |
1831 uint64_t left_op = static_cast<uint32_t>(rm_val); | 1840 uint64_t left_op = static_cast<uint32_t>(rm_val); |
1832 uint64_t right_op = static_cast<uint32_t>(rs_val); | 1841 uint64_t right_op = static_cast<uint32_t>(rs_val); |
1833 result = left_op * right_op + // Unsigned multiplication. | 1842 result = left_op * right_op + // Unsigned multiplication. |
1834 static_cast<uint32_t>(rd_lo_val) + | 1843 static_cast<uint32_t>(rd_lo_val) + |
1835 static_cast<uint32_t>(rd_hi_val); | 1844 static_cast<uint32_t>(rd_hi_val); |
1836 } | 1845 } |
1837 int32_t hi_res = Utils::High32Bits(result); | 1846 int32_t hi_res = Utils::High32Bits(result); |
1838 int32_t lo_res = Utils::Low32Bits(result); | 1847 int32_t lo_res = Utils::Low32Bits(result); |
1839 set_register(rd, lo_res); | 1848 set_register(rd, lo_res); |
1840 set_register(rn, hi_res); | 1849 set_register(rn, hi_res); |
1841 if (instr->HasS()) { | 1850 if (instr->HasS()) { |
1842 if (lo_res != 0) { | 1851 if (lo_res != 0) { |
1843 // Collapse bits 0..31 into bit 32 so that 32-bit Z check works. | 1852 // Collapse bits 0..31 into bit 32 so that 32-bit Z check works. |
1844 hi_res |= 1; | 1853 hi_res |= 1; |
1845 } | 1854 } |
1846 ASSERT((result == 0) == (hi_res == 0)); // Z bit | 1855 ASSERT((result == 0) == (hi_res == 0)); // Z bit |
1847 ASSERT(((result & (1LL << 63)) != 0) == (hi_res < 0)); // N bit | 1856 ASSERT(((result & (1LL << 63)) != 0) == (hi_res < 0)); // N bit |
1848 SetNZFlags(hi_res); | 1857 SetNZFlags(hi_res); |
1849 } | 1858 } |
1850 break; | 1859 break; |
1851 } | 1860 } |
1852 default: { | 1861 default: { |
1853 UnimplementedInstruction(instr); | 1862 UnimplementedInstruction(instr); |
1854 break; | 1863 break; |
1855 } | 1864 } |
1856 } | 1865 } |
(...skipping 620 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2477 } | 2486 } |
2478 | 2487 |
2479 | 2488 |
2480 void Simulator::DecodeType5(Instr* instr) { | 2489 void Simulator::DecodeType5(Instr* instr) { |
2481 // Format(instr, "b'l'cond 'target"); | 2490 // Format(instr, "b'l'cond 'target"); |
2482 int off = (instr->SImmed24Field() << 2) + 8; | 2491 int off = (instr->SImmed24Field() << 2) + 8; |
2483 intptr_t pc = get_pc(); | 2492 intptr_t pc = get_pc(); |
2484 if (instr->HasLink()) { | 2493 if (instr->HasLink()) { |
2485 set_register(LR, pc + Instr::kInstrSize); | 2494 set_register(LR, pc + Instr::kInstrSize); |
2486 } | 2495 } |
2487 set_pc(pc+off); | 2496 set_pc(pc + off); |
2488 } | 2497 } |
2489 | 2498 |
2490 | 2499 |
2491 void Simulator::DecodeType6(Instr* instr) { | 2500 void Simulator::DecodeType6(Instr* instr) { |
2492 if (instr->IsVFPDoubleTransfer()) { | 2501 if (instr->IsVFPDoubleTransfer()) { |
2493 Register rd = instr->RdField(); | 2502 Register rd = instr->RdField(); |
2494 Register rn = instr->RnField(); | 2503 Register rn = instr->RnField(); |
2495 if (instr->Bit(8) == 0) { | 2504 if (instr->Bit(8) == 0) { |
2496 SRegister sm = instr->SmField(); | 2505 SRegister sm = instr->SmField(); |
2497 SRegister sm1 = static_cast<SRegister>(sm + 1); | 2506 SRegister sm1 = static_cast<SRegister>(sm + 1); |
2498 ASSERT(sm1 < kNumberOfSRegisters); | 2507 ASSERT(sm1 < kNumberOfSRegisters); |
2499 if (instr->Bit(20) == 1) { | 2508 if (instr->Bit(20) == 1) { |
2500 // Format(instr, "vmovrrs'cond 'rd, 'rn, {'sm', 'sm1}"); | 2509 // Format(instr, "vmovrrs'cond 'rd, 'rn, {'sm', 'sm1}"); |
2501 set_register(rd, get_sregister_bits(sm)); | 2510 set_register(rd, get_sregister_bits(sm)); |
2502 set_register(rn, get_sregister_bits(sm1)); | 2511 set_register(rn, get_sregister_bits(sm1)); |
2503 } else { | 2512 } else { |
2504 // Format(instr, "vmovsrr'cond {'sm, 'sm1}, 'rd', 'rn"); | 2513 // Format(instr, "vmovsrr'cond {'sm, 'sm1}, 'rd', 'rn"); |
2505 set_sregister_bits(sm, get_register(rd)); | 2514 set_sregister_bits(sm, get_register(rd)); |
2506 set_sregister_bits(sm1, get_register(rn)); | 2515 set_sregister_bits(sm1, get_register(rn)); |
2507 } | 2516 } |
2508 } else { | 2517 } else { |
2509 DRegister dm = instr->DmField(); | 2518 DRegister dm = instr->DmField(); |
2510 if (instr->Bit(20) == 1) { | 2519 if (instr->Bit(20) == 1) { |
2511 // Format(instr, "vmovrrd'cond 'rd, 'rn, 'dm"); | 2520 // Format(instr, "vmovrrd'cond 'rd, 'rn, 'dm"); |
2512 int64_t dm_val = get_dregister_bits(dm); | 2521 int64_t dm_val = get_dregister_bits(dm); |
2513 set_register(rd, Utils::Low32Bits(dm_val)); | 2522 set_register(rd, Utils::Low32Bits(dm_val)); |
2514 set_register(rn, Utils::High32Bits(dm_val)); | 2523 set_register(rn, Utils::High32Bits(dm_val)); |
2515 } else { | 2524 } else { |
2516 // Format(instr, "vmovdrr'cond 'dm, 'rd, 'rn"); | 2525 // Format(instr, "vmovdrr'cond 'dm, 'rd, 'rn"); |
2517 int64_t dm_val = Utils::LowHighTo64Bits(get_register(rd), | 2526 int64_t dm_val = |
2518 get_register(rn)); | 2527 Utils::LowHighTo64Bits(get_register(rd), get_register(rn)); |
2519 set_dregister_bits(dm, dm_val); | 2528 set_dregister_bits(dm, dm_val); |
2520 } | 2529 } |
2521 } | 2530 } |
2522 } else if (instr-> IsVFPLoadStore()) { | 2531 } else if (instr->IsVFPLoadStore()) { |
2523 Register rn = instr->RnField(); | 2532 Register rn = instr->RnField(); |
2524 int32_t addr = get_register(rn); | 2533 int32_t addr = get_register(rn); |
2525 int32_t imm_val = instr->Bits(0, 8) << 2; | 2534 int32_t imm_val = instr->Bits(0, 8) << 2; |
2526 if (instr->Bit(23) == 1) { | 2535 if (instr->Bit(23) == 1) { |
2527 addr += imm_val; | 2536 addr += imm_val; |
2528 } else { | 2537 } else { |
2529 addr -= imm_val; | 2538 addr -= imm_val; |
2530 } | 2539 } |
2531 if (IsIllegalAddress(addr)) { | 2540 if (IsIllegalAddress(addr)) { |
2532 HandleIllegalAccess(addr, instr); | 2541 HandleIllegalAccess(addr, instr); |
(...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2711 if (instr->Bit(6) == 0) { | 2720 if (instr->Bit(6) == 0) { |
2712 // Format(instr, "vaddd'cond 'dd, 'dn, 'dm"); | 2721 // Format(instr, "vaddd'cond 'dd, 'dn, 'dm"); |
2713 set_dregister(dd, get_dregister(dn) + get_dregister(dm)); | 2722 set_dregister(dd, get_dregister(dn) + get_dregister(dm)); |
2714 } else { | 2723 } else { |
2715 // Format(instr, "vsubd'cond 'dd, 'dn, 'dm"); | 2724 // Format(instr, "vsubd'cond 'dd, 'dn, 'dm"); |
2716 set_dregister(dd, get_dregister(dn) - get_dregister(dm)); | 2725 set_dregister(dd, get_dregister(dn) - get_dregister(dm)); |
2717 } | 2726 } |
2718 } | 2727 } |
2719 break; | 2728 break; |
2720 } | 2729 } |
2721 case 0xb: { // Other VFP data-processing instructions | 2730 case 0xb: { // Other VFP data-processing instructions |
2722 if (instr->Bit(6) == 0) { // vmov immediate | 2731 if (instr->Bit(6) == 0) { // vmov immediate |
2723 if (instr->Bit(8) == 0) { | 2732 if (instr->Bit(8) == 0) { |
2724 // Format(instr, "vmovs'cond 'sd, #'immf"); | 2733 // Format(instr, "vmovs'cond 'sd, #'immf"); |
2725 set_sregister(sd, instr->ImmFloatField()); | 2734 set_sregister(sd, instr->ImmFloatField()); |
2726 } else { | 2735 } else { |
2727 // Format(instr, "vmovd'cond 'dd, #'immd"); | 2736 // Format(instr, "vmovd'cond 'dd, #'immd"); |
2728 set_dregister(dd, instr->ImmDoubleField()); | 2737 set_dregister(dd, instr->ImmDoubleField()); |
2729 } | 2738 } |
2730 break; | 2739 break; |
2731 } | 2740 } |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2781 } | 2790 } |
2782 break; | 2791 break; |
2783 } | 2792 } |
2784 default: { | 2793 default: { |
2785 UnimplementedInstruction(instr); | 2794 UnimplementedInstruction(instr); |
2786 break; | 2795 break; |
2787 } | 2796 } |
2788 } | 2797 } |
2789 break; | 2798 break; |
2790 } | 2799 } |
2791 case 4: // vcmp, vcmpe | 2800 case 4: // vcmp, vcmpe |
2792 case 5: { // vcmp #0.0, vcmpe #0.0 | 2801 case 5: { // vcmp #0.0, vcmpe #0.0 |
2793 if (instr->Bit(7) == 1) { // vcmpe | 2802 if (instr->Bit(7) == 1) { // vcmpe |
2794 UnimplementedInstruction(instr); | 2803 UnimplementedInstruction(instr); |
2795 } else { | 2804 } else { |
2796 fp_n_flag_ = false; | 2805 fp_n_flag_ = false; |
2797 fp_z_flag_ = false; | 2806 fp_z_flag_ = false; |
2798 fp_c_flag_ = false; | 2807 fp_c_flag_ = false; |
2799 fp_v_flag_ = false; | 2808 fp_v_flag_ = false; |
2800 if (instr->Bit(8) == 0) { // vcmps | 2809 if (instr->Bit(8) == 0) { // vcmps |
2801 float sd_val = get_sregister(sd); | 2810 float sd_val = get_sregister(sd); |
2802 float sm_val; | 2811 float sm_val; |
(...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2945 } | 2954 } |
2946 int32_t sd_val; | 2955 int32_t sd_val; |
2947 if (instr->Bit(16) == 0) { | 2956 if (instr->Bit(16) == 0) { |
2948 sd_val = static_cast<int32_t>(ud_val); | 2957 sd_val = static_cast<int32_t>(ud_val); |
2949 } else { | 2958 } else { |
2950 sd_val = id_val; | 2959 sd_val = id_val; |
2951 } | 2960 } |
2952 set_sregister_bits(sd, sd_val); | 2961 set_sregister_bits(sd, sd_val); |
2953 break; | 2962 break; |
2954 } | 2963 } |
2955 case 2: // vcvtb, vcvtt | 2964 case 2: // vcvtb, vcvtt |
2956 case 3: // vcvtb, vcvtt | 2965 case 3: // vcvtb, vcvtt |
2957 case 9: // undefined | 2966 case 9: // undefined |
2958 case 10: // vcvt between floating-point and fixed-point | 2967 case 10: // vcvt between floating-point and fixed-point |
2959 case 11: // vcvt between floating-point and fixed-point | 2968 case 11: // vcvt between floating-point and fixed-point |
2960 case 14: // vcvt between floating-point and fixed-point | 2969 case 14: // vcvt between floating-point and fixed-point |
2961 case 15: // vcvt between floating-point and fixed-point | 2970 case 15: // vcvt between floating-point and fixed-point |
2962 default: { | 2971 default: { |
2963 UnimplementedInstruction(instr); | 2972 UnimplementedInstruction(instr); |
2964 break; | 2973 break; |
2965 } | 2974 } |
2966 } | 2975 } |
2967 } | 2976 } break; |
2968 break; | |
2969 } | 2977 } |
2970 } else { | 2978 } else { |
2971 // 8, 16, or 32-bit Transfer between ARM Core and VFP | 2979 // 8, 16, or 32-bit Transfer between ARM Core and VFP |
2972 if ((instr->Bits(21, 3) == 0) && (instr->Bit(8) == 0)) { | 2980 if ((instr->Bits(21, 3) == 0) && (instr->Bit(8) == 0)) { |
2973 Register rd = instr->RdField(); | 2981 Register rd = instr->RdField(); |
2974 SRegister sn = instr->SnField(); | 2982 SRegister sn = instr->SnField(); |
2975 if (instr->Bit(20) == 0) { | 2983 if (instr->Bit(20) == 0) { |
2976 // Format(instr, "vmovs'cond 'sn, 'rd"); | 2984 // Format(instr, "vmovs'cond 'sn, 'rd"); |
2977 set_sregister_bits(sn, get_register(rd)); | 2985 set_sregister_bits(sn, get_register(rd)); |
2978 } else { | 2986 } else { |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3012 } | 3020 } |
3013 } | 3021 } |
3014 } else { | 3022 } else { |
3015 UnimplementedInstruction(instr); | 3023 UnimplementedInstruction(instr); |
3016 } | 3024 } |
3017 } | 3025 } |
3018 | 3026 |
3019 | 3027 |
3020 static float arm_reciprocal_sqrt_estimate(float a) { | 3028 static float arm_reciprocal_sqrt_estimate(float a) { |
3021 // From the ARM Architecture Reference Manual A2-87. | 3029 // From the ARM Architecture Reference Manual A2-87. |
3022 if (isinf(a) || (fabs(a) >= exp2f(126))) return 0.0; | 3030 if (isinf(a) || (fabs(a) >= exp2f(126))) |
3023 else if (a == 0.0) return kPosInfinity; | 3031 return 0.0; |
3024 else if (isnan(a)) return a; | 3032 else if (a == 0.0) |
| 3033 return kPosInfinity; |
| 3034 else if (isnan(a)) |
| 3035 return a; |
3025 | 3036 |
3026 uint32_t a_bits = bit_cast<uint32_t, float>(a); | 3037 uint32_t a_bits = bit_cast<uint32_t, float>(a); |
3027 uint64_t scaled; | 3038 uint64_t scaled; |
3028 if (((a_bits >> 23) & 1) != 0) { | 3039 if (((a_bits >> 23) & 1) != 0) { |
3029 // scaled = '0 01111111101' : operand<22:0> : Zeros(29) | 3040 // scaled = '0 01111111101' : operand<22:0> : Zeros(29) |
3030 scaled = (static_cast<uint64_t>(0x3fd) << 52) | | 3041 scaled = (static_cast<uint64_t>(0x3fd) << 52) | |
3031 ((static_cast<uint64_t>(a_bits) & 0x7fffff) << 29); | 3042 ((static_cast<uint64_t>(a_bits) & 0x7fffff) << 29); |
3032 } else { | 3043 } else { |
3033 // scaled = '0 01111111110' : operand<22:0> : Zeros(29) | 3044 // scaled = '0 01111111110' : operand<22:0> : Zeros(29) |
3034 scaled = (static_cast<uint64_t>(0x3fe) << 52) | | 3045 scaled = (static_cast<uint64_t>(0x3fe) << 52) | |
(...skipping 17 matching lines...) Expand all Loading... |
3052 // range 0.5 <= a < 1.0 | 3063 // range 0.5 <= a < 1.0 |
3053 | 3064 |
3054 // a in units of 1/256 rounded down. | 3065 // a in units of 1/256 rounded down. |
3055 int32_t q1 = static_cast<int32_t>(scaled_d * 256.0); | 3066 int32_t q1 = static_cast<int32_t>(scaled_d * 256.0); |
3056 // reciprocal root r. | 3067 // reciprocal root r. |
3057 r = 1.0 / sqrt((static_cast<double>(q1) + 0.5) / 256.0); | 3068 r = 1.0 / sqrt((static_cast<double>(q1) + 0.5) / 256.0); |
3058 } | 3069 } |
3059 // r in units of 1/256 rounded to nearest. | 3070 // r in units of 1/256 rounded to nearest. |
3060 int32_t s = static_cast<int>(256.0 * r + 0.5); | 3071 int32_t s = static_cast<int>(256.0 * r + 0.5); |
3061 double estimate = static_cast<double>(s) / 256.0; | 3072 double estimate = static_cast<double>(s) / 256.0; |
3062 ASSERT((estimate >= 1.0) && (estimate <= (511.0/256.0))); | 3073 ASSERT((estimate >= 1.0) && (estimate <= (511.0 / 256.0))); |
3063 | 3074 |
3064 // result = 0 : result_exp<7:0> : estimate<51:29> | 3075 // result = 0 : result_exp<7:0> : estimate<51:29> |
3065 int32_t result_bits = ((result_exp & 0xff) << 23) | | 3076 int32_t result_bits = |
| 3077 ((result_exp & 0xff) << 23) | |
3066 ((bit_cast<uint64_t, double>(estimate) >> 29) & 0x7fffff); | 3078 ((bit_cast<uint64_t, double>(estimate) >> 29) & 0x7fffff); |
3067 return bit_cast<float, int32_t>(result_bits); | 3079 return bit_cast<float, int32_t>(result_bits); |
3068 } | 3080 } |
3069 | 3081 |
3070 | 3082 |
3071 static float arm_recip_estimate(float a) { | 3083 static float arm_recip_estimate(float a) { |
3072 // From the ARM Architecture Reference Manual A2-85. | 3084 // From the ARM Architecture Reference Manual A2-85. |
3073 if (isinf(a) || (fabs(a) >= exp2f(126))) return 0.0; | 3085 if (isinf(a) || (fabs(a) >= exp2f(126))) |
3074 else if (a == 0.0) return kPosInfinity; | 3086 return 0.0; |
3075 else if (isnan(a)) return a; | 3087 else if (a == 0.0) |
| 3088 return kPosInfinity; |
| 3089 else if (isnan(a)) |
| 3090 return a; |
3076 | 3091 |
3077 uint32_t a_bits = bit_cast<uint32_t, float>(a); | 3092 uint32_t a_bits = bit_cast<uint32_t, float>(a); |
3078 // scaled = '0011 1111 1110' : a<22:0> : Zeros(29) | 3093 // scaled = '0011 1111 1110' : a<22:0> : Zeros(29) |
3079 uint64_t scaled = (static_cast<uint64_t>(0x3fe) << 52) | | 3094 uint64_t scaled = (static_cast<uint64_t>(0x3fe) << 52) | |
3080 ((static_cast<uint64_t>(a_bits) & 0x7fffff) << 29); | 3095 ((static_cast<uint64_t>(a_bits) & 0x7fffff) << 29); |
3081 // result_exp = 253 - UInt(a<30:23>) | 3096 // result_exp = 253 - UInt(a<30:23>) |
3082 int32_t result_exp = 253 - ((a_bits >> 23) & 0xff); | 3097 int32_t result_exp = 253 - ((a_bits >> 23) & 0xff); |
3083 ASSERT((result_exp >= 1) && (result_exp <= 252)); | 3098 ASSERT((result_exp >= 1) && (result_exp <= 252)); |
3084 | 3099 |
3085 double scaled_d = bit_cast<double, uint64_t>(scaled); | 3100 double scaled_d = bit_cast<double, uint64_t>(scaled); |
3086 ASSERT((scaled_d >= 0.5) && (scaled_d < 1.0)); | 3101 ASSERT((scaled_d >= 0.5) && (scaled_d < 1.0)); |
3087 | 3102 |
3088 // a in units of 1/512 rounded down. | 3103 // a in units of 1/512 rounded down. |
3089 int32_t q = static_cast<int32_t>(scaled_d * 512.0); | 3104 int32_t q = static_cast<int32_t>(scaled_d * 512.0); |
3090 // reciprocal r. | 3105 // reciprocal r. |
3091 double r = 1.0 / ((static_cast<double>(q) + 0.5) / 512.0); | 3106 double r = 1.0 / ((static_cast<double>(q) + 0.5) / 512.0); |
3092 // r in units of 1/256 rounded to nearest. | 3107 // r in units of 1/256 rounded to nearest. |
3093 int32_t s = static_cast<int32_t>(256.0 * r + 0.5); | 3108 int32_t s = static_cast<int32_t>(256.0 * r + 0.5); |
3094 double estimate = static_cast<double>(s) / 256.0; | 3109 double estimate = static_cast<double>(s) / 256.0; |
3095 ASSERT((estimate >= 1.0) && (estimate <= (511.0/256.0))); | 3110 ASSERT((estimate >= 1.0) && (estimate <= (511.0 / 256.0))); |
3096 | 3111 |
3097 // result = sign : result_exp<7:0> : estimate<51:29> | 3112 // result = sign : result_exp<7:0> : estimate<51:29> |
3098 int32_t result_bits = | 3113 int32_t result_bits = |
3099 (a_bits & 0x80000000) | ((result_exp & 0xff) << 23) | | 3114 (a_bits & 0x80000000) | ((result_exp & 0xff) << 23) | |
3100 ((bit_cast<uint64_t, double>(estimate) >> 29) & 0x7fffff); | 3115 ((bit_cast<uint64_t, double>(estimate) >> 29) & 0x7fffff); |
3101 return bit_cast<float, int32_t>(result_bits); | 3116 return bit_cast<float, int32_t>(result_bits); |
3102 } | 3117 } |
3103 | 3118 |
3104 | 3119 |
3105 static void simd_value_swap(simd_value_t* s1, int i1, | 3120 static void simd_value_swap(simd_value_t* s1, |
3106 simd_value_t* s2, int i2) { | 3121 int i1, |
| 3122 simd_value_t* s2, |
| 3123 int i2) { |
3107 uint32_t tmp; | 3124 uint32_t tmp; |
3108 tmp = s1->data_[i1].u; | 3125 tmp = s1->data_[i1].u; |
3109 s1->data_[i1].u = s2->data_[i2].u; | 3126 s1->data_[i1].u = s2->data_[i2].u; |
3110 s2->data_[i2].u = tmp; | 3127 s2->data_[i2].u = tmp; |
3111 } | 3128 } |
3112 | 3129 |
3113 | 3130 |
3114 void Simulator::DecodeSIMDDataProcessing(Instr* instr) { | 3131 void Simulator::DecodeSIMDDataProcessing(Instr* instr) { |
3115 ASSERT(instr->ConditionField() == kSpecialCondition); | 3132 ASSERT(instr->ConditionField() == kSpecialCondition); |
3116 | 3133 |
(...skipping 220 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3337 // Format(instr, "vminqs 'qd, 'qn, 'qm"); | 3354 // Format(instr, "vminqs 'qd, 'qn, 'qm"); |
3338 for (int i = 0; i < 4; i++) { | 3355 for (int i = 0; i < 4; i++) { |
3339 s8d.data_[i].f = | 3356 s8d.data_[i].f = |
3340 s8n.data_[i].f <= s8m.data_[i].f ? s8n.data_[i].f : s8m.data_[i].f; | 3357 s8n.data_[i].f <= s8m.data_[i].f ? s8n.data_[i].f : s8m.data_[i].f; |
3341 } | 3358 } |
3342 } else if ((instr->Bits(8, 4) == 15) && (instr->Bit(4) == 0) && | 3359 } else if ((instr->Bits(8, 4) == 15) && (instr->Bit(4) == 0) && |
3343 (instr->Bits(20, 2) == 0) && (instr->Bits(23, 2) == 0)) { | 3360 (instr->Bits(20, 2) == 0) && (instr->Bits(23, 2) == 0)) { |
3344 // Format(instr, "vmaxqs 'qd, 'qn, 'qm"); | 3361 // Format(instr, "vmaxqs 'qd, 'qn, 'qm"); |
3345 for (int i = 0; i < 4; i++) { | 3362 for (int i = 0; i < 4; i++) { |
3346 s8d.data_[i].f = | 3363 s8d.data_[i].f = |
3347 s8n.data_[i].f >= s8m.data_[i].f ? s8n.data_[i].f : s8m.data_[i].f; | 3364 s8n.data_[i].f >= s8m.data_[i].f ? s8n.data_[i].f : s8m.data_[i].f; |
3348 } | 3365 } |
3349 } else if ((instr->Bits(8, 4) == 7) && (instr->Bit(4) == 0) && | 3366 } else if ((instr->Bits(8, 4) == 7) && (instr->Bit(4) == 0) && |
3350 (instr->Bits(20, 2) == 3) && (instr->Bits(23, 2) == 3) && | 3367 (instr->Bits(20, 2) == 3) && (instr->Bits(23, 2) == 3) && |
3351 (instr->Bit(7) == 0) && (instr->Bits(16, 4) == 9)) { | 3368 (instr->Bit(7) == 0) && (instr->Bits(16, 4) == 9)) { |
3352 // Format(instr, "vabsqs 'qd, 'qm"); | 3369 // Format(instr, "vabsqs 'qd, 'qm"); |
3353 for (int i = 0; i < 4; i++) { | 3370 for (int i = 0; i < 4; i++) { |
3354 s8d.data_[i].f = fabsf(s8m.data_[i].f); | 3371 s8d.data_[i].f = fabsf(s8m.data_[i].f); |
3355 } | 3372 } |
3356 } else if ((instr->Bits(8, 4) == 7) && (instr->Bit(4) == 0) && | 3373 } else if ((instr->Bits(8, 4) == 7) && (instr->Bit(4) == 0) && |
3357 (instr->Bits(20, 2) == 3) && (instr->Bits(23, 2) == 3) && | 3374 (instr->Bits(20, 2) == 3) && (instr->Bits(23, 2) == 3) && |
(...skipping 542 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3900 set_register(THR, reinterpret_cast<uword>(thread)); | 3917 set_register(THR, reinterpret_cast<uword>(thread)); |
3901 // Set the tag. | 3918 // Set the tag. |
3902 thread->set_vm_tag(VMTag::kDartTagId); | 3919 thread->set_vm_tag(VMTag::kDartTagId); |
3903 // Clear top exit frame. | 3920 // Clear top exit frame. |
3904 thread->set_top_exit_frame_info(0); | 3921 thread->set_top_exit_frame_info(0); |
3905 | 3922 |
3906 ASSERT(raw_exception != Object::null()); | 3923 ASSERT(raw_exception != Object::null()); |
3907 set_register(kExceptionObjectReg, bit_cast<int32_t>(raw_exception)); | 3924 set_register(kExceptionObjectReg, bit_cast<int32_t>(raw_exception)); |
3908 set_register(kStackTraceObjectReg, bit_cast<int32_t>(raw_stacktrace)); | 3925 set_register(kStackTraceObjectReg, bit_cast<int32_t>(raw_stacktrace)); |
3909 // Restore pool pointer. | 3926 // Restore pool pointer. |
3910 int32_t code = *reinterpret_cast<int32_t*>( | 3927 int32_t code = |
3911 fp + kPcMarkerSlotFromFp * kWordSize); | 3928 *reinterpret_cast<int32_t*>(fp + kPcMarkerSlotFromFp * kWordSize); |
3912 int32_t pp = *reinterpret_cast<int32_t*>( | 3929 int32_t pp = *reinterpret_cast<int32_t*>(code + Code::object_pool_offset() - |
3913 code + Code::object_pool_offset() - kHeapObjectTag); | 3930 kHeapObjectTag); |
3914 set_register(CODE_REG, code); | 3931 set_register(CODE_REG, code); |
3915 set_register(PP, pp); | 3932 set_register(PP, pp); |
3916 buf->Longjmp(); | 3933 buf->Longjmp(); |
3917 } | 3934 } |
3918 | 3935 |
3919 } // namespace dart | 3936 } // namespace dart |
3920 | 3937 |
3921 #endif // defined(USING_SIMULATOR) | 3938 #endif // defined(USING_SIMULATOR) |
3922 | 3939 |
3923 #endif // defined TARGET_ARCH_ARM | 3940 #endif // defined TARGET_ARCH_ARM |
OLD | NEW |