diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 8e7e28c7ffcc59420c12ce66d29ed859aeded18f..7302097021b7ad7fa2ffc1058ca07d746cf0c02a 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,18 @@ +2003-10-14 Ulrich Weigand <uweigand@de.ibm.com> + + * config/s390/s390-protos.h (s390_alc_comparison): Add prototype. + (s390_slb_comparison): Likewise. + * config/s390/s390.c (s390_alc_comparison, s390_slb_comparison): + New functions. + * config/s390/s390.h (PREDICATE_CODES): Add s390_alc_comparison + and s390_slb_comparison. + * config/s390/s390.md ("*adddi3_31", "*subdi3_31"): Do not use on + zSeries machines. + ("*adddi3_31z", "*subdi3_31z"): New insns. + ("*adddi3_alc_cc", "*adddi3_alc", "*subdi3_slb_cc", "*subdi3_slb", + "*addsi3_alc_cc", "*addsi3_alc", "*subsi3_slb_cc", "*subsi3_slb"): + New insns. + 2003-10-14 Nathanael Nerode <neroden@gcc.gnu.org> * configure.in: Clean up some feedback echoes. diff --git a/gcc/config/s390/s390-protos.h b/gcc/config/s390/s390-protos.h index 40026d3b85f66b056e3364c56be2ab9e416c7e13..76ceccdc5127c1ca0023927019dd75fb5452f3df 100644 --- a/gcc/config/s390/s390-protos.h +++ b/gcc/config/s390/s390-protos.h @@ -49,6 +49,8 @@ extern int tls_symbolic_operand (rtx); extern int s390_match_ccmode (rtx, enum machine_mode); extern enum machine_mode s390_tm_ccmode (rtx, rtx, int); extern enum machine_mode s390_select_ccmode (enum rtx_code, rtx, rtx); +extern int s390_alc_comparison (rtx op, enum machine_mode mode); +extern int s390_slb_comparison (rtx op, enum machine_mode mode); extern int symbolic_reference_mentioned_p (rtx); extern int tls_symbolic_reference_mentioned_p (rtx); extern rtx s390_tls_get_offset (void); diff --git a/gcc/config/s390/s390.c b/gcc/config/s390/s390.c index cf68a5210278e7f3eef6dc52454e428902526159..6d56b0278b15a7b4ee26ade329b024833a056e62 100644 --- a/gcc/config/s390/s390.c +++ b/gcc/config/s390/s390.c @@ -447,6 +447,90 @@ s390_select_ccmode (enum rtx_code code, rtx op0, rtx op1) } } +/* Return nonzero if OP is a valid comparison operator + for an ALC condition in mode MODE. */ + +int +s390_alc_comparison (rtx op, enum machine_mode mode) +{ + if (mode != VOIDmode && mode != GET_MODE (op)) + return 0; + + if (GET_RTX_CLASS (GET_CODE (op)) != '<') + return 0; + + if (GET_CODE (XEXP (op, 0)) != REG + || REGNO (XEXP (op, 0)) != CC_REGNUM + || XEXP (op, 1) != const0_rtx) + return 0; + + switch (GET_MODE (XEXP (op, 0))) + { + case CCL1mode: + return GET_CODE (op) == LTU; + + case CCL2mode: + return GET_CODE (op) == LEU; + + case CCUmode: + return GET_CODE (op) == GTU; + + case CCURmode: + return GET_CODE (op) == LTU; + + case CCSmode: + return GET_CODE (op) == UNGT; + + case CCSRmode: + return GET_CODE (op) == UNLT; + + default: + return 0; + } +} + +/* Return nonzero if OP is a valid comparison operator + for an SLB condition in mode MODE. */ + +int +s390_slb_comparison (rtx op, enum machine_mode mode) +{ + if (mode != VOIDmode && mode != GET_MODE (op)) + return 0; + + if (GET_RTX_CLASS (GET_CODE (op)) != '<') + return 0; + + if (GET_CODE (XEXP (op, 0)) != REG + || REGNO (XEXP (op, 0)) != CC_REGNUM + || XEXP (op, 1) != const0_rtx) + return 0; + + switch (GET_MODE (XEXP (op, 0))) + { + case CCL1mode: + return GET_CODE (op) == GEU; + + case CCL2mode: + return GET_CODE (op) == GTU; + + case CCUmode: + return GET_CODE (op) == LEU; + + case CCURmode: + return GET_CODE (op) == GEU; + + case CCSmode: + return GET_CODE (op) == LE; + + case CCSRmode: + return GET_CODE (op) == GE; + + default: + return 0; + } +} + /* Return branch condition mask to implement a branch specified by CODE. */ diff --git a/gcc/config/s390/s390.h b/gcc/config/s390/s390.h index 0a605505dfacb349598ff7126b4ed1fce3bc2378..1c3241c63e3b708c3ff0ffe02fe7635a093488e7 100644 --- a/gcc/config/s390/s390.h +++ b/gcc/config/s390/s390.h @@ -1030,7 +1030,9 @@ do { \ {"const0_operand", { CONST_INT, CONST_DOUBLE }}, \ {"consttable_operand", { SYMBOL_REF, LABEL_REF, CONST, \ CONST_INT, CONST_DOUBLE }}, \ - {"s390_plus_operand", { PLUS }}, + {"s390_plus_operand", { PLUS }}, \ + {"s390_alc_comparison", { LTU, GTU, LEU, GEU }}, \ + {"s390_slb_comparison", { LTU, GTU, LEU, GEU }}, /* Specify the machine mode that this machine uses for the index in the tablejump instruction. */ diff --git a/gcc/config/s390/s390.md b/gcc/config/s390/s390.md index 9cdce811405dde602d94b396fb29163d0ceec27d..5f49e6ab1d138f8b64483eb2221464a6ab754dbc 100644 --- a/gcc/config/s390/s390.md +++ b/gcc/config/s390/s390.md @@ -3254,12 +3254,37 @@ ag\t%0,%2" [(set_attr "op_type" "RRE,RI,RXY")]) +(define_insn_and_split "*adddi3_31z" + [(set (match_operand:DI 0 "register_operand" "=&d") + (plus:DI (match_operand:DI 1 "nonimmediate_operand" "%0") + (match_operand:DI 2 "general_operand" "do") ) ) + (clobber (reg:CC 33))] + "!TARGET_64BIT && TARGET_CPU_ZARCH" + "#" + "&& reload_completed" + [(parallel + [(set (reg:CCL1 33) + (compare:CCL1 (plus:SI (match_dup 7) (match_dup 8)) + (match_dup 7))) + (set (match_dup 6) (plus:SI (match_dup 7) (match_dup 8)))]) + (parallel + [(set (match_dup 3) (plus:SI (plus:SI (match_dup 4) (match_dup 5)) + (ltu:SI (reg:CCL1 33) (const_int 0)))) + (clobber (reg:CC 33))])] + "operands[3] = operand_subword (operands[0], 0, 0, DImode); + operands[4] = operand_subword (operands[1], 0, 0, DImode); + operands[5] = operand_subword (operands[2], 0, 0, DImode); + operands[6] = operand_subword (operands[0], 1, 0, DImode); + operands[7] = operand_subword (operands[1], 1, 0, DImode); + operands[8] = operand_subword (operands[2], 1, 0, DImode);" + [(set_attr "op_type" "NN")]) + (define_insn_and_split "*adddi3_31" [(set (match_operand:DI 0 "register_operand" "=&d") (plus:DI (match_operand:DI 1 "nonimmediate_operand" "%0") (match_operand:DI 2 "general_operand" "do") ) ) (clobber (reg:CC 33))] - "!TARGET_64BIT" + "!TARGET_CPU_ZARCH" "#" "&& reload_completed" [(parallel @@ -3804,12 +3829,37 @@ sg\t%0,%2" [(set_attr "op_type" "RRE,RRE")]) +(define_insn_and_split "*subdi3_31z" + [(set (match_operand:DI 0 "register_operand" "=&d") + (minus:DI (match_operand:DI 1 "register_operand" "0") + (match_operand:DI 2 "general_operand" "do") ) ) + (clobber (reg:CC 33))] + "!TARGET_64BIT && TARGET_CPU_ZARCH" + "#" + "&& reload_completed" + [(parallel + [(set (reg:CCL2 33) + (compare:CCL2 (minus:SI (match_dup 7) (match_dup 8)) + (match_dup 7))) + (set (match_dup 6) (minus:SI (match_dup 7) (match_dup 8)))]) + (parallel + [(set (match_dup 3) (minus:SI (minus:SI (match_dup 4) (match_dup 5)) + (gtu:SI (reg:CCL2 33) (const_int 0)))) + (clobber (reg:CC 33))])] + "operands[3] = operand_subword (operands[0], 0, 0, DImode); + operands[4] = operand_subword (operands[1], 0, 0, DImode); + operands[5] = operand_subword (operands[2], 0, 0, DImode); + operands[6] = operand_subword (operands[0], 1, 0, DImode); + operands[7] = operand_subword (operands[1], 1, 0, DImode); + operands[8] = operand_subword (operands[2], 1, 0, DImode);" + [(set_attr "op_type" "NN")]) + (define_insn_and_split "*subdi3_31" [(set (match_operand:DI 0 "register_operand" "=&d") (minus:DI (match_operand:DI 1 "register_operand" "0") (match_operand:DI 2 "general_operand" "do") ) ) (clobber (reg:CC 33))] - "!TARGET_64BIT" + "!TARGET_CPU_ZARCH" "#" "&& reload_completed" [(parallel @@ -4057,6 +4107,127 @@ (set_attr "type" "fsimps,fsimps")]) +;; +;;- Conditional add/subtract instructions. +;; + +; +; adddicc instruction pattern(s). +; + +(define_insn "*adddi3_alc_cc" + [(set (reg 33) + (compare + (plus:DI (plus:DI (match_operand:DI 1 "nonimmediate_operand" "%0,0") + (match_operand:DI 2 "general_operand" "d,m")) + (match_operand:DI 3 "s390_alc_comparison" "")) + (const_int 0))) + (set (match_operand:DI 0 "register_operand" "=d,d") + (plus:DI (plus:DI (match_dup 1) (match_dup 2)) (match_dup 3)))] + "s390_match_ccmode (insn, CCLmode) && TARGET_64BIT" + "@ + alcgr\\t%0,%2 + alcg\\t%0,%2" + [(set_attr "op_type" "RRE,RXY")]) + +(define_insn "*adddi3_alc" + [(set (match_operand:DI 0 "register_operand" "=d,d") + (plus:DI (plus:DI (match_operand:DI 1 "nonimmediate_operand" "%0,0") + (match_operand:DI 2 "general_operand" "d,m")) + (match_operand:DI 3 "s390_alc_comparison" ""))) + (clobber (reg:CC 33))] + "TARGET_64BIT" + "@ + alcgr\\t%0,%2 + alcg\\t%0,%2" + [(set_attr "op_type" "RRE,RXY")]) + +(define_insn "*subdi3_slb_cc" + [(set (reg 33) + (compare + (minus:DI (minus:DI (match_operand:DI 1 "nonimmediate_operand" "0,0") + (match_operand:DI 2 "general_operand" "d,m")) + (match_operand:DI 3 "s390_slb_comparison" "")) + (const_int 0))) + (set (match_operand:DI 0 "register_operand" "=d,d") + (minus:DI (minus:DI (match_dup 1) (match_dup 2)) (match_dup 3)))] + "s390_match_ccmode (insn, CCLmode) && TARGET_64BIT" + "@ + slbgr\\t%0,%2 + slbg\\t%0,%2" + [(set_attr "op_type" "RRE,RXY")]) + +(define_insn "*subdi3_slb" + [(set (match_operand:DI 0 "register_operand" "=d,d") + (minus:DI (minus:DI (match_operand:DI 1 "nonimmediate_operand" "0,0") + (match_operand:DI 2 "general_operand" "d,m")) + (match_operand:DI 3 "s390_slb_comparison" ""))) + (clobber (reg:CC 33))] + "TARGET_64BIT" + "@ + slbgr\\t%0,%2 + slbg\\t%0,%2" + [(set_attr "op_type" "RRE,RXY")]) + +; +; addsicc instruction pattern(s). +; + +(define_insn "*addsi3_alc_cc" + [(set (reg 33) + (compare + (plus:SI (plus:SI (match_operand:SI 1 "nonimmediate_operand" "%0,0") + (match_operand:SI 2 "general_operand" "d,m")) + (match_operand:SI 3 "s390_alc_comparison" "")) + (const_int 0))) + (set (match_operand:SI 0 "register_operand" "=d,d") + (plus:SI (plus:SI (match_dup 1) (match_dup 2)) (match_dup 3)))] + "s390_match_ccmode (insn, CCLmode) && TARGET_CPU_ZARCH" + "@ + alcr\\t%0,%2 + alc\\t%0,%2" + [(set_attr "op_type" "RRE,RXY")]) + +(define_insn "*addsi3_alc" + [(set (match_operand:SI 0 "register_operand" "=d,d") + (plus:SI (plus:SI (match_operand:SI 1 "nonimmediate_operand" "%0,0") + (match_operand:SI 2 "general_operand" "d,m")) + (match_operand:SI 3 "s390_alc_comparison" ""))) + (clobber (reg:CC 33))] + "TARGET_CPU_ZARCH" + "@ + alcr\\t%0,%2 + alc\\t%0,%2" + [(set_attr "op_type" "RRE,RXY")]) + +(define_insn "*subsi3_slb_cc" + [(set (reg 33) + (compare + (minus:SI (minus:SI (match_operand:SI 1 "nonimmediate_operand" "0,0") + (match_operand:SI 2 "general_operand" "d,m")) + (match_operand:SI 3 "s390_slb_comparison" "")) + (const_int 0))) + (set (match_operand:SI 0 "register_operand" "=d,d") + (minus:SI (minus:SI (match_dup 1) (match_dup 2)) (match_dup 3)))] + "s390_match_ccmode (insn, CCLmode) && TARGET_CPU_ZARCH" + "@ + slbr\\t%0,%2 + slb\\t%0,%2" + [(set_attr "op_type" "RRE,RXY")]) + +(define_insn "*subsi3_slb" + [(set (match_operand:SI 0 "register_operand" "=d,d") + (minus:SI (minus:SI (match_operand:SI 1 "nonimmediate_operand" "0,0") + (match_operand:SI 2 "general_operand" "d,m")) + (match_operand:SI 3 "s390_slb_comparison" ""))) + (clobber (reg:CC 33))] + "TARGET_CPU_ZARCH" + "@ + slbr\\t%0,%2 + slb\\t%0,%2" + [(set_attr "op_type" "RRE,RXY")]) + + ;; ;;- Multiply instructions. ;;