diff options
author | danglin <danglin@138bc75d-0d04-0410-961f-82ee72b054a4> | 2002-04-04 02:48:18 +0000 |
---|---|---|
committer | danglin <danglin@138bc75d-0d04-0410-961f-82ee72b054a4> | 2002-04-04 02:48:18 +0000 |
commit | a584fe8afeb598d1c5dc1dbf021cdb05123f2f45 (patch) | |
tree | 581f501853359286f80b37739491cd24a96a7357 /gcc/config/pa/pa.c | |
parent | 9ff1ea9aecfd0c186fcb3c0081d36b0f0ceb5173 (diff) | |
download | gcc-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.c | 395 |
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 { |