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