* remote-mips.c: New file; implements MIPS remote debugging
authorIan Lance Taylor <ian@airs.com>
Mon, 22 Feb 1993 23:43:03 +0000 (23:43 +0000)
committerIan Lance Taylor <ian@airs.com>
Mon, 22 Feb 1993 23:43:03 +0000 (23:43 +0000)
protocol.
* config/idt.mt: New file; uses remote-mips.c
* configure.in (mips-idt-ecoff): New target; uses idt.mt.

* mips-tdep.c (mips_fpu): New variable; controls use of MIPS
floating point coprocessor.
(mips_push_dummy_frame): If not mips_fpu, don't save floating
point registers.
(mips_pop_frame): If not mips_fpu, don't restore floating point
registers.
(_initialize_mips_tdep): New function; let the user reset mips_fpu
variable.
* tm-mips.h (EXTRACT_RETURN_VALUE, STORE_RETURN_VALUE): If not
mips_fpu, don't use fp0 as floating point return register.
(FIX_CALL_DUMMY): If not mips_fpu, don't save floating point
registers.

Also added remote-mips.c to .Sanitize file.

gdb/.Sanitize
gdb/ChangeLog
gdb/config/.Sanitize
gdb/config/idt.mt [new file with mode: 0644]
gdb/configure.in
gdb/mips-tdep.c
gdb/remote-mips.c
gdb/tm-mips.h

index d4b358326bf653ee608fc7c42a813dd175eecddd..99ffba91595b2fe89500ccf6d6141adbd58951a9 100644 (file)
@@ -206,6 +206,7 @@ remote-adapt.c
 remote-eb.c
 remote-es1800.c
 remote-hms.c
+remote-mips.c
 remote-mm.c
 remote-nindy.c
 remote-sim.c
index e5146882947634bf484fd64643f6bcfcd3476978..3cb822a6f584c3600d44a63afcac26c208110b6e 100644 (file)
@@ -1,3 +1,23 @@
+Mon Feb 22 15:21:54 1993  Ian Lance Taylor  (ian@cygnus.com)
+
+       * remote-mips.c: New file; implements MIPS remote debugging
+       protocol.
+       * config/idt.mt: New file; uses remote-mips.c
+       * configure.in (mips-idt-ecoff): New target; uses idt.mt.
+
+       * mips-tdep.c (mips_fpu): New variable; controls use of MIPS
+       floating point coprocessor.
+       (mips_push_dummy_frame): If not mips_fpu, don't save floating
+       point registers.
+       (mips_pop_frame): If not mips_fpu, don't restore floating point
+       registers.
+       (_initialize_mips_tdep): New function; let the user reset mips_fpu
+       variable.
+       * tm-mips.h (EXTRACT_RETURN_VALUE, STORE_RETURN_VALUE): If not
+       mips_fpu, don't use fp0 as floating point return register.
+       (FIX_CALL_DUMMY): If not mips_fpu, don't save floating point
+       registers.
+
 Mon Feb 22 07:54:03 1993  Mike Werner  (mtw@poseidon.cygnus.com)
 
         * gdb/testsuite: made modifications to testcases, etc., to allow
index 50347bcdc3095f6317b3154163fad0a0d5ab774a..c5cbc26f36e403e037ab970aeb9e0c7733cf52a5 100644 (file)
@@ -66,6 +66,7 @@ i386v.mt
 i386v32.mh
 i386v4.mh
 i386v4.mt
+idt.mt
 irix3.mh
 irix3.mt
 irix4.mh
diff --git a/gdb/config/idt.mt b/gdb/config/idt.mt
new file mode 100644 (file)
index 0000000..d7fcecb
--- /dev/null
@@ -0,0 +1,3 @@
+# Target: Big-endian IDT board.
+TDEPFILES= mips-pinsn.o mips-tdep.o exec.o remote-mips.o
+TM_FILE= tm-bigmips.h
index 72bcdbd7c58c4e60ff92c072dd91072de6c08c39..0af76bf05965671da7dd7ea61998993a035bcf28 100644 (file)
@@ -171,6 +171,7 @@ m88k-*-*)           gdb_target=m88k ;;
 
 mips-big-*)            gdb_target=bigmips ;;
 mips-dec-*)            gdb_target=decstation ;;
