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 > >