From: Carl Love Date: Mon, 31 Aug 2020 21:12:31 +0000 (-0500) Subject: Add bcd builtings listed in appendix B of the ABI X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=05161256d3d2a598966ca1cf676fa0e427570f73;p=gcc.git Add bcd builtings listed in appendix B of the ABI 2020-10-29 Carl Love 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_test, *bcd_test2, bcd_, bcd_): Add mode to name. Change iterator from V1TI to VBCD. (*bcdinvalid_, bcdshift_v16qi): New define_insn. (bcdinvalid_, bcdmul10_v16qi, bcddiv10_v16qi): New define. * config/rs6000/dfp.md (dfp_denbcd_v16qi_inst): New define_insn. (dfp_denbcd_v16qi): New define_expand. * config/rs6000/rs6000-builtin.def (BU_P8V_MISC_1): New define. (BCDADD): Replaced with BCDADD_V1TI and BCDADD_V16QI. (BCDADD_LT): Replaced with BCDADD_LT_V1TI and BCDADD_LT_V16QI. (BCDADD_EQ): Replaced with BCDADD_EQ_V1TI and BCDADD_EQ_V16QI. (BCDADD_GT): Replaced with BCDADD_GT_V1TI and BCDADD_GT_V16QI. (BCDADD_OV): Replaced with BCDADD_OV_V1TI and BCDADD_OV_V16QI. (BCDSUB_V1TI, BCDSUB_V16QI, BCDSUB_LT_V1TI, BCDSUB_LT_V16QI, BCDSUB_LE_V1TI, BCDSUB_LE_V16QI, BCDSUB_EQ_V1TI, BCDSUB_EQ_V16QI, BCDSUB_GT_V1TI, BCDSUB_GT_V16QI, BCDSUB_GE_V1TI, BCDSUB_GE_V16QI, BCDSUB_OV_V1TI, BCDSUB_OV_V16QI, BCDINVALID_V1TI, BCDINVALID_V16QI, BCDMUL10_V16QI, BCDDIV10_V16QI, DENBCD_V16QI): New builtin definitions. (BCDADD, BCDADD_LT, BCDADD_EQ, BCDADD_GT, BCDADD_OV, BCDSUB, BCDSUB_LT, BCDSUB_LE, BCDSUB_EQ, BCDSUB_GT, BCDSUB_GE, BCDSUB_OV, BCDINVALID, BCDMUL10, BCDDIV10, DENBCD): New overload definitions. * config/rs6000/rs6000-call.c (P8V_BUILTIN_VEC_BCDADD, P8V_BUILTIN_VEC_BCDADD_LT, P8V_BUILTIN_VEC_BCDADD_EQ, P8V_BUILTIN_VEC_BCDADD_GT, P8V_BUILTIN_VEC_BCDADD_OV, P8V_BUILTIN_VEC_BCDINVALID, P9V_BUILTIN_VEC_BCDMUL10, P8V_BUILTIN_VEC_DENBCD. P8V_BUILTIN_VEC_BCDSUB, P8V_BUILTIN_VEC_BCDSUB_LT, P8V_BUILTIN_VEC_BCDSUB_LE, P8V_BUILTIN_VEC_BCDSUB_EQ, P8V_BUILTIN_VEC_BCDSUB_GT, P8V_BUILTIN_VEC_BCDSUB_GE, P8V_BUILTIN_VEC_BCDSUB_OV): New overloaded specifications. (CODE_FOR_bcdadd): Replaced with CODE_FOR_bcdadd_v16qi and CODE_FOR_bcdadd_v1ti. (CODE_FOR_bcdadd_lt): Replaced with CODE_FOR_bcdadd_lt_v16qi and CODE_FOR_bcdadd_lt_v1ti. (CODE_FOR_bcdadd_eq): Replaced with CODE_FOR_bcdadd_eq_v16qi and CODE_FOR_bcdadd_eq_v1ti. (CODE_FOR_bcdadd_gt): Replaced with CODE_FOR_bcdadd_gt_v16qi and CODE_FOR_bcdadd_gt_v1ti. (CODE_FOR_bcdsub): Replaced with CODE_FOR_bcdsub_v16qi and CODE_FOR_bcdsub_v1ti. (CODE_FOR_bcdsub_lt): Replaced with CODE_FOR_bcdsub_lt_v16qi and CODE_FOR_bcdsub_lt_v1ti. (CODE_FOR_bcdsub_eq): Replaced with CODE_FOR_bcdsub_eq_v16qi and CODE_FOR_bcdsub_eq_v1ti. (CODE_FOR_bcdsub_gt): Replaced with CODE_FOR_bcdsub_gt_v16qi and CODE_FOR_bcdsub_gt_v1ti. (rs6000_expand_ternop_builtin): Add CODE_FOR_dfp_denbcd_v16qi to else if. * doc/extend.texi: Add documentation for new builtins. gcc/testsuite/ * gcc.target/powerpc/bcd-2.c: Add include altivec.h. * gcc.target/powerpc/bcd-3.c: Add include altivec.h. * gcc.target/powerpc/bcd-4.c: New test. --- diff --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" - [(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_" + [(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_test" +(define_insn "*bcd_test_" [(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. %0,%1,%2,%3" [(set_attr "type" "vecsimple")]) -(define_insn "*bcd_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_test2_" + [(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_" +(define_expand "bcd__" [(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_" + [(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_" + [(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 %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_" [(set (match_operand:DI 0 "gpc_reg_operand" "=d") (unspec:DI [(match_operand:DDTD 1 "gpc_reg_operand" "d")] diff --git a/gcc/config/rs6000/rs6000-builtin.def b/gcc/config/rs6000/rs6000-builtin.def index 5b05da87f4b..a58102c3785 100644 --- a/gcc/config/rs6000/rs6000-builtin.def +++ b/gcc/config/rs6000/rs6000-builtin.def @@ -696,6 +696,14 @@ /* Miscellaneous builtins for instructions added in ISA 2.07. These instructions do require the ISA 2.07 vector support, but they aren't vector instructions. */ +#define BU_P8V_MISC_1(ENUM, NAME, ATTR, ICODE) \ + RS6000_BUILTIN_1 (MISC_BUILTIN_ ## ENUM, /* ENUM */ \ + "__builtin_" NAME, /* NAME */ \ + RS6000_BTM_P8_VECTOR, /* MASK */ \ + (RS6000_BTC_ ## ATTR /* ATTR */ \ + | RS6000_BTC_UNARY), \ + CODE_FOR_ ## ICODE) /* ICODE */ + #define BU_P8V_MISC_3(ENUM, NAME, ATTR, ICODE) \ RS6000_BUILTIN_3 (MISC_BUILTIN_ ## ENUM, /* ENUM */ \ "__builtin_" NAME, /* NAME */ \ @@ -2668,16 +2676,55 @@ BU_P7_MISC_1 (CBCDTD, "cbcdtd", CONST, cbcdtd) BU_P7_MISC_2 (ADDG6S, "addg6s", CONST, addg6s) /* 3 argument BCD functions added in ISA 2.07. */ -BU_P8V_MISC_3 (BCDADD, "bcdadd", CONST, bcdadd) -BU_P8V_MISC_3 (BCDADD_LT, "bcdadd_lt", CONST, bcdadd_lt) -BU_P8V_MISC_3 (BCDADD_EQ, "bcdadd_eq", CONST, bcdadd_eq) -BU_P8V_MISC_3 (BCDADD_GT, "bcdadd_gt", CONST, bcdadd_gt) -BU_P8V_MISC_3 (BCDADD_OV, "bcdadd_ov", CONST, bcdadd_unordered) -BU_P8V_MISC_3 (BCDSUB, "bcdsub", CONST, bcdsub) -BU_P8V_MISC_3 (BCDSUB_LT, "bcdsub_lt", CONST, bcdsub_lt) -BU_P8V_MISC_3 (BCDSUB_EQ, "bcdsub_eq", CONST, bcdsub_eq) -BU_P8V_MISC_3 (BCDSUB_GT, "bcdsub_gt", CONST, bcdsub_gt) -BU_P8V_MISC_3 (BCDSUB_OV, "bcdsub_ov", CONST, bcdsub_unordered) +BU_P8V_MISC_3 (BCDADD_V1TI, "bcdadd_v1ti", CONST, bcdadd_v1ti) +BU_P8V_MISC_3 (BCDADD_V16QI, "bcdadd_v16qi", CONST, bcdadd_v16qi) +BU_P8V_MISC_3 (BCDADD_LT_V1TI, "bcdadd_lt_v1ti", CONST, bcdadd_lt_v1ti) +BU_P8V_MISC_3 (BCDADD_LT_V16QI, "bcdadd_lt_v16qi", CONST, bcdadd_lt_v16qi) +BU_P8V_MISC_3 (BCDADD_EQ_V1TI, "bcdadd_eq_v1ti", CONST, bcdadd_eq_v1ti) +BU_P8V_MISC_3 (BCDADD_EQ_V16QI, "bcdadd_eq_v16qi", CONST, bcdadd_eq_v16qi) +BU_P8V_MISC_3 (BCDADD_GT_V1TI, "bcdadd_gt_v1ti", CONST, bcdadd_gt_v1ti) +BU_P8V_MISC_3 (BCDADD_GT_V16QI, "bcdadd_gt_v16qi", CONST, bcdadd_gt_v16qi) +BU_P8V_MISC_3 (BCDADD_OV_V1TI, "bcdadd_ov_v1ti", CONST, bcdadd_unordered_v1ti) +BU_P8V_MISC_3 (BCDADD_OV_V16QI, "bcdadd_ov_v16qi", CONST, bcdadd_unordered_v16qi) + +BU_P8V_MISC_3 (BCDSUB_V1TI, "bcdsub_v1ti", CONST, bcdsub_v1ti) +BU_P8V_MISC_3 (BCDSUB_V16QI, "bcdsub_v16qi", CONST, bcdsub_v16qi) +BU_P8V_MISC_3 (BCDSUB_LT_V1TI, "bcdsub_lt_v1ti", CONST, bcdsub_lt_v1ti) +BU_P8V_MISC_3 (BCDSUB_LT_V16QI, "bcdsub_lt_v16qi", CONST, bcdsub_lt_v16qi) +BU_P8V_MISC_3 (BCDSUB_LE_V1TI, "bcdsub_le_v1ti", CONST, bcdsub_le_v1ti) +BU_P8V_MISC_3 (BCDSUB_LE_V16QI, "bcdsub_le_v16qi", CONST, bcdsub_le_v16qi) +BU_P8V_MISC_3 (BCDSUB_EQ_V1TI, "bcdsub_eq_v1ti", CONST, bcdsub_eq_v1ti) +BU_P8V_MISC_3 (BCDSUB_EQ_V16QI, "bcdsub_eq_v16qi", CONST, bcdsub_eq_v16qi) +BU_P8V_MISC_3 (BCDSUB_GT_V1TI, "bcdsub_gt_v1ti", CONST, bcdsub_gt_v1ti) +BU_P8V_MISC_3 (BCDSUB_GT_V16QI, "bcdsub_gt_v16qi", CONST, bcdsub_gt_v16qi) +BU_P8V_MISC_3 (BCDSUB_GE_V1TI, "bcdsub_ge_v1ti", CONST, bcdsub_ge_v1ti) +BU_P8V_MISC_3 (BCDSUB_GE_V16QI, "bcdsub_ge_v16qi", CONST, bcdsub_ge_v16qi) +BU_P8V_MISC_3 (BCDSUB_OV_V1TI, "bcdsub_ov_v1ti", CONST, bcdsub_unordered_v1ti) +BU_P8V_MISC_3 (BCDSUB_OV_V16QI, "bcdsub_ov_v16qi", CONST, bcdsub_unordered_v16qi) + +BU_P8V_MISC_1 (BCDINVALID_V1TI, "bcdinvalid_v1ti", CONST, bcdinvalid_v1ti) +BU_P8V_MISC_1 (BCDINVALID_V16QI, "bcdinvalid_v16qi", CONST, bcdinvalid_v16qi) + +BU_P9V_AV_1 (BCDMUL10_V16QI, "bcdmul10_v16qi", CONST, bcdmul10_v16qi) +BU_P9V_AV_1 (BCDDIV10_V16QI, "bcddiv10_v16qi", CONST, bcddiv10_v16qi) +BU_P8V_MISC_1 (DENBCD_V16QI, "denb2dfp_v16qi", CONST, dfp_denbcd_v16qi) + +BU_P8V_OVERLOAD_3 (BCDADD, "bcdadd") +BU_P8V_OVERLOAD_3 (BCDADD_LT, "bcdadd_lt") +BU_P8V_OVERLOAD_3 (BCDADD_EQ, "bcdadd_eq") +BU_P8V_OVERLOAD_3 (BCDADD_GT, "bcdadd_gt") +BU_P8V_OVERLOAD_3 (BCDADD_OV, "bcdadd_ov") +BU_P8V_OVERLOAD_3 (BCDSUB, "bcdsub") +BU_P8V_OVERLOAD_3 (BCDSUB_LT, "bcdsub_lt") +BU_P8V_OVERLOAD_3 (BCDSUB_LE, "bcdsub_le") +BU_P8V_OVERLOAD_3 (BCDSUB_EQ, "bcdsub_eq") +BU_P8V_OVERLOAD_3 (BCDSUB_GT, "bcdsub_gt") +BU_P8V_OVERLOAD_3 (BCDSUB_GE, "bcdsub_ge") +BU_P8V_OVERLOAD_3 (BCDSUB_OV, "bcdsub_ov") +BU_P8V_OVERLOAD_1 (BCDINVALID, "bcdinvalid") +BU_P9V_OVERLOAD_1 (BCDMUL10, "bcdmul10") +BU_P9V_OVERLOAD_1 (BCDDIV10, "bcddiv10") +BU_P8V_OVERLOAD_1 (DENBCD, "denb2dfp") /* 2 argument pack/unpack 128-bit floating point types. */ BU_DFP_MISC_2 (PACK_TD, "pack_dec128", CONST, packtd) diff --git a/gcc/config/rs6000/rs6000-call.c b/gcc/config/rs6000/rs6000-call.c index b044778a7ae..92378e958a9 100644 --- a/gcc/config/rs6000/rs6000-call.c +++ b/gcc/config/rs6000/rs6000-call.c @@ -985,6 +985,82 @@ const struct altivec_builtin_types altivec_overloaded_builtins[] = { RS6000_BTI_unsigned_V4SI, RS6000_BTI_V4SF, RS6000_BTI_INTSI, 0 }, { ALTIVEC_BUILTIN_VEC_CTU, VSX_BUILTIN_XVCVDPUXDS_SCALE, RS6000_BTI_unsigned_V2DI, RS6000_BTI_V2DF, RS6000_BTI_INTSI, 0 }, + + { P8V_BUILTIN_VEC_BCDADD, MISC_BUILTIN_BCDADD_V1TI, + RS6000_BTI_V1TI, RS6000_BTI_V1TI, RS6000_BTI_V1TI, RS6000_BTI_INTSI }, + { P8V_BUILTIN_VEC_BCDADD, MISC_BUILTIN_BCDADD_V16QI, + RS6000_BTI_unsigned_V16QI, RS6000_BTI_unsigned_V16QI, + RS6000_BTI_unsigned_V16QI, RS6000_BTI_INTSI }, + { P8V_BUILTIN_VEC_BCDADD_LT, MISC_BUILTIN_BCDADD_LT_V1TI, + RS6000_BTI_INTSI, RS6000_BTI_V1TI, RS6000_BTI_V1TI, RS6000_BTI_INTSI }, + { P8V_BUILTIN_VEC_BCDADD_LT, MISC_BUILTIN_BCDADD_LT_V16QI, + RS6000_BTI_INTSI, RS6000_BTI_unsigned_V16QI, + RS6000_BTI_unsigned_V16QI, RS6000_BTI_INTSI }, + { P8V_BUILTIN_VEC_BCDADD_EQ, MISC_BUILTIN_BCDADD_EQ_V1TI, + RS6000_BTI_INTSI, RS6000_BTI_V1TI, RS6000_BTI_V1TI, RS6000_BTI_INTSI }, + { P8V_BUILTIN_VEC_BCDADD_EQ, MISC_BUILTIN_BCDADD_EQ_V16QI, + RS6000_BTI_INTSI, RS6000_BTI_unsigned_V16QI, + RS6000_BTI_unsigned_V16QI, RS6000_BTI_INTSI }, + { P8V_BUILTIN_VEC_BCDADD_GT, MISC_BUILTIN_BCDADD_GT_V1TI, + RS6000_BTI_INTSI, RS6000_BTI_V1TI, RS6000_BTI_V1TI, RS6000_BTI_INTSI }, + { P8V_BUILTIN_VEC_BCDADD_GT, MISC_BUILTIN_BCDADD_GT_V16QI, + RS6000_BTI_INTSI, RS6000_BTI_unsigned_V16QI, + RS6000_BTI_unsigned_V16QI, RS6000_BTI_INTSI }, + { P8V_BUILTIN_VEC_BCDADD_OV, MISC_BUILTIN_BCDADD_OV_V1TI, + RS6000_BTI_INTSI, RS6000_BTI_V1TI, RS6000_BTI_V1TI, RS6000_BTI_INTSI }, + { P8V_BUILTIN_VEC_BCDADD_OV, MISC_BUILTIN_BCDADD_OV_V16QI, + RS6000_BTI_INTSI, RS6000_BTI_unsigned_V16QI, + RS6000_BTI_unsigned_V16QI, RS6000_BTI_INTSI }, + { P8V_BUILTIN_VEC_BCDINVALID, MISC_BUILTIN_BCDINVALID_V1TI, + RS6000_BTI_INTSI, RS6000_BTI_V1TI, 0, 0 }, + { P8V_BUILTIN_VEC_BCDINVALID, MISC_BUILTIN_BCDINVALID_V16QI, + RS6000_BTI_INTSI, RS6000_BTI_unsigned_V16QI, 0, 0 }, + + { P9V_BUILTIN_VEC_BCDMUL10, P9V_BUILTIN_BCDMUL10_V16QI, + RS6000_BTI_unsigned_V16QI, RS6000_BTI_unsigned_V16QI, 0, 0 }, + { P9V_BUILTIN_VEC_BCDDIV10, P9V_BUILTIN_BCDDIV10_V16QI, + RS6000_BTI_unsigned_V16QI, RS6000_BTI_unsigned_V16QI, 0, 0 }, + + { P8V_BUILTIN_VEC_DENBCD, MISC_BUILTIN_DENBCD_V16QI, + RS6000_BTI_dfloat128, RS6000_BTI_unsigned_V16QI, 0, 0 }, + + { P8V_BUILTIN_VEC_BCDSUB, MISC_BUILTIN_BCDSUB_V1TI, + RS6000_BTI_V1TI, RS6000_BTI_V1TI, RS6000_BTI_V1TI, RS6000_BTI_INTSI }, + { P8V_BUILTIN_VEC_BCDSUB, MISC_BUILTIN_BCDSUB_V16QI, + RS6000_BTI_unsigned_V16QI, RS6000_BTI_unsigned_V16QI, + RS6000_BTI_unsigned_V16QI, RS6000_BTI_INTSI }, + { P8V_BUILTIN_VEC_BCDSUB_LT, MISC_BUILTIN_BCDSUB_LT_V1TI, + RS6000_BTI_INTSI, RS6000_BTI_V1TI, RS6000_BTI_V1TI, RS6000_BTI_INTSI }, + { P8V_BUILTIN_VEC_BCDSUB_LT, MISC_BUILTIN_BCDSUB_LT_V16QI, + RS6000_BTI_INTSI, RS6000_BTI_unsigned_V16QI, + RS6000_BTI_unsigned_V16QI, RS6000_BTI_INTSI }, + { P8V_BUILTIN_VEC_BCDSUB_LE, MISC_BUILTIN_BCDSUB_LE_V1TI, + RS6000_BTI_INTSI, RS6000_BTI_V1TI, RS6000_BTI_V1TI, RS6000_BTI_INTSI }, + { P8V_BUILTIN_VEC_BCDSUB_LE, MISC_BUILTIN_BCDSUB_LE_V16QI, + RS6000_BTI_INTSI, RS6000_BTI_unsigned_V16QI, + RS6000_BTI_unsigned_V16QI, RS6000_BTI_INTSI }, + { P8V_BUILTIN_VEC_BCDSUB_EQ, MISC_BUILTIN_BCDSUB_EQ_V1TI, + RS6000_BTI_INTSI, RS6000_BTI_V1TI, RS6000_BTI_V1TI, RS6000_BTI_INTSI }, + { P8V_BUILTIN_VEC_BCDSUB_EQ, MISC_BUILTIN_BCDSUB_EQ_V16QI, + RS6000_BTI_INTSI, RS6000_BTI_unsigned_V16QI, + RS6000_BTI_unsigned_V16QI, RS6000_BTI_INTSI }, + { P8V_BUILTIN_VEC_BCDSUB_GT, MISC_BUILTIN_BCDSUB_GT_V1TI, + RS6000_BTI_INTSI, RS6000_BTI_V1TI, RS6000_BTI_V1TI, RS6000_BTI_INTSI }, + { P8V_BUILTIN_VEC_BCDSUB_GT, MISC_BUILTIN_BCDSUB_GT_V16QI, + RS6000_BTI_INTSI, RS6000_BTI_unsigned_V16QI, + RS6000_BTI_unsigned_V16QI, RS6000_BTI_INTSI }, + { P8V_BUILTIN_VEC_BCDSUB_GE, MISC_BUILTIN_BCDSUB_GE_V1TI, + RS6000_BTI_INTSI, RS6000_BTI_V1TI, RS6000_BTI_V1TI, RS6000_BTI_INTSI }, + { P8V_BUILTIN_VEC_BCDSUB_GE, MISC_BUILTIN_BCDSUB_GE_V16QI, + RS6000_BTI_INTSI, RS6000_BTI_unsigned_V16QI, + RS6000_BTI_unsigned_V16QI, RS6000_BTI_INTSI }, + { P8V_BUILTIN_VEC_BCDSUB_OV, MISC_BUILTIN_BCDSUB_OV_V1TI, + RS6000_BTI_INTSI, RS6000_BTI_V1TI, RS6000_BTI_V1TI, RS6000_BTI_INTSI }, + { P8V_BUILTIN_VEC_BCDSUB_OV, MISC_BUILTIN_BCDSUB_OV_V16QI, + RS6000_BTI_INTSI, RS6000_BTI_unsigned_V16QI, + RS6000_BTI_unsigned_V16QI, RS6000_BTI_INTSI }, + + { VSX_BUILTIN_VEC_DIV, VSX_BUILTIN_XVDIVSP, RS6000_BTI_V4SF, RS6000_BTI_V4SF, RS6000_BTI_V4SF, 0 }, { VSX_BUILTIN_VEC_DIV, VSX_BUILTIN_XVDIVDP, @@ -10570,14 +10646,22 @@ rs6000_expand_ternop_builtin (enum insn_code icode, tree exp, rtx target) } else if (icode == CODE_FOR_vsx_set_v2df || icode == CODE_FOR_vsx_set_v2di - || icode == CODE_FOR_bcdadd - || icode == CODE_FOR_bcdadd_lt - || icode == CODE_FOR_bcdadd_eq - || icode == CODE_FOR_bcdadd_gt - || icode == CODE_FOR_bcdsub - || icode == CODE_FOR_bcdsub_lt - || icode == CODE_FOR_bcdsub_eq - || icode == CODE_FOR_bcdsub_gt) + || icode == CODE_FOR_bcdadd_v16qi + || icode == CODE_FOR_bcdadd_v1ti + || icode == CODE_FOR_bcdadd_lt_v16qi + || icode == CODE_FOR_bcdadd_lt_v1ti + || icode == CODE_FOR_bcdadd_eq_v16qi + || icode == CODE_FOR_bcdadd_eq_v1ti + || icode == CODE_FOR_bcdadd_gt_v16qi + || icode == CODE_FOR_bcdadd_gt_v1ti + || icode == CODE_FOR_bcdsub_v16qi + || icode == CODE_FOR_bcdsub_v1ti + || icode == CODE_FOR_bcdsub_lt_v16qi + || icode == CODE_FOR_bcdsub_lt_v1ti + || icode == CODE_FOR_bcdsub_eq_v16qi + || icode == CODE_FOR_bcdsub_eq_v1ti + || icode == CODE_FOR_bcdsub_gt_v16qi + || icode == CODE_FOR_bcdsub_gt_v1ti) { /* Only allow 1-bit unsigned literals. */ STRIP_NOPS (arg2); @@ -10601,7 +10685,8 @@ rs6000_expand_ternop_builtin (enum insn_code icode, tree exp, rtx target) } } else if (icode == CODE_FOR_dfp_denbcd_dd - || icode == CODE_FOR_dfp_denbcd_td) + || icode == CODE_FOR_dfp_denbcd_td + || icode == CODE_FOR_dfp_denbcd_v16qi) { /* Only allow 1-bit unsigned literals. */ STRIP_NOPS (arg0); diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi index f14772f7d38..7a6ecce6a84 100644 --- a/gcc/doc/extend.texi +++ b/gcc/doc/extend.texi @@ -20257,15 +20257,28 @@ __int128 vec_vsubuqm (__int128, __int128); __uint128 vec_vsubuqm (__uint128, __uint128); vector __int128 __builtin_bcdadd (vector __int128, vector __int128, const int); +vector unsigned char __builtin_bcdadd (vector unsigned char, vector unsigned char, + const int); int __builtin_bcdadd_lt (vector __int128, vector __int128, const int); +int __builtin_bcdadd_lt (vector unsigned char, vector unsigned char, const int); int __builtin_bcdadd_eq (vector __int128, vector __int128, const int); +int __builtin_bcdadd_eq (vector unsigned char, vector unsigned char, const int); int __builtin_bcdadd_gt (vector __int128, vector __int128, const int); +int __builtin_bcdadd_gt (vector unsigned char, vector unsigned char, const int); int __builtin_bcdadd_ov (vector __int128, vector __int128, const int); +int __builtin_bcdadd_ov (vector unsigned char, vector unsigned char, const int); + vector __int128 __builtin_bcdsub (vector __int128, vector __int128, const int); +vector unsigned char __builtin_bcdsub (vector unsigned char, vector unsigned char, + const int); int __builtin_bcdsub_lt (vector __int128, vector __int128, const int); +int __builtin_bcdsub_lt (vector unsigned char, vector unsigned char, const int); int __builtin_bcdsub_eq (vector __int128, vector __int128, const int); +int __builtin_bcdsub_eq (vector unsigned char, vector unsigned char, const int); int __builtin_bcdsub_gt (vector __int128, vector __int128, const int); +int __builtin_bcdsub_gt (vector unsigned char, vector unsigned char, const int); int __builtin_bcdsub_ov (vector __int128, vector __int128, const int); +int __builtin_bcdsub_ov (vector unsigned char, vector unsigned char, const int); @end smallexample @node PowerPC AltiVec Built-in Functions Available on ISA 3.0 diff --git a/gcc/testsuite/gcc.target/powerpc/bcd-2.c b/gcc/testsuite/gcc.target/powerpc/bcd-2.c index 2f51dee257f..95c3699a144 100644 --- a/gcc/testsuite/gcc.target/powerpc/bcd-2.c +++ b/gcc/testsuite/gcc.target/powerpc/bcd-2.c @@ -14,6 +14,8 @@ /* { dg-final { scan-assembler-not "stxvw4x" } } */ /* { dg-final { scan-assembler-not "stxvd2x" } } */ +#include + 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 + /* Test whether the peephole works to allow folding a bcdadd, with a bcdadd_ into a single instruction. */ diff --git a/gcc/testsuite/gcc.target/powerpc/bcd-4.c b/gcc/testsuite/gcc.target/powerpc/bcd-4.c new file mode 100644 index 00000000000..2c8554dfe82 --- /dev/null +++ b/gcc/testsuite/gcc.target/powerpc/bcd-4.c @@ -0,0 +1,521 @@ +/* { dg-do run } */ +/* { dg-require-effective-target int128 } */ +/* { dg-require-effective-target power10_hw } */ +/* { dg-options "-mdejagnu-cpu=power10 -O2 -save-temps" } */ +/* { dg-final { scan-assembler-times {\mbcdadd\M} 7 } } */ +/* { dg-final { scan-assembler-times {\mbcdsub\M} 18 } } */ +/* { dg-final { scan-assembler-times {\mbcds\M} 2 } } */ +/* { dg-final { scan-assembler-times {\mdenbcdq\M} 1 } } */ + +#include + +#define DEBUG 0 + +#if DEBUG +#include +#endif + + +#define BCD_POS0 12 // 0xC +#define BCD_POS1 15 // 0xF +#define BCD_NEG 13 // 0xD + +void abort (void); + + union conv_t + { + _Decimal128 d128; + vector unsigned char ch; + vector long long unsigned int vllui; + } conv; + +_Decimal128 convert_vec_char (vector unsigned char a) +{ + union conv_t conv; + _Decimal128 result; + + conv.ch = a; + result = conv.d128; + return result; +} + +vector unsigned char maxbcd(unsigned int sign) +{ + vector unsigned char result; + int i; + + for (i = 15; i > 0; i--) + result[i] = 0x99; + + result[0] = sign << 4 | 0x9; +} + +vector unsigned char num2bcd(long int a, int encoding) +{ + int i; + unsigned int hi, low, sign; + + vector unsigned char result; + + if (a > 0) { + if (encoding == 0) + sign = BCD_POS0; + else + sign = BCD_POS1; + + } else { + sign = BCD_NEG; + a = -a; + } + + hi = a % 10; // 1st digit + a = a / 10; + result[0] = hi << 4| sign; + + for (i = 1; i < 16; i++) + { + low = a % 10; + a = a / 10; + hi = a % 10; + a = a / 10; + result[i] = hi << 4 | low; + } + + + return result; +} + +int main () +{ + int i; + long int value_a, value_b, value_result; + vector unsigned char a, b, result, exp_result; + _Decimal128 result_d128, exp_result_d128; + + /* Make a and b positive BCD numbers */ + value_a = 1020304; + a = num2bcd(value_a, 0); + + value_b = 101010; + b = num2bcd(value_b, 0); + + value_result = value_a + value_b; + exp_result = num2bcd(value_result, 0); + + result = __builtin_bcdadd (a, b, 0); + + for (i = 0; i < 16; i++) + if (exp_result[i] != result[i]) { + +#if DEBUG + printf("ERROR: __builtin_bcdadd result[%d] = %d does not match " + "expected_result[%d] = %d\n", + i, result[i], i, exp_result[i]); +#else + abort(); +#endif + } + + /* result should be positive */ + if ((result[0] & 0xF) != BCD_POS0) +#if DEBUG + printf("ERROR: __builtin_bcdadd sign of result is %d. Does not match " + "expected_result = %d\n", + result[0] & 0xF, BCD_POS0); +#else + abort(); +#endif + + /* Make a and b positive BCD numbers using alternate positive encoding. */ + value_a = 1030507; + a = num2bcd(value_a, 1); + + value_b = 204060; + b = num2bcd(value_b, 1); + + value_result = value_a + value_b; + exp_result = num2bcd(value_result, 1); + + result = __builtin_bcdadd (a, b, 1); + + for (i = 0; i < 16; i++) + if (exp_result[i] != result[i]) { +#if DEBUG + printf("ERROR: __builtin_bcdadd result[%d] = %d does not match " + "expected_result[%d] = %d\n", + i, result[i], i, exp_result[i]); +#else + abort(); +#endif + } + + /* Result should be positive, alternate encoding. */ + if ((result[0] & 0xF) != BCD_POS1) +#if DEBUG + printf("ERROR: __builtin_bcdadd sign of result is %d. Does not " + "match expected_result = %d\n", + result[0] & 0xF, BCD_POS1); +#else + abort(); +#endif + + /* Make a and b negative BCD numbers */ + value_a = -1030507; + a = num2bcd(value_a, 0); + + value_b = -1010101; + b = num2bcd(value_b, 0); + + value_result = value_a + value_b; + exp_result = num2bcd(value_result, 0); + + result = __builtin_bcdadd (a, b, 0); + + for (i = 0; i < 16; i++) + if (exp_result[i] != result[i]) { +#if DEBUG + printf("ERROR: __builtin_bcdadd, neg result[%d] = %d does not match " + "expected_result[%d] = %d\n", + i, result[i], i, exp_result[i]); +#else + abort(); +#endif + } + + /* result should be negative */ + if ((result[0] & 0xF) != BCD_NEG) +#if DEBUG + printf("ERROR: __builtin_bcdadd sign, neg of result is %d. Does not " + "match expected_result = %d\n", + result[0] & 0xF, BCD_NEG); +#else + abort(); +#endif + + + /* Make a negative, b positive BCD numbers */ + value_a = -1030507; + a = num2bcd(value_a, 0); + + value_b = 1010101; + b = num2bcd(value_b, 0); + + value_result = value_a - value_b; + exp_result = num2bcd(value_result, 0); + + result = __builtin_bcdsub (a, b, 0); + + for (i = 0; i < 16; i++) + if (exp_result[i] != result[i]) { +#if DEBUG + printf("ERROR: __builtin_bcdsub, neg result[%d] = %d does not match " + "expected_result[%d] = %d\n", + i, result[i], i, exp_result[i]); +#else + abort(); +#endif + } + + /* result should be positive, alt encoding */ + if ((result[0] & 0xF) != BCD_NEG) +#if DEBUG + printf("ERROR: __builtin_bcdadd sign, of result is %d. Does not match " + "expected_result = %d\n", + result[0] & 0xF, BCD_NEG); +#else + abort(); +#endif + + /* Make a and b positive BCD numbers */ + value_a = 1030507; + a = num2bcd(value_a, 1); + + value_b = 1010101; + b = num2bcd(value_b, 1); + + value_result = value_a - value_b; + exp_result = num2bcd(value_result, 1); + + result = __builtin_bcdsub (a, b, 1); + + for (i = 0; i < 16; i++) + if (exp_result[i] != result[i]) { +#if DEBUG + printf("ERROR:carll __builtin_bcdsub, pos result[%d] = %d does not " + "match expected_result[%d] = %d\n", + i, result[i], i, exp_result[i]); +#else + abort(); +#endif + } + + /* result should be positive */ + if ((result[0] & 0xF) != BCD_POS1) +#if DEBUG + printf("ERROR: __builtin_bcdsub sign, result is %d. Does not match " + "expected_result = %d\n", + result[0] & 0xF, BCD_POS1); +#else + abort(); +#endif + + /* Test overflow add and subtract. */ + a = maxbcd(BCD_POS0); + b = maxbcd(BCD_POS0); + + if(__builtin_bcdadd_ofl (a, b, 0) == 0) +#if DEBUG + printf("ERROR: __builtin_bcdadd did not overflow as expected\n"); +#else + abort(); +#endif + + value_a = 99999999; + a = num2bcd(value_a, 0); + + value_b = 999999999; + b = num2bcd(value_b, 0); + + if(__builtin_bcdadd_ofl (a, b, 0)) +#if DEBUG + printf("ERROR: __builtin_bcdadd unexpectedly overflowed\n"); +#else + abort(); +#endif + + a = maxbcd(BCD_NEG); + b = maxbcd(BCD_NEG); + + if (__builtin_bcdsub_ofl (a, b, 0) == 0) +#if DEBUG + printf("ERROR: __builtin_bcdsub did not overflow as expected\n"); +#else + abort(); +#endif + + value_a = -99999999; + a = num2bcd(value_a, 0); + + value_b = -999999999; + b = num2bcd(value_b, 0); + + if (__builtin_bcdsub_ofl (a, b, 0)) +#if DEBUG + printf("ERROR: __builtin_bcdsub unexpectedly overflowed\n"); +#else + abort(); +#endif + + /* Test arguments for valid/invalid */ + if (__builtin_bcdinvalid (a)) +#if DEBUG + printf("ERROR: __builtin_invalid input is unexpectedly invalid.\n"); +#else + abort(); +#endif + + a[3] = 0xBB; /* an invalid BCD digit */ + if (!__builtin_bcdinvalid (a)) +#if DEBUG + printf("ERROR: __builtin_invalid input is unexpectedly valid.\n"); +#else + abort(); +#endif + + value_a = 1020304; + a = num2bcd(value_a, 0); + + value_b = 101010; + b = num2bcd(value_b, 0); + + /* Test equality */ + if (__builtin_bcdcmpeq (a, b)) +#if DEBUG + printf("ERROR: __builtin__bcdcmpeq result is unexpectedly 1.\n"); +#else + abort(); +#endif + + if (!__builtin_bcdcmpeq (a, a)) +#if DEBUG + printf("ERROR: __builtin__bcdcmpeq result is unexpectedly 0.\n"); +#else + abort(); +#endif + + + /* Test a greater then b, inputs already setup this way. */ + if (!__builtin_bcdcmpgt (a, b)) +#if DEBUG + printf("ERROR: __builtin__bcdcmpgt result is unexpectedly 0.\n"); +#else + abort(); +#endif + + if (__builtin_bcdcmpgt (b, a)) +#if DEBUG + printf("ERROR: __builtin__bcdcmpgt result is unexpectedly 1.\n"); +#else + abort(); +#endif + + if (__builtin_bcdcmpgt (a, a)) +#if DEBUG + printf("ERROR: __builtin__bcdcmpgt input equal, result is unexpectedly " + "1.\n"); +#else + abort(); +#endif + + + if (!__builtin_bcdcmpge (a, b)) +#if DEBUG + printf("ERROR: __builtin__bcdcmpge result is unexpectedly 0.\n"); +#else + abort(); +#endif + + if (__builtin_bcdcmpge (b, a)) +#if DEBUG + printf("ERROR: __builtin__bcdcmpge result is unexpectedly 1.\n"); +#else + abort(); +#endif + + if (!__builtin_bcdcmpge (b, b)) +#if DEBUG + printf("ERROR: __builtin__bcdcmpge inputs equal result is unexpectedly " + "0.\n"); +#else + abort(); +#endif + + /* Test a less then b. */ + value_a = 101010; + a = num2bcd(value_a, 0); + value_b = 1020304; + b = num2bcd(value_b, 0); + + if (!__builtin_bcdcmplt (a, b)) +#if DEBUG + printf("ERROR: __builtin__bcdcmplt result is unexpectedly 0.\n"); +#else + abort(); +#endif + + if (__builtin_bcdcmplt (b, a)) +#if DEBUG + printf("ERROR: __builtin__bcdcmplt result is unexpectedly 1.\n"); +#else + abort(); +#endif + + if (__builtin_bcdcmplt (b, b)) +#if DEBUG + printf("ERROR: __builtin__bcdcmplt inputs equal result is unexpectedly " + "1.\n"); +#else + abort(); +#endif + + + if (!__builtin_bcdcmple (a, b)) +#if DEBUG + printf("ERROR: __builtin__bcdcmple result is unexpectedly 0.\n"); +#else + abort(); +#endif + + if (__builtin_bcdcmple (b, a)) +#if DEBUG + printf("ERROR: __builtin__bcdcmple result is unexpectedly 1.\n"); +#else + abort(); +#endif + + if (!__builtin_bcdcmple (a, a)) +#if DEBUG + printf("ERROR: __builtin__bcdcmple inputs equal result is unexpectedly " + "0.\n"); +#else + abort(); +#endif + + /* Test multipy 10 */ + value_a = 1020304; + a = num2bcd(value_a, 0); + + value_result = value_a * 10; + exp_result = num2bcd(value_result, 0); + + result = __builtin_bcdmul10 (a); + + for (i = 0; i < 16; i++) + if (exp_result[i] != result[i]) { +#if DEBUG + printf("ERROR:carll __builtin_bcdmul10, pos result[%d] = %d does not " + "match expected_result[%d] = %d\n", + i, result[i], i, exp_result[i]); +#else + abort(); +#endif + } + + /* result should be positive */ + if ((result[0] & 0xF) != BCD_POS0) +#if 0 + printf("ERROR: __builtin_bcdmul10 sign, result is %d. Does not match " + "expected_result = %d\n", + result[0] & 0xF, BCD_POS1); +#else + abort(); +#endif + + /* Test divide 10 */ + value_a = 1020304; + a = num2bcd(value_a, 0); + + value_result = value_a / 10; + exp_result = num2bcd(value_result, 0); + + result = __builtin_bcddiv10 (a); + + for (i = 0; i < 16; i++) + if (exp_result[i] != result[i]) { +#if DEBUG + printf("ERROR:carll __builtin_bcddiv10, pos result[%d] = %d does not " + "match expected_result[%d] = %d\n", + i, result[i], i, exp_result[i]); +#else + abort(); +#endif + } + + /* result should be positive */ + if ((result[0] & 0xF) != BCD_POS0) +#if DEBUG + printf("ERROR: __builtin_bcddiv10 sign, result is %d. Does not match " + "expected_result = %d\n", + result[0] & 0xF, BCD_POS1); +#else + abort(); +#endif + + value_a = 1020304; + exp_result_d128 = 1020304; + a = num2bcd(value_a, 0); + + conv.ch = a; + conv.d128 = __builtin_bcd2dfp (a); + result_d128 = conv.d128; + + if (result_d128 != exp_result_d128) +#if DEBUG + printf("ERROR: __builtin_bcd2dfp, result does not match expected_result." + "\n"); +#else + abort(); +#endif + return 0; +} +