From 5f59286d82acdb9ab57b17d9f89cf7225a2c16dc Mon Sep 17 00:00:00 2001 From: jakub Date: Wed, 3 Jun 2009 17:28:00 +0000 Subject: [PATCH] * config/rs6000/rs6000.c (rs6000_emit_stack_reset): Return generated insn if it is changing sp. Use gen_add3_insn instead of conditionally gen_addsi3 and gen_adddi3. (offset_below_red_zone_p): New static inline function. (rs6000_emit_epilogue): Emit needed epilogue unwind info. Use gen_add3_insn instead of conditionally gen_addsi3 and gen_adddi3. * config/rs6000/ppc-asm.h: Include auto-host.h. (CFI_STARTPROC, CFI_ENDPROC, CFI_DEF_CFA_REGISTER, CFI_OFFSET, CFI_RESTORE): Define. * config/rs6000/crtresxgpr.asm: Add unwind info. * config/rs6000/crtresxfpr.asm: Likewise. * config/rs6000/crtresgpr.asm: Likewise. * config/rs6000/crtresfpr.asm: Likewise. * config/rs6000/crtsavgpr.asm: Likewise. * config/rs6000/crtsavfpr.asm: Likewise. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@148138 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/ChangeLog | 16 +++ gcc/config/rs6000/crtresfpr.asm | 2 + gcc/config/rs6000/crtresgpr.asm | 2 + gcc/config/rs6000/crtresxfpr.asm | 42 ++++++++ gcc/config/rs6000/crtresxgpr.asm | 42 ++++++++ gcc/config/rs6000/crtsavfpr.asm | 2 + gcc/config/rs6000/crtsavgpr.asm | 2 + gcc/config/rs6000/ppc-asm.h | 19 +++- gcc/config/rs6000/rs6000.c | 225 ++++++++++++++++++++++++++++----------- 9 files changed, 287 insertions(+), 65 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 100249c41fb..e28fd41818e 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,5 +1,21 @@ 2009-06-03 Jakub Jelinek + * config/rs6000/rs6000.c (rs6000_emit_stack_reset): Return generated + insn if it is changing sp. Use gen_add3_insn instead of + conditionally gen_addsi3 and gen_adddi3. + (offset_below_red_zone_p): New static inline function. + (rs6000_emit_epilogue): Emit needed epilogue unwind info. + Use gen_add3_insn instead of conditionally gen_addsi3 and gen_adddi3. + * config/rs6000/ppc-asm.h: Include auto-host.h. + (CFI_STARTPROC, CFI_ENDPROC, CFI_DEF_CFA_REGISTER, CFI_OFFSET, + CFI_RESTORE): Define. + * config/rs6000/crtresxgpr.asm: Add unwind info. + * config/rs6000/crtresxfpr.asm: Likewise. + * config/rs6000/crtresgpr.asm: Likewise. + * config/rs6000/crtresfpr.asm: Likewise. + * config/rs6000/crtsavgpr.asm: Likewise. + * config/rs6000/crtsavfpr.asm: Likewise. + * dwarf2out.c (output_cfi_directive): Pass 1 instead of 0 to second argument of DWARF2_FRAME_REG_OUT macros. diff --git a/gcc/config/rs6000/crtresfpr.asm b/gcc/config/rs6000/crtresfpr.asm index 7adc9c1e757..9fb228cf458 100644 --- a/gcc/config/rs6000/crtresfpr.asm +++ b/gcc/config/rs6000/crtresfpr.asm @@ -38,6 +38,7 @@ /* Called with r11 pointing to the stack header word of the caller of the */ /* function, just beyond the end of the floating point save area. */ +CFI_STARTPROC HIDDEN_FUNC(_restfpr_14) lfd 14,-144(11) /* restore fp registers */ HIDDEN_FUNC(_restfpr_15) lfd 15,-136(11) HIDDEN_FUNC(_restfpr_16) lfd 16,-128(11) @@ -75,5 +76,6 @@ FUNC_END(_restfpr_17) FUNC_END(_restfpr_16) FUNC_END(_restfpr_15) FUNC_END(_restfpr_14) +CFI_ENDPROC #endif diff --git a/gcc/config/rs6000/crtresgpr.asm b/gcc/config/rs6000/crtresgpr.asm index 4ed3d8e21c5..9f9cec9f9ca 100644 --- a/gcc/config/rs6000/crtresgpr.asm +++ b/gcc/config/rs6000/crtresgpr.asm @@ -38,6 +38,7 @@ /* Called with r11 pointing to the stack header word of the caller of the */ /* function, just beyond the end of the integer restore area. */ +CFI_STARTPROC HIDDEN_FUNC(_restgpr_14) lwz 14,-72(11) /* restore gp registers */ HIDDEN_FUNC(_restgpr_15) lwz 15,-68(11) HIDDEN_FUNC(_restgpr_16) lwz 16,-64(11) @@ -75,5 +76,6 @@ FUNC_END(_restgpr_17) FUNC_END(_restgpr_16) FUNC_END(_restgpr_15) FUNC_END(_restgpr_14) +CFI_ENDPROC #endif diff --git a/gcc/config/rs6000/crtresxfpr.asm b/gcc/config/rs6000/crtresxfpr.asm index 5a87a98052f..633f2db61f0 100644 --- a/gcc/config/rs6000/crtresxfpr.asm +++ b/gcc/config/rs6000/crtresxfpr.asm @@ -40,27 +40,68 @@ /* In addition to restoring the fp registers, it will return to the caller's */ /* caller */ +CFI_STARTPROC +CFI_DEF_CFA_REGISTER (11) +CFI_OFFSET (65, 4) +CFI_OFFSET (46, -144) +CFI_OFFSET (47, -136) +CFI_OFFSET (48, -128) +CFI_OFFSET (49, -120) +CFI_OFFSET (50, -112) +CFI_OFFSET (51, -104) +CFI_OFFSET (52, -96) +CFI_OFFSET (53, -88) +CFI_OFFSET (54, -80) +CFI_OFFSET (55, -72) +CFI_OFFSET (56, -64) +CFI_OFFSET (57, -56) +CFI_OFFSET (58, -48) +CFI_OFFSET (59, -40) +CFI_OFFSET (60, -32) +CFI_OFFSET (61, -24) +CFI_OFFSET (62, -16) +CFI_OFFSET (63, -8) HIDDEN_FUNC(_restfpr_14_x) lfd 14,-144(11) /* restore fp registers */ +CFI_RESTORE (46) HIDDEN_FUNC(_restfpr_15_x) lfd 15,-136(11) +CFI_RESTORE (47) HIDDEN_FUNC(_restfpr_16_x) lfd 16,-128(11) +CFI_RESTORE (48) HIDDEN_FUNC(_restfpr_17_x) lfd 17,-120(11) +CFI_RESTORE (49) HIDDEN_FUNC(_restfpr_18_x) lfd 18,-112(11) +CFI_RESTORE (50) HIDDEN_FUNC(_restfpr_19_x) lfd 19,-104(11) +CFI_RESTORE (51) HIDDEN_FUNC(_restfpr_20_x) lfd 20,-96(11) +CFI_RESTORE (52) HIDDEN_FUNC(_restfpr_21_x) lfd 21,-88(11) +CFI_RESTORE (53) HIDDEN_FUNC(_restfpr_22_x) lfd 22,-80(11) +CFI_RESTORE (54) HIDDEN_FUNC(_restfpr_23_x) lfd 23,-72(11) +CFI_RESTORE (55) HIDDEN_FUNC(_restfpr_24_x) lfd 24,-64(11) +CFI_RESTORE (56) HIDDEN_FUNC(_restfpr_25_x) lfd 25,-56(11) +CFI_RESTORE (57) HIDDEN_FUNC(_restfpr_26_x) lfd 26,-48(11) +CFI_RESTORE (58) HIDDEN_FUNC(_restfpr_27_x) lfd 27,-40(11) +CFI_RESTORE (59) HIDDEN_FUNC(_restfpr_28_x) lfd 28,-32(11) +CFI_RESTORE (60) HIDDEN_FUNC(_restfpr_29_x) lfd 29,-24(11) +CFI_RESTORE (61) HIDDEN_FUNC(_restfpr_30_x) lfd 30,-16(11) +CFI_RESTORE (62) HIDDEN_FUNC(_restfpr_31_x) lwz 0,4(11) lfd 31,-8(11) +CFI_RESTORE (63) mtlr 0 +CFI_RESTORE (65) mr 1,11 +CFI_DEF_CFA_REGISTER (1) blr FUNC_END(_restfpr_31_x) FUNC_END(_restfpr_30_x) @@ -80,5 +121,6 @@ FUNC_END(_restfpr_17_x) FUNC_END(_restfpr_16_x) FUNC_END(_restfpr_15_x) FUNC_END(_restfpr_14_x) +CFI_ENDPROC #endif diff --git a/gcc/config/rs6000/crtresxgpr.asm b/gcc/config/rs6000/crtresxgpr.asm index 9317131c8ce..451b2b69d1e 100644 --- a/gcc/config/rs6000/crtresxgpr.asm +++ b/gcc/config/rs6000/crtresxgpr.asm @@ -38,27 +38,68 @@ /* Called with r11 pointing to the stack header word of the caller of the */ /* function, just beyond the end of the integer restore area. */ +CFI_STARTPROC +CFI_DEF_CFA_REGISTER (11) +CFI_OFFSET (65, 4) +CFI_OFFSET (14, -72) +CFI_OFFSET (15, -68) +CFI_OFFSET (16, -64) +CFI_OFFSET (17, -60) +CFI_OFFSET (18, -56) +CFI_OFFSET (19, -52) +CFI_OFFSET (20, -48) +CFI_OFFSET (21, -44) +CFI_OFFSET (22, -40) +CFI_OFFSET (23, -36) +CFI_OFFSET (24, -32) +CFI_OFFSET (25, -28) +CFI_OFFSET (26, -24) +CFI_OFFSET (27, -20) +CFI_OFFSET (28, -16) +CFI_OFFSET (29, -12) +CFI_OFFSET (30, -8) +CFI_OFFSET (31, -4) HIDDEN_FUNC(_restgpr_14_x) lwz 14,-72(11) /* restore gp registers */ +CFI_RESTORE (14) HIDDEN_FUNC(_restgpr_15_x) lwz 15,-68(11) +CFI_RESTORE (15) HIDDEN_FUNC(_restgpr_16_x) lwz 16,-64(11) +CFI_RESTORE (16) HIDDEN_FUNC(_restgpr_17_x) lwz 17,-60(11) +CFI_RESTORE (17) HIDDEN_FUNC(_restgpr_18_x) lwz 18,-56(11) +CFI_RESTORE (18) HIDDEN_FUNC(_restgpr_19_x) lwz 19,-52(11) +CFI_RESTORE (19) HIDDEN_FUNC(_restgpr_20_x) lwz 20,-48(11) +CFI_RESTORE (20) HIDDEN_FUNC(_restgpr_21_x) lwz 21,-44(11) +CFI_RESTORE (21) HIDDEN_FUNC(_restgpr_22_x) lwz 22,-40(11) +CFI_RESTORE (22) HIDDEN_FUNC(_restgpr_23_x) lwz 23,-36(11) +CFI_RESTORE (23) HIDDEN_FUNC(_restgpr_24_x) lwz 24,-32(11) +CFI_RESTORE (24) HIDDEN_FUNC(_restgpr_25_x) lwz 25,-28(11) +CFI_RESTORE (25) HIDDEN_FUNC(_restgpr_26_x) lwz 26,-24(11) +CFI_RESTORE (26) HIDDEN_FUNC(_restgpr_27_x) lwz 27,-20(11) +CFI_RESTORE (27) HIDDEN_FUNC(_restgpr_28_x) lwz 28,-16(11) +CFI_RESTORE (28) HIDDEN_FUNC(_restgpr_29_x) lwz 29,-12(11) +CFI_RESTORE (29) HIDDEN_FUNC(_restgpr_30_x) lwz 30,-8(11) +CFI_RESTORE (30) HIDDEN_FUNC(_restgpr_31_x) lwz 0,4(11) lwz 31,-4(11) +CFI_RESTORE (31) mtlr 0 +CFI_RESTORE (65) mr 1,11 +CFI_DEF_CFA_REGISTER (1) blr FUNC_END(_restgpr_31_x) FUNC_END(_restgpr_30_x) @@ -78,5 +119,6 @@ FUNC_END(_restgpr_17_x) FUNC_END(_restgpr_16_x) FUNC_END(_restgpr_15_x) FUNC_END(_restgpr_14_x) +CFI_ENDPROC #endif diff --git a/gcc/config/rs6000/crtsavfpr.asm b/gcc/config/rs6000/crtsavfpr.asm index fe40a9e13d0..3cdb25033ca 100644 --- a/gcc/config/rs6000/crtsavfpr.asm +++ b/gcc/config/rs6000/crtsavfpr.asm @@ -38,6 +38,7 @@ /* Called with r11 pointing to the stack header word of the caller of the */ /* function, just beyond the end of the floating point save area. */ +CFI_STARTPROC HIDDEN_FUNC(_savefpr_14) stfd 14,-144(11) /* save fp registers */ HIDDEN_FUNC(_savefpr_15) stfd 15,-136(11) HIDDEN_FUNC(_savefpr_16) stfd 16,-128(11) @@ -75,5 +76,6 @@ FUNC_END(_savefpr_17) FUNC_END(_savefpr_16) FUNC_END(_savefpr_15) FUNC_END(_savefpr_14) +CFI_ENDPROC #endif diff --git a/gcc/config/rs6000/crtsavgpr.asm b/gcc/config/rs6000/crtsavgpr.asm index 6c5f6720934..6d473963bad 100644 --- a/gcc/config/rs6000/crtsavgpr.asm +++ b/gcc/config/rs6000/crtsavgpr.asm @@ -38,6 +38,7 @@ /* Called with r11 pointing to the stack header word of the caller of the */ /* function, just beyond the end of the integer save area. */ +CFI_STARTPROC HIDDEN_FUNC(_savegpr_14) stw 14,-72(11) /* save gp registers */ HIDDEN_FUNC(_savegpr_15) stw 15,-68(11) HIDDEN_FUNC(_savegpr_16) stw 16,-64(11) @@ -75,5 +76,6 @@ FUNC_END(_savegpr_17) FUNC_END(_savegpr_16) FUNC_END(_savegpr_15) FUNC_END(_savegpr_14) +CFI_ENDPROC #endif diff --git a/gcc/config/rs6000/ppc-asm.h b/gcc/config/rs6000/ppc-asm.h index 3a70a137b55..575187c3265 100644 --- a/gcc/config/rs6000/ppc-asm.h +++ b/gcc/config/rs6000/ppc-asm.h @@ -1,6 +1,6 @@ /* PowerPC asm definitions for GNU C. -Copyright (C) 2002, 2003, 2008 Free Software Foundation, Inc. +Copyright (C) 2002, 2003, 2008, 2009 Free Software Foundation, Inc. This file is part of GCC. @@ -196,6 +196,23 @@ GLUE(.L,name): \ .size FUNC_NAME(name),GLUE(.L,name)-FUNC_NAME(name) #endif +/* For HAVE_GAS_CFI_DIRECTIVE. */ +#include "auto-host.h" + +#ifdef HAVE_GAS_CFI_DIRECTIVE +# define CFI_STARTPROC .cfi_startproc +# define CFI_ENDPROC .cfi_endproc +# define CFI_OFFSET(reg, off) .cfi_offset reg, off +# define CFI_DEF_CFA_REGISTER(reg) .cfi_def_cfa_register reg +# define CFI_RESTORE(reg) .cfi_restore reg +#else +# define CFI_STARTPROC +# define CFI_ENDPROC +# define CFI_OFFSET(reg, off) +# define CFI_DEF_CFA_REGISTER(reg) +# define CFI_RESTORE(reg) +#endif + #if defined __linux__ && !defined __powerpc64__ .section .note.GNU-stack .previous diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c index be2eca084b1..579d22485ab 100644 --- a/gcc/config/rs6000/rs6000.c +++ b/gcc/config/rs6000/rs6000.c @@ -778,7 +778,7 @@ static const char *rs6000_mangle_type (const_tree); extern const struct attribute_spec rs6000_attribute_table[]; static void rs6000_set_default_type_attributes (tree); static rtx rs6000_savres_routine_sym (rs6000_stack_t *, bool, bool, bool); -static void rs6000_emit_stack_reset (rs6000_stack_t *, rtx, rtx, int, bool); +static rtx rs6000_emit_stack_reset (rs6000_stack_t *, rtx, rtx, int, bool); static rtx rs6000_make_savres_rtx (rs6000_stack_t *, rtx, int, enum machine_mode, bool, bool, bool); static bool rs6000_reg_live_or_pic_offset_p (int); @@ -15892,7 +15892,7 @@ rs6000_savres_routine_sym (rs6000_stack_t *info, bool savep, bool gpr, bool exit stack pointer, but move the base of the frame into r11 for use by out-of-line register restore routines. */ -static void +static rtx rs6000_emit_stack_reset (rs6000_stack_t *info, rtx sp_reg_rtx, rtx frame_reg_rtx, int sp_offset, bool savres) @@ -15908,10 +15908,10 @@ rs6000_emit_stack_reset (rs6000_stack_t *info, if (frame_reg_rtx != sp_reg_rtx) { if (sp_offset != 0) - emit_insn (gen_addsi3 (sp_reg_rtx, frame_reg_rtx, - GEN_INT (sp_offset))); + return emit_insn (gen_addsi3 (sp_reg_rtx, frame_reg_rtx, + GEN_INT (sp_offset))); else if (!savres) - emit_move_insn (sp_reg_rtx, frame_reg_rtx); + return emit_move_insn (sp_reg_rtx, frame_reg_rtx); } else if (sp_offset != 0) { @@ -15923,12 +15923,12 @@ rs6000_emit_stack_reset (rs6000_stack_t *info, ? gen_rtx_REG (Pmode, 11) : sp_reg_rtx); - emit_insn (TARGET_32BIT - ? gen_addsi3 (dest_reg, sp_reg_rtx, - GEN_INT (sp_offset)) - : gen_adddi3 (dest_reg, sp_reg_rtx, - GEN_INT (sp_offset))); + rtx insn = emit_insn (gen_add3_insn (dest_reg, sp_reg_rtx, + GEN_INT (sp_offset))); + if (!savres) + return insn; } + return NULL_RTX; } /* Construct a parallel rtx describing the effect of a call to an @@ -16838,12 +16838,19 @@ rs6000_restore_saved_cr (rtx reg, int using_mfcr_multiple) } } -/* Emit function epilogue as insns. +/* Return true if OFFSET from stack pointer can be clobbered by signals. + V.4 doesn't have any stack cushion, AIX ABIs have 220 or 288 bytes + below stack pointer not cloberred by signals. */ + +static inline bool +offset_below_red_zone_p (HOST_WIDE_INT offset) +{ + return offset < (DEFAULT_ABI == ABI_V4 + ? 0 + : TARGET_32BIT ? -220 : -288); +} - At present, dwarf2out_frame_debug_expr doesn't understand - register restores, so we don't bother setting RTX_FRAME_RELATED_P - anywhere in the epilogue. Most of the insns below would in any case - need special notes to explain where r11 is in relation to the stack. */ +/* Emit function epilogue as insns. */ void rs6000_emit_epilogue (int sibcall) @@ -16859,6 +16866,8 @@ rs6000_emit_epilogue (int sibcall) int sp_offset = 0; rtx sp_reg_rtx = gen_rtx_REG (Pmode, 1); rtx frame_reg_rtx = sp_reg_rtx; + rtx cfa_restores = NULL_RTX; + rtx insn; enum machine_mode reg_mode = Pmode; int reg_size = TARGET_32BIT ? 4 : 8; int i; @@ -16999,7 +17008,7 @@ rs6000_emit_epilogue (int sibcall) && info->altivec_size != 0 && (ALWAYS_RESTORE_ALTIVEC_BEFORE_POP || (DEFAULT_ABI != ABI_V4 - && info->altivec_save_offset < (TARGET_32BIT ? -220 : -288)))) + && offset_below_red_zone_p (info->altivec_save_offset)))) { int i; @@ -17016,7 +17025,7 @@ rs6000_emit_epilogue (int sibcall) for (i = info->first_altivec_reg_save; i <= LAST_ALTIVEC_REGNO; ++i) if (info->vrsave_mask & ALTIVEC_REG_BIT (i)) { - rtx addr, areg, mem; + rtx addr, areg, mem, reg; areg = gen_rtx_REG (Pmode, 0); emit_move_insn @@ -17028,7 +17037,13 @@ rs6000_emit_epilogue (int sibcall) addr = gen_rtx_PLUS (Pmode, frame_reg_rtx, areg); mem = gen_frame_mem (V4SImode, addr); - emit_move_insn (gen_rtx_REG (V4SImode, i), mem); + reg = gen_rtx_REG (V4SImode, i); + emit_move_insn (reg, mem); + if (offset_below_red_zone_p (info->altivec_save_offset + + (i - info->first_altivec_reg_save) + * 16)) + cfa_restores = alloc_reg_note (REG_CFA_RESTORE, reg, + cfa_restores); } } @@ -17038,7 +17053,7 @@ rs6000_emit_epilogue (int sibcall) && info->vrsave_mask != 0 && (ALWAYS_RESTORE_ALTIVEC_BEFORE_POP || (DEFAULT_ABI != ABI_V4 - && info->vrsave_save_offset < (TARGET_32BIT ? -220 : -288)))) + && offset_below_red_zone_p (info->vrsave_save_offset)))) { rtx addr, mem, reg; @@ -17064,6 +17079,7 @@ rs6000_emit_epilogue (int sibcall) emit_insn (generate_set_vrsave (reg, info, 1)); } + insn = NULL_RTX; /* If we have a large stack frame, restore the old stack pointer using the backchain. */ if (use_backchain_to_restore_sp) @@ -17075,8 +17091,8 @@ rs6000_emit_epilogue (int sibcall) if (DEFAULT_ABI == ABI_V4) frame_reg_rtx = gen_rtx_REG (Pmode, 11); - emit_move_insn (frame_reg_rtx, - gen_rtx_MEM (Pmode, sp_reg_rtx)); + insn = emit_move_insn (frame_reg_rtx, + gen_rtx_MEM (Pmode, sp_reg_rtx)); sp_offset = 0; } else if (ALWAYS_RESTORE_ALTIVEC_BEFORE_POP @@ -17085,7 +17101,7 @@ rs6000_emit_epilogue (int sibcall) ; else { - emit_move_insn (sp_reg_rtx, frame_reg_rtx); + insn = emit_move_insn (sp_reg_rtx, frame_reg_rtx); frame_reg_rtx = sp_reg_rtx; } } @@ -17097,38 +17113,42 @@ rs6000_emit_epilogue (int sibcall) if (DEFAULT_ABI == ABI_V4) frame_reg_rtx = gen_rtx_REG (Pmode, 11); - emit_insn (TARGET_32BIT - ? gen_addsi3 (frame_reg_rtx, hard_frame_pointer_rtx, - GEN_INT (info->total_size)) - : gen_adddi3 (frame_reg_rtx, hard_frame_pointer_rtx, - GEN_INT (info->total_size))); + insn = emit_insn (gen_add3_insn (frame_reg_rtx, hard_frame_pointer_rtx, + GEN_INT (info->total_size))); sp_offset = 0; } else if (info->push_p && DEFAULT_ABI != ABI_V4 && !crtl->calls_eh_return) { - emit_insn (TARGET_32BIT - ? gen_addsi3 (sp_reg_rtx, sp_reg_rtx, - GEN_INT (info->total_size)) - : gen_adddi3 (sp_reg_rtx, sp_reg_rtx, - GEN_INT (info->total_size))); + insn = emit_insn (gen_add3_insn (sp_reg_rtx, sp_reg_rtx, + GEN_INT (info->total_size))); sp_offset = 0; } + if (insn && frame_reg_rtx == sp_reg_rtx) + { + if (cfa_restores) + { + REG_NOTES (insn) = cfa_restores; + cfa_restores = NULL_RTX; + } + add_reg_note (insn, REG_CFA_DEF_CFA, sp_reg_rtx); + RTX_FRAME_RELATED_P (insn) = 1; + } /* Restore AltiVec registers if we have not done so already. */ if (!ALWAYS_RESTORE_ALTIVEC_BEFORE_POP && TARGET_ALTIVEC_ABI && info->altivec_size != 0 && (DEFAULT_ABI == ABI_V4 - || info->altivec_save_offset >= (TARGET_32BIT ? -220 : -288))) + || !offset_below_red_zone_p (info->altivec_save_offset))) { int i; for (i = info->first_altivec_reg_save; i <= LAST_ALTIVEC_REGNO; ++i) if (info->vrsave_mask & ALTIVEC_REG_BIT (i)) { - rtx addr, areg, mem; + rtx addr, areg, mem, reg; areg = gen_rtx_REG (Pmode, 0); emit_move_insn @@ -17140,7 +17160,11 @@ rs6000_emit_epilogue (int sibcall) addr = gen_rtx_PLUS (Pmode, frame_reg_rtx, areg); mem = gen_frame_mem (V4SImode, addr); - emit_move_insn (gen_rtx_REG (V4SImode, i), mem); + reg = gen_rtx_REG (V4SImode, i); + emit_move_insn (reg, mem); + if (DEFAULT_ABI == ABI_V4) + cfa_restores = alloc_reg_note (REG_CFA_RESTORE, reg, + cfa_restores); } } @@ -17150,7 +17174,7 @@ rs6000_emit_epilogue (int sibcall) && TARGET_ALTIVEC_VRSAVE && info->vrsave_mask != 0 && (DEFAULT_ABI == ABI_V4 - || info->vrsave_save_offset >= (TARGET_32BIT ? -220 : -288))) + || !offset_below_red_zone_p (info->vrsave_save_offset))) { rtx addr, mem, reg; @@ -17183,7 +17207,8 @@ rs6000_emit_epilogue (int sibcall) emit_move_insn (gen_rtx_REG (SImode, 12), mem); } - /* Set LR here to try to overlap restores below. */ + /* Set LR here to try to overlap restores below. LR is always saved + above incoming stack, so it never needs REG_CFA_RESTORE. */ if (restore_lr) emit_move_insn (gen_rtx_REG (Pmode, LR_REGNO), gen_rtx_REG (Pmode, 0)); @@ -17265,7 +17290,7 @@ rs6000_emit_epilogue (int sibcall) for (i = 0; i < 32 - info->first_gp_reg_save; i++) if (rs6000_reg_live_or_pic_offset_p (info->first_gp_reg_save + i)) { - rtx offset, addr, mem; + rtx offset, addr, mem, reg; /* We're doing all this to ensure that the immediate offset fits into the immediate field of 'evldd'. */ @@ -17274,9 +17299,24 @@ rs6000_emit_epilogue (int sibcall) offset = GEN_INT (spe_offset + reg_size * i); addr = gen_rtx_PLUS (Pmode, frame_reg_rtx, offset); mem = gen_rtx_MEM (V2SImode, addr); + reg = gen_rtx_REG (reg_mode, info->first_gp_reg_save + i); - emit_move_insn (gen_rtx_REG (reg_mode, info->first_gp_reg_save + i), - mem); + insn = emit_move_insn (reg, mem); + if (DEFAULT_ABI == ABI_V4) + { + if (frame_pointer_needed + && info->first_gp_reg_save + i + == HARD_FRAME_POINTER_REGNUM) + { + add_reg_note (insn, REG_CFA_DEF_CFA, + plus_constant (frame_reg_rtx, + sp_offset)); + RTX_FRAME_RELATED_P (insn) = 1; + } + + cfa_restores = alloc_reg_note (REG_CFA_RESTORE, reg, + cfa_restores); + } } } else @@ -17288,7 +17328,6 @@ rs6000_emit_epilogue (int sibcall) /*savep=*/false, /*gpr=*/true, /*exitp=*/true); emit_jump_insn (par); - /* We don't want anybody else emitting things after we jumped back. */ return; @@ -17317,8 +17356,15 @@ rs6000_emit_epilogue (int sibcall) if (can_use_exit) { if (info->cr_save_p) - rs6000_restore_saved_cr (gen_rtx_REG (SImode, 12), - using_mtcr_multiple); + { + rs6000_restore_saved_cr (gen_rtx_REG (SImode, 12), + using_mtcr_multiple); + if (DEFAULT_ABI == ABI_V4) + cfa_restores + = alloc_reg_note (REG_CFA_RESTORE, + gen_rtx_REG (SImode, CR2_REGNO), + cfa_restores); + } emit_jump_insn (par); @@ -17326,8 +17372,22 @@ rs6000_emit_epilogue (int sibcall) back. */ return; } - else - emit_insn (par); + + insn = emit_insn (par); + if (DEFAULT_ABI == ABI_V4) + { + if (frame_pointer_needed) + { + add_reg_note (insn, REG_CFA_DEF_CFA, + plus_constant (frame_reg_rtx, sp_offset)); + RTX_FRAME_RELATED_P (insn) = 1; + } + + for (i = info->first_gp_reg_save; i < 32; i++) + cfa_restores + = alloc_reg_note (REG_CFA_RESTORE, + gen_rtx_REG (reg_mode, i), cfa_restores); + } } else if (using_load_multiple) { @@ -17340,13 +17400,20 @@ rs6000_emit_epilogue (int sibcall) + sp_offset + reg_size * i)); rtx mem = gen_frame_mem (reg_mode, addr); + rtx reg = gen_rtx_REG (reg_mode, info->first_gp_reg_save + i); - RTVEC_ELT (p, i) = - gen_rtx_SET (VOIDmode, - gen_rtx_REG (reg_mode, info->first_gp_reg_save + i), - mem); + RTVEC_ELT (p, i) = gen_rtx_SET (VOIDmode, reg, mem); + if (DEFAULT_ABI == ABI_V4) + cfa_restores = alloc_reg_note (REG_CFA_RESTORE, reg, + cfa_restores); + } + insn = emit_insn (gen_rtx_PARALLEL (VOIDmode, p)); + if (DEFAULT_ABI == ABI_V4 && frame_pointer_needed) + { + add_reg_note (insn, REG_CFA_DEF_CFA, + plus_constant (frame_reg_rtx, sp_offset)); + RTX_FRAME_RELATED_P (insn) = 1; } - emit_insn (gen_rtx_PARALLEL (VOIDmode, p)); } else { @@ -17358,9 +17425,23 @@ rs6000_emit_epilogue (int sibcall) + sp_offset + reg_size * i)); rtx mem = gen_frame_mem (reg_mode, addr); + rtx reg = gen_rtx_REG (reg_mode, info->first_gp_reg_save + i); - emit_move_insn (gen_rtx_REG (reg_mode, - info->first_gp_reg_save + i), mem); + insn = emit_move_insn (reg, mem); + if (DEFAULT_ABI == ABI_V4) + { + if (frame_pointer_needed + && info->first_gp_reg_save + i + == HARD_FRAME_POINTER_REGNUM) + { + add_reg_note (insn, REG_CFA_DEF_CFA, + plus_constant (frame_reg_rtx, sp_offset)); + RTX_FRAME_RELATED_P (insn) = 1; + } + + cfa_restores = alloc_reg_note (REG_CFA_RESTORE, reg, + cfa_restores); + } } } @@ -17370,36 +17451,52 @@ rs6000_emit_epilogue (int sibcall) if ((df_regs_ever_live_p (info->first_fp_reg_save+i) && ! call_used_regs[info->first_fp_reg_save+i])) { - rtx addr, mem; + rtx addr, mem, reg; addr = gen_rtx_PLUS (Pmode, frame_reg_rtx, GEN_INT (info->fp_save_offset + sp_offset + 8 * i)); mem = gen_frame_mem (((TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT) ? DFmode : SFmode), addr); + reg = gen_rtx_REG (((TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT) + ? DFmode : SFmode), + info->first_fp_reg_save + i); - emit_move_insn (gen_rtx_REG (((TARGET_HARD_FLOAT - && TARGET_DOUBLE_FLOAT) - ? DFmode : SFmode), - info->first_fp_reg_save + i), - mem); + emit_move_insn (reg, mem); + if (DEFAULT_ABI == ABI_V4) + cfa_restores = alloc_reg_note (REG_CFA_RESTORE, reg, + cfa_restores); } /* If we saved cr, restore it here. Just those that were used. */ if (info->cr_save_p) - rs6000_restore_saved_cr (gen_rtx_REG (SImode, 12), using_mtcr_multiple); + { + rs6000_restore_saved_cr (gen_rtx_REG (SImode, 12), using_mtcr_multiple); + if (DEFAULT_ABI == ABI_V4) + cfa_restores + = alloc_reg_note (REG_CFA_RESTORE, gen_rtx_REG (SImode, CR2_REGNO), + cfa_restores); + } /* If this is V.4, unwind the stack pointer after all of the loads have been done. */ - rs6000_emit_stack_reset (info, sp_reg_rtx, frame_reg_rtx, - sp_offset, !restoring_FPRs_inline); + insn = rs6000_emit_stack_reset (info, sp_reg_rtx, frame_reg_rtx, + sp_offset, !restoring_FPRs_inline); + if (insn) + { + if (cfa_restores) + { + REG_NOTES (insn) = cfa_restores; + cfa_restores = NULL_RTX; + } + add_reg_note (insn, REG_CFA_DEF_CFA, sp_reg_rtx); + RTX_FRAME_RELATED_P (insn) = 1; + } if (crtl->calls_eh_return) { rtx sa = EH_RETURN_STACKADJ_RTX; - emit_insn (TARGET_32BIT - ? gen_addsi3 (sp_reg_rtx, sp_reg_rtx, sa) - : gen_adddi3 (sp_reg_rtx, sp_reg_rtx, sa)); + emit_insn (gen_add3_insn (sp_reg_rtx, sp_reg_rtx, sa)); } if (!sibcall) -- 2.11.4.GIT