diff options
author | Peter Maydell | 2020-08-28 20:33:32 +0200 |
---|---|---|
committer | Peter Maydell | 2020-09-01 12:19:32 +0200 |
commit | e4a6d4a69e239becfd83bdcd996476e7b8e1138d (patch) | |
tree | 21431394aad0edec16f00c7ec88302a6fcbc8c6a | |
parent | target/arm: Implement VFP fp16 VMOV between gp and halfprec registers (diff) | |
download | qemu-e4a6d4a69e239becfd83bdcd996476e7b8e1138d.tar.gz qemu-e4a6d4a69e239becfd83bdcd996476e7b8e1138d.tar.xz qemu-e4a6d4a69e239becfd83bdcd996476e7b8e1138d.zip |
target/arm: Implement FP16 for Neon VADD, VSUB, VABD, VMUL
Implement FP16 support for the Neon insns which use the DO_3S_FP_GVEC
macro: VADD, VSUB, VABD, VMUL.
For VABD this requires us to implement a new gvec_fabd_h helper
using the machinery we have already for the other helpers.
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Message-id: 20200828183354.27913-24-peter.maydell@linaro.org
-rw-r--r-- | target/arm/helper.h | 1 | ||||
-rw-r--r-- | target/arm/translate-neon.c.inc | 36 | ||||
-rw-r--r-- | target/arm/vec_helper.c | 6 |
3 files changed, 26 insertions, 17 deletions
diff --git a/target/arm/helper.h b/target/arm/helper.h index f5ad5088bf..aa1ac75571 100644 --- a/target/arm/helper.h +++ b/target/arm/helper.h @@ -629,6 +629,7 @@ DEF_HELPER_FLAGS_5(gvec_fmul_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32) DEF_HELPER_FLAGS_5(gvec_fmul_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32) DEF_HELPER_FLAGS_5(gvec_fmul_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32) +DEF_HELPER_FLAGS_5(gvec_fabd_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32) DEF_HELPER_FLAGS_5(gvec_fabd_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32) DEF_HELPER_FLAGS_5(gvec_ftsmul_h, TCG_CALL_NO_RWG, diff --git a/target/arm/translate-neon.c.inc b/target/arm/translate-neon.c.inc index 9879731a52..9d0959517f 100644 --- a/target/arm/translate-neon.c.inc +++ b/target/arm/translate-neon.c.inc @@ -1082,34 +1082,36 @@ static bool do_3same_fp(DisasContext *s, arg_3same *a, VFPGen3OpSPFn *fn, return true; } -/* - * For all the functions using this macro, size == 1 means fp16, - * which is an architecture extension we don't implement yet. - */ -#define DO_3S_FP_GVEC(INSN,FUNC) \ - static void gen_##INSN##_3s(unsigned vece, uint32_t rd_ofs, \ - uint32_t rn_ofs, uint32_t rm_ofs, \ - uint32_t oprsz, uint32_t maxsz) \ +#define WRAP_FP_GVEC(WRAPNAME, FPST, FUNC) \ + static void WRAPNAME(unsigned vece, uint32_t rd_ofs, \ + uint32_t rn_ofs, uint32_t rm_ofs, \ + uint32_t oprsz, uint32_t maxsz) \ { \ - TCGv_ptr fpst = fpstatus_ptr(FPST_STD); \ + TCGv_ptr fpst = fpstatus_ptr(FPST); \ tcg_gen_gvec_3_ptr(rd_ofs, rn_ofs, rm_ofs, fpst, \ oprsz, maxsz, 0, FUNC); \ tcg_temp_free_ptr(fpst); \ - } \ + } + +#define DO_3S_FP_GVEC(INSN,SFUNC,HFUNC) \ + WRAP_FP_GVEC(gen_##INSN##_fp32_3s, FPST_STD, SFUNC) \ + WRAP_FP_GVEC(gen_##INSN##_fp16_3s, FPST_STD_F16, HFUNC) \ static bool trans_##INSN##_fp_3s(DisasContext *s, arg_3same *a) \ { \ if (a->size != 0) { \ - /* TODO fp16 support */ \ - return false; \ + if (!dc_isar_feature(aa32_fp16_arith, s)) { \ + return false; \ + } \ + return do_3same(s, a, gen_##INSN##_fp16_3s); \ } \ - return do_3same(s, a, gen_##INSN##_3s); \ + return do_3same(s, a, gen_##INSN##_fp32_3s); \ } -DO_3S_FP_GVEC(VADD, gen_helper_gvec_fadd_s) -DO_3S_FP_GVEC(VSUB, gen_helper_gvec_fsub_s) -DO_3S_FP_GVEC(VABD, gen_helper_gvec_fabd_s) -DO_3S_FP_GVEC(VMUL, gen_helper_gvec_fmul_s) +DO_3S_FP_GVEC(VADD, gen_helper_gvec_fadd_s, gen_helper_gvec_fadd_h) +DO_3S_FP_GVEC(VSUB, gen_helper_gvec_fsub_s, gen_helper_gvec_fsub_h) +DO_3S_FP_GVEC(VABD, gen_helper_gvec_fabd_s, gen_helper_gvec_fabd_h) +DO_3S_FP_GVEC(VMUL, gen_helper_gvec_fmul_s, gen_helper_gvec_fmul_h) /* * For all the functions using this macro, size == 1 means fp16, diff --git a/target/arm/vec_helper.c b/target/arm/vec_helper.c index a6c53d2ab6..988d5784e8 100644 --- a/target/arm/vec_helper.c +++ b/target/arm/vec_helper.c @@ -707,6 +707,11 @@ static float64 float64_ftsmul(float64 op1, uint64_t op2, float_status *stat) return result; } +static float16 float16_abd(float16 op1, float16 op2, float_status *stat) +{ + return float16_abs(float16_sub(op1, op2, stat)); +} + static float32 float32_abd(float32 op1, float32 op2, float_status *stat) { return float32_abs(float32_sub(op1, op2, stat)); @@ -739,6 +744,7 @@ DO_3OP(gvec_ftsmul_h, float16_ftsmul, float16) DO_3OP(gvec_ftsmul_s, float32_ftsmul, float32) DO_3OP(gvec_ftsmul_d, float64_ftsmul, float64) +DO_3OP(gvec_fabd_h, float16_abd, float16) DO_3OP(gvec_fabd_s, float32_abd, float32) #ifdef TARGET_AARCH64 |