aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Brook <paul@codesourcery.com>2006-03-13 23:43:12 +0000
committerPaul Brook <paul@codesourcery.com>2006-03-13 23:43:12 +0000
commit1d70401e9e949ee5787a6c1bbda85b8a688ed03d (patch)
treec1a7651d363eb25e0bae31b972ead2b81e8d878b
parent9096dfefa7cda02a4b4f598e33c6c9da777f8174 (diff)
2006-03-13 Paul Brook <paul@codesourcery.com>
* gcc/config/arm/arm.c (arm_dwarf_handle_frame_unspec): New function. (TARGET_DWARF_HANDLE_FRAME_UNSPEC): Define. (arm_compute_save_reg0_reg12_mask): Save r0 if dynamic stack alignment is required. (arm_output_epilogue): Restore sp from r0. (arm_expand_prologue): Save sp in r0 before aligning stack. (arm_unwind_emit_sequence): Remove redundant SP push code. (arm_unwind_emit_set): Handle UNSPEC_STACK_ALIGN. * gcc/config/arm/arm.md (UNSPEC_STACK_ALIGN): Define. git-svn-id: https://gcc.gnu.org/svn/gcc/branches/csl/arm-4_1@112030 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--ChangeLog.csl12
-rw-r--r--gcc/config/arm/arm.c95
-rw-r--r--gcc/config/arm/arm.md2
3 files changed, 71 insertions, 38 deletions
diff --git a/ChangeLog.csl b/ChangeLog.csl
index 7a59a76cf6a..7030278d326 100644
--- a/ChangeLog.csl
+++ b/ChangeLog.csl
@@ -1,5 +1,17 @@
2006-03-13 Paul Brook <paul@codesourcery.com>
+ * gcc/config/arm/arm.c (arm_dwarf_handle_frame_unspec): New function.
+ (TARGET_DWARF_HANDLE_FRAME_UNSPEC): Define.
+ (arm_compute_save_reg0_reg12_mask): Save r0 if dynamic stack
+ alignment is required.
+ (arm_output_epilogue): Restore sp from r0.
+ (arm_expand_prologue): Save sp in r0 before aligning stack.
+ (arm_unwind_emit_sequence): Remove redundant SP push code.
+ (arm_unwind_emit_set): Handle UNSPEC_STACK_ALIGN.
+ * gcc/config/arm/arm.md (UNSPEC_STACK_ALIGN): Define.
+
+2006-03-13 Paul Brook <paul@codesourcery.com>
+
Merge from csl/sourcerygxx-4_1
2006-02-27 Nathan Sidwell <nathan@potter.codesourcery.com>
Backport the following
diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
index 5787824b77c..8b7390944a2 100644
--- a/gcc/config/arm/arm.c
+++ b/gcc/config/arm/arm.c
@@ -178,6 +178,7 @@ static bool arm_must_pass_in_stack (enum machine_mode, tree);
static void arm_unwind_emit (FILE *, rtx);
static bool arm_output_ttype (rtx);
#endif
+static void arm_dwarf_handle_frame_unspec (const char *, rtx, int);
static tree arm_cxx_guard_type (void);
static bool arm_cxx_guard_mask_bit (void);
@@ -361,6 +362,9 @@ static bool arm_tls_symbol_p (rtx x);
#define TARGET_ARM_EABI_UNWINDER true
#endif /* TARGET_UNWIND_INFO */
+#undef TARGET_DWARF_HANDLE_FRAME_UNSPEC
+#define TARGET_DWARF_HANDLE_FRAME_UNSPEC arm_dwarf_handle_frame_unspec
+
#undef TARGET_CANNOT_COPY_INSN_P
#define TARGET_CANNOT_COPY_INSN_P arm_cannot_copy_insn_p
@@ -9540,6 +9544,10 @@ arm_compute_save_reg0_reg12_mask (void)
&& (regs_ever_live[PIC_OFFSET_TABLE_REGNUM]
|| current_function_uses_pic_offset_table))
save_reg_mask |= 1 << PIC_OFFSET_TABLE_REGNUM;
+
+ /* The prologue will copy SP into R0, so save it. */
+ if (IS_STACKALIGN (func_type))
+ save_reg_mask |= 1;
}
/* Save registers so the exception handler can modify them. */
@@ -10414,8 +10422,7 @@ arm_output_epilogue (rtx sibling)
if (IS_STACKALIGN (func_type))
{
/* See comment in arm_expand_prologue. */
- asm_fprintf (f, "\tpop\t{%r}\n", IP_REGNUM);
- asm_fprintf (f, "\tmov\t%r, %r\n", SP_REGNUM, IP_REGNUM);
+ asm_fprintf (f, "\tmov\t%r, %r\n", SP_REGNUM, 0);
}
if (arm_arch5 || arm_arch4t)
asm_fprintf (f, "\tbx\t%r\n", LR_REGNUM);
@@ -11080,43 +11087,32 @@ arm_expand_prologue (void)
if (IS_STACKALIGN (func_type))
{
rtx dwarf;
+ rtx r0;
+ rtx r1;
/* Handle a word-aligned stack pointer. We generate the following:
- mov ip, sp
- push {ip}
- push {ip}
- sub ip, ip, #4
- bic ip, ip, #4
- mov sp, ip
- <Normal prologue+body+epilogue, leaving return address in LR>
- pop {ip}
- mov sp, ip
+ mov r0, sp
+ bic r1, r0, #7
+ mov sp, r1
+ <save and restore r0 in normal prologue/epilogue>
+ mov sp, r0
bx lr
- Generating accurate unwind information for this is tricky. Instead
- we just tell the unwinder that the first instruction pushes
- sp onto the stack. */
+ The unwinder doesn't need to know about the stack realignment.
+ Just tell it we saved SP in r0. */
gcc_assert (TARGET_THUMB2 && !arm_arch_notm && args_to_push == 0);
- dwarf = gen_rtx_SEQUENCE (VOIDmode, rtvec_alloc (2));
- XVECEXP (dwarf, 0, 0) =
- gen_rtx_SET (VOIDmode, gen_rtx_MEM (SImode,
- gen_rtx_PLUS (SImode, stack_pointer_rtx, GEN_INT (-4))),
- stack_pointer_rtx);
- XVECEXP (dwarf, 0, 1) =
- gen_rtx_SET (VOIDmode, stack_pointer_rtx,
- gen_rtx_PLUS (SImode, stack_pointer_rtx, GEN_INT(4)));
-
- insn = gen_movsi (ip_rtx, stack_pointer_rtx);
+ r0 = gen_rtx_REG (SImode, 0);
+ r1 = gen_rtx_REG (SImode, 1);
+ dwarf = gen_rtx_UNSPEC (SImode, NULL_RTVEC, UNSPEC_STACK_ALIGN);
+ dwarf = gen_rtx_SET (SImode, r0, dwarf);
+ insn = gen_movsi (r0, stack_pointer_rtx);
RTX_FRAME_RELATED_P (insn) = 1;
REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR,
dwarf, REG_NOTES (insn));
emit_insn (insn);
- insn = emit_multi_reg_push (1 << IP_REGNUM);
- insn = emit_multi_reg_push (1 << IP_REGNUM);
- emit_insn (gen_addsi3 (ip_rtx, ip_rtx, GEN_INT (-4)));
- emit_insn (gen_andsi3 (ip_rtx, ip_rtx, GEN_INT (~(HOST_WIDE_INT)4)));
- emit_insn (gen_movsi (stack_pointer_rtx, ip_rtx));
+ emit_insn (gen_andsi3 (r1, r0, GEN_INT (~(HOST_WIDE_INT)7)));
+ emit_insn (gen_movsi (stack_pointer_rtx, r1));
}
if (frame_pointer_needed && TARGET_ARM)
@@ -15849,14 +15845,6 @@ arm_unwind_emit_sequence (FILE * asm_out_file, rtx p)
if (GET_CODE (e) != SET)
abort ();
- if (GET_CODE (XEXP (e, 0)) == MEM)
- {
- /* Stack pointer push to align SP. */
- gcc_assert (rtx_equal_p (XEXP (e, 1), stack_pointer_rtx));
- asm_fprintf (asm_out_file, "\t.save {%r}\n", SP_REGNUM);
- return;
- }
-
/* First insn will adjust the stack pointer. */
if (GET_CODE (e) != SET
|| GET_CODE (XEXP (e, 0)) != REG
@@ -15956,6 +15944,7 @@ arm_unwind_emit_set (FILE * asm_out_file, rtx p)
{
rtx e0;
rtx e1;
+ unsigned reg;
e0 = XEXP (p, 0);
e1 = XEXP (p, 1);
@@ -15992,7 +15981,6 @@ arm_unwind_emit_set (FILE * asm_out_file, rtx p)
else if (REGNO (e0) == HARD_FRAME_POINTER_REGNUM)
{
HOST_WIDE_INT offset;
- unsigned reg;
if (GET_CODE (e1) == PLUS)
{
@@ -16019,6 +16007,13 @@ arm_unwind_emit_set (FILE * asm_out_file, rtx p)
/* Move from sp to reg. */
asm_fprintf (asm_out_file, "\t.movsp %r\n", REGNO (e0));
}
+ else if (GET_CODE (e1) == UNSPEC && XINT (e1, 1) == UNSPEC_STACK_ALIGN)
+ {
+ /* Stack pointer save before alignment. */
+ reg = REGNO (e0);
+ asm_fprintf (asm_out_file, "\t.unwind_raw 0, 0x%x @ vsp = r%d\n",
+ reg + 0x90, reg);
+ }
else
abort ();
break;
@@ -16084,6 +16079,30 @@ arm_output_ttype (rtx x)
#endif /* TARGET_UNWIND_INFO */
+/* Handle UNSPEC DWARF call frame instructions. These are needed for dynamic
+ stack alignment. */
+
+static void
+arm_dwarf_handle_frame_unspec (const char *label, rtx pattern, int index)
+{
+ rtx unspec = SET_SRC (pattern);
+ gcc_assert (GET_CODE (unspec) == UNSPEC);
+
+ switch (index)
+ {
+ case UNSPEC_STACK_ALIGN:
+ /* ??? We should set the CFA = (SP & ~7). At this point we haven't
+ put anything on the stack, so hopefully it won't matter.
+ CFA = SP will be correct after alignment. */
+ dwarf2out_reg_save_reg (label, stack_pointer_rtx,
+ SET_DEST (pattern));
+ break;
+ default:
+ gcc_unreachable ();
+ }
+}
+
+
/* Output unwind directives for the start/end of a function. */
void
diff --git a/gcc/config/arm/arm.md b/gcc/config/arm/arm.md
index 17c4faffc54..bbbc7e0362f 100644
--- a/gcc/config/arm/arm.md
+++ b/gcc/config/arm/arm.md
@@ -93,6 +93,8 @@
(UNSPEC_TLS 20) ; A symbol that has been treated properly for TLS usage.
(UNSPEC_PIC_LABEL 21) ; A label used for PIC access that does not appear in the
; instruction stream.
+ (UNSPEC_STACK_ALIGN 20) ; Doubleword aligned stack pointer. Used to
+ ; generate correct unwind information.
]
)