public inbox for gcc-cvs@sourceware.org
help / color / mirror / Atom feed
* [gcc r11-4623] Add bcd builtings listed in appendix B of the ABI
@ 2020-11-02 17:30 Carl Love
  0 siblings, 0 replies; only message in thread
From: Carl Love @ 2020-11-02 17:30 UTC (permalink / raw)
  To: gcc-cvs

https://gcc.gnu.org/g:05161256d3d2a598966ca1cf676fa0e427570f73

commit r11-4623-g05161256d3d2a598966ca1cf676fa0e427570f73
Author: Carl Love <cel@us.ibm.com>
Date:   Mon Aug 31 16:12:31 2020 -0500

    Add bcd builtings listed in appendix B of the ABI
    
    2020-10-29  Carl Love  <cel@us.ibm.com>
    
    gcc/
            PR target/93449
            * config/rs6000/altivec.h (__builtin_bcdadd, __builtin_bcdadd_lt,
            __builtin_bcdadd_eq, __builtin_bcdadd_gt, __builtin_bcdadd_ofl,
            __builtin_bcdadd_ov, __builtin_bcdsub, __builtin_bcdsub_lt,
            __builtin_bcdsub_eq, __builtin_bcdsub_gt, __builtin_bcdsub_ofl,
            __builtin_bcdsub_ov, __builtin_bcdinvalid, __builtin_bcdmul10,
            __builtin_bcddiv10, __builtin_bcd2dfp, __builtin_bcdcmpeq,
            __builtin_bcdcmpgt, __builtin_bcdcmplt, __builtin_bcdcmpge,
            __builtin_bcdcmple): Add defines.
            * config/rs6000/altivec.md: Add UNSPEC_BCDSHIFT.
            (BCD_TEST): Add le, ge to code iterator.
            Add VBCD mode iterator.
            (bcd<bcd_add_sub>_test, *bcd<bcd_add_sub>_test2,
            bcd<bcd_add_sub>_<code>, bcd<bcd_add_sub>_<code>): Add mode to name.
            Change iterator from V1TI to VBCD.
            (*bcdinvalid_<mode>, bcdshift_v16qi): New define_insn.
            (bcdinvalid_<mode>, bcdmul10_v16qi, bcddiv10_v16qi): New define.
            * config/rs6000/dfp.md (dfp_denbcd_v16qi_inst): New define_insn.
            (dfp_denbcd_v16qi): New define_expand.
            * config/rs6000/rs6000-builtin.def (BU_P8V_MISC_1): New define.
            (BCDADD): Replaced with BCDADD_V1TI and BCDADD_V16QI.
            (BCDADD_LT): Replaced with BCDADD_LT_V1TI and BCDADD_LT_V16QI.
            (BCDADD_EQ): Replaced with BCDADD_EQ_V1TI and BCDADD_EQ_V16QI.
            (BCDADD_GT): Replaced with BCDADD_GT_V1TI and BCDADD_GT_V16QI.
            (BCDADD_OV): Replaced with BCDADD_OV_V1TI and BCDADD_OV_V16QI.
            (BCDSUB_V1TI, BCDSUB_V16QI, BCDSUB_LT_V1TI, BCDSUB_LT_V16QI,
            BCDSUB_LE_V1TI, BCDSUB_LE_V16QI, BCDSUB_EQ_V1TI, BCDSUB_EQ_V16QI,
            BCDSUB_GT_V1TI, BCDSUB_GT_V16QI, BCDSUB_GE_V1TI, BCDSUB_GE_V16QI,
            BCDSUB_OV_V1TI, BCDSUB_OV_V16QI, BCDINVALID_V1TI, BCDINVALID_V16QI,
            BCDMUL10_V16QI, BCDDIV10_V16QI, DENBCD_V16QI): New builtin definitions.
            (BCDADD, BCDADD_LT, BCDADD_EQ, BCDADD_GT, BCDADD_OV, BCDSUB, BCDSUB_LT,
            BCDSUB_LE, BCDSUB_EQ, BCDSUB_GT, BCDSUB_GE, BCDSUB_OV, BCDINVALID,
            BCDMUL10, BCDDIV10, DENBCD): New overload definitions.
            * config/rs6000/rs6000-call.c (P8V_BUILTIN_VEC_BCDADD, P8V_BUILTIN_VEC_BCDADD_LT,
            P8V_BUILTIN_VEC_BCDADD_EQ, P8V_BUILTIN_VEC_BCDADD_GT, P8V_BUILTIN_VEC_BCDADD_OV,
            P8V_BUILTIN_VEC_BCDINVALID, P9V_BUILTIN_VEC_BCDMUL10, P8V_BUILTIN_VEC_DENBCD.
            P8V_BUILTIN_VEC_BCDSUB, P8V_BUILTIN_VEC_BCDSUB_LT, P8V_BUILTIN_VEC_BCDSUB_LE,
            P8V_BUILTIN_VEC_BCDSUB_EQ, P8V_BUILTIN_VEC_BCDSUB_GT, P8V_BUILTIN_VEC_BCDSUB_GE,
            P8V_BUILTIN_VEC_BCDSUB_OV): New overloaded specifications.
            (CODE_FOR_bcdadd): Replaced with CODE_FOR_bcdadd_v16qi and CODE_FOR_bcdadd_v1ti.
            (CODE_FOR_bcdadd_lt): Replaced with CODE_FOR_bcdadd_lt_v16qi and CODE_FOR_bcdadd_lt_v1ti.
            (CODE_FOR_bcdadd_eq): Replaced with CODE_FOR_bcdadd_eq_v16qi and CODE_FOR_bcdadd_eq_v1ti.
            (CODE_FOR_bcdadd_gt): Replaced with CODE_FOR_bcdadd_gt_v16qi and CODE_FOR_bcdadd_gt_v1ti.
            (CODE_FOR_bcdsub): Replaced with CODE_FOR_bcdsub_v16qi and CODE_FOR_bcdsub_v1ti.
            (CODE_FOR_bcdsub_lt): Replaced with CODE_FOR_bcdsub_lt_v16qi and CODE_FOR_bcdsub_lt_v1ti.
            (CODE_FOR_bcdsub_eq): Replaced with CODE_FOR_bcdsub_eq_v16qi and CODE_FOR_bcdsub_eq_v1ti.
            (CODE_FOR_bcdsub_gt): Replaced with CODE_FOR_bcdsub_gt_v16qi and CODE_FOR_bcdsub_gt_v1ti.
            (rs6000_expand_ternop_builtin):  Add CODE_FOR_dfp_denbcd_v16qi to else if.
            * doc/extend.texi: Add documentation for new builtins.
    
    gcc/testsuite/
            * gcc.target/powerpc/bcd-2.c: Add include altivec.h.
            * gcc.target/powerpc/bcd-3.c: Add include altivec.h.
            * gcc.target/powerpc/bcd-4.c: New test.

Diff:
---
 gcc/config/rs6000/altivec.h              |  25 ++
 gcc/config/rs6000/altivec.md             | 104 +++++-
 gcc/config/rs6000/dfp.md                 |  22 ++
 gcc/config/rs6000/rs6000-builtin.def     |  67 +++-
 gcc/config/rs6000/rs6000-call.c          | 103 +++++-
 gcc/doc/extend.texi                      |  13 +
 gcc/testsuite/gcc.target/powerpc/bcd-2.c |   2 +
 gcc/testsuite/gcc.target/powerpc/bcd-3.c |   2 +
 gcc/testsuite/gcc.target/powerpc/bcd-4.c | 521 +++++++++++++++++++++++++++++++
 9 files changed, 823 insertions(+), 36 deletions(-)

