1257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// Copyright 2011 the V8 project authors. All rights reserved. 23100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// Redistribution and use in source and binary forms, with or without 33100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// modification, are permitted provided that the following conditions are 43100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// met: 53100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// 63100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// * Redistributions of source code must retain the above copyright 73100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// notice, this list of conditions and the following disclaimer. 83100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// * Redistributions in binary form must reproduce the above 93100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// copyright notice, this list of conditions and the following 103100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// disclaimer in the documentation and/or other materials provided 113100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// with the distribution. 123100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// * Neither the name of Google Inc. nor the names of its 133100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// contributors may be used to endorse or promote products derived 143100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// from this software without specific prior written permission. 153100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// 163100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 173100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 183100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 193100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 203100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 213100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 223100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 233100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 243100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 253100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 263100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 273100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 283100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu#include <stdlib.h> 2944f0eee88ff00398ff7f715fab053374d808c90dSteve Block#include <math.h> 3044f0eee88ff00398ff7f715fab053374d808c90dSteve Block#include <limits.h> 313100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu#include <cstdarg> 323100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu#include "v8.h" 333100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 34f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke#if defined(V8_TARGET_ARCH_MIPS) 35f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 36589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch#include "cpu.h" 373100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu#include "disasm.h" 383100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu#include "assembler.h" 39257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch#include "globals.h" // Need the BitCast. 403100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu#include "mips/constants-mips.h" 413100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu#include "mips/simulator-mips.h" 423100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 433100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 443100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// Only build the simulator if not compiling for real MIPS hardware. 4544f0eee88ff00398ff7f715fab053374d808c90dSteve Block#if defined(USE_SIMULATOR) 463100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 4744f0eee88ff00398ff7f715fab053374d808c90dSteve Blocknamespace v8 { 4844f0eee88ff00398ff7f715fab053374d808c90dSteve Blocknamespace internal { 493100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 50257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// Utils functions. 513100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescubool HaveSameSign(int32_t a, int32_t b) { 5244f0eee88ff00398ff7f715fab053374d808c90dSteve Block return ((a ^ b) >= 0); 5344f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 5444f0eee88ff00398ff7f715fab053374d808c90dSteve Block 5544f0eee88ff00398ff7f715fab053374d808c90dSteve Block 5644f0eee88ff00398ff7f715fab053374d808c90dSteve Blockuint32_t get_fcsr_condition_bit(uint32_t cc) { 5744f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (cc == 0) { 5844f0eee88ff00398ff7f715fab053374d808c90dSteve Block return 23; 5944f0eee88ff00398ff7f715fab053374d808c90dSteve Block } else { 6044f0eee88ff00398ff7f715fab053374d808c90dSteve Block return 24 + cc; 6144f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 623100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} 633100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 643100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 653100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// This macro provides a platform independent use of sscanf. The reason for 663100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// SScanF not being implemented in a platform independent was through 673100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// ::v8::internal::OS in the same way as SNPrintF is that the Windows C Run-Time 683100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// Library does not provide vsscanf. 693100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu#define SScanF sscanf // NOLINT 703100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 7144f0eee88ff00398ff7f715fab053374d808c90dSteve Block// The MipsDebugger class is used by the simulator while debugging simulated 723100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// code. 7344f0eee88ff00398ff7f715fab053374d808c90dSteve Blockclass MipsDebugger { 743100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu public: 753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch explicit MipsDebugger(Simulator* sim) : sim_(sim) { } 7644f0eee88ff00398ff7f715fab053374d808c90dSteve Block ~MipsDebugger(); 773100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 783100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu void Stop(Instruction* instr); 793100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu void Debug(); 8044f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Print all registers with a nice formatting. 8144f0eee88ff00398ff7f715fab053374d808c90dSteve Block void PrintAllRegs(); 8244f0eee88ff00398ff7f715fab053374d808c90dSteve Block void PrintAllRegsIncludingFPU(); 833100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 843100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu private: 853100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // We set the breakpoint code to 0xfffff to easily recognize it. 863100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu static const Instr kBreakpointInstr = SPECIAL | BREAK | 0xfffff << 6; 873100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu static const Instr kNopInstr = 0x0; 883100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 893100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu Simulator* sim_; 903100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 913100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu int32_t GetRegisterValue(int regnum); 9244f0eee88ff00398ff7f715fab053374d808c90dSteve Block int32_t GetFPURegisterValueInt(int regnum); 9344f0eee88ff00398ff7f715fab053374d808c90dSteve Block int64_t GetFPURegisterValueLong(int regnum); 9444f0eee88ff00398ff7f715fab053374d808c90dSteve Block float GetFPURegisterValueFloat(int regnum); 9544f0eee88ff00398ff7f715fab053374d808c90dSteve Block double GetFPURegisterValueDouble(int regnum); 963100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu bool GetValue(const char* desc, int32_t* value); 973100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 983100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // Set or delete a breakpoint. Returns true if successful. 993100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu bool SetBreakpoint(Instruction* breakpc); 1003100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu bool DeleteBreakpoint(Instruction* breakpc); 1013100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 1023100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // Undo and redo all breakpoints. This is needed to bracket disassembly and 1033100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // execution to skip past breakpoints when run from the debugger. 1043100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu void UndoBreakpoints(); 1053100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu void RedoBreakpoints(); 1063100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}; 1073100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 10844f0eee88ff00398ff7f715fab053374d808c90dSteve Block 10944f0eee88ff00398ff7f715fab053374d808c90dSteve BlockMipsDebugger::~MipsDebugger() { 1103100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} 1113100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 11244f0eee88ff00398ff7f715fab053374d808c90dSteve Block 1133100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu#ifdef GENERATED_CODE_COVERAGE 1143100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescustatic FILE* coverage_log = NULL; 1153100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 1163100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 1173100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescustatic void InitializeCoverage() { 1183100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu char* file_name = getenv("V8_GENERATED_CODE_COVERAGE_LOG"); 1193100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu if (file_name != NULL) { 1203100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu coverage_log = fopen(file_name, "aw+"); 1213100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu } 1223100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} 1233100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 1243100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 12544f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid MipsDebugger::Stop(Instruction* instr) { 1263fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Get the stop code. 1273fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch uint32_t code = instr->Bits(25, 6); 1283fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Retrieve the encoded address, which comes just after this stop. 1293fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch char** msg_address = 1303fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch reinterpret_cast<char**>(sim_->get_pc() + Instr::kInstrSize); 1313fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch char* msg = *msg_address; 1323fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch ASSERT(msg != NULL); 1333fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 1343fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Update this stop description. 1353fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch if (!watched_stops[code].desc) { 1363fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch watched_stops[code].desc = msg; 1373fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 1383fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 1393fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch if (strlen(msg) > 0) { 1403100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu if (coverage_log != NULL) { 1413100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu fprintf(coverage_log, "%s\n", str); 1423100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu fflush(coverage_log); 1433100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu } 1443fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Overwrite the instruction and address with nops. 1453fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch instr->SetInstructionBits(kNopInstr); 1463fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch reinterpret_cast<Instr*>(msg_address)->SetInstructionBits(kNopInstr); 1473100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu } 1483fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch sim_->set_pc(sim_->get_pc() + 2 * Instruction::kInstructionSize); 1493100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} 1503100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 15144f0eee88ff00398ff7f715fab053374d808c90dSteve Block 152257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch#else // GENERATED_CODE_COVERAGE 1533100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 1543100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu#define UNSUPPORTED() printf("Unsupported instruction.\n"); 1553100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 1563100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescustatic void InitializeCoverage() {} 1573100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 1583100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 15944f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid MipsDebugger::Stop(Instruction* instr) { 1603fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Get the stop code. 1613fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch uint32_t code = instr->Bits(25, 6); 1623fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Retrieve the encoded address, which comes just after this stop. 1633fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch char* msg = *reinterpret_cast<char**>(sim_->get_pc() + 1643fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Instruction::kInstrSize); 1653fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Update this stop description. 1663fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch if (!sim_->watched_stops[code].desc) { 1673fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch sim_->watched_stops[code].desc = msg; 1683fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 1693fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch PrintF("Simulator hit %s (%u)\n", msg, code); 1703fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch sim_->set_pc(sim_->get_pc() + 2 * Instruction::kInstrSize); 1713100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu Debug(); 1723100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} 1736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block#endif // GENERATED_CODE_COVERAGE 1743100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 1753100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 17644f0eee88ff00398ff7f715fab053374d808c90dSteve Blockint32_t MipsDebugger::GetRegisterValue(int regnum) { 1773100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu if (regnum == kNumSimuRegisters) { 1783100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu return sim_->get_pc(); 1793100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu } else { 1803100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu return sim_->get_register(regnum); 1813100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu } 1823100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} 1833100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 1843100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 18544f0eee88ff00398ff7f715fab053374d808c90dSteve Blockint32_t MipsDebugger::GetFPURegisterValueInt(int regnum) { 18644f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (regnum == kNumFPURegisters) { 18744f0eee88ff00398ff7f715fab053374d808c90dSteve Block return sim_->get_pc(); 18844f0eee88ff00398ff7f715fab053374d808c90dSteve Block } else { 18944f0eee88ff00398ff7f715fab053374d808c90dSteve Block return sim_->get_fpu_register(regnum); 19044f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 19144f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 19244f0eee88ff00398ff7f715fab053374d808c90dSteve Block 19344f0eee88ff00398ff7f715fab053374d808c90dSteve Block 19444f0eee88ff00398ff7f715fab053374d808c90dSteve Blockint64_t MipsDebugger::GetFPURegisterValueLong(int regnum) { 19544f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (regnum == kNumFPURegisters) { 19644f0eee88ff00398ff7f715fab053374d808c90dSteve Block return sim_->get_pc(); 19744f0eee88ff00398ff7f715fab053374d808c90dSteve Block } else { 19844f0eee88ff00398ff7f715fab053374d808c90dSteve Block return sim_->get_fpu_register_long(regnum); 19944f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 20044f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 20144f0eee88ff00398ff7f715fab053374d808c90dSteve Block 20244f0eee88ff00398ff7f715fab053374d808c90dSteve Block 20344f0eee88ff00398ff7f715fab053374d808c90dSteve Blockfloat MipsDebugger::GetFPURegisterValueFloat(int regnum) { 20444f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (regnum == kNumFPURegisters) { 20544f0eee88ff00398ff7f715fab053374d808c90dSteve Block return sim_->get_pc(); 20644f0eee88ff00398ff7f715fab053374d808c90dSteve Block } else { 20744f0eee88ff00398ff7f715fab053374d808c90dSteve Block return sim_->get_fpu_register_float(regnum); 20844f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 20944f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 21044f0eee88ff00398ff7f715fab053374d808c90dSteve Block 21144f0eee88ff00398ff7f715fab053374d808c90dSteve Block 21244f0eee88ff00398ff7f715fab053374d808c90dSteve Blockdouble MipsDebugger::GetFPURegisterValueDouble(int regnum) { 21344f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (regnum == kNumFPURegisters) { 21444f0eee88ff00398ff7f715fab053374d808c90dSteve Block return sim_->get_pc(); 21544f0eee88ff00398ff7f715fab053374d808c90dSteve Block } else { 21644f0eee88ff00398ff7f715fab053374d808c90dSteve Block return sim_->get_fpu_register_double(regnum); 21744f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 21844f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 21944f0eee88ff00398ff7f715fab053374d808c90dSteve Block 22044f0eee88ff00398ff7f715fab053374d808c90dSteve Block 22144f0eee88ff00398ff7f715fab053374d808c90dSteve Blockbool MipsDebugger::GetValue(const char* desc, int32_t* value) { 2223100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu int regnum = Registers::Number(desc); 22344f0eee88ff00398ff7f715fab053374d808c90dSteve Block int fpuregnum = FPURegisters::Number(desc); 22444f0eee88ff00398ff7f715fab053374d808c90dSteve Block 2253100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu if (regnum != kInvalidRegister) { 2263100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu *value = GetRegisterValue(regnum); 2273100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu return true; 22844f0eee88ff00398ff7f715fab053374d808c90dSteve Block } else if (fpuregnum != kInvalidFPURegister) { 22944f0eee88ff00398ff7f715fab053374d808c90dSteve Block *value = GetFPURegisterValueInt(fpuregnum); 23044f0eee88ff00398ff7f715fab053374d808c90dSteve Block return true; 23144f0eee88ff00398ff7f715fab053374d808c90dSteve Block } else if (strncmp(desc, "0x", 2) == 0) { 23244f0eee88ff00398ff7f715fab053374d808c90dSteve Block return SScanF(desc, "%x", reinterpret_cast<uint32_t*>(value)) == 1; 2333100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu } else { 2343100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu return SScanF(desc, "%i", value) == 1; 2353100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu } 2363100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu return false; 2373100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} 2383100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 2393100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 24044f0eee88ff00398ff7f715fab053374d808c90dSteve Blockbool MipsDebugger::SetBreakpoint(Instruction* breakpc) { 2413100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // Check if a breakpoint can be set. If not return without any side-effects. 2423100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu if (sim_->break_pc_ != NULL) { 2433100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu return false; 2443100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu } 2453100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 2463100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // Set the breakpoint. 2473100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu sim_->break_pc_ = breakpc; 2483100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu sim_->break_instr_ = breakpc->InstructionBits(); 2493100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // Not setting the breakpoint instruction in the code itself. It will be set 2503100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // when the debugger shell continues. 2513100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu return true; 2523100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} 2533100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 2543100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 25544f0eee88ff00398ff7f715fab053374d808c90dSteve Blockbool MipsDebugger::DeleteBreakpoint(Instruction* breakpc) { 2563100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu if (sim_->break_pc_ != NULL) { 2573100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu sim_->break_pc_->SetInstructionBits(sim_->break_instr_); 2583100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu } 2593100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 2603100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu sim_->break_pc_ = NULL; 2613100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu sim_->break_instr_ = 0; 2623100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu return true; 2633100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} 2643100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 2653100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 26644f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid MipsDebugger::UndoBreakpoints() { 2673100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu if (sim_->break_pc_ != NULL) { 2683100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu sim_->break_pc_->SetInstructionBits(sim_->break_instr_); 2693100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu } 2703100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} 2713100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 2723100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 27344f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid MipsDebugger::RedoBreakpoints() { 2743100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu if (sim_->break_pc_ != NULL) { 2753100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu sim_->break_pc_->SetInstructionBits(kBreakpointInstr); 2763100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu } 2773100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} 2783100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 27944f0eee88ff00398ff7f715fab053374d808c90dSteve Block 28044f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid MipsDebugger::PrintAllRegs() { 2813100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu#define REG_INFO(n) Registers::Name(n), GetRegisterValue(n), GetRegisterValue(n) 2823100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 2833100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu PrintF("\n"); 284257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // at, v0, a0. 2853100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu PrintF("%3s: 0x%08x %10d\t%3s: 0x%08x %10d\t%3s: 0x%08x %10d\n", 2863100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu REG_INFO(1), REG_INFO(2), REG_INFO(4)); 287257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // v1, a1. 2883100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu PrintF("%26s\t%3s: 0x%08x %10d\t%3s: 0x%08x %10d\n", 2893100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu "", REG_INFO(3), REG_INFO(5)); 290257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // a2. 2913100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu PrintF("%26s\t%26s\t%3s: 0x%08x %10d\n", "", "", REG_INFO(6)); 292257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // a3. 2933100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu PrintF("%26s\t%26s\t%3s: 0x%08x %10d\n", "", "", REG_INFO(7)); 2943100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu PrintF("\n"); 2953100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // t0-t7, s0-s7 2963100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu for (int i = 0; i < 8; i++) { 2973100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu PrintF("%3s: 0x%08x %10d\t%3s: 0x%08x %10d\n", 2983100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu REG_INFO(8+i), REG_INFO(16+i)); 2993100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu } 3003100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu PrintF("\n"); 301257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // t8, k0, LO. 3023100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu PrintF("%3s: 0x%08x %10d\t%3s: 0x%08x %10d\t%3s: 0x%08x %10d\n", 3033100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu REG_INFO(24), REG_INFO(26), REG_INFO(32)); 304257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // t9, k1, HI. 3053100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu PrintF("%3s: 0x%08x %10d\t%3s: 0x%08x %10d\t%3s: 0x%08x %10d\n", 3063100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu REG_INFO(25), REG_INFO(27), REG_INFO(33)); 307257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // sp, fp, gp. 3083100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu PrintF("%3s: 0x%08x %10d\t%3s: 0x%08x %10d\t%3s: 0x%08x %10d\n", 3093100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu REG_INFO(29), REG_INFO(30), REG_INFO(28)); 310257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // pc. 3113100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu PrintF("%3s: 0x%08x %10d\t%3s: 0x%08x %10d\n", 3123100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu REG_INFO(31), REG_INFO(34)); 31344f0eee88ff00398ff7f715fab053374d808c90dSteve Block 31444f0eee88ff00398ff7f715fab053374d808c90dSteve Block#undef REG_INFO 31544f0eee88ff00398ff7f715fab053374d808c90dSteve Block#undef FPU_REG_INFO 31644f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 31744f0eee88ff00398ff7f715fab053374d808c90dSteve Block 31844f0eee88ff00398ff7f715fab053374d808c90dSteve Block 31944f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid MipsDebugger::PrintAllRegsIncludingFPU() { 32044f0eee88ff00398ff7f715fab053374d808c90dSteve Block#define FPU_REG_INFO(n) FPURegisters::Name(n), FPURegisters::Name(n+1), \ 32144f0eee88ff00398ff7f715fab053374d808c90dSteve Block GetFPURegisterValueInt(n+1), \ 32244f0eee88ff00398ff7f715fab053374d808c90dSteve Block GetFPURegisterValueInt(n), \ 32344f0eee88ff00398ff7f715fab053374d808c90dSteve Block GetFPURegisterValueDouble(n) 32444f0eee88ff00398ff7f715fab053374d808c90dSteve Block 32544f0eee88ff00398ff7f715fab053374d808c90dSteve Block PrintAllRegs(); 32644f0eee88ff00398ff7f715fab053374d808c90dSteve Block 32744f0eee88ff00398ff7f715fab053374d808c90dSteve Block PrintF("\n\n"); 328257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // f0, f1, f2, ... f31. 32944f0eee88ff00398ff7f715fab053374d808c90dSteve Block PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO(0) ); 33044f0eee88ff00398ff7f715fab053374d808c90dSteve Block PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO(2) ); 33144f0eee88ff00398ff7f715fab053374d808c90dSteve Block PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO(4) ); 33244f0eee88ff00398ff7f715fab053374d808c90dSteve Block PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO(6) ); 33344f0eee88ff00398ff7f715fab053374d808c90dSteve Block PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO(8) ); 33444f0eee88ff00398ff7f715fab053374d808c90dSteve Block PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO(10)); 33544f0eee88ff00398ff7f715fab053374d808c90dSteve Block PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO(12)); 33644f0eee88ff00398ff7f715fab053374d808c90dSteve Block PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO(14)); 33744f0eee88ff00398ff7f715fab053374d808c90dSteve Block PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO(16)); 33844f0eee88ff00398ff7f715fab053374d808c90dSteve Block PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO(18)); 33944f0eee88ff00398ff7f715fab053374d808c90dSteve Block PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO(20)); 34044f0eee88ff00398ff7f715fab053374d808c90dSteve Block PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO(22)); 34144f0eee88ff00398ff7f715fab053374d808c90dSteve Block PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO(24)); 34244f0eee88ff00398ff7f715fab053374d808c90dSteve Block PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO(26)); 34344f0eee88ff00398ff7f715fab053374d808c90dSteve Block PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO(28)); 34444f0eee88ff00398ff7f715fab053374d808c90dSteve Block PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO(30)); 34544f0eee88ff00398ff7f715fab053374d808c90dSteve Block 3463100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu#undef REG_INFO 34744f0eee88ff00398ff7f715fab053374d808c90dSteve Block#undef FPU_REG_INFO 3483100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} 3493100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 35044f0eee88ff00398ff7f715fab053374d808c90dSteve Block 35144f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid MipsDebugger::Debug() { 3523100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu intptr_t last_pc = -1; 3533100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu bool done = false; 3543100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 3553100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu#define COMMAND_SIZE 63 3563100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu#define ARG_SIZE 255 3573100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 3583100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu#define STR(a) #a 3593100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu#define XSTR(a) STR(a) 3603100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 3613100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu char cmd[COMMAND_SIZE + 1]; 3623100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu char arg1[ARG_SIZE + 1]; 3633100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu char arg2[ARG_SIZE + 1]; 36444f0eee88ff00398ff7f715fab053374d808c90dSteve Block char* argv[3] = { cmd, arg1, arg2 }; 3653100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 366257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Make sure to have a proper terminating character if reaching the limit. 3673100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu cmd[COMMAND_SIZE] = 0; 3683100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu arg1[ARG_SIZE] = 0; 3693100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu arg2[ARG_SIZE] = 0; 3703100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 3713100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // Undo all set breakpoints while running in the debugger shell. This will 3723100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // make them invisible to all commands. 3733100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu UndoBreakpoints(); 3743100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 3753100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu while (!done && (sim_->get_pc() != Simulator::end_sim_pc)) { 3763100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu if (last_pc != sim_->get_pc()) { 3773100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu disasm::NameConverter converter; 3783100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu disasm::Disassembler dasm(converter); 379257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Use a reasonably large buffer. 3803100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu v8::internal::EmbeddedVector<char, 256> buffer; 3813100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu dasm.InstructionDecode(buffer, 382257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch reinterpret_cast<byte*>(sim_->get_pc())); 3833100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu PrintF(" 0x%08x %s\n", sim_->get_pc(), buffer.start()); 3843100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu last_pc = sim_->get_pc(); 3853100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu } 3863100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu char* line = ReadLine("sim> "); 3873100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu if (line == NULL) { 3883100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu break; 3893100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu } else { 3903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch char* last_input = sim_->last_debugger_input(); 3913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (strcmp(line, "\n") == 0 && last_input != NULL) { 3923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch line = last_input; 3933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 3943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Ownership is transferred to sim_; 3953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch sim_->set_last_debugger_input(line); 3963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 3973100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // Use sscanf to parse the individual parts of the command line. At the 3983100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // moment no command expects more than two parameters. 39944f0eee88ff00398ff7f715fab053374d808c90dSteve Block int argc = SScanF(line, 4003100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu "%" XSTR(COMMAND_SIZE) "s " 4013100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu "%" XSTR(ARG_SIZE) "s " 4023100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu "%" XSTR(ARG_SIZE) "s", 4033100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu cmd, arg1, arg2); 4043100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu if ((strcmp(cmd, "si") == 0) || (strcmp(cmd, "stepi") == 0)) { 40544f0eee88ff00398ff7f715fab053374d808c90dSteve Block Instruction* instr = reinterpret_cast<Instruction*>(sim_->get_pc()); 40644f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (!(instr->IsTrap()) || 40744f0eee88ff00398ff7f715fab053374d808c90dSteve Block instr->InstructionBits() == rtCallRedirInstr) { 4083100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu sim_->InstructionDecode( 40944f0eee88ff00398ff7f715fab053374d808c90dSteve Block reinterpret_cast<Instruction*>(sim_->get_pc())); 4103100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu } else { 4113100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // Allow si to jump over generated breakpoints. 4123100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu PrintF("/!\\ Jumping over generated breakpoint.\n"); 41344f0eee88ff00398ff7f715fab053374d808c90dSteve Block sim_->set_pc(sim_->get_pc() + Instruction::kInstrSize); 4143100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu } 4153100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu } else if ((strcmp(cmd, "c") == 0) || (strcmp(cmd, "cont") == 0)) { 4163100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // Execute the one instruction we broke at with breakpoints disabled. 4173100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu sim_->InstructionDecode(reinterpret_cast<Instruction*>(sim_->get_pc())); 4183100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // Leave the debugger shell. 4193100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu done = true; 4203100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu } else if ((strcmp(cmd, "p") == 0) || (strcmp(cmd, "print") == 0)) { 42144f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (argc == 2) { 4223100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu int32_t value; 42344f0eee88ff00398ff7f715fab053374d808c90dSteve Block float fvalue; 4243100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu if (strcmp(arg1, "all") == 0) { 4253100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu PrintAllRegs(); 42644f0eee88ff00398ff7f715fab053374d808c90dSteve Block } else if (strcmp(arg1, "allf") == 0) { 42744f0eee88ff00398ff7f715fab053374d808c90dSteve Block PrintAllRegsIncludingFPU(); 4283100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu } else { 42944f0eee88ff00398ff7f715fab053374d808c90dSteve Block int regnum = Registers::Number(arg1); 43044f0eee88ff00398ff7f715fab053374d808c90dSteve Block int fpuregnum = FPURegisters::Number(arg1); 43144f0eee88ff00398ff7f715fab053374d808c90dSteve Block 43244f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (regnum != kInvalidRegister) { 43344f0eee88ff00398ff7f715fab053374d808c90dSteve Block value = GetRegisterValue(regnum); 4343100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu PrintF("%s: 0x%08x %d \n", arg1, value, value); 43544f0eee88ff00398ff7f715fab053374d808c90dSteve Block } else if (fpuregnum != kInvalidFPURegister) { 43644f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (fpuregnum % 2 == 1) { 43744f0eee88ff00398ff7f715fab053374d808c90dSteve Block value = GetFPURegisterValueInt(fpuregnum); 43844f0eee88ff00398ff7f715fab053374d808c90dSteve Block fvalue = GetFPURegisterValueFloat(fpuregnum); 43944f0eee88ff00398ff7f715fab053374d808c90dSteve Block PrintF("%s: 0x%08x %11.4e\n", arg1, value, fvalue); 44044f0eee88ff00398ff7f715fab053374d808c90dSteve Block } else { 44144f0eee88ff00398ff7f715fab053374d808c90dSteve Block double dfvalue; 44244f0eee88ff00398ff7f715fab053374d808c90dSteve Block int32_t lvalue1 = GetFPURegisterValueInt(fpuregnum); 44344f0eee88ff00398ff7f715fab053374d808c90dSteve Block int32_t lvalue2 = GetFPURegisterValueInt(fpuregnum + 1); 44444f0eee88ff00398ff7f715fab053374d808c90dSteve Block dfvalue = GetFPURegisterValueDouble(fpuregnum); 44544f0eee88ff00398ff7f715fab053374d808c90dSteve Block PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", 44644f0eee88ff00398ff7f715fab053374d808c90dSteve Block FPURegisters::Name(fpuregnum+1), 44744f0eee88ff00398ff7f715fab053374d808c90dSteve Block FPURegisters::Name(fpuregnum), 44844f0eee88ff00398ff7f715fab053374d808c90dSteve Block lvalue1, 44944f0eee88ff00398ff7f715fab053374d808c90dSteve Block lvalue2, 45044f0eee88ff00398ff7f715fab053374d808c90dSteve Block dfvalue); 45144f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 4523100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu } else { 4533100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu PrintF("%s unrecognized\n", arg1); 4543100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu } 4553100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu } 4563100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu } else { 45744f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (argc == 3) { 45844f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (strcmp(arg2, "single") == 0) { 45944f0eee88ff00398ff7f715fab053374d808c90dSteve Block int32_t value; 46044f0eee88ff00398ff7f715fab053374d808c90dSteve Block float fvalue; 46144f0eee88ff00398ff7f715fab053374d808c90dSteve Block int fpuregnum = FPURegisters::Number(arg1); 46244f0eee88ff00398ff7f715fab053374d808c90dSteve Block 46344f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (fpuregnum != kInvalidFPURegister) { 46444f0eee88ff00398ff7f715fab053374d808c90dSteve Block value = GetFPURegisterValueInt(fpuregnum); 46544f0eee88ff00398ff7f715fab053374d808c90dSteve Block fvalue = GetFPURegisterValueFloat(fpuregnum); 46644f0eee88ff00398ff7f715fab053374d808c90dSteve Block PrintF("%s: 0x%08x %11.4e\n", arg1, value, fvalue); 46744f0eee88ff00398ff7f715fab053374d808c90dSteve Block } else { 46844f0eee88ff00398ff7f715fab053374d808c90dSteve Block PrintF("%s unrecognized\n", arg1); 46944f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 47044f0eee88ff00398ff7f715fab053374d808c90dSteve Block } else { 47144f0eee88ff00398ff7f715fab053374d808c90dSteve Block PrintF("print <fpu register> single\n"); 47244f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 47344f0eee88ff00398ff7f715fab053374d808c90dSteve Block } else { 47444f0eee88ff00398ff7f715fab053374d808c90dSteve Block PrintF("print <register> or print <fpu register> single\n"); 47544f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 4763100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu } 4773100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu } else if ((strcmp(cmd, "po") == 0) 4783100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu || (strcmp(cmd, "printobject") == 0)) { 47944f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (argc == 2) { 4803100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu int32_t value; 4813100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu if (GetValue(arg1, &value)) { 4823100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu Object* obj = reinterpret_cast<Object*>(value); 4833100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu PrintF("%s: \n", arg1); 4843100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu#ifdef DEBUG 4853100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu obj->PrintLn(); 4863100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu#else 4873100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu obj->ShortPrint(); 4883100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu PrintF("\n"); 4893100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu#endif 4903100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu } else { 4913100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu PrintF("%s unrecognized\n", arg1); 4923100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu } 4933100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu } else { 4943100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu PrintF("printobject <value>\n"); 4953100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu } 49644f0eee88ff00398ff7f715fab053374d808c90dSteve Block } else if (strcmp(cmd, "stack") == 0 || strcmp(cmd, "mem") == 0) { 49744f0eee88ff00398ff7f715fab053374d808c90dSteve Block int32_t* cur = NULL; 49844f0eee88ff00398ff7f715fab053374d808c90dSteve Block int32_t* end = NULL; 49944f0eee88ff00398ff7f715fab053374d808c90dSteve Block int next_arg = 1; 50044f0eee88ff00398ff7f715fab053374d808c90dSteve Block 50144f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (strcmp(cmd, "stack") == 0) { 50244f0eee88ff00398ff7f715fab053374d808c90dSteve Block cur = reinterpret_cast<int32_t*>(sim_->get_register(Simulator::sp)); 503257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else { // Command "mem". 50444f0eee88ff00398ff7f715fab053374d808c90dSteve Block int32_t value; 50544f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (!GetValue(arg1, &value)) { 50644f0eee88ff00398ff7f715fab053374d808c90dSteve Block PrintF("%s unrecognized\n", arg1); 50744f0eee88ff00398ff7f715fab053374d808c90dSteve Block continue; 50844f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 50944f0eee88ff00398ff7f715fab053374d808c90dSteve Block cur = reinterpret_cast<int32_t*>(value); 51044f0eee88ff00398ff7f715fab053374d808c90dSteve Block next_arg++; 51144f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 51244f0eee88ff00398ff7f715fab053374d808c90dSteve Block 51344f0eee88ff00398ff7f715fab053374d808c90dSteve Block int32_t words; 51444f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (argc == next_arg) { 51544f0eee88ff00398ff7f715fab053374d808c90dSteve Block words = 10; 51644f0eee88ff00398ff7f715fab053374d808c90dSteve Block } else if (argc == next_arg + 1) { 51744f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (!GetValue(argv[next_arg], &words)) { 51844f0eee88ff00398ff7f715fab053374d808c90dSteve Block words = 10; 51944f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 52044f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 52144f0eee88ff00398ff7f715fab053374d808c90dSteve Block end = cur + words; 52244f0eee88ff00398ff7f715fab053374d808c90dSteve Block 52344f0eee88ff00398ff7f715fab053374d808c90dSteve Block while (cur < end) { 524257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch PrintF(" 0x%08x: 0x%08x %10d", 52544f0eee88ff00398ff7f715fab053374d808c90dSteve Block reinterpret_cast<intptr_t>(cur), *cur, *cur); 526257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch HeapObject* obj = reinterpret_cast<HeapObject*>(*cur); 527257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch int value = *cur; 528257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Heap* current_heap = v8::internal::Isolate::Current()->heap(); 529257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (current_heap->Contains(obj) || ((value & 1) == 0)) { 530257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch PrintF(" ("); 531257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if ((value & 1) == 0) { 532257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch PrintF("smi %d", value / 2); 533257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else { 534257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch obj->ShortPrint(); 535257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 536257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch PrintF(")"); 537257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 538257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch PrintF("\n"); 53944f0eee88ff00398ff7f715fab053374d808c90dSteve Block cur++; 54044f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 54144f0eee88ff00398ff7f715fab053374d808c90dSteve Block 542257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else if ((strcmp(cmd, "disasm") == 0) || 543257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch (strcmp(cmd, "dpc") == 0) || 544257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch (strcmp(cmd, "di") == 0)) { 5453100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu disasm::NameConverter converter; 5463100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu disasm::Disassembler dasm(converter); 547257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Use a reasonably large buffer. 5483100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu v8::internal::EmbeddedVector<char, 256> buffer; 5493100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 550257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch byte* cur = NULL; 551257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch byte* end = NULL; 5523100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 55344f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (argc == 1) { 554257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch cur = reinterpret_cast<byte*>(sim_->get_pc()); 55544f0eee88ff00398ff7f715fab053374d808c90dSteve Block end = cur + (10 * Instruction::kInstrSize); 55644f0eee88ff00398ff7f715fab053374d808c90dSteve Block } else if (argc == 2) { 557257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch int regnum = Registers::Number(arg1); 558257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (regnum != kInvalidRegister || strncmp(arg1, "0x", 2) == 0) { 559257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // The argument is an address or a register name. 560257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch int32_t value; 561257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (GetValue(arg1, &value)) { 562257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch cur = reinterpret_cast<byte*>(value); 563257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Disassemble 10 instructions at <arg1>. 564257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch end = cur + (10 * Instruction::kInstrSize); 565257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 566257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else { 567257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // The argument is the number of instructions. 568257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch int32_t value; 569257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (GetValue(arg1, &value)) { 570257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch cur = reinterpret_cast<byte*>(sim_->get_pc()); 571257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Disassemble <arg1> instructions. 572257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch end = cur + (value * Instruction::kInstrSize); 573257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 5743100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu } 5753100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu } else { 5763100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu int32_t value1; 5773100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu int32_t value2; 5783100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu if (GetValue(arg1, &value1) && GetValue(arg2, &value2)) { 579257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch cur = reinterpret_cast<byte*>(value1); 58044f0eee88ff00398ff7f715fab053374d808c90dSteve Block end = cur + (value2 * Instruction::kInstrSize); 5813100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu } 5823100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu } 5833100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 5843100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu while (cur < end) { 5853100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu dasm.InstructionDecode(buffer, cur); 58644f0eee88ff00398ff7f715fab053374d808c90dSteve Block PrintF(" 0x%08x %s\n", 58744f0eee88ff00398ff7f715fab053374d808c90dSteve Block reinterpret_cast<intptr_t>(cur), buffer.start()); 58844f0eee88ff00398ff7f715fab053374d808c90dSteve Block cur += Instruction::kInstrSize; 5893100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu } 5903100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu } else if (strcmp(cmd, "gdb") == 0) { 5913100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu PrintF("relinquishing control to gdb\n"); 5923100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu v8::internal::OS::DebugBreak(); 5933100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu PrintF("regaining control from gdb\n"); 5943100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu } else if (strcmp(cmd, "break") == 0) { 59544f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (argc == 2) { 5963100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu int32_t value; 5973100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu if (GetValue(arg1, &value)) { 5983100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu if (!SetBreakpoint(reinterpret_cast<Instruction*>(value))) { 5993100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu PrintF("setting breakpoint failed\n"); 6003100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu } 6013100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu } else { 6023100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu PrintF("%s unrecognized\n", arg1); 6033100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu } 6043100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu } else { 6053100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu PrintF("break <address>\n"); 6063100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu } 6073100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu } else if (strcmp(cmd, "del") == 0) { 6083100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu if (!DeleteBreakpoint(NULL)) { 6093100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu PrintF("deleting breakpoint failed\n"); 6103100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu } 6113100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu } else if (strcmp(cmd, "flags") == 0) { 6123100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu PrintF("No flags on MIPS !\n"); 6133fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } else if (strcmp(cmd, "stop") == 0) { 6143fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch int32_t value; 6153fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch intptr_t stop_pc = sim_->get_pc() - 6163fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 2 * Instruction::kInstrSize; 6173fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Instruction* stop_instr = reinterpret_cast<Instruction*>(stop_pc); 6183fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Instruction* msg_address = 6193fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch reinterpret_cast<Instruction*>(stop_pc + 6203fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Instruction::kInstrSize); 6213fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch if ((argc == 2) && (strcmp(arg1, "unstop") == 0)) { 6223fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Remove the current stop. 6233fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch if (sim_->IsStopInstruction(stop_instr)) { 6243fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch stop_instr->SetInstructionBits(kNopInstr); 6253fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch msg_address->SetInstructionBits(kNopInstr); 6263fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } else { 6273fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch PrintF("Not at debugger stop.\n"); 6283fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 6293fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } else if (argc == 3) { 6303fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Print information about all/the specified breakpoint(s). 6313fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch if (strcmp(arg1, "info") == 0) { 6323fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch if (strcmp(arg2, "all") == 0) { 6333fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch PrintF("Stop information:\n"); 6343fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch for (uint32_t i = kMaxWatchpointCode + 1; 6353fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch i <= kMaxStopCode; 6363fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch i++) { 6373fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch sim_->PrintStopInfo(i); 6383fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 6393fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } else if (GetValue(arg2, &value)) { 6403fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch sim_->PrintStopInfo(value); 6413fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } else { 6423fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch PrintF("Unrecognized argument.\n"); 6433fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 6443fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } else if (strcmp(arg1, "enable") == 0) { 6453fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Enable all/the specified breakpoint(s). 6463fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch if (strcmp(arg2, "all") == 0) { 6473fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch for (uint32_t i = kMaxWatchpointCode + 1; 6483fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch i <= kMaxStopCode; 6493fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch i++) { 6503fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch sim_->EnableStop(i); 6513fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 6523fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } else if (GetValue(arg2, &value)) { 6533fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch sim_->EnableStop(value); 6543fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } else { 6553fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch PrintF("Unrecognized argument.\n"); 6563fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 6573fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } else if (strcmp(arg1, "disable") == 0) { 6583fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Disable all/the specified breakpoint(s). 6593fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch if (strcmp(arg2, "all") == 0) { 6603fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch for (uint32_t i = kMaxWatchpointCode + 1; 6613fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch i <= kMaxStopCode; 6623fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch i++) { 6633fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch sim_->DisableStop(i); 6643fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 6653fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } else if (GetValue(arg2, &value)) { 6663fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch sim_->DisableStop(value); 6673fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } else { 6683fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch PrintF("Unrecognized argument.\n"); 6693fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 6703fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 6713fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } else { 6723fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch PrintF("Wrong usage. Use help command for more information.\n"); 6733fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 6743100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu } else if ((strcmp(cmd, "stat") == 0) || (strcmp(cmd, "st") == 0)) { 675257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Print registers and disassemble. 6763100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu PrintAllRegs(); 6773100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu PrintF("\n"); 6783100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 6793100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu disasm::NameConverter converter; 6803100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu disasm::Disassembler dasm(converter); 681257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Use a reasonably large buffer. 6823100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu v8::internal::EmbeddedVector<char, 256> buffer; 6833100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 684257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch byte* cur = NULL; 685257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch byte* end = NULL; 6863100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 68744f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (argc == 1) { 688257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch cur = reinterpret_cast<byte*>(sim_->get_pc()); 68944f0eee88ff00398ff7f715fab053374d808c90dSteve Block end = cur + (10 * Instruction::kInstrSize); 69044f0eee88ff00398ff7f715fab053374d808c90dSteve Block } else if (argc == 2) { 6913100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu int32_t value; 6923100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu if (GetValue(arg1, &value)) { 693257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch cur = reinterpret_cast<byte*>(value); 6943100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // no length parameter passed, assume 10 instructions 69544f0eee88ff00398ff7f715fab053374d808c90dSteve Block end = cur + (10 * Instruction::kInstrSize); 6963100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu } 6973100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu } else { 6983100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu int32_t value1; 6993100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu int32_t value2; 7003100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu if (GetValue(arg1, &value1) && GetValue(arg2, &value2)) { 701257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch cur = reinterpret_cast<byte*>(value1); 70244f0eee88ff00398ff7f715fab053374d808c90dSteve Block end = cur + (value2 * Instruction::kInstrSize); 7033100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu } 7043100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu } 7053100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 7063100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu while (cur < end) { 7073100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu dasm.InstructionDecode(buffer, cur); 70844f0eee88ff00398ff7f715fab053374d808c90dSteve Block PrintF(" 0x%08x %s\n", 70944f0eee88ff00398ff7f715fab053374d808c90dSteve Block reinterpret_cast<intptr_t>(cur), buffer.start()); 71044f0eee88ff00398ff7f715fab053374d808c90dSteve Block cur += Instruction::kInstrSize; 7113100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu } 7123100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu } else if ((strcmp(cmd, "h") == 0) || (strcmp(cmd, "help") == 0)) { 7133100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu PrintF("cont\n"); 7143100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu PrintF(" continue execution (alias 'c')\n"); 7153100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu PrintF("stepi\n"); 7163100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu PrintF(" step one instruction (alias 'si')\n"); 7173100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu PrintF("print <register>\n"); 7183100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu PrintF(" print register content (alias 'p')\n"); 7193100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu PrintF(" use register name 'all' to print all registers\n"); 7203100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu PrintF("printobject <register>\n"); 7213100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu PrintF(" print an object from a register (alias 'po')\n"); 72244f0eee88ff00398ff7f715fab053374d808c90dSteve Block PrintF("stack [<words>]\n"); 72344f0eee88ff00398ff7f715fab053374d808c90dSteve Block PrintF(" dump stack content, default dump 10 words)\n"); 72444f0eee88ff00398ff7f715fab053374d808c90dSteve Block PrintF("mem <address> [<words>]\n"); 72544f0eee88ff00398ff7f715fab053374d808c90dSteve Block PrintF(" dump memory content, default dump 10 words)\n"); 7263100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu PrintF("flags\n"); 7273100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu PrintF(" print flags\n"); 7283100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu PrintF("disasm [<instructions>]\n"); 729257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch PrintF("disasm [<address/register>]\n"); 730257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch PrintF("disasm [[<address/register>] <instructions>]\n"); 731257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch PrintF(" disassemble code, default is 10 instructions\n"); 732257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch PrintF(" from pc (alias 'di')\n"); 7333100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu PrintF("gdb\n"); 7343100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu PrintF(" enter gdb\n"); 7353100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu PrintF("break <address>\n"); 7363100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu PrintF(" set a break point on the address\n"); 7373100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu PrintF("del\n"); 7383100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu PrintF(" delete the breakpoint\n"); 7393fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch PrintF("stop feature:\n"); 7403fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch PrintF(" Description:\n"); 7413fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch PrintF(" Stops are debug instructions inserted by\n"); 7423fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch PrintF(" the Assembler::stop() function.\n"); 7433fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch PrintF(" When hitting a stop, the Simulator will\n"); 7443fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch PrintF(" stop and and give control to the Debugger.\n"); 7453fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch PrintF(" All stop codes are watched:\n"); 7463fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch PrintF(" - They can be enabled / disabled: the Simulator\n"); 7473fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch PrintF(" will / won't stop when hitting them.\n"); 7483fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch PrintF(" - The Simulator keeps track of how many times they \n"); 7493fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch PrintF(" are met. (See the info command.) Going over a\n"); 7503fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch PrintF(" disabled stop still increases its counter. \n"); 7513fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch PrintF(" Commands:\n"); 7523fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch PrintF(" stop info all/<code> : print infos about number <code>\n"); 7533fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch PrintF(" or all stop(s).\n"); 7543fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch PrintF(" stop enable/disable all/<code> : enables / disables\n"); 7553fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch PrintF(" all or number <code> stop(s)\n"); 7563fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch PrintF(" stop unstop\n"); 7573fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch PrintF(" ignore the stop instruction at the current location\n"); 7583fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch PrintF(" from now on\n"); 7593100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu } else { 7603100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu PrintF("Unknown command: %s\n", cmd); 7613100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu } 7623100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu } 7633100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu } 7643100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 7653100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // Add all the breakpoints back to stop execution and enter the debugger 7663100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // shell when hit. 7673100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu RedoBreakpoints(); 7683100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 7693100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu#undef COMMAND_SIZE 7703100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu#undef ARG_SIZE 7713100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 7723100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu#undef STR 7733100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu#undef XSTR 7743100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} 7753100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 7763100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 77744f0eee88ff00398ff7f715fab053374d808c90dSteve Blockstatic bool ICacheMatch(void* one, void* two) { 77844f0eee88ff00398ff7f715fab053374d808c90dSteve Block ASSERT((reinterpret_cast<intptr_t>(one) & CachePage::kPageMask) == 0); 77944f0eee88ff00398ff7f715fab053374d808c90dSteve Block ASSERT((reinterpret_cast<intptr_t>(two) & CachePage::kPageMask) == 0); 78044f0eee88ff00398ff7f715fab053374d808c90dSteve Block return one == two; 78144f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 78244f0eee88ff00398ff7f715fab053374d808c90dSteve Block 7833100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 78444f0eee88ff00398ff7f715fab053374d808c90dSteve Blockstatic uint32_t ICacheHash(void* key) { 78544f0eee88ff00398ff7f715fab053374d808c90dSteve Block return static_cast<uint32_t>(reinterpret_cast<uintptr_t>(key)) >> 2; 78644f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 7873100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 78844f0eee88ff00398ff7f715fab053374d808c90dSteve Block 78944f0eee88ff00398ff7f715fab053374d808c90dSteve Blockstatic bool AllOnOnePage(uintptr_t start, int size) { 79044f0eee88ff00398ff7f715fab053374d808c90dSteve Block intptr_t start_page = (start & ~CachePage::kPageMask); 79144f0eee88ff00398ff7f715fab053374d808c90dSteve Block intptr_t end_page = ((start + size) & ~CachePage::kPageMask); 79244f0eee88ff00398ff7f715fab053374d808c90dSteve Block return start_page == end_page; 79344f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 79444f0eee88ff00398ff7f715fab053374d808c90dSteve Block 79544f0eee88ff00398ff7f715fab053374d808c90dSteve Block 7963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid Simulator::set_last_debugger_input(char* input) { 7973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch DeleteArray(last_debugger_input_); 7983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch last_debugger_input_ = input; 7993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 8003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 8013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 80244f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid Simulator::FlushICache(v8::internal::HashMap* i_cache, 80344f0eee88ff00398ff7f715fab053374d808c90dSteve Block void* start_addr, 80444f0eee88ff00398ff7f715fab053374d808c90dSteve Block size_t size) { 80544f0eee88ff00398ff7f715fab053374d808c90dSteve Block intptr_t start = reinterpret_cast<intptr_t>(start_addr); 80644f0eee88ff00398ff7f715fab053374d808c90dSteve Block int intra_line = (start & CachePage::kLineMask); 80744f0eee88ff00398ff7f715fab053374d808c90dSteve Block start -= intra_line; 80844f0eee88ff00398ff7f715fab053374d808c90dSteve Block size += intra_line; 80944f0eee88ff00398ff7f715fab053374d808c90dSteve Block size = ((size - 1) | CachePage::kLineMask) + 1; 81044f0eee88ff00398ff7f715fab053374d808c90dSteve Block int offset = (start & CachePage::kPageMask); 81144f0eee88ff00398ff7f715fab053374d808c90dSteve Block while (!AllOnOnePage(start, size - 1)) { 81244f0eee88ff00398ff7f715fab053374d808c90dSteve Block int bytes_to_flush = CachePage::kPageSize - offset; 81344f0eee88ff00398ff7f715fab053374d808c90dSteve Block FlushOnePage(i_cache, start, bytes_to_flush); 81444f0eee88ff00398ff7f715fab053374d808c90dSteve Block start += bytes_to_flush; 81544f0eee88ff00398ff7f715fab053374d808c90dSteve Block size -= bytes_to_flush; 81644f0eee88ff00398ff7f715fab053374d808c90dSteve Block ASSERT_EQ(0, start & CachePage::kPageMask); 81744f0eee88ff00398ff7f715fab053374d808c90dSteve Block offset = 0; 81844f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 81944f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (size != 0) { 82044f0eee88ff00398ff7f715fab053374d808c90dSteve Block FlushOnePage(i_cache, start, size); 82144f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 82244f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 82344f0eee88ff00398ff7f715fab053374d808c90dSteve Block 82444f0eee88ff00398ff7f715fab053374d808c90dSteve Block 82544f0eee88ff00398ff7f715fab053374d808c90dSteve BlockCachePage* Simulator::GetCachePage(v8::internal::HashMap* i_cache, void* page) { 82644f0eee88ff00398ff7f715fab053374d808c90dSteve Block v8::internal::HashMap::Entry* entry = i_cache->Lookup(page, 827257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ICacheHash(page), 828257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch true); 82944f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (entry->value == NULL) { 83044f0eee88ff00398ff7f715fab053374d808c90dSteve Block CachePage* new_page = new CachePage(); 83144f0eee88ff00398ff7f715fab053374d808c90dSteve Block entry->value = new_page; 83244f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 83344f0eee88ff00398ff7f715fab053374d808c90dSteve Block return reinterpret_cast<CachePage*>(entry->value); 83444f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 83544f0eee88ff00398ff7f715fab053374d808c90dSteve Block 83644f0eee88ff00398ff7f715fab053374d808c90dSteve Block 83744f0eee88ff00398ff7f715fab053374d808c90dSteve Block// Flush from start up to and not including start + size. 83844f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid Simulator::FlushOnePage(v8::internal::HashMap* i_cache, 83944f0eee88ff00398ff7f715fab053374d808c90dSteve Block intptr_t start, 84044f0eee88ff00398ff7f715fab053374d808c90dSteve Block int size) { 84144f0eee88ff00398ff7f715fab053374d808c90dSteve Block ASSERT(size <= CachePage::kPageSize); 84244f0eee88ff00398ff7f715fab053374d808c90dSteve Block ASSERT(AllOnOnePage(start, size - 1)); 84344f0eee88ff00398ff7f715fab053374d808c90dSteve Block ASSERT((start & CachePage::kLineMask) == 0); 84444f0eee88ff00398ff7f715fab053374d808c90dSteve Block ASSERT((size & CachePage::kLineMask) == 0); 84544f0eee88ff00398ff7f715fab053374d808c90dSteve Block void* page = reinterpret_cast<void*>(start & (~CachePage::kPageMask)); 84644f0eee88ff00398ff7f715fab053374d808c90dSteve Block int offset = (start & CachePage::kPageMask); 84744f0eee88ff00398ff7f715fab053374d808c90dSteve Block CachePage* cache_page = GetCachePage(i_cache, page); 84844f0eee88ff00398ff7f715fab053374d808c90dSteve Block char* valid_bytemap = cache_page->ValidityByte(offset); 84944f0eee88ff00398ff7f715fab053374d808c90dSteve Block memset(valid_bytemap, CachePage::LINE_INVALID, size >> CachePage::kLineShift); 85044f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 85144f0eee88ff00398ff7f715fab053374d808c90dSteve Block 85244f0eee88ff00398ff7f715fab053374d808c90dSteve Block 85344f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid Simulator::CheckICache(v8::internal::HashMap* i_cache, 85444f0eee88ff00398ff7f715fab053374d808c90dSteve Block Instruction* instr) { 85544f0eee88ff00398ff7f715fab053374d808c90dSteve Block intptr_t address = reinterpret_cast<intptr_t>(instr); 85644f0eee88ff00398ff7f715fab053374d808c90dSteve Block void* page = reinterpret_cast<void*>(address & (~CachePage::kPageMask)); 85744f0eee88ff00398ff7f715fab053374d808c90dSteve Block void* line = reinterpret_cast<void*>(address & (~CachePage::kLineMask)); 85844f0eee88ff00398ff7f715fab053374d808c90dSteve Block int offset = (address & CachePage::kPageMask); 85944f0eee88ff00398ff7f715fab053374d808c90dSteve Block CachePage* cache_page = GetCachePage(i_cache, page); 86044f0eee88ff00398ff7f715fab053374d808c90dSteve Block char* cache_valid_byte = cache_page->ValidityByte(offset); 86144f0eee88ff00398ff7f715fab053374d808c90dSteve Block bool cache_hit = (*cache_valid_byte == CachePage::LINE_VALID); 86244f0eee88ff00398ff7f715fab053374d808c90dSteve Block char* cached_line = cache_page->CachedData(offset & ~CachePage::kLineMask); 86344f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (cache_hit) { 86444f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Check that the data in memory matches the contents of the I-cache. 86544f0eee88ff00398ff7f715fab053374d808c90dSteve Block CHECK(memcmp(reinterpret_cast<void*>(instr), 86644f0eee88ff00398ff7f715fab053374d808c90dSteve Block cache_page->CachedData(offset), 86744f0eee88ff00398ff7f715fab053374d808c90dSteve Block Instruction::kInstrSize) == 0); 86844f0eee88ff00398ff7f715fab053374d808c90dSteve Block } else { 86944f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Cache miss. Load memory into the cache. 87044f0eee88ff00398ff7f715fab053374d808c90dSteve Block memcpy(cached_line, line, CachePage::kLineLength); 87144f0eee88ff00398ff7f715fab053374d808c90dSteve Block *cache_valid_byte = CachePage::LINE_VALID; 87244f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 87344f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 8743100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 8753100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 876257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid Simulator::Initialize(Isolate* isolate) { 877257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (isolate->simulator_initialized()) return; 878257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch isolate->set_simulator_initialized(true); 879257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ::v8::internal::ExternalReference::set_redirector(isolate, 880257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch &RedirectExternalReference); 8813100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} 8823100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 8833100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 884257744e915dfc84d6d07a6b2accf8402d9ffc708Ben MurdochSimulator::Simulator(Isolate* isolate) : isolate_(isolate) { 88544f0eee88ff00398ff7f715fab053374d808c90dSteve Block i_cache_ = isolate_->simulator_i_cache(); 88644f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (i_cache_ == NULL) { 88744f0eee88ff00398ff7f715fab053374d808c90dSteve Block i_cache_ = new v8::internal::HashMap(&ICacheMatch); 88844f0eee88ff00398ff7f715fab053374d808c90dSteve Block isolate_->set_simulator_i_cache(i_cache_); 88944f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 890257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Initialize(isolate); 8913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Set up simulator support first. Some of this information is needed to 8923100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // setup the architecture state. 89344f0eee88ff00398ff7f715fab053374d808c90dSteve Block stack_ = reinterpret_cast<char*>(malloc(stack_size_)); 8943100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu pc_modified_ = false; 8953100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu icount_ = 0; 89644f0eee88ff00398ff7f715fab053374d808c90dSteve Block break_count_ = 0; 8973100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu break_pc_ = NULL; 8983100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu break_instr_ = 0; 8993100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 9003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Set up architecture state. 9013100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // All registers are initialized to zero to start with. 9023100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu for (int i = 0; i < kNumSimuRegisters; i++) { 9033100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu registers_[i] = 0; 9043100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu } 90544f0eee88ff00398ff7f715fab053374d808c90dSteve Block for (int i = 0; i < kNumFPURegisters; i++) { 90644f0eee88ff00398ff7f715fab053374d808c90dSteve Block FPUregisters_[i] = 0; 90744f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 90844f0eee88ff00398ff7f715fab053374d808c90dSteve Block FCSR_ = 0; 9093100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 9103100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // The sp is initialized to point to the bottom (high address) of the 9113100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // allocated stack area. To be safe in potential stack underflows we leave 9123100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // some buffer below. 91344f0eee88ff00398ff7f715fab053374d808c90dSteve Block registers_[sp] = reinterpret_cast<int32_t>(stack_) + stack_size_ - 64; 9143100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // The ra and pc are initialized to a known bad value that will cause an 9153100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // access violation if the simulator ever tries to execute it. 9163100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu registers_[pc] = bad_ra; 9173100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu registers_[ra] = bad_ra; 9183100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu InitializeCoverage(); 91944f0eee88ff00398ff7f715fab053374d808c90dSteve Block for (int i = 0; i < kNumExceptions; i++) { 92044f0eee88ff00398ff7f715fab053374d808c90dSteve Block exceptions[i] = 0; 92144f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 9223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 9233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch last_debugger_input_ = NULL; 9243100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} 9253100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 9263100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 9273100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// When the generated code calls an external reference we need to catch that in 9283100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// the simulator. The external reference will be a function compiled for the 9293100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// host architecture. We need to call that function instead of trying to 9303100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// execute it with the simulator. We do that by redirecting the external 9313100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// reference to a swi (software-interrupt) instruction that is handled by 9323100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// the simulator. We write the original destination of the jump just at a known 9333100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// offset from the swi instruction so the simulator knows what to call. 9343100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuclass Redirection { 9353100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu public: 93644f0eee88ff00398ff7f715fab053374d808c90dSteve Block Redirection(void* external_function, ExternalReference::Type type) 9373100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu : external_function_(external_function), 9383100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu swi_instruction_(rtCallRedirInstr), 93944f0eee88ff00398ff7f715fab053374d808c90dSteve Block type_(type), 94044f0eee88ff00398ff7f715fab053374d808c90dSteve Block next_(NULL) { 94144f0eee88ff00398ff7f715fab053374d808c90dSteve Block Isolate* isolate = Isolate::Current(); 94244f0eee88ff00398ff7f715fab053374d808c90dSteve Block next_ = isolate->simulator_redirection(); 94344f0eee88ff00398ff7f715fab053374d808c90dSteve Block Simulator::current(isolate)-> 94444f0eee88ff00398ff7f715fab053374d808c90dSteve Block FlushICache(isolate->simulator_i_cache(), 94544f0eee88ff00398ff7f715fab053374d808c90dSteve Block reinterpret_cast<void*>(&swi_instruction_), 94644f0eee88ff00398ff7f715fab053374d808c90dSteve Block Instruction::kInstrSize); 94744f0eee88ff00398ff7f715fab053374d808c90dSteve Block isolate->set_simulator_redirection(this); 9483100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu } 9493100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 9503100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu void* address_of_swi_instruction() { 9513100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu return reinterpret_cast<void*>(&swi_instruction_); 9523100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu } 9533100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 9543100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu void* external_function() { return external_function_; } 95544f0eee88ff00398ff7f715fab053374d808c90dSteve Block ExternalReference::Type type() { return type_; } 9563100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 95744f0eee88ff00398ff7f715fab053374d808c90dSteve Block static Redirection* Get(void* external_function, 95844f0eee88ff00398ff7f715fab053374d808c90dSteve Block ExternalReference::Type type) { 95944f0eee88ff00398ff7f715fab053374d808c90dSteve Block Isolate* isolate = Isolate::Current(); 96044f0eee88ff00398ff7f715fab053374d808c90dSteve Block Redirection* current = isolate->simulator_redirection(); 96144f0eee88ff00398ff7f715fab053374d808c90dSteve Block for (; current != NULL; current = current->next_) { 9623100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu if (current->external_function_ == external_function) return current; 9633100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu } 96444f0eee88ff00398ff7f715fab053374d808c90dSteve Block return new Redirection(external_function, type); 9653100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu } 9663100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 9673100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu static Redirection* FromSwiInstruction(Instruction* swi_instruction) { 9683100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu char* addr_of_swi = reinterpret_cast<char*>(swi_instruction); 9693100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu char* addr_of_redirection = 9703100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu addr_of_swi - OFFSET_OF(Redirection, swi_instruction_); 9713100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu return reinterpret_cast<Redirection*>(addr_of_redirection); 9723100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu } 9733100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 9743100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu private: 9753100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu void* external_function_; 9763100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu uint32_t swi_instruction_; 97744f0eee88ff00398ff7f715fab053374d808c90dSteve Block ExternalReference::Type type_; 9783100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu Redirection* next_; 9793100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}; 9803100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 9813100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 9823100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid* Simulator::RedirectExternalReference(void* external_function, 98344f0eee88ff00398ff7f715fab053374d808c90dSteve Block ExternalReference::Type type) { 98444f0eee88ff00398ff7f715fab053374d808c90dSteve Block Redirection* redirection = Redirection::Get(external_function, type); 9853100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu return redirection->address_of_swi_instruction(); 9863100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} 9873100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 9883100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 9893100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// Get the active Simulator for the current thread. 99044f0eee88ff00398ff7f715fab053374d808c90dSteve BlockSimulator* Simulator::current(Isolate* isolate) { 99144f0eee88ff00398ff7f715fab053374d808c90dSteve Block v8::internal::Isolate::PerIsolateThreadData* isolate_data = 992257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch isolate->FindOrAllocatePerThreadDataForThisThread(); 993257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(isolate_data != NULL); 99444f0eee88ff00398ff7f715fab053374d808c90dSteve Block ASSERT(isolate_data != NULL); 99544f0eee88ff00398ff7f715fab053374d808c90dSteve Block 99644f0eee88ff00398ff7f715fab053374d808c90dSteve Block Simulator* sim = isolate_data->simulator(); 9973100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu if (sim == NULL) { 99844f0eee88ff00398ff7f715fab053374d808c90dSteve Block // TODO(146): delete the simulator object when a thread/isolate goes away. 999257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch sim = new Simulator(isolate); 100044f0eee88ff00398ff7f715fab053374d808c90dSteve Block isolate_data->set_simulator(sim); 10013100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu } 10023100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu return sim; 10033100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} 10043100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 10053100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 10063100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// Sets the register in the architecture state. It will also deal with updating 10073100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// Simulator internal state for special registers such as PC. 10083100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Simulator::set_register(int reg, int32_t value) { 10093100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu ASSERT((reg >= 0) && (reg < kNumSimuRegisters)); 10103100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu if (reg == pc) { 10113100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu pc_modified_ = true; 10123100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu } 10133100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 1014257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Zero register always holds 0. 10153100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu registers_[reg] = (reg == 0) ? 0 : value; 10163100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} 10173100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 101844f0eee88ff00398ff7f715fab053374d808c90dSteve Block 10193100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Simulator::set_fpu_register(int fpureg, int32_t value) { 10203100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu ASSERT((fpureg >= 0) && (fpureg < kNumFPURegisters)); 10213100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu FPUregisters_[fpureg] = value; 10223100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} 10233100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 102444f0eee88ff00398ff7f715fab053374d808c90dSteve Block 102544f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid Simulator::set_fpu_register_float(int fpureg, float value) { 102644f0eee88ff00398ff7f715fab053374d808c90dSteve Block ASSERT((fpureg >= 0) && (fpureg < kNumFPURegisters)); 102744f0eee88ff00398ff7f715fab053374d808c90dSteve Block *BitCast<float*>(&FPUregisters_[fpureg]) = value; 102844f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 102944f0eee88ff00398ff7f715fab053374d808c90dSteve Block 103044f0eee88ff00398ff7f715fab053374d808c90dSteve Block 10313100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Simulator::set_fpu_register_double(int fpureg, double value) { 10323100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu ASSERT((fpureg >= 0) && (fpureg < kNumFPURegisters) && ((fpureg % 2) == 0)); 103344f0eee88ff00398ff7f715fab053374d808c90dSteve Block *BitCast<double*>(&FPUregisters_[fpureg]) = value; 10343100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} 10353100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 10363100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 10373100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// Get the register from the architecture state. This function does handle 10383100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// the special case of accessing the PC register. 10393100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuint32_t Simulator::get_register(int reg) const { 10403100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu ASSERT((reg >= 0) && (reg < kNumSimuRegisters)); 10413100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu if (reg == 0) 10423100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu return 0; 10433100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu else 10443100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu return registers_[reg] + ((reg == pc) ? Instruction::kPCReadOffset : 0); 10453100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} 10463100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 104744f0eee88ff00398ff7f715fab053374d808c90dSteve Block 10483100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuint32_t Simulator::get_fpu_register(int fpureg) const { 10493100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu ASSERT((fpureg >= 0) && (fpureg < kNumFPURegisters)); 10503100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu return FPUregisters_[fpureg]; 10513100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} 10523100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 105344f0eee88ff00398ff7f715fab053374d808c90dSteve Block 105444f0eee88ff00398ff7f715fab053374d808c90dSteve Blockint64_t Simulator::get_fpu_register_long(int fpureg) const { 105544f0eee88ff00398ff7f715fab053374d808c90dSteve Block ASSERT((fpureg >= 0) && (fpureg < kNumFPURegisters) && ((fpureg % 2) == 0)); 105644f0eee88ff00398ff7f715fab053374d808c90dSteve Block return *BitCast<int64_t*>( 105744f0eee88ff00398ff7f715fab053374d808c90dSteve Block const_cast<int32_t*>(&FPUregisters_[fpureg])); 105844f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 105944f0eee88ff00398ff7f715fab053374d808c90dSteve Block 106044f0eee88ff00398ff7f715fab053374d808c90dSteve Block 106144f0eee88ff00398ff7f715fab053374d808c90dSteve Blockfloat Simulator::get_fpu_register_float(int fpureg) const { 106244f0eee88ff00398ff7f715fab053374d808c90dSteve Block ASSERT((fpureg >= 0) && (fpureg < kNumFPURegisters)); 106344f0eee88ff00398ff7f715fab053374d808c90dSteve Block return *BitCast<float*>( 106444f0eee88ff00398ff7f715fab053374d808c90dSteve Block const_cast<int32_t*>(&FPUregisters_[fpureg])); 106544f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 106644f0eee88ff00398ff7f715fab053374d808c90dSteve Block 106744f0eee88ff00398ff7f715fab053374d808c90dSteve Block 10683100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescudouble Simulator::get_fpu_register_double(int fpureg) const { 10693100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu ASSERT((fpureg >= 0) && (fpureg < kNumFPURegisters) && ((fpureg % 2) == 0)); 107044f0eee88ff00398ff7f715fab053374d808c90dSteve Block return *BitCast<double*>(const_cast<int32_t*>(&FPUregisters_[fpureg])); 107144f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 107244f0eee88ff00398ff7f715fab053374d808c90dSteve Block 107344f0eee88ff00398ff7f715fab053374d808c90dSteve Block 1074257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// For use in calls that take two double values, constructed either 1075257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// from a0-a3 or f12 and f14. 1076257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid Simulator::GetFpArgs(double* x, double* y) { 1077257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (!IsMipsSoftFloatABI) { 1078257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch *x = get_fpu_register_double(12); 1079257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch *y = get_fpu_register_double(14); 1080257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else { 1081257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // We use a char buffer to get around the strict-aliasing rules which 1082257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // otherwise allow the compiler to optimize away the copy. 1083257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch char buffer[sizeof(*x)]; 1084257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch int32_t* reg_buffer = reinterpret_cast<int32_t*>(buffer); 1085257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1086257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Registers a0 and a1 -> x. 1087257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch reg_buffer[0] = get_register(a0); 1088257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch reg_buffer[1] = get_register(a1); 1089257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch memcpy(x, buffer, sizeof(buffer)); 1090257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1091257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Registers a2 and a3 -> y. 1092257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch reg_buffer[0] = get_register(a2); 1093257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch reg_buffer[1] = get_register(a3); 1094257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch memcpy(y, buffer, sizeof(buffer)); 1095257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 1096257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 1097257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1098257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1099257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// For use in calls that take one double value, constructed either 1100257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// from a0 and a1 or f12. 1101257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid Simulator::GetFpArgs(double* x) { 1102257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (!IsMipsSoftFloatABI) { 1103257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch *x = get_fpu_register_double(12); 1104257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else { 1105257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // We use a char buffer to get around the strict-aliasing rules which 1106257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // otherwise allow the compiler to optimize away the copy. 1107257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch char buffer[sizeof(*x)]; 1108257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch int32_t* reg_buffer = reinterpret_cast<int32_t*>(buffer); 1109257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Registers a0 and a1 -> x. 1110257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch reg_buffer[0] = get_register(a0); 1111257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch reg_buffer[1] = get_register(a1); 1112257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch memcpy(x, buffer, sizeof(buffer)); 1113257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 1114257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 1115257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1116257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1117257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// For use in calls that take one double value constructed either 1118257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// from a0 and a1 or f12 and one integer value. 1119257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid Simulator::GetFpArgs(double* x, int32_t* y) { 1120257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (!IsMipsSoftFloatABI) { 1121257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch *x = get_fpu_register_double(12); 1122257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch *y = get_register(a2); 1123257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else { 1124257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // We use a char buffer to get around the strict-aliasing rules which 1125257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // otherwise allow the compiler to optimize away the copy. 1126257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch char buffer[sizeof(*x)]; 1127257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch int32_t* reg_buffer = reinterpret_cast<int32_t*>(buffer); 1128257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Registers 0 and 1 -> x. 1129257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch reg_buffer[0] = get_register(a0); 1130257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch reg_buffer[1] = get_register(a1); 1131257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch memcpy(x, buffer, sizeof(buffer)); 1132257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1133257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Register 2 -> y. 1134257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch reg_buffer[0] = get_register(a2); 1135257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch memcpy(y, buffer, sizeof(*y)); 1136257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 1137257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 1138257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1139257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1140257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// The return value is either in v0/v1 or f0. 1141257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid Simulator::SetFpResult(const double& result) { 1142257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (!IsMipsSoftFloatABI) { 1143257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch set_fpu_register_double(0, result); 1144257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else { 1145257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch char buffer[2 * sizeof(registers_[0])]; 1146257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch int32_t* reg_buffer = reinterpret_cast<int32_t*>(buffer); 1147257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch memcpy(buffer, &result, sizeof(buffer)); 1148257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Copy result to v0 and v1. 1149257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch set_register(v0, reg_buffer[0]); 1150257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch set_register(v1, reg_buffer[1]); 1151257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 1152257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 1153257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1154257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 115544f0eee88ff00398ff7f715fab053374d808c90dSteve Block// Helper functions for setting and testing the FCSR register's bits. 115644f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid Simulator::set_fcsr_bit(uint32_t cc, bool value) { 115744f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (value) { 115844f0eee88ff00398ff7f715fab053374d808c90dSteve Block FCSR_ |= (1 << cc); 115944f0eee88ff00398ff7f715fab053374d808c90dSteve Block } else { 116044f0eee88ff00398ff7f715fab053374d808c90dSteve Block FCSR_ &= ~(1 << cc); 116144f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 116244f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 116344f0eee88ff00398ff7f715fab053374d808c90dSteve Block 116444f0eee88ff00398ff7f715fab053374d808c90dSteve Block 116544f0eee88ff00398ff7f715fab053374d808c90dSteve Blockbool Simulator::test_fcsr_bit(uint32_t cc) { 116644f0eee88ff00398ff7f715fab053374d808c90dSteve Block return FCSR_ & (1 << cc); 11673100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} 11683100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 116944f0eee88ff00398ff7f715fab053374d808c90dSteve Block 117044f0eee88ff00398ff7f715fab053374d808c90dSteve Block// Sets the rounding error codes in FCSR based on the result of the rounding. 117144f0eee88ff00398ff7f715fab053374d808c90dSteve Block// Returns true if the operation was invalid. 117244f0eee88ff00398ff7f715fab053374d808c90dSteve Blockbool Simulator::set_fcsr_round_error(double original, double rounded) { 11733fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch bool ret = false; 11743fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 11753fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch if (!isfinite(original) || !isfinite(rounded)) { 11763fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch set_fcsr_bit(kFCSRInvalidOpFlagBit, true); 11773fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch ret = true; 117844f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 11793fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 11803fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch if (original != rounded) { 11813fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch set_fcsr_bit(kFCSRInexactFlagBit, true); 11823fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 11833fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 11843fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch if (rounded < DBL_MIN && rounded > -DBL_MIN && rounded != 0) { 11853fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch set_fcsr_bit(kFCSRUnderflowFlagBit, true); 11863fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch ret = true; 11873fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 11883fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 11893fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch if (rounded > INT_MAX || rounded < INT_MIN) { 11903fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch set_fcsr_bit(kFCSROverflowFlagBit, true); 11913fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // The reference is not really clear but it seems this is required: 11923fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch set_fcsr_bit(kFCSRInvalidOpFlagBit, true); 11933fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch ret = true; 11943fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 11953fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 11963fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return ret; 119744f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 119844f0eee88ff00398ff7f715fab053374d808c90dSteve Block 119944f0eee88ff00398ff7f715fab053374d808c90dSteve Block 12003100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// Raw access to the PC register. 12013100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Simulator::set_pc(int32_t value) { 12023100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu pc_modified_ = true; 12033100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu registers_[pc] = value; 12043100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} 12053100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 120644f0eee88ff00398ff7f715fab053374d808c90dSteve Block 120744f0eee88ff00398ff7f715fab053374d808c90dSteve Blockbool Simulator::has_bad_pc() const { 120844f0eee88ff00398ff7f715fab053374d808c90dSteve Block return ((registers_[pc] == bad_ra) || (registers_[pc] == end_sim_pc)); 120944f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 121044f0eee88ff00398ff7f715fab053374d808c90dSteve Block 121144f0eee88ff00398ff7f715fab053374d808c90dSteve Block 12123100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// Raw access to the PC register without the special adjustment when reading. 12133100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuint32_t Simulator::get_pc() const { 12143100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu return registers_[pc]; 12153100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} 12163100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 12173100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 12183100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// The MIPS cannot do unaligned reads and writes. On some MIPS platforms an 12193100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// interrupt is caused. On others it does a funky rotation thing. For now we 12203100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// simply disallow unaligned reads, but at some point we may want to move to 12213100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// emulating the rotate behaviour. Note that simulator runs have the runtime 12223100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// system running directly on the host system and only generated code is 12233100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// executed in the simulator. Since the host is typically IA32 we will not 12243100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// get the correct MIPS-like behaviour on unaligned accesses. 12253100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 12263100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuint Simulator::ReadW(int32_t addr, Instruction* instr) { 122744f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (addr >=0 && addr < 0x400) { 1228257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // This has to be a NULL-dereference, drop into debugger. 1229589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch PrintF("Memory read from bad address: 0x%08x, pc=0x%08x\n", 1230589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch addr, reinterpret_cast<intptr_t>(instr)); 123144f0eee88ff00398ff7f715fab053374d808c90dSteve Block MipsDebugger dbg(this); 123244f0eee88ff00398ff7f715fab053374d808c90dSteve Block dbg.Debug(); 123344f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 123444f0eee88ff00398ff7f715fab053374d808c90dSteve Block if ((addr & kPointerAlignmentMask) == 0) { 12353100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu intptr_t* ptr = reinterpret_cast<intptr_t*>(addr); 12363100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu return *ptr; 12373100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu } 1238257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch PrintF("Unaligned read at 0x%08x, pc=0x%08" V8PRIxPTR "\n", 1239257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch addr, 1240257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch reinterpret_cast<intptr_t>(instr)); 124144f0eee88ff00398ff7f715fab053374d808c90dSteve Block MipsDebugger dbg(this); 124244f0eee88ff00398ff7f715fab053374d808c90dSteve Block dbg.Debug(); 12433100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu return 0; 12443100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} 12453100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 12463100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 12473100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Simulator::WriteW(int32_t addr, int value, Instruction* instr) { 124844f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (addr >= 0 && addr < 0x400) { 1249257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // This has to be a NULL-dereference, drop into debugger. 1250589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch PrintF("Memory write to bad address: 0x%08x, pc=0x%08x\n", 1251589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch addr, reinterpret_cast<intptr_t>(instr)); 125244f0eee88ff00398ff7f715fab053374d808c90dSteve Block MipsDebugger dbg(this); 125344f0eee88ff00398ff7f715fab053374d808c90dSteve Block dbg.Debug(); 125444f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 125544f0eee88ff00398ff7f715fab053374d808c90dSteve Block if ((addr & kPointerAlignmentMask) == 0) { 12563100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu intptr_t* ptr = reinterpret_cast<intptr_t*>(addr); 12573100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu *ptr = value; 12583100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu return; 12593100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu } 1260257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch PrintF("Unaligned write at 0x%08x, pc=0x%08" V8PRIxPTR "\n", 1261257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch addr, 1262257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch reinterpret_cast<intptr_t>(instr)); 126344f0eee88ff00398ff7f715fab053374d808c90dSteve Block MipsDebugger dbg(this); 126444f0eee88ff00398ff7f715fab053374d808c90dSteve Block dbg.Debug(); 12653100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} 12663100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 12673100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 12683100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescudouble Simulator::ReadD(int32_t addr, Instruction* instr) { 12693100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu if ((addr & kDoubleAlignmentMask) == 0) { 12703100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu double* ptr = reinterpret_cast<double*>(addr); 12713100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu return *ptr; 12723100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu } 1273257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch PrintF("Unaligned (double) read at 0x%08x, pc=0x%08" V8PRIxPTR "\n", 1274257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch addr, 1275257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch reinterpret_cast<intptr_t>(instr)); 12763100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu OS::Abort(); 12773100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu return 0; 12783100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} 12793100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 12803100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 12813100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Simulator::WriteD(int32_t addr, double value, Instruction* instr) { 12823100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu if ((addr & kDoubleAlignmentMask) == 0) { 12833100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu double* ptr = reinterpret_cast<double*>(addr); 12843100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu *ptr = value; 12853100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu return; 12863100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu } 1287257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch PrintF("Unaligned (double) write at 0x%08x, pc=0x%08" V8PRIxPTR "\n", 1288257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch addr, 1289257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch reinterpret_cast<intptr_t>(instr)); 12903100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu OS::Abort(); 12913100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} 12923100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 12933100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 12943100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuuint16_t Simulator::ReadHU(int32_t addr, Instruction* instr) { 12953100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu if ((addr & 1) == 0) { 12963100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu uint16_t* ptr = reinterpret_cast<uint16_t*>(addr); 12973100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu return *ptr; 12983100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu } 1299257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch PrintF("Unaligned unsigned halfword read at 0x%08x, pc=0x%08" V8PRIxPTR "\n", 1300257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch addr, 1301257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch reinterpret_cast<intptr_t>(instr)); 13023100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu OS::Abort(); 13033100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu return 0; 13043100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} 13053100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 13063100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 13073100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuint16_t Simulator::ReadH(int32_t addr, Instruction* instr) { 13083100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu if ((addr & 1) == 0) { 13093100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu int16_t* ptr = reinterpret_cast<int16_t*>(addr); 13103100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu return *ptr; 13113100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu } 1312257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch PrintF("Unaligned signed halfword read at 0x%08x, pc=0x%08" V8PRIxPTR "\n", 1313257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch addr, 1314257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch reinterpret_cast<intptr_t>(instr)); 13153100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu OS::Abort(); 13163100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu return 0; 13173100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} 13183100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 13193100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 13203100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Simulator::WriteH(int32_t addr, uint16_t value, Instruction* instr) { 13213100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu if ((addr & 1) == 0) { 13223100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu uint16_t* ptr = reinterpret_cast<uint16_t*>(addr); 13233100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu *ptr = value; 13243100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu return; 13253100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu } 1326257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch PrintF("Unaligned unsigned halfword write at 0x%08x, pc=0x%08" V8PRIxPTR "\n", 1327257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch addr, 1328257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch reinterpret_cast<intptr_t>(instr)); 13293100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu OS::Abort(); 13303100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} 13313100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 13323100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 13333100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Simulator::WriteH(int32_t addr, int16_t value, Instruction* instr) { 13343100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu if ((addr & 1) == 0) { 13353100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu int16_t* ptr = reinterpret_cast<int16_t*>(addr); 13363100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu *ptr = value; 13373100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu return; 13383100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu } 1339257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch PrintF("Unaligned halfword write at 0x%08x, pc=0x%08" V8PRIxPTR "\n", 1340257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch addr, 1341257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch reinterpret_cast<intptr_t>(instr)); 13423100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu OS::Abort(); 13433100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} 13443100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 13453100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 13463100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuuint32_t Simulator::ReadBU(int32_t addr) { 13473100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu uint8_t* ptr = reinterpret_cast<uint8_t*>(addr); 13483100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu return *ptr & 0xff; 13493100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} 13503100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 13513100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 13523100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuint32_t Simulator::ReadB(int32_t addr) { 13533100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu int8_t* ptr = reinterpret_cast<int8_t*>(addr); 135444f0eee88ff00398ff7f715fab053374d808c90dSteve Block return *ptr; 13553100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} 13563100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 13573100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 13583100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Simulator::WriteB(int32_t addr, uint8_t value) { 13593100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu uint8_t* ptr = reinterpret_cast<uint8_t*>(addr); 13603100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu *ptr = value; 13613100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} 13623100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 13633100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 13643100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Simulator::WriteB(int32_t addr, int8_t value) { 13653100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu int8_t* ptr = reinterpret_cast<int8_t*>(addr); 13663100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu *ptr = value; 13673100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} 13683100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 13693100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 13703100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// Returns the limit of the stack area to enable checking for stack overflows. 13713100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuuintptr_t Simulator::StackLimit() const { 13723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Leave a safety margin of 1024 bytes to prevent overrunning the stack when 13733100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // pushing values. 13743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return reinterpret_cast<uintptr_t>(stack_) + 1024; 13753100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} 13763100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 13773100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 13783100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// Unsupported instructions use Format to print an error and stop execution. 13793100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Simulator::Format(Instruction* instr, const char* format) { 13803100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu PrintF("Simulator found unsupported instruction:\n 0x%08x: %s\n", 138144f0eee88ff00398ff7f715fab053374d808c90dSteve Block reinterpret_cast<intptr_t>(instr), format); 13823100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu UNIMPLEMENTED_MIPS(); 13833100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} 13843100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 13853100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 13863100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// Calls into the V8 runtime are based on this very simple interface. 13873100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// Note: To be able to return two values from some calls the code in runtime.cc 13883100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// uses the ObjectPair which is essentially two 32-bit values stuffed into a 13893100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// 64-bit value. With the code below we assume that all runtime calls return 139044f0eee88ff00398ff7f715fab053374d808c90dSteve Block// 64 bits of result. If they don't, the v1 result register contains a bogus 13913100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// value, which is fine because it is caller-saved. 13923100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescutypedef int64_t (*SimulatorRuntimeCall)(int32_t arg0, 13933100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu int32_t arg1, 13943100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu int32_t arg2, 139544f0eee88ff00398ff7f715fab053374d808c90dSteve Block int32_t arg3, 139644f0eee88ff00398ff7f715fab053374d808c90dSteve Block int32_t arg4, 139744f0eee88ff00398ff7f715fab053374d808c90dSteve Block int32_t arg5); 139844f0eee88ff00398ff7f715fab053374d808c90dSteve Blocktypedef double (*SimulatorRuntimeFPCall)(int32_t arg0, 139944f0eee88ff00398ff7f715fab053374d808c90dSteve Block int32_t arg1, 140044f0eee88ff00398ff7f715fab053374d808c90dSteve Block int32_t arg2, 140144f0eee88ff00398ff7f715fab053374d808c90dSteve Block int32_t arg3); 14023100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 1403257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// This signature supports direct call in to API function native callback 1404257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// (refer to InvocationCallback in v8.h). 1405257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochtypedef v8::Handle<v8::Value> (*SimulatorRuntimeDirectApiCall)(int32_t arg0); 1406257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1407257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// This signature supports direct call to accessor getter callback. 1408257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochtypedef v8::Handle<v8::Value> (*SimulatorRuntimeDirectGetterCall)(int32_t arg0, 1409257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch int32_t arg1); 1410257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 14113100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// Software interrupt instructions are used by the simulator to call into the 141244f0eee88ff00398ff7f715fab053374d808c90dSteve Block// C-based V8 runtime. They are also used for debugging with simulator. 14133100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Simulator::SoftwareInterrupt(Instruction* instr) { 141444f0eee88ff00398ff7f715fab053374d808c90dSteve Block // There are several instructions that could get us here, 141544f0eee88ff00398ff7f715fab053374d808c90dSteve Block // the break_ instruction, or several variants of traps. All 141644f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Are "SPECIAL" class opcode, and are distinuished by function. 141744f0eee88ff00398ff7f715fab053374d808c90dSteve Block int32_t func = instr->FunctionFieldRaw(); 14183fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch uint32_t code = (func == BREAK) ? instr->Bits(25, 6) : -1; 141944f0eee88ff00398ff7f715fab053374d808c90dSteve Block 14203100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // We first check if we met a call_rt_redirected. 14213100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu if (instr->InstructionBits() == rtCallRedirInstr) { 14223100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu Redirection* redirection = Redirection::FromSwiInstruction(instr); 14233100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu int32_t arg0 = get_register(a0); 14243100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu int32_t arg1 = get_register(a1); 14253100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu int32_t arg2 = get_register(a2); 14263100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu int32_t arg3 = get_register(a3); 142744f0eee88ff00398ff7f715fab053374d808c90dSteve Block 142844f0eee88ff00398ff7f715fab053374d808c90dSteve Block int32_t* stack_pointer = reinterpret_cast<int32_t*>(get_register(sp)); 142969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch // Args 4 and 5 are on the stack after the reserved space for args 0..3. 143069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch int32_t arg4 = stack_pointer[4]; 143169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch int32_t arg5 = stack_pointer[5]; 1432257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1433257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch bool fp_call = 1434257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch (redirection->type() == ExternalReference::BUILTIN_FP_FP_CALL) || 1435257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch (redirection->type() == ExternalReference::BUILTIN_COMPARE_CALL) || 1436257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch (redirection->type() == ExternalReference::BUILTIN_FP_CALL) || 1437257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch (redirection->type() == ExternalReference::BUILTIN_FP_INT_CALL); 1438257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1439257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (!IsMipsSoftFloatABI) { 1440257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // With the hard floating point calling convention, double 1441257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // arguments are passed in FPU registers. Fetch the arguments 1442257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // from there and call the builtin using soft floating point 1443257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // convention. 1444257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch switch (redirection->type()) { 1445257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch case ExternalReference::BUILTIN_FP_FP_CALL: 1446257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch case ExternalReference::BUILTIN_COMPARE_CALL: 1447257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch arg0 = get_fpu_register(f12); 1448257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch arg1 = get_fpu_register(f13); 1449257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch arg2 = get_fpu_register(f14); 1450257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch arg3 = get_fpu_register(f15); 1451257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch break; 1452257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch case ExternalReference::BUILTIN_FP_CALL: 1453257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch arg0 = get_fpu_register(f12); 1454257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch arg1 = get_fpu_register(f13); 1455257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch break; 1456257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch case ExternalReference::BUILTIN_FP_INT_CALL: 1457257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch arg0 = get_fpu_register(f12); 1458257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch arg1 = get_fpu_register(f13); 1459257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch arg2 = get_register(a2); 1460257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch break; 1461257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch default: 1462257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch break; 1463257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 146444f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 1465257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 14663100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // This is dodgy but it works because the C entry stubs are never moved. 14673100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // See comment in codegen-arm.cc and bug 1242173. 14683100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu int32_t saved_ra = get_register(ra); 146944f0eee88ff00398ff7f715fab053374d808c90dSteve Block 147044f0eee88ff00398ff7f715fab053374d808c90dSteve Block intptr_t external = 1471257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch reinterpret_cast<intptr_t>(redirection->external_function()); 147244f0eee88ff00398ff7f715fab053374d808c90dSteve Block 147344f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Based on CpuFeatures::IsSupported(FPU), Mips will use either hardware 147444f0eee88ff00398ff7f715fab053374d808c90dSteve Block // FPU, or gcc soft-float routines. Hardware FPU is simulated in this 147544f0eee88ff00398ff7f715fab053374d808c90dSteve Block // simulator. Soft-float has additional abstraction of ExternalReference, 1476257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // to support serialization. 1477257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (fp_call) { 14783100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu SimulatorRuntimeFPCall target = 1479257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch reinterpret_cast<SimulatorRuntimeFPCall>(external); 1480257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (::v8::internal::FLAG_trace_sim) { 1481257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch double dval0, dval1; 1482257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch int32_t ival; 1483257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch switch (redirection->type()) { 1484257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch case ExternalReference::BUILTIN_FP_FP_CALL: 1485257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch case ExternalReference::BUILTIN_COMPARE_CALL: 1486257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch GetFpArgs(&dval0, &dval1); 1487257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch PrintF("Call to host function at %p with args %f, %f", 1488257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch FUNCTION_ADDR(target), dval0, dval1); 1489257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch break; 1490257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch case ExternalReference::BUILTIN_FP_CALL: 1491257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch GetFpArgs(&dval0); 1492257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch PrintF("Call to host function at %p with arg %f", 14933fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch FUNCTION_ADDR(target), dval0); 1494257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch break; 1495257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch case ExternalReference::BUILTIN_FP_INT_CALL: 1496257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch GetFpArgs(&dval0, &ival); 1497257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch PrintF("Call to host function at %p with args %f, %d", 1498257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch FUNCTION_ADDR(target), dval0, ival); 1499257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch break; 1500257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch default: 1501257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch UNREACHABLE(); 1502257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch break; 150344f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 15043100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu } 150544f0eee88ff00398ff7f715fab053374d808c90dSteve Block double result = target(arg0, arg1, arg2, arg3); 1506257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (redirection->type() != ExternalReference::BUILTIN_COMPARE_CALL) { 1507257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch SetFpResult(result); 1508257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else { 1509257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch int32_t gpreg_pair[2]; 1510257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch memcpy(&gpreg_pair[0], &result, 2 * sizeof(int32_t)); 1511257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch set_register(v0, gpreg_pair[0]); 1512257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch set_register(v1, gpreg_pair[1]); 1513257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 151444f0eee88ff00398ff7f715fab053374d808c90dSteve Block } else if (redirection->type() == ExternalReference::DIRECT_API_CALL) { 1515257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // See DirectCEntryStub::GenerateCall for explanation of register usage. 1516257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch SimulatorRuntimeDirectApiCall target = 1517257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch reinterpret_cast<SimulatorRuntimeDirectApiCall>(external); 1518257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (::v8::internal::FLAG_trace_sim) { 1519257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch PrintF("Call to host function at %p args %08x\n", 1520257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch FUNCTION_ADDR(target), arg1); 1521257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 1522257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch v8::Handle<v8::Value> result = target(arg1); 1523257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch *(reinterpret_cast<int*>(arg0)) = (int32_t) *result; 1524257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch set_register(v0, arg0); 152544f0eee88ff00398ff7f715fab053374d808c90dSteve Block } else if (redirection->type() == ExternalReference::DIRECT_GETTER_CALL) { 1526257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // See DirectCEntryStub::GenerateCall for explanation of register usage. 1527257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch SimulatorRuntimeDirectGetterCall target = 1528257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch reinterpret_cast<SimulatorRuntimeDirectGetterCall>(external); 1529257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (::v8::internal::FLAG_trace_sim) { 1530257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch PrintF("Call to host function at %p args %08x %08x\n", 1531257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch FUNCTION_ADDR(target), arg1, arg2); 1532257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 1533257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch v8::Handle<v8::Value> result = target(arg1, arg2); 1534257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch *(reinterpret_cast<int*>(arg0)) = (int32_t) *result; 1535257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch set_register(v0, arg0); 15363100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu } else { 15373100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu SimulatorRuntimeCall target = 1538257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch reinterpret_cast<SimulatorRuntimeCall>(external); 1539257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (::v8::internal::FLAG_trace_sim) { 15403100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu PrintF( 1541257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch "Call to host function at %p " 1542257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch "args %08x, %08x, %08x, %08x, %08x, %08x\n", 15433100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu FUNCTION_ADDR(target), 15443100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu arg0, 15453100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu arg1, 15463100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu arg2, 154744f0eee88ff00398ff7f715fab053374d808c90dSteve Block arg3, 154844f0eee88ff00398ff7f715fab053374d808c90dSteve Block arg4, 154944f0eee88ff00398ff7f715fab053374d808c90dSteve Block arg5); 15503100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu } 155144f0eee88ff00398ff7f715fab053374d808c90dSteve Block int64_t result = target(arg0, arg1, arg2, arg3, arg4, arg5); 155244f0eee88ff00398ff7f715fab053374d808c90dSteve Block set_register(v0, static_cast<int32_t>(result)); 155344f0eee88ff00398ff7f715fab053374d808c90dSteve Block set_register(v1, static_cast<int32_t>(result >> 32)); 155444f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 155544f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (::v8::internal::FLAG_trace_sim) { 155644f0eee88ff00398ff7f715fab053374d808c90dSteve Block PrintF("Returned %08x : %08x\n", get_register(v1), get_register(v0)); 15573100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu } 15583100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu set_register(ra, saved_ra); 15593100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu set_pc(get_register(ra)); 156044f0eee88ff00398ff7f715fab053374d808c90dSteve Block 15613fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } else if (func == BREAK && code <= kMaxStopCode) { 15623fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch if (IsWatchpoint(code)) { 15633fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch PrintWatchpoint(code); 15643fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } else { 15653fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch IncreaseStopCounter(code); 15663fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch HandleStop(code, instr); 15673fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 15683100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu } else { 156944f0eee88ff00398ff7f715fab053374d808c90dSteve Block // All remaining break_ codes, and all traps are handled here. 157044f0eee88ff00398ff7f715fab053374d808c90dSteve Block MipsDebugger dbg(this); 15713100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu dbg.Debug(); 15723100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu } 15733100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} 15743100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 157544f0eee88ff00398ff7f715fab053374d808c90dSteve Block 15763fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch// Stop helper functions. 15773fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochbool Simulator::IsWatchpoint(uint32_t code) { 15783fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return (code <= kMaxWatchpointCode); 15793fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch} 15803fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 15813fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 15823fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid Simulator::PrintWatchpoint(uint32_t code) { 15833fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch MipsDebugger dbg(this); 15843fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch ++break_count_; 15853fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch PrintF("\n---- break %d marker: %3d (instr count: %8d) ----------" 15863fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch "----------------------------------", 15873fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch code, break_count_, icount_); 15883fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch dbg.PrintAllRegs(); // Print registers and continue running. 15893fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch} 15903fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 15913fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 15923fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid Simulator::HandleStop(uint32_t code, Instruction* instr) { 15933fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Stop if it is enabled, otherwise go on jumping over the stop 15943fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // and the message address. 15953fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch if (IsEnabledStop(code)) { 15963fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch MipsDebugger dbg(this); 15973fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch dbg.Stop(instr); 15983fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } else { 15993fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch set_pc(get_pc() + 2 * Instruction::kInstrSize); 16003fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 16013fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch} 16023fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 16033fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 16043fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochbool Simulator::IsStopInstruction(Instruction* instr) { 16053fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch int32_t func = instr->FunctionFieldRaw(); 16063fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch uint32_t code = static_cast<uint32_t>(instr->Bits(25, 6)); 16073fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return (func == BREAK) && code > kMaxWatchpointCode && code <= kMaxStopCode; 16083fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch} 16093fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 16103fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 16113fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochbool Simulator::IsEnabledStop(uint32_t code) { 16123fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch ASSERT(code <= kMaxStopCode); 16133fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch ASSERT(code > kMaxWatchpointCode); 16143fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return !(watched_stops[code].count & kStopDisabledBit); 16153fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch} 16163fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 16173fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 16183fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid Simulator::EnableStop(uint32_t code) { 16193fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch if (!IsEnabledStop(code)) { 16203fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch watched_stops[code].count &= ~kStopDisabledBit; 16213fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 16223fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch} 16233fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 16243fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 16253fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid Simulator::DisableStop(uint32_t code) { 16263fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch if (IsEnabledStop(code)) { 16273fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch watched_stops[code].count |= kStopDisabledBit; 16283fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 16293fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch} 16303fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 16313fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 16323fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid Simulator::IncreaseStopCounter(uint32_t code) { 16333fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch ASSERT(code <= kMaxStopCode); 16343fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch if ((watched_stops[code].count & ~(1 << 31)) == 0x7fffffff) { 16353fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch PrintF("Stop counter for code %i has overflowed.\n" 16363fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch "Enabling this code and reseting the counter to 0.\n", code); 16373fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch watched_stops[code].count = 0; 16383fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch EnableStop(code); 16393fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } else { 16403fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch watched_stops[code].count++; 16413fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 16423fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch} 16433fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 16443fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 16453fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch// Print a stop status. 16463fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid Simulator::PrintStopInfo(uint32_t code) { 16473fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch if (code <= kMaxWatchpointCode) { 16483fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch PrintF("That is a watchpoint, not a stop.\n"); 16493fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return; 16503fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } else if (code > kMaxStopCode) { 16513fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch PrintF("Code too large, only %u stops can be used\n", kMaxStopCode + 1); 16523fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return; 16533fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 16543fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch const char* state = IsEnabledStop(code) ? "Enabled" : "Disabled"; 16553fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch int32_t count = watched_stops[code].count & ~kStopDisabledBit; 16563fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Don't print the state of unused breakpoints. 16573fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch if (count != 0) { 16583fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch if (watched_stops[code].desc) { 16593fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch PrintF("stop %i - 0x%x: \t%s, \tcounter = %i, \t%s\n", 16603fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch code, code, state, count, watched_stops[code].desc); 16613fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } else { 16623fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch PrintF("stop %i - 0x%x: \t%s, \tcounter = %i\n", 16633fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch code, code, state, count); 16643fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 16653fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 16663fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch} 16673fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 16683fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 16693100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Simulator::SignalExceptions() { 16703100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu for (int i = 1; i < kNumExceptions; i++) { 16713100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu if (exceptions[i] != 0) { 16723100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu V8_Fatal(__FILE__, __LINE__, "Error: Exception %i raised.", i); 16733100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu } 16743100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu } 16753100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} 16763100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 16773100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 167844f0eee88ff00398ff7f715fab053374d808c90dSteve Block// Handle execution based on instruction types. 16793100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 168044f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid Simulator::ConfigureTypeRegister(Instruction* instr, 168144f0eee88ff00398ff7f715fab053374d808c90dSteve Block int32_t& alu_out, 168244f0eee88ff00398ff7f715fab053374d808c90dSteve Block int64_t& i64hilo, 168344f0eee88ff00398ff7f715fab053374d808c90dSteve Block uint64_t& u64hilo, 168444f0eee88ff00398ff7f715fab053374d808c90dSteve Block int32_t& next_pc, 168544f0eee88ff00398ff7f715fab053374d808c90dSteve Block bool& do_interrupt) { 168644f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Every local variable declared here needs to be const. 168744f0eee88ff00398ff7f715fab053374d808c90dSteve Block // This is to make sure that changed values are sent back to 168844f0eee88ff00398ff7f715fab053374d808c90dSteve Block // DecodeTypeRegister correctly. 168944f0eee88ff00398ff7f715fab053374d808c90dSteve Block 169044f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Instruction fields. 169144f0eee88ff00398ff7f715fab053374d808c90dSteve Block const Opcode op = instr->OpcodeFieldRaw(); 169244f0eee88ff00398ff7f715fab053374d808c90dSteve Block const int32_t rs_reg = instr->RsValue(); 169344f0eee88ff00398ff7f715fab053374d808c90dSteve Block const int32_t rs = get_register(rs_reg); 169444f0eee88ff00398ff7f715fab053374d808c90dSteve Block const uint32_t rs_u = static_cast<uint32_t>(rs); 169544f0eee88ff00398ff7f715fab053374d808c90dSteve Block const int32_t rt_reg = instr->RtValue(); 169644f0eee88ff00398ff7f715fab053374d808c90dSteve Block const int32_t rt = get_register(rt_reg); 169744f0eee88ff00398ff7f715fab053374d808c90dSteve Block const uint32_t rt_u = static_cast<uint32_t>(rt); 169844f0eee88ff00398ff7f715fab053374d808c90dSteve Block const int32_t rd_reg = instr->RdValue(); 169944f0eee88ff00398ff7f715fab053374d808c90dSteve Block const uint32_t sa = instr->SaValue(); 170044f0eee88ff00398ff7f715fab053374d808c90dSteve Block 170144f0eee88ff00398ff7f715fab053374d808c90dSteve Block const int32_t fs_reg = instr->FsValue(); 17023100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 17033100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 1704257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ---------- Configuration. 17053100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu switch (op) { 1706257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch case COP1: // Coprocessor instructions. 17073100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu switch (instr->RsFieldRaw()) { 170844f0eee88ff00398ff7f715fab053374d808c90dSteve Block case BC1: // Handled in DecodeTypeImmed, should never come here. 17093100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu UNREACHABLE(); 17103100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu break; 171144f0eee88ff00398ff7f715fab053374d808c90dSteve Block case CFC1: 171244f0eee88ff00398ff7f715fab053374d808c90dSteve Block // At the moment only FCSR is supported. 171344f0eee88ff00398ff7f715fab053374d808c90dSteve Block ASSERT(fs_reg == kFCSRRegister); 171444f0eee88ff00398ff7f715fab053374d808c90dSteve Block alu_out = FCSR_; 171544f0eee88ff00398ff7f715fab053374d808c90dSteve Block break; 17163100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu case MFC1: 17173100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu alu_out = get_fpu_register(fs_reg); 17183100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu break; 17193100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu case MFHC1: 172044f0eee88ff00398ff7f715fab053374d808c90dSteve Block UNIMPLEMENTED_MIPS(); 17213100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu break; 172244f0eee88ff00398ff7f715fab053374d808c90dSteve Block case CTC1: 17233100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu case MTC1: 17243100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu case MTHC1: 17253100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // Do the store in the execution step. 17263100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu break; 17273100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu case S: 17283100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu case D: 17293100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu case W: 17303100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu case L: 17313100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu case PS: 17323100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // Do everything in the execution step. 17333100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu break; 17343100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu default: 17353100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu UNIMPLEMENTED_MIPS(); 17363100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu }; 17373100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu break; 17383100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu case SPECIAL: 17393100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu switch (instr->FunctionFieldRaw()) { 17403100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu case JR: 17413100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu case JALR: 174244f0eee88ff00398ff7f715fab053374d808c90dSteve Block next_pc = get_register(instr->RsValue()); 17433100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu break; 17443100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu case SLL: 17453100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu alu_out = rt << sa; 17463100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu break; 17473100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu case SRL: 174844f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (rs_reg == 0) { 174944f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Regular logical right shift of a word by a fixed number of 175044f0eee88ff00398ff7f715fab053374d808c90dSteve Block // bits instruction. RS field is always equal to 0. 175144f0eee88ff00398ff7f715fab053374d808c90dSteve Block alu_out = rt_u >> sa; 175244f0eee88ff00398ff7f715fab053374d808c90dSteve Block } else { 175344f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Logical right-rotate of a word by a fixed number of bits. This 175444f0eee88ff00398ff7f715fab053374d808c90dSteve Block // is special case of SRL instruction, added in MIPS32 Release 2. 1755257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // RS field is equal to 00001. 175644f0eee88ff00398ff7f715fab053374d808c90dSteve Block alu_out = (rt_u >> sa) | (rt_u << (32 - sa)); 175744f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 17583100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu break; 17593100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu case SRA: 17603100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu alu_out = rt >> sa; 17613100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu break; 17623100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu case SLLV: 17633100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu alu_out = rt << rs; 17643100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu break; 17653100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu case SRLV: 176644f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (sa == 0) { 176744f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Regular logical right-shift of a word by a variable number of 176844f0eee88ff00398ff7f715fab053374d808c90dSteve Block // bits instruction. SA field is always equal to 0. 176944f0eee88ff00398ff7f715fab053374d808c90dSteve Block alu_out = rt_u >> rs; 177044f0eee88ff00398ff7f715fab053374d808c90dSteve Block } else { 177144f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Logical right-rotate of a word by a variable number of bits. 177244f0eee88ff00398ff7f715fab053374d808c90dSteve Block // This is special case od SRLV instruction, added in MIPS32 1773257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Release 2. SA field is equal to 00001. 177444f0eee88ff00398ff7f715fab053374d808c90dSteve Block alu_out = (rt_u >> rs_u) | (rt_u << (32 - rs_u)); 177544f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 17763100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu break; 17773100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu case SRAV: 17783100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu alu_out = rt >> rs; 17793100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu break; 17803100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu case MFHI: 17813100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu alu_out = get_register(HI); 17823100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu break; 17833100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu case MFLO: 17843100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu alu_out = get_register(LO); 17853100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu break; 17863100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu case MULT: 178744f0eee88ff00398ff7f715fab053374d808c90dSteve Block i64hilo = static_cast<int64_t>(rs) * static_cast<int64_t>(rt); 17883100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu break; 17893100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu case MULTU: 179044f0eee88ff00398ff7f715fab053374d808c90dSteve Block u64hilo = static_cast<uint64_t>(rs_u) * static_cast<uint64_t>(rt_u); 17913100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu break; 17923100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu case ADD: 17933100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu if (HaveSameSign(rs, rt)) { 17943100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu if (rs > 0) { 17953100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu exceptions[kIntegerOverflow] = rs > (Registers::kMaxValue - rt); 17963100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu } else if (rs < 0) { 17973100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu exceptions[kIntegerUnderflow] = rs < (Registers::kMinValue - rt); 17983100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu } 17993100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu } 18003100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu alu_out = rs + rt; 18013100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu break; 18023100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu case ADDU: 18033100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu alu_out = rs + rt; 18043100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu break; 18053100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu case SUB: 18063100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu if (!HaveSameSign(rs, rt)) { 18073100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu if (rs > 0) { 18083100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu exceptions[kIntegerOverflow] = rs > (Registers::kMaxValue + rt); 18093100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu } else if (rs < 0) { 18103100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu exceptions[kIntegerUnderflow] = rs < (Registers::kMinValue + rt); 18113100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu } 18123100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu } 18133100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu alu_out = rs - rt; 18143100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu break; 18153100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu case SUBU: 18163100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu alu_out = rs - rt; 18173100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu break; 18183100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu case AND: 18193100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu alu_out = rs & rt; 18203100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu break; 18213100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu case OR: 18223100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu alu_out = rs | rt; 18233100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu break; 18243100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu case XOR: 18253100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu alu_out = rs ^ rt; 18263100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu break; 18273100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu case NOR: 18283100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu alu_out = ~(rs | rt); 18293100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu break; 18303100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu case SLT: 18313100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu alu_out = rs < rt ? 1 : 0; 18323100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu break; 18333100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu case SLTU: 18343100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu alu_out = rs_u < rt_u ? 1 : 0; 18353100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu break; 1836257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Break and trap instructions. 18373100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu case BREAK: 183844f0eee88ff00398ff7f715fab053374d808c90dSteve Block 18393100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu do_interrupt = true; 18403100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu break; 18413100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu case TGE: 18423100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu do_interrupt = rs >= rt; 18433100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu break; 18443100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu case TGEU: 18453100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu do_interrupt = rs_u >= rt_u; 18463100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu break; 18473100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu case TLT: 18483100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu do_interrupt = rs < rt; 18493100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu break; 18503100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu case TLTU: 18513100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu do_interrupt = rs_u < rt_u; 18523100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu break; 18533100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu case TEQ: 18543100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu do_interrupt = rs == rt; 18553100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu break; 18563100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu case TNE: 18573100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu do_interrupt = rs != rt; 18583100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu break; 185944f0eee88ff00398ff7f715fab053374d808c90dSteve Block case MOVN: 186044f0eee88ff00398ff7f715fab053374d808c90dSteve Block case MOVZ: 186144f0eee88ff00398ff7f715fab053374d808c90dSteve Block case MOVCI: 186244f0eee88ff00398ff7f715fab053374d808c90dSteve Block // No action taken on decode. 186344f0eee88ff00398ff7f715fab053374d808c90dSteve Block break; 1864257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch case DIV: 1865257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch case DIVU: 1866257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // div and divu never raise exceptions. 1867257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch break; 18683100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu default: 18693100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu UNREACHABLE(); 18703100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu }; 18713100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu break; 18723100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu case SPECIAL2: 18733100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu switch (instr->FunctionFieldRaw()) { 18743100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu case MUL: 18753100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu alu_out = rs_u * rt_u; // Only the lower 32 bits are kept. 18763100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu break; 187744f0eee88ff00398ff7f715fab053374d808c90dSteve Block case CLZ: 187844f0eee88ff00398ff7f715fab053374d808c90dSteve Block alu_out = __builtin_clz(rs_u); 187944f0eee88ff00398ff7f715fab053374d808c90dSteve Block break; 18803100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu default: 18813100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu UNREACHABLE(); 188244f0eee88ff00398ff7f715fab053374d808c90dSteve Block }; 188344f0eee88ff00398ff7f715fab053374d808c90dSteve Block break; 188444f0eee88ff00398ff7f715fab053374d808c90dSteve Block case SPECIAL3: 188544f0eee88ff00398ff7f715fab053374d808c90dSteve Block switch (instr->FunctionFieldRaw()) { 188644f0eee88ff00398ff7f715fab053374d808c90dSteve Block case INS: { // Mips32r2 instruction. 1887257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Interpret rd field as 5-bit msb of insert. 188844f0eee88ff00398ff7f715fab053374d808c90dSteve Block uint16_t msb = rd_reg; 188944f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Interpret sa field as 5-bit lsb of insert. 189044f0eee88ff00398ff7f715fab053374d808c90dSteve Block uint16_t lsb = sa; 189144f0eee88ff00398ff7f715fab053374d808c90dSteve Block uint16_t size = msb - lsb + 1; 189244f0eee88ff00398ff7f715fab053374d808c90dSteve Block uint32_t mask = (1 << size) - 1; 189344f0eee88ff00398ff7f715fab053374d808c90dSteve Block alu_out = (rt_u & ~(mask << lsb)) | ((rs_u & mask) << lsb); 189444f0eee88ff00398ff7f715fab053374d808c90dSteve Block break; 189544f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 189644f0eee88ff00398ff7f715fab053374d808c90dSteve Block case EXT: { // Mips32r2 instruction. 1897257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Interpret rd field as 5-bit msb of extract. 189844f0eee88ff00398ff7f715fab053374d808c90dSteve Block uint16_t msb = rd_reg; 189944f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Interpret sa field as 5-bit lsb of extract. 190044f0eee88ff00398ff7f715fab053374d808c90dSteve Block uint16_t lsb = sa; 190144f0eee88ff00398ff7f715fab053374d808c90dSteve Block uint16_t size = msb + 1; 190244f0eee88ff00398ff7f715fab053374d808c90dSteve Block uint32_t mask = (1 << size) - 1; 190344f0eee88ff00398ff7f715fab053374d808c90dSteve Block alu_out = (rs_u & (mask << lsb)) >> lsb; 190444f0eee88ff00398ff7f715fab053374d808c90dSteve Block break; 190544f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 190644f0eee88ff00398ff7f715fab053374d808c90dSteve Block default: 190744f0eee88ff00398ff7f715fab053374d808c90dSteve Block UNREACHABLE(); 190844f0eee88ff00398ff7f715fab053374d808c90dSteve Block }; 19093100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu break; 19103100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu default: 19113100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu UNREACHABLE(); 19123100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu }; 191344f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 191444f0eee88ff00398ff7f715fab053374d808c90dSteve Block 191544f0eee88ff00398ff7f715fab053374d808c90dSteve Block 191644f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid Simulator::DecodeTypeRegister(Instruction* instr) { 191744f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Instruction fields. 191844f0eee88ff00398ff7f715fab053374d808c90dSteve Block const Opcode op = instr->OpcodeFieldRaw(); 191944f0eee88ff00398ff7f715fab053374d808c90dSteve Block const int32_t rs_reg = instr->RsValue(); 192044f0eee88ff00398ff7f715fab053374d808c90dSteve Block const int32_t rs = get_register(rs_reg); 192144f0eee88ff00398ff7f715fab053374d808c90dSteve Block const uint32_t rs_u = static_cast<uint32_t>(rs); 192244f0eee88ff00398ff7f715fab053374d808c90dSteve Block const int32_t rt_reg = instr->RtValue(); 192344f0eee88ff00398ff7f715fab053374d808c90dSteve Block const int32_t rt = get_register(rt_reg); 192444f0eee88ff00398ff7f715fab053374d808c90dSteve Block const uint32_t rt_u = static_cast<uint32_t>(rt); 192544f0eee88ff00398ff7f715fab053374d808c90dSteve Block const int32_t rd_reg = instr->RdValue(); 192644f0eee88ff00398ff7f715fab053374d808c90dSteve Block 192744f0eee88ff00398ff7f715fab053374d808c90dSteve Block const int32_t fs_reg = instr->FsValue(); 192844f0eee88ff00398ff7f715fab053374d808c90dSteve Block const int32_t ft_reg = instr->FtValue(); 192944f0eee88ff00398ff7f715fab053374d808c90dSteve Block const int32_t fd_reg = instr->FdValue(); 193044f0eee88ff00398ff7f715fab053374d808c90dSteve Block int64_t i64hilo = 0; 193144f0eee88ff00398ff7f715fab053374d808c90dSteve Block uint64_t u64hilo = 0; 193244f0eee88ff00398ff7f715fab053374d808c90dSteve Block 1933257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ALU output. 193444f0eee88ff00398ff7f715fab053374d808c90dSteve Block // It should not be used as is. Instructions using it should always 193544f0eee88ff00398ff7f715fab053374d808c90dSteve Block // initialize it first. 193644f0eee88ff00398ff7f715fab053374d808c90dSteve Block int32_t alu_out = 0x12345678; 193744f0eee88ff00398ff7f715fab053374d808c90dSteve Block 193844f0eee88ff00398ff7f715fab053374d808c90dSteve Block // For break and trap instructions. 193944f0eee88ff00398ff7f715fab053374d808c90dSteve Block bool do_interrupt = false; 194044f0eee88ff00398ff7f715fab053374d808c90dSteve Block 1941257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // For jr and jalr. 194244f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Get current pc. 194344f0eee88ff00398ff7f715fab053374d808c90dSteve Block int32_t current_pc = get_pc(); 194444f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Next pc 194544f0eee88ff00398ff7f715fab053374d808c90dSteve Block int32_t next_pc = 0; 194644f0eee88ff00398ff7f715fab053374d808c90dSteve Block 19473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Set up the variables if needed before executing the instruction. 194844f0eee88ff00398ff7f715fab053374d808c90dSteve Block ConfigureTypeRegister(instr, 194944f0eee88ff00398ff7f715fab053374d808c90dSteve Block alu_out, 195044f0eee88ff00398ff7f715fab053374d808c90dSteve Block i64hilo, 195144f0eee88ff00398ff7f715fab053374d808c90dSteve Block u64hilo, 195244f0eee88ff00398ff7f715fab053374d808c90dSteve Block next_pc, 195344f0eee88ff00398ff7f715fab053374d808c90dSteve Block do_interrupt); 19543100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 19553100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // ---------- Raise exceptions triggered. 19563100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu SignalExceptions(); 19573100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 1958257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ---------- Execution. 19593100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu switch (op) { 19603100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu case COP1: 19613100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu switch (instr->RsFieldRaw()) { 1962257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch case BC1: // Branch on coprocessor condition. 19633100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu UNREACHABLE(); 19643100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu break; 196544f0eee88ff00398ff7f715fab053374d808c90dSteve Block case CFC1: 196644f0eee88ff00398ff7f715fab053374d808c90dSteve Block set_register(rt_reg, alu_out); 19673100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu case MFC1: 19683100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu set_register(rt_reg, alu_out); 19693100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu break; 197044f0eee88ff00398ff7f715fab053374d808c90dSteve Block case MFHC1: 197144f0eee88ff00398ff7f715fab053374d808c90dSteve Block UNIMPLEMENTED_MIPS(); 197244f0eee88ff00398ff7f715fab053374d808c90dSteve Block break; 197344f0eee88ff00398ff7f715fab053374d808c90dSteve Block case CTC1: 197444f0eee88ff00398ff7f715fab053374d808c90dSteve Block // At the moment only FCSR is supported. 197544f0eee88ff00398ff7f715fab053374d808c90dSteve Block ASSERT(fs_reg == kFCSRRegister); 197644f0eee88ff00398ff7f715fab053374d808c90dSteve Block FCSR_ = registers_[rt_reg]; 197744f0eee88ff00398ff7f715fab053374d808c90dSteve Block break; 19783100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu case MTC1: 19793100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu FPUregisters_[fs_reg] = registers_[rt_reg]; 19803100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu break; 19813100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu case MTHC1: 198244f0eee88ff00398ff7f715fab053374d808c90dSteve Block UNIMPLEMENTED_MIPS(); 19833100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu break; 19843100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu case S: 198544f0eee88ff00398ff7f715fab053374d808c90dSteve Block float f; 19863100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu switch (instr->FunctionFieldRaw()) { 19873100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu case CVT_D_S: 198844f0eee88ff00398ff7f715fab053374d808c90dSteve Block f = get_fpu_register_float(fs_reg); 198944f0eee88ff00398ff7f715fab053374d808c90dSteve Block set_fpu_register_double(fd_reg, static_cast<double>(f)); 199044f0eee88ff00398ff7f715fab053374d808c90dSteve Block break; 19913100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu case CVT_W_S: 19923100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu case CVT_L_S: 199344f0eee88ff00398ff7f715fab053374d808c90dSteve Block case TRUNC_W_S: 199444f0eee88ff00398ff7f715fab053374d808c90dSteve Block case TRUNC_L_S: 199544f0eee88ff00398ff7f715fab053374d808c90dSteve Block case ROUND_W_S: 199644f0eee88ff00398ff7f715fab053374d808c90dSteve Block case ROUND_L_S: 199744f0eee88ff00398ff7f715fab053374d808c90dSteve Block case FLOOR_W_S: 199844f0eee88ff00398ff7f715fab053374d808c90dSteve Block case FLOOR_L_S: 199944f0eee88ff00398ff7f715fab053374d808c90dSteve Block case CEIL_W_S: 200044f0eee88ff00398ff7f715fab053374d808c90dSteve Block case CEIL_L_S: 20013100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu case CVT_PS_S: 20023100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu UNIMPLEMENTED_MIPS(); 20033100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu break; 20043100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu default: 20053100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu UNREACHABLE(); 20063100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu } 20073100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu break; 20083100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu case D: 200944f0eee88ff00398ff7f715fab053374d808c90dSteve Block double ft, fs; 201044f0eee88ff00398ff7f715fab053374d808c90dSteve Block uint32_t cc, fcsr_cc; 201144f0eee88ff00398ff7f715fab053374d808c90dSteve Block int64_t i64; 201244f0eee88ff00398ff7f715fab053374d808c90dSteve Block fs = get_fpu_register_double(fs_reg); 201344f0eee88ff00398ff7f715fab053374d808c90dSteve Block ft = get_fpu_register_double(ft_reg); 201444f0eee88ff00398ff7f715fab053374d808c90dSteve Block cc = instr->FCccValue(); 201544f0eee88ff00398ff7f715fab053374d808c90dSteve Block fcsr_cc = get_fcsr_condition_bit(cc); 20163100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu switch (instr->FunctionFieldRaw()) { 201744f0eee88ff00398ff7f715fab053374d808c90dSteve Block case ADD_D: 201844f0eee88ff00398ff7f715fab053374d808c90dSteve Block set_fpu_register_double(fd_reg, fs + ft); 201944f0eee88ff00398ff7f715fab053374d808c90dSteve Block break; 202044f0eee88ff00398ff7f715fab053374d808c90dSteve Block case SUB_D: 202144f0eee88ff00398ff7f715fab053374d808c90dSteve Block set_fpu_register_double(fd_reg, fs - ft); 202244f0eee88ff00398ff7f715fab053374d808c90dSteve Block break; 202344f0eee88ff00398ff7f715fab053374d808c90dSteve Block case MUL_D: 202444f0eee88ff00398ff7f715fab053374d808c90dSteve Block set_fpu_register_double(fd_reg, fs * ft); 202544f0eee88ff00398ff7f715fab053374d808c90dSteve Block break; 202644f0eee88ff00398ff7f715fab053374d808c90dSteve Block case DIV_D: 202744f0eee88ff00398ff7f715fab053374d808c90dSteve Block set_fpu_register_double(fd_reg, fs / ft); 202844f0eee88ff00398ff7f715fab053374d808c90dSteve Block break; 202944f0eee88ff00398ff7f715fab053374d808c90dSteve Block case ABS_D: 203044f0eee88ff00398ff7f715fab053374d808c90dSteve Block set_fpu_register_double(fd_reg, fs < 0 ? -fs : fs); 203144f0eee88ff00398ff7f715fab053374d808c90dSteve Block break; 203244f0eee88ff00398ff7f715fab053374d808c90dSteve Block case MOV_D: 203344f0eee88ff00398ff7f715fab053374d808c90dSteve Block set_fpu_register_double(fd_reg, fs); 203444f0eee88ff00398ff7f715fab053374d808c90dSteve Block break; 203544f0eee88ff00398ff7f715fab053374d808c90dSteve Block case NEG_D: 203644f0eee88ff00398ff7f715fab053374d808c90dSteve Block set_fpu_register_double(fd_reg, -fs); 203744f0eee88ff00398ff7f715fab053374d808c90dSteve Block break; 203844f0eee88ff00398ff7f715fab053374d808c90dSteve Block case SQRT_D: 203944f0eee88ff00398ff7f715fab053374d808c90dSteve Block set_fpu_register_double(fd_reg, sqrt(fs)); 204044f0eee88ff00398ff7f715fab053374d808c90dSteve Block break; 204144f0eee88ff00398ff7f715fab053374d808c90dSteve Block case C_UN_D: 204244f0eee88ff00398ff7f715fab053374d808c90dSteve Block set_fcsr_bit(fcsr_cc, isnan(fs) || isnan(ft)); 204344f0eee88ff00398ff7f715fab053374d808c90dSteve Block break; 204444f0eee88ff00398ff7f715fab053374d808c90dSteve Block case C_EQ_D: 204544f0eee88ff00398ff7f715fab053374d808c90dSteve Block set_fcsr_bit(fcsr_cc, (fs == ft)); 204644f0eee88ff00398ff7f715fab053374d808c90dSteve Block break; 204744f0eee88ff00398ff7f715fab053374d808c90dSteve Block case C_UEQ_D: 204844f0eee88ff00398ff7f715fab053374d808c90dSteve Block set_fcsr_bit(fcsr_cc, (fs == ft) || (isnan(fs) || isnan(ft))); 204944f0eee88ff00398ff7f715fab053374d808c90dSteve Block break; 205044f0eee88ff00398ff7f715fab053374d808c90dSteve Block case C_OLT_D: 205144f0eee88ff00398ff7f715fab053374d808c90dSteve Block set_fcsr_bit(fcsr_cc, (fs < ft)); 205244f0eee88ff00398ff7f715fab053374d808c90dSteve Block break; 205344f0eee88ff00398ff7f715fab053374d808c90dSteve Block case C_ULT_D: 205444f0eee88ff00398ff7f715fab053374d808c90dSteve Block set_fcsr_bit(fcsr_cc, (fs < ft) || (isnan(fs) || isnan(ft))); 205544f0eee88ff00398ff7f715fab053374d808c90dSteve Block break; 205644f0eee88ff00398ff7f715fab053374d808c90dSteve Block case C_OLE_D: 205744f0eee88ff00398ff7f715fab053374d808c90dSteve Block set_fcsr_bit(fcsr_cc, (fs <= ft)); 205844f0eee88ff00398ff7f715fab053374d808c90dSteve Block break; 205944f0eee88ff00398ff7f715fab053374d808c90dSteve Block case C_ULE_D: 206044f0eee88ff00398ff7f715fab053374d808c90dSteve Block set_fcsr_bit(fcsr_cc, (fs <= ft) || (isnan(fs) || isnan(ft))); 206144f0eee88ff00398ff7f715fab053374d808c90dSteve Block break; 206244f0eee88ff00398ff7f715fab053374d808c90dSteve Block case CVT_W_D: // Convert double to word. 206344f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Rounding modes are not yet supported. 206444f0eee88ff00398ff7f715fab053374d808c90dSteve Block ASSERT((FCSR_ & 3) == 0); 206544f0eee88ff00398ff7f715fab053374d808c90dSteve Block // In rounding mode 0 it should behave like ROUND. 206644f0eee88ff00398ff7f715fab053374d808c90dSteve Block case ROUND_W_D: // Round double to word. 206744f0eee88ff00398ff7f715fab053374d808c90dSteve Block { 206844f0eee88ff00398ff7f715fab053374d808c90dSteve Block double rounded = fs > 0 ? floor(fs + 0.5) : ceil(fs - 0.5); 206944f0eee88ff00398ff7f715fab053374d808c90dSteve Block int32_t result = static_cast<int32_t>(rounded); 207044f0eee88ff00398ff7f715fab053374d808c90dSteve Block set_fpu_register(fd_reg, result); 207144f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (set_fcsr_round_error(fs, rounded)) { 207244f0eee88ff00398ff7f715fab053374d808c90dSteve Block set_fpu_register(fd_reg, kFPUInvalidResult); 207344f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 207444f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 207544f0eee88ff00398ff7f715fab053374d808c90dSteve Block break; 207644f0eee88ff00398ff7f715fab053374d808c90dSteve Block case TRUNC_W_D: // Truncate double to word (round towards 0). 207744f0eee88ff00398ff7f715fab053374d808c90dSteve Block { 20783fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch double rounded = trunc(fs); 20793fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch int32_t result = static_cast<int32_t>(rounded); 208044f0eee88ff00398ff7f715fab053374d808c90dSteve Block set_fpu_register(fd_reg, result); 20813fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch if (set_fcsr_round_error(fs, rounded)) { 208244f0eee88ff00398ff7f715fab053374d808c90dSteve Block set_fpu_register(fd_reg, kFPUInvalidResult); 208344f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 208444f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 208544f0eee88ff00398ff7f715fab053374d808c90dSteve Block break; 208644f0eee88ff00398ff7f715fab053374d808c90dSteve Block case FLOOR_W_D: // Round double to word towards negative infinity. 208744f0eee88ff00398ff7f715fab053374d808c90dSteve Block { 208844f0eee88ff00398ff7f715fab053374d808c90dSteve Block double rounded = floor(fs); 208944f0eee88ff00398ff7f715fab053374d808c90dSteve Block int32_t result = static_cast<int32_t>(rounded); 209044f0eee88ff00398ff7f715fab053374d808c90dSteve Block set_fpu_register(fd_reg, result); 209144f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (set_fcsr_round_error(fs, rounded)) { 209244f0eee88ff00398ff7f715fab053374d808c90dSteve Block set_fpu_register(fd_reg, kFPUInvalidResult); 209344f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 209444f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 209544f0eee88ff00398ff7f715fab053374d808c90dSteve Block break; 209644f0eee88ff00398ff7f715fab053374d808c90dSteve Block case CEIL_W_D: // Round double to word towards positive infinity. 209744f0eee88ff00398ff7f715fab053374d808c90dSteve Block { 209844f0eee88ff00398ff7f715fab053374d808c90dSteve Block double rounded = ceil(fs); 209944f0eee88ff00398ff7f715fab053374d808c90dSteve Block int32_t result = static_cast<int32_t>(rounded); 210044f0eee88ff00398ff7f715fab053374d808c90dSteve Block set_fpu_register(fd_reg, result); 210144f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (set_fcsr_round_error(fs, rounded)) { 210244f0eee88ff00398ff7f715fab053374d808c90dSteve Block set_fpu_register(fd_reg, kFPUInvalidResult); 210344f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 210444f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 210544f0eee88ff00398ff7f715fab053374d808c90dSteve Block break; 210644f0eee88ff00398ff7f715fab053374d808c90dSteve Block case CVT_S_D: // Convert double to float (single). 210744f0eee88ff00398ff7f715fab053374d808c90dSteve Block set_fpu_register_float(fd_reg, static_cast<float>(fs)); 210844f0eee88ff00398ff7f715fab053374d808c90dSteve Block break; 21093fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch case CVT_L_D: { // Mips32r2: Truncate double to 64-bit long-word. 21103fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch double rounded = trunc(fs); 21113fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch i64 = static_cast<int64_t>(rounded); 211244f0eee88ff00398ff7f715fab053374d808c90dSteve Block set_fpu_register(fd_reg, i64 & 0xffffffff); 211344f0eee88ff00398ff7f715fab053374d808c90dSteve Block set_fpu_register(fd_reg + 1, i64 >> 32); 211444f0eee88ff00398ff7f715fab053374d808c90dSteve Block break; 21153fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 21163fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch case TRUNC_L_D: { // Mips32r2 instruction. 21173fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch double rounded = trunc(fs); 21183fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch i64 = static_cast<int64_t>(rounded); 211944f0eee88ff00398ff7f715fab053374d808c90dSteve Block set_fpu_register(fd_reg, i64 & 0xffffffff); 212044f0eee88ff00398ff7f715fab053374d808c90dSteve Block set_fpu_register(fd_reg + 1, i64 >> 32); 212144f0eee88ff00398ff7f715fab053374d808c90dSteve Block break; 21223fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 212344f0eee88ff00398ff7f715fab053374d808c90dSteve Block case ROUND_L_D: { // Mips32r2 instruction. 212444f0eee88ff00398ff7f715fab053374d808c90dSteve Block double rounded = fs > 0 ? floor(fs + 0.5) : ceil(fs - 0.5); 212544f0eee88ff00398ff7f715fab053374d808c90dSteve Block i64 = static_cast<int64_t>(rounded); 212644f0eee88ff00398ff7f715fab053374d808c90dSteve Block set_fpu_register(fd_reg, i64 & 0xffffffff); 212744f0eee88ff00398ff7f715fab053374d808c90dSteve Block set_fpu_register(fd_reg + 1, i64 >> 32); 212844f0eee88ff00398ff7f715fab053374d808c90dSteve Block break; 212944f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 213044f0eee88ff00398ff7f715fab053374d808c90dSteve Block case FLOOR_L_D: // Mips32r2 instruction. 213144f0eee88ff00398ff7f715fab053374d808c90dSteve Block i64 = static_cast<int64_t>(floor(fs)); 213244f0eee88ff00398ff7f715fab053374d808c90dSteve Block set_fpu_register(fd_reg, i64 & 0xffffffff); 213344f0eee88ff00398ff7f715fab053374d808c90dSteve Block set_fpu_register(fd_reg + 1, i64 >> 32); 213444f0eee88ff00398ff7f715fab053374d808c90dSteve Block break; 213544f0eee88ff00398ff7f715fab053374d808c90dSteve Block case CEIL_L_D: // Mips32r2 instruction. 213644f0eee88ff00398ff7f715fab053374d808c90dSteve Block i64 = static_cast<int64_t>(ceil(fs)); 213744f0eee88ff00398ff7f715fab053374d808c90dSteve Block set_fpu_register(fd_reg, i64 & 0xffffffff); 213844f0eee88ff00398ff7f715fab053374d808c90dSteve Block set_fpu_register(fd_reg + 1, i64 >> 32); 213944f0eee88ff00398ff7f715fab053374d808c90dSteve Block break; 214044f0eee88ff00398ff7f715fab053374d808c90dSteve Block case C_F_D: 21413100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu UNIMPLEMENTED_MIPS(); 21423100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu break; 21433100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu default: 21443100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu UNREACHABLE(); 21453100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu } 21463100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu break; 21473100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu case W: 21483100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu switch (instr->FunctionFieldRaw()) { 214944f0eee88ff00398ff7f715fab053374d808c90dSteve Block case CVT_S_W: // Convert word to float (single). 215044f0eee88ff00398ff7f715fab053374d808c90dSteve Block alu_out = get_fpu_register(fs_reg); 215144f0eee88ff00398ff7f715fab053374d808c90dSteve Block set_fpu_register_float(fd_reg, static_cast<float>(alu_out)); 21523100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu break; 21533100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu case CVT_D_W: // Convert word to double. 215444f0eee88ff00398ff7f715fab053374d808c90dSteve Block alu_out = get_fpu_register(fs_reg); 215544f0eee88ff00398ff7f715fab053374d808c90dSteve Block set_fpu_register_double(fd_reg, static_cast<double>(alu_out)); 21563100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu break; 21573100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu default: 21583100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu UNREACHABLE(); 21593100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu }; 21603100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu break; 21613100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu case L: 21623100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu switch (instr->FunctionFieldRaw()) { 216344f0eee88ff00398ff7f715fab053374d808c90dSteve Block case CVT_D_L: // Mips32r2 instruction. 216444f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Watch the signs here, we want 2 32-bit vals 216544f0eee88ff00398ff7f715fab053374d808c90dSteve Block // to make a sign-64. 216644f0eee88ff00398ff7f715fab053374d808c90dSteve Block i64 = (uint32_t) get_fpu_register(fs_reg); 216744f0eee88ff00398ff7f715fab053374d808c90dSteve Block i64 |= ((int64_t) get_fpu_register(fs_reg + 1) << 32); 216844f0eee88ff00398ff7f715fab053374d808c90dSteve Block set_fpu_register_double(fd_reg, static_cast<double>(i64)); 216944f0eee88ff00398ff7f715fab053374d808c90dSteve Block break; 21703100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu case CVT_S_L: 21713100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu UNIMPLEMENTED_MIPS(); 21723100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu break; 21733100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu default: 21743100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu UNREACHABLE(); 21753100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu } 21763100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu break; 21773100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu case PS: 21783100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu break; 21793100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu default: 21803100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu UNREACHABLE(); 21813100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu }; 21823100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu break; 21833100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu case SPECIAL: 21843100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu switch (instr->FunctionFieldRaw()) { 21853100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu case JR: { 21863100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu Instruction* branch_delay_instr = reinterpret_cast<Instruction*>( 218744f0eee88ff00398ff7f715fab053374d808c90dSteve Block current_pc+Instruction::kInstrSize); 21883100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu BranchDelayInstructionDecode(branch_delay_instr); 21893100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu set_pc(next_pc); 21903100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu pc_modified_ = true; 21913100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu break; 21923100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu } 21933100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu case JALR: { 21943100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu Instruction* branch_delay_instr = reinterpret_cast<Instruction*>( 219544f0eee88ff00398ff7f715fab053374d808c90dSteve Block current_pc+Instruction::kInstrSize); 21963100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu BranchDelayInstructionDecode(branch_delay_instr); 2197257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch set_register(31, current_pc + 2 * Instruction::kInstrSize); 21983100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu set_pc(next_pc); 21993100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu pc_modified_ = true; 22003100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu break; 22013100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu } 22023100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // Instructions using HI and LO registers. 22033100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu case MULT: 220444f0eee88ff00398ff7f715fab053374d808c90dSteve Block set_register(LO, static_cast<int32_t>(i64hilo & 0xffffffff)); 220544f0eee88ff00398ff7f715fab053374d808c90dSteve Block set_register(HI, static_cast<int32_t>(i64hilo >> 32)); 220644f0eee88ff00398ff7f715fab053374d808c90dSteve Block break; 22073100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu case MULTU: 220844f0eee88ff00398ff7f715fab053374d808c90dSteve Block set_register(LO, static_cast<int32_t>(u64hilo & 0xffffffff)); 220944f0eee88ff00398ff7f715fab053374d808c90dSteve Block set_register(HI, static_cast<int32_t>(u64hilo >> 32)); 22103100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu break; 22113100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu case DIV: 2212257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Divide by zero was not checked in the configuration step - div and 2213257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // divu do not raise exceptions. On division by 0, the result will 2214257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // be UNPREDICTABLE. 2215257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (rt != 0) { 2216257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch set_register(LO, rs / rt); 2217257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch set_register(HI, rs % rt); 2218257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 22193100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu break; 22203100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu case DIVU: 2221257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (rt_u != 0) { 2222257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch set_register(LO, rs_u / rt_u); 2223257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch set_register(HI, rs_u % rt_u); 2224257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 22253100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu break; 222644f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Break and trap instructions. 22273100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu case BREAK: 22283100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu case TGE: 22293100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu case TGEU: 22303100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu case TLT: 22313100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu case TLTU: 22323100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu case TEQ: 22333100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu case TNE: 22343100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu if (do_interrupt) { 22353100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu SoftwareInterrupt(instr); 22363100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu } 22373100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu break; 223844f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Conditional moves. 223944f0eee88ff00398ff7f715fab053374d808c90dSteve Block case MOVN: 224044f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (rt) set_register(rd_reg, rs); 224144f0eee88ff00398ff7f715fab053374d808c90dSteve Block break; 224244f0eee88ff00398ff7f715fab053374d808c90dSteve Block case MOVCI: { 2243257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch uint32_t cc = instr->FBccValue(); 224444f0eee88ff00398ff7f715fab053374d808c90dSteve Block uint32_t fcsr_cc = get_fcsr_condition_bit(cc); 2245257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (instr->Bit(16)) { // Read Tf bit. 224644f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (test_fcsr_bit(fcsr_cc)) set_register(rd_reg, rs); 224744f0eee88ff00398ff7f715fab053374d808c90dSteve Block } else { 224844f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (!test_fcsr_bit(fcsr_cc)) set_register(rd_reg, rs); 224944f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 225044f0eee88ff00398ff7f715fab053374d808c90dSteve Block break; 225144f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 225244f0eee88ff00398ff7f715fab053374d808c90dSteve Block case MOVZ: 225344f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (!rt) set_register(rd_reg, rs); 225444f0eee88ff00398ff7f715fab053374d808c90dSteve Block break; 22553100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu default: // For other special opcodes we do the default operation. 22563100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu set_register(rd_reg, alu_out); 22573100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu }; 22583100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu break; 22593100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu case SPECIAL2: 22603100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu switch (instr->FunctionFieldRaw()) { 22613100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu case MUL: 22623100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu set_register(rd_reg, alu_out); 22633100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // HI and LO are UNPREDICTABLE after the operation. 22643100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu set_register(LO, Unpredictable); 22653100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu set_register(HI, Unpredictable); 22663100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu break; 226744f0eee88ff00398ff7f715fab053374d808c90dSteve Block default: // For other special2 opcodes we do the default operation. 226844f0eee88ff00398ff7f715fab053374d808c90dSteve Block set_register(rd_reg, alu_out); 226944f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 227044f0eee88ff00398ff7f715fab053374d808c90dSteve Block break; 227144f0eee88ff00398ff7f715fab053374d808c90dSteve Block case SPECIAL3: 227244f0eee88ff00398ff7f715fab053374d808c90dSteve Block switch (instr->FunctionFieldRaw()) { 227344f0eee88ff00398ff7f715fab053374d808c90dSteve Block case INS: 227444f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Ins instr leaves result in Rt, rather than Rd. 227544f0eee88ff00398ff7f715fab053374d808c90dSteve Block set_register(rt_reg, alu_out); 227644f0eee88ff00398ff7f715fab053374d808c90dSteve Block break; 227744f0eee88ff00398ff7f715fab053374d808c90dSteve Block case EXT: 227844f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Ext instr leaves result in Rt, rather than Rd. 227944f0eee88ff00398ff7f715fab053374d808c90dSteve Block set_register(rt_reg, alu_out); 228044f0eee88ff00398ff7f715fab053374d808c90dSteve Block break; 22813100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu default: 22823100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu UNREACHABLE(); 228344f0eee88ff00398ff7f715fab053374d808c90dSteve Block }; 22843100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu break; 22853100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // Unimplemented opcodes raised an error in the configuration step before, 22863100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // so we can use the default here to set the destination register in common 22873100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // cases. 22883100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu default: 22893100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu set_register(rd_reg, alu_out); 22903100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu }; 22913100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} 22923100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 229344f0eee88ff00398ff7f715fab053374d808c90dSteve Block 22943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// Type 2: instructions using a 16 bytes immediate. (e.g. addi, beq). 22953100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Simulator::DecodeTypeImmediate(Instruction* instr) { 229644f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Instruction fields. 22973100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu Opcode op = instr->OpcodeFieldRaw(); 229844f0eee88ff00398ff7f715fab053374d808c90dSteve Block int32_t rs = get_register(instr->RsValue()); 22993100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu uint32_t rs_u = static_cast<uint32_t>(rs); 2300257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch int32_t rt_reg = instr->RtValue(); // Destination register. 23013100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu int32_t rt = get_register(rt_reg); 230244f0eee88ff00398ff7f715fab053374d808c90dSteve Block int16_t imm16 = instr->Imm16Value(); 23033100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 2304257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch int32_t ft_reg = instr->FtValue(); // Destination register. 23053100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 230644f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Zero extended immediate. 23073100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu uint32_t oe_imm16 = 0xffff & imm16; 230844f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Sign extended immediate. 23093100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu int32_t se_imm16 = imm16; 23103100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 23113100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // Get current pc. 23123100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu int32_t current_pc = get_pc(); 23133100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // Next pc. 23143100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu int32_t next_pc = bad_ra; 23153100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 231644f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Used for conditional branch instructions. 23173100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu bool do_branch = false; 23183100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu bool execute_branch_delay_instruction = false; 23193100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 232044f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Used for arithmetic instructions. 23213100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu int32_t alu_out = 0; 232244f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Floating point. 23233100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu double fp_out = 0.0; 232444f0eee88ff00398ff7f715fab053374d808c90dSteve Block uint32_t cc, cc_value, fcsr_cc; 23253100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 232644f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Used for memory instructions. 23273100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu int32_t addr = 0x0; 2328257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Value to be written in memory. 232944f0eee88ff00398ff7f715fab053374d808c90dSteve Block uint32_t mem_value = 0x0; 23303100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 2331257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ---------- Configuration (and execution for REGIMM). 23323100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu switch (op) { 233344f0eee88ff00398ff7f715fab053374d808c90dSteve Block // ------------- COP1. Coprocessor instructions. 23343100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu case COP1: 23353100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu switch (instr->RsFieldRaw()) { 233644f0eee88ff00398ff7f715fab053374d808c90dSteve Block case BC1: // Branch on coprocessor condition. 233744f0eee88ff00398ff7f715fab053374d808c90dSteve Block cc = instr->FBccValue(); 233844f0eee88ff00398ff7f715fab053374d808c90dSteve Block fcsr_cc = get_fcsr_condition_bit(cc); 233944f0eee88ff00398ff7f715fab053374d808c90dSteve Block cc_value = test_fcsr_bit(fcsr_cc); 234044f0eee88ff00398ff7f715fab053374d808c90dSteve Block do_branch = (instr->FBtrueValue()) ? cc_value : !cc_value; 234144f0eee88ff00398ff7f715fab053374d808c90dSteve Block execute_branch_delay_instruction = true; 2342257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Set next_pc. 234344f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (do_branch) { 234444f0eee88ff00398ff7f715fab053374d808c90dSteve Block next_pc = current_pc + (imm16 << 2) + Instruction::kInstrSize; 234544f0eee88ff00398ff7f715fab053374d808c90dSteve Block } else { 234644f0eee88ff00398ff7f715fab053374d808c90dSteve Block next_pc = current_pc + kBranchReturnOffset; 234744f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 23483100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu break; 23493100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu default: 23503100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu UNREACHABLE(); 23513100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu }; 23523100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu break; 2353257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ------------- REGIMM class. 23543100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu case REGIMM: 23553100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu switch (instr->RtFieldRaw()) { 23563100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu case BLTZ: 23573100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu do_branch = (rs < 0); 23583100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu break; 23593100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu case BLTZAL: 23603100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu do_branch = rs < 0; 23613100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu break; 23623100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu case BGEZ: 23633100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu do_branch = rs >= 0; 23643100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu break; 23653100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu case BGEZAL: 23663100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu do_branch = rs >= 0; 23673100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu break; 23683100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu default: 23693100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu UNREACHABLE(); 23703100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu }; 23713100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu switch (instr->RtFieldRaw()) { 23723100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu case BLTZ: 23733100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu case BLTZAL: 23743100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu case BGEZ: 23753100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu case BGEZAL: 23763100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // Branch instructions common part. 23773100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu execute_branch_delay_instruction = true; 2378257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Set next_pc. 23793100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu if (do_branch) { 238044f0eee88ff00398ff7f715fab053374d808c90dSteve Block next_pc = current_pc + (imm16 << 2) + Instruction::kInstrSize; 23813100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu if (instr->IsLinkingInstruction()) { 23823100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu set_register(31, current_pc + kBranchReturnOffset); 23833100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu } 23843100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu } else { 23853100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu next_pc = current_pc + kBranchReturnOffset; 23863100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu } 23873100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu default: 23883100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu break; 23893100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu }; 2390257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch break; // case REGIMM. 2391257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ------------- Branch instructions. 23923100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // When comparing to zero, the encoding of rt field is always 0, so we don't 23933100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // need to replace rt with zero. 23943100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu case BEQ: 23953100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu do_branch = (rs == rt); 23963100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu break; 23973100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu case BNE: 23983100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu do_branch = rs != rt; 23993100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu break; 24003100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu case BLEZ: 24013100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu do_branch = rs <= 0; 24023100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu break; 24033100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu case BGTZ: 24043100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu do_branch = rs > 0; 24053100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu break; 2406257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ------------- Arithmetic instructions. 24073100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu case ADDI: 24083100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu if (HaveSameSign(rs, se_imm16)) { 24093100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu if (rs > 0) { 24103100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu exceptions[kIntegerOverflow] = rs > (Registers::kMaxValue - se_imm16); 24113100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu } else if (rs < 0) { 24123100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu exceptions[kIntegerUnderflow] = 24133100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu rs < (Registers::kMinValue - se_imm16); 24143100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu } 24153100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu } 24163100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu alu_out = rs + se_imm16; 24173100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu break; 24183100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu case ADDIU: 24193100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu alu_out = rs + se_imm16; 24203100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu break; 24213100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu case SLTI: 24223100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu alu_out = (rs < se_imm16) ? 1 : 0; 24233100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu break; 24243100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu case SLTIU: 24253100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu alu_out = (rs_u < static_cast<uint32_t>(se_imm16)) ? 1 : 0; 24263100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu break; 24273100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu case ANDI: 24283100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu alu_out = rs & oe_imm16; 24293100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu break; 24303100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu case ORI: 24313100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu alu_out = rs | oe_imm16; 24323100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu break; 24333100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu case XORI: 24343100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu alu_out = rs ^ oe_imm16; 24353100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu break; 24363100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu case LUI: 24373100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu alu_out = (oe_imm16 << 16); 24383100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu break; 2439257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ------------- Memory instructions. 24403100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu case LB: 24413100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu addr = rs + se_imm16; 24423100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu alu_out = ReadB(addr); 24433100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu break; 244444f0eee88ff00398ff7f715fab053374d808c90dSteve Block case LH: 244544f0eee88ff00398ff7f715fab053374d808c90dSteve Block addr = rs + se_imm16; 244644f0eee88ff00398ff7f715fab053374d808c90dSteve Block alu_out = ReadH(addr, instr); 244744f0eee88ff00398ff7f715fab053374d808c90dSteve Block break; 244844f0eee88ff00398ff7f715fab053374d808c90dSteve Block case LWL: { 2449257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // al_offset is offset of the effective address within an aligned word. 245044f0eee88ff00398ff7f715fab053374d808c90dSteve Block uint8_t al_offset = (rs + se_imm16) & kPointerAlignmentMask; 245144f0eee88ff00398ff7f715fab053374d808c90dSteve Block uint8_t byte_shift = kPointerAlignmentMask - al_offset; 245244f0eee88ff00398ff7f715fab053374d808c90dSteve Block uint32_t mask = (1 << byte_shift * 8) - 1; 245344f0eee88ff00398ff7f715fab053374d808c90dSteve Block addr = rs + se_imm16 - al_offset; 245444f0eee88ff00398ff7f715fab053374d808c90dSteve Block alu_out = ReadW(addr, instr); 245544f0eee88ff00398ff7f715fab053374d808c90dSteve Block alu_out <<= byte_shift * 8; 245644f0eee88ff00398ff7f715fab053374d808c90dSteve Block alu_out |= rt & mask; 245744f0eee88ff00398ff7f715fab053374d808c90dSteve Block break; 245844f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 24593100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu case LW: 24603100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu addr = rs + se_imm16; 24613100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu alu_out = ReadW(addr, instr); 24623100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu break; 24633100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu case LBU: 24643100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu addr = rs + se_imm16; 24653100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu alu_out = ReadBU(addr); 24663100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu break; 246744f0eee88ff00398ff7f715fab053374d808c90dSteve Block case LHU: 246844f0eee88ff00398ff7f715fab053374d808c90dSteve Block addr = rs + se_imm16; 246944f0eee88ff00398ff7f715fab053374d808c90dSteve Block alu_out = ReadHU(addr, instr); 247044f0eee88ff00398ff7f715fab053374d808c90dSteve Block break; 247144f0eee88ff00398ff7f715fab053374d808c90dSteve Block case LWR: { 2472257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // al_offset is offset of the effective address within an aligned word. 247344f0eee88ff00398ff7f715fab053374d808c90dSteve Block uint8_t al_offset = (rs + se_imm16) & kPointerAlignmentMask; 247444f0eee88ff00398ff7f715fab053374d808c90dSteve Block uint8_t byte_shift = kPointerAlignmentMask - al_offset; 247544f0eee88ff00398ff7f715fab053374d808c90dSteve Block uint32_t mask = al_offset ? (~0 << (byte_shift + 1) * 8) : 0; 247644f0eee88ff00398ff7f715fab053374d808c90dSteve Block addr = rs + se_imm16 - al_offset; 247744f0eee88ff00398ff7f715fab053374d808c90dSteve Block alu_out = ReadW(addr, instr); 247844f0eee88ff00398ff7f715fab053374d808c90dSteve Block alu_out = static_cast<uint32_t> (alu_out) >> al_offset * 8; 247944f0eee88ff00398ff7f715fab053374d808c90dSteve Block alu_out |= rt & mask; 248044f0eee88ff00398ff7f715fab053374d808c90dSteve Block break; 248144f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 24823100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu case SB: 24833100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu addr = rs + se_imm16; 24843100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu break; 248544f0eee88ff00398ff7f715fab053374d808c90dSteve Block case SH: 248644f0eee88ff00398ff7f715fab053374d808c90dSteve Block addr = rs + se_imm16; 248744f0eee88ff00398ff7f715fab053374d808c90dSteve Block break; 248844f0eee88ff00398ff7f715fab053374d808c90dSteve Block case SWL: { 248944f0eee88ff00398ff7f715fab053374d808c90dSteve Block uint8_t al_offset = (rs + se_imm16) & kPointerAlignmentMask; 249044f0eee88ff00398ff7f715fab053374d808c90dSteve Block uint8_t byte_shift = kPointerAlignmentMask - al_offset; 249144f0eee88ff00398ff7f715fab053374d808c90dSteve Block uint32_t mask = byte_shift ? (~0 << (al_offset + 1) * 8) : 0; 249244f0eee88ff00398ff7f715fab053374d808c90dSteve Block addr = rs + se_imm16 - al_offset; 249344f0eee88ff00398ff7f715fab053374d808c90dSteve Block mem_value = ReadW(addr, instr) & mask; 249444f0eee88ff00398ff7f715fab053374d808c90dSteve Block mem_value |= static_cast<uint32_t>(rt) >> byte_shift * 8; 249544f0eee88ff00398ff7f715fab053374d808c90dSteve Block break; 249644f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 24973100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu case SW: 24983100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu addr = rs + se_imm16; 24993100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu break; 250044f0eee88ff00398ff7f715fab053374d808c90dSteve Block case SWR: { 250144f0eee88ff00398ff7f715fab053374d808c90dSteve Block uint8_t al_offset = (rs + se_imm16) & kPointerAlignmentMask; 250244f0eee88ff00398ff7f715fab053374d808c90dSteve Block uint32_t mask = (1 << al_offset * 8) - 1; 250344f0eee88ff00398ff7f715fab053374d808c90dSteve Block addr = rs + se_imm16 - al_offset; 250444f0eee88ff00398ff7f715fab053374d808c90dSteve Block mem_value = ReadW(addr, instr); 250544f0eee88ff00398ff7f715fab053374d808c90dSteve Block mem_value = (rt << al_offset * 8) | (mem_value & mask); 250644f0eee88ff00398ff7f715fab053374d808c90dSteve Block break; 250744f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 25083100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu case LWC1: 25093100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu addr = rs + se_imm16; 25103100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu alu_out = ReadW(addr, instr); 25113100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu break; 25123100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu case LDC1: 25133100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu addr = rs + se_imm16; 25143100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu fp_out = ReadD(addr, instr); 25153100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu break; 25163100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu case SWC1: 25173100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu case SDC1: 25183100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu addr = rs + se_imm16; 25193100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu break; 25203100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu default: 25213100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu UNREACHABLE(); 25223100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu }; 25233100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 25243100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // ---------- Raise exceptions triggered. 25253100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu SignalExceptions(); 25263100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 2527257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ---------- Execution. 25283100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu switch (op) { 2529257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ------------- Branch instructions. 25303100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu case BEQ: 25313100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu case BNE: 25323100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu case BLEZ: 25333100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu case BGTZ: 25343100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // Branch instructions common part. 25353100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu execute_branch_delay_instruction = true; 2536257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Set next_pc. 25373100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu if (do_branch) { 253844f0eee88ff00398ff7f715fab053374d808c90dSteve Block next_pc = current_pc + (imm16 << 2) + Instruction::kInstrSize; 25393100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu if (instr->IsLinkingInstruction()) { 254044f0eee88ff00398ff7f715fab053374d808c90dSteve Block set_register(31, current_pc + 2* Instruction::kInstrSize); 25413100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu } 25423100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu } else { 254344f0eee88ff00398ff7f715fab053374d808c90dSteve Block next_pc = current_pc + 2 * Instruction::kInstrSize; 25443100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu } 25453100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu break; 2546257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ------------- Arithmetic instructions. 25473100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu case ADDI: 25483100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu case ADDIU: 25493100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu case SLTI: 25503100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu case SLTIU: 25513100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu case ANDI: 25523100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu case ORI: 25533100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu case XORI: 25543100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu case LUI: 25553100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu set_register(rt_reg, alu_out); 25563100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu break; 2557257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ------------- Memory instructions. 25583100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu case LB: 255944f0eee88ff00398ff7f715fab053374d808c90dSteve Block case LH: 256044f0eee88ff00398ff7f715fab053374d808c90dSteve Block case LWL: 25613100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu case LW: 25623100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu case LBU: 256344f0eee88ff00398ff7f715fab053374d808c90dSteve Block case LHU: 256444f0eee88ff00398ff7f715fab053374d808c90dSteve Block case LWR: 25653100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu set_register(rt_reg, alu_out); 25663100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu break; 25673100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu case SB: 25683100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu WriteB(addr, static_cast<int8_t>(rt)); 25693100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu break; 257044f0eee88ff00398ff7f715fab053374d808c90dSteve Block case SH: 257144f0eee88ff00398ff7f715fab053374d808c90dSteve Block WriteH(addr, static_cast<uint16_t>(rt), instr); 257244f0eee88ff00398ff7f715fab053374d808c90dSteve Block break; 257344f0eee88ff00398ff7f715fab053374d808c90dSteve Block case SWL: 257444f0eee88ff00398ff7f715fab053374d808c90dSteve Block WriteW(addr, mem_value, instr); 257544f0eee88ff00398ff7f715fab053374d808c90dSteve Block break; 25763100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu case SW: 25773100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu WriteW(addr, rt, instr); 25783100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu break; 257944f0eee88ff00398ff7f715fab053374d808c90dSteve Block case SWR: 258044f0eee88ff00398ff7f715fab053374d808c90dSteve Block WriteW(addr, mem_value, instr); 258144f0eee88ff00398ff7f715fab053374d808c90dSteve Block break; 25823100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu case LWC1: 25833100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu set_fpu_register(ft_reg, alu_out); 25843100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu break; 25853100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu case LDC1: 25863100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu set_fpu_register_double(ft_reg, fp_out); 25873100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu break; 25883100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu case SWC1: 25893100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu addr = rs + se_imm16; 25903100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu WriteW(addr, get_fpu_register(ft_reg), instr); 25913100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu break; 25923100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu case SDC1: 25933100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu addr = rs + se_imm16; 259444f0eee88ff00398ff7f715fab053374d808c90dSteve Block WriteD(addr, get_fpu_register_double(ft_reg), instr); 25953100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu break; 25963100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu default: 25973100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu break; 25983100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu }; 25993100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 26003100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 26013100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu if (execute_branch_delay_instruction) { 26023100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // Execute branch delay slot 26033100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // We don't check for end_sim_pc. First it should not be met as the current 26043100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // pc is valid. Secondly a jump should always execute its branch delay slot. 26053100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu Instruction* branch_delay_instr = 260644f0eee88ff00398ff7f715fab053374d808c90dSteve Block reinterpret_cast<Instruction*>(current_pc+Instruction::kInstrSize); 26073100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu BranchDelayInstructionDecode(branch_delay_instr); 26083100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu } 26093100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 26103100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // If needed update pc after the branch delay execution. 26113100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu if (next_pc != bad_ra) { 26123100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu set_pc(next_pc); 26133100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu } 26143100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} 26153100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 261644f0eee88ff00398ff7f715fab053374d808c90dSteve Block 26173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// Type 3: instructions using a 26 bytes immediate. (e.g. j, jal). 26183100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Simulator::DecodeTypeJump(Instruction* instr) { 26193100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // Get current pc. 26203100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu int32_t current_pc = get_pc(); 26213100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // Get unchanged bits of pc. 26223100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu int32_t pc_high_bits = current_pc & 0xf0000000; 2623257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Next pc. 262444f0eee88ff00398ff7f715fab053374d808c90dSteve Block int32_t next_pc = pc_high_bits | (instr->Imm26Value() << 2); 26253100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 2626257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Execute branch delay slot. 26273100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // We don't check for end_sim_pc. First it should not be met as the current pc 26283100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // is valid. Secondly a jump should always execute its branch delay slot. 26293100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu Instruction* branch_delay_instr = 2630257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch reinterpret_cast<Instruction*>(current_pc + Instruction::kInstrSize); 26313100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu BranchDelayInstructionDecode(branch_delay_instr); 26323100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 26333100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // Update pc and ra if necessary. 26343100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // Do this after the branch delay execution. 26353100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu if (instr->IsLinkingInstruction()) { 2636257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch set_register(31, current_pc + 2 * Instruction::kInstrSize); 26373100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu } 26383100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu set_pc(next_pc); 26393100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu pc_modified_ = true; 26403100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} 26413100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 264244f0eee88ff00398ff7f715fab053374d808c90dSteve Block 26433100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// Executes the current instruction. 26443100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Simulator::InstructionDecode(Instruction* instr) { 264544f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (v8::internal::FLAG_check_icache) { 264644f0eee88ff00398ff7f715fab053374d808c90dSteve Block CheckICache(isolate_->simulator_i_cache(), instr); 264744f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 26483100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu pc_modified_ = false; 26493100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu if (::v8::internal::FLAG_trace_sim) { 26503100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu disasm::NameConverter converter; 26513100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu disasm::Disassembler dasm(converter); 2652257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Use a reasonably large buffer. 26533100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu v8::internal::EmbeddedVector<char, 256> buffer; 2654257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch dasm.InstructionDecode(buffer, reinterpret_cast<byte*>(instr)); 265544f0eee88ff00398ff7f715fab053374d808c90dSteve Block PrintF(" 0x%08x %s\n", reinterpret_cast<intptr_t>(instr), 2656257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch buffer.start()); 26573100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu } 26583100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 26593100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu switch (instr->InstructionType()) { 26603100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu case Instruction::kRegisterType: 26613100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu DecodeTypeRegister(instr); 26623100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu break; 26633100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu case Instruction::kImmediateType: 26643100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu DecodeTypeImmediate(instr); 26653100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu break; 26663100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu case Instruction::kJumpType: 26673100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu DecodeTypeJump(instr); 26683100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu break; 26693100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu default: 26703100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu UNSUPPORTED(); 26713100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu } 26723100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu if (!pc_modified_) { 26733100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu set_register(pc, reinterpret_cast<int32_t>(instr) + 267444f0eee88ff00398ff7f715fab053374d808c90dSteve Block Instruction::kInstrSize); 26753100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu } 26763100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} 26773100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 26783100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 26793100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 26803100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Simulator::Execute() { 26813100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // Get the PC to simulate. Cannot use the accessor here as we need the 26823100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // raw PC value and not the one used as input to arithmetic instructions. 26833100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu int program_counter = get_pc(); 26843100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu if (::v8::internal::FLAG_stop_sim_at == 0) { 26853100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // Fast version of the dispatch loop without checking whether the simulator 26863100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // should be stopping at a particular executed instruction. 26873100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu while (program_counter != end_sim_pc) { 26883100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu Instruction* instr = reinterpret_cast<Instruction*>(program_counter); 26893100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu icount_++; 26903100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu InstructionDecode(instr); 26913100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu program_counter = get_pc(); 26923100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu } 26933100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu } else { 26943100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // FLAG_stop_sim_at is at the non-default value. Stop in the debugger when 26953100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // we reach the particular instuction count. 26963100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu while (program_counter != end_sim_pc) { 26973100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu Instruction* instr = reinterpret_cast<Instruction*>(program_counter); 26983100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu icount_++; 26993100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu if (icount_ == ::v8::internal::FLAG_stop_sim_at) { 270044f0eee88ff00398ff7f715fab053374d808c90dSteve Block MipsDebugger dbg(this); 27013100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu dbg.Debug(); 27023100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu } else { 27033100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu InstructionDecode(instr); 27043100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu } 27053100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu program_counter = get_pc(); 27063100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu } 27073100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu } 27083100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} 27093100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 27103100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 2711257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochint32_t Simulator::Call(byte* entry, int argument_count, ...) { 27123100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu va_list parameters; 27133100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu va_start(parameters, argument_count); 27143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Set up arguments. 27153100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 27163100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // First four arguments passed in registers. 27173100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu ASSERT(argument_count >= 4); 27183100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu set_register(a0, va_arg(parameters, int32_t)); 27193100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu set_register(a1, va_arg(parameters, int32_t)); 27203100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu set_register(a2, va_arg(parameters, int32_t)); 27213100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu set_register(a3, va_arg(parameters, int32_t)); 27223100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 27233100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // Remaining arguments passed on stack. 27243100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu int original_stack = get_register(sp); 27253100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // Compute position of stack on entry to generated code. 27263100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu int entry_stack = (original_stack - (argument_count - 4) * sizeof(int32_t) 272744f0eee88ff00398ff7f715fab053374d808c90dSteve Block - kCArgsSlotsSize); 27283100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu if (OS::ActivationFrameAlignment() != 0) { 27293100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu entry_stack &= -OS::ActivationFrameAlignment(); 27303100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu } 27313100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // Store remaining arguments on stack, from low to high memory. 27323100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu intptr_t* stack_argument = reinterpret_cast<intptr_t*>(entry_stack); 27333100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu for (int i = 4; i < argument_count; i++) { 2734589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch stack_argument[i - 4 + kCArgSlotCount] = va_arg(parameters, int32_t); 27353100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu } 27363100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu va_end(parameters); 27373100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu set_register(sp, entry_stack); 27383100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 2739257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Prepare to execute the code at entry. 27403100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu set_register(pc, reinterpret_cast<int32_t>(entry)); 27413100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // Put down marker for end of simulation. The simulator will stop simulation 27423100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // when the PC reaches this value. By saving the "end simulation" value into 27433100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // the LR the simulation stops when returning to this call point. 27443100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu set_register(ra, end_sim_pc); 27453100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 27463100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // Remember the values of callee-saved registers. 27473100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // The code below assumes that r9 is not used as sb (static base) in 27483100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // simulator code and therefore is regarded as a callee-saved register. 27493100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu int32_t s0_val = get_register(s0); 27503100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu int32_t s1_val = get_register(s1); 27513100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu int32_t s2_val = get_register(s2); 27523100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu int32_t s3_val = get_register(s3); 27533100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu int32_t s4_val = get_register(s4); 27543100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu int32_t s5_val = get_register(s5); 27553100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu int32_t s6_val = get_register(s6); 27563100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu int32_t s7_val = get_register(s7); 27573100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu int32_t gp_val = get_register(gp); 27583100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu int32_t sp_val = get_register(sp); 27593100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu int32_t fp_val = get_register(fp); 27603100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 27613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Set up the callee-saved registers with a known value. To be able to check 27623100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // that they are preserved properly across JS execution. 27633100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu int32_t callee_saved_value = icount_; 27643100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu set_register(s0, callee_saved_value); 27653100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu set_register(s1, callee_saved_value); 27663100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu set_register(s2, callee_saved_value); 27673100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu set_register(s3, callee_saved_value); 27683100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu set_register(s4, callee_saved_value); 27693100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu set_register(s5, callee_saved_value); 27703100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu set_register(s6, callee_saved_value); 27713100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu set_register(s7, callee_saved_value); 27723100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu set_register(gp, callee_saved_value); 27733100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu set_register(fp, callee_saved_value); 27743100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 2775257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Start the simulation. 27763100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu Execute(); 27773100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 27783100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // Check that the callee-saved registers have been preserved. 27793100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu CHECK_EQ(callee_saved_value, get_register(s0)); 27803100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu CHECK_EQ(callee_saved_value, get_register(s1)); 27813100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu CHECK_EQ(callee_saved_value, get_register(s2)); 27823100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu CHECK_EQ(callee_saved_value, get_register(s3)); 27833100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu CHECK_EQ(callee_saved_value, get_register(s4)); 27843100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu CHECK_EQ(callee_saved_value, get_register(s5)); 27853100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu CHECK_EQ(callee_saved_value, get_register(s6)); 27863100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu CHECK_EQ(callee_saved_value, get_register(s7)); 27873100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu CHECK_EQ(callee_saved_value, get_register(gp)); 27883100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu CHECK_EQ(callee_saved_value, get_register(fp)); 27893100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 27903100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // Restore callee-saved registers with the original value. 27913100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu set_register(s0, s0_val); 27923100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu set_register(s1, s1_val); 27933100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu set_register(s2, s2_val); 27943100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu set_register(s3, s3_val); 27953100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu set_register(s4, s4_val); 27963100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu set_register(s5, s5_val); 27973100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu set_register(s6, s6_val); 27983100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu set_register(s7, s7_val); 27993100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu set_register(gp, gp_val); 28003100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu set_register(sp, sp_val); 28013100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu set_register(fp, fp_val); 28023100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 28033100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // Pop stack passed arguments. 28043100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu CHECK_EQ(entry_stack, get_register(sp)); 28053100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu set_register(sp, original_stack); 28063100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 28073100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu int32_t result = get_register(v0); 28083100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu return result; 28093100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} 28103100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 28113100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 28123100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuuintptr_t Simulator::PushAddress(uintptr_t address) { 28133100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu int new_sp = get_register(sp) - sizeof(uintptr_t); 28143100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu uintptr_t* stack_slot = reinterpret_cast<uintptr_t*>(new_sp); 28153100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu *stack_slot = address; 28163100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu set_register(sp, new_sp); 28173100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu return new_sp; 28183100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} 28193100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 28203100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 28213100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuuintptr_t Simulator::PopAddress() { 28223100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu int current_sp = get_register(sp); 28233100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu uintptr_t* stack_slot = reinterpret_cast<uintptr_t*>(current_sp); 28243100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu uintptr_t address = *stack_slot; 28253100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu set_register(sp, current_sp + sizeof(uintptr_t)); 28263100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu return address; 28273100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} 28283100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 28293100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 28303100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu#undef UNSUPPORTED 28313100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 283244f0eee88ff00398ff7f715fab053374d808c90dSteve Block} } // namespace v8::internal 28333100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 283444f0eee88ff00398ff7f715fab053374d808c90dSteve Block#endif // USE_SIMULATOR 28353100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 2836f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke#endif // V8_TARGET_ARCH_MIPS 2837