1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/js/src/jit/arm/Simulator-arm.h Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,367 @@ 1.4 +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ 1.5 +// Copyright 2012 the V8 project authors. All rights reserved. 1.6 +// Redistribution and use in source and binary forms, with or without 1.7 +// modification, are permitted provided that the following conditions are 1.8 +// met: 1.9 +// 1.10 +// * Redistributions of source code must retain the above copyright 1.11 +// notice, this list of conditions and the following disclaimer. 1.12 +// * Redistributions in binary form must reproduce the above 1.13 +// copyright notice, this list of conditions and the following 1.14 +// disclaimer in the documentation and/or other materials provided 1.15 +// with the distribution. 1.16 +// * Neither the name of Google Inc. nor the names of its 1.17 +// contributors may be used to endorse or promote products derived 1.18 +// from this software without specific prior written permission. 1.19 +// 1.20 +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 1.21 +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 1.22 +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 1.23 +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 1.24 +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 1.25 +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 1.26 +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 1.27 +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 1.28 +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 1.29 +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 1.30 +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 1.31 + 1.32 +#ifndef jit_arm_Simulator_arm_h 1.33 +#define jit_arm_Simulator_arm_h 1.34 + 1.35 +#ifdef JS_ARM_SIMULATOR 1.36 + 1.37 +#include "jit/arm/Architecture-arm.h" 1.38 +#include "jit/IonTypes.h" 1.39 + 1.40 +namespace js { 1.41 +namespace jit { 1.42 + 1.43 +class SimulatorRuntime; 1.44 +SimulatorRuntime *CreateSimulatorRuntime(); 1.45 +void DestroySimulatorRuntime(SimulatorRuntime *srt); 1.46 + 1.47 +// VFP rounding modes. See ARM DDI 0406B Page A2-29. 1.48 +enum VFPRoundingMode { 1.49 + SimRN = 0 << 22, // Round to Nearest. 1.50 + SimRP = 1 << 22, // Round towards Plus Infinity. 1.51 + SimRM = 2 << 22, // Round towards Minus Infinity. 1.52 + SimRZ = 3 << 22, // Round towards zero. 1.53 + 1.54 + // Aliases. 1.55 + kRoundToNearest = SimRN, 1.56 + kRoundToPlusInf = SimRP, 1.57 + kRoundToMinusInf = SimRM, 1.58 + kRoundToZero = SimRZ 1.59 +}; 1.60 + 1.61 +const uint32_t kVFPRoundingModeMask = 3 << 22; 1.62 + 1.63 +typedef int32_t Instr; 1.64 +class SimInstruction; 1.65 + 1.66 +class Simulator 1.67 +{ 1.68 + friend class Redirection; 1.69 + 1.70 + public: 1.71 + friend class ArmDebugger; 1.72 + enum Register { 1.73 + no_reg = -1, 1.74 + r0 = 0, r1, r2, r3, r4, r5, r6, r7, 1.75 + r8, r9, r10, r11, r12, r13, r14, r15, 1.76 + num_registers, 1.77 + sp = 13, 1.78 + lr = 14, 1.79 + pc = 15, 1.80 + s0 = 0, s1, s2, s3, s4, s5, s6, s7, 1.81 + s8, s9, s10, s11, s12, s13, s14, s15, 1.82 + s16, s17, s18, s19, s20, s21, s22, s23, 1.83 + s24, s25, s26, s27, s28, s29, s30, s31, 1.84 + num_s_registers = 32, 1.85 + d0 = 0, d1, d2, d3, d4, d5, d6, d7, 1.86 + d8, d9, d10, d11, d12, d13, d14, d15, 1.87 + d16, d17, d18, d19, d20, d21, d22, d23, 1.88 + d24, d25, d26, d27, d28, d29, d30, d31, 1.89 + num_d_registers = 32, 1.90 + q0 = 0, q1, q2, q3, q4, q5, q6, q7, 1.91 + q8, q9, q10, q11, q12, q13, q14, q15, 1.92 + num_q_registers = 16 1.93 + }; 1.94 + 1.95 + explicit Simulator(SimulatorRuntime *srt); 1.96 + ~Simulator(); 1.97 + 1.98 + // The currently executing Simulator instance. Potentially there can be one 1.99 + // for each native thread. 1.100 + static Simulator *Current(); 1.101 + 1.102 + static inline uintptr_t StackLimit() { 1.103 + return Simulator::Current()->stackLimit(); 1.104 + } 1.105 + 1.106 + // Accessors for register state. Reading the pc value adheres to the ARM 1.107 + // architecture specification and is off by a 8 from the currently executing 1.108 + // instruction. 1.109 + void set_register(int reg, int32_t value); 1.110 + int32_t get_register(int reg) const; 1.111 + double get_double_from_register_pair(int reg); 1.112 + void set_register_pair_from_double(int reg, double* value); 1.113 + void set_dw_register(int dreg, const int* dbl); 1.114 + 1.115 + // Support for VFP. 1.116 + void get_d_register(int dreg, uint64_t* value); 1.117 + void set_d_register(int dreg, const uint64_t* value); 1.118 + void get_d_register(int dreg, uint32_t* value); 1.119 + void set_d_register(int dreg, const uint32_t* value); 1.120 + void get_q_register(int qreg, uint64_t* value); 1.121 + void set_q_register(int qreg, const uint64_t* value); 1.122 + void get_q_register(int qreg, uint32_t* value); 1.123 + void set_q_register(int qreg, const uint32_t* value); 1.124 + void set_s_register(int reg, unsigned int value); 1.125 + unsigned int get_s_register(int reg) const; 1.126 + 1.127 + void set_d_register_from_double(int dreg, const double& dbl) { 1.128 + setVFPRegister<double, 2>(dreg, dbl); 1.129 + } 1.130 + double get_double_from_d_register(int dreg) { 1.131 + return getFromVFPRegister<double, 2>(dreg); 1.132 + } 1.133 + void set_s_register_from_float(int sreg, const float flt) { 1.134 + setVFPRegister<float, 1>(sreg, flt); 1.135 + } 1.136 + float get_float_from_s_register(int sreg) { 1.137 + return getFromVFPRegister<float, 1>(sreg); 1.138 + } 1.139 + void set_s_register_from_sinteger(int sreg, const int sint) { 1.140 + setVFPRegister<int, 1>(sreg, sint); 1.141 + } 1.142 + int get_sinteger_from_s_register(int sreg) { 1.143 + return getFromVFPRegister<int, 1>(sreg); 1.144 + } 1.145 + 1.146 + // Special case of set_register and get_register to access the raw PC value. 1.147 + void set_pc(int32_t value); 1.148 + int32_t get_pc() const; 1.149 + 1.150 + void set_resume_pc(int32_t value) { 1.151 + resume_pc_ = value; 1.152 + } 1.153 + 1.154 + uintptr_t stackLimit() const; 1.155 + bool overRecursed(uintptr_t newsp = 0) const; 1.156 + bool overRecursedWithExtra(uint32_t extra) const; 1.157 + 1.158 + // Executes ARM instructions until the PC reaches end_sim_pc. 1.159 + template<bool EnableStopSimAt> 1.160 + void execute(); 1.161 + 1.162 + // Sets up the simulator state and grabs the result on return. 1.163 + int64_t call(uint8_t* entry, int argument_count, ...); 1.164 + 1.165 + // Debugger input. 1.166 + void setLastDebuggerInput(char *input); 1.167 + char *lastDebuggerInput() { return lastDebuggerInput_; } 1.168 + 1.169 + // Returns true if pc register contains one of the 'special_values' defined 1.170 + // below (bad_lr, end_sim_pc). 1.171 + bool has_bad_pc() const; 1.172 + 1.173 + private: 1.174 + enum special_values { 1.175 + // Known bad pc value to ensure that the simulator does not execute 1.176 + // without being properly setup. 1.177 + bad_lr = -1, 1.178 + // A pc value used to signal the simulator to stop execution. Generally 1.179 + // the lr is set to this value on transition from native C code to 1.180 + // simulated execution, so that the simulator can "return" to the native 1.181 + // C code. 1.182 + end_sim_pc = -2 1.183 + }; 1.184 + 1.185 + // Checks if the current instruction should be executed based on its 1.186 + // condition bits. 1.187 + inline bool conditionallyExecute(SimInstruction* instr); 1.188 + 1.189 + // Helper functions to set the conditional flags in the architecture state. 1.190 + void setNZFlags(int32_t val); 1.191 + void setCFlag(bool val); 1.192 + void setVFlag(bool val); 1.193 + bool carryFrom(int32_t left, int32_t right, int32_t carry = 0); 1.194 + bool borrowFrom(int32_t left, int32_t right); 1.195 + bool overflowFrom(int32_t alu_out, int32_t left, int32_t right, bool addition); 1.196 + 1.197 + inline int getCarry() { return c_flag_ ? 1 : 0; }; 1.198 + 1.199 + // Support for VFP. 1.200 + void compute_FPSCR_Flags(double val1, double val2); 1.201 + void copy_FPSCR_to_APSR(); 1.202 + inline double canonicalizeNaN(double value); 1.203 + 1.204 + // Helper functions to decode common "addressing" modes 1.205 + int32_t getShiftRm(SimInstruction *instr, bool* carry_out); 1.206 + int32_t getImm(SimInstruction *instr, bool* carry_out); 1.207 + int32_t processPU(SimInstruction *instr, int num_regs, int operand_size, 1.208 + intptr_t *start_address, intptr_t *end_address); 1.209 + void handleRList(SimInstruction *instr, bool load); 1.210 + void handleVList(SimInstruction *inst); 1.211 + void softwareInterrupt(SimInstruction *instr); 1.212 + 1.213 + // Stop helper functions. 1.214 + inline bool isStopInstruction(SimInstruction *instr); 1.215 + inline bool isWatchedStop(uint32_t bkpt_code); 1.216 + inline bool isEnabledStop(uint32_t bkpt_code); 1.217 + inline void enableStop(uint32_t bkpt_code); 1.218 + inline void disableStop(uint32_t bkpt_code); 1.219 + inline void increaseStopCounter(uint32_t bkpt_code); 1.220 + void printStopInfo(uint32_t code); 1.221 + 1.222 + // Read and write memory. 1.223 + inline uint8_t readBU(int32_t addr); 1.224 + inline int8_t readB(int32_t addr); 1.225 + inline void writeB(int32_t addr, uint8_t value); 1.226 + inline void writeB(int32_t addr, int8_t value); 1.227 + 1.228 + inline uint16_t readHU(int32_t addr, SimInstruction *instr); 1.229 + inline int16_t readH(int32_t addr, SimInstruction *instr); 1.230 + // Note: Overloaded on the sign of the value. 1.231 + inline void writeH(int32_t addr, uint16_t value, SimInstruction *instr); 1.232 + inline void writeH(int32_t addr, int16_t value, SimInstruction *instr); 1.233 + 1.234 + inline int readW(int32_t addr, SimInstruction *instr); 1.235 + inline void writeW(int32_t addr, int value, SimInstruction *instr); 1.236 + 1.237 + int32_t *readDW(int32_t addr); 1.238 + void writeDW(int32_t addr, int32_t value1, int32_t value2); 1.239 + 1.240 + // Executing is handled based on the instruction type. 1.241 + // Both type 0 and type 1 rolled into one. 1.242 + void decodeType01(SimInstruction *instr); 1.243 + void decodeType2(SimInstruction *instr); 1.244 + void decodeType3(SimInstruction *instr); 1.245 + void decodeType4(SimInstruction *instr); 1.246 + void decodeType5(SimInstruction *instr); 1.247 + void decodeType6(SimInstruction *instr); 1.248 + void decodeType7(SimInstruction *instr); 1.249 + 1.250 + // Support for VFP. 1.251 + void decodeTypeVFP(SimInstruction *instr); 1.252 + void decodeType6CoprocessorIns(SimInstruction *instr); 1.253 + void decodeSpecialCondition(SimInstruction *instr); 1.254 + 1.255 + void decodeVMOVBetweenCoreAndSinglePrecisionRegisters(SimInstruction *instr); 1.256 + void decodeVCMP(SimInstruction *instr); 1.257 + void decodeVCVTBetweenDoubleAndSingle(SimInstruction *instr); 1.258 + void decodeVCVTBetweenFloatingPointAndInteger(SimInstruction *instr); 1.259 + void decodeVCVTBetweenFloatingPointAndIntegerFrac(SimInstruction *instr); 1.260 + 1.261 + // Executes one instruction. 1.262 + void instructionDecode(SimInstruction *instr); 1.263 + 1.264 + public: 1.265 + static bool ICacheCheckingEnabled; 1.266 + static void FlushICache(void *start, size_t size); 1.267 + 1.268 + static int64_t StopSimAt; 1.269 + 1.270 + // Runtime call support. 1.271 + static void *RedirectNativeFunction(void *nativeFunction, ABIFunctionType type); 1.272 + 1.273 + private: 1.274 + // Handle arguments and return value for runtime FP functions. 1.275 + void getFpArgs(double *x, double *y, int32_t *z); 1.276 + void setCallResultDouble(double result); 1.277 + void setCallResultFloat(float result); 1.278 + void setCallResult(int64_t res); 1.279 + void scratchVolatileRegisters(bool scratchFloat = true); 1.280 + 1.281 + template<class ReturnType, int register_size> 1.282 + ReturnType getFromVFPRegister(int reg_index); 1.283 + 1.284 + template<class InputType, int register_size> 1.285 + void setVFPRegister(int reg_index, const InputType& value); 1.286 + 1.287 + void callInternal(uint8_t* entry); 1.288 + 1.289 + // Architecture state. 1.290 + // Saturating instructions require a Q flag to indicate saturation. 1.291 + // There is currently no way to read the CPSR directly, and thus read the Q 1.292 + // flag, so this is left unimplemented. 1.293 + int32_t registers_[16]; 1.294 + bool n_flag_; 1.295 + bool z_flag_; 1.296 + bool c_flag_; 1.297 + bool v_flag_; 1.298 + 1.299 + // VFP architecture state. 1.300 + uint32_t vfp_registers_[num_d_registers * 2]; 1.301 + bool n_flag_FPSCR_; 1.302 + bool z_flag_FPSCR_; 1.303 + bool c_flag_FPSCR_; 1.304 + bool v_flag_FPSCR_; 1.305 + 1.306 + // VFP rounding mode. See ARM DDI 0406B Page A2-29. 1.307 + VFPRoundingMode FPSCR_rounding_mode_; 1.308 + bool FPSCR_default_NaN_mode_; 1.309 + 1.310 + // VFP FP exception flags architecture state. 1.311 + bool inv_op_vfp_flag_; 1.312 + bool div_zero_vfp_flag_; 1.313 + bool overflow_vfp_flag_; 1.314 + bool underflow_vfp_flag_; 1.315 + bool inexact_vfp_flag_; 1.316 + 1.317 + // Simulator support. 1.318 + char *stack_; 1.319 + bool pc_modified_; 1.320 + int64_t icount_; 1.321 + 1.322 + int32_t resume_pc_; 1.323 + 1.324 + // Debugger input. 1.325 + char *lastDebuggerInput_; 1.326 + 1.327 + // Registered breakpoints. 1.328 + SimInstruction *break_pc_; 1.329 + Instr break_instr_; 1.330 + 1.331 + SimulatorRuntime *srt_; 1.332 + 1.333 + // A stop is watched if its code is less than kNumOfWatchedStops. 1.334 + // Only watched stops support enabling/disabling and the counter feature. 1.335 + static const uint32_t kNumOfWatchedStops = 256; 1.336 + 1.337 + // Breakpoint is disabled if bit 31 is set. 1.338 + static const uint32_t kStopDisabledBit = 1 << 31; 1.339 + 1.340 + // A stop is enabled, meaning the simulator will stop when meeting the 1.341 + // instruction, if bit 31 of watched_stops_[code].count is unset. 1.342 + // The value watched_stops_[code].count & ~(1 << 31) indicates how many times 1.343 + // the breakpoint was hit or gone through. 1.344 + struct StopCountAndDesc { 1.345 + uint32_t count; 1.346 + char *desc; 1.347 + }; 1.348 + StopCountAndDesc watched_stops_[kNumOfWatchedStops]; 1.349 + 1.350 + public: 1.351 + int64_t icount() { 1.352 + return icount_; 1.353 + } 1.354 + 1.355 +}; 1.356 + 1.357 +#define JS_CHECK_SIMULATOR_RECURSION_WITH_EXTRA(cx, extra, onerror) \ 1.358 + JS_BEGIN_MACRO \ 1.359 + if (cx->mainThread().simulator()->overRecursedWithExtra(extra)) { \ 1.360 + js_ReportOverRecursed(cx); \ 1.361 + onerror; \ 1.362 + } \ 1.363 + JS_END_MACRO 1.364 + 1.365 +} // namespace jit 1.366 +} // namespace js 1.367 + 1.368 +#endif /* JS_ARM_SIMULATOR */ 1.369 + 1.370 +#endif /* jit_arm_Simulator_arm_h */