deps: update v8 to 4.3.61.21
[platform/upstream/nodejs.git] / deps / v8 / src / arm / simulator-arm.cc
1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include <stdarg.h>
6 #include <stdlib.h>
7 #include <cmath>
8
9 #include "src/v8.h"
10
11 #if V8_TARGET_ARCH_ARM
12
13 #include "src/arm/constants-arm.h"
14 #include "src/arm/simulator-arm.h"
15 #include "src/assembler.h"
16 #include "src/base/bits.h"
17 #include "src/codegen.h"
18 #include "src/disasm.h"
19
20 #if defined(USE_SIMULATOR)
21
22 // Only build the simulator if not compiling for real ARM hardware.
23 namespace v8 {
24 namespace internal {
25
26 // This macro provides a platform independent use of sscanf. The reason for
27 // SScanF not being implemented in a platform independent way through
28 // ::v8::internal::OS in the same way as SNPrintF is that the
29 // Windows C Run-Time Library does not provide vsscanf.
30 #define SScanF sscanf  // NOLINT
31
32 // The ArmDebugger class is used by the simulator while debugging simulated ARM
33 // code.
34 class ArmDebugger {
35  public:
36   explicit ArmDebugger(Simulator* sim) : sim_(sim) { }
37   ~ArmDebugger();
38
39   void Stop(Instruction* instr);
40   void Debug();
41
42  private:
43   static const Instr kBreakpointInstr =
44       (al | (7*B25) | (1*B24) | kBreakpoint);
45   static const Instr kNopInstr = (al | (13*B21));
46
47   Simulator* sim_;
48
49   int32_t GetRegisterValue(int regnum);
50   double GetRegisterPairDoubleValue(int regnum);
51   double GetVFPDoubleRegisterValue(int regnum);
52   bool GetValue(const char* desc, int32_t* value);
53   bool GetVFPSingleValue(const char* desc, float* value);
54   bool GetVFPDoubleValue(const char* desc, double* value);
55
56   // Set or delete a breakpoint. Returns true if successful.
57   bool SetBreakpoint(Instruction* breakpc);
58   bool DeleteBreakpoint(Instruction* breakpc);
59
60   // Undo and redo all breakpoints. This is needed to bracket disassembly and
61   // execution to skip past breakpoints when run from the debugger.
62   void UndoBreakpoints();
63   void RedoBreakpoints();
64 };
65
66
67 ArmDebugger::~ArmDebugger() {
68 }
69
70
71
72 #ifdef GENERATED_CODE_COVERAGE
73 static FILE* coverage_log = NULL;
74
75
76 static void InitializeCoverage() {
77   char* file_name = getenv("V8_GENERATED_CODE_COVERAGE_LOG");
78   if (file_name != NULL) {
79     coverage_log = fopen(file_name, "aw+");
80   }
81 }
82
83
84 void ArmDebugger::Stop(Instruction* instr) {
85   // Get the stop code.
86   uint32_t code = instr->SvcValue() & kStopCodeMask;
87   // Retrieve the encoded address, which comes just after this stop.
88   char** msg_address =
89     reinterpret_cast<char**>(sim_->get_pc() + Instruction::kInstrSize);
90   char* msg = *msg_address;
91   DCHECK(msg != NULL);
92
93   // Update this stop description.
94   if (isWatchedStop(code) && !watched_stops_[code].desc) {
95     watched_stops_[code].desc = msg;
96   }
97
98   if (strlen(msg) > 0) {
99     if (coverage_log != NULL) {
100       fprintf(coverage_log, "%s\n", msg);
101       fflush(coverage_log);
102     }
103     // Overwrite the instruction and address with nops.
104     instr->SetInstructionBits(kNopInstr);
105     reinterpret_cast<Instruction*>(msg_address)->SetInstructionBits(kNopInstr);
106   }
107   sim_->set_pc(sim_->get_pc() + 2 * Instruction::kInstrSize);
108 }
109
110 #else  // ndef GENERATED_CODE_COVERAGE
111
112 static void InitializeCoverage() {
113 }
114
115
116 void ArmDebugger::Stop(Instruction* instr) {
117   // Get the stop code.
118   uint32_t code = instr->SvcValue() & kStopCodeMask;
119   // Retrieve the encoded address, which comes just after this stop.
120   char* msg = *reinterpret_cast<char**>(sim_->get_pc()
121                                         + Instruction::kInstrSize);
122   // Update this stop description.
123   if (sim_->isWatchedStop(code) && !sim_->watched_stops_[code].desc) {
124     sim_->watched_stops_[code].desc = msg;
125   }
126   // Print the stop message and code if it is not the default code.
127   if (code != kMaxStopCode) {
128     PrintF("Simulator hit stop %u: %s\n", code, msg);
129   } else {
130     PrintF("Simulator hit %s\n", msg);
131   }
132   sim_->set_pc(sim_->get_pc() + 2 * Instruction::kInstrSize);
133   Debug();
134 }
135 #endif
136
137
138 int32_t ArmDebugger::GetRegisterValue(int regnum) {
139   if (regnum == kPCRegister) {
140     return sim_->get_pc();
141   } else {
142     return sim_->get_register(regnum);
143   }
144 }
145
146
147 double ArmDebugger::GetRegisterPairDoubleValue(int regnum) {
148   return sim_->get_double_from_register_pair(regnum);
149 }
150
151
152 double ArmDebugger::GetVFPDoubleRegisterValue(int regnum) {
153   return sim_->get_double_from_d_register(regnum);
154 }
155
156
157 bool ArmDebugger::GetValue(const char* desc, int32_t* value) {
158   int regnum = Registers::Number(desc);
159   if (regnum != kNoRegister) {
160     *value = GetRegisterValue(regnum);
161     return true;
162   } else {
163     if (strncmp(desc, "0x", 2) == 0) {
164       return SScanF(desc + 2, "%x", reinterpret_cast<uint32_t*>(value)) == 1;
165     } else {
166       return SScanF(desc, "%u", reinterpret_cast<uint32_t*>(value)) == 1;
167     }
168   }
169   return false;
170 }
171
172
173 bool ArmDebugger::GetVFPSingleValue(const char* desc, float* value) {
174   bool is_double;
175   int regnum = VFPRegisters::Number(desc, &is_double);
176   if (regnum != kNoRegister && !is_double) {
177     *value = sim_->get_float_from_s_register(regnum);
178     return true;
179   }
180   return false;
181 }
182
183
184 bool ArmDebugger::GetVFPDoubleValue(const char* desc, double* value) {
185   bool is_double;
186   int regnum = VFPRegisters::Number(desc, &is_double);
187   if (regnum != kNoRegister && is_double) {
188     *value = sim_->get_double_from_d_register(regnum);
189     return true;
190   }
191   return false;
192 }
193
194
195 bool ArmDebugger::SetBreakpoint(Instruction* breakpc) {
196   // Check if a breakpoint can be set. If not return without any side-effects.
197   if (sim_->break_pc_ != NULL) {
198     return false;
199   }
200
201   // Set the breakpoint.
202   sim_->break_pc_ = breakpc;
203   sim_->break_instr_ = breakpc->InstructionBits();
204   // Not setting the breakpoint instruction in the code itself. It will be set
205   // when the debugger shell continues.
206   return true;
207 }
208
209
210 bool ArmDebugger::DeleteBreakpoint(Instruction* breakpc) {
211   if (sim_->break_pc_ != NULL) {
212     sim_->break_pc_->SetInstructionBits(sim_->break_instr_);
213   }
214
215   sim_->break_pc_ = NULL;
216   sim_->break_instr_ = 0;
217   return true;
218 }
219
220
221 void ArmDebugger::UndoBreakpoints() {
222   if (sim_->break_pc_ != NULL) {
223     sim_->break_pc_->SetInstructionBits(sim_->break_instr_);
224   }
225 }
226
227
228 void ArmDebugger::RedoBreakpoints() {
229   if (sim_->break_pc_ != NULL) {
230     sim_->break_pc_->SetInstructionBits(kBreakpointInstr);
231   }
232 }
233
234
235 void ArmDebugger::Debug() {
236   intptr_t last_pc = -1;
237   bool done = false;
238
239 #define COMMAND_SIZE 63
240 #define ARG_SIZE 255
241
242 #define STR(a) #a
243 #define XSTR(a) STR(a)
244
245   char cmd[COMMAND_SIZE + 1];
246   char arg1[ARG_SIZE + 1];
247   char arg2[ARG_SIZE + 1];
248   char* argv[3] = { cmd, arg1, arg2 };
249
250   // make sure to have a proper terminating character if reaching the limit
251   cmd[COMMAND_SIZE] = 0;
252   arg1[ARG_SIZE] = 0;
253   arg2[ARG_SIZE] = 0;
254
255   // Undo all set breakpoints while running in the debugger shell. This will
256   // make them invisible to all commands.
257   UndoBreakpoints();
258
259   while (!done && !sim_->has_bad_pc()) {
260     if (last_pc != sim_->get_pc()) {
261       disasm::NameConverter converter;
262       disasm::Disassembler dasm(converter);
263       // use a reasonably large buffer
264       v8::internal::EmbeddedVector<char, 256> buffer;
265       dasm.InstructionDecode(buffer,
266                              reinterpret_cast<byte*>(sim_->get_pc()));
267       PrintF("  0x%08x  %s\n", sim_->get_pc(), buffer.start());
268       last_pc = sim_->get_pc();
269     }
270     char* line = ReadLine("sim> ");
271     if (line == NULL) {
272       break;
273     } else {
274       char* last_input = sim_->last_debugger_input();
275       if (strcmp(line, "\n") == 0 && last_input != NULL) {
276         line = last_input;
277       } else {
278         // Ownership is transferred to sim_;
279         sim_->set_last_debugger_input(line);
280       }
281       // Use sscanf to parse the individual parts of the command line. At the
282       // moment no command expects more than two parameters.
283       int argc = SScanF(line,
284                         "%" XSTR(COMMAND_SIZE) "s "
285                         "%" XSTR(ARG_SIZE) "s "
286                         "%" XSTR(ARG_SIZE) "s",
287                         cmd, arg1, arg2);
288       if ((strcmp(cmd, "si") == 0) || (strcmp(cmd, "stepi") == 0)) {
289         sim_->InstructionDecode(reinterpret_cast<Instruction*>(sim_->get_pc()));
290       } else if ((strcmp(cmd, "c") == 0) || (strcmp(cmd, "cont") == 0)) {
291         // Execute the one instruction we broke at with breakpoints disabled.
292         sim_->InstructionDecode(reinterpret_cast<Instruction*>(sim_->get_pc()));
293         // Leave the debugger shell.
294         done = true;
295       } else if ((strcmp(cmd, "p") == 0) || (strcmp(cmd, "print") == 0)) {
296         if (argc == 2 || (argc == 3 && strcmp(arg2, "fp") == 0)) {
297           int32_t value;
298           float svalue;
299           double dvalue;
300           if (strcmp(arg1, "all") == 0) {
301             for (int i = 0; i < kNumRegisters; i++) {
302               value = GetRegisterValue(i);
303               PrintF("%3s: 0x%08x %10d", Registers::Name(i), value, value);
304               if ((argc == 3 && strcmp(arg2, "fp") == 0) &&
305                   i < 8 &&
306                   (i % 2) == 0) {
307                 dvalue = GetRegisterPairDoubleValue(i);
308                 PrintF(" (%f)\n", dvalue);
309               } else {
310                 PrintF("\n");
311               }
312             }
313             for (int i = 0; i < DwVfpRegister::NumRegisters(); i++) {
314               dvalue = GetVFPDoubleRegisterValue(i);
315               uint64_t as_words = bit_cast<uint64_t>(dvalue);
316               PrintF("%3s: %f 0x%08x %08x\n",
317                      VFPRegisters::Name(i, true),
318                      dvalue,
319                      static_cast<uint32_t>(as_words >> 32),
320                      static_cast<uint32_t>(as_words & 0xffffffff));
321             }
322           } else {
323             if (GetValue(arg1, &value)) {
324               PrintF("%s: 0x%08x %d \n", arg1, value, value);
325             } else if (GetVFPSingleValue(arg1, &svalue)) {
326               uint32_t as_word = bit_cast<uint32_t>(svalue);
327               PrintF("%s: %f 0x%08x\n", arg1, svalue, as_word);
328             } else if (GetVFPDoubleValue(arg1, &dvalue)) {
329               uint64_t as_words = bit_cast<uint64_t>(dvalue);
330               PrintF("%s: %f 0x%08x %08x\n",
331                      arg1,
332                      dvalue,
333                      static_cast<uint32_t>(as_words >> 32),
334                      static_cast<uint32_t>(as_words & 0xffffffff));
335             } else {
336               PrintF("%s unrecognized\n", arg1);
337             }
338           }
339         } else {
340           PrintF("print <register>\n");
341         }
342       } else if ((strcmp(cmd, "po") == 0)
343                  || (strcmp(cmd, "printobject") == 0)) {
344         if (argc == 2) {
345           int32_t value;
346           OFStream os(stdout);
347           if (GetValue(arg1, &value)) {
348             Object* obj = reinterpret_cast<Object*>(value);
349             os << arg1 << ": \n";
350 #ifdef DEBUG
351             obj->Print(os);
352             os << "\n";
353 #else
354             os << Brief(obj) << "\n";
355 #endif
356           } else {
357             os << arg1 << " unrecognized\n";
358           }
359         } else {
360           PrintF("printobject <value>\n");
361         }
362       } else if (strcmp(cmd, "stack") == 0 || strcmp(cmd, "mem") == 0) {
363         int32_t* cur = NULL;
364         int32_t* end = NULL;
365         int next_arg = 1;
366
367         if (strcmp(cmd, "stack") == 0) {
368           cur = reinterpret_cast<int32_t*>(sim_->get_register(Simulator::sp));
369         } else {  // "mem"
370           int32_t value;
371           if (!GetValue(arg1, &value)) {
372             PrintF("%s unrecognized\n", arg1);
373             continue;
374           }
375           cur = reinterpret_cast<int32_t*>(value);
376           next_arg++;
377         }
378
379         int32_t words;
380         if (argc == next_arg) {
381           words = 10;
382         } else {
383           if (!GetValue(argv[next_arg], &words)) {
384             words = 10;
385           }
386         }
387         end = cur + words;
388
389         while (cur < end) {
390           PrintF("  0x%08x:  0x%08x %10d",
391                  reinterpret_cast<intptr_t>(cur), *cur, *cur);
392           HeapObject* obj = reinterpret_cast<HeapObject*>(*cur);
393           int value = *cur;
394           Heap* current_heap = v8::internal::Isolate::Current()->heap();
395           if (((value & 1) == 0) || current_heap->Contains(obj)) {
396             PrintF(" (");
397             if ((value & 1) == 0) {
398               PrintF("smi %d", value / 2);
399             } else {
400               obj->ShortPrint();
401             }
402             PrintF(")");
403           }
404           PrintF("\n");
405           cur++;
406         }
407       } else if (strcmp(cmd, "disasm") == 0 || strcmp(cmd, "di") == 0) {
408         disasm::NameConverter converter;
409         disasm::Disassembler dasm(converter);
410         // use a reasonably large buffer
411         v8::internal::EmbeddedVector<char, 256> buffer;
412
413         byte* prev = NULL;
414         byte* cur = NULL;
415         byte* end = NULL;
416
417         if (argc == 1) {
418           cur = reinterpret_cast<byte*>(sim_->get_pc());
419           end = cur + (10 * Instruction::kInstrSize);
420         } else if (argc == 2) {
421           int regnum = Registers::Number(arg1);
422           if (regnum != kNoRegister || strncmp(arg1, "0x", 2) == 0) {
423             // The argument is an address or a register name.
424             int32_t value;
425             if (GetValue(arg1, &value)) {
426               cur = reinterpret_cast<byte*>(value);
427               // Disassemble 10 instructions at <arg1>.
428               end = cur + (10 * Instruction::kInstrSize);
429             }
430           } else {
431             // The argument is the number of instructions.
432             int32_t value;
433             if (GetValue(arg1, &value)) {
434               cur = reinterpret_cast<byte*>(sim_->get_pc());
435               // Disassemble <arg1> instructions.
436               end = cur + (value * Instruction::kInstrSize);
437             }
438           }
439         } else {
440           int32_t value1;
441           int32_t value2;
442           if (GetValue(arg1, &value1) && GetValue(arg2, &value2)) {
443             cur = reinterpret_cast<byte*>(value1);
444             end = cur + (value2 * Instruction::kInstrSize);
445           }
446         }
447
448         while (cur < end) {
449           prev = cur;
450           cur += dasm.InstructionDecode(buffer, cur);
451           PrintF("  0x%08x  %s\n",
452                  reinterpret_cast<intptr_t>(prev), buffer.start());
453         }
454       } else if (strcmp(cmd, "gdb") == 0) {
455         PrintF("relinquishing control to gdb\n");
456         v8::base::OS::DebugBreak();
457         PrintF("regaining control from gdb\n");
458       } else if (strcmp(cmd, "break") == 0) {
459         if (argc == 2) {
460           int32_t value;
461           if (GetValue(arg1, &value)) {
462             if (!SetBreakpoint(reinterpret_cast<Instruction*>(value))) {
463               PrintF("setting breakpoint failed\n");
464             }
465           } else {
466             PrintF("%s unrecognized\n", arg1);
467           }
468         } else {
469           PrintF("break <address>\n");
470         }
471       } else if (strcmp(cmd, "del") == 0) {
472         if (!DeleteBreakpoint(NULL)) {
473           PrintF("deleting breakpoint failed\n");
474         }
475       } else if (strcmp(cmd, "flags") == 0) {
476         PrintF("N flag: %d; ", sim_->n_flag_);
477         PrintF("Z flag: %d; ", sim_->z_flag_);
478         PrintF("C flag: %d; ", sim_->c_flag_);
479         PrintF("V flag: %d\n", sim_->v_flag_);
480         PrintF("INVALID OP flag: %d; ", sim_->inv_op_vfp_flag_);
481         PrintF("DIV BY ZERO flag: %d; ", sim_->div_zero_vfp_flag_);
482         PrintF("OVERFLOW flag: %d; ", sim_->overflow_vfp_flag_);
483         PrintF("UNDERFLOW flag: %d; ", sim_->underflow_vfp_flag_);
484         PrintF("INEXACT flag: %d;\n", sim_->inexact_vfp_flag_);
485       } else if (strcmp(cmd, "stop") == 0) {
486         int32_t value;
487         intptr_t stop_pc = sim_->get_pc() - 2 * Instruction::kInstrSize;
488         Instruction* stop_instr = reinterpret_cast<Instruction*>(stop_pc);
489         Instruction* msg_address =
490           reinterpret_cast<Instruction*>(stop_pc + Instruction::kInstrSize);
491         if ((argc == 2) && (strcmp(arg1, "unstop") == 0)) {
492           // Remove the current stop.
493           if (sim_->isStopInstruction(stop_instr)) {
494             stop_instr->SetInstructionBits(kNopInstr);
495             msg_address->SetInstructionBits(kNopInstr);
496           } else {
497             PrintF("Not at debugger stop.\n");
498           }
499         } else if (argc == 3) {
500           // Print information about all/the specified breakpoint(s).
501           if (strcmp(arg1, "info") == 0) {
502             if (strcmp(arg2, "all") == 0) {
503               PrintF("Stop information:\n");
504               for (uint32_t i = 0; i < sim_->kNumOfWatchedStops; i++) {
505                 sim_->PrintStopInfo(i);
506               }
507             } else if (GetValue(arg2, &value)) {
508               sim_->PrintStopInfo(value);
509             } else {
510               PrintF("Unrecognized argument.\n");
511             }
512           } else if (strcmp(arg1, "enable") == 0) {
513             // Enable all/the specified breakpoint(s).
514             if (strcmp(arg2, "all") == 0) {
515               for (uint32_t i = 0; i < sim_->kNumOfWatchedStops; i++) {
516                 sim_->EnableStop(i);
517               }
518             } else if (GetValue(arg2, &value)) {
519               sim_->EnableStop(value);
520             } else {
521               PrintF("Unrecognized argument.\n");
522             }
523           } else if (strcmp(arg1, "disable") == 0) {
524             // Disable all/the specified breakpoint(s).
525             if (strcmp(arg2, "all") == 0) {
526               for (uint32_t i = 0; i < sim_->kNumOfWatchedStops; i++) {
527                 sim_->DisableStop(i);
528               }
529             } else if (GetValue(arg2, &value)) {
530               sim_->DisableStop(value);
531             } else {
532               PrintF("Unrecognized argument.\n");
533             }
534           }
535         } else {
536           PrintF("Wrong usage. Use help command for more information.\n");
537         }
538       } else if ((strcmp(cmd, "t") == 0) || strcmp(cmd, "trace") == 0) {
539         ::v8::internal::FLAG_trace_sim = !::v8::internal::FLAG_trace_sim;
540         PrintF("Trace of executed instructions is %s\n",
541                ::v8::internal::FLAG_trace_sim ? "on" : "off");
542       } else if ((strcmp(cmd, "h") == 0) || (strcmp(cmd, "help") == 0)) {
543         PrintF("cont\n");
544         PrintF("  continue execution (alias 'c')\n");
545         PrintF("stepi\n");
546         PrintF("  step one instruction (alias 'si')\n");
547         PrintF("print <register>\n");
548         PrintF("  print register content (alias 'p')\n");
549         PrintF("  use register name 'all' to print all registers\n");
550         PrintF("  add argument 'fp' to print register pair double values\n");
551         PrintF("printobject <register>\n");
552         PrintF("  print an object from a register (alias 'po')\n");
553         PrintF("flags\n");
554         PrintF("  print flags\n");
555         PrintF("stack [<words>]\n");
556         PrintF("  dump stack content, default dump 10 words)\n");
557         PrintF("mem <address> [<words>]\n");
558         PrintF("  dump memory content, default dump 10 words)\n");
559         PrintF("disasm [<instructions>]\n");
560         PrintF("disasm [<address/register>]\n");
561         PrintF("disasm [[<address/register>] <instructions>]\n");
562         PrintF("  disassemble code, default is 10 instructions\n");
563         PrintF("  from pc (alias 'di')\n");
564         PrintF("gdb\n");
565         PrintF("  enter gdb\n");
566         PrintF("break <address>\n");
567         PrintF("  set a break point on the address\n");
568         PrintF("del\n");
569         PrintF("  delete the breakpoint\n");
570         PrintF("trace (alias 't')\n");
571         PrintF("  toogle the tracing of all executed statements\n");
572         PrintF("stop feature:\n");
573         PrintF("  Description:\n");
574         PrintF("    Stops are debug instructions inserted by\n");
575         PrintF("    the Assembler::stop() function.\n");
576         PrintF("    When hitting a stop, the Simulator will\n");
577         PrintF("    stop and and give control to the ArmDebugger.\n");
578         PrintF("    The first %d stop codes are watched:\n",
579                Simulator::kNumOfWatchedStops);
580         PrintF("    - They can be enabled / disabled: the Simulator\n");
581         PrintF("      will / won't stop when hitting them.\n");
582         PrintF("    - The Simulator keeps track of how many times they \n");
583         PrintF("      are met. (See the info command.) Going over a\n");
584         PrintF("      disabled stop still increases its counter. \n");
585         PrintF("  Commands:\n");
586         PrintF("    stop info all/<code> : print infos about number <code>\n");
587         PrintF("      or all stop(s).\n");
588         PrintF("    stop enable/disable all/<code> : enables / disables\n");
589         PrintF("      all or number <code> stop(s)\n");
590         PrintF("    stop unstop\n");
591         PrintF("      ignore the stop instruction at the current location\n");
592         PrintF("      from now on\n");
593       } else {
594         PrintF("Unknown command: %s\n", cmd);
595       }
596     }
597   }
598
599   // Add all the breakpoints back to stop execution and enter the debugger
600   // shell when hit.
601   RedoBreakpoints();
602
603 #undef COMMAND_SIZE
604 #undef ARG_SIZE
605
606 #undef STR
607 #undef XSTR
608 }
609
610
611 static bool ICacheMatch(void* one, void* two) {
612   DCHECK((reinterpret_cast<intptr_t>(one) & CachePage::kPageMask) == 0);
613   DCHECK((reinterpret_cast<intptr_t>(two) & CachePage::kPageMask) == 0);
614   return one == two;
615 }
616
617
618 static uint32_t ICacheHash(void* key) {
619   return static_cast<uint32_t>(reinterpret_cast<uintptr_t>(key)) >> 2;
620 }
621
622
623 static bool AllOnOnePage(uintptr_t start, int size) {
624   intptr_t start_page = (start & ~CachePage::kPageMask);
625   intptr_t end_page = ((start + size) & ~CachePage::kPageMask);
626   return start_page == end_page;
627 }
628
629
630 void Simulator::set_last_debugger_input(char* input) {
631   DeleteArray(last_debugger_input_);
632   last_debugger_input_ = input;
633 }
634
635
636 void Simulator::FlushICache(v8::internal::HashMap* i_cache,
637                             void* start_addr,
638                             size_t size) {
639   intptr_t start = reinterpret_cast<intptr_t>(start_addr);
640   int intra_line = (start & CachePage::kLineMask);
641   start -= intra_line;
642   size += intra_line;
643   size = ((size - 1) | CachePage::kLineMask) + 1;
644   int offset = (start & CachePage::kPageMask);
645   while (!AllOnOnePage(start, size - 1)) {
646     int bytes_to_flush = CachePage::kPageSize - offset;
647     FlushOnePage(i_cache, start, bytes_to_flush);
648     start += bytes_to_flush;
649     size -= bytes_to_flush;
650     DCHECK_EQ(0, start & CachePage::kPageMask);
651     offset = 0;
652   }
653   if (size != 0) {
654     FlushOnePage(i_cache, start, size);
655   }
656 }
657
658
659 CachePage* Simulator::GetCachePage(v8::internal::HashMap* i_cache, void* page) {
660   v8::internal::HashMap::Entry* entry = i_cache->Lookup(page,
661                                                         ICacheHash(page),
662                                                         true);
663   if (entry->value == NULL) {
664     CachePage* new_page = new CachePage();
665     entry->value = new_page;
666   }
667   return reinterpret_cast<CachePage*>(entry->value);
668 }
669
670
671 // Flush from start up to and not including start + size.
672 void Simulator::FlushOnePage(v8::internal::HashMap* i_cache,
673                              intptr_t start,
674                              int size) {
675   DCHECK(size <= CachePage::kPageSize);
676   DCHECK(AllOnOnePage(start, size - 1));
677   DCHECK((start & CachePage::kLineMask) == 0);
678   DCHECK((size & CachePage::kLineMask) == 0);
679   void* page = reinterpret_cast<void*>(start & (~CachePage::kPageMask));
680   int offset = (start & CachePage::kPageMask);
681   CachePage* cache_page = GetCachePage(i_cache, page);
682   char* valid_bytemap = cache_page->ValidityByte(offset);
683   memset(valid_bytemap, CachePage::LINE_INVALID, size >> CachePage::kLineShift);
684 }
685
686
687 void Simulator::CheckICache(v8::internal::HashMap* i_cache,
688                             Instruction* instr) {
689   intptr_t address = reinterpret_cast<intptr_t>(instr);
690   void* page = reinterpret_cast<void*>(address & (~CachePage::kPageMask));
691   void* line = reinterpret_cast<void*>(address & (~CachePage::kLineMask));
692   int offset = (address & CachePage::kPageMask);
693   CachePage* cache_page = GetCachePage(i_cache, page);
694   char* cache_valid_byte = cache_page->ValidityByte(offset);
695   bool cache_hit = (*cache_valid_byte == CachePage::LINE_VALID);
696   char* cached_line = cache_page->CachedData(offset & ~CachePage::kLineMask);
697   if (cache_hit) {
698     // Check that the data in memory matches the contents of the I-cache.
699     CHECK_EQ(0,
700              memcmp(reinterpret_cast<void*>(instr),
701                     cache_page->CachedData(offset), Instruction::kInstrSize));
702   } else {
703     // Cache miss.  Load memory into the cache.
704     memcpy(cached_line, line, CachePage::kLineLength);
705     *cache_valid_byte = CachePage::LINE_VALID;
706   }
707 }
708
709
710 void Simulator::Initialize(Isolate* isolate) {
711   if (isolate->simulator_initialized()) return;
712   isolate->set_simulator_initialized(true);
713   ::v8::internal::ExternalReference::set_redirector(isolate,
714                                                     &RedirectExternalReference);
715 }
716
717
718 Simulator::Simulator(Isolate* isolate) : isolate_(isolate) {
719   i_cache_ = isolate_->simulator_i_cache();
720   if (i_cache_ == NULL) {
721     i_cache_ = new v8::internal::HashMap(&ICacheMatch);
722     isolate_->set_simulator_i_cache(i_cache_);
723   }
724   Initialize(isolate);
725   // Set up simulator support first. Some of this information is needed to
726   // setup the architecture state.
727   size_t stack_size = 1 * 1024*1024;  // allocate 1MB for stack
728   stack_ = reinterpret_cast<char*>(malloc(stack_size));
729   pc_modified_ = false;
730   icount_ = 0;
731   break_pc_ = NULL;
732   break_instr_ = 0;
733
734   // Set up architecture state.
735   // All registers are initialized to zero to start with.
736   for (int i = 0; i < num_registers; i++) {
737     registers_[i] = 0;
738   }
739   n_flag_ = false;
740   z_flag_ = false;
741   c_flag_ = false;
742   v_flag_ = false;
743
744   // Initializing VFP registers.
745   // All registers are initialized to zero to start with
746   // even though s_registers_ & d_registers_ share the same
747   // physical registers in the target.
748   for (int i = 0; i < num_d_registers * 2; i++) {
749     vfp_registers_[i] = 0;
750   }
751   n_flag_FPSCR_ = false;
752   z_flag_FPSCR_ = false;
753   c_flag_FPSCR_ = false;
754   v_flag_FPSCR_ = false;
755   FPSCR_rounding_mode_ = RN;
756   FPSCR_default_NaN_mode_ = false;
757
758   inv_op_vfp_flag_ = false;
759   div_zero_vfp_flag_ = false;
760   overflow_vfp_flag_ = false;
761   underflow_vfp_flag_ = false;
762   inexact_vfp_flag_ = false;
763
764   // The sp is initialized to point to the bottom (high address) of the
765   // allocated stack area. To be safe in potential stack underflows we leave
766   // some buffer below.
767   registers_[sp] = reinterpret_cast<int32_t>(stack_) + stack_size - 64;
768   // The lr and pc are initialized to a known bad value that will cause an
769   // access violation if the simulator ever tries to execute it.
770   registers_[pc] = bad_lr;
771   registers_[lr] = bad_lr;
772   InitializeCoverage();
773
774   last_debugger_input_ = NULL;
775 }
776
777
778 Simulator::~Simulator() {
779 }
780
781
782 // When the generated code calls an external reference we need to catch that in
783 // the simulator.  The external reference will be a function compiled for the
784 // host architecture.  We need to call that function instead of trying to
785 // execute it with the simulator.  We do that by redirecting the external
786 // reference to a svc (Supervisor Call) instruction that is handled by
787 // the simulator.  We write the original destination of the jump just at a known
788 // offset from the svc instruction so the simulator knows what to call.
789 class Redirection {
790  public:
791   Redirection(void* external_function, ExternalReference::Type type)
792       : external_function_(external_function),
793         swi_instruction_(al | (0xf*B24) | kCallRtRedirected),
794         type_(type),
795         next_(NULL) {
796     Isolate* isolate = Isolate::Current();
797     next_ = isolate->simulator_redirection();
798     Simulator::current(isolate)->
799         FlushICache(isolate->simulator_i_cache(),
800                     reinterpret_cast<void*>(&swi_instruction_),
801                     Instruction::kInstrSize);
802     isolate->set_simulator_redirection(this);
803   }
804
805   void* address_of_swi_instruction() {
806     return reinterpret_cast<void*>(&swi_instruction_);
807   }
808
809   void* external_function() { return external_function_; }
810   ExternalReference::Type type() { return type_; }
811
812   static Redirection* Get(void* external_function,
813                           ExternalReference::Type type) {
814     Isolate* isolate = Isolate::Current();
815     Redirection* current = isolate->simulator_redirection();
816     for (; current != NULL; current = current->next_) {
817       if (current->external_function_ == external_function) {
818         DCHECK_EQ(current->type(), type);
819         return current;
820       }
821     }
822     return new Redirection(external_function, type);
823   }
824
825   static Redirection* FromSwiInstruction(Instruction* swi_instruction) {
826     char* addr_of_swi = reinterpret_cast<char*>(swi_instruction);
827     char* addr_of_redirection =
828         addr_of_swi - OFFSET_OF(Redirection, swi_instruction_);
829     return reinterpret_cast<Redirection*>(addr_of_redirection);
830   }
831
832   static void* ReverseRedirection(int32_t reg) {
833     Redirection* redirection = FromSwiInstruction(
834         reinterpret_cast<Instruction*>(reinterpret_cast<void*>(reg)));
835     return redirection->external_function();
836   }
837
838  private:
839   void* external_function_;
840   uint32_t swi_instruction_;
841   ExternalReference::Type type_;
842   Redirection* next_;
843 };
844
845
846 void* Simulator::RedirectExternalReference(void* external_function,
847                                            ExternalReference::Type type) {
848   Redirection* redirection = Redirection::Get(external_function, type);
849   return redirection->address_of_swi_instruction();
850 }
851
852
853 // Get the active Simulator for the current thread.
854 Simulator* Simulator::current(Isolate* isolate) {
855   v8::internal::Isolate::PerIsolateThreadData* isolate_data =
856       isolate->FindOrAllocatePerThreadDataForThisThread();
857   DCHECK(isolate_data != NULL);
858
859   Simulator* sim = isolate_data->simulator();
860   if (sim == NULL) {
861     // TODO(146): delete the simulator object when a thread/isolate goes away.
862     sim = new Simulator(isolate);
863     isolate_data->set_simulator(sim);
864   }
865   return sim;
866 }
867
868
869 // Sets the register in the architecture state. It will also deal with updating
870 // Simulator internal state for special registers such as PC.
871 void Simulator::set_register(int reg, int32_t value) {
872   DCHECK((reg >= 0) && (reg < num_registers));
873   if (reg == pc) {
874     pc_modified_ = true;
875   }
876   registers_[reg] = value;
877 }
878
879
880 // Get the register from the architecture state. This function does handle
881 // the special case of accessing the PC register.
882 int32_t Simulator::get_register(int reg) const {
883   DCHECK((reg >= 0) && (reg < num_registers));
884   // Stupid code added to avoid bug in GCC.
885   // See: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=43949
886   if (reg >= num_registers) return 0;
887   // End stupid code.
888   return registers_[reg] + ((reg == pc) ? Instruction::kPCReadOffset : 0);
889 }
890
891
892 double Simulator::get_double_from_register_pair(int reg) {
893   DCHECK((reg >= 0) && (reg < num_registers) && ((reg % 2) == 0));
894
895   double dm_val = 0.0;
896   // Read the bits from the unsigned integer register_[] array
897   // into the double precision floating point value and return it.
898   char buffer[2 * sizeof(vfp_registers_[0])];
899   memcpy(buffer, &registers_[reg], 2 * sizeof(registers_[0]));
900   memcpy(&dm_val, buffer, 2 * sizeof(registers_[0]));
901   return(dm_val);
902 }
903
904
905 void Simulator::set_register_pair_from_double(int reg, double* value) {
906   DCHECK((reg >= 0) && (reg < num_registers) && ((reg % 2) == 0));
907   memcpy(registers_ + reg, value, sizeof(*value));
908 }
909
910
911 void Simulator::set_dw_register(int dreg, const int* dbl) {
912   DCHECK((dreg >= 0) && (dreg < num_d_registers));
913   registers_[dreg] = dbl[0];
914   registers_[dreg + 1] = dbl[1];
915 }
916
917
918 void Simulator::get_d_register(int dreg, uint64_t* value) {
919   DCHECK((dreg >= 0) && (dreg < DwVfpRegister::NumRegisters()));
920   memcpy(value, vfp_registers_ + dreg * 2, sizeof(*value));
921 }
922
923
924 void Simulator::set_d_register(int dreg, const uint64_t* value) {
925   DCHECK((dreg >= 0) && (dreg < DwVfpRegister::NumRegisters()));
926   memcpy(vfp_registers_ + dreg * 2, value, sizeof(*value));
927 }
928
929
930 void Simulator::get_d_register(int dreg, uint32_t* value) {
931   DCHECK((dreg >= 0) && (dreg < DwVfpRegister::NumRegisters()));
932   memcpy(value, vfp_registers_ + dreg * 2, sizeof(*value) * 2);
933 }
934
935
936 void Simulator::set_d_register(int dreg, const uint32_t* value) {
937   DCHECK((dreg >= 0) && (dreg < DwVfpRegister::NumRegisters()));
938   memcpy(vfp_registers_ + dreg * 2, value, sizeof(*value) * 2);
939 }
940
941
942 void Simulator::get_q_register(int qreg, uint64_t* value) {
943   DCHECK((qreg >= 0) && (qreg < num_q_registers));
944   memcpy(value, vfp_registers_ + qreg * 4, sizeof(*value) * 2);
945 }
946
947
948 void Simulator::set_q_register(int qreg, const uint64_t* value) {
949   DCHECK((qreg >= 0) && (qreg < num_q_registers));
950   memcpy(vfp_registers_ + qreg * 4, value, sizeof(*value) * 2);
951 }
952
953
954 void Simulator::get_q_register(int qreg, uint32_t* value) {
955   DCHECK((qreg >= 0) && (qreg < num_q_registers));
956   memcpy(value, vfp_registers_ + qreg * 4, sizeof(*value) * 4);
957 }
958
959
960 void Simulator::set_q_register(int qreg, const uint32_t* value) {
961   DCHECK((qreg >= 0) && (qreg < num_q_registers));
962   memcpy(vfp_registers_ + qreg * 4, value, sizeof(*value) * 4);
963 }
964
965
966 // Raw access to the PC register.
967 void Simulator::set_pc(int32_t value) {
968   pc_modified_ = true;
969   registers_[pc] = value;
970 }
971
972
973 bool Simulator::has_bad_pc() const {
974   return ((registers_[pc] == bad_lr) || (registers_[pc] == end_sim_pc));
975 }
976
977
978 // Raw access to the PC register without the special adjustment when reading.
979 int32_t Simulator::get_pc() const {
980   return registers_[pc];
981 }
982
983
984 // Getting from and setting into VFP registers.
985 void Simulator::set_s_register(int sreg, unsigned int value) {
986   DCHECK((sreg >= 0) && (sreg < num_s_registers));
987   vfp_registers_[sreg] = value;
988 }
989
990
991 unsigned int Simulator::get_s_register(int sreg) const {
992   DCHECK((sreg >= 0) && (sreg < num_s_registers));
993   return vfp_registers_[sreg];
994 }
995
996
997 template<class InputType, int register_size>
998 void Simulator::SetVFPRegister(int reg_index, const InputType& value) {
999   DCHECK(reg_index >= 0);
1000   if (register_size == 1) DCHECK(reg_index < num_s_registers);
1001   if (register_size == 2) DCHECK(reg_index < DwVfpRegister::NumRegisters());
1002
1003   char buffer[register_size * sizeof(vfp_registers_[0])];
1004   memcpy(buffer, &value, register_size * sizeof(vfp_registers_[0]));
1005   memcpy(&vfp_registers_[reg_index * register_size], buffer,
1006          register_size * sizeof(vfp_registers_[0]));
1007 }
1008
1009
1010 template<class ReturnType, int register_size>
1011 ReturnType Simulator::GetFromVFPRegister(int reg_index) {
1012   DCHECK(reg_index >= 0);
1013   if (register_size == 1) DCHECK(reg_index < num_s_registers);
1014   if (register_size == 2) DCHECK(reg_index < DwVfpRegister::NumRegisters());
1015
1016   ReturnType value = 0;
1017   char buffer[register_size * sizeof(vfp_registers_[0])];
1018   memcpy(buffer, &vfp_registers_[register_size * reg_index],
1019          register_size * sizeof(vfp_registers_[0]));
1020   memcpy(&value, buffer, register_size * sizeof(vfp_registers_[0]));
1021   return value;
1022 }
1023
1024
1025 // Runtime FP routines take:
1026 // - two double arguments
1027 // - one double argument and zero or one integer arguments.
1028 // All are consructed here from r0-r3 or d0, d1 and r0.
1029 void Simulator::GetFpArgs(double* x, double* y, int32_t* z) {
1030   if (use_eabi_hardfloat()) {
1031     *x = get_double_from_d_register(0);
1032     *y = get_double_from_d_register(1);
1033     *z = get_register(0);
1034   } else {
1035     // Registers 0 and 1 -> x.
1036     *x = get_double_from_register_pair(0);
1037     // Register 2 and 3 -> y.
1038     *y = get_double_from_register_pair(2);
1039     // Register 2 -> z
1040     *z = get_register(2);
1041   }
1042 }
1043
1044
1045 // The return value is either in r0/r1 or d0.
1046 void Simulator::SetFpResult(const double& result) {
1047   if (use_eabi_hardfloat()) {
1048     char buffer[2 * sizeof(vfp_registers_[0])];
1049     memcpy(buffer, &result, sizeof(buffer));
1050     // Copy result to d0.
1051     memcpy(vfp_registers_, buffer, sizeof(buffer));
1052   } else {
1053     char buffer[2 * sizeof(registers_[0])];
1054     memcpy(buffer, &result, sizeof(buffer));
1055     // Copy result to r0 and r1.
1056     memcpy(registers_, buffer, sizeof(buffer));
1057   }
1058 }
1059
1060
1061 void Simulator::TrashCallerSaveRegisters() {
1062   // We don't trash the registers with the return value.
1063   registers_[2] = 0x50Bad4U;
1064   registers_[3] = 0x50Bad4U;
1065   registers_[12] = 0x50Bad4U;
1066 }
1067
1068
1069 // Some Operating Systems allow unaligned access on ARMv7 targets. We
1070 // assume that unaligned accesses are not allowed unless the v8 build system
1071 // defines the CAN_USE_UNALIGNED_ACCESSES macro to be non-zero.
1072 // The following statements below describes the behavior of the ARM CPUs
1073 // that don't support unaligned access.
1074 // Some ARM platforms raise an interrupt on detecting unaligned access.
1075 // On others it does a funky rotation thing.  For now we
1076 // simply disallow unaligned reads.  Note that simulator runs have the runtime
1077 // system running directly on the host system and only generated code is
1078 // executed in the simulator.  Since the host is typically IA32 we will not
1079 // get the correct ARM-like behaviour on unaligned accesses for those ARM
1080 // targets that don't support unaligned loads and stores.
1081
1082
1083 int Simulator::ReadW(int32_t addr, Instruction* instr) {
1084   if (FLAG_enable_unaligned_accesses || (addr & 3) == 0) {
1085     intptr_t* ptr = reinterpret_cast<intptr_t*>(addr);
1086     return *ptr;
1087   } else {
1088     PrintF("Unaligned read at 0x%08x, pc=0x%08" V8PRIxPTR "\n",
1089            addr,
1090            reinterpret_cast<intptr_t>(instr));
1091     UNIMPLEMENTED();
1092     return 0;
1093   }
1094 }
1095
1096
1097 void Simulator::WriteW(int32_t addr, int value, Instruction* instr) {
1098   if (FLAG_enable_unaligned_accesses || (addr & 3) == 0) {
1099     intptr_t* ptr = reinterpret_cast<intptr_t*>(addr);
1100     *ptr = value;
1101   } else {
1102     PrintF("Unaligned write at 0x%08x, pc=0x%08" V8PRIxPTR "\n",
1103            addr,
1104            reinterpret_cast<intptr_t>(instr));
1105     UNIMPLEMENTED();
1106   }
1107 }
1108
1109
1110 uint16_t Simulator::ReadHU(int32_t addr, Instruction* instr) {
1111   if (FLAG_enable_unaligned_accesses || (addr & 1) == 0) {
1112     uint16_t* ptr = reinterpret_cast<uint16_t*>(addr);
1113     return *ptr;
1114   } else {
1115     PrintF("Unaligned unsigned halfword read at 0x%08x, pc=0x%08"
1116            V8PRIxPTR "\n",
1117            addr,
1118            reinterpret_cast<intptr_t>(instr));
1119     UNIMPLEMENTED();
1120     return 0;
1121   }
1122 }
1123
1124
1125 int16_t Simulator::ReadH(int32_t addr, Instruction* instr) {
1126   if (FLAG_enable_unaligned_accesses || (addr & 1) == 0) {
1127     int16_t* ptr = reinterpret_cast<int16_t*>(addr);
1128     return *ptr;
1129   } else {
1130     PrintF("Unaligned signed halfword read at 0x%08x\n", addr);
1131     UNIMPLEMENTED();
1132     return 0;
1133   }
1134 }
1135
1136
1137 void Simulator::WriteH(int32_t addr, uint16_t value, Instruction* instr) {
1138   if (FLAG_enable_unaligned_accesses || (addr & 1) == 0) {
1139     uint16_t* ptr = reinterpret_cast<uint16_t*>(addr);
1140     *ptr = value;
1141   } else {
1142     PrintF("Unaligned unsigned halfword write at 0x%08x, pc=0x%08"
1143            V8PRIxPTR "\n",
1144            addr,
1145            reinterpret_cast<intptr_t>(instr));
1146     UNIMPLEMENTED();
1147   }
1148 }
1149
1150
1151 void Simulator::WriteH(int32_t addr, int16_t value, Instruction* instr) {
1152   if (FLAG_enable_unaligned_accesses || (addr & 1) == 0) {
1153     int16_t* ptr = reinterpret_cast<int16_t*>(addr);
1154     *ptr = value;
1155   } else {
1156     PrintF("Unaligned halfword write at 0x%08x, pc=0x%08" V8PRIxPTR "\n",
1157            addr,
1158            reinterpret_cast<intptr_t>(instr));
1159     UNIMPLEMENTED();
1160   }
1161 }
1162
1163
1164 uint8_t Simulator::ReadBU(int32_t addr) {
1165   uint8_t* ptr = reinterpret_cast<uint8_t*>(addr);
1166   return *ptr;
1167 }
1168
1169
1170 int8_t Simulator::ReadB(int32_t addr) {
1171   int8_t* ptr = reinterpret_cast<int8_t*>(addr);
1172   return *ptr;
1173 }
1174
1175
1176 void Simulator::WriteB(int32_t addr, uint8_t value) {
1177   uint8_t* ptr = reinterpret_cast<uint8_t*>(addr);
1178   *ptr = value;
1179 }
1180
1181
1182 void Simulator::WriteB(int32_t addr, int8_t value) {
1183   int8_t* ptr = reinterpret_cast<int8_t*>(addr);
1184   *ptr = value;
1185 }
1186
1187
1188 int32_t* Simulator::ReadDW(int32_t addr) {
1189   if (FLAG_enable_unaligned_accesses || (addr & 3) == 0) {
1190     int32_t* ptr = reinterpret_cast<int32_t*>(addr);
1191     return ptr;
1192   } else {
1193     PrintF("Unaligned read at 0x%08x\n", addr);
1194     UNIMPLEMENTED();
1195     return 0;
1196   }
1197 }
1198
1199
1200 void Simulator::WriteDW(int32_t addr, int32_t value1, int32_t value2) {
1201   if (FLAG_enable_unaligned_accesses || (addr & 3) == 0) {
1202     int32_t* ptr = reinterpret_cast<int32_t*>(addr);
1203     *ptr++ = value1;
1204     *ptr = value2;
1205   } else {
1206     PrintF("Unaligned write at 0x%08x\n", addr);
1207     UNIMPLEMENTED();
1208   }
1209 }
1210
1211
1212 // Returns the limit of the stack area to enable checking for stack overflows.
1213 uintptr_t Simulator::StackLimit() const {
1214   // Leave a safety margin of 1024 bytes to prevent overrunning the stack when
1215   // pushing values.
1216   return reinterpret_cast<uintptr_t>(stack_) + 1024;
1217 }
1218
1219
1220 // Unsupported instructions use Format to print an error and stop execution.
1221 void Simulator::Format(Instruction* instr, const char* format) {
1222   PrintF("Simulator found unsupported instruction:\n 0x%08x: %s\n",
1223          reinterpret_cast<intptr_t>(instr), format);
1224   UNIMPLEMENTED();
1225 }
1226
1227
1228 // Checks if the current instruction should be executed based on its
1229 // condition bits.
1230 bool Simulator::ConditionallyExecute(Instruction* instr) {
1231   switch (instr->ConditionField()) {
1232     case eq: return z_flag_;
1233     case ne: return !z_flag_;
1234     case cs: return c_flag_;
1235     case cc: return !c_flag_;
1236     case mi: return n_flag_;
1237     case pl: return !n_flag_;
1238     case vs: return v_flag_;
1239     case vc: return !v_flag_;
1240     case hi: return c_flag_ && !z_flag_;
1241     case ls: return !c_flag_ || z_flag_;
1242     case ge: return n_flag_ == v_flag_;
1243     case lt: return n_flag_ != v_flag_;
1244     case gt: return !z_flag_ && (n_flag_ == v_flag_);
1245     case le: return z_flag_ || (n_flag_ != v_flag_);
1246     case al: return true;
1247     default: UNREACHABLE();
1248   }
1249   return false;
1250 }
1251
1252
1253 // Calculate and set the Negative and Zero flags.
1254 void Simulator::SetNZFlags(int32_t val) {
1255   n_flag_ = (val < 0);
1256   z_flag_ = (val == 0);
1257 }
1258
1259
1260 // Set the Carry flag.
1261 void Simulator::SetCFlag(bool val) {
1262   c_flag_ = val;
1263 }
1264
1265
1266 // Set the oVerflow flag.
1267 void Simulator::SetVFlag(bool val) {
1268   v_flag_ = val;
1269 }
1270
1271
1272 // Calculate C flag value for additions.
1273 bool Simulator::CarryFrom(int32_t left, int32_t right, int32_t carry) {
1274   uint32_t uleft = static_cast<uint32_t>(left);
1275   uint32_t uright = static_cast<uint32_t>(right);
1276   uint32_t urest  = 0xffffffffU - uleft;
1277
1278   return (uright > urest) ||
1279          (carry && (((uright + 1) > urest) || (uright > (urest - 1))));
1280 }
1281
1282
1283 // Calculate C flag value for subtractions.
1284 bool Simulator::BorrowFrom(int32_t left, int32_t right) {
1285   uint32_t uleft = static_cast<uint32_t>(left);
1286   uint32_t uright = static_cast<uint32_t>(right);
1287
1288   return (uright > uleft);
1289 }
1290
1291
1292 // Calculate V flag value for additions and subtractions.
1293 bool Simulator::OverflowFrom(int32_t alu_out,
1294                              int32_t left, int32_t right, bool addition) {
1295   bool overflow;
1296   if (addition) {
1297                // operands have the same sign
1298     overflow = ((left >= 0 && right >= 0) || (left < 0 && right < 0))
1299                // and operands and result have different sign
1300                && ((left < 0 && alu_out >= 0) || (left >= 0 && alu_out < 0));
1301   } else {
1302                // operands have different signs
1303     overflow = ((left < 0 && right >= 0) || (left >= 0 && right < 0))
1304                // and first operand and result have different signs
1305                && ((left < 0 && alu_out >= 0) || (left >= 0 && alu_out < 0));
1306   }
1307   return overflow;
1308 }
1309
1310
1311 // Support for VFP comparisons.
1312 void Simulator::Compute_FPSCR_Flags(double val1, double val2) {
1313   if (std::isnan(val1) || std::isnan(val2)) {
1314     n_flag_FPSCR_ = false;
1315     z_flag_FPSCR_ = false;
1316     c_flag_FPSCR_ = true;
1317     v_flag_FPSCR_ = true;
1318   // All non-NaN cases.
1319   } else if (val1 == val2) {
1320     n_flag_FPSCR_ = false;
1321     z_flag_FPSCR_ = true;
1322     c_flag_FPSCR_ = true;
1323     v_flag_FPSCR_ = false;
1324   } else if (val1 < val2) {
1325     n_flag_FPSCR_ = true;
1326     z_flag_FPSCR_ = false;
1327     c_flag_FPSCR_ = false;
1328     v_flag_FPSCR_ = false;
1329   } else {
1330     // Case when (val1 > val2).
1331     n_flag_FPSCR_ = false;
1332     z_flag_FPSCR_ = false;
1333     c_flag_FPSCR_ = true;
1334     v_flag_FPSCR_ = false;
1335   }
1336 }
1337
1338
1339 void Simulator::Copy_FPSCR_to_APSR() {
1340   n_flag_ = n_flag_FPSCR_;
1341   z_flag_ = z_flag_FPSCR_;
1342   c_flag_ = c_flag_FPSCR_;
1343   v_flag_ = v_flag_FPSCR_;
1344 }
1345
1346
1347 // Addressing Mode 1 - Data-processing operands:
1348 // Get the value based on the shifter_operand with register.
1349 int32_t Simulator::GetShiftRm(Instruction* instr, bool* carry_out) {
1350   ShiftOp shift = instr->ShiftField();
1351   int shift_amount = instr->ShiftAmountValue();
1352   int32_t result = get_register(instr->RmValue());
1353   if (instr->Bit(4) == 0) {
1354     // by immediate
1355     if ((shift == ROR) && (shift_amount == 0)) {
1356       UNIMPLEMENTED();
1357       return result;
1358     } else if (((shift == LSR) || (shift == ASR)) && (shift_amount == 0)) {
1359       shift_amount = 32;
1360     }
1361     switch (shift) {
1362       case ASR: {
1363         if (shift_amount == 0) {
1364           if (result < 0) {
1365             result = 0xffffffff;
1366             *carry_out = true;
1367           } else {
1368             result = 0;
1369             *carry_out = false;
1370           }
1371         } else {
1372           result >>= (shift_amount - 1);
1373           *carry_out = (result & 1) == 1;
1374           result >>= 1;
1375         }
1376         break;
1377       }
1378
1379       case LSL: {
1380         if (shift_amount == 0) {
1381           *carry_out = c_flag_;
1382         } else {
1383           result <<= (shift_amount - 1);
1384           *carry_out = (result < 0);
1385           result <<= 1;
1386         }
1387         break;
1388       }
1389
1390       case LSR: {
1391         if (shift_amount == 0) {
1392           result = 0;
1393           *carry_out = c_flag_;
1394         } else {
1395           uint32_t uresult = static_cast<uint32_t>(result);
1396           uresult >>= (shift_amount - 1);
1397           *carry_out = (uresult & 1) == 1;
1398           uresult >>= 1;
1399           result = static_cast<int32_t>(uresult);
1400         }
1401         break;
1402       }
1403
1404       case ROR: {
1405         if (shift_amount == 0) {
1406           *carry_out = c_flag_;
1407         } else {
1408           uint32_t left = static_cast<uint32_t>(result) >> shift_amount;
1409           uint32_t right = static_cast<uint32_t>(result) << (32 - shift_amount);
1410           result = right | left;
1411           *carry_out = (static_cast<uint32_t>(result) >> 31) != 0;
1412         }
1413         break;
1414       }
1415
1416       default: {
1417         UNREACHABLE();
1418         break;
1419       }
1420     }
1421   } else {
1422     // by register
1423     int rs = instr->RsValue();
1424     shift_amount = get_register(rs) &0xff;
1425     switch (shift) {
1426       case ASR: {
1427         if (shift_amount == 0) {
1428           *carry_out = c_flag_;
1429         } else if (shift_amount < 32) {
1430           result >>= (shift_amount - 1);
1431           *carry_out = (result & 1) == 1;
1432           result >>= 1;
1433         } else {
1434           DCHECK(shift_amount >= 32);
1435           if (result < 0) {
1436             *carry_out = true;
1437             result = 0xffffffff;
1438           } else {
1439             *carry_out = false;
1440             result = 0;
1441           }
1442         }
1443         break;
1444       }
1445
1446       case LSL: {
1447         if (shift_amount == 0) {
1448           *carry_out = c_flag_;
1449         } else if (shift_amount < 32) {
1450           result <<= (shift_amount - 1);
1451           *carry_out = (result < 0);
1452           result <<= 1;
1453         } else if (shift_amount == 32) {
1454           *carry_out = (result & 1) == 1;
1455           result = 0;
1456         } else {
1457           DCHECK(shift_amount > 32);
1458           *carry_out = false;
1459           result = 0;
1460         }
1461         break;
1462       }
1463
1464       case LSR: {
1465         if (shift_amount == 0) {
1466           *carry_out = c_flag_;
1467         } else if (shift_amount < 32) {
1468           uint32_t uresult = static_cast<uint32_t>(result);
1469           uresult >>= (shift_amount - 1);
1470           *carry_out = (uresult & 1) == 1;
1471           uresult >>= 1;
1472           result = static_cast<int32_t>(uresult);
1473         } else if (shift_amount == 32) {
1474           *carry_out = (result < 0);
1475           result = 0;
1476         } else {
1477           *carry_out = false;
1478           result = 0;
1479         }
1480         break;
1481       }
1482
1483       case ROR: {
1484         if (shift_amount == 0) {
1485           *carry_out = c_flag_;
1486         } else {
1487           uint32_t left = static_cast<uint32_t>(result) >> shift_amount;
1488           uint32_t right = static_cast<uint32_t>(result) << (32 - shift_amount);
1489           result = right | left;
1490           *carry_out = (static_cast<uint32_t>(result) >> 31) != 0;
1491         }
1492         break;
1493       }
1494
1495       default: {
1496         UNREACHABLE();
1497         break;
1498       }
1499     }
1500   }
1501   return result;
1502 }
1503
1504
1505 // Addressing Mode 1 - Data-processing operands:
1506 // Get the value based on the shifter_operand with immediate.
1507 int32_t Simulator::GetImm(Instruction* instr, bool* carry_out) {
1508   int rotate = instr->RotateValue() * 2;
1509   int immed8 = instr->Immed8Value();
1510   int imm = base::bits::RotateRight32(immed8, rotate);
1511   *carry_out = (rotate == 0) ? c_flag_ : (imm < 0);
1512   return imm;
1513 }
1514
1515
1516 static int count_bits(int bit_vector) {
1517   int count = 0;
1518   while (bit_vector != 0) {
1519     if ((bit_vector & 1) != 0) {
1520       count++;
1521     }
1522     bit_vector >>= 1;
1523   }
1524   return count;
1525 }
1526
1527
1528 int32_t Simulator::ProcessPU(Instruction* instr,
1529                              int num_regs,
1530                              int reg_size,
1531                              intptr_t* start_address,
1532                              intptr_t* end_address) {
1533   int rn = instr->RnValue();
1534   int32_t rn_val = get_register(rn);
1535   switch (instr->PUField()) {
1536     case da_x: {
1537       UNIMPLEMENTED();
1538       break;
1539     }
1540     case ia_x: {
1541       *start_address = rn_val;
1542       *end_address = rn_val + (num_regs * reg_size) - reg_size;
1543       rn_val = rn_val + (num_regs * reg_size);
1544       break;
1545     }
1546     case db_x: {
1547       *start_address = rn_val - (num_regs * reg_size);
1548       *end_address = rn_val - reg_size;
1549       rn_val = *start_address;
1550       break;
1551     }
1552     case ib_x: {
1553       *start_address = rn_val + reg_size;
1554       *end_address = rn_val + (num_regs * reg_size);
1555       rn_val = *end_address;
1556       break;
1557     }
1558     default: {
1559       UNREACHABLE();
1560       break;
1561     }
1562   }
1563   return rn_val;
1564 }
1565
1566
1567 // Addressing Mode 4 - Load and Store Multiple
1568 void Simulator::HandleRList(Instruction* instr, bool load) {
1569   int rlist = instr->RlistValue();
1570   int num_regs = count_bits(rlist);
1571
1572   intptr_t start_address = 0;
1573   intptr_t end_address = 0;
1574   int32_t rn_val =
1575       ProcessPU(instr, num_regs, kPointerSize, &start_address, &end_address);
1576
1577   intptr_t* address = reinterpret_cast<intptr_t*>(start_address);
1578   // Catch null pointers a little earlier.
1579   DCHECK(start_address > 8191 || start_address < 0);
1580   int reg = 0;
1581   while (rlist != 0) {
1582     if ((rlist & 1) != 0) {
1583       if (load) {
1584         set_register(reg, *address);
1585       } else {
1586         *address = get_register(reg);
1587       }
1588       address += 1;
1589     }
1590     reg++;
1591     rlist >>= 1;
1592   }
1593   DCHECK(end_address == ((intptr_t)address) - 4);
1594   if (instr->HasW()) {
1595     set_register(instr->RnValue(), rn_val);
1596   }
1597 }
1598
1599
1600 // Addressing Mode 6 - Load and Store Multiple Coprocessor registers.
1601 void Simulator::HandleVList(Instruction* instr) {
1602   VFPRegPrecision precision =
1603       (instr->SzValue() == 0) ? kSinglePrecision : kDoublePrecision;
1604   int operand_size = (precision == kSinglePrecision) ? 4 : 8;
1605
1606   bool load = (instr->VLValue() == 0x1);
1607
1608   int vd;
1609   int num_regs;
1610   vd = instr->VFPDRegValue(precision);
1611   if (precision == kSinglePrecision) {
1612     num_regs = instr->Immed8Value();
1613   } else {
1614     num_regs = instr->Immed8Value() / 2;
1615   }
1616
1617   intptr_t start_address = 0;
1618   intptr_t end_address = 0;
1619   int32_t rn_val =
1620       ProcessPU(instr, num_regs, operand_size, &start_address, &end_address);
1621
1622   intptr_t* address = reinterpret_cast<intptr_t*>(start_address);
1623   for (int reg = vd; reg < vd + num_regs; reg++) {
1624     if (precision == kSinglePrecision) {
1625       if (load) {
1626         set_s_register_from_sinteger(
1627             reg, ReadW(reinterpret_cast<int32_t>(address), instr));
1628       } else {
1629         WriteW(reinterpret_cast<int32_t>(address),
1630                get_sinteger_from_s_register(reg), instr);
1631       }
1632       address += 1;
1633     } else {
1634       if (load) {
1635         int32_t data[] = {
1636           ReadW(reinterpret_cast<int32_t>(address), instr),
1637           ReadW(reinterpret_cast<int32_t>(address + 1), instr)
1638         };
1639         set_d_register(reg, reinterpret_cast<uint32_t*>(data));
1640       } else {
1641         uint32_t data[2];
1642         get_d_register(reg, data);
1643         WriteW(reinterpret_cast<int32_t>(address), data[0], instr);
1644         WriteW(reinterpret_cast<int32_t>(address + 1), data[1], instr);
1645       }
1646       address += 2;
1647     }
1648   }
1649   DCHECK(reinterpret_cast<intptr_t>(address) - operand_size == end_address);
1650   if (instr->HasW()) {
1651     set_register(instr->RnValue(), rn_val);
1652   }
1653 }
1654
1655
1656 // Calls into the V8 runtime are based on this very simple interface.
1657 // Note: To be able to return two values from some calls the code in runtime.cc
1658 // uses the ObjectPair which is essentially two 32-bit values stuffed into a
1659 // 64-bit value. With the code below we assume that all runtime calls return
1660 // 64 bits of result. If they don't, the r1 result register contains a bogus
1661 // value, which is fine because it is caller-saved.
1662 typedef int64_t (*SimulatorRuntimeCall)(int32_t arg0,
1663                                         int32_t arg1,
1664                                         int32_t arg2,
1665                                         int32_t arg3,
1666                                         int32_t arg4,
1667                                         int32_t arg5);
1668
1669 // These prototypes handle the four types of FP calls.
1670 typedef int64_t (*SimulatorRuntimeCompareCall)(double darg0, double darg1);
1671 typedef double (*SimulatorRuntimeFPFPCall)(double darg0, double darg1);
1672 typedef double (*SimulatorRuntimeFPCall)(double darg0);
1673 typedef double (*SimulatorRuntimeFPIntCall)(double darg0, int32_t arg0);
1674
1675 // This signature supports direct call in to API function native callback
1676 // (refer to InvocationCallback in v8.h).
1677 typedef void (*SimulatorRuntimeDirectApiCall)(int32_t arg0);
1678 typedef void (*SimulatorRuntimeProfilingApiCall)(int32_t arg0, void* arg1);
1679
1680 // This signature supports direct call to accessor getter callback.
1681 typedef void (*SimulatorRuntimeDirectGetterCall)(int32_t arg0, int32_t arg1);
1682 typedef void (*SimulatorRuntimeProfilingGetterCall)(
1683     int32_t arg0, int32_t arg1, void* arg2);
1684
1685 // Software interrupt instructions are used by the simulator to call into the
1686 // C-based V8 runtime.
1687 void Simulator::SoftwareInterrupt(Instruction* instr) {
1688   int svc = instr->SvcValue();
1689   switch (svc) {
1690     case kCallRtRedirected: {
1691       // Check if stack is aligned. Error if not aligned is reported below to
1692       // include information on the function called.
1693       bool stack_aligned =
1694           (get_register(sp)
1695            & (::v8::internal::FLAG_sim_stack_alignment - 1)) == 0;
1696       Redirection* redirection = Redirection::FromSwiInstruction(instr);
1697       int32_t arg0 = get_register(r0);
1698       int32_t arg1 = get_register(r1);
1699       int32_t arg2 = get_register(r2);
1700       int32_t arg3 = get_register(r3);
1701       int32_t* stack_pointer = reinterpret_cast<int32_t*>(get_register(sp));
1702       int32_t arg4 = stack_pointer[0];
1703       int32_t arg5 = stack_pointer[1];
1704       bool fp_call =
1705          (redirection->type() == ExternalReference::BUILTIN_FP_FP_CALL) ||
1706          (redirection->type() == ExternalReference::BUILTIN_COMPARE_CALL) ||
1707          (redirection->type() == ExternalReference::BUILTIN_FP_CALL) ||
1708          (redirection->type() == ExternalReference::BUILTIN_FP_INT_CALL);
1709       // This is dodgy but it works because the C entry stubs are never moved.
1710       // See comment in codegen-arm.cc and bug 1242173.
1711       int32_t saved_lr = get_register(lr);
1712       intptr_t external =
1713           reinterpret_cast<intptr_t>(redirection->external_function());
1714       if (fp_call) {
1715         double dval0, dval1;  // one or two double parameters
1716         int32_t ival;         // zero or one integer parameters
1717         int64_t iresult = 0;  // integer return value
1718         double dresult = 0;   // double return value
1719         GetFpArgs(&dval0, &dval1, &ival);
1720         if (::v8::internal::FLAG_trace_sim || !stack_aligned) {
1721           SimulatorRuntimeCall generic_target =
1722             reinterpret_cast<SimulatorRuntimeCall>(external);
1723           switch (redirection->type()) {
1724           case ExternalReference::BUILTIN_FP_FP_CALL:
1725           case ExternalReference::BUILTIN_COMPARE_CALL:
1726             PrintF("Call to host function at %p with args %f, %f",
1727                    FUNCTION_ADDR(generic_target), dval0, dval1);
1728             break;
1729           case ExternalReference::BUILTIN_FP_CALL:
1730             PrintF("Call to host function at %p with arg %f",
1731                 FUNCTION_ADDR(generic_target), dval0);
1732             break;
1733           case ExternalReference::BUILTIN_FP_INT_CALL:
1734             PrintF("Call to host function at %p with args %f, %d",
1735                    FUNCTION_ADDR(generic_target), dval0, ival);
1736             break;
1737           default:
1738             UNREACHABLE();
1739             break;
1740           }
1741           if (!stack_aligned) {
1742             PrintF(" with unaligned stack %08x\n", get_register(sp));
1743           }
1744           PrintF("\n");
1745         }
1746         CHECK(stack_aligned);
1747         switch (redirection->type()) {
1748         case ExternalReference::BUILTIN_COMPARE_CALL: {
1749           SimulatorRuntimeCompareCall target =
1750             reinterpret_cast<SimulatorRuntimeCompareCall>(external);
1751           iresult = target(dval0, dval1);
1752           set_register(r0, static_cast<int32_t>(iresult));
1753           set_register(r1, static_cast<int32_t>(iresult >> 32));
1754           break;
1755         }
1756         case ExternalReference::BUILTIN_FP_FP_CALL: {
1757           SimulatorRuntimeFPFPCall target =
1758             reinterpret_cast<SimulatorRuntimeFPFPCall>(external);
1759           dresult = target(dval0, dval1);
1760           SetFpResult(dresult);
1761           break;
1762         }
1763         case ExternalReference::BUILTIN_FP_CALL: {
1764           SimulatorRuntimeFPCall target =
1765             reinterpret_cast<SimulatorRuntimeFPCall>(external);
1766           dresult = target(dval0);
1767           SetFpResult(dresult);
1768           break;
1769         }
1770         case ExternalReference::BUILTIN_FP_INT_CALL: {
1771           SimulatorRuntimeFPIntCall target =
1772             reinterpret_cast<SimulatorRuntimeFPIntCall>(external);
1773           dresult = target(dval0, ival);
1774           SetFpResult(dresult);
1775           break;
1776         }
1777         default:
1778           UNREACHABLE();
1779           break;
1780         }
1781         if (::v8::internal::FLAG_trace_sim || !stack_aligned) {
1782           switch (redirection->type()) {
1783           case ExternalReference::BUILTIN_COMPARE_CALL:
1784             PrintF("Returned %08x\n", static_cast<int32_t>(iresult));
1785             break;
1786           case ExternalReference::BUILTIN_FP_FP_CALL:
1787           case ExternalReference::BUILTIN_FP_CALL:
1788           case ExternalReference::BUILTIN_FP_INT_CALL:
1789             PrintF("Returned %f\n", dresult);
1790             break;
1791           default:
1792             UNREACHABLE();
1793             break;
1794           }
1795         }
1796       } else if (redirection->type() == ExternalReference::DIRECT_API_CALL) {
1797         if (::v8::internal::FLAG_trace_sim || !stack_aligned) {
1798           PrintF("Call to host function at %p args %08x",
1799               reinterpret_cast<void*>(external), arg0);
1800           if (!stack_aligned) {
1801             PrintF(" with unaligned stack %08x\n", get_register(sp));
1802           }
1803           PrintF("\n");
1804         }
1805         CHECK(stack_aligned);
1806         SimulatorRuntimeDirectApiCall target =
1807             reinterpret_cast<SimulatorRuntimeDirectApiCall>(external);
1808         target(arg0);
1809       } else if (
1810           redirection->type() == ExternalReference::PROFILING_API_CALL) {
1811         if (::v8::internal::FLAG_trace_sim || !stack_aligned) {
1812           PrintF("Call to host function at %p args %08x %08x",
1813               reinterpret_cast<void*>(external), arg0, arg1);
1814           if (!stack_aligned) {
1815             PrintF(" with unaligned stack %08x\n", get_register(sp));
1816           }
1817           PrintF("\n");
1818         }
1819         CHECK(stack_aligned);
1820         SimulatorRuntimeProfilingApiCall target =
1821             reinterpret_cast<SimulatorRuntimeProfilingApiCall>(external);
1822         target(arg0, Redirection::ReverseRedirection(arg1));
1823       } else if (
1824           redirection->type() == ExternalReference::DIRECT_GETTER_CALL) {
1825         if (::v8::internal::FLAG_trace_sim || !stack_aligned) {
1826           PrintF("Call to host function at %p args %08x %08x",
1827               reinterpret_cast<void*>(external), arg0, arg1);
1828           if (!stack_aligned) {
1829             PrintF(" with unaligned stack %08x\n", get_register(sp));
1830           }
1831           PrintF("\n");
1832         }
1833         CHECK(stack_aligned);
1834         SimulatorRuntimeDirectGetterCall target =
1835             reinterpret_cast<SimulatorRuntimeDirectGetterCall>(external);
1836         target(arg0, arg1);
1837       } else if (
1838           redirection->type() == ExternalReference::PROFILING_GETTER_CALL) {
1839         if (::v8::internal::FLAG_trace_sim || !stack_aligned) {
1840           PrintF("Call to host function at %p args %08x %08x %08x",
1841               reinterpret_cast<void*>(external), arg0, arg1, arg2);
1842           if (!stack_aligned) {
1843             PrintF(" with unaligned stack %08x\n", get_register(sp));
1844           }
1845           PrintF("\n");
1846         }
1847         CHECK(stack_aligned);
1848         SimulatorRuntimeProfilingGetterCall target =
1849             reinterpret_cast<SimulatorRuntimeProfilingGetterCall>(
1850                 external);
1851         target(arg0, arg1, Redirection::ReverseRedirection(arg2));
1852       } else {
1853         // builtin call.
1854         DCHECK(redirection->type() == ExternalReference::BUILTIN_CALL);
1855         SimulatorRuntimeCall target =
1856             reinterpret_cast<SimulatorRuntimeCall>(external);
1857         if (::v8::internal::FLAG_trace_sim || !stack_aligned) {
1858           PrintF(
1859               "Call to host function at %p "
1860               "args %08x, %08x, %08x, %08x, %08x, %08x",
1861               FUNCTION_ADDR(target),
1862               arg0,
1863               arg1,
1864               arg2,
1865               arg3,
1866               arg4,
1867               arg5);
1868           if (!stack_aligned) {
1869             PrintF(" with unaligned stack %08x\n", get_register(sp));
1870           }
1871           PrintF("\n");
1872         }
1873         CHECK(stack_aligned);
1874         int64_t result = target(arg0, arg1, arg2, arg3, arg4, arg5);
1875         int32_t lo_res = static_cast<int32_t>(result);
1876         int32_t hi_res = static_cast<int32_t>(result >> 32);
1877         if (::v8::internal::FLAG_trace_sim) {
1878           PrintF("Returned %08x\n", lo_res);
1879         }
1880         set_register(r0, lo_res);
1881         set_register(r1, hi_res);
1882       }
1883       set_register(lr, saved_lr);
1884       set_pc(get_register(lr));
1885       break;
1886     }
1887     case kBreakpoint: {
1888       ArmDebugger dbg(this);
1889       dbg.Debug();
1890       break;
1891     }
1892     // stop uses all codes greater than 1 << 23.
1893     default: {
1894       if (svc >= (1 << 23)) {
1895         uint32_t code = svc & kStopCodeMask;
1896         if (isWatchedStop(code)) {
1897           IncreaseStopCounter(code);
1898         }
1899         // Stop if it is enabled, otherwise go on jumping over the stop
1900         // and the message address.
1901         if (isEnabledStop(code)) {
1902           ArmDebugger dbg(this);
1903           dbg.Stop(instr);
1904         } else {
1905           set_pc(get_pc() + 2 * Instruction::kInstrSize);
1906         }
1907       } else {
1908         // This is not a valid svc code.
1909         UNREACHABLE();
1910         break;
1911       }
1912     }
1913   }
1914 }
1915
1916
1917 double Simulator::canonicalizeNaN(double value) {
1918   // Default NaN value, see "NaN handling" in "IEEE 754 standard implementation
1919   // choices" of the ARM Reference Manual.
1920   const uint64_t kDefaultNaN = V8_UINT64_C(0x7FF8000000000000);
1921   if (FPSCR_default_NaN_mode_ && std::isnan(value)) {
1922     value = bit_cast<double>(kDefaultNaN);
1923   }
1924   return value;
1925 }
1926
1927
1928 // Stop helper functions.
1929 bool Simulator::isStopInstruction(Instruction* instr) {
1930   return (instr->Bits(27, 24) == 0xF) && (instr->SvcValue() >= kStopCode);
1931 }
1932
1933
1934 bool Simulator::isWatchedStop(uint32_t code) {
1935   DCHECK(code <= kMaxStopCode);
1936   return code < kNumOfWatchedStops;
1937 }
1938
1939
1940 bool Simulator::isEnabledStop(uint32_t code) {
1941   DCHECK(code <= kMaxStopCode);
1942   // Unwatched stops are always enabled.
1943   return !isWatchedStop(code) ||
1944     !(watched_stops_[code].count & kStopDisabledBit);
1945 }
1946
1947
1948 void Simulator::EnableStop(uint32_t code) {
1949   DCHECK(isWatchedStop(code));
1950   if (!isEnabledStop(code)) {
1951     watched_stops_[code].count &= ~kStopDisabledBit;
1952   }
1953 }
1954
1955
1956 void Simulator::DisableStop(uint32_t code) {
1957   DCHECK(isWatchedStop(code));
1958   if (isEnabledStop(code)) {
1959     watched_stops_[code].count |= kStopDisabledBit;
1960   }
1961 }
1962
1963
1964 void Simulator::IncreaseStopCounter(uint32_t code) {
1965   DCHECK(code <= kMaxStopCode);
1966   DCHECK(isWatchedStop(code));
1967   if ((watched_stops_[code].count & ~(1 << 31)) == 0x7fffffff) {
1968     PrintF("Stop counter for code %i has overflowed.\n"
1969            "Enabling this code and reseting the counter to 0.\n", code);
1970     watched_stops_[code].count = 0;
1971     EnableStop(code);
1972   } else {
1973     watched_stops_[code].count++;
1974   }
1975 }
1976
1977
1978 // Print a stop status.
1979 void Simulator::PrintStopInfo(uint32_t code) {
1980   DCHECK(code <= kMaxStopCode);
1981   if (!isWatchedStop(code)) {
1982     PrintF("Stop not watched.");
1983   } else {
1984     const char* state = isEnabledStop(code) ? "Enabled" : "Disabled";
1985     int32_t count = watched_stops_[code].count & ~kStopDisabledBit;
1986     // Don't print the state of unused breakpoints.
1987     if (count != 0) {
1988       if (watched_stops_[code].desc) {
1989         PrintF("stop %i - 0x%x: \t%s, \tcounter = %i, \t%s\n",
1990                code, code, state, count, watched_stops_[code].desc);
1991       } else {
1992         PrintF("stop %i - 0x%x: \t%s, \tcounter = %i\n",
1993                code, code, state, count);
1994       }
1995     }
1996   }
1997 }
1998
1999
2000 // Handle execution based on instruction types.
2001
2002 // Instruction types 0 and 1 are both rolled into one function because they
2003 // only differ in the handling of the shifter_operand.
2004 void Simulator::DecodeType01(Instruction* instr) {
2005   int type = instr->TypeValue();
2006   if ((type == 0) && instr->IsSpecialType0()) {
2007     // multiply instruction or extra loads and stores
2008     if (instr->Bits(7, 4) == 9) {
2009       if (instr->Bit(24) == 0) {
2010         // Raw field decoding here. Multiply instructions have their Rd in
2011         // funny places.
2012         int rn = instr->RnValue();
2013         int rm = instr->RmValue();
2014         int rs = instr->RsValue();
2015         int32_t rs_val = get_register(rs);
2016         int32_t rm_val = get_register(rm);
2017         if (instr->Bit(23) == 0) {
2018           if (instr->Bit(21) == 0) {
2019             // The MUL instruction description (A 4.1.33) refers to Rd as being
2020             // the destination for the operation, but it confusingly uses the
2021             // Rn field to encode it.
2022             // Format(instr, "mul'cond's 'rn, 'rm, 'rs");
2023             int rd = rn;  // Remap the rn field to the Rd register.
2024             int32_t alu_out = rm_val * rs_val;
2025             set_register(rd, alu_out);
2026             if (instr->HasS()) {
2027               SetNZFlags(alu_out);
2028             }
2029           } else {
2030             int rd = instr->RdValue();
2031             int32_t acc_value = get_register(rd);
2032             if (instr->Bit(22) == 0) {
2033               // The MLA instruction description (A 4.1.28) refers to the order
2034               // of registers as "Rd, Rm, Rs, Rn". But confusingly it uses the
2035               // Rn field to encode the Rd register and the Rd field to encode
2036               // the Rn register.
2037               // Format(instr, "mla'cond's 'rn, 'rm, 'rs, 'rd");
2038               int32_t mul_out = rm_val * rs_val;
2039               int32_t result = acc_value + mul_out;
2040               set_register(rn, result);
2041             } else {
2042               // Format(instr, "mls'cond's 'rn, 'rm, 'rs, 'rd");
2043               int32_t mul_out = rm_val * rs_val;
2044               int32_t result = acc_value - mul_out;
2045               set_register(rn, result);
2046             }
2047           }
2048         } else {
2049           // The signed/long multiply instructions use the terms RdHi and RdLo
2050           // when referring to the target registers. They are mapped to the Rn
2051           // and Rd fields as follows:
2052           // RdLo == Rd
2053           // RdHi == Rn (This is confusingly stored in variable rd here
2054           //             because the mul instruction from above uses the
2055           //             Rn field to encode the Rd register. Good luck figuring
2056           //             this out without reading the ARM instruction manual
2057           //             at a very detailed level.)
2058           // Format(instr, "'um'al'cond's 'rd, 'rn, 'rs, 'rm");
2059           int rd_hi = rn;  // Remap the rn field to the RdHi register.
2060           int rd_lo = instr->RdValue();
2061           int32_t hi_res = 0;
2062           int32_t lo_res = 0;
2063           if (instr->Bit(22) == 1) {
2064             int64_t left_op  = static_cast<int32_t>(rm_val);
2065             int64_t right_op = static_cast<int32_t>(rs_val);
2066             uint64_t result = left_op * right_op;
2067             hi_res = static_cast<int32_t>(result >> 32);
2068             lo_res = static_cast<int32_t>(result & 0xffffffff);
2069           } else {
2070             // unsigned multiply
2071             uint64_t left_op  = static_cast<uint32_t>(rm_val);
2072             uint64_t right_op = static_cast<uint32_t>(rs_val);
2073             uint64_t result = left_op * right_op;
2074             hi_res = static_cast<int32_t>(result >> 32);
2075             lo_res = static_cast<int32_t>(result & 0xffffffff);
2076           }
2077           set_register(rd_lo, lo_res);
2078           set_register(rd_hi, hi_res);
2079           if (instr->HasS()) {
2080             UNIMPLEMENTED();
2081           }
2082         }
2083       } else {
2084         UNIMPLEMENTED();  // Not used by V8.
2085       }
2086     } else {
2087       // extra load/store instructions
2088       int rd = instr->RdValue();
2089       int rn = instr->RnValue();
2090       int32_t rn_val = get_register(rn);
2091       int32_t addr = 0;
2092       if (instr->Bit(22) == 0) {
2093         int rm = instr->RmValue();
2094         int32_t rm_val = get_register(rm);
2095         switch (instr->PUField()) {
2096           case da_x: {
2097             // Format(instr, "'memop'cond'sign'h 'rd, ['rn], -'rm");
2098             DCHECK(!instr->HasW());
2099             addr = rn_val;
2100             rn_val -= rm_val;
2101             set_register(rn, rn_val);
2102             break;
2103           }
2104           case ia_x: {
2105             // Format(instr, "'memop'cond'sign'h 'rd, ['rn], +'rm");
2106             DCHECK(!instr->HasW());
2107             addr = rn_val;
2108             rn_val += rm_val;
2109             set_register(rn, rn_val);
2110             break;
2111           }
2112           case db_x: {
2113             // Format(instr, "'memop'cond'sign'h 'rd, ['rn, -'rm]'w");
2114             rn_val -= rm_val;
2115             addr = rn_val;
2116             if (instr->HasW()) {
2117               set_register(rn, rn_val);
2118             }
2119             break;
2120           }
2121           case ib_x: {
2122             // Format(instr, "'memop'cond'sign'h 'rd, ['rn, +'rm]'w");
2123             rn_val += rm_val;
2124             addr = rn_val;
2125             if (instr->HasW()) {
2126               set_register(rn, rn_val);
2127             }
2128             break;
2129           }
2130           default: {
2131             // The PU field is a 2-bit field.
2132             UNREACHABLE();
2133             break;
2134           }
2135         }
2136       } else {
2137         int32_t imm_val = (instr->ImmedHValue() << 4) | instr->ImmedLValue();
2138         switch (instr->PUField()) {
2139           case da_x: {
2140             // Format(instr, "'memop'cond'sign'h 'rd, ['rn], #-'off8");
2141             DCHECK(!instr->HasW());
2142             addr = rn_val;
2143             rn_val -= imm_val;
2144             set_register(rn, rn_val);
2145             break;
2146           }
2147           case ia_x: {
2148             // Format(instr, "'memop'cond'sign'h 'rd, ['rn], #+'off8");
2149             DCHECK(!instr->HasW());
2150             addr = rn_val;
2151             rn_val += imm_val;
2152             set_register(rn, rn_val);
2153             break;
2154           }
2155           case db_x: {
2156             // Format(instr, "'memop'cond'sign'h 'rd, ['rn, #-'off8]'w");
2157             rn_val -= imm_val;
2158             addr = rn_val;
2159             if (instr->HasW()) {
2160               set_register(rn, rn_val);
2161             }
2162             break;
2163           }
2164           case ib_x: {
2165             // Format(instr, "'memop'cond'sign'h 'rd, ['rn, #+'off8]'w");
2166             rn_val += imm_val;
2167             addr = rn_val;
2168             if (instr->HasW()) {
2169               set_register(rn, rn_val);
2170             }
2171             break;
2172           }
2173           default: {
2174             // The PU field is a 2-bit field.
2175             UNREACHABLE();
2176             break;
2177           }
2178         }
2179       }
2180       if (((instr->Bits(7, 4) & 0xd) == 0xd) && (instr->Bit(20) == 0)) {
2181         DCHECK((rd % 2) == 0);
2182         if (instr->HasH()) {
2183           // The strd instruction.
2184           int32_t value1 = get_register(rd);
2185           int32_t value2 = get_register(rd+1);
2186           WriteDW(addr, value1, value2);
2187         } else {
2188           // The ldrd instruction.
2189           int* rn_data = ReadDW(addr);
2190           set_dw_register(rd, rn_data);
2191         }
2192       } else if (instr->HasH()) {
2193         if (instr->HasSign()) {
2194           if (instr->HasL()) {
2195             int16_t val = ReadH(addr, instr);
2196             set_register(rd, val);
2197           } else {
2198             int16_t val = get_register(rd);
2199             WriteH(addr, val, instr);
2200           }
2201         } else {
2202           if (instr->HasL()) {
2203             uint16_t val = ReadHU(addr, instr);
2204             set_register(rd, val);
2205           } else {
2206             uint16_t val = get_register(rd);
2207             WriteH(addr, val, instr);
2208           }
2209         }
2210       } else {
2211         // signed byte loads
2212         DCHECK(instr->HasSign());
2213         DCHECK(instr->HasL());
2214         int8_t val = ReadB(addr);
2215         set_register(rd, val);
2216       }
2217       return;
2218     }
2219   } else if ((type == 0) && instr->IsMiscType0()) {
2220     if (instr->Bits(22, 21) == 1) {
2221       int rm = instr->RmValue();
2222       switch (instr->BitField(7, 4)) {
2223         case BX:
2224           set_pc(get_register(rm));
2225           break;
2226         case BLX: {
2227           uint32_t old_pc = get_pc();
2228           set_pc(get_register(rm));
2229           set_register(lr, old_pc + Instruction::kInstrSize);
2230           break;
2231         }
2232         case BKPT: {
2233           ArmDebugger dbg(this);
2234           PrintF("Simulator hit BKPT.\n");
2235           dbg.Debug();
2236           break;
2237         }
2238         default:
2239           UNIMPLEMENTED();
2240       }
2241     } else if (instr->Bits(22, 21) == 3) {
2242       int rm = instr->RmValue();
2243       int rd = instr->RdValue();
2244       switch (instr->BitField(7, 4)) {
2245         case CLZ: {
2246           uint32_t bits = get_register(rm);
2247           int leading_zeros = 0;
2248           if (bits == 0) {
2249             leading_zeros = 32;
2250           } else {
2251             while ((bits & 0x80000000u) == 0) {
2252               bits <<= 1;
2253               leading_zeros++;
2254             }
2255           }
2256           set_register(rd, leading_zeros);
2257           break;
2258         }
2259         default:
2260           UNIMPLEMENTED();
2261       }
2262     } else {
2263       PrintF("%08x\n", instr->InstructionBits());
2264       UNIMPLEMENTED();
2265     }
2266   } else if ((type == 1) && instr->IsNopType1()) {
2267     // NOP.
2268   } else {
2269     int rd = instr->RdValue();
2270     int rn = instr->RnValue();
2271     int32_t rn_val = get_register(rn);
2272     int32_t shifter_operand = 0;
2273     bool shifter_carry_out = 0;
2274     if (type == 0) {
2275       shifter_operand = GetShiftRm(instr, &shifter_carry_out);
2276     } else {
2277       DCHECK(instr->TypeValue() == 1);
2278       shifter_operand = GetImm(instr, &shifter_carry_out);
2279     }
2280     int32_t alu_out;
2281
2282     switch (instr->OpcodeField()) {
2283       case AND: {
2284         // Format(instr, "and'cond's 'rd, 'rn, 'shift_rm");
2285         // Format(instr, "and'cond's 'rd, 'rn, 'imm");
2286         alu_out = rn_val & shifter_operand;
2287         set_register(rd, alu_out);
2288         if (instr->HasS()) {
2289           SetNZFlags(alu_out);
2290           SetCFlag(shifter_carry_out);
2291         }
2292         break;
2293       }
2294
2295       case EOR: {
2296         // Format(instr, "eor'cond's 'rd, 'rn, 'shift_rm");
2297         // Format(instr, "eor'cond's 'rd, 'rn, 'imm");
2298         alu_out = rn_val ^ shifter_operand;
2299         set_register(rd, alu_out);
2300         if (instr->HasS()) {
2301           SetNZFlags(alu_out);
2302           SetCFlag(shifter_carry_out);
2303         }
2304         break;
2305       }
2306
2307       case SUB: {
2308         // Format(instr, "sub'cond's 'rd, 'rn, 'shift_rm");
2309         // Format(instr, "sub'cond's 'rd, 'rn, 'imm");
2310         alu_out = rn_val - shifter_operand;
2311         set_register(rd, alu_out);
2312         if (instr->HasS()) {
2313           SetNZFlags(alu_out);
2314           SetCFlag(!BorrowFrom(rn_val, shifter_operand));
2315           SetVFlag(OverflowFrom(alu_out, rn_val, shifter_operand, false));
2316         }
2317         break;
2318       }
2319
2320       case RSB: {
2321         // Format(instr, "rsb'cond's 'rd, 'rn, 'shift_rm");
2322         // Format(instr, "rsb'cond's 'rd, 'rn, 'imm");
2323         alu_out = shifter_operand - rn_val;
2324         set_register(rd, alu_out);
2325         if (instr->HasS()) {
2326           SetNZFlags(alu_out);
2327           SetCFlag(!BorrowFrom(shifter_operand, rn_val));
2328           SetVFlag(OverflowFrom(alu_out, shifter_operand, rn_val, false));
2329         }
2330         break;
2331       }
2332
2333       case ADD: {
2334         // Format(instr, "add'cond's 'rd, 'rn, 'shift_rm");
2335         // Format(instr, "add'cond's 'rd, 'rn, 'imm");
2336         alu_out = rn_val + shifter_operand;
2337         set_register(rd, alu_out);
2338         if (instr->HasS()) {
2339           SetNZFlags(alu_out);
2340           SetCFlag(CarryFrom(rn_val, shifter_operand));
2341           SetVFlag(OverflowFrom(alu_out, rn_val, shifter_operand, true));
2342         }
2343         break;
2344       }
2345
2346       case ADC: {
2347         // Format(instr, "adc'cond's 'rd, 'rn, 'shift_rm");
2348         // Format(instr, "adc'cond's 'rd, 'rn, 'imm");
2349         alu_out = rn_val + shifter_operand + GetCarry();
2350         set_register(rd, alu_out);
2351         if (instr->HasS()) {
2352           SetNZFlags(alu_out);
2353           SetCFlag(CarryFrom(rn_val, shifter_operand, GetCarry()));
2354           SetVFlag(OverflowFrom(alu_out, rn_val, shifter_operand, true));
2355         }
2356         break;
2357       }
2358
2359       case SBC: {
2360         Format(instr, "sbc'cond's 'rd, 'rn, 'shift_rm");
2361         Format(instr, "sbc'cond's 'rd, 'rn, 'imm");
2362         break;
2363       }
2364
2365       case RSC: {
2366         Format(instr, "rsc'cond's 'rd, 'rn, 'shift_rm");
2367         Format(instr, "rsc'cond's 'rd, 'rn, 'imm");
2368         break;
2369       }
2370
2371       case TST: {
2372         if (instr->HasS()) {
2373           // Format(instr, "tst'cond 'rn, 'shift_rm");
2374           // Format(instr, "tst'cond 'rn, 'imm");
2375           alu_out = rn_val & shifter_operand;
2376           SetNZFlags(alu_out);
2377           SetCFlag(shifter_carry_out);
2378         } else {
2379           // Format(instr, "movw'cond 'rd, 'imm").
2380           alu_out = instr->ImmedMovwMovtValue();
2381           set_register(rd, alu_out);
2382         }
2383         break;
2384       }
2385
2386       case TEQ: {
2387         if (instr->HasS()) {
2388           // Format(instr, "teq'cond 'rn, 'shift_rm");
2389           // Format(instr, "teq'cond 'rn, 'imm");
2390           alu_out = rn_val ^ shifter_operand;
2391           SetNZFlags(alu_out);
2392           SetCFlag(shifter_carry_out);
2393         } else {
2394           // Other instructions matching this pattern are handled in the
2395           // miscellaneous instructions part above.
2396           UNREACHABLE();
2397         }
2398         break;
2399       }
2400
2401       case CMP: {
2402         if (instr->HasS()) {
2403           // Format(instr, "cmp'cond 'rn, 'shift_rm");
2404           // Format(instr, "cmp'cond 'rn, 'imm");
2405           alu_out = rn_val - shifter_operand;
2406           SetNZFlags(alu_out);
2407           SetCFlag(!BorrowFrom(rn_val, shifter_operand));
2408           SetVFlag(OverflowFrom(alu_out, rn_val, shifter_operand, false));
2409         } else {
2410           // Format(instr, "movt'cond 'rd, 'imm").
2411           alu_out = (get_register(rd) & 0xffff) |
2412               (instr->ImmedMovwMovtValue() << 16);
2413           set_register(rd, alu_out);
2414         }
2415         break;
2416       }
2417
2418       case CMN: {
2419         if (instr->HasS()) {
2420           // Format(instr, "cmn'cond 'rn, 'shift_rm");
2421           // Format(instr, "cmn'cond 'rn, 'imm");
2422           alu_out = rn_val + shifter_operand;
2423           SetNZFlags(alu_out);
2424           SetCFlag(CarryFrom(rn_val, shifter_operand));
2425           SetVFlag(OverflowFrom(alu_out, rn_val, shifter_operand, true));
2426         } else {
2427           // Other instructions matching this pattern are handled in the
2428           // miscellaneous instructions part above.
2429           UNREACHABLE();
2430         }
2431         break;
2432       }
2433
2434       case ORR: {
2435         // Format(instr, "orr'cond's 'rd, 'rn, 'shift_rm");
2436         // Format(instr, "orr'cond's 'rd, 'rn, 'imm");
2437         alu_out = rn_val | shifter_operand;
2438         set_register(rd, alu_out);
2439         if (instr->HasS()) {
2440           SetNZFlags(alu_out);
2441           SetCFlag(shifter_carry_out);
2442         }
2443         break;
2444       }
2445
2446       case MOV: {
2447         // Format(instr, "mov'cond's 'rd, 'shift_rm");
2448         // Format(instr, "mov'cond's 'rd, 'imm");
2449         alu_out = shifter_operand;
2450         set_register(rd, alu_out);
2451         if (instr->HasS()) {
2452           SetNZFlags(alu_out);
2453           SetCFlag(shifter_carry_out);
2454         }
2455         break;
2456       }
2457
2458       case BIC: {
2459         // Format(instr, "bic'cond's 'rd, 'rn, 'shift_rm");
2460         // Format(instr, "bic'cond's 'rd, 'rn, 'imm");
2461         alu_out = rn_val & ~shifter_operand;
2462         set_register(rd, alu_out);
2463         if (instr->HasS()) {
2464           SetNZFlags(alu_out);
2465           SetCFlag(shifter_carry_out);
2466         }
2467         break;
2468       }
2469
2470       case MVN: {
2471         // Format(instr, "mvn'cond's 'rd, 'shift_rm");
2472         // Format(instr, "mvn'cond's 'rd, 'imm");
2473         alu_out = ~shifter_operand;
2474         set_register(rd, alu_out);
2475         if (instr->HasS()) {
2476           SetNZFlags(alu_out);
2477           SetCFlag(shifter_carry_out);
2478         }
2479         break;
2480       }
2481
2482       default: {
2483         UNREACHABLE();
2484         break;
2485       }
2486     }
2487   }
2488 }
2489
2490
2491 void Simulator::DecodeType2(Instruction* instr) {
2492   int rd = instr->RdValue();
2493   int rn = instr->RnValue();
2494   int32_t rn_val = get_register(rn);
2495   int32_t im_val = instr->Offset12Value();
2496   int32_t addr = 0;
2497   switch (instr->PUField()) {
2498     case da_x: {
2499       // Format(instr, "'memop'cond'b 'rd, ['rn], #-'off12");
2500       DCHECK(!instr->HasW());
2501       addr = rn_val;
2502       rn_val -= im_val;
2503       set_register(rn, rn_val);
2504       break;
2505     }
2506     case ia_x: {
2507       // Format(instr, "'memop'cond'b 'rd, ['rn], #+'off12");
2508       DCHECK(!instr->HasW());
2509       addr = rn_val;
2510       rn_val += im_val;
2511       set_register(rn, rn_val);
2512       break;
2513     }
2514     case db_x: {
2515       // Format(instr, "'memop'cond'b 'rd, ['rn, #-'off12]'w");
2516       rn_val -= im_val;
2517       addr = rn_val;
2518       if (instr->HasW()) {
2519         set_register(rn, rn_val);
2520       }
2521       break;
2522     }
2523     case ib_x: {
2524       // Format(instr, "'memop'cond'b 'rd, ['rn, #+'off12]'w");
2525       rn_val += im_val;
2526       addr = rn_val;
2527       if (instr->HasW()) {
2528         set_register(rn, rn_val);
2529       }
2530       break;
2531     }
2532     default: {
2533       UNREACHABLE();
2534       break;
2535     }
2536   }
2537   if (instr->HasB()) {
2538     if (instr->HasL()) {
2539       byte val = ReadBU(addr);
2540       set_register(rd, val);
2541     } else {
2542       byte val = get_register(rd);
2543       WriteB(addr, val);
2544     }
2545   } else {
2546     if (instr->HasL()) {
2547       set_register(rd, ReadW(addr, instr));
2548     } else {
2549       WriteW(addr, get_register(rd), instr);
2550     }
2551   }
2552 }
2553
2554
2555 void Simulator::DecodeType3(Instruction* instr) {
2556   int rd = instr->RdValue();
2557   int rn = instr->RnValue();
2558   int32_t rn_val = get_register(rn);
2559   bool shifter_carry_out = 0;
2560   int32_t shifter_operand = GetShiftRm(instr, &shifter_carry_out);
2561   int32_t addr = 0;
2562   switch (instr->PUField()) {
2563     case da_x: {
2564       DCHECK(!instr->HasW());
2565       Format(instr, "'memop'cond'b 'rd, ['rn], -'shift_rm");
2566       UNIMPLEMENTED();
2567       break;
2568     }
2569     case ia_x: {
2570       if (instr->Bit(4) == 0) {
2571         // Memop.
2572       } else {
2573         if (instr->Bit(5) == 0) {
2574           switch (instr->Bits(22, 21)) {
2575             case 0:
2576               if (instr->Bit(20) == 0) {
2577                 if (instr->Bit(6) == 0) {
2578                   // Pkhbt.
2579                   uint32_t rn_val = get_register(rn);
2580                   uint32_t rm_val = get_register(instr->RmValue());
2581                   int32_t shift = instr->Bits(11, 7);
2582                   rm_val <<= shift;
2583                   set_register(rd, (rn_val & 0xFFFF) | (rm_val & 0xFFFF0000U));
2584                 } else {
2585                   // Pkhtb.
2586                   uint32_t rn_val = get_register(rn);
2587                   int32_t rm_val = get_register(instr->RmValue());
2588                   int32_t shift = instr->Bits(11, 7);
2589                   if (shift == 0) {
2590                     shift = 32;
2591                   }
2592                   rm_val >>= shift;
2593                   set_register(rd, (rn_val & 0xFFFF0000U) | (rm_val & 0xFFFF));
2594                 }
2595               } else {
2596                 UNIMPLEMENTED();
2597               }
2598               break;
2599             case 1:
2600               UNIMPLEMENTED();
2601               break;
2602             case 2:
2603               UNIMPLEMENTED();
2604               break;
2605             case 3: {
2606               // Usat.
2607               int32_t sat_pos = instr->Bits(20, 16);
2608               int32_t sat_val = (1 << sat_pos) - 1;
2609               int32_t shift = instr->Bits(11, 7);
2610               int32_t shift_type = instr->Bit(6);
2611               int32_t rm_val = get_register(instr->RmValue());
2612               if (shift_type == 0) {  // LSL
2613                 rm_val <<= shift;
2614               } else {  // ASR
2615                 rm_val >>= shift;
2616               }
2617               // If saturation occurs, the Q flag should be set in the CPSR.
2618               // There is no Q flag yet, and no instruction (MRS) to read the
2619               // CPSR directly.
2620               if (rm_val > sat_val) {
2621                 rm_val = sat_val;
2622               } else if (rm_val < 0) {
2623                 rm_val = 0;
2624               }
2625               set_register(rd, rm_val);
2626               break;
2627             }
2628           }
2629         } else {
2630           switch (instr->Bits(22, 21)) {
2631             case 0:
2632               UNIMPLEMENTED();
2633               break;
2634             case 1:
2635               if (instr->Bits(9, 6) == 1) {
2636                 if (instr->Bit(20) == 0) {
2637                   if (instr->Bits(19, 16) == 0xF) {
2638                     // Sxtb.
2639                     int32_t rm_val = get_register(instr->RmValue());
2640                     int32_t rotate = instr->Bits(11, 10);
2641                     switch (rotate) {
2642                       case 0:
2643                         break;
2644                       case 1:
2645                         rm_val = (rm_val >> 8) | (rm_val << 24);
2646                         break;
2647                       case 2:
2648                         rm_val = (rm_val >> 16) | (rm_val << 16);
2649                         break;
2650                       case 3:
2651                         rm_val = (rm_val >> 24) | (rm_val << 8);
2652                         break;
2653                     }
2654                     set_register(rd, static_cast<int8_t>(rm_val));
2655                   } else {
2656                     // Sxtab.
2657                     int32_t rn_val = get_register(rn);
2658                     int32_t rm_val = get_register(instr->RmValue());
2659                     int32_t rotate = instr->Bits(11, 10);
2660                     switch (rotate) {
2661                       case 0:
2662                         break;
2663                       case 1:
2664                         rm_val = (rm_val >> 8) | (rm_val << 24);
2665                         break;
2666                       case 2:
2667                         rm_val = (rm_val >> 16) | (rm_val << 16);
2668                         break;
2669                       case 3:
2670                         rm_val = (rm_val >> 24) | (rm_val << 8);
2671                         break;
2672                     }
2673                     set_register(rd, rn_val + static_cast<int8_t>(rm_val));
2674                   }
2675                 } else {
2676                   if (instr->Bits(19, 16) == 0xF) {
2677                     // Sxth.
2678                     int32_t rm_val = get_register(instr->RmValue());
2679                     int32_t rotate = instr->Bits(11, 10);
2680                     switch (rotate) {
2681                       case 0:
2682                         break;
2683                       case 1:
2684                         rm_val = (rm_val >> 8) | (rm_val << 24);
2685                         break;
2686                       case 2:
2687                         rm_val = (rm_val >> 16) | (rm_val << 16);
2688                         break;
2689                       case 3:
2690                         rm_val = (rm_val >> 24) | (rm_val << 8);
2691                         break;
2692                     }
2693                     set_register(rd, static_cast<int16_t>(rm_val));
2694                   } else {
2695                     // Sxtah.
2696                     int32_t rn_val = get_register(rn);
2697                     int32_t rm_val = get_register(instr->RmValue());
2698                     int32_t rotate = instr->Bits(11, 10);
2699                     switch (rotate) {
2700                       case 0:
2701                         break;
2702                       case 1:
2703                         rm_val = (rm_val >> 8) | (rm_val << 24);
2704                         break;
2705                       case 2:
2706                         rm_val = (rm_val >> 16) | (rm_val << 16);
2707                         break;
2708                       case 3:
2709                         rm_val = (rm_val >> 24) | (rm_val << 8);
2710                         break;
2711                     }
2712                     set_register(rd, rn_val + static_cast<int16_t>(rm_val));
2713                   }
2714                 }
2715               } else {
2716                 UNREACHABLE();
2717               }
2718               break;
2719             case 2:
2720               if ((instr->Bit(20) == 0) && (instr->Bits(9, 6) == 1)) {
2721                 if (instr->Bits(19, 16) == 0xF) {
2722                   // Uxtb16.
2723                   uint32_t rm_val = get_register(instr->RmValue());
2724                   int32_t rotate = instr->Bits(11, 10);
2725                   switch (rotate) {
2726                     case 0:
2727                       break;
2728                     case 1:
2729                       rm_val = (rm_val >> 8) | (rm_val << 24);
2730                       break;
2731                     case 2:
2732                       rm_val = (rm_val >> 16) | (rm_val << 16);
2733                       break;
2734                     case 3:
2735                       rm_val = (rm_val >> 24) | (rm_val << 8);
2736                       break;
2737                   }
2738                   set_register(rd, (rm_val & 0xFF) | (rm_val & 0xFF0000));
2739                 } else {
2740                   UNIMPLEMENTED();
2741                 }
2742               } else {
2743                 UNIMPLEMENTED();
2744               }
2745               break;
2746             case 3:
2747               if ((instr->Bits(9, 6) == 1)) {
2748                 if (instr->Bit(20) == 0) {
2749                   if (instr->Bits(19, 16) == 0xF) {
2750                     // Uxtb.
2751                     uint32_t rm_val = get_register(instr->RmValue());
2752                     int32_t rotate = instr->Bits(11, 10);
2753                     switch (rotate) {
2754                       case 0:
2755                         break;
2756                       case 1:
2757                         rm_val = (rm_val >> 8) | (rm_val << 24);
2758                         break;
2759                       case 2:
2760                         rm_val = (rm_val >> 16) | (rm_val << 16);
2761                         break;
2762                       case 3:
2763                         rm_val = (rm_val >> 24) | (rm_val << 8);
2764                         break;
2765                     }
2766                     set_register(rd, (rm_val & 0xFF));
2767                   } else {
2768                     // Uxtab.
2769                     uint32_t rn_val = get_register(rn);
2770                     uint32_t rm_val = get_register(instr->RmValue());
2771                     int32_t rotate = instr->Bits(11, 10);
2772                     switch (rotate) {
2773                       case 0:
2774                         break;
2775                       case 1:
2776                         rm_val = (rm_val >> 8) | (rm_val << 24);
2777                         break;
2778                       case 2:
2779                         rm_val = (rm_val >> 16) | (rm_val << 16);
2780                         break;
2781                       case 3:
2782                         rm_val = (rm_val >> 24) | (rm_val << 8);
2783                         break;
2784                     }
2785                     set_register(rd, rn_val + (rm_val & 0xFF));
2786                   }
2787                 } else {
2788                   if (instr->Bits(19, 16) == 0xF) {
2789                     // Uxth.
2790                     uint32_t rm_val = get_register(instr->RmValue());
2791                     int32_t rotate = instr->Bits(11, 10);
2792                     switch (rotate) {
2793                       case 0:
2794                         break;
2795                       case 1:
2796                         rm_val = (rm_val >> 8) | (rm_val << 24);
2797                         break;
2798                       case 2:
2799                         rm_val = (rm_val >> 16) | (rm_val << 16);
2800                         break;
2801                       case 3:
2802                         rm_val = (rm_val >> 24) | (rm_val << 8);
2803                         break;
2804                     }
2805                     set_register(rd, (rm_val & 0xFFFF));
2806                   } else {
2807                     // Uxtah.
2808                     uint32_t rn_val = get_register(rn);
2809                     uint32_t rm_val = get_register(instr->RmValue());
2810                     int32_t rotate = instr->Bits(11, 10);
2811                     switch (rotate) {
2812                       case 0:
2813                         break;
2814                       case 1:
2815                         rm_val = (rm_val >> 8) | (rm_val << 24);
2816                         break;
2817                       case 2:
2818                         rm_val = (rm_val >> 16) | (rm_val << 16);
2819                         break;
2820                       case 3:
2821                         rm_val = (rm_val >> 24) | (rm_val << 8);
2822                         break;
2823                     }
2824                     set_register(rd, rn_val + (rm_val & 0xFFFF));
2825                   }
2826                 }
2827               } else {
2828                 UNIMPLEMENTED();
2829               }
2830               break;
2831           }
2832         }
2833         return;
2834       }
2835       break;
2836     }
2837     case db_x: {
2838       if (instr->Bits(22, 20) == 0x5) {
2839         if (instr->Bits(7, 4) == 0x1) {
2840           int rm = instr->RmValue();
2841           int32_t rm_val = get_register(rm);
2842           int rs = instr->RsValue();
2843           int32_t rs_val = get_register(rs);
2844           if (instr->Bits(15, 12) == 0xF) {
2845             // SMMUL (in V8 notation matching ARM ISA format)
2846             // Format(instr, "smmul'cond 'rn, 'rm, 'rs");
2847             rn_val = base::bits::SignedMulHigh32(rm_val, rs_val);
2848           } else {
2849             // SMMLA (in V8 notation matching ARM ISA format)
2850             // Format(instr, "smmla'cond 'rn, 'rm, 'rs, 'rd");
2851             int rd = instr->RdValue();
2852             int32_t rd_val = get_register(rd);
2853             rn_val = base::bits::SignedMulHighAndAdd32(rm_val, rs_val, rd_val);
2854           }
2855           set_register(rn, rn_val);
2856           return;
2857         }
2858       }
2859       if (FLAG_enable_sudiv) {
2860         if (instr->Bits(5, 4) == 0x1) {
2861           if ((instr->Bit(22) == 0x0) && (instr->Bit(20) == 0x1)) {
2862             // (s/u)div (in V8 notation matching ARM ISA format) rn = rm/rs
2863             // Format(instr, "'(s/u)div'cond'b 'rn, 'rm, 'rs);
2864             int rm = instr->RmValue();
2865             int32_t rm_val = get_register(rm);
2866             int rs = instr->RsValue();
2867             int32_t rs_val = get_register(rs);
2868             int32_t ret_val = 0;
2869             // udiv
2870             if (instr->Bit(21) == 0x1) {
2871               ret_val = bit_cast<int32_t>(base::bits::UnsignedDiv32(
2872                   bit_cast<uint32_t>(rm_val), bit_cast<uint32_t>(rs_val)));
2873             } else {
2874               ret_val = base::bits::SignedDiv32(rm_val, rs_val);
2875             }
2876             set_register(rn, ret_val);
2877             return;
2878           }
2879         }
2880       }
2881       // Format(instr, "'memop'cond'b 'rd, ['rn, -'shift_rm]'w");
2882       addr = rn_val - shifter_operand;
2883       if (instr->HasW()) {
2884         set_register(rn, addr);
2885       }
2886       break;
2887     }
2888     case ib_x: {
2889       if (instr->HasW() && (instr->Bits(6, 4) == 0x5)) {
2890         uint32_t widthminus1 = static_cast<uint32_t>(instr->Bits(20, 16));
2891         uint32_t lsbit = static_cast<uint32_t>(instr->Bits(11, 7));
2892         uint32_t msbit = widthminus1 + lsbit;
2893         if (msbit <= 31) {
2894           if (instr->Bit(22)) {
2895             // ubfx - unsigned bitfield extract.
2896             uint32_t rm_val =
2897                 static_cast<uint32_t>(get_register(instr->RmValue()));
2898             uint32_t extr_val = rm_val << (31 - msbit);
2899             extr_val = extr_val >> (31 - widthminus1);
2900             set_register(instr->RdValue(), extr_val);
2901           } else {
2902             // sbfx - signed bitfield extract.
2903             int32_t rm_val = get_register(instr->RmValue());
2904             int32_t extr_val = rm_val << (31 - msbit);
2905             extr_val = extr_val >> (31 - widthminus1);
2906             set_register(instr->RdValue(), extr_val);
2907           }
2908         } else {
2909           UNREACHABLE();
2910         }
2911         return;
2912       } else if (!instr->HasW() && (instr->Bits(6, 4) == 0x1)) {
2913         uint32_t lsbit = static_cast<uint32_t>(instr->Bits(11, 7));
2914         uint32_t msbit = static_cast<uint32_t>(instr->Bits(20, 16));
2915         if (msbit >= lsbit) {
2916           // bfc or bfi - bitfield clear/insert.
2917           uint32_t rd_val =
2918               static_cast<uint32_t>(get_register(instr->RdValue()));
2919           uint32_t bitcount = msbit - lsbit + 1;
2920           uint32_t mask = 0xffffffffu >> (32 - bitcount);
2921           rd_val &= ~(mask << lsbit);
2922           if (instr->RmValue() != 15) {
2923             // bfi - bitfield insert.
2924             uint32_t rm_val =
2925                 static_cast<uint32_t>(get_register(instr->RmValue()));
2926             rm_val &= mask;
2927             rd_val |= rm_val << lsbit;
2928           }
2929           set_register(instr->RdValue(), rd_val);
2930         } else {
2931           UNREACHABLE();
2932         }
2933         return;
2934       } else {
2935         // Format(instr, "'memop'cond'b 'rd, ['rn, +'shift_rm]'w");
2936         addr = rn_val + shifter_operand;
2937         if (instr->HasW()) {
2938           set_register(rn, addr);
2939         }
2940       }
2941       break;
2942     }
2943     default: {
2944       UNREACHABLE();
2945       break;
2946     }
2947   }
2948   if (instr->HasB()) {
2949     if (instr->HasL()) {
2950       uint8_t byte = ReadB(addr);
2951       set_register(rd, byte);
2952     } else {
2953       uint8_t byte = get_register(rd);
2954       WriteB(addr, byte);
2955     }
2956   } else {
2957     if (instr->HasL()) {
2958       set_register(rd, ReadW(addr, instr));
2959     } else {
2960       WriteW(addr, get_register(rd), instr);
2961     }
2962   }
2963 }
2964
2965
2966 void Simulator::DecodeType4(Instruction* instr) {
2967   DCHECK(instr->Bit(22) == 0);  // only allowed to be set in privileged mode
2968   if (instr->HasL()) {
2969     // Format(instr, "ldm'cond'pu 'rn'w, 'rlist");
2970     HandleRList(instr, true);
2971   } else {
2972     // Format(instr, "stm'cond'pu 'rn'w, 'rlist");
2973     HandleRList(instr, false);
2974   }
2975 }
2976
2977
2978 void Simulator::DecodeType5(Instruction* instr) {
2979   // Format(instr, "b'l'cond 'target");
2980   int off = (instr->SImmed24Value() << 2);
2981   intptr_t pc_address = get_pc();
2982   if (instr->HasLink()) {
2983     set_register(lr, pc_address + Instruction::kInstrSize);
2984   }
2985   int pc_reg = get_register(pc);
2986   set_pc(pc_reg + off);
2987 }
2988
2989
2990 void Simulator::DecodeType6(Instruction* instr) {
2991   DecodeType6CoprocessorIns(instr);
2992 }
2993
2994
2995 void Simulator::DecodeType7(Instruction* instr) {
2996   if (instr->Bit(24) == 1) {
2997     SoftwareInterrupt(instr);
2998   } else {
2999     DecodeTypeVFP(instr);
3000   }
3001 }
3002
3003
3004 // void Simulator::DecodeTypeVFP(Instruction* instr)
3005 // The Following ARMv7 VFPv instructions are currently supported.
3006 // vmov :Sn = Rt
3007 // vmov :Rt = Sn
3008 // vcvt: Dd = Sm
3009 // vcvt: Sd = Dm
3010 // vcvt.f64.s32 Dd, Dd, #<fbits>
3011 // Dd = vabs(Dm)
3012 // Dd = vneg(Dm)
3013 // Dd = vadd(Dn, Dm)
3014 // Dd = vsub(Dn, Dm)
3015 // Dd = vmul(Dn, Dm)
3016 // Dd = vdiv(Dn, Dm)
3017 // vcmp(Dd, Dm)
3018 // vmrs
3019 // Dd = vsqrt(Dm)
3020 void Simulator::DecodeTypeVFP(Instruction* instr) {
3021   DCHECK((instr->TypeValue() == 7) && (instr->Bit(24) == 0x0) );
3022   DCHECK(instr->Bits(11, 9) == 0x5);
3023
3024   // Obtain double precision register codes.
3025   int vm = instr->VFPMRegValue(kDoublePrecision);
3026   int vd = instr->VFPDRegValue(kDoublePrecision);
3027   int vn = instr->VFPNRegValue(kDoublePrecision);
3028
3029   if (instr->Bit(4) == 0) {
3030     if (instr->Opc1Value() == 0x7) {
3031       // Other data processing instructions
3032       if ((instr->Opc2Value() == 0x0) && (instr->Opc3Value() == 0x1)) {
3033         // vmov register to register.
3034         if (instr->SzValue() == 0x1) {
3035           int m = instr->VFPMRegValue(kDoublePrecision);
3036           int d = instr->VFPDRegValue(kDoublePrecision);
3037           uint32_t data[2];
3038           get_d_register(m, data);
3039           set_d_register(d, data);
3040         } else {
3041           int m = instr->VFPMRegValue(kSinglePrecision);
3042           int d = instr->VFPDRegValue(kSinglePrecision);
3043           set_s_register_from_float(d, get_float_from_s_register(m));
3044         }
3045       } else if ((instr->Opc2Value() == 0x0) && (instr->Opc3Value() == 0x3)) {
3046         // vabs
3047         double dm_value = get_double_from_d_register(vm);
3048         double dd_value = std::fabs(dm_value);
3049         dd_value = canonicalizeNaN(dd_value);
3050         set_d_register_from_double(vd, dd_value);
3051       } else if ((instr->Opc2Value() == 0x1) && (instr->Opc3Value() == 0x1)) {
3052         // vneg
3053         double dm_value = get_double_from_d_register(vm);
3054         double dd_value = -dm_value;
3055         dd_value = canonicalizeNaN(dd_value);
3056         set_d_register_from_double(vd, dd_value);
3057       } else if ((instr->Opc2Value() == 0x7) && (instr->Opc3Value() == 0x3)) {
3058         DecodeVCVTBetweenDoubleAndSingle(instr);
3059       } else if ((instr->Opc2Value() == 0x8) && (instr->Opc3Value() & 0x1)) {
3060         DecodeVCVTBetweenFloatingPointAndInteger(instr);
3061       } else if ((instr->Opc2Value() == 0xA) && (instr->Opc3Value() == 0x3) &&
3062                  (instr->Bit(8) == 1)) {
3063         // vcvt.f64.s32 Dd, Dd, #<fbits>
3064         int fraction_bits = 32 - ((instr->Bits(3, 0) << 1) | instr->Bit(5));
3065         int fixed_value = get_sinteger_from_s_register(vd * 2);
3066         double divide = 1 << fraction_bits;
3067         set_d_register_from_double(vd, fixed_value / divide);
3068       } else if (((instr->Opc2Value() >> 1) == 0x6) &&
3069                  (instr->Opc3Value() & 0x1)) {
3070         DecodeVCVTBetweenFloatingPointAndInteger(instr);
3071       } else if (((instr->Opc2Value() == 0x4) || (instr->Opc2Value() == 0x5)) &&
3072                  (instr->Opc3Value() & 0x1)) {
3073         DecodeVCMP(instr);
3074       } else if (((instr->Opc2Value() == 0x1)) && (instr->Opc3Value() == 0x3)) {
3075         // vsqrt
3076         double dm_value = get_double_from_d_register(vm);
3077         double dd_value = fast_sqrt(dm_value);
3078         dd_value = canonicalizeNaN(dd_value);
3079         set_d_register_from_double(vd, dd_value);
3080       } else if (instr->Opc3Value() == 0x0) {
3081         // vmov immediate.
3082         if (instr->SzValue() == 0x1) {
3083           set_d_register_from_double(vd, instr->DoubleImmedVmov());
3084         } else {
3085           UNREACHABLE();  // Not used by v8.
3086         }
3087       } else if (((instr->Opc2Value() == 0x6)) && (instr->Opc3Value() == 0x3)) {
3088         // vrintz - truncate
3089         double dm_value = get_double_from_d_register(vm);
3090         double dd_value = trunc(dm_value);
3091         dd_value = canonicalizeNaN(dd_value);
3092         set_d_register_from_double(vd, dd_value);
3093       } else {
3094         UNREACHABLE();  // Not used by V8.
3095       }
3096     } else if (instr->Opc1Value() == 0x3) {
3097       if (instr->SzValue() != 0x1) {
3098         UNREACHABLE();  // Not used by V8.
3099       }
3100
3101       if (instr->Opc3Value() & 0x1) {
3102         // vsub
3103         double dn_value = get_double_from_d_register(vn);
3104         double dm_value = get_double_from_d_register(vm);
3105         double dd_value = dn_value - dm_value;
3106         dd_value = canonicalizeNaN(dd_value);
3107         set_d_register_from_double(vd, dd_value);
3108       } else {
3109         // vadd
3110         double dn_value = get_double_from_d_register(vn);
3111         double dm_value = get_double_from_d_register(vm);
3112         double dd_value = dn_value + dm_value;
3113         dd_value = canonicalizeNaN(dd_value);
3114         set_d_register_from_double(vd, dd_value);
3115       }
3116     } else if ((instr->Opc1Value() == 0x2) && !(instr->Opc3Value() & 0x1)) {
3117       // vmul
3118       if (instr->SzValue() != 0x1) {
3119         UNREACHABLE();  // Not used by V8.
3120       }
3121
3122       double dn_value = get_double_from_d_register(vn);
3123       double dm_value = get_double_from_d_register(vm);
3124       double dd_value = dn_value * dm_value;
3125       dd_value = canonicalizeNaN(dd_value);
3126       set_d_register_from_double(vd, dd_value);
3127     } else if ((instr->Opc1Value() == 0x0)) {
3128       // vmla, vmls
3129       const bool is_vmls = (instr->Opc3Value() & 0x1);
3130
3131       if (instr->SzValue() != 0x1) {
3132         UNREACHABLE();  // Not used by V8.
3133       }
3134
3135       const double dd_val = get_double_from_d_register(vd);
3136       const double dn_val = get_double_from_d_register(vn);
3137       const double dm_val = get_double_from_d_register(vm);
3138
3139       // Note: we do the mul and add/sub in separate steps to avoid getting a
3140       // result with too high precision.
3141       set_d_register_from_double(vd, dn_val * dm_val);
3142       if (is_vmls) {
3143         set_d_register_from_double(
3144           vd,
3145           canonicalizeNaN(dd_val - get_double_from_d_register(vd)));
3146       } else {
3147         set_d_register_from_double(
3148           vd,
3149           canonicalizeNaN(dd_val + get_double_from_d_register(vd)));
3150       }
3151     } else if ((instr->Opc1Value() == 0x4) && !(instr->Opc3Value() & 0x1)) {
3152       // vdiv
3153       if (instr->SzValue() != 0x1) {
3154         UNREACHABLE();  // Not used by V8.
3155       }
3156
3157       double dn_value = get_double_from_d_register(vn);
3158       double dm_value = get_double_from_d_register(vm);
3159       double dd_value = dn_value / dm_value;
3160       div_zero_vfp_flag_ = (dm_value == 0);
3161       dd_value = canonicalizeNaN(dd_value);
3162       set_d_register_from_double(vd, dd_value);
3163     } else {
3164       UNIMPLEMENTED();  // Not used by V8.
3165     }
3166   } else {
3167     if ((instr->VCValue() == 0x0) &&
3168         (instr->VAValue() == 0x0)) {
3169       DecodeVMOVBetweenCoreAndSinglePrecisionRegisters(instr);
3170     } else if ((instr->VLValue() == 0x0) &&
3171                (instr->VCValue() == 0x1) &&
3172                (instr->Bit(23) == 0x0)) {
3173       // vmov (ARM core register to scalar)
3174       int vd = instr->Bits(19, 16) | (instr->Bit(7) << 4);
3175       uint32_t data[2];
3176       get_d_register(vd, data);
3177       data[instr->Bit(21)] = get_register(instr->RtValue());
3178       set_d_register(vd, data);
3179     } else if ((instr->VLValue() == 0x1) &&
3180                (instr->VCValue() == 0x1) &&
3181                (instr->Bit(23) == 0x0)) {
3182       // vmov (scalar to ARM core register)
3183       int vn = instr->Bits(19, 16) | (instr->Bit(7) << 4);
3184       double dn_value = get_double_from_d_register(vn);
3185       int32_t data[2];
3186       memcpy(data, &dn_value, 8);
3187       set_register(instr->RtValue(), data[instr->Bit(21)]);
3188     } else if ((instr->VLValue() == 0x1) &&
3189                (instr->VCValue() == 0x0) &&
3190                (instr->VAValue() == 0x7) &&
3191                (instr->Bits(19, 16) == 0x1)) {
3192       // vmrs
3193       uint32_t rt = instr->RtValue();
3194       if (rt == 0xF) {
3195         Copy_FPSCR_to_APSR();
3196       } else {
3197         // Emulate FPSCR from the Simulator flags.
3198         uint32_t fpscr = (n_flag_FPSCR_ << 31) |
3199                          (z_flag_FPSCR_ << 30) |
3200                          (c_flag_FPSCR_ << 29) |
3201                          (v_flag_FPSCR_ << 28) |
3202                          (FPSCR_default_NaN_mode_ << 25) |
3203                          (inexact_vfp_flag_ << 4) |
3204                          (underflow_vfp_flag_ << 3) |
3205                          (overflow_vfp_flag_ << 2) |
3206                          (div_zero_vfp_flag_ << 1) |
3207                          (inv_op_vfp_flag_ << 0) |
3208                          (FPSCR_rounding_mode_);
3209         set_register(rt, fpscr);
3210       }
3211     } else if ((instr->VLValue() == 0x0) &&
3212                (instr->VCValue() == 0x0) &&
3213                (instr->VAValue() == 0x7) &&
3214                (instr->Bits(19, 16) == 0x1)) {
3215       // vmsr
3216       uint32_t rt = instr->RtValue();
3217       if (rt == pc) {
3218         UNREACHABLE();
3219       } else {
3220         uint32_t rt_value = get_register(rt);
3221         n_flag_FPSCR_ = (rt_value >> 31) & 1;
3222         z_flag_FPSCR_ = (rt_value >> 30) & 1;
3223         c_flag_FPSCR_ = (rt_value >> 29) & 1;
3224         v_flag_FPSCR_ = (rt_value >> 28) & 1;
3225         FPSCR_default_NaN_mode_ = (rt_value >> 25) & 1;
3226         inexact_vfp_flag_ = (rt_value >> 4) & 1;
3227         underflow_vfp_flag_ = (rt_value >> 3) & 1;
3228         overflow_vfp_flag_ = (rt_value >> 2) & 1;
3229         div_zero_vfp_flag_ = (rt_value >> 1) & 1;
3230         inv_op_vfp_flag_ = (rt_value >> 0) & 1;
3231         FPSCR_rounding_mode_ =
3232             static_cast<VFPRoundingMode>((rt_value) & kVFPRoundingModeMask);
3233       }
3234     } else {
3235       UNIMPLEMENTED();  // Not used by V8.
3236     }
3237   }
3238 }
3239
3240
3241 void Simulator::DecodeVMOVBetweenCoreAndSinglePrecisionRegisters(
3242     Instruction* instr) {
3243   DCHECK((instr->Bit(4) == 1) && (instr->VCValue() == 0x0) &&
3244          (instr->VAValue() == 0x0));
3245
3246   int t = instr->RtValue();
3247   int n = instr->VFPNRegValue(kSinglePrecision);
3248   bool to_arm_register = (instr->VLValue() == 0x1);
3249
3250   if (to_arm_register) {
3251     int32_t int_value = get_sinteger_from_s_register(n);
3252     set_register(t, int_value);
3253   } else {
3254     int32_t rs_val = get_register(t);
3255     set_s_register_from_sinteger(n, rs_val);
3256   }
3257 }
3258
3259
3260 void Simulator::DecodeVCMP(Instruction* instr) {
3261   DCHECK((instr->Bit(4) == 0) && (instr->Opc1Value() == 0x7));
3262   DCHECK(((instr->Opc2Value() == 0x4) || (instr->Opc2Value() == 0x5)) &&
3263          (instr->Opc3Value() & 0x1));
3264   // Comparison.
3265
3266   VFPRegPrecision precision = kSinglePrecision;
3267   if (instr->SzValue() == 1) {
3268     precision = kDoublePrecision;
3269   }
3270
3271   int d = instr->VFPDRegValue(precision);
3272   int m = 0;
3273   if (instr->Opc2Value() == 0x4) {
3274     m = instr->VFPMRegValue(precision);
3275   }
3276
3277   if (precision == kDoublePrecision) {
3278     double dd_value = get_double_from_d_register(d);
3279     double dm_value = 0.0;
3280     if (instr->Opc2Value() == 0x4) {
3281       dm_value = get_double_from_d_register(m);
3282     }
3283
3284     // Raise exceptions for quiet NaNs if necessary.
3285     if (instr->Bit(7) == 1) {
3286       if (std::isnan(dd_value)) {
3287         inv_op_vfp_flag_ = true;
3288       }
3289     }
3290
3291     Compute_FPSCR_Flags(dd_value, dm_value);
3292   } else {
3293     UNIMPLEMENTED();  // Not used by V8.
3294   }
3295 }
3296
3297
3298 void Simulator::DecodeVCVTBetweenDoubleAndSingle(Instruction* instr) {
3299   DCHECK((instr->Bit(4) == 0) && (instr->Opc1Value() == 0x7));
3300   DCHECK((instr->Opc2Value() == 0x7) && (instr->Opc3Value() == 0x3));
3301
3302   VFPRegPrecision dst_precision = kDoublePrecision;
3303   VFPRegPrecision src_precision = kSinglePrecision;
3304   if (instr->SzValue() == 1) {
3305     dst_precision = kSinglePrecision;
3306     src_precision = kDoublePrecision;
3307   }
3308
3309   int dst = instr->VFPDRegValue(dst_precision);
3310   int src = instr->VFPMRegValue(src_precision);
3311
3312   if (dst_precision == kSinglePrecision) {
3313     double val = get_double_from_d_register(src);
3314     set_s_register_from_float(dst, static_cast<float>(val));
3315   } else {
3316     float val = get_float_from_s_register(src);
3317     set_d_register_from_double(dst, static_cast<double>(val));
3318   }
3319 }
3320
3321 bool get_inv_op_vfp_flag(VFPRoundingMode mode,
3322                          double val,
3323                          bool unsigned_) {
3324   DCHECK((mode == RN) || (mode == RM) || (mode == RZ));
3325   double max_uint = static_cast<double>(0xffffffffu);
3326   double max_int = static_cast<double>(kMaxInt);
3327   double min_int = static_cast<double>(kMinInt);
3328
3329   // Check for NaN.
3330   if (val != val) {
3331     return true;
3332   }
3333
3334   // Check for overflow. This code works because 32bit integers can be
3335   // exactly represented by ieee-754 64bit floating-point values.
3336   switch (mode) {
3337     case RN:
3338       return  unsigned_ ? (val >= (max_uint + 0.5)) ||
3339                           (val < -0.5)
3340                         : (val >= (max_int + 0.5)) ||
3341                           (val < (min_int - 0.5));
3342
3343     case RM:
3344       return  unsigned_ ? (val >= (max_uint + 1.0)) ||
3345                           (val < 0)
3346                         : (val >= (max_int + 1.0)) ||
3347                           (val < min_int);
3348
3349     case RZ:
3350       return  unsigned_ ? (val >= (max_uint + 1.0)) ||
3351                           (val <= -1)
3352                         : (val >= (max_int + 1.0)) ||
3353                           (val <= (min_int - 1.0));
3354     default:
3355       UNREACHABLE();
3356       return true;
3357   }
3358 }
3359
3360
3361 // We call this function only if we had a vfp invalid exception.
3362 // It returns the correct saturated value.
3363 int VFPConversionSaturate(double val, bool unsigned_res) {
3364   if (val != val) {
3365     return 0;
3366   } else {
3367     if (unsigned_res) {
3368       return (val < 0) ? 0 : 0xffffffffu;
3369     } else {
3370       return (val < 0) ? kMinInt : kMaxInt;
3371     }
3372   }
3373 }
3374
3375
3376 void Simulator::DecodeVCVTBetweenFloatingPointAndInteger(Instruction* instr) {
3377   DCHECK((instr->Bit(4) == 0) && (instr->Opc1Value() == 0x7) &&
3378          (instr->Bits(27, 23) == 0x1D));
3379   DCHECK(((instr->Opc2Value() == 0x8) && (instr->Opc3Value() & 0x1)) ||
3380          (((instr->Opc2Value() >> 1) == 0x6) && (instr->Opc3Value() & 0x1)));
3381
3382   // Conversion between floating-point and integer.
3383   bool to_integer = (instr->Bit(18) == 1);
3384
3385   VFPRegPrecision src_precision = (instr->SzValue() == 1) ? kDoublePrecision
3386                                                           : kSinglePrecision;
3387
3388   if (to_integer) {
3389     // We are playing with code close to the C++ standard's limits below,
3390     // hence the very simple code and heavy checks.
3391     //
3392     // Note:
3393     // C++ defines default type casting from floating point to integer as
3394     // (close to) rounding toward zero ("fractional part discarded").
3395
3396     int dst = instr->VFPDRegValue(kSinglePrecision);
3397     int src = instr->VFPMRegValue(src_precision);
3398
3399     // Bit 7 in vcvt instructions indicates if we should use the FPSCR rounding
3400     // mode or the default Round to Zero mode.
3401     VFPRoundingMode mode = (instr->Bit(7) != 1) ? FPSCR_rounding_mode_
3402                                                 : RZ;
3403     DCHECK((mode == RM) || (mode == RZ) || (mode == RN));
3404
3405     bool unsigned_integer = (instr->Bit(16) == 0);
3406     bool double_precision = (src_precision == kDoublePrecision);
3407
3408     double val = double_precision ? get_double_from_d_register(src)
3409                                   : get_float_from_s_register(src);
3410
3411     int temp = unsigned_integer ? static_cast<uint32_t>(val)
3412                                 : static_cast<int32_t>(val);
3413
3414     inv_op_vfp_flag_ = get_inv_op_vfp_flag(mode, val, unsigned_integer);
3415
3416     double abs_diff =
3417       unsigned_integer ? std::fabs(val - static_cast<uint32_t>(temp))
3418                        : std::fabs(val - temp);
3419
3420     inexact_vfp_flag_ = (abs_diff != 0);
3421
3422     if (inv_op_vfp_flag_) {
3423       temp = VFPConversionSaturate(val, unsigned_integer);
3424     } else {
3425       switch (mode) {
3426         case RN: {
3427           int val_sign = (val > 0) ? 1 : -1;
3428           if (abs_diff > 0.5) {
3429             temp += val_sign;
3430           } else if (abs_diff == 0.5) {
3431             // Round to even if exactly halfway.
3432             temp = ((temp % 2) == 0) ? temp : temp + val_sign;
3433           }
3434           break;
3435         }
3436
3437         case RM:
3438           temp = temp > val ? temp - 1 : temp;
3439           break;
3440
3441         case RZ:
3442           // Nothing to do.
3443           break;
3444
3445         default:
3446           UNREACHABLE();
3447       }
3448     }
3449
3450     // Update the destination register.
3451     set_s_register_from_sinteger(dst, temp);
3452
3453   } else {
3454     bool unsigned_integer = (instr->Bit(7) == 0);
3455
3456     int dst = instr->VFPDRegValue(src_precision);
3457     int src = instr->VFPMRegValue(kSinglePrecision);
3458
3459     int val = get_sinteger_from_s_register(src);
3460
3461     if (src_precision == kDoublePrecision) {
3462       if (unsigned_integer) {
3463         set_d_register_from_double(
3464             dst, static_cast<double>(static_cast<uint32_t>(val)));
3465       } else {
3466         set_d_register_from_double(dst, static_cast<double>(val));
3467       }
3468     } else {
3469       if (unsigned_integer) {
3470         set_s_register_from_float(
3471             dst, static_cast<float>(static_cast<uint32_t>(val)));
3472       } else {
3473         set_s_register_from_float(dst, static_cast<float>(val));
3474       }
3475     }
3476   }
3477 }
3478
3479
3480 // void Simulator::DecodeType6CoprocessorIns(Instruction* instr)
3481 // Decode Type 6 coprocessor instructions.
3482 // Dm = vmov(Rt, Rt2)
3483 // <Rt, Rt2> = vmov(Dm)
3484 // Ddst = MEM(Rbase + 4*offset).
3485 // MEM(Rbase + 4*offset) = Dsrc.
3486 void Simulator::DecodeType6CoprocessorIns(Instruction* instr) {
3487   DCHECK((instr->TypeValue() == 6));
3488
3489   if (instr->CoprocessorValue() == 0xA) {
3490     switch (instr->OpcodeValue()) {
3491       case 0x8:
3492       case 0xA:
3493       case 0xC:
3494       case 0xE: {  // Load and store single precision float to memory.
3495         int rn = instr->RnValue();
3496         int vd = instr->VFPDRegValue(kSinglePrecision);
3497         int offset = instr->Immed8Value();
3498         if (!instr->HasU()) {
3499           offset = -offset;
3500         }
3501
3502         int32_t address = get_register(rn) + 4 * offset;
3503         if (instr->HasL()) {
3504           // Load double from memory: vldr.
3505           set_s_register_from_sinteger(vd, ReadW(address, instr));
3506         } else {
3507           // Store double to memory: vstr.
3508           WriteW(address, get_sinteger_from_s_register(vd), instr);
3509         }
3510         break;
3511       }
3512       case 0x4:
3513       case 0x5:
3514       case 0x6:
3515       case 0x7:
3516       case 0x9:
3517       case 0xB:
3518         // Load/store multiple single from memory: vldm/vstm.
3519         HandleVList(instr);
3520         break;
3521       default:
3522         UNIMPLEMENTED();  // Not used by V8.
3523     }
3524   } else if (instr->CoprocessorValue() == 0xB) {
3525     switch (instr->OpcodeValue()) {
3526       case 0x2:
3527         // Load and store double to two GP registers
3528         if (instr->Bits(7, 6) != 0 || instr->Bit(4) != 1) {
3529           UNIMPLEMENTED();  // Not used by V8.
3530         } else {
3531           int rt = instr->RtValue();
3532           int rn = instr->RnValue();
3533           int vm = instr->VFPMRegValue(kDoublePrecision);
3534           if (instr->HasL()) {
3535             uint32_t data[2];
3536             get_d_register(vm, data);
3537             set_register(rt, data[0]);
3538             set_register(rn, data[1]);
3539           } else {
3540             int32_t data[] = { get_register(rt), get_register(rn) };
3541             set_d_register(vm, reinterpret_cast<uint32_t*>(data));
3542           }
3543         }
3544         break;
3545       case 0x8:
3546       case 0xA:
3547       case 0xC:
3548       case 0xE: {  // Load and store double to memory.
3549         int rn = instr->RnValue();
3550         int vd = instr->VFPDRegValue(kDoublePrecision);
3551         int offset = instr->Immed8Value();
3552         if (!instr->HasU()) {
3553           offset = -offset;
3554         }
3555         int32_t address = get_register(rn) + 4 * offset;
3556         if (instr->HasL()) {
3557           // Load double from memory: vldr.
3558           int32_t data[] = {
3559             ReadW(address, instr),
3560             ReadW(address + 4, instr)
3561           };
3562           set_d_register(vd, reinterpret_cast<uint32_t*>(data));
3563         } else {
3564           // Store double to memory: vstr.
3565           uint32_t data[2];
3566           get_d_register(vd, data);
3567           WriteW(address, data[0], instr);
3568           WriteW(address + 4, data[1], instr);
3569         }
3570         break;
3571       }
3572       case 0x4:
3573       case 0x5:
3574       case 0x6:
3575       case 0x7:
3576       case 0x9:
3577       case 0xB:
3578         // Load/store multiple double from memory: vldm/vstm.
3579         HandleVList(instr);
3580         break;
3581       default:
3582         UNIMPLEMENTED();  // Not used by V8.
3583     }
3584   } else {
3585     UNIMPLEMENTED();  // Not used by V8.
3586   }
3587 }
3588
3589
3590 void Simulator::DecodeSpecialCondition(Instruction* instr) {
3591   switch (instr->SpecialValue()) {
3592     case 5:
3593       if ((instr->Bits(18, 16) == 0) && (instr->Bits(11, 6) == 0x28) &&
3594           (instr->Bit(4) == 1)) {
3595         // vmovl signed
3596         if ((instr->VdValue() & 1) != 0) UNIMPLEMENTED();
3597         int Vd = (instr->Bit(22) << 3) | (instr->VdValue() >> 1);
3598         int Vm = (instr->Bit(5) << 4) | instr->VmValue();
3599         int imm3 = instr->Bits(21, 19);
3600         if ((imm3 != 1) && (imm3 != 2) && (imm3 != 4)) UNIMPLEMENTED();
3601         int esize = 8 * imm3;
3602         int elements = 64 / esize;
3603         int8_t from[8];
3604         get_d_register(Vm, reinterpret_cast<uint64_t*>(from));
3605         int16_t to[8];
3606         int e = 0;
3607         while (e < elements) {
3608           to[e] = from[e];
3609           e++;
3610         }
3611         set_q_register(Vd, reinterpret_cast<uint64_t*>(to));
3612       } else {
3613         UNIMPLEMENTED();
3614       }
3615       break;
3616     case 7:
3617       if ((instr->Bits(18, 16) == 0) && (instr->Bits(11, 6) == 0x28) &&
3618           (instr->Bit(4) == 1)) {
3619         // vmovl unsigned
3620         if ((instr->VdValue() & 1) != 0) UNIMPLEMENTED();
3621         int Vd = (instr->Bit(22) << 3) | (instr->VdValue() >> 1);
3622         int Vm = (instr->Bit(5) << 4) | instr->VmValue();
3623         int imm3 = instr->Bits(21, 19);
3624         if ((imm3 != 1) && (imm3 != 2) && (imm3 != 4)) UNIMPLEMENTED();
3625         int esize = 8 * imm3;
3626         int elements = 64 / esize;
3627         uint8_t from[8];
3628         get_d_register(Vm, reinterpret_cast<uint64_t*>(from));
3629         uint16_t to[8];
3630         int e = 0;
3631         while (e < elements) {
3632           to[e] = from[e];
3633           e++;
3634         }
3635         set_q_register(Vd, reinterpret_cast<uint64_t*>(to));
3636       } else {
3637         UNIMPLEMENTED();
3638       }
3639       break;
3640     case 8:
3641       if (instr->Bits(21, 20) == 0) {
3642         // vst1
3643         int Vd = (instr->Bit(22) << 4) | instr->VdValue();
3644         int Rn = instr->VnValue();
3645         int type = instr->Bits(11, 8);
3646         int Rm = instr->VmValue();
3647         int32_t address = get_register(Rn);
3648         int regs = 0;
3649         switch (type) {
3650           case nlt_1:
3651             regs = 1;
3652             break;
3653           case nlt_2:
3654             regs = 2;
3655             break;
3656           case nlt_3:
3657             regs = 3;
3658             break;
3659           case nlt_4:
3660             regs = 4;
3661             break;
3662           default:
3663             UNIMPLEMENTED();
3664             break;
3665         }
3666         int r = 0;
3667         while (r < regs) {
3668           uint32_t data[2];
3669           get_d_register(Vd + r, data);
3670           WriteW(address, data[0], instr);
3671           WriteW(address + 4, data[1], instr);
3672           address += 8;
3673           r++;
3674         }
3675         if (Rm != 15) {
3676           if (Rm == 13) {
3677             set_register(Rn, address);
3678           } else {
3679             set_register(Rn, get_register(Rn) + get_register(Rm));
3680           }
3681         }
3682       } else if (instr->Bits(21, 20) == 2) {
3683         // vld1
3684         int Vd = (instr->Bit(22) << 4) | instr->VdValue();
3685         int Rn = instr->VnValue();
3686         int type = instr->Bits(11, 8);
3687         int Rm = instr->VmValue();
3688         int32_t address = get_register(Rn);
3689         int regs = 0;
3690         switch (type) {
3691           case nlt_1:
3692             regs = 1;
3693             break;
3694           case nlt_2:
3695             regs = 2;
3696             break;
3697           case nlt_3:
3698             regs = 3;
3699             break;
3700           case nlt_4:
3701             regs = 4;
3702             break;
3703           default:
3704             UNIMPLEMENTED();
3705             break;
3706         }
3707         int r = 0;
3708         while (r < regs) {
3709           uint32_t data[2];
3710           data[0] = ReadW(address, instr);
3711           data[1] = ReadW(address + 4, instr);
3712           set_d_register(Vd + r, data);
3713           address += 8;
3714           r++;
3715         }
3716         if (Rm != 15) {
3717           if (Rm == 13) {
3718             set_register(Rn, address);
3719           } else {
3720             set_register(Rn, get_register(Rn) + get_register(Rm));
3721           }
3722         }
3723       } else {
3724         UNIMPLEMENTED();
3725       }
3726       break;
3727     case 0xA:
3728     case 0xB:
3729       if ((instr->Bits(22, 20) == 5) && (instr->Bits(15, 12) == 0xf)) {
3730         // pld: ignore instruction.
3731       } else {
3732         UNIMPLEMENTED();
3733       }
3734       break;
3735     case 0x1D:
3736       if (instr->Opc1Value() == 0x7 && instr->Opc3Value() == 0x1 &&
3737           instr->Bits(11, 9) == 0x5 && instr->Bits(19, 18) == 0x2 &&
3738           instr->Bit(8) == 0x1) {
3739         int vm = instr->VFPMRegValue(kDoublePrecision);
3740         int vd = instr->VFPDRegValue(kDoublePrecision);
3741         double dm_value = get_double_from_d_register(vm);
3742         double dd_value = 0.0;
3743         int rounding_mode = instr->Bits(17, 16);
3744         switch (rounding_mode) {
3745           case 0x0:  // vrinta - round with ties to away from zero
3746             dd_value = round(dm_value);
3747             break;
3748           case 0x1: {  // vrintn - round with ties to even
3749             dd_value = std::floor(dm_value);
3750             double error = dm_value - dd_value;
3751             // Take care of correctly handling the range [-0.5, -0.0], which
3752             // must yield -0.0.
3753             if ((-0.5 <= dm_value) && (dm_value < 0.0)) {
3754               dd_value = -0.0;
3755               // If the error is greater than 0.5, or is equal to 0.5 and the
3756               // integer result is odd, round up.
3757             } else if ((error > 0.5) ||
3758                        ((error == 0.5) && (fmod(dd_value, 2) != 0))) {
3759               dd_value++;
3760             }
3761             break;
3762           }
3763           case 0x2:  // vrintp - ceil
3764             dd_value = std::ceil(dm_value);
3765             break;
3766           case 0x3:  // vrintm - floor
3767             dd_value = std::floor(dm_value);
3768             break;
3769           default:
3770             UNREACHABLE();  // Case analysis is exhaustive.
3771             break;
3772         }
3773         dd_value = canonicalizeNaN(dd_value);
3774         set_d_register_from_double(vd, dd_value);
3775       } else {
3776         UNIMPLEMENTED();
3777       }
3778       break;
3779     default:
3780       UNIMPLEMENTED();
3781       break;
3782   }
3783 }
3784
3785
3786 // Executes the current instruction.
3787 void Simulator::InstructionDecode(Instruction* instr) {
3788   if (v8::internal::FLAG_check_icache) {
3789     CheckICache(isolate_->simulator_i_cache(), instr);
3790   }
3791   pc_modified_ = false;
3792   if (::v8::internal::FLAG_trace_sim) {
3793     disasm::NameConverter converter;
3794     disasm::Disassembler dasm(converter);
3795     // use a reasonably large buffer
3796     v8::internal::EmbeddedVector<char, 256> buffer;
3797     dasm.InstructionDecode(buffer,
3798                            reinterpret_cast<byte*>(instr));
3799     PrintF("  0x%08x  %s\n", reinterpret_cast<intptr_t>(instr), buffer.start());
3800   }
3801   if (instr->ConditionField() == kSpecialCondition) {
3802     DecodeSpecialCondition(instr);
3803   } else if (ConditionallyExecute(instr)) {
3804     switch (instr->TypeValue()) {
3805       case 0:
3806       case 1: {
3807         DecodeType01(instr);
3808         break;
3809       }
3810       case 2: {
3811         DecodeType2(instr);
3812         break;
3813       }
3814       case 3: {
3815         DecodeType3(instr);
3816         break;
3817       }
3818       case 4: {
3819         DecodeType4(instr);
3820         break;
3821       }
3822       case 5: {
3823         DecodeType5(instr);
3824         break;
3825       }
3826       case 6: {
3827         DecodeType6(instr);
3828         break;
3829       }
3830       case 7: {
3831         DecodeType7(instr);
3832         break;
3833       }
3834       default: {
3835         UNIMPLEMENTED();
3836         break;
3837       }
3838     }
3839   // If the instruction is a non taken conditional stop, we need to skip the
3840   // inlined message address.
3841   } else if (instr->IsStop()) {
3842     set_pc(get_pc() + 2 * Instruction::kInstrSize);
3843   }
3844   if (!pc_modified_) {
3845     set_register(pc, reinterpret_cast<int32_t>(instr)
3846                          + Instruction::kInstrSize);
3847   }
3848 }
3849
3850
3851 void Simulator::Execute() {
3852   // Get the PC to simulate. Cannot use the accessor here as we need the
3853   // raw PC value and not the one used as input to arithmetic instructions.
3854   int program_counter = get_pc();
3855
3856   if (::v8::internal::FLAG_stop_sim_at == 0) {
3857     // Fast version of the dispatch loop without checking whether the simulator
3858     // should be stopping at a particular executed instruction.
3859     while (program_counter != end_sim_pc) {
3860       Instruction* instr = reinterpret_cast<Instruction*>(program_counter);
3861       icount_++;
3862       InstructionDecode(instr);
3863       program_counter = get_pc();
3864     }
3865   } else {
3866     // FLAG_stop_sim_at is at the non-default value. Stop in the debugger when
3867     // we reach the particular instuction count.
3868     while (program_counter != end_sim_pc) {
3869       Instruction* instr = reinterpret_cast<Instruction*>(program_counter);
3870       icount_++;
3871       if (icount_ == ::v8::internal::FLAG_stop_sim_at) {
3872         ArmDebugger dbg(this);
3873         dbg.Debug();
3874       } else {
3875         InstructionDecode(instr);
3876       }
3877       program_counter = get_pc();
3878     }
3879   }
3880 }
3881
3882
3883 void Simulator::CallInternal(byte* entry) {
3884   // Prepare to execute the code at entry
3885   set_register(pc, reinterpret_cast<int32_t>(entry));
3886   // Put down marker for end of simulation. The simulator will stop simulation
3887   // when the PC reaches this value. By saving the "end simulation" value into
3888   // the LR the simulation stops when returning to this call point.
3889   set_register(lr, end_sim_pc);
3890
3891   // Remember the values of callee-saved registers.
3892   // The code below assumes that r9 is not used as sb (static base) in
3893   // simulator code and therefore is regarded as a callee-saved register.
3894   int32_t r4_val = get_register(r4);
3895   int32_t r5_val = get_register(r5);
3896   int32_t r6_val = get_register(r6);
3897   int32_t r7_val = get_register(r7);
3898   int32_t r8_val = get_register(r8);
3899   int32_t r9_val = get_register(r9);
3900   int32_t r10_val = get_register(r10);
3901   int32_t r11_val = get_register(r11);
3902
3903   // Set up the callee-saved registers with a known value. To be able to check
3904   // that they are preserved properly across JS execution.
3905   int32_t callee_saved_value = icount_;
3906   set_register(r4, callee_saved_value);
3907   set_register(r5, callee_saved_value);
3908   set_register(r6, callee_saved_value);
3909   set_register(r7, callee_saved_value);
3910   set_register(r8, callee_saved_value);
3911   set_register(r9, callee_saved_value);
3912   set_register(r10, callee_saved_value);
3913   set_register(r11, callee_saved_value);
3914
3915   // Start the simulation
3916   Execute();
3917
3918   // Check that the callee-saved registers have been preserved.
3919   CHECK_EQ(callee_saved_value, get_register(r4));
3920   CHECK_EQ(callee_saved_value, get_register(r5));
3921   CHECK_EQ(callee_saved_value, get_register(r6));
3922   CHECK_EQ(callee_saved_value, get_register(r7));
3923   CHECK_EQ(callee_saved_value, get_register(r8));
3924   CHECK_EQ(callee_saved_value, get_register(r9));
3925   CHECK_EQ(callee_saved_value, get_register(r10));
3926   CHECK_EQ(callee_saved_value, get_register(r11));
3927
3928   // Restore callee-saved registers with the original value.
3929   set_register(r4, r4_val);
3930   set_register(r5, r5_val);
3931   set_register(r6, r6_val);
3932   set_register(r7, r7_val);
3933   set_register(r8, r8_val);
3934   set_register(r9, r9_val);
3935   set_register(r10, r10_val);
3936   set_register(r11, r11_val);
3937 }
3938
3939
3940 int32_t Simulator::Call(byte* entry, int argument_count, ...) {
3941   va_list parameters;
3942   va_start(parameters, argument_count);
3943   // Set up arguments
3944
3945   // First four arguments passed in registers.
3946   DCHECK(argument_count >= 4);
3947   set_register(r0, va_arg(parameters, int32_t));
3948   set_register(r1, va_arg(parameters, int32_t));
3949   set_register(r2, va_arg(parameters, int32_t));
3950   set_register(r3, va_arg(parameters, int32_t));
3951
3952   // Remaining arguments passed on stack.
3953   int original_stack = get_register(sp);
3954   // Compute position of stack on entry to generated code.
3955   int entry_stack = (original_stack - (argument_count - 4) * sizeof(int32_t));
3956   if (base::OS::ActivationFrameAlignment() != 0) {
3957     entry_stack &= -base::OS::ActivationFrameAlignment();
3958   }
3959   // Store remaining arguments on stack, from low to high memory.
3960   intptr_t* stack_argument = reinterpret_cast<intptr_t*>(entry_stack);
3961   for (int i = 4; i < argument_count; i++) {
3962     stack_argument[i - 4] = va_arg(parameters, int32_t);
3963   }
3964   va_end(parameters);
3965   set_register(sp, entry_stack);
3966
3967   CallInternal(entry);
3968
3969   // Pop stack passed arguments.
3970   CHECK_EQ(entry_stack, get_register(sp));
3971   set_register(sp, original_stack);
3972
3973   int32_t result = get_register(r0);
3974   return result;
3975 }
3976
3977
3978 void Simulator::CallFP(byte* entry, double d0, double d1) {
3979   if (use_eabi_hardfloat()) {
3980     set_d_register_from_double(0, d0);
3981     set_d_register_from_double(1, d1);
3982   } else {
3983     set_register_pair_from_double(0, &d0);
3984     set_register_pair_from_double(2, &d1);
3985   }
3986   CallInternal(entry);
3987 }
3988
3989
3990 int32_t Simulator::CallFPReturnsInt(byte* entry, double d0, double d1) {
3991   CallFP(entry, d0, d1);
3992   int32_t result = get_register(r0);
3993   return result;
3994 }
3995
3996
3997 double Simulator::CallFPReturnsDouble(byte* entry, double d0, double d1) {
3998   CallFP(entry, d0, d1);
3999   if (use_eabi_hardfloat()) {
4000     return get_double_from_d_register(0);
4001   } else {
4002     return get_double_from_register_pair(0);
4003   }
4004 }
4005
4006
4007 uintptr_t Simulator::PushAddress(uintptr_t address) {
4008   int new_sp = get_register(sp) - sizeof(uintptr_t);
4009   uintptr_t* stack_slot = reinterpret_cast<uintptr_t*>(new_sp);
4010   *stack_slot = address;
4011   set_register(sp, new_sp);
4012   return new_sp;
4013 }
4014
4015
4016 uintptr_t Simulator::PopAddress() {
4017   int current_sp = get_register(sp);
4018   uintptr_t* stack_slot = reinterpret_cast<uintptr_t*>(current_sp);
4019   uintptr_t address = *stack_slot;
4020   set_register(sp, current_sp + sizeof(uintptr_t));
4021   return address;
4022 }
4023
4024 } }  // namespace v8::internal
4025
4026 #endif  // USE_SIMULATOR
4027
4028 #endif  // V8_TARGET_ARCH_ARM