v8  3.14.5(node0.10.28)
V8 is Google's open source JavaScript engine
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
simulator-arm.h
Go to the documentation of this file.
1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are
4 // met:
5 //
6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided
11 // with the distribution.
12 // * Neither the name of Google Inc. nor the names of its
13 // contributors may be used to endorse or promote products derived
14 // from this software without specific prior written permission.
15 //
16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 
28 
29 // Declares a Simulator for ARM instructions if we are not generating a native
30 // ARM binary. This Simulator allows us to run and debug ARM code generation on
31 // regular desktop machines.
32 // V8 calls into generated code by "calling" the CALL_GENERATED_CODE macro,
33 // which will start execution in the Simulator or forwards to the real entry
34 // on a ARM HW platform.
35 
36 #ifndef V8_ARM_SIMULATOR_ARM_H_
37 #define V8_ARM_SIMULATOR_ARM_H_
38 
39 #include "allocation.h"
40 
41 #if !defined(USE_SIMULATOR)
42 // Running without a simulator on a native arm platform.
43 
44 namespace v8 {
45 namespace internal {
46 
47 // When running without a simulator we call the entry directly.
48 #define CALL_GENERATED_CODE(entry, p0, p1, p2, p3, p4) \
49  (entry(p0, p1, p2, p3, p4))
50 
51 typedef int (*arm_regexp_matcher)(String*, int, const byte*, const byte*,
52  void*, int*, int, Address, int, Isolate*);
53 
54 
55 // Call the generated regexp code directly. The code at the entry address
56 // should act as a function matching the type arm_regexp_matcher.
57 // The fifth argument is a dummy that reserves the space used for
58 // the return address added by the ExitFrame in native calls.
59 #define CALL_GENERATED_REGEXP_CODE(entry, p0, p1, p2, p3, p4, p5, p6, p7, p8) \
60  (FUNCTION_CAST<arm_regexp_matcher>(entry)( \
61  p0, p1, p2, p3, NULL, p4, p5, p6, p7, p8))
62 
63 #define TRY_CATCH_FROM_ADDRESS(try_catch_address) \
64  reinterpret_cast<TryCatch*>(try_catch_address)
65 
66 // The stack limit beyond which we will throw stack overflow errors in
67 // generated code. Because generated code on arm uses the C stack, we
68 // just use the C stack limit.
70  public:
71  static inline uintptr_t JsLimitFromCLimit(v8::internal::Isolate* isolate,
72  uintptr_t c_limit) {
73  USE(isolate);
74  return c_limit;
75  }
76 
77  static inline uintptr_t RegisterCTryCatch(uintptr_t try_catch_address) {
78  return try_catch_address;
79  }
80 
81  static inline void UnregisterCTryCatch() { }
82 };
83 
84 } } // namespace v8::internal
85 
86 #else // !defined(USE_SIMULATOR)
87 // Running with a simulator.
88 
89 #include "constants-arm.h"
90 #include "hashmap.h"
91 #include "assembler.h"
92 
93 namespace v8 {
94 namespace internal {
95 
96 class CachePage {
97  public:
98  static const int LINE_VALID = 0;
99  static const int LINE_INVALID = 1;
100 
101  static const int kPageShift = 12;
102  static const int kPageSize = 1 << kPageShift;
103  static const int kPageMask = kPageSize - 1;
104  static const int kLineShift = 2; // The cache line is only 4 bytes right now.
105  static const int kLineLength = 1 << kLineShift;
106  static const int kLineMask = kLineLength - 1;
107 
108  CachePage() {
109  memset(&validity_map_, LINE_INVALID, sizeof(validity_map_));
110  }
111 
112  char* ValidityByte(int offset) {
113  return &validity_map_[offset >> kLineShift];
114  }
115 
116  char* CachedData(int offset) {
117  return &data_[offset];
118  }
119 
120  private:
121  char data_[kPageSize]; // The cached data.
122  static const int kValidityMapSize = kPageSize >> kLineShift;
123  char validity_map_[kValidityMapSize]; // One byte per line.
124 };
125 
126 
127 class Simulator {
128  public:
129  friend class ArmDebugger;
130  enum Register {
131  no_reg = -1,
132  r0 = 0, r1, r2, r3, r4, r5, r6, r7,
133  r8, r9, r10, r11, r12, r13, r14, r15,
134  num_registers,
135  sp = 13,
136  lr = 14,
137  pc = 15,
138  s0 = 0, s1, s2, s3, s4, s5, s6, s7,
139  s8, s9, s10, s11, s12, s13, s14, s15,
140  s16, s17, s18, s19, s20, s21, s22, s23,
141  s24, s25, s26, s27, s28, s29, s30, s31,
142  num_s_registers = 32,
143  d0 = 0, d1, d2, d3, d4, d5, d6, d7,
144  d8, d9, d10, d11, d12, d13, d14, d15,
145  num_d_registers = 16
146  };
147 
148  explicit Simulator(Isolate* isolate);
149  ~Simulator();
150 
151  // The currently executing Simulator instance. Potentially there can be one
152  // for each native thread.
153  static Simulator* current(v8::internal::Isolate* isolate);
154 
155  // Accessors for register state. Reading the pc value adheres to the ARM
156  // architecture specification and is off by a 8 from the currently executing
157  // instruction.
158  void set_register(int reg, int32_t value);
159  int32_t get_register(int reg) const;
160  double get_double_from_register_pair(int reg);
161  void set_dw_register(int dreg, const int* dbl);
162 
163  // Support for VFP.
164  void set_s_register(int reg, unsigned int value);
165  unsigned int get_s_register(int reg) const;
166 
167  void set_d_register_from_double(int dreg, const double& dbl) {
168  SetVFPRegister<double, 2>(dreg, dbl);
169  }
170 
171  double get_double_from_d_register(int dreg) {
172  return GetFromVFPRegister<double, 2>(dreg);
173  }
174 
175  void set_s_register_from_float(int sreg, const float flt) {
176  SetVFPRegister<float, 1>(sreg, flt);
177  }
178 
179  float get_float_from_s_register(int sreg) {
180  return GetFromVFPRegister<float, 1>(sreg);
181  }
182 
183  void set_s_register_from_sinteger(int sreg, const int sint) {
184  SetVFPRegister<int, 1>(sreg, sint);
185  }
186 
187  int get_sinteger_from_s_register(int sreg) {
188  return GetFromVFPRegister<int, 1>(sreg);
189  }
190 
191  // Special case of set_register and get_register to access the raw PC value.
192  void set_pc(int32_t value);
193  int32_t get_pc() const;
194 
195  // Accessor to the internal simulator stack area.
196  uintptr_t StackLimit() const;
197 
198  // Executes ARM instructions until the PC reaches end_sim_pc.
199  void Execute();
200 
201  // Call on program start.
202  static void Initialize(Isolate* isolate);
203 
204  // V8 generally calls into generated JS code with 5 parameters and into
205  // generated RegExp code with 7 parameters. This is a convenience function,
206  // which sets up the simulator state and grabs the result on return.
207  int32_t Call(byte* entry, int argument_count, ...);
208 
209  // Push an address onto the JS stack.
210  uintptr_t PushAddress(uintptr_t address);
211 
212  // Pop an address from the JS stack.
213  uintptr_t PopAddress();
214 
215  // Debugger input.
216  void set_last_debugger_input(char* input);
217  char* last_debugger_input() { return last_debugger_input_; }
218 
219  // ICache checking.
220  static void FlushICache(v8::internal::HashMap* i_cache, void* start,
221  size_t size);
222 
223  // Returns true if pc register contains one of the 'special_values' defined
224  // below (bad_lr, end_sim_pc).
225  bool has_bad_pc() const;
226 
227  // EABI variant for double arguments in use.
228  bool use_eabi_hardfloat() {
229 #if USE_EABI_HARDFLOAT
230  return true;
231 #else
232  return false;
233 #endif
234  }
235 
236  private:
237  enum special_values {
238  // Known bad pc value to ensure that the simulator does not execute
239  // without being properly setup.
240  bad_lr = -1,
241  // A pc value used to signal the simulator to stop execution. Generally
242  // the lr is set to this value on transition from native C code to
243  // simulated execution, so that the simulator can "return" to the native
244  // C code.
245  end_sim_pc = -2
246  };
247 
248  // Unsupported instructions use Format to print an error and stop execution.
249  void Format(Instruction* instr, const char* format);
250 
251  // Checks if the current instruction should be executed based on its
252  // condition bits.
253  bool ConditionallyExecute(Instruction* instr);
254 
255  // Helper functions to set the conditional flags in the architecture state.
256  void SetNZFlags(int32_t val);
257  void SetCFlag(bool val);
258  void SetVFlag(bool val);
259  bool CarryFrom(int32_t left, int32_t right, int32_t carry = 0);
260  bool BorrowFrom(int32_t left, int32_t right);
261  bool OverflowFrom(int32_t alu_out,
262  int32_t left,
263  int32_t right,
264  bool addition);
265 
266  inline int GetCarry() {
267  return c_flag_ ? 1 : 0;
268  };
269 
270  // Support for VFP.
271  void Compute_FPSCR_Flags(double val1, double val2);
272  void Copy_FPSCR_to_APSR();
273 
274  // Helper functions to decode common "addressing" modes
275  int32_t GetShiftRm(Instruction* instr, bool* carry_out);
276  int32_t GetImm(Instruction* instr, bool* carry_out);
277  void ProcessPUW(Instruction* instr,
278  int num_regs,
279  int operand_size,
280  intptr_t* start_address,
281  intptr_t* end_address);
282  void HandleRList(Instruction* instr, bool load);
283  void HandleVList(Instruction* inst);
284  void SoftwareInterrupt(Instruction* instr);
285 
286  // Stop helper functions.
287  inline bool isStopInstruction(Instruction* instr);
288  inline bool isWatchedStop(uint32_t bkpt_code);
289  inline bool isEnabledStop(uint32_t bkpt_code);
290  inline void EnableStop(uint32_t bkpt_code);
291  inline void DisableStop(uint32_t bkpt_code);
292  inline void IncreaseStopCounter(uint32_t bkpt_code);
293  void PrintStopInfo(uint32_t code);
294 
295  // Read and write memory.
296  inline uint8_t ReadBU(int32_t addr);
297  inline int8_t ReadB(int32_t addr);
298  inline void WriteB(int32_t addr, uint8_t value);
299  inline void WriteB(int32_t addr, int8_t value);
300 
301  inline uint16_t ReadHU(int32_t addr, Instruction* instr);
302  inline int16_t ReadH(int32_t addr, Instruction* instr);
303  // Note: Overloaded on the sign of the value.
304  inline void WriteH(int32_t addr, uint16_t value, Instruction* instr);
305  inline void WriteH(int32_t addr, int16_t value, Instruction* instr);
306 
307  inline int ReadW(int32_t addr, Instruction* instr);
308  inline void WriteW(int32_t addr, int value, Instruction* instr);
309 
310  int32_t* ReadDW(int32_t addr);
311  void WriteDW(int32_t addr, int32_t value1, int32_t value2);
312 
313  // Executing is handled based on the instruction type.
314  // Both type 0 and type 1 rolled into one.
315  void DecodeType01(Instruction* instr);
316  void DecodeType2(Instruction* instr);
317  void DecodeType3(Instruction* instr);
318  void DecodeType4(Instruction* instr);
319  void DecodeType5(Instruction* instr);
320  void DecodeType6(Instruction* instr);
321  void DecodeType7(Instruction* instr);
322 
323  // Support for VFP.
324  void DecodeTypeVFP(Instruction* instr);
325  void DecodeType6CoprocessorIns(Instruction* instr);
326 
327  void DecodeVMOVBetweenCoreAndSinglePrecisionRegisters(Instruction* instr);
328  void DecodeVCMP(Instruction* instr);
329  void DecodeVCVTBetweenDoubleAndSingle(Instruction* instr);
330  void DecodeVCVTBetweenFloatingPointAndInteger(Instruction* instr);
331 
332  // Executes one instruction.
333  void InstructionDecode(Instruction* instr);
334 
335  // ICache.
336  static void CheckICache(v8::internal::HashMap* i_cache, Instruction* instr);
337  static void FlushOnePage(v8::internal::HashMap* i_cache, intptr_t start,
338  int size);
339  static CachePage* GetCachePage(v8::internal::HashMap* i_cache, void* page);
340 
341  // Runtime call support.
342  static void* RedirectExternalReference(
343  void* external_function,
344  v8::internal::ExternalReference::Type type);
345 
346  // For use in calls that take double value arguments.
347  void GetFpArgs(double* x, double* y);
348  void GetFpArgs(double* x);
349  void GetFpArgs(double* x, int32_t* y);
350  void SetFpResult(const double& result);
351  void TrashCallerSaveRegisters();
352 
353  template<class ReturnType, int register_size>
354  ReturnType GetFromVFPRegister(int reg_index);
355 
356  template<class InputType, int register_size>
357  void SetVFPRegister(int reg_index, const InputType& value);
358 
359  // Architecture state.
360  // Saturating instructions require a Q flag to indicate saturation.
361  // There is currently no way to read the CPSR directly, and thus read the Q
362  // flag, so this is left unimplemented.
363  int32_t registers_[16];
364  bool n_flag_;
365  bool z_flag_;
366  bool c_flag_;
367  bool v_flag_;
368 
369  // VFP architecture state.
370  unsigned int vfp_register[num_s_registers];
371  bool n_flag_FPSCR_;
372  bool z_flag_FPSCR_;
373  bool c_flag_FPSCR_;
374  bool v_flag_FPSCR_;
375 
376  // VFP rounding mode. See ARM DDI 0406B Page A2-29.
377  VFPRoundingMode FPSCR_rounding_mode_;
378 
379  // VFP FP exception flags architecture state.
380  bool inv_op_vfp_flag_;
381  bool div_zero_vfp_flag_;
382  bool overflow_vfp_flag_;
383  bool underflow_vfp_flag_;
384  bool inexact_vfp_flag_;
385 
386  // Simulator support.
387  char* stack_;
388  bool pc_modified_;
389  int icount_;
390 
391  // Debugger input.
392  char* last_debugger_input_;
393 
394  // Icache simulation
395  v8::internal::HashMap* i_cache_;
396 
397  // Registered breakpoints.
398  Instruction* break_pc_;
399  Instr break_instr_;
400 
401  v8::internal::Isolate* isolate_;
402 
403  // A stop is watched if its code is less than kNumOfWatchedStops.
404  // Only watched stops support enabling/disabling and the counter feature.
405  static const uint32_t kNumOfWatchedStops = 256;
406 
407  // Breakpoint is disabled if bit 31 is set.
408  static const uint32_t kStopDisabledBit = 1 << 31;
409 
410  // A stop is enabled, meaning the simulator will stop when meeting the
411  // instruction, if bit 31 of watched_stops[code].count is unset.
412  // The value watched_stops[code].count & ~(1 << 31) indicates how many times
413  // the breakpoint was hit or gone through.
414  struct StopCountAndDesc {
415  uint32_t count;
416  char* desc;
417  };
418  StopCountAndDesc watched_stops[kNumOfWatchedStops];
419 };
420 
421 
422 // When running with the simulator transition into simulated execution at this
423 // point.
424 #define CALL_GENERATED_CODE(entry, p0, p1, p2, p3, p4) \
425  reinterpret_cast<Object*>(Simulator::current(Isolate::Current())->Call( \
426  FUNCTION_ADDR(entry), 5, p0, p1, p2, p3, p4))
427 
428 #define CALL_GENERATED_REGEXP_CODE(entry, p0, p1, p2, p3, p4, p5, p6, p7, p8) \
429  Simulator::current(Isolate::Current())->Call( \
430  entry, 10, p0, p1, p2, p3, NULL, p4, p5, p6, p7, p8)
431 
432 #define TRY_CATCH_FROM_ADDRESS(try_catch_address) \
433  try_catch_address == NULL ? \
434  NULL : *(reinterpret_cast<TryCatch**>(try_catch_address))
435 
436 
437 // The simulator has its own stack. Thus it has a different stack limit from
438 // the C-based native code. Setting the c_limit to indicate a very small
439 // stack cause stack overflow errors, since the simulator ignores the input.
440 // This is unlikely to be an issue in practice, though it might cause testing
441 // trouble down the line.
442 class SimulatorStack : public v8::internal::AllStatic {
443  public:
444  static inline uintptr_t JsLimitFromCLimit(v8::internal::Isolate* isolate,
445  uintptr_t c_limit) {
446  return Simulator::current(isolate)->StackLimit();
447  }
448 
449  static inline uintptr_t RegisterCTryCatch(uintptr_t try_catch_address) {
450  Simulator* sim = Simulator::current(Isolate::Current());
451  return sim->PushAddress(try_catch_address);
452  }
453 
454  static inline void UnregisterCTryCatch() {
455  Simulator::current(Isolate::Current())->PopAddress();
456  }
457 };
458 
459 } } // namespace v8::internal
460 
461 #endif // !defined(USE_SIMULATOR)
462 #endif // V8_ARM_SIMULATOR_ARM_H_
byte * Address
Definition: globals.h:157
const SwVfpRegister s2
const DwVfpRegister d11
const SwVfpRegister s28
const SwVfpRegister s12
const SwVfpRegister s29
const Register r14
const SwVfpRegister s25
const SwVfpRegister s26
const SwVfpRegister s17
const Register r3
const Register r11
const SwVfpRegister s7
const SwVfpRegister s8
const SwVfpRegister s10
const DwVfpRegister d8
const DwVfpRegister d5
const DwVfpRegister d0
const SwVfpRegister s16
const Register r6
int int32_t
Definition: unicode.cc:47
const SwVfpRegister s14
const SwVfpRegister s21
const DwVfpRegister d12
const DwVfpRegister d6
unsigned short uint16_t
Definition: unicode.cc:46
static void UnregisterCTryCatch()
Definition: simulator-arm.h:81
const Register r2
const DwVfpRegister d9
const SwVfpRegister s23
const SwVfpRegister s22
const SwVfpRegister s6
const SwVfpRegister s31
uint8_t byte
Definition: globals.h:156
const SwVfpRegister s18
const Register sp
const SwVfpRegister s3
const DwVfpRegister d13
const SwVfpRegister s13
const Register r9
const SwVfpRegister s27
const DwVfpRegister d7
static uintptr_t JsLimitFromCLimit(v8::internal::Isolate *isolate, uintptr_t c_limit)
Definition: simulator-arm.h:71
const Register pc
const Register r12
const SwVfpRegister s0
const Register r13
const DwVfpRegister d3
const Register r0
const SwVfpRegister s19
const SwVfpRegister s5
const SwVfpRegister s1
const Register lr
const Register r1
const DwVfpRegister d14
const SwVfpRegister s30
const Register r8
void USE(T)
Definition: globals.h:289
const SwVfpRegister s4
const DwVfpRegister d2
const SwVfpRegister s20
const SwVfpRegister s9
const Register r10
const Register no_reg
activate correct semantics for inheriting readonliness enable harmony semantics for typeof enable harmony enable harmony proxies enable all harmony harmony_scoping harmony_proxies harmony_scoping tracks arrays with only smi values automatically unbox arrays of doubles use crankshaft use hydrogen range analysis use hydrogen global value numbering use function inlining maximum number of AST nodes considered for a single inlining loop invariant code motion print statistics for hydrogen trace generated IR for specified phases trace register allocator trace range analysis trace representation types environment for every instruction put a break point before deoptimizing polymorphic inlining perform array bounds checks elimination use dead code elimination trace on stack replacement optimize closures cache optimized code for closures functions with arguments object loop weight for representation inference allow uint32 values on optimize frames if they are used only in safe operations track parallel recompilation enable all profiler experiments number of stack frames inspected by the profiler call recompile stub directly when self optimizing trigger profiler ticks based on counting instead of timing weight back edges by jump distance for interrupt triggering percentage of ICs that must have type info to allow optimization watch_ic_patching retry_self_opt interrupt_at_exit extra verbose compilation tracing generate extra code(assertions) for debugging") DEFINE_bool(code_comments
const DwVfpRegister d1
static uintptr_t RegisterCTryCatch(uintptr_t try_catch_address)
Definition: simulator-arm.h:77
const DwVfpRegister d10
signed short int16_t
Definition: unicode.cc:45
const SwVfpRegister s11
int(* arm_regexp_matcher)(String *, int, const byte *, const byte *, void *, int *, int, Address, int, Isolate *)
Definition: simulator-arm.h:51
const SwVfpRegister s15
const Register r15
const Register r5
const DwVfpRegister d15
const DwVfpRegister d4
const SwVfpRegister s24
const Register r4
const Register r7