1b8a8cc1952d61a2f3a2568848933943a543b5d3eBen 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. 4b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 5b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 6b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Declares a Simulator for MIPS instructions if we are not generating a native 7b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// MIPS binary. This Simulator allows us to run and debug MIPS code generation 8b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// on regular desktop machines. 9b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// V8 calls into generated code by "calling" the CALL_GENERATED_CODE macro, 10b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// which will start execution in the Simulator or forwards to the real entry 11b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// on a MIPS HW platform. 12b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 13b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#ifndef V8_MIPS_SIMULATOR_MIPS_H_ 14b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#define V8_MIPS_SIMULATOR_MIPS_H_ 15b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 16b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/allocation.h" 17b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/mips64/constants-mips64.h" 18b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 19b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#if !defined(USE_SIMULATOR) 20b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Running without a simulator on a native mips platform. 21b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 22b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochnamespace v8 { 23b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochnamespace internal { 24b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 25b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// When running without a simulator we call the entry directly. 26014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#define CALL_GENERATED_CODE(isolate, entry, p0, p1, p2, p3, p4) \ 27b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch entry(p0, p1, p2, p3, p4) 28b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 29b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 30b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Call the generated regexp code directly. The code at the entry address 31b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// should act as a function matching the type arm_regexp_matcher. 32b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// The fifth (or ninth) argument is a dummy that reserves the space used for 33b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// the return address added by the ExitFrame in native calls. 34b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochtypedef int (*mips_regexp_matcher)(String* input, 35b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int64_t start_offset, 36b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const byte* input_start, 37b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const byte* input_end, 38b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int* output, 39b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int64_t output_size, 40b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Address stack_base, 41b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int64_t direct_call, 42b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void* return_address, 43b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Isolate* isolate); 44b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 45014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#define CALL_GENERATED_REGEXP_CODE(isolate, entry, p0, p1, p2, p3, p4, p5, p6, \ 46014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch p7, p8) \ 47014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch (FUNCTION_CAST<mips_regexp_matcher>(entry)(p0, p1, p2, p3, p4, p5, p6, p7, \ 48014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch NULL, p8)) 49b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 50b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 51b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// The stack limit beyond which we will throw stack overflow errors in 52b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// generated code. Because generated code on mips uses the C stack, we 53b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// just use the C stack limit. 54b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochclass SimulatorStack : public v8::internal::AllStatic { 55b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch public: 56b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static inline uintptr_t JsLimitFromCLimit(Isolate* isolate, 57b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch uintptr_t c_limit) { 58b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return c_limit; 59b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 60b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 61014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch static inline uintptr_t RegisterCTryCatch(Isolate* isolate, 62014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch uintptr_t try_catch_address) { 63014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch USE(isolate); 64b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return try_catch_address; 65b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 66b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 67014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch static inline void UnregisterCTryCatch(Isolate* isolate) { USE(isolate); } 68b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}; 69b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 70014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} // namespace internal 71014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} // namespace v8 72b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 73b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Calculated the stack limit beyond which we will throw stack overflow errors. 74b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// This macro must be called from a C++ method. It relies on being able to take 75b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// the address of "this" to get a value on the current execution stack and then 76b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// calculates the stack limit based on that value. 77b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// NOTE: The check for overflow is not safe as there is no guarantee that the 78b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// running thread has its stack in all memory up to address 0x00000000. 79b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#define GENERATED_CODE_STACK_LIMIT(limit) \ 80b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch (reinterpret_cast<uintptr_t>(this) >= limit ? \ 81b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch reinterpret_cast<uintptr_t>(this) - limit : 0) 82b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 83b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#else // !defined(USE_SIMULATOR) 84b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Running with a simulator. 85b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 86b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/assembler.h" 8713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch#include "src/base/hashmap.h" 88b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 89b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochnamespace v8 { 90b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochnamespace internal { 91b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 92b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// ----------------------------------------------------------------------------- 93b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Utility functions 94b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 95b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochclass CachePage { 96b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch public: 97b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static const int LINE_VALID = 0; 98b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static const int LINE_INVALID = 1; 99b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 100b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static const int kPageShift = 12; 101b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static const int kPageSize = 1 << kPageShift; 102b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static const int kPageMask = kPageSize - 1; 103b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static const int kLineShift = 2; // The cache line is only 4 bytes right now. 104b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static const int kLineLength = 1 << kLineShift; 105b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static const int kLineMask = kLineLength - 1; 106b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 107b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CachePage() { 108b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch memset(&validity_map_, LINE_INVALID, sizeof(validity_map_)); 109b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 110b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 111b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch char* ValidityByte(int offset) { 112b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return &validity_map_[offset >> kLineShift]; 113b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 114b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 115b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch char* CachedData(int offset) { 116b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return &data_[offset]; 117b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 118b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 119b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch private: 120b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch char data_[kPageSize]; // The cached data. 121b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static const int kValidityMapSize = kPageSize >> kLineShift; 122b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch char validity_map_[kValidityMapSize]; // One byte per line. 123b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}; 124b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 125f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdochclass SimInstructionBase : public InstructionBase { 126f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch public: 127f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Type InstructionType() const { return type_; } 128f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch inline Instruction* instr() const { return instr_; } 129f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch inline int32_t operand() const { return operand_; } 130f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 131f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch protected: 132f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch SimInstructionBase() : operand_(-1), instr_(nullptr), type_(kUnsupported) {} 133f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch explicit SimInstructionBase(Instruction* instr) {} 134f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 135f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch int32_t operand_; 136f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Instruction* instr_; 137f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Type type_; 138f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 139f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch private: 140f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch DISALLOW_ASSIGN(SimInstructionBase); 141f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch}; 142f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 143f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdochclass SimInstruction : public InstructionGetters<SimInstructionBase> { 144f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch public: 145f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch SimInstruction() {} 146f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 147f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch explicit SimInstruction(Instruction* instr) { *this = instr; } 148f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 149f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch SimInstruction& operator=(Instruction* instr) { 150f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch operand_ = *reinterpret_cast<const int32_t*>(instr); 151f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch instr_ = instr; 152f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch type_ = InstructionBase::InstructionType(); 153f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch DCHECK(reinterpret_cast<void*>(&operand_) == this); 154f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch return *this; 155f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch } 156f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch}; 157f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 158b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochclass Simulator { 159b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch public: 160b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch friend class MipsDebugger; 161b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 162b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Registers are declared in order. See SMRL chapter 2. 163b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch enum Register { 164b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch no_reg = -1, 165b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch zero_reg = 0, 166b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch at, 167b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch v0, v1, 168b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch a0, a1, a2, a3, a4, a5, a6, a7, 169b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch t0, t1, t2, t3, 170b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch s0, s1, s2, s3, s4, s5, s6, s7, 171b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch t8, t9, 172b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch k0, k1, 173b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch gp, 174b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch sp, 175b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch s8, 176b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ra, 177b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // LO, HI, and pc. 178b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LO, 179b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HI, 180b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch pc, // pc must be the last register. 181b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch kNumSimuRegisters, 182b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // aliases 183b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch fp = s8 184b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch }; 185b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 186b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Coprocessor registers. 187b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Generated code will always use doubles. So we will only use even registers. 188b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch enum FPURegister { 189b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch f0, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, 190b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch f12, f13, f14, f15, // f12 and f14 are arguments FPURegisters. 191b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch f16, f17, f18, f19, f20, f21, f22, f23, f24, f25, 192b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch f26, f27, f28, f29, f30, f31, 193b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch kNumFPURegisters 194b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch }; 195b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 196b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch explicit Simulator(Isolate* isolate); 197b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ~Simulator(); 198b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 199b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // The currently executing Simulator instance. Potentially there can be one 200b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // for each native thread. 201b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static Simulator* current(v8::internal::Isolate* isolate); 202b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 203b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Accessors for register state. Reading the pc value adheres to the MIPS 204b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // architecture specification and is off by a 8 from the currently executing 205b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // instruction. 206b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void set_register(int reg, int64_t value); 207b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void set_register_word(int reg, int32_t value); 208b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void set_dw_register(int dreg, const int* dbl); 209b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int64_t get_register(int reg) const; 210b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch double get_double_from_register_pair(int reg); 211b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Same for FPURegisters. 212b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void set_fpu_register(int fpureg, int64_t value); 213b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void set_fpu_register_word(int fpureg, int32_t value); 214b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void set_fpu_register_hi_word(int fpureg, int32_t value); 215b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void set_fpu_register_float(int fpureg, float value); 216b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void set_fpu_register_double(int fpureg, double value); 217014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch void set_fpu_register_invalid_result64(float original, float rounded); 218014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch void set_fpu_register_invalid_result(float original, float rounded); 219014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch void set_fpu_register_word_invalid_result(float original, float rounded); 220014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch void set_fpu_register_invalid_result64(double original, double rounded); 221014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch void set_fpu_register_invalid_result(double original, double rounded); 222014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch void set_fpu_register_word_invalid_result(double original, double rounded); 223b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int64_t get_fpu_register(int fpureg) const; 224b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int32_t get_fpu_register_word(int fpureg) const; 225b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int32_t get_fpu_register_signed_word(int fpureg) const; 226b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int32_t get_fpu_register_hi_word(int fpureg) const; 227b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch float get_fpu_register_float(int fpureg) const; 228b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch double get_fpu_register_double(int fpureg) const; 229b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void set_fcsr_bit(uint32_t cc, bool value); 230b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool test_fcsr_bit(uint32_t cc); 231b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool set_fcsr_round_error(double original, double rounded); 232b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool set_fcsr_round64_error(double original, double rounded); 233014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch bool set_fcsr_round_error(float original, float rounded); 234014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch bool set_fcsr_round64_error(float original, float rounded); 235014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch void round_according_to_fcsr(double toRound, double& rounded, 236014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch int32_t& rounded_int, double fs); 237014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch void round64_according_to_fcsr(double toRound, double& rounded, 238014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch int64_t& rounded_int, double fs); 239014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch void round_according_to_fcsr(float toRound, float& rounded, 240014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch int32_t& rounded_int, float fs); 241014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch void round64_according_to_fcsr(float toRound, float& rounded, 242014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch int64_t& rounded_int, float fs); 243014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch void set_fcsr_rounding_mode(FPURoundingMode mode); 244014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch unsigned int get_fcsr_rounding_mode(); 245b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Special case of set_register and get_register to access the raw PC value. 246b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void set_pc(int64_t value); 247b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int64_t get_pc() const; 248b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 249014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Address get_sp() const { 250b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return reinterpret_cast<Address>(static_cast<intptr_t>(get_register(sp))); 251b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 252b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 253b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Accessor to the internal simulator stack area. 254014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch uintptr_t StackLimit(uintptr_t c_limit) const; 255b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 256b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Executes MIPS instructions until the PC reaches end_sim_pc. 257b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void Execute(); 258b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 259b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Call on program start. 260b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static void Initialize(Isolate* isolate); 261b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 262f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch static void TearDown(base::CustomMatcherHashMap* i_cache, Redirection* first); 263014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 264b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // V8 generally calls into generated JS code with 5 parameters and into 265b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // generated RegExp code with 7 parameters. This is a convenience function, 266b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // which sets up the simulator state and grabs the result on return. 267b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int64_t Call(byte* entry, int argument_count, ...); 268b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Alternative: call a 2-argument double function. 269b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch double CallFP(byte* entry, double d0, double d1); 270b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 271b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Push an address onto the JS stack. 272b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch uintptr_t PushAddress(uintptr_t address); 273b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 274b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Pop an address from the JS stack. 275b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch uintptr_t PopAddress(); 276b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 277b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Debugger input. 278b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void set_last_debugger_input(char* input); 279b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch char* last_debugger_input() { return last_debugger_input_; } 280b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 281b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // ICache checking. 282f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch static void FlushICache(base::CustomMatcherHashMap* i_cache, void* start, 283f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch size_t size); 284b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 285b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Returns true if pc register contains one of the 'special_values' defined 286b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // below (bad_ra, end_sim_pc). 287b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool has_bad_pc() const; 288b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 289b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch private: 290b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch enum special_values { 291b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Known bad pc value to ensure that the simulator does not execute 292b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // without being properly setup. 293b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bad_ra = -1, 294b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // A pc value used to signal the simulator to stop execution. Generally 295b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // the ra is set to this value on transition from native C code to 296b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // simulated execution, so that the simulator can "return" to the native 297b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // C code. 298b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch end_sim_pc = -2, 299b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Unpredictable value. 300b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Unpredictable = 0xbadbeaf 301b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch }; 302b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 303b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Unsupported instructions use Format to print an error and stop execution. 304b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void Format(Instruction* instr, const char* format); 305b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 30662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // Helpers for data value tracing. 30762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch enum TraceType { 30862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch BYTE, 30962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch HALF, 31062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch WORD, 31162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch DWORD, 31262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch FLOAT, 31362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch DOUBLE, 31462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch FLOAT_DOUBLE, 31562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch WORD_DWORD 31662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch }; 31762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 318b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Read and write memory. 319b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch inline uint32_t ReadBU(int64_t addr); 320b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch inline int32_t ReadB(int64_t addr); 321b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch inline void WriteB(int64_t addr, uint8_t value); 322b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch inline void WriteB(int64_t addr, int8_t value); 323b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 324b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch inline uint16_t ReadHU(int64_t addr, Instruction* instr); 325b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch inline int16_t ReadH(int64_t addr, Instruction* instr); 326b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Note: Overloaded on the sign of the value. 327b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch inline void WriteH(int64_t addr, uint16_t value, Instruction* instr); 328b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch inline void WriteH(int64_t addr, int16_t value, Instruction* instr); 329b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 330b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch inline uint32_t ReadWU(int64_t addr, Instruction* instr); 33162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch inline int32_t ReadW(int64_t addr, Instruction* instr, TraceType t = WORD); 332b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch inline void WriteW(int64_t addr, int32_t value, Instruction* instr); 333b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch inline int64_t Read2W(int64_t addr, Instruction* instr); 334b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch inline void Write2W(int64_t addr, int64_t value, Instruction* instr); 335b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 336b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch inline double ReadD(int64_t addr, Instruction* instr); 337b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch inline void WriteD(int64_t addr, double value, Instruction* instr); 338b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 339b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Helper for debugging memory access. 340b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch inline void DieOrDebug(); 341b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 34262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch void TraceRegWr(int64_t value, TraceType t = DWORD); 343b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void TraceMemWr(int64_t addr, int64_t value, TraceType t); 34462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch void TraceMemRd(int64_t addr, int64_t value, TraceType t = DWORD); 345b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 346b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Operations depending on endianness. 347b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Get Double Higher / Lower word. 348b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch inline int32_t GetDoubleHIW(double* addr); 349b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch inline int32_t GetDoubleLOW(double* addr); 350b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Set Double Higher / Lower word. 351b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch inline int32_t SetDoubleHIW(double* addr); 352b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch inline int32_t SetDoubleLOW(double* addr); 353b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 354f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch SimInstruction instr_; 355f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 356014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // functions called from DecodeTypeRegister. 357014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch void DecodeTypeRegisterCOP1(); 358014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 359014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch void DecodeTypeRegisterCOP1X(); 360014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 361014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch void DecodeTypeRegisterSPECIAL(); 362014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 363014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 364014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch void DecodeTypeRegisterSPECIAL2(); 365014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 366014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch void DecodeTypeRegisterSPECIAL3(); 367014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 368014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch void DecodeTypeRegisterSRsType(); 369014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 370014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch void DecodeTypeRegisterDRsType(); 371014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 372014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch void DecodeTypeRegisterWRsType(); 373014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 374014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch void DecodeTypeRegisterLRsType(); 375014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 376b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Executing is handled based on the instruction type. 377f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch void DecodeTypeRegister(); 378014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 379f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch inline int32_t rs_reg() const { return instr_.RsValue(); } 380014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch inline int64_t rs() const { return get_register(rs_reg()); } 381014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch inline uint64_t rs_u() const { 382014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch return static_cast<uint64_t>(get_register(rs_reg())); 383014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 384f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch inline int32_t rt_reg() const { return instr_.RtValue(); } 385014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch inline int64_t rt() const { return get_register(rt_reg()); } 386014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch inline uint64_t rt_u() const { 387014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch return static_cast<uint64_t>(get_register(rt_reg())); 388014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 389f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch inline int32_t rd_reg() const { return instr_.RdValue(); } 390f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch inline int32_t fr_reg() const { return instr_.FrValue(); } 391f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch inline int32_t fs_reg() const { return instr_.FsValue(); } 392f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch inline int32_t ft_reg() const { return instr_.FtValue(); } 393f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch inline int32_t fd_reg() const { return instr_.FdValue(); } 394f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch inline int32_t sa() const { return instr_.SaValue(); } 395f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch inline int32_t lsa_sa() const { return instr_.LsaSaValue(); } 396014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 397014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch inline void SetResult(const int32_t rd_reg, const int64_t alu_out) { 398014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch set_register(rd_reg, alu_out); 399014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch TraceRegWr(alu_out); 400014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 401b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 40262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch inline void SetFPUWordResult(int32_t fd_reg, int32_t alu_out) { 40362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch set_fpu_register_word(fd_reg, alu_out); 40462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch TraceRegWr(get_fpu_register(fd_reg), WORD); 40562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } 40662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 40762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch inline void SetFPUWordResult2(int32_t fd_reg, int32_t alu_out) { 40862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch set_fpu_register_word(fd_reg, alu_out); 40962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch TraceRegWr(get_fpu_register(fd_reg)); 41062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } 41162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 41262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch inline void SetFPUResult(int32_t fd_reg, int64_t alu_out) { 41362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch set_fpu_register(fd_reg, alu_out); 41462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch TraceRegWr(get_fpu_register(fd_reg)); 41562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } 41662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 41762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch inline void SetFPUResult2(int32_t fd_reg, int64_t alu_out) { 41862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch set_fpu_register(fd_reg, alu_out); 41962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch TraceRegWr(get_fpu_register(fd_reg), DOUBLE); 42062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } 42162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 42262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch inline void SetFPUFloatResult(int32_t fd_reg, float alu_out) { 42362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch set_fpu_register_float(fd_reg, alu_out); 42462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch TraceRegWr(get_fpu_register(fd_reg), FLOAT); 42562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } 42662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 42762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch inline void SetFPUDoubleResult(int32_t fd_reg, double alu_out) { 42862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch set_fpu_register_double(fd_reg, alu_out); 42962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch TraceRegWr(get_fpu_register(fd_reg), DOUBLE); 43062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } 43162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 432f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch void DecodeTypeImmediate(); 433f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch void DecodeTypeJump(); 434b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 435b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Used for breakpoints and traps. 436f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch void SoftwareInterrupt(); 437b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 438014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Compact branch guard. 439014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch void CheckForbiddenSlot(int64_t current_pc) { 440014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Instruction* instr_after_compact_branch = 441014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch reinterpret_cast<Instruction*>(current_pc + Instruction::kInstrSize); 442014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (instr_after_compact_branch->IsForbiddenAfterBranch()) { 443014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch V8_Fatal(__FILE__, __LINE__, 444014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch "Error: Unexpected instruction 0x%08x immediately after a " 445014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch "compact branch instruction.", 446014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch *reinterpret_cast<uint32_t*>(instr_after_compact_branch)); 447014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 448014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 449014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 450b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Stop helper functions. 451b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool IsWatchpoint(uint64_t code); 452b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void PrintWatchpoint(uint64_t code); 453b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void HandleStop(uint64_t code, Instruction* instr); 454b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool IsStopInstruction(Instruction* instr); 455b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool IsEnabledStop(uint64_t code); 456b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void EnableStop(uint64_t code); 457b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void DisableStop(uint64_t code); 458b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void IncreaseStopCounter(uint64_t code); 459b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void PrintStopInfo(uint64_t code); 460b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 461b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 462b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Executes one instruction. 463b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void InstructionDecode(Instruction* instr); 464b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Execute one instruction placed in a branch delay slot. 465b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void BranchDelayInstructionDecode(Instruction* instr) { 466b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (instr->InstructionBits() == nopInstr) { 467b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Short-cut generic nop instructions. They are always valid and they 468b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // never change the simulator state. 469b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return; 470b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 471b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 472014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (instr->IsForbiddenAfterBranch()) { 473b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch V8_Fatal(__FILE__, __LINE__, 474b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch "Eror:Unexpected %i opcode in a branch delay slot.", 475b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch instr->OpcodeValue()); 476b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 477b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch InstructionDecode(instr); 478014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch SNPrintF(trace_buf_, " "); 479b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 480b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 481b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // ICache. 482f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch static void CheckICache(base::CustomMatcherHashMap* i_cache, 483f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Instruction* instr); 484f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch static void FlushOnePage(base::CustomMatcherHashMap* i_cache, intptr_t start, 485f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch size_t size); 486f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch static CachePage* GetCachePage(base::CustomMatcherHashMap* i_cache, 487f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch void* page); 488b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 489b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch enum Exception { 490b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch none, 491b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch kIntegerOverflow, 492b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch kIntegerUnderflow, 493b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch kDivideByZero, 494b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch kNumExceptions 495b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch }; 496b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 497b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Exceptions. 498014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch void SignalException(Exception e); 499b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 500b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Runtime call support. 501014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch static void* RedirectExternalReference(Isolate* isolate, 502014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch void* external_function, 503b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExternalReference::Type type); 504b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 505b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Handle arguments and return value for runtime FP functions. 506b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void GetFpArgs(double* x, double* y, int32_t* z); 507b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void SetFpResult(const double& result); 508b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 509b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void CallInternal(byte* entry); 510b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 511b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Architecture state. 512b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Registers. 513b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int64_t registers_[kNumSimuRegisters]; 514b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Coprocessor Registers. 515b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int64_t FPUregisters_[kNumFPURegisters]; 516b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // FPU control register. 517b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch uint32_t FCSR_; 518b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 519b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Simulator support. 520b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Allocate 1MB for stack. 521b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch size_t stack_size_; 522b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch char* stack_; 523b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool pc_modified_; 524b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int64_t icount_; 525b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int break_count_; 526b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmbeddedVector<char, 128> trace_buf_; 527b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 528b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Debugger input. 529b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch char* last_debugger_input_; 530b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 531b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Icache simulation. 532f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch base::CustomMatcherHashMap* i_cache_; 533b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 534b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch v8::internal::Isolate* isolate_; 535b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 536b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Registered breakpoints. 537b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Instruction* break_pc_; 538b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Instr break_instr_; 539b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 540b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Stop is disabled if bit 31 is set. 541b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static const uint32_t kStopDisabledBit = 1 << 31; 542b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 543b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // A stop is enabled, meaning the simulator will stop when meeting the 544b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // instruction, if bit 31 of watched_stops_[code].count is unset. 545b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // The value watched_stops_[code].count & ~(1 << 31) indicates how many times 546b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // the breakpoint was hit or gone through. 547b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch struct StopCountAndDesc { 548b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch uint32_t count; 549b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch char* desc; 550b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch }; 551b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch StopCountAndDesc watched_stops_[kMaxStopCode + 1]; 552b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}; 553b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 554b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 555b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// When running with the simulator transition into simulated execution at this 556b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// point. 557014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#define CALL_GENERATED_CODE(isolate, entry, p0, p1, p2, p3, p4) \ 558014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch reinterpret_cast<Object*>(Simulator::current(isolate)->Call( \ 559014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch FUNCTION_ADDR(entry), 5, reinterpret_cast<int64_t*>(p0), \ 560014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch reinterpret_cast<int64_t*>(p1), reinterpret_cast<int64_t*>(p2), \ 561958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier reinterpret_cast<int64_t*>(p3), reinterpret_cast<int64_t*>(p4))) 562958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 563b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 564014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#define CALL_GENERATED_REGEXP_CODE(isolate, entry, p0, p1, p2, p3, p4, p5, p6, \ 565014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch p7, p8) \ 566014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch static_cast<int>(Simulator::current(isolate)->Call( \ 567014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch entry, 10, p0, p1, p2, p3, p4, reinterpret_cast<int64_t*>(p5), p6, p7, \ 568014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch NULL, p8)) 569b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 570b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 571b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// The simulator has its own stack. Thus it has a different stack limit from 572014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// the C-based native code. The JS-based limit normally points near the end of 573014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// the simulator stack. When the C-based limit is exhausted we reflect that by 574014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// lowering the JS-based limit as well, to make stack checks trigger. 575b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochclass SimulatorStack : public v8::internal::AllStatic { 576b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch public: 577b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static inline uintptr_t JsLimitFromCLimit(Isolate* isolate, 578b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch uintptr_t c_limit) { 579014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch return Simulator::current(isolate)->StackLimit(c_limit); 580b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 581b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 582014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch static inline uintptr_t RegisterCTryCatch(Isolate* isolate, 583014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch uintptr_t try_catch_address) { 584014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Simulator* sim = Simulator::current(isolate); 585b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return sim->PushAddress(try_catch_address); 586b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 587b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 588014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch static inline void UnregisterCTryCatch(Isolate* isolate) { 589014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Simulator::current(isolate)->PopAddress(); 590b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 591b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}; 592b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 593014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} // namespace internal 594014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} // namespace v8 595b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 596b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif // !defined(USE_SIMULATOR) 597b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif // V8_MIPS_SIMULATOR_MIPS_H_ 598