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