blob: 5c77756394e24d55fe15af266d91dea9add0e4f9 [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"
Ben Murdoch61f157c2016-09-16 13:49:30 +010078#include "src/base/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 Murdoch61f157c2016-09-16 13:49:30 +0100219 static void TearDown(base::HashMap* i_cache, Redirection* first);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000220
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.
Ben Murdoch61f157c2016-09-16 13:49:30 +0100239 static void FlushICache(base::HashMap* i_cache, void* start, size_t size);
Steve Block44f0eee2011-05-26 01:26:41 +0100240
241 // Returns true if pc register contains one of the 'special_values' defined
242 // below (bad_ra, end_sim_pc).
243 bool has_bad_pc() const;
244
Andrei Popescu31002712010-02-23 13:46:05 +0000245 private:
246 enum special_values {
247 // Known bad pc value to ensure that the simulator does not execute
248 // without being properly setup.
249 bad_ra = -1,
250 // A pc value used to signal the simulator to stop execution. Generally
251 // the ra is set to this value on transition from native C code to
252 // simulated execution, so that the simulator can "return" to the native
253 // C code.
254 end_sim_pc = -2,
255 // Unpredictable value.
256 Unpredictable = 0xbadbeaf
257 };
258
259 // Unsupported instructions use Format to print an error and stop execution.
260 void Format(Instruction* instr, const char* format);
261
262 // Read and write memory.
263 inline uint32_t ReadBU(int32_t addr);
264 inline int32_t ReadB(int32_t addr);
265 inline void WriteB(int32_t addr, uint8_t value);
266 inline void WriteB(int32_t addr, int8_t value);
267
268 inline uint16_t ReadHU(int32_t addr, Instruction* instr);
269 inline int16_t ReadH(int32_t addr, Instruction* instr);
270 // Note: Overloaded on the sign of the value.
271 inline void WriteH(int32_t addr, uint16_t value, Instruction* instr);
272 inline void WriteH(int32_t addr, int16_t value, Instruction* instr);
273
274 inline int ReadW(int32_t addr, Instruction* instr);
275 inline void WriteW(int32_t addr, int value, Instruction* instr);
276
277 inline double ReadD(int32_t addr, Instruction* instr);
278 inline void WriteD(int32_t addr, double value, Instruction* instr);
279
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000280 // Helpers for data value tracing.
281 enum TraceType {
282 BYTE,
283 HALF,
284 WORD
285 // DWORD,
286 // DFLOAT - Floats may have printing issues due to paired lwc1's
287 };
288
289 void TraceRegWr(int32_t value);
290 void TraceMemWr(int32_t addr, int32_t value, TraceType t);
291 void TraceMemRd(int32_t addr, int32_t value);
292 EmbeddedVector<char, 128> trace_buf_;
293
Andrei Popescu31002712010-02-23 13:46:05 +0000294 // Operations depending on endianness.
295 // Get Double Higher / Lower word.
296 inline int32_t GetDoubleHIW(double* addr);
297 inline int32_t GetDoubleLOW(double* addr);
298 // Set Double Higher / Lower word.
299 inline int32_t SetDoubleHIW(double* addr);
300 inline int32_t SetDoubleLOW(double* addr);
301
Andrei Popescu31002712010-02-23 13:46:05 +0000302 // Executing is handled based on the instruction type.
303 void DecodeTypeRegister(Instruction* instr);
Steve Block44f0eee2011-05-26 01:26:41 +0100304
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000305 // Functions called from DecodeTypeRegister.
306 void DecodeTypeRegisterCOP1();
307
308 void DecodeTypeRegisterCOP1X();
309
310 void DecodeTypeRegisterSPECIAL();
311
312 void DecodeTypeRegisterSPECIAL2();
313
314 void DecodeTypeRegisterSPECIAL3();
315
316 // Called from DecodeTypeRegisterCOP1.
317 void DecodeTypeRegisterSRsType();
318
319 void DecodeTypeRegisterDRsType();
320
321 void DecodeTypeRegisterWRsType();
322
323 void DecodeTypeRegisterLRsType();
324
325 Instruction* currentInstr_;
326
327 inline Instruction* get_instr() const { return currentInstr_; }
328 inline void set_instr(Instruction* instr) { currentInstr_ = instr; }
329
330 inline int32_t rs_reg() const { return currentInstr_->RsValue(); }
331 inline int32_t rs() const { return get_register(rs_reg()); }
332 inline uint32_t rs_u() const {
333 return static_cast<uint32_t>(get_register(rs_reg()));
334 }
335 inline int32_t rt_reg() const { return currentInstr_->RtValue(); }
336 inline int32_t rt() const { return get_register(rt_reg()); }
337 inline uint32_t rt_u() const {
338 return static_cast<uint32_t>(get_register(rt_reg()));
339 }
340 inline int32_t rd_reg() const { return currentInstr_->RdValue(); }
341 inline int32_t fr_reg() const { return currentInstr_->FrValue(); }
342 inline int32_t fs_reg() const { return currentInstr_->FsValue(); }
343 inline int32_t ft_reg() const { return currentInstr_->FtValue(); }
344 inline int32_t fd_reg() const { return currentInstr_->FdValue(); }
345 inline int32_t sa() const { return currentInstr_->SaValue(); }
346 inline int32_t lsa_sa() const { return currentInstr_->LsaSaValue(); }
347
348 inline void SetResult(int32_t rd_reg, int32_t alu_out) {
349 set_register(rd_reg, alu_out);
350 TraceRegWr(alu_out);
351 }
Steve Block44f0eee2011-05-26 01:26:41 +0100352
Andrei Popescu31002712010-02-23 13:46:05 +0000353 void DecodeTypeImmediate(Instruction* instr);
354 void DecodeTypeJump(Instruction* instr);
355
356 // Used for breakpoints and traps.
357 void SoftwareInterrupt(Instruction* instr);
358
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000359 // Compact branch guard.
360 void CheckForbiddenSlot(int32_t current_pc) {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100361 Instruction* instr_after_compact_branch =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000362 reinterpret_cast<Instruction*>(current_pc + Instruction::kInstrSize);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100363 if (instr_after_compact_branch->IsForbiddenAfterBranch()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000364 V8_Fatal(__FILE__, __LINE__,
365 "Error: Unexpected instruction 0x%08x immediately after a "
366 "compact branch instruction.",
Ben Murdoch097c5b22016-05-18 11:27:45 +0100367 *reinterpret_cast<uint32_t*>(instr_after_compact_branch));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000368 }
369 }
370
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000371 // Stop helper functions.
372 bool IsWatchpoint(uint32_t code);
373 void PrintWatchpoint(uint32_t code);
374 void HandleStop(uint32_t code, Instruction* instr);
375 bool IsStopInstruction(Instruction* instr);
376 bool IsEnabledStop(uint32_t code);
377 void EnableStop(uint32_t code);
378 void DisableStop(uint32_t code);
379 void IncreaseStopCounter(uint32_t code);
380 void PrintStopInfo(uint32_t code);
381
382
Andrei Popescu31002712010-02-23 13:46:05 +0000383 // Executes one instruction.
384 void InstructionDecode(Instruction* instr);
385 // Execute one instruction placed in a branch delay slot.
386 void BranchDelayInstructionDecode(Instruction* instr) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100387 if (instr->InstructionBits() == nopInstr) {
388 // Short-cut generic nop instructions. They are always valid and they
389 // never change the simulator state.
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100390 return;
391 }
392
Andrei Popescu31002712010-02-23 13:46:05 +0000393 if (instr->IsForbiddenInBranchDelay()) {
394 V8_Fatal(__FILE__, __LINE__,
395 "Eror:Unexpected %i opcode in a branch delay slot.",
Steve Block44f0eee2011-05-26 01:26:41 +0100396 instr->OpcodeValue());
Andrei Popescu31002712010-02-23 13:46:05 +0000397 }
398 InstructionDecode(instr);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000399 SNPrintF(trace_buf_, " ");
Andrei Popescu31002712010-02-23 13:46:05 +0000400 }
401
Steve Block44f0eee2011-05-26 01:26:41 +0100402 // ICache.
Ben Murdoch61f157c2016-09-16 13:49:30 +0100403 static void CheckICache(base::HashMap* i_cache, Instruction* instr);
404 static void FlushOnePage(base::HashMap* i_cache, intptr_t start, int size);
405 static CachePage* GetCachePage(base::HashMap* i_cache, void* page);
Steve Block44f0eee2011-05-26 01:26:41 +0100406
Andrei Popescu31002712010-02-23 13:46:05 +0000407 enum Exception {
408 none,
409 kIntegerOverflow,
410 kIntegerUnderflow,
411 kDivideByZero,
412 kNumExceptions
413 };
Andrei Popescu31002712010-02-23 13:46:05 +0000414
415 // Exceptions.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000416 void SignalException(Exception e);
Andrei Popescu31002712010-02-23 13:46:05 +0000417
418 // Runtime call support.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000419 static void* RedirectExternalReference(Isolate* isolate,
420 void* external_function,
Steve Block44f0eee2011-05-26 01:26:41 +0100421 ExternalReference::Type type);
Andrei Popescu31002712010-02-23 13:46:05 +0000422
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000423 // Handle arguments and return value for runtime FP functions.
424 void GetFpArgs(double* x, double* y, int32_t* z);
Ben Murdoch257744e2011-11-30 15:57:28 +0000425 void SetFpResult(const double& result);
426
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000427 void CallInternal(byte* entry);
Andrei Popescu31002712010-02-23 13:46:05 +0000428
429 // Architecture state.
430 // Registers.
431 int32_t registers_[kNumSimuRegisters];
432 // Coprocessor Registers.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000433 // Note: FP32 mode uses only the lower 32-bit part of each element,
434 // the upper 32-bit is unpredictable.
435 int64_t FPUregisters_[kNumFPURegisters];
Steve Block44f0eee2011-05-26 01:26:41 +0100436 // FPU control register.
437 uint32_t FCSR_;
Andrei Popescu31002712010-02-23 13:46:05 +0000438
439 // Simulator support.
Ben Murdoch257744e2011-11-30 15:57:28 +0000440 // Allocate 1MB for stack.
441 static const size_t stack_size_ = 1 * 1024*1024;
Andrei Popescu31002712010-02-23 13:46:05 +0000442 char* stack_;
443 bool pc_modified_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000444 uint64_t icount_;
Steve Block44f0eee2011-05-26 01:26:41 +0100445 int break_count_;
446
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100447 // Debugger input.
448 char* last_debugger_input_;
449
Ben Murdoch257744e2011-11-30 15:57:28 +0000450 // Icache simulation.
Ben Murdoch61f157c2016-09-16 13:49:30 +0100451 base::HashMap* i_cache_;
Andrei Popescu31002712010-02-23 13:46:05 +0000452
Ben Murdoch257744e2011-11-30 15:57:28 +0000453 v8::internal::Isolate* isolate_;
454
Andrei Popescu31002712010-02-23 13:46:05 +0000455 // Registered breakpoints.
456 Instruction* break_pc_;
457 Instr break_instr_;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000458
459 // Stop is disabled if bit 31 is set.
460 static const uint32_t kStopDisabledBit = 1 << 31;
461
462 // A stop is enabled, meaning the simulator will stop when meeting the
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000463 // instruction, if bit 31 of watched_stops_[code].count is unset.
464 // The value watched_stops_[code].count & ~(1 << 31) indicates how many times
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000465 // the breakpoint was hit or gone through.
466 struct StopCountAndDesc {
467 uint32_t count;
468 char* desc;
469 };
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000470 StopCountAndDesc watched_stops_[kMaxStopCode + 1];
Andrei Popescu31002712010-02-23 13:46:05 +0000471};
472
Steve Block44f0eee2011-05-26 01:26:41 +0100473
474// When running with the simulator transition into simulated execution at this
475// point.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000476#define CALL_GENERATED_CODE(isolate, entry, p0, p1, p2, p3, p4) \
477 reinterpret_cast<Object*>(Simulator::current(isolate)->Call( \
Steve Block44f0eee2011-05-26 01:26:41 +0100478 FUNCTION_ADDR(entry), 5, p0, p1, p2, p3, p4))
479
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000480#define CALL_GENERATED_REGEXP_CODE(isolate, entry, p0, p1, p2, p3, p4, p5, p6, \
481 p7, p8) \
482 Simulator::current(isolate) \
483 ->Call(entry, 10, p0, p1, p2, p3, NULL, p4, p5, p6, p7, p8)
Andrei Popescu31002712010-02-23 13:46:05 +0000484
485
486// The simulator has its own stack. Thus it has a different stack limit from
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000487// the C-based native code. The JS-based limit normally points near the end of
488// the simulator stack. When the C-based limit is exhausted we reflect that by
489// lowering the JS-based limit as well, to make stack checks trigger.
Andrei Popescu31002712010-02-23 13:46:05 +0000490class SimulatorStack : public v8::internal::AllStatic {
491 public:
Ben Murdoch257744e2011-11-30 15:57:28 +0000492 static inline uintptr_t JsLimitFromCLimit(Isolate* isolate,
493 uintptr_t c_limit) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000494 return Simulator::current(isolate)->StackLimit(c_limit);
Andrei Popescu31002712010-02-23 13:46:05 +0000495 }
496
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000497 static inline uintptr_t RegisterCTryCatch(Isolate* isolate,
498 uintptr_t try_catch_address) {
499 Simulator* sim = Simulator::current(isolate);
Andrei Popescu31002712010-02-23 13:46:05 +0000500 return sim->PushAddress(try_catch_address);
501 }
502
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000503 static inline void UnregisterCTryCatch(Isolate* isolate) {
504 Simulator::current(isolate)->PopAddress();
Andrei Popescu31002712010-02-23 13:46:05 +0000505 }
506};
507
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000508} // namespace internal
509} // namespace v8
Andrei Popescu31002712010-02-23 13:46:05 +0000510
Steve Block44f0eee2011-05-26 01:26:41 +0100511#endif // !defined(USE_SIMULATOR)
Andrei Popescu31002712010-02-23 13:46:05 +0000512#endif // V8_MIPS_SIMULATOR_MIPS_H_