From c590ff441ce10f85149c48993696b5bf46627ee8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20Benn=C3=A9e?= Date: Thu, 8 Mar 2018 18:51:27 -0500 Subject: [PATCH] arm/translate-a64: add FP16 FNEG/FABS to simd_two_reg_misc_fp16 Neither of these operations alter the floating point status registers so we can do a pure bitwise operation, either squashing any sign bit (ABS) or inverting it (NEG). Backports commit 15f8a233c8c023dbc77b6fe6cd7c79eac9bee263 from qemu --- qemu/target/arm/translate-a64.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/qemu/target/arm/translate-a64.c b/qemu/target/arm/translate-a64.c index 1f72ed9d..398e3a15 100644 --- a/qemu/target/arm/translate-a64.c +++ b/qemu/target/arm/translate-a64.c @@ -11418,6 +11418,7 @@ static void disas_simd_two_reg_misc_fp16(DisasContext *s, uint32_t insn) TCGv_i32 tcg_rmode = NULL; TCGv_ptr tcg_fpstatus = NULL; bool need_rmode = false; + bool need_fpst = true; int rmode; if (!arm_dc_feature(s, ARM_FEATURE_V8_FP16)) { @@ -11536,6 +11537,10 @@ static void disas_simd_two_reg_misc_fp16(DisasContext *s, uint32_t insn) need_rmode = true; rmode = FPROUNDING_ZERO; break; + case 0x2f: /* FABS */ + case 0x6f: /* FNEG */ + need_fpst = false; + break; default: fprintf(stderr, "%s: insn %#04x fpop %#2x\n", __func__, insn, fpop); g_assert_not_reached(); @@ -11558,7 +11563,7 @@ static void disas_simd_two_reg_misc_fp16(DisasContext *s, uint32_t insn) return; } - if (need_rmode) { + if (need_rmode || need_fpst) { tcg_fpstatus = get_fpstatus_ptr(tcg_ctx, true); } @@ -11588,6 +11593,9 @@ static void disas_simd_two_reg_misc_fp16(DisasContext *s, uint32_t insn) case 0x7b: /* FCVTZU */ gen_helper_advsimd_f16touinth(tcg_ctx, tcg_res, tcg_op, tcg_fpstatus); break; + case 0x6f: /* FNEG */ + tcg_gen_xori_i32(tcg_ctx, tcg_res, tcg_op, 0x8000); + break; default: g_assert_not_reached(); } @@ -11631,6 +11639,12 @@ static void disas_simd_two_reg_misc_fp16(DisasContext *s, uint32_t insn) case 0x59: /* FRINTX */ gen_helper_advsimd_rinth_exact(tcg_ctx, tcg_res, tcg_op, tcg_fpstatus); break; + case 0x2f: /* FABS */ + tcg_gen_andi_i32(tcg_ctx, tcg_res, tcg_op, 0x7fff); + break; + case 0x6f: /* FNEG */ + tcg_gen_xori_i32(tcg_ctx, tcg_res, tcg_op, 0x8000); + break; default: g_assert_not_reached(); }