This implements addc, addic, adde, addze, addme, subfc, subfic, subfe,
subfze, subfme.  Some of those in multiple forms: canonical RTL for the
"immediate" insns has four forms; subfX has a special form for subtracting
a register from itself.

All these new insns get type "add" for now.


2014-12-08  Segher Boessenkool  <seg...@kernel.crashing.org>

gcc/
        PR target/64180
        * config/rs6000/predicates.md (adde_operand): New.
        * config/rs6000/rs6000.md (add<mode>3_carry): New.
        (add<mode>3_imm_carry_pos): New.
        (add<mode>3_imm_carry_0): New.
        (add<mode>3_imm_carry_m1): New.
        (add<mode>3_imm_carry_neg): New.
        (add<mode>3_carry_in): New.
        (add<mode>3_carry_in_0): New.
        (add<mode>3_carry_in_m1): New.
        (subf<mode>3_carry): New.
        (subf<mode>3_imm_carry_0): New.
        (subf<mode>3_imm_carry_m1): New.
        (subf<mode>3_carry_in): New.
        (subf<mode>3_carry_in_0): New.
        (subf<mode>3_carry_in_m1): New.
        (subf<mode>3_carry_in_xx): New.

---
 gcc/config/rs6000/predicates.md |   6 ++
 gcc/config/rs6000/rs6000.md     | 162 ++++++++++++++++++++++++++++++++++++++++
 2 files changed, 168 insertions(+)

diff --git a/gcc/config/rs6000/predicates.md b/gcc/config/rs6000/predicates.md
index ea230a5..a19cb2f 100644
--- a/gcc/config/rs6000/predicates.md
+++ b/gcc/config/rs6000/predicates.md
@@ -788,6 +788,12 @@ (define_predicate "add_operand"
                 || satisfies_constraint_L (op)")
     (match_operand 0 "gpc_reg_operand")))
 
