Better support V.4 calling sequences.

This commit is contained in:
Michael Meissner
1995-07-27 03:50:05 +00:00
parent ddb97850d0
commit 068c9fd63f
3 changed files with 267 additions and 266 deletions

View File

@ -1,3 +1,27 @@
Wed Jul 26 23:33:34 1995 Michael Meissner <meissner@cygnus.com>
* config/rs6000/tm-rs6000.h (rs6000_framedata): Add offsets the
gprs, fprs, lr, and cr is stored at.
(FRAME_FIND_SAVED_REGS): Use new fields in rs6000_framedata.
(function_frame_info): Delete declaration.
(SKIP_PROLOGUE): Skip_prologue is now passed a rs6000_framedata
structure to fill in.
(FRAMELESS_FUNCTION_INVOCATION): Function now longer takes a
second argument.
(FRAME_SAVED_PC): Call frame_saved_pc.
* rs6000-tdep.c (skip_prologue): Recognize V.4 prologues as well
as AIX style. Fill in rs6000_framedata structure. Remember where
the gprs, fprs, cr, and lr are saved.
(pop_frame): Use skip_prologue, not function_frame_info, and use
new rs6000_framedata fields.
(function_frame_info): Function deleted.
(frameless_function_invocation): Separate frame_saved_pc support
to new function. Recognize V.4 frames.
(frame_saved_pc): New function.
(frame_get_cache_fsr): Use skip_prologue, not function_frame_info.
(frame_initial_stack_address): Ditto.
Wed Jul 26 01:00:37 1995 Jeff Law (law@snake.cs.utah.edu)
* remote.c: Add documentation for extended protocol operations

View File

