aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Earnshaw <rearnsha@arm.com>2003-06-13 14:30:38 +0000
committerRichard Earnshaw <rearnsha@gcc.gnu.org>2003-06-13 14:30:38 +0000
commit6ab5da80508bc198963b872b6333eb968b3c273e (patch)
treeed8eb3b5b4a0867e6ea7eb1a724413c7d03ca435
parentcec57f7231040e0bd2d4fdce26d78592574abc21 (diff)
downloadgcc-6ab5da80508bc198963b872b6333eb968b3c273e.zip
gcc-6ab5da80508bc198963b872b6333eb968b3c273e.tar.gz
gcc-6ab5da80508bc198963b872b6333eb968b3c273e.tar.bz2
arm.c (output_call_mem): If the address references the link-register use an instruction sequence that...
* arm.c (output_call_mem): If the address references the link-register use an instruction sequence that avoids early-clobbering IP. (eliminate_lr2ip): Delete. From-SVN: r67899
-rw-r--r--gcc/ChangeLog6
-rw-r--r--gcc/config/arm/arm.c48
2 files changed, 15 insertions, 39 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 6e67d29..c86143d 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,9 @@
+2003-06-13 Richard Earnshaw <rearnsha@arm.com>
+
+ * arm.c (output_call_mem): If the address references the link-register
+ use an instruction sequence that avoids early-clobbering IP.
+ (eliminate_lr2ip): Delete.
+
2003-06-13 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
* c-format.c (format_types_orig): Disallow '*' width/precision in
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);