diff options
-rw-r--r-- | gdb/ChangeLog | 29 | ||||
-rw-r--r-- | gdb/rs6000-tdep.c | 60 | ||||
-rw-r--r-- | gdb/tm-rs6000.h | 28 |
3 files changed, 88 insertions, 29 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 58d5758..a999142 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,5 +1,34 @@ +Tue Nov 17 11:17:06 1992 Ian Lance Taylor (ian@cygnus.com) + + * tm-rs6000.h (BELIEVE_PCC_PROMOTION): Define, since AIX cc gets + it right. + (aix_framedata): added nosavedpc field. + (SAVED_PC_AFTER_CALL): Don't try to optimize; just call + read_register. + (FRAMELESS_FUNCTION_INVOCATION): Pass second argument of 0. + (FRAME_SAVED_PC): If PC not saved, use SAVED_PC_AFTER_CALL. + * rs6000-tdep.c (skip_prologue): Handle gcc generated stfd + instructions as function_frame_info does. Expand special case of + st r31,-4(r1) to be st r31,NUM(r1), since gcc can generate offsets + other than -4. + (pop_frame): Add 4 rather than sizeof (int) to avoid host + dependence. + (function_frame_info): Set frameless if the function has no frame, + and set nosavedpc if the PC was not saved. Handle gcc generated + stfd 31,-4(31); st 31, -12(31) correctly. + (frameless_function_invocation): New second argument pcsaved; if 0 + return whether the function has a frame, if 1 return whether the + function saved PC. + (frame_initial_stack_address): Correct typo: cache registers for + callee_fi, not for fi, (avoids reading garbage memory locations). + Mon Nov 16 15:58:07 1992 Stu Grossman (grossman at cygnus.com) + * infrun.c (wait_for_inferior (just before step_over_function + label)): Change test for stepping into subroutine to check for the + presence of line number info. This makes stuff compiled with -g1 + cause GDB to not lose control when stepping. + * symtab.c (find_pc_line): Improve code per gnu's suggestions. Improve comments as well. diff --git a/gdb/rs6000-tdep.c b/gdb/rs6000-tdep.c index 80deb81..14c88a4 100644 --- a/gdb/rs6000-tdep.c +++ b/gdb/rs6000-tdep.c @@ -210,6 +210,11 @@ CORE_ADDR pc; return pc - 4; /* don't skip over this branch */ } + 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); @@ -217,7 +222,7 @@ CORE_ADDR pc; while (((tmp = op >> 16) == 0x9001) || /* st r0, NUM(r1) */ (tmp == 0x9421) || /* stu r1, NUM(r1) */ - (op == 0x93e1fffc)) /* st r31,-4(r1) */ + (tmp == 0x93e1)) /* st r31,NUM(r1) */ { pc += 4; op = read_memory_integer (pc, 4); @@ -476,7 +481,7 @@ pop_frame () if (fdata.saved_gpr != -1) for (ii=fdata.saved_gpr; ii <= 31; ++ii) { read_memory (addr, ®isters [REGISTER_BYTE (ii)], 4); - addr += sizeof (int); + addr += 4; } if (fdata.saved_fpr != -1) @@ -533,7 +538,8 @@ fix_call_dummy(dummyname, pc, fun, nargs, type) /* return information about a function frame. in struct aix_frameinfo fdata: - - frameless is TRUE, if function does not save %pc value in its frame. + - 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. @@ -550,20 +556,22 @@ function_frame_info (pc, fdata) fdata->offset = 0; fdata->saved_gpr = fdata->saved_fpr = fdata->alloca_reg = -1; + fdata->frameless = 1; op = read_memory_integer (pc, 4); if (op == 0x7c0802a6) { /* mflr r0 */ pc += 4; op = read_memory_integer (pc, 4); + fdata->nosavedpc = 0; fdata->frameless = 0; } - else /* else, this is a frameless invocation */ - fdata->frameless = 1; - + 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??? */ @@ -577,11 +585,13 @@ function_frame_info (pc, fdata) 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) */ @@ -589,7 +599,7 @@ function_frame_info (pc, fdata) fdata->saved_gpr = (op >> 21) & 0x1f; tmp2 = op & 0xffff; if (tmp2 > 0x7fff) - tmp2 = 0xffff0000 | tmp2; + tmp2 = (~0 &~ 0xffff) | tmp2; if (tmp2 < 0) { tmp2 = tmp2 * -1; @@ -602,29 +612,43 @@ function_frame_info (pc, fdata) 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) */ - (op == 0x93e1fffc)) /* st r31,-4(r1) */ + (tmp == 0x93e1)) /* st r31, NUM(r1) */ { + int tmp2; + /* gcc takes a short cut and uses this instruction to save r31 only. */ - if (op == 0x93e1fffc) { + if (tmp == 0x93e1) { if (fdata->offset) /* fatal ("Unrecognized prolog."); */ printf ("Unrecognized prolog!\n"); fdata->saved_gpr = 31; - fdata->offset = 4; + 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 */ @@ -636,10 +660,13 @@ function_frame_info (pc, fdata) { pc += 4; /* store fpr double */ op = read_memory_integer (pc, 4); + fdata->frameless = 0; } - if (op == 0x603f0000) /* oril r31, r1, 0x0 */ + if (op == 0x603f0000) { /* oril r31, r1, 0x0 */ fdata->alloca_reg = 31; + fdata->frameless = 0; + } } @@ -906,11 +933,14 @@ 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. */ + 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 -frameless_function_invocation (fi) +frameless_function_invocation (fi, pcsaved) struct frame_info *fi; +int pcsaved; { CORE_ADDR func_start; struct aix_framedata fdata; @@ -924,7 +954,7 @@ struct frame_info *fi; return 0; function_frame_info (func_start, &fdata); - return fdata.frameless; + return pcsaved ? fdata.nosavedpc : fdata.frameless; } @@ -1026,7 +1056,7 @@ frame_initial_stack_address (fi) for (callee_fi = fi->next; callee_fi; callee_fi = callee_fi->next) { if (!callee_fi->cache_fsr) - frame_get_cache_fsr (fi, NULL); + frame_get_cache_fsr (callee_fi, NULL); /* this is the address in which alloca register is saved. */ diff --git a/gdb/tm-rs6000.h b/gdb/tm-rs6000.h index 1b0ffde..5dff65c 100644 --- a/gdb/tm-rs6000.h +++ b/gdb/tm-rs6000.h @@ -36,6 +36,9 @@ extern int symtab_relocated; #define PC_LOAD_SEGMENT(PC) pc_load_segment_name(PC) +/* AIX cc seems to get this right. */ + +#define BELIEVE_PCC_PROMOTION 1 /* Conversion between a register number in stab string to actual register num. */ @@ -82,6 +85,7 @@ struct aix_framedata { int saved_fpr; /* smallest # of saved fpr */ int alloca_reg; /* alloca register number (frame ptr) */ char frameless; /* true if frameless functions. */ + char nosavedpc; /* true if pc not saved. */ }; void @@ -174,13 +178,7 @@ extern int loadinfotextindex; the new frame is not set up until the new function executes some instructions. */ -#define SAVED_PC_AFTER_CALL(frame) \ - (register_valid [LR_REGNUM] ? \ - (*(int*)®isters[REGISTER_BYTE (LR_REGNUM)]) : \ - read_register (LR_REGNUM)) - -/*#define SAVED_PC_AFTER_CALL(frame) saved_pc_after_call(frame) */ - +#define SAVED_PC_AFTER_CALL(frame) read_register (LR_REGNUM) /* Address of end of stack space. */ @@ -423,7 +421,7 @@ extern unsigned int rs6000_struct_return_address; does not, FRAMELESS is set to 1, else 0. */ #define FRAMELESS_FUNCTION_INVOCATION(FI, FRAMELESS) \ - FRAMELESS = frameless_function_invocation (FI) + FRAMELESS = frameless_function_invocation (FI, 0) /* 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 @@ -436,17 +434,19 @@ extern unsigned int rs6000_struct_return_address; CORE_ADDR initial_sp; /* initial stack pointer. */ \ struct frame_saved_regs *cache_fsr; /* saved registers */ -/* Frameless function invocation in IBM RS/6000 is 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. In the following, even though it is considered a - frameless invocation, we still need to walk one frame up. */ +/* 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. */ #define INIT_EXTRA_FRAME_INFO(fromleaf, fi) \ fi->initial_sp = 0; \ fi->cache_fsr = 0; -#define FRAME_SAVED_PC(FRAME) \ - read_memory_integer (read_memory_integer ((FRAME)->frame, 4)+8, 4) +#define FRAME_SAVED_PC(FRAME) \ + (frameless_function_invocation (FRAME, 1) \ + ? SAVED_PC_AFTER_CALL (FRAME) \ + : read_memory_integer (read_memory_integer ((FRAME)->frame, 4)+8, 4)) #define FRAME_ARGS_ADDRESS(FI) \ (((struct frame_info*)(FI))->initial_sp ? \ |