(match_test "mode != HImode")
(match_test "TARGET_SH4A_ARCH"))))
+;; A predicate describing the T bit register in any form.
+(define_predicate "t_reg_operand"
+ (match_code "reg,subreg,sign_extend,zero_extend")
+{
+ switch (GET_CODE (op))
+ {
+ case REG:
+ return REGNO (op) == T_REG;
+
+ case SUBREG:
+ return REGNO (SUBREG_REG (op)) == T_REG;
+
+ case ZERO_EXTEND:
+ case SIGN_EXTEND:
+ return GET_CODE (XEXP (op, 0)) == SUBREG
+ && REGNO (SUBREG_REG (XEXP (op, 0))) == T_REG;
+
+ default:
+ return 0;
+ }
+})
+
+;; A predicate describing a negated T bit register.
+(define_predicate "negt_reg_operand"
+ (match_code "subreg,xor")
+{
+ switch (GET_CODE (op))
+ {
+ case XOR:
+ return t_reg_operand (XEXP (op, 0), GET_MODE (XEXP (op, 0)))
+ && satisfies_constraint_M (XEXP (op, 1));
+
+ case SUBREG:
+ return negt_reg_operand (XEXP (op, 0), GET_MODE (XEXP (op, 0)));
+
+ default:
+ return 0;
+ }
+})
void
expand_cbranchsi4 (rtx *operands, enum rtx_code comparison, int probability)
{
- rtx (*branch_expander) (rtx) = gen_branch_true;
+ rtx (*branch_expander) (rtx, rtx) = gen_branch_true;
rtx jump;
comparison = prepare_cbranch_operands (operands, SImode, comparison);
emit_insn (gen_rtx_SET (VOIDmode, gen_rtx_REG (SImode, T_REG),
gen_rtx_fmt_ee (comparison, SImode,
operands[1], operands[2])));
- jump = emit_jump_insn (branch_expander (operands[3]));
+ jump = emit_jump_insn (branch_expander (operands[3], get_t_reg_rtx ()));
if (probability >= 0)
add_reg_note (jump, REG_BR_PROB, GEN_INT (probability));
if (TARGET_CMPEQDI_T)
{
emit_insn (gen_cmpeqdi_t (operands[1], operands[2]));
- emit_jump_insn (gen_branch_true (operands[3]));
+ emit_jump_insn (gen_branch_true (operands[3], get_t_reg_rtx ()));
return true;
}
msw_skip = NE;
if (TARGET_CMPEQDI_T)
{
emit_insn (gen_cmpeqdi_t (operands[1], operands[2]));
- emit_jump_insn (gen_branch_false (operands[3]));
+ emit_jump_insn (gen_branch_false (operands[3], get_t_reg_rtx ()));
return true;
}
msw_taken = NE;
sh_emit_set_t_insn (gen_ieee_ccmpeqsf_t (op0, op1), mode);
if (branch_code == code)
- emit_jump_insn (gen_branch_true (operands[3]));
+ emit_jump_insn (gen_branch_true (operands[3], get_t_reg_rtx ()));
else
- emit_jump_insn (gen_branch_false (operands[3]));
+ emit_jump_insn (gen_branch_false (operands[3], get_t_reg_rtx ()));
}
void
{
lab = gen_label_rtx ();
sh_emit_scc_to_t (EQ, op0, op1);
- emit_jump_insn (gen_branch_true (lab));
+ emit_jump_insn (gen_branch_true (lab, get_t_reg_rtx ()));
code = GT;
}
else
if (code == LSHIFTRT)
{
emit_insn (gen_rotlsi3_1 (operands[0], operands[0]));
- emit_insn (gen_movt (operands[0]));
+ emit_insn (gen_movt (operands[0], get_t_reg_rtx ()));
return;
}
else if (code == ASHIFT)
\f
#include "ggc.h"
+static GTY(()) rtx t_reg_rtx;
+rtx
+get_t_reg_rtx (void)
+{
+ if (! t_reg_rtx)
+ t_reg_rtx = gen_rtx_REG (SImode, T_REG);
+ return t_reg_rtx;
+}
+
static GTY(()) rtx fpscr_rtx;
rtx
get_fpscr_rtx (void)
result = gen_reg_rtx (SImode);
val = INTVAL (op1);
if ((code == EQ && val == 1) || (code == NE && val == 0))
- emit_insn (gen_movt (result));
+ emit_insn (gen_movt (result, get_t_reg_rtx ()));
else if ((code == EQ && val == 0) || (code == NE && val == 1))
emit_insn (gen_movnegt (result));
else if (code == EQ || code == NE)
emit_insn (gen_movsi (operands[0], operands[1]));
emit_jump_insn (INTVAL (operands[3])
- ? gen_branch_true (skip_neg_label)
- : gen_branch_false (skip_neg_label));
+ ? gen_branch_true (skip_neg_label, get_t_reg_rtx ())
+ : gen_branch_false (skip_neg_label, get_t_reg_rtx ()));
emit_label_after (skip_neg_label,
emit_insn (gen_negsi2 (operands[0], operands[1])));
emit_insn (gen_movsi (high_dst, high_src));
emit_jump_insn (INTVAL (operands[3])
- ? gen_branch_true (skip_neg_label)
- : gen_branch_false (skip_neg_label));
+ ? gen_branch_true (skip_neg_label, get_t_reg_rtx ())
+ : gen_branch_false (skip_neg_label, get_t_reg_rtx ()));
if (!INTVAL (operands[3]))
emit_insn (gen_clrt ());
;; ------------------------------------------------------------------------
(define_insn "branch_true"
- [(set (pc) (if_then_else (ne (reg:SI T_REG) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- "TARGET_SH1"
-{
- return output_branch (1, insn, operands);
-}
- [(set_attr "type" "cbranch")])
-
-;; The *branch_true patterns help combine when trying to invert conditions.
-(define_insn "*branch_true"
- [(set (pc) (if_then_else (ne (zero_extend:SI (subreg:QI (reg:SI T_REG) 0))
+ [(set (pc) (if_then_else (ne (match_operand 1 "t_reg_operand" "")
(const_int 0))
(label_ref (match_operand 0 "" ""))
(pc)))]
- "TARGET_SH1 && TARGET_LITTLE_ENDIAN"
-{
- return output_branch (1, insn, operands);
-}
- [(set_attr "type" "cbranch")])
-
-(define_insn "*branch_true"
- [(set (pc) (if_then_else (ne (zero_extend:SI (subreg:QI (reg:SI T_REG) 3))
- (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- "TARGET_SH1 && ! TARGET_LITTLE_ENDIAN"
+ "TARGET_SH1"
{
return output_branch (1, insn, operands);
}
[(set_attr "type" "cbranch")])
(define_insn "branch_false"
- [(set (pc) (if_then_else (eq (reg:SI T_REG) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- "TARGET_SH1"
-{
- return output_branch (0, insn, operands);
-}
- [(set_attr "type" "cbranch")])
-
-;; The *branch_false patterns help combine when trying to invert conditions.
-(define_insn "*branch_false"
- [(set (pc) (if_then_else (eq (zero_extend:SI (subreg:QI (reg:SI T_REG) 0))
- (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- "TARGET_SH1 && TARGET_LITTLE_ENDIAN"
-{
- return output_branch (0, insn, operands);
-}
- [(set_attr "type" "cbranch")])
-
-(define_insn "*branch_false"
- [(set (pc) (if_then_else (eq (zero_extend:SI (subreg:QI (reg:SI T_REG) 3))
+ [(set (pc) (if_then_else (eq (match_operand 1 "t_reg_operand" "")
(const_int 0))
(label_ref (match_operand 0 "" ""))
(pc)))]
- "TARGET_SH1 && ! TARGET_LITTLE_ENDIAN"
+ "TARGET_SH1"
{
return output_branch (0, insn, operands);
}
(define_insn "movt"
[(set (match_operand:SI 0 "arith_reg_dest" "=r")
- (eq:SI (reg:SI T_REG) (const_int 1)))]
+ (match_operand:SI 1 "t_reg_operand"))]
"TARGET_SH1"
"movt %0"
[(set_attr "type" "arith")])
"negc %1,%0"
[(set_attr "type" "arith")])
-;; The *negnegt patterns help the combine pass to figure out how to fold
+;; The *negnegt pattern helps the combine pass to figure out how to fold
;; an explicit double T bit negation.
(define_insn_and_split "*negnegt"
[(set (reg:SI T_REG)
- (eq:SI (subreg:QI (xor:SI (reg:SI T_REG) (const_int 1)) 3)
- (const_int 0)))]
- "! TARGET_LITTLE_ENDIAN"
- "#"
- ""
- [(const_int 0)])
-
-(define_insn_and_split "*negnegt"
- [(set (reg:SI T_REG)
- (eq:SI (subreg:QI (xor:SI (reg:SI T_REG) (const_int 1)) 0)
- (const_int 0)))]
- "TARGET_LITTLE_ENDIAN"
- "#"
- ""
- [(const_int 0)])
-
-;; The *movtt patterns eliminate redundant T bit to T bit moves / tests.
-(define_insn_and_split "*movtt"
- [(set (reg:SI T_REG)
- (eq:SI (zero_extend:SI (subreg:QI (reg:SI T_REG) 3))
- (const_int 1)))]
- "! TARGET_LITTLE_ENDIAN"
+ (eq:SI (match_operand 0 "negt_reg_operand" "") (const_int 0)))]
+ "TARGET_SH1"
"#"
""
[(const_int 0)])
+;; The *movtt pattern eliminates redundant T bit to T bit moves / tests.
(define_insn_and_split "*movtt"
[(set (reg:SI T_REG)
- (eq:SI (zero_extend:SI (subreg:QI (reg:SI T_REG) 0))
- (const_int 1)))]
- "TARGET_LITTLE_ENDIAN"
+ (eq:SI (match_operand 0 "t_reg_operand" "") (const_int 1)))]
+ "TARGET_SH1"
"#"
""
[(const_int 0)])
-;; The *movt_qi patterns help the combine pass convert a movrt_negc pattern
-;; into a movt Rn, xor #1 Rn pattern. This can happen when e.g. a function
-;; returns the inverted T bit value.
-(define_insn "*movt_qi"
- [(set (match_operand:SI 0 "arith_reg_dest" "=r")
- (zero_extend:SI (subreg:QI (reg:SI T_REG) 3)))]
- "! TARGET_LITTLE_ENDIAN"
- "movt %0"
- [(set_attr "type" "arith")])
-
-(define_insn "*movt_qi"
- [(set (match_operand:SI 0 "arith_reg_dest" "=r")
- (zero_extend:SI (subreg:QI (reg:SI T_REG) 0)))]
- "TARGET_LITTLE_ENDIAN"
- "movt %0"
- [(set_attr "type" "arith")])
-
(define_expand "cstoresf4"
[(set (match_operand:SI 0 "register_operand" "=r")
(match_operator:SI 1 "sh_float_comparison_operator"
else
{
emit_insn (gen_stack_protect_test_si (operands[0], operands[1]));
- emit_jump_insn (gen_branch_true (operands[2]));
+ emit_jump_insn (gen_branch_true (operands[2], get_t_reg_rtx ()));
}
DONE;