1257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// Copyright 2011 the V8 project authors. All rights reserved. 2b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Use of this source code is governed by a BSD-style license that can be 3b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// found in the LICENSE file. 43100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 53100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 63100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// Declares a Simulator for MIPS instructions if we are not generating a native 73100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// MIPS binary. This Simulator allows us to run and debug MIPS code generation 83100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// on regular desktop machines. 93100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// V8 calls into generated code by "calling" the CALL_GENERATED_CODE macro, 103100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// which will start execution in the Simulator or forwards to the real entry 113100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// on a MIPS HW platform. 123100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 133100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu#ifndef V8_MIPS_SIMULATOR_MIPS_H_ 143100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu#define V8_MIPS_SIMULATOR_MIPS_H_ 153100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 16b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/allocation.h" 17b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/mips/constants-mips.h" 183100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 1944f0eee88ff00398ff7f715fab053374d808c90dSteve Block#if !defined(USE_SIMULATOR) 2044f0eee88ff00398ff7f715fab053374d808c90dSteve Block// Running without a simulator on a native mips platform. 2144f0eee88ff00398ff7f715fab053374d808c90dSteve Block 2244f0eee88ff00398ff7f715fab053374d808c90dSteve Blocknamespace v8 { 2344f0eee88ff00398ff7f715fab053374d808c90dSteve Blocknamespace internal { 243100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 253100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// When running without a simulator we call the entry directly. 26014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#define CALL_GENERATED_CODE(isolate, entry, p0, p1, p2, p3, p4) \ 2744f0eee88ff00398ff7f715fab053374d808c90dSteve Block entry(p0, p1, p2, p3, p4) 2844f0eee88ff00398ff7f715fab053374d808c90dSteve Block 2944f0eee88ff00398ff7f715fab053374d808c90dSteve Blocktypedef int (*mips_regexp_matcher)(String*, int, const byte*, const byte*, 30b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void*, int*, int, Address, int, Isolate*); 31257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3244f0eee88ff00398ff7f715fab053374d808c90dSteve Block 3344f0eee88ff00398ff7f715fab053374d808c90dSteve Block// Call the generated regexp code directly. The code at the entry address 3444f0eee88ff00398ff7f715fab053374d808c90dSteve Block// should act as a function matching the type arm_regexp_matcher. 3544f0eee88ff00398ff7f715fab053374d808c90dSteve Block// The fifth argument is a dummy that reserves the space used for 3644f0eee88ff00398ff7f715fab053374d808c90dSteve Block// the return address added by the ExitFrame in native calls. 37014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#define CALL_GENERATED_REGEXP_CODE(isolate, entry, p0, p1, p2, p3, p4, p5, p6, \ 38014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch p7, p8) \ 39014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch (FUNCTION_CAST<mips_regexp_matcher>(entry)(p0, p1, p2, p3, NULL, p4, p5, p6, \ 40014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch p7, p8)) 413100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 423100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// The stack limit beyond which we will throw stack overflow errors in 433100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// generated code. Because generated code on mips uses the C stack, we 443100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// just use the C stack limit. 453100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuclass SimulatorStack : public v8::internal::AllStatic { 463100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu public: 47257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch static inline uintptr_t JsLimitFromCLimit(Isolate* isolate, 48257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch uintptr_t c_limit) { 493100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu return c_limit; 503100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu } 513100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 52014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch static inline uintptr_t RegisterCTryCatch(Isolate* isolate, 53014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch uintptr_t try_catch_address) { 54014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch USE(isolate); 553100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu return try_catch_address; 563100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu } 573100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 58014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch static inline void UnregisterCTryCatch(Isolate* isolate) { USE(isolate); } 593100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}; 603100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 61014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} // namespace internal 62014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} // namespace v8 6344f0eee88ff00398ff7f715fab053374d808c90dSteve Block 643100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// Calculated the stack limit beyond which we will throw stack overflow errors. 653100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// This macro must be called from a C++ method. It relies on being able to take 663100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// the address of "this" to get a value on the current execution stack and then 673100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// calculates the stack limit based on that value. 683100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// NOTE: The check for overflow is not safe as there is no guarantee that the 693100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// running thread has its stack in all memory up to address 0x00000000. 703100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu#define GENERATED_CODE_STACK_LIMIT(limit) \ 713100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu (reinterpret_cast<uintptr_t>(this) >= limit ? \ 723100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu reinterpret_cast<uintptr_t>(this) - limit : 0) 733100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 7444f0eee88ff00398ff7f715fab053374d808c90dSteve Block#else // !defined(USE_SIMULATOR) 7544f0eee88ff00398ff7f715fab053374d808c90dSteve Block// Running with a simulator. 763100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 77b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/assembler.h" 7813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch#include "src/base/hashmap.h" 793100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 8044f0eee88ff00398ff7f715fab053374d808c90dSteve Blocknamespace v8 { 8144f0eee88ff00398ff7f715fab053374d808c90dSteve Blocknamespace internal { 823100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 8344f0eee88ff00398ff7f715fab053374d808c90dSteve Block// ----------------------------------------------------------------------------- 8444f0eee88ff00398ff7f715fab053374d808c90dSteve Block// Utility functions 853100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 8644f0eee88ff00398ff7f715fab053374d808c90dSteve Blockclass CachePage { 8744f0eee88ff00398ff7f715fab053374d808c90dSteve Block public: 8844f0eee88ff00398ff7f715fab053374d808c90dSteve Block static const int LINE_VALID = 0; 8944f0eee88ff00398ff7f715fab053374d808c90dSteve Block static const int LINE_INVALID = 1; 9044f0eee88ff00398ff7f715fab053374d808c90dSteve Block 9144f0eee88ff00398ff7f715fab053374d808c90dSteve Block static const int kPageShift = 12; 9244f0eee88ff00398ff7f715fab053374d808c90dSteve Block static const int kPageSize = 1 << kPageShift; 9344f0eee88ff00398ff7f715fab053374d808c90dSteve Block static const int kPageMask = kPageSize - 1; 9444f0eee88ff00398ff7f715fab053374d808c90dSteve Block static const int kLineShift = 2; // The cache line is only 4 bytes right now. 9544f0eee88ff00398ff7f715fab053374d808c90dSteve Block static const int kLineLength = 1 << kLineShift; 9644f0eee88ff00398ff7f715fab053374d808c90dSteve Block static const int kLineMask = kLineLength - 1; 9744f0eee88ff00398ff7f715fab053374d808c90dSteve Block 9844f0eee88ff00398ff7f715fab053374d808c90dSteve Block CachePage() { 9944f0eee88ff00398ff7f715fab053374d808c90dSteve Block memset(&validity_map_, LINE_INVALID, sizeof(validity_map_)); 10044f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 1013100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 10244f0eee88ff00398ff7f715fab053374d808c90dSteve Block char* ValidityByte(int offset) { 10344f0eee88ff00398ff7f715fab053374d808c90dSteve Block return &validity_map_[offset >> kLineShift]; 10444f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 1053100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 10644f0eee88ff00398ff7f715fab053374d808c90dSteve Block char* CachedData(int offset) { 10744f0eee88ff00398ff7f715fab053374d808c90dSteve Block return &data_[offset]; 10844f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 1093100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 11044f0eee88ff00398ff7f715fab053374d808c90dSteve Block private: 11144f0eee88ff00398ff7f715fab053374d808c90dSteve Block char data_[kPageSize]; // The cached data. 11244f0eee88ff00398ff7f715fab053374d808c90dSteve Block static const int kValidityMapSize = kPageSize >> kLineShift; 11344f0eee88ff00398ff7f715fab053374d808c90dSteve Block char validity_map_[kValidityMapSize]; // One byte per line. 11444f0eee88ff00398ff7f715fab053374d808c90dSteve Block}; 1153100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 116f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdochclass SimInstructionBase : public InstructionBase { 117f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch public: 118f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Type InstructionType() const { return type_; } 119f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch inline Instruction* instr() const { return instr_; } 120f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch inline int32_t operand() const { return operand_; } 121f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 122f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch protected: 123f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch SimInstructionBase() : operand_(-1), instr_(nullptr), type_(kUnsupported) {} 124f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch explicit SimInstructionBase(Instruction* instr) {} 125f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 126f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch int32_t operand_; 127f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Instruction* instr_; 128f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Type type_; 129f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 130f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch private: 131f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch DISALLOW_ASSIGN(SimInstructionBase); 132f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch}; 133f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 134f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdochclass SimInstruction : public InstructionGetters<SimInstructionBase> { 135f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch public: 136f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch SimInstruction() {} 137f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 138f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch explicit SimInstruction(Instruction* instr) { *this = instr; } 139f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 140f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch SimInstruction& operator=(Instruction* instr) { 141f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch operand_ = *reinterpret_cast<const int32_t*>(instr); 142f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch instr_ = instr; 143f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch type_ = InstructionBase::InstructionType(); 144f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch DCHECK(reinterpret_cast<void*>(&operand_) == this); 145f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch return *this; 146f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch } 147f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch}; 148f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 1493100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuclass Simulator { 1503100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu public: 15144f0eee88ff00398ff7f715fab053374d808c90dSteve Block friend class MipsDebugger; 1523100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 1533100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // Registers are declared in order. See SMRL chapter 2. 1543100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu enum Register { 1553100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu no_reg = -1, 1563100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu zero_reg = 0, 1573100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu at, 1583100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu v0, v1, 1593100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu a0, a1, a2, a3, 1603100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu t0, t1, t2, t3, t4, t5, t6, t7, 1613100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu s0, s1, s2, s3, s4, s5, s6, s7, 1623100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu t8, t9, 1633100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu k0, k1, 1643100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu gp, 1653100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu sp, 1663100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu s8, 1673100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu ra, 168257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // LO, HI, and pc. 1693100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu LO, 1703100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu HI, 1713100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu pc, // pc must be the last register. 1723100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu kNumSimuRegisters, 1733100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // aliases 1743100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu fp = s8 1753100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu }; 1763100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 1773100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // Coprocessor registers. 1783100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // Generated code will always use doubles. So we will only use even registers. 1793100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu enum FPURegister { 1803100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu f0, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, 181257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch f12, f13, f14, f15, // f12 and f14 are arguments FPURegisters. 1823100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu f16, f17, f18, f19, f20, f21, f22, f23, f24, f25, 1833100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu f26, f27, f28, f29, f30, f31, 1843100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu kNumFPURegisters 1853100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu }; 1863100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 187257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch explicit Simulator(Isolate* isolate); 1883100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu ~Simulator(); 1893100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 1903100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // The currently executing Simulator instance. Potentially there can be one 1913100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // for each native thread. 19244f0eee88ff00398ff7f715fab053374d808c90dSteve Block static Simulator* current(v8::internal::Isolate* isolate); 1933100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 1943100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // Accessors for register state. Reading the pc value adheres to the MIPS 1953100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // architecture specification and is off by a 8 from the currently executing 1963100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // instruction. 1973100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu void set_register(int reg, int32_t value); 198b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void set_dw_register(int dreg, const int* dbl); 1993100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu int32_t get_register(int reg) const; 200b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch double get_double_from_register_pair(int reg); 201257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Same for FPURegisters. 202b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void set_fpu_register(int fpureg, int64_t value); 203b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void set_fpu_register_word(int fpureg, int32_t value); 204b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void set_fpu_register_hi_word(int fpureg, int32_t value); 20544f0eee88ff00398ff7f715fab053374d808c90dSteve Block void set_fpu_register_float(int fpureg, float value); 2063100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu void set_fpu_register_double(int fpureg, double value); 207014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch void set_fpu_register_invalid_result64(float original, float rounded); 208014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch void set_fpu_register_invalid_result(float original, float rounded); 209014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch void set_fpu_register_word_invalid_result(float original, float rounded); 210014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch void set_fpu_register_invalid_result64(double original, double rounded); 211014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch void set_fpu_register_invalid_result(double original, double rounded); 212014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch void set_fpu_register_word_invalid_result(double original, double rounded); 213b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int64_t get_fpu_register(int fpureg) const; 214b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int32_t get_fpu_register_word(int fpureg) const; 215b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int32_t get_fpu_register_signed_word(int fpureg) const; 216b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int32_t get_fpu_register_hi_word(int fpureg) const; 21744f0eee88ff00398ff7f715fab053374d808c90dSteve Block float get_fpu_register_float(int fpureg) const; 2183100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu double get_fpu_register_double(int fpureg) const; 21944f0eee88ff00398ff7f715fab053374d808c90dSteve Block void set_fcsr_bit(uint32_t cc, bool value); 22044f0eee88ff00398ff7f715fab053374d808c90dSteve Block bool test_fcsr_bit(uint32_t cc); 221014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch void set_fcsr_rounding_mode(FPURoundingMode mode); 222014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch unsigned int get_fcsr_rounding_mode(); 22344f0eee88ff00398ff7f715fab053374d808c90dSteve Block bool set_fcsr_round_error(double original, double rounded); 224014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch bool set_fcsr_round_error(float original, float rounded); 225014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch bool set_fcsr_round64_error(double original, double rounded); 226014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch bool set_fcsr_round64_error(float original, float rounded); 227014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch void round_according_to_fcsr(double toRound, double& rounded, 228014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch int32_t& rounded_int, double fs); 229014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch void round_according_to_fcsr(float toRound, float& rounded, 230014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch int32_t& rounded_int, float fs); 231014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch void round64_according_to_fcsr(double toRound, double& rounded, 232014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch int64_t& rounded_int, double fs); 233014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch void round64_according_to_fcsr(float toRound, float& rounded, 234014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch int64_t& rounded_int, float fs); 2353100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // Special case of set_register and get_register to access the raw PC value. 2363100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu void set_pc(int32_t value); 2373100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu int32_t get_pc() const; 2383100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 239014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Address get_sp() const { 240b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return reinterpret_cast<Address>(static_cast<intptr_t>(get_register(sp))); 241b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 242b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2433100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // Accessor to the internal simulator stack area. 244014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch uintptr_t StackLimit(uintptr_t c_limit) const; 2453100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 2463100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // Executes MIPS instructions until the PC reaches end_sim_pc. 2473100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu void Execute(); 2483100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 2493100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // Call on program start. 250257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch static void Initialize(Isolate* isolate); 2513100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 252f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch static void TearDown(base::CustomMatcherHashMap* i_cache, Redirection* first); 253014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2543100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // V8 generally calls into generated JS code with 5 parameters and into 2553100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // generated RegExp code with 7 parameters. This is a convenience function, 2563100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // which sets up the simulator state and grabs the result on return. 25744f0eee88ff00398ff7f715fab053374d808c90dSteve Block int32_t Call(byte* entry, int argument_count, ...); 258b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Alternative: call a 2-argument double function. 259b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch double CallFP(byte* entry, double d0, double d1); 2603100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 2613100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // Push an address onto the JS stack. 2623100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu uintptr_t PushAddress(uintptr_t address); 2633100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 2643100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // Pop an address from the JS stack. 2653100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu uintptr_t PopAddress(); 2663100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 2673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Debugger input. 2683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void set_last_debugger_input(char* input); 2693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch char* last_debugger_input() { return last_debugger_input_; } 2703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 27144f0eee88ff00398ff7f715fab053374d808c90dSteve Block // ICache checking. 272f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch static void FlushICache(base::CustomMatcherHashMap* i_cache, void* start, 273f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch size_t size); 27444f0eee88ff00398ff7f715fab053374d808c90dSteve Block 27544f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Returns true if pc register contains one of the 'special_values' defined 27644f0eee88ff00398ff7f715fab053374d808c90dSteve Block // below (bad_ra, end_sim_pc). 27744f0eee88ff00398ff7f715fab053374d808c90dSteve Block bool has_bad_pc() const; 27844f0eee88ff00398ff7f715fab053374d808c90dSteve Block 2793100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu private: 2803100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu enum special_values { 2813100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // Known bad pc value to ensure that the simulator does not execute 2823100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // without being properly setup. 2833100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu bad_ra = -1, 2843100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // A pc value used to signal the simulator to stop execution. Generally 2853100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // the ra is set to this value on transition from native C code to 2863100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // simulated execution, so that the simulator can "return" to the native 2873100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // C code. 2883100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu end_sim_pc = -2, 2893100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // Unpredictable value. 2903100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu Unpredictable = 0xbadbeaf 2913100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu }; 2923100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 2933100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // Unsupported instructions use Format to print an error and stop execution. 2943100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu void Format(Instruction* instr, const char* format); 2953100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 2963100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // Read and write memory. 2973100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu inline uint32_t ReadBU(int32_t addr); 2983100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu inline int32_t ReadB(int32_t addr); 2993100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu inline void WriteB(int32_t addr, uint8_t value); 3003100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu inline void WriteB(int32_t addr, int8_t value); 3013100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 3023100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu inline uint16_t ReadHU(int32_t addr, Instruction* instr); 3033100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu inline int16_t ReadH(int32_t addr, Instruction* instr); 3043100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // Note: Overloaded on the sign of the value. 3053100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu inline void WriteH(int32_t addr, uint16_t value, Instruction* instr); 3063100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu inline void WriteH(int32_t addr, int16_t value, Instruction* instr); 3073100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 3083100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu inline int ReadW(int32_t addr, Instruction* instr); 3093100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu inline void WriteW(int32_t addr, int value, Instruction* instr); 3103100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 3113100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu inline double ReadD(int32_t addr, Instruction* instr); 3123100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu inline void WriteD(int32_t addr, double value, Instruction* instr); 3133100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 314014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Helpers for data value tracing. 315014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch enum TraceType { 316014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch BYTE, 317014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch HALF, 318014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch WORD 319014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // DWORD, 320014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // DFLOAT - Floats may have printing issues due to paired lwc1's 321014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch }; 322014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 323014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch void TraceRegWr(int32_t value); 324014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch void TraceMemWr(int32_t addr, int32_t value, TraceType t); 325014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch void TraceMemRd(int32_t addr, int32_t value); 326014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch EmbeddedVector<char, 128> trace_buf_; 327014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 3283100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // Operations depending on endianness. 3293100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // Get Double Higher / Lower word. 3303100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu inline int32_t GetDoubleHIW(double* addr); 3313100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu inline int32_t GetDoubleLOW(double* addr); 3323100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // Set Double Higher / Lower word. 3333100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu inline int32_t SetDoubleHIW(double* addr); 3343100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu inline int32_t SetDoubleLOW(double* addr); 3353100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 336f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch SimInstruction instr_; 337f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 3383100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // Executing is handled based on the instruction type. 339f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch void DecodeTypeRegister(); 34044f0eee88ff00398ff7f715fab053374d808c90dSteve Block 341014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Functions called from DecodeTypeRegister. 342014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch void DecodeTypeRegisterCOP1(); 343014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 344014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch void DecodeTypeRegisterCOP1X(); 345014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 346014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch void DecodeTypeRegisterSPECIAL(); 347014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 348014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch void DecodeTypeRegisterSPECIAL2(); 349014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 350014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch void DecodeTypeRegisterSPECIAL3(); 351014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 352014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Called from DecodeTypeRegisterCOP1. 353014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch void DecodeTypeRegisterSRsType(); 354014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 355014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch void DecodeTypeRegisterDRsType(); 356014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 357014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch void DecodeTypeRegisterWRsType(); 358014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 359014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch void DecodeTypeRegisterLRsType(); 360014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 361f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch inline int32_t rs_reg() const { return instr_.RsValue(); } 362014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch inline int32_t rs() const { return get_register(rs_reg()); } 363014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch inline uint32_t rs_u() const { 364014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch return static_cast<uint32_t>(get_register(rs_reg())); 365014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 366f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch inline int32_t rt_reg() const { return instr_.RtValue(); } 367014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch inline int32_t rt() const { return get_register(rt_reg()); } 368014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch inline uint32_t rt_u() const { 369014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch return static_cast<uint32_t>(get_register(rt_reg())); 370014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 371f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch inline int32_t rd_reg() const { return instr_.RdValue(); } 372f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch inline int32_t fr_reg() const { return instr_.FrValue(); } 373f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch inline int32_t fs_reg() const { return instr_.FsValue(); } 374f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch inline int32_t ft_reg() const { return instr_.FtValue(); } 375f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch inline int32_t fd_reg() const { return instr_.FdValue(); } 376f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch inline int32_t sa() const { return instr_.SaValue(); } 377f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch inline int32_t lsa_sa() const { return instr_.LsaSaValue(); } 378014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 379014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch inline void SetResult(int32_t rd_reg, int32_t alu_out) { 380014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch set_register(rd_reg, alu_out); 381014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch TraceRegWr(alu_out); 382014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 38344f0eee88ff00398ff7f715fab053374d808c90dSteve Block 384f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch void DecodeTypeImmediate(); 385f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch void DecodeTypeJump(); 3863100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 3873100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // Used for breakpoints and traps. 388f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch void SoftwareInterrupt(); 3893100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 390014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Compact branch guard. 391014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch void CheckForbiddenSlot(int32_t current_pc) { 392109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Instruction* instr_after_compact_branch = 393014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch reinterpret_cast<Instruction*>(current_pc + Instruction::kInstrSize); 394109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch if (instr_after_compact_branch->IsForbiddenAfterBranch()) { 395014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch V8_Fatal(__FILE__, __LINE__, 396014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch "Error: Unexpected instruction 0x%08x immediately after a " 397014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch "compact branch instruction.", 398109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch *reinterpret_cast<uint32_t*>(instr_after_compact_branch)); 399014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 400014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 401014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 4023fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Stop helper functions. 4033fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch bool IsWatchpoint(uint32_t code); 4043fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch void PrintWatchpoint(uint32_t code); 4053fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch void HandleStop(uint32_t code, Instruction* instr); 4063fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch bool IsStopInstruction(Instruction* instr); 4073fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch bool IsEnabledStop(uint32_t code); 4083fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch void EnableStop(uint32_t code); 4093fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch void DisableStop(uint32_t code); 4103fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch void IncreaseStopCounter(uint32_t code); 4113fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch void PrintStopInfo(uint32_t code); 4123fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 4133fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 4143100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // Executes one instruction. 4153100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu void InstructionDecode(Instruction* instr); 4163100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // Execute one instruction placed in a branch delay slot. 4173100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu void BranchDelayInstructionDecode(Instruction* instr) { 4183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (instr->InstructionBits() == nopInstr) { 4193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Short-cut generic nop instructions. They are always valid and they 4203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // never change the simulator state. 4213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return; 4223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 4233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 4243100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu if (instr->IsForbiddenInBranchDelay()) { 4253100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu V8_Fatal(__FILE__, __LINE__, 4263100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu "Eror:Unexpected %i opcode in a branch delay slot.", 42744f0eee88ff00398ff7f715fab053374d808c90dSteve Block instr->OpcodeValue()); 4283100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu } 4293100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu InstructionDecode(instr); 430014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch SNPrintF(trace_buf_, " "); 4313100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu } 4323100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 43344f0eee88ff00398ff7f715fab053374d808c90dSteve Block // ICache. 434f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch static void CheckICache(base::CustomMatcherHashMap* i_cache, 435f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Instruction* instr); 436f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch static void FlushOnePage(base::CustomMatcherHashMap* i_cache, intptr_t start, 437f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch int size); 438f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch static CachePage* GetCachePage(base::CustomMatcherHashMap* i_cache, 439f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch void* page); 44044f0eee88ff00398ff7f715fab053374d808c90dSteve Block 4413100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu enum Exception { 4423100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu none, 4433100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu kIntegerOverflow, 4443100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu kIntegerUnderflow, 4453100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu kDivideByZero, 4463100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu kNumExceptions 4473100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu }; 4483100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 4493100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // Exceptions. 450014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch void SignalException(Exception e); 4513100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 4523100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // Runtime call support. 453014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch static void* RedirectExternalReference(Isolate* isolate, 454014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch void* external_function, 45544f0eee88ff00398ff7f715fab053374d808c90dSteve Block ExternalReference::Type type); 4563100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 457b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Handle arguments and return value for runtime FP functions. 458b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void GetFpArgs(double* x, double* y, int32_t* z); 459257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch void SetFpResult(const double& result); 460257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 461b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void CallInternal(byte* entry); 4623100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 4633100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // Architecture state. 4643100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // Registers. 4653100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu int32_t registers_[kNumSimuRegisters]; 4663100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // Coprocessor Registers. 467b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Note: FP32 mode uses only the lower 32-bit part of each element, 468b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // the upper 32-bit is unpredictable. 469b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int64_t FPUregisters_[kNumFPURegisters]; 47044f0eee88ff00398ff7f715fab053374d808c90dSteve Block // FPU control register. 47144f0eee88ff00398ff7f715fab053374d808c90dSteve Block uint32_t FCSR_; 4723100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 4733100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // Simulator support. 474257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Allocate 1MB for stack. 475257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch static const size_t stack_size_ = 1 * 1024*1024; 4763100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu char* stack_; 4773100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu bool pc_modified_; 478014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch uint64_t icount_; 47944f0eee88ff00398ff7f715fab053374d808c90dSteve Block int break_count_; 48044f0eee88ff00398ff7f715fab053374d808c90dSteve Block 4813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Debugger input. 4823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch char* last_debugger_input_; 4833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 484257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Icache simulation. 485f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch base::CustomMatcherHashMap* i_cache_; 4863100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 487257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch v8::internal::Isolate* isolate_; 488257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 4893100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // Registered breakpoints. 4903100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu Instruction* break_pc_; 4913100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu Instr break_instr_; 4923fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 4933fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Stop is disabled if bit 31 is set. 4943fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch static const uint32_t kStopDisabledBit = 1 << 31; 4953fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 4963fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // A stop is enabled, meaning the simulator will stop when meeting the 497b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // instruction, if bit 31 of watched_stops_[code].count is unset. 498b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // The value watched_stops_[code].count & ~(1 << 31) indicates how many times 4993fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // the breakpoint was hit or gone through. 5003fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch struct StopCountAndDesc { 5013fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch uint32_t count; 5023fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch char* desc; 5033fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch }; 504b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch StopCountAndDesc watched_stops_[kMaxStopCode + 1]; 5053100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}; 5063100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 50744f0eee88ff00398ff7f715fab053374d808c90dSteve Block 50844f0eee88ff00398ff7f715fab053374d808c90dSteve Block// When running with the simulator transition into simulated execution at this 50944f0eee88ff00398ff7f715fab053374d808c90dSteve Block// point. 510014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#define CALL_GENERATED_CODE(isolate, entry, p0, p1, p2, p3, p4) \ 511014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch reinterpret_cast<Object*>(Simulator::current(isolate)->Call( \ 51244f0eee88ff00398ff7f715fab053374d808c90dSteve Block FUNCTION_ADDR(entry), 5, p0, p1, p2, p3, p4)) 51344f0eee88ff00398ff7f715fab053374d808c90dSteve Block 514014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#define CALL_GENERATED_REGEXP_CODE(isolate, entry, p0, p1, p2, p3, p4, p5, p6, \ 515014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch p7, p8) \ 516014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Simulator::current(isolate) \ 517014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch ->Call(entry, 10, p0, p1, p2, p3, NULL, p4, p5, p6, p7, p8) 5183100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 5193100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 5203100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// The simulator has its own stack. Thus it has a different stack limit from 521014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// the C-based native code. The JS-based limit normally points near the end of 522014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// the simulator stack. When the C-based limit is exhausted we reflect that by 523014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// lowering the JS-based limit as well, to make stack checks trigger. 5243100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuclass SimulatorStack : public v8::internal::AllStatic { 5253100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu public: 526257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch static inline uintptr_t JsLimitFromCLimit(Isolate* isolate, 527257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch uintptr_t c_limit) { 528014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch return Simulator::current(isolate)->StackLimit(c_limit); 5293100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu } 5303100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 531014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch static inline uintptr_t RegisterCTryCatch(Isolate* isolate, 532014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch uintptr_t try_catch_address) { 533014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Simulator* sim = Simulator::current(isolate); 5343100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu return sim->PushAddress(try_catch_address); 5353100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu } 5363100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 537014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch static inline void UnregisterCTryCatch(Isolate* isolate) { 538014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Simulator::current(isolate)->PopAddress(); 5393100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu } 5403100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}; 5413100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 542014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} // namespace internal 543014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} // namespace v8 5443100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 54544f0eee88ff00398ff7f715fab053374d808c90dSteve Block#endif // !defined(USE_SIMULATOR) 5463100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu#endif // V8_MIPS_SIMULATOR_MIPS_H_ 547