Thu May 21 13:14:25 1998 John Metzler <jmetzler@cygnus.com>
[deliverable/binutils-gdb.git] / gdb / d30v-tdep.c
index 50b3d0d0c5d7f8df076a5e72b617a9736f4e048d..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;
 
@@ -320,7 +328,7 @@ d30v_frame_chain (frame)
   if (!read_memory_unsigned_integer(fsr.regs[FP_REGNUM],4))
     return (CORE_ADDR)0;
 
-  return read_memory_unsigned_integer(fsr.regs[FP_REGNUM],4)| DMEM_START;
+  return read_memory_unsigned_integer(fsr.regs[FP_REGNUM],4);
 }  
 
 static int next_addr, uses_frame;
@@ -440,16 +448,16 @@ prologue_find_regs (op, fsr, addr)
   if ((op & OP_MASK_ALL_BUT_IMM) == OP_SUB_SP_IMM)
     {
       offset = EXTRACT_IMM6(op);
-      next_addr -= offset;
+      frame_size += -offset;
       return 1;
     }
 
-  /* st  rn, @(sp,0) */
+  /* st  rn, @(sp,0) -- observed */
   if (((op & OP_MASK_ALL_BUT_RA) == OP_STW_SP_R0) ||
       ((op & OP_MASK_ALL_BUT_RA) == OP_STW_SP_IMM0))
     {
       n = EXTRACT_RA(op);
-      fsr->regs[n] = next_addr;
+      fsr->regs[n] = (- frame_size);
       return 1;
     }
 
@@ -458,11 +466,18 @@ prologue_find_regs (op, fsr, addr)
       ((op & OP_MASK_ALL_BUT_RA) == OP_ST2W_SP_IMM0))
     {
       n = EXTRACT_RA(op);
-      fsr->regs[n] = next_addr;
-      fsr->regs[n+1] = next_addr+4;
+      fsr->regs[n] = (- frame_size);
+      fsr->regs[n+1] = (- frame_size) + 4;
       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,11 +501,65 @@ 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);
 
   uses_frame = 0;
-  while (1)
+  while (pc < fi->pc)
     {
       opl = (unsigned long)read_memory_integer (pc, 4);
       opr = (unsigned long)read_memory_integer (pc+4, 4);
@@ -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;
     }
   
+#if 0
   fi->size = frame_size;
+
   if (!fp)
-#if 0
-    fp = read_register(SP_REGNUM) | DMEM_START;
-#else
     fp = read_register(SP_REGNUM);
-#endif
+
   for (i=0; i<NUM_REGS-1; i++)
     if (fsr->regs[i])
       {
@@ -571,7 +643,7 @@ d30v_frame_find_saved_regs (fi, fsr)
   else
     fi->return_pc = read_register(LR_REGNUM);
   
-  /* th SP is not normally (ever?) saved, but check anyway */
+  /* 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, */
@@ -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
@@ -861,27 +953,37 @@ d30v_push_arguments (nargs, args, sp, struct_return, struct_addr)
       struct type *arg_type = check_typedef (VALUE_TYPE (arg));
       len = TYPE_LENGTH (arg_type);
       contents = VALUE_CONTENTS(arg);
-      val = extract_signed_integer (contents, len);
       if (len > 4)
        {
          /* we need multiple registers */
          int ndx;
 
-         for (ndx = 0; ndx < len; ndx += 4, len -= 4)
+         for (ndx = 0; len > 0; ndx += 8, len -= 8)
            {
+             if (regnum & 1)
+               regnum++;       /* all args > 4 bytes start in even register */
+
              if (regnum < 18)
                {
-                 if (len > 4)
-                   val = extract_signed_integer (&contents[ndx], 4);
-                 else
-                   val = extract_signed_integer (&contents[ndx], len);
+                 val = extract_signed_integer (&contents[ndx], 4);
+                 write_register (regnum++, val);
 
+                 if (len >= 8)
+                   val = extract_signed_integer (&contents[ndx+4], 4);
+                 else
+                   val = extract_signed_integer (&contents[ndx+4], len-4);
                  write_register (regnum++, val);
                }
              else
                {
                  /* no more registers available.  put it on the stack */
-                 sp -= len;
+
+                 /* all args > 4 bytes are padded to a multiple of 8 bytes
+                  and start on an 8 byte boundary */
+                 if (sp & 7)
+                   sp -= (sp & 7); /* align it */
+
+                 sp -= ((len + 7) & ~7); /* allocate space */
                  write_memory (sp, &contents[ndx], len);
                  break;
                }
@@ -891,16 +993,20 @@ d30v_push_arguments (nargs, args, sp, struct_return, struct_addr)
        {
          if (regnum < 18 )
            {
+             val = extract_signed_integer (contents, len);
              write_register (regnum++, val);
            }
          else
            {
-             sp -= len;
-             store_address (buffer, len, val);
-             write_memory (sp, buffer, len);
+             /* all args are padded to a multiple of 4 bytes (at least) */
+             sp -= ((len + 3) & ~3);
+             write_memory (sp, contents, len);
            }
        }
     }
+  if (sp & 7)
+    /* stack pointer is not on an 8 byte boundary -- align it */
+    sp -= (sp & 7);
   return sp;
 }
 
This page took 0.02646 seconds and 4 git commands to generate.