mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-03-25 05:30:25 +08:00
arm.h (CONDITIONAL_REGISTER_USAGE): Make r11 fixed and global for -mcaller-super-interworking.
* config/arm/arm.h (CONDITIONAL_REGISTER_USAGE): Make r11 fixed and global for -mcaller-super-interworking. (CALLER_INTERWORKING_SLOT_SIZE): New macro. * config/arm/arm.c (thumb_compute_save_reg_mask): Save r11 if CALLER_INTERWORKING_SLOT_SIZE is nonzero and the function does not need a frame pointer. (arm_get_frame_offsets): Add CALLER_INTERWORKING_SLOT_SIZE bytes to the soft frame pointer offset. (thumb_expand_prologue): Set up r11 for -mcaller-super-interworking. * config/arm/arm.md (*call_reg_thumb, *call_value_reg_thumb): Use _interwork_{r7,r11}_call_via_rN if some arguments are passed on the stack. Use frame_pointer_needed to choose between them. * config/arm/lib1funcs.asm (_arm_return_{r7,r11}): New functions. (interwork_with_frame): New macro. (interwork): Add _interwork_{r7,r11}_call_via_rN(). From-SVN: r89031
This commit is contained in:
parent
ef9af07733
commit
a25036452a
@ -1,3 +1,21 @@
|
||||
2004-10-14 Richard Sandiford <rsandifo@redhat.com>
|
||||
|
||||
* config/arm/arm.h (CONDITIONAL_REGISTER_USAGE): Make r11 fixed and
|
||||
global for -mcaller-super-interworking.
|
||||
(CALLER_INTERWORKING_SLOT_SIZE): New macro.
|
||||
* config/arm/arm.c (thumb_compute_save_reg_mask): Save r11 if
|
||||
CALLER_INTERWORKING_SLOT_SIZE is nonzero and the function does
|
||||
not need a frame pointer.
|
||||
(arm_get_frame_offsets): Add CALLER_INTERWORKING_SLOT_SIZE bytes to
|
||||
the soft frame pointer offset.
|
||||
(thumb_expand_prologue): Set up r11 for -mcaller-super-interworking.
|
||||
* config/arm/arm.md (*call_reg_thumb, *call_value_reg_thumb): Use
|
||||
_interwork_{r7,r11}_call_via_rN if some arguments are passed on
|
||||
the stack. Use frame_pointer_needed to choose between them.
|
||||
* config/arm/lib1funcs.asm (_arm_return_{r7,r11}): New functions.
|
||||
(interwork_with_frame): New macro.
|
||||
(interwork): Add _interwork_{r7,r11}_call_via_rN().
|
||||
|
||||
2004-10-14 Ben Elliston <bje@au.ibm.com>
|
||||
|
||||
PR other/17900
|
||||
|
@ -8741,6 +8741,9 @@ thumb_compute_save_reg_mask (void)
|
||||
mask |= (1 << PIC_OFFSET_TABLE_REGNUM);
|
||||
if (TARGET_SINGLE_PIC_BASE)
|
||||
mask &= ~(1 << arm_pic_register);
|
||||
/* See if we might need r11 for calls to _interwork_r11_call_via_rN(). */
|
||||
if (!frame_pointer_needed && CALLER_INTERWORKING_SLOT_SIZE > 0)
|
||||
mask |= 1 << ARM_HARD_FRAME_POINTER_REGNUM;
|
||||
|
||||
/* lr will also be pushed if any lo regs are pushed. */
|
||||
if (mask & 0xff || thumb_force_lr_save ())
|
||||
@ -9820,7 +9823,7 @@ arm_get_frame_offsets (void)
|
||||
|
||||
/* Saved registers include the stack frame. */
|
||||
offsets->saved_regs = offsets->saved_args + saved;
|
||||
offsets->soft_frame = offsets->saved_regs;
|
||||
offsets->soft_frame = offsets->saved_regs + CALLER_INTERWORKING_SLOT_SIZE;
|
||||
/* A leaf function does not need any stack alignment if it has nothing
|
||||
on the stack. */
|
||||
if (leaf && frame_size == 0)
|
||||
@ -12977,6 +12980,9 @@ thumb_expand_prologue (void)
|
||||
stack_pointer_rtx));
|
||||
RTX_FRAME_RELATED_P (insn) = 1;
|
||||
}
|
||||
else if (CALLER_INTERWORKING_SLOT_SIZE > 0)
|
||||
emit_move_insn (gen_rtx_REG (Pmode, ARM_HARD_FRAME_POINTER_REGNUM),
|
||||
stack_pointer_rtx);
|
||||
|
||||
amount = offsets->outgoing_args - offsets->saved_regs;
|
||||
if (amount)
|
||||
|
@ -917,10 +917,16 @@ extern const char * structure_size_string;
|
||||
fixed_regs[10] = 1; \
|
||||
call_used_regs[10] = 1; \
|
||||
} \
|
||||
if (TARGET_APCS_FRAME) \
|
||||
/* -mcaller-super-interworking reserves r11 for calls to \
|
||||
_interwork_r11_call_via_rN(). Making the register global \
|
||||
is an easy way of ensuring that it remains valid for all \
|
||||
calls. */ \
|
||||
if (TARGET_APCS_FRAME || TARGET_CALLER_INTERWORKING) \
|
||||
{ \
|
||||
fixed_regs[ARM_HARD_FRAME_POINTER_REGNUM] = 1; \
|
||||
call_used_regs[ARM_HARD_FRAME_POINTER_REGNUM] = 1; \
|
||||
if (TARGET_CALLER_INTERWORKING) \
|
||||
global_regs[ARM_HARD_FRAME_POINTER_REGNUM] = 1; \
|
||||
} \
|
||||
SUBTARGET_CONDITIONAL_REGISTER_USAGE \
|
||||
}
|
||||
@ -1519,6 +1525,20 @@ enum reg_class
|
||||
goes at a more negative offset in the frame. */
|
||||
#define FRAME_GROWS_DOWNWARD 1
|
||||
|
||||
/* The amount of scratch space needed by _interwork_{r7,r11}_call_via_rN().
|
||||
When present, it is one word in size, and sits at the top of the frame,
|
||||
between the soft frame pointer and either r7 or r11.
|
||||
|
||||
We only need _interwork_rM_call_via_rN() for -mcaller-super-interworking,
|
||||
and only then if some outgoing arguments are passed on the stack. It would
|
||||
be tempting to also check whether the stack arguments are passed by indirect
|
||||
calls, but there seems to be no reason in principle why a post-reload pass
|
||||
couldn't convert a direct call into an indirect one. */
|
||||
#define CALLER_INTERWORKING_SLOT_SIZE \
|
||||
(TARGET_CALLER_INTERWORKING \
|
||||
&& current_function_outgoing_args_size != 0 \
|
||||
? UNITS_PER_WORD : 0)
|
||||
|
||||
/* Offset within stack frame to start allocating local variables at.
|
||||
If FRAME_GROWS_DOWNWARD, this is the offset to the END of the
|
||||
first local allocated. Otherwise, it is the offset to the BEGINNING
|
||||
|
@ -7435,10 +7435,14 @@
|
||||
"TARGET_THUMB && !arm_arch5"
|
||||
"*
|
||||
{
|
||||
if (TARGET_CALLER_INTERWORKING)
|
||||
return \"bl\\t%__interwork_call_via_%0\";
|
||||
else
|
||||
if (!TARGET_CALLER_INTERWORKING)
|
||||
return \"bl\\t%__call_via_%0\";
|
||||
else if (operands[1] == const0_rtx)
|
||||
return \"bl\\t%__interwork_call_via_%0\";
|
||||
else if (frame_pointer_needed)
|
||||
return \"bl\\t%__interwork_r7_call_via_%0\";
|
||||
else
|
||||
return \"bl\\t%__interwork_r11_call_via_%0\";
|
||||
}"
|
||||
[(set_attr "type" "call")]
|
||||
)
|
||||
@ -7525,10 +7529,14 @@
|
||||
"TARGET_THUMB && !arm_arch5"
|
||||
"*
|
||||
{
|
||||
if (TARGET_CALLER_INTERWORKING)
|
||||
return \"bl\\t%__interwork_call_via_%1\";
|
||||
else
|
||||
if (!TARGET_CALLER_INTERWORKING)
|
||||
return \"bl\\t%__call_via_%1\";
|
||||
else if (operands[2] == const0_rtx)
|
||||
return \"bl\\t%__interwork_call_via_%1\";
|
||||
else if (frame_pointer_needed)
|
||||
return \"bl\\t%__interwork_r7_call_via_%1\";
|
||||
else
|
||||
return \"bl\\t%__interwork_r11_call_via_%1\";
|
||||
}"
|
||||
[(set_attr "type" "call")]
|
||||
)
|
||||
|
@ -1098,7 +1098,20 @@ LSYM(Lover12):
|
||||
the target code cannot be relied upon to return via a BX instruction, so
|
||||
instead we have to store the resturn address on the stack and allow the
|
||||
called function to return here instead. Upon return we recover the real
|
||||
return address and use a BX to get back to Thumb mode. */
|
||||
return address and use a BX to get back to Thumb mode.
|
||||
|
||||
There are three variations of this code. The first,
|
||||
_interwork_call_via_rN(), will push the return address onto the
|
||||
stack and pop it in _arm_return(). It should only be used if all
|
||||
arguments are passed in registers.
|
||||
|
||||
The second, _interwork_r7_call_via_rN(), instead stores the return
|
||||
address at [r7, #-4]. It is the caller's responsibility to ensure
|
||||
that this address is valid and contains no useful data.
|
||||
|
||||
The third, _interwork_r11_call_via_rN(), works in the same way but
|
||||
uses r11 instead of r7. It is useful if the caller does not really
|
||||
need a frame pointer. */
|
||||
|
||||
.text
|
||||
.align 0
|
||||
@ -1107,7 +1120,33 @@ LSYM(Lover12):
|
||||
.globl _arm_return
|
||||
_arm_return:
|
||||
RETLDM
|
||||
.code 16
|
||||
|
||||
.globl _arm_return_r7
|
||||
_arm_return_r7:
|
||||
ldr lr, [r7, #-4]
|
||||
bx lr
|
||||
|
||||
.globl _arm_return_r11
|
||||
_arm_return_r11:
|
||||
ldr lr, [r11, #-4]
|
||||
bx lr
|
||||
|
||||
.macro interwork_with_frame frame, register, name, return
|
||||
.code 16
|
||||
|
||||
THUMB_FUNC_START \name
|
||||
|
||||
bx pc
|
||||
nop
|
||||
|
||||
.code 32
|
||||
tst \register, #1
|
||||
streq lr, [\frame, #-4]
|
||||
adreq lr, _arm_return_\frame
|
||||
bx \register
|
||||
|
||||
SIZE (\name)
|
||||
.endm
|
||||
|
||||
.macro interwork register
|
||||
.code 16
|
||||
@ -1126,6 +1165,9 @@ LSYM(Lchange_\register):
|
||||
bx \register
|
||||
|
||||
SIZE (_interwork_call_via_\register)
|
||||
|
||||
interwork_with_frame r7,\register,_interwork_r7_call_via_\register
|
||||
interwork_with_frame r11,\register,_interwork_r11_call_via_\register
|
||||
.endm
|
||||
|
||||
interwork r0
|
||||
|
Loading…
x
Reference in New Issue
Block a user