+mips-idt-ecoff)                gdb_target=idt ;;
 mips-little-*)         gdb_target=littlemips ;;
 mips-sgi-*)            gdb_target=irix3 ;;
 mips-sony-*)           gdb_target=bigmips ;;
index 7f7d0f5b12dcce722a67935fef4e85b2c037bca3..3e6c7a4fc5c40fb97389a0d191aebd6e5519a76a 100644 (file)
@@ -1,5 +1,5 @@
 /* Target-dependent code for the MIPS architecture, for GDB, the GNU Debugger.
-   Copyright 1988, 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+   Copyright 1988, 1989, 1990, 1991, 1992, 1993 Free Software Foundation, Inc.
    Contributed by Alessandro Forin(af@cs.cmu.edu) at CMU
    and by Per Bothner(bothner@cs.wisc.edu) at U.Wisconsin.
 
@@ -55,6 +55,10 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
 #include <sys/stat.h>
 
 \f
+/* Some MIPS boards don't support floating point, so we permit the
+   user to turn it off.  */
+int mips_fpu = 1;
+
 #define PROC_LOW_ADDR(proc) ((proc)->pdr.adr) /* least address */
 #define PROC_HIGH_ADDR(proc) ((proc)->pdr.iline) /* upper address bound */
 #define PROC_FRAME_OFFSET(proc) ((proc)->pdr.frameoffset)
@@ -316,16 +320,13 @@ init_extra_frame_info(fci)
       /* r0 bit means kernel trap */
       int kernel_trap = PROC_REG_MASK(proc_desc) & 1;
 
-      if (fci->frame == 0)
-      {
-        /* Fixup frame-pointer - only needed for top frame */
-        /* This may not be quite right, if proc has a real frame register */
-        if (fci->pc == PROC_LOW_ADDR(proc_desc))
-          fci->frame = read_register (SP_REGNUM);
-        else
-         fci->frame = READ_FRAME_REG(fci, PROC_FRAME_REG(proc_desc))
-                      + PROC_FRAME_OFFSET(proc_desc);
-      }
+      /* Fixup frame-pointer - only needed for top frame */
+      /* This may not be quite right, if proc has a real frame register */
+      if (fci->pc == PROC_LOW_ADDR(proc_desc))
+       fci->frame = read_register (SP_REGNUM);
+      else
+       fci->frame = READ_FRAME_REG(fci, PROC_FRAME_REG(proc_desc))
+                     + PROC_FRAME_OFFSET(proc_desc);
 
       if (proc_desc == &temp_proc_desc)
          *fci->saved_regs = temp_saved_regs;
@@ -381,11 +382,14 @@ init_extra_frame_info(fci)
    arguments without difficulty.  */
 
 FRAME
-setup_arbitrary_frame (stack, pc)
-     FRAME_ADDR stack;
-     CORE_ADDR pc;
+setup_arbitrary_frame (argc, argv)
+     int argc;
+     FRAME_ADDR *argv;
 {
-  return create_new_frame (stack, pc);
+  if (argc != 2)
+    error ("MIPS frame specifications require two arguments: sp and pc");
+
+  return create_new_frame (argv[0], argv[1]);
 }
 
 
@@ -470,12 +474,12 @@ mips_push_dummy_frame()
    *    Saved D18 (i.e. F19, F18)
    *    ...
    *    Saved D0 (i.e. F1, F0)
-   *   CALL_DUMMY (subroutine stub; see m-mips.h)
+   *   CALL_DUMMY (subroutine stub; see tm-mips.h)
    *   Parameter build area (not yet implemented)
    *  (low memory)
    */
   PROC_REG_MASK(proc_desc) = GEN_REG_SAVE_MASK;
-  PROC_FREG_MASK(proc_desc) = FLOAT_REG_SAVE_MASK;
+  PROC_FREG_MASK(proc_desc) = mips_fpu ? FLOAT_REG_SAVE_MASK : 0;
   PROC_REG_OFFSET(proc_desc) = /* offset of (Saved R31) from FP */
       -sizeof(long) - 4 * SPECIAL_REG_SAVE_COUNT;
   PROC_FREG_OFFSET(proc_desc) = /* offset of (Saved D18) from FP */
@@ -507,9 +511,11 @@ mips_push_dummy_frame()
   write_memory (sp - 8, (char *)&buffer, sizeof(REGISTER_TYPE));
   buffer = read_register (LO_REGNUM);
   write_memory (sp - 12, (char *)&buffer, sizeof(REGISTER_TYPE));
-  buffer = read_register (FCRCS_REGNUM);
+  buffer = read_register (mips_fpu ? FCRCS_REGNUM : ZERO_REGNUM);
   write_memory (sp - 16, (char *)&buffer, sizeof(REGISTER_TYPE));
-  sp -= 4 * (GEN_REG_SAVE_COUNT+FLOAT_REG_SAVE_COUNT+SPECIAL_REG_SAVE_COUNT);
+  sp -= 4 * (GEN_REG_SAVE_COUNT
+            + (mips_fpu ? FLOAT_REG_SAVE_COUNT : 0)
+            + SPECIAL_REG_SAVE_COUNT);
   write_register (SP_REGNUM, sp);
   PROC_LOW_ADDR(proc_desc) = sp - CALL_DUMMY_SIZE + CALL_DUMMY_START_OFFSET;
   PROC_HIGH_ADDR(proc_desc) = sp;
@@ -568,7 +574,8 @@ mips_pop_frame()
 
       write_register (HI_REGNUM, read_memory_integer(new_sp - 8, 4));
       write_register (LO_REGNUM, read_memory_integer(new_sp - 12, 4));
-      write_register (FCRCS_REGNUM, read_memory_integer(new_sp - 16, 4));
+      if (mips_fpu)
+       write_register (FCRCS_REGNUM, read_memory_integer(new_sp - 16, 4));
     }
 }
 
@@ -686,7 +693,11 @@ isa_NAN(p, len)
     }
   else if (len == 8)
     {
+#if TARGET_BYTE_ORDER == BIG_ENDIAN
+      exponent = *p;
+#else
       exponent = *(p+1);
+#endif
       exponent = exponent << 1 >> (32 - DOUBLE_EXP_BITS - 1);
       return ((exponent == -1) || (! exponent && *p * *(p+1)));
     }
@@ -739,3 +750,17 @@ mips_skip_prologue(pc)
 
     return pc;
 }
+
+/* Let the user turn off floating point.  */
+
+void
+_initialize_mips_tdep ()
+{
+  add_show_from_set
+    (add_set_cmd ("mips_fpu", class_support, var_boolean,
+                 (char *) &mips_fpu,
+                 "Set use of floating point coprocessor.\n\
+Turn off to avoid using floating point instructions when calling functions\n\
+or dealing with return values.", &setlist),
+     &showlist);
+}
index 6c559f1752f2460cd0ee4979c314532dbec290e6..73a653c25464048567ff588d6e51a7aadade3028 100644 (file)
@@ -48,7 +48,7 @@ static int mips_cksum PARAMS ((const unsigned char *hdr,
                               int len));
 
 static void
-mips_send_packet PARAMS ((const char *s));
+mips_send_packet PARAMS ((const char *s, int get_ack));
 
 static int
 mips_receive_packet PARAMS ((char *buff));
@@ -57,6 +57,9 @@ static int
 mips_request PARAMS ((char cmd, unsigned int addr, unsigned int data,
                      int *perr));
 
+static void
+mips_initialize PARAMS ((void));
+
 static void
 mips_open PARAMS ((char *name, int from_tty));
 
@@ -246,6 +249,9 @@ extern struct target_ops mips_ops;
 /* Set to 1 if the target is open.  */
 static int mips_is_open;
 
