042b2ada2c6edf51d9489870c36395cf52f0a81c
[platform/upstream/v8.git] / src / ppc / simulator-ppc.h
1 // Copyright 2014 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 PPC instructions if we are not generating a native
7 // PPC binary. This Simulator allows us to run and debug PPC code generation on
8 // 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 PPC HW platform.
12
13 #ifndef V8_PPC_SIMULATOR_PPC_H_
14 #define V8_PPC_SIMULATOR_PPC_H_
15
16 #include "src/allocation.h"
17
18 #if !defined(USE_SIMULATOR)
19 // Running without a simulator on a native ppc platform.
20
21 namespace v8 {
22 namespace internal {
23
24 // When running without a simulator we call the entry directly.
25 #define CALL_GENERATED_CODE(entry, p0, p1, p2, p3, p4) \
26   (entry(p0, p1, p2, p3, p4))
27
28 typedef int (*ppc_regexp_matcher)(String*, int, const byte*, const byte*, int*,
29                                   int, Address, int, void*, Isolate*);
30
31
32 // Call the generated regexp code directly. The code at the entry address
33 // should act as a function matching the type ppc_regexp_matcher.
34 // The ninth argument is a dummy that reserves the space used for
35 // the return address added by the ExitFrame in native calls.
36 #define CALL_GENERATED_REGEXP_CODE(entry, p0, p1, p2, p3, p4, p5, p6, p7, p8) \
37   (FUNCTION_CAST<ppc_regexp_matcher>(entry)(p0, p1, p2, p3, p4, p5, p6, p7,   \
38                                             NULL, p8))
39
40 // The stack limit beyond which we will throw stack overflow errors in
41 // generated code. Because generated code on ppc uses the C stack, we
42 // just use the C stack limit.
43 class SimulatorStack : public v8::internal::AllStatic {
44  public:
45   static inline uintptr_t JsLimitFromCLimit(v8::internal::Isolate* isolate,
46                                             uintptr_t c_limit) {
47     USE(isolate);
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 #else  // !defined(USE_SIMULATOR)
61 // Running with a simulator.
62
63 #include "src/assembler.h"
64 #include "src/hashmap.h"
65 #include "src/ppc/constants-ppc.h"
66
67 namespace v8 {
68 namespace internal {
69
70 class CachePage {
71  public:
72   static const int LINE_VALID = 0;
73   static const int LINE_INVALID = 1;
74
75   static const int kPageShift = 12;
76   static const int kPageSize = 1 << kPageShift;
77   static const int kPageMask = kPageSize - 1;
78   static const int kLineShift = 2;  // The cache line is only 4 bytes right now.
79   static const int kLineLength = 1 << kLineShift;
80   static const int kLineMask = kLineLength - 1;
81
82   CachePage() { memset(&validity_map_, LINE_INVALID, sizeof(validity_map_)); }
83
84   char* ValidityByte(int offset) {
85     return &validity_map_[offset >> kLineShift];
86   }
87
88   char* CachedData(int offset) { return &data_[offset]; }
89
90  private:
91   char data_[kPageSize];  // The cached data.
92   static const int kValidityMapSize = kPageSize >> kLineShift;
93   char validity_map_[kValidityMapSize];  // One byte per line.
94 };
95
96
97 class Simulator {
98  public:
99   friend class PPCDebugger;
100   enum Register {
101     no_reg = -1,
102     r0 = 0,
103     sp,
104     r2,
105     r3,
106     r4,
107     r5,
108     r6,
109     r7,
110     r8,
111     r9,
112     r10,
113     r11,
114     r12,
115     r13,
116     r14,
117     r15,
118     r16,
119     r17,
120     r18,
121     r19,
122     r20,
123     r21,
124     r22,
125     r23,
126     r24,
127     r25,
128     r26,
129     r27,
130     r28,
131     r29,
132     r30,
133     fp,
134     kNumGPRs = 32,
135     d0 = 0,
136     d1,
137     d2,
138     d3,
139     d4,
140     d5,
141     d6,
142     d7,
143     d8,
144     d9,
145     d10,
146     d11,
147     d12,
148     d13,
149     d14,
150     d15,
151     d16,
152     d17,
153     d18,
154     d19,
155     d20,
156     d21,
157     d22,
158     d23,
159     d24,
160     d25,
161     d26,
162     d27,
163     d28,
164     d29,
165     d30,
166     d31,
167     kNumFPRs = 32
168   };
169
170   explicit Simulator(Isolate* isolate);
171   ~Simulator();
172
173   // The currently executing Simulator instance. Potentially there can be one
174   // for each native thread.
175   static Simulator* current(v8::internal::Isolate* isolate);
176
177   // Accessors for register state.
178   void set_register(int reg, intptr_t value);
179   intptr_t get_register(int reg) const;
180   double get_double_from_register_pair(int reg);
181   void set_d_register_from_double(int dreg, const double dbl) {
182     DCHECK(dreg >= 0 && dreg < kNumFPRs);
183     *bit_cast<double*>(&fp_registers_[dreg]) = dbl;
184   }
185   double get_double_from_d_register(int dreg) {
186     DCHECK(dreg >= 0 && dreg < kNumFPRs);
187     return *bit_cast<double*>(&fp_registers_[dreg]);
188   }
189   void set_d_register(int dreg, int64_t value) {
190     DCHECK(dreg >= 0 && dreg < kNumFPRs);
191     fp_registers_[dreg] = value;
192   }
193   int64_t get_d_register(int dreg) {
194     DCHECK(dreg >= 0 && dreg < kNumFPRs);
195     return fp_registers_[dreg];
196   }
197
198   // Special case of set_register and get_register to access the raw PC value.
199   void set_pc(intptr_t value);
200   intptr_t get_pc() const;
201
202   Address get_sp() const {
203     return reinterpret_cast<Address>(static_cast<intptr_t>(get_register(sp)));
204   }
205
206   // Accessor to the internal simulator stack area.
207   uintptr_t StackLimit(uintptr_t c_limit) const;
208
209   // Executes PPC instructions until the PC reaches end_sim_pc.
210   void Execute();
211
212   // Call on program start.
213   static void Initialize(Isolate* isolate);
214
215   static void TearDown(HashMap* i_cache, Redirection* first);
216
217   // V8 generally calls into generated JS code with 5 parameters and into
218   // generated RegExp code with 7 parameters. This is a convenience function,
219   // which sets up the simulator state and grabs the result on return.
220   intptr_t Call(byte* entry, int argument_count, ...);
221   // Alternative: call a 2-argument double function.
222   void CallFP(byte* entry, double d0, double d1);
223   int32_t CallFPReturnsInt(byte* entry, double d0, double d1);
224   double CallFPReturnsDouble(byte* entry, double d0, double d1);
225
226   // Push an address onto the JS stack.
227   uintptr_t PushAddress(uintptr_t address);
228
229   // Pop an address from the JS stack.
230   uintptr_t PopAddress();
231
232   // Debugger input.
233   void set_last_debugger_input(char* input);
234   char* last_debugger_input() { return last_debugger_input_; }
235
236   // ICache checking.
237   static void FlushICache(v8::internal::HashMap* i_cache, void* start,
238                           size_t size);
239
240   // Returns true if pc register contains one of the 'special_values' defined
241   // below (bad_lr, end_sim_pc).
242   bool has_bad_pc() const;
243
244  private:
245   enum special_values {
246     // Known bad pc value to ensure that the simulator does not execute
247     // without being properly setup.
248     bad_lr = -1,
249     // A pc value used to signal the simulator to stop execution.  Generally
250     // the lr is set to this value on transition from native C code to
251     // simulated execution, so that the simulator can "return" to the native
252     // C code.
253     end_sim_pc = -2
254   };
255
256   enum BCType { BC_OFFSET, BC_LINK_REG, BC_CTR_REG };
257
258   // Unsupported instructions use Format to print an error and stop execution.
259   void Format(Instruction* instr, const char* format);
260
261   // Helper functions to set the conditional flags in the architecture state.
262   bool CarryFrom(int32_t left, int32_t right, int32_t carry = 0);
263   bool BorrowFrom(int32_t left, int32_t right);
264   bool OverflowFrom(int32_t alu_out, int32_t left, int32_t right,
265                     bool addition);
266
267   // Helper functions to decode common "addressing" modes
268   int32_t GetShiftRm(Instruction* instr, bool* carry_out);
269   int32_t GetImm(Instruction* instr, bool* carry_out);
270   void ProcessPUW(Instruction* instr, int num_regs, int operand_size,
271                   intptr_t* start_address, intptr_t* end_address);
272   void HandleRList(Instruction* instr, bool load);
273   void HandleVList(Instruction* inst);
274   void SoftwareInterrupt(Instruction* instr);
275
276   // Stop helper functions.
277   inline bool isStopInstruction(Instruction* instr);
278   inline bool isWatchedStop(uint32_t bkpt_code);
279   inline bool isEnabledStop(uint32_t bkpt_code);
280   inline void EnableStop(uint32_t bkpt_code);
281   inline void DisableStop(uint32_t bkpt_code);
282   inline void IncreaseStopCounter(uint32_t bkpt_code);
283   void PrintStopInfo(uint32_t code);
284
285   // Read and write memory.
286   inline uint8_t ReadBU(intptr_t addr);
287   inline int8_t ReadB(intptr_t addr);
288   inline void WriteB(intptr_t addr, uint8_t value);
289   inline void WriteB(intptr_t addr, int8_t value);
290
291   inline uint16_t ReadHU(intptr_t addr, Instruction* instr);
292   inline int16_t ReadH(intptr_t addr, Instruction* instr);
293   // Note: Overloaded on the sign of the value.
294   inline void WriteH(intptr_t addr, uint16_t value, Instruction* instr);
295   inline void WriteH(intptr_t addr, int16_t value, Instruction* instr);
296
297   inline uint32_t ReadWU(intptr_t addr, Instruction* instr);
298   inline int32_t ReadW(intptr_t addr, Instruction* instr);
299   inline void WriteW(intptr_t addr, uint32_t value, Instruction* instr);
300   inline void WriteW(intptr_t addr, int32_t value, Instruction* instr);
301
302   intptr_t* ReadDW(intptr_t addr);
303   void WriteDW(intptr_t addr, int64_t value);
304
305   void Trace(Instruction* instr);
306   void SetCR0(intptr_t result, bool setSO = false);
307   void ExecuteBranchConditional(Instruction* instr, BCType type);
308   void ExecuteExt1(Instruction* instr);
309   bool ExecuteExt2_10bit(Instruction* instr);
310   bool ExecuteExt2_9bit_part1(Instruction* instr);
311   bool ExecuteExt2_9bit_part2(Instruction* instr);
312   void ExecuteExt2_5bit(Instruction* instr);
313   void ExecuteExt2(Instruction* instr);
314   void ExecuteExt4(Instruction* instr);
315 #if V8_TARGET_ARCH_PPC64
316   void ExecuteExt5(Instruction* instr);
317 #endif
318   void ExecuteGeneric(Instruction* instr);
319
320   // Executes one instruction.
321   void ExecuteInstruction(Instruction* instr);
322
323   // ICache.
324   static void CheckICache(v8::internal::HashMap* i_cache, Instruction* instr);
325   static void FlushOnePage(v8::internal::HashMap* i_cache, intptr_t start,
326                            int size);
327   static CachePage* GetCachePage(v8::internal::HashMap* i_cache, void* page);
328
329   // Runtime call support.
330   static void* RedirectExternalReference(
331       void* external_function, v8::internal::ExternalReference::Type type);
332
333   // Handle arguments and return value for runtime FP functions.
334   void GetFpArgs(double* x, double* y, intptr_t* z);
335   void SetFpResult(const double& result);
336   void TrashCallerSaveRegisters();
337
338   void CallInternal(byte* entry);
339
340   // Architecture state.
341   // Saturating instructions require a Q flag to indicate saturation.
342   // There is currently no way to read the CPSR directly, and thus read the Q
343   // flag, so this is left unimplemented.
344   intptr_t registers_[kNumGPRs];
345   int32_t condition_reg_;
346   int32_t fp_condition_reg_;
347   intptr_t special_reg_lr_;
348   intptr_t special_reg_pc_;
349   intptr_t special_reg_ctr_;
350   int32_t special_reg_xer_;
351
352   int64_t fp_registers_[kNumFPRs];
353
354   // Simulator support.
355   char* stack_;
356   static const size_t stack_protection_size_ = 256 * kPointerSize;
357   bool pc_modified_;
358   int icount_;
359
360   // Debugger input.
361   char* last_debugger_input_;
362
363   // Icache simulation
364   v8::internal::HashMap* i_cache_;
365
366   // Registered breakpoints.
367   Instruction* break_pc_;
368   Instr break_instr_;
369
370   v8::internal::Isolate* isolate_;
371
372   // A stop is watched if its code is less than kNumOfWatchedStops.
373   // Only watched stops support enabling/disabling and the counter feature.
374   static const uint32_t kNumOfWatchedStops = 256;
375
376   // Breakpoint is disabled if bit 31 is set.
377   static const uint32_t kStopDisabledBit = 1 << 31;
378
379   // A stop is enabled, meaning the simulator will stop when meeting the
380   // instruction, if bit 31 of watched_stops_[code].count is unset.
381   // The value watched_stops_[code].count & ~(1 << 31) indicates how many times
382   // the breakpoint was hit or gone through.
383   struct StopCountAndDesc {
384     uint32_t count;
385     char* desc;
386   };
387   StopCountAndDesc watched_stops_[kNumOfWatchedStops];
388 };
389
390
391 // When running with the simulator transition into simulated execution at this
392 // point.
393 #define CALL_GENERATED_CODE(entry, p0, p1, p2, p3, p4)                    \
394   reinterpret_cast<Object*>(Simulator::current(Isolate::Current())->Call( \
395       FUNCTION_ADDR(entry), 5, (intptr_t)p0, (intptr_t)p1, (intptr_t)p2,  \
396       (intptr_t)p3, (intptr_t)p4))
397
398 #define CALL_GENERATED_REGEXP_CODE(entry, p0, p1, p2, p3, p4, p5, p6, p7, p8) \
399   Simulator::current(Isolate::Current())                                      \
400       ->Call(entry, 10, (intptr_t)p0, (intptr_t)p1, (intptr_t)p2,             \
401              (intptr_t)p3, (intptr_t)p4, (intptr_t)p5, (intptr_t)p6,          \
402              (intptr_t)p7, (intptr_t)NULL, (intptr_t)p8)
403
404
405 // The simulator has its own stack. Thus it has a different stack limit from
406 // the C-based native code.  The JS-based limit normally points near the end of
407 // the simulator stack.  When the C-based limit is exhausted we reflect that by
408 // lowering the JS-based limit as well, to make stack checks trigger.
409 class SimulatorStack : public v8::internal::AllStatic {
410  public:
411   static inline uintptr_t JsLimitFromCLimit(v8::internal::Isolate* isolate,
412                                             uintptr_t c_limit) {
413     return Simulator::current(isolate)->StackLimit(c_limit);
414   }
415
416   static inline uintptr_t RegisterCTryCatch(uintptr_t try_catch_address) {
417     Simulator* sim = Simulator::current(Isolate::Current());
418     return sim->PushAddress(try_catch_address);
419   }
420
421   static inline void UnregisterCTryCatch() {
422     Simulator::current(Isolate::Current())->PopAddress();
423   }
424 };
425 }
426 }  // namespace v8::internal
427
428 #endif  // !defined(USE_SIMULATOR)
429 #endif  // V8_PPC_SIMULATOR_PPC_H_