DWARF2 frame notes for hppa.
* dwarf2out.c (dwarf2out_frame_debug_expr): Support adjusting stack pointer via a LO_SUM. Ditto for setting a temp register used to save to the stack. Set cfa_temp when setting fp, and allow matches to cfa_temp in addition to cfa_store when saving regs. Handle POST_INC and LO_SUM register stores. Document the changes and errors in rule 12 doco. * pa.c (set_reg_plus_d, store_reg, load_reg): Return last insn. (actual_fsize, local_fsize, save_fregs): Move for store_reg to see. (load_reg): Move closer to epilogue code. (DO_FRAME_NOTES): Define to control the following.. (FRP): Define to set RTX_FRAME_RELATED_P on insns. (hppa_expand_prologue): Use FRP and REG_FRAME_RELATED_EXPR notes as necessary. (hppa_expand_epilogue): Likewise. From-SVN: r41074
This commit is contained in:
parent
78e766a0e1
commit
19ec6a367c
3 changed files with 286 additions and 168 deletions
|
@ -1,3 +1,21 @@
|
|||
2001-04-04 Alan Modra <alan@linuxcare.com.au>
|
||||
|
||||
* dwarf2out.c (dwarf2out_frame_debug_expr): Support adjusting
|
||||
stack pointer via a LO_SUM. Ditto for setting a temp register
|
||||
used to save to the stack. Set cfa_temp when setting fp, and
|
||||
allow matches to cfa_temp in addition to cfa_store when saving
|
||||
regs. Handle POST_INC and LO_SUM register stores. Document the
|
||||
changes and errors in rule 12 doco.
|
||||
|
||||
* pa.c (set_reg_plus_d, store_reg, load_reg): Return last insn.
|
||||
(actual_fsize, local_fsize, save_fregs): Move for store_reg to see.
|
||||
(load_reg): Move closer to epilogue code.
|
||||
(DO_FRAME_NOTES): Define to control the following..
|
||||
(FRP): Define to set RTX_FRAME_RELATED_P on insns.
|
||||
(hppa_expand_prologue): Use FRP and REG_FRAME_RELATED_EXPR
|
||||
notes as necessary.
|
||||
(hppa_expand_epilogue): Likewise.
|
||||
|
||||
2001-04-03 Richard Henderson <rth@redhat.com>
|
||||
|
||||
* configure.in (gcc_cv_as_leb128): Reject gas before 2.11.
|
||||
|
|
|
@ -42,21 +42,29 @@ Boston, MA 02111-1307, USA. */
|
|||
#include "recog.h"
|
||||
#include "tm_p.h"
|
||||
|
||||
#ifndef DO_FRAME_NOTES
|
||||
#ifdef INCOMING_RETURN_ADDR_RTX
|
||||
#define DO_FRAME_NOTES 1
|
||||
#else
|
||||
#define DO_FRAME_NOTES 0
|
||||
#endif
|
||||
#endif
|
||||
|
||||
static void pa_init_machine_status PARAMS ((struct function *));
|
||||
static void pa_mark_machine_status PARAMS ((struct function *));
|
||||
static void pa_free_machine_status PARAMS ((struct function *));
|
||||
static void pa_combine_instructions PARAMS ((rtx));
|
||||
static int pa_can_combine_p PARAMS ((rtx, rtx, rtx, int, rtx, rtx, rtx));
|
||||
static int forward_branch_p PARAMS ((rtx));
|
||||
static int shadd_constant_p PARAMS ((int));
|
||||
static void pa_add_gc_roots PARAMS ((void));
|
||||
static void mark_deferred_plabels PARAMS ((void *));
|
||||
static void compute_zdepwi_operands PARAMS ((unsigned HOST_WIDE_INT, unsigned *));
|
||||
static int compute_movstrsi_length PARAMS ((rtx));
|
||||
static void remove_useless_addtr_insns PARAMS ((rtx, int));
|
||||
static void store_reg PARAMS ((int, int, int));
|
||||
static void load_reg PARAMS ((int, int, int));
|
||||
static void set_reg_plus_d PARAMS ((int, int, int));
|
||||
static void pa_combine_instructions PARAMS ((rtx));
|
||||
static int pa_can_combine_p PARAMS ((rtx, rtx, rtx, int, rtx, rtx, rtx));
|
||||
static int forward_branch_p PARAMS ((rtx));
|
||||
static int shadd_constant_p PARAMS ((int));
|
||||
static void pa_add_gc_roots PARAMS ((void));
|
||||
static void mark_deferred_plabels PARAMS ((void *));
|
||||
static void compute_zdepwi_operands PARAMS ((unsigned HOST_WIDE_INT, unsigned *));
|
||||
static int compute_movstrsi_length PARAMS ((rtx));
|
||||
static void remove_useless_addtr_insns PARAMS ((rtx, int));
|
||||
static rtx store_reg PARAMS ((int, int, int));
|
||||
static rtx load_reg PARAMS ((int, int, int));
|
||||
static rtx set_reg_plus_d PARAMS ((int, int, int));
|
||||
|
||||
/* Save the operands last given to a compare for use when we
|
||||
generate a scc or bcc insn. */
|
||||
|
@ -2003,7 +2011,6 @@ output_move_double (operands)
|
|||
xoperands);
|
||||
return "ldw 0(%R0),%0\n\tldw 4(%R0),%R0";
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2743,60 +2750,41 @@ remove_useless_addtr_insns (insns, check_notes)
|
|||
|
||||
*/
|
||||
|
||||
/* Global variables set by FUNCTION_PROLOGUE. */
|
||||
/* Size of frame. Need to know this to emit return insns from
|
||||
leaf procedures. */
|
||||
static int actual_fsize;
|
||||
static int local_fsize, save_fregs;
|
||||
|
||||
/* Emit RTL to store REG at the memory location specified by BASE+DISP.
|
||||
Handle case where DISP > 8k by using the add_high_const patterns.
|
||||
|
||||
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
|
||||
static rtx
|
||||
store_reg (reg, disp, base)
|
||||
int reg, disp, base;
|
||||
{
|
||||
rtx i, dest, src, basereg;
|
||||
|
||||
src = gen_rtx_REG (word_mode, reg);
|
||||
basereg = gen_rtx_REG (Pmode, base);
|
||||
if (VAL_14_BITS_P (disp))
|
||||
emit_move_insn (gen_rtx_MEM (word_mode,
|
||||
plus_constant (gen_rtx_REG (Pmode, base),
|
||||
disp)),
|
||||
gen_rtx_REG (word_mode, reg));
|
||||
{
|
||||
dest = gen_rtx_MEM (word_mode, plus_constant (basereg, disp));
|
||||
i = emit_move_insn (dest, src);
|
||||
}
|
||||
else
|
||||
{
|
||||
emit_move_insn (gen_rtx_REG (Pmode, 1),
|
||||
gen_rtx_PLUS (Pmode, gen_rtx_REG (Pmode, base),
|
||||
gen_rtx_HIGH (Pmode, GEN_INT (disp))));
|
||||
emit_move_insn (gen_rtx_MEM (word_mode,
|
||||
gen_rtx_LO_SUM (Pmode,
|
||||
gen_rtx_REG (Pmode, 1),
|
||||
GEN_INT (disp))),
|
||||
gen_rtx_REG (word_mode, reg));
|
||||
}
|
||||
}
|
||||
|
||||
/* Emit RTL to load REG from the memory location specified by BASE+DISP.
|
||||
Handle case where DISP > 8k by using the add_high_const patterns.
|
||||
|
||||
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
|
||||
load_reg (reg, disp, base)
|
||||
int reg, disp, base;
|
||||
{
|
||||
if (VAL_14_BITS_P (disp))
|
||||
emit_move_insn (gen_rtx_REG (word_mode, reg),
|
||||
gen_rtx_MEM (word_mode,
|
||||
plus_constant (gen_rtx_REG (Pmode, base),
|
||||
disp)));
|
||||
else
|
||||
{
|
||||
emit_move_insn (gen_rtx_REG (Pmode, 1),
|
||||
gen_rtx_PLUS (Pmode, gen_rtx_REG (Pmode, base),
|
||||
gen_rtx_HIGH (Pmode, GEN_INT (disp))));
|
||||
emit_move_insn (gen_rtx_REG (word_mode, reg),
|
||||
gen_rtx_MEM (word_mode,
|
||||
gen_rtx_LO_SUM (Pmode,
|
||||
gen_rtx_REG (Pmode, 1),
|
||||
GEN_INT (disp))));
|
||||
rtx delta = GEN_INT (disp);
|
||||
rtx high = gen_rtx_PLUS (Pmode, basereg, gen_rtx_HIGH (Pmode, delta));
|
||||
rtx tmpreg = gen_rtx_REG (Pmode, 1);
|
||||
emit_move_insn (tmpreg, high);
|
||||
dest = gen_rtx_MEM (word_mode, gen_rtx_LO_SUM (Pmode, tmpreg, delta));
|
||||
i = emit_move_insn (dest, src);
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
/* Emit RTL to set REG to the value specified by BASE+DISP.
|
||||
|
@ -2805,31 +2793,30 @@ load_reg (reg, disp, base)
|
|||
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
|
||||
static rtx
|
||||
set_reg_plus_d (reg, base, disp)
|
||||
int reg, base, disp;
|
||||
{
|
||||
rtx i;
|
||||
|
||||
if (VAL_14_BITS_P (disp))
|
||||
emit_move_insn (gen_rtx_REG (Pmode, reg),
|
||||
plus_constant (gen_rtx_REG (Pmode, base), disp));
|
||||
{
|
||||
i = emit_move_insn (gen_rtx_REG (Pmode, reg),
|
||||
plus_constant (gen_rtx_REG (Pmode, base), disp));
|
||||
}
|
||||
else
|
||||
{
|
||||
rtx delta = GEN_INT (disp);
|
||||
emit_move_insn (gen_rtx_REG (Pmode, 1),
|
||||
gen_rtx_PLUS (Pmode, gen_rtx_REG (Pmode, base),
|
||||
gen_rtx_HIGH (Pmode, GEN_INT (disp))));
|
||||
emit_move_insn (gen_rtx_REG (Pmode, reg),
|
||||
gen_rtx_LO_SUM (Pmode,
|
||||
gen_rtx_REG (Pmode, 1),
|
||||
GEN_INT (disp)));
|
||||
gen_rtx_HIGH (Pmode, delta)));
|
||||
i = emit_move_insn (gen_rtx_REG (Pmode, reg),
|
||||
gen_rtx_LO_SUM (Pmode, gen_rtx_REG (Pmode, 1),
|
||||
delta));
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
/* Global variables set by FUNCTION_PROLOGUE. */
|
||||
/* Size of frame. Need to know this to emit return insns from
|
||||
leaf procedures. */
|
||||
static int actual_fsize;
|
||||
static int local_fsize, save_fregs;
|
||||
|
||||
int
|
||||
compute_frame_size (size, fregs_live)
|
||||
int size;
|
||||
|
@ -2937,8 +2924,20 @@ output_function_prologue (file, size)
|
|||
remove_useless_addtr_insns (get_insns (), 0);
|
||||
}
|
||||
|
||||
#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
|
||||
|
||||
void
|
||||
hppa_expand_prologue()
|
||||
hppa_expand_prologue ()
|
||||
{
|
||||
extern char call_used_regs[];
|
||||
int size = get_frame_size ();
|
||||
|
@ -2965,10 +2964,10 @@ hppa_expand_prologue()
|
|||
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
|
||||
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])
|
||||
store_reg (2, TARGET_64BIT ? -16 : -20, STACK_POINTER_REGNUM);
|
||||
FRP (store_reg (2, TARGET_64BIT ? -16 : -20, STACK_POINTER_REGNUM));
|
||||
|
||||
/* Allocate the local frame and set up the frame pointer if needed. */
|
||||
if (actual_fsize != 0)
|
||||
|
@ -2982,9 +2981,31 @@ hppa_expand_prologue()
|
|||
handles small (<8k) frames. The second handles large (>=8k)
|
||||
frames. */
|
||||
emit_move_insn (tmpreg, frame_pointer_rtx);
|
||||
emit_move_insn (frame_pointer_rtx, stack_pointer_rtx);
|
||||
FRP (emit_move_insn (frame_pointer_rtx, stack_pointer_rtx));
|
||||
if (VAL_14_BITS_P (actual_fsize))
|
||||
emit_insn (gen_post_store (stack_pointer_rtx, tmpreg, size_rtx));
|
||||
{
|
||||
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));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* It is incorrect to store the saved frame pointer at *sp,
|
||||
|
@ -2996,10 +3017,31 @@ hppa_expand_prologue()
|
|||
int adjust1 = 8192 - 64;
|
||||
int adjust2 = actual_fsize - adjust1;
|
||||
rtx delta = GEN_INT (adjust1);
|
||||
emit_insn (gen_post_store (stack_pointer_rtx, tmpreg, delta));
|
||||
set_reg_plus_d (STACK_POINTER_REGNUM,
|
||||
STACK_POINTER_REGNUM,
|
||||
adjust2);
|
||||
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));
|
||||
}
|
||||
|
||||
FRP (set_reg_plus_d (STACK_POINTER_REGNUM,
|
||||
STACK_POINTER_REGNUM,
|
||||
adjust2));
|
||||
}
|
||||
/* Prevent register spills from being scheduled before the
|
||||
stack pointer is raised. Necessary as we will be storing
|
||||
|
@ -3019,9 +3061,9 @@ hppa_expand_prologue()
|
|||
/* Can not optimize. Adjust the stack frame by actual_fsize
|
||||
bytes. */
|
||||
else
|
||||
set_reg_plus_d (STACK_POINTER_REGNUM,
|
||||
STACK_POINTER_REGNUM,
|
||||
actual_fsize);
|
||||
FRP (set_reg_plus_d (STACK_POINTER_REGNUM,
|
||||
STACK_POINTER_REGNUM,
|
||||
actual_fsize));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3034,7 +3076,7 @@ hppa_expand_prologue()
|
|||
for (i = 18, offset = local_fsize; i >= 4; i--)
|
||||
if (regs_ever_live[i] && ! call_used_regs[i])
|
||||
{
|
||||
store_reg (i, offset, FRAME_POINTER_REGNUM);
|
||||
FRP (store_reg (i, offset, FRAME_POINTER_REGNUM));
|
||||
offset += UNITS_PER_WORD;
|
||||
gr_saved++;
|
||||
}
|
||||
|
@ -3051,13 +3093,14 @@ hppa_expand_prologue()
|
|||
optimize the first GR save. */
|
||||
if (merge_sp_adjust_with_store)
|
||||
{
|
||||
rtx delta = GEN_INT (-offset);
|
||||
merge_sp_adjust_with_store = 0;
|
||||
emit_insn (gen_post_store (stack_pointer_rtx,
|
||||
gen_rtx_REG (word_mode, i),
|
||||
GEN_INT (-offset)));
|
||||
FRP (emit_insn (gen_post_store (stack_pointer_rtx,
|
||||
gen_rtx_REG (word_mode, i),
|
||||
delta)));
|
||||
}
|
||||
else
|
||||
store_reg (i, offset, STACK_POINTER_REGNUM);
|
||||
FRP (store_reg (i, offset, STACK_POINTER_REGNUM));
|
||||
offset += UNITS_PER_WORD;
|
||||
gr_saved++;
|
||||
}
|
||||
|
@ -3065,9 +3108,9 @@ hppa_expand_prologue()
|
|||
/* If we wanted to merge the SP adjustment with a GR save, but we never
|
||||
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);
|
||||
FRP (set_reg_plus_d (STACK_POINTER_REGNUM,
|
||||
STACK_POINTER_REGNUM,
|
||||
actual_fsize));
|
||||
}
|
||||
|
||||
/* The hppa calling conventions say that %r19, the pic offset
|
||||
|
@ -3088,9 +3131,9 @@ hppa_expand_prologue()
|
|||
/* 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);
|
||||
FRP (set_reg_plus_d (1, FRAME_POINTER_REGNUM, offset));
|
||||
else
|
||||
set_reg_plus_d (1, STACK_POINTER_REGNUM, offset);
|
||||
FRP (set_reg_plus_d (1, STACK_POINTER_REGNUM, offset));
|
||||
|
||||
/* Now actually save the FP registers. */
|
||||
for (i = FP_SAVED_REG_LAST; i >= FP_SAVED_REG_FIRST; i -= FP_REG_STEP)
|
||||
|
@ -3098,15 +3141,49 @@ hppa_expand_prologue()
|
|||
if (regs_ever_live[i]
|
||||
|| (! TARGET_64BIT && regs_ever_live[i + 1]))
|
||||
{
|
||||
emit_move_insn (gen_rtx_MEM (DFmode,
|
||||
gen_rtx_POST_INC (DFmode, tmpreg)),
|
||||
gen_rtx_REG (DFmode, i));
|
||||
rtx addr, reg;
|
||||
addr = gen_rtx_MEM (DFmode, gen_rtx_POST_INC (DFmode, tmpreg));
|
||||
reg = gen_rtx_REG (DFmode, i);
|
||||
FRP (emit_move_insn (addr, reg));
|
||||
fr_saved++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* ?!? Do we want frame notes in the epilogue yet? */
|
||||
#undef DO_FRAME_NOTES
|
||||
#define DO_FRAME_NOTES 0
|
||||
#undef FRP
|
||||
#define FRP(INSN) INSN
|
||||
|
||||
/* Emit RTL to load REG from the memory location specified by BASE+DISP.
|
||||
Handle case where DISP > 8k by using the add_high_const patterns. */
|
||||
|
||||
static rtx
|
||||
load_reg (reg, disp, base)
|
||||
int reg, disp, base;
|
||||
{
|
||||
rtx i, src, dest, basereg;
|
||||
|
||||
dest = gen_rtx_REG (word_mode, reg);
|
||||
basereg = gen_rtx_REG (Pmode, base);
|
||||
if (VAL_14_BITS_P (disp))
|
||||
{
|
||||
src = gen_rtx_MEM (word_mode, plus_constant (basereg, disp));
|
||||
i = emit_move_insn (dest, src);
|
||||
}
|
||||
else
|
||||
{
|
||||
rtx delta = GEN_INT (disp);
|
||||
rtx high = gen_rtx_PLUS (Pmode, basereg, gen_rtx_HIGH (Pmode, delta));
|
||||
rtx tmpreg = gen_rtx_REG (Pmode, 1);
|
||||
emit_move_insn (tmpreg, high);
|
||||
src = gen_rtx_MEM (word_mode, gen_rtx_LO_SUM (Pmode, tmpreg, delta));
|
||||
i = emit_move_insn (dest, src);
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
void
|
||||
output_function_epilogue (file, size)
|
||||
|
@ -3159,7 +3236,7 @@ hppa_expand_epilogue ()
|
|||
ret_off = TARGET_64BIT ? -16 : -20;
|
||||
if (frame_pointer_needed)
|
||||
{
|
||||
load_reg (2, ret_off, FRAME_POINTER_REGNUM);
|
||||
FRP (load_reg (2, ret_off, FRAME_POINTER_REGNUM));
|
||||
ret_off = 0;
|
||||
}
|
||||
else
|
||||
|
@ -3167,7 +3244,7 @@ hppa_expand_epilogue ()
|
|||
/* No frame pointer, and stack is smaller than 8k. */
|
||||
if (VAL_14_BITS_P (ret_off - actual_fsize))
|
||||
{
|
||||
load_reg (2, ret_off - actual_fsize, STACK_POINTER_REGNUM);
|
||||
FRP (load_reg (2, ret_off - actual_fsize, STACK_POINTER_REGNUM));
|
||||
ret_off = 0;
|
||||
}
|
||||
}
|
||||
|
@ -3179,7 +3256,7 @@ hppa_expand_epilogue ()
|
|||
for (i = 18, offset = local_fsize; i >= 4; i--)
|
||||
if (regs_ever_live[i] && ! call_used_regs[i])
|
||||
{
|
||||
load_reg (i, offset, FRAME_POINTER_REGNUM);
|
||||
FRP (load_reg (i, offset, FRAME_POINTER_REGNUM));
|
||||
offset += UNITS_PER_WORD;
|
||||
}
|
||||
}
|
||||
|
@ -3197,7 +3274,7 @@ hppa_expand_epilogue ()
|
|||
&& VAL_14_BITS_P (-actual_fsize))
|
||||
merge_sp_adjust_with_load = i;
|
||||
else
|
||||
load_reg (i, offset, STACK_POINTER_REGNUM);
|
||||
FRP (load_reg (i, offset, STACK_POINTER_REGNUM));
|
||||
offset += UNITS_PER_WORD;
|
||||
}
|
||||
}
|
||||
|
@ -3211,21 +3288,19 @@ hppa_expand_epilogue ()
|
|||
{
|
||||
/* Adjust the register to index off of. */
|
||||
if (frame_pointer_needed)
|
||||
set_reg_plus_d (1, FRAME_POINTER_REGNUM, offset);
|
||||
FRP (set_reg_plus_d (1, FRAME_POINTER_REGNUM, offset));
|
||||
else
|
||||
set_reg_plus_d (1, STACK_POINTER_REGNUM, offset);
|
||||
FRP (set_reg_plus_d (1, STACK_POINTER_REGNUM, offset));
|
||||
|
||||
/* Actually do the restores now. */
|
||||
for (i = FP_SAVED_REG_LAST; i >= FP_SAVED_REG_FIRST; i -= FP_REG_STEP)
|
||||
{
|
||||
if (regs_ever_live[i]
|
||||
|| (! TARGET_64BIT && regs_ever_live[i + 1]))
|
||||
{
|
||||
emit_move_insn (gen_rtx_REG (DFmode, i),
|
||||
gen_rtx_MEM (DFmode,
|
||||
gen_rtx_POST_INC (DFmode, tmpreg)));
|
||||
}
|
||||
}
|
||||
if (regs_ever_live[i]
|
||||
|| (! TARGET_64BIT && regs_ever_live[i + 1]))
|
||||
{
|
||||
rtx src = gen_rtx_MEM (DFmode, gen_rtx_POST_INC (DFmode, tmpreg));
|
||||
rtx dest = gen_rtx_REG (DFmode, i);
|
||||
FRP (emit_move_insn (dest, src));
|
||||
}
|
||||
}
|
||||
|
||||
/* Emit a blockage insn here to keep these insns from being moved to
|
||||
|
@ -3239,35 +3314,33 @@ hppa_expand_epilogue ()
|
|||
pointer is initially set to fp + 64 to avoid a race condition. */
|
||||
if (frame_pointer_needed)
|
||||
{
|
||||
set_reg_plus_d (STACK_POINTER_REGNUM, FRAME_POINTER_REGNUM, 64);
|
||||
emit_insn (gen_pre_load (frame_pointer_rtx,
|
||||
stack_pointer_rtx,
|
||||
GEN_INT (-64)));
|
||||
rtx delta = GEN_INT (-64);
|
||||
FRP (set_reg_plus_d (STACK_POINTER_REGNUM, FRAME_POINTER_REGNUM, 64));
|
||||
FRP (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);
|
||||
emit_insn (gen_pre_load (gen_rtx_REG (word_mode,
|
||||
merge_sp_adjust_with_load),
|
||||
stack_pointer_rtx,
|
||||
delta));
|
||||
rtx dest = gen_rtx_REG (word_mode, merge_sp_adjust_with_load);
|
||||
FRP (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);
|
||||
}
|
||||
FRP (set_reg_plus_d (STACK_POINTER_REGNUM,
|
||||
STACK_POINTER_REGNUM,
|
||||
- actual_fsize));
|
||||
|
||||
/* 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);
|
||||
FRP (load_reg (2, ret_off, STACK_POINTER_REGNUM));
|
||||
}
|
||||
|
||||
/* Set up a callee saved register for the pic offset table register. */
|
||||
void hppa_init_pic_save ()
|
||||
void
|
||||
hppa_init_pic_save ()
|
||||
{
|
||||
rtx insn, picreg;
|
||||
|
||||
|
|
117
gcc/dwarf2out.c
117
gcc/dwarf2out.c
|
@ -1133,11 +1133,13 @@ static dw_cfa_location cfa_temp;
|
|||
cfa_store.reg to the actual CFA
|
||||
cfa_temp register holding an integral value. cfa_temp.offset
|
||||
stores the value, which will be used to adjust the
|
||||
stack pointer.
|
||||
stack pointer. cfa_temp is also used like cfa_store,
|
||||
to track stores to the stack via fp or a temp reg.
|
||||
|
||||
Rules 1- 4: Setting a register's value to cfa.reg or an expression
|
||||
with cfa.reg as the first operand changes the cfa.reg and its
|
||||
cfa.offset.
|
||||
cfa.offset. Rule 1 and 4 also set cfa_temp.reg and
|
||||
cfa_temp.offset.
|
||||
|
||||
Rules 6- 9: Set a non-cfa.reg register value to a constant or an
|
||||
expression yielding a constant. This sets cfa_temp.reg
|
||||
|
@ -1146,9 +1148,9 @@ static dw_cfa_location cfa_temp;
|
|||
Rule 5: Create a new register cfa_store used to save items to the
|
||||
stack.
|
||||
|
||||
Rules 10-13: Save a register to the stack. Define offset as the
|
||||
Rules 10-14: Save a register to the stack. Define offset as the
|
||||
difference of the original location and cfa_store's
|
||||
location.
|
||||
location (or cfa_temp's location if cfa_temp is used).
|
||||
|
||||
The Rules
|
||||
|
||||
|
@ -1157,26 +1159,30 @@ static dw_cfa_location cfa_temp;
|
|||
|
||||
Rule 1:
|
||||
(set <reg1> <reg2>:cfa.reg)
|
||||
effects: cfa.reg = <REG1>
|
||||
effects: cfa.reg = <reg1>
|
||||
cfa.offset unchanged
|
||||
cfa_temp.reg = <reg1>
|
||||
cfa_temp.offset = cfa.offset
|
||||
|
||||
Rule 2:
|
||||
(set sp ({minus,plus} {sp,fp}:cfa.reg {<const_int>,<reg>:cfa_temp.reg}))
|
||||
(set sp ({minus,plus,losum} {sp,fp}:cfa.reg {<const_int>,<reg>:cfa_temp.reg}))
|
||||
effects: cfa.reg = sp if fp used
|
||||
cfa.offset += {+/- <const_int>, cfa_temp.offset} if cfa.reg==sp
|
||||
cfa_store.offset += {+/- <const_int>, cfa_temp.offset}
|
||||
if cfa_store.reg==sp
|
||||
|
||||
Rule 3:
|
||||
(set fp ({minus,plus} <reg>:cfa.reg <const_int>))
|
||||
(set fp ({minus,plus,losum} <reg>:cfa.reg <const_int>))
|
||||
effects: cfa.reg = fp
|
||||
cfa_offset += +/- <const_int>
|
||||
|
||||
Rule 4:
|
||||
(set <reg1> (plus <reg2>:cfa.reg <const_int>))
|
||||
(set <reg1> ({plus,losum} <reg2>:cfa.reg <const_int>))
|
||||
constraints: <reg1> != fp
|
||||
<reg1> != sp
|
||||
effects: cfa.reg = <reg1>
|
||||
cfa_temp.reg = <reg1>
|
||||
cfa_temp.offset = cfa.offset
|
||||
|
||||
Rule 5:
|
||||
(set <reg1> (plus <reg2>:cfa_temp.reg sp:cfa.reg))
|
||||
|
@ -1208,30 +1214,31 @@ static dw_cfa_location cfa_temp;
|
|||
(set (mem (pre_modify sp:cfa_store (???? <reg1> <const_int>))) <reg2>)
|
||||
effects: cfa_store.offset -= <const_int>
|
||||
cfa.offset = cfa_store.offset if cfa.reg == sp
|
||||
offset = -cfa_store.offset
|
||||
cfa.reg = sp
|
||||
cfa.base_offset = offset
|
||||
cfa.base_offset = -cfa_store.offset
|
||||
|
||||
Rule 11:
|
||||
(set (mem ({pre_inc,pre_dec} sp:cfa_store.reg)) <reg>)
|
||||
effects: cfa_store.offset += -/+ mode_size(mem)
|
||||
cfa.offset = cfa_store.offset if cfa.reg == sp
|
||||
offset = -cfa_store.offset
|
||||
cfa.reg = sp
|
||||
cfa.base_offset = offset
|
||||
cfa.base_offset = -cfa_store.offset
|
||||
|
||||
Rule 12:
|
||||
(set (mem ({minus,plus} <reg1>:cfa_store <const_int>)) <reg2>)
|
||||
effects: cfa_store.offset += -/+ <const_int>
|
||||
offset = -cfa_store.offset
|
||||
cfa.reg = <reg1
|
||||
cfa.base_offset = offset
|
||||
(set (mem ({minus,plus,losum} <reg1>:{cfa_store,cfa_temp} <const_int>)) <reg2>)
|
||||
effects: cfa.reg = <reg1>
|
||||
cfa.base_offset = -/+ <const_int> - {cfa_store,cfa_temp}.offset
|
||||
|
||||
Rule 13:
|
||||
(set (mem <reg1>:cfa_store) <reg2>)
|
||||
effects: offset = -cfa_store.offset
|
||||
cfa.reg = <reg1>
|
||||
cfa.base_offset = offset */
|
||||
(set (mem <reg1>:{cfa_store,cfa_temp}) <reg2>)
|
||||
effects: cfa.reg = <reg1>
|
||||
cfa.base_offset = -{cfa_store,cfa_temp}.offset
|
||||
|
||||
Rule 14:
|
||||
(set (mem (postinc <reg1>:cfa_temp <const_int>)) <reg2>)
|
||||
effects: cfa.reg = <reg1>
|
||||
cfa.base_offset = -cfa_temp.offset
|
||||
cfa_temp.offset -= mode_size(mem) */
|
||||
|
||||
static void
|
||||
dwarf2out_frame_debug_expr (expr, label)
|
||||
|
@ -1291,10 +1298,13 @@ dwarf2out_frame_debug_expr (expr, label)
|
|||
FP. So we just rely on the backends to only set
|
||||
RTX_FRAME_RELATED_P on appropriate insns. */
|
||||
cfa.reg = REGNO (dest);
|
||||
cfa_temp.reg = cfa.reg;
|
||||
cfa_temp.offset = cfa.offset;
|
||||
break;
|
||||
|
||||
case PLUS:
|
||||
case MINUS:
|
||||
case LO_SUM:
|
||||
if (dest == stack_pointer_rtx)
|
||||
{
|
||||
/* Rule 2 */
|
||||
|
@ -1320,10 +1330,13 @@ dwarf2out_frame_debug_expr (expr, label)
|
|||
abort ();
|
||||
cfa.reg = STACK_POINTER_REGNUM;
|
||||
}
|
||||
else if (GET_CODE (src) == LO_SUM)
|
||||
/* Assume we've set the source reg of the LO_SUM from sp. */
|
||||
;
|
||||
else if (XEXP (src, 0) != stack_pointer_rtx)
|
||||
abort ();
|
||||
|
||||
if (GET_CODE (src) == PLUS)
|
||||
if (GET_CODE (src) != MINUS)
|
||||
offset = -offset;
|
||||
if (cfa.reg == STACK_POINTER_REGNUM)
|
||||
cfa.offset += offset;
|
||||
|
@ -1343,7 +1356,7 @@ dwarf2out_frame_debug_expr (expr, label)
|
|||
&& GET_CODE (XEXP (src, 1)) == CONST_INT)
|
||||
{
|
||||
offset = INTVAL (XEXP (src, 1));
|
||||
if (GET_CODE (src) == PLUS)
|
||||
if (GET_CODE (src) != MINUS)
|
||||
offset = -offset;
|
||||
cfa.offset += offset;
|
||||
cfa.reg = HARD_FRAME_POINTER_REGNUM;
|
||||
|
@ -1353,7 +1366,7 @@ dwarf2out_frame_debug_expr (expr, label)
|
|||
}
|
||||
else
|
||||
{
|
||||
if (GET_CODE (src) != PLUS)
|
||||
if (GET_CODE (src) == MINUS)
|
||||
abort ();
|
||||
|
||||
/* Rule 4 */
|
||||
|
@ -1363,27 +1376,34 @@ dwarf2out_frame_debug_expr (expr, label)
|
|||
{
|
||||
/* Setting a temporary CFA register that will be copied
|
||||
into the FP later on. */
|
||||
offset = INTVAL (XEXP (src, 1));
|
||||
if (GET_CODE (src) == PLUS)
|
||||
offset = -offset;
|
||||
offset = - INTVAL (XEXP (src, 1));
|
||||
cfa.offset += offset;
|
||||
cfa.reg = REGNO (dest);
|
||||
/* Or used to save regs to the stack. */
|
||||
cfa_temp.reg = cfa.reg;
|
||||
cfa_temp.offset = cfa.offset;
|
||||
}
|
||||
/* Rule 5 */
|
||||
else
|
||||
else if (GET_CODE (XEXP (src, 0)) == REG
|
||||
&& REGNO (XEXP (src, 0)) == cfa_temp.reg
|
||||
&& XEXP (src, 1) == stack_pointer_rtx)
|
||||
{
|
||||
/* Setting a scratch register that we will use instead
|
||||
of SP for saving registers to the stack. */
|
||||
if (XEXP (src, 1) != stack_pointer_rtx)
|
||||
abort ();
|
||||
if (GET_CODE (XEXP (src, 0)) != REG
|
||||
|| (unsigned) REGNO (XEXP (src, 0)) != cfa_temp.reg)
|
||||
abort ();
|
||||
if (cfa.reg != STACK_POINTER_REGNUM)
|
||||
abort ();
|
||||
cfa_store.reg = REGNO (dest);
|
||||
cfa_store.offset = cfa.offset - cfa_temp.offset;
|
||||
}
|
||||
/* Rule 9 */
|
||||
else if (GET_CODE (src) == LO_SUM
|
||||
&& GET_CODE (XEXP (src, 1)) == CONST_INT)
|
||||
{
|
||||
cfa_temp.reg = REGNO (dest);
|
||||
cfa_temp.offset = INTVAL (XEXP (src, 1));
|
||||
}
|
||||
else
|
||||
abort ();
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -1410,14 +1430,6 @@ dwarf2out_frame_debug_expr (expr, label)
|
|||
case HIGH:
|
||||
break;
|
||||
|
||||
/* Rule 9 */
|
||||
case LO_SUM:
|
||||
if (GET_CODE (XEXP (src, 1)) != CONST_INT)
|
||||
abort ();
|
||||
cfa_temp.reg = REGNO (dest);
|
||||
cfa_temp.offset = INTVAL (XEXP (src, 1));
|
||||
break;
|
||||
|
||||
default:
|
||||
abort ();
|
||||
}
|
||||
|
@ -1470,23 +1482,38 @@ dwarf2out_frame_debug_expr (expr, label)
|
|||
/* With an offset. */
|
||||
case PLUS:
|
||||
case MINUS:
|
||||
case LO_SUM:
|
||||
if (GET_CODE (XEXP (XEXP (dest, 0), 1)) != CONST_INT)
|
||||
abort ();
|
||||
offset = INTVAL (XEXP (XEXP (dest, 0), 1));
|
||||
if (GET_CODE (XEXP (dest, 0)) == MINUS)
|
||||
offset = -offset;
|
||||
|
||||
if (cfa_store.reg != (unsigned) REGNO (XEXP (XEXP (dest, 0), 0)))
|
||||
if (cfa_store.reg == (unsigned) REGNO (XEXP (XEXP (dest, 0), 0)))
|
||||
offset -= cfa_store.offset;
|
||||
else if (cfa_temp.reg == (unsigned) REGNO (XEXP (XEXP (dest, 0), 0)))
|
||||
offset -= cfa_temp.offset;
|
||||
else
|
||||
abort ();
|
||||
offset -= cfa_store.offset;
|
||||
break;
|
||||
|
||||
/* Rule 13 */
|
||||
/* Without an offset. */
|
||||
case REG:
|
||||
if (cfa_store.reg != (unsigned) REGNO (XEXP (dest, 0)))
|
||||
if (cfa_store.reg == (unsigned) REGNO (XEXP (dest, 0)))
|
||||
offset = -cfa_store.offset;
|
||||
else if (cfa_temp.reg == (unsigned) REGNO (XEXP (dest, 0)))
|
||||
offset = -cfa_temp.offset;
|
||||
else
|
||||
abort ();
|
||||
offset = -cfa_store.offset;
|
||||
break;
|
||||
|
||||
/* Rule 14 */
|
||||
case POST_INC:
|
||||
if (cfa_temp.reg != (unsigned) REGNO (XEXP (XEXP (dest, 0), 0)))
|
||||
abort ();
|
||||
offset = -cfa_temp.offset;
|
||||
cfa_temp.offset -= GET_MODE_SIZE (GET_MODE (dest));
|
||||
break;
|
||||
|
||||
default:
|
||||
|
|
Loading…
Add table
Reference in a new issue