aboutsummaryrefslogtreecommitdiff
path: root/target/arm
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2020-08-28 19:33:24 +0100
committerPeter Maydell <peter.maydell@linaro.org>2020-09-01 11:19:32 +0100
commita149e2de0b63e3906729ed1d3df7d9ecdb6de5e6 (patch)
tree0c7a5d7d6c418e21489afabe7cb7ec472978ab3f /target/arm
parent414ba270c4fb758d987adf37ae9bfe531715c604 (diff)
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. Signed-off-by: Peter Maydell <peter.maydell@linaro.org> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20200828183354.27913-16-peter.maydell@linaro.org
Diffstat (limited to 'target/arm')
-rw-r--r--target/arm/translate-vfp.c.inc59
-rw-r--r--target/arm/vfp.decode2
2 files changed, 61 insertions, 0 deletions
diff --git a/target/arm/translate-vfp.c.inc b/target/arm/translate-vfp.c.inc
index 0140822d18..fdf486b7c1 100644
--- a/target/arm/translate-vfp.c.inc
+++ b/target/arm/translate-vfp.c.inc
@@ -2972,6 +2972,65 @@ 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;
+
+ 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();
+ neon_load_reg32(vd, a->vd);
+
+ fpst = fpstatus_ptr(FPST_FPCR_F16);
+ shift = tcg_const_i32(frac_bits);
+
+ /* Switch on op:U:sx bits */
+ switch (a->opc) {
+ case 0:
+ gen_helper_vfp_shtoh(vd, vd, shift, fpst);
+ break;
+ case 1:
+ gen_helper_vfp_sltoh(vd, vd, shift, fpst);
+ break;
+ case 2:
+ gen_helper_vfp_uhtoh(vd, vd, shift, fpst);
+ break;
+ case 3:
+ gen_helper_vfp_ultoh(vd, vd, shift, fpst);
+ break;
+ case 4:
+ gen_helper_vfp_toshh_round_to_zero(vd, vd, shift, fpst);
+ break;
+ case 5:
+ gen_helper_vfp_toslh_round_to_zero(vd, vd, shift, fpst);
+ break;
+ case 6:
+ gen_helper_vfp_touhh_round_to_zero(vd, vd, shift, fpst);
+ break;
+ case 7:
+ gen_helper_vfp_toulh_round_to_zero(vd, vd, shift, fpst);
+ break;
+ default:
+ g_assert_not_reached();
+ }
+
+ neon_store_reg32(vd, a->vd);
+ tcg_temp_free_i32(vd);
+ tcg_temp_free_i32(shift);
+ tcg_temp_free_ptr(fpst);
+ return true;
+}
+
static bool trans_VCVT_fix_sp(DisasContext *s, arg_VCVT_fix_sp *a)
{
TCGv_i32 vd, shift;
diff --git a/target/arm/vfp.decode b/target/arm/vfp.decode
index 642ec039e3..a8f1137be1 100644
--- a/target/arm/vfp.decode
+++ b/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 .... \