v8  3.11.10(node0.8.26)
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  void set_d_register_from_double(int dreg, const double& dbl);
167  double get_double_from_d_register(int dreg);
168  void set_s_register_from_float(int sreg, const float dbl);
169  float get_float_from_s_register(int sreg);
170  void set_s_register_from_sinteger(int reg, const int value);
171  int get_sinteger_from_s_register(int reg);
172 
173  // Special case of set_register and get_register to access the raw PC value.
174  void set_pc(int32_t value);
175  int32_t get_pc() const;
176 
177  // Accessor to the internal simulator stack area.
178  uintptr_t StackLimit() const;
179 
180  // Executes ARM instructions until the PC reaches end_sim_pc.
181  void Execute();
182 
183  // Call on program start.
184  static void Initialize(Isolate* isolate);
185 
186  // V8 generally calls into generated JS code with 5 parameters and into
187  // generated RegExp code with 7 parameters. This is a convenience function,
188  // which sets up the simulator state and grabs the result on return.
189  int32_t Call(byte* entry, int argument_count, ...);
190 
191  // Push an address onto the JS stack.
192  uintptr_t PushAddress(uintptr_t address);
193 
194  // Pop an address from the JS stack.
195  uintptr_t PopAddress();
196 
197  // Debugger input.
198  void set_last_debugger_input(char* input);
199  char* last_debugger_input() { return last_debugger_input_; }
200 
201  // ICache checking.
202  static void FlushICache(v8::internal::HashMap* i_cache, void* start,
203  size_t size);
204 
205  // Returns true if pc register contains one of the 'special_values' defined
206  // below (bad_lr, end_sim_pc).
207  bool has_bad_pc() const;
208 
209  // EABI variant for double arguments in use.
210  bool use_eabi_hardfloat() {
211 #if USE_EABI_HARDFLOAT
212  return true;
213 #else
214  return false;
215 #endif
216  }
217 
218  private:
219  enum special_values {
220  // Known bad pc value to ensure that the simulator does not execute
221  // without being properly setup.
222  bad_lr = -1,
223  // A pc value used to signal the simulator to stop execution. Generally
224  // the lr is set to this value on transition from native C code to
225  // simulated execution, so that the simulator can "return" to the native
226  // C code.
227  end_sim_pc = -2
228  };
229 
230  // Unsupported instructions use Format to print an error and stop execution.
231  void Format(Instruction* instr, const char* format);
232 
233  // Checks if the current instruction should be executed based on its
234  // condition bits.
235  bool ConditionallyExecute(Instruction* instr);
236 
237  // Helper functions to set the conditional flags in the architecture state.
238  void SetNZFlags(int32_t val);
239  void SetCFlag(bool val);
240  void SetVFlag(bool val);
241  bool CarryFrom(int32_t left, int32_t right, int32_t carry = 0);
242  bool BorrowFrom(int32_t left, int32_t right);
243  bool OverflowFrom(int32_t alu_out,
244  int32_t left,
245  int32_t right,
246  bool addition);
247 
248  inline int GetCarry() {
249  return c_flag_ ? 1 : 0;
250  };
251 
252  // Support for VFP.
253  void Compute_FPSCR_Flags(double val1, double val2);
254  void Copy_FPSCR_to_APSR();
255 
256  // Helper functions to decode common "addressing" modes
257  int32_t GetShiftRm(Instruction* instr, bool* carry_out);
258  int32_t GetImm(Instruction* instr, bool* carry_out);
259  void ProcessPUW(Instruction* instr,
260  int num_regs,
261  int operand_size,
262  intptr_t* start_address,
263  intptr_t* end_address);
264  void HandleRList(Instruction* instr, bool load);
265  void HandleVList(Instruction* inst);
266  void SoftwareInterrupt(Instruction* instr);
267 
268  // Stop helper functions.
269  inline bool isStopInstruction(Instruction* instr);
270  inline bool isWatchedStop(uint32_t bkpt_code);
271  inline bool isEnabledStop(uint32_t bkpt_code);
272  inline void EnableStop(uint32_t bkpt_code);
273  inline void DisableStop(uint32_t bkpt_code);
274  inline void IncreaseStopCounter(uint32_t bkpt_code);
275  void PrintStopInfo(uint32_t code);
276 
277  // Read and write memory.
278  inline uint8_t ReadBU(int32_t addr);
279  inline int8_t ReadB(int32_t addr);
280  inline void WriteB(int32_t addr, uint8_t value);
281  inline void WriteB(int32_t addr, int8_t value);
282 
283  inline uint16_t ReadHU(int32_t addr, Instruction* instr);
284  inline int16_t ReadH(int32_t addr, Instruction* instr);
285  // Note: Overloaded on the sign of the value.
286  inline void WriteH(int32_t addr, uint16_t value, Instruction* instr);
287  inline void WriteH(int32_t addr, int16_t value, Instruction* instr);
288 
289  inline int ReadW(int32_t addr, Instruction* instr);
290  inline void WriteW(int32_t addr, int value, Instruction* instr);
291 
292  int32_t* ReadDW(int32_t addr);
293  void WriteDW(int32_t addr, int32_t value1, int32_t value2);
294 
295  // Executing is handled based on the instruction type.
296  // Both type 0 and type 1 rolled into one.
297  void DecodeType01(Instruction* instr);
298  void DecodeType2(Instruction* instr);
299  void DecodeType3(Instruction* instr);
300  void DecodeType4(Instruction* instr);
301  void DecodeType5(Instruction* instr);
302  void DecodeType6(Instruction* instr);
303  void DecodeType7(Instruction* instr);
304 
305  // Support for VFP.
306  void DecodeTypeVFP(Instruction* instr);
307  void DecodeType6CoprocessorIns(Instruction* instr);
308 
309  void DecodeVMOVBetweenCoreAndSinglePrecisionRegisters(Instruction* instr);
310  void DecodeVCMP(Instruction* instr);
311  void DecodeVCVTBetweenDoubleAndSingle(Instruction* instr);
312  void DecodeVCVTBetweenFloatingPointAndInteger(Instruction* instr);
313 
314  // Executes one instruction.
315  void InstructionDecode(Instruction* instr);
316 
317  // ICache.
318  static void CheckICache(v8::internal::HashMap* i_cache, Instruction* instr);
319  static void FlushOnePage(v8::internal::HashMap* i_cache, intptr_t start,
320  int size);
321  static CachePage* GetCachePage(v8::internal::HashMap* i_cache, void* page);
322 
323  // Runtime call support.
324  static void* RedirectExternalReference(
325  void* external_function,
326  v8::internal::ExternalReference::Type type);
327 
328  // For use in calls that take double value arguments.
329  void GetFpArgs(double* x, double* y);
330  void GetFpArgs(double* x);
331  void GetFpArgs(double* x, int32_t* y);
332  void SetFpResult(const double& result);
333  void TrashCallerSaveRegisters();
334 
335  // Architecture state.
336  // Saturating instructions require a Q flag to indicate saturation.
337  // There is currently no way to read the CPSR directly, and thus read the Q
338  // flag, so this is left unimplemented.
339  int32_t registers_[16];
340  bool n_flag_;
341  bool z_flag_;
342  bool c_flag_;
343  bool v_flag_;
344 
345  // VFP architecture state.
346  unsigned int vfp_register[num_s_registers];
347  bool n_flag_FPSCR_;
348  bool z_flag_FPSCR_;
349  bool c_flag_FPSCR_;
350  bool v_flag_FPSCR_;
351 
352  // VFP rounding mode. See ARM DDI 0406B Page A2-29.
353  VFPRoundingMode FPSCR_rounding_mode_;
354 
355  // VFP FP exception flags architecture state.
356  bool inv_op_vfp_flag_;
357  bool div_zero_vfp_flag_;
358  bool overflow_vfp_flag_;
359  bool underflow_vfp_flag_;
360  bool inexact_vfp_flag_;
361 
362  // Simulator support.
363  char* stack_;
364  bool pc_modified_;
365  int icount_;
366 
367  // Debugger input.
368  char* last_debugger_input_;
369 
370  // Icache simulation
371  v8::internal::HashMap* i_cache_;
372 
373  // Registered breakpoints.
374  Instruction* break_pc_;
375  Instr break_instr_;
376 
377  v8::internal::Isolate* isolate_;
378 
379  // A stop is watched if its code is less than kNumOfWatchedStops.
380  // Only watched stops support enabling/disabling and the counter feature.
381  static const uint32_t kNumOfWatchedStops = 256;
382 
383  // Breakpoint is disabled if bit 31 is set.
384  static const uint32_t kStopDisabledBit = 1 << 31;
385 
386  // A stop is enabled, meaning the simulator will stop when meeting the
387  // instruction, if bit 31 of watched_stops[code].count is unset.
388  // The value watched_stops[code].count & ~(1 << 31) indicates how many times
389  // the breakpoint was hit or gone through.
390  struct StopCountAndDesc {
391  uint32_t count;
392  char* desc;
393  };
394  StopCountAndDesc watched_stops[kNumOfWatchedStops];
395 };
396 
397 
398 // When running with the simulator transition into simulated execution at this
399 // point.
400 #define CALL_GENERATED_CODE(entry, p0, p1, p2, p3, p4) \
401  reinterpret_cast<Object*>(Simulator::current(Isolate::Current())->Call( \
402  FUNCTION_ADDR(entry), 5, p0, p1, p2, p3, p4))
403 
404 #define CALL_GENERATED_REGEXP_CODE(entry, p0, p1, p2, p3, p4, p5, p6, p7, p8) \
405  Simulator::current(Isolate::Current())->Call( \
406  entry, 10, p0, p1, p2, p3, NULL, p4, p5, p6, p7, p8)
407 
408 #define TRY_CATCH_FROM_ADDRESS(try_catch_address) \
409  try_catch_address == NULL ? \
410  NULL : *(reinterpret_cast<TryCatch**>(try_catch_address))
411 
412 
413 // The simulator has its own stack. Thus it has a different stack limit from
414 // the C-based native code. Setting the c_limit to indicate a very small
415 // stack cause stack overflow errors, since the simulator ignores the input.
416 // This is unlikely to be an issue in practice, though it might cause testing
417 // trouble down the line.
418 class SimulatorStack : public v8::internal::AllStatic {
419  public:
420  static inline uintptr_t JsLimitFromCLimit(v8::internal::Isolate* isolate,
421  uintptr_t c_limit) {
422  return Simulator::current(isolate)->StackLimit();
423  }
424 
425  static inline uintptr_t RegisterCTryCatch(uintptr_t try_catch_address) {
426  Simulator* sim = Simulator::current(Isolate::Current());
427  return sim->PushAddress(try_catch_address);
428  }
429 
430  static inline void UnregisterCTryCatch() {
431  Simulator::current(Isolate::Current())->PopAddress();
432  }
433 };
434 
435 } } // namespace v8::internal
436 
437 #endif // !defined(USE_SIMULATOR)
438 #endif // V8_ARM_SIMULATOR_ARM_H_
byte * Address
Definition: globals.h:172
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:171
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:303
const SwVfpRegister s4
const DwVfpRegister d2
const SwVfpRegister s20
const SwVfpRegister s9
const Register r10
const Register no_reg
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
FlagType type() const
Definition: flags.cc:1358
const Register r5
const DwVfpRegister d15
const DwVfpRegister d4
const SwVfpRegister s24
const Register r4
const Register r7