+/* Set to 1 while the connection is being initialized.  */
+static int mips_initializing;
+
 /* The next sequence number to send.  */
 static int mips_send_seq;
 
@@ -263,7 +269,7 @@ static int mips_send_retries = 10;
 static int mips_syn_garbage = 1050;
 
 /* The time to wait for a packet, in seconds.  */
-static int mips_receive_wait = 30;
+static int mips_receive_wait = 5;
 
 /* Set if we have sent a packet to the board but have not yet received
    a reply.  */
@@ -273,13 +279,25 @@ static int mips_need_reply = 0;
 static int mips_debug = 0;
 
 /* Read a character from the remote, aborting on error.  Returns -2 on
-   timeout (since that's what serial_readchar returns).  */
+   timeout (since that's what serial_readchar returns).  FIXME: If we
+   see the string "<IDT>" from the board, then we are debugging on the
+   main console port, and we have somehow dropped out of remote
+   debugging mode.  In this case, we automatically go back in to
+   remote debugging mode.  This is a hack, put in because I can't find
+   any way for a program running on the remote board to terminate
+   without also ending remote debugging mode.  I assume users won't
+   have any trouble with this; for one thing, the IDT documentation
+   generally assumes that the remote debugging port is not the console
+   port.  This is, however, very convenient for DejaGnu when you only
+   have one connected serial port.  */
 
 static int
 mips_readchar (timeout)
      int timeout;
 {
   int ch;
+  static int state = 0;
+  static char nextstate[5] = { '<', 'I', 'D', 'T', '>' };
 
   ch = serial_readchar (timeout);
   if (ch == EOF)
@@ -293,6 +311,34 @@ mips_readchar (timeout)
       else
        printf_filtered ("Timed out in read\n");
     }
+
+  /* If we have seen <IDT> and we either time out, or we see a @
+     (which was echoed from a packet we sent), reset the board as
+     described above.  The first character in a packet after the SYN
+     (which is not echoed) is always an @ unless the packet is more
+     than 64 characters long, which ours never are.  */
+  if ((ch == -2 || ch == '@')
+      && state == 5
+      && ! mips_initializing)
+    {
+      if (mips_debug > 0)
+       printf_filtered ("Reinitializing MIPS debugging mode\n");
+      serial_write ("\rdb tty0\r", sizeof "\rdb tty0\r" - 1);
+      sleep (1);
+
+      mips_need_reply = 0;
+      mips_initialize ();
+
+      state = 0;
+
+      error ("Remote board reset");
+    }
+
+  if (ch == nextstate[state])
+    ++state;
+  else
+    state = 0;
+
   return ch;
 }
 
@@ -327,7 +373,11 @@ mips_receive_header (hdr, pgarbage, ch, timeout)
                 what the program is outputting, if the debugging is
                 being done on the console port.  FIXME: Perhaps this
                 should be filtered?  */
-             putchar (ch);
+             if (! mips_initializing || mips_debug > 0)
+               {
+                 putchar (ch);
+                 fflush (stdout);
+               }
 
              ++*pgarbage;
              if (*pgarbage > mips_syn_garbage)
@@ -416,8 +466,9 @@ mips_cksum (hdr, data, len)
 /* Send a packet containing the given ASCII string.  */
 
 static void
-mips_send_packet (s)
+mips_send_packet (s, get_ack)
      const char *s;
+     int get_ack;
 {
   unsigned int len;
   unsigned char *packet;
@@ -446,6 +497,9 @@ mips_send_packet (s)
      the sequence number we expect in the acknowledgement.  */
   mips_send_seq = (mips_send_seq + 1) % SEQ_MODULOS;
 
+  if (! get_ack)
+    return;
+
   /* We can only have one outstanding data packet, so we just wait for
      the acknowledgement here.  Keep retransmitting the packet until
      we get one, or until we've tried too many times.  */
@@ -728,7 +782,7 @@ mips_request (cmd, addr, data, perr)
       if (mips_need_reply)
        fatal ("mips_request: Trying to send command before reply");
       sprintf (buff, "0x0 %c 0x%x 0x%x", cmd, addr, data);
-      mips_send_packet (buff);
+      mips_send_packet (buff, 1);
       mips_need_reply = 1;
     }
 
