aboutsummaryrefslogtreecommitdiff
path: root/gcc/config/arm/arm.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/config/arm/arm.c')
-rw-r--r--gcc/config/arm/arm.c48
1 files changed, 9 insertions, 39 deletions
diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
index 9123594..f9f5474 100644
--- a/gcc/config/arm/arm.c
+++ b/gcc/config/arm/arm.c
@@ -73,7 +73,6 @@ static int arm_legitimate_index_p (enum machine_mode, rtx, int);
static int thumb_base_register_rtx_p (rtx, enum machine_mode, int);
inline static int thumb_index_register_rtx_p (rtx, int);
static int const_ok_for_op (HOST_WIDE_INT, enum rtx_code);
-static int eliminate_lr2ip (rtx *);
static rtx emit_multi_reg_push (int);
static rtx emit_sfm (int, int);
#ifndef AOF_ASSEMBLER
@@ -6965,54 +6964,25 @@ output_call (rtx *operands)
return "";
}
-static int
-eliminate_lr2ip (rtx *x)
-{
- int something_changed = 0;
- rtx x0 = * x;
- int code = GET_CODE (x0);
- int i, j;
- const char * fmt;
-
- switch (code)
- {
- case REG:
- if (REGNO (x0) == LR_REGNUM)
- {
- *x = gen_rtx_REG (SImode, IP_REGNUM);
- return 1;
- }
- return 0;
- default:
- /* Scan through the sub-elements and change any references there. */
- fmt = GET_RTX_FORMAT (code);
-
- for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
- if (fmt[i] == 'e')
- something_changed |= eliminate_lr2ip (&XEXP (x0, i));
- else if (fmt[i] == 'E')
- for (j = 0; j < XVECLEN (x0, i); j++)
- something_changed |= eliminate_lr2ip (&XVECEXP (x0, i, j));
-
- return something_changed;
- }
-}
-
/* Output a 'call' insn that is a reference in memory. */
const char *
output_call_mem (rtx *operands)
{
- operands[0] = copy_rtx (operands[0]); /* Be ultra careful. */
- /* Handle calls using lr by using ip (which may be clobbered in subr anyway). */
- if (eliminate_lr2ip (&operands[0]))
- output_asm_insn ("mov%?\t%|ip, %|lr", operands);
-
if (TARGET_INTERWORK)
{
output_asm_insn ("ldr%?\t%|ip, %0", operands);
output_asm_insn ("mov%?\t%|lr, %|pc", operands);
output_asm_insn ("bx%?\t%|ip", operands);
}
+ else if (regno_use_in (LR_REGNUM, operands[0]))
+ {
+ /* LR is used in the memory address. We load the address in the
+ first instruction. It's safe to use IP as the target of the
+ load since the call will kill it anyway. */
+ output_asm_insn ("ldr%?\t%|ip, %0", operands);
+ output_asm_insn ("mov%?\t%|lr, %|pc", operands);
+ output_asm_insn ("mov%?\t%|pc, %|ip", operands);
+ }
else
{
output_asm_insn ("mov%?\t%|lr, %|pc", operands);