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