js/src/jit/arm/Simulator-arm.h

changeset 0
6474c204b198
equal deleted inserted replaced
-1:000000000000 0:95d275a44da5
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 // Copyright 2012 the V8 project authors. All rights reserved.
3 // Redistribution and use in source and binary forms, with or without
4 // modification, are permitted provided that the following conditions are
5 // met:
6 //
7 // * Redistributions of source code must retain the above copyright
8 // notice, this list of conditions and the following disclaimer.
9 // * Redistributions in binary form must reproduce the above
10 // copyright notice, this list of conditions and the following
11 // disclaimer in the documentation and/or other materials provided
12 // with the distribution.
13 // * Neither the name of Google Inc. nor the names of its
14 // contributors may be used to endorse or promote products derived
15 // from this software without specific prior written permission.
16 //
17 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
29 #ifndef jit_arm_Simulator_arm_h
30 #define jit_arm_Simulator_arm_h
31
32 #ifdef JS_ARM_SIMULATOR
33
34 #include "jit/arm/Architecture-arm.h"
35 #include "jit/IonTypes.h"
36
37 namespace js {
38 namespace jit {
39
40 class SimulatorRuntime;
41 SimulatorRuntime *CreateSimulatorRuntime();
42 void DestroySimulatorRuntime(SimulatorRuntime *srt);
43
44 // VFP rounding modes. See ARM DDI 0406B Page A2-29.
45 enum VFPRoundingMode {
46 SimRN = 0 << 22, // Round to Nearest.
47 SimRP = 1 << 22, // Round towards Plus Infinity.
48 SimRM = 2 << 22, // Round towards Minus Infinity.
49 SimRZ = 3 << 22, // Round towards zero.
50
51 // Aliases.
52 kRoundToNearest = SimRN,
53 kRoundToPlusInf = SimRP,
54 kRoundToMinusInf = SimRM,
55 kRoundToZero = SimRZ
56 };
57
58 const uint32_t kVFPRoundingModeMask = 3 << 22;
59
60 typedef int32_t Instr;
61 class SimInstruction;
62
63 class Simulator
64 {
65 friend class Redirection;
66
67 public:
68 friend class ArmDebugger;
69 enum Register {
70 no_reg = -1,
71 r0 = 0, r1, r2, r3, r4, r5, r6, r7,
72 r8, r9, r10, r11, r12, r13, r14, r15,
73 num_registers,
74 sp = 13,
75 lr = 14,
76 pc = 15,
77 s0 = 0, s1, s2, s3, s4, s5, s6, s7,
78 s8, s9, s10, s11, s12, s13, s14, s15,
79 s16, s17, s18, s19, s20, s21, s22, s23,
80 s24, s25, s26, s27, s28, s29, s30, s31,
81 num_s_registers = 32,
82 d0 = 0, d1, d2, d3, d4, d5, d6, d7,
83 d8, d9, d10, d11, d12, d13, d14, d15,
84 d16, d17, d18, d19, d20, d21, d22, d23,
85 d24, d25, d26, d27, d28, d29, d30, d31,
86 num_d_registers = 32,
87 q0 = 0, q1, q2, q3, q4, q5, q6, q7,
88 q8, q9, q10, q11, q12, q13, q14, q15,
89 num_q_registers = 16
90 };
91
92 explicit Simulator(SimulatorRuntime *srt);
93 ~Simulator();
94
95 // The currently executing Simulator instance. Potentially there can be one
96 // for each native thread.
97 static Simulator *Current();
98
99 static inline uintptr_t StackLimit() {
100 return Simulator::Current()->stackLimit();
101 }
102
103 // Accessors for register state. Reading the pc value adheres to the ARM
104 // architecture specification and is off by a 8 from the currently executing
105 // instruction.
106 void set_register(int reg, int32_t value);
107 int32_t get_register(int reg) const;
108 double get_double_from_register_pair(int reg);
109 void set_register_pair_from_double(int reg, double* value);
110 void set_dw_register(int dreg, const int* dbl);
111
112 // Support for VFP.
113 void get_d_register(int dreg, uint64_t* value);
114 void set_d_register(int dreg, const uint64_t* value);
115 void get_d_register(int dreg, uint32_t* value);
116 void set_d_register(int dreg, const uint32_t* value);
117 void get_q_register(int qreg, uint64_t* value);
118 void set_q_register(int qreg, const uint64_t* value);
119 void get_q_register(int qreg, uint32_t* value);
120 void set_q_register(int qreg, const uint32_t* value);
121 void set_s_register(int reg, unsigned int value);
122 unsigned int get_s_register(int reg) const;
123
124 void set_d_register_from_double(int dreg, const double& dbl) {
125 setVFPRegister<double, 2>(dreg, dbl);
126 }
127 double get_double_from_d_register(int dreg) {
128 return getFromVFPRegister<double, 2>(dreg);
129 }
130 void set_s_register_from_float(int sreg, const float flt) {
131 setVFPRegister<float, 1>(sreg, flt);
132 }
133 float get_float_from_s_register(int sreg) {
134 return getFromVFPRegister<float, 1>(sreg);
135 }
136 void set_s_register_from_sinteger(int sreg, const int sint) {
137 setVFPRegister<int, 1>(sreg, sint);
138 }
139 int get_sinteger_from_s_register(int sreg) {
140 return getFromVFPRegister<int, 1>(sreg);
141 }
142
143 // Special case of set_register and get_register to access the raw PC value.
144 void set_pc(int32_t value);
145 int32_t get_pc() const;
146
147 void set_resume_pc(int32_t value) {
148 resume_pc_ = value;
149 }
150
151 uintptr_t stackLimit() const;
152 bool overRecursed(uintptr_t newsp = 0) const;
153 bool overRecursedWithExtra(uint32_t extra) const;
154
155 // Executes ARM instructions until the PC reaches end_sim_pc.
156 template<bool EnableStopSimAt>
157 void execute();
158
159 // Sets up the simulator state and grabs the result on return.
160 int64_t call(uint8_t* entry, int argument_count, ...);
161
162 // Debugger input.
163 void setLastDebuggerInput(char *input);
164 char *lastDebuggerInput() { return lastDebuggerInput_; }
165
166 // Returns true if pc register contains one of the 'special_values' defined
167 // below (bad_lr, end_sim_pc).
168 bool has_bad_pc() const;
169
170 private:
171 enum special_values {
172 // Known bad pc value to ensure that the simulator does not execute
173 // without being properly setup.
174 bad_lr = -1,
175 // A pc value used to signal the simulator to stop execution. Generally
176 // the lr is set to this value on transition from native C code to
177 // simulated execution, so that the simulator can "return" to the native
178 // C code.
179 end_sim_pc = -2
180 };
181
182 // Checks if the current instruction should be executed based on its
183 // condition bits.
184 inline bool conditionallyExecute(SimInstruction* instr);
185
186 // Helper functions to set the conditional flags in the architecture state.
187 void setNZFlags(int32_t val);
188 void setCFlag(bool val);
189 void setVFlag(bool val);
190 bool carryFrom(int32_t left, int32_t right, int32_t carry = 0);
191 bool borrowFrom(int32_t left, int32_t right);
192 bool overflowFrom(int32_t alu_out, int32_t left, int32_t right, bool addition);
193
194 inline int getCarry() { return c_flag_ ? 1 : 0; };
195
196 // Support for VFP.
197 void compute_FPSCR_Flags(double val1, double val2);
198 void copy_FPSCR_to_APSR();
199 inline double canonicalizeNaN(double value);
200
201 // Helper functions to decode common "addressing" modes
202 int32_t getShiftRm(SimInstruction *instr, bool* carry_out);
203 int32_t getImm(SimInstruction *instr, bool* carry_out);
204 int32_t processPU(SimInstruction *instr, int num_regs, int operand_size,
205 intptr_t *start_address, intptr_t *end_address);
206 void handleRList(SimInstruction *instr, bool load);
207 void handleVList(SimInstruction *inst);
208 void softwareInterrupt(SimInstruction *instr);
209
210 // Stop helper functions.
211 inline bool isStopInstruction(SimInstruction *instr);
212 inline bool isWatchedStop(uint32_t bkpt_code);
213 inline bool isEnabledStop(uint32_t bkpt_code);
214 inline void enableStop(uint32_t bkpt_code);
215 inline void disableStop(uint32_t bkpt_code);
216 inline void increaseStopCounter(uint32_t bkpt_code);
217 void printStopInfo(uint32_t code);
218
219 // Read and write memory.
220 inline uint8_t readBU(int32_t addr);
221 inline int8_t readB(int32_t addr);
222 inline void writeB(int32_t addr, uint8_t value);
223 inline void writeB(int32_t addr, int8_t value);
224
225 inline uint16_t readHU(int32_t addr, SimInstruction *instr);
226 inline int16_t readH(int32_t addr, SimInstruction *instr);
227 // Note: Overloaded on the sign of the value.
228 inline void writeH(int32_t addr, uint16_t value, SimInstruction *instr);
229 inline void writeH(int32_t addr, int16_t value, SimInstruction *instr);
230
231 inline int readW(int32_t addr, SimInstruction *instr);
232 inline void writeW(int32_t addr, int value, SimInstruction *instr);
233
234 int32_t *readDW(int32_t addr);
235 void writeDW(int32_t addr, int32_t value1, int32_t value2);
236
237 // Executing is handled based on the instruction type.
238 // Both type 0 and type 1 rolled into one.
239 void decodeType01(SimInstruction *instr);
240 void decodeType2(SimInstruction *instr);
241 void decodeType3(SimInstruction *instr);
242 void decodeType4(SimInstruction *instr);
243 void decodeType5(SimInstruction *instr);
244 void decodeType6(SimInstruction *instr);
245 void decodeType7(SimInstruction *instr);
246
247 // Support for VFP.
248 void decodeTypeVFP(SimInstruction *instr);
249 void decodeType6CoprocessorIns(SimInstruction *instr);
250 void decodeSpecialCondition(SimInstruction *instr);
251
252 void decodeVMOVBetweenCoreAndSinglePrecisionRegisters(SimInstruction *instr);
253 void decodeVCMP(SimInstruction *instr);
254 void decodeVCVTBetweenDoubleAndSingle(SimInstruction *instr);
255 void decodeVCVTBetweenFloatingPointAndInteger(SimInstruction *instr);
256 void decodeVCVTBetweenFloatingPointAndIntegerFrac(SimInstruction *instr);
257
258 // Executes one instruction.
259 void instructionDecode(SimInstruction *instr);
260
261 public:
262 static bool ICacheCheckingEnabled;
263 static void FlushICache(void *start, size_t size);
264
265 static int64_t StopSimAt;
266
267 // Runtime call support.
268 static void *RedirectNativeFunction(void *nativeFunction, ABIFunctionType type);
269
270 private:
271 // Handle arguments and return value for runtime FP functions.
272 void getFpArgs(double *x, double *y, int32_t *z);
273 void setCallResultDouble(double result);
274 void setCallResultFloat(float result);
275 void setCallResult(int64_t res);
276 void scratchVolatileRegisters(bool scratchFloat = true);
277
278 template<class ReturnType, int register_size>
279 ReturnType getFromVFPRegister(int reg_index);
280
281 template<class InputType, int register_size>
282 void setVFPRegister(int reg_index, const InputType& value);
283
284 void callInternal(uint8_t* entry);
285
286 // Architecture state.
287 // Saturating instructions require a Q flag to indicate saturation.
288 // There is currently no way to read the CPSR directly, and thus read the Q
289 // flag, so this is left unimplemented.
290 int32_t registers_[16];
291 bool n_flag_;
292 bool z_flag_;
293 bool c_flag_;
294 bool v_flag_;
295
296 // VFP architecture state.
297 uint32_t vfp_registers_[num_d_registers * 2];
298 bool n_flag_FPSCR_;
299 bool z_flag_FPSCR_;
300 bool c_flag_FPSCR_;
301 bool v_flag_FPSCR_;
302
303 // VFP rounding mode. See ARM DDI 0406B Page A2-29.
304 VFPRoundingMode FPSCR_rounding_mode_;
305 bool FPSCR_default_NaN_mode_;
306
307 // VFP FP exception flags architecture state.
308 bool inv_op_vfp_flag_;
309 bool div_zero_vfp_flag_;
310 bool overflow_vfp_flag_;
311 bool underflow_vfp_flag_;
312 bool inexact_vfp_flag_;
313
314 // Simulator support.
315 char *stack_;
316 bool pc_modified_;
317 int64_t icount_;
318
319 int32_t resume_pc_;
320
321 // Debugger input.
322 char *lastDebuggerInput_;
323
324 // Registered breakpoints.
325 SimInstruction *break_pc_;
326 Instr break_instr_;
327
328 SimulatorRuntime *srt_;
329
330 // A stop is watched if its code is less than kNumOfWatchedStops.
331 // Only watched stops support enabling/disabling and the counter feature.
332 static const uint32_t kNumOfWatchedStops = 256;
333
334 // Breakpoint is disabled if bit 31 is set.
335 static const uint32_t kStopDisabledBit = 1 << 31;
336
337 // A stop is enabled, meaning the simulator will stop when meeting the
338 // instruction, if bit 31 of watched_stops_[code].count is unset.
339 // The value watched_stops_[code].count & ~(1 << 31) indicates how many times
340 // the breakpoint was hit or gone through.
341 struct StopCountAndDesc {
342 uint32_t count;
343 char *desc;
344 };
345 StopCountAndDesc watched_stops_[kNumOfWatchedStops];
346
347 public:
348 int64_t icount() {
349 return icount_;
350 }
351
352 };
353
354 #define JS_CHECK_SIMULATOR_RECURSION_WITH_EXTRA(cx, extra, onerror) \
355 JS_BEGIN_MACRO \
356 if (cx->mainThread().simulator()->overRecursedWithExtra(extra)) { \
357 js_ReportOverRecursed(cx); \
358 onerror; \
359 } \
360 JS_END_MACRO
361
362 } // namespace jit
363 } // namespace js
364
365 #endif /* JS_ARM_SIMULATOR */
366
367 #endif /* jit_arm_Simulator_arm_h */

mercurial