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

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

Issue 2481873005: clang-format runtime/vm (Closed)
Patch Set: Merge Created 4 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « runtime/vm/simulator_arm64.h ('k') | runtime/vm/simulator_dbc.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « runtime/vm/simulator_arm64.h ('k') | runtime/vm/simulator_dbc.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698