Hi, Carl

Not commenting on the implementation.

Please stop using powerpc*-*-* in the test cases.  The test cases
already are in the gcc.target/powerpc directory.

Do the test cases really need lp64, or should this require something
like int128?

Thanks, David

On Fri, Oct 23, 2020 at 9:56 PM Carl Love <c...@us.ibm.com> wrote:
>
>
> Gcc maintainers:
>
> The following patch adds support for the built-ins listed in Table B.1,
> "Binary-Coded Decimal Built-In Functions" of the "64-Bit ELF V2 ABI
> Specification", July 30, 2019.
>
> The built-ins adds support the V16QI type for addition, subtraction and
> comparison as sepcified in the Table B.1.  Note, the V1TI type was
> previously supported for add, subtract and comparison.  The builtins
> for test for valid value, multiply by 10, divide by 10 and conversion
> to DFP value are also added for the V16QI type as specified in Table
> B.1.
>
> The patch includes adding the #include <altivec.h> to the existing bcd-
> 2.c and bcd-3.c tests so they will pass the regression tests as the
> builtins names are now listed in altivec.h rather then just using
> internal names.
>
> The patch was compiled and tested on:
>
>   powerpc64le-unknown-linux-gnu (Power 9 LE)
>
> with no regressions.
>
> Please let me know if this patch is acceptable for mainline.  Thanks.
>
>                 Carl Love
> --------------------------------------------------
>
> gcc/ChangeLog
>
> 2020-10-22  Carl Love  <c...@us.ibm.com>
>
>         * 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.
>         * confit/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.
>         * testsuite/gcc.target/powerpc/bcd-3.c: Add include altivec.h.
>         * testsuite/gcc.target/powerpc/bcd-4.c: New test.
> ---
>  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 | 519 +++++++++++++++++++++++
>  9 files changed, 821 insertions(+), 36 deletions(-)
>  create mode 100644 gcc/testsuite/gcc.target/powerpc/bcd-4.c
>
> 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_v16qi0001-Add-bcd-builtings-listed-in-appendix-B-of-the-ABI.patch
> +          || 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 5be1cbecf60..0b701ee506f 100644
> --- a/gcc/doc/extend.texi
> +++ b/gcc/doc/extend.texi
> @@ -20161,15 +20161,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..708ad7b6b3f
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/powerpc/bcd-4.c
> @@ -0,0 +1,519 @@
> +/* { dg-do compile { target { powerpc*-*-* && lp64 } } } */
> +/* { dg-require-effective-target power10_hw } */
> +/* { dg-options "-mdejagnu-cpu=power10 -O2" } */
> +/* { 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
> +}
> +
> --
> 2.17.1
>
>

Reply via email to