Home | History | Annotate | Download | only in mips
      1 // Copyright 2010 the V8 project authors. All rights reserved.
      2 // Redistribution and use in source and binary forms, with or without
      3 // modification, are permitted provided that the following conditions are
      4 // met:
      5 //
      6 //     * Redistributions of source code must retain the above copyright
      7 //       notice, this list of conditions and the following disclaimer.
      8 //     * Redistributions in binary form must reproduce the above
      9 //       copyright notice, this list of conditions and the following
     10 //       disclaimer in the documentation and/or other materials provided
     11 //       with the distribution.
     12 //     * Neither the name of Google Inc. nor the names of its
     13 //       contributors may be used to endorse or promote products derived
     14 //       from this software without specific prior written permission.
     15 //
     16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     27 
     28 #include <stdlib.h>
     29 #include <cstdarg>
     30 #include "v8.h"
     31 
     32 #include "disasm.h"
     33 #include "assembler.h"
     34 #include "globals.h"    // Need the bit_cast
     35 #include "mips/constants-mips.h"
     36 #include "mips/simulator-mips.h"
     37 
     38 namespace v8i = v8::internal;
     39 
     40 #if !defined(__mips)
     41 
     42 // Only build the simulator if not compiling for real MIPS hardware.
     43 namespace assembler {
     44 namespace mips {
     45 
     46 using ::v8::internal::Object;
     47 using ::v8::internal::PrintF;
     48 using ::v8::internal::OS;
     49 using ::v8::internal::ReadLine;
     50 using ::v8::internal::DeleteArray;
     51 
     52 // Utils functions
     53 bool HaveSameSign(int32_t a, int32_t b) {
     54   return ((a ^ b) > 0);
     55 }
     56 
     57 
     58 // This macro provides a platform independent use of sscanf. The reason for
     59 // SScanF not being implemented in a platform independent was through
     60 // ::v8::internal::OS in the same way as SNPrintF is that the Windows C Run-Time
     61 // Library does not provide vsscanf.
     62 #define SScanF sscanf  // NOLINT
     63 
     64 // The Debugger class is used by the simulator while debugging simulated MIPS
     65 // code.
     66 class Debugger {
     67  public:
     68   explicit Debugger(Simulator* sim);
     69   ~Debugger();
     70 
     71   void Stop(Instruction* instr);
     72   void Debug();
     73 
     74  private:
     75   // We set the breakpoint code to 0xfffff to easily recognize it.
     76   static const Instr kBreakpointInstr = SPECIAL | BREAK | 0xfffff << 6;
     77   static const Instr kNopInstr =  0x0;
     78 
     79   Simulator* sim_;
     80 
     81   int32_t GetRegisterValue(int regnum);
     82   bool GetValue(const char* desc, int32_t* value);
     83 
     84   // Set or delete a breakpoint. Returns true if successful.
     85   bool SetBreakpoint(Instruction* breakpc);
     86   bool DeleteBreakpoint(Instruction* breakpc);
     87 
     88   // Undo and redo all breakpoints. This is needed to bracket disassembly and
     89   // execution to skip past breakpoints when run from the debugger.
     90   void UndoBreakpoints();
     91   void RedoBreakpoints();
     92 
     93   // Print all registers with a nice formatting.
     94   void PrintAllRegs();
     95 };
     96 
     97 Debugger::Debugger(Simulator* sim) {
     98   sim_ = sim;
     99 }
    100 
    101 Debugger::~Debugger() {
    102 }
    103 
    104 #ifdef GENERATED_CODE_COVERAGE
    105 static FILE* coverage_log = NULL;
    106 
    107 
    108 static void InitializeCoverage() {
    109   char* file_name = getenv("V8_GENERATED_CODE_COVERAGE_LOG");
    110   if (file_name != NULL) {
    111     coverage_log = fopen(file_name, "aw+");
    112   }
    113 }
    114 
    115 
    116 void Debugger::Stop(Instruction* instr) {
    117   UNIMPLEMENTED_MIPS();
    118   char* str = reinterpret_cast<char*>(instr->InstructionBits());
    119   if (strlen(str) > 0) {
    120     if (coverage_log != NULL) {
    121       fprintf(coverage_log, "%s\n", str);
    122       fflush(coverage_log);
    123     }
    124     instr->SetInstructionBits(0x0);  // Overwrite with nop.
    125   }
    126   sim_->set_pc(sim_->get_pc() + Instruction::kInstructionSize);
    127 }
    128 
    129 #else  // ndef GENERATED_CODE_COVERAGE
    130 
    131 #define UNSUPPORTED() printf("Unsupported instruction.\n");
    132 
    133 static void InitializeCoverage() {}
    134 
    135 
    136 void Debugger::Stop(Instruction* instr) {
    137   const char* str = reinterpret_cast<char*>(instr->InstructionBits());
    138   PrintF("Simulator hit %s\n", str);
    139   sim_->set_pc(sim_->get_pc() + Instruction::kInstructionSize);
    140   Debug();
    141 }
    142 #endif  // def GENERATED_CODE_COVERAGE
    143 
    144 
    145 int32_t Debugger::GetRegisterValue(int regnum) {
    146   if (regnum == kNumSimuRegisters) {
    147     return sim_->get_pc();
    148   } else {
    149     return sim_->get_register(regnum);
    150   }
    151 }
    152 
    153 
    154 bool Debugger::GetValue(const char* desc, int32_t* value) {
    155   int regnum = Registers::Number(desc);
    156   if (regnum != kInvalidRegister) {
    157     *value = GetRegisterValue(regnum);
    158     return true;
    159   } else {
    160     return SScanF(desc, "%i", value) == 1;
    161   }
    162   return false;
    163 }
    164 
    165 
    166 bool Debugger::SetBreakpoint(Instruction* breakpc) {
    167   // Check if a breakpoint can be set. If not return without any side-effects.
    168   if (sim_->break_pc_ != NULL) {
    169     return false;
    170   }
    171 
    172   // Set the breakpoint.
    173   sim_->break_pc_ = breakpc;
    174   sim_->break_instr_ = breakpc->InstructionBits();
    175   // Not setting the breakpoint instruction in the code itself. It will be set
    176   // when the debugger shell continues.
    177   return true;
    178 }
    179 
    180 
    181 bool Debugger::DeleteBreakpoint(Instruction* breakpc) {
    182   if (sim_->break_pc_ != NULL) {
    183     sim_->break_pc_->SetInstructionBits(sim_->break_instr_);
    184   }
    185 
    186   sim_->break_pc_ = NULL;
    187   sim_->break_instr_ = 0;
    188   return true;
    189 }
    190 
    191 
    192 void Debugger::UndoBreakpoints() {
    193   if (sim_->break_pc_ != NULL) {
    194     sim_->break_pc_->SetInstructionBits(sim_->break_instr_);
    195   }
    196 }
    197 
    198 
    199 void Debugger::RedoBreakpoints() {
    200   if (sim_->break_pc_ != NULL) {
    201     sim_->break_pc_->SetInstructionBits(kBreakpointInstr);
    202   }
    203 }
    204 
    205 void Debugger::PrintAllRegs() {
    206 #define REG_INFO(n) Registers::Name(n), GetRegisterValue(n), GetRegisterValue(n)
    207 
    208   PrintF("\n");
    209   // at, v0, a0
    210   PrintF("%3s: 0x%08x %10d\t%3s: 0x%08x %10d\t%3s: 0x%08x %10d\n",
    211          REG_INFO(1), REG_INFO(2), REG_INFO(4));
    212   // v1, a1
    213   PrintF("%26s\t%3s: 0x%08x %10d\t%3s: 0x%08x %10d\n",
    214          "", REG_INFO(3), REG_INFO(5));
    215   // a2
    216   PrintF("%26s\t%26s\t%3s: 0x%08x %10d\n", "", "", REG_INFO(6));
    217   // a3
    218   PrintF("%26s\t%26s\t%3s: 0x%08x %10d\n", "", "", REG_INFO(7));
    219   PrintF("\n");
    220   // t0-t7, s0-s7
    221   for (int i = 0; i < 8; i++) {
    222     PrintF("%3s: 0x%08x %10d\t%3s: 0x%08x %10d\n",
    223            REG_INFO(8+i), REG_INFO(16+i));
    224   }
    225   PrintF("\n");
    226   // t8, k0, LO
    227   PrintF("%3s: 0x%08x %10d\t%3s: 0x%08x %10d\t%3s: 0x%08x %10d\n",
    228          REG_INFO(24), REG_INFO(26), REG_INFO(32));
    229   // t9, k1, HI
    230   PrintF("%3s: 0x%08x %10d\t%3s: 0x%08x %10d\t%3s: 0x%08x %10d\n",
    231          REG_INFO(25), REG_INFO(27), REG_INFO(33));
    232   // sp, fp, gp
    233   PrintF("%3s: 0x%08x %10d\t%3s: 0x%08x %10d\t%3s: 0x%08x %10d\n",
    234          REG_INFO(29), REG_INFO(30), REG_INFO(28));
    235   // pc
    236   PrintF("%3s: 0x%08x %10d\t%3s: 0x%08x %10d\n",
    237          REG_INFO(31), REG_INFO(34));
    238 #undef REG_INFO
    239 }
    240 
    241 void Debugger::Debug() {
    242   intptr_t last_pc = -1;
    243   bool done = false;
    244 
    245 #define COMMAND_SIZE 63
    246 #define ARG_SIZE 255
    247 
    248 #define STR(a) #a
    249 #define XSTR(a) STR(a)
    250 
    251   char cmd[COMMAND_SIZE + 1];
    252   char arg1[ARG_SIZE + 1];
    253   char arg2[ARG_SIZE + 1];
    254 
    255   // make sure to have a proper terminating character if reaching the limit
    256   cmd[COMMAND_SIZE] = 0;
    257   arg1[ARG_SIZE] = 0;
    258   arg2[ARG_SIZE] = 0;
    259 
    260   // Undo all set breakpoints while running in the debugger shell. This will
    261   // make them invisible to all commands.
    262   UndoBreakpoints();
    263 
    264   while (!done && (sim_->get_pc() != Simulator::end_sim_pc)) {
    265     if (last_pc != sim_->get_pc()) {
    266       disasm::NameConverter converter;
    267       disasm::Disassembler dasm(converter);
    268       // use a reasonably large buffer
    269       v8::internal::EmbeddedVector<char, 256> buffer;
    270       dasm.InstructionDecode(buffer,
    271                              reinterpret_cast<byte_*>(sim_->get_pc()));
    272       PrintF("  0x%08x  %s\n", sim_->get_pc(), buffer.start());
    273       last_pc = sim_->get_pc();
    274     }
    275     char* line = ReadLine("sim> ");
    276     if (line == NULL) {
    277       break;
    278     } else {
    279       // Use sscanf to parse the individual parts of the command line. At the
    280       // moment no command expects more than two parameters.
    281       int args = SScanF(line,
    282                         "%" XSTR(COMMAND_SIZE) "s "
    283                         "%" XSTR(ARG_SIZE) "s "
    284                         "%" XSTR(ARG_SIZE) "s",
    285                         cmd, arg1, arg2);
    286       if ((strcmp(cmd, "si") == 0) || (strcmp(cmd, "stepi") == 0)) {
    287         if (!(reinterpret_cast<Instruction*>(sim_->get_pc())->IsTrap())) {
    288           sim_->InstructionDecode(
    289                                 reinterpret_cast<Instruction*>(sim_->get_pc()));
    290         } else {
    291           // Allow si to jump over generated breakpoints.
    292           PrintF("/!\\ Jumping over generated breakpoint.\n");
    293           sim_->set_pc(sim_->get_pc() + Instruction::kInstructionSize);
    294         }
    295       } else if ((strcmp(cmd, "c") == 0) || (strcmp(cmd, "cont") == 0)) {
    296         // Execute the one instruction we broke at with breakpoints disabled.
    297         sim_->InstructionDecode(reinterpret_cast<Instruction*>(sim_->get_pc()));
    298         // Leave the debugger shell.
    299         done = true;
    300       } else if ((strcmp(cmd, "p") == 0) || (strcmp(cmd, "print") == 0)) {
    301         if (args == 2) {
    302           int32_t value;
    303           if (strcmp(arg1, "all") == 0) {
    304             PrintAllRegs();
    305           } else {
    306             if (GetValue(arg1, &value)) {
    307               PrintF("%s: 0x%08x %d \n", arg1, value, value);
    308             } else {
    309               PrintF("%s unrecognized\n", arg1);
    310             }
    311           }
    312         } else {
    313           PrintF("print <register>\n");
    314         }
    315       } else if ((strcmp(cmd, "po") == 0)
    316                  || (strcmp(cmd, "printobject") == 0)) {
    317         if (args == 2) {
    318           int32_t value;
    319           if (GetValue(arg1, &value)) {
    320             Object* obj = reinterpret_cast<Object*>(value);
    321             PrintF("%s: \n", arg1);
    322 #ifdef DEBUG
    323             obj->PrintLn();
    324 #else
    325             obj->ShortPrint();
    326             PrintF("\n");
    327 #endif
    328           } else {
    329             PrintF("%s unrecognized\n", arg1);
    330           }
    331         } else {
    332           PrintF("printobject <value>\n");
    333         }
    334       } else if ((strcmp(cmd, "disasm") == 0) || (strcmp(cmd, "dpc") == 0)) {
    335         disasm::NameConverter converter;
    336         disasm::Disassembler dasm(converter);
    337         // use a reasonably large buffer
    338         v8::internal::EmbeddedVector<char, 256> buffer;
    339 
    340         byte_* cur = NULL;
    341         byte_* end = NULL;
    342 
    343         if (args == 1) {
    344           cur = reinterpret_cast<byte_*>(sim_->get_pc());
    345           end = cur + (10 * Instruction::kInstructionSize);
    346         } else if (args == 2) {
    347           int32_t value;
    348           if (GetValue(arg1, &value)) {
    349             cur = reinterpret_cast<byte_*>(value);
    350             // no length parameter passed, assume 10 instructions
    351             end = cur + (10 * Instruction::kInstructionSize);
    352           }
    353         } else {
    354           int32_t value1;
    355           int32_t value2;
    356           if (GetValue(arg1, &value1) && GetValue(arg2, &value2)) {
    357             cur = reinterpret_cast<byte_*>(value1);
    358             end = cur + (value2 * Instruction::kInstructionSize);
    359           }
    360         }
    361 
    362         while (cur < end) {
    363           dasm.InstructionDecode(buffer, cur);
    364           PrintF("  0x%08x  %s\n", cur, buffer.start());
    365           cur += Instruction::kInstructionSize;
    366         }
    367       } else if (strcmp(cmd, "gdb") == 0) {
    368         PrintF("relinquishing control to gdb\n");
    369         v8::internal::OS::DebugBreak();
    370         PrintF("regaining control from gdb\n");
    371       } else if (strcmp(cmd, "break") == 0) {
    372         if (args == 2) {
    373           int32_t value;
    374           if (GetValue(arg1, &value)) {
    375             if (!SetBreakpoint(reinterpret_cast<Instruction*>(value))) {
    376               PrintF("setting breakpoint failed\n");
    377             }
    378           } else {
    379             PrintF("%s unrecognized\n", arg1);
    380           }
    381         } else {
    382           PrintF("break <address>\n");
    383         }
    384       } else if (strcmp(cmd, "del") == 0) {
    385         if (!DeleteBreakpoint(NULL)) {
    386           PrintF("deleting breakpoint failed\n");
    387         }
    388       } else if (strcmp(cmd, "flags") == 0) {
    389         PrintF("No flags on MIPS !\n");
    390       } else if (strcmp(cmd, "unstop") == 0) {
    391           PrintF("Unstop command not implemented on MIPS.");
    392       } else if ((strcmp(cmd, "stat") == 0) || (strcmp(cmd, "st") == 0)) {
    393         // Print registers and disassemble
    394         PrintAllRegs();
    395         PrintF("\n");
    396 
    397         disasm::NameConverter converter;
    398         disasm::Disassembler dasm(converter);
    399         // use a reasonably large buffer
    400         v8::internal::EmbeddedVector<char, 256> buffer;
    401 
    402         byte_* cur = NULL;
    403         byte_* end = NULL;
    404 
    405         if (args == 1) {
    406           cur = reinterpret_cast<byte_*>(sim_->get_pc());
    407           end = cur + (10 * Instruction::kInstructionSize);
    408         } else if (args == 2) {
    409           int32_t value;
    410           if (GetValue(arg1, &value)) {
    411             cur = reinterpret_cast<byte_*>(value);
    412             // no length parameter passed, assume 10 instructions
    413             end = cur + (10 * Instruction::kInstructionSize);
    414           }
    415         } else {
    416           int32_t value1;
    417           int32_t value2;
    418           if (GetValue(arg1, &value1) && GetValue(arg2, &value2)) {
    419             cur = reinterpret_cast<byte_*>(value1);
    420             end = cur + (value2 * Instruction::kInstructionSize);
    421           }
    422         }
    423 
    424         while (cur < end) {
    425           dasm.InstructionDecode(buffer, cur);
    426           PrintF("  0x%08x  %s\n", cur, buffer.start());
    427           cur += Instruction::kInstructionSize;
    428         }
    429       } else if ((strcmp(cmd, "h") == 0) || (strcmp(cmd, "help") == 0)) {
    430         PrintF("cont\n");
    431         PrintF("  continue execution (alias 'c')\n");
    432         PrintF("stepi\n");
    433         PrintF("  step one instruction (alias 'si')\n");
    434         PrintF("print <register>\n");
    435         PrintF("  print register content (alias 'p')\n");
    436         PrintF("  use register name 'all' to print all registers\n");
    437         PrintF("printobject <register>\n");
    438         PrintF("  print an object from a register (alias 'po')\n");
    439         PrintF("flags\n");
    440         PrintF("  print flags\n");
    441         PrintF("disasm [<instructions>]\n");
    442         PrintF("disasm [[<address>] <instructions>]\n");
    443         PrintF("  disassemble code, default is 10 instructions from pc\n");
    444         PrintF("gdb\n");
    445         PrintF("  enter gdb\n");
    446         PrintF("break <address>\n");
    447         PrintF("  set a break point on the address\n");
    448         PrintF("del\n");
    449         PrintF("  delete the breakpoint\n");
    450         PrintF("unstop\n");
    451         PrintF("  ignore the stop instruction at the current location");
    452         PrintF(" from now on\n");
    453       } else {
    454         PrintF("Unknown command: %s\n", cmd);
    455       }
    456     }
    457     DeleteArray(line);
    458   }
    459 
    460   // Add all the breakpoints back to stop execution and enter the debugger
    461   // shell when hit.
    462   RedoBreakpoints();
    463 
    464 #undef COMMAND_SIZE
    465 #undef ARG_SIZE
    466 
    467 #undef STR
    468 #undef XSTR
    469 }
    470 
    471 
    472 // Create one simulator per thread and keep it in thread local storage.
    473 static v8::internal::Thread::LocalStorageKey simulator_key;
    474 
    475 
    476 bool Simulator::initialized_ = false;
    477 
    478 
    479 void Simulator::Initialize() {
    480   if (initialized_) return;
    481   simulator_key = v8::internal::Thread::CreateThreadLocalKey();
    482   initialized_ = true;
    483   ::v8::internal::ExternalReference::set_redirector(&RedirectExternalReference);
    484 }
    485 
    486 
    487 Simulator::Simulator() {
    488   Initialize();
    489   // Setup simulator support first. Some of this information is needed to
    490   // setup the architecture state.
    491   size_t stack_size = 1 * 1024*1024;  // allocate 1MB for stack
    492   stack_ = reinterpret_cast<char*>(malloc(stack_size));
    493   pc_modified_ = false;
    494   icount_ = 0;
    495   break_pc_ = NULL;
    496   break_instr_ = 0;
    497 
    498   // Setup architecture state.
    499   // All registers are initialized to zero to start with.
    500   for (int i = 0; i < kNumSimuRegisters; i++) {
    501     registers_[i] = 0;
    502   }
    503 
    504   // The sp is initialized to point to the bottom (high address) of the
    505   // allocated stack area. To be safe in potential stack underflows we leave
    506   // some buffer below.
    507   registers_[sp] = reinterpret_cast<int32_t>(stack_) + stack_size - 64;
    508   // The ra and pc are initialized to a known bad value that will cause an
    509   // access violation if the simulator ever tries to execute it.
    510   registers_[pc] = bad_ra;
    511   registers_[ra] = bad_ra;
    512   InitializeCoverage();
    513 }
    514 
    515 
    516 // When the generated code calls an external reference we need to catch that in
    517 // the simulator.  The external reference will be a function compiled for the
    518 // host architecture.  We need to call that function instead of trying to
    519 // execute it with the simulator.  We do that by redirecting the external
    520 // reference to a swi (software-interrupt) instruction that is handled by
    521 // the simulator.  We write the original destination of the jump just at a known
    522 // offset from the swi instruction so the simulator knows what to call.
    523 class Redirection {
    524  public:
    525   Redirection(void* external_function, bool fp_return)
    526       : external_function_(external_function),
    527         swi_instruction_(rtCallRedirInstr),
    528         fp_return_(fp_return),
    529         next_(list_) {
    530     list_ = this;
    531   }
    532 
    533   void* address_of_swi_instruction() {
    534     return reinterpret_cast<void*>(&swi_instruction_);
    535   }
    536 
    537   void* external_function() { return external_function_; }
    538   bool fp_return() { return fp_return_; }
    539 
    540   static Redirection* Get(void* external_function, bool fp_return) {
    541     Redirection* current;
    542     for (current = list_; current != NULL; current = current->next_) {
    543       if (current->external_function_ == external_function) return current;
    544     }
    545     return new Redirection(external_function, fp_return);
    546   }
    547 
    548   static Redirection* FromSwiInstruction(Instruction* swi_instruction) {
    549     char* addr_of_swi = reinterpret_cast<char*>(swi_instruction);
    550     char* addr_of_redirection =
    551         addr_of_swi - OFFSET_OF(Redirection, swi_instruction_);
    552     return reinterpret_cast<Redirection*>(addr_of_redirection);
    553   }
    554 
    555  private:
    556   void* external_function_;
    557   uint32_t swi_instruction_;
    558   bool fp_return_;
    559   Redirection* next_;
    560   static Redirection* list_;
    561 };
    562 
    563 
    564 Redirection* Redirection::list_ = NULL;
    565 
    566 
    567 void* Simulator::RedirectExternalReference(void* external_function,
    568                                            bool fp_return) {
    569   Redirection* redirection = Redirection::Get(external_function, fp_return);
    570   return redirection->address_of_swi_instruction();
    571 }
    572 
    573 
    574 // Get the active Simulator for the current thread.
    575 Simulator* Simulator::current() {
    576   Initialize();
    577   Simulator* sim = reinterpret_cast<Simulator*>(
    578       v8::internal::Thread::GetThreadLocal(simulator_key));
    579   if (sim == NULL) {
    580     // TODO(146): delete the simulator object when a thread goes away.
    581     sim = new Simulator();
    582     v8::internal::Thread::SetThreadLocal(simulator_key, sim);
    583   }
    584   return sim;
    585 }
    586 
    587 
    588 // Sets the register in the architecture state. It will also deal with updating
    589 // Simulator internal state for special registers such as PC.
    590 void Simulator::set_register(int reg, int32_t value) {
    591   ASSERT((reg >= 0) && (reg < kNumSimuRegisters));
    592   if (reg == pc) {
    593     pc_modified_ = true;
    594   }
    595 
    596   // zero register always hold 0.
    597   registers_[reg] = (reg == 0) ? 0 : value;
    598 }
    599 
    600 void Simulator::set_fpu_register(int fpureg, int32_t value) {
    601   ASSERT((fpureg >= 0) && (fpureg < kNumFPURegisters));
    602   FPUregisters_[fpureg] = value;
    603 }
    604 
    605 void Simulator::set_fpu_register_double(int fpureg, double value) {
    606   ASSERT((fpureg >= 0) && (fpureg < kNumFPURegisters) && ((fpureg % 2) == 0));
    607   *v8i::bit_cast<double*, int32_t*>(&FPUregisters_[fpureg]) = value;
    608 }
    609 
    610 
    611 // Get the register from the architecture state. This function does handle
    612 // the special case of accessing the PC register.
    613 int32_t Simulator::get_register(int reg) const {
    614   ASSERT((reg >= 0) && (reg < kNumSimuRegisters));
    615   if (reg == 0)
    616     return 0;
    617   else
    618     return registers_[reg] + ((reg == pc) ? Instruction::kPCReadOffset : 0);
    619 }
    620 
    621 int32_t Simulator::get_fpu_register(int fpureg) const {
    622   ASSERT((fpureg >= 0) && (fpureg < kNumFPURegisters));
    623   return FPUregisters_[fpureg];
    624 }
    625 
    626 double Simulator::get_fpu_register_double(int fpureg) const {
    627   ASSERT((fpureg >= 0) && (fpureg < kNumFPURegisters) && ((fpureg % 2) == 0));
    628   return *v8i::bit_cast<double*, int32_t*>(
    629       const_cast<int32_t*>(&FPUregisters_[fpureg]));
    630 }
    631 
    632 // Raw access to the PC register.
    633 void Simulator::set_pc(int32_t value) {
    634   pc_modified_ = true;
    635   registers_[pc] = value;
    636 }
    637 
    638 // Raw access to the PC register without the special adjustment when reading.
    639 int32_t Simulator::get_pc() const {
    640   return registers_[pc];
    641 }
    642 
    643 
    644 // The MIPS cannot do unaligned reads and writes.  On some MIPS platforms an
    645 // interrupt is caused.  On others it does a funky rotation thing.  For now we
    646 // simply disallow unaligned reads, but at some point we may want to move to
    647 // emulating the rotate behaviour.  Note that simulator runs have the runtime
    648 // system running directly on the host system and only generated code is
    649 // executed in the simulator.  Since the host is typically IA32 we will not
    650 // get the correct MIPS-like behaviour on unaligned accesses.
    651 
    652 int Simulator::ReadW(int32_t addr, Instruction* instr) {
    653   if ((addr & v8i::kPointerAlignmentMask) == 0) {
    654     intptr_t* ptr = reinterpret_cast<intptr_t*>(addr);
    655     return *ptr;
    656   }
    657   PrintF("Unaligned read at 0x%08x, pc=%p\n", addr, instr);
    658   OS::Abort();
    659   return 0;
    660 }
    661 
    662 
    663 void Simulator::WriteW(int32_t addr, int value, Instruction* instr) {
    664   if ((addr & v8i::kPointerAlignmentMask) == 0) {
    665     intptr_t* ptr = reinterpret_cast<intptr_t*>(addr);
    666     *ptr = value;
    667     return;
    668   }
    669   PrintF("Unaligned write at 0x%08x, pc=%p\n", addr, instr);
    670   OS::Abort();
    671 }
    672 
    673 
    674 double Simulator::ReadD(int32_t addr, Instruction* instr) {
    675   if ((addr & kDoubleAlignmentMask) == 0) {
    676     double* ptr = reinterpret_cast<double*>(addr);
    677     return *ptr;
    678   }
    679   PrintF("Unaligned read at 0x%08x, pc=%p\n", addr, instr);
    680   OS::Abort();
    681   return 0;
    682 }
    683 
    684 
    685 void Simulator::WriteD(int32_t addr, double value, Instruction* instr) {
    686   if ((addr & kDoubleAlignmentMask) == 0) {
    687     double* ptr = reinterpret_cast<double*>(addr);
    688     *ptr = value;
    689     return;
    690   }
    691   PrintF("Unaligned write at 0x%08x, pc=%p\n", addr, instr);
    692   OS::Abort();
    693 }
    694 
    695 
    696 uint16_t Simulator::ReadHU(int32_t addr, Instruction* instr) {
    697   if ((addr & 1) == 0) {
    698     uint16_t* ptr = reinterpret_cast<uint16_t*>(addr);
    699     return *ptr;
    700   }
    701   PrintF("Unaligned unsigned halfword read at 0x%08x, pc=%p\n", addr, instr);
    702   OS::Abort();
    703   return 0;
    704 }
    705 
    706 
    707 int16_t Simulator::ReadH(int32_t addr, Instruction* instr) {
    708   if ((addr & 1) == 0) {
    709     int16_t* ptr = reinterpret_cast<int16_t*>(addr);
    710     return *ptr;
    711   }
    712   PrintF("Unaligned signed halfword read at 0x%08x, pc=%p\n", addr, instr);
    713   OS::Abort();
    714   return 0;
    715 }
    716 
    717 
    718 void Simulator::WriteH(int32_t addr, uint16_t value, Instruction* instr) {
    719   if ((addr & 1) == 0) {
    720     uint16_t* ptr = reinterpret_cast<uint16_t*>(addr);
    721     *ptr = value;
    722     return;
    723   }
    724   PrintF("Unaligned unsigned halfword write at 0x%08x, pc=%p\n", addr, instr);
    725   OS::Abort();
    726 }
    727 
    728 
    729 void Simulator::WriteH(int32_t addr, int16_t value, Instruction* instr) {
    730   if ((addr & 1) == 0) {
    731     int16_t* ptr = reinterpret_cast<int16_t*>(addr);
    732     *ptr = value;
    733     return;
    734   }
    735   PrintF("Unaligned halfword write at 0x%08x, pc=%p\n", addr, instr);
    736   OS::Abort();
    737 }
    738 
    739 
    740 uint32_t Simulator::ReadBU(int32_t addr) {
    741   uint8_t* ptr = reinterpret_cast<uint8_t*>(addr);
    742   return *ptr & 0xff;
    743 }
    744 
    745 
    746 int32_t Simulator::ReadB(int32_t addr) {
    747   int8_t* ptr = reinterpret_cast<int8_t*>(addr);
    748   return ((*ptr << 24) >> 24) & 0xff;
    749 }
    750 
    751 
    752 void Simulator::WriteB(int32_t addr, uint8_t value) {
    753   uint8_t* ptr = reinterpret_cast<uint8_t*>(addr);
    754   *ptr = value;
    755 }
    756 
    757 
    758 void Simulator::WriteB(int32_t addr, int8_t value) {
    759   int8_t* ptr = reinterpret_cast<int8_t*>(addr);
    760   *ptr = value;
    761 }
    762 
    763 
    764 // Returns the limit of the stack area to enable checking for stack overflows.
    765 uintptr_t Simulator::StackLimit() const {
    766   // Leave a safety margin of 256 bytes to prevent overrunning the stack when
    767   // pushing values.
    768   return reinterpret_cast<uintptr_t>(stack_) + 256;
    769 }
    770 
    771 
    772 // Unsupported instructions use Format to print an error and stop execution.
    773 void Simulator::Format(Instruction* instr, const char* format) {
    774   PrintF("Simulator found unsupported instruction:\n 0x%08x: %s\n",
    775          instr, format);
    776   UNIMPLEMENTED_MIPS();
    777 }
    778 
    779 
    780 // Calls into the V8 runtime are based on this very simple interface.
    781 // Note: To be able to return two values from some calls the code in runtime.cc
    782 // uses the ObjectPair which is essentially two 32-bit values stuffed into a
    783 // 64-bit value. With the code below we assume that all runtime calls return
    784 // 64 bits of result. If they don't, the r1 result register contains a bogus
    785 // value, which is fine because it is caller-saved.
    786 typedef int64_t (*SimulatorRuntimeCall)(int32_t arg0,
    787                                         int32_t arg1,
    788                                         int32_t arg2,
    789                                         int32_t arg3);
    790 typedef double (*SimulatorRuntimeFPCall)(double fparg0,
    791                                          double fparg1);
    792 
    793 
    794 // Software interrupt instructions are used by the simulator to call into the
    795 // C-based V8 runtime.
    796 void Simulator::SoftwareInterrupt(Instruction* instr) {
    797   // We first check if we met a call_rt_redirected.
    798   if (instr->InstructionBits() == rtCallRedirInstr) {
    799     Redirection* redirection = Redirection::FromSwiInstruction(instr);
    800     int32_t arg0 = get_register(a0);
    801     int32_t arg1 = get_register(a1);
    802     int32_t arg2 = get_register(a2);
    803     int32_t arg3 = get_register(a3);
    804     // fp args are (not always) in f12 and f14.
    805     // See MIPS conventions for more details.
    806     double fparg0 = get_fpu_register_double(f12);
    807     double fparg1 = get_fpu_register_double(f14);
    808     // This is dodgy but it works because the C entry stubs are never moved.
    809     // See comment in codegen-arm.cc and bug 1242173.
    810     int32_t saved_ra = get_register(ra);
    811     if (redirection->fp_return()) {
    812       intptr_t external =
    813           reinterpret_cast<intptr_t>(redirection->external_function());
    814       SimulatorRuntimeFPCall target =
    815           reinterpret_cast<SimulatorRuntimeFPCall>(external);
    816       if (::v8::internal::FLAG_trace_sim) {
    817         PrintF("Call to host function at %p with args %f, %f\n",
    818                FUNCTION_ADDR(target), fparg0, fparg1);
    819       }
    820       double result = target(fparg0, fparg1);
    821       set_fpu_register_double(f0, result);
    822     } else {
    823       intptr_t external =
    824           reinterpret_cast<int32_t>(redirection->external_function());
    825       SimulatorRuntimeCall target =
    826           reinterpret_cast<SimulatorRuntimeCall>(external);
    827       if (::v8::internal::FLAG_trace_sim) {
    828         PrintF(
    829             "Call to host function at %p with args %08x, %08x, %08x, %08x\n",
    830             FUNCTION_ADDR(target),
    831             arg0,
    832             arg1,
    833             arg2,
    834             arg3);
    835       }
    836       int64_t result = target(arg0, arg1, arg2, arg3);
    837       int32_t lo_res = static_cast<int32_t>(result);
    838       int32_t hi_res = static_cast<int32_t>(result >> 32);
    839       if (::v8::internal::FLAG_trace_sim) {
    840         PrintF("Returned %08x\n", lo_res);
    841       }
    842       set_register(v0, lo_res);
    843       set_register(v1, hi_res);
    844     }
    845     set_register(ra, saved_ra);
    846     set_pc(get_register(ra));
    847   } else {
    848     Debugger dbg(this);
    849     dbg.Debug();
    850   }
    851 }
    852 
    853 void Simulator::SignalExceptions() {
    854   for (int i = 1; i < kNumExceptions; i++) {
    855     if (exceptions[i] != 0) {
    856       V8_Fatal(__FILE__, __LINE__, "Error: Exception %i raised.", i);
    857     }
    858   }
    859 }
    860 
    861 // Handle execution based on instruction types.
    862 void Simulator::DecodeTypeRegister(Instruction* instr) {
    863   // Instruction fields
    864   Opcode   op     = instr->OpcodeFieldRaw();
    865   int32_t  rs_reg = instr->RsField();
    866   int32_t  rs     = get_register(rs_reg);
    867   uint32_t rs_u   = static_cast<uint32_t>(rs);
    868   int32_t  rt_reg = instr->RtField();
    869   int32_t  rt     = get_register(rt_reg);
    870   uint32_t rt_u   = static_cast<uint32_t>(rt);
    871   int32_t  rd_reg = instr->RdField();
    872   uint32_t sa     = instr->SaField();
    873 
    874   int32_t fs_reg= instr->FsField();
    875 
    876   // ALU output
    877   // It should not be used as is. Instructions using it should always initialize
    878   // it first.
    879   int32_t alu_out = 0x12345678;
    880   // Output or temporary for floating point.
    881   double fp_out = 0.0;
    882 
    883   // For break and trap instructions.
    884   bool do_interrupt = false;
    885 
    886   // For jr and jalr
    887   // Get current pc.
    888   int32_t current_pc = get_pc();
    889   // Next pc
    890   int32_t next_pc = 0;
    891 
    892   // ---------- Configuration
    893   switch (op) {
    894     case COP1:    // Coprocessor instructions
    895       switch (instr->RsFieldRaw()) {
    896         case BC1:   // branch on coprocessor condition
    897           UNREACHABLE();
    898           break;
    899         case MFC1:
    900           alu_out = get_fpu_register(fs_reg);
    901           break;
    902         case MFHC1:
    903           fp_out = get_fpu_register_double(fs_reg);
    904           alu_out = *v8i::bit_cast<int32_t*, double*>(&fp_out);
    905           break;
    906         case MTC1:
    907         case MTHC1:
    908           // Do the store in the execution step.
    909           break;
    910         case S:
    911         case D:
    912         case W:
    913         case L:
    914         case PS:
    915           // Do everything in the execution step.
    916           break;
    917         default:
    918           UNIMPLEMENTED_MIPS();
    919       };
    920       break;
    921     case SPECIAL:
    922       switch (instr->FunctionFieldRaw()) {
    923         case JR:
    924         case JALR:
    925           next_pc = get_register(instr->RsField());
    926           break;
    927         case SLL:
    928           alu_out = rt << sa;
    929           break;
    930         case SRL:
    931           alu_out = rt_u >> sa;
    932           break;
    933         case SRA:
    934           alu_out = rt >> sa;
    935           break;
    936         case SLLV:
    937           alu_out = rt << rs;
    938           break;
    939         case SRLV:
    940           alu_out = rt_u >> rs;
    941           break;
    942         case SRAV:
    943           alu_out = rt >> rs;
    944           break;
    945         case MFHI:
    946           alu_out = get_register(HI);
    947           break;
    948         case MFLO:
    949           alu_out = get_register(LO);
    950           break;
    951         case MULT:
    952           UNIMPLEMENTED_MIPS();
    953           break;
    954         case MULTU:
    955           UNIMPLEMENTED_MIPS();
    956           break;
    957         case DIV:
    958         case DIVU:
    959             exceptions[kDivideByZero] = rt == 0;
    960           break;
    961         case ADD:
    962           if (HaveSameSign(rs, rt)) {
    963             if (rs > 0) {
    964               exceptions[kIntegerOverflow] = rs > (Registers::kMaxValue - rt);
    965             } else if (rs < 0) {
    966               exceptions[kIntegerUnderflow] = rs < (Registers::kMinValue - rt);
    967             }
    968           }
    969           alu_out = rs + rt;
    970           break;
    971         case ADDU:
    972           alu_out = rs + rt;
    973           break;
    974         case SUB:
    975           if (!HaveSameSign(rs, rt)) {
    976             if (rs > 0) {
    977               exceptions[kIntegerOverflow] = rs > (Registers::kMaxValue + rt);
    978             } else if (rs < 0) {
    979               exceptions[kIntegerUnderflow] = rs < (Registers::kMinValue + rt);
    980             }
    981           }
    982           alu_out = rs - rt;
    983           break;
    984         case SUBU:
    985           alu_out = rs - rt;
    986           break;
    987         case AND:
    988           alu_out = rs & rt;
    989           break;
    990         case OR:
    991           alu_out = rs | rt;
    992           break;
    993         case XOR:
    994           alu_out = rs ^ rt;
    995           break;
    996         case NOR:
    997           alu_out = ~(rs | rt);
    998           break;
    999         case SLT:
   1000           alu_out = rs < rt ? 1 : 0;
   1001           break;
   1002         case SLTU:
   1003           alu_out = rs_u < rt_u ? 1 : 0;
   1004           break;
   1005         // Break and trap instructions
   1006         case BREAK:
   1007           do_interrupt = true;
   1008           break;
   1009         case TGE:
   1010           do_interrupt = rs >= rt;
   1011           break;
   1012         case TGEU:
   1013           do_interrupt = rs_u >= rt_u;
   1014           break;
   1015         case TLT:
   1016           do_interrupt = rs < rt;
   1017           break;
   1018         case TLTU:
   1019           do_interrupt = rs_u < rt_u;
   1020           break;
   1021         case TEQ:
   1022           do_interrupt = rs == rt;
   1023           break;
   1024         case TNE:
   1025           do_interrupt = rs != rt;
   1026           break;
   1027         default:
   1028           UNREACHABLE();
   1029       };
   1030       break;
   1031     case SPECIAL2:
   1032       switch (instr->FunctionFieldRaw()) {
   1033         case MUL:
   1034           alu_out = rs_u * rt_u;  // Only the lower 32 bits are kept.
   1035           break;
   1036         default:
   1037           UNREACHABLE();
   1038       }
   1039       break;
   1040     default:
   1041       UNREACHABLE();
   1042   };
   1043 
   1044   // ---------- Raise exceptions triggered.
   1045   SignalExceptions();
   1046 
   1047   // ---------- Execution
   1048   switch (op) {
   1049     case COP1:
   1050       switch (instr->RsFieldRaw()) {
   1051         case BC1:   // branch on coprocessor condition
   1052           UNREACHABLE();
   1053           break;
   1054         case MFC1:
   1055         case MFHC1:
   1056           set_register(rt_reg, alu_out);
   1057           break;
   1058         case MTC1:
   1059           // We don't need to set the higher bits to 0, because MIPS ISA says
   1060           // they are in an unpredictable state after executing MTC1.
   1061           FPUregisters_[fs_reg] = registers_[rt_reg];
   1062           FPUregisters_[fs_reg+1] = Unpredictable;
   1063           break;
   1064         case MTHC1:
   1065           // Here we need to keep the lower bits unchanged.
   1066           FPUregisters_[fs_reg+1] = registers_[rt_reg];
   1067           break;
   1068         case S:
   1069           switch (instr->FunctionFieldRaw()) {
   1070             case CVT_D_S:
   1071             case CVT_W_S:
   1072             case CVT_L_S:
   1073             case CVT_PS_S:
   1074               UNIMPLEMENTED_MIPS();
   1075               break;
   1076             default:
   1077               UNREACHABLE();
   1078           }
   1079           break;
   1080         case D:
   1081           switch (instr->FunctionFieldRaw()) {
   1082             case CVT_S_D:
   1083             case CVT_W_D:
   1084             case CVT_L_D:
   1085               UNIMPLEMENTED_MIPS();
   1086               break;
   1087             default:
   1088               UNREACHABLE();
   1089           }
   1090           break;
   1091         case W:
   1092           switch (instr->FunctionFieldRaw()) {
   1093             case CVT_S_W:
   1094               UNIMPLEMENTED_MIPS();
   1095               break;
   1096             case CVT_D_W:   // Convert word to double.
   1097               set_fpu_register(rd_reg, static_cast<double>(rs));
   1098               break;
   1099             default:
   1100               UNREACHABLE();
   1101           };
   1102           break;
   1103         case L:
   1104           switch (instr->FunctionFieldRaw()) {
   1105             case CVT_S_L:
   1106             case CVT_D_L:
   1107               UNIMPLEMENTED_MIPS();
   1108               break;
   1109             default:
   1110               UNREACHABLE();
   1111           }
   1112           break;
   1113         case PS:
   1114           break;
   1115         default:
   1116           UNREACHABLE();
   1117       };
   1118       break;
   1119     case SPECIAL:
   1120       switch (instr->FunctionFieldRaw()) {
   1121         case JR: {
   1122           Instruction* branch_delay_instr = reinterpret_cast<Instruction*>(
   1123               current_pc+Instruction::kInstructionSize);
   1124           BranchDelayInstructionDecode(branch_delay_instr);
   1125           set_pc(next_pc);
   1126           pc_modified_ = true;
   1127           break;
   1128         }
   1129         case JALR: {
   1130           Instruction* branch_delay_instr = reinterpret_cast<Instruction*>(
   1131               current_pc+Instruction::kInstructionSize);
   1132           BranchDelayInstructionDecode(branch_delay_instr);
   1133           set_register(31, current_pc + 2* Instruction::kInstructionSize);
   1134           set_pc(next_pc);
   1135           pc_modified_ = true;
   1136           break;
   1137         }
   1138         // Instructions using HI and LO registers.
   1139         case MULT:
   1140         case MULTU:
   1141           break;
   1142         case DIV:
   1143           // Divide by zero was checked in the configuration step.
   1144           set_register(LO, rs / rt);
   1145           set_register(HI, rs % rt);
   1146           break;
   1147         case DIVU:
   1148           set_register(LO, rs_u / rt_u);
   1149           set_register(HI, rs_u % rt_u);
   1150           break;
   1151         // Break and trap instructions
   1152         case BREAK:
   1153         case TGE:
   1154         case TGEU:
   1155         case TLT:
   1156         case TLTU:
   1157         case TEQ:
   1158         case TNE:
   1159           if (do_interrupt) {
   1160             SoftwareInterrupt(instr);
   1161           }
   1162           break;
   1163         default:  // For other special opcodes we do the default operation.
   1164           set_register(rd_reg, alu_out);
   1165       };
   1166       break;
   1167     case SPECIAL2:
   1168       switch (instr->FunctionFieldRaw()) {
   1169         case MUL:
   1170           set_register(rd_reg, alu_out);
   1171           // HI and LO are UNPREDICTABLE after the operation.
   1172           set_register(LO, Unpredictable);
   1173           set_register(HI, Unpredictable);
   1174           break;
   1175         default:
   1176           UNREACHABLE();
   1177       }
   1178       break;
   1179     // Unimplemented opcodes raised an error in the configuration step before,
   1180     // so we can use the default here to set the destination register in common
   1181     // cases.
   1182     default:
   1183       set_register(rd_reg, alu_out);
   1184   };
   1185 }
   1186 
   1187 // Type 2: instructions using a 16 bytes immediate. (eg: addi, beq)
   1188 void Simulator::DecodeTypeImmediate(Instruction* instr) {
   1189   // Instruction fields
   1190   Opcode   op     = instr->OpcodeFieldRaw();
   1191   int32_t  rs     = get_register(instr->RsField());
   1192   uint32_t rs_u   = static_cast<uint32_t>(rs);
   1193   int32_t  rt_reg = instr->RtField();  // destination register
   1194   int32_t  rt     = get_register(rt_reg);
   1195   int16_t  imm16  = instr->Imm16Field();
   1196 
   1197   int32_t  ft_reg = instr->FtField();  // destination register
   1198   int32_t  ft     = get_register(ft_reg);
   1199 
   1200   // zero extended immediate
   1201   uint32_t  oe_imm16 = 0xffff & imm16;
   1202   // sign extended immediate
   1203   int32_t   se_imm16 = imm16;
   1204 
   1205   // Get current pc.
   1206   int32_t current_pc = get_pc();
   1207   // Next pc.
   1208   int32_t next_pc = bad_ra;
   1209 
   1210   // Used for conditional branch instructions
   1211   bool do_branch = false;
   1212   bool execute_branch_delay_instruction = false;
   1213 
   1214   // Used for arithmetic instructions
   1215   int32_t alu_out = 0;
   1216   // Floating point
   1217   double fp_out = 0.0;
   1218 
   1219   // Used for memory instructions
   1220   int32_t addr = 0x0;
   1221 
   1222   // ---------- Configuration (and execution for REGIMM)
   1223   switch (op) {
   1224     // ------------- COP1. Coprocessor instructions
   1225     case COP1:
   1226       switch (instr->RsFieldRaw()) {
   1227         case BC1:   // branch on coprocessor condition
   1228           UNIMPLEMENTED_MIPS();
   1229           break;
   1230         default:
   1231           UNREACHABLE();
   1232       };
   1233       break;
   1234     // ------------- REGIMM class
   1235     case REGIMM:
   1236       switch (instr->RtFieldRaw()) {
   1237         case BLTZ:
   1238           do_branch = (rs  < 0);
   1239           break;
   1240         case BLTZAL:
   1241           do_branch = rs  < 0;
   1242           break;
   1243         case BGEZ:
   1244           do_branch = rs >= 0;
   1245           break;
   1246         case BGEZAL:
   1247           do_branch = rs >= 0;
   1248           break;
   1249         default:
   1250           UNREACHABLE();
   1251       };
   1252       switch (instr->RtFieldRaw()) {
   1253         case BLTZ:
   1254         case BLTZAL:
   1255         case BGEZ:
   1256         case BGEZAL:
   1257           // Branch instructions common part.
   1258           execute_branch_delay_instruction = true;
   1259           // Set next_pc
   1260           if (do_branch) {
   1261             next_pc = current_pc + (imm16 << 2) + Instruction::kInstructionSize;
   1262             if (instr->IsLinkingInstruction()) {
   1263               set_register(31, current_pc + kBranchReturnOffset);
   1264             }
   1265           } else {
   1266             next_pc = current_pc + kBranchReturnOffset;
   1267           }
   1268         default:
   1269           break;
   1270         };
   1271     break;  // case REGIMM
   1272     // ------------- Branch instructions
   1273     // When comparing to zero, the encoding of rt field is always 0, so we don't
   1274     // need to replace rt with zero.
   1275     case BEQ:
   1276       do_branch = (rs == rt);
   1277       break;
   1278     case BNE:
   1279       do_branch = rs != rt;
   1280       break;
   1281     case BLEZ:
   1282       do_branch = rs <= 0;
   1283       break;
   1284     case BGTZ:
   1285       do_branch = rs  > 0;
   1286       break;
   1287     // ------------- Arithmetic instructions
   1288     case ADDI:
   1289       if (HaveSameSign(rs, se_imm16)) {
   1290         if (rs > 0) {
   1291           exceptions[kIntegerOverflow] = rs > (Registers::kMaxValue - se_imm16);
   1292         } else if (rs < 0) {
   1293           exceptions[kIntegerUnderflow] =
   1294               rs < (Registers::kMinValue - se_imm16);
   1295         }
   1296       }
   1297       alu_out = rs + se_imm16;
   1298       break;
   1299     case ADDIU:
   1300       alu_out = rs + se_imm16;
   1301       break;
   1302     case SLTI:
   1303       alu_out = (rs < se_imm16) ? 1 : 0;
   1304       break;
   1305     case SLTIU:
   1306       alu_out = (rs_u < static_cast<uint32_t>(se_imm16)) ? 1 : 0;
   1307       break;
   1308     case ANDI:
   1309         alu_out = rs & oe_imm16;
   1310       break;
   1311     case ORI:
   1312         alu_out = rs | oe_imm16;
   1313       break;
   1314     case XORI:
   1315         alu_out = rs ^ oe_imm16;
   1316       break;
   1317     case LUI:
   1318         alu_out = (oe_imm16 << 16);
   1319       break;
   1320     // ------------- Memory instructions
   1321     case LB:
   1322       addr = rs + se_imm16;
   1323       alu_out = ReadB(addr);
   1324       break;
   1325     case LW:
   1326       addr = rs + se_imm16;
   1327       alu_out = ReadW(addr, instr);
   1328       break;
   1329     case LBU:
   1330       addr = rs + se_imm16;
   1331       alu_out = ReadBU(addr);
   1332       break;
   1333     case SB:
   1334       addr = rs + se_imm16;
   1335       break;
   1336     case SW:
   1337       addr = rs + se_imm16;
   1338       break;
   1339     case LWC1:
   1340       addr = rs + se_imm16;
   1341       alu_out = ReadW(addr, instr);
   1342       break;
   1343     case LDC1:
   1344       addr = rs + se_imm16;
   1345       fp_out = ReadD(addr, instr);
   1346       break;
   1347     case SWC1:
   1348     case SDC1:
   1349       addr = rs + se_imm16;
   1350       break;
   1351     default:
   1352       UNREACHABLE();
   1353   };
   1354 
   1355   // ---------- Raise exceptions triggered.
   1356   SignalExceptions();
   1357 
   1358   // ---------- Execution
   1359   switch (op) {
   1360     // ------------- Branch instructions
   1361     case BEQ:
   1362     case BNE:
   1363     case BLEZ:
   1364     case BGTZ:
   1365       // Branch instructions common part.
   1366       execute_branch_delay_instruction = true;
   1367       // Set next_pc
   1368       if (do_branch) {
   1369         next_pc = current_pc + (imm16 << 2) + Instruction::kInstructionSize;
   1370         if (instr->IsLinkingInstruction()) {
   1371           set_register(31, current_pc + 2* Instruction::kInstructionSize);
   1372         }
   1373       } else {
   1374         next_pc = current_pc + 2 * Instruction::kInstructionSize;
   1375       }
   1376       break;
   1377     // ------------- Arithmetic instructions
   1378     case ADDI:
   1379     case ADDIU:
   1380     case SLTI:
   1381     case SLTIU:
   1382     case ANDI:
   1383     case ORI:
   1384     case XORI:
   1385     case LUI:
   1386       set_register(rt_reg, alu_out);
   1387       break;
   1388     // ------------- Memory instructions
   1389     case LB:
   1390     case LW:
   1391     case LBU:
   1392       set_register(rt_reg, alu_out);
   1393       break;
   1394     case SB:
   1395       WriteB(addr, static_cast<int8_t>(rt));
   1396       break;
   1397     case SW:
   1398       WriteW(addr, rt, instr);
   1399       break;
   1400     case LWC1:
   1401       set_fpu_register(ft_reg, alu_out);
   1402       break;
   1403     case LDC1:
   1404       set_fpu_register_double(ft_reg, fp_out);
   1405       break;
   1406     case SWC1:
   1407       addr = rs + se_imm16;
   1408       WriteW(addr, get_fpu_register(ft_reg), instr);
   1409       break;
   1410     case SDC1:
   1411       addr = rs + se_imm16;
   1412       WriteD(addr, ft, instr);
   1413       break;
   1414     default:
   1415       break;
   1416   };
   1417 
   1418 
   1419   if (execute_branch_delay_instruction) {
   1420     // Execute branch delay slot
   1421     // We don't check for end_sim_pc. First it should not be met as the current
   1422     // pc is valid. Secondly a jump should always execute its branch delay slot.
   1423     Instruction* branch_delay_instr =
   1424       reinterpret_cast<Instruction*>(current_pc+Instruction::kInstructionSize);
   1425     BranchDelayInstructionDecode(branch_delay_instr);
   1426   }
   1427 
   1428   // If needed update pc after the branch delay execution.
   1429   if (next_pc != bad_ra) {
   1430     set_pc(next_pc);
   1431   }
   1432 }
   1433 
   1434 // Type 3: instructions using a 26 bytes immediate. (eg: j, jal)
   1435 void Simulator::DecodeTypeJump(Instruction* instr) {
   1436   // Get current pc.
   1437   int32_t current_pc = get_pc();
   1438   // Get unchanged bits of pc.
   1439   int32_t pc_high_bits = current_pc & 0xf0000000;
   1440   // Next pc
   1441   int32_t next_pc = pc_high_bits | (instr->Imm26Field() << 2);
   1442 
   1443   // Execute branch delay slot
   1444   // We don't check for end_sim_pc. First it should not be met as the current pc
   1445   // is valid. Secondly a jump should always execute its branch delay slot.
   1446   Instruction* branch_delay_instr =
   1447     reinterpret_cast<Instruction*>(current_pc+Instruction::kInstructionSize);
   1448   BranchDelayInstructionDecode(branch_delay_instr);
   1449 
   1450   // Update pc and ra if necessary.
   1451   // Do this after the branch delay execution.
   1452   if (instr->IsLinkingInstruction()) {
   1453     set_register(31, current_pc + 2* Instruction::kInstructionSize);
   1454   }
   1455   set_pc(next_pc);
   1456   pc_modified_ = true;
   1457 }
   1458 
   1459 // Executes the current instruction.
   1460 void Simulator::InstructionDecode(Instruction* instr) {
   1461   pc_modified_ = false;
   1462   if (::v8::internal::FLAG_trace_sim) {
   1463     disasm::NameConverter converter;
   1464     disasm::Disassembler dasm(converter);
   1465     // use a reasonably large buffer
   1466     v8::internal::EmbeddedVector<char, 256> buffer;
   1467     dasm.InstructionDecode(buffer,
   1468                            reinterpret_cast<byte_*>(instr));
   1469     PrintF("  0x%08x  %s\n", instr, buffer.start());
   1470   }
   1471 
   1472   switch (instr->InstructionType()) {
   1473     case Instruction::kRegisterType:
   1474       DecodeTypeRegister(instr);
   1475       break;
   1476     case Instruction::kImmediateType:
   1477       DecodeTypeImmediate(instr);
   1478       break;
   1479     case Instruction::kJumpType:
   1480       DecodeTypeJump(instr);
   1481       break;
   1482     default:
   1483       UNSUPPORTED();
   1484   }
   1485   if (!pc_modified_) {
   1486     set_register(pc, reinterpret_cast<int32_t>(instr) +
   1487                  Instruction::kInstructionSize);
   1488   }
   1489 }
   1490 
   1491 
   1492 
   1493 void Simulator::Execute() {
   1494   // Get the PC to simulate. Cannot use the accessor here as we need the
   1495   // raw PC value and not the one used as input to arithmetic instructions.
   1496   int program_counter = get_pc();
   1497   if (::v8::internal::FLAG_stop_sim_at == 0) {
   1498     // Fast version of the dispatch loop without checking whether the simulator
   1499     // should be stopping at a particular executed instruction.
   1500     while (program_counter != end_sim_pc) {
   1501       Instruction* instr = reinterpret_cast<Instruction*>(program_counter);
   1502       icount_++;
   1503       InstructionDecode(instr);
   1504       program_counter = get_pc();
   1505     }
   1506   } else {
   1507     // FLAG_stop_sim_at is at the non-default value. Stop in the debugger when
   1508     // we reach the particular instuction count.
   1509     while (program_counter != end_sim_pc) {
   1510       Instruction* instr = reinterpret_cast<Instruction*>(program_counter);
   1511       icount_++;
   1512       if (icount_ == ::v8::internal::FLAG_stop_sim_at) {
   1513         Debugger dbg(this);
   1514         dbg.Debug();
   1515       } else {
   1516         InstructionDecode(instr);
   1517       }
   1518       program_counter = get_pc();
   1519     }
   1520   }
   1521 }
   1522 
   1523 
   1524 int32_t Simulator::Call(byte_* entry, int argument_count, ...) {
   1525   va_list parameters;
   1526   va_start(parameters, argument_count);
   1527   // Setup arguments
   1528 
   1529   // First four arguments passed in registers.
   1530   ASSERT(argument_count >= 4);
   1531   set_register(a0, va_arg(parameters, int32_t));
   1532   set_register(a1, va_arg(parameters, int32_t));
   1533   set_register(a2, va_arg(parameters, int32_t));
   1534   set_register(a3, va_arg(parameters, int32_t));
   1535 
   1536   // Remaining arguments passed on stack.
   1537   int original_stack = get_register(sp);
   1538   // Compute position of stack on entry to generated code.
   1539   int entry_stack = (original_stack - (argument_count - 4) * sizeof(int32_t)
   1540                                     - kArgsSlotsSize);
   1541   if (OS::ActivationFrameAlignment() != 0) {
   1542     entry_stack &= -OS::ActivationFrameAlignment();
   1543   }
   1544   // Store remaining arguments on stack, from low to high memory.
   1545   intptr_t* stack_argument = reinterpret_cast<intptr_t*>(entry_stack);
   1546   for (int i = 4; i < argument_count; i++) {
   1547     stack_argument[i - 4 + kArgsSlotsNum] = va_arg(parameters, int32_t);
   1548   }
   1549   va_end(parameters);
   1550   set_register(sp, entry_stack);
   1551 
   1552   // Prepare to execute the code at entry
   1553   set_register(pc, reinterpret_cast<int32_t>(entry));
   1554   // Put down marker for end of simulation. The simulator will stop simulation
   1555   // when the PC reaches this value. By saving the "end simulation" value into
   1556   // the LR the simulation stops when returning to this call point.
   1557   set_register(ra, end_sim_pc);
   1558 
   1559   // Remember the values of callee-saved registers.
   1560   // The code below assumes that r9 is not used as sb (static base) in
   1561   // simulator code and therefore is regarded as a callee-saved register.
   1562   int32_t s0_val = get_register(s0);
   1563   int32_t s1_val = get_register(s1);
   1564   int32_t s2_val = get_register(s2);
   1565   int32_t s3_val = get_register(s3);
   1566   int32_t s4_val = get_register(s4);
   1567   int32_t s5_val = get_register(s5);
   1568   int32_t s6_val = get_register(s6);
   1569   int32_t s7_val = get_register(s7);
   1570   int32_t gp_val = get_register(gp);
   1571   int32_t sp_val = get_register(sp);
   1572   int32_t fp_val = get_register(fp);
   1573 
   1574   // Setup the callee-saved registers with a known value. To be able to check
   1575   // that they are preserved properly across JS execution.
   1576   int32_t callee_saved_value = icount_;
   1577   set_register(s0, callee_saved_value);
   1578   set_register(s1, callee_saved_value);
   1579   set_register(s2, callee_saved_value);
   1580   set_register(s3, callee_saved_value);
   1581   set_register(s4, callee_saved_value);
   1582   set_register(s5, callee_saved_value);
   1583   set_register(s6, callee_saved_value);
   1584   set_register(s7, callee_saved_value);
   1585   set_register(gp, callee_saved_value);
   1586   set_register(fp, callee_saved_value);
   1587 
   1588   // Start the simulation
   1589   Execute();
   1590 
   1591   // Check that the callee-saved registers have been preserved.
   1592   CHECK_EQ(callee_saved_value, get_register(s0));
   1593   CHECK_EQ(callee_saved_value, get_register(s1));
   1594   CHECK_EQ(callee_saved_value, get_register(s2));
   1595   CHECK_EQ(callee_saved_value, get_register(s3));
   1596   CHECK_EQ(callee_saved_value, get_register(s4));
   1597   CHECK_EQ(callee_saved_value, get_register(s5));
   1598   CHECK_EQ(callee_saved_value, get_register(s6));
   1599   CHECK_EQ(callee_saved_value, get_register(s7));
   1600   CHECK_EQ(callee_saved_value, get_register(gp));
   1601   CHECK_EQ(callee_saved_value, get_register(fp));
   1602 
   1603   // Restore callee-saved registers with the original value.
   1604   set_register(s0, s0_val);
   1605   set_register(s1, s1_val);
   1606   set_register(s2, s2_val);
   1607   set_register(s3, s3_val);
   1608   set_register(s4, s4_val);
   1609   set_register(s5, s5_val);
   1610   set_register(s6, s6_val);
   1611   set_register(s7, s7_val);
   1612   set_register(gp, gp_val);
   1613   set_register(sp, sp_val);
   1614   set_register(fp, fp_val);
   1615 
   1616   // Pop stack passed arguments.
   1617   CHECK_EQ(entry_stack, get_register(sp));
   1618   set_register(sp, original_stack);
   1619 
   1620   int32_t result = get_register(v0);
   1621   return result;
   1622 }
   1623 
   1624 
   1625 uintptr_t Simulator::PushAddress(uintptr_t address) {
   1626   int new_sp = get_register(sp) - sizeof(uintptr_t);
   1627   uintptr_t* stack_slot = reinterpret_cast<uintptr_t*>(new_sp);
   1628   *stack_slot = address;
   1629   set_register(sp, new_sp);
   1630   return new_sp;
   1631 }
   1632 
   1633 
   1634 uintptr_t Simulator::PopAddress() {
   1635   int current_sp = get_register(sp);
   1636   uintptr_t* stack_slot = reinterpret_cast<uintptr_t*>(current_sp);
   1637   uintptr_t address = *stack_slot;
   1638   set_register(sp, current_sp + sizeof(uintptr_t));
   1639   return address;
   1640 }
   1641 
   1642 
   1643 #undef UNSUPPORTED
   1644 
   1645 } }  // namespace assembler::mips
   1646 
   1647 #endif  // !defined(__mips)
   1648 
   1649