From 6e41113897e607c992cca59153bcd351f88647d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20Benn=C3=A9e?= Date: Thu, 8 Mar 2018 22:56:37 -0500 Subject: [PATCH] arm/translate-a64: add all single op FP16 to handle_fp_1src_half This includes FMOV, FABS, FNEG, FSQRT and FRINT[NPMZAXI]. We re-use existing helpers to achieve this. Backports commit c2c08713a6a5846bbe601d4d1b4f9708ba77efdc from qemu --- qemu/target/arm/translate-a64.c | 72 +++++++++++++++++++++++++++++++++ 1 file changed, 72 insertions(+) diff --git a/qemu/target/arm/translate-a64.c b/qemu/target/arm/translate-a64.c index 71b7a7d4..09ceb6fc 100644 --- a/qemu/target/arm/translate-a64.c +++ b/qemu/target/arm/translate-a64.c @@ -4690,6 +4690,66 @@ static void disas_fp_csel(DisasContext *s, uint32_t insn) tcg_temp_free_i64(tcg_ctx, t_true); } +/* Floating-point data-processing (1 source) - half precision */ +static void handle_fp_1src_half(DisasContext *s, int opcode, int rd, int rn) +{ + TCGContext *tcg_ctx = s->uc->tcg_ctx; + TCGv_ptr fpst = NULL; + TCGv_i32 tcg_op = tcg_temp_new_i32(tcg_ctx); + TCGv_i32 tcg_res = tcg_temp_new_i32(tcg_ctx); + + read_vec_element_i32(s, tcg_op, rn, 0, MO_16); + + switch (opcode) { + case 0x0: /* FMOV */ + tcg_gen_mov_i32(tcg_ctx, tcg_res, tcg_op); + break; + case 0x1: /* FABS */ + tcg_gen_andi_i32(tcg_ctx, tcg_res, tcg_op, 0x7fff); + break; + case 0x2: /* FNEG */ + tcg_gen_xori_i32(tcg_ctx, tcg_res, tcg_op, 0x8000); + break; + case 0x3: /* FSQRT */ + gen_helper_sqrt_f16(tcg_ctx, tcg_res, tcg_op, tcg_ctx->cpu_env); + break; + case 0x8: /* FRINTN */ + case 0x9: /* FRINTP */ + case 0xa: /* FRINTM */ + case 0xb: /* FRINTZ */ + case 0xc: /* FRINTA */ + { + TCGv_i32 tcg_rmode = tcg_const_i32(tcg_ctx, arm_rmode_to_sf(opcode & 7)); + fpst = get_fpstatus_ptr(tcg_ctx, true); + + gen_helper_set_rmode(tcg_ctx, tcg_rmode, tcg_rmode, fpst); + gen_helper_advsimd_rinth(tcg_ctx, tcg_res, tcg_op, fpst); + + gen_helper_set_rmode(tcg_ctx, tcg_rmode, tcg_rmode, fpst); + tcg_temp_free_i32(tcg_ctx, tcg_rmode); + break; + } + case 0xe: /* FRINTX */ + fpst = get_fpstatus_ptr(tcg_ctx, true); + gen_helper_advsimd_rinth_exact(tcg_ctx, tcg_res, tcg_op, fpst); + break; + case 0xf: /* FRINTI */ + fpst = get_fpstatus_ptr(tcg_ctx, true); + gen_helper_advsimd_rinth(tcg_ctx, tcg_res, tcg_op, fpst); + break; + default: + abort(); + } + + write_fp_sreg(s, rd, tcg_res); + + if (fpst) { + tcg_temp_free_ptr(tcg_ctx, fpst); + } + tcg_temp_free_i32(tcg_ctx, tcg_op); + tcg_temp_free_i32(tcg_ctx, tcg_res); +} + /* C3.6.25 Floating-point data-processing (1 source) - single precision */ static void handle_fp_1src_single(DisasContext *s, int opcode, int rd, int rn) { @@ -4922,6 +4982,18 @@ static void disas_fp_1src(DisasContext *s, uint32_t insn) handle_fp_1src_double(s, opcode, rd, rn); break; + case 3: + if (!arm_dc_feature(s, ARM_FEATURE_V8_FP16)) { + unallocated_encoding(s); + return; + } + + if (!fp_access_check(s)) { + return; + } + + handle_fp_1src_half(s, opcode, rd, rn); + break; default: unallocated_encoding(s); }