@@ -880,6 +880,43 @@ static void gen_vfp_ah_negd(TCGv_i64 d, TCGv_i64 s)
s, chs_s);
}
+/*
+ * These functions implement
+ * d = floatN_is_any_nan(s) ? s : floatN_abs(s)
+ * which for float32 is
+ * d = (s & ~(1 << 31)) > 0x7f800000UL) ? s : (s & ~(1 << 31))
+ * and similarly for the other float sizes.
+ */
+static void gen_vfp_ah_absh(TCGv_i32 d, TCGv_i32 s)
+{
+ TCGv_i32 abs_s = tcg_temp_new_i32();
+
+ gen_vfp_absh(abs_s, s);
+ tcg_gen_movcond_i32(TCG_COND_GTU, d,
+ abs_s, tcg_constant_i32(0x7c00),
+ s, abs_s);
+}
+
+static void gen_vfp_ah_abss(TCGv_i32 d, TCGv_i32 s)
+{
+ TCGv_i32 abs_s = tcg_temp_new_i32();
+
+ gen_vfp_abss(abs_s, s);
+ tcg_gen_movcond_i32(TCG_COND_GTU, d,
+ abs_s, tcg_constant_i32(0x7f800000UL),
+ s, abs_s);
+}
+
+static void gen_vfp_ah_absd(TCGv_i64 d, TCGv_i64 s)
+{
+ TCGv_i64 abs_s = tcg_temp_new_i64();
+
+ gen_vfp_absd(abs_s, s);
+ tcg_gen_movcond_i64(TCG_COND_GTU, d,
+ abs_s, tcg_constant_i64(0x7ff0000000000000ULL),
+ s, abs_s);
+}
+
static void gen_vfp_maybe_ah_negh(DisasContext *dc, TCGv_i32 d, TCGv_i32 s)
{
if (dc->fpcr_ah) {
@@ -5403,12 +5440,35 @@ static void gen_fabd_d(TCGv_i64 d, TCGv_i64 n, TCGv_i64 m, TCGv_ptr s)
gen_vfp_absd(d, d);
}
+static void gen_fabd_ah_h(TCGv_i32 d, TCGv_i32 n, TCGv_i32 m, TCGv_ptr s)
+{
+ gen_helper_vfp_subh(d, n, m, s);
+ gen_vfp_ah_absh(d, d);
+}
+
+static void gen_fabd_ah_s(TCGv_i32 d, TCGv_i32 n, TCGv_i32 m, TCGv_ptr s)
+{
+ gen_helper_vfp_subs(d, n, m, s);
+ gen_vfp_ah_abss(d, d);
+}
+
+static void gen_fabd_ah_d(TCGv_i64 d, TCGv_i64 n, TCGv_i64 m, TCGv_ptr s)
+{
+ gen_helper_vfp_subd(d, n, m, s);
+ gen_vfp_ah_absd(d, d);
+}
+
static const FPScalar f_scalar_fabd = {
gen_fabd_h,
gen_fabd_s,
gen_fabd_d,
};
-TRANS(FABD_s, do_fp3_scalar, a, &f_scalar_fabd, a->rn)
+static const FPScalar f_scalar_ah_fabd = {
+ gen_fabd_ah_h,
+ gen_fabd_ah_s,
+ gen_fabd_ah_d,
+};
+TRANS(FABD_s, do_fp3_scalar_2fn, a, &f_scalar_fabd, &f_scalar_ah_fabd, a->rn)
static const FPScalar f_scalar_frecps = {
gen_helper_recpsf_f16,
@@ -8654,7 +8714,12 @@ static const FPScalar1Int f_scalar_fabs = {
gen_vfp_abss,
gen_vfp_absd,
};
-TRANS(FABS_s, do_fp1_scalar_int, a, &f_scalar_fabs, true)
+static const FPScalar1Int f_scalar_ah_fabs = {
+ gen_vfp_ah_absh,
+ gen_vfp_ah_abss,
+ gen_vfp_ah_absd,
+};
+TRANS(FABS_s, do_fp1_scalar_int_2fn, a, &f_scalar_fabs, &f_scalar_ah_fabs)
static const FPScalar1Int f_scalar_fneg = {
gen_vfp_negh,