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

@@ -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; \
} \
}