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