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/globals.h"
18 #include "src/utils.h"
19 
20 namespace v8 {
21 namespace internal {
22 
23 #if !defined(USE_SIMULATOR)
24 
25 // Running without a simulator on a native ARM64 platform.
26 // When running without a simulator we call the entry directly.
27 #define CALL_GENERATED_CODE(isolate, entry, p0, p1, p2, p3, p4) \
28   (entry(p0, p1, p2, p3, p4))
29 
30 typedef int (*arm64_regexp_matcher)(String* input,
31                                     int64_t start_offset,
32                                     const byte* input_start,
33                                     const byte* input_end,
34                                     int* output,
35                                     int64_t output_size,
36                                     Address stack_base,
37                                     int64_t direct_call,
38                                     void* return_address,
39                                     Isolate* isolate);
40 
41 // Call the generated regexp code directly. The code at the entry address
42 // should act as a function matching the type arm64_regexp_matcher.
43 // The ninth argument is a dummy that reserves the space used for
44 // the return address added by the ExitFrame in native calls.
45 #define CALL_GENERATED_REGEXP_CODE(isolate, entry, p0, p1, p2, p3, p4, p5, p6, \
46                                    p7, p8)                                     \
47   (FUNCTION_CAST<arm64_regexp_matcher>(entry)(p0, p1, p2, p3, p4, p5, p6, p7,  \
48                                               NULL, p8))
49 
50 // Running without a simulator there is nothing to do.
51 class SimulatorStack : public v8::internal::AllStatic {
52  public:
JsLimitFromCLimit(v8::internal::Isolate * isolate,uintptr_t c_limit)53   static uintptr_t JsLimitFromCLimit(v8::internal::Isolate* isolate,
54                                      uintptr_t c_limit) {
55     USE(isolate);
56     return c_limit;
57   }
58 
RegisterCTryCatch(v8::internal::Isolate * isolate,uintptr_t try_catch_address)59   static uintptr_t RegisterCTryCatch(v8::internal::Isolate* isolate,
60                                      uintptr_t try_catch_address) {
61     USE(isolate);
62     return try_catch_address;
63   }
64 
UnregisterCTryCatch(v8::internal::Isolate * isolate)65   static void UnregisterCTryCatch(v8::internal::Isolate* isolate) {
66     USE(isolate);
67   }
68 };
69 
70 #else  // !defined(USE_SIMULATOR)
71 
72 
73 // The proper way to initialize a simulated system register (such as NZCV) is as
74 // follows:
75 //  SimSystemRegister nzcv = SimSystemRegister::DefaultValueFor(NZCV);
76 class SimSystemRegister {
77  public:
78   // The default constructor represents a register which has no writable bits.
79   // It is not possible to set its value to anything other than 0.
80   SimSystemRegister() : value_(0), write_ignore_mask_(0xffffffff) { }
81 
82   uint32_t RawValue() const {
83     return value_;
84   }
85 
86   void SetRawValue(uint32_t new_value) {
87     value_ = (value_ & write_ignore_mask_) | (new_value & ~write_ignore_mask_);
88   }
89 
90   uint32_t Bits(int msb, int lsb) const {
91     return unsigned_bitextract_32(msb, lsb, value_);
92   }
93 
94   int32_t SignedBits(int msb, int lsb) const {
95     return signed_bitextract_32(msb, lsb, value_);
96   }
97 
98   void SetBits(int msb, int lsb, uint32_t bits);
99 
100   // Default system register values.
101   static SimSystemRegister DefaultValueFor(SystemRegister id);
102 
103 #define DEFINE_GETTER(Name, HighBit, LowBit, Func, Type)                       \
104   Type Name() const { return static_cast<Type>(Func(HighBit, LowBit)); }       \
105   void Set##Name(Type bits) {                                                  \
106     SetBits(HighBit, LowBit, static_cast<Type>(bits));                         \
107   }
108 #define DEFINE_WRITE_IGNORE_MASK(Name, Mask)                                   \
109   static const uint32_t Name##WriteIgnoreMask = ~static_cast<uint32_t>(Mask);
110   SYSTEM_REGISTER_FIELDS_LIST(DEFINE_GETTER, DEFINE_WRITE_IGNORE_MASK)
111 #undef DEFINE_ZERO_BITS
112 #undef DEFINE_GETTER
113 
114  protected:
115   // Most system registers only implement a few of the bits in the word. Other
116   // bits are "read-as-zero, write-ignored". The write_ignore_mask argument
117   // describes the bits which are not modifiable.
118   SimSystemRegister(uint32_t value, uint32_t write_ignore_mask)
119       : value_(value), write_ignore_mask_(write_ignore_mask) { }
120 
121   uint32_t value_;
122   uint32_t write_ignore_mask_;
123 };
124 
125 
126 // Represent a register (r0-r31, v0-v31).
127 class SimRegisterBase {
128  public:
129   template<typename T>
130   void Set(T new_value) {
131     value_ = 0;
132     memcpy(&value_, &new_value, sizeof(T));
133   }
134 
135   template<typename T>
136   T Get() const {
137     T result;
138     memcpy(&result, &value_, sizeof(T));
139     return result;
140   }
141 
142  protected:
143   int64_t value_;
144 };
145 
146 
147 typedef SimRegisterBase SimRegister;      // r0-r31
148 typedef SimRegisterBase SimFPRegister;    // v0-v31
149 
150 
151 class Simulator : public DecoderVisitor {
152  public:
153   static void FlushICache(v8::internal::HashMap* i_cache, void* start,
154                           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(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_METHOD_CHECKING 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