@@ -2744,3 +2744,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)
@@ -1581,3 +1581,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
@@ -4696,6 +4696,58 @@ 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)
+{
+ if (float16_is_normal(a)) {
+ return extract16(a, 10, 5) - 15;
+ } else if (float16_is_infinity(a)) {
+ return INT16_MAX;
+ } else if (float16_is_any_nan(a) || float16_is_zero(a)) {
+ float_raise(float_flag_invalid, s);
+ return INT16_MIN;
+ } else {
+ /*
+ * denormal: bias - fractional_zeros
+ * = bias + masked_zeros - uint32_zeros
+ */
+ return -15 + 22 - clz32(extract16(a, 0, 10));
+ }
+}
+
+static int32_t do_float32_logb_as_int(float32 a, float_status *s)
+{
+ if (float32_is_normal(a)) {
+ return extract32(a, 23, 8) - 127;
+ } else if (float32_is_infinity(a)) {
+ return INT32_MAX;
+ } else if (float32_is_any_nan(a) || float32_is_zero(a)) {
+ float_raise(float_flag_invalid, s);
+ return INT32_MIN;
+ } else {
+ /* denormal (see above) */
+ return -127 + 9 - clz32(extract32(a, 0, 23));
+ }
+}
+
+static int64_t do_float64_logb_as_int(float64 a, float_status *s)
+{
+ if (float64_is_normal(a)) {
+ return extract64(a, 52, 11) - 1023;
+ } else if (float64_is_infinity(a)) {
+ return INT64_MAX;
+ } else if (float64_is_any_nan(a) || float64_is_zero(a)) {
+ float_raise(float_flag_invalid, s);
+ return INT64_MIN;
+ } else {
+ /* denormal (see above) */
+ return -1023 + 12 - clz64(extract64(a, 0, 52));
+ }
+}
+
+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,
@@ -8286,3 +8286,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;
+}