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