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

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

Powered by Google App Engine
This is Rietveld 408576698