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> 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 * 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 jump is not a comparison of a register. Instead, just don't record
conditional life information. conditional life information.
......
...@@ -30,6 +30,7 @@ FLOAT_MODE (XF, 12, 0); ...@@ -30,6 +30,7 @@ FLOAT_MODE (XF, 12, 0);
CCFPmode should be used with floating equalities. CCFPmode should be used with floating equalities.
CC_NOOVmode should be used with SImode integer equalities. CC_NOOVmode should be used with SImode integer equalities.
CC_Zmode should be used if only the Z flag is set correctly 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. */ CCmode should be used otherwise. */
CC_MODE (CC_NOOV); CC_MODE (CC_NOOV);
...@@ -48,3 +49,4 @@ CC_MODE (CC_DLTU); ...@@ -48,3 +49,4 @@ CC_MODE (CC_DLTU);
CC_MODE (CC_DGEU); CC_MODE (CC_DGEU);
CC_MODE (CC_DGTU); CC_MODE (CC_DGTU);
CC_MODE (CC_C); CC_MODE (CC_C);
CC_MODE (CC_N);
...@@ -178,6 +178,7 @@ extern const char *thumb_load_double_from_address (rtx *); ...@@ -178,6 +178,7 @@ extern const char *thumb_load_double_from_address (rtx *);
extern const char *thumb_output_move_mem_multiple (int, rtx *); extern const char *thumb_output_move_mem_multiple (int, rtx *);
extern void thumb_expand_movstrqi (rtx *); extern void thumb_expand_movstrqi (rtx *);
extern int thumb_cmp_operand (rtx, enum machine_mode); 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 rtx *thumb_legitimize_pic_address (rtx, enum machine_mode, rtx);
extern int thumb_go_if_legitimate_address (enum machine_mode, rtx); extern int thumb_go_if_legitimate_address (enum machine_mode, rtx);
extern rtx arm_return_addr (int, rtx); extern rtx arm_return_addr (int, rtx);
......
...@@ -86,7 +86,6 @@ static int number_of_first_bit_set (int); ...@@ -86,7 +86,6 @@ static int number_of_first_bit_set (int);
static void replace_symbols_in_block (tree, rtx, rtx); static void replace_symbols_in_block (tree, rtx, rtx);
static void thumb_exit (FILE *, int, rtx); static void thumb_exit (FILE *, int, rtx);
static void thumb_pushpop (FILE *, int, int); static void thumb_pushpop (FILE *, int, int);
static const char *thumb_condition_code (rtx, int);
static rtx is_jump_table (rtx); static rtx is_jump_table (rtx);
static HOST_WIDE_INT get_jump_table_size (rtx); static HOST_WIDE_INT get_jump_table_size (rtx);
static Mnode *move_minipool_fix_forward_ref (Mnode *, Mnode *, HOST_WIDE_INT); 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) ...@@ -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), return arm_select_dominance_cc_mode (XEXP (x, 0), XEXP (x, 1),
DOM_CC_X_OR_Y); 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 /* 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 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" this doesn't matter. (For LT and GE we can use "mi" and "pl"
instead. */ instead.) */
if (GET_MODE (x) == SImode if (GET_MODE (x) == SImode
&& y == const0_rtx && y == const0_rtx
&& (op == EQ || op == NE || op == LT || op == GE) && (op == EQ || op == NE || op == LT || op == GE)
...@@ -5588,7 +5596,8 @@ arm_select_cc_mode (enum rtx_code op, rtx x, rtx y) ...@@ -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) == NOT || GET_CODE (x) == NEG
|| GET_CODE (x) == LSHIFTRT || GET_CODE (x) == LSHIFTRT
|| GET_CODE (x) == ASHIFT || GET_CODE (x) == ASHIFTRT || 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; return CC_NOOVmode;
if (GET_MODE (x) == QImode && (op == EQ || op == NE)) if (GET_MODE (x) == QImode && (op == EQ || op == NE))
...@@ -9557,11 +9566,8 @@ arm_print_operand (FILE *stream, rtx x, int code) ...@@ -9557,11 +9566,8 @@ arm_print_operand (FILE *stream, rtx x, int code)
if (x == const_true_rtx) if (x == const_true_rtx)
return; return;
if (TARGET_ARM) fputs (arm_condition_codes[get_arm_condition_code (x)],
fputs (arm_condition_codes[get_arm_condition_code (x)], stream);
stream);
else
fputs (thumb_condition_code (x, 0), stream);
return; return;
case 'D': case 'D':
...@@ -9570,12 +9576,9 @@ arm_print_operand (FILE *stream, rtx x, int code) ...@@ -9570,12 +9576,9 @@ arm_print_operand (FILE *stream, rtx x, int code)
if (x == const_true_rtx) if (x == const_true_rtx)
abort (); abort ();
if (TARGET_ARM) fputs (arm_condition_codes[ARM_INVERSE_CONDITION_CODE
fputs (arm_condition_codes[ARM_INVERSE_CONDITION_CODE (get_arm_condition_code (x))],
(get_arm_condition_code (x))], stream);
stream);
else
fputs (thumb_condition_code (x, 1), stream);
return; return;
/* Cirrus registers can be accessed in a variety of ways: /* Cirrus registers can be accessed in a variety of ways:
...@@ -9815,6 +9818,14 @@ get_arm_condition_code (rtx comparison) ...@@ -9815,6 +9818,14 @@ get_arm_condition_code (rtx comparison)
default: abort (); default: abort ();
} }
case CC_Nmode:
switch (comp_code)
{
case NE: return ARM_MI;
case EQ: return ARM_PL;
default: abort ();
}
case CCFPEmode: case CCFPEmode:
case CCFPmode: case CCFPmode:
/* These encodings assume that AC=1 in the FPA system control /* These encodings assume that AC=1 in the FPA system control
...@@ -12083,7 +12094,8 @@ thumb_expand_epilogue (void) ...@@ -12083,7 +12094,8 @@ thumb_expand_epilogue (void)
{ {
HOST_WIDE_INT amount = (thumb_get_frame_size () HOST_WIDE_INT amount = (thumb_get_frame_size ()
+ current_function_outgoing_args_size); + current_function_outgoing_args_size);
int regno;
/* Naked functions don't have prologues. */ /* Naked functions don't have prologues. */
if (IS_NAKED (arm_current_func_type ())) if (IS_NAKED (arm_current_func_type ()))
return; return;
...@@ -12113,6 +12125,15 @@ thumb_expand_epilogue (void) ...@@ -12113,6 +12125,15 @@ thumb_expand_epilogue (void)
if (current_function_profile || TARGET_NO_SCHED_PRO) if (current_function_profile || TARGET_NO_SCHED_PRO)
emit_insn (gen_blockage ()); 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 static void
...@@ -12571,36 +12592,25 @@ thumb_cmp_operand (rtx op, enum machine_mode mode) ...@@ -12571,36 +12592,25 @@ thumb_cmp_operand (rtx op, enum machine_mode mode)
{ {
return ((GET_CODE (op) == CONST_INT return ((GET_CODE (op) == CONST_INT
&& (unsigned HOST_WIDE_INT) (INTVAL (op)) < 256) && (unsigned HOST_WIDE_INT) (INTVAL (op)) < 256)
|| register_operand (op, mode)); || s_register_operand (op, mode));
} }
static const char * /* Return TRUE if a result can be stored in OP without clobbering the
thumb_condition_code (rtx x, int invert) condition code register. Prior to reload we only accept a
{ register. After reload we have to be able to handle memory as
static const char * const conds[] = well, since a pseudo may not get a hard reg and reload cannot
{ handle output-reloads on jump insns.
"eq", "ne", "cs", "cc", "mi", "pl", "vs", "vc",
"hi", "ls", "ge", "lt", "gt", "le"
};
int val;
switch (GET_CODE (x)) We could possibly handle mem before reload as well, but that might
{ complicate things with the need to handle increment
case EQ: val = 0; break; side-effects. */
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 ();
}
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. */ /* Handle storing a half-word to memory during reload. */
......
...@@ -2689,6 +2689,7 @@ extern int making_const_table; ...@@ -2689,6 +2689,7 @@ extern int making_const_table;
{"reg_or_int_operand", {SUBREG, REG, CONST_INT}}, \ {"reg_or_int_operand", {SUBREG, REG, CONST_INT}}, \
{"index_operand", {SUBREG, REG, CONST_INT}}, \ {"index_operand", {SUBREG, REG, CONST_INT}}, \
{"thumb_cmp_operand", {SUBREG, REG, CONST_INT}}, \ {"thumb_cmp_operand", {SUBREG, REG, CONST_INT}}, \
{"thumb_cbrch_target_operand", {SUBREG, REG, MEM}}, \
{"offsettable_memory_operand", {MEM}}, \ {"offsettable_memory_operand", {MEM}}, \
{"bad_signed_byte_operand", {MEM}}, \ {"bad_signed_byte_operand", {MEM}}, \
{"alignable_memory_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