* frame.h: Move definition of struct frame_saved_args to before
authorStu Grossman <grossman@cygnus>
Fri, 11 Oct 1996 22:50:42 +0000 (22:50 +0000)
committerStu Grossman <grossman@cygnus>
Fri, 11 Oct 1996 22:50:42 +0000 (22:50 +0000)
struct frame to make it possible to use frame_saved_args in
EXTRA_FRAME_INFO macro.

* v850-tdep.c config/v850/tm-v850.h:  Lotsa new functions and
macros to make frame operations (such as backtrace) work.

gdb/ChangeLog
gdb/config/v850/tm-v850.h
gdb/v850-tdep.c

index c0b1a5b31743b12588a0dec84ec80ba4867e580f..32d8af27cb2289d5cb0a650f0d53857b7f6287cc 100644 (file)
@@ -1,3 +1,14 @@
+Fri Oct 11 15:43:54 1996  Stu Grossman  (grossman@critters.cygnus.com)
+
+       * frame.h:  Move definition of struct frame_saved_args to before
+       struct frame to make it possible to use frame_saved_args in
+       EXTRA_FRAME_INFO macro.
+
+start-sanitize-v850
+       * v850-tdep.c config/v850/tm-v850.h:  Lotsa new functions and
+       macros to make frame operations (such as backtrace) work.
+
+end-sanitize-v850
 Fri Oct 11 14:23:50 1996  Fred Fish  <fnf@cygnus.com>
 
        * dbxread.c (process_one_symbol): Check for null string directly
index b09b25a6d36476c33e457a3d88a98a6bb7bee2b8..5aa11b56962ac078ba7b7335c9be0d7468f72a21 100644 (file)
@@ -41,6 +41,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 
 #define SP_REGNUM 3
 #define FP_REGNUM 2
+#define V0_REGNUM 10
+#define V1_REGNUM 11
 #define RP_REGNUM 31
 #define PC_REGNUM 64
 
@@ -58,26 +60,49 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 
 #define DECR_PC_AFTER_BREAK 0
 
-#define POP_FRAME warning ("POP_FRAME not implemented yet!")
-
 #define INNER_THAN <
 
-#define FRAME_ARGS_SKIP 4
-
 #define SAVED_PC_AFTER_CALL(fi) read_register (RP_REGNUM)
 
-#define FRAME_CHAIN(fi) (read_memory_unsigned_integer ((fi)->frame - 8, 4))
+#ifdef __STDC__
+struct frame_info;
+struct frame_saved_regs;
+struct type;
+#endif
+
+#define EXTRA_FRAME_INFO struct frame_saved_regs fsr;
+
+extern void v850_init_extra_frame_info PARAMS ((struct frame_info *fi));
+#define INIT_EXTRA_FRAME_INFO(fromleaf, fi) v850_init_extra_frame_info (fi)
+#define INIT_FRAME_PC          /* Not necessary */
+
+extern void v850_frame_find_saved_regs PARAMS ((struct frame_info *fi, struct frame_saved_regs *regaddr));
+#define FRAME_FIND_SAVED_REGS(fi, regaddr) regaddr = fi->fsr
 
-#define FRAME_SAVED_PC(fi) (read_memory_unsigned_integer((fi)->frame - 4, 4))
+extern CORE_ADDR v850_frame_chain PARAMS ((struct frame_info *fi));
+#define FRAME_CHAIN(fi) v850_frame_chain (fi)
 
+extern CORE_ADDR v850_find_callers_reg PARAMS ((struct frame_info *fi, int regnum));
+#define FRAME_SAVED_PC(fi) (v850_find_callers_reg (fi, RP_REGNUM))
 
-#define SKIP_PROLOGUE(pc) pc+=8
+#define EXTRACT_RETURN_VALUE(TYPE, REGBUF, VALBUF) \
+  memcpy (VALBUF, REGBUF + REGISTER_BYTE (V0_REGNUM), TYPE_LENGTH (TYPE))
+
+#define EXTRACT_STRUCT_VALUE_ADDRESS(REGBUF) \
+  (extract_address (REGBUF + REGISTER_BYTE (V0_REGNUM), \
+                   REGISTER_RAW_SIZE (V0_REGNUM)))
+
+#define STORE_RETURN_VALUE(TYPE, VALBUF) \
+  write_register_bytes(REGISTER_BYTE (V0_REGNUM), VALBUF, TYPE_LENGTH (TYPE));
+
+extern CORE_ADDR v850_skip_prologue PARAMS ((CORE_ADDR pc));
+#define SKIP_PROLOGUE(pc) pc = v850_skip_prologue (pc)
+
+#define FRAME_ARGS_SKIP 0
 
 #define FRAME_ARGS_ADDRESS(fi) ((fi)->frame)
 #define FRAME_LOCALS_ADDRESS(fi) ((fi)->frame)
 #define FRAME_NUM_ARGS(val, fi) ((val) = -1)
