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