Commit defc0463 by Richard Earnshaw Committed by Richard Earnshaw

arm-modes.def (CC_Nmode): New condition code mode.

* arm-modes.def (CC_Nmode): New condition code mode.
* arm.c (thumb_condition_code): Delete.
(arm_select_cc_mode): Handle single-bit test for Thumb.
(arm_print_operand, cases 'd' and 'D'): Don't special case the
condition code logic for Thumb.
(get_arm_condition_code): Handle CC_Nmode.
(thumb_cbrch_target_operand): New function.
* arm.h (PREDICATE_CODES): Add thumb_cbrch_target_operand.
* arm-protos.h (thumb_cbrch_target_operand): Add prototype.
* arm.md: Add Thumb split patterns for zero_extract and
sign_extract.
(tbit_cbranch, andsi3_cbranch_scratch, andsi3_cbranch)
(orrsi3_cbranch_scratch, orrsi3_cbranch, xorsi3_cbranch_scratch)
(xorsi3_cbranch, addsi3_cbranch, addsi3_cbranch_scratch)
(subsi3_cbranch, subsi3_cbranch_scratch): New Thumb patterns.
(cbranchne_decr1): Re-work to use CC_Nmode.

* arm.c (thumb_expand_epilogue): Add clobbers of registers restored
by the return instruction.  Add a use of the link register if it
wasn't stored.

