Thu Nov 7 15:19:08 1996 Martin M. Hunt <hunt@pizza.cygnus.com>
authorMartin Hunt <hunt@redhat.com>
Thu, 7 Nov 1996 23:23:57 +0000 (23:23 +0000)
committerMartin Hunt <hunt@redhat.com>
Thu, 7 Nov 1996 23:23:57 +0000 (23:23 +0000)
* d10v-tdep.c: Fix some problems with inferior function calls.
* config/d10v/tm-d10v.h (EXTRA_FRAME_INFO): Change dummy to be
a pointer to the dummy's stack instead of just a flag.

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

index 2e0a8f4..9a5a10e 100644 (file)
@@ -1,3 +1,11 @@
+start-sanitize-d10v
+Thu Nov  7 15:19:08 1996  Martin M. Hunt  <hunt@pizza.cygnus.com>
+
+       * d10v-tdep.c: Fix some problems with inferior function calls.
+       * config/d10v/tm-d10v.h (EXTRA_FRAME_INFO): Change dummy to be
+       a pointer to the dummy's stack instead of just a flag.
+       
+end-sanitize-d10v      
 start-sanitize-m32r
 Tue Nov  5 10:21:02 1996  Michael Snyder  <msnyder@cleaver.cygnus.com>
 
index 9fe4825..bac6410 100644 (file)
@@ -154,7 +154,7 @@ extern CORE_ADDR d10v_skip_prologue ();
 
 #define EXTRA_FRAME_INFO \
     CORE_ADDR return_pc; \
-    int dummy; \
+    CORE_ADDR dummy; \
     int frameless; \
     int size;
 
index be4c5de..7920c4f 100644 (file)
@@ -502,7 +502,7 @@ d10v_fix_call_dummy (dummyname, start_sp, fun, nargs, args, type, gcc_p)
   CORE_ADDR sp;
   char buffer[MAX_REGISTER_RAW_SIZE];
   struct frame_info *frame = get_current_frame ();
-  frame->dummy = 1;
+  frame->dummy = start_sp;
   start_sp |= DMEM_START;
 
   sp = start_sp;
@@ -522,18 +522,15 @@ static void
 d10v_pop_dummy_frame (fi)
      struct frame_info *fi;
 {
-  CORE_ADDR sp = fi->frame;
+  CORE_ADDR sp = fi->dummy;
   int regnum;
 
-  for (regnum = NUM_REGS-1; regnum >= 0; regnum--)
+  for (regnum = 0; regnum < NUM_REGS; regnum++)
     {
+      sp -= REGISTER_RAW_SIZE(regnum);
       write_register(regnum, read_memory_unsigned_integer (sp, REGISTER_RAW_SIZE(regnum)));
-      sp += REGISTER_RAW_SIZE(regnum);
     }
-  target_store_registers (-1);
-  flush_cached_frames ();
-
-  write_register(SP_REGNUM, sp & 0xffff);
+  flush_cached_frames (); /* needed? */
 }
 
 
@@ -545,36 +542,76 @@ d10v_push_arguments (nargs, args, sp, struct_return, struct_addr)
      int struct_return;
      CORE_ADDR struct_addr;
 {
-  int i, len, regnum=2;
-  char *contents;
+  int i, len, index=0, regnum=2;
+  char buffer[4], *contents;
   LONGEST val;
-  
+  CORE_ADDR ptrs[10];
+
+  /* Pass 1. Put all large args on stack */
   for (i = 0; i < nargs; i++)
     {
       value_ptr arg = args[i];
       struct type *arg_type = check_typedef (VALUE_TYPE (arg));
-      switch (TYPE_CODE (arg_type))
-        {
-       case TYPE_CODE_INT:
-       case TYPE_CODE_BOOL:
-       case TYPE_CODE_CHAR:
-       case TYPE_CODE_RANGE:
-       case TYPE_CODE_ENUM:
-         break;
-       default:
-         break;
+      len = TYPE_LENGTH (arg_type);
+      contents = VALUE_CONTENTS(arg);
+      val = extract_signed_integer (contents, len);
+      if (len > 4)
+       {
+         /* put on stack and pass pointers */
+         sp -= len;
+         write_memory (sp, contents, len);
+         ptrs[index++] = sp;
        }
+    }
+
+  index = 0;
+
+  for (i = 0; i < nargs; i++)
+    {
+      value_ptr arg = args[i];
+      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)
-       write_register (regnum++, val>>16);
-      write_register (regnum++, val & 0xffff);
+      if (len > 4)
+       {
+         /* use a pointer to previously saved data */
+         if (regnum < 6)
+           write_register (regnum++, ptrs[index++]);
+         else
+           {
+             /* no more registers available.  put it on the stack */
+             sp -= 2;
+             store_address (buffer, 2, ptrs[index++]);
+             write_memory (sp, buffer, 2);
+           }
+       }
+      else
+       {
+         if (regnum < 6 )
+           {
+             if (len == 4)
+               write_register (regnum++, val>>16);
+             write_register (regnum++, val & 0xffff);
+           }
+         else
+           {
+             sp -= len;
+             store_address (buffer, len, val);
+             write_memory (sp, buffer, len);
+           }
+       }
     }
   return sp;
 }
 
 
+/* pick an out-of-the-way place to set the return value */
+/* for an inferior function call.  The link register is set to this  */
+/* value and a momentary breakpoint is set there.  When the breakpoint */
+/* is hit, the dummy frame is popped and the previous environment is */
+/* restored. */
+
 CORE_ADDR
 d10v_call_dummy_address ()
 {
@@ -603,5 +640,5 @@ d10v_extract_return_value (valtype, regbuf, valbuf)
      char regbuf[REGISTER_BYTES];
      char *valbuf;
 {
 memcpy (valbuf, regbuf + REGISTER_BYTE (2), TYPE_LENGTH (valtype));
+ memcpy (valbuf, regbuf + REGISTER_BYTE (2), TYPE_LENGTH (valtype));
 }