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