⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 translate.c

📁 qemu虚拟机代码
💻 C
📖 第 1 页 / 共 5 页
字号:
#undef VFP_OPstatic inline void gen_vfp_ld(DisasContext *s, int dp){    if (dp)        gen_ldst(vfp_ldd, s);    else        gen_ldst(vfp_lds, s);}static inline void gen_vfp_st(DisasContext *s, int dp){    if (dp)        gen_ldst(vfp_std, s);    else        gen_ldst(vfp_sts, s);}static inline longvfp_reg_offset (int dp, int reg){    if (dp)        return offsetof(CPUARMState, vfp.regs[reg]);    else if (reg & 1) {        return offsetof(CPUARMState, vfp.regs[reg >> 1])          + offsetof(CPU_DoubleU, l.upper);    } else {        return offsetof(CPUARMState, vfp.regs[reg >> 1])          + offsetof(CPU_DoubleU, l.lower);    }}static inline void gen_mov_F0_vreg(int dp, int reg){    if (dp)        gen_op_vfp_getreg_F0d(vfp_reg_offset(dp, reg));    else        gen_op_vfp_getreg_F0s(vfp_reg_offset(dp, reg));}static inline void gen_mov_F1_vreg(int dp, int reg){    if (dp)        gen_op_vfp_getreg_F1d(vfp_reg_offset(dp, reg));    else        gen_op_vfp_getreg_F1s(vfp_reg_offset(dp, reg));}static inline void gen_mov_vreg_F0(int dp, int reg){    if (dp)        gen_op_vfp_setreg_F0d(vfp_reg_offset(dp, reg));    else        gen_op_vfp_setreg_F0s(vfp_reg_offset(dp, reg));}/* Disassemble system coprocessor (cp15) instruction.  Return nonzero if   instruction is not defined.  */static int disas_cp15_insn(DisasContext *s, uint32_t insn){    uint32_t rd;    /* ??? Some cp15 registers are accessible from userspace.  */    if (IS_USER(s)) {        return 1;    }    if ((insn & 0x0fff0fff) == 0x0e070f90        || (insn & 0x0fff0fff) == 0x0e070f58) {        /* Wait for interrupt.  */        gen_op_movl_T0_im((long)s->pc);        gen_op_movl_reg_TN[0][15]();        gen_op_wfi();        s->is_jmp = DISAS_JUMP;        return 0;    }    rd = (insn >> 12) & 0xf;    if (insn & (1 << 20)) {        gen_op_movl_T0_cp15(insn);        /* If the destination register is r15 then sets condition codes.  */        if (rd != 15)            gen_movl_reg_T0(s, rd);    } else {        gen_movl_T0_reg(s, rd);        gen_op_movl_cp15_T0(insn);    }    gen_lookup_tb(s);    return 0;}/* Disassemble a VFP instruction.  Returns nonzero if an error occured   (ie. an undefined instruction).  */static int disas_vfp_insn(CPUState * env, DisasContext *s, uint32_t insn){    uint32_t rd, rn, rm, op, i, n, offset, delta_d, delta_m, bank_mask;    int dp, veclen;    if (!arm_feature(env, ARM_FEATURE_VFP))        return 1;    if ((env->vfp.xregs[ARM_VFP_FPEXC] & (1 << 30)) == 0) {        /* VFP disabled.  Only allow fmxr/fmrx to/from fpexc and fpsid.  */        if ((insn & 0x0fe00fff) != 0x0ee00a10)            return 1;        rn = (insn >> 16) & 0xf;        if (rn != 0 && rn != 8)            return 1;    }    dp = ((insn & 0xf00) == 0xb00);    switch ((insn >> 24) & 0xf) {    case 0xe:        if (insn & (1 << 4)) {            /* single register transfer */            if ((insn & 0x6f) != 0x00)                return 1;            rd = (insn >> 12) & 0xf;            if (dp) {                if (insn & 0x80)                    return 1;                rn = (insn >> 16) & 0xf;                /* Get the existing value even for arm->vfp moves because                   we only set half the register.  */                gen_mov_F0_vreg(1, rn);                gen_op_vfp_mrrd();                if (insn & (1 << 20)) {                    /* vfp->arm */                    if (insn & (1 << 21))                        gen_movl_reg_T1(s, rd);                    else                        gen_movl_reg_T0(s, rd);                } else {                    /* arm->vfp */                    if (insn & (1 << 21))                        gen_movl_T1_reg(s, rd);                    else                        gen_movl_T0_reg(s, rd);                    gen_op_vfp_mdrr();                    gen_mov_vreg_F0(dp, rn);                }            } else {                rn = ((insn >> 15) & 0x1e) | ((insn >> 7) & 1);                if (insn & (1 << 20)) {                    /* vfp->arm */                    if (insn & (1 << 21)) {                        /* system register */                        rn >>= 1;                        switch (rn) {                        case ARM_VFP_FPSID:                        case ARM_VFP_FPEXC:                        case ARM_VFP_FPINST:                        case ARM_VFP_FPINST2:                            gen_op_vfp_movl_T0_xreg(rn);                            break;                        case ARM_VFP_FPSCR:			    if (rd == 15)				gen_op_vfp_movl_T0_fpscr_flags();			    else				gen_op_vfp_movl_T0_fpscr();                            break;                        default:                            return 1;                        }                    } else {                        gen_mov_F0_vreg(0, rn);                        gen_op_vfp_mrs();                    }                    if (rd == 15) {                        /* Set the 4 flag bits in the CPSR.  */                        gen_op_movl_cpsr_T0(0xf0000000);                    } else                        gen_movl_reg_T0(s, rd);                } else {                    /* arm->vfp */                    gen_movl_T0_reg(s, rd);                    if (insn & (1 << 21)) {                        rn >>= 1;                        /* system register */                        switch (rn) {                        case ARM_VFP_FPSID:                            /* Writes are ignored.  */                            break;                        case ARM_VFP_FPSCR:                            gen_op_vfp_movl_fpscr_T0();                            gen_lookup_tb(s);                            break;                        case ARM_VFP_FPEXC:                            gen_op_vfp_movl_xreg_T0(rn);                            gen_lookup_tb(s);                            break;                        case ARM_VFP_FPINST:                        case ARM_VFP_FPINST2:                            gen_op_vfp_movl_xreg_T0(rn);                            break;                        default:                            return 1;                        }                    } else {                        gen_op_vfp_msr();                        gen_mov_vreg_F0(0, rn);                    }                }            }        } else {            /* data processing */            /* The opcode is in bits 23, 21, 20 and 6.  */            op = ((insn >> 20) & 8) | ((insn >> 19) & 6) | ((insn >> 6) & 1);            if (dp) {                if (op == 15) {                    /* rn is opcode */                    rn = ((insn >> 15) & 0x1e) | ((insn >> 7) & 1);                } else {                    /* rn is register number */                    if (insn & (1 << 7))                        return 1;                    rn = (insn >> 16) & 0xf;                }                if (op == 15 && (rn == 15 || rn > 17)) {                    /* Integer or single precision destination.  */                    rd = ((insn >> 11) & 0x1e) | ((insn >> 22) & 1);                } else {                    if (insn & (1 << 22))                        return 1;                    rd = (insn >> 12) & 0xf;                }                if (op == 15 && (rn == 16 || rn == 17)) {                    /* Integer source.  */                    rm = ((insn << 1) & 0x1e) | ((insn >> 5) & 1);                } else {                    if (insn & (1 << 5))                        return 1;                    rm = insn & 0xf;                }            } else {                rn = ((insn >> 15) & 0x1e) | ((insn >> 7) & 1);                if (op == 15 && rn == 15) {                    /* Double precision destination.  */                    if (insn & (1 << 22))                        return 1;                    rd = (insn >> 12) & 0xf;                } else                    rd = ((insn >> 11) & 0x1e) | ((insn >> 22) & 1);                rm = ((insn << 1) & 0x1e) | ((insn >> 5) & 1);            }            veclen = env->vfp.vec_len;            if (op == 15 && rn > 3)                veclen = 0;            /* Shut up compiler warnings.  */            delta_m = 0;            delta_d = 0;            bank_mask = 0;                        if (veclen > 0) {                if (dp)                    bank_mask = 0xc;                else                    bank_mask = 0x18;                /* Figure out what type of vector operation this is.  */                if ((rd & bank_mask) == 0) {                    /* scalar */                    veclen = 0;                } else {                    if (dp)                        delta_d = (env->vfp.vec_stride >> 1) + 1;                    else                        delta_d = env->vfp.vec_stride + 1;                    if ((rm & bank_mask) == 0) {                        /* mixed scalar/vector */                        delta_m = 0;                    } else {                        /* vector */                        delta_m = delta_d;                    }                }            }            /* Load the initial operands.  */            if (op == 15) {                switch (rn) {                case 16:                case 17:                    /* Integer source */                    gen_mov_F0_vreg(0, rm);                    break;                case 8:                case 9:                    /* Compare */                    gen_mov_F0_vreg(dp, rd);                    gen_mov_F1_vreg(dp, rm);                    break;                case 10:                case 11:                    /* Compare with zero */                    gen_mov_F0_vreg(dp, rd);                    gen_vfp_F1_ld0(dp);                    break;                default:                    /* One source operand.  */                    gen_mov_F0_vreg(dp, rm);                }            } else {                /* Two source operands.  */                gen_mov_F0_vreg(dp, rn);                gen_mov_F1_vreg(dp, rm);            }            for (;;) {                /* Perform the calculation.  */                switch (op) {                case 0: /* mac: fd + (fn * fm) */                    gen_vfp_mul(dp);                    gen_mov_F1_vreg(dp, rd);                    gen_vfp_add(dp);                    break;                case 1: /* nmac: fd - (fn * fm) */                    gen_vfp_mul(dp);                    gen_vfp_neg(dp);                    gen_mov_F1_vreg(dp, rd);                    gen_vfp_add(dp);                    break;                case 2: /* msc: -fd + (fn * fm) */                    gen_vfp_mul(dp);                    gen_mov_F1_vreg(dp, rd);                    gen_vfp_sub(dp);                    break;                case 3: /* nmsc: -fd - (fn * fm)  */                    gen_vfp_mul(dp);                    gen_mov_F1_vreg(dp, rd);                    gen_vfp_add(dp);                    gen_vfp_neg(dp);                    break;                case 4: /* mul: fn * fm */                    gen_vfp_mul(dp);                    break;                case 5: /* nmul: -(fn * fm) */                    gen_vfp_mul(dp);                    gen_vfp_neg(dp);                    break;                case 6: /* add: fn + fm */                    gen_vfp_add(dp);                    break;                case 7: /* sub: fn - fm */                    gen_vfp_sub(dp);                    break;                case 8: /* div: fn / fm */                    gen_vfp_div(dp);                    break;                case 15: /* extension space */                    switch (rn) {                    case 0: /* cpy */                        /* no-op */                        break;                    case 1: /* abs */                        gen_vfp_abs(dp);                        break;                    case 2: /* neg */                        gen_vfp_neg(dp);                        break;                    case 3: /* sqrt */                        gen_vfp_sqrt(dp);                        break;                    case 8: /* cmp */                        gen_vfp_cmp(dp);                        break;                    case 9: /* cmpe */                        gen_vfp_cmpe(dp);                        break;                    case 10: /* cmpz */                        gen_vfp_cmp(dp);                        break;                    case 11: /* cmpez */                        gen_vfp_F1_ld0(dp);                        gen_vfp_cmpe(dp);                        break;                    case 15: /* single<->double conversion */                        if (dp)                            gen_op_vfp_fcvtsd();                        else                            gen_op_vfp_fcvtds();                        break;                    case 16: /* fuito */                        gen_vfp_uito(dp);                        break;                    case 17: /* fsito */                        gen_vfp_sito(dp);                        break;                    case 24: /* ftoui */                        gen_vfp_toui(dp);                        break;                    case 25: /* ftouiz */                        gen_vfp_touiz(dp);                        break;                    case 26: /* ftosi */                        gen_vfp_tosi(dp);                        break;                    case 27: /* ftosiz */                        gen_vfp_tosiz(dp);                        break;                    default: /* undefined */                        printf ("rn:%d\n", rn);                        return 1;                    }                    break;                default: /* undefined */                    printf ("op:%d\n", op);                    return 1;                }                /* Write back the result.  */                if (op == 15 && (rn >= 8 && rn <= 11))                    ; /* Comparison, do nothing.  */                else if (op == 15 && rn > 17)                    /* Integer result.  */                    gen_mov_vreg_F0(0, rd);                else if (op == 15 && rn == 15)                    /* conversion */                    gen_mov_vreg_F0(!dp, rd);                else                    gen_mov_vreg_F0(dp, rd);                /* break out of the loop if we have finished  */                if (veclen == 0)                    break;                if (op == 15 && delta_m == 0) {                    /* single source one-many */                    while (veclen--) {                        rd = ((rd + delta_d) & (bank_mask - 1))                             | (rd & bank_mask);                        gen_mov_vreg_F0(dp, rd);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -