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