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/globals.h"
14#include "src/utils.h"
15#include "src/allocation.h"
16#include "src/assembler.h"
17#include "src/arm64/assembler-arm64.h"
18#include "src/arm64/decoder-arm64.h"
19#include "src/arm64/disasm-arm64.h"
20#include "src/arm64/instrument-arm64.h"
21
22#define REGISTER_CODE_LIST(R)                                                  \
23R(0)  R(1)  R(2)  R(3)  R(4)  R(5)  R(6)  R(7)                                 \
24R(8)  R(9)  R(10) R(11) R(12) R(13) R(14) R(15)                                \
25R(16) R(17) R(18) R(19) R(20) R(21) R(22) R(23)                                \
26R(24) R(25) R(26) R(27) R(28) R(29) R(30) R(31)
27
28namespace v8 {
29namespace 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
38typedef 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.
58class SimulatorStack : public v8::internal::AllStatic {
59 public:
60  static uintptr_t JsLimitFromCLimit(v8::internal::Isolate* isolate,
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
75enum 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);
85class 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).
136class 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
156typedef SimRegisterBase SimRegister;      // r0-r31
157typedef SimRegisterBase SimFPRegister;    // v0-v31
158
159
160class 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      ASSERT(sizeof(argument) <= sizeof(bits_));
215      memcpy(&bits_, &argument, sizeof(argument));
216      type_ = X_ARG;
217    }
218
219    explicit CallArgument(double argument) {
220      ASSERT(sizeof(argument) == sizeof(bits_));
221      memcpy(&bits_, &argument, sizeof(argument));
222      type_ = D_ARG;
223    }
224
225    explicit CallArgument(float argument) {
226      // TODO(all): CallArgument(float) is untested, remove this check once
227      //            tested.
228      UNIMPLEMENTED();
229      // Make the D register a NaN to try to trap errors if the callee expects a
230      // double. If it expects a float, the callee should ignore the top word.
231      ASSERT(sizeof(kFP64SignallingNaN) == sizeof(bits_));
232      memcpy(&bits_, &kFP64SignallingNaN, sizeof(kFP64SignallingNaN));
233      // Write the float payload to the S register.
234      ASSERT(sizeof(argument) <= sizeof(bits_));
235      memcpy(&bits_, &argument, sizeof(argument));
236      type_ = D_ARG;
237    }
238
239    // This indicates the end of the arguments list, so that CallArgument
240    // objects can be passed into varargs functions.
241    static CallArgument End() { return CallArgument(); }
242
243    int64_t bits() const { return bits_; }
244    bool IsEnd() const { return type_ == NO_ARG; }
245    bool IsX() const { return type_ == X_ARG; }
246    bool IsD() const { return type_ == D_ARG; }
247
248   private:
249    enum CallArgumentType { X_ARG, D_ARG, NO_ARG };
250
251    // All arguments are aligned to at least 64 bits and we don't support
252    // passing bigger arguments, so the payload size can be fixed at 64 bits.
253    int64_t bits_;
254    CallArgumentType type_;
255
256    CallArgument() { type_ = NO_ARG; }
257  };
258
259
260  // Start the debugging command line.
261  void Debug();
262
263  bool GetValue(const char* desc, int64_t* value);
264
265  bool PrintValue(const char* desc);
266
267  // Push an address onto the JS stack.
268  uintptr_t PushAddress(uintptr_t address);
269
270  // Pop an address from the JS stack.
271  uintptr_t PopAddress();
272
273  // Accessor to the internal simulator stack area.
274  uintptr_t StackLimit() const;
275
276  void ResetState();
277
278  // Runtime call support.
279  static void* RedirectExternalReference(void* external_function,
280                                         ExternalReference::Type type);
281  void DoRuntimeCall(Instruction* instr);
282
283  // Run the simulator.
284  static const Instruction* kEndOfSimAddress;
285  void DecodeInstruction();
286  void Run();
287  void RunFrom(Instruction* start);
288
289  // Simulation helpers.
290  template <typename T>
291  void set_pc(T new_pc) {
292    ASSERT(sizeof(T) == sizeof(pc_));
293    memcpy(&pc_, &new_pc, sizeof(T));
294    pc_modified_ = true;
295  }
296  Instruction* pc() { return pc_; }
297
298  void increment_pc() {
299    if (!pc_modified_) {
300      pc_ = pc_->following();
301    }
302
303    pc_modified_ = false;
304  }
305
306  virtual void Decode(Instruction* instr) {
307    decoder_->Decode(instr);
308  }
309
310  void ExecuteInstruction() {
311    ASSERT(IsAligned(reinterpret_cast<uintptr_t>(pc_), kInstructionSize));
312    CheckBreakNext();
313    Decode(pc_);
314    LogProcessorState();
315    increment_pc();
316    CheckBreakpoints();
317  }
318
319  // Declare all Visitor functions.
320  #define DECLARE(A)  void Visit##A(Instruction* instr);
321  VISITOR_LIST(DECLARE)
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    ASSERT(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 'size' bits of 'value' into an integer register. The value is
351  // zero-extended. This behaviour matches AArch64 register writes.
352
353  // Like set_reg(), but infer the access size from the template type.
354  template<typename T>
355  void set_reg(unsigned code, T value,
356               Reg31Mode r31mode = Reg31IsZeroRegister) {
357    ASSERT(code < kNumberOfRegisters);
358    if (!IsZeroRegister(code, r31mode))
359      registers_[code].Set(value);
360  }
361
362  // Common specialized accessors for the set_reg() template.
363  void set_wreg(unsigned code, int32_t value,
364                Reg31Mode r31mode = Reg31IsZeroRegister) {
365    set_reg(code, value, r31mode);
366  }
367
368  void set_xreg(unsigned code, int64_t value,
369                Reg31Mode r31mode = Reg31IsZeroRegister) {
370    set_reg(code, value, r31mode);
371  }
372
373  // Commonly-used special cases.
374  template<typename T>
375  void set_lr(T value) {
376    ASSERT(sizeof(T) == kPointerSize);
377    set_reg(kLinkRegCode, value);
378  }
379
380  template<typename T>
381  void set_sp(T value) {
382    ASSERT(sizeof(T) == kPointerSize);
383    set_reg(31, value, Reg31IsStackPointer);
384  }
385
386  int64_t sp() { return xreg(31, Reg31IsStackPointer); }
387  int64_t jssp() { return xreg(kJSSPCode, Reg31IsStackPointer); }
388  int64_t fp() {
389      return xreg(kFramePointerRegCode, Reg31IsStackPointer);
390  }
391  Instruction* lr() { return reg<Instruction*>(kLinkRegCode); }
392
393  Address get_sp() { return reg<Address>(31, Reg31IsStackPointer); }
394
395  template<typename T>
396  T fpreg(unsigned code) const {
397    ASSERT(code < kNumberOfRegisters);
398    return fpregisters_[code].Get<T>();
399  }
400
401  // Common specialized accessors for the fpreg() template.
402  float sreg(unsigned code) const {
403    return fpreg<float>(code);
404  }
405
406  uint32_t sreg_bits(unsigned code) const {
407    return fpreg<uint32_t>(code);
408  }
409
410  double dreg(unsigned code) const {
411    return fpreg<double>(code);
412  }
413
414  uint64_t dreg_bits(unsigned code) const {
415    return fpreg<uint64_t>(code);
416  }
417
418  double fpreg(unsigned size, unsigned code) const {
419    switch (size) {
420      case kSRegSizeInBits: return sreg(code);
421      case kDRegSizeInBits: return dreg(code);
422      default:
423        UNREACHABLE();
424        return 0.0;
425    }
426  }
427
428  // Write 'value' into a floating-point register. The value is zero-extended.
429  // This behaviour matches AArch64 register writes.
430  template<typename T>
431  void set_fpreg(unsigned code, T value) {
432    ASSERT((sizeof(value) == kDRegSize) || (sizeof(value) == kSRegSize));
433    ASSERT(code < kNumberOfFPRegisters);
434    fpregisters_[code].Set(value);
435  }
436
437  // Common specialized accessors for the set_fpreg() template.
438  void set_sreg(unsigned code, float value) {
439    set_fpreg(code, value);
440  }
441
442  void set_sreg_bits(unsigned code, uint32_t value) {
443    set_fpreg(code, value);
444  }
445
446  void set_dreg(unsigned code, double value) {
447    set_fpreg(code, value);
448  }
449
450  void set_dreg_bits(unsigned code, uint64_t value) {
451    set_fpreg(code, value);
452  }
453
454  SimSystemRegister& nzcv() { return nzcv_; }
455  SimSystemRegister& fpcr() { return fpcr_; }
456
457  // Debug helpers
458
459  // Simulator breakpoints.
460  struct Breakpoint {
461    Instruction* location;
462    bool enabled;
463  };
464  std::vector<Breakpoint> breakpoints_;
465  void SetBreakpoint(Instruction* breakpoint);
466  void ListBreakpoints();
467  void CheckBreakpoints();
468
469  // Helpers for the 'next' command.
470  // When this is set, the Simulator will insert a breakpoint after the next BL
471  // instruction it meets.
472  bool break_on_next_;
473  // Check if the Simulator should insert a break after the current instruction
474  // for the 'next' command.
475  void CheckBreakNext();
476
477  // Disassemble instruction at the given address.
478  void PrintInstructionsAt(Instruction* pc, uint64_t count);
479
480  void PrintSystemRegisters(bool print_all = false);
481  void PrintRegisters(bool print_all_regs = false);
482  void PrintFPRegisters(bool print_all_regs = false);
483  void PrintProcessorState();
484  void PrintWrite(uint8_t* address, uint64_t value, unsigned num_bytes);
485  void LogSystemRegisters() {
486    if (log_parameters_ & LOG_SYS_REGS) PrintSystemRegisters();
487  }
488  void LogRegisters() {
489    if (log_parameters_ & LOG_REGS) PrintRegisters();
490  }
491  void LogFPRegisters() {
492    if (log_parameters_ & LOG_FP_REGS) PrintFPRegisters();
493  }
494  void LogProcessorState() {
495    LogSystemRegisters();
496    LogRegisters();
497    LogFPRegisters();
498  }
499  void LogWrite(uint8_t* address, uint64_t value, unsigned num_bytes) {
500    if (log_parameters_ & LOG_WRITE) PrintWrite(address, value, num_bytes);
501  }
502
503  int log_parameters() { return log_parameters_; }
504  void set_log_parameters(int new_parameters) {
505    log_parameters_ = new_parameters;
506    if (!decoder_) {
507      if (new_parameters & LOG_DISASM) {
508        PrintF("Run --debug-sim to dynamically turn on disassembler\n");
509      }
510      return;
511    }
512    if (new_parameters & LOG_DISASM) {
513      decoder_->InsertVisitorBefore(print_disasm_, this);
514    } else {
515      decoder_->RemoveVisitor(print_disasm_);
516    }
517  }
518
519  static inline const char* WRegNameForCode(unsigned code,
520      Reg31Mode mode = Reg31IsZeroRegister);
521  static inline const char* XRegNameForCode(unsigned code,
522      Reg31Mode mode = Reg31IsZeroRegister);
523  static inline const char* SRegNameForCode(unsigned code);
524  static inline const char* DRegNameForCode(unsigned code);
525  static inline const char* VRegNameForCode(unsigned code);
526  static inline int CodeFromName(const char* name);
527
528 protected:
529  // Simulation helpers ------------------------------------
530  bool ConditionPassed(Condition cond) {
531    SimSystemRegister& flags = nzcv();
532    switch (cond) {
533      case eq:
534        return flags.Z();
535      case ne:
536        return !flags.Z();
537      case hs:
538        return flags.C();
539      case lo:
540        return !flags.C();
541      case mi:
542        return flags.N();
543      case pl:
544        return !flags.N();
545      case vs:
546        return flags.V();
547      case vc:
548        return !flags.V();
549      case hi:
550        return flags.C() && !flags.Z();
551      case ls:
552        return !(flags.C() && !flags.Z());
553      case ge:
554        return flags.N() == flags.V();
555      case lt:
556        return flags.N() != flags.V();
557      case gt:
558        return !flags.Z() && (flags.N() == flags.V());
559      case le:
560        return !(!flags.Z() && (flags.N() == flags.V()));
561      case nv:  // Fall through.
562      case al:
563        return true;
564      default:
565        UNREACHABLE();
566        return false;
567    }
568  }
569
570  bool ConditionFailed(Condition cond) {
571    return !ConditionPassed(cond);
572  }
573
574  template<typename T>
575  void AddSubHelper(Instruction* instr, T op2);
576  template<typename T>
577  T AddWithCarry(bool set_flags,
578                 T src1,
579                 T src2,
580                 T carry_in = 0);
581  template<typename T>
582  void AddSubWithCarry(Instruction* instr);
583  template<typename T>
584  void LogicalHelper(Instruction* instr, T op2);
585  template<typename T>
586  void ConditionalCompareHelper(Instruction* instr, T op2);
587  void LoadStoreHelper(Instruction* instr,
588                       int64_t offset,
589                       AddrMode addrmode);
590  void LoadStorePairHelper(Instruction* instr, AddrMode addrmode);
591  uint8_t* LoadStoreAddress(unsigned addr_reg,
592                            int64_t offset,
593                            AddrMode addrmode);
594  void LoadStoreWriteBack(unsigned addr_reg,
595                          int64_t offset,
596                          AddrMode addrmode);
597  void CheckMemoryAccess(uint8_t* address, uint8_t* stack);
598
599  uint64_t MemoryRead(uint8_t* address, unsigned num_bytes);
600  uint8_t MemoryRead8(uint8_t* address);
601  uint16_t MemoryRead16(uint8_t* address);
602  uint32_t MemoryRead32(uint8_t* address);
603  float MemoryReadFP32(uint8_t* address);
604  uint64_t MemoryRead64(uint8_t* address);
605  double MemoryReadFP64(uint8_t* address);
606
607  void MemoryWrite(uint8_t* address, uint64_t value, unsigned num_bytes);
608  void MemoryWrite32(uint8_t* address, uint32_t value);
609  void MemoryWriteFP32(uint8_t* address, float value);
610  void MemoryWrite64(uint8_t* address, uint64_t value);
611  void MemoryWriteFP64(uint8_t* address, double value);
612
613
614  template <typename T>
615  T ShiftOperand(T value,
616                 Shift shift_type,
617                 unsigned amount);
618  template <typename T>
619  T ExtendValue(T value,
620                Extend extend_type,
621                unsigned left_shift = 0);
622  template <typename T>
623  void Extract(Instruction* instr);
624  template <typename T>
625  void DataProcessing2Source(Instruction* instr);
626  template <typename T>
627  void BitfieldHelper(Instruction* instr);
628
629  uint64_t ReverseBits(uint64_t value, unsigned num_bits);
630  uint64_t ReverseBytes(uint64_t value, ReverseByteMode mode);
631
632  template <typename T>
633  T FPDefaultNaN() const;
634
635  void FPCompare(double val0, double val1);
636  double FPRoundInt(double value, FPRounding round_mode);
637  double FPToDouble(float value);
638  float FPToFloat(double value, FPRounding round_mode);
639  double FixedToDouble(int64_t src, int fbits, FPRounding round_mode);
640  double UFixedToDouble(uint64_t src, int fbits, FPRounding round_mode);
641  float FixedToFloat(int64_t src, int fbits, FPRounding round_mode);
642  float UFixedToFloat(uint64_t src, int fbits, FPRounding round_mode);
643  int32_t FPToInt32(double value, FPRounding rmode);
644  int64_t FPToInt64(double value, FPRounding rmode);
645  uint32_t FPToUInt32(double value, FPRounding rmode);
646  uint64_t FPToUInt64(double value, FPRounding rmode);
647
648  template <typename T>
649  T FPAdd(T op1, T op2);
650
651  template <typename T>
652  T FPDiv(T op1, T op2);
653
654  template <typename T>
655  T FPMax(T a, T b);
656
657  template <typename T>
658  T FPMaxNM(T a, T b);
659
660  template <typename T>
661  T FPMin(T a, T b);
662
663  template <typename T>
664  T FPMinNM(T a, T b);
665
666  template <typename T>
667  T FPMul(T op1, T op2);
668
669  template <typename T>
670  T FPMulAdd(T a, T op1, T op2);
671
672  template <typename T>
673  T FPSqrt(T op);
674
675  template <typename T>
676  T FPSub(T op1, T op2);
677
678  // Standard NaN processing.
679  template <typename T>
680  T FPProcessNaN(T op);
681
682  bool FPProcessNaNs(Instruction* instr);
683
684  template <typename T>
685  T FPProcessNaNs(T op1, T op2);
686
687  template <typename T>
688  T FPProcessNaNs3(T op1, T op2, T op3);
689
690  void CheckStackAlignment();
691
692  inline void CheckPCSComplianceAndRun();
693
694#ifdef DEBUG
695  // Corruption values should have their least significant byte cleared to
696  // allow the code of the register being corrupted to be inserted.
697  static const uint64_t kCallerSavedRegisterCorruptionValue =
698      0xca11edc0de000000UL;
699  // This value is a NaN in both 32-bit and 64-bit FP.
700  static const uint64_t kCallerSavedFPRegisterCorruptionValue =
701      0x7ff000007f801000UL;
702  // This value is a mix of 32/64-bits NaN and "verbose" immediate.
703  static const uint64_t kDefaultCPURegisterCorruptionValue =
704      0x7ffbad007f8bad00UL;
705
706  void CorruptRegisters(CPURegList* list,
707                        uint64_t value = kDefaultCPURegisterCorruptionValue);
708  void CorruptAllCallerSavedCPURegisters();
709#endif
710
711  // Pseudo Printf instruction
712  void DoPrintf(Instruction* instr);
713
714  // Processor state ---------------------------------------
715
716  // Output stream.
717  FILE* stream_;
718  PrintDisassembler* print_disasm_;
719  void PRINTF_METHOD_CHECKING TraceSim(const char* format, ...);
720
721  // Instrumentation.
722  Instrument* instrument_;
723
724  // General purpose registers. Register 31 is the stack pointer.
725  SimRegister registers_[kNumberOfRegisters];
726
727  // Floating point registers
728  SimFPRegister fpregisters_[kNumberOfFPRegisters];
729
730  // Processor state
731  // bits[31, 27]: Condition flags N, Z, C, and V.
732  //               (Negative, Zero, Carry, Overflow)
733  SimSystemRegister nzcv_;
734
735  // Floating-Point Control Register
736  SimSystemRegister fpcr_;
737
738  // Only a subset of FPCR features are supported by the simulator. This helper
739  // checks that the FPCR settings are supported.
740  //
741  // This is checked when floating-point instructions are executed, not when
742  // FPCR is set. This allows generated code to modify FPCR for external
743  // functions, or to save and restore it when entering and leaving generated
744  // code.
745  void AssertSupportedFPCR() {
746    ASSERT(fpcr().FZ() == 0);             // No flush-to-zero support.
747    ASSERT(fpcr().RMode() == FPTieEven);  // Ties-to-even rounding only.
748
749    // The simulator does not support half-precision operations so fpcr().AHP()
750    // is irrelevant, and is not checked here.
751  }
752
753  template <typename T>
754  static int CalcNFlag(T result) {
755    return (result >> (sizeof(T) * 8 - 1)) & 1;
756  }
757
758  static int CalcZFlag(uint64_t result) {
759    return result == 0;
760  }
761
762  static const uint32_t kConditionFlagsMask = 0xf0000000;
763
764  // Stack
765  byte* stack_;
766  static const intptr_t stack_protection_size_ = KB;
767  intptr_t stack_size_;
768  byte* stack_limit_;
769
770  Decoder<DispatchingDecoderVisitor>* decoder_;
771  Decoder<DispatchingDecoderVisitor>* disassembler_decoder_;
772
773  // Indicates if the pc has been modified by the instruction and should not be
774  // automatically incremented.
775  bool pc_modified_;
776  Instruction* pc_;
777
778  static const char* xreg_names[];
779  static const char* wreg_names[];
780  static const char* sreg_names[];
781  static const char* dreg_names[];
782  static const char* vreg_names[];
783
784  // Debugger input.
785  void set_last_debugger_input(char* input) {
786    DeleteArray(last_debugger_input_);
787    last_debugger_input_ = input;
788  }
789  char* last_debugger_input() { return last_debugger_input_; }
790  char* last_debugger_input_;
791
792 private:
793  void Init(FILE* stream);
794
795  int  log_parameters_;
796  Isolate* isolate_;
797};
798
799
800// When running with the simulator transition into simulated execution at this
801// point.
802#define CALL_GENERATED_CODE(entry, p0, p1, p2, p3, p4) \
803  reinterpret_cast<Object*>(Simulator::current(Isolate::Current())->CallJS(    \
804      FUNCTION_ADDR(entry),                                                    \
805      p0, p1, p2, p3, p4))
806
807#define CALL_GENERATED_REGEXP_CODE(entry, p0, p1, p2, p3, p4, p5, p6, p7, p8)  \
808  Simulator::current(Isolate::Current())->CallRegExp(                          \
809      entry,                                                                   \
810      p0, p1, p2, p3, p4, p5, p6, p7, NULL, p8)
811
812
813// The simulator has its own stack. Thus it has a different stack limit from
814// the C-based native code.
815// See also 'class SimulatorStack' in arm/simulator-arm.h.
816class SimulatorStack : public v8::internal::AllStatic {
817 public:
818  static uintptr_t JsLimitFromCLimit(v8::internal::Isolate* isolate,
819                                            uintptr_t c_limit) {
820    return Simulator::current(isolate)->StackLimit();
821  }
822
823  static uintptr_t RegisterCTryCatch(uintptr_t try_catch_address) {
824    Simulator* sim = Simulator::current(Isolate::Current());
825    return sim->PushAddress(try_catch_address);
826  }
827
828  static void UnregisterCTryCatch() {
829    Simulator::current(Isolate::Current())->PopAddress();
830  }
831};
832
833#endif  // !defined(USE_SIMULATOR)
834
835} }  // namespace v8::internal
836
837#endif  // V8_ARM64_SIMULATOR_ARM64_H_
838