• 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::HashMap* i_cache, void* start, size_t size) {
155     USE(i_cache);
156     USE(start);
157     USE(size);
158   }
159 
160   explicit Simulator(Decoder<DispatchingDecoderVisitor>* decoder,
161                      Isolate* isolate = NULL,
162                      FILE* stream = stderr);
163   Simulator();
164   ~Simulator();
165 
166   // System functions.
167 
168   static void Initialize(Isolate* isolate);
169 
170   static void TearDown(base::HashMap* i_cache, Redirection* first);
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                  Object* new_target,
190                  Object* target,
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(uintptr_t c_limit) const;
276 
277   void ResetState();
278 
279   // Runtime call support.
280   static void* RedirectExternalReference(Isolate* isolate,
281                                          void* external_function,
282                                          ExternalReference::Type type);
283   void DoRuntimeCall(Instruction* instr);
284 
285   // Run the simulator.
286   static const Instruction* kEndOfSimAddress;
287   void DecodeInstruction();
288   void Run();
289   void RunFrom(Instruction* start);
290 
291   // Simulation helpers.
292   template <typename T>
293   void set_pc(T new_pc) {
294     DCHECK(sizeof(T) == sizeof(pc_));
295     memcpy(&pc_, &new_pc, sizeof(T));
296     pc_modified_ = true;
297   }
298   Instruction* pc() { return pc_; }
299 
300   void increment_pc() {
301     if (!pc_modified_) {
302       pc_ = pc_->following();
303     }
304 
305     pc_modified_ = false;
306   }
307 
308   virtual void Decode(Instruction* instr) {
309     decoder_->Decode(instr);
310   }
311 
312   void ExecuteInstruction() {
313     DCHECK(IsAligned(reinterpret_cast<uintptr_t>(pc_), kInstructionSize));
314     CheckBreakNext();
315     Decode(pc_);
316     increment_pc();
317     CheckBreakpoints();
318   }
319 
320   // Declare all Visitor functions.
321   #define DECLARE(A)  void Visit##A(Instruction* instr);
322   VISITOR_LIST(DECLARE)
323   #undef DECLARE
324 
325   bool IsZeroRegister(unsigned code, Reg31Mode r31mode) const {
326     return ((code == 31) && (r31mode == Reg31IsZeroRegister));
327   }
328 
329   // Register accessors.
330   // Return 'size' bits of the value of an integer register, as the specified
331   // type. The value is zero-extended to fill the result.
332   //
333   template<typename T>
334   T reg(unsigned code, Reg31Mode r31mode = Reg31IsZeroRegister) const {
335     DCHECK(code < kNumberOfRegisters);
336     if (IsZeroRegister(code, r31mode)) {
337       return 0;
338     }
339     return registers_[code].Get<T>();
340   }
341 
342   // Common specialized accessors for the reg() template.
343   int32_t wreg(unsigned code, Reg31Mode r31mode = Reg31IsZeroRegister) const {
344     return reg<int32_t>(code, r31mode);
345   }
346 
347   int64_t xreg(unsigned code, Reg31Mode r31mode = Reg31IsZeroRegister) const {
348     return reg<int64_t>(code, r31mode);
349   }
350 
351   // Write 'value' into an integer register. The value is zero-extended. This
352   // behaviour matches AArch64 register writes.
353   template<typename T>
354   void set_reg(unsigned code, T value,
355                Reg31Mode r31mode = Reg31IsZeroRegister) {
356     set_reg_no_log(code, value, r31mode);
357     LogRegister(code, r31mode);
358   }
359 
360   // Common specialized accessors for the set_reg() template.
361   void set_wreg(unsigned code, int32_t value,
362                 Reg31Mode r31mode = Reg31IsZeroRegister) {
363     set_reg(code, value, r31mode);
364   }
365 
366   void set_xreg(unsigned code, int64_t value,
367                 Reg31Mode r31mode = Reg31IsZeroRegister) {
368     set_reg(code, value, r31mode);
369   }
370 
371   // As above, but don't automatically log the register update.
372   template <typename T>
373   void set_reg_no_log(unsigned code, T value,
374                       Reg31Mode r31mode = Reg31IsZeroRegister) {
375     DCHECK(code < kNumberOfRegisters);
376     if (!IsZeroRegister(code, r31mode)) {
377       registers_[code].Set(value);
378     }
379   }
380 
381   void set_wreg_no_log(unsigned code, int32_t value,
382                        Reg31Mode r31mode = Reg31IsZeroRegister) {
383     set_reg_no_log(code, value, r31mode);
384   }
385 
386   void set_xreg_no_log(unsigned code, int64_t value,
387                        Reg31Mode r31mode = Reg31IsZeroRegister) {
388     set_reg_no_log(code, value, r31mode);
389   }
390 
391   // Commonly-used special cases.
392   template<typename T>
393   void set_lr(T value) {
394     DCHECK(sizeof(T) == kPointerSize);
395     set_reg(kLinkRegCode, value);
396   }
397 
398   template<typename T>
399   void set_sp(T value) {
400     DCHECK(sizeof(T) == kPointerSize);
401     set_reg(31, value, Reg31IsStackPointer);
402   }
403 
404   int64_t sp() { return xreg(31, Reg31IsStackPointer); }
405   int64_t jssp() { return xreg(kJSSPCode, Reg31IsStackPointer); }
406   int64_t fp() {
407       return xreg(kFramePointerRegCode, Reg31IsStackPointer);
408   }
409   Instruction* lr() { return reg<Instruction*>(kLinkRegCode); }
410 
411   Address get_sp() const { return reg<Address>(31, Reg31IsStackPointer); }
412 
413   template<typename T>
414   T fpreg(unsigned code) const {
415     DCHECK(code < kNumberOfRegisters);
416     return fpregisters_[code].Get<T>();
417   }
418 
419   // Common specialized accessors for the fpreg() template.
420   float sreg(unsigned code) const {
421     return fpreg<float>(code);
422   }
423 
424   uint32_t sreg_bits(unsigned code) const {
425     return fpreg<uint32_t>(code);
426   }
427 
428   double dreg(unsigned code) const {
429     return fpreg<double>(code);
430   }
431 
432   uint64_t dreg_bits(unsigned code) const {
433     return fpreg<uint64_t>(code);
434   }
435 
436   double fpreg(unsigned size, unsigned code) const {
437     switch (size) {
438       case kSRegSizeInBits: return sreg(code);
439       case kDRegSizeInBits: return dreg(code);
440       default:
441         UNREACHABLE();
442         return 0.0;
443     }
444   }
445 
446   // Write 'value' into a floating-point register. The value is zero-extended.
447   // This behaviour matches AArch64 register writes.
448   template<typename T>
449   void set_fpreg(unsigned code, T value) {
450     set_fpreg_no_log(code, value);
451 
452     if (sizeof(value) <= kSRegSize) {
453       LogFPRegister(code, kPrintSRegValue);
454     } else {
455       LogFPRegister(code, kPrintDRegValue);
456     }
457   }
458 
459   // Common specialized accessors for the set_fpreg() template.
460   void set_sreg(unsigned code, float value) {
461     set_fpreg(code, value);
462   }
463 
464   void set_sreg_bits(unsigned code, uint32_t value) {
465     set_fpreg(code, value);
466   }
467 
468   void set_dreg(unsigned code, double value) {
469     set_fpreg(code, value);
470   }
471 
472   void set_dreg_bits(unsigned code, uint64_t value) {
473     set_fpreg(code, value);
474   }
475 
476   // As above, but don't automatically log the register update.
477   template <typename T>
478   void set_fpreg_no_log(unsigned code, T value) {
479     DCHECK((sizeof(value) == kDRegSize) || (sizeof(value) == kSRegSize));
480     DCHECK(code < kNumberOfFPRegisters);
481     fpregisters_[code].Set(value);
482   }
483 
484   void set_sreg_no_log(unsigned code, float value) {
485     set_fpreg_no_log(code, value);
486   }
487 
488   void set_dreg_no_log(unsigned code, double value) {
489     set_fpreg_no_log(code, value);
490   }
491 
492   SimSystemRegister& nzcv() { return nzcv_; }
493   SimSystemRegister& fpcr() { return fpcr_; }
494 
495   // Debug helpers
496 
497   // Simulator breakpoints.
498   struct Breakpoint {
499     Instruction* location;
500     bool enabled;
501   };
502   std::vector<Breakpoint> breakpoints_;
503   void SetBreakpoint(Instruction* breakpoint);
504   void ListBreakpoints();
505   void CheckBreakpoints();
506 
507   // Helpers for the 'next' command.
508   // When this is set, the Simulator will insert a breakpoint after the next BL
509   // instruction it meets.
510   bool break_on_next_;
511   // Check if the Simulator should insert a break after the current instruction
512   // for the 'next' command.
513   void CheckBreakNext();
514 
515   // Disassemble instruction at the given address.
516   void PrintInstructionsAt(Instruction* pc, uint64_t count);
517 
518   // Print all registers of the specified types.
519   void PrintRegisters();
520   void PrintFPRegisters();
521   void PrintSystemRegisters();
522 
523   // Like Print* (above), but respect log_parameters().
524   void LogSystemRegisters() {
525     if (log_parameters() & LOG_SYS_REGS) PrintSystemRegisters();
526   }
527   void LogRegisters() {
528     if (log_parameters() & LOG_REGS) PrintRegisters();
529   }
530   void LogFPRegisters() {
531     if (log_parameters() & LOG_FP_REGS) PrintFPRegisters();
532   }
533 
534   // Specify relevant register sizes, for PrintFPRegister.
535   //
536   // These values are bit masks; they can be combined in case multiple views of
537   // a machine register are interesting.
538   enum PrintFPRegisterSizes {
539     kPrintDRegValue = 1 << kDRegSize,
540     kPrintSRegValue = 1 << kSRegSize,
541     kPrintAllFPRegValues = kPrintDRegValue | kPrintSRegValue
542   };
543 
544   // Print individual register values (after update).
545   void PrintRegister(unsigned code, Reg31Mode r31mode = Reg31IsStackPointer);
546   void PrintFPRegister(unsigned code,
547                        PrintFPRegisterSizes sizes = kPrintAllFPRegValues);
548   void PrintSystemRegister(SystemRegister id);
549 
550   // Like Print* (above), but respect log_parameters().
551   void LogRegister(unsigned code, Reg31Mode r31mode = Reg31IsStackPointer) {
552     if (log_parameters() & LOG_REGS) PrintRegister(code, r31mode);
553   }
554   void LogFPRegister(unsigned code,
555                      PrintFPRegisterSizes sizes = kPrintAllFPRegValues) {
556     if (log_parameters() & LOG_FP_REGS) PrintFPRegister(code, sizes);
557   }
558   void LogSystemRegister(SystemRegister id) {
559     if (log_parameters() & LOG_SYS_REGS) PrintSystemRegister(id);
560   }
561 
562   // Print memory accesses.
563   void PrintRead(uintptr_t address, size_t size, unsigned reg_code);
564   void PrintReadFP(uintptr_t address, size_t size, unsigned reg_code);
565   void PrintWrite(uintptr_t address, size_t size, unsigned reg_code);
566   void PrintWriteFP(uintptr_t address, size_t size, unsigned reg_code);
567 
568   // Like Print* (above), but respect log_parameters().
569   void LogRead(uintptr_t address, size_t size, unsigned reg_code) {
570     if (log_parameters() & LOG_REGS) PrintRead(address, size, reg_code);
571   }
572   void LogReadFP(uintptr_t address, size_t size, unsigned reg_code) {
573     if (log_parameters() & LOG_FP_REGS) PrintReadFP(address, size, reg_code);
574   }
575   void LogWrite(uintptr_t address, size_t size, unsigned reg_code) {
576     if (log_parameters() & LOG_WRITE) PrintWrite(address, size, reg_code);
577   }
578   void LogWriteFP(uintptr_t address, size_t size, unsigned reg_code) {
579     if (log_parameters() & LOG_WRITE) PrintWriteFP(address, size, reg_code);
580   }
581 
582   int log_parameters() { return log_parameters_; }
583   void set_log_parameters(int new_parameters) {
584     log_parameters_ = new_parameters;
585     if (!decoder_) {
586       if (new_parameters & LOG_DISASM) {
587         PrintF("Run --debug-sim to dynamically turn on disassembler\n");
588       }
589       return;
590     }
591     if (new_parameters & LOG_DISASM) {
592       decoder_->InsertVisitorBefore(print_disasm_, this);
593     } else {
594       decoder_->RemoveVisitor(print_disasm_);
595     }
596   }
597 
598   static inline const char* WRegNameForCode(unsigned code,
599       Reg31Mode mode = Reg31IsZeroRegister);
600   static inline const char* XRegNameForCode(unsigned code,
601       Reg31Mode mode = Reg31IsZeroRegister);
602   static inline const char* SRegNameForCode(unsigned code);
603   static inline const char* DRegNameForCode(unsigned code);
604   static inline const char* VRegNameForCode(unsigned code);
605   static inline int CodeFromName(const char* name);
606 
607  protected:
608   // Simulation helpers ------------------------------------
609   bool ConditionPassed(Condition cond) {
610     SimSystemRegister& flags = nzcv();
611     switch (cond) {
612       case eq:
613         return flags.Z();
614       case ne:
615         return !flags.Z();
616       case hs:
617         return flags.C();
618       case lo:
619         return !flags.C();
620       case mi:
621         return flags.N();
622       case pl:
623         return !flags.N();
624       case vs:
625         return flags.V();
626       case vc:
627         return !flags.V();
628       case hi:
629         return flags.C() && !flags.Z();
630       case ls:
631         return !(flags.C() && !flags.Z());
632       case ge:
633         return flags.N() == flags.V();
634       case lt:
635         return flags.N() != flags.V();
636       case gt:
637         return !flags.Z() && (flags.N() == flags.V());
638       case le:
639         return !(!flags.Z() && (flags.N() == flags.V()));
640       case nv:  // Fall through.
641       case al:
642         return true;
643       default:
644         UNREACHABLE();
645         return false;
646     }
647   }
648 
649   bool ConditionFailed(Condition cond) {
650     return !ConditionPassed(cond);
651   }
652 
653   template<typename T>
654   void AddSubHelper(Instruction* instr, T op2);
655   template<typename T>
656   T AddWithCarry(bool set_flags,
657                  T src1,
658                  T src2,
659                  T carry_in = 0);
660   template<typename T>
661   void AddSubWithCarry(Instruction* instr);
662   template<typename T>
663   void LogicalHelper(Instruction* instr, T op2);
664   template<typename T>
665   void ConditionalCompareHelper(Instruction* instr, T op2);
666   void LoadStoreHelper(Instruction* instr,
667                        int64_t offset,
668                        AddrMode addrmode);
669   void LoadStorePairHelper(Instruction* instr, AddrMode addrmode);
670   uintptr_t LoadStoreAddress(unsigned addr_reg, int64_t offset,
671                              AddrMode addrmode);
672   void LoadStoreWriteBack(unsigned addr_reg,
673                           int64_t offset,
674                           AddrMode addrmode);
675   void CheckMemoryAccess(uintptr_t address, uintptr_t stack);
676 
677   // Memory read helpers.
678   template <typename T, typename A>
679   T MemoryRead(A address) {
680     T value;
681     STATIC_ASSERT((sizeof(value) == 1) || (sizeof(value) == 2) ||
682                   (sizeof(value) == 4) || (sizeof(value) == 8));
683     memcpy(&value, reinterpret_cast<const void*>(address), sizeof(value));
684     return value;
685   }
686 
687   // Memory write helpers.
688   template <typename T, typename A>
689   void MemoryWrite(A address, T value) {
690     STATIC_ASSERT((sizeof(value) == 1) || (sizeof(value) == 2) ||
691                   (sizeof(value) == 4) || (sizeof(value) == 8));
692     memcpy(reinterpret_cast<void*>(address), &value, sizeof(value));
693   }
694 
695   template <typename T>
696   T ShiftOperand(T value,
697                  Shift shift_type,
698                  unsigned amount);
699   template <typename T>
700   T ExtendValue(T value,
701                 Extend extend_type,
702                 unsigned left_shift = 0);
703   template <typename T>
704   void Extract(Instruction* instr);
705   template <typename T>
706   void DataProcessing2Source(Instruction* instr);
707   template <typename T>
708   void BitfieldHelper(Instruction* instr);
709 
710   template <typename T>
711   T FPDefaultNaN() const;
712 
713   void FPCompare(double val0, double val1);
714   double FPRoundInt(double value, FPRounding round_mode);
715   double FPToDouble(float value);
716   float FPToFloat(double value, FPRounding round_mode);
717   double FixedToDouble(int64_t src, int fbits, FPRounding round_mode);
718   double UFixedToDouble(uint64_t src, int fbits, FPRounding round_mode);
719   float FixedToFloat(int64_t src, int fbits, FPRounding round_mode);
720   float UFixedToFloat(uint64_t src, int fbits, FPRounding round_mode);
721   int32_t FPToInt32(double value, FPRounding rmode);
722   int64_t FPToInt64(double value, FPRounding rmode);
723   uint32_t FPToUInt32(double value, FPRounding rmode);
724   uint64_t FPToUInt64(double value, FPRounding rmode);
725 
726   template <typename T>
727   T FPAdd(T op1, T op2);
728 
729   template <typename T>
730   T FPDiv(T op1, T op2);
731 
732   template <typename T>
733   T FPMax(T a, T b);
734 
735   template <typename T>
736   T FPMaxNM(T a, T b);
737 
738   template <typename T>
739   T FPMin(T a, T b);
740 
741   template <typename T>
742   T FPMinNM(T a, T b);
743 
744   template <typename T>
745   T FPMul(T op1, T op2);
746 
747   template <typename T>
748   T FPMulAdd(T a, T op1, T op2);
749 
750   template <typename T>
751   T FPSqrt(T op);
752 
753   template <typename T>
754   T FPSub(T op1, T op2);
755 
756   // Standard NaN processing.
757   template <typename T>
758   T FPProcessNaN(T op);
759 
760   bool FPProcessNaNs(Instruction* instr);
761 
762   template <typename T>
763   T FPProcessNaNs(T op1, T op2);
764 
765   template <typename T>
766   T FPProcessNaNs3(T op1, T op2, T op3);
767 
768   void CheckStackAlignment();
769 
770   inline void CheckPCSComplianceAndRun();
771 
772 #ifdef DEBUG
773   // Corruption values should have their least significant byte cleared to
774   // allow the code of the register being corrupted to be inserted.
775   static const uint64_t kCallerSavedRegisterCorruptionValue =
776       0xca11edc0de000000UL;
777   // This value is a NaN in both 32-bit and 64-bit FP.
778   static const uint64_t kCallerSavedFPRegisterCorruptionValue =
779       0x7ff000007f801000UL;
780   // This value is a mix of 32/64-bits NaN and "verbose" immediate.
781   static const uint64_t kDefaultCPURegisterCorruptionValue =
782       0x7ffbad007f8bad00UL;
783 
784   void CorruptRegisters(CPURegList* list,
785                         uint64_t value = kDefaultCPURegisterCorruptionValue);
786   void CorruptAllCallerSavedCPURegisters();
787 #endif
788 
789   // Pseudo Printf instruction
790   void DoPrintf(Instruction* instr);
791 
792   // Processor state ---------------------------------------
793 
794   // Output stream.
795   FILE* stream_;
796   PrintDisassembler* print_disasm_;
797   void PRINTF_FORMAT(2, 3) TraceSim(const char* format, ...);
798 
799   // Instrumentation.
800   Instrument* instrument_;
801 
802   // General purpose registers. Register 31 is the stack pointer.
803   SimRegister registers_[kNumberOfRegisters];
804 
805   // Floating point registers
806   SimFPRegister fpregisters_[kNumberOfFPRegisters];
807 
808   // Processor state
809   // bits[31, 27]: Condition flags N, Z, C, and V.
810   //               (Negative, Zero, Carry, Overflow)
811   SimSystemRegister nzcv_;
812 
813   // Floating-Point Control Register
814   SimSystemRegister fpcr_;
815 
816   // Only a subset of FPCR features are supported by the simulator. This helper
817   // checks that the FPCR settings are supported.
818   //
819   // This is checked when floating-point instructions are executed, not when
820   // FPCR is set. This allows generated code to modify FPCR for external
821   // functions, or to save and restore it when entering and leaving generated
822   // code.
823   void AssertSupportedFPCR() {
824     DCHECK(fpcr().FZ() == 0);             // No flush-to-zero support.
825     DCHECK(fpcr().RMode() == FPTieEven);  // Ties-to-even rounding only.
826 
827     // The simulator does not support half-precision operations so fpcr().AHP()
828     // is irrelevant, and is not checked here.
829   }
830 
831   template <typename T>
832   static int CalcNFlag(T result) {
833     return (result >> (sizeof(T) * 8 - 1)) & 1;
834   }
835 
836   static int CalcZFlag(uint64_t result) {
837     return result == 0;
838   }
839 
840   static const uint32_t kConditionFlagsMask = 0xf0000000;
841 
842   // Stack
843   uintptr_t stack_;
844   static const size_t stack_protection_size_ = KB;
845   size_t stack_size_;
846   uintptr_t stack_limit_;
847 
848   Decoder<DispatchingDecoderVisitor>* decoder_;
849   Decoder<DispatchingDecoderVisitor>* disassembler_decoder_;
850 
851   // Indicates if the pc has been modified by the instruction and should not be
852   // automatically incremented.
853   bool pc_modified_;
854   Instruction* pc_;
855 
856   static const char* xreg_names[];
857   static const char* wreg_names[];
858   static const char* sreg_names[];
859   static const char* dreg_names[];
860   static const char* vreg_names[];
861 
862   // Debugger input.
863   void set_last_debugger_input(char* input) {
864     DeleteArray(last_debugger_input_);
865     last_debugger_input_ = input;
866   }
867   char* last_debugger_input() { return last_debugger_input_; }
868   char* last_debugger_input_;
869 
870  private:
871   void Init(FILE* stream);
872 
873   int  log_parameters_;
874   Isolate* isolate_;
875 };
876 
877 
878 // When running with the simulator transition into simulated execution at this
879 // point.
880 #define CALL_GENERATED_CODE(isolate, entry, p0, p1, p2, p3, p4)  \
881   reinterpret_cast<Object*>(Simulator::current(isolate)->CallJS( \
882       FUNCTION_ADDR(entry), p0, p1, p2, p3, p4))
883 
884 #define CALL_GENERATED_REGEXP_CODE(isolate, entry, p0, p1, p2, p3, p4, p5, p6, \
885                                    p7, p8)                                     \
886   static_cast<int>(Simulator::current(isolate)->CallRegExp(                    \
887       entry, p0, p1, p2, p3, p4, p5, p6, p7, NULL, p8))
888 
889 
890 // The simulator has its own stack. Thus it has a different stack limit from
891 // the C-based native code.  The JS-based limit normally points near the end of
892 // the simulator stack.  When the C-based limit is exhausted we reflect that by
893 // lowering the JS-based limit as well, to make stack checks trigger.
894 class SimulatorStack : public v8::internal::AllStatic {
895  public:
896   static uintptr_t JsLimitFromCLimit(v8::internal::Isolate* isolate,
897                                             uintptr_t c_limit) {
898     return Simulator::current(isolate)->StackLimit(c_limit);
899   }
900 
901   static uintptr_t RegisterCTryCatch(v8::internal::Isolate* isolate,
902                                      uintptr_t try_catch_address) {
903     Simulator* sim = Simulator::current(isolate);
904     return sim->PushAddress(try_catch_address);
905   }
906 
907   static void UnregisterCTryCatch(v8::internal::Isolate* isolate) {
908     Simulator::current(isolate)->PopAddress();
909   }
910 };
911 
912 #endif  // !defined(USE_SIMULATOR)
913 
914 }  // namespace internal
915 }  // namespace v8
916 
917 #endif  // V8_ARM64_SIMULATOR_ARM64_H_
918