mirror of
https://github.com/espressif/binutils-gdb.git
synced 2025-06-23 19:50:13 +08:00
Better support V.4 calling sequences.
This commit is contained in:
@ -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)
|
Wed Jul 26 01:00:37 1995 Jeff Law (law@snake.cs.utah.edu)
|
||||||
|
|
||||||
* remote.c: Add documentation for extended protocol operations
|
* remote.c: Add documentation for extended protocol operations
|
||||||
|
@ -56,7 +56,7 @@ struct fp_status {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/* To be used by function_frame_info. */
|
/* To be used by skip_prologue. */
|
||||||
|
|
||||||
struct rs6000_framedata {
|
struct rs6000_framedata {
|
||||||
int offset; /* # of bytes in gpr's and fpr's are saved */
|
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) */
|
int alloca_reg; /* alloca register number (frame ptr) */
|
||||||
char frameless; /* true if frameless functions. */
|
char frameless; /* true if frameless functions. */
|
||||||
char nosavedpc; /* true if pc not saved. */
|
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 the byte order of the machine. */
|
||||||
|
|
||||||
#define TARGET_BYTE_ORDER BIG_ENDIAN
|
#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
|
/* Advance PC across any function entry prologue instructions
|
||||||
to reach some "real" code. */
|
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
|
/* If PC is in some function-call trampoline code, return the PC
|
||||||
where the function itself actually starts. If not, return NULL. */
|
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. */
|
does not, FRAMELESS is set to 1, else 0. */
|
||||||
|
|
||||||
#define FRAMELESS_FUNCTION_INVOCATION(FI, FRAMELESS) \
|
#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
|
/* 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
|
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_PC_OFFSET 96
|
||||||
#define SIG_FRAME_FP_OFFSET 284
|
#define SIG_FRAME_FP_OFFSET 284
|
||||||
|
|
||||||
/* Frameless function invocation in IBM RS/6000 is sometimes
|
/* Return saved PC from a frame */
|
||||||
half-done. It perfectly sets up a new frame, e.g. a new frame (in
|
#define FRAME_SAVED_PC(FRAME) frame_saved_pc (FRAME)
|
||||||
fact stack) pointer, etc, but it doesn't save the %pc. We call
|
|
||||||
frameless_function_invocation to tell us how to get the %pc. */
|
|
||||||
|
|
||||||
#define FRAME_SAVED_PC(FRAME) \
|
extern unsigned long frame_saved_pc PARAMS ((struct frame_info *));
|
||||||
(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))
|
|
||||||
|
|
||||||
#define FRAME_ARGS_ADDRESS(FI) \
|
#define FRAME_ARGS_ADDRESS(FI) \
|
||||||
(((struct frame_info*)(FI))->initial_sp ? \
|
(((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; \
|
CORE_ADDR frame_addr, func_start; \
|
||||||
struct rs6000_framedata fdata; \
|
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; \
|
func_start = get_pc_function_start ((FRAME_INFO)->pc) + FUNCTION_START_OFFSET; \
|
||||||
function_frame_info (func_start, &fdata); \
|
(void) skip_prologue (func_start, &fdata); \
|
||||||
memset (&(FRAME_SAVED_REGS), '\0', sizeof (FRAME_SAVED_REGS)); \
|
memset (&(FRAME_SAVED_REGS), '\0', sizeof (FRAME_SAVED_REGS)); \
|
||||||
\
|
\
|
||||||
/* if there were any saved registers, figure out parent's stack pointer. */ \
|
/* 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(), \
|
/* the following is true only if the frame doesn't have a call to alloca(), \
|
||||||
FIXME. */ \
|
FIXME. */ \
|
||||||
if (fdata.saved_fpr >= 0 || fdata.saved_gpr >= 0) { \
|
if (fdata.saved_fpr == 0 && fdata.saved_gpr == 0 && \
|
||||||
if ((FRAME_INFO)->prev && (FRAME_INFO)->prev->frame) \
|
fdata.lr_offset == 0 && fdata.cr_offset == 0) { \
|
||||||
frame_addr = (FRAME_INFO)->prev->frame; \
|
frame_addr = 0; \
|
||||||
else \
|
\
|
||||||
frame_addr = read_memory_integer ((FRAME_INFO)->frame, 4); \
|
} 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 \
|
/* if != -1, fdata.saved_fpr is the smallest number of saved_fpr. All \
|
||||||
from saved_fpr to fp31 are saved right underneath caller stack pointer, \
|
fpr's from saved_fpr to f31 are saved. */ \
|
||||||
starting from fp31 first. */ \
|
|
||||||
\
|
|
||||||
if (fdata.saved_fpr >= 0) { \
|
if (fdata.saved_fpr >= 0) { \
|
||||||
for (ii=31; ii >= fdata.saved_fpr; --ii) \
|
int fpr_offset = frame_addr + fdata.fpr_offset; \
|
||||||
(FRAME_SAVED_REGS).regs [FP0_REGNUM + ii] = frame_addr - ((32 - ii) * 8); \
|
for (ii = fdata.saved_fpr; ii < 32; ii++) { \
|
||||||
frame_addr -= (32 - fdata.saved_fpr) * 8; \
|
(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 \
|
/* if != -1, fdata.saved_gpr is the smallest number of saved_gpr. All \
|
||||||
from saved_gpr to gpr31 are saved right under saved fprs, starting \
|
gpr's from saved_gpr to r31 are saved. */ \
|
||||||
from r31 first. */ \
|
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) \
|
/* If != 0, fdata.cr_offset is the offset from the frame that holds \
|
||||||
for (ii=31; ii >= fdata.saved_gpr; --ii) \
|
the CR */ \
|
||||||
(FRAME_SAVED_REGS).regs [ii] = frame_addr - ((32 - ii) * 4); \
|
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; \
|
||||||
|
} \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -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)
|
in struct rs6000_frameinfo fdata:
|
||||||
CORE_ADDR pc;
|
- 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];
|
char buf[4];
|
||||||
unsigned int tmp;
|
|
||||||
unsigned long op;
|
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))
|
if (target_read_memory (pc, buf, 4))
|
||||||
return pc; /* Can't access it -- assume no prologue. */
|
return pc; /* Can't access it -- assume no prologue. */
|
||||||
op = extract_unsigned_integer (buf, 4);
|
|
||||||
|
|
||||||
/* Assume that subsequent fetches can fail with low probability. */
|
/* 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 */
|
if ((op & 0xfc1fffff) == 0x7c0802a6) { /* mflr Rx */
|
||||||
pc += 4;
|
lr_reg = (op & 0x03e00000) | 0x90010000;
|
||||||
op = read_memory_integer (pc, 4);
|
continue;
|
||||||
}
|
|
||||||
|
|
||||||
if ((op & 0xfc00003e) == 0x7c000026) { /* mfcr Rx */
|
} else if ((op & 0xfc1fffff) == 0x7c000026) { /* mfcr Rx */
|
||||||
pc += 4;
|
cr_reg = (op & 0x03e00000) | 0x90010000;
|
||||||
op = read_memory_integer (pc, 4);
|
continue;
|
||||||
}
|
|
||||||
|
|
||||||
if ((op & 0xfc000000) == 0x48000000) { /* bl foo, to save fprs??? */
|
} else if ((op & 0xfc1f0000) == 0xd8010000) { /* stfd Rx,NUM(r1) */
|
||||||
pc += 4;
|
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);
|
op = read_memory_integer (pc, 4);
|
||||||
|
|
||||||
/* At this point, make sure this is not a trampoline function
|
/* And -mminimal-toc code on V.4 */
|
||||||
(a function that simply calls another functions, and nothing else).
|
} else if ((op & 0xffff0000) == 0x3fc00000 && /* addis 30,0,foo@ha */
|
||||||
If the next is not a nop, this branch was part of the function
|
/* addi 30,30,foo@l */
|
||||||
prologue. */
|
((read_memory_integer (pc+4, 4) & 0xffff0000) == 0x3bde0000)) {
|
||||||
|
pc += 8;
|
||||||
if (op == 0x4def7b82 || /* crorc 15, 15, 15 */
|
op = read_memory_integer (pc, 8);
|
||||||
op == 0x0)
|
|
||||||
return pc - 4; /* don't skip over this branch */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((op & 0xfc1f0000) == 0xd8010000) { /* stfd Rx,NUM(r1) */
|
while ((op >> 22) == 0x20f) { /* l r31, ... or */
|
||||||
pc += 4; /* store floating register double */
|
pc += 4; /* l r30, ... */
|
||||||
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, ... */
|
|
||||||
op = read_memory_integer (pc, 4);
|
op = read_memory_integer (pc, 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* store parameters into stack */
|
/* store parameters into stack */
|
||||||
while(
|
while(
|
||||||
(op & 0xfc1f0000) == 0xd8010000 || /* stfd Rx,NUM(r1) */
|
(op & 0xfc1f0000) == 0x90010000 || /* st rx,NUM(r1) */
|
||||||
(op & 0xfc1f0000) == 0x90010000 || /* st r?, NUM(r1) */
|
(op & 0xfc1f0000) == 0xd8010000 || /* stfd Rx,NUM(r1) */
|
||||||
(op & 0xfc000000) == 0xfc000000 || /* frsp, fp?, .. */
|
(op & 0xfc1f0000) == 0xfc010000) { /* frsp, fp?,NUM(r1) */
|
||||||
(op & 0xd0000000) == 0xd0000000) /* stfs, fp?, .. */
|
pc += 4;
|
||||||
{
|
op = read_memory_integer (pc, 4);
|
||||||
pc += 4; /* store fpr double */
|
}
|
||||||
op = read_memory_integer (pc, 4);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (op == 0x603f0000 /* oril r31, r1, 0x0 */
|
/* Set up frame pointer */
|
||||||
|| op == 0x7c3f0b78) { /* mr r31, r1 */
|
if (op == 0x603f0000 /* oril r31, r1, 0x0 */
|
||||||
pc += 4; /* this happens if r31 is used as */
|
|| op == 0x7c3f0b78) { /* mr r31, r1 */
|
||||||
op = read_memory_integer (pc, 4); /* frame ptr. (gcc does that) */
|
pc += 4; /* this happens if r31 is used as */
|
||||||
|
op = read_memory_integer (pc, 4); /* frame ptr. (gcc does that) */
|
||||||
|
|
||||||
tmp = 0;
|
/* store parameters into frame */
|
||||||
while ((op >> 16) == (0x907f + tmp)) { /* st r3, NUM(r31) */
|
while (
|
||||||
pc += 4; /* st r4, NUM(r31), ... */
|
(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);
|
op = read_memory_integer (pc, 4);
|
||||||
tmp += 0x20;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
/* I have problems with skipping over __main() that I need to address
|
/* I have problems with skipping over __main() that I need to address
|
||||||
* sometime. Previously, I used to use misc_function_vector which
|
* sometime. Previously, I used to use misc_function_vector which
|
||||||
@ -302,6 +379,7 @@ CORE_ADDR pc;
|
|||||||
}
|
}
|
||||||
#endif /* 0 */
|
#endif /* 0 */
|
||||||
|
|
||||||
|
fdata->frameless = (pc == orig_pc);
|
||||||
return pc;
|
return pc;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -496,16 +574,16 @@ pop_frame ()
|
|||||||
saved %pc value in the previous frame. */
|
saved %pc value in the previous frame. */
|
||||||
|
|
||||||
addr = get_pc_function_start (frame->pc) + FUNCTION_START_OFFSET;
|
addr = get_pc_function_start (frame->pc) + FUNCTION_START_OFFSET;
|
||||||
function_frame_info (addr, &fdata);
|
(void) skip_prologue (addr, &fdata);
|
||||||
|
|
||||||
if (fdata.frameless)
|
if (fdata.frameless)
|
||||||
prev_sp = sp;
|
prev_sp = sp;
|
||||||
else
|
else
|
||||||
prev_sp = read_memory_integer (sp, 4);
|
prev_sp = read_memory_integer (sp, 4);
|
||||||
if (fdata.nosavedpc)
|
if (fdata.lr_offset == 0)
|
||||||
lr = read_register (LR_REGNUM);
|
lr = read_register (LR_REGNUM);
|
||||||
else
|
else
|
||||||
lr = read_memory_integer (prev_sp+8, 4);
|
lr = read_memory_integer (prev_sp + fdata.lr_offset, 4);
|
||||||
|
|
||||||
/* reset %pc value. */
|
/* reset %pc value. */
|
||||||
write_register (PC_REGNUM, lr);
|
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;
|
*(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
|
/* 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
|
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.
|
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.
|
/* 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. */
|
|
||||||
|
|
||||||
int
|
int
|
||||||
frameless_function_invocation (fi, pcsaved)
|
frameless_function_invocation (fi)
|
||||||
struct frame_info *fi;
|
struct frame_info *fi;
|
||||||
int pcsaved;
|
|
||||||
{
|
{
|
||||||
CORE_ADDR func_start;
|
CORE_ADDR func_start;
|
||||||
struct rs6000_framedata fdata;
|
struct rs6000_framedata fdata;
|
||||||
@ -991,10 +923,35 @@ int pcsaved;
|
|||||||
if (!func_start)
|
if (!func_start)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
function_frame_info (func_start, &fdata);
|
(void) skip_prologue (func_start, &fdata);
|
||||||
return pcsaved ? fdata.nosavedpc : fdata.frameless;
|
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.
|
/* If saved registers of frame FI are not known yet, read and cache them.
|
||||||
&FDATAP contains rs6000_framedata; TDATAP can be NULL,
|
&FDATAP contains rs6000_framedata; TDATAP can be NULL,
|
||||||
@ -1014,7 +971,7 @@ frame_get_cache_fsr (fi, fdatap)
|
|||||||
|
|
||||||
if (fdatap == NULL) {
|
if (fdatap == NULL) {
|
||||||
fdatap = &work_fdata;
|
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 *)
|
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.. */
|
/* 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. */
|
/* if saved registers of this frame are not known yet, read and cache them. */
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user