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

changeset 0
6474c204b198
     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 */

mercurial