@@ -766,6 +820,64 @@ mips_request (cmd, addr, data, perr)
   return rresponse;
 }
 
+/* Initialize a new connection to the MIPS board, and make sure we are
+   really connected.  */
+
+static void
+mips_initialize ()
+{
+  char cr;
+  int hold_wait;
+  int tries;
+  char buff[DATA_MAXLEN + 1];
+  int err;
+
+  if (mips_initializing)
+    return;
+
+  mips_initializing = 1;
+
+  mips_send_seq = 0;
+  mips_receive_seq = 0;
+
+  /* The board seems to want to send us a packet.  I don't know what
+     it means.  The packet seems to be triggered by a carriage return
+     character, although perhaps any character would do.  */
+  cr = '\r';
+  serial_write (&cr, 1);
+
+  hold_wait = mips_receive_wait;
+  mips_receive_wait = 3;
+
+  tries = 0;
+  while (catch_errors (mips_receive_packet, buff, (char *) NULL) == 0)
+    {
+      char cc;
+
+      if (tries > 0)
+       error ("Could not connect to target");
+      ++tries;
+
+      /* We did not receive the packet we expected; try resetting the
+        board and trying again.  */
+      printf_filtered ("Failed to initialize; trying to reset board\n");
+      cc = '\003';
+      serial_write (&cc, 1);
+      sleep (2);
+      serial_write ("\rdb tty0\r", sizeof "\rdb tty0\r" - 1);
+      sleep (1);
+      cr = '\r';
+      serial_write (&cr, 1);
+    }
+
+  mips_receive_wait = hold_wait;
+  mips_initializing = 0;
+
+  /* If this doesn't call error, we have connected; we don't care if
+     the request itself succeeds or fails.  */
+  mips_request ('r', (unsigned int) 0, (unsigned int) 0, &err);
+}
+
 /* Open a connection to the remote board.  */
 
 static void
@@ -773,10 +885,6 @@ mips_open (name, from_tty)
      char *name;
      int from_tty;
 {
-  int err;
-  char cr;
-  char buff[DATA_MAXLEN + 1];
-
   if (name == 0)
     error (
 "To open a MIPS remote debugging connection, you need to specify what serial\n\
@@ -785,28 +893,20 @@ device is attached to the target board (e.g., /dev/ttya).");
   target_preopen (from_tty);
 
   if (mips_is_open)
-    mips_close (0);
+    unpush_target (&mips_ops);
 
   if (serial_open (name) == 0)
     perror_with_name (name);
 
   mips_is_open = 1;
 
-  /* The board seems to want to send us a packet.  I don't know what
-     it means.  */
-  cr = '\r';
-  serial_write (&cr, 1);
-  mips_receive_packet (buff);
-
-  /* If this doesn't call error, we have connected; we don't care if
-     the request itself succeeds or fails.  */
-  mips_request ('r', (unsigned int) 0, (unsigned int) 0, &err);
+  mips_initialize ();
 
   if (from_tty)
     printf ("Remote MIPS debugging using %s\n", name);
   push_target (&mips_ops);     /* Switch to using remote target now */
 
-  start_remote ();             /* Initialize gdb process mechanisms */
+  /* FIXME: Should we call start_remote here?  */
 }
 
 /* Close a connection to the remote board.  */
@@ -817,11 +917,14 @@ mips_close (quitting)
 {
   if (mips_is_open)
     {
+      int err;
+
+      mips_is_open = 0;
+
       /* Get the board out of remote debugging mode.  */
-      mips_request ('x', (unsigned int) 0, (unsigned int) 0,
-                   (int *) NULL);
+      mips_request ('x', (unsigned int) 0, (unsigned int) 0, &err);
+
       serial_close ();
-      mips_is_open = 0;
     }
 }
 
