blob: 1d156d860f694d7d61284514dfec514583256a62 [file] [log] [blame]
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001// Copyright 2011 the V8 project authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
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
16#include "src/allocation.h"
17#include "src/mips64/constants-mips64.h"
18
19#if !defined(USE_SIMULATOR)
20// Running without a simulator on a native mips platform.
21
22namespace v8 {
23namespace internal {
24
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) \
Ben Murdochb8a8cc12014-11-26 15:28:44 +000027 entry(p0, p1, p2, p3, p4)
28
29
30// Call the generated regexp code directly. The code at the entry address
31// should act as a function matching the type arm_regexp_matcher.
32// The fifth (or ninth) argument is a dummy that reserves the space used for
33// the return address added by the ExitFrame in native calls.
34#ifdef MIPS_ABI_N64
35typedef int (*mips_regexp_matcher)(String* input,
36 int64_t start_offset,
37 const byte* input_start,
38 const byte* input_end,
39 int* output,
40 int64_t output_size,
41 Address stack_base,
42 int64_t direct_call,
43 void* return_address,
44 Isolate* isolate);
45
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000046#define CALL_GENERATED_REGEXP_CODE(isolate, entry, p0, p1, p2, p3, p4, p5, p6, \
47 p7, p8) \
48 (FUNCTION_CAST<mips_regexp_matcher>(entry)(p0, p1, p2, p3, p4, p5, p6, p7, \
49 NULL, p8))
Ben Murdochb8a8cc12014-11-26 15:28:44 +000050
51#else // O32 Abi.
52
53typedef int (*mips_regexp_matcher)(String* input,
54 int32_t start_offset,
55 const byte* input_start,
56 const byte* input_end,
57 void* return_address,
58 int* output,
59 int32_t output_size,
60 Address stack_base,
61 int32_t direct_call,
62 Isolate* isolate);
63
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000064#define CALL_GENERATED_REGEXP_CODE(isolate, entry, p0, p1, p2, p3, p4, p5, p6, \
65 p7, p8) \
66 (FUNCTION_CAST<mips_regexp_matcher>(entry)(p0, p1, p2, p3, NULL, p4, p5, p6, \
67 p7, p8))
Ben Murdochb8a8cc12014-11-26 15:28:44 +000068
69#endif // MIPS_ABI_N64
70
71
72// The stack limit beyond which we will throw stack overflow errors in
73// generated code. Because generated code on mips uses the C stack, we
74// just use the C stack limit.
75class SimulatorStack : public v8::internal::AllStatic {
76 public:
77 static inline uintptr_t JsLimitFromCLimit(Isolate* isolate,
78 uintptr_t c_limit) {
79 return c_limit;
80 }
81
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000082 static inline uintptr_t RegisterCTryCatch(Isolate* isolate,
83 uintptr_t try_catch_address) {
84 USE(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000085 return try_catch_address;
86 }
87
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000088 static inline void UnregisterCTryCatch(Isolate* isolate) { USE(isolate); }
Ben Murdochb8a8cc12014-11-26 15:28:44 +000089};
90
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000091} // namespace internal
92} // namespace v8
Ben Murdochb8a8cc12014-11-26 15:28:44 +000093
94// Calculated the stack limit beyond which we will throw stack overflow errors.
95// This macro must be called from a C++ method. It relies on being able to take
96// the address of "this" to get a value on the current execution stack and then
97// calculates the stack limit based on that value.
98// NOTE: The check for overflow is not safe as there is no guarantee that the
99// running thread has its stack in all memory up to address 0x00000000.
100#define GENERATED_CODE_STACK_LIMIT(limit) \
101 (reinterpret_cast<uintptr_t>(this) >= limit ? \
102 reinterpret_cast<uintptr_t>(this) - limit : 0)
103
104#else // !defined(USE_SIMULATOR)
105// Running with a simulator.
106
107#include "src/assembler.h"
108#include "src/hashmap.h"
109
110namespace v8 {
111namespace internal {
112
113// -----------------------------------------------------------------------------
114// Utility functions
115
116class CachePage {
117 public:
118 static const int LINE_VALID = 0;
119 static const int LINE_INVALID = 1;
120
121 static const int kPageShift = 12;
122 static const int kPageSize = 1 << kPageShift;
123 static const int kPageMask = kPageSize - 1;
124 static const int kLineShift = 2; // The cache line is only 4 bytes right now.
125 static const int kLineLength = 1 << kLineShift;
126 static const int kLineMask = kLineLength - 1;
127
128 CachePage() {
129 memset(&validity_map_, LINE_INVALID, sizeof(validity_map_));
130 }
131
132 char* ValidityByte(int offset) {
133 return &validity_map_[offset >> kLineShift];
134 }
135
136 char* CachedData(int offset) {
137 return &data_[offset];
138 }
139
140 private:
141 char data_[kPageSize]; // The cached data.
142 static const int kValidityMapSize = kPageSize >> kLineShift;
143 char validity_map_[kValidityMapSize]; // One byte per line.
144};
145
146class Simulator {
147 public:
148 friend class MipsDebugger;
149
150 // Registers are declared in order. See SMRL chapter 2.
151 enum Register {
152 no_reg = -1,
153 zero_reg = 0,
154 at,
155 v0, v1,
156 a0, a1, a2, a3, a4, a5, a6, a7,
157 t0, t1, t2, t3,
158 s0, s1, s2, s3, s4, s5, s6, s7,
159 t8, t9,
160 k0, k1,
161 gp,
162 sp,
163 s8,
164 ra,
165 // LO, HI, and pc.
166 LO,
167 HI,
168 pc, // pc must be the last register.
169 kNumSimuRegisters,
170 // aliases
171 fp = s8
172 };
173
174 // Coprocessor registers.
175 // Generated code will always use doubles. So we will only use even registers.
176 enum FPURegister {
177 f0, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11,
178 f12, f13, f14, f15, // f12 and f14 are arguments FPURegisters.
179 f16, f17, f18, f19, f20, f21, f22, f23, f24, f25,
180 f26, f27, f28, f29, f30, f31,
181 kNumFPURegisters
182 };
183
184 explicit Simulator(Isolate* isolate);
185 ~Simulator();
186
187 // The currently executing Simulator instance. Potentially there can be one
188 // for each native thread.
189 static Simulator* current(v8::internal::Isolate* isolate);
190
191 // Accessors for register state. Reading the pc value adheres to the MIPS
192 // architecture specification and is off by a 8 from the currently executing
193 // instruction.
194 void set_register(int reg, int64_t value);
195 void set_register_word(int reg, int32_t value);
196 void set_dw_register(int dreg, const int* dbl);
197 int64_t get_register(int reg) const;
198 double get_double_from_register_pair(int reg);
199 // Same for FPURegisters.
200 void set_fpu_register(int fpureg, int64_t value);
201 void set_fpu_register_word(int fpureg, int32_t value);
202 void set_fpu_register_hi_word(int fpureg, int32_t value);
203 void set_fpu_register_float(int fpureg, float value);
204 void set_fpu_register_double(int fpureg, double value);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000205 void set_fpu_register_invalid_result64(float original, float rounded);
206 void set_fpu_register_invalid_result(float original, float rounded);
207 void set_fpu_register_word_invalid_result(float original, float rounded);
208 void set_fpu_register_invalid_result64(double original, double rounded);
209 void set_fpu_register_invalid_result(double original, double rounded);
210 void set_fpu_register_word_invalid_result(double original, double rounded);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000211 int64_t get_fpu_register(int fpureg) const;
212 int32_t get_fpu_register_word(int fpureg) const;
213 int32_t get_fpu_register_signed_word(int fpureg) const;
214 int32_t get_fpu_register_hi_word(int fpureg) const;
215 float get_fpu_register_float(int fpureg) const;
216 double get_fpu_register_double(int fpureg) const;
217 void set_fcsr_bit(uint32_t cc, bool value);
218 bool test_fcsr_bit(uint32_t cc);
219 bool set_fcsr_round_error(double original, double rounded);
220 bool set_fcsr_round64_error(double original, double rounded);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000221 bool set_fcsr_round_error(float original, float rounded);
222 bool set_fcsr_round64_error(float original, float rounded);
223 void round_according_to_fcsr(double toRound, double& rounded,
224 int32_t& rounded_int, double fs);
225 void round64_according_to_fcsr(double toRound, double& rounded,
226 int64_t& rounded_int, double fs);
227 void round_according_to_fcsr(float toRound, float& rounded,
228 int32_t& rounded_int, float fs);
229 void round64_according_to_fcsr(float toRound, float& rounded,
230 int64_t& rounded_int, float fs);
231 void set_fcsr_rounding_mode(FPURoundingMode mode);
232 unsigned int get_fcsr_rounding_mode();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000233 // Special case of set_register and get_register to access the raw PC value.
234 void set_pc(int64_t value);
235 int64_t get_pc() const;
236
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000237 Address get_sp() const {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000238 return reinterpret_cast<Address>(static_cast<intptr_t>(get_register(sp)));
239 }
240
241 // Accessor to the internal simulator stack area.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000242 uintptr_t StackLimit(uintptr_t c_limit) const;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000243
244 // Executes MIPS instructions until the PC reaches end_sim_pc.
245 void Execute();
246
247 // Call on program start.
248 static void Initialize(Isolate* isolate);
249
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000250 static void TearDown(HashMap* i_cache, Redirection* first);
251
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000252 // V8 generally calls into generated JS code with 5 parameters and into
253 // generated RegExp code with 7 parameters. This is a convenience function,
254 // which sets up the simulator state and grabs the result on return.
255 int64_t Call(byte* entry, int argument_count, ...);
256 // Alternative: call a 2-argument double function.
257 double CallFP(byte* entry, double d0, double d1);
258
259 // Push an address onto the JS stack.
260 uintptr_t PushAddress(uintptr_t address);
261
262 // Pop an address from the JS stack.
263 uintptr_t PopAddress();
264
265 // Debugger input.
266 void set_last_debugger_input(char* input);
267 char* last_debugger_input() { return last_debugger_input_; }
268
269 // ICache checking.
270 static void FlushICache(v8::internal::HashMap* i_cache, void* start,
271 size_t size);
272
273 // Returns true if pc register contains one of the 'special_values' defined
274 // below (bad_ra, end_sim_pc).
275 bool has_bad_pc() const;
276
277 private:
278 enum special_values {
279 // Known bad pc value to ensure that the simulator does not execute
280 // without being properly setup.
281 bad_ra = -1,
282 // A pc value used to signal the simulator to stop execution. Generally
283 // the ra is set to this value on transition from native C code to
284 // simulated execution, so that the simulator can "return" to the native
285 // C code.
286 end_sim_pc = -2,
287 // Unpredictable value.
288 Unpredictable = 0xbadbeaf
289 };
290
291 // Unsupported instructions use Format to print an error and stop execution.
292 void Format(Instruction* instr, const char* format);
293
294 // Read and write memory.
295 inline uint32_t ReadBU(int64_t addr);
296 inline int32_t ReadB(int64_t addr);
297 inline void WriteB(int64_t addr, uint8_t value);
298 inline void WriteB(int64_t addr, int8_t value);
299
300 inline uint16_t ReadHU(int64_t addr, Instruction* instr);
301 inline int16_t ReadH(int64_t addr, Instruction* instr);
302 // Note: Overloaded on the sign of the value.
303 inline void WriteH(int64_t addr, uint16_t value, Instruction* instr);
304 inline void WriteH(int64_t addr, int16_t value, Instruction* instr);
305
306 inline uint32_t ReadWU(int64_t addr, Instruction* instr);
307 inline int32_t ReadW(int64_t addr, Instruction* instr);
308 inline void WriteW(int64_t addr, int32_t value, Instruction* instr);
309 inline int64_t Read2W(int64_t addr, Instruction* instr);
310 inline void Write2W(int64_t addr, int64_t value, Instruction* instr);
311
312 inline double ReadD(int64_t addr, Instruction* instr);
313 inline void WriteD(int64_t addr, double value, Instruction* instr);
314
315 // Helper for debugging memory access.
316 inline void DieOrDebug();
317
318 // Helpers for data value tracing.
319 enum TraceType {
320 BYTE,
321 HALF,
322 WORD,
323 DWORD
324 // DFLOAT - Floats may have printing issues due to paired lwc1's
325 };
326
327 void TraceRegWr(int64_t value);
328 void TraceMemWr(int64_t addr, int64_t value, TraceType t);
329 void TraceMemRd(int64_t addr, int64_t value);
330
331 // Operations depending on endianness.
332 // Get Double Higher / Lower word.
333 inline int32_t GetDoubleHIW(double* addr);
334 inline int32_t GetDoubleLOW(double* addr);
335 // Set Double Higher / Lower word.
336 inline int32_t SetDoubleHIW(double* addr);
337 inline int32_t SetDoubleLOW(double* addr);
338
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000339 // functions called from DecodeTypeRegister.
340 void DecodeTypeRegisterCOP1();
341
342 void DecodeTypeRegisterCOP1X();
343
344 void DecodeTypeRegisterSPECIAL();
345
346
347 void DecodeTypeRegisterSPECIAL2();
348
349 void DecodeTypeRegisterSPECIAL3();
350
351 void DecodeTypeRegisterSRsType();
352
353 void DecodeTypeRegisterDRsType();
354
355 void DecodeTypeRegisterWRsType();
356
357 void DecodeTypeRegisterLRsType();
358
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000359 // Executing is handled based on the instruction type.
360 void DecodeTypeRegister(Instruction* instr);
361
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000362 Instruction* currentInstr_;
363 inline Instruction* get_instr() const { return currentInstr_; }
364 inline void set_instr(Instruction* instr) { currentInstr_ = instr; }
365
366 inline int32_t rs_reg() const { return currentInstr_->RsValue(); }
367 inline int64_t rs() const { return get_register(rs_reg()); }
368 inline uint64_t rs_u() const {
369 return static_cast<uint64_t>(get_register(rs_reg()));
370 }
371 inline int32_t rt_reg() const { return currentInstr_->RtValue(); }
372 inline int64_t rt() const { return get_register(rt_reg()); }
373 inline uint64_t rt_u() const {
374 return static_cast<uint64_t>(get_register(rt_reg()));
375 }
376 inline int32_t rd_reg() const { return currentInstr_->RdValue(); }
377 inline int32_t fr_reg() const { return currentInstr_->FrValue(); }
378 inline int32_t fs_reg() const { return currentInstr_->FsValue(); }
379 inline int32_t ft_reg() const { return currentInstr_->FtValue(); }
380 inline int32_t fd_reg() const { return currentInstr_->FdValue(); }
381 inline int32_t sa() const { return currentInstr_->SaValue(); }
382 inline int32_t lsa_sa() const { return currentInstr_->LsaSaValue(); }
383
384 inline void SetResult(const int32_t rd_reg, const int64_t alu_out) {
385 set_register(rd_reg, alu_out);
386 TraceRegWr(alu_out);
387 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000388
389 void DecodeTypeImmediate(Instruction* instr);
390 void DecodeTypeJump(Instruction* instr);
391
392 // Used for breakpoints and traps.
393 void SoftwareInterrupt(Instruction* instr);
394
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000395 // Compact branch guard.
396 void CheckForbiddenSlot(int64_t current_pc) {
397 Instruction* instr_after_compact_branch =
398 reinterpret_cast<Instruction*>(current_pc + Instruction::kInstrSize);
399 if (instr_after_compact_branch->IsForbiddenAfterBranch()) {
400 V8_Fatal(__FILE__, __LINE__,
401 "Error: Unexpected instruction 0x%08x immediately after a "
402 "compact branch instruction.",
403 *reinterpret_cast<uint32_t*>(instr_after_compact_branch));
404 }
405 }
406
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000407 // Stop helper functions.
408 bool IsWatchpoint(uint64_t code);
409 void PrintWatchpoint(uint64_t code);
410 void HandleStop(uint64_t code, Instruction* instr);
411 bool IsStopInstruction(Instruction* instr);
412 bool IsEnabledStop(uint64_t code);
413 void EnableStop(uint64_t code);
414 void DisableStop(uint64_t code);
415 void IncreaseStopCounter(uint64_t code);
416 void PrintStopInfo(uint64_t code);
417
418
419 // Executes one instruction.
420 void InstructionDecode(Instruction* instr);
421 // Execute one instruction placed in a branch delay slot.
422 void BranchDelayInstructionDecode(Instruction* instr) {
423 if (instr->InstructionBits() == nopInstr) {
424 // Short-cut generic nop instructions. They are always valid and they
425 // never change the simulator state.
426 return;
427 }
428
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000429 if (instr->IsForbiddenAfterBranch()) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000430 V8_Fatal(__FILE__, __LINE__,
431 "Eror:Unexpected %i opcode in a branch delay slot.",
432 instr->OpcodeValue());
433 }
434 InstructionDecode(instr);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000435 SNPrintF(trace_buf_, " ");
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000436 }
437
438 // ICache.
439 static void CheckICache(v8::internal::HashMap* i_cache, Instruction* instr);
440 static void FlushOnePage(v8::internal::HashMap* i_cache, intptr_t start,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000441 size_t size);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000442 static CachePage* GetCachePage(v8::internal::HashMap* i_cache, void* page);
443
444 enum Exception {
445 none,
446 kIntegerOverflow,
447 kIntegerUnderflow,
448 kDivideByZero,
449 kNumExceptions
450 };
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000451
452 // Exceptions.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000453 void SignalException(Exception e);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000454
455 // Runtime call support.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000456 static void* RedirectExternalReference(Isolate* isolate,
457 void* external_function,
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000458 ExternalReference::Type type);
459
460 // Handle arguments and return value for runtime FP functions.
461 void GetFpArgs(double* x, double* y, int32_t* z);
462 void SetFpResult(const double& result);
463
464 void CallInternal(byte* entry);
465
466 // Architecture state.
467 // Registers.
468 int64_t registers_[kNumSimuRegisters];
469 // Coprocessor Registers.
470 int64_t FPUregisters_[kNumFPURegisters];
471 // FPU control register.
472 uint32_t FCSR_;
473
474 // Simulator support.
475 // Allocate 1MB for stack.
476 size_t stack_size_;
477 char* stack_;
478 bool pc_modified_;
479 int64_t icount_;
480 int break_count_;
481 EmbeddedVector<char, 128> trace_buf_;
482
483 // Debugger input.
484 char* last_debugger_input_;
485
486 // Icache simulation.
487 v8::internal::HashMap* i_cache_;
488
489 v8::internal::Isolate* isolate_;
490
491 // Registered breakpoints.
492 Instruction* break_pc_;
493 Instr break_instr_;
494
495 // Stop is disabled if bit 31 is set.
496 static const uint32_t kStopDisabledBit = 1 << 31;
497
498 // A stop is enabled, meaning the simulator will stop when meeting the
499 // instruction, if bit 31 of watched_stops_[code].count is unset.
500 // The value watched_stops_[code].count & ~(1 << 31) indicates how many times
501 // the breakpoint was hit or gone through.
502 struct StopCountAndDesc {
503 uint32_t count;
504 char* desc;
505 };
506 StopCountAndDesc watched_stops_[kMaxStopCode + 1];
507};
508
509
510// When running with the simulator transition into simulated execution at this
511// point.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000512#define CALL_GENERATED_CODE(isolate, entry, p0, p1, p2, p3, p4) \
513 reinterpret_cast<Object*>(Simulator::current(isolate)->Call( \
514 FUNCTION_ADDR(entry), 5, reinterpret_cast<int64_t*>(p0), \
515 reinterpret_cast<int64_t*>(p1), reinterpret_cast<int64_t*>(p2), \
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400516 reinterpret_cast<int64_t*>(p3), reinterpret_cast<int64_t*>(p4)))
517
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000518
519#ifdef MIPS_ABI_N64
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000520#define CALL_GENERATED_REGEXP_CODE(isolate, entry, p0, p1, p2, p3, p4, p5, p6, \
521 p7, p8) \
522 static_cast<int>(Simulator::current(isolate)->Call( \
523 entry, 10, p0, p1, p2, p3, p4, reinterpret_cast<int64_t*>(p5), p6, p7, \
524 NULL, p8))
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000525#else // Must be O32 Abi.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000526#define CALL_GENERATED_REGEXP_CODE(isolate, entry, p0, p1, p2, p3, p4, p5, p6, \
527 p7, p8) \
528 static_cast<int>(Simulator::current(isolate)->Call( \
529 entry, 10, p0, p1, p2, p3, NULL, p4, p5, p6, p7, p8))
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000530#endif // MIPS_ABI_N64
531
532
533// The simulator has its own stack. Thus it has a different stack limit from
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000534// the C-based native code. The JS-based limit normally points near the end of
535// the simulator stack. When the C-based limit is exhausted we reflect that by
536// lowering the JS-based limit as well, to make stack checks trigger.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000537class SimulatorStack : public v8::internal::AllStatic {
538 public:
539 static inline uintptr_t JsLimitFromCLimit(Isolate* isolate,
540 uintptr_t c_limit) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000541 return Simulator::current(isolate)->StackLimit(c_limit);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000542 }
543
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000544 static inline uintptr_t RegisterCTryCatch(Isolate* isolate,
545 uintptr_t try_catch_address) {
546 Simulator* sim = Simulator::current(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000547 return sim->PushAddress(try_catch_address);
548 }
549
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000550 static inline void UnregisterCTryCatch(Isolate* isolate) {
551 Simulator::current(isolate)->PopAddress();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000552 }
553};
554
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000555} // namespace internal
556} // namespace v8
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000557
558#endif // !defined(USE_SIMULATOR)
559#endif // V8_MIPS_SIMULATOR_MIPS_H_