From 4850377f01712812fe87404c84c53053c99ff199 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Mon, 1 Mar 2021 16:31:32 -0500 Subject: [PATCH] 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. Backport e4a6d4a69e239becfd83bdcd996476e7b8e1138d --- qemu/aarch64.h | 1 + qemu/aarch64eb.h | 1 + qemu/arm.h | 1 + qemu/armeb.h | 1 + qemu/header_gen.py | 1 + qemu/m68k.h | 1 + qemu/mips.h | 1 + qemu/mips64.h | 1 + qemu/mips64el.h | 1 + qemu/mipsel.h | 1 + qemu/powerpc.h | 1 + qemu/riscv32.h | 1 + qemu/riscv64.h | 1 + qemu/sparc.h | 1 + qemu/sparc64.h | 1 + qemu/target/arm/helper.h | 1 + qemu/target/arm/translate-neon.inc.c | 36 +++++++++++++++------------- qemu/target/arm/vec_helper.c | 6 +++++ qemu/x86_64.h | 1 + 19 files changed, 42 insertions(+), 17 deletions(-) diff --git a/qemu/aarch64.h b/qemu/aarch64.h index dc8b9f0c..abcc30d9 100644 --- a/qemu/aarch64.h +++ b/qemu/aarch64.h @@ -1264,6 +1264,7 @@ #define helper_gvec_eq32 helper_gvec_eq32_aarch64 #define helper_gvec_eq64 helper_gvec_eq64_aarch64 #define helper_gvec_eqv helper_gvec_eqv_aarch64 +#define helper_gvec_fabd_h helper_gvec_fabd_h_aarch64 #define helper_gvec_fabd_s helper_gvec_fabd_s_aarch64 #define helper_gvec_fadd_d helper_gvec_fadd_d_aarch64 #define helper_gvec_fadd_h helper_gvec_fadd_h_aarch64 diff --git a/qemu/aarch64eb.h b/qemu/aarch64eb.h index 3a422b10..8e97c20c 100644 --- a/qemu/aarch64eb.h +++ b/qemu/aarch64eb.h @@ -1264,6 +1264,7 @@ #define helper_gvec_eq32 helper_gvec_eq32_aarch64eb #define helper_gvec_eq64 helper_gvec_eq64_aarch64eb #define helper_gvec_eqv helper_gvec_eqv_aarch64eb +#define helper_gvec_fabd_h helper_gvec_fabd_h_aarch64eb #define helper_gvec_fabd_s helper_gvec_fabd_s_aarch64eb #define helper_gvec_fadd_d helper_gvec_fadd_d_aarch64eb #define helper_gvec_fadd_h helper_gvec_fadd_h_aarch64eb diff --git a/qemu/arm.h b/qemu/arm.h index 85fee87c..b7f577d0 100644 --- a/qemu/arm.h +++ b/qemu/arm.h @@ -1264,6 +1264,7 @@ #define helper_gvec_eq32 helper_gvec_eq32_arm #define helper_gvec_eq64 helper_gvec_eq64_arm #define helper_gvec_eqv helper_gvec_eqv_arm +#define helper_gvec_fabd_h helper_gvec_fabd_h_arm #define helper_gvec_fabd_s helper_gvec_fabd_s_arm #define helper_gvec_fadd_d helper_gvec_fadd_d_arm #define helper_gvec_fadd_h helper_gvec_fadd_h_arm diff --git a/qemu/armeb.h b/qemu/armeb.h index b5f80beb..af5741ae 100644 --- a/qemu/armeb.h +++ b/qemu/armeb.h @@ -1264,6 +1264,7 @@ #define helper_gvec_eq32 helper_gvec_eq32_armeb #define helper_gvec_eq64 helper_gvec_eq64_armeb #define helper_gvec_eqv helper_gvec_eqv_armeb +#define helper_gvec_fabd_h helper_gvec_fabd_h_armeb #define helper_gvec_fabd_s helper_gvec_fabd_s_armeb #define helper_gvec_fadd_d helper_gvec_fadd_d_armeb #define helper_gvec_fadd_h helper_gvec_fadd_h_armeb diff --git a/qemu/header_gen.py b/qemu/header_gen.py index 54dbdc4e..542d0b9b 100644 --- a/qemu/header_gen.py +++ b/qemu/header_gen.py @@ -1270,6 +1270,7 @@ symbols = ( 'helper_gvec_eq32', 'helper_gvec_eq64', 'helper_gvec_eqv', + 'helper_gvec_fabd_h', 'helper_gvec_fabd_s', 'helper_gvec_fadd_d', 'helper_gvec_fadd_h', diff --git a/qemu/m68k.h b/qemu/m68k.h index 8a394307..012c0fca 100644 --- a/qemu/m68k.h +++ b/qemu/m68k.h @@ -1264,6 +1264,7 @@ #define helper_gvec_eq32 helper_gvec_eq32_m68k #define helper_gvec_eq64 helper_gvec_eq64_m68k #define helper_gvec_eqv helper_gvec_eqv_m68k +#define helper_gvec_fabd_h helper_gvec_fabd_h_m68k #define helper_gvec_fabd_s helper_gvec_fabd_s_m68k #define helper_gvec_fadd_d helper_gvec_fadd_d_m68k #define helper_gvec_fadd_h helper_gvec_fadd_h_m68k diff --git a/qemu/mips.h b/qemu/mips.h index 1ba6b8f8..70a338f2 100644 --- a/qemu/mips.h +++ b/qemu/mips.h @@ -1264,6 +1264,7 @@ #define helper_gvec_eq32 helper_gvec_eq32_mips #define helper_gvec_eq64 helper_gvec_eq64_mips #define helper_gvec_eqv helper_gvec_eqv_mips +#define helper_gvec_fabd_h helper_gvec_fabd_h_mips #define helper_gvec_fabd_s helper_gvec_fabd_s_mips #define helper_gvec_fadd_d helper_gvec_fadd_d_mips #define helper_gvec_fadd_h helper_gvec_fadd_h_mips diff --git a/qemu/mips64.h b/qemu/mips64.h index 5035e1a2..00f0eb07 100644 --- a/qemu/mips64.h +++ b/qemu/mips64.h @@ -1264,6 +1264,7 @@ #define helper_gvec_eq32 helper_gvec_eq32_mips64 #define helper_gvec_eq64 helper_gvec_eq64_mips64 #define helper_gvec_eqv helper_gvec_eqv_mips64 +#define helper_gvec_fabd_h helper_gvec_fabd_h_mips64 #define helper_gvec_fabd_s helper_gvec_fabd_s_mips64 #define helper_gvec_fadd_d helper_gvec_fadd_d_mips64 #define helper_gvec_fadd_h helper_gvec_fadd_h_mips64 diff --git a/qemu/mips64el.h b/qemu/mips64el.h index c39ca800..61656687 100644 --- a/qemu/mips64el.h +++ b/qemu/mips64el.h @@ -1264,6 +1264,7 @@ #define helper_gvec_eq32 helper_gvec_eq32_mips64el #define helper_gvec_eq64 helper_gvec_eq64_mips64el #define helper_gvec_eqv helper_gvec_eqv_mips64el +#define helper_gvec_fabd_h helper_gvec_fabd_h_mips64el #define helper_gvec_fabd_s helper_gvec_fabd_s_mips64el #define helper_gvec_fadd_d helper_gvec_fadd_d_mips64el #define helper_gvec_fadd_h helper_gvec_fadd_h_mips64el diff --git a/qemu/mipsel.h b/qemu/mipsel.h index 35737e6e..0b867e52 100644 --- a/qemu/mipsel.h +++ b/qemu/mipsel.h @@ -1264,6 +1264,7 @@ #define helper_gvec_eq32 helper_gvec_eq32_mipsel #define helper_gvec_eq64 helper_gvec_eq64_mipsel #define helper_gvec_eqv helper_gvec_eqv_mipsel +#define helper_gvec_fabd_h helper_gvec_fabd_h_mipsel #define helper_gvec_fabd_s helper_gvec_fabd_s_mipsel #define helper_gvec_fadd_d helper_gvec_fadd_d_mipsel #define helper_gvec_fadd_h helper_gvec_fadd_h_mipsel diff --git a/qemu/powerpc.h b/qemu/powerpc.h index 9bdd0ecb..94be24e8 100644 --- a/qemu/powerpc.h +++ b/qemu/powerpc.h @@ -1264,6 +1264,7 @@ #define helper_gvec_eq32 helper_gvec_eq32_powerpc #define helper_gvec_eq64 helper_gvec_eq64_powerpc #define helper_gvec_eqv helper_gvec_eqv_powerpc +#define helper_gvec_fabd_h helper_gvec_fabd_h_powerpc #define helper_gvec_fabd_s helper_gvec_fabd_s_powerpc #define helper_gvec_fadd_d helper_gvec_fadd_d_powerpc #define helper_gvec_fadd_h helper_gvec_fadd_h_powerpc diff --git a/qemu/riscv32.h b/qemu/riscv32.h index 11529ebb..730a148f 100644 --- a/qemu/riscv32.h +++ b/qemu/riscv32.h @@ -1264,6 +1264,7 @@ #define helper_gvec_eq32 helper_gvec_eq32_riscv32 #define helper_gvec_eq64 helper_gvec_eq64_riscv32 #define helper_gvec_eqv helper_gvec_eqv_riscv32 +#define helper_gvec_fabd_h helper_gvec_fabd_h_riscv32 #define helper_gvec_fabd_s helper_gvec_fabd_s_riscv32 #define helper_gvec_fadd_d helper_gvec_fadd_d_riscv32 #define helper_gvec_fadd_h helper_gvec_fadd_h_riscv32 diff --git a/qemu/riscv64.h b/qemu/riscv64.h index 5fcccaf0..1108db0d 100644 --- a/qemu/riscv64.h +++ b/qemu/riscv64.h @@ -1264,6 +1264,7 @@ #define helper_gvec_eq32 helper_gvec_eq32_riscv64 #define helper_gvec_eq64 helper_gvec_eq64_riscv64 #define helper_gvec_eqv helper_gvec_eqv_riscv64 +#define helper_gvec_fabd_h helper_gvec_fabd_h_riscv64 #define helper_gvec_fabd_s helper_gvec_fabd_s_riscv64 #define helper_gvec_fadd_d helper_gvec_fadd_d_riscv64 #define helper_gvec_fadd_h helper_gvec_fadd_h_riscv64 diff --git a/qemu/sparc.h b/qemu/sparc.h index f1ff004c..492c3fb2 100644 --- a/qemu/sparc.h +++ b/qemu/sparc.h @@ -1264,6 +1264,7 @@ #define helper_gvec_eq32 helper_gvec_eq32_sparc #define helper_gvec_eq64 helper_gvec_eq64_sparc #define helper_gvec_eqv helper_gvec_eqv_sparc +#define helper_gvec_fabd_h helper_gvec_fabd_h_sparc #define helper_gvec_fabd_s helper_gvec_fabd_s_sparc #define helper_gvec_fadd_d helper_gvec_fadd_d_sparc #define helper_gvec_fadd_h helper_gvec_fadd_h_sparc diff --git a/qemu/sparc64.h b/qemu/sparc64.h index 5f830f4f..0e9eef2d 100644 --- a/qemu/sparc64.h +++ b/qemu/sparc64.h @@ -1264,6 +1264,7 @@ #define helper_gvec_eq32 helper_gvec_eq32_sparc64 #define helper_gvec_eq64 helper_gvec_eq64_sparc64 #define helper_gvec_eqv helper_gvec_eqv_sparc64 +#define helper_gvec_fabd_h helper_gvec_fabd_h_sparc64 #define helper_gvec_fabd_s helper_gvec_fabd_s_sparc64 #define helper_gvec_fadd_d helper_gvec_fadd_d_sparc64 #define helper_gvec_fadd_h helper_gvec_fadd_h_sparc64 diff --git a/qemu/target/arm/helper.h b/qemu/target/arm/helper.h index a40e3445..67535b18 100644 --- a/qemu/target/arm/helper.h +++ b/qemu/target/arm/helper.h @@ -627,6 +627,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/qemu/target/arm/translate-neon.inc.c b/qemu/target/arm/translate-neon.inc.c index 4ef3d846..ad78d01e 100644 --- a/qemu/target/arm/translate-neon.inc.c +++ b/qemu/target/arm/translate-neon.inc.c @@ -1101,34 +1101,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(TCGContext *s, 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(TCGContext *s, 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(s, FPST_STD); \ + TCGv_ptr fpst = fpstatus_ptr(s, FPST); \ tcg_gen_gvec_3_ptr(s, rd_ofs, rn_ofs, rm_ofs, fpst, \ oprsz, maxsz, 0, FUNC); \ tcg_temp_free_ptr(s, 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/qemu/target/arm/vec_helper.c b/qemu/target/arm/vec_helper.c index 7e3a60f6..8625303e 100644 --- a/qemu/target/arm/vec_helper.c +++ b/qemu/target/arm/vec_helper.c @@ -708,6 +708,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)); @@ -740,6 +745,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 diff --git a/qemu/x86_64.h b/qemu/x86_64.h index 427f705c..8183a7e9 100644 --- a/qemu/x86_64.h +++ b/qemu/x86_64.h @@ -1264,6 +1264,7 @@ #define helper_gvec_eq32 helper_gvec_eq32_x86_64 #define helper_gvec_eq64 helper_gvec_eq64_x86_64 #define helper_gvec_eqv helper_gvec_eqv_x86_64 +#define helper_gvec_fabd_h helper_gvec_fabd_h_x86_64 #define helper_gvec_fabd_s helper_gvec_fabd_s_x86_64 #define helper_gvec_fadd_d helper_gvec_fadd_d_x86_64 #define helper_gvec_fadd_h helper_gvec_fadd_h_x86_64