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.
 

Reply via email to