+;; Return 1 if the operand is either a non-special register, or 0, or -1.
+(define_predicate "adde_operand"
+  (if_then_else (match_code "const_int")
+    (match_test "INTVAL (op) == 0 || INTVAL (op) == -1")
+    (match_operand 0 "gpc_reg_operand")))
+
 ;; Return 1 if OP is a constant but not a valid add_operand.
 (define_predicate "non_add_cint_operand"
   (and (match_code "const_int")
diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md
index dcdb7c1..e23fadb 100644
--- a/gcc/config/rs6000/rs6000.md
+++ b/gcc/config/rs6000/rs6000.md
@@ -1634,6 +1634,96 @@ (define_split
     FAIL;
 })
 
+
+(define_insn "add<mode>3_carry"
+  [(set (match_operand:P 0 "gpc_reg_operand" "=r")
+       (plus:P (match_operand:P 1 "gpc_reg_operand" "r")
+               (match_operand:P 2 "reg_or_short_operand" "rI")))
+   (set (reg:P CA_REGNO)
+       (ltu:P (plus:P (match_dup 1)
+                      (match_dup 2))
+              (match_dup 1)))]
+  ""
+  "add%I2c %0,%1,%2"
+  [(set_attr "type" "add")])
+
+(define_insn "*add<mode>3_imm_carry_pos"
+  [(set (match_operand:P 0 "gpc_reg_operand" "=r")
+       (plus:P (match_operand:P 1 "gpc_reg_operand" "r")
+               (match_operand:P 2 "short_cint_operand" "n")))
+   (set (reg:P CA_REGNO)
+       (geu:P (match_dup 1)
+              (match_operand:P 3 "const_int_operand" "n")))]
+  "INTVAL (operands[2]) > 0
+   && INTVAL (operands[2]) + INTVAL (operands[3]) == 0"
+  "addic %0,%1,%2"
+  [(set_attr "type" "add")])
+
+(define_insn "*add<mode>3_imm_carry_0"
+  [(set (match_operand:P 0 "gpc_reg_operand" "=r")
+       (match_operand:P 1 "gpc_reg_operand" "r"))
+   (set (reg:P CA_REGNO)
+       (const_int 0))]
+  ""
+  "addic %0,%1,0"
+  [(set_attr "type" "add")])
+
+(define_insn "*add<mode>3_imm_carry_m1"
+  [(set (match_operand:P 0 "gpc_reg_operand" "=r")
+       (plus:P (match_operand:P 1 "gpc_reg_operand" "r")
+               (const_int -1)))
+   (set (reg:P CA_REGNO)
+       (ne:P (match_dup 1)
+             (const_int 0)))]
+  ""
+  "addic %0,%1,-1"
+  [(set_attr "type" "add")])
+
+(define_insn "*add<mode>3_imm_carry_neg"
+  [(set (match_operand:P 0 "gpc_reg_operand" "=r")
+       (plus:P (match_operand:P 1 "gpc_reg_operand" "r")
+               (match_operand:P 2 "short_cint_operand" "n")))
+   (set (reg:P CA_REGNO)
+       (gtu:P (match_dup 1)
+              (match_operand:P 3 "const_int_operand" "n")))]
+  "INTVAL (operands[2]) < 0
+   && INTVAL (operands[2]) + INTVAL (operands[3]) == -1"
+  "addic %0,%1,%2"
+  [(set_attr "type" "add")])
+
+
+(define_insn "add<mode>3_carry_in"
+  [(set (match_operand:GPR 0 "gpc_reg_operand" "=r,r")
+       (plus:GPR (plus:GPR (match_operand:GPR 1 "gpc_reg_operand" "r,r")
+                           (match_operand:GPR 2 "adde_operand" "r,n"))
+                 (reg:GPR CA_REGNO)))
+   (clobber (reg:GPR CA_REGNO))]
+  ""
+  "@
+   adde %0,%1,%2
+   add%G2e %0,%1"
+  [(set_attr "type" "add")])
+
+(define_insn "add<mode>3_carry_in_0"
+  [(set (match_operand:GPR 0 "gpc_reg_operand" "=r,r")
+       (plus:GPR (match_operand:GPR 1 "gpc_reg_operand" "r,r")
+                 (reg:GPR CA_REGNO)))
+   (clobber (reg:GPR CA_REGNO))]
+  ""
+  "addze %0,%1"
+  [(set_attr "type" "add")])
+
+(define_insn "add<mode>3_carry_in_m1"
+  [(set (match_operand:GPR 0 "gpc_reg_operand" "=r,r")
+       (plus:GPR (plus:GPR (match_operand:GPR 1 "gpc_reg_operand" "r,r")
+                           (reg:GPR CA_REGNO))
+                 (const_int -1)))
+   (clobber (reg:GPR CA_REGNO))]
+  ""
+  "addme %0,%1"
+  [(set_attr "type" "add")])
+
+
 (define_expand "one_cmpl<mode>2"
   [(set (match_operand:SDI 0 "gpc_reg_operand" "")
        (not:SDI (match_operand:SDI 1 "gpc_reg_operand" "")))]
@@ -1772,6 +1862,78 @@ (define_insn "subf<mode>3_imm"
   [(set_attr "type" "add")])
 
 
+(define_insn "subf<mode>3_carry"
+  [(set (match_operand:P 0 "gpc_reg_operand" "=r")
+       (minus:P (match_operand:P 2 "reg_or_short_operand" "rI")
+                (match_operand:P 1 "gpc_reg_operand" "r")))
+   (set (reg:P CA_REGNO)
+       (leu:P (match_dup 1)
+              (match_dup 2)))]
+  ""
+  "subf%I2c %0,%1,%2"
+  [(set_attr "type" "add")])
+
+(define_insn "*subf<mode>3_imm_carry_0"
+  [(set (match_operand:P 0 "gpc_reg_operand" "=r")
+       (neg:P (match_operand:P 1 "gpc_reg_operand" "r")))
+   (set (reg:P CA_REGNO)
+       (eq:P (match_dup 1)
+             (const_int 0)))]
+  ""
+  "subfic %0,%1,0"
+  [(set_attr "type" "add")])
+
+(define_insn "*subf<mode>3_imm_carry_m1"
+  [(set (match_operand:P 0 "gpc_reg_operand" "=r")
+       (not:P (match_operand:P 1 "gpc_reg_operand" "r")))
+   (set (reg:P CA_REGNO)
+       (const_int 1))]
+  ""
+  "subfic %0,%1,-1"
+  [(set_attr "type" "add")])
+
+
+(define_insn "subf<mode>3_carry_in"
+  [(set (match_operand:GPR 0 "gpc_reg_operand" "=r,r")
+       (plus:GPR (plus:GPR (not:GPR (match_operand:GPR 1 "gpc_reg_operand" 
"r,r"))
+                           (reg:GPR CA_REGNO))
+                 (match_operand:GPR 2 "adde_operand" "r,n")))
+   (clobber (reg:GPR CA_REGNO))]
+  ""
+  "@
+   subfe %0,%1,%2
+   subf%G2e %0,%1"
+  [(set_attr "type" "add")])
+
+(define_insn "*subf<mode>3_carry_in_0"
+  [(set (match_operand:GPR 0 "gpc_reg_operand" "=r")
+       (plus:GPR (not:GPR (match_operand:GPR 1 "gpc_reg_operand" "r"))
+                 (reg:GPR CA_REGNO)))
+   (clobber (reg:GPR CA_REGNO))]
+  ""
+  "subfze %0,%1"
+  [(set_attr "type" "add")])
+
+(define_insn "*subf<mode>3_carry_in_m1"
+  [(set (match_operand:GPR 0 "gpc_reg_operand" "=r")
+       (plus:GPR (plus:GPR (not:GPR (match_operand:GPR 1 "gpc_reg_operand" 
"r"))
+                           (reg:GPR CA_REGNO))
+                 (const_int -1)))
+   (clobber (reg:GPR CA_REGNO))]
+  ""
+  "subfme %0,%1"
+  [(set_attr "type" "add")])
+
+(define_insn "subf<mode>3_carry_in_xx"
+  [(set (match_operand:GPR 0 "gpc_reg_operand" "=r")
+       (plus:GPR (reg:GPR CA_REGNO)
+                 (const_int -1)))
+   (clobber (reg:GPR CA_REGNO))]
+  ""
+  "subfe %0,%0,%0"
+  [(set_attr "type" "add")])
+
+
 (define_expand "neg<mode>2"
   [(set (match_operand:SDI 0 "gpc_reg_operand" "")
        (neg:SDI (match_operand:SDI 1 "gpc_reg_operand" "")))]
-- 
1.8.1.4

Reply via email to