V8 Project
simulator-arm64.h
Go to the documentation of this file.
1 // Copyright 2013 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 #ifndef V8_ARM64_SIMULATOR_ARM64_H_
6 #define V8_ARM64_SIMULATOR_ARM64_H_
7 
8 #include <stdarg.h>
9 #include <vector>
10 
11 #include "src/v8.h"
12 
13 #include "src/allocation.h"
16 #include "src/arm64/disasm-arm64.h"
18 #include "src/assembler.h"
19 #include "src/globals.h"
20 #include "src/utils.h"
21 
22 #define REGISTER_CODE_LIST(R) \
23 R(0) R(1) R(2) R(3) R(4) R(5) R(6) R(7) \
24 R(8) R(9) R(10) R(11) R(12) R(13) R(14) R(15) \
25 R(16) R(17) R(18) R(19) R(20) R(21) R(22) R(23) \
26 R(24) R(25) R(26) R(27) R(28) R(29) R(30) R(31)
27 
28 namespace v8 {
29 namespace internal {
30 
31 #if !defined(USE_SIMULATOR)
32 
33 // Running without a simulator on a native ARM64 platform.
34 // When running without a simulator we call the entry directly.
35 #define CALL_GENERATED_CODE(entry, p0, p1, p2, p3, p4) \
36  (entry(p0, p1, p2, p3, p4))
37 
38 typedef int (*arm64_regexp_matcher)(String* input,
39  int64_t start_offset,
40  const byte* input_start,
41  const byte* input_end,
42  int* output,
43  int64_t output_size,
44  Address stack_base,
45  int64_t direct_call,
46  void* return_address,
47  Isolate* isolate);
48 
49 // Call the generated regexp code directly. The code at the entry address
50 // should act as a function matching the type arm64_regexp_matcher.
51 // The ninth argument is a dummy that reserves the space used for
52 // the return address added by the ExitFrame in native calls.
53 #define CALL_GENERATED_REGEXP_CODE(entry, p0, p1, p2, p3, p4, p5, p6, p7, p8) \
54  (FUNCTION_CAST<arm64_regexp_matcher>(entry)( \
55  p0, p1, p2, p3, p4, p5, p6, p7, NULL, p8))
56 
57 // Running without a simulator there is nothing to do.
58 class SimulatorStack : public v8::internal::AllStatic {
59  public:
61  uintptr_t c_limit) {
62  USE(isolate);
63  return c_limit;
64  }
65 
66  static uintptr_t RegisterCTryCatch(uintptr_t try_catch_address) {
67  return try_catch_address;
68  }
69 
70  static void UnregisterCTryCatch() { }
71 };
72 
73 #else // !defined(USE_SIMULATOR)
74 
75 enum ReverseByteMode {
76  Reverse16 = 0,
77  Reverse32 = 1,
78  Reverse64 = 2
79 };
80 
81 
82 // The proper way to initialize a simulated system register (such as NZCV) is as
83 // follows:
84 // SimSystemRegister nzcv = SimSystemRegister::DefaultValueFor(NZCV);
85 class SimSystemRegister {
86  public:
87  // The default constructor represents a register which has no writable bits.
88  // It is not possible to set its value to anything other than 0.
89  SimSystemRegister() : value_(0), write_ignore_mask_(0xffffffff) { }
90 
91  uint32_t RawValue() const {
92  return value_;
93  }
94 
95  void SetRawValue(uint32_t new_value) {
96  value_ = (value_ & write_ignore_mask_) | (new_value & ~write_ignore_mask_);
97  }
98 
99  uint32_t Bits(int msb, int lsb) const {
100  return unsigned_bitextract_32(msb, lsb, value_);
101  }
102 
103  int32_t SignedBits(int msb, int lsb) const {
104  return signed_bitextract_32(msb, lsb, value_);
105  }
106 
107  void SetBits(int msb, int lsb, uint32_t bits);
108 
109  // Default system register values.
110  static SimSystemRegister DefaultValueFor(SystemRegister id);
111 
112 #define DEFINE_GETTER(Name, HighBit, LowBit, Func, Type) \
113  Type Name() const { return static_cast<Type>(Func(HighBit, LowBit)); } \
114  void Set##Name(Type bits) { \
115  SetBits(HighBit, LowBit, static_cast<Type>(bits)); \
116  }
117 #define DEFINE_WRITE_IGNORE_MASK(Name, Mask) \
118  static const uint32_t Name##WriteIgnoreMask = ~static_cast<uint32_t>(Mask);
119  SYSTEM_REGISTER_FIELDS_LIST(DEFINE_GETTER, DEFINE_WRITE_IGNORE_MASK)
120 #undef DEFINE_ZERO_BITS
121 #undef DEFINE_GETTER
122 
123  protected:
124  // Most system registers only implement a few of the bits in the word. Other
125  // bits are "read-as-zero, write-ignored". The write_ignore_mask argument
126  // describes the bits which are not modifiable.
127  SimSystemRegister(uint32_t value, uint32_t write_ignore_mask)
128  : value_(value), write_ignore_mask_(write_ignore_mask) { }
129 
130  uint32_t value_;
131  uint32_t write_ignore_mask_;
132 };
133 
134 
135 // Represent a register (r0-r31, v0-v31).
136 class SimRegisterBase {
137  public:
138  template<typename T>
139  void Set(T new_value) {
140  value_ = 0;
141  memcpy(&value_, &new_value, sizeof(T));
142  }
143 
144  template<typename T>
145  T Get() const {
146  T result;
147  memcpy(&result, &value_, sizeof(T));
148  return result;
149  }
150 
151  protected:
152  int64_t value_;
153 };
154 
155 
156 typedef SimRegisterBase SimRegister; // r0-r31
157 typedef SimRegisterBase SimFPRegister; // v0-v31
158 
159 
160 class Simulator : public DecoderVisitor {
161  public:
162  explicit Simulator(Decoder<DispatchingDecoderVisitor>* decoder,
163  Isolate* isolate = NULL,
164  FILE* stream = stderr);
165  Simulator();
166  ~Simulator();
167 
168  // System functions.
169 
170  static void Initialize(Isolate* isolate);
171 
172  static Simulator* current(v8::internal::Isolate* isolate);
173 
174  class CallArgument;
175 
176  // Call an arbitrary function taking an arbitrary number of arguments. The
177  // varargs list must be a set of arguments with type CallArgument, and
178  // terminated by CallArgument::End().
179  void CallVoid(byte* entry, CallArgument* args);
180 
181  // Like CallVoid, but expect a return value.
182  int64_t CallInt64(byte* entry, CallArgument* args);
183  double CallDouble(byte* entry, CallArgument* args);
184 
185  // V8 calls into generated JS code with 5 parameters and into
186  // generated RegExp code with 10 parameters. These are convenience functions,
187  // which set up the simulator state and grab the result on return.
188  int64_t CallJS(byte* entry,
189  byte* function_entry,
190  JSFunction* func,
191  Object* revc,
192  int64_t argc,
193  Object*** argv);
194  int64_t CallRegExp(byte* entry,
195  String* input,
196  int64_t start_offset,
197  const byte* input_start,
198  const byte* input_end,
199  int* output,
200  int64_t output_size,
201  Address stack_base,
202  int64_t direct_call,
203  void* return_address,
204  Isolate* isolate);
205 
206  // A wrapper class that stores an argument for one of the above Call
207  // functions.
208  //
209  // Only arguments up to 64 bits in size are supported.
210  class CallArgument {
211  public:
212  template<typename T>
213  explicit CallArgument(T argument) {
214  bits_ = 0;
215  DCHECK(sizeof(argument) <= sizeof(bits_));
216  memcpy(&bits_, &argument, sizeof(argument));
217  type_ = X_ARG;
218  }
219 
220  explicit CallArgument(double argument) {
221  DCHECK(sizeof(argument) == sizeof(bits_));
222  memcpy(&bits_, &argument, sizeof(argument));
223  type_ = D_ARG;
224  }
225 
226  explicit CallArgument(float argument) {
227  // TODO(all): CallArgument(float) is untested, remove this check once
228  // tested.
229  UNIMPLEMENTED();
230  // Make the D register a NaN to try to trap errors if the callee expects a
231  // double. If it expects a float, the callee should ignore the top word.
232  DCHECK(sizeof(kFP64SignallingNaN) == sizeof(bits_));
233  memcpy(&bits_, &kFP64SignallingNaN, sizeof(kFP64SignallingNaN));
234  // Write the float payload to the S register.
235  DCHECK(sizeof(argument) <= sizeof(bits_));
236  memcpy(&bits_, &argument, sizeof(argument));
237  type_ = D_ARG;
238  }
239 
240  // This indicates the end of the arguments list, so that CallArgument
241  // objects can be passed into varargs functions.
242  static CallArgument End() { return CallArgument(); }
243 
244  int64_t bits() const { return bits_; }
245  bool IsEnd() const { return type_ == NO_ARG; }
246  bool IsX() const { return type_ == X_ARG; }
247  bool IsD() const { return type_ == D_ARG; }
248 
249  private:
250  enum CallArgumentType { X_ARG, D_ARG, NO_ARG };
251 
252  // All arguments are aligned to at least 64 bits and we don't support
253  // passing bigger arguments, so the payload size can be fixed at 64 bits.
254  int64_t bits_;
255  CallArgumentType type_;
256 
257  CallArgument() { type_ = NO_ARG; }
258  };
259 
260 
261  // Start the debugging command line.
262  void Debug();
263 
264  bool GetValue(const char* desc, int64_t* value);
265 
266  bool PrintValue(const char* desc);
267 
268  // Push an address onto the JS stack.
269  uintptr_t PushAddress(uintptr_t address);
270 
271  // Pop an address from the JS stack.
272  uintptr_t PopAddress();
273 
274  // Accessor to the internal simulator stack area.
275  uintptr_t StackLimit() const;
276 
277  void ResetState();
278 
279  // Runtime call support.
280  static void* RedirectExternalReference(void* external_function,
282  void DoRuntimeCall(Instruction* instr);
283 
284  // Run the simulator.
285  static const Instruction* kEndOfSimAddress;
286  void DecodeInstruction();
287  void Run();
288  void RunFrom(Instruction* start);
289 
290  // Simulation helpers.
291  template <typename T>
292  void set_pc(T new_pc) {
293  DCHECK(sizeof(T) == sizeof(pc_));
294  memcpy(&pc_, &new_pc, sizeof(T));
295  pc_modified_ = true;
296  }
297  Instruction* pc() { return pc_; }
298 
299  void increment_pc() {
300  if (!pc_modified_) {
301  pc_ = pc_->following();
302  }
303 
304  pc_modified_ = false;
305  }
306 
307  virtual void Decode(Instruction* instr) {
308  decoder_->Decode(instr);
309  }
310 
311  void ExecuteInstruction() {
312  DCHECK(IsAligned(reinterpret_cast<uintptr_t>(pc_), kInstructionSize));
313  CheckBreakNext();
314  Decode(pc_);
315  increment_pc();
316  CheckBreakpoints();
317  }
318 
319  // Declare all Visitor functions.
320  #define DECLARE(A) void Visit##A(Instruction* instr);
322  #undef DECLARE
323 
324  bool IsZeroRegister(unsigned code, Reg31Mode r31mode) const {
325  return ((code == 31) && (r31mode == Reg31IsZeroRegister));
326  }
327 
328  // Register accessors.
329  // Return 'size' bits of the value of an integer register, as the specified
330  // type. The value is zero-extended to fill the result.
331  //
332  template<typename T>
333  T reg(unsigned code, Reg31Mode r31mode = Reg31IsZeroRegister) const {
334  DCHECK(code < kNumberOfRegisters);
335  if (IsZeroRegister(code, r31mode)) {
336  return 0;
337  }
338  return registers_[code].Get<T>();
339  }
340 
341  // Common specialized accessors for the reg() template.
342  int32_t wreg(unsigned code, Reg31Mode r31mode = Reg31IsZeroRegister) const {
343  return reg<int32_t>(code, r31mode);
344  }
345 
346  int64_t xreg(unsigned code, Reg31Mode r31mode = Reg31IsZeroRegister) const {
347  return reg<int64_t>(code, r31mode);
348  }
349 
350  // Write 'value' into an integer register. The value is zero-extended. This
351  // behaviour matches AArch64 register writes.
352  template<typename T>
353  void set_reg(unsigned code, T value,
354  Reg31Mode r31mode = Reg31IsZeroRegister) {
355  set_reg_no_log(code, value, r31mode);
356  LogRegister(code, r31mode);
357  }
358 
359  // Common specialized accessors for the set_reg() template.
360  void set_wreg(unsigned code, int32_t value,
361  Reg31Mode r31mode = Reg31IsZeroRegister) {
362  set_reg(code, value, r31mode);
363  }
364 
365  void set_xreg(unsigned code, int64_t value,
366  Reg31Mode r31mode = Reg31IsZeroRegister) {
367  set_reg(code, value, r31mode);
368  }
369 
370  // As above, but don't automatically log the register update.
371  template <typename T>
372  void set_reg_no_log(unsigned code, T value,
373  Reg31Mode r31mode = Reg31IsZeroRegister) {
374  DCHECK(code < kNumberOfRegisters);
375  if (!IsZeroRegister(code, r31mode)) {
376  registers_[code].Set(value);
377  }
378  }
379 
380  void set_wreg_no_log(unsigned code, int32_t value,
381  Reg31Mode r31mode = Reg31IsZeroRegister) {
382  set_reg_no_log(code, value, r31mode);
383  }
384 
385  void set_xreg_no_log(unsigned code, int64_t value,
386  Reg31Mode r31mode = Reg31IsZeroRegister) {
387  set_reg_no_log(code, value, r31mode);
388  }
389 
390  // Commonly-used special cases.
391  template<typename T>
392  void set_lr(T value) {
393  DCHECK(sizeof(T) == kPointerSize);
394  set_reg(kLinkRegCode, value);
395  }
396 
397  template<typename T>
398  void set_sp(T value) {
399  DCHECK(sizeof(T) == kPointerSize);
400  set_reg(31, value, Reg31IsStackPointer);
401  }
402 
403  int64_t sp() { return xreg(31, Reg31IsStackPointer); }
404  int64_t jssp() { return xreg(kJSSPCode, Reg31IsStackPointer); }
405  int64_t fp() {
407  }
408  Instruction* lr() { return reg<Instruction*>(kLinkRegCode); }
409 
410  Address get_sp() { return reg<Address>(31, Reg31IsStackPointer); }
411 
412  template<typename T>
413  T fpreg(unsigned code) const {
414  DCHECK(code < kNumberOfRegisters);
415  return fpregisters_[code].Get<T>();
416  }
417 
418  // Common specialized accessors for the fpreg() template.
419  float sreg(unsigned code) const {
420  return fpreg<float>(code);
421  }
422 
423  uint32_t sreg_bits(unsigned code) const {
424  return fpreg<uint32_t>(code);
425  }
426 
427  double dreg(unsigned code) const {
428  return fpreg<double>(code);
429  }
430 
431  uint64_t dreg_bits(unsigned code) const {
432  return fpreg<uint64_t>(code);
433  }
434 
435  double fpreg(unsigned size, unsigned code) const {
436  switch (size) {
437  case kSRegSizeInBits: return sreg(code);
438  case kDRegSizeInBits: return dreg(code);
439  default:
440  UNREACHABLE();
441  return 0.0;
442  }
443  }
444 
445  // Write 'value' into a floating-point register. The value is zero-extended.
446  // This behaviour matches AArch64 register writes.
447  template<typename T>
448  void set_fpreg(unsigned code, T value) {
449  set_fpreg_no_log(code, value);
450 
451  if (sizeof(value) <= kSRegSize) {
452  LogFPRegister(code, kPrintSRegValue);
453  } else {
454  LogFPRegister(code, kPrintDRegValue);
455  }
456  }
457 
458  // Common specialized accessors for the set_fpreg() template.
459  void set_sreg(unsigned code, float value) {
460  set_fpreg(code, value);
461  }
462 
463  void set_sreg_bits(unsigned code, uint32_t value) {
464  set_fpreg(code, value);
465  }
466 
467  void set_dreg(unsigned code, double value) {
468  set_fpreg(code, value);
469  }
470 
471  void set_dreg_bits(unsigned code, uint64_t value) {
472  set_fpreg(code, value);
473  }
474 
475  // As above, but don't automatically log the register update.
476  template <typename T>
477  void set_fpreg_no_log(unsigned code, T value) {
478  DCHECK((sizeof(value) == kDRegSize) || (sizeof(value) == kSRegSize));
480  fpregisters_[code].Set(value);
481  }
482 
483  void set_sreg_no_log(unsigned code, float value) {
484  set_fpreg_no_log(code, value);
485  }
486 
487  void set_dreg_no_log(unsigned code, double value) {
488  set_fpreg_no_log(code, value);
489  }
490 
491  SimSystemRegister& nzcv() { return nzcv_; }
492  SimSystemRegister& fpcr() { return fpcr_; }
493 
494  // Debug helpers
495 
496  // Simulator breakpoints.
497  struct Breakpoint {
498  Instruction* location;
499  bool enabled;
500  };
501  std::vector<Breakpoint> breakpoints_;
502  void SetBreakpoint(Instruction* breakpoint);
503  void ListBreakpoints();
504  void CheckBreakpoints();
505 
506  // Helpers for the 'next' command.
507  // When this is set, the Simulator will insert a breakpoint after the next BL
508  // instruction it meets.
509  bool break_on_next_;
510  // Check if the Simulator should insert a break after the current instruction
511  // for the 'next' command.
512  void CheckBreakNext();
513 
514  // Disassemble instruction at the given address.
515  void PrintInstructionsAt(Instruction* pc, uint64_t count);
516 
517  // Print all registers of the specified types.
518  void PrintRegisters();
519  void PrintFPRegisters();
520  void PrintSystemRegisters();
521 
522  // Like Print* (above), but respect log_parameters().
523  void LogSystemRegisters() {
524  if (log_parameters() & LOG_SYS_REGS) PrintSystemRegisters();
525  }
526  void LogRegisters() {
527  if (log_parameters() & LOG_REGS) PrintRegisters();
528  }
529  void LogFPRegisters() {
530  if (log_parameters() & LOG_FP_REGS) PrintFPRegisters();
531  }
532 
533  // Specify relevant register sizes, for PrintFPRegister.
534  //
535  // These values are bit masks; they can be combined in case multiple views of
536  // a machine register are interesting.
537  enum PrintFPRegisterSizes {
538  kPrintDRegValue = 1 << kDRegSize,
539  kPrintSRegValue = 1 << kSRegSize,
540  kPrintAllFPRegValues = kPrintDRegValue | kPrintSRegValue
541  };
542 
543  // Print individual register values (after update).
544  void PrintRegister(unsigned code, Reg31Mode r31mode = Reg31IsStackPointer);
545  void PrintFPRegister(unsigned code,
546  PrintFPRegisterSizes sizes = kPrintAllFPRegValues);
547  void PrintSystemRegister(SystemRegister id);
548 
549  // Like Print* (above), but respect log_parameters().
550  void LogRegister(unsigned code, Reg31Mode r31mode = Reg31IsStackPointer) {
551  if (log_parameters() & LOG_REGS) PrintRegister(code, r31mode);
552  }
553  void LogFPRegister(unsigned code,
554  PrintFPRegisterSizes sizes = kPrintAllFPRegValues) {
555  if (log_parameters() & LOG_FP_REGS) PrintFPRegister(code, sizes);
556  }
557  void LogSystemRegister(SystemRegister id) {
558  if (log_parameters() & LOG_SYS_REGS) PrintSystemRegister(id);
559  }
560 
561  // Print memory accesses.
562  void PrintRead(uintptr_t address, size_t size, unsigned reg_code);
563  void PrintReadFP(uintptr_t address, size_t size, unsigned reg_code);
564  void PrintWrite(uintptr_t address, size_t size, unsigned reg_code);
565  void PrintWriteFP(uintptr_t address, size_t size, unsigned reg_code);
566 
567  // Like Print* (above), but respect log_parameters().
568  void LogRead(uintptr_t address, size_t size, unsigned reg_code) {
569  if (log_parameters() & LOG_REGS) PrintRead(address, size, reg_code);
570  }
571  void LogReadFP(uintptr_t address, size_t size, unsigned reg_code) {
572  if (log_parameters() & LOG_FP_REGS) PrintReadFP(address, size, reg_code);
573  }
574  void LogWrite(uintptr_t address, size_t size, unsigned reg_code) {
575  if (log_parameters() & LOG_WRITE) PrintWrite(address, size, reg_code);
576  }
577  void LogWriteFP(uintptr_t address, size_t size, unsigned reg_code) {
578  if (log_parameters() & LOG_WRITE) PrintWriteFP(address, size, reg_code);
579  }
580 
581  int log_parameters() { return log_parameters_; }
582  void set_log_parameters(int new_parameters) {
583  log_parameters_ = new_parameters;
584  if (!decoder_) {
585  if (new_parameters & LOG_DISASM) {
586  PrintF("Run --debug-sim to dynamically turn on disassembler\n");
587  }
588  return;
589  }
590  if (new_parameters & LOG_DISASM) {
591  decoder_->InsertVisitorBefore(print_disasm_, this);
592  } else {
593  decoder_->RemoveVisitor(print_disasm_);
594  }
595  }
596 
597  static inline const char* WRegNameForCode(unsigned code,
599  static inline const char* XRegNameForCode(unsigned code,
601  static inline const char* SRegNameForCode(unsigned code);
602  static inline const char* DRegNameForCode(unsigned code);
603  static inline const char* VRegNameForCode(unsigned code);
604  static inline int CodeFromName(const char* name);
605 
606  protected:
607  // Simulation helpers ------------------------------------
608  bool ConditionPassed(Condition cond) {
609  SimSystemRegister& flags = nzcv();
610  switch (cond) {
611  case eq:
612  return flags.Z();
613  case ne:
614  return !flags.Z();
615  case hs:
616  return flags.C();
617  case lo:
618  return !flags.C();
619  case mi:
620  return flags.N();
621  case pl:
622  return !flags.N();
623  case vs:
624  return flags.V();
625  case vc:
626  return !flags.V();
627  case hi:
628  return flags.C() && !flags.Z();
629  case ls:
630  return !(flags.C() && !flags.Z());
631  case ge:
632  return flags.N() == flags.V();
633  case lt:
634  return flags.N() != flags.V();
635  case gt:
636  return !flags.Z() && (flags.N() == flags.V());
637  case le:
638  return !(!flags.Z() && (flags.N() == flags.V()));
639  case nv: // Fall through.
640  case al:
641  return true;
642  default:
643  UNREACHABLE();
644  return false;
645  }
646  }
647 
648  bool ConditionFailed(Condition cond) {
649  return !ConditionPassed(cond);
650  }
651 
652  template<typename T>
653  void AddSubHelper(Instruction* instr, T op2);
654  template<typename T>
655  T AddWithCarry(bool set_flags,
656  T src1,
657  T src2,
658  T carry_in = 0);
659  template<typename T>
660  void AddSubWithCarry(Instruction* instr);
661  template<typename T>
662  void LogicalHelper(Instruction* instr, T op2);
663  template<typename T>
664  void ConditionalCompareHelper(Instruction* instr, T op2);
665  void LoadStoreHelper(Instruction* instr,
666  int64_t offset,
667  AddrMode addrmode);
668  void LoadStorePairHelper(Instruction* instr, AddrMode addrmode);
669  uintptr_t LoadStoreAddress(unsigned addr_reg, int64_t offset,
670  AddrMode addrmode);
671  void LoadStoreWriteBack(unsigned addr_reg,
672  int64_t offset,
673  AddrMode addrmode);
674  void CheckMemoryAccess(uintptr_t address, uintptr_t stack);
675 
676  // Memory read helpers.
677  template <typename T, typename A>
678  T MemoryRead(A address) {
679  T value;
680  STATIC_ASSERT((sizeof(value) == 1) || (sizeof(value) == 2) ||
681  (sizeof(value) == 4) || (sizeof(value) == 8));
682  memcpy(&value, reinterpret_cast<const void*>(address), sizeof(value));
683  return value;
684  }
685 
686  // Memory write helpers.
687  template <typename T, typename A>
688  void MemoryWrite(A address, T value) {
689  STATIC_ASSERT((sizeof(value) == 1) || (sizeof(value) == 2) ||
690  (sizeof(value) == 4) || (sizeof(value) == 8));
691  memcpy(reinterpret_cast<void*>(address), &value, sizeof(value));
692  }
693 
694  template <typename T>
695  T ShiftOperand(T value,
696  Shift shift_type,
697  unsigned amount);
698  template <typename T>
699  T ExtendValue(T value,
700  Extend extend_type,
701  unsigned left_shift = 0);
702  template <typename T>
703  void Extract(Instruction* instr);
704  template <typename T>
705  void DataProcessing2Source(Instruction* instr);
706  template <typename T>
707  void BitfieldHelper(Instruction* instr);
708 
709  uint64_t ReverseBits(uint64_t value, unsigned num_bits);
710  uint64_t ReverseBytes(uint64_t value, ReverseByteMode mode);
711 
712  template <typename T>
713  T FPDefaultNaN() const;
714 
715  void FPCompare(double val0, double val1);
716  double FPRoundInt(double value, FPRounding round_mode);
717  double FPToDouble(float value);
718  float FPToFloat(double value, FPRounding round_mode);
719  double FixedToDouble(int64_t src, int fbits, FPRounding round_mode);
720  double UFixedToDouble(uint64_t src, int fbits, FPRounding round_mode);
721  float FixedToFloat(int64_t src, int fbits, FPRounding round_mode);
722  float UFixedToFloat(uint64_t src, int fbits, FPRounding round_mode);
723  int32_t FPToInt32(double value, FPRounding rmode);
724  int64_t FPToInt64(double value, FPRounding rmode);
725  uint32_t FPToUInt32(double value, FPRounding rmode);
726  uint64_t FPToUInt64(double value, FPRounding rmode);
727 
728  template <typename T>
729  T FPAdd(T op1, T op2);
730 
731  template <typename T>
732  T FPDiv(T op1, T op2);
733 
734  template <typename T>
735  T FPMax(T a, T b);
736 
737  template <typename T>
738  T FPMaxNM(T a, T b);
739 
740  template <typename T>
741  T FPMin(T a, T b);
742 
743  template <typename T>
744  T FPMinNM(T a, T b);
745 
746  template <typename T>
747  T FPMul(T op1, T op2);
748 
749  template <typename T>
750  T FPMulAdd(T a, T op1, T op2);
751 
752  template <typename T>
753  T FPSqrt(T op);
754 
755  template <typename T>
756  T FPSub(T op1, T op2);
757 
758  // Standard NaN processing.
759  template <typename T>
760  T FPProcessNaN(T op);
761 
762  bool FPProcessNaNs(Instruction* instr);
763 
764  template <typename T>
765  T FPProcessNaNs(T op1, T op2);
766 
767  template <typename T>
768  T FPProcessNaNs3(T op1, T op2, T op3);
769 
770  void CheckStackAlignment();
771 
772  inline void CheckPCSComplianceAndRun();
773 
774 #ifdef DEBUG
775  // Corruption values should have their least significant byte cleared to
776  // allow the code of the register being corrupted to be inserted.
777  static const uint64_t kCallerSavedRegisterCorruptionValue =
778  0xca11edc0de000000UL;
779  // This value is a NaN in both 32-bit and 64-bit FP.
780  static const uint64_t kCallerSavedFPRegisterCorruptionValue =
781  0x7ff000007f801000UL;
782  // This value is a mix of 32/64-bits NaN and "verbose" immediate.
783  static const uint64_t kDefaultCPURegisterCorruptionValue =
784  0x7ffbad007f8bad00UL;
785 
786  void CorruptRegisters(CPURegList* list,
787  uint64_t value = kDefaultCPURegisterCorruptionValue);
788  void CorruptAllCallerSavedCPURegisters();
789 #endif
790 
791  // Pseudo Printf instruction
792  void DoPrintf(Instruction* instr);
793 
794  // Processor state ---------------------------------------
795 
796  // Output stream.
797  FILE* stream_;
798  PrintDisassembler* print_disasm_;
799  void PRINTF_METHOD_CHECKING TraceSim(const char* format, ...);
800 
801  // Instrumentation.
802  Instrument* instrument_;
803 
804  // General purpose registers. Register 31 is the stack pointer.
805  SimRegister registers_[kNumberOfRegisters];
806 
807  // Floating point registers
808  SimFPRegister fpregisters_[kNumberOfFPRegisters];
809 
810  // Processor state
811  // bits[31, 27]: Condition flags N, Z, C, and V.
812  // (Negative, Zero, Carry, Overflow)
813  SimSystemRegister nzcv_;
814 
815  // Floating-Point Control Register
816  SimSystemRegister fpcr_;
817 
818  // Only a subset of FPCR features are supported by the simulator. This helper
819  // checks that the FPCR settings are supported.
820  //
821  // This is checked when floating-point instructions are executed, not when
822  // FPCR is set. This allows generated code to modify FPCR for external
823  // functions, or to save and restore it when entering and leaving generated
824  // code.
825  void AssertSupportedFPCR() {
826  DCHECK(fpcr().FZ() == 0); // No flush-to-zero support.
827  DCHECK(fpcr().RMode() == FPTieEven); // Ties-to-even rounding only.
828 
829  // The simulator does not support half-precision operations so fpcr().AHP()
830  // is irrelevant, and is not checked here.
831  }
832 
833  template <typename T>
834  static int CalcNFlag(T result) {
835  return (result >> (sizeof(T) * 8 - 1)) & 1;
836  }
837 
838  static int CalcZFlag(uint64_t result) {
839  return result == 0;
840  }
841 
842  static const uint32_t kConditionFlagsMask = 0xf0000000;
843 
844  // Stack
845  uintptr_t stack_;
846  static const size_t stack_protection_size_ = KB;
847  size_t stack_size_;
848  uintptr_t stack_limit_;
849 
850  Decoder<DispatchingDecoderVisitor>* decoder_;
851  Decoder<DispatchingDecoderVisitor>* disassembler_decoder_;
852 
853  // Indicates if the pc has been modified by the instruction and should not be
854  // automatically incremented.
855  bool pc_modified_;
856  Instruction* pc_;
857 
858  static const char* xreg_names[];
859  static const char* wreg_names[];
860  static const char* sreg_names[];
861  static const char* dreg_names[];
862  static const char* vreg_names[];
863 
864  // Debugger input.
865  void set_last_debugger_input(char* input) {
866  DeleteArray(last_debugger_input_);
867  last_debugger_input_ = input;
868  }
869  char* last_debugger_input() { return last_debugger_input_; }
870  char* last_debugger_input_;
871 
872  private:
873  void Init(FILE* stream);
874 
875  int log_parameters_;
876  Isolate* isolate_;
877 };
878 
879 
880 // When running with the simulator transition into simulated execution at this
881 // point.
882 #define CALL_GENERATED_CODE(entry, p0, p1, p2, p3, p4) \
883  reinterpret_cast<Object*>(Simulator::current(Isolate::Current())->CallJS( \
884  FUNCTION_ADDR(entry), \
885  p0, p1, p2, p3, p4))
886 
887 #define CALL_GENERATED_REGEXP_CODE(entry, p0, p1, p2, p3, p4, p5, p6, p7, p8) \
888  Simulator::current(Isolate::Current())->CallRegExp( \
889  entry, \
890  p0, p1, p2, p3, p4, p5, p6, p7, NULL, p8)
891 
892 
893 // The simulator has its own stack. Thus it has a different stack limit from
894 // the C-based native code.
895 // See also 'class SimulatorStack' in arm/simulator-arm.h.
896 class SimulatorStack : public v8::internal::AllStatic {
897  public:
899  uintptr_t c_limit) {
900  return Simulator::current(isolate)->StackLimit();
901  }
902 
903  static uintptr_t RegisterCTryCatch(uintptr_t try_catch_address) {
904  Simulator* sim = Simulator::current(Isolate::Current());
905  return sim->PushAddress(try_catch_address);
906  }
907 
908  static void UnregisterCTryCatch() {
909  Simulator::current(Isolate::Current())->PopAddress();
910  }
911 };
912 
913 #endif // !defined(USE_SIMULATOR)
914 
915 } } // namespace v8::internal
916 
917 #endif // V8_ARM64_SIMULATOR_ARM64_H_
static uintptr_t RegisterCTryCatch(uintptr_t try_catch_address)
static uintptr_t JsLimitFromCLimit(v8::internal::Isolate *isolate, uintptr_t c_limit)
#define SYSTEM_REGISTER_FIELDS_LIST(V_, M_)
#define VISITOR_LIST(V)
Definition: decoder-arm64.h:19
#define DECLARE(A)
enable harmony numeric enable harmony object literal extensions Optimize object size
enable harmony numeric enable harmony object literal extensions Optimize object Array DOM strings and string trace pretenuring decisions of HAllocate instructions Enables optimizations which favor memory size over execution speed maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining trace the tracking of allocation sites deoptimize every n garbage collections perform array bounds checks elimination analyze liveness of environment slots and zap dead values flushes the cache of optimized code for closures on every GC allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes enable context specialization in TurboFan execution budget before interrupt is triggered max percentage of megamorphic generic ICs to allow optimization enable use of SAHF instruction if enable use of VFP3 instructions if available enable use of NEON instructions if enable use of SDIV and UDIV instructions if enable use of MLS instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of d16 d31 registers on ARM this requires VFP3 force all emitted branches to be in long enable alignment of csp to bytes on platforms which prefer the register to always be expose gc extension under the specified name show built in functions in stack traces use random jit cookie to mask large constants minimum length for automatic enable preparsing CPU profiler sampling interval in microseconds trace out of bounds accesses to external arrays default size of stack region v8 is allowed to maximum length of function source code printed in a stack trace min size of a semi the new space consists of two semi spaces print one trace line following each garbage collection do not print trace line after scavenger collection print cumulative GC statistics in name
enable harmony numeric enable harmony object literal extensions Optimize object Array DOM strings and string trace pretenuring decisions of HAllocate instructions Enables optimizations which favor memory size over execution speed maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining trace the tracking of allocation sites deoptimize every n garbage collections perform array bounds checks elimination analyze liveness of environment slots and zap dead values flushes the cache of optimized code for closures on every GC allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes enable context specialization in TurboFan execution budget before interrupt is triggered max percentage of megamorphic generic ICs to allow optimization enable use of SAHF instruction if enable use of VFP3 instructions if available enable use of NEON instructions if enable use of SDIV and UDIV instructions if enable use of MLS instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of d16 d31 registers on ARM this requires VFP3 force all emitted branches to be in long mode(MIPS only)") DEFINE_BOOL(enable_always_align_csp
enable harmony numeric enable harmony object literal extensions Optimize object Array DOM strings and string trace pretenuring decisions of HAllocate instructions Enables optimizations which favor memory size over execution speed maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining trace the tracking of allocation sites deoptimize every n garbage collections perform array bounds checks elimination analyze liveness of environment slots and zap dead values flushes the cache of optimized code for closures on every GC allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes enable context specialization in TurboFan execution budget before interrupt is triggered max percentage of megamorphic generic ICs to allow optimization enable use of SAHF instruction if enable use of VFP3 instructions if available enable use of NEON instructions if enable use of SDIV and UDIV instructions if enable use of MLS instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of d16 d31 registers on ARM this requires VFP3 force all emitted branches to be in long enable alignment of csp to bytes on platforms which prefer the register to always be NULL
#define DEFINE_GETTER(Name, HighBit, LowBit, Func)
#define UNREACHABLE()
Definition: logging.h:30
#define UNIMPLEMENTED()
Definition: logging.h:28
#define DCHECK(condition)
Definition: logging.h:205
void USE(T)
Definition: macros.h:322
int int32_t
Definition: unicode.cc:24
void DeleteArray(T *array)
Definition: allocation.h:68
const unsigned kJSSPCode
const int kPointerSize
Definition: globals.h:129
const unsigned kSRegSize
const int KB
Definition: globals.h:106
const unsigned kDRegSizeInBits
TypeImpl< ZoneTypeConfig > Type
const Register fp
kSerializedDataOffset Object
Definition: objects-inl.h:5322
const Register sp
const unsigned kSRegSizeInBits
const unsigned kNumberOfFPRegisters
const Register pc
const Register lr
byte * Address
Definition: globals.h:101
const unsigned kFramePointerRegCode
void PrintF(const char *format,...)
Definition: utils.cc:80
int(* arm64_regexp_matcher)(String *input, int64_t start_offset, const byte *input_start, const byte *input_end, int *output, int64_t output_size, Address stack_base, int64_t direct_call, void *return_address, Isolate *isolate)
const unsigned kDRegSize
int32_t signed_bitextract_32(int msb, int lsb, int32_t x)
Definition: utils.h:888
STATIC_ASSERT(sizeof(CPURegister)==sizeof(Register))
const unsigned kNumberOfRegisters
bool IsAligned(T value, U alignment)
Definition: utils.h:123
const unsigned kInstructionSize
const unsigned kLinkRegCode
uint32_t unsigned_bitextract_32(int msb, int lsb, uint32_t x)
Definition: utils.h:880
Debugger support for the V8 JavaScript engine.
Definition: accessors.cc:20
#define T(name, string, precedence)
Definition: token.cc:25
#define PRINTF_METHOD_CHECKING
Definition: utils.h:1027