112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// Copyright 2011 the V8 project authors. All rights reserved. 212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// Use of this source code is governed by a BSD-style license that can be 312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// found in the LICENSE file. 412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org#include <limits.h> 612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org#include <stdarg.h> 712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org#include <stdlib.h> 812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org#include <cmath> 912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 1012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org#include "src/v8.h" 1112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 1212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org#if V8_TARGET_ARCH_MIPS64 1312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 1412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org#include "src/assembler.h" 15e2a8937454723a720c81acc3f9e4162b18999b43machenbach@chromium.org#include "src/base/bits.h" 1612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org#include "src/disasm.h" 1712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org#include "src/mips64/constants-mips64.h" 1812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org#include "src/mips64/simulator-mips64.h" 197d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org#include "src/ostreams.h" 2012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 2112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// Only build the simulator if not compiling for real MIPS hardware. 2212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org#if defined(USE_SIMULATOR) 2312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 2412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgnamespace v8 { 2512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgnamespace internal { 2612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 2712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// Utils functions. 2812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgbool HaveSameSign(int64_t a, int64_t b) { 2912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org return ((a ^ b) >= 0); 3012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org} 3112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 3212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 3312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orguint32_t get_fcsr_condition_bit(uint32_t cc) { 3412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (cc == 0) { 3512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org return 23; 3612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } else { 3712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org return 24 + cc; 3812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 3912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org} 4012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 4112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 4212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgstatic int64_t MultiplyHighSigned(int64_t u, int64_t v) { 4312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org uint64_t u0, v0, w0; 4412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org int64_t u1, v1, w1, w2, t; 4512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 4612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org u0 = u & 0xffffffffL; 4712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org u1 = u >> 32; 4812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org v0 = v & 0xffffffffL; 4912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org v1 = v >> 32; 5012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 5112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org w0 = u0 * v0; 5212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org t = u1 * v0 + (w0 >> 32); 5312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org w1 = t & 0xffffffffL; 5412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org w2 = t >> 32; 5512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org w1 = u0 * v1 + w1; 5612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 5712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org return u1 * v1 + w2 + (w1 >> 32); 5812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org} 5912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 6012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 6112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// This macro provides a platform independent use of sscanf. The reason for 6212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// SScanF not being implemented in a platform independent was through 6312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// ::v8::internal::OS in the same way as SNPrintF is that the Windows C Run-Time 6412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// Library does not provide vsscanf. 6512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org#define SScanF sscanf // NOLINT 6612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 6712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// The MipsDebugger class is used by the simulator while debugging simulated 6812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// code. 6912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgclass MipsDebugger { 7012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org public: 7112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org explicit MipsDebugger(Simulator* sim) : sim_(sim) { } 7212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org ~MipsDebugger(); 7312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 7412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org void Stop(Instruction* instr); 7512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org void Debug(); 7612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Print all registers with a nice formatting. 7712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org void PrintAllRegs(); 7812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org void PrintAllRegsIncludingFPU(); 7912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 8012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org private: 8112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // We set the breakpoint code to 0xfffff to easily recognize it. 8212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org static const Instr kBreakpointInstr = SPECIAL | BREAK | 0xfffff << 6; 8312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org static const Instr kNopInstr = 0x0; 8412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 8512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Simulator* sim_; 8612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 8712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org int64_t GetRegisterValue(int regnum); 8812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org int64_t GetFPURegisterValue(int regnum); 8912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org float GetFPURegisterValueFloat(int regnum); 9012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org double GetFPURegisterValueDouble(int regnum); 9112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org bool GetValue(const char* desc, int64_t* value); 9212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 9312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Set or delete a breakpoint. Returns true if successful. 9412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org bool SetBreakpoint(Instruction* breakpc); 9512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org bool DeleteBreakpoint(Instruction* breakpc); 9612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 9712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Undo and redo all breakpoints. This is needed to bracket disassembly and 9812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // execution to skip past breakpoints when run from the debugger. 9912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org void UndoBreakpoints(); 10012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org void RedoBreakpoints(); 10112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org}; 10212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 10312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 10412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgMipsDebugger::~MipsDebugger() { 10512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org} 10612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 10712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 10812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org#ifdef GENERATED_CODE_COVERAGE 10912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgstatic FILE* coverage_log = NULL; 11012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 11112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 11212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgstatic void InitializeCoverage() { 11312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org char* file_name = getenv("V8_GENERATED_CODE_COVERAGE_LOG"); 11412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (file_name != NULL) { 11512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org coverage_log = fopen(file_name, "aw+"); 11612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 11712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org} 11812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 11912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 12012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgvoid MipsDebugger::Stop(Instruction* instr) { 12112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Get the stop code. 12212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org uint32_t code = instr->Bits(25, 6); 12312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Retrieve the encoded address, which comes just after this stop. 12412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org char** msg_address = 12512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org reinterpret_cast<char**>(sim_->get_pc() + Instr::kInstrSize); 12612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org char* msg = *msg_address; 127e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK(msg != NULL); 12812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 12912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Update this stop description. 13012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (!watched_stops_[code].desc) { 13112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org watched_stops_[code].desc = msg; 13212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 13312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 13412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (strlen(msg) > 0) { 13512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (coverage_log != NULL) { 13612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org fprintf(coverage_log, "%s\n", str); 13712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org fflush(coverage_log); 13812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 13912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Overwrite the instruction and address with nops. 14012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org instr->SetInstructionBits(kNopInstr); 14112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org reinterpret_cast<Instr*>(msg_address)->SetInstructionBits(kNopInstr); 14212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 14312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // TODO(yuyin): 2 -> 3? 14412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org sim_->set_pc(sim_->get_pc() + 3 * Instruction::kInstructionSize); 14512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org} 14612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 14712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 14812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org#else // GENERATED_CODE_COVERAGE 14912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 15012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org#define UNSUPPORTED() printf("Unsupported instruction.\n"); 15112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 15212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgstatic void InitializeCoverage() {} 15312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 15412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 15512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgvoid MipsDebugger::Stop(Instruction* instr) { 15612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Get the stop code. 15712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org uint32_t code = instr->Bits(25, 6); 15812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Retrieve the encoded address, which comes just after this stop. 15912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org char* msg = *reinterpret_cast<char**>(sim_->get_pc() + 16012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Instruction::kInstrSize); 16112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Update this stop description. 16212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (!sim_->watched_stops_[code].desc) { 16312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org sim_->watched_stops_[code].desc = msg; 16412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 16512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org PrintF("Simulator hit %s (%u)\n", msg, code); 16612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // TODO(yuyin): 2 -> 3? 16712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org sim_->set_pc(sim_->get_pc() + 3 * Instruction::kInstrSize); 16812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Debug(); 16912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org} 17012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org#endif // GENERATED_CODE_COVERAGE 17112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 17212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 17312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgint64_t MipsDebugger::GetRegisterValue(int regnum) { 17412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (regnum == kNumSimuRegisters) { 17512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org return sim_->get_pc(); 17612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } else { 17712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org return sim_->get_register(regnum); 17812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 17912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org} 18012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 18112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 18212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgint64_t MipsDebugger::GetFPURegisterValue(int regnum) { 18312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (regnum == kNumFPURegisters) { 18412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org return sim_->get_pc(); 18512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } else { 18612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org return sim_->get_fpu_register(regnum); 18712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 18812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org} 18912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 19012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 19112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgfloat MipsDebugger::GetFPURegisterValueFloat(int regnum) { 19212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (regnum == kNumFPURegisters) { 19312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org return sim_->get_pc(); 19412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } else { 19512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org return sim_->get_fpu_register_float(regnum); 19612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 19712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org} 19812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 19912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 20012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgdouble MipsDebugger::GetFPURegisterValueDouble(int regnum) { 20112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (regnum == kNumFPURegisters) { 20212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org return sim_->get_pc(); 20312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } else { 20412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org return sim_->get_fpu_register_double(regnum); 20512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 20612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org} 20712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 20812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 20912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgbool MipsDebugger::GetValue(const char* desc, int64_t* value) { 21012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org int regnum = Registers::Number(desc); 21112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org int fpuregnum = FPURegisters::Number(desc); 21212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 21312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (regnum != kInvalidRegister) { 21412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org *value = GetRegisterValue(regnum); 21512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org return true; 21612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } else if (fpuregnum != kInvalidFPURegister) { 21712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org *value = GetFPURegisterValue(fpuregnum); 21812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org return true; 21912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } else if (strncmp(desc, "0x", 2) == 0) { 22012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org return SScanF(desc + 2, "%" SCNx64, 22112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org reinterpret_cast<uint64_t*>(value)) == 1; 22212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } else { 22312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org return SScanF(desc, "%" SCNu64, reinterpret_cast<uint64_t*>(value)) == 1; 22412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 22512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org return false; 22612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org} 22712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 22812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 22912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgbool MipsDebugger::SetBreakpoint(Instruction* breakpc) { 23012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Check if a breakpoint can be set. If not return without any side-effects. 23112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (sim_->break_pc_ != NULL) { 23212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org return false; 23312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 23412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 23512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Set the breakpoint. 23612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org sim_->break_pc_ = breakpc; 23712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org sim_->break_instr_ = breakpc->InstructionBits(); 23812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Not setting the breakpoint instruction in the code itself. It will be set 23912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // when the debugger shell continues. 24012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org return true; 24112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org} 24212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 24312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 24412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgbool MipsDebugger::DeleteBreakpoint(Instruction* breakpc) { 24512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (sim_->break_pc_ != NULL) { 24612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org sim_->break_pc_->SetInstructionBits(sim_->break_instr_); 24712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 24812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 24912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org sim_->break_pc_ = NULL; 25012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org sim_->break_instr_ = 0; 25112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org return true; 25212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org} 25312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 25412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 25512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgvoid MipsDebugger::UndoBreakpoints() { 25612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (sim_->break_pc_ != NULL) { 25712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org sim_->break_pc_->SetInstructionBits(sim_->break_instr_); 25812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 25912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org} 26012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 26112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 26212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgvoid MipsDebugger::RedoBreakpoints() { 26312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (sim_->break_pc_ != NULL) { 26412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org sim_->break_pc_->SetInstructionBits(kBreakpointInstr); 26512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 26612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org} 26712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 26812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 26912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgvoid MipsDebugger::PrintAllRegs() { 27012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org#define REG_INFO(n) Registers::Name(n), GetRegisterValue(n), GetRegisterValue(n) 27112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 27212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org PrintF("\n"); 27312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // at, v0, a0. 27412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org PrintF("%3s: 0x%016lx %14ld\t%3s: 0x%016lx %14ld\t%3s: 0x%016lx %14ld\n", 27512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org REG_INFO(1), REG_INFO(2), REG_INFO(4)); 27612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // v1, a1. 27712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org PrintF("%34s\t%3s: 0x%016lx %14ld\t%3s: 0x%016lx %14ld\n", 27812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org "", REG_INFO(3), REG_INFO(5)); 27912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // a2. 28012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org PrintF("%34s\t%34s\t%3s: 0x%016lx %14ld\n", "", "", REG_INFO(6)); 28112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // a3. 28212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org PrintF("%34s\t%34s\t%3s: 0x%016lx %14ld\n", "", "", REG_INFO(7)); 28312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org PrintF("\n"); 28412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // a4-t3, s0-s7 28512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org for (int i = 0; i < 8; i++) { 28612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org PrintF("%3s: 0x%016lx %14ld\t%3s: 0x%016lx %14ld\n", 28712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org REG_INFO(8+i), REG_INFO(16+i)); 28812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 28912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org PrintF("\n"); 29012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // t8, k0, LO. 29112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org PrintF("%3s: 0x%016lx %14ld\t%3s: 0x%016lx %14ld\t%3s: 0x%016lx %14ld\n", 29212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org REG_INFO(24), REG_INFO(26), REG_INFO(32)); 29312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // t9, k1, HI. 29412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org PrintF("%3s: 0x%016lx %14ld\t%3s: 0x%016lx %14ld\t%3s: 0x%016lx %14ld\n", 29512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org REG_INFO(25), REG_INFO(27), REG_INFO(33)); 29612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // sp, fp, gp. 29712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org PrintF("%3s: 0x%016lx %14ld\t%3s: 0x%016lx %14ld\t%3s: 0x%016lx %14ld\n", 29812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org REG_INFO(29), REG_INFO(30), REG_INFO(28)); 29912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // pc. 30012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org PrintF("%3s: 0x%016lx %14ld\t%3s: 0x%016lx %14ld\n", 30112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org REG_INFO(31), REG_INFO(34)); 30212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 30312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org#undef REG_INFO 30412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org#undef FPU_REG_INFO 30512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org} 30612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 30712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 30812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgvoid MipsDebugger::PrintAllRegsIncludingFPU() { 30912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org#define FPU_REG_INFO(n) FPURegisters::Name(n), \ 31012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org GetFPURegisterValue(n), \ 31112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org GetFPURegisterValueDouble(n) 31212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 31312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org PrintAllRegs(); 31412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 31512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org PrintF("\n\n"); 31612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // f0, f1, f2, ... f31. 31712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // TODO(plind): consider printing 2 columns for space efficiency. 31812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org PrintF("%3s: 0x%016lx %16.4e\n", FPU_REG_INFO(0) ); 31912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org PrintF("%3s: 0x%016lx %16.4e\n", FPU_REG_INFO(1) ); 32012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org PrintF("%3s: 0x%016lx %16.4e\n", FPU_REG_INFO(2) ); 32112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org PrintF("%3s: 0x%016lx %16.4e\n", FPU_REG_INFO(3) ); 32212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org PrintF("%3s: 0x%016lx %16.4e\n", FPU_REG_INFO(4) ); 32312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org PrintF("%3s: 0x%016lx %16.4e\n", FPU_REG_INFO(5) ); 32412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org PrintF("%3s: 0x%016lx %16.4e\n", FPU_REG_INFO(6) ); 32512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org PrintF("%3s: 0x%016lx %16.4e\n", FPU_REG_INFO(7) ); 32612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org PrintF("%3s: 0x%016lx %16.4e\n", FPU_REG_INFO(8) ); 32712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org PrintF("%3s: 0x%016lx %16.4e\n", FPU_REG_INFO(9) ); 32812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org PrintF("%3s: 0x%016lx %16.4e\n", FPU_REG_INFO(10)); 32912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org PrintF("%3s: 0x%016lx %16.4e\n", FPU_REG_INFO(11)); 33012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org PrintF("%3s: 0x%016lx %16.4e\n", FPU_REG_INFO(12)); 33112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org PrintF("%3s: 0x%016lx %16.4e\n", FPU_REG_INFO(13)); 33212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org PrintF("%3s: 0x%016lx %16.4e\n", FPU_REG_INFO(14)); 33312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org PrintF("%3s: 0x%016lx %16.4e\n", FPU_REG_INFO(15)); 33412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org PrintF("%3s: 0x%016lx %16.4e\n", FPU_REG_INFO(16)); 33512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org PrintF("%3s: 0x%016lx %16.4e\n", FPU_REG_INFO(17)); 33612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org PrintF("%3s: 0x%016lx %16.4e\n", FPU_REG_INFO(18)); 33712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org PrintF("%3s: 0x%016lx %16.4e\n", FPU_REG_INFO(19)); 33812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org PrintF("%3s: 0x%016lx %16.4e\n", FPU_REG_INFO(20)); 33912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org PrintF("%3s: 0x%016lx %16.4e\n", FPU_REG_INFO(21)); 34012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org PrintF("%3s: 0x%016lx %16.4e\n", FPU_REG_INFO(22)); 34112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org PrintF("%3s: 0x%016lx %16.4e\n", FPU_REG_INFO(23)); 34212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org PrintF("%3s: 0x%016lx %16.4e\n", FPU_REG_INFO(24)); 34312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org PrintF("%3s: 0x%016lx %16.4e\n", FPU_REG_INFO(25)); 34412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org PrintF("%3s: 0x%016lx %16.4e\n", FPU_REG_INFO(26)); 34512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org PrintF("%3s: 0x%016lx %16.4e\n", FPU_REG_INFO(27)); 34612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org PrintF("%3s: 0x%016lx %16.4e\n", FPU_REG_INFO(28)); 34712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org PrintF("%3s: 0x%016lx %16.4e\n", FPU_REG_INFO(29)); 34812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org PrintF("%3s: 0x%016lx %16.4e\n", FPU_REG_INFO(30)); 34912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org PrintF("%3s: 0x%016lx %16.4e\n", FPU_REG_INFO(31)); 35012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 35112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org#undef REG_INFO 35212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org#undef FPU_REG_INFO 35312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org} 35412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 35512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 35612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgvoid MipsDebugger::Debug() { 35712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org intptr_t last_pc = -1; 35812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org bool done = false; 35912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 36012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org#define COMMAND_SIZE 63 36112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org#define ARG_SIZE 255 36212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 36312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org#define STR(a) #a 36412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org#define XSTR(a) STR(a) 36512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 36612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org char cmd[COMMAND_SIZE + 1]; 36712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org char arg1[ARG_SIZE + 1]; 36812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org char arg2[ARG_SIZE + 1]; 36912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org char* argv[3] = { cmd, arg1, arg2 }; 37012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 37112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Make sure to have a proper terminating character if reaching the limit. 37212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org cmd[COMMAND_SIZE] = 0; 37312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org arg1[ARG_SIZE] = 0; 37412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org arg2[ARG_SIZE] = 0; 37512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 37612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Undo all set breakpoints while running in the debugger shell. This will 37712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // make them invisible to all commands. 37812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org UndoBreakpoints(); 37912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 38012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org while (!done && (sim_->get_pc() != Simulator::end_sim_pc)) { 38112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (last_pc != sim_->get_pc()) { 38212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org disasm::NameConverter converter; 38312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org disasm::Disassembler dasm(converter); 38412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Use a reasonably large buffer. 38512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org v8::internal::EmbeddedVector<char, 256> buffer; 38612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org dasm.InstructionDecode(buffer, 38712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org reinterpret_cast<byte*>(sim_->get_pc())); 38812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org PrintF(" 0x%016lx %s\n", sim_->get_pc(), buffer.start()); 38912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org last_pc = sim_->get_pc(); 39012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 39112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org char* line = ReadLine("sim> "); 39212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (line == NULL) { 39312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org break; 39412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } else { 39512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org char* last_input = sim_->last_debugger_input(); 39612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (strcmp(line, "\n") == 0 && last_input != NULL) { 39712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org line = last_input; 39812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } else { 39912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Ownership is transferred to sim_; 40012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org sim_->set_last_debugger_input(line); 40112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 40212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Use sscanf to parse the individual parts of the command line. At the 40312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // moment no command expects more than two parameters. 40412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org int argc = SScanF(line, 40512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org "%" XSTR(COMMAND_SIZE) "s " 40612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org "%" XSTR(ARG_SIZE) "s " 40712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org "%" XSTR(ARG_SIZE) "s", 40812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org cmd, arg1, arg2); 40912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if ((strcmp(cmd, "si") == 0) || (strcmp(cmd, "stepi") == 0)) { 41012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Instruction* instr = reinterpret_cast<Instruction*>(sim_->get_pc()); 41112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (!(instr->IsTrap()) || 41212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org instr->InstructionBits() == rtCallRedirInstr) { 41312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org sim_->InstructionDecode( 41412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org reinterpret_cast<Instruction*>(sim_->get_pc())); 41512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } else { 41612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Allow si to jump over generated breakpoints. 41712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org PrintF("/!\\ Jumping over generated breakpoint.\n"); 41812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org sim_->set_pc(sim_->get_pc() + Instruction::kInstrSize); 41912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 42012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } else if ((strcmp(cmd, "c") == 0) || (strcmp(cmd, "cont") == 0)) { 42112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Execute the one instruction we broke at with breakpoints disabled. 42212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org sim_->InstructionDecode(reinterpret_cast<Instruction*>(sim_->get_pc())); 42312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Leave the debugger shell. 42412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org done = true; 42512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } else if ((strcmp(cmd, "p") == 0) || (strcmp(cmd, "print") == 0)) { 42612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (argc == 2) { 42712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org int64_t value; 42812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org double dvalue; 42912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (strcmp(arg1, "all") == 0) { 43012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org PrintAllRegs(); 43112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } else if (strcmp(arg1, "allf") == 0) { 43212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org PrintAllRegsIncludingFPU(); 43312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } else { 43412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org int regnum = Registers::Number(arg1); 43512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org int fpuregnum = FPURegisters::Number(arg1); 43612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 43712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (regnum != kInvalidRegister) { 43812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org value = GetRegisterValue(regnum); 43912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org PrintF("%s: 0x%08lx %ld \n", arg1, value, value); 44012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } else if (fpuregnum != kInvalidFPURegister) { 44112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org value = GetFPURegisterValue(fpuregnum); 44212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org dvalue = GetFPURegisterValueDouble(fpuregnum); 44312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org PrintF("%3s: 0x%016lx %16.4e\n", 44412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org FPURegisters::Name(fpuregnum), value, dvalue); 44512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } else { 44612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org PrintF("%s unrecognized\n", arg1); 44712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 44812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 44912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } else { 45012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (argc == 3) { 45112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (strcmp(arg2, "single") == 0) { 45212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org int64_t value; 45312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org float fvalue; 45412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org int fpuregnum = FPURegisters::Number(arg1); 45512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 45612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (fpuregnum != kInvalidFPURegister) { 45712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org value = GetFPURegisterValue(fpuregnum); 45812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org value &= 0xffffffffUL; 45912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org fvalue = GetFPURegisterValueFloat(fpuregnum); 46012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org PrintF("%s: 0x%08lx %11.4e\n", arg1, value, fvalue); 46112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } else { 46212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org PrintF("%s unrecognized\n", arg1); 46312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 46412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } else { 46512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org PrintF("print <fpu register> single\n"); 46612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 46712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } else { 46812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org PrintF("print <register> or print <fpu register> single\n"); 46912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 47012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 47112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } else if ((strcmp(cmd, "po") == 0) 47212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org || (strcmp(cmd, "printobject") == 0)) { 47312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (argc == 2) { 47412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org int64_t value; 47512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org OFStream os(stdout); 47612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (GetValue(arg1, &value)) { 47712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Object* obj = reinterpret_cast<Object*>(value); 47812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org os << arg1 << ": \n"; 47912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org#ifdef DEBUG 48012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org obj->Print(os); 48112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org os << "\n"; 48212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org#else 48312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org os << Brief(obj) << "\n"; 48412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org#endif 48512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } else { 48612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org os << arg1 << " unrecognized\n"; 48712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 48812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } else { 48912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org PrintF("printobject <value>\n"); 49012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 49112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } else if (strcmp(cmd, "stack") == 0 || strcmp(cmd, "mem") == 0) { 49212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org int64_t* cur = NULL; 49312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org int64_t* end = NULL; 49412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org int next_arg = 1; 49512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 49612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (strcmp(cmd, "stack") == 0) { 49712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org cur = reinterpret_cast<int64_t*>(sim_->get_register(Simulator::sp)); 49812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } else { // Command "mem". 49912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org int64_t value; 50012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (!GetValue(arg1, &value)) { 50112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org PrintF("%s unrecognized\n", arg1); 50212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org continue; 50312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 50412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org cur = reinterpret_cast<int64_t*>(value); 50512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org next_arg++; 50612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 50712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 50812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org int64_t words; 50912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (argc == next_arg) { 51012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org words = 10; 51112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } else { 51212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (!GetValue(argv[next_arg], &words)) { 51312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org words = 10; 51412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 51512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 51612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org end = cur + words; 51712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 51812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org while (cur < end) { 51912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org PrintF(" 0x%012lx: 0x%016lx %14ld", 52012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org reinterpret_cast<intptr_t>(cur), *cur, *cur); 52112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org HeapObject* obj = reinterpret_cast<HeapObject*>(*cur); 52212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org int64_t value = *cur; 52312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Heap* current_heap = v8::internal::Isolate::Current()->heap(); 52412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (((value & 1) == 0) || current_heap->Contains(obj)) { 52512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org PrintF(" ("); 52612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if ((value & 1) == 0) { 52712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org PrintF("smi %d", static_cast<int>(value >> 32)); 52812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } else { 52912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org obj->ShortPrint(); 53012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 53112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org PrintF(")"); 53212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 53312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org PrintF("\n"); 53412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org cur++; 53512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 53612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 53712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } else if ((strcmp(cmd, "disasm") == 0) || 53812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org (strcmp(cmd, "dpc") == 0) || 53912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org (strcmp(cmd, "di") == 0)) { 54012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org disasm::NameConverter converter; 54112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org disasm::Disassembler dasm(converter); 54212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Use a reasonably large buffer. 54312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org v8::internal::EmbeddedVector<char, 256> buffer; 54412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 54512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org byte* cur = NULL; 54612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org byte* end = NULL; 54712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 54812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (argc == 1) { 54912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org cur = reinterpret_cast<byte*>(sim_->get_pc()); 55012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org end = cur + (10 * Instruction::kInstrSize); 55112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } else if (argc == 2) { 55212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org int regnum = Registers::Number(arg1); 55312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (regnum != kInvalidRegister || strncmp(arg1, "0x", 2) == 0) { 55412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // The argument is an address or a register name. 55512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org int64_t value; 55612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (GetValue(arg1, &value)) { 55712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org cur = reinterpret_cast<byte*>(value); 55812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Disassemble 10 instructions at <arg1>. 55912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org end = cur + (10 * Instruction::kInstrSize); 56012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 56112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } else { 56212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // The argument is the number of instructions. 56312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org int64_t value; 56412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (GetValue(arg1, &value)) { 56512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org cur = reinterpret_cast<byte*>(sim_->get_pc()); 56612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Disassemble <arg1> instructions. 56712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org end = cur + (value * Instruction::kInstrSize); 56812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 56912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 57012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } else { 57112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org int64_t value1; 57212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org int64_t value2; 57312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (GetValue(arg1, &value1) && GetValue(arg2, &value2)) { 57412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org cur = reinterpret_cast<byte*>(value1); 57512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org end = cur + (value2 * Instruction::kInstrSize); 57612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 57712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 57812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 57912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org while (cur < end) { 58012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org dasm.InstructionDecode(buffer, cur); 58112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org PrintF(" 0x%08lx %s\n", 58212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org reinterpret_cast<intptr_t>(cur), buffer.start()); 58312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org cur += Instruction::kInstrSize; 58412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 58512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } else if (strcmp(cmd, "gdb") == 0) { 58612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org PrintF("relinquishing control to gdb\n"); 58712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org v8::base::OS::DebugBreak(); 58812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org PrintF("regaining control from gdb\n"); 58912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } else if (strcmp(cmd, "break") == 0) { 59012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (argc == 2) { 59112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org int64_t value; 59212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (GetValue(arg1, &value)) { 59312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (!SetBreakpoint(reinterpret_cast<Instruction*>(value))) { 59412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org PrintF("setting breakpoint failed\n"); 59512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 59612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } else { 59712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org PrintF("%s unrecognized\n", arg1); 59812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 59912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } else { 60012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org PrintF("break <address>\n"); 60112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 60212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } else if (strcmp(cmd, "del") == 0) { 60312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (!DeleteBreakpoint(NULL)) { 60412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org PrintF("deleting breakpoint failed\n"); 60512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 60612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } else if (strcmp(cmd, "flags") == 0) { 60712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org PrintF("No flags on MIPS !\n"); 60812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } else if (strcmp(cmd, "stop") == 0) { 60912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org int64_t value; 61012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org intptr_t stop_pc = sim_->get_pc() - 61112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 2 * Instruction::kInstrSize; 61212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Instruction* stop_instr = reinterpret_cast<Instruction*>(stop_pc); 61312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Instruction* msg_address = 61412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org reinterpret_cast<Instruction*>(stop_pc + 61512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Instruction::kInstrSize); 61612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if ((argc == 2) && (strcmp(arg1, "unstop") == 0)) { 61712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Remove the current stop. 61812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (sim_->IsStopInstruction(stop_instr)) { 61912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org stop_instr->SetInstructionBits(kNopInstr); 62012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org msg_address->SetInstructionBits(kNopInstr); 62112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } else { 62212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org PrintF("Not at debugger stop.\n"); 62312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 62412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } else if (argc == 3) { 62512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Print information about all/the specified breakpoint(s). 62612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (strcmp(arg1, "info") == 0) { 62712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (strcmp(arg2, "all") == 0) { 62812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org PrintF("Stop information:\n"); 62912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org for (uint32_t i = kMaxWatchpointCode + 1; 63012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org i <= kMaxStopCode; 63112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org i++) { 63212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org sim_->PrintStopInfo(i); 63312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 63412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } else if (GetValue(arg2, &value)) { 63512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org sim_->PrintStopInfo(value); 63612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } else { 63712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org PrintF("Unrecognized argument.\n"); 63812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 63912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } else if (strcmp(arg1, "enable") == 0) { 64012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Enable all/the specified breakpoint(s). 64112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (strcmp(arg2, "all") == 0) { 64212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org for (uint32_t i = kMaxWatchpointCode + 1; 64312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org i <= kMaxStopCode; 64412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org i++) { 64512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org sim_->EnableStop(i); 64612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 64712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } else if (GetValue(arg2, &value)) { 64812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org sim_->EnableStop(value); 64912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } else { 65012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org PrintF("Unrecognized argument.\n"); 65112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 65212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } else if (strcmp(arg1, "disable") == 0) { 65312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Disable all/the specified breakpoint(s). 65412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (strcmp(arg2, "all") == 0) { 65512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org for (uint32_t i = kMaxWatchpointCode + 1; 65612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org i <= kMaxStopCode; 65712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org i++) { 65812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org sim_->DisableStop(i); 65912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 66012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } else if (GetValue(arg2, &value)) { 66112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org sim_->DisableStop(value); 66212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } else { 66312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org PrintF("Unrecognized argument.\n"); 66412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 66512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 66612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } else { 66712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org PrintF("Wrong usage. Use help command for more information.\n"); 66812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 66912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } else if ((strcmp(cmd, "stat") == 0) || (strcmp(cmd, "st") == 0)) { 67012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Print registers and disassemble. 67112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org PrintAllRegs(); 67212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org PrintF("\n"); 67312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 67412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org disasm::NameConverter converter; 67512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org disasm::Disassembler dasm(converter); 67612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Use a reasonably large buffer. 67712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org v8::internal::EmbeddedVector<char, 256> buffer; 67812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 67912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org byte* cur = NULL; 68012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org byte* end = NULL; 68112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 68212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (argc == 1) { 68312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org cur = reinterpret_cast<byte*>(sim_->get_pc()); 68412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org end = cur + (10 * Instruction::kInstrSize); 68512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } else if (argc == 2) { 68612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org int64_t value; 68712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (GetValue(arg1, &value)) { 68812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org cur = reinterpret_cast<byte*>(value); 68912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // no length parameter passed, assume 10 instructions 69012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org end = cur + (10 * Instruction::kInstrSize); 69112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 69212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } else { 69312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org int64_t value1; 69412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org int64_t value2; 69512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (GetValue(arg1, &value1) && GetValue(arg2, &value2)) { 69612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org cur = reinterpret_cast<byte*>(value1); 69712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org end = cur + (value2 * Instruction::kInstrSize); 69812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 69912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 70012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 70112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org while (cur < end) { 70212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org dasm.InstructionDecode(buffer, cur); 70312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org PrintF(" 0x%08lx %s\n", 70412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org reinterpret_cast<intptr_t>(cur), buffer.start()); 70512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org cur += Instruction::kInstrSize; 70612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 70712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } else if ((strcmp(cmd, "h") == 0) || (strcmp(cmd, "help") == 0)) { 70812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org PrintF("cont\n"); 70912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org PrintF(" continue execution (alias 'c')\n"); 71012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org PrintF("stepi\n"); 71112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org PrintF(" step one instruction (alias 'si')\n"); 71212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org PrintF("print <register>\n"); 71312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org PrintF(" print register content (alias 'p')\n"); 71412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org PrintF(" use register name 'all' to print all registers\n"); 71512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org PrintF("printobject <register>\n"); 71612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org PrintF(" print an object from a register (alias 'po')\n"); 71712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org PrintF("stack [<words>]\n"); 71812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org PrintF(" dump stack content, default dump 10 words)\n"); 71912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org PrintF("mem <address> [<words>]\n"); 72012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org PrintF(" dump memory content, default dump 10 words)\n"); 72112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org PrintF("flags\n"); 72212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org PrintF(" print flags\n"); 72312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org PrintF("disasm [<instructions>]\n"); 72412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org PrintF("disasm [<address/register>]\n"); 72512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org PrintF("disasm [[<address/register>] <instructions>]\n"); 72612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org PrintF(" disassemble code, default is 10 instructions\n"); 72712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org PrintF(" from pc (alias 'di')\n"); 72812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org PrintF("gdb\n"); 72912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org PrintF(" enter gdb\n"); 73012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org PrintF("break <address>\n"); 73112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org PrintF(" set a break point on the address\n"); 73212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org PrintF("del\n"); 73312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org PrintF(" delete the breakpoint\n"); 73412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org PrintF("stop feature:\n"); 73512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org PrintF(" Description:\n"); 73612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org PrintF(" Stops are debug instructions inserted by\n"); 73712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org PrintF(" the Assembler::stop() function.\n"); 73812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org PrintF(" When hitting a stop, the Simulator will\n"); 73912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org PrintF(" stop and and give control to the Debugger.\n"); 74012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org PrintF(" All stop codes are watched:\n"); 74112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org PrintF(" - They can be enabled / disabled: the Simulator\n"); 74212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org PrintF(" will / won't stop when hitting them.\n"); 74312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org PrintF(" - The Simulator keeps track of how many times they \n"); 74412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org PrintF(" are met. (See the info command.) Going over a\n"); 74512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org PrintF(" disabled stop still increases its counter. \n"); 74612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org PrintF(" Commands:\n"); 74712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org PrintF(" stop info all/<code> : print infos about number <code>\n"); 74812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org PrintF(" or all stop(s).\n"); 74912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org PrintF(" stop enable/disable all/<code> : enables / disables\n"); 75012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org PrintF(" all or number <code> stop(s)\n"); 75112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org PrintF(" stop unstop\n"); 75212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org PrintF(" ignore the stop instruction at the current location\n"); 75312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org PrintF(" from now on\n"); 75412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } else { 75512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org PrintF("Unknown command: %s\n", cmd); 75612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 75712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 75812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 75912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 76012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Add all the breakpoints back to stop execution and enter the debugger 76112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // shell when hit. 76212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org RedoBreakpoints(); 76312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 76412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org#undef COMMAND_SIZE 76512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org#undef ARG_SIZE 76612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 76712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org#undef STR 76812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org#undef XSTR 76912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org} 77012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 77112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 77212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgstatic bool ICacheMatch(void* one, void* two) { 773e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK((reinterpret_cast<intptr_t>(one) & CachePage::kPageMask) == 0); 774e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK((reinterpret_cast<intptr_t>(two) & CachePage::kPageMask) == 0); 77512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org return one == two; 77612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org} 77712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 77812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 77912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgstatic uint32_t ICacheHash(void* key) { 78012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org return static_cast<uint32_t>(reinterpret_cast<uintptr_t>(key)) >> 2; 78112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org} 78212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 78312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 78412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgstatic bool AllOnOnePage(uintptr_t start, int size) { 78512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org intptr_t start_page = (start & ~CachePage::kPageMask); 78612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org intptr_t end_page = ((start + size) & ~CachePage::kPageMask); 78712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org return start_page == end_page; 78812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org} 78912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 79012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 79112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgvoid Simulator::set_last_debugger_input(char* input) { 79212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org DeleteArray(last_debugger_input_); 79312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org last_debugger_input_ = input; 79412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org} 79512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 79612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 79712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgvoid Simulator::FlushICache(v8::internal::HashMap* i_cache, 79812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org void* start_addr, 79912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org size_t size) { 80012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org int64_t start = reinterpret_cast<int64_t>(start_addr); 80112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org int64_t intra_line = (start & CachePage::kLineMask); 80212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org start -= intra_line; 80312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org size += intra_line; 80412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org size = ((size - 1) | CachePage::kLineMask) + 1; 80512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org int offset = (start & CachePage::kPageMask); 80612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org while (!AllOnOnePage(start, size - 1)) { 80712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org int bytes_to_flush = CachePage::kPageSize - offset; 80812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org FlushOnePage(i_cache, start, bytes_to_flush); 80912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org start += bytes_to_flush; 81012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org size -= bytes_to_flush; 811e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK_EQ((uint64_t)0, start & CachePage::kPageMask); 81212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org offset = 0; 81312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 81412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (size != 0) { 81512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org FlushOnePage(i_cache, start, size); 81612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 81712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org} 81812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 81912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 82012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgCachePage* Simulator::GetCachePage(v8::internal::HashMap* i_cache, void* page) { 82112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org v8::internal::HashMap::Entry* entry = i_cache->Lookup(page, 82212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org ICacheHash(page), 82312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org true); 82412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (entry->value == NULL) { 82512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org CachePage* new_page = new CachePage(); 82612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org entry->value = new_page; 82712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 82812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org return reinterpret_cast<CachePage*>(entry->value); 82912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org} 83012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 83112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 83212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// Flush from start up to and not including start + size. 83312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgvoid Simulator::FlushOnePage(v8::internal::HashMap* i_cache, 83412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org intptr_t start, 83512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org int size) { 836e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK(size <= CachePage::kPageSize); 837e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK(AllOnOnePage(start, size - 1)); 838e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK((start & CachePage::kLineMask) == 0); 839e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK((size & CachePage::kLineMask) == 0); 84012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org void* page = reinterpret_cast<void*>(start & (~CachePage::kPageMask)); 84112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org int offset = (start & CachePage::kPageMask); 84212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org CachePage* cache_page = GetCachePage(i_cache, page); 84312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org char* valid_bytemap = cache_page->ValidityByte(offset); 84412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org memset(valid_bytemap, CachePage::LINE_INVALID, size >> CachePage::kLineShift); 84512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org} 84612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 84712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 84812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgvoid Simulator::CheckICache(v8::internal::HashMap* i_cache, 84912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Instruction* instr) { 85012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org int64_t address = reinterpret_cast<int64_t>(instr); 85112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org void* page = reinterpret_cast<void*>(address & (~CachePage::kPageMask)); 85212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org void* line = reinterpret_cast<void*>(address & (~CachePage::kLineMask)); 85312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org int offset = (address & CachePage::kPageMask); 85412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org CachePage* cache_page = GetCachePage(i_cache, page); 85512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org char* cache_valid_byte = cache_page->ValidityByte(offset); 85612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org bool cache_hit = (*cache_valid_byte == CachePage::LINE_VALID); 85712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org char* cached_line = cache_page->CachedData(offset & ~CachePage::kLineMask); 85812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (cache_hit) { 85912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Check that the data in memory matches the contents of the I-cache. 86012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org CHECK_EQ(0, memcmp(reinterpret_cast<void*>(instr), 86112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org cache_page->CachedData(offset), 86212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Instruction::kInstrSize)); 86312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } else { 86412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Cache miss. Load memory into the cache. 86512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org memcpy(cached_line, line, CachePage::kLineLength); 86612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org *cache_valid_byte = CachePage::LINE_VALID; 86712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 86812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org} 86912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 87012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 87112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgvoid Simulator::Initialize(Isolate* isolate) { 87212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (isolate->simulator_initialized()) return; 87312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org isolate->set_simulator_initialized(true); 87412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org ::v8::internal::ExternalReference::set_redirector(isolate, 87512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org &RedirectExternalReference); 87612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org} 87712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 87812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 87912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgSimulator::Simulator(Isolate* isolate) : isolate_(isolate) { 88012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org i_cache_ = isolate_->simulator_i_cache(); 88112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (i_cache_ == NULL) { 88212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org i_cache_ = new v8::internal::HashMap(&ICacheMatch); 88312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org isolate_->set_simulator_i_cache(i_cache_); 88412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 88512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Initialize(isolate); 88612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Set up simulator support first. Some of this information is needed to 88712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // setup the architecture state. 88812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org stack_size_ = FLAG_sim_stack_size * KB; 88912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org stack_ = reinterpret_cast<char*>(malloc(stack_size_)); 89012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org pc_modified_ = false; 89112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org icount_ = 0; 89212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org break_count_ = 0; 89312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org break_pc_ = NULL; 89412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org break_instr_ = 0; 89512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 89612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Set up architecture state. 89712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // All registers are initialized to zero to start with. 89812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org for (int i = 0; i < kNumSimuRegisters; i++) { 89912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org registers_[i] = 0; 90012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 90112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org for (int i = 0; i < kNumFPURegisters; i++) { 90212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org FPUregisters_[i] = 0; 90312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 90412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org FCSR_ = 0; 90512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 90612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // The sp is initialized to point to the bottom (high address) of the 90712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // allocated stack area. To be safe in potential stack underflows we leave 90812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // some buffer below. 90912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org registers_[sp] = reinterpret_cast<int64_t>(stack_) + stack_size_ - 64; 91012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // The ra and pc are initialized to a known bad value that will cause an 91112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // access violation if the simulator ever tries to execute it. 91212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org registers_[pc] = bad_ra; 91312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org registers_[ra] = bad_ra; 91412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org InitializeCoverage(); 91512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org for (int i = 0; i < kNumExceptions; i++) { 91612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org exceptions[i] = 0; 91712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 91812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 91912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org last_debugger_input_ = NULL; 92012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org} 92112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 92212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 92312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgSimulator::~Simulator() { 92412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org} 92512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 92612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 92712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// When the generated code calls an external reference we need to catch that in 92812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// the simulator. The external reference will be a function compiled for the 92912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// host architecture. We need to call that function instead of trying to 93012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// execute it with the simulator. We do that by redirecting the external 93112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// reference to a swi (software-interrupt) instruction that is handled by 93212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// the simulator. We write the original destination of the jump just at a known 93312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// offset from the swi instruction so the simulator knows what to call. 93412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgclass Redirection { 93512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org public: 93612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Redirection(void* external_function, ExternalReference::Type type) 93712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org : external_function_(external_function), 93812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org swi_instruction_(rtCallRedirInstr), 93912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org type_(type), 94012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org next_(NULL) { 94112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Isolate* isolate = Isolate::Current(); 94212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org next_ = isolate->simulator_redirection(); 94312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Simulator::current(isolate)-> 94412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org FlushICache(isolate->simulator_i_cache(), 94512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org reinterpret_cast<void*>(&swi_instruction_), 94612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Instruction::kInstrSize); 94712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org isolate->set_simulator_redirection(this); 94812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 94912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 95012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org void* address_of_swi_instruction() { 95112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org return reinterpret_cast<void*>(&swi_instruction_); 95212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 95312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 95412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org void* external_function() { return external_function_; } 95512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org ExternalReference::Type type() { return type_; } 95612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 95712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org static Redirection* Get(void* external_function, 95812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org ExternalReference::Type type) { 95912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Isolate* isolate = Isolate::Current(); 96012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Redirection* current = isolate->simulator_redirection(); 96112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org for (; current != NULL; current = current->next_) { 96212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (current->external_function_ == external_function) return current; 96312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 96412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org return new Redirection(external_function, type); 96512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 96612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 96712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org static Redirection* FromSwiInstruction(Instruction* swi_instruction) { 96812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org char* addr_of_swi = reinterpret_cast<char*>(swi_instruction); 96912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org char* addr_of_redirection = 97012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org addr_of_swi - OFFSET_OF(Redirection, swi_instruction_); 97112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org return reinterpret_cast<Redirection*>(addr_of_redirection); 97212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 97312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 97412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org static void* ReverseRedirection(int64_t reg) { 97512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Redirection* redirection = FromSwiInstruction( 97612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org reinterpret_cast<Instruction*>(reinterpret_cast<void*>(reg))); 97712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org return redirection->external_function(); 97812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 97912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 98012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org private: 98112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org void* external_function_; 98212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org uint32_t swi_instruction_; 98312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org ExternalReference::Type type_; 98412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Redirection* next_; 98512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org}; 98612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 98712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 98812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgvoid* Simulator::RedirectExternalReference(void* external_function, 98912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org ExternalReference::Type type) { 99012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Redirection* redirection = Redirection::Get(external_function, type); 99112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org return redirection->address_of_swi_instruction(); 99212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org} 99312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 99412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 99512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// Get the active Simulator for the current thread. 99612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgSimulator* Simulator::current(Isolate* isolate) { 99712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org v8::internal::Isolate::PerIsolateThreadData* isolate_data = 99812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org isolate->FindOrAllocatePerThreadDataForThisThread(); 999e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK(isolate_data != NULL); 1000e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK(isolate_data != NULL); 100112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 100212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Simulator* sim = isolate_data->simulator(); 100312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (sim == NULL) { 100412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // TODO(146): delete the simulator object when a thread/isolate goes away. 100512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org sim = new Simulator(isolate); 100612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org isolate_data->set_simulator(sim); 100712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 100812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org return sim; 100912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org} 101012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 101112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 101212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// Sets the register in the architecture state. It will also deal with updating 101312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// Simulator internal state for special registers such as PC. 101412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgvoid Simulator::set_register(int reg, int64_t value) { 1015e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK((reg >= 0) && (reg < kNumSimuRegisters)); 101612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (reg == pc) { 101712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org pc_modified_ = true; 101812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 101912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 102012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Zero register always holds 0. 102112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org registers_[reg] = (reg == 0) ? 0 : value; 102212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org} 102312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 102412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 102512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgvoid Simulator::set_dw_register(int reg, const int* dbl) { 1026e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK((reg >= 0) && (reg < kNumSimuRegisters)); 102712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org registers_[reg] = dbl[1]; 102812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org registers_[reg] = registers_[reg] << 32; 102912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org registers_[reg] += dbl[0]; 103012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org} 103112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 103212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 103312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgvoid Simulator::set_fpu_register(int fpureg, int64_t value) { 1034e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK((fpureg >= 0) && (fpureg < kNumFPURegisters)); 103512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org FPUregisters_[fpureg] = value; 103612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org} 103712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 103812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 103912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgvoid Simulator::set_fpu_register_word(int fpureg, int32_t value) { 104012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Set ONLY lower 32-bits, leaving upper bits untouched. 104112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // TODO(plind): big endian issue. 1042e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK((fpureg >= 0) && (fpureg < kNumFPURegisters)); 104312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org int32_t *pword = reinterpret_cast<int32_t*>(&FPUregisters_[fpureg]); 104412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org *pword = value; 104512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org} 104612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 104712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 104812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgvoid Simulator::set_fpu_register_hi_word(int fpureg, int32_t value) { 104912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Set ONLY upper 32-bits, leaving lower bits untouched. 105012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // TODO(plind): big endian issue. 1051e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK((fpureg >= 0) && (fpureg < kNumFPURegisters)); 105212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org int32_t *phiword = (reinterpret_cast<int32_t*>(&FPUregisters_[fpureg])) + 1; 105312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org *phiword = value; 105412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org} 105512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 105612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 105712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgvoid Simulator::set_fpu_register_float(int fpureg, float value) { 1058e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK((fpureg >= 0) && (fpureg < kNumFPURegisters)); 1059e20e19efeef112c26d0e63b1e5118e695b42d855machenbach@chromium.org *bit_cast<float*>(&FPUregisters_[fpureg]) = value; 106012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org} 106112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 106212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 106312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgvoid Simulator::set_fpu_register_double(int fpureg, double value) { 1064e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK((fpureg >= 0) && (fpureg < kNumFPURegisters)); 1065e20e19efeef112c26d0e63b1e5118e695b42d855machenbach@chromium.org *bit_cast<double*>(&FPUregisters_[fpureg]) = value; 106612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org} 106712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 106812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 106912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// Get the register from the architecture state. This function does handle 107012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// the special case of accessing the PC register. 107112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgint64_t Simulator::get_register(int reg) const { 1072e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK((reg >= 0) && (reg < kNumSimuRegisters)); 107312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (reg == 0) 107412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org return 0; 107512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org else 107612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org return registers_[reg] + ((reg == pc) ? Instruction::kPCReadOffset : 0); 107712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org} 107812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 107912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 108012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgdouble Simulator::get_double_from_register_pair(int reg) { 108112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // TODO(plind): bad ABI stuff, refactor or remove. 1082e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK((reg >= 0) && (reg < kNumSimuRegisters) && ((reg % 2) == 0)); 108312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 108412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org double dm_val = 0.0; 108512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Read the bits from the unsigned integer register_[] array 108612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // into the double precision floating point value and return it. 108712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org char buffer[sizeof(registers_[0])]; 108812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org memcpy(buffer, ®isters_[reg], sizeof(registers_[0])); 108912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org memcpy(&dm_val, buffer, sizeof(registers_[0])); 109012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org return(dm_val); 109112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org} 109212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 109312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 109412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgint64_t Simulator::get_fpu_register(int fpureg) const { 1095e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK((fpureg >= 0) && (fpureg < kNumFPURegisters)); 109612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org return FPUregisters_[fpureg]; 109712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org} 109812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 109912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 110012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgint32_t Simulator::get_fpu_register_word(int fpureg) const { 1101e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK((fpureg >= 0) && (fpureg < kNumFPURegisters)); 110212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org return static_cast<int32_t>(FPUregisters_[fpureg] & 0xffffffff); 110312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org} 110412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 110512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 110612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgint32_t Simulator::get_fpu_register_signed_word(int fpureg) const { 1107e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK((fpureg >= 0) && (fpureg < kNumFPURegisters)); 110812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org return static_cast<int32_t>(FPUregisters_[fpureg] & 0xffffffff); 110912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org} 111012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 111112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 1112a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.orgint32_t Simulator::get_fpu_register_hi_word(int fpureg) const { 1113e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK((fpureg >= 0) && (fpureg < kNumFPURegisters)); 1114a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org return static_cast<int32_t>((FPUregisters_[fpureg] >> 32) & 0xffffffff); 111512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org} 111612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 111712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 111812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgfloat Simulator::get_fpu_register_float(int fpureg) const { 1119e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK((fpureg >= 0) && (fpureg < kNumFPURegisters)); 1120e20e19efeef112c26d0e63b1e5118e695b42d855machenbach@chromium.org return *bit_cast<float*>(const_cast<int64_t*>(&FPUregisters_[fpureg])); 112112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org} 112212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 112312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 112412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgdouble Simulator::get_fpu_register_double(int fpureg) const { 1125e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK((fpureg >= 0) && (fpureg < kNumFPURegisters)); 1126e20e19efeef112c26d0e63b1e5118e695b42d855machenbach@chromium.org return *bit_cast<double*>(&FPUregisters_[fpureg]); 112712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org} 112812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 112912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 113012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// Runtime FP routines take up to two double arguments and zero 113112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// or one integer arguments. All are constructed here, 113212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// from a0-a3 or f12 and f13 (n64), or f14 (O32). 113312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgvoid Simulator::GetFpArgs(double* x, double* y, int32_t* z) { 113412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (!IsMipsSoftFloatABI) { 113512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org const int fparg2 = (kMipsAbi == kN64) ? 13 : 14; 113612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org *x = get_fpu_register_double(12); 113712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org *y = get_fpu_register_double(fparg2); 113812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org *z = get_register(a2); 113912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } else { 114012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // TODO(plind): bad ABI stuff, refactor or remove. 114112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // We use a char buffer to get around the strict-aliasing rules which 114212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // otherwise allow the compiler to optimize away the copy. 114312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org char buffer[sizeof(*x)]; 114412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org int32_t* reg_buffer = reinterpret_cast<int32_t*>(buffer); 114512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 114612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Registers a0 and a1 -> x. 114712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org reg_buffer[0] = get_register(a0); 114812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org reg_buffer[1] = get_register(a1); 114912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org memcpy(x, buffer, sizeof(buffer)); 115012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Registers a2 and a3 -> y. 115112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org reg_buffer[0] = get_register(a2); 115212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org reg_buffer[1] = get_register(a3); 115312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org memcpy(y, buffer, sizeof(buffer)); 115412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Register 2 -> z. 115512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org reg_buffer[0] = get_register(a2); 115612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org memcpy(z, buffer, sizeof(*z)); 115712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 115812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org} 115912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 116012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 116112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// The return value is either in v0/v1 or f0. 116212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgvoid Simulator::SetFpResult(const double& result) { 116312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (!IsMipsSoftFloatABI) { 116412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org set_fpu_register_double(0, result); 116512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } else { 116612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org char buffer[2 * sizeof(registers_[0])]; 116712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org int64_t* reg_buffer = reinterpret_cast<int64_t*>(buffer); 116812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org memcpy(buffer, &result, sizeof(buffer)); 116912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Copy result to v0 and v1. 117012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org set_register(v0, reg_buffer[0]); 117112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org set_register(v1, reg_buffer[1]); 117212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 117312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org} 117412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 117512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 117612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// Helper functions for setting and testing the FCSR register's bits. 117712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgvoid Simulator::set_fcsr_bit(uint32_t cc, bool value) { 117812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (value) { 117912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org FCSR_ |= (1 << cc); 118012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } else { 118112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org FCSR_ &= ~(1 << cc); 118212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 118312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org} 118412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 118512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 118612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgbool Simulator::test_fcsr_bit(uint32_t cc) { 118712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org return FCSR_ & (1 << cc); 118812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org} 118912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 119012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 119112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// Sets the rounding error codes in FCSR based on the result of the rounding. 119212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// Returns true if the operation was invalid. 119312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgbool Simulator::set_fcsr_round_error(double original, double rounded) { 119412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org bool ret = false; 119512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org double max_int32 = std::numeric_limits<int32_t>::max(); 119612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org double min_int32 = std::numeric_limits<int32_t>::min(); 119712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 119812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (!std::isfinite(original) || !std::isfinite(rounded)) { 119912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org set_fcsr_bit(kFCSRInvalidOpFlagBit, true); 120012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org ret = true; 120112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 120212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 120312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (original != rounded) { 120412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org set_fcsr_bit(kFCSRInexactFlagBit, true); 120512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 120612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 120712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (rounded < DBL_MIN && rounded > -DBL_MIN && rounded != 0) { 120812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org set_fcsr_bit(kFCSRUnderflowFlagBit, true); 120912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org ret = true; 121012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 121112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 121212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (rounded > max_int32 || rounded < min_int32) { 121312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org set_fcsr_bit(kFCSROverflowFlagBit, true); 121412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // The reference is not really clear but it seems this is required: 121512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org set_fcsr_bit(kFCSRInvalidOpFlagBit, true); 121612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org ret = true; 121712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 121812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 121912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org return ret; 122012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org} 122112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 122212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 122312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// Sets the rounding error codes in FCSR based on the result of the rounding. 122412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// Returns true if the operation was invalid. 122512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgbool Simulator::set_fcsr_round64_error(double original, double rounded) { 122612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org bool ret = false; 122712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org double max_int64 = std::numeric_limits<int64_t>::max(); 122812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org double min_int64 = std::numeric_limits<int64_t>::min(); 122912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 123012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (!std::isfinite(original) || !std::isfinite(rounded)) { 123112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org set_fcsr_bit(kFCSRInvalidOpFlagBit, true); 123212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org ret = true; 123312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 123412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 123512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (original != rounded) { 123612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org set_fcsr_bit(kFCSRInexactFlagBit, true); 123712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 123812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 123912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (rounded < DBL_MIN && rounded > -DBL_MIN && rounded != 0) { 124012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org set_fcsr_bit(kFCSRUnderflowFlagBit, true); 124112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org ret = true; 124212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 124312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 124412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (rounded > max_int64 || rounded < min_int64) { 124512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org set_fcsr_bit(kFCSROverflowFlagBit, true); 124612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // The reference is not really clear but it seems this is required: 124712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org set_fcsr_bit(kFCSRInvalidOpFlagBit, true); 124812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org ret = true; 124912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 125012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 125112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org return ret; 125212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org} 125312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 125412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 125512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// Raw access to the PC register. 125612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgvoid Simulator::set_pc(int64_t value) { 125712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org pc_modified_ = true; 125812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org registers_[pc] = value; 125912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org} 126012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 126112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 126212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgbool Simulator::has_bad_pc() const { 126312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org return ((registers_[pc] == bad_ra) || (registers_[pc] == end_sim_pc)); 126412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org} 126512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 126612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 126712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// Raw access to the PC register without the special adjustment when reading. 126812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgint64_t Simulator::get_pc() const { 126912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org return registers_[pc]; 127012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org} 127112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 127212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 127312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// The MIPS cannot do unaligned reads and writes. On some MIPS platforms an 127412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// interrupt is caused. On others it does a funky rotation thing. For now we 127512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// simply disallow unaligned reads, but at some point we may want to move to 127612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// emulating the rotate behaviour. Note that simulator runs have the runtime 127712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// system running directly on the host system and only generated code is 127812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// executed in the simulator. Since the host is typically IA32 we will not 127912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// get the correct MIPS-like behaviour on unaligned accesses. 128012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 128112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// TODO(plind): refactor this messy debug code when we do unaligned access. 128212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgvoid Simulator::DieOrDebug() { 128312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (1) { // Flag for this was removed. 128412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org MipsDebugger dbg(this); 128512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org dbg.Debug(); 128612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } else { 128712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org base::OS::Abort(); 128812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 128912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org} 129012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 129112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 129212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgvoid Simulator::TraceRegWr(int64_t value) { 129312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (::v8::internal::FLAG_trace_sim) { 129412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org SNPrintF(trace_buf_, "%016lx", value); 129512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 129612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org} 129712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 129812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 129912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// TODO(plind): consider making icount_ printing a flag option. 130012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgvoid Simulator::TraceMemRd(int64_t addr, int64_t value) { 130112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (::v8::internal::FLAG_trace_sim) { 130212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org SNPrintF(trace_buf_, "%016lx <-- [%016lx] (%ld)", 130312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org value, addr, icount_); 130412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 130512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org} 130612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 130712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 130812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgvoid Simulator::TraceMemWr(int64_t addr, int64_t value, TraceType t) { 130912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (::v8::internal::FLAG_trace_sim) { 131012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org switch (t) { 131112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case BYTE: 131212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org SNPrintF(trace_buf_, " %02x --> [%016lx]", 131312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org static_cast<int8_t>(value), addr); 131412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org break; 131512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case HALF: 131612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org SNPrintF(trace_buf_, " %04x --> [%016lx]", 131712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org static_cast<int16_t>(value), addr); 131812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org break; 131912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case WORD: 132012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org SNPrintF(trace_buf_, " %08x --> [%016lx]", 132112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org static_cast<int32_t>(value), addr); 132212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org break; 132312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case DWORD: 132412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org SNPrintF(trace_buf_, "%016lx --> [%016lx] (%ld)", 132512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org value, addr, icount_); 132612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org break; 132712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 132812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 132912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org} 133012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 133112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 133212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// TODO(plind): sign-extend and zero-extend not implmented properly 133312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// on all the ReadXX functions, I don't think re-interpret cast does it. 133412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgint32_t Simulator::ReadW(int64_t addr, Instruction* instr) { 133512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (addr >=0 && addr < 0x400) { 133612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // This has to be a NULL-dereference, drop into debugger. 133712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org PrintF("Memory read from bad address: 0x%08lx, pc=0x%08lx\n", 133812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org addr, reinterpret_cast<intptr_t>(instr)); 133912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org DieOrDebug(); 134012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 134112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if ((addr & 0x3) == 0) { 134212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org int32_t* ptr = reinterpret_cast<int32_t*>(addr); 134312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org TraceMemRd(addr, static_cast<int64_t>(*ptr)); 134412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org return *ptr; 134512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 134612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org PrintF("Unaligned read at 0x%08lx, pc=0x%08" V8PRIxPTR "\n", 134712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org addr, 134812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org reinterpret_cast<intptr_t>(instr)); 134912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org DieOrDebug(); 135012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org return 0; 135112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org} 135212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 135312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 135412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orguint32_t Simulator::ReadWU(int64_t addr, Instruction* instr) { 135512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (addr >=0 && addr < 0x400) { 135612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // This has to be a NULL-dereference, drop into debugger. 135712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org PrintF("Memory read from bad address: 0x%08lx, pc=0x%08lx\n", 135812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org addr, reinterpret_cast<intptr_t>(instr)); 135912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org DieOrDebug(); 136012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 136112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if ((addr & 0x3) == 0) { 136212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org uint32_t* ptr = reinterpret_cast<uint32_t*>(addr); 136312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org TraceMemRd(addr, static_cast<int64_t>(*ptr)); 136412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org return *ptr; 136512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 136612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org PrintF("Unaligned read at 0x%08lx, pc=0x%08" V8PRIxPTR "\n", 136712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org addr, 136812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org reinterpret_cast<intptr_t>(instr)); 136912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org DieOrDebug(); 137012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org return 0; 137112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org} 137212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 137312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 137412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgvoid Simulator::WriteW(int64_t addr, int value, Instruction* instr) { 137512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (addr >= 0 && addr < 0x400) { 137612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // This has to be a NULL-dereference, drop into debugger. 137712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org PrintF("Memory write to bad address: 0x%08lx, pc=0x%08lx\n", 137812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org addr, reinterpret_cast<intptr_t>(instr)); 137912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org DieOrDebug(); 138012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 138112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if ((addr & 0x3) == 0) { 138212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org TraceMemWr(addr, value, WORD); 138312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org int* ptr = reinterpret_cast<int*>(addr); 138412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org *ptr = value; 138512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org return; 138612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 138712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org PrintF("Unaligned write at 0x%08lx, pc=0x%08" V8PRIxPTR "\n", 138812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org addr, 138912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org reinterpret_cast<intptr_t>(instr)); 139012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org DieOrDebug(); 139112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org} 139212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 139312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 139412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgint64_t Simulator::Read2W(int64_t addr, Instruction* instr) { 139512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (addr >=0 && addr < 0x400) { 139612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // This has to be a NULL-dereference, drop into debugger. 139712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org PrintF("Memory read from bad address: 0x%08lx, pc=0x%08lx\n", 139812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org addr, reinterpret_cast<intptr_t>(instr)); 139912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org DieOrDebug(); 140012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 140112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if ((addr & kPointerAlignmentMask) == 0) { 140212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org int64_t* ptr = reinterpret_cast<int64_t*>(addr); 140312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org TraceMemRd(addr, *ptr); 140412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org return *ptr; 140512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 140612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org PrintF("Unaligned read at 0x%08lx, pc=0x%08" V8PRIxPTR "\n", 140712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org addr, 140812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org reinterpret_cast<intptr_t>(instr)); 140912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org DieOrDebug(); 141012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org return 0; 141112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org} 141212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 141312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 141412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgvoid Simulator::Write2W(int64_t addr, int64_t value, Instruction* instr) { 141512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (addr >= 0 && addr < 0x400) { 141612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // This has to be a NULL-dereference, drop into debugger. 141712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org PrintF("Memory write to bad address: 0x%08lx, pc=0x%08lx\n", 141812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org addr, reinterpret_cast<intptr_t>(instr)); 141912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org DieOrDebug(); 142012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 142112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if ((addr & kPointerAlignmentMask) == 0) { 142212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org TraceMemWr(addr, value, DWORD); 142312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org int64_t* ptr = reinterpret_cast<int64_t*>(addr); 142412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org *ptr = value; 142512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org return; 142612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 142712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org PrintF("Unaligned write at 0x%08lx, pc=0x%08" V8PRIxPTR "\n", 142812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org addr, 142912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org reinterpret_cast<intptr_t>(instr)); 143012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org DieOrDebug(); 143112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org} 143212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 143312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 143412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgdouble Simulator::ReadD(int64_t addr, Instruction* instr) { 143512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if ((addr & kDoubleAlignmentMask) == 0) { 143612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org double* ptr = reinterpret_cast<double*>(addr); 143712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org return *ptr; 143812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 143912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org PrintF("Unaligned (double) read at 0x%08lx, pc=0x%08" V8PRIxPTR "\n", 144012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org addr, 144112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org reinterpret_cast<intptr_t>(instr)); 144212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org base::OS::Abort(); 144312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org return 0; 144412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org} 144512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 144612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 144712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgvoid Simulator::WriteD(int64_t addr, double value, Instruction* instr) { 144812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if ((addr & kDoubleAlignmentMask) == 0) { 144912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org double* ptr = reinterpret_cast<double*>(addr); 145012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org *ptr = value; 145112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org return; 145212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 145312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org PrintF("Unaligned (double) write at 0x%08lx, pc=0x%08" V8PRIxPTR "\n", 145412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org addr, 145512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org reinterpret_cast<intptr_t>(instr)); 145612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org DieOrDebug(); 145712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org} 145812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 145912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 146012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orguint16_t Simulator::ReadHU(int64_t addr, Instruction* instr) { 146112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if ((addr & 1) == 0) { 146212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org uint16_t* ptr = reinterpret_cast<uint16_t*>(addr); 146312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org TraceMemRd(addr, static_cast<int64_t>(*ptr)); 146412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org return *ptr; 146512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 146612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org PrintF("Unaligned unsigned halfword read at 0x%08lx, pc=0x%08" V8PRIxPTR "\n", 146712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org addr, 146812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org reinterpret_cast<intptr_t>(instr)); 146912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org DieOrDebug(); 147012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org return 0; 147112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org} 147212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 147312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 147412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgint16_t Simulator::ReadH(int64_t addr, Instruction* instr) { 147512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if ((addr & 1) == 0) { 147612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org int16_t* ptr = reinterpret_cast<int16_t*>(addr); 147712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org TraceMemRd(addr, static_cast<int64_t>(*ptr)); 147812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org return *ptr; 147912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 148012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org PrintF("Unaligned signed halfword read at 0x%08lx, pc=0x%08" V8PRIxPTR "\n", 148112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org addr, 148212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org reinterpret_cast<intptr_t>(instr)); 148312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org DieOrDebug(); 148412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org return 0; 148512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org} 148612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 148712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 148812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgvoid Simulator::WriteH(int64_t addr, uint16_t value, Instruction* instr) { 148912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if ((addr & 1) == 0) { 149012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org TraceMemWr(addr, value, HALF); 149112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org uint16_t* ptr = reinterpret_cast<uint16_t*>(addr); 149212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org *ptr = value; 149312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org return; 149412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 149512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org PrintF( 149612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org "Unaligned unsigned halfword write at 0x%08lx, pc=0x%08" V8PRIxPTR "\n", 149712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org addr, 149812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org reinterpret_cast<intptr_t>(instr)); 149912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org DieOrDebug(); 150012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org} 150112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 150212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 150312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgvoid Simulator::WriteH(int64_t addr, int16_t value, Instruction* instr) { 150412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if ((addr & 1) == 0) { 150512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org TraceMemWr(addr, value, HALF); 150612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org int16_t* ptr = reinterpret_cast<int16_t*>(addr); 150712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org *ptr = value; 150812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org return; 150912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 151012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org PrintF("Unaligned halfword write at 0x%08lx, pc=0x%08" V8PRIxPTR "\n", 151112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org addr, 151212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org reinterpret_cast<intptr_t>(instr)); 151312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org DieOrDebug(); 151412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org} 151512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 151612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 151712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orguint32_t Simulator::ReadBU(int64_t addr) { 151812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org uint8_t* ptr = reinterpret_cast<uint8_t*>(addr); 151912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org TraceMemRd(addr, static_cast<int64_t>(*ptr)); 152012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org return *ptr & 0xff; 152112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org} 152212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 152312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 152412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgint32_t Simulator::ReadB(int64_t addr) { 152512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org int8_t* ptr = reinterpret_cast<int8_t*>(addr); 152612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org TraceMemRd(addr, static_cast<int64_t>(*ptr)); 152712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org return *ptr; 152812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org} 152912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 153012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 153112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgvoid Simulator::WriteB(int64_t addr, uint8_t value) { 153212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org TraceMemWr(addr, value, BYTE); 153312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org uint8_t* ptr = reinterpret_cast<uint8_t*>(addr); 153412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org *ptr = value; 153512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org} 153612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 153712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 153812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgvoid Simulator::WriteB(int64_t addr, int8_t value) { 153912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org TraceMemWr(addr, value, BYTE); 154012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org int8_t* ptr = reinterpret_cast<int8_t*>(addr); 154112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org *ptr = value; 154212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org} 154312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 154412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 154512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// Returns the limit of the stack area to enable checking for stack overflows. 154612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orguintptr_t Simulator::StackLimit() const { 154712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Leave a safety margin of 1024 bytes to prevent overrunning the stack when 154812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // pushing values. 154912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org return reinterpret_cast<uintptr_t>(stack_) + 1024; 155012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org} 155112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 155212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 155312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// Unsupported instructions use Format to print an error and stop execution. 155412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgvoid Simulator::Format(Instruction* instr, const char* format) { 155512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org PrintF("Simulator found unsupported instruction:\n 0x%08lx: %s\n", 155612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org reinterpret_cast<intptr_t>(instr), format); 155712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org UNIMPLEMENTED_MIPS(); 155812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org} 155912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 156012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 156112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// Calls into the V8 runtime are based on this very simple interface. 156212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// Note: To be able to return two values from some calls the code in runtime.cc 156312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// uses the ObjectPair which is essentially two 32-bit values stuffed into a 156412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// 64-bit value. With the code below we assume that all runtime calls return 156512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// 64 bits of result. If they don't, the v1 result register contains a bogus 156612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// value, which is fine because it is caller-saved. 156712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 156812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgstruct ObjectPair { 156912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Object* x; 157012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Object* y; 157112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org}; 157212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 157312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgtypedef ObjectPair (*SimulatorRuntimeCall)(int64_t arg0, 157412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org int64_t arg1, 157512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org int64_t arg2, 157612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org int64_t arg3, 157712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org int64_t arg4, 157812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org int64_t arg5); 157912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 158012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 158112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// These prototypes handle the four types of FP calls. 158212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgtypedef int64_t (*SimulatorRuntimeCompareCall)(double darg0, double darg1); 158312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgtypedef double (*SimulatorRuntimeFPFPCall)(double darg0, double darg1); 158412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgtypedef double (*SimulatorRuntimeFPCall)(double darg0); 158512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgtypedef double (*SimulatorRuntimeFPIntCall)(double darg0, int32_t arg0); 158612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 158712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// This signature supports direct call in to API function native callback 158812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// (refer to InvocationCallback in v8.h). 158912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgtypedef void (*SimulatorRuntimeDirectApiCall)(int64_t arg0); 159012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgtypedef void (*SimulatorRuntimeProfilingApiCall)(int64_t arg0, void* arg1); 159112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 159212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// This signature supports direct call to accessor getter callback. 159312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgtypedef void (*SimulatorRuntimeDirectGetterCall)(int64_t arg0, int64_t arg1); 159412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgtypedef void (*SimulatorRuntimeProfilingGetterCall)( 159512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org int64_t arg0, int64_t arg1, void* arg2); 159612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 159712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// Software interrupt instructions are used by the simulator to call into the 159812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// C-based V8 runtime. They are also used for debugging with simulator. 159912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgvoid Simulator::SoftwareInterrupt(Instruction* instr) { 160012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // There are several instructions that could get us here, 160112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // the break_ instruction, or several variants of traps. All 160212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Are "SPECIAL" class opcode, and are distinuished by function. 160312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org int32_t func = instr->FunctionFieldRaw(); 160412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org uint32_t code = (func == BREAK) ? instr->Bits(25, 6) : -1; 160512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // We first check if we met a call_rt_redirected. 160612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (instr->InstructionBits() == rtCallRedirInstr) { 160712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Redirection* redirection = Redirection::FromSwiInstruction(instr); 160812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org int64_t arg0 = get_register(a0); 160912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org int64_t arg1 = get_register(a1); 161012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org int64_t arg2 = get_register(a2); 161112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org int64_t arg3 = get_register(a3); 161212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org int64_t arg4, arg5; 161312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 161412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (kMipsAbi == kN64) { 161512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org arg4 = get_register(a4); // Abi n64 register a4. 161612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org arg5 = get_register(a5); // Abi n64 register a5. 161712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } else { // Abi O32. 161812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org int64_t* stack_pointer = reinterpret_cast<int64_t*>(get_register(sp)); 161912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Args 4 and 5 are on the stack after the reserved space for args 0..3. 162012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org arg4 = stack_pointer[4]; 162112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org arg5 = stack_pointer[5]; 162212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 162312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org bool fp_call = 162412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org (redirection->type() == ExternalReference::BUILTIN_FP_FP_CALL) || 162512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org (redirection->type() == ExternalReference::BUILTIN_COMPARE_CALL) || 162612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org (redirection->type() == ExternalReference::BUILTIN_FP_CALL) || 162712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org (redirection->type() == ExternalReference::BUILTIN_FP_INT_CALL); 162812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 162912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (!IsMipsSoftFloatABI) { 163012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // With the hard floating point calling convention, double 163112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // arguments are passed in FPU registers. Fetch the arguments 163212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // from there and call the builtin using soft floating point 163312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // convention. 163412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org switch (redirection->type()) { 163512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case ExternalReference::BUILTIN_FP_FP_CALL: 163612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case ExternalReference::BUILTIN_COMPARE_CALL: 163712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org arg0 = get_fpu_register(f12); 163812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org arg1 = get_fpu_register(f13); 163912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org arg2 = get_fpu_register(f14); 164012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org arg3 = get_fpu_register(f15); 164112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org break; 164212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case ExternalReference::BUILTIN_FP_CALL: 164312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org arg0 = get_fpu_register(f12); 164412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org arg1 = get_fpu_register(f13); 164512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org break; 164612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case ExternalReference::BUILTIN_FP_INT_CALL: 164712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org arg0 = get_fpu_register(f12); 164812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org arg1 = get_fpu_register(f13); 164912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org arg2 = get_register(a2); 165012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org break; 165112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org default: 165212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org break; 165312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 165412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 165512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 165612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // This is dodgy but it works because the C entry stubs are never moved. 165712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // See comment in codegen-arm.cc and bug 1242173. 165812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org int64_t saved_ra = get_register(ra); 165912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 166012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org intptr_t external = 166112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org reinterpret_cast<intptr_t>(redirection->external_function()); 166212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 166312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Based on CpuFeatures::IsSupported(FPU), Mips will use either hardware 166412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // FPU, or gcc soft-float routines. Hardware FPU is simulated in this 166512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // simulator. Soft-float has additional abstraction of ExternalReference, 166612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // to support serialization. 166712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (fp_call) { 166812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org double dval0, dval1; // one or two double parameters 166912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org int32_t ival; // zero or one integer parameters 167012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org int64_t iresult = 0; // integer return value 167112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org double dresult = 0; // double return value 167212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org GetFpArgs(&dval0, &dval1, &ival); 167312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org SimulatorRuntimeCall generic_target = 167412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org reinterpret_cast<SimulatorRuntimeCall>(external); 167512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (::v8::internal::FLAG_trace_sim) { 167612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org switch (redirection->type()) { 167712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case ExternalReference::BUILTIN_FP_FP_CALL: 167812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case ExternalReference::BUILTIN_COMPARE_CALL: 167912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org PrintF("Call to host function at %p with args %f, %f", 168012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org FUNCTION_ADDR(generic_target), dval0, dval1); 168112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org break; 168212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case ExternalReference::BUILTIN_FP_CALL: 168312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org PrintF("Call to host function at %p with arg %f", 168412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org FUNCTION_ADDR(generic_target), dval0); 168512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org break; 168612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case ExternalReference::BUILTIN_FP_INT_CALL: 168712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org PrintF("Call to host function at %p with args %f, %d", 168812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org FUNCTION_ADDR(generic_target), dval0, ival); 168912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org break; 169012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org default: 169112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org UNREACHABLE(); 169212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org break; 169312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 169412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 169512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org switch (redirection->type()) { 169612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case ExternalReference::BUILTIN_COMPARE_CALL: { 169712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org SimulatorRuntimeCompareCall target = 169812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org reinterpret_cast<SimulatorRuntimeCompareCall>(external); 169912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org iresult = target(dval0, dval1); 170012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org set_register(v0, static_cast<int64_t>(iresult)); 170112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // set_register(v1, static_cast<int64_t>(iresult >> 32)); 170212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org break; 170312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 170412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case ExternalReference::BUILTIN_FP_FP_CALL: { 170512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org SimulatorRuntimeFPFPCall target = 170612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org reinterpret_cast<SimulatorRuntimeFPFPCall>(external); 170712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org dresult = target(dval0, dval1); 170812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org SetFpResult(dresult); 170912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org break; 171012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 171112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case ExternalReference::BUILTIN_FP_CALL: { 171212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org SimulatorRuntimeFPCall target = 171312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org reinterpret_cast<SimulatorRuntimeFPCall>(external); 171412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org dresult = target(dval0); 171512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org SetFpResult(dresult); 171612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org break; 171712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 171812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case ExternalReference::BUILTIN_FP_INT_CALL: { 171912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org SimulatorRuntimeFPIntCall target = 172012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org reinterpret_cast<SimulatorRuntimeFPIntCall>(external); 172112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org dresult = target(dval0, ival); 172212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org SetFpResult(dresult); 172312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org break; 172412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 172512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org default: 172612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org UNREACHABLE(); 172712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org break; 172812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 172912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (::v8::internal::FLAG_trace_sim) { 173012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org switch (redirection->type()) { 173112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case ExternalReference::BUILTIN_COMPARE_CALL: 173212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org PrintF("Returned %08x\n", static_cast<int32_t>(iresult)); 173312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org break; 173412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case ExternalReference::BUILTIN_FP_FP_CALL: 173512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case ExternalReference::BUILTIN_FP_CALL: 173612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case ExternalReference::BUILTIN_FP_INT_CALL: 173712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org PrintF("Returned %f\n", dresult); 173812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org break; 173912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org default: 174012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org UNREACHABLE(); 174112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org break; 174212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 174312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 174412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } else if (redirection->type() == ExternalReference::DIRECT_API_CALL) { 174512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (::v8::internal::FLAG_trace_sim) { 174612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org PrintF("Call to host function at %p args %08lx\n", 174712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org reinterpret_cast<void*>(external), arg0); 174812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 174912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org SimulatorRuntimeDirectApiCall target = 175012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org reinterpret_cast<SimulatorRuntimeDirectApiCall>(external); 175112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org target(arg0); 175212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } else if ( 175312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org redirection->type() == ExternalReference::PROFILING_API_CALL) { 175412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (::v8::internal::FLAG_trace_sim) { 175512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org PrintF("Call to host function at %p args %08lx %08lx\n", 175612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org reinterpret_cast<void*>(external), arg0, arg1); 175712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 175812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org SimulatorRuntimeProfilingApiCall target = 175912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org reinterpret_cast<SimulatorRuntimeProfilingApiCall>(external); 176012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org target(arg0, Redirection::ReverseRedirection(arg1)); 176112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } else if ( 176212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org redirection->type() == ExternalReference::DIRECT_GETTER_CALL) { 176312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (::v8::internal::FLAG_trace_sim) { 176412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org PrintF("Call to host function at %p args %08lx %08lx\n", 176512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org reinterpret_cast<void*>(external), arg0, arg1); 176612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 176712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org SimulatorRuntimeDirectGetterCall target = 176812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org reinterpret_cast<SimulatorRuntimeDirectGetterCall>(external); 176912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org target(arg0, arg1); 177012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } else if ( 177112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org redirection->type() == ExternalReference::PROFILING_GETTER_CALL) { 177212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (::v8::internal::FLAG_trace_sim) { 177312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org PrintF("Call to host function at %p args %08lx %08lx %08lx\n", 177412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org reinterpret_cast<void*>(external), arg0, arg1, arg2); 177512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 177612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org SimulatorRuntimeProfilingGetterCall target = 177712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org reinterpret_cast<SimulatorRuntimeProfilingGetterCall>(external); 177812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org target(arg0, arg1, Redirection::ReverseRedirection(arg2)); 177912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } else { 178012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org SimulatorRuntimeCall target = 178112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org reinterpret_cast<SimulatorRuntimeCall>(external); 178212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (::v8::internal::FLAG_trace_sim) { 178312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org PrintF( 178412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org "Call to host function at %p " 178512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org "args %08lx, %08lx, %08lx, %08lx, %08lx, %08lx\n", 178612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org FUNCTION_ADDR(target), 178712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org arg0, 178812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org arg1, 178912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org arg2, 179012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org arg3, 179112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org arg4, 179212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org arg5); 179312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 179412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // int64_t result = target(arg0, arg1, arg2, arg3, arg4, arg5); 179512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // set_register(v0, static_cast<int32_t>(result)); 179612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // set_register(v1, static_cast<int32_t>(result >> 32)); 179712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org ObjectPair result = target(arg0, arg1, arg2, arg3, arg4, arg5); 179812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org set_register(v0, (int64_t)(result.x)); 179912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org set_register(v1, (int64_t)(result.y)); 180012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 180112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (::v8::internal::FLAG_trace_sim) { 180212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org PrintF("Returned %08lx : %08lx\n", get_register(v1), get_register(v0)); 180312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 180412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org set_register(ra, saved_ra); 180512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org set_pc(get_register(ra)); 180612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 180712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } else if (func == BREAK && code <= kMaxStopCode) { 180812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (IsWatchpoint(code)) { 180912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org PrintWatchpoint(code); 181012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } else { 181112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org IncreaseStopCounter(code); 181212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org HandleStop(code, instr); 181312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 181412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } else { 181512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // All remaining break_ codes, and all traps are handled here. 181612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org MipsDebugger dbg(this); 181712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org dbg.Debug(); 181812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 181912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org} 182012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 182112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 182212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// Stop helper functions. 182312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgbool Simulator::IsWatchpoint(uint64_t code) { 182412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org return (code <= kMaxWatchpointCode); 182512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org} 182612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 182712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 182812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgvoid Simulator::PrintWatchpoint(uint64_t code) { 182912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org MipsDebugger dbg(this); 183012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org ++break_count_; 183112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org PrintF("\n---- break %ld marker: %3d (instr count: %8ld) ----------" 183212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org "----------------------------------", 183312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org code, break_count_, icount_); 183412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org dbg.PrintAllRegs(); // Print registers and continue running. 183512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org} 183612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 183712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 183812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgvoid Simulator::HandleStop(uint64_t code, Instruction* instr) { 183912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Stop if it is enabled, otherwise go on jumping over the stop 184012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // and the message address. 184112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (IsEnabledStop(code)) { 184212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org MipsDebugger dbg(this); 184312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org dbg.Stop(instr); 184412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } else { 184512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org set_pc(get_pc() + 2 * Instruction::kInstrSize); 184612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 184712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org} 184812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 184912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 185012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgbool Simulator::IsStopInstruction(Instruction* instr) { 185112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org int32_t func = instr->FunctionFieldRaw(); 185212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org uint32_t code = static_cast<uint32_t>(instr->Bits(25, 6)); 185312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org return (func == BREAK) && code > kMaxWatchpointCode && code <= kMaxStopCode; 185412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org} 185512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 185612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 185712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgbool Simulator::IsEnabledStop(uint64_t code) { 1858e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK(code <= kMaxStopCode); 1859e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK(code > kMaxWatchpointCode); 186012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org return !(watched_stops_[code].count & kStopDisabledBit); 186112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org} 186212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 186312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 186412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgvoid Simulator::EnableStop(uint64_t code) { 186512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (!IsEnabledStop(code)) { 186612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org watched_stops_[code].count &= ~kStopDisabledBit; 186712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 186812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org} 186912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 187012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 187112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgvoid Simulator::DisableStop(uint64_t code) { 187212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (IsEnabledStop(code)) { 187312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org watched_stops_[code].count |= kStopDisabledBit; 187412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 187512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org} 187612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 187712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 187812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgvoid Simulator::IncreaseStopCounter(uint64_t code) { 1879e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK(code <= kMaxStopCode); 188012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if ((watched_stops_[code].count & ~(1 << 31)) == 0x7fffffff) { 188112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org PrintF("Stop counter for code %ld has overflowed.\n" 188212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org "Enabling this code and reseting the counter to 0.\n", code); 188312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org watched_stops_[code].count = 0; 188412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org EnableStop(code); 188512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } else { 188612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org watched_stops_[code].count++; 188712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 188812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org} 188912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 189012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 189112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// Print a stop status. 189212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgvoid Simulator::PrintStopInfo(uint64_t code) { 189312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (code <= kMaxWatchpointCode) { 189412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org PrintF("That is a watchpoint, not a stop.\n"); 189512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org return; 189612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } else if (code > kMaxStopCode) { 189712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org PrintF("Code too large, only %u stops can be used\n", kMaxStopCode + 1); 189812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org return; 189912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 190012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org const char* state = IsEnabledStop(code) ? "Enabled" : "Disabled"; 190112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org int32_t count = watched_stops_[code].count & ~kStopDisabledBit; 190212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Don't print the state of unused breakpoints. 190312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (count != 0) { 190412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (watched_stops_[code].desc) { 190512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org PrintF("stop %ld - 0x%lx: \t%s, \tcounter = %i, \t%s\n", 190612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org code, code, state, count, watched_stops_[code].desc); 190712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } else { 190812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org PrintF("stop %ld - 0x%lx: \t%s, \tcounter = %i\n", 190912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org code, code, state, count); 191012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 191112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 191212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org} 191312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 191412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 191512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgvoid Simulator::SignalExceptions() { 191612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org for (int i = 1; i < kNumExceptions; i++) { 191712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (exceptions[i] != 0) { 191812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org V8_Fatal(__FILE__, __LINE__, "Error: Exception %i raised.", i); 191912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 192012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 192112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org} 192212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 192312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 192412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// Handle execution based on instruction types. 192512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 192612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgvoid Simulator::ConfigureTypeRegister(Instruction* instr, 192712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org int64_t* alu_out, 192812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org int64_t* i64hilo, 192912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org uint64_t* u64hilo, 193012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org int64_t* next_pc, 193112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org int64_t* return_addr_reg, 193212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org bool* do_interrupt, 193312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org int64_t* i128resultH, 193412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org int64_t* i128resultL) { 193512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Every local variable declared here needs to be const. 193612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // This is to make sure that changed values are sent back to 193712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // DecodeTypeRegister correctly. 193812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 193912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Instruction fields. 194012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org const Opcode op = instr->OpcodeFieldRaw(); 194112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org const int64_t rs_reg = instr->RsValue(); 194212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org const int64_t rs = get_register(rs_reg); 194312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org const uint64_t rs_u = static_cast<uint64_t>(rs); 194412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org const int64_t rt_reg = instr->RtValue(); 194512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org const int64_t rt = get_register(rt_reg); 194612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org const uint64_t rt_u = static_cast<uint64_t>(rt); 194712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org const int64_t rd_reg = instr->RdValue(); 194812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org const uint64_t sa = instr->SaValue(); 194912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 195012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org const int32_t fs_reg = instr->FsValue(); 195112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 195212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 195312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // ---------- Configuration. 195412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org switch (op) { 195512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case COP1: // Coprocessor instructions. 195612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org switch (instr->RsFieldRaw()) { 195712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case CFC1: 195812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // At the moment only FCSR is supported. 1959e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK(fs_reg == kFCSRRegister); 196012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org *alu_out = FCSR_; 196112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org break; 196212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case MFC1: 196312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org *alu_out = static_cast<int64_t>(get_fpu_register_word(fs_reg)); 196412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org break; 196512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case DMFC1: 196612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org *alu_out = get_fpu_register(fs_reg); 196712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org break; 196812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case MFHC1: 196912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org *alu_out = get_fpu_register_hi_word(fs_reg); 197012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org break; 197112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case CTC1: 197212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case MTC1: 197312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case DMTC1: 197412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case MTHC1: 197512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case S: 197612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case D: 197712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case W: 197812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case L: 197912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case PS: 198012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Do everything in the execution step. 198112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org break; 198212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org default: 1983dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org // BC1 BC1EQZ BC1NEZ handled in DecodeTypeImmed, should never come here. 1984dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org UNREACHABLE(); 198512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 198612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org break; 198712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case COP1X: 198812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org break; 198912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case SPECIAL: 199012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org switch (instr->FunctionFieldRaw()) { 199112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case JR: 199212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case JALR: 199312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org *next_pc = get_register(instr->RsValue()); 199412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org *return_addr_reg = instr->RdValue(); 199512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org break; 199612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case SLL: 199712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org *alu_out = (int32_t)rt << sa; 199812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org break; 199912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case DSLL: 200012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org *alu_out = rt << sa; 200112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org break; 200212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case DSLL32: 200312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org *alu_out = rt << sa << 32; 200412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org break; 200512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case SRL: 200612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (rs_reg == 0) { 200712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Regular logical right shift of a word by a fixed number of 200812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // bits instruction. RS field is always equal to 0. 200912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org *alu_out = (uint32_t)rt_u >> sa; 201012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } else { 201112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Logical right-rotate of a word by a fixed number of bits. This 201212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // is special case of SRL instruction, added in MIPS32 Release 2. 201312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // RS field is equal to 00001. 201412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org *alu_out = ((uint32_t)rt_u >> sa) | ((uint32_t)rt_u << (32 - sa)); 201512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 201612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org break; 201712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case DSRL: 201812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org *alu_out = rt_u >> sa; 201912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org break; 202012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case DSRL32: 202112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org *alu_out = rt_u >> sa >> 32; 202212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org break; 202312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case SRA: 202412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org *alu_out = (int32_t)rt >> sa; 202512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org break; 202612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case DSRA: 202712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org *alu_out = rt >> sa; 202812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org break; 202912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case DSRA32: 203012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org *alu_out = rt >> sa >> 32; 203112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org break; 203212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case SLLV: 203312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org *alu_out = (int32_t)rt << rs; 203412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org break; 203512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case DSLLV: 203612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org *alu_out = rt << rs; 203712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org break; 203812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case SRLV: 203912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (sa == 0) { 204012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Regular logical right-shift of a word by a variable number of 204112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // bits instruction. SA field is always equal to 0. 204212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org *alu_out = (uint32_t)rt_u >> rs; 204312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } else { 204412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Logical right-rotate of a word by a variable number of bits. 204512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // This is special case od SRLV instruction, added in MIPS32 204612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Release 2. SA field is equal to 00001. 204712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org *alu_out = 204812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org ((uint32_t)rt_u >> rs_u) | ((uint32_t)rt_u << (32 - rs_u)); 204912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 205012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org break; 205112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case DSRLV: 205212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (sa == 0) { 205312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Regular logical right-shift of a word by a variable number of 205412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // bits instruction. SA field is always equal to 0. 205512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org *alu_out = rt_u >> rs; 205612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } else { 205712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Logical right-rotate of a word by a variable number of bits. 205812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // This is special case od SRLV instruction, added in MIPS32 205912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Release 2. SA field is equal to 00001. 206012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org *alu_out = (rt_u >> rs_u) | (rt_u << (32 - rs_u)); 206112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 206212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org break; 206312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case SRAV: 206412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org *alu_out = (int32_t)rt >> rs; 206512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org break; 206612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case DSRAV: 206712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org *alu_out = rt >> rs; 206812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org break; 2069dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org case MFHI: // MFHI == CLZ on R6. 2070dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org if (kArchVariant != kMips64r6) { 2071e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK(instr->SaValue() == 0); 2072dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org *alu_out = get_register(HI); 2073dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org } else { 2074dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org // MIPS spec: If no bits were set in GPR rs, the result written to 2075dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org // GPR rd is 32. 2076e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK(instr->SaValue() == 1); 2077e2a8937454723a720c81acc3f9e4162b18999b43machenbach@chromium.org *alu_out = base::bits::CountLeadingZeros32(rs_u); 2078dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org } 207912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org break; 208012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case MFLO: 208112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org *alu_out = get_register(LO); 208212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org break; 2083dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org case MULT: // MULT == D_MUL_MUH. 208412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // TODO(plind) - Unify MULT/DMULT with single set of 64-bit HI/Lo 208512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // regs. 208612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // TODO(plind) - make the 32-bit MULT ops conform to spec regarding 208712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // checking of 32-bit input values, and un-define operations of HW. 208812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org *i64hilo = static_cast<int64_t>((int32_t)rs) * 208912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org static_cast<int64_t>((int32_t)rt); 209012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org break; 209112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case MULTU: 209212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org *u64hilo = static_cast<uint64_t>(rs_u) * static_cast<uint64_t>(rt_u); 209312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org break; 2094dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org case DMULT: // DMULT == D_MUL_MUH. 2095dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org if (kArchVariant != kMips64r6) { 2096dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org *i128resultH = MultiplyHighSigned(rs, rt); 2097dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org *i128resultL = rs * rt; 2098dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org } else { 2099dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org switch (instr->SaValue()) { 2100dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org case MUL_OP: 2101dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org *i128resultL = rs * rt; 2102dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org break; 2103dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org case MUH_OP: 2104dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org *i128resultH = MultiplyHighSigned(rs, rt); 2105dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org break; 2106dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org default: 2107dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org UNIMPLEMENTED_MIPS(); 2108dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org break; 2109dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org } 2110dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org } 211112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org break; 211212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case DMULTU: 211312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org UNIMPLEMENTED_MIPS(); 211412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org break; 211512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case ADD: 211612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case DADD: 211712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (HaveSameSign(rs, rt)) { 211812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (rs > 0) { 211912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org exceptions[kIntegerOverflow] = rs > (Registers::kMaxValue - rt); 212012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } else if (rs < 0) { 212112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org exceptions[kIntegerUnderflow] = rs < (Registers::kMinValue - rt); 212212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 212312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 212412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org *alu_out = rs + rt; 212512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org break; 212612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case ADDU: { 212712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org int32_t alu32_out = rs + rt; 212812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Sign-extend result of 32bit operation into 64bit register. 212912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org *alu_out = static_cast<int64_t>(alu32_out); 213012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 213112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org break; 213212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case DADDU: 213312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org *alu_out = rs + rt; 213412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org break; 213512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case SUB: 213612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case DSUB: 213712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (!HaveSameSign(rs, rt)) { 213812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (rs > 0) { 213912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org exceptions[kIntegerOverflow] = rs > (Registers::kMaxValue + rt); 214012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } else if (rs < 0) { 214112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org exceptions[kIntegerUnderflow] = rs < (Registers::kMinValue + rt); 214212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 214312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 214412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org *alu_out = rs - rt; 214512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org break; 214612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case SUBU: { 214712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org int32_t alu32_out = rs - rt; 214812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Sign-extend result of 32bit operation into 64bit register. 214912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org *alu_out = static_cast<int64_t>(alu32_out); 215012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 215112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org break; 215212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case DSUBU: 215312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org *alu_out = rs - rt; 215412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org break; 215512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case AND: 215612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org *alu_out = rs & rt; 215712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org break; 215812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case OR: 215912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org *alu_out = rs | rt; 216012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org break; 216112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case XOR: 216212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org *alu_out = rs ^ rt; 216312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org break; 216412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case NOR: 216512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org *alu_out = ~(rs | rt); 216612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org break; 216712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case SLT: 216812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org *alu_out = rs < rt ? 1 : 0; 216912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org break; 217012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case SLTU: 217112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org *alu_out = rs_u < rt_u ? 1 : 0; 217212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org break; 217312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Break and trap instructions. 217412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case BREAK: 217512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 217612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org *do_interrupt = true; 217712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org break; 217812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case TGE: 217912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org *do_interrupt = rs >= rt; 218012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org break; 218112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case TGEU: 218212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org *do_interrupt = rs_u >= rt_u; 218312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org break; 218412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case TLT: 218512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org *do_interrupt = rs < rt; 218612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org break; 218712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case TLTU: 218812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org *do_interrupt = rs_u < rt_u; 218912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org break; 219012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case TEQ: 219112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org *do_interrupt = rs == rt; 219212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org break; 219312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case TNE: 219412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org *do_interrupt = rs != rt; 219512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org break; 219612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case MOVN: 219712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case MOVZ: 219812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case MOVCI: 219912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // No action taken on decode. 220012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org break; 220112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case DIV: 220212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case DIVU: 220312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case DDIV: 220412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case DDIVU: 220512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // div and divu never raise exceptions. 220612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org break; 220712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org default: 220812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org UNREACHABLE(); 220912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 221012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org break; 221112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case SPECIAL2: 221212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org switch (instr->FunctionFieldRaw()) { 221312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case MUL: 221412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Only the lower 32 bits are kept. 221512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org *alu_out = (int32_t)rs_u * (int32_t)rt_u; 221612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org break; 221712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case CLZ: 221812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // MIPS32 spec: If no bits were set in GPR rs, the result written to 221912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // GPR rd is 32. 2220e2a8937454723a720c81acc3f9e4162b18999b43machenbach@chromium.org *alu_out = base::bits::CountLeadingZeros32(rs_u); 222112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org break; 222212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org default: 222312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org UNREACHABLE(); 222412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 222512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org break; 222612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case SPECIAL3: 222712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org switch (instr->FunctionFieldRaw()) { 222812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case INS: { // Mips32r2 instruction. 222912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Interpret rd field as 5-bit msb of insert. 223012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org uint16_t msb = rd_reg; 223112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Interpret sa field as 5-bit lsb of insert. 223212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org uint16_t lsb = sa; 223312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org uint16_t size = msb - lsb + 1; 223412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org uint32_t mask = (1 << size) - 1; 223512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org *alu_out = (rt_u & ~(mask << lsb)) | ((rs_u & mask) << lsb); 223612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org break; 223712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 223812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case EXT: { // Mips32r2 instruction. 223912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Interpret rd field as 5-bit msb of extract. 224012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org uint16_t msb = rd_reg; 224112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Interpret sa field as 5-bit lsb of extract. 224212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org uint16_t lsb = sa; 224312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org uint16_t size = msb + 1; 224412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org uint32_t mask = (1 << size) - 1; 224512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org *alu_out = (rs_u & (mask << lsb)) >> lsb; 224612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org break; 224712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 224812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org default: 224912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org UNREACHABLE(); 225012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 225112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org break; 225212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org default: 225312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org UNREACHABLE(); 225412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 225512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org} 225612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 225712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 225812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgvoid Simulator::DecodeTypeRegister(Instruction* instr) { 225912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Instruction fields. 226012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org const Opcode op = instr->OpcodeFieldRaw(); 226112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org const int64_t rs_reg = instr->RsValue(); 226212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org const int64_t rs = get_register(rs_reg); 226312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org const uint64_t rs_u = static_cast<uint32_t>(rs); 226412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org const int64_t rt_reg = instr->RtValue(); 226512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org const int64_t rt = get_register(rt_reg); 226612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org const uint64_t rt_u = static_cast<uint32_t>(rt); 226712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org const int64_t rd_reg = instr->RdValue(); 226812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 226912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org const int32_t fr_reg = instr->FrValue(); 227012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org const int32_t fs_reg = instr->FsValue(); 227112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org const int32_t ft_reg = instr->FtValue(); 227212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org const int64_t fd_reg = instr->FdValue(); 227312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org int64_t i64hilo = 0; 227412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org uint64_t u64hilo = 0; 227512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 227612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // ALU output. 227712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // It should not be used as is. Instructions using it should always 227812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // initialize it first. 227912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org int64_t alu_out = 0x12345678; 228012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 228112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // For break and trap instructions. 228212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org bool do_interrupt = false; 228312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 228412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // For jr and jalr. 228512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Get current pc. 228612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org int64_t current_pc = get_pc(); 228712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Next pc 228812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org int64_t next_pc = 0; 228912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org int64_t return_addr_reg = 31; 229012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 229112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org int64_t i128resultH; 229212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org int64_t i128resultL; 229312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 229412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Set up the variables if needed before executing the instruction. 229512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org ConfigureTypeRegister(instr, 229612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org &alu_out, 229712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org &i64hilo, 229812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org &u64hilo, 229912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org &next_pc, 230012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org &return_addr_reg, 230112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org &do_interrupt, 230212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org &i128resultH, 230312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org &i128resultL); 230412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 230512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // ---------- Raise exceptions triggered. 230612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org SignalExceptions(); 230712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 230812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // ---------- Execution. 230912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org switch (op) { 231012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case COP1: 231112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org switch (instr->RsFieldRaw()) { 231212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case BC1: // Branch on coprocessor condition. 2313dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org case BC1EQZ: 2314dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org case BC1NEZ: 231512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org UNREACHABLE(); 231612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org break; 231712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case CFC1: 231812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org set_register(rt_reg, alu_out); 231912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org break; 232012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case MFC1: 232112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case DMFC1: 232212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case MFHC1: 232312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org set_register(rt_reg, alu_out); 232412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org break; 232512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case CTC1: 232612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // At the moment only FCSR is supported. 2327e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK(fs_reg == kFCSRRegister); 232812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org FCSR_ = registers_[rt_reg]; 232912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org break; 233012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case MTC1: 233112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Hardware writes upper 32-bits to zero on mtc1. 233212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org set_fpu_register_hi_word(fs_reg, 0); 233312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org set_fpu_register_word(fs_reg, registers_[rt_reg]); 233412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org break; 233512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case DMTC1: 233612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org set_fpu_register(fs_reg, registers_[rt_reg]); 233712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org break; 233812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case MTHC1: 233912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org set_fpu_register_hi_word(fs_reg, registers_[rt_reg]); 234012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org break; 234112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case S: 234212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org float f; 234312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org switch (instr->FunctionFieldRaw()) { 234412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case CVT_D_S: 234512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org f = get_fpu_register_float(fs_reg); 234612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org set_fpu_register_double(fd_reg, static_cast<double>(f)); 234712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org break; 234812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org default: 2349dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org // CVT_W_S CVT_L_S TRUNC_W_S ROUND_W_S ROUND_L_S FLOOR_W_S FLOOR_L_S 2350dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org // CEIL_W_S CEIL_L_S CVT_PS_S are unimplemented. 235112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org UNREACHABLE(); 235212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 235312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org break; 235412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case D: 235512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org double ft, fs; 235612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org uint32_t cc, fcsr_cc; 235712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org int64_t i64; 235812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org fs = get_fpu_register_double(fs_reg); 235912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org ft = get_fpu_register_double(ft_reg); 236012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org cc = instr->FCccValue(); 236112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org fcsr_cc = get_fcsr_condition_bit(cc); 236212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org switch (instr->FunctionFieldRaw()) { 236312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case ADD_D: 236412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org set_fpu_register_double(fd_reg, fs + ft); 236512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org break; 236612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case SUB_D: 236712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org set_fpu_register_double(fd_reg, fs - ft); 236812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org break; 236912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case MUL_D: 237012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org set_fpu_register_double(fd_reg, fs * ft); 237112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org break; 237212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case DIV_D: 237312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org set_fpu_register_double(fd_reg, fs / ft); 237412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org break; 237512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case ABS_D: 237612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org set_fpu_register_double(fd_reg, fabs(fs)); 237712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org break; 237812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case MOV_D: 237912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org set_fpu_register_double(fd_reg, fs); 238012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org break; 238112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case NEG_D: 238212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org set_fpu_register_double(fd_reg, -fs); 238312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org break; 238412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case SQRT_D: 238512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org set_fpu_register_double(fd_reg, sqrt(fs)); 238612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org break; 238712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case C_UN_D: 238812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org set_fcsr_bit(fcsr_cc, std::isnan(fs) || std::isnan(ft)); 238912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org break; 239012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case C_EQ_D: 239112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org set_fcsr_bit(fcsr_cc, (fs == ft)); 239212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org break; 239312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case C_UEQ_D: 239412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org set_fcsr_bit(fcsr_cc, 239512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org (fs == ft) || (std::isnan(fs) || std::isnan(ft))); 239612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org break; 239712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case C_OLT_D: 239812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org set_fcsr_bit(fcsr_cc, (fs < ft)); 239912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org break; 240012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case C_ULT_D: 240112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org set_fcsr_bit(fcsr_cc, 240212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org (fs < ft) || (std::isnan(fs) || std::isnan(ft))); 240312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org break; 240412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case C_OLE_D: 240512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org set_fcsr_bit(fcsr_cc, (fs <= ft)); 240612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org break; 240712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case C_ULE_D: 240812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org set_fcsr_bit(fcsr_cc, 240912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org (fs <= ft) || (std::isnan(fs) || std::isnan(ft))); 241012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org break; 241112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case CVT_W_D: // Convert double to word. 241212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Rounding modes are not yet supported. 2413e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK((FCSR_ & 3) == 0); 241412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // In rounding mode 0 it should behave like ROUND. 241512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // No break. 241612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case ROUND_W_D: // Round double to word (round half to even). 241712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org { 241812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org double rounded = std::floor(fs + 0.5); 241912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org int32_t result = static_cast<int32_t>(rounded); 242012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if ((result & 1) != 0 && result - fs == 0.5) { 242112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // If the number is halfway between two integers, 242212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // round to the even one. 242312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org result--; 242412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 242512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org set_fpu_register_word(fd_reg, result); 242612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (set_fcsr_round_error(fs, rounded)) { 242712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org set_fpu_register(fd_reg, kFPUInvalidResult); 242812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 242912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 243012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org break; 243112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case TRUNC_W_D: // Truncate double to word (round towards 0). 243212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org { 243312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org double rounded = trunc(fs); 243412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org int32_t result = static_cast<int32_t>(rounded); 243512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org set_fpu_register_word(fd_reg, result); 243612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (set_fcsr_round_error(fs, rounded)) { 243712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org set_fpu_register(fd_reg, kFPUInvalidResult); 243812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 243912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 244012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org break; 244112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case FLOOR_W_D: // Round double to word towards negative infinity. 244212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org { 244312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org double rounded = std::floor(fs); 244412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org int32_t result = static_cast<int32_t>(rounded); 244512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org set_fpu_register_word(fd_reg, result); 244612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (set_fcsr_round_error(fs, rounded)) { 244712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org set_fpu_register(fd_reg, kFPUInvalidResult); 244812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 244912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 245012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org break; 245112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case CEIL_W_D: // Round double to word towards positive infinity. 245212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org { 245312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org double rounded = std::ceil(fs); 245412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org int32_t result = static_cast<int32_t>(rounded); 245512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org set_fpu_register_word(fd_reg, result); 245612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (set_fcsr_round_error(fs, rounded)) { 245712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org set_fpu_register(fd_reg, kFPUInvalidResult); 245812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 245912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 246012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org break; 246112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case CVT_S_D: // Convert double to float (single). 246212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org set_fpu_register_float(fd_reg, static_cast<float>(fs)); 246312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org break; 246412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case CVT_L_D: // Mips64r2: Truncate double to 64-bit long-word. 246512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Rounding modes are not yet supported. 2466e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK((FCSR_ & 3) == 0); 246712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // In rounding mode 0 it should behave like ROUND. 246812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // No break. 246912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case ROUND_L_D: { // Mips64r2 instruction. 247012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // check error cases 247112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org double rounded = fs > 0 ? floor(fs + 0.5) : ceil(fs - 0.5); 247212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org int64_t result = static_cast<int64_t>(rounded); 247312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org set_fpu_register(fd_reg, result); 247412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (set_fcsr_round64_error(fs, rounded)) { 247512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org set_fpu_register(fd_reg, kFPU64InvalidResult); 247612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 247712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org break; 247812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 247912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case TRUNC_L_D: { // Mips64r2 instruction. 248012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org double rounded = trunc(fs); 248112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org int64_t result = static_cast<int64_t>(rounded); 248212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org set_fpu_register(fd_reg, result); 248312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (set_fcsr_round64_error(fs, rounded)) { 248412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org set_fpu_register(fd_reg, kFPU64InvalidResult); 248512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 248612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org break; 248712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 248812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case FLOOR_L_D: { // Mips64r2 instruction. 248912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org double rounded = floor(fs); 249012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org int64_t result = static_cast<int64_t>(rounded); 249112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org set_fpu_register(fd_reg, result); 249212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (set_fcsr_round64_error(fs, rounded)) { 249312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org set_fpu_register(fd_reg, kFPU64InvalidResult); 249412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 249512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org break; 249612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 249712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case CEIL_L_D: { // Mips64r2 instruction. 249812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org double rounded = ceil(fs); 249912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org int64_t result = static_cast<int64_t>(rounded); 250012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org set_fpu_register(fd_reg, result); 250112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (set_fcsr_round64_error(fs, rounded)) { 250212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org set_fpu_register(fd_reg, kFPU64InvalidResult); 250312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 250412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org break; 250512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 250612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case C_F_D: 250712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org UNIMPLEMENTED_MIPS(); 250812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org break; 250912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org default: 251012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org UNREACHABLE(); 251112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 251212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org break; 251312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case W: 251412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org switch (instr->FunctionFieldRaw()) { 251512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case CVT_S_W: // Convert word to float (single). 251612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org alu_out = get_fpu_register_signed_word(fs_reg); 251712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org set_fpu_register_float(fd_reg, static_cast<float>(alu_out)); 251812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org break; 251912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case CVT_D_W: // Convert word to double. 252012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org alu_out = get_fpu_register_signed_word(fs_reg); 252112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org set_fpu_register_double(fd_reg, static_cast<double>(alu_out)); 252212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org break; 2523dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org default: // Mips64r6 CMP.S instructions unimplemented. 252412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org UNREACHABLE(); 252512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 252612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org break; 252712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case L: 2528dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org fs = get_fpu_register_double(fs_reg); 2529dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org ft = get_fpu_register_double(ft_reg); 253012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org switch (instr->FunctionFieldRaw()) { 2531dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org case CVT_D_L: // Mips32r2 instruction. 2532dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org i64 = get_fpu_register(fs_reg); 2533dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org set_fpu_register_double(fd_reg, static_cast<double>(i64)); 2534dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org break; 253512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case CVT_S_L: 253612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org UNIMPLEMENTED_MIPS(); 253712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org break; 2538dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org case CMP_AF: // Mips64r6 CMP.D instructions. 2539dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org UNIMPLEMENTED_MIPS(); 2540dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org break; 2541dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org case CMP_UN: 2542dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org if (std::isnan(fs) || std::isnan(ft)) { 2543dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org set_fpu_register(fd_reg, -1); 2544dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org } else { 2545dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org set_fpu_register(fd_reg, 0); 2546dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org } 2547dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org break; 2548dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org case CMP_EQ: 2549dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org if (fs == ft) { 2550dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org set_fpu_register(fd_reg, -1); 2551dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org } else { 2552dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org set_fpu_register(fd_reg, 0); 2553dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org } 2554dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org break; 2555dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org case CMP_UEQ: 2556dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org if ((fs == ft) || (std::isnan(fs) || std::isnan(ft))) { 2557dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org set_fpu_register(fd_reg, -1); 2558dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org } else { 2559dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org set_fpu_register(fd_reg, 0); 2560dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org } 2561dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org break; 2562dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org case CMP_LT: 2563dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org if (fs < ft) { 2564dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org set_fpu_register(fd_reg, -1); 2565dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org } else { 2566dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org set_fpu_register(fd_reg, 0); 2567dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org } 2568dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org break; 2569dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org case CMP_ULT: 2570dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org if ((fs < ft) || (std::isnan(fs) || std::isnan(ft))) { 2571dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org set_fpu_register(fd_reg, -1); 2572dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org } else { 2573dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org set_fpu_register(fd_reg, 0); 2574dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org } 2575dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org break; 2576dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org case CMP_LE: 2577dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org if (fs <= ft) { 2578dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org set_fpu_register(fd_reg, -1); 2579dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org } else { 2580dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org set_fpu_register(fd_reg, 0); 2581dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org } 2582dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org break; 2583dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org case CMP_ULE: 2584dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org if ((fs <= ft) || (std::isnan(fs) || std::isnan(ft))) { 2585dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org set_fpu_register(fd_reg, -1); 2586dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org } else { 2587dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org set_fpu_register(fd_reg, 0); 2588dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org } 2589dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org break; 2590dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org default: // CMP_OR CMP_UNE CMP_NE UNIMPLEMENTED 259112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org UNREACHABLE(); 259212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 259312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org break; 259412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org default: 259512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org UNREACHABLE(); 259612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 259712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org break; 259812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case COP1X: 259912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org switch (instr->FunctionFieldRaw()) { 260012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case MADD_D: 260112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org double fr, ft, fs; 260212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org fr = get_fpu_register_double(fr_reg); 260312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org fs = get_fpu_register_double(fs_reg); 260412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org ft = get_fpu_register_double(ft_reg); 260512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org set_fpu_register_double(fd_reg, fs * ft + fr); 260612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org break; 260712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org default: 260812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org UNREACHABLE(); 260912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 261012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org break; 261112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case SPECIAL: 261212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org switch (instr->FunctionFieldRaw()) { 261312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case JR: { 261412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Instruction* branch_delay_instr = reinterpret_cast<Instruction*>( 261512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org current_pc+Instruction::kInstrSize); 261612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org BranchDelayInstructionDecode(branch_delay_instr); 261712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org set_pc(next_pc); 261812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org pc_modified_ = true; 261912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org break; 262012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 262112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case JALR: { 262212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Instruction* branch_delay_instr = reinterpret_cast<Instruction*>( 262312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org current_pc+Instruction::kInstrSize); 262412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org BranchDelayInstructionDecode(branch_delay_instr); 262512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org set_register(return_addr_reg, 262612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org current_pc + 2 * Instruction::kInstrSize); 262712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org set_pc(next_pc); 262812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org pc_modified_ = true; 262912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org break; 263012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 263112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Instructions using HI and LO registers. 263212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case MULT: 2633dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org if (kArchVariant != kMips64r6) { 2634dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org set_register(LO, static_cast<int32_t>(i64hilo & 0xffffffff)); 2635dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org set_register(HI, static_cast<int32_t>(i64hilo >> 32)); 2636dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org } else { 2637dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org switch (instr->SaValue()) { 2638dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org case MUL_OP: 2639dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org set_register(rd_reg, 2640dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org static_cast<int32_t>(i64hilo & 0xffffffff)); 2641dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org break; 2642dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org case MUH_OP: 2643dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org set_register(rd_reg, static_cast<int32_t>(i64hilo >> 32)); 2644dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org break; 2645dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org default: 2646dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org UNIMPLEMENTED_MIPS(); 2647dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org break; 2648dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org } 2649dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org } 265012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org break; 265112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case MULTU: 265212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org set_register(LO, static_cast<int32_t>(u64hilo & 0xffffffff)); 265312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org set_register(HI, static_cast<int32_t>(u64hilo >> 32)); 265412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org break; 2655dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org case DMULT: // DMULT == D_MUL_MUH. 2656dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org if (kArchVariant != kMips64r6) { 2657dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org set_register(LO, static_cast<int64_t>(i128resultL)); 2658dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org set_register(HI, static_cast<int64_t>(i128resultH)); 2659dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org } else { 2660dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org switch (instr->SaValue()) { 2661dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org case MUL_OP: 2662dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org set_register(rd_reg, static_cast<int64_t>(i128resultL)); 2663dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org break; 2664dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org case MUH_OP: 2665dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org set_register(rd_reg, static_cast<int64_t>(i128resultH)); 2666dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org break; 2667dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org default: 2668dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org UNIMPLEMENTED_MIPS(); 2669dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org break; 2670dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org } 2671dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org } 267212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org break; 267312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case DMULTU: 267412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org UNIMPLEMENTED_MIPS(); 267512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org break; 2676dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org case DSLL: 2677dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org set_register(rd_reg, alu_out); 2678dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org break; 267912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case DIV: 268012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case DDIV: 2681dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org switch (kArchVariant) { 2682dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org case kMips64r2: 2683dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org // Divide by zero and overflow was not checked in the 2684dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org // configuration step - div and divu do not raise exceptions. On 2685dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org // division by 0 the result will be UNPREDICTABLE. On overflow 2686dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org // (INT_MIN/-1), return INT_MIN which is what the hardware does. 2687dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org if (rs == INT_MIN && rt == -1) { 2688dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org set_register(LO, INT_MIN); 2689dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org set_register(HI, 0); 2690dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org } else if (rt != 0) { 2691dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org set_register(LO, rs / rt); 2692dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org set_register(HI, rs % rt); 2693dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org } 2694dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org break; 2695dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org case kMips64r6: 2696dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org switch (instr->SaValue()) { 2697dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org case DIV_OP: 2698dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org if (rs == INT_MIN && rt == -1) { 2699dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org set_register(rd_reg, INT_MIN); 2700dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org } else if (rt != 0) { 2701dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org set_register(rd_reg, rs / rt); 2702dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org } 2703dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org break; 2704dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org case MOD_OP: 2705dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org if (rs == INT_MIN && rt == -1) { 2706dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org set_register(rd_reg, 0); 2707dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org } else if (rt != 0) { 2708dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org set_register(rd_reg, rs % rt); 2709dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org } 2710dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org break; 2711dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org default: 2712dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org UNIMPLEMENTED_MIPS(); 2713dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org break; 2714dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org } 2715dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org break; 2716dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org default: 2717dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org break; 271812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 271912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org break; 272012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case DIVU: 272112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (rt_u != 0) { 272212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org set_register(LO, rs_u / rt_u); 272312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org set_register(HI, rs_u % rt_u); 272412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 272512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org break; 272612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Break and trap instructions. 272712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case BREAK: 272812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case TGE: 272912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case TGEU: 273012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case TLT: 273112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case TLTU: 273212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case TEQ: 273312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case TNE: 273412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (do_interrupt) { 273512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org SoftwareInterrupt(instr); 273612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 273712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org break; 273812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Conditional moves. 273912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case MOVN: 274012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (rt) { 274112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org set_register(rd_reg, rs); 274212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org TraceRegWr(rs); 274312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 274412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org break; 274512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case MOVCI: { 274612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org uint32_t cc = instr->FBccValue(); 274712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org uint32_t fcsr_cc = get_fcsr_condition_bit(cc); 274812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (instr->Bit(16)) { // Read Tf bit. 274912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (test_fcsr_bit(fcsr_cc)) set_register(rd_reg, rs); 275012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } else { 275112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (!test_fcsr_bit(fcsr_cc)) set_register(rd_reg, rs); 275212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 275312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org break; 275412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 275512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case MOVZ: 275612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (!rt) { 275712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org set_register(rd_reg, rs); 275812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org TraceRegWr(rs); 275912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 276012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org break; 276112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org default: // For other special opcodes we do the default operation. 276212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org set_register(rd_reg, alu_out); 276312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org TraceRegWr(alu_out); 276412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 276512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org break; 276612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case SPECIAL2: 276712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org switch (instr->FunctionFieldRaw()) { 276812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case MUL: 276912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org set_register(rd_reg, alu_out); 277012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org TraceRegWr(alu_out); 277112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // HI and LO are UNPREDICTABLE after the operation. 277212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org set_register(LO, Unpredictable); 277312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org set_register(HI, Unpredictable); 277412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org break; 277512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org default: // For other special2 opcodes we do the default operation. 277612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org set_register(rd_reg, alu_out); 277712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 277812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org break; 277912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case SPECIAL3: 278012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org switch (instr->FunctionFieldRaw()) { 278112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case INS: 278212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Ins instr leaves result in Rt, rather than Rd. 278312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org set_register(rt_reg, alu_out); 278412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org TraceRegWr(alu_out); 278512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org break; 278612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case EXT: 278712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Ext instr leaves result in Rt, rather than Rd. 278812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org set_register(rt_reg, alu_out); 278912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org TraceRegWr(alu_out); 279012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org break; 279112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org default: 279212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org UNREACHABLE(); 279312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 279412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org break; 279512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Unimplemented opcodes raised an error in the configuration step before, 279612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // so we can use the default here to set the destination register in common 279712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // cases. 279812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org default: 279912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org set_register(rd_reg, alu_out); 280012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org TraceRegWr(alu_out); 280112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 280212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org} 280312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 280412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 280512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// Type 2: instructions using a 16 bytes immediate. (e.g. addi, beq). 280612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgvoid Simulator::DecodeTypeImmediate(Instruction* instr) { 280712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Instruction fields. 280812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Opcode op = instr->OpcodeFieldRaw(); 280912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org int64_t rs = get_register(instr->RsValue()); 281012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org uint64_t rs_u = static_cast<uint64_t>(rs); 281112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org int64_t rt_reg = instr->RtValue(); // Destination register. 281212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org int64_t rt = get_register(rt_reg); 281312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org int16_t imm16 = instr->Imm16Value(); 281412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 281512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org int32_t ft_reg = instr->FtValue(); // Destination register. 2816dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org int64_t ft = get_fpu_register(ft_reg); 281712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 281812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Zero extended immediate. 281912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org uint32_t oe_imm16 = 0xffff & imm16; 282012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Sign extended immediate. 282112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org int32_t se_imm16 = imm16; 282212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 282312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Get current pc. 282412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org int64_t current_pc = get_pc(); 282512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Next pc. 282612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org int64_t next_pc = bad_ra; 282712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 282812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Used for conditional branch instructions. 282912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org bool do_branch = false; 283012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org bool execute_branch_delay_instruction = false; 283112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 283212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Used for arithmetic instructions. 283312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org int64_t alu_out = 0; 283412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Floating point. 283512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org double fp_out = 0.0; 283612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org uint32_t cc, cc_value, fcsr_cc; 283712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 283812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Used for memory instructions. 283912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org int64_t addr = 0x0; 284012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Value to be written in memory. 284112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org uint64_t mem_value = 0x0; 284212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Alignment for 32-bit integers used in LWL, LWR, etc. 284312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org const int kInt32AlignmentMask = sizeof(uint32_t) - 1; 284412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 284512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // ---------- Configuration (and execution for REGIMM). 284612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org switch (op) { 284712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // ------------- COP1. Coprocessor instructions. 284812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case COP1: 284912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org switch (instr->RsFieldRaw()) { 285012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case BC1: // Branch on coprocessor condition. 285112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org cc = instr->FBccValue(); 285212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org fcsr_cc = get_fcsr_condition_bit(cc); 285312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org cc_value = test_fcsr_bit(fcsr_cc); 285412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org do_branch = (instr->FBtrueValue()) ? cc_value : !cc_value; 285512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org execute_branch_delay_instruction = true; 285612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Set next_pc. 285712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (do_branch) { 285812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org next_pc = current_pc + (imm16 << 2) + Instruction::kInstrSize; 285912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } else { 286012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org next_pc = current_pc + kBranchReturnOffset; 286112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 286212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org break; 2863dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org case BC1EQZ: 2864dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org do_branch = (ft & 0x1) ? false : true; 2865dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org execute_branch_delay_instruction = true; 2866dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org // Set next_pc. 2867dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org if (do_branch) { 2868dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org next_pc = current_pc + (imm16 << 2) + Instruction::kInstrSize; 2869dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org } else { 2870dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org next_pc = current_pc + kBranchReturnOffset; 2871dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org } 2872dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org break; 2873dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org case BC1NEZ: 2874dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org do_branch = (ft & 0x1) ? true : false; 2875dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org execute_branch_delay_instruction = true; 2876dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org // Set next_pc. 2877dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org if (do_branch) { 2878dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org next_pc = current_pc + (imm16 << 2) + Instruction::kInstrSize; 2879dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org } else { 2880dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org next_pc = current_pc + kBranchReturnOffset; 2881dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org } 2882dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org break; 288312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org default: 288412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org UNREACHABLE(); 288512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 288612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org break; 288712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // ------------- REGIMM class. 288812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case REGIMM: 288912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org switch (instr->RtFieldRaw()) { 289012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case BLTZ: 289112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org do_branch = (rs < 0); 289212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org break; 289312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case BLTZAL: 289412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org do_branch = rs < 0; 289512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org break; 289612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case BGEZ: 289712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org do_branch = rs >= 0; 289812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org break; 289912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case BGEZAL: 290012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org do_branch = rs >= 0; 290112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org break; 290212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org default: 290312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org UNREACHABLE(); 290412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 290512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org switch (instr->RtFieldRaw()) { 290612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case BLTZ: 290712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case BLTZAL: 290812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case BGEZ: 290912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case BGEZAL: 291012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Branch instructions common part. 291112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org execute_branch_delay_instruction = true; 291212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Set next_pc. 291312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (do_branch) { 291412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org next_pc = current_pc + (imm16 << 2) + Instruction::kInstrSize; 291512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (instr->IsLinkingInstruction()) { 291612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org set_register(31, current_pc + kBranchReturnOffset); 291712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 291812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } else { 291912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org next_pc = current_pc + kBranchReturnOffset; 292012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 292112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org default: 292212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org break; 292312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 292412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org break; // case REGIMM. 292512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // ------------- Branch instructions. 292612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // When comparing to zero, the encoding of rt field is always 0, so we don't 292712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // need to replace rt with zero. 292812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case BEQ: 292912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org do_branch = (rs == rt); 293012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org break; 293112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case BNE: 293212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org do_branch = rs != rt; 293312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org break; 293412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case BLEZ: 293512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org do_branch = rs <= 0; 293612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org break; 293712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case BGTZ: 293812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org do_branch = rs > 0; 293912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org break; 294012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // ------------- Arithmetic instructions. 294112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case ADDI: 294212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case DADDI: 294312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (HaveSameSign(rs, se_imm16)) { 294412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (rs > 0) { 294512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org exceptions[kIntegerOverflow] = rs > (Registers::kMaxValue - se_imm16); 294612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } else if (rs < 0) { 294712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org exceptions[kIntegerUnderflow] = 294812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org rs < (Registers::kMinValue - se_imm16); 294912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 295012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 295112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org alu_out = rs + se_imm16; 295212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org break; 295312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case ADDIU: { 295412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org int32_t alu32_out = rs + se_imm16; 295512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Sign-extend result of 32bit operation into 64bit register. 295612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org alu_out = static_cast<int64_t>(alu32_out); 295712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 295812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org break; 295912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case DADDIU: 296012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org alu_out = rs + se_imm16; 296112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org break; 296212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case SLTI: 296312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org alu_out = (rs < se_imm16) ? 1 : 0; 296412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org break; 296512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case SLTIU: 296612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org alu_out = (rs_u < static_cast<uint32_t>(se_imm16)) ? 1 : 0; 296712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org break; 296812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case ANDI: 296912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org alu_out = rs & oe_imm16; 297012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org break; 297112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case ORI: 297212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org alu_out = rs | oe_imm16; 297312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org break; 297412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case XORI: 297512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org alu_out = rs ^ oe_imm16; 297612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org break; 297712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case LUI: { 297812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org int32_t alu32_out = (oe_imm16 << 16); 297912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Sign-extend result of 32bit operation into 64bit register. 298012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org alu_out = static_cast<int64_t>(alu32_out); 298112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 298212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org break; 298312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // ------------- Memory instructions. 298412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case LB: 298512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org addr = rs + se_imm16; 298612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org alu_out = ReadB(addr); 298712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org break; 298812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case LH: 298912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org addr = rs + se_imm16; 299012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org alu_out = ReadH(addr, instr); 299112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org break; 299212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case LWL: { 299312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // al_offset is offset of the effective address within an aligned word. 299412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org uint8_t al_offset = (rs + se_imm16) & kInt32AlignmentMask; 299512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org uint8_t byte_shift = kInt32AlignmentMask - al_offset; 299612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org uint32_t mask = (1 << byte_shift * 8) - 1; 299712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org addr = rs + se_imm16 - al_offset; 299812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org alu_out = ReadW(addr, instr); 299912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org alu_out <<= byte_shift * 8; 300012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org alu_out |= rt & mask; 300112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org break; 300212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 300312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case LW: 300412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org addr = rs + se_imm16; 300512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org alu_out = ReadW(addr, instr); 300612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org break; 300712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case LWU: 300812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org addr = rs + se_imm16; 300912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org alu_out = ReadWU(addr, instr); 301012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org break; 301112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case LD: 301212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org addr = rs + se_imm16; 301312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org alu_out = Read2W(addr, instr); 301412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org break; 301512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case LBU: 301612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org addr = rs + se_imm16; 301712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org alu_out = ReadBU(addr); 301812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org break; 301912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case LHU: 302012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org addr = rs + se_imm16; 302112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org alu_out = ReadHU(addr, instr); 302212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org break; 302312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case LWR: { 302412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // al_offset is offset of the effective address within an aligned word. 302512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org uint8_t al_offset = (rs + se_imm16) & kInt32AlignmentMask; 302612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org uint8_t byte_shift = kInt32AlignmentMask - al_offset; 302712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org uint32_t mask = al_offset ? (~0 << (byte_shift + 1) * 8) : 0; 302812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org addr = rs + se_imm16 - al_offset; 302912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org alu_out = ReadW(addr, instr); 303012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org alu_out = static_cast<uint32_t> (alu_out) >> al_offset * 8; 303112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org alu_out |= rt & mask; 303212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org break; 303312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 303412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case SB: 303512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org addr = rs + se_imm16; 303612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org break; 303712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case SH: 303812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org addr = rs + se_imm16; 303912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org break; 304012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case SWL: { 304112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org uint8_t al_offset = (rs + se_imm16) & kInt32AlignmentMask; 304212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org uint8_t byte_shift = kInt32AlignmentMask - al_offset; 304312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org uint32_t mask = byte_shift ? (~0 << (al_offset + 1) * 8) : 0; 304412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org addr = rs + se_imm16 - al_offset; 304512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org mem_value = ReadW(addr, instr) & mask; 304612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org mem_value |= static_cast<uint32_t>(rt) >> byte_shift * 8; 304712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org break; 304812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 304912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case SW: 305012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case SD: 305112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org addr = rs + se_imm16; 305212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org break; 305312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case SWR: { 305412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org uint8_t al_offset = (rs + se_imm16) & kInt32AlignmentMask; 305512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org uint32_t mask = (1 << al_offset * 8) - 1; 305612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org addr = rs + se_imm16 - al_offset; 305712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org mem_value = ReadW(addr, instr); 305812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org mem_value = (rt << al_offset * 8) | (mem_value & mask); 305912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org break; 306012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 306112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case LWC1: 306212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org addr = rs + se_imm16; 306312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org alu_out = ReadW(addr, instr); 306412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org break; 306512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case LDC1: 306612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org addr = rs + se_imm16; 306712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org fp_out = ReadD(addr, instr); 306812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org break; 306912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case SWC1: 307012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case SDC1: 307112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org addr = rs + se_imm16; 307212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org break; 307312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org default: 307412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org UNREACHABLE(); 307512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 307612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 307712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // ---------- Raise exceptions triggered. 307812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org SignalExceptions(); 307912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 308012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // ---------- Execution. 308112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org switch (op) { 308212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // ------------- Branch instructions. 308312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case BEQ: 308412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case BNE: 308512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case BLEZ: 308612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case BGTZ: 308712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Branch instructions common part. 308812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org execute_branch_delay_instruction = true; 308912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Set next_pc. 309012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (do_branch) { 309112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org next_pc = current_pc + (imm16 << 2) + Instruction::kInstrSize; 309212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (instr->IsLinkingInstruction()) { 309312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org set_register(31, current_pc + 2* Instruction::kInstrSize); 309412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 309512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } else { 309612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org next_pc = current_pc + 2 * Instruction::kInstrSize; 309712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 309812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org break; 309912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // ------------- Arithmetic instructions. 310012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case ADDI: 310112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case DADDI: 310212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case ADDIU: 310312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case DADDIU: 310412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case SLTI: 310512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case SLTIU: 310612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case ANDI: 310712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case ORI: 310812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case XORI: 310912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case LUI: 311012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org set_register(rt_reg, alu_out); 311112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org TraceRegWr(alu_out); 311212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org break; 311312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // ------------- Memory instructions. 311412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case LB: 311512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case LH: 311612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case LWL: 311712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case LW: 311812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case LWU: 311912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case LD: 312012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case LBU: 312112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case LHU: 312212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case LWR: 312312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org set_register(rt_reg, alu_out); 312412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org break; 312512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case SB: 312612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org WriteB(addr, static_cast<int8_t>(rt)); 312712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org break; 312812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case SH: 312912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org WriteH(addr, static_cast<uint16_t>(rt), instr); 313012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org break; 313112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case SWL: 313212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org WriteW(addr, mem_value, instr); 313312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org break; 313412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case SW: 313512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org WriteW(addr, rt, instr); 313612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org break; 313712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case SD: 313812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Write2W(addr, rt, instr); 313912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org break; 314012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case SWR: 314112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org WriteW(addr, mem_value, instr); 314212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org break; 314312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case LWC1: 314412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org set_fpu_register(ft_reg, kFPUInvalidResult); // Trash upper 32 bits. 314512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org set_fpu_register_word(ft_reg, static_cast<int32_t>(alu_out)); 314612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org break; 314712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case LDC1: 314812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org set_fpu_register_double(ft_reg, fp_out); 314912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org break; 315012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case SWC1: 315112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org addr = rs + se_imm16; 315212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org WriteW(addr, get_fpu_register(ft_reg), instr); 315312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org break; 315412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case SDC1: 315512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org addr = rs + se_imm16; 315612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org WriteD(addr, get_fpu_register_double(ft_reg), instr); 315712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org break; 315812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org default: 315912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org break; 316012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 316112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 316212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 316312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (execute_branch_delay_instruction) { 316412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Execute branch delay slot 316512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // We don't check for end_sim_pc. First it should not be met as the current 316612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // pc is valid. Secondly a jump should always execute its branch delay slot. 316712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Instruction* branch_delay_instr = 316812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org reinterpret_cast<Instruction*>(current_pc+Instruction::kInstrSize); 316912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org BranchDelayInstructionDecode(branch_delay_instr); 317012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 317112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 317212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // If needed update pc after the branch delay execution. 317312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (next_pc != bad_ra) { 317412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org set_pc(next_pc); 317512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 317612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org} 317712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 317812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 317912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// Type 3: instructions using a 26 bytes immediate. (e.g. j, jal). 318012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgvoid Simulator::DecodeTypeJump(Instruction* instr) { 318112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Get current pc. 318212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org int32_t current_pc = get_pc(); 318312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Get unchanged bits of pc. 318412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org int32_t pc_high_bits = current_pc & 0xf0000000; 318512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Next pc. 318612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org int32_t next_pc = pc_high_bits | (instr->Imm26Value() << 2); 318712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 318812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Execute branch delay slot. 318912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // We don't check for end_sim_pc. First it should not be met as the current pc 319012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // is valid. Secondly a jump should always execute its branch delay slot. 319112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Instruction* branch_delay_instr = 319212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org reinterpret_cast<Instruction*>(current_pc + Instruction::kInstrSize); 319312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org BranchDelayInstructionDecode(branch_delay_instr); 319412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 319512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Update pc and ra if necessary. 319612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Do this after the branch delay execution. 319712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (instr->IsLinkingInstruction()) { 319812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org set_register(31, current_pc + 2 * Instruction::kInstrSize); 319912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 320012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org set_pc(next_pc); 320112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org pc_modified_ = true; 320212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org} 320312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 320412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 320512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// Executes the current instruction. 320612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgvoid Simulator::InstructionDecode(Instruction* instr) { 320712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (v8::internal::FLAG_check_icache) { 320812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org CheckICache(isolate_->simulator_i_cache(), instr); 320912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 321012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org pc_modified_ = false; 321112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 321212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org v8::internal::EmbeddedVector<char, 256> buffer; 321312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 321412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (::v8::internal::FLAG_trace_sim) { 321512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org SNPrintF(trace_buf_, " "); 321612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org disasm::NameConverter converter; 321712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org disasm::Disassembler dasm(converter); 321812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Use a reasonably large buffer. 321912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org dasm.InstructionDecode(buffer, reinterpret_cast<byte*>(instr)); 322012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 322112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 322212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org switch (instr->InstructionType()) { 322312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case Instruction::kRegisterType: 322412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org DecodeTypeRegister(instr); 322512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org break; 322612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case Instruction::kImmediateType: 322712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org DecodeTypeImmediate(instr); 322812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org break; 322912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org case Instruction::kJumpType: 323012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org DecodeTypeJump(instr); 323112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org break; 323212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org default: 323312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org UNSUPPORTED(); 323412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 323512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 323612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (::v8::internal::FLAG_trace_sim) { 323712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org PrintF(" 0x%08lx %-44s %s\n", reinterpret_cast<intptr_t>(instr), 323812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org buffer.start(), trace_buf_.start()); 323912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 324012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 324112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (!pc_modified_) { 324212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org set_register(pc, reinterpret_cast<int64_t>(instr) + 324312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Instruction::kInstrSize); 324412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 324512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org} 324612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 324712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 324812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 324912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgvoid Simulator::Execute() { 325012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Get the PC to simulate. Cannot use the accessor here as we need the 325112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // raw PC value and not the one used as input to arithmetic instructions. 325212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org int64_t program_counter = get_pc(); 325312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (::v8::internal::FLAG_stop_sim_at == 0) { 325412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Fast version of the dispatch loop without checking whether the simulator 325512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // should be stopping at a particular executed instruction. 325612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org while (program_counter != end_sim_pc) { 325712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Instruction* instr = reinterpret_cast<Instruction*>(program_counter); 325812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org icount_++; 325912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org InstructionDecode(instr); 326012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org program_counter = get_pc(); 326112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 326212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } else { 326312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // FLAG_stop_sim_at is at the non-default value. Stop in the debugger when 326412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // we reach the particular instuction count. 326512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org while (program_counter != end_sim_pc) { 326612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Instruction* instr = reinterpret_cast<Instruction*>(program_counter); 326712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org icount_++; 326812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (icount_ == static_cast<int64_t>(::v8::internal::FLAG_stop_sim_at)) { 326912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org MipsDebugger dbg(this); 327012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org dbg.Debug(); 327112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } else { 327212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org InstructionDecode(instr); 327312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 327412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org program_counter = get_pc(); 327512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 327612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 327712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org} 327812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 327912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 328012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgvoid Simulator::CallInternal(byte* entry) { 328112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Prepare to execute the code at entry. 328212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org set_register(pc, reinterpret_cast<int64_t>(entry)); 328312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Put down marker for end of simulation. The simulator will stop simulation 328412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // when the PC reaches this value. By saving the "end simulation" value into 328512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // the LR the simulation stops when returning to this call point. 328612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org set_register(ra, end_sim_pc); 328712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 328812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Remember the values of callee-saved registers. 328912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // The code below assumes that r9 is not used as sb (static base) in 329012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // simulator code and therefore is regarded as a callee-saved register. 329112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org int64_t s0_val = get_register(s0); 329212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org int64_t s1_val = get_register(s1); 329312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org int64_t s2_val = get_register(s2); 329412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org int64_t s3_val = get_register(s3); 329512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org int64_t s4_val = get_register(s4); 329612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org int64_t s5_val = get_register(s5); 329712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org int64_t s6_val = get_register(s6); 329812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org int64_t s7_val = get_register(s7); 329912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org int64_t gp_val = get_register(gp); 330012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org int64_t sp_val = get_register(sp); 330112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org int64_t fp_val = get_register(fp); 330212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 330312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Set up the callee-saved registers with a known value. To be able to check 330412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // that they are preserved properly across JS execution. 330512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org int64_t callee_saved_value = icount_; 330612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org set_register(s0, callee_saved_value); 330712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org set_register(s1, callee_saved_value); 330812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org set_register(s2, callee_saved_value); 330912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org set_register(s3, callee_saved_value); 331012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org set_register(s4, callee_saved_value); 331112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org set_register(s5, callee_saved_value); 331212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org set_register(s6, callee_saved_value); 331312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org set_register(s7, callee_saved_value); 331412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org set_register(gp, callee_saved_value); 331512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org set_register(fp, callee_saved_value); 331612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 331712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Start the simulation. 331812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org Execute(); 331912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 332012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Check that the callee-saved registers have been preserved. 332112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org CHECK_EQ(callee_saved_value, get_register(s0)); 332212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org CHECK_EQ(callee_saved_value, get_register(s1)); 332312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org CHECK_EQ(callee_saved_value, get_register(s2)); 332412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org CHECK_EQ(callee_saved_value, get_register(s3)); 332512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org CHECK_EQ(callee_saved_value, get_register(s4)); 332612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org CHECK_EQ(callee_saved_value, get_register(s5)); 332712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org CHECK_EQ(callee_saved_value, get_register(s6)); 332812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org CHECK_EQ(callee_saved_value, get_register(s7)); 332912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org CHECK_EQ(callee_saved_value, get_register(gp)); 333012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org CHECK_EQ(callee_saved_value, get_register(fp)); 333112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 333212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Restore callee-saved registers with the original value. 333312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org set_register(s0, s0_val); 333412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org set_register(s1, s1_val); 333512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org set_register(s2, s2_val); 333612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org set_register(s3, s3_val); 333712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org set_register(s4, s4_val); 333812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org set_register(s5, s5_val); 333912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org set_register(s6, s6_val); 334012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org set_register(s7, s7_val); 334112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org set_register(gp, gp_val); 334212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org set_register(sp, sp_val); 334312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org set_register(fp, fp_val); 334412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org} 334512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 334612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 334712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgint64_t Simulator::Call(byte* entry, int argument_count, ...) { 334812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org const int kRegisterPassedArguments = (kMipsAbi == kN64) ? 8 : 4; 334912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org va_list parameters; 335012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org va_start(parameters, argument_count); 335112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Set up arguments. 335212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 335312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // First four arguments passed in registers in both ABI's. 3354e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK(argument_count >= 4); 335512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org set_register(a0, va_arg(parameters, int64_t)); 335612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org set_register(a1, va_arg(parameters, int64_t)); 335712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org set_register(a2, va_arg(parameters, int64_t)); 335812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org set_register(a3, va_arg(parameters, int64_t)); 335912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 336012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (kMipsAbi == kN64) { 336112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Up to eight arguments passed in registers in N64 ABI. 336212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // TODO(plind): N64 ABI calls these regs a4 - a7. Clarify this. 336312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (argument_count >= 5) set_register(a4, va_arg(parameters, int64_t)); 336412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (argument_count >= 6) set_register(a5, va_arg(parameters, int64_t)); 336512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (argument_count >= 7) set_register(a6, va_arg(parameters, int64_t)); 336612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (argument_count >= 8) set_register(a7, va_arg(parameters, int64_t)); 336712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 336812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 336912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Remaining arguments passed on stack. 337012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org int64_t original_stack = get_register(sp); 337112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Compute position of stack on entry to generated code. 337212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org int stack_args_count = (argument_count > kRegisterPassedArguments) ? 337312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org (argument_count - kRegisterPassedArguments) : 0; 337412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org int stack_args_size = stack_args_count * sizeof(int64_t) + kCArgsSlotsSize; 337512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org int64_t entry_stack = original_stack - stack_args_size; 337612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 337712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (base::OS::ActivationFrameAlignment() != 0) { 337812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org entry_stack &= -base::OS::ActivationFrameAlignment(); 337912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 338012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Store remaining arguments on stack, from low to high memory. 338112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org intptr_t* stack_argument = reinterpret_cast<intptr_t*>(entry_stack); 338212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org for (int i = kRegisterPassedArguments; i < argument_count; i++) { 338312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org int stack_index = i - kRegisterPassedArguments + kCArgSlotCount; 338412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org stack_argument[stack_index] = va_arg(parameters, int64_t); 338512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 338612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org va_end(parameters); 338712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org set_register(sp, entry_stack); 338812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 338912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org CallInternal(entry); 339012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 339112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org // Pop stack passed arguments. 339212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org CHECK_EQ(entry_stack, get_register(sp)); 339312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org set_register(sp, original_stack); 339412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 339512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org int64_t result = get_register(v0); 339612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org return result; 339712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org} 339812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 339912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 340012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgdouble Simulator::CallFP(byte* entry, double d0, double d1) { 340112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (!IsMipsSoftFloatABI) { 340212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org const FPURegister fparg2 = (kMipsAbi == kN64) ? f13 : f14; 340312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org set_fpu_register_double(f12, d0); 340412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org set_fpu_register_double(fparg2, d1); 340512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } else { 340612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org int buffer[2]; 3407e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK(sizeof(buffer[0]) * 2 == sizeof(d0)); 340812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org memcpy(buffer, &d0, sizeof(d0)); 340912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org set_dw_register(a0, buffer); 341012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org memcpy(buffer, &d1, sizeof(d1)); 341112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org set_dw_register(a2, buffer); 341212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 341312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org CallInternal(entry); 341412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org if (!IsMipsSoftFloatABI) { 341512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org return get_fpu_register_double(f0); 341612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } else { 341712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org return get_double_from_register_pair(v0); 341812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org } 341912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org} 342012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 342112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 342212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orguintptr_t Simulator::PushAddress(uintptr_t address) { 342312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org int64_t new_sp = get_register(sp) - sizeof(uintptr_t); 342412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org uintptr_t* stack_slot = reinterpret_cast<uintptr_t*>(new_sp); 342512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org *stack_slot = address; 342612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org set_register(sp, new_sp); 342712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org return new_sp; 342812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org} 342912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 343012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 343112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orguintptr_t Simulator::PopAddress() { 343212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org int64_t current_sp = get_register(sp); 343312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org uintptr_t* stack_slot = reinterpret_cast<uintptr_t*>(current_sp); 343412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org uintptr_t address = *stack_slot; 343512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org set_register(sp, current_sp + sizeof(uintptr_t)); 343612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org return address; 343712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org} 343812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 343912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 344012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org#undef UNSUPPORTED 344112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 344212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org} } // namespace v8::internal 344312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 344412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org#endif // USE_SIMULATOR 344512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org 344612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org#endif // V8_TARGET_ARCH_MIPS64 3447