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