simulator-mips.cc revision 257744e915dfc84d6d07a6b2accf8402d9ffc708
1// Copyright 2011 the V8 project authors. All rights reserved.
2// Redistribution and use in source and binary forms, with or without
3// modification, are permitted provided that the following conditions are
4// met:
5//
6//     * Redistributions of source code must retain the above copyright
7//       notice, this list of conditions and the following disclaimer.
8//     * Redistributions in binary form must reproduce the above
9//       copyright notice, this list of conditions and the following
10//       disclaimer in the documentation and/or other materials provided
11//       with the distribution.
12//     * Neither the name of Google Inc. nor the names of its
13//       contributors may be used to endorse or promote products derived
14//       from this software without specific prior written permission.
15//
16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
28#include <stdlib.h>
29#include <math.h>
30#include <limits.h>
31#include <cstdarg>
32#include "v8.h"
33
34#if defined(V8_TARGET_ARCH_MIPS)
35
36#include "disasm.h"
37#include "assembler.h"
38#include "globals.h"    // Need the BitCast.
39#include "mips/constants-mips.h"
40#include "mips/simulator-mips.h"
41
42
43// Only build the simulator if not compiling for real MIPS hardware.
44#if defined(USE_SIMULATOR)
45
46namespace v8 {
47namespace internal {
48
49// Utils functions.
50bool HaveSameSign(int32_t a, int32_t b) {
51  return ((a ^ b) >= 0);
52}
53
54
55uint32_t get_fcsr_condition_bit(uint32_t cc) {
56  if (cc == 0) {
57    return 23;
58  } else {
59    return 24 + cc;
60  }
61}
62
63
64// This macro provides a platform independent use of sscanf. The reason for
65// SScanF not being implemented in a platform independent was through
66// ::v8::internal::OS in the same way as SNPrintF is that the Windows C Run-Time
67// Library does not provide vsscanf.
68#define SScanF sscanf  // NOLINT
69
70// The MipsDebugger class is used by the simulator while debugging simulated
71// code.
72class MipsDebugger {
73 public:
74  explicit MipsDebugger(Simulator* sim);
75  ~MipsDebugger();
76
77  void Stop(Instruction* instr);
78  void Debug();
79  // Print all registers with a nice formatting.
80  void PrintAllRegs();
81  void PrintAllRegsIncludingFPU();
82
83 private:
84  // We set the breakpoint code to 0xfffff to easily recognize it.
85  static const Instr kBreakpointInstr = SPECIAL | BREAK | 0xfffff << 6;
86  static const Instr kNopInstr =  0x0;
87
88  Simulator* sim_;
89
90  int32_t GetRegisterValue(int regnum);
91  int32_t GetFPURegisterValueInt(int regnum);
92  int64_t GetFPURegisterValueLong(int regnum);
93  float GetFPURegisterValueFloat(int regnum);
94  double GetFPURegisterValueDouble(int regnum);
95  bool GetValue(const char* desc, int32_t* value);
96
97  // Set or delete a breakpoint. Returns true if successful.
98  bool SetBreakpoint(Instruction* breakpc);
99  bool DeleteBreakpoint(Instruction* breakpc);
100
101  // Undo and redo all breakpoints. This is needed to bracket disassembly and
102  // execution to skip past breakpoints when run from the debugger.
103  void UndoBreakpoints();
104  void RedoBreakpoints();
105};
106
107MipsDebugger::MipsDebugger(Simulator* sim) {
108  sim_ = sim;
109}
110
111
112MipsDebugger::~MipsDebugger() {
113}
114
115
116#ifdef GENERATED_CODE_COVERAGE
117static FILE* coverage_log = NULL;
118
119
120static void InitializeCoverage() {
121  char* file_name = getenv("V8_GENERATED_CODE_COVERAGE_LOG");
122  if (file_name != NULL) {
123    coverage_log = fopen(file_name, "aw+");
124  }
125}
126
127
128void MipsDebugger::Stop(Instruction* instr) {
129  UNIMPLEMENTED_MIPS();
130  char* str = reinterpret_cast<char*>(instr->InstructionBits());
131  if (strlen(str) > 0) {
132    if (coverage_log != NULL) {
133      fprintf(coverage_log, "%s\n", str);
134      fflush(coverage_log);
135    }
136    instr->SetInstructionBits(0x0);  // Overwrite with nop.
137  }
138  sim_->set_pc(sim_->get_pc() + Instruction::kInstrSize);
139}
140
141
142#else  // GENERATED_CODE_COVERAGE
143
144#define UNSUPPORTED() printf("Unsupported instruction.\n");
145
146static void InitializeCoverage() {}
147
148
149void MipsDebugger::Stop(Instruction* instr) {
150  const char* str = reinterpret_cast<char*>(instr->InstructionBits());
151  PrintF("Simulator hit %s\n", str);
152  sim_->set_pc(sim_->get_pc() + Instruction::kInstrSize);
153  Debug();
154}
155#endif  // GENERATED_CODE_COVERAGE
156
157
158int32_t MipsDebugger::GetRegisterValue(int regnum) {
159  if (regnum == kNumSimuRegisters) {
160    return sim_->get_pc();
161  } else {
162    return sim_->get_register(regnum);
163  }
164}
165
166
167int32_t MipsDebugger::GetFPURegisterValueInt(int regnum) {
168  if (regnum == kNumFPURegisters) {
169    return sim_->get_pc();
170  } else {
171    return sim_->get_fpu_register(regnum);
172  }
173}
174
175
176int64_t MipsDebugger::GetFPURegisterValueLong(int regnum) {
177  if (regnum == kNumFPURegisters) {
178    return sim_->get_pc();
179  } else {
180    return sim_->get_fpu_register_long(regnum);
181  }
182}
183
184
185float MipsDebugger::GetFPURegisterValueFloat(int regnum) {
186  if (regnum == kNumFPURegisters) {
187    return sim_->get_pc();
188  } else {
189    return sim_->get_fpu_register_float(regnum);
190  }
191}
192
193
194double MipsDebugger::GetFPURegisterValueDouble(int regnum) {
195  if (regnum == kNumFPURegisters) {
196    return sim_->get_pc();
197  } else {
198    return sim_->get_fpu_register_double(regnum);
199  }
200}
201
202
203bool MipsDebugger::GetValue(const char* desc, int32_t* value) {
204  int regnum = Registers::Number(desc);
205  int fpuregnum = FPURegisters::Number(desc);
206
207  if (regnum != kInvalidRegister) {
208    *value = GetRegisterValue(regnum);
209    return true;
210  } else if (fpuregnum != kInvalidFPURegister) {
211    *value = GetFPURegisterValueInt(fpuregnum);
212    return true;
213  } else if (strncmp(desc, "0x", 2) == 0) {
214    return SScanF(desc, "%x", reinterpret_cast<uint32_t*>(value)) == 1;
215  } else {
216    return SScanF(desc, "%i", value) == 1;
217  }
218  return false;
219}
220
221
222bool MipsDebugger::SetBreakpoint(Instruction* breakpc) {
223  // Check if a breakpoint can be set. If not return without any side-effects.
224  if (sim_->break_pc_ != NULL) {
225    return false;
226  }
227
228  // Set the breakpoint.
229  sim_->break_pc_ = breakpc;
230  sim_->break_instr_ = breakpc->InstructionBits();
231  // Not setting the breakpoint instruction in the code itself. It will be set
232  // when the debugger shell continues.
233  return true;
234}
235
236
237bool MipsDebugger::DeleteBreakpoint(Instruction* breakpc) {
238  if (sim_->break_pc_ != NULL) {
239    sim_->break_pc_->SetInstructionBits(sim_->break_instr_);
240  }
241
242  sim_->break_pc_ = NULL;
243  sim_->break_instr_ = 0;
244  return true;
245}
246
247
248void MipsDebugger::UndoBreakpoints() {
249  if (sim_->break_pc_ != NULL) {
250    sim_->break_pc_->SetInstructionBits(sim_->break_instr_);
251  }
252}
253
254
255void MipsDebugger::RedoBreakpoints() {
256  if (sim_->break_pc_ != NULL) {
257    sim_->break_pc_->SetInstructionBits(kBreakpointInstr);
258  }
259}
260
261
262void MipsDebugger::PrintAllRegs() {
263#define REG_INFO(n) Registers::Name(n), GetRegisterValue(n), GetRegisterValue(n)
264
265  PrintF("\n");
266  // at, v0, a0.
267  PrintF("%3s: 0x%08x %10d\t%3s: 0x%08x %10d\t%3s: 0x%08x %10d\n",
268         REG_INFO(1), REG_INFO(2), REG_INFO(4));
269  // v1, a1.
270  PrintF("%26s\t%3s: 0x%08x %10d\t%3s: 0x%08x %10d\n",
271         "", REG_INFO(3), REG_INFO(5));
272  // a2.
273  PrintF("%26s\t%26s\t%3s: 0x%08x %10d\n", "", "", REG_INFO(6));
274  // a3.
275  PrintF("%26s\t%26s\t%3s: 0x%08x %10d\n", "", "", REG_INFO(7));
276  PrintF("\n");
277  // t0-t7, s0-s7
278  for (int i = 0; i < 8; i++) {
279    PrintF("%3s: 0x%08x %10d\t%3s: 0x%08x %10d\n",
280           REG_INFO(8+i), REG_INFO(16+i));
281  }
282  PrintF("\n");
283  // t8, k0, LO.
284  PrintF("%3s: 0x%08x %10d\t%3s: 0x%08x %10d\t%3s: 0x%08x %10d\n",
285         REG_INFO(24), REG_INFO(26), REG_INFO(32));
286  // t9, k1, HI.
287  PrintF("%3s: 0x%08x %10d\t%3s: 0x%08x %10d\t%3s: 0x%08x %10d\n",
288         REG_INFO(25), REG_INFO(27), REG_INFO(33));
289  // sp, fp, gp.
290  PrintF("%3s: 0x%08x %10d\t%3s: 0x%08x %10d\t%3s: 0x%08x %10d\n",
291         REG_INFO(29), REG_INFO(30), REG_INFO(28));
292  // pc.
293  PrintF("%3s: 0x%08x %10d\t%3s: 0x%08x %10d\n",
294         REG_INFO(31), REG_INFO(34));
295
296#undef REG_INFO
297#undef FPU_REG_INFO
298}
299
300
301void MipsDebugger::PrintAllRegsIncludingFPU() {
302#define FPU_REG_INFO(n) FPURegisters::Name(n), FPURegisters::Name(n+1), \
303        GetFPURegisterValueInt(n+1), \
304        GetFPURegisterValueInt(n), \
305                        GetFPURegisterValueDouble(n)
306
307  PrintAllRegs();
308
309  PrintF("\n\n");
310  // f0, f1, f2, ... f31.
311  PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO(0) );
312  PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO(2) );
313  PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO(4) );
314  PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO(6) );
315  PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO(8) );
316  PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO(10));
317  PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO(12));
318  PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO(14));
319  PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO(16));
320  PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO(18));
321  PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO(20));
322  PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO(22));
323  PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO(24));
324  PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO(26));
325  PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO(28));
326  PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO(30));
327
328#undef REG_INFO
329#undef FPU_REG_INFO
330}
331
332
333void MipsDebugger::Debug() {
334  intptr_t last_pc = -1;
335  bool done = false;
336
337#define COMMAND_SIZE 63
338#define ARG_SIZE 255
339
340#define STR(a) #a
341#define XSTR(a) STR(a)
342
343  char cmd[COMMAND_SIZE + 1];
344  char arg1[ARG_SIZE + 1];
345  char arg2[ARG_SIZE + 1];
346  char* argv[3] = { cmd, arg1, arg2 };
347
348  // Make sure to have a proper terminating character if reaching the limit.
349  cmd[COMMAND_SIZE] = 0;
350  arg1[ARG_SIZE] = 0;
351  arg2[ARG_SIZE] = 0;
352
353  // Undo all set breakpoints while running in the debugger shell. This will
354  // make them invisible to all commands.
355  UndoBreakpoints();
356
357  while (!done && (sim_->get_pc() != Simulator::end_sim_pc)) {
358    if (last_pc != sim_->get_pc()) {
359      disasm::NameConverter converter;
360      disasm::Disassembler dasm(converter);
361      // Use a reasonably large buffer.
362      v8::internal::EmbeddedVector<char, 256> buffer;
363      dasm.InstructionDecode(buffer,
364                             reinterpret_cast<byte*>(sim_->get_pc()));
365      PrintF("  0x%08x  %s\n", sim_->get_pc(), buffer.start());
366      last_pc = sim_->get_pc();
367    }
368    char* line = ReadLine("sim> ");
369    if (line == NULL) {
370      break;
371    } else {
372      // Use sscanf to parse the individual parts of the command line. At the
373      // moment no command expects more than two parameters.
374      int argc = SScanF(line,
375                        "%" XSTR(COMMAND_SIZE) "s "
376                        "%" XSTR(ARG_SIZE) "s "
377                        "%" XSTR(ARG_SIZE) "s",
378                        cmd, arg1, arg2);
379      if ((strcmp(cmd, "si") == 0) || (strcmp(cmd, "stepi") == 0)) {
380        Instruction* instr = reinterpret_cast<Instruction*>(sim_->get_pc());
381        if (!(instr->IsTrap()) ||
382            instr->InstructionBits() == rtCallRedirInstr) {
383          sim_->InstructionDecode(
384              reinterpret_cast<Instruction*>(sim_->get_pc()));
385        } else {
386          // Allow si to jump over generated breakpoints.
387          PrintF("/!\\ Jumping over generated breakpoint.\n");
388          sim_->set_pc(sim_->get_pc() + Instruction::kInstrSize);
389        }
390      } else if ((strcmp(cmd, "c") == 0) || (strcmp(cmd, "cont") == 0)) {
391        // Execute the one instruction we broke at with breakpoints disabled.
392        sim_->InstructionDecode(reinterpret_cast<Instruction*>(sim_->get_pc()));
393        // Leave the debugger shell.
394        done = true;
395      } else if ((strcmp(cmd, "p") == 0) || (strcmp(cmd, "print") == 0)) {
396        if (argc == 2) {
397          int32_t value;
398          float fvalue;
399          if (strcmp(arg1, "all") == 0) {
400            PrintAllRegs();
401          } else if (strcmp(arg1, "allf") == 0) {
402            PrintAllRegsIncludingFPU();
403          } else {
404            int regnum = Registers::Number(arg1);
405            int fpuregnum = FPURegisters::Number(arg1);
406
407            if (regnum != kInvalidRegister) {
408              value = GetRegisterValue(regnum);
409              PrintF("%s: 0x%08x %d \n", arg1, value, value);
410            } else if (fpuregnum != kInvalidFPURegister) {
411              if (fpuregnum % 2 == 1) {
412                value = GetFPURegisterValueInt(fpuregnum);
413                fvalue = GetFPURegisterValueFloat(fpuregnum);
414                PrintF("%s: 0x%08x %11.4e\n", arg1, value, fvalue);
415              } else {
416                double dfvalue;
417                int32_t lvalue1 = GetFPURegisterValueInt(fpuregnum);
418                int32_t lvalue2 = GetFPURegisterValueInt(fpuregnum + 1);
419                dfvalue = GetFPURegisterValueDouble(fpuregnum);
420                PrintF("%3s,%3s: 0x%08x%08x %16.4e\n",
421                       FPURegisters::Name(fpuregnum+1),
422                       FPURegisters::Name(fpuregnum),
423                       lvalue1,
424                       lvalue2,
425                       dfvalue);
426              }
427            } else {
428              PrintF("%s unrecognized\n", arg1);
429            }
430          }
431        } else {
432          if (argc == 3) {
433            if (strcmp(arg2, "single") == 0) {
434              int32_t value;
435              float fvalue;
436              int fpuregnum = FPURegisters::Number(arg1);
437
438              if (fpuregnum != kInvalidFPURegister) {
439                value = GetFPURegisterValueInt(fpuregnum);
440                fvalue = GetFPURegisterValueFloat(fpuregnum);
441                PrintF("%s: 0x%08x %11.4e\n", arg1, value, fvalue);
442              } else {
443                PrintF("%s unrecognized\n", arg1);
444              }
445            } else {
446              PrintF("print <fpu register> single\n");
447            }
448          } else {
449            PrintF("print <register> or print <fpu register> single\n");
450          }
451        }
452      } else if ((strcmp(cmd, "po") == 0)
453                 || (strcmp(cmd, "printobject") == 0)) {
454        if (argc == 2) {
455          int32_t value;
456          if (GetValue(arg1, &value)) {
457            Object* obj = reinterpret_cast<Object*>(value);
458            PrintF("%s: \n", arg1);
459#ifdef DEBUG
460            obj->PrintLn();
461#else
462            obj->ShortPrint();
463            PrintF("\n");
464#endif
465          } else {
466            PrintF("%s unrecognized\n", arg1);
467          }
468        } else {
469          PrintF("printobject <value>\n");
470        }
471      } else if (strcmp(cmd, "stack") == 0 || strcmp(cmd, "mem") == 0) {
472        int32_t* cur = NULL;
473        int32_t* end = NULL;
474        int next_arg = 1;
475
476        if (strcmp(cmd, "stack") == 0) {
477          cur = reinterpret_cast<int32_t*>(sim_->get_register(Simulator::sp));
478        } else {  // Command "mem".
479          int32_t value;
480          if (!GetValue(arg1, &value)) {
481            PrintF("%s unrecognized\n", arg1);
482            continue;
483          }
484          cur = reinterpret_cast<int32_t*>(value);
485          next_arg++;
486        }
487
488        int32_t words;
489        if (argc == next_arg) {
490          words = 10;
491        } else if (argc == next_arg + 1) {
492          if (!GetValue(argv[next_arg], &words)) {
493            words = 10;
494          }
495        }
496        end = cur + words;
497
498        while (cur < end) {
499          PrintF("  0x%08x:  0x%08x %10d",
500                 reinterpret_cast<intptr_t>(cur), *cur, *cur);
501          HeapObject* obj = reinterpret_cast<HeapObject*>(*cur);
502          int value = *cur;
503          Heap* current_heap = v8::internal::Isolate::Current()->heap();
504          if (current_heap->Contains(obj) || ((value & 1) == 0)) {
505            PrintF(" (");
506            if ((value & 1) == 0) {
507              PrintF("smi %d", value / 2);
508            } else {
509              obj->ShortPrint();
510            }
511            PrintF(")");
512          }
513          PrintF("\n");
514          cur++;
515        }
516
517      } else if ((strcmp(cmd, "disasm") == 0) ||
518                 (strcmp(cmd, "dpc") == 0) ||
519                 (strcmp(cmd, "di") == 0)) {
520        disasm::NameConverter converter;
521        disasm::Disassembler dasm(converter);
522        // Use a reasonably large buffer.
523        v8::internal::EmbeddedVector<char, 256> buffer;
524
525        byte* cur = NULL;
526        byte* end = NULL;
527
528        if (argc == 1) {
529          cur = reinterpret_cast<byte*>(sim_->get_pc());
530          end = cur + (10 * Instruction::kInstrSize);
531        } else if (argc == 2) {
532          int regnum = Registers::Number(arg1);
533          if (regnum != kInvalidRegister || strncmp(arg1, "0x", 2) == 0) {
534            // The argument is an address or a register name.
535            int32_t value;
536            if (GetValue(arg1, &value)) {
537              cur = reinterpret_cast<byte*>(value);
538              // Disassemble 10 instructions at <arg1>.
539              end = cur + (10 * Instruction::kInstrSize);
540            }
541          } else {
542            // The argument is the number of instructions.
543            int32_t value;
544            if (GetValue(arg1, &value)) {
545              cur = reinterpret_cast<byte*>(sim_->get_pc());
546              // Disassemble <arg1> instructions.
547              end = cur + (value * Instruction::kInstrSize);
548            }
549          }
550        } else {
551          int32_t value1;
552          int32_t value2;
553          if (GetValue(arg1, &value1) && GetValue(arg2, &value2)) {
554            cur = reinterpret_cast<byte*>(value1);
555            end = cur + (value2 * Instruction::kInstrSize);
556          }
557        }
558
559        while (cur < end) {
560          dasm.InstructionDecode(buffer, cur);
561          PrintF("  0x%08x  %s\n",
562              reinterpret_cast<intptr_t>(cur), buffer.start());
563          cur += Instruction::kInstrSize;
564        }
565      } else if (strcmp(cmd, "gdb") == 0) {
566        PrintF("relinquishing control to gdb\n");
567        v8::internal::OS::DebugBreak();
568        PrintF("regaining control from gdb\n");
569      } else if (strcmp(cmd, "break") == 0) {
570        if (argc == 2) {
571          int32_t value;
572          if (GetValue(arg1, &value)) {
573            if (!SetBreakpoint(reinterpret_cast<Instruction*>(value))) {
574              PrintF("setting breakpoint failed\n");
575            }
576          } else {
577            PrintF("%s unrecognized\n", arg1);
578          }
579        } else {
580          PrintF("break <address>\n");
581        }
582      } else if (strcmp(cmd, "del") == 0) {
583        if (!DeleteBreakpoint(NULL)) {
584          PrintF("deleting breakpoint failed\n");
585        }
586      } else if (strcmp(cmd, "flags") == 0) {
587        PrintF("No flags on MIPS !\n");
588      } else if (strcmp(cmd, "unstop") == 0) {
589          PrintF("Unstop command not implemented on MIPS.");
590      } else if ((strcmp(cmd, "stat") == 0) || (strcmp(cmd, "st") == 0)) {
591        // Print registers and disassemble.
592        PrintAllRegs();
593        PrintF("\n");
594
595        disasm::NameConverter converter;
596        disasm::Disassembler dasm(converter);
597        // Use a reasonably large buffer.
598        v8::internal::EmbeddedVector<char, 256> buffer;
599
600        byte* cur = NULL;
601        byte* end = NULL;
602
603        if (argc == 1) {
604          cur = reinterpret_cast<byte*>(sim_->get_pc());
605          end = cur + (10 * Instruction::kInstrSize);
606        } else if (argc == 2) {
607          int32_t value;
608          if (GetValue(arg1, &value)) {
609            cur = reinterpret_cast<byte*>(value);
610            // no length parameter passed, assume 10 instructions
611            end = cur + (10 * Instruction::kInstrSize);
612          }
613        } else {
614          int32_t value1;
615          int32_t value2;
616          if (GetValue(arg1, &value1) && GetValue(arg2, &value2)) {
617            cur = reinterpret_cast<byte*>(value1);
618            end = cur + (value2 * Instruction::kInstrSize);
619          }
620        }
621
622        while (cur < end) {
623          dasm.InstructionDecode(buffer, cur);
624          PrintF("  0x%08x  %s\n",
625                 reinterpret_cast<intptr_t>(cur), buffer.start());
626          cur += Instruction::kInstrSize;
627        }
628      } else if ((strcmp(cmd, "h") == 0) || (strcmp(cmd, "help") == 0)) {
629        PrintF("cont\n");
630        PrintF("  continue execution (alias 'c')\n");
631        PrintF("stepi\n");
632        PrintF("  step one instruction (alias 'si')\n");
633        PrintF("print <register>\n");
634        PrintF("  print register content (alias 'p')\n");
635        PrintF("  use register name 'all' to print all registers\n");
636        PrintF("printobject <register>\n");
637        PrintF("  print an object from a register (alias 'po')\n");
638        PrintF("stack [<words>]\n");
639        PrintF("  dump stack content, default dump 10 words)\n");
640        PrintF("mem <address> [<words>]\n");
641        PrintF("  dump memory content, default dump 10 words)\n");
642        PrintF("flags\n");
643        PrintF("  print flags\n");
644        PrintF("disasm [<instructions>]\n");
645        PrintF("disasm [<address/register>]\n");
646        PrintF("disasm [[<address/register>] <instructions>]\n");
647        PrintF("  disassemble code, default is 10 instructions\n");
648        PrintF("  from pc (alias 'di')\n");
649        PrintF("gdb\n");
650        PrintF("  enter gdb\n");
651        PrintF("break <address>\n");
652        PrintF("  set a break point on the address\n");
653        PrintF("del\n");
654        PrintF("  delete the breakpoint\n");
655        PrintF("unstop\n");
656        PrintF("  ignore the stop instruction at the current location");
657        PrintF(" from now on\n");
658      } else {
659        PrintF("Unknown command: %s\n", cmd);
660      }
661    }
662    DeleteArray(line);
663  }
664
665  // Add all the breakpoints back to stop execution and enter the debugger
666  // shell when hit.
667  RedoBreakpoints();
668
669#undef COMMAND_SIZE
670#undef ARG_SIZE
671
672#undef STR
673#undef XSTR
674}
675
676
677static bool ICacheMatch(void* one, void* two) {
678  ASSERT((reinterpret_cast<intptr_t>(one) & CachePage::kPageMask) == 0);
679  ASSERT((reinterpret_cast<intptr_t>(two) & CachePage::kPageMask) == 0);
680  return one == two;
681}
682
683
684static uint32_t ICacheHash(void* key) {
685  return static_cast<uint32_t>(reinterpret_cast<uintptr_t>(key)) >> 2;
686}
687
688
689static bool AllOnOnePage(uintptr_t start, int size) {
690  intptr_t start_page = (start & ~CachePage::kPageMask);
691  intptr_t end_page = ((start + size) & ~CachePage::kPageMask);
692  return start_page == end_page;
693}
694
695
696void Simulator::FlushICache(v8::internal::HashMap* i_cache,
697                            void* start_addr,
698                            size_t size) {
699  intptr_t start = reinterpret_cast<intptr_t>(start_addr);
700  int intra_line = (start & CachePage::kLineMask);
701  start -= intra_line;
702  size += intra_line;
703  size = ((size - 1) | CachePage::kLineMask) + 1;
704  int offset = (start & CachePage::kPageMask);
705  while (!AllOnOnePage(start, size - 1)) {
706    int bytes_to_flush = CachePage::kPageSize - offset;
707    FlushOnePage(i_cache, start, bytes_to_flush);
708    start += bytes_to_flush;
709    size -= bytes_to_flush;
710    ASSERT_EQ(0, start & CachePage::kPageMask);
711    offset = 0;
712  }
713  if (size != 0) {
714    FlushOnePage(i_cache, start, size);
715  }
716}
717
718
719CachePage* Simulator::GetCachePage(v8::internal::HashMap* i_cache, void* page) {
720  v8::internal::HashMap::Entry* entry = i_cache->Lookup(page,
721                                                        ICacheHash(page),
722                                                        true);
723  if (entry->value == NULL) {
724    CachePage* new_page = new CachePage();
725    entry->value = new_page;
726  }
727  return reinterpret_cast<CachePage*>(entry->value);
728}
729
730
731// Flush from start up to and not including start + size.
732void Simulator::FlushOnePage(v8::internal::HashMap* i_cache,
733                             intptr_t start,
734                             int size) {
735  ASSERT(size <= CachePage::kPageSize);
736  ASSERT(AllOnOnePage(start, size - 1));
737  ASSERT((start & CachePage::kLineMask) == 0);
738  ASSERT((size & CachePage::kLineMask) == 0);
739  void* page = reinterpret_cast<void*>(start & (~CachePage::kPageMask));
740  int offset = (start & CachePage::kPageMask);
741  CachePage* cache_page = GetCachePage(i_cache, page);
742  char* valid_bytemap = cache_page->ValidityByte(offset);
743  memset(valid_bytemap, CachePage::LINE_INVALID, size >> CachePage::kLineShift);
744}
745
746
747void Simulator::CheckICache(v8::internal::HashMap* i_cache,
748                            Instruction* instr) {
749  intptr_t address = reinterpret_cast<intptr_t>(instr);
750  void* page = reinterpret_cast<void*>(address & (~CachePage::kPageMask));
751  void* line = reinterpret_cast<void*>(address & (~CachePage::kLineMask));
752  int offset = (address & CachePage::kPageMask);
753  CachePage* cache_page = GetCachePage(i_cache, page);
754  char* cache_valid_byte = cache_page->ValidityByte(offset);
755  bool cache_hit = (*cache_valid_byte == CachePage::LINE_VALID);
756  char* cached_line = cache_page->CachedData(offset & ~CachePage::kLineMask);
757  if (cache_hit) {
758    // Check that the data in memory matches the contents of the I-cache.
759    CHECK(memcmp(reinterpret_cast<void*>(instr),
760                 cache_page->CachedData(offset),
761                 Instruction::kInstrSize) == 0);
762  } else {
763    // Cache miss.  Load memory into the cache.
764    memcpy(cached_line, line, CachePage::kLineLength);
765    *cache_valid_byte = CachePage::LINE_VALID;
766  }
767}
768
769
770void Simulator::Initialize(Isolate* isolate) {
771  if (isolate->simulator_initialized()) return;
772  isolate->set_simulator_initialized(true);
773  ::v8::internal::ExternalReference::set_redirector(isolate,
774                                                    &RedirectExternalReference);
775}
776
777
778Simulator::Simulator(Isolate* isolate) : isolate_(isolate) {
779  i_cache_ = isolate_->simulator_i_cache();
780  if (i_cache_ == NULL) {
781    i_cache_ = new v8::internal::HashMap(&ICacheMatch);
782    isolate_->set_simulator_i_cache(i_cache_);
783  }
784  Initialize(isolate);
785  // Setup simulator support first. Some of this information is needed to
786  // setup the architecture state.
787  stack_ = reinterpret_cast<char*>(malloc(stack_size_));
788  pc_modified_ = false;
789  icount_ = 0;
790  break_count_ = 0;
791  break_pc_ = NULL;
792  break_instr_ = 0;
793
794  // Setup architecture state.
795  // All registers are initialized to zero to start with.
796  for (int i = 0; i < kNumSimuRegisters; i++) {
797    registers_[i] = 0;
798  }
799  for (int i = 0; i < kNumFPURegisters; i++) {
800    FPUregisters_[i] = 0;
801  }
802  FCSR_ = 0;
803
804  // The sp is initialized to point to the bottom (high address) of the
805  // allocated stack area. To be safe in potential stack underflows we leave
806  // some buffer below.
807  registers_[sp] = reinterpret_cast<int32_t>(stack_) + stack_size_ - 64;
808  // The ra and pc are initialized to a known bad value that will cause an
809  // access violation if the simulator ever tries to execute it.
810  registers_[pc] = bad_ra;
811  registers_[ra] = bad_ra;
812  InitializeCoverage();
813  for (int i = 0; i < kNumExceptions; i++) {
814    exceptions[i] = 0;
815  }
816}
817
818
819// When the generated code calls an external reference we need to catch that in
820// the simulator.  The external reference will be a function compiled for the
821// host architecture.  We need to call that function instead of trying to
822// execute it with the simulator.  We do that by redirecting the external
823// reference to a swi (software-interrupt) instruction that is handled by
824// the simulator.  We write the original destination of the jump just at a known
825// offset from the swi instruction so the simulator knows what to call.
826class Redirection {
827 public:
828  Redirection(void* external_function, ExternalReference::Type type)
829      : external_function_(external_function),
830        swi_instruction_(rtCallRedirInstr),
831        type_(type),
832        next_(NULL) {
833    Isolate* isolate = Isolate::Current();
834    next_ = isolate->simulator_redirection();
835    Simulator::current(isolate)->
836        FlushICache(isolate->simulator_i_cache(),
837                    reinterpret_cast<void*>(&swi_instruction_),
838                    Instruction::kInstrSize);
839    isolate->set_simulator_redirection(this);
840  }
841
842  void* address_of_swi_instruction() {
843    return reinterpret_cast<void*>(&swi_instruction_);
844  }
845
846  void* external_function() { return external_function_; }
847  ExternalReference::Type type() { return type_; }
848
849  static Redirection* Get(void* external_function,
850                          ExternalReference::Type type) {
851    Isolate* isolate = Isolate::Current();
852    Redirection* current = isolate->simulator_redirection();
853    for (; current != NULL; current = current->next_) {
854      if (current->external_function_ == external_function) return current;
855    }
856    return new Redirection(external_function, type);
857  }
858
859  static Redirection* FromSwiInstruction(Instruction* swi_instruction) {
860    char* addr_of_swi = reinterpret_cast<char*>(swi_instruction);
861    char* addr_of_redirection =
862        addr_of_swi - OFFSET_OF(Redirection, swi_instruction_);
863    return reinterpret_cast<Redirection*>(addr_of_redirection);
864  }
865
866 private:
867  void* external_function_;
868  uint32_t swi_instruction_;
869  ExternalReference::Type type_;
870  Redirection* next_;
871};
872
873
874void* Simulator::RedirectExternalReference(void* external_function,
875                                           ExternalReference::Type type) {
876  Redirection* redirection = Redirection::Get(external_function, type);
877  return redirection->address_of_swi_instruction();
878}
879
880
881// Get the active Simulator for the current thread.
882Simulator* Simulator::current(Isolate* isolate) {
883  v8::internal::Isolate::PerIsolateThreadData* isolate_data =
884       isolate->FindOrAllocatePerThreadDataForThisThread();
885  ASSERT(isolate_data != NULL);
886  ASSERT(isolate_data != NULL);
887
888  Simulator* sim = isolate_data->simulator();
889  if (sim == NULL) {
890    // TODO(146): delete the simulator object when a thread/isolate goes away.
891    sim = new Simulator(isolate);
892    isolate_data->set_simulator(sim);
893  }
894  return sim;
895}
896
897
898// Sets the register in the architecture state. It will also deal with updating
899// Simulator internal state for special registers such as PC.
900void Simulator::set_register(int reg, int32_t value) {
901  ASSERT((reg >= 0) && (reg < kNumSimuRegisters));
902  if (reg == pc) {
903    pc_modified_ = true;
904  }
905
906  // Zero register always holds 0.
907  registers_[reg] = (reg == 0) ? 0 : value;
908}
909
910
911void Simulator::set_fpu_register(int fpureg, int32_t value) {
912  ASSERT((fpureg >= 0) && (fpureg < kNumFPURegisters));
913  FPUregisters_[fpureg] = value;
914}
915
916
917void Simulator::set_fpu_register_float(int fpureg, float value) {
918  ASSERT((fpureg >= 0) && (fpureg < kNumFPURegisters));
919  *BitCast<float*>(&FPUregisters_[fpureg]) = value;
920}
921
922
923void Simulator::set_fpu_register_double(int fpureg, double value) {
924  ASSERT((fpureg >= 0) && (fpureg < kNumFPURegisters) && ((fpureg % 2) == 0));
925  *BitCast<double*>(&FPUregisters_[fpureg]) = value;
926}
927
928
929// Get the register from the architecture state. This function does handle
930// the special case of accessing the PC register.
931int32_t Simulator::get_register(int reg) const {
932  ASSERT((reg >= 0) && (reg < kNumSimuRegisters));
933  if (reg == 0)
934    return 0;
935  else
936    return registers_[reg] + ((reg == pc) ? Instruction::kPCReadOffset : 0);
937}
938
939
940int32_t Simulator::get_fpu_register(int fpureg) const {
941  ASSERT((fpureg >= 0) && (fpureg < kNumFPURegisters));
942  return FPUregisters_[fpureg];
943}
944
945
946int64_t Simulator::get_fpu_register_long(int fpureg) const {
947  ASSERT((fpureg >= 0) && (fpureg < kNumFPURegisters) && ((fpureg % 2) == 0));
948  return *BitCast<int64_t*>(
949      const_cast<int32_t*>(&FPUregisters_[fpureg]));
950}
951
952
953float Simulator::get_fpu_register_float(int fpureg) const {
954  ASSERT((fpureg >= 0) && (fpureg < kNumFPURegisters));
955  return *BitCast<float*>(
956      const_cast<int32_t*>(&FPUregisters_[fpureg]));
957}
958
959
960double Simulator::get_fpu_register_double(int fpureg) const {
961  ASSERT((fpureg >= 0) && (fpureg < kNumFPURegisters) && ((fpureg % 2) == 0));
962  return *BitCast<double*>(const_cast<int32_t*>(&FPUregisters_[fpureg]));
963}
964
965
966// For use in calls that take two double values, constructed either
967// from a0-a3 or f12 and f14.
968void Simulator::GetFpArgs(double* x, double* y) {
969  if (!IsMipsSoftFloatABI) {
970    *x = get_fpu_register_double(12);
971    *y = get_fpu_register_double(14);
972  } else {
973    // We use a char buffer to get around the strict-aliasing rules which
974    // otherwise allow the compiler to optimize away the copy.
975    char buffer[sizeof(*x)];
976    int32_t* reg_buffer = reinterpret_cast<int32_t*>(buffer);
977
978    // Registers a0 and a1 -> x.
979    reg_buffer[0] = get_register(a0);
980    reg_buffer[1] = get_register(a1);
981    memcpy(x, buffer, sizeof(buffer));
982
983    // Registers a2 and a3 -> y.
984    reg_buffer[0] = get_register(a2);
985    reg_buffer[1] = get_register(a3);
986    memcpy(y, buffer, sizeof(buffer));
987  }
988}
989
990
991// For use in calls that take one double value, constructed either
992// from a0 and a1 or f12.
993void Simulator::GetFpArgs(double* x) {
994  if (!IsMipsSoftFloatABI) {
995    *x = get_fpu_register_double(12);
996  } else {
997    // We use a char buffer to get around the strict-aliasing rules which
998    // otherwise allow the compiler to optimize away the copy.
999    char buffer[sizeof(*x)];
1000    int32_t* reg_buffer = reinterpret_cast<int32_t*>(buffer);
1001    // Registers a0 and a1 -> x.
1002    reg_buffer[0] = get_register(a0);
1003    reg_buffer[1] = get_register(a1);
1004    memcpy(x, buffer, sizeof(buffer));
1005  }
1006}
1007
1008
1009// For use in calls that take one double value constructed either
1010// from a0 and a1 or f12 and one integer value.
1011void Simulator::GetFpArgs(double* x, int32_t* y) {
1012  if (!IsMipsSoftFloatABI) {
1013    *x = get_fpu_register_double(12);
1014    *y = get_register(a2);
1015  } else {
1016    // We use a char buffer to get around the strict-aliasing rules which
1017    // otherwise allow the compiler to optimize away the copy.
1018    char buffer[sizeof(*x)];
1019    int32_t* reg_buffer = reinterpret_cast<int32_t*>(buffer);
1020    // Registers 0 and 1 -> x.
1021    reg_buffer[0] = get_register(a0);
1022    reg_buffer[1] = get_register(a1);
1023    memcpy(x, buffer, sizeof(buffer));
1024
1025    // Register 2 -> y.
1026    reg_buffer[0] = get_register(a2);
1027    memcpy(y, buffer, sizeof(*y));
1028  }
1029}
1030
1031
1032// The return value is either in v0/v1 or f0.
1033void Simulator::SetFpResult(const double& result) {
1034  if (!IsMipsSoftFloatABI) {
1035    set_fpu_register_double(0, result);
1036  } else {
1037    char buffer[2 * sizeof(registers_[0])];
1038    int32_t* reg_buffer = reinterpret_cast<int32_t*>(buffer);
1039    memcpy(buffer, &result, sizeof(buffer));
1040    // Copy result to v0 and v1.
1041    set_register(v0, reg_buffer[0]);
1042    set_register(v1, reg_buffer[1]);
1043  }
1044}
1045
1046
1047// Helper functions for setting and testing the FCSR register's bits.
1048void Simulator::set_fcsr_bit(uint32_t cc, bool value) {
1049  if (value) {
1050    FCSR_ |= (1 << cc);
1051  } else {
1052    FCSR_ &= ~(1 << cc);
1053  }
1054}
1055
1056
1057bool Simulator::test_fcsr_bit(uint32_t cc) {
1058  return FCSR_ & (1 << cc);
1059}
1060
1061
1062// Sets the rounding error codes in FCSR based on the result of the rounding.
1063// Returns true if the operation was invalid.
1064bool Simulator::set_fcsr_round_error(double original, double rounded) {
1065  if (!isfinite(original) ||
1066      rounded > LONG_MAX ||
1067      rounded < LONG_MIN) {
1068    set_fcsr_bit(6, true);  // Invalid operation.
1069    return true;
1070  } else if (original != static_cast<double>(rounded)) {
1071    set_fcsr_bit(2, true);  // Inexact.
1072  }
1073  return false;
1074}
1075
1076
1077// Raw access to the PC register.
1078void Simulator::set_pc(int32_t value) {
1079  pc_modified_ = true;
1080  registers_[pc] = value;
1081}
1082
1083
1084bool Simulator::has_bad_pc() const {
1085  return ((registers_[pc] == bad_ra) || (registers_[pc] == end_sim_pc));
1086}
1087
1088
1089// Raw access to the PC register without the special adjustment when reading.
1090int32_t Simulator::get_pc() const {
1091  return registers_[pc];
1092}
1093
1094
1095// The MIPS cannot do unaligned reads and writes.  On some MIPS platforms an
1096// interrupt is caused.  On others it does a funky rotation thing.  For now we
1097// simply disallow unaligned reads, but at some point we may want to move to
1098// emulating the rotate behaviour.  Note that simulator runs have the runtime
1099// system running directly on the host system and only generated code is
1100// executed in the simulator.  Since the host is typically IA32 we will not
1101// get the correct MIPS-like behaviour on unaligned accesses.
1102
1103int Simulator::ReadW(int32_t addr, Instruction* instr) {
1104  if (addr >=0 && addr < 0x400) {
1105    // This has to be a NULL-dereference, drop into debugger.
1106    MipsDebugger dbg(this);
1107    dbg.Debug();
1108  }
1109  if ((addr & kPointerAlignmentMask) == 0) {
1110    intptr_t* ptr = reinterpret_cast<intptr_t*>(addr);
1111    return *ptr;
1112  }
1113  PrintF("Unaligned read at 0x%08x, pc=0x%08" V8PRIxPTR "\n",
1114         addr,
1115         reinterpret_cast<intptr_t>(instr));
1116  MipsDebugger dbg(this);
1117  dbg.Debug();
1118  return 0;
1119}
1120
1121
1122void Simulator::WriteW(int32_t addr, int value, Instruction* instr) {
1123  if (addr >= 0 && addr < 0x400) {
1124    // This has to be a NULL-dereference, drop into debugger.
1125    MipsDebugger dbg(this);
1126    dbg.Debug();
1127  }
1128  if ((addr & kPointerAlignmentMask) == 0) {
1129    intptr_t* ptr = reinterpret_cast<intptr_t*>(addr);
1130    *ptr = value;
1131    return;
1132  }
1133  PrintF("Unaligned write at 0x%08x, pc=0x%08" V8PRIxPTR "\n",
1134         addr,
1135         reinterpret_cast<intptr_t>(instr));
1136  MipsDebugger dbg(this);
1137  dbg.Debug();
1138}
1139
1140
1141double Simulator::ReadD(int32_t addr, Instruction* instr) {
1142  if ((addr & kDoubleAlignmentMask) == 0) {
1143    double* ptr = reinterpret_cast<double*>(addr);
1144    return *ptr;
1145  }
1146  PrintF("Unaligned (double) read at 0x%08x, pc=0x%08" V8PRIxPTR "\n",
1147         addr,
1148         reinterpret_cast<intptr_t>(instr));
1149  OS::Abort();
1150  return 0;
1151}
1152
1153
1154void Simulator::WriteD(int32_t addr, double value, Instruction* instr) {
1155  if ((addr & kDoubleAlignmentMask) == 0) {
1156    double* ptr = reinterpret_cast<double*>(addr);
1157    *ptr = value;
1158    return;
1159  }
1160  PrintF("Unaligned (double) write at 0x%08x, pc=0x%08" V8PRIxPTR "\n",
1161         addr,
1162         reinterpret_cast<intptr_t>(instr));
1163  OS::Abort();
1164}
1165
1166
1167uint16_t Simulator::ReadHU(int32_t addr, Instruction* instr) {
1168  if ((addr & 1) == 0) {
1169    uint16_t* ptr = reinterpret_cast<uint16_t*>(addr);
1170    return *ptr;
1171  }
1172  PrintF("Unaligned unsigned halfword read at 0x%08x, pc=0x%08" V8PRIxPTR "\n",
1173         addr,
1174         reinterpret_cast<intptr_t>(instr));
1175  OS::Abort();
1176  return 0;
1177}
1178
1179
1180int16_t Simulator::ReadH(int32_t addr, Instruction* instr) {
1181  if ((addr & 1) == 0) {
1182    int16_t* ptr = reinterpret_cast<int16_t*>(addr);
1183    return *ptr;
1184  }
1185  PrintF("Unaligned signed halfword read at 0x%08x, pc=0x%08" V8PRIxPTR "\n",
1186         addr,
1187         reinterpret_cast<intptr_t>(instr));
1188  OS::Abort();
1189  return 0;
1190}
1191
1192
1193void Simulator::WriteH(int32_t addr, uint16_t value, Instruction* instr) {
1194  if ((addr & 1) == 0) {
1195    uint16_t* ptr = reinterpret_cast<uint16_t*>(addr);
1196    *ptr = value;
1197    return;
1198  }
1199  PrintF("Unaligned unsigned halfword write at 0x%08x, pc=0x%08" V8PRIxPTR "\n",
1200         addr,
1201         reinterpret_cast<intptr_t>(instr));
1202  OS::Abort();
1203}
1204
1205
1206void Simulator::WriteH(int32_t addr, int16_t value, Instruction* instr) {
1207  if ((addr & 1) == 0) {
1208    int16_t* ptr = reinterpret_cast<int16_t*>(addr);
1209    *ptr = value;
1210    return;
1211  }
1212  PrintF("Unaligned halfword write at 0x%08x, pc=0x%08" V8PRIxPTR "\n",
1213         addr,
1214         reinterpret_cast<intptr_t>(instr));
1215  OS::Abort();
1216}
1217
1218
1219uint32_t Simulator::ReadBU(int32_t addr) {
1220  uint8_t* ptr = reinterpret_cast<uint8_t*>(addr);
1221  return *ptr & 0xff;
1222}
1223
1224
1225int32_t Simulator::ReadB(int32_t addr) {
1226  int8_t* ptr = reinterpret_cast<int8_t*>(addr);
1227  return *ptr;
1228}
1229
1230
1231void Simulator::WriteB(int32_t addr, uint8_t value) {
1232  uint8_t* ptr = reinterpret_cast<uint8_t*>(addr);
1233  *ptr = value;
1234}
1235
1236
1237void Simulator::WriteB(int32_t addr, int8_t value) {
1238  int8_t* ptr = reinterpret_cast<int8_t*>(addr);
1239  *ptr = value;
1240}
1241
1242
1243// Returns the limit of the stack area to enable checking for stack overflows.
1244uintptr_t Simulator::StackLimit() const {
1245  // Leave a safety margin of 256 bytes to prevent overrunning the stack when
1246  // pushing values.
1247  return reinterpret_cast<uintptr_t>(stack_) + 256;
1248}
1249
1250
1251// Unsupported instructions use Format to print an error and stop execution.
1252void Simulator::Format(Instruction* instr, const char* format) {
1253  PrintF("Simulator found unsupported instruction:\n 0x%08x: %s\n",
1254         reinterpret_cast<intptr_t>(instr), format);
1255  UNIMPLEMENTED_MIPS();
1256}
1257
1258
1259// Calls into the V8 runtime are based on this very simple interface.
1260// Note: To be able to return two values from some calls the code in runtime.cc
1261// uses the ObjectPair which is essentially two 32-bit values stuffed into a
1262// 64-bit value. With the code below we assume that all runtime calls return
1263// 64 bits of result. If they don't, the v1 result register contains a bogus
1264// value, which is fine because it is caller-saved.
1265typedef int64_t (*SimulatorRuntimeCall)(int32_t arg0,
1266                                        int32_t arg1,
1267                                        int32_t arg2,
1268                                        int32_t arg3,
1269                                        int32_t arg4,
1270                                        int32_t arg5);
1271typedef double (*SimulatorRuntimeFPCall)(int32_t arg0,
1272                                         int32_t arg1,
1273                                         int32_t arg2,
1274                                         int32_t arg3);
1275
1276// This signature supports direct call in to API function native callback
1277// (refer to InvocationCallback in v8.h).
1278typedef v8::Handle<v8::Value> (*SimulatorRuntimeDirectApiCall)(int32_t arg0);
1279
1280// This signature supports direct call to accessor getter callback.
1281typedef v8::Handle<v8::Value> (*SimulatorRuntimeDirectGetterCall)(int32_t arg0,
1282                                                                  int32_t arg1);
1283
1284// Software interrupt instructions are used by the simulator to call into the
1285// C-based V8 runtime. They are also used for debugging with simulator.
1286void Simulator::SoftwareInterrupt(Instruction* instr) {
1287  // There are several instructions that could get us here,
1288  // the break_ instruction, or several variants of traps. All
1289  // Are "SPECIAL" class opcode, and are distinuished by function.
1290  int32_t func = instr->FunctionFieldRaw();
1291  int32_t code = (func == BREAK) ? instr->Bits(25, 6) : -1;
1292
1293  // We first check if we met a call_rt_redirected.
1294  if (instr->InstructionBits() == rtCallRedirInstr) {
1295    Redirection* redirection = Redirection::FromSwiInstruction(instr);
1296    int32_t arg0 = get_register(a0);
1297    int32_t arg1 = get_register(a1);
1298    int32_t arg2 = get_register(a2);
1299    int32_t arg3 = get_register(a3);
1300    int32_t arg4 = 0;
1301    int32_t arg5 = 0;
1302
1303    // Need to check if sp is valid before assigning arg4, arg5.
1304    // This is a fix for cctest test-api/CatchStackOverflow which causes
1305    // the stack to overflow. For some reason arm doesn't need this
1306    // stack check here.
1307    int32_t* stack_pointer = reinterpret_cast<int32_t*>(get_register(sp));
1308    int32_t* stack = reinterpret_cast<int32_t*>(stack_);
1309    if (stack_pointer >= stack && stack_pointer < stack + stack_size_ - 5) {
1310      // Args 4 and 5 are on the stack after the reserved space for args 0..3.
1311      arg4 = stack_pointer[4];
1312      arg5 = stack_pointer[5];
1313    }
1314
1315    bool fp_call =
1316         (redirection->type() == ExternalReference::BUILTIN_FP_FP_CALL) ||
1317         (redirection->type() == ExternalReference::BUILTIN_COMPARE_CALL) ||
1318         (redirection->type() == ExternalReference::BUILTIN_FP_CALL) ||
1319         (redirection->type() == ExternalReference::BUILTIN_FP_INT_CALL);
1320
1321    if (!IsMipsSoftFloatABI) {
1322      // With the hard floating point calling convention, double
1323      // arguments are passed in FPU registers. Fetch the arguments
1324      // from there and call the builtin using soft floating point
1325      // convention.
1326      switch (redirection->type()) {
1327      case ExternalReference::BUILTIN_FP_FP_CALL:
1328      case ExternalReference::BUILTIN_COMPARE_CALL:
1329        arg0 = get_fpu_register(f12);
1330        arg1 = get_fpu_register(f13);
1331        arg2 = get_fpu_register(f14);
1332        arg3 = get_fpu_register(f15);
1333        break;
1334      case ExternalReference::BUILTIN_FP_CALL:
1335        arg0 = get_fpu_register(f12);
1336        arg1 = get_fpu_register(f13);
1337        break;
1338      case ExternalReference::BUILTIN_FP_INT_CALL:
1339        arg0 = get_fpu_register(f12);
1340        arg1 = get_fpu_register(f13);
1341        arg2 = get_register(a2);
1342        break;
1343      default:
1344        break;
1345      }
1346    }
1347
1348    // This is dodgy but it works because the C entry stubs are never moved.
1349    // See comment in codegen-arm.cc and bug 1242173.
1350    int32_t saved_ra = get_register(ra);
1351
1352    intptr_t external =
1353          reinterpret_cast<intptr_t>(redirection->external_function());
1354
1355    // Based on CpuFeatures::IsSupported(FPU), Mips will use either hardware
1356    // FPU, or gcc soft-float routines. Hardware FPU is simulated in this
1357    // simulator. Soft-float has additional abstraction of ExternalReference,
1358    // to support serialization.
1359    if (fp_call) {
1360      SimulatorRuntimeFPCall target =
1361                  reinterpret_cast<SimulatorRuntimeFPCall>(external);
1362      if (::v8::internal::FLAG_trace_sim) {
1363        double dval0, dval1;
1364        int32_t ival;
1365        switch (redirection->type()) {
1366          case ExternalReference::BUILTIN_FP_FP_CALL:
1367          case ExternalReference::BUILTIN_COMPARE_CALL:
1368            GetFpArgs(&dval0, &dval1);
1369            PrintF("Call to host function at %p with args %f, %f",
1370                FUNCTION_ADDR(target), dval0, dval1);
1371            break;
1372          case ExternalReference::BUILTIN_FP_CALL:
1373            GetFpArgs(&dval0);
1374            PrintF("Call to host function at %p with arg %f",
1375                FUNCTION_ADDR(target), dval1);
1376            break;
1377          case ExternalReference::BUILTIN_FP_INT_CALL:
1378            GetFpArgs(&dval0, &ival);
1379            PrintF("Call to host function at %p with args %f, %d",
1380                FUNCTION_ADDR(target), dval0, ival);
1381            break;
1382          default:
1383            UNREACHABLE();
1384            break;
1385        }
1386      }
1387      double result = target(arg0, arg1, arg2, arg3);
1388      if (redirection->type() != ExternalReference::BUILTIN_COMPARE_CALL) {
1389          SetFpResult(result);
1390      } else {
1391        int32_t gpreg_pair[2];
1392        memcpy(&gpreg_pair[0], &result, 2 * sizeof(int32_t));
1393        set_register(v0, gpreg_pair[0]);
1394        set_register(v1, gpreg_pair[1]);
1395      }
1396    } else if (redirection->type() == ExternalReference::DIRECT_API_CALL) {
1397      // See DirectCEntryStub::GenerateCall for explanation of register usage.
1398      SimulatorRuntimeDirectApiCall target =
1399                  reinterpret_cast<SimulatorRuntimeDirectApiCall>(external);
1400      if (::v8::internal::FLAG_trace_sim) {
1401        PrintF("Call to host function at %p args %08x\n",
1402               FUNCTION_ADDR(target), arg1);
1403      }
1404      v8::Handle<v8::Value> result = target(arg1);
1405      *(reinterpret_cast<int*>(arg0)) = (int32_t) *result;
1406      set_register(v0, arg0);
1407    } else if (redirection->type() == ExternalReference::DIRECT_GETTER_CALL) {
1408      // See DirectCEntryStub::GenerateCall for explanation of register usage.
1409      SimulatorRuntimeDirectGetterCall target =
1410                  reinterpret_cast<SimulatorRuntimeDirectGetterCall>(external);
1411      if (::v8::internal::FLAG_trace_sim) {
1412        PrintF("Call to host function at %p args %08x %08x\n",
1413               FUNCTION_ADDR(target), arg1, arg2);
1414      }
1415      v8::Handle<v8::Value> result = target(arg1, arg2);
1416      *(reinterpret_cast<int*>(arg0)) = (int32_t) *result;
1417      set_register(v0, arg0);
1418    } else {
1419      SimulatorRuntimeCall target =
1420                  reinterpret_cast<SimulatorRuntimeCall>(external);
1421      if (::v8::internal::FLAG_trace_sim) {
1422        PrintF(
1423            "Call to host function at %p "
1424            "args %08x, %08x, %08x, %08x, %08x, %08x\n",
1425            FUNCTION_ADDR(target),
1426            arg0,
1427            arg1,
1428            arg2,
1429            arg3,
1430            arg4,
1431            arg5);
1432      }
1433      int64_t result = target(arg0, arg1, arg2, arg3, arg4, arg5);
1434      set_register(v0, static_cast<int32_t>(result));
1435      set_register(v1, static_cast<int32_t>(result >> 32));
1436    }
1437    if (::v8::internal::FLAG_trace_sim) {
1438      PrintF("Returned %08x : %08x\n", get_register(v1), get_register(v0));
1439    }
1440    set_register(ra, saved_ra);
1441    set_pc(get_register(ra));
1442
1443  } else if (func == BREAK && code >= 0 && code < 32) {
1444    // First 32 break_ codes interpreted as debug-markers/watchpoints.
1445    MipsDebugger dbg(this);
1446    ++break_count_;
1447    PrintF("\n---- break %d marker: %3d  (instr count: %8d) ----------"
1448           "----------------------------------",
1449           code, break_count_, icount_);
1450    dbg.PrintAllRegs();  // Print registers and continue running.
1451  } else {
1452    // All remaining break_ codes, and all traps are handled here.
1453    MipsDebugger dbg(this);
1454    dbg.Debug();
1455  }
1456}
1457
1458
1459void Simulator::SignalExceptions() {
1460  for (int i = 1; i < kNumExceptions; i++) {
1461    if (exceptions[i] != 0) {
1462      V8_Fatal(__FILE__, __LINE__, "Error: Exception %i raised.", i);
1463    }
1464  }
1465}
1466
1467
1468// Handle execution based on instruction types.
1469
1470void Simulator::ConfigureTypeRegister(Instruction* instr,
1471                                      int32_t& alu_out,
1472                                      int64_t& i64hilo,
1473                                      uint64_t& u64hilo,
1474                                      int32_t& next_pc,
1475                                      bool& do_interrupt) {
1476  // Every local variable declared here needs to be const.
1477  // This is to make sure that changed values are sent back to
1478  // DecodeTypeRegister correctly.
1479
1480  // Instruction fields.
1481  const Opcode   op     = instr->OpcodeFieldRaw();
1482  const int32_t  rs_reg = instr->RsValue();
1483  const int32_t  rs     = get_register(rs_reg);
1484  const uint32_t rs_u   = static_cast<uint32_t>(rs);
1485  const int32_t  rt_reg = instr->RtValue();
1486  const int32_t  rt     = get_register(rt_reg);
1487  const uint32_t rt_u   = static_cast<uint32_t>(rt);
1488  const int32_t  rd_reg = instr->RdValue();
1489  const uint32_t sa     = instr->SaValue();
1490
1491  const int32_t  fs_reg = instr->FsValue();
1492
1493
1494  // ---------- Configuration.
1495  switch (op) {
1496    case COP1:    // Coprocessor instructions.
1497      switch (instr->RsFieldRaw()) {
1498        case BC1:   // Handled in DecodeTypeImmed, should never come here.
1499          UNREACHABLE();
1500          break;
1501        case CFC1:
1502          // At the moment only FCSR is supported.
1503          ASSERT(fs_reg == kFCSRRegister);
1504          alu_out = FCSR_;
1505          break;
1506        case MFC1:
1507          alu_out = get_fpu_register(fs_reg);
1508          break;
1509        case MFHC1:
1510          UNIMPLEMENTED_MIPS();
1511          break;
1512        case CTC1:
1513        case MTC1:
1514        case MTHC1:
1515          // Do the store in the execution step.
1516          break;
1517        case S:
1518        case D:
1519        case W:
1520        case L:
1521        case PS:
1522          // Do everything in the execution step.
1523          break;
1524        default:
1525          UNIMPLEMENTED_MIPS();
1526      };
1527      break;
1528    case SPECIAL:
1529      switch (instr->FunctionFieldRaw()) {
1530        case JR:
1531        case JALR:
1532          next_pc = get_register(instr->RsValue());
1533          break;
1534        case SLL:
1535          alu_out = rt << sa;
1536          break;
1537        case SRL:
1538          if (rs_reg == 0) {
1539            // Regular logical right shift of a word by a fixed number of
1540            // bits instruction. RS field is always equal to 0.
1541            alu_out = rt_u >> sa;
1542          } else {
1543            // Logical right-rotate of a word by a fixed number of bits. This
1544            // is special case of SRL instruction, added in MIPS32 Release 2.
1545            // RS field is equal to 00001.
1546            alu_out = (rt_u >> sa) | (rt_u << (32 - sa));
1547          }
1548          break;
1549        case SRA:
1550          alu_out = rt >> sa;
1551          break;
1552        case SLLV:
1553          alu_out = rt << rs;
1554          break;
1555        case SRLV:
1556          if (sa == 0) {
1557            // Regular logical right-shift of a word by a variable number of
1558            // bits instruction. SA field is always equal to 0.
1559            alu_out = rt_u >> rs;
1560          } else {
1561            // Logical right-rotate of a word by a variable number of bits.
1562            // This is special case od SRLV instruction, added in MIPS32
1563            // Release 2. SA field is equal to 00001.
1564            alu_out = (rt_u >> rs_u) | (rt_u << (32 - rs_u));
1565          }
1566          break;
1567        case SRAV:
1568          alu_out = rt >> rs;
1569          break;
1570        case MFHI:
1571          alu_out = get_register(HI);
1572          break;
1573        case MFLO:
1574          alu_out = get_register(LO);
1575          break;
1576        case MULT:
1577          i64hilo = static_cast<int64_t>(rs) * static_cast<int64_t>(rt);
1578          break;
1579        case MULTU:
1580          u64hilo = static_cast<uint64_t>(rs_u) * static_cast<uint64_t>(rt_u);
1581          break;
1582        case ADD:
1583          if (HaveSameSign(rs, rt)) {
1584            if (rs > 0) {
1585              exceptions[kIntegerOverflow] = rs > (Registers::kMaxValue - rt);
1586            } else if (rs < 0) {
1587              exceptions[kIntegerUnderflow] = rs < (Registers::kMinValue - rt);
1588            }
1589          }
1590          alu_out = rs + rt;
1591          break;
1592        case ADDU:
1593          alu_out = rs + rt;
1594          break;
1595        case SUB:
1596          if (!HaveSameSign(rs, rt)) {
1597            if (rs > 0) {
1598              exceptions[kIntegerOverflow] = rs > (Registers::kMaxValue + rt);
1599            } else if (rs < 0) {
1600              exceptions[kIntegerUnderflow] = rs < (Registers::kMinValue + rt);
1601            }
1602          }
1603          alu_out = rs - rt;
1604          break;
1605        case SUBU:
1606          alu_out = rs - rt;
1607          break;
1608        case AND:
1609          alu_out = rs & rt;
1610          break;
1611        case OR:
1612          alu_out = rs | rt;
1613          break;
1614        case XOR:
1615          alu_out = rs ^ rt;
1616          break;
1617        case NOR:
1618          alu_out = ~(rs | rt);
1619          break;
1620        case SLT:
1621          alu_out = rs < rt ? 1 : 0;
1622          break;
1623        case SLTU:
1624          alu_out = rs_u < rt_u ? 1 : 0;
1625          break;
1626        // Break and trap instructions.
1627        case BREAK:
1628
1629          do_interrupt = true;
1630          break;
1631        case TGE:
1632          do_interrupt = rs >= rt;
1633          break;
1634        case TGEU:
1635          do_interrupt = rs_u >= rt_u;
1636          break;
1637        case TLT:
1638          do_interrupt = rs < rt;
1639          break;
1640        case TLTU:
1641          do_interrupt = rs_u < rt_u;
1642          break;
1643        case TEQ:
1644          do_interrupt = rs == rt;
1645          break;
1646        case TNE:
1647          do_interrupt = rs != rt;
1648          break;
1649        case MOVN:
1650        case MOVZ:
1651        case MOVCI:
1652          // No action taken on decode.
1653          break;
1654        case DIV:
1655        case DIVU:
1656          // div and divu never raise exceptions.
1657          break;
1658        default:
1659          UNREACHABLE();
1660      };
1661      break;
1662    case SPECIAL2:
1663      switch (instr->FunctionFieldRaw()) {
1664        case MUL:
1665          alu_out = rs_u * rt_u;  // Only the lower 32 bits are kept.
1666          break;
1667        case CLZ:
1668          alu_out = __builtin_clz(rs_u);
1669          break;
1670        default:
1671          UNREACHABLE();
1672      };
1673      break;
1674    case SPECIAL3:
1675      switch (instr->FunctionFieldRaw()) {
1676        case INS: {   // Mips32r2 instruction.
1677          // Interpret rd field as 5-bit msb of insert.
1678          uint16_t msb = rd_reg;
1679          // Interpret sa field as 5-bit lsb of insert.
1680          uint16_t lsb = sa;
1681          uint16_t size = msb - lsb + 1;
1682          uint32_t mask = (1 << size) - 1;
1683          alu_out = (rt_u & ~(mask << lsb)) | ((rs_u & mask) << lsb);
1684          break;
1685        }
1686        case EXT: {   // Mips32r2 instruction.
1687          // Interpret rd field as 5-bit msb of extract.
1688          uint16_t msb = rd_reg;
1689          // Interpret sa field as 5-bit lsb of extract.
1690          uint16_t lsb = sa;
1691          uint16_t size = msb + 1;
1692          uint32_t mask = (1 << size) - 1;
1693          alu_out = (rs_u & (mask << lsb)) >> lsb;
1694          break;
1695        }
1696        default:
1697          UNREACHABLE();
1698      };
1699      break;
1700    default:
1701      UNREACHABLE();
1702  };
1703}
1704
1705
1706void Simulator::DecodeTypeRegister(Instruction* instr) {
1707  // Instruction fields.
1708  const Opcode   op     = instr->OpcodeFieldRaw();
1709  const int32_t  rs_reg = instr->RsValue();
1710  const int32_t  rs     = get_register(rs_reg);
1711  const uint32_t rs_u   = static_cast<uint32_t>(rs);
1712  const int32_t  rt_reg = instr->RtValue();
1713  const int32_t  rt     = get_register(rt_reg);
1714  const uint32_t rt_u   = static_cast<uint32_t>(rt);
1715  const int32_t  rd_reg = instr->RdValue();
1716
1717  const int32_t  fs_reg = instr->FsValue();
1718  const int32_t  ft_reg = instr->FtValue();
1719  const int32_t  fd_reg = instr->FdValue();
1720  int64_t  i64hilo = 0;
1721  uint64_t u64hilo = 0;
1722
1723  // ALU output.
1724  // It should not be used as is. Instructions using it should always
1725  // initialize it first.
1726  int32_t alu_out = 0x12345678;
1727
1728  // For break and trap instructions.
1729  bool do_interrupt = false;
1730
1731  // For jr and jalr.
1732  // Get current pc.
1733  int32_t current_pc = get_pc();
1734  // Next pc
1735  int32_t next_pc = 0;
1736
1737  // Setup the variables if needed before executing the instruction.
1738  ConfigureTypeRegister(instr,
1739                        alu_out,
1740                        i64hilo,
1741                        u64hilo,
1742                        next_pc,
1743                        do_interrupt);
1744
1745  // ---------- Raise exceptions triggered.
1746  SignalExceptions();
1747
1748  // ---------- Execution.
1749  switch (op) {
1750    case COP1:
1751      switch (instr->RsFieldRaw()) {
1752        case BC1:   // Branch on coprocessor condition.
1753          UNREACHABLE();
1754          break;
1755        case CFC1:
1756          set_register(rt_reg, alu_out);
1757        case MFC1:
1758          set_register(rt_reg, alu_out);
1759          break;
1760        case MFHC1:
1761          UNIMPLEMENTED_MIPS();
1762          break;
1763        case CTC1:
1764          // At the moment only FCSR is supported.
1765          ASSERT(fs_reg == kFCSRRegister);
1766          FCSR_ = registers_[rt_reg];
1767          break;
1768        case MTC1:
1769          FPUregisters_[fs_reg] = registers_[rt_reg];
1770          break;
1771        case MTHC1:
1772          UNIMPLEMENTED_MIPS();
1773          break;
1774        case S:
1775          float f;
1776          switch (instr->FunctionFieldRaw()) {
1777            case CVT_D_S:
1778              f = get_fpu_register_float(fs_reg);
1779              set_fpu_register_double(fd_reg, static_cast<double>(f));
1780              break;
1781            case CVT_W_S:
1782            case CVT_L_S:
1783            case TRUNC_W_S:
1784            case TRUNC_L_S:
1785            case ROUND_W_S:
1786            case ROUND_L_S:
1787            case FLOOR_W_S:
1788            case FLOOR_L_S:
1789            case CEIL_W_S:
1790            case CEIL_L_S:
1791            case CVT_PS_S:
1792              UNIMPLEMENTED_MIPS();
1793              break;
1794            default:
1795              UNREACHABLE();
1796          }
1797          break;
1798        case D:
1799          double ft, fs;
1800          uint32_t cc, fcsr_cc;
1801          int64_t  i64;
1802          fs = get_fpu_register_double(fs_reg);
1803          ft = get_fpu_register_double(ft_reg);
1804          cc = instr->FCccValue();
1805          fcsr_cc = get_fcsr_condition_bit(cc);
1806          switch (instr->FunctionFieldRaw()) {
1807            case ADD_D:
1808              set_fpu_register_double(fd_reg, fs + ft);
1809              break;
1810            case SUB_D:
1811              set_fpu_register_double(fd_reg, fs - ft);
1812              break;
1813            case MUL_D:
1814              set_fpu_register_double(fd_reg, fs * ft);
1815              break;
1816            case DIV_D:
1817              set_fpu_register_double(fd_reg, fs / ft);
1818              break;
1819            case ABS_D:
1820              set_fpu_register_double(fd_reg, fs < 0 ? -fs : fs);
1821              break;
1822            case MOV_D:
1823              set_fpu_register_double(fd_reg, fs);
1824              break;
1825            case NEG_D:
1826              set_fpu_register_double(fd_reg, -fs);
1827              break;
1828            case SQRT_D:
1829              set_fpu_register_double(fd_reg, sqrt(fs));
1830              break;
1831            case C_UN_D:
1832              set_fcsr_bit(fcsr_cc, isnan(fs) || isnan(ft));
1833              break;
1834            case C_EQ_D:
1835              set_fcsr_bit(fcsr_cc, (fs == ft));
1836              break;
1837            case C_UEQ_D:
1838              set_fcsr_bit(fcsr_cc, (fs == ft) || (isnan(fs) || isnan(ft)));
1839              break;
1840            case C_OLT_D:
1841              set_fcsr_bit(fcsr_cc, (fs < ft));
1842              break;
1843            case C_ULT_D:
1844              set_fcsr_bit(fcsr_cc, (fs < ft) || (isnan(fs) || isnan(ft)));
1845              break;
1846            case C_OLE_D:
1847              set_fcsr_bit(fcsr_cc, (fs <= ft));
1848              break;
1849            case C_ULE_D:
1850              set_fcsr_bit(fcsr_cc, (fs <= ft) || (isnan(fs) || isnan(ft)));
1851              break;
1852            case CVT_W_D:   // Convert double to word.
1853              // Rounding modes are not yet supported.
1854              ASSERT((FCSR_ & 3) == 0);
1855              // In rounding mode 0 it should behave like ROUND.
1856            case ROUND_W_D:  // Round double to word.
1857              {
1858                double rounded = fs > 0 ? floor(fs + 0.5) : ceil(fs - 0.5);
1859                int32_t result = static_cast<int32_t>(rounded);
1860                set_fpu_register(fd_reg, result);
1861                if (set_fcsr_round_error(fs, rounded)) {
1862                  set_fpu_register(fd_reg, kFPUInvalidResult);
1863                }
1864              }
1865              break;
1866            case TRUNC_W_D:  // Truncate double to word (round towards 0).
1867              {
1868                int32_t result = static_cast<int32_t>(fs);
1869                set_fpu_register(fd_reg, result);
1870                if (set_fcsr_round_error(fs, static_cast<double>(result))) {
1871                  set_fpu_register(fd_reg, kFPUInvalidResult);
1872                }
1873              }
1874              break;
1875            case FLOOR_W_D:  // Round double to word towards negative infinity.
1876              {
1877                double rounded = floor(fs);
1878                int32_t result = static_cast<int32_t>(rounded);
1879                set_fpu_register(fd_reg, result);
1880                if (set_fcsr_round_error(fs, rounded)) {
1881                  set_fpu_register(fd_reg, kFPUInvalidResult);
1882                }
1883              }
1884              break;
1885            case CEIL_W_D:  // Round double to word towards positive infinity.
1886              {
1887                double rounded = ceil(fs);
1888                int32_t result = static_cast<int32_t>(rounded);
1889                set_fpu_register(fd_reg, result);
1890                if (set_fcsr_round_error(fs, rounded)) {
1891                  set_fpu_register(fd_reg, kFPUInvalidResult);
1892                }
1893              }
1894              break;
1895            case CVT_S_D:  // Convert double to float (single).
1896              set_fpu_register_float(fd_reg, static_cast<float>(fs));
1897              break;
1898            case CVT_L_D:  // Mips32r2: Truncate double to 64-bit long-word.
1899              i64 = static_cast<int64_t>(fs);
1900              set_fpu_register(fd_reg, i64 & 0xffffffff);
1901              set_fpu_register(fd_reg + 1, i64 >> 32);
1902              break;
1903            case TRUNC_L_D:  // Mips32r2 instruction.
1904              i64 = static_cast<int64_t>(fs);
1905              set_fpu_register(fd_reg, i64 & 0xffffffff);
1906              set_fpu_register(fd_reg + 1, i64 >> 32);
1907              break;
1908            case ROUND_L_D: {  // Mips32r2 instruction.
1909              double rounded = fs > 0 ? floor(fs + 0.5) : ceil(fs - 0.5);
1910              i64 = static_cast<int64_t>(rounded);
1911              set_fpu_register(fd_reg, i64 & 0xffffffff);
1912              set_fpu_register(fd_reg + 1, i64 >> 32);
1913              break;
1914            }
1915            case FLOOR_L_D:  // Mips32r2 instruction.
1916              i64 = static_cast<int64_t>(floor(fs));
1917              set_fpu_register(fd_reg, i64 & 0xffffffff);
1918              set_fpu_register(fd_reg + 1, i64 >> 32);
1919              break;
1920            case CEIL_L_D:  // Mips32r2 instruction.
1921              i64 = static_cast<int64_t>(ceil(fs));
1922              set_fpu_register(fd_reg, i64 & 0xffffffff);
1923              set_fpu_register(fd_reg + 1, i64 >> 32);
1924              break;
1925            case C_F_D:
1926              UNIMPLEMENTED_MIPS();
1927              break;
1928            default:
1929              UNREACHABLE();
1930          }
1931          break;
1932        case W:
1933          switch (instr->FunctionFieldRaw()) {
1934            case CVT_S_W:   // Convert word to float (single).
1935              alu_out = get_fpu_register(fs_reg);
1936              set_fpu_register_float(fd_reg, static_cast<float>(alu_out));
1937              break;
1938            case CVT_D_W:   // Convert word to double.
1939              alu_out = get_fpu_register(fs_reg);
1940              set_fpu_register_double(fd_reg, static_cast<double>(alu_out));
1941              break;
1942            default:
1943              UNREACHABLE();
1944          };
1945          break;
1946        case L:
1947          switch (instr->FunctionFieldRaw()) {
1948          case CVT_D_L:  // Mips32r2 instruction.
1949            // Watch the signs here, we want 2 32-bit vals
1950            // to make a sign-64.
1951            i64 = (uint32_t) get_fpu_register(fs_reg);
1952            i64 |= ((int64_t) get_fpu_register(fs_reg + 1) << 32);
1953            set_fpu_register_double(fd_reg, static_cast<double>(i64));
1954            break;
1955            case CVT_S_L:
1956              UNIMPLEMENTED_MIPS();
1957              break;
1958            default:
1959              UNREACHABLE();
1960          }
1961          break;
1962        case PS:
1963          break;
1964        default:
1965          UNREACHABLE();
1966      };
1967      break;
1968    case SPECIAL:
1969      switch (instr->FunctionFieldRaw()) {
1970        case JR: {
1971          Instruction* branch_delay_instr = reinterpret_cast<Instruction*>(
1972              current_pc+Instruction::kInstrSize);
1973          BranchDelayInstructionDecode(branch_delay_instr);
1974          set_pc(next_pc);
1975          pc_modified_ = true;
1976          break;
1977        }
1978        case JALR: {
1979          Instruction* branch_delay_instr = reinterpret_cast<Instruction*>(
1980              current_pc+Instruction::kInstrSize);
1981          BranchDelayInstructionDecode(branch_delay_instr);
1982          set_register(31, current_pc + 2 * Instruction::kInstrSize);
1983          set_pc(next_pc);
1984          pc_modified_ = true;
1985          break;
1986        }
1987        // Instructions using HI and LO registers.
1988        case MULT:
1989          set_register(LO, static_cast<int32_t>(i64hilo & 0xffffffff));
1990          set_register(HI, static_cast<int32_t>(i64hilo >> 32));
1991          break;
1992        case MULTU:
1993          set_register(LO, static_cast<int32_t>(u64hilo & 0xffffffff));
1994          set_register(HI, static_cast<int32_t>(u64hilo >> 32));
1995          break;
1996        case DIV:
1997          // Divide by zero was not checked in the configuration step - div and
1998          // divu do not raise exceptions. On division by 0, the result will
1999          // be UNPREDICTABLE.
2000          if (rt != 0) {
2001            set_register(LO, rs / rt);
2002            set_register(HI, rs % rt);
2003          }
2004          break;
2005        case DIVU:
2006          if (rt_u != 0) {
2007            set_register(LO, rs_u / rt_u);
2008            set_register(HI, rs_u % rt_u);
2009          }
2010          break;
2011        // Break and trap instructions.
2012        case BREAK:
2013        case TGE:
2014        case TGEU:
2015        case TLT:
2016        case TLTU:
2017        case TEQ:
2018        case TNE:
2019          if (do_interrupt) {
2020            SoftwareInterrupt(instr);
2021          }
2022          break;
2023        // Conditional moves.
2024        case MOVN:
2025          if (rt) set_register(rd_reg, rs);
2026          break;
2027        case MOVCI: {
2028          uint32_t cc = instr->FBccValue();
2029          uint32_t fcsr_cc = get_fcsr_condition_bit(cc);
2030          if (instr->Bit(16)) {  // Read Tf bit.
2031            if (test_fcsr_bit(fcsr_cc)) set_register(rd_reg, rs);
2032          } else {
2033            if (!test_fcsr_bit(fcsr_cc)) set_register(rd_reg, rs);
2034          }
2035          break;
2036        }
2037        case MOVZ:
2038          if (!rt) set_register(rd_reg, rs);
2039          break;
2040        default:  // For other special opcodes we do the default operation.
2041          set_register(rd_reg, alu_out);
2042      };
2043      break;
2044    case SPECIAL2:
2045      switch (instr->FunctionFieldRaw()) {
2046        case MUL:
2047          set_register(rd_reg, alu_out);
2048          // HI and LO are UNPREDICTABLE after the operation.
2049          set_register(LO, Unpredictable);
2050          set_register(HI, Unpredictable);
2051          break;
2052        default:  // For other special2 opcodes we do the default operation.
2053          set_register(rd_reg, alu_out);
2054      }
2055      break;
2056    case SPECIAL3:
2057      switch (instr->FunctionFieldRaw()) {
2058        case INS:
2059          // Ins instr leaves result in Rt, rather than Rd.
2060          set_register(rt_reg, alu_out);
2061          break;
2062        case EXT:
2063          // Ext instr leaves result in Rt, rather than Rd.
2064          set_register(rt_reg, alu_out);
2065          break;
2066        default:
2067          UNREACHABLE();
2068      };
2069      break;
2070    // Unimplemented opcodes raised an error in the configuration step before,
2071    // so we can use the default here to set the destination register in common
2072    // cases.
2073    default:
2074      set_register(rd_reg, alu_out);
2075  };
2076}
2077
2078
2079// Type 2: instructions using a 16 bytes immediate. (eg: addi, beq).
2080void Simulator::DecodeTypeImmediate(Instruction* instr) {
2081  // Instruction fields.
2082  Opcode   op     = instr->OpcodeFieldRaw();
2083  int32_t  rs     = get_register(instr->RsValue());
2084  uint32_t rs_u   = static_cast<uint32_t>(rs);
2085  int32_t  rt_reg = instr->RtValue();  // Destination register.
2086  int32_t  rt     = get_register(rt_reg);
2087  int16_t  imm16  = instr->Imm16Value();
2088
2089  int32_t  ft_reg = instr->FtValue();  // Destination register.
2090
2091  // Zero extended immediate.
2092  uint32_t  oe_imm16 = 0xffff & imm16;
2093  // Sign extended immediate.
2094  int32_t   se_imm16 = imm16;
2095
2096  // Get current pc.
2097  int32_t current_pc = get_pc();
2098  // Next pc.
2099  int32_t next_pc = bad_ra;
2100
2101  // Used for conditional branch instructions.
2102  bool do_branch = false;
2103  bool execute_branch_delay_instruction = false;
2104
2105  // Used for arithmetic instructions.
2106  int32_t alu_out = 0;
2107  // Floating point.
2108  double fp_out = 0.0;
2109  uint32_t cc, cc_value, fcsr_cc;
2110
2111  // Used for memory instructions.
2112  int32_t addr = 0x0;
2113  // Value to be written in memory.
2114  uint32_t mem_value = 0x0;
2115
2116  // ---------- Configuration (and execution for REGIMM).
2117  switch (op) {
2118    // ------------- COP1. Coprocessor instructions.
2119    case COP1:
2120      switch (instr->RsFieldRaw()) {
2121        case BC1:   // Branch on coprocessor condition.
2122          cc = instr->FBccValue();
2123          fcsr_cc = get_fcsr_condition_bit(cc);
2124          cc_value = test_fcsr_bit(fcsr_cc);
2125          do_branch = (instr->FBtrueValue()) ? cc_value : !cc_value;
2126          execute_branch_delay_instruction = true;
2127          // Set next_pc.
2128          if (do_branch) {
2129            next_pc = current_pc + (imm16 << 2) + Instruction::kInstrSize;
2130          } else {
2131            next_pc = current_pc + kBranchReturnOffset;
2132          }
2133          break;
2134        default:
2135          UNREACHABLE();
2136      };
2137      break;
2138    // ------------- REGIMM class.
2139    case REGIMM:
2140      switch (instr->RtFieldRaw()) {
2141        case BLTZ:
2142          do_branch = (rs  < 0);
2143          break;
2144        case BLTZAL:
2145          do_branch = rs  < 0;
2146          break;
2147        case BGEZ:
2148          do_branch = rs >= 0;
2149          break;
2150        case BGEZAL:
2151          do_branch = rs >= 0;
2152          break;
2153        default:
2154          UNREACHABLE();
2155      };
2156      switch (instr->RtFieldRaw()) {
2157        case BLTZ:
2158        case BLTZAL:
2159        case BGEZ:
2160        case BGEZAL:
2161          // Branch instructions common part.
2162          execute_branch_delay_instruction = true;
2163          // Set next_pc.
2164          if (do_branch) {
2165            next_pc = current_pc + (imm16 << 2) + Instruction::kInstrSize;
2166            if (instr->IsLinkingInstruction()) {
2167              set_register(31, current_pc + kBranchReturnOffset);
2168            }
2169          } else {
2170            next_pc = current_pc + kBranchReturnOffset;
2171          }
2172        default:
2173          break;
2174        };
2175    break;  // case REGIMM.
2176    // ------------- Branch instructions.
2177    // When comparing to zero, the encoding of rt field is always 0, so we don't
2178    // need to replace rt with zero.
2179    case BEQ:
2180      do_branch = (rs == rt);
2181      break;
2182    case BNE:
2183      do_branch = rs != rt;
2184      break;
2185    case BLEZ:
2186      do_branch = rs <= 0;
2187      break;
2188    case BGTZ:
2189      do_branch = rs  > 0;
2190      break;
2191    // ------------- Arithmetic instructions.
2192    case ADDI:
2193      if (HaveSameSign(rs, se_imm16)) {
2194        if (rs > 0) {
2195          exceptions[kIntegerOverflow] = rs > (Registers::kMaxValue - se_imm16);
2196        } else if (rs < 0) {
2197          exceptions[kIntegerUnderflow] =
2198              rs < (Registers::kMinValue - se_imm16);
2199        }
2200      }
2201      alu_out = rs + se_imm16;
2202      break;
2203    case ADDIU:
2204      alu_out = rs + se_imm16;
2205      break;
2206    case SLTI:
2207      alu_out = (rs < se_imm16) ? 1 : 0;
2208      break;
2209    case SLTIU:
2210      alu_out = (rs_u < static_cast<uint32_t>(se_imm16)) ? 1 : 0;
2211      break;
2212    case ANDI:
2213        alu_out = rs & oe_imm16;
2214      break;
2215    case ORI:
2216        alu_out = rs | oe_imm16;
2217      break;
2218    case XORI:
2219        alu_out = rs ^ oe_imm16;
2220      break;
2221    case LUI:
2222        alu_out = (oe_imm16 << 16);
2223      break;
2224    // ------------- Memory instructions.
2225    case LB:
2226      addr = rs + se_imm16;
2227      alu_out = ReadB(addr);
2228      break;
2229    case LH:
2230      addr = rs + se_imm16;
2231      alu_out = ReadH(addr, instr);
2232      break;
2233    case LWL: {
2234      // al_offset is offset of the effective address within an aligned word.
2235      uint8_t al_offset = (rs + se_imm16) & kPointerAlignmentMask;
2236      uint8_t byte_shift = kPointerAlignmentMask - al_offset;
2237      uint32_t mask = (1 << byte_shift * 8) - 1;
2238      addr = rs + se_imm16 - al_offset;
2239      alu_out = ReadW(addr, instr);
2240      alu_out <<= byte_shift * 8;
2241      alu_out |= rt & mask;
2242      break;
2243    }
2244    case LW:
2245      addr = rs + se_imm16;
2246      alu_out = ReadW(addr, instr);
2247      break;
2248    case LBU:
2249      addr = rs + se_imm16;
2250      alu_out = ReadBU(addr);
2251      break;
2252    case LHU:
2253      addr = rs + se_imm16;
2254      alu_out = ReadHU(addr, instr);
2255      break;
2256    case LWR: {
2257      // al_offset is offset of the effective address within an aligned word.
2258      uint8_t al_offset = (rs + se_imm16) & kPointerAlignmentMask;
2259      uint8_t byte_shift = kPointerAlignmentMask - al_offset;
2260      uint32_t mask = al_offset ? (~0 << (byte_shift + 1) * 8) : 0;
2261      addr = rs + se_imm16 - al_offset;
2262      alu_out = ReadW(addr, instr);
2263      alu_out = static_cast<uint32_t> (alu_out) >> al_offset * 8;
2264      alu_out |= rt & mask;
2265      break;
2266    }
2267    case SB:
2268      addr = rs + se_imm16;
2269      break;
2270    case SH:
2271      addr = rs + se_imm16;
2272      break;
2273    case SWL: {
2274      uint8_t al_offset = (rs + se_imm16) & kPointerAlignmentMask;
2275      uint8_t byte_shift = kPointerAlignmentMask - al_offset;
2276      uint32_t mask = byte_shift ? (~0 << (al_offset + 1) * 8) : 0;
2277      addr = rs + se_imm16 - al_offset;
2278      mem_value = ReadW(addr, instr) & mask;
2279      mem_value |= static_cast<uint32_t>(rt) >> byte_shift * 8;
2280      break;
2281    }
2282    case SW:
2283      addr = rs + se_imm16;
2284      break;
2285    case SWR: {
2286      uint8_t al_offset = (rs + se_imm16) & kPointerAlignmentMask;
2287      uint32_t mask = (1 << al_offset * 8) - 1;
2288      addr = rs + se_imm16 - al_offset;
2289      mem_value = ReadW(addr, instr);
2290      mem_value = (rt << al_offset * 8) | (mem_value & mask);
2291      break;
2292    }
2293    case LWC1:
2294      addr = rs + se_imm16;
2295      alu_out = ReadW(addr, instr);
2296      break;
2297    case LDC1:
2298      addr = rs + se_imm16;
2299      fp_out = ReadD(addr, instr);
2300      break;
2301    case SWC1:
2302    case SDC1:
2303      addr = rs + se_imm16;
2304      break;
2305    default:
2306      UNREACHABLE();
2307  };
2308
2309  // ---------- Raise exceptions triggered.
2310  SignalExceptions();
2311
2312  // ---------- Execution.
2313  switch (op) {
2314    // ------------- Branch instructions.
2315    case BEQ:
2316    case BNE:
2317    case BLEZ:
2318    case BGTZ:
2319      // Branch instructions common part.
2320      execute_branch_delay_instruction = true;
2321      // Set next_pc.
2322      if (do_branch) {
2323        next_pc = current_pc + (imm16 << 2) + Instruction::kInstrSize;
2324        if (instr->IsLinkingInstruction()) {
2325          set_register(31, current_pc + 2* Instruction::kInstrSize);
2326        }
2327      } else {
2328        next_pc = current_pc + 2 * Instruction::kInstrSize;
2329      }
2330      break;
2331    // ------------- Arithmetic instructions.
2332    case ADDI:
2333    case ADDIU:
2334    case SLTI:
2335    case SLTIU:
2336    case ANDI:
2337    case ORI:
2338    case XORI:
2339    case LUI:
2340      set_register(rt_reg, alu_out);
2341      break;
2342    // ------------- Memory instructions.
2343    case LB:
2344    case LH:
2345    case LWL:
2346    case LW:
2347    case LBU:
2348    case LHU:
2349    case LWR:
2350      set_register(rt_reg, alu_out);
2351      break;
2352    case SB:
2353      WriteB(addr, static_cast<int8_t>(rt));
2354      break;
2355    case SH:
2356      WriteH(addr, static_cast<uint16_t>(rt), instr);
2357      break;
2358    case SWL:
2359      WriteW(addr, mem_value, instr);
2360      break;
2361    case SW:
2362      WriteW(addr, rt, instr);
2363      break;
2364    case SWR:
2365      WriteW(addr, mem_value, instr);
2366      break;
2367    case LWC1:
2368      set_fpu_register(ft_reg, alu_out);
2369      break;
2370    case LDC1:
2371      set_fpu_register_double(ft_reg, fp_out);
2372      break;
2373    case SWC1:
2374      addr = rs + se_imm16;
2375      WriteW(addr, get_fpu_register(ft_reg), instr);
2376      break;
2377    case SDC1:
2378      addr = rs + se_imm16;
2379      WriteD(addr, get_fpu_register_double(ft_reg), instr);
2380      break;
2381    default:
2382      break;
2383  };
2384
2385
2386  if (execute_branch_delay_instruction) {
2387    // Execute branch delay slot
2388    // We don't check for end_sim_pc. First it should not be met as the current
2389    // pc is valid. Secondly a jump should always execute its branch delay slot.
2390    Instruction* branch_delay_instr =
2391      reinterpret_cast<Instruction*>(current_pc+Instruction::kInstrSize);
2392    BranchDelayInstructionDecode(branch_delay_instr);
2393  }
2394
2395  // If needed update pc after the branch delay execution.
2396  if (next_pc != bad_ra) {
2397    set_pc(next_pc);
2398  }
2399}
2400
2401
2402// Type 3: instructions using a 26 bytes immediate. (eg: j, jal).
2403void Simulator::DecodeTypeJump(Instruction* instr) {
2404  // Get current pc.
2405  int32_t current_pc = get_pc();
2406  // Get unchanged bits of pc.
2407  int32_t pc_high_bits = current_pc & 0xf0000000;
2408  // Next pc.
2409  int32_t next_pc = pc_high_bits | (instr->Imm26Value() << 2);
2410
2411  // Execute branch delay slot.
2412  // We don't check for end_sim_pc. First it should not be met as the current pc
2413  // is valid. Secondly a jump should always execute its branch delay slot.
2414  Instruction* branch_delay_instr =
2415      reinterpret_cast<Instruction*>(current_pc + Instruction::kInstrSize);
2416  BranchDelayInstructionDecode(branch_delay_instr);
2417
2418  // Update pc and ra if necessary.
2419  // Do this after the branch delay execution.
2420  if (instr->IsLinkingInstruction()) {
2421    set_register(31, current_pc + 2 * Instruction::kInstrSize);
2422  }
2423  set_pc(next_pc);
2424  pc_modified_ = true;
2425}
2426
2427
2428// Executes the current instruction.
2429void Simulator::InstructionDecode(Instruction* instr) {
2430  if (v8::internal::FLAG_check_icache) {
2431    CheckICache(isolate_->simulator_i_cache(), instr);
2432  }
2433  pc_modified_ = false;
2434  if (::v8::internal::FLAG_trace_sim) {
2435    disasm::NameConverter converter;
2436    disasm::Disassembler dasm(converter);
2437    // Use a reasonably large buffer.
2438    v8::internal::EmbeddedVector<char, 256> buffer;
2439    dasm.InstructionDecode(buffer, reinterpret_cast<byte*>(instr));
2440    PrintF("  0x%08x  %s\n", reinterpret_cast<intptr_t>(instr),
2441        buffer.start());
2442  }
2443
2444  switch (instr->InstructionType()) {
2445    case Instruction::kRegisterType:
2446      DecodeTypeRegister(instr);
2447      break;
2448    case Instruction::kImmediateType:
2449      DecodeTypeImmediate(instr);
2450      break;
2451    case Instruction::kJumpType:
2452      DecodeTypeJump(instr);
2453      break;
2454    default:
2455      UNSUPPORTED();
2456  }
2457  if (!pc_modified_) {
2458    set_register(pc, reinterpret_cast<int32_t>(instr) +
2459                 Instruction::kInstrSize);
2460  }
2461}
2462
2463
2464
2465void Simulator::Execute() {
2466  // Get the PC to simulate. Cannot use the accessor here as we need the
2467  // raw PC value and not the one used as input to arithmetic instructions.
2468  int program_counter = get_pc();
2469  if (::v8::internal::FLAG_stop_sim_at == 0) {
2470    // Fast version of the dispatch loop without checking whether the simulator
2471    // should be stopping at a particular executed instruction.
2472    while (program_counter != end_sim_pc) {
2473      Instruction* instr = reinterpret_cast<Instruction*>(program_counter);
2474      icount_++;
2475      InstructionDecode(instr);
2476      program_counter = get_pc();
2477    }
2478  } else {
2479    // FLAG_stop_sim_at is at the non-default value. Stop in the debugger when
2480    // we reach the particular instuction count.
2481    while (program_counter != end_sim_pc) {
2482      Instruction* instr = reinterpret_cast<Instruction*>(program_counter);
2483      icount_++;
2484      if (icount_ == ::v8::internal::FLAG_stop_sim_at) {
2485        MipsDebugger dbg(this);
2486        dbg.Debug();
2487      } else {
2488        InstructionDecode(instr);
2489      }
2490      program_counter = get_pc();
2491    }
2492  }
2493}
2494
2495
2496int32_t Simulator::Call(byte* entry, int argument_count, ...) {
2497  va_list parameters;
2498  va_start(parameters, argument_count);
2499  // Setup arguments.
2500
2501  // First four arguments passed in registers.
2502  ASSERT(argument_count >= 4);
2503  set_register(a0, va_arg(parameters, int32_t));
2504  set_register(a1, va_arg(parameters, int32_t));
2505  set_register(a2, va_arg(parameters, int32_t));
2506  set_register(a3, va_arg(parameters, int32_t));
2507
2508  // Remaining arguments passed on stack.
2509  int original_stack = get_register(sp);
2510  // Compute position of stack on entry to generated code.
2511  int entry_stack = (original_stack - (argument_count - 4) * sizeof(int32_t)
2512                                    - kCArgsSlotsSize);
2513  if (OS::ActivationFrameAlignment() != 0) {
2514    entry_stack &= -OS::ActivationFrameAlignment();
2515  }
2516  // Store remaining arguments on stack, from low to high memory.
2517  intptr_t* stack_argument = reinterpret_cast<intptr_t*>(entry_stack);
2518  for (int i = 4; i < argument_count; i++) {
2519    stack_argument[i - 4 + kArgsSlotsNum] = va_arg(parameters, int32_t);
2520  }
2521  va_end(parameters);
2522  set_register(sp, entry_stack);
2523
2524  // Prepare to execute the code at entry.
2525  set_register(pc, reinterpret_cast<int32_t>(entry));
2526  // Put down marker for end of simulation. The simulator will stop simulation
2527  // when the PC reaches this value. By saving the "end simulation" value into
2528  // the LR the simulation stops when returning to this call point.
2529  set_register(ra, end_sim_pc);
2530
2531  // Remember the values of callee-saved registers.
2532  // The code below assumes that r9 is not used as sb (static base) in
2533  // simulator code and therefore is regarded as a callee-saved register.
2534  int32_t s0_val = get_register(s0);
2535  int32_t s1_val = get_register(s1);
2536  int32_t s2_val = get_register(s2);
2537  int32_t s3_val = get_register(s3);
2538  int32_t s4_val = get_register(s4);
2539  int32_t s5_val = get_register(s5);
2540  int32_t s6_val = get_register(s6);
2541  int32_t s7_val = get_register(s7);
2542  int32_t gp_val = get_register(gp);
2543  int32_t sp_val = get_register(sp);
2544  int32_t fp_val = get_register(fp);
2545
2546  // Setup the callee-saved registers with a known value. To be able to check
2547  // that they are preserved properly across JS execution.
2548  int32_t callee_saved_value = icount_;
2549  set_register(s0, callee_saved_value);
2550  set_register(s1, callee_saved_value);
2551  set_register(s2, callee_saved_value);
2552  set_register(s3, callee_saved_value);
2553  set_register(s4, callee_saved_value);
2554  set_register(s5, callee_saved_value);
2555  set_register(s6, callee_saved_value);
2556  set_register(s7, callee_saved_value);
2557  set_register(gp, callee_saved_value);
2558  set_register(fp, callee_saved_value);
2559
2560  // Start the simulation.
2561  Execute();
2562
2563  // Check that the callee-saved registers have been preserved.
2564  CHECK_EQ(callee_saved_value, get_register(s0));
2565  CHECK_EQ(callee_saved_value, get_register(s1));
2566  CHECK_EQ(callee_saved_value, get_register(s2));
2567  CHECK_EQ(callee_saved_value, get_register(s3));
2568  CHECK_EQ(callee_saved_value, get_register(s4));
2569  CHECK_EQ(callee_saved_value, get_register(s5));
2570  CHECK_EQ(callee_saved_value, get_register(s6));
2571  CHECK_EQ(callee_saved_value, get_register(s7));
2572  CHECK_EQ(callee_saved_value, get_register(gp));
2573  CHECK_EQ(callee_saved_value, get_register(fp));
2574
2575  // Restore callee-saved registers with the original value.
2576  set_register(s0, s0_val);
2577  set_register(s1, s1_val);
2578  set_register(s2, s2_val);
2579  set_register(s3, s3_val);
2580  set_register(s4, s4_val);
2581  set_register(s5, s5_val);
2582  set_register(s6, s6_val);
2583  set_register(s7, s7_val);
2584  set_register(gp, gp_val);
2585  set_register(sp, sp_val);
2586  set_register(fp, fp_val);
2587
2588  // Pop stack passed arguments.
2589  CHECK_EQ(entry_stack, get_register(sp));
2590  set_register(sp, original_stack);
2591
2592  int32_t result = get_register(v0);
2593  return result;
2594}
2595
2596
2597uintptr_t Simulator::PushAddress(uintptr_t address) {
2598  int new_sp = get_register(sp) - sizeof(uintptr_t);
2599  uintptr_t* stack_slot = reinterpret_cast<uintptr_t*>(new_sp);
2600  *stack_slot = address;
2601  set_register(sp, new_sp);
2602  return new_sp;
2603}
2604
2605
2606uintptr_t Simulator::PopAddress() {
2607  int current_sp = get_register(sp);
2608  uintptr_t* stack_slot = reinterpret_cast<uintptr_t*>(current_sp);
2609  uintptr_t address = *stack_slot;
2610  set_register(sp, current_sp + sizeof(uintptr_t));
2611  return address;
2612}
2613
2614
2615#undef UNSUPPORTED
2616
2617} }  // namespace v8::internal
2618
2619#endif  // USE_SIMULATOR
2620
2621#endif  // V8_TARGET_ARCH_MIPS
2622