From 068c9fd63f9a7ca5ec8ebc5aa1f758a4ea9f0405 Mon Sep 17 00:00:00 2001 From: Michael Meissner Date: Thu, 27 Jul 1995 03:50:05 +0000 Subject: [PATCH] Better support V.4 calling sequences. --- gdb/ChangeLog | 24 ++ gdb/config/rs6000/tm-rs6000.h | 96 ++++---- gdb/rs6000-tdep.c | 411 +++++++++++++++------------------- 3 files changed, 266 insertions(+), 265 deletions(-) diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 2338caf87d8..c27090551d5 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,27 @@ +Wed Jul 26 23:33:34 1995 Michael Meissner + + * 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 diff --git a/gdb/config/rs6000/tm-rs6000.h b/gdb/config/rs6000/tm-rs6000.h index 31a49efa076..8995d73b1ba 100644 --- a/gdb/config/rs6000/tm-rs6000.h +++ b/gdb/config/rs6000/tm-rs6000.h @@ -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; \ \ - /* 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. */ \ + } 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 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 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 != -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 != 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 (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 LR */ \ + if (fdata.lr_offset != 0) { \ + (FRAME_SAVED_REGS).regs [LR_REGNUM] = frame_addr + fdata.lr_offset; \ + } \ } diff --git a/gdb/rs6000-tdep.c b/gdb/rs6000-tdep.c index c3a123c5a16..51ea3073fd3 100644 --- a/gdb/rs6000-tdep.c +++ b/gdb/rs6000-tdep.c @@ -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 & 0xfc00003e) == 0x7c000026) { /* mfcr Rx */ - pc += 4; - op = read_memory_integer (pc, 4); - } - - 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 & 0xfc1fffff) == 0x7c0802a6) { /* mflr Rx */ + lr_reg = (op & 0x03e00000) | 0x90010000; + continue; + + } else if ((op & 0xfc1fffff) == 0x7c000026) { /* mfcr Rx */ + cr_reg = (op & 0x03e00000) | 0x90010000; + continue; + + } 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; - if (op == 0x4def7b82 || /* crorc 15, 15, 15 */ - op == 0x0) - return pc - 4; /* don't skip over this branch */ - } + } else if (op == 0x7c21016e) { /* stwux 1,1,0 */ + pc += 4; /* offset set above */ + op = read_memory_integer (pc, 4); + break; - if ((op & 0xfc1f0000) == 0xd8010000) { /* stfd Rx,NUM(r1) */ - pc += 4; /* store floating register double */ - op = read_memory_integer (pc, 4); - } + } else { + break; + } + } - if ((op & 0xfc1f0000) == 0xbc010000) { /* stm Rx, NUM(r1) */ - pc += 4; + /* 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); - } - while ((op & 0xfc1f0000) == 0x90010000 && /* st rx,NUM(r1), rx >= r13 */ - (op & 0x03e00000) >= 0x01a00000) { - pc += 4; - op = read_memory_integer (pc, 4); + /* 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 == 0x90010008) { /* st r0,8(r1) */ - pc += 4; + while ((op >> 22) == 0x20f) { /* l r31, ... or */ + pc += 4; /* l r30, ... */ 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) */ + /* store parameters into stack */ + while( + (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); } - while ((tmp = (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); - } - - 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), ... */ + /* 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) */ + + /* 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. */ -- 2.30.2