target/arm: Implement MVE VRINT insns

Implement the MVE VRINT insns, which round floating point inputs
to integer values, leaving them in floating point format.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
This commit is contained in:
Peter Maydell 2021-09-01 09:02:39 +01:00
parent 73d260db3c
commit 98e40fbd79
4 changed files with 93 additions and 0 deletions

View File

@ -882,3 +882,9 @@ DEF_HELPER_FLAGS_4(mve_vcvt_sf, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
DEF_HELPER_FLAGS_4(mve_vcvt_uf, TCG_CALL_NO_WG, void, env, ptr, ptr, i32) DEF_HELPER_FLAGS_4(mve_vcvt_uf, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
DEF_HELPER_FLAGS_4(mve_vcvt_fs, TCG_CALL_NO_WG, void, env, ptr, ptr, i32) DEF_HELPER_FLAGS_4(mve_vcvt_fs, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
DEF_HELPER_FLAGS_4(mve_vcvt_fu, TCG_CALL_NO_WG, void, env, ptr, ptr, i32) DEF_HELPER_FLAGS_4(mve_vcvt_fu, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
DEF_HELPER_FLAGS_4(mve_vrint_rm_h, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
DEF_HELPER_FLAGS_4(mve_vrint_rm_s, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
DEF_HELPER_FLAGS_3(mve_vrintx_h, TCG_CALL_NO_WG, void, env, ptr, ptr)
DEF_HELPER_FLAGS_3(mve_vrintx_s, TCG_CALL_NO_WG, void, env, ptr, ptr)

View File

@ -823,3 +823,10 @@ VCVTPS 1111 1111 1 . 11 .. 11 ... 000 10 0 1 . 0 ... 0 @1op
VCVTPU 1111 1111 1 . 11 .. 11 ... 000 10 1 1 . 0 ... 0 @1op VCVTPU 1111 1111 1 . 11 .. 11 ... 000 10 1 1 . 0 ... 0 @1op
VCVTMS 1111 1111 1 . 11 .. 11 ... 000 11 0 1 . 0 ... 0 @1op VCVTMS 1111 1111 1 . 11 .. 11 ... 000 11 0 1 . 0 ... 0 @1op
VCVTMU 1111 1111 1 . 11 .. 11 ... 000 11 1 1 . 0 ... 0 @1op VCVTMU 1111 1111 1 . 11 .. 11 ... 000 11 1 1 . 0 ... 0 @1op
VRINTN 1111 1111 1 . 11 .. 10 ... 001 000 1 . 0 ... 0 @1op
VRINTX 1111 1111 1 . 11 .. 10 ... 001 001 1 . 0 ... 0 @1op
VRINTA 1111 1111 1 . 11 .. 10 ... 001 010 1 . 0 ... 0 @1op
VRINTZ 1111 1111 1 . 11 .. 10 ... 001 011 1 . 0 ... 0 @1op
VRINTM 1111 1111 1 . 11 .. 10 ... 001 101 1 . 0 ... 0 @1op
VRINTP 1111 1111 1 . 11 .. 10 ... 001 111 1 . 0 ... 0 @1op

View File

@ -3333,6 +3333,12 @@ DO_VCVT_RMODE(vcvt_rm_uh, 2, uint16_t, helper_vfp_touhh)
DO_VCVT_RMODE(vcvt_rm_ss, 4, uint32_t, helper_vfp_tosls) DO_VCVT_RMODE(vcvt_rm_ss, 4, uint32_t, helper_vfp_tosls)
DO_VCVT_RMODE(vcvt_rm_us, 4, uint32_t, helper_vfp_touls) DO_VCVT_RMODE(vcvt_rm_us, 4, uint32_t, helper_vfp_touls)
#define DO_VRINT_RM_H(M, F, S) helper_rinth(M, S)
#define DO_VRINT_RM_S(M, F, S) helper_rints(M, S)
DO_VCVT_RMODE(vrint_rm_h, 2, uint16_t, DO_VRINT_RM_H)
DO_VCVT_RMODE(vrint_rm_s, 4, uint32_t, DO_VRINT_RM_S)
/* /*
* VCVT between halfprec and singleprec. As usual for halfprec * VCVT between halfprec and singleprec. As usual for halfprec
* conversions, FZ16 is ignored and AHP is observed. * conversions, FZ16 is ignored and AHP is observed.
@ -3413,3 +3419,32 @@ void HELPER(mve_vcvtt_hs)(CPUARMState *env, void *vd, void *vm)
{ {
do_vcvt_hs(env, vd, vm, 1); do_vcvt_hs(env, vd, vm, 1);
} }
#define DO_1OP_FP(OP, ESIZE, TYPE, FN) \
void HELPER(glue(mve_, OP))(CPUARMState *env, void *vd, void *vm) \
{ \
TYPE *d = vd, *m = vm; \
TYPE r; \
uint16_t mask = mve_element_mask(env); \
unsigned e; \
float_status *fpst; \
float_status scratch_fpst; \
for (e = 0; e < 16 / ESIZE; e++, mask >>= ESIZE) { \
if ((mask & MAKE_64BIT_MASK(0, ESIZE)) == 0) { \
continue; \
} \
fpst = (ESIZE == 2) ? &env->vfp.standard_fp_status_f16 : \
&env->vfp.standard_fp_status; \
if (!(mask & 1)) { \
/* We need the result but without updating flags */ \
scratch_fpst = *fpst; \
fpst = &scratch_fpst; \
} \
r = FN(m[H##ESIZE(e)], fpst); \
mergemask(&d[H##ESIZE(e)], r, mask); \
} \
mve_advance_vpt(env); \
}
DO_1OP_FP(vrintx_h, 2, float16, float16_round_to_int)
DO_1OP_FP(vrintx_s, 4, float32, float32_round_to_int)

View File

@ -641,6 +641,51 @@ DO_VCVT_SH(VCVTT_SH, vcvtt_sh)
DO_VCVT_SH(VCVTB_HS, vcvtb_hs) DO_VCVT_SH(VCVTB_HS, vcvtb_hs)
DO_VCVT_SH(VCVTT_HS, vcvtt_hs) DO_VCVT_SH(VCVTT_HS, vcvtt_hs)
#define DO_VRINT(INSN, RMODE) \
static void gen_##INSN##h(TCGv_ptr env, TCGv_ptr qd, TCGv_ptr qm) \
{ \
gen_helper_mve_vrint_rm_h(env, qd, qm, \
tcg_constant_i32(arm_rmode_to_sf(RMODE))); \
} \
static void gen_##INSN##s(TCGv_ptr env, TCGv_ptr qd, TCGv_ptr qm) \
{ \
gen_helper_mve_vrint_rm_s(env, qd, qm, \
tcg_constant_i32(arm_rmode_to_sf(RMODE))); \
} \
static bool trans_##INSN(DisasContext *s, arg_1op *a) \
{ \
static MVEGenOneOpFn * const fns[] = { \
NULL, \
gen_##INSN##h, \
gen_##INSN##s, \
NULL, \
}; \
if (!dc_isar_feature(aa32_mve_fp, s)) { \
return false; \
} \
return do_1op(s, a, fns[a->size]); \
}
DO_VRINT(VRINTN, FPROUNDING_TIEEVEN)
DO_VRINT(VRINTA, FPROUNDING_TIEAWAY)
DO_VRINT(VRINTZ, FPROUNDING_ZERO)
DO_VRINT(VRINTM, FPROUNDING_NEGINF)
DO_VRINT(VRINTP, FPROUNDING_POSINF)
static bool trans_VRINTX(DisasContext *s, arg_1op *a)
{
static MVEGenOneOpFn * const fns[] = {
NULL,
gen_helper_mve_vrintx_h,
gen_helper_mve_vrintx_s,
NULL,
};
if (!dc_isar_feature(aa32_mve_fp, s)) {
return false;
}
return do_1op(s, a, fns[a->size]);
}
/* Narrowing moves: only size 0 and 1 are valid */ /* Narrowing moves: only size 0 and 1 are valid */
#define DO_VMOVN(INSN, FN) \ #define DO_VMOVN(INSN, FN) \
static bool trans_##INSN(DisasContext *s, arg_1op *a) \ static bool trans_##INSN(DisasContext *s, arg_1op *a) \