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