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