From: amodra Date: Tue, 28 Sep 2010 15:25:03 +0000 (+0000) Subject: PR target/45807 X-Git-Tag: upstream/4.9.2~26328 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=40d9d51c016e99320e08d0d6a579ba30cb58ca3d;p=platform%2Fupstream%2Flinaro-gcc.git 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 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 157ce82..a176a7a 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,14 @@ +2010-09-29 Alan Modra + + 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 * 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 0bf781e..f9004b4 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 62eed2e..b233261 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 a5e055e..0678fc0 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 5a3e333..6399cab 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) {