Home | History | Annotate | Download | only in arm64
      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:
     54   static uintptr_t JsLimitFromCLimit(v8::internal::Isolate* isolate,
     55                                      uintptr_t c_limit) {
     56     USE(isolate);
     57     return c_limit;
     58   }
     59 
     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 
     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