summaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authoramodra <amodra@138bc75d-0d04-0410-961f-82ee72b054a4>2010-09-28 15:25:03 +0000
committeramodra <amodra@138bc75d-0d04-0410-961f-82ee72b054a4>2010-09-28 15:25:03 +0000
commit40d9d51c016e99320e08d0d6a579ba30cb58ca3d (patch)
tree08b4a63df76a2d77b9e83f02da266c0e8d284a26 /gcc
parent9a086f1008c450f19232eb75ca4f09159bb178f9 (diff)
downloadgcc-40d9d51c016e99320e08d0d6a579ba30cb58ca3d.tar.gz
PR target/45807
* config/rs6000/aix.h (SETUP_FRAME_ADDRESSES): Delete. * config/rs6000/linux64.h (SETUP_FRAME_ADDRESSES): Delete. * config/rs6000/rs6000-protos.h (rs6000_aix_emit_builtin_unwind_init): Delete. * config/rs6000/rs6000.c (rs6000_aix_emit_builtin_unwind_init): Delete. (rs6000_emit_prologue): Don't just create frame save info for r2, actually save r2. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@164685 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog11
-rw-r--r--gcc/config/rs6000/aix.h7
-rw-r--r--gcc/config/rs6000/linux64.h8
-rw-r--r--gcc/config/rs6000/rs6000-protos.h1
-rw-r--r--gcc/config/rs6000/rs6000.c99
5 files changed, 58 insertions, 68 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 157ce824195..a176a7a33b5 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,14 @@
+2010-09-29 Alan Modra <amodra@gmail.com>
+
+ PR target/45807
+ * config/rs6000/aix.h (SETUP_FRAME_ADDRESSES): Delete.
+ * config/rs6000/linux64.h (SETUP_FRAME_ADDRESSES): Delete.
+ * config/rs6000/rs6000-protos.h (rs6000_aix_emit_builtin_unwind_init):
+ Delete.
+ * config/rs6000/rs6000.c (rs6000_aix_emit_builtin_unwind_init): Delete.
+ (rs6000_emit_prologue): Don't just create frame save info for r2,
+ actually save r2.
+
2010-09-28 Richard Henderson <rth@redhat.com>
* config/i386/cygming.h (ASM_OUTPUT_DWARF_OFFSET): Output 8 bytes
diff --git a/gcc/config/rs6000/aix.h b/gcc/config/rs6000/aix.h
index 0bf781e853f..f9004b4e6f0 100644
--- a/gcc/config/rs6000/aix.h
+++ b/gcc/config/rs6000/aix.h
@@ -207,13 +207,6 @@
/* And similarly for general purpose registers. */
#define GP_SAVE_INLINE(FIRST_REG) ((FIRST_REG) < 32)
-/* __throw will restore its own return address to be the same as the
- return address of the function that the throw is being made to.
- This is unfortunate, because we want to check the original
- return address to see if we need to restore the TOC.
- So we have to squirrel it away with this. */
-#define SETUP_FRAME_ADDRESSES() rs6000_aix_emit_builtin_unwind_init ()
-
/* If the current unwind info (FS) does not contain explicit info
saving R2, then we have to do a minor amount of code reading to
figure out if it was saved. The big problem here is that the
diff --git a/gcc/config/rs6000/linux64.h b/gcc/config/rs6000/linux64.h
index 62eed2edc28..b233261286c 100644
--- a/gcc/config/rs6000/linux64.h
+++ b/gcc/config/rs6000/linux64.h
@@ -305,14 +305,6 @@ extern enum rs6000_cmodel cmodel;
#define BLOCK_REG_PADDING(MODE, TYPE, FIRST) \
(!(FIRST) ? upward : FUNCTION_ARG_PADDING (MODE, TYPE))
-/* __throw will restore its own return address to be the same as the
- return address of the function that the throw is being made to.
- This is unfortunate, because we want to check the original
- return address to see if we need to restore the TOC.
- So we have to squirrel it away with this. */
-#define SETUP_FRAME_ADDRESSES() \
- do { if (TARGET_64BIT) rs6000_aix_emit_builtin_unwind_init (); } while (0)
-
/* Override svr4.h */
#undef MD_EXEC_PREFIX
#undef MD_STARTFILE_PREFIX
diff --git a/gcc/config/rs6000/rs6000-protos.h b/gcc/config/rs6000/rs6000-protos.h
index a5e055ed3cf..0678fc0d189 100644
--- a/gcc/config/rs6000/rs6000-protos.h
+++ b/gcc/config/rs6000/rs6000-protos.h
@@ -163,7 +163,6 @@ extern int rs6000_trampoline_size (void);
extern alias_set_type get_TOC_alias_set (void);
extern void rs6000_emit_prologue (void);
extern void rs6000_emit_load_toc_table (int);
-extern void rs6000_aix_emit_builtin_unwind_init (void);
extern unsigned int rs6000_dbx_register_number (unsigned int);
extern void rs6000_emit_epilogue (int);
extern void rs6000_emit_eh_reg_restore (rtx, rtx);
diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c
index 5a3e333ffbe..6399cab0d31 100644
--- a/gcc/config/rs6000/rs6000.c
+++ b/gcc/config/rs6000/rs6000.c
@@ -18916,42 +18916,6 @@ rs6000_aix_asm_output_dwarf_table_ref (char * frame_table_label)
fprintf (asm_out_file, "\t.ref %s\n",
TARGET_STRIP_NAME_ENCODING (frame_table_label));
}
-
-/* If _Unwind_* has been called from within the same module,
- toc register is not guaranteed to be saved to 40(1) on function
- entry. Save it there in that case. */
-
-void
-rs6000_aix_emit_builtin_unwind_init (void)
-{
- rtx mem;
- rtx stack_top = gen_reg_rtx (Pmode);
- rtx opcode_addr = gen_reg_rtx (Pmode);
- rtx opcode = gen_reg_rtx (SImode);
- rtx tocompare = gen_reg_rtx (SImode);
- rtx no_toc_save_needed = gen_label_rtx ();
-
- mem = gen_frame_mem (Pmode, hard_frame_pointer_rtx);
- emit_move_insn (stack_top, mem);
-
- mem = gen_frame_mem (Pmode,
- gen_rtx_PLUS (Pmode, stack_top,
- GEN_INT (2 * GET_MODE_SIZE (Pmode))));
- emit_move_insn (opcode_addr, mem);
- emit_move_insn (opcode, gen_rtx_MEM (SImode, opcode_addr));
- emit_move_insn (tocompare, gen_int_mode (TARGET_32BIT ? 0x80410014
- : 0xE8410028, SImode));
-
- do_compare_rtx_and_jump (opcode, tocompare, EQ, 1,
- SImode, NULL_RTX, NULL_RTX,
- no_toc_save_needed, -1);
-
- mem = gen_frame_mem (Pmode,
- gen_rtx_PLUS (Pmode, stack_top,
- GEN_INT (5 * GET_MODE_SIZE (Pmode))));
- emit_move_insn (mem, gen_rtx_REG (Pmode, 2));
- emit_label (no_toc_save_needed);
-}
/* This ties together stack memory (MEM with an alias set of frame_alias_set)
and the change to the stack pointer. */
@@ -20237,22 +20201,6 @@ rs6000_emit_prologue (void)
{
unsigned int i, regno;
- /* In AIX ABI we need to pretend we save r2 here. */
- if (TARGET_AIX)
- {
- rtx addr, reg, mem;
-
- reg = gen_rtx_REG (reg_mode, 2);
- addr = gen_rtx_PLUS (Pmode, frame_reg_rtx,
- GEN_INT (sp_offset + 5 * reg_size));
- mem = gen_frame_mem (reg_mode, addr);
-
- insn = emit_move_insn (mem, reg);
- rs6000_frame_related (insn, frame_ptr_rtx, info->total_size,
- NULL_RTX, NULL_RTX);
- PATTERN (insn) = gen_blockage ();
- }
-
for (i = 0; ; ++i)
{
regno = EH_RETURN_DATA_REGNO (i);
@@ -20266,6 +20214,53 @@ rs6000_emit_prologue (void)
}
}
+ /* In AIX ABI we need to make sure r2 is really saved. */
+ if (TARGET_AIX && crtl->calls_eh_return)
+ {
+ rtx tmp_reg, tmp_reg_si, compare_result, toc_save_done, jump;
+ long toc_restore_insn;
+
+ gcc_assert (frame_reg_rtx == frame_ptr_rtx
+ || frame_reg_rtx == sp_reg_rtx);
+ tmp_reg = gen_rtx_REG (Pmode, 11);
+ tmp_reg_si = gen_rtx_REG (SImode, 11);
+ if (using_static_chain_p)
+ emit_move_insn (gen_rtx_REG (Pmode, 0), tmp_reg);
+ gcc_assert (saving_GPRs_inline && saving_FPRs_inline);
+ emit_move_insn (tmp_reg, gen_rtx_REG (Pmode, LR_REGNO));
+ /* Peek at instruction to which this function returns. If it's
+ restoring r2, then we know we've already saved r2. We can't
+ unconditionally save r2 because the value we have will already
+ be updated if we arrived at this function via a plt call or
+ toc adjusting stub. */
+ emit_move_insn (tmp_reg_si, gen_rtx_MEM (SImode, tmp_reg));
+ toc_restore_insn = ((TARGET_32BIT ? 0x80410014 : 0xE8410028)
+ ^ 0x80000000) - 0x80000000;
+ emit_insn (gen_xorsi3 (tmp_reg_si, tmp_reg_si,
+ GEN_INT (toc_restore_insn & ~0xffff)));
+ compare_result = gen_rtx_REG (CCUNSmode, CR0_REGNO);
+ validate_condition_mode (EQ, CCUNSmode);
+ emit_insn (gen_rtx_SET (VOIDmode, compare_result,
+ gen_rtx_COMPARE (CCUNSmode, tmp_reg_si,
+ GEN_INT (toc_restore_insn
+ & 0xffff))));
+ toc_save_done = gen_label_rtx ();
+ jump = gen_rtx_IF_THEN_ELSE (VOIDmode,
+ gen_rtx_EQ (VOIDmode, compare_result,
+ const0_rtx),
+ gen_rtx_LABEL_REF (VOIDmode, toc_save_done),
+ pc_rtx);
+ jump = emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx, jump));
+ JUMP_LABEL (jump) = toc_save_done;
+ LABEL_NUSES (toc_save_done) += 1;
+
+ emit_frame_save (frame_reg_rtx, frame_ptr_rtx, reg_mode, 2,
+ sp_offset + 5 * reg_size, info->total_size);
+ emit_label (toc_save_done);
+ if (using_static_chain_p)
+ emit_move_insn (tmp_reg, gen_rtx_REG (Pmode, 0));
+ }
+
/* Save CR if we use any that must be preserved. */
if (!WORLD_SAVE_P (info) && info->cr_save_p)
{