-#define FRAME_FIND_SAVED_REGS(fi, regaddr) warning ("FRAME_FIND_SAVED_REGS not implemented yet!")
-
-#define EXTRACT_RETURN_VALUE(TYPE, REGBUF, VALBUF) warning ("EXTRACT_RETURN_VALUE not implemented yet!")
-#define STORE_RETURN_VALUE(TYPE, VALBUF) warning ("STORE_RETURN_VALUE not implemented yet!")
 
+extern struct frame_info *v850_pop_frame PARAMS ((struct frame_info *frame));
+#define POP_FRAME v850_pop_frame (get_current_frame ())
index b710920942e15e0ce95a92b7939a1bef70c67da4..7363fc2e528157ddf4f9158b4820f2c3d8bd9a57 100644 (file)
@@ -30,6 +30,222 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 #include "gdb_string.h"
 
 #include "gdbcore.h"
+
+\f
+/* This function actually figures out the frame address for a given pc and
+   sp.  This is tricky on the v850 because we only use an explicit frame
+   pointer when using alloca().  The only reliable way to get this info is to
+   examine the prologue.
+*/
+
+void
+v850_init_extra_frame_info (fi)
+     struct frame_info *fi;
+{
+  struct symtab_and_line sal;
+  CORE_ADDR func_addr, prologue_end, current_pc;
+  int reg;
+  int frameoffset;
+  int framereg;
+
+  if (fi->next)
+    fi->pc = v850_find_callers_reg (fi->next, RP_REGNUM);
+
+  /* First, figure out the bounds of the prologue so that we can limit the
+     search to something reasonable.  */
+
+  if (find_pc_partial_function (fi->pc, NULL, &func_addr, NULL))
+    {
+      sal = find_pc_line (func_addr, 0);
+
+      prologue_end = sal.end;
+    }
+  else
+    prologue_end = func_addr + 100; /* We're in the boondocks */
+
+  prologue_end = min (prologue_end, fi->pc);
+
+  /* Now, search the prologue looking for instructions that setup fp, save
+     rp, adjust sp and such. */ 
+
+  framereg = SP_REGNUM;
+  frameoffset = 0;
+  memset (fi->fsr.regs, '\000', sizeof fi->fsr.regs);
+
+  for (current_pc = func_addr; current_pc < prologue_end; current_pc += 2)
+    {
+      int insn;
+
+      insn = read_memory_integer (current_pc, 2);
+
+      if ((insn & 0xffe0) == ((SP_REGNUM << 11) | 0x0240)) /* add <imm>,sp */
+       frameoffset = (insn & 0x1f) | ~0x1f;
+      else if (insn == ((SP_REGNUM << 11) | 0x0600 | SP_REGNUM)) /* addi <imm>,sp,sp */
+       {
+         current_pc += 2;
+
+         frameoffset = read_memory_integer (current_pc, 2);
+       }
+      else if (insn == ((FP_REGNUM << 11) | 0x0000 | 12)) /* mov r12,r2 */
+       framereg = FP_REGNUM;   /* Setting up fp */
+      else if ((insn & 0x07ff) == (0x0760 | SP_REGNUM))        /* st.w <reg>,<offset>[sp] */
+       {
+         reg = (insn >> 11) & 0x1f;    /* Extract <reg> */
+         current_pc += 2;
+
+         insn = read_memory_integer (current_pc, 2) & ~1;
+
+         fi->fsr.regs[reg] = insn + frameoffset;
+       }
+      else if ((insn & 0x07ff) == (0x0760 | FP_REGNUM))        /* st.w <reg>,<offset>[fp] */
+       {
+         reg = (insn >> 11) & 0x1f;    /* Extract <reg> */
+         current_pc += 2;
+
+         insn = read_memory_integer (current_pc, 2) & ~1;
+
+         fi->fsr.regs[reg] = insn;
+       }
+    }
+
+#if 0
+  if (!fi->next)
+    fi->frame = read_register (framereg);
+  else
+    if (framereg == SP_REGNUM)
+      fi->frame = fi->next->frame;
+    else
+      fi->frame = v850_find_callers_reg (fi, framereg);
+
+  if (framereg == SP_REGNUM)
+    fi->frame -= frameoffset;
+#else
+  if (!fi->next && framereg == SP_REGNUM)
+    fi->frame = read_register (framereg) - frameoffset;
+#endif
+
+  for (reg = 0; reg < NUM_REGS; reg++)
+    if (fi->fsr.regs[reg] != 0)
+      fi->fsr.regs[reg] += fi->frame;
+}
+
+/* Find the caller of this frame.  We do this by seeing if RP_REGNUM is saved
+   in the stack anywhere, otherwise we get it from the registers. */
+
+CORE_ADDR
+v850_find_callers_reg (fi, regnum)
+     struct frame_info *fi;
+     int regnum;
+{
+  for (; fi; fi = fi->next)
+    if (fi->fsr.regs[regnum] != 0)
+      return read_memory_integer (fi->fsr.regs[regnum], 4);
+
+  return read_register (regnum);
+}
+
+CORE_ADDR
+v850_frame_chain (fi)
+     struct frame_info *fi;
+{
+  CORE_ADDR callers_pc, callers_sp;
+  struct frame_info temp_fi;
+  CORE_ADDR func_addr, prologue_end, current_pc;
+  int frameoffset;
+
+  /* First, find out who called us */
+
+  callers_pc = v850_find_callers_reg (fi, RP_REGNUM);
+
+  /* Next, figure out where his prologue is.  */
+
+  if (find_pc_partial_function (callers_pc, NULL, &func_addr, NULL))
+    {
+      struct symtab_and_line sal;
+
+      sal = find_pc_line (func_addr, 0);
+
+      prologue_end = sal.end;
+    }
+  else
+    prologue_end = func_addr + 100; /* We're in the boondocks */
+
+  prologue_end = min (prologue_end, callers_pc);
+
+  /* Now, figure out the frame location of the caller by examining his prologue.
+     We're looking for either a load of the frame pointer register, or a stack
+     adjustment. */
+
+  frameoffset = 0;
+
+  for (current_pc = func_addr; current_pc < prologue_end; current_pc += 2)
+    {
+      int insn;
+
+      insn = read_memory_integer (current_pc, 2);
+
+      if ((insn & 0xffe0) == ((SP_REGNUM << 11) | 0x0240)) /* add <imm>,sp */
+       frameoffset = (insn & 0x1f) | ~0x1f;
+      else if (insn == ((SP_REGNUM << 11) | 0x0600 | SP_REGNUM)) /* addi <imm>,sp,sp */
+       {
+         current_pc += 2;
+
+         frameoffset = read_memory_integer (current_pc, 2);
+       }
+      else if (insn == ((FP_REGNUM << 11) | 0x0000 | 12)) /* mov r12,r2 */
+       return v850_find_callers_reg (fi, FP_REGNUM); /* It's using a frame pointer reg */
+      else if ((insn & 0x07ff) == (0x0760 | SP_REGNUM))        /* st.w <reg>,<offset>[sp] */
+       current_pc += 2;
+      else if ((insn & 0x07ff) == (0x0760 | FP_REGNUM))        /* st.w <reg>,<offset>[fp] */
+       current_pc += 2;
+    }
+
+  return fi->frame - frameoffset;
+}
+
+CORE_ADDR
+v850_skip_prologue (pc)
+     CORE_ADDR pc;
+{
+  CORE_ADDR func_addr, func_end;
+
+  /* See what the symbol table says */
+
+  if (find_pc_partial_function (pc, NULL, &func_addr, &func_end))
+    {
+      struct symtab_and_line sal;
+
+      sal = find_pc_line (func_addr, 0);
+
+      if (sal.end < func_end)
+       return sal.end;
+      else
+       /* The line after the prologue is after the end of the function.  In
+          this case, there probably isn't a prologue.  */
+       return pc;
+    }
+
+/* We can't find the start of this function, so there's nothing we can do. */
+  return pc;
+}
+
+struct frame_info *
+v850_pop_frame (frame)
+     struct frame_info *frame;
+{
+  int regnum;
+
+  write_register (PC_REGNUM, FRAME_SAVED_PC (frame));
+
+  for (regnum = 0; regnum < NUM_REGS; regnum++)
+    if (frame->fsr.regs[regnum] != 0)
+      write_register (regnum, read_memory_integer (frame->fsr.regs[regnum], 4));
+
+  write_register (SP_REGNUM, FRAME_FP (frame));
+  flush_cached_frames ();
+
+  return NULL;
+}
 \f
 void
 _initialize_sparc_tdep ()