#define IN_TARGET_CODE 1
#include "config.h"
+#define INCLUDE_STRING
#include "system.h"
#include "coretypes.h"
#include "backend.h"
static bool m68k_modes_tieable_p (machine_mode, machine_mode);
static machine_mode m68k_promote_function_mode (const_tree, machine_mode,
int *, const_tree, int);
+static void m68k_asm_final_postscan_insn (FILE *, rtx_insn *insn, rtx [], int);
\f
/* Initialize the GCC target structure. */
#undef TARGET_HAVE_SPECULATION_SAFE_VALUE
#define TARGET_HAVE_SPECULATION_SAFE_VALUE speculation_safe_value_not_needed
+#undef TARGET_ASM_FINAL_POSTSCAN_INSN
+#define TARGET_ASM_FINAL_POSTSCAN_INSN m68k_asm_final_postscan_insn
+
static const struct attribute_spec m68k_attribute_table[] =
{
/* { name, min_len, max_len, decl_req, type_req, fn_type_req,
emit_jump_insn (ret_rtx);
}
\f
-/* Return true if X is a valid comparison operator for the dbcc
- instruction.
-
- Note it rejects floating point comparison operators.
- (In the future we could use Fdbcc).
-
- It also rejects some comparisons when CC_NO_OVERFLOW is set. */
-
-int
-valid_dbcc_comparison_p_2 (rtx x, machine_mode mode ATTRIBUTE_UNUSED)
-{
- switch (GET_CODE (x))
- {
- case EQ: case NE: case GTU: case LTU:
- case GEU: case LEU:
- return 1;
-
- /* Reject some when CC_NO_OVERFLOW is set. This may be over
- conservative */
- case GT: case LT: case GE: case LE:
- return ! (cc_prev_status.flags & CC_NO_OVERFLOW);
- default:
- return 0;
- }
-}
-
-/* Return nonzero if flags are currently in the 68881 flag register. */
-int
-flags_in_68881 (void)
-{
- /* We could add support for these in the future */
- return cc_status.flags & CC_IN_68881;
-}
-
/* Return true if PARALLEL contains register REGNO. */
static bool
m68k_reg_present_p (const_rtx parallel, unsigned int regno)
return x;
}
+\f
+/* For eliding comparisons, we remember how the flags were set.
+ FLAGS_COMPARE_OP0 and FLAGS_COMPARE_OP1 are remembered for a direct
+ comparison, they take priority. FLAGS_OPERAND1 and FLAGS_OPERAND2
+ are used in more cases, they are a fallback for comparisons against
+ zero after a move or arithmetic insn.
+ FLAGS_VALID is set to FLAGS_VALID_NO if we should not use any of
+ these values. */
+
+static rtx flags_compare_op0, flags_compare_op1;
+static rtx flags_operand1, flags_operand2;
+static attr_flags_valid flags_valid = FLAGS_VALID_NO;
+
+/* Return a code other than UNKNOWN if we can elide a CODE comparison of
+ OP0 with OP1. */
+
+rtx_code
+m68k_find_flags_value (rtx op0, rtx op1, rtx_code code)
+{
+ if (flags_compare_op0 != NULL_RTX)
+ {
+ if (rtx_equal_p (op0, flags_compare_op0)
+ && rtx_equal_p (op1, flags_compare_op1))
+ return code;
+ if (rtx_equal_p (op0, flags_compare_op1)
+ && rtx_equal_p (op1, flags_compare_op0))
+ return swap_condition (code);
+ return UNKNOWN;
+ }
+
+ machine_mode mode = GET_MODE (op0);
+ if (op1 != CONST0_RTX (mode))
+ return UNKNOWN;
+ /* Comparisons against 0 with these two should have been optimized out. */
+ gcc_assert (code != LTU && code != GEU);
+ if (flags_valid == FLAGS_VALID_NOOV && (code == GT || code == LE))
+ return UNKNOWN;
+ if (rtx_equal_p (flags_operand1, op0) || rtx_equal_p (flags_operand2, op0))
+ return (FLOAT_MODE_P (mode) ? code
+ : code == GE ? PLUS : code == LT ? MINUS : code);
+ /* See if we are testing whether the high part of a DImode value is
+ positive or negative and we have the full value as a remembered
+ operand. */
+ if (code != GE && code != LT)
+ return UNKNOWN;
+ if (mode == SImode
+ && flags_operand1 != NULL_RTX && GET_MODE (flags_operand1) == DImode
+ && REG_P (flags_operand1) && REG_P (op0)
+ && hard_regno_nregs (REGNO (flags_operand1), DImode) == 2
+ && REGNO (flags_operand1) == REGNO (op0))
+ return code == GE ? PLUS : MINUS;
+ if (mode == SImode
+ && flags_operand2 != NULL_RTX && GET_MODE (flags_operand2) == DImode
+ && REG_P (flags_operand2) && REG_P (op0)
+ && hard_regno_nregs (REGNO (flags_operand2), DImode) == 2
+ && REGNO (flags_operand2) == REGNO (op0))
+ return code == GE ? PLUS : MINUS;
+ return UNKNOWN;
+}
+
+/* Called through CC_STATUS_INIT, which is invoked by final whenever a
+ label is encountered. */
+
+void
+m68k_init_cc ()
+{
+ flags_compare_op0 = flags_compare_op1 = NULL_RTX;
+ flags_operand1 = flags_operand2 = NULL_RTX;
+ flags_valid = FLAGS_VALID_NO;
+}
+
+/* Update flags for a move operation with OPERANDS. Called for move
+ operations where attr_flags_valid returns "set". */
+
+static void
+handle_flags_for_move (rtx *operands)
+{
+ flags_compare_op0 = flags_compare_op1 = NULL_RTX;
+ if (!ADDRESS_REG_P (operands[0]))
+ {
+ flags_valid = FLAGS_VALID_MOVE;
+ flags_operand1 = side_effects_p (operands[0]) ? NULL_RTX : operands[0];
+ if (side_effects_p (operands[1])
+ /* ??? For mem->mem moves, this can discard the source as a
+ valid compare operand. If you assume aligned moves, this
+ is unnecessary, but in theory, we could have an unaligned
+ move overwriting parts of its source. */
+ || modified_in_p (operands[1], current_output_insn))
+ flags_operand2 = NULL_RTX;
+ else
+ flags_operand2 = operands[1];
+ return;
+ }
+ if (flags_operand1 != NULL_RTX
+ && modified_in_p (flags_operand1, current_output_insn))
+ flags_operand1 = NULL_RTX;
+ if (flags_operand2 != NULL_RTX
+ && modified_in_p (flags_operand2, current_output_insn))
+ flags_operand2 = NULL_RTX;
+}
+
+/* Process INSN to remember flag operands if possible. */
+
+static void
+m68k_asm_final_postscan_insn (FILE *, rtx_insn *insn, rtx [], int)
+{
+ enum attr_flags_valid v = get_attr_flags_valid (insn);
+ if (v == FLAGS_VALID_SET)
+ return;
+ /* Comparisons use FLAGS_VALID_SET, so we can be sure we need to clear these
+ now. */
+ flags_compare_op0 = flags_compare_op1 = NULL_RTX;
+
+ if (v == FLAGS_VALID_NO)
+ {
+ flags_operand1 = flags_operand2 = NULL_RTX;
+ return;
+ }
+ else if (v == FLAGS_VALID_UNCHANGED)
+ {
+ if (flags_operand1 != NULL_RTX && modified_in_p (flags_operand1, insn))
+ flags_operand1 = NULL_RTX;
+ if (flags_operand2 != NULL_RTX && modified_in_p (flags_operand2, insn))
+ flags_operand2 = NULL_RTX;
+ return;
+ }
+
+ flags_valid = v;
+ rtx set = single_set (insn);
+ rtx dest = SET_DEST (set);
+ rtx src = SET_SRC (set);
+ if (side_effects_p (dest))
+ dest = NULL_RTX;
+
+ switch (v)
+ {
+ case FLAGS_VALID_YES:
+ case FLAGS_VALID_NOOV:
+ flags_operand1 = dest;
+ flags_operand2 = NULL_RTX;
+ break;
+ case FLAGS_VALID_MOVE:
+ /* fmoves to memory or data registers do not set the condition
+ codes. Normal moves _do_ set the condition codes, but not in
+ a way that is appropriate for comparison with 0, because -0.0
+ would be treated as a negative nonzero number. Note that it
+ isn't appropriate to conditionalize this restriction on
+ HONOR_SIGNED_ZEROS because that macro merely indicates whether
+ we care about the difference between -0.0 and +0.0. */
+ if (dest != NULL_RTX
+ && !FP_REG_P (dest)
+ && (FP_REG_P (src)
+ || GET_CODE (src) == FIX
+ || FLOAT_MODE_P (GET_MODE (dest))))
+ flags_operand1 = flags_operand2 = NULL_RTX;
+ else
+ {
+ flags_operand1 = dest;
+ if (GET_MODE (src) != VOIDmode && !side_effects_p (src)
+ && !modified_in_p (src, insn))
+ flags_operand2 = src;
+ else
+ flags_operand2 = NULL_RTX;
+ }
+ break;
+ default:
+ gcc_unreachable ();
+ }
+ return;
+}
-
/* Output a dbCC; jCC sequence. Note we do not handle the
- floating point version of this sequence (Fdbcc). We also
- do not handle alternative conditions when CC_NO_OVERFLOW is
- set. It is assumed that valid_dbcc_comparison_p and flags_in_68881 will
- kick those out before we get here. */
+ floating point version of this sequence (Fdbcc).
+ OPERANDS are as in the two peepholes. CODE is the code
+ returned by m68k_output_branch_<mode>. */
void
-output_dbcc_and_branch (rtx *operands)
+output_dbcc_and_branch (rtx *operands, rtx_code code)
{
- switch (GET_CODE (operands[3]))
+ switch (code)
{
case EQ:
output_asm_insn ("dbeq %0,%l1\n\tjeq %l2", operands);
output_asm_insn ("dbls %0,%l1\n\tjls %l2", operands);
break;
+ case PLUS:
+ output_asm_insn ("dbpl %0,%l1\n\tjle %l2", operands);
+ break;
+
+ case MINUS:
+ output_asm_insn ("dbmi %0,%l1\n\tjle %l2", operands);
+ break;
+
default:
gcc_unreachable ();
}
return "";
}
-const char *
-output_btst (rtx *operands, rtx countop, rtx dataop, rtx_insn *insn, int signpos)
+rtx_code
+m68k_output_btst (rtx countop, rtx dataop, rtx_code code, int signpos)
{
- operands[0] = countop;
- operands[1] = dataop;
+ rtx ops[2];
+ ops[0] = countop;
+ ops[1] = dataop;
if (GET_CODE (countop) == CONST_INT)
{
{
int offset = (count & ~signpos) / 8;
count = count & signpos;
- operands[1] = dataop = adjust_address (dataop, QImode, offset);
+ ops[1] = dataop = adjust_address (dataop, QImode, offset);
+ }
+
+ if (code == EQ || code == NE)
+ {
+ if (count == 31)
+ {
+ output_asm_insn ("tst%.l %1", ops);
+ return code == EQ ? PLUS : MINUS;
+ }
+ if (count == 15)
+ {
+ output_asm_insn ("tst%.w %1", ops);
+ return code == EQ ? PLUS : MINUS;
+ }
+ if (count == 7)
+ {
+ output_asm_insn ("tst%.b %1", ops);
+ return code == EQ ? PLUS : MINUS;
+ }
}
- if (count == signpos)
- cc_status.flags = CC_NOT_POSITIVE | CC_Z_IN_NOT_N;
- else
- cc_status.flags = CC_NOT_NEGATIVE | CC_Z_IN_NOT_N;
-
- /* These three statements used to use next_insns_test_no...
- but it appears that this should do the same job. */
- if (count == 31
- && next_insn_tests_no_inequality (insn))
- return "tst%.l %1";
- if (count == 15
- && next_insn_tests_no_inequality (insn))
- return "tst%.w %1";
- if (count == 7
- && next_insn_tests_no_inequality (insn))
- return "tst%.b %1";
/* Try to use `movew to ccr' followed by the appropriate branch insn.
On some m68k variants unfortunately that's slower than btst.
On 68000 and higher, that should also work for all HImode operands. */
if (TUNE_CPU32 || TARGET_COLDFIRE || optimize_size)
{
- if (count == 3 && DATA_REG_P (operands[1])
- && next_insn_tests_no_inequality (insn))
+ if (count == 3 && DATA_REG_P (ops[1]) && (code == EQ || code == NE))
{
- cc_status.flags = CC_NOT_NEGATIVE | CC_Z_IN_NOT_N | CC_NO_OVERFLOW;
- return "move%.w %1,%%ccr";
+ output_asm_insn ("move%.w %1,%%ccr", ops);
+ return code == EQ ? PLUS : MINUS;
}
- if (count == 2 && DATA_REG_P (operands[1])
- && next_insn_tests_no_inequality (insn))
+ if (count == 2 && DATA_REG_P (ops[1]) && (code == EQ || code == NE))
{
- cc_status.flags = CC_NOT_NEGATIVE | CC_INVERTED | CC_NO_OVERFLOW;
- return "move%.w %1,%%ccr";
+ output_asm_insn ("move%.w %1,%%ccr", ops);
+ return code == EQ ? NE : EQ;
}
/* count == 1 followed by bvc/bvs and
count == 0 followed by bcc/bcs are also possible, but need
cc_status.flags = CC_NOT_NEGATIVE;
}
- return "btst %0,%1";
+ output_asm_insn ("btst %0,%1", ops);
+ return code;
+}
+
+/* Output a bftst instruction for a zero_extract with ZXOP0, ZXOP1 and ZXOP2
+ operands. CODE is the code of the comparison, and we return the code to
+ be actually used in the jump. */
+
+rtx_code
+m68k_output_bftst (rtx zxop0, rtx zxop1, rtx zxop2, rtx_code code)
+{
+ if (zxop1 == const1_rtx && GET_CODE (zxop2) == CONST_INT)
+ {
+ int width = GET_CODE (zxop0) == REG ? 31 : 7;
+ /* Pass 1000 as SIGNPOS argument so that btst will
+ not think we are testing the sign bit for an `and'
+ and assume that nonzero implies a negative result. */
+ return m68k_output_btst (GEN_INT (width - INTVAL (zxop2)), zxop0, code, 1000);
+ }
+ rtx ops[3] = { zxop0, zxop1, zxop2 };
+ output_asm_insn ("bftst %0{%b2:%b1}", ops);
+ return code;
}
\f
/* Return true if X is a legitimate base register. STRICT_P says
case CONST_DOUBLE:
/* Make 0.0 cheaper than other floating constants to
encourage creating tstsf and tstdf insns. */
- if (outer_code == COMPARE
+ if ((GET_RTX_CLASS (outer_code) == RTX_COMPARE
+ || GET_RTX_CLASS (outer_code) == RTX_COMM_COMPARE)
&& (x == CONST0_RTX (SFmode) || x == CONST0_RTX (DFmode)))
*total = 4;
else
return true;
case ZERO_EXTRACT:
- if (outer_code == COMPARE)
+ if (GET_RTX_CLASS (outer_code) == RTX_COMPARE
+ || GET_RTX_CLASS (outer_code) == RTX_COMM_COMPARE)
*total = 0;
return false;
const char *
output_move_simode (rtx *operands)
{
+ handle_flags_for_move (operands);
+
if (GET_CODE (operands[1]) == CONST_INT)
return output_move_simode_const (operands);
else if ((GET_CODE (operands[1]) == SYMBOL_REF
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])
return "move%.w %1,%0";
}
else if (CONSTANT_P (operands[1]))
- return "move%.l %1,%0";
+ gcc_unreachable ();
return "move%.w %1,%0";
}
const char *
output_move_qimode (rtx *operands)
{
+ handle_flags_for_move (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
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]))
- return "move%.w %1,%0";
+ {
+ if (ADDRESS_REG_P (operands[1]))
+ CC_STATUS_INIT;
+ return "move%.w %1,%0";
+ }
return "move%.b %1,%0";
}
}
return "add%.l %2,%0";
}
-\f
-/* Store in cc_status the expressions that the condition codes will
- describe after execution of an instruction whose pattern is EXP.
- Do not alter them if the instruction would not alter the cc's. */
-
-/* On the 68000, all the insns to store in an address register fail to
- set the cc's. However, in some cases these instructions can make it
- possibly invalid to use the saved cc's. In those cases we clear out
- some or all of the saved cc's so they won't be used. */
-void
-notice_update_cc (rtx exp, rtx insn)
+/* Emit a comparison between OP0 and OP1. Return true iff the comparison
+ was reversed. SC1 is an SImode scratch reg, and SC2 a DImode scratch reg,
+ as needed. CODE is the code of the comparison, we return it unchanged or
+ swapped, as necessary. */
+rtx_code
+m68k_output_compare_di (rtx op0, rtx op1, rtx sc1, rtx sc2, rtx_insn *insn,
+ rtx_code code)
{
- if (GET_CODE (exp) == SET)
+ rtx ops[4];
+ ops[0] = op0;
+ ops[1] = op1;
+ ops[2] = sc1;
+ ops[3] = sc2;
+ if (op1 == const0_rtx)
{
- if (GET_CODE (SET_SRC (exp)) == CALL)
- CC_STATUS_INIT;
- else if (ADDRESS_REG_P (SET_DEST (exp)))
+ if (!REG_P (op0) || ADDRESS_REG_P (op0))
{
- if (cc_status.value1 && modified_in_p (cc_status.value1, insn))
- cc_status.value1 = 0;
- if (cc_status.value2 && modified_in_p (cc_status.value2, insn))
- cc_status.value2 = 0;
+ rtx xoperands[2];
+
+ xoperands[0] = sc2;
+ xoperands[1] = op0;
+ output_move_double (xoperands);
+ output_asm_insn ("neg%.l %R0\n\tnegx%.l %0", xoperands);
+ return swap_condition (code);
}
- /* fmoves to memory or data registers do not set the condition
- codes. Normal moves _do_ set the condition codes, but not in
- a way that is appropriate for comparison with 0, because -0.0
- would be treated as a negative nonzero number. Note that it
- isn't appropriate to conditionalize this restriction on
- HONOR_SIGNED_ZEROS because that macro merely indicates whether
- we care about the difference between -0.0 and +0.0. */
- else if (!FP_REG_P (SET_DEST (exp))
- && SET_DEST (exp) != cc0_rtx
- && (FP_REG_P (SET_SRC (exp))
- || GET_CODE (SET_SRC (exp)) == FIX
- || FLOAT_MODE_P (GET_MODE (SET_DEST (exp)))))
- CC_STATUS_INIT;
- /* A pair of move insns doesn't produce a useful overall cc. */
- else if (!FP_REG_P (SET_DEST (exp))
- && !FP_REG_P (SET_SRC (exp))
- && GET_MODE_SIZE (GET_MODE (SET_SRC (exp))) > 4
- && (GET_CODE (SET_SRC (exp)) == REG
- || GET_CODE (SET_SRC (exp)) == MEM
- || GET_CODE (SET_SRC (exp)) == CONST_DOUBLE))
- CC_STATUS_INIT;
- else if (SET_DEST (exp) != pc_rtx)
+ if (find_reg_note (insn, REG_DEAD, op0))
{
- cc_status.flags = 0;
- cc_status.value1 = SET_DEST (exp);
- cc_status.value2 = SET_SRC (exp);
+ output_asm_insn ("neg%.l %R0\n\tnegx%.l %0", ops);
+ return swap_condition (code);
}
- }
- else if (GET_CODE (exp) == PARALLEL
- && GET_CODE (XVECEXP (exp, 0, 0)) == SET)
- {
- rtx dest = SET_DEST (XVECEXP (exp, 0, 0));
- rtx src = SET_SRC (XVECEXP (exp, 0, 0));
-
- if (ADDRESS_REG_P (dest))
- CC_STATUS_INIT;
- else if (dest != pc_rtx)
+ else
{
- cc_status.flags = 0;
- cc_status.value1 = dest;
- cc_status.value2 = src;
+ /* 'sub' clears %1, and also clears the X cc bit.
+ 'tst' sets the Z cc bit according to the low part of the DImode
+ operand.
+ 'subx %1' (i.e. subx #0) acts as a (non-existent) tstx on the high
+ part. */
+ output_asm_insn ("sub%.l %2,%2\n\ttst%.l %R0\n\tsubx%.l %2,%0", ops);
+ return code;
}
}
+
+ if (rtx_equal_p (sc2, op0))
+ {
+ output_asm_insn ("sub%.l %R1,%R3\n\tsubx%.l %1,%3", ops);
+ return code;
+ }
else
+ {
+ output_asm_insn ("sub%.l %R0,%R3\n\tsubx%.l %0,%3", ops);
+ return swap_condition (code);
+ }
+}
+
+static void
+remember_compare_flags (rtx op0, rtx op1)
+{
+ if (side_effects_p (op0) || side_effects_p (op1))
CC_STATUS_INIT;
- if (cc_status.value2 != 0
- && ADDRESS_REG_P (cc_status.value2)
- && GET_MODE (cc_status.value2) == QImode)
- CC_STATUS_INIT;
- if (cc_status.value2 != 0)
- switch (GET_CODE (cc_status.value2))
- {
- case ASHIFT: case ASHIFTRT: case LSHIFTRT:
- case ROTATE: case ROTATERT:
- /* These instructions always clear the overflow bit, and set
- the carry to the bit shifted out. */
- cc_status.flags |= CC_OVERFLOW_UNUSABLE | CC_NO_CARRY;
- break;
+ else
+ {
+ flags_compare_op0 = op0;
+ flags_compare_op1 = op1;
+ flags_operand1 = flags_operand2 = NULL_RTX;
+ flags_valid = FLAGS_VALID_SET;
+ }
+}
- case PLUS: case MINUS: case MULT:
- case DIV: case UDIV: case MOD: case UMOD: case NEG:
- if (GET_MODE (cc_status.value2) != VOIDmode)
- cc_status.flags |= CC_NO_OVERFLOW;
- break;
- case ZERO_EXTEND:
- /* (SET r1 (ZERO_EXTEND r2)) on this machine
- ends with a move insn moving r2 in r2's mode.
- Thus, the cc's are set for r2.
- This can set N bit spuriously. */
- cc_status.flags |= CC_NOT_NEGATIVE;
+/* Emit a comparison between OP0 and OP1. CODE is the code of the
+ comparison. It is returned, potentially modified if necessary. */
+rtx_code
+m68k_output_compare_si (rtx op0, rtx op1, rtx_code code)
+{
+ rtx_code tmp = m68k_find_flags_value (op0, op1, code);
+ if (tmp != UNKNOWN)
+ return tmp;
- default:
- break;
- }
- if (cc_status.value1 && GET_CODE (cc_status.value1) == REG
- && cc_status.value2
- && reg_overlap_mentioned_p (cc_status.value1, cc_status.value2))
- cc_status.value2 = 0;
- /* Check for PRE_DEC in dest modifying a register used in src. */
- if (cc_status.value1 && GET_CODE (cc_status.value1) == MEM
- && GET_CODE (XEXP (cc_status.value1, 0)) == PRE_DEC
- && cc_status.value2
- && reg_overlap_mentioned_p (XEXP (XEXP (cc_status.value1, 0), 0),
- cc_status.value2))
- cc_status.value2 = 0;
- if (((cc_status.value1 && FP_REG_P (cc_status.value1))
- || (cc_status.value2 && FP_REG_P (cc_status.value2))))
- cc_status.flags = CC_IN_68881;
- if (cc_status.value2 && GET_CODE (cc_status.value2) == COMPARE
- && GET_MODE_CLASS (GET_MODE (XEXP (cc_status.value2, 0))) == MODE_FLOAT)
- {
- cc_status.flags = CC_IN_68881;
- if (!FP_REG_P (XEXP (cc_status.value2, 0))
- && FP_REG_P (XEXP (cc_status.value2, 1)))
- cc_status.flags |= CC_REVERSED;
+ remember_compare_flags (op0, op1);
+
+ rtx ops[2];
+ ops[0] = op0;
+ ops[1] = op1;
+ if (op1 == const0_rtx && (TARGET_68020 || TARGET_COLDFIRE || !ADDRESS_REG_P (op0)))
+ output_asm_insn ("tst%.l %0", ops);
+ else if (GET_CODE (op0) == MEM && GET_CODE (op1) == MEM)
+ output_asm_insn ("cmpm%.l %1,%0", ops);
+ else if (REG_P (op1)
+ || (!REG_P (op0) && GET_CODE (op0) != MEM))
+ {
+ output_asm_insn ("cmp%.l %d0,%d1", ops);
+ std::swap (flags_compare_op0, flags_compare_op1);
+ return swap_condition (code);
+ }
+ else if (!TARGET_COLDFIRE
+ && ADDRESS_REG_P (op0)
+ && GET_CODE (op1) == CONST_INT
+ && INTVAL (op1) < 0x8000
+ && INTVAL (op1) >= -0x8000)
+ output_asm_insn ("cmp%.w %1,%0", ops);
+ else
+ output_asm_insn ("cmp%.l %d1,%d0", ops);
+ return code;
+}
+
+/* Emit a comparison between OP0 and OP1. CODE is the code of the
+ comparison. It is returned, potentially modified if necessary. */
+rtx_code
+m68k_output_compare_hi (rtx op0, rtx op1, rtx_code code)
+{
+ rtx_code tmp = m68k_find_flags_value (op0, op1, code);
+ if (tmp != UNKNOWN)
+ return tmp;
+
+ remember_compare_flags (op0, op1);
+
+ rtx ops[2];
+ ops[0] = op0;
+ ops[1] = op1;
+ if (op1 == const0_rtx)
+ output_asm_insn ("tst%.w %d0", ops);
+ else if (GET_CODE (op0) == MEM && GET_CODE (op1) == MEM)
+ output_asm_insn ("cmpm%.w %1,%0", ops);
+ else if ((REG_P (op1) && !ADDRESS_REG_P (op1))
+ || (!REG_P (op0) && GET_CODE (op0) != MEM))
+ {
+ output_asm_insn ("cmp%.w %d0,%d1", ops);
+ std::swap (flags_compare_op0, flags_compare_op1);
+ return swap_condition (code);
+ }
+ else
+ output_asm_insn ("cmp%.w %d1,%d0", ops);
+ return code;
+}
+
+/* Emit a comparison between OP0 and OP1. CODE is the code of the
+ comparison. It is returned, potentially modified if necessary. */
+rtx_code
+m68k_output_compare_qi (rtx op0, rtx op1, rtx_code code)
+{
+ rtx_code tmp = m68k_find_flags_value (op0, op1, code);
+ if (tmp != UNKNOWN)
+ return tmp;
+
+ remember_compare_flags (op0, op1);
+
+ rtx ops[2];
+ ops[0] = op0;
+ ops[1] = op1;
+ if (op1 == const0_rtx)
+ output_asm_insn ("tst%.b %d0", ops);
+ else if (GET_CODE (op0) == MEM && GET_CODE (op1) == MEM)
+ output_asm_insn ("cmpm%.b %1,%0", ops);
+ else if (REG_P (op1) || (!REG_P (op0) && GET_CODE (op0) != MEM))
+ {
+ output_asm_insn ("cmp%.b %d0,%d1", ops);
+ std::swap (flags_compare_op0, flags_compare_op1);
+ return swap_condition (code);
+ }
+ else
+ output_asm_insn ("cmp%.b %d1,%d0", ops);
+ return code;
+}
+
+/* Emit a comparison between OP0 and OP1. CODE is the code of the
+ comparison. It is returned, potentially modified if necessary. */
+rtx_code
+m68k_output_compare_fp (rtx op0, rtx op1, rtx_code code)
+{
+ rtx_code tmp = m68k_find_flags_value (op0, op1, code);
+ if (tmp != UNKNOWN)
+ return tmp;
+
+ rtx ops[2];
+ ops[0] = op0;
+ ops[1] = op1;
+
+ remember_compare_flags (op0, op1);
+
+ machine_mode mode = GET_MODE (op0);
+ std::string prec = mode == SFmode ? "s" : mode == DFmode ? "d" : "x";
+
+ if (op1 == CONST0_RTX (GET_MODE (op0)))
+ {
+ if (FP_REG_P (op0))
+ output_asm_insn ("ftst%.x %0", ops);
+ else
+ output_asm_insn (("ftst%." + prec + " %0").c_str (), ops);
+ return code;
+ }
+
+ switch (which_alternative)
+ {
+ case 0:
+ output_asm_insn ("fcmp%.x %1,%0", ops);
+ break;
+ case 1:
+ output_asm_insn (("fcmp%." + prec + " %f1,%0").c_str (), ops);
+ break;
+ case 2:
+ output_asm_insn (("fcmp%." + prec + " %0,%f1").c_str (), ops);
+ std::swap (flags_compare_op0, flags_compare_op1);
+ return swap_condition (code);
+ case 3:
+ /* This is the ftst case, handled earlier. */
+ gcc_unreachable ();
+ }
+ return code;
+}
+
+/* Return an output template for a branch with CODE. */
+const char *
+m68k_output_branch_integer (rtx_code code)
+{
+ switch (code)
+ {
+ case EQ:
+ return "jeq %l3";
+ case NE:
+ return "jne %l3";
+ case GT:
+ return "jgt %l3";
+ case GTU:
+ return "jhi %l3";
+ case LT:
+ return "jlt %l3";
+ case LTU:
+ return "jcs %l3";
+ case GE:
+ return "jge %l3";
+ case GEU:
+ return "jcc %l3";
+ case LE:
+ return "jle %l3";
+ case LEU:
+ return "jls %l3";
+ case PLUS:
+ return "jpl %l3";
+ case MINUS:
+ return "jmi %l3";
+ default:
+ gcc_unreachable ();
+ }
+}
+
+/* Return an output template for a reversed branch with CODE. */
+const char *
+m68k_output_branch_integer_rev (rtx_code code)
+{
+ switch (code)
+ {
+ case EQ:
+ return "jne %l3";
+ case NE:
+ return "jeq %l3";
+ case GT:
+ return "jle %l3";
+ case GTU:
+ return "jls %l3";
+ case LT:
+ return "jge %l3";
+ case LTU:
+ return "jcc %l3";
+ case GE:
+ return "jlt %l3";
+ case GEU:
+ return "jcs %l3";
+ case LE:
+ return "jgt %l3";
+ case LEU:
+ return "jhi %l3";
+ case PLUS:
+ return "jmi %l3";
+ case MINUS:
+ return "jpl %l3";
+ default:
+ gcc_unreachable ();
+ }
+}
+
+/* Return an output template for a scc instruction with CODE. */
+const char *
+m68k_output_scc (rtx_code code)
+{
+ switch (code)
+ {
+ case EQ:
+ return "seq %0";
+ case NE:
+ return "sne %0";
+ case GT:
+ return "sgt %0";
+ case GTU:
+ return "shi %0";
+ case LT:
+ return "slt %0";
+ case LTU:
+ return "scs %0";
+ case GE:
+ return "sge %0";
+ case GEU:
+ return "scc %0";
+ case LE:
+ return "sle %0";
+ case LEU:
+ return "sls %0";
+ case PLUS:
+ return "spl %0";
+ case MINUS:
+ return "smi %0";
+ default:
+ gcc_unreachable ();
+ }
+}
+
+/* Return an output template for a floating point branch
+ instruction with CODE. */
+const char *
+m68k_output_branch_float (rtx_code code)
+{
+ switch (code)
+ {
+ case EQ:
+ return "fjeq %l3";
+ case NE:
+ return "fjne %l3";
+ case GT:
+ return "fjgt %l3";
+ case LT:
+ return "fjlt %l3";
+ case GE:
+ return "fjge %l3";
+ case LE:
+ return "fjle %l3";
+ case ORDERED:
+ return "fjor %l3";
+ case UNORDERED:
+ return "fjun %l3";
+ case UNEQ:
+ return "fjueq %l3";
+ case UNGE:
+ return "fjuge %l3";
+ case UNGT:
+ return "fjugt %l3";
+ case UNLE:
+ return "fjule %l3";
+ case UNLT:
+ return "fjult %l3";
+ case LTGT:
+ return "fjogl %l3";
+ default:
+ gcc_unreachable ();
+ }
+}
+
+/* Return an output template for a reversed floating point branch
+ instruction with CODE. */
+const char *
+m68k_output_branch_float_rev (rtx_code code)
+{
+ switch (code)
+ {
+ case EQ:
+ return "fjne %l3";
+ case NE:
+ return "fjeq %l3";
+ case GT:
+ return "fjngt %l3";
+ case LT:
+ return "fjnlt %l3";
+ case GE:
+ return "fjnge %l3";
+ case LE:
+ return "fjnle %l3";
+ case ORDERED:
+ return "fjun %l3";
+ case UNORDERED:
+ return "fjor %l3";
+ case UNEQ:
+ return "fjogl %l3";
+ case UNGE:
+ return "fjolt %l3";
+ case UNGT:
+ return "fjole %l3";
+ case UNLE:
+ return "fjogt %l3";
+ case UNLT:
+ return "fjoge %l3";
+ case LTGT:
+ return "fjueq %l3";
+ default:
+ gcc_unreachable ();
+ }
+}
+
+/* Return an output template for a floating point scc
+ instruction with CODE. */
+const char *
+m68k_output_scc_float (rtx_code code)
+{
+ switch (code)
+ {
+ case EQ:
+ return "fseq %0";
+ case NE:
+ return "fsne %0";
+ case GT:
+ return "fsgt %0";
+ case GTU:
+ return "fshi %0";
+ case LT:
+ return "fslt %0";
+ case GE:
+ return "fsge %0";
+ case LE:
+ return "fsle %0";
+ case ORDERED:
+ return "fsor %0";
+ case UNORDERED:
+ return "fsun %0";
+ case UNEQ:
+ return "fsueq %0";
+ case UNGE:
+ return "fsuge %0";
+ case UNGT:
+ return "fsugt %0";
+ case UNLE:
+ return "fsule %0";
+ case UNLT:
+ return "fsult %0";
+ case LTGT:
+ return "fsogl %0";
+ default:
+ gcc_unreachable ();
}
}
\f
output_andsi3 (rtx *operands)
{
int logval;
+ CC_STATUS_INIT;
if (GET_CODE (operands[2]) == CONST_INT
&& (INTVAL (operands[2]) | 0xffff) == -1
&& (DATA_REG_P (operands[0])
if (GET_CODE (operands[0]) != REG)
operands[0] = adjust_address (operands[0], HImode, 2);
operands[2] = GEN_INT (INTVAL (operands[2]) & 0xffff);
- /* Do not delete a following tstl %0 insn; that would be incorrect. */
- CC_STATUS_INIT;
if (operands[2] == const0_rtx)
return "clr%.w %0";
return "and%.w %2,%0";
operands[0] = adjust_address (operands[0], SImode, 3 - (logval / 8));
operands[1] = GEN_INT (logval % 8);
}
- /* This does not set condition codes in a standard way. */
- CC_STATUS_INIT;
return "bclr %1,%0";
}
+ /* Only a standard logical operation on the whole word sets the
+ condition codes in a way we can use. */
+ if (!side_effects_p (operands[0]))
+ flags_operand1 = operands[0];
+ flags_valid = FLAGS_VALID_YES;
return "and%.l %2,%0";
}
output_iorsi3 (rtx *operands)
{
register int logval;
+ CC_STATUS_INIT;
if (GET_CODE (operands[2]) == CONST_INT
&& INTVAL (operands[2]) >> 16 == 0
&& (DATA_REG_P (operands[0])
{
if (GET_CODE (operands[0]) != REG)
operands[0] = adjust_address (operands[0], HImode, 2);
- /* Do not delete a following tstl %0 insn; that would be incorrect. */
- CC_STATUS_INIT;
if (INTVAL (operands[2]) == 0xffff)
return "mov%.w %2,%0";
return "or%.w %2,%0";
operands[0] = adjust_address (operands[0], SImode, 3 - (logval / 8));
operands[1] = GEN_INT (logval % 8);
}
- CC_STATUS_INIT;
return "bset %1,%0";
}
+ /* Only a standard logical operation on the whole word sets the
+ condition codes in a way we can use. */
+ if (!side_effects_p (operands[0]))
+ flags_operand1 = operands[0];
+ flags_valid = FLAGS_VALID_YES;
return "or%.l %2,%0";
}
output_xorsi3 (rtx *operands)
{
register int logval;
+ CC_STATUS_INIT;
if (GET_CODE (operands[2]) == CONST_INT
&& INTVAL (operands[2]) >> 16 == 0
&& (offsettable_memref_p (operands[0]) || DATA_REG_P (operands[0]))
{
if (! DATA_REG_P (operands[0]))
operands[0] = adjust_address (operands[0], HImode, 2);
- /* Do not delete a following tstl %0 insn; that would be incorrect. */
- CC_STATUS_INIT;
if (INTVAL (operands[2]) == 0xffff)
return "not%.w %0";
return "eor%.w %2,%0";
operands[0] = adjust_address (operands[0], SImode, 3 - (logval / 8));
operands[1] = GEN_INT (logval % 8);
}
- CC_STATUS_INIT;
return "bchg %1,%0";
}
+ /* Only a standard logical operation on the whole word sets the
+ condition codes in a way we can use. */
+ if (!side_effects_p (operands[0]))
+ flags_operand1 = operands[0];
+ flags_valid = FLAGS_VALID_YES;
return "eor%.l %2,%0";
}
;; Alternative is OK for ColdFire.
(define_attr "ok_for_coldfire" "yes,no" (const_string "yes"))
+;; Instruction sets flags predictably to allow a following comparison to be
+;; elided.
+;; "no" means we should clear all flag state. "yes" means the destination
+;; register is valid. "noov" is similar but does not allow tests that rely
+;; on the overflow flag. "unchanged" means the instruction does not set the
+;; flags (but we should still verify none of the remembered operands are
+;; clobbered). "move" is a special case for which we remember both the
+;; destination and the source. "set" is another special case where the
+;; instruction pattern already performs the update and no more work is
+;; required in postscan_insn.
+(define_attr "flags_valid" "no,yes,set,noov,move,unchanged" (const_string "no"))
+
;; Define 'enabled' attribute.
(define_attr "enabled" ""
(cond [(and (match_test "TARGET_COLDFIRE")
DONE;
})
\f
-;; We don't want to allow a constant operand for test insns because
-;; (set (cc0) (const_int foo)) has no mode information. Such insns will
-;; be folded while optimizing anyway.
-
-(define_insn "tstdi"
- [(set (cc0)
- (compare (match_operand:DI 0 "nonimmediate_operand" "am,d")
- (const_int 0)))
- (clobber (match_scratch:SI 1 "=X,d"))
- (clobber (match_scratch:DI 2 "=d,X"))]
+;; Compare instructions, combined with jumps or scc operations.
+
+(define_insn "beq0_di"
+ [(set (pc)
+ (if_then_else (eq (match_operand:DI 0 "general_operand" "d*a,o,<>")
+ (const_int 0))
+ (label_ref (match_operand 1 "" ",,"))
+ (pc)))
+ (clobber (match_scratch:SI 2 "=d,&d,d"))]
""
{
- if (which_alternative == 0)
- {
- rtx xoperands[2];
-
- xoperands[0] = operands[2];
- xoperands[1] = operands[0];
- output_move_double (xoperands);
- cc_status.flags |= CC_REVERSED; /*|*/
- return "neg%.l %R2\;negx%.l %2";
- }
- if (find_reg_note (insn, REG_DEAD, operands[0]))
+ rtx_code code = m68k_find_flags_value (operands[0], const0_rtx, EQ);
+ if (code == EQ)
+ return "jeq %l1";
+ if (which_alternative == 2)
+ return "move%.l %0,%2\;or%.l %0,%2\;jeq %l1";
+ if (GET_CODE (operands[0]) == REG)
+ operands[3] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1);
+ else
+ operands[3] = adjust_address (operands[0], SImode, 4);
+ if (! ADDRESS_REG_P (operands[0]))
{
- cc_status.flags |= CC_REVERSED; /*|*/
- return "neg%.l %R0\;negx%.l %0";
+ if (reg_overlap_mentioned_p (operands[2], operands[0]))
+ {
+ if (reg_overlap_mentioned_p (operands[2], operands[3]))
+ return "or%.l %0,%2\;jeq %l1";
+ else
+ return "or%.l %3,%2\;jeq %l1";
+ }
+ return "move%.l %0,%2\;or%.l %3,%2\;jeq %l1";
}
+ operands[4] = gen_label_rtx();
+ if (TARGET_68020 || TARGET_COLDFIRE)
+ output_asm_insn ("tst%.l %0\;jne %l4\;tst%.l %3\;jeq %l1", operands);
else
- /*
- 'sub' clears %1, and also clears the X cc bit
- 'tst' sets the Z cc bit according to the low part of the DImode operand
- 'subx %1' (i.e. subx #0) acts as a (non-existent) tstx on the high part.
- */
- return "sub%.l %1,%1\;tst%.l %R0\;subx%.l %1,%0";
-})
-
-;; If you think that the 68020 does not support tstl a0,
-;; reread page B-167 of the 68020 manual more carefully.
-(define_insn "*tstsi_internal_68020_cf"
- [(set (cc0)
- (compare (match_operand:SI 0 "nonimmediate_operand" "rm")
- (const_int 0)))]
- "TARGET_68020 || TARGET_COLDFIRE"
- "tst%.l %0"
- [(set_attr "type" "tst_l")])
-
-;; On an address reg, cmpw may replace cmpl.
-(define_insn "*tstsi_internal"
- [(set (cc0)
- (compare (match_operand:SI 0 "nonimmediate_operand" "dm,r")
- (const_int 0)))]
- "!(TARGET_68020 || TARGET_COLDFIRE)"
- "@
- tst%.l %0
- cmp%.w #0,%0"
- [(set_attr "type" "tst_l,cmp")])
-
-;; This can't use an address register, because comparisons
-;; with address registers as second operand always test the whole word.
-(define_insn "*tsthi_internal"
- [(set (cc0)
- (compare (match_operand:HI 0 "nonimmediate_operand" "dm")
- (const_int 0)))]
- ""
- "tst%.w %0"
- [(set_attr "type" "tst")])
-
-(define_insn "*tstqi_internal"
- [(set (cc0)
- (compare (match_operand:QI 0 "nonimmediate_operand" "dm")
- (const_int 0)))]
- ""
- "tst%.b %0"
- [(set_attr "type" "tst")])
-
-(define_insn "tst<mode>_68881"
- [(set (cc0)
- (compare (match_operand:FP 0 "general_operand" "f<FP:dreg>m")
- (match_operand:FP 1 "const0_operand" "H")))]
- "TARGET_68881"
-{
- cc_status.flags = CC_IN_68881;
- if (FP_REG_P (operands[0]))
- return "ftst%.x %0";
- return "ftst%.<FP:prec> %0";
-}
- [(set_attr "type" "ftst")])
-
-(define_insn "tst<mode>_cf"
- [(set (cc0)
- (compare (match_operand:FP 0 "general_operand" "f<FP:dreg><Q>U")
- (match_operand:FP 1 "const0_operand" "H")))]
- "TARGET_COLDFIRE_FPU"
-{
- cc_status.flags = CC_IN_68881;
- if (FP_REG_P (operands[0]))
- return "ftst%.d %0";
- return "ftst%.<FP:prec> %0";
-}
- [(set_attr "type" "ftst")])
-
-\f
-;; compare instructions.
+ output_asm_insn ("cmp%.w #0,%0\;jne %l4\;cmp%.w #0,%3\;jeq %l1", operands);
+ (*targetm.asm_out.internal_label) (asm_out_file, "L",
+ CODE_LABEL_NUMBER (operands[4]));
+ return "";
+})
-(define_insn "*cmpdi_internal"
- [(set (cc0)
- (compare (match_operand:DI 1 "nonimmediate_operand" "0,d")
- (match_operand:DI 2 "general_operand" "d,0")))
- (clobber (match_scratch:DI 0 "=d,d"))]
+(define_insn "bne0_di"
+ [(set (pc)
+ (if_then_else (ne (match_operand:DI 0 "general_operand" "d,o,*a")
+ (const_int 0))
+ (label_ref (match_operand 1 "" ",,"))
+ (pc)))
+ (clobber (match_scratch:SI 2 "=d,&d,X"))]
""
{
- if (rtx_equal_p (operands[0], operands[1]))
- return "sub%.l %R2,%R0\;subx%.l %2,%0";
+ rtx_code code = m68k_find_flags_value (operands[0], const0_rtx, NE);
+ if (code == NE)
+ return "jne %l1";
+ if (GET_CODE (operands[0]) == REG)
+ operands[3] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1);
else
+ operands[3] = adjust_address (operands[0], SImode, 4);
+ if (!ADDRESS_REG_P (operands[0]))
{
- cc_status.flags |= CC_REVERSED; /*|*/
- return "sub%.l %R1,%R0\;subx%.l %1,%0";
+ if (reg_overlap_mentioned_p (operands[2], operands[0]))
+ {
+ if (reg_overlap_mentioned_p (operands[2], operands[3]))
+ return "or%.l %0,%2\;jne %l1";
+ else
+ return "or%.l %3,%2\;jne %l1";
+ }
+ return "move%.l %0,%2\;or%.l %3,%2\;jne %l1";
}
+ if (TARGET_68020 || TARGET_COLDFIRE)
+ return "tst%.l %0\;jne %l1\;tst%.l %3\;jne %l1";
+ else
+ return "cmp%.w #0,%0\;jne %l1\;cmp%.w #0,%3\;jne %l1";
})
-(define_insn "cmpdi"
- [(set (cc0)
- (compare (match_operand:DI 0 "nonimmediate_operand")
- (match_operand:DI 1 "general_operand")))
- (clobber (match_scratch:DI 2))]
+(define_insn "cbranchdi4_insn"
+ [(set (pc)
+ (if_then_else (match_operator 1 "ordered_comparison_operator"
+ [(match_operand:DI 2 "nonimmediate_operand" "0,d,am,d")
+ (match_operand:DI 3 "general_operand" "d,0,C0,C0")])
+ (label_ref (match_operand 4 ""))
+ (pc)))
+ (clobber (match_scratch:DI 0 "=d,d,d,X"))
+ (clobber (match_scratch:SI 5 "=X,X,X,d"))]
""
- "")
-
+{
+ rtx_code code = GET_CODE (operands[1]);
+ code = m68k_output_compare_di (operands[2], operands[3], operands[5], operands[0], insn, code);
+ operands[3] = operands[4];
+ return m68k_output_branch_integer (code);
+})
(define_expand "cbranchdi4"
- [(set (pc)
- (if_then_else (match_operator 0 "ordered_comparison_operator"
- [(match_operand:DI 1 "nonimmediate_operand")
- (match_operand:DI 2 "general_operand")])
- (label_ref (match_operand 3 ""))
- (pc)))]
+ [(parallel
+ [(set (pc)
+ (if_then_else (match_operator 0 "ordered_comparison_operator"
+ [(match_operand:DI 1 "nonimmediate_operand")
+ (match_operand:DI 2 "general_operand")])
+ (label_ref (match_operand 3 ""))
+ (pc)))
+ (clobber (match_scratch:DI 4 ""))
+ (clobber (match_scratch:SI 5 ""))])]
""
{
- if (operands[2] == const0_rtx)
- emit_insn (gen_tstdi (operands[1]));
- else
- emit_insn (gen_cmpdi (operands[1], operands[2]));
- operands[1] = cc0_rtx;
- operands[2] = const0_rtx;
+ rtx_code code = GET_CODE (operands[0]);
+ if ((code == GE || code == LT) && operands[2] == const0_rtx)
+ {
+ rtx xop1 = operand_subword_force (operands[1], 0, DImode);
+ rtx xop2 = operand_subword_force (operands[2], 0, DImode);
+ /* gen_cbranchsi4 won't use anything from operands[0] other than the
+ code. */
+ emit_jump_insn (gen_cbranchsi4 (operands[0], xop1, xop2, operands[3]));
+ DONE;
+ }
+ if (code == EQ && operands[2] == const0_rtx)
+ {
+ emit_jump_insn (gen_beq0_di (operands[1], operands[3]));
+ DONE;
+ }
+ if (code == NE && operands[2] == const0_rtx)
+ {
+ emit_jump_insn (gen_bne0_di (operands[1], operands[3]));
+ DONE;
+ }
})
(define_expand "cstoredi4"
(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;
+ rtx_code code = GET_CODE (operands[1]);
+ if ((code == GE || code == LT) && operands[3] == const0_rtx)
+ {
+ rtx xop2 = operand_subword_force (operands[2], 0, DImode);
+ rtx xop3 = operand_subword_force (operands[3], 0, DImode);
+ /* gen_cstoresi4 won't use anything from operands[1] other than the
+ code. */
+ emit_jump_insn (gen_cstoresi4 (operands[0], operands[1], xop2, xop3));
+ DONE;
+ }
})
+(define_mode_iterator CMPMODE [QI HI SI])
-(define_expand "cbranchsi4"
- [(set (cc0)
- (compare (match_operand:SI 1 "nonimmediate_operand" "")
- (match_operand:SI 2 "general_operand" "")))
- (set (pc)
+(define_expand "cbranch<mode>4"
+ [(set (pc)
(if_then_else (match_operator 0 "ordered_comparison_operator"
- [(cc0) (const_int 0)])
+ [(match_operand:CMPMODE 1 "nonimmediate_operand" "")
+ (match_operand:CMPMODE 2 "m68k_comparison_operand" "")])
(label_ref (match_operand 3 ""))
(pc)))]
""
"")
-(define_expand "cstoresi4"
- [(set (cc0)
- (compare (match_operand:SI 2 "nonimmediate_operand" "")
- (match_operand:SI 3 "general_operand" "")))
- (set (match_operand:QI 0 "register_operand")
+(define_expand "cstore<mode>4"
+ [(set (match_operand:QI 0 "register_operand")
(match_operator:QI 1 "ordered_comparison_operator"
- [(cc0) (const_int 0)]))]
+ [(match_operand:CMPMODE 2 "nonimmediate_operand" "")
+ (match_operand:CMPMODE 3 "m68k_comparison_operand" "")]))]
""
"")
-
-;; A composite of the cmp, cmpa, cmpi & cmpm m68000 op codes.
-;;
;; In theory we ought to be able to use some 'S' constraints and
;; operand predicates that allow PC-rel addressing modes in the
;; comparison patterns and expanders below. But we would have to be
;; both operands and determining whether or not we emit the operands in
;; order or reversed is not trivial to do just based on the constraints
;; and operand predicates. So to be safe, just don't allow the PC-rel
-;; versions in the various comparison expanders, patterns, for comparisons.
-(define_insn ""
- [(set (cc0)
- (compare (match_operand:SI 0 "nonimmediate_operand" "rKT,rKs,mr,ma,>")
- (match_operand:SI 1 "general_operand" "mr,ma,KTr,Ksr,>")))]
+
+(define_mode_attr scc0_constraints [(QI "=d,d,d") (HI "=d,d,d,d,d") (SI "=d,d,d,d,d,d")])
+(define_mode_attr cmp1_constraints [(QI "dn,dm,>") (HI "rnm,d,n,m,>") (SI "r,r,r,mr,ma,>")])
+(define_mode_attr cmp2_constraints [(QI "dm,nd,>") (HI "d,rnm,m,n,>") (SI "mrC0,mr,ma,KTrC0,Ksr,>")])
+
+;; Note that operand 0 of an SCC insn is supported in the hardware as
+;; memory, but we cannot allow it to be in memory in case the address
+;; needs to be reloaded.
+
+(define_mode_attr scc0_cf_constraints [(QI "=d") (HI "=d") (SI "=d,d,d")])
+(define_mode_attr cmp1_cf_constraints [(QI "dm") (HI "dm") (SI "mrKs,r,rm")])
+(define_mode_attr cmp2_cf_constraints [(QI "C0") (HI "C0") (SI "r,mrKs,C0")])
+(define_mode_attr cmp2_cf_predicate [(QI "const0_operand") (HI "const0_operand") (SI "general_operand")])
+
+(define_insn "cbranch<mode>4_insn"
+ [(set (pc)
+ (if_then_else (match_operator 0 "ordered_comparison_operator"
+ [(match_operand:CMPMODE 1 "nonimmediate_operand" "<cmp1_constraints>")
+ (match_operand:CMPMODE 2 "general_operand" "<cmp2_constraints>")])
+ (label_ref (match_operand 3 ""))
+ (pc)))]
"!TARGET_COLDFIRE"
{
- if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
- return "cmpm%.l %1,%0";
- if (REG_P (operands[1])
- || (!REG_P (operands[0]) && GET_CODE (operands[0]) != MEM))
- {
- cc_status.flags |= CC_REVERSED; /*|*/
- return "cmp%.l %d0,%d1";
- }
- if (ADDRESS_REG_P (operands[0])
- && GET_CODE (operands[1]) == CONST_INT
- && INTVAL (operands[1]) < 0x8000
- && INTVAL (operands[1]) >= -0x8000)
- return "cmp%.w %1,%0";
- return "cmp%.l %d1,%d0";
-})
-
-(define_insn "*cmpsi_cf"
- [(set (cc0)
- (compare (match_operand:SI 0 "nonimmediate_operand" "mrKs,r")
- (match_operand:SI 1 "general_operand" "r,mrKs")))]
- "TARGET_COLDFIRE"
+ rtx_code code = GET_CODE (operands[0]);
+ code = m68k_output_compare_<mode> (operands[1], operands[2], code);
+ return m68k_output_branch_integer (code);
+}
+ [(set_attr "flags_valid" "set")])
+
+(define_insn "cbranch<mode>4_insn_rev"
+ [(set (pc)
+ (if_then_else (match_operator 0 "ordered_comparison_operator"
+ [(match_operand:CMPMODE 1 "nonimmediate_operand" "<cmp1_constraints>")
+ (match_operand:CMPMODE 2 "general_operand" "<cmp2_constraints>")])
+ (pc)
+ (label_ref (match_operand 3 ""))))]
+ "!TARGET_COLDFIRE"
{
- if (REG_P (operands[1])
- || (!REG_P (operands[0]) && GET_CODE (operands[0]) != MEM))
- {
- cc_status.flags |= CC_REVERSED; /*|*/
- return "cmp%.l %d0,%d1";
- }
- return "cmp%.l %d1,%d0";
+ rtx_code code = GET_CODE (operands[0]);
+ code = m68k_output_compare_<mode> (operands[1], operands[2], code);
+ return m68k_output_branch_integer_rev (code);
}
- [(set_attr "type" "cmp_l")])
+ [(set_attr "flags_valid" "set")])
-(define_expand "cbranchhi4"
- [(set (cc0)
- (compare (match_operand:HI 1 "nonimmediate_operand" "")
- (match_operand:HI 2 "m68k_subword_comparison_operand" "")))
- (set (pc)
+(define_insn "cbranch<mode>4_insn_cf"
+ [(set (pc)
(if_then_else (match_operator 0 "ordered_comparison_operator"
- [(cc0) (const_int 0)])
+ [(match_operand:CMPMODE 1 "nonimmediate_operand" "<cmp1_cf_constraints>")
+ (match_operand:CMPMODE 2 "<cmp2_cf_predicate>" "<cmp2_cf_constraints>")])
(label_ref (match_operand 3 ""))
(pc)))]
- ""
- "")
+ "TARGET_COLDFIRE"
+{
+ rtx_code code = GET_CODE (operands[0]);
+ code = m68k_output_compare_<mode> (operands[1], operands[2], code);
+ return m68k_output_branch_integer (code);
+}
+ [(set_attr "flags_valid" "set")])
-(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 "cbranch<mode>4_insn_cf_rev"
+ [(set (pc)
+ (if_then_else (match_operator 0 "ordered_comparison_operator"
+ [(match_operand:CMPMODE 1 "nonimmediate_operand" "<cmp1_cf_constraints>")
+ (match_operand:CMPMODE 2 "<cmp2_cf_predicate>" "<cmp2_cf_constraints>")])
+ (pc)
+ (label_ref (match_operand 3 ""))))]
+ "TARGET_COLDFIRE"
+{
+ rtx_code code = GET_CODE (operands[0]);
+ code = m68k_output_compare_<mode> (operands[1], operands[2], code);
+ return m68k_output_branch_integer_rev (code);
+}
+ [(set_attr "flags_valid" "set")])
-(define_insn ""
- [(set (cc0)
- (compare (match_operand:HI 0 "nonimmediate_operand" "rnm,d,n,m,>")
- (match_operand:HI 1 "general_operand" "d,rnm,m,n,>")))]
+(define_insn "cstore<mode>4_insn"
+ [(set (match_operand:QI 0 "register_operand" "<scc0_constraints>")
+ (match_operator:QI 1 "ordered_comparison_operator"
+ [(match_operand:CMPMODE 2 "nonimmediate_operand" "<cmp1_constraints>")
+ (match_operand:CMPMODE 3 "general_operand" "<cmp2_constraints>")]))]
"!TARGET_COLDFIRE"
{
- if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
- return "cmpm%.w %1,%0";
- if ((REG_P (operands[1]) && !ADDRESS_REG_P (operands[1]))
- || (!REG_P (operands[0]) && GET_CODE (operands[0]) != MEM))
- {
- cc_status.flags |= CC_REVERSED; /*|*/
- return "cmp%.w %d0,%d1";
- }
- return "cmp%.w %d1,%d0";
-})
+ rtx_code code = GET_CODE (operands[1]);
+ code = m68k_output_compare_<mode> (operands[2], operands[3], code);
+ return m68k_output_scc (code);
+}
+ [(set_attr "flags_valid" "set")])
-(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)])
+(define_insn "cstore<mode>4_insn_cf"
+ [(set (match_operand:QI 0 "register_operand" "<scc0_cf_constraints>")
+ (match_operator:QI 1 "ordered_comparison_operator"
+ [(match_operand:CMPMODE 2 "nonimmediate_operand" "<cmp1_cf_constraints>")
+ (match_operand:CMPMODE 3 "<cmp2_cf_predicate>" "<cmp2_cf_constraints>")]))]
+ "TARGET_COLDFIRE"
+{
+ rtx_code code = GET_CODE (operands[1]);
+ code = m68k_output_compare_<mode> (operands[2], operands[3], code);
+ return m68k_output_scc (code);
+}
+ [(set_attr "flags_valid" "set")])
+
+;; ColdFire/5200 only allows "<Q>" type addresses when the bit position is
+;; specified as a constant, so we must disable all patterns that may extract
+;; from a MEM at a constant bit position if we can't use this as a constraint.
+
+(define_insn "cbranchsi4_btst_mem_insn"
+ [(set (pc)
+ (if_then_else (match_operator 0 "equality_comparison_operator"
+ [(zero_extract:SI (match_operand:QI 1 "memory_src_operand" "oS,o")
+ (const_int 1)
+ (minus:SI (const_int 7)
+ (match_operand:SI 2 "general_operand" "di,d")))
+ (const_int 0)])
(label_ref (match_operand 3 ""))
(pc)))]
""
- "")
+{
+ rtx_code code = GET_CODE (operands[0]);
+ code = m68k_output_btst (operands[2], operands[1], code, 7);
+ return m68k_output_branch_integer (code);
+}
+ [(set_attr "ok_for_coldfire" "no,yes")])
-(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 "cbranchsi4_btst_reg_insn"
+ [(set (pc)
+ (if_then_else (match_operator 0 "equality_comparison_operator"
+ [(zero_extract:SI (match_operand:SI 1 "register_operand" "d")
+ (const_int 1)
+ (minus:SI (const_int 31)
+ (match_operand:SI 2 "general_operand" "di")))
+ (const_int 0)])
+ (label_ref (match_operand 3 ""))
+ (pc)))]
+ "!(CONST_INT_P (operands[1]) && !IN_RANGE (INTVAL (operands[1]), 0, 31))"
+{
+ rtx_code code = GET_CODE (operands[0]);
+ code = m68k_output_btst (operands[2], operands[1], code, 31);
+ return m68k_output_branch_integer (code);
+})
-(define_insn ""
- [(set (cc0)
- (compare (match_operand:QI 0 "nonimmediate_operand" "dn,dm,>")
- (match_operand:QI 1 "general_operand" "dm,nd,>")))]
- "!TARGET_COLDFIRE"
+;; Nonoffsettable mem refs are ok in this one pattern
+;; since we don't try to adjust them.
+(define_insn "cbranchsi4_btst_mem_insn_1"
+ [(set (pc)
+ (if_then_else (match_operator 0 "equality_comparison_operator"
+ [(zero_extract:SI (match_operand:QI 1 "memory_operand" "m")
+ (const_int 1)
+ (match_operand:SI 2 "const_int_operand" "n"))
+ (const_int 0)])
+ (label_ref (match_operand 3 ""))
+ (pc)))]
+ "!TARGET_COLDFIRE && (unsigned) INTVAL (operands[2]) < 8"
+{
+ rtx_code code = GET_CODE (operands[0]);
+ operands[2] = GEN_INT (7 - INTVAL (operands[2]));
+ code = m68k_output_btst (operands[2], operands[1], code, 7);
+ return m68k_output_branch_integer (code);
+})
+
+(define_insn "cbranchsi4_btst_reg_insn_1"
+ [(set (pc)
+ (if_then_else (match_operator 0 "equality_comparison_operator"
+ [(zero_extract:SI (match_operand:SI 1 "nonimmediate_operand" "do,dQ")
+ (const_int 1)
+ (match_operand:SI 2 "const_int_operand" "n,n"))
+ (const_int 0)])
+ (label_ref (match_operand 3 ""))
+ (pc)))]
+ "!(REG_P (operands[1]) && !IN_RANGE (INTVAL (operands[2]), 0, 31))"
{
- if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
- return "cmpm%.b %1,%0";
- if (REG_P (operands[1])
- || (!REG_P (operands[0]) && GET_CODE (operands[0]) != MEM))
+ rtx_code code = GET_CODE (operands[0]);
+ if (GET_CODE (operands[1]) == MEM)
{
- cc_status.flags |= CC_REVERSED; /*|*/
- return "cmp%.b %d0,%d1";
+ operands[1] = adjust_address (operands[1], QImode,
+ INTVAL (operands[2]) / 8);
+ operands[2] = GEN_INT (7 - INTVAL (operands[2]) % 8);
+ code = m68k_output_btst (operands[2], operands[1], code, 7);
}
- return "cmp%.b %d1,%d0";
+ else
+ {
+ operands[2] = GEN_INT (31 - INTVAL (operands[2]));
+ code = m68k_output_btst (operands[2], operands[1], code, 31);
+ }
+ return m68k_output_branch_integer (code);
+}
+ [(set_attr "ok_for_coldfire" "no,yes")])
+
+(define_mode_iterator BTST [QI SI])
+(define_mode_attr btst_predicate [(QI "memory_operand") (SI "register_operand")])
+(define_mode_attr btst_constraint [(QI "o") (SI "d")])
+(define_mode_attr btst_range [(QI "7") (SI "31")])
+
+;; Special patterns for optimizing bit-field instructions.
+(define_insn "cbranch_bftst<mode>_insn"
+ [(set (pc)
+ (if_then_else (match_operator 0 "ordered_comparison_operator"
+ [(zero_extract:SI (match_operand:BTST 1 "<btst_predicate>" "<btst_constraint>")
+ (match_operand:SI 2 "const_int_operand" "n")
+ (match_operand:SI 3 "general_operand" "dn"))
+ (const_int 0)])
+ (label_ref (match_operand 4 ""))
+ (pc)))]
+ "TARGET_68020 && TARGET_BITFIELD
+ && (!REG_P (operands[1]) || !CONST_INT_P (operands[3])
+ || IN_RANGE (INTVAL (operands[3]), 0, 31))"
+{
+ rtx_code code = GET_CODE (operands[0]);
+ code = m68k_output_bftst (operands[1], operands[2], operands[3], code);
+ operands[3] = operands[4];
+ return m68k_output_branch_integer (code);
})
+(define_insn "cstore_bftst<mode>_insn"
+ [(set (match_operand:QI 0 "register_operand" "=d")
+ (match_operator:QI 1 "ordered_comparison_operator"
+ [(zero_extract:SI (match_operand:BTST 2 "<btst_predicate>" "<btst_constraint>")
+ (match_operand:SI 3 "const_int_operand" "n")
+ (match_operand:SI 4 "general_operand" "dn"))
+ (const_int 0)]))]
+ "TARGET_68020 && TARGET_BITFIELD
+ && (!REG_P (operands[2]) || !CONST_INT_P (operands[4])
+ || IN_RANGE (INTVAL (operands[4]), 0, 31))"
+{
+ rtx_code code = GET_CODE (operands[1]);
+ code = m68k_output_bftst (operands[2], operands[3], operands[4], code);
+ return m68k_output_scc (code);
+})
+
+;; Floating point comparison patterns
(define_expand "cbranch<mode>4"
- [(set (cc0)
- (compare (match_operand:FP 1 "register_operand" "")
- (match_operand:FP 2 "fp_src_operand" "")))
- (set (pc)
+ [(set (pc)
(if_then_else (match_operator 0 "comparison_operator"
- [(cc0) (const_int 0)])
+ [(match_operand:FP 1 "register_operand" "")
+ (match_operand:FP 2 "fp_src_operand" "")])
(label_ref (match_operand 3 ""))
(pc)))]
"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" "")
- (match_operand:FP 3 "fp_src_operand" "")))
- (set (match_operand:QI 0 "register_operand")
+ [(set (match_operand:QI 0 "register_operand")
(match_operator:QI 1 "m68k_cstore_comparison_operator"
- [(cc0) (const_int 0)]))]
+ [(match_operand:FP 2 "register_operand" "")
+ (match_operand:FP 3 "fp_src_operand" "")]))]
"TARGET_HARD_FLOAT && !(TUNE_68060 || TARGET_COLDFIRE_FPU)"
"if (TARGET_COLDFIRE && operands[2] != const0_rtx)
FAIL;")
-(define_insn "*cmp<mode>_68881"
- [(set (cc0)
- (compare (match_operand:FP 0 "fp_src_operand" "f,f,<FP:dreg>mF")
- (match_operand:FP 1 "fp_src_operand" "f,<FP:dreg>mF,f")))]
+(define_insn "cbranch<mode>4_insn_68881"
+ [(set (pc)
+ (if_then_else (match_operator 0 "comparison_operator"
+ [(match_operand:FP 1 "fp_src_operand" "f,f,<FP:dreg>mF,f<FP:dreg>m")
+ (match_operand:FP 2 "fp_src_operand" "f,<FP:dreg>mF,f,H")])
+ (label_ref (match_operand 3 ""))
+ (pc)))]
"TARGET_68881
- && (register_operand (operands[0], <MODE>mode)
- || register_operand (operands[1], <MODE>mode))"
- "@
- fcmp%.x %1,%0
- fcmp%.<FP:prec> %f1,%0
- fcmp%.<FP:prec> %0,%f1"
- [(set_attr "type" "fcmp")])
-
-(define_insn "*cmp<mode>_cf"
- [(set (cc0)
- (compare (match_operand:FP 0 "fp_src_operand" "f,f,<FP:dreg><Q>U")
- (match_operand:FP 1 "fp_src_operand" "f,<FP:dreg><Q>U,f")))]
- "TARGET_COLDFIRE_FPU
- && (register_operand (operands[0], <MODE>mode)
- || register_operand (operands[1], <MODE>mode))"
- "@
- fcmp%.d %1,%0
- fcmp%.<FP:prec> %f1,%0
- fcmp%.<FP:prec> %0,%f1"
- [(set_attr "type" "fcmp")])
-\f
-;; Recognizers for btst instructions.
-
-;; ColdFire/5200 only allows "<Q>" type addresses when the bit position is
-;; specified as a constant, so we must disable all patterns that may extract
-;; from a MEM at a constant bit position if we can't use this as a constraint.
-
-(define_insn ""
- [(set
- (cc0)
- (compare (zero_extract:SI (match_operand:QI 0 "memory_src_operand" "oS")
- (const_int 1)
- (minus:SI (const_int 7)
- (match_operand:SI 1 "general_operand" "di")))
- (const_int 0)))]
- "!TARGET_COLDFIRE"
+ && (register_operand (operands[1], <MODE>mode)
+ || register_operand (operands[2], <MODE>mode)
+ || const0_operand (operands[2], <MODE>mode))"
{
- return output_btst (operands, operands[1], operands[0], insn, 7);
-})
+ rtx_code code = GET_CODE (operands[0]);
+ code = m68k_output_compare_fp (operands[1], operands[2], code);
+ return m68k_output_branch_float (code);
+}
+ [(set_attr "flags_valid" "set")])
-;; This is the same as the above pattern except for the constraints. The 'i'
-;; has been deleted.
+(define_insn "cbranch<mode>4_insn_cf"
+ [(set (pc)
+ (if_then_else (match_operator 0 "comparison_operator"
+ [(match_operand:FP 1 "fp_src_operand" "f,f,<FP:dreg><Q>U,f<FP:dreg><Q>U")
+ (match_operand:FP 2 "fp_src_operand" "f,<FP:dreg><Q>U,f,H")])
+ (label_ref (match_operand 3 ""))
+ (pc)))]
+ "TARGET_COLDFIRE_FPU
+ && (register_operand (operands[1], <MODE>mode)
+ || register_operand (operands[2], <MODE>mode)
+ || const0_operand (operands[2], <MODE>mode))"
+{
+ rtx_code code = GET_CODE (operands[0]);
+ code = m68k_output_compare_fp (operands[1], operands[2], code);
+ return m68k_output_branch_float (code);
+}
+ [(set_attr "flags_valid" "set")])
-(define_insn ""
- [(set
- (cc0)
- (compare (zero_extract:SI (match_operand:QI 0 "memory_operand" "o")
- (const_int 1)
- (minus:SI (const_int 7)
- (match_operand:SI 1 "general_operand" "d")))
- (const_int 0)))]
- "TARGET_COLDFIRE"
+(define_insn "cbranch<mode>4_insn_rev_68881"
+ [(set (pc)
+ (if_then_else (match_operator 0 "comparison_operator"
+ [(match_operand:FP 1 "fp_src_operand" "f,f,<FP:dreg>mF,f<FP:dreg>m")
+ (match_operand:FP 2 "fp_src_operand" "f,<FP:dreg>mF,f,H")])
+ (pc)
+ (label_ref (match_operand 3 ""))))]
+ "TARGET_68881
+ && (register_operand (operands[1], <MODE>mode)
+ || register_operand (operands[2], <MODE>mode)
+ || const0_operand (operands[2], <MODE>mode))"
{
- return output_btst (operands, operands[1], operands[0], insn, 7);
-})
+ rtx_code code = GET_CODE (operands[0]);
+ code = m68k_output_compare_fp (operands[1], operands[2], code);
+ return m68k_output_branch_float_rev (code);
+}
+ [(set_attr "flags_valid" "set")])
-(define_insn ""
- [(set
- (cc0)
- (compare (zero_extract:SI (match_operand:SI 0 "register_operand" "d")
- (const_int 1)
- (minus:SI (const_int 31)
- (match_operand:SI 1 "general_operand" "di")))
- (const_int 0)))]
- "!(CONST_INT_P (operands[1]) && !IN_RANGE (INTVAL (operands[1]), 0, 31))"
+(define_insn "cbranch<mode>4_insn_rev_cf"
+ [(set (pc)
+ (if_then_else (match_operator 0 "comparison_operator"
+ [(match_operand:FP 1 "fp_src_operand" "f,f,<FP:dreg><Q>U,f<FP:dreg><Q>U")
+ (match_operand:FP 2 "fp_src_operand" "f,<FP:dreg><Q>U,f,H")])
+ (pc)
+ (label_ref (match_operand 3 ""))))]
+ "TARGET_COLDFIRE_FPU
+ && (register_operand (operands[1], <MODE>mode)
+ || register_operand (operands[2], <MODE>mode)
+ || const0_operand (operands[2], <MODE>mode))"
{
- return output_btst (operands, operands[1], operands[0], insn, 31);
-})
+ rtx_code code = GET_CODE (operands[0]);
+ code = m68k_output_compare_fp (operands[1], operands[2], code);
+ return m68k_output_branch_float_rev (code);
+}
+ [(set_attr "flags_valid" "set")])
-;; The following two patterns are like the previous two
-;; except that they use the fact that bit-number operands
-;; are automatically masked to 3 or 5 bits.
+(define_insn "cstore<mode>4_insn_68881"
+ [(set (match_operand:QI 0 "register_operand" "=d,d,d,d")
+ (match_operator:QI 1 "m68k_cstore_comparison_operator"
+ [(match_operand:FP 2 "fp_src_operand" "f,f,<FP:dreg>mF,f<FP:dreg>m")
+ (match_operand:FP 3 "fp_src_operand" "f,<FP:dreg>mF,f,H")]))]
+ "TARGET_HARD_FLOAT && !(TUNE_68060 || TARGET_COLDFIRE_FPU)
+ && (register_operand (operands[2], <MODE>mode)
+ || register_operand (operands[3], <MODE>mode)
+ || const0_operand (operands[3], <MODE>mode))"
+{
+ rtx_code code = GET_CODE (operands[1]);
+ code = m68k_output_compare_fp (operands[2], operands[3], code);
+ return m68k_output_scc_float (code);
+}
+ [(set_attr "flags_valid" "set")])
-(define_insn ""
- [(set
- (cc0)
- (compare (zero_extract:SI (match_operand:QI 0 "memory_operand" "o")
- (const_int 1)
- (minus:SI (const_int 7)
- (and:SI
- (match_operand:SI 1 "register_operand" "d")
- (const_int 7))))
- (const_int 0)))]
- ""
+;; Test against zero only for coldfire floating point cstore.
+(define_insn "cstore<mode>4_insn_cf"
+ [(set (match_operand:QI 0 "register_operand" "=d")
+ (match_operator:QI 1 "m68k_cstore_comparison_operator"
+ [(match_operand:FP 2 "fp_src_operand" "f<FP:dreg><Q>U")
+ (match_operand:FP 3 "const0_operand" "H")]))]
+ "TARGET_HARD_FLOAT && TARGET_COLDFIRE_FPU"
{
- return output_btst (operands, operands[1], operands[0], insn, 7);
-})
+ rtx_code code = GET_CODE (operands[1]);
+ code = m68k_output_compare_fp (operands[2], operands[3], code);
+ return m68k_output_scc_float (code);
+}
+ [(set_attr "flags_valid" "set")])
-(define_insn ""
- [(set
- (cc0)
- (compare (zero_extract:SI (match_operand:SI 0 "register_operand" "d")
- (const_int 1)
- (minus:SI (const_int 31)
- (and:SI
- (match_operand:SI 1 "register_operand" "d")
- (const_int 31))))
- (const_int 0)))]
- ""
-{
- return output_btst (operands, operands[1], operands[0], insn, 31);
-})
-
-;; Nonoffsettable mem refs are ok in this one pattern
-;; since we don't try to adjust them.
-(define_insn ""
- [(set
- (cc0)
- (compare (zero_extract:SI (match_operand:QI 0 "memory_operand" "m")
- (const_int 1)
- (match_operand:SI 1 "const_int_operand" "n"))
- (const_int 0)))]
- "(unsigned) INTVAL (operands[1]) < 8 && !TARGET_COLDFIRE"
-{
- operands[1] = GEN_INT (7 - INTVAL (operands[1]));
- return output_btst (operands, operands[1], operands[0], insn, 7);
-})
-
-(define_insn ""
- [(set
- (cc0)
- (compare (zero_extract:SI (match_operand:SI 0 "register_operand" "do")
- (const_int 1)
- (match_operand:SI 1 "const_int_operand" "n"))
- (const_int 0)))]
- "!TARGET_COLDFIRE
- && !(REG_P (operands[0]) && !IN_RANGE (INTVAL (operands[1]), 0, 31))"
-{
- if (GET_CODE (operands[0]) == MEM)
- {
- operands[0] = adjust_address (operands[0], QImode,
- INTVAL (operands[1]) / 8);
- operands[1] = GEN_INT (7 - INTVAL (operands[1]) % 8);
- return output_btst (operands, operands[1], operands[0], insn, 7);
- }
- operands[1] = GEN_INT (31 - INTVAL (operands[1]));
- return output_btst (operands, operands[1], operands[0], insn, 31);
-})
-
-;; This is the same as the above pattern except for the constraints.
-;; The 'o' has been replaced with 'Q'.
-
-(define_insn ""
- [(set
- (cc0)
- (compare (zero_extract:SI (match_operand:SI 0 "register_operand" "dQ")
- (const_int 1)
- (match_operand:SI 1 "const_int_operand" "n"))
- (const_int 0)))]
- "TARGET_COLDFIRE
- && !(REG_P (operands[0]) && !IN_RANGE (INTVAL (operands[1]), 0, 31))"
-{
- if (GET_CODE (operands[0]) == MEM)
- {
- operands[0] = adjust_address (operands[0], QImode,
- INTVAL (operands[1]) / 8);
- operands[1] = GEN_INT (7 - INTVAL (operands[1]) % 8);
- return output_btst (operands, operands[1], operands[0], insn, 7);
- }
- operands[1] = GEN_INT (31 - INTVAL (operands[1]));
- return output_btst (operands, operands[1], operands[0], insn, 31);
-})
-
-\f
;; move instructions
;; A special case in which it is not desirable
"!TARGET_COLDFIRE && reload_completed"
{
return output_move_simode (operands);
-})
+}
+ [(set_attr "flags_valid" "set")])
;; Before reload is completed the register constraints
;; force integer constants in range for a moveq to be reloaded
"!TARGET_COLDFIRE"
{
return output_move_simode (operands);
-})
+}
+ [(set_attr "flags_valid" "set")])
;; ColdFire move instructions can have at most one operand of mode >= 6.
(define_insn "*movsi_cf"
[(set (match_operand:HI 0 "nonimmediate_operand" "=g")
(match_operand:HI 1 "general_src_operand" "gS"))]
"!TARGET_COLDFIRE"
- "* return output_move_himode (operands);")
+ "* return output_move_himode (operands);"
+ [(set (attr "flags_valid")
+ (if_then_else (match_operand 0 "address_reg_operand")
+ (const_string "unchanged")
+ (const_string "move")))])
(define_insn ""
[(set (match_operand:HI 0 "nonimmediate_operand" "=r<Q>,g,U")
(match_operand:HI 1 "general_operand" "g,r<Q>,U"))]
"TARGET_COLDFIRE"
- "* return output_move_himode (operands);")
+ "* return output_move_himode (operands);"
+ [(set (attr "flags_valid")
+ (if_then_else (match_operand 0 "address_reg_operand")
+ (const_string "unchanged")
+ (const_string "move")))])
(define_expand "movstricthi"
[(set (strict_low_part (match_operand:HI 0 "nonimmediate_operand" ""))
[(set (strict_low_part (match_operand:HI 0 "nonimmediate_operand" "+dm"))
(match_operand:HI 1 "general_src_operand" "rmSn"))]
"!TARGET_COLDFIRE"
- "* return output_move_stricthi (operands);")
+ "* return output_move_stricthi (operands);"
+ [(set_attr "flags_valid" "move")])
(define_insn ""
[(set (strict_low_part (match_operand:HI 0 "nonimmediate_operand" "+d,m"))
(match_operand:HI 1 "general_src_operand" "rmn,r"))]
"TARGET_COLDFIRE"
- "* return output_move_stricthi (operands);")
+ "* return output_move_stricthi (operands);"
+ [(set_attr "flags_valid" "move")])
(define_expand "movqi"
[(set (match_operand:QI 0 "nonimmediate_operand" "")
[(set (match_operand:QI 0 "nonimmediate_operand" "=d,*a,m")
(match_operand:QI 1 "general_src_operand" "dmSi*a,di*a,dmSi"))]
"!TARGET_COLDFIRE"
- "* return output_move_qimode (operands);")
+ "* return output_move_qimode (operands);"
+ [(set_attr "flags_valid" "set")])
(define_insn ""
[(set (match_operand:QI 0 "nonimmediate_operand" "=d<Q>,dm,U,d*a")
(match_operand:QI 1 "general_src_operand" "dmi,d<Q>,U,di*a"))]
"TARGET_COLDFIRE"
- "* return output_move_qimode (operands);")
+ "* return output_move_qimode (operands);"
+ [(set_attr "flags_valid" "set")])
(define_expand "movstrictqi"
[(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" ""))
[(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+dm"))
(match_operand:QI 1 "general_src_operand" "dmSn"))]
"!TARGET_COLDFIRE"
- "* return output_move_strictqi (operands);")
+ "* return output_move_strictqi (operands);"
+ [(set_attr "flags_valid" "move")])
(define_insn "*movstrictqi_cf"
[(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+d, Ac, d,m"))
return "clr%.l %0";
}
return "move%.l %1,%0";
-})
+}
+ [(set_attr "flags_valid" "move")])
(define_insn "movsf_cf_soft"
[(set (match_operand:SF 0 "nonimmediate_operand" "=r<Q>,g,U")
return "fmove%.d %f1,%0";
}
return output_move_double (operands);
-})
+}
+ [(set_attr "flags_valid" "move")])
(define_insn_and_split "movdf_cf_soft"
[(set (match_operand:DF 0 "nonimmediate_operand" "=r,g")
return "fmove%.x %f1,%0";
}
return output_move_double (operands);
-})
+}
+ [(set_attr "flags_valid" "move")])
(define_insn ""
[(set (match_operand:XF 0 "nonimmediate_operand" "=rm,rf,&rof<>")
"!TARGET_COLDFIRE"
{
if (GET_CODE (operands[0]) == REG)
- {
- /* Must clear condition codes, since the move.l bases them on
- the entire 32 bits, not just the desired 8 bits. */
- CC_STATUS_INIT;
- return "move%.l %1,%0";
- }
+ return "move%.l %1,%0";
+
if (GET_CODE (operands[1]) == MEM)
operands[1] = adjust_address (operands[1], QImode, 3);
return "move%.b %1,%0";
-})
+}
+ [(set (attr "flags_valid")
+ (if_then_else (match_operand 0 "register_operand")
+ (const_string "no")
+ (const_string "yes")))])
(define_insn "trunchiqi2"
[(set (match_operand:QI 0 "nonimmediate_operand" "=dm,d")
if (GET_CODE (operands[0]) == REG
&& (GET_CODE (operands[1]) == MEM
|| GET_CODE (operands[1]) == CONST_INT))
- {
- /* Must clear condition codes, since the move.w bases them on
- the entire 16 bits, not just the desired 8 bits. */
- CC_STATUS_INIT;
- return "move%.w %1,%0";
- }
+ return "move%.w %1,%0";
+
if (GET_CODE (operands[0]) == REG)
- {
- /* Must clear condition codes, since the move.l bases them on
- the entire 32 bits, not just the desired 8 bits. */
- CC_STATUS_INIT;
- return "move%.l %1,%0";
- }
+ return "move%.l %1,%0";
+
if (GET_CODE (operands[1]) == MEM)
operands[1] = adjust_address (operands[1], QImode, 1);
return "move%.b %1,%0";
-})
+}
+ [(set (attr "flags_valid")
+ (if_then_else (match_operand 0 "register_operand")
+ (const_string "no")
+ (const_string "yes")))])
(define_insn "truncsihi2"
[(set (match_operand:HI 0 "nonimmediate_operand" "=dm,d")
"!TARGET_COLDFIRE"
{
if (GET_CODE (operands[0]) == REG)
- {
- /* Must clear condition codes, since the move.l bases them on
- the entire 32 bits, not just the desired 8 bits. */
- CC_STATUS_INIT;
- return "move%.l %1,%0";
- }
+ return "move%.l %1,%0";
+
if (GET_CODE (operands[1]) == MEM)
operands[1] = adjust_address (operands[1], QImode, 2);
return "move%.w %1,%0";
-})
+}
+ [(set (attr "flags_valid")
+ (if_then_else (match_operand 0 "register_operand")
+ (const_string "no")
+ (const_string "yes")))])
\f
;; zero extension instructions
(sign_extend:DI (match_operand:QI 1 "general_src_operand" "rmS")))]
""
{
- CC_STATUS_INIT;
operands[2] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1);
if (ISA_HAS_MVS_MVZ)
return "mvs%.b %1,%2\;smi %0\;extb%.l %0";
(match_operand:HI 1 "general_src_operand" "rmS")))]
""
{
- CC_STATUS_INIT;
operands[2] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1);
if (ISA_HAS_MVS_MVZ)
return "mvs%.w %1,%2\;smi %0\;extb%.l %0";
(clobber (match_scratch:SI 2 "=X,d,d,d"))]
""
{
- CC_STATUS_INIT;
-
if (which_alternative == 0)
/* Handle alternative 0. */
{
(match_operand:SI 2 "general_operand" "rmn"))))]
""
{
- CC_STATUS_INIT;
operands[3] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1);
if (GET_CODE (operands[1]) == CONST_INT
&& (unsigned) INTVAL (operands[1]) > 8)
{
if (REGNO (operands[0]) == REGNO (operands[1]))
{
- /* Extending float to double in an fp-reg is a no-op.
- NOTICE_UPDATE_CC has already assumed that the
- cc will be set. So cancel what it did. */
- cc_status = cc_prev_status;
+ /* Extending float to double in an fp-reg is a no-op. */
return "";
}
return "f%&move%.x %1,%0";
{
if (REGNO (operands[0]) == REGNO (operands[1]))
{
- /* Extending float to double in an fp-reg is a no-op.
- NOTICE_UPDATE_CC has already assumed that the
- cc will be set. So cancel what it did. */
- cc_status = cc_prev_status;
+ /* Extending float to double in an fp-reg is a no-op. */
return "";
}
return "fdmove%.d %1,%0";
(clobber (match_scratch:SI 3 "=d"))]
"TARGET_68881 && TUNE_68040"
{
- CC_STATUS_INIT;
return "fmovem%.l %!,%2\;moveq #16,%3\;or%.l %2,%3\;and%.w #-33,%3\;fmovem%.l %3,%!\;fmove%.l %1,%0\;fmovem%.l %2,%!";
})
(clobber (match_scratch:SI 3 "=d"))]
"TARGET_68881 && TUNE_68040"
{
- CC_STATUS_INIT;
return "fmovem%.l %!,%2\;moveq #16,%3\;or%.l %2,%3\;and%.w #-33,%3\;fmovem%.l %3,%!\;fmove%.w %1,%0\;fmovem%.l %2,%!";
})
(clobber (match_scratch:SI 3 "=d"))]
"TARGET_68881 && TUNE_68040"
{
- CC_STATUS_INIT;
return "fmovem%.l %!,%2\;moveq #16,%3\;or%.l %2,%3\;and%.w #-33,%3\;fmovem%.l %3,%!\;fmove%.b %1,%0\;fmovem%.l %2,%!";
})
(clobber (match_scratch:SI 3 "=&d,X,a,?d"))]
"!TARGET_COLDFIRE"
{
- CC_STATUS_INIT;
if (ADDRESS_REG_P (operands[0]))
return "add%.w %1,%0";
else if (ADDRESS_REG_P (operands[3]))
(match_operand:DI 2 "general_operand" "0,0")))]
"!TARGET_COLDFIRE"
{
- CC_STATUS_INIT;
if (GET_CODE (operands[0]) == REG)
operands[2] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1);
else
(match_operand:DI 2 "register_operand" "0")))]
"TARGET_COLDFIRE"
{
- CC_STATUS_INIT;
return "add%.l %1,%R0\;negx%.l %0\;neg%.l %0";
})
(match_operand:DI 2 "general_operand" "0,0")))]
""
{
- CC_STATUS_INIT;
if (GET_CODE (operands[1]) == REG)
operands[1] = gen_rtx_REG (SImode, REGNO (operands[1]) + 1);
else
else
{
gcc_assert (GET_CODE (operands[0]) == MEM);
- CC_STATUS_INIT;
if (GET_CODE (XEXP (operands[0], 0)) == POST_INC)
{
operands[1] = gen_rtx_MEM (SImode,
return "add%.l %R2,%1\;move%.l %0,%3\;addx%.l %2,%3\;move%.l %3,%0";
}
}
-})
+}
+ [(set (attr "flags_valid")
+ (if_then_else (match_operand 0 "register_operand")
+ (const_string "noov")
+ (const_string "no")))])
(define_insn "addsi_lshrsi_31"
[(set (match_operand:SI 0 "nonimmediate_operand" "=dm,dm,d<Q>")
"! TARGET_COLDFIRE"
- "* return output_addsi3 (operands);")
+ "* return output_addsi3 (operands);"
+ [(set_attr "flags_valid" "noov,unchanged,unchanged,noov,unchanged")])
(define_insn_and_split "*addsi3_5200"
[(set (match_operand:SI 0 "nonimmediate_operand" "=mr,mr,a, m,r, ?a, ?a,?a,?a")
return "subq%.w %2,%0";
}
/* On the CPU32 it is faster to use two addqw instructions to
- add a small integer (8 < N <= 16) to a register.
+ add a small integer (8 < N <= 16) to a register.
Likewise for subqw. */
if (TUNE_CPU32 && REG_P (operands[0]))
{
return MOTOROLA ? "lea (%c2,%0),%0" : "lea %0@(%c2),%0";
}
return "add%.w %2,%0";
-})
+}
+ [(set (attr "flags_valid")
+ (if_then_else (match_operand 0 "address_reg_operand")
+ (const_string "unchanged")
+ (const_string "noov")))])
;; These insns must use MATCH_DUP instead of the more expected
;; use of a matching constraint because the "output" here is also
(match_operand:HI 1 "general_src_operand" "dn,rmSn")))]
"!TARGET_COLDFIRE"
{
+ gcc_assert (!ADDRESS_REG_P (operands[0]));
if (GET_CODE (operands[1]) == CONST_INT)
{
/* If the constant would be a negative number when interpreted as
return "subq%.w #8,%0\;subq%.w %1,%0";
}
}
- if (ADDRESS_REG_P (operands[0]) && !TUNE_68040)
- return MOTOROLA ? "lea (%c1,%0),%0" : "lea %0@(%c1),%0";
}
return "add%.w %1,%0";
-})
+}
+ [(set_attr "flags_valid" "noov")])
(define_insn ""
[(set (strict_low_part (match_operand:HI 0 "nonimmediate_operand" "+m,d"))
(match_dup 0)))]
"!TARGET_COLDFIRE"
{
+ gcc_assert (!ADDRESS_REG_P (operands[0]));
if (GET_CODE (operands[1]) == CONST_INT)
{
/* If the constant would be a negative number when interpreted as
return "subq%.w #8,%0\;subq%.w %1,%0";
}
}
- if (ADDRESS_REG_P (operands[0]) && !TUNE_68040)
- return MOTOROLA ? "lea (%c1,%0),%0" : "lea %0@(%c1),%0";
}
return "add%.w %1,%0";
-})
+}
+ [(set_attr "flags_valid" "noov")])
(define_insn "addqi3"
[(set (match_operand:QI 0 "nonimmediate_operand" "=m,d")
}
}
return "add%.b %2,%0";
-})
+}
+ [(set_attr "flags_valid" "noov")])
(define_insn ""
[(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+m,d"))
(clobber (match_scratch:SI 3 "=&d,X,a,?d"))]
"!TARGET_COLDFIRE"
{
- CC_STATUS_INIT;
if (ADDRESS_REG_P (operands[0]))
return "sub%.w %2,%0";
else if (ADDRESS_REG_P (operands[3]))
(const_int 32))))]
""
{
- CC_STATUS_INIT;
if (GET_CODE (operands[1]) == REG)
operands[1] = gen_rtx_REG (SImode, REGNO (operands[1]) + 1);
else
else
{
gcc_assert (GET_CODE (operands[0]) == MEM);
- CC_STATUS_INIT;
if (GET_CODE (XEXP (operands[0], 0)) == POST_INC)
{
operands[1]
return "sub%.l %R2,%1\;move%.l %0,%3\;subx%.l %2,%3\;move%.l %3,%0";
}
}
-})
+}
+ [(set (attr "flags_valid")
+ (if_then_else (match_operand 0 "register_operand")
+ (const_string "noov")
+ (const_string "no")))])
(define_insn "subsi3"
- [(set (match_operand:SI 0 "nonimmediate_operand" "=mda,m,d,a")
- (minus:SI (match_operand:SI 1 "general_operand" "0,0,0,0")
- (match_operand:SI 2 "general_src_operand" "I,dT,mSrT,mSrs")))]
+ [(set (match_operand:SI 0 "nonimmediate_operand" "=md,ma,m,d,a")
+ (minus:SI (match_operand:SI 1 "general_operand" "0,0,0,0,0")
+ (match_operand:SI 2 "general_src_operand" "I,I,dT,mSrT,mSrs")))]
""
"@
+ subq%.l %2, %0
subq%.l %2, %0
sub%.l %2,%0
sub%.l %2,%0
sub%.l %2,%0"
- [(set_attr "type" "aluq_l,alu_l,alu_l,alu_l")
- (set_attr "opy" "2")])
+ [(set_attr "type" "aluq_l,aluq_l,alu_l,alu_l,alu_l")
+ (set_attr "opy" "2")
+ (set_attr "flags_valid" "noov,unchanged,noov,noov,unchanged")])
(define_insn ""
[(set (match_operand:SI 0 "nonimmediate_operand" "=a")
(minus:HI (match_operand:HI 1 "general_operand" "0,0")
(match_operand:HI 2 "general_src_operand" "dn,rmSn")))]
"!TARGET_COLDFIRE"
- "sub%.w %2,%0")
+ "sub%.w %2,%0"
+ [(set_attr "flags_valid" "noov")])
(define_insn ""
[(set (strict_low_part (match_operand:HI 0 "nonimmediate_operand" "+m,d"))
(minus:HI (match_dup 0)
(match_operand:HI 1 "general_src_operand" "dn,rmSn")))]
"!TARGET_COLDFIRE"
- "sub%.w %1,%0")
+ "sub%.w %1,%0"
+ [(set_attr "flags_valid" "noov")])
(define_insn "subqi3"
[(set (match_operand:QI 0 "nonimmediate_operand" "=m,d")
(minus:QI (match_operand:QI 1 "general_operand" "0,0")
(match_operand:QI 2 "general_src_operand" "dn,dmSn")))]
"!TARGET_COLDFIRE"
- "sub%.b %2,%0")
+ "sub%.b %2,%0"
+ [(set_attr "flags_valid" "noov")])
(define_insn ""
[(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+m,d"))
(minus:QI (match_dup 0)
(match_operand:QI 1 "general_src_operand" "dn,dmSn")))]
"!TARGET_COLDFIRE"
- "sub%.b %1,%0")
+ "sub%.b %1,%0"
+ [(set_attr "flags_valid" "noov")])
(define_expand "sub<mode>3"
[(set (match_operand:FP 0 "nonimmediate_operand" "")
(const_int 32))))
(clobber (match_operand:SI 1 "register_operand" "=d"))]
"TARGET_68020 && !TUNE_68060 && !TARGET_COLDFIRE"
-{
- CC_STATUS_INIT;
- return "mulu%.l %3,%0:%1";
-})
+ "mulu%.l %3,%0:%1")
(define_insn "const_umulsi3_highpart"
[(set (match_operand:SI 0 "register_operand" "=d")
(const_int 32))))
(clobber (match_operand:SI 1 "register_operand" "=d"))]
"TARGET_68020 && !TUNE_68060 && !TARGET_COLDFIRE"
-{
- CC_STATUS_INIT;
- return "mulu%.l %3,%0:%1";
-})
+ "mulu%.l %3,%0:%1")
(define_expand "smulsi3_highpart"
[(parallel
(const_int 32))))
(clobber (match_operand:SI 1 "register_operand" "=d"))]
"TARGET_68020 && !TUNE_68060 && !TARGET_COLDFIRE"
-{
- CC_STATUS_INIT;
- return "muls%.l %3,%0:%1";
-})
+ "muls%.l %3,%0:%1")
(define_insn "const_smulsi3_highpart"
[(set (match_operand:SI 0 "register_operand" "=d")
(const_int 32))))
(clobber (match_operand:SI 1 "register_operand" "=d"))]
"TARGET_68020 && !TUNE_68060 && !TARGET_COLDFIRE"
-{
- CC_STATUS_INIT;
- return "muls%.l %3,%0:%1";
-})
+ "muls%.l %3,%0:%1")
(define_expand "mul<mode>3"
[(set (match_operand:FP 0 "nonimmediate_operand" "")
(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"
{
(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"
{
(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"
{
(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"
{
})
(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"
{
"extl %0\;divs %2,%0",
operands);
if (!find_reg_note(insn, REG_UNUSED, operands[3]))
- {
- CC_STATUS_INIT;
- return "move%.l %0,%3\;swap %3";
- }
+ return "move%.l %0,%3\;swap %3";
else
return "";
})
(define_insn "udivmodhi4"
- [(set (match_operand:HI 0 "nonimmediate_operand" "=d")
+ [(set (match_operand:HI 0 "register_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"
{
operands);
if (!find_reg_note(insn, REG_UNUSED, operands[3]))
- {
- CC_STATUS_INIT;
- return "move%.l %0,%3\;swap %3";
- }
+ return "move%.l %0,%3\;swap %3";
else
return "";
})
"!TARGET_COLDFIRE"
{
return output_andsi3 (operands);
-})
+}
+ [(set_attr "flags_valid" "set")])
(define_insn "andsi3_5200"
[(set (match_operand:SI 0 "not_sp_operand" "=m,d")
(and:HI (match_operand:HI 1 "general_operand" "%0,0")
(match_operand:HI 2 "general_src_operand" "dn,dmSn")))]
"!TARGET_COLDFIRE"
- "and%.w %2,%0")
+ "and%.w %2,%0"
+ [(set_attr "flags_valid" "yes")])
(define_insn ""
[(set (strict_low_part (match_operand:HI 0 "nonimmediate_operand" "+m,d"))
(and:HI (match_dup 0)
(match_operand:HI 1 "general_src_operand" "dn,dmSn")))]
"!TARGET_COLDFIRE"
- "and%.w %1,%0")
+ "and%.w %1,%0"
+ [(set_attr "flags_valid" "yes")])
(define_insn ""
[(set (strict_low_part (match_operand:HI 0 "nonimmediate_operand" "+m,d"))
(and:HI (match_operand:HI 1 "general_src_operand" "dn,dmSn")
(match_dup 0)))]
"!TARGET_COLDFIRE"
- "and%.w %1,%0")
+ "and%.w %1,%0"
+ [(set_attr "flags_valid" "yes")])
(define_insn "andqi3"
[(set (match_operand:QI 0 "nonimmediate_operand" "=m,d")
(and:QI (match_operand:QI 1 "general_operand" "%0,0")
(match_operand:QI 2 "general_src_operand" "dn,dmSn")))]
"!TARGET_COLDFIRE"
- "and%.b %2,%0")
+ "and%.b %2,%0"
+ [(set_attr "flags_valid" "yes")])
(define_insn ""
[(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+m,d"))
(and:QI (match_dup 0)
(match_operand:QI 1 "general_src_operand" "dn,dmSn")))]
"!TARGET_COLDFIRE"
- "and%.b %1,%0")
+ "and%.b %1,%0"
+ [(set_attr "flags_valid" "yes")])
(define_insn ""
[(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+m,d"))
{
int byte_mode;
- CC_STATUS_INIT;
if (GET_CODE (operands[0]) == REG)
operands[0] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1);
else
"! TARGET_COLDFIRE"
{
return output_iorsi3 (operands);
-})
+}
+ [(set_attr "flags_valid" "set")])
(define_insn "iorsi3_5200"
[(set (match_operand:SI 0 "nonimmediate_operand" "=m,d")
"TARGET_COLDFIRE"
{
return output_iorsi3 (operands);
-})
+}
+ [(set_attr "flags_valid" "set")])
(define_insn "iorhi3"
[(set (match_operand:HI 0 "nonimmediate_operand" "=m,d")
(ior:HI (match_operand:HI 1 "general_src_operand" "dn,dmSn")
(match_dup 0)))]
"!TARGET_COLDFIRE"
- "or%.w %1,%0")
+ "or%.w %1,%0"
+ [(set_attr "flags_valid" "yes")])
(define_insn "iorqi3"
[(set (match_operand:QI 0 "nonimmediate_operand" "=m,d")
(ior:QI (match_operand:QI 1 "general_operand" "%0,0")
(match_operand:QI 2 "general_src_operand" "dn,dmSn")))]
"!TARGET_COLDFIRE"
- "or%.b %2,%0")
+ "or%.b %2,%0"
+ [(set_attr "flags_valid" "yes")])
(define_insn ""
[(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+m,d"))
(ior:QI (match_dup 0)
(match_operand:QI 1 "general_src_operand" "dn,dmSn")))]
"!TARGET_COLDFIRE"
- "or%.b %1,%0")
+ "or%.b %1,%0"
+ [(set_attr "flags_valid" "yes")])
(define_insn ""
[(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+m,d"))
(ior:QI (match_operand:QI 1 "general_src_operand" "dn,dmSn")
(match_dup 0)))]
"!TARGET_COLDFIRE"
- "or%.b %1,%0")
+ "or%.b %1,%0"
+ [(set_attr "flags_valid" "yes")])
;; On all 68k models, this makes faster code in a special case.
;; See also ashlsi_16, ashrsi_16 and lshrsi_16.
(const_int 16))))]
""
{
- CC_STATUS_INIT;
if (GET_CODE (operands[2]) != REG)
operands[2] = adjust_address (operands[2], HImode, 2);
if (GET_CODE (operands[2]) != REG
{
int byte_mode;
- CC_STATUS_INIT;
byte_mode = (GET_MODE (operands[1]) == QImode);
if (GET_CODE (operands[0]) == MEM)
operands[0] = adjust_address (operands[0], byte_mode ? QImode : HImode,
"!TARGET_COLDFIRE"
{
return output_xorsi3 (operands);
-})
+}
+ [(set_attr "flags_valid" "set")])
(define_insn "xorsi3_5200"
[(set (match_operand:SI 0 "nonimmediate_operand" "=dm,d")
"TARGET_COLDFIRE"
{
return output_xorsi3 (operands);
-})
+}
+ [(set_attr "flags_valid" "set")])
(define_insn "xorhi3"
[(set (match_operand:HI 0 "nonimmediate_operand" "=dm")
(xor:HI (match_operand:HI 1 "general_operand" "%0")
(match_operand:HI 2 "general_operand" "dn")))]
"!TARGET_COLDFIRE"
- "eor%.w %2,%0")
+ "eor%.w %2,%0"
+ [(set_attr "flags_valid" "yes")])
(define_insn ""
[(set (strict_low_part (match_operand:HI 0 "nonimmediate_operand" "+dm"))
(xor:HI (match_dup 0)
(match_operand:HI 1 "general_operand" "dn")))]
"!TARGET_COLDFIRE"
- "eor%.w %1,%0")
+ "eor%.w %1,%0"
+ [(set_attr "flags_valid" "yes")])
(define_insn ""
[(set (strict_low_part (match_operand:HI 0 "nonimmediate_operand" "+dm"))
(xor:HI (match_operand:HI 1 "general_operand" "dn")
(match_dup 0)))]
"!TARGET_COLDFIRE"
- "eor%.w %1,%0")
+ "eor%.w %1,%0"
+ [(set_attr "flags_valid" "yes")])
(define_insn "xorqi3"
[(set (match_operand:QI 0 "nonimmediate_operand" "=dm")
(xor:QI (match_operand:QI 1 "general_operand" "%0")
(match_operand:QI 2 "general_operand" "dn")))]
"!TARGET_COLDFIRE"
- "eor%.b %2,%0")
+ "eor%.b %2,%0"
+ [(set_attr "flags_valid" "yes")])
(define_insn ""
[(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+dm"))
(xor:QI (match_dup 0)
(match_operand:QI 1 "general_operand" "dn")))]
"!TARGET_COLDFIRE"
- "eor%.b %1,%0")
+ "eor%.b %1,%0"
+ [(set_attr "flags_valid" "yes")])
(define_insn ""
[(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+dm"))
(xor:QI (match_operand:QI 1 "general_operand" "dn")
(match_dup 0)))]
"!TARGET_COLDFIRE"
- "eor%.b %1,%0")
+ "eor%.b %1,%0"
+ [(set_attr "flags_valid" "yes")])
\f
;; negation instructions
(neg:SI (match_operand:SI 1 "general_operand" "0")))]
"!TARGET_COLDFIRE"
"neg%.l %0"
- [(set_attr "type" "neg_l")])
+ [(set_attr "type" "neg_l")
+ (set_attr "flags_valid" "noov")])
(define_insn "negsi2_5200"
[(set (match_operand:SI 0 "nonimmediate_operand" "=d")
(neg:SI (match_operand:SI 1 "general_operand" "0")))]
"TARGET_COLDFIRE"
"neg%.l %0"
- [(set_attr "type" "neg_l")])
+ [(set_attr "type" "neg_l")
+ (set_attr "flags_valid" "noov")])
(define_insn "neghi2"
[(set (match_operand:HI 0 "nonimmediate_operand" "=dm")
(neg:HI (match_operand:HI 1 "general_operand" "0")))]
"!TARGET_COLDFIRE"
- "neg%.w %0")
+ "neg%.w %0"
+ [(set_attr "flags_valid" "noov")])
(define_insn ""
[(set (strict_low_part (match_operand:HI 0 "nonimmediate_operand" "+dm"))
(neg:HI (match_dup 0)))]
"!TARGET_COLDFIRE"
- "neg%.w %0")
+ "neg%.w %0"
+ [(set_attr "flags_valid" "noov")])
(define_insn "negqi2"
[(set (match_operand:QI 0 "nonimmediate_operand" "=dm")
(neg:QI (match_operand:QI 1 "general_operand" "0")))]
"!TARGET_COLDFIRE"
- "neg%.b %0")
+ "neg%.b %0"
+ [(set_attr "flags_valid" "noov")])
(define_insn ""
[(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+dm"))
(neg:QI (match_dup 0)))]
"!TARGET_COLDFIRE"
- "neg%.b %0")
+ "neg%.b %0"
+ [(set_attr "flags_valid" "noov")])
;; If using software floating point, just flip the sign bit.
[(set (match_operand:SI 0 "register_operand" "=d")
(clz:SI (match_operand:SI 1 "general_operand" "do")))]
"TARGET_68020 && TARGET_BITFIELD"
-{
- CC_STATUS_INIT;
- return "bfffo %1{#0:#0},%0";
-})
+ "bfffo %1{#0:#0},%0")
;; ColdFire ff1 instruction implements clz.
(define_insn "*clzsi2_cf"
[(set (match_operand:SI 0 "register_operand" "=d")
(clz:SI (match_operand:SI 1 "register_operand" "0")))]
"ISA_HAS_FF1"
-{
- CC_STATUS_INIT;
- return "ff1 %0";
-}
+ "ff1 %0"
[(set_attr "type" "ext")])
\f
;; one complement instructions
[(set (match_operand:SI 0 "nonimmediate_operand" "=dm")
(not:SI (match_operand:SI 1 "general_operand" "0")))]
"!TARGET_COLDFIRE"
- "not%.l %0")
+ "not%.l %0"
+ [(set_attr "flags_valid" "yes")])
(define_insn "one_cmplsi2_5200"
[(set (match_operand:SI 0 "nonimmediate_operand" "=d")
[(set (match_operand:HI 0 "nonimmediate_operand" "=dm")
(not:HI (match_operand:HI 1 "general_operand" "0")))]
"!TARGET_COLDFIRE"
- "not%.w %0")
+ "not%.w %0"
+ [(set_attr "flags_valid" "yes")])
(define_insn ""
[(set (strict_low_part (match_operand:HI 0 "nonimmediate_operand" "+dm"))
(not:HI (match_dup 0)))]
"!TARGET_COLDFIRE"
- "not%.w %0")
+ "not%.w %0"
+ [(set_attr "flags_valid" "yes")])
(define_insn "one_cmplqi2"
[(set (match_operand:QI 0 "nonimmediate_operand" "=dm")
(not:QI (match_operand:QI 1 "general_operand" "0")))]
"!TARGET_COLDFIRE"
- "not%.b %0")
+ "not%.b %0"
+ [(set_attr "flags_valid" "yes")])
(define_insn ""
[(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+dm"))
(not:QI (match_dup 0)))]
"!TARGET_COLDFIRE"
- "not%.b %0")
+ "not%.b %0"
+ [(set_attr "flags_valid" "yes")])
\f
;; arithmetic shift instructions
;; We don't need the shift memory by 1 bit instruction
(clobber (match_scratch:SI 2 "=a,X"))]
""
{
- CC_STATUS_INIT;
if (GET_CODE (operands[0]) == MEM)
{
if (GET_CODE (XEXP (operands[0], 0)) == PRE_DEC)
(ashift:SI (match_operand:SI 1 "register_operand" "0")
(const_int 16)))]
"!TUNE_68060"
-{
- CC_STATUS_INIT;
- return "swap %0\;clr%.w %0";
-})
+ "swap %0\;clr%.w %0")
;; ashift patterns : use lsl instead of asl, because lsl always clears the
-;; overflow bit, so we must not set CC_NO_OVERFLOW.
+;; overflow bit, allowing more comparisons.
;; On the 68000, this makes faster code in a special case.
&& INTVAL (operands[2]) > 16
&& INTVAL (operands[2]) <= 24"
{
- CC_STATUS_INIT;
-
operands[2] = GEN_INT (INTVAL (operands[2]) - 16);
return "lsl%.w %2,%0\;swap %0\;clr%.w %0";
})
""
{
if (operands[2] == const1_rtx)
- {
- cc_status.flags = CC_NO_OVERFLOW;
- return "add%.l %0,%0";
- }
+ return "add%.l %0,%0";
return "lsl%.l %2,%0";
-})
+}
+ [(set (attr "flags_valid")
+ (if_then_else (match_operand 2 "const1_operand")
+ (const_string "noov")
+ (const_string "yes")))])
(define_insn "ashlhi3"
[(set (match_operand:HI 0 "register_operand" "=d")
(ashift:HI (match_operand:HI 1 "register_operand" "0")
(match_operand:HI 2 "general_operand" "dI")))]
"!TARGET_COLDFIRE"
- "lsl%.w %2,%0")
+ "lsl%.w %2,%0"
+ [(set_attr "flags_valid" "yes")])
(define_insn ""
[(set (strict_low_part (match_operand:HI 0 "register_operand" "+d"))
(ashift:HI (match_dup 0)
(match_operand:HI 1 "general_operand" "dI")))]
"!TARGET_COLDFIRE"
- "lsl%.w %1,%0")
+ "lsl%.w %1,%0"
+ [(set_attr "flags_valid" "yes")])
(define_insn "ashlqi3"
[(set (match_operand:QI 0 "register_operand" "=d")
(ashift:QI (match_operand:QI 1 "register_operand" "0")
(match_operand:QI 2 "general_operand" "dI")))]
"!TARGET_COLDFIRE"
- "lsl%.b %2,%0")
+ "lsl%.b %2,%0"
+ [(set_attr "flags_valid" "yes")])
(define_insn ""
[(set (strict_low_part (match_operand:QI 0 "register_operand" "+d"))
(ashift:QI (match_dup 0)
(match_operand:QI 1 "general_operand" "dI")))]
"!TARGET_COLDFIRE"
- "lsl%.b %1,%0")
+ "lsl%.b %1,%0"
+ [(set_attr "flags_valid" "yes")])
;; On most 68k models, this makes faster code in a special case.
"!TARGET_COLDFIRE"
{
operands[1] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1);
- CC_STATUS_INIT;
return "asr%.l #1,%0\;roxr%.l #1,%1";
})
(const_int 32)))]
""
{
- CC_STATUS_INIT;
if (TARGET_68020)
return "move%.l %1,%R0\;smi %0\;extb%.l %0";
else
(clobber (match_scratch:SI 2 "=d,d"))]
""
{
- CC_STATUS_INIT;
operands[3] = adjust_address (operands[0], SImode,
which_alternative == 0 ? 4 : 0);
operands[0] = adjust_address (operands[0], SImode, 0);
|| (INTVAL (operands[2]) > 32 && INTVAL (operands[2]) <= 63))"
{
operands[1] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1);
- CC_STATUS_INIT;
if (INTVAL (operands[2]) == 48)
return "swap %0\;ext%.l %0\;move%.l %0,%1\;smi %0\;ext%.w %0";
if (INTVAL (operands[2]) == 31)
""
"asr%.l %2,%0"
[(set_attr "type" "shift")
- (set_attr "opy" "2")])
+ (set_attr "opy" "2")
+ (set_attr "flags_valid" "noov")])
(define_insn "ashrhi3"
[(set (match_operand:HI 0 "register_operand" "=d")
(ashiftrt:HI (match_operand:HI 1 "register_operand" "0")
(match_operand:HI 2 "general_operand" "dI")))]
"!TARGET_COLDFIRE"
- "asr%.w %2,%0")
+ "asr%.w %2,%0"
+ [(set_attr "flags_valid" "noov")])
(define_insn ""
[(set (strict_low_part (match_operand:HI 0 "register_operand" "+d"))
(ashiftrt:HI (match_dup 0)
(match_operand:HI 1 "general_operand" "dI")))]
"!TARGET_COLDFIRE"
- "asr%.w %1,%0")
+ "asr%.w %1,%0"
+ [(set_attr "flags_valid" "noov")])
(define_insn "ashrqi3"
[(set (match_operand:QI 0 "register_operand" "=d")
(ashiftrt:QI (match_operand:QI 1 "register_operand" "0")
(match_operand:QI 2 "general_operand" "dI")))]
"!TARGET_COLDFIRE"
- "asr%.b %2,%0")
+ "asr%.b %2,%0"
+ [(set_attr "flags_valid" "noov")])
(define_insn ""
[(set (strict_low_part (match_operand:QI 0 "register_operand" "+d"))
(ashiftrt:QI (match_dup 0)
(match_operand:QI 1 "general_operand" "dI")))]
"!TARGET_COLDFIRE"
- "asr%.b %1,%0")
+ "asr%.b %1,%0"
+ [(set_attr "flags_valid" "noov")])
\f
;; logical shift instructions
(const_int 1)))]
"!TARGET_COLDFIRE"
{
- CC_STATUS_INIT;
return "lsr%.l #1,%0\;roxr%.l #1,%R0";
})
(const_int 16)))]
"!TUNE_68060"
{
- CC_STATUS_INIT;
return "clr%.w %0\;swap %0";
})
""
"lsr%.l %2,%0"
[(set_attr "type" "shift")
- (set_attr "opy" "2")])
+ (set_attr "opy" "2")
+ (set_attr "flags_valid" "yes")])
(define_insn "lshrhi3"
[(set (match_operand:HI 0 "register_operand" "=d")
(lshiftrt:HI (match_operand:HI 1 "register_operand" "0")
(match_operand:HI 2 "general_operand" "dI")))]
"!TARGET_COLDFIRE"
- "lsr%.w %2,%0")
+ "lsr%.w %2,%0"
+ [(set_attr "flags_valid" "yes")])
(define_insn ""
[(set (strict_low_part (match_operand:HI 0 "register_operand" "+d"))
(lshiftrt:HI (match_dup 0)
(match_operand:HI 1 "general_operand" "dI")))]
"!TARGET_COLDFIRE"
- "lsr%.w %1,%0")
+ "lsr%.w %1,%0"
+ [(set_attr "flags_valid" "yes")])
(define_insn "lshrqi3"
[(set (match_operand:QI 0 "register_operand" "=d")
(lshiftrt:QI (match_operand:QI 1 "register_operand" "0")
(match_operand:QI 2 "general_operand" "dI")))]
"!TARGET_COLDFIRE"
- "lsr%.b %2,%0")
+ "lsr%.b %2,%0"
+ [(set_attr "flags_valid" "yes")])
(define_insn ""
[(set (strict_low_part (match_operand:QI 0 "register_operand" "+d"))
(lshiftrt:QI (match_dup 0)
(match_operand:QI 1 "general_operand" "dI")))]
"!TARGET_COLDFIRE"
- "lsr%.b %1,%0")
+ "lsr%.b %1,%0"
+ [(set_attr "flags_valid" "yes")])
\f
;; rotate instructions
(const_int 16)))]
""
"swap %0"
- [(set_attr "type" "shift")])
+ [(set_attr "type" "shift")
+ (set_attr "flags_valid" "yes")])
(define_insn "rotlsi3"
[(set (match_operand:SI 0 "register_operand" "=d")
}
else
return "rol%.l %2,%0";
-})
+}
+ [(set_attr "flags_valid" "yes")])
(define_insn "rotlhi3"
[(set (match_operand:HI 0 "register_operand" "=d")
}
else
return "rol%.w %2,%0";
-})
+}
+ [(set_attr "flags_valid" "yes")])
(define_insn "*rotlhi3_lowpart"
[(set (strict_low_part (match_operand:HI 0 "register_operand" "+d"))
}
else
return "rol%.w %1,%0";
-})
+}
+ [(set_attr "flags_valid" "yes")])
(define_insn "rotlqi3"
[(set (match_operand:QI 0 "register_operand" "=d")
}
else
return "rol%.b %2,%0";
-})
+}
+ [(set_attr "flags_valid" "yes")])
(define_insn "*rotlqi3_lowpart"
[(set (strict_low_part (match_operand:QI 0 "register_operand" "+d"))
}
else
return "rol%.b %1,%0";
-})
+}
+ [(set_attr "flags_valid" "yes")])
(define_insn "rotrsi3"
[(set (match_operand:SI 0 "register_operand" "=d")
(rotatert:SI (match_operand:SI 1 "register_operand" "0")
(match_operand:SI 2 "general_operand" "dI")))]
"!TARGET_COLDFIRE"
- "ror%.l %2,%0")
+ "ror%.l %2,%0"
+ [(set_attr "flags_valid" "yes")])
(define_insn "rotrhi3"
[(set (match_operand:HI 0 "register_operand" "=d")
(rotatert:QI (match_operand:QI 1 "register_operand" "0")
(match_operand:QI 2 "general_operand" "dI")))]
"!TARGET_COLDFIRE"
- "ror%.b %2,%0")
+ "ror%.b %2,%0"
+ [(set_attr "flags_valid" "yes")])
(define_insn ""
[(set (strict_low_part (match_operand:QI 0 "register_operand" "+d"))
(rotatert:QI (match_dup 0)
(match_operand:QI 1 "general_operand" "dI")))]
"!TARGET_COLDFIRE"
- "ror%.b %1,%0")
+ "ror%.b %1,%0"
+ [(set_attr "flags_valid" "yes")])
(define_expand "bswapsi2"
[(set (match_operand:SI 0 "register_operand")
(match_operand:SI 1 "general_operand" "d")) 3)
(match_dup 0)))]
""
-{
- CC_STATUS_INIT;
- return "bset %1,%0";
-}
+ "bset %1,%0"
[(set_attr "type" "bitrw")])
;; set bit, bit number is (sign/zero)_extended from HImode/QImode
[(match_operand 1 "general_operand" "d")])) 3)
(match_dup 0)))]
""
-{
- CC_STATUS_INIT;
- return "bset %1,%0";
-}
+ "bset %1,%0"
[(set_attr "type" "bitrw")])
(define_insn "*bsetdreg"
(const_int 31)))
(match_operand:SI 2 "register_operand" "0")))]
""
-{
- CC_STATUS_INIT;
- return "bset %1,%0";
-}
+ "bset %1,%0"
[(set_attr "type" "bitrw")])
(define_insn "*bchgdreg"
(const_int 31)))
(match_operand:SI 2 "register_operand" "0")))]
""
-{
- CC_STATUS_INIT;
- return "bchg %1,%0";
-}
+ "bchg %1,%0"
[(set_attr "type" "bitrw")])
(define_insn "*bclrdreg"
(const_int 31)))
(match_operand:SI 2 "register_operand" "0")))]
""
-{
- CC_STATUS_INIT;
- return "bclr %1,%0";
-}
+ "bclr %1,%0"
[(set_attr "type" "bitrw")])
;; clear bit, bit number is int
(match_operand:SI 1 "general_operand" "d")))
(const_int 0))]
""
-{
- CC_STATUS_INIT;
- return "bclr %1,%0";
-}
+ "bclr %1,%0"
[(set_attr "type" "bitrw")])
;; clear bit, bit number is (sign/zero)_extended from HImode/QImode
[(match_operand 1 "general_operand" "d")])))
(const_int 0))]
""
-{
- CC_STATUS_INIT;
- return "bclr %1,%0";
-}
+ "bclr %1,%0"
[(set_attr "type" "bitrw")])
;; Special cases of bit-field insns which we should
&& (INTVAL (operands[2]) == 8 || INTVAL (operands[2]) == 16)
&& INTVAL (operands[3]) % INTVAL (operands[2]) == 0"
{
- cc_status.flags |= CC_NOT_NEGATIVE;
if (INTVAL (operands[2]) + INTVAL (operands[3]) != 32)
return "bfextu %1{%b3:%b2},%0";
(zero_extract:SI (match_operand:SI 1 "general_operand" "")
(match_operand:SI 2 "const_int_operand" "")
(match_operand:SI 3 "const_int_operand" "")))]
- "TARGET_68020 && TARGET_BITFIELD"
- "")
-
-(define_insn "*extzv_bfextu_mem"
- [(set (match_operand:SI 0 "register_operand" "=d")
- (zero_extract:SI (match_operand:QI 1 "memory_operand" "o")
- (match_operand:SI 2 "nonmemory_operand" "dn")
- (match_operand:SI 3 "nonmemory_operand" "dn")))]
- "TARGET_68020 && TARGET_BITFIELD"
-{
- if (GET_CODE (operands[2]) == CONST_INT)
- {
- if (INTVAL (operands[2]) != 32)
- cc_status.flags |= CC_NOT_NEGATIVE;
- }
- else
- {
- CC_STATUS_INIT;
- }
- return "bfextu %1{%b3:%b2},%0";
-})
-
-(define_insn "*insv_bfchg_mem"
- [(set (zero_extract:SI (match_operand:QI 0 "memory_operand" "+o")
- (match_operand:SI 1 "nonmemory_operand" "dn")
- (match_operand:SI 2 "nonmemory_operand" "dn"))
- (xor:SI (zero_extract:SI (match_dup 0) (match_dup 1) (match_dup 2))
- (match_operand 3 "const_int_operand" "n")))]
- "TARGET_68020 && TARGET_BITFIELD
- && (INTVAL (operands[3]) == -1
- || (GET_CODE (operands[1]) == CONST_INT
- && (~ INTVAL (operands[3]) & ((1 << INTVAL (operands[1]))- 1)) == 0))"
-{
- CC_STATUS_INIT;
- return "bfchg %0{%b2:%b1}";
-})
-
-(define_insn "*insv_bfclr_mem"
- [(set (zero_extract:SI (match_operand:QI 0 "memory_operand" "+o")
- (match_operand:SI 1 "nonmemory_operand" "dn")
- (match_operand:SI 2 "nonmemory_operand" "dn"))
- (const_int 0))]
- "TARGET_68020 && TARGET_BITFIELD"
-{
- CC_STATUS_INIT;
- return "bfclr %0{%b2:%b1}";
-})
-
-(define_insn "*insv_bfset_mem"
- [(set (zero_extract:SI (match_operand:QI 0 "memory_operand" "+o")
- (match_operand:SI 1 "general_operand" "dn")
- (match_operand:SI 2 "general_operand" "dn"))
- (const_int -1))]
- "TARGET_68020 && TARGET_BITFIELD"
-{
- CC_STATUS_INIT;
- return "bfset %0{%b2:%b1}";
-})
-
-(define_expand "insv"
- [(set (zero_extract:SI (match_operand:SI 0 "nonimmediate_operand" "")
- (match_operand:SI 1 "const_int_operand" "")
- (match_operand:SI 2 "const_int_operand" ""))
- (match_operand:SI 3 "reg_or_pow2_m1_operand" ""))]
- "TARGET_68020 && TARGET_BITFIELD"
- "
-{
- /* Special case initializing a field to all ones. */
- if (GET_CODE (operands[3]) == CONST_INT)
- {
- if (exact_log2 (INTVAL (operands[3]) + 1) != INTVAL (operands[1]))
- operands[3] = force_reg (SImode, operands[3]);
- else
- operands[3] = constm1_rtx;
-
- }
-}")
-
-(define_insn "*insv_bfins_mem"
- [(set (zero_extract:SI (match_operand:QI 0 "memory_operand" "+o")
- (match_operand:SI 1 "nonmemory_operand" "dn")
- (match_operand:SI 2 "nonmemory_operand" "dn"))
- (match_operand:SI 3 "register_operand" "d"))]
- "TARGET_68020 && TARGET_BITFIELD"
- "bfins %3,%0{%b2:%b1}")
-
-;; Now recognize bit-field insns that operate on registers
-;; (or at least were intended to do so).
-
-(define_insn "*extv_bfexts_reg"
- [(set (match_operand:SI 0 "nonimmediate_operand" "=d")
- (sign_extract:SI (match_operand:SI 1 "register_operand" "d")
- (match_operand:SI 2 "const_int_operand" "n")
- (match_operand:SI 3 "const_int_operand" "n")))]
- "TARGET_68020 && TARGET_BITFIELD && IN_RANGE (INTVAL (operands[3]), 0, 31)"
- "bfexts %1{%b3:%b2},%0")
-
-(define_insn "*extv_bfextu_reg"
- [(set (match_operand:SI 0 "nonimmediate_operand" "=d")
- (zero_extract:SI (match_operand:SI 1 "register_operand" "d")
- (match_operand:SI 2 "const_int_operand" "n")
- (match_operand:SI 3 "const_int_operand" "n")))]
- "TARGET_68020 && TARGET_BITFIELD && IN_RANGE (INTVAL (operands[3]), 0, 31)"
-{
- if (GET_CODE (operands[2]) == CONST_INT)
- {
- if (INTVAL (operands[2]) != 32)
- cc_status.flags |= CC_NOT_NEGATIVE;
- }
- else
- {
- CC_STATUS_INIT;
- }
- return "bfextu %1{%b3:%b2},%0";
-})
-
-(define_insn "*insv_bfclr_reg"
- [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "+d")
- (match_operand:SI 1 "const_int_operand" "n")
- (match_operand:SI 2 "const_int_operand" "n"))
- (const_int 0))]
- "TARGET_68020 && TARGET_BITFIELD && IN_RANGE (INTVAL (operands[2]), 0, 31)"
-{
- CC_STATUS_INIT;
- return "bfclr %0{%b2:%b1}";
-})
-
-(define_insn "*insv_bfset_reg"
- [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "+d")
- (match_operand:SI 1 "const_int_operand" "n")
- (match_operand:SI 2 "const_int_operand" "n"))
- (const_int -1))]
- "TARGET_68020 && TARGET_BITFIELD && IN_RANGE (INTVAL (operands[2]), 0, 31)"
-{
- CC_STATUS_INIT;
- return "bfset %0{%b2:%b1}";
-})
-
-(define_insn "*insv_bfins_reg"
- [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "+d")
- (match_operand:SI 1 "const_int_operand" "n")
- (match_operand:SI 2 "const_int_operand" "n"))
- (match_operand:SI 3 "register_operand" "d"))]
- "TARGET_68020 && TARGET_BITFIELD && IN_RANGE (INTVAL (operands[2]), 0, 31)"
-{
-#if 0
- /* These special cases are now recognized by a specific pattern. */
- if (GET_CODE (operands[1]) == CONST_INT && GET_CODE (operands[2]) == CONST_INT
- && INTVAL (operands[1]) == 16 && INTVAL (operands[2]) == 16)
- return "move%.w %3,%0";
- if (GET_CODE (operands[1]) == CONST_INT && GET_CODE (operands[2]) == CONST_INT
- && INTVAL (operands[1]) == 24 && INTVAL (operands[2]) == 8)
- return "move%.b %3,%0";
-#endif
- return "bfins %3,%0{%b2:%b1}";
-})
-\f
-;; Special patterns for optimizing bit-field instructions.
-
-(define_insn "*tst_bftst_mem"
- [(set (cc0)
- (compare (zero_extract:SI (match_operand:QI 0 "memory_operand" "o")
- (match_operand:SI 1 "const_int_operand" "n")
- (match_operand:SI 2 "general_operand" "dn"))
- (const_int 0)))]
- "TARGET_68020 && TARGET_BITFIELD"
-{
- if (operands[1] == const1_rtx
- && GET_CODE (operands[2]) == CONST_INT)
- {
- int width = GET_CODE (operands[0]) == REG ? 31 : 7;
- return output_btst (operands,
- GEN_INT (width - INTVAL (operands[2])),
- operands[0], insn, 1000);
- /* Pass 1000 as SIGNPOS argument so that btst will
- not think we are testing the sign bit for an `and'
- and assume that nonzero implies a negative result. */
- }
- if (INTVAL (operands[1]) != 32)
- cc_status.flags = CC_NOT_NEGATIVE;
- return "bftst %0{%b2:%b1}";
-})
-
-
-;;; now handle the register cases
-(define_insn "*tst_bftst_reg"
- [(set (cc0)
- (compare (zero_extract:SI (match_operand:SI 0 "register_operand" "d")
- (match_operand:SI 1 "const_int_operand" "n")
- (match_operand:SI 2 "general_operand" "dn"))
- (const_int 0)))]
- "TARGET_68020 && TARGET_BITFIELD
- && !(CONST_INT_P (operands[2]) && !IN_RANGE (INTVAL (operands[2]), 0, 31))"
-{
- if (operands[1] == const1_rtx
- && GET_CODE (operands[2]) == CONST_INT)
- {
- int width = GET_CODE (operands[0]) == REG ? 31 : 7;
- return output_btst (operands, GEN_INT (width - INTVAL (operands[2])),
- operands[0], insn, 1000);
- /* Pass 1000 as SIGNPOS argument so that btst will
- not think we are testing the sign bit for an `and'
- and assume that nonzero implies a negative result. */
- }
- if (INTVAL (operands[1]) != 32)
- cc_status.flags = CC_NOT_NEGATIVE;
- return "bftst %0{%b2:%b1}";
-})
-\f
-(define_insn "scc0_di"
- [(set (match_operand:QI 0 "nonimmediate_operand" "=dm")
- (match_operator 1 "ordered_comparison_operator"
- [(match_operand:DI 2 "general_operand" "ro") (const_int 0)]))]
- "! TARGET_COLDFIRE"
-{
- return output_scc_di (operands[1], operands[2], const0_rtx, operands[0]);
-})
-
-(define_insn "scc0_di_5200"
- [(set (match_operand:QI 0 "nonimmediate_operand" "=d")
- (match_operator 1 "ordered_comparison_operator"
- [(match_operand:DI 2 "general_operand" "ro") (const_int 0)]))]
- "TARGET_COLDFIRE"
-{
- return output_scc_di (operands[1], operands[2], const0_rtx, operands[0]);
-})
-
-(define_insn "scc_di"
- [(set (match_operand:QI 0 "nonimmediate_operand" "=dm,dm")
- (match_operator 1 "ordered_comparison_operator"
- [(match_operand:DI 2 "general_operand" "ro,r")
- (match_operand:DI 3 "general_operand" "r,ro")]))]
- "! TARGET_COLDFIRE"
-{
- return output_scc_di (operands[1], operands[2], operands[3], operands[0]);
-})
-
-(define_insn "scc_di_5200"
- [(set (match_operand:QI 0 "nonimmediate_operand" "=d,d")
- (match_operator 1 "ordered_comparison_operator"
- [(match_operand:DI 2 "general_operand" "ro,r")
- (match_operand:DI 3 "general_operand" "r,ro")]))]
- "TARGET_COLDFIRE"
-{
- return output_scc_di (operands[1], operands[2], operands[3], operands[0]);
-})
-
-;; Note that operand 0 of an SCC insn is supported in the hardware as
-;; memory, but we cannot allow it to be in memory in case the address
-;; needs to be reloaded.
-
-(define_insn ""
- [(set (match_operand:QI 0 "register_operand" "=d")
- (eq:QI (cc0) (const_int 0)))]
- ""
-{
- cc_status = cc_prev_status;
- OUTPUT_JUMP ("seq %0", "fseq %0", "seq %0");
-})
-
-(define_insn ""
- [(set (match_operand:QI 0 "register_operand" "=d")
- (ne:QI (cc0) (const_int 0)))]
- ""
-{
- cc_status = cc_prev_status;
- OUTPUT_JUMP ("sne %0", "fsne %0", "sne %0");
-})
-
-(define_insn ""
- [(set (match_operand:QI 0 "register_operand" "=d")
- (gt:QI (cc0) (const_int 0)))]
- ""
-{
- cc_status = cc_prev_status;
- OUTPUT_JUMP ("sgt %0", "fsgt %0", 0);
-})
-
-(define_insn ""
- [(set (match_operand:QI 0 "register_operand" "=d")
- (gtu:QI (cc0) (const_int 0)))]
- ""
-{
- cc_status = cc_prev_status;
- return "shi %0";
-})
-
-(define_insn ""
- [(set (match_operand:QI 0 "register_operand" "=d")
- (lt:QI (cc0) (const_int 0)))]
- ""
-{
- cc_status = cc_prev_status;
- OUTPUT_JUMP ("slt %0", "fslt %0", "smi %0");
-})
-
-(define_insn ""
- [(set (match_operand:QI 0 "register_operand" "=d")
- (ltu:QI (cc0) (const_int 0)))]
- ""
-{
- cc_status = cc_prev_status;
- return "scs %0";
-})
-
-(define_insn ""
- [(set (match_operand:QI 0 "register_operand" "=d")
- (ge:QI (cc0) (const_int 0)))]
- ""
-{
- cc_status = cc_prev_status;
- OUTPUT_JUMP ("sge %0", "fsge %0", "spl %0");
-})
-
-(define_insn "*scc"
- [(set (match_operand:QI 0 "register_operand" "=d")
- (geu:QI (cc0) (const_int 0)))]
- ""
-{
- cc_status = cc_prev_status;
- return "scc %0";
-}
- [(set_attr "type" "scc")])
-
-(define_insn ""
- [(set (match_operand:QI 0 "register_operand" "=d")
- (le:QI (cc0) (const_int 0)))]
- ""
-{
- cc_status = cc_prev_status;
- OUTPUT_JUMP ("sle %0", "fsle %0", 0);
-})
-
-(define_insn "*sls"
- [(set (match_operand:QI 0 "register_operand" "=d")
- (leu:QI (cc0) (const_int 0)))]
- ""
-{
- cc_status = cc_prev_status;
- return "sls %0";
-}
- [(set_attr "type" "scc")])
-
-(define_insn "*sordered_1"
- [(set (match_operand:QI 0 "register_operand" "=d")
- (ordered:QI (cc0) (const_int 0)))]
- "TARGET_68881 && !TUNE_68060"
-{
- cc_status = cc_prev_status;
- return "fsor %0";
-})
-
-(define_insn "*sunordered_1"
- [(set (match_operand:QI 0 "register_operand" "=d")
- (unordered:QI (cc0) (const_int 0)))]
- "TARGET_68881 && !TUNE_68060"
-{
- cc_status = cc_prev_status;
- return "fsun %0";
-})
-
-(define_insn "*suneq_1"
- [(set (match_operand:QI 0 "register_operand" "=d")
- (uneq:QI (cc0) (const_int 0)))]
- "TARGET_68881 && !TUNE_68060"
-{
- cc_status = cc_prev_status;
- return "fsueq %0";
-})
-
-(define_insn "*sunge_1"
- [(set (match_operand:QI 0 "register_operand" "=d")
- (unge:QI (cc0) (const_int 0)))]
- "TARGET_68881 && !TUNE_68060"
-{
- cc_status = cc_prev_status;
- return "fsuge %0";
-})
-
-(define_insn "*sungt_1"
- [(set (match_operand:QI 0 "register_operand" "=d")
- (ungt:QI (cc0) (const_int 0)))]
- "TARGET_68881 && !TUNE_68060"
-{
- cc_status = cc_prev_status;
- return "fsugt %0";
-})
-
-(define_insn "*sunle_1"
- [(set (match_operand:QI 0 "register_operand" "=d")
- (unle:QI (cc0) (const_int 0)))]
- "TARGET_68881 && !TUNE_68060"
-{
- cc_status = cc_prev_status;
- return "fsule %0";
-})
-
-(define_insn "*sunlt_1"
- [(set (match_operand:QI 0 "register_operand" "=d")
- (unlt:QI (cc0) (const_int 0)))]
- "TARGET_68881 && !TUNE_68060"
-{
- cc_status = cc_prev_status;
- return "fsult %0";
-})
-
-(define_insn "*sltgt_1"
- [(set (match_operand:QI 0 "register_operand" "=d")
- (ltgt:QI (cc0) (const_int 0)))]
- "TARGET_68881 && !TUNE_68060"
-{
- cc_status = cc_prev_status;
- return "fsogl %0";
-})
-
-(define_insn "*fsogt_1"
- [(set (match_operand:QI 0 "register_operand" "=d")
- (not:QI (unle:QI (cc0) (const_int 0))))]
- "TARGET_68881 && !TUNE_68060"
-{
- cc_status = cc_prev_status;
- return "fsogt %0";
-})
-
-(define_insn "*fsoge_1"
- [(set (match_operand:QI 0 "register_operand" "=d")
- (not:QI (unlt:QI (cc0) (const_int 0))))]
- "TARGET_68881 && !TUNE_68060"
-{
- cc_status = cc_prev_status;
- return "fsoge %0";
-})
-
-(define_insn "*fsolt_1"
- [(set (match_operand:QI 0 "register_operand" "=d")
- (not:QI (unge:QI (cc0) (const_int 0))))]
- "TARGET_68881 && !TUNE_68060"
-{
- cc_status = cc_prev_status;
- return "fsolt %0";
-})
-
-(define_insn "*fsole_1"
- [(set (match_operand:QI 0 "register_operand" "=d")
- (not:QI (ungt:QI (cc0) (const_int 0))))]
- "TARGET_68881 && !TUNE_68060"
-{
- cc_status = cc_prev_status;
- return "fsole %0";
-})
-\f
-;; Basic conditional jump instructions.
-
-(define_insn "beq0_di"
- [(set (pc)
- (if_then_else (eq (match_operand:DI 0 "general_operand" "d*a,o,<>")
- (const_int 0))
- (label_ref (match_operand 1 "" ",,"))
- (pc)))
- (clobber (match_scratch:SI 2 "=d,&d,d"))]
- ""
-{
- CC_STATUS_INIT;
- if (which_alternative == 2)
- return "move%.l %0,%2\;or%.l %0,%2\;jeq %l1";
- if ((cc_prev_status.value1
- && rtx_equal_p (cc_prev_status.value1, operands[0]))
- || (cc_prev_status.value2
- && rtx_equal_p (cc_prev_status.value2, operands[0])))
- {
- cc_status = cc_prev_status;
- return "jeq %l1";
- }
- if (GET_CODE (operands[0]) == REG)
- operands[3] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1);
- else
- operands[3] = adjust_address (operands[0], SImode, 4);
- if (! ADDRESS_REG_P (operands[0]))
- {
- if (reg_overlap_mentioned_p (operands[2], operands[0]))
- {
- if (reg_overlap_mentioned_p (operands[2], operands[3]))
- return "or%.l %0,%2\;jeq %l1";
- else
- return "or%.l %3,%2\;jeq %l1";
- }
- return "move%.l %0,%2\;or%.l %3,%2\;jeq %l1";
- }
- operands[4] = gen_label_rtx();
- if (TARGET_68020 || TARGET_COLDFIRE)
- output_asm_insn ("tst%.l %0\;jne %l4\;tst%.l %3\;jeq %l1", operands);
- else
- output_asm_insn ("cmp%.w #0,%0\;jne %l4\;cmp%.w #0,%3\;jeq %l1", operands);
- (*targetm.asm_out.internal_label) (asm_out_file, "L",
- CODE_LABEL_NUMBER (operands[4]));
- return "";
-})
-
-(define_insn "bne0_di"
- [(set (pc)
- (if_then_else (ne (match_operand:DI 0 "general_operand" "d,o,*a")
- (const_int 0))
- (label_ref (match_operand 1 "" ",,"))
- (pc)))
- (clobber (match_scratch:SI 2 "=d,&d,X"))]
- ""
-{
- if ((cc_prev_status.value1
- && rtx_equal_p (cc_prev_status.value1, operands[0]))
- || (cc_prev_status.value2
- && rtx_equal_p (cc_prev_status.value2, operands[0])))
- {
- cc_status = cc_prev_status;
- return "jne %l1";
- }
- CC_STATUS_INIT;
- if (GET_CODE (operands[0]) == REG)
- operands[3] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1);
- else
- operands[3] = adjust_address (operands[0], SImode, 4);
- if (!ADDRESS_REG_P (operands[0]))
- {
- if (reg_overlap_mentioned_p (operands[2], operands[0]))
- {
- if (reg_overlap_mentioned_p (operands[2], operands[3]))
- return "or%.l %0,%2\;jne %l1";
- else
- return "or%.l %3,%2\;jne %l1";
- }
- return "move%.l %0,%2\;or%.l %3,%2\;jne %l1";
- }
- if (TARGET_68020 || TARGET_COLDFIRE)
- return "tst%.l %0\;jne %l1\;tst%.l %3\;jne %l1";
- else
- return "cmp%.w #0,%0\;jne %l1\;cmp%.w #0,%3\;jne %l1";
-})
-
-(define_insn "bge0_di"
- [(set (pc)
- (if_then_else (ge (match_operand:DI 0 "general_operand" "ro")
- (const_int 0))
- (label_ref (match_operand 1 "" ""))
- (pc)))]
- ""
-{
- if ((cc_prev_status.value1
- && rtx_equal_p (cc_prev_status.value1, operands[0]))
- || (cc_prev_status.value2
- && rtx_equal_p (cc_prev_status.value2, operands[0])))
- {
- cc_status = cc_prev_status;
- return cc_status.flags & CC_REVERSED ? "jle %l1" : "jpl %l1";
- }
- CC_STATUS_INIT;
- if (TARGET_68020 || TARGET_COLDFIRE || ! ADDRESS_REG_P (operands[0]))
- output_asm_insn("tst%.l %0", operands);
- else
- {
- /* On an address reg, cmpw may replace cmpl. */
- output_asm_insn("cmp%.w #0,%0", operands);
- }
- return "jpl %l1";
-})
-
-(define_insn "blt0_di"
- [(set (pc)
- (if_then_else (lt (match_operand:DI 0 "general_operand" "ro")
- (const_int 0))
- (label_ref (match_operand 1 "" ""))
- (pc)))]
- ""
-{
- if ((cc_prev_status.value1
- && rtx_equal_p (cc_prev_status.value1, operands[0]))
- || (cc_prev_status.value2
- && rtx_equal_p (cc_prev_status.value2, operands[0])))
- {
- cc_status = cc_prev_status;
- return cc_status.flags & CC_REVERSED ? "jgt %l1" : "jmi %l1";
- }
- CC_STATUS_INIT;
- if (TARGET_68020 || TARGET_COLDFIRE || ! ADDRESS_REG_P (operands[0]))
- output_asm_insn("tst%.l %0", operands);
- else
- {
- /* On an address reg, cmpw may replace cmpl. */
- output_asm_insn("cmp%.w #0,%0", operands);
- }
- return "jmi %l1";
-})
-
-(define_insn "beq"
- [(set (pc)
- (if_then_else (eq (cc0)
- (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
-{
- OUTPUT_JUMP ("jeq %l0", "fjeq %l0", "jeq %l0");
-}
- [(set_attr "type" "bcc")])
-
-(define_insn "bne"
- [(set (pc)
- (if_then_else (ne (cc0)
- (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
-{
- OUTPUT_JUMP ("jne %l0", "fjne %l0", "jne %l0");
-}
- [(set_attr "type" "bcc")])
-
-(define_insn "bgt"
- [(set (pc)
- (if_then_else (gt (cc0)
- (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
-{
- if ((cc_status.flags & CC_OVERFLOW_UNUSABLE) != 0)
- {
- cc_status.flags &= ~CC_OVERFLOW_UNUSABLE;
- return 0;
- }
-
- OUTPUT_JUMP ("jgt %l0", "fjgt %l0", 0);
-}
- [(set_attr "type" "bcc")])
-
-(define_insn "bgtu"
- [(set (pc)
- (if_then_else (gtu (cc0)
- (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
-{
- if ((cc_status.flags & CC_OVERFLOW_UNUSABLE) != 0)
- {
- cc_status.flags &= ~CC_OVERFLOW_UNUSABLE;
- return 0;
- }
-
- return "jhi %l0";
-}
- [(set_attr "type" "bcc")])
-
-(define_insn "blt"
- [(set (pc)
- (if_then_else (lt (cc0)
- (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
-{
- if ((cc_status.flags & CC_OVERFLOW_UNUSABLE) != 0)
- {
- cc_status.flags &= ~CC_OVERFLOW_UNUSABLE;
- return 0;
- }
-
- OUTPUT_JUMP ("jlt %l0", "fjlt %l0", "jmi %l0");
-}
- [(set_attr "type" "bcc")])
-
-(define_insn "bltu"
- [(set (pc)
- (if_then_else (ltu (cc0)
- (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
-{
- if ((cc_status.flags & CC_OVERFLOW_UNUSABLE) != 0)
- {
- cc_status.flags &= ~CC_OVERFLOW_UNUSABLE;
- return 0;
- }
-
- return "jcs %l0";
-}
- [(set_attr "type" "bcc")])
-
-(define_insn "bge"
- [(set (pc)
- (if_then_else (ge (cc0)
- (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
-{
- if ((cc_status.flags & CC_OVERFLOW_UNUSABLE) != 0)
- {
- cc_status.flags &= ~CC_OVERFLOW_UNUSABLE;
- return 0;
- }
-
- OUTPUT_JUMP ("jge %l0", "fjge %l0", "jpl %l0");
-})
-
-(define_insn "bgeu"
- [(set (pc)
- (if_then_else (geu (cc0)
- (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
-{
- if ((cc_status.flags & CC_OVERFLOW_UNUSABLE) != 0)
- {
- cc_status.flags &= ~CC_OVERFLOW_UNUSABLE;
- return 0;
- }
-
- return "jcc %l0";
-}
- [(set_attr "type" "bcc")])
-
-(define_insn "ble"
- [(set (pc)
- (if_then_else (le (cc0)
- (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
-{
- if ((cc_status.flags & CC_OVERFLOW_UNUSABLE) != 0)
- {
- cc_status.flags &= ~CC_OVERFLOW_UNUSABLE;
- return 0;
- }
-
- OUTPUT_JUMP ("jle %l0", "fjle %l0", 0);
-}
- [(set_attr "type" "bcc")])
-
-(define_insn "bleu"
- [(set (pc)
- (if_then_else (leu (cc0)
- (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
-{
- if ((cc_status.flags & CC_OVERFLOW_UNUSABLE) != 0)
- {
- cc_status.flags &= ~CC_OVERFLOW_UNUSABLE;
- return 0;
- }
-
- return "jls %l0";
-}
- [(set_attr "type" "bcc")])
-
-(define_insn "bordered"
- [(set (pc)
- (if_then_else (ordered (cc0) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- "TARGET_HARD_FLOAT"
-{
- gcc_assert (cc_prev_status.flags & CC_IN_68881);
- return "fjor %l0";
-}
- [(set_attr "type" "fbcc")])
-
-(define_insn "bunordered"
- [(set (pc)
- (if_then_else (unordered (cc0) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- "TARGET_HARD_FLOAT"
-{
- gcc_assert (cc_prev_status.flags & CC_IN_68881);
- return "fjun %l0";
-}
- [(set_attr "type" "fbcc")])
-
-(define_insn "buneq"
- [(set (pc)
- (if_then_else (uneq (cc0) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- "TARGET_HARD_FLOAT"
-{
- gcc_assert (cc_prev_status.flags & CC_IN_68881);
- return "fjueq %l0";
-}
- [(set_attr "type" "fbcc")])
-
-(define_insn "bunge"
- [(set (pc)
- (if_then_else (unge (cc0) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- "TARGET_HARD_FLOAT"
-{
- gcc_assert (cc_prev_status.flags & CC_IN_68881);
- return "fjuge %l0";
-}
- [(set_attr "type" "fbcc")])
-
-(define_insn "bungt"
- [(set (pc)
- (if_then_else (ungt (cc0) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- "TARGET_HARD_FLOAT"
-{
- gcc_assert (cc_prev_status.flags & CC_IN_68881);
- return "fjugt %l0";
-}
- [(set_attr "type" "fbcc")])
-
-(define_insn "bunle"
- [(set (pc)
- (if_then_else (unle (cc0) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- "TARGET_HARD_FLOAT"
-{
- gcc_assert (cc_prev_status.flags & CC_IN_68881);
- return "fjule %l0";
-}
- [(set_attr "type" "fbcc")])
-
-(define_insn "bunlt"
- [(set (pc)
- (if_then_else (unlt (cc0) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- "TARGET_HARD_FLOAT"
-{
- gcc_assert (cc_prev_status.flags & CC_IN_68881);
- return "fjult %l0";
-}
- [(set_attr "type" "fbcc")])
-
-(define_insn "bltgt"
- [(set (pc)
- (if_then_else (ltgt (cc0) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- "TARGET_HARD_FLOAT"
-{
- gcc_assert (cc_prev_status.flags & CC_IN_68881);
- return "fjogl %l0";
-}
- [(set_attr "type" "fbcc")])
-\f
-;; Negated conditional jump instructions.
-
-(define_insn "*beq_rev"
- [(set (pc)
- (if_then_else (eq (cc0)
- (const_int 0))
- (pc)
- (label_ref (match_operand 0 "" ""))))]
- ""
-{
- OUTPUT_JUMP ("jne %l0", "fjne %l0", "jne %l0");
-}
- [(set_attr "type" "bcc")])
-
-(define_insn "*bne_rev"
- [(set (pc)
- (if_then_else (ne (cc0)
- (const_int 0))
- (pc)
- (label_ref (match_operand 0 "" ""))))]
- ""
-{
- OUTPUT_JUMP ("jeq %l0", "fjeq %l0", "jeq %l0");
-}
- [(set_attr "type" "bcc")])
-
-(define_insn "*bgt_rev"
- [(set (pc)
- (if_then_else (gt (cc0)
- (const_int 0))
- (pc)
- (label_ref (match_operand 0 "" ""))))]
- ""
-{
- if ((cc_status.flags & CC_OVERFLOW_UNUSABLE) != 0)
- {
- cc_status.flags &= ~CC_OVERFLOW_UNUSABLE;
- return 0;
- }
-
- OUTPUT_JUMP ("jle %l0", "fjngt %l0", 0);
-}
- [(set_attr "type" "bcc")])
-
-(define_insn "*bgtu_rev"
- [(set (pc)
- (if_then_else (gtu (cc0)
- (const_int 0))
- (pc)
- (label_ref (match_operand 0 "" ""))))]
- ""
-{
- if ((cc_status.flags & CC_OVERFLOW_UNUSABLE) != 0)
- {
- cc_status.flags &= ~CC_OVERFLOW_UNUSABLE;
- return 0;
- }
-
- return "jls %l0";
-}
- [(set_attr "type" "bcc")])
-
-(define_insn "*blt_rev"
- [(set (pc)
- (if_then_else (lt (cc0)
- (const_int 0))
- (pc)
- (label_ref (match_operand 0 "" ""))))]
- ""
-{
- if ((cc_status.flags & CC_OVERFLOW_UNUSABLE) != 0)
- {
- cc_status.flags &= ~CC_OVERFLOW_UNUSABLE;
- return 0;
- }
-
- OUTPUT_JUMP ("jge %l0", "fjnlt %l0", "jpl %l0");
-}
- [(set_attr "type" "bcc")])
-
-(define_insn "*bltu_rev"
- [(set (pc)
- (if_then_else (ltu (cc0)
- (const_int 0))
- (pc)
- (label_ref (match_operand 0 "" ""))))]
- ""
-{
- if ((cc_status.flags & CC_OVERFLOW_UNUSABLE) != 0)
- {
- cc_status.flags &= ~CC_OVERFLOW_UNUSABLE;
- return 0;
- }
-
- return "jcc %l0";
-}
- [(set_attr "type" "bcc")])
+ "TARGET_68020 && TARGET_BITFIELD"
+ "")
-(define_insn "*bge_rev"
- [(set (pc)
- (if_then_else (ge (cc0)
- (const_int 0))
- (pc)
- (label_ref (match_operand 0 "" ""))))]
- ""
+(define_insn "*extzv_bfextu_mem"
+ [(set (match_operand:SI 0 "register_operand" "=d")
+ (zero_extract:SI (match_operand:QI 1 "memory_operand" "o")
+ (match_operand:SI 2 "nonmemory_operand" "dn")
+ (match_operand:SI 3 "nonmemory_operand" "dn")))]
+ "TARGET_68020 && TARGET_BITFIELD"
{
- if ((cc_status.flags & CC_OVERFLOW_UNUSABLE) != 0)
- {
- cc_status.flags &= ~CC_OVERFLOW_UNUSABLE;
- return 0;
- }
+ return "bfextu %1{%b3:%b2},%0";
+})
- OUTPUT_JUMP ("jlt %l0", "fjnge %l0", "jmi %l0");
-}
- [(set_attr "type" "bcc")])
+(define_insn "*insv_bfchg_mem"
+ [(set (zero_extract:SI (match_operand:QI 0 "memory_operand" "+o")
+ (match_operand:SI 1 "nonmemory_operand" "dn")
+ (match_operand:SI 2 "nonmemory_operand" "dn"))
+ (xor:SI (zero_extract:SI (match_dup 0) (match_dup 1) (match_dup 2))
+ (match_operand 3 "const_int_operand" "n")))]
+ "TARGET_68020 && TARGET_BITFIELD
+ && (INTVAL (operands[3]) == -1
+ || (GET_CODE (operands[1]) == CONST_INT
+ && (~ INTVAL (operands[3]) & ((1 << INTVAL (operands[1]))- 1)) == 0))"
+{
+ return "bfchg %0{%b2:%b1}";
+})
-(define_insn "*bgeu_rev"
- [(set (pc)
- (if_then_else (geu (cc0)
- (const_int 0))
- (pc)
- (label_ref (match_operand 0 "" ""))))]
- ""
+(define_insn "*insv_bfclr_mem"
+ [(set (zero_extract:SI (match_operand:QI 0 "memory_operand" "+o")
+ (match_operand:SI 1 "nonmemory_operand" "dn")
+ (match_operand:SI 2 "nonmemory_operand" "dn"))
+ (const_int 0))]
+ "TARGET_68020 && TARGET_BITFIELD"
{
- if ((cc_status.flags & CC_OVERFLOW_UNUSABLE) != 0)
- {
- cc_status.flags &= ~CC_OVERFLOW_UNUSABLE;
- return 0;
- }
+ return "bfclr %0{%b2:%b1}";
+})
- return "jcs %l0";
-}
- [(set_attr "type" "bcc")])
+(define_insn "*insv_bfset_mem"
+ [(set (zero_extract:SI (match_operand:QI 0 "memory_operand" "+o")
+ (match_operand:SI 1 "general_operand" "dn")
+ (match_operand:SI 2 "general_operand" "dn"))
+ (const_int -1))]
+ "TARGET_68020 && TARGET_BITFIELD"
+{
+ return "bfset %0{%b2:%b1}";
+})
-(define_insn "*ble_rev"
- [(set (pc)
- (if_then_else (le (cc0)
- (const_int 0))
- (pc)
- (label_ref (match_operand 0 "" ""))))]
- ""
+(define_expand "insv"
+ [(set (zero_extract:SI (match_operand:SI 0 "nonimmediate_operand" "")
+ (match_operand:SI 1 "const_int_operand" "")
+ (match_operand:SI 2 "const_int_operand" ""))
+ (match_operand:SI 3 "reg_or_pow2_m1_operand" ""))]
+ "TARGET_68020 && TARGET_BITFIELD"
+ "
{
- if ((cc_status.flags & CC_OVERFLOW_UNUSABLE) != 0)
+ /* Special case initializing a field to all ones. */
+ if (GET_CODE (operands[3]) == CONST_INT)
{
- cc_status.flags &= ~CC_OVERFLOW_UNUSABLE;
- return 0;
+ if (exact_log2 (INTVAL (operands[3]) + 1) != INTVAL (operands[1]))
+ operands[3] = force_reg (SImode, operands[3]);
+ else
+ operands[3] = constm1_rtx;
+
}
+}")
- OUTPUT_JUMP ("jgt %l0", "fjnle %l0", 0);
-}
- [(set_attr "type" "bcc")])
+(define_insn "*insv_bfins_mem"
+ [(set (zero_extract:SI (match_operand:QI 0 "memory_operand" "+o")
+ (match_operand:SI 1 "nonmemory_operand" "dn")
+ (match_operand:SI 2 "nonmemory_operand" "dn"))
+ (match_operand:SI 3 "register_operand" "d"))]
+ "TARGET_68020 && TARGET_BITFIELD"
+ "bfins %3,%0{%b2:%b1}")
-(define_insn "*bleu_rev"
- [(set (pc)
- (if_then_else (leu (cc0)
- (const_int 0))
- (pc)
- (label_ref (match_operand 0 "" ""))))]
- ""
-{
- if ((cc_status.flags & CC_OVERFLOW_UNUSABLE) != 0)
- {
- cc_status.flags &= ~CC_OVERFLOW_UNUSABLE;
- return 0;
- }
+;; Now recognize bit-field insns that operate on registers
+;; (or at least were intended to do so).
- return "jhi %l0";
-}
- [(set_attr "type" "bcc")])
+(define_insn "*extv_bfexts_reg"
+ [(set (match_operand:SI 0 "nonimmediate_operand" "=d")
+ (sign_extract:SI (match_operand:SI 1 "register_operand" "d")
+ (match_operand:SI 2 "const_int_operand" "n")
+ (match_operand:SI 3 "const_int_operand" "n")))]
+ "TARGET_68020 && TARGET_BITFIELD && IN_RANGE (INTVAL (operands[3]), 0, 31)"
+ "bfexts %1{%b3:%b2},%0")
-(define_insn "*bordered_rev"
- [(set (pc)
- (if_then_else (ordered (cc0) (const_int 0))
- (pc)
- (label_ref (match_operand 0 "" ""))))]
- "TARGET_HARD_FLOAT"
+(define_insn "*extv_bfextu_reg"
+ [(set (match_operand:SI 0 "nonimmediate_operand" "=d")
+ (zero_extract:SI (match_operand:SI 1 "register_operand" "d")
+ (match_operand:SI 2 "const_int_operand" "n")
+ (match_operand:SI 3 "const_int_operand" "n")))]
+ "TARGET_68020 && TARGET_BITFIELD && IN_RANGE (INTVAL (operands[3]), 0, 31)"
{
- gcc_assert (cc_prev_status.flags & CC_IN_68881);
- return "fjun %l0";
-}
- [(set_attr "type" "fbcc")])
+ return "bfextu %1{%b3:%b2},%0";
+})
-(define_insn "*bunordered_rev"
- [(set (pc)
- (if_then_else (unordered (cc0) (const_int 0))
- (pc)
- (label_ref (match_operand 0 "" ""))))]
- "TARGET_HARD_FLOAT"
+(define_insn "*insv_bfclr_reg"
+ [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "+d")
+ (match_operand:SI 1 "const_int_operand" "n")
+ (match_operand:SI 2 "const_int_operand" "n"))
+ (const_int 0))]
+ "TARGET_68020 && TARGET_BITFIELD && IN_RANGE (INTVAL (operands[2]), 0, 31)"
{
- gcc_assert (cc_prev_status.flags & CC_IN_68881);
- return "fjor %l0";
-}
- [(set_attr "type" "fbcc")])
+ return "bfclr %0{%b2:%b1}";
+})
-(define_insn "*buneq_rev"
- [(set (pc)
- (if_then_else (uneq (cc0) (const_int 0))
- (pc)
- (label_ref (match_operand 0 "" ""))))]
- "TARGET_HARD_FLOAT"
+(define_insn "*insv_bfset_reg"
+ [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "+d")
+ (match_operand:SI 1 "const_int_operand" "n")
+ (match_operand:SI 2 "const_int_operand" "n"))
+ (const_int -1))]
+ "TARGET_68020 && TARGET_BITFIELD && IN_RANGE (INTVAL (operands[2]), 0, 31)"
{
- gcc_assert (cc_prev_status.flags & CC_IN_68881);
- return "fjogl %l0";
-}
- [(set_attr "type" "fbcc")])
+ return "bfset %0{%b2:%b1}";
+})
-(define_insn "*bunge_rev"
- [(set (pc)
- (if_then_else (unge (cc0) (const_int 0))
- (pc)
- (label_ref (match_operand 0 "" ""))))]
- "TARGET_HARD_FLOAT"
+(define_insn "*insv_bfins_reg"
+ [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "+d")
+ (match_operand:SI 1 "const_int_operand" "n")
+ (match_operand:SI 2 "const_int_operand" "n"))
+ (match_operand:SI 3 "register_operand" "d"))]
+ "TARGET_68020 && TARGET_BITFIELD && IN_RANGE (INTVAL (operands[2]), 0, 31)"
{
- gcc_assert (cc_prev_status.flags & CC_IN_68881);
- return "fjolt %l0";
-}
- [(set_attr "type" "fbcc")])
-
-(define_insn "*bungt_rev"
- [(set (pc)
- (if_then_else (ungt (cc0) (const_int 0))
- (pc)
- (label_ref (match_operand 0 "" ""))))]
- "TARGET_HARD_FLOAT"
+#if 0
+ /* These special cases are now recognized by a specific pattern. */
+ if (GET_CODE (operands[1]) == CONST_INT && GET_CODE (operands[2]) == CONST_INT
+ && INTVAL (operands[1]) == 16 && INTVAL (operands[2]) == 16)
+ return "move%.w %3,%0";
+ if (GET_CODE (operands[1]) == CONST_INT && GET_CODE (operands[2]) == CONST_INT
+ && INTVAL (operands[1]) == 24 && INTVAL (operands[2]) == 8)
+ return "move%.b %3,%0";
+#endif
+ return "bfins %3,%0{%b2:%b1}";
+})
+\f
+(define_insn "scc0_di"
+ [(set (match_operand:QI 0 "nonimmediate_operand" "=dm")
+ (match_operator 1 "ordered_comparison_operator"
+ [(match_operand:DI 2 "general_operand" "ro") (const_int 0)]))]
+ "! TARGET_COLDFIRE"
{
- gcc_assert (cc_prev_status.flags & CC_IN_68881);
- return "fjole %l0";
-}
- [(set_attr "type" "fbcc")])
+ return output_scc_di (operands[1], operands[2], const0_rtx, operands[0]);
+})
-(define_insn "*bunle_rev"
- [(set (pc)
- (if_then_else (unle (cc0) (const_int 0))
- (pc)
- (label_ref (match_operand 0 "" ""))))]
- "TARGET_HARD_FLOAT"
+(define_insn "scc0_di_5200"
+ [(set (match_operand:QI 0 "nonimmediate_operand" "=d")
+ (match_operator 1 "ordered_comparison_operator"
+ [(match_operand:DI 2 "general_operand" "ro") (const_int 0)]))]
+ "TARGET_COLDFIRE"
{
- gcc_assert (cc_prev_status.flags & CC_IN_68881);
- return "fjogt %l0";
-}
- [(set_attr "type" "fbcc")])
+ return output_scc_di (operands[1], operands[2], const0_rtx, operands[0]);
+})
-(define_insn "*bunlt_rev"
- [(set (pc)
- (if_then_else (unlt (cc0) (const_int 0))
- (pc)
- (label_ref (match_operand 0 "" ""))))]
- "TARGET_HARD_FLOAT"
+(define_insn "scc_di"
+ [(set (match_operand:QI 0 "nonimmediate_operand" "=dm,dm")
+ (match_operator 1 "ordered_comparison_operator"
+ [(match_operand:DI 2 "general_operand" "ro,r")
+ (match_operand:DI 3 "general_operand" "r,ro")]))]
+ "! TARGET_COLDFIRE"
{
- gcc_assert (cc_prev_status.flags & CC_IN_68881);
- return "fjoge %l0";
-}
- [(set_attr "type" "fbcc")])
+ return output_scc_di (operands[1], operands[2], operands[3], operands[0]);
+})
-(define_insn "*bltgt_rev"
- [(set (pc)
- (if_then_else (ltgt (cc0) (const_int 0))
- (pc)
- (label_ref (match_operand 0 "" ""))))]
- "TARGET_HARD_FLOAT"
+(define_insn "scc_di_5200"
+ [(set (match_operand:QI 0 "nonimmediate_operand" "=d,d")
+ (match_operator 1 "ordered_comparison_operator"
+ [(match_operand:DI 2 "general_operand" "ro,r")
+ (match_operand:DI 3 "general_operand" "r,ro")]))]
+ "TARGET_COLDFIRE"
{
- gcc_assert (cc_prev_status.flags & CC_IN_68881);
- return "fjueq %l0";
-}
- [(set_attr "type" "fbcc")])
+ return output_scc_di (operands[1], operands[2], operands[3], operands[0]);
+})
\f
;; Unconditional and other jump instructions
(define_insn "jump"
(const_int -1)))]
"!TARGET_COLDFIRE"
{
- CC_STATUS_INIT;
if (DATA_REG_P (operands[0]))
return "dbra %0,%l1";
if (GET_CODE (operands[0]) == MEM)
(const_int -1)))]
"!TARGET_COLDFIRE"
{
- CC_STATUS_INIT;
if (DATA_REG_P (operands[0]))
return "dbra %0,%l1\;clr%.w %0\;subq%.l #1,%0\;jcc %l1";
if (GET_CODE (operands[0]) == MEM)
(const_int -1)))]
"!TARGET_COLDFIRE && find_reg_note (insn, REG_NONNEG, 0)"
{
- CC_STATUS_INIT;
if (DATA_REG_P (operands[0]))
return "dbra %0,%l1";
if (GET_CODE (operands[0]) == MEM)
(const_int -1)))]
"!TARGET_COLDFIRE && find_reg_note (insn, REG_NONNEG, 0)"
{
- CC_STATUS_INIT;
if (DATA_REG_P (operands[0]))
return "dbra %0,%l1\;clr%.w %0\;subq%.l #1,%0\;jcc %l1";
if (GET_CODE (operands[0]) == MEM)
(define_insn "blockage"
[(unspec_volatile [(const_int 0)] UNSPECV_BLOCKAGE)]
""
- "")
+ ""
+ [(set_attr "flags_valid" "unchanged")])
(define_insn "nop"
[(const_int 0)]
""
"nop"
- [(set_attr "type" "nop")])
+ [(set_attr "type" "nop")
+ (set_attr "flags_valid" "unchanged")])
(define_expand "prologue"
[(const_int 0)]
;;
;; 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"
- [(cc0) (const_int 0)])
- (label_ref (match_operand 2 "" ""))
- (pc)))
- (parallel
- [(set (pc)
- (if_then_else
- (ne (match_operand:HI 0 "register_operand" "")
- (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
- (ne (match_operand:SI 0 "register_operand" "")
- (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_peephole
- [(set (pc) (if_then_else (match_operator 3 "valid_dbcc_comparison_p"
- [(cc0) (const_int 0)])
+ [(set (pc) (if_then_else (match_operator 3 "ordered_comparison_operator"
+ [(match_operand:CMPMODE 4 "general_operand" "")
+ (match_operand:CMPMODE 5 "general_operand" "")])
(label_ref (match_operand 2 "" ""))
(pc)))
(parallel
[(set (pc)
(if_then_else
- (ge (plus:HI (match_operand:HI 0 "register_operand" "")
- (const_int -1))
+ (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)))])]
- "!TARGET_COLDFIRE && DATA_REG_P (operands[0]) && ! flags_in_68881 ()"
+ (plus:DBCC (match_dup 0)
+ (const_int -1)))])]
+ "!TARGET_COLDFIRE && DATA_REG_P (operands[0])"
{
- CC_STATUS_INIT;
- output_dbcc_and_branch (operands);
+ rtx_code code = GET_CODE (operands[3]);
+ code = m68k_output_compare_<CMPMODE:mode> (operands[4], operands[5], code);
+ output_dbcc_and_branch (operands, code);
return "";
})
(define_peephole
- [(set (pc) (if_then_else (match_operator 3 "valid_dbcc_comparison_p"
- [(cc0) (const_int 0)])
+ [(set (pc) (if_then_else (match_operator 3 "ordered_comparison_operator"
+ [(match_operand:CMPMODE 4 "general_operand" "")
+ (match_operand:CMPMODE 5 "general_operand" "")])
(label_ref (match_operand 2 "" ""))
(pc)))
(parallel
[(set (pc)
(if_then_else
- (ge (plus:SI (match_operand:SI 0 "register_operand" "")
- (const_int -1))
+ (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)))])]
- "!TARGET_COLDFIRE && DATA_REG_P (operands[0]) && ! flags_in_68881 ()"
+ (plus:DBCC (match_dup 0)
+ (const_int -1)))])]
+ "!TARGET_COLDFIRE && DATA_REG_P (operands[0])"
{
- CC_STATUS_INIT;
- output_dbcc_and_branch (operands);
+ rtx_code code = GET_CODE (operands[3]);
+ code = m68k_output_compare_<CMPMODE:mode> (operands[4], operands[5], code);
+ output_dbcc_and_branch (operands, code);
return "";
})
-
\f
(define_insn "extendsfxf2"
[(set (match_operand:XF 0 "nonimmediate_operand" "=fm,f")
{
if (REGNO (operands[0]) == REGNO (operands[1]))
{
- /* Extending float to double in an fp-reg is a no-op.
- NOTICE_UPDATE_CC has already assumed that the
- cc will be set. So cancel what it did. */
- cc_status = cc_prev_status;
+ /* Extending float to double in an fp-reg is a no-op. */
return "";
}
return "f%$move%.x %1,%0";
{
if (REGNO (operands[0]) == REGNO (operands[1]))
{
- /* Extending float to double in an fp-reg is a no-op.
- NOTICE_UPDATE_CC has already assumed that the
- cc will be set. So cancel what it did. */
- cc_status = cc_prev_status;
+ /* Extending float to double in an fp-reg is a no-op. */
return "";
}
return "fmove%.x %1,%0";
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")])
-(define_expand "ctrapdi4"
+;; ??? 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_insn "ctrap<mode>4"
[(trap_if (match_operator 0 "ordered_comparison_operator"
- [(cc0) (const_int 0)])
- (match_operand:SI 3 "const1_operand" ""))]
- "TARGET_68020"
+ [(match_operand:CMPMODE 1 "nonimmediate_operand" "<cmp1_constraints>")
+ (match_operand:CMPMODE 2 "general_operand" "<cmp2_constraints>")])
+ (match_operand:SI 3 "const1_operand" ""))]
+ "TARGET_68020 && !TARGET_COLDFIRE"
{
- if (operands[2] == const0_rtx)
- emit_insn (gen_tstdi (operands[1]));
- else
- emit_insn (gen_cmpdi (operands[1], operands[2]));
- operands[1] = cc0_rtx;
- operands[2] = const0_rtx;
-})
-
-(define_expand "ctrapsi4"
- [(set (cc0)
- (compare (match_operand:SI 1 "nonimmediate_operand" "")
- (match_operand:SI 2 "general_operand" "")))
- (trap_if (match_operator 0 "ordered_comparison_operator"
- [(cc0) (const_int 0)])
- (match_operand:SI 3 "const1_operand" ""))]
- "TARGET_68020"
- "")
-
-(define_expand "ctraphi4"
- [(set (cc0)
- (compare (match_operand:HI 1 "nonimmediate_src_operand" "")
- (match_operand:HI 2 "general_src_operand" "")))
- (trap_if (match_operator 0 "ordered_comparison_operator"
- [(cc0) (const_int 0)])
- (match_operand:SI 3 "const1_operand" ""))]
- "TARGET_68020"
- "")
-
-(define_expand "ctrapqi4"
- [(set (cc0)
- (compare (match_operand:QI 1 "nonimmediate_src_operand" "")
- (match_operand:QI 2 "general_src_operand" "")))
- (trap_if (match_operator 0 "ordered_comparison_operator"
- [(cc0) (const_int 0)])
- (match_operand:SI 3 "const1_operand" ""))]
- "TARGET_68020"
- "")
+ rtx_code code = GET_CODE (operands[0]);
+ code = m68k_output_compare_<mode> (operands[1], operands[2], code);
+ switch (code)
+ {
+ case EQ: return "trapeq";
+ case NE: return "trapne";
+ case GT: return "trapgt";
+ case GTU: return "traphi";
+ case LT: return "traplt";
+ case LTU: return "trapcs";
+ case GE: return "trapge";
+ case GEU: return "trapcc";
+ case LE: return "traple";
+ case LEU: return "trapls";
+ default: gcc_unreachable ();
+ }
+})
-(define_insn "*conditional_trap"
+(define_insn "ctrap<mode>4_cf"
[(trap_if (match_operator 0 "ordered_comparison_operator"
- [(cc0) (const_int 0)])
- (match_operand:SI 1 "const1_operand" "I"))]
- "TARGET_68020 && ! flags_in_68881 ()"
-{
- switch (GET_CODE (operands[0]))
+ [(match_operand:CMPMODE 1 "nonimmediate_operand" "<cmp1_cf_constraints>")
+ (match_operand:CMPMODE 2 "general_operand" "<cmp2_cf_constraints>")])
+ (match_operand:SI 3 "const1_operand" ""))]
+ "TARGET_68020 && TARGET_COLDFIRE"
+{
+ rtx_code code = GET_CODE (operands[0]);
+ code = m68k_output_compare_<mode> (operands[1], operands[2], code);
+ switch (code)
{
case EQ: return "trapeq";
case NE: return "trapne";
(define_peephole2
[(set (match_operand:SI 0 "register_operand" "")
(match_operand:SI 1 "addq_subq_operand" ""))
- (set (cc0) (compare (match_operand:SI 2 "register_operand" "")
- (match_dup 0)))
(set (pc) (if_then_else (match_operator 5 "equality_comparison_operator"
- [(cc0) (const_int 0)])
+ [(match_operand:SI 2 "register_operand" "") (match_dup 0)])
(match_operand 3 "pc_or_label_operand")
(match_operand 4 "pc_or_label_operand")))]
"peep2_reg_dead_p (2, operands[0])
&& DATA_REG_P (operands[2])
&& !rtx_equal_p (operands[0], operands[2])"
[(set (match_dup 2) (plus:SI (match_dup 2) (match_dup 6)))
- (set (cc0) (compare (match_dup 2) (const_int 0)))
- (set (pc) (if_then_else (match_op_dup 5 [(cc0) (const_int 0)])
+ (set (pc) (if_then_else (match_op_dup 5 [(match_dup 2) (const_int 0)])
(match_dup 3)
(match_dup 4)))]
"operands[6] = GEN_INT (-INTVAL (operands[1]));")
(define_peephole2
[(set (match_operand:SI 0 "register_operand" "")
(match_operand:SI 1 "pow2_m1_operand" ""))
- (set (cc0) (compare (match_operand:SI 2 "register_operand" "")
- (match_operand:SI 3 "register_operand" "")))
- (set (pc) (if_then_else (gtu (cc0) (const_int 0))
+ (set (pc) (if_then_else (gtu (match_operand:SI 2 "register_operand" "")
+ (match_operand:SI 3 "register_operand" ""))
(match_operand 4 "pc_or_label_operand")
(match_operand 5 "pc_or_label_operand")))]
"INTVAL (operands[1]) <= 255
&& (optimize_size || TUNE_68040_60)
&& DATA_REG_P (operands[2])"
[(set (match_dup 7) (lshiftrt:SI (match_dup 7) (match_dup 6)))
- (set (cc0) (compare (match_dup 7) (const_int 0)))
- (set (pc) (if_then_else (ne (cc0) (const_int 0))
+ (set (pc) (if_then_else (ne (match_dup 7) (const_int 0))
(match_dup 4) (match_dup 5)))]
"
{
}")
(define_peephole2
- [(set (cc0) (compare (match_operand:SI 0 "register_operand" "")
- (match_operand:SI 1 "pow2_m1_operand" "")))
- (set (pc) (if_then_else (gtu (cc0) (const_int 0))
+ [(set (pc) (if_then_else (gtu (match_operand:SI 0 "register_operand" "")
+ (match_operand:SI 1 "pow2_m1_operand" ""))
(match_operand 2 "pc_or_label_operand")
(match_operand 3 "pc_or_label_operand")))]
"INTVAL (operands[1]) <= 255
&& (optimize_size || TUNE_68040_60)
&& DATA_REG_P (operands[0])"
[(set (match_dup 0) (lshiftrt:SI (match_dup 0) (match_dup 4)))
- (set (cc0) (compare (match_dup 0) (const_int 0)))
- (set (pc) (if_then_else (ne (cc0) (const_int 0))
+ (set (pc) (if_then_else (ne (match_dup 0) (const_int 0))
(match_dup 2) (match_dup 3)))]
"{ operands[4] = GEN_INT (exact_log2 (INTVAL (operands[1]) + 1)); }")
(define_peephole2
[(set (match_operand:SI 0 "register_operand" "")
(match_operand:SI 1 "pow2_m1_operand" ""))
- (set (cc0) (compare (match_operand:SI 2 "register_operand" "")
- (match_operand:SI 3 "register_operand" "")))
- (set (pc) (if_then_else (leu (cc0) (const_int 0))
+ (set (pc) (if_then_else (leu (match_operand:SI 2 "register_operand" "")
+ (match_operand:SI 3 "register_operand" ""))
(match_operand 4 "pc_or_label_operand")
(match_operand 5 "pc_or_label_operand")))]
"INTVAL (operands[1]) <= 255
&& (optimize_size || TUNE_68040_60)
&& DATA_REG_P (operands[2])"
[(set (match_dup 7) (lshiftrt:SI (match_dup 7) (match_dup 6)))
- (set (cc0) (compare (match_dup 7) (const_int 0)))
- (set (pc) (if_then_else (eq (cc0) (const_int 0))
+ (set (pc) (if_then_else (eq (match_dup 7) (const_int 0))
(match_dup 4) (match_dup 5)))]
"
{
operands[7] = operands[2];
}")
(define_peephole2
- [(set (cc0) (compare (match_operand:SI 0 "register_operand" "")
- (match_operand:SI 1 "pow2_m1_operand" "")))
- (set (pc) (if_then_else (leu (cc0) (const_int 0))
+ [(set (pc) (if_then_else (leu (match_operand:SI 0 "register_operand" "")
+ (match_operand:SI 1 "pow2_m1_operand" ""))
(match_operand 2 "pc_or_label_operand")
(match_operand 3 "pc_or_label_operand")))]
"INTVAL (operands[1]) <= 255
&& (optimize_size || TUNE_68040_60)
&& DATA_REG_P (operands[0])"
[(set (match_dup 0) (lshiftrt:SI (match_dup 0) (match_dup 4)))
- (set (cc0) (compare (match_dup 0) (const_int 0)))
- (set (pc) (if_then_else (eq (cc0) (const_int 0))
+ (set (pc) (if_then_else (eq (match_dup 0) (const_int 0))
(match_dup 2) (match_dup 3)))]
"{ operands[4] = GEN_INT (exact_log2 (INTVAL (operands[1]) + 1)); }")
;; internally against 65535).
;; The rotate in the output pattern will turn into a swap.
(define_peephole2
- [(set (cc0) (compare (match_operand:SI 0 "register_operand" "")
- (const_int 65535)))
- (set (pc) (if_then_else (match_operator 1 "swap_peephole_relational_operator"
- [(cc0) (const_int 0)])
+ [(set (pc) (if_then_else (match_operator 1 "swap_peephole_relational_operator"
+ [(match_operand:SI 0 "register_operand" "")
+ (const_int 65535)])
(match_operand 2 "pc_or_label_operand")
(match_operand 3 "pc_or_label_operand")))]
"peep2_reg_dead_p (1, operands[0])
&& (optimize_size || TUNE_68000_10)
&& DATA_REG_P (operands[0])"
[(set (match_dup 0) (rotate:SI (match_dup 0) (const_int 16)))
- (set (cc0) (compare (subreg:HI (match_dup 0) 2) (const_int 0)))
- (set (pc) (if_then_else (match_op_dup 1 [(cc0) (const_int 0)])
+ (set (pc) (if_then_else (match_op_dup 1 [(subreg:HI (match_dup 0) 2) (const_int 0)])
(match_dup 2) (match_dup 3)))]
"")