📄 translate.c
字号:
#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 + -