From 74a6af4e2384c3b4da071f6164ec08e71fe919d0 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Sun, 28 Feb 2021 05:15:38 -0500 Subject: [PATCH] target/arm: Implement VFP fp16 VCVT between float and fixed-point Implement the fp16 versions of the VFP VCVT instruction forms which convert between floating point and fixed-point. Backports a149e2de0b63e3906729ed1d3df7d9ecdb6de5e6 --- qemu/target/arm/translate-vfp.inc.c | 60 +++++++++++++++++++++++++++++ qemu/target/arm/vfp.decode | 2 + 2 files changed, 62 insertions(+) diff --git a/qemu/target/arm/translate-vfp.inc.c b/qemu/target/arm/translate-vfp.inc.c index c45a4460..3054c012 100644 --- a/qemu/target/arm/translate-vfp.inc.c +++ b/qemu/target/arm/translate-vfp.inc.c @@ -3023,6 +3023,66 @@ static bool trans_VJCVT(DisasContext *s, arg_VJCVT *a) return true; } +static bool trans_VCVT_fix_hp(DisasContext *s, arg_VCVT_fix_sp *a) +{ + TCGv_i32 vd, shift; + TCGv_ptr fpst; + int frac_bits; + TCGContext *tcg_ctx = s->uc->tcg_ctx; + + if (!dc_isar_feature(aa32_fp16_arith, s)) { + return false; + } + + if (!vfp_access_check(s)) { + return true; + } + + frac_bits = (a->opc & 1) ? (32 - a->imm) : (16 - a->imm); + + vd = tcg_temp_new_i32(tcg_ctx); + neon_load_reg32(s, vd, a->vd); + + fpst = fpstatus_ptr(tcg_ctx, FPST_FPCR_F16); + shift = tcg_const_i32(tcg_ctx, frac_bits); + + /* Switch on op:U:sx bits */ + switch (a->opc) { + case 0: + gen_helper_vfp_shtoh(tcg_ctx, vd, vd, shift, fpst); + break; + case 1: + gen_helper_vfp_sltoh(tcg_ctx, vd, vd, shift, fpst); + break; + case 2: + gen_helper_vfp_uhtoh(tcg_ctx, vd, vd, shift, fpst); + break; + case 3: + gen_helper_vfp_ultoh(tcg_ctx, vd, vd, shift, fpst); + break; + case 4: + gen_helper_vfp_toshh_round_to_zero(tcg_ctx, vd, vd, shift, fpst); + break; + case 5: + gen_helper_vfp_toslh_round_to_zero(tcg_ctx, vd, vd, shift, fpst); + break; + case 6: + gen_helper_vfp_touhh_round_to_zero(tcg_ctx, vd, vd, shift, fpst); + break; + case 7: + gen_helper_vfp_toulh_round_to_zero(tcg_ctx, vd, vd, shift, fpst); + break; + default: + g_assert_not_reached(); + } + + neon_store_reg32(s, vd, a->vd); + tcg_temp_free_i32(tcg_ctx, vd); + tcg_temp_free_i32(tcg_ctx, shift); + tcg_temp_free_ptr(tcg_ctx, fpst); + return true; +} + static bool trans_VCVT_fix_sp(DisasContext *s, arg_VCVT_fix_sp *a) { TCGContext *tcg_ctx = s->uc->tcg_ctx; diff --git a/qemu/target/arm/vfp.decode b/qemu/target/arm/vfp.decode index 642ec039..a8f1137b 100644 --- a/qemu/target/arm/vfp.decode +++ b/qemu/target/arm/vfp.decode @@ -225,6 +225,8 @@ VJCVT ---- 1110 1.11 1001 .... 1011 11.0 .... @vfp_dm_sd # We assemble bits 18 (op), 16 (u) and 7 (sx) into a single opc field # for the convenience of the trans_VCVT_fix functions. %vcvt_fix_op 18:1 16:1 7:1 +VCVT_fix_hp ---- 1110 1.11 1.1. .... 1001 .1.0 .... \ + vd=%vd_sp imm=%vm_sp opc=%vcvt_fix_op VCVT_fix_sp ---- 1110 1.11 1.1. .... 1010 .1.0 .... \ vd=%vd_sp imm=%vm_sp opc=%vcvt_fix_op VCVT_fix_dp ---- 1110 1.11 1.1. .... 1011 .1.0 .... \