target/arm: Create gen_set_rmode, gen_restore_rmode

Split out common subroutines for handing rounding mode
changes during translation.  Use tcg_constant_i32 and
tcg_temp_new_i32 instead of tcg_const_i32.

Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
This commit is contained in:
Richard Henderson 2023-02-25 11:06:53 -10:00
parent 97584f2bc8
commit 8d1b02a6a1
4 changed files with 48 additions and 48 deletions

View File

@ -6146,13 +6146,12 @@ static void handle_fp_1src_half(DisasContext *s, int opcode, int rd, int rn)
case 0xb: /* FRINTZ */
case 0xc: /* FRINTA */
{
TCGv_i32 tcg_rmode = tcg_const_i32(arm_rmode_to_sf(opcode & 7));
TCGv_i32 tcg_rmode;
fpst = fpstatus_ptr(FPST_FPCR_F16);
gen_helper_set_rmode(tcg_rmode, tcg_rmode, fpst);
tcg_rmode = gen_set_rmode(opcode & 7, fpst);
gen_helper_advsimd_rinth(tcg_res, tcg_op, fpst);
gen_helper_set_rmode(tcg_rmode, tcg_rmode, fpst);
gen_restore_rmode(tcg_rmode, fpst);
break;
}
case 0xe: /* FRINTX */
@ -6231,10 +6230,9 @@ static void handle_fp_1src_single(DisasContext *s, int opcode, int rd, int rn)
fpst = fpstatus_ptr(FPST_FPCR);
if (rmode >= 0) {
TCGv_i32 tcg_rmode = tcg_const_i32(arm_rmode_to_sf(rmode));
gen_helper_set_rmode(tcg_rmode, tcg_rmode, fpst);
TCGv_i32 tcg_rmode = gen_set_rmode(rmode, fpst);
gen_fpst(tcg_res, tcg_op, fpst);
gen_helper_set_rmode(tcg_rmode, tcg_rmode, fpst);
gen_restore_rmode(tcg_rmode, fpst);
} else {
gen_fpst(tcg_res, tcg_op, fpst);
}
@ -6304,10 +6302,9 @@ static void handle_fp_1src_double(DisasContext *s, int opcode, int rd, int rn)
fpst = fpstatus_ptr(FPST_FPCR);
if (rmode >= 0) {
TCGv_i32 tcg_rmode = tcg_const_i32(arm_rmode_to_sf(rmode));
gen_helper_set_rmode(tcg_rmode, tcg_rmode, fpst);
TCGv_i32 tcg_rmode = gen_set_rmode(rmode, fpst);
gen_fpst(tcg_res, tcg_op, fpst);
gen_helper_set_rmode(tcg_rmode, tcg_rmode, fpst);
gen_restore_rmode(tcg_rmode, fpst);
} else {
gen_fpst(tcg_res, tcg_op, fpst);
}
@ -6944,9 +6941,7 @@ static void handle_fpfpcvt(DisasContext *s, int rd, int rn, int opcode,
rmode = FPROUNDING_TIEAWAY;
}
tcg_rmode = tcg_const_i32(arm_rmode_to_sf(rmode));
gen_helper_set_rmode(tcg_rmode, tcg_rmode, tcg_fpstatus);
tcg_rmode = gen_set_rmode(rmode, tcg_fpstatus);
switch (type) {
case 1: /* float64 */
@ -7023,7 +7018,7 @@ static void handle_fpfpcvt(DisasContext *s, int rd, int rn, int opcode,
g_assert_not_reached();
}
gen_helper_set_rmode(tcg_rmode, tcg_rmode, tcg_fpstatus);
gen_restore_rmode(tcg_rmode, tcg_fpstatus);
}
}
@ -8771,9 +8766,8 @@ static void handle_simd_shift_fpint_conv(DisasContext *s, bool is_scalar,
assert(!(is_scalar && is_q));
tcg_rmode = tcg_const_i32(arm_rmode_to_sf(FPROUNDING_ZERO));
tcg_fpstatus = fpstatus_ptr(size == MO_16 ? FPST_FPCR_F16 : FPST_FPCR);
gen_helper_set_rmode(tcg_rmode, tcg_rmode, tcg_fpstatus);
tcg_rmode = gen_set_rmode(FPROUNDING_ZERO, tcg_fpstatus);
fracbits = (16 << size) - immhb;
tcg_shift = tcg_constant_i32(fracbits);
@ -8831,7 +8825,7 @@ static void handle_simd_shift_fpint_conv(DisasContext *s, bool is_scalar,
}
}
gen_helper_set_rmode(tcg_rmode, tcg_rmode, tcg_fpstatus);
gen_restore_rmode(tcg_rmode, tcg_fpstatus);
}
/* AdvSIMD scalar shift by immediate
@ -10219,12 +10213,11 @@ static void disas_simd_scalar_two_reg_misc(DisasContext *s, uint32_t insn)
}
if (is_fcvt) {
tcg_rmode = tcg_const_i32(arm_rmode_to_sf(rmode));
tcg_fpstatus = fpstatus_ptr(FPST_FPCR);
gen_helper_set_rmode(tcg_rmode, tcg_rmode, tcg_fpstatus);
tcg_rmode = gen_set_rmode(rmode, tcg_fpstatus);
} else {
tcg_rmode = NULL;
tcg_fpstatus = NULL;
tcg_rmode = NULL;
}
if (size == 3) {
@ -10276,7 +10269,7 @@ static void disas_simd_scalar_two_reg_misc(DisasContext *s, uint32_t insn)
}
if (is_fcvt) {
gen_helper_set_rmode(tcg_rmode, tcg_rmode, tcg_fpstatus);
gen_restore_rmode(tcg_rmode, tcg_fpstatus);
}
}
@ -12406,8 +12399,7 @@ static void disas_simd_two_reg_misc(DisasContext *s, uint32_t insn)
tcg_fpstatus = NULL;
}
if (rmode >= 0) {
tcg_rmode = tcg_const_i32(arm_rmode_to_sf(rmode));
gen_helper_set_rmode(tcg_rmode, tcg_rmode, tcg_fpstatus);
tcg_rmode = gen_set_rmode(rmode, tcg_fpstatus);
} else {
tcg_rmode = NULL;
}
@ -12590,7 +12582,7 @@ static void disas_simd_two_reg_misc(DisasContext *s, uint32_t insn)
clear_vec_high(s, is_q, rd);
if (tcg_rmode) {
gen_helper_set_rmode(tcg_rmode, tcg_rmode, tcg_fpstatus);
gen_restore_rmode(tcg_rmode, tcg_fpstatus);
}
}
@ -12758,8 +12750,7 @@ static void disas_simd_two_reg_misc_fp16(DisasContext *s, uint32_t insn)
}
if (rmode >= 0) {
tcg_rmode = tcg_const_i32(arm_rmode_to_sf(rmode));
gen_helper_set_rmode(tcg_rmode, tcg_rmode, tcg_fpstatus);
tcg_rmode = gen_set_rmode(rmode, tcg_fpstatus);
}
if (is_scalar) {
@ -12859,7 +12850,7 @@ static void disas_simd_two_reg_misc_fp16(DisasContext *s, uint32_t insn)
}
if (tcg_rmode) {
gen_helper_set_rmode(tcg_rmode, tcg_rmode, tcg_fpstatus);
gen_restore_rmode(tcg_rmode, tcg_fpstatus);
}
}

View File

@ -4096,17 +4096,15 @@ static bool do_frint_mode(DisasContext *s, arg_rpr_esz *a,
}
vsz = vec_full_reg_size(s);
tmode = tcg_const_i32(arm_rmode_to_sf(mode));
status = fpstatus_ptr(a->esz == MO_16 ? FPST_FPCR_F16 : FPST_FPCR);
gen_helper_set_rmode(tmode, tmode, status);
tmode = gen_set_rmode(mode, status);
tcg_gen_gvec_3_ptr(vec_full_reg_offset(s, a->rd),
vec_full_reg_offset(s, a->rn),
pred_full_reg_offset(s, a->pg),
status, vsz, vsz, 0, fn);
gen_helper_set_rmode(tmode, tmode, status);
gen_restore_rmode(tmode, status);
return true;
}

View File

@ -464,8 +464,7 @@ static bool trans_VRINT(DisasContext *s, arg_VRINT *a)
fpst = fpstatus_ptr(FPST_FPCR);
}
tcg_rmode = tcg_const_i32(arm_rmode_to_sf(rounding));
gen_helper_set_rmode(tcg_rmode, tcg_rmode, fpst);
tcg_rmode = gen_set_rmode(rounding, fpst);
if (sz == 3) {
TCGv_i64 tcg_op;
@ -489,7 +488,7 @@ static bool trans_VRINT(DisasContext *s, arg_VRINT *a)
vfp_store_reg32(tcg_res, rd);
}
gen_helper_set_rmode(tcg_rmode, tcg_rmode, fpst);
gen_restore_rmode(tcg_rmode, fpst);
return true;
}
@ -533,9 +532,7 @@ static bool trans_VCVT(DisasContext *s, arg_VCVT *a)
}
tcg_shift = tcg_constant_i32(0);
tcg_rmode = tcg_const_i32(arm_rmode_to_sf(rounding));
gen_helper_set_rmode(tcg_rmode, tcg_rmode, fpst);
tcg_rmode = gen_set_rmode(rounding, fpst);
if (sz == 3) {
TCGv_i64 tcg_double, tcg_res;
@ -572,7 +569,7 @@ static bool trans_VCVT(DisasContext *s, arg_VCVT *a)
vfp_store_reg32(tcg_res, rd);
}
gen_helper_set_rmode(tcg_rmode, tcg_rmode, fpst);
gen_restore_rmode(tcg_rmode, fpst);
return true;
}
@ -2783,10 +2780,9 @@ static bool trans_VRINTZ_hp(DisasContext *s, arg_VRINTZ_sp *a)
tmp = tcg_temp_new_i32();
vfp_load_reg32(tmp, a->vm);
fpst = fpstatus_ptr(FPST_FPCR_F16);
tcg_rmode = tcg_const_i32(arm_rmode_to_sf(FPROUNDING_ZERO));
gen_helper_set_rmode(tcg_rmode, tcg_rmode, fpst);
tcg_rmode = gen_set_rmode(FPROUNDING_ZERO, fpst);
gen_helper_rinth(tmp, tmp, fpst);
gen_helper_set_rmode(tcg_rmode, tcg_rmode, fpst);
gen_restore_rmode(tcg_rmode, fpst);
vfp_store_reg32(tmp, a->vd);
return true;
}
@ -2808,10 +2804,9 @@ static bool trans_VRINTZ_sp(DisasContext *s, arg_VRINTZ_sp *a)
tmp = tcg_temp_new_i32();
vfp_load_reg32(tmp, a->vm);
fpst = fpstatus_ptr(FPST_FPCR);
tcg_rmode = tcg_const_i32(arm_rmode_to_sf(FPROUNDING_ZERO));
gen_helper_set_rmode(tcg_rmode, tcg_rmode, fpst);
tcg_rmode = gen_set_rmode(FPROUNDING_ZERO, fpst);
gen_helper_rints(tmp, tmp, fpst);
gen_helper_set_rmode(tcg_rmode, tcg_rmode, fpst);
gen_restore_rmode(tcg_rmode, fpst);
vfp_store_reg32(tmp, a->vd);
return true;
}
@ -2842,10 +2837,9 @@ static bool trans_VRINTZ_dp(DisasContext *s, arg_VRINTZ_dp *a)
tmp = tcg_temp_new_i64();
vfp_load_reg64(tmp, a->vm);
fpst = fpstatus_ptr(FPST_FPCR);
tcg_rmode = tcg_const_i32(arm_rmode_to_sf(FPROUNDING_ZERO));
gen_helper_set_rmode(tcg_rmode, tcg_rmode, fpst);
tcg_rmode = gen_set_rmode(FPROUNDING_ZERO, fpst);
gen_helper_rintd(tmp, tmp, fpst);
gen_helper_set_rmode(tcg_rmode, tcg_rmode, fpst);
gen_restore_rmode(tcg_rmode, fpst);
vfp_store_reg64(tmp, a->vd);
return true;
}

View File

@ -616,6 +616,23 @@ static inline TCGv_ptr gen_lookup_cp_reg(uint32_t key)
return ret;
}
/*
* Set and reset rounding mode around another operation.
*/
static inline TCGv_i32 gen_set_rmode(ARMFPRounding rmode, TCGv_ptr fpst)
{
TCGv_i32 new = tcg_constant_i32(arm_rmode_to_sf(rmode));
TCGv_i32 old = tcg_temp_new_i32();
gen_helper_set_rmode(old, new, fpst);
return old;
}
static inline void gen_restore_rmode(TCGv_i32 old, TCGv_ptr fpst)
{
gen_helper_set_rmode(old, old, fpst);
}
/*
* Helpers for implementing sets of trans_* functions.
* Defer the implementation of NAME to FUNC, with optional extra arguments.