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_register_pair_from_double(int reg, double* value) {
916  ASSERT((reg >= 0) && (reg < num_registers) && ((reg % 2) == 0));
917  memcpy(registers_ + reg, value, sizeof(*value));
918}
919
920
921void Simulator::set_dw_register(int dreg, const int* dbl) {
922  ASSERT((dreg >= 0) && (dreg < num_d_registers));
923  registers_[dreg] = dbl[0];
924  registers_[dreg + 1] = dbl[1];
925}
926
927
928void Simulator::get_d_register(int dreg, uint64_t* value) {
929  ASSERT((dreg >= 0) && (dreg < DwVfpRegister::NumRegisters()));
930  memcpy(value, vfp_registers_ + dreg * 2, sizeof(*value));
931}
932
933
934void Simulator::set_d_register(int dreg, const uint64_t* value) {
935  ASSERT((dreg >= 0) && (dreg < DwVfpRegister::NumRegisters()));
936  memcpy(vfp_registers_ + dreg * 2, value, sizeof(*value));
937}
938
939
940void Simulator::get_d_register(int dreg, uint32_t* value) {
941  ASSERT((dreg >= 0) && (dreg < DwVfpRegister::NumRegisters()));
942  memcpy(value, vfp_registers_ + dreg * 2, sizeof(*value) * 2);
943}
944
945
946void Simulator::set_d_register(int dreg, const uint32_t* value) {
947  ASSERT((dreg >= 0) && (dreg < DwVfpRegister::NumRegisters()));
948  memcpy(vfp_registers_ + dreg * 2, value, sizeof(*value) * 2);
949}
950
951
952void Simulator::get_q_register(int qreg, uint64_t* value) {
953  ASSERT((qreg >= 0) && (qreg < num_q_registers));
954  memcpy(value, vfp_registers_ + qreg * 4, sizeof(*value) * 2);
955}
956
957
958void Simulator::set_q_register(int qreg, const uint64_t* value) {
959  ASSERT((qreg >= 0) && (qreg < num_q_registers));
960  memcpy(vfp_registers_ + qreg * 4, value, sizeof(*value) * 2);
961}
962
963
964void Simulator::get_q_register(int qreg, uint32_t* value) {
965  ASSERT((qreg >= 0) && (qreg < num_q_registers));
966  memcpy(value, vfp_registers_ + qreg * 4, sizeof(*value) * 4);
967}
968
969
970void Simulator::set_q_register(int qreg, const uint32_t* value) {
971  ASSERT((qreg >= 0) && (qreg < num_q_registers));
972  memcpy(vfp_registers_ + qreg * 4, value, sizeof(*value) * 4);
973}
974
975
976// Raw access to the PC register.
977void Simulator::set_pc(int32_t value) {
978  pc_modified_ = true;
979  registers_[pc] = value;
980}
981
982
983bool Simulator::has_bad_pc() const {
984  return ((registers_[pc] == bad_lr) || (registers_[pc] == end_sim_pc));
985}
986
987
988// Raw access to the PC register without the special adjustment when reading.
989int32_t Simulator::get_pc() const {
990  return registers_[pc];
991}
992
993
994// Getting from and setting into VFP registers.
995void Simulator::set_s_register(int sreg, unsigned int value) {
996  ASSERT((sreg >= 0) && (sreg < num_s_registers));
997  vfp_registers_[sreg] = value;
998}
999
1000
1001unsigned int Simulator::get_s_register(int sreg) const {
1002  ASSERT((sreg >= 0) && (sreg < num_s_registers));
1003  return vfp_registers_[sreg];
1004}
1005
1006
1007template<class InputType, int register_size>
1008void Simulator::SetVFPRegister(int reg_index, const InputType& value) {
1009  ASSERT(reg_index >= 0);
1010  if (register_size == 1) ASSERT(reg_index < num_s_registers);
1011  if (register_size == 2) ASSERT(reg_index < DwVfpRegister::NumRegisters());
1012
1013  char buffer[register_size * sizeof(vfp_registers_[0])];
1014  OS::MemCopy(buffer, &value, register_size * sizeof(vfp_registers_[0]));
1015  OS::MemCopy(&vfp_registers_[reg_index * register_size], buffer,
1016              register_size * sizeof(vfp_registers_[0]));
1017}
1018
1019
1020template<class ReturnType, int register_size>
1021ReturnType Simulator::GetFromVFPRegister(int reg_index) {
1022  ASSERT(reg_index >= 0);
1023  if (register_size == 1) ASSERT(reg_index < num_s_registers);
1024  if (register_size == 2) ASSERT(reg_index < DwVfpRegister::NumRegisters());
1025
1026  ReturnType value = 0;
1027  char buffer[register_size * sizeof(vfp_registers_[0])];
1028  OS::MemCopy(buffer, &vfp_registers_[register_size * reg_index],
1029              register_size * sizeof(vfp_registers_[0]));
1030  OS::MemCopy(&value, buffer, register_size * sizeof(vfp_registers_[0]));
1031  return value;
1032}
1033
1034
1035// Runtime FP routines take:
1036// - two double arguments
1037// - one double argument and zero or one integer arguments.
1038// All are consructed here from r0-r3 or d0, d1 and r0.
1039void Simulator::GetFpArgs(double* x, double* y, int32_t* z) {
1040  if (use_eabi_hardfloat()) {
1041    *x = get_double_from_d_register(0);
1042    *y = get_double_from_d_register(1);
1043    *z = get_register(0);
1044  } else {
1045    // Registers 0 and 1 -> x.
1046    *x = get_double_from_register_pair(0);
1047    // Register 2 and 3 -> y.
1048    *y = get_double_from_register_pair(2);
1049    // Register 2 -> z
1050    *z = get_register(2);
1051  }
1052}
1053
1054
1055// The return value is either in r0/r1 or d0.
1056void Simulator::SetFpResult(const double& result) {
1057  if (use_eabi_hardfloat()) {
1058    char buffer[2 * sizeof(vfp_registers_[0])];
1059    OS::MemCopy(buffer, &result, sizeof(buffer));
1060    // Copy result to d0.
1061    OS::MemCopy(vfp_registers_, buffer, sizeof(buffer));
1062  } else {
1063    char buffer[2 * sizeof(registers_[0])];
1064    OS::MemCopy(buffer, &result, sizeof(buffer));
1065    // Copy result to r0 and r1.
1066    OS::MemCopy(registers_, buffer, sizeof(buffer));
1067  }
1068}
1069
1070
1071void Simulator::TrashCallerSaveRegisters() {
1072  // We don't trash the registers with the return value.
1073  registers_[2] = 0x50Bad4U;
1074  registers_[3] = 0x50Bad4U;
1075  registers_[12] = 0x50Bad4U;
1076}
1077
1078
1079// Some Operating Systems allow unaligned access on ARMv7 targets. We
1080// assume that unaligned accesses are not allowed unless the v8 build system
1081// defines the CAN_USE_UNALIGNED_ACCESSES macro to be non-zero.
1082// The following statements below describes the behavior of the ARM CPUs
1083// that don't support unaligned access.
1084// Some ARM platforms raise an interrupt on detecting unaligned access.
1085// On others it does a funky rotation thing.  For now we
1086// simply disallow unaligned reads.  Note that simulator runs have the runtime
1087// system running directly on the host system and only generated code is
1088// executed in the simulator.  Since the host is typically IA32 we will not
1089// get the correct ARM-like behaviour on unaligned accesses for those ARM
1090// targets that don't support unaligned loads and stores.
1091
1092
1093int Simulator::ReadW(int32_t addr, Instruction* instr) {
1094  if (FLAG_enable_unaligned_accesses || (addr & 3) == 0) {
1095    intptr_t* ptr = reinterpret_cast<intptr_t*>(addr);
1096    return *ptr;
1097  } else {
1098    PrintF("Unaligned read at 0x%08x, pc=0x%08" V8PRIxPTR "\n",
1099           addr,
1100           reinterpret_cast<intptr_t>(instr));
1101    UNIMPLEMENTED();
1102    return 0;
1103  }
1104}
1105
1106
1107void Simulator::WriteW(int32_t addr, int value, Instruction* instr) {
1108  if (FLAG_enable_unaligned_accesses || (addr & 3) == 0) {
1109    intptr_t* ptr = reinterpret_cast<intptr_t*>(addr);
1110    *ptr = value;
1111  } else {
1112    PrintF("Unaligned write at 0x%08x, pc=0x%08" V8PRIxPTR "\n",
1113           addr,
1114           reinterpret_cast<intptr_t>(instr));
1115    UNIMPLEMENTED();
1116  }
1117}
1118
1119
1120uint16_t Simulator::ReadHU(int32_t addr, Instruction* instr) {
1121  if (FLAG_enable_unaligned_accesses || (addr & 1) == 0) {
1122    uint16_t* ptr = reinterpret_cast<uint16_t*>(addr);
1123    return *ptr;
1124  } else {
1125    PrintF("Unaligned unsigned halfword read at 0x%08x, pc=0x%08"
1126           V8PRIxPTR "\n",
1127           addr,
1128           reinterpret_cast<intptr_t>(instr));
1129    UNIMPLEMENTED();
1130    return 0;
1131  }
1132}
1133
1134
1135int16_t Simulator::ReadH(int32_t addr, Instruction* instr) {
1136  if (FLAG_enable_unaligned_accesses || (addr & 1) == 0) {
1137    int16_t* ptr = reinterpret_cast<int16_t*>(addr);
1138    return *ptr;
1139  } else {
1140    PrintF("Unaligned signed halfword read at 0x%08x\n", addr);
1141    UNIMPLEMENTED();
1142    return 0;
1143  }
1144}
1145
1146
1147void Simulator::WriteH(int32_t addr, uint16_t value, Instruction* instr) {
1148  if (FLAG_enable_unaligned_accesses || (addr & 1) == 0) {
1149    uint16_t* ptr = reinterpret_cast<uint16_t*>(addr);
1150    *ptr = value;
1151  } else {
1152    PrintF("Unaligned unsigned halfword write at 0x%08x, pc=0x%08"
1153           V8PRIxPTR "\n",
1154           addr,
1155           reinterpret_cast<intptr_t>(instr));
1156    UNIMPLEMENTED();
1157  }
1158}
1159
1160
1161void Simulator::WriteH(int32_t addr, int16_t value, Instruction* instr) {
1162  if (FLAG_enable_unaligned_accesses || (addr & 1) == 0) {
1163    int16_t* ptr = reinterpret_cast<int16_t*>(addr);
1164    *ptr = value;
1165  } else {
1166    PrintF("Unaligned halfword write at 0x%08x, pc=0x%08" V8PRIxPTR "\n",
1167           addr,
1168           reinterpret_cast<intptr_t>(instr));
1169    UNIMPLEMENTED();
1170  }
1171}
1172
1173
1174uint8_t Simulator::ReadBU(int32_t addr) {
1175  uint8_t* ptr = reinterpret_cast<uint8_t*>(addr);
1176  return *ptr;
1177}
1178
1179
1180int8_t Simulator::ReadB(int32_t addr) {
1181  int8_t* ptr = reinterpret_cast<int8_t*>(addr);
1182  return *ptr;
1183}
1184
1185
1186void Simulator::WriteB(int32_t addr, uint8_t value) {
1187  uint8_t* ptr = reinterpret_cast<uint8_t*>(addr);
1188  *ptr = value;
1189}
1190
1191
1192void Simulator::WriteB(int32_t addr, int8_t value) {
1193  int8_t* ptr = reinterpret_cast<int8_t*>(addr);
1194  *ptr = value;
1195}
1196
1197
1198int32_t* Simulator::ReadDW(int32_t addr) {
1199  if (FLAG_enable_unaligned_accesses || (addr & 3) == 0) {
1200    int32_t* ptr = reinterpret_cast<int32_t*>(addr);
1201    return ptr;
1202  } else {
1203    PrintF("Unaligned read at 0x%08x\n", addr);
1204    UNIMPLEMENTED();
1205    return 0;
1206  }
1207}
1208
1209
1210void Simulator::WriteDW(int32_t addr, int32_t value1, int32_t value2) {
1211  if (FLAG_enable_unaligned_accesses || (addr & 3) == 0) {
1212    int32_t* ptr = reinterpret_cast<int32_t*>(addr);
1213    *ptr++ = value1;
1214    *ptr = value2;
1215  } else {
1216    PrintF("Unaligned write at 0x%08x\n", addr);
1217    UNIMPLEMENTED();
1218  }
1219}
1220
1221
1222// Returns the limit of the stack area to enable checking for stack overflows.
1223uintptr_t Simulator::StackLimit() const {
1224  // Leave a safety margin of 1024 bytes to prevent overrunning the stack when
1225  // pushing values.
1226  return reinterpret_cast<uintptr_t>(stack_) + 1024;
1227}
1228
1229
1230// Unsupported instructions use Format to print an error and stop execution.
1231void Simulator::Format(Instruction* instr, const char* format) {
1232  PrintF("Simulator found unsupported instruction:\n 0x%08x: %s\n",
1233         reinterpret_cast<intptr_t>(instr), format);
1234  UNIMPLEMENTED();
1235}
1236
1237
1238// Checks if the current instruction should be executed based on its
1239// condition bits.
1240bool Simulator::ConditionallyExecute(Instruction* instr) {
1241  switch (instr->ConditionField()) {
1242    case eq: return z_flag_;
1243    case ne: return !z_flag_;
1244    case cs: return c_flag_;
1245    case cc: return !c_flag_;
1246    case mi: return n_flag_;
1247    case pl: return !n_flag_;
1248    case vs: return v_flag_;
1249    case vc: return !v_flag_;
1250    case hi: return c_flag_ && !z_flag_;
1251    case ls: return !c_flag_ || z_flag_;
1252    case ge: return n_flag_ == v_flag_;
1253    case lt: return n_flag_ != v_flag_;
1254    case gt: return !z_flag_ && (n_flag_ == v_flag_);
1255    case le: return z_flag_ || (n_flag_ != v_flag_);
1256    case al: return true;
1257    default: UNREACHABLE();
1258  }
1259  return false;
1260}
1261
1262
1263// Calculate and set the Negative and Zero flags.
1264void Simulator::SetNZFlags(int32_t val) {
1265  n_flag_ = (val < 0);
1266  z_flag_ = (val == 0);
1267}
1268
1269
1270// Set the Carry flag.
1271void Simulator::SetCFlag(bool val) {
1272  c_flag_ = val;
1273}
1274
1275
1276// Set the oVerflow flag.
1277void Simulator::SetVFlag(bool val) {
1278  v_flag_ = val;
1279}
1280
1281
1282// Calculate C flag value for additions.
1283bool Simulator::CarryFrom(int32_t left, int32_t right, int32_t carry) {
1284  uint32_t uleft = static_cast<uint32_t>(left);
1285  uint32_t uright = static_cast<uint32_t>(right);
1286  uint32_t urest  = 0xffffffffU - uleft;
1287
1288  return (uright > urest) ||
1289         (carry && (((uright + 1) > urest) || (uright > (urest - 1))));
1290}
1291
1292
1293// Calculate C flag value for subtractions.
1294bool Simulator::BorrowFrom(int32_t left, int32_t right) {
1295  uint32_t uleft = static_cast<uint32_t>(left);
1296  uint32_t uright = static_cast<uint32_t>(right);
1297
1298  return (uright > uleft);
1299}
1300
1301
1302// Calculate V flag value for additions and subtractions.
1303bool Simulator::OverflowFrom(int32_t alu_out,
1304                             int32_t left, int32_t right, bool addition) {
1305  bool overflow;
1306  if (addition) {
1307               // operands have the same sign
1308    overflow = ((left >= 0 && right >= 0) || (left < 0 && right < 0))
1309               // and operands and result have different sign
1310               && ((left < 0 && alu_out >= 0) || (left >= 0 && alu_out < 0));
1311  } else {
1312               // operands have different signs
1313    overflow = ((left < 0 && right >= 0) || (left >= 0 && right < 0))
1314               // and first operand and result have different signs
1315               && ((left < 0 && alu_out >= 0) || (left >= 0 && alu_out < 0));
1316  }
1317  return overflow;
1318}
1319
1320
1321// Support for VFP comparisons.
1322void Simulator::Compute_FPSCR_Flags(double val1, double val2) {
1323  if (std::isnan(val1) || std::isnan(val2)) {
1324    n_flag_FPSCR_ = false;
1325    z_flag_FPSCR_ = false;
1326    c_flag_FPSCR_ = true;
1327    v_flag_FPSCR_ = true;
1328  // All non-NaN cases.
1329  } else if (val1 == val2) {
1330    n_flag_FPSCR_ = false;
1331    z_flag_FPSCR_ = true;
1332    c_flag_FPSCR_ = true;
1333    v_flag_FPSCR_ = false;
1334  } else if (val1 < val2) {
1335    n_flag_FPSCR_ = true;
1336    z_flag_FPSCR_ = false;
1337    c_flag_FPSCR_ = false;
1338    v_flag_FPSCR_ = false;
1339  } else {
1340    // Case when (val1 > val2).
1341    n_flag_FPSCR_ = false;
1342    z_flag_FPSCR_ = false;
1343    c_flag_FPSCR_ = true;
1344    v_flag_FPSCR_ = false;
1345  }
1346}
1347
1348
1349void Simulator::Copy_FPSCR_to_APSR() {
1350  n_flag_ = n_flag_FPSCR_;
1351  z_flag_ = z_flag_FPSCR_;
1352  c_flag_ = c_flag_FPSCR_;
1353  v_flag_ = v_flag_FPSCR_;
1354}
1355
1356
1357// Addressing Mode 1 - Data-processing operands:
1358// Get the value based on the shifter_operand with register.
1359int32_t Simulator::GetShiftRm(Instruction* instr, bool* carry_out) {
1360  ShiftOp shift = instr->ShiftField();
1361  int shift_amount = instr->ShiftAmountValue();
1362  int32_t result = get_register(instr->RmValue());
1363  if (instr->Bit(4) == 0) {
1364    // by immediate
1365    if ((shift == ROR) && (shift_amount == 0)) {
1366      UNIMPLEMENTED();
1367      return result;
1368    } else if (((shift == LSR) || (shift == ASR)) && (shift_amount == 0)) {
1369      shift_amount = 32;
1370    }
1371    switch (shift) {
1372      case ASR: {
1373        if (shift_amount == 0) {
1374          if (result < 0) {
1375            result = 0xffffffff;
1376            *carry_out = true;
1377          } else {
1378            result = 0;
1379            *carry_out = false;
1380          }
1381        } else {
1382          result >>= (shift_amount - 1);
1383          *carry_out = (result & 1) == 1;
1384          result >>= 1;
1385        }
1386        break;
1387      }
1388
1389      case LSL: {
1390        if (shift_amount == 0) {
1391          *carry_out = c_flag_;
1392        } else {
1393          result <<= (shift_amount - 1);
1394          *carry_out = (result < 0);
1395          result <<= 1;
1396        }
1397        break;
1398      }
1399
1400      case LSR: {
1401        if (shift_amount == 0) {
1402          result = 0;
1403          *carry_out = c_flag_;
1404        } else {
1405          uint32_t uresult = static_cast<uint32_t>(result);
1406          uresult >>= (shift_amount - 1);
1407          *carry_out = (uresult & 1) == 1;
1408          uresult >>= 1;
1409          result = static_cast<int32_t>(uresult);
1410        }
1411        break;
1412      }
1413
1414      case ROR: {
1415        if (shift_amount == 0) {
1416          *carry_out = c_flag_;
1417        } else {
1418          uint32_t left = static_cast<uint32_t>(result) >> shift_amount;
1419          uint32_t right = static_cast<uint32_t>(result) << (32 - shift_amount);
1420          result = right | left;
1421          *carry_out = (static_cast<uint32_t>(result) >> 31) != 0;
1422        }
1423        break;
1424      }
1425
1426      default: {
1427        UNREACHABLE();
1428        break;
1429      }
1430    }
1431  } else {
1432    // by register
1433    int rs = instr->RsValue();
1434    shift_amount = get_register(rs) &0xff;
1435    switch (shift) {
1436      case ASR: {
1437        if (shift_amount == 0) {
1438          *carry_out = c_flag_;
1439        } else if (shift_amount < 32) {
1440          result >>= (shift_amount - 1);
1441          *carry_out = (result & 1) == 1;
1442          result >>= 1;
1443        } else {
1444          ASSERT(shift_amount >= 32);
1445          if (result < 0) {
1446            *carry_out = true;
1447            result = 0xffffffff;
1448          } else {
1449            *carry_out = false;
1450            result = 0;
1451          }
1452        }
1453        break;
1454      }
1455
1456      case LSL: {
1457        if (shift_amount == 0) {
1458          *carry_out = c_flag_;
1459        } else if (shift_amount < 32) {
1460          result <<= (shift_amount - 1);
1461          *carry_out = (result < 0);
1462          result <<= 1;
1463        } else if (shift_amount == 32) {
1464          *carry_out = (result & 1) == 1;
1465          result = 0;
1466        } else {
1467          ASSERT(shift_amount > 32);
1468          *carry_out = false;
1469          result = 0;
1470        }
1471        break;
1472      }
1473
1474      case LSR: {
1475        if (shift_amount == 0) {
1476          *carry_out = c_flag_;
1477        } else if (shift_amount < 32) {
1478          uint32_t uresult = static_cast<uint32_t>(result);
1479          uresult >>= (shift_amount - 1);
1480          *carry_out = (uresult & 1) == 1;
1481          uresult >>= 1;
1482          result = static_cast<int32_t>(uresult);
1483        } else if (shift_amount == 32) {
1484          *carry_out = (result < 0);
1485          result = 0;
1486        } else {
1487          *carry_out = false;
1488          result = 0;
1489        }
1490        break;
1491      }
1492
1493      case ROR: {
1494        if (shift_amount == 0) {
1495          *carry_out = c_flag_;
1496        } else {
1497          uint32_t left = static_cast<uint32_t>(result) >> shift_amount;
1498          uint32_t right = static_cast<uint32_t>(result) << (32 - shift_amount);
1499          result = right | left;
1500          *carry_out = (static_cast<uint32_t>(result) >> 31) != 0;
1501        }
1502        break;
1503      }
1504
1505      default: {
1506        UNREACHABLE();
1507        break;
1508      }
1509    }
1510  }
1511  return result;
1512}
1513
1514
1515// Addressing Mode 1 - Data-processing operands:
1516// Get the value based on the shifter_operand with immediate.
1517int32_t Simulator::GetImm(Instruction* instr, bool* carry_out) {
1518  int rotate = instr->RotateValue() * 2;
1519  int immed8 = instr->Immed8Value();
1520  int imm = (immed8 >> rotate) | (immed8 << (32 - rotate));
1521  *carry_out = (rotate == 0) ? c_flag_ : (imm < 0);
1522  return imm;
1523}
1524
1525
1526static int count_bits(int bit_vector) {
1527  int count = 0;
1528  while (bit_vector != 0) {
1529    if ((bit_vector & 1) != 0) {
1530      count++;
1531    }
1532    bit_vector >>= 1;
1533  }
1534  return count;
1535}
1536
1537
1538int32_t Simulator::ProcessPU(Instruction* instr,
1539                             int num_regs,
1540                             int reg_size,
1541                             intptr_t* start_address,
1542                             intptr_t* end_address) {
1543  int rn = instr->RnValue();
1544  int32_t rn_val = get_register(rn);
1545  switch (instr->PUField()) {
1546    case da_x: {
1547      UNIMPLEMENTED();
1548      break;
1549    }
1550    case ia_x: {
1551      *start_address = rn_val;
1552      *end_address = rn_val + (num_regs * reg_size) - reg_size;
1553      rn_val = rn_val + (num_regs * reg_size);
1554      break;
1555    }
1556    case db_x: {
1557      *start_address = rn_val - (num_regs * reg_size);
1558      *end_address = rn_val - reg_size;
1559      rn_val = *start_address;
1560      break;
1561    }
1562    case ib_x: {
1563      *start_address = rn_val + reg_size;
1564      *end_address = rn_val + (num_regs * reg_size);
1565      rn_val = *end_address;
1566      break;
1567    }
1568    default: {
1569      UNREACHABLE();
1570      break;
1571    }
1572  }
1573  return rn_val;
1574}
1575
1576
1577// Addressing Mode 4 - Load and Store Multiple
1578void Simulator::HandleRList(Instruction* instr, bool load) {
1579  int rlist = instr->RlistValue();
1580  int num_regs = count_bits(rlist);
1581
1582  intptr_t start_address = 0;
1583  intptr_t end_address = 0;
1584  int32_t rn_val =
1585      ProcessPU(instr, num_regs, kPointerSize, &start_address, &end_address);
1586
1587  intptr_t* address = reinterpret_cast<intptr_t*>(start_address);
1588  // Catch null pointers a little earlier.
1589  ASSERT(start_address > 8191 || start_address < 0);
1590  int reg = 0;
1591  while (rlist != 0) {
1592    if ((rlist & 1) != 0) {
1593      if (load) {
1594        set_register(reg, *address);
1595      } else {
1596        *address = get_register(reg);
1597      }
1598      address += 1;
1599    }
1600    reg++;
1601    rlist >>= 1;
1602  }
1603  ASSERT(end_address == ((intptr_t)address) - 4);
1604  if (instr->HasW()) {
1605    set_register(instr->RnValue(), rn_val);
1606  }
1607}
1608
1609
1610// Addressing Mode 6 - Load and Store Multiple Coprocessor registers.
1611void Simulator::HandleVList(Instruction* instr) {
1612  VFPRegPrecision precision =
1613      (instr->SzValue() == 0) ? kSinglePrecision : kDoublePrecision;
1614  int operand_size = (precision == kSinglePrecision) ? 4 : 8;
1615
1616  bool load = (instr->VLValue() == 0x1);
1617
1618  int vd;
1619  int num_regs;
1620  vd = instr->VFPDRegValue(precision);
1621  if (precision == kSinglePrecision) {
1622    num_regs = instr->Immed8Value();
1623  } else {
1624    num_regs = instr->Immed8Value() / 2;
1625  }
1626
1627  intptr_t start_address = 0;
1628  intptr_t end_address = 0;
1629  int32_t rn_val =
1630      ProcessPU(instr, num_regs, operand_size, &start_address, &end_address);
1631
1632  intptr_t* address = reinterpret_cast<intptr_t*>(start_address);
1633  for (int reg = vd; reg < vd + num_regs; reg++) {
1634    if (precision == kSinglePrecision) {
1635      if (load) {
1636        set_s_register_from_sinteger(
1637            reg, ReadW(reinterpret_cast<int32_t>(address), instr));
1638      } else {
1639        WriteW(reinterpret_cast<int32_t>(address),
1640               get_sinteger_from_s_register(reg), instr);
1641      }
1642      address += 1;
1643    } else {
1644      if (load) {
1645        int32_t data[] = {
1646          ReadW(reinterpret_cast<int32_t>(address), instr),
1647          ReadW(reinterpret_cast<int32_t>(address + 1), instr)
1648        };
1649        double d;
1650        OS::MemCopy(&d, data, 8);
1651        set_d_register_from_double(reg, d);
1652      } else {
1653        int32_t data[2];
1654        double d = get_double_from_d_register(reg);
1655        OS::MemCopy(data, &d, 8);
1656        WriteW(reinterpret_cast<int32_t>(address), data[0], instr);
1657        WriteW(reinterpret_cast<int32_t>(address + 1), data[1], instr);
1658      }
1659      address += 2;
1660    }
1661  }
1662  ASSERT(reinterpret_cast<intptr_t>(address) - operand_size == end_address);
1663  if (instr->HasW()) {
1664    set_register(instr->RnValue(), rn_val);
1665  }
1666}
1667
1668
1669// Calls into the V8 runtime are based on this very simple interface.
1670// Note: To be able to return two values from some calls the code in runtime.cc
1671// uses the ObjectPair which is essentially two 32-bit values stuffed into a
1672// 64-bit value. With the code below we assume that all runtime calls return
1673// 64 bits of result. If they don't, the r1 result register contains a bogus
1674// value, which is fine because it is caller-saved.
1675typedef int64_t (*SimulatorRuntimeCall)(int32_t arg0,
1676                                        int32_t arg1,
1677                                        int32_t arg2,
1678                                        int32_t arg3,
1679                                        int32_t arg4,
1680                                        int32_t arg5);
1681
1682// These prototypes handle the four types of FP calls.
1683typedef int64_t (*SimulatorRuntimeCompareCall)(double darg0, double darg1);
1684typedef double (*SimulatorRuntimeFPFPCall)(double darg0, double darg1);
1685typedef double (*SimulatorRuntimeFPCall)(double darg0);
1686typedef double (*SimulatorRuntimeFPIntCall)(double darg0, int32_t arg0);
1687
1688// This signature supports direct call in to API function native callback
1689// (refer to InvocationCallback in v8.h).
1690typedef void (*SimulatorRuntimeDirectApiCall)(int32_t arg0);
1691typedef void (*SimulatorRuntimeProfilingApiCall)(int32_t arg0, int32_t arg1);
1692
1693// This signature supports direct call to accessor getter callback.
1694typedef void (*SimulatorRuntimeDirectGetterCall)(int32_t arg0, int32_t arg1);
1695typedef void (*SimulatorRuntimeProfilingGetterCall)(
1696    int32_t arg0, int32_t arg1, int32_t arg2);
1697
1698// Software interrupt instructions are used by the simulator to call into the
1699// C-based V8 runtime.
1700void Simulator::SoftwareInterrupt(Instruction* instr) {
1701  int svc = instr->SvcValue();
1702  switch (svc) {
1703    case kCallRtRedirected: {
1704      // Check if stack is aligned. Error if not aligned is reported below to
1705      // include information on the function called.
1706      bool stack_aligned =
1707          (get_register(sp)
1708           & (::v8::internal::FLAG_sim_stack_alignment - 1)) == 0;
1709      Redirection* redirection = Redirection::FromSwiInstruction(instr);
1710      int32_t arg0 = get_register(r0);
1711      int32_t arg1 = get_register(r1);
1712      int32_t arg2 = get_register(r2);
1713      int32_t arg3 = get_register(r3);
1714      int32_t* stack_pointer = reinterpret_cast<int32_t*>(get_register(sp));
1715      int32_t arg4 = stack_pointer[0];
1716      int32_t arg5 = stack_pointer[1];
1717      bool fp_call =
1718         (redirection->type() == ExternalReference::BUILTIN_FP_FP_CALL) ||
1719         (redirection->type() == ExternalReference::BUILTIN_COMPARE_CALL) ||
1720         (redirection->type() == ExternalReference::BUILTIN_FP_CALL) ||
1721         (redirection->type() == ExternalReference::BUILTIN_FP_INT_CALL);
1722      // This is dodgy but it works because the C entry stubs are never moved.
1723      // See comment in codegen-arm.cc and bug 1242173.
1724      int32_t saved_lr = get_register(lr);
1725      intptr_t external =
1726          reinterpret_cast<intptr_t>(redirection->external_function());
1727      if (fp_call) {
1728        double dval0, dval1;  // one or two double parameters
1729        int32_t ival;         // zero or one integer parameters
1730        int64_t iresult = 0;  // integer return value
1731        double dresult = 0;   // double return value
1732        GetFpArgs(&dval0, &dval1, &ival);
1733        if (::v8::internal::FLAG_trace_sim || !stack_aligned) {
1734          SimulatorRuntimeCall generic_target =
1735            reinterpret_cast<SimulatorRuntimeCall>(external);
1736          switch (redirection->type()) {
1737          case ExternalReference::BUILTIN_FP_FP_CALL:
1738          case ExternalReference::BUILTIN_COMPARE_CALL:
1739            PrintF("Call to host function at %p with args %f, %f",
1740                   FUNCTION_ADDR(generic_target), dval0, dval1);
1741            break;
1742          case ExternalReference::BUILTIN_FP_CALL:
1743            PrintF("Call to host function at %p with arg %f",
1744                FUNCTION_ADDR(generic_target), dval0);
1745            break;
1746          case ExternalReference::BUILTIN_FP_INT_CALL:
1747            PrintF("Call to host function at %p with args %f, %d",
1748                   FUNCTION_ADDR(generic_target), dval0, ival);
1749            break;
1750          default:
1751            UNREACHABLE();
1752            break;
1753          }
1754          if (!stack_aligned) {
1755            PrintF(" with unaligned stack %08x\n", get_register(sp));
1756          }
1757          PrintF("\n");
1758        }
1759        CHECK(stack_aligned);
1760        switch (redirection->type()) {
1761        case ExternalReference::BUILTIN_COMPARE_CALL: {
1762          SimulatorRuntimeCompareCall target =
1763            reinterpret_cast<SimulatorRuntimeCompareCall>(external);
1764          iresult = target(dval0, dval1);
1765          set_register(r0, static_cast<int32_t>(iresult));
1766          set_register(r1, static_cast<int32_t>(iresult >> 32));
1767          break;
1768        }
1769        case ExternalReference::BUILTIN_FP_FP_CALL: {
1770          SimulatorRuntimeFPFPCall target =
1771            reinterpret_cast<SimulatorRuntimeFPFPCall>(external);
1772          dresult = target(dval0, dval1);
1773          SetFpResult(dresult);
1774          break;
1775        }
1776        case ExternalReference::BUILTIN_FP_CALL: {
1777          SimulatorRuntimeFPCall target =
1778            reinterpret_cast<SimulatorRuntimeFPCall>(external);
1779          dresult = target(dval0);
1780          SetFpResult(dresult);
1781          break;
1782        }
1783        case ExternalReference::BUILTIN_FP_INT_CALL: {
1784          SimulatorRuntimeFPIntCall target =
1785            reinterpret_cast<SimulatorRuntimeFPIntCall>(external);
1786          dresult = target(dval0, ival);
1787          SetFpResult(dresult);
1788          break;
1789        }
1790        default:
1791          UNREACHABLE();
1792          break;
1793        }
1794        if (::v8::internal::FLAG_trace_sim || !stack_aligned) {
1795          switch (redirection->type()) {
1796          case ExternalReference::BUILTIN_COMPARE_CALL:
1797            PrintF("Returned %08x\n", static_cast<int32_t>(iresult));
1798            break;
1799          case ExternalReference::BUILTIN_FP_FP_CALL:
1800          case ExternalReference::BUILTIN_FP_CALL:
1801          case ExternalReference::BUILTIN_FP_INT_CALL:
1802            PrintF("Returned %f\n", dresult);
1803            break;
1804          default:
1805            UNREACHABLE();
1806            break;
1807          }
1808        }
1809      } else if (redirection->type() == ExternalReference::DIRECT_API_CALL) {
1810        if (::v8::internal::FLAG_trace_sim || !stack_aligned) {
1811          PrintF("Call to host function at %p args %08x",
1812              reinterpret_cast<void*>(external), arg0);
1813          if (!stack_aligned) {
1814            PrintF(" with unaligned stack %08x\n", get_register(sp));
1815          }
1816          PrintF("\n");
1817        }
1818        CHECK(stack_aligned);
1819        SimulatorRuntimeDirectApiCall target =
1820            reinterpret_cast<SimulatorRuntimeDirectApiCall>(external);
1821        target(arg0);
1822      } else if (
1823          redirection->type() == ExternalReference::PROFILING_API_CALL) {
1824        if (::v8::internal::FLAG_trace_sim || !stack_aligned) {
1825          PrintF("Call to host function at %p args %08x %08x",
1826              reinterpret_cast<void*>(external), arg0, arg1);
1827          if (!stack_aligned) {
1828            PrintF(" with unaligned stack %08x\n", get_register(sp));
1829          }
1830          PrintF("\n");
1831        }
1832        CHECK(stack_aligned);
1833        SimulatorRuntimeProfilingApiCall target =
1834            reinterpret_cast<SimulatorRuntimeProfilingApiCall>(external);
1835        target(arg0, arg1);
1836      } else if (
1837          redirection->type() == ExternalReference::DIRECT_GETTER_CALL) {
1838        if (::v8::internal::FLAG_trace_sim || !stack_aligned) {
1839          PrintF("Call to host function at %p args %08x %08x",
1840              reinterpret_cast<void*>(external), arg0, arg1);
1841          if (!stack_aligned) {
1842            PrintF(" with unaligned stack %08x\n", get_register(sp));
1843          }
1844          PrintF("\n");
1845        }
1846        CHECK(stack_aligned);
1847        SimulatorRuntimeDirectGetterCall target =
1848            reinterpret_cast<SimulatorRuntimeDirectGetterCall>(external);
1849        target(arg0, arg1);
1850      } else if (
1851          redirection->type() == ExternalReference::PROFILING_GETTER_CALL) {
1852        if (::v8::internal::FLAG_trace_sim || !stack_aligned) {
1853          PrintF("Call to host function at %p args %08x %08x %08x",
1854              reinterpret_cast<void*>(external), arg0, arg1, arg2);
1855          if (!stack_aligned) {
1856            PrintF(" with unaligned stack %08x\n", get_register(sp));
1857          }
1858          PrintF("\n");
1859        }
1860        CHECK(stack_aligned);
1861        SimulatorRuntimeProfilingGetterCall target =
1862            reinterpret_cast<SimulatorRuntimeProfilingGetterCall>(
1863                external);
1864        target(arg0, arg1, arg2);
1865      } else {
1866        // builtin call.
1867        ASSERT(redirection->type() == ExternalReference::BUILTIN_CALL);
1868        SimulatorRuntimeCall target =
1869            reinterpret_cast<SimulatorRuntimeCall>(external);
1870        if (::v8::internal::FLAG_trace_sim || !stack_aligned) {
1871          PrintF(
1872              "Call to host function at %p "
1873              "args %08x, %08x, %08x, %08x, %08x, %08x",
1874              FUNCTION_ADDR(target),
1875              arg0,
1876              arg1,
1877              arg2,
1878              arg3,
1879              arg4,
1880              arg5);
1881          if (!stack_aligned) {
1882            PrintF(" with unaligned stack %08x\n", get_register(sp));
1883          }
1884          PrintF("\n");
1885        }
1886        CHECK(stack_aligned);
1887        int64_t result = target(arg0, arg1, arg2, arg3, arg4, arg5);
1888        int32_t lo_res = static_cast<int32_t>(result);
1889        int32_t hi_res = static_cast<int32_t>(result >> 32);
1890        if (::v8::internal::FLAG_trace_sim) {
1891          PrintF("Returned %08x\n", lo_res);
1892        }
1893        set_register(r0, lo_res);
1894        set_register(r1, hi_res);
1895      }
1896      set_register(lr, saved_lr);
1897      set_pc(get_register(lr));
1898      break;
1899    }
1900    case kBreakpoint: {
1901      ArmDebugger dbg(this);
1902      dbg.Debug();
1903      break;
1904    }
1905    // stop uses all codes greater than 1 << 23.
1906    default: {
1907      if (svc >= (1 << 23)) {
1908        uint32_t code = svc & kStopCodeMask;
1909        if (isWatchedStop(code)) {
1910          IncreaseStopCounter(code);
1911        }
1912        // Stop if it is enabled, otherwise go on jumping over the stop
1913        // and the message address.
1914        if (isEnabledStop(code)) {
1915          ArmDebugger dbg(this);
1916          dbg.Stop(instr);
1917        } else {
1918          set_pc(get_pc() + 2 * Instruction::kInstrSize);
1919        }
1920      } else {
1921        // This is not a valid svc code.
1922        UNREACHABLE();
1923        break;
1924      }
1925    }
1926  }
1927}
1928
1929
1930double Simulator::canonicalizeNaN(double value) {
1931  return (FPSCR_default_NaN_mode_ && std::isnan(value)) ?
1932    FixedDoubleArray::canonical_not_the_hole_nan_as_double() : value;
1933}
1934
1935
1936// Stop helper functions.
1937bool Simulator::isStopInstruction(Instruction* instr) {
1938  return (instr->Bits(27, 24) == 0xF) && (instr->SvcValue() >= kStopCode);
1939}
1940
1941
1942bool Simulator::isWatchedStop(uint32_t code) {
1943  ASSERT(code <= kMaxStopCode);
1944  return code < kNumOfWatchedStops;
1945}
1946
1947
1948bool Simulator::isEnabledStop(uint32_t code) {
1949  ASSERT(code <= kMaxStopCode);
1950  // Unwatched stops are always enabled.
1951  return !isWatchedStop(code) ||
1952    !(watched_stops_[code].count & kStopDisabledBit);
1953}
1954
1955
1956void Simulator::EnableStop(uint32_t code) {
1957  ASSERT(isWatchedStop(code));
1958  if (!isEnabledStop(code)) {
1959    watched_stops_[code].count &= ~kStopDisabledBit;
1960  }
1961}
1962
1963
1964void Simulator::DisableStop(uint32_t code) {
1965  ASSERT(isWatchedStop(code));
1966  if (isEnabledStop(code)) {
1967    watched_stops_[code].count |= kStopDisabledBit;
1968  }
1969}
1970
1971
1972void Simulator::IncreaseStopCounter(uint32_t code) {
1973  ASSERT(code <= kMaxStopCode);
1974  ASSERT(isWatchedStop(code));
1975  if ((watched_stops_[code].count & ~(1 << 31)) == 0x7fffffff) {
1976    PrintF("Stop counter for code %i has overflowed.\n"
1977           "Enabling this code and reseting the counter to 0.\n", code);
1978    watched_stops_[code].count = 0;
1979    EnableStop(code);
1980  } else {
1981    watched_stops_[code].count++;
1982  }
1983}
1984
1985
1986// Print a stop status.
1987void Simulator::PrintStopInfo(uint32_t code) {
1988  ASSERT(code <= kMaxStopCode);
1989  if (!isWatchedStop(code)) {
1990    PrintF("Stop not watched.");
1991  } else {
1992    const char* state = isEnabledStop(code) ? "Enabled" : "Disabled";
1993    int32_t count = watched_stops_[code].count & ~kStopDisabledBit;
1994    // Don't print the state of unused breakpoints.
1995    if (count != 0) {
1996      if (watched_stops_[code].desc) {
1997        PrintF("stop %i - 0x%x: \t%s, \tcounter = %i, \t%s\n",
1998               code, code, state, count, watched_stops_[code].desc);
1999      } else {
2000        PrintF("stop %i - 0x%x: \t%s, \tcounter = %i\n",
2001               code, code, state, count);
2002      }
2003    }
2004  }
2005}
2006
2007
2008// Handle execution based on instruction types.
2009
2010// Instruction types 0 and 1 are both rolled into one function because they
2011// only differ in the handling of the shifter_operand.
2012void Simulator::DecodeType01(Instruction* instr) {
2013  int type = instr->TypeValue();
2014  if ((type == 0) && instr->IsSpecialType0()) {
2015    // multiply instruction or extra loads and stores
2016    if (instr->Bits(7, 4) == 9) {
2017      if (instr->Bit(24) == 0) {
2018        // Raw field decoding here. Multiply instructions have their Rd in
2019        // funny places.
2020        int rn = instr->RnValue();
2021        int rm = instr->RmValue();
2022        int rs = instr->RsValue();
2023        int32_t rs_val = get_register(rs);
2024        int32_t rm_val = get_register(rm);
2025        if (instr->Bit(23) == 0) {
2026          if (instr->Bit(21) == 0) {
2027            // The MUL instruction description (A 4.1.33) refers to Rd as being
2028            // the destination for the operation, but it confusingly uses the
2029            // Rn field to encode it.
2030            // Format(instr, "mul'cond's 'rn, 'rm, 'rs");
2031            int rd = rn;  // Remap the rn field to the Rd register.
2032            int32_t alu_out = rm_val * rs_val;
2033            set_register(rd, alu_out);
2034            if (instr->HasS()) {
2035              SetNZFlags(alu_out);
2036            }
2037          } else {
2038            int rd = instr->RdValue();
2039            int32_t acc_value = get_register(rd);
2040            if (instr->Bit(22) == 0) {
2041              // The MLA instruction description (A 4.1.28) refers to the order
2042              // of registers as "Rd, Rm, Rs, Rn". But confusingly it uses the
2043              // Rn field to encode the Rd register and the Rd field to encode
2044              // the Rn register.
2045              // Format(instr, "mla'cond's 'rn, 'rm, 'rs, 'rd");
2046              int32_t mul_out = rm_val * rs_val;
2047              int32_t result = acc_value + mul_out;
2048              set_register(rn, result);
2049            } else {
2050              // Format(instr, "mls'cond's 'rn, 'rm, 'rs, 'rd");
2051              int32_t mul_out = rm_val * rs_val;
2052              int32_t result = acc_value - mul_out;
2053              set_register(rn, result);
2054            }
2055          }
2056        } else {
2057          // The signed/long multiply instructions use the terms RdHi and RdLo
2058          // when referring to the target registers. They are mapped to the Rn
2059          // and Rd fields as follows:
2060          // RdLo == Rd
2061          // RdHi == Rn (This is confusingly stored in variable rd here
2062          //             because the mul instruction from above uses the
2063          //             Rn field to encode the Rd register. Good luck figuring
2064          //             this out without reading the ARM instruction manual
2065          //             at a very detailed level.)
2066          // Format(instr, "'um'al'cond's 'rd, 'rn, 'rs, 'rm");
2067          int rd_hi = rn;  // Remap the rn field to the RdHi register.
2068          int rd_lo = instr->RdValue();
2069          int32_t hi_res = 0;
2070          int32_t lo_res = 0;
2071          if (instr->Bit(22) == 1) {
2072            int64_t left_op  = static_cast<int32_t>(rm_val);
2073            int64_t right_op = static_cast<int32_t>(rs_val);
2074            uint64_t result = left_op * right_op;
2075            hi_res = static_cast<int32_t>(result >> 32);
2076            lo_res = static_cast<int32_t>(result & 0xffffffff);
2077          } else {
2078            // unsigned multiply
2079            uint64_t left_op  = static_cast<uint32_t>(rm_val);
2080            uint64_t right_op = static_cast<uint32_t>(rs_val);
2081            uint64_t result = left_op * right_op;
2082            hi_res = static_cast<int32_t>(result >> 32);
2083            lo_res = static_cast<int32_t>(result & 0xffffffff);
2084          }
2085          set_register(rd_lo, lo_res);
2086          set_register(rd_hi, hi_res);
2087          if (instr->HasS()) {
2088            UNIMPLEMENTED();
2089          }
2090        }
2091      } else {
2092        UNIMPLEMENTED();  // Not used by V8.
2093      }
2094    } else {
2095      // extra load/store instructions
2096      int rd = instr->RdValue();
2097      int rn = instr->RnValue();
2098      int32_t rn_val = get_register(rn);
2099      int32_t addr = 0;
2100      if (instr->Bit(22) == 0) {
2101        int rm = instr->RmValue();
2102        int32_t rm_val = get_register(rm);
2103        switch (instr->PUField()) {
2104          case da_x: {
2105            // Format(instr, "'memop'cond'sign'h 'rd, ['rn], -'rm");
2106            ASSERT(!instr->HasW());
2107            addr = rn_val;
2108            rn_val -= rm_val;
2109            set_register(rn, rn_val);
2110            break;
2111          }
2112          case ia_x: {
2113            // Format(instr, "'memop'cond'sign'h 'rd, ['rn], +'rm");
2114            ASSERT(!instr->HasW());
2115            addr = rn_val;
2116            rn_val += rm_val;
2117            set_register(rn, rn_val);
2118            break;
2119          }
2120          case db_x: {
2121            // Format(instr, "'memop'cond'sign'h 'rd, ['rn, -'rm]'w");
2122            rn_val -= rm_val;
2123            addr = rn_val;
2124            if (instr->HasW()) {
2125              set_register(rn, rn_val);
2126            }
2127            break;
2128          }
2129          case ib_x: {
2130            // Format(instr, "'memop'cond'sign'h 'rd, ['rn, +'rm]'w");
2131            rn_val += rm_val;
2132            addr = rn_val;
2133            if (instr->HasW()) {
2134              set_register(rn, rn_val);
2135            }
2136            break;
2137          }
2138          default: {
2139            // The PU field is a 2-bit field.
2140            UNREACHABLE();
2141            break;
2142          }
2143        }
2144      } else {
2145        int32_t imm_val = (instr->ImmedHValue() << 4) | instr->ImmedLValue();
2146        switch (instr->PUField()) {
2147          case da_x: {
2148            // Format(instr, "'memop'cond'sign'h 'rd, ['rn], #-'off8");
2149            ASSERT(!instr->HasW());
2150            addr = rn_val;
2151            rn_val -= imm_val;
2152            set_register(rn, rn_val);
2153            break;
2154          }
2155          case ia_x: {
2156            // Format(instr, "'memop'cond'sign'h 'rd, ['rn], #+'off8");
2157            ASSERT(!instr->HasW());
2158            addr = rn_val;
2159            rn_val += imm_val;
2160            set_register(rn, rn_val);
2161            break;
2162          }
2163          case db_x: {
2164            // Format(instr, "'memop'cond'sign'h 'rd, ['rn, #-'off8]'w");
2165            rn_val -= imm_val;
2166            addr = rn_val;
2167            if (instr->HasW()) {
2168              set_register(rn, rn_val);
2169            }
2170            break;
2171          }
2172          case ib_x: {
2173            // Format(instr, "'memop'cond'sign'h 'rd, ['rn, #+'off8]'w");
2174            rn_val += imm_val;
2175            addr = rn_val;
2176            if (instr->HasW()) {
2177              set_register(rn, rn_val);
2178            }
2179            break;
2180          }
2181          default: {
2182            // The PU field is a 2-bit field.
2183            UNREACHABLE();
2184            break;
2185          }
2186        }
2187      }
2188      if (((instr->Bits(7, 4) & 0xd) == 0xd) && (instr->Bit(20) == 0)) {
2189        ASSERT((rd % 2) == 0);
2190        if (instr->HasH()) {
2191          // The strd instruction.
2192          int32_t value1 = get_register(rd);
2193          int32_t value2 = get_register(rd+1);
2194          WriteDW(addr, value1, value2);
2195        } else {
2196          // The ldrd instruction.
2197          int* rn_data = ReadDW(addr);
2198          set_dw_register(rd, rn_data);
2199        }
2200      } else if (instr->HasH()) {
2201        if (instr->HasSign()) {
2202          if (instr->HasL()) {
2203            int16_t val = ReadH(addr, instr);
2204            set_register(rd, val);
2205          } else {
2206            int16_t val = get_register(rd);
2207            WriteH(addr, val, instr);
2208          }
2209        } else {
2210          if (instr->HasL()) {
2211            uint16_t val = ReadHU(addr, instr);
2212            set_register(rd, val);
2213          } else {
2214            uint16_t val = get_register(rd);
2215            WriteH(addr, val, instr);
2216          }
2217        }
2218      } else {
2219        // signed byte loads
2220        ASSERT(instr->HasSign());
2221        ASSERT(instr->HasL());
2222        int8_t val = ReadB(addr);
2223        set_register(rd, val);
2224      }
2225      return;
2226    }
2227  } else if ((type == 0) && instr->IsMiscType0()) {
2228    if (instr->Bits(22, 21) == 1) {
2229      int rm = instr->RmValue();
2230      switch (instr->BitField(7, 4)) {
2231        case BX:
2232          set_pc(get_register(rm));
2233          break;
2234        case BLX: {
2235          uint32_t old_pc = get_pc();
2236          set_pc(get_register(rm));
2237          set_register(lr, old_pc + Instruction::kInstrSize);
2238          break;
2239        }
2240        case BKPT: {
2241          ArmDebugger dbg(this);
2242          PrintF("Simulator hit BKPT.\n");
2243          dbg.Debug();
2244          break;
2245        }
2246        default:
2247          UNIMPLEMENTED();
2248      }
2249    } else if (instr->Bits(22, 21) == 3) {
2250      int rm = instr->RmValue();
2251      int rd = instr->RdValue();
2252      switch (instr->BitField(7, 4)) {
2253        case CLZ: {
2254          uint32_t bits = get_register(rm);
2255          int leading_zeros = 0;
2256          if (bits == 0) {
2257            leading_zeros = 32;
2258          } else {
2259            while ((bits & 0x80000000u) == 0) {
2260              bits <<= 1;
2261              leading_zeros++;
2262            }
2263          }
2264          set_register(rd, leading_zeros);
2265          break;
2266        }
2267        default:
2268          UNIMPLEMENTED();
2269      }
2270    } else {
2271      PrintF("%08x\n", instr->InstructionBits());
2272      UNIMPLEMENTED();
2273    }
2274  } else if ((type == 1) && instr->IsNopType1()) {
2275    // NOP.
2276  } else {
2277    int rd = instr->RdValue();
2278    int rn = instr->RnValue();
2279    int32_t rn_val = get_register(rn);
2280    int32_t shifter_operand = 0;
2281    bool shifter_carry_out = 0;
2282    if (type == 0) {
2283      shifter_operand = GetShiftRm(instr, &shifter_carry_out);
2284    } else {
2285      ASSERT(instr->TypeValue() == 1);
2286      shifter_operand = GetImm(instr, &shifter_carry_out);
2287    }
2288    int32_t alu_out;
2289
2290    switch (instr->OpcodeField()) {
2291      case AND: {
2292        // Format(instr, "and'cond's 'rd, 'rn, 'shift_rm");
2293        // Format(instr, "and'cond's 'rd, 'rn, 'imm");
2294        alu_out = rn_val & shifter_operand;
2295        set_register(rd, alu_out);
2296        if (instr->HasS()) {
2297          SetNZFlags(alu_out);
2298          SetCFlag(shifter_carry_out);
2299        }
2300        break;
2301      }
2302
2303      case EOR: {
2304        // Format(instr, "eor'cond's 'rd, 'rn, 'shift_rm");
2305        // Format(instr, "eor'cond's 'rd, 'rn, 'imm");
2306        alu_out = rn_val ^ shifter_operand;
2307        set_register(rd, alu_out);
2308        if (instr->HasS()) {
2309          SetNZFlags(alu_out);
2310          SetCFlag(shifter_carry_out);
2311        }
2312        break;
2313      }
2314
2315      case SUB: {
2316        // Format(instr, "sub'cond's 'rd, 'rn, 'shift_rm");
2317        // Format(instr, "sub'cond's 'rd, 'rn, 'imm");
2318        alu_out = rn_val - shifter_operand;
2319        set_register(rd, alu_out);
2320        if (instr->HasS()) {
2321          SetNZFlags(alu_out);
2322          SetCFlag(!BorrowFrom(rn_val, shifter_operand));
2323          SetVFlag(OverflowFrom(alu_out, rn_val, shifter_operand, false));
2324        }
2325        break;
2326      }
2327
2328      case RSB: {
2329        // Format(instr, "rsb'cond's 'rd, 'rn, 'shift_rm");
2330        // Format(instr, "rsb'cond's 'rd, 'rn, 'imm");
2331        alu_out = shifter_operand - rn_val;
2332        set_register(rd, alu_out);
2333        if (instr->HasS()) {
2334          SetNZFlags(alu_out);
2335          SetCFlag(!BorrowFrom(shifter_operand, rn_val));
2336          SetVFlag(OverflowFrom(alu_out, shifter_operand, rn_val, false));
2337        }
2338        break;
2339      }
2340
2341      case ADD: {
2342        // Format(instr, "add'cond's 'rd, 'rn, 'shift_rm");
2343        // Format(instr, "add'cond's 'rd, 'rn, 'imm");
2344        alu_out = rn_val + shifter_operand;
2345        set_register(rd, alu_out);
2346        if (instr->HasS()) {
2347          SetNZFlags(alu_out);
2348          SetCFlag(CarryFrom(rn_val, shifter_operand));
2349          SetVFlag(OverflowFrom(alu_out, rn_val, shifter_operand, true));
2350        }
2351        break;
2352      }
2353
2354      case ADC: {
2355        // Format(instr, "adc'cond's 'rd, 'rn, 'shift_rm");
2356        // Format(instr, "adc'cond's 'rd, 'rn, 'imm");
2357        alu_out = rn_val + shifter_operand + GetCarry();
2358        set_register(rd, alu_out);
2359        if (instr->HasS()) {
2360          SetNZFlags(alu_out);
2361          SetCFlag(CarryFrom(rn_val, shifter_operand, GetCarry()));
2362          SetVFlag(OverflowFrom(alu_out, rn_val, shifter_operand, true));
2363        }
2364        break;
2365      }
2366
2367      case SBC: {
2368        Format(instr, "sbc'cond's 'rd, 'rn, 'shift_rm");
2369        Format(instr, "sbc'cond's 'rd, 'rn, 'imm");
2370        break;
2371      }
2372
2373      case RSC: {
2374        Format(instr, "rsc'cond's 'rd, 'rn, 'shift_rm");
2375        Format(instr, "rsc'cond's 'rd, 'rn, 'imm");
2376        break;
2377      }
2378
2379      case TST: {
2380        if (instr->HasS()) {
2381          // Format(instr, "tst'cond 'rn, 'shift_rm");
2382          // Format(instr, "tst'cond 'rn, 'imm");
2383          alu_out = rn_val & shifter_operand;
2384          SetNZFlags(alu_out);
2385          SetCFlag(shifter_carry_out);
2386        } else {
2387          // Format(instr, "movw'cond 'rd, 'imm").
2388          alu_out = instr->ImmedMovwMovtValue();
2389          set_register(rd, alu_out);
2390        }
2391        break;
2392      }
2393
2394      case TEQ: {
2395        if (instr->HasS()) {
2396          // Format(instr, "teq'cond 'rn, 'shift_rm");
2397          // Format(instr, "teq'cond 'rn, 'imm");
2398          alu_out = rn_val ^ shifter_operand;
2399          SetNZFlags(alu_out);
2400          SetCFlag(shifter_carry_out);
2401        } else {
2402          // Other instructions matching this pattern are handled in the
2403          // miscellaneous instructions part above.
2404          UNREACHABLE();
2405        }
2406        break;
2407      }
2408
2409      case CMP: {
2410        if (instr->HasS()) {
2411          // Format(instr, "cmp'cond 'rn, 'shift_rm");
2412          // Format(instr, "cmp'cond 'rn, 'imm");
2413          alu_out = rn_val - shifter_operand;
2414          SetNZFlags(alu_out);
2415          SetCFlag(!BorrowFrom(rn_val, shifter_operand));
2416          SetVFlag(OverflowFrom(alu_out, rn_val, shifter_operand, false));
2417        } else {
2418          // Format(instr, "movt'cond 'rd, 'imm").
2419          alu_out = (get_register(rd) & 0xffff) |
2420              (instr->ImmedMovwMovtValue() << 16);
2421          set_register(rd, alu_out);
2422        }
2423        break;
2424      }
2425
2426      case CMN: {
2427        if (instr->HasS()) {
2428          // Format(instr, "cmn'cond 'rn, 'shift_rm");
2429          // Format(instr, "cmn'cond 'rn, 'imm");
2430          alu_out = rn_val + shifter_operand;
2431          SetNZFlags(alu_out);
2432          SetCFlag(CarryFrom(rn_val, shifter_operand));
2433          SetVFlag(OverflowFrom(alu_out, rn_val, shifter_operand, true));
2434        } else {
2435          // Other instructions matching this pattern are handled in the
2436          // miscellaneous instructions part above.
2437          UNREACHABLE();
2438        }
2439        break;
2440      }
2441
2442      case ORR: {
2443        // Format(instr, "orr'cond's 'rd, 'rn, 'shift_rm");
2444        // Format(instr, "orr'cond's 'rd, 'rn, 'imm");
2445        alu_out = rn_val | shifter_operand;
2446        set_register(rd, alu_out);
2447        if (instr->HasS()) {
2448          SetNZFlags(alu_out);
2449          SetCFlag(shifter_carry_out);
2450        }
2451        break;
2452      }
2453
2454      case MOV: {
2455        // Format(instr, "mov'cond's 'rd, 'shift_rm");
2456        // Format(instr, "mov'cond's 'rd, 'imm");
2457        alu_out = shifter_operand;
2458        set_register(rd, alu_out);
2459        if (instr->HasS()) {
2460          SetNZFlags(alu_out);
2461          SetCFlag(shifter_carry_out);
2462        }
2463        break;
2464      }
2465
2466      case BIC: {
2467        // Format(instr, "bic'cond's 'rd, 'rn, 'shift_rm");
2468        // Format(instr, "bic'cond's 'rd, 'rn, 'imm");
2469        alu_out = rn_val & ~shifter_operand;
2470        set_register(rd, alu_out);
2471        if (instr->HasS()) {
2472          SetNZFlags(alu_out);
2473          SetCFlag(shifter_carry_out);
2474        }
2475        break;
2476      }
2477
2478      case MVN: {
2479        // Format(instr, "mvn'cond's 'rd, 'shift_rm");
2480        // Format(instr, "mvn'cond's 'rd, 'imm");
2481        alu_out = ~shifter_operand;
2482        set_register(rd, alu_out);
2483        if (instr->HasS()) {
2484          SetNZFlags(alu_out);
2485          SetCFlag(shifter_carry_out);
2486        }
2487        break;
2488      }
2489
2490      default: {
2491        UNREACHABLE();
2492        break;
2493      }
2494    }
2495  }
2496}
2497
2498
2499void Simulator::DecodeType2(Instruction* instr) {
2500  int rd = instr->RdValue();
2501  int rn = instr->RnValue();
2502  int32_t rn_val = get_register(rn);
2503  int32_t im_val = instr->Offset12Value();
2504  int32_t addr = 0;
2505  switch (instr->PUField()) {
2506    case da_x: {
2507      // Format(instr, "'memop'cond'b 'rd, ['rn], #-'off12");
2508      ASSERT(!instr->HasW());
2509      addr = rn_val;
2510      rn_val -= im_val;
2511      set_register(rn, rn_val);
2512      break;
2513    }
2514    case ia_x: {
2515      // Format(instr, "'memop'cond'b 'rd, ['rn], #+'off12");
2516      ASSERT(!instr->HasW());
2517      addr = rn_val;
2518      rn_val += im_val;
2519      set_register(rn, rn_val);
2520      break;
2521    }
2522    case db_x: {
2523      // Format(instr, "'memop'cond'b 'rd, ['rn, #-'off12]'w");
2524      rn_val -= im_val;
2525      addr = rn_val;
2526      if (instr->HasW()) {
2527        set_register(rn, rn_val);
2528      }
2529      break;
2530    }
2531    case ib_x: {
2532      // Format(instr, "'memop'cond'b 'rd, ['rn, #+'off12]'w");
2533      rn_val += im_val;
2534      addr = rn_val;
2535      if (instr->HasW()) {
2536        set_register(rn, rn_val);
2537      }
2538      break;
2539    }
2540    default: {
2541      UNREACHABLE();
2542      break;
2543    }
2544  }
2545  if (instr->HasB()) {
2546    if (instr->HasL()) {
2547      byte val = ReadBU(addr);
2548      set_register(rd, val);
2549    } else {
2550      byte val = get_register(rd);
2551      WriteB(addr, val);
2552    }
2553  } else {
2554    if (instr->HasL()) {
2555      set_register(rd, ReadW(addr, instr));
2556    } else {
2557      WriteW(addr, get_register(rd), instr);
2558    }
2559  }
2560}
2561
2562
2563void Simulator::DecodeType3(Instruction* instr) {
2564  int rd = instr->RdValue();
2565  int rn = instr->RnValue();
2566  int32_t rn_val = get_register(rn);
2567  bool shifter_carry_out = 0;
2568  int32_t shifter_operand = GetShiftRm(instr, &shifter_carry_out);
2569  int32_t addr = 0;
2570  switch (instr->PUField()) {
2571    case da_x: {
2572      ASSERT(!instr->HasW());
2573      Format(instr, "'memop'cond'b 'rd, ['rn], -'shift_rm");
2574      UNIMPLEMENTED();
2575      break;
2576    }
2577    case ia_x: {
2578      if (instr->Bit(4) == 0) {
2579        // Memop.
2580      } else {
2581        if (instr->Bit(5) == 0) {
2582          switch (instr->Bits(22, 21)) {
2583            case 0:
2584              if (instr->Bit(20) == 0) {
2585                if (instr->Bit(6) == 0) {
2586                  // Pkhbt.
2587                  uint32_t rn_val = get_register(rn);
2588                  uint32_t rm_val = get_register(instr->RmValue());
2589                  int32_t shift = instr->Bits(11, 7);
2590                  rm_val <<= shift;
2591                  set_register(rd, (rn_val & 0xFFFF) | (rm_val & 0xFFFF0000U));
2592                } else {
2593                  // Pkhtb.
2594                  uint32_t rn_val = get_register(rn);
2595                  int32_t rm_val = get_register(instr->RmValue());
2596                  int32_t shift = instr->Bits(11, 7);
2597                  if (shift == 0) {
2598                    shift = 32;
2599                  }
2600                  rm_val >>= shift;
2601                  set_register(rd, (rn_val & 0xFFFF0000U) | (rm_val & 0xFFFF));
2602                }
2603              } else {
2604                UNIMPLEMENTED();
2605              }
2606              break;
2607            case 1:
2608              UNIMPLEMENTED();
2609              break;
2610            case 2:
2611              UNIMPLEMENTED();
2612              break;
2613            case 3: {
2614              // Usat.
2615              int32_t sat_pos = instr->Bits(20, 16);
2616              int32_t sat_val = (1 << sat_pos) - 1;
2617              int32_t shift = instr->Bits(11, 7);
2618              int32_t shift_type = instr->Bit(6);
2619              int32_t rm_val = get_register(instr->RmValue());
2620              if (shift_type == 0) {  // LSL
2621                rm_val <<= shift;
2622              } else {  // ASR
2623                rm_val >>= shift;
2624              }
2625              // If saturation occurs, the Q flag should be set in the CPSR.
2626              // There is no Q flag yet, and no instruction (MRS) to read the
2627              // CPSR directly.
2628              if (rm_val > sat_val) {
2629                rm_val = sat_val;
2630              } else if (rm_val < 0) {
2631                rm_val = 0;
2632              }
2633              set_register(rd, rm_val);
2634              break;
2635            }
2636          }
2637        } else {
2638          switch (instr->Bits(22, 21)) {
2639            case 0:
2640              UNIMPLEMENTED();
2641              break;
2642            case 1:
2643              UNIMPLEMENTED();
2644              break;
2645            case 2:
2646              if ((instr->Bit(20) == 0) && (instr->Bits(9, 6) == 1)) {
2647                if (instr->Bits(19, 16) == 0xF) {
2648                  // Uxtb16.
2649                  uint32_t rm_val = get_register(instr->RmValue());
2650                  int32_t rotate = instr->Bits(11, 10);
2651                  switch (rotate) {
2652                    case 0:
2653                      break;
2654                    case 1:
2655                      rm_val = (rm_val >> 8) | (rm_val << 24);
2656                      break;
2657                    case 2:
2658                      rm_val = (rm_val >> 16) | (rm_val << 16);
2659                      break;
2660                    case 3:
2661                      rm_val = (rm_val >> 24) | (rm_val << 8);
2662                      break;
2663                  }
2664                  set_register(rd,
2665                               (rm_val & 0xFF) | (rm_val & 0xFF0000));
2666                } else {
2667                  UNIMPLEMENTED();
2668                }
2669              } else {
2670                UNIMPLEMENTED();
2671              }
2672              break;
2673            case 3:
2674              if ((instr->Bit(20) == 0) && (instr->Bits(9, 6) == 1)) {
2675                if (instr->Bits(19, 16) == 0xF) {
2676                  // Uxtb.
2677                  uint32_t rm_val = get_register(instr->RmValue());
2678                  int32_t rotate = instr->Bits(11, 10);
2679                  switch (rotate) {
2680                    case 0:
2681                      break;
2682                    case 1:
2683                      rm_val = (rm_val >> 8) | (rm_val << 24);
2684                      break;
2685                    case 2:
2686                      rm_val = (rm_val >> 16) | (rm_val << 16);
2687                      break;
2688                    case 3:
2689                      rm_val = (rm_val >> 24) | (rm_val << 8);
2690                      break;
2691                  }
2692                  set_register(rd, (rm_val & 0xFF));
2693                } else {
2694                  // Uxtab.
2695                  uint32_t rn_val = get_register(rn);
2696                  uint32_t rm_val = get_register(instr->RmValue());
2697                  int32_t rotate = instr->Bits(11, 10);
2698                  switch (rotate) {
2699                    case 0:
2700                      break;
2701                    case 1:
2702                      rm_val = (rm_val >> 8) | (rm_val << 24);
2703                      break;
2704                    case 2:
2705                      rm_val = (rm_val >> 16) | (rm_val << 16);
2706                      break;
2707                    case 3:
2708                      rm_val = (rm_val >> 24) | (rm_val << 8);
2709                      break;
2710                  }
2711                  set_register(rd, rn_val + (rm_val & 0xFF));
2712                }
2713              } else {
2714                UNIMPLEMENTED();
2715              }
2716              break;
2717          }
2718        }
2719        return;
2720      }
2721      break;
2722    }
2723    case db_x: {
2724      if (FLAG_enable_sudiv) {
2725        if (!instr->HasW()) {
2726          if (instr->Bits(5, 4) == 0x1) {
2727             if ((instr->Bit(22) == 0x0) && (instr->Bit(20) == 0x1)) {
2728               // sdiv (in V8 notation matching ARM ISA format) rn = rm/rs
2729               // Format(instr, "'sdiv'cond'b 'rn, 'rm, 'rs);
2730               int rm = instr->RmValue();
2731               int32_t rm_val = get_register(rm);
2732               int rs = instr->RsValue();
2733               int32_t rs_val = get_register(rs);
2734               int32_t ret_val = 0;
2735               ASSERT(rs_val != 0);
2736               ret_val = rm_val/rs_val;
2737               set_register(rn, ret_val);
2738               return;
2739             }
2740           }
2741         }
2742       }
2743      // Format(instr, "'memop'cond'b 'rd, ['rn, -'shift_rm]'w");
2744      addr = rn_val - shifter_operand;
2745      if (instr->HasW()) {
2746        set_register(rn, addr);
2747      }
2748      break;
2749    }
2750    case ib_x: {
2751      if (instr->HasW() && (instr->Bits(6, 4) == 0x5)) {
2752        uint32_t widthminus1 = static_cast<uint32_t>(instr->Bits(20, 16));
2753        uint32_t lsbit = static_cast<uint32_t>(instr->Bits(11, 7));
2754        uint32_t msbit = widthminus1 + lsbit;
2755        if (msbit <= 31) {
2756          if (instr->Bit(22)) {
2757            // ubfx - unsigned bitfield extract.
2758            uint32_t rm_val =
2759                static_cast<uint32_t>(get_register(instr->RmValue()));
2760            uint32_t extr_val = rm_val << (31 - msbit);
2761            extr_val = extr_val >> (31 - widthminus1);
2762            set_register(instr->RdValue(), extr_val);
2763          } else {
2764            // sbfx - signed bitfield extract.
2765            int32_t rm_val = get_register(instr->RmValue());
2766            int32_t extr_val = rm_val << (31 - msbit);
2767            extr_val = extr_val >> (31 - widthminus1);
2768            set_register(instr->RdValue(), extr_val);
2769          }
2770        } else {
2771          UNREACHABLE();
2772        }
2773        return;
2774      } else if (!instr->HasW() && (instr->Bits(6, 4) == 0x1)) {
2775        uint32_t lsbit = static_cast<uint32_t>(instr->Bits(11, 7));
2776        uint32_t msbit = static_cast<uint32_t>(instr->Bits(20, 16));
2777        if (msbit >= lsbit) {
2778          // bfc or bfi - bitfield clear/insert.
2779          uint32_t rd_val =
2780              static_cast<uint32_t>(get_register(instr->RdValue()));
2781          uint32_t bitcount = msbit - lsbit + 1;
2782          uint32_t mask = (1 << bitcount) - 1;
2783          rd_val &= ~(mask << lsbit);
2784          if (instr->RmValue() != 15) {
2785            // bfi - bitfield insert.
2786            uint32_t rm_val =
2787                static_cast<uint32_t>(get_register(instr->RmValue()));
2788            rm_val &= mask;
2789            rd_val |= rm_val << lsbit;
2790          }
2791          set_register(instr->RdValue(), rd_val);
2792        } else {
2793          UNREACHABLE();
2794        }
2795        return;
2796      } else {
2797        // Format(instr, "'memop'cond'b 'rd, ['rn, +'shift_rm]'w");
2798        addr = rn_val + shifter_operand;
2799        if (instr->HasW()) {
2800          set_register(rn, addr);
2801        }
2802      }
2803      break;
2804    }
2805    default: {
2806      UNREACHABLE();
2807      break;
2808    }
2809  }
2810  if (instr->HasB()) {
2811    if (instr->HasL()) {
2812      uint8_t byte = ReadB(addr);
2813      set_register(rd, byte);
2814    } else {
2815      uint8_t byte = get_register(rd);
2816      WriteB(addr, byte);
2817    }
2818  } else {
2819    if (instr->HasL()) {
2820      set_register(rd, ReadW(addr, instr));
2821    } else {
2822      WriteW(addr, get_register(rd), instr);
2823    }
2824  }
2825}
2826
2827
2828void Simulator::DecodeType4(Instruction* instr) {
2829  ASSERT(instr->Bit(22) == 0);  // only allowed to be set in privileged mode
2830  if (instr->HasL()) {
2831    // Format(instr, "ldm'cond'pu 'rn'w, 'rlist");
2832    HandleRList(instr, true);
2833  } else {
2834    // Format(instr, "stm'cond'pu 'rn'w, 'rlist");
2835    HandleRList(instr, false);
2836  }
2837}
2838
2839
2840void Simulator::DecodeType5(Instruction* instr) {
2841  // Format(instr, "b'l'cond 'target");
2842  int off = (instr->SImmed24Value() << 2);
2843  intptr_t pc_address = get_pc();
2844  if (instr->HasLink()) {
2845    set_register(lr, pc_address + Instruction::kInstrSize);
2846  }
2847  int pc_reg = get_register(pc);
2848  set_pc(pc_reg + off);
2849}
2850
2851
2852void Simulator::DecodeType6(Instruction* instr) {
2853  DecodeType6CoprocessorIns(instr);
2854}
2855
2856
2857void Simulator::DecodeType7(Instruction* instr) {
2858  if (instr->Bit(24) == 1) {
2859    SoftwareInterrupt(instr);
2860  } else {
2861    DecodeTypeVFP(instr);
2862  }
2863}
2864
2865
2866// void Simulator::DecodeTypeVFP(Instruction* instr)
2867// The Following ARMv7 VFPv instructions are currently supported.
2868// vmov :Sn = Rt
2869// vmov :Rt = Sn
2870// vcvt: Dd = Sm
2871// vcvt: Sd = Dm
2872// vcvt.f64.s32 Dd, Dd, #<fbits>
2873// Dd = vabs(Dm)
2874// Dd = vneg(Dm)
2875// Dd = vadd(Dn, Dm)
2876// Dd = vsub(Dn, Dm)
2877// Dd = vmul(Dn, Dm)
2878// Dd = vdiv(Dn, Dm)
2879// vcmp(Dd, Dm)
2880// vmrs
2881// Dd = vsqrt(Dm)
2882void Simulator::DecodeTypeVFP(Instruction* instr) {
2883  ASSERT((instr->TypeValue() == 7) && (instr->Bit(24) == 0x0) );
2884  ASSERT(instr->Bits(11, 9) == 0x5);
2885
2886  // Obtain double precision register codes.
2887  int vm = instr->VFPMRegValue(kDoublePrecision);
2888  int vd = instr->VFPDRegValue(kDoublePrecision);
2889  int vn = instr->VFPNRegValue(kDoublePrecision);
2890
2891  if (instr->Bit(4) == 0) {
2892    if (instr->Opc1Value() == 0x7) {
2893      // Other data processing instructions
2894      if ((instr->Opc2Value() == 0x0) && (instr->Opc3Value() == 0x1)) {
2895        // vmov register to register.
2896        if (instr->SzValue() == 0x1) {
2897          int m = instr->VFPMRegValue(kDoublePrecision);
2898          int d = instr->VFPDRegValue(kDoublePrecision);
2899          set_d_register_from_double(d, get_double_from_d_register(m));
2900        } else {
2901          int m = instr->VFPMRegValue(kSinglePrecision);
2902          int d = instr->VFPDRegValue(kSinglePrecision);
2903          set_s_register_from_float(d, get_float_from_s_register(m));
2904        }
2905      } else if ((instr->Opc2Value() == 0x0) && (instr->Opc3Value() == 0x3)) {
2906        // vabs
2907        double dm_value = get_double_from_d_register(vm);
2908        double dd_value = fabs(dm_value);
2909        dd_value = canonicalizeNaN(dd_value);
2910        set_d_register_from_double(vd, dd_value);
2911      } else if ((instr->Opc2Value() == 0x1) && (instr->Opc3Value() == 0x1)) {
2912        // vneg
2913        double dm_value = get_double_from_d_register(vm);
2914        double dd_value = -dm_value;
2915        dd_value = canonicalizeNaN(dd_value);
2916        set_d_register_from_double(vd, dd_value);
2917      } else if ((instr->Opc2Value() == 0x7) && (instr->Opc3Value() == 0x3)) {
2918        DecodeVCVTBetweenDoubleAndSingle(instr);
2919      } else if ((instr->Opc2Value() == 0x8) && (instr->Opc3Value() & 0x1)) {
2920        DecodeVCVTBetweenFloatingPointAndInteger(instr);
2921      } else if ((instr->Opc2Value() == 0xA) && (instr->Opc3Value() == 0x3) &&
2922                 (instr->Bit(8) == 1)) {
2923        // vcvt.f64.s32 Dd, Dd, #<fbits>
2924        int fraction_bits = 32 - ((instr->Bit(5) << 4) | instr->Bits(3, 0));
2925        int fixed_value = get_sinteger_from_s_register(vd * 2);
2926        double divide = 1 << fraction_bits;
2927        set_d_register_from_double(vd, fixed_value / divide);
2928      } else if (((instr->Opc2Value() >> 1) == 0x6) &&
2929                 (instr->Opc3Value() & 0x1)) {
2930        DecodeVCVTBetweenFloatingPointAndInteger(instr);
2931      } else if (((instr->Opc2Value() == 0x4) || (instr->Opc2Value() == 0x5)) &&
2932                 (instr->Opc3Value() & 0x1)) {
2933        DecodeVCMP(instr);
2934      } else if (((instr->Opc2Value() == 0x1)) && (instr->Opc3Value() == 0x3)) {
2935        // vsqrt
2936        double dm_value = get_double_from_d_register(vm);
2937        double dd_value = sqrt(dm_value);
2938        dd_value = canonicalizeNaN(dd_value);
2939        set_d_register_from_double(vd, dd_value);
2940      } else if (instr->Opc3Value() == 0x0) {
2941        // vmov immediate.
2942        if (instr->SzValue() == 0x1) {
2943          set_d_register_from_double(vd, instr->DoubleImmedVmov());
2944        } else {
2945          UNREACHABLE();  // Not used by v8.
2946        }
2947      } else {
2948        UNREACHABLE();  // Not used by V8.
2949      }
2950    } else if (instr->Opc1Value() == 0x3) {
2951      if (instr->SzValue() != 0x1) {
2952        UNREACHABLE();  // Not used by V8.
2953      }
2954
2955      if (instr->Opc3Value() & 0x1) {
2956        // vsub
2957        double dn_value = get_double_from_d_register(vn);
2958        double dm_value = get_double_from_d_register(vm);
2959        double dd_value = dn_value - dm_value;
2960        dd_value = canonicalizeNaN(dd_value);
2961        set_d_register_from_double(vd, dd_value);
2962      } else {
2963        // vadd
2964        double dn_value = get_double_from_d_register(vn);
2965        double dm_value = get_double_from_d_register(vm);
2966        double dd_value = dn_value + dm_value;
2967        dd_value = canonicalizeNaN(dd_value);
2968        set_d_register_from_double(vd, dd_value);
2969      }
2970    } else if ((instr->Opc1Value() == 0x2) && !(instr->Opc3Value() & 0x1)) {
2971      // vmul
2972      if (instr->SzValue() != 0x1) {
2973        UNREACHABLE();  // Not used by V8.
2974      }
2975
2976      double dn_value = get_double_from_d_register(vn);
2977      double dm_value = get_double_from_d_register(vm);
2978      double dd_value = dn_value * dm_value;
2979      dd_value = canonicalizeNaN(dd_value);
2980      set_d_register_from_double(vd, dd_value);
2981    } else if ((instr->Opc1Value() == 0x0)) {
2982      // vmla, vmls
2983      const bool is_vmls = (instr->Opc3Value() & 0x1);
2984
2985      if (instr->SzValue() != 0x1) {
2986        UNREACHABLE();  // Not used by V8.
2987      }
2988
2989      const double dd_val = get_double_from_d_register(vd);
2990      const double dn_val = get_double_from_d_register(vn);
2991      const double dm_val = get_double_from_d_register(vm);
2992
2993      // Note: we do the mul and add/sub in separate steps to avoid getting a
2994      // result with too high precision.
2995      set_d_register_from_double(vd, dn_val * dm_val);
2996      if (is_vmls) {
2997        set_d_register_from_double(
2998          vd,
2999          canonicalizeNaN(dd_val - get_double_from_d_register(vd)));
3000      } else {
3001        set_d_register_from_double(
3002          vd,
3003          canonicalizeNaN(dd_val + get_double_from_d_register(vd)));
3004      }
3005    } else if ((instr->Opc1Value() == 0x4) && !(instr->Opc3Value() & 0x1)) {
3006      // vdiv
3007      if (instr->SzValue() != 0x1) {
3008        UNREACHABLE();  // Not used by V8.
3009      }
3010
3011      double dn_value = get_double_from_d_register(vn);
3012      double dm_value = get_double_from_d_register(vm);
3013      double dd_value = dn_value / dm_value;
3014      div_zero_vfp_flag_ = (dm_value == 0);
3015      dd_value = canonicalizeNaN(dd_value);
3016      set_d_register_from_double(vd, dd_value);
3017    } else {
3018      UNIMPLEMENTED();  // Not used by V8.
3019    }
3020  } else {
3021    if ((instr->VCValue() == 0x0) &&
3022        (instr->VAValue() == 0x0)) {
3023      DecodeVMOVBetweenCoreAndSinglePrecisionRegisters(instr);
3024    } else if ((instr->VLValue() == 0x0) &&
3025               (instr->VCValue() == 0x1) &&
3026               (instr->Bit(23) == 0x0)) {
3027      // vmov (ARM core register to scalar)
3028      int vd = instr->Bits(19, 16) | (instr->Bit(7) << 4);
3029      double dd_value = get_double_from_d_register(vd);
3030      int32_t data[2];
3031      OS::MemCopy(data, &dd_value, 8);
3032      data[instr->Bit(21)] = get_register(instr->RtValue());
3033      OS::MemCopy(&dd_value, data, 8);
3034      set_d_register_from_double(vd, dd_value);
3035    } else if ((instr->VLValue() == 0x1) &&
3036               (instr->VCValue() == 0x1) &&
3037               (instr->Bit(23) == 0x0)) {
3038      // vmov (scalar to ARM core register)
3039      int vn = instr->Bits(19, 16) | (instr->Bit(7) << 4);
3040      double dn_value = get_double_from_d_register(vn);
3041      int32_t data[2];
3042      OS::MemCopy(data, &dn_value, 8);
3043      set_register(instr->RtValue(), data[instr->Bit(21)]);
3044    } else if ((instr->VLValue() == 0x1) &&
3045               (instr->VCValue() == 0x0) &&
3046               (instr->VAValue() == 0x7) &&
3047               (instr->Bits(19, 16) == 0x1)) {
3048      // vmrs
3049      uint32_t rt = instr->RtValue();
3050      if (rt == 0xF) {
3051        Copy_FPSCR_to_APSR();
3052      } else {
3053        // Emulate FPSCR from the Simulator flags.
3054        uint32_t fpscr = (n_flag_FPSCR_ << 31) |
3055                         (z_flag_FPSCR_ << 30) |
3056                         (c_flag_FPSCR_ << 29) |
3057                         (v_flag_FPSCR_ << 28) |
3058                         (FPSCR_default_NaN_mode_ << 25) |
3059                         (inexact_vfp_flag_ << 4) |
3060                         (underflow_vfp_flag_ << 3) |
3061                         (overflow_vfp_flag_ << 2) |
3062                         (div_zero_vfp_flag_ << 1) |
3063                         (inv_op_vfp_flag_ << 0) |
3064                         (FPSCR_rounding_mode_);
3065        set_register(rt, fpscr);
3066      }
3067    } else if ((instr->VLValue() == 0x0) &&
3068               (instr->VCValue() == 0x0) &&
3069               (instr->VAValue() == 0x7) &&
3070               (instr->Bits(19, 16) == 0x1)) {
3071      // vmsr
3072      uint32_t rt = instr->RtValue();
3073      if (rt == pc) {
3074        UNREACHABLE();
3075      } else {
3076        uint32_t rt_value = get_register(rt);
3077        n_flag_FPSCR_ = (rt_value >> 31) & 1;
3078        z_flag_FPSCR_ = (rt_value >> 30) & 1;
3079        c_flag_FPSCR_ = (rt_value >> 29) & 1;
3080        v_flag_FPSCR_ = (rt_value >> 28) & 1;
3081        FPSCR_default_NaN_mode_ = (rt_value >> 25) & 1;
3082        inexact_vfp_flag_ = (rt_value >> 4) & 1;
3083        underflow_vfp_flag_ = (rt_value >> 3) & 1;
3084        overflow_vfp_flag_ = (rt_value >> 2) & 1;
3085        div_zero_vfp_flag_ = (rt_value >> 1) & 1;
3086        inv_op_vfp_flag_ = (rt_value >> 0) & 1;
3087        FPSCR_rounding_mode_ =
3088            static_cast<VFPRoundingMode>((rt_value) & kVFPRoundingModeMask);
3089      }
3090    } else {
3091      UNIMPLEMENTED();  // Not used by V8.
3092    }
3093  }
3094}
3095
3096
3097void Simulator::DecodeVMOVBetweenCoreAndSinglePrecisionRegisters(
3098    Instruction* instr) {
3099  ASSERT((instr->Bit(4) == 1) && (instr->VCValue() == 0x0) &&
3100         (instr->VAValue() == 0x0));
3101
3102  int t = instr->RtValue();
3103  int n = instr->VFPNRegValue(kSinglePrecision);
3104  bool to_arm_register = (instr->VLValue() == 0x1);
3105
3106  if (to_arm_register) {
3107    int32_t int_value = get_sinteger_from_s_register(n);
3108    set_register(t, int_value);
3109  } else {
3110    int32_t rs_val = get_register(t);
3111    set_s_register_from_sinteger(n, rs_val);
3112  }
3113}
3114
3115
3116void Simulator::DecodeVCMP(Instruction* instr) {
3117  ASSERT((instr->Bit(4) == 0) && (instr->Opc1Value() == 0x7));
3118  ASSERT(((instr->Opc2Value() == 0x4) || (instr->Opc2Value() == 0x5)) &&
3119         (instr->Opc3Value() & 0x1));
3120  // Comparison.
3121
3122  VFPRegPrecision precision = kSinglePrecision;
3123  if (instr->SzValue() == 1) {
3124    precision = kDoublePrecision;
3125  }
3126
3127  int d = instr->VFPDRegValue(precision);
3128  int m = 0;
3129  if (instr->Opc2Value() == 0x4) {
3130    m = instr->VFPMRegValue(precision);
3131  }
3132
3133  if (precision == kDoublePrecision) {
3134    double dd_value = get_double_from_d_register(d);
3135    double dm_value = 0.0;
3136    if (instr->Opc2Value() == 0x4) {
3137      dm_value = get_double_from_d_register(m);
3138    }
3139
3140    // Raise exceptions for quiet NaNs if necessary.
3141    if (instr->Bit(7) == 1) {
3142      if (std::isnan(dd_value)) {
3143        inv_op_vfp_flag_ = true;
3144      }
3145    }
3146
3147    Compute_FPSCR_Flags(dd_value, dm_value);
3148  } else {
3149    UNIMPLEMENTED();  // Not used by V8.
3150  }
3151}
3152
3153
3154void Simulator::DecodeVCVTBetweenDoubleAndSingle(Instruction* instr) {
3155  ASSERT((instr->Bit(4) == 0) && (instr->Opc1Value() == 0x7));
3156  ASSERT((instr->Opc2Value() == 0x7) && (instr->Opc3Value() == 0x3));
3157
3158  VFPRegPrecision dst_precision = kDoublePrecision;
3159  VFPRegPrecision src_precision = kSinglePrecision;
3160  if (instr->SzValue() == 1) {
3161    dst_precision = kSinglePrecision;
3162    src_precision = kDoublePrecision;
3163  }
3164
3165  int dst = instr->VFPDRegValue(dst_precision);
3166  int src = instr->VFPMRegValue(src_precision);
3167
3168  if (dst_precision == kSinglePrecision) {
3169    double val = get_double_from_d_register(src);
3170    set_s_register_from_float(dst, static_cast<float>(val));
3171  } else {
3172    float val = get_float_from_s_register(src);
3173    set_d_register_from_double(dst, static_cast<double>(val));
3174  }
3175}
3176
3177bool get_inv_op_vfp_flag(VFPRoundingMode mode,
3178                         double val,
3179                         bool unsigned_) {
3180  ASSERT((mode == RN) || (mode == RM) || (mode == RZ));
3181  double max_uint = static_cast<double>(0xffffffffu);
3182  double max_int = static_cast<double>(kMaxInt);
3183  double min_int = static_cast<double>(kMinInt);
3184
3185  // Check for NaN.
3186  if (val != val) {
3187    return true;
3188  }
3189
3190  // Check for overflow. This code works because 32bit integers can be
3191  // exactly represented by ieee-754 64bit floating-point values.
3192  switch (mode) {
3193    case RN:
3194      return  unsigned_ ? (val >= (max_uint + 0.5)) ||
3195                          (val < -0.5)
3196                        : (val >= (max_int + 0.5)) ||
3197                          (val < (min_int - 0.5));
3198
3199    case RM:
3200      return  unsigned_ ? (val >= (max_uint + 1.0)) ||
3201                          (val < 0)
3202                        : (val >= (max_int + 1.0)) ||
3203                          (val < min_int);
3204
3205    case RZ:
3206      return  unsigned_ ? (val >= (max_uint + 1.0)) ||
3207                          (val <= -1)
3208                        : (val >= (max_int + 1.0)) ||
3209                          (val <= (min_int - 1.0));
3210    default:
3211      UNREACHABLE();
3212      return true;
3213  }
3214}
3215
3216
3217// We call this function only if we had a vfp invalid exception.
3218// It returns the correct saturated value.
3219int VFPConversionSaturate(double val, bool unsigned_res) {
3220  if (val != val) {
3221    return 0;
3222  } else {
3223    if (unsigned_res) {
3224      return (val < 0) ? 0 : 0xffffffffu;
3225    } else {
3226      return (val < 0) ? kMinInt : kMaxInt;
3227    }
3228  }
3229}
3230
3231
3232void Simulator::DecodeVCVTBetweenFloatingPointAndInteger(Instruction* instr) {
3233  ASSERT((instr->Bit(4) == 0) && (instr->Opc1Value() == 0x7) &&
3234         (instr->Bits(27, 23) == 0x1D));
3235  ASSERT(((instr->Opc2Value() == 0x8) && (instr->Opc3Value() & 0x1)) ||
3236         (((instr->Opc2Value() >> 1) == 0x6) && (instr->Opc3Value() & 0x1)));
3237
3238  // Conversion between floating-point and integer.
3239  bool to_integer = (instr->Bit(18) == 1);
3240
3241  VFPRegPrecision src_precision = (instr->SzValue() == 1) ? kDoublePrecision
3242                                                          : kSinglePrecision;
3243
3244  if (to_integer) {
3245    // We are playing with code close to the C++ standard's limits below,
3246    // hence the very simple code and heavy checks.
3247    //
3248    // Note:
3249    // C++ defines default type casting from floating point to integer as
3250    // (close to) rounding toward zero ("fractional part discarded").
3251
3252    int dst = instr->VFPDRegValue(kSinglePrecision);
3253    int src = instr->VFPMRegValue(src_precision);
3254
3255    // Bit 7 in vcvt instructions indicates if we should use the FPSCR rounding
3256    // mode or the default Round to Zero mode.
3257    VFPRoundingMode mode = (instr->Bit(7) != 1) ? FPSCR_rounding_mode_
3258                                                : RZ;
3259    ASSERT((mode == RM) || (mode == RZ) || (mode == RN));
3260
3261    bool unsigned_integer = (instr->Bit(16) == 0);
3262    bool double_precision = (src_precision == kDoublePrecision);
3263
3264    double val = double_precision ? get_double_from_d_register(src)
3265                                  : get_float_from_s_register(src);
3266
3267    int temp = unsigned_integer ? static_cast<uint32_t>(val)
3268                                : static_cast<int32_t>(val);
3269
3270    inv_op_vfp_flag_ = get_inv_op_vfp_flag(mode, val, unsigned_integer);
3271
3272    double abs_diff =
3273      unsigned_integer ? fabs(val - static_cast<uint32_t>(temp))
3274                       : fabs(val - temp);
3275
3276    inexact_vfp_flag_ = (abs_diff != 0);
3277
3278    if (inv_op_vfp_flag_) {
3279      temp = VFPConversionSaturate(val, unsigned_integer);
3280    } else {
3281      switch (mode) {
3282        case RN: {
3283          int val_sign = (val > 0) ? 1 : -1;
3284          if (abs_diff > 0.5) {
3285            temp += val_sign;
3286          } else if (abs_diff == 0.5) {
3287            // Round to even if exactly halfway.
3288            temp = ((temp % 2) == 0) ? temp : temp + val_sign;
3289          }
3290          break;
3291        }
3292
3293        case RM:
3294          temp = temp > val ? temp - 1 : temp;
3295          break;
3296
3297        case RZ:
3298          // Nothing to do.
3299          break;
3300
3301        default:
3302          UNREACHABLE();
3303      }
3304    }
3305
3306    // Update the destination register.
3307    set_s_register_from_sinteger(dst, temp);
3308
3309  } else {
3310    bool unsigned_integer = (instr->Bit(7) == 0);
3311
3312    int dst = instr->VFPDRegValue(src_precision);
3313    int src = instr->VFPMRegValue(kSinglePrecision);
3314
3315    int val = get_sinteger_from_s_register(src);
3316
3317    if (src_precision == kDoublePrecision) {
3318      if (unsigned_integer) {
3319        set_d_register_from_double(
3320            dst, static_cast<double>(static_cast<uint32_t>(val)));
3321      } else {
3322        set_d_register_from_double(dst, static_cast<double>(val));
3323      }
3324    } else {
3325      if (unsigned_integer) {
3326        set_s_register_from_float(
3327            dst, static_cast<float>(static_cast<uint32_t>(val)));
3328      } else {
3329        set_s_register_from_float(dst, static_cast<float>(val));
3330      }
3331    }
3332  }
3333}
3334
3335
3336// void Simulator::DecodeType6CoprocessorIns(Instruction* instr)
3337// Decode Type 6 coprocessor instructions.
3338// Dm = vmov(Rt, Rt2)
3339// <Rt, Rt2> = vmov(Dm)
3340// Ddst = MEM(Rbase + 4*offset).
3341// MEM(Rbase + 4*offset) = Dsrc.
3342void Simulator::DecodeType6CoprocessorIns(Instruction* instr) {
3343  ASSERT((instr->TypeValue() == 6));
3344
3345  if (instr->CoprocessorValue() == 0xA) {
3346    switch (instr->OpcodeValue()) {
3347      case 0x8:
3348      case 0xA:
3349      case 0xC:
3350      case 0xE: {  // Load and store single precision float to memory.
3351        int rn = instr->RnValue();
3352        int vd = instr->VFPDRegValue(kSinglePrecision);
3353        int offset = instr->Immed8Value();
3354        if (!instr->HasU()) {
3355          offset = -offset;
3356        }
3357
3358        int32_t address = get_register(rn) + 4 * offset;
3359        if (instr->HasL()) {
3360          // Load double from memory: vldr.
3361          set_s_register_from_sinteger(vd, ReadW(address, instr));
3362        } else {
3363          // Store double to memory: vstr.
3364          WriteW(address, get_sinteger_from_s_register(vd), instr);
3365        }
3366        break;
3367      }
3368      case 0x4:
3369      case 0x5:
3370      case 0x6:
3371      case 0x7:
3372      case 0x9:
3373      case 0xB:
3374        // Load/store multiple single from memory: vldm/vstm.
3375        HandleVList(instr);
3376        break;
3377      default:
3378        UNIMPLEMENTED();  // Not used by V8.
3379    }
3380  } else if (instr->CoprocessorValue() == 0xB) {
3381    switch (instr->OpcodeValue()) {
3382      case 0x2:
3383        // Load and store double to two GP registers
3384        if (instr->Bits(7, 6) != 0 || instr->Bit(4) != 1) {
3385          UNIMPLEMENTED();  // Not used by V8.
3386        } else {
3387          int rt = instr->RtValue();
3388          int rn = instr->RnValue();
3389          int vm = instr->VFPMRegValue(kDoublePrecision);
3390          if (instr->HasL()) {
3391            int32_t data[2];
3392            double d = get_double_from_d_register(vm);
3393            OS::MemCopy(data, &d, 8);
3394            set_register(rt, data[0]);
3395            set_register(rn, data[1]);
3396          } else {
3397            int32_t data[] = { get_register(rt), get_register(rn) };
3398            double d;
3399            OS::MemCopy(&d, data, 8);
3400            set_d_register_from_double(vm, d);
3401          }
3402        }
3403        break;
3404      case 0x8:
3405      case 0xA:
3406      case 0xC:
3407      case 0xE: {  // Load and store double to memory.
3408        int rn = instr->RnValue();
3409        int vd = instr->VFPDRegValue(kDoublePrecision);
3410        int offset = instr->Immed8Value();
3411        if (!instr->HasU()) {
3412          offset = -offset;
3413        }
3414        int32_t address = get_register(rn) + 4 * offset;
3415        if (instr->HasL()) {
3416          // Load double from memory: vldr.
3417          int32_t data[] = {
3418            ReadW(address, instr),
3419            ReadW(address + 4, instr)
3420          };
3421          double val;
3422          OS::MemCopy(&val, data, 8);
3423          set_d_register_from_double(vd, val);
3424        } else {
3425          // Store double to memory: vstr.
3426          int32_t data[2];
3427          double val = get_double_from_d_register(vd);
3428          OS::MemCopy(data, &val, 8);
3429          WriteW(address, data[0], instr);
3430          WriteW(address + 4, data[1], instr);
3431        }
3432        break;
3433      }
3434      case 0x4:
3435      case 0x5:
3436      case 0x6:
3437      case 0x7:
3438      case 0x9:
3439      case 0xB:
3440        // Load/store multiple double from memory: vldm/vstm.
3441        HandleVList(instr);
3442        break;
3443      default:
3444        UNIMPLEMENTED();  // Not used by V8.
3445    }
3446  } else {
3447    UNIMPLEMENTED();  // Not used by V8.
3448  }
3449}
3450
3451
3452void Simulator::DecodeSpecialCondition(Instruction* instr) {
3453  switch (instr->SpecialValue()) {
3454    case 5:
3455      if ((instr->Bits(18, 16) == 0) && (instr->Bits(11, 6) == 0x28) &&
3456          (instr->Bit(4) == 1)) {
3457        // vmovl signed
3458        int Vd = (instr->Bit(22) << 4) | instr->VdValue();
3459        int Vm = (instr->Bit(5) << 4) | instr->VmValue();
3460        int imm3 = instr->Bits(21, 19);
3461        if ((imm3 != 1) && (imm3 != 2) && (imm3 != 4)) UNIMPLEMENTED();
3462        int esize = 8 * imm3;
3463        int elements = 64 / esize;
3464        int8_t from[8];
3465        get_d_register(Vm, reinterpret_cast<uint64_t*>(from));
3466        int16_t to[8];
3467        int e = 0;
3468        while (e < elements) {
3469          to[e] = from[e];
3470          e++;
3471        }
3472        set_q_register(Vd, reinterpret_cast<uint64_t*>(to));
3473      } else {
3474        UNIMPLEMENTED();
3475      }
3476      break;
3477    case 7:
3478      if ((instr->Bits(18, 16) == 0) && (instr->Bits(11, 6) == 0x28) &&
3479          (instr->Bit(4) == 1)) {
3480        // vmovl unsigned
3481        int Vd = (instr->Bit(22) << 4) | instr->VdValue();
3482        int Vm = (instr->Bit(5) << 4) | instr->VmValue();
3483        int imm3 = instr->Bits(21, 19);
3484        if ((imm3 != 1) && (imm3 != 2) && (imm3 != 4)) UNIMPLEMENTED();
3485        int esize = 8 * imm3;
3486        int elements = 64 / esize;
3487        uint8_t from[8];
3488        get_d_register(Vm, reinterpret_cast<uint64_t*>(from));
3489        uint16_t to[8];
3490        int e = 0;
3491        while (e < elements) {
3492          to[e] = from[e];
3493          e++;
3494        }
3495        set_q_register(Vd, reinterpret_cast<uint64_t*>(to));
3496      } else {
3497        UNIMPLEMENTED();
3498      }
3499      break;
3500    case 8:
3501      if (instr->Bits(21, 20) == 0) {
3502        // vst1
3503        int Vd = (instr->Bit(22) << 4) | instr->VdValue();
3504        int Rn = instr->VnValue();
3505        int type = instr->Bits(11, 8);
3506        int Rm = instr->VmValue();
3507        int32_t address = get_register(Rn);
3508        int regs = 0;
3509        switch (type) {
3510          case nlt_1:
3511            regs = 1;
3512            break;
3513          case nlt_2:
3514            regs = 2;
3515            break;
3516          case nlt_3:
3517            regs = 3;
3518            break;
3519          case nlt_4:
3520            regs = 4;
3521            break;
3522          default:
3523            UNIMPLEMENTED();
3524            break;
3525        }
3526        int r = 0;
3527        while (r < regs) {
3528          uint32_t data[2];
3529          get_d_register(Vd + r, data);
3530          WriteW(address, data[0], instr);
3531          WriteW(address + 4, data[1], instr);
3532          address += 8;
3533          r++;
3534        }
3535        if (Rm != 15) {
3536          if (Rm == 13) {
3537            set_register(Rn, address);
3538          } else {
3539            set_register(Rn, get_register(Rn) + get_register(Rm));
3540          }
3541        }
3542      } else if (instr->Bits(21, 20) == 2) {
3543        // vld1
3544        int Vd = (instr->Bit(22) << 4) | instr->VdValue();
3545        int Rn = instr->VnValue();
3546        int type = instr->Bits(11, 8);
3547        int Rm = instr->VmValue();
3548        int32_t address = get_register(Rn);
3549        int regs = 0;
3550        switch (type) {
3551          case nlt_1:
3552            regs = 1;
3553            break;
3554          case nlt_2:
3555            regs = 2;
3556            break;
3557          case nlt_3:
3558            regs = 3;
3559            break;
3560          case nlt_4:
3561            regs = 4;
3562            break;
3563          default:
3564            UNIMPLEMENTED();
3565            break;
3566        }
3567        int r = 0;
3568        while (r < regs) {
3569          uint32_t data[2];
3570          data[0] = ReadW(address, instr);
3571          data[1] = ReadW(address + 4, instr);
3572          set_d_register(Vd + r, data);
3573          address += 8;
3574          r++;
3575        }
3576        if (Rm != 15) {
3577          if (Rm == 13) {
3578            set_register(Rn, address);
3579          } else {
3580            set_register(Rn, get_register(Rn) + get_register(Rm));
3581          }
3582        }
3583      } else {
3584        UNIMPLEMENTED();
3585      }
3586      break;
3587    case 0xA:
3588    case 0xB:
3589      if ((instr->Bits(22, 20) == 5) && (instr->Bits(15, 12) == 0xf)) {
3590        // pld: ignore instruction.
3591      } else {
3592        UNIMPLEMENTED();
3593      }
3594      break;
3595    default:
3596      UNIMPLEMENTED();
3597      break;
3598  }
3599}
3600
3601
3602// Executes the current instruction.
3603void Simulator::InstructionDecode(Instruction* instr) {
3604  if (v8::internal::FLAG_check_icache) {
3605    CheckICache(isolate_->simulator_i_cache(), instr);
3606  }
3607  pc_modified_ = false;
3608  if (::v8::internal::FLAG_trace_sim) {
3609    disasm::NameConverter converter;
3610    disasm::Disassembler dasm(converter);
3611    // use a reasonably large buffer
3612    v8::internal::EmbeddedVector<char, 256> buffer;
3613    dasm.InstructionDecode(buffer,
3614                           reinterpret_cast<byte*>(instr));
3615    PrintF("  0x%08x  %s\n", reinterpret_cast<intptr_t>(instr), buffer.start());
3616  }
3617  if (instr->ConditionField() == kSpecialCondition) {
3618    DecodeSpecialCondition(instr);
3619  } else if (ConditionallyExecute(instr)) {
3620    switch (instr->TypeValue()) {
3621      case 0:
3622      case 1: {
3623        DecodeType01(instr);
3624        break;
3625      }
3626      case 2: {
3627        DecodeType2(instr);
3628        break;
3629      }
3630      case 3: {
3631        DecodeType3(instr);
3632        break;
3633      }
3634      case 4: {
3635        DecodeType4(instr);
3636        break;
3637      }
3638      case 5: {
3639        DecodeType5(instr);
3640        break;
3641      }
3642      case 6: {
3643        DecodeType6(instr);
3644        break;
3645      }
3646      case 7: {
3647        DecodeType7(instr);
3648        break;
3649      }
3650      default: {
3651        UNIMPLEMENTED();
3652        break;
3653      }
3654    }
3655  // If the instruction is a non taken conditional stop, we need to skip the
3656  // inlined message address.
3657  } else if (instr->IsStop()) {
3658    set_pc(get_pc() + 2 * Instruction::kInstrSize);
3659  }
3660  if (!pc_modified_) {
3661    set_register(pc, reinterpret_cast<int32_t>(instr)
3662                         + Instruction::kInstrSize);
3663  }
3664}
3665
3666
3667void Simulator::Execute() {
3668  // Get the PC to simulate. Cannot use the accessor here as we need the
3669  // raw PC value and not the one used as input to arithmetic instructions.
3670  int program_counter = get_pc();
3671
3672  if (::v8::internal::FLAG_stop_sim_at == 0) {
3673    // Fast version of the dispatch loop without checking whether the simulator
3674    // should be stopping at a particular executed instruction.
3675    while (program_counter != end_sim_pc) {
3676      Instruction* instr = reinterpret_cast<Instruction*>(program_counter);
3677      icount_++;
3678      InstructionDecode(instr);
3679      program_counter = get_pc();
3680    }
3681  } else {
3682    // FLAG_stop_sim_at is at the non-default value. Stop in the debugger when
3683    // we reach the particular instuction count.
3684    while (program_counter != end_sim_pc) {
3685      Instruction* instr = reinterpret_cast<Instruction*>(program_counter);
3686      icount_++;
3687      if (icount_ == ::v8::internal::FLAG_stop_sim_at) {
3688        ArmDebugger dbg(this);
3689        dbg.Debug();
3690      } else {
3691        InstructionDecode(instr);
3692      }
3693      program_counter = get_pc();
3694    }
3695  }
3696}
3697
3698
3699void Simulator::CallInternal(byte* entry) {
3700  // Prepare to execute the code at entry
3701  set_register(pc, reinterpret_cast<int32_t>(entry));
3702  // Put down marker for end of simulation. The simulator will stop simulation
3703  // when the PC reaches this value. By saving the "end simulation" value into
3704  // the LR the simulation stops when returning to this call point.
3705  set_register(lr, end_sim_pc);
3706
3707  // Remember the values of callee-saved registers.
3708  // The code below assumes that r9 is not used as sb (static base) in
3709  // simulator code and therefore is regarded as a callee-saved register.
3710  int32_t r4_val = get_register(r4);
3711  int32_t r5_val = get_register(r5);
3712  int32_t r6_val = get_register(r6);
3713  int32_t r7_val = get_register(r7);
3714  int32_t r8_val = get_register(r8);
3715  int32_t r9_val = get_register(r9);
3716  int32_t r10_val = get_register(r10);
3717  int32_t r11_val = get_register(r11);
3718
3719  // Set up the callee-saved registers with a known value. To be able to check
3720  // that they are preserved properly across JS execution.
3721  int32_t callee_saved_value = icount_;
3722  set_register(r4, callee_saved_value);
3723  set_register(r5, callee_saved_value);
3724  set_register(r6, callee_saved_value);
3725  set_register(r7, callee_saved_value);
3726  set_register(r8, callee_saved_value);
3727  set_register(r9, callee_saved_value);
3728  set_register(r10, callee_saved_value);
3729  set_register(r11, callee_saved_value);
3730
3731  // Start the simulation
3732  Execute();
3733
3734  // Check that the callee-saved registers have been preserved.
3735  CHECK_EQ(callee_saved_value, get_register(r4));
3736  CHECK_EQ(callee_saved_value, get_register(r5));
3737  CHECK_EQ(callee_saved_value, get_register(r6));
3738  CHECK_EQ(callee_saved_value, get_register(r7));
3739  CHECK_EQ(callee_saved_value, get_register(r8));
3740  CHECK_EQ(callee_saved_value, get_register(r9));
3741  CHECK_EQ(callee_saved_value, get_register(r10));
3742  CHECK_EQ(callee_saved_value, get_register(r11));
3743
3744  // Restore callee-saved registers with the original value.
3745  set_register(r4, r4_val);
3746  set_register(r5, r5_val);
3747  set_register(r6, r6_val);
3748  set_register(r7, r7_val);
3749  set_register(r8, r8_val);
3750  set_register(r9, r9_val);
3751  set_register(r10, r10_val);
3752  set_register(r11, r11_val);
3753}
3754
3755
3756int32_t Simulator::Call(byte* entry, int argument_count, ...) {
3757  va_list parameters;
3758  va_start(parameters, argument_count);
3759  // Set up arguments
3760
3761  // First four arguments passed in registers.
3762  ASSERT(argument_count >= 4);
3763  set_register(r0, va_arg(parameters, int32_t));
3764  set_register(r1, va_arg(parameters, int32_t));
3765  set_register(r2, va_arg(parameters, int32_t));
3766  set_register(r3, va_arg(parameters, int32_t));
3767
3768  // Remaining arguments passed on stack.
3769  int original_stack = get_register(sp);
3770  // Compute position of stack on entry to generated code.
3771  int entry_stack = (original_stack - (argument_count - 4) * sizeof(int32_t));
3772  if (OS::ActivationFrameAlignment() != 0) {
3773    entry_stack &= -OS::ActivationFrameAlignment();
3774  }
3775  // Store remaining arguments on stack, from low to high memory.
3776  intptr_t* stack_argument = reinterpret_cast<intptr_t*>(entry_stack);
3777  for (int i = 4; i < argument_count; i++) {
3778    stack_argument[i - 4] = va_arg(parameters, int32_t);
3779  }
3780  va_end(parameters);
3781  set_register(sp, entry_stack);
3782
3783  CallInternal(entry);
3784
3785  // Pop stack passed arguments.
3786  CHECK_EQ(entry_stack, get_register(sp));
3787  set_register(sp, original_stack);
3788
3789  int32_t result = get_register(r0);
3790  return result;
3791}
3792
3793
3794void Simulator::CallFP(byte* entry, double d0, double d1) {
3795  if (use_eabi_hardfloat()) {
3796    set_d_register_from_double(0, d0);
3797    set_d_register_from_double(1, d1);
3798  } else {
3799    set_register_pair_from_double(0, &d0);
3800    set_register_pair_from_double(2, &d1);
3801  }
3802  CallInternal(entry);
3803}
3804
3805
3806int32_t Simulator::CallFPReturnsInt(byte* entry, double d0, double d1) {
3807  CallFP(entry, d0, d1);
3808  int32_t result = get_register(r0);
3809  return result;
3810}
3811
3812
3813double Simulator::CallFPReturnsDouble(byte* entry, double d0, double d1) {
3814  CallFP(entry, d0, d1);
3815  if (use_eabi_hardfloat()) {
3816    return get_double_from_d_register(0);
3817  } else {
3818    return get_double_from_register_pair(0);
3819  }
3820}
3821
3822
3823uintptr_t Simulator::PushAddress(uintptr_t address) {
3824  int new_sp = get_register(sp) - sizeof(uintptr_t);
3825  uintptr_t* stack_slot = reinterpret_cast<uintptr_t*>(new_sp);
3826  *stack_slot = address;
3827  set_register(sp, new_sp);
3828  return new_sp;
3829}
3830
3831
3832uintptr_t Simulator::PopAddress() {
3833  int current_sp = get_register(sp);
3834  uintptr_t* stack_slot = reinterpret_cast<uintptr_t*>(current_sp);
3835  uintptr_t address = *stack_slot;
3836  set_register(sp, current_sp + sizeof(uintptr_t));
3837  return address;
3838}
3839
3840} }  // namespace v8::internal
3841
3842#endif  // USE_SIMULATOR
3843
3844#endif  // V8_TARGET_ARCH_ARM
3845