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