target/arm: Implement SVE2 FLOGB

Signed-off-by: Stephen Long <steplong@quicinc.com>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Message-id: 20210525010358.152808-76-richard.henderson@linaro.org
Message-Id: <20200430191405.21641-1-steplong@quicinc.com>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
Stephen Long 2021-05-24 18:03:41 -07:00 committed by Peter Maydell
parent 9536527731
commit 631be02e29
4 changed files with 119 additions and 0 deletions

View File

@ -2754,3 +2754,7 @@ DEF_HELPER_FLAGS_5(sve2_fcvtlt_hs, TCG_CALL_NO_RWG,
void, ptr, ptr, ptr, ptr, i32)
DEF_HELPER_FLAGS_5(sve2_fcvtlt_sd, TCG_CALL_NO_RWG,
void, ptr, ptr, ptr, ptr, i32)
DEF_HELPER_FLAGS_5(flogb_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
DEF_HELPER_FLAGS_5(flogb_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
DEF_HELPER_FLAGS_5(flogb_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)

View File

@ -1588,3 +1588,6 @@ FCVTNT_sh 01100100 10 0010 00 101 ... ..... ..... @rd_pg_rn_e0
FCVTLT_hs 01100100 10 0010 01 101 ... ..... ..... @rd_pg_rn_e0
FCVTNT_ds 01100100 11 0010 10 101 ... ..... ..... @rd_pg_rn_e0
FCVTLT_sd 01100100 11 0010 11 101 ... ..... ..... @rd_pg_rn_e0
### SVE2 floating-point convert to integer
FLOGB 01100101 00 011 esz:2 0101 pg:3 rn:5 rd:5 &rpr_esz

View File

@ -4729,6 +4729,94 @@ DO_ZPZ_FP(sve_ucvt_dh, uint64_t, , uint64_to_float16)
DO_ZPZ_FP(sve_ucvt_ds, uint64_t, , uint64_to_float32)
DO_ZPZ_FP(sve_ucvt_dd, uint64_t, , uint64_to_float64)
static int16_t do_float16_logb_as_int(float16 a, float_status *s)
{
/* Extract frac to the top of the uint32_t. */
uint32_t frac = (uint32_t)a << (16 + 6);
int16_t exp = extract32(a, 10, 5);
if (unlikely(exp == 0)) {
if (frac != 0) {
if (!get_flush_inputs_to_zero(s)) {
/* denormal: bias - fractional_zeros */
return -15 - clz32(frac);
}
/* flush to zero */
float_raise(float_flag_input_denormal, s);
}
} else if (unlikely(exp == 0x1f)) {
if (frac == 0) {
return INT16_MAX; /* infinity */
}
} else {
/* normal: exp - bias */
return exp - 15;
}
/* nan or zero */
float_raise(float_flag_invalid, s);
return INT16_MIN;
}
static int32_t do_float32_logb_as_int(float32 a, float_status *s)
{
/* Extract frac to the top of the uint32_t. */
uint32_t frac = a << 9;
int32_t exp = extract32(a, 23, 8);
if (unlikely(exp == 0)) {
if (frac != 0) {
if (!get_flush_inputs_to_zero(s)) {
/* denormal: bias - fractional_zeros */
return -127 - clz32(frac);
}
/* flush to zero */
float_raise(float_flag_input_denormal, s);
}
} else if (unlikely(exp == 0xff)) {
if (frac == 0) {
return INT32_MAX; /* infinity */
}
} else {
/* normal: exp - bias */
return exp - 127;
}
/* nan or zero */
float_raise(float_flag_invalid, s);
return INT32_MIN;
}
static int64_t do_float64_logb_as_int(float64 a, float_status *s)
{
/* Extract frac to the top of the uint64_t. */
uint64_t frac = a << 12;
int64_t exp = extract64(a, 52, 11);
if (unlikely(exp == 0)) {
if (frac != 0) {
if (!get_flush_inputs_to_zero(s)) {
/* denormal: bias - fractional_zeros */
return -1023 - clz64(frac);
}
/* flush to zero */
float_raise(float_flag_input_denormal, s);
}
} else if (unlikely(exp == 0x7ff)) {
if (frac == 0) {
return INT64_MAX; /* infinity */
}
} else {
/* normal: exp - bias */
return exp - 1023;
}
/* nan or zero */
float_raise(float_flag_invalid, s);
return INT64_MIN;
}
DO_ZPZ_FP(flogb_h, float16, H1_2, do_float16_logb_as_int)
DO_ZPZ_FP(flogb_s, float32, H1_4, do_float32_logb_as_int)
DO_ZPZ_FP(flogb_d, float64, , do_float64_logb_as_int)
#undef DO_ZPZ_FP
static void do_fmla_zpzzz_h(void *vd, void *vn, void *vm, void *va, void *vg,

View File

@ -8307,3 +8307,27 @@ static bool trans_FCVTXNT_ds(DisasContext *s, arg_rpr_esz *a)
}
return do_frint_mode(s, a, float_round_to_odd, gen_helper_sve2_fcvtnt_ds);
}
static bool trans_FLOGB(DisasContext *s, arg_rpr_esz *a)
{
static gen_helper_gvec_3_ptr * const fns[] = {
NULL, gen_helper_flogb_h,
gen_helper_flogb_s, gen_helper_flogb_d
};
if (!dc_isar_feature(aa64_sve2, s) || fns[a->esz] == NULL) {
return false;
}
if (sve_access_check(s)) {
TCGv_ptr status =
fpstatus_ptr(a->esz == MO_16 ? FPST_FPCR_F16 : FPST_FPCR);
unsigned vsz = vec_full_reg_size(s);
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, fns[a->esz]);
tcg_temp_free_ptr(status);
}
return true;
}