| 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 |