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