diff --git a/qemu/target/arm/translate-vfp.inc.c b/qemu/target/arm/translate-vfp.inc.c index 52dd1284..09c6a085 100644 --- a/qemu/target/arm/translate-vfp.inc.c +++ b/qemu/target/arm/translate-vfp.inc.c @@ -2622,3 +2622,77 @@ static bool trans_VCVT_fix_dp(DisasContext *s, arg_VCVT_fix_dp *a) tcg_temp_free_ptr(tcg_ctx, fpst); return true; } + +static bool trans_VCVT_sp_int(DisasContext *s, arg_VCVT_sp_int *a) +{ + TCGContext *tcg_ctx = s->uc->tcg_ctx; + TCGv_i32 vm; + TCGv_ptr fpst; + + if (!vfp_access_check(s)) { + return true; + } + + fpst = get_fpstatus_ptr(s, false); + vm = tcg_temp_new_i32(tcg_ctx); + neon_load_reg32(s, vm, a->vm); + + if (a->s) { + if (a->rz) { + gen_helper_vfp_tosizs(tcg_ctx, vm, vm, fpst); + } else { + gen_helper_vfp_tosis(tcg_ctx, vm, vm, fpst); + } + } else { + if (a->rz) { + gen_helper_vfp_touizs(tcg_ctx, vm, vm, fpst); + } else { + gen_helper_vfp_touis(tcg_ctx, vm, vm, fpst); + } + } + neon_store_reg32(s, vm, a->vd); + tcg_temp_free_i32(tcg_ctx, vm); + tcg_temp_free_ptr(tcg_ctx, fpst); + return true; +} + +static bool trans_VCVT_dp_int(DisasContext *s, arg_VCVT_dp_int *a) +{ + TCGContext *tcg_ctx = s->uc->tcg_ctx; + TCGv_i32 vd; + TCGv_i64 vm; + TCGv_ptr fpst; + + /* UNDEF accesses to D16-D31 if they don't exist. */ + if (!dc_isar_feature(aa32_fp_d32, s) && (a->vm & 0x10)) { + return false; + } + + if (!vfp_access_check(s)) { + return true; + } + + fpst = get_fpstatus_ptr(s, false); + vm = tcg_temp_new_i64(tcg_ctx); + vd = tcg_temp_new_i32(tcg_ctx); + neon_load_reg64(s, vm, a->vm); + + if (a->s) { + if (a->rz) { + gen_helper_vfp_tosizd(tcg_ctx, vd, vm, fpst); + } else { + gen_helper_vfp_tosid(tcg_ctx, vd, vm, fpst); + } + } else { + if (a->rz) { + gen_helper_vfp_touizd(tcg_ctx, vd, vm, fpst); + } else { + gen_helper_vfp_touid(tcg_ctx, vd, vm, fpst); + } + } + neon_store_reg32(s, vd, a->vd); + tcg_temp_free_i32(tcg_ctx, vd); + tcg_temp_free_i64(tcg_ctx, vm); + tcg_temp_free_ptr(tcg_ctx, fpst); + return true; +} diff --git a/qemu/target/arm/translate.c b/qemu/target/arm/translate.c index 603c899e..8f0572ca 100644 --- a/qemu/target/arm/translate.c +++ b/qemu/target/arm/translate.c @@ -1477,9 +1477,7 @@ static inline void gen_vfp_##name(DisasContext *s, int dp, int neon) \ tcg_temp_free_ptr(tcg_ctx, statusptr); \ } -VFP_GEN_FTOI(toui) VFP_GEN_FTOI(touiz) -VFP_GEN_FTOI(tosi) VFP_GEN_FTOI(tosiz) #undef VFP_GEN_FTOI @@ -1683,36 +1681,7 @@ static TCGv_ptr vfp_reg_ptr(DisasContext *s, bool dp, int reg) } #define tcg_gen_ld_f32 tcg_gen_ld_i32 -#define tcg_gen_ld_f64 tcg_gen_ld_i64 #define tcg_gen_st_f32 tcg_gen_st_i32 -#define tcg_gen_st_f64 tcg_gen_st_i64 - -static inline void gen_mov_F0_vreg(DisasContext *s, int dp, int reg) -{ - TCGContext *tcg_ctx = s->uc->tcg_ctx; - if (dp) - tcg_gen_ld_f64(tcg_ctx, s->F0d, tcg_ctx->cpu_env, vfp_reg_offset(dp, reg)); - else - tcg_gen_ld_f32(tcg_ctx, s->F0s, tcg_ctx->cpu_env, vfp_reg_offset(dp, reg)); -} - -static inline void gen_mov_F1_vreg(DisasContext *s, int dp, int reg) -{ - TCGContext *tcg_ctx = s->uc->tcg_ctx; - if (dp) - tcg_gen_ld_f64(tcg_ctx, s->F1d, tcg_ctx->cpu_env, vfp_reg_offset(dp, reg)); - else - tcg_gen_ld_f32(tcg_ctx, s->F1s, tcg_ctx->cpu_env, vfp_reg_offset(dp, reg)); -} - -static inline void gen_mov_vreg_F0(DisasContext *s, int dp, int reg) -{ - TCGContext *tcg_ctx = s->uc->tcg_ctx; - if (dp) - tcg_gen_st_f64(tcg_ctx, s->F0d, tcg_ctx->cpu_env, vfp_reg_offset(dp, reg)); - else - tcg_gen_st_f32(tcg_ctx, s->F0s, tcg_ctx->cpu_env, vfp_reg_offset(dp, reg)); -} #define ARM_CP_RW_BIT (1 << 20) @@ -3077,9 +3046,6 @@ static void gen_neon_dup_high16(DisasContext *s, TCGv_i32 var) */ static int disas_vfp_insn(DisasContext *s, uint32_t insn) { - uint32_t rd, rn, rm, op, delta_d, delta_m, bank_mask; - int dp, veclen; - if (!arm_dc_feature(s, ARM_FEATURE_VFP)) { return 1; } @@ -3100,213 +3066,8 @@ static int disas_vfp_insn(DisasContext *s, uint32_t insn) } } - if (extract32(insn, 28, 4) == 0xf) { - /* - * Encodings with T=1 (Thumb) or unconditional (ARM): these - * were all handled by the decodetree decoder, so any insn - * patterns which get here must be UNDEF. - */ - return 1; - } - - /* - * FIXME: this access check should not take precedence over UNDEF - * for invalid encodings; we will generate incorrect syndrome information - * for attempts to execute invalid vfp/neon encodings with FP disabled. - */ - if (!vfp_access_check(s)) { - return 0; - } - - dp = ((insn & 0xf00) == 0xb00); - switch ((insn >> 24) & 0xf) { - case 0xe: - if (insn & (1 << 4)) { - /* already handled by decodetree */ - return 1; - } else { - /* data processing */ - bool rd_is_dp = dp; - bool rm_is_dp = dp; - bool no_output = false; - - /* The opcode is in bits 23, 21, 20 and 6. */ - op = ((insn >> 20) & 8) | ((insn >> 19) & 6) | ((insn >> 6) & 1); - rn = VFP_SREG_N(insn); - - switch (op) { - case 0 ... 14: - /* Already handled by decodetree */ - return 1; - case 15: - switch (rn) { - case 0 ... 23: - case 28 ... 31: - /* Already handled by decodetree */ - return 1; - default: - break; - } - default: - break; - } - - if (op == 15) { - /* rn is opcode, encoded as per VFP_SREG_N. */ - switch (rn) { - case 0x18: /* vcvtr.u32.fxx */ - case 0x19: /* vcvtz.u32.fxx */ - case 0x1a: /* vcvtr.s32.fxx */ - case 0x1b: /* vcvtz.s32.fxx */ - rd_is_dp = false; - break; - - default: - return 1; - } - } else if (dp) { - /* rn is register number */ - VFP_DREG_N(rn, insn); - } - - if (rd_is_dp) { - VFP_DREG_D(rd, insn); - } else { - rd = VFP_SREG_D(insn); - } - if (rm_is_dp) { - VFP_DREG_M(rm, insn); - } else { - rm = VFP_SREG_M(insn); - } - - veclen = s->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 = (s->vec_stride >> 1) + 1; - else - delta_d = s->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) { - default: - /* One source operand. */ - gen_mov_F0_vreg(s, rm_is_dp, rm); - break; - } - } else { - /* Two source operands. */ - gen_mov_F0_vreg(s, dp, rn); - gen_mov_F1_vreg(s, dp, rm); - } - - for (;;) { - /* Perform the calculation. */ - switch (op) { - case 15: /* extension space */ - switch (rn) { - case 24: /* ftoui */ - gen_vfp_toui(s, dp, 0); - break; - case 25: /* ftouiz */ - gen_vfp_touiz(s, dp, 0); - break; - case 26: /* ftosi */ - gen_vfp_tosi(s, dp, 0); - break; - case 27: /* ftosiz */ - gen_vfp_tosiz(s, dp, 0); - break; - default: /* undefined */ - g_assert_not_reached(); - } - break; - default: /* undefined */ - return 1; - } - - /* Write back the result, if any. */ - if (!no_output) { - gen_mov_vreg_F0(s, rd_is_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(s, dp, rd); - } - break; - } - /* Setup the next operands. */ - veclen--; - rd = ((rd + delta_d) & (bank_mask - 1)) - | (rd & bank_mask); - - if (op == 15) { - /* One source operand. */ - rm = ((rm + delta_m) & (bank_mask - 1)) - | (rm & bank_mask); - gen_mov_F0_vreg(s, dp, rm); - } else { - /* Two source operands. */ - rn = ((rn + delta_d) & (bank_mask - 1)) - | (rn & bank_mask); - gen_mov_F0_vreg(s, dp, rn); - if (delta_m) { - rm = ((rm + delta_m) & (bank_mask - 1)) - | (rm & bank_mask); - gen_mov_F1_vreg(s, dp, rm); - } - } - } - } - break; - case 0xc: - case 0xd: - /* Already handled by decodetree */ - return 1; - default: - /* Should never happen. */ - return 1; - } - return 0; + /* If the decodetree decoder didn't handle this insn, it must be UNDEF */ + return 1; } static inline bool use_goto_tb(DisasContext *s, target_ulong dest) diff --git a/qemu/target/arm/vfp.decode b/qemu/target/arm/vfp.decode index c3223a12..ea24365b 100644 --- a/qemu/target/arm/vfp.decode +++ b/qemu/target/arm/vfp.decode @@ -234,3 +234,9 @@ VCVT_fix_sp ---- 1110 1.11 1.1. .... 1010 .1.0 .... \ vd=%vd_sp imm=%vm_sp opc=%vcvt_fix_op VCVT_fix_dp ---- 1110 1.11 1.1. .... 1011 .1.0 .... \ vd=%vd_dp imm=%vm_sp opc=%vcvt_fix_op + +# VCVT float to integer (VCVT and VCVTR): Vd always single; Vd depends on size +VCVT_sp_int ---- 1110 1.11 110 s:1 .... 1010 rz:1 1.0 .... \ + vd=%vd_sp vm=%vm_sp +VCVT_dp_int ---- 1110 1.11 110 s:1 .... 1011 rz:1 1.0 .... \ + vd=%vd_sp vm=%vm_dp