| OLD | NEW | 
|    1 // Copyright 2014 the V8 project authors. All rights reserved. |    1 // Copyright 2014 the V8 project authors. All rights reserved. | 
|    2 // Use of this source code is governed by a BSD-style license that can be |    2 // Use of this source code is governed by a BSD-style license that can be | 
|    3 // found in the LICENSE file. |    3 // found in the LICENSE file. | 
|    4  |    4  | 
|    5  |    5 // Declares a Simulator for S390 instructions if we are not generating a native | 
|    6 // Declares a Simulator for PPC instructions if we are not generating a native |    6 // S390 binary. This Simulator allows us to run and debug S390 code generation | 
|    7 // PPC binary. This Simulator allows us to run and debug PPC code generation on |    7 // on regular desktop machines. | 
|    8 // regular desktop machines. |  | 
|    9 // V8 calls into generated code by "calling" the CALL_GENERATED_CODE macro, |    8 // V8 calls into generated code by "calling" the CALL_GENERATED_CODE macro, | 
|   10 // which will start execution in the Simulator or forwards to the real entry |    9 // which will start execution in the Simulator or forwards to the real entry | 
|   11 // on a PPC HW platform. |   10 // on a S390 hardware platform. | 
|   12  |   11  | 
|   13 #ifndef V8_PPC_SIMULATOR_PPC_H_ |   12 #ifndef V8_S390_SIMULATOR_S390_H_ | 
|   14 #define V8_PPC_SIMULATOR_PPC_H_ |   13 #define V8_S390_SIMULATOR_S390_H_ | 
|   15  |   14  | 
|   16 #include "src/allocation.h" |   15 #include "src/allocation.h" | 
|   17  |   16  | 
|   18 #if !defined(USE_SIMULATOR) |   17 #if !defined(USE_SIMULATOR) | 
|   19 // Running without a simulator on a native ppc platform. |   18 // Running without a simulator on a native s390 platform. | 
|   20  |   19  | 
|   21 namespace v8 { |   20 namespace v8 { | 
|   22 namespace internal { |   21 namespace internal { | 
|   23  |   22  | 
|   24 // When running without a simulator we call the entry directly. |   23 // When running without a simulator we call the entry directly. | 
|   25 #define CALL_GENERATED_CODE(isolate, entry, p0, p1, p2, p3, p4) \ |   24 #define CALL_GENERATED_CODE(isolate, entry, p0, p1, p2, p3, p4) \ | 
|   26   (entry(p0, p1, p2, p3, p4)) |   25   (entry(p0, p1, p2, p3, p4)) | 
|   27  |   26  | 
|   28 typedef int (*ppc_regexp_matcher)(String*, int, const byte*, const byte*, int*, |   27 typedef int (*s390_regexp_matcher)(String*, int, const byte*, const byte*, int*, | 
|   29                                   int, Address, int, void*, Isolate*); |   28                                    int, Address, int, void*, Isolate*); | 
|   30  |  | 
|   31  |   29  | 
|   32 // Call the generated regexp code directly. The code at the entry address |   30 // Call the generated regexp code directly. The code at the entry address | 
|   33 // should act as a function matching the type ppc_regexp_matcher. |   31 // should act as a function matching the type ppc_regexp_matcher. | 
|   34 // The ninth argument is a dummy that reserves the space used for |   32 // The ninth argument is a dummy that reserves the space used for | 
|   35 // the return address added by the ExitFrame in native calls. |   33 // the return address added by the ExitFrame in native calls. | 
|   36 #define CALL_GENERATED_REGEXP_CODE(isolate, entry, p0, p1, p2, p3, p4, p5, p6, \ |   34 #define CALL_GENERATED_REGEXP_CODE(isolate, entry, p0, p1, p2, p3, p4, p5, p6, \ | 
|   37                                    p7, p8)                                     \ |   35                                    p7, p8)                                     \ | 
|   38   (FUNCTION_CAST<ppc_regexp_matcher>(entry)(p0, p1, p2, p3, p4, p5, p6, p7,    \ |   36   (FUNCTION_CAST<s390_regexp_matcher>(entry)(p0, p1, p2, p3, p4, p5, p6, p7,   \ | 
|   39                                             NULL, p8)) |   37                                              NULL, p8)) | 
|   40  |   38  | 
|   41 // The stack limit beyond which we will throw stack overflow errors in |   39 // The stack limit beyond which we will throw stack overflow errors in | 
|   42 // generated code. Because generated code on ppc uses the C stack, we |   40 // generated code. Because generated code on s390 uses the C stack, we | 
|   43 // just use the C stack limit. |   41 // just use the C stack limit. | 
|   44 class SimulatorStack : public v8::internal::AllStatic { |   42 class SimulatorStack : public v8::internal::AllStatic { | 
|   45  public: |   43  public: | 
|   46   static inline uintptr_t JsLimitFromCLimit(v8::internal::Isolate* isolate, |   44   static inline uintptr_t JsLimitFromCLimit(v8::internal::Isolate* isolate, | 
|   47                                             uintptr_t c_limit) { |   45                                             uintptr_t c_limit) { | 
|   48     USE(isolate); |   46     USE(isolate); | 
|   49     return c_limit; |   47     return c_limit; | 
|   50   } |   48   } | 
|   51  |   49  | 
|   52   static inline uintptr_t RegisterCTryCatch(v8::internal::Isolate* isolate, |   50   static inline uintptr_t RegisterCTryCatch(v8::internal::Isolate* isolate, | 
|   53                                             uintptr_t try_catch_address) { |   51                                             uintptr_t try_catch_address) { | 
|   54     USE(isolate); |   52     USE(isolate); | 
|   55     return try_catch_address; |   53     return try_catch_address; | 
|   56   } |   54   } | 
|   57  |   55  | 
|   58   static inline void UnregisterCTryCatch(v8::internal::Isolate* isolate) { |   56   static inline void UnregisterCTryCatch(v8::internal::Isolate* isolate) { | 
|   59     USE(isolate); |   57     USE(isolate); | 
|   60   } |   58   } | 
|   61 }; |   59 }; | 
|   62 }  // namespace internal |   60 }  // namespace internal | 
|   63 }  // namespace v8 |   61 }  // namespace v8 | 
|   64  |   62  | 
|   65 #else  // !defined(USE_SIMULATOR) |   63 #else  // !defined(USE_SIMULATOR) | 
|   66 // Running with a simulator. |   64 // Running with a simulator. | 
|   67  |   65  | 
|   68 #include "src/assembler.h" |   66 #include "src/assembler.h" | 
|   69 #include "src/hashmap.h" |   67 #include "src/hashmap.h" | 
|   70 #include "src/ppc/constants-ppc.h" |   68 #include "src/s390/constants-s390.h" | 
|   71  |   69  | 
|   72 namespace v8 { |   70 namespace v8 { | 
|   73 namespace internal { |   71 namespace internal { | 
|   74  |   72  | 
|   75 class CachePage { |   73 class CachePage { | 
|   76  public: |   74  public: | 
|   77   static const int LINE_VALID = 0; |   75   static const int LINE_VALID = 0; | 
|   78   static const int LINE_INVALID = 1; |   76   static const int LINE_INVALID = 1; | 
|   79  |   77  | 
|   80   static const int kPageShift = 12; |   78   static const int kPageShift = 12; | 
| (...skipping 10 matching lines...) Expand all  Loading... | 
|   91   } |   89   } | 
|   92  |   90  | 
|   93   char* CachedData(int offset) { return &data_[offset]; } |   91   char* CachedData(int offset) { return &data_[offset]; } | 
|   94  |   92  | 
|   95  private: |   93  private: | 
|   96   char data_[kPageSize];  // The cached data. |   94   char data_[kPageSize];  // The cached data. | 
|   97   static const int kValidityMapSize = kPageSize >> kLineShift; |   95   static const int kValidityMapSize = kPageSize >> kLineShift; | 
|   98   char validity_map_[kValidityMapSize];  // One byte per line. |   96   char validity_map_[kValidityMapSize];  // One byte per line. | 
|   99 }; |   97 }; | 
|  100  |   98  | 
|  101  |  | 
|  102 class Simulator { |   99 class Simulator { | 
|  103  public: |  100  public: | 
|  104   friend class PPCDebugger; |  101   friend class S390Debugger; | 
|  105   enum Register { |  102   enum Register { | 
|  106     no_reg = -1, |  103     no_reg = -1, | 
|  107     r0 = 0, |  104     r0 = 0, | 
|  108     sp, |  105     r1 = 1, | 
|  109     r2, |  106     r2 = 2, | 
|  110     r3, |  107     r3 = 3, | 
|  111     r4, |  108     r4 = 4, | 
|  112     r5, |  109     r5 = 5, | 
|  113     r6, |  110     r6 = 6, | 
|  114     r7, |  111     r7 = 7, | 
|  115     r8, |  112     r8 = 8, | 
|  116     r9, |  113     r9 = 9, | 
|  117     r10, |  114     r10 = 10, | 
|  118     r11, |  115     r11 = 11, | 
|  119     r12, |  116     r12 = 12, | 
|  120     r13, |  117     r13 = 13, | 
|  121     r14, |  118     r14 = 14, | 
|  122     r15, |  119     r15 = 15, | 
|  123     r16, |  120     fp = r11, | 
|  124     r17, |  121     ip = r12, | 
|  125     r18, |  122     cp = r13, | 
|  126     r19, |  123     ra = r14, | 
|  127     r20, |  124     sp = r15,  // name aliases | 
|  128     r21, |  125     kNumGPRs = 16, | 
|  129     r22, |  | 
|  130     r23, |  | 
|  131     r24, |  | 
|  132     r25, |  | 
|  133     r26, |  | 
|  134     r27, |  | 
|  135     r28, |  | 
|  136     r29, |  | 
|  137     r30, |  | 
|  138     fp, |  | 
|  139     kNumGPRs = 32, |  | 
|  140     d0 = 0, |  126     d0 = 0, | 
|  141     d1, |  127     d1, | 
|  142     d2, |  128     d2, | 
|  143     d3, |  129     d3, | 
|  144     d4, |  130     d4, | 
|  145     d5, |  131     d5, | 
|  146     d6, |  132     d6, | 
|  147     d7, |  133     d7, | 
|  148     d8, |  134     d8, | 
|  149     d9, |  135     d9, | 
|  150     d10, |  136     d10, | 
|  151     d11, |  137     d11, | 
|  152     d12, |  138     d12, | 
|  153     d13, |  139     d13, | 
|  154     d14, |  140     d14, | 
|  155     d15, |  141     d15, | 
|  156     d16, |  142     kNumFPRs = 16 | 
|  157     d17, |  | 
|  158     d18, |  | 
|  159     d19, |  | 
|  160     d20, |  | 
|  161     d21, |  | 
|  162     d22, |  | 
|  163     d23, |  | 
|  164     d24, |  | 
|  165     d25, |  | 
|  166     d26, |  | 
|  167     d27, |  | 
|  168     d28, |  | 
|  169     d29, |  | 
|  170     d30, |  | 
|  171     d31, |  | 
|  172     kNumFPRs = 32 |  | 
|  173   }; |  143   }; | 
|  174  |  144  | 
|  175   explicit Simulator(Isolate* isolate); |  145   explicit Simulator(Isolate* isolate); | 
|  176   ~Simulator(); |  146   ~Simulator(); | 
|  177  |  147  | 
|  178   // The currently executing Simulator instance. Potentially there can be one |  148   // The currently executing Simulator instance. Potentially there can be one | 
|  179   // for each native thread. |  149   // for each native thread. | 
|  180   static Simulator* current(v8::internal::Isolate* isolate); |  150   static Simulator* current(v8::internal::Isolate* isolate); | 
|  181  |  151  | 
|  182   // Accessors for register state. |  152   // Accessors for register state. | 
|  183   void set_register(int reg, intptr_t value); |  153   void set_register(int reg, uint64_t value); | 
|  184   intptr_t get_register(int reg) const; |  154   uint64_t get_register(int reg) const; | 
 |  155   template <typename T> | 
 |  156   T get_low_register(int reg) const; | 
 |  157   template <typename T> | 
 |  158   T get_high_register(int reg) const; | 
 |  159   void set_low_register(int reg, uint32_t value); | 
 |  160   void set_high_register(int reg, uint32_t value); | 
 |  161  | 
|  185   double get_double_from_register_pair(int reg); |  162   double get_double_from_register_pair(int reg); | 
|  186   void set_d_register_from_double(int dreg, const double dbl) { |  163   void set_d_register_from_double(int dreg, const double dbl) { | 
|  187     DCHECK(dreg >= 0 && dreg < kNumFPRs); |  164     DCHECK(dreg >= 0 && dreg < kNumFPRs); | 
|  188     *bit_cast<double*>(&fp_registers_[dreg]) = dbl; |  165     *bit_cast<double*>(&fp_registers_[dreg]) = dbl; | 
|  189   } |  166   } | 
 |  167  | 
|  190   double get_double_from_d_register(int dreg) { |  168   double get_double_from_d_register(int dreg) { | 
|  191     DCHECK(dreg >= 0 && dreg < kNumFPRs); |  169     DCHECK(dreg >= 0 && dreg < kNumFPRs); | 
|  192     return *bit_cast<double*>(&fp_registers_[dreg]); |  170     return *bit_cast<double*>(&fp_registers_[dreg]); | 
|  193   } |  171   } | 
|  194   void set_d_register(int dreg, int64_t value) { |  172   void set_d_register(int dreg, int64_t value) { | 
|  195     DCHECK(dreg >= 0 && dreg < kNumFPRs); |  173     DCHECK(dreg >= 0 && dreg < kNumFPRs); | 
|  196     fp_registers_[dreg] = value; |  174     fp_registers_[dreg] = value; | 
|  197   } |  175   } | 
|  198   int64_t get_d_register(int dreg) { |  176   int64_t get_d_register(int dreg) { | 
|  199     DCHECK(dreg >= 0 && dreg < kNumFPRs); |  177     DCHECK(dreg >= 0 && dreg < kNumFPRs); | 
|  200     return fp_registers_[dreg]; |  178     return fp_registers_[dreg]; | 
|  201   } |  179   } | 
|  202  |  180  | 
 |  181   void set_d_register_from_float32(int dreg, const float f) { | 
 |  182     DCHECK(dreg >= 0 && dreg < kNumFPRs); | 
 |  183  | 
 |  184     int32_t f_int = *bit_cast<int32_t*>(&f); | 
 |  185     int64_t finalval = static_cast<int64_t>(f_int) << 32; | 
 |  186     set_d_register(dreg, finalval); | 
 |  187   } | 
 |  188  | 
 |  189   float get_float32_from_d_register(int dreg) { | 
 |  190     DCHECK(dreg >= 0 && dreg < kNumFPRs); | 
 |  191  | 
 |  192     int64_t regval = get_d_register(dreg) >> 32; | 
 |  193     int32_t regval32 = static_cast<int32_t>(regval); | 
 |  194     return *bit_cast<float*>(®val32); | 
 |  195   } | 
 |  196  | 
|  203   // Special case of set_register and get_register to access the raw PC value. |  197   // Special case of set_register and get_register to access the raw PC value. | 
|  204   void set_pc(intptr_t value); |  198   void set_pc(intptr_t value); | 
|  205   intptr_t get_pc() const; |  199   intptr_t get_pc() const; | 
|  206  |  200  | 
|  207   Address get_sp() const { |  201   Address get_sp() const { | 
|  208     return reinterpret_cast<Address>(static_cast<intptr_t>(get_register(sp))); |  202     return reinterpret_cast<Address>(static_cast<intptr_t>(get_register(sp))); | 
|  209   } |  203   } | 
|  210  |  204  | 
|  211   // Accessor to the internal simulator stack area. |  205   // Accessor to the internal simulator stack area. | 
|  212   uintptr_t StackLimit(uintptr_t c_limit) const; |  206   uintptr_t StackLimit(uintptr_t c_limit) const; | 
|  213  |  207  | 
|  214   // Executes PPC instructions until the PC reaches end_sim_pc. |  208   // Executes S390 instructions until the PC reaches end_sim_pc. | 
|  215   void Execute(); |  209   void Execute(); | 
|  216  |  210  | 
|  217   // Call on program start. |  211   // Call on program start. | 
|  218   static void Initialize(Isolate* isolate); |  212   static void Initialize(Isolate* isolate); | 
|  219  |  213  | 
|  220   static void TearDown(HashMap* i_cache, Redirection* first); |  214   static void TearDown(HashMap* i_cache, Redirection* first); | 
|  221  |  215  | 
|  222   // V8 generally calls into generated JS code with 5 parameters and into |  216   // V8 generally calls into generated JS code with 5 parameters and into | 
|  223   // generated RegExp code with 7 parameters. This is a convenience function, |  217   // generated RegExp code with 7 parameters. This is a convenience function, | 
|  224   // which sets up the simulator state and grabs the result on return. |  218   // which sets up the simulator state and grabs the result on return. | 
| (...skipping 26 matching lines...) Expand all  Loading... | 
|  251     // Known bad pc value to ensure that the simulator does not execute |  245     // Known bad pc value to ensure that the simulator does not execute | 
|  252     // without being properly setup. |  246     // without being properly setup. | 
|  253     bad_lr = -1, |  247     bad_lr = -1, | 
|  254     // A pc value used to signal the simulator to stop execution.  Generally |  248     // A pc value used to signal the simulator to stop execution.  Generally | 
|  255     // the lr is set to this value on transition from native C code to |  249     // the lr is set to this value on transition from native C code to | 
|  256     // simulated execution, so that the simulator can "return" to the native |  250     // simulated execution, so that the simulator can "return" to the native | 
|  257     // C code. |  251     // C code. | 
|  258     end_sim_pc = -2 |  252     end_sim_pc = -2 | 
|  259   }; |  253   }; | 
|  260  |  254  | 
|  261   enum BCType { BC_OFFSET, BC_LINK_REG, BC_CTR_REG }; |  | 
|  262  |  | 
|  263   // Unsupported instructions use Format to print an error and stop execution. |  255   // Unsupported instructions use Format to print an error and stop execution. | 
|  264   void Format(Instruction* instr, const char* format); |  256   void Format(Instruction* instr, const char* format); | 
|  265  |  257  | 
|  266   // Helper functions to set the conditional flags in the architecture state. |  258   // Helper functions to set the conditional flags in the architecture state. | 
|  267   bool CarryFrom(int32_t left, int32_t right, int32_t carry = 0); |  259   bool CarryFrom(int32_t left, int32_t right, int32_t carry = 0); | 
|  268   bool BorrowFrom(int32_t left, int32_t right); |  260   bool BorrowFrom(int32_t left, int32_t right); | 
|  269   bool OverflowFrom(int32_t alu_out, int32_t left, int32_t right, |  261   bool OverflowFrom(int32_t alu_out, int32_t left, int32_t right, | 
|  270                     bool addition); |  262                     bool addition); | 
|  271  |  263  | 
|  272   // Helper functions to decode common "addressing" modes |  264   // Helper functions to decode common "addressing" modes | 
|  273   int32_t GetShiftRm(Instruction* instr, bool* carry_out); |  265   int32_t GetShiftRm(Instruction* instr, bool* carry_out); | 
|  274   int32_t GetImm(Instruction* instr, bool* carry_out); |  266   int32_t GetImm(Instruction* instr, bool* carry_out); | 
|  275   void ProcessPUW(Instruction* instr, int num_regs, int operand_size, |  267   void ProcessPUW(Instruction* instr, int num_regs, int operand_size, | 
|  276                   intptr_t* start_address, intptr_t* end_address); |  268                   intptr_t* start_address, intptr_t* end_address); | 
|  277   void HandleRList(Instruction* instr, bool load); |  269   void HandleRList(Instruction* instr, bool load); | 
|  278   void HandleVList(Instruction* inst); |  270   void HandleVList(Instruction* inst); | 
|  279   void SoftwareInterrupt(Instruction* instr); |  271   void SoftwareInterrupt(Instruction* instr); | 
|  280  |  272  | 
|  281   // Stop helper functions. |  273   // Stop helper functions. | 
|  282   inline bool isStopInstruction(Instruction* instr); |  274   inline bool isStopInstruction(Instruction* instr); | 
|  283   inline bool isWatchedStop(uint32_t bkpt_code); |  275   inline bool isWatchedStop(uint32_t bkpt_code); | 
|  284   inline bool isEnabledStop(uint32_t bkpt_code); |  276   inline bool isEnabledStop(uint32_t bkpt_code); | 
|  285   inline void EnableStop(uint32_t bkpt_code); |  277   inline void EnableStop(uint32_t bkpt_code); | 
|  286   inline void DisableStop(uint32_t bkpt_code); |  278   inline void DisableStop(uint32_t bkpt_code); | 
|  287   inline void IncreaseStopCounter(uint32_t bkpt_code); |  279   inline void IncreaseStopCounter(uint32_t bkpt_code); | 
|  288   void PrintStopInfo(uint32_t code); |  280   void PrintStopInfo(uint32_t code); | 
|  289  |  281  | 
 |  282   // Byte Reverse | 
 |  283   inline int16_t ByteReverse(int16_t hword); | 
 |  284   inline int32_t ByteReverse(int32_t word); | 
 |  285  | 
|  290   // Read and write memory. |  286   // Read and write memory. | 
|  291   inline uint8_t ReadBU(intptr_t addr); |  287   inline uint8_t ReadBU(intptr_t addr); | 
|  292   inline int8_t ReadB(intptr_t addr); |  288   inline int8_t ReadB(intptr_t addr); | 
|  293   inline void WriteB(intptr_t addr, uint8_t value); |  289   inline void WriteB(intptr_t addr, uint8_t value); | 
|  294   inline void WriteB(intptr_t addr, int8_t value); |  290   inline void WriteB(intptr_t addr, int8_t value); | 
|  295  |  291  | 
|  296   inline uint16_t ReadHU(intptr_t addr, Instruction* instr); |  292   inline uint16_t ReadHU(intptr_t addr, Instruction* instr); | 
|  297   inline int16_t ReadH(intptr_t addr, Instruction* instr); |  293   inline int16_t ReadH(intptr_t addr, Instruction* instr); | 
|  298   // Note: Overloaded on the sign of the value. |  294   // Note: Overloaded on the sign of the value. | 
|  299   inline void WriteH(intptr_t addr, uint16_t value, Instruction* instr); |  295   inline void WriteH(intptr_t addr, uint16_t value, Instruction* instr); | 
|  300   inline void WriteH(intptr_t addr, int16_t value, Instruction* instr); |  296   inline void WriteH(intptr_t addr, int16_t value, Instruction* instr); | 
|  301  |  297  | 
|  302   inline uint32_t ReadWU(intptr_t addr, Instruction* instr); |  298   inline uint32_t ReadWU(intptr_t addr, Instruction* instr); | 
|  303   inline int32_t ReadW(intptr_t addr, Instruction* instr); |  299   inline int32_t ReadW(intptr_t addr, Instruction* instr); | 
|  304   inline void WriteW(intptr_t addr, uint32_t value, Instruction* instr); |  300   inline void WriteW(intptr_t addr, uint32_t value, Instruction* instr); | 
|  305   inline void WriteW(intptr_t addr, int32_t value, Instruction* instr); |  301   inline void WriteW(intptr_t addr, int32_t value, Instruction* instr); | 
|  306  |  302  | 
|  307   intptr_t* ReadDW(intptr_t addr); |  303   inline int64_t ReadDW(intptr_t addr); | 
|  308   void WriteDW(intptr_t addr, int64_t value); |  304   inline double ReadDouble(intptr_t addr); | 
 |  305   inline void WriteDW(intptr_t addr, int64_t value); | 
|  309  |  306  | 
 |  307   // S390 | 
|  310   void Trace(Instruction* instr); |  308   void Trace(Instruction* instr); | 
|  311   void SetCR0(intptr_t result, bool setSO = false); |  309   bool DecodeTwoByte(Instruction* instr); | 
|  312   void ExecuteBranchConditional(Instruction* instr, BCType type); |  310   bool DecodeFourByte(Instruction* instr); | 
|  313   void ExecuteExt1(Instruction* instr); |  311   bool DecodeFourByteArithmetic(Instruction* instr); | 
|  314   bool ExecuteExt2_10bit(Instruction* instr); |  312   bool DecodeFourByteFloatingPoint(Instruction* instr); | 
|  315   bool ExecuteExt2_9bit_part1(Instruction* instr); |  313   void DecodeFourByteFloatingPointIntConversion(Instruction* instr); | 
|  316   bool ExecuteExt2_9bit_part2(Instruction* instr); |  314   void DecodeFourByteFloatingPointRound(Instruction* instr); | 
|  317   void ExecuteExt2_5bit(Instruction* instr); |  | 
|  318   void ExecuteExt2(Instruction* instr); |  | 
|  319   void ExecuteExt3(Instruction* instr); |  | 
|  320   void ExecuteExt4(Instruction* instr); |  | 
|  321 #if V8_TARGET_ARCH_PPC64 |  | 
|  322   void ExecuteExt5(Instruction* instr); |  | 
|  323 #endif |  | 
|  324   void ExecuteGeneric(Instruction* instr); |  | 
|  325  |  315  | 
|  326   void SetFPSCR(int bit) { fp_condition_reg_ |= (1 << (31 - bit)); } |  316   bool DecodeSixByte(Instruction* instr); | 
|  327   void ClearFPSCR(int bit) { fp_condition_reg_ &= ~(1 << (31 - bit)); } |  317   bool DecodeSixByteArithmetic(Instruction* instr); | 
 |  318   bool S390InstructionDecode(Instruction* instr); | 
 |  319  | 
 |  320   template <typename T> | 
 |  321   void SetS390ConditionCode(T lhs, T rhs) { | 
 |  322     condition_reg_ = 0; | 
 |  323     if (lhs == rhs) { | 
 |  324       condition_reg_ |= CC_EQ; | 
 |  325     } else if (lhs < rhs) { | 
 |  326       condition_reg_ |= CC_LT; | 
 |  327     } else if (lhs > rhs) { | 
 |  328       condition_reg_ |= CC_GT; | 
 |  329     } | 
 |  330  | 
 |  331     // We get down here only for floating point | 
 |  332     // comparisons and the values are unordered | 
 |  333     // i.e. NaN | 
 |  334     if (condition_reg_ == 0) condition_reg_ = unordered; | 
 |  335   } | 
 |  336  | 
 |  337   bool isNaN(double value) { return (value != value); } | 
 |  338  | 
 |  339   // Set the condition code for bitwise operations | 
 |  340   // CC0 is set if value == 0. | 
 |  341   // CC1 is set if value != 0. | 
 |  342   // CC2/CC3 are not set. | 
 |  343   template <typename T> | 
 |  344   void SetS390BitWiseConditionCode(T value) { | 
 |  345     condition_reg_ = 0; | 
 |  346  | 
 |  347     if (value == 0) | 
 |  348       condition_reg_ |= CC_EQ; | 
 |  349     else | 
 |  350       condition_reg_ |= CC_LT; | 
 |  351   } | 
 |  352  | 
 |  353   void SetS390OverflowCode(bool isOF) { | 
 |  354     if (isOF) condition_reg_ = CC_OF; | 
 |  355   } | 
 |  356  | 
 |  357   bool TestConditionCode(Condition mask) { | 
 |  358     // Check for unconditional branch | 
 |  359     if (mask == 0xf) return true; | 
 |  360  | 
 |  361     return (condition_reg_ & mask) != 0; | 
 |  362   } | 
|  328  |  363  | 
|  329   // Executes one instruction. |  364   // Executes one instruction. | 
|  330   void ExecuteInstruction(Instruction* instr); |  365   void ExecuteInstruction(Instruction* instr, bool auto_incr_pc = true); | 
|  331  |  366  | 
|  332   // ICache. |  367   // ICache. | 
|  333   static void CheckICache(v8::internal::HashMap* i_cache, Instruction* instr); |  368   static void CheckICache(v8::internal::HashMap* i_cache, Instruction* instr); | 
|  334   static void FlushOnePage(v8::internal::HashMap* i_cache, intptr_t start, |  369   static void FlushOnePage(v8::internal::HashMap* i_cache, intptr_t start, | 
|  335                            int size); |  370                            int size); | 
|  336   static CachePage* GetCachePage(v8::internal::HashMap* i_cache, void* page); |  371   static CachePage* GetCachePage(v8::internal::HashMap* i_cache, void* page); | 
|  337  |  372  | 
|  338   // Runtime call support. |  373   // Runtime call support. | 
|  339   static void* RedirectExternalReference( |  374   static void* RedirectExternalReference( | 
|  340       Isolate* isolate, void* external_function, |  375       Isolate* isolate, void* external_function, | 
|  341       v8::internal::ExternalReference::Type type); |  376       v8::internal::ExternalReference::Type type); | 
|  342  |  377  | 
|  343   // Handle arguments and return value for runtime FP functions. |  378   // Handle arguments and return value for runtime FP functions. | 
|  344   void GetFpArgs(double* x, double* y, intptr_t* z); |  379   void GetFpArgs(double* x, double* y, intptr_t* z); | 
|  345   void SetFpResult(const double& result); |  380   void SetFpResult(const double& result); | 
|  346   void TrashCallerSaveRegisters(); |  381   void TrashCallerSaveRegisters(); | 
|  347  |  382  | 
|  348   void CallInternal(byte* entry); |  383   void CallInternal(byte* entry, int reg_arg_count = 3); | 
|  349  |  384  | 
|  350   // Architecture state. |  385   // Architecture state. | 
|  351   // Saturating instructions require a Q flag to indicate saturation. |  386   // On z9 and higher and supported Linux on z Systems platforms, all registers | 
|  352   // There is currently no way to read the CPSR directly, and thus read the Q |  387   // are 64-bit, even in 31-bit mode. | 
|  353   // flag, so this is left unimplemented. |  388   uint64_t registers_[kNumGPRs]; | 
|  354   intptr_t registers_[kNumGPRs]; |  389   int64_t fp_registers_[kNumFPRs]; | 
 |  390  | 
 |  391   // Condition Code register. In S390, the last 4 bits are used. | 
|  355   int32_t condition_reg_; |  392   int32_t condition_reg_; | 
|  356   int32_t fp_condition_reg_; |  393   // Special register to track PC. | 
|  357   intptr_t special_reg_lr_; |  | 
|  358   intptr_t special_reg_pc_; |  394   intptr_t special_reg_pc_; | 
|  359   intptr_t special_reg_ctr_; |  | 
|  360   int32_t special_reg_xer_; |  | 
|  361  |  | 
|  362   int64_t fp_registers_[kNumFPRs]; |  | 
|  363  |  395  | 
|  364   // Simulator support. |  396   // Simulator support. | 
|  365   char* stack_; |  397   char* stack_; | 
|  366   static const size_t stack_protection_size_ = 256 * kPointerSize; |  398   static const size_t stack_protection_size_ = 256 * kPointerSize; | 
|  367   bool pc_modified_; |  399   bool pc_modified_; | 
|  368   int icount_; |  400   int64_t icount_; | 
|  369  |  401  | 
|  370   // Debugger input. |  402   // Debugger input. | 
|  371   char* last_debugger_input_; |  403   char* last_debugger_input_; | 
|  372  |  404  | 
|  373   // Icache simulation |  405   // Icache simulation | 
|  374   v8::internal::HashMap* i_cache_; |  406   v8::internal::HashMap* i_cache_; | 
|  375  |  407  | 
|  376   // Registered breakpoints. |  408   // Registered breakpoints. | 
|  377   Instruction* break_pc_; |  409   Instruction* break_pc_; | 
|  378   Instr break_instr_; |  410   Instr break_instr_; | 
|  379  |  411  | 
|  380   v8::internal::Isolate* isolate_; |  412   v8::internal::Isolate* isolate_; | 
|  381  |  413  | 
|  382   // A stop is watched if its code is less than kNumOfWatchedStops. |  414   // A stop is watched if its code is less than kNumOfWatchedStops. | 
|  383   // Only watched stops support enabling/disabling and the counter feature. |  415   // Only watched stops support enabling/disabling and the counter feature. | 
|  384   static const uint32_t kNumOfWatchedStops = 256; |  416   static const uint32_t kNumOfWatchedStops = 256; | 
|  385  |  417  | 
|  386   // Breakpoint is disabled if bit 31 is set. |  418   // Breakpoint is disabled if bit 31 is set. | 
|  387   static const uint32_t kStopDisabledBit = 1 << 31; |  419   static const uint32_t kStopDisabledBit = 1 << 31; | 
|  388  |  420  | 
|  389   // A stop is enabled, meaning the simulator will stop when meeting the |  421   // A stop is enabled, meaning the simulator will stop when meeting the | 
|  390   // instruction, if bit 31 of watched_stops_[code].count is unset. |  422   // instruction, if bit 31 of watched_stops_[code].count is unset. | 
|  391   // The value watched_stops_[code].count & ~(1 << 31) indicates how many times |  423   // The value watched_stops_[code].count & ~(1 << 31) indicates how many times | 
|  392   // the breakpoint was hit or gone through. |  424   // the breakpoint was hit or gone through. | 
|  393   struct StopCountAndDesc { |  425   struct StopCountAndDesc { | 
|  394     uint32_t count; |  426     uint32_t count; | 
|  395     char* desc; |  427     char* desc; | 
|  396   }; |  428   }; | 
|  397   StopCountAndDesc watched_stops_[kNumOfWatchedStops]; |  429   StopCountAndDesc watched_stops_[kNumOfWatchedStops]; | 
 |  430   void DebugStart(); | 
|  398 }; |  431 }; | 
|  399  |  432  | 
|  400  |  | 
|  401 // When running with the simulator transition into simulated execution at this |  433 // When running with the simulator transition into simulated execution at this | 
|  402 // point. |  434 // point. | 
|  403 #define CALL_GENERATED_CODE(isolate, entry, p0, p1, p2, p3, p4)          \ |  435 #define CALL_GENERATED_CODE(isolate, entry, p0, p1, p2, p3, p4)          \ | 
|  404   reinterpret_cast<Object*>(Simulator::current(isolate)->Call(           \ |  436   reinterpret_cast<Object*>(Simulator::current(isolate)->Call(           \ | 
|  405       FUNCTION_ADDR(entry), 5, (intptr_t)p0, (intptr_t)p1, (intptr_t)p2, \ |  437       FUNCTION_ADDR(entry), 5, (intptr_t)p0, (intptr_t)p1, (intptr_t)p2, \ | 
|  406       (intptr_t)p3, (intptr_t)p4)) |  438       (intptr_t)p3, (intptr_t)p4)) | 
|  407  |  439  | 
|  408 #define CALL_GENERATED_REGEXP_CODE(isolate, entry, p0, p1, p2, p3, p4, p5, p6, \ |  440 #define CALL_GENERATED_REGEXP_CODE(isolate, entry, p0, p1, p2, p3, p4, p5, p6, \ | 
|  409                                    p7, p8)                                     \ |  441                                    p7, p8)                                     \ | 
|  410   Simulator::current(isolate)->Call(entry, 10, (intptr_t)p0, (intptr_t)p1,     \ |  442   Simulator::current(isolate)->Call(entry, 10, (intptr_t)p0, (intptr_t)p1,     \ | 
|  411                                     (intptr_t)p2, (intptr_t)p3, (intptr_t)p4,  \ |  443                                     (intptr_t)p2, (intptr_t)p3, (intptr_t)p4,  \ | 
|  412                                     (intptr_t)p5, (intptr_t)p6, (intptr_t)p7,  \ |  444                                     (intptr_t)p5, (intptr_t)p6, (intptr_t)p7,  \ | 
|  413                                     (intptr_t)NULL, (intptr_t)p8) |  445                                     (intptr_t)NULL, (intptr_t)p8) | 
|  414  |  446  | 
|  415  |  | 
|  416 // The simulator has its own stack. Thus it has a different stack limit from |  447 // The simulator has its own stack. Thus it has a different stack limit from | 
|  417 // the C-based native code.  The JS-based limit normally points near the end of |  448 // the C-based native code.  The JS-based limit normally points near the end of | 
|  418 // the simulator stack.  When the C-based limit is exhausted we reflect that by |  449 // the simulator stack.  When the C-based limit is exhausted we reflect that by | 
|  419 // lowering the JS-based limit as well, to make stack checks trigger. |  450 // lowering the JS-based limit as well, to make stack checks trigger. | 
|  420 class SimulatorStack : public v8::internal::AllStatic { |  451 class SimulatorStack : public v8::internal::AllStatic { | 
|  421  public: |  452  public: | 
|  422   static inline uintptr_t JsLimitFromCLimit(v8::internal::Isolate* isolate, |  453   static inline uintptr_t JsLimitFromCLimit(v8::internal::Isolate* isolate, | 
|  423                                             uintptr_t c_limit) { |  454                                             uintptr_t c_limit) { | 
|  424     return Simulator::current(isolate)->StackLimit(c_limit); |  455     return Simulator::current(isolate)->StackLimit(c_limit); | 
|  425   } |  456   } | 
|  426  |  457  | 
|  427   static inline uintptr_t RegisterCTryCatch(v8::internal::Isolate* isolate, |  458   static inline uintptr_t RegisterCTryCatch(v8::internal::Isolate* isolate, | 
|  428                                             uintptr_t try_catch_address) { |  459                                             uintptr_t try_catch_address) { | 
|  429     Simulator* sim = Simulator::current(isolate); |  460     Simulator* sim = Simulator::current(isolate); | 
|  430     return sim->PushAddress(try_catch_address); |  461     return sim->PushAddress(try_catch_address); | 
|  431   } |  462   } | 
|  432  |  463  | 
|  433   static inline void UnregisterCTryCatch(v8::internal::Isolate* isolate) { |  464   static inline void UnregisterCTryCatch(v8::internal::Isolate* isolate) { | 
|  434     Simulator::current(isolate)->PopAddress(); |  465     Simulator::current(isolate)->PopAddress(); | 
|  435   } |  466   } | 
|  436 }; |  467 }; | 
 |  468  | 
|  437 }  // namespace internal |  469 }  // namespace internal | 
|  438 }  // namespace v8 |  470 }  // namespace v8 | 
|  439  |  471  | 
|  440 #endif  // !defined(USE_SIMULATOR) |  472 #endif  // !defined(USE_SIMULATOR) | 
|  441 #endif  // V8_PPC_SIMULATOR_PPC_H_ |  473 #endif  // V8_S390_SIMULATOR_S390_H_ | 
| OLD | NEW |