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