diff --git a/qemu/aarch64.h b/qemu/aarch64.h index ba5ad03c..6ce3114c 100644 --- a/qemu/aarch64.h +++ b/qemu/aarch64.h @@ -993,6 +993,9 @@ #define helper_gvec_eq16 helper_gvec_eq16_aarch64 #define helper_gvec_eq32 helper_gvec_eq32_aarch64 #define helper_gvec_eq64 helper_gvec_eq64_aarch64 +#define helper_gvec_fcaddh helper_gvec_fcaddh_aarch64 +#define helper_gvec_fcadds helper_gvec_fcadds_aarch64 +#define helper_gvec_fcaddd helper_gvec_fcaddd_aarch64 #define helper_gvec_le8 helper_gvec_le8_aarch64 #define helper_gvec_le16 helper_gvec_le16_aarch64 #define helper_gvec_le32 helper_gvec_le32_aarch64 diff --git a/qemu/aarch64eb.h b/qemu/aarch64eb.h index c4aec7a7..1635d33e 100644 --- a/qemu/aarch64eb.h +++ b/qemu/aarch64eb.h @@ -993,6 +993,9 @@ #define helper_gvec_eq16 helper_gvec_eq16_aarch64eb #define helper_gvec_eq32 helper_gvec_eq32_aarch64eb #define helper_gvec_eq64 helper_gvec_eq64_aarch64eb +#define helper_gvec_fcaddh helper_gvec_fcaddh_aarch64eb +#define helper_gvec_fcadds helper_gvec_fcadds_aarch64eb +#define helper_gvec_fcaddd helper_gvec_fcaddd_aarch64eb #define helper_gvec_le8 helper_gvec_le8_aarch64eb #define helper_gvec_le16 helper_gvec_le16_aarch64eb #define helper_gvec_le32 helper_gvec_le32_aarch64eb diff --git a/qemu/arm.h b/qemu/arm.h index 71f84cb9..13a859bb 100644 --- a/qemu/arm.h +++ b/qemu/arm.h @@ -993,6 +993,9 @@ #define helper_gvec_eq16 helper_gvec_eq16_arm #define helper_gvec_eq32 helper_gvec_eq32_arm #define helper_gvec_eq64 helper_gvec_eq64_arm +#define helper_gvec_fcaddh helper_gvec_fcaddh_arm +#define helper_gvec_fcadds helper_gvec_fcadds_arm +#define helper_gvec_fcaddd helper_gvec_fcaddd_arm #define helper_gvec_le8 helper_gvec_le8_arm #define helper_gvec_le16 helper_gvec_le16_arm #define helper_gvec_le32 helper_gvec_le32_arm diff --git a/qemu/armeb.h b/qemu/armeb.h index 9b4795ef..afef33cc 100644 --- a/qemu/armeb.h +++ b/qemu/armeb.h @@ -993,6 +993,9 @@ #define helper_gvec_eq16 helper_gvec_eq16_armeb #define helper_gvec_eq32 helper_gvec_eq32_armeb #define helper_gvec_eq64 helper_gvec_eq64_armeb +#define helper_gvec_fcaddh helper_gvec_fcaddh_armeb +#define helper_gvec_fcadds helper_gvec_fcadds_armeb +#define helper_gvec_fcaddd helper_gvec_fcaddd_armeb #define helper_gvec_le8 helper_gvec_le8_armeb #define helper_gvec_le16 helper_gvec_le16_armeb #define helper_gvec_le32 helper_gvec_le32_armeb diff --git a/qemu/header_gen.py b/qemu/header_gen.py index 36481c54..4b5e4491 100644 --- a/qemu/header_gen.py +++ b/qemu/header_gen.py @@ -999,6 +999,9 @@ symbols = ( 'helper_gvec_eq16', 'helper_gvec_eq32', 'helper_gvec_eq64', + 'helper_gvec_fcaddh', + 'helper_gvec_fcadds', + 'helper_gvec_fcaddd', 'helper_gvec_le8', 'helper_gvec_le16', 'helper_gvec_le32', diff --git a/qemu/m68k.h b/qemu/m68k.h index 95eda856..0c2ae9d8 100644 --- a/qemu/m68k.h +++ b/qemu/m68k.h @@ -993,6 +993,9 @@ #define helper_gvec_eq16 helper_gvec_eq16_m68k #define helper_gvec_eq32 helper_gvec_eq32_m68k #define helper_gvec_eq64 helper_gvec_eq64_m68k +#define helper_gvec_fcaddh helper_gvec_fcaddh_m68k +#define helper_gvec_fcadds helper_gvec_fcadds_m68k +#define helper_gvec_fcaddd helper_gvec_fcaddd_m68k #define helper_gvec_le8 helper_gvec_le8_m68k #define helper_gvec_le16 helper_gvec_le16_m68k #define helper_gvec_le32 helper_gvec_le32_m68k diff --git a/qemu/mips.h b/qemu/mips.h index 13758cc5..b804ab95 100644 --- a/qemu/mips.h +++ b/qemu/mips.h @@ -993,6 +993,9 @@ #define helper_gvec_eq16 helper_gvec_eq16_mips #define helper_gvec_eq32 helper_gvec_eq32_mips #define helper_gvec_eq64 helper_gvec_eq64_mips +#define helper_gvec_fcaddh helper_gvec_fcaddh_mips +#define helper_gvec_fcadds helper_gvec_fcadds_mips +#define helper_gvec_fcaddd helper_gvec_fcaddd_mips #define helper_gvec_le8 helper_gvec_le8_mips #define helper_gvec_le16 helper_gvec_le16_mips #define helper_gvec_le32 helper_gvec_le32_mips diff --git a/qemu/mips64.h b/qemu/mips64.h index 4538eabd..11aec618 100644 --- a/qemu/mips64.h +++ b/qemu/mips64.h @@ -993,6 +993,9 @@ #define helper_gvec_eq16 helper_gvec_eq16_mips64 #define helper_gvec_eq32 helper_gvec_eq32_mips64 #define helper_gvec_eq64 helper_gvec_eq64_mips64 +#define helper_gvec_fcaddh helper_gvec_fcaddh_mips64 +#define helper_gvec_fcadds helper_gvec_fcadds_mips64 +#define helper_gvec_fcaddd helper_gvec_fcaddd_mips64 #define helper_gvec_le8 helper_gvec_le8_mips64 #define helper_gvec_le16 helper_gvec_le16_mips64 #define helper_gvec_le32 helper_gvec_le32_mips64 diff --git a/qemu/mips64el.h b/qemu/mips64el.h index aa2d225b..d7e7aede 100644 --- a/qemu/mips64el.h +++ b/qemu/mips64el.h @@ -993,6 +993,9 @@ #define helper_gvec_eq16 helper_gvec_eq16_mips64el #define helper_gvec_eq32 helper_gvec_eq32_mips64el #define helper_gvec_eq64 helper_gvec_eq64_mips64el +#define helper_gvec_fcaddh helper_gvec_fcaddh_mips64el +#define helper_gvec_fcadds helper_gvec_fcadds_mips64el +#define helper_gvec_fcaddd helper_gvec_fcaddd_mips64el #define helper_gvec_le8 helper_gvec_le8_mips64el #define helper_gvec_le16 helper_gvec_le16_mips64el #define helper_gvec_le32 helper_gvec_le32_mips64el diff --git a/qemu/mipsel.h b/qemu/mipsel.h index 8495d5a2..faf1b25e 100644 --- a/qemu/mipsel.h +++ b/qemu/mipsel.h @@ -993,6 +993,9 @@ #define helper_gvec_eq16 helper_gvec_eq16_mipsel #define helper_gvec_eq32 helper_gvec_eq32_mipsel #define helper_gvec_eq64 helper_gvec_eq64_mipsel +#define helper_gvec_fcaddh helper_gvec_fcaddh_mipsel +#define helper_gvec_fcadds helper_gvec_fcadds_mipsel +#define helper_gvec_fcaddd helper_gvec_fcaddd_mipsel #define helper_gvec_le8 helper_gvec_le8_mipsel #define helper_gvec_le16 helper_gvec_le16_mipsel #define helper_gvec_le32 helper_gvec_le32_mipsel diff --git a/qemu/powerpc.h b/qemu/powerpc.h index b7fed034..45196045 100644 --- a/qemu/powerpc.h +++ b/qemu/powerpc.h @@ -993,6 +993,9 @@ #define helper_gvec_eq16 helper_gvec_eq16_powerpc #define helper_gvec_eq32 helper_gvec_eq32_powerpc #define helper_gvec_eq64 helper_gvec_eq64_powerpc +#define helper_gvec_fcaddh helper_gvec_fcaddh_powerpc +#define helper_gvec_fcadds helper_gvec_fcadds_powerpc +#define helper_gvec_fcaddd helper_gvec_fcaddd_powerpc #define helper_gvec_le8 helper_gvec_le8_powerpc #define helper_gvec_le16 helper_gvec_le16_powerpc #define helper_gvec_le32 helper_gvec_le32_powerpc diff --git a/qemu/sparc.h b/qemu/sparc.h index 37bc689c..1f3c836f 100644 --- a/qemu/sparc.h +++ b/qemu/sparc.h @@ -993,6 +993,9 @@ #define helper_gvec_eq16 helper_gvec_eq16_sparc #define helper_gvec_eq32 helper_gvec_eq32_sparc #define helper_gvec_eq64 helper_gvec_eq64_sparc +#define helper_gvec_fcaddh helper_gvec_fcaddh_sparc +#define helper_gvec_fcadds helper_gvec_fcadds_sparc +#define helper_gvec_fcaddd helper_gvec_fcaddd_sparc #define helper_gvec_le8 helper_gvec_le8_sparc #define helper_gvec_le16 helper_gvec_le16_sparc #define helper_gvec_le32 helper_gvec_le32_sparc diff --git a/qemu/sparc64.h b/qemu/sparc64.h index 24449419..43d36482 100644 --- a/qemu/sparc64.h +++ b/qemu/sparc64.h @@ -993,6 +993,9 @@ #define helper_gvec_eq16 helper_gvec_eq16_sparc64 #define helper_gvec_eq32 helper_gvec_eq32_sparc64 #define helper_gvec_eq64 helper_gvec_eq64_sparc64 +#define helper_gvec_fcaddh helper_gvec_fcaddh_sparc64 +#define helper_gvec_fcadds helper_gvec_fcadds_sparc64 +#define helper_gvec_fcaddd helper_gvec_fcaddd_sparc64 #define helper_gvec_le8 helper_gvec_le8_sparc64 #define helper_gvec_le16 helper_gvec_le16_sparc64 #define helper_gvec_le32 helper_gvec_le32_sparc64 diff --git a/qemu/target/arm/helper.h b/qemu/target/arm/helper.h index fe5d6542..0812c37b 100644 --- a/qemu/target/arm/helper.h +++ b/qemu/target/arm/helper.h @@ -580,6 +580,13 @@ DEF_HELPER_FLAGS_5(gvec_qrdmlah_s32, TCG_CALL_NO_RWG, DEF_HELPER_FLAGS_5(gvec_qrdmlsh_s32, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32) +DEF_HELPER_FLAGS_5(gvec_fcaddh, TCG_CALL_NO_RWG, + void, ptr, ptr, ptr, ptr, i32) +DEF_HELPER_FLAGS_5(gvec_fcadds, TCG_CALL_NO_RWG, + void, ptr, ptr, ptr, ptr, i32) +DEF_HELPER_FLAGS_5(gvec_fcaddd, TCG_CALL_NO_RWG, + void, ptr, ptr, ptr, ptr, i32) + #ifdef TARGET_ARM #define helper_clz helper_clz_arm #define gen_helper_clz gen_helper_clz_arm diff --git a/qemu/target/arm/translate-a64.c b/qemu/target/arm/translate-a64.c index 0d678d5b..478bbd98 100644 --- a/qemu/target/arm/translate-a64.c +++ b/qemu/target/arm/translate-a64.c @@ -759,6 +759,23 @@ static void gen_gvec_op3_env(DisasContext *s, bool is_q, int rd, is_q ? 16 : 8, vec_full_reg_size(s), 0, fn); } +/* Expand a 3-operand + fpstatus pointer + simd data value operation using + * an out-of-line helper. + */ +static void gen_gvec_op3_fpst(DisasContext *s, bool is_q, int rd, int rn, + int rm, bool is_fp16, int data, + gen_helper_gvec_3_ptr *fn) +{ + TCGContext *tcg_ctx = s->uc->tcg_ctx; + + TCGv_ptr fpst = get_fpstatus_ptr(tcg_ctx, is_fp16); + tcg_gen_gvec_3_ptr(tcg_ctx, vec_full_reg_offset(s, rd), + vec_full_reg_offset(s, rn), + vec_full_reg_offset(s, rm), fpst, + is_q ? 16 : 8, vec_full_reg_size(s), data, fn); + tcg_temp_free_ptr(tcg_ctx, fpst); +} + /* Set ZF and NF based on a 64 bit result. This is alas fiddlier * than the 32 bit equivalent. */ @@ -10967,7 +10984,7 @@ static void disas_simd_three_reg_same_extra(DisasContext *s, uint32_t insn) int size = extract32(insn, 22, 2); bool u = extract32(insn, 29, 1); bool is_q = extract32(insn, 30, 1); - int feature; + int feature, rot; switch (u * 16 + opcode) { case 0x10: /* SQRDMLAH (vector) */ @@ -10978,6 +10995,16 @@ static void disas_simd_three_reg_same_extra(DisasContext *s, uint32_t insn) } feature = ARM_FEATURE_V8_RDM; break; + case 0xc: /* FCADD, #90 */ + case 0xe: /* FCADD, #270 */ + if (size == 0 + || (size == 1 && !arm_dc_feature(s, ARM_FEATURE_V8_FP16)) + || (size == 3 && !is_q)) { + unallocated_encoding(s); + return; + } + feature = ARM_FEATURE_V8_FCMA; + break; default: unallocated_encoding(s); return; @@ -11017,6 +11044,27 @@ static void disas_simd_three_reg_same_extra(DisasContext *s, uint32_t insn) } return; + case 0xc: /* FCADD, #90 */ + case 0xe: /* FCADD, #270 */ + rot = extract32(opcode, 1, 1); + switch (size) { + case 1: + gen_gvec_op3_fpst(s, is_q, rd, rn, rm, size == 1, rot, + gen_helper_gvec_fcaddh); + break; + case 2: + gen_gvec_op3_fpst(s, is_q, rd, rn, rm, size == 1, rot, + gen_helper_gvec_fcadds); + break; + case 3: + gen_gvec_op3_fpst(s, is_q, rd, rn, rm, size == 1, rot, + gen_helper_gvec_fcaddd); + break; + default: + g_assert_not_reached(); + } + return; + default: g_assert_not_reached(); } diff --git a/qemu/x86_64.h b/qemu/x86_64.h index 22d48bdd..f040d880 100644 --- a/qemu/x86_64.h +++ b/qemu/x86_64.h @@ -993,6 +993,9 @@ #define helper_gvec_eq16 helper_gvec_eq16_x86_64 #define helper_gvec_eq32 helper_gvec_eq32_x86_64 #define helper_gvec_eq64 helper_gvec_eq64_x86_64 +#define helper_gvec_fcaddh helper_gvec_fcaddh_x86_64 +#define helper_gvec_fcadds helper_gvec_fcadds_x86_64 +#define helper_gvec_fcaddd helper_gvec_fcaddd_x86_64 #define helper_gvec_le8 helper_gvec_le8_x86_64 #define helper_gvec_le16 helper_gvec_le16_x86_64 #define helper_gvec_le32 helper_gvec_le32_x86_64