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