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