aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorPaul Brook <pbrook@gcc.gnu.org>2008-03-11 17:43:22 +0000
committerPaul Brook <pbrook@gcc.gnu.org>2008-03-11 17:43:22 +0000
commitec6237e4403c864d94378d7c6bd96a01ff2bc06e (patch)
tree9aab21af74f13d71b320c1bcf209e001e2f18eeb /gcc
parent2f6025a15b2eed2f15eb1a997330f097e4814641 (diff)
downloadgcc-ec6237e4403c864d94378d7c6bd96a01ff2bc06e.zip
gcc-ec6237e4403c864d94378d7c6bd96a01ff2bc06e.tar.gz
gcc-ec6237e4403c864d94378d7c6bd96a01ff2bc06e.tar.bz2
arm.c (use_return_insn): Check TARGET_APCS_FRAME.
2008-03-11 Paul Brook <paul@codesourcery.com> Vladimir Prus <vladimir@codesourcery.com> * config/arm/arm.c (use_return_insn): Check TARGET_APCS_FRAME. (arm_compute_save_reg0_reg12_mask): Always check if register 11 must be saved. Always safe hard frame pointer when frame_pointer_needeed. (arm_compute_save_reg_mask): Save IP and PC only with apcs frames. (arm_output_epilogue): Adjust Thumb2 codepath to be also invoked and work for ARM non-apcs frames. (arm_expand_prologue): Don't bother saving IP for non-apcs frame, since it's not clobbered by prologue code. Implement non-apcs frame layout. From-SVN: r133117
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog22
-rw-r--r--gcc/config/arm/arm.c105
2 files changed, 86 insertions, 41 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 7b7f9d7..c3fb00a 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,19 @@
+2008-03-11 Paul Brook <paul@codesourcery.com>
+ Vladimir Prus <vladimir@codesourcery.com>
+
+ * config/arm/arm.c (use_return_insn): Check TARGET_APCS_FRAME.
+ (arm_compute_save_reg0_reg12_mask): Always
+ check if register 11 must be saved. Always safe hard frame pointer
+ when frame_pointer_needeed.
+ (arm_compute_save_reg_mask): Save IP and PC
+ only with apcs frames.
+ (arm_output_epilogue): Adjust Thumb2 codepath to
+ be also invoked and work for ARM non-apcs frames.
+ (arm_expand_prologue): Don't bother saving IP
+ for non-apcs frame, since it's not clobbered by
+ prologue code. Implement non-apcs frame
+ layout.
+
2008-03-11 Paolo Bonzini <bonzini@gnu.org>
PR rtl-optimization/35281
@@ -6,9 +22,9 @@
2008-03-11 Paolo Bonzini <bonzini@gnu.org>
- * langhooks-def.h (LANG_HOOKS_CLEAR_BINDING_STACK): Delete.
- * langhooks.h (struct lang_hooks): Delete clear_binding_stack member.
- * toplev.c (compile_file): Don't call it.
+ * langhooks-def.h (LANG_HOOKS_CLEAR_BINDING_STACK): Delete.
+ * langhooks.h (struct lang_hooks): Delete clear_binding_stack member.
+ * toplev.c (compile_file): Don't call it.
2008-03-11 Uros Bizjak <ubizjak@gmail.com>
diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
index bddb0e2..531dd1fe 100644
--- a/gcc/config/arm/arm.c
+++ b/gcc/config/arm/arm.c
@@ -1662,7 +1662,8 @@ use_return_insn (int iscond, rtx sibling)
|| current_function_calls_alloca
/* Or if there is a stack adjustment. However, if the stack pointer
is saved on the stack, we can use a pre-incrementing stack load. */
- || !(stack_adjust == 0 || (frame_pointer_needed && stack_adjust == 4)))
+ || !(stack_adjust == 0 || (TARGET_APCS_FRAME && frame_pointer_needed
+ && stack_adjust == 4)))
return 0;
saved_int_regs = arm_compute_save_reg_mask ();
@@ -10706,25 +10707,14 @@ arm_compute_save_reg0_reg12_mask (void)
}
else
{
- /* In arm mode we handle r11 (FP) as a special case. */
- unsigned last_reg = TARGET_ARM ? 10 : 11;
-
/* In the normal case we only need to save those registers
which are call saved and which are used by this function. */
- for (reg = 0; reg <= last_reg; reg++)
+ for (reg = 0; reg <= 11; reg++)
if (df_regs_ever_live_p (reg) && ! call_used_regs[reg])
save_reg_mask |= (1 << reg);
/* Handle the frame pointer as a special case. */
- if (! TARGET_APCS_FRAME
- && ! frame_pointer_needed
- && df_regs_ever_live_p (HARD_FRAME_POINTER_REGNUM)
- && ! call_used_regs[HARD_FRAME_POINTER_REGNUM])
- save_reg_mask |= 1 << HARD_FRAME_POINTER_REGNUM;
- else if (! TARGET_APCS_FRAME
- && ! frame_pointer_needed
- && df_regs_ever_live_p (HARD_FRAME_POINTER_REGNUM)
- && ! call_used_regs[HARD_FRAME_POINTER_REGNUM])
+ if (frame_pointer_needed)
save_reg_mask |= 1 << HARD_FRAME_POINTER_REGNUM;
/* If we aren't loading the PIC register,
@@ -10775,7 +10765,7 @@ arm_compute_save_reg_mask (void)
/* If we are creating a stack frame, then we must save the frame pointer,
IP (which will hold the old stack pointer), LR and the PC. */
- if (frame_pointer_needed && TARGET_ARM)
+ if (TARGET_APCS_FRAME && frame_pointer_needed && TARGET_ARM)
save_reg_mask |=
(1 << ARM_HARD_FRAME_POINTER_REGNUM)
| (1 << IP_REGNUM)
@@ -11306,7 +11296,7 @@ arm_output_epilogue (rtx sibling)
if (saved_regs_mask & (1 << reg))
floats_offset += 4;
- if (frame_pointer_needed && TARGET_ARM)
+ if (TARGET_APCS_FRAME && frame_pointer_needed && TARGET_ARM)
{
/* This variable is for the Virtual Frame Pointer, not VFP regs. */
int vfp_offset = offsets->frame;
@@ -11452,32 +11442,60 @@ arm_output_epilogue (rtx sibling)
}
else
{
+ /* This branch is executed for ARM mode (non-apcs frames) and
+ Thumb-2 mode. Frame layout is essentially the same for those
+ cases, except that in ARM mode frame pointer points to the
+ first saved register, while in Thumb-2 mode the frame pointer points
+ to the last saved register.
+
+ It is possible to make frame pointer point to last saved
+ register in both cases, and remove some conditionals below.
+ That means that fp setup in prologue would be just "mov fp, sp"
+ and sp restore in epilogue would be just "mov sp, fp", whereas
+ now we have to use add/sub in those cases. However, the value
+ of that would be marginal, as both mov and add/sub are 32-bit
+ in ARM mode, and it would require extra conditionals
+ in arm_expand_prologue to distingish ARM-apcs-frame case
+ (where frame pointer is required to point at first register)
+ and ARM-non-apcs-frame. Therefore, such change is postponed
+ until real need arise. */
HOST_WIDE_INT amount;
int rfe;
/* Restore stack pointer if necessary. */
- if (frame_pointer_needed)
- {
- /* For Thumb-2 restore sp from the frame pointer.
- Operand restrictions mean we have to increment FP, then copy
- to SP. */
- amount = offsets->locals_base - offsets->saved_regs;
- operands[0] = hard_frame_pointer_rtx;
- }
- else
+ if (TARGET_ARM && frame_pointer_needed)
{
operands[0] = stack_pointer_rtx;
- amount = offsets->outgoing_args - offsets->saved_regs;
+ operands[1] = hard_frame_pointer_rtx;
+
+ operands[2] = GEN_INT (offsets->frame - offsets->saved_regs);
+ output_add_immediate (operands);
}
-
- if (amount)
+ else
{
- operands[1] = operands[0];
- operands[2] = GEN_INT (amount);
- output_add_immediate (operands);
+ if (frame_pointer_needed)
+ {
+ /* For Thumb-2 restore sp from the frame pointer.
+ Operand restrictions mean we have to incrememnt FP, then copy
+ to SP. */
+ amount = offsets->locals_base - offsets->saved_regs;
+ operands[0] = hard_frame_pointer_rtx;
+ }
+ else
+ {
+ operands[0] = stack_pointer_rtx;
+ amount = offsets->outgoing_args - offsets->saved_regs;
+ }
+
+ if (amount)
+ {
+ operands[1] = operands[0];
+ operands[2] = GEN_INT (amount);
+ output_add_immediate (operands);
+ }
+ if (frame_pointer_needed)
+ asm_fprintf (f, "\tmov\t%r, %r\n",
+ SP_REGNUM, HARD_FRAME_POINTER_REGNUM);
}
- if (frame_pointer_needed)
- asm_fprintf (f, "\tmov\t%r, %r\n",
- SP_REGNUM, HARD_FRAME_POINTER_REGNUM);
if (arm_fpu_arch == FPUTYPE_FPA_EMU2)
{
@@ -12320,7 +12338,10 @@ arm_expand_prologue (void)
emit_insn (gen_movsi (stack_pointer_rtx, r1));
}
- if (frame_pointer_needed && TARGET_ARM)
+ /* For APCS frames, if IP register is clobbered
+ when creating frame, save that register in a special
+ way. */
+ if (TARGET_APCS_FRAME && frame_pointer_needed && TARGET_ARM)
{
if (IS_INTERRUPT (func_type))
{
@@ -12419,13 +12440,13 @@ arm_expand_prologue (void)
}
/* If this is an interrupt service routine, and the link register
- is going to be pushed, and we are not creating a stack frame,
- (which would involve an extra push of IP and a pop in the epilogue)
+ is going to be pushed, and we're not generating extra
+ push of IP (needed when frame is needed and frame layout if apcs),
subtracting four from LR now will mean that the function return
can be done with a single instruction. */
if ((func_type == ARM_FT_ISR || func_type == ARM_FT_FIQ)
&& (live_regs_mask & (1 << LR_REGNUM)) != 0
- && ! frame_pointer_needed
+ && !(frame_pointer_needed && TARGET_APCS_FRAME)
&& TARGET_ARM)
{
rtx lr = gen_rtx_REG (SImode, LR_REGNUM);
@@ -12446,6 +12467,7 @@ arm_expand_prologue (void)
if (frame_pointer_needed && TARGET_ARM)
{
/* Create the new frame pointer. */
+ if (TARGET_APCS_FRAME)
{
insn = GEN_INT (-(4 + args_to_push + fp_offset));
insn = emit_insn (gen_addsi3 (hard_frame_pointer_rtx, ip_rtx, insn));
@@ -12467,6 +12489,13 @@ arm_expand_prologue (void)
emit_insn (gen_prologue_use (ip_rtx));
}
}
+ else
+ {
+ insn = GEN_INT (saved_regs - 4);
+ insn = emit_insn (gen_addsi3 (hard_frame_pointer_rtx,
+ stack_pointer_rtx, insn));
+ RTX_FRAME_RELATED_P (insn) = 1;
+ }
}
offsets = arm_get_frame_offsets ();