Thu May 21 13:14:25 1998 John Metzler <jmetzler@cygnus.com>
[deliverable/binutils-gdb.git] / gdb / d30v-tdep.c
index 09cd9e3f3920a04163fb927665db473671fbd36e..1add1db54ec527cfed4178216a33fdb02464a1d5 100644 (file)
@@ -35,6 +35,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 
 void d30v_frame_find_saved_regs PARAMS ((struct frame_info *fi,
                                         struct frame_saved_regs *fsr));
+void d30v_frame_find_saved_regs_offsets PARAMS ((struct frame_info *fi,
+                                                struct frame_saved_regs *fsr));
 static void d30v_pop_dummy_frame PARAMS ((struct frame_info *fi));
 static void d30v_print_flags PARAMS ((void));
 static void print_flags_command PARAMS ((char *, int));
@@ -63,6 +65,7 @@ static void print_flags_command PARAMS ((char *, int));
 #define OP_ADD_SP_IMM          0x080bffc0 /* add sp,sp,imm */
 #define OP_ADD_R22_SP_IMM      0x08096fc0 /* add r22,sp,imm */
 #define OP_STW_FP_SP_IMM       0x054bdfc0 /* stw fp,@(sp,imm) */
+#define OP_OR_SP_R0_IMM                0x03abf000 /* or sp,r0,imm */
 
 /* no mask */
 #define OP_OR_FP_R0_SP         0x03a3d03f /* or fp,r0,sp */
@@ -293,6 +296,8 @@ d30v_skip_prologue (pc)
   return pc;
 }
 
+static int end_of_stack;
+
 /* Given a GDB frame, determine the address of the calling function's frame.
    This will be used to create a new GDB frame struct, and then
    INIT_EXTRA_FRAME_INFO and INIT_FRAME_PC will be called for the new frame.
@@ -306,6 +311,9 @@ d30v_frame_chain (frame)
 
   d30v_frame_find_saved_regs (frame, &fsr);
 
+  if (end_of_stack)
+    return (CORE_ADDR)0;
+
   if (frame->return_pc == IMEM_START)
     return (CORE_ADDR)0;
 
@@ -463,6 +471,13 @@ prologue_find_regs (op, fsr, addr)
       return 1;
     }
 
+  /* stw fp,@(sp,imm) -- observed */
+  if ((op & OP_MASK_ALL_BUT_IMM) == OP_STW_FP_SP_IMM)
+    {
+      offset = EXTRACT_IMM6(op);
+      fsr->regs[FP_REGNUM] = (offset - frame_size);
+      return 1;
+    }
   return 0;
 }
 
@@ -486,6 +501,60 @@ d30v_frame_find_saved_regs (fi, fsr)
   memset (fsr, 0, sizeof (*fsr));
   next_addr = 0;
   frame_size = 0;
+  end_of_stack = 0;
+
+  uses_frame = 0;
+
+  d30v_frame_find_saved_regs_offsets (fi, fsr);
+  
+  fi->size = frame_size;
+
+  if (!fp)
+    fp = read_register(SP_REGNUM);
+
+  for (i=0; i<NUM_REGS-1; i++)
+    if (fsr->regs[i])
+      {
+       fsr->regs[i] = fsr->regs[i] + fp + frame_size;
+      }
+
+  if (fsr->regs[LR_REGNUM])
+    fi->return_pc = read_memory_unsigned_integer(fsr->regs[LR_REGNUM],4);
+  else
+    fi->return_pc = read_register(LR_REGNUM);
+  
+  /* the SP is not normally (ever?) saved, but check anyway */
+  if (!fsr->regs[SP_REGNUM])
+    {
+      /* if the FP was saved, that means the current FP is valid, */
+      /* otherwise, it isn't being used, so we use the SP instead */
+      if (uses_frame)
+       fsr->regs[SP_REGNUM] = read_register(FP_REGNUM) + fi->size;
+      else
+       {
+         fsr->regs[SP_REGNUM] = fp + fi->size;
+         fi->frameless = 1;
+         fsr->regs[FP_REGNUM] = 0;
+       }
+    }
+}
+
+void
+d30v_frame_find_saved_regs_offsets (fi, fsr)
+     struct frame_info *fi;
+     struct frame_saved_regs *fsr;
+{
+  CORE_ADDR fp, pc;
+  unsigned long opl, opr;
+  unsigned long op1, op2;
+  unsigned long fm0, fm1;
+  int i;
+
+  fp = fi->frame;
+  memset (fsr, 0, sizeof (*fsr));
+  next_addr = 0;
+  frame_size = 0;
+  end_of_stack = 0;
 
   pc = get_pc_function_start (fi->pc);
 
@@ -531,6 +600,10 @@ d30v_frame_find_saved_regs (fi, fsr)
              fsr->regs[n] = (offset - frame_size);
              fsr->regs[n+1] = (offset - frame_size) + 4;
            }
+         else if ((opl & OP_MASK_ALL_BUT_IMM) == OP_OR_SP_R0_IMM)
+           {
+             end_of_stack = 1;
+           }
          else
            break;
        }
@@ -553,13 +626,12 @@ d30v_frame_find_saved_regs (fi, fsr)
       pc += 8;
     }
   
-  fi->size = frame_size;
-  if (!fp || !uses_frame)
 #if 0
-    fp = read_register(SP_REGNUM) | DMEM_START;
-#else
+  fi->size = frame_size;
+
+  if (!fp)
     fp = read_register(SP_REGNUM);
-#endif
+
   for (i=0; i<NUM_REGS-1; i++)
     if (fsr->regs[i])
       {
@@ -585,6 +657,7 @@ d30v_frame_find_saved_regs (fi, fsr)
          fsr->regs[FP_REGNUM] = 0;
        }
     }
+#endif
 }
 
 void
@@ -597,7 +670,26 @@ d30v_init_extra_frame_info (fromleaf, fi)
   if (fi->next && (fi->pc == 0))
     fi->pc = fi->next->return_pc; 
 
-  d30v_frame_find_saved_regs (fi, &dummy);
+  d30v_frame_find_saved_regs_offsets (fi, &dummy);
+
+  if (uses_frame == 0)
+    fi->frameless = 1;
+  else
+    fi->frameless = 0;
+
+  if ((fi->next == 0) && (uses_frame == 0))
+    /* innermost frame and it's "frameless",
+       so the fi->frame field is wrong, fix it! */
+    fi->frame = read_sp ();
+
+  if (dummy.regs[LR_REGNUM])
+    {
+      /* it was saved, grab it! */
+      dummy.regs[LR_REGNUM] += (fi->frame + frame_size);
+      fi->return_pc = read_memory_unsigned_integer(dummy.regs[LR_REGNUM],4);
+    }
+  else
+    fi->return_pc = read_register(LR_REGNUM);
 }
 
 void
This page took 0.027016 seconds and 4 git commands to generate.