diff options
Diffstat (limited to 'gcc/config/arm/arm.c')
-rw-r--r-- | gcc/config/arm/arm.c | 48 |
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); |