arm.c: Include "debug.h".

* config/arm/arm.c: Include "debug.h".
	(thumb_pushpop): Take two new arguments.  Add some commentary.
	Output frame information when pushing.
	(thumb_exit, thumb_unexpanded_epilogue): Update calls to
	thumb_pushpop.
	(thumb_output_function_prologue): Likewise.  Accumulate a CFA
	offset, and pass it to thumb_pushpop.  Output CFI information.
	(thumb_expand_prologue): Add some frame-related markers and notes.

From-SVN: r76362
This commit is contained in:
Daniel Jacobowitz 2004-01-22 17:00:56 +00:00 committed by Daniel Jacobowitz
parent 0067d1217b
commit 980e61bb2e
2 changed files with 115 additions and 22 deletions

View File

@ -1,3 +1,14 @@
2004-01-22 Daniel Jacobowitz <drow@mvista.com>
* config/arm/arm.c: Include "debug.h".
(thumb_pushpop): Take two new arguments. Add some commentary.
Output frame information when pushing.
(thumb_exit, thumb_unexpanded_epilogue): Update calls to
thumb_pushpop.
(thumb_output_function_prologue): Likewise. Accumulate a CFA
offset, and pass it to thumb_pushpop. Output CFI information.
(thumb_expand_prologue): Add some frame-related markers and notes.
2004-01-22 Ulrich Weigand <uweigand@de.ibm.com>
* config/s390/s390.c (s390_frame_info): Allow large frame sizes

View File