diff --git a/gcc/config/rs6000/altivec.h b/gcc/config/rs6000/altivec.h
index df10a8c498d..e1884f51bd8 100644
--- a/gcc/config/rs6000/altivec.h
+++ b/gcc/config/rs6000/altivec.h
@@ -497,8 +497,33 @@
 
 #define vec_xlx __builtin_vec_vextulx
 #define vec_xrx __builtin_vec_vexturx
+
 #endif
 
+/* BCD builtins, map ABI builtin name to existing builtin name.  */
+#define __builtin_bcdadd     __builtin_vec_bcdadd
+#define __builtin_bcdadd_lt  __builtin_vec_bcdadd_lt
+#define __builtin_bcdadd_eq  __builtin_vec_bcdadd_eq
+#define __builtin_bcdadd_gt  __builtin_vec_bcdadd_gt
+#define __builtin_bcdadd_ofl __builtin_vec_bcdadd_ov
+#define __builtin_bcdadd_ov  __builtin_vec_bcdadd_ov
+#define __builtin_bcdsub     __builtin_vec_bcdsub
+#define __builtin_bcdsub_lt  __builtin_vec_bcdsub_lt
+#define __builtin_bcdsub_eq  __builtin_vec_bcdsub_eq
+#define __builtin_bcdsub_gt  __builtin_vec_bcdsub_gt
+#define __builtin_bcdsub_ofl __builtin_vec_bcdsub_ov
+#define __builtin_bcdsub_ov  __builtin_vec_bcdsub_ov
+#define __builtin_bcdinvalid __builtin_vec_bcdinvalid
+#define __builtin_bcdmul10   __builtin_vec_bcdmul10
+#define __builtin_bcddiv10   __builtin_vec_bcddiv10
+#define __builtin_bcd2dfp    __builtin_vec_denb2dfp
+#define __builtin_bcdcmpeq(a,b)   __builtin_vec_bcdsub_eq(a,b,0)
+#define __builtin_bcdcmpgt(a,b)   __builtin_vec_bcdsub_gt(a,b,0)
+#define __builtin_bcdcmplt(a,b)   __builtin_vec_bcdsub_lt(a,b,0)
+#define __builtin_bcdcmpge(a,b)   __builtin_vec_bcdsub_ge(a,b,0)
+#define __builtin_bcdcmple(a,b)   __builtin_vec_bcdsub_le(a,b,0)
+
+
 /* Predicates.
    For C++, we use templates in order to allow non-parenthesized arguments.
    For C, instead, we use macros since non-parenthesized arguments were
diff --git a/gcc/config/rs6000/altivec.md b/gcc/config/rs6000/altivec.md
index 0a2e634d6b0..6a6ce0f84ed 100644
--- a/gcc/config/rs6000/altivec.md
+++ b/gcc/config/rs6000/altivec.md
@@ -160,6 +160,7 @@
    UNSPEC_BCDADD
    UNSPEC_BCDSUB
    UNSPEC_BCD_OVERFLOW
+   UNSPEC_BCDSHIFT
    UNSPEC_VRLMI
    UNSPEC_VRLNM
    UNSPEC_VCFUGED
@@ -4410,12 +4411,13 @@
 (define_int_attr bcd_add_sub [(UNSPEC_BCDADD "add")
 			      (UNSPEC_BCDSUB "sub")])
 
-(define_code_iterator BCD_TEST [eq lt gt unordered])
+(define_code_iterator BCD_TEST [eq lt le gt ge unordered])
+(define_mode_iterator VBCD [V1TI V16QI])
 
-(define_insn "bcd<bcd_add_sub>"
-  [(set (match_operand:V1TI 0 "gpc_reg_operand" "=v")
-	(unspec:V1TI [(match_operand:V1TI 1 "gpc_reg_operand" "v")
-		      (match_operand:V1TI 2 "gpc_reg_operand" "v")
+(define_insn "bcd<bcd_add_sub>_<mode>"
+  [(set (match_operand:VBCD 0 "register_operand" "=v")
+	(unspec:VBCD [(match_operand:VBCD 1 "register_operand" "v")
+		      (match_operand:VBCD 2 "register_operand" "v")
 		      (match_operand:QI 3 "const_0_to_1_operand" "n")]
 		     UNSPEC_BCD_ADD_SUB))
    (clobber (reg:CCFP CR6_REGNO))]
@@ -4428,23 +4430,23 @@
 ;; UNORDERED test on an integer type (like V1TImode) is not defined.  The type
 ;; probably should be one that can go in the VMX (Altivec) registers, so we
 ;; can't use DDmode or DFmode.
-(define_insn "*bcd<bcd_add_sub>_test"
+(define_insn "*bcd<bcd_add_sub>_test_<mode>"
   [(set (reg:CCFP CR6_REGNO)
 	(compare:CCFP
-	 (unspec:V2DF [(match_operand:V1TI 1 "register_operand" "v")
-		       (match_operand:V1TI 2 "register_operand" "v")
+	 (unspec:V2DF [(match_operand:VBCD 1 "register_operand" "v")
+		       (match_operand:VBCD 2 "register_operand" "v")
 		       (match_operand:QI 3 "const_0_to_1_operand" "i")]
 		      UNSPEC_BCD_ADD_SUB)
 	 (match_operand:V2DF 4 "zero_constant" "j")))
-   (clobber (match_scratch:V1TI 0 "=v"))]
+   (clobber (match_scratch:VBCD 0 "=v"))]
   "TARGET_P8_VECTOR"
   "bcd<bcd_add_sub>. %0,%1,%2,%3"
   [(set_attr "type" "vecsimple")])
 
-(define_insn "*bcd<bcd_add_sub>_test2"
-  [(set (match_operand:V1TI 0 "register_operand" "=v")
-	(unspec:V1TI [(match_operand:V1TI 1 "register_operand" "v")
-		      (match_operand:V1TI 2 "register_operand" "v")
+(define_insn "*bcd<bcd_add_sub>_test2_<mode>"
+  [(set (match_operand:VBCD 0 "register_operand" "=v")
+	(unspec:VBCD [(match_operand:VBCD 1 "register_operand" "v")
+		      (match_operand:VBCD 2 "register_operand" "v")
 		      (match_operand:QI 3 "const_0_to_1_operand" "i")]
 		     UNSPEC_BCD_ADD_SUB))
    (set (reg:CCFP CR6_REGNO)
@@ -4540,15 +4542,15 @@
 }
    [(set_attr "type" "vecsimple")])
 
-(define_expand "bcd<bcd_add_sub>_<code>"
+(define_expand "bcd<bcd_add_sub>_<code>_<mode>"
   [(parallel [(set (reg:CCFP CR6_REGNO)
 		   (compare:CCFP
-		    (unspec:V2DF [(match_operand:V1TI 1 "register_operand")
-				  (match_operand:V1TI 2 "register_operand")
+		    (unspec:V2DF [(match_operand:VBCD 1 "register_operand")
+				  (match_operand:VBCD 2 "register_operand")
 				  (match_operand:QI 3 "const_0_to_1_operand")]
 				 UNSPEC_BCD_ADD_SUB)
 		    (match_dup 4)))
-	      (clobber (match_scratch:V1TI 5))])
+	      (clobber (match_scratch:VBCD 5))])
    (set (match_operand:SI 0 "register_operand")
 	(BCD_TEST:SI (reg:CCFP CR6_REGNO)
 		     (const_int 0)))]
@@ -4557,6 +4559,74 @@
   operands[4] = CONST0_RTX (V2DFmode);
 })
 
+(define_insn "*bcdinvalid_<mode>"
+  [(set (reg:CCFP CR6_REGNO)
+	(compare:CCFP
+	 (unspec:V2DF [(match_operand:VBCD 1 "register_operand" "v")]
+		      UNSPEC_BCDADD)
+	 (match_operand:V2DF 2 "zero_constant" "j")))
+   (clobber (match_scratch:VBCD 0 "=v"))]
+  "TARGET_P8_VECTOR"
+  "bcdadd. %0,%1,%1,0"
+  [(set_attr "type" "vecsimple")])
+
+(define_expand "bcdinvalid_<mode>"
+  [(parallel [(set (reg:CCFP CR6_REGNO)
+		   (compare:CCFP
+		    (unspec:V2DF [(match_operand:VBCD 1 "register_operand")]
+				 UNSPEC_BCDADD)
+		    (match_dup 2)))
+	      (clobber (match_scratch:VBCD 3))])
+   (set (match_operand:SI 0 "register_operand")
+	(unordered:SI (reg:CCFP CR6_REGNO)
+		      (const_int 0)))]
+  "TARGET_P8_VECTOR"
+{
+  operands[2] = CONST0_RTX (V2DFmode);
+})
+
+(define_insn "bcdshift_v16qi"
+  [(set (match_operand:V16QI 0 "register_operand" "=v")
+	(unspec:V16QI [(match_operand:V16QI 1 "register_operand" "v")
+		       (match_operand:V16QI 2 "register_operand" "v")
+		       (match_operand:QI 3 "const_0_to_1_operand" "n")]
+		     UNSPEC_BCDSHIFT))
+   (clobber (reg:CCFP CR6_REGNO))]
+  "TARGET_P8_VECTOR"
+  "bcds. %0,%1,%2,%3"
+  [(set_attr "type" "vecsimple")])
+
+(define_expand "bcdmul10_v16qi"
+  [(set (match_operand:V16QI 0 "register_operand")
+	(unspec:V16QI [(match_operand:V16QI 1 "register_operand")]
+		      UNSPEC_BCDSHIFT))
+   (clobber (reg:CCFP CR6_REGNO))]
+  "TARGET_P9_VECTOR"
+{
+  rtx one = gen_reg_rtx (V16QImode);
+
+  emit_insn (gen_altivec_vspltisb (one, const1_rtx));
+  emit_insn (gen_bcdshift_v16qi (operands[0], one, operands[1], const0_rtx));
+
+  DONE;
+})
+
+(define_expand "bcddiv10_v16qi"
+  [(set (match_operand:V16QI 0 "register_operand")
+	(unspec:V16QI [(match_operand:V16QI 1 "register_operand")]
+		      UNSPEC_BCDSHIFT))
+   (clobber (reg:CCFP CR6_REGNO))]
+  "TARGET_P9_VECTOR"
+{
+  rtx one = gen_reg_rtx (V16QImode);
+
+  emit_insn (gen_altivec_vspltisb (one, constm1_rtx));
+  emit_insn (gen_bcdshift_v16qi (operands[0], one, operands[1], const0_rtx));
+
+  DONE;
+})
+
+
 ;; Peephole2 pattern to combine a bcdadd/bcdsub that calculates the value and
 ;; the bcdadd/bcdsub that tests the value.  The combiner won't work since
 ;; CR6 is a hard coded register.  Unfortunately, all of the Altivec predicate
diff --git a/gcc/config/rs6000/dfp.md b/gcc/config/rs6000/dfp.md
index 8f822732bac..9a952300cd6 100644
--- a/gcc/config/rs6000/dfp.md
+++ b/gcc/config/rs6000/dfp.md
@@ -273,6 +273,28 @@
   "denbcd<q> %1,%0,%2"
   [(set_attr "type" "dfp")])
 
+(define_insn "dfp_denbcd_v16qi_inst"
+  [(set (match_operand:TD 0 "gpc_reg_operand" "=d")
+	(unspec:TD [(match_operand:QI 1 "const_0_to_1_operand" "i")
+		    (match_operand:V16QI 2 "register_operand" "d")]
+		   UNSPEC_DENBCD))]
+  "TARGET_DFP"
+  "denbcdq %1,%0,%2"
+  [(set_attr "type" "dfp")])
+
+(define_expand "dfp_denbcd_v16qi"
+  [(set (match_operand:TD 0 "gpc_reg_operand" "=d")
+	(unspec:TD [(match_operand:V16QI 1 "register_operand" "v")]
+		   UNSPEC_DENBCD))]
+  "TARGET_DFP"
+ {
+   // Move vs128 upper 64-bits and lower 64-bits to fp register pair
+   convert_move (operands[0], operands[1], true);
+   emit_insn (gen_dfp_denbcd_v16qi_inst (operands[0], GEN_INT(1),
+					 operands[0]));
+   DONE;
+ })
+
 (define_insn "dfp_dxex_<mode>"
   [(set (match_operand:DI 0 "gpc_reg_operand" "=d")
 	(unspec:DI [(match_operand:DDTD 1 "gpc_reg_operand" "d")]
diff --git a/gcc/config/rs6000/rs6000-builtin.def b/gcc/config/rs6000/rs6000-builtin.def
index 5b05da87f4b..a58102c3785 100644
--- a/gcc/config/rs6000/rs6000-builtin.def
+++ b/gcc/config/rs6000/rs6000-builtin.def
@@ -696,6 +696,14 @@
 /* Miscellaneous builtins for instructions added in ISA 2.07.  These
    instructions do require the ISA 2.07 vector support, but they aren't vector
    instructions.  */
