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