From-SVN: r72595
parent 38b2a605
2003-10-17 Richard Earnshaw <rearnsha@arm.com>
* arm-modes.def (CC_Nmode): New condition code mode.
* arm.c (thumb_condition_code): Delete.
(arm_select_cc_mode): Handle single-bit test for Thumb.
(arm_print_operand, cases 'd' and 'D'): Don't special case the
condition code logic for Thumb.
(get_arm_condition_code): Handle CC_Nmode.
(thumb_cbrch_target_operand): New function.
* arm.h (PREDICATE_CODES): Add thumb_cbrch_target_operand.
* arm-protos.h (thumb_cbrch_target_operand): Add prototype.
* arm.md: Add Thumb split patterns for zero_extract and
sign_extract.
(tbit_cbranch, andsi3_cbranch_scratch, andsi3_cbranch)
(orrsi3_cbranch_scratch, orrsi3_cbranch, xorsi3_cbranch_scratch)
(xorsi3_cbranch, addsi3_cbranch, addsi3_cbranch_scratch)
(subsi3_cbranch, subsi3_cbranch_scratch): New Thumb patterns.
(cbranchne_decr1): Re-work to use CC_Nmode.
* arm.c (thumb_expand_epilogue): Add clobbers of registers restored
by the return instruction. Add a use of the link register if it
wasn't stored.
2003-10-17 Richard Earnshaw <rearnsha@arm.com>
* flow.c (init_propagate_block_info): Don't abort if a conditional
jump is not a comparison of a register. Instead, just don't record
conditional life information.
......
......@@ -30,6 +30,7 @@ FLOAT_MODE (XF, 12, 0);
CCFPmode should be used with floating equalities.
CC_NOOVmode should be used with SImode integer equalities.
CC_Zmode should be used if only the Z flag is set correctly
CC_Nmode should be used if only the N (sign) flag is set correctly
CCmode should be used otherwise. */
CC_MODE (CC_NOOV);
......@@ -48,3 +49,4 @@ CC_MODE (CC_DLTU);
CC_MODE (CC_DGEU);
CC_MODE (CC_DGTU);
CC_MODE (CC_C);
CC_MODE (CC_N);
......@@ -178,6 +178,7 @@ extern const char *thumb_load_double_from_address (rtx *);
extern const char *thumb_output_move_mem_multiple (int, rtx *);
extern void thumb_expand_movstrqi (rtx *);
extern int thumb_cmp_operand (rtx, enum machine_mode);
extern int thumb_cbrch_target_operand (rtx, enum machine_mode);
extern rtx *thumb_legitimize_pic_address (rtx, enum machine_mode, rtx);
extern int thumb_go_if_legitimate_address (enum machine_mode, rtx);
extern rtx arm_return_addr (int, rtx);
......
......@@ -86,7 +86,6 @@ static int number_of_first_bit_set (int);
static void replace_symbols_in_block (tree, rtx, rtx);
static void thumb_exit (FILE *, int, rtx);
static void thumb_pushpop (FILE *, int, int);
static const char *thumb_condition_code (rtx, int);
static rtx is_jump_table (rtx);
static HOST_WIDE_INT get_jump_table_size (rtx);
static Mnode *move_minipool_fix_forward_ref (Mnode *, Mnode *, HOST_WIDE_INT);
......@@ -5575,10 +5574,19 @@ arm_select_cc_mode (enum rtx_code op, rtx x, rtx y)
return arm_select_dominance_cc_mode (XEXP (x, 0), XEXP (x, 1),
DOM_CC_X_OR_Y);
/* An operation (on Thumb) where we want to test for a single bit.
This is done by shifting that bit up into the top bit of a
scratch register; we can then branch on the sign bit. */
if (TARGET_THUMB
&& GET_MODE (x) == SImode
&& (op == EQ || op == NE)
&& (GET_CODE (x) == ZERO_EXTRACT))
return CC_Nmode;
/* An operation that sets the condition codes as a side-effect, the
V flag is not set correctly, so we can only use comparisons where
this doesn't matter. (For LT and GE we can use "mi" and "pl"
instead. */
instead.) */
if (GET_MODE (x) == SImode
&& y == const0_rtx
&& (op == EQ || op == NE || op == LT || op == GE)
......@@ -5588,7 +5596,8 @@ arm_select_cc_mode (enum rtx_code op, rtx x, rtx y)
|| GET_CODE (x) == NOT || GET_CODE (x) == NEG
|| GET_CODE (x) == LSHIFTRT
|| GET_CODE (x) == ASHIFT || GET_CODE (x) == ASHIFTRT
|| GET_CODE (x) == ROTATERT || GET_CODE (x) == ZERO_EXTRACT))
|| GET_CODE (x) == ROTATERT
|| (TARGET_ARM && GET_CODE (x) == ZERO_EXTRACT)))
return CC_NOOVmode;
if (GET_MODE (x) == QImode && (op == EQ || op == NE))
......@@ -9557,11 +9566,8 @@ arm_print_operand (FILE *stream, rtx x, int code)
if (x == const_true_rtx)
return;
if (TARGET_ARM)
fputs (arm_condition_codes[get_arm_condition_code (x)],
stream);
else
fputs (thumb_condition_code (x, 0), stream);
fputs (arm_condition_codes[get_arm_condition_code (x)],
stream);
return;
case 'D':
......@@ -9570,12 +9576,9 @@ arm_print_operand (FILE *stream, rtx x, int code)
if (x == const_true_rtx)
abort ();
if (TARGET_ARM)
fputs (arm_condition_codes[ARM_INVERSE_CONDITION_CODE
(get_arm_condition_code (x))],
stream);
else
fputs (thumb_condition_code (x, 1), stream);
fputs (arm_condition_codes[ARM_INVERSE_CONDITION_CODE
(get_arm_condition_code (x))],
stream);
return;
/* Cirrus registers can be accessed in a variety of ways:
......@@ -9815,6 +9818,14 @@ get_arm_condition_code (rtx comparison)
default: abort ();
}
case CC_Nmode:
switch (comp_code)
{
case NE: return ARM_MI;
case EQ: return ARM_PL;
default: abort ();
}
case CCFPEmode:
case CCFPmode:
/* These encodings assume that AC=1 in the FPA system control
......@@ -12083,7 +12094,8 @@ thumb_expand_epilogue (void)
{
HOST_WIDE_INT amount = (thumb_get_frame_size ()
+ current_function_outgoing_args_size);
int regno;
/* Naked functions don't have prologues. */
if (IS_NAKED (arm_current_func_type ()))
return;
......@@ -12113,6 +12125,15 @@ thumb_expand_epilogue (void)
if (current_function_profile || TARGET_NO_SCHED_PRO)
emit_insn (gen_blockage ());
/* Emit a clobber for each insn that will be restored in the epilogue,
so that flow2 will get register lifetimes correct. */
for (regno = 0; regno < 13; regno++)
if (regs_ever_live[regno] && !call_used_regs[regno])
emit_insn (gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (SImode, regno)));
if (! regs_ever_live[LR_REGNUM])
emit_insn (gen_rtx_USE (VOIDmode, gen_rtx_REG (SImode, LR_REGNUM)));
}
static void
......@@ -12571,36 +12592,25 @@ thumb_cmp_operand (rtx op, enum machine_mode mode)
{
return ((GET_CODE (op) == CONST_INT
&& (unsigned HOST_WIDE_INT) (INTVAL (op)) < 256)
|| register_operand (op, mode));
|| s_register_operand (op, mode));
}
static const char *
thumb_condition_code (rtx x, int invert)
{
static const char * const conds[] =
{
"eq", "ne", "cs", "cc", "mi", "pl", "vs", "vc",
"hi", "ls", "ge", "lt", "gt", "le"
};
int val;
/* Return TRUE if a result can be stored in OP without clobbering the
condition code register. Prior to reload we only accept a
register. After reload we have to be able to handle memory as
well, since a pseudo may not get a hard reg and reload cannot
handle output-reloads on jump insns.
switch (GET_CODE (x))
{
case EQ: val = 0; break;
case NE: val = 1; break;
case GEU: val = 2; break;
case LTU: val = 3; break;
case GTU: val = 8; break;
case LEU: val = 9; break;
case GE: val = 10; break;
case LT: val = 11; break;
case GT: val = 12; break;
case LE: val = 13; break;
default:
abort ();
}
We could possibly handle mem before reload as well, but that might
complicate things with the need to handle increment
side-effects. */
return conds[val ^ invert];
int
thumb_cbrch_target_operand (rtx op, enum machine_mode mode)
{
return (s_register_operand (op, mode)
|| ((reload_in_progress || reload_completed)
&& memory_operand (op, mode)));
}
/* Handle storing a half-word to memory during reload. */
......
......@@ -2689,6 +2689,7 @@ extern int making_const_table;
{"reg_or_int_operand", {SUBREG, REG, CONST_INT}}, \
{"index_operand", {SUBREG, REG, CONST_INT}}, \
{"thumb_cmp_operand", {SUBREG, REG, CONST_INT}}, \
{"thumb_cbrch_target_operand", {SUBREG, REG, MEM}}, \
{"offsettable_memory_operand", {MEM}}, \
{"bad_signed_byte_operand", {MEM}}, \
{"alignable_memory_operand", {MEM}}, \
......
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