mirror of https://github.com/xemu-project/xemu.git
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:
parent
97584f2bc8
commit
8d1b02a6a1
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
|
|
Loading…
Reference in New Issue