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