• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2011 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 <limits.h>
6 #include <stdarg.h>
7 #include <stdlib.h>
8 #include <cmath>
9 
10 #include "src/v8.h"
11 
12 #if V8_TARGET_ARCH_MIPS
13 
14 #include "src/assembler.h"
15 #include "src/base/bits.h"
16 #include "src/disasm.h"
17 #include "src/mips/constants-mips.h"
18 #include "src/mips/simulator-mips.h"
19 #include "src/ostreams.h"
20 
21 
22 // Only build the simulator if not compiling for real MIPS hardware.
23 #if defined(USE_SIMULATOR)
24 
25 namespace v8 {
26 namespace internal {
27 
28 // Utils functions.
HaveSameSign(int32_t a,int32_t b)29 bool HaveSameSign(int32_t a, int32_t b) {
30   return ((a ^ b) >= 0);
31 }
32 
33 
get_fcsr_condition_bit(uint32_t cc)34 uint32_t get_fcsr_condition_bit(uint32_t cc) {
35   if (cc == 0) {
36     return 23;
37   } else {
38     return 24 + cc;
39   }
40 }
41 
42 
43 // This macro provides a platform independent use of sscanf. The reason for
44 // SScanF not being implemented in a platform independent was through
45 // ::v8::internal::OS in the same way as SNPrintF is that the Windows C Run-Time
46 // Library does not provide vsscanf.
47 #define SScanF sscanf  // NOLINT
48 
49 // The MipsDebugger class is used by the simulator while debugging simulated
50 // code.
51 class MipsDebugger {
52  public:
MipsDebugger(Simulator * sim)53   explicit MipsDebugger(Simulator* sim) : sim_(sim) { }
54   ~MipsDebugger();
55 
56   void Stop(Instruction* instr);
57   void Debug();
58   // Print all registers with a nice formatting.
59   void PrintAllRegs();
60   void PrintAllRegsIncludingFPU();
61 
62  private:
63   // We set the breakpoint code to 0xfffff to easily recognize it.
64   static const Instr kBreakpointInstr = SPECIAL | BREAK | 0xfffff << 6;
65   static const Instr kNopInstr =  0x0;
66 
67   Simulator* sim_;
68 
69   int32_t GetRegisterValue(int regnum);
70   int32_t GetFPURegisterValue32(int regnum);
71   int64_t GetFPURegisterValue64(int regnum);
72   float GetFPURegisterValueFloat(int regnum);
73   double GetFPURegisterValueDouble(int regnum);
74   bool GetValue(const char* desc, int32_t* value);
75   bool GetValue(const char* desc, int64_t* value);
76 
77   // Set or delete a breakpoint. Returns true if successful.
78   bool SetBreakpoint(Instruction* breakpc);
79   bool DeleteBreakpoint(Instruction* breakpc);
80 
81   // Undo and redo all breakpoints. This is needed to bracket disassembly and
82   // execution to skip past breakpoints when run from the debugger.
83   void UndoBreakpoints();
84   void RedoBreakpoints();
85 };
86 
87 
~MipsDebugger()88 MipsDebugger::~MipsDebugger() {
89 }
90 
91 
92 #ifdef GENERATED_CODE_COVERAGE
93 static FILE* coverage_log = NULL;
94 
95 
InitializeCoverage()96 static void InitializeCoverage() {
97   char* file_name = getenv("V8_GENERATED_CODE_COVERAGE_LOG");
98   if (file_name != NULL) {
99     coverage_log = fopen(file_name, "aw+");
100   }
101 }
102 
103 
Stop(Instruction * instr)104 void MipsDebugger::Stop(Instruction* instr) {
105   // Get the stop code.
106   uint32_t code = instr->Bits(25, 6);
107   // Retrieve the encoded address, which comes just after this stop.
108   char** msg_address =
109     reinterpret_cast<char**>(sim_->get_pc() + Instr::kInstrSize);
110   char* msg = *msg_address;
111   DCHECK(msg != NULL);
112 
113   // Update this stop description.
114   if (!watched_stops_[code].desc) {
115     watched_stops_[code].desc = msg;
116   }
117 
118   if (strlen(msg) > 0) {
119     if (coverage_log != NULL) {
120       fprintf(coverage_log, "%s\n", str);
121       fflush(coverage_log);
122     }
123     // Overwrite the instruction and address with nops.
124     instr->SetInstructionBits(kNopInstr);
125     reinterpret_cast<Instr*>(msg_address)->SetInstructionBits(kNopInstr);
126   }
127   sim_->set_pc(sim_->get_pc() + 2 * Instruction::kInstructionSize);
128 }
129 
130 
131 #else  // GENERATED_CODE_COVERAGE
132 
133 #define UNSUPPORTED() printf("Unsupported instruction.\n");
134 
InitializeCoverage()135 static void InitializeCoverage() {}
136 
137 
Stop(Instruction * instr)138 void MipsDebugger::Stop(Instruction* instr) {
139   // Get the stop code.
140   uint32_t code = instr->Bits(25, 6);
141   // Retrieve the encoded address, which comes just after this stop.
142   char* msg = *reinterpret_cast<char**>(sim_->get_pc() +
143       Instruction::kInstrSize);
144   // Update this stop description.
145   if (!sim_->watched_stops_[code].desc) {
146     sim_->watched_stops_[code].desc = msg;
147   }
148   PrintF("Simulator hit %s (%u)\n", msg, code);
149   sim_->set_pc(sim_->get_pc() + 2 * Instruction::kInstrSize);
150   Debug();
151 }
152 #endif  // GENERATED_CODE_COVERAGE
153 
154 
GetRegisterValue(int regnum)155 int32_t MipsDebugger::GetRegisterValue(int regnum) {
156   if (regnum == kNumSimuRegisters) {
157     return sim_->get_pc();
158   } else {
159     return sim_->get_register(regnum);
160   }
161 }
162 
163 
GetFPURegisterValue32(int regnum)164 int32_t MipsDebugger::GetFPURegisterValue32(int regnum) {
165   if (regnum == kNumFPURegisters) {
166     return sim_->get_pc();
167   } else {
168     return sim_->get_fpu_register_word(regnum);
169   }
170 }
171 
172 
GetFPURegisterValue64(int regnum)173 int64_t MipsDebugger::GetFPURegisterValue64(int regnum) {
174   if (regnum == kNumFPURegisters) {
175     return sim_->get_pc();
176   } else {
177     return sim_->get_fpu_register(regnum);
178   }
179 }
180 
181 
GetFPURegisterValueFloat(int regnum)182 float MipsDebugger::GetFPURegisterValueFloat(int regnum) {
183   if (regnum == kNumFPURegisters) {
184     return sim_->get_pc();
185   } else {
186     return sim_->get_fpu_register_float(regnum);
187   }
188 }
189 
190 
GetFPURegisterValueDouble(int regnum)191 double MipsDebugger::GetFPURegisterValueDouble(int regnum) {
192   if (regnum == kNumFPURegisters) {
193     return sim_->get_pc();
194   } else {
195     return sim_->get_fpu_register_double(regnum);
196   }
197 }
198 
199 
GetValue(const char * desc,int32_t * value)200 bool MipsDebugger::GetValue(const char* desc, int32_t* value) {
201   int regnum = Registers::Number(desc);
202   int fpuregnum = FPURegisters::Number(desc);
203 
204   if (regnum != kInvalidRegister) {
205     *value = GetRegisterValue(regnum);
206     return true;
207   } else if (fpuregnum != kInvalidFPURegister) {
208     *value = GetFPURegisterValue32(fpuregnum);
209     return true;
210   } else if (strncmp(desc, "0x", 2) == 0) {
211     return SScanF(desc, "%x", reinterpret_cast<uint32_t*>(value)) == 1;
212   } else {
213     return SScanF(desc, "%i", value) == 1;
214   }
215   return false;
216 }
217 
218 
GetValue(const char * desc,int64_t * value)219 bool MipsDebugger::GetValue(const char* desc, int64_t* value) {
220   int regnum = Registers::Number(desc);
221   int fpuregnum = FPURegisters::Number(desc);
222 
223   if (regnum != kInvalidRegister) {
224     *value = GetRegisterValue(regnum);
225     return true;
226   } else if (fpuregnum != kInvalidFPURegister) {
227     *value = GetFPURegisterValue64(fpuregnum);
228     return true;
229   } else if (strncmp(desc, "0x", 2) == 0) {
230     return SScanF(desc + 2, "%" SCNx64,
231                   reinterpret_cast<uint64_t*>(value)) == 1;
232   } else {
233     return SScanF(desc, "%" SCNu64, reinterpret_cast<uint64_t*>(value)) == 1;
234   }
235   return false;
236 }
237 
238 
SetBreakpoint(Instruction * breakpc)239 bool MipsDebugger::SetBreakpoint(Instruction* breakpc) {
240   // Check if a breakpoint can be set. If not return without any side-effects.
241   if (sim_->break_pc_ != NULL) {
242     return false;
243   }
244 
245   // Set the breakpoint.
246   sim_->break_pc_ = breakpc;
247   sim_->break_instr_ = breakpc->InstructionBits();
248   // Not setting the breakpoint instruction in the code itself. It will be set
249   // when the debugger shell continues.
250   return true;
251 }
252 
253 
DeleteBreakpoint(Instruction * breakpc)254 bool MipsDebugger::DeleteBreakpoint(Instruction* breakpc) {
255   if (sim_->break_pc_ != NULL) {
256     sim_->break_pc_->SetInstructionBits(sim_->break_instr_);
257   }
258 
259   sim_->break_pc_ = NULL;
260   sim_->break_instr_ = 0;
261   return true;
262 }
263 
264 
UndoBreakpoints()265 void MipsDebugger::UndoBreakpoints() {
266   if (sim_->break_pc_ != NULL) {
267     sim_->break_pc_->SetInstructionBits(sim_->break_instr_);
268   }
269 }
270 
271 
RedoBreakpoints()272 void MipsDebugger::RedoBreakpoints() {
273   if (sim_->break_pc_ != NULL) {
274     sim_->break_pc_->SetInstructionBits(kBreakpointInstr);
275   }
276 }
277 
278 
PrintAllRegs()279 void MipsDebugger::PrintAllRegs() {
280 #define REG_INFO(n) Registers::Name(n), GetRegisterValue(n), GetRegisterValue(n)
281 
282   PrintF("\n");
283   // at, v0, a0.
284   PrintF("%3s: 0x%08x %10d\t%3s: 0x%08x %10d\t%3s: 0x%08x %10d\n",
285          REG_INFO(1), REG_INFO(2), REG_INFO(4));
286   // v1, a1.
287   PrintF("%26s\t%3s: 0x%08x %10d\t%3s: 0x%08x %10d\n",
288          "", REG_INFO(3), REG_INFO(5));
289   // a2.
290   PrintF("%26s\t%26s\t%3s: 0x%08x %10d\n", "", "", REG_INFO(6));
291   // a3.
292   PrintF("%26s\t%26s\t%3s: 0x%08x %10d\n", "", "", REG_INFO(7));
293   PrintF("\n");
294   // t0-t7, s0-s7
295   for (int i = 0; i < 8; i++) {
296     PrintF("%3s: 0x%08x %10d\t%3s: 0x%08x %10d\n",
297            REG_INFO(8+i), REG_INFO(16+i));
298   }
299   PrintF("\n");
300   // t8, k0, LO.
301   PrintF("%3s: 0x%08x %10d\t%3s: 0x%08x %10d\t%3s: 0x%08x %10d\n",
302          REG_INFO(24), REG_INFO(26), REG_INFO(32));
303   // t9, k1, HI.
304   PrintF("%3s: 0x%08x %10d\t%3s: 0x%08x %10d\t%3s: 0x%08x %10d\n",
305          REG_INFO(25), REG_INFO(27), REG_INFO(33));
306   // sp, fp, gp.
307   PrintF("%3s: 0x%08x %10d\t%3s: 0x%08x %10d\t%3s: 0x%08x %10d\n",
308          REG_INFO(29), REG_INFO(30), REG_INFO(28));
309   // pc.
310   PrintF("%3s: 0x%08x %10d\t%3s: 0x%08x %10d\n",
311          REG_INFO(31), REG_INFO(34));
312 
313 #undef REG_INFO
314 #undef FPU_REG_INFO
315 }
316 
317 
PrintAllRegsIncludingFPU()318 void MipsDebugger::PrintAllRegsIncludingFPU() {
319 #define FPU_REG_INFO32(n) FPURegisters::Name(n), FPURegisters::Name(n+1), \
320         GetFPURegisterValue32(n+1), \
321         GetFPURegisterValue32(n), \
322         GetFPURegisterValueDouble(n)
323 
324 #define FPU_REG_INFO64(n) FPURegisters::Name(n), \
325         GetFPURegisterValue64(n), \
326         GetFPURegisterValueDouble(n)
327 
328   PrintAllRegs();
329 
330   PrintF("\n\n");
331   // f0, f1, f2, ... f31.
332   // This must be a compile-time switch,
333   // compiler will throw out warnings otherwise.
334   if (kFpuMode == kFP64) {
335     PrintF("%3s: 0x%016llx %16.4e\n", FPU_REG_INFO64(0) );
336     PrintF("%3s: 0x%016llx %16.4e\n", FPU_REG_INFO64(1) );
337     PrintF("%3s: 0x%016llx %16.4e\n", FPU_REG_INFO64(2) );
338     PrintF("%3s: 0x%016llx %16.4e\n", FPU_REG_INFO64(3) );
339     PrintF("%3s: 0x%016llx %16.4e\n", FPU_REG_INFO64(4) );
340     PrintF("%3s: 0x%016llx %16.4e\n", FPU_REG_INFO64(5) );
341     PrintF("%3s: 0x%016llx %16.4e\n", FPU_REG_INFO64(6) );
342     PrintF("%3s: 0x%016llx %16.4e\n", FPU_REG_INFO64(7) );
343     PrintF("%3s: 0x%016llx %16.4e\n", FPU_REG_INFO64(8) );
344     PrintF("%3s: 0x%016llx %16.4e\n", FPU_REG_INFO64(9) );
345     PrintF("%3s: 0x%016llx %16.4e\n", FPU_REG_INFO64(10));
346     PrintF("%3s: 0x%016llx %16.4e\n", FPU_REG_INFO64(11));
347     PrintF("%3s: 0x%016llx %16.4e\n", FPU_REG_INFO64(12));
348     PrintF("%3s: 0x%016llx %16.4e\n", FPU_REG_INFO64(13));
349     PrintF("%3s: 0x%016llx %16.4e\n", FPU_REG_INFO64(14));
350     PrintF("%3s: 0x%016llx %16.4e\n", FPU_REG_INFO64(15));
351     PrintF("%3s: 0x%016llx %16.4e\n", FPU_REG_INFO64(16));
352     PrintF("%3s: 0x%016llx %16.4e\n", FPU_REG_INFO64(17));
353     PrintF("%3s: 0x%016llx %16.4e\n", FPU_REG_INFO64(18));
354     PrintF("%3s: 0x%016llx %16.4e\n", FPU_REG_INFO64(19));
355     PrintF("%3s: 0x%016llx %16.4e\n", FPU_REG_INFO64(20));
356     PrintF("%3s: 0x%016llx %16.4e\n", FPU_REG_INFO64(21));
357     PrintF("%3s: 0x%016llx %16.4e\n", FPU_REG_INFO64(22));
358     PrintF("%3s: 0x%016llx %16.4e\n", FPU_REG_INFO64(23));
359     PrintF("%3s: 0x%016llx %16.4e\n", FPU_REG_INFO64(24));
360     PrintF("%3s: 0x%016llx %16.4e\n", FPU_REG_INFO64(25));
361     PrintF("%3s: 0x%016llx %16.4e\n", FPU_REG_INFO64(26));
362     PrintF("%3s: 0x%016llx %16.4e\n", FPU_REG_INFO64(27));
363     PrintF("%3s: 0x%016llx %16.4e\n", FPU_REG_INFO64(28));
364     PrintF("%3s: 0x%016llx %16.4e\n", FPU_REG_INFO64(29));
365     PrintF("%3s: 0x%016llx %16.4e\n", FPU_REG_INFO64(30));
366     PrintF("%3s: 0x%016llx %16.4e\n", FPU_REG_INFO64(31));
367   } else {
368     PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO32(0) );
369     PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO32(2) );
370     PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO32(4) );
371     PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO32(6) );
372     PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO32(8) );
373     PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO32(10));
374     PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO32(12));
375     PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO32(14));
376     PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO32(16));
377     PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO32(18));
378     PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO32(20));
379     PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO32(22));
380     PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO32(24));
381     PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO32(26));
382     PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO32(28));
383     PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO32(30));
384   }
385 
386 #undef REG_INFO
387 #undef FPU_REG_INFO32
388 #undef FPU_REG_INFO64
389 }
390 
391 
Debug()392 void MipsDebugger::Debug() {
393   intptr_t last_pc = -1;
394   bool done = false;
395 
396 #define COMMAND_SIZE 63
397 #define ARG_SIZE 255
398 
399 #define STR(a) #a
400 #define XSTR(a) STR(a)
401 
402   char cmd[COMMAND_SIZE + 1];
403   char arg1[ARG_SIZE + 1];
404   char arg2[ARG_SIZE + 1];
405   char* argv[3] = { cmd, arg1, arg2 };
406 
407   // Make sure to have a proper terminating character if reaching the limit.
408   cmd[COMMAND_SIZE] = 0;
409   arg1[ARG_SIZE] = 0;
410   arg2[ARG_SIZE] = 0;
411 
412   // Undo all set breakpoints while running in the debugger shell. This will
413   // make them invisible to all commands.
414   UndoBreakpoints();
415 
416   while (!done && (sim_->get_pc() != Simulator::end_sim_pc)) {
417     if (last_pc != sim_->get_pc()) {
418       disasm::NameConverter converter;
419       disasm::Disassembler dasm(converter);
420       // Use a reasonably large buffer.
421       v8::internal::EmbeddedVector<char, 256> buffer;
422       dasm.InstructionDecode(buffer,
423                              reinterpret_cast<byte*>(sim_->get_pc()));
424       PrintF("  0x%08x  %s\n", sim_->get_pc(), buffer.start());
425       last_pc = sim_->get_pc();
426     }
427     char* line = ReadLine("sim> ");
428     if (line == NULL) {
429       break;
430     } else {
431       char* last_input = sim_->last_debugger_input();
432       if (strcmp(line, "\n") == 0 && last_input != NULL) {
433         line = last_input;
434       } else {
435         // Ownership is transferred to sim_;
436         sim_->set_last_debugger_input(line);
437       }
438       // Use sscanf to parse the individual parts of the command line. At the
439       // moment no command expects more than two parameters.
440       int argc = SScanF(line,
441                         "%" XSTR(COMMAND_SIZE) "s "
442                         "%" XSTR(ARG_SIZE) "s "
443                         "%" XSTR(ARG_SIZE) "s",
444                         cmd, arg1, arg2);
445       if ((strcmp(cmd, "si") == 0) || (strcmp(cmd, "stepi") == 0)) {
446         Instruction* instr = reinterpret_cast<Instruction*>(sim_->get_pc());
447         if (!(instr->IsTrap()) ||
448             instr->InstructionBits() == rtCallRedirInstr) {
449           sim_->InstructionDecode(
450               reinterpret_cast<Instruction*>(sim_->get_pc()));
451         } else {
452           // Allow si to jump over generated breakpoints.
453           PrintF("/!\\ Jumping over generated breakpoint.\n");
454           sim_->set_pc(sim_->get_pc() + Instruction::kInstrSize);
455         }
456       } else if ((strcmp(cmd, "c") == 0) || (strcmp(cmd, "cont") == 0)) {
457         // Execute the one instruction we broke at with breakpoints disabled.
458         sim_->InstructionDecode(reinterpret_cast<Instruction*>(sim_->get_pc()));
459         // Leave the debugger shell.
460         done = true;
461       } else if ((strcmp(cmd, "p") == 0) || (strcmp(cmd, "print") == 0)) {
462         if (argc == 2) {
463           if (strcmp(arg1, "all") == 0) {
464             PrintAllRegs();
465           } else if (strcmp(arg1, "allf") == 0) {
466             PrintAllRegsIncludingFPU();
467           } else {
468             int regnum = Registers::Number(arg1);
469             int fpuregnum = FPURegisters::Number(arg1);
470 
471             if (regnum != kInvalidRegister) {
472               int32_t value;
473               value = GetRegisterValue(regnum);
474               PrintF("%s: 0x%08x %d \n", arg1, value, value);
475             } else if (fpuregnum != kInvalidFPURegister) {
476               if (IsFp64Mode()) {
477                 int64_t value;
478                 double dvalue;
479                 value = GetFPURegisterValue64(fpuregnum);
480                 dvalue = GetFPURegisterValueDouble(fpuregnum);
481                 PrintF("%3s: 0x%016llx %16.4e\n",
482                        FPURegisters::Name(fpuregnum), value, dvalue);
483               } else {
484                 if (fpuregnum % 2 == 1) {
485                   int32_t value;
486                   float fvalue;
487                   value = GetFPURegisterValue32(fpuregnum);
488                   fvalue = GetFPURegisterValueFloat(fpuregnum);
489                   PrintF("%s: 0x%08x %11.4e\n", arg1, value, fvalue);
490                 } else {
491                   double dfvalue;
492                   int32_t lvalue1 = GetFPURegisterValue32(fpuregnum);
493                   int32_t lvalue2 = GetFPURegisterValue32(fpuregnum + 1);
494                   dfvalue = GetFPURegisterValueDouble(fpuregnum);
495                   PrintF("%3s,%3s: 0x%08x%08x %16.4e\n",
496                          FPURegisters::Name(fpuregnum+1),
497                          FPURegisters::Name(fpuregnum),
498                          lvalue1,
499                          lvalue2,
500                          dfvalue);
501                 }
502               }
503             } else {
504               PrintF("%s unrecognized\n", arg1);
505             }
506           }
507         } else {
508           if (argc == 3) {
509             if (strcmp(arg2, "single") == 0) {
510               int32_t value;
511               float fvalue;
512               int fpuregnum = FPURegisters::Number(arg1);
513 
514               if (fpuregnum != kInvalidFPURegister) {
515                 value = GetFPURegisterValue32(fpuregnum);
516                 fvalue = GetFPURegisterValueFloat(fpuregnum);
517                 PrintF("%s: 0x%08x %11.4e\n", arg1, value, fvalue);
518               } else {
519                 PrintF("%s unrecognized\n", arg1);
520               }
521             } else {
522               PrintF("print <fpu register> single\n");
523             }
524           } else {
525             PrintF("print <register> or print <fpu register> single\n");
526           }
527         }
528       } else if ((strcmp(cmd, "po") == 0)
529                  || (strcmp(cmd, "printobject") == 0)) {
530         if (argc == 2) {
531           int32_t value;
532           OFStream os(stdout);
533           if (GetValue(arg1, &value)) {
534             Object* obj = reinterpret_cast<Object*>(value);
535             os << arg1 << ": \n";
536 #ifdef DEBUG
537             obj->Print(os);
538             os << "\n";
539 #else
540             os << Brief(obj) << "\n";
541 #endif
542           } else {
543             os << arg1 << " unrecognized\n";
544           }
545         } else {
546           PrintF("printobject <value>\n");
547         }
548       } else if (strcmp(cmd, "stack") == 0 || strcmp(cmd, "mem") == 0) {
549         int32_t* cur = NULL;
550         int32_t* end = NULL;
551         int next_arg = 1;
552 
553         if (strcmp(cmd, "stack") == 0) {
554           cur = reinterpret_cast<int32_t*>(sim_->get_register(Simulator::sp));
555         } else {  // Command "mem".
556           int32_t value;
557           if (!GetValue(arg1, &value)) {
558             PrintF("%s unrecognized\n", arg1);
559             continue;
560           }
561           cur = reinterpret_cast<int32_t*>(value);
562           next_arg++;
563         }
564 
565         // TODO(palfia): optimize this.
566         if (IsFp64Mode()) {
567           int64_t words;
568           if (argc == next_arg) {
569             words = 10;
570           } else {
571             if (!GetValue(argv[next_arg], &words)) {
572               words = 10;
573             }
574           }
575           end = cur + words;
576         } else {
577           int32_t words;
578           if (argc == next_arg) {
579             words = 10;
580           } else {
581             if (!GetValue(argv[next_arg], &words)) {
582               words = 10;
583             }
584           }
585           end = cur + words;
586         }
587 
588         while (cur < end) {
589           PrintF("  0x%08x:  0x%08x %10d",
590                  reinterpret_cast<intptr_t>(cur), *cur, *cur);
591           HeapObject* obj = reinterpret_cast<HeapObject*>(*cur);
592           int value = *cur;
593           Heap* current_heap = v8::internal::Isolate::Current()->heap();
594           if (((value & 1) == 0) || current_heap->Contains(obj)) {
595             PrintF(" (");
596             if ((value & 1) == 0) {
597               PrintF("smi %d", value / 2);
598             } else {
599               obj->ShortPrint();
600             }
601             PrintF(")");
602           }
603           PrintF("\n");
604           cur++;
605         }
606 
607       } else if ((strcmp(cmd, "disasm") == 0) ||
608                  (strcmp(cmd, "dpc") == 0) ||
609                  (strcmp(cmd, "di") == 0)) {
610         disasm::NameConverter converter;
611         disasm::Disassembler dasm(converter);
612         // Use a reasonably large buffer.
613         v8::internal::EmbeddedVector<char, 256> buffer;
614 
615         byte* cur = NULL;
616         byte* end = NULL;
617 
618         if (argc == 1) {
619           cur = reinterpret_cast<byte*>(sim_->get_pc());
620           end = cur + (10 * Instruction::kInstrSize);
621         } else if (argc == 2) {
622           int regnum = Registers::Number(arg1);
623           if (regnum != kInvalidRegister || strncmp(arg1, "0x", 2) == 0) {
624             // The argument is an address or a register name.
625             int32_t value;
626             if (GetValue(arg1, &value)) {
627               cur = reinterpret_cast<byte*>(value);
628               // Disassemble 10 instructions at <arg1>.
629               end = cur + (10 * Instruction::kInstrSize);
630             }
631           } else {
632             // The argument is the number of instructions.
633             int32_t value;
634             if (GetValue(arg1, &value)) {
635               cur = reinterpret_cast<byte*>(sim_->get_pc());
636               // Disassemble <arg1> instructions.
637               end = cur + (value * Instruction::kInstrSize);
638             }
639           }
640         } else {
641           int32_t value1;
642           int32_t value2;
643           if (GetValue(arg1, &value1) && GetValue(arg2, &value2)) {
644             cur = reinterpret_cast<byte*>(value1);
645             end = cur + (value2 * Instruction::kInstrSize);
646           }
647         }
648 
649         while (cur < end) {
650           dasm.InstructionDecode(buffer, cur);
651           PrintF("  0x%08x  %s\n",
652               reinterpret_cast<intptr_t>(cur), buffer.start());
653           cur += Instruction::kInstrSize;
654         }
655       } else if (strcmp(cmd, "gdb") == 0) {
656         PrintF("relinquishing control to gdb\n");
657         v8::base::OS::DebugBreak();
658         PrintF("regaining control from gdb\n");
659       } else if (strcmp(cmd, "break") == 0) {
660         if (argc == 2) {
661           int32_t value;
662           if (GetValue(arg1, &value)) {
663             if (!SetBreakpoint(reinterpret_cast<Instruction*>(value))) {
664               PrintF("setting breakpoint failed\n");
665             }
666           } else {
667             PrintF("%s unrecognized\n", arg1);
668           }
669         } else {
670           PrintF("break <address>\n");
671         }
672       } else if (strcmp(cmd, "del") == 0) {
673         if (!DeleteBreakpoint(NULL)) {
674           PrintF("deleting breakpoint failed\n");
675         }
676       } else if (strcmp(cmd, "flags") == 0) {
677         PrintF("No flags on MIPS !\n");
678       } else if (strcmp(cmd, "stop") == 0) {
679         int32_t value;
680         intptr_t stop_pc = sim_->get_pc() -
681             2 * Instruction::kInstrSize;
682         Instruction* stop_instr = reinterpret_cast<Instruction*>(stop_pc);
683         Instruction* msg_address =
684           reinterpret_cast<Instruction*>(stop_pc +
685               Instruction::kInstrSize);
686         if ((argc == 2) && (strcmp(arg1, "unstop") == 0)) {
687           // Remove the current stop.
688           if (sim_->IsStopInstruction(stop_instr)) {
689             stop_instr->SetInstructionBits(kNopInstr);
690             msg_address->SetInstructionBits(kNopInstr);
691           } else {
692             PrintF("Not at debugger stop.\n");
693           }
694         } else if (argc == 3) {
695           // Print information about all/the specified breakpoint(s).
696           if (strcmp(arg1, "info") == 0) {
697             if (strcmp(arg2, "all") == 0) {
698               PrintF("Stop information:\n");
699               for (uint32_t i = kMaxWatchpointCode + 1;
700                    i <= kMaxStopCode;
701                    i++) {
702                 sim_->PrintStopInfo(i);
703               }
704             } else if (GetValue(arg2, &value)) {
705               sim_->PrintStopInfo(value);
706             } else {
707               PrintF("Unrecognized argument.\n");
708             }
709           } else if (strcmp(arg1, "enable") == 0) {
710             // Enable all/the specified breakpoint(s).
711             if (strcmp(arg2, "all") == 0) {
712               for (uint32_t i = kMaxWatchpointCode + 1;
713                    i <= kMaxStopCode;
714                    i++) {
715                 sim_->EnableStop(i);
716               }
717             } else if (GetValue(arg2, &value)) {
718               sim_->EnableStop(value);
719             } else {
720               PrintF("Unrecognized argument.\n");
721             }
722           } else if (strcmp(arg1, "disable") == 0) {
723             // Disable all/the specified breakpoint(s).
724             if (strcmp(arg2, "all") == 0) {
725               for (uint32_t i = kMaxWatchpointCode + 1;
726                    i <= kMaxStopCode;
727                    i++) {
728                 sim_->DisableStop(i);
729               }
730             } else if (GetValue(arg2, &value)) {
731               sim_->DisableStop(value);
732             } else {
733               PrintF("Unrecognized argument.\n");
734             }
735           }
736         } else {
737           PrintF("Wrong usage. Use help command for more information.\n");
738         }
739       } else if ((strcmp(cmd, "stat") == 0) || (strcmp(cmd, "st") == 0)) {
740         // Print registers and disassemble.
741         PrintAllRegs();
742         PrintF("\n");
743 
744         disasm::NameConverter converter;
745         disasm::Disassembler dasm(converter);
746         // Use a reasonably large buffer.
747         v8::internal::EmbeddedVector<char, 256> buffer;
748 
749         byte* cur = NULL;
750         byte* end = NULL;
751 
752         if (argc == 1) {
753           cur = reinterpret_cast<byte*>(sim_->get_pc());
754           end = cur + (10 * Instruction::kInstrSize);
755         } else if (argc == 2) {
756           int32_t value;
757           if (GetValue(arg1, &value)) {
758             cur = reinterpret_cast<byte*>(value);
759             // no length parameter passed, assume 10 instructions
760             end = cur + (10 * Instruction::kInstrSize);
761           }
762         } else {
763           int32_t value1;
764           int32_t value2;
765           if (GetValue(arg1, &value1) && GetValue(arg2, &value2)) {
766             cur = reinterpret_cast<byte*>(value1);
767             end = cur + (value2 * Instruction::kInstrSize);
768           }
769         }
770 
771         while (cur < end) {
772           dasm.InstructionDecode(buffer, cur);
773           PrintF("  0x%08x  %s\n",
774                  reinterpret_cast<intptr_t>(cur), buffer.start());
775           cur += Instruction::kInstrSize;
776         }
777       } else if ((strcmp(cmd, "h") == 0) || (strcmp(cmd, "help") == 0)) {
778         PrintF("cont\n");
779         PrintF("  continue execution (alias 'c')\n");
780         PrintF("stepi\n");
781         PrintF("  step one instruction (alias 'si')\n");
782         PrintF("print <register>\n");
783         PrintF("  print register content (alias 'p')\n");
784         PrintF("  use register name 'all' to print all registers\n");
785         PrintF("printobject <register>\n");
786         PrintF("  print an object from a register (alias 'po')\n");
787         PrintF("stack [<words>]\n");
788         PrintF("  dump stack content, default dump 10 words)\n");
789         PrintF("mem <address> [<words>]\n");
790         PrintF("  dump memory content, default dump 10 words)\n");
791         PrintF("flags\n");
792         PrintF("  print flags\n");
793         PrintF("disasm [<instructions>]\n");
794         PrintF("disasm [<address/register>]\n");
795         PrintF("disasm [[<address/register>] <instructions>]\n");
796         PrintF("  disassemble code, default is 10 instructions\n");
797         PrintF("  from pc (alias 'di')\n");
798         PrintF("gdb\n");
799         PrintF("  enter gdb\n");
800         PrintF("break <address>\n");
801         PrintF("  set a break point on the address\n");
802         PrintF("del\n");
803         PrintF("  delete the breakpoint\n");
804         PrintF("stop feature:\n");
805         PrintF("  Description:\n");
806         PrintF("    Stops are debug instructions inserted by\n");
807         PrintF("    the Assembler::stop() function.\n");
808         PrintF("    When hitting a stop, the Simulator will\n");
809         PrintF("    stop and and give control to the Debugger.\n");
810         PrintF("    All stop codes are watched:\n");
811         PrintF("    - They can be enabled / disabled: the Simulator\n");
812         PrintF("       will / won't stop when hitting them.\n");
813         PrintF("    - The Simulator keeps track of how many times they \n");
814         PrintF("      are met. (See the info command.) Going over a\n");
815         PrintF("      disabled stop still increases its counter. \n");
816         PrintF("  Commands:\n");
817         PrintF("    stop info all/<code> : print infos about number <code>\n");
818         PrintF("      or all stop(s).\n");
819         PrintF("    stop enable/disable all/<code> : enables / disables\n");
820         PrintF("      all or number <code> stop(s)\n");
821         PrintF("    stop unstop\n");
822         PrintF("      ignore the stop instruction at the current location\n");
823         PrintF("      from now on\n");
824       } else {
825         PrintF("Unknown command: %s\n", cmd);
826       }
827     }
828   }
829 
830   // Add all the breakpoints back to stop execution and enter the debugger
831   // shell when hit.
832   RedoBreakpoints();
833 
834 #undef COMMAND_SIZE
835 #undef ARG_SIZE
836 
837 #undef STR
838 #undef XSTR
839 }
840 
841 
ICacheMatch(void * one,void * two)842 static bool ICacheMatch(void* one, void* two) {
843   DCHECK((reinterpret_cast<intptr_t>(one) & CachePage::kPageMask) == 0);
844   DCHECK((reinterpret_cast<intptr_t>(two) & CachePage::kPageMask) == 0);
845   return one == two;
846 }
847 
848 
ICacheHash(void * key)849 static uint32_t ICacheHash(void* key) {
850   return static_cast<uint32_t>(reinterpret_cast<uintptr_t>(key)) >> 2;
851 }
852 
853 
AllOnOnePage(uintptr_t start,int size)854 static bool AllOnOnePage(uintptr_t start, int size) {
855   intptr_t start_page = (start & ~CachePage::kPageMask);
856   intptr_t end_page = ((start + size) & ~CachePage::kPageMask);
857   return start_page == end_page;
858 }
859 
860 
set_last_debugger_input(char * input)861 void Simulator::set_last_debugger_input(char* input) {
862   DeleteArray(last_debugger_input_);
863   last_debugger_input_ = input;
864 }
865 
866 
FlushICache(v8::internal::HashMap * i_cache,void * start_addr,size_t size)867 void Simulator::FlushICache(v8::internal::HashMap* i_cache,
868                             void* start_addr,
869                             size_t size) {
870   intptr_t start = reinterpret_cast<intptr_t>(start_addr);
871   int intra_line = (start & CachePage::kLineMask);
872   start -= intra_line;
873   size += intra_line;
874   size = ((size - 1) | CachePage::kLineMask) + 1;
875   int offset = (start & CachePage::kPageMask);
876   while (!AllOnOnePage(start, size - 1)) {
877     int bytes_to_flush = CachePage::kPageSize - offset;
878     FlushOnePage(i_cache, start, bytes_to_flush);
879     start += bytes_to_flush;
880     size -= bytes_to_flush;
881     DCHECK_EQ(0, start & CachePage::kPageMask);
882     offset = 0;
883   }
884   if (size != 0) {
885     FlushOnePage(i_cache, start, size);
886   }
887 }
888 
889 
GetCachePage(v8::internal::HashMap * i_cache,void * page)890 CachePage* Simulator::GetCachePage(v8::internal::HashMap* i_cache, void* page) {
891   v8::internal::HashMap::Entry* entry = i_cache->Lookup(page,
892                                                         ICacheHash(page),
893                                                         true);
894   if (entry->value == NULL) {
895     CachePage* new_page = new CachePage();
896     entry->value = new_page;
897   }
898   return reinterpret_cast<CachePage*>(entry->value);
899 }
900 
901 
902 // Flush from start up to and not including start + size.
FlushOnePage(v8::internal::HashMap * i_cache,intptr_t start,int size)903 void Simulator::FlushOnePage(v8::internal::HashMap* i_cache,
904                              intptr_t start,
905                              int size) {
906   DCHECK(size <= CachePage::kPageSize);
907   DCHECK(AllOnOnePage(start, size - 1));
908   DCHECK((start & CachePage::kLineMask) == 0);
909   DCHECK((size & CachePage::kLineMask) == 0);
910   void* page = reinterpret_cast<void*>(start & (~CachePage::kPageMask));
911   int offset = (start & CachePage::kPageMask);
912   CachePage* cache_page = GetCachePage(i_cache, page);
913   char* valid_bytemap = cache_page->ValidityByte(offset);
914   memset(valid_bytemap, CachePage::LINE_INVALID, size >> CachePage::kLineShift);
915 }
916 
917 
CheckICache(v8::internal::HashMap * i_cache,Instruction * instr)918 void Simulator::CheckICache(v8::internal::HashMap* i_cache,
919                             Instruction* instr) {
920   intptr_t address = reinterpret_cast<intptr_t>(instr);
921   void* page = reinterpret_cast<void*>(address & (~CachePage::kPageMask));
922   void* line = reinterpret_cast<void*>(address & (~CachePage::kLineMask));
923   int offset = (address & CachePage::kPageMask);
924   CachePage* cache_page = GetCachePage(i_cache, page);
925   char* cache_valid_byte = cache_page->ValidityByte(offset);
926   bool cache_hit = (*cache_valid_byte == CachePage::LINE_VALID);
927   char* cached_line = cache_page->CachedData(offset & ~CachePage::kLineMask);
928   if (cache_hit) {
929     // Check that the data in memory matches the contents of the I-cache.
930     CHECK_EQ(0, memcmp(reinterpret_cast<void*>(instr),
931                        cache_page->CachedData(offset),
932                        Instruction::kInstrSize));
933   } else {
934     // Cache miss.  Load memory into the cache.
935     memcpy(cached_line, line, CachePage::kLineLength);
936     *cache_valid_byte = CachePage::LINE_VALID;
937   }
938 }
939 
940 
Initialize(Isolate * isolate)941 void Simulator::Initialize(Isolate* isolate) {
942   if (isolate->simulator_initialized()) return;
943   isolate->set_simulator_initialized(true);
944   ::v8::internal::ExternalReference::set_redirector(isolate,
945                                                     &RedirectExternalReference);
946 }
947 
948 
Simulator(Isolate * isolate)949 Simulator::Simulator(Isolate* isolate) : isolate_(isolate) {
950   i_cache_ = isolate_->simulator_i_cache();
951   if (i_cache_ == NULL) {
952     i_cache_ = new v8::internal::HashMap(&ICacheMatch);
953     isolate_->set_simulator_i_cache(i_cache_);
954   }
955   Initialize(isolate);
956   // Set up simulator support first. Some of this information is needed to
957   // setup the architecture state.
958   stack_ = reinterpret_cast<char*>(malloc(stack_size_));
959   pc_modified_ = false;
960   icount_ = 0;
961   break_count_ = 0;
962   break_pc_ = NULL;
963   break_instr_ = 0;
964 
965   // Set up architecture state.
966   // All registers are initialized to zero to start with.
967   for (int i = 0; i < kNumSimuRegisters; i++) {
968     registers_[i] = 0;
969   }
970   for (int i = 0; i < kNumFPURegisters; i++) {
971     FPUregisters_[i] = 0;
972   }
973   FCSR_ = 0;
974 
975   // The sp is initialized to point to the bottom (high address) of the
976   // allocated stack area. To be safe in potential stack underflows we leave
977   // some buffer below.
978   registers_[sp] = reinterpret_cast<int32_t>(stack_) + stack_size_ - 64;
979   // The ra and pc are initialized to a known bad value that will cause an
980   // access violation if the simulator ever tries to execute it.
981   registers_[pc] = bad_ra;
982   registers_[ra] = bad_ra;
983   InitializeCoverage();
984   for (int i = 0; i < kNumExceptions; i++) {
985     exceptions[i] = 0;
986   }
987 
988   last_debugger_input_ = NULL;
989 }
990 
991 
~Simulator()992 Simulator::~Simulator() {
993 }
994 
995 
996 // When the generated code calls an external reference we need to catch that in
997 // the simulator.  The external reference will be a function compiled for the
998 // host architecture.  We need to call that function instead of trying to
999 // execute it with the simulator.  We do that by redirecting the external
1000 // reference to a swi (software-interrupt) instruction that is handled by
1001 // the simulator.  We write the original destination of the jump just at a known
1002 // offset from the swi instruction so the simulator knows what to call.
1003 class Redirection {
1004  public:
Redirection(void * external_function,ExternalReference::Type type)1005   Redirection(void* external_function, ExternalReference::Type type)
1006       : external_function_(external_function),
1007         swi_instruction_(rtCallRedirInstr),
1008         type_(type),
1009         next_(NULL) {
1010     Isolate* isolate = Isolate::Current();
1011     next_ = isolate->simulator_redirection();
1012     Simulator::current(isolate)->
1013         FlushICache(isolate->simulator_i_cache(),
1014                     reinterpret_cast<void*>(&swi_instruction_),
1015                     Instruction::kInstrSize);
1016     isolate->set_simulator_redirection(this);
1017   }
1018 
address_of_swi_instruction()1019   void* address_of_swi_instruction() {
1020     return reinterpret_cast<void*>(&swi_instruction_);
1021   }
1022 
external_function()1023   void* external_function() { return external_function_; }
type()1024   ExternalReference::Type type() { return type_; }
1025 
Get(void * external_function,ExternalReference::Type type)1026   static Redirection* Get(void* external_function,
1027                           ExternalReference::Type type) {
1028     Isolate* isolate = Isolate::Current();
1029     Redirection* current = isolate->simulator_redirection();
1030     for (; current != NULL; current = current->next_) {
1031       if (current->external_function_ == external_function) return current;
1032     }
1033     return new Redirection(external_function, type);
1034   }
1035 
FromSwiInstruction(Instruction * swi_instruction)1036   static Redirection* FromSwiInstruction(Instruction* swi_instruction) {
1037     char* addr_of_swi = reinterpret_cast<char*>(swi_instruction);
1038     char* addr_of_redirection =
1039         addr_of_swi - OFFSET_OF(Redirection, swi_instruction_);
1040     return reinterpret_cast<Redirection*>(addr_of_redirection);
1041   }
1042 
ReverseRedirection(int32_t reg)1043   static void* ReverseRedirection(int32_t reg) {
1044     Redirection* redirection = FromSwiInstruction(
1045         reinterpret_cast<Instruction*>(reinterpret_cast<void*>(reg)));
1046     return redirection->external_function();
1047   }
1048 
1049  private:
1050   void* external_function_;
1051   uint32_t swi_instruction_;
1052   ExternalReference::Type type_;
1053   Redirection* next_;
1054 };
1055 
1056 
RedirectExternalReference(void * external_function,ExternalReference::Type type)1057 void* Simulator::RedirectExternalReference(void* external_function,
1058                                            ExternalReference::Type type) {
1059   Redirection* redirection = Redirection::Get(external_function, type);
1060   return redirection->address_of_swi_instruction();
1061 }
1062 
1063 
1064 // Get the active Simulator for the current thread.
current(Isolate * isolate)1065 Simulator* Simulator::current(Isolate* isolate) {
1066   v8::internal::Isolate::PerIsolateThreadData* isolate_data =
1067        isolate->FindOrAllocatePerThreadDataForThisThread();
1068   DCHECK(isolate_data != NULL);
1069   DCHECK(isolate_data != NULL);
1070 
1071   Simulator* sim = isolate_data->simulator();
1072   if (sim == NULL) {
1073     // TODO(146): delete the simulator object when a thread/isolate goes away.
1074     sim = new Simulator(isolate);
1075     isolate_data->set_simulator(sim);
1076   }
1077   return sim;
1078 }
1079 
1080 
1081 // Sets the register in the architecture state. It will also deal with updating
1082 // Simulator internal state for special registers such as PC.
set_register(int reg,int32_t value)1083 void Simulator::set_register(int reg, int32_t value) {
1084   DCHECK((reg >= 0) && (reg < kNumSimuRegisters));
1085   if (reg == pc) {
1086     pc_modified_ = true;
1087   }
1088 
1089   // Zero register always holds 0.
1090   registers_[reg] = (reg == 0) ? 0 : value;
1091 }
1092 
1093 
set_dw_register(int reg,const int * dbl)1094 void Simulator::set_dw_register(int reg, const int* dbl) {
1095   DCHECK((reg >= 0) && (reg < kNumSimuRegisters));
1096   registers_[reg] = dbl[0];
1097   registers_[reg + 1] = dbl[1];
1098 }
1099 
1100 
set_fpu_register(int fpureg,int64_t value)1101 void Simulator::set_fpu_register(int fpureg, int64_t value) {
1102   DCHECK(IsFp64Mode());
1103   DCHECK((fpureg >= 0) && (fpureg < kNumFPURegisters));
1104   FPUregisters_[fpureg] = value;
1105 }
1106 
1107 
set_fpu_register_word(int fpureg,int32_t value)1108 void Simulator::set_fpu_register_word(int fpureg, int32_t value) {
1109   // Set ONLY lower 32-bits, leaving upper bits untouched.
1110   // TODO(plind): big endian issue.
1111   DCHECK((fpureg >= 0) && (fpureg < kNumFPURegisters));
1112   int32_t *pword = reinterpret_cast<int32_t*>(&FPUregisters_[fpureg]);
1113   *pword = value;
1114 }
1115 
1116 
set_fpu_register_hi_word(int fpureg,int32_t value)1117 void Simulator::set_fpu_register_hi_word(int fpureg, int32_t value) {
1118   // Set ONLY upper 32-bits, leaving lower bits untouched.
1119   // TODO(plind): big endian issue.
1120   DCHECK((fpureg >= 0) && (fpureg < kNumFPURegisters));
1121   int32_t *phiword = (reinterpret_cast<int32_t*>(&FPUregisters_[fpureg])) + 1;
1122   *phiword = value;
1123 }
1124 
1125 
set_fpu_register_float(int fpureg,float value)1126 void Simulator::set_fpu_register_float(int fpureg, float value) {
1127   DCHECK((fpureg >= 0) && (fpureg < kNumFPURegisters));
1128   *bit_cast<float*>(&FPUregisters_[fpureg]) = value;
1129 }
1130 
1131 
set_fpu_register_double(int fpureg,double value)1132 void Simulator::set_fpu_register_double(int fpureg, double value) {
1133   if (IsFp64Mode()) {
1134     DCHECK((fpureg >= 0) && (fpureg < kNumFPURegisters));
1135     *bit_cast<double*>(&FPUregisters_[fpureg]) = value;
1136   } else {
1137     DCHECK((fpureg >= 0) && (fpureg < kNumFPURegisters) && ((fpureg % 2) == 0));
1138     int64_t i64 = bit_cast<int64_t>(value);
1139     set_fpu_register_word(fpureg, i64 & 0xffffffff);
1140     set_fpu_register_word(fpureg + 1, i64 >> 32);
1141   }
1142 }
1143 
1144 
1145 // Get the register from the architecture state. This function does handle
1146 // the special case of accessing the PC register.
get_register(int reg) const1147 int32_t Simulator::get_register(int reg) const {
1148   DCHECK((reg >= 0) && (reg < kNumSimuRegisters));
1149   if (reg == 0)
1150     return 0;
1151   else
1152     return registers_[reg] + ((reg == pc) ? Instruction::kPCReadOffset : 0);
1153 }
1154 
1155 
get_double_from_register_pair(int reg)1156 double Simulator::get_double_from_register_pair(int reg) {
1157   // TODO(plind): bad ABI stuff, refactor or remove.
1158   DCHECK((reg >= 0) && (reg < kNumSimuRegisters) && ((reg % 2) == 0));
1159 
1160   double dm_val = 0.0;
1161   // Read the bits from the unsigned integer register_[] array
1162   // into the double precision floating point value and return it.
1163   char buffer[2 * sizeof(registers_[0])];
1164   memcpy(buffer, &registers_[reg], 2 * sizeof(registers_[0]));
1165   memcpy(&dm_val, buffer, 2 * sizeof(registers_[0]));
1166   return(dm_val);
1167 }
1168 
1169 
get_fpu_register(int fpureg) const1170 int64_t Simulator::get_fpu_register(int fpureg) const {
1171   DCHECK(IsFp64Mode());
1172   DCHECK((fpureg >= 0) && (fpureg < kNumFPURegisters));
1173   return FPUregisters_[fpureg];
1174 }
1175 
1176 
get_fpu_register_word(int fpureg) const1177 int32_t Simulator::get_fpu_register_word(int fpureg) const {
1178   DCHECK((fpureg >= 0) && (fpureg < kNumFPURegisters));
1179   return static_cast<int32_t>(FPUregisters_[fpureg] & 0xffffffff);
1180 }
1181 
1182 
get_fpu_register_signed_word(int fpureg) const1183 int32_t Simulator::get_fpu_register_signed_word(int fpureg) const {
1184   DCHECK((fpureg >= 0) && (fpureg < kNumFPURegisters));
1185   return static_cast<int32_t>(FPUregisters_[fpureg] & 0xffffffff);
1186 }
1187 
1188 
get_fpu_register_hi_word(int fpureg) const1189 int32_t Simulator::get_fpu_register_hi_word(int fpureg) const {
1190   DCHECK((fpureg >= 0) && (fpureg < kNumFPURegisters));
1191   return static_cast<int32_t>((FPUregisters_[fpureg] >> 32) & 0xffffffff);
1192 }
1193 
1194 
get_fpu_register_float(int fpureg) const1195 float Simulator::get_fpu_register_float(int fpureg) const {
1196   DCHECK((fpureg >= 0) && (fpureg < kNumFPURegisters));
1197   return *bit_cast<float*>(const_cast<int64_t*>(&FPUregisters_[fpureg]));
1198 }
1199 
1200 
get_fpu_register_double(int fpureg) const1201 double Simulator::get_fpu_register_double(int fpureg) const {
1202   if (IsFp64Mode()) {
1203     DCHECK((fpureg >= 0) && (fpureg < kNumFPURegisters));
1204     return *bit_cast<double*>(&FPUregisters_[fpureg]);
1205   } else {
1206     DCHECK((fpureg >= 0) && (fpureg < kNumFPURegisters) && ((fpureg % 2) == 0));
1207     int64_t i64;
1208     i64 = static_cast<uint32_t>(get_fpu_register_word(fpureg));
1209     i64 |= static_cast<uint64_t>(get_fpu_register_word(fpureg + 1)) << 32;
1210     return bit_cast<double>(i64);
1211   }
1212 }
1213 
1214 
1215 // Runtime FP routines take up to two double arguments and zero
1216 // or one integer arguments. All are constructed here,
1217 // from a0-a3 or f12 and f14.
GetFpArgs(double * x,double * y,int32_t * z)1218 void Simulator::GetFpArgs(double* x, double* y, int32_t* z) {
1219   if (!IsMipsSoftFloatABI) {
1220     *x = get_fpu_register_double(12);
1221     *y = get_fpu_register_double(14);
1222     *z = get_register(a2);
1223   } else {
1224     // TODO(plind): bad ABI stuff, refactor or remove.
1225     // We use a char buffer to get around the strict-aliasing rules which
1226     // otherwise allow the compiler to optimize away the copy.
1227     char buffer[sizeof(*x)];
1228     int32_t* reg_buffer = reinterpret_cast<int32_t*>(buffer);
1229 
1230     // Registers a0 and a1 -> x.
1231     reg_buffer[0] = get_register(a0);
1232     reg_buffer[1] = get_register(a1);
1233     memcpy(x, buffer, sizeof(buffer));
1234     // Registers a2 and a3 -> y.
1235     reg_buffer[0] = get_register(a2);
1236     reg_buffer[1] = get_register(a3);
1237     memcpy(y, buffer, sizeof(buffer));
1238     // Register 2 -> z.
1239     reg_buffer[0] = get_register(a2);
1240     memcpy(z, buffer, sizeof(*z));
1241   }
1242 }
1243 
1244 
1245 // The return value is either in v0/v1 or f0.
SetFpResult(const double & result)1246 void Simulator::SetFpResult(const double& result) {
1247   if (!IsMipsSoftFloatABI) {
1248     set_fpu_register_double(0, result);
1249   } else {
1250     char buffer[2 * sizeof(registers_[0])];
1251     int32_t* reg_buffer = reinterpret_cast<int32_t*>(buffer);
1252     memcpy(buffer, &result, sizeof(buffer));
1253     // Copy result to v0 and v1.
1254     set_register(v0, reg_buffer[0]);
1255     set_register(v1, reg_buffer[1]);
1256   }
1257 }
1258 
1259 
1260 // Helper functions for setting and testing the FCSR register's bits.
set_fcsr_bit(uint32_t cc,bool value)1261 void Simulator::set_fcsr_bit(uint32_t cc, bool value) {
1262   if (value) {
1263     FCSR_ |= (1 << cc);
1264   } else {
1265     FCSR_ &= ~(1 << cc);
1266   }
1267 }
1268 
1269 
test_fcsr_bit(uint32_t cc)1270 bool Simulator::test_fcsr_bit(uint32_t cc) {
1271   return FCSR_ & (1 << cc);
1272 }
1273 
1274 
1275 // Sets the rounding error codes in FCSR based on the result of the rounding.
1276 // Returns true if the operation was invalid.
set_fcsr_round_error(double original,double rounded)1277 bool Simulator::set_fcsr_round_error(double original, double rounded) {
1278   bool ret = false;
1279   double max_int32 = std::numeric_limits<int32_t>::max();
1280   double min_int32 = std::numeric_limits<int32_t>::min();
1281 
1282   if (!std::isfinite(original) || !std::isfinite(rounded)) {
1283     set_fcsr_bit(kFCSRInvalidOpFlagBit, true);
1284     ret = true;
1285   }
1286 
1287   if (original != rounded) {
1288     set_fcsr_bit(kFCSRInexactFlagBit, true);
1289   }
1290 
1291   if (rounded < DBL_MIN && rounded > -DBL_MIN && rounded != 0) {
1292     set_fcsr_bit(kFCSRUnderflowFlagBit, true);
1293     ret = true;
1294   }
1295 
1296   if (rounded > max_int32 || rounded < min_int32) {
1297     set_fcsr_bit(kFCSROverflowFlagBit, true);
1298     // The reference is not really clear but it seems this is required:
1299     set_fcsr_bit(kFCSRInvalidOpFlagBit, true);
1300     ret = true;
1301   }
1302 
1303   return ret;
1304 }
1305 
1306 
1307 // Raw access to the PC register.
set_pc(int32_t value)1308 void Simulator::set_pc(int32_t value) {
1309   pc_modified_ = true;
1310   registers_[pc] = value;
1311 }
1312 
1313 
has_bad_pc() const1314 bool Simulator::has_bad_pc() const {
1315   return ((registers_[pc] == bad_ra) || (registers_[pc] == end_sim_pc));
1316 }
1317 
1318 
1319 // Raw access to the PC register without the special adjustment when reading.
get_pc() const1320 int32_t Simulator::get_pc() const {
1321   return registers_[pc];
1322 }
1323 
1324 
1325 // The MIPS cannot do unaligned reads and writes.  On some MIPS platforms an
1326 // interrupt is caused.  On others it does a funky rotation thing.  For now we
1327 // simply disallow unaligned reads, but at some point we may want to move to
1328 // emulating the rotate behaviour.  Note that simulator runs have the runtime
1329 // system running directly on the host system and only generated code is
1330 // executed in the simulator.  Since the host is typically IA32 we will not
1331 // get the correct MIPS-like behaviour on unaligned accesses.
1332 
ReadW(int32_t addr,Instruction * instr)1333 int Simulator::ReadW(int32_t addr, Instruction* instr) {
1334   if (addr >=0 && addr < 0x400) {
1335     // This has to be a NULL-dereference, drop into debugger.
1336     PrintF("Memory read from bad address: 0x%08x, pc=0x%08x\n",
1337            addr, reinterpret_cast<intptr_t>(instr));
1338     MipsDebugger dbg(this);
1339     dbg.Debug();
1340   }
1341   if ((addr & kPointerAlignmentMask) == 0) {
1342     intptr_t* ptr = reinterpret_cast<intptr_t*>(addr);
1343     return *ptr;
1344   }
1345   PrintF("Unaligned read at 0x%08x, pc=0x%08" V8PRIxPTR "\n",
1346          addr,
1347          reinterpret_cast<intptr_t>(instr));
1348   MipsDebugger dbg(this);
1349   dbg.Debug();
1350   return 0;
1351 }
1352 
1353 
WriteW(int32_t addr,int value,Instruction * instr)1354 void Simulator::WriteW(int32_t addr, int value, Instruction* instr) {
1355   if (addr >= 0 && addr < 0x400) {
1356     // This has to be a NULL-dereference, drop into debugger.
1357     PrintF("Memory write to bad address: 0x%08x, pc=0x%08x\n",
1358            addr, reinterpret_cast<intptr_t>(instr));
1359     MipsDebugger dbg(this);
1360     dbg.Debug();
1361   }
1362   if ((addr & kPointerAlignmentMask) == 0) {
1363     intptr_t* ptr = reinterpret_cast<intptr_t*>(addr);
1364     *ptr = value;
1365     return;
1366   }
1367   PrintF("Unaligned write at 0x%08x, pc=0x%08" V8PRIxPTR "\n",
1368          addr,
1369          reinterpret_cast<intptr_t>(instr));
1370   MipsDebugger dbg(this);
1371   dbg.Debug();
1372 }
1373 
1374 
ReadD(int32_t addr,Instruction * instr)1375 double Simulator::ReadD(int32_t addr, Instruction* instr) {
1376   if ((addr & kDoubleAlignmentMask) == 0) {
1377     double* ptr = reinterpret_cast<double*>(addr);
1378     return *ptr;
1379   }
1380   PrintF("Unaligned (double) read at 0x%08x, pc=0x%08" V8PRIxPTR "\n",
1381          addr,
1382          reinterpret_cast<intptr_t>(instr));
1383   base::OS::Abort();
1384   return 0;
1385 }
1386 
1387 
WriteD(int32_t addr,double value,Instruction * instr)1388 void Simulator::WriteD(int32_t addr, double value, Instruction* instr) {
1389   if ((addr & kDoubleAlignmentMask) == 0) {
1390     double* ptr = reinterpret_cast<double*>(addr);
1391     *ptr = value;
1392     return;
1393   }
1394   PrintF("Unaligned (double) write at 0x%08x, pc=0x%08" V8PRIxPTR "\n",
1395          addr,
1396          reinterpret_cast<intptr_t>(instr));
1397   base::OS::Abort();
1398 }
1399 
1400 
ReadHU(int32_t addr,Instruction * instr)1401 uint16_t Simulator::ReadHU(int32_t addr, Instruction* instr) {
1402   if ((addr & 1) == 0) {
1403     uint16_t* ptr = reinterpret_cast<uint16_t*>(addr);
1404     return *ptr;
1405   }
1406   PrintF("Unaligned unsigned halfword read at 0x%08x, pc=0x%08" V8PRIxPTR "\n",
1407          addr,
1408          reinterpret_cast<intptr_t>(instr));
1409   base::OS::Abort();
1410   return 0;
1411 }
1412 
1413 
ReadH(int32_t addr,Instruction * instr)1414 int16_t Simulator::ReadH(int32_t addr, Instruction* instr) {
1415   if ((addr & 1) == 0) {
1416     int16_t* ptr = reinterpret_cast<int16_t*>(addr);
1417     return *ptr;
1418   }
1419   PrintF("Unaligned signed halfword read at 0x%08x, pc=0x%08" V8PRIxPTR "\n",
1420          addr,
1421          reinterpret_cast<intptr_t>(instr));
1422   base::OS::Abort();
1423   return 0;
1424 }
1425 
1426 
WriteH(int32_t addr,uint16_t value,Instruction * instr)1427 void Simulator::WriteH(int32_t addr, uint16_t value, Instruction* instr) {
1428   if ((addr & 1) == 0) {
1429     uint16_t* ptr = reinterpret_cast<uint16_t*>(addr);
1430     *ptr = value;
1431     return;
1432   }
1433   PrintF("Unaligned unsigned halfword write at 0x%08x, pc=0x%08" V8PRIxPTR "\n",
1434          addr,
1435          reinterpret_cast<intptr_t>(instr));
1436   base::OS::Abort();
1437 }
1438 
1439 
WriteH(int32_t addr,int16_t value,Instruction * instr)1440 void Simulator::WriteH(int32_t addr, int16_t value, Instruction* instr) {
1441   if ((addr & 1) == 0) {
1442     int16_t* ptr = reinterpret_cast<int16_t*>(addr);
1443     *ptr = value;
1444     return;
1445   }
1446   PrintF("Unaligned halfword write at 0x%08x, pc=0x%08" V8PRIxPTR "\n",
1447          addr,
1448          reinterpret_cast<intptr_t>(instr));
1449   base::OS::Abort();
1450 }
1451 
1452 
ReadBU(int32_t addr)1453 uint32_t Simulator::ReadBU(int32_t addr) {
1454   uint8_t* ptr = reinterpret_cast<uint8_t*>(addr);
1455   return *ptr & 0xff;
1456 }
1457 
1458 
ReadB(int32_t addr)1459 int32_t Simulator::ReadB(int32_t addr) {
1460   int8_t* ptr = reinterpret_cast<int8_t*>(addr);
1461   return *ptr;
1462 }
1463 
1464 
WriteB(int32_t addr,uint8_t value)1465 void Simulator::WriteB(int32_t addr, uint8_t value) {
1466   uint8_t* ptr = reinterpret_cast<uint8_t*>(addr);
1467   *ptr = value;
1468 }
1469 
1470 
WriteB(int32_t addr,int8_t value)1471 void Simulator::WriteB(int32_t addr, int8_t value) {
1472   int8_t* ptr = reinterpret_cast<int8_t*>(addr);
1473   *ptr = value;
1474 }
1475 
1476 
1477 // Returns the limit of the stack area to enable checking for stack overflows.
StackLimit() const1478 uintptr_t Simulator::StackLimit() const {
1479   // Leave a safety margin of 1024 bytes to prevent overrunning the stack when
1480   // pushing values.
1481   return reinterpret_cast<uintptr_t>(stack_) + 1024;
1482 }
1483 
1484 
1485 // Unsupported instructions use Format to print an error and stop execution.
Format(Instruction * instr,const char * format)1486 void Simulator::Format(Instruction* instr, const char* format) {
1487   PrintF("Simulator found unsupported instruction:\n 0x%08x: %s\n",
1488          reinterpret_cast<intptr_t>(instr), format);
1489   UNIMPLEMENTED_MIPS();
1490 }
1491 
1492 
1493 // Calls into the V8 runtime are based on this very simple interface.
1494 // Note: To be able to return two values from some calls the code in runtime.cc
1495 // uses the ObjectPair which is essentially two 32-bit values stuffed into a
1496 // 64-bit value. With the code below we assume that all runtime calls return
1497 // 64 bits of result. If they don't, the v1 result register contains a bogus
1498 // value, which is fine because it is caller-saved.
1499 typedef int64_t (*SimulatorRuntimeCall)(int32_t arg0,
1500                                         int32_t arg1,
1501                                         int32_t arg2,
1502                                         int32_t arg3,
1503                                         int32_t arg4,
1504                                         int32_t arg5);
1505 
1506 // These prototypes handle the four types of FP calls.
1507 typedef int64_t (*SimulatorRuntimeCompareCall)(double darg0, double darg1);
1508 typedef double (*SimulatorRuntimeFPFPCall)(double darg0, double darg1);
1509 typedef double (*SimulatorRuntimeFPCall)(double darg0);
1510 typedef double (*SimulatorRuntimeFPIntCall)(double darg0, int32_t arg0);
1511 
1512 // This signature supports direct call in to API function native callback
1513 // (refer to InvocationCallback in v8.h).
1514 typedef void (*SimulatorRuntimeDirectApiCall)(int32_t arg0);
1515 typedef void (*SimulatorRuntimeProfilingApiCall)(int32_t arg0, void* arg1);
1516 
1517 // This signature supports direct call to accessor getter callback.
1518 typedef void (*SimulatorRuntimeDirectGetterCall)(int32_t arg0, int32_t arg1);
1519 typedef void (*SimulatorRuntimeProfilingGetterCall)(
1520     int32_t arg0, int32_t arg1, void* arg2);
1521 
1522 // Software interrupt instructions are used by the simulator to call into the
1523 // C-based V8 runtime. They are also used for debugging with simulator.
SoftwareInterrupt(Instruction * instr)1524 void Simulator::SoftwareInterrupt(Instruction* instr) {
1525   // There are several instructions that could get us here,
1526   // the break_ instruction, or several variants of traps. All
1527   // Are "SPECIAL" class opcode, and are distinuished by function.
1528   int32_t func = instr->FunctionFieldRaw();
1529   uint32_t code = (func == BREAK) ? instr->Bits(25, 6) : -1;
1530 
1531   // We first check if we met a call_rt_redirected.
1532   if (instr->InstructionBits() == rtCallRedirInstr) {
1533     Redirection* redirection = Redirection::FromSwiInstruction(instr);
1534     int32_t arg0 = get_register(a0);
1535     int32_t arg1 = get_register(a1);
1536     int32_t arg2 = get_register(a2);
1537     int32_t arg3 = get_register(a3);
1538 
1539     int32_t* stack_pointer = reinterpret_cast<int32_t*>(get_register(sp));
1540     // Args 4 and 5 are on the stack after the reserved space for args 0..3.
1541     int32_t arg4 = stack_pointer[4];
1542     int32_t arg5 = stack_pointer[5];
1543 
1544     bool fp_call =
1545          (redirection->type() == ExternalReference::BUILTIN_FP_FP_CALL) ||
1546          (redirection->type() == ExternalReference::BUILTIN_COMPARE_CALL) ||
1547          (redirection->type() == ExternalReference::BUILTIN_FP_CALL) ||
1548          (redirection->type() == ExternalReference::BUILTIN_FP_INT_CALL);
1549 
1550     if (!IsMipsSoftFloatABI) {
1551       // With the hard floating point calling convention, double
1552       // arguments are passed in FPU registers. Fetch the arguments
1553       // from there and call the builtin using soft floating point
1554       // convention.
1555       switch (redirection->type()) {
1556       case ExternalReference::BUILTIN_FP_FP_CALL:
1557       case ExternalReference::BUILTIN_COMPARE_CALL:
1558         if (IsFp64Mode()) {
1559           arg0 = get_fpu_register_word(f12);
1560           arg1 = get_fpu_register_hi_word(f12);
1561           arg2 = get_fpu_register_word(f14);
1562           arg3 = get_fpu_register_hi_word(f14);
1563         } else {
1564           arg0 = get_fpu_register_word(f12);
1565           arg1 = get_fpu_register_word(f13);
1566           arg2 = get_fpu_register_word(f14);
1567           arg3 = get_fpu_register_word(f15);
1568         }
1569         break;
1570       case ExternalReference::BUILTIN_FP_CALL:
1571         if (IsFp64Mode()) {
1572           arg0 = get_fpu_register_word(f12);
1573           arg1 = get_fpu_register_hi_word(f12);
1574         } else {
1575           arg0 = get_fpu_register_word(f12);
1576           arg1 = get_fpu_register_word(f13);
1577         }
1578         break;
1579       case ExternalReference::BUILTIN_FP_INT_CALL:
1580         if (IsFp64Mode()) {
1581           arg0 = get_fpu_register_word(f12);
1582           arg1 = get_fpu_register_hi_word(f12);
1583         } else {
1584           arg0 = get_fpu_register_word(f12);
1585           arg1 = get_fpu_register_word(f13);
1586         }
1587         arg2 = get_register(a2);
1588         break;
1589       default:
1590         break;
1591       }
1592     }
1593 
1594     // This is dodgy but it works because the C entry stubs are never moved.
1595     // See comment in codegen-arm.cc and bug 1242173.
1596     int32_t saved_ra = get_register(ra);
1597 
1598     intptr_t external =
1599           reinterpret_cast<intptr_t>(redirection->external_function());
1600 
1601     // Based on CpuFeatures::IsSupported(FPU), Mips will use either hardware
1602     // FPU, or gcc soft-float routines. Hardware FPU is simulated in this
1603     // simulator. Soft-float has additional abstraction of ExternalReference,
1604     // to support serialization.
1605     if (fp_call) {
1606       double dval0, dval1;  // one or two double parameters
1607       int32_t ival;         // zero or one integer parameters
1608       int64_t iresult = 0;  // integer return value
1609       double dresult = 0;   // double return value
1610       GetFpArgs(&dval0, &dval1, &ival);
1611       SimulatorRuntimeCall generic_target =
1612           reinterpret_cast<SimulatorRuntimeCall>(external);
1613       if (::v8::internal::FLAG_trace_sim) {
1614         switch (redirection->type()) {
1615           case ExternalReference::BUILTIN_FP_FP_CALL:
1616           case ExternalReference::BUILTIN_COMPARE_CALL:
1617             PrintF("Call to host function at %p with args %f, %f",
1618                    FUNCTION_ADDR(generic_target), dval0, dval1);
1619             break;
1620           case ExternalReference::BUILTIN_FP_CALL:
1621             PrintF("Call to host function at %p with arg %f",
1622                 FUNCTION_ADDR(generic_target), dval0);
1623             break;
1624           case ExternalReference::BUILTIN_FP_INT_CALL:
1625             PrintF("Call to host function at %p with args %f, %d",
1626                    FUNCTION_ADDR(generic_target), dval0, ival);
1627             break;
1628           default:
1629             UNREACHABLE();
1630             break;
1631         }
1632       }
1633       switch (redirection->type()) {
1634       case ExternalReference::BUILTIN_COMPARE_CALL: {
1635         SimulatorRuntimeCompareCall target =
1636           reinterpret_cast<SimulatorRuntimeCompareCall>(external);
1637         iresult = target(dval0, dval1);
1638         set_register(v0, static_cast<int32_t>(iresult));
1639         set_register(v1, static_cast<int32_t>(iresult >> 32));
1640         break;
1641       }
1642       case ExternalReference::BUILTIN_FP_FP_CALL: {
1643         SimulatorRuntimeFPFPCall target =
1644           reinterpret_cast<SimulatorRuntimeFPFPCall>(external);
1645         dresult = target(dval0, dval1);
1646         SetFpResult(dresult);
1647         break;
1648       }
1649       case ExternalReference::BUILTIN_FP_CALL: {
1650         SimulatorRuntimeFPCall target =
1651           reinterpret_cast<SimulatorRuntimeFPCall>(external);
1652         dresult = target(dval0);
1653         SetFpResult(dresult);
1654         break;
1655       }
1656       case ExternalReference::BUILTIN_FP_INT_CALL: {
1657         SimulatorRuntimeFPIntCall target =
1658           reinterpret_cast<SimulatorRuntimeFPIntCall>(external);
1659         dresult = target(dval0, ival);
1660         SetFpResult(dresult);
1661         break;
1662       }
1663       default:
1664         UNREACHABLE();
1665         break;
1666       }
1667       if (::v8::internal::FLAG_trace_sim) {
1668         switch (redirection->type()) {
1669         case ExternalReference::BUILTIN_COMPARE_CALL:
1670           PrintF("Returned %08x\n", static_cast<int32_t>(iresult));
1671           break;
1672         case ExternalReference::BUILTIN_FP_FP_CALL:
1673         case ExternalReference::BUILTIN_FP_CALL:
1674         case ExternalReference::BUILTIN_FP_INT_CALL:
1675           PrintF("Returned %f\n", dresult);
1676           break;
1677         default:
1678           UNREACHABLE();
1679           break;
1680         }
1681       }
1682     } else if (redirection->type() == ExternalReference::DIRECT_API_CALL) {
1683       if (::v8::internal::FLAG_trace_sim) {
1684         PrintF("Call to host function at %p args %08x\n",
1685             reinterpret_cast<void*>(external), arg0);
1686       }
1687       SimulatorRuntimeDirectApiCall target =
1688           reinterpret_cast<SimulatorRuntimeDirectApiCall>(external);
1689       target(arg0);
1690     } else if (
1691         redirection->type() == ExternalReference::PROFILING_API_CALL) {
1692       if (::v8::internal::FLAG_trace_sim) {
1693         PrintF("Call to host function at %p args %08x %08x\n",
1694             reinterpret_cast<void*>(external), arg0, arg1);
1695       }
1696       SimulatorRuntimeProfilingApiCall target =
1697           reinterpret_cast<SimulatorRuntimeProfilingApiCall>(external);
1698       target(arg0, Redirection::ReverseRedirection(arg1));
1699     } else if (
1700         redirection->type() == ExternalReference::DIRECT_GETTER_CALL) {
1701       if (::v8::internal::FLAG_trace_sim) {
1702         PrintF("Call to host function at %p args %08x %08x\n",
1703             reinterpret_cast<void*>(external), arg0, arg1);
1704       }
1705       SimulatorRuntimeDirectGetterCall target =
1706           reinterpret_cast<SimulatorRuntimeDirectGetterCall>(external);
1707       target(arg0, arg1);
1708     } else if (
1709         redirection->type() == ExternalReference::PROFILING_GETTER_CALL) {
1710       if (::v8::internal::FLAG_trace_sim) {
1711         PrintF("Call to host function at %p args %08x %08x %08x\n",
1712             reinterpret_cast<void*>(external), arg0, arg1, arg2);
1713       }
1714       SimulatorRuntimeProfilingGetterCall target =
1715           reinterpret_cast<SimulatorRuntimeProfilingGetterCall>(external);
1716       target(arg0, arg1, Redirection::ReverseRedirection(arg2));
1717     } else {
1718       SimulatorRuntimeCall target =
1719                   reinterpret_cast<SimulatorRuntimeCall>(external);
1720       if (::v8::internal::FLAG_trace_sim) {
1721         PrintF(
1722             "Call to host function at %p "
1723             "args %08x, %08x, %08x, %08x, %08x, %08x\n",
1724             FUNCTION_ADDR(target),
1725             arg0,
1726             arg1,
1727             arg2,
1728             arg3,
1729             arg4,
1730             arg5);
1731       }
1732       int64_t result = target(arg0, arg1, arg2, arg3, arg4, arg5);
1733       set_register(v0, static_cast<int32_t>(result));
1734       set_register(v1, static_cast<int32_t>(result >> 32));
1735     }
1736     if (::v8::internal::FLAG_trace_sim) {
1737       PrintF("Returned %08x : %08x\n", get_register(v1), get_register(v0));
1738     }
1739     set_register(ra, saved_ra);
1740     set_pc(get_register(ra));
1741 
1742   } else if (func == BREAK && code <= kMaxStopCode) {
1743     if (IsWatchpoint(code)) {
1744       PrintWatchpoint(code);
1745     } else {
1746       IncreaseStopCounter(code);
1747       HandleStop(code, instr);
1748     }
1749   } else {
1750     // All remaining break_ codes, and all traps are handled here.
1751     MipsDebugger dbg(this);
1752     dbg.Debug();
1753   }
1754 }
1755 
1756 
1757 // Stop helper functions.
IsWatchpoint(uint32_t code)1758 bool Simulator::IsWatchpoint(uint32_t code) {
1759   return (code <= kMaxWatchpointCode);
1760 }
1761 
1762 
PrintWatchpoint(uint32_t code)1763 void Simulator::PrintWatchpoint(uint32_t code) {
1764   MipsDebugger dbg(this);
1765   ++break_count_;
1766   PrintF("\n---- break %d marker: %3d  (instr count: %8d) ----------"
1767          "----------------------------------",
1768          code, break_count_, icount_);
1769   dbg.PrintAllRegs();  // Print registers and continue running.
1770 }
1771 
1772 
HandleStop(uint32_t code,Instruction * instr)1773 void Simulator::HandleStop(uint32_t code, Instruction* instr) {
1774   // Stop if it is enabled, otherwise go on jumping over the stop
1775   // and the message address.
1776   if (IsEnabledStop(code)) {
1777     MipsDebugger dbg(this);
1778     dbg.Stop(instr);
1779   } else {
1780     set_pc(get_pc() + 2 * Instruction::kInstrSize);
1781   }
1782 }
1783 
1784 
IsStopInstruction(Instruction * instr)1785 bool Simulator::IsStopInstruction(Instruction* instr) {
1786   int32_t func = instr->FunctionFieldRaw();
1787   uint32_t code = static_cast<uint32_t>(instr->Bits(25, 6));
1788   return (func == BREAK) && code > kMaxWatchpointCode && code <= kMaxStopCode;
1789 }
1790 
1791 
IsEnabledStop(uint32_t code)1792 bool Simulator::IsEnabledStop(uint32_t code) {
1793   DCHECK(code <= kMaxStopCode);
1794   DCHECK(code > kMaxWatchpointCode);
1795   return !(watched_stops_[code].count & kStopDisabledBit);
1796 }
1797 
1798 
EnableStop(uint32_t code)1799 void Simulator::EnableStop(uint32_t code) {
1800   if (!IsEnabledStop(code)) {
1801     watched_stops_[code].count &= ~kStopDisabledBit;
1802   }
1803 }
1804 
1805 
DisableStop(uint32_t code)1806 void Simulator::DisableStop(uint32_t code) {
1807   if (IsEnabledStop(code)) {
1808     watched_stops_[code].count |= kStopDisabledBit;
1809   }
1810 }
1811 
1812 
IncreaseStopCounter(uint32_t code)1813 void Simulator::IncreaseStopCounter(uint32_t code) {
1814   DCHECK(code <= kMaxStopCode);
1815   if ((watched_stops_[code].count & ~(1 << 31)) == 0x7fffffff) {
1816     PrintF("Stop counter for code %i has overflowed.\n"
1817            "Enabling this code and reseting the counter to 0.\n", code);
1818     watched_stops_[code].count = 0;
1819     EnableStop(code);
1820   } else {
1821     watched_stops_[code].count++;
1822   }
1823 }
1824 
1825 
1826 // Print a stop status.
PrintStopInfo(uint32_t code)1827 void Simulator::PrintStopInfo(uint32_t code) {
1828   if (code <= kMaxWatchpointCode) {
1829     PrintF("That is a watchpoint, not a stop.\n");
1830     return;
1831   } else if (code > kMaxStopCode) {
1832     PrintF("Code too large, only %u stops can be used\n", kMaxStopCode + 1);
1833     return;
1834   }
1835   const char* state = IsEnabledStop(code) ? "Enabled" : "Disabled";
1836   int32_t count = watched_stops_[code].count & ~kStopDisabledBit;
1837   // Don't print the state of unused breakpoints.
1838   if (count != 0) {
1839     if (watched_stops_[code].desc) {
1840       PrintF("stop %i - 0x%x: \t%s, \tcounter = %i, \t%s\n",
1841              code, code, state, count, watched_stops_[code].desc);
1842     } else {
1843       PrintF("stop %i - 0x%x: \t%s, \tcounter = %i\n",
1844              code, code, state, count);
1845     }
1846   }
1847 }
1848 
1849 
SignalExceptions()1850 void Simulator::SignalExceptions() {
1851   for (int i = 1; i < kNumExceptions; i++) {
1852     if (exceptions[i] != 0) {
1853       V8_Fatal(__FILE__, __LINE__, "Error: Exception %i raised.", i);
1854     }
1855   }
1856 }
1857 
1858 
1859 // Handle execution based on instruction types.
1860 
ConfigureTypeRegister(Instruction * instr,int32_t * alu_out,int64_t * i64hilo,uint64_t * u64hilo,int32_t * next_pc,int32_t * return_addr_reg,bool * do_interrupt)1861 void Simulator::ConfigureTypeRegister(Instruction* instr,
1862                                       int32_t* alu_out,
1863                                       int64_t* i64hilo,
1864                                       uint64_t* u64hilo,
1865                                       int32_t* next_pc,
1866                                       int32_t* return_addr_reg,
1867                                       bool* do_interrupt) {
1868   // Every local variable declared here needs to be const.
1869   // This is to make sure that changed values are sent back to
1870   // DecodeTypeRegister correctly.
1871 
1872   // Instruction fields.
1873   const Opcode   op     = instr->OpcodeFieldRaw();
1874   const int32_t  rs_reg = instr->RsValue();
1875   const int32_t  rs     = get_register(rs_reg);
1876   const uint32_t rs_u   = static_cast<uint32_t>(rs);
1877   const int32_t  rt_reg = instr->RtValue();
1878   const int32_t  rt     = get_register(rt_reg);
1879   const uint32_t rt_u   = static_cast<uint32_t>(rt);
1880   const int32_t  rd_reg = instr->RdValue();
1881   const uint32_t sa     = instr->SaValue();
1882 
1883   const int32_t  fs_reg = instr->FsValue();
1884 
1885 
1886   // ---------- Configuration.
1887   switch (op) {
1888     case COP1:    // Coprocessor instructions.
1889       switch (instr->RsFieldRaw()) {
1890         case CFC1:
1891           // At the moment only FCSR is supported.
1892           DCHECK(fs_reg == kFCSRRegister);
1893           *alu_out = FCSR_;
1894           break;
1895         case MFC1:
1896           *alu_out = get_fpu_register_word(fs_reg);
1897           break;
1898         case MFHC1:
1899           *alu_out = get_fpu_register_hi_word(fs_reg);
1900           break;
1901         case CTC1:
1902         case MTC1:
1903         case MTHC1:
1904         case S:
1905         case D:
1906         case W:
1907         case L:
1908         case PS:
1909           // Do everything in the execution step.
1910           break;
1911         default:
1912         // BC1 BC1EQZ BC1NEZ handled in DecodeTypeImmed, should never come here.
1913           UNREACHABLE();
1914       }
1915       break;
1916     case COP1X:
1917       break;
1918     case SPECIAL:
1919       switch (instr->FunctionFieldRaw()) {
1920         case JR:
1921         case JALR:
1922           *next_pc = get_register(instr->RsValue());
1923           *return_addr_reg = instr->RdValue();
1924           break;
1925         case SLL:
1926           *alu_out = rt << sa;
1927           break;
1928         case SRL:
1929           if (rs_reg == 0) {
1930             // Regular logical right shift of a word by a fixed number of
1931             // bits instruction. RS field is always equal to 0.
1932             *alu_out = rt_u >> sa;
1933           } else {
1934             // Logical right-rotate of a word by a fixed number of bits. This
1935             // is special case of SRL instruction, added in MIPS32 Release 2.
1936             // RS field is equal to 00001.
1937             *alu_out = (rt_u >> sa) | (rt_u << (32 - sa));
1938           }
1939           break;
1940         case SRA:
1941           *alu_out = rt >> sa;
1942           break;
1943         case SLLV:
1944           *alu_out = rt << rs;
1945           break;
1946         case SRLV:
1947           if (sa == 0) {
1948             // Regular logical right-shift of a word by a variable number of
1949             // bits instruction. SA field is always equal to 0.
1950             *alu_out = rt_u >> rs;
1951           } else {
1952             // Logical right-rotate of a word by a variable number of bits.
1953             // This is special case od SRLV instruction, added in MIPS32
1954             // Release 2. SA field is equal to 00001.
1955             *alu_out = (rt_u >> rs_u) | (rt_u << (32 - rs_u));
1956           }
1957           break;
1958         case SRAV:
1959           *alu_out = rt >> rs;
1960           break;
1961         case MFHI:  // MFHI == CLZ on R6.
1962           if (!IsMipsArchVariant(kMips32r6)) {
1963             DCHECK(instr->SaValue() == 0);
1964             *alu_out = get_register(HI);
1965           } else {
1966             // MIPS spec: If no bits were set in GPR rs, the result written to
1967             // GPR rd is 32.
1968             DCHECK(instr->SaValue() == 1);
1969             *alu_out = base::bits::CountLeadingZeros32(rs_u);
1970           }
1971           break;
1972         case MFLO:
1973           *alu_out = get_register(LO);
1974           break;
1975         case MULT:  // MULT == MUL_MUH.
1976           if (!IsMipsArchVariant(kMips32r6)) {
1977             *i64hilo = static_cast<int64_t>(rs) * static_cast<int64_t>(rt);
1978           } else {
1979             switch (instr->SaValue()) {
1980               case MUL_OP:
1981               case MUH_OP:
1982                 *i64hilo = static_cast<int64_t>(rs) * static_cast<int64_t>(rt);
1983                 break;
1984               default:
1985                 UNIMPLEMENTED_MIPS();
1986                 break;
1987             }
1988           }
1989           break;
1990         case MULTU:  // MULTU == MUL_MUH_U.
1991           if (!IsMipsArchVariant(kMips32r6)) {
1992             *u64hilo = static_cast<uint64_t>(rs_u) *
1993                 static_cast<uint64_t>(rt_u);
1994           } else {
1995             switch (instr->SaValue()) {
1996               case MUL_OP:
1997               case MUH_OP:
1998                 *u64hilo = static_cast<uint64_t>(rs_u) *
1999                     static_cast<uint64_t>(rt_u);
2000                 break;
2001               default:
2002                 UNIMPLEMENTED_MIPS();
2003                 break;
2004             }
2005           }
2006           break;
2007         case ADD:
2008           if (HaveSameSign(rs, rt)) {
2009             if (rs > 0) {
2010               exceptions[kIntegerOverflow] = rs > (Registers::kMaxValue - rt);
2011             } else if (rs < 0) {
2012               exceptions[kIntegerUnderflow] = rs < (Registers::kMinValue - rt);
2013             }
2014           }
2015           *alu_out = rs + rt;
2016           break;
2017         case ADDU:
2018           *alu_out = rs + rt;
2019           break;
2020         case SUB:
2021           if (!HaveSameSign(rs, rt)) {
2022             if (rs > 0) {
2023               exceptions[kIntegerOverflow] = rs > (Registers::kMaxValue + rt);
2024             } else if (rs < 0) {
2025               exceptions[kIntegerUnderflow] = rs < (Registers::kMinValue + rt);
2026             }
2027           }
2028           *alu_out = rs - rt;
2029           break;
2030         case SUBU:
2031           *alu_out = rs - rt;
2032           break;
2033         case AND:
2034           *alu_out = rs & rt;
2035           break;
2036         case OR:
2037           *alu_out = rs | rt;
2038           break;
2039         case XOR:
2040           *alu_out = rs ^ rt;
2041           break;
2042         case NOR:
2043           *alu_out = ~(rs | rt);
2044           break;
2045         case SLT:
2046           *alu_out = rs < rt ? 1 : 0;
2047           break;
2048         case SLTU:
2049           *alu_out = rs_u < rt_u ? 1 : 0;
2050           break;
2051         // Break and trap instructions.
2052         case BREAK:
2053           *do_interrupt = true;
2054           break;
2055         case TGE:
2056           *do_interrupt = rs >= rt;
2057           break;
2058         case TGEU:
2059           *do_interrupt = rs_u >= rt_u;
2060           break;
2061         case TLT:
2062           *do_interrupt = rs < rt;
2063           break;
2064         case TLTU:
2065           *do_interrupt = rs_u < rt_u;
2066           break;
2067         case TEQ:
2068           *do_interrupt = rs == rt;
2069           break;
2070         case TNE:
2071           *do_interrupt = rs != rt;
2072           break;
2073         case MOVN:
2074         case MOVZ:
2075         case MOVCI:
2076           // No action taken on decode.
2077           break;
2078         case DIV:
2079         case DIVU:
2080           // div and divu never raise exceptions.
2081           break;
2082         default:
2083           UNREACHABLE();
2084       }
2085       break;
2086     case SPECIAL2:
2087       switch (instr->FunctionFieldRaw()) {
2088         case MUL:
2089           *alu_out = rs_u * rt_u;  // Only the lower 32 bits are kept.
2090           break;
2091         case CLZ:
2092           // MIPS32 spec: If no bits were set in GPR rs, the result written to
2093           // GPR rd is 32.
2094           *alu_out = base::bits::CountLeadingZeros32(rs_u);
2095           break;
2096         default:
2097           UNREACHABLE();
2098       }
2099       break;
2100     case SPECIAL3:
2101       switch (instr->FunctionFieldRaw()) {
2102         case INS: {   // Mips32r2 instruction.
2103           // Interpret rd field as 5-bit msb of insert.
2104           uint16_t msb = rd_reg;
2105           // Interpret sa field as 5-bit lsb of insert.
2106           uint16_t lsb = sa;
2107           uint16_t size = msb - lsb + 1;
2108           uint32_t mask = (1 << size) - 1;
2109           *alu_out = (rt_u & ~(mask << lsb)) | ((rs_u & mask) << lsb);
2110           break;
2111         }
2112         case EXT: {   // Mips32r2 instruction.
2113           // Interpret rd field as 5-bit msb of extract.
2114           uint16_t msb = rd_reg;
2115           // Interpret sa field as 5-bit lsb of extract.
2116           uint16_t lsb = sa;
2117           uint16_t size = msb + 1;
2118           uint32_t mask = (1 << size) - 1;
2119           *alu_out = (rs_u & (mask << lsb)) >> lsb;
2120           break;
2121         }
2122         default:
2123           UNREACHABLE();
2124       }
2125       break;
2126     default:
2127       UNREACHABLE();
2128   }
2129 }
2130 
2131 
DecodeTypeRegister(Instruction * instr)2132 void Simulator::DecodeTypeRegister(Instruction* instr) {
2133   // Instruction fields.
2134   const Opcode   op     = instr->OpcodeFieldRaw();
2135   const int32_t  rs_reg = instr->RsValue();
2136   const int32_t  rs     = get_register(rs_reg);
2137   const uint32_t rs_u   = static_cast<uint32_t>(rs);
2138   const int32_t  rt_reg = instr->RtValue();
2139   const int32_t  rt     = get_register(rt_reg);
2140   const uint32_t rt_u   = static_cast<uint32_t>(rt);
2141   const int32_t  rd_reg = instr->RdValue();
2142 
2143   const int32_t  fr_reg = instr->FrValue();
2144   const int32_t  fs_reg = instr->FsValue();
2145   const int32_t  ft_reg = instr->FtValue();
2146   const int32_t  fd_reg = instr->FdValue();
2147   int64_t  i64hilo = 0;
2148   uint64_t u64hilo = 0;
2149 
2150   // ALU output.
2151   // It should not be used as is. Instructions using it should always
2152   // initialize it first.
2153   int32_t alu_out = 0x12345678;
2154 
2155   // For break and trap instructions.
2156   bool do_interrupt = false;
2157 
2158   // For jr and jalr.
2159   // Get current pc.
2160   int32_t current_pc = get_pc();
2161   // Next pc
2162   int32_t next_pc = 0;
2163   int32_t return_addr_reg = 31;
2164 
2165   // Set up the variables if needed before executing the instruction.
2166   ConfigureTypeRegister(instr,
2167                         &alu_out,
2168                         &i64hilo,
2169                         &u64hilo,
2170                         &next_pc,
2171                         &return_addr_reg,
2172                         &do_interrupt);
2173 
2174   // ---------- Raise exceptions triggered.
2175   SignalExceptions();
2176 
2177   // ---------- Execution.
2178   switch (op) {
2179     case COP1:
2180       switch (instr->RsFieldRaw()) {
2181         case CFC1:
2182           set_register(rt_reg, alu_out);
2183           break;
2184         case MFC1:
2185           set_register(rt_reg, alu_out);
2186           break;
2187         case MFHC1:
2188           set_register(rt_reg, alu_out);
2189           break;
2190         case CTC1:
2191           // At the moment only FCSR is supported.
2192           DCHECK(fs_reg == kFCSRRegister);
2193           FCSR_ = registers_[rt_reg];
2194           break;
2195         case MTC1:
2196           // Hardware writes upper 32-bits to zero on mtc1.
2197           set_fpu_register_hi_word(fs_reg, 0);
2198           set_fpu_register_word(fs_reg, registers_[rt_reg]);
2199           break;
2200         case MTHC1:
2201           set_fpu_register_hi_word(fs_reg, registers_[rt_reg]);
2202           break;
2203         case S:
2204           float f;
2205           switch (instr->FunctionFieldRaw()) {
2206             case CVT_D_S:
2207               f = get_fpu_register_float(fs_reg);
2208               set_fpu_register_double(fd_reg, static_cast<double>(f));
2209               break;
2210             default:
2211             // CVT_W_S CVT_L_S TRUNC_W_S ROUND_W_S ROUND_L_S FLOOR_W_S FLOOR_L_S
2212             // CEIL_W_S CEIL_L_S CVT_PS_S are unimplemented.
2213               UNREACHABLE();
2214           }
2215           break;
2216         case D:
2217           double ft, fs;
2218           uint32_t cc, fcsr_cc;
2219           int64_t  i64;
2220           fs = get_fpu_register_double(fs_reg);
2221           ft = get_fpu_register_double(ft_reg);
2222           cc = instr->FCccValue();
2223           fcsr_cc = get_fcsr_condition_bit(cc);
2224           switch (instr->FunctionFieldRaw()) {
2225             case ADD_D:
2226               set_fpu_register_double(fd_reg, fs + ft);
2227               break;
2228             case SUB_D:
2229               set_fpu_register_double(fd_reg, fs - ft);
2230               break;
2231             case MUL_D:
2232               set_fpu_register_double(fd_reg, fs * ft);
2233               break;
2234             case DIV_D:
2235               set_fpu_register_double(fd_reg, fs / ft);
2236               break;
2237             case ABS_D:
2238               set_fpu_register_double(fd_reg, fabs(fs));
2239               break;
2240             case MOV_D:
2241               set_fpu_register_double(fd_reg, fs);
2242               break;
2243             case NEG_D:
2244               set_fpu_register_double(fd_reg, -fs);
2245               break;
2246             case SQRT_D:
2247               set_fpu_register_double(fd_reg, sqrt(fs));
2248               break;
2249             case C_UN_D:
2250               set_fcsr_bit(fcsr_cc, std::isnan(fs) || std::isnan(ft));
2251               break;
2252             case C_EQ_D:
2253               set_fcsr_bit(fcsr_cc, (fs == ft));
2254               break;
2255             case C_UEQ_D:
2256               set_fcsr_bit(fcsr_cc,
2257                            (fs == ft) || (std::isnan(fs) || std::isnan(ft)));
2258               break;
2259             case C_OLT_D:
2260               set_fcsr_bit(fcsr_cc, (fs < ft));
2261               break;
2262             case C_ULT_D:
2263               set_fcsr_bit(fcsr_cc,
2264                            (fs < ft) || (std::isnan(fs) || std::isnan(ft)));
2265               break;
2266             case C_OLE_D:
2267               set_fcsr_bit(fcsr_cc, (fs <= ft));
2268               break;
2269             case C_ULE_D:
2270               set_fcsr_bit(fcsr_cc,
2271                            (fs <= ft) || (std::isnan(fs) || std::isnan(ft)));
2272               break;
2273             case CVT_W_D:   // Convert double to word.
2274               // Rounding modes are not yet supported.
2275               DCHECK((FCSR_ & 3) == 0);
2276               // In rounding mode 0 it should behave like ROUND.
2277             case ROUND_W_D:  // Round double to word (round half to even).
2278               {
2279                 double rounded = std::floor(fs + 0.5);
2280                 int32_t result = static_cast<int32_t>(rounded);
2281                 if ((result & 1) != 0 && result - fs == 0.5) {
2282                   // If the number is halfway between two integers,
2283                   // round to the even one.
2284                   result--;
2285                 }
2286                 set_fpu_register_word(fd_reg, result);
2287                 if (set_fcsr_round_error(fs, rounded)) {
2288                   set_fpu_register_word(fd_reg, kFPUInvalidResult);
2289                 }
2290               }
2291               break;
2292             case TRUNC_W_D:  // Truncate double to word (round towards 0).
2293               {
2294                 double rounded = trunc(fs);
2295                 int32_t result = static_cast<int32_t>(rounded);
2296                 set_fpu_register_word(fd_reg, result);
2297                 if (set_fcsr_round_error(fs, rounded)) {
2298                   set_fpu_register_word(fd_reg, kFPUInvalidResult);
2299                 }
2300               }
2301               break;
2302             case FLOOR_W_D:  // Round double to word towards negative infinity.
2303               {
2304                 double rounded = std::floor(fs);
2305                 int32_t result = static_cast<int32_t>(rounded);
2306                 set_fpu_register_word(fd_reg, result);
2307                 if (set_fcsr_round_error(fs, rounded)) {
2308                   set_fpu_register_word(fd_reg, kFPUInvalidResult);
2309                 }
2310               }
2311               break;
2312             case CEIL_W_D:  // Round double to word towards positive infinity.
2313               {
2314                 double rounded = std::ceil(fs);
2315                 int32_t result = static_cast<int32_t>(rounded);
2316                 set_fpu_register_word(fd_reg, result);
2317                 if (set_fcsr_round_error(fs, rounded)) {
2318                   set_fpu_register_word(fd_reg, kFPUInvalidResult);
2319                 }
2320               }
2321               break;
2322             case CVT_S_D:  // Convert double to float (single).
2323               set_fpu_register_float(fd_reg, static_cast<float>(fs));
2324               break;
2325             case CVT_L_D: {  // Mips32r2: Truncate double to 64-bit long-word.
2326               double rounded = trunc(fs);
2327               i64 = static_cast<int64_t>(rounded);
2328               if (IsFp64Mode()) {
2329                 set_fpu_register(fd_reg, i64);
2330               } else {
2331                 set_fpu_register_word(fd_reg, i64 & 0xffffffff);
2332                 set_fpu_register_word(fd_reg + 1, i64 >> 32);
2333               }
2334               break;
2335             }
2336             case TRUNC_L_D: {  // Mips32r2 instruction.
2337               double rounded = trunc(fs);
2338               i64 = static_cast<int64_t>(rounded);
2339               if (IsFp64Mode()) {
2340                 set_fpu_register(fd_reg, i64);
2341               } else {
2342                 set_fpu_register_word(fd_reg, i64 & 0xffffffff);
2343                 set_fpu_register_word(fd_reg + 1, i64 >> 32);
2344               }
2345               break;
2346             }
2347             case ROUND_L_D: {  // Mips32r2 instruction.
2348               double rounded =
2349                   fs > 0 ? std::floor(fs + 0.5) : std::ceil(fs - 0.5);
2350               i64 = static_cast<int64_t>(rounded);
2351               if (IsFp64Mode()) {
2352                 set_fpu_register(fd_reg, i64);
2353               } else {
2354                 set_fpu_register_word(fd_reg, i64 & 0xffffffff);
2355                 set_fpu_register_word(fd_reg + 1, i64 >> 32);
2356               }
2357               break;
2358             }
2359             case FLOOR_L_D:  // Mips32r2 instruction.
2360               i64 = static_cast<int64_t>(std::floor(fs));
2361               if (IsFp64Mode()) {
2362                 set_fpu_register(fd_reg, i64);
2363               } else {
2364                 set_fpu_register_word(fd_reg, i64 & 0xffffffff);
2365                 set_fpu_register_word(fd_reg + 1, i64 >> 32);
2366               }
2367               break;
2368             case CEIL_L_D:  // Mips32r2 instruction.
2369               i64 = static_cast<int64_t>(std::ceil(fs));
2370               if (IsFp64Mode()) {
2371                 set_fpu_register(fd_reg, i64);
2372               } else {
2373                 set_fpu_register_word(fd_reg, i64 & 0xffffffff);
2374                 set_fpu_register_word(fd_reg + 1, i64 >> 32);
2375               }
2376               break;
2377             case C_F_D:
2378               UNIMPLEMENTED_MIPS();
2379               break;
2380             default:
2381               UNREACHABLE();
2382           }
2383           break;
2384         case W:
2385           switch (instr->FunctionFieldRaw()) {
2386             case CVT_S_W:   // Convert word to float (single).
2387               alu_out = get_fpu_register_signed_word(fs_reg);
2388               set_fpu_register_float(fd_reg, static_cast<float>(alu_out));
2389               break;
2390             case CVT_D_W:   // Convert word to double.
2391               alu_out = get_fpu_register_signed_word(fs_reg);
2392               set_fpu_register_double(fd_reg, static_cast<double>(alu_out));
2393               break;
2394             default:  // Mips64r6 CMP.S instructions unimplemented.
2395               UNREACHABLE();
2396           }
2397           break;
2398         case L:
2399           fs = get_fpu_register_double(fs_reg);
2400           ft = get_fpu_register_double(ft_reg);
2401           switch (instr->FunctionFieldRaw()) {
2402           case CVT_D_L:  // Mips32r2 instruction.
2403             // Watch the signs here, we want 2 32-bit vals
2404             // to make a sign-64.
2405             if (IsFp64Mode()) {
2406               i64 = get_fpu_register(fs_reg);
2407             } else {
2408               i64 = static_cast<uint32_t>(get_fpu_register_word(fs_reg));
2409               i64 |= static_cast<int64_t>(
2410                   get_fpu_register_word(fs_reg + 1)) << 32;
2411             }
2412             set_fpu_register_double(fd_reg, static_cast<double>(i64));
2413             break;
2414             case CVT_S_L:
2415               UNIMPLEMENTED_MIPS();
2416               break;
2417             case CMP_AF:  // Mips64r6 CMP.D instructions.
2418               UNIMPLEMENTED_MIPS();
2419               break;
2420             case CMP_UN:
2421               if (std::isnan(fs) || std::isnan(ft)) {
2422                 set_fpu_register(fd_reg, -1);
2423               } else {
2424                 set_fpu_register(fd_reg, 0);
2425               }
2426               break;
2427             case CMP_EQ:
2428               if (fs == ft) {
2429                 set_fpu_register(fd_reg, -1);
2430               } else {
2431                 set_fpu_register(fd_reg, 0);
2432               }
2433               break;
2434             case CMP_UEQ:
2435               if ((fs == ft) || (std::isnan(fs) || std::isnan(ft))) {
2436                 set_fpu_register(fd_reg, -1);
2437               } else {
2438                 set_fpu_register(fd_reg, 0);
2439               }
2440               break;
2441             case CMP_LT:
2442               if (fs < ft) {
2443                 set_fpu_register(fd_reg, -1);
2444               } else {
2445                 set_fpu_register(fd_reg, 0);
2446               }
2447               break;
2448             case CMP_ULT:
2449               if ((fs < ft) || (std::isnan(fs) || std::isnan(ft))) {
2450                 set_fpu_register(fd_reg, -1);
2451               } else {
2452                 set_fpu_register(fd_reg, 0);
2453               }
2454               break;
2455             case CMP_LE:
2456               if (fs <= ft) {
2457                 set_fpu_register(fd_reg, -1);
2458               } else {
2459                 set_fpu_register(fd_reg, 0);
2460               }
2461               break;
2462             case CMP_ULE:
2463               if ((fs <= ft) || (std::isnan(fs) || std::isnan(ft))) {
2464                 set_fpu_register(fd_reg, -1);
2465               } else {
2466                 set_fpu_register(fd_reg, 0);
2467               }
2468               break;
2469             default:  // CMP_OR CMP_UNE CMP_NE UNIMPLEMENTED.
2470               UNREACHABLE();
2471           }
2472           break;
2473         default:
2474           UNREACHABLE();
2475       }
2476       break;
2477     case COP1X:
2478       switch (instr->FunctionFieldRaw()) {
2479         case MADD_D:
2480           double fr, ft, fs;
2481           fr = get_fpu_register_double(fr_reg);
2482           fs = get_fpu_register_double(fs_reg);
2483           ft = get_fpu_register_double(ft_reg);
2484           set_fpu_register_double(fd_reg, fs * ft + fr);
2485           break;
2486         default:
2487           UNREACHABLE();
2488       }
2489       break;
2490     case SPECIAL:
2491       switch (instr->FunctionFieldRaw()) {
2492         case JR: {
2493           Instruction* branch_delay_instr = reinterpret_cast<Instruction*>(
2494               current_pc+Instruction::kInstrSize);
2495           BranchDelayInstructionDecode(branch_delay_instr);
2496           set_pc(next_pc);
2497           pc_modified_ = true;
2498           break;
2499         }
2500         case JALR: {
2501           Instruction* branch_delay_instr = reinterpret_cast<Instruction*>(
2502               current_pc+Instruction::kInstrSize);
2503           BranchDelayInstructionDecode(branch_delay_instr);
2504           set_register(return_addr_reg,
2505                        current_pc + 2 * Instruction::kInstrSize);
2506           set_pc(next_pc);
2507           pc_modified_ = true;
2508           break;
2509         }
2510         // Instructions using HI and LO registers.
2511         case MULT:
2512           if (!IsMipsArchVariant(kMips32r6)) {
2513             set_register(LO, static_cast<int32_t>(i64hilo & 0xffffffff));
2514             set_register(HI, static_cast<int32_t>(i64hilo >> 32));
2515           } else {
2516             switch (instr->SaValue()) {
2517               case MUL_OP:
2518                 set_register(rd_reg,
2519                     static_cast<int32_t>(i64hilo & 0xffffffff));
2520                 break;
2521               case MUH_OP:
2522                 set_register(rd_reg, static_cast<int32_t>(i64hilo >> 32));
2523                 break;
2524               default:
2525                 UNIMPLEMENTED_MIPS();
2526                 break;
2527             }
2528           }
2529           break;
2530         case MULTU:
2531           if (!IsMipsArchVariant(kMips32r6)) {
2532             set_register(LO, static_cast<int32_t>(u64hilo & 0xffffffff));
2533             set_register(HI, static_cast<int32_t>(u64hilo >> 32));
2534           } else {
2535             switch (instr->SaValue()) {
2536               case MUL_OP:
2537                 set_register(rd_reg,
2538                     static_cast<int32_t>(u64hilo & 0xffffffff));
2539                 break;
2540               case MUH_OP:
2541                 set_register(rd_reg, static_cast<int32_t>(u64hilo >> 32));
2542                 break;
2543               default:
2544                 UNIMPLEMENTED_MIPS();
2545                 break;
2546             }
2547           }
2548           break;
2549         case DIV:
2550           if (IsMipsArchVariant(kMips32r6)) {
2551             switch (instr->SaValue()) {
2552               case DIV_OP:
2553                 if (rs == INT_MIN && rt == -1) {
2554                   set_register(rd_reg, INT_MIN);
2555                 } else if (rt != 0) {
2556                   set_register(rd_reg, rs / rt);
2557                 }
2558                 break;
2559               case MOD_OP:
2560                 if (rs == INT_MIN && rt == -1) {
2561                   set_register(rd_reg, 0);
2562                 } else if (rt != 0) {
2563                   set_register(rd_reg, rs % rt);
2564                 }
2565                 break;
2566               default:
2567                 UNIMPLEMENTED_MIPS();
2568                 break;
2569             }
2570           } else {
2571             // Divide by zero and overflow was not checked in the
2572             // configuration step - div and divu do not raise exceptions. On
2573             // division by 0 the result will be UNPREDICTABLE. On overflow
2574             // (INT_MIN/-1), return INT_MIN which is what the hardware does.
2575             if (rs == INT_MIN && rt == -1) {
2576               set_register(LO, INT_MIN);
2577               set_register(HI, 0);
2578             } else if (rt != 0) {
2579               set_register(LO, rs / rt);
2580               set_register(HI, rs % rt);
2581             }
2582           }
2583           break;
2584         case DIVU:
2585           if (IsMipsArchVariant(kMips32r6)) {
2586             switch (instr->SaValue()) {
2587               case DIV_OP:
2588                 if (rt_u != 0) {
2589                   set_register(rd_reg, rs_u / rt_u);
2590                 }
2591                 break;
2592               case MOD_OP:
2593                 if (rt_u != 0) {
2594                   set_register(rd_reg, rs_u % rt_u);
2595                 }
2596                 break;
2597               default:
2598                 UNIMPLEMENTED_MIPS();
2599                 break;
2600               }
2601           } else {
2602             if (rt_u != 0) {
2603               set_register(LO, rs_u / rt_u);
2604               set_register(HI, rs_u % rt_u);
2605             }
2606           }
2607           break;
2608         // Break and trap instructions.
2609         case BREAK:
2610         case TGE:
2611         case TGEU:
2612         case TLT:
2613         case TLTU:
2614         case TEQ:
2615         case TNE:
2616           if (do_interrupt) {
2617             SoftwareInterrupt(instr);
2618           }
2619           break;
2620         // Conditional moves.
2621         case MOVN:
2622           if (rt) set_register(rd_reg, rs);
2623           break;
2624         case MOVCI: {
2625           uint32_t cc = instr->FBccValue();
2626           uint32_t fcsr_cc = get_fcsr_condition_bit(cc);
2627           if (instr->Bit(16)) {  // Read Tf bit.
2628             if (test_fcsr_bit(fcsr_cc)) set_register(rd_reg, rs);
2629           } else {
2630             if (!test_fcsr_bit(fcsr_cc)) set_register(rd_reg, rs);
2631           }
2632           break;
2633         }
2634         case MOVZ:
2635           if (!rt) set_register(rd_reg, rs);
2636           break;
2637         default:  // For other special opcodes we do the default operation.
2638           set_register(rd_reg, alu_out);
2639       }
2640       break;
2641     case SPECIAL2:
2642       switch (instr->FunctionFieldRaw()) {
2643         case MUL:
2644           set_register(rd_reg, alu_out);
2645           // HI and LO are UNPREDICTABLE after the operation.
2646           set_register(LO, Unpredictable);
2647           set_register(HI, Unpredictable);
2648           break;
2649         default:  // For other special2 opcodes we do the default operation.
2650           set_register(rd_reg, alu_out);
2651       }
2652       break;
2653     case SPECIAL3:
2654       switch (instr->FunctionFieldRaw()) {
2655         case INS:
2656           // Ins instr leaves result in Rt, rather than Rd.
2657           set_register(rt_reg, alu_out);
2658           break;
2659         case EXT:
2660           // Ext instr leaves result in Rt, rather than Rd.
2661           set_register(rt_reg, alu_out);
2662           break;
2663         default:
2664           UNREACHABLE();
2665       }
2666       break;
2667     // Unimplemented opcodes raised an error in the configuration step before,
2668     // so we can use the default here to set the destination register in common
2669     // cases.
2670     default:
2671       set_register(rd_reg, alu_out);
2672   }
2673 }
2674 
2675 
2676 // Type 2: instructions using a 16 bytes immediate. (e.g. addi, beq).
DecodeTypeImmediate(Instruction * instr)2677 void Simulator::DecodeTypeImmediate(Instruction* instr) {
2678   // Instruction fields.
2679   Opcode   op     = instr->OpcodeFieldRaw();
2680   int32_t  rs     = get_register(instr->RsValue());
2681   uint32_t rs_u   = static_cast<uint32_t>(rs);
2682   int32_t  rt_reg = instr->RtValue();  // Destination register.
2683   int32_t  rt     = get_register(rt_reg);
2684   int16_t  imm16  = instr->Imm16Value();
2685 
2686   int32_t  ft_reg = instr->FtValue();  // Destination register.
2687   int64_t  ft;
2688 
2689   // Zero extended immediate.
2690   uint32_t  oe_imm16 = 0xffff & imm16;
2691   // Sign extended immediate.
2692   int32_t   se_imm16 = imm16;
2693 
2694   // Get current pc.
2695   int32_t current_pc = get_pc();
2696   // Next pc.
2697   int32_t next_pc = bad_ra;
2698 
2699   // Used for conditional branch instructions.
2700   bool do_branch = false;
2701   bool execute_branch_delay_instruction = false;
2702 
2703   // Used for arithmetic instructions.
2704   int32_t alu_out = 0;
2705   // Floating point.
2706   double fp_out = 0.0;
2707   uint32_t cc, cc_value, fcsr_cc;
2708 
2709   // Used for memory instructions.
2710   int32_t addr = 0x0;
2711   // Value to be written in memory.
2712   uint32_t mem_value = 0x0;
2713 
2714   // ---------- Configuration (and execution for REGIMM).
2715   switch (op) {
2716     // ------------- COP1. Coprocessor instructions.
2717     case COP1:
2718       switch (instr->RsFieldRaw()) {
2719         case BC1:   // Branch on coprocessor condition.
2720           cc = instr->FBccValue();
2721           fcsr_cc = get_fcsr_condition_bit(cc);
2722           cc_value = test_fcsr_bit(fcsr_cc);
2723           do_branch = (instr->FBtrueValue()) ? cc_value : !cc_value;
2724           execute_branch_delay_instruction = true;
2725           // Set next_pc.
2726           if (do_branch) {
2727             next_pc = current_pc + (imm16 << 2) + Instruction::kInstrSize;
2728           } else {
2729             next_pc = current_pc + kBranchReturnOffset;
2730           }
2731           break;
2732         case BC1EQZ:
2733           ft = get_fpu_register(ft_reg);
2734           do_branch = (ft & 0x1) ? false : true;
2735           execute_branch_delay_instruction = true;
2736           // Set next_pc.
2737           if (do_branch) {
2738             next_pc = current_pc + (imm16 << 2) + Instruction::kInstrSize;
2739           } else {
2740             next_pc = current_pc + kBranchReturnOffset;
2741           }
2742           break;
2743         case BC1NEZ:
2744           ft = get_fpu_register(ft_reg);
2745           do_branch = (ft & 0x1) ? true : false;
2746           execute_branch_delay_instruction = true;
2747           // Set next_pc.
2748           if (do_branch) {
2749             next_pc = current_pc + (imm16 << 2) + Instruction::kInstrSize;
2750           } else {
2751             next_pc = current_pc + kBranchReturnOffset;
2752           }
2753           break;
2754         default:
2755           UNREACHABLE();
2756       }
2757       break;
2758     // ------------- REGIMM class.
2759     case REGIMM:
2760       switch (instr->RtFieldRaw()) {
2761         case BLTZ:
2762           do_branch = (rs  < 0);
2763           break;
2764         case BLTZAL:
2765           do_branch = rs  < 0;
2766           break;
2767         case BGEZ:
2768           do_branch = rs >= 0;
2769           break;
2770         case BGEZAL:
2771           do_branch = rs >= 0;
2772           break;
2773         default:
2774           UNREACHABLE();
2775       }
2776       switch (instr->RtFieldRaw()) {
2777         case BLTZ:
2778         case BLTZAL:
2779         case BGEZ:
2780         case BGEZAL:
2781           // Branch instructions common part.
2782           execute_branch_delay_instruction = true;
2783           // Set next_pc.
2784           if (do_branch) {
2785             next_pc = current_pc + (imm16 << 2) + Instruction::kInstrSize;
2786             if (instr->IsLinkingInstruction()) {
2787               set_register(31, current_pc + kBranchReturnOffset);
2788             }
2789           } else {
2790             next_pc = current_pc + kBranchReturnOffset;
2791           }
2792         default:
2793           break;
2794         }
2795     break;  // case REGIMM.
2796     // ------------- Branch instructions.
2797     // When comparing to zero, the encoding of rt field is always 0, so we don't
2798     // need to replace rt with zero.
2799     case BEQ:
2800       do_branch = (rs == rt);
2801       break;
2802     case BNE:
2803       do_branch = rs != rt;
2804       break;
2805     case BLEZ:
2806       do_branch = rs <= 0;
2807       break;
2808     case BGTZ:
2809       do_branch = rs  > 0;
2810       break;
2811     // ------------- Arithmetic instructions.
2812     case ADDI:
2813       if (HaveSameSign(rs, se_imm16)) {
2814         if (rs > 0) {
2815           exceptions[kIntegerOverflow] = rs > (Registers::kMaxValue - se_imm16);
2816         } else if (rs < 0) {
2817           exceptions[kIntegerUnderflow] =
2818               rs < (Registers::kMinValue - se_imm16);
2819         }
2820       }
2821       alu_out = rs + se_imm16;
2822       break;
2823     case ADDIU:
2824       alu_out = rs + se_imm16;
2825       break;
2826     case SLTI:
2827       alu_out = (rs < se_imm16) ? 1 : 0;
2828       break;
2829     case SLTIU:
2830       alu_out = (rs_u < static_cast<uint32_t>(se_imm16)) ? 1 : 0;
2831       break;
2832     case ANDI:
2833         alu_out = rs & oe_imm16;
2834       break;
2835     case ORI:
2836         alu_out = rs | oe_imm16;
2837       break;
2838     case XORI:
2839         alu_out = rs ^ oe_imm16;
2840       break;
2841     case LUI:
2842         alu_out = (oe_imm16 << 16);
2843       break;
2844     // ------------- Memory instructions.
2845     case LB:
2846       addr = rs + se_imm16;
2847       alu_out = ReadB(addr);
2848       break;
2849     case LH:
2850       addr = rs + se_imm16;
2851       alu_out = ReadH(addr, instr);
2852       break;
2853     case LWL: {
2854       // al_offset is offset of the effective address within an aligned word.
2855       uint8_t al_offset = (rs + se_imm16) & kPointerAlignmentMask;
2856       uint8_t byte_shift = kPointerAlignmentMask - al_offset;
2857       uint32_t mask = (1 << byte_shift * 8) - 1;
2858       addr = rs + se_imm16 - al_offset;
2859       alu_out = ReadW(addr, instr);
2860       alu_out <<= byte_shift * 8;
2861       alu_out |= rt & mask;
2862       break;
2863     }
2864     case LW:
2865       addr = rs + se_imm16;
2866       alu_out = ReadW(addr, instr);
2867       break;
2868     case LBU:
2869       addr = rs + se_imm16;
2870       alu_out = ReadBU(addr);
2871       break;
2872     case LHU:
2873       addr = rs + se_imm16;
2874       alu_out = ReadHU(addr, instr);
2875       break;
2876     case LWR: {
2877       // al_offset is offset of the effective address within an aligned word.
2878       uint8_t al_offset = (rs + se_imm16) & kPointerAlignmentMask;
2879       uint8_t byte_shift = kPointerAlignmentMask - al_offset;
2880       uint32_t mask = al_offset ? (~0 << (byte_shift + 1) * 8) : 0;
2881       addr = rs + se_imm16 - al_offset;
2882       alu_out = ReadW(addr, instr);
2883       alu_out = static_cast<uint32_t> (alu_out) >> al_offset * 8;
2884       alu_out |= rt & mask;
2885       break;
2886     }
2887     case SB:
2888       addr = rs + se_imm16;
2889       break;
2890     case SH:
2891       addr = rs + se_imm16;
2892       break;
2893     case SWL: {
2894       uint8_t al_offset = (rs + se_imm16) & kPointerAlignmentMask;
2895       uint8_t byte_shift = kPointerAlignmentMask - al_offset;
2896       uint32_t mask = byte_shift ? (~0 << (al_offset + 1) * 8) : 0;
2897       addr = rs + se_imm16 - al_offset;
2898       mem_value = ReadW(addr, instr) & mask;
2899       mem_value |= static_cast<uint32_t>(rt) >> byte_shift * 8;
2900       break;
2901     }
2902     case SW:
2903       addr = rs + se_imm16;
2904       break;
2905     case SWR: {
2906       uint8_t al_offset = (rs + se_imm16) & kPointerAlignmentMask;
2907       uint32_t mask = (1 << al_offset * 8) - 1;
2908       addr = rs + se_imm16 - al_offset;
2909       mem_value = ReadW(addr, instr);
2910       mem_value = (rt << al_offset * 8) | (mem_value & mask);
2911       break;
2912     }
2913     case LWC1:
2914       addr = rs + se_imm16;
2915       alu_out = ReadW(addr, instr);
2916       break;
2917     case LDC1:
2918       addr = rs + se_imm16;
2919       fp_out = ReadD(addr, instr);
2920       break;
2921     case SWC1:
2922     case SDC1:
2923       addr = rs + se_imm16;
2924       break;
2925     default:
2926       UNREACHABLE();
2927   }
2928 
2929   // ---------- Raise exceptions triggered.
2930   SignalExceptions();
2931 
2932   // ---------- Execution.
2933   switch (op) {
2934     // ------------- Branch instructions.
2935     case BEQ:
2936     case BNE:
2937     case BLEZ:
2938     case BGTZ:
2939       // Branch instructions common part.
2940       execute_branch_delay_instruction = true;
2941       // Set next_pc.
2942       if (do_branch) {
2943         next_pc = current_pc + (imm16 << 2) + Instruction::kInstrSize;
2944         if (instr->IsLinkingInstruction()) {
2945           set_register(31, current_pc + 2* Instruction::kInstrSize);
2946         }
2947       } else {
2948         next_pc = current_pc + 2 * Instruction::kInstrSize;
2949       }
2950       break;
2951     // ------------- Arithmetic instructions.
2952     case ADDI:
2953     case ADDIU:
2954     case SLTI:
2955     case SLTIU:
2956     case ANDI:
2957     case ORI:
2958     case XORI:
2959     case LUI:
2960       set_register(rt_reg, alu_out);
2961       break;
2962     // ------------- Memory instructions.
2963     case LB:
2964     case LH:
2965     case LWL:
2966     case LW:
2967     case LBU:
2968     case LHU:
2969     case LWR:
2970       set_register(rt_reg, alu_out);
2971       break;
2972     case SB:
2973       WriteB(addr, static_cast<int8_t>(rt));
2974       break;
2975     case SH:
2976       WriteH(addr, static_cast<uint16_t>(rt), instr);
2977       break;
2978     case SWL:
2979       WriteW(addr, mem_value, instr);
2980       break;
2981     case SW:
2982       WriteW(addr, rt, instr);
2983       break;
2984     case SWR:
2985       WriteW(addr, mem_value, instr);
2986       break;
2987     case LWC1:
2988       set_fpu_register_hi_word(ft_reg, 0);
2989       set_fpu_register_word(ft_reg, alu_out);
2990       break;
2991     case LDC1:
2992       set_fpu_register_double(ft_reg, fp_out);
2993       break;
2994     case SWC1:
2995       addr = rs + se_imm16;
2996       WriteW(addr, get_fpu_register_word(ft_reg), instr);
2997       break;
2998     case SDC1:
2999       addr = rs + se_imm16;
3000       WriteD(addr, get_fpu_register_double(ft_reg), instr);
3001       break;
3002     default:
3003       break;
3004   }
3005 
3006 
3007   if (execute_branch_delay_instruction) {
3008     // Execute branch delay slot
3009     // We don't check for end_sim_pc. First it should not be met as the current
3010     // pc is valid. Secondly a jump should always execute its branch delay slot.
3011     Instruction* branch_delay_instr =
3012       reinterpret_cast<Instruction*>(current_pc+Instruction::kInstrSize);
3013     BranchDelayInstructionDecode(branch_delay_instr);
3014   }
3015 
3016   // If needed update pc after the branch delay execution.
3017   if (next_pc != bad_ra) {
3018     set_pc(next_pc);
3019   }
3020 }
3021 
3022 
3023 // Type 3: instructions using a 26 bytes immediate. (e.g. j, jal).
DecodeTypeJump(Instruction * instr)3024 void Simulator::DecodeTypeJump(Instruction* instr) {
3025   // Get current pc.
3026   int32_t current_pc = get_pc();
3027   // Get unchanged bits of pc.
3028   int32_t pc_high_bits = current_pc & 0xf0000000;
3029   // Next pc.
3030   int32_t next_pc = pc_high_bits | (instr->Imm26Value() << 2);
3031 
3032   // Execute branch delay slot.
3033   // We don't check for end_sim_pc. First it should not be met as the current pc
3034   // is valid. Secondly a jump should always execute its branch delay slot.
3035   Instruction* branch_delay_instr =
3036       reinterpret_cast<Instruction*>(current_pc + Instruction::kInstrSize);
3037   BranchDelayInstructionDecode(branch_delay_instr);
3038 
3039   // Update pc and ra if necessary.
3040   // Do this after the branch delay execution.
3041   if (instr->IsLinkingInstruction()) {
3042     set_register(31, current_pc + 2 * Instruction::kInstrSize);
3043   }
3044   set_pc(next_pc);
3045   pc_modified_ = true;
3046 }
3047 
3048 
3049 // Executes the current instruction.
InstructionDecode(Instruction * instr)3050 void Simulator::InstructionDecode(Instruction* instr) {
3051   if (v8::internal::FLAG_check_icache) {
3052     CheckICache(isolate_->simulator_i_cache(), instr);
3053   }
3054   pc_modified_ = false;
3055   if (::v8::internal::FLAG_trace_sim) {
3056     disasm::NameConverter converter;
3057     disasm::Disassembler dasm(converter);
3058     // Use a reasonably large buffer.
3059     v8::internal::EmbeddedVector<char, 256> buffer;
3060     dasm.InstructionDecode(buffer, reinterpret_cast<byte*>(instr));
3061     PrintF("  0x%08x  %s\n", reinterpret_cast<intptr_t>(instr),
3062         buffer.start());
3063   }
3064 
3065   switch (instr->InstructionType()) {
3066     case Instruction::kRegisterType:
3067       DecodeTypeRegister(instr);
3068       break;
3069     case Instruction::kImmediateType:
3070       DecodeTypeImmediate(instr);
3071       break;
3072     case Instruction::kJumpType:
3073       DecodeTypeJump(instr);
3074       break;
3075     default:
3076       UNSUPPORTED();
3077   }
3078   if (!pc_modified_) {
3079     set_register(pc, reinterpret_cast<int32_t>(instr) +
3080                  Instruction::kInstrSize);
3081   }
3082 }
3083 
3084 
3085 
Execute()3086 void Simulator::Execute() {
3087   // Get the PC to simulate. Cannot use the accessor here as we need the
3088   // raw PC value and not the one used as input to arithmetic instructions.
3089   int program_counter = get_pc();
3090   if (::v8::internal::FLAG_stop_sim_at == 0) {
3091     // Fast version of the dispatch loop without checking whether the simulator
3092     // should be stopping at a particular executed instruction.
3093     while (program_counter != end_sim_pc) {
3094       Instruction* instr = reinterpret_cast<Instruction*>(program_counter);
3095       icount_++;
3096       InstructionDecode(instr);
3097       program_counter = get_pc();
3098     }
3099   } else {
3100     // FLAG_stop_sim_at is at the non-default value. Stop in the debugger when
3101     // we reach the particular instuction count.
3102     while (program_counter != end_sim_pc) {
3103       Instruction* instr = reinterpret_cast<Instruction*>(program_counter);
3104       icount_++;
3105       if (icount_ == ::v8::internal::FLAG_stop_sim_at) {
3106         MipsDebugger dbg(this);
3107         dbg.Debug();
3108       } else {
3109         InstructionDecode(instr);
3110       }
3111       program_counter = get_pc();
3112     }
3113   }
3114 }
3115 
3116 
CallInternal(byte * entry)3117 void Simulator::CallInternal(byte* entry) {
3118   // Prepare to execute the code at entry.
3119   set_register(pc, reinterpret_cast<int32_t>(entry));
3120   // Put down marker for end of simulation. The simulator will stop simulation
3121   // when the PC reaches this value. By saving the "end simulation" value into
3122   // the LR the simulation stops when returning to this call point.
3123   set_register(ra, end_sim_pc);
3124 
3125   // Remember the values of callee-saved registers.
3126   // The code below assumes that r9 is not used as sb (static base) in
3127   // simulator code and therefore is regarded as a callee-saved register.
3128   int32_t s0_val = get_register(s0);
3129   int32_t s1_val = get_register(s1);
3130   int32_t s2_val = get_register(s2);
3131   int32_t s3_val = get_register(s3);
3132   int32_t s4_val = get_register(s4);
3133   int32_t s5_val = get_register(s5);
3134   int32_t s6_val = get_register(s6);
3135   int32_t s7_val = get_register(s7);
3136   int32_t gp_val = get_register(gp);
3137   int32_t sp_val = get_register(sp);
3138   int32_t fp_val = get_register(fp);
3139 
3140   // Set up the callee-saved registers with a known value. To be able to check
3141   // that they are preserved properly across JS execution.
3142   int32_t callee_saved_value = icount_;
3143   set_register(s0, callee_saved_value);
3144   set_register(s1, callee_saved_value);
3145   set_register(s2, callee_saved_value);
3146   set_register(s3, callee_saved_value);
3147   set_register(s4, callee_saved_value);
3148   set_register(s5, callee_saved_value);
3149   set_register(s6, callee_saved_value);
3150   set_register(s7, callee_saved_value);
3151   set_register(gp, callee_saved_value);
3152   set_register(fp, callee_saved_value);
3153 
3154   // Start the simulation.
3155   Execute();
3156 
3157   // Check that the callee-saved registers have been preserved.
3158   CHECK_EQ(callee_saved_value, get_register(s0));
3159   CHECK_EQ(callee_saved_value, get_register(s1));
3160   CHECK_EQ(callee_saved_value, get_register(s2));
3161   CHECK_EQ(callee_saved_value, get_register(s3));
3162   CHECK_EQ(callee_saved_value, get_register(s4));
3163   CHECK_EQ(callee_saved_value, get_register(s5));
3164   CHECK_EQ(callee_saved_value, get_register(s6));
3165   CHECK_EQ(callee_saved_value, get_register(s7));
3166   CHECK_EQ(callee_saved_value, get_register(gp));
3167   CHECK_EQ(callee_saved_value, get_register(fp));
3168 
3169   // Restore callee-saved registers with the original value.
3170   set_register(s0, s0_val);
3171   set_register(s1, s1_val);
3172   set_register(s2, s2_val);
3173   set_register(s3, s3_val);
3174   set_register(s4, s4_val);
3175   set_register(s5, s5_val);
3176   set_register(s6, s6_val);
3177   set_register(s7, s7_val);
3178   set_register(gp, gp_val);
3179   set_register(sp, sp_val);
3180   set_register(fp, fp_val);
3181 }
3182 
3183 
Call(byte * entry,int argument_count,...)3184 int32_t Simulator::Call(byte* entry, int argument_count, ...) {
3185   va_list parameters;
3186   va_start(parameters, argument_count);
3187   // Set up arguments.
3188 
3189   // First four arguments passed in registers.
3190   DCHECK(argument_count >= 4);
3191   set_register(a0, va_arg(parameters, int32_t));
3192   set_register(a1, va_arg(parameters, int32_t));
3193   set_register(a2, va_arg(parameters, int32_t));
3194   set_register(a3, va_arg(parameters, int32_t));
3195 
3196   // Remaining arguments passed on stack.
3197   int original_stack = get_register(sp);
3198   // Compute position of stack on entry to generated code.
3199   int entry_stack = (original_stack - (argument_count - 4) * sizeof(int32_t)
3200                                     - kCArgsSlotsSize);
3201   if (base::OS::ActivationFrameAlignment() != 0) {
3202     entry_stack &= -base::OS::ActivationFrameAlignment();
3203   }
3204   // Store remaining arguments on stack, from low to high memory.
3205   intptr_t* stack_argument = reinterpret_cast<intptr_t*>(entry_stack);
3206   for (int i = 4; i < argument_count; i++) {
3207     stack_argument[i - 4 + kCArgSlotCount] = va_arg(parameters, int32_t);
3208   }
3209   va_end(parameters);
3210   set_register(sp, entry_stack);
3211 
3212   CallInternal(entry);
3213 
3214   // Pop stack passed arguments.
3215   CHECK_EQ(entry_stack, get_register(sp));
3216   set_register(sp, original_stack);
3217 
3218   int32_t result = get_register(v0);
3219   return result;
3220 }
3221 
3222 
CallFP(byte * entry,double d0,double d1)3223 double Simulator::CallFP(byte* entry, double d0, double d1) {
3224   if (!IsMipsSoftFloatABI) {
3225     set_fpu_register_double(f12, d0);
3226     set_fpu_register_double(f14, d1);
3227   } else {
3228     int buffer[2];
3229     DCHECK(sizeof(buffer[0]) * 2 == sizeof(d0));
3230     memcpy(buffer, &d0, sizeof(d0));
3231     set_dw_register(a0, buffer);
3232     memcpy(buffer, &d1, sizeof(d1));
3233     set_dw_register(a2, buffer);
3234   }
3235   CallInternal(entry);
3236   if (!IsMipsSoftFloatABI) {
3237     return get_fpu_register_double(f0);
3238   } else {
3239     return get_double_from_register_pair(v0);
3240   }
3241 }
3242 
3243 
PushAddress(uintptr_t address)3244 uintptr_t Simulator::PushAddress(uintptr_t address) {
3245   int new_sp = get_register(sp) - sizeof(uintptr_t);
3246   uintptr_t* stack_slot = reinterpret_cast<uintptr_t*>(new_sp);
3247   *stack_slot = address;
3248   set_register(sp, new_sp);
3249   return new_sp;
3250 }
3251 
3252 
PopAddress()3253 uintptr_t Simulator::PopAddress() {
3254   int current_sp = get_register(sp);
3255   uintptr_t* stack_slot = reinterpret_cast<uintptr_t*>(current_sp);
3256   uintptr_t address = *stack_slot;
3257   set_register(sp, current_sp + sizeof(uintptr_t));
3258   return address;
3259 }
3260 
3261 
3262 #undef UNSUPPORTED
3263 
3264 } }  // namespace v8::internal
3265 
3266 #endif  // USE_SIMULATOR
3267 
3268 #endif  // V8_TARGET_ARCH_MIPS
3269