Better support V.4 calling sequences.
authorMichael Meissner <gnu@the-meissners.org>
Thu, 27 Jul 1995 03:50:05 +0000 (03:50 +0000)
committerMichael Meissner <gnu@the-meissners.org>
Thu, 27 Jul 1995 03:50:05 +0000 (03:50 +0000)
gdb/ChangeLog
gdb/config/rs6000/tm-rs6000.h
gdb/rs6000-tdep.c

index 2338caf87d8d52ad8b3e5273ef97c6f062bcd4a4..c27090551d560e268a570828c0c7000109ffa098 100644 (file)
@@ -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)
 
        * remote.c:  Add documentation for extended protocol operations
index 31a49efa076badbf31d6f83bf38b38b93b68d19c..8995d73b1ba10ac0b1c16a6517482b9c278f2b37 100644 (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;                                                    \
                                                                        \
-  /* 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;        \
+  }                                                                    \
 }
 
 \f
index c3a123c5a164f52e01d0971b664b65b0964a2f58..51ea3073fd3b54c963362ea295fe7830d31382ee 100644 (file)
@@ -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. */