@ -56,7 +56,7 @@ struct fp_status {
};
/* To be used by function_frame_info. */
/* To be used by skip_prologue. */
struct rs6000_framedata {
int offset; /* # of bytes in gpr's and fpr's are saved */
@ -65,11 +65,12 @@ struct rs6000_framedata {
int alloca_reg; /* alloca register number (frame ptr) */
char frameless; /* true if frameless functions. */
char nosavedpc; /* true if pc not saved. */
int gpr_offset; /* offset of saved gprs */
int fpr_offset; /* offset of saved fprs */
int lr_offset; /* offset of saved lr */
int cr_offset; /* offset of saved cr */
};
void
function_frame_info PARAMS ((CORE_ADDR, struct rs6000_framedata *));
/* Define the byte order of the machine. */
#define TARGET_BYTE_ORDER BIG_ENDIAN
@ -87,7 +88,14 @@ function_frame_info PARAMS ((CORE_ADDR, struct rs6000_framedata *));
/* Advance PC across any function entry prologue instructions
to reach some "real" code. */
#define SKIP_PROLOGUE(pc) pc = skip_prologue (pc)
#define SKIP_PROLOGUE(pc) \
do { \
struct rs6000_framedata _frame; \
pc = skip_prologue (pc, &_frame); \
} while (0)
extern CORE_ADDR skip_prologue PARAMS((CORE_ADDR, struct rs6000_framedata *));
/* If PC is in some function-call trampoline code, return the PC
where the function itself actually starts. If not, return NULL. */
@ -386,7 +394,9 @@ CORE_ADDR rs6000_frame_chain PARAMS ((struct frame_info *));
does not, FRAMELESS is set to 1, else 0. */
#define FRAMELESS_FUNCTION_INVOCATION(FI, FRAMELESS) \
FRAMELESS = frameless_function_invocation (FI, 0)
FRAMELESS = frameless_function_invocation (FI)
extern int frameless_function_invocation PARAMS((struct frame_info *));
/* Functions calling alloca() change the value of the stack pointer. We
need to use initial stack pointer (which is saved in r31 by gcc) in
@ -424,17 +434,10 @@ CORE_ADDR rs6000_frame_chain PARAMS ((struct frame_info *));
#define SIG_FRAME_PC_OFFSET 96
#define SIG_FRAME_FP_OFFSET 284
/* Frameless function invocation in IBM RS/6000 is sometimes
half-done. It perfectly sets up a new frame, e.g. a new frame (in
fact stack) pointer, etc, but it doesn't save the %pc. We call
frameless_function_invocation to tell us how to get the %pc. */
/* Return saved PC from a frame */
#define FRAME_SAVED_PC(FRAME) frame_saved_pc (FRAME)
#define FRAME_SAVED_PC(FRAME) \
(frameless_function_invocation (FRAME, 1) \
? SAVED_PC_AFTER_CALL (FRAME) \
: (FRAME)->signal_handler_caller \
? read_memory_integer ((FRAME)->frame + SIG_FRAME_PC_OFFSET, 4) \
: read_memory_integer (rs6000_frame_chain (FRAME) + 8, 4))
extern unsigned long frame_saved_pc PARAMS ((struct frame_info *));
#define FRAME_ARGS_ADDRESS(FI) \
(((struct frame_info*)(FI))->initial_sp ? \
@ -471,40 +474,57 @@ CORE_ADDR rs6000_frame_chain PARAMS ((struct frame_info *));
CORE_ADDR frame_addr, func_start; \
struct rs6000_framedata fdata; \
\
/* find the start of the function and collect info about its frame. */\
/* find the start of the function and collect info about its frame. */ \
\
func_start = get_pc_function_start ((FRAME_INFO)->pc) + FUNCTION_START_OFFSET; \
function_frame_info (func_start, &fdata); \
memset (&(FRAME_SAVED_REGS), '\0', sizeof (FRAME_SAVED_REGS)); \
(void) skip_prologue (func_start, &fdata); \
memset (&(FRAME_SAVED_REGS), '\0', sizeof (FRAME_SAVED_REGS)); \
\
/* if there were any saved registers, figure out parent's stack pointer. */ \
frame_addr = 0; \
/* the following is true only if the frame doesn't have a call to alloca(), \
FIXME. */ \
if (fdata.saved_fpr >= 0 || fdata.saved_gpr >= 0) { \
if ((FRAME_INFO)->prev && (FRAME_INFO)->prev->frame) \
frame_addr = (FRAME_INFO)->prev->frame; \
else \
frame_addr = read_memory_integer ((FRAME_INFO)->frame, 4); \
if (fdata.saved_fpr == 0 && fdata.saved_gpr == 0 && \
fdata.lr_offset == 0 && fdata.cr_offset == 0) { \
frame_addr = 0; \
\
} else if ((FRAME_INFO)->prev && (FRAME_INFO)->prev->frame) { \
frame_addr = (FRAME_INFO)->prev->frame; \
\
} else { \
frame_addr = read_memory_integer ((FRAME_INFO)->frame, 4); \
} \
\
/* if != -1, fdata.saved_fpr is the smallest number of saved_fpr. All fpr's \
from saved_fpr to fp31 are saved right underneath caller stack pointer, \
starting from fp31 first. */ \
\
/* if != -1, fdata.saved_fpr is the smallest number of saved_fpr. All \
fpr's from saved_fpr to f31 are saved. */ \
if (fdata.saved_fpr >= 0) { \
for (ii=31; ii >= fdata.saved_fpr; --ii) \
(FRAME_SAVED_REGS).regs [FP0_REGNUM + ii] = frame_addr - ((32 - ii) * 8); \
frame_addr -= (32 - fdata.saved_fpr) * 8; \
int fpr_offset = frame_addr + fdata.fpr_offset; \
for (ii = fdata.saved_fpr; ii < 32; ii++) { \
(FRAME_SAVED_REGS).regs [FP0_REGNUM + ii] = fpr_offset; \
fpr_offset += 8; \
} \
} \
\
/* if != -1, fdata.saved_gpr is the smallest number of saved_gpr. All gpr's \
from saved_gpr to gpr31 are saved right under saved fprs, starting \
from r31 first. */ \
/* if != -1, fdata.saved_gpr is the smallest number of saved_gpr. All \
gpr's from saved_gpr to r31 are saved. */ \
if (fdata.saved_gpr >= 0) { \
int gpr_offset = frame_addr + fdata.gpr_offset; \
for (ii = fdata.saved_gpr; ii < 32; ii++) { \
(FRAME_SAVED_REGS).regs [ii] = gpr_offset; \
gpr_offset += 4; \
} \
} \
\
if (fdata.saved_gpr >= 0) \
for (ii=31; ii >= fdata.saved_gpr; --ii) \
(FRAME_SAVED_REGS).regs [ii] = frame_addr - ((32 - ii) * 4); \
/* If != 0, fdata.cr_offset is the offset from the frame that holds \
the CR */ \
if (fdata.cr_offset != 0) { \
(FRAME_SAVED_REGS).regs [CR_REGNUM] = frame_addr + fdata.cr_offset; \
} \
\
/* If != 0, fdata.cr_offset is the offset from the frame that holds \
the LR */ \
if (fdata.lr_offset != 0) { \
(FRAME_SAVED_REGS).regs [LR_REGNUM] = frame_addr + fdata.lr_offset; \
} \
}

View File

@ -177,104 +177,181 @@ single_step (signal)
}
/* return pc value after skipping a function prologue. */
/* return pc value after skipping a function prologue and also return
information about a function frame.
skip_prologue (pc)
CORE_ADDR pc;
in struct rs6000_frameinfo fdata:
- frameless is TRUE, if function does not have a frame.
- nosavedpc is TRUE, if function does not save %pc value in its frame.
- offset is the number of bytes used in the frame to save registers.
- saved_gpr is the number of the first saved gpr.
- saved_fpr is the number of the first saved fpr.
- alloca_reg is the number of the register used for alloca() handling.
Otherwise -1.
- gpr_offset is the offset of the saved gprs
- fpr_offset is the offset of the saved fprs
- lr_offset is the offset of the saved lr
- cr_offset is the offset of the saved cr
*/
#define SIGNED_SHORT(x) \
((sizeof (short) == 2) \
? ((int)(short)(x)) \
: ((int)((((x) & 0xffff) ^ 0x8000) - 0x8000)))
#define GET_SRC_REG(x) (((x) >> 21) & 0x1f)
CORE_ADDR
skip_prologue (pc, fdata)
CORE_ADDR pc;
struct rs6000_framedata *fdata;
{
CORE_ADDR orig_pc = pc;
char buf[4];
unsigned int tmp;
unsigned long op;
int lr_reg = 0;
int cr_reg = 0;
int reg;
static struct rs6000_framedata zero_frame;
*fdata = zero_frame;
fdata->saved_gpr = -1;
fdata->saved_fpr = -1;
fdata->alloca_reg = -1;
fdata->frameless = 1;
fdata->nosavedpc = 1;
if (target_read_memory (pc, buf, 4))
return pc; /* Can't access it -- assume no prologue. */
op = extract_unsigned_integer (buf, 4);
/* Assume that subsequent fetches can fail with low probability. */
pc -= 4;
for (;;)
{
pc += 4;
op = read_memory_integer (pc, 4);
if (op == 0x7c0802a6) { /* mflr r0 */
pc += 4;
op = read_memory_integer (pc, 4);
}
if ((op & 0xfc1fffff) == 0x7c0802a6) { /* mflr Rx */
lr_reg = (op & 0x03e00000) | 0x90010000;
continue;
if ((op & 0xfc00003e) == 0x7c000026) { /* mfcr Rx */
pc += 4;
op = read_memory_integer (pc, 4);
}
} else if ((op & 0xfc1fffff) == 0x7c000026) { /* mfcr Rx */
cr_reg = (op & 0x03e00000) | 0x90010000;
continue;
if ((op & 0xfc000000) == 0x48000000) { /* bl foo, to save fprs??? */
pc += 4;
} else if ((op & 0xfc1f0000) == 0xd8010000) { /* stfd Rx,NUM(r1) */
reg = GET_SRC_REG (op);
if (fdata->saved_fpr == -1 || fdata->saved_fpr > reg) {
fdata->saved_fpr = reg;
fdata->fpr_offset = SIGNED_SHORT (op);
}
continue;
} else if (((op & 0xfc1f0000) == 0xbc010000) || /* stm Rx, NUM(r1) */
((op & 0xfc1f0000) == 0x90010000 && /* st rx,NUM(r1), rx >= r13 */
(op & 0x03e00000) >= 0x01a00000)) {
reg = GET_SRC_REG (op);
if (fdata->saved_gpr == -1 || fdata->saved_gpr > reg) {
fdata->saved_gpr = reg;
fdata->gpr_offset = SIGNED_SHORT (op);
}
continue;
} else if ((op & 0xffff0000) == 0x3c000000) { /* addis 0,0,NUM, used for >= 32k frames */
fdata->offset = (op & 0x0000ffff) << 16;
continue;
} else if ((op & 0xffff0000) == 0x60000000) { /* ori 0,0,NUM, 2nd half of >= 32k frames */
fdata->offset |= (op & 0x0000ffff);
continue;
} else if ((op & 0xffff0000) == lr_reg) { /* st Rx,NUM(r1) where Rx == lr */
fdata->lr_offset = SIGNED_SHORT (op);
fdata->nosavedpc = 0;
lr_reg = 0;
continue;
} else if ((op & 0xffff0000) == cr_reg) { /* st Rx,NUM(r1) where Rx == cr */
fdata->cr_offset = SIGNED_SHORT (op);
cr_reg = 0;
continue;
} else if ((op & 0xfc000000) == 0x48000000) { /* bl foo, to save fprs??? */
op = read_memory_integer (pc+4, 4);
/* At this point, make sure this is not a trampoline function
(a function that simply calls another functions, and nothing else).
If the next is not a nop, this branch was part of the function
prologue. */
if (op == 0x4def7b82 || op == 0) /* crorc 15, 15, 15 */
return pc; /* don't skip over this branch */
continue;
} else if ((op & 0xffff0000) == 0x94210000) { /* stu r1,NUM(r1) */
fdata->offset = - SIGNED_SHORT (op);
pc += 4;
op = read_memory_integer (pc, 4);
break;
} else if (op == 0x7c21016e) { /* stwux 1,1,0 */
pc += 4; /* offset set above */
op = read_memory_integer (pc, 4);
break;
} else {
break;
}
}
/* Skip -mreloctable (V.4/eabi) load up the toc case */
if (op == 0x48000005 && /* bl .+4 */
read_memory_integer (pc+4, 4) == 0x7fc802a6 && /* mflr r30 */
(read_memory_integer (pc+8, 4) & 0xffff) == 0x801e0000 && /* lwz 0,NUM(r30) */
read_memory_integer (pc+12, 4) == 0x7fc0f214) { /* add r30,r0,r30 */
pc += 16;
op = read_memory_integer (pc, 4);
/* At this point, make sure this is not a trampoline function
(a function that simply calls another functions, and nothing else).
If the next is not a nop, this branch was part of the function
prologue. */
if (op == 0x4def7b82 || /* crorc 15, 15, 15 */
op == 0x0)
return pc - 4; /* don't skip over this branch */
/* And -mminimal-toc code on V.4 */
} else if ((op & 0xffff0000) == 0x3fc00000 && /* addis 30,0,foo@ha */
/* addi 30,30,foo@l */
((read_memory_integer (pc+4, 4) & 0xffff0000) == 0x3bde0000)) {
pc += 8;
op = read_memory_integer (pc, 8);
}
if ((op & 0xfc1f0000) == 0xd8010000) { /* stfd Rx,NUM(r1) */
pc += 4; /* store floating register double */
op = read_memory_integer (pc, 4);
}
if ((op & 0xfc1f0000) == 0xbc010000) { /* stm Rx, NUM(r1) */
pc += 4;
op = read_memory_integer (pc, 4);
}
while ((op & 0xfc1f0000) == 0x90010000 && /* st rx,NUM(r1), rx >= r13 */
(op & 0x03e00000) >= 0x01a00000) {
pc += 4;
op = read_memory_integer (pc, 4);
}
if (op == 0x90010008) { /* st r0,8(r1) */
pc += 4;
op = read_memory_integer (pc, 4);
}
if (op == 0x91810004) { /* st r12,4(r1) */
pc += 4;
op = read_memory_integer (pc, 4);
}
if ((op & 0xffff0000) == 0x94210000) { /* stu r1,NUM(r1) */
pc += 4;
op = read_memory_integer (pc, 4);
}
while ((tmp = (op >> 22)) == 0x20f) { /* l r31, ... or */
pc += 4; /* l r30, ... */
while ((op >> 22) == 0x20f) { /* l r31, ... or */
pc += 4; /* l r30, ... */
op = read_memory_integer (pc, 4);
}
/* store parameters into stack */
while(
(op & 0xfc1f0000) == 0xd8010000 || /* stfd Rx,NUM(r1) */
(op & 0xfc1f0000) == 0x90010000 || /* st r?, NUM(r1) */
(op & 0xfc000000) == 0xfc000000 || /* frsp, fp?, .. */
(op & 0xd0000000) == 0xd0000000) /* stfs, fp?, .. */
{
pc += 4; /* store fpr double */
op = read_memory_integer (pc, 4);
}
(op & 0xfc1f0000) == 0x90010000 || /* st rx,NUM(r1) */
(op & 0xfc1f0000) == 0xd8010000 || /* stfd Rx,NUM(r1) */
(op & 0xfc1f0000) == 0xfc010000) { /* frsp, fp?,NUM(r1) */
pc += 4;
op = read_memory_integer (pc, 4);
}
if (op == 0x603f0000 /* oril r31, r1, 0x0 */
|| op == 0x7c3f0b78) { /* mr r31, r1 */
pc += 4; /* this happens if r31 is used as */
op = read_memory_integer (pc, 4); /* frame ptr. (gcc does that) */
/* Set up frame pointer */
if (op == 0x603f0000 /* oril r31, r1, 0x0 */
|| op == 0x7c3f0b78) { /* mr r31, r1 */
pc += 4; /* this happens if r31 is used as */
op = read_memory_integer (pc, 4); /* frame ptr. (gcc does that) */
tmp = 0;
while ((op >> 16) == (0x907f + tmp)) { /* st r3, NUM(r31) */
pc += 4; /* st r4, NUM(r31), ... */
/* store parameters into frame */
while (
(op & 0xfc1f0000) == 0x901f0000 || /* st rx,NUM(r1) */
(op & 0xfc1f0000) == 0xd81f0000 || /* stfd Rx,NUM(r1) */
(op & 0xfc1f0000) == 0xfc1f0000) { /* frsp, fp?,NUM(r1) */
pc += 4;
op = read_memory_integer (pc, 4);
tmp += 0x20;
}
}
#if 0
/* I have problems with skipping over __main() that I need to address
* sometime. Previously, I used to use misc_function_vector which
@ -302,6 +379,7 @@ CORE_ADDR pc;
}
#endif /* 0 */
fdata->frameless = (pc == orig_pc);
return pc;
}
@ -496,16 +574,16 @@ pop_frame ()
saved %pc value in the previous frame. */
addr = get_pc_function_start (frame->pc) + FUNCTION_START_OFFSET;
function_frame_info (addr, &fdata);
(void) skip_prologue (addr, &fdata);
if (fdata.frameless)
prev_sp = sp;
else
prev_sp = read_memory_integer (sp, 4);
if (fdata.nosavedpc)
if (fdata.lr_offset == 0)
lr = read_register (LR_REGNUM);
else
lr = read_memory_integer (prev_sp+8, 4);
lr = read_memory_integer (prev_sp + fdata.lr_offset, 4);
/* reset %pc value. */
write_register (PC_REGNUM, lr);
@ -568,147 +646,6 @@ fix_call_dummy(dummyname, pc, fun, nargs, type)
*(int*)((char*)dummyname + TARGET_ADDR_OFFSET+4) = ii;
}
/* return information about a function frame.
in struct rs6000_frameinfo fdata:
- frameless is TRUE, if function does not have a frame.
- nosavedpc is TRUE, if function does not save %pc value in its frame.
- offset is the number of bytes used in the frame to save registers.
- saved_gpr is the number of the first saved gpr.
- saved_fpr is the number of the first saved fpr.
- alloca_reg is the number of the register used for alloca() handling.
Otherwise -1.
*/
void
function_frame_info (pc, fdata)
CORE_ADDR pc;
struct rs6000_framedata *fdata;
{
unsigned int tmp;
register unsigned int op;
char buf[4];
fdata->offset = 0;
fdata->saved_gpr = fdata->saved_fpr = fdata->alloca_reg = -1;
fdata->frameless = 1;
/* Do not error out if we can't access the instructions. */
if (target_read_memory (pc, buf, 4))
return;
op = extract_unsigned_integer (buf, 4);
if (op == 0x7c0802a6) { /* mflr r0 */
pc += 4;
op = read_memory_integer (pc, 4);
fdata->nosavedpc = 0;
fdata->frameless = 0;
}
else /* else, pc is not saved */
fdata->nosavedpc = 1;
if ((op & 0xfc00003e) == 0x7c000026) { /* mfcr Rx */
pc += 4;
op = read_memory_integer (pc, 4);
fdata->frameless = 0;
}
if ((op & 0xfc000000) == 0x48000000) { /* bl foo, to save fprs??? */
pc += 4;
op = read_memory_integer (pc, 4);
/* At this point, make sure this is not a trampoline function
(a function that simply calls another functions, and nothing else).
If the next is not a nop, this branch was part of the function
prologue. */
if (op == 0x4def7b82 || /* crorc 15, 15, 15 */
op == 0x0)
return; /* prologue is over */
fdata->frameless = 0;
}
if ((op & 0xfc1f0000) == 0xd8010000) { /* stfd Rx,NUM(r1) */
pc += 4; /* store floating register double */
op = read_memory_integer (pc, 4);
fdata->frameless = 0;
}
if ((op & 0xfc1f0000) == 0xbc010000) { /* stm Rx, NUM(r1) */
int tmp2;
fdata->saved_gpr = (op >> 21) & 0x1f;
tmp2 = op & 0xffff;
if (tmp2 > 0x7fff)
tmp2 = (~0 &~ 0xffff) | tmp2;
if (tmp2 < 0) {
tmp2 = tmp2 * -1;
fdata->saved_fpr = (tmp2 - ((32 - fdata->saved_gpr) * 4)) / 8;
if ( fdata->saved_fpr > 0)
fdata->saved_fpr = 32 - fdata->saved_fpr;
else
fdata->saved_fpr = -1;
}
fdata->offset = tmp2;
pc += 4;
op = read_memory_integer (pc, 4);
fdata->frameless = 0;
}
while (((tmp = op >> 16) == 0x9001) || /* st r0, NUM(r1) */
(tmp == 0x9421) || /* stu r1, NUM(r1) */
(tmp == 0x93e1)) /* st r31, NUM(r1) */
{
int tmp2;
/* gcc takes a short cut and uses this instruction to save r31 only. */
if (tmp == 0x93e1) {
if (fdata->offset)
/* fatal ("Unrecognized prolog."); */
printf_unfiltered ("Unrecognized prolog!\n");
fdata->saved_gpr = 31;
tmp2 = op & 0xffff;
if (tmp2 > 0x7fff) {
tmp2 = - ((~0 &~ 0xffff) | tmp2);
fdata->saved_fpr = (tmp2 - ((32 - 31) * 4)) / 8;
if ( fdata->saved_fpr > 0)
fdata->saved_fpr = 32 - fdata->saved_fpr;
else
fdata->saved_fpr = -1;
}
fdata->offset = tmp2;
}
pc += 4;
op = read_memory_integer (pc, 4);
fdata->frameless = 0;
}
while ((tmp = (op >> 22)) == 0x20f) { /* l r31, ... or */
pc += 4; /* l r30, ... */
op = read_memory_integer (pc, 4);
fdata->frameless = 0;
}
/* store parameters into stack */
while(
(op & 0xfc1f0000) == 0xd8010000 || /* stfd Rx,NUM(r1) */
(op & 0xfc1f0000) == 0x90010000 || /* st r?, NUM(r1) */
(op & 0xfc000000) == 0xfc000000 || /* frsp, fp?, .. */
(op & 0xd0000000) == 0xd0000000) /* stfs, fp?, .. */
{
pc += 4; /* store fpr double */
op = read_memory_integer (pc, 4);
fdata->frameless = 0;
}
if (op == 0x603f0000 /* oril r31, r1, 0x0 */
|| op == 0x7c3f0b78) /* mr r31, r1 */
{
fdata->alloca_reg = 31;
fdata->frameless = 0;
}
}
/* Pass the arguments in either registers, or in the stack. In RS6000, the first
eight words of the argument list (that might be less than eight parameters if
some parameters occupy more than one word) are passed in r3..r11 registers.
@ -964,15 +901,10 @@ CORE_ADDR pc;
}
/* Determines whether the function FI has a frame on the stack or not.
Called from the FRAMELESS_FUNCTION_INVOCATION macro in tm.h with a
second argument of 0, and from the FRAME_SAVED_PC macro with a
second argument of 1. */
/* Determines whether the function FI has a frame on the stack or not. */
int
frameless_function_invocation (fi, pcsaved)
struct frame_info *fi;
int pcsaved;
frameless_function_invocation (fi)
struct frame_info *fi;
{
CORE_ADDR func_start;
struct rs6000_framedata fdata;
@ -991,10 +923,35 @@ int pcsaved;
if (!func_start)
return 0;
function_frame_info (func_start, &fdata);
return pcsaved ? fdata.nosavedpc : fdata.frameless;
(void) skip_prologue (func_start, &fdata);
return fdata.frameless;
}
/* Return the PC saved in a frame */
unsigned long
frame_saved_pc (fi)
struct frame_info *fi;
{
CORE_ADDR func_start;
struct rs6000_framedata fdata;
int frameless;
func_start = get_pc_function_start (fi->pc) + FUNCTION_START_OFFSET;
/* If we failed to find the start of the function, it is a mistake
to inspect the instructions. */
if (!func_start)
return 0;
(void) skip_prologue (func_start, &fdata);
if (fdata.lr_offset == 0)
return read_register (LR_REGNUM);
if (fi->signal_handler_caller)
return read_memory_integer (fi->frame + SIG_FRAME_PC_OFFSET, 4);
return read_memory_integer (rs6000_frame_chain (fi) + fdata.lr_offset, 4);
}
/* If saved registers of frame FI are not known yet, read and cache them.
&FDATAP contains rs6000_framedata; TDATAP can be NULL,
@ -1014,7 +971,7 @@ frame_get_cache_fsr (fi, fdatap)
if (fdatap == NULL) {
fdatap = &work_fdata;
function_frame_info (get_pc_function_start (fi->pc), fdatap);
(void) skip_prologue (get_pc_function_start (fi->pc), fdatap);
}
fi->cache_fsr = (struct frame_saved_regs *)
@ -1065,7 +1022,7 @@ frame_initial_stack_address (fi)
/* find out if this function is using an alloca register.. */
function_frame_info (get_pc_function_start (fi->pc), &fdata);
(void) skip_prologue (get_pc_function_start (fi->pc), &fdata);
/* if saved registers of this frame are not known yet, read and cache them. */