forked from Imagelibrary/binutils-gdb
Better support V.4 calling sequences.
This commit is contained in:
@@ -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; \
|
||||
} \
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user