* frv-tdep.c (skip_prologue_using_sal): New function. Taken verbatim

from mips-tdep.c.
	(frv_analyze_prologue): Rework to account for intermixed prologue /
	body instructions.
This commit is contained in:
Kevin Buettner 2003-12-19 00:34:26 +00:00
parent a53cf7226d
commit d40fcd7bc1
2 changed files with 189 additions and 39 deletions

View File

@ -1,3 +1,10 @@
2003-12-18 Kevin Buettner <kevinb@redhat.com>
* frv-tdep.c (skip_prologue_using_sal): New function. Taken verbatim
from mips-tdep.c.
(frv_analyze_prologue): Rework to account for intermixed prologue /
body instructions.
2003-12-18 Michael Chastain <mec.gnu@mindspring.com>
* hppa-tdep.c (hppa_gdbarch_init): Set sizeof(long_double) to 128.

View File

@ -417,6 +417,61 @@ is_argument_reg (int reg)
return (8 <= reg && reg <= 13);
}
/* Given PC at the function's start address, attempt to find the
prologue end using SAL information. Return zero if the skip fails.
A non-optimized prologue traditionally has one SAL for the function
and a second for the function body. A single line function has
them both pointing at the same line.
An optimized prologue is similar but the prologue may contain
instructions (SALs) from the instruction body. Need to skip those
while not getting into the function body.
The functions end point and an increasing SAL line are used as
indicators of the prologue's endpoint.
This code is based on the function refine_prologue_limit (versions
found in both ia64 and ppc). */
static CORE_ADDR
skip_prologue_using_sal (CORE_ADDR func_addr)
{
struct symtab_and_line prologue_sal;
CORE_ADDR start_pc;
CORE_ADDR end_pc;
/* Get an initial range for the function. */
find_pc_partial_function (func_addr, NULL, &start_pc, &end_pc);
start_pc += FUNCTION_START_OFFSET;
prologue_sal = find_pc_line (start_pc, 0);
if (prologue_sal.line != 0)
{
while (prologue_sal.end < end_pc)
{
struct symtab_and_line sal;
sal = find_pc_line (prologue_sal.end, 0);
if (sal.line == 0)
break;
/* Assume that a consecutive SAL for the same (or larger)
line mark the prologue -> body transition. */
if (sal.line >= prologue_sal.line)
break;
/* The case in which compiler's optimizer/scheduler has
moved instructions into the prologue. We look ahead in
the function looking for address ranges whose
corresponding line number is less the first one that we
found for the function. This is more conservative then
refine_prologue_limit which scans a large number of SALs
looking for any in the prologue */
prologue_sal = sal;
}
}
return prologue_sal.end;
}
/* Scan an FR-V prologue, starting at PC, until frame->PC.
If FRAME is non-zero, fill in its saved_regs with appropriate addresses.
@ -474,26 +529,111 @@ frv_analyze_prologue (CORE_ADDR pc, struct frame_info *next_frame,
char gr_saved[64];
int gr_sp_offset[64];
/* The address of the most recently scanned prologue instruction. */
CORE_ADDR last_prologue_pc;
/* The address of the next instruction. */
CORE_ADDR next_pc;
/* The upper bound to of the pc values to scan. */
CORE_ADDR lim_pc;
memset (gr_saved, 0, sizeof (gr_saved));
while (! next_frame || pc < frame_pc_unwind (next_frame))
last_prologue_pc = pc;
/* Try to compute an upper limit (on how far to scan) based on the
line number info. */
lim_pc = skip_prologue_using_sal (pc);
/* If there's no line number info, lim_pc will be 0. In that case,
set the limit to be 100 instructions away from pc. Hopefully, this
will be far enough away to account for the entire prologue. Don't
worry about overshooting the end of the function. The scan loop
below contains some checks to avoid scanning unreasonably far. */
if (lim_pc == 0)
lim_pc = pc + 400;
/* If we have a frame, we don't want to scan past the frame's pc. This
will catch those cases where the pc is in the prologue. */
if (next_frame)
{
CORE_ADDR frame_pc = frame_pc_unwind (next_frame);
if (frame_pc < lim_pc)
lim_pc = frame_pc;
}
/* Scan the prologue. */
while (pc < lim_pc)
{
LONGEST op = read_memory_integer (pc, 4);
next_pc = pc + 4;
/* The tests in this chain of ifs should be in order of
decreasing selectivity, so that more particular patterns get
to fire before less particular patterns. */
/* Some sort of control transfer instruction: stop scanning prologue.
Integer Conditional Branch:
X XXXX XX 0000110 XX XXXXXXXXXXXXXXXX
Floating-point / media Conditional Branch:
X XXXX XX 0000111 XX XXXXXXXXXXXXXXXX
LCR Conditional Branch to LR
X XXXX XX 0001110 XX XX 001 X XXXXXXXXXX
Integer conditional Branches to LR
X XXXX XX 0001110 XX XX 010 X XXXXXXXXXX
X XXXX XX 0001110 XX XX 011 X XXXXXXXXXX
Floating-point/Media Branches to LR
X XXXX XX 0001110 XX XX 110 X XXXXXXXXXX
X XXXX XX 0001110 XX XX 111 X XXXXXXXXXX
Jump and Link
X XXXXX X 0001100 XXXXXX XXXXXX XXXXXX
X XXXXX X 0001101 XXXXXX XXXXXX XXXXXX
Call
X XXXXXX 0001111 XXXXXXXXXXXXXXXXXX
Return from Trap
X XXXXX X 0000101 XXXXXX XXXXXX XXXXXX
Integer Conditional Trap
X XXXX XX 0000100 XXXXXX XXXX 00 XXXXXX
X XXXX XX 0011100 XXXXXX XXXXXXXXXXXX
Floating-point /media Conditional Trap
X XXXX XX 0000100 XXXXXX XXXX 01 XXXXXX
X XXXX XX 0011101 XXXXXX XXXXXXXXXXXX
Break
X XXXX XX 0000100 XXXXXX XXXX 11 XXXXXX
Media Trap
X XXXX XX 0000100 XXXXXX XXXX 10 XXXXXX */
if ((op & 0x01d80000) == 0x00180000 /* Conditional branches and Call */
|| (op & 0x01f80000) == 0x00300000 /* Jump and Link */
|| (op & 0x01f80000) == 0x00100000 /* Return from Trap, Trap */
|| (op & 0x01f80000) == 0x00700000) /* Trap immediate */
{
/* Stop scanning; not in prologue any longer. */
break;
}
/* Loading something from memory into fp probably means that
we're in the epilogue. Stop scanning the prologue.
ld @(GRi, GRk), fp
X 000010 0000010 XXXXXX 000100 XXXXXX
ldi @(GRi, d12), fp
X 000010 0110010 XXXXXX XXXXXXXXXXXX */
else if ((op & 0x7ffc0fc0) == 0x04080100
|| (op & 0x7ffc0000) == 0x04c80000)
{
break;
}
/* Setting the FP from the SP:
ori sp, 0, fp
P 000010 0100010 000001 000000000000 = 0x04881000
0 111111 1111111 111111 111111111111 = 0x7fffffff
. . . . . . . .
We treat this as part of the prologue. */
if ((op & 0x7fffffff) == 0x04881000)
else if ((op & 0x7fffffff) == 0x04881000)
{
fp_set = 1;
fp_offset = 0;
last_prologue_pc = next_pc;
}
/* Move the link register to the scratch register grJ, before saving:
@ -508,11 +648,10 @@ frv_analyze_prologue (CORE_ADDR pc, struct frame_info *next_frame,
/* If we're moving it to a scratch register, that's fine. */
if (is_caller_saves_reg (gr_j))
lr_save_reg = gr_j;
/* Otherwise it's not a prologue instruction that we
recognize. */
else
break;
{
lr_save_reg = gr_j;
last_prologue_pc = next_pc;
}
}
/* To save multiple callee-saves registers on the stack, at
@ -550,10 +689,8 @@ frv_analyze_prologue (CORE_ADDR pc, struct frame_info *next_frame,
gr_saved[gr_k + i] = 1;
gr_sp_offset[gr_k + i] = 4 * i;
}
last_prologue_pc = next_pc;
}
else
/* It's not a prologue instruction. */
break;
}
/* Adjusting the stack pointer. (The stack pointer is GR1.)
@ -564,11 +701,22 @@ frv_analyze_prologue (CORE_ADDR pc, struct frame_info *next_frame,
We treat this as part of the prologue. */
else if ((op & 0x7ffff000) == 0x02401000)
{
/* Sign-extend the twelve-bit field.
(Isn't there a better way to do this?) */
int s = (((op & 0xfff) - 0x800) & 0xfff) - 0x800;
if (framesize == 0)
{
/* Sign-extend the twelve-bit field.
(Isn't there a better way to do this?) */
int s = (((op & 0xfff) - 0x800) & 0xfff) - 0x800;
framesize -= s;
framesize -= s;
last_prologue_pc = pc;
}
else
{
/* If the prologue is being adjusted again, we've
likely gone too far; i.e. we're probably in the
epilogue. */
break;
}
}
/* Setting the FP to a constant distance from the SP:
@ -584,6 +732,7 @@ frv_analyze_prologue (CORE_ADDR pc, struct frame_info *next_frame,
int s = (((op & 0xfff) - 0x800) & 0xfff) - 0x800;
fp_set = 1;
fp_offset = s;
last_prologue_pc = pc;
}
/* To spill an argument register to a scratch register:
@ -602,10 +751,10 @@ frv_analyze_prologue (CORE_ADDR pc, struct frame_info *next_frame,
{
int gr_i = ((op >> 12) & 0x3f);
/* If the source isn't an arg register, then this isn't a
prologue instruction. */
if (! is_argument_reg (gr_i))
break;
/* Make sure that the source is an arg register; if it is, we'll
treat it as a prologue instruction. */
if (is_argument_reg (gr_i))
last_prologue_pc = next_pc;
}
/* To spill 16-bit values to the stack:
@ -625,8 +774,10 @@ frv_analyze_prologue (CORE_ADDR pc, struct frame_info *next_frame,
{
int gr_k = ((op >> 25) & 0x3f);
if (! is_argument_reg (gr_k))
break; /* Source isn't an arg register. */
/* Make sure that GRk is really an argument register; treat
it as a prologue instruction if so. */
if (is_argument_reg (gr_k))
last_prologue_pc = next_pc;
}
/* To save multiple callee-saves register on the stack, at a
@ -667,10 +818,8 @@ frv_analyze_prologue (CORE_ADDR pc, struct frame_info *next_frame,
gr_saved[gr_k + i] = 1;
gr_sp_offset[gr_k + i] = s + (4 * i);
}
last_prologue_pc = next_pc;
}
else
/* It's not a prologue instruction. */
break;
}
/* Storing any kind of integer register at any constant offset
@ -704,13 +853,16 @@ frv_analyze_prologue (CORE_ADDR pc, struct frame_info *next_frame,
/* If the address isn't relative to the SP or FP, it's not a
prologue instruction. */
if (gr_i != sp_regnum && gr_i != fp_regnum)
break;
{
/* Do nothing; not a prologue instruction. */
}
/* Saving the old FP in the new frame (relative to the SP). */
if (gr_k == fp_regnum && gr_i == sp_regnum)
else if (gr_k == fp_regnum && gr_i == sp_regnum)
{
gr_saved[fp_regnum] = 1;
gr_sp_offset[fp_regnum] = offset;
last_prologue_pc = next_pc;
}
/* Saving callee-saves register(s) on the stack, relative to
@ -723,6 +875,7 @@ frv_analyze_prologue (CORE_ADDR pc, struct frame_info *next_frame,
gr_sp_offset[gr_k] = offset;
else
gr_sp_offset[gr_k] = offset + fp_offset;
last_prologue_pc = next_pc;
}
/* Saving the scratch register holding the return address. */
@ -734,24 +887,14 @@ frv_analyze_prologue (CORE_ADDR pc, struct frame_info *next_frame,
lr_sp_offset = offset;
else
lr_sp_offset = offset + fp_offset;
last_prologue_pc = next_pc;
}
/* Spilling int-sized arguments to the stack. */
else if (is_argument_reg (gr_k))
;
/* It's not a store instruction we recognize, so this must
be the end of the prologue. */
else
break;
last_prologue_pc = next_pc;
}
/* It's not any instruction we recognize, so this must be the end
of the prologue. */
else
break;
pc += 4;
pc = next_pc;
}
if (next_frame && info)
@ -790,7 +933,7 @@ frv_analyze_prologue (CORE_ADDR pc, struct frame_info *next_frame,
trad_frame_set_value (info->saved_regs, sp_regnum, info->prev_sp);
}
return pc;
return last_prologue_pc;
}