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