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