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

Side by Side Diff: src/arm/simulator-thumb2.cc

Issue 601028: Forking disassembler and simulator for Thumb2 support;... Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: '' Created 10 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/arm/regexp-macro-assembler-arm.cc ('k') | src/simulator.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright 2010 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are
4 // met:
5 //
6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided
11 // with the distribution.
12 // * Neither the name of Google Inc. nor the names of its
13 // contributors may be used to endorse or promote products derived
14 // from this software without specific prior written permission.
15 //
16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
28 #include <stdlib.h>
29 #include <cstdarg>
30 #include "v8.h"
31
32 #include "disasm.h"
33 #include "assembler.h"
34 #include "arm/simulator-thumb2.h"
35
36 #if !defined(__arm__)
37
38 // Only build the simulator if not compiling for real ARM hardware.
39 namespace assembler {
40 namespace arm {
41
42 using ::v8::internal::Object;
43 using ::v8::internal::PrintF;
44 using ::v8::internal::OS;
45 using ::v8::internal::ReadLine;
46 using ::v8::internal::DeleteArray;
47
48 // This macro provides a platform independent use of sscanf. The reason for
49 // SScanF not being implemented in a platform independent way through
50 // ::v8::internal::OS in the same way as SNPrintF is that the
51 // Windows C Run-Time Library does not provide vsscanf.
52 #define SScanF sscanf // NOLINT
53
54 // The Debugger class is used by the simulator while debugging simulated ARM
55 // code.
56 class Debugger {
57 public:
58 explicit Debugger(Simulator* sim);
59 ~Debugger();
60
61 void Stop(Instr* instr);
62 void Debug();
63
64 private:
65 static const instr_t kBreakpointInstr =
66 ((AL << 28) | (7 << 25) | (1 << 24) | break_point);
67 static const instr_t kNopInstr =
68 ((AL << 28) | (13 << 21));
69
70 Simulator* sim_;
71
72 int32_t GetRegisterValue(int regnum);
73 bool GetValue(const char* desc, int32_t* value);
74
75 // Set or delete a breakpoint. Returns true if successful.
76 bool SetBreakpoint(Instr* breakpc);
77 bool DeleteBreakpoint(Instr* breakpc);
78
79 // Undo and redo all breakpoints. This is needed to bracket disassembly and
80 // execution to skip past breakpoints when run from the debugger.
81 void UndoBreakpoints();
82 void RedoBreakpoints();
83 };
84
85
86 Debugger::Debugger(Simulator* sim) {
87 sim_ = sim;
88 }
89
90
91 Debugger::~Debugger() {
92 }
93
94
95
96 #ifdef GENERATED_CODE_COVERAGE
97 static FILE* coverage_log = NULL;
98
99
100 static void InitializeCoverage() {
101 char* file_name = getenv("V8_GENERATED_CODE_COVERAGE_LOG");
102 if (file_name != NULL) {
103 coverage_log = fopen(file_name, "aw+");
104 }
105 }
106
107
108 void Debugger::Stop(Instr* instr) {
109 char* str = reinterpret_cast<char*>(instr->InstructionBits() & 0x0fffffff);
110 if (strlen(str) > 0) {
111 if (coverage_log != NULL) {
112 fprintf(coverage_log, "%s\n", str);
113 fflush(coverage_log);
114 }
115 instr->SetInstructionBits(0xe1a00000); // Overwrite with nop.
116 }
117 sim_->set_pc(sim_->get_pc() + Instr::kInstrSize);
118 }
119
120 #else // ndef GENERATED_CODE_COVERAGE
121
122 static void InitializeCoverage() {
123 }
124
125
126 void Debugger::Stop(Instr* instr) {
127 const char* str = (const char*)(instr->InstructionBits() & 0x0fffffff);
128 PrintF("Simulator hit %s\n", str);
129 sim_->set_pc(sim_->get_pc() + Instr::kInstrSize);
130 Debug();
131 }
132 #endif
133
134
135 int32_t Debugger::GetRegisterValue(int regnum) {
136 if (regnum == kPCRegister) {
137 return sim_->get_pc();
138 } else {
139 return sim_->get_register(regnum);
140 }
141 }
142
143
144 bool Debugger::GetValue(const char* desc, int32_t* value) {
145 int regnum = Registers::Number(desc);
146 if (regnum != kNoRegister) {
147 *value = GetRegisterValue(regnum);
148 return true;
149 } else {
150 return SScanF(desc, "%i", value) == 1;
151 }
152 return false;
153 }
154
155
156 bool Debugger::SetBreakpoint(Instr* breakpc) {
157 // Check if a breakpoint can be set. If not return without any side-effects.
158 if (sim_->break_pc_ != NULL) {
159 return false;
160 }
161
162 // Set the breakpoint.
163 sim_->break_pc_ = breakpc;
164 sim_->break_instr_ = breakpc->InstructionBits();
165 // Not setting the breakpoint instruction in the code itself. It will be set
166 // when the debugger shell continues.
167 return true;
168 }
169
170
171 bool Debugger::DeleteBreakpoint(Instr* breakpc) {
172 if (sim_->break_pc_ != NULL) {
173 sim_->break_pc_->SetInstructionBits(sim_->break_instr_);
174 }
175
176 sim_->break_pc_ = NULL;
177 sim_->break_instr_ = 0;
178 return true;
179 }
180
181
182 void Debugger::UndoBreakpoints() {
183 if (sim_->break_pc_ != NULL) {
184 sim_->break_pc_->SetInstructionBits(sim_->break_instr_);
185 }
186 }
187
188
189 void Debugger::RedoBreakpoints() {
190 if (sim_->break_pc_ != NULL) {
191 sim_->break_pc_->SetInstructionBits(kBreakpointInstr);
192 }
193 }
194
195
196 void Debugger::Debug() {
197 intptr_t last_pc = -1;
198 bool done = false;
199
200 #define COMMAND_SIZE 63
201 #define ARG_SIZE 255
202
203 #define STR(a) #a
204 #define XSTR(a) STR(a)
205
206 char cmd[COMMAND_SIZE + 1];
207 char arg1[ARG_SIZE + 1];
208 char arg2[ARG_SIZE + 1];
209
210 // make sure to have a proper terminating character if reaching the limit
211 cmd[COMMAND_SIZE] = 0;
212 arg1[ARG_SIZE] = 0;
213 arg2[ARG_SIZE] = 0;
214
215 // Undo all set breakpoints while running in the debugger shell. This will
216 // make them invisible to all commands.
217 UndoBreakpoints();
218
219 while (!done) {
220 if (last_pc != sim_->get_pc()) {
221 disasm::NameConverter converter;
222 disasm::Disassembler dasm(converter);
223 // use a reasonably large buffer
224 v8::internal::EmbeddedVector<char, 256> buffer;
225 dasm.InstructionDecode(buffer,
226 reinterpret_cast<byte*>(sim_->get_pc()));
227 PrintF(" 0x%08x %s\n", sim_->get_pc(), buffer.start());
228 last_pc = sim_->get_pc();
229 }
230 char* line = ReadLine("sim> ");
231 if (line == NULL) {
232 break;
233 } else {
234 // Use sscanf to parse the individual parts of the command line. At the
235 // moment no command expects more than two parameters.
236 int args = SScanF(line,
237 "%" XSTR(COMMAND_SIZE) "s "
238 "%" XSTR(ARG_SIZE) "s "
239 "%" XSTR(ARG_SIZE) "s",
240 cmd, arg1, arg2);
241 if ((strcmp(cmd, "si") == 0) || (strcmp(cmd, "stepi") == 0)) {
242 sim_->InstructionDecode(sim_->get_pc());
243 } else if ((strcmp(cmd, "c") == 0) || (strcmp(cmd, "cont") == 0)) {
244 // Execute the one instruction we broke at with breakpoints disabled.
245 sim_->InstructionDecode(sim_->get_pc());
246 // Leave the debugger shell.
247 done = true;
248 } else if ((strcmp(cmd, "p") == 0) || (strcmp(cmd, "print") == 0)) {
249 if (args == 2) {
250 int32_t value;
251 if (strcmp(arg1, "all") == 0) {
252 for (int i = 0; i < kNumRegisters; i++) {
253 value = GetRegisterValue(i);
254 PrintF("%3s: 0x%08x %10d\n", Registers::Name(i), value, value);
255 }
256 } else {
257 if (GetValue(arg1, &value)) {
258 PrintF("%s: 0x%08x %d \n", arg1, value, value);
259 } else {
260 PrintF("%s unrecognized\n", arg1);
261 }
262 }
263 } else {
264 PrintF("print <register>\n");
265 }
266 } else if ((strcmp(cmd, "po") == 0)
267 || (strcmp(cmd, "printobject") == 0)) {
268 if (args == 2) {
269 int32_t value;
270 if (GetValue(arg1, &value)) {
271 Object* obj = reinterpret_cast<Object*>(value);
272 PrintF("%s: \n", arg1);
273 #ifdef DEBUG
274 obj->PrintLn();
275 #else
276 obj->ShortPrint();
277 PrintF("\n");
278 #endif
279 } else {
280 PrintF("%s unrecognized\n", arg1);
281 }
282 } else {
283 PrintF("printobject <value>\n");
284 }
285 } else if (strcmp(cmd, "disasm") == 0) {
286 disasm::NameConverter converter;
287 disasm::Disassembler dasm(converter);
288 // use a reasonably large buffer
289 v8::internal::EmbeddedVector<char, 256> buffer;
290
291 byte* cur = NULL;
292 byte* end = NULL;
293
294 if (args == 1) {
295 cur = reinterpret_cast<byte*>(sim_->get_pc());
296 end = cur + (10 * Instr::kInstrSize);
297 } else if (args == 2) {
298 int32_t value;
299 if (GetValue(arg1, &value)) {
300 cur = reinterpret_cast<byte*>(value);
301 // no length parameter passed, assume 10 instructions
302 end = cur + (10 * Instr::kInstrSize);
303 }
304 } else {
305 int32_t value1;
306 int32_t value2;
307 if (GetValue(arg1, &value1) && GetValue(arg2, &value2)) {
308 cur = reinterpret_cast<byte*>(value1);
309 end = cur + (value2 * Instr::kInstrSize);
310 }
311 }
312
313 while (cur < end) {
314 dasm.InstructionDecode(buffer, cur);
315 PrintF(" 0x%08x %s\n", cur, buffer.start());
316 cur += Instr::kInstrSize;
317 }
318 } else if (strcmp(cmd, "gdb") == 0) {
319 PrintF("relinquishing control to gdb\n");
320 v8::internal::OS::DebugBreak();
321 PrintF("regaining control from gdb\n");
322 } else if (strcmp(cmd, "break") == 0) {
323 if (args == 2) {
324 int32_t value;
325 if (GetValue(arg1, &value)) {
326 if (!SetBreakpoint(reinterpret_cast<Instr*>(value))) {
327 PrintF("setting breakpoint failed\n");
328 }
329 } else {
330 PrintF("%s unrecognized\n", arg1);
331 }
332 } else {
333 PrintF("break <address>\n");
334 }
335 } else if (strcmp(cmd, "del") == 0) {
336 if (!DeleteBreakpoint(NULL)) {
337 PrintF("deleting breakpoint failed\n");
338 }
339 } else if (strcmp(cmd, "flags") == 0) {
340 PrintF("N flag: %d; ", sim_->n_flag_);
341 PrintF("Z flag: %d; ", sim_->z_flag_);
342 PrintF("C flag: %d; ", sim_->c_flag_);
343 PrintF("V flag: %d\n", sim_->v_flag_);
344 PrintF("INVALID OP flag: %d; ", sim_->inv_op_vfp_flag_);
345 PrintF("DIV BY ZERO flag: %d; ", sim_->div_zero_vfp_flag_);
346 PrintF("OVERFLOW flag: %d; ", sim_->overflow_vfp_flag_);
347 PrintF("UNDERFLOW flag: %d; ", sim_->underflow_vfp_flag_);
348 PrintF("INEXACT flag: %d; ", sim_->inexact_vfp_flag_);
349 } else if (strcmp(cmd, "unstop") == 0) {
350 intptr_t stop_pc = sim_->get_pc() - Instr::kInstrSize;
351 Instr* stop_instr = reinterpret_cast<Instr*>(stop_pc);
352 if (stop_instr->ConditionField() == special_condition) {
353 stop_instr->SetInstructionBits(kNopInstr);
354 } else {
355 PrintF("Not at debugger stop.");
356 }
357 } else if ((strcmp(cmd, "t") == 0) || strcmp(cmd, "trace") == 0) {
358 ::v8::internal::FLAG_trace_sim = !::v8::internal::FLAG_trace_sim;
359 PrintF("Trace of executed instructions is %s\n",
360 ::v8::internal::FLAG_trace_sim ? "on" : "off");
361 } else if ((strcmp(cmd, "h") == 0) || (strcmp(cmd, "help") == 0)) {
362 PrintF("cont\n");
363 PrintF(" continue execution (alias 'c')\n");
364 PrintF("stepi\n");
365 PrintF(" step one instruction (alias 'si')\n");
366 PrintF("print <register>\n");
367 PrintF(" print register content (alias 'p')\n");
368 PrintF(" use register name 'all' to print all registers\n");
369 PrintF("printobject <register>\n");
370 PrintF(" print an object from a register (alias 'po')\n");
371 PrintF("flags\n");
372 PrintF(" print flags\n");
373 PrintF("disasm [<instructions>]\n");
374 PrintF("disasm [[<address>] <instructions>]\n");
375 PrintF(" disassemble code, default is 10 instructions from pc\n");
376 PrintF("gdb\n");
377 PrintF(" enter gdb\n");
378 PrintF("break <address>\n");
379 PrintF(" set a break point on the address\n");
380 PrintF("del\n");
381 PrintF(" delete the breakpoint\n");
382 PrintF("unstop\n");
383 PrintF(" ignore the stop instruction at the current location");
384 PrintF(" from now on\n");
385 PrintF("trace (alias 't')\n");
386 PrintF(" toogle the tracing of all executed statements");
387 } else {
388 PrintF("Unknown command: %s\n", cmd);
389 }
390 }
391 DeleteArray(line);
392 }
393
394 // Add all the breakpoints back to stop execution and enter the debugger
395 // shell when hit.
396 RedoBreakpoints();
397
398 #undef COMMAND_SIZE
399 #undef ARG_SIZE
400
401 #undef STR
402 #undef XSTR
403 }
404
405
406 // Create one simulator per thread and keep it in thread local storage.
407 static v8::internal::Thread::LocalStorageKey simulator_key;
408
409
410 bool Simulator::initialized_ = false;
411
412
413 void Simulator::Initialize() {
414 if (initialized_) return;
415 PrintF("This is actually the thumb2 simulator!\n");
416 simulator_key = v8::internal::Thread::CreateThreadLocalKey();
417 initialized_ = true;
418 ::v8::internal::ExternalReference::set_redirector(&RedirectExternalReference);
419 }
420
421
422 Simulator::Simulator() {
423 Initialize();
424 // Setup simulator support first. Some of this information is needed to
425 // setup the architecture state.
426 size_t stack_size = 1 * 1024*1024; // allocate 1MB for stack
427 stack_ = reinterpret_cast<char*>(malloc(stack_size));
428 pc_modified_ = false;
429 icount_ = 0;
430 break_pc_ = NULL;
431 break_instr_ = 0;
432
433 // Setup architecture state.
434 // All registers are initialized to zero to start with.
435 for (int i = 0; i < num_registers; i++) {
436 registers_[i] = 0;
437 }
438 n_flag_ = false;
439 z_flag_ = false;
440 c_flag_ = false;
441 v_flag_ = false;
442
443 // Initializing VFP registers.
444 // All registers are initialized to zero to start with
445 // even though s_registers_ & d_registers_ share the same
446 // physical registers in the target.
447 for (int i = 0; i < num_s_registers; i++) {
448 vfp_register[i] = 0;
449 }
450 n_flag_FPSCR_ = false;
451 z_flag_FPSCR_ = false;
452 c_flag_FPSCR_ = false;
453 v_flag_FPSCR_ = false;
454
455 inv_op_vfp_flag_ = false;
456 div_zero_vfp_flag_ = false;
457 overflow_vfp_flag_ = false;
458 underflow_vfp_flag_ = false;
459 inexact_vfp_flag_ = false;
460
461 // The sp is initialized to point to the bottom (high address) of the
462 // allocated stack area. To be safe in potential stack underflows we leave
463 // some buffer below.
464 registers_[sp] = reinterpret_cast<int32_t>(stack_) + stack_size - 64;
465 // The lr and pc are initialized to a known bad value that will cause an
466 // access violation if the simulator ever tries to execute it.
467 registers_[pc] = bad_lr;
468 registers_[lr] = bad_lr;
469
470 enter_debug_ = false;
471
472 InitializeCoverage();
473 }
474
475
476 // When the generated code calls an external reference we need to catch that in
477 // the simulator. The external reference will be a function compiled for the
478 // host architecture. We need to call that function instead of trying to
479 // execute it with the simulator. We do that by redirecting the external
480 // reference to a swi (software-interrupt) instruction that is handled by
481 // the simulator. We write the original destination of the jump just at a known
482 // offset from the swi instruction so the simulator knows what to call.
483 class Redirection {
484 public:
485 Redirection(void* external_function, bool fp_return)
486 : external_function_(external_function),
487 swi_instruction_((AL << 28) | (0xf << 24) | call_rt_redirected),
488 fp_return_(fp_return),
489 next_(list_) {
490 list_ = this;
491 }
492
493 void* address_of_swi_instruction() {
494 return reinterpret_cast<void*>(&swi_instruction_);
495 }
496
497 void* external_function() { return external_function_; }
498 bool fp_return() { return fp_return_; }
499
500 static Redirection* Get(void* external_function, bool fp_return) {
501 Redirection* current;
502 for (current = list_; current != NULL; current = current->next_) {
503 if (current->external_function_ == external_function) return current;
504 }
505 return new Redirection(external_function, fp_return);
506 }
507
508 static Redirection* FromSwiInstruction(Instr* swi_instruction) {
509 char* addr_of_swi = reinterpret_cast<char*>(swi_instruction);
510 char* addr_of_redirection =
511 addr_of_swi - OFFSET_OF(Redirection, swi_instruction_);
512 return reinterpret_cast<Redirection*>(addr_of_redirection);
513 }
514
515 private:
516 void* external_function_;
517 uint32_t swi_instruction_;
518 bool fp_return_;
519 Redirection* next_;
520 static Redirection* list_;
521 };
522
523
524 Redirection* Redirection::list_ = NULL;
525
526
527 void* Simulator::RedirectExternalReference(void* external_function,
528 bool fp_return) {
529 Redirection* redirection = Redirection::Get(external_function, fp_return);
530 return redirection->address_of_swi_instruction();
531 }
532
533
534 // Get the active Simulator for the current thread.
535 Simulator* Simulator::current() {
536 Initialize();
537 Simulator* sim = reinterpret_cast<Simulator*>(
538 v8::internal::Thread::GetThreadLocal(simulator_key));
539 if (sim == NULL) {
540 // TODO(146): delete the simulator object when a thread goes away.
541 sim = new Simulator();
542 v8::internal::Thread::SetThreadLocal(simulator_key, sim);
543 }
544 return sim;
545 }
546
547
548 // Sets the register in the architecture state. It will also deal with updating
549 // Simulator internal state for special registers such as PC.
550 void Simulator::set_register(int reg, int32_t value) {
551 ASSERT((reg >= 0) && (reg < num_registers));
552 if (reg == pc) {
553 pc_modified_ = true;
554 }
555 registers_[reg] = value;
556 }
557
558
559 // Get the register from the architecture state. This function does handle
560 // the special case of accessing the PC register.
561 int32_t Simulator::get_register(int reg) const {
562 ASSERT((reg >= 0) && (reg < num_registers));
563 if (reg == pc) {
564 int32_t v = registers_[reg];
565 return v + ((v & 1) ? + Instr::kPCReadOffsetThumb : Instr::kPCReadOffset);
566 }
567 return registers_[reg];
568 }
569
570
571 // Raw access to the PC register.
572 void Simulator::set_pc(int32_t value) {
573 pc_modified_ = true;
574 registers_[pc] = value;
575 }
576
577
578 // Raw access to the PC register without the special adjustment when reading.
579 int32_t Simulator::get_pc() const {
580 return registers_[pc];
581 }
582
583
584 // Getting from and setting into VFP registers.
585 void Simulator::set_s_register(int sreg, unsigned int value) {
586 ASSERT((sreg >= 0) && (sreg < num_s_registers));
587 vfp_register[sreg] = value;
588 }
589
590
591 unsigned int Simulator::get_s_register(int sreg) const {
592 ASSERT((sreg >= 0) && (sreg < num_s_registers));
593 return vfp_register[sreg];
594 }
595
596
597 void Simulator::set_s_register_from_float(int sreg, const float flt) {
598 ASSERT((sreg >= 0) && (sreg < num_s_registers));
599 // Read the bits from the single precision floating point value
600 // into the unsigned integer element of vfp_register[] given by index=sreg.
601 char buffer[sizeof(vfp_register[0])];
602 memcpy(buffer, &flt, sizeof(vfp_register[0]));
603 memcpy(&vfp_register[sreg], buffer, sizeof(vfp_register[0]));
604 }
605
606
607 void Simulator::set_s_register_from_sinteger(int sreg, const int sint) {
608 ASSERT((sreg >= 0) && (sreg < num_s_registers));
609 // Read the bits from the integer value into the unsigned integer element of
610 // vfp_register[] given by index=sreg.
611 char buffer[sizeof(vfp_register[0])];
612 memcpy(buffer, &sint, sizeof(vfp_register[0]));
613 memcpy(&vfp_register[sreg], buffer, sizeof(vfp_register[0]));
614 }
615
616
617 void Simulator::set_d_register_from_double(int dreg, const double& dbl) {
618 ASSERT((dreg >= 0) && (dreg < num_d_registers));
619 // Read the bits from the double precision floating point value into the two
620 // consecutive unsigned integer elements of vfp_register[] given by index
621 // 2*sreg and 2*sreg+1.
622 char buffer[2 * sizeof(vfp_register[0])];
623 memcpy(buffer, &dbl, 2 * sizeof(vfp_register[0]));
624 #ifndef BIG_ENDIAN_FLOATING_POINT
625 memcpy(&vfp_register[dreg * 2], buffer, 2 * sizeof(vfp_register[0]));
626 #else
627 memcpy(&vfp_register[dreg * 2], &buffer[4], sizeof(vfp_register[0]));
628 memcpy(&vfp_register[dreg * 2 + 1], &buffer[0], sizeof(vfp_register[0]));
629 #endif
630 }
631
632
633 float Simulator::get_float_from_s_register(int sreg) {
634 ASSERT((sreg >= 0) && (sreg < num_s_registers));
635
636 float sm_val = 0.0;
637 // Read the bits from the unsigned integer vfp_register[] array
638 // into the single precision floating point value and return it.
639 char buffer[sizeof(vfp_register[0])];
640 memcpy(buffer, &vfp_register[sreg], sizeof(vfp_register[0]));
641 memcpy(&sm_val, buffer, sizeof(vfp_register[0]));
642 return(sm_val);
643 }
644
645
646 int Simulator::get_sinteger_from_s_register(int sreg) {
647 ASSERT((sreg >= 0) && (sreg < num_s_registers));
648
649 int sm_val = 0;
650 // Read the bits from the unsigned integer vfp_register[] array
651 // into the single precision floating point value and return it.
652 char buffer[sizeof(vfp_register[0])];
653 memcpy(buffer, &vfp_register[sreg], sizeof(vfp_register[0]));
654 memcpy(&sm_val, buffer, sizeof(vfp_register[0]));
655 return(sm_val);
656 }
657
658
659 double Simulator::get_double_from_d_register(int dreg) {
660 ASSERT((dreg >= 0) && (dreg < num_d_registers));
661
662 double dm_val = 0.0;
663 // Read the bits from the unsigned integer vfp_register[] array
664 // into the double precision floating point value and return it.
665 char buffer[2 * sizeof(vfp_register[0])];
666 #ifdef BIG_ENDIAN_FLOATING_POINT
667 memcpy(&buffer[0], &vfp_register[2 * dreg + 1], sizeof(vfp_register[0]));
668 memcpy(&buffer[4], &vfp_register[2 * dreg], sizeof(vfp_register[0]));
669 #else
670 memcpy(buffer, &vfp_register[2 * dreg], 2 * sizeof(vfp_register[0]));
671 #endif
672 memcpy(&dm_val, buffer, 2 * sizeof(vfp_register[0]));
673 return(dm_val);
674 }
675
676
677 // For use in calls that take two double values, constructed from r0, r1, r2
678 // and r3.
679 void Simulator::GetFpArgs(double* x, double* y) {
680 // We use a char buffer to get around the strict-aliasing rules which
681 // otherwise allow the compiler to optimize away the copy.
682 char buffer[2 * sizeof(registers_[0])];
683 // Registers 0 and 1 -> x.
684 memcpy(buffer, registers_, sizeof(buffer));
685 memcpy(x, buffer, sizeof(buffer));
686 // Registers 2 and 3 -> y.
687 memcpy(buffer, registers_ + 2, sizeof(buffer));
688 memcpy(y, buffer, sizeof(buffer));
689 }
690
691
692 void Simulator::SetFpResult(const double& result) {
693 char buffer[2 * sizeof(registers_[0])];
694 memcpy(buffer, &result, sizeof(buffer));
695 // result -> registers 0 and 1.
696 memcpy(registers_, buffer, sizeof(buffer));
697 }
698
699
700 void Simulator::TrashCallerSaveRegisters() {
701 // We don't trash the registers with the return value.
702 registers_[2] = 0x50Bad4U;
703 registers_[3] = 0x50Bad4U;
704 registers_[12] = 0x50Bad4U;
705 }
706
707
708 // The ARM cannot do unaligned reads and writes. On some ARM platforms an
709 // interrupt is caused. On others it does a funky rotation thing. For now we
710 // simply disallow unaligned reads, but at some point we may want to move to
711 // emulating the rotate behaviour. Note that simulator runs have the runtime
712 // system running directly on the host system and only generated code is
713 // executed in the simulator. Since the host is typically IA32 we will not
714 // get the correct ARM-like behaviour on unaligned accesses.
715
716 int Simulator::ReadW(int32_t addr, Instr* instr) {
717 if ((addr & 3) == 0) {
718 intptr_t* ptr = reinterpret_cast<intptr_t*>(addr);
719 return *ptr;
720 }
721 PrintF("Unaligned read at 0x%08x\n", addr);
722 UNIMPLEMENTED();
723 return 0;
724 }
725
726
727 void Simulator::WriteW(int32_t addr, int value, Instr* instr) {
728 if ((addr & 3) == 0) {
729 intptr_t* ptr = reinterpret_cast<intptr_t*>(addr);
730 *ptr = value;
731 return;
732 }
733 PrintF("Unaligned write at 0x%08x, pc=%p\n", addr, instr);
734 UNIMPLEMENTED();
735 }
736
737
738 uint16_t Simulator::ReadHU(int32_t addr, Instr* instr) {
739 if ((addr & 1) == 0) {
740 uint16_t* ptr = reinterpret_cast<uint16_t*>(addr);
741 return *ptr;
742 }
743 PrintF("Unaligned unsigned halfword read at 0x%08x, pc=%p\n", addr, instr);
744 UNIMPLEMENTED();
745 return 0;
746 }
747
748
749 int16_t Simulator::ReadH(int32_t addr, Instr* instr) {
750 if ((addr & 1) == 0) {
751 int16_t* ptr = reinterpret_cast<int16_t*>(addr);
752 return *ptr;
753 }
754 PrintF("Unaligned signed halfword read at 0x%08x\n", addr);
755 UNIMPLEMENTED();
756 return 0;
757 }
758
759
760 void Simulator::WriteH(int32_t addr, uint16_t value, Instr* instr) {
761 if ((addr & 1) == 0) {
762 uint16_t* ptr = reinterpret_cast<uint16_t*>(addr);
763 *ptr = value;
764 return;
765 }
766 PrintF("Unaligned unsigned halfword write at 0x%08x, pc=%p\n", addr, instr);
767 UNIMPLEMENTED();
768 }
769
770
771 void Simulator::WriteH(int32_t addr, int16_t value, Instr* instr) {
772 if ((addr & 1) == 0) {
773 int16_t* ptr = reinterpret_cast<int16_t*>(addr);
774 *ptr = value;
775 return;
776 }
777 PrintF("Unaligned halfword write at 0x%08x, pc=%p\n", addr, instr);
778 UNIMPLEMENTED();
779 }
780
781
782 uint8_t Simulator::ReadBU(int32_t addr) {
783 uint8_t* ptr = reinterpret_cast<uint8_t*>(addr);
784 return *ptr;
785 }
786
787
788 int8_t Simulator::ReadB(int32_t addr) {
789 int8_t* ptr = reinterpret_cast<int8_t*>(addr);
790 return *ptr;
791 }
792
793
794 void Simulator::WriteB(int32_t addr, uint8_t value) {
795 uint8_t* ptr = reinterpret_cast<uint8_t*>(addr);
796 *ptr = value;
797 }
798
799
800 void Simulator::WriteB(int32_t addr, int8_t value) {
801 int8_t* ptr = reinterpret_cast<int8_t*>(addr);
802 *ptr = value;
803 }
804
805
806 // Returns the limit of the stack area to enable checking for stack overflows.
807 uintptr_t Simulator::StackLimit() const {
808 // Leave a safety margin of 256 bytes to prevent overrunning the stack when
809 // pushing values.
810 return reinterpret_cast<uintptr_t>(stack_) + 256;
811 }
812
813
814 // Unsupported instructions use Format to print an error and stop execution.
815 void Simulator::Format(Instr* instr, const char* format) {
816 PrintF("Simulator found unsupported instruction:\n 0x%08x: %s\n",
817 instr, format);
818 UNIMPLEMENTED();
819 }
820
821
822 // Checks if the current instruction should be executed based on its
823 // condition bits.
824 bool Simulator::ConditionallyExecute(Instr* instr) {
825 switch (instr->ConditionField()) {
826 case EQ: return z_flag_;
827 case NE: return !z_flag_;
828 case CS: return c_flag_;
829 case CC: return !c_flag_;
830 case MI: return n_flag_;
831 case PL: return !n_flag_;
832 case VS: return v_flag_;
833 case VC: return !v_flag_;
834 case HI: return c_flag_ && !z_flag_;
835 case LS: return !c_flag_ || z_flag_;
836 case GE: return n_flag_ == v_flag_;
837 case LT: return n_flag_ != v_flag_;
838 case GT: return !z_flag_ && (n_flag_ == v_flag_);
839 case LE: return z_flag_ || (n_flag_ != v_flag_);
840 case AL: return true;
841 default: UNREACHABLE();
842 }
843 return false;
844 }
845
846
847 // Calculate and set the Negative and Zero flags.
848 void Simulator::SetNZFlags(int32_t val) {
849 n_flag_ = (val < 0);
850 z_flag_ = (val == 0);
851 }
852
853
854 // Set the Carry flag.
855 void Simulator::SetCFlag(bool val) {
856 c_flag_ = val;
857 }
858
859
860 // Set the oVerflow flag.
861 void Simulator::SetVFlag(bool val) {
862 v_flag_ = val;
863 }
864
865
866 // Calculate C flag value for additions.
867 bool Simulator::CarryFrom(int32_t left, int32_t right) {
868 uint32_t uleft = static_cast<uint32_t>(left);
869 uint32_t uright = static_cast<uint32_t>(right);
870 uint32_t urest = 0xffffffffU - uleft;
871
872 return (uright > urest);
873 }
874
875
876 // Calculate C flag value for subtractions.
877 bool Simulator::BorrowFrom(int32_t left, int32_t right) {
878 uint32_t uleft = static_cast<uint32_t>(left);
879 uint32_t uright = static_cast<uint32_t>(right);
880
881 return (uright > uleft);
882 }
883
884
885 // Calculate V flag value for additions and subtractions.
886 bool Simulator::OverflowFrom(int32_t alu_out,
887 int32_t left, int32_t right, bool addition) {
888 bool overflow;
889 if (addition) {
890 // operands have the same sign
891 overflow = ((left >= 0 && right >= 0) || (left < 0 && right < 0))
892 // and operands and result have different sign
893 && ((left < 0 && alu_out >= 0) || (left >= 0 && alu_out < 0));
894 } else {
895 // operands have different signs
896 overflow = ((left < 0 && right >= 0) || (left >= 0 && right < 0))
897 // and first operand and result have different signs
898 && ((left < 0 && alu_out >= 0) || (left >= 0 && alu_out < 0));
899 }
900 return overflow;
901 }
902
903
904 // Support for VFP comparisons.
905 void Simulator::Compute_FPSCR_Flags(double val1, double val2) {
906 if (isnan(val1) || isnan(val2)) {
907 n_flag_FPSCR_ = false;
908 z_flag_FPSCR_ = false;
909 c_flag_FPSCR_ = true;
910 v_flag_FPSCR_ = true;
911 // All non-NaN cases.
912 } else if (val1 == val2) {
913 n_flag_FPSCR_ = false;
914 z_flag_FPSCR_ = true;
915 c_flag_FPSCR_ = true;
916 v_flag_FPSCR_ = false;
917 } else if (val1 < val2) {
918 n_flag_FPSCR_ = true;
919 z_flag_FPSCR_ = false;
920 c_flag_FPSCR_ = false;
921 v_flag_FPSCR_ = false;
922 } else {
923 // Case when (val1 > val2).
924 n_flag_FPSCR_ = false;
925 z_flag_FPSCR_ = false;
926 c_flag_FPSCR_ = true;
927 v_flag_FPSCR_ = false;
928 }
929 }
930
931
932 void Simulator::Copy_FPSCR_to_APSR() {
933 n_flag_ = n_flag_FPSCR_;
934 z_flag_ = z_flag_FPSCR_;
935 c_flag_ = c_flag_FPSCR_;
936 v_flag_ = v_flag_FPSCR_;
937 }
938
939
940 // Addressing Mode 1 - Data-processing operands:
941 // Get the value based on the shifter_operand with register.
942 int32_t Simulator::GetShiftRm(Instr* instr, bool* carry_out) {
943 Shift shift = instr->ShiftField();
944 int shift_amount = instr->ShiftAmountField();
945 int32_t result = get_register(instr->RmField());
946 if (instr->Bit(4) == 0) {
947 // by immediate
948 if ((shift == ROR) && (shift_amount == 0)) {
949 UNIMPLEMENTED();
950 return result;
951 } else if (((shift == LSR) || (shift == ASR)) && (shift_amount == 0)) {
952 shift_amount = 32;
953 }
954 switch (shift) {
955 case ASR: {
956 if (shift_amount == 0) {
957 if (result < 0) {
958 result = 0xffffffff;
959 *carry_out = true;
960 } else {
961 result = 0;
962 *carry_out = false;
963 }
964 } else {
965 result >>= (shift_amount - 1);
966 *carry_out = (result & 1) == 1;
967 result >>= 1;
968 }
969 break;
970 }
971
972 case LSL: {
973 if (shift_amount == 0) {
974 *carry_out = c_flag_;
975 } else {
976 result <<= (shift_amount - 1);
977 *carry_out = (result < 0);
978 result <<= 1;
979 }
980 break;
981 }
982
983 case LSR: {
984 if (shift_amount == 0) {
985 result = 0;
986 *carry_out = c_flag_;
987 } else {
988 uint32_t uresult = static_cast<uint32_t>(result);
989 uresult >>= (shift_amount - 1);
990 *carry_out = (uresult & 1) == 1;
991 uresult >>= 1;
992 result = static_cast<int32_t>(uresult);
993 }
994 break;
995 }
996
997 case ROR: {
998 UNIMPLEMENTED();
999 break;
1000 }
1001
1002 default: {
1003 UNREACHABLE();
1004 break;
1005 }
1006 }
1007 } else {
1008 // by register
1009 int rs = instr->RsField();
1010 shift_amount = get_register(rs) &0xff;
1011 switch (shift) {
1012 case ASR: {
1013 if (shift_amount == 0) {
1014 *carry_out = c_flag_;
1015 } else if (shift_amount < 32) {
1016 result >>= (shift_amount - 1);
1017 *carry_out = (result & 1) == 1;
1018 result >>= 1;
1019 } else {
1020 ASSERT(shift_amount >= 32);
1021 if (result < 0) {
1022 *carry_out = true;
1023 result = 0xffffffff;
1024 } else {
1025 *carry_out = false;
1026 result = 0;
1027 }
1028 }
1029 break;
1030 }
1031
1032 case LSL: {
1033 if (shift_amount == 0) {
1034 *carry_out = c_flag_;
1035 } else if (shift_amount < 32) {
1036 result <<= (shift_amount - 1);
1037 *carry_out = (result < 0);
1038 result <<= 1;
1039 } else if (shift_amount == 32) {
1040 *carry_out = (result & 1) == 1;
1041 result = 0;
1042 } else {
1043 ASSERT(shift_amount > 32);
1044 *carry_out = false;
1045 result = 0;
1046 }
1047 break;
1048 }
1049
1050 case LSR: {
1051 if (shift_amount == 0) {
1052 *carry_out = c_flag_;
1053 } else if (shift_amount < 32) {
1054 uint32_t uresult = static_cast<uint32_t>(result);
1055 uresult >>= (shift_amount - 1);
1056 *carry_out = (uresult & 1) == 1;
1057 uresult >>= 1;
1058 result = static_cast<int32_t>(uresult);
1059 } else if (shift_amount == 32) {
1060 *carry_out = (result < 0);
1061 result = 0;
1062 } else {
1063 *carry_out = false;
1064 result = 0;
1065 }
1066 break;
1067 }
1068
1069 case ROR: {
1070 UNIMPLEMENTED();
1071 break;
1072 }
1073
1074 default: {
1075 UNREACHABLE();
1076 break;
1077 }
1078 }
1079 }
1080 return result;
1081 }
1082
1083
1084 // Addressing Mode 1 - Data-processing operands:
1085 // Get the value based on the shifter_operand with immediate.
1086 int32_t Simulator::GetImm(Instr* instr, bool* carry_out) {
1087 int rotate = instr->RotateField() * 2;
1088 int immed8 = instr->Immed8Field();
1089 int imm = (immed8 >> rotate) | (immed8 << (32 - rotate));
1090 *carry_out = (rotate == 0) ? c_flag_ : (imm < 0);
1091 return imm;
1092 }
1093
1094
1095 static int count_bits(int bit_vector) {
1096 int count = 0;
1097 while (bit_vector != 0) {
1098 if ((bit_vector & 1) != 0) {
1099 count++;
1100 }
1101 bit_vector >>= 1;
1102 }
1103 return count;
1104 }
1105
1106
1107 // Addressing Mode 4 - Load and Store Multiple
1108 void Simulator::HandleRList(Instr* instr, bool load) {
1109 int rn = instr->RnField();
1110 int32_t rn_val = get_register(rn);
1111 int rlist = instr->RlistField();
1112 int num_regs = count_bits(rlist);
1113
1114 intptr_t start_address = 0;
1115 intptr_t end_address = 0;
1116 switch (instr->PUField()) {
1117 case 0: {
1118 // Print("da");
1119 UNIMPLEMENTED();
1120 break;
1121 }
1122 case 1: {
1123 // Print("ia");
1124 start_address = rn_val;
1125 end_address = rn_val + (num_regs * 4) - 4;
1126 rn_val = rn_val + (num_regs * 4);
1127 break;
1128 }
1129 case 2: {
1130 // Print("db");
1131 start_address = rn_val - (num_regs * 4);
1132 end_address = rn_val - 4;
1133 rn_val = start_address;
1134 break;
1135 }
1136 case 3: {
1137 // Print("ib");
1138 UNIMPLEMENTED();
1139 break;
1140 }
1141 default: {
1142 UNREACHABLE();
1143 break;
1144 }
1145 }
1146 if (instr->HasW()) {
1147 set_register(rn, rn_val);
1148 }
1149 intptr_t* address = reinterpret_cast<intptr_t*>(start_address);
1150 int reg = 0;
1151 while (rlist != 0) {
1152 if ((rlist & 1) != 0) {
1153 if (load) {
1154 set_register(reg, *address);
1155 } else {
1156 *address = get_register(reg);
1157 }
1158 address += 1;
1159 }
1160 reg++;
1161 rlist >>= 1;
1162 }
1163 ASSERT(end_address == ((intptr_t)address) - 4);
1164 }
1165
1166
1167 // Calls into the V8 runtime are based on this very simple interface.
1168 // Note: To be able to return two values from some calls the code in runtime.cc
1169 // uses the ObjectPair which is essentially two 32-bit values stuffed into a
1170 // 64-bit value. With the code below we assume that all runtime calls return
1171 // 64 bits of result. If they don't, the r1 result register contains a bogus
1172 // value, which is fine because it is caller-saved.
1173 typedef int64_t (*SimulatorRuntimeCall)(int32_t arg0,
1174 int32_t arg1,
1175 int32_t arg2,
1176 int32_t arg3);
1177 typedef double (*SimulatorRuntimeFPCall)(int32_t arg0,
1178 int32_t arg1,
1179 int32_t arg2,
1180 int32_t arg3);
1181
1182
1183 // Software interrupt instructions are used by the simulator to call into the
1184 // C-based V8 runtime.
1185 void Simulator::SoftwareInterrupt(Instr* instr) {
1186 int swi = instr->SwiField();
1187 switch (swi) {
1188 case call_rt_redirected: {
1189 Redirection* redirection = Redirection::FromSwiInstruction(instr);
1190 int32_t arg0 = get_register(r0);
1191 int32_t arg1 = get_register(r1);
1192 int32_t arg2 = get_register(r2);
1193 int32_t arg3 = get_register(r3);
1194 // This is dodgy but it works because the C entry stubs are never moved.
1195 // See comment in codegen-arm.cc and bug 1242173.
1196 int32_t saved_lr = get_register(lr);
1197 if (redirection->fp_return()) {
1198 intptr_t external =
1199 reinterpret_cast<intptr_t>(redirection->external_function());
1200 SimulatorRuntimeFPCall target =
1201 reinterpret_cast<SimulatorRuntimeFPCall>(external);
1202 if (::v8::internal::FLAG_trace_sim) {
1203 double x, y;
1204 GetFpArgs(&x, &y);
1205 PrintF("Call to host function at %p with args %f, %f\n",
1206 FUNCTION_ADDR(target), x, y);
1207 }
1208 double result = target(arg0, arg1, arg2, arg3);
1209 SetFpResult(result);
1210 } else {
1211 intptr_t external =
1212 reinterpret_cast<int32_t>(redirection->external_function());
1213 SimulatorRuntimeCall target =
1214 reinterpret_cast<SimulatorRuntimeCall>(external);
1215 if (::v8::internal::FLAG_trace_sim) {
1216 PrintF(
1217 "Call to host function at %p with args %08x, %08x, %08x, %08x\n",
1218 FUNCTION_ADDR(target),
1219 arg0,
1220 arg1,
1221 arg2,
1222 arg3);
1223 }
1224 int64_t result = target(arg0, arg1, arg2, arg3);
1225 int32_t lo_res = static_cast<int32_t>(result);
1226 int32_t hi_res = static_cast<int32_t>(result >> 32);
1227 if (::v8::internal::FLAG_trace_sim) {
1228 PrintF("Returned %08x\n", lo_res);
1229 }
1230 set_register(r0, lo_res);
1231 set_register(r1, hi_res);
1232 }
1233 set_register(lr, saved_lr);
1234 set_pc(get_register(lr));
1235 break;
1236 }
1237 case break_point: {
1238 Debugger dbg(this);
1239 dbg.Debug();
1240 break;
1241 }
1242 default: {
1243 UNREACHABLE();
1244 break;
1245 }
1246 }
1247 }
1248
1249
1250 // Handle execution based on instruction types.
1251
1252 // Instruction types 0 and 1 are both rolled into one function because they
1253 // only differ in the handling of the shifter_operand.
1254 void Simulator::DecodeType01(Instr* instr) {
1255 int type = instr->TypeField();
1256 if ((type == 0) && instr->IsSpecialType0()) {
1257 // multiply instruction or extra loads and stores
1258 if (instr->Bits(7, 4) == 9) {
1259 if (instr->Bit(24) == 0) {
1260 // Raw field decoding here. Multiply instructions have their Rd in
1261 // funny places.
1262 int rn = instr->RnField();
1263 int rm = instr->RmField();
1264 int rs = instr->RsField();
1265 int32_t rs_val = get_register(rs);
1266 int32_t rm_val = get_register(rm);
1267 if (instr->Bit(23) == 0) {
1268 if (instr->Bit(21) == 0) {
1269 // The MUL instruction description (A 4.1.33) refers to Rd as being
1270 // the destination for the operation, but it confusingly uses the
1271 // Rn field to encode it.
1272 // Format(instr, "mul'cond's 'rn, 'rm, 'rs");
1273 int rd = rn; // Remap the rn field to the Rd register.
1274 int32_t alu_out = rm_val * rs_val;
1275 set_register(rd, alu_out);
1276 if (instr->HasS()) {
1277 SetNZFlags(alu_out);
1278 }
1279 } else {
1280 // The MLA instruction description (A 4.1.28) refers to the order
1281 // of registers as "Rd, Rm, Rs, Rn". But confusingly it uses the
1282 // Rn field to encode the Rd register and the Rd field to encode
1283 // the Rn register.
1284 Format(instr, "mla'cond's 'rn, 'rm, 'rs, 'rd");
1285 }
1286 } else {
1287 // The signed/long multiply instructions use the terms RdHi and RdLo
1288 // when referring to the target registers. They are mapped to the Rn
1289 // and Rd fields as follows:
1290 // RdLo == Rd
1291 // RdHi == Rn (This is confusingly stored in variable rd here
1292 // because the mul instruction from above uses the
1293 // Rn field to encode the Rd register. Good luck figuring
1294 // this out without reading the ARM instruction manual
1295 // at a very detailed level.)
1296 // Format(instr, "'um'al'cond's 'rd, 'rn, 'rs, 'rm");
1297 int rd_hi = rn; // Remap the rn field to the RdHi register.
1298 int rd_lo = instr->RdField();
1299 int32_t hi_res = 0;
1300 int32_t lo_res = 0;
1301 if (instr->Bit(22) == 1) {
1302 int64_t left_op = static_cast<int32_t>(rm_val);
1303 int64_t right_op = static_cast<int32_t>(rs_val);
1304 uint64_t result = left_op * right_op;
1305 hi_res = static_cast<int32_t>(result >> 32);
1306 lo_res = static_cast<int32_t>(result & 0xffffffff);
1307 } else {
1308 // unsigned multiply
1309 uint64_t left_op = static_cast<uint32_t>(rm_val);
1310 uint64_t right_op = static_cast<uint32_t>(rs_val);
1311 uint64_t result = left_op * right_op;
1312 hi_res = static_cast<int32_t>(result >> 32);
1313 lo_res = static_cast<int32_t>(result & 0xffffffff);
1314 }
1315 set_register(rd_lo, lo_res);
1316 set_register(rd_hi, hi_res);
1317 if (instr->HasS()) {
1318 UNIMPLEMENTED();
1319 }
1320 }
1321 } else {
1322 UNIMPLEMENTED(); // Not used by V8.
1323 }
1324 } else {
1325 // extra load/store instructions
1326 int rd = instr->RdField();
1327 int rn = instr->RnField();
1328 int32_t rn_val = get_register(rn);
1329 int32_t addr = 0;
1330 if (instr->Bit(22) == 0) {
1331 int rm = instr->RmField();
1332 int32_t rm_val = get_register(rm);
1333 switch (instr->PUField()) {
1334 case 0: {
1335 // Format(instr, "'memop'cond'sign'h 'rd, ['rn], -'rm");
1336 ASSERT(!instr->HasW());
1337 addr = rn_val;
1338 rn_val -= rm_val;
1339 set_register(rn, rn_val);
1340 break;
1341 }
1342 case 1: {
1343 // Format(instr, "'memop'cond'sign'h 'rd, ['rn], +'rm");
1344 ASSERT(!instr->HasW());
1345 addr = rn_val;
1346 rn_val += rm_val;
1347 set_register(rn, rn_val);
1348 break;
1349 }
1350 case 2: {
1351 // Format(instr, "'memop'cond'sign'h 'rd, ['rn, -'rm]'w");
1352 rn_val -= rm_val;
1353 addr = rn_val;
1354 if (instr->HasW()) {
1355 set_register(rn, rn_val);
1356 }
1357 break;
1358 }
1359 case 3: {
1360 // Format(instr, "'memop'cond'sign'h 'rd, ['rn, +'rm]'w");
1361 rn_val += rm_val;
1362 addr = rn_val;
1363 if (instr->HasW()) {
1364 set_register(rn, rn_val);
1365 }
1366 break;
1367 }
1368 default: {
1369 // The PU field is a 2-bit field.
1370 UNREACHABLE();
1371 break;
1372 }
1373 }
1374 } else {
1375 int32_t imm_val = (instr->ImmedHField() << 4) | instr->ImmedLField();
1376 switch (instr->PUField()) {
1377 case 0: {
1378 // Format(instr, "'memop'cond'sign'h 'rd, ['rn], #-'off8");
1379 ASSERT(!instr->HasW());
1380 addr = rn_val;
1381 rn_val -= imm_val;
1382 set_register(rn, rn_val);
1383 break;
1384 }
1385 case 1: {
1386 // Format(instr, "'memop'cond'sign'h 'rd, ['rn], #+'off8");
1387 ASSERT(!instr->HasW());
1388 addr = rn_val;
1389 rn_val += imm_val;
1390 set_register(rn, rn_val);
1391 break;
1392 }
1393 case 2: {
1394 // Format(instr, "'memop'cond'sign'h 'rd, ['rn, #-'off8]'w");
1395 rn_val -= imm_val;
1396 addr = rn_val;
1397 if (instr->HasW()) {
1398 set_register(rn, rn_val);
1399 }
1400 break;
1401 }
1402 case 3: {
1403 // Format(instr, "'memop'cond'sign'h 'rd, ['rn, #+'off8]'w");
1404 rn_val += imm_val;
1405 addr = rn_val;
1406 if (instr->HasW()) {
1407 set_register(rn, rn_val);
1408 }
1409 break;
1410 }
1411 default: {
1412 // The PU field is a 2-bit field.
1413 UNREACHABLE();
1414 break;
1415 }
1416 }
1417 }
1418 if (instr->HasH()) {
1419 if (instr->HasSign()) {
1420 if (instr->HasL()) {
1421 int16_t val = ReadH(addr, instr);
1422 set_register(rd, val);
1423 } else {
1424 int16_t val = get_register(rd);
1425 WriteH(addr, val, instr);
1426 }
1427 } else {
1428 if (instr->HasL()) {
1429 uint16_t val = ReadHU(addr, instr);
1430 set_register(rd, val);
1431 } else {
1432 uint16_t val = get_register(rd);
1433 WriteH(addr, val, instr);
1434 }
1435 }
1436 } else {
1437 // signed byte loads
1438 ASSERT(instr->HasSign());
1439 ASSERT(instr->HasL());
1440 int8_t val = ReadB(addr);
1441 set_register(rd, val);
1442 }
1443 return;
1444 }
1445 } else {
1446 int rd = instr->RdField();
1447 int rn = instr->RnField();
1448 int32_t rn_val = get_register(rn);
1449 int32_t shifter_operand = 0;
1450 bool shifter_carry_out = 0;
1451 if (type == 0) {
1452 shifter_operand = GetShiftRm(instr, &shifter_carry_out);
1453 } else {
1454 ASSERT(instr->TypeField() == 1);
1455 shifter_operand = GetImm(instr, &shifter_carry_out);
1456 }
1457 int32_t alu_out;
1458
1459 switch (instr->OpcodeField()) {
1460 case AND: {
1461 // Format(instr, "and'cond's 'rd, 'rn, 'shift_rm");
1462 // Format(instr, "and'cond's 'rd, 'rn, 'imm");
1463 alu_out = rn_val & shifter_operand;
1464 set_register(rd, alu_out);
1465 if (instr->HasS()) {
1466 SetNZFlags(alu_out);
1467 SetCFlag(shifter_carry_out);
1468 }
1469 break;
1470 }
1471
1472 case EOR: {
1473 // Format(instr, "eor'cond's 'rd, 'rn, 'shift_rm");
1474 // Format(instr, "eor'cond's 'rd, 'rn, 'imm");
1475 alu_out = rn_val ^ shifter_operand;
1476 set_register(rd, alu_out);
1477 if (instr->HasS()) {
1478 SetNZFlags(alu_out);
1479 SetCFlag(shifter_carry_out);
1480 }
1481 break;
1482 }
1483
1484 case SUB: {
1485 // Format(instr, "sub'cond's 'rd, 'rn, 'shift_rm");
1486 // Format(instr, "sub'cond's 'rd, 'rn, 'imm");
1487 alu_out = rn_val - shifter_operand;
1488 set_register(rd, alu_out);
1489 if (instr->HasS()) {
1490 SetNZFlags(alu_out);
1491 SetCFlag(!BorrowFrom(rn_val, shifter_operand));
1492 SetVFlag(OverflowFrom(alu_out, rn_val, shifter_operand, false));
1493 }
1494 break;
1495 }
1496
1497 case RSB: {
1498 // Format(instr, "rsb'cond's 'rd, 'rn, 'shift_rm");
1499 // Format(instr, "rsb'cond's 'rd, 'rn, 'imm");
1500 alu_out = shifter_operand - rn_val;
1501 set_register(rd, alu_out);
1502 if (instr->HasS()) {
1503 SetNZFlags(alu_out);
1504 SetCFlag(!BorrowFrom(shifter_operand, rn_val));
1505 SetVFlag(OverflowFrom(alu_out, shifter_operand, rn_val, false));
1506 }
1507 break;
1508 }
1509
1510 case ADD: {
1511 // Format(instr, "add'cond's 'rd, 'rn, 'shift_rm");
1512 // Format(instr, "add'cond's 'rd, 'rn, 'imm");
1513 alu_out = rn_val + shifter_operand;
1514 set_register(rd, alu_out);
1515 if (instr->HasS()) {
1516 SetNZFlags(alu_out);
1517 SetCFlag(CarryFrom(rn_val, shifter_operand));
1518 SetVFlag(OverflowFrom(alu_out, rn_val, shifter_operand, true));
1519 }
1520 break;
1521 }
1522
1523 case ADC: {
1524 Format(instr, "adc'cond's 'rd, 'rn, 'shift_rm");
1525 Format(instr, "adc'cond's 'rd, 'rn, 'imm");
1526 break;
1527 }
1528
1529 case SBC: {
1530 Format(instr, "sbc'cond's 'rd, 'rn, 'shift_rm");
1531 Format(instr, "sbc'cond's 'rd, 'rn, 'imm");
1532 break;
1533 }
1534
1535 case RSC: {
1536 Format(instr, "rsc'cond's 'rd, 'rn, 'shift_rm");
1537 Format(instr, "rsc'cond's 'rd, 'rn, 'imm");
1538 break;
1539 }
1540
1541 case TST: {
1542 if (instr->HasS()) {
1543 // Format(instr, "tst'cond 'rn, 'shift_rm");
1544 // Format(instr, "tst'cond 'rn, 'imm");
1545 alu_out = rn_val & shifter_operand;
1546 SetNZFlags(alu_out);
1547 SetCFlag(shifter_carry_out);
1548 } else {
1549 UNIMPLEMENTED();
1550 }
1551 break;
1552 }
1553
1554 case TEQ: {
1555 if (instr->HasS()) {
1556 // Format(instr, "teq'cond 'rn, 'shift_rm");
1557 // Format(instr, "teq'cond 'rn, 'imm");
1558 alu_out = rn_val ^ shifter_operand;
1559 SetNZFlags(alu_out);
1560 SetCFlag(shifter_carry_out);
1561 } else {
1562 ASSERT(type == 0);
1563 int rm = instr->RmField();
1564 switch (instr->Bits(7, 4)) {
1565 case BX:
1566 set_pc(get_register(rm));
1567 break;
1568 case BLX: {
1569 uint32_t old_pc = get_pc();
1570 set_pc(get_register(rm));
1571 set_register(lr, old_pc + Instr::kInstrSize);
1572 break;
1573 }
1574 default:
1575 UNIMPLEMENTED();
1576 }
1577 }
1578 break;
1579 }
1580
1581 case CMP: {
1582 if (instr->HasS()) {
1583 // Format(instr, "cmp'cond 'rn, 'shift_rm");
1584 // Format(instr, "cmp'cond 'rn, 'imm");
1585 alu_out = rn_val - shifter_operand;
1586 SetNZFlags(alu_out);
1587 SetCFlag(!BorrowFrom(rn_val, shifter_operand));
1588 SetVFlag(OverflowFrom(alu_out, rn_val, shifter_operand, false));
1589 } else {
1590 UNIMPLEMENTED();
1591 }
1592 break;
1593 }
1594
1595 case CMN: {
1596 if (instr->HasS()) {
1597 // Format(instr, "cmn'cond 'rn, 'shift_rm");
1598 // Format(instr, "cmn'cond 'rn, 'imm");
1599 alu_out = rn_val + shifter_operand;
1600 SetNZFlags(alu_out);
1601 SetCFlag(!CarryFrom(rn_val, shifter_operand));
1602 SetVFlag(OverflowFrom(alu_out, rn_val, shifter_operand, true));
1603 } else {
1604 ASSERT(type == 0);
1605 int rm = instr->RmField();
1606 int rd = instr->RdField();
1607 switch (instr->Bits(7, 4)) {
1608 case CLZ: {
1609 uint32_t bits = get_register(rm);
1610 int leading_zeros = 0;
1611 if (bits == 0) {
1612 leading_zeros = 32;
1613 } else {
1614 while ((bits & 0x80000000u) == 0) {
1615 bits <<= 1;
1616 leading_zeros++;
1617 }
1618 }
1619 set_register(rd, leading_zeros);
1620 break;
1621 }
1622 default:
1623 UNIMPLEMENTED();
1624 }
1625 }
1626 break;
1627 }
1628
1629 case ORR: {
1630 // Format(instr, "orr'cond's 'rd, 'rn, 'shift_rm");
1631 // Format(instr, "orr'cond's 'rd, 'rn, 'imm");
1632 alu_out = rn_val | shifter_operand;
1633 set_register(rd, alu_out);
1634 if (instr->HasS()) {
1635 SetNZFlags(alu_out);
1636 SetCFlag(shifter_carry_out);
1637 }
1638 break;
1639 }
1640
1641 case MOV: {
1642 // Format(instr, "mov'cond's 'rd, 'shift_rm");
1643 // Format(instr, "mov'cond's 'rd, 'imm");
1644 alu_out = shifter_operand;
1645 set_register(rd, alu_out);
1646 if (instr->HasS()) {
1647 SetNZFlags(alu_out);
1648 SetCFlag(shifter_carry_out);
1649 }
1650 break;
1651 }
1652
1653 case BIC: {
1654 // Format(instr, "bic'cond's 'rd, 'rn, 'shift_rm");
1655 // Format(instr, "bic'cond's 'rd, 'rn, 'imm");
1656 alu_out = rn_val & ~shifter_operand;
1657 set_register(rd, alu_out);
1658 if (instr->HasS()) {
1659 SetNZFlags(alu_out);
1660 SetCFlag(shifter_carry_out);
1661 }
1662 break;
1663 }
1664
1665 case MVN: {
1666 // Format(instr, "mvn'cond's 'rd, 'shift_rm");
1667 // Format(instr, "mvn'cond's 'rd, 'imm");
1668 alu_out = ~shifter_operand;
1669 set_register(rd, alu_out);
1670 if (instr->HasS()) {
1671 SetNZFlags(alu_out);
1672 SetCFlag(shifter_carry_out);
1673 }
1674 break;
1675 }
1676
1677 default: {
1678 UNREACHABLE();
1679 break;
1680 }
1681 }
1682 }
1683 }
1684
1685
1686 void Simulator::DecodeType2(Instr* instr) {
1687 int rd = instr->RdField();
1688 int rn = instr->RnField();
1689 int32_t rn_val = get_register(rn);
1690 int32_t im_val = instr->Offset12Field();
1691 int32_t addr = 0;
1692 switch (instr->PUField()) {
1693 case 0: {
1694 // Format(instr, "'memop'cond'b 'rd, ['rn], #-'off12");
1695 ASSERT(!instr->HasW());
1696 addr = rn_val;
1697 rn_val -= im_val;
1698 set_register(rn, rn_val);
1699 break;
1700 }
1701 case 1: {
1702 // Format(instr, "'memop'cond'b 'rd, ['rn], #+'off12");
1703 ASSERT(!instr->HasW());
1704 addr = rn_val;
1705 rn_val += im_val;
1706 set_register(rn, rn_val);
1707 break;
1708 }
1709 case 2: {
1710 // Format(instr, "'memop'cond'b 'rd, ['rn, #-'off12]'w");
1711 rn_val -= im_val;
1712 addr = rn_val;
1713 if (instr->HasW()) {
1714 set_register(rn, rn_val);
1715 }
1716 break;
1717 }
1718 case 3: {
1719 // Format(instr, "'memop'cond'b 'rd, ['rn, #+'off12]'w");
1720 rn_val += im_val;
1721 addr = rn_val;
1722 if (instr->HasW()) {
1723 set_register(rn, rn_val);
1724 }
1725 break;
1726 }
1727 default: {
1728 UNREACHABLE();
1729 break;
1730 }
1731 }
1732 if (instr->HasB()) {
1733 if (instr->HasL()) {
1734 byte val = ReadBU(addr);
1735 set_register(rd, val);
1736 } else {
1737 byte val = get_register(rd);
1738 WriteB(addr, val);
1739 }
1740 } else {
1741 if (instr->HasL()) {
1742 set_register(rd, ReadW(addr, instr));
1743 } else {
1744 WriteW(addr, get_register(rd), instr);
1745 }
1746 }
1747 }
1748
1749
1750 void Simulator::DecodeType3(Instr* instr) {
1751 ASSERT(instr->Bits(6, 4) == 0x5 || instr->Bit(4) == 0);
1752 int rd = instr->RdField();
1753 int rn = instr->RnField();
1754 int32_t rn_val = get_register(rn);
1755 bool shifter_carry_out = 0;
1756 int32_t shifter_operand = GetShiftRm(instr, &shifter_carry_out);
1757 int32_t addr = 0;
1758 switch (instr->PUField()) {
1759 case 0: {
1760 ASSERT(!instr->HasW());
1761 Format(instr, "'memop'cond'b 'rd, ['rn], -'shift_rm");
1762 break;
1763 }
1764 case 1: {
1765 ASSERT(!instr->HasW());
1766 Format(instr, "'memop'cond'b 'rd, ['rn], +'shift_rm");
1767 break;
1768 }
1769 case 2: {
1770 // Format(instr, "'memop'cond'b 'rd, ['rn, -'shift_rm]'w");
1771 addr = rn_val - shifter_operand;
1772 if (instr->HasW()) {
1773 set_register(rn, addr);
1774 }
1775 break;
1776 }
1777 case 3: {
1778 if (instr->HasW() && (instr->Bits(6, 4) == 0x5)) {
1779 uint32_t widthminus1 = static_cast<uint32_t>(instr->Bits(20, 16));
1780 uint32_t lsbit = static_cast<uint32_t>(instr->ShiftAmountField());
1781 uint32_t msbit = widthminus1 + lsbit;
1782 if (msbit <= 31) {
1783 uint32_t rm_val =
1784 static_cast<uint32_t>(get_register(instr->RmField()));
1785 uint32_t extr_val = rm_val << (31 - msbit);
1786 extr_val = extr_val >> (31 - widthminus1);
1787 set_register(instr->RdField(), extr_val);
1788 } else {
1789 UNREACHABLE();
1790 }
1791 return;
1792 } else {
1793 // Format(instr, "'memop'cond'b 'rd, ['rn, +'shift_rm]'w");
1794 addr = rn_val + shifter_operand;
1795 if (instr->HasW()) {
1796 set_register(rn, addr);
1797 }
1798 }
1799 break;
1800 }
1801 default: {
1802 UNREACHABLE();
1803 break;
1804 }
1805 }
1806 if (instr->HasB()) {
1807 if (instr->HasL()) {
1808 uint8_t byte = ReadB(addr);
1809 set_register(rd, byte);
1810 } else {
1811 uint8_t byte = get_register(rd);
1812 WriteB(addr, byte);
1813 }
1814 } else {
1815 if (instr->HasL()) {
1816 set_register(rd, ReadW(addr, instr));
1817 } else {
1818 WriteW(addr, get_register(rd), instr);
1819 }
1820 }
1821 }
1822
1823
1824 void Simulator::DecodeType4(Instr* instr) {
1825 ASSERT(instr->Bit(22) == 0); // only allowed to be set in privileged mode
1826 if (instr->HasL()) {
1827 // Format(instr, "ldm'cond'pu 'rn'w, 'rlist");
1828 HandleRList(instr, true);
1829 } else {
1830 // Format(instr, "stm'cond'pu 'rn'w, 'rlist");
1831 HandleRList(instr, false);
1832 }
1833 }
1834
1835
1836 void Simulator::DecodeType5(Instr* instr) {
1837 // Format(instr, "b'l'cond 'target");
1838 int off = (instr->SImmed24Field() << 2);
1839 intptr_t pc_address = get_pc();
1840 if (instr->HasLink()) {
1841 set_register(lr, pc_address + Instr::kInstrSize);
1842 }
1843 int pc_reg = get_register(pc);
1844 set_pc(pc_reg + off);
1845 }
1846
1847
1848 void Simulator::DecodeType6(Instr* instr) {
1849 DecodeType6CoprocessorIns(instr);
1850 }
1851
1852
1853 void Simulator::DecodeType7(Instr* instr) {
1854 if (instr->Bit(24) == 1) {
1855 SoftwareInterrupt(instr);
1856 } else {
1857 DecodeTypeVFP(instr);
1858 }
1859 }
1860
1861
1862 void Simulator::DecodeUnconditional(Instr* instr) {
1863 if (instr->Bits(7, 4) == 0x0B && instr->Bits(27, 25) == 0 && instr->HasL()) {
1864 // Load halfword instruction, either register or immediate offset.
1865 int rd = instr->RdField();
1866 int rn = instr->RnField();
1867 int32_t rn_val = get_register(rn);
1868 int32_t addr = 0;
1869 int32_t offset;
1870 if (instr->Bit(22) == 0) {
1871 // Register offset.
1872 int rm = instr->RmField();
1873 offset = get_register(rm);
1874 } else {
1875 // Immediate offset
1876 offset = instr->Bits(3, 0) + (instr->Bits(11, 8) << 4);
1877 }
1878 switch (instr->PUField()) {
1879 case 0: {
1880 // Post index, negative.
1881 ASSERT(!instr->HasW());
1882 addr = rn_val;
1883 rn_val -= offset;
1884 set_register(rn, rn_val);
1885 break;
1886 }
1887 case 1: {
1888 // Post index, positive.
1889 ASSERT(!instr->HasW());
1890 addr = rn_val;
1891 rn_val += offset;
1892 set_register(rn, rn_val);
1893 break;
1894 }
1895 case 2: {
1896 // Pre index or offset, negative.
1897 rn_val -= offset;
1898 addr = rn_val;
1899 if (instr->HasW()) {
1900 set_register(rn, rn_val);
1901 }
1902 break;
1903 }
1904 case 3: {
1905 // Pre index or offset, positive.
1906 rn_val += offset;
1907 addr = rn_val;
1908 if (instr->HasW()) {
1909 set_register(rn, rn_val);
1910 }
1911 break;
1912 }
1913 default: {
1914 // The PU field is a 2-bit field.
1915 UNREACHABLE();
1916 break;
1917 }
1918 }
1919 // Not sign extending, so load as unsigned.
1920 uint16_t halfword = ReadH(addr, instr);
1921 set_register(rd, halfword);
1922 } else {
1923 Debugger dbg(this);
1924 dbg.Stop(instr);
1925 }
1926 }
1927
1928
1929 // void Simulator::DecodeTypeVFP(Instr* instr)
1930 // The Following ARMv7 VFPv instructions are currently supported.
1931 // vmov :Sn = Rt
1932 // vmov :Rt = Sn
1933 // vcvt: Dd = Sm
1934 // vcvt: Sd = Dm
1935 // Dd = vadd(Dn, Dm)
1936 // Dd = vsub(Dn, Dm)
1937 // Dd = vmul(Dn, Dm)
1938 // Dd = vdiv(Dn, Dm)
1939 // vcmp(Dd, Dm)
1940 // VMRS
1941 void Simulator::DecodeTypeVFP(Instr* instr) {
1942 ASSERT((instr->TypeField() == 7) && (instr->Bit(24) == 0x0) );
1943
1944 int rt = instr->RtField();
1945 int vm = instr->VmField();
1946 int vn = instr->VnField();
1947 int vd = instr->VdField();
1948
1949 if (instr->Bit(23) == 1) {
1950 if ((instr->Bits(21, 19) == 0x7) &&
1951 (instr->Bits(18, 16) == 0x5) &&
1952 (instr->Bits(11, 9) == 0x5) &&
1953 (instr->Bit(8) == 1) &&
1954 (instr->Bit(6) == 1) &&
1955 (instr->Bit(4) == 0)) {
1956 double dm_val = get_double_from_d_register(vm);
1957 int32_t int_value = static_cast<int32_t>(dm_val);
1958 set_s_register_from_sinteger(((vd<<1) | instr->DField()), int_value);
1959 } else if ((instr->Bits(21, 19) == 0x7) &&
1960 (instr->Bits(18, 16) == 0x0) &&
1961 (instr->Bits(11, 9) == 0x5) &&
1962 (instr->Bit(8) == 1) &&
1963 (instr->Bit(7) == 1) &&
1964 (instr->Bit(6) == 1) &&
1965 (instr->Bit(4) == 0)) {
1966 int32_t int_value = get_sinteger_from_s_register(((vm<<1) |
1967 instr->MField()));
1968 double dbl_value = static_cast<double>(int_value);
1969 set_d_register_from_double(vd, dbl_value);
1970 } else if ((instr->Bit(21) == 0x0) &&
1971 (instr->Bit(20) == 0x0) &&
1972 (instr->Bits(11, 9) == 0x5) &&
1973 (instr->Bit(8) == 1) &&
1974 (instr->Bit(6) == 0) &&
1975 (instr->Bit(4) == 0)) {
1976 double dn_value = get_double_from_d_register(vn);
1977 double dm_value = get_double_from_d_register(vm);
1978 double dd_value = dn_value / dm_value;
1979 set_d_register_from_double(vd, dd_value);
1980 } else if ((instr->Bits(21, 20) == 0x3) &&
1981 (instr->Bits(19, 16) == 0x4) &&
1982 (instr->Bits(11, 9) == 0x5) &&
1983 (instr->Bit(8) == 0x1) &&
1984 (instr->Bit(6) == 0x1) &&
1985 (instr->Bit(4) == 0x0)) {
1986 double dd_value = get_double_from_d_register(vd);
1987 double dm_value = get_double_from_d_register(vm);
1988 Compute_FPSCR_Flags(dd_value, dm_value);
1989 } else if ((instr->Bits(23, 20) == 0xF) &&
1990 (instr->Bits(19, 16) == 0x1) &&
1991 (instr->Bits(11, 8) == 0xA) &&
1992 (instr->Bits(7, 5) == 0x0) &&
1993 (instr->Bit(4) == 0x1) &&
1994 (instr->Bits(3, 0) == 0x0)) {
1995 if (instr->Bits(15, 12) == 0xF)
1996 Copy_FPSCR_to_APSR();
1997 else
1998 UNIMPLEMENTED(); // Not used by V8.
1999 } else {
2000 UNIMPLEMENTED(); // Not used by V8.
2001 }
2002 } else if (instr->Bit(21) == 1) {
2003 if ((instr->Bit(20) == 0x1) &&
2004 (instr->Bits(11, 9) == 0x5) &&
2005 (instr->Bit(8) == 0x1) &&
2006 (instr->Bit(6) == 0) &&
2007 (instr->Bit(4) == 0)) {
2008 double dn_value = get_double_from_d_register(vn);
2009 double dm_value = get_double_from_d_register(vm);
2010 double dd_value = dn_value + dm_value;
2011 set_d_register_from_double(vd, dd_value);
2012 } else if ((instr->Bit(20) == 0x1) &&
2013 (instr->Bits(11, 9) == 0x5) &&
2014 (instr->Bit(8) == 0x1) &&
2015 (instr->Bit(6) == 1) &&
2016 (instr->Bit(4) == 0)) {
2017 double dn_value = get_double_from_d_register(vn);
2018 double dm_value = get_double_from_d_register(vm);
2019 double dd_value = dn_value - dm_value;
2020 set_d_register_from_double(vd, dd_value);
2021 } else if ((instr->Bit(20) == 0x0) &&
2022 (instr->Bits(11, 9) == 0x5) &&
2023 (instr->Bit(8) == 0x1) &&
2024 (instr->Bit(6) == 0) &&
2025 (instr->Bit(4) == 0)) {
2026 double dn_value = get_double_from_d_register(vn);
2027 double dm_value = get_double_from_d_register(vm);
2028 double dd_value = dn_value * dm_value;
2029 set_d_register_from_double(vd, dd_value);
2030 } else {
2031 UNIMPLEMENTED(); // Not used by V8.
2032 }
2033 } else {
2034 if ((instr->Bit(20) == 0x0) &&
2035 (instr->Bits(11, 8) == 0xA) &&
2036 (instr->Bits(6, 5) == 0x0) &&
2037 (instr->Bit(4) == 1) &&
2038 (instr->Bits(3, 0) == 0x0)) {
2039 int32_t rs_val = get_register(rt);
2040 set_s_register_from_sinteger(((vn<<1) | instr->NField()), rs_val);
2041 } else if ((instr->Bit(20) == 0x1) &&
2042 (instr->Bits(11, 8) == 0xA) &&
2043 (instr->Bits(6, 5) == 0x0) &&
2044 (instr->Bit(4) == 1) &&
2045 (instr->Bits(3, 0) == 0x0)) {
2046 int32_t int_value = get_sinteger_from_s_register(((vn<<1) |
2047 instr->NField()));
2048 set_register(rt, int_value);
2049 } else {
2050 UNIMPLEMENTED(); // Not used by V8.
2051 }
2052 }
2053 }
2054
2055
2056 // void Simulator::DecodeType6CoprocessorIns(Instr* instr)
2057 // Decode Type 6 coprocessor instructions.
2058 // Dm = vmov(Rt, Rt2)
2059 // <Rt, Rt2> = vmov(Dm)
2060 // Ddst = MEM(Rbase + 4*offset).
2061 // MEM(Rbase + 4*offset) = Dsrc.
2062 void Simulator::DecodeType6CoprocessorIns(Instr* instr) {
2063 ASSERT((instr->TypeField() == 6));
2064
2065 if (instr->CoprocessorField() != 0xB) {
2066 UNIMPLEMENTED(); // Not used by V8.
2067 } else {
2068 switch (instr->OpcodeField()) {
2069 case 0x2:
2070 // Load and store double to two GP registers
2071 if (instr->Bits(7, 4) != 0x1) {
2072 UNIMPLEMENTED(); // Not used by V8.
2073 } else {
2074 int rt = instr->RtField();
2075 int rn = instr->RnField();
2076 int vm = instr->VmField();
2077 if (instr->HasL()) {
2078 int32_t rt_int_value = get_sinteger_from_s_register(2*vm);
2079 int32_t rn_int_value = get_sinteger_from_s_register(2*vm+1);
2080
2081 set_register(rt, rt_int_value);
2082 set_register(rn, rn_int_value);
2083 } else {
2084 int32_t rs_val = get_register(rt);
2085 int32_t rn_val = get_register(rn);
2086
2087 set_s_register_from_sinteger(2*vm, rs_val);
2088 set_s_register_from_sinteger((2*vm+1), rn_val);
2089 }
2090 }
2091 break;
2092 case 0x8:
2093 case 0xC: { // Load and store double to memory.
2094 int rn = instr->RnField();
2095 int vd = instr->VdField();
2096 int offset = instr->Immed8Field();
2097 if (!instr->HasU()) {
2098 offset = -offset;
2099 }
2100 int32_t address = get_register(rn) + 4 * offset;
2101 if (instr->HasL()) {
2102 // Load double from memory: vldr.
2103 set_s_register_from_sinteger(2*vd, ReadW(address, instr));
2104 set_s_register_from_sinteger(2*vd + 1, ReadW(address + 4, instr));
2105 } else {
2106 // Store double to memory: vstr.
2107 WriteW(address, get_sinteger_from_s_register(2*vd), instr);
2108 WriteW(address + 4, get_sinteger_from_s_register(2*vd + 1), instr);
2109 }
2110 break;
2111 }
2112 default:
2113 UNIMPLEMENTED(); // Not used by V8.
2114 break;
2115 }
2116 }
2117 }
2118
2119 void Simulator::InstructionDecode(int32_t adr) {
2120 if (::v8::internal::FLAG_trace_sim) {
2121 disasm::NameConverter converter;
2122 disasm::Disassembler dasm(converter);
2123 // use a reasonably large buffer
2124 v8::internal::EmbeddedVector<char, 256> buffer;
2125 dasm.InstructionDecode(buffer,
2126 reinterpret_cast<byte*>(adr));
2127 PrintF(" 0x%08x %s\n", adr, buffer.start());
2128 }
2129 if (adr & 1) {
2130 InstructionDecodeThumb2(reinterpret_cast<byte*>(adr));
2131 } else {
2132 InstructionDecodeArm(reinterpret_cast<Instr*>(adr));
2133 }
2134 }
2135
2136 int32_t Simulator::GetOperand2(const InstrThumb2& instr, bool* carry_out) {
2137 switch (instr.Variant()) {
2138 case VARIANT_IMMEDIATE:
2139 return instr.Imm();
2140
2141 case VARIANT_REGISTER:
2142 return GetRmShiftImm(instr, carry_out);
2143
2144 default:
2145 UNIMPLEMENTED();
2146 return -1;
2147 }
2148 }
2149
2150 int32_t Simulator::GetRmShiftImm(const InstrThumb2& instr, bool* carry_out) {
2151 Shift shift = (Shift) instr.Type();
2152 int shift_amount = instr.Imm();
2153 int32_t result = get_register(instr.Rm());
2154
2155 switch (shift) {
2156 case no_shift:
2157 break;
2158
2159 case ASR: {
2160 result >>= (shift_amount - 1);
2161 *carry_out = (result & 1) == 1;
2162 result >>= 1;
2163 break;
2164 }
2165
2166 case LSL: {
2167 result <<= (shift_amount - 1);
2168 *carry_out = (result < 0);
2169 result <<= 1;
2170 break;
2171 }
2172
2173 case LSR: {
2174 uint32_t uresult = static_cast<uint32_t>(result);
2175 uresult >>= (shift_amount - 1);
2176 *carry_out = (uresult & 1) == 1;
2177 uresult >>= 1;
2178 result = static_cast<int32_t>(uresult);
2179 break;
2180 }
2181
2182 case RRX:
2183 case ROR: {
2184 UNIMPLEMENTED();
2185 break;
2186 }
2187
2188 default: {
2189 UNREACHABLE();
2190 break;
2191 }
2192 }
2193 return result;
2194 }
2195
2196
2197
2198 void Simulator::InstructionDecodeThumb2(byte* adr) {
2199 pc_modified_ = false;
2200 InstrThumb2 instr(adr);
2201 bool shifter_carry_out = 0;
2202 int32_t alu_out;
2203 int32_t operand2;
2204
2205 // enter_debug_ = true;
2206
2207
2208 // PrintF("executing OP: %i size: %i rn: %i rm: %i rd: %i\n",
2209 // instr.Op(), instr.Size(), instr.Rn(), instr.Rm(), instr.Rd());
2210
2211 int32_t rn_val = get_register(instr.Rn());
2212 switch (instr.Op()) {
2213 case OP_AND:
2214 alu_out = rn_val & GetOperand2(instr, &shifter_carry_out);
2215 set_register(instr.Rd(), alu_out);
2216 if (instr.HasS()) {
2217 SetNZFlags(alu_out);
2218 SetCFlag(shifter_carry_out);
2219 }
2220 break;
2221 case OP_ADD:
2222 operand2 = GetOperand2(instr, &shifter_carry_out);
2223 alu_out = rn_val + operand2;
2224 set_register(instr.Rd(), alu_out);
2225 if (instr.HasS()) {
2226 SetNZFlags(alu_out);
2227 SetCFlag(CarryFrom(rn_val, operand2));
2228 SetVFlag(OverflowFrom(alu_out, rn_val, operand2, true));
2229 }
2230 break;
2231
2232 case OP_SUB:
2233 operand2 = GetOperand2(instr, &shifter_carry_out);
2234 alu_out = rn_val - operand2;
2235 set_register(instr.Rd(), alu_out);
2236 if (instr.HasS()) {
2237 SetNZFlags(alu_out);
2238 SetCFlag(!BorrowFrom(rn_val, operand2));
2239 SetVFlag(OverflowFrom(alu_out, rn_val, operand2, false));
2240 }
2241 break;
2242
2243 default:
2244 PrintF("Unrecogized Thumb Instruction");
2245 UNIMPLEMENTED();
2246 }
2247 if (!pc_modified_) {
2248 set_register(pc, reinterpret_cast<int32_t>(adr) + instr.Size());
2249 }
2250 }
2251
2252 // Executes the current instruction.
2253 void Simulator::InstructionDecodeArm(Instr* instr) {
2254 pc_modified_ = false;
2255 if (instr->ConditionField() == special_condition) {
2256 DecodeUnconditional(instr);
2257 } else if (ConditionallyExecute(instr)) {
2258 switch (instr->TypeField()) {
2259 case 0:
2260 case 1: {
2261 DecodeType01(instr);
2262 break;
2263 }
2264 case 2: {
2265 DecodeType2(instr);
2266 break;
2267 }
2268 case 3: {
2269 DecodeType3(instr);
2270 break;
2271 }
2272 case 4: {
2273 DecodeType4(instr);
2274 break;
2275 }
2276 case 5: {
2277 DecodeType5(instr);
2278 break;
2279 }
2280 case 6: {
2281 DecodeType6(instr);
2282 break;
2283 }
2284 case 7: {
2285 DecodeType7(instr);
2286 break;
2287 }
2288 default: {
2289 UNIMPLEMENTED();
2290 break;
2291 }
2292 }
2293 }
2294 if (!pc_modified_) {
2295 set_register(pc, reinterpret_cast<int32_t>(instr) + Instr::kInstrSize);
2296 }
2297 }
2298
2299
2300 void Simulator::Execute() {
2301 // Get the PC to simulate. Cannot use the accessor here as we need the
2302 // raw PC value and not the one used as input to arithmetic instructions.
2303 int program_counter = get_pc();
2304
2305 if (::v8::internal::FLAG_stop_sim_at == 0) {
2306 // Fast version of the dispatch loop without checking whether the simulator
2307 // should be stopping at a particular executed instruction.
2308 while (program_counter != end_sim_pc) {
2309 icount_++;
2310 InstructionDecode(program_counter);
2311 program_counter = get_pc();
2312 }
2313 } else {
2314 // FLAG_stop_sim_at is at the non-default value. Stop in the debugger when
2315 // we reach the particular instuction count.
2316 while (program_counter != end_sim_pc) {
2317 icount_++;
2318 if (icount_ == ::v8::internal::FLAG_stop_sim_at) {
2319 Debugger dbg(this);
2320 dbg.Debug();
2321 } else if (program_counter & 1) {
2322 InstructionDecode(program_counter);
2323 }
2324 program_counter = get_pc();
2325 }
2326 }
2327 }
2328
2329
2330 int32_t Simulator::Call(byte* entry, int argument_count, ...) {
2331 va_list parameters;
2332 va_start(parameters, argument_count);
2333 // Setup arguments
2334
2335 // First four arguments passed in registers.
2336 ASSERT(argument_count >= 4);
2337 set_register(r0, va_arg(parameters, int32_t));
2338 set_register(r1, va_arg(parameters, int32_t));
2339 set_register(r2, va_arg(parameters, int32_t));
2340 set_register(r3, va_arg(parameters, int32_t));
2341
2342 // Remaining arguments passed on stack.
2343 int original_stack = get_register(sp);
2344 // Compute position of stack on entry to generated code.
2345 int entry_stack = (original_stack - (argument_count - 4) * sizeof(int32_t));
2346 if (OS::ActivationFrameAlignment() != 0) {
2347 entry_stack &= -OS::ActivationFrameAlignment();
2348 }
2349 // Store remaining arguments on stack, from low to high memory.
2350 intptr_t* stack_argument = reinterpret_cast<intptr_t*>(entry_stack);
2351 for (int i = 4; i < argument_count; i++) {
2352 stack_argument[i - 4] = va_arg(parameters, int32_t);
2353 }
2354 va_end(parameters);
2355 set_register(sp, entry_stack);
2356
2357 // Prepare to execute the code at entry
2358 set_register(pc, reinterpret_cast<int32_t>(entry));
2359 // Put down marker for end of simulation. The simulator will stop simulation
2360 // when the PC reaches this value. By saving the "end simulation" value into
2361 // the LR the simulation stops when returning to this call point.
2362 set_register(lr, end_sim_pc);
2363
2364 // Remember the values of callee-saved registers.
2365 // The code below assumes that r9 is not used as sb (static base) in
2366 // simulator code and therefore is regarded as a callee-saved register.
2367 int32_t r4_val = get_register(r4);
2368 int32_t r5_val = get_register(r5);
2369 int32_t r6_val = get_register(r6);
2370 int32_t r7_val = get_register(r7);
2371 int32_t r8_val = get_register(r8);
2372 int32_t r9_val = get_register(r9);
2373 int32_t r10_val = get_register(r10);
2374 int32_t r11_val = get_register(r11);
2375
2376 // Setup the callee-saved registers with a known value. To be able to check
2377 // that they are preserved properly across JS execution.
2378 int32_t callee_saved_value = icount_;
2379 set_register(r4, callee_saved_value);
2380 set_register(r5, callee_saved_value);
2381 set_register(r6, callee_saved_value);
2382 set_register(r7, callee_saved_value);
2383 set_register(r8, callee_saved_value);
2384 set_register(r9, callee_saved_value);
2385 set_register(r10, callee_saved_value);
2386 set_register(r11, callee_saved_value);
2387
2388 // Start the simulation
2389 Execute();
2390
2391 // Check that the callee-saved registers have been preserved.
2392 CHECK_EQ(callee_saved_value, get_register(r4));
2393 CHECK_EQ(callee_saved_value, get_register(r5));
2394 CHECK_EQ(callee_saved_value, get_register(r6));
2395 CHECK_EQ(callee_saved_value, get_register(r7));
2396 CHECK_EQ(callee_saved_value, get_register(r8));
2397 CHECK_EQ(callee_saved_value, get_register(r9));
2398 CHECK_EQ(callee_saved_value, get_register(r10));
2399 CHECK_EQ(callee_saved_value, get_register(r11));
2400
2401 // Restore callee-saved registers with the original value.
2402 set_register(r4, r4_val);
2403 set_register(r5, r5_val);
2404 set_register(r6, r6_val);
2405 set_register(r7, r7_val);
2406 set_register(r8, r8_val);
2407 set_register(r9, r9_val);
2408 set_register(r10, r10_val);
2409 set_register(r11, r11_val);
2410
2411 // Pop stack passed arguments.
2412 CHECK_EQ(entry_stack, get_register(sp));
2413 set_register(sp, original_stack);
2414
2415 int32_t result = get_register(r0);
2416 return result;
2417 }
2418
2419
2420 uintptr_t Simulator::PushAddress(uintptr_t address) {
2421 int new_sp = get_register(sp) - sizeof(uintptr_t);
2422 uintptr_t* stack_slot = reinterpret_cast<uintptr_t*>(new_sp);
2423 *stack_slot = address;
2424 set_register(sp, new_sp);
2425 return new_sp;
2426 }
2427
2428
2429 uintptr_t Simulator::PopAddress() {
2430 int current_sp = get_register(sp);
2431 uintptr_t* stack_slot = reinterpret_cast<uintptr_t*>(current_sp);
2432 uintptr_t address = *stack_slot;
2433 set_register(sp, current_sp + sizeof(uintptr_t));
2434 return address;
2435 }
2436
2437
2438 } } // namespace assembler::arm
2439
2440 #endif // !defined(__arm__)
OLDNEW
« no previous file with comments | « src/arm/regexp-macro-assembler-arm.cc ('k') | src/simulator.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698