summaryrefslogtreecommitdiff
path: root/gcc/config/pa/pa.c
diff options
context:
space:
mode:
authordanglin <danglin@138bc75d-0d04-0410-961f-82ee72b054a4>2002-04-04 02:48:18 +0000
committerdanglin <danglin@138bc75d-0d04-0410-961f-82ee72b054a4>2002-04-04 02:48:18 +0000
commita584fe8afeb598d1c5dc1dbf021cdb05123f2f45 (patch)
tree581f501853359286f80b37739491cd24a96a7357 /gcc/config/pa/pa.c
parent9ff1ea9aecfd0c186fcb3c0081d36b0f0ceb5173 (diff)
downloadgcc-a584fe8afeb598d1c5dc1dbf021cdb05123f2f45.tar.gz
* pa-linux.h (INCOMING_RETURN_ADDR_RTX): Move.
(DWARF_FRAME_RETURN_COLUMN): Move. (ASM_PREFERRED_EH_DATA_FORMAT): Define. (ASM_MAYBE_OUTPUT_ENCODED_ADDR_RTX): Define. * pa.c (except.h, predict.h): Include. (FRP): Delete. (store_reg_modify, set_reg_plus_d): Revise prototypes. (output_ascii): Add cast. (store_reg_modify): Revise to add frame notes. (set_reg_plus_d): Likewise. (compute_frame_size): Include space for eh data registers in frame if the current function calls eh_return. (hppa_expand_prologue): Ensure register %r2 is saved if the current function calls eh_return. Save eh data registers if the current function calls eh_return. Fix code to add frame notes. Emit blockage to prevent insns with frame notes being scheduled in the delay slot of calls. (hppa_expand_epilogue): Restore eh data registers and do final stack adjustment if the current function calls eh_return. Don't add frame notes. (output_call): Revise for change in length of call insn. Don't do return pointer adjustment for an unconditional jump in the delay slot of a call when using frame notes. * pa.h (EH_RETURN_DATA_REGNO): Revise for TARGET_64BIT compatibility. (EH_RETURN_HANDLER_RTX): Use saved value on stack. (ARG_POINTER_CFA_OFFSET): Define. * pa.md (return_external_pic): New pattern. (prologue): Correct formatting. Use return_external_pic if current function calls eh_return. (call_internal_symref, call_value_internal_symref, sibcall_internal_symref, sibcall_value_internal_symref): Change default lengths of short, long non-pic, and long pic calls to 8, 68, and 84, respectively. (exception_receiver): Use hppa_pic_save_rtx () to restore pic register. * configure.in ("assembler dwarf2 debug_line support"): Add hppa*-*-* to list of targets to check using "nop" insn. * configure: Rebuilt. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@51836 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/config/pa/pa.c')
-rw-r--r--gcc/config/pa/pa.c395
1 files changed, 268 insertions, 127 deletions
diff --git a/gcc/config/pa/pa.c b/gcc/config/pa/pa.c
index 16f6533e540..7890958fb91 100644
--- a/gcc/config/pa/pa.c
+++ b/gcc/config/pa/pa.c
@@ -32,6 +32,7 @@ Boston, MA 02111-1307, USA. */
#include "insn-attr.h"
#include "flags.h"
#include "tree.h"
+#include "except.h"
#include "expr.h"
#include "optabs.h"
#include "libfuncs.h"
@@ -43,6 +44,7 @@ Boston, MA 02111-1307, USA. */
#include "toplev.h"
#include "ggc.h"
#include "recog.h"
+#include "predict.h"
#include "tm_p.h"
#include "target.h"
#include "target-def.h"
@@ -55,18 +57,6 @@ Boston, MA 02111-1307, USA. */
#endif
#endif
-#if DO_FRAME_NOTES
-#define FRP(INSN) \
- do \
- { \
- rtx insn = INSN; \
- RTX_FRAME_RELATED_P (insn) = 1; \
- } \
- while (0)
-#else
-#define FRP(INSN) INSN
-#endif
-
#ifndef FUNC_BEGIN_PROLOG_LABEL
#define FUNC_BEGIN_PROLOG_LABEL "LFBP"
#endif
@@ -83,8 +73,9 @@ static int compute_movstrsi_length PARAMS ((rtx));
static bool pa_assemble_integer PARAMS ((rtx, unsigned int, int));
static void remove_useless_addtr_insns PARAMS ((rtx, int));
static void store_reg PARAMS ((int, int, int));
+static void store_reg_modify PARAMS ((int, int, int));
static void load_reg PARAMS ((int, int, int));
-static void set_reg_plus_d PARAMS ((int, int, int));
+static void set_reg_plus_d PARAMS ((int, int, int, int));
static void pa_output_function_epilogue PARAMS ((FILE *, HOST_WIDE_INT));
static int pa_adjust_cost PARAMS ((rtx, rtx, rtx, int));
static int pa_adjust_priority PARAMS ((rtx, int));
@@ -2662,7 +2653,7 @@ output_ascii (file, p, size)
fputs ("\"\n\t.STRING \"", file);
chars_output = 0;
}
- fwrite (partial_output, 1, co, file);
+ fwrite (partial_output, 1, (size_t) co, file);
chars_output += co;
co = 0;
}
@@ -2933,15 +2924,60 @@ store_reg (reg, disp, base)
RTX_FRAME_RELATED_P (insn) = 1;
}
-/* Emit RTL to set REG to the value specified by BASE+DISP.
- Handle case where DISP > 8k by using the add_high_const patterns.
+/* Emit RTL to store REG at the memory location specified by BASE and then
+ add MOD to BASE. MOD must be <= 8k. */
- Note in DISP > 8k case, we will leave the high part of the address
- in %r1. There is code in expand_hppa_{prologue,epilogue} that knows this.*/
+static void
+store_reg_modify (base, reg, mod)
+ int base, reg, mod;
+{
+ rtx insn, basereg, srcreg, delta;
+
+ if (! VAL_14_BITS_P (mod))
+ abort ();
+
+ basereg = gen_rtx_REG (Pmode, base);
+ srcreg = gen_rtx_REG (word_mode, reg);
+ delta = GEN_INT (mod);
+
+ insn = emit_insn (gen_post_store (basereg, srcreg, delta));
+ if (DO_FRAME_NOTES)
+ {
+ RTX_FRAME_RELATED_P (insn) = 1;
+
+ /* RTX_FRAME_RELATED_P must be set on each frame related set
+ in a parallel with more than one element. Don't set
+ RTX_FRAME_RELATED_P in the first set if reg is temporary
+ register 1. The effect of this operation is recorded in
+ the initial copy. */
+ if (reg != 1)
+ {
+ RTX_FRAME_RELATED_P (XVECEXP (PATTERN (insn), 0, 0)) = 1;
+ RTX_FRAME_RELATED_P (XVECEXP (PATTERN (insn), 0, 1)) = 1;
+ }
+ else
+ {
+ /* The first element of a PARALLEL is always processed if it is
+ a SET. Thus, we need an expression list for this case. */
+ REG_NOTES (insn)
+ = gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR,
+ gen_rtx_SET (VOIDmode, basereg,
+ gen_rtx_PLUS (word_mode, basereg, delta)),
+ REG_NOTES (insn));
+ }
+ }
+}
+
+/* Emit RTL to set REG to the value specified by BASE+DISP. Handle case
+ where DISP > 8k by using the add_high_const patterns. NOTE indicates
+ whether to add a frame note or not.
+
+ In the DISP > 8k case, we leave the high part of the address in %r1.
+ There is code in expand_hppa_{prologue,epilogue} that knows about this. */
static void
-set_reg_plus_d (reg, base, disp)
- int reg, base, disp;
+set_reg_plus_d (reg, base, disp, note)
+ int reg, base, disp, note;
{
rtx insn;
@@ -2963,7 +2999,7 @@ set_reg_plus_d (reg, base, disp)
delta));
}
- if (DO_FRAME_NOTES && reg == STACK_POINTER_REGNUM)
+ if (DO_FRAME_NOTES && note)
RTX_FRAME_RELATED_P (insn) = 1;
}
@@ -2981,6 +3017,18 @@ compute_frame_size (size, fregs_live)
of them at the same time. */
fsize = size + (size || frame_pointer_needed ? STARTING_FRAME_OFFSET : 0);
+ /* If the current function calls __builtin_eh_return, then we need
+ to allocate stack space for registers that will hold data for
+ the exception handler. */
+ if (DO_FRAME_NOTES && current_function_calls_eh_return)
+ {
+ unsigned int i;
+
+ for (i = 0; EH_RETURN_DATA_REGNO (i) != INVALID_REGNUM; ++i)
+ continue;
+ fsize += i * UNITS_PER_WORD;
+ }
+
/* Account for space used by the callee general register saves. */
for (i = 18; i >= 3; i--)
if (regs_ever_live[i])
@@ -3108,7 +3156,7 @@ hppa_expand_prologue ()
int size = get_frame_size ();
int merge_sp_adjust_with_store = 0;
int i, offset;
- rtx tmpreg, size_rtx;
+ rtx insn, tmpreg;
gr_saved = 0;
fr_saved = 0;
@@ -3126,12 +3174,11 @@ hppa_expand_prologue ()
/* Compute a few things we will use often. */
tmpreg = gen_rtx_REG (word_mode, 1);
- size_rtx = GEN_INT (actual_fsize);
/* Save RP first. The calling conventions manual states RP will
always be stored into the caller's frame at sp - 20 or sp - 16
depending on which ABI is in use. */
- if (regs_ever_live[2])
+ if (regs_ever_live[2] || current_function_calls_eh_return)
store_reg (2, TARGET_64BIT ? -16 : -20, STACK_POINTER_REGNUM);
/* Allocate the local frame and set up the frame pointer if needed. */
@@ -3141,36 +3188,30 @@ hppa_expand_prologue ()
{
/* Copy the old frame pointer temporarily into %r1. Set up the
new stack pointer, then store away the saved old frame pointer
- into the stack at sp+actual_fsize and at the same time update
- the stack pointer by actual_fsize bytes. Two versions, first
+ into the stack at sp and at the same time update the stack
+ pointer by actual_fsize bytes. Two versions, first
handles small (<8k) frames. The second handles large (>=8k)
frames. */
- emit_move_insn (tmpreg, frame_pointer_rtx);
- FRP (emit_move_insn (frame_pointer_rtx, stack_pointer_rtx));
- if (VAL_14_BITS_P (actual_fsize))
+ insn = emit_move_insn (tmpreg, frame_pointer_rtx);
+ if (DO_FRAME_NOTES)
{
- rtx insn = emit_insn (gen_post_store (stack_pointer_rtx, tmpreg,
- size_rtx));
- if (DO_FRAME_NOTES)
- {
- rtvec vec;
- RTX_FRAME_RELATED_P (insn) = 1;
- vec = gen_rtvec (2,
- gen_rtx_SET (VOIDmode,
- gen_rtx_MEM (word_mode,
- stack_pointer_rtx),
- frame_pointer_rtx),
- gen_rtx_SET (VOIDmode,
- stack_pointer_rtx,
- gen_rtx_PLUS (word_mode,
- stack_pointer_rtx,
- size_rtx)));
- REG_NOTES (insn)
- = gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR,
- gen_rtx_SEQUENCE (VOIDmode, vec),
- REG_NOTES (insn));
- }
+ /* We need to record the frame pointer save here since the
+ new frame pointer is set in the following insn. */
+ RTX_FRAME_RELATED_P (insn) = 1;
+ REG_NOTES (insn)
+ = gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR,
+ gen_rtx_SET (VOIDmode,
+ gen_rtx_MEM (word_mode, stack_pointer_rtx),
+ frame_pointer_rtx),
+ REG_NOTES (insn));
}
+
+ insn = emit_move_insn (frame_pointer_rtx, stack_pointer_rtx);
+ if (DO_FRAME_NOTES)
+ RTX_FRAME_RELATED_P (insn) = 1;
+
+ if (VAL_14_BITS_P (actual_fsize))
+ store_reg_modify (STACK_POINTER_REGNUM, 1, actual_fsize);
else
{
/* It is incorrect to store the saved frame pointer at *sp,
@@ -3181,32 +3222,12 @@ hppa_expand_prologue ()
finish allocating the new frame. */
int adjust1 = 8192 - 64;
int adjust2 = actual_fsize - adjust1;
- rtx delta = GEN_INT (adjust1);
- rtx insn = emit_insn (gen_post_store (stack_pointer_rtx, tmpreg,
- delta));
- if (DO_FRAME_NOTES)
- {
- rtvec vec;
- RTX_FRAME_RELATED_P (insn) = 1;
- vec = gen_rtvec (2,
- gen_rtx_SET (VOIDmode,
- gen_rtx_MEM (word_mode,
- stack_pointer_rtx),
- frame_pointer_rtx),
- gen_rtx_SET (VOIDmode,
- stack_pointer_rtx,
- gen_rtx_PLUS (word_mode,
- stack_pointer_rtx,
- delta)));
- REG_NOTES (insn)
- = gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR,
- gen_rtx_SEQUENCE (VOIDmode, vec),
- REG_NOTES (insn));
- }
+ store_reg_modify (STACK_POINTER_REGNUM, 1, adjust1);
set_reg_plus_d (STACK_POINTER_REGNUM, STACK_POINTER_REGNUM,
- adjust2);
+ adjust2, 1);
}
+
/* Prevent register spills from being scheduled before the
stack pointer is raised. Necessary as we will be storing
registers using the frame pointer as a base register, and
@@ -3226,7 +3247,7 @@ hppa_expand_prologue ()
bytes. */
else
set_reg_plus_d (STACK_POINTER_REGNUM, STACK_POINTER_REGNUM,
- actual_fsize);
+ actual_fsize, 1);
}
}
@@ -3236,7 +3257,27 @@ hppa_expand_prologue ()
was done earlier. */
if (frame_pointer_needed)
{
- for (i = 18, offset = local_fsize; i >= 4; i--)
+ offset = local_fsize;
+
+ /* Saving the EH return data registers in the frame is the simplest
+ way to get the frame unwind information emitted. We put them
+ just before the general registers. */
+ if (DO_FRAME_NOTES && current_function_calls_eh_return)
+ {
+ unsigned int i, regno;
+
+ for (i = 0; ; ++i)
+ {
+ regno = EH_RETURN_DATA_REGNO (i);
+ if (regno == INVALID_REGNUM)
+ break;
+
+ store_reg (regno, offset, FRAME_POINTER_REGNUM);
+ offset += UNITS_PER_WORD;
+ }
+ }
+
+ for (i = 18; i >= 4; i--)
if (regs_ever_live[i] && ! call_used_regs[i])
{
store_reg (i, offset, FRAME_POINTER_REGNUM);
@@ -3249,18 +3290,42 @@ hppa_expand_prologue ()
/* No frame pointer needed. */
else
{
- for (i = 18, offset = local_fsize - actual_fsize; i >= 3; i--)
+ offset = local_fsize - actual_fsize;
+
+ /* Saving the EH return data registers in the frame is the simplest
+ way to get the frame unwind information emitted. */
+ if (DO_FRAME_NOTES && current_function_calls_eh_return)
+ {
+ unsigned int i, regno;
+
+ for (i = 0; ; ++i)
+ {
+ regno = EH_RETURN_DATA_REGNO (i);
+ if (regno == INVALID_REGNUM)
+ break;
+
+ /* If merge_sp_adjust_with_store is nonzero, then we can
+ optimize the first save. */
+ if (merge_sp_adjust_with_store)
+ {
+ store_reg_modify (STACK_POINTER_REGNUM, regno, -offset);
+ merge_sp_adjust_with_store = 0;
+ }
+ else
+ store_reg (regno, offset, STACK_POINTER_REGNUM);
+ offset += UNITS_PER_WORD;
+ }
+ }
+
+ for (i = 18; i >= 3; i--)
if (regs_ever_live[i] && ! call_used_regs[i])
{
/* If merge_sp_adjust_with_store is nonzero, then we can
optimize the first GR save. */
if (merge_sp_adjust_with_store)
{
- rtx delta = GEN_INT (-offset);
+ store_reg_modify (STACK_POINTER_REGNUM, i, -offset);
merge_sp_adjust_with_store = 0;
- FRP (emit_insn (gen_post_store (stack_pointer_rtx,
- gen_rtx_REG (word_mode, i),
- delta)));
}
else
store_reg (i, offset, STACK_POINTER_REGNUM);
@@ -3272,7 +3337,7 @@ hppa_expand_prologue ()
did any GR saves, then just emit the adjustment here. */
if (merge_sp_adjust_with_store)
set_reg_plus_d (STACK_POINTER_REGNUM, STACK_POINTER_REGNUM,
- actual_fsize);
+ actual_fsize, 1);
}
/* The hppa calling conventions say that %r19, the pic offset
@@ -3290,12 +3355,20 @@ hppa_expand_prologue ()
/* Floating point register store. */
if (save_fregs)
{
+ rtx base;
+
/* First get the frame or stack pointer to the start of the FP register
save area. */
if (frame_pointer_needed)
- set_reg_plus_d (1, FRAME_POINTER_REGNUM, offset);
+ {
+ set_reg_plus_d (1, FRAME_POINTER_REGNUM, offset, 0);
+ base = frame_pointer_rtx;
+ }
else
- set_reg_plus_d (1, STACK_POINTER_REGNUM, offset);
+ {
+ set_reg_plus_d (1, STACK_POINTER_REGNUM, offset, 0);
+ base = stack_pointer_rtx;
+ }
/* Now actually save the FP registers. */
for (i = FP_SAVED_REG_LAST; i >= FP_SAVED_REG_FIRST; i -= FP_REG_STEP)
@@ -3310,20 +3383,49 @@ hppa_expand_prologue ()
if (DO_FRAME_NOTES)
{
RTX_FRAME_RELATED_P (insn) = 1;
- REG_NOTES (insn)
- = gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR,
- gen_rtx_SET (VOIDmode,
- gen_rtx_MEM (DFmode,
- plus_constant (stack_pointer_rtx,
- offset)),
- reg),
- REG_NOTES (insn));
+ if (TARGET_64BIT)
+ {
+ rtx mem = gen_rtx_MEM (DFmode,
+ plus_constant (base, offset));
+ REG_NOTES (insn)
+ = gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR,
+ gen_rtx_SET (VOIDmode, mem, reg),
+ REG_NOTES (insn));
+ }
+ else
+ {
+ rtx meml = gen_rtx_MEM (SFmode,
+ plus_constant (base, offset));
+ rtx memr = gen_rtx_MEM (SFmode,
+ plus_constant (base, offset + 4));
+ rtx regl = gen_rtx_REG (SFmode, i);
+ rtx regr = gen_rtx_REG (SFmode, i + 1);
+ rtx setl = gen_rtx_SET (VOIDmode, meml, regl);
+ rtx setr = gen_rtx_SET (VOIDmode, memr, regr);
+ rtvec vec;
+
+ RTX_FRAME_RELATED_P (setl) = 1;
+ RTX_FRAME_RELATED_P (setr) = 1;
+ vec = gen_rtvec (2, setl, setr);
+ REG_NOTES (insn)
+ = gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR,
+ gen_rtx_SEQUENCE (VOIDmode, vec),
+ REG_NOTES (insn));
+ }
}
offset += GET_MODE_SIZE (DFmode);
fr_saved++;
}
}
}
+
+ /* FIXME: expand_call and expand_millicode_call need to be fixed to
+ prevent insns with frame notes being scheduled in the delay slot
+ of calls. This causes problems because the dwarf2 output code
+ processes the insn list serially. For now, limit the migration
+ of prologue insns with a blockage. */
+ if (DO_FRAME_NOTES)
+ emit_insn (gen_blockage ());
}
/* Emit RTL to load REG from the memory location specified by BASE+DISP.
@@ -3407,7 +3509,7 @@ hppa_expand_epilogue ()
/* Try to restore RP early to avoid load/use interlocks when
RP gets used in the return (bv) instruction. This appears to still
be necessary even when we schedule the prologue and epilogue. */
- if (regs_ever_live [2])
+ if (regs_ever_live [2] || current_function_calls_eh_return)
{
ret_off = TARGET_64BIT ? -16 : -20;
if (frame_pointer_needed)
@@ -3429,7 +3531,26 @@ hppa_expand_epilogue ()
/* General register restores. */
if (frame_pointer_needed)
{
- for (i = 18, offset = local_fsize; i >= 4; i--)
+ offset = local_fsize;
+
+ /* If the current function calls __builtin_eh_return, then we need
+ to restore the saved EH data registers. */
+ if (DO_FRAME_NOTES && current_function_calls_eh_return)
+ {
+ unsigned int i, regno;
+
+ for (i = 0; ; ++i)
+ {
+ regno = EH_RETURN_DATA_REGNO (i);
+ if (regno == INVALID_REGNUM)
+ break;
+
+ load_reg (regno, offset, FRAME_POINTER_REGNUM);
+ offset += UNITS_PER_WORD;
+ }
+ }
+
+ for (i = 18; i >= 4; i--)
if (regs_ever_live[i] && ! call_used_regs[i])
{
load_reg (i, offset, FRAME_POINTER_REGNUM);
@@ -3438,7 +3559,34 @@ hppa_expand_epilogue ()
}
else
{
- for (i = 18, offset = local_fsize - actual_fsize; i >= 3; i--)
+ offset = local_fsize - actual_fsize;
+
+ /* If the current function calls __builtin_eh_return, then we need
+ to restore the saved EH data registers. */
+ if (DO_FRAME_NOTES && current_function_calls_eh_return)
+ {
+ unsigned int i, regno;
+
+ for (i = 0; ; ++i)
+ {
+ regno = EH_RETURN_DATA_REGNO (i);
+ if (regno == INVALID_REGNUM)
+ break;
+
+ /* Only for the first load.
+ merge_sp_adjust_with_load holds the register load
+ with which we will merge the sp adjustment. */
+ if (merge_sp_adjust_with_load == 0
+ && local_fsize == 0
+ && VAL_14_BITS_P (-actual_fsize))
+ merge_sp_adjust_with_load = regno;
+ else
+ load_reg (regno, offset, STACK_POINTER_REGNUM);
+ offset += UNITS_PER_WORD;
+ }
+ }
+
+ for (i = 18; i >= 3; i--)
{
if (regs_ever_live[i] && ! call_used_regs[i])
{
@@ -3464,9 +3612,9 @@ hppa_expand_epilogue ()
{
/* Adjust the register to index off of. */
if (frame_pointer_needed)
- set_reg_plus_d (1, FRAME_POINTER_REGNUM, offset);
+ set_reg_plus_d (1, FRAME_POINTER_REGNUM, offset, 0);
else
- set_reg_plus_d (1, STACK_POINTER_REGNUM, offset);
+ set_reg_plus_d (1, STACK_POINTER_REGNUM, offset, 0);
/* Actually do the restores now. */
for (i = FP_SAVED_REG_LAST; i >= FP_SAVED_REG_FIRST; i -= FP_REG_STEP)
@@ -3491,45 +3639,36 @@ hppa_expand_epilogue ()
if (frame_pointer_needed)
{
rtx delta = GEN_INT (-64);
- rtx insn;
- set_reg_plus_d (STACK_POINTER_REGNUM, FRAME_POINTER_REGNUM, 64);
- insn = emit_insn (gen_pre_load (frame_pointer_rtx, stack_pointer_rtx,
- delta));
- if (DO_FRAME_NOTES)
- {
- RTX_FRAME_RELATED_P (insn) = 1;
- REG_NOTES (insn)
- = gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR,
- gen_rtx_SET (VOIDmode, stack_pointer_rtx,
- gen_rtx_PLUS (word_mode, stack_pointer_rtx,
- delta)),
- REG_NOTES (insn));
- }
+
+ set_reg_plus_d (STACK_POINTER_REGNUM, FRAME_POINTER_REGNUM, 64, 0);
+ emit_insn (gen_pre_load (frame_pointer_rtx, stack_pointer_rtx, delta));
}
/* If we were deferring a callee register restore, do it now. */
else if (merge_sp_adjust_with_load)
{
rtx delta = GEN_INT (-actual_fsize);
rtx dest = gen_rtx_REG (word_mode, merge_sp_adjust_with_load);
- rtx insn = emit_insn (gen_pre_load (dest, stack_pointer_rtx, delta));
- if (DO_FRAME_NOTES)
- {
- RTX_FRAME_RELATED_P (insn) = 1;
- REG_NOTES (insn)
- = gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR,
- gen_rtx_SET (VOIDmode, stack_pointer_rtx,
- gen_rtx_PLUS (word_mode, stack_pointer_rtx,
- delta)),
- REG_NOTES (insn));
- }
+
+ emit_insn (gen_pre_load (dest, stack_pointer_rtx, delta));
}
else if (actual_fsize != 0)
- set_reg_plus_d (STACK_POINTER_REGNUM, STACK_POINTER_REGNUM, - actual_fsize);
+ set_reg_plus_d (STACK_POINTER_REGNUM, STACK_POINTER_REGNUM,
+ - actual_fsize, 0);
/* If we haven't restored %r2 yet (no frame pointer, and a stack
frame greater than 8k), do so now. */
if (ret_off != 0)
load_reg (2, ret_off, STACK_POINTER_REGNUM);
+
+ if (DO_FRAME_NOTES && current_function_calls_eh_return)
+ {
+ rtx sa = EH_RETURN_STACKADJ_RTX;
+
+ emit_insn (gen_blockage ());
+ emit_insn (TARGET_64BIT
+ ? gen_subdi3 (stack_pointer_rtx, stack_pointer_rtx, sa)
+ : gen_subsi3 (stack_pointer_rtx, stack_pointer_rtx, sa));
+ }
}
rtx
@@ -6029,10 +6168,10 @@ output_call (insn, call_dest, sibcall)
and we're sure that the branch will reach the beginning of the $CODE$
subspace. */
if ((dbr_sequence_length () == 0
- && get_attr_length (insn) == 8)
+ && get_attr_length (insn) == 12)
|| (dbr_sequence_length () != 0
&& GET_CODE (NEXT_INSN (insn)) != JUMP_INSN
- && get_attr_length (insn) == 4))
+ && get_attr_length (insn) == 8))
{
xoperands[0] = call_dest;
xoperands[1] = gen_rtx_REG (word_mode, sibcall ? 0 : 2);
@@ -6041,7 +6180,7 @@ output_call (insn, call_dest, sibcall)
}
/* This call may not reach the beginning of the $CODE$ subspace. */
- if (get_attr_length (insn) > 8)
+ if (get_attr_length (insn) > 12)
{
int delay_insn_deleted = 0;
rtx xoperands[2];
@@ -6241,14 +6380,16 @@ output_call (insn, call_dest, sibcall)
- INSN_ADDRESSES (INSN_UID (seq_insn)) - 8;
/* If the branch was too far away, emit a normal call followed
- by a nop, followed by the unconditional branch.
+ by a nop, followed by the unconditional branch. We also don't
+ adjust %r2 when generating dwarf2 frame or unwind info since
+ the adjustment confuses the dwarf2 output.
If the branch is close, then adjust %r2 from within the
call's delay slot. */
xoperands[0] = call_dest;
xoperands[1] = XEXP (PATTERN (NEXT_INSN (insn)), 1);
- if (! VAL_14_BITS_P (distance))
+ if (DO_FRAME_NOTES || ! VAL_14_BITS_P (distance))
output_asm_insn ("{bl|b,l} %0,%%r2\n\tnop\n\tb,n %1", xoperands);
else
{