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