This tidies up a few spots in the m68k backend in preparation for the
large patch to follow. This is purely for review purposes: this patch
has not been tested independently, and will be committed together with
the following one.
Noteworthy changes:
Some patterns and peepholes were unified through mode iterators. The
m68k_subword_comparison_operator predicate was adapted to also work with
SImode.
There are already scc_di patterns, so there is no need to generate a cc0
set/use pair in cstoredi.
Without HAVE_cc0, combine sometimes substitutes a stack push into the
destination of a divmod instruction, and then gets confused because it
doesn't seem to expect it in a PARALLEL. Since the instruction only
works on registers anyway, use register_operand.
There are patterns that use register_operand with "do" constraints which
allow memory. This works at reload time, but the instruction can not be
rerecognized later on. This becomes a problem if such operands occur in
a jump instruction, as subsequent passes will try to redirect branches
and thus attempt to rerecognize the pattern.
movqi/movhi do not accept constants that are not CONST_INT. The code to
output them would not set flags correctly and was changed to
gcc_unreachable.
Comments were added to some patterns which are not being generated due
to incorrect tests/predicates. Fixing these is out of scope for this
work, but the problems are at least documented.
All the passes working on conditional traps seem to assume
const_true_rtx is used for unconditional ones, rather than const1_rtx.
Bernd
* config/m68k/m68k.c (output_move_himode, output_move_qimode):
Replace code for non-CONST_INT constants with gcc_unreachable.
* config/m68k/m68k.md (cbranchdi): Don't generate individual
compare and test.
(CMPMODE): New mode_iterator.
(cbranchsi4, cbranchqi4, cbranchhi4): Replace expanders with
cbranch<mode>4.
(cstoresi4, cstoreqi4, cstorehi4): Replace expanders with
cstore<mode>4.
(cmp<mode>_68881): Remove 'F' constraint from first comparison
operand.
(bit test insns patterns): Use nonimmediate_operand, not
register_operand, for source operands that allow memory in
their constraints.
(divmodsi4, udivmodsi4, divmodhi4 and related unnamed patterns):
Use register_operand, not nonimmediate_operand, for the
destinations.
(DBCC): New mode_iterator.
(dbcc peepholes): Use it to reduce duplication.
(trap): Use const_true_rtx, not const1_rtx.
* config/m68k/predicates.md (m68k_comparison_operand): Renamed
from m68k_subword_comparison_operand and changed to handle
SImode.
diff --git a/gcc/config/m68k/m68k.c b/gcc/config/m68k/m68k.c
index 1030dfa5957..4f3503b9118 100644
--- a/gcc/config/m68k/m68k.c
+++ b/gcc/config/m68k/m68k.c
@@ -3072,7 +3072,7 @@ output_move_simode (rtx *operands)
const char *
output_move_himode (rtx *operands)
{
- if (GET_CODE (operands[1]) == CONST_INT)
+ if (GET_CODE (operands[1]) == CONST_INT)
{
if (operands[1] == const0_rtx
&& (DATA_REG_P (operands[0])
@@ -3094,7 +3094,7 @@ output_move_himode (rtx *operands)
return "move%.w %1,%0";
}
else if (CONSTANT_P (operands[1]))
- return "move%.l %1,%0";
+ gcc_unreachable ();
return "move%.w %1,%0";
}
@@ -3103,7 +3103,7 @@ output_move_qimode (rtx *operands)
{
/* 68k family always modifies the stack pointer by at least 2, even for
byte pushes. The 5200 (ColdFire) does not do this. */
-
+
/* This case is generated by pushqi1 pattern now. */
gcc_assert (!(GET_CODE (operands[0]) == MEM
&& GET_CODE (XEXP (operands[0], 0)) == PRE_DEC
@@ -3134,7 +3134,7 @@ output_move_qimode (rtx *operands)
if (operands[1] == const0_rtx && ADDRESS_REG_P (operands[0]))
return "sub%.l %0,%0";
if (GET_CODE (operands[1]) != CONST_INT && CONSTANT_P (operands[1]))
- return "move%.l %1,%0";
+ gcc_unreachable ();
/* 68k family (including the 5200 ColdFire) does not support byte moves to
from address registers. */
if (ADDRESS_REG_P (operands[0]) || ADDRESS_REG_P (operands[1]))
diff --git a/gcc/config/m68k/m68k.md b/gcc/config/m68k/m68k.md
index 31e8767e7e3..e60978150d1 100644
--- a/gcc/config/m68k/m68k.md
+++ b/gcc/config/m68k/m68k.md
@@ -456,19 +456,14 @@
(match_operand:DI 3 "general_operand")]))]
""
{
- if (operands[3] == const0_rtx)
- emit_insn (gen_tstdi (operands[2]));
- else
- emit_insn (gen_cmpdi (operands[2], operands[3]));
- operands[2] = cc0_rtx;
- operands[3] = const0_rtx;
})
+(define_mode_iterator CMPMODE [QI HI SI])
-(define_expand "cbranchsi4"
+(define_expand "cbranch<mode>4"
[(set (cc0)
- (compare (match_operand:SI 1 "nonimmediate_operand" "")
- (match_operand:SI 2 "general_operand" "")))
+ (compare (match_operand:CMPMODE 1 "nonimmediate_operand" "")
+ (match_operand:CMPMODE 2 "m68k_comparison_operand" "")))
(set (pc)
(if_then_else (match_operator 0 "ordered_comparison_operator"
[(cc0) (const_int 0)])
@@ -477,17 +472,16 @@
""
"")
-(define_expand "cstoresi4"
+(define_expand "cstore<mode>4"
[(set (cc0)
- (compare (match_operand:SI 2 "nonimmediate_operand" "")
- (match_operand:SI 3 "general_operand" "")))
+ (compare (match_operand:CMPMODE 2 "nonimmediate_operand" "")
+ (match_operand:CMPMODE 3 "m68k_comparison_operand" "")))
(set (match_operand:QI 0 "register_operand")
(match_operator:QI 1 "ordered_comparison_operator"
[(cc0) (const_int 0)]))]
""
"")
-
;; A composite of the cmp, cmpa, cmpi & cmpm m68000 op codes.
;;
;; In theory we ought to be able to use some 'S' constraints and
@@ -536,28 +530,6 @@
}
[(set_attr "type" "cmp_l")])
-(define_expand "cbranchhi4"
- [(set (cc0)
- (compare (match_operand:HI 1 "nonimmediate_operand" "")
- (match_operand:HI 2 "m68k_subword_comparison_operand" "")))
- (set (pc)
- (if_then_else (match_operator 0 "ordered_comparison_operator"
- [(cc0) (const_int 0)])
- (label_ref (match_operand 3 ""))
- (pc)))]
- ""
- "")
-
-(define_expand "cstorehi4"
- [(set (cc0)
- (compare (match_operand:HI 2 "nonimmediate_operand" "")
- (match_operand:HI 3 "m68k_subword_comparison_operand" "")))
- (set (match_operand:QI 0 "register_operand")
- (match_operator:QI 1 "ordered_comparison_operator"
- [(cc0) (const_int 0)]))]
- ""
- "")
-
(define_insn ""
[(set (cc0)
(compare (match_operand:HI 0 "nonimmediate_operand" "rnm,d,n,m,>")
@@ -575,28 +547,6 @@
return "cmp%.w %d1,%d0";
})
-(define_expand "cbranchqi4"
- [(set (cc0)
- (compare (match_operand:QI 1 "nonimmediate_operand" "")
- (match_operand:QI 2 "m68k_subword_comparison_operand" "")))
- (set (pc)
- (if_then_else (match_operator 0 "ordered_comparison_operator"
- [(cc0) (const_int 0)])
- (label_ref (match_operand 3 ""))
- (pc)))]
- ""
- "")
-
-(define_expand "cstoreqi4"
- [(set (cc0)
- (compare (match_operand:QI 2 "nonimmediate_operand" "")
- (match_operand:QI 3 "m68k_subword_comparison_operand" "")))
- (set (match_operand:QI 0 "register_operand")
- (match_operator:QI 1 "ordered_comparison_operator"
- [(cc0) (const_int 0)]))]
- ""
- "")
-
(define_insn ""
[(set (cc0)
(compare (match_operand:QI 0 "nonimmediate_operand" "dn,dm,>")
@@ -626,6 +576,8 @@
"TARGET_HARD_FLOAT"
"")
+;; ??? This presumably tries to allow tests against zero for coldfire, but
+;; it would have to test operands[3] and use CONST0_RTX (mode).
(define_expand "cstore<mode>4"
[(set (cc0)
(compare (match_operand:FP 2 "register_operand" "")
@@ -639,7 +591,7 @@
(define_insn "*cmp<mode>_68881"
[(set (cc0)
- (compare (match_operand:FP 0 "fp_src_operand" "f,f,<FP:dreg>mF")
+ (compare (match_operand:FP 0 "fp_src_operand" "f,f,<FP:dreg>m")
(match_operand:FP 1 "fp_src_operand" "f,<FP:dreg>mF,f")))]
"TARGET_68881
&& (register_operand (operands[0], <MODE>mode)
@@ -763,7 +715,7 @@
(define_insn ""
[(set
(cc0)
- (compare (zero_extract:SI (match_operand:SI 0 "register_operand" "do")
+ (compare (zero_extract:SI (match_operand:SI 0 "nonimmediate_operand" "do")
(const_int 1)
(match_operand:SI 1 "const_int_operand" "n"))
(const_int 0)))]
@@ -787,7 +739,7 @@
(define_insn ""
[(set
(cc0)
- (compare (zero_extract:SI (match_operand:SI 0 "register_operand" "dQ")
+ (compare (zero_extract:SI (match_operand:SI 0 "nonimmediate_operand" "dQ")
(const_int 1)
(match_operand:SI 1 "const_int_operand" "n"))
(const_int 0)))]
@@ -3483,19 +3435,19 @@
(define_expand "divmodsi4"
[(parallel
- [(set (match_operand:SI 0 "nonimmediate_operand" "")
+ [(set (match_operand:SI 0 "register_operand" "")
(div:SI (match_operand:SI 1 "general_operand" "")
(match_operand:SI 2 "general_src_operand" "")))
- (set (match_operand:SI 3 "nonimmediate_operand" "")
+ (set (match_operand:SI 3 "register_operand" "")
(mod:SI (match_dup 1) (match_dup 2)))])]
"TARGET_68020 || TARGET_CF_HWDIV"
"")
(define_insn ""
- [(set (match_operand:SI 0 "nonimmediate_operand" "=d")
+ [(set (match_operand:SI 0 "register_operand" "=d")
(div:SI (match_operand:SI 1 "general_operand" "0")
(match_operand:SI 2 "general_src_operand" "d<Q>U")))
- (set (match_operand:SI 3 "nonimmediate_operand" "=&d")
+ (set (match_operand:SI 3 "register_operand" "=&d")
(mod:SI (match_dup 1) (match_dup 2)))]
"TARGET_CF_HWDIV"
{
@@ -3510,10 +3462,10 @@
(set_attr "opy" "2")])
(define_insn ""
- [(set (match_operand:SI 0 "nonimmediate_operand" "=d")
+ [(set (match_operand:SI 0 "register_operand" "=d")
(div:SI (match_operand:SI 1 "general_operand" "0")
(match_operand:SI 2 "general_src_operand" "dmSTK")))
- (set (match_operand:SI 3 "nonimmediate_operand" "=d")
+ (set (match_operand:SI 3 "register_operand" "=d")
(mod:SI (match_dup 1) (match_dup 2)))]
"TARGET_68020"
{
@@ -3525,19 +3477,19 @@
(define_expand "udivmodsi4"
[(parallel
- [(set (match_operand:SI 0 "nonimmediate_operand" "=d")
+ [(set (match_operand:SI 0 "register_operand" "=d")
(udiv:SI (match_operand:SI 1 "general_operand" "0")
(match_operand:SI 2 "general_src_operand" "dmSTK")))
- (set (match_operand:SI 3 "nonimmediate_operand" "=d")
+ (set (match_operand:SI 3 "register_operand" "=d")
(umod:SI (match_dup 1) (match_dup 2)))])]
"TARGET_68020 || TARGET_CF_HWDIV"
"")
(define_insn ""
- [(set (match_operand:SI 0 "nonimmediate_operand" "=d")
+ [(set (match_operand:SI 0 "register_operand" "=d")
(udiv:SI (match_operand:SI 1 "general_operand" "0")
(match_operand:SI 2 "general_src_operand" "d<Q>U")))
- (set (match_operand:SI 3 "nonimmediate_operand" "=&d")
+ (set (match_operand:SI 3 "register_operand" "=&d")
(umod:SI (match_dup 1) (match_dup 2)))]
"TARGET_CF_HWDIV"
{
@@ -3552,10 +3504,10 @@
(set_attr "opy" "2")])
(define_insn ""
- [(set (match_operand:SI 0 "nonimmediate_operand" "=d")
+ [(set (match_operand:SI 0 "register_operand" "=d")
(udiv:SI (match_operand:SI 1 "general_operand" "0")
(match_operand:SI 2 "general_src_operand" "dmSTK")))
- (set (match_operand:SI 3 "nonimmediate_operand" "=d")
+ (set (match_operand:SI 3 "register_operand" "=d")
(umod:SI (match_dup 1) (match_dup 2)))]
"TARGET_68020 && !TARGET_COLDFIRE"
{
@@ -3566,10 +3518,10 @@
})
(define_insn "divmodhi4"
- [(set (match_operand:HI 0 "nonimmediate_operand" "=d")
+ [(set (match_operand:HI 0 "register_operand" "=d")
(div:HI (match_operand:HI 1 "general_operand" "0")
(match_operand:HI 2 "general_src_operand" "dmSKT")))
- (set (match_operand:HI 3 "nonimmediate_operand" "=d")
+ (set (match_operand:HI 3 "register_operand" "=d")
(mod:HI (match_dup 1) (match_dup 2)))]
"!TARGET_COLDFIRE || TARGET_CF_HWDIV"
{
@@ -3590,7 +3542,7 @@
[(set (match_operand:HI 0 "nonimmediate_operand" "=d")
(udiv:HI (match_operand:HI 1 "general_operand" "0")
(match_operand:HI 2 "general_src_operand" "dmSKT")))
- (set (match_operand:HI 3 "nonimmediate_operand" "=d")
+ (set (match_operand:HI 3 "register_operand" "=d")
(umod:HI (match_dup 1) (match_dup 2)))]
"!TARGET_COLDFIRE || TARGET_CF_HWDIV"
{
@@ -7379,6 +7331,7 @@
;;
;; Which moves the jCC condition outside the inner loop for free.
;;
+(define_mode_iterator DBCC [HI SI])
(define_peephole
[(set (pc) (if_then_else (match_operator 3 "valid_dbcc_comparison_p"
@@ -7388,13 +7341,13 @@
(parallel
[(set (pc)
(if_then_else
- (ne (match_operand:HI 0 "register_operand" "")
+ (ne (match_operand:DBCC 0 "register_operand" "")
(const_int 0))
(label_ref (match_operand 1 "" ""))
(pc)))
(set (match_dup 0)
- (plus:HI (match_dup 0)
- (const_int -1)))])]
+ (plus:DBCC (match_dup 0)
+ (const_int -1)))])]
"!TARGET_COLDFIRE && DATA_REG_P (operands[0]) && ! flags_in_68881 ()"
{
CC_STATUS_INIT;
@@ -7410,66 +7363,20 @@
(parallel
[(set (pc)
(if_then_else
- (ne (match_operand:SI 0 "register_operand" "")
+ (ge (plus:DBCC (match_operand:DBCC 0 "register_operand" "")
+ (const_int -1))
(const_int 0))
(label_ref (match_operand 1 "" ""))
(pc)))
(set (match_dup 0)
- (plus:SI (match_dup 0)
- (const_int -1)))])]
+ (plus:DBCC (match_dup 0)
+ (const_int -1)))])]
"!TARGET_COLDFIRE && DATA_REG_P (operands[0]) && ! flags_in_68881 ()"
{
CC_STATUS_INIT;
output_dbcc_and_branch (operands);
return "";
})
-
-(define_peephole
- [(set (pc) (if_then_else (match_operator 3 "valid_dbcc_comparison_p"
- [(cc0) (const_int 0)])
- (label_ref (match_operand 2 "" ""))
- (pc)))
- (parallel
- [(set (pc)
- (if_then_else
- (ge (plus:HI (match_operand:HI 0 "register_operand" "")
- (const_int -1))
- (const_int 0))
- (label_ref (match_operand 1 "" ""))
- (pc)))
- (set (match_dup 0)
- (plus:HI (match_dup 0)
- (const_int -1)))])]
- "!TARGET_COLDFIRE && DATA_REG_P (operands[0]) && ! flags_in_68881 ()"
-{
- CC_STATUS_INIT;
- output_dbcc_and_branch (operands);
- return "";
-})
-
-(define_peephole
- [(set (pc) (if_then_else (match_operator 3 "valid_dbcc_comparison_p"
- [(cc0) (const_int 0)])
- (label_ref (match_operand 2 "" ""))
- (pc)))
- (parallel
- [(set (pc)
- (if_then_else
- (ge (plus:SI (match_operand:SI 0 "register_operand" "")
- (const_int -1))
- (const_int 0))
- (label_ref (match_operand 1 "" ""))
- (pc)))
- (set (match_dup 0)
- (plus:SI (match_dup 0)
- (const_int -1)))])]
- "!TARGET_COLDFIRE && DATA_REG_P (operands[0]) && ! flags_in_68881 ()"
-{
- CC_STATUS_INIT;
- output_dbcc_and_branch (operands);
- return "";
-})
-
(define_insn "extendsfxf2"
[(set (match_operand:XF 0 "nonimmediate_operand" "=fm,f")
@@ -7583,13 +7490,17 @@
return "fcos%.<FP:prec> %1,%0";
})
-;; Unconditional traps are assumed to have (const_int 1) for the condition.
+;; Unconditional traps are assumed to have const_true_rtx for the condition.
(define_insn "trap"
- [(trap_if (const_int 1) (const_int 7))]
+ [(trap_if (const_int -1) (const_int 7))]
""
"trap #7"
[(set_attr "type" "trap")])
+;; ??? Our trap instruction uses constant 7 for operand 3, which is
+;; also the trap vector used by TRAPcc instruction. By restricting
+;; these patterns to const1_operand, they will not be generated.
+;; Left disabled for now, as enabling it seems to cause issues.
(define_expand "ctrapdi4"
[(trap_if (match_operator 0 "ordered_comparison_operator"
[(cc0) (const_int 0)])
diff --git a/gcc/config/m68k/predicates.md b/gcc/config/m68k/predicates.md
index ad297883f85..4cc3d3dc1bd 100644
--- a/gcc/config/m68k/predicates.md
+++ b/gcc/config/m68k/predicates.md
@@ -210,10 +210,10 @@
(and (match_code "const_int")
(match_test "op == const1_rtx")))
-;; A valid operand for a HImode or QImode conditional operation.
-;; ColdFire has tst patterns, but not cmp patterns.
-(define_predicate "m68k_subword_comparison_operand"
- (if_then_else (match_test "TARGET_COLDFIRE")
+;; A valid operand for a conditional operation.
+;; ColdFire has tst patterns for HImode and QImode, but not cmp patterns.
+(define_predicate "m68k_comparison_operand"
+ (if_then_else (match_test "TARGET_COLDFIRE && mode != SImode")
(and (match_code "const_int")
(match_test "op == const0_rtx"))
(match_operand 0 "general_src_operand")))