• 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 #if V8_TARGET_ARCH_MIPS64
11 
12 #include "src/assembler.h"
13 #include "src/base/bits.h"
14 #include "src/codegen.h"
15 #include "src/disasm.h"
16 #include "src/mips64/constants-mips64.h"
17 #include "src/mips64/simulator-mips64.h"
18 #include "src/ostreams.h"
19 #include "src/runtime/runtime-utils.h"
20 
21 // Only build the simulator if not compiling for real MIPS hardware.
22 #if defined(USE_SIMULATOR)
23 
24 namespace v8 {
25 namespace internal {
26 
27 // Util functions.
HaveSameSign(int64_t a,int64_t b)28 inline bool HaveSameSign(int64_t a, int64_t b) { return ((a ^ b) >= 0); }
29 
get_fcsr_condition_bit(uint32_t cc)30 uint32_t get_fcsr_condition_bit(uint32_t cc) {
31   if (cc == 0) {
32     return 23;
33   } else {
34     return 24 + cc;
35   }
36 }
37 
38 
MultiplyHighSigned(int64_t u,int64_t v)39 static int64_t MultiplyHighSigned(int64_t u, int64_t v) {
40   uint64_t u0, v0, w0;
41   int64_t u1, v1, w1, w2, t;
42 
43   u0 = u & 0xffffffffL;
44   u1 = u >> 32;
45   v0 = v & 0xffffffffL;
46   v1 = v >> 32;
47 
48   w0 = u0 * v0;
49   t = u1 * v0 + (w0 >> 32);
50   w1 = t & 0xffffffffL;
51   w2 = t >> 32;
52   w1 = u0 * v1 + w1;
53 
54   return u1 * v1 + w2 + (w1 >> 32);
55 }
56 
57 
58 // This macro provides a platform independent use of sscanf. The reason for
59 // SScanF not being implemented in a platform independent was through
60 // ::v8::internal::OS in the same way as SNPrintF is that the Windows C Run-Time
61 // Library does not provide vsscanf.
62 #define SScanF sscanf  // NOLINT
63 
64 // The MipsDebugger class is used by the simulator while debugging simulated
65 // code.
66 class MipsDebugger {
67  public:
MipsDebugger(Simulator * sim)68   explicit MipsDebugger(Simulator* sim) : sim_(sim) { }
69   ~MipsDebugger();
70 
71   void Stop(Instruction* instr);
72   void Debug();
73   // Print all registers with a nice formatting.
74   void PrintAllRegs();
75   void PrintAllRegsIncludingFPU();
76 
77  private:
78   // We set the breakpoint code to 0xfffff to easily recognize it.
79   static const Instr kBreakpointInstr = SPECIAL | BREAK | 0xfffff << 6;
80   static const Instr kNopInstr =  0x0;
81 
82   Simulator* sim_;
83 
84   int64_t GetRegisterValue(int regnum);
85   int64_t GetFPURegisterValue(int regnum);
86   float GetFPURegisterValueFloat(int regnum);
87   double GetFPURegisterValueDouble(int regnum);
88   bool GetValue(const char* desc, int64_t* value);
89 
90   // Set or delete a breakpoint. Returns true if successful.
91   bool SetBreakpoint(Instruction* breakpc);
92   bool DeleteBreakpoint(Instruction* breakpc);
93 
94   // Undo and redo all breakpoints. This is needed to bracket disassembly and
95   // execution to skip past breakpoints when run from the debugger.
96   void UndoBreakpoints();
97   void RedoBreakpoints();
98 };
99 
100 
~MipsDebugger()101 MipsDebugger::~MipsDebugger() {
102 }
103 
104 
105 #ifdef GENERATED_CODE_COVERAGE
106 static FILE* coverage_log = NULL;
107 
108 
InitializeCoverage()109 static void InitializeCoverage() {
110   char* file_name = getenv("V8_GENERATED_CODE_COVERAGE_LOG");
111   if (file_name != NULL) {
112     coverage_log = fopen(file_name, "aw+");
113   }
114 }
115 
116 
Stop(Instruction * instr)117 void MipsDebugger::Stop(Instruction* instr) {
118   // Get the stop code.
119   uint32_t code = instr->Bits(25, 6);
120   // Retrieve the encoded address, which comes just after this stop.
121   char** msg_address =
122     reinterpret_cast<char**>(sim_->get_pc() + Instr::kInstrSize);
123   char* msg = *msg_address;
124   DCHECK(msg != NULL);
125 
126   // Update this stop description.
127   if (!watched_stops_[code].desc) {
128     watched_stops_[code].desc = msg;
129   }
130 
131   if (strlen(msg) > 0) {
132     if (coverage_log != NULL) {
133       fprintf(coverage_log, "%s\n", str);
134       fflush(coverage_log);
135     }
136     // Overwrite the instruction and address with nops.
137     instr->SetInstructionBits(kNopInstr);
138     reinterpret_cast<Instr*>(msg_address)->SetInstructionBits(kNopInstr);
139   }
140   // TODO(yuyin): 2 -> 3?
141   sim_->set_pc(sim_->get_pc() + 3 * Instruction::kInstructionSize);
142 }
143 
144 
145 #else  // GENERATED_CODE_COVERAGE
146 
147 #define UNSUPPORTED() printf("Sim: Unsupported instruction.\n");
148 
InitializeCoverage()149 static void InitializeCoverage() {}
150 
151 
Stop(Instruction * instr)152 void MipsDebugger::Stop(Instruction* instr) {
153   // Get the stop code.
154   uint32_t code = instr->Bits(25, 6);
155   // Retrieve the encoded address, which comes just after this stop.
156   char* msg = *reinterpret_cast<char**>(sim_->get_pc() +
157       Instruction::kInstrSize);
158   // Update this stop description.
159   if (!sim_->watched_stops_[code].desc) {
160     sim_->watched_stops_[code].desc = msg;
161   }
162   PrintF("Simulator hit %s (%u)\n", msg, code);
163   // TODO(yuyin): 2 -> 3?
164   sim_->set_pc(sim_->get_pc() + 3 * Instruction::kInstrSize);
165   Debug();
166 }
167 #endif  // GENERATED_CODE_COVERAGE
168 
169 
GetRegisterValue(int regnum)170 int64_t MipsDebugger::GetRegisterValue(int regnum) {
171   if (regnum == kNumSimuRegisters) {
172     return sim_->get_pc();
173   } else {
174     return sim_->get_register(regnum);
175   }
176 }
177 
178 
GetFPURegisterValue(int regnum)179 int64_t MipsDebugger::GetFPURegisterValue(int regnum) {
180   if (regnum == kNumFPURegisters) {
181     return sim_->get_pc();
182   } else {
183     return sim_->get_fpu_register(regnum);
184   }
185 }
186 
187 
GetFPURegisterValueFloat(int regnum)188 float MipsDebugger::GetFPURegisterValueFloat(int regnum) {
189   if (regnum == kNumFPURegisters) {
190     return sim_->get_pc();
191   } else {
192     return sim_->get_fpu_register_float(regnum);
193   }
194 }
195 
196 
GetFPURegisterValueDouble(int regnum)197 double MipsDebugger::GetFPURegisterValueDouble(int regnum) {
198   if (regnum == kNumFPURegisters) {
199     return sim_->get_pc();
200   } else {
201     return sim_->get_fpu_register_double(regnum);
202   }
203 }
204 
205 
GetValue(const char * desc,int64_t * value)206 bool MipsDebugger::GetValue(const char* desc, int64_t* value) {
207   int regnum = Registers::Number(desc);
208   int fpuregnum = FPURegisters::Number(desc);
209 
210   if (regnum != kInvalidRegister) {
211     *value = GetRegisterValue(regnum);
212     return true;
213   } else if (fpuregnum != kInvalidFPURegister) {
214     *value = GetFPURegisterValue(fpuregnum);
215     return true;
216   } else if (strncmp(desc, "0x", 2) == 0) {
217     return SScanF(desc + 2, "%" SCNx64,
218                   reinterpret_cast<uint64_t*>(value)) == 1;
219   } else {
220     return SScanF(desc, "%" SCNu64, reinterpret_cast<uint64_t*>(value)) == 1;
221   }
222   return false;
223 }
224 
225 
SetBreakpoint(Instruction * breakpc)226 bool MipsDebugger::SetBreakpoint(Instruction* breakpc) {
227   // Check if a breakpoint can be set. If not return without any side-effects.
228   if (sim_->break_pc_ != NULL) {
229     return false;
230   }
231 
232   // Set the breakpoint.
233   sim_->break_pc_ = breakpc;
234   sim_->break_instr_ = breakpc->InstructionBits();
235   // Not setting the breakpoint instruction in the code itself. It will be set
236   // when the debugger shell continues.
237   return true;
238 }
239 
240 
DeleteBreakpoint(Instruction * breakpc)241 bool MipsDebugger::DeleteBreakpoint(Instruction* breakpc) {
242   if (sim_->break_pc_ != NULL) {
243     sim_->break_pc_->SetInstructionBits(sim_->break_instr_);
244   }
245 
246   sim_->break_pc_ = NULL;
247   sim_->break_instr_ = 0;
248   return true;
249 }
250 
251 
UndoBreakpoints()252 void MipsDebugger::UndoBreakpoints() {
253   if (sim_->break_pc_ != NULL) {
254     sim_->break_pc_->SetInstructionBits(sim_->break_instr_);
255   }
256 }
257 
258 
RedoBreakpoints()259 void MipsDebugger::RedoBreakpoints() {
260   if (sim_->break_pc_ != NULL) {
261     sim_->break_pc_->SetInstructionBits(kBreakpointInstr);
262   }
263 }
264 
265 
PrintAllRegs()266 void MipsDebugger::PrintAllRegs() {
267 #define REG_INFO(n) Registers::Name(n), GetRegisterValue(n), GetRegisterValue(n)
268 
269   PrintF("\n");
270   // at, v0, a0.
271   PrintF("%3s: 0x%016" PRIx64 " %14" PRId64 "\t%3s: 0x%016" PRIx64 " %14" PRId64
272          "\t%3s: 0x%016" PRIx64 " %14" PRId64 "\n",
273          REG_INFO(1), REG_INFO(2), REG_INFO(4));
274   // v1, a1.
275   PrintF("%34s\t%3s: 0x%016" PRIx64 "  %14" PRId64 " \t%3s: 0x%016" PRIx64
276          "  %14" PRId64 " \n",
277          "", REG_INFO(3), REG_INFO(5));
278   // a2.
279   PrintF("%34s\t%34s\t%3s: 0x%016" PRIx64 "  %14" PRId64 " \n", "", "",
280          REG_INFO(6));
281   // a3.
282   PrintF("%34s\t%34s\t%3s: 0x%016" PRIx64 "  %14" PRId64 " \n", "", "",
283          REG_INFO(7));
284   PrintF("\n");
285   // a4-t3, s0-s7
286   for (int i = 0; i < 8; i++) {
287     PrintF("%3s: 0x%016" PRIx64 "  %14" PRId64 " \t%3s: 0x%016" PRIx64
288            "  %14" PRId64 " \n",
289            REG_INFO(8 + i), REG_INFO(16 + i));
290   }
291   PrintF("\n");
292   // t8, k0, LO.
293   PrintF("%3s: 0x%016" PRIx64 "  %14" PRId64 " \t%3s: 0x%016" PRIx64
294          "  %14" PRId64 " \t%3s: 0x%016" PRIx64 "  %14" PRId64 " \n",
295          REG_INFO(24), REG_INFO(26), REG_INFO(32));
296   // t9, k1, HI.
297   PrintF("%3s: 0x%016" PRIx64 "  %14" PRId64 " \t%3s: 0x%016" PRIx64
298          "  %14" PRId64 " \t%3s: 0x%016" PRIx64 "  %14" PRId64 " \n",
299          REG_INFO(25), REG_INFO(27), REG_INFO(33));
300   // sp, fp, gp.
301   PrintF("%3s: 0x%016" PRIx64 "  %14" PRId64 " \t%3s: 0x%016" PRIx64
302          "  %14" PRId64 " \t%3s: 0x%016" PRIx64 "  %14" PRId64 " \n",
303          REG_INFO(29), REG_INFO(30), REG_INFO(28));
304   // pc.
305   PrintF("%3s: 0x%016" PRIx64 "  %14" PRId64 " \t%3s: 0x%016" PRIx64
306          "  %14" PRId64 " \n",
307          REG_INFO(31), REG_INFO(34));
308 
309 #undef REG_INFO
310 #undef FPU_REG_INFO
311 }
312 
313 
PrintAllRegsIncludingFPU()314 void MipsDebugger::PrintAllRegsIncludingFPU() {
315 #define FPU_REG_INFO(n) FPURegisters::Name(n), \
316         GetFPURegisterValue(n), \
317         GetFPURegisterValueDouble(n)
318 
319   PrintAllRegs();
320 
321   PrintF("\n\n");
322   // f0, f1, f2, ... f31.
323   // TODO(plind): consider printing 2 columns for space efficiency.
324   PrintF("%3s: 0x%016" PRIx64 "  %16.4e\n", FPU_REG_INFO(0));
325   PrintF("%3s: 0x%016" PRIx64 "  %16.4e\n", FPU_REG_INFO(1));
326   PrintF("%3s: 0x%016" PRIx64 "  %16.4e\n", FPU_REG_INFO(2));
327   PrintF("%3s: 0x%016" PRIx64 "  %16.4e\n", FPU_REG_INFO(3));
328   PrintF("%3s: 0x%016" PRIx64 "  %16.4e\n", FPU_REG_INFO(4));
329   PrintF("%3s: 0x%016" PRIx64 "  %16.4e\n", FPU_REG_INFO(5));
330   PrintF("%3s: 0x%016" PRIx64 "  %16.4e\n", FPU_REG_INFO(6));
331   PrintF("%3s: 0x%016" PRIx64 "  %16.4e\n", FPU_REG_INFO(7));
332   PrintF("%3s: 0x%016" PRIx64 "  %16.4e\n", FPU_REG_INFO(8));
333   PrintF("%3s: 0x%016" PRIx64 "  %16.4e\n", FPU_REG_INFO(9));
334   PrintF("%3s: 0x%016" PRIx64 "  %16.4e\n", FPU_REG_INFO(10));
335   PrintF("%3s: 0x%016" PRIx64 "  %16.4e\n", FPU_REG_INFO(11));
336   PrintF("%3s: 0x%016" PRIx64 "  %16.4e\n", FPU_REG_INFO(12));
337   PrintF("%3s: 0x%016" PRIx64 "  %16.4e\n", FPU_REG_INFO(13));
338   PrintF("%3s: 0x%016" PRIx64 "  %16.4e\n", FPU_REG_INFO(14));
339   PrintF("%3s: 0x%016" PRIx64 "  %16.4e\n", FPU_REG_INFO(15));
340   PrintF("%3s: 0x%016" PRIx64 "  %16.4e\n", FPU_REG_INFO(16));
341   PrintF("%3s: 0x%016" PRIx64 "  %16.4e\n", FPU_REG_INFO(17));
342   PrintF("%3s: 0x%016" PRIx64 "  %16.4e\n", FPU_REG_INFO(18));
343   PrintF("%3s: 0x%016" PRIx64 "  %16.4e\n", FPU_REG_INFO(19));
344   PrintF("%3s: 0x%016" PRIx64 "  %16.4e\n", FPU_REG_INFO(20));
345   PrintF("%3s: 0x%016" PRIx64 "  %16.4e\n", FPU_REG_INFO(21));
346   PrintF("%3s: 0x%016" PRIx64 "  %16.4e\n", FPU_REG_INFO(22));
347   PrintF("%3s: 0x%016" PRIx64 "  %16.4e\n", FPU_REG_INFO(23));
348   PrintF("%3s: 0x%016" PRIx64 "  %16.4e\n", FPU_REG_INFO(24));
349   PrintF("%3s: 0x%016" PRIx64 "  %16.4e\n", FPU_REG_INFO(25));
350   PrintF("%3s: 0x%016" PRIx64 "  %16.4e\n", FPU_REG_INFO(26));
351   PrintF("%3s: 0x%016" PRIx64 "  %16.4e\n", FPU_REG_INFO(27));
352   PrintF("%3s: 0x%016" PRIx64 "  %16.4e\n", FPU_REG_INFO(28));
353   PrintF("%3s: 0x%016" PRIx64 "  %16.4e\n", FPU_REG_INFO(29));
354   PrintF("%3s: 0x%016" PRIx64 "  %16.4e\n", FPU_REG_INFO(30));
355   PrintF("%3s: 0x%016" PRIx64 "  %16.4e\n", FPU_REG_INFO(31));
356 
357 #undef REG_INFO
358 #undef FPU_REG_INFO
359 }
360 
361 
Debug()362 void MipsDebugger::Debug() {
363   intptr_t last_pc = -1;
364   bool done = false;
365 
366 #define COMMAND_SIZE 63
367 #define ARG_SIZE 255
368 
369 #define STR(a) #a
370 #define XSTR(a) STR(a)
371 
372   char cmd[COMMAND_SIZE + 1];
373   char arg1[ARG_SIZE + 1];
374   char arg2[ARG_SIZE + 1];
375   char* argv[3] = { cmd, arg1, arg2 };
376 
377   // Make sure to have a proper terminating character if reaching the limit.
378   cmd[COMMAND_SIZE] = 0;
379   arg1[ARG_SIZE] = 0;
380   arg2[ARG_SIZE] = 0;
381 
382   // Undo all set breakpoints while running in the debugger shell. This will
383   // make them invisible to all commands.
384   UndoBreakpoints();
385 
386   while (!done && (sim_->get_pc() != Simulator::end_sim_pc)) {
387     if (last_pc != sim_->get_pc()) {
388       disasm::NameConverter converter;
389       disasm::Disassembler dasm(converter);
390       // Use a reasonably large buffer.
391       v8::internal::EmbeddedVector<char, 256> buffer;
392       dasm.InstructionDecode(buffer,
393                              reinterpret_cast<byte*>(sim_->get_pc()));
394       PrintF("  0x%016" PRIx64 "   %s\n", sim_->get_pc(), buffer.start());
395       last_pc = sim_->get_pc();
396     }
397     char* line = ReadLine("sim> ");
398     if (line == NULL) {
399       break;
400     } else {
401       char* last_input = sim_->last_debugger_input();
402       if (strcmp(line, "\n") == 0 && last_input != NULL) {
403         line = last_input;
404       } else {
405         // Ownership is transferred to sim_;
406         sim_->set_last_debugger_input(line);
407       }
408       // Use sscanf to parse the individual parts of the command line. At the
409       // moment no command expects more than two parameters.
410       int argc = SScanF(line,
411                         "%" XSTR(COMMAND_SIZE) "s "
412                         "%" XSTR(ARG_SIZE) "s "
413                         "%" XSTR(ARG_SIZE) "s",
414                         cmd, arg1, arg2);
415       if ((strcmp(cmd, "si") == 0) || (strcmp(cmd, "stepi") == 0)) {
416         Instruction* instr = reinterpret_cast<Instruction*>(sim_->get_pc());
417         if (!(instr->IsTrap()) ||
418             instr->InstructionBits() == rtCallRedirInstr) {
419           sim_->InstructionDecode(
420               reinterpret_cast<Instruction*>(sim_->get_pc()));
421         } else {
422           // Allow si to jump over generated breakpoints.
423           PrintF("/!\\ Jumping over generated breakpoint.\n");
424           sim_->set_pc(sim_->get_pc() + Instruction::kInstrSize);
425         }
426       } else if ((strcmp(cmd, "c") == 0) || (strcmp(cmd, "cont") == 0)) {
427         // Execute the one instruction we broke at with breakpoints disabled.
428         sim_->InstructionDecode(reinterpret_cast<Instruction*>(sim_->get_pc()));
429         // Leave the debugger shell.
430         done = true;
431       } else if ((strcmp(cmd, "p") == 0) || (strcmp(cmd, "print") == 0)) {
432         if (argc == 2) {
433           int64_t value;
434           double dvalue;
435           if (strcmp(arg1, "all") == 0) {
436             PrintAllRegs();
437           } else if (strcmp(arg1, "allf") == 0) {
438             PrintAllRegsIncludingFPU();
439           } else {
440             int regnum = Registers::Number(arg1);
441             int fpuregnum = FPURegisters::Number(arg1);
442 
443             if (regnum != kInvalidRegister) {
444               value = GetRegisterValue(regnum);
445               PrintF("%s: 0x%08" PRIx64 "  %" PRId64 "  \n", arg1, value,
446                      value);
447             } else if (fpuregnum != kInvalidFPURegister) {
448               value = GetFPURegisterValue(fpuregnum);
449               dvalue = GetFPURegisterValueDouble(fpuregnum);
450               PrintF("%3s: 0x%016" PRIx64 "  %16.4e\n",
451                      FPURegisters::Name(fpuregnum), value, dvalue);
452             } else {
453               PrintF("%s unrecognized\n", arg1);
454             }
455           }
456         } else {
457           if (argc == 3) {
458             if (strcmp(arg2, "single") == 0) {
459               int64_t value;
460               float fvalue;
461               int fpuregnum = FPURegisters::Number(arg1);
462 
463               if (fpuregnum != kInvalidFPURegister) {
464                 value = GetFPURegisterValue(fpuregnum);
465                 value &= 0xffffffffUL;
466                 fvalue = GetFPURegisterValueFloat(fpuregnum);
467                 PrintF("%s: 0x%08" PRIx64 "  %11.4e\n", arg1, value, fvalue);
468               } else {
469                 PrintF("%s unrecognized\n", arg1);
470               }
471             } else {
472               PrintF("print <fpu register> single\n");
473             }
474           } else {
475             PrintF("print <register> or print <fpu register> single\n");
476           }
477         }
478       } else if ((strcmp(cmd, "po") == 0)
479                  || (strcmp(cmd, "printobject") == 0)) {
480         if (argc == 2) {
481           int64_t value;
482           OFStream os(stdout);
483           if (GetValue(arg1, &value)) {
484             Object* obj = reinterpret_cast<Object*>(value);
485             os << arg1 << ": \n";
486 #ifdef DEBUG
487             obj->Print(os);
488             os << "\n";
489 #else
490             os << Brief(obj) << "\n";
491 #endif
492           } else {
493             os << arg1 << " unrecognized\n";
494           }
495         } else {
496           PrintF("printobject <value>\n");
497         }
498       } else if (strcmp(cmd, "stack") == 0 || strcmp(cmd, "mem") == 0) {
499         int64_t* cur = NULL;
500         int64_t* end = NULL;
501         int next_arg = 1;
502 
503         if (strcmp(cmd, "stack") == 0) {
504           cur = reinterpret_cast<int64_t*>(sim_->get_register(Simulator::sp));
505         } else {  // Command "mem".
506           int64_t value;
507           if (!GetValue(arg1, &value)) {
508             PrintF("%s unrecognized\n", arg1);
509             continue;
510           }
511           cur = reinterpret_cast<int64_t*>(value);
512           next_arg++;
513         }
514 
515         int64_t words;
516         if (argc == next_arg) {
517           words = 10;
518         } else {
519           if (!GetValue(argv[next_arg], &words)) {
520             words = 10;
521           }
522         }
523         end = cur + words;
524 
525         while (cur < end) {
526           PrintF("  0x%012" PRIxPTR " :  0x%016" PRIx64 "  %14" PRId64 " ",
527                  reinterpret_cast<intptr_t>(cur), *cur, *cur);
528           HeapObject* obj = reinterpret_cast<HeapObject*>(*cur);
529           int64_t value = *cur;
530           Heap* current_heap = sim_->isolate_->heap();
531           if (((value & 1) == 0) ||
532               current_heap->ContainsSlow(obj->address())) {
533             PrintF(" (");
534             if ((value & 1) == 0) {
535               PrintF("smi %d", static_cast<int>(value >> 32));
536             } else {
537               obj->ShortPrint();
538             }
539             PrintF(")");
540           }
541           PrintF("\n");
542           cur++;
543         }
544 
545       } else if ((strcmp(cmd, "disasm") == 0) ||
546                  (strcmp(cmd, "dpc") == 0) ||
547                  (strcmp(cmd, "di") == 0)) {
548         disasm::NameConverter converter;
549         disasm::Disassembler dasm(converter);
550         // Use a reasonably large buffer.
551         v8::internal::EmbeddedVector<char, 256> buffer;
552 
553         byte* cur = NULL;
554         byte* end = NULL;
555 
556         if (argc == 1) {
557           cur = reinterpret_cast<byte*>(sim_->get_pc());
558           end = cur + (10 * Instruction::kInstrSize);
559         } else if (argc == 2) {
560           int regnum = Registers::Number(arg1);
561           if (regnum != kInvalidRegister || strncmp(arg1, "0x", 2) == 0) {
562             // The argument is an address or a register name.
563             int64_t value;
564             if (GetValue(arg1, &value)) {
565               cur = reinterpret_cast<byte*>(value);
566               // Disassemble 10 instructions at <arg1>.
567               end = cur + (10 * Instruction::kInstrSize);
568             }
569           } else {
570             // The argument is the number of instructions.
571             int64_t value;
572             if (GetValue(arg1, &value)) {
573               cur = reinterpret_cast<byte*>(sim_->get_pc());
574               // Disassemble <arg1> instructions.
575               end = cur + (value * Instruction::kInstrSize);
576             }
577           }
578         } else {
579           int64_t value1;
580           int64_t value2;
581           if (GetValue(arg1, &value1) && GetValue(arg2, &value2)) {
582             cur = reinterpret_cast<byte*>(value1);
583             end = cur + (value2 * Instruction::kInstrSize);
584           }
585         }
586 
587         while (cur < end) {
588           dasm.InstructionDecode(buffer, cur);
589           PrintF("  0x%08" PRIxPTR "   %s\n", reinterpret_cast<intptr_t>(cur),
590                  buffer.start());
591           cur += Instruction::kInstrSize;
592         }
593       } else if (strcmp(cmd, "gdb") == 0) {
594         PrintF("relinquishing control to gdb\n");
595         v8::base::OS::DebugBreak();
596         PrintF("regaining control from gdb\n");
597       } else if (strcmp(cmd, "break") == 0) {
598         if (argc == 2) {
599           int64_t value;
600           if (GetValue(arg1, &value)) {
601             if (!SetBreakpoint(reinterpret_cast<Instruction*>(value))) {
602               PrintF("setting breakpoint failed\n");
603             }
604           } else {
605             PrintF("%s unrecognized\n", arg1);
606           }
607         } else {
608           PrintF("break <address>\n");
609         }
610       } else if (strcmp(cmd, "del") == 0) {
611         if (!DeleteBreakpoint(NULL)) {
612           PrintF("deleting breakpoint failed\n");
613         }
614       } else if (strcmp(cmd, "flags") == 0) {
615         PrintF("No flags on MIPS !\n");
616       } else if (strcmp(cmd, "stop") == 0) {
617         int64_t value;
618         intptr_t stop_pc = sim_->get_pc() -
619             2 * Instruction::kInstrSize;
620         Instruction* stop_instr = reinterpret_cast<Instruction*>(stop_pc);
621         Instruction* msg_address =
622           reinterpret_cast<Instruction*>(stop_pc +
623               Instruction::kInstrSize);
624         if ((argc == 2) && (strcmp(arg1, "unstop") == 0)) {
625           // Remove the current stop.
626           if (sim_->IsStopInstruction(stop_instr)) {
627             stop_instr->SetInstructionBits(kNopInstr);
628             msg_address->SetInstructionBits(kNopInstr);
629           } else {
630             PrintF("Not at debugger stop.\n");
631           }
632         } else if (argc == 3) {
633           // Print information about all/the specified breakpoint(s).
634           if (strcmp(arg1, "info") == 0) {
635             if (strcmp(arg2, "all") == 0) {
636               PrintF("Stop information:\n");
637               for (uint32_t i = kMaxWatchpointCode + 1;
638                    i <= kMaxStopCode;
639                    i++) {
640                 sim_->PrintStopInfo(i);
641               }
642             } else if (GetValue(arg2, &value)) {
643               sim_->PrintStopInfo(value);
644             } else {
645               PrintF("Unrecognized argument.\n");
646             }
647           } else if (strcmp(arg1, "enable") == 0) {
648             // Enable all/the specified breakpoint(s).
649             if (strcmp(arg2, "all") == 0) {
650               for (uint32_t i = kMaxWatchpointCode + 1;
651                    i <= kMaxStopCode;
652                    i++) {
653                 sim_->EnableStop(i);
654               }
655             } else if (GetValue(arg2, &value)) {
656               sim_->EnableStop(value);
657             } else {
658               PrintF("Unrecognized argument.\n");
659             }
660           } else if (strcmp(arg1, "disable") == 0) {
661             // Disable all/the specified breakpoint(s).
662             if (strcmp(arg2, "all") == 0) {
663               for (uint32_t i = kMaxWatchpointCode + 1;
664                    i <= kMaxStopCode;
665                    i++) {
666                 sim_->DisableStop(i);
667               }
668             } else if (GetValue(arg2, &value)) {
669               sim_->DisableStop(value);
670             } else {
671               PrintF("Unrecognized argument.\n");
672             }
673           }
674         } else {
675           PrintF("Wrong usage. Use help command for more information.\n");
676         }
677       } else if ((strcmp(cmd, "stat") == 0) || (strcmp(cmd, "st") == 0)) {
678         // Print registers and disassemble.
679         PrintAllRegs();
680         PrintF("\n");
681 
682         disasm::NameConverter converter;
683         disasm::Disassembler dasm(converter);
684         // Use a reasonably large buffer.
685         v8::internal::EmbeddedVector<char, 256> buffer;
686 
687         byte* cur = NULL;
688         byte* end = NULL;
689 
690         if (argc == 1) {
691           cur = reinterpret_cast<byte*>(sim_->get_pc());
692           end = cur + (10 * Instruction::kInstrSize);
693         } else if (argc == 2) {
694           int64_t value;
695           if (GetValue(arg1, &value)) {
696             cur = reinterpret_cast<byte*>(value);
697             // no length parameter passed, assume 10 instructions
698             end = cur + (10 * Instruction::kInstrSize);
699           }
700         } else {
701           int64_t value1;
702           int64_t value2;
703           if (GetValue(arg1, &value1) && GetValue(arg2, &value2)) {
704             cur = reinterpret_cast<byte*>(value1);
705             end = cur + (value2 * Instruction::kInstrSize);
706           }
707         }
708 
709         while (cur < end) {
710           dasm.InstructionDecode(buffer, cur);
711           PrintF("  0x%08" PRIxPTR "   %s\n", reinterpret_cast<intptr_t>(cur),
712                  buffer.start());
713           cur += Instruction::kInstrSize;
714         }
715       } else if ((strcmp(cmd, "h") == 0) || (strcmp(cmd, "help") == 0)) {
716         PrintF("cont\n");
717         PrintF("  continue execution (alias 'c')\n");
718         PrintF("stepi\n");
719         PrintF("  step one instruction (alias 'si')\n");
720         PrintF("print <register>\n");
721         PrintF("  print register content (alias 'p')\n");
722         PrintF("  use register name 'all' to print all registers\n");
723         PrintF("printobject <register>\n");
724         PrintF("  print an object from a register (alias 'po')\n");
725         PrintF("stack [<words>]\n");
726         PrintF("  dump stack content, default dump 10 words)\n");
727         PrintF("mem <address> [<words>]\n");
728         PrintF("  dump memory content, default dump 10 words)\n");
729         PrintF("flags\n");
730         PrintF("  print flags\n");
731         PrintF("disasm [<instructions>]\n");
732         PrintF("disasm [<address/register>]\n");
733         PrintF("disasm [[<address/register>] <instructions>]\n");
734         PrintF("  disassemble code, default is 10 instructions\n");
735         PrintF("  from pc (alias 'di')\n");
736         PrintF("gdb\n");
737         PrintF("  enter gdb\n");
738         PrintF("break <address>\n");
739         PrintF("  set a break point on the address\n");
740         PrintF("del\n");
741         PrintF("  delete the breakpoint\n");
742         PrintF("stop feature:\n");
743         PrintF("  Description:\n");
744         PrintF("    Stops are debug instructions inserted by\n");
745         PrintF("    the Assembler::stop() function.\n");
746         PrintF("    When hitting a stop, the Simulator will\n");
747         PrintF("    stop and and give control to the Debugger.\n");
748         PrintF("    All stop codes are watched:\n");
749         PrintF("    - They can be enabled / disabled: the Simulator\n");
750         PrintF("       will / won't stop when hitting them.\n");
751         PrintF("    - The Simulator keeps track of how many times they \n");
752         PrintF("      are met. (See the info command.) Going over a\n");
753         PrintF("      disabled stop still increases its counter. \n");
754         PrintF("  Commands:\n");
755         PrintF("    stop info all/<code> : print infos about number <code>\n");
756         PrintF("      or all stop(s).\n");
757         PrintF("    stop enable/disable all/<code> : enables / disables\n");
758         PrintF("      all or number <code> stop(s)\n");
759         PrintF("    stop unstop\n");
760         PrintF("      ignore the stop instruction at the current location\n");
761         PrintF("      from now on\n");
762       } else {
763         PrintF("Unknown command: %s\n", cmd);
764       }
765     }
766   }
767 
768   // Add all the breakpoints back to stop execution and enter the debugger
769   // shell when hit.
770   RedoBreakpoints();
771 
772 #undef COMMAND_SIZE
773 #undef ARG_SIZE
774 
775 #undef STR
776 #undef XSTR
777 }
778 
779 
ICacheMatch(void * one,void * two)780 static bool ICacheMatch(void* one, void* two) {
781   DCHECK((reinterpret_cast<intptr_t>(one) & CachePage::kPageMask) == 0);
782   DCHECK((reinterpret_cast<intptr_t>(two) & CachePage::kPageMask) == 0);
783   return one == two;
784 }
785 
786 
ICacheHash(void * key)787 static uint32_t ICacheHash(void* key) {
788   return static_cast<uint32_t>(reinterpret_cast<uintptr_t>(key)) >> 2;
789 }
790 
791 
AllOnOnePage(uintptr_t start,size_t size)792 static bool AllOnOnePage(uintptr_t start, size_t size) {
793   intptr_t start_page = (start & ~CachePage::kPageMask);
794   intptr_t end_page = ((start + size) & ~CachePage::kPageMask);
795   return start_page == end_page;
796 }
797 
798 
set_last_debugger_input(char * input)799 void Simulator::set_last_debugger_input(char* input) {
800   DeleteArray(last_debugger_input_);
801   last_debugger_input_ = input;
802 }
803 
FlushICache(base::HashMap * i_cache,void * start_addr,size_t size)804 void Simulator::FlushICache(base::HashMap* i_cache, void* start_addr,
805                             size_t size) {
806   int64_t start = reinterpret_cast<int64_t>(start_addr);
807   int64_t intra_line = (start & CachePage::kLineMask);
808   start -= intra_line;
809   size += intra_line;
810   size = ((size - 1) | CachePage::kLineMask) + 1;
811   int offset = (start & CachePage::kPageMask);
812   while (!AllOnOnePage(start, size - 1)) {
813     int bytes_to_flush = CachePage::kPageSize - offset;
814     FlushOnePage(i_cache, start, bytes_to_flush);
815     start += bytes_to_flush;
816     size -= bytes_to_flush;
817     DCHECK_EQ((int64_t)0, start & CachePage::kPageMask);
818     offset = 0;
819   }
820   if (size != 0) {
821     FlushOnePage(i_cache, start, size);
822   }
823 }
824 
GetCachePage(base::HashMap * i_cache,void * page)825 CachePage* Simulator::GetCachePage(base::HashMap* i_cache, void* page) {
826   base::HashMap::Entry* entry = i_cache->LookupOrInsert(page, ICacheHash(page));
827   if (entry->value == NULL) {
828     CachePage* new_page = new CachePage();
829     entry->value = new_page;
830   }
831   return reinterpret_cast<CachePage*>(entry->value);
832 }
833 
834 
835 // Flush from start up to and not including start + size.
FlushOnePage(base::HashMap * i_cache,intptr_t start,size_t size)836 void Simulator::FlushOnePage(base::HashMap* i_cache, intptr_t start,
837                              size_t size) {
838   DCHECK(size <= CachePage::kPageSize);
839   DCHECK(AllOnOnePage(start, size - 1));
840   DCHECK((start & CachePage::kLineMask) == 0);
841   DCHECK((size & CachePage::kLineMask) == 0);
842   void* page = reinterpret_cast<void*>(start & (~CachePage::kPageMask));
843   int offset = (start & CachePage::kPageMask);
844   CachePage* cache_page = GetCachePage(i_cache, page);
845   char* valid_bytemap = cache_page->ValidityByte(offset);
846   memset(valid_bytemap, CachePage::LINE_INVALID, size >> CachePage::kLineShift);
847 }
848 
CheckICache(base::HashMap * i_cache,Instruction * instr)849 void Simulator::CheckICache(base::HashMap* i_cache, Instruction* instr) {
850   int64_t address = reinterpret_cast<int64_t>(instr);
851   void* page = reinterpret_cast<void*>(address & (~CachePage::kPageMask));
852   void* line = reinterpret_cast<void*>(address & (~CachePage::kLineMask));
853   int offset = (address & CachePage::kPageMask);
854   CachePage* cache_page = GetCachePage(i_cache, page);
855   char* cache_valid_byte = cache_page->ValidityByte(offset);
856   bool cache_hit = (*cache_valid_byte == CachePage::LINE_VALID);
857   char* cached_line = cache_page->CachedData(offset & ~CachePage::kLineMask);
858   if (cache_hit) {
859     // Check that the data in memory matches the contents of the I-cache.
860     CHECK_EQ(0, memcmp(reinterpret_cast<void*>(instr),
861                        cache_page->CachedData(offset),
862                        Instruction::kInstrSize));
863   } else {
864     // Cache miss.  Load memory into the cache.
865     memcpy(cached_line, line, CachePage::kLineLength);
866     *cache_valid_byte = CachePage::LINE_VALID;
867   }
868 }
869 
870 
Initialize(Isolate * isolate)871 void Simulator::Initialize(Isolate* isolate) {
872   if (isolate->simulator_initialized()) return;
873   isolate->set_simulator_initialized(true);
874   ::v8::internal::ExternalReference::set_redirector(isolate,
875                                                     &RedirectExternalReference);
876 }
877 
878 
Simulator(Isolate * isolate)879 Simulator::Simulator(Isolate* isolate) : isolate_(isolate) {
880   i_cache_ = isolate_->simulator_i_cache();
881   if (i_cache_ == NULL) {
882     i_cache_ = new base::HashMap(&ICacheMatch);
883     isolate_->set_simulator_i_cache(i_cache_);
884   }
885   Initialize(isolate);
886   // Set up simulator support first. Some of this information is needed to
887   // setup the architecture state.
888   stack_size_ = FLAG_sim_stack_size * KB;
889   stack_ = reinterpret_cast<char*>(malloc(stack_size_));
890   pc_modified_ = false;
891   icount_ = 0;
892   break_count_ = 0;
893   break_pc_ = NULL;
894   break_instr_ = 0;
895 
896   // Set up architecture state.
897   // All registers are initialized to zero to start with.
898   for (int i = 0; i < kNumSimuRegisters; i++) {
899     registers_[i] = 0;
900   }
901   for (int i = 0; i < kNumFPURegisters; i++) {
902     FPUregisters_[i] = 0;
903   }
904 
905   if (kArchVariant == kMips64r6) {
906     FCSR_ = kFCSRNaN2008FlagMask;
907   } else {
908     FCSR_ = 0;
909   }
910 
911   // The sp is initialized to point to the bottom (high address) of the
912   // allocated stack area. To be safe in potential stack underflows we leave
913   // some buffer below.
914   registers_[sp] = reinterpret_cast<int64_t>(stack_) + stack_size_ - 64;
915   // The ra and pc are initialized to a known bad value that will cause an
916   // access violation if the simulator ever tries to execute it.
917   registers_[pc] = bad_ra;
918   registers_[ra] = bad_ra;
919   InitializeCoverage();
920 
921   last_debugger_input_ = NULL;
922 }
923 
924 
~Simulator()925 Simulator::~Simulator() { free(stack_); }
926 
927 
928 // When the generated code calls an external reference we need to catch that in
929 // the simulator.  The external reference will be a function compiled for the
930 // host architecture.  We need to call that function instead of trying to
931 // execute it with the simulator.  We do that by redirecting the external
932 // reference to a swi (software-interrupt) instruction that is handled by
933 // the simulator.  We write the original destination of the jump just at a known
934 // offset from the swi instruction so the simulator knows what to call.
935 class Redirection {
936  public:
Redirection(Isolate * isolate,void * external_function,ExternalReference::Type type)937   Redirection(Isolate* isolate, void* external_function,
938               ExternalReference::Type type)
939       : external_function_(external_function),
940         swi_instruction_(rtCallRedirInstr),
941         type_(type),
942         next_(NULL) {
943     next_ = isolate->simulator_redirection();
944     Simulator::current(isolate)->
945         FlushICache(isolate->simulator_i_cache(),
946                     reinterpret_cast<void*>(&swi_instruction_),
947                     Instruction::kInstrSize);
948     isolate->set_simulator_redirection(this);
949   }
950 
address_of_swi_instruction()951   void* address_of_swi_instruction() {
952     return reinterpret_cast<void*>(&swi_instruction_);
953   }
954 
external_function()955   void* external_function() { return external_function_; }
type()956   ExternalReference::Type type() { return type_; }
957 
Get(Isolate * isolate,void * external_function,ExternalReference::Type type)958   static Redirection* Get(Isolate* isolate, void* external_function,
959                           ExternalReference::Type type) {
960     Redirection* current = isolate->simulator_redirection();
961     for (; current != NULL; current = current->next_) {
962       if (current->external_function_ == external_function) return current;
963     }
964     return new Redirection(isolate, external_function, type);
965   }
966 
FromSwiInstruction(Instruction * swi_instruction)967   static Redirection* FromSwiInstruction(Instruction* swi_instruction) {
968     char* addr_of_swi = reinterpret_cast<char*>(swi_instruction);
969     char* addr_of_redirection =
970         addr_of_swi - offsetof(Redirection, swi_instruction_);
971     return reinterpret_cast<Redirection*>(addr_of_redirection);
972   }
973 
ReverseRedirection(int64_t reg)974   static void* ReverseRedirection(int64_t reg) {
975     Redirection* redirection = FromSwiInstruction(
976         reinterpret_cast<Instruction*>(reinterpret_cast<void*>(reg)));
977     return redirection->external_function();
978   }
979 
DeleteChain(Redirection * redirection)980   static void DeleteChain(Redirection* redirection) {
981     while (redirection != nullptr) {
982       Redirection* next = redirection->next_;
983       delete redirection;
984       redirection = next;
985     }
986   }
987 
988  private:
989   void* external_function_;
990   uint32_t swi_instruction_;
991   ExternalReference::Type type_;
992   Redirection* next_;
993 };
994 
995 
996 // static
TearDown(base::HashMap * i_cache,Redirection * first)997 void Simulator::TearDown(base::HashMap* i_cache, Redirection* first) {
998   Redirection::DeleteChain(first);
999   if (i_cache != nullptr) {
1000     for (base::HashMap::Entry* entry = i_cache->Start(); entry != nullptr;
1001          entry = i_cache->Next(entry)) {
1002       delete static_cast<CachePage*>(entry->value);
1003     }
1004     delete i_cache;
1005   }
1006 }
1007 
1008 
RedirectExternalReference(Isolate * isolate,void * external_function,ExternalReference::Type type)1009 void* Simulator::RedirectExternalReference(Isolate* isolate,
1010                                            void* external_function,
1011                                            ExternalReference::Type type) {
1012   Redirection* redirection = Redirection::Get(isolate, external_function, type);
1013   return redirection->address_of_swi_instruction();
1014 }
1015 
1016 
1017 // Get the active Simulator for the current thread.
current(Isolate * isolate)1018 Simulator* Simulator::current(Isolate* isolate) {
1019   v8::internal::Isolate::PerIsolateThreadData* isolate_data =
1020        isolate->FindOrAllocatePerThreadDataForThisThread();
1021   DCHECK(isolate_data != NULL);
1022   DCHECK(isolate_data != NULL);
1023 
1024   Simulator* sim = isolate_data->simulator();
1025   if (sim == NULL) {
1026     // TODO(146): delete the simulator object when a thread/isolate goes away.
1027     sim = new Simulator(isolate);
1028     isolate_data->set_simulator(sim);
1029   }
1030   return sim;
1031 }
1032 
1033 
1034 // Sets the register in the architecture state. It will also deal with updating
1035 // Simulator internal state for special registers such as PC.
set_register(int reg,int64_t value)1036 void Simulator::set_register(int reg, int64_t value) {
1037   DCHECK((reg >= 0) && (reg < kNumSimuRegisters));
1038   if (reg == pc) {
1039     pc_modified_ = true;
1040   }
1041 
1042   // Zero register always holds 0.
1043   registers_[reg] = (reg == 0) ? 0 : value;
1044 }
1045 
1046 
set_dw_register(int reg,const int * dbl)1047 void Simulator::set_dw_register(int reg, const int* dbl) {
1048   DCHECK((reg >= 0) && (reg < kNumSimuRegisters));
1049   registers_[reg] = dbl[1];
1050   registers_[reg] = registers_[reg] << 32;
1051   registers_[reg] += dbl[0];
1052 }
1053 
1054 
set_fpu_register(int fpureg,int64_t value)1055 void Simulator::set_fpu_register(int fpureg, int64_t value) {
1056   DCHECK((fpureg >= 0) && (fpureg < kNumFPURegisters));
1057   FPUregisters_[fpureg] = value;
1058 }
1059 
1060 
set_fpu_register_word(int fpureg,int32_t value)1061 void Simulator::set_fpu_register_word(int fpureg, int32_t value) {
1062   // Set ONLY lower 32-bits, leaving upper bits untouched.
1063   DCHECK((fpureg >= 0) && (fpureg < kNumFPURegisters));
1064   int32_t* pword;
1065   if (kArchEndian == kLittle) {
1066     pword = reinterpret_cast<int32_t*>(&FPUregisters_[fpureg]);
1067   } else {
1068     pword = reinterpret_cast<int32_t*>(&FPUregisters_[fpureg]) + 1;
1069   }
1070   *pword = value;
1071 }
1072 
1073 
set_fpu_register_hi_word(int fpureg,int32_t value)1074 void Simulator::set_fpu_register_hi_word(int fpureg, int32_t value) {
1075   // Set ONLY upper 32-bits, leaving lower bits untouched.
1076   DCHECK((fpureg >= 0) && (fpureg < kNumFPURegisters));
1077   int32_t* phiword;
1078   if (kArchEndian == kLittle) {
1079     phiword = (reinterpret_cast<int32_t*>(&FPUregisters_[fpureg])) + 1;
1080   } else {
1081     phiword = reinterpret_cast<int32_t*>(&FPUregisters_[fpureg]);
1082   }
1083   *phiword = value;
1084 }
1085 
1086 
set_fpu_register_float(int fpureg,float value)1087 void Simulator::set_fpu_register_float(int fpureg, float value) {
1088   DCHECK((fpureg >= 0) && (fpureg < kNumFPURegisters));
1089   *bit_cast<float*>(&FPUregisters_[fpureg]) = value;
1090 }
1091 
1092 
set_fpu_register_double(int fpureg,double value)1093 void Simulator::set_fpu_register_double(int fpureg, double value) {
1094   DCHECK((fpureg >= 0) && (fpureg < kNumFPURegisters));
1095   *bit_cast<double*>(&FPUregisters_[fpureg]) = value;
1096 }
1097 
1098 
1099 // Get the register from the architecture state. This function does handle
1100 // the special case of accessing the PC register.
get_register(int reg) const1101 int64_t Simulator::get_register(int reg) const {
1102   DCHECK((reg >= 0) && (reg < kNumSimuRegisters));
1103   if (reg == 0)
1104     return 0;
1105   else
1106     return registers_[reg] + ((reg == pc) ? Instruction::kPCReadOffset : 0);
1107 }
1108 
1109 
get_double_from_register_pair(int reg)1110 double Simulator::get_double_from_register_pair(int reg) {
1111   // TODO(plind): bad ABI stuff, refactor or remove.
1112   DCHECK((reg >= 0) && (reg < kNumSimuRegisters) && ((reg % 2) == 0));
1113 
1114   double dm_val = 0.0;
1115   // Read the bits from the unsigned integer register_[] array
1116   // into the double precision floating point value and return it.
1117   char buffer[sizeof(registers_[0])];
1118   memcpy(buffer, &registers_[reg], sizeof(registers_[0]));
1119   memcpy(&dm_val, buffer, sizeof(registers_[0]));
1120   return(dm_val);
1121 }
1122 
1123 
get_fpu_register(int fpureg) const1124 int64_t Simulator::get_fpu_register(int fpureg) const {
1125   DCHECK((fpureg >= 0) && (fpureg < kNumFPURegisters));
1126   return FPUregisters_[fpureg];
1127 }
1128 
1129 
get_fpu_register_word(int fpureg) const1130 int32_t Simulator::get_fpu_register_word(int fpureg) const {
1131   DCHECK((fpureg >= 0) && (fpureg < kNumFPURegisters));
1132   return static_cast<int32_t>(FPUregisters_[fpureg] & 0xffffffff);
1133 }
1134 
1135 
get_fpu_register_signed_word(int fpureg) const1136 int32_t Simulator::get_fpu_register_signed_word(int fpureg) const {
1137   DCHECK((fpureg >= 0) && (fpureg < kNumFPURegisters));
1138   return static_cast<int32_t>(FPUregisters_[fpureg] & 0xffffffff);
1139 }
1140 
1141 
get_fpu_register_hi_word(int fpureg) const1142 int32_t Simulator::get_fpu_register_hi_word(int fpureg) const {
1143   DCHECK((fpureg >= 0) && (fpureg < kNumFPURegisters));
1144   return static_cast<int32_t>((FPUregisters_[fpureg] >> 32) & 0xffffffff);
1145 }
1146 
1147 
get_fpu_register_float(int fpureg) const1148 float Simulator::get_fpu_register_float(int fpureg) const {
1149   DCHECK((fpureg >= 0) && (fpureg < kNumFPURegisters));
1150   return *bit_cast<float*>(const_cast<int64_t*>(&FPUregisters_[fpureg]));
1151 }
1152 
1153 
get_fpu_register_double(int fpureg) const1154 double Simulator::get_fpu_register_double(int fpureg) const {
1155   DCHECK((fpureg >= 0) && (fpureg < kNumFPURegisters));
1156   return *bit_cast<double*>(&FPUregisters_[fpureg]);
1157 }
1158 
1159 
1160 // Runtime FP routines take up to two double arguments and zero
1161 // or one integer arguments. All are constructed here,
1162 // from a0-a3 or f12 and f13 (n64), or f14 (O32).
GetFpArgs(double * x,double * y,int32_t * z)1163 void Simulator::GetFpArgs(double* x, double* y, int32_t* z) {
1164   if (!IsMipsSoftFloatABI) {
1165     const int fparg2 = 13;
1166     *x = get_fpu_register_double(12);
1167     *y = get_fpu_register_double(fparg2);
1168     *z = static_cast<int32_t>(get_register(a2));
1169   } else {
1170   // TODO(plind): bad ABI stuff, refactor or remove.
1171     // We use a char buffer to get around the strict-aliasing rules which
1172     // otherwise allow the compiler to optimize away the copy.
1173     char buffer[sizeof(*x)];
1174     int32_t* reg_buffer = reinterpret_cast<int32_t*>(buffer);
1175 
1176     // Registers a0 and a1 -> x.
1177     reg_buffer[0] = get_register(a0);
1178     reg_buffer[1] = get_register(a1);
1179     memcpy(x, buffer, sizeof(buffer));
1180     // Registers a2 and a3 -> y.
1181     reg_buffer[0] = get_register(a2);
1182     reg_buffer[1] = get_register(a3);
1183     memcpy(y, buffer, sizeof(buffer));
1184     // Register 2 -> z.
1185     reg_buffer[0] = get_register(a2);
1186     memcpy(z, buffer, sizeof(*z));
1187   }
1188 }
1189 
1190 
1191 // The return value is either in v0/v1 or f0.
SetFpResult(const double & result)1192 void Simulator::SetFpResult(const double& result) {
1193   if (!IsMipsSoftFloatABI) {
1194     set_fpu_register_double(0, result);
1195   } else {
1196     char buffer[2 * sizeof(registers_[0])];
1197     int64_t* reg_buffer = reinterpret_cast<int64_t*>(buffer);
1198     memcpy(buffer, &result, sizeof(buffer));
1199     // Copy result to v0 and v1.
1200     set_register(v0, reg_buffer[0]);
1201     set_register(v1, reg_buffer[1]);
1202   }
1203 }
1204 
1205 
1206 // Helper functions for setting and testing the FCSR register's bits.
set_fcsr_bit(uint32_t cc,bool value)1207 void Simulator::set_fcsr_bit(uint32_t cc, bool value) {
1208   if (value) {
1209     FCSR_ |= (1 << cc);
1210   } else {
1211     FCSR_ &= ~(1 << cc);
1212   }
1213 }
1214 
1215 
test_fcsr_bit(uint32_t cc)1216 bool Simulator::test_fcsr_bit(uint32_t cc) {
1217   return FCSR_ & (1 << cc);
1218 }
1219 
1220 
set_fcsr_rounding_mode(FPURoundingMode mode)1221 void Simulator::set_fcsr_rounding_mode(FPURoundingMode mode) {
1222   FCSR_ |= mode & kFPURoundingModeMask;
1223 }
1224 
1225 
get_fcsr_rounding_mode()1226 unsigned int Simulator::get_fcsr_rounding_mode() {
1227   return FCSR_ & kFPURoundingModeMask;
1228 }
1229 
1230 
1231 // Sets the rounding error codes in FCSR based on the result of the rounding.
1232 // Returns true if the operation was invalid.
set_fcsr_round_error(double original,double rounded)1233 bool Simulator::set_fcsr_round_error(double original, double rounded) {
1234   bool ret = false;
1235   double max_int32 = std::numeric_limits<int32_t>::max();
1236   double min_int32 = std::numeric_limits<int32_t>::min();
1237 
1238   if (!std::isfinite(original) || !std::isfinite(rounded)) {
1239     set_fcsr_bit(kFCSRInvalidOpFlagBit, true);
1240     ret = true;
1241   }
1242 
1243   if (original != rounded) {
1244     set_fcsr_bit(kFCSRInexactFlagBit, true);
1245   }
1246 
1247   if (rounded < DBL_MIN && rounded > -DBL_MIN && rounded != 0) {
1248     set_fcsr_bit(kFCSRUnderflowFlagBit, true);
1249     ret = true;
1250   }
1251 
1252   if (rounded > max_int32 || rounded < min_int32) {
1253     set_fcsr_bit(kFCSROverflowFlagBit, true);
1254     // The reference is not really clear but it seems this is required:
1255     set_fcsr_bit(kFCSRInvalidOpFlagBit, true);
1256     ret = true;
1257   }
1258 
1259   return ret;
1260 }
1261 
1262 
1263 // Sets the rounding error codes in FCSR based on the result of the rounding.
1264 // Returns true if the operation was invalid.
set_fcsr_round64_error(double original,double rounded)1265 bool Simulator::set_fcsr_round64_error(double original, double rounded) {
1266   bool ret = false;
1267   // The value of INT64_MAX (2^63-1) can't be represented as double exactly,
1268   // loading the most accurate representation into max_int64, which is 2^63.
1269   double max_int64 = std::numeric_limits<int64_t>::max();
1270   double min_int64 = std::numeric_limits<int64_t>::min();
1271 
1272   if (!std::isfinite(original) || !std::isfinite(rounded)) {
1273     set_fcsr_bit(kFCSRInvalidOpFlagBit, true);
1274     ret = true;
1275   }
1276 
1277   if (original != rounded) {
1278     set_fcsr_bit(kFCSRInexactFlagBit, true);
1279   }
1280 
1281   if (rounded < DBL_MIN && rounded > -DBL_MIN && rounded != 0) {
1282     set_fcsr_bit(kFCSRUnderflowFlagBit, true);
1283     ret = true;
1284   }
1285 
1286   if (rounded >= max_int64 || rounded < min_int64) {
1287     set_fcsr_bit(kFCSROverflowFlagBit, true);
1288     // The reference is not really clear but it seems this is required:
1289     set_fcsr_bit(kFCSRInvalidOpFlagBit, true);
1290     ret = true;
1291   }
1292 
1293   return ret;
1294 }
1295 
1296 
1297 // Sets the rounding error codes in FCSR based on the result of the rounding.
1298 // Returns true if the operation was invalid.
set_fcsr_round_error(float original,float rounded)1299 bool Simulator::set_fcsr_round_error(float original, float rounded) {
1300   bool ret = false;
1301   double max_int32 = std::numeric_limits<int32_t>::max();
1302   double min_int32 = std::numeric_limits<int32_t>::min();
1303 
1304   if (!std::isfinite(original) || !std::isfinite(rounded)) {
1305     set_fcsr_bit(kFCSRInvalidOpFlagBit, true);
1306     ret = true;
1307   }
1308 
1309   if (original != rounded) {
1310     set_fcsr_bit(kFCSRInexactFlagBit, true);
1311   }
1312 
1313   if (rounded < FLT_MIN && rounded > -FLT_MIN && rounded != 0) {
1314     set_fcsr_bit(kFCSRUnderflowFlagBit, true);
1315     ret = true;
1316   }
1317 
1318   if (rounded > max_int32 || rounded < min_int32) {
1319     set_fcsr_bit(kFCSROverflowFlagBit, true);
1320     // The reference is not really clear but it seems this is required:
1321     set_fcsr_bit(kFCSRInvalidOpFlagBit, true);
1322     ret = true;
1323   }
1324 
1325   return ret;
1326 }
1327 
set_fpu_register_word_invalid_result(float original,float rounded)1328 void Simulator::set_fpu_register_word_invalid_result(float original,
1329                                                      float rounded) {
1330   if (FCSR_ & kFCSRNaN2008FlagMask) {
1331     double max_int32 = std::numeric_limits<int32_t>::max();
1332     double min_int32 = std::numeric_limits<int32_t>::min();
1333     if (std::isnan(original)) {
1334       set_fpu_register_word(fd_reg(), 0);
1335     } else if (rounded > max_int32) {
1336       set_fpu_register_word(fd_reg(), kFPUInvalidResult);
1337     } else if (rounded < min_int32) {
1338       set_fpu_register_word(fd_reg(), kFPUInvalidResultNegative);
1339     } else {
1340       UNREACHABLE();
1341     }
1342   } else {
1343     set_fpu_register_word(fd_reg(), kFPUInvalidResult);
1344   }
1345 }
1346 
1347 
set_fpu_register_invalid_result(float original,float rounded)1348 void Simulator::set_fpu_register_invalid_result(float original, float rounded) {
1349   if (FCSR_ & kFCSRNaN2008FlagMask) {
1350     double max_int32 = std::numeric_limits<int32_t>::max();
1351     double min_int32 = std::numeric_limits<int32_t>::min();
1352     if (std::isnan(original)) {
1353       set_fpu_register(fd_reg(), 0);
1354     } else if (rounded > max_int32) {
1355       set_fpu_register(fd_reg(), kFPUInvalidResult);
1356     } else if (rounded < min_int32) {
1357       set_fpu_register(fd_reg(), kFPUInvalidResultNegative);
1358     } else {
1359       UNREACHABLE();
1360     }
1361   } else {
1362     set_fpu_register(fd_reg(), kFPUInvalidResult);
1363   }
1364 }
1365 
1366 
set_fpu_register_invalid_result64(float original,float rounded)1367 void Simulator::set_fpu_register_invalid_result64(float original,
1368                                                   float rounded) {
1369   if (FCSR_ & kFCSRNaN2008FlagMask) {
1370     // The value of INT64_MAX (2^63-1) can't be represented as double exactly,
1371     // loading the most accurate representation into max_int64, which is 2^63.
1372     double max_int64 = std::numeric_limits<int64_t>::max();
1373     double min_int64 = std::numeric_limits<int64_t>::min();
1374     if (std::isnan(original)) {
1375       set_fpu_register(fd_reg(), 0);
1376     } else if (rounded >= max_int64) {
1377       set_fpu_register(fd_reg(), kFPU64InvalidResult);
1378     } else if (rounded < min_int64) {
1379       set_fpu_register(fd_reg(), kFPU64InvalidResultNegative);
1380     } else {
1381       UNREACHABLE();
1382     }
1383   } else {
1384     set_fpu_register(fd_reg(), kFPU64InvalidResult);
1385   }
1386 }
1387 
1388 
set_fpu_register_word_invalid_result(double original,double rounded)1389 void Simulator::set_fpu_register_word_invalid_result(double original,
1390                                                      double rounded) {
1391   if (FCSR_ & kFCSRNaN2008FlagMask) {
1392     double max_int32 = std::numeric_limits<int32_t>::max();
1393     double min_int32 = std::numeric_limits<int32_t>::min();
1394     if (std::isnan(original)) {
1395       set_fpu_register_word(fd_reg(), 0);
1396     } else if (rounded > max_int32) {
1397       set_fpu_register_word(fd_reg(), kFPUInvalidResult);
1398     } else if (rounded < min_int32) {
1399       set_fpu_register_word(fd_reg(), kFPUInvalidResultNegative);
1400     } else {
1401       UNREACHABLE();
1402     }
1403   } else {
1404     set_fpu_register_word(fd_reg(), kFPUInvalidResult);
1405   }
1406 }
1407 
1408 
set_fpu_register_invalid_result(double original,double rounded)1409 void Simulator::set_fpu_register_invalid_result(double original,
1410                                                 double rounded) {
1411   if (FCSR_ & kFCSRNaN2008FlagMask) {
1412     double max_int32 = std::numeric_limits<int32_t>::max();
1413     double min_int32 = std::numeric_limits<int32_t>::min();
1414     if (std::isnan(original)) {
1415       set_fpu_register(fd_reg(), 0);
1416     } else if (rounded > max_int32) {
1417       set_fpu_register(fd_reg(), kFPUInvalidResult);
1418     } else if (rounded < min_int32) {
1419       set_fpu_register(fd_reg(), kFPUInvalidResultNegative);
1420     } else {
1421       UNREACHABLE();
1422     }
1423   } else {
1424     set_fpu_register(fd_reg(), kFPUInvalidResult);
1425   }
1426 }
1427 
1428 
set_fpu_register_invalid_result64(double original,double rounded)1429 void Simulator::set_fpu_register_invalid_result64(double original,
1430                                                   double rounded) {
1431   if (FCSR_ & kFCSRNaN2008FlagMask) {
1432     // The value of INT64_MAX (2^63-1) can't be represented as double exactly,
1433     // loading the most accurate representation into max_int64, which is 2^63.
1434     double max_int64 = std::numeric_limits<int64_t>::max();
1435     double min_int64 = std::numeric_limits<int64_t>::min();
1436     if (std::isnan(original)) {
1437       set_fpu_register(fd_reg(), 0);
1438     } else if (rounded >= max_int64) {
1439       set_fpu_register(fd_reg(), kFPU64InvalidResult);
1440     } else if (rounded < min_int64) {
1441       set_fpu_register(fd_reg(), kFPU64InvalidResultNegative);
1442     } else {
1443       UNREACHABLE();
1444     }
1445   } else {
1446     set_fpu_register(fd_reg(), kFPU64InvalidResult);
1447   }
1448 }
1449 
1450 
1451 // Sets the rounding error codes in FCSR based on the result of the rounding.
1452 // Returns true if the operation was invalid.
set_fcsr_round64_error(float original,float rounded)1453 bool Simulator::set_fcsr_round64_error(float original, float rounded) {
1454   bool ret = false;
1455   // The value of INT64_MAX (2^63-1) can't be represented as double exactly,
1456   // loading the most accurate representation into max_int64, which is 2^63.
1457   double max_int64 = std::numeric_limits<int64_t>::max();
1458   double min_int64 = std::numeric_limits<int64_t>::min();
1459 
1460   if (!std::isfinite(original) || !std::isfinite(rounded)) {
1461     set_fcsr_bit(kFCSRInvalidOpFlagBit, true);
1462     ret = true;
1463   }
1464 
1465   if (original != rounded) {
1466     set_fcsr_bit(kFCSRInexactFlagBit, true);
1467   }
1468 
1469   if (rounded < FLT_MIN && rounded > -FLT_MIN && rounded != 0) {
1470     set_fcsr_bit(kFCSRUnderflowFlagBit, true);
1471     ret = true;
1472   }
1473 
1474   if (rounded >= max_int64 || rounded < min_int64) {
1475     set_fcsr_bit(kFCSROverflowFlagBit, true);
1476     // The reference is not really clear but it seems this is required:
1477     set_fcsr_bit(kFCSRInvalidOpFlagBit, true);
1478     ret = true;
1479   }
1480 
1481   return ret;
1482 }
1483 
1484 
1485 // For cvt instructions only
round_according_to_fcsr(double toRound,double & rounded,int32_t & rounded_int,double fs)1486 void Simulator::round_according_to_fcsr(double toRound, double& rounded,
1487                                         int32_t& rounded_int, double fs) {
1488   // 0 RN (round to nearest): Round a result to the nearest
1489   // representable value; if the result is exactly halfway between
1490   // two representable values, round to zero. Behave like round_w_d.
1491 
1492   // 1 RZ (round toward zero): Round a result to the closest
1493   // representable value whose absolute value is less than or
1494   // equal to the infinitely accurate result. Behave like trunc_w_d.
1495 
1496   // 2 RP (round up, or toward +infinity): Round a result to the
1497   // next representable value up. Behave like ceil_w_d.
1498 
1499   // 3 RN (round down, or toward −infinity): Round a result to
1500   // the next representable value down. Behave like floor_w_d.
1501   switch (FCSR_ & 3) {
1502     case kRoundToNearest:
1503       rounded = std::floor(fs + 0.5);
1504       rounded_int = static_cast<int32_t>(rounded);
1505       if ((rounded_int & 1) != 0 && rounded_int - fs == 0.5) {
1506         // If the number is halfway between two integers,
1507         // round to the even one.
1508         rounded_int--;
1509       }
1510       break;
1511     case kRoundToZero:
1512       rounded = trunc(fs);
1513       rounded_int = static_cast<int32_t>(rounded);
1514       break;
1515     case kRoundToPlusInf:
1516       rounded = std::ceil(fs);
1517       rounded_int = static_cast<int32_t>(rounded);
1518       break;
1519     case kRoundToMinusInf:
1520       rounded = std::floor(fs);
1521       rounded_int = static_cast<int32_t>(rounded);
1522       break;
1523   }
1524 }
1525 
1526 
round64_according_to_fcsr(double toRound,double & rounded,int64_t & rounded_int,double fs)1527 void Simulator::round64_according_to_fcsr(double toRound, double& rounded,
1528                                           int64_t& rounded_int, double fs) {
1529   // 0 RN (round to nearest): Round a result to the nearest
1530   // representable value; if the result is exactly halfway between
1531   // two representable values, round to zero. Behave like round_w_d.
1532 
1533   // 1 RZ (round toward zero): Round a result to the closest
1534   // representable value whose absolute value is less than or.
1535   // equal to the infinitely accurate result. Behave like trunc_w_d.
1536 
1537   // 2 RP (round up, or toward +infinity): Round a result to the
1538   // next representable value up. Behave like ceil_w_d.
1539 
1540   // 3 RN (round down, or toward −infinity): Round a result to
1541   // the next representable value down. Behave like floor_w_d.
1542   switch (FCSR_ & 3) {
1543     case kRoundToNearest:
1544       rounded = std::floor(fs + 0.5);
1545       rounded_int = static_cast<int64_t>(rounded);
1546       if ((rounded_int & 1) != 0 && rounded_int - fs == 0.5) {
1547         // If the number is halfway between two integers,
1548         // round to the even one.
1549         rounded_int--;
1550       }
1551       break;
1552     case kRoundToZero:
1553       rounded = trunc(fs);
1554       rounded_int = static_cast<int64_t>(rounded);
1555       break;
1556     case kRoundToPlusInf:
1557       rounded = std::ceil(fs);
1558       rounded_int = static_cast<int64_t>(rounded);
1559       break;
1560     case kRoundToMinusInf:
1561       rounded = std::floor(fs);
1562       rounded_int = static_cast<int64_t>(rounded);
1563       break;
1564   }
1565 }
1566 
1567 
1568 // for cvt instructions only
round_according_to_fcsr(float toRound,float & rounded,int32_t & rounded_int,float fs)1569 void Simulator::round_according_to_fcsr(float toRound, float& rounded,
1570                                         int32_t& rounded_int, float fs) {
1571   // 0 RN (round to nearest): Round a result to the nearest
1572   // representable value; if the result is exactly halfway between
1573   // two representable values, round to zero. Behave like round_w_d.
1574 
1575   // 1 RZ (round toward zero): Round a result to the closest
1576   // representable value whose absolute value is less than or
1577   // equal to the infinitely accurate result. Behave like trunc_w_d.
1578 
1579   // 2 RP (round up, or toward +infinity): Round a result to the
1580   // next representable value up. Behave like ceil_w_d.
1581 
1582   // 3 RN (round down, or toward −infinity): Round a result to
1583   // the next representable value down. Behave like floor_w_d.
1584   switch (FCSR_ & 3) {
1585     case kRoundToNearest:
1586       rounded = std::floor(fs + 0.5);
1587       rounded_int = static_cast<int32_t>(rounded);
1588       if ((rounded_int & 1) != 0 && rounded_int - fs == 0.5) {
1589         // If the number is halfway between two integers,
1590         // round to the even one.
1591         rounded_int--;
1592       }
1593       break;
1594     case kRoundToZero:
1595       rounded = trunc(fs);
1596       rounded_int = static_cast<int32_t>(rounded);
1597       break;
1598     case kRoundToPlusInf:
1599       rounded = std::ceil(fs);
1600       rounded_int = static_cast<int32_t>(rounded);
1601       break;
1602     case kRoundToMinusInf:
1603       rounded = std::floor(fs);
1604       rounded_int = static_cast<int32_t>(rounded);
1605       break;
1606   }
1607 }
1608 
1609 
round64_according_to_fcsr(float toRound,float & rounded,int64_t & rounded_int,float fs)1610 void Simulator::round64_according_to_fcsr(float toRound, float& rounded,
1611                                           int64_t& rounded_int, float fs) {
1612   // 0 RN (round to nearest): Round a result to the nearest
1613   // representable value; if the result is exactly halfway between
1614   // two representable values, round to zero. Behave like round_w_d.
1615 
1616   // 1 RZ (round toward zero): Round a result to the closest
1617   // representable value whose absolute value is less than or.
1618   // equal to the infinitely accurate result. Behave like trunc_w_d.
1619 
1620   // 2 RP (round up, or toward +infinity): Round a result to the
1621   // next representable value up. Behave like ceil_w_d.
1622 
1623   // 3 RN (round down, or toward −infinity): Round a result to
1624   // the next representable value down. Behave like floor_w_d.
1625   switch (FCSR_ & 3) {
1626     case kRoundToNearest:
1627       rounded = std::floor(fs + 0.5);
1628       rounded_int = static_cast<int64_t>(rounded);
1629       if ((rounded_int & 1) != 0 && rounded_int - fs == 0.5) {
1630         // If the number is halfway between two integers,
1631         // round to the even one.
1632         rounded_int--;
1633       }
1634       break;
1635     case kRoundToZero:
1636       rounded = trunc(fs);
1637       rounded_int = static_cast<int64_t>(rounded);
1638       break;
1639     case kRoundToPlusInf:
1640       rounded = std::ceil(fs);
1641       rounded_int = static_cast<int64_t>(rounded);
1642       break;
1643     case kRoundToMinusInf:
1644       rounded = std::floor(fs);
1645       rounded_int = static_cast<int64_t>(rounded);
1646       break;
1647   }
1648 }
1649 
1650 
1651 // Raw access to the PC register.
set_pc(int64_t value)1652 void Simulator::set_pc(int64_t value) {
1653   pc_modified_ = true;
1654   registers_[pc] = value;
1655 }
1656 
1657 
has_bad_pc() const1658 bool Simulator::has_bad_pc() const {
1659   return ((registers_[pc] == bad_ra) || (registers_[pc] == end_sim_pc));
1660 }
1661 
1662 
1663 // Raw access to the PC register without the special adjustment when reading.
get_pc() const1664 int64_t Simulator::get_pc() const {
1665   return registers_[pc];
1666 }
1667 
1668 
1669 // The MIPS cannot do unaligned reads and writes.  On some MIPS platforms an
1670 // interrupt is caused.  On others it does a funky rotation thing.  For now we
1671 // simply disallow unaligned reads, but at some point we may want to move to
1672 // emulating the rotate behaviour.  Note that simulator runs have the runtime
1673 // system running directly on the host system and only generated code is
1674 // executed in the simulator.  Since the host is typically IA32 we will not
1675 // get the correct MIPS-like behaviour on unaligned accesses.
1676 
1677 // TODO(plind): refactor this messy debug code when we do unaligned access.
DieOrDebug()1678 void Simulator::DieOrDebug() {
1679   if (1) {  // Flag for this was removed.
1680     MipsDebugger dbg(this);
1681     dbg.Debug();
1682   } else {
1683     base::OS::Abort();
1684   }
1685 }
1686 
1687 
TraceRegWr(int64_t value)1688 void Simulator::TraceRegWr(int64_t value) {
1689   if (::v8::internal::FLAG_trace_sim) {
1690     SNPrintF(trace_buf_, "%016" PRIx64 " ", value);
1691   }
1692 }
1693 
1694 
1695 // TODO(plind): consider making icount_ printing a flag option.
TraceMemRd(int64_t addr,int64_t value)1696 void Simulator::TraceMemRd(int64_t addr, int64_t value) {
1697   if (::v8::internal::FLAG_trace_sim) {
1698     SNPrintF(trace_buf_,
1699              "%016" PRIx64 "  <-- [%016" PRIx64 " ]    (%" PRId64 " )", value,
1700              addr, icount_);
1701   }
1702 }
1703 
1704 
TraceMemWr(int64_t addr,int64_t value,TraceType t)1705 void Simulator::TraceMemWr(int64_t addr, int64_t value, TraceType t) {
1706   if (::v8::internal::FLAG_trace_sim) {
1707     switch (t) {
1708       case BYTE:
1709         SNPrintF(trace_buf_, "               %02x --> [%016" PRIx64 " ]",
1710                  static_cast<int8_t>(value), addr);
1711         break;
1712       case HALF:
1713         SNPrintF(trace_buf_, "            %04x --> [%016" PRIx64 " ]",
1714                  static_cast<int16_t>(value), addr);
1715         break;
1716       case WORD:
1717         SNPrintF(trace_buf_, "        %08x --> [%016" PRIx64 " ]",
1718                  static_cast<int32_t>(value), addr);
1719         break;
1720       case DWORD:
1721         SNPrintF(trace_buf_,
1722                  "%016" PRIx64 "  --> [%016" PRIx64 " ]    (%" PRId64 " )",
1723                  value, addr, icount_);
1724         break;
1725     }
1726   }
1727 }
1728 
1729 
1730 // TODO(plind): sign-extend and zero-extend not implmented properly
1731 // on all the ReadXX functions, I don't think re-interpret cast does it.
ReadW(int64_t addr,Instruction * instr)1732 int32_t Simulator::ReadW(int64_t addr, Instruction* instr) {
1733   if (addr >=0 && addr < 0x400) {
1734     // This has to be a NULL-dereference, drop into debugger.
1735     PrintF("Memory read from bad address: 0x%08" PRIx64 " , pc=0x%08" PRIxPTR
1736            " \n",
1737            addr, reinterpret_cast<intptr_t>(instr));
1738     DieOrDebug();
1739   }
1740   if ((addr & 0x3) == 0 || kArchVariant == kMips64r6) {
1741     int32_t* ptr = reinterpret_cast<int32_t*>(addr);
1742     TraceMemRd(addr, static_cast<int64_t>(*ptr));
1743     return *ptr;
1744   }
1745   PrintF("Unaligned read at 0x%08" PRIx64 " , pc=0x%08" V8PRIxPTR "\n", addr,
1746          reinterpret_cast<intptr_t>(instr));
1747   DieOrDebug();
1748   return 0;
1749 }
1750 
1751 
ReadWU(int64_t addr,Instruction * instr)1752 uint32_t Simulator::ReadWU(int64_t addr, Instruction* instr) {
1753   if (addr >=0 && addr < 0x400) {
1754     // This has to be a NULL-dereference, drop into debugger.
1755     PrintF("Memory read from bad address: 0x%08" PRIx64 " , pc=0x%08" PRIxPTR
1756            " \n",
1757            addr, reinterpret_cast<intptr_t>(instr));
1758     DieOrDebug();
1759   }
1760   if ((addr & 0x3) == 0 || kArchVariant == kMips64r6) {
1761     uint32_t* ptr = reinterpret_cast<uint32_t*>(addr);
1762     TraceMemRd(addr, static_cast<int64_t>(*ptr));
1763     return *ptr;
1764   }
1765   PrintF("Unaligned read at 0x%08" PRIx64 " , pc=0x%08" V8PRIxPTR "\n", addr,
1766          reinterpret_cast<intptr_t>(instr));
1767   DieOrDebug();
1768   return 0;
1769 }
1770 
1771 
WriteW(int64_t addr,int32_t value,Instruction * instr)1772 void Simulator::WriteW(int64_t addr, int32_t value, Instruction* instr) {
1773   if (addr >= 0 && addr < 0x400) {
1774     // This has to be a NULL-dereference, drop into debugger.
1775     PrintF("Memory write to bad address: 0x%08" PRIx64 " , pc=0x%08" PRIxPTR
1776            " \n",
1777            addr, reinterpret_cast<intptr_t>(instr));
1778     DieOrDebug();
1779   }
1780   if ((addr & 0x3) == 0 || kArchVariant == kMips64r6) {
1781     TraceMemWr(addr, value, WORD);
1782     int* ptr = reinterpret_cast<int*>(addr);
1783     *ptr = value;
1784     return;
1785   }
1786   PrintF("Unaligned write at 0x%08" PRIx64 " , pc=0x%08" V8PRIxPTR "\n", addr,
1787          reinterpret_cast<intptr_t>(instr));
1788   DieOrDebug();
1789 }
1790 
1791 
Read2W(int64_t addr,Instruction * instr)1792 int64_t Simulator::Read2W(int64_t addr, Instruction* instr) {
1793   if (addr >=0 && addr < 0x400) {
1794     // This has to be a NULL-dereference, drop into debugger.
1795     PrintF("Memory read from bad address: 0x%08" PRIx64 " , pc=0x%08" PRIxPTR
1796            " \n",
1797            addr, reinterpret_cast<intptr_t>(instr));
1798     DieOrDebug();
1799   }
1800   if ((addr & kPointerAlignmentMask) == 0 || kArchVariant == kMips64r6) {
1801     int64_t* ptr = reinterpret_cast<int64_t*>(addr);
1802     TraceMemRd(addr, *ptr);
1803     return *ptr;
1804   }
1805   PrintF("Unaligned read at 0x%08" PRIx64 " , pc=0x%08" V8PRIxPTR "\n", addr,
1806          reinterpret_cast<intptr_t>(instr));
1807   DieOrDebug();
1808   return 0;
1809 }
1810 
1811 
Write2W(int64_t addr,int64_t value,Instruction * instr)1812 void Simulator::Write2W(int64_t addr, int64_t value, Instruction* instr) {
1813   if (addr >= 0 && addr < 0x400) {
1814     // This has to be a NULL-dereference, drop into debugger.
1815     PrintF("Memory write to bad address: 0x%08" PRIx64 " , pc=0x%08" PRIxPTR
1816            "\n",
1817            addr, reinterpret_cast<intptr_t>(instr));
1818     DieOrDebug();
1819   }
1820   if ((addr & kPointerAlignmentMask) == 0 || kArchVariant == kMips64r6) {
1821     TraceMemWr(addr, value, DWORD);
1822     int64_t* ptr = reinterpret_cast<int64_t*>(addr);
1823     *ptr = value;
1824     return;
1825   }
1826   PrintF("Unaligned write at 0x%08" PRIx64 " , pc=0x%08" V8PRIxPTR "\n", addr,
1827          reinterpret_cast<intptr_t>(instr));
1828   DieOrDebug();
1829 }
1830 
1831 
ReadD(int64_t addr,Instruction * instr)1832 double Simulator::ReadD(int64_t addr, Instruction* instr) {
1833   if ((addr & kDoubleAlignmentMask) == 0 || kArchVariant == kMips64r6) {
1834     double* ptr = reinterpret_cast<double*>(addr);
1835     return *ptr;
1836   }
1837   PrintF("Unaligned (double) read at 0x%08" PRIx64 " , pc=0x%08" V8PRIxPTR "\n",
1838          addr, reinterpret_cast<intptr_t>(instr));
1839   base::OS::Abort();
1840   return 0;
1841 }
1842 
1843 
WriteD(int64_t addr,double value,Instruction * instr)1844 void Simulator::WriteD(int64_t addr, double value, Instruction* instr) {
1845   if ((addr & kDoubleAlignmentMask) == 0 || kArchVariant == kMips64r6) {
1846     double* ptr = reinterpret_cast<double*>(addr);
1847     *ptr = value;
1848     return;
1849   }
1850   PrintF("Unaligned (double) write at 0x%08" PRIx64 " , pc=0x%08" V8PRIxPTR
1851          "\n",
1852          addr, reinterpret_cast<intptr_t>(instr));
1853   DieOrDebug();
1854 }
1855 
1856 
ReadHU(int64_t addr,Instruction * instr)1857 uint16_t Simulator::ReadHU(int64_t addr, Instruction* instr) {
1858   if ((addr & 1) == 0 || kArchVariant == kMips64r6) {
1859     uint16_t* ptr = reinterpret_cast<uint16_t*>(addr);
1860     TraceMemRd(addr, static_cast<int64_t>(*ptr));
1861     return *ptr;
1862   }
1863   PrintF("Unaligned unsigned halfword read at 0x%08" PRIx64
1864          " , pc=0x%08" V8PRIxPTR "\n",
1865          addr, reinterpret_cast<intptr_t>(instr));
1866   DieOrDebug();
1867   return 0;
1868 }
1869 
1870 
ReadH(int64_t addr,Instruction * instr)1871 int16_t Simulator::ReadH(int64_t addr, Instruction* instr) {
1872   if ((addr & 1) == 0 || kArchVariant == kMips64r6) {
1873     int16_t* ptr = reinterpret_cast<int16_t*>(addr);
1874     TraceMemRd(addr, static_cast<int64_t>(*ptr));
1875     return *ptr;
1876   }
1877   PrintF("Unaligned signed halfword read at 0x%08" PRIx64
1878          " , pc=0x%08" V8PRIxPTR "\n",
1879          addr, reinterpret_cast<intptr_t>(instr));
1880   DieOrDebug();
1881   return 0;
1882 }
1883 
1884 
WriteH(int64_t addr,uint16_t value,Instruction * instr)1885 void Simulator::WriteH(int64_t addr, uint16_t value, Instruction* instr) {
1886   if ((addr & 1) == 0 || kArchVariant == kMips64r6) {
1887     TraceMemWr(addr, value, HALF);
1888     uint16_t* ptr = reinterpret_cast<uint16_t*>(addr);
1889     *ptr = value;
1890     return;
1891   }
1892   PrintF("Unaligned unsigned halfword write at 0x%08" PRIx64
1893          " , pc=0x%08" V8PRIxPTR "\n",
1894          addr, reinterpret_cast<intptr_t>(instr));
1895   DieOrDebug();
1896 }
1897 
1898 
WriteH(int64_t addr,int16_t value,Instruction * instr)1899 void Simulator::WriteH(int64_t addr, int16_t value, Instruction* instr) {
1900   if ((addr & 1) == 0 || kArchVariant == kMips64r6) {
1901     TraceMemWr(addr, value, HALF);
1902     int16_t* ptr = reinterpret_cast<int16_t*>(addr);
1903     *ptr = value;
1904     return;
1905   }
1906   PrintF("Unaligned halfword write at 0x%08" PRIx64 " , pc=0x%08" V8PRIxPTR
1907          "\n",
1908          addr, reinterpret_cast<intptr_t>(instr));
1909   DieOrDebug();
1910 }
1911 
1912 
ReadBU(int64_t addr)1913 uint32_t Simulator::ReadBU(int64_t addr) {
1914   uint8_t* ptr = reinterpret_cast<uint8_t*>(addr);
1915   TraceMemRd(addr, static_cast<int64_t>(*ptr));
1916   return *ptr & 0xff;
1917 }
1918 
1919 
ReadB(int64_t addr)1920 int32_t Simulator::ReadB(int64_t addr) {
1921   int8_t* ptr = reinterpret_cast<int8_t*>(addr);
1922   TraceMemRd(addr, static_cast<int64_t>(*ptr));
1923   return *ptr;
1924 }
1925 
1926 
WriteB(int64_t addr,uint8_t value)1927 void Simulator::WriteB(int64_t addr, uint8_t value) {
1928   TraceMemWr(addr, value, BYTE);
1929   uint8_t* ptr = reinterpret_cast<uint8_t*>(addr);
1930   *ptr = value;
1931 }
1932 
1933 
WriteB(int64_t addr,int8_t value)1934 void Simulator::WriteB(int64_t addr, int8_t value) {
1935   TraceMemWr(addr, value, BYTE);
1936   int8_t* ptr = reinterpret_cast<int8_t*>(addr);
1937   *ptr = value;
1938 }
1939 
1940 
1941 // Returns the limit of the stack area to enable checking for stack overflows.
StackLimit(uintptr_t c_limit) const1942 uintptr_t Simulator::StackLimit(uintptr_t c_limit) const {
1943   // The simulator uses a separate JS stack. If we have exhausted the C stack,
1944   // we also drop down the JS limit to reflect the exhaustion on the JS stack.
1945   if (GetCurrentStackPosition() < c_limit) {
1946     return reinterpret_cast<uintptr_t>(get_sp());
1947   }
1948 
1949   // Otherwise the limit is the JS stack. Leave a safety margin of 1024 bytes
1950   // to prevent overrunning the stack when pushing values.
1951   return reinterpret_cast<uintptr_t>(stack_) + 1024;
1952 }
1953 
1954 
1955 // Unsupported instructions use Format to print an error and stop execution.
Format(Instruction * instr,const char * format)1956 void Simulator::Format(Instruction* instr, const char* format) {
1957   PrintF("Simulator found unsupported instruction:\n 0x%08" PRIxPTR " : %s\n",
1958          reinterpret_cast<intptr_t>(instr), format);
1959   UNIMPLEMENTED_MIPS();
1960 }
1961 
1962 
1963 // Calls into the V8 runtime are based on this very simple interface.
1964 // Note: To be able to return two values from some calls the code in runtime.cc
1965 // uses the ObjectPair which is essentially two 32-bit values stuffed into a
1966 // 64-bit value. With the code below we assume that all runtime calls return
1967 // 64 bits of result. If they don't, the v1 result register contains a bogus
1968 // value, which is fine because it is caller-saved.
1969 
1970 typedef ObjectPair (*SimulatorRuntimeCall)(int64_t arg0,
1971                                         int64_t arg1,
1972                                         int64_t arg2,
1973                                         int64_t arg3,
1974                                         int64_t arg4,
1975                                         int64_t arg5);
1976 
1977 typedef ObjectTriple (*SimulatorRuntimeTripleCall)(int64_t arg0, int64_t arg1,
1978                                                    int64_t arg2, int64_t arg3,
1979                                                    int64_t arg4);
1980 
1981 // These prototypes handle the four types of FP calls.
1982 typedef int64_t (*SimulatorRuntimeCompareCall)(double darg0, double darg1);
1983 typedef double (*SimulatorRuntimeFPFPCall)(double darg0, double darg1);
1984 typedef double (*SimulatorRuntimeFPCall)(double darg0);
1985 typedef double (*SimulatorRuntimeFPIntCall)(double darg0, int32_t arg0);
1986 
1987 // This signature supports direct call in to API function native callback
1988 // (refer to InvocationCallback in v8.h).
1989 typedef void (*SimulatorRuntimeDirectApiCall)(int64_t arg0);
1990 typedef void (*SimulatorRuntimeProfilingApiCall)(int64_t arg0, void* arg1);
1991 
1992 // This signature supports direct call to accessor getter callback.
1993 typedef void (*SimulatorRuntimeDirectGetterCall)(int64_t arg0, int64_t arg1);
1994 typedef void (*SimulatorRuntimeProfilingGetterCall)(
1995     int64_t arg0, int64_t arg1, void* arg2);
1996 
1997 // Software interrupt instructions are used by the simulator to call into the
1998 // C-based V8 runtime. They are also used for debugging with simulator.
SoftwareInterrupt(Instruction * instr)1999 void Simulator::SoftwareInterrupt(Instruction* instr) {
2000   // There are several instructions that could get us here,
2001   // the break_ instruction, or several variants of traps. All
2002   // Are "SPECIAL" class opcode, and are distinuished by function.
2003   int32_t func = instr->FunctionFieldRaw();
2004   uint32_t code = (func == BREAK) ? instr->Bits(25, 6) : -1;
2005   // We first check if we met a call_rt_redirected.
2006   if (instr->InstructionBits() == rtCallRedirInstr) {
2007     Redirection* redirection = Redirection::FromSwiInstruction(instr);
2008     int64_t arg0 = get_register(a0);
2009     int64_t arg1 = get_register(a1);
2010     int64_t arg2 = get_register(a2);
2011     int64_t arg3 = get_register(a3);
2012     int64_t arg4, arg5;
2013 
2014     arg4 = get_register(a4);  // Abi n64 register a4.
2015     arg5 = get_register(a5);  // Abi n64 register a5.
2016 
2017     bool fp_call =
2018          (redirection->type() == ExternalReference::BUILTIN_FP_FP_CALL) ||
2019          (redirection->type() == ExternalReference::BUILTIN_COMPARE_CALL) ||
2020          (redirection->type() == ExternalReference::BUILTIN_FP_CALL) ||
2021          (redirection->type() == ExternalReference::BUILTIN_FP_INT_CALL);
2022 
2023     if (!IsMipsSoftFloatABI) {
2024       // With the hard floating point calling convention, double
2025       // arguments are passed in FPU registers. Fetch the arguments
2026       // from there and call the builtin using soft floating point
2027       // convention.
2028       switch (redirection->type()) {
2029       case ExternalReference::BUILTIN_FP_FP_CALL:
2030       case ExternalReference::BUILTIN_COMPARE_CALL:
2031         arg0 = get_fpu_register(f12);
2032         arg1 = get_fpu_register(f13);
2033         arg2 = get_fpu_register(f14);
2034         arg3 = get_fpu_register(f15);
2035         break;
2036       case ExternalReference::BUILTIN_FP_CALL:
2037         arg0 = get_fpu_register(f12);
2038         arg1 = get_fpu_register(f13);
2039         break;
2040       case ExternalReference::BUILTIN_FP_INT_CALL:
2041         arg0 = get_fpu_register(f12);
2042         arg1 = get_fpu_register(f13);
2043         arg2 = get_register(a2);
2044         break;
2045       default:
2046         break;
2047       }
2048     }
2049 
2050     // This is dodgy but it works because the C entry stubs are never moved.
2051     // See comment in codegen-arm.cc and bug 1242173.
2052     int64_t saved_ra = get_register(ra);
2053 
2054     intptr_t external =
2055           reinterpret_cast<intptr_t>(redirection->external_function());
2056 
2057     // Based on CpuFeatures::IsSupported(FPU), Mips will use either hardware
2058     // FPU, or gcc soft-float routines. Hardware FPU is simulated in this
2059     // simulator. Soft-float has additional abstraction of ExternalReference,
2060     // to support serialization.
2061     if (fp_call) {
2062       double dval0, dval1;  // one or two double parameters
2063       int32_t ival;         // zero or one integer parameters
2064       int64_t iresult = 0;  // integer return value
2065       double dresult = 0;   // double return value
2066       GetFpArgs(&dval0, &dval1, &ival);
2067       SimulatorRuntimeCall generic_target =
2068           reinterpret_cast<SimulatorRuntimeCall>(external);
2069       if (::v8::internal::FLAG_trace_sim) {
2070         switch (redirection->type()) {
2071           case ExternalReference::BUILTIN_FP_FP_CALL:
2072           case ExternalReference::BUILTIN_COMPARE_CALL:
2073             PrintF("Call to host function at %p with args %f, %f",
2074                    static_cast<void*>(FUNCTION_ADDR(generic_target)), dval0,
2075                    dval1);
2076             break;
2077           case ExternalReference::BUILTIN_FP_CALL:
2078             PrintF("Call to host function at %p with arg %f",
2079                    static_cast<void*>(FUNCTION_ADDR(generic_target)), dval0);
2080             break;
2081           case ExternalReference::BUILTIN_FP_INT_CALL:
2082             PrintF("Call to host function at %p with args %f, %d",
2083                    static_cast<void*>(FUNCTION_ADDR(generic_target)), dval0,
2084                    ival);
2085             break;
2086           default:
2087             UNREACHABLE();
2088             break;
2089         }
2090       }
2091       switch (redirection->type()) {
2092       case ExternalReference::BUILTIN_COMPARE_CALL: {
2093         SimulatorRuntimeCompareCall target =
2094           reinterpret_cast<SimulatorRuntimeCompareCall>(external);
2095         iresult = target(dval0, dval1);
2096         set_register(v0, static_cast<int64_t>(iresult));
2097       //  set_register(v1, static_cast<int64_t>(iresult >> 32));
2098         break;
2099       }
2100       case ExternalReference::BUILTIN_FP_FP_CALL: {
2101         SimulatorRuntimeFPFPCall target =
2102           reinterpret_cast<SimulatorRuntimeFPFPCall>(external);
2103         dresult = target(dval0, dval1);
2104         SetFpResult(dresult);
2105         break;
2106       }
2107       case ExternalReference::BUILTIN_FP_CALL: {
2108         SimulatorRuntimeFPCall target =
2109           reinterpret_cast<SimulatorRuntimeFPCall>(external);
2110         dresult = target(dval0);
2111         SetFpResult(dresult);
2112         break;
2113       }
2114       case ExternalReference::BUILTIN_FP_INT_CALL: {
2115         SimulatorRuntimeFPIntCall target =
2116           reinterpret_cast<SimulatorRuntimeFPIntCall>(external);
2117         dresult = target(dval0, ival);
2118         SetFpResult(dresult);
2119         break;
2120       }
2121       default:
2122         UNREACHABLE();
2123         break;
2124       }
2125       if (::v8::internal::FLAG_trace_sim) {
2126         switch (redirection->type()) {
2127         case ExternalReference::BUILTIN_COMPARE_CALL:
2128           PrintF("Returned %08x\n", static_cast<int32_t>(iresult));
2129           break;
2130         case ExternalReference::BUILTIN_FP_FP_CALL:
2131         case ExternalReference::BUILTIN_FP_CALL:
2132         case ExternalReference::BUILTIN_FP_INT_CALL:
2133           PrintF("Returned %f\n", dresult);
2134           break;
2135         default:
2136           UNREACHABLE();
2137           break;
2138         }
2139       }
2140     } else if (redirection->type() == ExternalReference::DIRECT_API_CALL) {
2141       if (::v8::internal::FLAG_trace_sim) {
2142         PrintF("Call to host function at %p args %08" PRIx64 " \n",
2143                reinterpret_cast<void*>(external), arg0);
2144       }
2145       SimulatorRuntimeDirectApiCall target =
2146           reinterpret_cast<SimulatorRuntimeDirectApiCall>(external);
2147       target(arg0);
2148     } else if (
2149         redirection->type() == ExternalReference::PROFILING_API_CALL) {
2150       if (::v8::internal::FLAG_trace_sim) {
2151         PrintF("Call to host function at %p args %08" PRIx64 "  %08" PRIx64
2152                " \n",
2153                reinterpret_cast<void*>(external), arg0, arg1);
2154       }
2155       SimulatorRuntimeProfilingApiCall target =
2156           reinterpret_cast<SimulatorRuntimeProfilingApiCall>(external);
2157       target(arg0, Redirection::ReverseRedirection(arg1));
2158     } else if (
2159         redirection->type() == ExternalReference::DIRECT_GETTER_CALL) {
2160       if (::v8::internal::FLAG_trace_sim) {
2161         PrintF("Call to host function at %p args %08" PRIx64 "  %08" PRIx64
2162                " \n",
2163                reinterpret_cast<void*>(external), arg0, arg1);
2164       }
2165       SimulatorRuntimeDirectGetterCall target =
2166           reinterpret_cast<SimulatorRuntimeDirectGetterCall>(external);
2167       target(arg0, arg1);
2168     } else if (
2169         redirection->type() == ExternalReference::PROFILING_GETTER_CALL) {
2170       if (::v8::internal::FLAG_trace_sim) {
2171         PrintF("Call to host function at %p args %08" PRIx64 "  %08" PRIx64
2172                "  %08" PRIx64 " \n",
2173                reinterpret_cast<void*>(external), arg0, arg1, arg2);
2174       }
2175       SimulatorRuntimeProfilingGetterCall target =
2176           reinterpret_cast<SimulatorRuntimeProfilingGetterCall>(external);
2177       target(arg0, arg1, Redirection::ReverseRedirection(arg2));
2178     } else if (redirection->type() == ExternalReference::BUILTIN_CALL_TRIPLE) {
2179       // builtin call returning ObjectTriple.
2180       SimulatorRuntimeTripleCall target =
2181           reinterpret_cast<SimulatorRuntimeTripleCall>(external);
2182       if (::v8::internal::FLAG_trace_sim) {
2183         PrintF(
2184             "Call to host triple returning runtime function %p "
2185             "args %016" PRIx64 ", %016" PRIx64 ", %016" PRIx64 ", %016" PRIx64
2186             ", %016" PRIx64 "\n",
2187             static_cast<void*>(FUNCTION_ADDR(target)), arg1, arg2, arg3, arg4,
2188             arg5);
2189       }
2190       // arg0 is a hidden argument pointing to the return location, so don't
2191       // pass it to the target function.
2192       ObjectTriple result = target(arg1, arg2, arg3, arg4, arg5);
2193       if (::v8::internal::FLAG_trace_sim) {
2194         PrintF("Returned { %p, %p, %p }\n", static_cast<void*>(result.x),
2195                static_cast<void*>(result.y), static_cast<void*>(result.z));
2196       }
2197       // Return is passed back in address pointed to by hidden first argument.
2198       ObjectTriple* sim_result = reinterpret_cast<ObjectTriple*>(arg0);
2199       *sim_result = result;
2200       set_register(v0, arg0);
2201     } else {
2202       DCHECK(redirection->type() == ExternalReference::BUILTIN_CALL ||
2203              redirection->type() == ExternalReference::BUILTIN_CALL_PAIR);
2204       SimulatorRuntimeCall target =
2205                   reinterpret_cast<SimulatorRuntimeCall>(external);
2206       if (::v8::internal::FLAG_trace_sim) {
2207         PrintF(
2208             "Call to host function at %p "
2209             "args %08" PRIx64 " , %08" PRIx64 " , %08" PRIx64 " , %08" PRIx64
2210             " , %08" PRIx64 " , %08" PRIx64 " \n",
2211             static_cast<void*>(FUNCTION_ADDR(target)), arg0, arg1, arg2, arg3,
2212             arg4, arg5);
2213       }
2214       // int64_t result = target(arg0, arg1, arg2, arg3, arg4, arg5);
2215       // set_register(v0, static_cast<int32_t>(result));
2216       // set_register(v1, static_cast<int32_t>(result >> 32));
2217       ObjectPair result = target(arg0, arg1, arg2, arg3, arg4, arg5);
2218       set_register(v0, (int64_t)(result.x));
2219       set_register(v1, (int64_t)(result.y));
2220     }
2221      if (::v8::internal::FLAG_trace_sim) {
2222        PrintF("Returned %08" PRIx64 "  : %08" PRIx64 " \n", get_register(v1),
2223               get_register(v0));
2224     }
2225     set_register(ra, saved_ra);
2226     set_pc(get_register(ra));
2227 
2228   } else if (func == BREAK && code <= kMaxStopCode) {
2229     if (IsWatchpoint(code)) {
2230       PrintWatchpoint(code);
2231     } else {
2232       IncreaseStopCounter(code);
2233       HandleStop(code, instr);
2234     }
2235   } else {
2236     // All remaining break_ codes, and all traps are handled here.
2237     MipsDebugger dbg(this);
2238     dbg.Debug();
2239   }
2240 }
2241 
2242 
2243 // Stop helper functions.
IsWatchpoint(uint64_t code)2244 bool Simulator::IsWatchpoint(uint64_t code) {
2245   return (code <= kMaxWatchpointCode);
2246 }
2247 
2248 
PrintWatchpoint(uint64_t code)2249 void Simulator::PrintWatchpoint(uint64_t code) {
2250   MipsDebugger dbg(this);
2251   ++break_count_;
2252   PrintF("\n---- break %" PRId64 "  marker: %3d  (instr count: %8" PRId64
2253          " ) ----------"
2254          "----------------------------------",
2255          code, break_count_, icount_);
2256   dbg.PrintAllRegs();  // Print registers and continue running.
2257 }
2258 
2259 
HandleStop(uint64_t code,Instruction * instr)2260 void Simulator::HandleStop(uint64_t code, Instruction* instr) {
2261   // Stop if it is enabled, otherwise go on jumping over the stop
2262   // and the message address.
2263   if (IsEnabledStop(code)) {
2264     MipsDebugger dbg(this);
2265     dbg.Stop(instr);
2266   } else {
2267     set_pc(get_pc() + 2 * Instruction::kInstrSize);
2268   }
2269 }
2270 
2271 
IsStopInstruction(Instruction * instr)2272 bool Simulator::IsStopInstruction(Instruction* instr) {
2273   int32_t func = instr->FunctionFieldRaw();
2274   uint32_t code = static_cast<uint32_t>(instr->Bits(25, 6));
2275   return (func == BREAK) && code > kMaxWatchpointCode && code <= kMaxStopCode;
2276 }
2277 
2278 
IsEnabledStop(uint64_t code)2279 bool Simulator::IsEnabledStop(uint64_t code) {
2280   DCHECK(code <= kMaxStopCode);
2281   DCHECK(code > kMaxWatchpointCode);
2282   return !(watched_stops_[code].count & kStopDisabledBit);
2283 }
2284 
2285 
EnableStop(uint64_t code)2286 void Simulator::EnableStop(uint64_t code) {
2287   if (!IsEnabledStop(code)) {
2288     watched_stops_[code].count &= ~kStopDisabledBit;
2289   }
2290 }
2291 
2292 
DisableStop(uint64_t code)2293 void Simulator::DisableStop(uint64_t code) {
2294   if (IsEnabledStop(code)) {
2295     watched_stops_[code].count |= kStopDisabledBit;
2296   }
2297 }
2298 
2299 
IncreaseStopCounter(uint64_t code)2300 void Simulator::IncreaseStopCounter(uint64_t code) {
2301   DCHECK(code <= kMaxStopCode);
2302   if ((watched_stops_[code].count & ~(1 << 31)) == 0x7fffffff) {
2303     PrintF("Stop counter for code %" PRId64
2304            "  has overflowed.\n"
2305            "Enabling this code and reseting the counter to 0.\n",
2306            code);
2307     watched_stops_[code].count = 0;
2308     EnableStop(code);
2309   } else {
2310     watched_stops_[code].count++;
2311   }
2312 }
2313 
2314 
2315 // Print a stop status.
PrintStopInfo(uint64_t code)2316 void Simulator::PrintStopInfo(uint64_t code) {
2317   if (code <= kMaxWatchpointCode) {
2318     PrintF("That is a watchpoint, not a stop.\n");
2319     return;
2320   } else if (code > kMaxStopCode) {
2321     PrintF("Code too large, only %u stops can be used\n", kMaxStopCode + 1);
2322     return;
2323   }
2324   const char* state = IsEnabledStop(code) ? "Enabled" : "Disabled";
2325   int32_t count = watched_stops_[code].count & ~kStopDisabledBit;
2326   // Don't print the state of unused breakpoints.
2327   if (count != 0) {
2328     if (watched_stops_[code].desc) {
2329       PrintF("stop %" PRId64 "  - 0x%" PRIx64 " : \t%s, \tcounter = %i, \t%s\n",
2330              code, code, state, count, watched_stops_[code].desc);
2331     } else {
2332       PrintF("stop %" PRId64 "  - 0x%" PRIx64 " : \t%s, \tcounter = %i\n", code,
2333              code, state, count);
2334     }
2335   }
2336 }
2337 
2338 
SignalException(Exception e)2339 void Simulator::SignalException(Exception e) {
2340   V8_Fatal(__FILE__, __LINE__, "Error: Exception %i raised.",
2341            static_cast<int>(e));
2342 }
2343 
2344 // Min/Max template functions for Double and Single arguments.
2345 
2346 template <typename T>
2347 static T FPAbs(T a);
2348 
2349 template <>
FPAbs(double a)2350 double FPAbs<double>(double a) {
2351   return fabs(a);
2352 }
2353 
2354 template <>
FPAbs(float a)2355 float FPAbs<float>(float a) {
2356   return fabsf(a);
2357 }
2358 
2359 template <typename T>
FPUProcessNaNsAndZeros(T a,T b,MaxMinKind kind,T & result)2360 static bool FPUProcessNaNsAndZeros(T a, T b, MaxMinKind kind, T& result) {
2361   if (std::isnan(a) && std::isnan(b)) {
2362     result = a;
2363   } else if (std::isnan(a)) {
2364     result = b;
2365   } else if (std::isnan(b)) {
2366     result = a;
2367   } else if (b == a) {
2368     // Handle -0.0 == 0.0 case.
2369     // std::signbit() returns int 0 or 1 so substracting MaxMinKind::kMax
2370     // negates the result.
2371     result = std::signbit(b) - static_cast<int>(kind) ? b : a;
2372   } else {
2373     return false;
2374   }
2375   return true;
2376 }
2377 
2378 template <typename T>
FPUMin(T a,T b)2379 static T FPUMin(T a, T b) {
2380   T result;
2381   if (FPUProcessNaNsAndZeros(a, b, MaxMinKind::kMin, result)) {
2382     return result;
2383   } else {
2384     return b < a ? b : a;
2385   }
2386 }
2387 
2388 template <typename T>
FPUMax(T a,T b)2389 static T FPUMax(T a, T b) {
2390   T result;
2391   if (FPUProcessNaNsAndZeros(a, b, MaxMinKind::kMax, result)) {
2392     return result;
2393   } else {
2394     return b > a ? b : a;
2395   }
2396 }
2397 
2398 template <typename T>
FPUMinA(T a,T b)2399 static T FPUMinA(T a, T b) {
2400   T result;
2401   if (!FPUProcessNaNsAndZeros(a, b, MaxMinKind::kMin, result)) {
2402     if (FPAbs(a) < FPAbs(b)) {
2403       result = a;
2404     } else if (FPAbs(b) < FPAbs(a)) {
2405       result = b;
2406     } else {
2407       result = a < b ? a : b;
2408     }
2409   }
2410   return result;
2411 }
2412 
2413 template <typename T>
FPUMaxA(T a,T b)2414 static T FPUMaxA(T a, T b) {
2415   T result;
2416   if (!FPUProcessNaNsAndZeros(a, b, MaxMinKind::kMin, result)) {
2417     if (FPAbs(a) > FPAbs(b)) {
2418       result = a;
2419     } else if (FPAbs(b) > FPAbs(a)) {
2420       result = b;
2421     } else {
2422       result = a > b ? a : b;
2423     }
2424   }
2425   return result;
2426 }
2427 
2428 // Handle execution based on instruction types.
2429 
DecodeTypeRegisterSRsType()2430 void Simulator::DecodeTypeRegisterSRsType() {
2431   float fs, ft, fd;
2432   fs = get_fpu_register_float(fs_reg());
2433   ft = get_fpu_register_float(ft_reg());
2434   fd = get_fpu_register_float(fd_reg());
2435   int32_t ft_int = bit_cast<int32_t>(ft);
2436   int32_t fd_int = bit_cast<int32_t>(fd);
2437   uint32_t cc, fcsr_cc;
2438   cc = get_instr()->FCccValue();
2439   fcsr_cc = get_fcsr_condition_bit(cc);
2440   switch (get_instr()->FunctionFieldRaw()) {
2441     case RINT: {
2442       DCHECK(kArchVariant == kMips64r6);
2443       float result, temp_result;
2444       double temp;
2445       float upper = std::ceil(fs);
2446       float lower = std::floor(fs);
2447       switch (get_fcsr_rounding_mode()) {
2448         case kRoundToNearest:
2449           if (upper - fs < fs - lower) {
2450             result = upper;
2451           } else if (upper - fs > fs - lower) {
2452             result = lower;
2453           } else {
2454             temp_result = upper / 2;
2455             float reminder = modf(temp_result, &temp);
2456             if (reminder == 0) {
2457               result = upper;
2458             } else {
2459               result = lower;
2460             }
2461           }
2462           break;
2463         case kRoundToZero:
2464           result = (fs > 0 ? lower : upper);
2465           break;
2466         case kRoundToPlusInf:
2467           result = upper;
2468           break;
2469         case kRoundToMinusInf:
2470           result = lower;
2471           break;
2472       }
2473       set_fpu_register_float(fd_reg(), result);
2474       if (result != fs) {
2475         set_fcsr_bit(kFCSRInexactFlagBit, true);
2476       }
2477       break;
2478     }
2479     case ADD_S:
2480       set_fpu_register_float(fd_reg(), fs + ft);
2481       break;
2482     case SUB_S:
2483       set_fpu_register_float(fd_reg(), fs - ft);
2484       break;
2485     case MUL_S:
2486       set_fpu_register_float(fd_reg(), fs * ft);
2487       break;
2488     case DIV_S:
2489       set_fpu_register_float(fd_reg(), fs / ft);
2490       break;
2491     case ABS_S:
2492       set_fpu_register_float(fd_reg(), fabs(fs));
2493       break;
2494     case MOV_S:
2495       set_fpu_register_float(fd_reg(), fs);
2496       break;
2497     case NEG_S:
2498       set_fpu_register_float(fd_reg(), -fs);
2499       break;
2500     case SQRT_S:
2501       lazily_initialize_fast_sqrt(isolate_);
2502       set_fpu_register_float(fd_reg(), fast_sqrt(fs, isolate_));
2503       break;
2504     case RSQRT_S: {
2505       lazily_initialize_fast_sqrt(isolate_);
2506       float result = 1.0 / fast_sqrt(fs, isolate_);
2507       set_fpu_register_float(fd_reg(), result);
2508       break;
2509     }
2510     case RECIP_S: {
2511       float result = 1.0 / fs;
2512       set_fpu_register_float(fd_reg(), result);
2513       break;
2514     }
2515     case C_F_D:
2516       set_fcsr_bit(fcsr_cc, false);
2517       break;
2518     case C_UN_D:
2519       set_fcsr_bit(fcsr_cc, std::isnan(fs) || std::isnan(ft));
2520       break;
2521     case C_EQ_D:
2522       set_fcsr_bit(fcsr_cc, (fs == ft));
2523       break;
2524     case C_UEQ_D:
2525       set_fcsr_bit(fcsr_cc, (fs == ft) || (std::isnan(fs) || std::isnan(ft)));
2526       break;
2527     case C_OLT_D:
2528       set_fcsr_bit(fcsr_cc, (fs < ft));
2529       break;
2530     case C_ULT_D:
2531       set_fcsr_bit(fcsr_cc, (fs < ft) || (std::isnan(fs) || std::isnan(ft)));
2532       break;
2533     case C_OLE_D:
2534       set_fcsr_bit(fcsr_cc, (fs <= ft));
2535       break;
2536     case C_ULE_D:
2537       set_fcsr_bit(fcsr_cc, (fs <= ft) || (std::isnan(fs) || std::isnan(ft)));
2538       break;
2539     case CVT_D_S:
2540       set_fpu_register_double(fd_reg(), static_cast<double>(fs));
2541       break;
2542     case CLASS_S: {  // Mips64r6 instruction
2543       // Convert float input to uint32_t for easier bit manipulation
2544       uint32_t classed = bit_cast<uint32_t>(fs);
2545 
2546       // Extracting sign, exponent and mantissa from the input float
2547       uint32_t sign = (classed >> 31) & 1;
2548       uint32_t exponent = (classed >> 23) & 0x000000ff;
2549       uint32_t mantissa = classed & 0x007fffff;
2550       uint32_t result;
2551       float fResult;
2552 
2553       // Setting flags if input float is negative infinity,
2554       // positive infinity, negative zero or positive zero
2555       bool negInf = (classed == 0xFF800000);
2556       bool posInf = (classed == 0x7F800000);
2557       bool negZero = (classed == 0x80000000);
2558       bool posZero = (classed == 0x00000000);
2559 
2560       bool signalingNan;
2561       bool quietNan;
2562       bool negSubnorm;
2563       bool posSubnorm;
2564       bool negNorm;
2565       bool posNorm;
2566 
2567       // Setting flags if float is NaN
2568       signalingNan = false;
2569       quietNan = false;
2570       if (!negInf && !posInf && (exponent == 0xff)) {
2571         quietNan = ((mantissa & 0x00200000) == 0) &&
2572                    ((mantissa & (0x00200000 - 1)) == 0);
2573         signalingNan = !quietNan;
2574       }
2575 
2576       // Setting flags if float is subnormal number
2577       posSubnorm = false;
2578       negSubnorm = false;
2579       if ((exponent == 0) && (mantissa != 0)) {
2580         DCHECK(sign == 0 || sign == 1);
2581         posSubnorm = (sign == 0);
2582         negSubnorm = (sign == 1);
2583       }
2584 
2585       // Setting flags if float is normal number
2586       posNorm = false;
2587       negNorm = false;
2588       if (!posSubnorm && !negSubnorm && !posInf && !negInf && !signalingNan &&
2589           !quietNan && !negZero && !posZero) {
2590         DCHECK(sign == 0 || sign == 1);
2591         posNorm = (sign == 0);
2592         negNorm = (sign == 1);
2593       }
2594 
2595       // Calculating result according to description of CLASS.S instruction
2596       result = (posZero << 9) | (posSubnorm << 8) | (posNorm << 7) |
2597                (posInf << 6) | (negZero << 5) | (negSubnorm << 4) |
2598                (negNorm << 3) | (negInf << 2) | (quietNan << 1) | signalingNan;
2599 
2600       DCHECK(result != 0);
2601 
2602       fResult = bit_cast<float>(result);
2603       set_fpu_register_float(fd_reg(), fResult);
2604 
2605       break;
2606     }
2607     case CVT_L_S: {
2608       float rounded;
2609       int64_t result;
2610       round64_according_to_fcsr(fs, rounded, result, fs);
2611       set_fpu_register(fd_reg(), result);
2612       if (set_fcsr_round64_error(fs, rounded)) {
2613         set_fpu_register_invalid_result64(fs, rounded);
2614       }
2615       break;
2616     }
2617     case CVT_W_S: {
2618       float rounded;
2619       int32_t result;
2620       round_according_to_fcsr(fs, rounded, result, fs);
2621       set_fpu_register_word(fd_reg(), result);
2622       if (set_fcsr_round_error(fs, rounded)) {
2623         set_fpu_register_word_invalid_result(fs, rounded);
2624       }
2625       break;
2626     }
2627     case TRUNC_W_S: {  // Truncate single to word (round towards 0).
2628       float rounded = trunc(fs);
2629       int32_t result = static_cast<int32_t>(rounded);
2630       set_fpu_register_word(fd_reg(), result);
2631       if (set_fcsr_round_error(fs, rounded)) {
2632         set_fpu_register_word_invalid_result(fs, rounded);
2633       }
2634     } break;
2635     case TRUNC_L_S: {  // Mips64r2 instruction.
2636       float rounded = trunc(fs);
2637       int64_t result = static_cast<int64_t>(rounded);
2638       set_fpu_register(fd_reg(), result);
2639       if (set_fcsr_round64_error(fs, rounded)) {
2640         set_fpu_register_invalid_result64(fs, rounded);
2641       }
2642       break;
2643     }
2644     case ROUND_W_S: {
2645       float rounded = std::floor(fs + 0.5);
2646       int32_t result = static_cast<int32_t>(rounded);
2647       if ((result & 1) != 0 && result - fs == 0.5) {
2648         // If the number is halfway between two integers,
2649         // round to the even one.
2650         result--;
2651       }
2652       set_fpu_register_word(fd_reg(), result);
2653       if (set_fcsr_round_error(fs, rounded)) {
2654         set_fpu_register_word_invalid_result(fs, rounded);
2655       }
2656       break;
2657     }
2658     case ROUND_L_S: {  // Mips64r2 instruction.
2659       float rounded = std::floor(fs + 0.5);
2660       int64_t result = static_cast<int64_t>(rounded);
2661       if ((result & 1) != 0 && result - fs == 0.5) {
2662         // If the number is halfway between two integers,
2663         // round to the even one.
2664         result--;
2665       }
2666       int64_t i64 = static_cast<int64_t>(result);
2667       set_fpu_register(fd_reg(), i64);
2668       if (set_fcsr_round64_error(fs, rounded)) {
2669         set_fpu_register_invalid_result64(fs, rounded);
2670       }
2671       break;
2672     }
2673     case FLOOR_L_S: {  // Mips64r2 instruction.
2674       float rounded = floor(fs);
2675       int64_t result = static_cast<int64_t>(rounded);
2676       set_fpu_register(fd_reg(), result);
2677       if (set_fcsr_round64_error(fs, rounded)) {
2678         set_fpu_register_invalid_result64(fs, rounded);
2679       }
2680       break;
2681     }
2682     case FLOOR_W_S:  // Round double to word towards negative infinity.
2683     {
2684       float rounded = std::floor(fs);
2685       int32_t result = static_cast<int32_t>(rounded);
2686       set_fpu_register_word(fd_reg(), result);
2687       if (set_fcsr_round_error(fs, rounded)) {
2688         set_fpu_register_word_invalid_result(fs, rounded);
2689       }
2690     } break;
2691     case CEIL_W_S:  // Round double to word towards positive infinity.
2692     {
2693       float rounded = std::ceil(fs);
2694       int32_t result = static_cast<int32_t>(rounded);
2695       set_fpu_register_word(fd_reg(), result);
2696       if (set_fcsr_round_error(fs, rounded)) {
2697         set_fpu_register_invalid_result(fs, rounded);
2698       }
2699     } break;
2700     case CEIL_L_S: {  // Mips64r2 instruction.
2701       float rounded = ceil(fs);
2702       int64_t result = static_cast<int64_t>(rounded);
2703       set_fpu_register(fd_reg(), result);
2704       if (set_fcsr_round64_error(fs, rounded)) {
2705         set_fpu_register_invalid_result64(fs, rounded);
2706       }
2707       break;
2708     }
2709     case MINA:
2710       DCHECK(kArchVariant == kMips64r6);
2711       set_fpu_register_float(fd_reg(), FPUMinA(ft, fs));
2712       break;
2713     case MAXA:
2714       DCHECK(kArchVariant == kMips64r6);
2715       set_fpu_register_float(fd_reg(), FPUMaxA(ft, fs));
2716       break;
2717     case MIN:
2718       DCHECK(kArchVariant == kMips64r6);
2719       set_fpu_register_float(fd_reg(), FPUMin(ft, fs));
2720       break;
2721     case MAX:
2722       DCHECK(kArchVariant == kMips64r6);
2723       set_fpu_register_float(fd_reg(), FPUMax(ft, fs));
2724       break;
2725     case SEL:
2726       DCHECK(kArchVariant == kMips64r6);
2727       set_fpu_register_float(fd_reg(), (fd_int & 0x1) == 0 ? fs : ft);
2728       break;
2729     case SELEQZ_C:
2730       DCHECK(kArchVariant == kMips64r6);
2731       set_fpu_register_float(fd_reg(), (ft_int & 0x1) == 0
2732                                            ? get_fpu_register_float(fs_reg())
2733                                            : 0.0);
2734       break;
2735     case SELNEZ_C:
2736       DCHECK(kArchVariant == kMips64r6);
2737       set_fpu_register_float(fd_reg(), (ft_int & 0x1) != 0
2738                                            ? get_fpu_register_float(fs_reg())
2739                                            : 0.0);
2740       break;
2741     case MOVZ_C: {
2742       DCHECK(kArchVariant == kMips64r2);
2743       if (rt() == 0) {
2744         set_fpu_register_float(fd_reg(), fs);
2745       }
2746       break;
2747     }
2748     case MOVN_C: {
2749       DCHECK(kArchVariant == kMips64r2);
2750       if (rt() != 0) {
2751         set_fpu_register_float(fd_reg(), fs);
2752       }
2753       break;
2754     }
2755     case MOVF: {
2756       // Same function field for MOVT.D and MOVF.D
2757       uint32_t ft_cc = (ft_reg() >> 2) & 0x7;
2758       ft_cc = get_fcsr_condition_bit(ft_cc);
2759 
2760       if (get_instr()->Bit(16)) {  // Read Tf bit.
2761         // MOVT.D
2762         if (test_fcsr_bit(ft_cc)) set_fpu_register_float(fd_reg(), fs);
2763       } else {
2764         // MOVF.D
2765         if (!test_fcsr_bit(ft_cc)) set_fpu_register_float(fd_reg(), fs);
2766       }
2767       break;
2768     }
2769     default:
2770       // TRUNC_W_S ROUND_W_S ROUND_L_S FLOOR_W_S FLOOR_L_S
2771       // CEIL_W_S CEIL_L_S CVT_PS_S are unimplemented.
2772       UNREACHABLE();
2773   }
2774 }
2775 
2776 
DecodeTypeRegisterDRsType()2777 void Simulator::DecodeTypeRegisterDRsType() {
2778   double ft, fs, fd;
2779   uint32_t cc, fcsr_cc;
2780   fs = get_fpu_register_double(fs_reg());
2781   ft = (get_instr()->FunctionFieldRaw() != MOVF)
2782            ? get_fpu_register_double(ft_reg())
2783            : 0.0;
2784   fd = get_fpu_register_double(fd_reg());
2785   cc = get_instr()->FCccValue();
2786   fcsr_cc = get_fcsr_condition_bit(cc);
2787   int64_t ft_int = bit_cast<int64_t>(ft);
2788   int64_t fd_int = bit_cast<int64_t>(fd);
2789   switch (get_instr()->FunctionFieldRaw()) {
2790     case RINT: {
2791       DCHECK(kArchVariant == kMips64r6);
2792       double result, temp, temp_result;
2793       double upper = std::ceil(fs);
2794       double lower = std::floor(fs);
2795       switch (get_fcsr_rounding_mode()) {
2796         case kRoundToNearest:
2797           if (upper - fs < fs - lower) {
2798             result = upper;
2799           } else if (upper - fs > fs - lower) {
2800             result = lower;
2801           } else {
2802             temp_result = upper / 2;
2803             double reminder = modf(temp_result, &temp);
2804             if (reminder == 0) {
2805               result = upper;
2806             } else {
2807               result = lower;
2808             }
2809           }
2810           break;
2811         case kRoundToZero:
2812           result = (fs > 0 ? lower : upper);
2813           break;
2814         case kRoundToPlusInf:
2815           result = upper;
2816           break;
2817         case kRoundToMinusInf:
2818           result = lower;
2819           break;
2820       }
2821       set_fpu_register_double(fd_reg(), result);
2822       if (result != fs) {
2823         set_fcsr_bit(kFCSRInexactFlagBit, true);
2824       }
2825       break;
2826     }
2827     case SEL:
2828       DCHECK(kArchVariant == kMips64r6);
2829       set_fpu_register_double(fd_reg(), (fd_int & 0x1) == 0 ? fs : ft);
2830       break;
2831     case SELEQZ_C:
2832       DCHECK(kArchVariant == kMips64r6);
2833       set_fpu_register_double(fd_reg(), (ft_int & 0x1) == 0 ? fs : 0.0);
2834       break;
2835     case SELNEZ_C:
2836       DCHECK(kArchVariant == kMips64r6);
2837       set_fpu_register_double(fd_reg(), (ft_int & 0x1) != 0 ? fs : 0.0);
2838       break;
2839     case MOVZ_C: {
2840       DCHECK(kArchVariant == kMips64r2);
2841       if (rt() == 0) {
2842         set_fpu_register_double(fd_reg(), fs);
2843       }
2844       break;
2845     }
2846     case MOVN_C: {
2847       DCHECK(kArchVariant == kMips64r2);
2848       if (rt() != 0) {
2849         set_fpu_register_double(fd_reg(), fs);
2850       }
2851       break;
2852     }
2853     case MOVF: {
2854       // Same function field for MOVT.D and MOVF.D
2855       uint32_t ft_cc = (ft_reg() >> 2) & 0x7;
2856       ft_cc = get_fcsr_condition_bit(ft_cc);
2857       if (get_instr()->Bit(16)) {  // Read Tf bit.
2858         // MOVT.D
2859         if (test_fcsr_bit(ft_cc)) set_fpu_register_double(fd_reg(), fs);
2860       } else {
2861         // MOVF.D
2862         if (!test_fcsr_bit(ft_cc)) set_fpu_register_double(fd_reg(), fs);
2863       }
2864       break;
2865     }
2866     case MINA:
2867       DCHECK(kArchVariant == kMips64r6);
2868       set_fpu_register_double(fd_reg(), FPUMinA(ft, fs));
2869       break;
2870     case MAXA:
2871       DCHECK(kArchVariant == kMips64r6);
2872       set_fpu_register_double(fd_reg(), FPUMaxA(ft, fs));
2873       break;
2874     case MIN:
2875       DCHECK(kArchVariant == kMips64r6);
2876       set_fpu_register_double(fd_reg(), FPUMin(ft, fs));
2877       break;
2878     case MAX:
2879       DCHECK(kArchVariant == kMips64r6);
2880       set_fpu_register_double(fd_reg(), FPUMax(ft, fs));
2881       break;
2882     case ADD_D:
2883       set_fpu_register_double(fd_reg(), fs + ft);
2884       break;
2885     case SUB_D:
2886       set_fpu_register_double(fd_reg(), fs - ft);
2887       break;
2888     case MUL_D:
2889       set_fpu_register_double(fd_reg(), fs * ft);
2890       break;
2891     case DIV_D:
2892       set_fpu_register_double(fd_reg(), fs / ft);
2893       break;
2894     case ABS_D:
2895       set_fpu_register_double(fd_reg(), fabs(fs));
2896       break;
2897     case MOV_D:
2898       set_fpu_register_double(fd_reg(), fs);
2899       break;
2900     case NEG_D:
2901       set_fpu_register_double(fd_reg(), -fs);
2902       break;
2903     case SQRT_D:
2904       lazily_initialize_fast_sqrt(isolate_);
2905       set_fpu_register_double(fd_reg(), fast_sqrt(fs, isolate_));
2906       break;
2907     case RSQRT_D: {
2908       lazily_initialize_fast_sqrt(isolate_);
2909       double result = 1.0 / fast_sqrt(fs, isolate_);
2910       set_fpu_register_double(fd_reg(), result);
2911       break;
2912     }
2913     case RECIP_D: {
2914       double result = 1.0 / fs;
2915       set_fpu_register_double(fd_reg(), result);
2916       break;
2917     }
2918     case C_UN_D:
2919       set_fcsr_bit(fcsr_cc, std::isnan(fs) || std::isnan(ft));
2920       break;
2921     case C_EQ_D:
2922       set_fcsr_bit(fcsr_cc, (fs == ft));
2923       break;
2924     case C_UEQ_D:
2925       set_fcsr_bit(fcsr_cc, (fs == ft) || (std::isnan(fs) || std::isnan(ft)));
2926       break;
2927     case C_OLT_D:
2928       set_fcsr_bit(fcsr_cc, (fs < ft));
2929       break;
2930     case C_ULT_D:
2931       set_fcsr_bit(fcsr_cc, (fs < ft) || (std::isnan(fs) || std::isnan(ft)));
2932       break;
2933     case C_OLE_D:
2934       set_fcsr_bit(fcsr_cc, (fs <= ft));
2935       break;
2936     case C_ULE_D:
2937       set_fcsr_bit(fcsr_cc, (fs <= ft) || (std::isnan(fs) || std::isnan(ft)));
2938       break;
2939     case CVT_W_D: {  // Convert double to word.
2940       double rounded;
2941       int32_t result;
2942       round_according_to_fcsr(fs, rounded, result, fs);
2943       set_fpu_register_word(fd_reg(), result);
2944       if (set_fcsr_round_error(fs, rounded)) {
2945         set_fpu_register_word_invalid_result(fs, rounded);
2946       }
2947       break;
2948     }
2949     case ROUND_W_D:  // Round double to word (round half to even).
2950     {
2951       double rounded = std::floor(fs + 0.5);
2952       int32_t result = static_cast<int32_t>(rounded);
2953       if ((result & 1) != 0 && result - fs == 0.5) {
2954         // If the number is halfway between two integers,
2955         // round to the even one.
2956         result--;
2957       }
2958       set_fpu_register_word(fd_reg(), result);
2959       if (set_fcsr_round_error(fs, rounded)) {
2960         set_fpu_register_invalid_result(fs, rounded);
2961       }
2962     } break;
2963     case TRUNC_W_D:  // Truncate double to word (round towards 0).
2964     {
2965       double rounded = trunc(fs);
2966       int32_t result = static_cast<int32_t>(rounded);
2967       set_fpu_register_word(fd_reg(), result);
2968       if (set_fcsr_round_error(fs, rounded)) {
2969         set_fpu_register_invalid_result(fs, rounded);
2970       }
2971     } break;
2972     case FLOOR_W_D:  // Round double to word towards negative infinity.
2973     {
2974       double rounded = std::floor(fs);
2975       int32_t result = static_cast<int32_t>(rounded);
2976       set_fpu_register_word(fd_reg(), result);
2977       if (set_fcsr_round_error(fs, rounded)) {
2978         set_fpu_register_invalid_result(fs, rounded);
2979       }
2980     } break;
2981     case CEIL_W_D:  // Round double to word towards positive infinity.
2982     {
2983       double rounded = std::ceil(fs);
2984       int32_t result = static_cast<int32_t>(rounded);
2985       set_fpu_register_word(fd_reg(), result);
2986       if (set_fcsr_round_error(fs, rounded)) {
2987         set_fpu_register_invalid_result(fs, rounded);
2988       }
2989     } break;
2990     case CVT_S_D:  // Convert double to float (single).
2991       set_fpu_register_float(fd_reg(), static_cast<float>(fs));
2992       break;
2993     case CVT_L_D: {  // Mips64r2: Truncate double to 64-bit long-word.
2994       double rounded;
2995       int64_t result;
2996       round64_according_to_fcsr(fs, rounded, result, fs);
2997       set_fpu_register(fd_reg(), result);
2998       if (set_fcsr_round64_error(fs, rounded)) {
2999         set_fpu_register_invalid_result64(fs, rounded);
3000       }
3001       break;
3002     }
3003     case ROUND_L_D: {  // Mips64r2 instruction.
3004       double rounded = std::floor(fs + 0.5);
3005       int64_t result = static_cast<int64_t>(rounded);
3006       if ((result & 1) != 0 && result - fs == 0.5) {
3007         // If the number is halfway between two integers,
3008         // round to the even one.
3009         result--;
3010       }
3011       int64_t i64 = static_cast<int64_t>(result);
3012       set_fpu_register(fd_reg(), i64);
3013       if (set_fcsr_round64_error(fs, rounded)) {
3014         set_fpu_register_invalid_result64(fs, rounded);
3015       }
3016       break;
3017     }
3018     case TRUNC_L_D: {  // Mips64r2 instruction.
3019       double rounded = trunc(fs);
3020       int64_t result = static_cast<int64_t>(rounded);
3021       set_fpu_register(fd_reg(), result);
3022       if (set_fcsr_round64_error(fs, rounded)) {
3023         set_fpu_register_invalid_result64(fs, rounded);
3024       }
3025       break;
3026     }
3027     case FLOOR_L_D: {  // Mips64r2 instruction.
3028       double rounded = floor(fs);
3029       int64_t result = static_cast<int64_t>(rounded);
3030       set_fpu_register(fd_reg(), result);
3031       if (set_fcsr_round64_error(fs, rounded)) {
3032         set_fpu_register_invalid_result64(fs, rounded);
3033       }
3034       break;
3035     }
3036     case CEIL_L_D: {  // Mips64r2 instruction.
3037       double rounded = ceil(fs);
3038       int64_t result = static_cast<int64_t>(rounded);
3039       set_fpu_register(fd_reg(), result);
3040       if (set_fcsr_round64_error(fs, rounded)) {
3041         set_fpu_register_invalid_result64(fs, rounded);
3042       }
3043       break;
3044     }
3045     case CLASS_D: {  // Mips64r6 instruction
3046       // Convert double input to uint64_t for easier bit manipulation
3047       uint64_t classed = bit_cast<uint64_t>(fs);
3048 
3049       // Extracting sign, exponent and mantissa from the input double
3050       uint32_t sign = (classed >> 63) & 1;
3051       uint32_t exponent = (classed >> 52) & 0x00000000000007ff;
3052       uint64_t mantissa = classed & 0x000fffffffffffff;
3053       uint64_t result;
3054       double dResult;
3055 
3056       // Setting flags if input double is negative infinity,
3057       // positive infinity, negative zero or positive zero
3058       bool negInf = (classed == 0xFFF0000000000000);
3059       bool posInf = (classed == 0x7FF0000000000000);
3060       bool negZero = (classed == 0x8000000000000000);
3061       bool posZero = (classed == 0x0000000000000000);
3062 
3063       bool signalingNan;
3064       bool quietNan;
3065       bool negSubnorm;
3066       bool posSubnorm;
3067       bool negNorm;
3068       bool posNorm;
3069 
3070       // Setting flags if double is NaN
3071       signalingNan = false;
3072       quietNan = false;
3073       if (!negInf && !posInf && exponent == 0x7ff) {
3074         quietNan = ((mantissa & 0x0008000000000000) != 0) &&
3075                    ((mantissa & (0x0008000000000000 - 1)) == 0);
3076         signalingNan = !quietNan;
3077       }
3078 
3079       // Setting flags if double is subnormal number
3080       posSubnorm = false;
3081       negSubnorm = false;
3082       if ((exponent == 0) && (mantissa != 0)) {
3083         DCHECK(sign == 0 || sign == 1);
3084         posSubnorm = (sign == 0);
3085         negSubnorm = (sign == 1);
3086       }
3087 
3088       // Setting flags if double is normal number
3089       posNorm = false;
3090       negNorm = false;
3091       if (!posSubnorm && !negSubnorm && !posInf && !negInf && !signalingNan &&
3092           !quietNan && !negZero && !posZero) {
3093         DCHECK(sign == 0 || sign == 1);
3094         posNorm = (sign == 0);
3095         negNorm = (sign == 1);
3096       }
3097 
3098       // Calculating result according to description of CLASS.D instruction
3099       result = (posZero << 9) | (posSubnorm << 8) | (posNorm << 7) |
3100                (posInf << 6) | (negZero << 5) | (negSubnorm << 4) |
3101                (negNorm << 3) | (negInf << 2) | (quietNan << 1) | signalingNan;
3102 
3103       DCHECK(result != 0);
3104 
3105       dResult = bit_cast<double>(result);
3106       set_fpu_register_double(fd_reg(), dResult);
3107 
3108       break;
3109     }
3110     case C_F_D: {
3111       set_fcsr_bit(fcsr_cc, false);
3112       break;
3113     }
3114     default:
3115       UNREACHABLE();
3116   }
3117 }
3118 
3119 
DecodeTypeRegisterWRsType()3120 void Simulator::DecodeTypeRegisterWRsType() {
3121   float fs = get_fpu_register_float(fs_reg());
3122   float ft = get_fpu_register_float(ft_reg());
3123   int64_t alu_out = 0x12345678;
3124   switch (get_instr()->FunctionFieldRaw()) {
3125     case CVT_S_W:  // Convert word to float (single).
3126       alu_out = get_fpu_register_signed_word(fs_reg());
3127       set_fpu_register_float(fd_reg(), static_cast<float>(alu_out));
3128       break;
3129     case CVT_D_W:  // Convert word to double.
3130       alu_out = get_fpu_register_signed_word(fs_reg());
3131       set_fpu_register_double(fd_reg(), static_cast<double>(alu_out));
3132       break;
3133     case CMP_AF:
3134       set_fpu_register_word(fd_reg(), 0);
3135       break;
3136     case CMP_UN:
3137       if (std::isnan(fs) || std::isnan(ft)) {
3138         set_fpu_register_word(fd_reg(), -1);
3139       } else {
3140         set_fpu_register_word(fd_reg(), 0);
3141       }
3142       break;
3143     case CMP_EQ:
3144       if (fs == ft) {
3145         set_fpu_register_word(fd_reg(), -1);
3146       } else {
3147         set_fpu_register_word(fd_reg(), 0);
3148       }
3149       break;
3150     case CMP_UEQ:
3151       if ((fs == ft) || (std::isnan(fs) || std::isnan(ft))) {
3152         set_fpu_register_word(fd_reg(), -1);
3153       } else {
3154         set_fpu_register_word(fd_reg(), 0);
3155       }
3156       break;
3157     case CMP_LT:
3158       if (fs < ft) {
3159         set_fpu_register_word(fd_reg(), -1);
3160       } else {
3161         set_fpu_register_word(fd_reg(), 0);
3162       }
3163       break;
3164     case CMP_ULT:
3165       if ((fs < ft) || (std::isnan(fs) || std::isnan(ft))) {
3166         set_fpu_register_word(fd_reg(), -1);
3167       } else {
3168         set_fpu_register_word(fd_reg(), 0);
3169       }
3170       break;
3171     case CMP_LE:
3172       if (fs <= ft) {
3173         set_fpu_register_word(fd_reg(), -1);
3174       } else {
3175         set_fpu_register_word(fd_reg(), 0);
3176       }
3177       break;
3178     case CMP_ULE:
3179       if ((fs <= ft) || (std::isnan(fs) || std::isnan(ft))) {
3180         set_fpu_register_word(fd_reg(), -1);
3181       } else {
3182         set_fpu_register_word(fd_reg(), 0);
3183       }
3184       break;
3185     case CMP_OR:
3186       if (!std::isnan(fs) && !std::isnan(ft)) {
3187         set_fpu_register_word(fd_reg(), -1);
3188       } else {
3189         set_fpu_register_word(fd_reg(), 0);
3190       }
3191       break;
3192     case CMP_UNE:
3193       if ((fs != ft) || (std::isnan(fs) || std::isnan(ft))) {
3194         set_fpu_register_word(fd_reg(), -1);
3195       } else {
3196         set_fpu_register_word(fd_reg(), 0);
3197       }
3198       break;
3199     case CMP_NE:
3200       if (fs != ft) {
3201         set_fpu_register_word(fd_reg(), -1);
3202       } else {
3203         set_fpu_register_word(fd_reg(), 0);
3204       }
3205       break;
3206     default:
3207       UNREACHABLE();
3208   }
3209 }
3210 
3211 
DecodeTypeRegisterLRsType()3212 void Simulator::DecodeTypeRegisterLRsType() {
3213   double fs = get_fpu_register_double(fs_reg());
3214   double ft = get_fpu_register_double(ft_reg());
3215   int64_t i64;
3216   switch (get_instr()->FunctionFieldRaw()) {
3217     case CVT_D_L:  // Mips32r2 instruction.
3218       i64 = get_fpu_register(fs_reg());
3219       set_fpu_register_double(fd_reg(), static_cast<double>(i64));
3220       break;
3221     case CVT_S_L:
3222       i64 = get_fpu_register(fs_reg());
3223       set_fpu_register_float(fd_reg(), static_cast<float>(i64));
3224       break;
3225     case CMP_AF:
3226       set_fpu_register(fd_reg(), 0);
3227       break;
3228     case CMP_UN:
3229       if (std::isnan(fs) || std::isnan(ft)) {
3230         set_fpu_register(fd_reg(), -1);
3231       } else {
3232         set_fpu_register(fd_reg(), 0);
3233       }
3234       break;
3235     case CMP_EQ:
3236       if (fs == ft) {
3237         set_fpu_register(fd_reg(), -1);
3238       } else {
3239         set_fpu_register(fd_reg(), 0);
3240       }
3241       break;
3242     case CMP_UEQ:
3243       if ((fs == ft) || (std::isnan(fs) || std::isnan(ft))) {
3244         set_fpu_register(fd_reg(), -1);
3245       } else {
3246         set_fpu_register(fd_reg(), 0);
3247       }
3248       break;
3249     case CMP_LT:
3250       if (fs < ft) {
3251         set_fpu_register(fd_reg(), -1);
3252       } else {
3253         set_fpu_register(fd_reg(), 0);
3254       }
3255       break;
3256     case CMP_ULT:
3257       if ((fs < ft) || (std::isnan(fs) || std::isnan(ft))) {
3258         set_fpu_register(fd_reg(), -1);
3259       } else {
3260         set_fpu_register(fd_reg(), 0);
3261       }
3262       break;
3263     case CMP_LE:
3264       if (fs <= ft) {
3265         set_fpu_register(fd_reg(), -1);
3266       } else {
3267         set_fpu_register(fd_reg(), 0);
3268       }
3269       break;
3270     case CMP_ULE:
3271       if ((fs <= ft) || (std::isnan(fs) || std::isnan(ft))) {
3272         set_fpu_register(fd_reg(), -1);
3273       } else {
3274         set_fpu_register(fd_reg(), 0);
3275       }
3276       break;
3277     case CMP_OR:
3278       if (!std::isnan(fs) && !std::isnan(ft)) {
3279         set_fpu_register(fd_reg(), -1);
3280       } else {
3281         set_fpu_register(fd_reg(), 0);
3282       }
3283       break;
3284     case CMP_UNE:
3285       if ((fs != ft) || (std::isnan(fs) || std::isnan(ft))) {
3286         set_fpu_register(fd_reg(), -1);
3287       } else {
3288         set_fpu_register(fd_reg(), 0);
3289       }
3290       break;
3291     case CMP_NE:
3292       if (fs != ft && (!std::isnan(fs) && !std::isnan(ft))) {
3293         set_fpu_register(fd_reg(), -1);
3294       } else {
3295         set_fpu_register(fd_reg(), 0);
3296       }
3297       break;
3298     default:
3299       UNREACHABLE();
3300   }
3301 }
3302 
3303 
DecodeTypeRegisterCOP1()3304 void Simulator::DecodeTypeRegisterCOP1() {
3305   switch (get_instr()->RsFieldRaw()) {
3306     case BC1:  // Branch on coprocessor condition.
3307     case BC1EQZ:
3308     case BC1NEZ:
3309       UNREACHABLE();
3310       break;
3311     case CFC1:
3312       // At the moment only FCSR is supported.
3313       DCHECK(fs_reg() == kFCSRRegister);
3314       set_register(rt_reg(), FCSR_);
3315       break;
3316     case MFC1:
3317       set_register(rt_reg(),
3318                    static_cast<int64_t>(get_fpu_register_word(fs_reg())));
3319       break;
3320     case DMFC1:
3321       set_register(rt_reg(), get_fpu_register(fs_reg()));
3322       break;
3323     case MFHC1:
3324       set_register(rt_reg(), get_fpu_register_hi_word(fs_reg()));
3325       break;
3326     case CTC1: {
3327       // At the moment only FCSR is supported.
3328       DCHECK(fs_reg() == kFCSRRegister);
3329       uint32_t reg = static_cast<uint32_t>(rt());
3330       if (kArchVariant == kMips64r6) {
3331         FCSR_ = reg | kFCSRNaN2008FlagMask;
3332       } else {
3333         DCHECK(kArchVariant == kMips64r2);
3334         FCSR_ = reg & ~kFCSRNaN2008FlagMask;
3335       }
3336       break;
3337     }
3338     case MTC1:
3339       // Hardware writes upper 32-bits to zero on mtc1.
3340       set_fpu_register_hi_word(fs_reg(), 0);
3341       set_fpu_register_word(fs_reg(), static_cast<int32_t>(rt()));
3342       break;
3343     case DMTC1:
3344       set_fpu_register(fs_reg(), rt());
3345       break;
3346     case MTHC1:
3347       set_fpu_register_hi_word(fs_reg(), static_cast<int32_t>(rt()));
3348       break;
3349     case S:
3350       DecodeTypeRegisterSRsType();
3351       break;
3352     case D:
3353       DecodeTypeRegisterDRsType();
3354       break;
3355     case W:
3356       DecodeTypeRegisterWRsType();
3357       break;
3358     case L:
3359       DecodeTypeRegisterLRsType();
3360       break;
3361     default:
3362       UNREACHABLE();
3363   }
3364 }
3365 
3366 
DecodeTypeRegisterCOP1X()3367 void Simulator::DecodeTypeRegisterCOP1X() {
3368   switch (get_instr()->FunctionFieldRaw()) {
3369     case MADD_D:
3370       double fr, ft, fs;
3371       fr = get_fpu_register_double(fr_reg());
3372       fs = get_fpu_register_double(fs_reg());
3373       ft = get_fpu_register_double(ft_reg());
3374       set_fpu_register_double(fd_reg(), fs * ft + fr);
3375       break;
3376     default:
3377       UNREACHABLE();
3378   }
3379 }
3380 
3381 
DecodeTypeRegisterSPECIAL()3382 void Simulator::DecodeTypeRegisterSPECIAL() {
3383   int64_t i64hilo;
3384   uint64_t u64hilo;
3385   int64_t alu_out;
3386   bool do_interrupt = false;
3387 
3388   switch (get_instr()->FunctionFieldRaw()) {
3389     case SELEQZ_S:
3390       DCHECK(kArchVariant == kMips64r6);
3391       set_register(rd_reg(), rt() == 0 ? rs() : 0);
3392       break;
3393     case SELNEZ_S:
3394       DCHECK(kArchVariant == kMips64r6);
3395       set_register(rd_reg(), rt() != 0 ? rs() : 0);
3396       break;
3397     case JR: {
3398       int64_t next_pc = rs();
3399       int64_t current_pc = get_pc();
3400       Instruction* branch_delay_instr =
3401           reinterpret_cast<Instruction*>(current_pc + Instruction::kInstrSize);
3402       BranchDelayInstructionDecode(branch_delay_instr);
3403       set_pc(next_pc);
3404       pc_modified_ = true;
3405       break;
3406     }
3407     case JALR: {
3408       int64_t next_pc = rs();
3409       int64_t current_pc = get_pc();
3410       int32_t return_addr_reg = rd_reg();
3411       Instruction* branch_delay_instr =
3412           reinterpret_cast<Instruction*>(current_pc + Instruction::kInstrSize);
3413       BranchDelayInstructionDecode(branch_delay_instr);
3414       set_register(return_addr_reg, current_pc + 2 * Instruction::kInstrSize);
3415       set_pc(next_pc);
3416       pc_modified_ = true;
3417       break;
3418     }
3419     case SLL:
3420       SetResult(rd_reg(), static_cast<int32_t>(rt()) << sa());
3421       break;
3422     case DSLL:
3423       SetResult(rd_reg(), rt() << sa());
3424       break;
3425     case DSLL32:
3426       SetResult(rd_reg(), rt() << sa() << 32);
3427       break;
3428     case SRL:
3429       if (rs_reg() == 0) {
3430         // Regular logical right shift of a word by a fixed number of
3431         // bits instruction. RS field is always equal to 0.
3432         // Sign-extend the 32-bit result.
3433         alu_out = static_cast<int32_t>(static_cast<uint32_t>(rt_u()) >> sa());
3434       } else if (rs_reg() == 1) {
3435         // Logical right-rotate of a word by a fixed number of bits. This
3436         // is special case of SRL instruction, added in MIPS32 Release 2.
3437         // RS field is equal to 00001.
3438         alu_out = static_cast<int32_t>(
3439             base::bits::RotateRight32(static_cast<const uint32_t>(rt_u()),
3440                                       static_cast<const uint32_t>(sa())));
3441       } else {
3442         UNREACHABLE();
3443       }
3444       SetResult(rd_reg(), alu_out);
3445       break;
3446     case DSRL:
3447       if (rs_reg() == 0) {
3448         // Regular logical right shift of a word by a fixed number of
3449         // bits instruction. RS field is always equal to 0.
3450         // Sign-extend the 64-bit result.
3451         alu_out = static_cast<int64_t>(rt_u() >> sa());
3452       } else if (rs_reg() == 1) {
3453         // Logical right-rotate of a word by a fixed number of bits. This
3454         // is special case of SRL instruction, added in MIPS32 Release 2.
3455         // RS field is equal to 00001.
3456         alu_out = static_cast<int64_t>(base::bits::RotateRight64(rt_u(), sa()));
3457       } else {
3458         UNREACHABLE();
3459       }
3460       SetResult(rd_reg(), alu_out);
3461       break;
3462     case DSRL32:
3463       if (rs_reg() == 0) {
3464         // Regular logical right shift of a word by a fixed number of
3465         // bits instruction. RS field is always equal to 0.
3466         // Sign-extend the 64-bit result.
3467         alu_out = static_cast<int64_t>(rt_u() >> sa() >> 32);
3468       } else if (rs_reg() == 1) {
3469         // Logical right-rotate of a word by a fixed number of bits. This
3470         // is special case of SRL instruction, added in MIPS32 Release 2.
3471         // RS field is equal to 00001.
3472         alu_out =
3473             static_cast<int64_t>(base::bits::RotateRight64(rt_u(), sa() + 32));
3474       } else {
3475         UNREACHABLE();
3476       }
3477       SetResult(rd_reg(), alu_out);
3478       break;
3479     case SRA:
3480       SetResult(rd_reg(), (int32_t)rt() >> sa());
3481       break;
3482     case DSRA:
3483       SetResult(rd_reg(), rt() >> sa());
3484       break;
3485     case DSRA32:
3486       SetResult(rd_reg(), rt() >> sa() >> 32);
3487       break;
3488     case SLLV:
3489       SetResult(rd_reg(), (int32_t)rt() << rs());
3490       break;
3491     case DSLLV:
3492       SetResult(rd_reg(), rt() << rs());
3493       break;
3494     case SRLV:
3495       if (sa() == 0) {
3496         // Regular logical right-shift of a word by a variable number of
3497         // bits instruction. SA field is always equal to 0.
3498         alu_out = static_cast<int32_t>((uint32_t)rt_u() >> rs());
3499       } else {
3500         // Logical right-rotate of a word by a variable number of bits.
3501         // This is special case od SRLV instruction, added in MIPS32
3502         // Release 2. SA field is equal to 00001.
3503         alu_out = static_cast<int32_t>(
3504             base::bits::RotateRight32(static_cast<const uint32_t>(rt_u()),
3505                                       static_cast<const uint32_t>(rs_u())));
3506       }
3507       SetResult(rd_reg(), alu_out);
3508       break;
3509     case DSRLV:
3510       if (sa() == 0) {
3511         // Regular logical right-shift of a word by a variable number of
3512         // bits instruction. SA field is always equal to 0.
3513         alu_out = static_cast<int64_t>(rt_u() >> rs());
3514       } else {
3515         // Logical right-rotate of a word by a variable number of bits.
3516         // This is special case od SRLV instruction, added in MIPS32
3517         // Release 2. SA field is equal to 00001.
3518         alu_out =
3519             static_cast<int64_t>(base::bits::RotateRight64(rt_u(), rs_u()));
3520       }
3521       SetResult(rd_reg(), alu_out);
3522       break;
3523     case SRAV:
3524       SetResult(rd_reg(), (int32_t)rt() >> rs());
3525       break;
3526     case DSRAV:
3527       SetResult(rd_reg(), rt() >> rs());
3528       break;
3529     case LSA: {
3530       DCHECK(kArchVariant == kMips64r6);
3531       int8_t sa = lsa_sa() + 1;
3532       int32_t _rt = static_cast<int32_t>(rt());
3533       int32_t _rs = static_cast<int32_t>(rs());
3534       int32_t res = _rs << sa;
3535       res += _rt;
3536       SetResult(rd_reg(), static_cast<int64_t>(res));
3537       break;
3538     }
3539     case DLSA:
3540       DCHECK(kArchVariant == kMips64r6);
3541       SetResult(rd_reg(), (rs() << (lsa_sa() + 1)) + rt());
3542       break;
3543     case MFHI:  // MFHI == CLZ on R6.
3544       if (kArchVariant != kMips64r6) {
3545         DCHECK(sa() == 0);
3546         alu_out = get_register(HI);
3547       } else {
3548         // MIPS spec: If no bits were set in GPR rs(), the result written to
3549         // GPR rd() is 32.
3550         DCHECK(sa() == 1);
3551         alu_out = base::bits::CountLeadingZeros32(static_cast<int32_t>(rs_u()));
3552       }
3553       SetResult(rd_reg(), alu_out);
3554       break;
3555     case MFLO:  // MFLO == DCLZ on R6.
3556       if (kArchVariant != kMips64r6) {
3557         DCHECK(sa() == 0);
3558         alu_out = get_register(LO);
3559       } else {
3560         // MIPS spec: If no bits were set in GPR rs(), the result written to
3561         // GPR rd() is 64.
3562         DCHECK(sa() == 1);
3563         alu_out = base::bits::CountLeadingZeros64(static_cast<int64_t>(rs_u()));
3564       }
3565       SetResult(rd_reg(), alu_out);
3566       break;
3567     // Instructions using HI and LO registers.
3568     case MULT: {  // MULT == D_MUL_MUH.
3569       int32_t rs_lo = static_cast<int32_t>(rs());
3570       int32_t rt_lo = static_cast<int32_t>(rt());
3571       i64hilo = static_cast<int64_t>(rs_lo) * static_cast<int64_t>(rt_lo);
3572       if (kArchVariant != kMips64r6) {
3573         set_register(LO, static_cast<int32_t>(i64hilo & 0xffffffff));
3574         set_register(HI, static_cast<int32_t>(i64hilo >> 32));
3575       } else {
3576         switch (sa()) {
3577           case MUL_OP:
3578             set_register(rd_reg(), static_cast<int32_t>(i64hilo & 0xffffffff));
3579             break;
3580           case MUH_OP:
3581             set_register(rd_reg(), static_cast<int32_t>(i64hilo >> 32));
3582             break;
3583           default:
3584             UNIMPLEMENTED_MIPS();
3585             break;
3586         }
3587       }
3588       break;
3589     }
3590     case MULTU:
3591       u64hilo = static_cast<uint64_t>(rs_u() & 0xffffffff) *
3592                 static_cast<uint64_t>(rt_u() & 0xffffffff);
3593       if (kArchVariant != kMips64r6) {
3594         set_register(LO, static_cast<int32_t>(u64hilo & 0xffffffff));
3595         set_register(HI, static_cast<int32_t>(u64hilo >> 32));
3596       } else {
3597         switch (sa()) {
3598           case MUL_OP:
3599             set_register(rd_reg(), static_cast<int32_t>(u64hilo & 0xffffffff));
3600             break;
3601           case MUH_OP:
3602             set_register(rd_reg(), static_cast<int32_t>(u64hilo >> 32));
3603             break;
3604           default:
3605             UNIMPLEMENTED_MIPS();
3606             break;
3607         }
3608       }
3609       break;
3610     case DMULT:  // DMULT == D_MUL_MUH.
3611       if (kArchVariant != kMips64r6) {
3612         set_register(LO, rs() * rt());
3613         set_register(HI, MultiplyHighSigned(rs(), rt()));
3614       } else {
3615         switch (sa()) {
3616           case MUL_OP:
3617             set_register(rd_reg(), rs() * rt());
3618             break;
3619           case MUH_OP:
3620             set_register(rd_reg(), MultiplyHighSigned(rs(), rt()));
3621             break;
3622           default:
3623             UNIMPLEMENTED_MIPS();
3624             break;
3625         }
3626       }
3627       break;
3628     case DMULTU:
3629       UNIMPLEMENTED_MIPS();
3630       break;
3631     case DIV:
3632     case DDIV: {
3633       const int64_t int_min_value =
3634           get_instr()->FunctionFieldRaw() == DIV ? INT_MIN : LONG_MIN;
3635       switch (kArchVariant) {
3636         case kMips64r2:
3637           // Divide by zero and overflow was not checked in the
3638           // configuration step - div and divu do not raise exceptions. On
3639           // division by 0 the result will be UNPREDICTABLE. On overflow
3640           // (INT_MIN/-1), return INT_MIN which is what the hardware does.
3641           if (rs() == int_min_value && rt() == -1) {
3642             set_register(LO, int_min_value);
3643             set_register(HI, 0);
3644           } else if (rt() != 0) {
3645             set_register(LO, rs() / rt());
3646             set_register(HI, rs() % rt());
3647           }
3648           break;
3649         case kMips64r6:
3650           switch (sa()) {
3651             case DIV_OP:
3652               if (rs() == int_min_value && rt() == -1) {
3653                 set_register(rd_reg(), int_min_value);
3654               } else if (rt() != 0) {
3655                 set_register(rd_reg(), rs() / rt());
3656               }
3657               break;
3658             case MOD_OP:
3659               if (rs() == int_min_value && rt() == -1) {
3660                 set_register(rd_reg(), 0);
3661               } else if (rt() != 0) {
3662                 set_register(rd_reg(), rs() % rt());
3663               }
3664               break;
3665             default:
3666               UNIMPLEMENTED_MIPS();
3667               break;
3668           }
3669           break;
3670         default:
3671           break;
3672       }
3673       break;
3674     }
3675     case DIVU:
3676       switch (kArchVariant) {
3677         case kMips64r6: {
3678           uint32_t rt_u_32 = static_cast<uint32_t>(rt_u());
3679           uint32_t rs_u_32 = static_cast<uint32_t>(rs_u());
3680           switch (get_instr()->SaValue()) {
3681             case DIV_OP:
3682               if (rt_u_32 != 0) {
3683                 set_register(rd_reg(), rs_u_32 / rt_u_32);
3684               }
3685               break;
3686             case MOD_OP:
3687               if (rt_u() != 0) {
3688                 set_register(rd_reg(), rs_u_32 % rt_u_32);
3689               }
3690               break;
3691             default:
3692               UNIMPLEMENTED_MIPS();
3693               break;
3694           }
3695         } break;
3696         default: {
3697           if (rt_u() != 0) {
3698             uint32_t rt_u_32 = static_cast<uint32_t>(rt_u());
3699             uint32_t rs_u_32 = static_cast<uint32_t>(rs_u());
3700             set_register(LO, rs_u_32 / rt_u_32);
3701             set_register(HI, rs_u_32 % rt_u_32);
3702           }
3703         }
3704       }
3705       break;
3706     case DDIVU:
3707       switch (kArchVariant) {
3708         case kMips64r6: {
3709           switch (get_instr()->SaValue()) {
3710             case DIV_OP:
3711               if (rt_u() != 0) {
3712                 set_register(rd_reg(), rs_u() / rt_u());
3713               }
3714               break;
3715             case MOD_OP:
3716               if (rt_u() != 0) {
3717                 set_register(rd_reg(), rs_u() % rt_u());
3718               }
3719               break;
3720             default:
3721               UNIMPLEMENTED_MIPS();
3722               break;
3723           }
3724         } break;
3725         default: {
3726           if (rt_u() != 0) {
3727             set_register(LO, rs_u() / rt_u());
3728             set_register(HI, rs_u() % rt_u());
3729           }
3730         }
3731       }
3732       break;
3733     case ADD:
3734     case DADD:
3735       if (HaveSameSign(rs(), rt())) {
3736         if (rs() > 0) {
3737           if (rs() > (Registers::kMaxValue - rt())) {
3738             SignalException(kIntegerOverflow);
3739           }
3740         } else if (rs() < 0) {
3741           if (rs() < (Registers::kMinValue - rt())) {
3742             SignalException(kIntegerUnderflow);
3743           }
3744         }
3745       }
3746       SetResult(rd_reg(), rs() + rt());
3747       break;
3748     case ADDU: {
3749       int32_t alu32_out = static_cast<int32_t>(rs() + rt());
3750       // Sign-extend result of 32bit operation into 64bit register.
3751       SetResult(rd_reg(), static_cast<int64_t>(alu32_out));
3752       break;
3753     }
3754     case DADDU:
3755       SetResult(rd_reg(), rs() + rt());
3756       break;
3757     case SUB:
3758     case DSUB:
3759       if (!HaveSameSign(rs(), rt())) {
3760         if (rs() > 0) {
3761           if (rs() > (Registers::kMaxValue + rt())) {
3762             SignalException(kIntegerOverflow);
3763           }
3764         } else if (rs() < 0) {
3765           if (rs() < (Registers::kMinValue + rt())) {
3766             SignalException(kIntegerUnderflow);
3767           }
3768         }
3769       }
3770       SetResult(rd_reg(), rs() - rt());
3771       break;
3772     case SUBU: {
3773       int32_t alu32_out = static_cast<int32_t>(rs() - rt());
3774       // Sign-extend result of 32bit operation into 64bit register.
3775       SetResult(rd_reg(), static_cast<int64_t>(alu32_out));
3776       break;
3777     }
3778     case DSUBU:
3779       SetResult(rd_reg(), rs() - rt());
3780       break;
3781     case AND:
3782       SetResult(rd_reg(), rs() & rt());
3783       break;
3784     case OR:
3785       SetResult(rd_reg(), rs() | rt());
3786       break;
3787     case XOR:
3788       SetResult(rd_reg(), rs() ^ rt());
3789       break;
3790     case NOR:
3791       SetResult(rd_reg(), ~(rs() | rt()));
3792       break;
3793     case SLT:
3794       SetResult(rd_reg(), rs() < rt() ? 1 : 0);
3795       break;
3796     case SLTU:
3797       SetResult(rd_reg(), rs_u() < rt_u() ? 1 : 0);
3798       break;
3799     // Break and trap instructions.
3800     case BREAK:
3801       do_interrupt = true;
3802       break;
3803     case TGE:
3804       do_interrupt = rs() >= rt();
3805       break;
3806     case TGEU:
3807       do_interrupt = rs_u() >= rt_u();
3808       break;
3809     case TLT:
3810       do_interrupt = rs() < rt();
3811       break;
3812     case TLTU:
3813       do_interrupt = rs_u() < rt_u();
3814       break;
3815     case TEQ:
3816       do_interrupt = rs() == rt();
3817       break;
3818     case TNE:
3819       do_interrupt = rs() != rt();
3820       break;
3821     case SYNC:
3822       // TODO(palfia): Ignore sync instruction for now.
3823       break;
3824     // Conditional moves.
3825     case MOVN:
3826       if (rt()) {
3827         SetResult(rd_reg(), rs());
3828       }
3829       break;
3830     case MOVCI: {
3831       uint32_t cc = get_instr()->FBccValue();
3832       uint32_t fcsr_cc = get_fcsr_condition_bit(cc);
3833       if (get_instr()->Bit(16)) {  // Read Tf bit.
3834         if (test_fcsr_bit(fcsr_cc)) set_register(rd_reg(), rs());
3835       } else {
3836         if (!test_fcsr_bit(fcsr_cc)) set_register(rd_reg(), rs());
3837       }
3838       break;
3839     }
3840     case MOVZ:
3841       if (!rt()) {
3842         SetResult(rd_reg(), rs());
3843       }
3844       break;
3845     default:
3846       UNREACHABLE();
3847   }
3848   if (do_interrupt) {
3849     SoftwareInterrupt(get_instr());
3850   }
3851 }
3852 
3853 
DecodeTypeRegisterSPECIAL2()3854 void Simulator::DecodeTypeRegisterSPECIAL2() {
3855   int64_t alu_out;
3856   switch (get_instr()->FunctionFieldRaw()) {
3857     case MUL:
3858       alu_out = static_cast<int32_t>(rs_u()) * static_cast<int32_t>(rt_u());
3859       SetResult(rd_reg(), alu_out);
3860       // HI and LO are UNPREDICTABLE after the operation.
3861       set_register(LO, Unpredictable);
3862       set_register(HI, Unpredictable);
3863       break;
3864     case CLZ:
3865       // MIPS32 spec: If no bits were set in GPR rs(), the result written to
3866       // GPR rd is 32.
3867       alu_out = base::bits::CountLeadingZeros32(static_cast<uint32_t>(rs_u()));
3868       SetResult(rd_reg(), alu_out);
3869       break;
3870     case DCLZ:
3871       // MIPS64 spec: If no bits were set in GPR rs(), the result written to
3872       // GPR rd is 64.
3873       alu_out = base::bits::CountLeadingZeros64(static_cast<uint64_t>(rs_u()));
3874       SetResult(rd_reg(), alu_out);
3875       break;
3876     default:
3877       alu_out = 0x12345678;
3878       UNREACHABLE();
3879   }
3880 }
3881 
3882 
DecodeTypeRegisterSPECIAL3()3883 void Simulator::DecodeTypeRegisterSPECIAL3() {
3884   int64_t alu_out;
3885   switch (get_instr()->FunctionFieldRaw()) {
3886     case INS: {  // Mips64r2 instruction.
3887       // Interpret rd field as 5-bit msb of insert.
3888       uint16_t msb = rd_reg();
3889       // Interpret sa field as 5-bit lsb of insert.
3890       uint16_t lsb = sa();
3891       uint16_t size = msb - lsb + 1;
3892       uint64_t mask = (1ULL << size) - 1;
3893       alu_out = static_cast<int32_t>((rt_u() & ~(mask << lsb)) |
3894                                      ((rs_u() & mask) << lsb));
3895       SetResult(rt_reg(), alu_out);
3896       break;
3897     }
3898     case DINS: {  // Mips64r2 instruction.
3899       // Interpret rd field as 5-bit msb of insert.
3900       uint16_t msb = rd_reg();
3901       // Interpret sa field as 5-bit lsb of insert.
3902       uint16_t lsb = sa();
3903       uint16_t size = msb - lsb + 1;
3904       uint64_t mask = (1ULL << size) - 1;
3905       alu_out = (rt_u() & ~(mask << lsb)) | ((rs_u() & mask) << lsb);
3906       SetResult(rt_reg(), alu_out);
3907       break;
3908     }
3909     case EXT: {  // Mips64r2 instruction.
3910       // Interpret rd field as 5-bit msb of extract.
3911       uint16_t msb = rd_reg();
3912       // Interpret sa field as 5-bit lsb of extract.
3913       uint16_t lsb = sa();
3914       uint16_t size = msb + 1;
3915       uint64_t mask = (1ULL << size) - 1;
3916       alu_out = static_cast<int32_t>((rs_u() & (mask << lsb)) >> lsb);
3917       SetResult(rt_reg(), alu_out);
3918       break;
3919     }
3920     case DEXT: {  // Mips64r2 instruction.
3921       // Interpret rd field as 5-bit msb of extract.
3922       uint16_t msb = rd_reg();
3923       // Interpret sa field as 5-bit lsb of extract.
3924       uint16_t lsb = sa();
3925       uint16_t size = msb + 1;
3926       uint64_t mask = (1ULL << size) - 1;
3927       alu_out = static_cast<int64_t>((rs_u() & (mask << lsb)) >> lsb);
3928       SetResult(rt_reg(), alu_out);
3929       break;
3930     }
3931     case DEXTM: {
3932       // Interpret rd field as 5-bit msb of extract.
3933       uint16_t msb = rd_reg();
3934       // Interpret sa field as 5-bit lsb of extract.
3935       uint16_t lsb = sa();
3936       uint16_t size = msb + 33;
3937       uint64_t mask = (1ULL << size) - 1;
3938       alu_out = static_cast<int64_t>((rs_u() & (mask << lsb)) >> lsb);
3939       SetResult(rt_reg(), alu_out);
3940       break;
3941     }
3942     case DEXTU: {
3943       // Interpret rd field as 5-bit msb of extract.
3944       uint16_t msb = rd_reg();
3945       // Interpret sa field as 5-bit lsb of extract.
3946       uint16_t lsb = sa() + 32;
3947       uint16_t size = msb + 1;
3948       uint64_t mask = (1ULL << size) - 1;
3949       alu_out = static_cast<int64_t>((rs_u() & (mask << lsb)) >> lsb);
3950       SetResult(rt_reg(), alu_out);
3951       break;
3952     }
3953     case BSHFL: {
3954       int32_t sa = get_instr()->SaFieldRaw() >> kSaShift;
3955       switch (sa) {
3956         case BITSWAP: {
3957           uint32_t input = static_cast<uint32_t>(rt());
3958           uint32_t output = 0;
3959           uint8_t i_byte, o_byte;
3960 
3961           // Reverse the bit in byte for each individual byte
3962           for (int i = 0; i < 4; i++) {
3963             output = output >> 8;
3964             i_byte = input & 0xff;
3965 
3966             // Fast way to reverse bits in byte
3967             // Devised by Sean Anderson, July 13, 2001
3968             o_byte = static_cast<uint8_t>(((i_byte * 0x0802LU & 0x22110LU) |
3969                                            (i_byte * 0x8020LU & 0x88440LU)) *
3970                                               0x10101LU >>
3971                                           16);
3972 
3973             output = output | (static_cast<uint32_t>(o_byte << 24));
3974             input = input >> 8;
3975           }
3976 
3977           alu_out = static_cast<int64_t>(static_cast<int32_t>(output));
3978           break;
3979         }
3980         case SEB: {
3981           uint8_t input = static_cast<uint8_t>(rt());
3982           uint32_t output = input;
3983           uint32_t mask = 0x00000080;
3984 
3985           // Extending sign
3986           if (mask & input) {
3987             output |= 0xFFFFFF00;
3988           }
3989 
3990           alu_out = static_cast<int32_t>(output);
3991           break;
3992         }
3993         case SEH: {
3994           uint16_t input = static_cast<uint16_t>(rt());
3995           uint32_t output = input;
3996           uint32_t mask = 0x00008000;
3997 
3998           // Extending sign
3999           if (mask & input) {
4000             output |= 0xFFFF0000;
4001           }
4002 
4003           alu_out = static_cast<int32_t>(output);
4004           break;
4005         }
4006         case WSBH: {
4007           uint32_t input = static_cast<uint32_t>(rt());
4008           uint64_t output = 0;
4009 
4010           uint32_t mask = 0xFF000000;
4011           for (int i = 0; i < 4; i++) {
4012             uint32_t tmp = mask & input;
4013             if (i % 2 == 0) {
4014               tmp = tmp >> 8;
4015             } else {
4016               tmp = tmp << 8;
4017             }
4018             output = output | tmp;
4019             mask = mask >> 8;
4020           }
4021           mask = 0x80000000;
4022 
4023           // Extending sign
4024           if (mask & output) {
4025             output |= 0xFFFFFFFF00000000;
4026           }
4027 
4028           alu_out = static_cast<int64_t>(output);
4029           break;
4030         }
4031         default: {
4032           const uint8_t bp2 = get_instr()->Bp2Value();
4033           sa >>= kBp2Bits;
4034           switch (sa) {
4035             case ALIGN: {
4036               if (bp2 == 0) {
4037                 alu_out = static_cast<int32_t>(rt());
4038               } else {
4039                 uint64_t rt_hi = rt() << (8 * bp2);
4040                 uint64_t rs_lo = rs() >> (8 * (4 - bp2));
4041                 alu_out = static_cast<int32_t>(rt_hi | rs_lo);
4042               }
4043               break;
4044             }
4045             default:
4046               alu_out = 0x12345678;
4047               UNREACHABLE();
4048               break;
4049           }
4050           break;
4051         }
4052       }
4053       SetResult(rd_reg(), alu_out);
4054       break;
4055     }
4056     case DBSHFL: {
4057       int32_t sa = get_instr()->SaFieldRaw() >> kSaShift;
4058       switch (sa) {
4059         case DBITSWAP: {
4060           switch (sa) {
4061             case DBITSWAP_SA: {  // Mips64r6
4062               uint64_t input = static_cast<uint64_t>(rt());
4063               uint64_t output = 0;
4064               uint8_t i_byte, o_byte;
4065 
4066               // Reverse the bit in byte for each individual byte
4067               for (int i = 0; i < 8; i++) {
4068                 output = output >> 8;
4069                 i_byte = input & 0xff;
4070 
4071                 // Fast way to reverse bits in byte
4072                 // Devised by Sean Anderson, July 13, 2001
4073                 o_byte =
4074                     static_cast<uint8_t>(((i_byte * 0x0802LU & 0x22110LU) |
4075                                           (i_byte * 0x8020LU & 0x88440LU)) *
4076                                              0x10101LU >>
4077                                          16);
4078 
4079                 output = output | ((static_cast<uint64_t>(o_byte) << 56));
4080                 input = input >> 8;
4081               }
4082 
4083               alu_out = static_cast<int64_t>(output);
4084               break;
4085             }
4086           }
4087           break;
4088         }
4089         case DSBH: {
4090           uint64_t input = static_cast<uint64_t>(rt());
4091           uint64_t output = 0;
4092 
4093           uint64_t mask = 0xFF00000000000000;
4094           for (int i = 0; i < 8; i++) {
4095             uint64_t tmp = mask & input;
4096             if (i % 2 == 0)
4097               tmp = tmp >> 8;
4098             else
4099               tmp = tmp << 8;
4100 
4101             output = output | tmp;
4102             mask = mask >> 8;
4103           }
4104 
4105           alu_out = static_cast<int64_t>(output);
4106           break;
4107         }
4108         case DSHD: {
4109           uint64_t input = static_cast<uint64_t>(rt());
4110           uint64_t output = 0;
4111 
4112           uint64_t mask = 0xFFFF000000000000;
4113           for (int i = 0; i < 4; i++) {
4114             uint64_t tmp = mask & input;
4115             if (i == 0)
4116               tmp = tmp >> 48;
4117             else if (i == 1)
4118               tmp = tmp >> 16;
4119             else if (i == 2)
4120               tmp = tmp << 16;
4121             else
4122               tmp = tmp << 48;
4123             output = output | tmp;
4124             mask = mask >> 16;
4125           }
4126 
4127           alu_out = static_cast<int64_t>(output);
4128           break;
4129         }
4130         default: {
4131           const uint8_t bp3 = get_instr()->Bp3Value();
4132           sa >>= kBp3Bits;
4133           switch (sa) {
4134             case DALIGN: {
4135               if (bp3 == 0) {
4136                 alu_out = static_cast<int64_t>(rt());
4137               } else {
4138                 uint64_t rt_hi = rt() << (8 * bp3);
4139                 uint64_t rs_lo = rs() >> (8 * (8 - bp3));
4140                 alu_out = static_cast<int64_t>(rt_hi | rs_lo);
4141               }
4142               break;
4143             }
4144             default:
4145               alu_out = 0x12345678;
4146               UNREACHABLE();
4147               break;
4148           }
4149           break;
4150         }
4151       }
4152       SetResult(rd_reg(), alu_out);
4153       break;
4154     }
4155     default:
4156       UNREACHABLE();
4157   }
4158 }
4159 
4160 
DecodeTypeRegister(Instruction * instr)4161 void Simulator::DecodeTypeRegister(Instruction* instr) {
4162   set_instr(instr);
4163 
4164   // ---------- Execution.
4165   switch (instr->OpcodeFieldRaw()) {
4166     case COP1:
4167       DecodeTypeRegisterCOP1();
4168       break;
4169     case COP1X:
4170       DecodeTypeRegisterCOP1X();
4171       break;
4172     case SPECIAL:
4173       DecodeTypeRegisterSPECIAL();
4174       break;
4175     case SPECIAL2:
4176       DecodeTypeRegisterSPECIAL2();
4177       break;
4178     case SPECIAL3:
4179       DecodeTypeRegisterSPECIAL3();
4180       break;
4181     // Unimplemented opcodes raised an error in the configuration step before,
4182     // so we can use the default here to set the destination register in common
4183     // cases.
4184     default:
4185       UNREACHABLE();
4186   }
4187 }
4188 
4189 
4190 // Type 2: instructions using a 16, 21 or 26 bits immediate. (e.g. beq, beqc).
DecodeTypeImmediate(Instruction * instr)4191 void Simulator::DecodeTypeImmediate(Instruction* instr) {
4192   // Instruction fields.
4193   Opcode op = instr->OpcodeFieldRaw();
4194   int32_t rs_reg = instr->RsValue();
4195   int64_t rs = get_register(instr->RsValue());
4196   uint64_t rs_u = static_cast<uint64_t>(rs);
4197   int32_t rt_reg = instr->RtValue();  // Destination register.
4198   int64_t rt = get_register(rt_reg);
4199   int16_t imm16 = instr->Imm16Value();
4200   int32_t imm18 = instr->Imm18Value();
4201 
4202   int32_t ft_reg = instr->FtValue();  // Destination register.
4203 
4204   // Zero extended immediate.
4205   uint64_t oe_imm16 = 0xffff & imm16;
4206   // Sign extended immediate.
4207   int64_t se_imm16 = imm16;
4208   int64_t se_imm18 = imm18 | ((imm18 & 0x20000) ? 0xfffffffffffc0000 : 0);
4209 
4210   // Next pc.
4211   int64_t next_pc = bad_ra;
4212 
4213   // Used for conditional branch instructions.
4214   bool execute_branch_delay_instruction = false;
4215 
4216   // Used for arithmetic instructions.
4217   int64_t alu_out = 0;
4218 
4219   // Used for memory instructions.
4220   int64_t addr = 0x0;
4221   // Alignment for 32-bit integers used in LWL, LWR, etc.
4222   const int kInt32AlignmentMask = sizeof(uint32_t) - 1;
4223   // Alignment for 64-bit integers used in LDL, LDR, etc.
4224   const int kInt64AlignmentMask = sizeof(uint64_t) - 1;
4225 
4226   // Branch instructions common part.
4227   auto BranchAndLinkHelper = [this, instr, &next_pc,
4228                               &execute_branch_delay_instruction](
4229       bool do_branch) {
4230     execute_branch_delay_instruction = true;
4231     int64_t current_pc = get_pc();
4232     if (do_branch) {
4233       int16_t imm16 = instr->Imm16Value();
4234       next_pc = current_pc + (imm16 << 2) + Instruction::kInstrSize;
4235       set_register(31, current_pc + 2 * Instruction::kInstrSize);
4236     } else {
4237       next_pc = current_pc + 2 * Instruction::kInstrSize;
4238     }
4239   };
4240 
4241   auto BranchHelper = [this, instr, &next_pc,
4242                        &execute_branch_delay_instruction](bool do_branch) {
4243     execute_branch_delay_instruction = true;
4244     int64_t current_pc = get_pc();
4245     if (do_branch) {
4246       int16_t imm16 = instr->Imm16Value();
4247       next_pc = current_pc + (imm16 << 2) + Instruction::kInstrSize;
4248     } else {
4249       next_pc = current_pc + 2 * Instruction::kInstrSize;
4250     }
4251   };
4252 
4253   auto BranchAndLinkCompactHelper = [this, instr, &next_pc](bool do_branch,
4254                                                             int bits) {
4255     int64_t current_pc = get_pc();
4256     CheckForbiddenSlot(current_pc);
4257     if (do_branch) {
4258       int32_t imm = instr->ImmValue(bits);
4259       imm <<= 32 - bits;
4260       imm >>= 32 - bits;
4261       next_pc = current_pc + (imm << 2) + Instruction::kInstrSize;
4262       set_register(31, current_pc + Instruction::kInstrSize);
4263     }
4264   };
4265 
4266   auto BranchCompactHelper = [&next_pc, this, instr](bool do_branch, int bits) {
4267     int64_t current_pc = get_pc();
4268     CheckForbiddenSlot(current_pc);
4269     if (do_branch) {
4270       int32_t imm = instr->ImmValue(bits);
4271       imm <<= 32 - bits;
4272       imm >>= 32 - bits;
4273       next_pc = get_pc() + (imm << 2) + Instruction::kInstrSize;
4274     }
4275   };
4276 
4277   switch (op) {
4278     // ------------- COP1. Coprocessor instructions.
4279     case COP1:
4280       switch (instr->RsFieldRaw()) {
4281         case BC1: {  // Branch on coprocessor condition.
4282           uint32_t cc = instr->FBccValue();
4283           uint32_t fcsr_cc = get_fcsr_condition_bit(cc);
4284           uint32_t cc_value = test_fcsr_bit(fcsr_cc);
4285           bool do_branch = (instr->FBtrueValue()) ? cc_value : !cc_value;
4286           BranchHelper(do_branch);
4287           break;
4288         }
4289         case BC1EQZ:
4290           BranchHelper(!(get_fpu_register(ft_reg) & 0x1));
4291           break;
4292         case BC1NEZ:
4293           BranchHelper(get_fpu_register(ft_reg) & 0x1);
4294           break;
4295         default:
4296           UNREACHABLE();
4297       }
4298       break;
4299     // ------------- REGIMM class.
4300     case REGIMM:
4301       switch (instr->RtFieldRaw()) {
4302         case BLTZ:
4303           BranchHelper(rs < 0);
4304           break;
4305         case BGEZ:
4306           BranchHelper(rs >= 0);
4307           break;
4308         case BLTZAL:
4309           BranchAndLinkHelper(rs < 0);
4310           break;
4311         case BGEZAL:
4312           BranchAndLinkHelper(rs >= 0);
4313           break;
4314         case DAHI:
4315           SetResult(rs_reg, rs + (se_imm16 << 32));
4316           break;
4317         case DATI:
4318           SetResult(rs_reg, rs + (se_imm16 << 48));
4319           break;
4320         default:
4321           UNREACHABLE();
4322       }
4323       break;  // case REGIMM.
4324     // ------------- Branch instructions.
4325     // When comparing to zero, the encoding of rt field is always 0, so we don't
4326     // need to replace rt with zero.
4327     case BEQ:
4328       BranchHelper(rs == rt);
4329       break;
4330     case BNE:
4331       BranchHelper(rs != rt);
4332       break;
4333     case POP06:  // BLEZALC, BGEZALC, BGEUC, BLEZ (pre-r6)
4334       if (kArchVariant == kMips64r6) {
4335         if (rt_reg != 0) {
4336           if (rs_reg == 0) {  // BLEZALC
4337             BranchAndLinkCompactHelper(rt <= 0, 16);
4338           } else {
4339             if (rs_reg == rt_reg) {  // BGEZALC
4340               BranchAndLinkCompactHelper(rt >= 0, 16);
4341             } else {  // BGEUC
4342               BranchCompactHelper(
4343                   static_cast<uint64_t>(rs) >= static_cast<uint64_t>(rt), 16);
4344             }
4345           }
4346         } else {  // BLEZ
4347           BranchHelper(rs <= 0);
4348         }
4349       } else {  // BLEZ
4350         BranchHelper(rs <= 0);
4351       }
4352       break;
4353     case POP07:  // BGTZALC, BLTZALC, BLTUC, BGTZ (pre-r6)
4354       if (kArchVariant == kMips64r6) {
4355         if (rt_reg != 0) {
4356           if (rs_reg == 0) {  // BGTZALC
4357             BranchAndLinkCompactHelper(rt > 0, 16);
4358           } else {
4359             if (rt_reg == rs_reg) {  // BLTZALC
4360               BranchAndLinkCompactHelper(rt < 0, 16);
4361             } else {  // BLTUC
4362               BranchCompactHelper(
4363                   static_cast<uint64_t>(rs) < static_cast<uint64_t>(rt), 16);
4364             }
4365           }
4366         } else {  // BGTZ
4367           BranchHelper(rs > 0);
4368         }
4369       } else {  // BGTZ
4370         BranchHelper(rs > 0);
4371       }
4372       break;
4373     case POP26:  // BLEZC, BGEZC, BGEC/BLEC / BLEZL (pre-r6)
4374       if (kArchVariant == kMips64r6) {
4375         if (rt_reg != 0) {
4376           if (rs_reg == 0) {  // BLEZC
4377             BranchCompactHelper(rt <= 0, 16);
4378           } else {
4379             if (rs_reg == rt_reg) {  // BGEZC
4380               BranchCompactHelper(rt >= 0, 16);
4381             } else {  // BGEC/BLEC
4382               BranchCompactHelper(rs >= rt, 16);
4383             }
4384           }
4385         }
4386       } else {  // BLEZL
4387         BranchAndLinkHelper(rs <= 0);
4388       }
4389       break;
4390     case POP27:  // BGTZC, BLTZC, BLTC/BGTC / BGTZL (pre-r6)
4391       if (kArchVariant == kMips64r6) {
4392         if (rt_reg != 0) {
4393           if (rs_reg == 0) {  // BGTZC
4394             BranchCompactHelper(rt > 0, 16);
4395           } else {
4396             if (rs_reg == rt_reg) {  // BLTZC
4397               BranchCompactHelper(rt < 0, 16);
4398             } else {  // BLTC/BGTC
4399               BranchCompactHelper(rs < rt, 16);
4400             }
4401           }
4402         }
4403       } else {  // BGTZL
4404         BranchAndLinkHelper(rs > 0);
4405       }
4406       break;
4407     case POP66:           // BEQZC, JIC
4408       if (rs_reg != 0) {  // BEQZC
4409         BranchCompactHelper(rs == 0, 21);
4410       } else {  // JIC
4411         next_pc = rt + imm16;
4412       }
4413       break;
4414     case POP76:           // BNEZC, JIALC
4415       if (rs_reg != 0) {  // BNEZC
4416         BranchCompactHelper(rs != 0, 21);
4417       } else {  // JIALC
4418         int64_t current_pc = get_pc();
4419         set_register(31, current_pc + Instruction::kInstrSize);
4420         next_pc = rt + imm16;
4421       }
4422       break;
4423     case BC:
4424       BranchCompactHelper(true, 26);
4425       break;
4426     case BALC:
4427       BranchAndLinkCompactHelper(true, 26);
4428       break;
4429     case POP10:  // BOVC, BEQZALC, BEQC / ADDI (pre-r6)
4430       if (kArchVariant == kMips64r6) {
4431         if (rs_reg >= rt_reg) {  // BOVC
4432           bool condition = !is_int32(rs) || !is_int32(rt) || !is_int32(rs + rt);
4433           BranchCompactHelper(condition, 16);
4434         } else {
4435           if (rs_reg == 0) {  // BEQZALC
4436             BranchAndLinkCompactHelper(rt == 0, 16);
4437           } else {  // BEQC
4438             BranchCompactHelper(rt == rs, 16);
4439           }
4440         }
4441       } else {  // ADDI
4442         if (HaveSameSign(rs, se_imm16)) {
4443           if (rs > 0) {
4444             if (rs <= Registers::kMaxValue - se_imm16) {
4445               SignalException(kIntegerOverflow);
4446             }
4447           } else if (rs < 0) {
4448             if (rs >= Registers::kMinValue - se_imm16) {
4449               SignalException(kIntegerUnderflow);
4450             }
4451           }
4452         }
4453         SetResult(rt_reg, rs + se_imm16);
4454       }
4455       break;
4456     case POP30:  // BNVC, BNEZALC, BNEC / DADDI (pre-r6)
4457       if (kArchVariant == kMips64r6) {
4458         if (rs_reg >= rt_reg) {  // BNVC
4459           bool condition = is_int32(rs) && is_int32(rt) && is_int32(rs + rt);
4460           BranchCompactHelper(condition, 16);
4461         } else {
4462           if (rs_reg == 0) {  // BNEZALC
4463             BranchAndLinkCompactHelper(rt != 0, 16);
4464           } else {  // BNEC
4465             BranchCompactHelper(rt != rs, 16);
4466           }
4467         }
4468       }
4469       break;
4470     // ------------- Arithmetic instructions.
4471     case ADDIU: {
4472       DCHECK(is_int32(rs));
4473       int32_t alu32_out = static_cast<int32_t>(rs + se_imm16);
4474       // Sign-extend result of 32bit operation into 64bit register.
4475       SetResult(rt_reg, static_cast<int64_t>(alu32_out));
4476       break;
4477     }
4478     case DADDIU:
4479       SetResult(rt_reg, rs + se_imm16);
4480       break;
4481     case SLTI:
4482       SetResult(rt_reg, rs < se_imm16 ? 1 : 0);
4483       break;
4484     case SLTIU:
4485       SetResult(rt_reg, rs_u < static_cast<uint64_t>(se_imm16) ? 1 : 0);
4486       break;
4487     case ANDI:
4488       SetResult(rt_reg, rs & oe_imm16);
4489       break;
4490     case ORI:
4491       SetResult(rt_reg, rs | oe_imm16);
4492       break;
4493     case XORI:
4494       SetResult(rt_reg, rs ^ oe_imm16);
4495       break;
4496     case LUI:
4497       if (rs_reg != 0) {
4498         // AUI instruction.
4499         DCHECK(kArchVariant == kMips64r6);
4500         int32_t alu32_out = static_cast<int32_t>(rs + (se_imm16 << 16));
4501         SetResult(rt_reg, static_cast<int64_t>(alu32_out));
4502       } else {
4503         // LUI instruction.
4504         int32_t alu32_out = static_cast<int32_t>(oe_imm16 << 16);
4505         // Sign-extend result of 32bit operation into 64bit register.
4506         SetResult(rt_reg, static_cast<int64_t>(alu32_out));
4507       }
4508       break;
4509     case DAUI:
4510       DCHECK(kArchVariant == kMips64r6);
4511       DCHECK(rs_reg != 0);
4512       SetResult(rt_reg, rs + (se_imm16 << 16));
4513       break;
4514     // ------------- Memory instructions.
4515     case LB:
4516       set_register(rt_reg, ReadB(rs + se_imm16));
4517       break;
4518     case LH:
4519       set_register(rt_reg, ReadH(rs + se_imm16, instr));
4520       break;
4521     case LWL: {
4522       // al_offset is offset of the effective address within an aligned word.
4523       uint8_t al_offset = (rs + se_imm16) & kInt32AlignmentMask;
4524       uint8_t byte_shift = kInt32AlignmentMask - al_offset;
4525       uint32_t mask = (1 << byte_shift * 8) - 1;
4526       addr = rs + se_imm16 - al_offset;
4527       int32_t val = ReadW(addr, instr);
4528       val <<= byte_shift * 8;
4529       val |= rt & mask;
4530       set_register(rt_reg, static_cast<int64_t>(val));
4531       break;
4532     }
4533     case LW:
4534       set_register(rt_reg, ReadW(rs + se_imm16, instr));
4535       break;
4536     case LWU:
4537       set_register(rt_reg, ReadWU(rs + se_imm16, instr));
4538       break;
4539     case LD:
4540       set_register(rt_reg, Read2W(rs + se_imm16, instr));
4541       break;
4542     case LBU:
4543       set_register(rt_reg, ReadBU(rs + se_imm16));
4544       break;
4545     case LHU:
4546       set_register(rt_reg, ReadHU(rs + se_imm16, instr));
4547       break;
4548     case LWR: {
4549       // al_offset is offset of the effective address within an aligned word.
4550       uint8_t al_offset = (rs + se_imm16) & kInt32AlignmentMask;
4551       uint8_t byte_shift = kInt32AlignmentMask - al_offset;
4552       uint32_t mask = al_offset ? (~0 << (byte_shift + 1) * 8) : 0;
4553       addr = rs + se_imm16 - al_offset;
4554       alu_out = ReadW(addr, instr);
4555       alu_out = static_cast<uint32_t> (alu_out) >> al_offset * 8;
4556       alu_out |= rt & mask;
4557       set_register(rt_reg, alu_out);
4558       break;
4559     }
4560     case LDL: {
4561       // al_offset is offset of the effective address within an aligned word.
4562       uint8_t al_offset = (rs + se_imm16) & kInt64AlignmentMask;
4563       uint8_t byte_shift = kInt64AlignmentMask - al_offset;
4564       uint64_t mask = (1UL << byte_shift * 8) - 1;
4565       addr = rs + se_imm16 - al_offset;
4566       alu_out = Read2W(addr, instr);
4567       alu_out <<= byte_shift * 8;
4568       alu_out |= rt & mask;
4569       set_register(rt_reg, alu_out);
4570       break;
4571     }
4572     case LDR: {
4573       // al_offset is offset of the effective address within an aligned word.
4574       uint8_t al_offset = (rs + se_imm16) & kInt64AlignmentMask;
4575       uint8_t byte_shift = kInt64AlignmentMask - al_offset;
4576       uint64_t mask = al_offset ? (~0UL << (byte_shift + 1) * 8) : 0UL;
4577       addr = rs + se_imm16 - al_offset;
4578       alu_out = Read2W(addr, instr);
4579       alu_out = alu_out >> al_offset * 8;
4580       alu_out |= rt & mask;
4581       set_register(rt_reg, alu_out);
4582       break;
4583     }
4584     case SB:
4585       WriteB(rs + se_imm16, static_cast<int8_t>(rt));
4586       break;
4587     case SH:
4588       WriteH(rs + se_imm16, static_cast<uint16_t>(rt), instr);
4589       break;
4590     case SWL: {
4591       uint8_t al_offset = (rs + se_imm16) & kInt32AlignmentMask;
4592       uint8_t byte_shift = kInt32AlignmentMask - al_offset;
4593       uint32_t mask = byte_shift ? (~0 << (al_offset + 1) * 8) : 0;
4594       addr = rs + se_imm16 - al_offset;
4595       uint64_t mem_value = ReadW(addr, instr) & mask;
4596       mem_value |= static_cast<uint32_t>(rt) >> byte_shift * 8;
4597       WriteW(addr, static_cast<int32_t>(mem_value), instr);
4598       break;
4599     }
4600     case SW:
4601       WriteW(rs + se_imm16, static_cast<int32_t>(rt), instr);
4602       break;
4603     case SD:
4604       Write2W(rs + se_imm16, rt, instr);
4605       break;
4606     case SWR: {
4607       uint8_t al_offset = (rs + se_imm16) & kInt32AlignmentMask;
4608       uint32_t mask = (1 << al_offset * 8) - 1;
4609       addr = rs + se_imm16 - al_offset;
4610       uint64_t mem_value = ReadW(addr, instr);
4611       mem_value = (rt << al_offset * 8) | (mem_value & mask);
4612       WriteW(addr, static_cast<int32_t>(mem_value), instr);
4613       break;
4614     }
4615     case SDL: {
4616       uint8_t al_offset = (rs + se_imm16) & kInt64AlignmentMask;
4617       uint8_t byte_shift = kInt64AlignmentMask - al_offset;
4618       uint64_t mask = byte_shift ? (~0UL << (al_offset + 1) * 8) : 0;
4619       addr = rs + se_imm16 - al_offset;
4620       uint64_t mem_value = Read2W(addr, instr) & mask;
4621       mem_value |= rt >> byte_shift * 8;
4622       Write2W(addr, mem_value, instr);
4623       break;
4624     }
4625     case SDR: {
4626       uint8_t al_offset = (rs + se_imm16) & kInt64AlignmentMask;
4627       uint64_t mask = (1UL << al_offset * 8) - 1;
4628       addr = rs + se_imm16 - al_offset;
4629       uint64_t mem_value = Read2W(addr, instr);
4630       mem_value = (rt << al_offset * 8) | (mem_value & mask);
4631       Write2W(addr, mem_value, instr);
4632       break;
4633     }
4634     case LWC1:
4635       set_fpu_register(ft_reg, kFPUInvalidResult);  // Trash upper 32 bits.
4636       set_fpu_register_word(ft_reg, ReadW(rs + se_imm16, instr));
4637       break;
4638     case LDC1:
4639       set_fpu_register_double(ft_reg, ReadD(rs + se_imm16, instr));
4640       break;
4641     case SWC1: {
4642       int32_t alu_out_32 = static_cast<int32_t>(get_fpu_register(ft_reg));
4643       WriteW(rs + se_imm16, alu_out_32, instr);
4644       break;
4645     }
4646     case SDC1:
4647       WriteD(rs + se_imm16, get_fpu_register_double(ft_reg), instr);
4648       break;
4649     // ------------- PC-Relative instructions.
4650     case PCREL: {
4651       // rt field: checking 5-bits.
4652       int32_t imm21 = instr->Imm21Value();
4653       int64_t current_pc = get_pc();
4654       uint8_t rt = (imm21 >> kImm16Bits);
4655       switch (rt) {
4656         case ALUIPC:
4657           addr = current_pc + (se_imm16 << 16);
4658           alu_out = static_cast<int64_t>(~0x0FFFF) & addr;
4659           break;
4660         case AUIPC:
4661           alu_out = current_pc + (se_imm16 << 16);
4662           break;
4663         default: {
4664           int32_t imm19 = instr->Imm19Value();
4665           // rt field: checking the most significant 3-bits.
4666           rt = (imm21 >> kImm18Bits);
4667           switch (rt) {
4668             case LDPC:
4669               addr =
4670                   (current_pc & static_cast<int64_t>(~0x7)) + (se_imm18 << 3);
4671               alu_out = Read2W(addr, instr);
4672               break;
4673             default: {
4674               // rt field: checking the most significant 2-bits.
4675               rt = (imm21 >> kImm19Bits);
4676               switch (rt) {
4677                 case LWUPC: {
4678                   // Set sign.
4679                   imm19 <<= (kOpcodeBits + kRsBits + 2);
4680                   imm19 >>= (kOpcodeBits + kRsBits + 2);
4681                   addr = current_pc + (imm19 << 2);
4682                   uint32_t* ptr = reinterpret_cast<uint32_t*>(addr);
4683                   alu_out = *ptr;
4684                   break;
4685                 }
4686                 case LWPC: {
4687                   // Set sign.
4688                   imm19 <<= (kOpcodeBits + kRsBits + 2);
4689                   imm19 >>= (kOpcodeBits + kRsBits + 2);
4690                   addr = current_pc + (imm19 << 2);
4691                   int32_t* ptr = reinterpret_cast<int32_t*>(addr);
4692                   alu_out = *ptr;
4693                   break;
4694                 }
4695                 case ADDIUPC: {
4696                   int64_t se_imm19 =
4697                       imm19 | ((imm19 & 0x40000) ? 0xfffffffffff80000 : 0);
4698                   alu_out = current_pc + (se_imm19 << 2);
4699                   break;
4700                 }
4701                 default:
4702                   UNREACHABLE();
4703                   break;
4704               }
4705               break;
4706             }
4707           }
4708           break;
4709         }
4710       }
4711       set_register(rs_reg, alu_out);
4712       break;
4713     }
4714     default:
4715       UNREACHABLE();
4716   }
4717 
4718   if (execute_branch_delay_instruction) {
4719     // Execute branch delay slot
4720     // We don't check for end_sim_pc. First it should not be met as the current
4721     // pc is valid. Secondly a jump should always execute its branch delay slot.
4722     Instruction* branch_delay_instr =
4723         reinterpret_cast<Instruction*>(get_pc() + Instruction::kInstrSize);
4724     BranchDelayInstructionDecode(branch_delay_instr);
4725   }
4726 
4727   // If needed update pc after the branch delay execution.
4728   if (next_pc != bad_ra) {
4729     set_pc(next_pc);
4730   }
4731 }
4732 
4733 
4734 // Type 3: instructions using a 26 bytes immediate. (e.g. j, jal).
DecodeTypeJump(Instruction * instr)4735 void Simulator::DecodeTypeJump(Instruction* instr) {
4736   // Get current pc.
4737   int64_t current_pc = get_pc();
4738   // Get unchanged bits of pc.
4739   int64_t pc_high_bits = current_pc & 0xfffffffff0000000;
4740   // Next pc.
4741   int64_t next_pc = pc_high_bits | (instr->Imm26Value() << 2);
4742 
4743   // Execute branch delay slot.
4744   // We don't check for end_sim_pc. First it should not be met as the current pc
4745   // is valid. Secondly a jump should always execute its branch delay slot.
4746   Instruction* branch_delay_instr =
4747       reinterpret_cast<Instruction*>(current_pc + Instruction::kInstrSize);
4748   BranchDelayInstructionDecode(branch_delay_instr);
4749 
4750   // Update pc and ra if necessary.
4751   // Do this after the branch delay execution.
4752   if (instr->IsLinkingInstruction()) {
4753     set_register(31, current_pc + 2 * Instruction::kInstrSize);
4754   }
4755   set_pc(next_pc);
4756   pc_modified_ = true;
4757 }
4758 
4759 
4760 // Executes the current instruction.
InstructionDecode(Instruction * instr)4761 void Simulator::InstructionDecode(Instruction* instr) {
4762   if (v8::internal::FLAG_check_icache) {
4763     CheckICache(isolate_->simulator_i_cache(), instr);
4764   }
4765   pc_modified_ = false;
4766 
4767   v8::internal::EmbeddedVector<char, 256> buffer;
4768 
4769   if (::v8::internal::FLAG_trace_sim) {
4770     SNPrintF(trace_buf_, " ");
4771     disasm::NameConverter converter;
4772     disasm::Disassembler dasm(converter);
4773     // Use a reasonably large buffer.
4774     dasm.InstructionDecode(buffer, reinterpret_cast<byte*>(instr));
4775   }
4776 
4777   switch (instr->InstructionType(Instruction::TypeChecks::EXTRA)) {
4778     case Instruction::kRegisterType:
4779       DecodeTypeRegister(instr);
4780       break;
4781     case Instruction::kImmediateType:
4782       DecodeTypeImmediate(instr);
4783       break;
4784     case Instruction::kJumpType:
4785       DecodeTypeJump(instr);
4786       break;
4787     default:
4788       UNSUPPORTED();
4789   }
4790 
4791   if (::v8::internal::FLAG_trace_sim) {
4792     PrintF("  0x%08" PRIxPTR "   %-44s   %s\n",
4793            reinterpret_cast<intptr_t>(instr), buffer.start(),
4794            trace_buf_.start());
4795   }
4796 
4797   if (!pc_modified_) {
4798     set_register(pc, reinterpret_cast<int64_t>(instr) +
4799                  Instruction::kInstrSize);
4800   }
4801 }
4802 
4803 
4804 
Execute()4805 void Simulator::Execute() {
4806   // Get the PC to simulate. Cannot use the accessor here as we need the
4807   // raw PC value and not the one used as input to arithmetic instructions.
4808   int64_t program_counter = get_pc();
4809   if (::v8::internal::FLAG_stop_sim_at == 0) {
4810     // Fast version of the dispatch loop without checking whether the simulator
4811     // should be stopping at a particular executed instruction.
4812     while (program_counter != end_sim_pc) {
4813       Instruction* instr = reinterpret_cast<Instruction*>(program_counter);
4814       icount_++;
4815       InstructionDecode(instr);
4816       program_counter = get_pc();
4817     }
4818   } else {
4819     // FLAG_stop_sim_at is at the non-default value. Stop in the debugger when
4820     // we reach the particular instuction count.
4821     while (program_counter != end_sim_pc) {
4822       Instruction* instr = reinterpret_cast<Instruction*>(program_counter);
4823       icount_++;
4824       if (icount_ == static_cast<uint64_t>(::v8::internal::FLAG_stop_sim_at)) {
4825         MipsDebugger dbg(this);
4826         dbg.Debug();
4827       } else {
4828         InstructionDecode(instr);
4829       }
4830       program_counter = get_pc();
4831     }
4832   }
4833 }
4834 
4835 
CallInternal(byte * entry)4836 void Simulator::CallInternal(byte* entry) {
4837   // Adjust JS-based stack limit to C-based stack limit.
4838   isolate_->stack_guard()->AdjustStackLimitForSimulator();
4839 
4840   // Prepare to execute the code at entry.
4841   set_register(pc, reinterpret_cast<int64_t>(entry));
4842   // Put down marker for end of simulation. The simulator will stop simulation
4843   // when the PC reaches this value. By saving the "end simulation" value into
4844   // the LR the simulation stops when returning to this call point.
4845   set_register(ra, end_sim_pc);
4846 
4847   // Remember the values of callee-saved registers.
4848   // The code below assumes that r9 is not used as sb (static base) in
4849   // simulator code and therefore is regarded as a callee-saved register.
4850   int64_t s0_val = get_register(s0);
4851   int64_t s1_val = get_register(s1);
4852   int64_t s2_val = get_register(s2);
4853   int64_t s3_val = get_register(s3);
4854   int64_t s4_val = get_register(s4);
4855   int64_t s5_val = get_register(s5);
4856   int64_t s6_val = get_register(s6);
4857   int64_t s7_val = get_register(s7);
4858   int64_t gp_val = get_register(gp);
4859   int64_t sp_val = get_register(sp);
4860   int64_t fp_val = get_register(fp);
4861 
4862   // Set up the callee-saved registers with a known value. To be able to check
4863   // that they are preserved properly across JS execution.
4864   int64_t callee_saved_value = icount_;
4865   set_register(s0, callee_saved_value);
4866   set_register(s1, callee_saved_value);
4867   set_register(s2, callee_saved_value);
4868   set_register(s3, callee_saved_value);
4869   set_register(s4, callee_saved_value);
4870   set_register(s5, callee_saved_value);
4871   set_register(s6, callee_saved_value);
4872   set_register(s7, callee_saved_value);
4873   set_register(gp, callee_saved_value);
4874   set_register(fp, callee_saved_value);
4875 
4876   // Start the simulation.
4877   Execute();
4878 
4879   // Check that the callee-saved registers have been preserved.
4880   CHECK_EQ(callee_saved_value, get_register(s0));
4881   CHECK_EQ(callee_saved_value, get_register(s1));
4882   CHECK_EQ(callee_saved_value, get_register(s2));
4883   CHECK_EQ(callee_saved_value, get_register(s3));
4884   CHECK_EQ(callee_saved_value, get_register(s4));
4885   CHECK_EQ(callee_saved_value, get_register(s5));
4886   CHECK_EQ(callee_saved_value, get_register(s6));
4887   CHECK_EQ(callee_saved_value, get_register(s7));
4888   CHECK_EQ(callee_saved_value, get_register(gp));
4889   CHECK_EQ(callee_saved_value, get_register(fp));
4890 
4891   // Restore callee-saved registers with the original value.
4892   set_register(s0, s0_val);
4893   set_register(s1, s1_val);
4894   set_register(s2, s2_val);
4895   set_register(s3, s3_val);
4896   set_register(s4, s4_val);
4897   set_register(s5, s5_val);
4898   set_register(s6, s6_val);
4899   set_register(s7, s7_val);
4900   set_register(gp, gp_val);
4901   set_register(sp, sp_val);
4902   set_register(fp, fp_val);
4903 }
4904 
4905 
Call(byte * entry,int argument_count,...)4906 int64_t Simulator::Call(byte* entry, int argument_count, ...) {
4907   const int kRegisterPassedArguments = 8;
4908   va_list parameters;
4909   va_start(parameters, argument_count);
4910   // Set up arguments.
4911 
4912   // First four arguments passed in registers in both ABI's.
4913   DCHECK(argument_count >= 4);
4914   set_register(a0, va_arg(parameters, int64_t));
4915   set_register(a1, va_arg(parameters, int64_t));
4916   set_register(a2, va_arg(parameters, int64_t));
4917   set_register(a3, va_arg(parameters, int64_t));
4918 
4919   // Up to eight arguments passed in registers in N64 ABI.
4920   // TODO(plind): N64 ABI calls these regs a4 - a7. Clarify this.
4921   if (argument_count >= 5) set_register(a4, va_arg(parameters, int64_t));
4922   if (argument_count >= 6) set_register(a5, va_arg(parameters, int64_t));
4923   if (argument_count >= 7) set_register(a6, va_arg(parameters, int64_t));
4924   if (argument_count >= 8) set_register(a7, va_arg(parameters, int64_t));
4925 
4926   // Remaining arguments passed on stack.
4927   int64_t original_stack = get_register(sp);
4928   // Compute position of stack on entry to generated code.
4929   int stack_args_count = (argument_count > kRegisterPassedArguments) ?
4930                          (argument_count - kRegisterPassedArguments) : 0;
4931   int stack_args_size = stack_args_count * sizeof(int64_t) + kCArgsSlotsSize;
4932   int64_t entry_stack = original_stack - stack_args_size;
4933 
4934   if (base::OS::ActivationFrameAlignment() != 0) {
4935     entry_stack &= -base::OS::ActivationFrameAlignment();
4936   }
4937   // Store remaining arguments on stack, from low to high memory.
4938   intptr_t* stack_argument = reinterpret_cast<intptr_t*>(entry_stack);
4939   for (int i = kRegisterPassedArguments; i < argument_count; i++) {
4940     int stack_index = i - kRegisterPassedArguments + kCArgSlotCount;
4941     stack_argument[stack_index] = va_arg(parameters, int64_t);
4942   }
4943   va_end(parameters);
4944   set_register(sp, entry_stack);
4945 
4946   CallInternal(entry);
4947 
4948   // Pop stack passed arguments.
4949   CHECK_EQ(entry_stack, get_register(sp));
4950   set_register(sp, original_stack);
4951 
4952   int64_t result = get_register(v0);
4953   return result;
4954 }
4955 
4956 
CallFP(byte * entry,double d0,double d1)4957 double Simulator::CallFP(byte* entry, double d0, double d1) {
4958   if (!IsMipsSoftFloatABI) {
4959     const FPURegister fparg2 = f13;
4960     set_fpu_register_double(f12, d0);
4961     set_fpu_register_double(fparg2, d1);
4962   } else {
4963     int buffer[2];
4964     DCHECK(sizeof(buffer[0]) * 2 == sizeof(d0));
4965     memcpy(buffer, &d0, sizeof(d0));
4966     set_dw_register(a0, buffer);
4967     memcpy(buffer, &d1, sizeof(d1));
4968     set_dw_register(a2, buffer);
4969   }
4970   CallInternal(entry);
4971   if (!IsMipsSoftFloatABI) {
4972     return get_fpu_register_double(f0);
4973   } else {
4974     return get_double_from_register_pair(v0);
4975   }
4976 }
4977 
4978 
PushAddress(uintptr_t address)4979 uintptr_t Simulator::PushAddress(uintptr_t address) {
4980   int64_t new_sp = get_register(sp) - sizeof(uintptr_t);
4981   uintptr_t* stack_slot = reinterpret_cast<uintptr_t*>(new_sp);
4982   *stack_slot = address;
4983   set_register(sp, new_sp);
4984   return new_sp;
4985 }
4986 
4987 
PopAddress()4988 uintptr_t Simulator::PopAddress() {
4989   int64_t current_sp = get_register(sp);
4990   uintptr_t* stack_slot = reinterpret_cast<uintptr_t*>(current_sp);
4991   uintptr_t address = *stack_slot;
4992   set_register(sp, current_sp + sizeof(uintptr_t));
4993   return address;
4994 }
4995 
4996 
4997 #undef UNSUPPORTED
4998 }  // namespace internal
4999 }  // namespace v8
5000 
5001 #endif  // USE_SIMULATOR
5002 
5003 #endif  // V8_TARGET_ARCH_MIPS64
5004