• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2012 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 ARM instructions if we are not generating a native
6 // ARM binary. This Simulator allows us to run and debug ARM code generation on
7 // regular desktop machines.
8 // V8 calls into generated code by using the GeneratedCode class,
9 // which will start execution in the Simulator or forwards to the real entry
10 // on a ARM HW platform.
11 
12 #ifndef V8_EXECUTION_ARM_SIMULATOR_ARM_H_
13 #define V8_EXECUTION_ARM_SIMULATOR_ARM_H_
14 
15 // globals.h defines USE_SIMULATOR.
16 #include "src/common/globals.h"
17 
18 #if defined(USE_SIMULATOR)
19 // Running with a simulator.
20 
21 #include "src/base/hashmap.h"
22 #include "src/base/lazy-instance.h"
23 #include "src/base/platform/mutex.h"
24 #include "src/codegen/arm/constants-arm.h"
25 #include "src/execution/simulator-base.h"
26 #include "src/utils/allocation.h"
27 #include "src/utils/boxed-float.h"
28 
29 namespace v8 {
30 namespace internal {
31 
32 class CachePage {
33  public:
34   static const int LINE_VALID = 0;
35   static const int LINE_INVALID = 1;
36 
37   static const int kPageShift = 12;
38   static const int kPageSize = 1 << kPageShift;
39   static const int kPageMask = kPageSize - 1;
40   static const int kLineShift = 2;  // The cache line is only 4 bytes right now.
41   static const int kLineLength = 1 << kLineShift;
42   static const int kLineMask = kLineLength - 1;
43 
CachePage()44   CachePage() { memset(&validity_map_, LINE_INVALID, sizeof(validity_map_)); }
45 
ValidityByte(int offset)46   char* ValidityByte(int offset) {
47     return &validity_map_[offset >> kLineShift];
48   }
49 
CachedData(int offset)50   char* CachedData(int offset) { return &data_[offset]; }
51 
52  private:
53   char data_[kPageSize];  // The cached data.
54   static const int kValidityMapSize = kPageSize >> kLineShift;
55   char validity_map_[kValidityMapSize];  // One byte per line.
56 };
57 
58 class Simulator : public SimulatorBase {
59  public:
60   friend class ArmDebugger;
61   enum Register {
62     no_reg = -1,
63     r0 = 0,
64     r1,
65     r2,
66     r3,
67     r4,
68     r5,
69     r6,
70     r7,
71     r8,
72     r9,
73     r10,
74     r11,
75     r12,
76     r13,
77     r14,
78     r15,
79     num_registers,
80     sp = 13,
81     lr = 14,
82     pc = 15,
83     s0 = 0,
84     s1,
85     s2,
86     s3,
87     s4,
88     s5,
89     s6,
90     s7,
91     s8,
92     s9,
93     s10,
94     s11,
95     s12,
96     s13,
97     s14,
98     s15,
99     s16,
100     s17,
101     s18,
102     s19,
103     s20,
104     s21,
105     s22,
106     s23,
107     s24,
108     s25,
109     s26,
110     s27,
111     s28,
112     s29,
113     s30,
114     s31,
115     num_s_registers = 32,
116     d0 = 0,
117     d1,
118     d2,
119     d3,
120     d4,
121     d5,
122     d6,
123     d7,
124     d8,
125     d9,
126     d10,
127     d11,
128     d12,
129     d13,
130     d14,
131     d15,
132     d16,
133     d17,
134     d18,
135     d19,
136     d20,
137     d21,
138     d22,
139     d23,
140     d24,
141     d25,
142     d26,
143     d27,
144     d28,
145     d29,
146     d30,
147     d31,
148     num_d_registers = 32,
149     q0 = 0,
150     q1,
151     q2,
152     q3,
153     q4,
154     q5,
155     q6,
156     q7,
157     q8,
158     q9,
159     q10,
160     q11,
161     q12,
162     q13,
163     q14,
164     q15,
165     num_q_registers = 16
166   };
167 
168   explicit Simulator(Isolate* isolate);
169   ~Simulator();
170 
171   // The currently executing Simulator instance. Potentially there can be one
172   // for each native thread.
173   V8_EXPORT_PRIVATE static Simulator* current(v8::internal::Isolate* isolate);
174 
175   // Accessors for register state. Reading the pc value adheres to the ARM
176   // architecture specification and is off by a 8 from the currently executing
177   // instruction.
178   void set_register(int reg, int32_t value);
179   V8_EXPORT_PRIVATE int32_t get_register(int reg) const;
180   double get_double_from_register_pair(int reg);
181   void set_register_pair_from_double(int reg, double* value);
182   void set_dw_register(int dreg, const int* dbl);
183 
184   // Support for VFP.
185   void get_d_register(int dreg, uint64_t* value);
186   void set_d_register(int dreg, const uint64_t* value);
187   void get_d_register(int dreg, uint32_t* value);
188   void set_d_register(int dreg, const uint32_t* value);
189   // Support for NEON.
190   template <typename T, int SIZE = kSimd128Size>
191   void get_neon_register(int reg, T (&value)[SIZE / sizeof(T)]);
192   template <typename T, int SIZE = kSimd128Size>
193   void set_neon_register(int reg, const T (&value)[SIZE / sizeof(T)]);
194 
195   void set_s_register(int reg, unsigned int value);
196   unsigned int get_s_register(int reg) const;
197 
set_d_register_from_double(int dreg,const Float64 dbl)198   void set_d_register_from_double(int dreg, const Float64 dbl) {
199     SetVFPRegister<Float64, 2>(dreg, dbl);
200   }
set_d_register_from_double(int dreg,const double dbl)201   void set_d_register_from_double(int dreg, const double dbl) {
202     SetVFPRegister<double, 2>(dreg, dbl);
203   }
204 
get_double_from_d_register(int dreg)205   Float64 get_double_from_d_register(int dreg) {
206     return GetFromVFPRegister<Float64, 2>(dreg);
207   }
208 
set_s_register_from_float(int sreg,const Float32 flt)209   void set_s_register_from_float(int sreg, const Float32 flt) {
210     SetVFPRegister<Float32, 1>(sreg, flt);
211   }
set_s_register_from_float(int sreg,const float flt)212   void set_s_register_from_float(int sreg, const float flt) {
213     SetVFPRegister<float, 1>(sreg, flt);
214   }
215 
get_float_from_s_register(int sreg)216   Float32 get_float_from_s_register(int sreg) {
217     return GetFromVFPRegister<Float32, 1>(sreg);
218   }
219 
set_s_register_from_sinteger(int sreg,const int sint)220   void set_s_register_from_sinteger(int sreg, const int sint) {
221     SetVFPRegister<int, 1>(sreg, sint);
222   }
223 
get_sinteger_from_s_register(int sreg)224   int get_sinteger_from_s_register(int sreg) {
225     return GetFromVFPRegister<int, 1>(sreg);
226   }
227 
228   // Special case of set_register and get_register to access the raw PC value.
229   void set_pc(int32_t value);
230   V8_EXPORT_PRIVATE int32_t get_pc() const;
231 
get_sp()232   Address get_sp() const { return static_cast<Address>(get_register(sp)); }
233 
234   // Accessor to the internal simulator stack area.
235   uintptr_t StackLimit(uintptr_t c_limit) const;
236 
237   // Executes ARM instructions until the PC reaches end_sim_pc.
238   void Execute();
239 
240   template <typename Return, typename... Args>
Call(Address entry,Args...args)241   Return Call(Address entry, Args... args) {
242     return VariadicCall<Return>(this, &Simulator::CallImpl, entry, args...);
243   }
244 
245   // Alternative: call a 2-argument double function.
246   template <typename Return>
CallFP(Address entry,double d0,double d1)247   Return CallFP(Address entry, double d0, double d1) {
248     return ConvertReturn<Return>(CallFPImpl(entry, d0, d1));
249   }
250 
251   // Push an address onto the JS stack.
252   uintptr_t PushAddress(uintptr_t address);
253 
254   // Pop an address from the JS stack.
255   uintptr_t PopAddress();
256 
257   // Debugger input.
258   void set_last_debugger_input(char* input);
last_debugger_input()259   char* last_debugger_input() { return last_debugger_input_; }
260 
261   // Redirection support.
262   static void SetRedirectInstruction(Instruction* instruction);
263 
264   // ICache checking.
265   static bool ICacheMatch(void* one, void* two);
266   static void FlushICache(base::CustomMatcherHashMap* i_cache, void* start,
267                           size_t size);
268 
269   // Returns true if pc register contains one of the 'special_values' defined
270   // below (bad_lr, end_sim_pc).
271   bool has_bad_pc() const;
272 
273   // EABI variant for double arguments in use.
use_eabi_hardfloat()274   bool use_eabi_hardfloat() {
275 #if USE_EABI_HARDFLOAT
276     return true;
277 #else
278     return false;
279 #endif
280   }
281 
282  private:
283   enum special_values {
284     // Known bad pc value to ensure that the simulator does not execute
285     // without being properly setup.
286     bad_lr = -1,
287     // A pc value used to signal the simulator to stop execution.  Generally
288     // the lr is set to this value on transition from native C code to
289     // simulated execution, so that the simulator can "return" to the native
290     // C code.
291     end_sim_pc = -2
292   };
293 
294   V8_EXPORT_PRIVATE intptr_t CallImpl(Address entry, int argument_count,
295                                       const intptr_t* arguments);
296   intptr_t CallFPImpl(Address entry, double d0, double d1);
297 
298   // Unsupported instructions use Format to print an error and stop execution.
299   void Format(Instruction* instr, const char* format);
300 
301   // Checks if the current instruction should be executed based on its
302   // condition bits.
303   inline bool ConditionallyExecute(Instruction* instr);
304 
305   // Helper functions to set the conditional flags in the architecture state.
306   void SetNZFlags(int32_t val);
307   void SetCFlag(bool val);
308   void SetVFlag(bool val);
309   bool CarryFrom(int32_t left, int32_t right, int32_t carry = 0);
310   bool BorrowFrom(int32_t left, int32_t right, int32_t carry = 1);
311   bool OverflowFrom(int32_t alu_out, int32_t left, int32_t right,
312                     bool addition);
313 
GetCarry()314   inline int GetCarry() { return c_flag_ ? 1 : 0; }
315 
316   // Support for VFP.
317   void Compute_FPSCR_Flags(float val1, float val2);
318   void Compute_FPSCR_Flags(double val1, double val2);
319   void Copy_FPSCR_to_APSR();
320   inline float canonicalizeNaN(float value);
321   inline double canonicalizeNaN(double value);
322   inline Float32 canonicalizeNaN(Float32 value);
323   inline Float64 canonicalizeNaN(Float64 value);
324 
325   // Helper functions to decode common "addressing" modes
326   int32_t GetShiftRm(Instruction* instr, bool* carry_out);
327   int32_t GetImm(Instruction* instr, bool* carry_out);
328   int32_t ProcessPU(Instruction* instr, int num_regs, int operand_size,
329                     intptr_t* start_address, intptr_t* end_address);
330   void HandleRList(Instruction* instr, bool load);
331   void HandleVList(Instruction* inst);
332   void SoftwareInterrupt(Instruction* instr);
333   void DebugAtNextPC();
334 
335   // Stop helper functions.
336   inline bool isWatchedStop(uint32_t bkpt_code);
337   inline bool isEnabledStop(uint32_t bkpt_code);
338   inline void EnableStop(uint32_t bkpt_code);
339   inline void DisableStop(uint32_t bkpt_code);
340   inline void IncreaseStopCounter(uint32_t bkpt_code);
341   void PrintStopInfo(uint32_t code);
342 
343   // Read and write memory.
344   // The *Ex functions are exclusive access. The writes return the strex status:
345   // 0 if the write succeeds, and 1 if the write fails.
346   inline uint8_t ReadBU(int32_t addr);
347   inline int8_t ReadB(int32_t addr);
348   uint8_t ReadExBU(int32_t addr);
349   inline void WriteB(int32_t addr, uint8_t value);
350   inline void WriteB(int32_t addr, int8_t value);
351   int WriteExB(int32_t addr, uint8_t value);
352 
353   inline uint16_t ReadHU(int32_t addr);
354   inline int16_t ReadH(int32_t addr);
355   uint16_t ReadExHU(int32_t addr);
356   // Note: Overloaded on the sign of the value.
357   inline void WriteH(int32_t addr, uint16_t value);
358   inline void WriteH(int32_t addr, int16_t value);
359   int WriteExH(int32_t addr, uint16_t value);
360 
361   inline int ReadW(int32_t addr);
362   int ReadExW(int32_t addr);
363   inline void WriteW(int32_t addr, int value);
364   int WriteExW(int32_t addr, int value);
365 
366   int32_t* ReadDW(int32_t addr);
367   void WriteDW(int32_t addr, int32_t value1, int32_t value2);
368   int32_t* ReadExDW(int32_t addr);
369   int WriteExDW(int32_t addr, int32_t value1, int32_t value2);
370 
371   // Executing is handled based on the instruction type.
372   // Both type 0 and type 1 rolled into one.
373   void DecodeType01(Instruction* instr);
374   void DecodeType2(Instruction* instr);
375   void DecodeType3(Instruction* instr);
376   void DecodeType4(Instruction* instr);
377   void DecodeType5(Instruction* instr);
378   void DecodeType6(Instruction* instr);
379   void DecodeType7(Instruction* instr);
380 
381   // CP15 coprocessor instructions.
382   void DecodeTypeCP15(Instruction* instr);
383 
384   // Support for VFP.
385   void DecodeTypeVFP(Instruction* instr);
386   void DecodeType6CoprocessorIns(Instruction* instr);
387   void DecodeSpecialCondition(Instruction* instr);
388 
389   void DecodeFloatingPointDataProcessing(Instruction* instr);
390   void DecodeUnconditional(Instruction* instr);
391   void DecodeAdvancedSIMDDataProcessing(Instruction* instr);
392   void DecodeMemoryHintsAndBarriers(Instruction* instr);
393   void DecodeAdvancedSIMDElementOrStructureLoadStore(Instruction* instr);
394   void DecodeAdvancedSIMDTwoOrThreeRegisters(Instruction* instr);
395 
396   void DecodeVMOVBetweenCoreAndSinglePrecisionRegisters(Instruction* instr);
397   void DecodeVCMP(Instruction* instr);
398   void DecodeVCVTBetweenDoubleAndSingle(Instruction* instr);
399   int32_t ConvertDoubleToInt(double val, bool unsigned_integer,
400                              VFPRoundingMode mode);
401   void DecodeVCVTBetweenFloatingPointAndInteger(Instruction* instr);
402 
403   // Executes one instruction.
404   void InstructionDecode(Instruction* instr);
405 
406   // ICache.
407   static void CheckICache(base::CustomMatcherHashMap* i_cache,
408                           Instruction* instr);
409   static void FlushOnePage(base::CustomMatcherHashMap* i_cache, intptr_t start,
410                            int size);
411   static CachePage* GetCachePage(base::CustomMatcherHashMap* i_cache,
412                                  void* page);
413 
414   // Handle arguments and return value for runtime FP functions.
415   void GetFpArgs(double* x, double* y, int32_t* z);
416   void SetFpResult(const double& result);
417   void TrashCallerSaveRegisters();
418 
419   template <class ReturnType, int register_size>
420   ReturnType GetFromVFPRegister(int reg_index);
421 
422   template <class InputType, int register_size>
423   void SetVFPRegister(int reg_index, const InputType& value);
424 
425   void SetSpecialRegister(SRegisterFieldMask reg_and_mask, uint32_t value);
426   uint32_t GetFromSpecialRegister(SRegister reg);
427 
428   void CallInternal(Address entry);
429 
430   // Architecture state.
431   // Saturating instructions require a Q flag to indicate saturation.
432   // There is currently no way to read the CPSR directly, and thus read the Q
433   // flag, so this is left unimplemented.
434   int32_t registers_[16];
435   bool n_flag_;
436   bool z_flag_;
437   bool c_flag_;
438   bool v_flag_;
439 
440   // VFP architecture state.
441   unsigned int vfp_registers_[num_d_registers * 2];
442   bool n_flag_FPSCR_;
443   bool z_flag_FPSCR_;
444   bool c_flag_FPSCR_;
445   bool v_flag_FPSCR_;
446 
447   // VFP rounding mode. See ARM DDI 0406B Page A2-29.
448   VFPRoundingMode FPSCR_rounding_mode_;
449   bool FPSCR_default_NaN_mode_;
450 
451   // VFP FP exception flags architecture state.
452   bool inv_op_vfp_flag_;
453   bool div_zero_vfp_flag_;
454   bool overflow_vfp_flag_;
455   bool underflow_vfp_flag_;
456   bool inexact_vfp_flag_;
457 
458   // Simulator support.
459   char* stack_;
460   bool pc_modified_;
461   int icount_;
462 
463   // Debugger input.
464   char* last_debugger_input_;
465 
466   // Registered breakpoints.
467   Instruction* break_pc_;
468   Instr break_instr_;
469 
470   v8::internal::Isolate* isolate_;
471 
472   // A stop is watched if its code is less than kNumOfWatchedStops.
473   // Only watched stops support enabling/disabling and the counter feature.
474   static const uint32_t kNumOfWatchedStops = 256;
475 
476   // Breakpoint is disabled if bit 31 is set.
477   static const uint32_t kStopDisabledBit = 1 << 31;
478 
479   // A stop is enabled, meaning the simulator will stop when meeting the
480   // instruction, if bit 31 of watched_stops_[code].count is unset.
481   // The value watched_stops_[code].count & ~(1 << 31) indicates how many times
482   // the breakpoint was hit or gone through.
483   struct StopCountAndDesc {
484     uint32_t count;
485     char* desc;
486   };
487   StopCountAndDesc watched_stops_[kNumOfWatchedStops];
488 
489   // Synchronization primitives. See ARM DDI 0406C.b, A2.9.
490   enum class MonitorAccess {
491     Open,
492     Exclusive,
493   };
494 
495   enum class TransactionSize {
496     None = 0,
497     Byte = 1,
498     HalfWord = 2,
499     Word = 4,
500     DoubleWord = 8,
501   };
502 
503   // The least-significant bits of the address are ignored. The number of bits
504   // is implementation-defined, between 3 and 11. See ARM DDI 0406C.b, A3.4.3.
505   static const int32_t kExclusiveTaggedAddrMask = ~((1 << 11) - 1);
506 
507   class LocalMonitor {
508    public:
509     LocalMonitor();
510 
511     // These functions manage the state machine for the local monitor, but do
512     // not actually perform loads and stores. NotifyStoreExcl only returns
513     // true if the exclusive store is allowed; the global monitor will still
514     // have to be checked to see whether the memory should be updated.
515     void NotifyLoad(int32_t addr);
516     void NotifyLoadExcl(int32_t addr, TransactionSize size);
517     void NotifyStore(int32_t addr);
518     bool NotifyStoreExcl(int32_t addr, TransactionSize size);
519 
520    private:
521     void Clear();
522 
523     MonitorAccess access_state_;
524     int32_t tagged_addr_;
525     TransactionSize size_;
526   };
527 
528   class GlobalMonitor {
529    public:
530     class Processor {
531      public:
532       Processor();
533 
534      private:
535       friend class GlobalMonitor;
536       // These functions manage the state machine for the global monitor, but do
537       // not actually perform loads and stores.
538       void Clear_Locked();
539       void NotifyLoadExcl_Locked(int32_t addr);
540       void NotifyStore_Locked(int32_t addr, bool is_requesting_processor);
541       bool NotifyStoreExcl_Locked(int32_t addr, bool is_requesting_processor);
542 
543       MonitorAccess access_state_;
544       int32_t tagged_addr_;
545       Processor* next_;
546       Processor* prev_;
547       // A strex can fail due to background cache evictions. Rather than
548       // simulating this, we'll just occasionally introduce cases where an
549       // exclusive store fails. This will happen once after every
550       // kMaxFailureCounter exclusive stores.
551       static const int kMaxFailureCounter = 5;
552       int failure_counter_;
553     };
554 
555     // Exposed so it can be accessed by Simulator::{Read,Write}Ex*.
556     base::Mutex mutex;
557 
558     void NotifyLoadExcl_Locked(int32_t addr, Processor* processor);
559     void NotifyStore_Locked(int32_t addr, Processor* processor);
560     bool NotifyStoreExcl_Locked(int32_t addr, Processor* processor);
561 
562     // Called when the simulator is destroyed.
563     void RemoveProcessor(Processor* processor);
564 
565     static GlobalMonitor* Get();
566 
567    private:
568     // Private constructor. Call {GlobalMonitor::Get()} to get the singleton.
569     GlobalMonitor() = default;
570     friend class base::LeakyObject<GlobalMonitor>;
571 
572     bool IsProcessorInLinkedList_Locked(Processor* processor) const;
573     void PrependProcessor_Locked(Processor* processor);
574 
575     Processor* head_ = nullptr;
576   };
577 
578   LocalMonitor local_monitor_;
579   GlobalMonitor::Processor global_monitor_processor_;
580 };
581 
582 }  // namespace internal
583 }  // namespace v8
584 
585 #endif  // defined(USE_SIMULATOR)
586 #endif  // V8_EXECUTION_ARM_SIMULATOR_ARM_H_
587