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