David: On Sat, 2020-10-24 at 11:29 -0400, David Edelsohn wrote: > 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
OK, I looked at the test case and it really needs 128-bit integer support. I changed the test case header to: +++ b/gcc/testsuite/gcc.target/powerpc/bcd-4.c @@ -0,0 +1,519 @@ +/* { dg-do compile { target int128 } } */ +/* { dg-require-effective-target power10_hw } */ +/* { dg-options "-mdejagnu-cpu=power10 -O2" } */ I reran the regression test. There were no regressions. Does the above look more reasonable? Carl -------------------------------------------------------------------- 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 ----------------------------------------------------------------- 2020-10-29 Carl Love <c...@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. * 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. gcc/testsuite/ * gcc.target/powerpc/bcd-3.c: Add include altivec.h. * 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_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 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..6d30e49126c --- /dev/null +++ b/gcc/testsuite/gcc.target/powerpc/bcd-4.c @@ -0,0 +1,519 @@ +/* { dg-do compile { target int128 } } */ +/* { 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