;;
;; One day we'll probably need to handle calls to targets more than 4M
;; away.
+;;
+
+;; Condition codes
+;;
+;; Data movement (load, store, register copy) does not modify condition
+;; codes. But there is no way to add two registers together without
+;; modifying the condition codes.
+;;
+;; So we do not expose the condition codes until after reload. The
+;; general approach is to have a define_insn_and_split for the basic
+;; operation with no condition codes in the pattern (to give the
+;; optimizers maximal freedom). The splitter adds a clobber of the
+;; condition codes after reload. There is a distinct pattern which
+;; sets the condition codes.
+;;
+;; As noted, data movement does not affect condition codes.
+;;
+;; Arithmetic generally set the codes in the expected ways, with mul
+;; instructions being a notable outlier. div instructions generally
+;; do the right thing, except when the output registers are the same
+;; when the flags do not get set. We just assume they're clobbered
+;; for div instructions to avoid MD bloat with marginal benefit
+;;
+;; The bit manipulation instructions (clr1, not1, set1) set condition
+;; codes, but not in a useful way (they're set to the prior status of
+;; the bit). So we just model those as clobbers. tst1 does set the
+;; condition codes in a useful way. We could perhaps do better with
+;; these by noting they only modify the Z flag, it doesn't seem worth
+;; the effort.
+;;
+;; Byte swaps seem to change the condition codes, but I haven't tried
+;; to describe how.
+;;
+;; I have no documentation on the rotate instructions. They likely
+;; set the condition codes, but I've left them as clobbers for now.
+
;; The size of instructions in bytes.
;; ----------------------------------------------------------------------
(define_insn "*v850_tst1"
- [(set (cc0)
+ [(set (reg:CCZ CC_REGNUM)
(compare (zero_extract:SI (match_operand:QI 0 "memory_operand" "m")
(const_int 1)
(match_operand:QI 1 "const_int_operand" "n"))
(const_int 0)))]
- ""
+ "reload_completed"
"tst1 %1,%0"
[(set_attr "length" "4")])
;; This replaces ld.b;sar;andi with tst1;setf nz.
+;; Should there be variants for HI or SI modes?
-(define_split
+(define_insn_and_split ""
[(set (match_operand:SI 0 "register_operand" "")
(compare (zero_extract:SI (match_operand:QI 1 "memory_operand" "")
(const_int 1)
(match_operand 2 "const_int_operand" ""))
(const_int 0)))]
""
- [(set (cc0) (compare (zero_extract:SI (match_dup 1)
- (const_int 1)
- (match_dup 2))
- (const_int 0)))
- (set (match_dup 0) (ne:SI (cc0) (const_int 0)))])
+ "#"
+ "reload_completed"
+ [(set (reg:CCZ CC_REGNUM) (compare (zero_extract:SI (match_dup 1)
+ (const_int 1)
+ (match_dup 2))
+ (const_int 0)))
+ (set (match_dup 0) (ne:SI (reg:CCZ CC_REGNUM) (const_int 0)))])
(define_expand "cbranchsi4"
- [(set (cc0)
- (compare (match_operand:SI 1 "register_operand" "")
- (match_operand:SI 2 "reg_or_int5_operand" "")))
- (set (pc)
+ [(set (pc)
(if_then_else
- (match_operator 0 "ordered_comparison_operator" [(cc0)
- (const_int 0)])
+ (match_operator 0 "comparison_operator"
+ [(match_operand:SI 1 "register_operand")
+ (match_operand:SI 2 "reg_or_int5_operand")])
(label_ref (match_operand 3 "" ""))
(pc)))]
"")
-(define_expand "cstoresi4"
- [(set (cc0)
- (compare (match_operand:SI 2 "register_operand" "")
- (match_operand:SI 3 "reg_or_int5_operand" "")))
- (set (match_operand:SI 0 "register_operand")
- (match_operator:SI 1 "ordered_comparison_operator" [(cc0)
- (const_int 0)]))]
- "")
-
-(define_expand "cmpsi"
- [(set (cc0)
- (compare (match_operand:SI 0 "register_operand" "r,r")
- (match_operand:SI 1 "reg_or_int5_operand" "r,J")))]
- ""
- {
- v850_compare_op0 = operands[0];
- v850_compare_op1 = operands[1];
- DONE;
- })
-
(define_insn "cmpsi_insn"
- [(set (cc0)
+ [(set (reg:CC CC_REGNUM)
(compare (match_operand:SI 0 "register_operand" "r,r")
(match_operand:SI 1 "reg_or_int5_operand" "r,J")))]
- ""
- "@
- cmp %1,%0
- cmp %1,%0"
+ "reload_completed"
+ "cmp %1,%0"
[(set_attr "length" "2,2")])
-(define_expand "cbranchsf4"
+(define_insn_and_split "cbranchsf4"
[(set (pc)
(if_then_else (match_operator 0 "ordered_comparison_operator"
- [(match_operand:SF 1 "register_operand")
- (match_operand:SF 2 "register_operand")])
+ [(match_operand:SF 1 "register_operand" "r")
+ (match_operand:SF 2 "register_operand" "r")])
(label_ref (match_operand 3 ""))
- (pc)))
- (clobber (cc0))]
+ (pc)))]
"TARGET_USE_FPU"
-{
- enum rtx_code cond = GET_CODE (operands[0]);
- machine_mode mode;
- rtx fcc_reg;
- rtx cc_reg;
- rtx tmp;
-
- v850_compare_op0 = operands[1];
- v850_compare_op1 = operands[2];
-
- if (GET_MODE_CLASS (GET_MODE (v850_compare_op0)) != MODE_FLOAT)
- FAIL;
-
- mode = v850_gen_float_compare (cond, VOIDmode, v850_compare_op0, v850_compare_op1);
- fcc_reg = gen_rtx_REG (mode, FCC_REGNUM);
- cc_reg = gen_rtx_REG (mode, CC_REGNUM);
- emit_insn (gen_rtx_SET (cc_reg, fcc_reg));
- tmp = gen_rtx_fmt_ee (cond, mode, cc_reg, const0_rtx);
- tmp = gen_rtx_IF_THEN_ELSE (VOIDmode, tmp,
- gen_rtx_LABEL_REF (VOIDmode, operands[3]), pc_rtx);
- emit_jump_insn (gen_rtx_SET (pc_rtx, tmp));
- DONE;
-})
+ "#"
+ "reload_completed"
+ [(set (match_dup 4) (match_dup 5))
+ (set (pc)
+ (if_then_else (match_dup 6)
+ (label_ref (match_dup 3))
+ (pc)))]
+ "{
+ /* This will generate the comparison insn at the start of
+ the sequence and get us the right mode to use for our
+ condition code registers. */
+ enum machine_mode mode
+ = v850_gen_float_compare (GET_CODE (operands[0]),
+ GET_MODE (operands[1]),
+ operands[1], operands[2]);
+ /* We want operands referring to CC_REGNUM and FCC_REGNUM
+ in mode MODE. */
+ operands[4] = gen_rtx_REG (mode, CC_REGNUM);
+ operands[5] = gen_rtx_REG (mode, FCC_REGNUM);
+ if (mode == CC_FPU_NEmode)
+ operands[6] = gen_rtx_NE (mode, operands[4], const0_rtx);
+ else
+ operands[6] = gen_rtx_EQ (mode, operands[4], const0_rtx);
+}")
(define_insn "cstoresf4"
[(set (match_operand:SI 0 "register_operand" "=r")
(match_operator:SI 1 "ordered_comparison_operator"
[(match_operand:SF 2 "register_operand" "r")
- (match_operand:SF 3 "register_operand" "r")]))]
+ (match_operand:SF 3 "register_operand" "r")]))
+ (clobber (reg:CC CC_REGNUM))]
"TARGET_USE_FPU"
{
if (GET_CODE (operands[1]) == GT || GET_CODE (operands[1]) == GE)
[(set_attr "length" "12")
(set_attr "type" "fpu")])
-(define_expand "cbranchdf4"
+(define_insn_and_split "cbranchdf4"
[(set (pc)
(if_then_else (match_operator 0 "ordered_comparison_operator"
- [(match_operand:DF 1 "even_reg_operand")
- (match_operand:DF 2 "even_reg_operand")])
+ [(match_operand:DF 1 "even_reg_operand" "r")
+ (match_operand:DF 2 "even_reg_operand" "r")])
(label_ref (match_operand 3 ""))
- (pc)))
- (clobber (cc0))]
+ (pc)))]
"TARGET_USE_FPU"
-{
- enum rtx_code cond = GET_CODE (operands[0]);
- machine_mode mode;
- rtx fcc_reg;
- rtx cc_reg;
- rtx tmp;
-
- v850_compare_op0 = operands[1];
- v850_compare_op1 = operands[2];
-
- if (GET_MODE_CLASS (GET_MODE (v850_compare_op0)) != MODE_FLOAT)
- FAIL;
-
- mode = v850_gen_float_compare (cond, VOIDmode, v850_compare_op0, v850_compare_op1);
- fcc_reg = gen_rtx_REG (mode, FCC_REGNUM);
- cc_reg = gen_rtx_REG (mode, CC_REGNUM);
- emit_insn (gen_rtx_SET (cc_reg, fcc_reg));
- tmp = gen_rtx_fmt_ee (cond, mode, cc_reg, const0_rtx);
- tmp = gen_rtx_IF_THEN_ELSE (VOIDmode, tmp,
- gen_rtx_LABEL_REF (VOIDmode, operands[3]), pc_rtx);
- emit_jump_insn (gen_rtx_SET (pc_rtx, tmp));
- DONE;
-})
+ "#"
+ "reload_completed"
+;; How to get the mode here?
+ [(set (match_dup 4) (match_dup 5))
+ (set (pc)
+ (if_then_else (match_dup 6)
+ (label_ref (match_dup 3))
+ (pc)))]
+ "{
+ /* This will generate the comparison insn at the start of
+ the sequence and get us the right mode to use for our
+ condition code registers. */
+ enum machine_mode mode
+ = v850_gen_float_compare (GET_CODE (operands[0]),
+ GET_MODE (operands[1]),
+ operands[1], operands[2]);
+ PUT_MODE (operands[0], mode);
+ /* We want operands referring to CC_REGNUM and FCC_REGNUM
+ in mode MODE. */
+ operands[4] = gen_rtx_REG (mode, CC_REGNUM);
+ operands[5] = gen_rtx_REG (mode, FCC_REGNUM);
+ if (mode == CC_FPU_NEmode)
+ operands[6] = gen_rtx_NE (mode, operands[4], const0_rtx);
+ else
+ operands[6] = gen_rtx_EQ (mode, operands[4], const0_rtx);
+}")
(define_insn "cstoredf4"
[(set (match_operand:SI 0 "register_operand" "=r")
(match_operator:SI 1 "ordered_comparison_operator"
[(match_operand:DF 2 "even_reg_operand" "r")
- (match_operand:DF 3 "even_reg_operand" "r")]))]
+ (match_operand:DF 3 "even_reg_operand" "r")]))
+ (clobber (reg:CC CC_REGNUM))]
"TARGET_USE_FPU"
{
if (GET_CODE (operands[1]) == GT || GET_CODE (operands[1]) == GE)
[(set_attr "length" "12")
(set_attr "type" "fpu")])
-(define_expand "cmpsf"
- [(set (reg:CC CC_REGNUM)
- (compare (match_operand:SF 0 "register_operand" "r")
- (match_operand:SF 1 "register_operand" "r")))]
- "TARGET_USE_FPU"
- {
- v850_compare_op0 = operands[0];
- v850_compare_op1 = operands[1];
- DONE;
- })
-
-(define_expand "cmpdf"
- [(set (reg:CC CC_REGNUM)
- (compare (match_operand:DF 0 "even_reg_operand" "r")
- (match_operand:DF 1 "even_reg_operand" "r")))]
- "TARGET_USE_FPU"
- {
- v850_compare_op0 = operands[0];
- v850_compare_op1 = operands[1];
- DONE;
- })
-
;; ----------------------------------------------------------------------
;; ADD INSTRUCTIONS
;; ----------------------------------------------------------------------
-(define_insn "addsi3"
+(define_insn_and_split "addsi3"
+ [(set (match_operand:SI 0 "register_operand" "=r,r,r")
+ (plus:SI (match_operand:SI 1 "register_operand" "%0,r,r")
+ (match_operand:SI 2 "nonmemory_operand" "rJ,K,U")))]
+ ""
+ "#"
+ "reload_completed"
+ [(parallel [(set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))
+ (clobber (reg:CC CC_REGNUM))])])
+
+(define_insn "addsi3_clobber_flags"
[(set (match_operand:SI 0 "register_operand" "=r,r,r")
(plus:SI (match_operand:SI 1 "register_operand" "%0,r,r")
(match_operand:SI 2 "nonmemory_operand" "rJ,K,U")))
(clobber (reg:CC CC_REGNUM))]
-
""
"@
add %2,%0
;; ----------------------------------------------------------------------
;; SUBTRACT INSTRUCTIONS
;; ----------------------------------------------------------------------
+(define_insn_and_split "subsi3"
+ [(set (match_operand:SI 0 "register_operand" "=r,r")
+ (minus:SI (match_operand:SI 1 "register_operand" "0,r")
+ (match_operand:SI 2 "register_operand" "r,0")))]
+ ""
+ "#"
+ "reload_completed"
+ [(parallel [(set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))
+ (clobber (reg:CC CC_REGNUM))])])
-(define_insn "subsi3"
+(define_insn "subsi3_clobber_flags"
[(set (match_operand:SI 0 "register_operand" "=r,r")
(minus:SI (match_operand:SI 1 "register_operand" "0,r")
(match_operand:SI 2 "register_operand" "r,0")))
subr %1,%0"
[(set_attr "length" "2,2")])
-(define_insn "negsi2"
+(define_insn_and_split "negsi2"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (neg:SI (match_operand:SI 1 "register_operand" "0")))]
+ ""
+ "#"
+ "reload_completed"
+ [(parallel [(set (match_dup 0) (neg:SI (match_dup 1)))
+ (clobber (reg:CC CC_REGNUM))])])
+
+(define_insn "negsi2_clobber_flags"
[(set (match_operand:SI 0 "register_operand" "=r")
(neg:SI (match_operand:SI 1 "register_operand" "0")))
(clobber (reg:CC CC_REGNUM))]
(match_dup 2)))
(clobber (reg:CC CC_REGNUM))]
"TARGET_V850E_UP"
- "sxh %0\n\tdivh %2,%0,%3"
+ "sxh %0\\n\\tdivh %2,%0,%3"
[(set_attr "length" "6")
(set_attr "type" "div")])
(match_dup 2)))
(clobber (reg:CC CC_REGNUM))]
"TARGET_V850E_UP"
- "zxh %0\n\tdivhu %2,%0,%3"
+ "zxh %0\\n\\ndivhu %2,%0,%3"
[(set_attr "length" "6")
(set_attr "type" "div")])
\f
[(set_attr "length" "4")
(set_attr "type" "bit1")])
-(define_insn "andsi3"
+(define_insn_and_split "andsi3"
+ [(set (match_operand:SI 0 "register_operand" "=r,r,r")
+ (and:SI (match_operand:SI 1 "register_operand" "%0,0,r")
+ (match_operand:SI 2 "nonmemory_operand" "r,I,M")))]
+ ""
+ "#"
+ "reload_completed"
+ [(parallel [(set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))
+ (clobber (reg:CC CC_REGNUM))])])
+
+(define_insn "andsi3_clobber_flags"
[(set (match_operand:SI 0 "register_operand" "=r,r,r")
(and:SI (match_operand:SI 1 "register_operand" "%0,0,r")
(match_operand:SI 2 "nonmemory_operand" "r,I,M")))
(clobber (reg:CC CC_REGNUM))]
- ""
+ "reload_completed"
"@
and %2,%0
and %.,%0
[(set_attr "length" "4")
(set_attr "type" "bit1")])
-(define_insn "iorsi3"
+(define_insn_and_split "iorsi3"
+ [(set (match_operand:SI 0 "register_operand" "=r,r,r")
+ (ior:SI (match_operand:SI 1 "register_operand" "%0,0,r")
+ (match_operand:SI 2 "nonmemory_operand" "r,I,M")))]
+ ""
+ "#"
+ "reload_completed"
+ [(parallel [(set (match_dup 0) (ior:SI (match_dup 1) (match_dup 2)))
+ (clobber (reg:CC CC_REGNUM))])])
+
+(define_insn "iorsi3_clobber_flags"
[(set (match_operand:SI 0 "register_operand" "=r,r,r")
(ior:SI (match_operand:SI 1 "register_operand" "%0,0,r")
(match_operand:SI 2 "nonmemory_operand" "r,I,M")))
[(set_attr "length" "4")
(set_attr "type" "bit1")])
-(define_insn "xorsi3"
+(define_insn_and_split "xorsi3"
+ [(set (match_operand:SI 0 "register_operand" "=r,r,r")
+ (xor:SI (match_operand:SI 1 "register_operand" "%0,0,r")
+ (match_operand:SI 2 "nonmemory_operand" "r,I,M")))]
+ ""
+ "#"
+ "reload_completed"
+ [(parallel [(set (match_dup 0) (xor:SI (match_dup 1) (match_dup 2)))
+ (clobber (reg:CC CC_REGNUM))])])
+
+(define_insn "xorsi3_clobber_flags"
[(set (match_operand:SI 0 "register_operand" "=r,r,r")
(xor:SI (match_operand:SI 1 "register_operand" "%0,0,r")
(match_operand:SI 2 "nonmemory_operand" "r,I,M")))
xor %.,%0
xori %2,%1,%0"
[(set_attr "length" "2,2,4")])
+
\f
;; ----------------------------------------------------------------------
;; NOT INSTRUCTIONS
;; ----------------------------------------------------------------------
-(define_insn "one_cmplsi2"
+(define_insn_and_split "one_cmplsi2"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (not:SI (match_operand:SI 1 "register_operand" "r")))]
+ ""
+ "#"
+ "reload_completed"
+ [(parallel [(set (match_dup 0) (not:SI (match_dup 1)))
+ (clobber (reg:CC CC_REGNUM))])])
+
+
+(define_insn "one_cmplsi2_clobber_flags"
[(set (match_operand:SI 0 "register_operand" "=r")
(not:SI (match_operand:SI 1 "register_operand" "r")))
(clobber (reg:CC CC_REGNUM))]
[(set (zero_extract:SI (match_operand:SI 0 "register_operand" "+r")
(match_operand:SI 1 "immediate_operand" "n")
(match_operand:SI 2 "immediate_operand" "n"))
- (match_operand:SI 3 "register_operand" "r"))]
+ (match_operand:SI 3 "register_operand" "r"))
+ (clobber (reg:CC CC_REGNUM))]
"TARGET_V850E3V5_UP"
"bins %3, %2, %1, %0"
[(set_attr "length" "4")])
;; Scc INSTRUCTIONS
;; -----------------------------------------------------------------
-(define_insn "*setcc"
+(define_insn_and_split "*cbranchsi4_insn"
+ [(set (pc)
+ (if_then_else (match_operator 0 "comparison_operator"
+ [(match_operand:SI 1 "register_operand" "r")
+ (match_operand:SI 2 "reg_or_int5_operand" "rJ")])
+ (label_ref (match_operand 3 "" ""))
+ (pc)))]
+ ""
+ "#"
+ "reload_completed"
+ [(set (reg:CC CC_REGNUM)
+ (compare:CC (match_dup 1) (match_dup 2)))
+ (set (pc)
+ (if_then_else (match_op_dup 0
+ [(reg:CC CC_REGNUM) (const_int 0)])
+ (label_ref (match_dup 3))
+ (pc)))]
+ "")
+
+
+(define_insn_and_split "cstoresi4"
[(set (match_operand:SI 0 "register_operand" "=r")
(match_operator:SI 1 "comparison_operator"
- [(cc0) (const_int 0)]))]
+ [(match_operand:SI 2 "register_operand" "r")
+ (match_operand:SI 3 "reg_or_int5_operand" "rJ")]))]
""
- "setf %c1,%0"
- [(set_attr "length" "4")])
+ "#"
+ "reload_completed"
+ [(set (reg:CC CC_REGNUM)
+ (compare:CC (match_dup 2) (match_dup 3)))
+ (set (match_dup 0) (match_op_dup 1
+ [(reg:CC CC_REGNUM) (const_int 0)]))]
+ "")
-(define_insn "setf_insn"
+(define_insn "*setcc_insn"
[(set (match_operand:SI 0 "register_operand" "=r")
- (match_operator:SI 1 "comparison_operator"
- [(reg:CC CC_REGNUM) (const_int 0)]))]
- ""
- "setf %b1,%0"
+ (match_operator:SI 1 "comparison_operator"
+ [(reg:CC CC_REGNUM) (const_int 0)]))]
+ "reload_completed"
+ "setf %c1,%0"
[(set_attr "length" "4")])
(define_insn "set_z_insn"
}
})
-;; ??? Clobbering the condition codes is overkill.
-
-;; ??? We sometimes emit an unnecessary compare instruction because the
-;; condition codes may have already been set by an earlier instruction,
-;; but we have no code here to avoid the compare if it is unnecessary.
-
(define_insn "movsicc_normal_cc"
[(set (match_operand:SI 0 "register_operand" "=r")
(if_then_else:SI
[(reg:CC CC_REGNUM) (const_int 0)])
(match_operand:SI 2 "reg_or_int5_operand" "rJ")
(match_operand:SI 3 "reg_or_0_operand" "rI")))]
- "(TARGET_V850E_UP)"
+ "reload_completed && (TARGET_V850E_UP)"
"cmov %c1,%2,%z3,%0";
[(set_attr "length" "6")])
[(reg:CC CC_REGNUM) (const_int 0)])
(match_operand:SI 2 "reg_or_0_operand" "rI")
(match_operand:SI 3 "reg_or_int5_operand" "rJ")))]
- "(TARGET_V850E_UP)"
+ "reload_completed && (TARGET_V850E_UP)"
"cmov %C1,%3,%z2,%0"
[(set_attr "length" "6")])
-(define_insn "*movsicc_normal"
+(define_insn_and_split "*movsicc_normal"
[(set (match_operand:SI 0 "register_operand" "=r")
(if_then_else:SI
(match_operator 1 "comparison_operator"
(match_operand:SI 2 "reg_or_int5_operand" "rJ")
(match_operand:SI 3 "reg_or_0_operand" "rI")))]
"(TARGET_V850E_UP)"
- "cmp %5,%4 ; cmov %c1,%2,%z3,%0"
- [(set_attr "length" "6")])
+ "#"
+ "reload_completed"
+ [(set (reg:CC CC_REGNUM)
+ (compare:CC (match_dup 4) (match_dup 5)))
+ (set (match_dup 0)
+ (if_then_else:SI (match_op_dup 1
+ [(reg:CC CC_REGNUM) (const_int 0)])
+ (match_dup 2) (match_dup 3)))])
-(define_insn "*movsicc_reversed"
+
+(define_insn_and_split "*movsicc_reversed"
[(set (match_operand:SI 0 "register_operand" "=r")
(if_then_else:SI
(match_operator 1 "comparison_operator"
[(match_operand:SI 4 "register_operand" "r")
(match_operand:SI 5 "reg_or_int5_operand" "rJ")])
- (match_operand:SI 2 "reg_or_0_operand" "rI")
- (match_operand:SI 3 "reg_or_int5_operand" "rJ")))]
+ (match_operand:SI 2 "reg_or_int5_operand" "rI")
+ (match_operand:SI 3 "reg_or_0_operand" "rJ")))]
"(TARGET_V850E_UP)"
- "cmp %5,%4 ; cmov %C1,%3,%z2,%0"
- [(set_attr "length" "6")])
+ "#"
+ "reload_completed"
+ [(set (reg:CC CC_REGNUM)
+ (compare:CC (match_dup 4) (match_dup 5)))
+ (set (match_dup 0)
+ (if_then_else:SI (match_op_dup 1
+ [(reg:CC CC_REGNUM) (const_int 0)])
+ (match_dup 2) (match_dup 3)))])
+;; We could expose the setting of the condition codes here.
(define_insn "*movsicc_tst1"
[(set (match_operand:SI 0 "register_operand" "=r")
(if_then_else:SI
(match_operand 3 "const_int_operand" "n"))
(const_int 0)])
(match_operand:SI 4 "reg_or_int5_operand" "rJ")
- (match_operand:SI 5 "reg_or_0_operand" "rI")))]
+ (match_operand:SI 5 "reg_or_0_operand" "rI")))
+ (clobber (reg:CC CC_REGNUM))]
"(TARGET_V850E_UP)"
"tst1 %3,%2 ; cmov %c1,%4,%z5,%0"
[(set_attr "length" "8")])
+;; We could expose the setting of the condition codes here.
(define_insn "*movsicc_tst1_reversed"
[(set (match_operand:SI 0 "register_operand" "=r")
(if_then_else:SI
(match_operand 3 "const_int_operand" "n"))
(const_int 0)])
(match_operand:SI 4 "reg_or_0_operand" "rI")
- (match_operand:SI 5 "reg_or_int5_operand" "rJ")))]
+ (match_operand:SI 5 "reg_or_int5_operand" "rJ")))
+ (clobber (reg:CC CC_REGNUM))]
"(TARGET_V850E_UP)"
"tst1 %3,%2 ; cmov %C1,%5,%z4,%0"
[(set_attr "length" "8")])
;; second pattern by subsequent combining. As above, we must include the
;; comparison to avoid input reloads in an insn using cc0.
+;; We could expose the setting of the condition codes here.
+;; However, I haven't seen this pattern used, so I'm not going
+;; to bother.
(define_insn "*sasf"
[(set (match_operand:SI 0 "register_operand" "=r")
(ior:SI
[(ashift:SI (match_operand:SI 1 "register_operand" "r")
(match_operand:SI 2 "const_int_operand" "n"))
(lshiftrt:SI (match_dup 1)
- (match_operand:SI 3 "const_int_operand" "n"))]))]
+ (match_operand:SI 3 "const_int_operand" "n"))]))
+ (clobber (reg:CC CC_REGNUM))]
"TARGET_V850E3V5_UP && (INTVAL (operands[2]) + INTVAL (operands[3]) == 32)"
"rotl %2, %1, %0"
[(set_attr "length" "4")])
[(lshiftrt:SI (match_operand:SI 1 "register_operand" "r")
(match_operand:SI 3 "const_int_operand" "n"))
(ashift:SI (match_dup 1)
- (match_operand:SI 2 "const_int_operand" "n"))]))]
+ (match_operand:SI 2 "const_int_operand" "n"))]))
+ (clobber (reg:CC CC_REGNUM))]
"TARGET_V850E3V5_UP && (INTVAL (operands[2]) + INTVAL (operands[3]) == 32)"
"rotl %2, %1, %0"
[(set_attr "length" "4")])
}
)
+;; Note the embedded arithmetic. That affects the condition codes!
(define_insn "fix_loop_counter"
[(unspec:SI [(match_operand:SI 0 "register_operand" "+r,!m")
- (clobber (match_scratch:SI 1 "=X,r"))] UNSPEC_LOOP)]
+ (clobber (match_scratch:SI 1 "=X,r"))] UNSPEC_LOOP)
+ (clobber (reg:CC CC_REGNUM))]
"TARGET_V850E3V5_UP && TARGET_LOOP"
{
switch (which_alternative)
;; Conditional jump instructions
-(define_insn "*branch_normal"
+(define_insn_and_split "*cbranchsi4_insn"
[(set (pc)
- (if_then_else (match_operator 1 "comparison_operator"
- [(cc0) (const_int 0)])
- (label_ref (match_operand 0 "" ""))
+ (if_then_else (match_operator 0 "comparison_operator"
+ [(match_operand:SI 1 "register_operand" "r")
+ (match_operand:SI 2 "reg_or_int5_operand" "rJ")])
+ (label_ref (match_operand 3 "" ""))
(pc)))]
""
-{
- if (get_attr_length (insn) == 2)
- return "b%b1 %l0";
- if (TARGET_V850E3V5_UP && get_attr_length (insn) == 4)
- return "b%b1 %l0";
- return "b%B1 .+6 ; jr %l0";
-}
- [(set (attr "length")
- (if_then_else (lt (abs (minus (match_dup 0) (pc)))
- (const_int 256))
- (const_int 2)
- (if_then_else (lt (abs (minus (match_dup 0) (pc)))
- (const_int 65536))
- (const_int 4)
- (const_int 6))))])
+ "#"
+ "reload_completed"
+ [(set (reg:CC CC_REGNUM)
+ (compare:CC (match_dup 1) (match_dup 2)))
+ (set (pc)
+ (if_then_else (match_op_dup 0
+ [(reg:CC CC_REGNUM) (const_int 0)])
+ (label_ref (match_dup 3))
+ (pc)))]
+ "")
-(define_insn "*branch_invert"
+(define_insn "*branch_normal"
[(set (pc)
(if_then_else (match_operator 1 "comparison_operator"
- [(cc0) (const_int 0)])
- (pc)
- (label_ref (match_operand 0 "" ""))))]
- ""
-{
- if (get_attr_length (insn) == 2)
- return "b%B1 %l0";
-
- if (TARGET_V850E3V5_UP && get_attr_length (insn) == 4)
- return "b%B1 %l0";
-
- return "b%b1 .+6 ; jr %l0";
-}
- [(set (attr "length")
- (if_then_else (lt (abs (minus (match_dup 0) (pc)))
- (const_int 256))
- (const_int 2)
- (if_then_else (lt (abs (minus (match_dup 0) (pc)))
- (const_int 65536))
- (const_int 4)
- (const_int 6))))])
-
-(define_insn "branch_z_normal"
- [(set (pc)
- (if_then_else (match_operand 1 "v850_float_z_comparison_operator" "")
+ [(reg CC_REGNUM) (const_int 0)])
(label_ref (match_operand 0 "" ""))
(pc)))]
- "TARGET_V850E2V3_UP"
+ "reload_completed"
{
+ bool nzmode = GET_MODE (XEXP (operands[1], 0)) == CCNZmode;
if (get_attr_length (insn) == 2)
- return "bz %l0";
-
+ {
+ if (nzmode)
+ return "b%d1 %l0";
+ else
+ return "b%b1 %l0";
+ }
if (TARGET_V850E3V5_UP && get_attr_length (insn) == 4)
- return "bz %l0";
-
- return "bnz 1f ; jr %l0 ; 1:";
+ {
+ if (nzmode)
+ return "b%d1 %l0";
+ else
+ return "b%b1 %l0";
+ }
+ if (nzmode)
+ return "b%D1 .+6 ; jr %l0";
+ else
+ return "b%B1 .+6 ; jr %l0";
}
[(set (attr "length")
(if_then_else (lt (abs (minus (match_dup 0) (pc)))
(const_int 4)
(const_int 6))))])
-(define_insn "*branch_z_invert"
+(define_insn "*branch_invert"
[(set (pc)
- (if_then_else (match_operand 1 "v850_float_z_comparison_operator" "")
+ (if_then_else (match_operator 1 "comparison_operator"
+ [(reg CC_REGNUM) (const_int 0)])
(pc)
(label_ref (match_operand 0 "" ""))))]
- "TARGET_V850E2V3_UP"
+ "reload_completed"
{
- if (get_attr_length (insn) == 2)
- return "bnz %l0";
-
- if (TARGET_V850E3V5_UP && get_attr_length (insn) == 4)
- return "bnz %l0";
-
- return "bz 1f ; jr %l0 ; 1:";
-}
- [(set (attr "length")
- (if_then_else (lt (abs (minus (match_dup 0) (pc)))
- (const_int 256))
- (const_int 2)
- (if_then_else (lt (abs (minus (match_dup 0) (pc)))
- (const_int 65536))
- (const_int 4)
- (const_int 6))))])
+ bool nzmode = GET_MODE (XEXP (operands[1], 0)) == CCNZmode;
-(define_insn "branch_nz_normal"
- [(set (pc)
- (if_then_else (match_operand 1 "v850_float_nz_comparison_operator" "")
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- "TARGET_V850E2V3_UP"
-{
if (get_attr_length (insn) == 2)
- return "bnz %l0";
-
- if (TARGET_V850E3V5_UP && get_attr_length (insn) == 4)
- return "bnz %l0";
-
- return "bz 1f ; jr %l0 ; 1:";
-}
-[(set (attr "length")
- (if_then_else (lt (abs (minus (match_dup 0) (pc)))
- (const_int 256))
- (const_int 2)
- (if_then_else (lt (abs (minus (match_dup 0) (pc)))
- (const_int 65536))
- (const_int 4)
- (const_int 6))))])
-
-(define_insn "*branch_nz_invert"
- [(set (pc)
- (if_then_else (match_operand 1 "v850_float_nz_comparison_operator" "")
- (pc)
- (label_ref (match_operand 0 "" ""))))]
- "TARGET_V850E2V3_UP"
-{
- if (get_attr_length (insn) == 2)
- return "bz %l0";
+ {
+ if (nzmode)
+ return "b%D1 %l0";
+ else
+ return "b%B1 %l0";
+ }
if (TARGET_V850E3V5_UP && get_attr_length (insn) == 4)
- return "bz %l0";
+ {
+ if (nzmode)
+ return "b%D1 %l0";
+ else
+ return "b%B1 %l0";
+ }
- return "bnz 1f ; jr %l0 ; 1:";
+ if (nzmode)
+ return "b%d1 .+6 ; jr %l0";
+ else
+ return "b%b1 .+6 ; jr %l0";
}
[(set (attr "length")
(if_then_else (lt (abs (minus (match_dup 0) (pc)))
(define_insn "call_internal_short"
[(call (mem:QI (match_operand:SI 0 "call_address_operand" "S,r"))
(match_operand:SI 1 "general_operand" "g,g"))
+ (clobber (reg:CC CC_REGNUM))
(clobber (reg:SI 31))]
"! TARGET_LONG_CALLS"
{
(define_insn "call_internal_long"
[(call (mem:QI (match_operand:SI 0 "call_address_operand" "S,r"))
(match_operand:SI 1 "general_operand" "g,g"))
+ (clobber (reg:CC CC_REGNUM))
(clobber (reg:SI 31))]
"TARGET_LONG_CALLS"
{
[(set (match_operand 0 "" "=r,r")
(call (mem:QI (match_operand:SI 1 "call_address_operand" "S,r"))
(match_operand:SI 2 "general_operand" "g,g")))
+ (clobber (reg:CC CC_REGNUM))
(clobber (reg:SI 31))]
"! TARGET_LONG_CALLS"
{
[(set (match_operand 0 "" "=r,r")
(call (mem:QI (match_operand:SI 1 "call_address_operand" "S,r"))
(match_operand:SI 2 "general_operand" "g,g")))
+ (clobber (reg:CC CC_REGNUM))
(clobber (reg:SI 31))]
"TARGET_LONG_CALLS"
{
;; EXTEND INSTRUCTIONS
;; ----------------------------------------------------------------------
+;; We only need the CC clobber because of the andi alternative
(define_insn "*zero_extendhisi2_v850e"
[(set (match_operand:SI 0 "register_operand" "=r,r,r,r")
(zero_extend:SI
(define_insn "*extendhisi_insn"
[(set (match_operand:SI 0 "register_operand" "=r,r,r")
- (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "0,Q,m")))
- (clobber (reg:CC CC_REGNUM))]
+ (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "0,Q,m")))]
"(TARGET_V850E_UP)"
"@
sxh %0
(define_insn "*extendqisi_insn"
[(set (match_operand:SI 0 "register_operand" "=r,r,r")
- (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "0,Q,m")))
- (clobber (reg:CC CC_REGNUM))]
+ (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "0,Q,m")))]
"(TARGET_V850E_UP)"
"@
sxb %0
;; SHIFTS
;; ----------------------------------------------------------------------
-(define_insn "ashlsi3"
+(define_insn_and_split "ashlsi3"
+ [(set (match_operand:SI 0 "register_operand" "=r,r")
+ (ashift:SI
+ (match_operand:SI 1 "register_operand" "0,0")
+ (match_operand:SI 2 "nonmemory_operand" "r,N")))]
+ ""
+ "#"
+ "reload_completed"
+ [(parallel [(set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))
+ (clobber (reg:CC CC_REGNUM))])])
+
+(define_insn "ashlsi3_clobber_flags"
[(set (match_operand:SI 0 "register_operand" "=r,r")
(ashift:SI
(match_operand:SI 1 "register_operand" "0,0")
shl %2,%0"
[(set_attr "length" "4,2")])
-(define_insn "ashlsi3_v850e2"
+(define_insn "ashlsi3_v850e2_clobber_flags"
[(set (match_operand:SI 0 "register_operand" "=r")
(ashift:SI
(match_operand:SI 1 "register_operand" "r")
"shl %2,%1,%0"
[(set_attr "length" "4")])
-(define_insn "lshrsi3"
+(define_insn_and_split "lshrsi3"
+ [(set (match_operand:SI 0 "register_operand" "=r,r")
+ (lshiftrt:SI
+ (match_operand:SI 1 "register_operand" "0,0")
+ (match_operand:SI 2 "nonmemory_operand" "r,N")))]
+ ""
+ "#"
+ "reload_completed"
+ [(parallel [(set (match_dup 0) (lshiftrt:SI (match_dup 1) (match_dup 2)))
+ (clobber (reg:CC CC_REGNUM))])])
+
+(define_insn "lshrsi3_clobber_flags"
[(set (match_operand:SI 0 "register_operand" "=r,r")
(lshiftrt:SI
(match_operand:SI 1 "register_operand" "0,0")
shr %2,%0"
[(set_attr "length" "4,2")])
-(define_insn "lshrsi3_v850e2"
+(define_insn "lshrsi3_v850e2_clobber_flags"
[(set (match_operand:SI 0 "register_operand" "=r")
(lshiftrt:SI
(match_operand:SI 1 "register_operand" "r")
"shr %2,%1,%0"
[(set_attr "length" "4")])
-(define_insn "ashrsi3"
+(define_insn_and_split "ashrsi3"
+ [(set (match_operand:SI 0 "register_operand" "=r,r")
+ (ashiftrt:SI
+ (match_operand:SI 1 "register_operand" "0,0")
+ (match_operand:SI 2 "nonmemory_operand" "r,N")))]
+ ""
+ "#"
+ "reload_completed"
+ [(parallel [(set (match_dup 0) (ashiftrt:SI (match_dup 1) (match_dup 2)))
+ (clobber (reg:CC CC_REGNUM))])])
+
+(define_insn "ashrsi3_clobber_flags"
[(set (match_operand:SI 0 "register_operand" "=r,r")
(ashiftrt:SI
(match_operand:SI 1 "register_operand" "0,0")
sar %2,%0"
[(set_attr "length" "4,2")])
-(define_insn "ashrsi3_v850e2"
+(define_insn "ashrsi3_v850e2_clobber_flags"
[(set (match_operand:SI 0 "register_operand" "=r")
(ashiftrt:SI
(match_operand:SI 1 "register_operand" "r")
;; ---------------- special insns
;;
+;; reciprocal
+
;; Generic code demands that the recip and rsqrt named patterns
;; have precisely one operand. So that's what we expose in the
;; expander via the strange UNSPEC. However, those expanders
[(set (reg:CC_FPU_LE FCC_REGNUM)
(compare:CC_FPU_LE (match_operand:SF 0 "register_operand" "r")
(match_operand:SF 1 "register_operand" "r")))]
- "TARGET_USE_FPU"
+ "reload_completed && TARGET_USE_FPU"
"cmpf.s le, %z0, %z1"
[(set_attr "length" "4")
(set_attr "type" "fpu")])
[(set (reg:CC_FPU_LT FCC_REGNUM)
(compare:CC_FPU_LT (match_operand:SF 0 "register_operand" "r")
(match_operand:SF 1 "register_operand" "r")))]
- "TARGET_USE_FPU"
+ "reload_completed && TARGET_USE_FPU"
"cmpf.s lt, %z0, %z1"
[(set_attr "length" "4")
(set_attr "type" "fpu")])
[(set (reg:CC_FPU_GE FCC_REGNUM)
(compare:CC_FPU_GE (match_operand:SF 0 "register_operand" "r")
(match_operand:SF 1 "register_operand" "r")))]
- "TARGET_USE_FPU"
+ "reload_completed && TARGET_USE_FPU"
"cmpf.s le, %z1, %z0"
[(set_attr "length" "4")
(set_attr "type" "fpu")])
[(set (reg:CC_FPU_GT FCC_REGNUM)
(compare:CC_FPU_GT (match_operand:SF 0 "register_operand" "r")
(match_operand:SF 1 "register_operand" "r")))]
- "TARGET_USE_FPU"
+ "reload_completed && TARGET_USE_FPU"
"cmpf.s lt, %z1, %z0"
[(set_attr "length" "4")
(set_attr "type" "fpu")])
[(set (reg:CC_FPU_EQ FCC_REGNUM)
(compare:CC_FPU_EQ (match_operand:SF 0 "register_operand" "r")
(match_operand:SF 1 "register_operand" "r")))]
- "TARGET_USE_FPU"
+ "reload_completed && TARGET_USE_FPU"
"cmpf.s eq, %z0, %z1"
[(set_attr "length" "4")
(set_attr "type" "fpu")])
[(set (reg:CC_FPU_LE FCC_REGNUM)
(compare:CC_FPU_LE (match_operand:DF 0 "even_reg_operand" "r")
(match_operand:DF 1 "even_reg_operand" "r")))]
- "TARGET_USE_FPU"
+ "reload_completed && TARGET_USE_FPU"
"cmpf.d le, %z0, %z1"
[(set_attr "length" "4")
(set_attr "type" "fpu")])
[(set (reg:CC_FPU_LT FCC_REGNUM)
(compare:CC_FPU_LT (match_operand:DF 0 "even_reg_operand" "r")
(match_operand:DF 1 "even_reg_operand" "r")))]
- "TARGET_USE_FPU"
+ "reload_completed && TARGET_USE_FPU"
"cmpf.d lt, %z0, %z1"
[(set_attr "length" "4")
(set_attr "type" "fpu")])
[(set (reg:CC_FPU_GE FCC_REGNUM)
(compare:CC_FPU_GE (match_operand:DF 0 "even_reg_operand" "r")
(match_operand:DF 1 "even_reg_operand" "r")))]
- "TARGET_USE_FPU"
+ "reload_completed && TARGET_USE_FPU"
"cmpf.d le, %z1, %z0"
[(set_attr "length" "4")
(set_attr "type" "fpu")])
[(set (reg:CC_FPU_GT FCC_REGNUM)
(compare:CC_FPU_GT (match_operand:DF 0 "even_reg_operand" "r")
(match_operand:DF 1 "even_reg_operand" "r")))]
- "TARGET_USE_FPU"
+ "reload_completed && TARGET_USE_FPU"
"cmpf.d lt, %z1, %z0"
[(set_attr "length" "4")
(set_attr "type" "fpu")])
[(set (reg:CC_FPU_EQ FCC_REGNUM)
(compare:CC_FPU_EQ (match_operand:DF 0 "even_reg_operand" "r")
(match_operand:DF 1 "even_reg_operand" "r")))]
- "TARGET_USE_FPU"
+ "reload_completed && TARGET_USE_FPU"
"cmpf.d eq, %z0, %z1"
[(set_attr "length" "4")
(set_attr "type" "fpu")])
(define_insn "trfsr"
[(set (match_operand 0 "" "") (match_operand 1 "" ""))]
- "TARGET_USE_FPU
+ "reload_completed
+ && TARGET_USE_FPU
&& GET_MODE(operands[0]) == GET_MODE(operands[1])
&& GET_CODE(operands[0]) == REG && REGNO (operands[0]) == CC_REGNUM
&& GET_CODE(operands[1]) == REG && REGNO (operands[1]) == FCC_REGNUM
;; Initialize an interrupt function. Do not depend on TARGET_PROLOG_FUNCTION.
(define_insn "callt_save_interrupt"
- [(unspec_volatile [(const_int 0)] 2)]
+ [(unspec_volatile [(const_int 0)] 2)
+ (clobber (reg:CC CC_REGNUM))]
"(TARGET_V850E_UP) && !TARGET_DISABLE_CALLT"
;; The CALLT instruction stores the next address of CALLT to CTPC register
;; without saving its previous value. So if the interrupt handler
[(set_attr "length" "26")])
(define_insn "callt_return_interrupt"
- [(unspec_volatile [(const_int 0)] 3)]
+ [(unspec_volatile [(const_int 0)] 3)
+ (clobber (reg:CC CC_REGNUM))]
"(TARGET_V850E_UP) && !TARGET_DISABLE_CALLT"
"callt ctoff(__callt_return_interrupt)"
[(set_attr "length" "2")])
(set (mem:SI (plus:SI (reg:SI 3) (const_int -16))) (reg:SI 4))
(set (mem:SI (plus:SI (reg:SI 3) (const_int -12))) (reg:SI 1))
(set (mem:SI (plus:SI (reg:SI 3) (const_int -8))) (reg:SI 10))
- (set (mem:SI (plus:SI (reg:SI 3) (const_int -4))) (reg:SI 11))]
+ (set (mem:SI (plus:SI (reg:SI 3) (const_int -4))) (reg:SI 11))
+ (clobber (reg:CC CC_REGNUM))]
""
{
if (TARGET_PROLOG_FUNCTION && !TARGET_LONG_CALLS)
(set (reg:SI 10) (mem:SI (plus:SI (reg:SI 3) (const_int 12))))
(set (reg:SI 1) (mem:SI (plus:SI (reg:SI 3) (const_int 8))))
(set (reg:SI 4) (mem:SI (plus:SI (reg:SI 3) (const_int 4))))
- (set (reg:SI 30) (mem:SI (reg:SI 3)))]
+ (set (reg:SI 30) (mem:SI (reg:SI 3)))
+ (clobber (reg:CC CC_REGNUM))]
""
{
if (TARGET_PROLOG_FUNCTION && !TARGET_LONG_CALLS)
;; insns this complicated.
(define_insn "callt_save_all_interrupt"
- [(unspec_volatile [(const_int 0)] 0)]
+ [(unspec_volatile [(const_int 0)] 0)
+ (clobber (reg:CC CC_REGNUM))]
"(TARGET_V850E_UP) && !TARGET_DISABLE_CALLT"
"callt ctoff(__callt_save_all_interrupt)"
[(set_attr "length" "2")])
(define_insn "save_all_interrupt"
- [(unspec_volatile [(const_int 0)] 0)]
+ [(unspec_volatile [(const_int 0)] 0)
+ (clobber (reg:CC CC_REGNUM))]
""
{
if (TARGET_PROLOG_FUNCTION && !TARGET_LONG_CALLS)
[(set (attr "length")
(if_then_else (match_test "TARGET_LONG_CALLS")
(const_int 4)
- (const_int 62)))])
+ (const_int 62)
+ ))])
(define_insn "_save_all_interrupt"
- [(unspec_volatile [(const_int 0)] 0)]
+ [(unspec_volatile [(const_int 0)] 0)
+ (clobber (reg:CC CC_REGNUM))]
"TARGET_V850 && ! TARGET_LONG_CALLS"
"jarl __save_all_interrupt,r10"
[(set_attr "length" "4")])
;; insns this complicated.
(define_insn "callt_restore_all_interrupt"
- [(unspec_volatile [(const_int 0)] 1)]
+ [(unspec_volatile [(const_int 0)] 1)
+ (clobber (reg:CC CC_REGNUM))]
"(TARGET_V850E_UP) && !TARGET_DISABLE_CALLT"
"callt ctoff(__callt_restore_all_interrupt)"
[(set_attr "length" "2")])
(define_insn "restore_all_interrupt"
- [(unspec_volatile [(const_int 0)] 1)]
+ [(unspec_volatile [(const_int 0)] 1)
+ (clobber (reg:CC CC_REGNUM))]
""
{
if (TARGET_PROLOG_FUNCTION && !TARGET_LONG_CALLS)
))])
(define_insn "_restore_all_interrupt"
- [(unspec_volatile [(const_int 0)] 1)]
+ [(unspec_volatile [(const_int 0)] 1)
+ (clobber (reg:CC CC_REGNUM))]
"TARGET_V850 && ! TARGET_LONG_CALLS"
"jarl __restore_all_interrupt,r10"
[(set_attr "length" "4")])