@@ -852,7 +955,7 @@ mips_resume (step, siggnal)
           siggnal);
 
   mips_request (step ? 's' : 'c',
-               (unsigned int) read_register (PC_REGNUM),
+               (unsigned int) 1,
                (unsigned int) 0,
                (int *) NULL);
 }
@@ -1099,6 +1202,28 @@ mips_files_info (ignore)
   printf ("Debugging a MIPS board over a serial line.\n");
 }
 
+/* Kill the process running on the board.  This will actually only
+   work if we are doing remote debugging over the console input.  I
+   think that if IDT/sim had the remote debug interrupt enabled on the
+   right port, we could interrupt the process with a break signal.  */
+
+static void
+mips_kill ()
+{
+#if 0
+  if (mips_is_open)
+    {
+      char cc;
+
+      /* Send a ^C.  */
+      cc = '\003';
+      serial_write (&cc, 1);
+      sleep (1);
+      target_mourn_inferior ();
+    }
+#endif
+}
+
 /* Load an executable onto the board.  */
 
 static void
@@ -1109,6 +1234,7 @@ mips_load (args, from_tty)
   bfd *abfd;
   asection *s;
   int err;
+  CORE_ADDR text;
 
   abfd = bfd_openr (args, 0);
   if (abfd == (bfd *) NULL)
@@ -1117,6 +1243,7 @@ mips_load (args, from_tty)
   if (bfd_check_format (abfd, bfd_object) == 0)
     error ("%s: Not an object file", args);
 
+  text = UINT_MAX;
   for (s = abfd->sections; s != (asection *) NULL; s = s->next)
     {
       if ((s->flags & SEC_LOAD) != 0)
@@ -1140,6 +1267,10 @@ mips_load (args, from_tty)
              mips_xfer_memory (vma, buffer, size, 1, &mips_ops);
 
              do_cleanups (old_chain);
+
+             if ((bfd_get_section_flags (abfd, s) & SEC_CODE) != 0
+                 && vma < text)
+               text = vma;
            }
        }
     }
@@ -1152,7 +1283,13 @@ mips_load (args, from_tty)
 
   bfd_close (abfd);
 
-  /* FIXME: Should we call symbol_file_add here?  */
+  /* FIXME: Should we call symbol_file_add here?  The local variable
+     text exists just for this call.  Making the call seems to confuse
+     gdb if more than one file is loaded in.  Perhaps passing MAINLINE
+     as 1 would fix this, but it's not clear that that is correct
+     either since it is possible to load several files onto the board.
+
+     symbol_file_add (args, from_tty, text, 0, 0, 0);  */
 }
 
 /* Start running on the target board.  */
@@ -1165,7 +1302,6 @@ mips_create_inferior (execfile, args, env)
 {
   CORE_ADDR entry_pt;
 
-  /* FIXME: Actually, we probably could pass arguments.  */
   if (args && *args)
     error ("Can't pass arguments to remote MIPS board.");
 
@@ -1176,6 +1312,8 @@ mips_create_inferior (execfile, args, env)
 
   init_wait_for_inferior ();
 
+  /* FIXME: Should we set inferior_pid here?  */
+
   proceed (entry_pt, -1, 0);
 }
 
@@ -1213,7 +1351,7 @@ Specify the serial device it is connected to (e.g., /dev/ttya).",  /* to_doc */
   NULL,                                /* to_terminal_ours_for_output */
   NULL,                                /* to_terminal_ours */
   NULL,                                /* to_terminal_info */
-  NULL,                                /* to_kill */
+  mips_kill,                   /* to_kill */
   mips_load,                   /* to_load */
   NULL,                                /* to_lookup_symbol */
   mips_create_inferior,                /* to_create_inferior */
index 0075662b52aca7dedabe8b2168a0e1d1864220a6..9096b06f571bca2b18f1245c0195ebbfd15f62cd 100644 (file)
@@ -34,6 +34,11 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
 /* Floating point is IEEE compliant */
 #define IEEE_FLOAT
 
