Commit bad41521 by Richard Henderson Committed by Richard Henderson

mn10300: Cleanup all arithmetic.

For addition and logicals, define an operation-plus-flags update pattern
in preparation for compare elimination.  In addition, clean up the way
we compare and validate CC_MODEs.  Define NEG in terms of NOT; this is
smaller and allows a non-clobbering destination alternative.

From-SVN: r169010
parent 9efb4993
2011-01-19 Richard Henderson <rth@redhat.com> 2011-01-19 Richard Henderson <rth@redhat.com>
* config/mn10300/mn10300-modes.def (CCZN, CCZNC): New modes.
* config/mn10300/mn10300.c (CC_FLAG_Z): New.
(CC_FLAG_N, CC_FLAG_C, CC_FLAG_V): New.
(cc_flags_for_mode, cc_flags_for_code): New.
(mn10300_print_operand) ['B']: Use nc/ns for GE/LT when the
overflow flag is not valid. Validate that the flags we need
for the comparison are valid.
(mn10300_output_cmp): Remove.
(mn10300_output_add): New.
(mn10300_select_cc_mode): Use cc_flags_for_code.
(mn10300_split_cbranch): New.
(mn10300_match_ccmode): New.
(mn10300_split_and_operand_count): New.
* config/mn10300/mn10300.h (SELECT_CC_MODE): Pass all of the arguments
to the function.
* config/mn10300/mn10300.md (*am33_addsi3, *mn10300_addsi3): Merge...
(addsi3): ... here. Use mn10300_output_add.
(*addsi3_flags): New.
(*am33_subsi3, *mn10300_subsi3): Merge...
(subsi3): ... here. Use attribute isa.
(*subsi3_flags): New.
(negsi2): Rewrite from expander to insn_and_split. Use NOT+INC
when possible.
(*am33_andsi3, *mn10300_andsi3): Merge...
(andsi3): ... here.
(*andsi3_flags): New.
(andsi3 splitters): New.
(*am33_iorsi3, *mn10300_iorsi3): Merge...
(iorsi3): ... here.
(*iorsi3_flags): New.
(*am33_xorsi3, *mn10300_xorsi3): Merge...
(xorsi3): ... here.
(*xorsi3_flags): New.
(*am33_cmpsi2, *mn10300_cmplsi2): Merge...
(one_cmplsi2): ... here.
(*one_cmplsi2_flags): New.
(*cbranchsi4_cmp): Rename from cbranchsi4_post_reload. Use "r"
instead of "dax" in constraints. Use mn10300_split_cbranch.
(*cmpsi): Rename from cmpsi. Do not use mn10300_output_cmp. Do not
use matching constraints to eliminate a self-comparison.
(*integer_conditional_branch): Rename from integer_conditional_branch.
Use int_mode_flags to match CC_REG.
(*cbranchsi4_btst, *btstsi): New.
(*cbranchsf4_cmp): Rename from *cbranchsf4_post_reload. Use
mn10300_split_cbranch.
(*am33_cmpsf): Rename from am33_cmpsf.
(*float_conditional_branch): Rename from float_conditional_branch.
(*zero_extendqisi2_am33, *zero_extendqisi2_mn10300): Merge...
(zero_extendqisi2): ... here.
(*zero_extendhisi2_am33, *zero_extendhisi2_mn10300): Merge...
(zero_extendhisi2): ... here.
(*extendqisi2_am33, *extendqisi2_mn10300): Merge...
(extendqisi2): ... here.
(*extendhisi2_am33, *extendhisi2_mn10300): Merge...
(extendhisi2): ... here.
(*am33_ashlsi3, *mn10300_ashlsi3): Merge...
(ashlsi3): ... here.
(*am33_lshrsi3, *mn10300_lshrsi3): Merge...
(lshrsi3): ... here.
(*am33_ashrisi3, *mn10300_ashrsi3): Merge...
(ashrsi3): ... here.
(consecutive add peephole): Remove.
* config/mn10300/predicates.md (label_ref_operand): New.
(int_mode_flags): New.
(CCZN_comparison_operator): New.
* config/mn10300/mn10300.md (UNSPEC_EXT): New. * config/mn10300/mn10300.md (UNSPEC_EXT): New.
(throughput_42_latency_43): New reservation. (throughput_42_latency_43): New reservation.
(mulsidi3, umulsidi3): New expanders. (mulsidi3, umulsidi3): New expanders.
......
...@@ -19,4 +19,6 @@ ...@@ -19,4 +19,6 @@
the Free Software Foundation, , Inc., 51 Franklin Street - Fifth the Free Software Foundation, , Inc., 51 Franklin Street - Fifth
Floor, Boston, MA 02110-1301, USA. */ Floor, Boston, MA 02110-1301, USA. */
CC_MODE (CCZN);
CC_MODE (CCZNC);
CC_MODE (CC_FLOAT); CC_MODE (CC_FLOAT);
...@@ -32,13 +32,16 @@ extern int mn10300_get_live_callee_saved_regs (void); ...@@ -32,13 +32,16 @@ extern int mn10300_get_live_callee_saved_regs (void);
extern bool mn10300_hard_regno_mode_ok (unsigned int, Mmode); extern bool mn10300_hard_regno_mode_ok (unsigned int, Mmode);
extern bool mn10300_legitimate_constant_p (rtx); extern bool mn10300_legitimate_constant_p (rtx);
extern bool mn10300_modes_tieable (Mmode, Mmode); extern bool mn10300_modes_tieable (Mmode, Mmode);
extern Cstar mn10300_output_cmp (rtx, rtx); extern Cstar mn10300_output_add (rtx[3], bool);
extern void mn10300_print_operand (FILE *, rtx, int); extern void mn10300_print_operand (FILE *, rtx, int);
extern void mn10300_print_operand_address (FILE *, rtx); extern void mn10300_print_operand_address (FILE *, rtx);
extern void mn10300_print_reg_list (FILE *, int); extern void mn10300_print_reg_list (FILE *, int);
extern Mmode mn10300_select_cc_mode (rtx); extern Mmode mn10300_select_cc_mode (enum rtx_code, rtx, rtx);
extern int mn10300_store_multiple_operation (rtx, Mmode); extern int mn10300_store_multiple_operation (rtx, Mmode);
extern int mn10300_symbolic_operand (rtx, Mmode); extern int mn10300_symbolic_operand (rtx, Mmode);
extern void mn10300_split_cbranch (Mmode, rtx, rtx);
extern int mn10300_split_and_operand_count (rtx);
extern bool mn10300_match_ccmode (rtx, Mmode);
#endif /* RTX_CODE */ #endif /* RTX_CODE */
extern bool mn10300_regno_in_class_p (unsigned, int, bool); extern bool mn10300_regno_in_class_p (unsigned, int, bool);
......
...@@ -81,6 +81,14 @@ static const struct default_options mn10300_option_optimization_table[] = ...@@ -81,6 +81,14 @@ static const struct default_options mn10300_option_optimization_table[] =
{ OPT_LEVELS_1_PLUS, OPT_fomit_frame_pointer, NULL, 1 }, { OPT_LEVELS_1_PLUS, OPT_fomit_frame_pointer, NULL, 1 },
{ OPT_LEVELS_NONE, 0, NULL, 0 } { OPT_LEVELS_NONE, 0, NULL, 0 }
}; };
#define CC_FLAG_Z 1
#define CC_FLAG_N 2
#define CC_FLAG_C 4
#define CC_FLAG_V 8
static int cc_flags_for_mode(enum machine_mode);
static int cc_flags_for_code(enum rtx_code);
/* Implement TARGET_HANDLE_OPTION. */ /* Implement TARGET_HANDLE_OPTION. */
...@@ -134,7 +142,7 @@ mn10300_option_override (void) ...@@ -134,7 +142,7 @@ mn10300_option_override (void)
when this flag is not enabled by default. */ when this flag is not enabled by default. */
flag_split_wide_types = 1; flag_split_wide_types = 1;
} }
if (mn10300_tune_string) if (mn10300_tune_string)
{ {
if (strcasecmp (mn10300_tune_string, "mn10300") == 0) if (strcasecmp (mn10300_tune_string, "mn10300") == 0)
...@@ -171,95 +179,82 @@ mn10300_print_operand (FILE *file, rtx x, int code) ...@@ -171,95 +179,82 @@ mn10300_print_operand (FILE *file, rtx x, int code)
{ {
case 'b': case 'b':
case 'B': case 'B':
if (GET_MODE (XEXP (x, 0)) == CC_FLOATmode) {
{ enum rtx_code cmp = GET_CODE (x);
switch (code == 'b' ? GET_CODE (x) enum machine_mode mode = GET_MODE (XEXP (x, 0));
: reverse_condition_maybe_unordered (GET_CODE (x))) const char *str;
{ int have_flags;
case NE:
fprintf (file, "ne"); if (code == 'B')
break; cmp = reverse_condition (cmp);
case EQ: have_flags = cc_flags_for_mode (mode);
fprintf (file, "eq");
break; switch (cmp)
case GE: {
fprintf (file, "ge"); case NE:
break; str = "ne";
case GT: break;
fprintf (file, "gt"); case EQ:
break; str = "eq";
case LE: break;
fprintf (file, "le"); case GE:
break; /* bge is smaller than bnc. */
case LT: str = (have_flags & CC_FLAG_V ? "ge" : "nc");
fprintf (file, "lt"); break;
break; case LT:
case ORDERED: str = (have_flags & CC_FLAG_V ? "lt" : "ns");
fprintf (file, "lge"); break;
break; case GT:
case UNORDERED: str = "gt";
fprintf (file, "uo"); break;
break; case LE:
case LTGT: str = "le";
fprintf (file, "lg"); break;
break; case GEU:
case UNEQ: str = "cc";
fprintf (file, "ue"); break;
break; case GTU:
case UNGE: str = "hi";
fprintf (file, "uge"); break;
break; case LEU:
case UNGT: str = "ls";
fprintf (file, "ug"); break;
break; case LTU:
case UNLE: str = "cs";
fprintf (file, "ule"); break;
break; case ORDERED:
case UNLT: str = "lge";
fprintf (file, "ul"); break;
break; case UNORDERED:
default: str = "uo";
gcc_unreachable (); break;
} case LTGT:
break; str = "lg";
} break;
/* These are normal and reversed branches. */ case UNEQ:
switch (code == 'b' ? GET_CODE (x) : reverse_condition (GET_CODE (x))) str = "ue";
{ break;
case NE: case UNGE:
fprintf (file, "ne"); str = "uge";
break; break;
case EQ: case UNGT:
fprintf (file, "eq"); str = "ug";
break; break;
case GE: case UNLE:
fprintf (file, "ge"); str = "ule";
break; break;
case GT: case UNLT:
fprintf (file, "gt"); str = "ul";
break; break;
case LE: default:
fprintf (file, "le"); gcc_unreachable ();
break; }
case LT:
fprintf (file, "lt"); gcc_checking_assert ((cc_flags_for_code (cmp) & ~have_flags) == 0);
break; fputs (str, file);
case GEU: }
fprintf (file, "cc");
break;
case GTU:
fprintf (file, "hi");
break;
case LEU:
fprintf (file, "ls");
break;
case LTU:
fprintf (file, "cs");
break;
default:
gcc_unreachable ();
}
break; break;
case 'C': case 'C':
/* This is used for the operand to a call instruction; /* This is used for the operand to a call instruction;
if it's a REG, enclose it in parens, else output if it's a REG, enclose it in parens, else output
...@@ -1709,95 +1704,96 @@ mn10300_function_value_regno_p (const unsigned int regno) ...@@ -1709,95 +1704,96 @@ mn10300_function_value_regno_p (const unsigned int regno)
return (regno == FIRST_DATA_REGNUM || regno == FIRST_ADDRESS_REGNUM); return (regno == FIRST_DATA_REGNUM || regno == FIRST_ADDRESS_REGNUM);
} }
/* Output a compare insn. */ /* Output an addition operation. */
const char * const char *
mn10300_output_cmp (rtx operand, rtx insn) mn10300_output_add (rtx operands[3], bool need_flags)
{ {
rtx temp; rtx dest, src1, src2;
int past_call = 0; unsigned int dest_regnum, src1_regnum, src2_regnum;
enum reg_class src1_class, src2_class, dest_class;
/* We can save a byte if we can find a register which has the value dest = operands[0];
zero in it. */ src1 = operands[1];
temp = PREV_INSN (insn); src2 = operands[2];
while (optimize && temp)
{
rtx set;
/* We allow the search to go through call insns. We record
the fact that we've past a CALL_INSN and reject matches which
use call clobbered registers. */
if (LABEL_P (temp)
|| JUMP_P (temp)
|| GET_CODE (temp) == BARRIER)
break;
if (CALL_P (temp)) dest_regnum = true_regnum (dest);
past_call = 1; src1_regnum = true_regnum (src1);
if (GET_CODE (temp) == NOTE) dest_class = REGNO_REG_CLASS (dest_regnum);
{ src1_class = REGNO_REG_CLASS (src1_regnum);
temp = PREV_INSN (temp);
continue;
}
/* It must be an insn, see if it is a simple set. */ if (GET_CODE (src2) == CONST_INT)
set = single_set (temp); {
if (!set) gcc_assert (dest_regnum == src1_regnum);
{
temp = PREV_INSN (temp);
continue;
}
/* Are we setting a data register to zero (this does not win for if (src2 == const1_rtx && !need_flags)
address registers)? return "inc %0";
if (INTVAL (src2) == 4 && !need_flags && dest_class != DATA_REGS)
If it's a call clobbered register, have we past a call? return "inc4 %0";
Make sure the register we find isn't the same as ourself;
the mn10300 can't encode that.
??? reg_set_between_p return nonzero anytime we pass a CALL_INSN
so the code to detect calls here isn't doing anything useful. */
if (REG_P (SET_DEST (set))
&& SET_SRC (set) == CONST0_RTX (GET_MODE (SET_DEST (set)))
&& !reg_set_between_p (SET_DEST (set), temp, insn)
&& (REGNO_REG_CLASS (REGNO (SET_DEST (set)))
== REGNO_REG_CLASS (REGNO (operand)))
&& REGNO_REG_CLASS (REGNO (SET_DEST (set))) != EXTENDED_REGS
&& REGNO (SET_DEST (set)) != REGNO (operand)
&& (!past_call
|| ! call_really_used_regs [REGNO (SET_DEST (set))]))
{
rtx xoperands[2];
xoperands[0] = operand;
xoperands[1] = SET_DEST (set);
output_asm_insn ("cmp %1,%0", xoperands); gcc_assert (!need_flags || dest_class != SP_REGS);
return ""; return "add %2,%0";
} }
else if (CONSTANT_P (src2))
return "add %2,%0";
src2_regnum = true_regnum (src2);
src2_class = REGNO_REG_CLASS (src2_regnum);
if (dest_regnum == src1_regnum)
return "add %2,%0";
if (dest_regnum == src2_regnum)
return "add %1,%0";
/* The rest of the cases are reg = reg+reg. For AM33, we can implement
this directly, as below, but when optimizing for space we can sometimes
do better by using a mov+add. For MN103, we claimed that we could
implement a three-operand add because the various move and add insns
change sizes across register classes, and we can often do better than
reload in choosing which operand to move. */
if (TARGET_AM33 && optimize_insn_for_speed_p ())
return "add %2,%1,%0";
/* Catch cases where no extended register was used. */
if (src1_class != EXTENDED_REGS
&& src2_class != EXTENDED_REGS
&& dest_class != EXTENDED_REGS)
{
/* We have to copy one of the sources into the destination, then
add the other source to the destination.
Carefully select which source to copy to the destination; a
naive implementation will waste a byte when the source classes
are different and the destination is an address register.
Selecting the lowest cost register copy will optimize this
sequence. */
if (src1_class == dest_class)
return "mov %1,%0\n\tadd %2,%0";
else
return "mov %2,%0\n\tadd %1,%0";
}
if (REGNO_REG_CLASS (REGNO (operand)) == EXTENDED_REGS /* At least one register is an extended register. */
&& REG_P (SET_DEST (set))
&& SET_SRC (set) == CONST0_RTX (GET_MODE (SET_DEST (set)))
&& !reg_set_between_p (SET_DEST (set), temp, insn)
&& (REGNO_REG_CLASS (REGNO (SET_DEST (set)))
!= REGNO_REG_CLASS (REGNO (operand)))
&& REGNO_REG_CLASS (REGNO (SET_DEST (set))) == EXTENDED_REGS
&& REGNO (SET_DEST (set)) != REGNO (operand)
&& (!past_call
|| ! call_really_used_regs [REGNO (SET_DEST (set))]))
{
rtx xoperands[2];
xoperands[0] = operand;
xoperands[1] = SET_DEST (set);
output_asm_insn ("cmp %1,%0", xoperands); /* The three operand add instruction on the am33 is a win iff the
return ""; output register is an extended register, or if both source
} registers are extended registers. */
temp = PREV_INSN (temp); if (dest_class == EXTENDED_REGS || src1_class == src2_class)
} return "add %2,%1,%0";
return "cmp 0,%0";
/* It is better to copy one of the sources to the destination, then
perform a 2 address add. The destination in this case must be
an address or data register and one of the sources must be an
extended register and the remaining source must not be an extended
register.
The best code for this case is to copy the extended reg to the
destination, then emit a two address add. */
if (src1_class == EXTENDED_REGS)
return "mov %1,%0\n\tadd %2,%0";
else
return "mov %2,%0\n\tadd %1,%0";
} }
/* Return 1 if X contains a symbolic expression. We know these /* Return 1 if X contains a symbolic expression. We know these
...@@ -2674,10 +2670,80 @@ mn10300_modes_tieable (enum machine_mode mode1, enum machine_mode mode2) ...@@ -2674,10 +2670,80 @@ mn10300_modes_tieable (enum machine_mode mode1, enum machine_mode mode2)
return false; return false;
} }
static int
cc_flags_for_mode (enum machine_mode mode)
{
switch (mode)
{
case CCmode:
return CC_FLAG_Z | CC_FLAG_N | CC_FLAG_C | CC_FLAG_V;
case CCZNCmode:
return CC_FLAG_Z | CC_FLAG_N | CC_FLAG_C;
case CCZNmode:
return CC_FLAG_Z | CC_FLAG_N;
case CC_FLOATmode:
return -1;
default:
gcc_unreachable ();
}
}
static int
cc_flags_for_code (enum rtx_code code)
{
switch (code)
{
case EQ: /* Z */
case NE: /* ~Z */
return CC_FLAG_Z;
case LT: /* N */
case GE: /* ~N */
return CC_FLAG_N;
break;
case GT: /* ~(Z|(N^V)) */
case LE: /* Z|(N^V) */
return CC_FLAG_Z | CC_FLAG_N | CC_FLAG_V;
case GEU: /* ~C */
case LTU: /* C */
return CC_FLAG_C;
case GTU: /* ~(C | Z) */
case LEU: /* C | Z */
return CC_FLAG_Z | CC_FLAG_C;
case ORDERED:
case UNORDERED:
case LTGT:
case UNEQ:
case UNGE:
case UNGT:
case UNLE:
case UNLT:
return -1;
default:
gcc_unreachable ();
}
}
enum machine_mode enum machine_mode
mn10300_select_cc_mode (rtx x) mn10300_select_cc_mode (enum rtx_code code, rtx x, rtx y ATTRIBUTE_UNUSED)
{ {
return (GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT) ? CC_FLOATmode : CCmode; int req;
if (GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT)
return CC_FLOATmode;
req = cc_flags_for_code (code);
if (req & CC_FLAG_V)
return CCmode;
if (req & CC_FLAG_C)
return CCZNCmode;
return CCZNmode;
} }
static inline bool static inline bool
...@@ -2811,6 +2877,82 @@ mn10300_md_asm_clobbers (tree outputs ATTRIBUTE_UNUSED, ...@@ -2811,6 +2877,82 @@ mn10300_md_asm_clobbers (tree outputs ATTRIBUTE_UNUSED,
return clobbers; return clobbers;
} }
/* A helper function for splitting cbranch patterns after reload. */
void
mn10300_split_cbranch (enum machine_mode cmp_mode, rtx cmp_op, rtx label_ref)
{
rtx flags, x;
flags = gen_rtx_REG (cmp_mode, CC_REG);
x = gen_rtx_COMPARE (cmp_mode, XEXP (cmp_op, 0), XEXP (cmp_op, 1));
x = gen_rtx_SET (VOIDmode, flags, x);
emit_insn (x);
x = gen_rtx_fmt_ee (GET_CODE (cmp_op), VOIDmode, flags, const0_rtx);
x = gen_rtx_IF_THEN_ELSE (VOIDmode, x, label_ref, pc_rtx);
x = gen_rtx_SET (VOIDmode, pc_rtx, x);
emit_jump_insn (x);
}
/* A helper function for matching parallels that set the flags. */
bool
mn10300_match_ccmode (rtx insn, enum machine_mode cc_mode)
{
rtx op1, flags;
enum machine_mode flags_mode;
gcc_checking_assert (XVECLEN (PATTERN (insn), 0) == 2);
op1 = XVECEXP (PATTERN (insn), 0, 1);
gcc_checking_assert (GET_CODE (SET_SRC (op1)) == COMPARE);
flags = SET_DEST (op1);
flags_mode = GET_MODE (flags);
if (GET_MODE (SET_SRC (op1)) != flags_mode)
return false;
if (GET_MODE_CLASS (flags_mode) != MODE_CC)
return false;
/* Ensure that the mode of FLAGS is compatible with CC_MODE. */
if (cc_flags_for_mode (flags_mode) & ~cc_flags_for_mode (cc_mode))
return false;
return true;
}
int
mn10300_split_and_operand_count (rtx op)
{
HOST_WIDE_INT val = INTVAL (op);
int count;
if (val < 0)
{
/* High bit is set, look for bits clear at the bottom. */
count = exact_log2 (-val);
if (count < 0)
return 0;
/* This is only size win if we can use the asl2 insn. Otherwise we
would be replacing 1 6-byte insn with 2 3-byte insns. */
if (count > (optimize_insn_for_speed_p () ? 2 : 4))
return 0;
return -count;
}
else
{
/* High bit is clear, look for bits set at the bottom. */
count = exact_log2 (val + 1);
count = 32 - count;
/* Again, this is only a size win with asl2. */
if (count > (optimize_insn_for_speed_p () ? 2 : 4))
return 0;
return -count;
}
}
/* Initialize the GCC target structure. */ /* Initialize the GCC target structure. */
#undef TARGET_EXCEPT_UNWIND_INFO #undef TARGET_EXCEPT_UNWIND_INFO
......
...@@ -600,7 +600,7 @@ do { \ ...@@ -600,7 +600,7 @@ do { \
/* Non-global SYMBOL_REFs have SYMBOL_REF_FLAG enabled. */ /* Non-global SYMBOL_REFs have SYMBOL_REF_FLAG enabled. */
#define MN10300_GLOBAL_P(X) (! SYMBOL_REF_FLAG (X)) #define MN10300_GLOBAL_P(X) (! SYMBOL_REF_FLAG (X))
#define SELECT_CC_MODE(OP, X, Y) mn10300_select_cc_mode (X) #define SELECT_CC_MODE(OP, X, Y) mn10300_select_cc_mode (OP, X, Y)
#define REVERSIBLE_CC_MODE(MODE) 0 #define REVERSIBLE_CC_MODE(MODE) 0
/* Nonzero if access to memory by bytes or half words is no faster /* Nonzero if access to memory by bytes or half words is no faster
......
...@@ -507,104 +507,6 @@ ...@@ -507,104 +507,6 @@
])] ])]
) )
;; ----------------------------------------------------------------------
;; ADD INSTRUCTIONS
;; ----------------------------------------------------------------------
(define_expand "addsi3"
[(parallel [(set (match_operand:SI 0 "register_operand")
(plus:SI (match_operand:SI 1 "register_operand")
(match_operand:SI 2 "nonmemory_operand")))
(clobber (reg:CC CC_REG))
])
]
""
"")
(define_insn "*am33_addsi3"
[(set (match_operand:SI 0 "register_operand" "=dx,a,x,a,dax,!*y,!dax")
(plus:SI (match_operand:SI 1 "register_operand" "%0,0,0,0,0,0,dax")
(match_operand:SI 2 "nonmemory_operand" "J,J,L,L,daxi,i,dax")))
(clobber (reg:CC CC_REG))
]
"TARGET_AM33"
"*
{
switch (which_alternative)
{
case 0:
case 1:
return \"inc %0\";
case 2:
case 3:
return \"inc4 %0\";
case 4:
case 5:
return \"add %2,%0\";
case 6:
{
enum reg_class src1_class, src2_class, dst_class;
src1_class = REGNO_REG_CLASS (true_regnum (operands[1]));
src2_class = REGNO_REG_CLASS (true_regnum (operands[2]));
dst_class = REGNO_REG_CLASS (true_regnum (operands[0]));
/* I'm not sure if this can happen or not. Might as well be prepared
and generate the best possible code if it does happen. */
if (true_regnum (operands[0]) == true_regnum (operands[1]))
return \"add %2,%0\";
if (true_regnum (operands[0]) == true_regnum (operands[2]))
return \"add %1,%0\";
/* Catch cases where no extended register was used. These should be
handled just like the mn10300. */
if (src1_class != EXTENDED_REGS
&& src2_class != EXTENDED_REGS
&& dst_class != EXTENDED_REGS)
{
/* We have to copy one of the sources into the destination, then
add the other source to the destination.
Carefully select which source to copy to the destination; a
naive implementation will waste a byte when the source classes
are different and the destination is an address register.
Selecting the lowest cost register copy will optimize this
sequence. */
if (REGNO_REG_CLASS (true_regnum (operands[1]))
== REGNO_REG_CLASS (true_regnum (operands[0])))
return \"mov %1,%0\;add %2,%0\";
return \"mov %2,%0\;add %1,%0\";
}
/* At least one register is an extended register. */
/* The three operand add instruction on the am33 is a win iff the
output register is an extended register, or if both source
registers are extended registers. */
if (dst_class == EXTENDED_REGS
|| src1_class == src2_class)
return \"add %2,%1,%0\";
/* It is better to copy one of the sources to the destination, then
perform a 2 address add. The destination in this case must be
an address or data register and one of the sources must be an
extended register and the remaining source must not be an extended
register.
The best code for this case is to copy the extended reg to the
destination, then emit a two address add. */
if (src1_class == EXTENDED_REGS)
return \"mov %1,%0\;add %2,%0\";
return \"mov %2,%0\;add %1,%0\";
}
default:
gcc_unreachable ();
}
}"
[(set_attr "timings" "11,11,11,11,11,11,22")]
)
;; If the flags register is not live, generate CLR instead of MOV 0. ;; If the flags register is not live, generate CLR instead of MOV 0.
;; For MN103, this is only legal for DATA_REGS; for AM33 this is legal ;; For MN103, this is only legal for DATA_REGS; for AM33 this is legal
;; but not a win for ADDRESS_REGS. ;; but not a win for ADDRESS_REGS.
...@@ -629,123 +531,90 @@ ...@@ -629,123 +531,90 @@
;; ADD INSTRUCTIONS ;; ADD INSTRUCTIONS
;; ---------------------------------------------------------------------- ;; ----------------------------------------------------------------------
(define_insn "*mn10300_addsi3" (define_insn "addsi3"
[(set (match_operand:SI 0 "register_operand" "=dx,a,a,dax,!*y,!dax") [(set (match_operand:SI 0 "register_operand" "=r,!*y,!r")
(plus:SI (match_operand:SI 1 "register_operand" "%0,0,0,0,0,dax") (plus:SI (match_operand:SI 1 "register_operand" "%0, 0, r")
(match_operand:SI 2 "nonmemory_operand" "J,J,L,daxi,i,dax"))) (match_operand:SI 2 "nonmemory_operand" "ri, i, r")))
(clobber (reg:CC CC_REG)) (clobber (reg:CC CC_REG))]
]
"" ""
"* { return mn10300_output_add (operands, false); }
{ [(set_attr "timings" "11,11,22")]
switch (which_alternative) )
{
case 0: ;; Note that ADD IMM,SP does not set the flags, so omit that here.
case 1: (define_insn "*addsi3_flags"
return \"inc %0\"; [(set (match_operand:SI 0 "register_operand" "=r,!r")
case 2: (plus:SI (match_operand:SI 1 "register_operand" "%0, r")
return \"inc4 %0\"; (match_operand:SI 2 "nonmemory_operand" "ri, r")))
case 3: (set (reg CC_REG)
case 4: (compare (plus:SI (match_dup 1) (match_dup 2))
return \"add %2,%0\"; (const_int 0)))]
case 5: "reload_completed && mn10300_match_ccmode (insn, CCZNCmode)"
/* I'm not sure if this can happen or not. Might as well be prepared { return mn10300_output_add (operands, true); }
and generate the best possible code if it does happen. */ [(set_attr "timings" "11,22")]
if (true_regnum (operands[0]) == true_regnum (operands[1]))
return \"add %2,%0\";
if (true_regnum (operands[0]) == true_regnum (operands[2]))
return \"add %1,%0\";
/* We have to copy one of the sources into the destination, then add
the other source to the destination.
Carefully select which source to copy to the destination; a naive
implementation will waste a byte when the source classes are different
and the destination is an address register. Selecting the lowest
cost register copy will optimize this sequence. */
if (REGNO_REG_CLASS (true_regnum (operands[1]))
== REGNO_REG_CLASS (true_regnum (operands[0])))
return \"mov %1,%0\;add %2,%0\";
return \"mov %2,%0\;add %1,%0\";
default:
gcc_unreachable ();
}
}"
[(set_attr "timings" "11,11,11,11,11,22")]
) )
;; ---------------------------------------------------------------------- ;; ----------------------------------------------------------------------
;; SUBTRACT INSTRUCTIONS ;; SUBTRACT INSTRUCTIONS
;; ---------------------------------------------------------------------- ;; ----------------------------------------------------------------------
(define_expand "subsi3" (define_insn "subsi3"
[(parallel [(set (match_operand:SI 0 "register_operand") [(set (match_operand:SI 0 "register_operand" "=r,r")
(minus:SI (match_operand:SI 1 "register_operand") (minus:SI (match_operand:SI 1 "register_operand" " 0,r")
(match_operand:SI 2 "nonmemory_operand"))) (match_operand:SI 2 "nonmemory_operand" "ri,r")))
(clobber (reg:CC CC_REG)) (clobber (reg:CC CC_REG))]
])
]
"" ""
"") "@
sub %2,%0
(define_insn "*am33_subsi3" sub %2,%1,%0"
[(set (match_operand:SI 0 "register_operand" "=dax,!dax") [(set_attr "isa" "*,am33")
(minus:SI (match_operand:SI 1 "register_operand" "0,dax") (set_attr "timings" "11,22")]
(match_operand:SI 2 "nonmemory_operand" "daxi,dax")))
(clobber (reg:CC CC_REG))
]
"TARGET_AM33"
"*
{
if (true_regnum (operands[0]) == true_regnum (operands[1]))
return \"sub %2,%0\";
else
{
enum reg_class src1_class, src2_class, dst_class;
src1_class = REGNO_REG_CLASS (true_regnum (operands[1]));
src2_class = REGNO_REG_CLASS (true_regnum (operands[2]));
dst_class = REGNO_REG_CLASS (true_regnum (operands[0]));
/* If no extended registers are used, then the best way to handle
this is to copy the first source operand into the destination
and emit a two address subtraction. */
if (src1_class != EXTENDED_REGS
&& src2_class != EXTENDED_REGS
&& dst_class != EXTENDED_REGS
&& true_regnum (operands[0]) != true_regnum (operands[2]))
return \"mov %1,%0\;sub %2,%0\";
return \"sub %2,%1,%0\";
}
}"
[(set_attr "timings" "11,22")]
) )
(define_insn "*mn10300_subsi3" (define_insn "*subsi3_flags"
[(set (match_operand:SI 0 "register_operand" "=dax") [(set (match_operand:SI 0 "register_operand" "=r,r")
(minus:SI (match_operand:SI 1 "register_operand" "0") (minus:SI (match_operand:SI 1 "register_operand" " 0,r")
(match_operand:SI 2 "nonmemory_operand" "daxi"))) (match_operand:SI 2 "nonmemory_operand" "ri,r")))
(clobber (reg:CC CC_REG)) (set (reg CC_REG)
] (compare (minus:SI (match_dup 1) (match_dup 2))
"" (const_int 0)))]
"sub %2,%0" "reload_completed && mn10300_match_ccmode (insn, CCZNCmode)"
[(set (attr "timings") (if_then_else (eq_attr "cpu" "am34") "@
(const_int 11) (const_int 22)))] sub %2,%0
sub %2,%1,%0"
[(set_attr "isa" "*,am33")
(set_attr "timings" "11,22")]
) )
(define_expand "negsi2" (define_insn_and_split "negsi2"
[(set (match_operand:SI 0 "register_operand") [(set (match_operand:SI 0 "register_operand" "=D,&r")
(neg:SI (match_operand:SI 1 "register_operand")))] (neg:SI (match_operand:SI 1 "register_operand" " 0, r")))
(clobber (reg:CC CC_REG))]
"" ""
" "#"
"&& reload_completed"
[(const_int 0)]
{ {
rtx target = gen_reg_rtx (SImode); /* Recall that twos-compliment is ones-compliment plus one. When
allocated in DATA_REGS this is 2+1 bytes; otherwise (for am33)
emit_move_insn (target, const0_rtx); this is 3+3 bytes.
emit_insn (gen_subsi3 (target, target, operands[1]));
emit_move_insn (operands[0], target); For AM33, it would have been possible to load zero and use the
three-address subtract to have a total size of 3+4*N bytes for
multiple negations, plus increased throughput. Not attempted here. */
if (true_regnum (operands[0]) == true_regnum (operands[1]))
{
emit_insn (gen_one_cmplsi2 (operands[0], operands[0]));
emit_insn (gen_addsi3 (operands[0], operands[0], const1_rtx));
}
else
{
emit_move_insn (operands[0], const0_rtx);
emit_insn (gen_subsi3 (operands[0], operands[0], operands[1]));
}
DONE; DONE;
}") })
;; ---------------------------------------------------------------------- ;; ----------------------------------------------------------------------
;; MULTIPLY INSTRUCTIONS ;; MULTIPLY INSTRUCTIONS
...@@ -935,221 +804,174 @@ ...@@ -935,221 +804,174 @@
;; AND INSTRUCTIONS ;; AND INSTRUCTIONS
;; ---------------------------------------------------------------------- ;; ----------------------------------------------------------------------
(define_expand "andsi3" (define_insn "andsi3"
[(parallel [(set (match_operand:SI 0 "register_operand") [(set (match_operand:SI 0 "register_operand" "=D,D,r")
(and:SI (match_operand:SI 1 "register_operand") (and:SI (match_operand:SI 1 "register_operand" "%0,0,r")
(match_operand:SI 2 "nonmemory_operand"))) (match_operand:SI 2 "nonmemory_operand" " i,D,r")))
(clobber (reg:CC CC_REG)) (clobber (reg:CC CC_REG))]
])
]
"" ""
"") "@
and %2,%0
(define_insn "*am33_andsi3" and %2,%0
[(set (match_operand:SI 0 "register_operand" "=dx,dx,!dax") and %2,%1,%0"
(and:SI (match_operand:SI 1 "register_operand" "%0,0,dax") [(set_attr "isa" "*,*,am33")
(match_operand:SI 2 "nonmemory_operand" "N,dxi,dax"))) (set_attr "timings" "22,11,11")]
(clobber (reg:CC CC_REG)) )
]
"TARGET_AM33" (define_insn "*andsi3_flags"
{ [(set (match_operand:SI 0 "register_operand" "=D,D,r")
if (CONST_INT_P (operands[2])) (and:SI (match_operand:SI 1 "register_operand" "%0,0,r")
switch (INTVAL (operands[2])) (match_operand:SI 2 "nonmemory_operand" " i,D,r")))
{ (set (reg CC_REG)
case 0xff: return "extbu %0"; (compare (and:SI (match_dup 1) (match_dup 2))
case 0xffff: return "exthu %0"; (const_int 0)))]
case 0x7fffffff: return "add %0, %0; lsr 1, %0"; "reload_completed && mn10300_match_ccmode (insn, CCZNmode)"
case 0x3fffffff: return "asl2 %0; lsr 2, %0"; "@
case 0x1fffffff: return "add %0, %0; asl2 %0; lsr 3, %0"; and %2,%0
case 0x0fffffff: return "asl2 %0; asl2 %0; lsr 4, %0"; and %2,%0
case 0xfffffffe: return "lsr 1, %0; add %0, %0"; and %2,%1,%0"
case 0xfffffffc: return "lsr 2, %0; asl2 %0"; [(set_attr "isa" "*,*,am33")
case 0xfffffff8: return "lsr 3, %0; add %0, %0; asl2 %0"; (set_attr "timings" "22,11,11")]
case 0xfffffff0: return "lsr 4, %0; asl2 %0; asl2 %0";
}
if (REG_P (operands[2]) && REG_P (operands[1])
&& true_regnum (operands[0]) != true_regnum (operands[1])
&& true_regnum (operands[0]) != true_regnum (operands[2])
&& REGNO_REG_CLASS (true_regnum (operands[0])) == DATA_REGS
&& REGNO_REG_CLASS (true_regnum (operands[1])) == DATA_REGS
&& REGNO_REG_CLASS (true_regnum (operands[2])) == DATA_REGS)
return "mov %1, %0; and %2, %0";
if (REG_P (operands[2]) && REG_P (operands[1])
&& true_regnum (operands[0]) != true_regnum (operands[1])
&& true_regnum (operands[0]) != true_regnum (operands[2]))
return "and %1, %2, %0";
if (REG_P (operands[2]) && REG_P (operands[0])
&& true_regnum (operands[2]) == true_regnum (operands[0]))
return "and %1, %0";
return "and %2, %0";
}
[(set_attr "timings" "33")]
) )
(define_insn "*mn10300_andsi3" ;; Make sure we generate extensions instead of ANDs.
[(set (match_operand:SI 0 "register_operand" "=dx,dx")
(and:SI (match_operand:SI 1 "register_operand" "%0,0") (define_split
(match_operand:SI 2 "nonmemory_operand" "N,dxi"))) [(parallel [(set (match_operand:SI 0 "register_operand" "")
(clobber (reg:CC CC_REG)) (and:SI (match_operand:SI 1 "register_operand" "")
] (const_int 255)))
(clobber (reg:CC CC_REG))])]
"" ""
{ [(set (match_dup 0) (zero_extend:SI (match_dup 1)))]
if (CONST_INT_P (operands[2])) { operands[1] = gen_lowpart (QImode, operands[1]); }
switch (INTVAL (operands[2])) )
{
case 0xff: return "extbu %0";
case 0xffff: return "exthu %0";
case 0x7fffffff: return "add %0, %0; lsr 1, %0";
case 0x3fffffff: return "asl2 %0; lsr 2, %0";
case 0x1fffffff: return "add %0, %0; asl2 %0; lsr 3, %0";
case 0x0fffffff: return "asl2 %0; asl2 %0; lsr 4, %0";
case 0xfffffffe: return "lsr 1, %0; add %0, %0";
case 0xfffffffc: return "lsr 2, %0; asl2 %0";
case 0xfffffff8: return "lsr 3, %0; add %0, %0; asl2 %0";
case 0xfffffff0: return "lsr 4, %0; asl2 %0; asl2 %0";
}
return "and %2, %0"; (define_split
} [(parallel [(set (match_operand:SI 0 "register_operand" "")
[(set_attr "timings" "33")] (and:SI (match_operand:SI 1 "register_operand" "")
(const_int 65535)))
(clobber (reg:CC CC_REG))])]
""
[(set (match_dup 0) (zero_extend:SI (match_dup 1)))]
{ operands[1] = gen_lowpart (HImode, operands[1]); }
) )
;; Split AND by an appropriate constant into two shifts. Recall that
;; operations with a full 32-bit immediate require an extra cycle, so
;; this is a size optimization with no speed penalty. This only applies
;; do DATA_REGS; the shift insns that AM33 adds are too large for a win.
(define_split
[(parallel [(set (match_operand:SI 0 "register_operand" "")
(and:SI (match_dup 0)
(match_operand:SI 1 "const_int_operand" "")))
(clobber (reg:CC CC_REG))])]
"reload_completed
&& REGNO_DATA_P (true_regnum (operands[0]), 1)
&& mn10300_split_and_operand_count (operands[1]) != 0"
[(const_int 0)]
{
int count = mn10300_split_and_operand_count (operands[1]);
if (count > 0)
{
emit_insn (gen_lshrsi3 (operands[0], operands[0], GEN_INT (count)));
emit_insn (gen_ashlsi3 (operands[0], operands[0], GEN_INT (count)));
}
else
{
emit_insn (gen_ashlsi3 (operands[0], operands[0], GEN_INT (-count)));
emit_insn (gen_lshrsi3 (operands[0], operands[0], GEN_INT (-count)));
}
DONE;
})
;; ---------------------------------------------------------------------- ;; ----------------------------------------------------------------------
;; OR INSTRUCTIONS ;; OR INSTRUCTIONS
;; ---------------------------------------------------------------------- ;; ----------------------------------------------------------------------
(define_expand "iorsi3" (define_insn "iorsi3"
[(parallel [(set (match_operand:SI 0 "register_operand") [(set (match_operand:SI 0 "register_operand" "=D,D,r")
(ior:SI (match_operand:SI 1 "register_operand") (ior:SI (match_operand:SI 1 "register_operand" "%0,0,r")
(match_operand:SI 2 "nonmemory_operand"))) (match_operand:SI 2 "nonmemory_operand" " i,D,r")))
(clobber (reg:CC CC_REG)) (clobber (reg:CC CC_REG))]
])
]
""
"")
(define_insn "*am33_iorsi3"
[(set (match_operand:SI 0 "register_operand" "=dx,!dax")
(ior:SI (match_operand:SI 1 "register_operand" "%0,dax")
(match_operand:SI 2 "nonmemory_operand" "dxi,dax")))
(clobber (reg:CC CC_REG))
]
"TARGET_AM33"
"*
{
if (REG_P (operands[2]) && REG_P (operands[1])
&& true_regnum (operands[0]) != true_regnum (operands[1])
&& true_regnum (operands[0]) != true_regnum (operands[2])
&& REGNO_REG_CLASS (true_regnum (operands[0])) == DATA_REGS
&& REGNO_REG_CLASS (true_regnum (operands[1])) == DATA_REGS
&& REGNO_REG_CLASS (true_regnum (operands[2])) == DATA_REGS)
return \"mov %1,%0\;or %2,%0\";
if (REG_P (operands[2]) && REG_P (operands[1])
&& true_regnum (operands[0]) != true_regnum (operands[1])
&& true_regnum (operands[0]) != true_regnum (operands[2]))
return \"or %1,%2,%0\";
if (REG_P (operands[2]) && REG_P (operands[0])
&& true_regnum (operands[2]) == true_regnum (operands[0]))
return \"or %1,%0\";
return \"or %2,%0\";
}"
[(set_attr "timings" "22")]
)
(define_insn "*mn10300_iorsi3"
[(set (match_operand:SI 0 "register_operand" "=dx")
(ior:SI (match_operand:SI 1 "register_operand" "%0")
(match_operand:SI 2 "nonmemory_operand" "dxi")))
(clobber (reg:CC CC_REG))
]
"" ""
"or %2,%0" "@
[(set_attr "timings" "33")] or %2,%0
or %2,%0
or %2,%1,%0"
[(set_attr "isa" "*,*,am33")
(set_attr "timings" "22,11,11")]
)
(define_insn "*iorsi3_flags"
[(set (match_operand:SI 0 "register_operand" "=D,D,r")
(ior:SI (match_operand:SI 1 "register_operand" "%0,0,r")
(match_operand:SI 2 "nonmemory_operand" " i,D,r")))
(set (reg CC_REG)
(compare (ior:SI (match_dup 1) (match_dup 2))
(const_int 0)))]
"reload_completed && mn10300_match_ccmode (insn, CCZNmode)"
"@
or %2,%0
or %2,%0
or %2,%1,%0"
[(set_attr "isa" "*,*,am33")
(set_attr "timings" "22,11,11")]
) )
;; ---------------------------------------------------------------------- ;; ----------------------------------------------------------------------
;; XOR INSTRUCTIONS ;; XOR INSTRUCTIONS
;; ---------------------------------------------------------------------- ;; ----------------------------------------------------------------------
(define_expand "xorsi3" (define_insn "xorsi3"
[(parallel [(set (match_operand:SI 0 "register_operand") [(set (match_operand:SI 0 "register_operand" "=D,D,r")
(xor:SI (match_operand:SI 1 "register_operand") (xor:SI (match_operand:SI 1 "register_operand" "%0,0,r")
(match_operand:SI 2 "nonmemory_operand"))) (match_operand:SI 2 "nonmemory_operand" " i,D,r")))
(clobber (reg:CC CC_REG)) (clobber (reg:CC CC_REG))]
])
]
""
"")
(define_insn "*am33_xorsi3"
[(set (match_operand:SI 0 "register_operand" "=dx,!dax")
(xor:SI (match_operand:SI 1 "register_operand" "%0,dax")
(match_operand:SI 2 "nonmemory_operand" "dxi,dax")))
(clobber (reg:CC CC_REG))
]
"TARGET_AM33"
"*
{
if (REG_P (operands[2]) && REG_P (operands[1])
&& true_regnum (operands[0]) != true_regnum (operands[1])
&& true_regnum (operands[0]) != true_regnum (operands[2])
&& REGNO_REG_CLASS (true_regnum (operands[0])) == DATA_REGS
&& REGNO_REG_CLASS (true_regnum (operands[1])) == DATA_REGS
&& REGNO_REG_CLASS (true_regnum (operands[2])) == DATA_REGS)
return \"mov %1,%0\;xor %2,%0\";
if (REG_P (operands[2]) && REG_P (operands[1])
&& true_regnum (operands[0]) != true_regnum (operands[1])
&& true_regnum (operands[0]) != true_regnum (operands[2]))
return \"xor %1,%2,%0\";
if (REG_P (operands[2]) && REG_P (operands[0])
&& true_regnum (operands[2]) == true_regnum (operands[0]))
return \"xor %1,%0\";
return \"xor %2,%0\";
}"
[(set_attr "timings" "22")]
)
(define_insn "*mn10300_xorsi3"
[(set (match_operand:SI 0 "register_operand" "=dx")
(xor:SI (match_operand:SI 1 "register_operand" "%0")
(match_operand:SI 2 "nonmemory_operand" "dxi")))
(clobber (reg:CC CC_REG))
]
"" ""
"xor %2,%0" "@
[(set_attr "timings" "11")] xor %2,%0
xor %2,%0
xor %2,%1,%0"
[(set_attr "isa" "*,*,am33")
(set_attr "timings" "22,11,11")]
)
(define_insn "*xorsi3_flags"
[(set (match_operand:SI 0 "register_operand" "=D,D,r")
(xor:SI (match_operand:SI 1 "register_operand" "%0,0,r")
(match_operand:SI 2 "nonmemory_operand" " i,D,r")))
(set (reg CC_REG)
(compare (xor:SI (match_dup 1) (match_dup 2))
(const_int 0)))]
"reload_completed && mn10300_match_ccmode (insn, CCZNmode)"
"@
xor %2,%0
xor %2,%0
xor %2,%1,%0"
[(set_attr "isa" "*,*,am33")
(set_attr "timings" "22,11,11")]
) )
;; ---------------------------------------------------------------------- ;; ----------------------------------------------------------------------
;; NOT INSTRUCTIONS ;; NOT INSTRUCTIONS
;; ---------------------------------------------------------------------- ;; ----------------------------------------------------------------------
(define_expand "one_cmplsi2" (define_insn "one_cmplsi2"
[(parallel [(set (match_operand:SI 0 "register_operand") [(set (match_operand:SI 0 "register_operand" "=D")
(not:SI (match_operand:SI 1 "register_operand"))) (not:SI (match_operand:SI 1 "register_operand" " 0")))
(clobber (reg:CC CC_REG)) (clobber (reg:CC CC_REG))]
])
]
"" ""
"")
(define_insn "*am33_cmplsi2"
[(set (match_operand:SI 0 "register_operand" "=dx,!dax")
(not:SI (match_operand:SI 1 "register_operand" "0,0")))
(clobber (reg:CC CC_REG))
]
"TARGET_AM33"
"not %0" "not %0"
) )
(define_insn "*mn10300_cmplsi2" (define_insn "*one_cmplsi2_flags"
[(set (match_operand:SI 0 "register_operand" "=dx") [(set (match_operand:SI 0 "register_operand" "=D")
(not:SI (match_operand:SI 1 "register_operand" "0"))) (not:SI (match_operand:SI 1 "register_operand" " 0")))
(clobber (reg:CC CC_REG)) (set (reg CC_REG)
] (compare (not:SI (match_dup 1))
"" (const_int 0)))]
"reload_completed && mn10300_match_ccmode (insn, CCZNmode)"
"not %0" "not %0"
) )
...@@ -1165,140 +987,133 @@ ...@@ -1165,140 +987,133 @@
(match_operator 0 "ordered_comparison_operator" (match_operator 0 "ordered_comparison_operator"
[(match_operand:SI 1 "register_operand") [(match_operand:SI 1 "register_operand")
(match_operand:SI 2 "nonmemory_operand")]) (match_operand:SI 2 "nonmemory_operand")])
(label_ref (match_operand 3 "")) (label_ref (match_operand 3 ""))
(pc)))] (pc)))]
"" ""
"" ""
) )
(define_insn_and_split "*cbranchsi4_post_reload" (define_insn_and_split "*cbranchsi4_cmp"
[(set (pc) [(set (pc)
(if_then_else (match_operator 3 "ordered_comparison_operator" (if_then_else (match_operator 3 "ordered_comparison_operator"
[(match_operand:SI 0 "register_operand" "dax") [(match_operand:SI 0 "register_operand" "r")
(match_operand:SI 1 "nonmemory_operand" "daxi")]) (match_operand:SI 1 "nonmemory_operand" "ri")])
(label_ref (match_operand 2 "" "")) (match_operand 2 "label_ref_operand" "")
(pc))) (pc)))]
]
"" ""
"#" "#"
"reload_completed" "reload_completed"
[(const_int 0)] [(const_int 0)]
" {
/* We construct the split by hand as otherwise the JUMP_LABEL mn10300_split_cbranch (CCmode, operands[3], operands[2]);
attribute is not set correctly on the jump insn. */ DONE;
emit_insn (gen_cmpsi (operands[0], operands[1])); })
emit_jump_insn (gen_integer_conditional_branch
(gen_rtx_fmt_ee (GET_CODE (operands[3]),
CCmode,
gen_rtx_REG (CCmode, CC_REG),
const0_rtx),
operands[2]));
"
)
;; Ordinarily, the cmp instruction will set the Z bit of cc0 to 1 if (define_insn "*cmpsi"
;; its operands hold equal values, but the operands of a cmp [(set (reg CC_REG)
;; instruction must be distinct registers. In the case where we'd (compare (match_operand:SI 0 "register_operand" "r")
;; like to compare a register to itself, we can achieve this effect (match_operand:SI 1 "nonmemory_operand" "ri")))]
;; with a btst 0,d0 instead. (This will not alter the contents of d0 "reload_completed"
;; but will have the proper effect on cc0. Using d0 is arbitrary; any {
;; data register would work.) /* The operands of CMP must be distinct registers. In the case where
we've failed to optimize the comparison of a register to itself, we
;; Even though the first alternative would be preferable if it can must use another method to set the Z flag. We can achieve this
;; possibly match, reload must not be given the opportunity to attempt effect with a BTST 0,D0. This will not alter the contents of D0;
;; to use it. It assumes that such matches can only occur when one of the use of d0 is arbitrary; any data register would work. */
;; the operands is used for input and the other for output. Since if (rtx_equal_p (operands[0], operands[1]))
;; this is not the case, it abort()s. Indeed, such a reload cannot be return "btst 0,d0";
;; possibly satisfied, so just mark the alternative with a `!', so else
;; that it is not considered by reload. return "cmp %1,%0";
}
(define_insn "cmpsi"
[(set (reg:CC CC_REG)
(compare (match_operand:SI 0 "register_operand" "!*d*a*x,dax,dax")
(match_operand:SI 1 "nonmemory_operand" "*0,I,daxi")))]
""
{
if (which_alternative == 0)
return \"btst 0,d0\";
if (which_alternative == 1)
return mn10300_output_cmp (operands[0], insn);
return \"cmp %1,%0\";
}
[(set_attr_alternative "timings" [(set_attr_alternative "timings"
[(const_int 11) [(if_then_else (eq_attr "cpu" "am34") (const_int 11) (const_int 22))])]
(if_then_else (eq_attr "cpu" "am34")
(const_int 11) (const_int 22))
(const_int 22)
])
]
) )
(define_insn "integer_conditional_branch" (define_insn "*integer_conditional_branch"
[(set (pc) [(set (pc)
(if_then_else (match_operator 0 "comparison_operator" (if_then_else (match_operator 0 "comparison_operator"
[(reg:CC CC_REG) (const_int 0)]) [(match_operand 2 "int_mode_flags" "")
(const_int 0)])
(label_ref (match_operand 1 "" "")) (label_ref (match_operand 1 "" ""))
(pc)))] (pc)))]
"" "reload_completed"
"b%b0 %1" "b%b0 %1"
) )
(define_insn_and_split "*cbranchsi4_btst"
[(set (pc)
(if_then_else
(match_operator 3 "CCZN_comparison_operator"
[(and:SI (match_operand:SI 0 "register_operand" "D")
(match_operand:SI 1 "immediate_operand" "i"))
(const_int 0)])
(match_operand 2 "label_ref_operand" "")
(pc)))]
""
"#"
"reload_completed"
[(const_int 0)]
{
mn10300_split_cbranch (CCZNmode, operands[3], operands[2]);
DONE;
})
(define_insn "*btstsi"
[(set (reg:CCZN CC_REG)
(compare:CCZN
(and:SI (match_operand:SI 0 "register_operand" "D")
(match_operand:SI 1 "immediate_operand" "i"))
(const_int 0)))]
"reload_completed"
"btst %1,%0"
)
(define_expand "cbranchsf4" (define_expand "cbranchsf4"
[(set (pc) [(set (pc)
(if_then_else (if_then_else
(match_operator 0 "ordered_comparison_operator" (match_operator 0 "ordered_comparison_operator"
[(match_operand:SF 1 "register_operand") [(match_operand:SF 1 "register_operand")
(match_operand:SF 2 "nonmemory_operand")]) (match_operand:SF 2 "nonmemory_operand")])
(label_ref (match_operand 3 "")) (label_ref (match_operand 3 ""))
(pc)))] (pc)))]
"TARGET_AM33_2" "TARGET_AM33_2"
"" ""
) )
(define_insn_and_split "*cbranchsf4_post_reload" (define_insn_and_split "*cbranchsf4_cmp"
[(set (pc) [(set (pc)
(if_then_else (match_operator 3 "ordered_comparison_operator" (if_then_else (match_operator 3 "ordered_comparison_operator"
[(match_operand:SF 0 "register_operand" "f") [(match_operand:SF 0 "register_operand" "f")
(match_operand:SF 1 "nonmemory_operand" "fF")]) (match_operand:SF 1 "nonmemory_operand" "fF")])
(label_ref (match_operand 2 "" "")) (match_operand 2 "label_ref_operand" "")
(pc))) (pc)))
] ]
"TARGET_AM33_2" "TARGET_AM33_2"
"#" "#"
"&& reload_completed" "&& reload_completed"
[(const_int 0)] [(const_int 0)]
" {
/* We construct the split by hand as otherwise the JUMP_LABEL mn10300_split_cbranch (CC_FLOATmode, operands[3], operands[2]);
attribute is not set correctly on the jump insn. */ DONE;
emit_insn (gen_am33_cmpsf (operands[0], operands[1])); })
emit_jump_insn (gen_float_conditional_branch
(gen_rtx_fmt_ee (GET_CODE (operands[3]),
CC_FLOATmode,
gen_rtx_REG (CC_FLOATmode, CC_REG),
const0_rtx),
operands[2]));
"
)
(define_insn "am33_cmpsf" (define_insn "*am33_cmpsf"
[(set (reg:CC_FLOAT CC_REG) [(set (reg:CC_FLOAT CC_REG)
(compare:CC_FLOAT (match_operand:SF 0 "register_operand" "f") (compare:CC_FLOAT (match_operand:SF 0 "register_operand" "f")
(match_operand:SF 1 "nonmemory_operand" "fF")))] (match_operand:SF 1 "nonmemory_operand" "fF")))]
"TARGET_AM33_2" "TARGET_AM33_2 && reload_completed"
"fcmp %1, %0" "fcmp %1, %0"
[(set (attr "timings") (if_then_else (eq_attr "cpu" "am34") [(set (attr "timings") (if_then_else (eq_attr "cpu" "am34")
(const_int 17) (const_int 25)))] (const_int 17) (const_int 25)))]
) )
(define_insn "float_conditional_branch" (define_insn "*float_conditional_branch"
[(set (pc) [(set (pc)
(if_then_else (match_operator 0 "comparison_operator" (if_then_else (match_operator 0 "comparison_operator"
[(reg:CC_FLOAT CC_REG) (const_int 0)]) [(reg:CC_FLOAT CC_REG) (const_int 0)])
(label_ref (match_operand 1 "" "")) (label_ref (match_operand 1 "" ""))
(pc)))] (pc)))]
"TARGET_AM33_2" "TARGET_AM33_2 && reload_completed"
"fb%b0 %1" "fb%b0 %1"
[(set (attr "timings") (if_then_else (eq_attr "cpu" "am34") [(set (attr "timings") (if_then_else (eq_attr "cpu" "am34")
(const_int 44) (const_int 33)))] (const_int 44) (const_int 33)))]
...@@ -1340,7 +1155,6 @@ ...@@ -1340,7 +1155,6 @@
(match_operand:SI 2 "immediate_operand") (match_operand:SI 2 "immediate_operand")
(match_operand 3 "" "") (match_operand 4 "")] (match_operand 3 "" "") (match_operand 4 "")]
"" ""
"
{ {
rtx table = gen_reg_rtx (SImode); rtx table = gen_reg_rtx (SImode);
rtx index = gen_reg_rtx (SImode); rtx index = gen_reg_rtx (SImode);
...@@ -1360,7 +1174,7 @@ ...@@ -1360,7 +1174,7 @@
emit_jump_insn (gen_tablejump (addr, operands[3])); emit_jump_insn (gen_tablejump (addr, operands[3]));
DONE; DONE;
}") })
(define_insn "tablejump" (define_insn "tablejump"
[(set (pc) (match_operand:SI 0 "register_operand" "a")) [(set (pc) (match_operand:SI 0 "register_operand" "a"))
...@@ -1470,7 +1284,6 @@ ...@@ -1470,7 +1284,6 @@
(match_operand 1 "") (match_operand 1 "")
(match_operand 2 "")])] (match_operand 2 "")])]
"" ""
"
{ {
int i; int i;
...@@ -1482,7 +1295,7 @@ ...@@ -1482,7 +1295,7 @@
emit_move_insn (SET_DEST (set), SET_SRC (set)); emit_move_insn (SET_DEST (set), SET_SRC (set));
} }
DONE; DONE;
}") })
(define_insn "nop" (define_insn "nop"
[(const_int 0)] [(const_int 0)]
...@@ -1494,328 +1307,109 @@ ...@@ -1494,328 +1307,109 @@
;; EXTEND INSTRUCTIONS ;; EXTEND INSTRUCTIONS
;; ---------------------------------------------------------------------- ;; ----------------------------------------------------------------------
(define_expand "zero_extendqisi2" (define_insn "zero_extendqisi2"
[(set (match_operand:SI 0 "register_operand") [(set (match_operand:SI 0 "register_operand" "=D,D,r")
(zero_extend:SI (zero_extend:SI
(match_operand:QI 1 "nonimmediate_operand")))] (match_operand:QI 1 "nonimmediate_operand" " 0,m,r")))]
"" ""
"")
(define_insn "*zero_extendqisi2_am33"
[(set (match_operand:SI 0 "register_operand" "=dx,dx,dx,!dax,!dax,!dax")
(zero_extend:SI
(match_operand:QI 1 "nonimmediate_operand" "0,dax,m,0,dax,m")))]
"TARGET_AM33"
"@ "@
extbu %0 extbu %0
mov %1,%0\;extbu %0 movbu %1,%0
movbu %1,%0 extbu %1,%0"
extbu %0 [(set_attr "isa" "*,*,am33")
mov %1,%0\;extbu %0 (set_attr_alternative "timings"
movbu %1,%0" [(const_int 11)
[(set_attr_alternative "timings" (if_then_else (eq_attr "cpu" "am34")
[(const_int 11) (const_int 13) (const_int 24))
(const_int 22) (const_int 11)
(if_then_else (eq_attr "cpu" "am34") ])]
(const_int 13) (const_int 24))
(const_int 11)
(const_int 22)
(if_then_else (eq_attr "cpu" "am34")
(const_int 13) (const_int 24))
])
]
)
(define_insn "*zero_extendqisi2_mn10300"
[(set (match_operand:SI 0 "register_operand" "=dx,dx,dx")
(zero_extend:SI
(match_operand:QI 1 "nonimmediate_operand" "0,d,m")))]
""
"@
extbu %0
mov %1,%0\;extbu %0
movbu %1,%0"
[(set_attr_alternative "timings"
[(const_int 11)
(const_int 22)
(if_then_else (eq_attr "cpu" "am34")
(const_int 13) (const_int 24))
])
]
)
(define_expand "zero_extendhisi2"
[(set (match_operand:SI 0 "register_operand")
(zero_extend:SI
(match_operand:HI 1 "nonimmediate_operand")))]
""
"")
(define_insn "*zero_extendhisi2_am33"
[(set (match_operand:SI 0 "register_operand" "=dx,dx,dx,!dax,!dax,!dax")
(zero_extend:SI
(match_operand:HI 1 "nonimmediate_operand" "0,dax,m,0,dax,m")))]
"TARGET_AM33"
"@
exthu %0
mov %1,%0\;exthu %0
movhu %1,%0
exthu %0
mov %1,%0\;exthu %0
movhu %1,%0"
[(set_attr_alternative "timings"
[(const_int 11)
(const_int 22)
(if_then_else (eq_attr "cpu" "am34")
(const_int 13) (const_int 24))
(const_int 11)
(const_int 22)
(if_then_else (eq_attr "cpu" "am34")
(const_int 13) (const_int 24))
])
]
) )
(define_insn "*zero_extendhisi2_mn10300" (define_insn "zero_extendhisi2"
[(set (match_operand:SI 0 "register_operand" "=dx,dx,dx") [(set (match_operand:SI 0 "register_operand" "=D,D,r")
(zero_extend:SI (zero_extend:SI
(match_operand:HI 1 "nonimmediate_operand" "0,dx,m")))] (match_operand:HI 1 "nonimmediate_operand" " 0,m,r")))]
""
"@
exthu %0
mov %1,%0\;exthu %0
movhu %1,%0"
[(set_attr_alternative "timings"
[(const_int 11)
(const_int 22)
(if_then_else (eq_attr "cpu" "am34")
(const_int 13) (const_int 24))
])
]
)
;;- sign extension instructions
(define_expand "extendqisi2"
[(set (match_operand:SI 0 "register_operand")
(sign_extend:SI
(match_operand:QI 1 "register_operand")))]
"" ""
"")
(define_insn "*extendqisi2_am33"
[(set (match_operand:SI 0 "register_operand" "=dx,dx,!dax,!dax")
(sign_extend:SI
(match_operand:QI 1 "register_operand" "0,dx,0,dax")))]
"TARGET_AM33"
"@ "@
extb %0 exthu %0
mov %1,%0\;extb %0 movhu %1,%0
extb %0 exthu %1,%0"
mov %1,%0\;extb %0" [(set_attr "isa" "*,*,am33")
[(set_attr "timings" "11,22,11,22")] (set_attr_alternative "timings"
) [(const_int 11)
(if_then_else (eq_attr "cpu" "am34")
(define_insn "*extendqisi2_mn10300" (const_int 13) (const_int 24))
[(set (match_operand:SI 0 "register_operand" "=dx,dx") (const_int 11)])]
(sign_extend:SI
(match_operand:QI 1 "register_operand" "0,dx")))]
""
"@
extb %0
mov %1,%0\;extb %0"
[(set_attr "timings" "11,22")]
) )
(define_expand "extendhisi2" (define_insn "extendqisi2"
[(set (match_operand:SI 0 "register_operand") [(set (match_operand:SI 0 "register_operand" "=D,r")
(sign_extend:SI (sign_extend:SI
(match_operand:HI 1 "register_operand")))] (match_operand:QI 1 "register_operand" "0,r")))]
"" ""
"")
(define_insn "*extendhisi2_am33"
[(set (match_operand:SI 0 "register_operand" "=dx,dx,!dax,!dax")
(sign_extend:SI
(match_operand:HI 1 "register_operand" "0,dax,0,dax")))]
"TARGET_AM33"
"@ "@
exth %0 extb %0
mov %1,%0\;exth %0 extb %1,%0"
exth %0 [(set_attr "isa" "*,am33")]
mov %1,%0\;exth %0"
[(set_attr "timings" "11,22,11,22")]
) )
(define_insn "*extendhisi2_mn10300" (define_insn "extendhisi2"
[(set (match_operand:SI 0 "register_operand" "=dx,dx") [(set (match_operand:SI 0 "register_operand" "=D,r")
(sign_extend:SI (sign_extend:SI
(match_operand:HI 1 "register_operand" "0,dx")))] (match_operand:HI 1 "register_operand" "0,r")))]
"" ""
"@ "@
exth %0 exth %0
mov %1,%0\;exth %0" exth %1,%0"
[(set_attr "timings" "11,22")] [(set_attr "isa" "*,am33")]
) )
;; ---------------------------------------------------------------------- ;; ----------------------------------------------------------------------
;; SHIFTS ;; SHIFTS
;; ---------------------------------------------------------------------- ;; ----------------------------------------------------------------------
(define_expand "ashlsi3" (define_insn "ashlsi3"
[(parallel [(set (match_operand:SI 0 "register_operand") [(set (match_operand:SI 0 "register_operand" "=r,D,d,d, D,r")
(ashift:SI
(match_operand:SI 1 "register_operand")
(match_operand:QI 2 "nonmemory_operand")))
(clobber (reg:CC CC_REG))
])
]
""
"")
(define_insn "*am33_ashlsi3"
[(set (match_operand:SI 0 "register_operand" "=dax,dx,!dax")
(ashift:SI (ashift:SI
(match_operand:SI 1 "register_operand" "0,0,dax") (match_operand:SI 1 "register_operand" " 0,0,0,0, 0,r")
(match_operand:QI 2 "nonmemory_operand" "J,dxi,dax"))) (match_operand:QI 2 "nonmemory_operand" " J,K,M,L,Di,r")))
(clobber (reg:CC CC_REG)) (clobber (reg:CC CC_REG))]
]
"TARGET_AM33"
"*
{
if (CONST_INT_P (operands[2]) && INTVAL (operands[2]) == 1)
return \"add %0,%0\";
if (CONST_INT_P (operands[2]) && INTVAL (operands[2]) == 2)
return \"asl2 %0\";
if (CONST_INT_P (operands[2]) && INTVAL (operands[2]) == 3
&& REGNO_REG_CLASS (true_regnum (operands[0])) == DATA_REGS)
return \"asl2 %0\;add %0,%0\";
if (CONST_INT_P (operands[2]) && INTVAL (operands[2]) == 4
&& REGNO_REG_CLASS (true_regnum (operands[0])) == DATA_REGS)
return \"asl2 %0\;asl2 %0\";
if (true_regnum (operands[1]) == true_regnum (operands[0]))
return \"asl %S2,%0\";
if (REGNO_REG_CLASS (true_regnum (operands[0])) == DATA_REGS
&& REGNO_REG_CLASS (true_regnum (operands[1])) == DATA_REGS
&& true_regnum (operands[0]) != true_regnum (operands[2]))
return \"mov %1,%0\;asl %S2,%0\";
return \"asl %2,%1,%0\";
}"
[(set_attr "timings" "22")]
)
(define_insn "*mn10300_ashlsi3"
[(set (match_operand:SI 0 "register_operand" "=dax,dx,dx,dx,dx")
(ashift:SI
(match_operand:SI 1 "register_operand" "0,0,0,0,0")
(match_operand:QI 2 "nonmemory_operand" "J,K,M,L,dxi")))
(clobber (reg:CC CC_REG))
]
"" ""
"@ "@
add %0,%0 add %0,%0
asl2 %0 asl2 %0
asl2 %0\;add %0,%0 asl2 %0\;add %0,%0
asl2 %0\;asl2 %0 asl2 %0\;asl2 %0
asl %S2,%0" asl %S2,%0
[(set_attr "timings" "11,11,22,22,11")] asl %2,%1,%0"
) [(set_attr "isa" "*,*,*,*,*,am33")
(set_attr "timings" "11,11,22,22,11,11")]
(define_expand "lshrsi3" )
[(parallel [(set (match_operand:SI 0 "register_operand")
(lshiftrt:SI (define_insn "lshrsi3"
(match_operand:SI 1 "register_operand") [(set (match_operand:SI 0 "register_operand" "=D,r")
(match_operand:QI 2 "nonmemory_operand")))
(clobber (reg:CC CC_REG))
])
]
""
"")
(define_insn "*am33_lshrsi3"
[(set (match_operand:SI 0 "register_operand" "=dx,!dax")
(lshiftrt:SI (lshiftrt:SI
(match_operand:SI 1 "register_operand" "0,dax") (match_operand:SI 1 "register_operand" " 0,r")
(match_operand:QI 2 "nonmemory_operand" "dxi,dax"))) (match_operand:QI 2 "nonmemory_operand" "Di,r")))
(clobber (reg:CC CC_REG)) (clobber (reg:CC CC_REG))]
]
"TARGET_AM33"
"*
{
if (true_regnum (operands[1]) == true_regnum (operands[0]))
return \"lsr %S2,%0\";
if (REGNO_REG_CLASS (true_regnum (operands[0])) == DATA_REGS
&& REGNO_REG_CLASS (true_regnum (operands[1])) == DATA_REGS
&& true_regnum (operands[0]) != true_regnum (operands[2]))
return \"mov %1,%0\;lsr %S2,%0\";
return \"lsr %2,%1,%0\";
}"
[(set_attr "timings" "22")]
)
(define_insn "*mn10300_lshrsi3"
[(set (match_operand:SI 0 "register_operand" "=dx")
(lshiftrt:SI
(match_operand:SI 1 "register_operand" "0")
(match_operand:QI 2 "nonmemory_operand" "dxi")))
(clobber (reg:CC CC_REG))
]
""
"lsr %S2,%0"
[(set (attr "timings") (if_then_else (eq_attr "cpu" "am34")
(const_int 11) (const_int 22)))]
)
(define_expand "ashrsi3"
[(parallel [(set (match_operand:SI 0 "register_operand")
(ashiftrt:SI
(match_operand:SI 1 "register_operand")
(match_operand:QI 2 "nonmemory_operand")))
(clobber (reg:CC CC_REG))
])
]
"" ""
"") "@
lsr %S2,%0
(define_insn "*am33_ashrisi3" lsr %2,%1,%0"
[(set (match_operand:SI 0 "register_operand" "=dx,!dax") [(set_attr "isa" "*,am33")]
(ashiftrt:SI
(match_operand:SI 1 "register_operand" "0,dax")
(match_operand:QI 2 "nonmemory_operand" "dxi,dax")))
(clobber (reg:CC CC_REG))
]
"TARGET_AM33"
"*
{
if (true_regnum (operands[1]) == true_regnum (operands[0]))
return \"asr %S2,%0\";
if (REGNO_REG_CLASS (true_regnum (operands[0])) == DATA_REGS
&& REGNO_REG_CLASS (true_regnum (operands[1])) == DATA_REGS
&& true_regnum (operands[0]) != true_regnum (operands[2]))
return \"mov %1,%0\;asr %S2,%0\";
return \"asr %2,%1,%0\";
}"
[(set_attr "timings" "22")]
) )
(define_insn "*mn10300_ashrsi3" (define_insn "ashrsi3"
[(set (match_operand:SI 0 "register_operand" "=dx") [(set (match_operand:SI 0 "register_operand" "=D,r")
(ashiftrt:SI (ashiftrt:SI
(match_operand:SI 1 "register_operand" "0") (match_operand:SI 1 "register_operand" " 0,r")
(match_operand:QI 2 "nonmemory_operand" "dxi"))) (match_operand:QI 2 "nonmemory_operand" "Di,r")))
(clobber (reg:CC CC_REG)) (clobber (reg:CC CC_REG))]
]
"" ""
"asr %S2,%0" "@
[(set (attr "timings") (if_then_else (eq_attr "cpu" "am34") asr %S2,%0
(const_int 11) (const_int 22)))] asr %2,%1,%0"
[(set_attr "isa" "*,am33")]
) )
;; ---------------------------------------------------------------------- ;; ----------------------------------------------------------------------
...@@ -2092,28 +1686,6 @@ ...@@ -2092,28 +1686,6 @@
[(set_attr "timings" "66")] [(set_attr "timings" "66")]
) )
;; Try to combine consecutive updates of the stack pointer (or any
;; other register for that matter).
(define_peephole
[(parallel [(set (match_operand:SI 0 "register_operand" "=dxay")
(plus:SI (match_dup 0)
(match_operand 1 "const_int_operand" "")))
(clobber (reg:CC CC_REG))
])
(parallel [(set (match_dup 0)
(plus:SI (match_dup 0)
(match_operand 2 "const_int_operand" "")))
(clobber (reg:CC CC_REG))
])
]
""
"*
{
operands[1] = GEN_INT (INTVAL (operands[2]) + INTVAL (operands[1]));
return \"add %1,%0\";
}"
)
(define_expand "int_label" (define_expand "int_label"
[(unspec [(match_operand:SI 0 "" "")] UNSPEC_INT_LABEL)] [(unspec [(match_operand:SI 0 "" "")] UNSPEC_INT_LABEL)]
"" "") "" "")
......
...@@ -42,3 +42,19 @@ ...@@ -42,3 +42,19 @@
return XEXP (op, 0) == stack_pointer_rtx return XEXP (op, 0) == stack_pointer_rtx
|| XEXP (op, 1) == stack_pointer_rtx; || XEXP (op, 1) == stack_pointer_rtx;
}) })
(define_predicate "label_ref_operand"
(match_code "label_ref"))
(define_special_predicate "int_mode_flags"
(match_code "reg")
{
if (REGNO (op) != CC_REG)
return false;
if (GET_MODE (op) == CC_FLOATmode)
return false;
return GET_MODE_CLASS (GET_MODE (op)) == MODE_CC;
})
(define_predicate "CCZN_comparison_operator"
(match_code "eq,ne,lt,ge"))
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment