Home | History | Annotate | Download | only in mips
      1 // Copyright 2010 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 
     46 namespace v8 {
     47 namespace internal {
     48 
     49 // Utils functions
     50 bool HaveSameSign(int32_t a, int32_t b) {
     51   return ((a ^ b) >= 0);
     52 }
     53 
     54 
     55 uint32_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.
     72 class 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 
    107 MipsDebugger::MipsDebugger(Simulator* sim) {
    108   sim_ = sim;
    109 }
    110 
    111 
    112 MipsDebugger::~MipsDebugger() {
    113 }
    114 
    115 
    116 #ifdef GENERATED_CODE_COVERAGE
    117 static FILE* coverage_log = NULL;
    118 
    119 
    120 static 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 
    128 void 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  // ndef GENERATED_CODE_COVERAGE
    143 
    144 #define UNSUPPORTED() printf("Unsupported instruction.\n");
    145 
    146 static void InitializeCoverage() {}
    147 
    148 
    149 void 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 
    158 int32_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 
    167 int32_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 
    176 int64_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 
    185 float 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 
    194 double 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 
    203 bool 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 
    222 bool 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 
    237 bool 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 
    248 void MipsDebugger::UndoBreakpoints() {
    249   if (sim_->break_pc_ != NULL) {
    250     sim_->break_pc_->SetInstructionBits(sim_->break_instr_);
    251   }
    252 }
    253 
    254 
    255 void MipsDebugger::RedoBreakpoints() {
    256   if (sim_->break_pc_ != NULL) {
    257     sim_->break_pc_->SetInstructionBits(kBreakpointInstr);
    258   }
    259 }
    260 
    261 
    262 void 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 
    301 void 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 
    333 void 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 {  // "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\n",
    500                  reinterpret_cast<intptr_t>(cur), *cur, *cur);
    501           cur++;
    502         }
    503 
    504       } else if ((strcmp(cmd, "disasm") == 0) || (strcmp(cmd, "dpc") == 0)) {
    505         disasm::NameConverter converter;
    506         disasm::Disassembler dasm(converter);
    507         // use a reasonably large buffer
    508         v8::internal::EmbeddedVector<char, 256> buffer;
    509 
    510         byte_* cur = NULL;
    511         byte_* end = NULL;
    512 
    513         if (argc == 1) {
    514           cur = reinterpret_cast<byte_*>(sim_->get_pc());
    515           end = cur + (10 * Instruction::kInstrSize);
    516         } else if (argc == 2) {
    517           int32_t value;
    518           if (GetValue(arg1, &value)) {
    519             cur = reinterpret_cast<byte_*>(value);
    520             // no length parameter passed, assume 10 instructions
    521             end = cur + (10 * Instruction::kInstrSize);
    522           }
    523         } else {
    524           int32_t value1;
    525           int32_t value2;
    526           if (GetValue(arg1, &value1) && GetValue(arg2, &value2)) {
    527             cur = reinterpret_cast<byte_*>(value1);
    528             end = cur + (value2 * Instruction::kInstrSize);
    529           }
    530         }
    531 
    532         while (cur < end) {
    533           dasm.InstructionDecode(buffer, cur);
    534           PrintF("  0x%08x  %s\n",
    535               reinterpret_cast<intptr_t>(cur), buffer.start());
    536           cur += Instruction::kInstrSize;
    537         }
    538       } else if (strcmp(cmd, "gdb") == 0) {
    539         PrintF("relinquishing control to gdb\n");
    540         v8::internal::OS::DebugBreak();
    541         PrintF("regaining control from gdb\n");
    542       } else if (strcmp(cmd, "break") == 0) {
    543         if (argc == 2) {
    544           int32_t value;
    545           if (GetValue(arg1, &value)) {
    546             if (!SetBreakpoint(reinterpret_cast<Instruction*>(value))) {
    547               PrintF("setting breakpoint failed\n");
    548             }
    549           } else {
    550             PrintF("%s unrecognized\n", arg1);
    551           }
    552         } else {
    553           PrintF("break <address>\n");
    554         }
    555       } else if (strcmp(cmd, "del") == 0) {
    556         if (!DeleteBreakpoint(NULL)) {
    557           PrintF("deleting breakpoint failed\n");
    558         }
    559       } else if (strcmp(cmd, "flags") == 0) {
    560         PrintF("No flags on MIPS !\n");
    561       } else if (strcmp(cmd, "unstop") == 0) {
    562           PrintF("Unstop command not implemented on MIPS.");
    563       } else if ((strcmp(cmd, "stat") == 0) || (strcmp(cmd, "st") == 0)) {
    564         // Print registers and disassemble
    565         PrintAllRegs();
    566         PrintF("\n");
    567 
    568         disasm::NameConverter converter;
    569         disasm::Disassembler dasm(converter);
    570         // use a reasonably large buffer
    571         v8::internal::EmbeddedVector<char, 256> buffer;
    572 
    573         byte_* cur = NULL;
    574         byte_* end = NULL;
    575 
    576         if (argc == 1) {
    577           cur = reinterpret_cast<byte_*>(sim_->get_pc());
    578           end = cur + (10 * Instruction::kInstrSize);
    579         } else if (argc == 2) {
    580           int32_t value;
    581           if (GetValue(arg1, &value)) {
    582             cur = reinterpret_cast<byte_*>(value);
    583             // no length parameter passed, assume 10 instructions
    584             end = cur + (10 * Instruction::kInstrSize);
    585           }
    586         } else {
    587           int32_t value1;
    588           int32_t value2;
    589           if (GetValue(arg1, &value1) && GetValue(arg2, &value2)) {
    590             cur = reinterpret_cast<byte_*>(value1);
    591             end = cur + (value2 * Instruction::kInstrSize);
    592           }
    593         }
    594 
    595         while (cur < end) {
    596           dasm.InstructionDecode(buffer, cur);
    597           PrintF("  0x%08x  %s\n",
    598                  reinterpret_cast<intptr_t>(cur), buffer.start());
    599           cur += Instruction::kInstrSize;
    600         }
    601       } else if ((strcmp(cmd, "h") == 0) || (strcmp(cmd, "help") == 0)) {
    602         PrintF("cont\n");
    603         PrintF("  continue execution (alias 'c')\n");
    604         PrintF("stepi\n");
    605         PrintF("  step one instruction (alias 'si')\n");
    606         PrintF("print <register>\n");
    607         PrintF("  print register content (alias 'p')\n");
    608         PrintF("  use register name 'all' to print all registers\n");
    609         PrintF("printobject <register>\n");
    610         PrintF("  print an object from a register (alias 'po')\n");
    611         PrintF("stack [<words>]\n");
    612         PrintF("  dump stack content, default dump 10 words)\n");
    613         PrintF("mem <address> [<words>]\n");
    614         PrintF("  dump memory content, default dump 10 words)\n");
    615         PrintF("flags\n");
    616         PrintF("  print flags\n");
    617         PrintF("disasm [<instructions>]\n");
    618         PrintF("disasm [[<address>] <instructions>]\n");
    619         PrintF("  disassemble code, default is 10 instructions from pc\n");
    620         PrintF("gdb\n");
    621         PrintF("  enter gdb\n");
    622         PrintF("break <address>\n");
    623         PrintF("  set a break point on the address\n");
    624         PrintF("del\n");
    625         PrintF("  delete the breakpoint\n");
    626         PrintF("unstop\n");
    627         PrintF("  ignore the stop instruction at the current location");
    628         PrintF(" from now on\n");
    629       } else {
    630         PrintF("Unknown command: %s\n", cmd);
    631       }
    632     }
    633     DeleteArray(line);
    634   }
    635 
    636   // Add all the breakpoints back to stop execution and enter the debugger
    637   // shell when hit.
    638   RedoBreakpoints();
    639 
    640 #undef COMMAND_SIZE
    641 #undef ARG_SIZE
    642 
    643 #undef STR
    644 #undef XSTR
    645 }
    646 
    647 
    648 static bool ICacheMatch(void* one, void* two) {
    649   ASSERT((reinterpret_cast<intptr_t>(one) & CachePage::kPageMask) == 0);
    650   ASSERT((reinterpret_cast<intptr_t>(two) & CachePage::kPageMask) == 0);
    651   return one == two;
    652 }
    653 
    654 
    655 static uint32_t ICacheHash(void* key) {
    656   return static_cast<uint32_t>(reinterpret_cast<uintptr_t>(key)) >> 2;
    657 }
    658 
    659 
    660 static bool AllOnOnePage(uintptr_t start, int size) {
    661   intptr_t start_page = (start & ~CachePage::kPageMask);
    662   intptr_t end_page = ((start + size) & ~CachePage::kPageMask);
    663   return start_page == end_page;
    664 }
    665 
    666 
    667 void Simulator::FlushICache(v8::internal::HashMap* i_cache,
    668                             void* start_addr,
    669                             size_t size) {
    670   intptr_t start = reinterpret_cast<intptr_t>(start_addr);
    671   int intra_line = (start & CachePage::kLineMask);
    672   start -= intra_line;
    673   size += intra_line;
    674   size = ((size - 1) | CachePage::kLineMask) + 1;
    675   int offset = (start & CachePage::kPageMask);
    676   while (!AllOnOnePage(start, size - 1)) {
    677     int bytes_to_flush = CachePage::kPageSize - offset;
    678     FlushOnePage(i_cache, start, bytes_to_flush);
    679     start += bytes_to_flush;
    680     size -= bytes_to_flush;
    681     ASSERT_EQ(0, start & CachePage::kPageMask);
    682     offset = 0;
    683   }
    684   if (size != 0) {
    685     FlushOnePage(i_cache, start, size);
    686   }
    687 }
    688 
    689 
    690 CachePage* Simulator::GetCachePage(v8::internal::HashMap* i_cache, void* page) {
    691   v8::internal::HashMap::Entry* entry = i_cache->Lookup(page,
    692                                                          ICacheHash(page),
    693                                                          true);
    694   if (entry->value == NULL) {
    695     CachePage* new_page = new CachePage();
    696     entry->value = new_page;
    697   }
    698   return reinterpret_cast<CachePage*>(entry->value);
    699 }
    700 
    701 
    702 // Flush from start up to and not including start + size.
    703 void Simulator::FlushOnePage(v8::internal::HashMap* i_cache,
    704                              intptr_t start,
    705                              int size) {
    706   ASSERT(size <= CachePage::kPageSize);
    707   ASSERT(AllOnOnePage(start, size - 1));
    708   ASSERT((start & CachePage::kLineMask) == 0);
    709   ASSERT((size & CachePage::kLineMask) == 0);
    710   void* page = reinterpret_cast<void*>(start & (~CachePage::kPageMask));
    711   int offset = (start & CachePage::kPageMask);
    712   CachePage* cache_page = GetCachePage(i_cache, page);
    713   char* valid_bytemap = cache_page->ValidityByte(offset);
    714   memset(valid_bytemap, CachePage::LINE_INVALID, size >> CachePage::kLineShift);
    715 }
    716 
    717 
    718 void Simulator::CheckICache(v8::internal::HashMap* i_cache,
    719                             Instruction* instr) {
    720   intptr_t address = reinterpret_cast<intptr_t>(instr);
    721   void* page = reinterpret_cast<void*>(address & (~CachePage::kPageMask));
    722   void* line = reinterpret_cast<void*>(address & (~CachePage::kLineMask));
    723   int offset = (address & CachePage::kPageMask);
    724   CachePage* cache_page = GetCachePage(i_cache, page);
    725   char* cache_valid_byte = cache_page->ValidityByte(offset);
    726   bool cache_hit = (*cache_valid_byte == CachePage::LINE_VALID);
    727   char* cached_line = cache_page->CachedData(offset & ~CachePage::kLineMask);
    728   if (cache_hit) {
    729     // Check that the data in memory matches the contents of the I-cache.
    730     CHECK(memcmp(reinterpret_cast<void*>(instr),
    731                  cache_page->CachedData(offset),
    732                  Instruction::kInstrSize) == 0);
    733   } else {
    734     // Cache miss.  Load memory into the cache.
    735     memcpy(cached_line, line, CachePage::kLineLength);
    736     *cache_valid_byte = CachePage::LINE_VALID;
    737   }
    738 }
    739 
    740 
    741 void Simulator::Initialize() {
    742   if (Isolate::Current()->simulator_initialized()) return;
    743   Isolate::Current()->set_simulator_initialized(true);
    744   ::v8::internal::ExternalReference::set_redirector(&RedirectExternalReference);
    745 }
    746 
    747 
    748 Simulator::Simulator() : isolate_(Isolate::Current()) {
    749   i_cache_ = isolate_->simulator_i_cache();
    750   if (i_cache_ == NULL) {
    751     i_cache_ = new v8::internal::HashMap(&ICacheMatch);
    752     isolate_->set_simulator_i_cache(i_cache_);
    753   }
    754   Initialize();
    755   // Setup simulator support first. Some of this information is needed to
    756   // setup the architecture state.
    757   stack_size_ = 1 * 1024*1024;  // allocate 1MB for stack
    758   stack_ = reinterpret_cast<char*>(malloc(stack_size_));
    759   pc_modified_ = false;
    760   icount_ = 0;
    761   break_count_ = 0;
    762   break_pc_ = NULL;
    763   break_instr_ = 0;
    764 
    765   // Setup architecture state.
    766   // All registers are initialized to zero to start with.
    767   for (int i = 0; i < kNumSimuRegisters; i++) {
    768     registers_[i] = 0;
    769   }
    770   for (int i = 0; i < kNumFPURegisters; i++) {
    771     FPUregisters_[i] = 0;
    772   }
    773   FCSR_ = 0;
    774 
    775   // The sp is initialized to point to the bottom (high address) of the
    776   // allocated stack area. To be safe in potential stack underflows we leave
    777   // some buffer below.
    778   registers_[sp] = reinterpret_cast<int32_t>(stack_) + stack_size_ - 64;
    779   // The ra and pc are initialized to a known bad value that will cause an
    780   // access violation if the simulator ever tries to execute it.
    781   registers_[pc] = bad_ra;
    782   registers_[ra] = bad_ra;
    783   InitializeCoverage();
    784   for (int i = 0; i < kNumExceptions; i++) {
    785     exceptions[i] = 0;
    786   }
    787 }
    788 
    789 
    790 // When the generated code calls an external reference we need to catch that in
    791 // the simulator.  The external reference will be a function compiled for the
    792 // host architecture.  We need to call that function instead of trying to
    793 // execute it with the simulator.  We do that by redirecting the external
    794 // reference to a swi (software-interrupt) instruction that is handled by
    795 // the simulator.  We write the original destination of the jump just at a known
    796 // offset from the swi instruction so the simulator knows what to call.
    797 class Redirection {
    798  public:
    799   Redirection(void* external_function, ExternalReference::Type type)
    800       : external_function_(external_function),
    801         swi_instruction_(rtCallRedirInstr),
    802         type_(type),
    803         next_(NULL) {
    804     Isolate* isolate = Isolate::Current();
    805     next_ = isolate->simulator_redirection();
    806     Simulator::current(isolate)->
    807         FlushICache(isolate->simulator_i_cache(),
    808                     reinterpret_cast<void*>(&swi_instruction_),
    809                     Instruction::kInstrSize);
    810     isolate->set_simulator_redirection(this);
    811   }
    812 
    813   void* address_of_swi_instruction() {
    814     return reinterpret_cast<void*>(&swi_instruction_);
    815   }
    816 
    817   void* external_function() { return external_function_; }
    818   ExternalReference::Type type() { return type_; }
    819 
    820   static Redirection* Get(void* external_function,
    821                           ExternalReference::Type type) {
    822     Isolate* isolate = Isolate::Current();
    823     Redirection* current = isolate->simulator_redirection();
    824     for (; current != NULL; current = current->next_) {
    825       if (current->external_function_ == external_function) return current;
    826     }
    827     return new Redirection(external_function, type);
    828   }
    829 
    830   static Redirection* FromSwiInstruction(Instruction* swi_instruction) {
    831     char* addr_of_swi = reinterpret_cast<char*>(swi_instruction);
    832     char* addr_of_redirection =
    833         addr_of_swi - OFFSET_OF(Redirection, swi_instruction_);
    834     return reinterpret_cast<Redirection*>(addr_of_redirection);
    835   }
    836 
    837  private:
    838   void* external_function_;
    839   uint32_t swi_instruction_;
    840   ExternalReference::Type type_;
    841   Redirection* next_;
    842 };
    843 
    844 
    845 void* Simulator::RedirectExternalReference(void* external_function,
    846                                            ExternalReference::Type type) {
    847   Redirection* redirection = Redirection::Get(external_function, type);
    848   return redirection->address_of_swi_instruction();
    849 }
    850 
    851 
    852 // Get the active Simulator for the current thread.
    853 Simulator* Simulator::current(Isolate* isolate) {
    854   v8::internal::Isolate::PerIsolateThreadData* isolate_data =
    855       Isolate::CurrentPerIsolateThreadData();
    856   if (isolate_data == NULL) {
    857     Isolate::EnterDefaultIsolate();
    858     isolate_data = Isolate::CurrentPerIsolateThreadData();
    859   }
    860   ASSERT(isolate_data != NULL);
    861 
    862   Simulator* sim = isolate_data->simulator();
    863   if (sim == NULL) {
    864     // TODO(146): delete the simulator object when a thread/isolate goes away.
    865     sim = new Simulator();
    866     isolate_data->set_simulator(sim);
    867   }
    868   return sim;
    869 }
    870 
    871 
    872 // Sets the register in the architecture state. It will also deal with updating
    873 // Simulator internal state for special registers such as PC.
    874 void Simulator::set_register(int reg, int32_t value) {
    875   ASSERT((reg >= 0) && (reg < kNumSimuRegisters));
    876   if (reg == pc) {
    877     pc_modified_ = true;
    878   }
    879 
    880   // zero register always hold 0.
    881   registers_[reg] = (reg == 0) ? 0 : value;
    882 }
    883 
    884 
    885 void Simulator::set_fpu_register(int fpureg, int32_t value) {
    886   ASSERT((fpureg >= 0) && (fpureg < kNumFPURegisters));
    887   FPUregisters_[fpureg] = value;
    888 }
    889 
    890 
    891 void Simulator::set_fpu_register_float(int fpureg, float value) {
    892   ASSERT((fpureg >= 0) && (fpureg < kNumFPURegisters));
    893   *BitCast<float*>(&FPUregisters_[fpureg]) = value;
    894 }
    895 
    896 
    897 void Simulator::set_fpu_register_double(int fpureg, double value) {
    898   ASSERT((fpureg >= 0) && (fpureg < kNumFPURegisters) && ((fpureg % 2) == 0));
    899   *BitCast<double*>(&FPUregisters_[fpureg]) = value;
    900 }
    901 
    902 
    903 // Get the register from the architecture state. This function does handle
    904 // the special case of accessing the PC register.
    905 int32_t Simulator::get_register(int reg) const {
    906   ASSERT((reg >= 0) && (reg < kNumSimuRegisters));
    907   if (reg == 0)
    908     return 0;
    909   else
    910     return registers_[reg] + ((reg == pc) ? Instruction::kPCReadOffset : 0);
    911 }
    912 
    913 
    914 int32_t Simulator::get_fpu_register(int fpureg) const {
    915   ASSERT((fpureg >= 0) && (fpureg < kNumFPURegisters));
    916   return FPUregisters_[fpureg];
    917 }
    918 
    919 
    920 int64_t Simulator::get_fpu_register_long(int fpureg) const {
    921   ASSERT((fpureg >= 0) && (fpureg < kNumFPURegisters) && ((fpureg % 2) == 0));
    922   return *BitCast<int64_t*>(
    923       const_cast<int32_t*>(&FPUregisters_[fpureg]));
    924 }
    925 
    926 
    927 float Simulator::get_fpu_register_float(int fpureg) const {
    928   ASSERT((fpureg >= 0) && (fpureg < kNumFPURegisters));
    929   return *BitCast<float*>(
    930       const_cast<int32_t*>(&FPUregisters_[fpureg]));
    931 }
    932 
    933 
    934 double Simulator::get_fpu_register_double(int fpureg) const {
    935   ASSERT((fpureg >= 0) && (fpureg < kNumFPURegisters) && ((fpureg % 2) == 0));
    936   return *BitCast<double*>(const_cast<int32_t*>(&FPUregisters_[fpureg]));
    937 }
    938 
    939 
    940 // Helper functions for setting and testing the FCSR register's bits.
    941 void Simulator::set_fcsr_bit(uint32_t cc, bool value) {
    942   if (value) {
    943     FCSR_ |= (1 << cc);
    944   } else {
    945     FCSR_ &= ~(1 << cc);
    946   }
    947 }
    948 
    949 
    950 bool Simulator::test_fcsr_bit(uint32_t cc) {
    951   return FCSR_ & (1 << cc);
    952 }
    953 
    954 
    955 // Sets the rounding error codes in FCSR based on the result of the rounding.
    956 // Returns true if the operation was invalid.
    957 bool Simulator::set_fcsr_round_error(double original, double rounded) {
    958   if (!isfinite(original) ||
    959       rounded > LONG_MAX ||
    960       rounded < LONG_MIN) {
    961     set_fcsr_bit(6, true);  // Invalid operation.
    962     return true;
    963   } else if (original != static_cast<double>(rounded)) {
    964     set_fcsr_bit(2, true);  // Inexact.
    965   }
    966   return false;
    967 }
    968 
    969 
    970 // Raw access to the PC register.
    971 void Simulator::set_pc(int32_t value) {
    972   pc_modified_ = true;
    973   registers_[pc] = value;
    974 }
    975 
    976 
    977 bool Simulator::has_bad_pc() const {
    978   return ((registers_[pc] == bad_ra) || (registers_[pc] == end_sim_pc));
    979 }
    980 
    981 
    982 // Raw access to the PC register without the special adjustment when reading.
    983 int32_t Simulator::get_pc() const {
    984   return registers_[pc];
    985 }
    986 
    987 
    988 // The MIPS cannot do unaligned reads and writes.  On some MIPS platforms an
    989 // interrupt is caused.  On others it does a funky rotation thing.  For now we
    990 // simply disallow unaligned reads, but at some point we may want to move to
    991 // emulating the rotate behaviour.  Note that simulator runs have the runtime
    992 // system running directly on the host system and only generated code is
    993 // executed in the simulator.  Since the host is typically IA32 we will not
    994 // get the correct MIPS-like behaviour on unaligned accesses.
    995 
    996 int Simulator::ReadW(int32_t addr, Instruction* instr) {
    997   if (addr >=0 && addr < 0x400) {
    998     // this has to be a NULL-dereference
    999     MipsDebugger dbg(this);
   1000     dbg.Debug();
   1001   }
   1002   if ((addr & kPointerAlignmentMask) == 0) {
   1003     intptr_t* ptr = reinterpret_cast<intptr_t*>(addr);
   1004     return *ptr;
   1005   }
   1006   PrintF("Unaligned read at 0x%08x, pc=%p\n", addr,
   1007       reinterpret_cast<void*>(instr));
   1008   MipsDebugger dbg(this);
   1009   dbg.Debug();
   1010   return 0;
   1011 }
   1012 
   1013 
   1014 void Simulator::WriteW(int32_t addr, int value, Instruction* instr) {
   1015   if (addr >= 0 && addr < 0x400) {
   1016     // this has to be a NULL-dereference
   1017     MipsDebugger dbg(this);
   1018     dbg.Debug();
   1019   }
   1020   if ((addr & kPointerAlignmentMask) == 0) {
   1021     intptr_t* ptr = reinterpret_cast<intptr_t*>(addr);
   1022     *ptr = value;
   1023     return;
   1024   }
   1025   PrintF("Unaligned write at 0x%08x, pc=%p\n", addr,
   1026       reinterpret_cast<void*>(instr));
   1027   MipsDebugger dbg(this);
   1028   dbg.Debug();
   1029 }
   1030 
   1031 
   1032 double Simulator::ReadD(int32_t addr, Instruction* instr) {
   1033   if ((addr & kDoubleAlignmentMask) == 0) {
   1034     double* ptr = reinterpret_cast<double*>(addr);
   1035     return *ptr;
   1036   }
   1037   PrintF("Unaligned (double) read at 0x%08x, pc=%p\n", addr,
   1038       reinterpret_cast<void*>(instr));
   1039   OS::Abort();
   1040   return 0;
   1041 }
   1042 
   1043 
   1044 void Simulator::WriteD(int32_t addr, double value, Instruction* instr) {
   1045   if ((addr & kDoubleAlignmentMask) == 0) {
   1046     double* ptr = reinterpret_cast<double*>(addr);
   1047     *ptr = value;
   1048     return;
   1049   }
   1050   PrintF("Unaligned (double) write at 0x%08x, pc=%p\n", addr,
   1051       reinterpret_cast<void*>(instr));
   1052   OS::Abort();
   1053 }
   1054 
   1055 
   1056 uint16_t Simulator::ReadHU(int32_t addr, Instruction* instr) {
   1057   if ((addr & 1) == 0) {
   1058     uint16_t* ptr = reinterpret_cast<uint16_t*>(addr);
   1059     return *ptr;
   1060   }
   1061   PrintF("Unaligned unsigned halfword read at 0x%08x, pc=%p\n", addr,
   1062       reinterpret_cast<void*>(instr));
   1063   OS::Abort();
   1064   return 0;
   1065 }
   1066 
   1067 
   1068 int16_t Simulator::ReadH(int32_t addr, Instruction* instr) {
   1069   if ((addr & 1) == 0) {
   1070     int16_t* ptr = reinterpret_cast<int16_t*>(addr);
   1071     return *ptr;
   1072   }
   1073   PrintF("Unaligned signed halfword read at 0x%08x, pc=%p\n", addr,
   1074       reinterpret_cast<void*>(instr));
   1075   OS::Abort();
   1076   return 0;
   1077 }
   1078 
   1079 
   1080 void Simulator::WriteH(int32_t addr, uint16_t value, Instruction* instr) {
   1081   if ((addr & 1) == 0) {
   1082     uint16_t* ptr = reinterpret_cast<uint16_t*>(addr);
   1083     *ptr = value;
   1084     return;
   1085   }
   1086   PrintF("Unaligned unsigned halfword write at 0x%08x, pc=%p\n", addr,
   1087       reinterpret_cast<void*>(instr));
   1088   OS::Abort();
   1089 }
   1090 
   1091 
   1092 void Simulator::WriteH(int32_t addr, int16_t value, Instruction* instr) {
   1093   if ((addr & 1) == 0) {
   1094     int16_t* ptr = reinterpret_cast<int16_t*>(addr);
   1095     *ptr = value;
   1096     return;
   1097   }
   1098   PrintF("Unaligned halfword write at 0x%08x, pc=%p\n", addr,
   1099       reinterpret_cast<void*>(instr));
   1100   OS::Abort();
   1101 }
   1102 
   1103 
   1104 uint32_t Simulator::ReadBU(int32_t addr) {
   1105   uint8_t* ptr = reinterpret_cast<uint8_t*>(addr);
   1106   return *ptr & 0xff;
   1107 }
   1108 
   1109 
   1110 int32_t Simulator::ReadB(int32_t addr) {
   1111   int8_t* ptr = reinterpret_cast<int8_t*>(addr);
   1112   return *ptr;
   1113 }
   1114 
   1115 
   1116 void Simulator::WriteB(int32_t addr, uint8_t value) {
   1117   uint8_t* ptr = reinterpret_cast<uint8_t*>(addr);
   1118   *ptr = value;
   1119 }
   1120 
   1121 
   1122 void Simulator::WriteB(int32_t addr, int8_t value) {
   1123   int8_t* ptr = reinterpret_cast<int8_t*>(addr);
   1124   *ptr = value;
   1125 }
   1126 
   1127 
   1128 // Returns the limit of the stack area to enable checking for stack overflows.
   1129 uintptr_t Simulator::StackLimit() const {
   1130   // Leave a safety margin of 256 bytes to prevent overrunning the stack when
   1131   // pushing values.
   1132   return reinterpret_cast<uintptr_t>(stack_) + 256;
   1133 }
   1134 
   1135 
   1136 // Unsupported instructions use Format to print an error and stop execution.
   1137 void Simulator::Format(Instruction* instr, const char* format) {
   1138   PrintF("Simulator found unsupported instruction:\n 0x%08x: %s\n",
   1139          reinterpret_cast<intptr_t>(instr), format);
   1140   UNIMPLEMENTED_MIPS();
   1141 }
   1142 
   1143 
   1144 // Calls into the V8 runtime are based on this very simple interface.
   1145 // Note: To be able to return two values from some calls the code in runtime.cc
   1146 // uses the ObjectPair which is essentially two 32-bit values stuffed into a
   1147 // 64-bit value. With the code below we assume that all runtime calls return
   1148 // 64 bits of result. If they don't, the v1 result register contains a bogus
   1149 // value, which is fine because it is caller-saved.
   1150 typedef int64_t (*SimulatorRuntimeCall)(int32_t arg0,
   1151                                         int32_t arg1,
   1152                                         int32_t arg2,
   1153                                         int32_t arg3,
   1154                                         int32_t arg4,
   1155                                         int32_t arg5);
   1156 typedef double (*SimulatorRuntimeFPCall)(int32_t arg0,
   1157                                          int32_t arg1,
   1158                                          int32_t arg2,
   1159                                          int32_t arg3);
   1160 
   1161 // Software interrupt instructions are used by the simulator to call into the
   1162 // C-based V8 runtime. They are also used for debugging with simulator.
   1163 void Simulator::SoftwareInterrupt(Instruction* instr) {
   1164   // There are several instructions that could get us here,
   1165   // the break_ instruction, or several variants of traps. All
   1166   // Are "SPECIAL" class opcode, and are distinuished by function.
   1167   int32_t func = instr->FunctionFieldRaw();
   1168   int32_t code = (func == BREAK) ? instr->Bits(25, 6) : -1;
   1169 
   1170   // We first check if we met a call_rt_redirected.
   1171   if (instr->InstructionBits() == rtCallRedirInstr) {
   1172     // Check if stack is aligned. Error if not aligned is reported below to
   1173     // include information on the function called.
   1174     bool stack_aligned =
   1175         (get_register(sp)
   1176          & (::v8::internal::FLAG_sim_stack_alignment - 1)) == 0;
   1177     Redirection* redirection = Redirection::FromSwiInstruction(instr);
   1178     int32_t arg0 = get_register(a0);
   1179     int32_t arg1 = get_register(a1);
   1180     int32_t arg2 = get_register(a2);
   1181     int32_t arg3 = get_register(a3);
   1182     int32_t arg4 = 0;
   1183     int32_t arg5 = 0;
   1184 
   1185     // Need to check if sp is valid before assigning arg4, arg5.
   1186     // This is a fix for cctest test-api/CatchStackOverflow which causes
   1187     // the stack to overflow. For some reason arm doesn't need this
   1188     // stack check here.
   1189     int32_t* stack_pointer = reinterpret_cast<int32_t*>(get_register(sp));
   1190     int32_t* stack = reinterpret_cast<int32_t*>(stack_);
   1191     if (stack_pointer >= stack && stack_pointer < stack + stack_size_) {
   1192       arg4 = stack_pointer[0];
   1193       arg5 = stack_pointer[1];
   1194     }
   1195     // This is dodgy but it works because the C entry stubs are never moved.
   1196     // See comment in codegen-arm.cc and bug 1242173.
   1197     int32_t saved_ra = get_register(ra);
   1198 
   1199     intptr_t external =
   1200         reinterpret_cast<int32_t>(redirection->external_function());
   1201 
   1202     // Based on CpuFeatures::IsSupported(FPU), Mips will use either hardware
   1203     // FPU, or gcc soft-float routines. Hardware FPU is simulated in this
   1204     // simulator. Soft-float has additional abstraction of ExternalReference,
   1205     // to support serialization. Finally, when simulated on x86 host, the
   1206     // x86 softfloat routines are used, and this Redirection infrastructure
   1207     // lets simulated-mips make calls into x86 C code.
   1208     // When doing that, the 'double' return type must be handled differently
   1209     // than the usual int64_t return. The data is returned in different
   1210     // registers and cannot be cast from one type to the other. However, the
   1211     // calling arguments are passed the same way in both cases.
   1212     if (redirection->type() == ExternalReference::FP_RETURN_CALL) {
   1213       SimulatorRuntimeFPCall target =
   1214           reinterpret_cast<SimulatorRuntimeFPCall>(external);
   1215       if (::v8::internal::FLAG_trace_sim || !stack_aligned) {
   1216         PrintF("Call to host function at %p with args %08x:%08x %08x:%08x",
   1217                FUNCTION_ADDR(target), arg0, arg1, arg2, arg3);
   1218         if (!stack_aligned) {
   1219           PrintF(" with unaligned stack %08x\n", get_register(sp));
   1220         }
   1221         PrintF("\n");
   1222       }
   1223       double result = target(arg0, arg1, arg2, arg3);
   1224       // fp result -> registers v0 and v1.
   1225       int32_t gpreg_pair[2];
   1226       memcpy(&gpreg_pair[0], &result, 2 * sizeof(int32_t));
   1227       set_register(v0, gpreg_pair[0]);
   1228       set_register(v1, gpreg_pair[1]);
   1229     } else if (redirection->type() == ExternalReference::DIRECT_API_CALL) {
   1230       PrintF("Mips does not yet support ExternalReference::DIRECT_API_CALL\n");
   1231       ASSERT(redirection->type() != ExternalReference::DIRECT_API_CALL);
   1232     } else if (redirection->type() == ExternalReference::DIRECT_GETTER_CALL) {
   1233       PrintF("Mips does not support ExternalReference::DIRECT_GETTER_CALL\n");
   1234       ASSERT(redirection->type() != ExternalReference::DIRECT_GETTER_CALL);
   1235     } else {
   1236       // Builtin call.
   1237       ASSERT(redirection->type() == ExternalReference::BUILTIN_CALL);
   1238       SimulatorRuntimeCall target =
   1239           reinterpret_cast<SimulatorRuntimeCall>(external);
   1240       if (::v8::internal::FLAG_trace_sim || !stack_aligned) {
   1241         PrintF(
   1242             "Call to host function at %p: %08x, %08x, %08x, %08x, %08x, %08x",
   1243             FUNCTION_ADDR(target),
   1244             arg0,
   1245             arg1,
   1246             arg2,
   1247             arg3,
   1248             arg4,
   1249             arg5);
   1250         if (!stack_aligned) {
   1251           PrintF(" with unaligned stack %08x\n", get_register(sp));
   1252         }
   1253         PrintF("\n");
   1254       }
   1255 
   1256       int64_t result = target(arg0, arg1, arg2, arg3, arg4, arg5);
   1257       set_register(v0, static_cast<int32_t>(result));
   1258       set_register(v1, static_cast<int32_t>(result >> 32));
   1259     }
   1260     if (::v8::internal::FLAG_trace_sim) {
   1261       PrintF("Returned %08x : %08x\n", get_register(v1), get_register(v0));
   1262     }
   1263     set_register(ra, saved_ra);
   1264     set_pc(get_register(ra));
   1265 
   1266   } else if (func == BREAK && code >= 0 && code < 16) {
   1267     // First 16 break_ codes interpreted as debug markers.
   1268     MipsDebugger dbg(this);
   1269     ++break_count_;
   1270     PrintF("\n---- break %d marker: %3d  (instr count: %8d) ----------"
   1271            "----------------------------------",
   1272            code, break_count_, icount_);
   1273     dbg.PrintAllRegs();  // Print registers and continue running.
   1274   } else {
   1275     // All remaining break_ codes, and all traps are handled here.
   1276     MipsDebugger dbg(this);
   1277     dbg.Debug();
   1278   }
   1279 }
   1280 
   1281 
   1282 void Simulator::SignalExceptions() {
   1283   for (int i = 1; i < kNumExceptions; i++) {
   1284     if (exceptions[i] != 0) {
   1285       V8_Fatal(__FILE__, __LINE__, "Error: Exception %i raised.", i);
   1286     }
   1287   }
   1288 }
   1289 
   1290 
   1291 // Handle execution based on instruction types.
   1292 
   1293 void Simulator::ConfigureTypeRegister(Instruction* instr,
   1294                                       int32_t& alu_out,
   1295                                       int64_t& i64hilo,
   1296                                       uint64_t& u64hilo,
   1297                                       int32_t& next_pc,
   1298                                       bool& do_interrupt) {
   1299   // Every local variable declared here needs to be const.
   1300   // This is to make sure that changed values are sent back to
   1301   // DecodeTypeRegister correctly.
   1302 
   1303   // Instruction fields.
   1304   const Opcode   op     = instr->OpcodeFieldRaw();
   1305   const int32_t  rs_reg = instr->RsValue();
   1306   const int32_t  rs     = get_register(rs_reg);
   1307   const uint32_t rs_u   = static_cast<uint32_t>(rs);
   1308   const int32_t  rt_reg = instr->RtValue();
   1309   const int32_t  rt     = get_register(rt_reg);
   1310   const uint32_t rt_u   = static_cast<uint32_t>(rt);
   1311   const int32_t  rd_reg = instr->RdValue();
   1312   const uint32_t sa     = instr->SaValue();
   1313 
   1314   const int32_t  fs_reg = instr->FsValue();
   1315 
   1316 
   1317   // ---------- Configuration
   1318   switch (op) {
   1319     case COP1:    // Coprocessor instructions
   1320       switch (instr->RsFieldRaw()) {
   1321         case BC1:   // Handled in DecodeTypeImmed, should never come here.
   1322           UNREACHABLE();
   1323           break;
   1324         case CFC1:
   1325           // At the moment only FCSR is supported.
   1326           ASSERT(fs_reg == kFCSRRegister);
   1327           alu_out = FCSR_;
   1328           break;
   1329         case MFC1:
   1330           alu_out = get_fpu_register(fs_reg);
   1331           break;
   1332         case MFHC1:
   1333           UNIMPLEMENTED_MIPS();
   1334           break;
   1335         case CTC1:
   1336         case MTC1:
   1337         case MTHC1:
   1338           // Do the store in the execution step.
   1339           break;
   1340         case S:
   1341         case D:
   1342         case W:
   1343         case L:
   1344         case PS:
   1345           // Do everything in the execution step.
   1346           break;
   1347         default:
   1348           UNIMPLEMENTED_MIPS();
   1349       };
   1350       break;
   1351     case SPECIAL:
   1352       switch (instr->FunctionFieldRaw()) {
   1353         case JR:
   1354         case JALR:
   1355           next_pc = get_register(instr->RsValue());
   1356           break;
   1357         case SLL:
   1358           alu_out = rt << sa;
   1359           break;
   1360         case SRL:
   1361           if (rs_reg == 0) {
   1362             // Regular logical right shift of a word by a fixed number of
   1363             // bits instruction. RS field is always equal to 0.
   1364             alu_out = rt_u >> sa;
   1365           } else {
   1366             // Logical right-rotate of a word by a fixed number of bits. This
   1367             // is special case of SRL instruction, added in MIPS32 Release 2.
   1368             // RS field is equal to 00001
   1369             alu_out = (rt_u >> sa) | (rt_u << (32 - sa));
   1370           }
   1371           break;
   1372         case SRA:
   1373           alu_out = rt >> sa;
   1374           break;
   1375         case SLLV:
   1376           alu_out = rt << rs;
   1377           break;
   1378         case SRLV:
   1379           if (sa == 0) {
   1380             // Regular logical right-shift of a word by a variable number of
   1381             // bits instruction. SA field is always equal to 0.
   1382             alu_out = rt_u >> rs;
   1383           } else {
   1384             // Logical right-rotate of a word by a variable number of bits.
   1385             // This is special case od SRLV instruction, added in MIPS32
   1386             // Release 2. SA field is equal to 00001
   1387             alu_out = (rt_u >> rs_u) | (rt_u << (32 - rs_u));
   1388           }
   1389           break;
   1390         case SRAV:
   1391           alu_out = rt >> rs;
   1392           break;
   1393         case MFHI:
   1394           alu_out = get_register(HI);
   1395           break;
   1396         case MFLO:
   1397           alu_out = get_register(LO);
   1398           break;
   1399         case MULT:
   1400           i64hilo = static_cast<int64_t>(rs) * static_cast<int64_t>(rt);
   1401           break;
   1402         case MULTU:
   1403           u64hilo = static_cast<uint64_t>(rs_u) * static_cast<uint64_t>(rt_u);
   1404           break;
   1405         case DIV:
   1406         case DIVU:
   1407             exceptions[kDivideByZero] = rt == 0;
   1408           break;
   1409         case ADD:
   1410           if (HaveSameSign(rs, rt)) {
   1411             if (rs > 0) {
   1412               exceptions[kIntegerOverflow] = rs > (Registers::kMaxValue - rt);
   1413             } else if (rs < 0) {
   1414               exceptions[kIntegerUnderflow] = rs < (Registers::kMinValue - rt);
   1415             }
   1416           }
   1417           alu_out = rs + rt;
   1418           break;
   1419         case ADDU:
   1420           alu_out = rs + rt;
   1421           break;
   1422         case SUB:
   1423           if (!HaveSameSign(rs, rt)) {
   1424             if (rs > 0) {
   1425               exceptions[kIntegerOverflow] = rs > (Registers::kMaxValue + rt);
   1426             } else if (rs < 0) {
   1427               exceptions[kIntegerUnderflow] = rs < (Registers::kMinValue + rt);
   1428             }
   1429           }
   1430           alu_out = rs - rt;
   1431           break;
   1432         case SUBU:
   1433           alu_out = rs - rt;
   1434           break;
   1435         case AND:
   1436           alu_out = rs & rt;
   1437           break;
   1438         case OR:
   1439           alu_out = rs | rt;
   1440           break;
   1441         case XOR:
   1442           alu_out = rs ^ rt;
   1443           break;
   1444         case NOR:
   1445           alu_out = ~(rs | rt);
   1446           break;
   1447         case SLT:
   1448           alu_out = rs < rt ? 1 : 0;
   1449           break;
   1450         case SLTU:
   1451           alu_out = rs_u < rt_u ? 1 : 0;
   1452           break;
   1453         // Break and trap instructions
   1454         case BREAK:
   1455 
   1456           do_interrupt = true;
   1457           break;
   1458         case TGE:
   1459           do_interrupt = rs >= rt;
   1460           break;
   1461         case TGEU:
   1462           do_interrupt = rs_u >= rt_u;
   1463           break;
   1464         case TLT:
   1465           do_interrupt = rs < rt;
   1466           break;
   1467         case TLTU:
   1468           do_interrupt = rs_u < rt_u;
   1469           break;
   1470         case TEQ:
   1471           do_interrupt = rs == rt;
   1472           break;
   1473         case TNE:
   1474           do_interrupt = rs != rt;
   1475           break;
   1476         case MOVN:
   1477         case MOVZ:
   1478         case MOVCI:
   1479           // No action taken on decode.
   1480           break;
   1481         default:
   1482           UNREACHABLE();
   1483       };
   1484       break;
   1485     case SPECIAL2:
   1486       switch (instr->FunctionFieldRaw()) {
   1487         case MUL:
   1488           alu_out = rs_u * rt_u;  // Only the lower 32 bits are kept.
   1489           break;
   1490         case CLZ:
   1491           alu_out = __builtin_clz(rs_u);
   1492           break;
   1493         default:
   1494           UNREACHABLE();
   1495       };
   1496       break;
   1497     case SPECIAL3:
   1498       switch (instr->FunctionFieldRaw()) {
   1499         case INS: {   // Mips32r2 instruction.
   1500           // Interpret Rd field as 5-bit msb of insert.
   1501           uint16_t msb = rd_reg;
   1502           // Interpret sa field as 5-bit lsb of insert.
   1503           uint16_t lsb = sa;
   1504           uint16_t size = msb - lsb + 1;
   1505           uint32_t mask = (1 << size) - 1;
   1506           alu_out = (rt_u & ~(mask << lsb)) | ((rs_u & mask) << lsb);
   1507           break;
   1508         }
   1509         case EXT: {   // Mips32r2 instruction.
   1510           // Interpret Rd field as 5-bit msb of extract.
   1511           uint16_t msb = rd_reg;
   1512           // Interpret sa field as 5-bit lsb of extract.
   1513           uint16_t lsb = sa;
   1514           uint16_t size = msb + 1;
   1515           uint32_t mask = (1 << size) - 1;
   1516           alu_out = (rs_u & (mask << lsb)) >> lsb;
   1517           break;
   1518         }
   1519         default:
   1520           UNREACHABLE();
   1521       };
   1522       break;
   1523     default:
   1524       UNREACHABLE();
   1525   };
   1526 }
   1527 
   1528 
   1529 void Simulator::DecodeTypeRegister(Instruction* instr) {
   1530   // Instruction fields.
   1531   const Opcode   op     = instr->OpcodeFieldRaw();
   1532   const int32_t  rs_reg = instr->RsValue();
   1533   const int32_t  rs     = get_register(rs_reg);
   1534   const uint32_t rs_u   = static_cast<uint32_t>(rs);
   1535   const int32_t  rt_reg = instr->RtValue();
   1536   const int32_t  rt     = get_register(rt_reg);
   1537   const uint32_t rt_u   = static_cast<uint32_t>(rt);
   1538   const int32_t  rd_reg = instr->RdValue();
   1539 
   1540   const int32_t  fs_reg = instr->FsValue();
   1541   const int32_t  ft_reg = instr->FtValue();
   1542   const int32_t  fd_reg = instr->FdValue();
   1543   int64_t  i64hilo = 0;
   1544   uint64_t u64hilo = 0;
   1545 
   1546   // ALU output
   1547   // It should not be used as is. Instructions using it should always
   1548   // initialize it first.
   1549   int32_t alu_out = 0x12345678;
   1550 
   1551   // For break and trap instructions.
   1552   bool do_interrupt = false;
   1553 
   1554   // For jr and jalr
   1555   // Get current pc.
   1556   int32_t current_pc = get_pc();
   1557   // Next pc
   1558   int32_t next_pc = 0;
   1559 
   1560   // Setup the variables if needed before executing the instruction.
   1561   ConfigureTypeRegister(instr,
   1562                         alu_out,
   1563                         i64hilo,
   1564                         u64hilo,
   1565                         next_pc,
   1566                         do_interrupt);
   1567 
   1568   // ---------- Raise exceptions triggered.
   1569   SignalExceptions();
   1570 
   1571   // ---------- Execution
   1572   switch (op) {
   1573     case COP1:
   1574       switch (instr->RsFieldRaw()) {
   1575         case BC1:   // branch on coprocessor condition
   1576           UNREACHABLE();
   1577           break;
   1578         case CFC1:
   1579           set_register(rt_reg, alu_out);
   1580         case MFC1:
   1581           set_register(rt_reg, alu_out);
   1582           break;
   1583         case MFHC1:
   1584           UNIMPLEMENTED_MIPS();
   1585           break;
   1586         case CTC1:
   1587           // At the moment only FCSR is supported.
   1588           ASSERT(fs_reg == kFCSRRegister);
   1589           FCSR_ = registers_[rt_reg];
   1590           break;
   1591         case MTC1:
   1592           FPUregisters_[fs_reg] = registers_[rt_reg];
   1593           break;
   1594         case MTHC1:
   1595           UNIMPLEMENTED_MIPS();
   1596           break;
   1597         case S:
   1598           float f;
   1599           switch (instr->FunctionFieldRaw()) {
   1600             case CVT_D_S:
   1601               f = get_fpu_register_float(fs_reg);
   1602               set_fpu_register_double(fd_reg, static_cast<double>(f));
   1603               break;
   1604             case CVT_W_S:
   1605             case CVT_L_S:
   1606             case TRUNC_W_S:
   1607             case TRUNC_L_S:
   1608             case ROUND_W_S:
   1609             case ROUND_L_S:
   1610             case FLOOR_W_S:
   1611             case FLOOR_L_S:
   1612             case CEIL_W_S:
   1613             case CEIL_L_S:
   1614             case CVT_PS_S:
   1615               UNIMPLEMENTED_MIPS();
   1616               break;
   1617             default:
   1618               UNREACHABLE();
   1619           }
   1620           break;
   1621         case D:
   1622           double ft, fs;
   1623           uint32_t cc, fcsr_cc;
   1624           int64_t  i64;
   1625           fs = get_fpu_register_double(fs_reg);
   1626           ft = get_fpu_register_double(ft_reg);
   1627           cc = instr->FCccValue();
   1628           fcsr_cc = get_fcsr_condition_bit(cc);
   1629           switch (instr->FunctionFieldRaw()) {
   1630             case ADD_D:
   1631               set_fpu_register_double(fd_reg, fs + ft);
   1632               break;
   1633             case SUB_D:
   1634               set_fpu_register_double(fd_reg, fs - ft);
   1635               break;
   1636             case MUL_D:
   1637               set_fpu_register_double(fd_reg, fs * ft);
   1638               break;
   1639             case DIV_D:
   1640               set_fpu_register_double(fd_reg, fs / ft);
   1641               break;
   1642             case ABS_D:
   1643               set_fpu_register_double(fd_reg, fs < 0 ? -fs : fs);
   1644               break;
   1645             case MOV_D:
   1646               set_fpu_register_double(fd_reg, fs);
   1647               break;
   1648             case NEG_D:
   1649               set_fpu_register_double(fd_reg, -fs);
   1650               break;
   1651             case SQRT_D:
   1652               set_fpu_register_double(fd_reg, sqrt(fs));
   1653               break;
   1654             case C_UN_D:
   1655               set_fcsr_bit(fcsr_cc, isnan(fs) || isnan(ft));
   1656               break;
   1657             case C_EQ_D:
   1658               set_fcsr_bit(fcsr_cc, (fs == ft));
   1659               break;
   1660             case C_UEQ_D:
   1661               set_fcsr_bit(fcsr_cc, (fs == ft) || (isnan(fs) || isnan(ft)));
   1662               break;
   1663             case C_OLT_D:
   1664               set_fcsr_bit(fcsr_cc, (fs < ft));
   1665               break;
   1666             case C_ULT_D:
   1667               set_fcsr_bit(fcsr_cc, (fs < ft) || (isnan(fs) || isnan(ft)));
   1668               break;
   1669             case C_OLE_D:
   1670               set_fcsr_bit(fcsr_cc, (fs <= ft));
   1671               break;
   1672             case C_ULE_D:
   1673               set_fcsr_bit(fcsr_cc, (fs <= ft) || (isnan(fs) || isnan(ft)));
   1674               break;
   1675             case CVT_W_D:   // Convert double to word.
   1676               // Rounding modes are not yet supported.
   1677               ASSERT((FCSR_ & 3) == 0);
   1678               // In rounding mode 0 it should behave like ROUND.
   1679             case ROUND_W_D:  // Round double to word.
   1680               {
   1681                 double rounded = fs > 0 ? floor(fs + 0.5) : ceil(fs - 0.5);
   1682                 int32_t result = static_cast<int32_t>(rounded);
   1683                 set_fpu_register(fd_reg, result);
   1684                 if (set_fcsr_round_error(fs, rounded)) {
   1685                   set_fpu_register(fd_reg, kFPUInvalidResult);
   1686                 }
   1687               }
   1688               break;
   1689             case TRUNC_W_D:  // Truncate double to word (round towards 0).
   1690               {
   1691                 int32_t result = static_cast<int32_t>(fs);
   1692                 set_fpu_register(fd_reg, result);
   1693                 if (set_fcsr_round_error(fs, static_cast<double>(result))) {
   1694                   set_fpu_register(fd_reg, kFPUInvalidResult);
   1695                 }
   1696               }
   1697               break;
   1698             case FLOOR_W_D:  // Round double to word towards negative infinity.
   1699               {
   1700                 double rounded = floor(fs);
   1701                 int32_t result = static_cast<int32_t>(rounded);
   1702                 set_fpu_register(fd_reg, result);
   1703                 if (set_fcsr_round_error(fs, rounded)) {
   1704                   set_fpu_register(fd_reg, kFPUInvalidResult);
   1705                 }
   1706               }
   1707               break;
   1708             case CEIL_W_D:  // Round double to word towards positive infinity.
   1709               {
   1710                 double rounded = ceil(fs);
   1711                 int32_t result = static_cast<int32_t>(rounded);
   1712                 set_fpu_register(fd_reg, result);
   1713                 if (set_fcsr_round_error(fs, rounded)) {
   1714                   set_fpu_register(fd_reg, kFPUInvalidResult);
   1715                 }
   1716               }
   1717               break;
   1718             case CVT_S_D:  // Convert double to float (single).
   1719               set_fpu_register_float(fd_reg, static_cast<float>(fs));
   1720               break;
   1721             case CVT_L_D:  // Mips32r2: Truncate double to 64-bit long-word.
   1722               i64 = static_cast<int64_t>(fs);
   1723               set_fpu_register(fd_reg, i64 & 0xffffffff);
   1724               set_fpu_register(fd_reg + 1, i64 >> 32);
   1725               break;
   1726             case TRUNC_L_D:  // Mips32r2 instruction.
   1727               i64 = static_cast<int64_t>(fs);
   1728               set_fpu_register(fd_reg, i64 & 0xffffffff);
   1729               set_fpu_register(fd_reg + 1, i64 >> 32);
   1730               break;
   1731             case ROUND_L_D: {  // Mips32r2 instruction.
   1732               double rounded = fs > 0 ? floor(fs + 0.5) : ceil(fs - 0.5);
   1733               i64 = static_cast<int64_t>(rounded);
   1734               set_fpu_register(fd_reg, i64 & 0xffffffff);
   1735               set_fpu_register(fd_reg + 1, i64 >> 32);
   1736               break;
   1737             }
   1738             case FLOOR_L_D:  // Mips32r2 instruction.
   1739               i64 = static_cast<int64_t>(floor(fs));
   1740               set_fpu_register(fd_reg, i64 & 0xffffffff);
   1741               set_fpu_register(fd_reg + 1, i64 >> 32);
   1742               break;
   1743             case CEIL_L_D:  // Mips32r2 instruction.
   1744               i64 = static_cast<int64_t>(ceil(fs));
   1745               set_fpu_register(fd_reg, i64 & 0xffffffff);
   1746               set_fpu_register(fd_reg + 1, i64 >> 32);
   1747               break;
   1748             case C_F_D:
   1749               UNIMPLEMENTED_MIPS();
   1750               break;
   1751             default:
   1752               UNREACHABLE();
   1753           }
   1754           break;
   1755         case W:
   1756           switch (instr->FunctionFieldRaw()) {
   1757             case CVT_S_W:   // Convert word to float (single).
   1758               alu_out = get_fpu_register(fs_reg);
   1759               set_fpu_register_float(fd_reg, static_cast<float>(alu_out));
   1760               break;
   1761             case CVT_D_W:   // Convert word to double.
   1762               alu_out = get_fpu_register(fs_reg);
   1763               set_fpu_register_double(fd_reg, static_cast<double>(alu_out));
   1764               break;
   1765             default:
   1766               UNREACHABLE();
   1767           };
   1768           break;
   1769         case L:
   1770           switch (instr->FunctionFieldRaw()) {
   1771           case CVT_D_L:  // Mips32r2 instruction.
   1772             // Watch the signs here, we want 2 32-bit vals
   1773             // to make a sign-64.
   1774             i64 = (uint32_t) get_fpu_register(fs_reg);
   1775             i64 |= ((int64_t) get_fpu_register(fs_reg + 1) << 32);
   1776             set_fpu_register_double(fd_reg, static_cast<double>(i64));
   1777             break;
   1778             case CVT_S_L:
   1779               UNIMPLEMENTED_MIPS();
   1780               break;
   1781             default:
   1782               UNREACHABLE();
   1783           }
   1784           break;
   1785         case PS:
   1786           break;
   1787         default:
   1788           UNREACHABLE();
   1789       };
   1790       break;
   1791     case SPECIAL:
   1792       switch (instr->FunctionFieldRaw()) {
   1793         case JR: {
   1794           Instruction* branch_delay_instr = reinterpret_cast<Instruction*>(
   1795               current_pc+Instruction::kInstrSize);
   1796           BranchDelayInstructionDecode(branch_delay_instr);
   1797           set_pc(next_pc);
   1798           pc_modified_ = true;
   1799           break;
   1800         }
   1801         case JALR: {
   1802           Instruction* branch_delay_instr = reinterpret_cast<Instruction*>(
   1803               current_pc+Instruction::kInstrSize);
   1804           BranchDelayInstructionDecode(branch_delay_instr);
   1805           set_register(31, current_pc + 2* Instruction::kInstrSize);
   1806           set_pc(next_pc);
   1807           pc_modified_ = true;
   1808           break;
   1809         }
   1810         // Instructions using HI and LO registers.
   1811         case MULT:
   1812           set_register(LO, static_cast<int32_t>(i64hilo & 0xffffffff));
   1813           set_register(HI, static_cast<int32_t>(i64hilo >> 32));
   1814           break;
   1815         case MULTU:
   1816           set_register(LO, static_cast<int32_t>(u64hilo & 0xffffffff));
   1817           set_register(HI, static_cast<int32_t>(u64hilo >> 32));
   1818           break;
   1819         case DIV:
   1820           // Divide by zero was checked in the configuration step.
   1821           set_register(LO, rs / rt);
   1822           set_register(HI, rs % rt);
   1823           break;
   1824         case DIVU:
   1825           set_register(LO, rs_u / rt_u);
   1826           set_register(HI, rs_u % rt_u);
   1827           break;
   1828         // Break and trap instructions.
   1829         case BREAK:
   1830         case TGE:
   1831         case TGEU:
   1832         case TLT:
   1833         case TLTU:
   1834         case TEQ:
   1835         case TNE:
   1836           if (do_interrupt) {
   1837             SoftwareInterrupt(instr);
   1838           }
   1839           break;
   1840         // Conditional moves.
   1841         case MOVN:
   1842           if (rt) set_register(rd_reg, rs);
   1843           break;
   1844         case MOVCI: {
   1845           uint32_t cc = instr->FCccValue();
   1846           uint32_t fcsr_cc = get_fcsr_condition_bit(cc);
   1847           if (instr->Bit(16)) {  // Read Tf bit
   1848             if (test_fcsr_bit(fcsr_cc)) set_register(rd_reg, rs);
   1849           } else {
   1850             if (!test_fcsr_bit(fcsr_cc)) set_register(rd_reg, rs);
   1851           }
   1852           break;
   1853         }
   1854         case MOVZ:
   1855           if (!rt) set_register(rd_reg, rs);
   1856           break;
   1857         default:  // For other special opcodes we do the default operation.
   1858           set_register(rd_reg, alu_out);
   1859       };
   1860       break;
   1861     case SPECIAL2:
   1862       switch (instr->FunctionFieldRaw()) {
   1863         case MUL:
   1864           set_register(rd_reg, alu_out);
   1865           // HI and LO are UNPREDICTABLE after the operation.
   1866           set_register(LO, Unpredictable);
   1867           set_register(HI, Unpredictable);
   1868           break;
   1869         default:  // For other special2 opcodes we do the default operation.
   1870           set_register(rd_reg, alu_out);
   1871       }
   1872       break;
   1873     case SPECIAL3:
   1874       switch (instr->FunctionFieldRaw()) {
   1875         case INS:
   1876           // Ins instr leaves result in Rt, rather than Rd.
   1877           set_register(rt_reg, alu_out);
   1878           break;
   1879         case EXT:
   1880           // Ext instr leaves result in Rt, rather than Rd.
   1881           set_register(rt_reg, alu_out);
   1882           break;
   1883         default:
   1884           UNREACHABLE();
   1885       };
   1886       break;
   1887     // Unimplemented opcodes raised an error in the configuration step before,
   1888     // so we can use the default here to set the destination register in common
   1889     // cases.
   1890     default:
   1891       set_register(rd_reg, alu_out);
   1892   };
   1893 }
   1894 
   1895 
   1896 // Type 2: instructions using a 16 bytes immediate. (eg: addi, beq)
   1897 void Simulator::DecodeTypeImmediate(Instruction* instr) {
   1898   // Instruction fields.
   1899   Opcode   op     = instr->OpcodeFieldRaw();
   1900   int32_t  rs     = get_register(instr->RsValue());
   1901   uint32_t rs_u   = static_cast<uint32_t>(rs);
   1902   int32_t  rt_reg = instr->RtValue();  // destination register
   1903   int32_t  rt     = get_register(rt_reg);
   1904   int16_t  imm16  = instr->Imm16Value();
   1905 
   1906   int32_t  ft_reg = instr->FtValue();  // destination register
   1907 
   1908   // Zero extended immediate.
   1909   uint32_t  oe_imm16 = 0xffff & imm16;
   1910   // Sign extended immediate.
   1911   int32_t   se_imm16 = imm16;
   1912 
   1913   // Get current pc.
   1914   int32_t current_pc = get_pc();
   1915   // Next pc.
   1916   int32_t next_pc = bad_ra;
   1917 
   1918   // Used for conditional branch instructions.
   1919   bool do_branch = false;
   1920   bool execute_branch_delay_instruction = false;
   1921 
   1922   // Used for arithmetic instructions.
   1923   int32_t alu_out = 0;
   1924   // Floating point.
   1925   double fp_out = 0.0;
   1926   uint32_t cc, cc_value, fcsr_cc;
   1927 
   1928   // Used for memory instructions.
   1929   int32_t addr = 0x0;
   1930   // Value to be written in memory
   1931   uint32_t mem_value = 0x0;
   1932 
   1933   // ---------- Configuration (and execution for REGIMM)
   1934   switch (op) {
   1935     // ------------- COP1. Coprocessor instructions.
   1936     case COP1:
   1937       switch (instr->RsFieldRaw()) {
   1938         case BC1:   // Branch on coprocessor condition.
   1939           cc = instr->FBccValue();
   1940           fcsr_cc = get_fcsr_condition_bit(cc);
   1941           cc_value = test_fcsr_bit(fcsr_cc);
   1942           do_branch = (instr->FBtrueValue()) ? cc_value : !cc_value;
   1943           execute_branch_delay_instruction = true;
   1944           // Set next_pc
   1945           if (do_branch) {
   1946             next_pc = current_pc + (imm16 << 2) + Instruction::kInstrSize;
   1947           } else {
   1948             next_pc = current_pc + kBranchReturnOffset;
   1949           }
   1950           break;
   1951         default:
   1952           UNREACHABLE();
   1953       };
   1954       break;
   1955     // ------------- REGIMM class
   1956     case REGIMM:
   1957       switch (instr->RtFieldRaw()) {
   1958         case BLTZ:
   1959           do_branch = (rs  < 0);
   1960           break;
   1961         case BLTZAL:
   1962           do_branch = rs  < 0;
   1963           break;
   1964         case BGEZ:
   1965           do_branch = rs >= 0;
   1966           break;
   1967         case BGEZAL:
   1968           do_branch = rs >= 0;
   1969           break;
   1970         default:
   1971           UNREACHABLE();
   1972       };
   1973       switch (instr->RtFieldRaw()) {
   1974         case BLTZ:
   1975         case BLTZAL:
   1976         case BGEZ:
   1977         case BGEZAL:
   1978           // Branch instructions common part.
   1979           execute_branch_delay_instruction = true;
   1980           // Set next_pc
   1981           if (do_branch) {
   1982             next_pc = current_pc + (imm16 << 2) + Instruction::kInstrSize;
   1983             if (instr->IsLinkingInstruction()) {
   1984               set_register(31, current_pc + kBranchReturnOffset);
   1985             }
   1986           } else {
   1987             next_pc = current_pc + kBranchReturnOffset;
   1988           }
   1989         default:
   1990           break;
   1991         };
   1992     break;  // case REGIMM
   1993     // ------------- Branch instructions
   1994     // When comparing to zero, the encoding of rt field is always 0, so we don't
   1995     // need to replace rt with zero.
   1996     case BEQ:
   1997       do_branch = (rs == rt);
   1998       break;
   1999     case BNE:
   2000       do_branch = rs != rt;
   2001       break;
   2002     case BLEZ:
   2003       do_branch = rs <= 0;
   2004       break;
   2005     case BGTZ:
   2006       do_branch = rs  > 0;
   2007       break;
   2008     // ------------- Arithmetic instructions
   2009     case ADDI:
   2010       if (HaveSameSign(rs, se_imm16)) {
   2011         if (rs > 0) {
   2012           exceptions[kIntegerOverflow] = rs > (Registers::kMaxValue - se_imm16);
   2013         } else if (rs < 0) {
   2014           exceptions[kIntegerUnderflow] =
   2015               rs < (Registers::kMinValue - se_imm16);
   2016         }
   2017       }
   2018       alu_out = rs + se_imm16;
   2019       break;
   2020     case ADDIU:
   2021       alu_out = rs + se_imm16;
   2022       break;
   2023     case SLTI:
   2024       alu_out = (rs < se_imm16) ? 1 : 0;
   2025       break;
   2026     case SLTIU:
   2027       alu_out = (rs_u < static_cast<uint32_t>(se_imm16)) ? 1 : 0;
   2028       break;
   2029     case ANDI:
   2030         alu_out = rs & oe_imm16;
   2031       break;
   2032     case ORI:
   2033         alu_out = rs | oe_imm16;
   2034       break;
   2035     case XORI:
   2036         alu_out = rs ^ oe_imm16;
   2037       break;
   2038     case LUI:
   2039         alu_out = (oe_imm16 << 16);
   2040       break;
   2041     // ------------- Memory instructions
   2042     case LB:
   2043       addr = rs + se_imm16;
   2044       alu_out = ReadB(addr);
   2045       break;
   2046     case LH:
   2047       addr = rs + se_imm16;
   2048       alu_out = ReadH(addr, instr);
   2049       break;
   2050     case LWL: {
   2051       // al_offset is an offset of the effective address within an aligned word
   2052       uint8_t al_offset = (rs + se_imm16) & kPointerAlignmentMask;
   2053       uint8_t byte_shift = kPointerAlignmentMask - al_offset;
   2054       uint32_t mask = (1 << byte_shift * 8) - 1;
   2055       addr = rs + se_imm16 - al_offset;
   2056       alu_out = ReadW(addr, instr);
   2057       alu_out <<= byte_shift * 8;
   2058       alu_out |= rt & mask;
   2059       break;
   2060     }
   2061     case LW:
   2062       addr = rs + se_imm16;
   2063       alu_out = ReadW(addr, instr);
   2064       break;
   2065     case LBU:
   2066       addr = rs + se_imm16;
   2067       alu_out = ReadBU(addr);
   2068       break;
   2069     case LHU:
   2070       addr = rs + se_imm16;
   2071       alu_out = ReadHU(addr, instr);
   2072       break;
   2073     case LWR: {
   2074       // al_offset is an offset of the effective address within an aligned word
   2075       uint8_t al_offset = (rs + se_imm16) & kPointerAlignmentMask;
   2076       uint8_t byte_shift = kPointerAlignmentMask - al_offset;
   2077       uint32_t mask = al_offset ? (~0 << (byte_shift + 1) * 8) : 0;
   2078       addr = rs + se_imm16 - al_offset;
   2079       alu_out = ReadW(addr, instr);
   2080       alu_out = static_cast<uint32_t> (alu_out) >> al_offset * 8;
   2081       alu_out |= rt & mask;
   2082       break;
   2083     }
   2084     case SB:
   2085       addr = rs + se_imm16;
   2086       break;
   2087     case SH:
   2088       addr = rs + se_imm16;
   2089       break;
   2090     case SWL: {
   2091       uint8_t al_offset = (rs + se_imm16) & kPointerAlignmentMask;
   2092       uint8_t byte_shift = kPointerAlignmentMask - al_offset;
   2093       uint32_t mask = byte_shift ? (~0 << (al_offset + 1) * 8) : 0;
   2094       addr = rs + se_imm16 - al_offset;
   2095       mem_value = ReadW(addr, instr) & mask;
   2096       mem_value |= static_cast<uint32_t>(rt) >> byte_shift * 8;
   2097       break;
   2098     }
   2099     case SW:
   2100       addr = rs + se_imm16;
   2101       break;
   2102     case SWR: {
   2103       uint8_t al_offset = (rs + se_imm16) & kPointerAlignmentMask;
   2104       uint32_t mask = (1 << al_offset * 8) - 1;
   2105       addr = rs + se_imm16 - al_offset;
   2106       mem_value = ReadW(addr, instr);
   2107       mem_value = (rt << al_offset * 8) | (mem_value & mask);
   2108       break;
   2109     }
   2110     case LWC1:
   2111       addr = rs + se_imm16;
   2112       alu_out = ReadW(addr, instr);
   2113       break;
   2114     case LDC1:
   2115       addr = rs + se_imm16;
   2116       fp_out = ReadD(addr, instr);
   2117       break;
   2118     case SWC1:
   2119     case SDC1:
   2120       addr = rs + se_imm16;
   2121       break;
   2122     default:
   2123       UNREACHABLE();
   2124   };
   2125 
   2126   // ---------- Raise exceptions triggered.
   2127   SignalExceptions();
   2128 
   2129   // ---------- Execution
   2130   switch (op) {
   2131     // ------------- Branch instructions
   2132     case BEQ:
   2133     case BNE:
   2134     case BLEZ:
   2135     case BGTZ:
   2136       // Branch instructions common part.
   2137       execute_branch_delay_instruction = true;
   2138       // Set next_pc
   2139       if (do_branch) {
   2140         next_pc = current_pc + (imm16 << 2) + Instruction::kInstrSize;
   2141         if (instr->IsLinkingInstruction()) {
   2142           set_register(31, current_pc + 2* Instruction::kInstrSize);
   2143         }
   2144       } else {
   2145         next_pc = current_pc + 2 * Instruction::kInstrSize;
   2146       }
   2147       break;
   2148     // ------------- Arithmetic instructions
   2149     case ADDI:
   2150     case ADDIU:
   2151     case SLTI:
   2152     case SLTIU:
   2153     case ANDI:
   2154     case ORI:
   2155     case XORI:
   2156     case LUI:
   2157       set_register(rt_reg, alu_out);
   2158       break;
   2159     // ------------- Memory instructions
   2160     case LB:
   2161     case LH:
   2162     case LWL:
   2163     case LW:
   2164     case LBU:
   2165     case LHU:
   2166     case LWR:
   2167       set_register(rt_reg, alu_out);
   2168       break;
   2169     case SB:
   2170       WriteB(addr, static_cast<int8_t>(rt));
   2171       break;
   2172     case SH:
   2173       WriteH(addr, static_cast<uint16_t>(rt), instr);
   2174       break;
   2175     case SWL:
   2176       WriteW(addr, mem_value, instr);
   2177       break;
   2178     case SW:
   2179       WriteW(addr, rt, instr);
   2180       break;
   2181     case SWR:
   2182       WriteW(addr, mem_value, instr);
   2183       break;
   2184     case LWC1:
   2185       set_fpu_register(ft_reg, alu_out);
   2186       break;
   2187     case LDC1:
   2188       set_fpu_register_double(ft_reg, fp_out);
   2189       break;
   2190     case SWC1:
   2191       addr = rs + se_imm16;
   2192       WriteW(addr, get_fpu_register(ft_reg), instr);
   2193       break;
   2194     case SDC1:
   2195       addr = rs + se_imm16;
   2196       WriteD(addr, get_fpu_register_double(ft_reg), instr);
   2197       break;
   2198     default:
   2199       break;
   2200   };
   2201 
   2202 
   2203   if (execute_branch_delay_instruction) {
   2204     // Execute branch delay slot
   2205     // We don't check for end_sim_pc. First it should not be met as the current
   2206     // pc is valid. Secondly a jump should always execute its branch delay slot.
   2207     Instruction* branch_delay_instr =
   2208       reinterpret_cast<Instruction*>(current_pc+Instruction::kInstrSize);
   2209     BranchDelayInstructionDecode(branch_delay_instr);
   2210   }
   2211 
   2212   // If needed update pc after the branch delay execution.
   2213   if (next_pc != bad_ra) {
   2214     set_pc(next_pc);
   2215   }
   2216 }
   2217 
   2218 
   2219 // Type 3: instructions using a 26 bytes immediate. (eg: j, jal)
   2220 void Simulator::DecodeTypeJump(Instruction* instr) {
   2221   // Get current pc.
   2222   int32_t current_pc = get_pc();
   2223   // Get unchanged bits of pc.
   2224   int32_t pc_high_bits = current_pc & 0xf0000000;
   2225   // Next pc
   2226   int32_t next_pc = pc_high_bits | (instr->Imm26Value() << 2);
   2227 
   2228   // Execute branch delay slot
   2229   // We don't check for end_sim_pc. First it should not be met as the current pc
   2230   // is valid. Secondly a jump should always execute its branch delay slot.
   2231   Instruction* branch_delay_instr =
   2232     reinterpret_cast<Instruction*>(current_pc+Instruction::kInstrSize);
   2233   BranchDelayInstructionDecode(branch_delay_instr);
   2234 
   2235   // Update pc and ra if necessary.
   2236   // Do this after the branch delay execution.
   2237   if (instr->IsLinkingInstruction()) {
   2238     set_register(31, current_pc + 2* Instruction::kInstrSize);
   2239   }
   2240   set_pc(next_pc);
   2241   pc_modified_ = true;
   2242 }
   2243 
   2244 
   2245 // Executes the current instruction.
   2246 void Simulator::InstructionDecode(Instruction* instr) {
   2247   if (v8::internal::FLAG_check_icache) {
   2248     CheckICache(isolate_->simulator_i_cache(), instr);
   2249   }
   2250   pc_modified_ = false;
   2251   if (::v8::internal::FLAG_trace_sim) {
   2252     disasm::NameConverter converter;
   2253     disasm::Disassembler dasm(converter);
   2254     // use a reasonably large buffer
   2255     v8::internal::EmbeddedVector<char, 256> buffer;
   2256     dasm.InstructionDecode(buffer, reinterpret_cast<byte_*>(instr));
   2257     PrintF("  0x%08x  %s\n", reinterpret_cast<intptr_t>(instr),
   2258            buffer.start());
   2259   }
   2260 
   2261   switch (instr->InstructionType()) {
   2262     case Instruction::kRegisterType:
   2263       DecodeTypeRegister(instr);
   2264       break;
   2265     case Instruction::kImmediateType:
   2266       DecodeTypeImmediate(instr);
   2267       break;
   2268     case Instruction::kJumpType:
   2269       DecodeTypeJump(instr);
   2270       break;
   2271     default:
   2272       UNSUPPORTED();
   2273   }
   2274   if (!pc_modified_) {
   2275     set_register(pc, reinterpret_cast<int32_t>(instr) +
   2276                  Instruction::kInstrSize);
   2277   }
   2278 }
   2279 
   2280 
   2281 
   2282 void Simulator::Execute() {
   2283   // Get the PC to simulate. Cannot use the accessor here as we need the
   2284   // raw PC value and not the one used as input to arithmetic instructions.
   2285   int program_counter = get_pc();
   2286   if (::v8::internal::FLAG_stop_sim_at == 0) {
   2287     // Fast version of the dispatch loop without checking whether the simulator
   2288     // should be stopping at a particular executed instruction.
   2289     while (program_counter != end_sim_pc) {
   2290       Instruction* instr = reinterpret_cast<Instruction*>(program_counter);
   2291       icount_++;
   2292       InstructionDecode(instr);
   2293       program_counter = get_pc();
   2294     }
   2295   } else {
   2296     // FLAG_stop_sim_at is at the non-default value. Stop in the debugger when
   2297     // we reach the particular instuction count.
   2298     while (program_counter != end_sim_pc) {
   2299       Instruction* instr = reinterpret_cast<Instruction*>(program_counter);
   2300       icount_++;
   2301       if (icount_ == ::v8::internal::FLAG_stop_sim_at) {
   2302         MipsDebugger dbg(this);
   2303         dbg.Debug();
   2304       } else {
   2305         InstructionDecode(instr);
   2306       }
   2307       program_counter = get_pc();
   2308     }
   2309   }
   2310 }
   2311 
   2312 
   2313 int32_t Simulator::Call(byte_* entry, int argument_count, ...) {
   2314   va_list parameters;
   2315   va_start(parameters, argument_count);
   2316   // Setup arguments
   2317 
   2318   // First four arguments passed in registers.
   2319   ASSERT(argument_count >= 4);
   2320   set_register(a0, va_arg(parameters, int32_t));
   2321   set_register(a1, va_arg(parameters, int32_t));
   2322   set_register(a2, va_arg(parameters, int32_t));
   2323   set_register(a3, va_arg(parameters, int32_t));
   2324 
   2325   // Remaining arguments passed on stack.
   2326   int original_stack = get_register(sp);
   2327   // Compute position of stack on entry to generated code.
   2328   int entry_stack = (original_stack - (argument_count - 4) * sizeof(int32_t)
   2329                                     - kCArgsSlotsSize);
   2330   if (OS::ActivationFrameAlignment() != 0) {
   2331     entry_stack &= -OS::ActivationFrameAlignment();
   2332   }
   2333   // Store remaining arguments on stack, from low to high memory.
   2334   intptr_t* stack_argument = reinterpret_cast<intptr_t*>(entry_stack);
   2335   for (int i = 4; i < argument_count; i++) {
   2336     stack_argument[i - 4 + kArgsSlotsNum] = va_arg(parameters, int32_t);
   2337   }
   2338   va_end(parameters);
   2339   set_register(sp, entry_stack);
   2340 
   2341   // Prepare to execute the code at entry
   2342   set_register(pc, reinterpret_cast<int32_t>(entry));
   2343   // Put down marker for end of simulation. The simulator will stop simulation
   2344   // when the PC reaches this value. By saving the "end simulation" value into
   2345   // the LR the simulation stops when returning to this call point.
   2346   set_register(ra, end_sim_pc);
   2347 
   2348   // Remember the values of callee-saved registers.
   2349   // The code below assumes that r9 is not used as sb (static base) in
   2350   // simulator code and therefore is regarded as a callee-saved register.
   2351   int32_t s0_val = get_register(s0);
   2352   int32_t s1_val = get_register(s1);
   2353   int32_t s2_val = get_register(s2);
   2354   int32_t s3_val = get_register(s3);
   2355   int32_t s4_val = get_register(s4);
   2356   int32_t s5_val = get_register(s5);
   2357   int32_t s6_val = get_register(s6);
   2358   int32_t s7_val = get_register(s7);
   2359   int32_t gp_val = get_register(gp);
   2360   int32_t sp_val = get_register(sp);
   2361   int32_t fp_val = get_register(fp);
   2362 
   2363   // Setup the callee-saved registers with a known value. To be able to check
   2364   // that they are preserved properly across JS execution.
   2365   int32_t callee_saved_value = icount_;
   2366   set_register(s0, callee_saved_value);
   2367   set_register(s1, callee_saved_value);
   2368   set_register(s2, callee_saved_value);
   2369   set_register(s3, callee_saved_value);
   2370   set_register(s4, callee_saved_value);
   2371   set_register(s5, callee_saved_value);
   2372   set_register(s6, callee_saved_value);
   2373   set_register(s7, callee_saved_value);
   2374   set_register(gp, callee_saved_value);
   2375   set_register(fp, callee_saved_value);
   2376 
   2377   // Start the simulation
   2378   Execute();
   2379 
   2380   // Check that the callee-saved registers have been preserved.
   2381   CHECK_EQ(callee_saved_value, get_register(s0));
   2382   CHECK_EQ(callee_saved_value, get_register(s1));
   2383   CHECK_EQ(callee_saved_value, get_register(s2));
   2384   CHECK_EQ(callee_saved_value, get_register(s3));
   2385   CHECK_EQ(callee_saved_value, get_register(s4));
   2386   CHECK_EQ(callee_saved_value, get_register(s5));
   2387   CHECK_EQ(callee_saved_value, get_register(s6));
   2388   CHECK_EQ(callee_saved_value, get_register(s7));
   2389   CHECK_EQ(callee_saved_value, get_register(gp));
   2390   CHECK_EQ(callee_saved_value, get_register(fp));
   2391 
   2392   // Restore callee-saved registers with the original value.
   2393   set_register(s0, s0_val);
   2394   set_register(s1, s1_val);
   2395   set_register(s2, s2_val);
   2396   set_register(s3, s3_val);
   2397   set_register(s4, s4_val);
   2398   set_register(s5, s5_val);
   2399   set_register(s6, s6_val);
   2400   set_register(s7, s7_val);
   2401   set_register(gp, gp_val);
   2402   set_register(sp, sp_val);
   2403   set_register(fp, fp_val);
   2404 
   2405   // Pop stack passed arguments.
   2406   CHECK_EQ(entry_stack, get_register(sp));
   2407   set_register(sp, original_stack);
   2408 
   2409   int32_t result = get_register(v0);
   2410   return result;
   2411 }
   2412 
   2413 
   2414 uintptr_t Simulator::PushAddress(uintptr_t address) {
   2415   int new_sp = get_register(sp) - sizeof(uintptr_t);
   2416   uintptr_t* stack_slot = reinterpret_cast<uintptr_t*>(new_sp);
   2417   *stack_slot = address;
   2418   set_register(sp, new_sp);
   2419   return new_sp;
   2420 }
   2421 
   2422 
   2423 uintptr_t Simulator::PopAddress() {
   2424   int current_sp = get_register(sp);
   2425   uintptr_t* stack_slot = reinterpret_cast<uintptr_t*>(current_sp);
   2426   uintptr_t address = *stack_slot;
   2427   set_register(sp, current_sp + sizeof(uintptr_t));
   2428   return address;
   2429 }
   2430 
   2431 
   2432 #undef UNSUPPORTED
   2433 
   2434 } }  // namespace v8::internal
   2435 
   2436 #endif  // USE_SIMULATOR
   2437 
   2438 #endif  // V8_TARGET_ARCH_MIPS
   2439