+/* Some MIPS boards are provided both with and without a floating
+   point coprocessor; we provide a user settable variable to tell gdb
+   whether there is one or not.  */
+extern int mips_fpu;
+
 /* Define this if the C compiler puts an underscore at the front
    of external names before giving them to the linker.  */
 
@@ -205,13 +210,13 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
    into VALBUF.  XXX floats */
 
 #define EXTRACT_RETURN_VALUE(TYPE,REGBUF,VALBUF) \
-  bcopy (REGBUF+REGISTER_BYTE (TYPE_CODE (TYPE) == TYPE_CODE_FLT ? FP0_REGNUM : 2), VALBUF, TYPE_LENGTH (TYPE))
+  bcopy (REGBUF + REGISTER_BYTE ((TYPE_CODE (TYPE) == TYPE_CODE_FLT && mips_fpu) ? FP0_REGNUM : 2), VALBUF, TYPE_LENGTH (TYPE))
 
 /* Write into appropriate registers a function return value
    of type TYPE, given in virtual format.  */
 
 #define STORE_RETURN_VALUE(TYPE,VALBUF) \
-  write_register_bytes (REGISTER_BYTE (TYPE_CODE (TYPE) == TYPE_CODE_FLT ? FP0_REGNUM : 2), VALBUF, TYPE_LENGTH (TYPE))
+  write_register_bytes (REGISTER_BYTE ((TYPE_CODE (TYPE) == TYPE_CODE_FLT && mips_fpu) ? FP0_REGNUM : 2), VALBUF, TYPE_LENGTH (TYPE))
 
 /* Extract from an array REGBUF containing the (raw) register state
    the address in which a function should return its structure value,
@@ -294,11 +299,11 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
  0,                            /* nop    #  ... to stop raw backtrace*/\
  0x27bd0000,                   /* addu sp,?0 # Pseudo prologue */\
 /* Start here: */\
- MK_OP(061,SP_REGNUM,12,0),    /* lwc1 $f12,0(sp) # Reload first 4 args*/\
+ MK_OP(061,SP_REGNUM,12,0),    /* lwc1 $f12,0(sp) # Reload FP regs*/\
  MK_OP(061,SP_REGNUM,13,4),    /* lwc1 $f13,4(sp) */\
  MK_OP(061,SP_REGNUM,14,8),    /* lwc1 $f14,8(sp) */\
  MK_OP(061,SP_REGNUM,15,12),   /* lwc1 $f15,12(sp) */\
- MK_OP(043,SP_REGNUM,4,0),     /* lw $r4,0(sp) # Re-load FP regs*/\
+ MK_OP(043,SP_REGNUM,4,0),     /* lw $r4,0(sp) # Reload first 4 args*/\
  MK_OP(043,SP_REGNUM,5,4),     /* lw $r5,4(sp) */\
  MK_OP(043,SP_REGNUM,6,8),     /* lw $r6,8(sp) */\
  MK_OP(043,SP_REGNUM,7,12),    /* lw $r7,12(sp) */\
@@ -315,8 +320,19 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
    into a call sequence of the above form stored at DUMMYNAME.  */
 
 #define FIX_CALL_DUMMY(dummyname, start_sp, fun, nargs,        args, rettype, gcc_p)\
-  (((int*)dummyname)[11] |= (((unsigned long)(fun)) >> 16), \
-   ((int*)dummyname)[12] |= (unsigned short)(fun))
+  do \
+    { \
+      ((int*)(dummyname))[11] |= ((unsigned long)(fun)) >> 16; \
+      ((int*)(dummyname))[12] |= (unsigned short)(fun); \
+      if (! mips_fpu) \
+       { \
+         ((int *) (dummyname))[3] = 0; \
+         ((int *) (dummyname))[4] = 0; \
+         ((int *) (dummyname))[5] = 0; \
+         ((int *) (dummyname))[6] = 0; \
+       } \
+    } \
+  while (0)
 
 /* There's a mess in stack frame creation.  See comments in blockframe.c
    near reference to INIT_FRAME_PC_FIRST.  */