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:
Richard Sandiford 2004-10-14 07:37:11 +00:00 committed by Richard Sandiford
parent ef9af07733
commit a25036452a
5 changed files with 104 additions and 10 deletions

View File

@ -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

View File

@ -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)

View File

@ -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

View File

@ -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")]
)

View File

@ -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