For some newlib sources, pdp11 doloop_end was creating problems because it was handed a QImode operand when it only wants HImode. This patch cures that, and also adds addqi3 and subqi3 patterns to help with that case.
Committed. paul ChangeLog: 2018-10-12 Paul Koning <n...@arrl.net> * config/pdp11/pdp11.md (doloop_end): New expander. (doloop_end_insn): renamed from "doloop_end". (addqi3): New pattern. (subqi3): New pattern. * config/pdp11/predicates.md (incdec_operand): New predicate. Index: config/pdp11/predicates.md =================================================================== --- config/pdp11/predicates.md (revision 265131) +++ config/pdp11/predicates.md (revision 265132) @@ -30,6 +30,14 @@ (and (match_code "const_int") (match_test "(unsigned) INTVAL (op) < 4"))) +;; Accept integer arguments +1 and -1, for which add and sub can be +;; done as inc or dec instructions. This matches the rule for the +;; L and M constraints. +(define_predicate "incdec_operand" + (and (match_code "const_int") + (ior (match_test "INTVAL (op) == -1") + (match_test "INTVAL (op) == 1")))) + ;; Accept anything general_operand accepts, except that registers must ;; be FPU registers. (define_predicate "float_operand" Index: config/pdp11/pdp11.md =================================================================== --- config/pdp11/pdp11.md (revision 265131) +++ config/pdp11/pdp11.md (revision 265132) @@ -251,9 +251,28 @@ ;; sob instruction ;; -;; Do a define_expand because some alternatives clobber CC. +;; This expander has to check for mode match because the doloop pass +;; in gcc that invokes it does not do so, i.e., it may attempt to apply +;; this pattern even if the count operand is QI or SI mode. +(define_expand "doloop_end" + [(parallel [(set (pc) + (if_then_else + (ne (match_operand:HI 0 "nonimmediate_operand" "+r,!m") + (const_int 1)) + (label_ref (match_operand 1 "" "")) + (pc))) + (set (match_dup 0) + (plus:HI (match_dup 0) + (const_int -1)))])] + "TARGET_40_PLUS" + "{ + if (GET_MODE (operands[0]) != HImode) + FAIL; + }") + +;; Do a define_split because some alternatives clobber CC. ;; Some don't, but it isn't all that interesting to cover that case. -(define_insn_and_split "doloop_end" +(define_insn_and_split "doloop_end_insn" [(set (pc) (if_then_else (ne (match_operand:HI 0 "nonimmediate_operand" "+r,!m") @@ -1067,6 +1086,35 @@ }" [(set_attr "length" "2,4,4,6")]) +(define_insn_and_split "addqi3" + [(set (match_operand:QI 0 "nonimmediate_operand" "=rR,Q") + (plus:QI (match_operand:QI 1 "general_operand" "%0,0") + (match_operand:QI 2 "incdec_operand" "LM,LM")))] + "" + "#" + "reload_completed" + [(parallel [(set (match_dup 0) + (plus:QI (match_dup 1) (match_dup 2))) + (clobber (reg:CC CC_REGNUM))])] + "" + [(set_attr "length" "2,4")]) + +;; Inc/dec sets V if overflow from the operation +(define_insn "*addqi3<cc_ccnz>" + [(set (match_operand:QI 0 "nonimmediate_operand" "=rR,Q") + (plus:QI (match_operand:QI 1 "general_operand" "%0,0") + (match_operand:QI 2 "incdec_operand" "LM,LM"))) + (clobber (reg:CC CC_REGNUM))] + "reload_completed" + "* +{ + if (INTVAL(operands[2]) == 1) + return \"incb\t%0\"; + else + return \"decb\t%0\"; +}" + [(set_attr "length" "2,4")]) + ;;- subtract instructions ;; we don't have to care for constant second @@ -1226,6 +1274,35 @@ }" [(set_attr "length" "2,4,4,6")]) +(define_insn_and_split "subqi3" + [(set (match_operand:QI 0 "nonimmediate_operand" "=rR,Q") + (plus:QI (match_operand:QI 1 "general_operand" "%0,0") + (match_operand:QI 2 "incdec_operand" "LM,LM")))] + "" + "#" + "reload_completed" + [(parallel [(set (match_dup 0) + (plus:QI (match_dup 1) (match_dup 2))) + (clobber (reg:CC CC_REGNUM))])] + "" + [(set_attr "length" "2,4")]) + +;; Inc/dec sets V if overflow from the operation +(define_insn "*subqi3<cc_ccnz>" + [(set (match_operand:QI 0 "nonimmediate_operand" "=rR,Q") + (plus:QI (match_operand:QI 1 "general_operand" "%0,0") + (match_operand:QI 2 "incdec_operand" "LM,LM"))) + (clobber (reg:CC CC_REGNUM))] + "reload_completed" + "* +{ + if (INTVAL(operands[2]) == -1) + return \"incb\t%0\"; + else + return \"decb\t%0\"; +}" + [(set_attr "length" "2,4")]) + ;;;;- and instructions ;; Bit-and on the pdp (like on the VAX) is done with a clear-bits insn.