diff --git a/qemu/target/arm/translate-vfp.inc.c b/qemu/target/arm/translate-vfp.inc.c index 19d08f30..6c8a4b3f 100644 --- a/qemu/target/arm/translate-vfp.inc.c +++ b/qemu/target/arm/translate-vfp.inc.c @@ -2188,3 +2188,172 @@ static bool trans_VCVT_f16_f64(DisasContext *s, arg_VCVT_f16_f64 *a) tcg_temp_free_i32(tcg_ctx, tmp); return true; } + +static bool trans_VRINTR_sp(DisasContext *s, arg_VRINTR_sp *a) +{ + TCGContext *tcg_ctx = s->uc->tcg_ctx; + TCGv_ptr fpst; + TCGv_i32 tmp; + + if (!dc_isar_feature(aa32_vrint, s)) { + return false; + } + + if (!vfp_access_check(s)) { + return true; + } + + tmp = tcg_temp_new_i32(tcg_ctx); + neon_load_reg32(s, tmp, a->vm); + fpst = get_fpstatus_ptr(s, false); + gen_helper_rints(tcg_ctx, tmp, tmp, fpst); + neon_store_reg32(s, tmp, a->vd); + tcg_temp_free_ptr(tcg_ctx, fpst); + tcg_temp_free_i32(tcg_ctx, tmp); + return true; +} + +static bool trans_VRINTR_dp(DisasContext *s, arg_VRINTR_sp *a) +{ + TCGContext *tcg_ctx = s->uc->tcg_ctx; + TCGv_ptr fpst; + TCGv_i64 tmp; + + if (!dc_isar_feature(aa32_vrint, s)) { + return false; + } + + /* UNDEF accesses to D16-D31 if they don't exist. */ + if (!dc_isar_feature(aa32_fp_d32, s) && ((a->vd | a->vm) & 0x10)) { + return false; + } + + if (!vfp_access_check(s)) { + return true; + } + + tmp = tcg_temp_new_i64(tcg_ctx); + neon_load_reg64(s, tmp, a->vm); + fpst = get_fpstatus_ptr(s, false); + gen_helper_rintd(tcg_ctx, tmp, tmp, fpst); + neon_store_reg64(s, tmp, a->vd); + tcg_temp_free_ptr(tcg_ctx, fpst); + tcg_temp_free_i64(tcg_ctx, tmp); + return true; +} + +static bool trans_VRINTZ_sp(DisasContext *s, arg_VRINTZ_sp *a) +{ + TCGContext *tcg_ctx = s->uc->tcg_ctx; + TCGv_ptr fpst; + TCGv_i32 tmp; + TCGv_i32 tcg_rmode; + + if (!dc_isar_feature(aa32_vrint, s)) { + return false; + } + + if (!vfp_access_check(s)) { + return true; + } + + tmp = tcg_temp_new_i32(tcg_ctx); + neon_load_reg32(s, tmp, a->vm); + fpst = get_fpstatus_ptr(s, false); + tcg_rmode = tcg_const_i32(tcg_ctx, float_round_to_zero); + gen_helper_set_rmode(tcg_ctx, tcg_rmode, tcg_rmode, fpst); + gen_helper_rints(tcg_ctx, tmp, tmp, fpst); + gen_helper_set_rmode(tcg_ctx, tcg_rmode, tcg_rmode, fpst); + neon_store_reg32(s, tmp, a->vd); + tcg_temp_free_ptr(tcg_ctx, fpst); + tcg_temp_free_i32(tcg_ctx, tcg_rmode); + tcg_temp_free_i32(tcg_ctx, tmp); + return true; +} + +static bool trans_VRINTZ_dp(DisasContext *s, arg_VRINTZ_sp *a) +{ + TCGContext *tcg_ctx = s->uc->tcg_ctx; + TCGv_ptr fpst; + TCGv_i64 tmp; + TCGv_i32 tcg_rmode; + + if (!dc_isar_feature(aa32_vrint, s)) { + return false; + } + + /* UNDEF accesses to D16-D31 if they don't exist. */ + if (!dc_isar_feature(aa32_fp_d32, s) && ((a->vd | a->vm) & 0x10)) { + return false; + } + + if (!vfp_access_check(s)) { + return true; + } + + tmp = tcg_temp_new_i64(tcg_ctx); + neon_load_reg64(s, tmp, a->vm); + fpst = get_fpstatus_ptr(s, false); + tcg_rmode = tcg_const_i32(tcg_ctx, float_round_to_zero); + gen_helper_set_rmode(tcg_ctx, tcg_rmode, tcg_rmode, fpst); + gen_helper_rintd(tcg_ctx, tmp, tmp, fpst); + gen_helper_set_rmode(tcg_ctx, tcg_rmode, tcg_rmode, fpst); + neon_store_reg64(s, tmp, a->vd); + tcg_temp_free_ptr(tcg_ctx, fpst); + tcg_temp_free_i64(tcg_ctx, tmp); + tcg_temp_free_i32(tcg_ctx, tcg_rmode); + return true; +} + +static bool trans_VRINTX_sp(DisasContext *s, arg_VRINTX_sp *a) +{ + TCGContext *tcg_ctx = s->uc->tcg_ctx; + TCGv_ptr fpst; + TCGv_i32 tmp; + + if (!dc_isar_feature(aa32_vrint, s)) { + return false; + } + + if (!vfp_access_check(s)) { + return true; + } + + tmp = tcg_temp_new_i32(tcg_ctx); + neon_load_reg32(s, tmp, a->vm); + fpst = get_fpstatus_ptr(s, false); + gen_helper_rints_exact(tcg_ctx, tmp, tmp, fpst); + neon_store_reg32(s, tmp, a->vd); + tcg_temp_free_ptr(tcg_ctx, fpst); + tcg_temp_free_i32(tcg_ctx, tmp); + return true; +} + +static bool trans_VRINTX_dp(DisasContext *s, arg_VRINTX_dp *a) +{ + TCGContext *tcg_ctx = s->uc->tcg_ctx; + TCGv_ptr fpst; + TCGv_i64 tmp; + + if (!dc_isar_feature(aa32_vrint, s)) { + return false; + } + + /* UNDEF accesses to D16-D31 if they don't exist. */ + if (!dc_isar_feature(aa32_fp_d32, s) && ((a->vd | a->vm) & 0x10)) { + return false; + } + + if (!vfp_access_check(s)) { + return true; + } + + tmp = tcg_temp_new_i64(tcg_ctx); + neon_load_reg64(s, tmp, a->vm); + fpst = get_fpstatus_ptr(s, false); + gen_helper_rintd_exact(tcg_ctx, tmp, tmp, fpst); + neon_store_reg64(s, tmp, a->vd); + tcg_temp_free_ptr(tcg_ctx, fpst); + tcg_temp_free_i64(tcg_ctx, tmp); + return true; +} diff --git a/qemu/target/arm/translate.c b/qemu/target/arm/translate.c index 412f48eb..7e78c052 100644 --- a/qemu/target/arm/translate.c +++ b/qemu/target/arm/translate.c @@ -3145,7 +3145,7 @@ static int disas_vfp_insn(DisasContext *s, uint32_t insn) return 1; case 15: switch (rn) { - case 0 ... 11: + case 0 ... 14: /* Already handled by decodetree */ return 1; default: @@ -3158,11 +3158,6 @@ static int disas_vfp_insn(DisasContext *s, uint32_t insn) if (op == 15) { /* rn is opcode, encoded as per VFP_SREG_N. */ switch (rn) { - case 0x0c: /* vrintr */ - case 0x0d: /* vrintz */ - case 0x0e: /* vrintx */ - break; - case 0x0f: /* vcvt double<->single */ rd_is_dp = !dp; break; @@ -3285,44 +3280,6 @@ static int disas_vfp_insn(DisasContext *s, uint32_t insn) switch (op) { case 15: /* extension space */ switch (rn) { - case 12: /* vrintr */ - { - TCGv_ptr fpst = get_fpstatus_ptr(s, 0); - if (dp) { - gen_helper_rintd(tcg_ctx, s->F0d, s->F0d, fpst); - } else { - gen_helper_rints(tcg_ctx, s->F0s, s->F0s, fpst); - } - tcg_temp_free_ptr(tcg_ctx, fpst); - break; - } - case 13: /* vrintz */ - { - TCGv_ptr fpst = get_fpstatus_ptr(s, 0); - TCGv_i32 tcg_rmode; - tcg_rmode = tcg_const_i32(tcg_ctx, float_round_to_zero); - gen_helper_set_rmode(tcg_ctx, tcg_rmode, tcg_rmode, fpst); - if (dp) { - gen_helper_rintd(tcg_ctx, s->F0d, s->F0d, fpst); - } else { - gen_helper_rints(tcg_ctx, s->F0s, s->F0s, fpst); - } - gen_helper_set_rmode(tcg_ctx, tcg_rmode, tcg_rmode, fpst); - tcg_temp_free_i32(tcg_ctx, tcg_rmode); - tcg_temp_free_ptr(tcg_ctx, fpst); - break; - } - case 14: /* vrintx */ - { - TCGv_ptr fpst = get_fpstatus_ptr(s, 0); - if (dp) { - gen_helper_rintd_exact(tcg_ctx, s->F0d, s->F0d, fpst); - } else { - gen_helper_rints_exact(tcg_ctx, s->F0s, s->F0s, fpst); - } - tcg_temp_free_ptr(tcg_ctx, fpst); - break; - } case 15: /* single<->double conversion */ if (dp) { gen_helper_vfp_fcvtsd(tcg_ctx, s->F0s, s->F0d, tcg_ctx->cpu_env); diff --git a/qemu/target/arm/vfp.decode b/qemu/target/arm/vfp.decode index b88d1d06..9942d2ae 100644 --- a/qemu/target/arm/vfp.decode +++ b/qemu/target/arm/vfp.decode @@ -193,3 +193,18 @@ VCVT_f16_f32 ---- 1110 1.11 0011 .... 1010 t:1 1.0 .... \ vd=%vd_sp vm=%vm_sp VCVT_f16_f64 ---- 1110 1.11 0011 .... 1011 t:1 1.0 .... \ vd=%vd_sp vm=%vm_dp + +VRINTR_sp ---- 1110 1.11 0110 .... 1010 01.0 .... \ + vd=%vd_sp vm=%vm_sp +VRINTR_dp ---- 1110 1.11 0110 .... 1011 01.0 .... \ + vd=%vd_dp vm=%vm_dp + +VRINTZ_sp ---- 1110 1.11 0110 .... 1010 11.0 .... \ + vd=%vd_sp vm=%vm_sp +VRINTZ_dp ---- 1110 1.11 0110 .... 1011 11.0 .... \ + vd=%vd_dp vm=%vm_dp + +VRINTX_sp ---- 1110 1.11 0111 .... 1010 01.0 .... \ + vd=%vd_sp vm=%vm_sp +VRINTX_dp ---- 1110 1.11 0111 .... 1011 01.0 .... \ + vd=%vd_dp vm=%vm_dp