OLD | NEW |
1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, 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_ARM64) | 9 #if defined(TARGET_ARCH_ARM64) |
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_arm64.h" | 17 #include "vm/constants_arm64.h" |
18 #include "vm/disassembler.h" | 18 #include "vm/disassembler.h" |
19 #include "vm/lockers.h" | 19 #include "vm/lockers.h" |
20 #include "vm/native_arguments.h" | 20 #include "vm/native_arguments.h" |
21 #include "vm/stack_frame.h" | 21 #include "vm/stack_frame.h" |
22 #include "vm/os_thread.h" | 22 #include "vm/os_thread.h" |
23 | 23 |
24 namespace dart { | 24 namespace dart { |
25 | 25 |
26 DEFINE_FLAG(uint64_t, trace_sim_after, ULLONG_MAX, | 26 DEFINE_FLAG(uint64_t, |
| 27 trace_sim_after, |
| 28 ULLONG_MAX, |
27 "Trace simulator execution after instruction count reached."); | 29 "Trace simulator execution after instruction count reached."); |
28 DEFINE_FLAG(uint64_t, stop_sim_at, ULLONG_MAX, | 30 DEFINE_FLAG(uint64_t, |
| 31 stop_sim_at, |
| 32 ULLONG_MAX, |
29 "Instruction address or instruction count to stop simulator at."); | 33 "Instruction address or instruction count to stop simulator at."); |
30 | 34 |
31 | 35 |
32 // This macro provides a platform independent use of sscanf. The reason for | 36 // This macro provides a platform independent use of sscanf. The reason for |
33 // SScanF not being implemented in a platform independent way through | 37 // SScanF not being implemented in a platform independent way through |
34 // OS in the same way as SNPrint is that the Windows C Run-Time | 38 // OS in the same way as SNPrint is that the Windows C Run-Time |
35 // Library does not provide vsscanf. | 39 // Library does not provide vsscanf. |
36 #define SScanF sscanf // NOLINT | 40 #define SScanF sscanf // NOLINT |
37 | 41 |
38 | 42 |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
89 private: | 93 private: |
90 Simulator* sim_; | 94 Simulator* sim_; |
91 | 95 |
92 bool GetValue(char* desc, uint64_t* value); | 96 bool GetValue(char* desc, uint64_t* value); |
93 bool GetSValue(char* desc, uint32_t* value); | 97 bool GetSValue(char* desc, uint32_t* value); |
94 bool GetDValue(char* desc, uint64_t* value); | 98 bool GetDValue(char* desc, uint64_t* value); |
95 bool GetQValue(char* desc, simd_value_t* value); | 99 bool GetQValue(char* desc, simd_value_t* 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[] = { |
134 "r0", "r1", "r2", "r3", | 139 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", |
135 "r4", "r5", "r6", "r7", | 140 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", |
136 "r8", "r9", "r10", "r11", | 141 "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23", |
137 "r12", "r13", "r14", "r15", | 142 "r24", "r25", "r26", "r27", "r28", "r29", "r30", |
138 "r16", "r17", "r18", "r19", | |
139 "r20", "r21", "r22", "r23", | |
140 "r24", "r25", "r26", "r27", | |
141 "r28", "r29", "r30", | |
142 | 143 |
143 "ip0", "ip1", "pp", "ctx", "fp", "lr", "sp", "zr", | 144 "ip0", "ip1", "pp", "ctx", "fp", "lr", "sp", "zr", |
144 }; | 145 }; |
145 static const Register kRegisters[] = { | 146 static const Register kRegisters[] = { |
146 R0, R1, R2, R3, R4, R5, R6, R7, | 147 R0, R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, |
147 R8, R9, R10, R11, R12, R13, R14, R15, | 148 R11, R12, R13, R14, R15, R16, R17, R18, R19, R20, R21, |
148 R16, R17, R18, R19, R20, R21, R22, R23, | 149 R22, R23, R24, R25, R26, R27, R28, R29, R30, |
149 R24, R25, R26, R27, R28, R29, R30, | |
150 | 150 |
151 IP0, IP1, PP, CTX, FP, LR, R31, ZR, | 151 IP0, IP1, PP, CTX, FP, LR, R31, ZR, |
152 }; | 152 }; |
153 ASSERT(ARRAY_SIZE(kNames) == ARRAY_SIZE(kRegisters)); | 153 ASSERT(ARRAY_SIZE(kNames) == ARRAY_SIZE(kRegisters)); |
154 for (unsigned i = 0; i < ARRAY_SIZE(kNames); i++) { | 154 for (unsigned i = 0; i < ARRAY_SIZE(kNames); i++) { |
155 if (strcmp(kNames[i], name) == 0) { | 155 if (strcmp(kNames[i], name) == 0) { |
156 return kRegisters[i]; | 156 return kRegisters[i]; |
157 } | 157 } |
158 } | 158 } |
159 return kNoRegister; | 159 return kNoRegister; |
160 } | 160 } |
161 | 161 |
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
256 } | 256 } |
257 *value = *(reinterpret_cast<simd_value_t*>(addr)); | 257 *value = *(reinterpret_cast<simd_value_t*>(addr)); |
258 return true; | 258 return true; |
259 } | 259 } |
260 } | 260 } |
261 return false; | 261 return false; |
262 } | 262 } |
263 | 263 |
264 | 264 |
265 TokenPosition SimulatorDebugger::GetApproximateTokenIndex(const Code& code, | 265 TokenPosition SimulatorDebugger::GetApproximateTokenIndex(const Code& code, |
266 uword pc) { | 266 uword pc) { |
267 TokenPosition token_pos = TokenPosition::kNoSource; | 267 TokenPosition token_pos = TokenPosition::kNoSource; |
268 uword pc_offset = pc - code.PayloadStart(); | 268 uword pc_offset = pc - code.PayloadStart(); |
269 const PcDescriptors& descriptors = | 269 const PcDescriptors& descriptors = |
270 PcDescriptors::Handle(code.pc_descriptors()); | 270 PcDescriptors::Handle(code.pc_descriptors()); |
271 PcDescriptors::Iterator iter(descriptors, RawPcDescriptors::kAnyKind); | 271 PcDescriptors::Iterator iter(descriptors, RawPcDescriptors::kAnyKind); |
272 while (iter.MoveNext()) { | 272 while (iter.MoveNext()) { |
273 if (iter.PcOffset() == pc_offset) { | 273 if (iter.PcOffset() == pc_offset) { |
274 return iter.TokenPos(); | 274 return iter.TokenPos(); |
275 } else if (!token_pos.IsReal() && (iter.PcOffset() > pc_offset)) { | 275 } else if (!token_pos.IsReal() && (iter.PcOffset() > pc_offset)) { |
276 token_pos = iter.TokenPos(); | 276 token_pos = iter.TokenPos(); |
277 } | 277 } |
278 } | 278 } |
279 return token_pos; | 279 return token_pos; |
280 } | 280 } |
281 | 281 |
282 | 282 |
283 void SimulatorDebugger::PrintDartFrame(uword pc, uword fp, uword sp, | 283 void SimulatorDebugger::PrintDartFrame(uword pc, |
| 284 uword fp, |
| 285 uword sp, |
284 const Function& function, | 286 const Function& function, |
285 TokenPosition token_pos, | 287 TokenPosition token_pos, |
286 bool is_optimized, | 288 bool is_optimized, |
287 bool is_inlined) { | 289 bool is_inlined) { |
288 const Script& script = Script::Handle(function.script()); | 290 const Script& script = Script::Handle(function.script()); |
289 const String& func_name = String::Handle(function.QualifiedScrubbedName()); | 291 const String& func_name = String::Handle(function.QualifiedScrubbedName()); |
290 const String& url = String::Handle(script.url()); | 292 const String& url = String::Handle(script.url()); |
291 intptr_t line = -1; | 293 intptr_t line = -1; |
292 intptr_t column = -1; | 294 intptr_t column = -1; |
293 if (token_pos.IsReal()) { | 295 if (token_pos.IsReal()) { |
294 script.GetTokenLocation(token_pos, &line, &column); | 296 script.GetTokenLocation(token_pos, &line, &column); |
295 } | 297 } |
296 OS::Print("pc=0x%" Px " fp=0x%" Px " sp=0x%" Px " %s%s (%s:%" Pd | 298 OS::Print( |
297 ":%" Pd ")\n", | 299 "pc=0x%" Px " fp=0x%" Px " sp=0x%" Px " %s%s (%s:%" Pd ":%" Pd ")\n", pc, |
298 pc, fp, sp, | 300 fp, sp, is_optimized ? (is_inlined ? "inlined " : "optimized ") : "", |
299 is_optimized ? (is_inlined ? "inlined " : "optimized ") : "", | 301 func_name.ToCString(), url.ToCString(), line, column); |
300 func_name.ToCString(), | |
301 url.ToCString(), | |
302 line, column); | |
303 } | 302 } |
304 | 303 |
305 | 304 |
306 void SimulatorDebugger::PrintBacktrace() { | 305 void SimulatorDebugger::PrintBacktrace() { |
307 StackFrameIterator frames(sim_->get_register(FP), | 306 StackFrameIterator frames(sim_->get_register(FP), sim_->get_register(SP), |
308 sim_->get_register(SP), | |
309 sim_->get_pc(), | 307 sim_->get_pc(), |
310 StackFrameIterator::kDontValidateFrames); | 308 StackFrameIterator::kDontValidateFrames); |
311 StackFrame* frame = frames.NextFrame(); | 309 StackFrame* frame = frames.NextFrame(); |
312 ASSERT(frame != NULL); | 310 ASSERT(frame != NULL); |
313 Function& function = Function::Handle(); | 311 Function& function = Function::Handle(); |
314 Function& inlined_function = Function::Handle(); | 312 Function& inlined_function = Function::Handle(); |
315 Code& code = Code::Handle(); | 313 Code& code = Code::Handle(); |
316 Code& unoptimized_code = Code::Handle(); | 314 Code& unoptimized_code = Code::Handle(); |
317 while (frame != NULL) { | 315 while (frame != NULL) { |
318 if (frame->IsDartFrame()) { | 316 if (frame->IsDartFrame()) { |
319 code = frame->LookupDartCode(); | 317 code = frame->LookupDartCode(); |
320 function = code.function(); | 318 function = code.function(); |
321 if (code.is_optimized()) { | 319 if (code.is_optimized()) { |
322 // For optimized frames, extract all the inlined functions if any | 320 // For optimized frames, extract all the inlined functions if any |
323 // into the stack trace. | 321 // into the stack trace. |
324 InlinedFunctionsIterator it(code, frame->pc()); | 322 InlinedFunctionsIterator it(code, frame->pc()); |
325 while (!it.Done()) { | 323 while (!it.Done()) { |
326 // Print each inlined frame with its pc in the corresponding | 324 // Print each inlined frame with its pc in the corresponding |
327 // unoptimized frame. | 325 // unoptimized frame. |
328 inlined_function = it.function(); | 326 inlined_function = it.function(); |
329 unoptimized_code = it.code(); | 327 unoptimized_code = it.code(); |
330 uword unoptimized_pc = it.pc(); | 328 uword unoptimized_pc = it.pc(); |
331 it.Advance(); | 329 it.Advance(); |
332 if (!it.Done()) { | 330 if (!it.Done()) { |
333 PrintDartFrame(unoptimized_pc, frame->fp(), frame->sp(), | 331 PrintDartFrame( |
334 inlined_function, | 332 unoptimized_pc, frame->fp(), frame->sp(), inlined_function, |
335 GetApproximateTokenIndex(unoptimized_code, | 333 GetApproximateTokenIndex(unoptimized_code, unoptimized_pc), |
336 unoptimized_pc), | 334 true, true); |
337 true, true); | |
338 } | 335 } |
339 } | 336 } |
340 // Print the optimized inlining frame below. | 337 // Print the optimized inlining frame below. |
341 } | 338 } |
342 PrintDartFrame(frame->pc(), frame->fp(), frame->sp(), | 339 PrintDartFrame(frame->pc(), frame->fp(), frame->sp(), function, |
343 function, | |
344 GetApproximateTokenIndex(code, frame->pc()), | 340 GetApproximateTokenIndex(code, frame->pc()), |
345 code.is_optimized(), false); | 341 code.is_optimized(), false); |
346 } else { | 342 } else { |
347 OS::Print("pc=0x%" Px " fp=0x%" Px " sp=0x%" Px " %s frame\n", | 343 OS::Print("pc=0x%" Px " fp=0x%" Px " sp=0x%" Px " %s frame\n", |
348 frame->pc(), frame->fp(), frame->sp(), | 344 frame->pc(), frame->fp(), frame->sp(), |
349 frame->IsEntryFrame() ? "entry" : | 345 frame->IsEntryFrame() |
350 frame->IsExitFrame() ? "exit" : | 346 ? "entry" |
351 frame->IsStubFrame() ? "stub" : "invalid"); | 347 : frame->IsExitFrame() |
| 348 ? "exit" |
| 349 : frame->IsStubFrame() ? "stub" : "invalid"); |
352 } | 350 } |
353 frame = frames.NextFrame(); | 351 frame = frames.NextFrame(); |
354 } | 352 } |
355 } | 353 } |
356 | 354 |
357 | 355 |
358 bool SimulatorDebugger::SetBreakpoint(Instr* breakpc) { | 356 bool SimulatorDebugger::SetBreakpoint(Instr* breakpc) { |
359 // Check if a breakpoint can be set. If not return without any side-effects. | 357 // Check if a breakpoint can be set. If not return without any side-effects. |
360 if (sim_->break_pc_ != NULL) { | 358 if (sim_->break_pc_ != NULL) { |
361 return false; | 359 return false; |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
436 FATAL("ReadLine failed"); | 434 FATAL("ReadLine failed"); |
437 } else { | 435 } else { |
438 // Use sscanf to parse the individual parts of the command line. At the | 436 // Use sscanf to parse the individual parts of the command line. At the |
439 // moment no command expects more than two parameters. | 437 // moment no command expects more than two parameters. |
440 int args = SScanF(line, | 438 int args = SScanF(line, |
441 "%" XSTR(COMMAND_SIZE) "s " | 439 "%" XSTR(COMMAND_SIZE) "s " |
442 "%" XSTR(ARG_SIZE) "s " | 440 "%" XSTR(ARG_SIZE) "s " |
443 "%" XSTR(ARG_SIZE) "s", | 441 "%" XSTR(ARG_SIZE) "s", |
444 cmd, arg1, arg2); | 442 cmd, arg1, arg2); |
445 if ((strcmp(cmd, "h") == 0) || (strcmp(cmd, "help") == 0)) { | 443 if ((strcmp(cmd, "h") == 0) || (strcmp(cmd, "help") == 0)) { |
446 OS::Print("c/cont -- continue execution\n" | 444 OS::Print( |
447 "disasm -- disassemble instrs at current pc location\n" | 445 "c/cont -- continue execution\n" |
448 " other variants are:\n" | 446 "disasm -- disassemble instrs at current pc location\n" |
449 " disasm <address>\n" | 447 " other variants are:\n" |
450 " disasm <address> <number_of_instructions>\n" | 448 " disasm <address>\n" |
451 " by default 10 instrs are disassembled\n" | 449 " disasm <address> <number_of_instructions>\n" |
452 "del -- delete breakpoints\n" | 450 " by default 10 instrs are disassembled\n" |
453 "flags -- print flag values\n" | 451 "del -- delete breakpoints\n" |
454 "gdb -- transfer control to gdb\n" | 452 "flags -- print flag values\n" |
455 "h/help -- print this help string\n" | 453 "gdb -- transfer control to gdb\n" |
456 "break <address> -- set break point at specified address\n" | 454 "h/help -- print this help string\n" |
457 "p/print <reg or icount or value or *addr> -- print integer\n" | 455 "break <address> -- set break point at specified address\n" |
458 "pf/printfloat <vreg or *addr> --print float value\n" | 456 "p/print <reg or icount or value or *addr> -- print integer\n" |
459 "pd/printdouble <vreg or *addr> -- print double value\n" | 457 "pf/printfloat <vreg or *addr> --print float value\n" |
460 "pq/printquad <vreg or *addr> -- print vector register\n" | 458 "pd/printdouble <vreg or *addr> -- print double value\n" |
461 "po/printobject <*reg or *addr> -- print object\n" | 459 "pq/printquad <vreg or *addr> -- print vector register\n" |
462 "si/stepi -- single step an instruction\n" | 460 "po/printobject <*reg or *addr> -- print object\n" |
463 "trace -- toggle execution tracing mode\n" | 461 "si/stepi -- single step an instruction\n" |
464 "bt -- print backtrace\n" | 462 "trace -- toggle execution tracing mode\n" |
465 "unstop -- if current pc is a stop instr make it a nop\n" | 463 "bt -- print backtrace\n" |
466 "q/quit -- Quit the debugger and exit the program\n"); | 464 "unstop -- if current pc is a stop instr make it a nop\n" |
| 465 "q/quit -- Quit the debugger and exit the program\n"); |
467 } else if ((strcmp(cmd, "quit") == 0) || (strcmp(cmd, "q") == 0)) { | 466 } else if ((strcmp(cmd, "quit") == 0) || (strcmp(cmd, "q") == 0)) { |
468 OS::Print("Quitting\n"); | 467 OS::Print("Quitting\n"); |
469 OS::Exit(0); | 468 OS::Exit(0); |
470 } else if ((strcmp(cmd, "si") == 0) || (strcmp(cmd, "stepi") == 0)) { | 469 } else if ((strcmp(cmd, "si") == 0) || (strcmp(cmd, "stepi") == 0)) { |
471 sim_->InstructionDecode(reinterpret_cast<Instr*>(sim_->get_pc())); | 470 sim_->InstructionDecode(reinterpret_cast<Instr*>(sim_->get_pc())); |
472 } else if ((strcmp(cmd, "c") == 0) || (strcmp(cmd, "cont") == 0)) { | 471 } else if ((strcmp(cmd, "c") == 0) || (strcmp(cmd, "cont") == 0)) { |
473 // Execute the one instruction we broke at with breakpoints disabled. | 472 // Execute the one instruction we broke at with breakpoints disabled. |
474 sim_->InstructionDecode(reinterpret_cast<Instr*>(sim_->get_pc())); | 473 sim_->InstructionDecode(reinterpret_cast<Instr*>(sim_->get_pc())); |
475 // Leave the debugger shell. | 474 // Leave the debugger shell. |
476 done = true; | 475 done = true; |
477 } else if ((strcmp(cmd, "p") == 0) || (strcmp(cmd, "print") == 0)) { | 476 } else if ((strcmp(cmd, "p") == 0) || (strcmp(cmd, "print") == 0)) { |
478 if (args == 2) { | 477 if (args == 2) { |
479 uint64_t value; | 478 uint64_t value; |
480 if (strcmp(arg1, "icount") == 0) { | 479 if (strcmp(arg1, "icount") == 0) { |
481 value = sim_->get_icount(); | 480 value = sim_->get_icount(); |
482 OS::Print("icount: %" Pu64 " 0x%" Px64 "\n", value, value); | 481 OS::Print("icount: %" Pu64 " 0x%" Px64 "\n", value, value); |
483 } else if (GetValue(arg1, &value)) { | 482 } else if (GetValue(arg1, &value)) { |
484 OS::Print("%s: %" Pu64 " 0x%" Px64 "\n", arg1, value, value); | 483 OS::Print("%s: %" Pu64 " 0x%" Px64 "\n", arg1, value, value); |
485 } else { | 484 } else { |
486 OS::Print("%s unrecognized\n", arg1); | 485 OS::Print("%s unrecognized\n", arg1); |
487 } | 486 } |
488 } else { | 487 } else { |
489 OS::Print("print <reg or icount or value or *addr>\n"); | 488 OS::Print("print <reg or icount or value or *addr>\n"); |
490 } | 489 } |
491 } else if ((strcmp(cmd, "pf") == 0) || | 490 } else if ((strcmp(cmd, "pf") == 0) || (strcmp(cmd, "printfloat") == 0)) { |
492 (strcmp(cmd, "printfloat") == 0)) { | |
493 if (args == 2) { | 491 if (args == 2) { |
494 uint32_t value; | 492 uint32_t value; |
495 if (GetSValue(arg1, &value)) { | 493 if (GetSValue(arg1, &value)) { |
496 float svalue = bit_cast<float, uint32_t>(value); | 494 float svalue = bit_cast<float, uint32_t>(value); |
497 OS::Print("%s: %d 0x%x %.8g\n", | 495 OS::Print("%s: %d 0x%x %.8g\n", arg1, value, value, svalue); |
498 arg1, value, value, svalue); | |
499 } else { | 496 } else { |
500 OS::Print("%s unrecognized\n", arg1); | 497 OS::Print("%s unrecognized\n", arg1); |
501 } | 498 } |
502 } else { | 499 } else { |
503 OS::Print("printfloat <vreg or *addr>\n"); | 500 OS::Print("printfloat <vreg or *addr>\n"); |
504 } | 501 } |
505 } else if ((strcmp(cmd, "pd") == 0) || | 502 } else if ((strcmp(cmd, "pd") == 0) || |
506 (strcmp(cmd, "printdouble") == 0)) { | 503 (strcmp(cmd, "printdouble") == 0)) { |
507 if (args == 2) { | 504 if (args == 2) { |
508 uint64_t long_value; | 505 uint64_t long_value; |
509 if (GetDValue(arg1, &long_value)) { | 506 if (GetDValue(arg1, &long_value)) { |
510 double dvalue = bit_cast<double, uint64_t>(long_value); | 507 double dvalue = bit_cast<double, uint64_t>(long_value); |
511 OS::Print("%s: %" Pu64 " 0x%" Px64 " %.8g\n", | 508 OS::Print("%s: %" Pu64 " 0x%" Px64 " %.8g\n", arg1, long_value, |
512 arg1, long_value, long_value, dvalue); | 509 long_value, dvalue); |
513 } else { | 510 } else { |
514 OS::Print("%s unrecognized\n", arg1); | 511 OS::Print("%s unrecognized\n", arg1); |
515 } | 512 } |
516 } else { | 513 } else { |
517 OS::Print("printdouble <vreg or *addr>\n"); | 514 OS::Print("printdouble <vreg or *addr>\n"); |
518 } | 515 } |
519 } else if ((strcmp(cmd, "pq") == 0) || | 516 } else if ((strcmp(cmd, "pq") == 0) || (strcmp(cmd, "printquad") == 0)) { |
520 (strcmp(cmd, "printquad") == 0)) { | |
521 if (args == 2) { | 517 if (args == 2) { |
522 simd_value_t quad_value; | 518 simd_value_t quad_value; |
523 if (GetQValue(arg1, &quad_value)) { | 519 if (GetQValue(arg1, &quad_value)) { |
524 const int64_t d0 = quad_value.bits.i64[0]; | 520 const int64_t d0 = quad_value.bits.i64[0]; |
525 const int64_t d1 = quad_value.bits.i64[1]; | 521 const int64_t d1 = quad_value.bits.i64[1]; |
526 const double dval0 = bit_cast<double, int64_t>(d0); | 522 const double dval0 = bit_cast<double, int64_t>(d0); |
527 const double dval1 = bit_cast<double, int64_t>(d1); | 523 const double dval1 = bit_cast<double, int64_t>(d1); |
528 const int32_t s0 = quad_value.bits.i32[0]; | 524 const int32_t s0 = quad_value.bits.i32[0]; |
529 const int32_t s1 = quad_value.bits.i32[1]; | 525 const int32_t s1 = quad_value.bits.i32[1]; |
530 const int32_t s2 = quad_value.bits.i32[2]; | 526 const int32_t s2 = quad_value.bits.i32[2]; |
(...skipping 17 matching lines...) Expand all Loading... |
548 } else if ((strcmp(cmd, "po") == 0) || | 544 } else if ((strcmp(cmd, "po") == 0) || |
549 (strcmp(cmd, "printobject") == 0)) { | 545 (strcmp(cmd, "printobject") == 0)) { |
550 if (args == 2) { | 546 if (args == 2) { |
551 uint64_t value; | 547 uint64_t value; |
552 // Make the dereferencing '*' optional. | 548 // Make the dereferencing '*' optional. |
553 if (((arg1[0] == '*') && GetValue(arg1 + 1, &value)) || | 549 if (((arg1[0] == '*') && GetValue(arg1 + 1, &value)) || |
554 GetValue(arg1, &value)) { | 550 GetValue(arg1, &value)) { |
555 if (Isolate::Current()->heap()->Contains(value)) { | 551 if (Isolate::Current()->heap()->Contains(value)) { |
556 OS::Print("%s: \n", arg1); | 552 OS::Print("%s: \n", arg1); |
557 #if defined(DEBUG) | 553 #if defined(DEBUG) |
558 const Object& obj = Object::Handle( | 554 const Object& obj = |
559 reinterpret_cast<RawObject*>(value)); | 555 Object::Handle(reinterpret_cast<RawObject*>(value)); |
560 obj.Print(); | 556 obj.Print(); |
561 #endif // defined(DEBUG) | 557 #endif // defined(DEBUG) |
562 } else { | 558 } else { |
563 OS::Print("0x%" Px64 " is not an object reference\n", value); | 559 OS::Print("0x%" Px64 " is not an object reference\n", value); |
564 } | 560 } |
565 } else { | 561 } else { |
566 OS::Print("%s unrecognized\n", arg1); | 562 OS::Print("%s unrecognized\n", arg1); |
567 } | 563 } |
568 } else { | 564 } else { |
569 OS::Print("printobject <*reg or *addr>\n"); | 565 OS::Print("printobject <*reg or *addr>\n"); |
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
680 OS::Print("%s", prompt); | 676 OS::Print("%s", prompt); |
681 while (keep_going) { | 677 while (keep_going) { |
682 if (fgets(line_buf, sizeof(line_buf), stdin) == NULL) { | 678 if (fgets(line_buf, sizeof(line_buf), stdin) == NULL) { |
683 // fgets got an error. Just give up. | 679 // fgets got an error. Just give up. |
684 if (result != NULL) { | 680 if (result != NULL) { |
685 delete[] result; | 681 delete[] result; |
686 } | 682 } |
687 return NULL; | 683 return NULL; |
688 } | 684 } |
689 intptr_t len = strlen(line_buf); | 685 intptr_t len = strlen(line_buf); |
690 if (len > 1 && | 686 if (len > 1 && line_buf[len - 2] == '\\' && line_buf[len - 1] == '\n') { |
691 line_buf[len - 2] == '\\' && | |
692 line_buf[len - 1] == '\n') { | |
693 // When we read a line that ends with a "\" we remove the escape and | 687 // When we read a line that ends with a "\" we remove the escape and |
694 // append the remainder. | 688 // append the remainder. |
695 line_buf[len - 2] = '\n'; | 689 line_buf[len - 2] = '\n'; |
696 line_buf[len - 1] = 0; | 690 line_buf[len - 1] = 0; |
697 len -= 1; | 691 len -= 1; |
698 } else if ((len > 0) && (line_buf[len - 1] == '\n')) { | 692 } else if ((len > 0) && (line_buf[len - 1] == '\n')) { |
699 // Since we read a new line we are done reading the line. This | 693 // Since we read a new line we are done reading the line. This |
700 // will exit the loop after copying this buffer into the result. | 694 // will exit the loop after copying this buffer into the result. |
701 keep_going = false; | 695 keep_going = false; |
702 } | 696 } |
(...skipping 25 matching lines...) Expand all Loading... |
728 offset += len; | 722 offset += len; |
729 } | 723 } |
730 ASSERT(result != NULL); | 724 ASSERT(result != NULL); |
731 result[offset] = '\0'; | 725 result[offset] = '\0'; |
732 return result; | 726 return result; |
733 } | 727 } |
734 | 728 |
735 | 729 |
736 // Synchronization primitives support. | 730 // Synchronization primitives support. |
737 Mutex* Simulator::exclusive_access_lock_ = NULL; | 731 Mutex* Simulator::exclusive_access_lock_ = NULL; |
738 Simulator::AddressTag Simulator::exclusive_access_state_[kNumAddressTags] = | 732 Simulator::AddressTag Simulator::exclusive_access_state_[kNumAddressTags] = { |
739 {{NULL, 0}}; | 733 {NULL, 0}}; |
740 int Simulator::next_address_tag_ = 0; | 734 int Simulator::next_address_tag_ = 0; |
741 | 735 |
742 | 736 |
743 void Simulator::InitOnce() { | 737 void Simulator::InitOnce() { |
744 // Setup exclusive access state lock. | 738 // Setup exclusive access state lock. |
745 exclusive_access_lock_ = new Mutex(); | 739 exclusive_access_lock_ = new Mutex(); |
746 } | 740 } |
747 | 741 |
748 | 742 |
749 Simulator::Simulator() { | 743 Simulator::Simulator() { |
750 // Setup simulator support first. Some of this information is needed to | 744 // Setup simulator support first. Some of this information is needed to |
751 // setup the architecture state. | 745 // setup the architecture state. |
752 // We allocate the stack here, the size is computed as the sum of | 746 // We allocate the stack here, the size is computed as the sum of |
753 // the size specified by the user and the buffer space needed for | 747 // the size specified by the user and the buffer space needed for |
754 // handling stack overflow exceptions. To be safe in potential | 748 // handling stack overflow exceptions. To be safe in potential |
755 // stack underflows we also add some underflow buffer space. | 749 // stack underflows we also add some underflow buffer space. |
756 stack_ = new char[(OSThread::GetSpecifiedStackSize() + | 750 stack_ = |
757 OSThread::kStackSizeBuffer + | 751 new char[(OSThread::GetSpecifiedStackSize() + OSThread::kStackSizeBuffer + |
758 kSimulatorStackUnderflowSize)]; | 752 kSimulatorStackUnderflowSize)]; |
759 pc_modified_ = false; | 753 pc_modified_ = false; |
760 icount_ = 0; | 754 icount_ = 0; |
761 break_pc_ = NULL; | 755 break_pc_ = NULL; |
762 break_instr_ = 0; | 756 break_instr_ = 0; |
763 last_setjmp_buffer_ = NULL; | 757 last_setjmp_buffer_ = NULL; |
764 top_exit_frame_info_ = 0; | 758 top_exit_frame_info_ = 0; |
765 | 759 |
766 // Setup architecture state. | 760 // Setup architecture state. |
767 // All registers are initialized to zero to start with. | 761 // All registers are initialized to zero to start with. |
768 for (int i = 0; i < kNumberOfCpuRegisters; i++) { | 762 for (int i = 0; i < kNumberOfCpuRegisters; i++) { |
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
850 : external_function_(external_function), | 844 : external_function_(external_function), |
851 call_kind_(call_kind), | 845 call_kind_(call_kind), |
852 argument_count_(argument_count), | 846 argument_count_(argument_count), |
853 hlt_instruction_(Instr::kSimulatorRedirectInstruction), | 847 hlt_instruction_(Instr::kSimulatorRedirectInstruction), |
854 next_(list_) { | 848 next_(list_) { |
855 // Atomically prepend this element to the front of the global list. | 849 // Atomically prepend this element to the front of the global list. |
856 // Note: Since elements are never removed, there is no ABA issue. | 850 // Note: Since elements are never removed, there is no ABA issue. |
857 Redirection* list_head = list_; | 851 Redirection* list_head = list_; |
858 do { | 852 do { |
859 next_ = list_head; | 853 next_ = list_head; |
860 list_head = reinterpret_cast<Redirection*>( | 854 list_head = |
861 AtomicOperations::CompareAndSwapWord( | 855 reinterpret_cast<Redirection*>(AtomicOperations::CompareAndSwapWord( |
862 reinterpret_cast<uword*>(&list_), | 856 reinterpret_cast<uword*>(&list_), reinterpret_cast<uword>(next_), |
863 reinterpret_cast<uword>(next_), | |
864 reinterpret_cast<uword>(this))); | 857 reinterpret_cast<uword>(this))); |
865 } while (list_head != next_); | 858 } while (list_head != next_); |
866 } | 859 } |
867 | 860 |
868 uword external_function_; | 861 uword external_function_; |
869 Simulator::CallKind call_kind_; | 862 Simulator::CallKind call_kind_; |
870 int argument_count_; | 863 int argument_count_; |
871 uint32_t hlt_instruction_; | 864 uint32_t hlt_instruction_; |
872 Redirection* next_; | 865 Redirection* next_; |
873 static Redirection* list_; | 866 static Redirection* list_; |
(...skipping 22 matching lines...) Expand all Loading... |
896 Simulator* simulator = Isolate::Current()->simulator(); | 889 Simulator* simulator = Isolate::Current()->simulator(); |
897 if (simulator == NULL) { | 890 if (simulator == NULL) { |
898 simulator = new Simulator(); | 891 simulator = new Simulator(); |
899 Isolate::Current()->set_simulator(simulator); | 892 Isolate::Current()->set_simulator(simulator); |
900 } | 893 } |
901 return simulator; | 894 return simulator; |
902 } | 895 } |
903 | 896 |
904 | 897 |
905 // Sets the register in the architecture state. | 898 // Sets the register in the architecture state. |
906 void Simulator::set_register( | 899 void Simulator::set_register(Instr* instr, |
907 Instr* instr, Register reg, int64_t value, R31Type r31t) { | 900 Register reg, |
| 901 int64_t value, |
| 902 R31Type r31t) { |
908 // Register is in range. | 903 // Register is in range. |
909 ASSERT((reg >= 0) && (reg < kNumberOfCpuRegisters)); | 904 ASSERT((reg >= 0) && (reg < kNumberOfCpuRegisters)); |
910 ASSERT(instr == NULL || reg != R18); // R18 is globally reserved on iOS. | 905 ASSERT(instr == NULL || reg != R18); // R18 is globally reserved on iOS. |
911 if ((reg != R31) || (r31t != R31IsZR)) { | 906 if ((reg != R31) || (r31t != R31IsZR)) { |
912 registers_[reg] = value; | 907 registers_[reg] = value; |
913 // If we're setting CSP, make sure it is 16-byte aligned. In truth, CSP | 908 // If we're setting CSP, make sure it is 16-byte aligned. In truth, CSP |
914 // can store addresses that are not 16-byte aligned, but loads and stores | 909 // can store addresses that are not 16-byte aligned, but loads and stores |
915 // are not allowed through CSP when it is not aligned. Thus, this check is | 910 // are not allowed through CSP when it is not aligned. Thus, this check is |
916 // more conservative that necessary. However, it will likely be more | 911 // more conservative that necessary. However, it will likely be more |
917 // useful to find the program locations where CSP is set to a bad value, | 912 // useful to find the program locations where CSP is set to a bad value, |
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1013 | 1008 |
1014 int64_t Simulator::get_last_pc() const { | 1009 int64_t Simulator::get_last_pc() const { |
1015 return last_pc_; | 1010 return last_pc_; |
1016 } | 1011 } |
1017 | 1012 |
1018 | 1013 |
1019 void Simulator::HandleIllegalAccess(uword addr, Instr* instr) { | 1014 void Simulator::HandleIllegalAccess(uword addr, Instr* instr) { |
1020 uword fault_pc = get_pc(); | 1015 uword fault_pc = get_pc(); |
1021 uword last_pc = get_last_pc(); | 1016 uword last_pc = get_last_pc(); |
1022 char buffer[128]; | 1017 char buffer[128]; |
1023 snprintf(buffer, sizeof(buffer), | 1018 snprintf(buffer, sizeof(buffer), "illegal memory access at 0x%" Px |
1024 "illegal memory access at 0x%" Px ", pc=0x%" Px ", last_pc=0x%" Px"\n", | 1019 ", pc=0x%" Px ", last_pc=0x%" Px "\n", |
1025 addr, fault_pc, last_pc); | 1020 addr, fault_pc, last_pc); |
1026 SimulatorDebugger dbg(this); | 1021 SimulatorDebugger dbg(this); |
1027 dbg.Stop(instr, buffer); | 1022 dbg.Stop(instr, buffer); |
1028 // The debugger will return control in non-interactive mode. | 1023 // The debugger will return control in non-interactive mode. |
1029 FATAL("Cannot continue execution after illegal memory access."); | 1024 FATAL("Cannot continue execution after illegal memory access."); |
1030 } | 1025 } |
1031 | 1026 |
1032 | 1027 |
1033 // The ARMv8 manual advises that an unaligned access may generate a fault, | 1028 // The ARMv8 manual advises that an unaligned access may generate a fault, |
1034 // and if not, will likely take a number of additional cycles to execute, | 1029 // and if not, will likely take a number of additional cycles to execute, |
1035 // so let's just not generate any. | 1030 // so let's just not generate any. |
1036 void Simulator::UnalignedAccess(const char* msg, uword addr, Instr* instr) { | 1031 void Simulator::UnalignedAccess(const char* msg, uword addr, Instr* instr) { |
1037 char buffer[128]; | 1032 char buffer[128]; |
1038 snprintf(buffer, sizeof(buffer), | 1033 snprintf(buffer, sizeof(buffer), "unaligned %s at 0x%" Px ", pc=%p\n", msg, |
1039 "unaligned %s at 0x%" Px ", pc=%p\n", msg, addr, instr); | 1034 addr, instr); |
1040 SimulatorDebugger dbg(this); | 1035 SimulatorDebugger dbg(this); |
1041 dbg.Stop(instr, buffer); | 1036 dbg.Stop(instr, buffer); |
1042 // The debugger will not be able to single step past this instruction, but | 1037 // The debugger will not be able to single step past this instruction, but |
1043 // it will be possible to disassemble the code and inspect registers. | 1038 // it will be possible to disassemble the code and inspect registers. |
1044 FATAL("Cannot continue execution after unaligned access."); | 1039 FATAL("Cannot continue execution after unaligned access."); |
1045 } | 1040 } |
1046 | 1041 |
1047 | 1042 |
1048 void Simulator::UnimplementedInstruction(Instr* instr) { | 1043 void Simulator::UnimplementedInstruction(Instr* instr) { |
1049 char buffer[128]; | 1044 char buffer[128]; |
1050 snprintf(buffer, sizeof(buffer), | 1045 snprintf(buffer, sizeof(buffer), |
1051 "Unimplemented instruction: at %p, last_pc=0x%" Px64 "\n", | 1046 "Unimplemented instruction: at %p, last_pc=0x%" Px64 "\n", instr, |
1052 instr, get_last_pc()); | 1047 get_last_pc()); |
1053 SimulatorDebugger dbg(this); | 1048 SimulatorDebugger dbg(this); |
1054 dbg.Stop(instr, buffer); | 1049 dbg.Stop(instr, buffer); |
1055 FATAL("Cannot continue execution after unimplemented instruction."); | 1050 FATAL("Cannot continue execution after unimplemented instruction."); |
1056 } | 1051 } |
1057 | 1052 |
1058 | 1053 |
1059 // Returns the top of the stack area to enable checking for stack pointer | 1054 // Returns the top of the stack area to enable checking for stack pointer |
1060 // validity. | 1055 // validity. |
1061 uword Simulator::StackTop() const { | 1056 uword Simulator::StackTop() const { |
1062 // To be safe in potential stack underflows we leave some buffer above and | 1057 // To be safe in potential stack underflows we leave some buffer above and |
1063 // set the stack top. | 1058 // set the stack top. |
1064 return StackBase() + | 1059 return StackBase() + |
1065 (OSThread::GetSpecifiedStackSize() + OSThread::kStackSizeBuffer); | 1060 (OSThread::GetSpecifiedStackSize() + OSThread::kStackSizeBuffer); |
1066 } | 1061 } |
1067 | 1062 |
1068 | 1063 |
1069 bool Simulator::IsTracingExecution() const { | 1064 bool Simulator::IsTracingExecution() const { |
1070 return icount_ > FLAG_trace_sim_after; | 1065 return icount_ > FLAG_trace_sim_after; |
1071 } | 1066 } |
1072 | 1067 |
1073 | 1068 |
1074 intptr_t Simulator::ReadX(uword addr, Instr* instr) { | 1069 intptr_t Simulator::ReadX(uword addr, Instr* instr) { |
1075 if ((addr & 7) == 0) { | 1070 if ((addr & 7) == 0) { |
(...skipping 199 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1275 } else { | 1270 } else { |
1276 // Same effect on exclusive access state as an LDREX. | 1271 // Same effect on exclusive access state as an LDREX. |
1277 SetExclusiveAccess(reinterpret_cast<uword>(address)); | 1272 SetExclusiveAccess(reinterpret_cast<uword>(address)); |
1278 } | 1273 } |
1279 return value; | 1274 return value; |
1280 } | 1275 } |
1281 | 1276 |
1282 | 1277 |
1283 // Unsupported instructions use Format to print an error and stop execution. | 1278 // Unsupported instructions use Format to print an error and stop execution. |
1284 void Simulator::Format(Instr* instr, const char* format) { | 1279 void Simulator::Format(Instr* instr, const char* format) { |
1285 OS::Print("Simulator found unsupported instruction:\n 0x%p: %s\n", | 1280 OS::Print("Simulator found unsupported instruction:\n 0x%p: %s\n", instr, |
1286 instr, | |
1287 format); | 1281 format); |
1288 UNIMPLEMENTED(); | 1282 UNIMPLEMENTED(); |
1289 } | 1283 } |
1290 | 1284 |
1291 | 1285 |
1292 // Calculate and set the Negative and Zero flags. | 1286 // Calculate and set the Negative and Zero flags. |
1293 void Simulator::SetNZFlagsW(int32_t val) { | 1287 void Simulator::SetNZFlagsW(int32_t val) { |
1294 n_flag_ = (val < 0); | 1288 n_flag_ = (val < 0); |
1295 z_flag_ = (val == 0); | 1289 z_flag_ = (val == 0); |
1296 } | 1290 } |
(...skipping 17 matching lines...) Expand all Loading... |
1314 | 1308 |
1315 // Calculate and set the Negative and Zero flags. | 1309 // Calculate and set the Negative and Zero flags. |
1316 void Simulator::SetNZFlagsX(int64_t val) { | 1310 void Simulator::SetNZFlagsX(int64_t val) { |
1317 n_flag_ = (val < 0); | 1311 n_flag_ = (val < 0); |
1318 z_flag_ = (val == 0); | 1312 z_flag_ = (val == 0); |
1319 } | 1313 } |
1320 | 1314 |
1321 | 1315 |
1322 // Calculate C flag value for additions and subtractions. | 1316 // Calculate C flag value for additions and subtractions. |
1323 bool Simulator::CarryFromX(int64_t alu_out, | 1317 bool Simulator::CarryFromX(int64_t alu_out, |
1324 int64_t left, int64_t right, bool addition) { | 1318 int64_t left, |
| 1319 int64_t right, |
| 1320 bool addition) { |
1325 if (addition) { | 1321 if (addition) { |
1326 return (((left & right) | ((left | right) & ~alu_out)) >> 63) != 0; | 1322 return (((left & right) | ((left | right) & ~alu_out)) >> 63) != 0; |
1327 } else { | 1323 } else { |
1328 return (((~left & right) | ((~left | right) & alu_out)) >> 63) == 0; | 1324 return (((~left & right) | ((~left | right) & alu_out)) >> 63) == 0; |
1329 } | 1325 } |
1330 } | 1326 } |
1331 | 1327 |
1332 | 1328 |
1333 // Calculate V flag value for additions and subtractions. | 1329 // Calculate V flag value for additions and subtractions. |
1334 bool Simulator::OverflowFromX(int64_t alu_out, | 1330 bool Simulator::OverflowFromX(int64_t alu_out, |
1335 int64_t left, int64_t right, bool addition) { | 1331 int64_t left, |
| 1332 int64_t right, |
| 1333 bool addition) { |
1336 if (addition) { | 1334 if (addition) { |
1337 return (((alu_out ^ left) & (alu_out ^ right)) >> 63) != 0; | 1335 return (((alu_out ^ left) & (alu_out ^ right)) >> 63) != 0; |
1338 } else { | 1336 } else { |
1339 return (((left ^ right) & (alu_out ^ left)) >> 63) != 0; | 1337 return (((left ^ right) & (alu_out ^ left)) >> 63) != 0; |
1340 } | 1338 } |
1341 } | 1339 } |
1342 | 1340 |
1343 | 1341 |
1344 // Set the Carry flag. | 1342 // Set the Carry flag. |
1345 void Simulator::SetCFlag(bool val) { | 1343 void Simulator::SetCFlag(bool val) { |
1346 c_flag_ = val; | 1344 c_flag_ = val; |
1347 } | 1345 } |
1348 | 1346 |
1349 | 1347 |
1350 // Set the oVerflow flag. | 1348 // Set the oVerflow flag. |
1351 void Simulator::SetVFlag(bool val) { | 1349 void Simulator::SetVFlag(bool val) { |
1352 v_flag_ = val; | 1350 v_flag_ = val; |
1353 } | 1351 } |
1354 | 1352 |
1355 | 1353 |
1356 void Simulator::DecodeMoveWide(Instr* instr) { | 1354 void Simulator::DecodeMoveWide(Instr* instr) { |
1357 const Register rd = instr->RdField(); | 1355 const Register rd = instr->RdField(); |
1358 const int hw = instr->HWField(); | 1356 const int hw = instr->HWField(); |
1359 const int64_t shift = hw << 4; | 1357 const int64_t shift = hw << 4; |
1360 const int64_t shifted_imm = | 1358 const int64_t shifted_imm = static_cast<int64_t>(instr->Imm16Field()) |
1361 static_cast<int64_t>(instr->Imm16Field()) << shift; | 1359 << shift; |
1362 | 1360 |
1363 if (instr->SFField()) { | 1361 if (instr->SFField()) { |
1364 if (instr->Bits(29, 2) == 0) { | 1362 if (instr->Bits(29, 2) == 0) { |
1365 // Format(instr, "movn'sf 'rd, 'imm16 'hw"); | 1363 // Format(instr, "movn'sf 'rd, 'imm16 'hw"); |
1366 set_register(instr, rd, ~shifted_imm, instr->RdMode()); | 1364 set_register(instr, rd, ~shifted_imm, instr->RdMode()); |
1367 } else if (instr->Bits(29, 2) == 2) { | 1365 } else if (instr->Bits(29, 2) == 2) { |
1368 // Format(instr, "movz'sf 'rd, 'imm16 'hw"); | 1366 // Format(instr, "movz'sf 'rd, 'imm16 'hw"); |
1369 set_register(instr, rd, shifted_imm, instr->RdMode()); | 1367 set_register(instr, rd, shifted_imm, instr->RdMode()); |
1370 } else if (instr->Bits(29, 2) == 3) { | 1368 } else if (instr->Bits(29, 2) == 3) { |
1371 // Format(instr, "movk'sf 'rd, 'imm16 'hw"); | 1369 // Format(instr, "movk'sf 'rd, 'imm16 'hw"); |
1372 const int64_t rd_val = get_register(rd, instr->RdMode()); | 1370 const int64_t rd_val = get_register(rd, instr->RdMode()); |
1373 const int64_t result = (rd_val & ~(0xffffL << shift)) | shifted_imm; | 1371 const int64_t result = (rd_val & ~(0xffffL << shift)) | shifted_imm; |
1374 set_register(instr, rd, result, instr->RdMode()); | 1372 set_register(instr, rd, result, instr->RdMode()); |
1375 } else { | 1373 } else { |
1376 UnimplementedInstruction(instr); | 1374 UnimplementedInstruction(instr); |
1377 } | 1375 } |
1378 } else if ((hw & 0x2) == 0) { | 1376 } else if ((hw & 0x2) == 0) { |
1379 if (instr->Bits(29, 2) == 0) { | 1377 if (instr->Bits(29, 2) == 0) { |
1380 // Format(instr, "movn'sf 'rd, 'imm16 'hw"); | 1378 // Format(instr, "movn'sf 'rd, 'imm16 'hw"); |
1381 set_wregister(rd, ~shifted_imm & kWRegMask, instr->RdMode()); | 1379 set_wregister(rd, ~shifted_imm & kWRegMask, instr->RdMode()); |
1382 } else if (instr->Bits(29, 2) == 2) { | 1380 } else if (instr->Bits(29, 2) == 2) { |
1383 // Format(instr, "movz'sf 'rd, 'imm16 'hw"); | 1381 // Format(instr, "movz'sf 'rd, 'imm16 'hw"); |
1384 set_wregister(rd, shifted_imm & kWRegMask, instr->RdMode()); | 1382 set_wregister(rd, shifted_imm & kWRegMask, instr->RdMode()); |
1385 } else if (instr->Bits(29, 2) == 3) { | 1383 } else if (instr->Bits(29, 2) == 3) { |
1386 // Format(instr, "movk'sf 'rd, 'imm16 'hw"); | 1384 // Format(instr, "movk'sf 'rd, 'imm16 'hw"); |
1387 const int32_t rd_val = get_wregister(rd, instr->RdMode()); | 1385 const int32_t rd_val = get_wregister(rd, instr->RdMode()); |
1388 const int32_t result = (rd_val & ~(0xffffL << shift)) | shifted_imm; | 1386 const int32_t result = (rd_val & ~(0xffffL << shift)) | shifted_imm; |
1389 set_wregister(rd, result, instr->RdMode()); | 1387 set_wregister(rd, result, instr->RdMode()); |
1390 } else { | 1388 } else { |
1391 UnimplementedInstruction(instr); | 1389 UnimplementedInstruction(instr); |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1431 SetVFlag(OverflowFromW(rn_val, imm, carry_in)); | 1429 SetVFlag(OverflowFromW(rn_val, imm, carry_in)); |
1432 } | 1430 } |
1433 } | 1431 } |
1434 } | 1432 } |
1435 | 1433 |
1436 | 1434 |
1437 void Simulator::DecodeLogicalImm(Instr* instr) { | 1435 void Simulator::DecodeLogicalImm(Instr* instr) { |
1438 const int op = instr->Bits(29, 2); | 1436 const int op = instr->Bits(29, 2); |
1439 const bool set_flags = op == 3; | 1437 const bool set_flags = op == 3; |
1440 const int out_size = ((instr->SFField() == 0) && (instr->NField() == 0)) | 1438 const int out_size = ((instr->SFField() == 0) && (instr->NField() == 0)) |
1441 ? kWRegSizeInBits : kXRegSizeInBits; | 1439 ? kWRegSizeInBits |
| 1440 : kXRegSizeInBits; |
1442 const Register rn = instr->RnField(); | 1441 const Register rn = instr->RnField(); |
1443 const Register rd = instr->RdField(); | 1442 const Register rd = instr->RdField(); |
1444 const int64_t rn_val = get_register(rn, instr->RnMode()); | 1443 const int64_t rn_val = get_register(rn, instr->RnMode()); |
1445 const uint64_t imm = instr->ImmLogical(); | 1444 const uint64_t imm = instr->ImmLogical(); |
1446 if (imm == 0) { | 1445 if (imm == 0) { |
1447 UnimplementedInstruction(instr); | 1446 UnimplementedInstruction(instr); |
1448 } | 1447 } |
1449 | 1448 |
1450 int64_t alu_out = 0; | 1449 int64_t alu_out = 0; |
1451 switch (op) { | 1450 switch (op) { |
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1537 | 1536 |
1538 | 1537 |
1539 bool Simulator::ConditionallyExecute(Instr* instr) { | 1538 bool Simulator::ConditionallyExecute(Instr* instr) { |
1540 Condition cond; | 1539 Condition cond; |
1541 if (instr->IsConditionalSelectOp()) { | 1540 if (instr->IsConditionalSelectOp()) { |
1542 cond = instr->SelectConditionField(); | 1541 cond = instr->SelectConditionField(); |
1543 } else { | 1542 } else { |
1544 cond = instr->ConditionField(); | 1543 cond = instr->ConditionField(); |
1545 } | 1544 } |
1546 switch (cond) { | 1545 switch (cond) { |
1547 case EQ: return z_flag_; | 1546 case EQ: |
1548 case NE: return !z_flag_; | 1547 return z_flag_; |
1549 case CS: return c_flag_; | 1548 case NE: |
1550 case CC: return !c_flag_; | 1549 return !z_flag_; |
1551 case MI: return n_flag_; | 1550 case CS: |
1552 case PL: return !n_flag_; | 1551 return c_flag_; |
1553 case VS: return v_flag_; | 1552 case CC: |
1554 case VC: return !v_flag_; | 1553 return !c_flag_; |
1555 case HI: return c_flag_ && !z_flag_; | 1554 case MI: |
1556 case LS: return !c_flag_ || z_flag_; | 1555 return n_flag_; |
1557 case GE: return n_flag_ == v_flag_; | 1556 case PL: |
1558 case LT: return n_flag_ != v_flag_; | 1557 return !n_flag_; |
1559 case GT: return !z_flag_ && (n_flag_ == v_flag_); | 1558 case VS: |
1560 case LE: return z_flag_ || (n_flag_ != v_flag_); | 1559 return v_flag_; |
1561 case AL: return true; | 1560 case VC: |
1562 default: UNREACHABLE(); | 1561 return !v_flag_; |
| 1562 case HI: |
| 1563 return c_flag_ && !z_flag_; |
| 1564 case LS: |
| 1565 return !c_flag_ || z_flag_; |
| 1566 case GE: |
| 1567 return n_flag_ == v_flag_; |
| 1568 case LT: |
| 1569 return n_flag_ != v_flag_; |
| 1570 case GT: |
| 1571 return !z_flag_ && (n_flag_ == v_flag_); |
| 1572 case LE: |
| 1573 return z_flag_ || (n_flag_ != v_flag_); |
| 1574 case AL: |
| 1575 return true; |
| 1576 default: |
| 1577 UNREACHABLE(); |
1563 } | 1578 } |
1564 return false; | 1579 return false; |
1565 } | 1580 } |
1566 | 1581 |
1567 | 1582 |
1568 void Simulator::DecodeConditionalBranch(Instr* instr) { | 1583 void Simulator::DecodeConditionalBranch(Instr* instr) { |
1569 // Format(instr, "b'cond 'dest19"); | 1584 // Format(instr, "b'cond 'dest19"); |
1570 if ((instr->Bit(24) != 0) || (instr->Bit(4) != 0)) { | 1585 if ((instr->Bit(24) != 0) || (instr->Bit(4) != 0)) { |
1571 UnimplementedInstruction(instr); | 1586 UnimplementedInstruction(instr); |
1572 } | 1587 } |
1573 const int64_t imm19 = instr->SImm19Field(); | 1588 const int64_t imm19 = instr->SImm19Field(); |
1574 const int64_t dest = get_pc() + (imm19 << 2); | 1589 const int64_t dest = get_pc() + (imm19 << 2); |
1575 if (ConditionallyExecute(instr)) { | 1590 if (ConditionallyExecute(instr)) { |
1576 set_pc(dest); | 1591 set_pc(dest); |
1577 } | 1592 } |
1578 } | 1593 } |
1579 | 1594 |
1580 | 1595 |
1581 // Calls into the Dart runtime are based on this interface. | 1596 // Calls into the Dart runtime are based on this interface. |
1582 typedef void (*SimulatorRuntimeCall)(NativeArguments arguments); | 1597 typedef void (*SimulatorRuntimeCall)(NativeArguments arguments); |
1583 | 1598 |
1584 // Calls to leaf Dart runtime functions are based on this interface. | 1599 // Calls to leaf Dart runtime functions are based on this interface. |
1585 typedef int64_t (*SimulatorLeafRuntimeCall)( | 1600 typedef int64_t (*SimulatorLeafRuntimeCall)(int64_t r0, |
1586 int64_t r0, int64_t r1, int64_t r2, int64_t r3, | 1601 int64_t r1, |
1587 int64_t r4, int64_t r5, int64_t r6, int64_t r7); | 1602 int64_t r2, |
| 1603 int64_t r3, |
| 1604 int64_t r4, |
| 1605 int64_t r5, |
| 1606 int64_t r6, |
| 1607 int64_t r7); |
1588 | 1608 |
1589 // Calls to leaf float Dart runtime functions are based on this interface. | 1609 // Calls to leaf float Dart runtime functions are based on this interface. |
1590 typedef double (*SimulatorLeafFloatRuntimeCall)( | 1610 typedef double (*SimulatorLeafFloatRuntimeCall)(double d0, |
1591 double d0, double d1, double d2, double d3, | 1611 double d1, |
1592 double d4, double d5, double d6, double d7); | 1612 double d2, |
| 1613 double d3, |
| 1614 double d4, |
| 1615 double d5, |
| 1616 double d6, |
| 1617 double d7); |
1593 | 1618 |
1594 // Calls to native Dart functions are based on this interface. | 1619 // Calls to native Dart functions are based on this interface. |
1595 typedef void (*SimulatorBootstrapNativeCall)(NativeArguments* arguments); | 1620 typedef void (*SimulatorBootstrapNativeCall)(NativeArguments* arguments); |
1596 typedef void (*SimulatorNativeCall)(NativeArguments* arguments, uword target); | 1621 typedef void (*SimulatorNativeCall)(NativeArguments* arguments, uword target); |
1597 | 1622 |
1598 | 1623 |
1599 void Simulator::DoRedirectedCall(Instr* instr) { | 1624 void Simulator::DoRedirectedCall(Instr* instr) { |
1600 SimulatorSetjmpBuffer buffer(this); | 1625 SimulatorSetjmpBuffer buffer(this); |
1601 if (!setjmp(buffer.buffer_)) { | 1626 if (!setjmp(buffer.buffer_)) { |
1602 int64_t saved_lr = get_register(LR); | 1627 int64_t saved_lr = get_register(LR); |
(...skipping 25 matching lines...) Expand all Loading... |
1628 reinterpret_cast<SimulatorLeafRuntimeCall>(external); | 1653 reinterpret_cast<SimulatorLeafRuntimeCall>(external); |
1629 const int64_t r0 = get_register(R0); | 1654 const int64_t r0 = get_register(R0); |
1630 const int64_t r1 = get_register(R1); | 1655 const int64_t r1 = get_register(R1); |
1631 const int64_t r2 = get_register(R2); | 1656 const int64_t r2 = get_register(R2); |
1632 const int64_t r3 = get_register(R3); | 1657 const int64_t r3 = get_register(R3); |
1633 const int64_t r4 = get_register(R4); | 1658 const int64_t r4 = get_register(R4); |
1634 const int64_t r5 = get_register(R5); | 1659 const int64_t r5 = get_register(R5); |
1635 const int64_t r6 = get_register(R6); | 1660 const int64_t r6 = get_register(R6); |
1636 const int64_t r7 = get_register(R7); | 1661 const int64_t r7 = get_register(R7); |
1637 const int64_t res = target(r0, r1, r2, r3, r4, r5, r6, r7); | 1662 const int64_t res = target(r0, r1, r2, r3, r4, r5, r6, r7); |
1638 set_register(instr, R0, res); // Set returned result from function. | 1663 set_register(instr, R0, res); // Set returned result from function. |
1639 set_register(instr, R1, icount_); // Zap unused result register. | 1664 set_register(instr, R1, icount_); // Zap unused result register. |
1640 } else if (redirection->call_kind() == kLeafFloatRuntimeCall) { | 1665 } else if (redirection->call_kind() == kLeafFloatRuntimeCall) { |
1641 ASSERT((0 <= redirection->argument_count()) && | 1666 ASSERT((0 <= redirection->argument_count()) && |
1642 (redirection->argument_count() <= 8)); | 1667 (redirection->argument_count() <= 8)); |
1643 SimulatorLeafFloatRuntimeCall target = | 1668 SimulatorLeafFloatRuntimeCall target = |
1644 reinterpret_cast<SimulatorLeafFloatRuntimeCall>(external); | 1669 reinterpret_cast<SimulatorLeafFloatRuntimeCall>(external); |
1645 const double d0 = bit_cast<double, int64_t>(get_vregisterd(V0, 0)); | 1670 const double d0 = bit_cast<double, int64_t>(get_vregisterd(V0, 0)); |
1646 const double d1 = bit_cast<double, int64_t>(get_vregisterd(V1, 0)); | 1671 const double d1 = bit_cast<double, int64_t>(get_vregisterd(V1, 0)); |
1647 const double d2 = bit_cast<double, int64_t>(get_vregisterd(V2, 0)); | 1672 const double d2 = bit_cast<double, int64_t>(get_vregisterd(V2, 0)); |
1648 const double d3 = bit_cast<double, int64_t>(get_vregisterd(V3, 0)); | 1673 const double d3 = bit_cast<double, int64_t>(get_vregisterd(V3, 0)); |
(...skipping 209 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1858 } | 1883 } |
1859 } | 1884 } |
1860 | 1885 |
1861 | 1886 |
1862 void Simulator::DecodeLoadStoreReg(Instr* instr) { | 1887 void Simulator::DecodeLoadStoreReg(Instr* instr) { |
1863 // Calculate the address. | 1888 // Calculate the address. |
1864 const Register rn = instr->RnField(); | 1889 const Register rn = instr->RnField(); |
1865 const Register rt = instr->RtField(); | 1890 const Register rt = instr->RtField(); |
1866 const VRegister vt = instr->VtField(); | 1891 const VRegister vt = instr->VtField(); |
1867 const int64_t rn_val = get_register(rn, R31IsSP); | 1892 const int64_t rn_val = get_register(rn, R31IsSP); |
1868 const uint32_t size = | 1893 const uint32_t size = (instr->Bit(26) == 1) |
1869 (instr->Bit(26) == 1) ? ((instr->Bit(23) << 2) | instr->SzField()) | 1894 ? ((instr->Bit(23) << 2) | instr->SzField()) |
1870 : instr->SzField(); | 1895 : instr->SzField(); |
1871 uword address = 0; | 1896 uword address = 0; |
1872 uword wb_address = 0; | 1897 uword wb_address = 0; |
1873 bool wb = false; | 1898 bool wb = false; |
1874 if (instr->Bit(24) == 1) { | 1899 if (instr->Bit(24) == 1) { |
1875 // addr = rn + scaled unsigned 12-bit immediate offset. | 1900 // addr = rn + scaled unsigned 12-bit immediate offset. |
1876 const uint32_t imm12 = static_cast<uint32_t>(instr->Imm12Field()); | 1901 const uint32_t imm12 = static_cast<uint32_t>(instr->Imm12Field()); |
1877 const uint32_t offset = imm12 << size; | 1902 const uint32_t offset = imm12 << size; |
1878 address = rn_val + offset; | 1903 address = rn_val + offset; |
1879 } else if (instr->Bits(10, 2) == 0) { | 1904 } else if (instr->Bits(10, 2) == 0) { |
1880 // addr = rn + signed 9-bit immediate offset. | 1905 // addr = rn + signed 9-bit immediate offset. |
1881 wb = false; | 1906 wb = false; |
1882 const int64_t offset = static_cast<int64_t>(instr->SImm9Field()); | 1907 const int64_t offset = static_cast<int64_t>(instr->SImm9Field()); |
1883 address = rn_val + offset; | 1908 address = rn_val + offset; |
1884 wb_address = rn_val; | 1909 wb_address = rn_val; |
1885 } else if (instr->Bit(10) == 1) { | 1910 } else if (instr->Bit(10) == 1) { |
1886 // addr = rn + signed 9-bit immediate offset. | 1911 // addr = rn + signed 9-bit immediate offset. |
1887 wb = true; | 1912 wb = true; |
1888 const int64_t offset = static_cast<int64_t>(instr->SImm9Field()); | 1913 const int64_t offset = static_cast<int64_t>(instr->SImm9Field()); |
1889 if (instr->Bit(11) == 1) { | 1914 if (instr->Bit(11) == 1) { |
1890 // Pre-index. | 1915 // Pre-index. |
1891 address = rn_val + offset; | 1916 address = rn_val + offset; |
1892 wb_address = address; | 1917 wb_address = address; |
1893 } else { | 1918 } else { |
1894 // Post-index. | 1919 // Post-index. |
1895 address = rn_val; | 1920 address = rn_val; |
1896 wb_address = rn_val + offset; | 1921 wb_address = rn_val + offset; |
1897 } | 1922 } |
1898 } else if (instr->Bits(10, 2) == 2) { | 1923 } else if (instr->Bits(10, 2) == 2) { |
1899 // addr = rn + (rm EXT optionally scaled by operand instruction size). | 1924 // addr = rn + (rm EXT optionally scaled by operand instruction size). |
1900 const Register rm = instr->RmField(); | 1925 const Register rm = instr->RmField(); |
1901 const Extend ext = instr->ExtendTypeField(); | 1926 const Extend ext = instr->ExtendTypeField(); |
1902 const uint8_t scale = | 1927 const uint8_t scale = (ext == UXTX) && (instr->Bit(12) == 1) ? size : 0; |
1903 (ext == UXTX) && (instr->Bit(12) == 1) ? size : 0; | |
1904 const int64_t rm_val = get_register(rm, R31IsZR); | 1928 const int64_t rm_val = get_register(rm, R31IsZR); |
1905 const int64_t offset = ExtendOperand(kXRegSizeInBits, rm_val, ext, scale); | 1929 const int64_t offset = ExtendOperand(kXRegSizeInBits, rm_val, ext, scale); |
1906 address = rn_val + offset; | 1930 address = rn_val + offset; |
1907 } else { | 1931 } else { |
1908 UnimplementedInstruction(instr); | 1932 UnimplementedInstruction(instr); |
1909 return; | 1933 return; |
1910 } | 1934 } |
1911 | 1935 |
1912 // Check the address. | 1936 // Check the address. |
1913 if (IsIllegalAddress(address)) { | 1937 if (IsIllegalAddress(address)) { |
(...skipping 249 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2163 // Format(instr, "ldrx 'rt, 'pcldr"); | 2187 // Format(instr, "ldrx 'rt, 'pcldr"); |
2164 set_register(instr, rt, val, R31IsZR); | 2188 set_register(instr, rt, val, R31IsZR); |
2165 } else { | 2189 } else { |
2166 // Format(instr, "ldrw 'rt, 'pcldr"); | 2190 // Format(instr, "ldrw 'rt, 'pcldr"); |
2167 set_wregister(rt, static_cast<int32_t>(val), R31IsZR); | 2191 set_wregister(rt, static_cast<int32_t>(val), R31IsZR); |
2168 } | 2192 } |
2169 } | 2193 } |
2170 | 2194 |
2171 | 2195 |
2172 void Simulator::DecodeLoadStoreExclusive(Instr* instr) { | 2196 void Simulator::DecodeLoadStoreExclusive(Instr* instr) { |
2173 if ((instr->Bit(23) != 0) || | 2197 if ((instr->Bit(23) != 0) || (instr->Bit(21) != 0) || (instr->Bit(15) != 0)) { |
2174 (instr->Bit(21) != 0) || | |
2175 (instr->Bit(15) != 0)) { | |
2176 UNIMPLEMENTED(); | 2198 UNIMPLEMENTED(); |
2177 } | 2199 } |
2178 const int32_t size = instr->Bits(30, 2); | 2200 const int32_t size = instr->Bits(30, 2); |
2179 if (size != 3) { | 2201 if (size != 3) { |
2180 UNIMPLEMENTED(); | 2202 UNIMPLEMENTED(); |
2181 } | 2203 } |
2182 | 2204 |
2183 const Register rs = instr->RsField(); | 2205 const Register rs = instr->RsField(); |
2184 const Register rn = instr->RnField(); | 2206 const Register rn = instr->RnField(); |
2185 const Register rt = instr->RtField(); | 2207 const Register rt = instr->RtField(); |
(...skipping 580 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2766 const Register rn = instr->RnField(); | 2788 const Register rn = instr->RnField(); |
2767 const Register rd = instr->RdField(); | 2789 const Register rd = instr->RdField(); |
2768 if ((op == 0) && (imm4 == 7)) { | 2790 if ((op == 0) && (imm4 == 7)) { |
2769 if (Q == 0) { | 2791 if (Q == 0) { |
2770 // Format(instr, "vmovrs 'rd, 'vn'idx5"); | 2792 // Format(instr, "vmovrs 'rd, 'vn'idx5"); |
2771 set_wregister(rd, get_vregisters(vn, idx5), R31IsZR); | 2793 set_wregister(rd, get_vregisters(vn, idx5), R31IsZR); |
2772 } else { | 2794 } else { |
2773 // Format(instr, "vmovrd 'rd, 'vn'idx5"); | 2795 // Format(instr, "vmovrd 'rd, 'vn'idx5"); |
2774 set_register(instr, rd, get_vregisterd(vn, idx5), R31IsZR); | 2796 set_register(instr, rd, get_vregisterd(vn, idx5), R31IsZR); |
2775 } | 2797 } |
2776 } else if ((Q == 1) && (op == 0) && (imm4 == 0)) { | 2798 } else if ((Q == 1) && (op == 0) && (imm4 == 0)) { |
2777 // Format(instr, "vdup'csz 'vd, 'vn'idx5"); | 2799 // Format(instr, "vdup'csz 'vd, 'vn'idx5"); |
2778 if (element_bytes == 4) { | 2800 if (element_bytes == 4) { |
2779 for (int i = 0; i < 4; i++) { | 2801 for (int i = 0; i < 4; i++) { |
2780 set_vregisters(vd, i, get_vregisters(vn, idx5)); | 2802 set_vregisters(vd, i, get_vregisters(vn, idx5)); |
2781 } | 2803 } |
2782 } else if (element_bytes == 8) { | 2804 } else if (element_bytes == 8) { |
2783 for (int i = 0; i < 2; i++) { | 2805 for (int i = 0; i < 2; i++) { |
2784 set_vregisterd(vd, i, get_vregisterd(vn, idx5)); | 2806 set_vregisterd(vd, i, get_vregisterd(vn, idx5)); |
2785 } | 2807 } |
2786 } else { | 2808 } else { |
(...skipping 190 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2977 return; | 2999 return; |
2978 } | 3000 } |
2979 set_vregisterd(vd, idx, res); | 3001 set_vregisterd(vd, idx, res); |
2980 } | 3002 } |
2981 } | 3003 } |
2982 } | 3004 } |
2983 | 3005 |
2984 | 3006 |
2985 static float arm_reciprocal_sqrt_estimate(float a) { | 3007 static float arm_reciprocal_sqrt_estimate(float a) { |
2986 // From the ARM Architecture Reference Manual A2-87. | 3008 // From the ARM Architecture Reference Manual A2-87. |
2987 if (isinf(a) || (fabs(a) >= exp2f(126))) return 0.0; | 3009 if (isinf(a) || (fabs(a) >= exp2f(126))) |
2988 else if (a == 0.0) return kPosInfinity; | 3010 return 0.0; |
2989 else if (isnan(a)) return a; | 3011 else if (a == 0.0) |
| 3012 return kPosInfinity; |
| 3013 else if (isnan(a)) |
| 3014 return a; |
2990 | 3015 |
2991 uint32_t a_bits = bit_cast<uint32_t, float>(a); | 3016 uint32_t a_bits = bit_cast<uint32_t, float>(a); |
2992 uint64_t scaled; | 3017 uint64_t scaled; |
2993 if (((a_bits >> 23) & 1) != 0) { | 3018 if (((a_bits >> 23) & 1) != 0) { |
2994 // scaled = '0 01111111101' : operand<22:0> : Zeros(29) | 3019 // scaled = '0 01111111101' : operand<22:0> : Zeros(29) |
2995 scaled = (static_cast<uint64_t>(0x3fd) << 52) | | 3020 scaled = (static_cast<uint64_t>(0x3fd) << 52) | |
2996 ((static_cast<uint64_t>(a_bits) & 0x7fffff) << 29); | 3021 ((static_cast<uint64_t>(a_bits) & 0x7fffff) << 29); |
2997 } else { | 3022 } else { |
2998 // scaled = '0 01111111110' : operand<22:0> : Zeros(29) | 3023 // scaled = '0 01111111110' : operand<22:0> : Zeros(29) |
2999 scaled = (static_cast<uint64_t>(0x3fe) << 52) | | 3024 scaled = (static_cast<uint64_t>(0x3fe) << 52) | |
(...skipping 17 matching lines...) Expand all Loading... |
3017 // range 0.5 <= a < 1.0 | 3042 // range 0.5 <= a < 1.0 |
3018 | 3043 |
3019 // a in units of 1/256 rounded down. | 3044 // a in units of 1/256 rounded down. |
3020 int32_t q1 = static_cast<int32_t>(scaled_d * 256.0); | 3045 int32_t q1 = static_cast<int32_t>(scaled_d * 256.0); |
3021 // reciprocal root r. | 3046 // reciprocal root r. |
3022 r = 1.0 / sqrt((static_cast<double>(q1) + 0.5) / 256.0); | 3047 r = 1.0 / sqrt((static_cast<double>(q1) + 0.5) / 256.0); |
3023 } | 3048 } |
3024 // r in units of 1/256 rounded to nearest. | 3049 // r in units of 1/256 rounded to nearest. |
3025 int32_t s = static_cast<int>(256.0 * r + 0.5); | 3050 int32_t s = static_cast<int>(256.0 * r + 0.5); |
3026 double estimate = static_cast<double>(s) / 256.0; | 3051 double estimate = static_cast<double>(s) / 256.0; |
3027 ASSERT((estimate >= 1.0) && (estimate <= (511.0/256.0))); | 3052 ASSERT((estimate >= 1.0) && (estimate <= (511.0 / 256.0))); |
3028 | 3053 |
3029 // result = 0 : result_exp<7:0> : estimate<51:29> | 3054 // result = 0 : result_exp<7:0> : estimate<51:29> |
3030 int32_t result_bits = ((result_exp & 0xff) << 23) | | 3055 int32_t result_bits = |
| 3056 ((result_exp & 0xff) << 23) | |
3031 ((bit_cast<uint64_t, double>(estimate) >> 29) & 0x7fffff); | 3057 ((bit_cast<uint64_t, double>(estimate) >> 29) & 0x7fffff); |
3032 return bit_cast<float, int32_t>(result_bits); | 3058 return bit_cast<float, int32_t>(result_bits); |
3033 } | 3059 } |
3034 | 3060 |
3035 | 3061 |
3036 static float arm_recip_estimate(float a) { | 3062 static float arm_recip_estimate(float a) { |
3037 // From the ARM Architecture Reference Manual A2-85. | 3063 // From the ARM Architecture Reference Manual A2-85. |
3038 if (isinf(a) || (fabs(a) >= exp2f(126))) return 0.0; | 3064 if (isinf(a) || (fabs(a) >= exp2f(126))) |
3039 else if (a == 0.0) return kPosInfinity; | 3065 return 0.0; |
3040 else if (isnan(a)) return a; | 3066 else if (a == 0.0) |
| 3067 return kPosInfinity; |
| 3068 else if (isnan(a)) |
| 3069 return a; |
3041 | 3070 |
3042 uint32_t a_bits = bit_cast<uint32_t, float>(a); | 3071 uint32_t a_bits = bit_cast<uint32_t, float>(a); |
3043 // scaled = '0011 1111 1110' : a<22:0> : Zeros(29) | 3072 // scaled = '0011 1111 1110' : a<22:0> : Zeros(29) |
3044 uint64_t scaled = (static_cast<uint64_t>(0x3fe) << 52) | | 3073 uint64_t scaled = (static_cast<uint64_t>(0x3fe) << 52) | |
3045 ((static_cast<uint64_t>(a_bits) & 0x7fffff) << 29); | 3074 ((static_cast<uint64_t>(a_bits) & 0x7fffff) << 29); |
3046 // result_exp = 253 - UInt(a<30:23>) | 3075 // result_exp = 253 - UInt(a<30:23>) |
3047 int32_t result_exp = 253 - ((a_bits >> 23) & 0xff); | 3076 int32_t result_exp = 253 - ((a_bits >> 23) & 0xff); |
3048 ASSERT((result_exp >= 1) && (result_exp <= 252)); | 3077 ASSERT((result_exp >= 1) && (result_exp <= 252)); |
3049 | 3078 |
3050 double scaled_d = bit_cast<double, uint64_t>(scaled); | 3079 double scaled_d = bit_cast<double, uint64_t>(scaled); |
3051 ASSERT((scaled_d >= 0.5) && (scaled_d < 1.0)); | 3080 ASSERT((scaled_d >= 0.5) && (scaled_d < 1.0)); |
3052 | 3081 |
3053 // a in units of 1/512 rounded down. | 3082 // a in units of 1/512 rounded down. |
3054 int32_t q = static_cast<int32_t>(scaled_d * 512.0); | 3083 int32_t q = static_cast<int32_t>(scaled_d * 512.0); |
3055 // reciprocal r. | 3084 // reciprocal r. |
3056 double r = 1.0 / ((static_cast<double>(q) + 0.5) / 512.0); | 3085 double r = 1.0 / ((static_cast<double>(q) + 0.5) / 512.0); |
3057 // r in units of 1/256 rounded to nearest. | 3086 // r in units of 1/256 rounded to nearest. |
3058 int32_t s = static_cast<int32_t>(256.0 * r + 0.5); | 3087 int32_t s = static_cast<int32_t>(256.0 * r + 0.5); |
3059 double estimate = static_cast<double>(s) / 256.0; | 3088 double estimate = static_cast<double>(s) / 256.0; |
3060 ASSERT((estimate >= 1.0) && (estimate <= (511.0/256.0))); | 3089 ASSERT((estimate >= 1.0) && (estimate <= (511.0 / 256.0))); |
3061 | 3090 |
3062 // result = sign : result_exp<7:0> : estimate<51:29> | 3091 // result = sign : result_exp<7:0> : estimate<51:29> |
3063 int32_t result_bits = | 3092 int32_t result_bits = |
3064 (a_bits & 0x80000000) | ((result_exp & 0xff) << 23) | | 3093 (a_bits & 0x80000000) | ((result_exp & 0xff) << 23) | |
3065 ((bit_cast<uint64_t, double>(estimate) >> 29) & 0x7fffff); | 3094 ((bit_cast<uint64_t, double>(estimate) >> 29) & 0x7fffff); |
3066 return bit_cast<float, int32_t>(result_bits); | 3095 return bit_cast<float, int32_t>(result_bits); |
3067 } | 3096 } |
3068 | 3097 |
3069 | 3098 |
3070 void Simulator::DecodeSIMDTwoReg(Instr* instr) { | 3099 void Simulator::DecodeSIMDTwoReg(Instr* instr) { |
(...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3210 | 3239 |
3211 if ((instr->Bit(29) != 0) || (instr->Bits(22, 2) != 1) || | 3240 if ((instr->Bit(29) != 0) || (instr->Bits(22, 2) != 1) || |
3212 ((instr->SFField() == 0) && (instr->Bits(16, 5) != 2))) { | 3241 ((instr->SFField() == 0) && (instr->Bits(16, 5) != 2))) { |
3213 UnimplementedInstruction(instr); | 3242 UnimplementedInstruction(instr); |
3214 return; | 3243 return; |
3215 } | 3244 } |
3216 if (instr->Bits(16, 5) == 2) { | 3245 if (instr->Bits(16, 5) == 2) { |
3217 // Format(instr, "scvtfd'sf 'vd, 'rn"); | 3246 // Format(instr, "scvtfd'sf 'vd, 'rn"); |
3218 const int64_t rn_val64 = get_register(rn, instr->RnMode()); | 3247 const int64_t rn_val64 = get_register(rn, instr->RnMode()); |
3219 const int32_t rn_val32 = get_wregister(rn, instr->RnMode()); | 3248 const int32_t rn_val32 = get_wregister(rn, instr->RnMode()); |
3220 const double vn_dbl = (instr->SFField() == 1) ? | 3249 const double vn_dbl = (instr->SFField() == 1) |
3221 static_cast<double>(rn_val64) : static_cast<double>(rn_val32); | 3250 ? static_cast<double>(rn_val64) |
| 3251 : static_cast<double>(rn_val32); |
3222 set_vregisterd(vd, 0, bit_cast<int64_t, double>(vn_dbl)); | 3252 set_vregisterd(vd, 0, bit_cast<int64_t, double>(vn_dbl)); |
3223 set_vregisterd(vd, 1, 0); | 3253 set_vregisterd(vd, 1, 0); |
3224 } else if (instr->Bits(16, 5) == 6) { | 3254 } else if (instr->Bits(16, 5) == 6) { |
3225 // Format(instr, "fmovrd'sf 'rd, 'vn"); | 3255 // Format(instr, "fmovrd'sf 'rd, 'vn"); |
3226 const int64_t vn_val = get_vregisterd(vn, 0); | 3256 const int64_t vn_val = get_vregisterd(vn, 0); |
3227 set_register(instr, rd, vn_val, R31IsZR); | 3257 set_register(instr, rd, vn_val, R31IsZR); |
3228 } else if (instr->Bits(16, 5) == 7) { | 3258 } else if (instr->Bits(16, 5) == 7) { |
3229 // Format(instr, "fmovdr'sf 'vd, 'rn"); | 3259 // Format(instr, "fmovdr'sf 'vd, 'rn"); |
3230 const int64_t rn_val = get_register(rn, R31IsZR); | 3260 const int64_t rn_val = get_register(rn, R31IsZR); |
3231 set_vregisterd(vd, 0, rn_val); | 3261 set_vregisterd(vd, 0, rn_val); |
(...skipping 366 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3598 set_register(NULL, THR, reinterpret_cast<int64_t>(thread)); | 3628 set_register(NULL, THR, reinterpret_cast<int64_t>(thread)); |
3599 // Set the tag. | 3629 // Set the tag. |
3600 thread->set_vm_tag(VMTag::kDartTagId); | 3630 thread->set_vm_tag(VMTag::kDartTagId); |
3601 // Clear top exit frame. | 3631 // Clear top exit frame. |
3602 thread->set_top_exit_frame_info(0); | 3632 thread->set_top_exit_frame_info(0); |
3603 | 3633 |
3604 ASSERT(raw_exception != Object::null()); | 3634 ASSERT(raw_exception != Object::null()); |
3605 set_register(NULL, kExceptionObjectReg, bit_cast<int64_t>(raw_exception)); | 3635 set_register(NULL, kExceptionObjectReg, bit_cast<int64_t>(raw_exception)); |
3606 set_register(NULL, kStackTraceObjectReg, bit_cast<int64_t>(raw_stacktrace)); | 3636 set_register(NULL, kStackTraceObjectReg, bit_cast<int64_t>(raw_stacktrace)); |
3607 // Restore pool pointer. | 3637 // Restore pool pointer. |
3608 int64_t code = *reinterpret_cast<int64_t*>( | 3638 int64_t code = |
3609 fp + kPcMarkerSlotFromFp * kWordSize); | 3639 *reinterpret_cast<int64_t*>(fp + kPcMarkerSlotFromFp * kWordSize); |
3610 int64_t pp = *reinterpret_cast<int64_t*>( | 3640 int64_t pp = *reinterpret_cast<int64_t*>(code + Code::object_pool_offset() - |
3611 code + Code::object_pool_offset() - kHeapObjectTag); | 3641 kHeapObjectTag); |
3612 pp -= kHeapObjectTag; // In the PP register, the pool pointer is untagged. | 3642 pp -= kHeapObjectTag; // In the PP register, the pool pointer is untagged. |
3613 set_register(NULL, CODE_REG, code); | 3643 set_register(NULL, CODE_REG, code); |
3614 set_register(NULL, PP, pp); | 3644 set_register(NULL, PP, pp); |
3615 buf->Longjmp(); | 3645 buf->Longjmp(); |
3616 } | 3646 } |
3617 | 3647 |
3618 } // namespace dart | 3648 } // namespace dart |
3619 | 3649 |
3620 #endif // !defined(USING_SIMULATOR) | 3650 #endif // !defined(USING_SIMULATOR) |
3621 | 3651 |
3622 #endif // defined TARGET_ARCH_ARM64 | 3652 #endif // defined TARGET_ARCH_ARM64 |
OLD | NEW |