@ -50,6 +50,7 @@
#include "tm_p.h"
#include "target.h"
#include "target-def.h"
#include "debug.h"
/* Forward definitions of types. */
typedef struct minipool_node Mnode;
@ -85,7 +86,7 @@ static struct machine_function *arm_init_machine_status (void);
static int number_of_first_bit_set (int);
static void replace_symbols_in_block (tree, rtx, rtx);
static void thumb_exit (FILE *, int, rtx);
static void thumb_pushpop (FILE *, int, int);
static void thumb_pushpop (FILE *, int, int, int *, int);
static rtx is_jump_table (rtx);
static HOST_WIDE_INT get_jump_table_size (rtx);
static Mnode *move_minipool_fix_forward_ref (Mnode *, Mnode *, HOST_WIDE_INT);
@ -11562,7 +11563,8 @@ thumb_exit (FILE *f, int reg_containing_return_addr, rtx eh_ofs)
}
/* Pop as many registers as we can. */
thumb_pushpop (f, regs_available_for_popping, FALSE);
thumb_pushpop (f, regs_available_for_popping, FALSE, NULL,
regs_available_for_popping);
/* Process the registers we popped. */
if (reg_containing_return_addr == -1)
@ -11643,7 +11645,8 @@ thumb_exit (FILE *f, int reg_containing_return_addr, rtx eh_ofs)
int popped_into;
int move_to;
thumb_pushpop (f, regs_available_for_popping, FALSE);
thumb_pushpop (f, regs_available_for_popping, FALSE, NULL,
regs_available_for_popping);
/* We have popped either FP or SP.
Move whichever one it is into the correct register. */
@ -11663,7 +11666,8 @@ thumb_exit (FILE *f, int reg_containing_return_addr, rtx eh_ofs)
{
int popped_into;
thumb_pushpop (f, regs_available_for_popping, FALSE);
thumb_pushpop (f, regs_available_for_popping, FALSE, NULL,
regs_available_for_popping);
popped_into = number_of_first_bit_set (regs_available_for_popping);
@ -11693,12 +11697,20 @@ thumb_exit (FILE *f, int reg_containing_return_addr, rtx eh_ofs)
asm_fprintf (f, "\tbx\t%r\n", reg_containing_return_addr);
}
/* Emit code to push or pop registers to or from the stack. */
/* Emit code to push or pop registers to or from the stack. F is the
assembly file. MASK is the registers to push or pop. PUSH is
non-zero if we should push, and zero if we should pop. For debugging
output, if pushing, adjust CFA_OFFSET by the amount of space added
to the stack. REAL_REGS should have the same number of bits set as
MASK, and will be used instead (in the same order) to describe which
registers were saved - this is used to mark the save slots when we
push high registers after moving them to low registers. */
static void
thumb_pushpop (FILE *f, int mask, int push)
thumb_pushpop (FILE *f, int mask, int push, int *cfa_offset, int real_regs)
{
int regno;
int lo_mask = mask & 0xFF;
int pushed_words = 0;
if (lo_mask == 0 && !push && (mask & (1 << 15)))
{
@ -11719,6 +11731,8 @@ thumb_pushpop (FILE *f, int mask, int push)
if ((lo_mask & ~1) != 0)
fprintf (f, ", ");
pushed_words++;
}
}
@ -11729,6 +11743,8 @@ thumb_pushpop (FILE *f, int mask, int push)
fprintf (f, ", ");
asm_fprintf (f, "%r", LR_REGNUM);
pushed_words++;
}
else if (!push && (mask & (1 << PC_REGNUM)))
{
@ -11753,6 +11769,23 @@ thumb_pushpop (FILE *f, int mask, int push)
}
fprintf (f, "}\n");
if (push && pushed_words && dwarf2out_do_frame ())
{
char *l = dwarf2out_cfi_label ();
int pushed_mask = real_regs;
*cfa_offset += pushed_words * 4;
dwarf2out_def_cfa (l, SP_REGNUM, *cfa_offset);
pushed_words = 0;
pushed_mask = real_regs;
for (regno = 0; regno <= 14; regno++, pushed_mask >>= 1)
{
if (pushed_mask & 1)
dwarf2out_reg_save (l, regno, 4 * pushed_words++ - *cfa_offset);
}
}
}
void
@ -11951,7 +11984,7 @@ thumb_unexpanded_epilogue (void)
mask &= (2 << regno) - 1; /* A noop if regno == 8 */
/* Pop the values into the low register(s). */
thumb_pushpop (asm_out_file, mask, 0);
thumb_pushpop (asm_out_file, mask, 0, NULL, mask);
/* Move the value(s) into the high registers. */
for (regno = 0; regno <= LAST_LO_REGNUM; regno++)
@ -11993,7 +12026,8 @@ thumb_unexpanded_epilogue (void)
structure was created which includes an adjusted stack
pointer, so just pop everything. */
if (live_regs_mask)
thumb_pushpop (asm_out_file, live_regs_mask, FALSE);
thumb_pushpop (asm_out_file, live_regs_mask, FALSE, NULL,
live_regs_mask);
if (eh_ofs)
thumb_exit (asm_out_file, 2, eh_ofs);
@ -12013,11 +12047,13 @@ thumb_unexpanded_epilogue (void)
live_regs_mask &= ~(1 << PC_REGNUM);
if (live_regs_mask)
thumb_pushpop (asm_out_file, live_regs_mask, FALSE);
thumb_pushpop (asm_out_file, live_regs_mask, FALSE, NULL,
live_regs_mask);
if (had_to_push_lr)
/* Get the return address into a temporary register. */
thumb_pushpop (asm_out_file, 1 << LAST_ARG_REGNUM, 0);
thumb_pushpop (asm_out_file, 1 << LAST_ARG_REGNUM, 0, NULL,
1 << LAST_ARG_REGNUM);
/* Remove the argument registers that were pushed onto the stack. */
asm_fprintf (asm_out_file, "\tadd\t%r, %r, #%d\n",
@ -12163,6 +12199,8 @@ thumb_get_frame_size (void)
void
thumb_expand_prologue (void)
{
rtx insn, dwarf;
HOST_WIDE_INT amount = (thumb_get_frame_size ()
+ current_function_outgoing_args_size);
unsigned long func_type;
@ -12180,15 +12218,21 @@ thumb_expand_prologue (void)
}
if (frame_pointer_needed)
emit_insn (gen_movsi (hard_frame_pointer_rtx, stack_pointer_rtx));
{
insn = emit_insn (gen_movsi (hard_frame_pointer_rtx, stack_pointer_rtx));
RTX_FRAME_RELATED_P (insn) = 1;
}
if (amount)
{
amount = ROUND_UP_WORD (amount);
if (amount < 512)
emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx,
GEN_INT (- amount)));
{
insn = emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx,
GEN_INT (- amount)));
RTX_FRAME_RELATED_P (insn) = 1;
}
else
{
int regno;
@ -12228,8 +12272,16 @@ thumb_expand_prologue (void)
/* Decrement the stack. */
emit_insn (gen_movsi (reg, GEN_INT (- amount)));
emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx,
reg));
insn = emit_insn (gen_addsi3 (stack_pointer_rtx,
stack_pointer_rtx, reg));
RTX_FRAME_RELATED_P (insn) = 1;
dwarf = gen_rtx_SET (SImode, stack_pointer_rtx,
plus_constant (stack_pointer_rtx,
GEN_INT (- amount)));
RTX_FRAME_RELATED_P (dwarf) = 1;
REG_NOTES (insn)
= gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR, dwarf,
REG_NOTES (insn));
/* Restore the low register's original value. */
emit_insn (gen_movsi (reg, spare));
@ -12245,8 +12297,17 @@ thumb_expand_prologue (void)
reg = gen_rtx (REG, SImode, regno);
emit_insn (gen_movsi (reg, GEN_INT (- amount)));
emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx,
reg));
insn = emit_insn (gen_addsi3 (stack_pointer_rtx,
stack_pointer_rtx, reg));
RTX_FRAME_RELATED_P (insn) = 1;
dwarf = gen_rtx_SET (SImode, stack_pointer_rtx,
plus_constant (stack_pointer_rtx,
GEN_INT (- amount)));
RTX_FRAME_RELATED_P (dwarf) = 1;
REG_NOTES (insn)
= gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR, dwarf,
REG_NOTES (insn));
}
}
}
@ -12307,6 +12368,7 @@ thumb_output_function_prologue (FILE *f, HOST_WIDE_INT size ATTRIBUTE_UNUSED)
{
int live_regs_mask = 0;
int high_regs_pushed = 0;
int cfa_offset = 0;
int regno;
if (IS_NAKED (arm_current_func_type ()))
@ -12369,6 +12431,16 @@ thumb_output_function_prologue (FILE *f, HOST_WIDE_INT size ATTRIBUTE_UNUSED)
asm_fprintf (f, "\tsub\t%r, %r, #%d\n",
SP_REGNUM, SP_REGNUM,
current_function_pretend_args_size);
/* We don't need to record the stores for unwinding (would it
help the debugger any if we did?), but record the change in
the stack pointer. */
if (dwarf2out_do_frame ())
{
char *l = dwarf2out_cfi_label ();
cfa_offset = cfa_offset + current_function_pretend_args_size;
dwarf2out_def_cfa (l, SP_REGNUM, cfa_offset);
}
}
for (regno = 0; regno <= LAST_LO_REGNUM; regno++)
@ -12424,9 +12496,16 @@ thumb_output_function_prologue (FILE *f, HOST_WIDE_INT size ATTRIBUTE_UNUSED)
asm_fprintf
(f, "\tsub\t%r, %r, #16\t%@ Create stack backtrace structure\n",
SP_REGNUM, SP_REGNUM);
if (dwarf2out_do_frame ())
{
char *l = dwarf2out_cfi_label ();
cfa_offset = cfa_offset + 16;
dwarf2out_def_cfa (l, SP_REGNUM, cfa_offset);
}
if (live_regs_mask)
thumb_pushpop (f, live_regs_mask, 1);
thumb_pushpop (f, live_regs_mask, 1, &cfa_offset, live_regs_mask);
for (offset = 0, wr = 1 << 15; wr != 0; wr >>= 1)
if (wr & live_regs_mask)
@ -12470,7 +12549,7 @@ thumb_output_function_prologue (FILE *f, HOST_WIDE_INT size ATTRIBUTE_UNUSED)
ARM_HARD_FRAME_POINTER_REGNUM, work_register);
}
else if (live_regs_mask)
thumb_pushpop (f, live_regs_mask, 1);
thumb_pushpop (f, live_regs_mask, 1, &cfa_offset, live_regs_mask);
for (regno = 8; regno < 13; regno++)
if (THUMB_REG_PUSHED_P (regno))
@ -12498,6 +12577,8 @@ thumb_output_function_prologue (FILE *f, HOST_WIDE_INT size ATTRIBUTE_UNUSED)
while (high_regs_pushed > 0)
{
int real_regs_mask = 0;
for (regno = LAST_LO_REGNUM; regno >= 0; regno--)
{
if (mask & (1 << regno))
@ -12505,6 +12586,7 @@ thumb_output_function_prologue (FILE *f, HOST_WIDE_INT size ATTRIBUTE_UNUSED)
asm_fprintf (f, "\tmov\t%r, %r\n", regno, next_hi_reg);
high_regs_pushed--;
real_regs_mask |= (1 << next_hi_reg);
if (high_regs_pushed)
{
@ -12520,8 +12602,8 @@ thumb_output_function_prologue (FILE *f, HOST_WIDE_INT size ATTRIBUTE_UNUSED)
}
}
}
thumb_pushpop (f, mask, 1);
thumb_pushpop (f, mask, 1, &cfa_offset, real_regs_mask);
}
if (pushable_regs == 0