From f3cb92c86c552191af75d6388491f1a43be38baf Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 15 Feb 2019 18:12:47 -0500 Subject: [PATCH] target/arm: Use vector operations for saturation For same-sign saturation, we have tcg vector operations. We can compute the QC bit by comparing the saturated value against the unsaturated value. Backports commit 89e68b575e138d0af1435f11a8ffcd8779c237bd from qemu --- qemu/aarch64.h | 20 ++++ qemu/aarch64eb.h | 20 ++++ qemu/arm.h | 20 ++++ qemu/armeb.h | 20 ++++ qemu/header_gen.py | 24 +++++ qemu/m68k.h | 16 +++ qemu/mips.h | 16 +++ qemu/mips64.h | 16 +++ qemu/mips64el.h | 16 +++ qemu/mipsel.h | 16 +++ qemu/powerpc.h | 16 +++ qemu/sparc.h | 16 +++ qemu/sparc64.h | 16 +++ qemu/target/arm/helper.h | 33 ++++++ qemu/target/arm/translate-a64.c | 36 +++---- qemu/target/arm/translate.c | 172 +++++++++++++++++++++++++++----- qemu/target/arm/translate.h | 4 + qemu/target/arm/vec_helper.c | 131 ++++++++++++++++++++++++ qemu/x86_64.h | 16 +++ 19 files changed, 580 insertions(+), 44 deletions(-) diff --git a/qemu/aarch64.h b/qemu/aarch64.h index 6d1b8df4..6b5fe808 100644 --- a/qemu/aarch64.h +++ b/qemu/aarch64.h @@ -1229,6 +1229,14 @@ #define helper_gvec_smin16 helper_gvec_smin16_aarch64 #define helper_gvec_smin32 helper_gvec_smin32_aarch64 #define helper_gvec_smin64 helper_gvec_smin64_aarch64 +#define helper_gvec_sqadd_b helper_gvec_sqadd_b_aarch64 +#define helper_gvec_sqadd_d helper_gvec_sqadd_d_aarch64 +#define helper_gvec_sqadd_h helper_gvec_sqadd_h_aarch64 +#define helper_gvec_sqadd_s helper_gvec_sqadd_s_aarch64 +#define helper_gvec_sqsub_b helper_gvec_sqsub_b_aarch64 +#define helper_gvec_sqsub_d helper_gvec_sqsub_d_aarch64 +#define helper_gvec_sqsub_h helper_gvec_sqsub_h_aarch64 +#define helper_gvec_sqsub_s helper_gvec_sqsub_s_aarch64 #define helper_gvec_sub8 helper_gvec_sub8_aarch64 #define helper_gvec_sub16 helper_gvec_sub16_aarch64 #define helper_gvec_sub32 helper_gvec_sub32_aarch64 @@ -1257,6 +1265,14 @@ #define helper_gvec_umin16 helper_gvec_umin16_aarch64 #define helper_gvec_umin32 helper_gvec_umin32_aarch64 #define helper_gvec_umin64 helper_gvec_umin64_aarch64 +#define helper_gvec_uqadd_b helper_gvec_uqadd_b_aarch64 +#define helper_gvec_uqadd_d helper_gvec_uqadd_d_aarch64 +#define helper_gvec_uqadd_h helper_gvec_uqadd_h_aarch64 +#define helper_gvec_uqadd_s helper_gvec_uqadd_s_aarch64 +#define helper_gvec_uqsub_b helper_gvec_uqsub_b_aarch64 +#define helper_gvec_uqsub_d helper_gvec_uqsub_d_aarch64 +#define helper_gvec_uqsub_h helper_gvec_uqsub_h_aarch64 +#define helper_gvec_uqsub_s helper_gvec_uqsub_s_aarch64 #define helper_gvec_usadd8 helper_gvec_usadd8_aarch64 #define helper_gvec_usadd16 helper_gvec_usadd16_aarch64 #define helper_gvec_usadd32 helper_gvec_usadd32_aarch64 @@ -4328,12 +4344,16 @@ #define read_cpu_reg read_cpu_reg_aarch64 #define read_cpu_reg_sp read_cpu_reg_sp_aarch64 #define sli_op sli_op_aarch64 +#define sqadd_op sqadd_op_aarch64 +#define sqsub_op sqsub_op_aarch64 #define ssra_op ssra_op_aarch64 #define sri_op sri_op_aarch64 #define sve_access_check sve_access_check_aarch64 #define sve_exception_el sve_exception_el_aarch64 #define sve_zcr_len_for_el sve_zcr_len_for_el_aarch64 #define unallocated_encoding unallocated_encoding_aarch64 +#define uqadd_op uqadd_op_aarch64 +#define uqsub_op uqsub_op_aarch64 #define usra_op usra_op_aarch64 #define vfp_expand_imm vfp_expand_imm_aarch64 #define write_fp_dreg write_fp_dreg_aarch64 diff --git a/qemu/aarch64eb.h b/qemu/aarch64eb.h index 93922a3a..86b8d38a 100644 --- a/qemu/aarch64eb.h +++ b/qemu/aarch64eb.h @@ -1229,6 +1229,14 @@ #define helper_gvec_smin16 helper_gvec_smin16_aarch64eb #define helper_gvec_smin32 helper_gvec_smin32_aarch64eb #define helper_gvec_smin64 helper_gvec_smin64_aarch64eb +#define helper_gvec_sqadd_b helper_gvec_sqadd_b_aarch64eb +#define helper_gvec_sqadd_d helper_gvec_sqadd_d_aarch64eb +#define helper_gvec_sqadd_h helper_gvec_sqadd_h_aarch64eb +#define helper_gvec_sqadd_s helper_gvec_sqadd_s_aarch64eb +#define helper_gvec_sqsub_b helper_gvec_sqsub_b_aarch64eb +#define helper_gvec_sqsub_d helper_gvec_sqsub_d_aarch64eb +#define helper_gvec_sqsub_h helper_gvec_sqsub_h_aarch64eb +#define helper_gvec_sqsub_s helper_gvec_sqsub_s_aarch64eb #define helper_gvec_sub8 helper_gvec_sub8_aarch64eb #define helper_gvec_sub16 helper_gvec_sub16_aarch64eb #define helper_gvec_sub32 helper_gvec_sub32_aarch64eb @@ -1257,6 +1265,14 @@ #define helper_gvec_umin16 helper_gvec_umin16_aarch64eb #define helper_gvec_umin32 helper_gvec_umin32_aarch64eb #define helper_gvec_umin64 helper_gvec_umin64_aarch64eb +#define helper_gvec_uqadd_b helper_gvec_uqadd_b_aarch64eb +#define helper_gvec_uqadd_d helper_gvec_uqadd_d_aarch64eb +#define helper_gvec_uqadd_h helper_gvec_uqadd_h_aarch64eb +#define helper_gvec_uqadd_s helper_gvec_uqadd_s_aarch64eb +#define helper_gvec_uqsub_b helper_gvec_uqsub_b_aarch64eb +#define helper_gvec_uqsub_d helper_gvec_uqsub_d_aarch64eb +#define helper_gvec_uqsub_h helper_gvec_uqsub_h_aarch64eb +#define helper_gvec_uqsub_s helper_gvec_uqsub_s_aarch64eb #define helper_gvec_usadd8 helper_gvec_usadd8_aarch64eb #define helper_gvec_usadd16 helper_gvec_usadd16_aarch64eb #define helper_gvec_usadd32 helper_gvec_usadd32_aarch64eb @@ -4328,12 +4344,16 @@ #define read_cpu_reg read_cpu_reg_aarch64eb #define read_cpu_reg_sp read_cpu_reg_sp_aarch64eb #define sli_op sli_op_aarch64eb +#define sqadd_op sqadd_op_aarch64eb +#define sqsub_op sqsub_op_aarch64eb #define ssra_op ssra_op_aarch64eb #define sri_op sri_op_aarch64eb #define sve_access_check sve_access_check_aarch64eb #define sve_exception_el sve_exception_el_aarch64eb #define sve_zcr_len_for_el sve_zcr_len_for_el_aarch64eb #define unallocated_encoding unallocated_encoding_aarch64eb +#define uqadd_op uqadd_op_aarch64eb +#define uqsub_op uqsub_op_aarch64eb #define usra_op usra_op_aarch64eb #define vfp_expand_imm vfp_expand_imm_aarch64eb #define write_fp_dreg write_fp_dreg_aarch64eb diff --git a/qemu/arm.h b/qemu/arm.h index 55d5a68d..b1148921 100644 --- a/qemu/arm.h +++ b/qemu/arm.h @@ -1229,6 +1229,14 @@ #define helper_gvec_smin16 helper_gvec_smin16_arm #define helper_gvec_smin32 helper_gvec_smin32_arm #define helper_gvec_smin64 helper_gvec_smin64_arm +#define helper_gvec_sqadd_b helper_gvec_sqadd_b_arm +#define helper_gvec_sqadd_d helper_gvec_sqadd_d_arm +#define helper_gvec_sqadd_h helper_gvec_sqadd_h_arm +#define helper_gvec_sqadd_s helper_gvec_sqadd_s_arm +#define helper_gvec_sqsub_b helper_gvec_sqsub_b_arm +#define helper_gvec_sqsub_d helper_gvec_sqsub_d_arm +#define helper_gvec_sqsub_h helper_gvec_sqsub_h_arm +#define helper_gvec_sqsub_s helper_gvec_sqsub_s_arm #define helper_gvec_sub8 helper_gvec_sub8_arm #define helper_gvec_sub16 helper_gvec_sub16_arm #define helper_gvec_sub32 helper_gvec_sub32_arm @@ -1257,6 +1265,14 @@ #define helper_gvec_umin16 helper_gvec_umin16_arm #define helper_gvec_umin32 helper_gvec_umin32_arm #define helper_gvec_umin64 helper_gvec_umin64_arm +#define helper_gvec_uqadd_b helper_gvec_uqadd_b_arm +#define helper_gvec_uqadd_d helper_gvec_uqadd_d_arm +#define helper_gvec_uqadd_h helper_gvec_uqadd_h_arm +#define helper_gvec_uqadd_s helper_gvec_uqadd_s_arm +#define helper_gvec_uqsub_b helper_gvec_uqsub_b_arm +#define helper_gvec_uqsub_d helper_gvec_uqsub_d_arm +#define helper_gvec_uqsub_h helper_gvec_uqsub_h_arm +#define helper_gvec_uqsub_s helper_gvec_uqsub_s_arm #define helper_gvec_usadd8 helper_gvec_usadd8_arm #define helper_gvec_usadd16 helper_gvec_usadd16_arm #define helper_gvec_usadd32 helper_gvec_usadd32_arm @@ -3333,9 +3349,13 @@ #define raise_exception raise_exception_arm #define raise_exception_ra raise_exception_ra_arm #define sli_op sli_op_arm +#define sqadd_op sqadd_op_arm +#define sqsub_op sqsub_op_arm #define ssra_op ssra_op_arm #define sri_op sri_op_arm #define sve_exception_el sve_exception_el_arm #define sve_zcr_len_for_el sve_zcr_len_for_el_arm +#define uqadd_op uqadd_op_arm +#define uqsub_op uqsub_op_arm #define usra_op usra_op_arm #endif diff --git a/qemu/armeb.h b/qemu/armeb.h index e271b713..86a588b8 100644 --- a/qemu/armeb.h +++ b/qemu/armeb.h @@ -1229,6 +1229,14 @@ #define helper_gvec_smin16 helper_gvec_smin16_armeb #define helper_gvec_smin32 helper_gvec_smin32_armeb #define helper_gvec_smin64 helper_gvec_smin64_armeb +#define helper_gvec_sqadd_b helper_gvec_sqadd_b_armeb +#define helper_gvec_sqadd_d helper_gvec_sqadd_d_armeb +#define helper_gvec_sqadd_h helper_gvec_sqadd_h_armeb +#define helper_gvec_sqadd_s helper_gvec_sqadd_s_armeb +#define helper_gvec_sqsub_b helper_gvec_sqsub_b_armeb +#define helper_gvec_sqsub_d helper_gvec_sqsub_d_armeb +#define helper_gvec_sqsub_h helper_gvec_sqsub_h_armeb +#define helper_gvec_sqsub_s helper_gvec_sqsub_s_armeb #define helper_gvec_sub8 helper_gvec_sub8_armeb #define helper_gvec_sub16 helper_gvec_sub16_armeb #define helper_gvec_sub32 helper_gvec_sub32_armeb @@ -1257,6 +1265,14 @@ #define helper_gvec_umin16 helper_gvec_umin16_armeb #define helper_gvec_umin32 helper_gvec_umin32_armeb #define helper_gvec_umin64 helper_gvec_umin64_armeb +#define helper_gvec_uqadd_b helper_gvec_uqadd_b_armeb +#define helper_gvec_uqadd_d helper_gvec_uqadd_d_armeb +#define helper_gvec_uqadd_h helper_gvec_uqadd_h_armeb +#define helper_gvec_uqadd_s helper_gvec_uqadd_s_armeb +#define helper_gvec_uqsub_b helper_gvec_uqsub_b_armeb +#define helper_gvec_uqsub_d helper_gvec_uqsub_d_armeb +#define helper_gvec_uqsub_h helper_gvec_uqsub_h_armeb +#define helper_gvec_uqsub_s helper_gvec_uqsub_s_armeb #define helper_gvec_usadd8 helper_gvec_usadd8_armeb #define helper_gvec_usadd16 helper_gvec_usadd16_armeb #define helper_gvec_usadd32 helper_gvec_usadd32_armeb @@ -3333,9 +3349,13 @@ #define raise_exception raise_exception_armeb #define raise_exception_ra raise_exception_ra_armeb #define sli_op sli_op_armeb +#define sqadd_op sqadd_op_armeb +#define sqsub_op sqsub_op_armeb #define ssra_op ssra_op_armeb #define sri_op sri_op_armeb #define sve_exception_el sve_exception_el_armeb #define sve_zcr_len_for_el sve_zcr_len_for_el_armeb +#define uqadd_op uqadd_op_armeb +#define uqsub_op uqsub_op_armeb #define usra_op usra_op_armeb #endif diff --git a/qemu/header_gen.py b/qemu/header_gen.py index 1a589c5c..cfcd71f8 100644 --- a/qemu/header_gen.py +++ b/qemu/header_gen.py @@ -1235,6 +1235,14 @@ symbols = ( 'helper_gvec_smin16', 'helper_gvec_smin32', 'helper_gvec_smin64', + 'helper_gvec_sqadd_b', + 'helper_gvec_sqadd_d', + 'helper_gvec_sqadd_h', + 'helper_gvec_sqadd_s', + 'helper_gvec_sqsub_b', + 'helper_gvec_sqsub_d', + 'helper_gvec_sqsub_h', + 'helper_gvec_sqsub_s', 'helper_gvec_sub8', 'helper_gvec_sub16', 'helper_gvec_sub32', @@ -1263,6 +1271,14 @@ symbols = ( 'helper_gvec_umin16', 'helper_gvec_umin32', 'helper_gvec_umin64', + 'helper_gvec_uqadd_b', + 'helper_gvec_uqadd_d', + 'helper_gvec_uqadd_h', + 'helper_gvec_uqadd_s', + 'helper_gvec_uqsub_b', + 'helper_gvec_uqsub_d', + 'helper_gvec_uqsub_h', + 'helper_gvec_uqsub_s', 'helper_gvec_usadd8', 'helper_gvec_usadd16', 'helper_gvec_usadd32', @@ -3342,10 +3358,14 @@ arm_symbols = ( 'raise_exception', 'raise_exception_ra', 'sli_op', + 'sqadd_op', + 'sqsub_op', 'ssra_op', 'sri_op', 'sve_exception_el', 'sve_zcr_len_for_el', + 'uqadd_op', + 'uqsub_op', 'usra_op', ) @@ -4374,12 +4394,16 @@ aarch64_symbols = ( 'read_cpu_reg', 'read_cpu_reg_sp', 'sli_op', + 'sqadd_op', + 'sqsub_op', 'ssra_op', 'sri_op', 'sve_access_check', 'sve_exception_el', 'sve_zcr_len_for_el', 'unallocated_encoding', + 'uqadd_op', + 'uqsub_op', 'usra_op', 'vfp_expand_imm', 'write_fp_dreg', diff --git a/qemu/m68k.h b/qemu/m68k.h index 4286fe66..43b66825 100644 --- a/qemu/m68k.h +++ b/qemu/m68k.h @@ -1229,6 +1229,14 @@ #define helper_gvec_smin16 helper_gvec_smin16_m68k #define helper_gvec_smin32 helper_gvec_smin32_m68k #define helper_gvec_smin64 helper_gvec_smin64_m68k +#define helper_gvec_sqadd_b helper_gvec_sqadd_b_m68k +#define helper_gvec_sqadd_d helper_gvec_sqadd_d_m68k +#define helper_gvec_sqadd_h helper_gvec_sqadd_h_m68k +#define helper_gvec_sqadd_s helper_gvec_sqadd_s_m68k +#define helper_gvec_sqsub_b helper_gvec_sqsub_b_m68k +#define helper_gvec_sqsub_d helper_gvec_sqsub_d_m68k +#define helper_gvec_sqsub_h helper_gvec_sqsub_h_m68k +#define helper_gvec_sqsub_s helper_gvec_sqsub_s_m68k #define helper_gvec_sub8 helper_gvec_sub8_m68k #define helper_gvec_sub16 helper_gvec_sub16_m68k #define helper_gvec_sub32 helper_gvec_sub32_m68k @@ -1257,6 +1265,14 @@ #define helper_gvec_umin16 helper_gvec_umin16_m68k #define helper_gvec_umin32 helper_gvec_umin32_m68k #define helper_gvec_umin64 helper_gvec_umin64_m68k +#define helper_gvec_uqadd_b helper_gvec_uqadd_b_m68k +#define helper_gvec_uqadd_d helper_gvec_uqadd_d_m68k +#define helper_gvec_uqadd_h helper_gvec_uqadd_h_m68k +#define helper_gvec_uqadd_s helper_gvec_uqadd_s_m68k +#define helper_gvec_uqsub_b helper_gvec_uqsub_b_m68k +#define helper_gvec_uqsub_d helper_gvec_uqsub_d_m68k +#define helper_gvec_uqsub_h helper_gvec_uqsub_h_m68k +#define helper_gvec_uqsub_s helper_gvec_uqsub_s_m68k #define helper_gvec_usadd8 helper_gvec_usadd8_m68k #define helper_gvec_usadd16 helper_gvec_usadd16_m68k #define helper_gvec_usadd32 helper_gvec_usadd32_m68k diff --git a/qemu/mips.h b/qemu/mips.h index 5af1bac7..59d92a66 100644 --- a/qemu/mips.h +++ b/qemu/mips.h @@ -1229,6 +1229,14 @@ #define helper_gvec_smin16 helper_gvec_smin16_mips #define helper_gvec_smin32 helper_gvec_smin32_mips #define helper_gvec_smin64 helper_gvec_smin64_mips +#define helper_gvec_sqadd_b helper_gvec_sqadd_b_mips +#define helper_gvec_sqadd_d helper_gvec_sqadd_d_mips +#define helper_gvec_sqadd_h helper_gvec_sqadd_h_mips +#define helper_gvec_sqadd_s helper_gvec_sqadd_s_mips +#define helper_gvec_sqsub_b helper_gvec_sqsub_b_mips +#define helper_gvec_sqsub_d helper_gvec_sqsub_d_mips +#define helper_gvec_sqsub_h helper_gvec_sqsub_h_mips +#define helper_gvec_sqsub_s helper_gvec_sqsub_s_mips #define helper_gvec_sub8 helper_gvec_sub8_mips #define helper_gvec_sub16 helper_gvec_sub16_mips #define helper_gvec_sub32 helper_gvec_sub32_mips @@ -1257,6 +1265,14 @@ #define helper_gvec_umin16 helper_gvec_umin16_mips #define helper_gvec_umin32 helper_gvec_umin32_mips #define helper_gvec_umin64 helper_gvec_umin64_mips +#define helper_gvec_uqadd_b helper_gvec_uqadd_b_mips +#define helper_gvec_uqadd_d helper_gvec_uqadd_d_mips +#define helper_gvec_uqadd_h helper_gvec_uqadd_h_mips +#define helper_gvec_uqadd_s helper_gvec_uqadd_s_mips +#define helper_gvec_uqsub_b helper_gvec_uqsub_b_mips +#define helper_gvec_uqsub_d helper_gvec_uqsub_d_mips +#define helper_gvec_uqsub_h helper_gvec_uqsub_h_mips +#define helper_gvec_uqsub_s helper_gvec_uqsub_s_mips #define helper_gvec_usadd8 helper_gvec_usadd8_mips #define helper_gvec_usadd16 helper_gvec_usadd16_mips #define helper_gvec_usadd32 helper_gvec_usadd32_mips diff --git a/qemu/mips64.h b/qemu/mips64.h index b07516ff..06074da0 100644 --- a/qemu/mips64.h +++ b/qemu/mips64.h @@ -1229,6 +1229,14 @@ #define helper_gvec_smin16 helper_gvec_smin16_mips64 #define helper_gvec_smin32 helper_gvec_smin32_mips64 #define helper_gvec_smin64 helper_gvec_smin64_mips64 +#define helper_gvec_sqadd_b helper_gvec_sqadd_b_mips64 +#define helper_gvec_sqadd_d helper_gvec_sqadd_d_mips64 +#define helper_gvec_sqadd_h helper_gvec_sqadd_h_mips64 +#define helper_gvec_sqadd_s helper_gvec_sqadd_s_mips64 +#define helper_gvec_sqsub_b helper_gvec_sqsub_b_mips64 +#define helper_gvec_sqsub_d helper_gvec_sqsub_d_mips64 +#define helper_gvec_sqsub_h helper_gvec_sqsub_h_mips64 +#define helper_gvec_sqsub_s helper_gvec_sqsub_s_mips64 #define helper_gvec_sub8 helper_gvec_sub8_mips64 #define helper_gvec_sub16 helper_gvec_sub16_mips64 #define helper_gvec_sub32 helper_gvec_sub32_mips64 @@ -1257,6 +1265,14 @@ #define helper_gvec_umin16 helper_gvec_umin16_mips64 #define helper_gvec_umin32 helper_gvec_umin32_mips64 #define helper_gvec_umin64 helper_gvec_umin64_mips64 +#define helper_gvec_uqadd_b helper_gvec_uqadd_b_mips64 +#define helper_gvec_uqadd_d helper_gvec_uqadd_d_mips64 +#define helper_gvec_uqadd_h helper_gvec_uqadd_h_mips64 +#define helper_gvec_uqadd_s helper_gvec_uqadd_s_mips64 +#define helper_gvec_uqsub_b helper_gvec_uqsub_b_mips64 +#define helper_gvec_uqsub_d helper_gvec_uqsub_d_mips64 +#define helper_gvec_uqsub_h helper_gvec_uqsub_h_mips64 +#define helper_gvec_uqsub_s helper_gvec_uqsub_s_mips64 #define helper_gvec_usadd8 helper_gvec_usadd8_mips64 #define helper_gvec_usadd16 helper_gvec_usadd16_mips64 #define helper_gvec_usadd32 helper_gvec_usadd32_mips64 diff --git a/qemu/mips64el.h b/qemu/mips64el.h index 3722b353..78f7729a 100644 --- a/qemu/mips64el.h +++ b/qemu/mips64el.h @@ -1229,6 +1229,14 @@ #define helper_gvec_smin16 helper_gvec_smin16_mips64el #define helper_gvec_smin32 helper_gvec_smin32_mips64el #define helper_gvec_smin64 helper_gvec_smin64_mips64el +#define helper_gvec_sqadd_b helper_gvec_sqadd_b_mips64el +#define helper_gvec_sqadd_d helper_gvec_sqadd_d_mips64el +#define helper_gvec_sqadd_h helper_gvec_sqadd_h_mips64el +#define helper_gvec_sqadd_s helper_gvec_sqadd_s_mips64el +#define helper_gvec_sqsub_b helper_gvec_sqsub_b_mips64el +#define helper_gvec_sqsub_d helper_gvec_sqsub_d_mips64el +#define helper_gvec_sqsub_h helper_gvec_sqsub_h_mips64el +#define helper_gvec_sqsub_s helper_gvec_sqsub_s_mips64el #define helper_gvec_sub8 helper_gvec_sub8_mips64el #define helper_gvec_sub16 helper_gvec_sub16_mips64el #define helper_gvec_sub32 helper_gvec_sub32_mips64el @@ -1257,6 +1265,14 @@ #define helper_gvec_umin16 helper_gvec_umin16_mips64el #define helper_gvec_umin32 helper_gvec_umin32_mips64el #define helper_gvec_umin64 helper_gvec_umin64_mips64el +#define helper_gvec_uqadd_b helper_gvec_uqadd_b_mips64el +#define helper_gvec_uqadd_d helper_gvec_uqadd_d_mips64el +#define helper_gvec_uqadd_h helper_gvec_uqadd_h_mips64el +#define helper_gvec_uqadd_s helper_gvec_uqadd_s_mips64el +#define helper_gvec_uqsub_b helper_gvec_uqsub_b_mips64el +#define helper_gvec_uqsub_d helper_gvec_uqsub_d_mips64el +#define helper_gvec_uqsub_h helper_gvec_uqsub_h_mips64el +#define helper_gvec_uqsub_s helper_gvec_uqsub_s_mips64el #define helper_gvec_usadd8 helper_gvec_usadd8_mips64el #define helper_gvec_usadd16 helper_gvec_usadd16_mips64el #define helper_gvec_usadd32 helper_gvec_usadd32_mips64el diff --git a/qemu/mipsel.h b/qemu/mipsel.h index dcc83c0c..97c1aa52 100644 --- a/qemu/mipsel.h +++ b/qemu/mipsel.h @@ -1229,6 +1229,14 @@ #define helper_gvec_smin16 helper_gvec_smin16_mipsel #define helper_gvec_smin32 helper_gvec_smin32_mipsel #define helper_gvec_smin64 helper_gvec_smin64_mipsel +#define helper_gvec_sqadd_b helper_gvec_sqadd_b_mipsel +#define helper_gvec_sqadd_d helper_gvec_sqadd_d_mipsel +#define helper_gvec_sqadd_h helper_gvec_sqadd_h_mipsel +#define helper_gvec_sqadd_s helper_gvec_sqadd_s_mipsel +#define helper_gvec_sqsub_b helper_gvec_sqsub_b_mipsel +#define helper_gvec_sqsub_d helper_gvec_sqsub_d_mipsel +#define helper_gvec_sqsub_h helper_gvec_sqsub_h_mipsel +#define helper_gvec_sqsub_s helper_gvec_sqsub_s_mipsel #define helper_gvec_sub8 helper_gvec_sub8_mipsel #define helper_gvec_sub16 helper_gvec_sub16_mipsel #define helper_gvec_sub32 helper_gvec_sub32_mipsel @@ -1257,6 +1265,14 @@ #define helper_gvec_umin16 helper_gvec_umin16_mipsel #define helper_gvec_umin32 helper_gvec_umin32_mipsel #define helper_gvec_umin64 helper_gvec_umin64_mipsel +#define helper_gvec_uqadd_b helper_gvec_uqadd_b_mipsel +#define helper_gvec_uqadd_d helper_gvec_uqadd_d_mipsel +#define helper_gvec_uqadd_h helper_gvec_uqadd_h_mipsel +#define helper_gvec_uqadd_s helper_gvec_uqadd_s_mipsel +#define helper_gvec_uqsub_b helper_gvec_uqsub_b_mipsel +#define helper_gvec_uqsub_d helper_gvec_uqsub_d_mipsel +#define helper_gvec_uqsub_h helper_gvec_uqsub_h_mipsel +#define helper_gvec_uqsub_s helper_gvec_uqsub_s_mipsel #define helper_gvec_usadd8 helper_gvec_usadd8_mipsel #define helper_gvec_usadd16 helper_gvec_usadd16_mipsel #define helper_gvec_usadd32 helper_gvec_usadd32_mipsel diff --git a/qemu/powerpc.h b/qemu/powerpc.h index c8520bff..ed534720 100644 --- a/qemu/powerpc.h +++ b/qemu/powerpc.h @@ -1229,6 +1229,14 @@ #define helper_gvec_smin16 helper_gvec_smin16_powerpc #define helper_gvec_smin32 helper_gvec_smin32_powerpc #define helper_gvec_smin64 helper_gvec_smin64_powerpc +#define helper_gvec_sqadd_b helper_gvec_sqadd_b_powerpc +#define helper_gvec_sqadd_d helper_gvec_sqadd_d_powerpc +#define helper_gvec_sqadd_h helper_gvec_sqadd_h_powerpc +#define helper_gvec_sqadd_s helper_gvec_sqadd_s_powerpc +#define helper_gvec_sqsub_b helper_gvec_sqsub_b_powerpc +#define helper_gvec_sqsub_d helper_gvec_sqsub_d_powerpc +#define helper_gvec_sqsub_h helper_gvec_sqsub_h_powerpc +#define helper_gvec_sqsub_s helper_gvec_sqsub_s_powerpc #define helper_gvec_sub8 helper_gvec_sub8_powerpc #define helper_gvec_sub16 helper_gvec_sub16_powerpc #define helper_gvec_sub32 helper_gvec_sub32_powerpc @@ -1257,6 +1265,14 @@ #define helper_gvec_umin16 helper_gvec_umin16_powerpc #define helper_gvec_umin32 helper_gvec_umin32_powerpc #define helper_gvec_umin64 helper_gvec_umin64_powerpc +#define helper_gvec_uqadd_b helper_gvec_uqadd_b_powerpc +#define helper_gvec_uqadd_d helper_gvec_uqadd_d_powerpc +#define helper_gvec_uqadd_h helper_gvec_uqadd_h_powerpc +#define helper_gvec_uqadd_s helper_gvec_uqadd_s_powerpc +#define helper_gvec_uqsub_b helper_gvec_uqsub_b_powerpc +#define helper_gvec_uqsub_d helper_gvec_uqsub_d_powerpc +#define helper_gvec_uqsub_h helper_gvec_uqsub_h_powerpc +#define helper_gvec_uqsub_s helper_gvec_uqsub_s_powerpc #define helper_gvec_usadd8 helper_gvec_usadd8_powerpc #define helper_gvec_usadd16 helper_gvec_usadd16_powerpc #define helper_gvec_usadd32 helper_gvec_usadd32_powerpc diff --git a/qemu/sparc.h b/qemu/sparc.h index 72f61716..8b774d7d 100644 --- a/qemu/sparc.h +++ b/qemu/sparc.h @@ -1229,6 +1229,14 @@ #define helper_gvec_smin16 helper_gvec_smin16_sparc #define helper_gvec_smin32 helper_gvec_smin32_sparc #define helper_gvec_smin64 helper_gvec_smin64_sparc +#define helper_gvec_sqadd_b helper_gvec_sqadd_b_sparc +#define helper_gvec_sqadd_d helper_gvec_sqadd_d_sparc +#define helper_gvec_sqadd_h helper_gvec_sqadd_h_sparc +#define helper_gvec_sqadd_s helper_gvec_sqadd_s_sparc +#define helper_gvec_sqsub_b helper_gvec_sqsub_b_sparc +#define helper_gvec_sqsub_d helper_gvec_sqsub_d_sparc +#define helper_gvec_sqsub_h helper_gvec_sqsub_h_sparc +#define helper_gvec_sqsub_s helper_gvec_sqsub_s_sparc #define helper_gvec_sub8 helper_gvec_sub8_sparc #define helper_gvec_sub16 helper_gvec_sub16_sparc #define helper_gvec_sub32 helper_gvec_sub32_sparc @@ -1257,6 +1265,14 @@ #define helper_gvec_umin16 helper_gvec_umin16_sparc #define helper_gvec_umin32 helper_gvec_umin32_sparc #define helper_gvec_umin64 helper_gvec_umin64_sparc +#define helper_gvec_uqadd_b helper_gvec_uqadd_b_sparc +#define helper_gvec_uqadd_d helper_gvec_uqadd_d_sparc +#define helper_gvec_uqadd_h helper_gvec_uqadd_h_sparc +#define helper_gvec_uqadd_s helper_gvec_uqadd_s_sparc +#define helper_gvec_uqsub_b helper_gvec_uqsub_b_sparc +#define helper_gvec_uqsub_d helper_gvec_uqsub_d_sparc +#define helper_gvec_uqsub_h helper_gvec_uqsub_h_sparc +#define helper_gvec_uqsub_s helper_gvec_uqsub_s_sparc #define helper_gvec_usadd8 helper_gvec_usadd8_sparc #define helper_gvec_usadd16 helper_gvec_usadd16_sparc #define helper_gvec_usadd32 helper_gvec_usadd32_sparc diff --git a/qemu/sparc64.h b/qemu/sparc64.h index 22e6ee60..ff77492d 100644 --- a/qemu/sparc64.h +++ b/qemu/sparc64.h @@ -1229,6 +1229,14 @@ #define helper_gvec_smin16 helper_gvec_smin16_sparc64 #define helper_gvec_smin32 helper_gvec_smin32_sparc64 #define helper_gvec_smin64 helper_gvec_smin64_sparc64 +#define helper_gvec_sqadd_b helper_gvec_sqadd_b_sparc64 +#define helper_gvec_sqadd_d helper_gvec_sqadd_d_sparc64 +#define helper_gvec_sqadd_h helper_gvec_sqadd_h_sparc64 +#define helper_gvec_sqadd_s helper_gvec_sqadd_s_sparc64 +#define helper_gvec_sqsub_b helper_gvec_sqsub_b_sparc64 +#define helper_gvec_sqsub_d helper_gvec_sqsub_d_sparc64 +#define helper_gvec_sqsub_h helper_gvec_sqsub_h_sparc64 +#define helper_gvec_sqsub_s helper_gvec_sqsub_s_sparc64 #define helper_gvec_sub8 helper_gvec_sub8_sparc64 #define helper_gvec_sub16 helper_gvec_sub16_sparc64 #define helper_gvec_sub32 helper_gvec_sub32_sparc64 @@ -1257,6 +1265,14 @@ #define helper_gvec_umin16 helper_gvec_umin16_sparc64 #define helper_gvec_umin32 helper_gvec_umin32_sparc64 #define helper_gvec_umin64 helper_gvec_umin64_sparc64 +#define helper_gvec_uqadd_b helper_gvec_uqadd_b_sparc64 +#define helper_gvec_uqadd_d helper_gvec_uqadd_d_sparc64 +#define helper_gvec_uqadd_h helper_gvec_uqadd_h_sparc64 +#define helper_gvec_uqadd_s helper_gvec_uqadd_s_sparc64 +#define helper_gvec_uqsub_b helper_gvec_uqsub_b_sparc64 +#define helper_gvec_uqsub_d helper_gvec_uqsub_d_sparc64 +#define helper_gvec_uqsub_h helper_gvec_uqsub_h_sparc64 +#define helper_gvec_uqsub_s helper_gvec_uqsub_s_sparc64 #define helper_gvec_usadd8 helper_gvec_usadd8_sparc64 #define helper_gvec_usadd16 helper_gvec_usadd16_sparc64 #define helper_gvec_usadd32 helper_gvec_usadd32_sparc64 diff --git a/qemu/target/arm/helper.h b/qemu/target/arm/helper.h index f75ea69e..71a09827 100644 --- a/qemu/target/arm/helper.h +++ b/qemu/target/arm/helper.h @@ -643,6 +643,39 @@ DEF_HELPER_FLAGS_6(gvec_fmla_idx_s, TCG_CALL_NO_RWG, DEF_HELPER_FLAGS_6(gvec_fmla_idx_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, ptr, i32) +DEF_HELPER_FLAGS_5(gvec_uqadd_b, TCG_CALL_NO_RWG, + void, ptr, ptr, ptr, ptr, i32) +DEF_HELPER_FLAGS_5(gvec_uqadd_h, TCG_CALL_NO_RWG, + void, ptr, ptr, ptr, ptr, i32) +DEF_HELPER_FLAGS_5(gvec_uqadd_s, TCG_CALL_NO_RWG, + void, ptr, ptr, ptr, ptr, i32) +DEF_HELPER_FLAGS_5(gvec_uqadd_d, TCG_CALL_NO_RWG, + void, ptr, ptr, ptr, ptr, i32) +DEF_HELPER_FLAGS_5(gvec_sqadd_b, TCG_CALL_NO_RWG, + void, ptr, ptr, ptr, ptr, i32) +DEF_HELPER_FLAGS_5(gvec_sqadd_h, TCG_CALL_NO_RWG, + void, ptr, ptr, ptr, ptr, i32) +DEF_HELPER_FLAGS_5(gvec_sqadd_s, TCG_CALL_NO_RWG, + void, ptr, ptr, ptr, ptr, i32) +DEF_HELPER_FLAGS_5(gvec_sqadd_d, TCG_CALL_NO_RWG, + void, ptr, ptr, ptr, ptr, i32) +DEF_HELPER_FLAGS_5(gvec_uqsub_b, TCG_CALL_NO_RWG, + void, ptr, ptr, ptr, ptr, i32) +DEF_HELPER_FLAGS_5(gvec_uqsub_h, TCG_CALL_NO_RWG, + void, ptr, ptr, ptr, ptr, i32) +DEF_HELPER_FLAGS_5(gvec_uqsub_s, TCG_CALL_NO_RWG, + void, ptr, ptr, ptr, ptr, i32) +DEF_HELPER_FLAGS_5(gvec_uqsub_d, TCG_CALL_NO_RWG, + void, ptr, ptr, ptr, ptr, i32) +DEF_HELPER_FLAGS_5(gvec_sqsub_b, TCG_CALL_NO_RWG, + void, ptr, ptr, ptr, ptr, i32) +DEF_HELPER_FLAGS_5(gvec_sqsub_h, TCG_CALL_NO_RWG, + void, ptr, ptr, ptr, ptr, i32) +DEF_HELPER_FLAGS_5(gvec_sqsub_s, TCG_CALL_NO_RWG, + void, ptr, ptr, ptr, ptr, i32) +DEF_HELPER_FLAGS_5(gvec_sqsub_d, 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 4eae6a41..13e9485c 100644 --- a/qemu/target/arm/translate-a64.c +++ b/qemu/target/arm/translate-a64.c @@ -11109,6 +11109,22 @@ static void disas_simd_3same_int(DisasContext *s, uint32_t insn) } switch (opcode) { + case 0x01: /* SQADD, UQADD */ + tcg_gen_gvec_4(tcg_ctx, vec_full_reg_offset(s, rd), + offsetof(CPUARMState, vfp.qc), + vec_full_reg_offset(s, rn), + vec_full_reg_offset(s, rm), + is_q ? 16 : 8, vec_full_reg_size(s), + (u ? uqadd_op : sqadd_op) + size); + return; + case 0x05: /* SQSUB, UQSUB */ + tcg_gen_gvec_4(tcg_ctx, vec_full_reg_offset(s, rd), + offsetof(CPUARMState, vfp.qc), + vec_full_reg_offset(s, rn), + vec_full_reg_offset(s, rm), + is_q ? 16 : 8, vec_full_reg_size(s), + (u ? uqsub_op : sqsub_op) + size); + return; case 0x0c: /* SMAX, UMAX */ if (u) { gen_gvec_fn3(s, is_q, rd, rn, rm, tcg_gen_gvec_umax, size); @@ -11204,16 +11220,6 @@ static void disas_simd_3same_int(DisasContext *s, uint32_t insn) genfn = fns[size][u]; break; } - case 0x1: /* SQADD, UQADD */ - { - static NeonGenTwoOpEnvFn * const fns[3][2] = { - { gen_helper_neon_qadd_s8, gen_helper_neon_qadd_u8 }, - { gen_helper_neon_qadd_s16, gen_helper_neon_qadd_u16 }, - { gen_helper_neon_qadd_s32, gen_helper_neon_qadd_u32 }, - }; - genenvfn = fns[size][u]; - break; - } case 0x2: /* SRHADD, URHADD */ { static NeonGenTwoOpFn * const fns[3][2] = { @@ -11234,16 +11240,6 @@ static void disas_simd_3same_int(DisasContext *s, uint32_t insn) genfn = fns[size][u]; break; } - case 0x5: /* SQSUB, UQSUB */ - { - static NeonGenTwoOpEnvFn * const fns[3][2] = { - { gen_helper_neon_qsub_s8, gen_helper_neon_qsub_u8 }, - { gen_helper_neon_qsub_s16, gen_helper_neon_qsub_u16 }, - { gen_helper_neon_qsub_s32, gen_helper_neon_qsub_u32 }, - }; - genenvfn = fns[size][u]; - break; - } case 0x8: /* SSHL, USHL */ { static NeonGenTwoOpFn * const fns[3][2] = { diff --git a/qemu/target/arm/translate.c b/qemu/target/arm/translate.c index 2daeb7d4..84801898 100644 --- a/qemu/target/arm/translate.c +++ b/qemu/target/arm/translate.c @@ -6309,6 +6309,142 @@ const GVecGen3 cmtst_op[4] = { .vece = MO_64 }, }; +static void gen_uqadd_vec(TCGContext *s, unsigned vece, TCGv_vec t, TCGv_vec sat, + TCGv_vec a, TCGv_vec b) +{ + TCGv_vec x = tcg_temp_new_vec_matching(s, t); + tcg_gen_add_vec(s, vece, x, a, b); + tcg_gen_usadd_vec(s, vece, t, a, b); + tcg_gen_cmp_vec(s, TCG_COND_NE, vece, x, x, t); + tcg_gen_or_vec(s, vece, sat, sat, x); + tcg_temp_free_vec(s, x); +} + +const GVecGen4 uqadd_op[4] = { + { .fniv = gen_uqadd_vec, + .fno = gen_helper_gvec_uqadd_b, + .opc = INDEX_op_usadd_vec, + .write_aofs = true, + .vece = MO_8 }, + { .fniv = gen_uqadd_vec, + .fno = gen_helper_gvec_uqadd_h, + .opc = INDEX_op_usadd_vec, + .write_aofs = true, + .vece = MO_16 }, + { .fniv = gen_uqadd_vec, + .fno = gen_helper_gvec_uqadd_s, + .opc = INDEX_op_usadd_vec, + .write_aofs = true, + .vece = MO_32 }, + { .fniv = gen_uqadd_vec, + .fno = gen_helper_gvec_uqadd_d, + .opc = INDEX_op_usadd_vec, + .write_aofs = true, + .vece = MO_64 }, +}; + +static void gen_sqadd_vec(TCGContext *s, unsigned vece, TCGv_vec t, TCGv_vec sat, + TCGv_vec a, TCGv_vec b) +{ + TCGv_vec x = tcg_temp_new_vec_matching(s, t); + tcg_gen_add_vec(s, vece, x, a, b); + tcg_gen_ssadd_vec(s, vece, t, a, b); + tcg_gen_cmp_vec(s, TCG_COND_NE, vece, x, x, t); + tcg_gen_or_vec(s, vece, sat, sat, x); + tcg_temp_free_vec(s, x); +} + +const GVecGen4 sqadd_op[4] = { + { .fniv = gen_sqadd_vec, + .fno = gen_helper_gvec_sqadd_b, + .opc = INDEX_op_ssadd_vec, + .write_aofs = true, + .vece = MO_8 }, + { .fniv = gen_sqadd_vec, + .fno = gen_helper_gvec_sqadd_h, + .opc = INDEX_op_ssadd_vec, + .write_aofs = true, + .vece = MO_16 }, + { .fniv = gen_sqadd_vec, + .fno = gen_helper_gvec_sqadd_s, + .opc = INDEX_op_ssadd_vec, + .write_aofs = true, + .vece = MO_32 }, + { .fniv = gen_sqadd_vec, + .fno = gen_helper_gvec_sqadd_d, + .opc = INDEX_op_ssadd_vec, + .write_aofs = true, + .vece = MO_64 }, +}; + +static void gen_uqsub_vec(TCGContext *s, unsigned vece, TCGv_vec t, TCGv_vec sat, + TCGv_vec a, TCGv_vec b) +{ + TCGv_vec x = tcg_temp_new_vec_matching(s, t); + tcg_gen_sub_vec(s, vece, x, a, b); + tcg_gen_ussub_vec(s, vece, t, a, b); + tcg_gen_cmp_vec(s, TCG_COND_NE, vece, x, x, t); + tcg_gen_or_vec(s, vece, sat, sat, x); + tcg_temp_free_vec(s, x); +} + +const GVecGen4 uqsub_op[4] = { + { .fniv = gen_uqsub_vec, + .fno = gen_helper_gvec_uqsub_b, + .opc = INDEX_op_ussub_vec, + .write_aofs = true, + .vece = MO_8 }, + { .fniv = gen_uqsub_vec, + .fno = gen_helper_gvec_uqsub_h, + .opc = INDEX_op_ussub_vec, + .write_aofs = true, + .vece = MO_16 }, + { .fniv = gen_uqsub_vec, + .fno = gen_helper_gvec_uqsub_s, + .opc = INDEX_op_ussub_vec, + .write_aofs = true, + .vece = MO_32 }, + { .fniv = gen_uqsub_vec, + .fno = gen_helper_gvec_uqsub_d, + .opc = INDEX_op_ussub_vec, + .write_aofs = true, + .vece = MO_64 }, +}; + +static void gen_sqsub_vec(TCGContext *s, unsigned vece, TCGv_vec t, TCGv_vec sat, + TCGv_vec a, TCGv_vec b) +{ + TCGv_vec x = tcg_temp_new_vec_matching(s, t); + tcg_gen_sub_vec(s, vece, x, a, b); + tcg_gen_sssub_vec(s, vece, t, a, b); + tcg_gen_cmp_vec(s, TCG_COND_NE, vece, x, x, t); + tcg_gen_or_vec(s, vece, sat, sat, x); + tcg_temp_free_vec(s, x); +} + +const GVecGen4 sqsub_op[4] = { + { .fniv = gen_sqsub_vec, + .fno = gen_helper_gvec_sqsub_b, + .opc = INDEX_op_sssub_vec, + .write_aofs = true, + .vece = MO_8 }, + { .fniv = gen_sqsub_vec, + .fno = gen_helper_gvec_sqsub_h, + .opc = INDEX_op_sssub_vec, + .write_aofs = true, + .vece = MO_16 }, + { .fniv = gen_sqsub_vec, + .fno = gen_helper_gvec_sqsub_s, + .opc = INDEX_op_sssub_vec, + .write_aofs = true, + .vece = MO_32 }, + { .fniv = gen_sqsub_vec, + .fno = gen_helper_gvec_sqsub_d, + .opc = INDEX_op_sssub_vec, + .write_aofs = true, + .vece = MO_64 }, +}; + /* Translate a NEON data processing instruction. Return nonzero if the instruction is invalid. We process data in a mixture of 32-bit and 64-bit chunks. @@ -6493,6 +6629,18 @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn) } return 0; + case NEON_3R_VQADD: + tcg_gen_gvec_4(tcg_ctx, rd_ofs, offsetof(CPUARMState, vfp.qc), + rn_ofs, rm_ofs, vec_size, vec_size, + (u ? uqadd_op : sqadd_op) + size); + break; + + case NEON_3R_VQSUB: + tcg_gen_gvec_4(tcg_ctx, rd_ofs, offsetof(CPUARMState, vfp.qc), + rn_ofs, rm_ofs, vec_size, vec_size, + (u ? uqsub_op : sqsub_op) + size); + break; + case NEON_3R_VMUL: /* VMUL */ if (u) { /* Polynomial case allows only P8 and is handled below. */ @@ -6557,24 +6705,6 @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn) neon_load_reg64(s, s->V0, rn + pass); neon_load_reg64(s, s->V1, rm + pass); switch (op) { - case NEON_3R_VQADD: - if (u) { - gen_helper_neon_qadd_u64(tcg_ctx, s->V0, tcg_ctx->cpu_env, - s->V0, s->V1); - } else { - gen_helper_neon_qadd_s64(tcg_ctx, s->V0, tcg_ctx->cpu_env, - s->V0, s->V1); - } - break; - case NEON_3R_VQSUB: - if (u) { - gen_helper_neon_qsub_u64(tcg_ctx, s->V0, tcg_ctx->cpu_env, - s->V0, s->V1); - } else { - gen_helper_neon_qsub_s64(tcg_ctx, s->V0, tcg_ctx->cpu_env, - s->V0, s->V1); - } - break; case NEON_3R_VSHL: if (u) { gen_helper_neon_shl_u64(tcg_ctx, s->V0, s->V1, s->V0); @@ -6690,18 +6820,12 @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn) case NEON_3R_VHADD: GEN_NEON_INTEGER_OP(hadd); break; - case NEON_3R_VQADD: - GEN_NEON_INTEGER_OP_ENV(qadd); - break; case NEON_3R_VRHADD: GEN_NEON_INTEGER_OP(rhadd); break; case NEON_3R_VHSUB: GEN_NEON_INTEGER_OP(hsub); break; - case NEON_3R_VQSUB: - GEN_NEON_INTEGER_OP_ENV(qsub); - break; case NEON_3R_VSHL: GEN_NEON_INTEGER_OP(shl); break; diff --git a/qemu/target/arm/translate.h b/qemu/target/arm/translate.h index 09a72830..f5ecdbf1 100644 --- a/qemu/target/arm/translate.h +++ b/qemu/target/arm/translate.h @@ -213,6 +213,10 @@ extern const GVecGen2i ssra_op[4]; extern const GVecGen2i usra_op[4]; extern const GVecGen2i sri_op[4]; extern const GVecGen2i sli_op[4]; +extern const GVecGen4 uqadd_op[4]; +extern const GVecGen4 sqadd_op[4]; +extern const GVecGen4 uqsub_op[4]; +extern const GVecGen4 sqsub_op[4]; void gen_cmtst_i64(TCGContext* tcg_ctx, TCGv_i64 d, TCGv_i64 a, TCGv_i64 b); /* diff --git a/qemu/target/arm/vec_helper.c b/qemu/target/arm/vec_helper.c index 930d7151..41f58e1f 100644 --- a/qemu/target/arm/vec_helper.c +++ b/qemu/target/arm/vec_helper.c @@ -767,3 +767,134 @@ DO_FMLA_IDX(gvec_fmla_idx_s, float32, H4) DO_FMLA_IDX(gvec_fmla_idx_d, float64, ) #undef DO_FMLA_IDX + +#define DO_SAT(NAME, WTYPE, TYPEN, TYPEM, OP, MIN, MAX) \ +void HELPER(NAME)(void *vd, void *vq, void *vn, void *vm, uint32_t desc) \ +{ \ + intptr_t i, oprsz = simd_oprsz(desc); \ + TYPEN *d = vd, *n = vn; TYPEM *m = vm; \ + bool q = false; \ + for (i = 0; i < oprsz / sizeof(TYPEN); i++) { \ + WTYPE dd = (WTYPE)n[i] OP m[i]; \ + if (dd < MIN) { \ + dd = MIN; \ + q = true; \ + } else if (dd > MAX) { \ + dd = MAX; \ + q = true; \ + } \ + d[i] = dd; \ + } \ + if (q) { \ + uint32_t *qc = vq; \ + qc[0] = 1; \ + } \ + clear_tail(d, oprsz, simd_maxsz(desc)); \ +} + +DO_SAT(gvec_uqadd_b, int, uint8_t, uint8_t, +, 0, UINT8_MAX) +DO_SAT(gvec_uqadd_h, int, uint16_t, uint16_t, +, 0, UINT16_MAX) +DO_SAT(gvec_uqadd_s, int64_t, uint32_t, uint32_t, +, 0, UINT32_MAX) + +DO_SAT(gvec_sqadd_b, int, int8_t, int8_t, +, INT8_MIN, INT8_MAX) +DO_SAT(gvec_sqadd_h, int, int16_t, int16_t, +, INT16_MIN, INT16_MAX) +DO_SAT(gvec_sqadd_s, int64_t, int32_t, int32_t, +, INT32_MIN, INT32_MAX) + +DO_SAT(gvec_uqsub_b, int, uint8_t, uint8_t, -, 0, UINT8_MAX) +DO_SAT(gvec_uqsub_h, int, uint16_t, uint16_t, -, 0, UINT16_MAX) +DO_SAT(gvec_uqsub_s, int64_t, uint32_t, uint32_t, -, 0, UINT32_MAX) + +DO_SAT(gvec_sqsub_b, int, int8_t, int8_t, -, INT8_MIN, INT8_MAX) +DO_SAT(gvec_sqsub_h, int, int16_t, int16_t, -, INT16_MIN, INT16_MAX) +DO_SAT(gvec_sqsub_s, int64_t, int32_t, int32_t, -, INT32_MIN, INT32_MAX) + +#undef DO_SAT + +void HELPER(gvec_uqadd_d)(void *vd, void *vq, void *vn, + void *vm, uint32_t desc) +{ + intptr_t i, oprsz = simd_oprsz(desc); + uint64_t *d = vd, *n = vn, *m = vm; + bool q = false; + + for (i = 0; i < oprsz / 8; i++) { + uint64_t nn = n[i], mm = m[i], dd = nn + mm; + if (dd < nn) { + dd = UINT64_MAX; + q = true; + } + d[i] = dd; + } + if (q) { + uint32_t *qc = vq; + qc[0] = 1; + } + clear_tail(d, oprsz, simd_maxsz(desc)); +} + +void HELPER(gvec_uqsub_d)(void *vd, void *vq, void *vn, + void *vm, uint32_t desc) +{ + intptr_t i, oprsz = simd_oprsz(desc); + uint64_t *d = vd, *n = vn, *m = vm; + bool q = false; + + for (i = 0; i < oprsz / 8; i++) { + uint64_t nn = n[i], mm = m[i], dd = nn - mm; + if (nn < mm) { + dd = 0; + q = true; + } + d[i] = dd; + } + if (q) { + uint32_t *qc = vq; + qc[0] = 1; + } + clear_tail(d, oprsz, simd_maxsz(desc)); +} + +void HELPER(gvec_sqadd_d)(void *vd, void *vq, void *vn, + void *vm, uint32_t desc) +{ + intptr_t i, oprsz = simd_oprsz(desc); + int64_t *d = vd, *n = vn, *m = vm; + bool q = false; + + for (i = 0; i < oprsz / 8; i++) { + int64_t nn = n[i], mm = m[i], dd = nn + mm; + if (((dd ^ nn) & ~(nn ^ mm)) & INT64_MIN) { + dd = (nn >> 63) ^ ~INT64_MIN; + q = true; + } + d[i] = dd; + } + if (q) { + uint32_t *qc = vq; + qc[0] = 1; + } + clear_tail(d, oprsz, simd_maxsz(desc)); +} + +void HELPER(gvec_sqsub_d)(void *vd, void *vq, void *vn, + void *vm, uint32_t desc) +{ + intptr_t i, oprsz = simd_oprsz(desc); + int64_t *d = vd, *n = vn, *m = vm; + bool q = false; + + for (i = 0; i < oprsz / 8; i++) { + int64_t nn = n[i], mm = m[i], dd = nn - mm; + if (((dd ^ nn) & (nn ^ mm)) & INT64_MIN) { + dd = (nn >> 63) ^ ~INT64_MIN; + q = true; + } + d[i] = dd; + } + if (q) { + uint32_t *qc = vq; + qc[0] = 1; + } + clear_tail(d, oprsz, simd_maxsz(desc)); +} + diff --git a/qemu/x86_64.h b/qemu/x86_64.h index a57dc2be..319ff1d1 100644 --- a/qemu/x86_64.h +++ b/qemu/x86_64.h @@ -1229,6 +1229,14 @@ #define helper_gvec_smin16 helper_gvec_smin16_x86_64 #define helper_gvec_smin32 helper_gvec_smin32_x86_64 #define helper_gvec_smin64 helper_gvec_smin64_x86_64 +#define helper_gvec_sqadd_b helper_gvec_sqadd_b_x86_64 +#define helper_gvec_sqadd_d helper_gvec_sqadd_d_x86_64 +#define helper_gvec_sqadd_h helper_gvec_sqadd_h_x86_64 +#define helper_gvec_sqadd_s helper_gvec_sqadd_s_x86_64 +#define helper_gvec_sqsub_b helper_gvec_sqsub_b_x86_64 +#define helper_gvec_sqsub_d helper_gvec_sqsub_d_x86_64 +#define helper_gvec_sqsub_h helper_gvec_sqsub_h_x86_64 +#define helper_gvec_sqsub_s helper_gvec_sqsub_s_x86_64 #define helper_gvec_sub8 helper_gvec_sub8_x86_64 #define helper_gvec_sub16 helper_gvec_sub16_x86_64 #define helper_gvec_sub32 helper_gvec_sub32_x86_64 @@ -1257,6 +1265,14 @@ #define helper_gvec_umin16 helper_gvec_umin16_x86_64 #define helper_gvec_umin32 helper_gvec_umin32_x86_64 #define helper_gvec_umin64 helper_gvec_umin64_x86_64 +#define helper_gvec_uqadd_b helper_gvec_uqadd_b_x86_64 +#define helper_gvec_uqadd_d helper_gvec_uqadd_d_x86_64 +#define helper_gvec_uqadd_h helper_gvec_uqadd_h_x86_64 +#define helper_gvec_uqadd_s helper_gvec_uqadd_s_x86_64 +#define helper_gvec_uqsub_b helper_gvec_uqsub_b_x86_64 +#define helper_gvec_uqsub_d helper_gvec_uqsub_d_x86_64 +#define helper_gvec_uqsub_h helper_gvec_uqsub_h_x86_64 +#define helper_gvec_uqsub_s helper_gvec_uqsub_s_x86_64 #define helper_gvec_usadd8 helper_gvec_usadd8_x86_64 #define helper_gvec_usadd16 helper_gvec_usadd16_x86_64 #define helper_gvec_usadd32 helper_gvec_usadd32_x86_64