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 |