Commit 19ec6a36 by Alan Modra Committed by Alan Modra

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
parent 78e766a0
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> 2001-04-03 Richard Henderson <rth@redhat.com>
* configure.in (gcc_cv_as_leb128): Reject gas before 2.11. * configure.in (gcc_cv_as_leb128): Reject gas before 2.11.
......
...@@ -42,21 +42,29 @@ Boston, MA 02111-1307, USA. */ ...@@ -42,21 +42,29 @@ Boston, MA 02111-1307, USA. */
#include "recog.h" #include "recog.h"
#include "tm_p.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_init_machine_status PARAMS ((struct function *));
static void pa_mark_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_free_machine_status PARAMS ((struct function *));
static void pa_combine_instructions PARAMS ((rtx)); static void pa_combine_instructions PARAMS ((rtx));
static int pa_can_combine_p PARAMS ((rtx, rtx, rtx, int, rtx, rtx, rtx)); static int pa_can_combine_p PARAMS ((rtx, rtx, rtx, int, rtx, rtx, rtx));
static int forward_branch_p PARAMS ((rtx)); static int forward_branch_p PARAMS ((rtx));
static int shadd_constant_p PARAMS ((int)); static int shadd_constant_p PARAMS ((int));
static void pa_add_gc_roots PARAMS ((void)); static void pa_add_gc_roots PARAMS ((void));
static void mark_deferred_plabels PARAMS ((void *)); static void mark_deferred_plabels PARAMS ((void *));
static void compute_zdepwi_operands PARAMS ((unsigned HOST_WIDE_INT, unsigned *)); static void compute_zdepwi_operands PARAMS ((unsigned HOST_WIDE_INT, unsigned *));
static int compute_movstrsi_length PARAMS ((rtx)); static int compute_movstrsi_length PARAMS ((rtx));
static void remove_useless_addtr_insns PARAMS ((rtx, int)); static void remove_useless_addtr_insns PARAMS ((rtx, int));
static void store_reg PARAMS ((int, int, int)); static rtx store_reg PARAMS ((int, int, int));
static void load_reg PARAMS ((int, int, int)); static rtx load_reg PARAMS ((int, int, int));
static void set_reg_plus_d 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 /* Save the operands last given to a compare for use when we
generate a scc or bcc insn. */ generate a scc or bcc insn. */
...@@ -2003,7 +2011,6 @@ output_move_double (operands) ...@@ -2003,7 +2011,6 @@ output_move_double (operands)
xoperands); xoperands);
return "ldw 0(%R0),%0\n\tldw 4(%R0),%R0"; return "ldw 0(%R0),%0\n\tldw 4(%R0),%R0";
} }
} }
} }
...@@ -2743,60 +2750,41 @@ remove_useless_addtr_insns (insns, check_notes) ...@@ -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. /* 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. 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 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.*/ in %r1. There is code in expand_hppa_{prologue,epilogue} that knows this.*/
static void static rtx
store_reg (reg, disp, base) store_reg (reg, disp, base)
int 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)) 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));
else
{ {
emit_move_insn (gen_rtx_REG (Pmode, 1), dest = gen_rtx_MEM (word_mode, plus_constant (basereg, disp));
gen_rtx_PLUS (Pmode, gen_rtx_REG (Pmode, base), i = emit_move_insn (dest, src);
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 else
{ {
emit_move_insn (gen_rtx_REG (Pmode, 1), rtx delta = GEN_INT (disp);
gen_rtx_PLUS (Pmode, gen_rtx_REG (Pmode, base), rtx high = gen_rtx_PLUS (Pmode, basereg, gen_rtx_HIGH (Pmode, delta));
gen_rtx_HIGH (Pmode, GEN_INT (disp)))); rtx tmpreg = gen_rtx_REG (Pmode, 1);
emit_move_insn (gen_rtx_REG (word_mode, reg), emit_move_insn (tmpreg, high);
gen_rtx_MEM (word_mode, dest = gen_rtx_MEM (word_mode, gen_rtx_LO_SUM (Pmode, tmpreg, delta));
gen_rtx_LO_SUM (Pmode, i = emit_move_insn (dest, src);
gen_rtx_REG (Pmode, 1),
GEN_INT (disp))));
} }
return i;
} }
/* Emit RTL to set REG to the value specified by BASE+DISP. /* Emit RTL to set REG to the value specified by BASE+DISP.
...@@ -2805,31 +2793,30 @@ load_reg (reg, disp, base) ...@@ -2805,31 +2793,30 @@ load_reg (reg, disp, base)
Note in DISP > 8k case, we will leave the high part of the address 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.*/ in %r1. There is code in expand_hppa_{prologue,epilogue} that knows this.*/
static void static rtx
set_reg_plus_d (reg, base, disp) set_reg_plus_d (reg, base, disp)
int reg, base, disp; int reg, base, disp;
{ {
rtx i;
if (VAL_14_BITS_P (disp)) 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 else
{ {
rtx delta = GEN_INT (disp);
emit_move_insn (gen_rtx_REG (Pmode, 1), emit_move_insn (gen_rtx_REG (Pmode, 1),
gen_rtx_PLUS (Pmode, gen_rtx_REG (Pmode, base), gen_rtx_PLUS (Pmode, gen_rtx_REG (Pmode, base),
gen_rtx_HIGH (Pmode, GEN_INT (disp)))); gen_rtx_HIGH (Pmode, delta)));
emit_move_insn (gen_rtx_REG (Pmode, reg), i = emit_move_insn (gen_rtx_REG (Pmode, reg),
gen_rtx_LO_SUM (Pmode, gen_rtx_LO_SUM (Pmode, gen_rtx_REG (Pmode, 1),
gen_rtx_REG (Pmode, 1), delta));
GEN_INT (disp)));
} }
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 int
compute_frame_size (size, fregs_live) compute_frame_size (size, fregs_live)
int size; int size;
...@@ -2937,8 +2924,20 @@ output_function_prologue (file, size) ...@@ -2937,8 +2924,20 @@ output_function_prologue (file, size)
remove_useless_addtr_insns (get_insns (), 0); 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 void
hppa_expand_prologue() hppa_expand_prologue ()
{ {
extern char call_used_regs[]; extern char call_used_regs[];
int size = get_frame_size (); int size = get_frame_size ();
...@@ -2965,10 +2964,10 @@ hppa_expand_prologue() ...@@ -2965,10 +2964,10 @@ hppa_expand_prologue()
size_rtx = GEN_INT (actual_fsize); size_rtx = GEN_INT (actual_fsize);
/* Save RP first. The calling conventions manual states RP will /* 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. */ depending on which ABI is in use. */
if (regs_ever_live[2]) 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. */ /* Allocate the local frame and set up the frame pointer if needed. */
if (actual_fsize != 0) if (actual_fsize != 0)
...@@ -2982,9 +2981,31 @@ hppa_expand_prologue() ...@@ -2982,9 +2981,31 @@ hppa_expand_prologue()
handles small (<8k) frames. The second handles large (>=8k) handles small (<8k) frames. The second handles large (>=8k)
frames. */ frames. */
emit_move_insn (tmpreg, frame_pointer_rtx); 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)) 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 else
{ {
/* It is incorrect to store the saved frame pointer at *sp, /* It is incorrect to store the saved frame pointer at *sp,
...@@ -2996,10 +3017,31 @@ hppa_expand_prologue() ...@@ -2996,10 +3017,31 @@ hppa_expand_prologue()
int adjust1 = 8192 - 64; int adjust1 = 8192 - 64;
int adjust2 = actual_fsize - adjust1; int adjust2 = actual_fsize - adjust1;
rtx delta = GEN_INT (adjust1); rtx delta = GEN_INT (adjust1);
emit_insn (gen_post_store (stack_pointer_rtx, tmpreg, delta)); rtx insn = emit_insn (gen_post_store (stack_pointer_rtx, tmpreg,
set_reg_plus_d (STACK_POINTER_REGNUM, delta));
STACK_POINTER_REGNUM, if (DO_FRAME_NOTES)
adjust2); {
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 /* Prevent register spills from being scheduled before the
stack pointer is raised. Necessary as we will be storing stack pointer is raised. Necessary as we will be storing
...@@ -3019,9 +3061,9 @@ hppa_expand_prologue() ...@@ -3019,9 +3061,9 @@ hppa_expand_prologue()
/* Can not optimize. Adjust the stack frame by actual_fsize /* Can not optimize. Adjust the stack frame by actual_fsize
bytes. */ bytes. */
else else
set_reg_plus_d (STACK_POINTER_REGNUM, FRP (set_reg_plus_d (STACK_POINTER_REGNUM,
STACK_POINTER_REGNUM, STACK_POINTER_REGNUM,
actual_fsize); actual_fsize));
} }
} }
...@@ -3034,7 +3076,7 @@ hppa_expand_prologue() ...@@ -3034,7 +3076,7 @@ hppa_expand_prologue()
for (i = 18, offset = local_fsize; i >= 4; i--) for (i = 18, offset = local_fsize; i >= 4; i--)
if (regs_ever_live[i] && ! call_used_regs[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; offset += UNITS_PER_WORD;
gr_saved++; gr_saved++;
} }
...@@ -3051,13 +3093,14 @@ hppa_expand_prologue() ...@@ -3051,13 +3093,14 @@ hppa_expand_prologue()
optimize the first GR save. */ optimize the first GR save. */
if (merge_sp_adjust_with_store) if (merge_sp_adjust_with_store)
{ {
rtx delta = GEN_INT (-offset);
merge_sp_adjust_with_store = 0; merge_sp_adjust_with_store = 0;
emit_insn (gen_post_store (stack_pointer_rtx, FRP (emit_insn (gen_post_store (stack_pointer_rtx,
gen_rtx_REG (word_mode, i), gen_rtx_REG (word_mode, i),
GEN_INT (-offset))); delta)));
} }
else else
store_reg (i, offset, STACK_POINTER_REGNUM); FRP (store_reg (i, offset, STACK_POINTER_REGNUM));
offset += UNITS_PER_WORD; offset += UNITS_PER_WORD;
gr_saved++; gr_saved++;
} }
...@@ -3065,9 +3108,9 @@ hppa_expand_prologue() ...@@ -3065,9 +3108,9 @@ hppa_expand_prologue()
/* If we wanted to merge the SP adjustment with a GR save, but we never /* 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. */ did any GR saves, then just emit the adjustment here. */
if (merge_sp_adjust_with_store) if (merge_sp_adjust_with_store)
set_reg_plus_d (STACK_POINTER_REGNUM, FRP (set_reg_plus_d (STACK_POINTER_REGNUM,
STACK_POINTER_REGNUM, STACK_POINTER_REGNUM,
actual_fsize); actual_fsize));
} }
/* The hppa calling conventions say that %r19, the pic offset /* The hppa calling conventions say that %r19, the pic offset
...@@ -3088,9 +3131,9 @@ hppa_expand_prologue() ...@@ -3088,9 +3131,9 @@ hppa_expand_prologue()
/* First get the frame or stack pointer to the start of the FP register /* First get the frame or stack pointer to the start of the FP register
save area. */ save area. */
if (frame_pointer_needed) if (frame_pointer_needed)
set_reg_plus_d (1, FRAME_POINTER_REGNUM, offset); FRP (set_reg_plus_d (1, FRAME_POINTER_REGNUM, offset));
else 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. */ /* Now actually save the FP registers. */
for (i = FP_SAVED_REG_LAST; i >= FP_SAVED_REG_FIRST; i -= FP_REG_STEP) for (i = FP_SAVED_REG_LAST; i >= FP_SAVED_REG_FIRST; i -= FP_REG_STEP)
...@@ -3098,15 +3141,49 @@ hppa_expand_prologue() ...@@ -3098,15 +3141,49 @@ hppa_expand_prologue()
if (regs_ever_live[i] if (regs_ever_live[i]
|| (! TARGET_64BIT && regs_ever_live[i + 1])) || (! TARGET_64BIT && regs_ever_live[i + 1]))
{ {
emit_move_insn (gen_rtx_MEM (DFmode, rtx addr, reg;
gen_rtx_POST_INC (DFmode, tmpreg)), addr = gen_rtx_MEM (DFmode, gen_rtx_POST_INC (DFmode, tmpreg));
gen_rtx_REG (DFmode, i)); reg = gen_rtx_REG (DFmode, i);
FRP (emit_move_insn (addr, reg));
fr_saved++; 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 void
output_function_epilogue (file, size) output_function_epilogue (file, size)
...@@ -3159,7 +3236,7 @@ hppa_expand_epilogue () ...@@ -3159,7 +3236,7 @@ hppa_expand_epilogue ()
ret_off = TARGET_64BIT ? -16 : -20; ret_off = TARGET_64BIT ? -16 : -20;
if (frame_pointer_needed) if (frame_pointer_needed)
{ {
load_reg (2, ret_off, FRAME_POINTER_REGNUM); FRP (load_reg (2, ret_off, FRAME_POINTER_REGNUM));
ret_off = 0; ret_off = 0;
} }
else else
...@@ -3167,7 +3244,7 @@ hppa_expand_epilogue () ...@@ -3167,7 +3244,7 @@ hppa_expand_epilogue ()
/* No frame pointer, and stack is smaller than 8k. */ /* No frame pointer, and stack is smaller than 8k. */
if (VAL_14_BITS_P (ret_off - actual_fsize)) 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; ret_off = 0;
} }
} }
...@@ -3179,7 +3256,7 @@ hppa_expand_epilogue () ...@@ -3179,7 +3256,7 @@ hppa_expand_epilogue ()
for (i = 18, offset = local_fsize; i >= 4; i--) for (i = 18, offset = local_fsize; i >= 4; i--)
if (regs_ever_live[i] && ! call_used_regs[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; offset += UNITS_PER_WORD;
} }
} }
...@@ -3197,7 +3274,7 @@ hppa_expand_epilogue () ...@@ -3197,7 +3274,7 @@ hppa_expand_epilogue ()
&& VAL_14_BITS_P (-actual_fsize)) && VAL_14_BITS_P (-actual_fsize))
merge_sp_adjust_with_load = i; merge_sp_adjust_with_load = i;
else else
load_reg (i, offset, STACK_POINTER_REGNUM); FRP (load_reg (i, offset, STACK_POINTER_REGNUM));
offset += UNITS_PER_WORD; offset += UNITS_PER_WORD;
} }
} }
...@@ -3211,21 +3288,19 @@ hppa_expand_epilogue () ...@@ -3211,21 +3288,19 @@ hppa_expand_epilogue ()
{ {
/* Adjust the register to index off of. */ /* Adjust the register to index off of. */
if (frame_pointer_needed) if (frame_pointer_needed)
set_reg_plus_d (1, FRAME_POINTER_REGNUM, offset); FRP (set_reg_plus_d (1, FRAME_POINTER_REGNUM, offset));
else 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. */ /* Actually do the restores now. */
for (i = FP_SAVED_REG_LAST; i >= FP_SAVED_REG_FIRST; i -= FP_REG_STEP) for (i = FP_SAVED_REG_LAST; i >= FP_SAVED_REG_FIRST; i -= FP_REG_STEP)
{ if (regs_ever_live[i]
if (regs_ever_live[i] || (! TARGET_64BIT && regs_ever_live[i + 1]))
|| (! TARGET_64BIT && regs_ever_live[i + 1])) {
{ rtx src = gen_rtx_MEM (DFmode, gen_rtx_POST_INC (DFmode, tmpreg));
emit_move_insn (gen_rtx_REG (DFmode, i), rtx dest = gen_rtx_REG (DFmode, i);
gen_rtx_MEM (DFmode, FRP (emit_move_insn (dest, src));
gen_rtx_POST_INC (DFmode, tmpreg))); }
}
}
} }
/* Emit a blockage insn here to keep these insns from being moved to /* Emit a blockage insn here to keep these insns from being moved to
...@@ -3239,35 +3314,33 @@ hppa_expand_epilogue () ...@@ -3239,35 +3314,33 @@ hppa_expand_epilogue ()
pointer is initially set to fp + 64 to avoid a race condition. */ pointer is initially set to fp + 64 to avoid a race condition. */
if (frame_pointer_needed) if (frame_pointer_needed)
{ {
set_reg_plus_d (STACK_POINTER_REGNUM, FRAME_POINTER_REGNUM, 64); rtx delta = GEN_INT (-64);
emit_insn (gen_pre_load (frame_pointer_rtx, FRP (set_reg_plus_d (STACK_POINTER_REGNUM, FRAME_POINTER_REGNUM, 64));
stack_pointer_rtx, FRP (emit_insn (gen_pre_load (frame_pointer_rtx,
GEN_INT (-64))); stack_pointer_rtx,
delta)));
} }
/* If we were deferring a callee register restore, do it now. */ /* If we were deferring a callee register restore, do it now. */
else if (merge_sp_adjust_with_load) else if (merge_sp_adjust_with_load)
{ {
rtx delta = GEN_INT (-actual_fsize); rtx delta = GEN_INT (-actual_fsize);
emit_insn (gen_pre_load (gen_rtx_REG (word_mode, rtx dest = gen_rtx_REG (word_mode, merge_sp_adjust_with_load);
merge_sp_adjust_with_load), FRP (emit_insn (gen_pre_load (dest, stack_pointer_rtx, delta)));
stack_pointer_rtx,
delta));
} }
else if (actual_fsize != 0) else if (actual_fsize != 0)
{ FRP (set_reg_plus_d (STACK_POINTER_REGNUM,
set_reg_plus_d (STACK_POINTER_REGNUM, STACK_POINTER_REGNUM,
STACK_POINTER_REGNUM, - actual_fsize));
- actual_fsize);
}
/* If we haven't restored %r2 yet (no frame pointer, and a stack /* If we haven't restored %r2 yet (no frame pointer, and a stack
frame greater than 8k), do so now. */ frame greater than 8k), do so now. */
if (ret_off != 0) 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. */ /* 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; rtx insn, picreg;
......
...@@ -1133,11 +1133,13 @@ static dw_cfa_location cfa_temp; ...@@ -1133,11 +1133,13 @@ static dw_cfa_location cfa_temp;
cfa_store.reg to the actual CFA cfa_store.reg to the actual CFA
cfa_temp register holding an integral value. cfa_temp.offset cfa_temp register holding an integral value. cfa_temp.offset
stores the value, which will be used to adjust the 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 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 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 Rules 6- 9: Set a non-cfa.reg register value to a constant or an
expression yielding a constant. This sets cfa_temp.reg expression yielding a constant. This sets cfa_temp.reg
...@@ -1146,9 +1148,9 @@ static dw_cfa_location cfa_temp; ...@@ -1146,9 +1148,9 @@ static dw_cfa_location cfa_temp;
Rule 5: Create a new register cfa_store used to save items to the Rule 5: Create a new register cfa_store used to save items to the
stack. 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 difference of the original location and cfa_store's
location. location (or cfa_temp's location if cfa_temp is used).
The Rules The Rules
...@@ -1157,26 +1159,30 @@ static dw_cfa_location cfa_temp; ...@@ -1157,26 +1159,30 @@ static dw_cfa_location cfa_temp;
Rule 1: Rule 1:
(set <reg1> <reg2>:cfa.reg) (set <reg1> <reg2>:cfa.reg)
effects: cfa.reg = <REG1> effects: cfa.reg = <reg1>
cfa.offset unchanged cfa.offset unchanged
cfa_temp.reg = <reg1>
cfa_temp.offset = cfa.offset
Rule 2: 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 effects: cfa.reg = sp if fp used
cfa.offset += {+/- <const_int>, cfa_temp.offset} if cfa.reg==sp cfa.offset += {+/- <const_int>, cfa_temp.offset} if cfa.reg==sp
cfa_store.offset += {+/- <const_int>, cfa_temp.offset} cfa_store.offset += {+/- <const_int>, cfa_temp.offset}
if cfa_store.reg==sp if cfa_store.reg==sp
Rule 3: 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 effects: cfa.reg = fp
cfa_offset += +/- <const_int> cfa_offset += +/- <const_int>
Rule 4: Rule 4:
(set <reg1> (plus <reg2>:cfa.reg <const_int>)) (set <reg1> ({plus,losum} <reg2>:cfa.reg <const_int>))
constraints: <reg1> != fp constraints: <reg1> != fp
<reg1> != sp <reg1> != sp
effects: cfa.reg = <reg1> effects: cfa.reg = <reg1>
cfa_temp.reg = <reg1>
cfa_temp.offset = cfa.offset
Rule 5: Rule 5:
(set <reg1> (plus <reg2>:cfa_temp.reg sp:cfa.reg)) (set <reg1> (plus <reg2>:cfa_temp.reg sp:cfa.reg))
...@@ -1208,30 +1214,31 @@ static dw_cfa_location cfa_temp; ...@@ -1208,30 +1214,31 @@ static dw_cfa_location cfa_temp;
(set (mem (pre_modify sp:cfa_store (???? <reg1> <const_int>))) <reg2>) (set (mem (pre_modify sp:cfa_store (???? <reg1> <const_int>))) <reg2>)
effects: cfa_store.offset -= <const_int> effects: cfa_store.offset -= <const_int>
cfa.offset = cfa_store.offset if cfa.reg == sp cfa.offset = cfa_store.offset if cfa.reg == sp
offset = -cfa_store.offset
cfa.reg = sp cfa.reg = sp
cfa.base_offset = offset cfa.base_offset = -cfa_store.offset
Rule 11: Rule 11:
(set (mem ({pre_inc,pre_dec} sp:cfa_store.reg)) <reg>) (set (mem ({pre_inc,pre_dec} sp:cfa_store.reg)) <reg>)
effects: cfa_store.offset += -/+ mode_size(mem) effects: cfa_store.offset += -/+ mode_size(mem)
cfa.offset = cfa_store.offset if cfa.reg == sp cfa.offset = cfa_store.offset if cfa.reg == sp
offset = -cfa_store.offset
cfa.reg = sp cfa.reg = sp
cfa.base_offset = offset cfa.base_offset = -cfa_store.offset
Rule 12: Rule 12:
(set (mem ({minus,plus} <reg1>:cfa_store <const_int>)) <reg2>) (set (mem ({minus,plus,losum} <reg1>:{cfa_store,cfa_temp} <const_int>)) <reg2>)
effects: cfa_store.offset += -/+ <const_int> effects: cfa.reg = <reg1>
offset = -cfa_store.offset cfa.base_offset = -/+ <const_int> - {cfa_store,cfa_temp}.offset
cfa.reg = <reg1
cfa.base_offset = offset
Rule 13: Rule 13:
(set (mem <reg1>:cfa_store) <reg2>) (set (mem <reg1>:{cfa_store,cfa_temp}) <reg2>)
effects: offset = -cfa_store.offset effects: cfa.reg = <reg1>
cfa.reg = <reg1> cfa.base_offset = -{cfa_store,cfa_temp}.offset
cfa.base_offset = 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 static void
dwarf2out_frame_debug_expr (expr, label) dwarf2out_frame_debug_expr (expr, label)
...@@ -1291,10 +1298,13 @@ 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 FP. So we just rely on the backends to only set
RTX_FRAME_RELATED_P on appropriate insns. */ RTX_FRAME_RELATED_P on appropriate insns. */
cfa.reg = REGNO (dest); cfa.reg = REGNO (dest);
cfa_temp.reg = cfa.reg;
cfa_temp.offset = cfa.offset;
break; break;
case PLUS: case PLUS:
case MINUS: case MINUS:
case LO_SUM:
if (dest == stack_pointer_rtx) if (dest == stack_pointer_rtx)
{ {
/* Rule 2 */ /* Rule 2 */
...@@ -1320,10 +1330,13 @@ dwarf2out_frame_debug_expr (expr, label) ...@@ -1320,10 +1330,13 @@ dwarf2out_frame_debug_expr (expr, label)
abort (); abort ();
cfa.reg = STACK_POINTER_REGNUM; 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) else if (XEXP (src, 0) != stack_pointer_rtx)
abort (); abort ();
if (GET_CODE (src) == PLUS) if (GET_CODE (src) != MINUS)
offset = -offset; offset = -offset;
if (cfa.reg == STACK_POINTER_REGNUM) if (cfa.reg == STACK_POINTER_REGNUM)
cfa.offset += offset; cfa.offset += offset;
...@@ -1343,7 +1356,7 @@ dwarf2out_frame_debug_expr (expr, label) ...@@ -1343,7 +1356,7 @@ dwarf2out_frame_debug_expr (expr, label)
&& GET_CODE (XEXP (src, 1)) == CONST_INT) && GET_CODE (XEXP (src, 1)) == CONST_INT)
{ {
offset = INTVAL (XEXP (src, 1)); offset = INTVAL (XEXP (src, 1));
if (GET_CODE (src) == PLUS) if (GET_CODE (src) != MINUS)
offset = -offset; offset = -offset;
cfa.offset += offset; cfa.offset += offset;
cfa.reg = HARD_FRAME_POINTER_REGNUM; cfa.reg = HARD_FRAME_POINTER_REGNUM;
...@@ -1353,7 +1366,7 @@ dwarf2out_frame_debug_expr (expr, label) ...@@ -1353,7 +1366,7 @@ dwarf2out_frame_debug_expr (expr, label)
} }
else else
{ {
if (GET_CODE (src) != PLUS) if (GET_CODE (src) == MINUS)
abort (); abort ();
/* Rule 4 */ /* Rule 4 */
...@@ -1363,27 +1376,34 @@ dwarf2out_frame_debug_expr (expr, label) ...@@ -1363,27 +1376,34 @@ dwarf2out_frame_debug_expr (expr, label)
{ {
/* Setting a temporary CFA register that will be copied /* Setting a temporary CFA register that will be copied
into the FP later on. */ into the FP later on. */
offset = INTVAL (XEXP (src, 1)); offset = - INTVAL (XEXP (src, 1));
if (GET_CODE (src) == PLUS)
offset = -offset;
cfa.offset += offset; cfa.offset += offset;
cfa.reg = REGNO (dest); cfa.reg = REGNO (dest);
/* Or used to save regs to the stack. */
cfa_temp.reg = cfa.reg;
cfa_temp.offset = cfa.offset;
} }
/* Rule 5 */ /* 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 /* Setting a scratch register that we will use instead
of SP for saving registers to the stack. */ 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) if (cfa.reg != STACK_POINTER_REGNUM)
abort (); abort ();
cfa_store.reg = REGNO (dest); cfa_store.reg = REGNO (dest);
cfa_store.offset = cfa.offset - cfa_temp.offset; 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; break;
...@@ -1410,14 +1430,6 @@ dwarf2out_frame_debug_expr (expr, label) ...@@ -1410,14 +1430,6 @@ dwarf2out_frame_debug_expr (expr, label)
case HIGH: case HIGH:
break; 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: default:
abort (); abort ();
} }
...@@ -1470,23 +1482,38 @@ dwarf2out_frame_debug_expr (expr, label) ...@@ -1470,23 +1482,38 @@ dwarf2out_frame_debug_expr (expr, label)
/* With an offset. */ /* With an offset. */
case PLUS: case PLUS:
case MINUS: case MINUS:
case LO_SUM:
if (GET_CODE (XEXP (XEXP (dest, 0), 1)) != CONST_INT) if (GET_CODE (XEXP (XEXP (dest, 0), 1)) != CONST_INT)
abort (); abort ();
offset = INTVAL (XEXP (XEXP (dest, 0), 1)); offset = INTVAL (XEXP (XEXP (dest, 0), 1));
if (GET_CODE (XEXP (dest, 0)) == MINUS) if (GET_CODE (XEXP (dest, 0)) == MINUS)
offset = -offset; 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 (); abort ();
offset -= cfa_store.offset;
break; break;
/* Rule 13 */ /* Rule 13 */
/* Without an offset. */ /* Without an offset. */
case REG: 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 (); 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; break;
default: default:
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment