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-inl.h"
     13 #include "src/base/bits.h"
     14 #include "src/codegen.h"
     15 #include "src/disasm.h"
     16 #include "src/macro-assembler.h"
     17 #include "src/mips/constants-mips.h"
     18 #include "src/mips/simulator-mips.h"
     19 #include "src/ostreams.h"
     20 #include "src/runtime/runtime-utils.h"
     21 
     22 
     23 // Only build the simulator if not compiling for real MIPS hardware.
     24 #if defined(USE_SIMULATOR)
     25 
     26 namespace v8 {
     27 namespace internal {
     28 
     29 // Utils functions.
     30 bool HaveSameSign(int32_t a, int32_t b) {
     31   return ((a ^ b) >= 0);
     32 }
     33 
     34 
     35 uint32_t get_fcsr_condition_bit(uint32_t cc) {
     36   if (cc == 0) {
     37     return 23;
     38   } else {
     39     return 24 + cc;
     40   }
     41 }
     42 
     43 
     44 // This macro provides a platform independent use of sscanf. The reason for
     45 // SScanF not being implemented in a platform independent was through
     46 // ::v8::internal::OS in the same way as SNPrintF is that the Windows C Run-Time
     47 // Library does not provide vsscanf.
     48 #define SScanF sscanf  // NOLINT
     49 
     50 // The MipsDebugger class is used by the simulator while debugging simulated
     51 // code.
     52 class MipsDebugger {
     53  public:
     54   explicit MipsDebugger(Simulator* sim) : sim_(sim) { }
     55 
     56   void Stop(Instruction* instr);
     57   void Debug();
     58   // Print all registers with a nice formatting.
     59   void PrintAllRegs();
     60   void PrintAllRegsIncludingFPU();
     61 
     62  private:
     63   // We set the breakpoint code to 0xFFFFF to easily recognize it.
     64   static const Instr kBreakpointInstr = SPECIAL | BREAK | 0xFFFFF << 6;
     65   static const Instr kNopInstr =  0x0;
     66 
     67   Simulator* sim_;
     68 
     69   int32_t GetRegisterValue(int regnum);
     70   int32_t GetFPURegisterValue32(int regnum);
     71   int64_t GetFPURegisterValue64(int regnum);
     72   float GetFPURegisterValueFloat(int regnum);
     73   double GetFPURegisterValueDouble(int regnum);
     74   bool GetValue(const char* desc, int32_t* value);
     75   bool GetValue(const char* desc, int64_t* value);
     76 
     77   // Set or delete a breakpoint. Returns true if successful.
     78   bool SetBreakpoint(Instruction* breakpc);
     79   bool DeleteBreakpoint(Instruction* breakpc);
     80 
     81   // Undo and redo all breakpoints. This is needed to bracket disassembly and
     82   // execution to skip past breakpoints when run from the debugger.
     83   void UndoBreakpoints();
     84   void RedoBreakpoints();
     85 };
     86 
     87 
     88 #define UNSUPPORTED() printf("Sim: Unsupported instruction.\n");
     89 
     90 
     91 void MipsDebugger::Stop(Instruction* instr) {
     92   // Get the stop code.
     93   uint32_t code = instr->Bits(25, 6);
     94   PrintF("Simulator hit (%u)\n", code);
     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_ != nullptr) {
    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_ != nullptr) {
    200     sim_->break_pc_->SetInstructionBits(sim_->break_instr_);
    201   }
    202 
    203   sim_->break_pc_ = nullptr;
    204   sim_->break_instr_ = 0;
    205   return true;
    206 }
    207 
    208 
    209 void MipsDebugger::UndoBreakpoints() {
    210   if (sim_->break_pc_ != nullptr) {
    211     sim_->break_pc_->SetInstructionBits(sim_->break_instr_);
    212   }
    213 }
    214 
    215 
    216 void MipsDebugger::RedoBreakpoints() {
    217   if (sim_->break_pc_ != nullptr) {
    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 == nullptr) {
    373       break;
    374     } else {
    375       char* last_input = sim_->last_debugger_input();
    376       if (strcmp(line, "\n") == 0 && last_input != nullptr) {
    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() + 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           StdoutStream os;
    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 = nullptr;
    494         int32_t* end = nullptr;
    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 = nullptr;
    561         byte* end = nullptr;
    562 
    563         if (argc == 1) {
    564           cur = reinterpret_cast<byte*>(sim_->get_pc());
    565           end = cur + (10 * 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 * 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 * 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 * 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 += 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(nullptr)) {
    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() - 2 * kInstrSize;
    626         Instruction* stop_instr = reinterpret_cast<Instruction*>(stop_pc);
    627         Instruction* msg_address =
    628             reinterpret_cast<Instruction*>(stop_pc + kInstrSize);
    629         if ((argc == 2) && (strcmp(arg1, "unstop") == 0)) {
    630           // Remove the current stop.
    631           if (sim_->IsStopInstruction(stop_instr)) {
    632             stop_instr->SetInstructionBits(kNopInstr);
    633             msg_address->SetInstructionBits(kNopInstr);
    634           } else {
    635             PrintF("Not at debugger stop.\n");
    636           }
    637         } else if (argc == 3) {
    638           // Print information about all/the specified breakpoint(s).
    639           if (strcmp(arg1, "info") == 0) {
    640             if (strcmp(arg2, "all") == 0) {
    641               PrintF("Stop information:\n");
    642               for (uint32_t i = kMaxWatchpointCode + 1;
    643                    i <= kMaxStopCode;
    644                    i++) {
    645                 sim_->PrintStopInfo(i);
    646               }
    647             } else if (GetValue(arg2, &value)) {
    648               sim_->PrintStopInfo(value);
    649             } else {
    650               PrintF("Unrecognized argument.\n");
    651             }
    652           } else if (strcmp(arg1, "enable") == 0) {
    653             // Enable all/the specified breakpoint(s).
    654             if (strcmp(arg2, "all") == 0) {
    655               for (uint32_t i = kMaxWatchpointCode + 1;
    656                    i <= kMaxStopCode;
    657                    i++) {
    658                 sim_->EnableStop(i);
    659               }
    660             } else if (GetValue(arg2, &value)) {
    661               sim_->EnableStop(value);
    662             } else {
    663               PrintF("Unrecognized argument.\n");
    664             }
    665           } else if (strcmp(arg1, "disable") == 0) {
    666             // Disable all/the specified breakpoint(s).
    667             if (strcmp(arg2, "all") == 0) {
    668               for (uint32_t i = kMaxWatchpointCode + 1;
    669                    i <= kMaxStopCode;
    670                    i++) {
    671                 sim_->DisableStop(i);
    672               }
    673             } else if (GetValue(arg2, &value)) {
    674               sim_->DisableStop(value);
    675             } else {
    676               PrintF("Unrecognized argument.\n");
    677             }
    678           }
    679         } else {
    680           PrintF("Wrong usage. Use help command for more information.\n");
    681         }
    682       } else if ((strcmp(cmd, "stat") == 0) || (strcmp(cmd, "st") == 0)) {
    683         // Print registers and disassemble.
    684         PrintAllRegs();
    685         PrintF("\n");
    686 
    687         disasm::NameConverter converter;
    688         disasm::Disassembler dasm(converter);
    689         // Use a reasonably large buffer.
    690         v8::internal::EmbeddedVector<char, 256> buffer;
    691 
    692         byte* cur = nullptr;
    693         byte* end = nullptr;
    694 
    695         if (argc == 1) {
    696           cur = reinterpret_cast<byte*>(sim_->get_pc());
    697           end = cur + (10 * kInstrSize);
    698         } else if (argc == 2) {
    699           int32_t value;
    700           if (GetValue(arg1, &value)) {
    701             cur = reinterpret_cast<byte*>(value);
    702             // no length parameter passed, assume 10 instructions
    703             end = cur + (10 * kInstrSize);
    704           }
    705         } else {
    706           int32_t value1;
    707           int32_t value2;
    708           if (GetValue(arg1, &value1) && GetValue(arg2, &value2)) {
    709             cur = reinterpret_cast<byte*>(value1);
    710             end = cur + (value2 * kInstrSize);
    711           }
    712         }
    713 
    714         while (cur < end) {
    715           dasm.InstructionDecode(buffer, cur);
    716           PrintF("  0x%08" PRIxPTR "  %s\n", reinterpret_cast<intptr_t>(cur),
    717                  buffer.start());
    718           cur += kInstrSize;
    719         }
    720       } else if ((strcmp(cmd, "h") == 0) || (strcmp(cmd, "help") == 0)) {
    721         PrintF("cont\n");
    722         PrintF("  continue execution (alias 'c')\n");
    723         PrintF("stepi\n");
    724         PrintF("  step one instruction (alias 'si')\n");
    725         PrintF("print <register>\n");
    726         PrintF("  print register content (alias 'p')\n");
    727         PrintF("  use register name 'all' to print all registers\n");
    728         PrintF("printobject <register>\n");
    729         PrintF("  print an object from a register (alias 'po')\n");
    730         PrintF("stack [<words>]\n");
    731         PrintF("  dump stack content, default dump 10 words)\n");
    732         PrintF("mem <address> [<words>]\n");
    733         PrintF("  dump memory content, default dump 10 words)\n");
    734         PrintF("flags\n");
    735         PrintF("  print flags\n");
    736         PrintF("disasm [<instructions>]\n");
    737         PrintF("disasm [<address/register>]\n");
    738         PrintF("disasm [[<address/register>] <instructions>]\n");
    739         PrintF("  disassemble code, default is 10 instructions\n");
    740         PrintF("  from pc (alias 'di')\n");
    741         PrintF("gdb\n");
    742         PrintF("  enter gdb\n");
    743         PrintF("break <address>\n");
    744         PrintF("  set a break point on the address\n");
    745         PrintF("del\n");
    746         PrintF("  delete the breakpoint\n");
    747         PrintF("stop feature:\n");
    748         PrintF("  Description:\n");
    749         PrintF("    Stops are debug instructions inserted by\n");
    750         PrintF("    the Assembler::stop() function.\n");
    751         PrintF("    When hitting a stop, the Simulator will\n");
    752         PrintF("    stop and give control to the Debugger.\n");
    753         PrintF("    All stop codes are watched:\n");
    754         PrintF("    - They can be enabled / disabled: the Simulator\n");
    755         PrintF("       will / won't stop when hitting them.\n");
    756         PrintF("    - The Simulator keeps track of how many times they \n");
    757         PrintF("      are met. (See the info command.) Going over a\n");
    758         PrintF("      disabled stop still increases its counter. \n");
    759         PrintF("  Commands:\n");
    760         PrintF("    stop info all/<code> : print infos about number <code>\n");
    761         PrintF("      or all stop(s).\n");
    762         PrintF("    stop enable/disable all/<code> : enables / disables\n");
    763         PrintF("      all or number <code> stop(s)\n");
    764         PrintF("    stop unstop\n");
    765         PrintF("      ignore the stop instruction at the current location\n");
    766         PrintF("      from now on\n");
    767       } else {
    768         PrintF("Unknown command: %s\n", cmd);
    769       }
    770     }
    771   }
    772 
    773   // Add all the breakpoints back to stop execution and enter the debugger
    774   // shell when hit.
    775   RedoBreakpoints();
    776 
    777 #undef COMMAND_SIZE
    778 #undef ARG_SIZE
    779 
    780 #undef STR
    781 #undef XSTR
    782 }
    783 
    784 bool Simulator::ICacheMatch(void* one, void* two) {
    785   DCHECK_EQ(reinterpret_cast<intptr_t>(one) & CachePage::kPageMask, 0);
    786   DCHECK_EQ(reinterpret_cast<intptr_t>(two) & CachePage::kPageMask, 0);
    787   return one == two;
    788 }
    789 
    790 
    791 static uint32_t ICacheHash(void* key) {
    792   return static_cast<uint32_t>(reinterpret_cast<uintptr_t>(key)) >> 2;
    793 }
    794 
    795 
    796 static bool AllOnOnePage(uintptr_t start, int size) {
    797   intptr_t start_page = (start & ~CachePage::kPageMask);
    798   intptr_t end_page = ((start + size) & ~CachePage::kPageMask);
    799   return start_page == end_page;
    800 }
    801 
    802 
    803 void Simulator::set_last_debugger_input(char* input) {
    804   DeleteArray(last_debugger_input_);
    805   last_debugger_input_ = input;
    806 }
    807 
    808 void Simulator::SetRedirectInstruction(Instruction* instruction) {
    809   instruction->SetInstructionBits(rtCallRedirInstr);
    810 }
    811 
    812 void Simulator::FlushICache(base::CustomMatcherHashMap* i_cache,
    813                             void* start_addr, size_t size) {
    814   intptr_t start = reinterpret_cast<intptr_t>(start_addr);
    815   int intra_line = (start & CachePage::kLineMask);
    816   start -= intra_line;
    817   size += intra_line;
    818   size = ((size - 1) | CachePage::kLineMask) + 1;
    819   int offset = (start & CachePage::kPageMask);
    820   while (!AllOnOnePage(start, size - 1)) {
    821     int bytes_to_flush = CachePage::kPageSize - offset;
    822     FlushOnePage(i_cache, start, bytes_to_flush);
    823     start += bytes_to_flush;
    824     size -= bytes_to_flush;
    825     DCHECK_EQ(0, start & CachePage::kPageMask);
    826     offset = 0;
    827   }
    828   if (size != 0) {
    829     FlushOnePage(i_cache, start, size);
    830   }
    831 }
    832 
    833 CachePage* Simulator::GetCachePage(base::CustomMatcherHashMap* i_cache,
    834                                    void* page) {
    835   base::CustomMatcherHashMap::Entry* entry =
    836       i_cache->LookupOrInsert(page, ICacheHash(page));
    837   if (entry->value == nullptr) {
    838     CachePage* new_page = new CachePage();
    839     entry->value = new_page;
    840   }
    841   return reinterpret_cast<CachePage*>(entry->value);
    842 }
    843 
    844 
    845 // Flush from start up to and not including start + size.
    846 void Simulator::FlushOnePage(base::CustomMatcherHashMap* i_cache,
    847                              intptr_t start, int size) {
    848   DCHECK_LE(size, CachePage::kPageSize);
    849   DCHECK(AllOnOnePage(start, size - 1));
    850   DCHECK_EQ(start & CachePage::kLineMask, 0);
    851   DCHECK_EQ(size & CachePage::kLineMask, 0);
    852   void* page = reinterpret_cast<void*>(start & (~CachePage::kPageMask));
    853   int offset = (start & CachePage::kPageMask);
    854   CachePage* cache_page = GetCachePage(i_cache, page);
    855   char* valid_bytemap = cache_page->ValidityByte(offset);
    856   memset(valid_bytemap, CachePage::LINE_INVALID, size >> CachePage::kLineShift);
    857 }
    858 
    859 void Simulator::CheckICache(base::CustomMatcherHashMap* i_cache,
    860                             Instruction* instr) {
    861   intptr_t address = reinterpret_cast<intptr_t>(instr);
    862   void* page = reinterpret_cast<void*>(address & (~CachePage::kPageMask));
    863   void* line = reinterpret_cast<void*>(address & (~CachePage::kLineMask));
    864   int offset = (address & CachePage::kPageMask);
    865   CachePage* cache_page = GetCachePage(i_cache, page);
    866   char* cache_valid_byte = cache_page->ValidityByte(offset);
    867   bool cache_hit = (*cache_valid_byte == CachePage::LINE_VALID);
    868   char* cached_line = cache_page->CachedData(offset & ~CachePage::kLineMask);
    869   if (cache_hit) {
    870     // Check that the data in memory matches the contents of the I-cache.
    871     CHECK_EQ(0, memcmp(reinterpret_cast<void*>(instr),
    872                        cache_page->CachedData(offset), 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 Simulator::Simulator(Isolate* isolate) : isolate_(isolate) {
    882   // Set up simulator support first. Some of this information is needed to
    883   // setup the architecture state.
    884   stack_ = reinterpret_cast<char*>(malloc(stack_size_));
    885   pc_modified_ = false;
    886   icount_ = 0;
    887   break_count_ = 0;
    888   break_pc_ = nullptr;
    889   break_instr_ = 0;
    890 
    891   // Set up architecture state.
    892   // All registers are initialized to zero to start with.
    893   for (int i = 0; i < kNumSimuRegisters; i++) {
    894     registers_[i] = 0;
    895   }
    896   for (int i = 0; i < kNumFPURegisters; i++) {
    897     FPUregisters_[2 * i] = 0;
    898     FPUregisters_[2 * i + 1] = 0;  // upper part for MSA ASE
    899   }
    900   if (IsMipsArchVariant(kMips32r6)) {
    901     FCSR_ = kFCSRNaN2008FlagMask;
    902     MSACSR_ = 0;
    903   } else {
    904     DCHECK(IsMipsArchVariant(kMips32r1) || IsMipsArchVariant(kMips32r2));
    905     FCSR_ = 0;
    906   }
    907 
    908   // The sp is initialized to point to the bottom (high address) of the
    909   // allocated stack area. To be safe in potential stack underflows we leave
    910   // some buffer below.
    911   registers_[sp] = reinterpret_cast<int32_t>(stack_) + stack_size_ - 64;
    912   // The ra and pc are initialized to a known bad value that will cause an
    913   // access violation if the simulator ever tries to execute it.
    914   registers_[pc] = bad_ra;
    915   registers_[ra] = bad_ra;
    916   last_debugger_input_ = nullptr;
    917 }
    918 
    919 
    920 Simulator::~Simulator() { free(stack_); }
    921 
    922 
    923 // Get the active Simulator for the current thread.
    924 Simulator* Simulator::current(Isolate* isolate) {
    925   v8::internal::Isolate::PerIsolateThreadData* isolate_data =
    926        isolate->FindOrAllocatePerThreadDataForThisThread();
    927   DCHECK_NOT_NULL(isolate_data);
    928 
    929   Simulator* sim = isolate_data->simulator();
    930   if (sim == nullptr) {
    931     // TODO(146): delete the simulator object when a thread/isolate goes away.
    932     sim = new Simulator(isolate);
    933     isolate_data->set_simulator(sim);
    934   }
    935   return sim;
    936 }
    937 
    938 
    939 // Sets the register in the architecture state. It will also deal with updating
    940 // Simulator internal state for special registers such as PC.
    941 void Simulator::set_register(int reg, int32_t value) {
    942   DCHECK((reg >= 0) && (reg < kNumSimuRegisters));
    943   if (reg == pc) {
    944     pc_modified_ = true;
    945   }
    946 
    947   // Zero register always holds 0.
    948   registers_[reg] = (reg == 0) ? 0 : value;
    949 }
    950 
    951 
    952 void Simulator::set_dw_register(int reg, const int* dbl) {
    953   DCHECK((reg >= 0) && (reg < kNumSimuRegisters));
    954   registers_[reg] = dbl[0];
    955   registers_[reg + 1] = dbl[1];
    956 }
    957 
    958 
    959 void Simulator::set_fpu_register(int fpureg, int64_t value) {
    960   DCHECK(IsFp64Mode());
    961   DCHECK((fpureg >= 0) && (fpureg < kNumFPURegisters));
    962   FPUregisters_[fpureg * 2] = value;
    963 }
    964 
    965 
    966 void Simulator::set_fpu_register_word(int fpureg, int32_t value) {
    967   // Set ONLY lower 32-bits, leaving upper bits untouched.
    968   // TODO(plind): big endian issue.
    969   DCHECK((fpureg >= 0) && (fpureg < kNumFPURegisters));
    970   int32_t* pword = reinterpret_cast<int32_t*>(&FPUregisters_[fpureg * 2]);
    971   *pword = value;
    972 }
    973 
    974 
    975 void Simulator::set_fpu_register_hi_word(int fpureg, int32_t value) {
    976   // Set ONLY upper 32-bits, leaving lower bits untouched.
    977   // TODO(plind): big endian issue.
    978   DCHECK((fpureg >= 0) && (fpureg < kNumFPURegisters));
    979   int32_t* phiword =
    980       (reinterpret_cast<int32_t*>(&FPUregisters_[fpureg * 2])) + 1;
    981   *phiword = value;
    982 }
    983 
    984 
    985 void Simulator::set_fpu_register_float(int fpureg, float value) {
    986   DCHECK((fpureg >= 0) && (fpureg < kNumFPURegisters));
    987   *bit_cast<float*>(&FPUregisters_[fpureg * 2]) = value;
    988 }
    989 
    990 
    991 void Simulator::set_fpu_register_double(int fpureg, double value) {
    992   if (IsFp64Mode()) {
    993     DCHECK((fpureg >= 0) && (fpureg < kNumFPURegisters));
    994     *bit_cast<double*>(&FPUregisters_[fpureg * 2]) = value;
    995   } else {
    996     DCHECK((fpureg >= 0) && (fpureg < kNumFPURegisters) && ((fpureg % 2) == 0));
    997     int64_t i64 = bit_cast<int64_t>(value);
    998     set_fpu_register_word(fpureg, i64 & 0xFFFFFFFF);
    999     set_fpu_register_word(fpureg + 1, i64 >> 32);
   1000   }
   1001 }
   1002 
   1003 
   1004 // Get the register from the architecture state. This function does handle
   1005 // the special case of accessing the PC register.
   1006 int32_t Simulator::get_register(int reg) const {
   1007   DCHECK((reg >= 0) && (reg < kNumSimuRegisters));
   1008   if (reg == 0)
   1009     return 0;
   1010   else
   1011     return registers_[reg] + ((reg == pc) ? Instruction::kPCReadOffset : 0);
   1012 }
   1013 
   1014 
   1015 double Simulator::get_double_from_register_pair(int reg) {
   1016   // TODO(plind): bad ABI stuff, refactor or remove.
   1017   DCHECK((reg >= 0) && (reg < kNumSimuRegisters) && ((reg % 2) == 0));
   1018 
   1019   double dm_val = 0.0;
   1020   // Read the bits from the unsigned integer register_[] array
   1021   // into the double precision floating point value and return it.
   1022   char buffer[2 * sizeof(registers_[0])];
   1023   memcpy(buffer, &registers_[reg], 2 * sizeof(registers_[0]));
   1024   memcpy(&dm_val, buffer, 2 * sizeof(registers_[0]));
   1025   return(dm_val);
   1026 }
   1027 
   1028 
   1029 int64_t Simulator::get_fpu_register(int fpureg) const {
   1030   if (IsFp64Mode()) {
   1031     DCHECK((fpureg >= 0) && (fpureg < kNumFPURegisters));
   1032     return FPUregisters_[fpureg * 2];
   1033   } else {
   1034     DCHECK((fpureg >= 0) && (fpureg < kNumFPURegisters) && ((fpureg % 2) == 0));
   1035     uint64_t i64;
   1036     i64 = static_cast<uint32_t>(get_fpu_register_word(fpureg));
   1037     i64 |= static_cast<uint64_t>(get_fpu_register_word(fpureg + 1)) << 32;
   1038     return static_cast<int64_t>(i64);
   1039   }
   1040 }
   1041 
   1042 
   1043 int32_t Simulator::get_fpu_register_word(int fpureg) const {
   1044   DCHECK((fpureg >= 0) && (fpureg < kNumFPURegisters));
   1045   return static_cast<int32_t>(FPUregisters_[fpureg * 2] & 0xFFFFFFFF);
   1046 }
   1047 
   1048 
   1049 int32_t Simulator::get_fpu_register_signed_word(int fpureg) const {
   1050   DCHECK((fpureg >= 0) && (fpureg < kNumFPURegisters));
   1051   return static_cast<int32_t>(FPUregisters_[fpureg * 2] & 0xFFFFFFFF);
   1052 }
   1053 
   1054 
   1055 int32_t Simulator::get_fpu_register_hi_word(int fpureg) const {
   1056   DCHECK((fpureg >= 0) && (fpureg < kNumFPURegisters));
   1057   return static_cast<int32_t>((FPUregisters_[fpureg * 2] >> 32) & 0xFFFFFFFF);
   1058 }
   1059 
   1060 
   1061 float Simulator::get_fpu_register_float(int fpureg) const {
   1062   DCHECK((fpureg >= 0) && (fpureg < kNumFPURegisters));
   1063   return *bit_cast<float*>(const_cast<int64_t*>(&FPUregisters_[fpureg * 2]));
   1064 }
   1065 
   1066 
   1067 double Simulator::get_fpu_register_double(int fpureg) const {
   1068   if (IsFp64Mode()) {
   1069     DCHECK((fpureg >= 0) && (fpureg < kNumFPURegisters));
   1070     return *bit_cast<double*>(&FPUregisters_[fpureg * 2]);
   1071   } else {
   1072     DCHECK((fpureg >= 0) && (fpureg < kNumFPURegisters) && ((fpureg % 2) == 0));
   1073     int64_t i64;
   1074     i64 = static_cast<uint32_t>(get_fpu_register_word(fpureg));
   1075     i64 |= static_cast<uint64_t>(get_fpu_register_word(fpureg + 1)) << 32;
   1076     return bit_cast<double>(i64);
   1077   }
   1078 }
   1079 
   1080 template <typename T>
   1081 void Simulator::get_msa_register(int wreg, T* value) {
   1082   DCHECK((wreg >= 0) && (wreg < kNumMSARegisters));
   1083   memcpy(value, FPUregisters_ + wreg * 2, kSimd128Size);
   1084 }
   1085 
   1086 template <typename T>
   1087 void Simulator::set_msa_register(int wreg, const T* value) {
   1088   DCHECK((wreg >= 0) && (wreg < kNumMSARegisters));
   1089   memcpy(FPUregisters_ + wreg * 2, value, kSimd128Size);
   1090 }
   1091 
   1092 // Runtime FP routines take up to two double arguments and zero
   1093 // or one integer arguments. All are constructed here,
   1094 // from a0-a3 or f12 and f14.
   1095 void Simulator::GetFpArgs(double* x, double* y, int32_t* z) {
   1096   if (!IsMipsSoftFloatABI) {
   1097     *x = get_fpu_register_double(12);
   1098     *y = get_fpu_register_double(14);
   1099     *z = get_register(a2);
   1100   } else {
   1101     // TODO(plind): bad ABI stuff, refactor or remove.
   1102     // We use a char buffer to get around the strict-aliasing rules which
   1103     // otherwise allow the compiler to optimize away the copy.
   1104     char buffer[sizeof(*x)];
   1105     int32_t* reg_buffer = reinterpret_cast<int32_t*>(buffer);
   1106 
   1107     // Registers a0 and a1 -> x.
   1108     reg_buffer[0] = get_register(a0);
   1109     reg_buffer[1] = get_register(a1);
   1110     memcpy(x, buffer, sizeof(buffer));
   1111     // Registers a2 and a3 -> y.
   1112     reg_buffer[0] = get_register(a2);
   1113     reg_buffer[1] = get_register(a3);
   1114     memcpy(y, buffer, sizeof(buffer));
   1115     // Register 2 -> z.
   1116     reg_buffer[0] = get_register(a2);
   1117     memcpy(z, buffer, sizeof(*z));
   1118   }
   1119 }
   1120 
   1121 
   1122 // The return value is either in v0/v1 or f0.
   1123 void Simulator::SetFpResult(const double& result) {
   1124   if (!IsMipsSoftFloatABI) {
   1125     set_fpu_register_double(0, result);
   1126   } else {
   1127     char buffer[2 * sizeof(registers_[0])];
   1128     int32_t* reg_buffer = reinterpret_cast<int32_t*>(buffer);
   1129     memcpy(buffer, &result, sizeof(buffer));
   1130     // Copy result to v0 and v1.
   1131     set_register(v0, reg_buffer[0]);
   1132     set_register(v1, reg_buffer[1]);
   1133   }
   1134 }
   1135 
   1136 
   1137 // Helper functions for setting and testing the FCSR register's bits.
   1138 void Simulator::set_fcsr_bit(uint32_t cc, bool value) {
   1139   if (value) {
   1140     FCSR_ |= (1 << cc);
   1141   } else {
   1142     FCSR_ &= ~(1 << cc);
   1143   }
   1144 }
   1145 
   1146 
   1147 bool Simulator::test_fcsr_bit(uint32_t cc) {
   1148   return FCSR_ & (1 << cc);
   1149 }
   1150 
   1151 
   1152 void Simulator::set_fcsr_rounding_mode(FPURoundingMode mode) {
   1153   FCSR_ |= mode & kFPURoundingModeMask;
   1154 }
   1155 
   1156 void Simulator::set_msacsr_rounding_mode(FPURoundingMode mode) {
   1157   MSACSR_ |= mode & kFPURoundingModeMask;
   1158 }
   1159 
   1160 unsigned int Simulator::get_fcsr_rounding_mode() {
   1161   return FCSR_ & kFPURoundingModeMask;
   1162 }
   1163 
   1164 unsigned int Simulator::get_msacsr_rounding_mode() {
   1165   return MSACSR_ & kFPURoundingModeMask;
   1166 }
   1167 
   1168 void Simulator::set_fpu_register_word_invalid_result(float original,
   1169                                                      float rounded) {
   1170   if (FCSR_ & kFCSRNaN2008FlagMask) {
   1171     double max_int32 = std::numeric_limits<int32_t>::max();
   1172     double min_int32 = std::numeric_limits<int32_t>::min();
   1173     if (std::isnan(original)) {
   1174       set_fpu_register_word(fd_reg(), 0);
   1175     } else if (rounded > max_int32) {
   1176       set_fpu_register_word(fd_reg(), kFPUInvalidResult);
   1177     } else if (rounded < min_int32) {
   1178       set_fpu_register_word(fd_reg(), kFPUInvalidResultNegative);
   1179     } else {
   1180       UNREACHABLE();
   1181     }
   1182   } else {
   1183     set_fpu_register_word(fd_reg(), kFPUInvalidResult);
   1184   }
   1185 }
   1186 
   1187 
   1188 void Simulator::set_fpu_register_invalid_result(float original, float rounded) {
   1189   if (FCSR_ & kFCSRNaN2008FlagMask) {
   1190     double max_int32 = std::numeric_limits<int32_t>::max();
   1191     double min_int32 = std::numeric_limits<int32_t>::min();
   1192     if (std::isnan(original)) {
   1193       set_fpu_register(fd_reg(), 0);
   1194     } else if (rounded > max_int32) {
   1195       set_fpu_register(fd_reg(), kFPUInvalidResult);
   1196     } else if (rounded < min_int32) {
   1197       set_fpu_register(fd_reg(), kFPUInvalidResultNegative);
   1198     } else {
   1199       UNREACHABLE();
   1200     }
   1201   } else {
   1202     set_fpu_register(fd_reg(), kFPUInvalidResult);
   1203   }
   1204 }
   1205 
   1206 
   1207 void Simulator::set_fpu_register_invalid_result64(float original,
   1208                                                   float rounded) {
   1209   if (FCSR_ & kFCSRNaN2008FlagMask) {
   1210     // The value of INT64_MAX (2^63-1) can't be represented as double exactly,
   1211     // loading the most accurate representation into max_int64, which is 2^63.
   1212     double max_int64 = std::numeric_limits<int64_t>::max();
   1213     double min_int64 = std::numeric_limits<int64_t>::min();
   1214     if (std::isnan(original)) {
   1215       set_fpu_register(fd_reg(), 0);
   1216     } else if (rounded >= max_int64) {
   1217       set_fpu_register(fd_reg(), kFPU64InvalidResult);
   1218     } else if (rounded < min_int64) {
   1219       set_fpu_register(fd_reg(), kFPU64InvalidResultNegative);
   1220     } else {
   1221       UNREACHABLE();
   1222     }
   1223   } else {
   1224     set_fpu_register(fd_reg(), kFPU64InvalidResult);
   1225   }
   1226 }
   1227 
   1228 
   1229 void Simulator::set_fpu_register_word_invalid_result(double original,
   1230                                                      double rounded) {
   1231   if (FCSR_ & kFCSRNaN2008FlagMask) {
   1232     double max_int32 = std::numeric_limits<int32_t>::max();
   1233     double min_int32 = std::numeric_limits<int32_t>::min();
   1234     if (std::isnan(original)) {
   1235       set_fpu_register_word(fd_reg(), 0);
   1236     } else if (rounded > max_int32) {
   1237       set_fpu_register_word(fd_reg(), kFPUInvalidResult);
   1238     } else if (rounded < min_int32) {
   1239       set_fpu_register_word(fd_reg(), kFPUInvalidResultNegative);
   1240     } else {
   1241       UNREACHABLE();
   1242     }
   1243   } else {
   1244     set_fpu_register_word(fd_reg(), kFPUInvalidResult);
   1245   }
   1246 }
   1247 
   1248 
   1249 void Simulator::set_fpu_register_invalid_result(double original,
   1250                                                 double rounded) {
   1251   if (FCSR_ & kFCSRNaN2008FlagMask) {
   1252     double max_int32 = std::numeric_limits<int32_t>::max();
   1253     double min_int32 = std::numeric_limits<int32_t>::min();
   1254     if (std::isnan(original)) {
   1255       set_fpu_register(fd_reg(), 0);
   1256     } else if (rounded > max_int32) {
   1257       set_fpu_register(fd_reg(), kFPUInvalidResult);
   1258     } else if (rounded < min_int32) {
   1259       set_fpu_register(fd_reg(), kFPUInvalidResultNegative);
   1260     } else {
   1261       UNREACHABLE();
   1262     }
   1263   } else {
   1264     set_fpu_register(fd_reg(), kFPUInvalidResult);
   1265   }
   1266 }
   1267 
   1268 
   1269 void Simulator::set_fpu_register_invalid_result64(double original,
   1270                                                   double rounded) {
   1271   if (FCSR_ & kFCSRNaN2008FlagMask) {
   1272     // The value of INT64_MAX (2^63-1) can't be represented as double exactly,
   1273     // loading the most accurate representation into max_int64, which is 2^63.
   1274     double max_int64 = std::numeric_limits<int64_t>::max();
   1275     double min_int64 = std::numeric_limits<int64_t>::min();
   1276     if (std::isnan(original)) {
   1277       set_fpu_register(fd_reg(), 0);
   1278     } else if (rounded >= max_int64) {
   1279       set_fpu_register(fd_reg(), kFPU64InvalidResult);
   1280     } else if (rounded < min_int64) {
   1281       set_fpu_register(fd_reg(), kFPU64InvalidResultNegative);
   1282     } else {
   1283       UNREACHABLE();
   1284     }
   1285   } else {
   1286     set_fpu_register(fd_reg(), kFPU64InvalidResult);
   1287   }
   1288 }
   1289 
   1290 
   1291 // Sets the rounding error codes in FCSR based on the result of the rounding.
   1292 // Returns true if the operation was invalid.
   1293 bool Simulator::set_fcsr_round_error(double original, double rounded) {
   1294   bool ret = false;
   1295   double max_int32 = std::numeric_limits<int32_t>::max();
   1296   double min_int32 = std::numeric_limits<int32_t>::min();
   1297 
   1298   if (!std::isfinite(original) || !std::isfinite(rounded)) {
   1299     set_fcsr_bit(kFCSRInvalidOpFlagBit, true);
   1300     ret = true;
   1301   }
   1302 
   1303   if (original != rounded) {
   1304     set_fcsr_bit(kFCSRInexactFlagBit, true);
   1305   }
   1306 
   1307   if (rounded < DBL_MIN && rounded > -DBL_MIN && rounded != 0) {
   1308     set_fcsr_bit(kFCSRUnderflowFlagBit, true);
   1309     ret = true;
   1310   }
   1311 
   1312   if (rounded > max_int32 || rounded < min_int32) {
   1313     set_fcsr_bit(kFCSROverflowFlagBit, true);
   1314     // The reference is not really clear but it seems this is required:
   1315     set_fcsr_bit(kFCSRInvalidOpFlagBit, true);
   1316     ret = true;
   1317   }
   1318 
   1319   return ret;
   1320 }
   1321 
   1322 
   1323 // Sets the rounding error codes in FCSR based on the result of the rounding.
   1324 // Returns true if the operation was invalid.
   1325 bool Simulator::set_fcsr_round64_error(double original, double rounded) {
   1326   bool ret = false;
   1327   // The value of INT64_MAX (2^63-1) can't be represented as double exactly,
   1328   // loading the most accurate representation into max_int64, which is 2^63.
   1329   double max_int64 = std::numeric_limits<int64_t>::max();
   1330   double min_int64 = std::numeric_limits<int64_t>::min();
   1331 
   1332   if (!std::isfinite(original) || !std::isfinite(rounded)) {
   1333     set_fcsr_bit(kFCSRInvalidOpFlagBit, true);
   1334     ret = true;
   1335   }
   1336 
   1337   if (original != rounded) {
   1338     set_fcsr_bit(kFCSRInexactFlagBit, true);
   1339   }
   1340 
   1341   if (rounded < DBL_MIN && rounded > -DBL_MIN && rounded != 0) {
   1342     set_fcsr_bit(kFCSRUnderflowFlagBit, true);
   1343     ret = true;
   1344   }
   1345 
   1346   if (rounded >= max_int64 || rounded < min_int64) {
   1347     set_fcsr_bit(kFCSROverflowFlagBit, true);
   1348     // The reference is not really clear but it seems this is required:
   1349     set_fcsr_bit(kFCSRInvalidOpFlagBit, true);
   1350     ret = true;
   1351   }
   1352 
   1353   return ret;
   1354 }
   1355 
   1356 
   1357 // Sets the rounding error codes in FCSR based on the result of the rounding.
   1358 // Returns true if the operation was invalid.
   1359 bool Simulator::set_fcsr_round_error(float original, float rounded) {
   1360   bool ret = false;
   1361   double max_int32 = std::numeric_limits<int32_t>::max();
   1362   double min_int32 = std::numeric_limits<int32_t>::min();
   1363 
   1364   if (!std::isfinite(original) || !std::isfinite(rounded)) {
   1365     set_fcsr_bit(kFCSRInvalidOpFlagBit, true);
   1366     ret = true;
   1367   }
   1368 
   1369   if (original != rounded) {
   1370     set_fcsr_bit(kFCSRInexactFlagBit, true);
   1371   }
   1372 
   1373   if (rounded < FLT_MIN && rounded > -FLT_MIN && rounded != 0) {
   1374     set_fcsr_bit(kFCSRUnderflowFlagBit, true);
   1375     ret = true;
   1376   }
   1377 
   1378   if (rounded > max_int32 || rounded < min_int32) {
   1379     set_fcsr_bit(kFCSROverflowFlagBit, true);
   1380     // The reference is not really clear but it seems this is required:
   1381     set_fcsr_bit(kFCSRInvalidOpFlagBit, true);
   1382     ret = true;
   1383   }
   1384 
   1385   return ret;
   1386 }
   1387 
   1388 
   1389 // Sets the rounding error codes in FCSR based on the result of the rounding.
   1390 // Returns true if the operation was invalid.
   1391 bool Simulator::set_fcsr_round64_error(float original, float rounded) {
   1392   bool ret = false;
   1393   // The value of INT64_MAX (2^63-1) can't be represented as double exactly,
   1394   // loading the most accurate representation into max_int64, which is 2^63.
   1395   double max_int64 = std::numeric_limits<int64_t>::max();
   1396   double min_int64 = std::numeric_limits<int64_t>::min();
   1397 
   1398   if (!std::isfinite(original) || !std::isfinite(rounded)) {
   1399     set_fcsr_bit(kFCSRInvalidOpFlagBit, true);
   1400     ret = true;
   1401   }
   1402 
   1403   if (original != rounded) {
   1404     set_fcsr_bit(kFCSRInexactFlagBit, true);
   1405   }
   1406 
   1407   if (rounded < FLT_MIN && rounded > -FLT_MIN && rounded != 0) {
   1408     set_fcsr_bit(kFCSRUnderflowFlagBit, true);
   1409     ret = true;
   1410   }
   1411 
   1412   if (rounded >= max_int64 || rounded < min_int64) {
   1413     set_fcsr_bit(kFCSROverflowFlagBit, true);
   1414     // The reference is not really clear but it seems this is required:
   1415     set_fcsr_bit(kFCSRInvalidOpFlagBit, true);
   1416     ret = true;
   1417   }
   1418 
   1419   return ret;
   1420 }
   1421 
   1422 
   1423 void Simulator::round_according_to_fcsr(double toRound, double& rounded,
   1424                                         int32_t& rounded_int, double fs) {
   1425   // 0 RN (round to nearest): Round a result to the nearest
   1426   // representable value; if the result is exactly halfway between
   1427   // two representable values, round to zero. Behave like round_w_d.
   1428 
   1429   // 1 RZ (round toward zero): Round a result to the closest
   1430   // representable value whose absolute value is less than or
   1431   // equal to the infinitely accurate result. Behave like trunc_w_d.
   1432 
   1433   // 2 RP (round up, or toward  infinity): Round a result to the
   1434   // next representable value up. Behave like ceil_w_d.
   1435 
   1436   // 3 RD (round down, or toward infinity): Round a result to
   1437   // the next representable value down. Behave like floor_w_d.
   1438   switch (get_fcsr_rounding_mode()) {
   1439     case kRoundToNearest:
   1440       rounded = std::floor(fs + 0.5);
   1441       rounded_int = static_cast<int32_t>(rounded);
   1442       if ((rounded_int & 1) != 0 && rounded_int - fs == 0.5) {
   1443         // If the number is halfway between two integers,
   1444         // round to the even one.
   1445         rounded_int--;
   1446         rounded -= 1.;
   1447       }
   1448       break;
   1449     case kRoundToZero:
   1450       rounded = trunc(fs);
   1451       rounded_int = static_cast<int32_t>(rounded);
   1452       break;
   1453     case kRoundToPlusInf:
   1454       rounded = std::ceil(fs);
   1455       rounded_int = static_cast<int32_t>(rounded);
   1456       break;
   1457     case kRoundToMinusInf:
   1458       rounded = std::floor(fs);
   1459       rounded_int = static_cast<int32_t>(rounded);
   1460       break;
   1461   }
   1462 }
   1463 
   1464 
   1465 void Simulator::round_according_to_fcsr(float toRound, float& rounded,
   1466                                         int32_t& rounded_int, float fs) {
   1467   // 0 RN (round to nearest): Round a result to the nearest
   1468   // representable value; if the result is exactly halfway between
   1469   // two representable values, round to zero. Behave like round_w_d.
   1470 
   1471   // 1 RZ (round toward zero): Round a result to the closest
   1472   // representable value whose absolute value is less than or
   1473   // equal to the infinitely accurate result. Behave like trunc_w_d.
   1474 
   1475   // 2 RP (round up, or toward  infinity): Round a result to the
   1476   // next representable value up. Behave like ceil_w_d.
   1477 
   1478   // 3 RD (round down, or toward infinity): Round a result to
   1479   // the next representable value down. Behave like floor_w_d.
   1480   switch (get_fcsr_rounding_mode()) {
   1481     case kRoundToNearest:
   1482       rounded = std::floor(fs + 0.5);
   1483       rounded_int = static_cast<int32_t>(rounded);
   1484       if ((rounded_int & 1) != 0 && rounded_int - fs == 0.5) {
   1485         // If the number is halfway between two integers,
   1486         // round to the even one.
   1487         rounded_int--;
   1488         rounded -= 1.f;
   1489       }
   1490       break;
   1491     case kRoundToZero:
   1492       rounded = trunc(fs);
   1493       rounded_int = static_cast<int32_t>(rounded);
   1494       break;
   1495     case kRoundToPlusInf:
   1496       rounded = std::ceil(fs);
   1497       rounded_int = static_cast<int32_t>(rounded);
   1498       break;
   1499     case kRoundToMinusInf:
   1500       rounded = std::floor(fs);
   1501       rounded_int = static_cast<int32_t>(rounded);
   1502       break;
   1503   }
   1504 }
   1505 
   1506 template <typename T_fp, typename T_int>
   1507 void Simulator::round_according_to_msacsr(T_fp toRound, T_fp& rounded,
   1508                                           T_int& rounded_int) {
   1509   // 0 RN (round to nearest): Round a result to the nearest
   1510   // representable value; if the result is exactly halfway between
   1511   // two representable values, round to zero. Behave like round_w_d.
   1512 
   1513   // 1 RZ (round toward zero): Round a result to the closest
   1514   // representable value whose absolute value is less than or
   1515   // equal to the infinitely accurate result. Behave like trunc_w_d.
   1516 
   1517   // 2 RP (round up, or toward  infinity): Round a result to the
   1518   // next representable value up. Behave like ceil_w_d.
   1519 
   1520   // 3 RD (round down, or toward infinity): Round a result to
   1521   // the next representable value down. Behave like floor_w_d.
   1522   switch (get_msacsr_rounding_mode()) {
   1523     case kRoundToNearest:
   1524       rounded = std::floor(toRound + 0.5);
   1525       rounded_int = static_cast<T_int>(rounded);
   1526       if ((rounded_int & 1) != 0 && rounded_int - toRound == 0.5) {
   1527         // If the number is halfway between two integers,
   1528         // round to the even one.
   1529         rounded_int--;
   1530         rounded -= 1;
   1531       }
   1532       break;
   1533     case kRoundToZero:
   1534       rounded = trunc(toRound);
   1535       rounded_int = static_cast<T_int>(rounded);
   1536       break;
   1537     case kRoundToPlusInf:
   1538       rounded = std::ceil(toRound);
   1539       rounded_int = static_cast<T_int>(rounded);
   1540       break;
   1541     case kRoundToMinusInf:
   1542       rounded = std::floor(toRound);
   1543       rounded_int = static_cast<T_int>(rounded);
   1544       break;
   1545   }
   1546 }
   1547 
   1548 void Simulator::round64_according_to_fcsr(double toRound, double& rounded,
   1549                                           int64_t& rounded_int, double fs) {
   1550   // 0 RN (round to nearest): Round a result to the nearest
   1551   // representable value; if the result is exactly halfway between
   1552   // two representable values, round to zero. Behave like round_w_d.
   1553 
   1554   // 1 RZ (round toward zero): Round a result to the closest
   1555   // representable value whose absolute value is less than or.
   1556   // equal to the infinitely accurate result. Behave like trunc_w_d.
   1557 
   1558   // 2 RP (round up, or toward +infinity): Round a result to the
   1559   // next representable value up. Behave like ceil_w_d.
   1560 
   1561   // 3 RN (round down, or toward infinity): Round a result to
   1562   // the next representable value down. Behave like floor_w_d.
   1563   switch (FCSR_ & 3) {
   1564     case kRoundToNearest:
   1565       rounded = std::floor(fs + 0.5);
   1566       rounded_int = static_cast<int64_t>(rounded);
   1567       if ((rounded_int & 1) != 0 && rounded_int - fs == 0.5) {
   1568         // If the number is halfway between two integers,
   1569         // round to the even one.
   1570         rounded_int--;
   1571         rounded -= 1.;
   1572       }
   1573       break;
   1574     case kRoundToZero:
   1575       rounded = trunc(fs);
   1576       rounded_int = static_cast<int64_t>(rounded);
   1577       break;
   1578     case kRoundToPlusInf:
   1579       rounded = std::ceil(fs);
   1580       rounded_int = static_cast<int64_t>(rounded);
   1581       break;
   1582     case kRoundToMinusInf:
   1583       rounded = std::floor(fs);
   1584       rounded_int = static_cast<int64_t>(rounded);
   1585       break;
   1586   }
   1587 }
   1588 
   1589 
   1590 void Simulator::round64_according_to_fcsr(float toRound, float& rounded,
   1591                                           int64_t& rounded_int, float 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         rounded -= 1.f;
   1614       }
   1615       break;
   1616     case kRoundToZero:
   1617       rounded = trunc(fs);
   1618       rounded_int = static_cast<int64_t>(rounded);
   1619       break;
   1620     case kRoundToPlusInf:
   1621       rounded = std::ceil(fs);
   1622       rounded_int = static_cast<int64_t>(rounded);
   1623       break;
   1624     case kRoundToMinusInf:
   1625       rounded = std::floor(fs);
   1626       rounded_int = static_cast<int64_t>(rounded);
   1627       break;
   1628   }
   1629 }
   1630 
   1631 
   1632 // Raw access to the PC register.
   1633 void Simulator::set_pc(int32_t value) {
   1634   pc_modified_ = true;
   1635   registers_[pc] = value;
   1636 }
   1637 
   1638 
   1639 bool Simulator::has_bad_pc() const {
   1640   return ((registers_[pc] == bad_ra) || (registers_[pc] == end_sim_pc));
   1641 }
   1642 
   1643 
   1644 // Raw access to the PC register without the special adjustment when reading.
   1645 int32_t Simulator::get_pc() const {
   1646   return registers_[pc];
   1647 }
   1648 
   1649 
   1650 // The MIPS cannot do unaligned reads and writes.  On some MIPS platforms an
   1651 // interrupt is caused.  On others it does a funky rotation thing.  For now we
   1652 // simply disallow unaligned reads, but at some point we may want to move to
   1653 // emulating the rotate behaviour.  Note that simulator runs have the runtime
   1654 // system running directly on the host system and only generated code is
   1655 // executed in the simulator.  Since the host is typically IA32 we will not
   1656 // get the correct MIPS-like behaviour on unaligned accesses.
   1657 
   1658 void Simulator::TraceRegWr(int32_t value, TraceType t) {
   1659   if (::v8::internal::FLAG_trace_sim) {
   1660     union {
   1661       int32_t fmt_int32;
   1662       float fmt_float;
   1663     } v;
   1664     v.fmt_int32 = value;
   1665 
   1666     switch (t) {
   1667       case WORD:
   1668         SNPrintF(trace_buf_, "%08" PRIx32 "    (%" PRIu64 ")    int32:%" PRId32
   1669                              " uint32:%" PRIu32,
   1670                  value, icount_, value, value);
   1671         break;
   1672       case FLOAT:
   1673         SNPrintF(trace_buf_, "%08" PRIx32 "    (%" PRIu64 ")    flt:%e",
   1674                  v.fmt_int32, icount_, v.fmt_float);
   1675         break;
   1676       default:
   1677         UNREACHABLE();
   1678     }
   1679   }
   1680 }
   1681 
   1682 void Simulator::TraceRegWr(int64_t value, TraceType t) {
   1683   if (::v8::internal::FLAG_trace_sim) {
   1684     union {
   1685       int64_t fmt_int64;
   1686       double fmt_double;
   1687     } v;
   1688     v.fmt_int64 = value;
   1689 
   1690     switch (t) {
   1691       case DWORD:
   1692         SNPrintF(trace_buf_, "%016" PRIx64 "    (%" PRIu64 ")    int64:%" PRId64
   1693                              " uint64:%" PRIu64,
   1694                  value, icount_, value, value);
   1695         break;
   1696       case DOUBLE:
   1697         SNPrintF(trace_buf_, "%016" PRIx64 "    (%" PRIu64 ")    dbl:%e",
   1698                  v.fmt_int64, icount_, v.fmt_double);
   1699         break;
   1700       default:
   1701         UNREACHABLE();
   1702     }
   1703   }
   1704 }
   1705 
   1706 template <typename T>
   1707 void Simulator::TraceMSARegWr(T* value, TraceType t) {
   1708   if (::v8::internal::FLAG_trace_sim) {
   1709     union {
   1710       uint8_t b[16];
   1711       uint16_t h[8];
   1712       uint32_t w[4];
   1713       uint64_t d[2];
   1714       float f[4];
   1715       double df[2];
   1716     } v;
   1717     memcpy(v.b, value, kSimd128Size);
   1718     switch (t) {
   1719       case BYTE:
   1720         SNPrintF(trace_buf_,
   1721                  "LO: %016" PRIx64 "  HI: %016" PRIx64 "    (%" PRIu64 ")",
   1722                  v.d[0], v.d[1], icount_);
   1723         break;
   1724       case HALF:
   1725         SNPrintF(trace_buf_,
   1726                  "LO: %016" PRIx64 "  HI: %016" PRIx64 "    (%" PRIu64 ")",
   1727                  v.d[0], v.d[1], icount_);
   1728         break;
   1729       case WORD:
   1730         SNPrintF(trace_buf_,
   1731                  "LO: %016" PRIx64 "  HI: %016" PRIx64 "    (%" PRIu64
   1732                  ")    int32[0..3]:%" PRId32 "  %" PRId32 "  %" PRId32
   1733                  "  %" PRId32,
   1734                  v.d[0], v.d[1], icount_, v.w[0], v.w[1], v.w[2], v.w[3]);
   1735         break;
   1736       case DWORD:
   1737         SNPrintF(trace_buf_,
   1738                  "LO: %016" PRIx64 "  HI: %016" PRIx64 "    (%" PRIu64 ")",
   1739                  v.d[0], v.d[1], icount_);
   1740         break;
   1741       case FLOAT:
   1742         SNPrintF(trace_buf_,
   1743                  "LO: %016" PRIx64 "  HI: %016" PRIx64 "    (%" PRIu64
   1744                  ")    flt[0..3]:%e  %e  %e  %e",
   1745                  v.d[0], v.d[1], icount_, v.f[0], v.f[1], v.f[2], v.f[3]);
   1746         break;
   1747       case DOUBLE:
   1748         SNPrintF(trace_buf_,
   1749                  "LO: %016" PRIx64 "  HI: %016" PRIx64 "    (%" PRIu64
   1750                  ")    dbl[0..1]:%e  %e",
   1751                  v.d[0], v.d[1], icount_, v.df[0], v.df[1]);
   1752         break;
   1753       default:
   1754         UNREACHABLE();
   1755     }
   1756   }
   1757 }
   1758 
   1759 template <typename T>
   1760 void Simulator::TraceMSARegWr(T* value) {
   1761   if (::v8::internal::FLAG_trace_sim) {
   1762     union {
   1763       uint8_t b[kMSALanesByte];
   1764       uint16_t h[kMSALanesHalf];
   1765       uint32_t w[kMSALanesWord];
   1766       uint64_t d[kMSALanesDword];
   1767       float f[kMSALanesWord];
   1768       double df[kMSALanesDword];
   1769     } v;
   1770     memcpy(v.b, value, kMSALanesByte);
   1771 
   1772     if (std::is_same<T, int32_t>::value) {
   1773       SNPrintF(trace_buf_,
   1774                "LO: %016" PRIx64 "  HI: %016" PRIx64 "    (%" PRIu64
   1775                ")    int32[0..3]:%" PRId32 "  %" PRId32 "  %" PRId32
   1776                "  %" PRId32,
   1777                v.d[0], v.d[1], icount_, v.w[0], v.w[1], v.w[2], v.w[3]);
   1778     } else if (std::is_same<T, float>::value) {
   1779       SNPrintF(trace_buf_,
   1780                "LO: %016" PRIx64 "  HI: %016" PRIx64 "    (%" PRIu64
   1781                ")    flt[0..3]:%e  %e  %e  %e",
   1782                v.d[0], v.d[1], icount_, v.f[0], v.f[1], v.f[2], v.f[3]);
   1783     } else if (std::is_same<T, double>::value) {
   1784       SNPrintF(trace_buf_,
   1785                "LO: %016" PRIx64 "  HI: %016" PRIx64 "    (%" PRIu64
   1786                ")    dbl[0..1]:%e  %e",
   1787                v.d[0], v.d[1], icount_, v.df[0], v.df[1]);
   1788     } else {
   1789       SNPrintF(trace_buf_,
   1790                "LO: %016" PRIx64 "  HI: %016" PRIx64 "    (%" PRIu64 ")",
   1791                v.d[0], v.d[1], icount_);
   1792     }
   1793   }
   1794 }
   1795 
   1796 // TODO(plind): consider making icount_ printing a flag option.
   1797 void Simulator::TraceMemRd(int32_t addr, int32_t value, TraceType t) {
   1798   if (::v8::internal::FLAG_trace_sim) {
   1799     union {
   1800       int32_t fmt_int32;
   1801       float fmt_float;
   1802     } v;
   1803     v.fmt_int32 = value;
   1804 
   1805     switch (t) {
   1806       case WORD:
   1807         SNPrintF(trace_buf_, "%08" PRIx32 " <-- [%08" PRIx32 "]    (%" PRIu64
   1808                              ")    int32:%" PRId32 " uint32:%" PRIu32,
   1809                  value, addr, icount_, value, value);
   1810         break;
   1811       case FLOAT:
   1812         SNPrintF(trace_buf_,
   1813                  "%08" PRIx32 " <-- [%08" PRIx32 "]    (%" PRIu64 ")    flt:%e",
   1814                  v.fmt_int32, addr, icount_, v.fmt_float);
   1815         break;
   1816       default:
   1817         UNREACHABLE();
   1818     }
   1819   }
   1820 }
   1821 
   1822 
   1823 void Simulator::TraceMemWr(int32_t addr, int32_t value, TraceType t) {
   1824   if (::v8::internal::FLAG_trace_sim) {
   1825     switch (t) {
   1826       case BYTE:
   1827         SNPrintF(trace_buf_,
   1828                  "      %02" PRIx8 " --> [%08" PRIx32 "]    (%" PRIu64 ")",
   1829                  static_cast<uint8_t>(value), addr, icount_);
   1830         break;
   1831       case HALF:
   1832         SNPrintF(trace_buf_,
   1833                  "    %04" PRIx16 " --> [%08" PRIx32 "]    (%" PRIu64 ")",
   1834                  static_cast<uint16_t>(value), addr, icount_);
   1835         break;
   1836       case WORD:
   1837         SNPrintF(trace_buf_,
   1838                  "%08" PRIx32 " --> [%08" PRIx32 "]    (%" PRIu64 ")", value,
   1839                  addr, icount_);
   1840         break;
   1841       default:
   1842         UNREACHABLE();
   1843     }
   1844   }
   1845 }
   1846 
   1847 template <typename T>
   1848 void Simulator::TraceMemRd(int32_t addr, T value) {
   1849   if (::v8::internal::FLAG_trace_sim) {
   1850     switch (sizeof(T)) {
   1851       case 1:
   1852         SNPrintF(trace_buf_,
   1853                  "%08" PRIx8 " <-- [%08" PRIx32 "]    (%" PRIu64
   1854                  ")    int8:%" PRId8 " uint8:%" PRIu8,
   1855                  static_cast<uint8_t>(value), addr, icount_,
   1856                  static_cast<int8_t>(value), static_cast<uint8_t>(value));
   1857         break;
   1858       case 2:
   1859         SNPrintF(trace_buf_,
   1860                  "%08" PRIx16 " <-- [%08" PRIx32 "]    (%" PRIu64
   1861                  ")    int16:%" PRId16 " uint16:%" PRIu16,
   1862                  static_cast<uint16_t>(value), addr, icount_,
   1863                  static_cast<int16_t>(value), static_cast<uint16_t>(value));
   1864         break;
   1865       case 4:
   1866         SNPrintF(trace_buf_,
   1867                  "%08" PRIx32 " <-- [%08" PRIx32 "]    (%" PRIu64
   1868                  ")    int32:%" PRId32 " uint32:%" PRIu32,
   1869                  static_cast<uint32_t>(value), addr, icount_,
   1870                  static_cast<int32_t>(value), static_cast<uint32_t>(value));
   1871         break;
   1872       case 8:
   1873         SNPrintF(trace_buf_,
   1874                  "%08" PRIx64 " <-- [%08" PRIx32 "]    (%" PRIu64
   1875                  ")    int64:%" PRId64 " uint64:%" PRIu64,
   1876                  static_cast<uint64_t>(value), addr, icount_,
   1877                  static_cast<int64_t>(value), static_cast<uint64_t>(value));
   1878         break;
   1879       default:
   1880         UNREACHABLE();
   1881     }
   1882   }
   1883 }
   1884 
   1885 template <typename T>
   1886 void Simulator::TraceMemWr(int32_t addr, T value) {
   1887   if (::v8::internal::FLAG_trace_sim) {
   1888     switch (sizeof(T)) {
   1889       case 1:
   1890         SNPrintF(trace_buf_,
   1891                  "      %02" PRIx8 " --> [%08" PRIx32 "]    (%" PRIu64 ")",
   1892                  static_cast<uint8_t>(value), addr, icount_);
   1893         break;
   1894       case 2:
   1895         SNPrintF(trace_buf_,
   1896                  "    %04" PRIx16 " --> [%08" PRIx32 "]    (%" PRIu64 ")",
   1897                  static_cast<uint16_t>(value), addr, icount_);
   1898         break;
   1899       case 4:
   1900         SNPrintF(trace_buf_,
   1901                  "%08" PRIx32 " --> [%08" PRIx32 "]    (%" PRIu64 ")",
   1902                  static_cast<uint32_t>(value), addr, icount_);
   1903         break;
   1904       case 8:
   1905         SNPrintF(trace_buf_,
   1906                  "%16" PRIx64 " --> [%08" PRIx32 "]    (%" PRIu64 ")",
   1907                  static_cast<uint64_t>(value), addr, icount_);
   1908         break;
   1909       default:
   1910         UNREACHABLE();
   1911     }
   1912   }
   1913 }
   1914 
   1915 void Simulator::TraceMemRd(int32_t addr, int64_t value, TraceType t) {
   1916   if (::v8::internal::FLAG_trace_sim) {
   1917     union {
   1918       int64_t fmt_int64;
   1919       int32_t fmt_int32[2];
   1920       float fmt_float[2];
   1921       double fmt_double;
   1922     } v;
   1923     v.fmt_int64 = value;
   1924 
   1925     switch (t) {
   1926       case DWORD:
   1927         SNPrintF(trace_buf_, "%016" PRIx64 " <-- [%08" PRIx32 "]    (%" PRIu64
   1928                              ")    int64:%" PRId64 " uint64:%" PRIu64,
   1929                  v.fmt_int64, addr, icount_, v.fmt_int64, v.fmt_int64);
   1930         break;
   1931       case DOUBLE:
   1932         SNPrintF(trace_buf_, "%016" PRIx64 " <-- [%08" PRIx32 "]    (%" PRIu64
   1933                              ")    dbl:%e",
   1934                  v.fmt_int64, addr, icount_, v.fmt_double);
   1935         break;
   1936       case FLOAT_DOUBLE:
   1937         SNPrintF(trace_buf_, "%08" PRIx32 " <-- [%08" PRIx32 "]    (%" PRIu64
   1938                              ")    flt:%e dbl:%e",
   1939                  v.fmt_int32[1], addr, icount_, v.fmt_float[1], v.fmt_double);
   1940         break;
   1941       default:
   1942         UNREACHABLE();
   1943     }
   1944   }
   1945 }
   1946 
   1947 void Simulator::TraceMemWr(int32_t addr, int64_t value, TraceType t) {
   1948   if (::v8::internal::FLAG_trace_sim) {
   1949     switch (t) {
   1950       case DWORD:
   1951         SNPrintF(trace_buf_,
   1952                  "%016" PRIx64 " --> [%08" PRIx32 "]    (%" PRIu64 ")", value,
   1953                  addr, icount_);
   1954         break;
   1955       default:
   1956         UNREACHABLE();
   1957     }
   1958   }
   1959 }
   1960 
   1961 int Simulator::ReadW(int32_t addr, Instruction* instr, TraceType t) {
   1962   if (addr >=0 && addr < 0x400) {
   1963     // This has to be a nullptr-dereference, drop into debugger.
   1964     PrintF("Memory read from bad address: 0x%08x, pc=0x%08" PRIxPTR "\n", addr,
   1965            reinterpret_cast<intptr_t>(instr));
   1966     MipsDebugger dbg(this);
   1967     dbg.Debug();
   1968   }
   1969   if ((addr & kPointerAlignmentMask) == 0 || IsMipsArchVariant(kMips32r6)) {
   1970     intptr_t* ptr = reinterpret_cast<intptr_t*>(addr);
   1971     switch (t) {
   1972       case WORD:
   1973         TraceMemRd(addr, static_cast<int32_t>(*ptr), t);
   1974         break;
   1975       case FLOAT:
   1976         // This TraceType is allowed but tracing for this value will be omitted.
   1977         break;
   1978       default:
   1979         UNREACHABLE();
   1980     }
   1981     return *ptr;
   1982   }
   1983   PrintF("Unaligned read at 0x%08x, pc=0x%08" V8PRIxPTR "\n",
   1984          addr,
   1985          reinterpret_cast<intptr_t>(instr));
   1986   MipsDebugger dbg(this);
   1987   dbg.Debug();
   1988   return 0;
   1989 }
   1990 
   1991 void Simulator::WriteW(int32_t addr, int value, Instruction* instr) {
   1992   if (addr >= 0 && addr < 0x400) {
   1993     // This has to be a nullptr-dereference, drop into debugger.
   1994     PrintF("Memory write to bad address: 0x%08x, pc=0x%08" PRIxPTR "\n", addr,
   1995            reinterpret_cast<intptr_t>(instr));
   1996     MipsDebugger dbg(this);
   1997     dbg.Debug();
   1998   }
   1999   if ((addr & kPointerAlignmentMask) == 0 || IsMipsArchVariant(kMips32r6)) {
   2000     intptr_t* ptr = reinterpret_cast<intptr_t*>(addr);
   2001     TraceMemWr(addr, value, WORD);
   2002     *ptr = value;
   2003     return;
   2004   }
   2005   PrintF("Unaligned write at 0x%08x, pc=0x%08" V8PRIxPTR "\n",
   2006          addr,
   2007          reinterpret_cast<intptr_t>(instr));
   2008   MipsDebugger dbg(this);
   2009   dbg.Debug();
   2010 }
   2011 
   2012 double Simulator::ReadD(int32_t addr, Instruction* instr) {
   2013   if ((addr & kDoubleAlignmentMask) == 0 || IsMipsArchVariant(kMips32r6)) {
   2014     double* ptr = reinterpret_cast<double*>(addr);
   2015     return *ptr;
   2016   }
   2017   PrintF("Unaligned (double) read at 0x%08x, pc=0x%08" V8PRIxPTR "\n",
   2018          addr,
   2019          reinterpret_cast<intptr_t>(instr));
   2020   base::OS::Abort();
   2021   return 0;
   2022 }
   2023 
   2024 
   2025 void Simulator::WriteD(int32_t addr, double value, Instruction* instr) {
   2026   if ((addr & kDoubleAlignmentMask) == 0 || IsMipsArchVariant(kMips32r6)) {
   2027     double* ptr = reinterpret_cast<double*>(addr);
   2028     *ptr = value;
   2029     return;
   2030   }
   2031   PrintF("Unaligned (double) write at 0x%08x, pc=0x%08" V8PRIxPTR "\n",
   2032          addr,
   2033          reinterpret_cast<intptr_t>(instr));
   2034   base::OS::Abort();
   2035 }
   2036 
   2037 
   2038 uint16_t Simulator::ReadHU(int32_t addr, Instruction* instr) {
   2039   if ((addr & 1) == 0 || IsMipsArchVariant(kMips32r6)) {
   2040     uint16_t* ptr = reinterpret_cast<uint16_t*>(addr);
   2041     TraceMemRd(addr, static_cast<int32_t>(*ptr));
   2042     return *ptr;
   2043   }
   2044   PrintF("Unaligned unsigned halfword read at 0x%08x, pc=0x%08" V8PRIxPTR "\n",
   2045          addr,
   2046          reinterpret_cast<intptr_t>(instr));
   2047   base::OS::Abort();
   2048   return 0;
   2049 }
   2050 
   2051 
   2052 int16_t Simulator::ReadH(int32_t addr, Instruction* instr) {
   2053   if ((addr & 1) == 0 || IsMipsArchVariant(kMips32r6)) {
   2054     int16_t* ptr = reinterpret_cast<int16_t*>(addr);
   2055     TraceMemRd(addr, static_cast<int32_t>(*ptr));
   2056     return *ptr;
   2057   }
   2058   PrintF("Unaligned signed halfword read at 0x%08x, pc=0x%08" V8PRIxPTR "\n",
   2059          addr,
   2060          reinterpret_cast<intptr_t>(instr));
   2061   base::OS::Abort();
   2062   return 0;
   2063 }
   2064 
   2065 
   2066 void Simulator::WriteH(int32_t addr, uint16_t value, Instruction* instr) {
   2067   if ((addr & 1) == 0 || IsMipsArchVariant(kMips32r6)) {
   2068     uint16_t* ptr = reinterpret_cast<uint16_t*>(addr);
   2069     TraceMemWr(addr, value, HALF);
   2070     *ptr = value;
   2071     return;
   2072   }
   2073   PrintF("Unaligned unsigned halfword write at 0x%08x, pc=0x%08" V8PRIxPTR "\n",
   2074          addr,
   2075          reinterpret_cast<intptr_t>(instr));
   2076   base::OS::Abort();
   2077 }
   2078 
   2079 
   2080 void Simulator::WriteH(int32_t addr, int16_t value, Instruction* instr) {
   2081   if ((addr & 1) == 0 || IsMipsArchVariant(kMips32r6)) {
   2082     int16_t* ptr = reinterpret_cast<int16_t*>(addr);
   2083     TraceMemWr(addr, value, HALF);
   2084     *ptr = value;
   2085     return;
   2086   }
   2087   PrintF("Unaligned halfword write at 0x%08x, pc=0x%08" V8PRIxPTR "\n",
   2088          addr,
   2089          reinterpret_cast<intptr_t>(instr));
   2090   base::OS::Abort();
   2091 }
   2092 
   2093 
   2094 uint32_t Simulator::ReadBU(int32_t addr) {
   2095   uint8_t* ptr = reinterpret_cast<uint8_t*>(addr);
   2096   TraceMemRd(addr, static_cast<int32_t>(*ptr));
   2097   return *ptr & 0xFF;
   2098 }
   2099 
   2100 
   2101 int32_t Simulator::ReadB(int32_t addr) {
   2102   int8_t* ptr = reinterpret_cast<int8_t*>(addr);
   2103   TraceMemRd(addr, static_cast<int32_t>(*ptr));
   2104   return *ptr;
   2105 }
   2106 
   2107 
   2108 void Simulator::WriteB(int32_t addr, uint8_t value) {
   2109   uint8_t* ptr = reinterpret_cast<uint8_t*>(addr);
   2110   TraceMemWr(addr, value, BYTE);
   2111   *ptr = value;
   2112 }
   2113 
   2114 
   2115 void Simulator::WriteB(int32_t addr, int8_t value) {
   2116   int8_t* ptr = reinterpret_cast<int8_t*>(addr);
   2117   TraceMemWr(addr, value, BYTE);
   2118   *ptr = value;
   2119 }
   2120 
   2121 template <typename T>
   2122 T Simulator::ReadMem(int32_t addr, Instruction* instr) {
   2123   int alignment_mask = (1 << sizeof(T)) - 1;
   2124   if ((addr & alignment_mask) == 0 || IsMipsArchVariant(kMips32r6)) {
   2125     T* ptr = reinterpret_cast<T*>(addr);
   2126     TraceMemRd(addr, *ptr);
   2127     return *ptr;
   2128   }
   2129   PrintF("Unaligned read of type sizeof(%d) at 0x%08x, pc=0x%08" V8PRIxPTR "\n",
   2130          sizeof(T), addr, reinterpret_cast<intptr_t>(instr));
   2131   base::OS::Abort();
   2132   return 0;
   2133 }
   2134 
   2135 template <typename T>
   2136 void Simulator::WriteMem(int32_t addr, T value, Instruction* instr) {
   2137   int alignment_mask = (1 << sizeof(T)) - 1;
   2138   if ((addr & alignment_mask) == 0 || IsMipsArchVariant(kMips32r6)) {
   2139     T* ptr = reinterpret_cast<T*>(addr);
   2140     *ptr = value;
   2141     TraceMemWr(addr, value);
   2142     return;
   2143   }
   2144   PrintF("Unaligned write of type sizeof(%d) at 0x%08x, pc=0x%08" V8PRIxPTR
   2145          "\n",
   2146          sizeof(T), addr, reinterpret_cast<intptr_t>(instr));
   2147   base::OS::Abort();
   2148 }
   2149 
   2150 // Returns the limit of the stack area to enable checking for stack overflows.
   2151 uintptr_t Simulator::StackLimit(uintptr_t c_limit) const {
   2152   // The simulator uses a separate JS stack. If we have exhausted the C stack,
   2153   // we also drop down the JS limit to reflect the exhaustion on the JS stack.
   2154   if (GetCurrentStackPosition() < c_limit) {
   2155     return reinterpret_cast<uintptr_t>(get_sp());
   2156   }
   2157 
   2158   // Otherwise the limit is the JS stack. Leave a safety margin of 1024 bytes
   2159   // to prevent overrunning the stack when pushing values.
   2160   return reinterpret_cast<uintptr_t>(stack_) + 1024;
   2161 }
   2162 
   2163 
   2164 // Unsupported instructions use Format to print an error and stop execution.
   2165 void Simulator::Format(Instruction* instr, const char* format) {
   2166   PrintF("Simulator found unsupported instruction:\n 0x%08" PRIxPTR ": %s\n",
   2167          reinterpret_cast<intptr_t>(instr), format);
   2168   UNIMPLEMENTED_MIPS();
   2169 }
   2170 
   2171 
   2172 // Calls into the V8 runtime are based on this very simple interface.
   2173 // Note: To be able to return two values from some calls the code in runtime.cc
   2174 // uses the ObjectPair which is essentially two 32-bit values stuffed into a
   2175 // 64-bit value. With the code below we assume that all runtime calls return
   2176 // 64 bits of result. If they don't, the v1 result register contains a bogus
   2177 // value, which is fine because it is caller-saved.
   2178 typedef int64_t (*SimulatorRuntimeCall)(int32_t arg0, int32_t arg1,
   2179                                         int32_t arg2, int32_t arg3,
   2180                                         int32_t arg4, int32_t arg5,
   2181                                         int32_t arg6, int32_t arg7,
   2182                                         int32_t arg8);
   2183 
   2184 // These prototypes handle the four types of FP calls.
   2185 typedef int64_t (*SimulatorRuntimeCompareCall)(double darg0, double darg1);
   2186 typedef double (*SimulatorRuntimeFPFPCall)(double darg0, double darg1);
   2187 typedef double (*SimulatorRuntimeFPCall)(double darg0);
   2188 typedef double (*SimulatorRuntimeFPIntCall)(double darg0, int32_t arg0);
   2189 
   2190 // This signature supports direct call in to API function native callback
   2191 // (refer to InvocationCallback in v8.h).
   2192 typedef void (*SimulatorRuntimeDirectApiCall)(int32_t arg0);
   2193 typedef void (*SimulatorRuntimeProfilingApiCall)(int32_t arg0, void* arg1);
   2194 
   2195 // This signature supports direct call to accessor getter callback.
   2196 typedef void (*SimulatorRuntimeDirectGetterCall)(int32_t arg0, int32_t arg1);
   2197 typedef void (*SimulatorRuntimeProfilingGetterCall)(
   2198     int32_t arg0, int32_t arg1, void* arg2);
   2199 
   2200 // Software interrupt instructions are used by the simulator to call into the
   2201 // C-based V8 runtime. They are also used for debugging with simulator.
   2202 void Simulator::SoftwareInterrupt() {
   2203   // There are several instructions that could get us here,
   2204   // the break_ instruction, or several variants of traps. All
   2205   // Are "SPECIAL" class opcode, and are distinuished by function.
   2206   int32_t func = instr_.FunctionFieldRaw();
   2207   uint32_t code = (func == BREAK) ? instr_.Bits(25, 6) : -1;
   2208 
   2209   // We first check if we met a call_rt_redirected.
   2210   if (instr_.InstructionBits() == rtCallRedirInstr) {
   2211     Redirection* redirection = Redirection::FromInstruction(instr_.instr());
   2212     int32_t arg0 = get_register(a0);
   2213     int32_t arg1 = get_register(a1);
   2214     int32_t arg2 = get_register(a2);
   2215     int32_t arg3 = get_register(a3);
   2216 
   2217     int32_t* stack_pointer = reinterpret_cast<int32_t*>(get_register(sp));
   2218     // Args 4 and 5 are on the stack after the reserved space for args 0..3.
   2219     int32_t arg4 = stack_pointer[4];
   2220     int32_t arg5 = stack_pointer[5];
   2221     int32_t arg6 = stack_pointer[6];
   2222     int32_t arg7 = stack_pointer[7];
   2223     int32_t arg8 = stack_pointer[8];
   2224     STATIC_ASSERT(kMaxCParameters == 9);
   2225 
   2226     bool fp_call =
   2227          (redirection->type() == ExternalReference::BUILTIN_FP_FP_CALL) ||
   2228          (redirection->type() == ExternalReference::BUILTIN_COMPARE_CALL) ||
   2229          (redirection->type() == ExternalReference::BUILTIN_FP_CALL) ||
   2230          (redirection->type() == ExternalReference::BUILTIN_FP_INT_CALL);
   2231 
   2232     if (!IsMipsSoftFloatABI) {
   2233       // With the hard floating point calling convention, double
   2234       // arguments are passed in FPU registers. Fetch the arguments
   2235       // from there and call the builtin using soft floating point
   2236       // convention.
   2237       switch (redirection->type()) {
   2238       case ExternalReference::BUILTIN_FP_FP_CALL:
   2239       case ExternalReference::BUILTIN_COMPARE_CALL:
   2240         if (IsFp64Mode()) {
   2241           arg0 = get_fpu_register_word(f12);
   2242           arg1 = get_fpu_register_hi_word(f12);
   2243           arg2 = get_fpu_register_word(f14);
   2244           arg3 = get_fpu_register_hi_word(f14);
   2245         } else {
   2246           arg0 = get_fpu_register_word(f12);
   2247           arg1 = get_fpu_register_word(f13);
   2248           arg2 = get_fpu_register_word(f14);
   2249           arg3 = get_fpu_register_word(f15);
   2250         }
   2251         break;
   2252       case ExternalReference::BUILTIN_FP_CALL:
   2253         if (IsFp64Mode()) {
   2254           arg0 = get_fpu_register_word(f12);
   2255           arg1 = get_fpu_register_hi_word(f12);
   2256         } else {
   2257           arg0 = get_fpu_register_word(f12);
   2258           arg1 = get_fpu_register_word(f13);
   2259         }
   2260         break;
   2261       case ExternalReference::BUILTIN_FP_INT_CALL:
   2262         if (IsFp64Mode()) {
   2263           arg0 = get_fpu_register_word(f12);
   2264           arg1 = get_fpu_register_hi_word(f12);
   2265         } else {
   2266           arg0 = get_fpu_register_word(f12);
   2267           arg1 = get_fpu_register_word(f13);
   2268         }
   2269         arg2 = get_register(a2);
   2270         break;
   2271       default:
   2272         break;
   2273       }
   2274     }
   2275 
   2276     // This is dodgy but it works because the C entry stubs are never moved.
   2277     // See comment in codegen-arm.cc and bug 1242173.
   2278     int32_t saved_ra = get_register(ra);
   2279 
   2280     intptr_t external =
   2281           reinterpret_cast<intptr_t>(redirection->external_function());
   2282 
   2283     // Based on CpuFeatures::IsSupported(FPU), Mips will use either hardware
   2284     // FPU, or gcc soft-float routines. Hardware FPU is simulated in this
   2285     // simulator. Soft-float has additional abstraction of ExternalReference,
   2286     // to support serialization.
   2287     if (fp_call) {
   2288       double dval0, dval1;  // one or two double parameters
   2289       int32_t ival;         // zero or one integer parameters
   2290       int64_t iresult = 0;  // integer return value
   2291       double dresult = 0;   // double return value
   2292       GetFpArgs(&dval0, &dval1, &ival);
   2293       SimulatorRuntimeCall generic_target =
   2294           reinterpret_cast<SimulatorRuntimeCall>(external);
   2295       if (::v8::internal::FLAG_trace_sim) {
   2296         switch (redirection->type()) {
   2297           case ExternalReference::BUILTIN_FP_FP_CALL:
   2298           case ExternalReference::BUILTIN_COMPARE_CALL:
   2299             PrintF("Call to host function at %p with args %f, %f",
   2300                    reinterpret_cast<void*>(FUNCTION_ADDR(generic_target)),
   2301                    dval0, dval1);
   2302             break;
   2303           case ExternalReference::BUILTIN_FP_CALL:
   2304             PrintF("Call to host function at %p with arg %f",
   2305                    reinterpret_cast<void*>(FUNCTION_ADDR(generic_target)),
   2306                    dval0);
   2307             break;
   2308           case ExternalReference::BUILTIN_FP_INT_CALL:
   2309             PrintF("Call to host function at %p with args %f, %d",
   2310                    reinterpret_cast<void*>(FUNCTION_ADDR(generic_target)),
   2311                    dval0, ival);
   2312             break;
   2313           default:
   2314             UNREACHABLE();
   2315             break;
   2316         }
   2317       }
   2318       switch (redirection->type()) {
   2319       case ExternalReference::BUILTIN_COMPARE_CALL: {
   2320         SimulatorRuntimeCompareCall target =
   2321           reinterpret_cast<SimulatorRuntimeCompareCall>(external);
   2322         iresult = target(dval0, dval1);
   2323         set_register(v0, static_cast<int32_t>(iresult));
   2324         set_register(v1, static_cast<int32_t>(iresult >> 32));
   2325         break;
   2326       }
   2327       case ExternalReference::BUILTIN_FP_FP_CALL: {
   2328         SimulatorRuntimeFPFPCall target =
   2329           reinterpret_cast<SimulatorRuntimeFPFPCall>(external);
   2330         dresult = target(dval0, dval1);
   2331         SetFpResult(dresult);
   2332         break;
   2333       }
   2334       case ExternalReference::BUILTIN_FP_CALL: {
   2335         SimulatorRuntimeFPCall target =
   2336           reinterpret_cast<SimulatorRuntimeFPCall>(external);
   2337         dresult = target(dval0);
   2338         SetFpResult(dresult);
   2339         break;
   2340       }
   2341       case ExternalReference::BUILTIN_FP_INT_CALL: {
   2342         SimulatorRuntimeFPIntCall target =
   2343           reinterpret_cast<SimulatorRuntimeFPIntCall>(external);
   2344         dresult = target(dval0, ival);
   2345         SetFpResult(dresult);
   2346         break;
   2347       }
   2348       default:
   2349         UNREACHABLE();
   2350         break;
   2351       }
   2352       if (::v8::internal::FLAG_trace_sim) {
   2353         switch (redirection->type()) {
   2354         case ExternalReference::BUILTIN_COMPARE_CALL:
   2355           PrintF("Returned %08x\n", static_cast<int32_t>(iresult));
   2356           break;
   2357         case ExternalReference::BUILTIN_FP_FP_CALL:
   2358         case ExternalReference::BUILTIN_FP_CALL:
   2359         case ExternalReference::BUILTIN_FP_INT_CALL:
   2360           PrintF("Returned %f\n", dresult);
   2361           break;
   2362         default:
   2363           UNREACHABLE();
   2364           break;
   2365         }
   2366       }
   2367     } else if (redirection->type() == ExternalReference::DIRECT_API_CALL) {
   2368       if (::v8::internal::FLAG_trace_sim) {
   2369         PrintF("Call to host function at %p args %08x\n",
   2370             reinterpret_cast<void*>(external), arg0);
   2371       }
   2372       SimulatorRuntimeDirectApiCall target =
   2373           reinterpret_cast<SimulatorRuntimeDirectApiCall>(external);
   2374       target(arg0);
   2375     } else if (
   2376         redirection->type() == ExternalReference::PROFILING_API_CALL) {
   2377       if (::v8::internal::FLAG_trace_sim) {
   2378         PrintF("Call to host function at %p args %08x %08x\n",
   2379             reinterpret_cast<void*>(external), arg0, arg1);
   2380       }
   2381       SimulatorRuntimeProfilingApiCall target =
   2382           reinterpret_cast<SimulatorRuntimeProfilingApiCall>(external);
   2383       target(arg0, Redirection::ReverseRedirection(arg1));
   2384     } else if (
   2385         redirection->type() == ExternalReference::DIRECT_GETTER_CALL) {
   2386       if (::v8::internal::FLAG_trace_sim) {
   2387         PrintF("Call to host function at %p args %08x %08x\n",
   2388             reinterpret_cast<void*>(external), arg0, arg1);
   2389       }
   2390       SimulatorRuntimeDirectGetterCall target =
   2391           reinterpret_cast<SimulatorRuntimeDirectGetterCall>(external);
   2392       target(arg0, arg1);
   2393     } else if (
   2394         redirection->type() == ExternalReference::PROFILING_GETTER_CALL) {
   2395       if (::v8::internal::FLAG_trace_sim) {
   2396         PrintF("Call to host function at %p args %08x %08x %08x\n",
   2397             reinterpret_cast<void*>(external), arg0, arg1, arg2);
   2398       }
   2399       SimulatorRuntimeProfilingGetterCall target =
   2400           reinterpret_cast<SimulatorRuntimeProfilingGetterCall>(external);
   2401       target(arg0, arg1, Redirection::ReverseRedirection(arg2));
   2402     } else {
   2403       DCHECK(redirection->type() == ExternalReference::BUILTIN_CALL ||
   2404              redirection->type() == ExternalReference::BUILTIN_CALL_PAIR);
   2405       SimulatorRuntimeCall target =
   2406                   reinterpret_cast<SimulatorRuntimeCall>(external);
   2407       if (::v8::internal::FLAG_trace_sim) {
   2408         PrintF(
   2409             "Call to host function at %p "
   2410             "args %08x, %08x, %08x, %08x, %08x, %08x, %08x, %08x, %08x\n",
   2411             reinterpret_cast<void*>(FUNCTION_ADDR(target)), arg0, arg1, arg2,
   2412             arg3, arg4, arg5, arg6, arg7, arg8);
   2413       }
   2414       int64_t result =
   2415           target(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8);
   2416       set_register(v0, static_cast<int32_t>(result));
   2417       set_register(v1, static_cast<int32_t>(result >> 32));
   2418     }
   2419     if (::v8::internal::FLAG_trace_sim) {
   2420       PrintF("Returned %08x : %08x\n", get_register(v1), get_register(v0));
   2421     }
   2422     set_register(ra, saved_ra);
   2423     set_pc(get_register(ra));
   2424 
   2425   } else if (func == BREAK && code <= kMaxStopCode) {
   2426     if (IsWatchpoint(code)) {
   2427       PrintWatchpoint(code);
   2428     } else {
   2429       IncreaseStopCounter(code);
   2430       HandleStop(code, instr_.instr());
   2431     }
   2432   } else {
   2433     // All remaining break_ codes, and all traps are handled here.
   2434     MipsDebugger dbg(this);
   2435     dbg.Debug();
   2436   }
   2437 }
   2438 
   2439 
   2440 // Stop helper functions.
   2441 bool Simulator::IsWatchpoint(uint32_t code) {
   2442   return (code <= kMaxWatchpointCode);
   2443 }
   2444 
   2445 
   2446 void Simulator::PrintWatchpoint(uint32_t code) {
   2447   MipsDebugger dbg(this);
   2448   ++break_count_;
   2449   PrintF("\n---- break %d marker: %3d  (instr count: %" PRIu64
   2450          ") ----------"
   2451          "----------------------------------",
   2452          code, break_count_, icount_);
   2453   dbg.PrintAllRegs();  // Print registers and continue running.
   2454 }
   2455 
   2456 
   2457 void Simulator::HandleStop(uint32_t code, Instruction* instr) {
   2458   // Stop if it is enabled, otherwise go on jumping over the stop
   2459   // and the message address.
   2460   if (IsEnabledStop(code)) {
   2461     MipsDebugger dbg(this);
   2462     dbg.Stop(instr);
   2463   }
   2464 }
   2465 
   2466 
   2467 bool Simulator::IsStopInstruction(Instruction* instr) {
   2468   int32_t func = instr->FunctionFieldRaw();
   2469   uint32_t code = static_cast<uint32_t>(instr->Bits(25, 6));
   2470   return (func == BREAK) && code > kMaxWatchpointCode && code <= kMaxStopCode;
   2471 }
   2472 
   2473 
   2474 bool Simulator::IsEnabledStop(uint32_t code) {
   2475   DCHECK_LE(code, kMaxStopCode);
   2476   DCHECK_GT(code, kMaxWatchpointCode);
   2477   return !(watched_stops_[code].count & kStopDisabledBit);
   2478 }
   2479 
   2480 
   2481 void Simulator::EnableStop(uint32_t code) {
   2482   if (!IsEnabledStop(code)) {
   2483     watched_stops_[code].count &= ~kStopDisabledBit;
   2484   }
   2485 }
   2486 
   2487 
   2488 void Simulator::DisableStop(uint32_t code) {
   2489   if (IsEnabledStop(code)) {
   2490     watched_stops_[code].count |= kStopDisabledBit;
   2491   }
   2492 }
   2493 
   2494 
   2495 void Simulator::IncreaseStopCounter(uint32_t code) {
   2496   DCHECK_LE(code, kMaxStopCode);
   2497   if ((watched_stops_[code].count & ~(1 << 31)) == 0x7FFFFFFF) {
   2498     PrintF("Stop counter for code %i has overflowed.\n"
   2499            "Enabling this code and reseting the counter to 0.\n", code);
   2500     watched_stops_[code].count = 0;
   2501     EnableStop(code);
   2502   } else {
   2503     watched_stops_[code].count++;
   2504   }
   2505 }
   2506 
   2507 
   2508 // Print a stop status.
   2509 void Simulator::PrintStopInfo(uint32_t code) {
   2510   if (code <= kMaxWatchpointCode) {
   2511     PrintF("That is a watchpoint, not a stop.\n");
   2512     return;
   2513   } else if (code > kMaxStopCode) {
   2514     PrintF("Code too large, only %u stops can be used\n", kMaxStopCode + 1);
   2515     return;
   2516   }
   2517   const char* state = IsEnabledStop(code) ? "Enabled" : "Disabled";
   2518   int32_t count = watched_stops_[code].count & ~kStopDisabledBit;
   2519   // Don't print the state of unused breakpoints.
   2520   if (count != 0) {
   2521     if (watched_stops_[code].desc) {
   2522       PrintF("stop %i - 0x%x: \t%s, \tcounter = %i, \t%s\n",
   2523              code, code, state, count, watched_stops_[code].desc);
   2524     } else {
   2525       PrintF("stop %i - 0x%x: \t%s, \tcounter = %i\n",
   2526              code, code, state, count);
   2527     }
   2528   }
   2529 }
   2530 
   2531 
   2532 void Simulator::SignalException(Exception e) {
   2533   FATAL("Error: Exception %i raised.", static_cast<int>(e));
   2534 }
   2535 
   2536 // Min/Max template functions for Double and Single arguments.
   2537 
   2538 template <typename T>
   2539 static T FPAbs(T a);
   2540 
   2541 template <>
   2542 double FPAbs<double>(double a) {
   2543   return fabs(a);
   2544 }
   2545 
   2546 template <>
   2547 float FPAbs<float>(float a) {
   2548   return fabsf(a);
   2549 }
   2550 
   2551 template <typename T>
   2552 static bool FPUProcessNaNsAndZeros(T a, T b, MaxMinKind kind, T& result) {
   2553   if (std::isnan(a) && std::isnan(b)) {
   2554     result = a;
   2555   } else if (std::isnan(a)) {
   2556     result = b;
   2557   } else if (std::isnan(b)) {
   2558     result = a;
   2559   } else if (b == a) {
   2560     // Handle -0.0 == 0.0 case.
   2561     // std::signbit() returns int 0 or 1 so subtracting MaxMinKind::kMax
   2562     // negates the result.
   2563     result = std::signbit(b) - static_cast<int>(kind) ? b : a;
   2564   } else {
   2565     return false;
   2566   }
   2567   return true;
   2568 }
   2569 
   2570 template <typename T>
   2571 static T FPUMin(T a, T b) {
   2572   T result;
   2573   if (FPUProcessNaNsAndZeros(a, b, MaxMinKind::kMin, result)) {
   2574     return result;
   2575   } else {
   2576     return b < a ? b : a;
   2577   }
   2578 }
   2579 
   2580 template <typename T>
   2581 static T FPUMax(T a, T b) {
   2582   T result;
   2583   if (FPUProcessNaNsAndZeros(a, b, MaxMinKind::kMax, result)) {
   2584     return result;
   2585   } else {
   2586     return b > a ? b : a;
   2587   }
   2588 }
   2589 
   2590 template <typename T>
   2591 static T FPUMinA(T a, T b) {
   2592   T result;
   2593   if (!FPUProcessNaNsAndZeros(a, b, MaxMinKind::kMin, result)) {
   2594     if (FPAbs(a) < FPAbs(b)) {
   2595       result = a;
   2596     } else if (FPAbs(b) < FPAbs(a)) {
   2597       result = b;
   2598     } else {
   2599       result = a < b ? a : b;
   2600     }
   2601   }
   2602   return result;
   2603 }
   2604 
   2605 template <typename T>
   2606 static T FPUMaxA(T a, T b) {
   2607   T result;
   2608   if (!FPUProcessNaNsAndZeros(a, b, MaxMinKind::kMin, result)) {
   2609     if (FPAbs(a) > FPAbs(b)) {
   2610       result = a;
   2611     } else if (FPAbs(b) > FPAbs(a)) {
   2612       result = b;
   2613     } else {
   2614       result = a > b ? a : b;
   2615     }
   2616   }
   2617   return result;
   2618 }
   2619 
   2620 enum class KeepSign : bool { no = false, yes };
   2621 
   2622 template <typename T, typename std::enable_if<std::is_floating_point<T>::value,
   2623                                               int>::type = 0>
   2624 T FPUCanonalizeNaNArg(T result, T arg, KeepSign keepSign = KeepSign::no) {
   2625   DCHECK(std::isnan(arg));
   2626   T qNaN = std::numeric_limits<T>::quiet_NaN();
   2627   if (keepSign == KeepSign::yes) {
   2628     return std::copysign(qNaN, result);
   2629   }
   2630   return qNaN;
   2631 }
   2632 
   2633 template <typename T>
   2634 T FPUCanonalizeNaNArgs(T result, KeepSign keepSign, T first) {
   2635   if (std::isnan(first)) {
   2636     return FPUCanonalizeNaNArg(result, first, keepSign);
   2637   }
   2638   return result;
   2639 }
   2640 
   2641 template <typename T, typename... Args>
   2642 T FPUCanonalizeNaNArgs(T result, KeepSign keepSign, T first, Args... args) {
   2643   if (std::isnan(first)) {
   2644     return FPUCanonalizeNaNArg(result, first, keepSign);
   2645   }
   2646   return FPUCanonalizeNaNArgs(result, keepSign, args...);
   2647 }
   2648 
   2649 template <typename Func, typename T, typename... Args>
   2650 T FPUCanonalizeOperation(Func f, T first, Args... args) {
   2651   return FPUCanonalizeOperation(f, KeepSign::no, first, args...);
   2652 }
   2653 
   2654 template <typename Func, typename T, typename... Args>
   2655 T FPUCanonalizeOperation(Func f, KeepSign keepSign, T first, Args... args) {
   2656   T result = f(first, args...);
   2657   if (std::isnan(result)) {
   2658     result = FPUCanonalizeNaNArgs(result, keepSign, first, args...);
   2659   }
   2660   return result;
   2661 }
   2662 
   2663 // Handle execution based on instruction types.
   2664 
   2665 void Simulator::DecodeTypeRegisterDRsType() {
   2666   double ft, fs, fd;
   2667   uint32_t cc, fcsr_cc;
   2668   int64_t i64;
   2669   fs = get_fpu_register_double(fs_reg());
   2670   ft = (instr_.FunctionFieldRaw() != MOVF) ? get_fpu_register_double(ft_reg())
   2671                                            : 0.0;
   2672   fd = get_fpu_register_double(fd_reg());
   2673   int64_t ft_int = bit_cast<int64_t>(ft);
   2674   int64_t fd_int = bit_cast<int64_t>(fd);
   2675   cc = instr_.FCccValue();
   2676   fcsr_cc = get_fcsr_condition_bit(cc);
   2677   switch (instr_.FunctionFieldRaw()) {
   2678     case RINT: {
   2679       DCHECK(IsMipsArchVariant(kMips32r6));
   2680       double result, temp, temp_result;
   2681       double upper = std::ceil(fs);
   2682       double lower = std::floor(fs);
   2683       switch (get_fcsr_rounding_mode()) {
   2684         case kRoundToNearest:
   2685           if (upper - fs < fs - lower) {
   2686             result = upper;
   2687           } else if (upper - fs > fs - lower) {
   2688             result = lower;
   2689           } else {
   2690             temp_result = upper / 2;
   2691             double reminder = modf(temp_result, &temp);
   2692             if (reminder == 0) {
   2693               result = upper;
   2694             } else {
   2695               result = lower;
   2696             }
   2697           }
   2698           break;
   2699         case kRoundToZero:
   2700           result = (fs > 0 ? lower : upper);
   2701           break;
   2702         case kRoundToPlusInf:
   2703           result = upper;
   2704           break;
   2705         case kRoundToMinusInf:
   2706           result = lower;
   2707           break;
   2708       }
   2709       SetFPUDoubleResult(fd_reg(), result);
   2710       if (result != fs) {
   2711         set_fcsr_bit(kFCSRInexactFlagBit, true);
   2712       }
   2713       break;
   2714     }
   2715     case SEL:
   2716       DCHECK(IsMipsArchVariant(kMips32r6));
   2717       SetFPUDoubleResult(fd_reg(), (fd_int & 0x1) == 0 ? fs : ft);
   2718       break;
   2719     case SELEQZ_C:
   2720       DCHECK(IsMipsArchVariant(kMips32r6));
   2721       SetFPUDoubleResult(fd_reg(), (ft_int & 0x1) == 0 ? fs : 0.0);
   2722       break;
   2723     case SELNEZ_C:
   2724       DCHECK(IsMipsArchVariant(kMips32r6));
   2725       SetFPUDoubleResult(fd_reg(), (ft_int & 0x1) != 0 ? fs : 0.0);
   2726       break;
   2727     case MOVZ_C: {
   2728       DCHECK(IsMipsArchVariant(kMips32r2));
   2729       if (rt() == 0) {
   2730         SetFPUDoubleResult(fd_reg(), fs);
   2731       }
   2732       break;
   2733     }
   2734     case MOVN_C: {
   2735       DCHECK(IsMipsArchVariant(kMips32r2));
   2736       int32_t rt_reg = instr_.RtValue();
   2737       int32_t rt = get_register(rt_reg);
   2738       if (rt != 0) {
   2739         SetFPUDoubleResult(fd_reg(), fs);
   2740       }
   2741       break;
   2742     }
   2743     case MOVF: {
   2744       // Same function field for MOVT.D and MOVF.D
   2745       uint32_t ft_cc = (ft_reg() >> 2) & 0x7;
   2746       ft_cc = get_fcsr_condition_bit(ft_cc);
   2747       if (instr_.Bit(16)) {  // Read Tf bit.
   2748         // MOVT.D
   2749         if (test_fcsr_bit(ft_cc)) SetFPUDoubleResult(fd_reg(), fs);
   2750       } else {
   2751         // MOVF.D
   2752         if (!test_fcsr_bit(ft_cc)) SetFPUDoubleResult(fd_reg(), fs);
   2753       }
   2754       break;
   2755     }
   2756     case MIN:
   2757       DCHECK(IsMipsArchVariant(kMips32r6));
   2758       SetFPUDoubleResult(fd_reg(), FPUMin(ft, fs));
   2759       break;
   2760     case MAX:
   2761       DCHECK(IsMipsArchVariant(kMips32r6));
   2762       SetFPUDoubleResult(fd_reg(), FPUMax(ft, fs));
   2763       break;
   2764     case MINA:
   2765       DCHECK(IsMipsArchVariant(kMips32r6));
   2766       SetFPUDoubleResult(fd_reg(), FPUMinA(ft, fs));
   2767       break;
   2768     case MAXA:
   2769       DCHECK(IsMipsArchVariant(kMips32r6));
   2770       SetFPUDoubleResult(fd_reg(), FPUMaxA(ft, fs));
   2771       break;
   2772     case ADD_D:
   2773       SetFPUDoubleResult(
   2774           fd_reg(),
   2775           FPUCanonalizeOperation(
   2776               [](double lhs, double rhs) { return lhs + rhs; }, fs, ft));
   2777       break;
   2778     case SUB_D:
   2779       SetFPUDoubleResult(
   2780           fd_reg(),
   2781           FPUCanonalizeOperation(
   2782               [](double lhs, double rhs) { return lhs - rhs; }, fs, ft));
   2783       break;
   2784     case MADDF_D:
   2785       DCHECK(IsMipsArchVariant(kMips32r6));
   2786       SetFPUDoubleResult(fd_reg(), std::fma(fs, ft, fd));
   2787       break;
   2788     case MSUBF_D:
   2789       DCHECK(IsMipsArchVariant(kMips32r6));
   2790       SetFPUDoubleResult(fd_reg(), std::fma(-fs, ft, fd));
   2791       break;
   2792     case MUL_D:
   2793       SetFPUDoubleResult(
   2794           fd_reg(),
   2795           FPUCanonalizeOperation(
   2796               [](double lhs, double rhs) { return lhs * rhs; }, fs, ft));
   2797       break;
   2798     case DIV_D:
   2799       SetFPUDoubleResult(
   2800           fd_reg(),
   2801           FPUCanonalizeOperation(
   2802               [](double lhs, double rhs) { return lhs / rhs; }, fs, ft));
   2803       break;
   2804     case ABS_D:
   2805       SetFPUDoubleResult(
   2806           fd_reg(),
   2807           FPUCanonalizeOperation([](double fs) { return FPAbs(fs); }, fs));
   2808       break;
   2809     case MOV_D:
   2810       SetFPUDoubleResult(fd_reg(), fs);
   2811       break;
   2812     case NEG_D:
   2813       SetFPUDoubleResult(fd_reg(),
   2814                          FPUCanonalizeOperation([](double src) { return -src; },
   2815                                                 KeepSign::yes, fs));
   2816       break;
   2817     case SQRT_D:
   2818       SetFPUDoubleResult(
   2819           fd_reg(),
   2820           FPUCanonalizeOperation([](double fs) { return std::sqrt(fs); }, fs));
   2821       break;
   2822     case RSQRT_D:
   2823       SetFPUDoubleResult(
   2824           fd_reg(), FPUCanonalizeOperation(
   2825                         [](double fs) { return 1.0 / std::sqrt(fs); }, fs));
   2826       break;
   2827     case RECIP_D:
   2828       SetFPUDoubleResult(fd_reg(), FPUCanonalizeOperation(
   2829                                        [](double fs) { return 1.0 / fs; }, fs));
   2830       break;
   2831     case C_UN_D:
   2832       set_fcsr_bit(fcsr_cc, std::isnan(fs) || std::isnan(ft));
   2833       TraceRegWr(test_fcsr_bit(fcsr_cc));
   2834       break;
   2835     case C_EQ_D:
   2836       set_fcsr_bit(fcsr_cc, (fs == ft));
   2837       TraceRegWr(test_fcsr_bit(fcsr_cc));
   2838       break;
   2839     case C_UEQ_D:
   2840       set_fcsr_bit(fcsr_cc, (fs == ft) || (std::isnan(fs) || std::isnan(ft)));
   2841       TraceRegWr(test_fcsr_bit(fcsr_cc));
   2842       break;
   2843     case C_OLT_D:
   2844       set_fcsr_bit(fcsr_cc, (fs < ft));
   2845       TraceRegWr(test_fcsr_bit(fcsr_cc));
   2846       break;
   2847     case C_ULT_D:
   2848       set_fcsr_bit(fcsr_cc, (fs < ft) || (std::isnan(fs) || std::isnan(ft)));
   2849       TraceRegWr(test_fcsr_bit(fcsr_cc));
   2850       break;
   2851     case C_OLE_D:
   2852       set_fcsr_bit(fcsr_cc, (fs <= ft));
   2853       TraceRegWr(test_fcsr_bit(fcsr_cc));
   2854       break;
   2855     case C_ULE_D:
   2856       set_fcsr_bit(fcsr_cc, (fs <= ft) || (std::isnan(fs) || std::isnan(ft)));
   2857       TraceRegWr(test_fcsr_bit(fcsr_cc));
   2858       break;
   2859     case CVT_W_D: {  // Convert double to word.
   2860       double rounded;
   2861       int32_t result;
   2862       round_according_to_fcsr(fs, rounded, result, fs);
   2863       SetFPUWordResult(fd_reg(), result);
   2864       if (set_fcsr_round_error(fs, rounded)) {
   2865         set_fpu_register_word_invalid_result(fs, rounded);
   2866       }
   2867     } break;
   2868     case ROUND_W_D:  // Round double to word (round half to even).
   2869     {
   2870       double rounded = std::floor(fs + 0.5);
   2871       int32_t result = static_cast<int32_t>(rounded);
   2872       if ((result & 1) != 0 && result - fs == 0.5) {
   2873         // If the number is halfway between two integers,
   2874         // round to the even one.
   2875         result--;
   2876       }
   2877       SetFPUWordResult(fd_reg(), result);
   2878       if (set_fcsr_round_error(fs, rounded)) {
   2879         set_fpu_register_word_invalid_result(fs, rounded);
   2880       }
   2881     } break;
   2882     case TRUNC_W_D:  // Truncate double to word (round towards 0).
   2883     {
   2884       double rounded = trunc(fs);
   2885       int32_t result = static_cast<int32_t>(rounded);
   2886       SetFPUWordResult(fd_reg(), result);
   2887       if (set_fcsr_round_error(fs, rounded)) {
   2888         set_fpu_register_word_invalid_result(fs, rounded);
   2889       }
   2890     } break;
   2891     case FLOOR_W_D:  // Round double to word towards negative infinity.
   2892     {
   2893       double rounded = std::floor(fs);
   2894       int32_t result = static_cast<int32_t>(rounded);
   2895       SetFPUWordResult(fd_reg(), result);
   2896       if (set_fcsr_round_error(fs, rounded)) {
   2897         set_fpu_register_word_invalid_result(fs, rounded);
   2898       }
   2899     } break;
   2900     case CEIL_W_D:  // Round double to word towards positive infinity.
   2901     {
   2902       double rounded = std::ceil(fs);
   2903       int32_t result = static_cast<int32_t>(rounded);
   2904       SetFPUWordResult(fd_reg(), result);
   2905       if (set_fcsr_round_error(fs, rounded)) {
   2906         set_fpu_register_word_invalid_result(fs, rounded);
   2907       }
   2908     } break;
   2909     case CVT_S_D:  // Convert double to float (single).
   2910       SetFPUFloatResult(fd_reg(), static_cast<float>(fs));
   2911       break;
   2912     case CVT_L_D: {  // Mips32r2: Truncate double to 64-bit long-word.
   2913       if (IsFp64Mode()) {
   2914         int64_t result;
   2915         double rounded;
   2916         round64_according_to_fcsr(fs, rounded, result, fs);
   2917         SetFPUResult(fd_reg(), result);
   2918         if (set_fcsr_round64_error(fs, rounded)) {
   2919           set_fpu_register_invalid_result64(fs, rounded);
   2920         }
   2921       } else {
   2922         UNSUPPORTED();
   2923       }
   2924       break;
   2925       break;
   2926     }
   2927     case TRUNC_L_D: {  // Mips32r2 instruction.
   2928       DCHECK(IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6));
   2929       double rounded = trunc(fs);
   2930       i64 = static_cast<int64_t>(rounded);
   2931       if (IsFp64Mode()) {
   2932         SetFPUResult(fd_reg(), i64);
   2933         if (set_fcsr_round64_error(fs, rounded)) {
   2934           set_fpu_register_invalid_result64(fs, rounded);
   2935         }
   2936       } else {
   2937         UNSUPPORTED();
   2938       }
   2939       break;
   2940     }
   2941     case ROUND_L_D: {  // Mips32r2 instruction.
   2942       DCHECK(IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6));
   2943       double rounded = std::floor(fs + 0.5);
   2944       int64_t result = static_cast<int64_t>(rounded);
   2945       if ((result & 1) != 0 && result - fs == 0.5) {
   2946         // If the number is halfway between two integers,
   2947         // round to the even one.
   2948         result--;
   2949       }
   2950       int64_t i64 = static_cast<int64_t>(result);
   2951       if (IsFp64Mode()) {
   2952         SetFPUResult(fd_reg(), i64);
   2953         if (set_fcsr_round64_error(fs, rounded)) {
   2954           set_fpu_register_invalid_result64(fs, rounded);
   2955         }
   2956       } else {
   2957         UNSUPPORTED();
   2958       }
   2959       break;
   2960     }
   2961     case FLOOR_L_D: {  // Mips32r2 instruction.
   2962       DCHECK(IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6));
   2963       double rounded = std::floor(fs);
   2964       int64_t i64 = static_cast<int64_t>(rounded);
   2965       if (IsFp64Mode()) {
   2966         SetFPUResult(fd_reg(), i64);
   2967         if (set_fcsr_round64_error(fs, rounded)) {
   2968           set_fpu_register_invalid_result64(fs, rounded);
   2969         }
   2970       } else {
   2971         UNSUPPORTED();
   2972       }
   2973       break;
   2974     }
   2975     case CEIL_L_D: {  // Mips32r2 instruction.
   2976       DCHECK(IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6));
   2977       double rounded = std::ceil(fs);
   2978       int64_t i64 = static_cast<int64_t>(rounded);
   2979       if (IsFp64Mode()) {
   2980         SetFPUResult(fd_reg(), i64);
   2981         if (set_fcsr_round64_error(fs, rounded)) {
   2982           set_fpu_register_invalid_result64(fs, rounded);
   2983         }
   2984       } else {
   2985         UNSUPPORTED();
   2986       }
   2987       break;
   2988     }
   2989     case CLASS_D: {  // Mips32r6 instruction
   2990       // Convert double input to uint64_t for easier bit manipulation
   2991       uint64_t classed = bit_cast<uint64_t>(fs);
   2992 
   2993       // Extracting sign, exponent and mantissa from the input double
   2994       uint32_t sign = (classed >> 63) & 1;
   2995       uint32_t exponent = (classed >> 52) & 0x00000000000007FF;
   2996       uint64_t mantissa = classed & 0x000FFFFFFFFFFFFF;
   2997       uint64_t result;
   2998       double dResult;
   2999 
   3000       // Setting flags if input double is negative infinity,
   3001       // positive infinity, negative zero or positive zero
   3002       bool negInf = (classed == 0xFFF0000000000000);
   3003       bool posInf = (classed == 0x7FF0000000000000);
   3004       bool negZero = (classed == 0x8000000000000000);
   3005       bool posZero = (classed == 0x0000000000000000);
   3006 
   3007       bool signalingNan;
   3008       bool quietNan;
   3009       bool negSubnorm;
   3010       bool posSubnorm;
   3011       bool negNorm;
   3012       bool posNorm;
   3013 
   3014       // Setting flags if double is NaN
   3015       signalingNan = false;
   3016       quietNan = false;
   3017       if (!negInf && !posInf && exponent == 0x7FF) {
   3018         quietNan = ((mantissa & 0x0008000000000000) != 0) &&
   3019                    ((mantissa & (0x0008000000000000 - 1)) == 0);
   3020         signalingNan = !quietNan;
   3021       }
   3022 
   3023       // Setting flags if double is subnormal number
   3024       posSubnorm = false;
   3025       negSubnorm = false;
   3026       if ((exponent == 0) && (mantissa != 0)) {
   3027         DCHECK(sign == 0 || sign == 1);
   3028         posSubnorm = (sign == 0);
   3029         negSubnorm = (sign == 1);
   3030       }
   3031 
   3032       // Setting flags if double is normal number
   3033       posNorm = false;
   3034       negNorm = false;
   3035       if (!posSubnorm && !negSubnorm && !posInf && !negInf && !signalingNan &&
   3036           !quietNan && !negZero && !posZero) {
   3037         DCHECK(sign == 0 || sign == 1);
   3038         posNorm = (sign == 0);
   3039         negNorm = (sign == 1);
   3040       }
   3041 
   3042       // Calculating result according to description of CLASS.D instruction
   3043       result = (posZero << 9) | (posSubnorm << 8) | (posNorm << 7) |
   3044                (posInf << 6) | (negZero << 5) | (negSubnorm << 4) |
   3045                (negNorm << 3) | (negInf << 2) | (quietNan << 1) | signalingNan;
   3046 
   3047       DCHECK_NE(result, 0);
   3048 
   3049       dResult = bit_cast<double>(result);
   3050       SetFPUDoubleResult(fd_reg(), dResult);
   3051 
   3052       break;
   3053     }
   3054     case C_F_D: {
   3055       set_fcsr_bit(fcsr_cc, false);
   3056       TraceRegWr(test_fcsr_bit(fcsr_cc));
   3057       break;
   3058     }
   3059     default:
   3060       UNREACHABLE();
   3061   }
   3062 }
   3063 
   3064 
   3065 void Simulator::DecodeTypeRegisterWRsType() {
   3066   float fs = get_fpu_register_float(fs_reg());
   3067   float ft = get_fpu_register_float(ft_reg());
   3068   int32_t alu_out = 0x12345678;
   3069   switch (instr_.FunctionFieldRaw()) {
   3070     case CVT_S_W:  // Convert word to float (single).
   3071       alu_out = get_fpu_register_signed_word(fs_reg());
   3072       SetFPUFloatResult(fd_reg(), static_cast<float>(alu_out));
   3073       break;
   3074     case CVT_D_W:  // Convert word to double.
   3075       alu_out = get_fpu_register_signed_word(fs_reg());
   3076       SetFPUDoubleResult(fd_reg(), static_cast<double>(alu_out));
   3077       break;
   3078     case CMP_AF:
   3079       SetFPUWordResult(fd_reg(), 0);
   3080       break;
   3081     case CMP_UN:
   3082       if (std::isnan(fs) || std::isnan(ft)) {
   3083         SetFPUWordResult(fd_reg(), -1);
   3084       } else {
   3085         SetFPUWordResult(fd_reg(), 0);
   3086       }
   3087       break;
   3088     case CMP_EQ:
   3089       if (fs == ft) {
   3090         SetFPUWordResult(fd_reg(), -1);
   3091       } else {
   3092         SetFPUWordResult(fd_reg(), 0);
   3093       }
   3094       break;
   3095     case CMP_UEQ:
   3096       if ((fs == ft) || (std::isnan(fs) || std::isnan(ft))) {
   3097         SetFPUWordResult(fd_reg(), -1);
   3098       } else {
   3099         SetFPUWordResult(fd_reg(), 0);
   3100       }
   3101       break;
   3102     case CMP_LT:
   3103       if (fs < ft) {
   3104         SetFPUWordResult(fd_reg(), -1);
   3105       } else {
   3106         SetFPUWordResult(fd_reg(), 0);
   3107       }
   3108       break;
   3109     case CMP_ULT:
   3110       if ((fs < ft) || (std::isnan(fs) || std::isnan(ft))) {
   3111         SetFPUWordResult(fd_reg(), -1);
   3112       } else {
   3113         SetFPUWordResult(fd_reg(), 0);
   3114       }
   3115       break;
   3116     case CMP_LE:
   3117       if (fs <= ft) {
   3118         SetFPUWordResult(fd_reg(), -1);
   3119       } else {
   3120         SetFPUWordResult(fd_reg(), 0);
   3121       }
   3122       break;
   3123     case CMP_ULE:
   3124       if ((fs <= ft) || (std::isnan(fs) || std::isnan(ft))) {
   3125         SetFPUWordResult(fd_reg(), -1);
   3126       } else {
   3127         SetFPUWordResult(fd_reg(), 0);
   3128       }
   3129       break;
   3130     case CMP_OR:
   3131       if (!std::isnan(fs) && !std::isnan(ft)) {
   3132         SetFPUWordResult(fd_reg(), -1);
   3133       } else {
   3134         SetFPUWordResult(fd_reg(), 0);
   3135       }
   3136       break;
   3137     case CMP_UNE:
   3138       if ((fs != ft) || (std::isnan(fs) || std::isnan(ft))) {
   3139         SetFPUWordResult(fd_reg(), -1);
   3140       } else {
   3141         SetFPUWordResult(fd_reg(), 0);
   3142       }
   3143       break;
   3144     case CMP_NE:
   3145       if (fs != ft) {
   3146         SetFPUWordResult(fd_reg(), -1);
   3147       } else {
   3148         SetFPUWordResult(fd_reg(), 0);
   3149       }
   3150       break;
   3151     default:
   3152       UNREACHABLE();
   3153   }
   3154 }
   3155 
   3156 
   3157 void Simulator::DecodeTypeRegisterSRsType() {
   3158   float fs, ft, fd;
   3159   fs = get_fpu_register_float(fs_reg());
   3160   ft = get_fpu_register_float(ft_reg());
   3161   fd = get_fpu_register_float(fd_reg());
   3162   int32_t ft_int = bit_cast<int32_t>(ft);
   3163   int32_t fd_int = bit_cast<int32_t>(fd);
   3164   uint32_t cc, fcsr_cc;
   3165   cc = instr_.FCccValue();
   3166   fcsr_cc = get_fcsr_condition_bit(cc);
   3167   switch (instr_.FunctionFieldRaw()) {
   3168     case RINT: {
   3169       DCHECK(IsMipsArchVariant(kMips32r6));
   3170       float result, temp_result;
   3171       double temp;
   3172       float upper = std::ceil(fs);
   3173       float lower = std::floor(fs);
   3174       switch (get_fcsr_rounding_mode()) {
   3175         case kRoundToNearest:
   3176           if (upper - fs < fs - lower) {
   3177             result = upper;
   3178           } else if (upper - fs > fs - lower) {
   3179             result = lower;
   3180           } else {
   3181             temp_result = upper / 2;
   3182             float reminder = modf(temp_result, &temp);
   3183             if (reminder == 0) {
   3184               result = upper;
   3185             } else {
   3186               result = lower;
   3187             }
   3188           }
   3189           break;
   3190         case kRoundToZero:
   3191           result = (fs > 0 ? lower : upper);
   3192           break;
   3193         case kRoundToPlusInf:
   3194           result = upper;
   3195           break;
   3196         case kRoundToMinusInf:
   3197           result = lower;
   3198           break;
   3199       }
   3200       SetFPUFloatResult(fd_reg(), result);
   3201       if (result != fs) {
   3202         set_fcsr_bit(kFCSRInexactFlagBit, true);
   3203       }
   3204       break;
   3205     }
   3206     case ADD_S:
   3207       SetFPUFloatResult(
   3208           fd_reg(),
   3209           FPUCanonalizeOperation([](float lhs, float rhs) { return lhs + rhs; },
   3210                                  fs, ft));
   3211       break;
   3212     case SUB_S:
   3213       SetFPUFloatResult(
   3214           fd_reg(),
   3215           FPUCanonalizeOperation([](float lhs, float rhs) { return lhs - rhs; },
   3216                                  fs, ft));
   3217       break;
   3218     case MADDF_S:
   3219       DCHECK(IsMipsArchVariant(kMips32r6));
   3220       SetFPUFloatResult(fd_reg(), std::fma(fs, ft, fd));
   3221       break;
   3222     case MSUBF_S:
   3223       DCHECK(IsMipsArchVariant(kMips32r6));
   3224       SetFPUFloatResult(fd_reg(), std::fma(-fs, ft, fd));
   3225       break;
   3226     case MUL_S:
   3227       SetFPUFloatResult(
   3228           fd_reg(),
   3229           FPUCanonalizeOperation([](float lhs, float rhs) { return lhs * rhs; },
   3230                                  fs, ft));
   3231       break;
   3232     case DIV_S:
   3233       SetFPUFloatResult(
   3234           fd_reg(),
   3235           FPUCanonalizeOperation([](float lhs, float rhs) { return lhs / rhs; },
   3236                                  fs, ft));
   3237       break;
   3238     case ABS_S:
   3239       SetFPUFloatResult(fd_reg(), FPUCanonalizeOperation(
   3240                                       [](float fs) { return FPAbs(fs); }, fs));
   3241       break;
   3242     case MOV_S:
   3243       SetFPUFloatResult(fd_reg(), fs);
   3244       break;
   3245     case NEG_S:
   3246       SetFPUFloatResult(fd_reg(),
   3247                         FPUCanonalizeOperation([](float src) { return -src; },
   3248                                                KeepSign::yes, fs));
   3249       break;
   3250     case SQRT_S:
   3251       SetFPUFloatResult(
   3252           fd_reg(),
   3253           FPUCanonalizeOperation([](float src) { return std::sqrt(src); }, fs));
   3254       break;
   3255     case RSQRT_S:
   3256       SetFPUFloatResult(
   3257           fd_reg(), FPUCanonalizeOperation(
   3258                         [](float src) { return 1.0 / std::sqrt(src); }, fs));
   3259       break;
   3260     case RECIP_S:
   3261       SetFPUFloatResult(fd_reg(), FPUCanonalizeOperation(
   3262                                       [](float src) { return 1.0 / src; }, fs));
   3263       break;
   3264     case C_F_D:
   3265       set_fcsr_bit(fcsr_cc, false);
   3266       TraceRegWr(test_fcsr_bit(fcsr_cc));
   3267       break;
   3268     case C_UN_D:
   3269       set_fcsr_bit(fcsr_cc, std::isnan(fs) || std::isnan(ft));
   3270       TraceRegWr(test_fcsr_bit(fcsr_cc));
   3271       break;
   3272     case C_EQ_D:
   3273       set_fcsr_bit(fcsr_cc, (fs == ft));
   3274       TraceRegWr(test_fcsr_bit(fcsr_cc));
   3275       break;
   3276     case C_UEQ_D:
   3277       set_fcsr_bit(fcsr_cc, (fs == ft) || (std::isnan(fs) || std::isnan(ft)));
   3278       TraceRegWr(test_fcsr_bit(fcsr_cc));
   3279       break;
   3280     case C_OLT_D:
   3281       set_fcsr_bit(fcsr_cc, (fs < ft));
   3282       TraceRegWr(test_fcsr_bit(fcsr_cc));
   3283       break;
   3284     case C_ULT_D:
   3285       set_fcsr_bit(fcsr_cc, (fs < ft) || (std::isnan(fs) || std::isnan(ft)));
   3286       TraceRegWr(test_fcsr_bit(fcsr_cc));
   3287       break;
   3288     case C_OLE_D:
   3289       set_fcsr_bit(fcsr_cc, (fs <= ft));
   3290       TraceRegWr(test_fcsr_bit(fcsr_cc));
   3291       break;
   3292     case C_ULE_D:
   3293       set_fcsr_bit(fcsr_cc, (fs <= ft) || (std::isnan(fs) || std::isnan(ft)));
   3294       TraceRegWr(test_fcsr_bit(fcsr_cc));
   3295       break;
   3296     case CVT_D_S:
   3297       SetFPUDoubleResult(fd_reg(), static_cast<double>(fs));
   3298       break;
   3299     case SEL:
   3300       DCHECK(IsMipsArchVariant(kMips32r6));
   3301       SetFPUFloatResult(fd_reg(), (fd_int & 0x1) == 0 ? fs : ft);
   3302       break;
   3303     case CLASS_S: {  // Mips32r6 instruction
   3304       // Convert float input to uint32_t for easier bit manipulation
   3305       float fs = get_fpu_register_float(fs_reg());
   3306       uint32_t classed = bit_cast<uint32_t>(fs);
   3307 
   3308       // Extracting sign, exponent and mantissa from the input float
   3309       uint32_t sign = (classed >> 31) & 1;
   3310       uint32_t exponent = (classed >> 23) & 0x000000FF;
   3311       uint32_t mantissa = classed & 0x007FFFFF;
   3312       uint32_t result;
   3313       float fResult;
   3314 
   3315       // Setting flags if input float is negative infinity,
   3316       // positive infinity, negative zero or positive zero
   3317       bool negInf = (classed == 0xFF800000);
   3318       bool posInf = (classed == 0x7F800000);
   3319       bool negZero = (classed == 0x80000000);
   3320       bool posZero = (classed == 0x00000000);
   3321 
   3322       bool signalingNan;
   3323       bool quietNan;
   3324       bool negSubnorm;
   3325       bool posSubnorm;
   3326       bool negNorm;
   3327       bool posNorm;
   3328 
   3329       // Setting flags if float is NaN
   3330       signalingNan = false;
   3331       quietNan = false;
   3332       if (!negInf && !posInf && (exponent == 0xFF)) {
   3333         quietNan = ((mantissa & 0x00200000) == 0) &&
   3334                    ((mantissa & (0x00200000 - 1)) == 0);
   3335         signalingNan = !quietNan;
   3336       }
   3337 
   3338       // Setting flags if float is subnormal number
   3339       posSubnorm = false;
   3340       negSubnorm = false;
   3341       if ((exponent == 0) && (mantissa != 0)) {
   3342         DCHECK(sign == 0 || sign == 1);
   3343         posSubnorm = (sign == 0);
   3344         negSubnorm = (sign == 1);
   3345       }
   3346 
   3347       // Setting flags if float is normal number
   3348       posNorm = false;
   3349       negNorm = false;
   3350       if (!posSubnorm && !negSubnorm && !posInf && !negInf && !signalingNan &&
   3351           !quietNan && !negZero && !posZero) {
   3352         DCHECK(sign == 0 || sign == 1);
   3353         posNorm = (sign == 0);
   3354         negNorm = (sign == 1);
   3355       }
   3356 
   3357       // Calculating result according to description of CLASS.S instruction
   3358       result = (posZero << 9) | (posSubnorm << 8) | (posNorm << 7) |
   3359                (posInf << 6) | (negZero << 5) | (negSubnorm << 4) |
   3360                (negNorm << 3) | (negInf << 2) | (quietNan << 1) | signalingNan;
   3361 
   3362       DCHECK_NE(result, 0);
   3363 
   3364       fResult = bit_cast<float>(result);
   3365       SetFPUFloatResult(fd_reg(), fResult);
   3366 
   3367       break;
   3368     }
   3369     case SELEQZ_C:
   3370       DCHECK(IsMipsArchVariant(kMips32r6));
   3371       SetFPUFloatResult(
   3372           fd_reg(),
   3373           (ft_int & 0x1) == 0 ? get_fpu_register_float(fs_reg()) : 0.0);
   3374       break;
   3375     case SELNEZ_C:
   3376       DCHECK(IsMipsArchVariant(kMips32r6));
   3377       SetFPUFloatResult(
   3378           fd_reg(),
   3379           (ft_int & 0x1) != 0 ? get_fpu_register_float(fs_reg()) : 0.0);
   3380       break;
   3381     case MOVZ_C: {
   3382       DCHECK(IsMipsArchVariant(kMips32r2));
   3383       if (rt() == 0) {
   3384         SetFPUFloatResult(fd_reg(), fs);
   3385       }
   3386       break;
   3387     }
   3388     case MOVN_C: {
   3389       DCHECK(IsMipsArchVariant(kMips32r2));
   3390       if (rt() != 0) {
   3391         SetFPUFloatResult(fd_reg(), fs);
   3392       }
   3393       break;
   3394     }
   3395     case MOVF: {
   3396       // Same function field for MOVT.D and MOVF.D
   3397       uint32_t ft_cc = (ft_reg() >> 2) & 0x7;
   3398       ft_cc = get_fcsr_condition_bit(ft_cc);
   3399 
   3400       if (instr_.Bit(16)) {  // Read Tf bit.
   3401         // MOVT.D
   3402         if (test_fcsr_bit(ft_cc)) SetFPUFloatResult(fd_reg(), fs);
   3403       } else {
   3404         // MOVF.D
   3405         if (!test_fcsr_bit(ft_cc)) SetFPUFloatResult(fd_reg(), fs);
   3406       }
   3407       break;
   3408     }
   3409     case TRUNC_W_S: {  // Truncate single to word (round towards 0).
   3410       float rounded = trunc(fs);
   3411       int32_t result = static_cast<int32_t>(rounded);
   3412       SetFPUWordResult(fd_reg(), result);
   3413       if (set_fcsr_round_error(fs, rounded)) {
   3414         set_fpu_register_word_invalid_result(fs, rounded);
   3415       }
   3416     } break;
   3417     case TRUNC_L_S: {  // Mips32r2 instruction.
   3418       DCHECK(IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6));
   3419       float rounded = trunc(fs);
   3420       int64_t i64 = static_cast<int64_t>(rounded);
   3421       if (IsFp64Mode()) {
   3422         SetFPUResult(fd_reg(), i64);
   3423         if (set_fcsr_round64_error(fs, rounded)) {
   3424           set_fpu_register_invalid_result64(fs, rounded);
   3425         }
   3426       } else {
   3427         UNSUPPORTED();
   3428       }
   3429       break;
   3430     }
   3431     case FLOOR_W_S:  // Round double to word towards negative infinity.
   3432     {
   3433       float rounded = std::floor(fs);
   3434       int32_t result = static_cast<int32_t>(rounded);
   3435       SetFPUWordResult(fd_reg(), result);
   3436       if (set_fcsr_round_error(fs, rounded)) {
   3437         set_fpu_register_word_invalid_result(fs, rounded);
   3438       }
   3439     } break;
   3440     case FLOOR_L_S: {  // Mips32r2 instruction.
   3441       DCHECK(IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6));
   3442       float rounded = std::floor(fs);
   3443       int64_t i64 = static_cast<int64_t>(rounded);
   3444       if (IsFp64Mode()) {
   3445         SetFPUResult(fd_reg(), i64);
   3446         if (set_fcsr_round64_error(fs, rounded)) {
   3447           set_fpu_register_invalid_result64(fs, rounded);
   3448         }
   3449       } else {
   3450         UNSUPPORTED();
   3451       }
   3452       break;
   3453     }
   3454     case ROUND_W_S: {
   3455       float rounded = std::floor(fs + 0.5);
   3456       int32_t result = static_cast<int32_t>(rounded);
   3457       if ((result & 1) != 0 && result - fs == 0.5) {
   3458         // If the number is halfway between two integers,
   3459         // round to the even one.
   3460         result--;
   3461       }
   3462       SetFPUWordResult(fd_reg(), result);
   3463       if (set_fcsr_round_error(fs, rounded)) {
   3464         set_fpu_register_word_invalid_result(fs, rounded);
   3465       }
   3466       break;
   3467     }
   3468     case ROUND_L_S: {  // Mips32r2 instruction.
   3469       DCHECK(IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6));
   3470       float rounded = std::floor(fs + 0.5);
   3471       int64_t result = static_cast<int64_t>(rounded);
   3472       if ((result & 1) != 0 && result - fs == 0.5) {
   3473         // If the number is halfway between two integers,
   3474         // round to the even one.
   3475         result--;
   3476       }
   3477       int64_t i64 = static_cast<int64_t>(result);
   3478       if (IsFp64Mode()) {
   3479         SetFPUResult(fd_reg(), i64);
   3480         if (set_fcsr_round64_error(fs, rounded)) {
   3481           set_fpu_register_invalid_result64(fs, rounded);
   3482         }
   3483       } else {
   3484         UNSUPPORTED();
   3485       }
   3486       break;
   3487     }
   3488     case CEIL_W_S:  // Round double to word towards positive infinity.
   3489     {
   3490       float rounded = std::ceil(fs);
   3491       int32_t result = static_cast<int32_t>(rounded);
   3492       SetFPUWordResult(fd_reg(), result);
   3493       if (set_fcsr_round_error(fs, rounded)) {
   3494         set_fpu_register_word_invalid_result(fs, rounded);
   3495       }
   3496     } break;
   3497     case CEIL_L_S: {  // Mips32r2 instruction.
   3498       DCHECK(IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6));
   3499       float rounded = std::ceil(fs);
   3500       int64_t i64 = static_cast<int64_t>(rounded);
   3501       if (IsFp64Mode()) {
   3502         SetFPUResult(fd_reg(), i64);
   3503         if (set_fcsr_round64_error(fs, rounded)) {
   3504           set_fpu_register_invalid_result64(fs, rounded);
   3505         }
   3506       } else {
   3507         UNSUPPORTED();
   3508       }
   3509       break;
   3510     }
   3511     case MIN:
   3512       DCHECK(IsMipsArchVariant(kMips32r6));
   3513       SetFPUFloatResult(fd_reg(), FPUMin(ft, fs));
   3514       break;
   3515     case MAX:
   3516       DCHECK(IsMipsArchVariant(kMips32r6));
   3517       SetFPUFloatResult(fd_reg(), FPUMax(ft, fs));
   3518       break;
   3519     case MINA:
   3520       DCHECK(IsMipsArchVariant(kMips32r6));
   3521       SetFPUFloatResult(fd_reg(), FPUMinA(ft, fs));
   3522       break;
   3523     case MAXA:
   3524       DCHECK(IsMipsArchVariant(kMips32r6));
   3525       SetFPUFloatResult(fd_reg(), FPUMaxA(ft, fs));
   3526       break;
   3527     case CVT_L_S: {
   3528       if (IsFp64Mode()) {
   3529         int64_t result;
   3530         float rounded;
   3531         round64_according_to_fcsr(fs, rounded, result, fs);
   3532         SetFPUResult(fd_reg(), result);
   3533         if (set_fcsr_round64_error(fs, rounded)) {
   3534           set_fpu_register_invalid_result64(fs, rounded);
   3535         }
   3536       } else {
   3537         UNSUPPORTED();
   3538       }
   3539       break;
   3540     }
   3541     case CVT_W_S: {
   3542       float rounded;
   3543       int32_t result;
   3544       round_according_to_fcsr(fs, rounded, result, fs);
   3545       SetFPUWordResult(fd_reg(), result);
   3546       if (set_fcsr_round_error(fs, rounded)) {
   3547         set_fpu_register_word_invalid_result(fs, rounded);
   3548       }
   3549       break;
   3550     }
   3551     default:
   3552       // CVT_W_S CVT_L_S  ROUND_W_S ROUND_L_S FLOOR_W_S FLOOR_L_S
   3553       // CEIL_W_S CEIL_L_S CVT_PS_S are unimplemented.
   3554       UNREACHABLE();
   3555   }
   3556 }
   3557 
   3558 
   3559 void Simulator::DecodeTypeRegisterLRsType() {
   3560   double fs = get_fpu_register_double(fs_reg());
   3561   double ft = get_fpu_register_double(ft_reg());
   3562   switch (instr_.FunctionFieldRaw()) {
   3563     case CVT_D_L:  // Mips32r2 instruction.
   3564       // Watch the signs here, we want 2 32-bit vals
   3565       // to make a sign-64.
   3566       int64_t i64;
   3567       if (IsFp64Mode()) {
   3568         i64 = get_fpu_register(fs_reg());
   3569       } else {
   3570         i64 = static_cast<uint32_t>(get_fpu_register_word(fs_reg()));
   3571         i64 |= static_cast<int64_t>(get_fpu_register_word(fs_reg() + 1)) << 32;
   3572       }
   3573       SetFPUDoubleResult(fd_reg(), static_cast<double>(i64));
   3574       break;
   3575     case CVT_S_L:
   3576       if (IsFp64Mode()) {
   3577         i64 = get_fpu_register(fs_reg());
   3578       } else {
   3579         i64 = static_cast<uint32_t>(get_fpu_register_word(fs_reg()));
   3580         i64 |= static_cast<int64_t>(get_fpu_register_word(fs_reg() + 1)) << 32;
   3581       }
   3582       SetFPUFloatResult(fd_reg(), static_cast<float>(i64));
   3583       break;
   3584     case CMP_AF:  // Mips64r6 CMP.D instructions.
   3585       SetFPUResult(fd_reg(), 0);
   3586       break;
   3587     case CMP_UN:
   3588       if (std::isnan(fs) || std::isnan(ft)) {
   3589         SetFPUResult(fd_reg(), -1);
   3590       } else {
   3591         SetFPUResult(fd_reg(), 0);
   3592       }
   3593       break;
   3594     case CMP_EQ:
   3595       if (fs == ft) {
   3596         SetFPUResult(fd_reg(), -1);
   3597       } else {
   3598         SetFPUResult(fd_reg(), 0);
   3599       }
   3600       break;
   3601     case CMP_UEQ:
   3602       if ((fs == ft) || (std::isnan(fs) || std::isnan(ft))) {
   3603         SetFPUResult(fd_reg(), -1);
   3604       } else {
   3605         SetFPUResult(fd_reg(), 0);
   3606       }
   3607       break;
   3608     case CMP_LT:
   3609       if (fs < ft) {
   3610         SetFPUResult(fd_reg(), -1);
   3611       } else {
   3612         SetFPUResult(fd_reg(), 0);
   3613       }
   3614       break;
   3615     case CMP_ULT:
   3616       if ((fs < ft) || (std::isnan(fs) || std::isnan(ft))) {
   3617         SetFPUResult(fd_reg(), -1);
   3618       } else {
   3619         SetFPUResult(fd_reg(), 0);
   3620       }
   3621       break;
   3622     case CMP_LE:
   3623       if (fs <= ft) {
   3624         SetFPUResult(fd_reg(), -1);
   3625       } else {
   3626         SetFPUResult(fd_reg(), 0);
   3627       }
   3628       break;
   3629     case CMP_ULE:
   3630       if ((fs <= ft) || (std::isnan(fs) || std::isnan(ft))) {
   3631         SetFPUResult(fd_reg(), -1);
   3632       } else {
   3633         SetFPUResult(fd_reg(), 0);
   3634       }
   3635       break;
   3636     case CMP_OR:
   3637       if (!std::isnan(fs) && !std::isnan(ft)) {
   3638         SetFPUResult(fd_reg(), -1);
   3639       } else {
   3640         SetFPUResult(fd_reg(), 0);
   3641       }
   3642       break;
   3643     case CMP_UNE:
   3644       if ((fs != ft) || (std::isnan(fs) || std::isnan(ft))) {
   3645         SetFPUResult(fd_reg(), -1);
   3646       } else {
   3647         SetFPUResult(fd_reg(), 0);
   3648       }
   3649       break;
   3650     case CMP_NE:
   3651       if (fs != ft && (!std::isnan(fs) && !std::isnan(ft))) {
   3652         SetFPUResult(fd_reg(), -1);
   3653       } else {
   3654         SetFPUResult(fd_reg(), 0);
   3655       }
   3656       break;
   3657     default:
   3658       UNREACHABLE();
   3659   }
   3660 }
   3661 
   3662 
   3663 void Simulator::DecodeTypeRegisterCOP1() {
   3664   switch (instr_.RsFieldRaw()) {
   3665     case CFC1:
   3666       // At the moment only FCSR is supported.
   3667       DCHECK_EQ(fs_reg(), kFCSRRegister);
   3668       SetResult(rt_reg(), FCSR_);
   3669       break;
   3670     case MFC1:
   3671       SetResult(rt_reg(), get_fpu_register_word(fs_reg()));
   3672       break;
   3673     case MFHC1:
   3674       if (IsFp64Mode()) {
   3675         SetResult(rt_reg(), get_fpu_register_hi_word(fs_reg()));
   3676       } else {
   3677         SetResult(rt_reg(), get_fpu_register_word(fs_reg() + 1));
   3678       }
   3679       break;
   3680     case CTC1: {
   3681       // At the moment only FCSR is supported.
   3682       DCHECK_EQ(fs_reg(), kFCSRRegister);
   3683       int32_t reg = registers_[rt_reg()];
   3684       if (IsMipsArchVariant(kMips32r6)) {
   3685         FCSR_ = reg | kFCSRNaN2008FlagMask;
   3686       } else {
   3687         DCHECK(IsMipsArchVariant(kMips32r1) || IsMipsArchVariant(kMips32r2));
   3688         FCSR_ = reg & ~kFCSRNaN2008FlagMask;
   3689       }
   3690       TraceRegWr(static_cast<int32_t>(FCSR_));
   3691       break;
   3692     }
   3693     case MTC1:
   3694       // Hardware writes upper 32-bits to zero on mtc1.
   3695       set_fpu_register_hi_word(fs_reg(), 0);
   3696       set_fpu_register_word(fs_reg(), registers_[rt_reg()]);
   3697       TraceRegWr(get_fpu_register_word(fs_reg()), FLOAT);
   3698       break;
   3699     case MTHC1:
   3700       if (IsFp64Mode()) {
   3701         set_fpu_register_hi_word(fs_reg(), registers_[rt_reg()]);
   3702         TraceRegWr(get_fpu_register(fs_reg()), DOUBLE);
   3703       } else {
   3704         set_fpu_register_word(fs_reg() + 1, registers_[rt_reg()]);
   3705         if (fs_reg() % 2) {
   3706           TraceRegWr(get_fpu_register_word(fs_reg() + 1), FLOAT);
   3707         } else {
   3708           TraceRegWr(get_fpu_register(fs_reg()), DOUBLE);
   3709         }
   3710       }
   3711       break;
   3712     case S: {
   3713       DecodeTypeRegisterSRsType();
   3714       break;
   3715     }
   3716     case D:
   3717       DecodeTypeRegisterDRsType();
   3718       break;
   3719     case W:
   3720       DecodeTypeRegisterWRsType();
   3721       break;
   3722     case L:
   3723       DecodeTypeRegisterLRsType();
   3724       break;
   3725     case PS:
   3726       // Not implemented.
   3727       UNREACHABLE();
   3728     default:
   3729       UNREACHABLE();
   3730   }
   3731 }
   3732 
   3733 
   3734 void Simulator::DecodeTypeRegisterCOP1X() {
   3735   switch (instr_.FunctionFieldRaw()) {
   3736     case MADD_S: {
   3737       DCHECK(IsMipsArchVariant(kMips32r2));
   3738       float fr, ft, fs;
   3739       fr = get_fpu_register_float(fr_reg());
   3740       fs = get_fpu_register_float(fs_reg());
   3741       ft = get_fpu_register_float(ft_reg());
   3742       SetFPUFloatResult(fd_reg(), fs * ft + fr);
   3743       break;
   3744     }
   3745     case MSUB_S: {
   3746       DCHECK(IsMipsArchVariant(kMips32r2));
   3747       float fr, ft, fs;
   3748       fr = get_fpu_register_float(fr_reg());
   3749       fs = get_fpu_register_float(fs_reg());
   3750       ft = get_fpu_register_float(ft_reg());
   3751       SetFPUFloatResult(fd_reg(), fs * ft - fr);
   3752       break;
   3753     }
   3754     case MADD_D: {
   3755       DCHECK(IsMipsArchVariant(kMips32r2));
   3756       double fr, ft, fs;
   3757       fr = get_fpu_register_double(fr_reg());
   3758       fs = get_fpu_register_double(fs_reg());
   3759       ft = get_fpu_register_double(ft_reg());
   3760       SetFPUDoubleResult(fd_reg(), fs * ft + fr);
   3761       break;
   3762     }
   3763     case MSUB_D: {
   3764       DCHECK(IsMipsArchVariant(kMips32r2));
   3765       double fr, ft, fs;
   3766       fr = get_fpu_register_double(fr_reg());
   3767       fs = get_fpu_register_double(fs_reg());
   3768       ft = get_fpu_register_double(ft_reg());
   3769       SetFPUDoubleResult(fd_reg(), fs * ft - fr);
   3770       break;
   3771     }
   3772     default:
   3773       UNREACHABLE();
   3774   }
   3775 }
   3776 
   3777 
   3778 void Simulator::DecodeTypeRegisterSPECIAL() {
   3779   int64_t alu_out = 0x12345678;
   3780   int64_t i64hilo = 0;
   3781   uint64_t u64hilo = 0;
   3782   bool do_interrupt = false;
   3783 
   3784   switch (instr_.FunctionFieldRaw()) {
   3785     case SELEQZ_S:
   3786       DCHECK(IsMipsArchVariant(kMips32r6));
   3787       SetResult(rd_reg(), rt() == 0 ? rs() : 0);
   3788       break;
   3789     case SELNEZ_S:
   3790       DCHECK(IsMipsArchVariant(kMips32r6));
   3791       SetResult(rd_reg(), rt() != 0 ? rs() : 0);
   3792       break;
   3793     case JR: {
   3794       int32_t next_pc = rs();
   3795       int32_t current_pc = get_pc();
   3796       Instruction* branch_delay_instr =
   3797           reinterpret_cast<Instruction*>(current_pc + kInstrSize);
   3798       BranchDelayInstructionDecode(branch_delay_instr);
   3799       set_pc(next_pc);
   3800       pc_modified_ = true;
   3801       break;
   3802     }
   3803     case JALR: {
   3804       int32_t next_pc = rs();
   3805       int32_t return_addr_reg = rd_reg();
   3806       int32_t current_pc = get_pc();
   3807       Instruction* branch_delay_instr =
   3808           reinterpret_cast<Instruction*>(current_pc + kInstrSize);
   3809       BranchDelayInstructionDecode(branch_delay_instr);
   3810       set_register(return_addr_reg, current_pc + 2 * kInstrSize);
   3811       set_pc(next_pc);
   3812       pc_modified_ = true;
   3813       break;
   3814     }
   3815     case SLL:
   3816       alu_out = rt() << sa();
   3817       SetResult(rd_reg(), static_cast<int32_t>(alu_out));
   3818       break;
   3819     case SRL:
   3820       if (rs_reg() == 0) {
   3821         // Regular logical right shift of a word by a fixed number of
   3822         // bits instruction. RS field is always equal to 0.
   3823         alu_out = rt_u() >> sa();
   3824       } else {
   3825         // Logical right-rotate of a word by a fixed number of bits. This
   3826         // is special case of SRL instruction, added in MIPS32 Release 2.
   3827         // RS field is equal to 00001.
   3828         alu_out = base::bits::RotateRight32(rt_u(), sa());
   3829       }
   3830       SetResult(rd_reg(), static_cast<int32_t>(alu_out));
   3831       break;
   3832     case SRA:
   3833       alu_out = rt() >> sa();
   3834       SetResult(rd_reg(), static_cast<int32_t>(alu_out));
   3835       break;
   3836     case SLLV:
   3837       alu_out = rt() << rs();
   3838       SetResult(rd_reg(), static_cast<int32_t>(alu_out));
   3839       break;
   3840     case SRLV:
   3841       if (sa() == 0) {
   3842         // Regular logical right-shift of a word by a variable number of
   3843         // bits instruction. SA field is always equal to 0.
   3844         alu_out = rt_u() >> rs();
   3845       } else {
   3846         // Logical right-rotate of a word by a variable number of bits.
   3847         // This is special case od SRLV instruction, added in MIPS32
   3848         // Release 2. SA field is equal to 00001.
   3849         alu_out = base::bits::RotateRight32(rt_u(), rs_u());
   3850       }
   3851       SetResult(rd_reg(), static_cast<int32_t>(alu_out));
   3852       break;
   3853     case SRAV:
   3854       SetResult(rd_reg(), rt() >> rs());
   3855       break;
   3856     case LSA: {
   3857       DCHECK(IsMipsArchVariant(kMips32r6));
   3858       int8_t sa = lsa_sa() + 1;
   3859       int32_t _rt = rt();
   3860       int32_t _rs = rs();
   3861       int32_t res = _rs << sa;
   3862       res += _rt;
   3863       DCHECK_EQ(res, (rs() << (lsa_sa() + 1)) + rt());
   3864       SetResult(rd_reg(), (rs() << (lsa_sa() + 1)) + rt());
   3865       break;
   3866     }
   3867     case MFHI:  // MFHI == CLZ on R6.
   3868       if (!IsMipsArchVariant(kMips32r6)) {
   3869         DCHECK_EQ(sa(), 0);
   3870         alu_out = get_register(HI);
   3871       } else {
   3872         // MIPS spec: If no bits were set in GPR rs, the result written to
   3873         // GPR rd is 32.
   3874         DCHECK_EQ(sa(), 1);
   3875         alu_out = base::bits::CountLeadingZeros32(rs_u());
   3876       }
   3877       SetResult(rd_reg(), static_cast<int32_t>(alu_out));
   3878       break;
   3879     case MFLO:
   3880       alu_out = get_register(LO);
   3881       SetResult(rd_reg(), static_cast<int32_t>(alu_out));
   3882       break;
   3883     // Instructions using HI and LO registers.
   3884     case MULT:
   3885       i64hilo = static_cast<int64_t>(rs()) * static_cast<int64_t>(rt());
   3886       if (!IsMipsArchVariant(kMips32r6)) {
   3887         set_register(LO, static_cast<int32_t>(i64hilo & 0xFFFFFFFF));
   3888         set_register(HI, static_cast<int32_t>(i64hilo >> 32));
   3889       } else {
   3890         switch (sa()) {
   3891           case MUL_OP:
   3892             SetResult(rd_reg(), static_cast<int32_t>(i64hilo & 0xFFFFFFFF));
   3893             break;
   3894           case MUH_OP:
   3895             SetResult(rd_reg(), static_cast<int32_t>(i64hilo >> 32));
   3896             break;
   3897           default:
   3898             UNIMPLEMENTED_MIPS();
   3899             break;
   3900         }
   3901       }
   3902       break;
   3903     case MULTU:
   3904       u64hilo = static_cast<uint64_t>(rs_u()) * static_cast<uint64_t>(rt_u());
   3905       if (!IsMipsArchVariant(kMips32r6)) {
   3906         set_register(LO, static_cast<int32_t>(u64hilo & 0xFFFFFFFF));
   3907         set_register(HI, static_cast<int32_t>(u64hilo >> 32));
   3908       } else {
   3909         switch (sa()) {
   3910           case MUL_OP:
   3911             SetResult(rd_reg(), static_cast<int32_t>(u64hilo & 0xFFFFFFFF));
   3912             break;
   3913           case MUH_OP:
   3914             SetResult(rd_reg(), static_cast<int32_t>(u64hilo >> 32));
   3915             break;
   3916           default:
   3917             UNIMPLEMENTED_MIPS();
   3918             break;
   3919         }
   3920       }
   3921       break;
   3922     case DIV:
   3923       if (IsMipsArchVariant(kMips32r6)) {
   3924         switch (sa()) {
   3925           case DIV_OP:
   3926             if (rs() == INT_MIN && rt() == -1) {
   3927               SetResult(rd_reg(), INT_MIN);
   3928             } else if (rt() != 0) {
   3929               SetResult(rd_reg(), rs() / rt());
   3930             }
   3931             break;
   3932           case MOD_OP:
   3933             if (rs() == INT_MIN && rt() == -1) {
   3934               SetResult(rd_reg(), 0);
   3935             } else if (rt() != 0) {
   3936               SetResult(rd_reg(), rs() % rt());
   3937             }
   3938             break;
   3939           default:
   3940             UNIMPLEMENTED_MIPS();
   3941             break;
   3942         }
   3943       } else {
   3944         // Divide by zero and overflow was not checked in the
   3945         // configuration step - div and divu do not raise exceptions. On
   3946         // division by 0 the result will be UNPREDICTABLE. On overflow
   3947         // (INT_MIN/-1), return INT_MIN which is what the hardware does.
   3948         if (rs() == INT_MIN && rt() == -1) {
   3949           set_register(LO, INT_MIN);
   3950           set_register(HI, 0);
   3951         } else if (rt() != 0) {
   3952           set_register(LO, rs() / rt());
   3953           set_register(HI, rs() % rt());
   3954         }
   3955       }
   3956       break;
   3957     case DIVU:
   3958       if (IsMipsArchVariant(kMips32r6)) {
   3959         switch (sa()) {
   3960           case DIV_OP:
   3961             if (rt_u() != 0) {
   3962               SetResult(rd_reg(), rs_u() / rt_u());
   3963             }
   3964             break;
   3965           case MOD_OP:
   3966             if (rt_u() != 0) {
   3967               SetResult(rd_reg(), rs_u() % rt_u());
   3968             }
   3969             break;
   3970           default:
   3971             UNIMPLEMENTED_MIPS();
   3972             break;
   3973         }
   3974       } else {
   3975         if (rt_u() != 0) {
   3976           set_register(LO, rs_u() / rt_u());
   3977           set_register(HI, rs_u() % rt_u());
   3978         }
   3979       }
   3980       break;
   3981     case ADD:
   3982       if (HaveSameSign(rs(), rt())) {
   3983         if (rs() > 0) {
   3984           if (rs() <= (Registers::kMaxValue - rt())) {
   3985             SignalException(kIntegerOverflow);
   3986           }
   3987         } else if (rs() < 0) {
   3988           if (rs() >= (Registers::kMinValue - rt())) {
   3989             SignalException(kIntegerUnderflow);
   3990           }
   3991         }
   3992       }
   3993       SetResult(rd_reg(), rs() + rt());
   3994       break;
   3995     case ADDU:
   3996       SetResult(rd_reg(), rs() + rt());
   3997       break;
   3998     case SUB:
   3999       if (!HaveSameSign(rs(), rt())) {
   4000         if (rs() > 0) {
   4001           if (rs() <= (Registers::kMaxValue + rt())) {
   4002             SignalException(kIntegerOverflow);
   4003           }
   4004         } else if (rs() < 0) {
   4005           if (rs() >= (Registers::kMinValue + rt())) {
   4006             SignalException(kIntegerUnderflow);
   4007           }
   4008         }
   4009       }
   4010       SetResult(rd_reg(), rs() - rt());
   4011       break;
   4012     case SUBU:
   4013       SetResult(rd_reg(), rs() - rt());
   4014       break;
   4015     case AND:
   4016       SetResult(rd_reg(), rs() & rt());
   4017       break;
   4018     case OR:
   4019       SetResult(rd_reg(), rs() | rt());
   4020       break;
   4021     case XOR:
   4022       SetResult(rd_reg(), rs() ^ rt());
   4023       break;
   4024     case NOR:
   4025       SetResult(rd_reg(), ~(rs() | rt()));
   4026       break;
   4027     case SLT:
   4028       SetResult(rd_reg(), rs() < rt() ? 1 : 0);
   4029       break;
   4030     case SLTU:
   4031       SetResult(rd_reg(), rs_u() < rt_u() ? 1 : 0);
   4032       break;
   4033     // Break and trap instructions.
   4034     case BREAK:
   4035       do_interrupt = true;
   4036       break;
   4037     case TGE:
   4038       do_interrupt = rs() >= rt();
   4039       break;
   4040     case TGEU:
   4041       do_interrupt = rs_u() >= rt_u();
   4042       break;
   4043     case TLT:
   4044       do_interrupt = rs() < rt();
   4045       break;
   4046     case TLTU:
   4047       do_interrupt = rs_u() < rt_u();
   4048       break;
   4049     case TEQ:
   4050       do_interrupt = rs() == rt();
   4051       break;
   4052     case TNE:
   4053       do_interrupt = rs() != rt();
   4054       break;
   4055     case SYNC:
   4056       // TODO(palfia): Ignore sync instruction for now.
   4057       break;
   4058     // Conditional moves.
   4059     case MOVN:
   4060       if (rt()) {
   4061         SetResult(rd_reg(), rs());
   4062       }
   4063       break;
   4064     case MOVCI: {
   4065       uint32_t cc = instr_.FBccValue();
   4066       uint32_t fcsr_cc = get_fcsr_condition_bit(cc);
   4067       if (instr_.Bit(16)) {  // Read Tf bit.
   4068         if (test_fcsr_bit(fcsr_cc)) set_register(rd_reg(), rs());
   4069       } else {
   4070         if (!test_fcsr_bit(fcsr_cc)) set_register(rd_reg(), rs());
   4071       }
   4072       break;
   4073     }
   4074     case MOVZ:
   4075       if (!rt()) {
   4076         SetResult(rd_reg(), rs());
   4077       }
   4078       break;
   4079     default:
   4080       UNREACHABLE();
   4081   }
   4082   if (do_interrupt) {
   4083     SoftwareInterrupt();
   4084   }
   4085 }
   4086 
   4087 
   4088 void Simulator::DecodeTypeRegisterSPECIAL2() {
   4089   int32_t alu_out;
   4090   switch (instr_.FunctionFieldRaw()) {
   4091     case MUL:
   4092       // Only the lower 32 bits are kept.
   4093       alu_out = rs_u() * rt_u();
   4094       // HI and LO are UNPREDICTABLE after the operation.
   4095       set_register(LO, Unpredictable);
   4096       set_register(HI, Unpredictable);
   4097       break;
   4098     case CLZ:
   4099       // MIPS32 spec: If no bits were set in GPR rs, the result written to
   4100       // GPR rd is 32.
   4101       alu_out = base::bits::CountLeadingZeros32(rs_u());
   4102       break;
   4103     default:
   4104       alu_out = 0x12345678;
   4105       UNREACHABLE();
   4106   }
   4107   SetResult(rd_reg(), alu_out);
   4108 }
   4109 
   4110 
   4111 void Simulator::DecodeTypeRegisterSPECIAL3() {
   4112   int32_t alu_out;
   4113   switch (instr_.FunctionFieldRaw()) {
   4114     case INS: {  // Mips32r2 instruction.
   4115       // Interpret rd field as 5-bit msb of insert.
   4116       uint16_t msb = rd_reg();
   4117       // Interpret sa field as 5-bit lsb of insert.
   4118       uint16_t lsb = sa();
   4119       uint16_t size = msb - lsb + 1;
   4120       uint32_t mask;
   4121       if (size < 32) {
   4122         mask = (1 << size) - 1;
   4123       } else {
   4124         mask = std::numeric_limits<uint32_t>::max();
   4125       }
   4126       alu_out = (rt_u() & ~(mask << lsb)) | ((rs_u() & mask) << lsb);
   4127       // Ins instr leaves result in Rt, rather than Rd.
   4128       SetResult(rt_reg(), alu_out);
   4129       break;
   4130     }
   4131     case EXT: {  // Mips32r2 instruction.
   4132       // Interpret rd field as 5-bit msb of extract.
   4133       uint16_t msb = rd_reg();
   4134       // Interpret sa field as 5-bit lsb of extract.
   4135       uint16_t lsb = sa();
   4136       uint16_t size = msb + 1;
   4137       uint32_t mask;
   4138       if (size < 32) {
   4139         mask = (1 << size) - 1;
   4140       } else {
   4141         mask = std::numeric_limits<uint32_t>::max();
   4142       }
   4143       alu_out = (rs_u() & (mask << lsb)) >> lsb;
   4144       SetResult(rt_reg(), alu_out);
   4145       break;
   4146     }
   4147     case BSHFL: {
   4148       int sa = instr_.SaFieldRaw() >> kSaShift;
   4149       switch (sa) {
   4150         case BITSWAP: {
   4151           uint32_t input = static_cast<uint32_t>(rt());
   4152           uint32_t output = 0;
   4153           uint8_t i_byte, o_byte;
   4154 
   4155           // Reverse the bit in byte for each individual byte
   4156           for (int i = 0; i < 4; i++) {
   4157             output = output >> 8;
   4158             i_byte = input & 0xFF;
   4159 
   4160             // Fast way to reverse bits in byte
   4161             // Devised by Sean Anderson, July 13, 2001
   4162             o_byte = static_cast<uint8_t>(((i_byte * 0x0802LU & 0x22110LU) |
   4163                                            (i_byte * 0x8020LU & 0x88440LU)) *
   4164                                               0x10101LU >>
   4165                                           16);
   4166 
   4167             output = output | (static_cast<uint32_t>(o_byte << 24));
   4168             input = input >> 8;
   4169           }
   4170 
   4171           alu_out = static_cast<int32_t>(output);
   4172           break;
   4173         }
   4174         case SEB: {
   4175           uint8_t input = static_cast<uint8_t>(rt());
   4176           uint32_t output = input;
   4177           uint32_t mask = 0x00000080;
   4178 
   4179           // Extending sign
   4180           if (mask & input) {
   4181             output |= 0xFFFFFF00;
   4182           }
   4183 
   4184           alu_out = static_cast<int32_t>(output);
   4185           break;
   4186         }
   4187         case SEH: {
   4188           uint16_t input = static_cast<uint16_t>(rt());
   4189           uint32_t output = input;
   4190           uint32_t mask = 0x00008000;
   4191 
   4192           // Extending sign
   4193           if (mask & input) {
   4194             output |= 0xFFFF0000;
   4195           }
   4196 
   4197           alu_out = static_cast<int32_t>(output);
   4198           break;
   4199         }
   4200         case WSBH: {
   4201           uint32_t input = static_cast<uint32_t>(rt());
   4202           uint32_t output = 0;
   4203 
   4204           uint32_t mask = 0xFF000000;
   4205           for (int i = 0; i < 4; i++) {
   4206             uint32_t tmp = mask & input;
   4207             if (i % 2 == 0) {
   4208               tmp = tmp >> 8;
   4209             } else {
   4210               tmp = tmp << 8;
   4211             }
   4212             output = output | tmp;
   4213             mask = mask >> 8;
   4214           }
   4215 
   4216           alu_out = static_cast<int32_t>(output);
   4217           break;
   4218         }
   4219         default: {
   4220           const uint8_t bp = instr_.Bp2Value();
   4221           sa >>= kBp2Bits;
   4222           switch (sa) {
   4223             case ALIGN: {
   4224               if (bp == 0) {
   4225                 alu_out = static_cast<int32_t>(rt());
   4226               } else {
   4227                 uint32_t rt_hi = rt() << (8 * bp);
   4228                 uint32_t rs_lo = rs() >> (8 * (4 - bp));
   4229                 alu_out = static_cast<int32_t>(rt_hi | rs_lo);
   4230               }
   4231               break;
   4232             }
   4233             default:
   4234               alu_out = 0x12345678;
   4235               UNREACHABLE();
   4236               break;
   4237           }
   4238         }
   4239       }
   4240       SetResult(rd_reg(), alu_out);
   4241       break;
   4242     }
   4243     default:
   4244       UNREACHABLE();
   4245   }
   4246 }
   4247 
   4248 int Simulator::DecodeMsaDataFormat() {
   4249   int df = -1;
   4250   if (instr_.IsMSABranchInstr()) {
   4251     switch (instr_.RsFieldRaw()) {
   4252       case BZ_V:
   4253       case BNZ_V:
   4254         df = MSA_VECT;
   4255         break;
   4256       case BZ_B:
   4257       case BNZ_B:
   4258         df = MSA_BYTE;
   4259         break;
   4260       case BZ_H:
   4261       case BNZ_H:
   4262         df = MSA_HALF;
   4263         break;
   4264       case BZ_W:
   4265       case BNZ_W:
   4266         df = MSA_WORD;
   4267         break;
   4268       case BZ_D:
   4269       case BNZ_D:
   4270         df = MSA_DWORD;
   4271         break;
   4272       default:
   4273         UNREACHABLE();
   4274         break;
   4275     }
   4276   } else {
   4277     int DF[] = {MSA_BYTE, MSA_HALF, MSA_WORD, MSA_DWORD};
   4278     switch (instr_.MSAMinorOpcodeField()) {
   4279       case kMsaMinorI5:
   4280       case kMsaMinorI10:
   4281       case kMsaMinor3R:
   4282         df = DF[instr_.Bits(22, 21)];
   4283         break;
   4284       case kMsaMinorMI10:
   4285         df = DF[instr_.Bits(1, 0)];
   4286         break;
   4287       case kMsaMinorBIT:
   4288         df = DF[instr_.MsaBitDf()];
   4289         break;
   4290       case kMsaMinorELM:
   4291         df = DF[instr_.MsaElmDf()];
   4292         break;
   4293       case kMsaMinor3RF: {
   4294         uint32_t opcode = instr_.InstructionBits() & kMsa3RFMask;
   4295         switch (opcode) {
   4296           case FEXDO:
   4297           case FTQ:
   4298           case MUL_Q:
   4299           case MADD_Q:
   4300           case MSUB_Q:
   4301           case MULR_Q:
   4302           case MADDR_Q:
   4303           case MSUBR_Q:
   4304             df = DF[1 + instr_.Bit(21)];
   4305             break;
   4306           default:
   4307             df = DF[2 + instr_.Bit(21)];
   4308             break;
   4309         }
   4310       } break;
   4311       case kMsaMinor2R:
   4312         df = DF[instr_.Bits(17, 16)];
   4313         break;
   4314       case kMsaMinor2RF:
   4315         df = DF[2 + instr_.Bit(16)];
   4316         break;
   4317       default:
   4318         UNREACHABLE();
   4319         break;
   4320     }
   4321   }
   4322   return df;
   4323 }
   4324 
   4325 void Simulator::DecodeTypeMsaI8() {
   4326   DCHECK(IsMipsArchVariant(kMips32r6));
   4327   DCHECK(CpuFeatures::IsSupported(MIPS_SIMD));
   4328   uint32_t opcode = instr_.InstructionBits() & kMsaI8Mask;
   4329   int8_t i8 = instr_.MsaImm8Value();
   4330   msa_reg_t ws, wd;
   4331 
   4332   switch (opcode) {
   4333     case ANDI_B:
   4334       get_msa_register(instr_.WsValue(), ws.b);
   4335       for (int i = 0; i < kMSALanesByte; i++) {
   4336         wd.b[i] = ws.b[i] & i8;
   4337       }
   4338       set_msa_register(instr_.WdValue(), wd.b);
   4339       TraceMSARegWr(wd.b);
   4340       break;
   4341     case ORI_B:
   4342       get_msa_register(instr_.WsValue(), ws.b);
   4343       for (int i = 0; i < kMSALanesByte; i++) {
   4344         wd.b[i] = ws.b[i] | i8;
   4345       }
   4346       set_msa_register(instr_.WdValue(), wd.b);
   4347       TraceMSARegWr(wd.b);
   4348       break;
   4349     case NORI_B:
   4350       get_msa_register(instr_.WsValue(), ws.b);
   4351       for (int i = 0; i < kMSALanesByte; i++) {
   4352         wd.b[i] = ~(ws.b[i] | i8);
   4353       }
   4354       set_msa_register(instr_.WdValue(), wd.b);
   4355       TraceMSARegWr(wd.b);
   4356       break;
   4357     case XORI_B:
   4358       get_msa_register(instr_.WsValue(), ws.b);
   4359       for (int i = 0; i < kMSALanesByte; i++) {
   4360         wd.b[i] = ws.b[i] ^ i8;
   4361       }
   4362       set_msa_register(instr_.WdValue(), wd.b);
   4363       TraceMSARegWr(wd.b);
   4364       break;
   4365     case BMNZI_B:
   4366       get_msa_register(instr_.WsValue(), ws.b);
   4367       get_msa_register(instr_.WdValue(), wd.b);
   4368       for (int i = 0; i < kMSALanesByte; i++) {
   4369         wd.b[i] = (ws.b[i] & i8) | (wd.b[i] & ~i8);
   4370       }
   4371       set_msa_register(instr_.WdValue(), wd.b);
   4372       TraceMSARegWr(wd.b);
   4373       break;
   4374     case BMZI_B:
   4375       get_msa_register(instr_.WsValue(), ws.b);
   4376       get_msa_register(instr_.WdValue(), wd.b);
   4377       for (int i = 0; i < kMSALanesByte; i++) {
   4378         wd.b[i] = (ws.b[i] & ~i8) | (wd.b[i] & i8);
   4379       }
   4380       set_msa_register(instr_.WdValue(), wd.b);
   4381       TraceMSARegWr(wd.b);
   4382       break;
   4383     case BSELI_B:
   4384       get_msa_register(instr_.WsValue(), ws.b);
   4385       get_msa_register(instr_.WdValue(), wd.b);
   4386       for (int i = 0; i < kMSALanesByte; i++) {
   4387         wd.b[i] = (ws.b[i] & ~wd.b[i]) | (wd.b[i] & i8);
   4388       }
   4389       set_msa_register(instr_.WdValue(), wd.b);
   4390       TraceMSARegWr(wd.b);
   4391       break;
   4392     case SHF_B:
   4393       get_msa_register(instr_.WsValue(), ws.b);
   4394       for (int i = 0; i < kMSALanesByte; i++) {
   4395         int j = i % 4;
   4396         int k = (i8 >> (2 * j)) & 0x3;
   4397         wd.b[i] = ws.b[i - j + k];
   4398       }
   4399       set_msa_register(instr_.WdValue(), wd.b);
   4400       TraceMSARegWr(wd.b);
   4401       break;
   4402     case SHF_H:
   4403       get_msa_register(instr_.WsValue(), ws.h);
   4404       for (int i = 0; i < kMSALanesHalf; i++) {
   4405         int j = i % 4;
   4406         int k = (i8 >> (2 * j)) & 0x3;
   4407         wd.h[i] = ws.h[i - j + k];
   4408       }
   4409       set_msa_register(instr_.WdValue(), wd.h);
   4410       TraceMSARegWr(wd.h);
   4411       break;
   4412     case SHF_W:
   4413       get_msa_register(instr_.WsValue(), ws.w);
   4414       for (int i = 0; i < kMSALanesWord; i++) {
   4415         int j = (i8 >> (2 * i)) & 0x3;
   4416         wd.w[i] = ws.w[j];
   4417       }
   4418       set_msa_register(instr_.WdValue(), wd.w);
   4419       TraceMSARegWr(wd.w);
   4420       break;
   4421     default:
   4422       UNREACHABLE();
   4423   }
   4424 }
   4425 
   4426 template <typename T>
   4427 T Simulator::MsaI5InstrHelper(uint32_t opcode, T ws, int32_t i5) {
   4428   T res;
   4429   uint32_t ui5 = i5 & 0x1Fu;
   4430   uint64_t ws_u64 = static_cast<uint64_t>(ws);
   4431   uint64_t ui5_u64 = static_cast<uint64_t>(ui5);
   4432 
   4433   switch (opcode) {
   4434     case ADDVI:
   4435       res = static_cast<T>(ws + ui5);
   4436       break;
   4437     case SUBVI:
   4438       res = static_cast<T>(ws - ui5);
   4439       break;
   4440     case MAXI_S:
   4441       res = static_cast<T>(Max(ws, static_cast<T>(i5)));
   4442       break;
   4443     case MINI_S:
   4444       res = static_cast<T>(Min(ws, static_cast<T>(i5)));
   4445       break;
   4446     case MAXI_U:
   4447       res = static_cast<T>(Max(ws_u64, ui5_u64));
   4448       break;
   4449     case MINI_U:
   4450       res = static_cast<T>(Min(ws_u64, ui5_u64));
   4451       break;
   4452     case CEQI:
   4453       res = static_cast<T>(!Compare(ws, static_cast<T>(i5)) ? -1ull : 0ull);
   4454       break;
   4455     case CLTI_S:
   4456       res = static_cast<T>((Compare(ws, static_cast<T>(i5)) == -1) ? -1ull
   4457                                                                    : 0ull);
   4458       break;
   4459     case CLTI_U:
   4460       res = static_cast<T>((Compare(ws_u64, ui5_u64) == -1) ? -1ull : 0ull);
   4461       break;
   4462     case CLEI_S:
   4463       res =
   4464           static_cast<T>((Compare(ws, static_cast<T>(i5)) != 1) ? -1ull : 0ull);
   4465       break;
   4466     case CLEI_U:
   4467       res = static_cast<T>((Compare(ws_u64, ui5_u64) != 1) ? -1ull : 0ull);
   4468       break;
   4469     default:
   4470       UNREACHABLE();
   4471   }
   4472   return res;
   4473 }
   4474 
   4475 void Simulator::DecodeTypeMsaI5() {
   4476   DCHECK(IsMipsArchVariant(kMips32r6));
   4477   DCHECK(CpuFeatures::IsSupported(MIPS_SIMD));
   4478   uint32_t opcode = instr_.InstructionBits() & kMsaI5Mask;
   4479   msa_reg_t ws, wd;
   4480 
   4481   // sign extend 5bit value to int32_t
   4482   int32_t i5 = static_cast<int32_t>(instr_.MsaImm5Value() << 27) >> 27;
   4483 
   4484 #define MSA_I5_DF(elem, num_of_lanes)                      \
   4485   get_msa_register(instr_.WsValue(), ws.elem);             \
   4486   for (int i = 0; i < num_of_lanes; i++) {                 \
   4487     wd.elem[i] = MsaI5InstrHelper(opcode, ws.elem[i], i5); \
   4488   }                                                        \
   4489   set_msa_register(instr_.WdValue(), wd.elem);             \
   4490   TraceMSARegWr(wd.elem)
   4491 
   4492   switch (DecodeMsaDataFormat()) {
   4493     case MSA_BYTE:
   4494       MSA_I5_DF(b, kMSALanesByte);
   4495       break;
   4496     case MSA_HALF:
   4497       MSA_I5_DF(h, kMSALanesHalf);
   4498       break;
   4499     case MSA_WORD:
   4500       MSA_I5_DF(w, kMSALanesWord);
   4501       break;
   4502     case MSA_DWORD:
   4503       MSA_I5_DF(d, kMSALanesDword);
   4504       break;
   4505     default:
   4506       UNREACHABLE();
   4507   }
   4508 #undef MSA_I5_DF
   4509 }
   4510 
   4511 void Simulator::DecodeTypeMsaI10() {
   4512   DCHECK(IsMipsArchVariant(kMips32r6));
   4513   DCHECK(CpuFeatures::IsSupported(MIPS_SIMD));
   4514   uint32_t opcode = instr_.InstructionBits() & kMsaI5Mask;
   4515   int64_t s10 = (static_cast<int64_t>(instr_.MsaImm10Value()) << 54) >> 54;
   4516   msa_reg_t wd;
   4517 
   4518 #define MSA_I10_DF(elem, num_of_lanes, T)      \
   4519   for (int i = 0; i < num_of_lanes; ++i) {     \
   4520     wd.elem[i] = static_cast<T>(s10);          \
   4521   }                                            \
   4522   set_msa_register(instr_.WdValue(), wd.elem); \
   4523   TraceMSARegWr(wd.elem)
   4524 
   4525   if (opcode == LDI) {
   4526     switch (DecodeMsaDataFormat()) {
   4527       case MSA_BYTE:
   4528         MSA_I10_DF(b, kMSALanesByte, int8_t);
   4529         break;
   4530       case MSA_HALF:
   4531         MSA_I10_DF(h, kMSALanesHalf, int16_t);
   4532         break;
   4533       case MSA_WORD:
   4534         MSA_I10_DF(w, kMSALanesWord, int32_t);
   4535         break;
   4536       case MSA_DWORD:
   4537         MSA_I10_DF(d, kMSALanesDword, int64_t);
   4538         break;
   4539       default:
   4540         UNREACHABLE();
   4541     }
   4542   } else {
   4543     UNREACHABLE();
   4544   }
   4545 #undef MSA_I10_DF
   4546 }
   4547 
   4548 void Simulator::DecodeTypeMsaELM() {
   4549   DCHECK(IsMipsArchVariant(kMips32r6));
   4550   DCHECK(CpuFeatures::IsSupported(MIPS_SIMD));
   4551   uint32_t opcode = instr_.InstructionBits() & kMsaLongerELMMask;
   4552   int32_t n = instr_.MsaElmNValue();
   4553   int32_t alu_out;
   4554   switch (opcode) {
   4555     case CTCMSA:
   4556       DCHECK_EQ(sa(), kMSACSRRegister);
   4557       MSACSR_ = bit_cast<uint32_t>(registers_[rd_reg()]);
   4558       TraceRegWr(static_cast<int32_t>(MSACSR_));
   4559       break;
   4560     case CFCMSA:
   4561       DCHECK_EQ(rd_reg(), kMSACSRRegister);
   4562       SetResult(sa(), bit_cast<int32_t>(MSACSR_));
   4563       break;
   4564     case MOVE_V: {
   4565       msa_reg_t ws;
   4566       get_msa_register(ws_reg(), &ws);
   4567       set_msa_register(wd_reg(), &ws);
   4568       TraceMSARegWr(&ws);
   4569     } break;
   4570     default:
   4571       opcode &= kMsaELMMask;
   4572       switch (opcode) {
   4573         case COPY_S:
   4574         case COPY_U: {
   4575           msa_reg_t ws;
   4576           switch (DecodeMsaDataFormat()) {
   4577             case MSA_BYTE: {
   4578               DCHECK_LT(n, kMSALanesByte);
   4579               get_msa_register(instr_.WsValue(), ws.b);
   4580               alu_out = static_cast<int32_t>(ws.b[n]);
   4581               SetResult(wd_reg(),
   4582                         (opcode == COPY_U) ? alu_out & 0xFFu : alu_out);
   4583               break;
   4584             }
   4585             case MSA_HALF: {
   4586               DCHECK_LT(n, kMSALanesHalf);
   4587               get_msa_register(instr_.WsValue(), ws.h);
   4588               alu_out = static_cast<int32_t>(ws.h[n]);
   4589               SetResult(wd_reg(),
   4590                         (opcode == COPY_U) ? alu_out & 0xFFFFu : alu_out);
   4591               break;
   4592             }
   4593             case MSA_WORD: {
   4594               DCHECK_LT(n, kMSALanesWord);
   4595               get_msa_register(instr_.WsValue(), ws.w);
   4596               alu_out = static_cast<int32_t>(ws.w[n]);
   4597               SetResult(wd_reg(), alu_out);
   4598               break;
   4599             }
   4600             default:
   4601               UNREACHABLE();
   4602           }
   4603         } break;
   4604         case INSERT: {
   4605           msa_reg_t wd;
   4606           switch (DecodeMsaDataFormat()) {
   4607             case MSA_BYTE: {
   4608               DCHECK_LT(n, kMSALanesByte);
   4609               int32_t rs = get_register(instr_.WsValue());
   4610               get_msa_register(instr_.WdValue(), wd.b);
   4611               wd.b[n] = rs & 0xFFu;
   4612               set_msa_register(instr_.WdValue(), wd.b);
   4613               TraceMSARegWr(wd.b);
   4614               break;
   4615             }
   4616             case MSA_HALF: {
   4617               DCHECK_LT(n, kMSALanesHalf);
   4618               int32_t rs = get_register(instr_.WsValue());
   4619               get_msa_register(instr_.WdValue(), wd.h);
   4620               wd.h[n] = rs & 0xFFFFu;
   4621               set_msa_register(instr_.WdValue(), wd.h);
   4622               TraceMSARegWr(wd.h);
   4623               break;
   4624             }
   4625             case MSA_WORD: {
   4626               DCHECK_LT(n, kMSALanesWord);
   4627               int32_t rs = get_register(instr_.WsValue());
   4628               get_msa_register(instr_.WdValue(), wd.w);
   4629               wd.w[n] = rs;
   4630               set_msa_register(instr_.WdValue(), wd.w);
   4631               TraceMSARegWr(wd.w);
   4632               break;
   4633             }
   4634             default:
   4635               UNREACHABLE();
   4636           }
   4637         } break;
   4638         case SLDI: {
   4639           uint8_t v[32];
   4640           msa_reg_t ws;
   4641           msa_reg_t wd;
   4642           get_msa_register(ws_reg(), &ws);
   4643           get_msa_register(wd_reg(), &wd);
   4644 #define SLDI_DF(s, k)                \
   4645   for (unsigned i = 0; i < s; i++) { \
   4646     v[i] = ws.b[s * k + i];          \
   4647     v[i + s] = wd.b[s * k + i];      \
   4648   }                                  \
   4649   for (unsigned i = 0; i < s; i++) { \
   4650     wd.b[s * k + i] = v[i + n];      \
   4651   }
   4652           switch (DecodeMsaDataFormat()) {
   4653             case MSA_BYTE:
   4654               DCHECK(n < kMSALanesByte);
   4655               SLDI_DF(kMSARegSize / sizeof(int8_t) / kBitsPerByte, 0)
   4656               break;
   4657             case MSA_HALF:
   4658               DCHECK(n < kMSALanesHalf);
   4659               for (int k = 0; k < 2; ++k) {
   4660                 SLDI_DF(kMSARegSize / sizeof(int16_t) / kBitsPerByte, k)
   4661               }
   4662               break;
   4663             case MSA_WORD:
   4664               DCHECK(n < kMSALanesWord);
   4665               for (int k = 0; k < 4; ++k) {
   4666                 SLDI_DF(kMSARegSize / sizeof(int32_t) / kBitsPerByte, k)
   4667               }
   4668               break;
   4669             case MSA_DWORD:
   4670               DCHECK(n < kMSALanesDword);
   4671               for (int k = 0; k < 8; ++k) {
   4672                 SLDI_DF(kMSARegSize / sizeof(int64_t) / kBitsPerByte, k)
   4673               }
   4674               break;
   4675             default:
   4676               UNREACHABLE();
   4677           }
   4678           set_msa_register(wd_reg(), &wd);
   4679           TraceMSARegWr(&wd);
   4680         } break;
   4681 #undef SLDI_DF
   4682         case SPLATI:
   4683         case INSVE:
   4684           UNIMPLEMENTED();
   4685           break;
   4686         default:
   4687           UNREACHABLE();
   4688       }
   4689       break;
   4690   }
   4691 }
   4692 
   4693 template <typename T>
   4694 T Simulator::MsaBitInstrHelper(uint32_t opcode, T wd, T ws, int32_t m) {
   4695   typedef typename std::make_unsigned<T>::type uT;
   4696   T res;
   4697   switch (opcode) {
   4698     case SLLI:
   4699       res = static_cast<T>(ws << m);
   4700       break;
   4701     case SRAI:
   4702       res = static_cast<T>(ArithmeticShiftRight(ws, m));
   4703       break;
   4704     case SRLI:
   4705       res = static_cast<T>(static_cast<uT>(ws) >> m);
   4706       break;
   4707     case BCLRI:
   4708       res = static_cast<T>(static_cast<T>(~(1ull << m)) & ws);
   4709       break;
   4710     case BSETI:
   4711       res = static_cast<T>(static_cast<T>(1ull << m) | ws);
   4712       break;
   4713     case BNEGI:
   4714       res = static_cast<T>(static_cast<T>(1ull << m) ^ ws);
   4715       break;
   4716     case BINSLI: {
   4717       int elem_size = 8 * sizeof(T);
   4718       int bits = m + 1;
   4719       if (bits == elem_size) {
   4720         res = static_cast<T>(ws);
   4721       } else {
   4722         uint64_t mask = ((1ull << bits) - 1) << (elem_size - bits);
   4723         res = static_cast<T>((static_cast<T>(mask) & ws) |
   4724                              (static_cast<T>(~mask) & wd));
   4725       }
   4726     } break;
   4727     case BINSRI: {
   4728       int elem_size = 8 * sizeof(T);
   4729       int bits = m + 1;
   4730       if (bits == elem_size) {
   4731         res = static_cast<T>(ws);
   4732       } else {
   4733         uint64_t mask = (1ull << bits) - 1;
   4734         res = static_cast<T>((static_cast<T>(mask) & ws) |
   4735                              (static_cast<T>(~mask) & wd));
   4736       }
   4737     } break;
   4738     case SAT_S: {
   4739 #define M_MAX_INT(x) static_cast<int64_t>((1LL << ((x)-1)) - 1)
   4740 #define M_MIN_INT(x) static_cast<int64_t>(-(1LL << ((x)-1)))
   4741       int shift = 64 - 8 * sizeof(T);
   4742       int64_t ws_i64 = (static_cast<int64_t>(ws) << shift) >> shift;
   4743       res = static_cast<T>(ws_i64 < M_MIN_INT(m + 1)
   4744                                ? M_MIN_INT(m + 1)
   4745                                : ws_i64 > M_MAX_INT(m + 1) ? M_MAX_INT(m + 1)
   4746                                                            : ws_i64);
   4747 #undef M_MAX_INT
   4748 #undef M_MIN_INT
   4749     } break;
   4750     case SAT_U: {
   4751 #define M_MAX_UINT(x) static_cast<uint64_t>(-1ULL >> (64 - (x)))
   4752       uint64_t mask = static_cast<uint64_t>(-1ULL >> (64 - 8 * sizeof(T)));
   4753       uint64_t ws_u64 = static_cast<uint64_t>(ws) & mask;
   4754       res = static_cast<T>(ws_u64 < M_MAX_UINT(m + 1) ? ws_u64
   4755                                                       : M_MAX_UINT(m + 1));
   4756 #undef M_MAX_UINT
   4757     } break;
   4758     case SRARI:
   4759       if (!m) {
   4760         res = static_cast<T>(ws);
   4761       } else {
   4762         res = static_cast<T>(ArithmeticShiftRight(ws, m)) +
   4763               static_cast<T>((ws >> (m - 1)) & 0x1);
   4764       }
   4765       break;
   4766     case SRLRI:
   4767       if (!m) {
   4768         res = static_cast<T>(ws);
   4769       } else {
   4770         res = static_cast<T>(static_cast<uT>(ws) >> m) +
   4771               static_cast<T>((ws >> (m - 1)) & 0x1);
   4772       }
   4773       break;
   4774     default:
   4775       UNREACHABLE();
   4776   }
   4777   return res;
   4778 }
   4779 
   4780 void Simulator::DecodeTypeMsaBIT() {
   4781   DCHECK(IsMipsArchVariant(kMips32r6));
   4782   DCHECK(CpuFeatures::IsSupported(MIPS_SIMD));
   4783   uint32_t opcode = instr_.InstructionBits() & kMsaBITMask;
   4784   int32_t m = instr_.MsaBitMValue();
   4785   msa_reg_t wd, ws;
   4786 
   4787 #define MSA_BIT_DF(elem, num_of_lanes)                                 \
   4788   get_msa_register(instr_.WsValue(), ws.elem);                         \
   4789   if (opcode == BINSLI || opcode == BINSRI) {                          \
   4790     get_msa_register(instr_.WdValue(), wd.elem);                       \
   4791   }                                                                    \
   4792   for (int i = 0; i < num_of_lanes; i++) {                             \
   4793     wd.elem[i] = MsaBitInstrHelper(opcode, wd.elem[i], ws.elem[i], m); \
   4794   }                                                                    \
   4795   set_msa_register(instr_.WdValue(), wd.elem);                         \
   4796   TraceMSARegWr(wd.elem)
   4797 
   4798   switch (DecodeMsaDataFormat()) {
   4799     case MSA_BYTE:
   4800       DCHECK(m < kMSARegSize / kMSALanesByte);
   4801       MSA_BIT_DF(b, kMSALanesByte);
   4802       break;
   4803     case MSA_HALF:
   4804       DCHECK(m < kMSARegSize / kMSALanesHalf);
   4805       MSA_BIT_DF(h, kMSALanesHalf);
   4806       break;
   4807     case MSA_WORD:
   4808       DCHECK(m < kMSARegSize / kMSALanesWord);
   4809       MSA_BIT_DF(w, kMSALanesWord);
   4810       break;
   4811     case MSA_DWORD:
   4812       DCHECK(m < kMSARegSize / kMSALanesDword);
   4813       MSA_BIT_DF(d, kMSALanesDword);
   4814       break;
   4815     default:
   4816       UNREACHABLE();
   4817   }
   4818 #undef MSA_BIT_DF
   4819 }
   4820 
   4821 void Simulator::DecodeTypeMsaMI10() {
   4822   DCHECK(IsMipsArchVariant(kMips32r6));
   4823   DCHECK(CpuFeatures::IsSupported(MIPS_SIMD));
   4824   uint32_t opcode = instr_.InstructionBits() & kMsaMI10Mask;
   4825   int32_t s10 = (static_cast<int32_t>(instr_.MsaImmMI10Value()) << 22) >> 22;
   4826   int32_t rs = get_register(instr_.WsValue());
   4827   int32_t addr;
   4828   msa_reg_t wd;
   4829 
   4830 #define MSA_MI10_LOAD(elem, num_of_lanes, T)       \
   4831   for (int i = 0; i < num_of_lanes; ++i) {         \
   4832     addr = rs + (s10 + i) * sizeof(T);             \
   4833     wd.elem[i] = ReadMem<T>(addr, instr_.instr()); \
   4834   }                                                \
   4835   set_msa_register(instr_.WdValue(), wd.elem);
   4836 
   4837 #define MSA_MI10_STORE(elem, num_of_lanes, T)      \
   4838   get_msa_register(instr_.WdValue(), wd.elem);     \
   4839   for (int i = 0; i < num_of_lanes; ++i) {         \
   4840     addr = rs + (s10 + i) * sizeof(T);             \
   4841     WriteMem<T>(addr, wd.elem[i], instr_.instr()); \
   4842   }
   4843 
   4844   if (opcode == MSA_LD) {
   4845     switch (DecodeMsaDataFormat()) {
   4846       case MSA_BYTE:
   4847         MSA_MI10_LOAD(b, kMSALanesByte, int8_t);
   4848         break;
   4849       case MSA_HALF:
   4850         MSA_MI10_LOAD(h, kMSALanesHalf, int16_t);
   4851         break;
   4852       case MSA_WORD:
   4853         MSA_MI10_LOAD(w, kMSALanesWord, int32_t);
   4854         break;
   4855       case MSA_DWORD:
   4856         MSA_MI10_LOAD(d, kMSALanesDword, int64_t);
   4857         break;
   4858       default:
   4859         UNREACHABLE();
   4860     }
   4861   } else if (opcode == MSA_ST) {
   4862     switch (DecodeMsaDataFormat()) {
   4863       case MSA_BYTE:
   4864         MSA_MI10_STORE(b, kMSALanesByte, int8_t);
   4865         break;
   4866       case MSA_HALF:
   4867         MSA_MI10_STORE(h, kMSALanesHalf, int16_t);
   4868         break;
   4869       case MSA_WORD:
   4870         MSA_MI10_STORE(w, kMSALanesWord, int32_t);
   4871         break;
   4872       case MSA_DWORD:
   4873         MSA_MI10_STORE(d, kMSALanesDword, int64_t);
   4874         break;
   4875       default:
   4876         UNREACHABLE();
   4877     }
   4878   } else {
   4879     UNREACHABLE();
   4880   }
   4881 
   4882 #undef MSA_MI10_LOAD
   4883 #undef MSA_MI10_STORE
   4884 }
   4885 
   4886 template <typename T>
   4887 T Simulator::Msa3RInstrHelper(uint32_t opcode, T wd, T ws, T wt) {
   4888   typedef typename std::make_unsigned<T>::type uT;
   4889   T res;
   4890   T wt_modulo = wt % (sizeof(T) * 8);
   4891   switch (opcode) {
   4892     case SLL_MSA:
   4893       res = static_cast<T>(ws << wt_modulo);
   4894       break;
   4895     case SRA_MSA:
   4896       res = static_cast<T>(ArithmeticShiftRight(ws, wt_modulo));
   4897       break;
   4898     case SRL_MSA:
   4899       res = static_cast<T>(static_cast<uT>(ws) >> wt_modulo);
   4900       break;
   4901     case BCLR:
   4902       res = static_cast<T>(static_cast<T>(~(1ull << wt_modulo)) & ws);
   4903       break;
   4904     case BSET:
   4905       res = static_cast<T>(static_cast<T>(1ull << wt_modulo) | ws);
   4906       break;
   4907     case BNEG:
   4908       res = static_cast<T>(static_cast<T>(1ull << wt_modulo) ^ ws);
   4909       break;
   4910     case BINSL: {
   4911       int elem_size = 8 * sizeof(T);
   4912       int bits = wt_modulo + 1;
   4913       if (bits == elem_size) {
   4914         res = static_cast<T>(ws);
   4915       } else {
   4916         uint64_t mask = ((1ull << bits) - 1) << (elem_size - bits);
   4917         res = static_cast<T>((static_cast<T>(mask) & ws) |
   4918                              (static_cast<T>(~mask) & wd));
   4919       }
   4920     } break;
   4921     case BINSR: {
   4922       int elem_size = 8 * sizeof(T);
   4923       int bits = wt_modulo + 1;
   4924       if (bits == elem_size) {
   4925         res = static_cast<T>(ws);
   4926       } else {
   4927         uint64_t mask = (1ull << bits) - 1;
   4928         res = static_cast<T>((static_cast<T>(mask) & ws) |
   4929                              (static_cast<T>(~mask) & wd));
   4930       }
   4931     } break;
   4932     case ADDV:
   4933       res = ws + wt;
   4934       break;
   4935     case SUBV:
   4936       res = ws - wt;
   4937       break;
   4938     case MAX_S:
   4939       res = Max(ws, wt);
   4940       break;
   4941     case MAX_U:
   4942       res = static_cast<T>(Max(static_cast<uT>(ws), static_cast<uT>(wt)));
   4943       break;
   4944     case MIN_S:
   4945       res = Min(ws, wt);
   4946       break;
   4947     case MIN_U:
   4948       res = static_cast<T>(Min(static_cast<uT>(ws), static_cast<uT>(wt)));
   4949       break;
   4950     case MAX_A:
   4951       // We use negative abs in order to avoid problems
   4952       // with corner case for MIN_INT
   4953       res = Nabs(ws) < Nabs(wt) ? ws : wt;
   4954       break;
   4955     case MIN_A:
   4956       // We use negative abs in order to avoid problems
   4957       // with corner case for MIN_INT
   4958       res = Nabs(ws) > Nabs(wt) ? ws : wt;
   4959       break;
   4960     case CEQ:
   4961       res = static_cast<T>(!Compare(ws, wt) ? -1ull : 0ull);
   4962       break;
   4963     case CLT_S:
   4964       res = static_cast<T>((Compare(ws, wt) == -1) ? -1ull : 0ull);
   4965       break;
   4966     case CLT_U:
   4967       res = static_cast<T>(
   4968           (Compare(static_cast<uT>(ws), static_cast<uT>(wt)) == -1) ? -1ull
   4969                                                                     : 0ull);
   4970       break;
   4971     case CLE_S:
   4972       res = static_cast<T>((Compare(ws, wt) != 1) ? -1ull : 0ull);
   4973       break;
   4974     case CLE_U:
   4975       res = static_cast<T>(
   4976           (Compare(static_cast<uT>(ws), static_cast<uT>(wt)) != 1) ? -1ull
   4977                                                                    : 0ull);
   4978       break;
   4979     case ADD_A:
   4980       res = static_cast<T>(Abs(ws) + Abs(wt));
   4981       break;
   4982     case ADDS_A: {
   4983       T ws_nabs = Nabs(ws);
   4984       T wt_nabs = Nabs(wt);
   4985       if (ws_nabs < -std::numeric_limits<T>::max() - wt_nabs) {
   4986         res = std::numeric_limits<T>::max();
   4987       } else {
   4988         res = -(ws_nabs + wt_nabs);
   4989       }
   4990     } break;
   4991     case ADDS_S:
   4992       res = SaturateAdd(ws, wt);
   4993       break;
   4994     case ADDS_U: {
   4995       uT ws_u = static_cast<uT>(ws);
   4996       uT wt_u = static_cast<uT>(wt);
   4997       res = static_cast<T>(SaturateAdd(ws_u, wt_u));
   4998     } break;
   4999     case AVE_S:
   5000       res = static_cast<T>((wt & ws) + ((wt ^ ws) >> 1));
   5001       break;
   5002     case AVE_U: {
   5003       uT ws_u = static_cast<uT>(ws);
   5004       uT wt_u = static_cast<uT>(wt);
   5005       res = static_cast<T>((wt_u & ws_u) + ((wt_u ^ ws_u) >> 1));
   5006     } break;
   5007     case AVER_S:
   5008       res = static_cast<T>((wt | ws) - ((wt ^ ws) >> 1));
   5009       break;
   5010     case AVER_U: {
   5011       uT ws_u = static_cast<uT>(ws);
   5012       uT wt_u = static_cast<uT>(wt);
   5013       res = static_cast<T>((wt_u | ws_u) - ((wt_u ^ ws_u) >> 1));
   5014     } break;
   5015     case SUBS_S:
   5016       res = SaturateSub(ws, wt);
   5017       break;
   5018     case SUBS_U: {
   5019       uT ws_u = static_cast<uT>(ws);
   5020       uT wt_u = static_cast<uT>(wt);
   5021       res = static_cast<T>(SaturateSub(ws_u, wt_u));
   5022     } break;
   5023     case SUBSUS_U: {
   5024       uT wsu = static_cast<uT>(ws);
   5025       if (wt > 0) {
   5026         uT wtu = static_cast<uT>(wt);
   5027         if (wtu > wsu) {
   5028           res = 0;
   5029         } else {
   5030           res = static_cast<T>(wsu - wtu);
   5031         }
   5032       } else {
   5033         if (wsu > std::numeric_limits<uT>::max() + wt) {
   5034           res = static_cast<T>(std::numeric_limits<uT>::max());
   5035         } else {
   5036           res = static_cast<T>(wsu - wt);
   5037         }
   5038       }
   5039     } break;
   5040     case SUBSUU_S: {
   5041       uT wsu = static_cast<uT>(ws);
   5042       uT wtu = static_cast<uT>(wt);
   5043       uT wdu;
   5044       if (wsu > wtu) {
   5045         wdu = wsu - wtu;
   5046         if (wdu > std::numeric_limits<T>::max()) {
   5047           res = std::numeric_limits<T>::max();
   5048         } else {
   5049           res = static_cast<T>(wdu);
   5050         }
   5051       } else {
   5052         wdu = wtu - wsu;
   5053         CHECK(-std::numeric_limits<T>::max() ==
   5054               std::numeric_limits<T>::min() + 1);
   5055         if (wdu <= std::numeric_limits<T>::max()) {
   5056           res = -static_cast<T>(wdu);
   5057         } else {
   5058           res = std::numeric_limits<T>::min();
   5059         }
   5060       }
   5061     } break;
   5062     case ASUB_S:
   5063       res = static_cast<T>(Abs(ws - wt));
   5064       break;
   5065     case ASUB_U: {
   5066       uT wsu = static_cast<uT>(ws);
   5067       uT wtu = static_cast<uT>(wt);
   5068       res = static_cast<T>(wsu > wtu ? wsu - wtu : wtu - wsu);
   5069     } break;
   5070     case MULV:
   5071       res = ws * wt;
   5072       break;
   5073     case MADDV:
   5074       res = wd + ws * wt;
   5075       break;
   5076     case MSUBV:
   5077       res = wd - ws * wt;
   5078       break;
   5079     case DIV_S_MSA:
   5080       res = wt != 0 ? ws / wt : static_cast<T>(Unpredictable);
   5081       break;
   5082     case DIV_U:
   5083       res = wt != 0 ? static_cast<T>(static_cast<uT>(ws) / static_cast<uT>(wt))
   5084                     : static_cast<T>(Unpredictable);
   5085       break;
   5086     case MOD_S:
   5087       res = wt != 0 ? ws % wt : static_cast<T>(Unpredictable);
   5088       break;
   5089     case MOD_U:
   5090       res = wt != 0 ? static_cast<T>(static_cast<uT>(ws) % static_cast<uT>(wt))
   5091                     : static_cast<T>(Unpredictable);
   5092       break;
   5093     case DOTP_S:
   5094     case DOTP_U:
   5095     case DPADD_S:
   5096     case DPADD_U:
   5097     case DPSUB_S:
   5098     case DPSUB_U:
   5099     case SLD:
   5100     case SPLAT:
   5101       UNIMPLEMENTED();
   5102       break;
   5103     case SRAR: {
   5104       int bit = wt_modulo == 0 ? 0 : (ws >> (wt_modulo - 1)) & 1;
   5105       res = static_cast<T>(ArithmeticShiftRight(ws, wt_modulo) + bit);
   5106     } break;
   5107     case SRLR: {
   5108       uT wsu = static_cast<uT>(ws);
   5109       int bit = wt_modulo == 0 ? 0 : (wsu >> (wt_modulo - 1)) & 1;
   5110       res = static_cast<T>((wsu >> wt_modulo) + bit);
   5111     } break;
   5112     default:
   5113       UNREACHABLE();
   5114   }
   5115   return res;
   5116 }
   5117 
   5118 template <typename T_int, typename T_reg>
   5119 void Msa3RInstrHelper_shuffle(const uint32_t opcode, T_reg ws, T_reg wt,
   5120                               T_reg wd, const int i, const int num_of_lanes) {
   5121   T_int *ws_p, *wt_p, *wd_p;
   5122   ws_p = reinterpret_cast<T_int*>(ws);
   5123   wt_p = reinterpret_cast<T_int*>(wt);
   5124   wd_p = reinterpret_cast<T_int*>(wd);
   5125   switch (opcode) {
   5126     case PCKEV:
   5127       wd_p[i] = wt_p[2 * i];
   5128       wd_p[i + num_of_lanes / 2] = ws_p[2 * i];
   5129       break;
   5130     case PCKOD:
   5131       wd_p[i] = wt_p[2 * i + 1];
   5132       wd_p[i + num_of_lanes / 2] = ws_p[2 * i + 1];
   5133       break;
   5134     case ILVL:
   5135       wd_p[2 * i] = wt_p[i + num_of_lanes / 2];
   5136       wd_p[2 * i + 1] = ws_p[i + num_of_lanes / 2];
   5137       break;
   5138     case ILVR:
   5139       wd_p[2 * i] = wt_p[i];
   5140       wd_p[2 * i + 1] = ws_p[i];
   5141       break;
   5142     case ILVEV:
   5143       wd_p[2 * i] = wt_p[2 * i];
   5144       wd_p[2 * i + 1] = ws_p[2 * i];
   5145       break;
   5146     case ILVOD:
   5147       wd_p[2 * i] = wt_p[2 * i + 1];
   5148       wd_p[2 * i + 1] = ws_p[2 * i + 1];
   5149       break;
   5150     case VSHF: {
   5151       const int mask_not_valid = 0xC0;
   5152       const int mask_6_bits = 0x3F;
   5153       if ((wd_p[i] & mask_not_valid)) {
   5154         wd_p[i] = 0;
   5155       } else {
   5156         int k = (wd_p[i] & mask_6_bits) % (num_of_lanes * 2);
   5157         wd_p[i] = k >= num_of_lanes ? ws_p[k - num_of_lanes] : wt_p[k];
   5158       }
   5159     } break;
   5160     default:
   5161       UNREACHABLE();
   5162   }
   5163 }
   5164 
   5165 template <typename T_int, typename T_smaller_int, typename T_reg>
   5166 void Msa3RInstrHelper_horizontal(const uint32_t opcode, T_reg ws, T_reg wt,
   5167                                  T_reg wd, const int i,
   5168                                  const int num_of_lanes) {
   5169   typedef typename std::make_unsigned<T_int>::type T_uint;
   5170   typedef typename std::make_unsigned<T_smaller_int>::type T_smaller_uint;
   5171   T_int* wd_p;
   5172   T_smaller_int *ws_p, *wt_p;
   5173   ws_p = reinterpret_cast<T_smaller_int*>(ws);
   5174   wt_p = reinterpret_cast<T_smaller_int*>(wt);
   5175   wd_p = reinterpret_cast<T_int*>(wd);
   5176   T_uint* wd_pu;
   5177   T_smaller_uint *ws_pu, *wt_pu;
   5178   ws_pu = reinterpret_cast<T_smaller_uint*>(ws);
   5179   wt_pu = reinterpret_cast<T_smaller_uint*>(wt);
   5180   wd_pu = reinterpret_cast<T_uint*>(wd);
   5181   switch (opcode) {
   5182     case HADD_S:
   5183       wd_p[i] =
   5184           static_cast<T_int>(ws_p[2 * i + 1]) + static_cast<T_int>(wt_p[2 * i]);
   5185       break;
   5186     case HADD_U:
   5187       wd_pu[i] = static_cast<T_uint>(ws_pu[2 * i + 1]) +
   5188                  static_cast<T_uint>(wt_pu[2 * i]);
   5189       break;
   5190     case HSUB_S:
   5191       wd_p[i] =
   5192           static_cast<T_int>(ws_p[2 * i + 1]) - static_cast<T_int>(wt_p[2 * i]);
   5193       break;
   5194     case HSUB_U:
   5195       wd_pu[i] = static_cast<T_uint>(ws_pu[2 * i + 1]) -
   5196                  static_cast<T_uint>(wt_pu[2 * i]);
   5197       break;
   5198     default:
   5199       UNREACHABLE();
   5200   }
   5201 }
   5202 
   5203 void Simulator::DecodeTypeMsa3R() {
   5204   DCHECK(IsMipsArchVariant(kMips32r6));
   5205   DCHECK(CpuFeatures::IsSupported(MIPS_SIMD));
   5206   uint32_t opcode = instr_.InstructionBits() & kMsa3RMask;
   5207   msa_reg_t ws, wd, wt;
   5208   get_msa_register(ws_reg(), &ws);
   5209   get_msa_register(wt_reg(), &wt);
   5210   get_msa_register(wd_reg(), &wd);
   5211   switch (opcode) {
   5212     case HADD_S:
   5213     case HADD_U:
   5214     case HSUB_S:
   5215     case HSUB_U:
   5216 #define HORIZONTAL_ARITHMETIC_DF(num_of_lanes, int_type, lesser_int_type) \
   5217   for (int i = 0; i < num_of_lanes; ++i) {                                \
   5218     Msa3RInstrHelper_horizontal<int_type, lesser_int_type>(               \
   5219         opcode, &ws, &wt, &wd, i, num_of_lanes);                          \
   5220   }
   5221       switch (DecodeMsaDataFormat()) {
   5222         case MSA_HALF:
   5223           HORIZONTAL_ARITHMETIC_DF(kMSALanesHalf, int16_t, int8_t);
   5224           break;
   5225         case MSA_WORD:
   5226           HORIZONTAL_ARITHMETIC_DF(kMSALanesWord, int32_t, int16_t);
   5227           break;
   5228         case MSA_DWORD:
   5229           HORIZONTAL_ARITHMETIC_DF(kMSALanesDword, int64_t, int32_t);
   5230           break;
   5231         default:
   5232           UNREACHABLE();
   5233       }
   5234       break;
   5235 #undef HORIZONTAL_ARITHMETIC_DF
   5236     case VSHF:
   5237 #define VSHF_DF(num_of_lanes, int_type)                          \
   5238   for (int i = 0; i < num_of_lanes; ++i) {                       \
   5239     Msa3RInstrHelper_shuffle<int_type>(opcode, &ws, &wt, &wd, i, \
   5240                                        num_of_lanes);            \
   5241   }
   5242       switch (DecodeMsaDataFormat()) {
   5243         case MSA_BYTE:
   5244           VSHF_DF(kMSALanesByte, int8_t);
   5245           break;
   5246         case MSA_HALF:
   5247           VSHF_DF(kMSALanesHalf, int16_t);
   5248           break;
   5249         case MSA_WORD:
   5250           VSHF_DF(kMSALanesWord, int32_t);
   5251           break;
   5252         case MSA_DWORD:
   5253           VSHF_DF(kMSALanesDword, int64_t);
   5254           break;
   5255         default:
   5256           UNREACHABLE();
   5257       }
   5258 #undef VSHF_DF
   5259       break;
   5260     case PCKEV:
   5261     case PCKOD:
   5262     case ILVL:
   5263     case ILVR:
   5264     case ILVEV:
   5265     case ILVOD:
   5266 #define INTERLEAVE_PACK_DF(num_of_lanes, int_type)               \
   5267   for (int i = 0; i < num_of_lanes / 2; ++i) {                   \
   5268     Msa3RInstrHelper_shuffle<int_type>(opcode, &ws, &wt, &wd, i, \
   5269                                        num_of_lanes);            \
   5270   }
   5271       switch (DecodeMsaDataFormat()) {
   5272         case MSA_BYTE:
   5273           INTERLEAVE_PACK_DF(kMSALanesByte, int8_t);
   5274           break;
   5275         case MSA_HALF:
   5276           INTERLEAVE_PACK_DF(kMSALanesHalf, int16_t);
   5277           break;
   5278         case MSA_WORD:
   5279           INTERLEAVE_PACK_DF(kMSALanesWord, int32_t);
   5280           break;
   5281         case MSA_DWORD:
   5282           INTERLEAVE_PACK_DF(kMSALanesDword, int64_t);
   5283           break;
   5284         default:
   5285           UNREACHABLE();
   5286       }
   5287       break;
   5288 #undef INTERLEAVE_PACK_DF
   5289     default:
   5290 #define MSA_3R_DF(elem, num_of_lanes)                                          \
   5291   for (int i = 0; i < num_of_lanes; i++) {                                     \
   5292     wd.elem[i] = Msa3RInstrHelper(opcode, wd.elem[i], ws.elem[i], wt.elem[i]); \
   5293   }
   5294 
   5295       switch (DecodeMsaDataFormat()) {
   5296         case MSA_BYTE:
   5297           MSA_3R_DF(b, kMSALanesByte);
   5298           break;
   5299         case MSA_HALF:
   5300           MSA_3R_DF(h, kMSALanesHalf);
   5301           break;
   5302         case MSA_WORD:
   5303           MSA_3R_DF(w, kMSALanesWord);
   5304           break;
   5305         case MSA_DWORD:
   5306           MSA_3R_DF(d, kMSALanesDword);
   5307           break;
   5308         default:
   5309           UNREACHABLE();
   5310       }
   5311 #undef MSA_3R_DF
   5312       break;
   5313   }
   5314   set_msa_register(wd_reg(), &wd);
   5315   TraceMSARegWr(&wd);
   5316 }
   5317 
   5318 template <typename T_int, typename T_fp, typename T_reg>
   5319 void Msa3RFInstrHelper(uint32_t opcode, T_reg ws, T_reg wt, T_reg& wd) {
   5320   const T_int all_ones = static_cast<T_int>(-1);
   5321   const T_fp s_element = *reinterpret_cast<T_fp*>(&ws);
   5322   const T_fp t_element = *reinterpret_cast<T_fp*>(&wt);
   5323   switch (opcode) {
   5324     case FCUN: {
   5325       if (std::isnan(s_element) || std::isnan(t_element)) {
   5326         wd = all_ones;
   5327       } else {
   5328         wd = 0;
   5329       }
   5330     } break;
   5331     case FCEQ: {
   5332       if (s_element != t_element || std::isnan(s_element) ||
   5333           std::isnan(t_element)) {
   5334         wd = 0;
   5335       } else {
   5336         wd = all_ones;
   5337       }
   5338     } break;
   5339     case FCUEQ: {
   5340       if (s_element == t_element || std::isnan(s_element) ||
   5341           std::isnan(t_element)) {
   5342         wd = all_ones;
   5343       } else {
   5344         wd = 0;
   5345       }
   5346     } break;
   5347     case FCLT: {
   5348       if (s_element >= t_element || std::isnan(s_element) ||
   5349           std::isnan(t_element)) {
   5350         wd = 0;
   5351       } else {
   5352         wd = all_ones;
   5353       }
   5354     } break;
   5355     case FCULT: {
   5356       if (s_element < t_element || std::isnan(s_element) ||
   5357           std::isnan(t_element)) {
   5358         wd = all_ones;
   5359       } else {
   5360         wd = 0;
   5361       }
   5362     } break;
   5363     case FCLE: {
   5364       if (s_element > t_element || std::isnan(s_element) ||
   5365           std::isnan(t_element)) {
   5366         wd = 0;
   5367       } else {
   5368         wd = all_ones;
   5369       }
   5370     } break;
   5371     case FCULE: {
   5372       if (s_element <= t_element || std::isnan(s_element) ||
   5373           std::isnan(t_element)) {
   5374         wd = all_ones;
   5375       } else {
   5376         wd = 0;
   5377       }
   5378     } break;
   5379     case FCOR: {
   5380       if (std::isnan(s_element) || std::isnan(t_element)) {
   5381         wd = 0;
   5382       } else {
   5383         wd = all_ones;
   5384       }
   5385     } break;
   5386     case FCUNE: {
   5387       if (s_element != t_element || std::isnan(s_element) ||
   5388           std::isnan(t_element)) {
   5389         wd = all_ones;
   5390       } else {
   5391         wd = 0;
   5392       }
   5393     } break;
   5394     case FCNE: {
   5395       if (s_element == t_element || std::isnan(s_element) ||
   5396           std::isnan(t_element)) {
   5397         wd = 0;
   5398       } else {
   5399         wd = all_ones;
   5400       }
   5401     } break;
   5402     case FADD:
   5403       wd = bit_cast<T_int>(s_element + t_element);
   5404       break;
   5405     case FSUB:
   5406       wd = bit_cast<T_int>(s_element - t_element);
   5407       break;
   5408     case FMUL:
   5409       wd = bit_cast<T_int>(s_element * t_element);
   5410       break;
   5411     case FDIV: {
   5412       if (t_element == 0) {
   5413         wd = bit_cast<T_int>(std::numeric_limits<T_fp>::quiet_NaN());
   5414       } else {
   5415         wd = bit_cast<T_int>(s_element / t_element);
   5416       }
   5417     } break;
   5418     case FMADD:
   5419       wd = bit_cast<T_int>(
   5420           std::fma(s_element, t_element, *reinterpret_cast<T_fp*>(&wd)));
   5421       break;
   5422     case FMSUB:
   5423       wd = bit_cast<T_int>(
   5424           std::fma(s_element, -t_element, *reinterpret_cast<T_fp*>(&wd)));
   5425       break;
   5426     case FEXP2:
   5427       wd = bit_cast<T_int>(std::ldexp(s_element, static_cast<int>(wt)));
   5428       break;
   5429     case FMIN:
   5430       wd = bit_cast<T_int>(std::min(s_element, t_element));
   5431       break;
   5432     case FMAX:
   5433       wd = bit_cast<T_int>(std::max(s_element, t_element));
   5434       break;
   5435     case FMIN_A: {
   5436       wd = bit_cast<T_int>(
   5437           std::fabs(s_element) < std::fabs(t_element) ? s_element : t_element);
   5438     } break;
   5439     case FMAX_A: {
   5440       wd = bit_cast<T_int>(
   5441           std::fabs(s_element) > std::fabs(t_element) ? s_element : t_element);
   5442     } break;
   5443     case FSOR:
   5444     case FSUNE:
   5445     case FSNE:
   5446     case FSAF:
   5447     case FSUN:
   5448     case FSEQ:
   5449     case FSUEQ:
   5450     case FSLT:
   5451     case FSULT:
   5452     case FSLE:
   5453     case FSULE:
   5454       UNIMPLEMENTED();
   5455       break;
   5456     default:
   5457       UNREACHABLE();
   5458   }
   5459 }
   5460 
   5461 template <typename T_int, typename T_int_dbl, typename T_reg>
   5462 void Msa3RFInstrHelper2(uint32_t opcode, T_reg ws, T_reg wt, T_reg& wd) {
   5463   // typedef typename std::make_unsigned<T_int>::type T_uint;
   5464   typedef typename std::make_unsigned<T_int_dbl>::type T_uint_dbl;
   5465   const T_int max_int = std::numeric_limits<T_int>::max();
   5466   const T_int min_int = std::numeric_limits<T_int>::min();
   5467   const int shift = kBitsPerByte * sizeof(T_int) - 1;
   5468   const T_int_dbl reg_s = ws;
   5469   const T_int_dbl reg_t = wt;
   5470   T_int_dbl product, result;
   5471   product = reg_s * reg_t;
   5472   switch (opcode) {
   5473     case MUL_Q: {
   5474       const T_int_dbl min_fix_dbl =
   5475           bit_cast<T_uint_dbl>(std::numeric_limits<T_int_dbl>::min()) >> 1U;
   5476       const T_int_dbl max_fix_dbl = std::numeric_limits<T_int_dbl>::max() >> 1U;
   5477       if (product == min_fix_dbl) {
   5478         product = max_fix_dbl;
   5479       }
   5480       wd = static_cast<T_int>(product >> shift);
   5481     } break;
   5482     case MADD_Q: {
   5483       result = (product + (static_cast<T_int_dbl>(wd) << shift)) >> shift;
   5484       wd = static_cast<T_int>(
   5485           result > max_int ? max_int : result < min_int ? min_int : result);
   5486     } break;
   5487     case MSUB_Q: {
   5488       result = (-product + (static_cast<T_int_dbl>(wd) << shift)) >> shift;
   5489       wd = static_cast<T_int>(
   5490           result > max_int ? max_int : result < min_int ? min_int : result);
   5491     } break;
   5492     case MULR_Q: {
   5493       const T_int_dbl min_fix_dbl =
   5494           bit_cast<T_uint_dbl>(std::numeric_limits<T_int_dbl>::min()) >> 1U;
   5495       const T_int_dbl max_fix_dbl = std::numeric_limits<T_int_dbl>::max() >> 1U;
   5496       if (product == min_fix_dbl) {
   5497         wd = static_cast<T_int>(max_fix_dbl >> shift);
   5498         break;
   5499       }
   5500       wd = static_cast<T_int>((product + (1 << (shift - 1))) >> shift);
   5501     } break;
   5502     case MADDR_Q: {
   5503       result = (product + (static_cast<T_int_dbl>(wd) << shift) +
   5504                 (1 << (shift - 1))) >>
   5505                shift;
   5506       wd = static_cast<T_int>(
   5507           result > max_int ? max_int : result < min_int ? min_int : result);
   5508     } break;
   5509     case MSUBR_Q: {
   5510       result = (-product + (static_cast<T_int_dbl>(wd) << shift) +
   5511                 (1 << (shift - 1))) >>
   5512                shift;
   5513       wd = static_cast<T_int>(
   5514           result > max_int ? max_int : result < min_int ? min_int : result);
   5515     } break;
   5516     default:
   5517       UNREACHABLE();
   5518   }
   5519 }
   5520 
   5521 void Simulator::DecodeTypeMsa3RF() {
   5522   DCHECK(IsMipsArchVariant(kMips32r6));
   5523   DCHECK(CpuFeatures::IsSupported(MIPS_SIMD));
   5524   uint32_t opcode = instr_.InstructionBits() & kMsa3RFMask;
   5525   msa_reg_t wd, ws, wt;
   5526   if (opcode != FCAF) {
   5527     get_msa_register(ws_reg(), &ws);
   5528     get_msa_register(wt_reg(), &wt);
   5529   }
   5530   switch (opcode) {
   5531     case FCAF:
   5532       wd.d[0] = 0;
   5533       wd.d[1] = 0;
   5534       break;
   5535     case FEXDO:
   5536 #define PACK_FLOAT16(sign, exp, frac) \
   5537   static_cast<uint16_t>(((sign) << 15) + ((exp) << 10) + (frac))
   5538 #define FEXDO_DF(source, dst)                                        \
   5539   do {                                                               \
   5540     element = source;                                                \
   5541     aSign = element >> 31;                                           \
   5542     aExp = element >> 23 & 0xFF;                                     \
   5543     aFrac = element & 0x007FFFFF;                                    \
   5544     if (aExp == 0xFF) {                                              \
   5545       if (aFrac) {                                                   \
   5546         /* Input is a NaN */                                         \
   5547         dst = 0x7DFFU;                                               \
   5548         break;                                                       \
   5549       }                                                              \
   5550       /* Infinity */                                                 \
   5551       dst = PACK_FLOAT16(aSign, 0x1F, 0);                            \
   5552       break;                                                         \
   5553     } else if (aExp == 0 && aFrac == 0) {                            \
   5554       dst = PACK_FLOAT16(aSign, 0, 0);                               \
   5555       break;                                                         \
   5556     } else {                                                         \
   5557       int maxexp = 29;                                               \
   5558       uint32_t mask;                                                 \
   5559       uint32_t increment;                                            \
   5560       bool rounding_bumps_exp;                                       \
   5561       aFrac |= 0x00800000;                                           \
   5562       aExp -= 0x71;                                                  \
   5563       if (aExp < 1) {                                                \
   5564         /* Will be denormal in halfprec */                           \
   5565         mask = 0x00FFFFFF;                                           \
   5566         if (aExp >= -11) {                                           \
   5567           mask >>= 11 + aExp;                                        \
   5568         }                                                            \
   5569       } else {                                                       \
   5570         /* Normal number in halfprec */                              \
   5571         mask = 0x00001FFF;                                           \
   5572       }                                                              \
   5573       switch (MSACSR_ & 3) {                                         \
   5574         case kRoundToNearest:                                        \
   5575           increment = (mask + 1) >> 1;                               \
   5576           if ((aFrac & mask) == increment) {                         \
   5577             increment = aFrac & (increment << 1);                    \
   5578           }                                                          \
   5579           break;                                                     \
   5580         case kRoundToPlusInf:                                        \
   5581           increment = aSign ? 0 : mask;                              \
   5582           break;                                                     \
   5583         case kRoundToMinusInf:                                       \
   5584           increment = aSign ? mask : 0;                              \
   5585           break;                                                     \
   5586         case kRoundToZero:                                           \
   5587           increment = 0;                                             \
   5588           break;                                                     \
   5589       }                                                              \
   5590       rounding_bumps_exp = (aFrac + increment >= 0x01000000);        \
   5591       if (aExp > maxexp || (aExp == maxexp && rounding_bumps_exp)) { \
   5592         dst = PACK_FLOAT16(aSign, 0x1F, 0);                          \
   5593         break;                                                       \
   5594       }                                                              \
   5595       aFrac += increment;                                            \
   5596       if (rounding_bumps_exp) {                                      \
   5597         aFrac >>= 1;                                                 \
   5598         aExp++;                                                      \
   5599       }                                                              \
   5600       if (aExp < -10) {                                              \
   5601         dst = PACK_FLOAT16(aSign, 0, 0);                             \
   5602         break;                                                       \
   5603       }                                                              \
   5604       if (aExp < 0) {                                                \
   5605         aFrac >>= -aExp;                                             \
   5606         aExp = 0;                                                    \
   5607       }                                                              \
   5608       dst = PACK_FLOAT16(aSign, aExp, aFrac >> 13);                  \
   5609     }                                                                \
   5610   } while (0);
   5611       switch (DecodeMsaDataFormat()) {
   5612         case MSA_HALF:
   5613           for (int i = 0; i < kMSALanesWord; i++) {
   5614             uint_fast32_t element;
   5615             uint_fast32_t aSign, aFrac;
   5616             int_fast32_t aExp;
   5617             FEXDO_DF(ws.uw[i], wd.uh[i + kMSALanesHalf / 2])
   5618             FEXDO_DF(wt.uw[i], wd.uh[i])
   5619           }
   5620           break;
   5621         case MSA_WORD:
   5622           for (int i = 0; i < kMSALanesDword; i++) {
   5623             wd.w[i + kMSALanesWord / 2] = bit_cast<int32_t>(
   5624                 static_cast<float>(bit_cast<double>(ws.d[i])));
   5625             wd.w[i] = bit_cast<int32_t>(
   5626                 static_cast<float>(bit_cast<double>(wt.d[i])));
   5627           }
   5628           break;
   5629         default:
   5630           UNREACHABLE();
   5631       }
   5632       break;
   5633 #undef PACK_FLOAT16
   5634 #undef FEXDO_DF
   5635     case FTQ:
   5636 #define FTQ_DF(source, dst, fp_type, int_type)                 \
   5637   element = bit_cast<fp_type>(source) *                        \
   5638             (1U << (sizeof(int_type) * kBitsPerByte - 1));     \
   5639   if (element > std::numeric_limits<int_type>::max()) {        \
   5640     dst = std::numeric_limits<int_type>::max();                \
   5641   } else if (element < std::numeric_limits<int_type>::min()) { \
   5642     dst = std::numeric_limits<int_type>::min();                \
   5643   } else if (std::isnan(element)) {                            \
   5644     dst = 0;                                                   \
   5645   } else {                                                     \
   5646     int_type fixed_point;                                      \
   5647     round_according_to_msacsr(element, element, fixed_point);  \
   5648     dst = fixed_point;                                         \
   5649   }
   5650 
   5651       switch (DecodeMsaDataFormat()) {
   5652         case MSA_HALF:
   5653           for (int i = 0; i < kMSALanesWord; i++) {
   5654             float element;
   5655             FTQ_DF(ws.w[i], wd.h[i + kMSALanesHalf / 2], float, int16_t)
   5656             FTQ_DF(wt.w[i], wd.h[i], float, int16_t)
   5657           }
   5658           break;
   5659         case MSA_WORD:
   5660           double element;
   5661           for (int i = 0; i < kMSALanesDword; i++) {
   5662             FTQ_DF(ws.d[i], wd.w[i + kMSALanesWord / 2], double, int32_t)
   5663             FTQ_DF(wt.d[i], wd.w[i], double, int32_t)
   5664           }
   5665           break;
   5666         default:
   5667           UNREACHABLE();
   5668       }
   5669       break;
   5670 #undef FTQ_DF
   5671 #define MSA_3RF_DF(T1, T2, Lanes, ws, wt, wd)      \
   5672   for (int i = 0; i < Lanes; i++) {                \
   5673     Msa3RFInstrHelper<T1, T2>(opcode, ws, wt, wd); \
   5674   }
   5675 #define MSA_3RF_DF2(T1, T2, Lanes, ws, wt, wd)      \
   5676   for (int i = 0; i < Lanes; i++) {                 \
   5677     Msa3RFInstrHelper2<T1, T2>(opcode, ws, wt, wd); \
   5678   }
   5679     case MADD_Q:
   5680     case MSUB_Q:
   5681     case MADDR_Q:
   5682     case MSUBR_Q:
   5683       get_msa_register(wd_reg(), &wd);
   5684       V8_FALLTHROUGH;
   5685     case MUL_Q:
   5686     case MULR_Q:
   5687       switch (DecodeMsaDataFormat()) {
   5688         case MSA_HALF:
   5689           MSA_3RF_DF2(int16_t, int32_t, kMSALanesHalf, ws.h[i], wt.h[i],
   5690                       wd.h[i])
   5691           break;
   5692         case MSA_WORD:
   5693           MSA_3RF_DF2(int32_t, int64_t, kMSALanesWord, ws.w[i], wt.w[i],
   5694                       wd.w[i])
   5695           break;
   5696         default:
   5697           UNREACHABLE();
   5698       }
   5699       break;
   5700     default:
   5701       if (opcode == FMADD || opcode == FMSUB) {
   5702         get_msa_register(wd_reg(), &wd);
   5703       }
   5704       switch (DecodeMsaDataFormat()) {
   5705         case MSA_WORD:
   5706           MSA_3RF_DF(int32_t, float, kMSALanesWord, ws.w[i], wt.w[i], wd.w[i])
   5707           break;
   5708         case MSA_DWORD:
   5709           MSA_3RF_DF(int64_t, double, kMSALanesDword, ws.d[i], wt.d[i], wd.d[i])
   5710           break;
   5711         default:
   5712           UNREACHABLE();
   5713       }
   5714       break;
   5715 #undef MSA_3RF_DF
   5716 #undef MSA_3RF_DF2
   5717   }
   5718   set_msa_register(wd_reg(), &wd);
   5719   TraceMSARegWr(&wd);
   5720 }
   5721 
   5722 void Simulator::DecodeTypeMsaVec() {
   5723   DCHECK(IsMipsArchVariant(kMips32r6));
   5724   DCHECK(CpuFeatures::IsSupported(MIPS_SIMD));
   5725   uint32_t opcode = instr_.InstructionBits() & kMsaVECMask;
   5726   msa_reg_t wd, ws, wt;
   5727 
   5728   get_msa_register(instr_.WsValue(), ws.w);
   5729   get_msa_register(instr_.WtValue(), wt.w);
   5730   if (opcode == BMNZ_V || opcode == BMZ_V || opcode == BSEL_V) {
   5731     get_msa_register(instr_.WdValue(), wd.w);
   5732   }
   5733 
   5734   for (int i = 0; i < kMSALanesWord; i++) {
   5735     switch (opcode) {
   5736       case AND_V:
   5737         wd.w[i] = ws.w[i] & wt.w[i];
   5738         break;
   5739       case OR_V:
   5740         wd.w[i] = ws.w[i] | wt.w[i];
   5741         break;
   5742       case NOR_V:
   5743         wd.w[i] = ~(ws.w[i] | wt.w[i]);
   5744         break;
   5745       case XOR_V:
   5746         wd.w[i] = ws.w[i] ^ wt.w[i];
   5747         break;
   5748       case BMNZ_V:
   5749         wd.w[i] = (wt.w[i] & ws.w[i]) | (~wt.w[i] & wd.w[i]);
   5750         break;
   5751       case BMZ_V:
   5752         wd.w[i] = (~wt.w[i] & ws.w[i]) | (wt.w[i] & wd.w[i]);
   5753         break;
   5754       case BSEL_V:
   5755         wd.w[i] = (~wd.w[i] & ws.w[i]) | (wd.w[i] & wt.w[i]);
   5756         break;
   5757       default:
   5758         UNREACHABLE();
   5759     }
   5760   }
   5761   set_msa_register(instr_.WdValue(), wd.w);
   5762   TraceMSARegWr(wd.d);
   5763 }
   5764 
   5765 void Simulator::DecodeTypeMsa2R() {
   5766   DCHECK(IsMipsArchVariant(kMips32r6));
   5767   DCHECK(CpuFeatures::IsSupported(MIPS_SIMD));
   5768   uint32_t opcode = instr_.InstructionBits() & kMsa2RMask;
   5769   msa_reg_t wd, ws;
   5770   switch (opcode) {
   5771     case FILL:
   5772       switch (DecodeMsaDataFormat()) {
   5773         case MSA_BYTE: {
   5774           int32_t rs = get_register(instr_.WsValue());
   5775           for (int i = 0; i < kMSALanesByte; i++) {
   5776             wd.b[i] = rs & 0xFFu;
   5777           }
   5778           set_msa_register(instr_.WdValue(), wd.b);
   5779           TraceMSARegWr(wd.b);
   5780           break;
   5781         }
   5782         case MSA_HALF: {
   5783           int32_t rs = get_register(instr_.WsValue());
   5784           for (int i = 0; i < kMSALanesHalf; i++) {
   5785             wd.h[i] = rs & 0xFFFFu;
   5786           }
   5787           set_msa_register(instr_.WdValue(), wd.h);
   5788           TraceMSARegWr(wd.h);
   5789           break;
   5790         }
   5791         case MSA_WORD: {
   5792           int32_t rs = get_register(instr_.WsValue());
   5793           for (int i = 0; i < kMSALanesWord; i++) {
   5794             wd.w[i] = rs;
   5795           }
   5796           set_msa_register(instr_.WdValue(), wd.w);
   5797           TraceMSARegWr(wd.w);
   5798           break;
   5799         }
   5800         default:
   5801           UNREACHABLE();
   5802       }
   5803       break;
   5804     case PCNT:
   5805 #define PCNT_DF(elem, num_of_lanes)                       \
   5806   get_msa_register(instr_.WsValue(), ws.elem);            \
   5807   for (int i = 0; i < num_of_lanes; i++) {                \
   5808     uint64_t u64elem = static_cast<uint64_t>(ws.elem[i]); \
   5809     wd.elem[i] = base::bits::CountPopulation(u64elem);    \
   5810   }                                                       \
   5811   set_msa_register(instr_.WdValue(), wd.elem);            \
   5812   TraceMSARegWr(wd.elem)
   5813 
   5814       switch (DecodeMsaDataFormat()) {
   5815         case MSA_BYTE:
   5816           PCNT_DF(ub, kMSALanesByte);
   5817           break;
   5818         case MSA_HALF:
   5819           PCNT_DF(uh, kMSALanesHalf);
   5820           break;
   5821         case MSA_WORD:
   5822           PCNT_DF(uw, kMSALanesWord);
   5823           break;
   5824         case MSA_DWORD:
   5825           PCNT_DF(ud, kMSALanesDword);
   5826           break;
   5827         default:
   5828           UNREACHABLE();
   5829       }
   5830 #undef PCNT_DF
   5831       break;
   5832     case NLOC:
   5833 #define NLOC_DF(elem, num_of_lanes)                                         \
   5834   get_msa_register(instr_.WsValue(), ws.elem);                              \
   5835   for (int i = 0; i < num_of_lanes; i++) {                                  \
   5836     const uint64_t mask = (num_of_lanes == kMSALanesDword)                  \
   5837                               ? UINT64_MAX                                  \
   5838                               : (1ULL << (kMSARegSize / num_of_lanes)) - 1; \
   5839     uint64_t u64elem = static_cast<uint64_t>(~ws.elem[i]) & mask;           \
   5840     wd.elem[i] = base::bits::CountLeadingZeros64(u64elem) -                 \
   5841                  (64 - kMSARegSize / num_of_lanes);                         \
   5842   }                                                                         \
   5843   set_msa_register(instr_.WdValue(), wd.elem);                              \
   5844   TraceMSARegWr(wd.elem)
   5845 
   5846       switch (DecodeMsaDataFormat()) {
   5847         case MSA_BYTE:
   5848           NLOC_DF(ub, kMSALanesByte);
   5849           break;
   5850         case MSA_HALF:
   5851           NLOC_DF(uh, kMSALanesHalf);
   5852           break;
   5853         case MSA_WORD:
   5854           NLOC_DF(uw, kMSALanesWord);
   5855           break;
   5856         case MSA_DWORD:
   5857           NLOC_DF(ud, kMSALanesDword);
   5858           break;
   5859         default:
   5860           UNREACHABLE();
   5861       }
   5862 #undef NLOC_DF
   5863       break;
   5864     case NLZC:
   5865 #define NLZC_DF(elem, num_of_lanes)                         \
   5866   get_msa_register(instr_.WsValue(), ws.elem);              \
   5867   for (int i = 0; i < num_of_lanes; i++) {                  \
   5868     uint64_t u64elem = static_cast<uint64_t>(ws.elem[i]);   \
   5869     wd.elem[i] = base::bits::CountLeadingZeros64(u64elem) - \
   5870                  (64 - kMSARegSize / num_of_lanes);         \
   5871   }                                                         \
   5872   set_msa_register(instr_.WdValue(), wd.elem);              \
   5873   TraceMSARegWr(wd.elem)
   5874 
   5875       switch (DecodeMsaDataFormat()) {
   5876         case MSA_BYTE:
   5877           NLZC_DF(ub, kMSALanesByte);
   5878           break;
   5879         case MSA_HALF:
   5880           NLZC_DF(uh, kMSALanesHalf);
   5881           break;
   5882         case MSA_WORD:
   5883           NLZC_DF(uw, kMSALanesWord);
   5884           break;
   5885         case MSA_DWORD:
   5886           NLZC_DF(ud, kMSALanesDword);
   5887           break;
   5888         default:
   5889           UNREACHABLE();
   5890       }
   5891 #undef NLZC_DF
   5892       break;
   5893     default:
   5894       UNREACHABLE();
   5895   }
   5896 }
   5897 
   5898 #define BIT(n) (0x1LL << n)
   5899 #define QUIET_BIT_S(nan) (bit_cast<int32_t>(nan) & BIT(22))
   5900 #define QUIET_BIT_D(nan) (bit_cast<int64_t>(nan) & BIT(51))
   5901 static inline bool isSnan(float fp) { return !QUIET_BIT_S(fp); }
   5902 static inline bool isSnan(double fp) { return !QUIET_BIT_D(fp); }
   5903 #undef QUIET_BIT_S
   5904 #undef QUIET_BIT_D
   5905 
   5906 template <typename T_int, typename T_fp, typename T_src, typename T_dst>
   5907 T_int Msa2RFInstrHelper(uint32_t opcode, T_src src, T_dst& dst,
   5908                         Simulator* sim) {
   5909   typedef typename std::make_unsigned<T_int>::type T_uint;
   5910   switch (opcode) {
   5911     case FCLASS: {
   5912 #define SNAN_BIT BIT(0)
   5913 #define QNAN_BIT BIT(1)
   5914 #define NEG_INFINITY_BIT BIT(2)
   5915 #define NEG_NORMAL_BIT BIT(3)
   5916 #define NEG_SUBNORMAL_BIT BIT(4)
   5917 #define NEG_ZERO_BIT BIT(5)
   5918 #define POS_INFINITY_BIT BIT(6)
   5919 #define POS_NORMAL_BIT BIT(7)
   5920 #define POS_SUBNORMAL_BIT BIT(8)
   5921 #define POS_ZERO_BIT BIT(9)
   5922       T_fp element = *reinterpret_cast<T_fp*>(&src);
   5923       switch (std::fpclassify(element)) {
   5924         case FP_INFINITE:
   5925           if (std::signbit(element)) {
   5926             dst = NEG_INFINITY_BIT;
   5927           } else {
   5928             dst = POS_INFINITY_BIT;
   5929           }
   5930           break;
   5931         case FP_NAN:
   5932           if (isSnan(element)) {
   5933             dst = SNAN_BIT;
   5934           } else {
   5935             dst = QNAN_BIT;
   5936           }
   5937           break;
   5938         case FP_NORMAL:
   5939           if (std::signbit(element)) {
   5940             dst = NEG_NORMAL_BIT;
   5941           } else {
   5942             dst = POS_NORMAL_BIT;
   5943           }
   5944           break;
   5945         case FP_SUBNORMAL:
   5946           if (std::signbit(element)) {
   5947             dst = NEG_SUBNORMAL_BIT;
   5948           } else {
   5949             dst = POS_SUBNORMAL_BIT;
   5950           }
   5951           break;
   5952         case FP_ZERO:
   5953           if (std::signbit(element)) {
   5954             dst = NEG_ZERO_BIT;
   5955           } else {
   5956             dst = POS_ZERO_BIT;
   5957           }
   5958           break;
   5959         default:
   5960           UNREACHABLE();
   5961       }
   5962       break;
   5963     }
   5964 #undef BIT
   5965 #undef SNAN_BIT
   5966 #undef QNAN_BIT
   5967 #undef NEG_INFINITY_BIT
   5968 #undef NEG_NORMAL_BIT
   5969 #undef NEG_SUBNORMAL_BIT
   5970 #undef NEG_ZERO_BIT
   5971 #undef POS_INFINITY_BIT
   5972 #undef POS_NORMAL_BIT
   5973 #undef POS_SUBNORMAL_BIT
   5974 #undef POS_ZERO_BIT
   5975     case FTRUNC_S: {
   5976       T_fp element = bit_cast<T_fp>(src);
   5977       const T_int max_int = std::numeric_limits<T_int>::max();
   5978       const T_int min_int = std::numeric_limits<T_int>::min();
   5979       if (std::isnan(element)) {
   5980         dst = 0;
   5981       } else if (element >= max_int || element <= min_int) {
   5982         dst = element >= max_int ? max_int : min_int;
   5983       } else {
   5984         dst = static_cast<T_int>(std::trunc(element));
   5985       }
   5986       break;
   5987     }
   5988     case FTRUNC_U: {
   5989       T_fp element = bit_cast<T_fp>(src);
   5990       const T_uint max_int = std::numeric_limits<T_uint>::max();
   5991       if (std::isnan(element)) {
   5992         dst = 0;
   5993       } else if (element >= max_int || element <= 0) {
   5994         dst = element >= max_int ? max_int : 0;
   5995       } else {
   5996         dst = static_cast<T_uint>(std::trunc(element));
   5997       }
   5998       break;
   5999     }
   6000     case FSQRT: {
   6001       T_fp element = bit_cast<T_fp>(src);
   6002       if (element < 0 || std::isnan(element)) {
   6003         dst = bit_cast<T_int>(std::numeric_limits<T_fp>::quiet_NaN());
   6004       } else {
   6005         dst = bit_cast<T_int>(std::sqrt(element));
   6006       }
   6007       break;
   6008     }
   6009     case FRSQRT: {
   6010       T_fp element = bit_cast<T_fp>(src);
   6011       if (element < 0 || std::isnan(element)) {
   6012         dst = bit_cast<T_int>(std::numeric_limits<T_fp>::quiet_NaN());
   6013       } else {
   6014         dst = bit_cast<T_int>(1 / std::sqrt(element));
   6015       }
   6016       break;
   6017     }
   6018     case FRCP: {
   6019       T_fp element = bit_cast<T_fp>(src);
   6020       if (std::isnan(element)) {
   6021         dst = bit_cast<T_int>(std::numeric_limits<T_fp>::quiet_NaN());
   6022       } else {
   6023         dst = bit_cast<T_int>(1 / element);
   6024       }
   6025       break;
   6026     }
   6027     case FRINT: {
   6028       T_fp element = bit_cast<T_fp>(src);
   6029       if (std::isnan(element)) {
   6030         dst = bit_cast<T_int>(std::numeric_limits<T_fp>::quiet_NaN());
   6031       } else {
   6032         T_int dummy;
   6033         sim->round_according_to_msacsr<T_fp, T_int>(element, element, dummy);
   6034         dst = bit_cast<T_int>(element);
   6035       }
   6036       break;
   6037     }
   6038     case FLOG2: {
   6039       T_fp element = bit_cast<T_fp>(src);
   6040       switch (std::fpclassify(element)) {
   6041         case FP_NORMAL:
   6042         case FP_SUBNORMAL:
   6043           dst = bit_cast<T_int>(std::logb(element));
   6044           break;
   6045         case FP_ZERO:
   6046           dst = bit_cast<T_int>(-std::numeric_limits<T_fp>::infinity());
   6047           break;
   6048         case FP_NAN:
   6049           dst = bit_cast<T_int>(std::numeric_limits<T_fp>::quiet_NaN());
   6050           break;
   6051         case FP_INFINITE:
   6052           if (element < 0) {
   6053             dst = bit_cast<T_int>(std::numeric_limits<T_fp>::quiet_NaN());
   6054           } else {
   6055             dst = bit_cast<T_int>(std::numeric_limits<T_fp>::infinity());
   6056           }
   6057           break;
   6058         default:
   6059           UNREACHABLE();
   6060       }
   6061       break;
   6062     }
   6063     case FTINT_S: {
   6064       T_fp element = bit_cast<T_fp>(src);
   6065       const T_int max_int = std::numeric_limits<T_int>::max();
   6066       const T_int min_int = std::numeric_limits<T_int>::min();
   6067       if (std::isnan(element)) {
   6068         dst = 0;
   6069       } else if (element < min_int || element > max_int) {
   6070         dst = element > max_int ? max_int : min_int;
   6071       } else {
   6072         sim->round_according_to_msacsr<T_fp, T_int>(element, element, dst);
   6073       }
   6074       break;
   6075     }
   6076     case FTINT_U: {
   6077       T_fp element = bit_cast<T_fp>(src);
   6078       const T_uint max_uint = std::numeric_limits<T_uint>::max();
   6079       if (std::isnan(element)) {
   6080         dst = 0;
   6081       } else if (element < 0 || element > max_uint) {
   6082         dst = element > max_uint ? max_uint : 0;
   6083       } else {
   6084         T_uint res;
   6085         sim->round_according_to_msacsr<T_fp, T_uint>(element, element, res);
   6086         dst = *reinterpret_cast<T_int*>(&res);
   6087       }
   6088       break;
   6089     }
   6090     case FFINT_S:
   6091       dst = bit_cast<T_int>(static_cast<T_fp>(src));
   6092       break;
   6093     case FFINT_U:
   6094       typedef typename std::make_unsigned<T_src>::type uT_src;
   6095       dst = bit_cast<T_int>(static_cast<T_fp>(bit_cast<uT_src>(src)));
   6096       break;
   6097     default:
   6098       UNREACHABLE();
   6099   }
   6100   return 0;
   6101 }
   6102 
   6103 template <typename T_int, typename T_fp, typename T_reg>
   6104 T_int Msa2RFInstrHelper2(uint32_t opcode, T_reg ws, int i) {
   6105   switch (opcode) {
   6106 #define EXTRACT_FLOAT16_SIGN(fp16) (fp16 >> 15)
   6107 #define EXTRACT_FLOAT16_EXP(fp16) (fp16 >> 10 & 0x1F)
   6108 #define EXTRACT_FLOAT16_FRAC(fp16) (fp16 & 0x3FF)
   6109 #define PACK_FLOAT32(sign, exp, frac) \
   6110   static_cast<uint32_t>(((sign) << 31) + ((exp) << 23) + (frac))
   6111 #define FEXUP_DF(src_index)                                                   \
   6112   uint_fast16_t element = ws.uh[src_index];                                   \
   6113   uint_fast32_t aSign, aFrac;                                                 \
   6114   int_fast32_t aExp;                                                          \
   6115   aSign = EXTRACT_FLOAT16_SIGN(element);                                      \
   6116   aExp = EXTRACT_FLOAT16_EXP(element);                                        \
   6117   aFrac = EXTRACT_FLOAT16_FRAC(element);                                      \
   6118   if (V8_LIKELY(aExp && aExp != 0x1F)) {                                      \
   6119     return PACK_FLOAT32(aSign, aExp + 0x70, aFrac << 13);                     \
   6120   } else if (aExp == 0x1F) {                                                  \
   6121     if (aFrac) {                                                              \
   6122       return bit_cast<int32_t>(std::numeric_limits<float>::quiet_NaN());      \
   6123     } else {                                                                  \
   6124       return bit_cast<uint32_t>(std::numeric_limits<float>::infinity()) |     \
   6125              static_cast<uint32_t>(aSign) << 31;                              \
   6126     }                                                                         \
   6127   } else {                                                                    \
   6128     if (aFrac == 0) {                                                         \
   6129       return PACK_FLOAT32(aSign, 0, 0);                                       \
   6130     } else {                                                                  \
   6131       int_fast16_t shiftCount =                                               \
   6132           base::bits::CountLeadingZeros32(static_cast<uint32_t>(aFrac)) - 21; \
   6133       aFrac <<= shiftCount;                                                   \
   6134       aExp = -shiftCount;                                                     \
   6135       return PACK_FLOAT32(aSign, aExp + 0x70, aFrac << 13);                   \
   6136     }                                                                         \
   6137   }
   6138     case FEXUPL:
   6139       if (std::is_same<int32_t, T_int>::value) {
   6140         FEXUP_DF(i + kMSALanesWord)
   6141       } else {
   6142         return bit_cast<int64_t>(
   6143             static_cast<double>(bit_cast<float>(ws.w[i + kMSALanesDword])));
   6144       }
   6145     case FEXUPR:
   6146       if (std::is_same<int32_t, T_int>::value) {
   6147         FEXUP_DF(i)
   6148       } else {
   6149         return bit_cast<int64_t>(static_cast<double>(bit_cast<float>(ws.w[i])));
   6150       }
   6151     case FFQL: {
   6152       if (std::is_same<int32_t, T_int>::value) {
   6153         return bit_cast<int32_t>(static_cast<float>(ws.h[i + kMSALanesWord]) /
   6154                                  (1U << 15));
   6155       } else {
   6156         return bit_cast<int64_t>(static_cast<double>(ws.w[i + kMSALanesDword]) /
   6157                                  (1U << 31));
   6158       }
   6159       break;
   6160     }
   6161     case FFQR: {
   6162       if (std::is_same<int32_t, T_int>::value) {
   6163         return bit_cast<int32_t>(static_cast<float>(ws.h[i]) / (1U << 15));
   6164       } else {
   6165         return bit_cast<int64_t>(static_cast<double>(ws.w[i]) / (1U << 31));
   6166       }
   6167       break;
   6168       default:
   6169         UNREACHABLE();
   6170     }
   6171   }
   6172 #undef EXTRACT_FLOAT16_SIGN
   6173 #undef EXTRACT_FLOAT16_EXP
   6174 #undef EXTRACT_FLOAT16_FRAC
   6175 #undef PACK_FLOAT32
   6176 #undef FEXUP_DF
   6177 }
   6178 
   6179 void Simulator::DecodeTypeMsa2RF() {
   6180   DCHECK(IsMipsArchVariant(kMips32r6));
   6181   DCHECK(CpuFeatures::IsSupported(MIPS_SIMD));
   6182   uint32_t opcode = instr_.InstructionBits() & kMsa2RFMask;
   6183   msa_reg_t wd, ws;
   6184   get_msa_register(ws_reg(), &ws);
   6185   if (opcode == FEXUPL || opcode == FEXUPR || opcode == FFQL ||
   6186       opcode == FFQR) {
   6187     switch (DecodeMsaDataFormat()) {
   6188       case MSA_WORD:
   6189         for (int i = 0; i < kMSALanesWord; i++) {
   6190           wd.w[i] = Msa2RFInstrHelper2<int32_t, float>(opcode, ws, i);
   6191         }
   6192         break;
   6193       case MSA_DWORD:
   6194         for (int i = 0; i < kMSALanesDword; i++) {
   6195           wd.d[i] = Msa2RFInstrHelper2<int64_t, double>(opcode, ws, i);
   6196         }
   6197         break;
   6198       default:
   6199         UNREACHABLE();
   6200     }
   6201   } else {
   6202     switch (DecodeMsaDataFormat()) {
   6203       case MSA_WORD:
   6204         for (int i = 0; i < kMSALanesWord; i++) {
   6205           Msa2RFInstrHelper<int32_t, float>(opcode, ws.w[i], wd.w[i], this);
   6206         }
   6207         break;
   6208       case MSA_DWORD:
   6209         for (int i = 0; i < kMSALanesDword; i++) {
   6210           Msa2RFInstrHelper<int64_t, double>(opcode, ws.d[i], wd.d[i], this);
   6211         }
   6212         break;
   6213       default:
   6214         UNREACHABLE();
   6215     }
   6216   }
   6217   set_msa_register(wd_reg(), &wd);
   6218   TraceMSARegWr(&wd);
   6219 }
   6220 
   6221 void Simulator::DecodeTypeRegister() {
   6222   // ---------- Execution.
   6223   switch (instr_.OpcodeFieldRaw()) {
   6224     case COP1:
   6225       DecodeTypeRegisterCOP1();
   6226       break;
   6227     case COP1X:
   6228       DecodeTypeRegisterCOP1X();
   6229       break;
   6230     case SPECIAL:
   6231       DecodeTypeRegisterSPECIAL();
   6232       break;
   6233     case SPECIAL2:
   6234       DecodeTypeRegisterSPECIAL2();
   6235       break;
   6236     case SPECIAL3:
   6237       DecodeTypeRegisterSPECIAL3();
   6238       break;
   6239     case MSA:
   6240       switch (instr_.MSAMinorOpcodeField()) {
   6241         case kMsaMinor3R:
   6242           DecodeTypeMsa3R();
   6243           break;
   6244         case kMsaMinor3RF:
   6245           DecodeTypeMsa3RF();
   6246           break;
   6247         case kMsaMinorVEC:
   6248           DecodeTypeMsaVec();
   6249           break;
   6250         case kMsaMinor2R:
   6251           DecodeTypeMsa2R();
   6252           break;
   6253         case kMsaMinor2RF:
   6254           DecodeTypeMsa2RF();
   6255           break;
   6256         case kMsaMinorELM:
   6257           DecodeTypeMsaELM();
   6258           break;
   6259         default:
   6260           UNREACHABLE();
   6261       }
   6262       break;
   6263     default:
   6264       UNREACHABLE();
   6265   }
   6266 }
   6267 
   6268 
   6269 // Type 2: instructions using a 16, 21 or 26 bits immediate. (e.g. beq, beqc).
   6270 void Simulator::DecodeTypeImmediate() {
   6271   // Instruction fields.
   6272   Opcode op = instr_.OpcodeFieldRaw();
   6273   int32_t rs_reg = instr_.RsValue();
   6274   int32_t rs = get_register(instr_.RsValue());
   6275   uint32_t rs_u = static_cast<uint32_t>(rs);
   6276   int32_t rt_reg = instr_.RtValue();  // Destination register.
   6277   int32_t rt = get_register(rt_reg);
   6278   int16_t imm16 = instr_.Imm16Value();
   6279 
   6280   int32_t ft_reg = instr_.FtValue();  // Destination register.
   6281 
   6282   // Zero extended immediate.
   6283   uint32_t oe_imm16 = 0xFFFF & imm16;
   6284   // Sign extended immediate.
   6285   int32_t se_imm16 = imm16;
   6286 
   6287   // Next pc.
   6288   int32_t next_pc = bad_ra;
   6289 
   6290   // Used for conditional branch instructions.
   6291   bool execute_branch_delay_instruction = false;
   6292 
   6293   // Used for arithmetic instructions.
   6294   int32_t alu_out = 0;
   6295 
   6296   // Used for memory instructions.
   6297   int32_t addr = 0x0;
   6298 
   6299   // Branch instructions common part.
   6300   auto BranchAndLinkHelper =
   6301       [this, &next_pc, &execute_branch_delay_instruction](bool do_branch) {
   6302         execute_branch_delay_instruction = true;
   6303         int32_t current_pc = get_pc();
   6304         set_register(31, current_pc + 2 * kInstrSize);
   6305         if (do_branch) {
   6306           int16_t imm16 = this->instr_.Imm16Value();
   6307           next_pc = current_pc + (imm16 << 2) + kInstrSize;
   6308         } else {
   6309           next_pc = current_pc + 2 * kInstrSize;
   6310         }
   6311       };
   6312 
   6313   auto BranchHelper = [this, &next_pc,
   6314                        &execute_branch_delay_instruction](bool do_branch) {
   6315     execute_branch_delay_instruction = true;
   6316     int32_t current_pc = get_pc();
   6317     if (do_branch) {
   6318       int16_t imm16 = this->instr_.Imm16Value();
   6319       next_pc = current_pc + (imm16 << 2) + kInstrSize;
   6320     } else {
   6321       next_pc = current_pc + 2 * kInstrSize;
   6322     }
   6323   };
   6324 
   6325   auto BranchHelper_MSA = [this, &next_pc, imm16,
   6326                            &execute_branch_delay_instruction](bool do_branch) {
   6327     execute_branch_delay_instruction = true;
   6328     int32_t current_pc = get_pc();
   6329     const int32_t bitsIn16Int = sizeof(int16_t) * kBitsPerByte;
   6330     if (do_branch) {
   6331       if (FLAG_debug_code) {
   6332         int16_t bits = imm16 & 0xFC;
   6333         if (imm16 >= 0) {
   6334           CHECK_EQ(bits, 0);
   6335         } else {
   6336           CHECK_EQ(bits ^ 0xFC, 0);
   6337         }
   6338       }
   6339       // jump range :[pc + kInstrSize - 512 * kInstrSize,
   6340       //              pc + kInstrSize + 511 * kInstrSize]
   6341       int16_t offset = static_cast<int16_t>(imm16 << (bitsIn16Int - 10)) >>
   6342                        (bitsIn16Int - 12);
   6343       next_pc = current_pc + offset + kInstrSize;
   6344     } else {
   6345       next_pc = current_pc + 2 * kInstrSize;
   6346     }
   6347   };
   6348 
   6349   auto BranchAndLinkCompactHelper = [this, &next_pc](bool do_branch, int bits) {
   6350     int32_t current_pc = get_pc();
   6351     CheckForbiddenSlot(current_pc);
   6352     if (do_branch) {
   6353       int32_t imm = this->instr_.ImmValue(bits);
   6354       imm <<= 32 - bits;
   6355       imm >>= 32 - bits;
   6356       next_pc = current_pc + (imm << 2) + kInstrSize;
   6357       set_register(31, current_pc + kInstrSize);
   6358     }
   6359   };
   6360 
   6361   auto BranchCompactHelper = [this, &next_pc](bool do_branch, int bits) {
   6362     int32_t current_pc = get_pc();
   6363     CheckForbiddenSlot(current_pc);
   6364     if (do_branch) {
   6365       int32_t imm = this->instr_.ImmValue(bits);
   6366       imm <<= 32 - bits;
   6367       imm >>= 32 - bits;
   6368       next_pc = get_pc() + (imm << 2) + kInstrSize;
   6369     }
   6370   };
   6371 
   6372   switch (op) {
   6373     // ------------- COP1. Coprocessor instructions.
   6374     case COP1:
   6375       switch (instr_.RsFieldRaw()) {
   6376         case BC1: {  // Branch on coprocessor condition.
   6377           // Floating point.
   6378           uint32_t cc = instr_.FBccValue();
   6379           uint32_t fcsr_cc = get_fcsr_condition_bit(cc);
   6380           uint32_t cc_value = test_fcsr_bit(fcsr_cc);
   6381           bool do_branch = (instr_.FBtrueValue()) ? cc_value : !cc_value;
   6382           BranchHelper(do_branch);
   6383           break;
   6384         }
   6385         case BC1EQZ:
   6386           BranchHelper(!(get_fpu_register(ft_reg) & 0x1));
   6387           break;
   6388         case BC1NEZ:
   6389           BranchHelper(get_fpu_register(ft_reg) & 0x1);
   6390           break;
   6391         case BZ_V: {
   6392           msa_reg_t wt;
   6393           get_msa_register(wt_reg(), &wt);
   6394           BranchHelper_MSA(wt.d[0] == 0 && wt.d[1] == 0);
   6395         } break;
   6396 #define BZ_DF(witdh, lanes)          \
   6397   {                                  \
   6398     msa_reg_t wt;                    \
   6399     get_msa_register(wt_reg(), &wt); \
   6400     int i;                           \
   6401     for (i = 0; i < lanes; ++i) {    \
   6402       if (wt.witdh[i] == 0) {        \
   6403         break;                       \
   6404       }                              \
   6405     }                                \
   6406     BranchHelper_MSA(i != lanes);    \
   6407   }
   6408         case BZ_B:
   6409           BZ_DF(b, kMSALanesByte)
   6410           break;
   6411         case BZ_H:
   6412           BZ_DF(h, kMSALanesHalf)
   6413           break;
   6414         case BZ_W:
   6415           BZ_DF(w, kMSALanesWord)
   6416           break;
   6417         case BZ_D:
   6418           BZ_DF(d, kMSALanesDword)
   6419           break;
   6420 #undef BZ_DF
   6421         case BNZ_V: {
   6422           msa_reg_t wt;
   6423           get_msa_register(wt_reg(), &wt);
   6424           BranchHelper_MSA(wt.d[0] != 0 || wt.d[1] != 0);
   6425         } break;
   6426 #define BNZ_DF(witdh, lanes)         \
   6427   {                                  \
   6428     msa_reg_t wt;                    \
   6429     get_msa_register(wt_reg(), &wt); \
   6430     int i;                           \
   6431     for (i = 0; i < lanes; ++i) {    \
   6432       if (wt.witdh[i] == 0) {        \
   6433         break;                       \
   6434       }                              \
   6435     }                                \
   6436     BranchHelper_MSA(i == lanes);    \
   6437   }
   6438         case BNZ_B:
   6439           BNZ_DF(b, kMSALanesByte)
   6440           break;
   6441         case BNZ_H:
   6442           BNZ_DF(h, kMSALanesHalf)
   6443           break;
   6444         case BNZ_W:
   6445           BNZ_DF(w, kMSALanesWord)
   6446           break;
   6447         case BNZ_D:
   6448           BNZ_DF(d, kMSALanesDword)
   6449           break;
   6450 #undef BNZ_DF
   6451         default:
   6452           UNREACHABLE();
   6453       }
   6454       break;
   6455     // ------------- REGIMM class.
   6456     case REGIMM:
   6457       switch (instr_.RtFieldRaw()) {
   6458         case BLTZ:
   6459           BranchHelper(rs < 0);
   6460           break;
   6461         case BGEZ:
   6462           BranchHelper(rs >= 0);
   6463           break;
   6464         case BLTZAL:
   6465           BranchAndLinkHelper(rs < 0);
   6466           break;
   6467         case BGEZAL:
   6468           BranchAndLinkHelper(rs >= 0);
   6469           break;
   6470         default:
   6471           UNREACHABLE();
   6472       }
   6473       break;  // case REGIMM.
   6474     // ------------- Branch instructions.
   6475     // When comparing to zero, the encoding of rt field is always 0, so we don't
   6476     // need to replace rt with zero.
   6477     case BEQ:
   6478       BranchHelper(rs == rt);
   6479       break;
   6480     case BNE:
   6481       BranchHelper(rs != rt);
   6482       break;
   6483     case POP06:  // BLEZALC, BGEZALC, BGEUC, BLEZ (pre-r6)
   6484       if (IsMipsArchVariant(kMips32r6)) {
   6485         if (rt_reg != 0) {
   6486           if (rs_reg == 0) {  // BLEZALC
   6487             BranchAndLinkCompactHelper(rt <= 0, 16);
   6488           } else {
   6489             if (rs_reg == rt_reg) {  // BGEZALC
   6490               BranchAndLinkCompactHelper(rt >= 0, 16);
   6491             } else {  // BGEUC
   6492               BranchCompactHelper(
   6493                   static_cast<uint32_t>(rs) >= static_cast<uint32_t>(rt), 16);
   6494             }
   6495           }
   6496         } else {  // BLEZ
   6497           BranchHelper(rs <= 0);
   6498         }
   6499       } else {  // BLEZ
   6500         BranchHelper(rs <= 0);
   6501       }
   6502       break;
   6503     case POP07:  // BGTZALC, BLTZALC, BLTUC, BGTZ (pre-r6)
   6504       if (IsMipsArchVariant(kMips32r6)) {
   6505         if (rt_reg != 0) {
   6506           if (rs_reg == 0) {  // BGTZALC
   6507             BranchAndLinkCompactHelper(rt > 0, 16);
   6508           } else {
   6509             if (rt_reg == rs_reg) {  // BLTZALC
   6510               BranchAndLinkCompactHelper(rt < 0, 16);
   6511             } else {  // BLTUC
   6512               BranchCompactHelper(
   6513                   static_cast<uint32_t>(rs) < static_cast<uint32_t>(rt), 16);
   6514             }
   6515           }
   6516         } else {  // BGTZ
   6517           BranchHelper(rs > 0);
   6518         }
   6519       } else {  // BGTZ
   6520         BranchHelper(rs > 0);
   6521       }
   6522       break;
   6523     case POP26:  // BLEZC, BGEZC, BGEC/BLEC / BLEZL (pre-r6)
   6524       if (IsMipsArchVariant(kMips32r6)) {
   6525         if (rt_reg != 0) {
   6526           if (rs_reg == 0) {  // BLEZC
   6527             BranchCompactHelper(rt <= 0, 16);
   6528           } else {
   6529             if (rs_reg == rt_reg) {  // BGEZC
   6530               BranchCompactHelper(rt >= 0, 16);
   6531             } else {  // BGEC/BLEC
   6532               BranchCompactHelper(rs >= rt, 16);
   6533             }
   6534           }
   6535         }
   6536       } else {  // BLEZL
   6537         BranchAndLinkHelper(rs <= 0);
   6538       }
   6539       break;
   6540     case POP27:  // BGTZC, BLTZC, BLTC/BGTC / BGTZL (pre-r6)
   6541       if (IsMipsArchVariant(kMips32r6)) {
   6542         if (rt_reg != 0) {
   6543           if (rs_reg == 0) {  // BGTZC
   6544             BranchCompactHelper(rt > 0, 16);
   6545           } else {
   6546             if (rs_reg == rt_reg) {  // BLTZC
   6547               BranchCompactHelper(rt < 0, 16);
   6548             } else {  // BLTC/BGTC
   6549               BranchCompactHelper(rs < rt, 16);
   6550             }
   6551           }
   6552         }
   6553       } else {  // BGTZL
   6554         BranchAndLinkHelper(rs > 0);
   6555       }
   6556       break;
   6557     case POP66:           // BEQZC, JIC
   6558       if (rs_reg != 0) {  // BEQZC
   6559         BranchCompactHelper(rs == 0, 21);
   6560       } else {  // JIC
   6561         next_pc = rt + imm16;
   6562       }
   6563       break;
   6564     case POP76:           // BNEZC, JIALC
   6565       if (rs_reg != 0) {  // BNEZC
   6566         BranchCompactHelper(rs != 0, 21);
   6567       } else {  // JIALC
   6568         set_register(31, get_pc() + kInstrSize);
   6569         next_pc = rt + imm16;
   6570       }
   6571       break;
   6572     case BC:
   6573       BranchCompactHelper(true, 26);
   6574       break;
   6575     case BALC:
   6576       BranchAndLinkCompactHelper(true, 26);
   6577       break;
   6578     case POP10:  // BOVC, BEQZALC, BEQC / ADDI (pre-r6)
   6579       if (IsMipsArchVariant(kMips32r6)) {
   6580         if (rs_reg >= rt_reg) {  // BOVC
   6581           if (HaveSameSign(rs, rt)) {
   6582             if (rs > 0) {
   6583               BranchCompactHelper(rs > Registers::kMaxValue - rt, 16);
   6584             } else if (rs < 0) {
   6585               BranchCompactHelper(rs < Registers::kMinValue - rt, 16);
   6586             }
   6587           }
   6588         } else {
   6589           if (rs_reg == 0) {  // BEQZALC
   6590             BranchAndLinkCompactHelper(rt == 0, 16);
   6591           } else {  // BEQC
   6592             BranchCompactHelper(rt == rs, 16);
   6593           }
   6594         }
   6595       } else {  // ADDI
   6596         if (HaveSameSign(rs, se_imm16)) {
   6597           if (rs > 0) {
   6598             if (rs <= Registers::kMaxValue - se_imm16) {
   6599               SignalException(kIntegerOverflow);
   6600             }
   6601           } else if (rs < 0) {
   6602             if (rs >= Registers::kMinValue - se_imm16) {
   6603               SignalException(kIntegerUnderflow);
   6604             }
   6605           }
   6606         }
   6607         SetResult(rt_reg, rs + se_imm16);
   6608       }
   6609       break;
   6610     case POP30:  // BNVC, BNEZALC, BNEC / DADDI (pre-r6)
   6611       if (IsMipsArchVariant(kMips32r6)) {
   6612         if (rs_reg >= rt_reg) {  // BNVC
   6613           if (!HaveSameSign(rs, rt) || rs == 0 || rt == 0) {
   6614             BranchCompactHelper(true, 16);
   6615           } else {
   6616             if (rs > 0) {
   6617               BranchCompactHelper(rs <= Registers::kMaxValue - rt, 16);
   6618             } else if (rs < 0) {
   6619               BranchCompactHelper(rs >= Registers::kMinValue - rt, 16);
   6620             }
   6621           }
   6622         } else {
   6623           if (rs_reg == 0) {  // BNEZALC
   6624             BranchAndLinkCompactHelper(rt != 0, 16);
   6625           } else {  // BNEC
   6626             BranchCompactHelper(rt != rs, 16);
   6627           }
   6628         }
   6629       }
   6630       break;
   6631     // ------------- Arithmetic instructions.
   6632     case ADDIU:
   6633       SetResult(rt_reg, rs + se_imm16);
   6634       break;
   6635     case SLTI:
   6636       SetResult(rt_reg, rs < se_imm16 ? 1 : 0);
   6637       break;
   6638     case SLTIU:
   6639       SetResult(rt_reg, rs_u < static_cast<uint32_t>(se_imm16) ? 1 : 0);
   6640       break;
   6641     case ANDI:
   6642       SetResult(rt_reg, rs & oe_imm16);
   6643       break;
   6644     case ORI:
   6645       SetResult(rt_reg, rs | oe_imm16);
   6646       break;
   6647     case XORI:
   6648       SetResult(rt_reg, rs ^ oe_imm16);
   6649       break;
   6650     case LUI:
   6651       if (rs_reg != 0) {
   6652         // AUI
   6653         DCHECK(IsMipsArchVariant(kMips32r6));
   6654         SetResult(rt_reg, rs + (se_imm16 << 16));
   6655       } else {
   6656         // LUI
   6657         SetResult(rt_reg, oe_imm16 << 16);
   6658       }
   6659       break;
   6660     // ------------- Memory instructions.
   6661     case LB:
   6662       set_register(rt_reg, ReadB(rs + se_imm16));
   6663       break;
   6664     case LH:
   6665       set_register(rt_reg, ReadH(rs + se_imm16, instr_.instr()));
   6666       break;
   6667     case LWL: {
   6668       // al_offset is offset of the effective address within an aligned word.
   6669       uint8_t al_offset = (rs + se_imm16) & kPointerAlignmentMask;
   6670       uint8_t byte_shift = kPointerAlignmentMask - al_offset;
   6671       uint32_t mask = (1 << byte_shift * 8) - 1;
   6672       addr = rs + se_imm16 - al_offset;
   6673       alu_out = ReadW(addr, instr_.instr());
   6674       alu_out <<= byte_shift * 8;
   6675       alu_out |= rt & mask;
   6676       set_register(rt_reg, alu_out);
   6677       break;
   6678     }
   6679     case LW:
   6680       set_register(rt_reg, ReadW(rs + se_imm16, instr_.instr()));
   6681       break;
   6682     case LBU:
   6683       set_register(rt_reg, ReadBU(rs + se_imm16));
   6684       break;
   6685     case LHU:
   6686       set_register(rt_reg, ReadHU(rs + se_imm16, instr_.instr()));
   6687       break;
   6688     case LWR: {
   6689       // al_offset is offset of the effective address within an aligned word.
   6690       uint8_t al_offset = (rs + se_imm16) & kPointerAlignmentMask;
   6691       uint8_t byte_shift = kPointerAlignmentMask - al_offset;
   6692       uint32_t mask = al_offset ? (~0 << (byte_shift + 1) * 8) : 0;
   6693       addr = rs + se_imm16 - al_offset;
   6694       alu_out = ReadW(addr, instr_.instr());
   6695       alu_out = static_cast<uint32_t> (alu_out) >> al_offset * 8;
   6696       alu_out |= rt & mask;
   6697       set_register(rt_reg, alu_out);
   6698       break;
   6699     }
   6700     case SB:
   6701       WriteB(rs + se_imm16, static_cast<int8_t>(rt));
   6702       break;
   6703     case SH:
   6704       WriteH(rs + se_imm16, static_cast<uint16_t>(rt), instr_.instr());
   6705       break;
   6706     case SWL: {
   6707       uint8_t al_offset = (rs + se_imm16) & kPointerAlignmentMask;
   6708       uint8_t byte_shift = kPointerAlignmentMask - al_offset;
   6709       uint32_t mask = byte_shift ? (~0 << (al_offset + 1) * 8) : 0;
   6710       addr = rs + se_imm16 - al_offset;
   6711       // Value to be written in memory.
   6712       uint32_t mem_value = ReadW(addr, instr_.instr()) & mask;
   6713       mem_value |= static_cast<uint32_t>(rt) >> byte_shift * 8;
   6714       WriteW(addr, mem_value, instr_.instr());
   6715       break;
   6716     }
   6717     case SW:
   6718       WriteW(rs + se_imm16, rt, instr_.instr());
   6719       break;
   6720     case SWR: {
   6721       uint8_t al_offset = (rs + se_imm16) & kPointerAlignmentMask;
   6722       uint32_t mask = (1 << al_offset * 8) - 1;
   6723       addr = rs + se_imm16 - al_offset;
   6724       uint32_t mem_value = ReadW(addr, instr_.instr());
   6725       mem_value = (rt << al_offset * 8) | (mem_value & mask);
   6726       WriteW(addr, mem_value, instr_.instr());
   6727       break;
   6728     }
   6729     case LL: {
   6730       // LL/SC sequence cannot be simulated properly
   6731       DCHECK(!IsMipsArchVariant(kMips32r6));
   6732       set_register(rt_reg, ReadW(rs + se_imm16, instr_.instr()));
   6733       break;
   6734     }
   6735     case SC: {
   6736       // LL/SC sequence cannot be simulated properly
   6737       DCHECK(!IsMipsArchVariant(kMips32r6));
   6738       WriteW(rs + se_imm16, rt, instr_.instr());
   6739       set_register(rt_reg, 1);
   6740       break;
   6741     }
   6742     case LWC1:
   6743       set_fpu_register_hi_word(ft_reg, 0);
   6744       set_fpu_register_word(ft_reg,
   6745                             ReadW(rs + se_imm16, instr_.instr(), FLOAT));
   6746       if (ft_reg % 2) {
   6747         TraceMemRd(rs + se_imm16, get_fpu_register(ft_reg - 1), FLOAT_DOUBLE);
   6748       } else {
   6749         TraceMemRd(rs + se_imm16, get_fpu_register_word(ft_reg), FLOAT);
   6750       }
   6751       break;
   6752     case LDC1:
   6753       set_fpu_register_double(ft_reg, ReadD(rs + se_imm16, instr_.instr()));
   6754       TraceMemRd(rs + se_imm16, get_fpu_register(ft_reg), DOUBLE);
   6755       break;
   6756     case SWC1:
   6757       WriteW(rs + se_imm16, get_fpu_register_word(ft_reg), instr_.instr());
   6758       TraceMemWr(rs + se_imm16, get_fpu_register_word(ft_reg));
   6759       break;
   6760     case SDC1:
   6761       WriteD(rs + se_imm16, get_fpu_register_double(ft_reg), instr_.instr());
   6762       TraceMemWr(rs + se_imm16, get_fpu_register(ft_reg));
   6763       break;
   6764     // ------------- PC-Relative instructions.
   6765     case PCREL: {
   6766       // rt field: checking 5-bits.
   6767       int32_t imm21 = instr_.Imm21Value();
   6768       int32_t current_pc = get_pc();
   6769       uint8_t rt = (imm21 >> kImm16Bits);
   6770       switch (rt) {
   6771         case ALUIPC:
   6772           addr = current_pc + (se_imm16 << 16);
   6773           alu_out = static_cast<int64_t>(~0x0FFFF) & addr;
   6774           break;
   6775         case AUIPC:
   6776           alu_out = current_pc + (se_imm16 << 16);
   6777           break;
   6778         default: {
   6779           int32_t imm19 = instr_.Imm19Value();
   6780           // rt field: checking the most significant 2-bits.
   6781           rt = (imm21 >> kImm19Bits);
   6782           switch (rt) {
   6783             case LWPC: {
   6784               // Set sign.
   6785               imm19 <<= (kOpcodeBits + kRsBits + 2);
   6786               imm19 >>= (kOpcodeBits + kRsBits + 2);
   6787               addr = current_pc + (imm19 << 2);
   6788               uint32_t* ptr = reinterpret_cast<uint32_t*>(addr);
   6789               alu_out = *ptr;
   6790               break;
   6791             }
   6792             case ADDIUPC: {
   6793               int32_t se_imm19 = imm19 | ((imm19 & 0x40000) ? 0xFFF80000 : 0);
   6794               alu_out = current_pc + (se_imm19 << 2);
   6795               break;
   6796             }
   6797             default:
   6798               UNREACHABLE();
   6799               break;
   6800           }
   6801         }
   6802       }
   6803       SetResult(rs_reg, alu_out);
   6804       break;
   6805     }
   6806     case SPECIAL3: {
   6807       switch (instr_.FunctionFieldRaw()) {
   6808         case LL_R6: {
   6809           // LL/SC sequence cannot be simulated properly
   6810           DCHECK(IsMipsArchVariant(kMips32r6));
   6811           int32_t base = get_register(instr_.BaseValue());
   6812           int32_t offset9 = instr_.Imm9Value();
   6813           set_register(rt_reg, ReadW(base + offset9, instr_.instr()));
   6814           break;
   6815         }
   6816         case SC_R6: {
   6817           // LL/SC sequence cannot be simulated properly
   6818           DCHECK(IsMipsArchVariant(kMips32r6));
   6819           int32_t base = get_register(instr_.BaseValue());
   6820           int32_t offset9 = instr_.Imm9Value();
   6821           WriteW(base + offset9, rt, instr_.instr());
   6822           set_register(rt_reg, 1);
   6823           break;
   6824         }
   6825         default:
   6826           UNREACHABLE();
   6827       }
   6828       break;
   6829     }
   6830     case MSA:
   6831       switch (instr_.MSAMinorOpcodeField()) {
   6832         case kMsaMinorI8:
   6833           DecodeTypeMsaI8();
   6834           break;
   6835         case kMsaMinorI5:
   6836           DecodeTypeMsaI5();
   6837           break;
   6838         case kMsaMinorI10:
   6839           DecodeTypeMsaI10();
   6840           break;
   6841         case kMsaMinorELM:
   6842           DecodeTypeMsaELM();
   6843           break;
   6844         case kMsaMinorBIT:
   6845           DecodeTypeMsaBIT();
   6846           break;
   6847         case kMsaMinorMI10:
   6848           DecodeTypeMsaMI10();
   6849           break;
   6850         default:
   6851           UNREACHABLE();
   6852           break;
   6853       }
   6854       break;
   6855     default:
   6856       UNREACHABLE();
   6857   }
   6858 
   6859   if (execute_branch_delay_instruction) {
   6860     // Execute branch delay slot
   6861     // We don't check for end_sim_pc. First it should not be met as the current
   6862     // pc is valid. Secondly a jump should always execute its branch delay slot.
   6863     Instruction* branch_delay_instr =
   6864         reinterpret_cast<Instruction*>(get_pc() + kInstrSize);
   6865     BranchDelayInstructionDecode(branch_delay_instr);
   6866   }
   6867 
   6868   // If needed update pc after the branch delay execution.
   6869   if (next_pc != bad_ra) {
   6870     set_pc(next_pc);
   6871   }
   6872 }
   6873 
   6874 
   6875 // Type 3: instructions using a 26 bytes immediate. (e.g. j, jal).
   6876 void Simulator::DecodeTypeJump() {
   6877   SimInstruction simInstr = instr_;
   6878   // Get current pc.
   6879   int32_t current_pc = get_pc();
   6880   // Get unchanged bits of pc.
   6881   int32_t pc_high_bits = current_pc & 0xF0000000;
   6882   // Next pc.
   6883 
   6884   int32_t next_pc = pc_high_bits | (simInstr.Imm26Value() << 2);
   6885 
   6886   // Execute branch delay slot.
   6887   // We don't check for end_sim_pc. First it should not be met as the current pc
   6888   // is valid. Secondly a jump should always execute its branch delay slot.
   6889   Instruction* branch_delay_instr =
   6890       reinterpret_cast<Instruction*>(current_pc + kInstrSize);
   6891   BranchDelayInstructionDecode(branch_delay_instr);
   6892 
   6893   // Update pc and ra if necessary.
   6894   // Do this after the branch delay execution.
   6895   if (simInstr.IsLinkingInstruction()) {
   6896     set_register(31, current_pc + 2 * kInstrSize);
   6897   }
   6898   set_pc(next_pc);
   6899   pc_modified_ = true;
   6900 }
   6901 
   6902 
   6903 // Executes the current instruction.
   6904 void Simulator::InstructionDecode(Instruction* instr) {
   6905   if (v8::internal::FLAG_check_icache) {
   6906     CheckICache(i_cache(), instr);
   6907   }
   6908   pc_modified_ = false;
   6909   v8::internal::EmbeddedVector<char, 256> buffer;
   6910   if (::v8::internal::FLAG_trace_sim) {
   6911     SNPrintF(trace_buf_, "%s", "");
   6912     disasm::NameConverter converter;
   6913     disasm::Disassembler dasm(converter);
   6914     dasm.InstructionDecode(buffer, reinterpret_cast<byte*>(instr));
   6915   }
   6916 
   6917   instr_ = instr;
   6918   switch (instr_.InstructionType()) {
   6919     case Instruction::kRegisterType:
   6920       DecodeTypeRegister();
   6921       break;
   6922     case Instruction::kImmediateType:
   6923       DecodeTypeImmediate();
   6924       break;
   6925     case Instruction::kJumpType:
   6926       DecodeTypeJump();
   6927       break;
   6928     default:
   6929       UNSUPPORTED();
   6930   }
   6931   if (::v8::internal::FLAG_trace_sim) {
   6932     PrintF("  0x%08" PRIxPTR "  %-44s   %s\n",
   6933            reinterpret_cast<intptr_t>(instr), buffer.start(),
   6934            trace_buf_.start());
   6935   }
   6936   if (!pc_modified_) {
   6937     set_register(pc, reinterpret_cast<int32_t>(instr) + kInstrSize);
   6938   }
   6939 }
   6940 
   6941 void Simulator::Execute() {
   6942   // Get the PC to simulate. Cannot use the accessor here as we need the
   6943   // raw PC value and not the one used as input to arithmetic instructions.
   6944   int program_counter = get_pc();
   6945   if (::v8::internal::FLAG_stop_sim_at == 0) {
   6946     // Fast version of the dispatch loop without checking whether the simulator
   6947     // should be stopping at a particular executed instruction.
   6948     while (program_counter != end_sim_pc) {
   6949       Instruction* instr = reinterpret_cast<Instruction*>(program_counter);
   6950       icount_++;
   6951       InstructionDecode(instr);
   6952       program_counter = get_pc();
   6953     }
   6954   } else {
   6955     // FLAG_stop_sim_at is at the non-default value. Stop in the debugger when
   6956     // we reach the particular instruction count.
   6957     while (program_counter != end_sim_pc) {
   6958       Instruction* instr = reinterpret_cast<Instruction*>(program_counter);
   6959       icount_++;
   6960       if (icount_ == static_cast<uint64_t>(::v8::internal::FLAG_stop_sim_at)) {
   6961         MipsDebugger dbg(this);
   6962         dbg.Debug();
   6963       } else {
   6964         InstructionDecode(instr);
   6965       }
   6966       program_counter = get_pc();
   6967     }
   6968   }
   6969 }
   6970 
   6971 void Simulator::CallInternal(Address entry) {
   6972   // Adjust JS-based stack limit to C-based stack limit.
   6973   isolate_->stack_guard()->AdjustStackLimitForSimulator();
   6974 
   6975   // Prepare to execute the code at entry.
   6976   set_register(pc, static_cast<int32_t>(entry));
   6977   // Put down marker for end of simulation. The simulator will stop simulation
   6978   // when the PC reaches this value. By saving the "end simulation" value into
   6979   // the LR the simulation stops when returning to this call point.
   6980   set_register(ra, end_sim_pc);
   6981 
   6982   // Remember the values of callee-saved registers.
   6983   // The code below assumes that r9 is not used as sb (static base) in
   6984   // simulator code and therefore is regarded as a callee-saved register.
   6985   int32_t s0_val = get_register(s0);
   6986   int32_t s1_val = get_register(s1);
   6987   int32_t s2_val = get_register(s2);
   6988   int32_t s3_val = get_register(s3);
   6989   int32_t s4_val = get_register(s4);
   6990   int32_t s5_val = get_register(s5);
   6991   int32_t s6_val = get_register(s6);
   6992   int32_t s7_val = get_register(s7);
   6993   int32_t gp_val = get_register(gp);
   6994   int32_t sp_val = get_register(sp);
   6995   int32_t fp_val = get_register(fp);
   6996 
   6997   // Set up the callee-saved registers with a known value. To be able to check
   6998   // that they are preserved properly across JS execution.
   6999   int32_t callee_saved_value = static_cast<int32_t>(icount_);
   7000   set_register(s0, callee_saved_value);
   7001   set_register(s1, callee_saved_value);
   7002   set_register(s2, callee_saved_value);
   7003   set_register(s3, callee_saved_value);
   7004   set_register(s4, callee_saved_value);
   7005   set_register(s5, callee_saved_value);
   7006   set_register(s6, callee_saved_value);
   7007   set_register(s7, callee_saved_value);
   7008   set_register(gp, callee_saved_value);
   7009   set_register(fp, callee_saved_value);
   7010 
   7011   // Start the simulation.
   7012   Execute();
   7013 
   7014   // Check that the callee-saved registers have been preserved.
   7015   CHECK_EQ(callee_saved_value, get_register(s0));
   7016   CHECK_EQ(callee_saved_value, get_register(s1));
   7017   CHECK_EQ(callee_saved_value, get_register(s2));
   7018   CHECK_EQ(callee_saved_value, get_register(s3));
   7019   CHECK_EQ(callee_saved_value, get_register(s4));
   7020   CHECK_EQ(callee_saved_value, get_register(s5));
   7021   CHECK_EQ(callee_saved_value, get_register(s6));
   7022   CHECK_EQ(callee_saved_value, get_register(s7));
   7023   CHECK_EQ(callee_saved_value, get_register(gp));
   7024   CHECK_EQ(callee_saved_value, get_register(fp));
   7025 
   7026   // Restore callee-saved registers with the original value.
   7027   set_register(s0, s0_val);
   7028   set_register(s1, s1_val);
   7029   set_register(s2, s2_val);
   7030   set_register(s3, s3_val);
   7031   set_register(s4, s4_val);
   7032   set_register(s5, s5_val);
   7033   set_register(s6, s6_val);
   7034   set_register(s7, s7_val);
   7035   set_register(gp, gp_val);
   7036   set_register(sp, sp_val);
   7037   set_register(fp, fp_val);
   7038 }
   7039 
   7040 intptr_t Simulator::CallImpl(Address entry, int argument_count,
   7041                              const intptr_t* arguments) {
   7042   // Set up arguments.
   7043 
   7044   // First four arguments passed in registers.
   7045   int reg_arg_count = std::min(4, argument_count);
   7046   if (reg_arg_count > 0) set_register(a0, arguments[0]);
   7047   if (reg_arg_count > 1) set_register(a1, arguments[1]);
   7048   if (reg_arg_count > 2) set_register(a2, arguments[2]);
   7049   if (reg_arg_count > 3) set_register(a3, arguments[3]);
   7050 
   7051   // Remaining arguments passed on stack.
   7052   int original_stack = get_register(sp);
   7053   // Compute position of stack on entry to generated code.
   7054   int entry_stack = (original_stack - (argument_count - 4) * sizeof(int32_t)
   7055                                     - kCArgsSlotsSize);
   7056   if (base::OS::ActivationFrameAlignment() != 0) {
   7057     entry_stack &= -base::OS::ActivationFrameAlignment();
   7058   }
   7059   // Store remaining arguments on stack, from low to high memory.
   7060   intptr_t* stack_argument = reinterpret_cast<intptr_t*>(entry_stack);
   7061   memcpy(stack_argument + kCArgSlotCount, arguments + reg_arg_count,
   7062          (argument_count - reg_arg_count) * sizeof(*arguments));
   7063   set_register(sp, entry_stack);
   7064 
   7065   CallInternal(entry);
   7066 
   7067   // Pop stack passed arguments.
   7068   CHECK_EQ(entry_stack, get_register(sp));
   7069   set_register(sp, original_stack);
   7070 
   7071   return get_register(v0);
   7072 }
   7073 
   7074 double Simulator::CallFP(Address entry, double d0, double d1) {
   7075   if (!IsMipsSoftFloatABI) {
   7076     set_fpu_register_double(f12, d0);
   7077     set_fpu_register_double(f14, d1);
   7078   } else {
   7079     int buffer[2];
   7080     DCHECK(sizeof(buffer[0]) * 2 == sizeof(d0));
   7081     memcpy(buffer, &d0, sizeof(d0));
   7082     set_dw_register(a0, buffer);
   7083     memcpy(buffer, &d1, sizeof(d1));
   7084     set_dw_register(a2, buffer);
   7085   }
   7086   CallInternal(entry);
   7087   if (!IsMipsSoftFloatABI) {
   7088     return get_fpu_register_double(f0);
   7089   } else {
   7090     return get_double_from_register_pair(v0);
   7091   }
   7092 }
   7093 
   7094 
   7095 uintptr_t Simulator::PushAddress(uintptr_t address) {
   7096   int new_sp = get_register(sp) - sizeof(uintptr_t);
   7097   uintptr_t* stack_slot = reinterpret_cast<uintptr_t*>(new_sp);
   7098   *stack_slot = address;
   7099   set_register(sp, new_sp);
   7100   return new_sp;
   7101 }
   7102 
   7103 
   7104 uintptr_t Simulator::PopAddress() {
   7105   int current_sp = get_register(sp);
   7106   uintptr_t* stack_slot = reinterpret_cast<uintptr_t*>(current_sp);
   7107   uintptr_t address = *stack_slot;
   7108   set_register(sp, current_sp + sizeof(uintptr_t));
   7109   return address;
   7110 }
   7111 
   7112 
   7113 #undef UNSUPPORTED
   7114 
   7115 }  // namespace internal
   7116 }  // namespace v8
   7117 
   7118 #endif  // USE_SIMULATOR
   7119 
   7120 #endif  // V8_TARGET_ARCH_MIPS
   7121