@@ -471,10 +471,12 @@ (define_expand "adddi3"
hi_op2 = force_reg (SImode, hi_op2);
emit_insn (gen_addsi3_compareC (lo_dest, lo_op1, lo_op2));
+ rtx carry = gen_rtx_LTU (SImode, gen_rtx_REG (CC_Cmode, CC_REGNUM),
+ const0_rtx);
if (hi_op2 == const0_rtx)
- emit_insn (gen_add0si3_carryin_ltu (hi_dest, hi_op1));
+ emit_insn (gen_add0si3_carryin (hi_dest, hi_op1, carry));
else
- emit_insn (gen_addsi3_carryin_ltu (hi_dest, hi_op1, hi_op2));
+ emit_insn (gen_addsi3_carryin (hi_dest, hi_op1, hi_op2, carry));
}
if (lo_result != lo_dest)
@@ -858,11 +860,11 @@ (define_insn "*compare_addsi2_op1"
(set_attr "type" "alus_imm,alus_sreg,alus_imm,alus_imm,alus_sreg")]
)
-(define_insn "addsi3_carryin_<optab>"
+(define_insn "addsi3_carryin"
[(set (match_operand:SI 0 "s_register_operand" "=l,r,r")
(plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%l,r,r")
(match_operand:SI 2 "arm_not_operand" "0,rI,K"))
- (LTUGEU:SI (reg:<cnb> CC_REGNUM) (const_int 0))))]
+ (match_operand:SI 3 "arm_carry_operation" "")))]
"TARGET_32BIT"
"@
adc%?\\t%0, %1, %2
@@ -877,9 +879,9 @@ (define_insn "addsi3_carryin_<optab>"
)
;; Canonicalization of the above when the immediate is zero.
-(define_insn "add0si3_carryin_<optab>"
+(define_insn "add0si3_carryin"
[(set (match_operand:SI 0 "s_register_operand" "=r")
- (plus:SI (LTUGEU:SI (reg:<cnb> CC_REGNUM) (const_int 0))
+ (plus:SI (match_operand:SI 2 "arm_carry_operation" "")
(match_operand:SI 1 "arm_not_operand" "r")))]
"TARGET_32BIT"
"adc%?\\t%0, %1, #0"
@@ -889,9 +891,9 @@ (define_insn "add0si3_carryin_<optab>"
(set_attr "type" "adc_imm")]
)
-(define_insn "*addsi3_carryin_alt2_<optab>"
+(define_insn "*addsi3_carryin_alt2"
[(set (match_operand:SI 0 "s_register_operand" "=l,r,r")
- (plus:SI (plus:SI (LTUGEU:SI (reg:<cnb> CC_REGNUM) (const_int 0))
+ (plus:SI (plus:SI (match_operand:SI 3 "arm_carry_operation" "")
(match_operand:SI 1 "s_register_operand" "%l,r,r"))
(match_operand:SI 2 "arm_not_operand" "l,rI,K")))]
"TARGET_32BIT"
@@ -907,28 +909,30 @@ (define_insn "*addsi3_carryin_alt2_<optab>"
(set_attr "type" "adc_reg,adc_reg,adc_imm")]
)
-(define_insn "*addsi3_carryin_shift_<optab>"
- [(set (match_operand:SI 0 "s_register_operand" "=r")
+(define_insn "*addsi3_carryin_shift"
+ [(set (match_operand:SI 0 "s_register_operand" "=r,r")
(plus:SI (plus:SI
(match_operator:SI 2 "shift_operator"
- [(match_operand:SI 3 "s_register_operand" "r")
- (match_operand:SI 4 "reg_or_int_operand" "rM")])
- (LTUGEU:SI (reg:<cnb> CC_REGNUM) (const_int 0)))
- (match_operand:SI 1 "s_register_operand" "r")))]
+ [(match_operand:SI 3 "s_register_operand" "r,r")
+ (match_operand:SI 4 "shift_amount_operand" "M,r")])
+ (match_operand:SI 5 "arm_carry_operation" ""))
+ (match_operand:SI 1 "s_register_operand" "r,r")))]
"TARGET_32BIT"
"adc%?\\t%0, %1, %3%S2"
[(set_attr "conds" "use")
+ (set_attr "arch" "32,a")
+ (set_attr "shift" "3")
(set_attr "predicable" "yes")
(set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
(const_string "alu_shift_imm")
(const_string "alu_shift_reg")))]
)
-(define_insn "*addsi3_carryin_clobercc_<optab>"
+(define_insn "*addsi3_carryin_clobercc"
[(set (match_operand:SI 0 "s_register_operand" "=r")
(plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%r")
(match_operand:SI 2 "arm_rhs_operand" "rI"))
- (LTUGEU:SI (reg:<cnb> CC_REGNUM) (const_int 0))))
+ (match_operand:SI 3 "arm_carry_operation" "")))
(clobber (reg:CC CC_REGNUM))]
"TARGET_32BIT"
"adcs%?\\t%0, %1, %2"
@@ -219,11 +219,6 @@ (define_mode_iterator VPF [V8QI V16QI V2SF V4SF])
;; Code iterators
;;----------------------------------------------------------------------------
-;; A list of condition codes used in compare instructions where
-;; the carry flag from the addition is used instead of doing the
-;; compare a second time.
-(define_code_iterator LTUGEU [ltu geu])
-
;; The signed gt, ge comparisons
(define_code_iterator GTGE [gt ge])
@@ -809,13 +804,9 @@ (define_code_attr VQH_type [(plus "add") (smin "minmax") (smax "minmax")
(define_code_attr VQH_sign [(plus "i") (smin "s") (smax "s") (umin "u")
(umax "u")])
-(define_code_attr cnb [(ltu "CC_C") (geu "CC")])
-
;; Map rtl operator codes to optab names
(define_code_attr optab
- [(ltu "ltu")
- (geu "geu")
- (and "and")
+ [(and "and")
(ior "ior")
(xor "xor")])
@@ -356,6 +356,27 @@ (define_predicate "arm_comparison_operator_mode"
(define_special_predicate "lt_ge_comparison_operator"
(match_code "lt,ge"))
+(define_special_predicate "arm_carry_operation"
+ (match_code "geu,ltu")
+ {
+ if (XEXP (op, 1) != const0_rtx)
+ return false;
+
+ rtx op0 = XEXP (op, 0);
+
+ if (!REG_P (op0) || REGNO (op0) != CC_REGNUM)
+ return false;
+
+ machine_mode ccmode = GET_MODE (op0);
+ if (ccmode == CC_Cmode)
+ return GET_CODE (op) == LTU;
+ else if (ccmode == CCmode || ccmode == CC_RSBmode)
+ return GET_CODE (op) == GEU;
+
+ return false;
+ }
+)
+
;; Match a "borrow" operation for use with SBC. The precise code will
;; depend on the form of the comparison. This is generally the inverse of
;; a carry operation, since the logic of SBC uses "not borrow" in it's