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