+#define BU_P8V_MISC_1(ENUM, NAME, ATTR, ICODE)				\
+  RS6000_BUILTIN_1 (MISC_BUILTIN_ ## ENUM,		/* ENUM */	\
+		    "__builtin_" NAME,			/* NAME */	\
+		    RS6000_BTM_P8_VECTOR,		/* MASK */	\
+		    (RS6000_BTC_ ## ATTR		/* ATTR */	\
+		     | RS6000_BTC_UNARY),				\
+		    CODE_FOR_ ## ICODE)			/* ICODE */
+
 #define BU_P8V_MISC_3(ENUM, NAME, ATTR, ICODE)				\
   RS6000_BUILTIN_3 (MISC_BUILTIN_ ## ENUM,		/* ENUM */	\
 		    "__builtin_" NAME,			/* NAME */	\
@@ -2668,16 +2676,55 @@ BU_P7_MISC_1 (CBCDTD,		"cbcdtd",	CONST,	cbcdtd)
 BU_P7_MISC_2 (ADDG6S,		"addg6s",	CONST,	addg6s)
 
 /* 3 argument BCD functions added in ISA 2.07.  */
-BU_P8V_MISC_3 (BCDADD,		"bcdadd",	CONST,	bcdadd)
-BU_P8V_MISC_3 (BCDADD_LT,	"bcdadd_lt",	CONST,	bcdadd_lt)
-BU_P8V_MISC_3 (BCDADD_EQ,	"bcdadd_eq",	CONST,	bcdadd_eq)
-BU_P8V_MISC_3 (BCDADD_GT,	"bcdadd_gt",	CONST,	bcdadd_gt)
-BU_P8V_MISC_3 (BCDADD_OV,	"bcdadd_ov",	CONST,	bcdadd_unordered)
-BU_P8V_MISC_3 (BCDSUB,		"bcdsub",	CONST,	bcdsub)
-BU_P8V_MISC_3 (BCDSUB_LT,	"bcdsub_lt",	CONST,	bcdsub_lt)
-BU_P8V_MISC_3 (BCDSUB_EQ,	"bcdsub_eq",	CONST,	bcdsub_eq)
-BU_P8V_MISC_3 (BCDSUB_GT,	"bcdsub_gt",	CONST,	bcdsub_gt)
-BU_P8V_MISC_3 (BCDSUB_OV,	"bcdsub_ov",	CONST,	bcdsub_unordered)
+BU_P8V_MISC_3 (BCDADD_V1TI,	"bcdadd_v1ti",	CONST,	bcdadd_v1ti)
+BU_P8V_MISC_3 (BCDADD_V16QI,	"bcdadd_v16qi",	CONST,	bcdadd_v16qi)
+BU_P8V_MISC_3 (BCDADD_LT_V1TI,	"bcdadd_lt_v1ti",  CONST, bcdadd_lt_v1ti)
+BU_P8V_MISC_3 (BCDADD_LT_V16QI,	"bcdadd_lt_v16qi", CONST, bcdadd_lt_v16qi)
+BU_P8V_MISC_3 (BCDADD_EQ_V1TI,	"bcdadd_eq_v1ti",  CONST, bcdadd_eq_v1ti)
+BU_P8V_MISC_3 (BCDADD_EQ_V16QI,	"bcdadd_eq_v16qi", CONST, bcdadd_eq_v16qi)
+BU_P8V_MISC_3 (BCDADD_GT_V1TI,	"bcdadd_gt_v1ti",  CONST, bcdadd_gt_v1ti)
+BU_P8V_MISC_3 (BCDADD_GT_V16QI,	"bcdadd_gt_v16qi", CONST, bcdadd_gt_v16qi)
+BU_P8V_MISC_3 (BCDADD_OV_V1TI,	"bcdadd_ov_v1ti",  CONST, bcdadd_unordered_v1ti)
+BU_P8V_MISC_3 (BCDADD_OV_V16QI,	"bcdadd_ov_v16qi", CONST, bcdadd_unordered_v16qi)
+
+BU_P8V_MISC_3 (BCDSUB_V1TI,	"bcdsub_v1ti",	CONST,	bcdsub_v1ti)
+BU_P8V_MISC_3 (BCDSUB_V16QI,	"bcdsub_v16qi",	CONST,	bcdsub_v16qi)
+BU_P8V_MISC_3 (BCDSUB_LT_V1TI,	"bcdsub_lt_v1ti",  CONST, bcdsub_lt_v1ti)
+BU_P8V_MISC_3 (BCDSUB_LT_V16QI,	"bcdsub_lt_v16qi", CONST, bcdsub_lt_v16qi)
+BU_P8V_MISC_3 (BCDSUB_LE_V1TI,	"bcdsub_le_v1ti",  CONST, bcdsub_le_v1ti)
+BU_P8V_MISC_3 (BCDSUB_LE_V16QI,	"bcdsub_le_v16qi", CONST, bcdsub_le_v16qi)
+BU_P8V_MISC_3 (BCDSUB_EQ_V1TI,	"bcdsub_eq_v1ti",  CONST, bcdsub_eq_v1ti)
+BU_P8V_MISC_3 (BCDSUB_EQ_V16QI,	"bcdsub_eq_v16qi", CONST, bcdsub_eq_v16qi)
+BU_P8V_MISC_3 (BCDSUB_GT_V1TI,	"bcdsub_gt_v1ti",  CONST, bcdsub_gt_v1ti)
+BU_P8V_MISC_3 (BCDSUB_GT_V16QI,	"bcdsub_gt_v16qi", CONST, bcdsub_gt_v16qi)
+BU_P8V_MISC_3 (BCDSUB_GE_V1TI,	"bcdsub_ge_v1ti",  CONST, bcdsub_ge_v1ti)
+BU_P8V_MISC_3 (BCDSUB_GE_V16QI,	"bcdsub_ge_v16qi", CONST, bcdsub_ge_v16qi)
+BU_P8V_MISC_3 (BCDSUB_OV_V1TI,	"bcdsub_ov_v1ti",  CONST, bcdsub_unordered_v1ti)
+BU_P8V_MISC_3 (BCDSUB_OV_V16QI,	"bcdsub_ov_v16qi", CONST, bcdsub_unordered_v16qi)
+
+BU_P8V_MISC_1 (BCDINVALID_V1TI,	"bcdinvalid_v1ti",  CONST, bcdinvalid_v1ti)
+BU_P8V_MISC_1 (BCDINVALID_V16QI, "bcdinvalid_v16qi", CONST, bcdinvalid_v16qi)
+
+BU_P9V_AV_1 (BCDMUL10_V16QI, "bcdmul10_v16qi", CONST, bcdmul10_v16qi)
+BU_P9V_AV_1 (BCDDIV10_V16QI, "bcddiv10_v16qi", CONST, bcddiv10_v16qi)
+BU_P8V_MISC_1 (DENBCD_V16QI,	"denb2dfp_v16qi", CONST, dfp_denbcd_v16qi)
+
+BU_P8V_OVERLOAD_3 (BCDADD,	"bcdadd")
+BU_P8V_OVERLOAD_3 (BCDADD_LT,	"bcdadd_lt")
+BU_P8V_OVERLOAD_3 (BCDADD_EQ,	"bcdadd_eq")
+BU_P8V_OVERLOAD_3 (BCDADD_GT,	"bcdadd_gt")
+BU_P8V_OVERLOAD_3 (BCDADD_OV,	"bcdadd_ov")
+BU_P8V_OVERLOAD_3 (BCDSUB,	"bcdsub")
+BU_P8V_OVERLOAD_3 (BCDSUB_LT,	"bcdsub_lt")
+BU_P8V_OVERLOAD_3 (BCDSUB_LE,	"bcdsub_le")
+BU_P8V_OVERLOAD_3 (BCDSUB_EQ,	"bcdsub_eq")
+BU_P8V_OVERLOAD_3 (BCDSUB_GT,	"bcdsub_gt")
+BU_P8V_OVERLOAD_3 (BCDSUB_GE,	"bcdsub_ge")
+BU_P8V_OVERLOAD_3 (BCDSUB_OV,	"bcdsub_ov")
+BU_P8V_OVERLOAD_1 (BCDINVALID,	"bcdinvalid")
+BU_P9V_OVERLOAD_1 (BCDMUL10,	"bcdmul10")
+BU_P9V_OVERLOAD_1 (BCDDIV10,	"bcddiv10")
+BU_P8V_OVERLOAD_1 (DENBCD,	"denb2dfp")
 
 /* 2 argument pack/unpack 128-bit floating point types.  */
 BU_DFP_MISC_2 (PACK_TD,		"pack_dec128",		CONST,	packtd)
diff --git a/gcc/config/rs6000/rs6000-call.c b/gcc/config/rs6000/rs6000-call.c
index b044778a7ae..92378e958a9 100644
--- a/gcc/config/rs6000/rs6000-call.c
+++ b/gcc/config/rs6000/rs6000-call.c
@@ -985,6 +985,82 @@ const struct altivec_builtin_types altivec_overloaded_builtins[] = {
     RS6000_BTI_unsigned_V4SI, RS6000_BTI_V4SF, RS6000_BTI_INTSI, 0 },
   { ALTIVEC_BUILTIN_VEC_CTU, VSX_BUILTIN_XVCVDPUXDS_SCALE,
     RS6000_BTI_unsigned_V2DI, RS6000_BTI_V2DF, RS6000_BTI_INTSI, 0 },
+
+  { P8V_BUILTIN_VEC_BCDADD, MISC_BUILTIN_BCDADD_V1TI,
+    RS6000_BTI_V1TI, RS6000_BTI_V1TI, RS6000_BTI_V1TI, RS6000_BTI_INTSI },
+  { P8V_BUILTIN_VEC_BCDADD, MISC_BUILTIN_BCDADD_V16QI,
+    RS6000_BTI_unsigned_V16QI, RS6000_BTI_unsigned_V16QI,
+    RS6000_BTI_unsigned_V16QI, RS6000_BTI_INTSI },
+  { P8V_BUILTIN_VEC_BCDADD_LT, MISC_BUILTIN_BCDADD_LT_V1TI,
+    RS6000_BTI_INTSI, RS6000_BTI_V1TI, RS6000_BTI_V1TI, RS6000_BTI_INTSI },
+  { P8V_BUILTIN_VEC_BCDADD_LT, MISC_BUILTIN_BCDADD_LT_V16QI,
+    RS6000_BTI_INTSI, RS6000_BTI_unsigned_V16QI,
+    RS6000_BTI_unsigned_V16QI, RS6000_BTI_INTSI },
+  { P8V_BUILTIN_VEC_BCDADD_EQ, MISC_BUILTIN_BCDADD_EQ_V1TI,
+    RS6000_BTI_INTSI, RS6000_BTI_V1TI, RS6000_BTI_V1TI, RS6000_BTI_INTSI },
+  { P8V_BUILTIN_VEC_BCDADD_EQ, MISC_BUILTIN_BCDADD_EQ_V16QI,
+    RS6000_BTI_INTSI, RS6000_BTI_unsigned_V16QI,
+    RS6000_BTI_unsigned_V16QI, RS6000_BTI_INTSI },
+  { P8V_BUILTIN_VEC_BCDADD_GT, MISC_BUILTIN_BCDADD_GT_V1TI,
+    RS6000_BTI_INTSI, RS6000_BTI_V1TI, RS6000_BTI_V1TI, RS6000_BTI_INTSI },
+  { P8V_BUILTIN_VEC_BCDADD_GT, MISC_BUILTIN_BCDADD_GT_V16QI,
+    RS6000_BTI_INTSI, RS6000_BTI_unsigned_V16QI,
+    RS6000_BTI_unsigned_V16QI, RS6000_BTI_INTSI },
+  { P8V_BUILTIN_VEC_BCDADD_OV, MISC_BUILTIN_BCDADD_OV_V1TI,
+    RS6000_BTI_INTSI, RS6000_BTI_V1TI, RS6000_BTI_V1TI, RS6000_BTI_INTSI },
+  { P8V_BUILTIN_VEC_BCDADD_OV, MISC_BUILTIN_BCDADD_OV_V16QI,
+    RS6000_BTI_INTSI, RS6000_BTI_unsigned_V16QI,
+    RS6000_BTI_unsigned_V16QI, RS6000_BTI_INTSI },
+  { P8V_BUILTIN_VEC_BCDINVALID, MISC_BUILTIN_BCDINVALID_V1TI,
+    RS6000_BTI_INTSI, RS6000_BTI_V1TI, 0, 0 },
+  { P8V_BUILTIN_VEC_BCDINVALID, MISC_BUILTIN_BCDINVALID_V16QI,
+    RS6000_BTI_INTSI, RS6000_BTI_unsigned_V16QI, 0, 0 },
+
+  { P9V_BUILTIN_VEC_BCDMUL10, P9V_BUILTIN_BCDMUL10_V16QI,
+    RS6000_BTI_unsigned_V16QI, RS6000_BTI_unsigned_V16QI, 0, 0 },
+  { P9V_BUILTIN_VEC_BCDDIV10, P9V_BUILTIN_BCDDIV10_V16QI,
+    RS6000_BTI_unsigned_V16QI, RS6000_BTI_unsigned_V16QI, 0, 0 },
+
+  { P8V_BUILTIN_VEC_DENBCD, MISC_BUILTIN_DENBCD_V16QI,
+    RS6000_BTI_dfloat128, RS6000_BTI_unsigned_V16QI, 0, 0 },
+
+  { P8V_BUILTIN_VEC_BCDSUB, MISC_BUILTIN_BCDSUB_V1TI,
+    RS6000_BTI_V1TI, RS6000_BTI_V1TI, RS6000_BTI_V1TI, RS6000_BTI_INTSI },
+  { P8V_BUILTIN_VEC_BCDSUB, MISC_BUILTIN_BCDSUB_V16QI,
+    RS6000_BTI_unsigned_V16QI, RS6000_BTI_unsigned_V16QI,
+    RS6000_BTI_unsigned_V16QI, RS6000_BTI_INTSI },
+  { P8V_BUILTIN_VEC_BCDSUB_LT, MISC_BUILTIN_BCDSUB_LT_V1TI,
+    RS6000_BTI_INTSI, RS6000_BTI_V1TI, RS6000_BTI_V1TI, RS6000_BTI_INTSI },
+  { P8V_BUILTIN_VEC_BCDSUB_LT, MISC_BUILTIN_BCDSUB_LT_V16QI,
+    RS6000_BTI_INTSI, RS6000_BTI_unsigned_V16QI,
+    RS6000_BTI_unsigned_V16QI, RS6000_BTI_INTSI },
+  { P8V_BUILTIN_VEC_BCDSUB_LE, MISC_BUILTIN_BCDSUB_LE_V1TI,
+    RS6000_BTI_INTSI, RS6000_BTI_V1TI, RS6000_BTI_V1TI, RS6000_BTI_INTSI },
+  { P8V_BUILTIN_VEC_BCDSUB_LE, MISC_BUILTIN_BCDSUB_LE_V16QI,
+    RS6000_BTI_INTSI, RS6000_BTI_unsigned_V16QI,
+    RS6000_BTI_unsigned_V16QI, RS6000_BTI_INTSI },
+  { P8V_BUILTIN_VEC_BCDSUB_EQ, MISC_BUILTIN_BCDSUB_EQ_V1TI,
+    RS6000_BTI_INTSI, RS6000_BTI_V1TI, RS6000_BTI_V1TI, RS6000_BTI_INTSI },
+  { P8V_BUILTIN_VEC_BCDSUB_EQ, MISC_BUILTIN_BCDSUB_EQ_V16QI,
+    RS6000_BTI_INTSI, RS6000_BTI_unsigned_V16QI,
+    RS6000_BTI_unsigned_V16QI, RS6000_BTI_INTSI },
+  { P8V_BUILTIN_VEC_BCDSUB_GT, MISC_BUILTIN_BCDSUB_GT_V1TI,
+    RS6000_BTI_INTSI, RS6000_BTI_V1TI,  RS6000_BTI_V1TI, RS6000_BTI_INTSI },
+  { P8V_BUILTIN_VEC_BCDSUB_GT, MISC_BUILTIN_BCDSUB_GT_V16QI,
+    RS6000_BTI_INTSI, RS6000_BTI_unsigned_V16QI,
+    RS6000_BTI_unsigned_V16QI, RS6000_BTI_INTSI },
+  { P8V_BUILTIN_VEC_BCDSUB_GE, MISC_BUILTIN_BCDSUB_GE_V1TI,
+    RS6000_BTI_INTSI, RS6000_BTI_V1TI,  RS6000_BTI_V1TI, RS6000_BTI_INTSI },
+  { P8V_BUILTIN_VEC_BCDSUB_GE, MISC_BUILTIN_BCDSUB_GE_V16QI,
+    RS6000_BTI_INTSI, RS6000_BTI_unsigned_V16QI,
+    RS6000_BTI_unsigned_V16QI, RS6000_BTI_INTSI },
+  { P8V_BUILTIN_VEC_BCDSUB_OV, MISC_BUILTIN_BCDSUB_OV_V1TI,
+    RS6000_BTI_INTSI, RS6000_BTI_V1TI, RS6000_BTI_V1TI, RS6000_BTI_INTSI },
+  { P8V_BUILTIN_VEC_BCDSUB_OV, MISC_BUILTIN_BCDSUB_OV_V16QI,
+    RS6000_BTI_INTSI, RS6000_BTI_unsigned_V16QI,
+    RS6000_BTI_unsigned_V16QI, RS6000_BTI_INTSI },
+
+
   { VSX_BUILTIN_VEC_DIV, VSX_BUILTIN_XVDIVSP,
     RS6000_BTI_V4SF, RS6000_BTI_V4SF, RS6000_BTI_V4SF, 0 },
   { VSX_BUILTIN_VEC_DIV, VSX_BUILTIN_XVDIVDP,
@@ -10570,14 +10646,22 @@ rs6000_expand_ternop_builtin (enum insn_code icode, tree exp, rtx target)
     }
   else if (icode == CODE_FOR_vsx_set_v2df
            || icode == CODE_FOR_vsx_set_v2di
-	   || icode == CODE_FOR_bcdadd
-	   || icode == CODE_FOR_bcdadd_lt
-	   || icode == CODE_FOR_bcdadd_eq
-	   || icode == CODE_FOR_bcdadd_gt
-	   || icode == CODE_FOR_bcdsub
-	   || icode == CODE_FOR_bcdsub_lt
-	   || icode == CODE_FOR_bcdsub_eq
-	   || icode == CODE_FOR_bcdsub_gt)
+	   || icode == CODE_FOR_bcdadd_v16qi
+	   || icode == CODE_FOR_bcdadd_v1ti
+	   || icode == CODE_FOR_bcdadd_lt_v16qi
+	   || icode == CODE_FOR_bcdadd_lt_v1ti
+	   || icode == CODE_FOR_bcdadd_eq_v16qi
+	   || icode == CODE_FOR_bcdadd_eq_v1ti
+	   || icode == CODE_FOR_bcdadd_gt_v16qi
+	   || icode == CODE_FOR_bcdadd_gt_v1ti
+	   || icode == CODE_FOR_bcdsub_v16qi
+	   || icode == CODE_FOR_bcdsub_v1ti
+	   || icode == CODE_FOR_bcdsub_lt_v16qi
+	   || icode == CODE_FOR_bcdsub_lt_v1ti
+	   || icode == CODE_FOR_bcdsub_eq_v16qi
+	   || icode == CODE_FOR_bcdsub_eq_v1ti
+	   || icode == CODE_FOR_bcdsub_gt_v16qi
+	   || icode == CODE_FOR_bcdsub_gt_v1ti)
     {
       /* Only allow 1-bit unsigned literals.  */
       STRIP_NOPS (arg2);
@@ -10601,7 +10685,8 @@ rs6000_expand_ternop_builtin (enum insn_code icode, tree exp, rtx target)
 	}
     }
   else if (icode == CODE_FOR_dfp_denbcd_dd
-	   || icode == CODE_FOR_dfp_denbcd_td)
+	   || icode == CODE_FOR_dfp_denbcd_td
+	   || icode == CODE_FOR_dfp_denbcd_v16qi)
     {
       /* Only allow 1-bit unsigned literals.  */
       STRIP_NOPS (arg0);
diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi
index f14772f7d38..7a6ecce6a84 100644
--- a/gcc/doc/extend.texi
+++ b/gcc/doc/extend.texi
@@ -20257,15 +20257,28 @@ __int128 vec_vsubuqm (__int128, __int128);
 __uint128 vec_vsubuqm (__uint128, __uint128);
 
 vector __int128 __builtin_bcdadd (vector __int128, vector __int128, const int);
+vector unsigned char __builtin_bcdadd (vector unsigned char, vector unsigned char,
+                                       const int);
 int __builtin_bcdadd_lt (vector __int128, vector __int128, const int);
+int __builtin_bcdadd_lt (vector unsigned char, vector unsigned char, const int);
 int __builtin_bcdadd_eq (vector __int128, vector __int128, const int);
+int __builtin_bcdadd_eq (vector unsigned char, vector unsigned char, const int);
 int __builtin_bcdadd_gt (vector __int128, vector __int128, const int);
+int __builtin_bcdadd_gt (vector unsigned char, vector unsigned char, const int);
 int __builtin_bcdadd_ov (vector __int128, vector __int128, const int);
+int __builtin_bcdadd_ov (vector unsigned char, vector unsigned char, const int);
+
 vector __int128 __builtin_bcdsub (vector __int128, vector __int128, const int);
+vector unsigned char __builtin_bcdsub (vector unsigned char, vector unsigned char,
+                                       const int);
 int __builtin_bcdsub_lt (vector __int128, vector __int128, const int);
+int __builtin_bcdsub_lt (vector unsigned char, vector unsigned char, const int);
 int __builtin_bcdsub_eq (vector __int128, vector __int128, const int);
+int __builtin_bcdsub_eq (vector unsigned char, vector unsigned char, const int);
 int __builtin_bcdsub_gt (vector __int128, vector __int128, const int);
+int __builtin_bcdsub_gt (vector unsigned char, vector unsigned char, const int);
 int __builtin_bcdsub_ov (vector __int128, vector __int128, const int);
+int __builtin_bcdsub_ov (vector unsigned char, vector unsigned char, const int);
 @end smallexample
 
 @node PowerPC AltiVec Built-in Functions Available on ISA 3.0
diff --git a/gcc/testsuite/gcc.target/powerpc/bcd-2.c b/gcc/testsuite/gcc.target/powerpc/bcd-2.c
index 2f51dee257f..95c3699a144 100644
--- a/gcc/testsuite/gcc.target/powerpc/bcd-2.c
+++ b/gcc/testsuite/gcc.target/powerpc/bcd-2.c
@@ -14,6 +14,8 @@
 /* { dg-final { scan-assembler-not   "stxvw4x" 	      } } */
 /* { dg-final { scan-assembler-not   "stxvd2x" 	      } } */
 
+#include <altivec.h>
+
 typedef __int128_t __attribute__((__vector_size__(16)))	vector_128_t;
 typedef __int128_t					scalar_128_t;
 typedef	unsigned long long				scalar_64_t;
diff --git a/gcc/testsuite/gcc.target/powerpc/bcd-3.c b/gcc/testsuite/gcc.target/powerpc/bcd-3.c
index 1b20841ae1c..7948a0c95e2 100644
--- a/gcc/testsuite/gcc.target/powerpc/bcd-3.c
+++ b/gcc/testsuite/gcc.target/powerpc/bcd-3.c
@@ -18,6 +18,8 @@ typedef __int128_t __attribute__((__vector_size__(16)))	vector_128_t;
 typedef __int128_t					scalar_128_t;
 typedef	unsigned long long				scalar_64_t;
 
+#include <altivec.h>
+
 /* Test whether the peephole works to allow folding a bcdadd, with a
    bcdadd_<test> into a single instruction.  */
 
diff --git a/gcc/testsuite/gcc.target/powerpc/bcd-4.c b/gcc/testsuite/gcc.target/powerpc/bcd-4.c
new file mode 100644
index 00000000000..2c8554dfe82
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/bcd-4.c
@@ -0,0 +1,521 @@
+/* { dg-do run } */
+/* { dg-require-effective-target int128 } */
+/* { dg-require-effective-target power10_hw } */
+/* { dg-options "-mdejagnu-cpu=power10 -O2 -save-temps" } */
+/* { dg-final { scan-assembler-times {\mbcdadd\M} 7 } } */
+/* { dg-final { scan-assembler-times {\mbcdsub\M} 18 } } */
+/* { dg-final { scan-assembler-times {\mbcds\M} 2 } } */
+/* { dg-final { scan-assembler-times {\mdenbcdq\M} 1 } } */
+
+#include <altivec.h>
+
+#define DEBUG 0
+
+#if DEBUG
+#include <stdio.h>
+#endif
+
+
+#define BCD_POS0  12    //  0xC
+#define BCD_POS1  15    //  0xF
+#define BCD_NEG   13    //  0xD
+
+void abort (void);
+
+  union conv_t
+    {
+      _Decimal128 d128;
+      vector  unsigned char ch;
+      vector  long long unsigned int vllui;
+    } conv;
+  
+_Decimal128 convert_vec_char (vector unsigned char a)
+{
+  union conv_t conv;
+  _Decimal128 result;
+  
+  conv.ch = a;
+  result = conv.d128;
+  return result;
+}
+			      
+vector unsigned char maxbcd(unsigned int sign)
+{
+  vector unsigned char result;
+  int i;
+
+  for (i = 15; i > 0; i--)
+    result[i] = 0x99;
+
+  result[0] = sign << 4 | 0x9;
+}
+
+vector unsigned char num2bcd(long int a, int encoding)
+{
+  int i;
+  unsigned int hi, low, sign;
+  
+  vector unsigned char result;
+
+  if (a > 0) {
+    if (encoding == 0)
+      sign = BCD_POS0;
+    else
+      sign = BCD_POS1;
+
+  } else {
+    sign = BCD_NEG;
+    a = -a;
+  }
+
+  hi = a % 10;   // 1st digit
+  a = a / 10;
+  result[0] = hi << 4| sign;
+
+  for (i = 1; i < 16; i++)
+    {
+      low = a % 10;
+      a = a / 10;
+      hi = a % 10;
+      a = a / 10;
+      result[i] = hi << 4 | low;
+    }
+
+
+  return result;
+}
+
+int main ()
+{
+  int i;
+  long int value_a, value_b, value_result;
+  vector unsigned char a, b, result, exp_result;
+  _Decimal128 result_d128, exp_result_d128;
+
+  /* Make a and b positive BCD numbers */
+  value_a = 1020304;
+  a = num2bcd(value_a, 0);
+
+  value_b = 101010;
+  b = num2bcd(value_b, 0);
+ 
+  value_result = value_a + value_b;
+  exp_result = num2bcd(value_result, 0);
+  
+  result = __builtin_bcdadd (a, b, 0);
+
+  for (i = 0; i < 16; i++)
+    if (exp_result[i] != result[i]) {
+
+#if DEBUG
+      printf("ERROR: __builtin_bcdadd result[%d] = %d does not match "
+	     "expected_result[%d] = %d\n",
+	     i, result[i], i, exp_result[i]);
+#else
+      abort();
+#endif
+    }
+
+  /* result should be positive */
+  if ((result[0] & 0xF) != BCD_POS0)
+#if DEBUG
+      printf("ERROR: __builtin_bcdadd sign of result is %d.  Does not match "
+	     "expected_result = %d\n",
+	     result[0] & 0xF, BCD_POS0);
+#else
+      abort();
+#endif
+
+  /* Make a and b positive BCD numbers using alternate positive encoding.  */
+  value_a = 1030507;
+  a = num2bcd(value_a, 1);
+
+  value_b = 204060;
+  b = num2bcd(value_b, 1);
+
+  value_result = value_a + value_b;
+  exp_result = num2bcd(value_result, 1);
+  
+  result = __builtin_bcdadd (a, b, 1);
+
+  for (i = 0; i < 16; i++)
+    if (exp_result[i] != result[i]) {
+#if DEBUG
+      printf("ERROR: __builtin_bcdadd result[%d] = %d does not match "
+	     "expected_result[%d] = %d\n",
+	     i, result[i], i, exp_result[i]);
+#else
+      abort();
+#endif
+    }
+
+  /* Result should be positive, alternate encoding.  */
+  if ((result[0] & 0xF) != BCD_POS1)
+#if DEBUG
+    printf("ERROR: __builtin_bcdadd sign of result is %d.  Does not "
+	   "match expected_result = %d\n",
+	     result[0] & 0xF, BCD_POS1);
+#else
+    abort();
+#endif
+
+  /* Make a and b negative BCD numbers */
+  value_a = -1030507;
+  a = num2bcd(value_a, 0);
+
+  value_b = -1010101;
+  b = num2bcd(value_b, 0);
+
+  value_result = value_a + value_b;
+  exp_result = num2bcd(value_result, 0);
+  
+  result = __builtin_bcdadd (a, b, 0);
+
+  for (i = 0; i < 16; i++)
+    if (exp_result[i]  != result[i]) {
+#if DEBUG
+      printf("ERROR: __builtin_bcdadd, neg result[%d] = %d does not match "
+	     "expected_result[%d] = %d\n",
+	     i, result[i], i, exp_result[i]);
+#else
+      abort();
+#endif
+    }
+
+  /* result should be negative */
+  if ((result[0] & 0xF) != BCD_NEG)
+#if DEBUG
+    printf("ERROR: __builtin_bcdadd sign, neg of result is %d.  Does not "
+	   "match expected_result = %d\n",
+	     result[0] & 0xF, BCD_NEG);
+#else
+    abort();
+#endif
+
+ 
+  /* Make a negative, b positive BCD numbers */
+  value_a = -1030507;
+  a = num2bcd(value_a, 0);
+
+  value_b = 1010101;
+  b = num2bcd(value_b, 0);
+
+  value_result = value_a - value_b;
+  exp_result = num2bcd(value_result, 0);
+  
+  result = __builtin_bcdsub (a, b, 0);
+
+  for (i = 0; i < 16; i++)
+    if (exp_result[i] != result[i]) {
+#if DEBUG
+      printf("ERROR: __builtin_bcdsub, neg result[%d] = %d does not match "
+	     "expected_result[%d] = %d\n",
+	     i, result[i], i, exp_result[i]);
+#else
+      abort();
+#endif
+    }
+
+  /* result should be positive, alt encoding */
+  if ((result[0] & 0xF) != BCD_NEG)
+#if DEBUG
+    printf("ERROR: __builtin_bcdadd sign, of result is %d.  Does not match "
+	   "expected_result = %d\n",
+	     result[0] & 0xF, BCD_NEG);
+#else
+    abort();
+#endif
+
+  /* Make a and b positive BCD numbers */
+  value_a = 1030507;
+  a = num2bcd(value_a, 1);
+
+  value_b = 1010101;
+  b = num2bcd(value_b, 1);
+
+  value_result = value_a - value_b;
+  exp_result = num2bcd(value_result, 1);
+  
+  result = __builtin_bcdsub (a, b, 1);
+
+  for (i = 0; i < 16; i++)
+    if (exp_result[i] != result[i]) {
+#if DEBUG
+      printf("ERROR:carll __builtin_bcdsub, pos result[%d] = %d does not "
+	     "match expected_result[%d] = %d\n",
+	     i, result[i], i, exp_result[i]);
+#else
+      abort();
+#endif
+    }
+
+  /* result should be positive */
+  if ((result[0] & 0xF) != BCD_POS1)
+#if DEBUG
+    printf("ERROR: __builtin_bcdsub sign, result is %d.  Does not match "
+	   "expected_result = %d\n",
+	     result[0] & 0xF, BCD_POS1);
+#else
+      abort();
+#endif
+
+  /* Test overflow add and subtract.  */
+  a = maxbcd(BCD_POS0);
+  b = maxbcd(BCD_POS0);
+
+  if(__builtin_bcdadd_ofl (a, b, 0) == 0)
+#if DEBUG
+    printf("ERROR: __builtin_bcdadd did not overflow as expected\n");
+#else
+    abort();
+#endif
+
+  value_a = 99999999;
+  a = num2bcd(value_a, 0);
+
+  value_b = 999999999;
+  b = num2bcd(value_b, 0);
+
+  if(__builtin_bcdadd_ofl (a, b, 0))
+#if DEBUG
+    printf("ERROR: __builtin_bcdadd unexpectedly overflowed\n");
+#else
+    abort();
+#endif
+
+  a = maxbcd(BCD_NEG);
+  b = maxbcd(BCD_NEG);
+
+  if (__builtin_bcdsub_ofl (a, b, 0) == 0)
+#if DEBUG
+    printf("ERROR: __builtin_bcdsub did not overflow as expected\n");
+#else
+    abort();
+#endif
+
+  value_a = -99999999;
+  a = num2bcd(value_a, 0);
+
+  value_b = -999999999;
+  b = num2bcd(value_b, 0);
+
+  if (__builtin_bcdsub_ofl (a, b, 0))
+#if DEBUG
+    printf("ERROR: __builtin_bcdsub unexpectedly overflowed\n");
+#else
+    abort();
+#endif
+
+  /* Test arguments for valid/invalid */
+  if (__builtin_bcdinvalid (a))
+#if DEBUG
+    printf("ERROR: __builtin_invalid input is unexpectedly invalid.\n");
+#else
+    abort();
+#endif
+
+  a[3] = 0xBB;     /* an invalid BCD digit */
+  if (!__builtin_bcdinvalid (a))
+#if DEBUG
+    printf("ERROR: __builtin_invalid input is unexpectedly valid.\n");
+#else
+    abort();
+#endif
+
+  value_a = 1020304;
+  a = num2bcd(value_a, 0);
+
+  value_b = 101010;
+  b = num2bcd(value_b, 0);
+
+  /* Test equality */
+  if (__builtin_bcdcmpeq (a, b))
+#if DEBUG
+    printf("ERROR: __builtin__bcdcmpeq result is unexpectedly 1.\n");
+#else
+    abort();
+#endif
+
+  if (!__builtin_bcdcmpeq (a, a))
+#if DEBUG
+    printf("ERROR: __builtin__bcdcmpeq result is unexpectedly 0.\n");
+#else
+    abort();
+#endif
+
+
+  /* Test a greater then b, inputs already setup this way.  */
+  if (!__builtin_bcdcmpgt (a, b))
+#if DEBUG
+    printf("ERROR: __builtin__bcdcmpgt result is unexpectedly 0.\n");
+#else
+    abort();
+#endif
+
+  if (__builtin_bcdcmpgt (b, a))
+#if DEBUG
+    printf("ERROR: __builtin__bcdcmpgt result is unexpectedly 1.\n");
+#else
+    abort();
+#endif
+
+  if (__builtin_bcdcmpgt (a, a))
+#if DEBUG
+    printf("ERROR: __builtin__bcdcmpgt input equal, result is unexpectedly "
+	   "1.\n");
+#else
+    abort();
+#endif
+
+
+  if (!__builtin_bcdcmpge (a, b))
+#if DEBUG
+    printf("ERROR: __builtin__bcdcmpge result is unexpectedly 0.\n");
+#else
+    abort();
+#endif
+
+  if (__builtin_bcdcmpge (b, a))
+#if DEBUG
+    printf("ERROR: __builtin__bcdcmpge result is unexpectedly 1.\n");
+#else
+    abort();
+#endif
+
+  if (!__builtin_bcdcmpge (b, b))
+#if DEBUG
+    printf("ERROR: __builtin__bcdcmpge inputs equal result is unexpectedly "
+	   "0.\n");
+#else
+    abort();
+#endif
+
+  /* Test a less then b.  */
+  value_a = 101010;
+  a = num2bcd(value_a, 0);
+  value_b = 1020304;
+  b = num2bcd(value_b, 0);
+
+  if (!__builtin_bcdcmplt (a, b))
+#if DEBUG
+    printf("ERROR: __builtin__bcdcmplt result is unexpectedly 0.\n");
+#else
+    abort();
+#endif
+
+  if (__builtin_bcdcmplt (b, a))
+#if DEBUG
+    printf("ERROR: __builtin__bcdcmplt result is unexpectedly 1.\n");
+#else
+    abort();
+#endif
+
+  if (__builtin_bcdcmplt (b, b))
+#if DEBUG
+    printf("ERROR: __builtin__bcdcmplt inputs equal result is unexpectedly "
+	   "1.\n");
+#else
+    abort();
+#endif
+
+
+  if (!__builtin_bcdcmple (a, b))
+#if DEBUG
+    printf("ERROR: __builtin__bcdcmple result is unexpectedly 0.\n");
+#else
+    abort();
+#endif
+
+  if (__builtin_bcdcmple (b, a))
+#if DEBUG
+    printf("ERROR: __builtin__bcdcmple result is unexpectedly 1.\n");
+#else
+    abort();
+#endif
+
+  if (!__builtin_bcdcmple (a, a))
+#if DEBUG
+    printf("ERROR: __builtin__bcdcmple inputs equal result is unexpectedly "
+	   "0.\n");
+#else
+    abort();
+#endif
+
+  /* Test multipy 10 */
+  value_a = 1020304;
+  a = num2bcd(value_a, 0);
+
+  value_result = value_a * 10;
+  exp_result = num2bcd(value_result, 0);
+  
+  result = __builtin_bcdmul10 (a);
+
+  for (i = 0; i < 16; i++)
+    if (exp_result[i] != result[i]) {
+#if DEBUG
+      printf("ERROR:carll __builtin_bcdmul10, pos result[%d] = %d does not "
+	     "match expected_result[%d] = %d\n",
+	     i, result[i], i, exp_result[i]);
+#else
+      abort();
+#endif
+    }
+
+  /* result should be positive */
+  if ((result[0] & 0xF) != BCD_POS0)
+#if 0
+    printf("ERROR: __builtin_bcdmul10 sign, result is %d.  Does not match "
+	   "expected_result = %d\n",
+	   result[0] & 0xF, BCD_POS1);
+#else
+    abort();
+#endif
+
+  /* Test divide 10 */
+  value_a = 1020304;
+  a = num2bcd(value_a, 0);
+
+  value_result = value_a / 10;
+  exp_result = num2bcd(value_result, 0);
+  
+  result = __builtin_bcddiv10 (a);
+
+  for (i = 0; i < 16; i++)
+    if (exp_result[i] != result[i]) {
+#if DEBUG
+      printf("ERROR:carll __builtin_bcddiv10, pos result[%d] = %d does not "
+	     "match expected_result[%d] = %d\n",
+	     i, result[i], i, exp_result[i]);
+#else
+      abort();
+#endif
+    }
+
+  /* result should be positive */
+  if ((result[0] & 0xF) != BCD_POS0)
+#if DEBUG
+    printf("ERROR: __builtin_bcddiv10 sign, result is %d.  Does not match "
+	   "expected_result = %d\n",
+	     result[0] & 0xF, BCD_POS1);
+#else
+    abort();
+#endif
+
+   value_a = 1020304;
+   exp_result_d128 = 1020304;
+   a = num2bcd(value_a, 0);
+
+   conv.ch = a;
+   conv.d128 = __builtin_bcd2dfp (a);
+   result_d128 = conv.d128;
+   
+   if (result_d128 != exp_result_d128)
+#if DEBUG
+     printf("ERROR: __builtin_bcd2dfp, result does not match expected_result."
+	    "\n");
+#else
+     abort();
+#endif
+     return 0;
+}
+


^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2020-11-02 17:30 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-11-02 17:30 [gcc r11-4623] Add bcd builtings listed in appendix B of the ABI Carl Love

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).