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