blob: e1c42fdccadc0ce0bcfd0f2662281915020cab01 [file] [log] [blame]
Ben Murdoch257744e2011-11-30 15:57:28 +00001// Copyright 2011 the V8 project authors. All rights reserved.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
Andrei Popescu31002712010-02-23 13:46:05 +00004
5
6// Declares a Simulator for MIPS instructions if we are not generating a native
7// MIPS binary. This Simulator allows us to run and debug MIPS code generation
8// on regular desktop machines.
9// V8 calls into generated code by "calling" the CALL_GENERATED_CODE macro,
10// which will start execution in the Simulator or forwards to the real entry
11// on a MIPS HW platform.
12
13#ifndef V8_MIPS_SIMULATOR_MIPS_H_
14#define V8_MIPS_SIMULATOR_MIPS_H_
15
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016#include "src/allocation.h"
17#include "src/mips/constants-mips.h"
Andrei Popescu31002712010-02-23 13:46:05 +000018
Steve Block44f0eee2011-05-26 01:26:41 +010019#if !defined(USE_SIMULATOR)
20// Running without a simulator on a native mips platform.
21
22namespace v8 {
23namespace internal {
Andrei Popescu31002712010-02-23 13:46:05 +000024
25// When running without a simulator we call the entry directly.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000026#define CALL_GENERATED_CODE(isolate, entry, p0, p1, p2, p3, p4) \
Steve Block44f0eee2011-05-26 01:26:41 +010027 entry(p0, p1, p2, p3, p4)
28
29typedef int (*mips_regexp_matcher)(String*, int, const byte*, const byte*,
Ben Murdochb8a8cc12014-11-26 15:28:44 +000030 void*, int*, int, Address, int, Isolate*);
Ben Murdoch257744e2011-11-30 15:57:28 +000031
Steve Block44f0eee2011-05-26 01:26:41 +010032
33// Call the generated regexp code directly. The code at the entry address
34// should act as a function matching the type arm_regexp_matcher.
35// The fifth argument is a dummy that reserves the space used for
36// the return address added by the ExitFrame in native calls.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000037#define CALL_GENERATED_REGEXP_CODE(isolate, entry, p0, p1, p2, p3, p4, p5, p6, \
38 p7, p8) \
39 (FUNCTION_CAST<mips_regexp_matcher>(entry)(p0, p1, p2, p3, NULL, p4, p5, p6, \
40 p7, p8))
Andrei Popescu31002712010-02-23 13:46:05 +000041
42// The stack limit beyond which we will throw stack overflow errors in
43// generated code. Because generated code on mips uses the C stack, we
44// just use the C stack limit.
45class SimulatorStack : public v8::internal::AllStatic {
46 public:
Ben Murdoch257744e2011-11-30 15:57:28 +000047 static inline uintptr_t JsLimitFromCLimit(Isolate* isolate,
48 uintptr_t c_limit) {
Andrei Popescu31002712010-02-23 13:46:05 +000049 return c_limit;
50 }
51
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000052 static inline uintptr_t RegisterCTryCatch(Isolate* isolate,
53 uintptr_t try_catch_address) {
54 USE(isolate);
Andrei Popescu31002712010-02-23 13:46:05 +000055 return try_catch_address;
56 }
57
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000058 static inline void UnregisterCTryCatch(Isolate* isolate) { USE(isolate); }
Andrei Popescu31002712010-02-23 13:46:05 +000059};
60
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000061} // namespace internal
62} // namespace v8
Steve Block44f0eee2011-05-26 01:26:41 +010063
Andrei Popescu31002712010-02-23 13:46:05 +000064// Calculated the stack limit beyond which we will throw stack overflow errors.
65// This macro must be called from a C++ method. It relies on being able to take
66// the address of "this" to get a value on the current execution stack and then
67// calculates the stack limit based on that value.
68// NOTE: The check for overflow is not safe as there is no guarantee that the
69// running thread has its stack in all memory up to address 0x00000000.
70#define GENERATED_CODE_STACK_LIMIT(limit) \
71 (reinterpret_cast<uintptr_t>(this) >= limit ? \
72 reinterpret_cast<uintptr_t>(this) - limit : 0)
73
Steve Block44f0eee2011-05-26 01:26:41 +010074#else // !defined(USE_SIMULATOR)
75// Running with a simulator.
Andrei Popescu31002712010-02-23 13:46:05 +000076
Ben Murdochb8a8cc12014-11-26 15:28:44 +000077#include "src/assembler.h"
78#include "src/hashmap.h"
Andrei Popescu31002712010-02-23 13:46:05 +000079
Steve Block44f0eee2011-05-26 01:26:41 +010080namespace v8 {
81namespace internal {
Andrei Popescu31002712010-02-23 13:46:05 +000082
Steve Block44f0eee2011-05-26 01:26:41 +010083// -----------------------------------------------------------------------------
84// Utility functions
Andrei Popescu31002712010-02-23 13:46:05 +000085
Steve Block44f0eee2011-05-26 01:26:41 +010086class CachePage {
87 public:
88 static const int LINE_VALID = 0;
89 static const int LINE_INVALID = 1;
Andrei Popescu31002712010-02-23 13:46:05 +000090
Steve Block44f0eee2011-05-26 01:26:41 +010091 static const int kPageShift = 12;
92 static const int kPageSize = 1 << kPageShift;
93 static const int kPageMask = kPageSize - 1;
94 static const int kLineShift = 2; // The cache line is only 4 bytes right now.
95 static const int kLineLength = 1 << kLineShift;
96 static const int kLineMask = kLineLength - 1;
Andrei Popescu31002712010-02-23 13:46:05 +000097
Steve Block44f0eee2011-05-26 01:26:41 +010098 CachePage() {
99 memset(&validity_map_, LINE_INVALID, sizeof(validity_map_));
100 }
Andrei Popescu31002712010-02-23 13:46:05 +0000101
Steve Block44f0eee2011-05-26 01:26:41 +0100102 char* ValidityByte(int offset) {
103 return &validity_map_[offset >> kLineShift];
104 }
Andrei Popescu31002712010-02-23 13:46:05 +0000105
Steve Block44f0eee2011-05-26 01:26:41 +0100106 char* CachedData(int offset) {
107 return &data_[offset];
108 }
109
110 private:
111 char data_[kPageSize]; // The cached data.
112 static const int kValidityMapSize = kPageSize >> kLineShift;
113 char validity_map_[kValidityMapSize]; // One byte per line.
114};
Andrei Popescu31002712010-02-23 13:46:05 +0000115
116class Simulator {
117 public:
Steve Block44f0eee2011-05-26 01:26:41 +0100118 friend class MipsDebugger;
Andrei Popescu31002712010-02-23 13:46:05 +0000119
120 // Registers are declared in order. See SMRL chapter 2.
121 enum Register {
122 no_reg = -1,
123 zero_reg = 0,
124 at,
125 v0, v1,
126 a0, a1, a2, a3,
127 t0, t1, t2, t3, t4, t5, t6, t7,
128 s0, s1, s2, s3, s4, s5, s6, s7,
129 t8, t9,
130 k0, k1,
131 gp,
132 sp,
133 s8,
134 ra,
Ben Murdoch257744e2011-11-30 15:57:28 +0000135 // LO, HI, and pc.
Andrei Popescu31002712010-02-23 13:46:05 +0000136 LO,
137 HI,
138 pc, // pc must be the last register.
139 kNumSimuRegisters,
140 // aliases
141 fp = s8
142 };
143
144 // Coprocessor registers.
145 // Generated code will always use doubles. So we will only use even registers.
146 enum FPURegister {
147 f0, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11,
Ben Murdoch257744e2011-11-30 15:57:28 +0000148 f12, f13, f14, f15, // f12 and f14 are arguments FPURegisters.
Andrei Popescu31002712010-02-23 13:46:05 +0000149 f16, f17, f18, f19, f20, f21, f22, f23, f24, f25,
150 f26, f27, f28, f29, f30, f31,
151 kNumFPURegisters
152 };
153
Ben Murdoch257744e2011-11-30 15:57:28 +0000154 explicit Simulator(Isolate* isolate);
Andrei Popescu31002712010-02-23 13:46:05 +0000155 ~Simulator();
156
157 // The currently executing Simulator instance. Potentially there can be one
158 // for each native thread.
Steve Block44f0eee2011-05-26 01:26:41 +0100159 static Simulator* current(v8::internal::Isolate* isolate);
Andrei Popescu31002712010-02-23 13:46:05 +0000160
161 // Accessors for register state. Reading the pc value adheres to the MIPS
162 // architecture specification and is off by a 8 from the currently executing
163 // instruction.
164 void set_register(int reg, int32_t value);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000165 void set_dw_register(int dreg, const int* dbl);
Andrei Popescu31002712010-02-23 13:46:05 +0000166 int32_t get_register(int reg) const;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000167 double get_double_from_register_pair(int reg);
Ben Murdoch257744e2011-11-30 15:57:28 +0000168 // Same for FPURegisters.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000169 void set_fpu_register(int fpureg, int64_t value);
170 void set_fpu_register_word(int fpureg, int32_t value);
171 void set_fpu_register_hi_word(int fpureg, int32_t value);
Steve Block44f0eee2011-05-26 01:26:41 +0100172 void set_fpu_register_float(int fpureg, float value);
Andrei Popescu31002712010-02-23 13:46:05 +0000173 void set_fpu_register_double(int fpureg, double value);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000174 void set_fpu_register_invalid_result64(float original, float rounded);
175 void set_fpu_register_invalid_result(float original, float rounded);
176 void set_fpu_register_word_invalid_result(float original, float rounded);
177 void set_fpu_register_invalid_result64(double original, double rounded);
178 void set_fpu_register_invalid_result(double original, double rounded);
179 void set_fpu_register_word_invalid_result(double original, double rounded);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000180 int64_t get_fpu_register(int fpureg) const;
181 int32_t get_fpu_register_word(int fpureg) const;
182 int32_t get_fpu_register_signed_word(int fpureg) const;
183 int32_t get_fpu_register_hi_word(int fpureg) const;
Steve Block44f0eee2011-05-26 01:26:41 +0100184 float get_fpu_register_float(int fpureg) const;
Andrei Popescu31002712010-02-23 13:46:05 +0000185 double get_fpu_register_double(int fpureg) const;
Steve Block44f0eee2011-05-26 01:26:41 +0100186 void set_fcsr_bit(uint32_t cc, bool value);
187 bool test_fcsr_bit(uint32_t cc);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000188 void set_fcsr_rounding_mode(FPURoundingMode mode);
189 unsigned int get_fcsr_rounding_mode();
Steve Block44f0eee2011-05-26 01:26:41 +0100190 bool set_fcsr_round_error(double original, double rounded);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000191 bool set_fcsr_round_error(float original, float rounded);
192 bool set_fcsr_round64_error(double original, double rounded);
193 bool set_fcsr_round64_error(float original, float rounded);
194 void round_according_to_fcsr(double toRound, double& rounded,
195 int32_t& rounded_int, double fs);
196 void round_according_to_fcsr(float toRound, float& rounded,
197 int32_t& rounded_int, float fs);
198 void round64_according_to_fcsr(double toRound, double& rounded,
199 int64_t& rounded_int, double fs);
200 void round64_according_to_fcsr(float toRound, float& rounded,
201 int64_t& rounded_int, float fs);
Andrei Popescu31002712010-02-23 13:46:05 +0000202 // Special case of set_register and get_register to access the raw PC value.
203 void set_pc(int32_t value);
204 int32_t get_pc() const;
205
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000206 Address get_sp() const {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000207 return reinterpret_cast<Address>(static_cast<intptr_t>(get_register(sp)));
208 }
209
Andrei Popescu31002712010-02-23 13:46:05 +0000210 // Accessor to the internal simulator stack area.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000211 uintptr_t StackLimit(uintptr_t c_limit) const;
Andrei Popescu31002712010-02-23 13:46:05 +0000212
213 // Executes MIPS instructions until the PC reaches end_sim_pc.
214 void Execute();
215
216 // Call on program start.
Ben Murdoch257744e2011-11-30 15:57:28 +0000217 static void Initialize(Isolate* isolate);
Andrei Popescu31002712010-02-23 13:46:05 +0000218
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000219 static void TearDown(HashMap* i_cache, Redirection* first);
220
Andrei Popescu31002712010-02-23 13:46:05 +0000221 // V8 generally calls into generated JS code with 5 parameters and into
222 // generated RegExp code with 7 parameters. This is a convenience function,
223 // which sets up the simulator state and grabs the result on return.
Steve Block44f0eee2011-05-26 01:26:41 +0100224 int32_t Call(byte* entry, int argument_count, ...);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000225 // Alternative: call a 2-argument double function.
226 double CallFP(byte* entry, double d0, double d1);
Andrei Popescu31002712010-02-23 13:46:05 +0000227
228 // Push an address onto the JS stack.
229 uintptr_t PushAddress(uintptr_t address);
230
231 // Pop an address from the JS stack.
232 uintptr_t PopAddress();
233
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100234 // Debugger input.
235 void set_last_debugger_input(char* input);
236 char* last_debugger_input() { return last_debugger_input_; }
237
Steve Block44f0eee2011-05-26 01:26:41 +0100238 // ICache checking.
239 static void FlushICache(v8::internal::HashMap* i_cache, void* start,
240 size_t size);
241
242 // Returns true if pc register contains one of the 'special_values' defined
243 // below (bad_ra, end_sim_pc).
244 bool has_bad_pc() const;
245
Andrei Popescu31002712010-02-23 13:46:05 +0000246 private:
247 enum special_values {
248 // Known bad pc value to ensure that the simulator does not execute
249 // without being properly setup.
250 bad_ra = -1,
251 // A pc value used to signal the simulator to stop execution. Generally
252 // the ra is set to this value on transition from native C code to
253 // simulated execution, so that the simulator can "return" to the native
254 // C code.
255 end_sim_pc = -2,
256 // Unpredictable value.
257 Unpredictable = 0xbadbeaf
258 };
259
260 // Unsupported instructions use Format to print an error and stop execution.
261 void Format(Instruction* instr, const char* format);
262
263 // Read and write memory.
264 inline uint32_t ReadBU(int32_t addr);
265 inline int32_t ReadB(int32_t addr);
266 inline void WriteB(int32_t addr, uint8_t value);
267 inline void WriteB(int32_t addr, int8_t value);
268
269 inline uint16_t ReadHU(int32_t addr, Instruction* instr);
270 inline int16_t ReadH(int32_t addr, Instruction* instr);
271 // Note: Overloaded on the sign of the value.
272 inline void WriteH(int32_t addr, uint16_t value, Instruction* instr);
273 inline void WriteH(int32_t addr, int16_t value, Instruction* instr);
274
275 inline int ReadW(int32_t addr, Instruction* instr);
276 inline void WriteW(int32_t addr, int value, Instruction* instr);
277
278 inline double ReadD(int32_t addr, Instruction* instr);
279 inline void WriteD(int32_t addr, double value, Instruction* instr);
280
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000281 // Helpers for data value tracing.
282 enum TraceType {
283 BYTE,
284 HALF,
285 WORD
286 // DWORD,
287 // DFLOAT - Floats may have printing issues due to paired lwc1's
288 };
289
290 void TraceRegWr(int32_t value);
291 void TraceMemWr(int32_t addr, int32_t value, TraceType t);
292 void TraceMemRd(int32_t addr, int32_t value);
293 EmbeddedVector<char, 128> trace_buf_;
294
Andrei Popescu31002712010-02-23 13:46:05 +0000295 // Operations depending on endianness.
296 // Get Double Higher / Lower word.
297 inline int32_t GetDoubleHIW(double* addr);
298 inline int32_t GetDoubleLOW(double* addr);
299 // Set Double Higher / Lower word.
300 inline int32_t SetDoubleHIW(double* addr);
301 inline int32_t SetDoubleLOW(double* addr);
302
Andrei Popescu31002712010-02-23 13:46:05 +0000303 // Executing is handled based on the instruction type.
304 void DecodeTypeRegister(Instruction* instr);
Steve Block44f0eee2011-05-26 01:26:41 +0100305
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000306 // Functions called from DecodeTypeRegister.
307 void DecodeTypeRegisterCOP1();
308
309 void DecodeTypeRegisterCOP1X();
310
311 void DecodeTypeRegisterSPECIAL();
312
313 void DecodeTypeRegisterSPECIAL2();
314
315 void DecodeTypeRegisterSPECIAL3();
316
317 // Called from DecodeTypeRegisterCOP1.
318 void DecodeTypeRegisterSRsType();
319
320 void DecodeTypeRegisterDRsType();
321
322 void DecodeTypeRegisterWRsType();
323
324 void DecodeTypeRegisterLRsType();
325
326 Instruction* currentInstr_;
327
328 inline Instruction* get_instr() const { return currentInstr_; }
329 inline void set_instr(Instruction* instr) { currentInstr_ = instr; }
330
331 inline int32_t rs_reg() const { return currentInstr_->RsValue(); }
332 inline int32_t rs() const { return get_register(rs_reg()); }
333 inline uint32_t rs_u() const {
334 return static_cast<uint32_t>(get_register(rs_reg()));
335 }
336 inline int32_t rt_reg() const { return currentInstr_->RtValue(); }
337 inline int32_t rt() const { return get_register(rt_reg()); }
338 inline uint32_t rt_u() const {
339 return static_cast<uint32_t>(get_register(rt_reg()));
340 }
341 inline int32_t rd_reg() const { return currentInstr_->RdValue(); }
342 inline int32_t fr_reg() const { return currentInstr_->FrValue(); }
343 inline int32_t fs_reg() const { return currentInstr_->FsValue(); }
344 inline int32_t ft_reg() const { return currentInstr_->FtValue(); }
345 inline int32_t fd_reg() const { return currentInstr_->FdValue(); }
346 inline int32_t sa() const { return currentInstr_->SaValue(); }
347 inline int32_t lsa_sa() const { return currentInstr_->LsaSaValue(); }
348
349 inline void SetResult(int32_t rd_reg, int32_t alu_out) {
350 set_register(rd_reg, alu_out);
351 TraceRegWr(alu_out);
352 }
Steve Block44f0eee2011-05-26 01:26:41 +0100353
Andrei Popescu31002712010-02-23 13:46:05 +0000354 void DecodeTypeImmediate(Instruction* instr);
355 void DecodeTypeJump(Instruction* instr);
356
357 // Used for breakpoints and traps.
358 void SoftwareInterrupt(Instruction* instr);
359
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000360 // Compact branch guard.
361 void CheckForbiddenSlot(int32_t current_pc) {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100362 Instruction* instr_after_compact_branch =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000363 reinterpret_cast<Instruction*>(current_pc + Instruction::kInstrSize);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100364 if (instr_after_compact_branch->IsForbiddenAfterBranch()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000365 V8_Fatal(__FILE__, __LINE__,
366 "Error: Unexpected instruction 0x%08x immediately after a "
367 "compact branch instruction.",
Ben Murdoch097c5b22016-05-18 11:27:45 +0100368 *reinterpret_cast<uint32_t*>(instr_after_compact_branch));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000369 }
370 }
371
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000372 // Stop helper functions.
373 bool IsWatchpoint(uint32_t code);
374 void PrintWatchpoint(uint32_t code);
375 void HandleStop(uint32_t code, Instruction* instr);
376 bool IsStopInstruction(Instruction* instr);
377 bool IsEnabledStop(uint32_t code);
378 void EnableStop(uint32_t code);
379 void DisableStop(uint32_t code);
380 void IncreaseStopCounter(uint32_t code);
381 void PrintStopInfo(uint32_t code);
382
383
Andrei Popescu31002712010-02-23 13:46:05 +0000384 // Executes one instruction.
385 void InstructionDecode(Instruction* instr);
386 // Execute one instruction placed in a branch delay slot.
387 void BranchDelayInstructionDecode(Instruction* instr) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100388 if (instr->InstructionBits() == nopInstr) {
389 // Short-cut generic nop instructions. They are always valid and they
390 // never change the simulator state.
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100391 return;
392 }
393
Andrei Popescu31002712010-02-23 13:46:05 +0000394 if (instr->IsForbiddenInBranchDelay()) {
395 V8_Fatal(__FILE__, __LINE__,
396 "Eror:Unexpected %i opcode in a branch delay slot.",
Steve Block44f0eee2011-05-26 01:26:41 +0100397 instr->OpcodeValue());
Andrei Popescu31002712010-02-23 13:46:05 +0000398 }
399 InstructionDecode(instr);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000400 SNPrintF(trace_buf_, " ");
Andrei Popescu31002712010-02-23 13:46:05 +0000401 }
402
Steve Block44f0eee2011-05-26 01:26:41 +0100403 // ICache.
404 static void CheckICache(v8::internal::HashMap* i_cache, Instruction* instr);
405 static void FlushOnePage(v8::internal::HashMap* i_cache, intptr_t start,
406 int size);
407 static CachePage* GetCachePage(v8::internal::HashMap* i_cache, void* page);
408
Andrei Popescu31002712010-02-23 13:46:05 +0000409 enum Exception {
410 none,
411 kIntegerOverflow,
412 kIntegerUnderflow,
413 kDivideByZero,
414 kNumExceptions
415 };
Andrei Popescu31002712010-02-23 13:46:05 +0000416
417 // Exceptions.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000418 void SignalException(Exception e);
Andrei Popescu31002712010-02-23 13:46:05 +0000419
420 // Runtime call support.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000421 static void* RedirectExternalReference(Isolate* isolate,
422 void* external_function,
Steve Block44f0eee2011-05-26 01:26:41 +0100423 ExternalReference::Type type);
Andrei Popescu31002712010-02-23 13:46:05 +0000424
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000425 // Handle arguments and return value for runtime FP functions.
426 void GetFpArgs(double* x, double* y, int32_t* z);
Ben Murdoch257744e2011-11-30 15:57:28 +0000427 void SetFpResult(const double& result);
428
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000429 void CallInternal(byte* entry);
Andrei Popescu31002712010-02-23 13:46:05 +0000430
431 // Architecture state.
432 // Registers.
433 int32_t registers_[kNumSimuRegisters];
434 // Coprocessor Registers.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000435 // Note: FP32 mode uses only the lower 32-bit part of each element,
436 // the upper 32-bit is unpredictable.
437 int64_t FPUregisters_[kNumFPURegisters];
Steve Block44f0eee2011-05-26 01:26:41 +0100438 // FPU control register.
439 uint32_t FCSR_;
Andrei Popescu31002712010-02-23 13:46:05 +0000440
441 // Simulator support.
Ben Murdoch257744e2011-11-30 15:57:28 +0000442 // Allocate 1MB for stack.
443 static const size_t stack_size_ = 1 * 1024*1024;
Andrei Popescu31002712010-02-23 13:46:05 +0000444 char* stack_;
445 bool pc_modified_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000446 uint64_t icount_;
Steve Block44f0eee2011-05-26 01:26:41 +0100447 int break_count_;
448
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100449 // Debugger input.
450 char* last_debugger_input_;
451
Ben Murdoch257744e2011-11-30 15:57:28 +0000452 // Icache simulation.
Steve Block44f0eee2011-05-26 01:26:41 +0100453 v8::internal::HashMap* i_cache_;
Andrei Popescu31002712010-02-23 13:46:05 +0000454
Ben Murdoch257744e2011-11-30 15:57:28 +0000455 v8::internal::Isolate* isolate_;
456
Andrei Popescu31002712010-02-23 13:46:05 +0000457 // Registered breakpoints.
458 Instruction* break_pc_;
459 Instr break_instr_;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000460
461 // Stop is disabled if bit 31 is set.
462 static const uint32_t kStopDisabledBit = 1 << 31;
463
464 // A stop is enabled, meaning the simulator will stop when meeting the
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000465 // instruction, if bit 31 of watched_stops_[code].count is unset.
466 // The value watched_stops_[code].count & ~(1 << 31) indicates how many times
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000467 // the breakpoint was hit or gone through.
468 struct StopCountAndDesc {
469 uint32_t count;
470 char* desc;
471 };
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000472 StopCountAndDesc watched_stops_[kMaxStopCode + 1];
Andrei Popescu31002712010-02-23 13:46:05 +0000473};
474
Steve Block44f0eee2011-05-26 01:26:41 +0100475
476// When running with the simulator transition into simulated execution at this
477// point.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000478#define CALL_GENERATED_CODE(isolate, entry, p0, p1, p2, p3, p4) \
479 reinterpret_cast<Object*>(Simulator::current(isolate)->Call( \
Steve Block44f0eee2011-05-26 01:26:41 +0100480 FUNCTION_ADDR(entry), 5, p0, p1, p2, p3, p4))
481
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000482#define CALL_GENERATED_REGEXP_CODE(isolate, entry, p0, p1, p2, p3, p4, p5, p6, \
483 p7, p8) \
484 Simulator::current(isolate) \
485 ->Call(entry, 10, p0, p1, p2, p3, NULL, p4, p5, p6, p7, p8)
Andrei Popescu31002712010-02-23 13:46:05 +0000486
487
488// The simulator has its own stack. Thus it has a different stack limit from
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000489// the C-based native code. The JS-based limit normally points near the end of
490// the simulator stack. When the C-based limit is exhausted we reflect that by
491// lowering the JS-based limit as well, to make stack checks trigger.
Andrei Popescu31002712010-02-23 13:46:05 +0000492class SimulatorStack : public v8::internal::AllStatic {
493 public:
Ben Murdoch257744e2011-11-30 15:57:28 +0000494 static inline uintptr_t JsLimitFromCLimit(Isolate* isolate,
495 uintptr_t c_limit) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000496 return Simulator::current(isolate)->StackLimit(c_limit);
Andrei Popescu31002712010-02-23 13:46:05 +0000497 }
498
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000499 static inline uintptr_t RegisterCTryCatch(Isolate* isolate,
500 uintptr_t try_catch_address) {
501 Simulator* sim = Simulator::current(isolate);
Andrei Popescu31002712010-02-23 13:46:05 +0000502 return sim->PushAddress(try_catch_address);
503 }
504
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000505 static inline void UnregisterCTryCatch(Isolate* isolate) {
506 Simulator::current(isolate)->PopAddress();
Andrei Popescu31002712010-02-23 13:46:05 +0000507 }
508};
509
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000510} // namespace internal
511} // namespace v8
Andrei Popescu31002712010-02-23 13:46:05 +0000512
Steve Block44f0eee2011-05-26 01:26:41 +0100513#endif // !defined(USE_SIMULATOR)
Andrei Popescu31002712010-02-23 13:46:05 +0000514#endif // V8_MIPS_SIMULATOR_MIPS_H_