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