* configure.in (hppa*-*-*): Also configure and build stabs-only
[deliverable/binutils-gdb.git] / gdb / remote-udi.c
index 09572589c550f30ecf277c914be3bd0a4c9cdd9a..d4c634e7cbd8b639c2efa48e502024e3b114c657 100644 (file)
@@ -1,27 +1,13 @@
-/* 
- - Remote debugging interface for Am290*0 running MiniMON monitor, for GDB.
-   This is like remote.c but expects MiniMON to be running on the Am29000 
-   target hardware.
- - Originally written by Daniel Mann at AMD for gdb 3.91.6.
- - David Wood (wood@lab.ultra.nyu.edu) at New York University adapted this
-       file to gdb 3.95.  I was unable to get this working on sun3os4
-       with termio, only with sgtty.  Because we are only attempting to
-       use this module to debug our kernel, which is already loaded when
-       gdb is started up, I did not code up the file downloading facilities.  
-       As a result this module has only the stubs to download files. 
-       You should get tagged at compile time if you need to make any 
-       changes/additions.
-*- Daniel Mann at AMD took the 3.95 adaptions above and replaced
-       MiniMON interface with UDI-p interface.
-   Copyright (C) 1990 Free Software Foundation, Inc.
+/* Remote debugging interface for AMD 29k interfaced via UDI, for GDB.
+   Copyright 1990, 1992 Free Software Foundation, Inc.
+   Written by Daniel Mann.  Contributed by AMD.
 
 This file is part of GDB.
 
 This program is free software; you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 1, or (at your option)
-any later version.
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
 
 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -29,11 +15,22 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
-along with this program; see the file COPYING.  If not, write to
-the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
 
+/* This is like remote.c but uses the Universal Debug Interface (UDI) to 
+   talk to the target hardware (or simulator).  UDI is a TCP/IP based
+   protocol; for hardware that doesn't run TCP, an interface adapter 
+   daemon talks UDI on one side, and talks to the hardware (typically
+   over a serial port) on the other side.
 
-#include <stdio.h>
+ - Originally written by Daniel Mann at AMD for MiniMON and gdb 3.91.6.
+ - David Wood (wood@lab.ultra.nyu.edu) at New York University adapted this
+       file to gdb 3.95.  I was unable to get this working on sun3os4
+       with termio, only with sgtty.
+ - Daniel Mann at AMD took the 3.95 adaptions above and replaced
+       MiniMON interface with UDI-p interface.   */
 #include "defs.h"
 #include "inferior.h"
 #include "wait.h"
@@ -46,51 +43,33 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
 #include "terminal.h"
 #include "target.h"
 #include "29k-share/udi/udiproc.h"
+#include "gdbcmd.h"
+#include "bfd.h"
+#include "gdbcore.h" /* For download function */
 
 /* access the register store directly, without going through
-   the normal handler functions. This avoids an extra data copy
-*/
-
-/* #define DEBUG 1             /* */
-#ifdef DEBUG 
-# define DENTER(NAME)  (printf("Entering %s\n",NAME), fflush(stdout)) 
-# define DEXIT(NAME)   (printf("Exiting  %s\n",NAME), fflush(stdout))
-#else
-# define DENTER(NAME)  
-# define DEXIT(NAME)   
-#endif 
-
+   the normal handler functions. This avoids an extra data copy.  */
 
 extern int stop_soon_quietly;           /* for wait_for_inferior */
 extern struct value *call_function_by_hand();
-static void udi_resume();
-static void udi_fetch_registers ();
-static void udi_load();
-static int fetch_register ();
-static void udi_store_registers ();
-static int store_register ();
-static int regnum_to_srnum();
-static void  udi_close ();
-static CPUSpace udi_memory_space();
-static int udi_write_inferior_memory();
-static int udi_read_inferior_memory();
+static void udi_resume PARAMS ((int pid, int step, enum target_signal sig));
+static void udi_fetch_registers PARAMS ((int regno));
+static void udi_load PARAMS ((char *args, int from_tty));
+static void fetch_register PARAMS ((int regno));
+static void udi_store_registers PARAMS ((int regno));
+static int store_register PARAMS ((int regno));
+static int regnum_to_srnum PARAMS ((int regno));
+static void udi_close PARAMS ((int quitting));
+static CPUSpace udi_memory_space PARAMS ((CORE_ADDR addr));
+static int udi_write_inferior_memory PARAMS ((CORE_ADDR memaddr, char *myaddr,
+                                             int len));
+static int udi_read_inferior_memory PARAMS ((CORE_ADDR memaddr, char *myaddr,
+                                            int len));
+static void download PARAMS ((char *load_arg_string, int from_tty));
 char   CoffFileName[100] = "";
-/*
- * Processor types. 
- */
-#define TYPE_UNKNOWN    0
-#define TYPE_A29000     1
-#define TYPE_A29030     2
-#define TYPE_A29050     3
-static  char *processor_name[] = { "Unknown", "Am29000", "Am29030", "Am29050" };
-static  int processor_type=TYPE_UNKNOWN;
-#define FREEZE_MODE     (read_register(CPS_REGNUM) && 0x400)
-#define USE_SHADOW_PC  ((processor_type == TYPE_A29050) && FREEZE_MODE) 
-
-#define LLOG_FILE "udi.log"
-#if defined (LOG_FILE)
-FILE *log_file;
-#endif
+
+#define FREEZE_MODE     (read_register(CPS_REGNUM) & 0x400)
+#define USE_SHADOW_PC  ((processor_type == a29k_freeze_mode) && FREEZE_MODE)
 
 static int timeout = 5;
 extern struct target_ops udi_ops;             /* Forward declaration */
@@ -103,16 +82,21 @@ extern struct target_ops udi_ops;             /* Forward declaration */
 /* Descriptor for I/O to remote machine.  Initialize it to -1 so that
    udi_open knows that we don't have a file open when the program
    starts.  */
-  UDISessionId udi_session_id = -1;
 
-  CPUOffset    IMemStart = 0;
-  CPUSizeT     IMemSize = 0;
-  CPUOffset    DMemStart = 0;
-  CPUSizeT     DMemSize = 0;
-  CPUOffset    RMemStart = 0;
-  CPUSizeT     RMemSize = 0;
-  UDIUInt32    CPUPRL;
-  UDIUInt32    CoProcPRL;
+UDISessionId udi_session_id = -1;
+
+CPUOffset IMemStart = 0;
+CPUSizeT IMemSize = 0;
+CPUOffset DMemStart = 0;
+CPUSizeT DMemSize = 0;
+CPUOffset RMemStart = 0;
+CPUSizeT RMemSize = 0;
+UDIUInt32 CPUPRL;
+UDIUInt32 CoProcPRL;
+
+UDIMemoryRange address_ranges[2]; /* Text and data */
+UDIResource entry = {0, 0};    /* Entry point */
+CPUSizeT stack_sizes[2];       /* Regular and memory stacks */
 
 #define        SBUF_MAX        1024    /* maximum size of string handling buffer */
 char sbuf[SBUF_MAX];
@@ -128,98 +112,93 @@ typedef   struct  bkpt_entry_str
 static bkpt_entry_t    bkpt_table[BKPT_TABLE_SIZE];
 extern char    dfe_errmsg[];           /* error string */
 
-/*********************************************************** SIGNAL SUPPORT */
-/* Called when SIGALRM signal sent due to alarm() timeout.  */
-#ifndef HAVE_TERMIO
-
-#ifndef __STDC__
-# ifndef volatile
-#  define volatile /**/
-# endif
-#endif
-volatile int n_alarms;
-
-static void
-udi_timer ()
-{
-#if 0
-  if (kiodebug)
-    printf ("udi_timer called\n");
-#endif
-  n_alarms++;
-}
-#endif /* HAVE_TERMIO */
-
 /* malloc'd name of the program on the remote system.  */
 static char *prog_name = NULL;
 
-
-/* Number of SIGTRAPs we need to simulate.  That is, the next
-   NEED_ARTIFICIAL_TRAP calls to udi_wait should just return
-   SIGTRAP without actually waiting for anything.  */
-
-/******************************************************* UDI_CREATE_INFERIOR */
 /* This is called not only when we first attach, but also when the
    user types "run" after having attached.  */
+
 static void
 udi_create_inferior (execfile, args, env)
      char *execfile;
      char *args;
      char **env;
 {
-  DENTER("udi_create_inferior()");
+  char *args1;
 
   if (execfile)
-  { if (prog_name != NULL)
-       free (prog_name);
-    prog_name = savestring (execfile, strlen (execfile));
-  }
-
-  if (prog_name == 0 /* || exec_bfd == 0 */ )
-    error ("No exec file specified");
+    {
+      if (prog_name != NULL)
+       free (prog_name);
+      prog_name = savestring (execfile, strlen (execfile));
+    }
+  else if (entry.Offset)
+    execfile = "";
+  else
+    error ("No image loaded into target.");
 
-  if (udi_session_id < 0){
-        printf("UDI connection not open yet.\n");
-       return;
-  }
+  if (udi_session_id < 0)
+    {
+      printf_unfiltered("UDI connection not open yet.\n");
+      return;
+    }
 
   inferior_pid = 40000;
 
-#if defined(ULTRA3) && defined(KERNEL_DEBUGGING)
-   /* On ultra3 (NYU) we assume the kernel is already running so there is
-    *   no file to download
-    */
-#else
-  if(*args == '\0') args = prog_name;
-   udi_load(args, 0);
-#endif  /* !ULTRA3 */
-
-  /* We will get a task spawn event immediately.  */
-#ifdef NOTDEF          /* start_remote() now does a wait without a resume 
-                          so don't use it*/ 
-  start_remote ();
-#else
+  if (!entry.Offset)
+    download(execfile, 0);
+
+  args1 = alloca (strlen(execfile) + strlen(args) + 2);
+
+  if (execfile[0] == '\0')
+
+    /* It is empty.  We need to quote it somehow, or else the target
+       will think there is no argument being passed here.  According
+       to the UDI spec it is quoted "according to TIP OS rules" which
+       I guess means quoting it like the Unix shell should work
+       (sounds pretty bogus to me...).  In fact it doesn't work (with
+       isstip anyway), but passing in two quotes as the argument seems
+       like a reasonable enough behavior anyway (I guess).  */
+
+    strcpy (args1, "''");
+  else
+    strcpy (args1, execfile);
+  strcat (args1, " ");
+  strcat (args1, args);
+
+  UDIInitializeProcess (address_ranges,                /* ProcessMemory[] */
+                       (UDIInt)2,              /* NumberOfRanges */
+                       entry,                  /* EntryPoint */
+                       stack_sizes,            /* *StackSizes */
+                       (UDIInt)2,              /* NumberOfStacks */
+                       args1);                 /* ArgString */
+
   init_wait_for_inferior ();
   clear_proceed_status ();
-  proceed(-1,-1,0);
-#endif
-  DEXIT("udi_create_inferior()");
+  proceed (-1, TARGET_SIGNAL_DEFAULT, 0);
 }
-/******************************************************* UDI_MOURN_INFERIOR */
+
 static void
 udi_mourn()
 {
-  DENTER("udi_mourn()");
-        pop_target ();                /* Pop back to no-child state */
-        generic_mourn_inferior ();
-  DEXIT("udi_mourn()");
+#if 0
+  /* Requiring "target udi" each time you run is a major pain.  I suspect
+     this was just blindy copied from remote.c, in which "target" and
+     "run" are combined.  Having a udi target without an inferior seems
+     to work between "target udi" and "run", so why not now?  */
+  pop_target ();                /* Pop back to no-child state */
+#endif
+  /* But if we're going to want to run it again, we better remove the
+     breakpoints...  */
+  remove_breakpoints ();
+  generic_mourn_inferior ();
 }
 
 /******************************************************************** UDI_OPEN
 ** Open a connection to remote TIP.
    NAME is the socket domain used for communication with the TIP,
    then a space and the socket name or TIP-host name.
-   '<udi_udi_config_id> [progname]' for example.
+   '<udi_udi_config_id>' for example.
  */
 
 /* XXX - need cleanups for udiconnect for various failures!!! */
@@ -230,142 +209,86 @@ udi_open (name, from_tty)
      char *name;
      int from_tty;
 {
-  unsigned int prl;
-  char         *p;
-  int          cnt;
+  unsigned int prl;
+  char *p;
+  int cnt;
   UDIMemoryRange KnownMemory[10];
-  UDIUInt32    ChipVersions[10];
-  UDIInt       NumberOfRanges = 10;
-  UDIInt       NumberOfChips = 10;
-  UDIPId       PId;
-  UDIUInt32    TIPId, TargetId, DFEId, DFE, TIP, DFEIPCId, TIPIPCId;
-
-  DENTER("udi_open()");
+  UDIUInt32 ChipVersions[10];
+  UDIInt NumberOfRanges = 10;
+  UDIInt NumberOfChips = 10;
+  UDIPId PId;
+  UDIUInt32 TIPId, TargetId, DFEId, DFE, TIP, DFEIPCId, TIPIPCId;
 
   target_preopen(from_tty);
 
-  /* Find the first whitespace character, it separates udi_config_id
-     from prog_name.  */
-  if(!name) goto erroid;
-    for (p = name;
-         *p != '\0' && !isspace (*p); p++)
-      ;
-  if (*p == '\0')
-erroid:
-    error("Usage: target udi config_id progname, where config_id appears in udi_soc file");
-
-  udi_config_id = (char*)malloc (p - name + 1);
-  strncpy (udi_config_id, name, p - name);
-  udi_config_id[p - name] = '\0';
-
-  /* Skip over the whitespace after udi_config_id */
-  for (; isspace (*p); p++)
-    /*EMPTY*/;
-  
-  if (prog_name != NULL)
-    free (prog_name);
-  prog_name = savestring (p, strlen (p));
+  entry.Offset = 0;
 
-  if (UDIConnect(udi_config_id, &udi_session_id))
-    error("UDIConnect() failed: %s\n", dfe_errmsg);
+  for (cnt = 0; cnt < BKPT_TABLE_SIZE; cnt++)
+    bkpt_table[cnt].Type = 0;
 
-  push_target (&udi_ops);
+  if (udi_config_id)
+    free (udi_config_id);
 
-#ifndef HAVE_TERMIO
-#ifndef NO_SIGINTERRUPT
-  /* Cause SIGALRM's to make reads fail with EINTR instead of resuming
-     the read.  */
-  if (siginterrupt (SIGALRM, 1) != 0)
-    error ("udi_open: siginterrupt() %s", safe_strerror(errno));
-#endif
+  if (!name)
+    error("Usage: target udi config_id, where config_id appears in udi_soc file");
 
-  /* Set up read timeout timer.  */
-  if ((void (*)) signal (SIGALRM, udi_timer) == (void (*)) -1)
-    error ("udi_open: signal() %s", safe_strerror(errno));
-#endif
+  udi_config_id = strdup (strtok (name, " \t"));
+
+  if (UDIConnect (udi_config_id, &udi_session_id))
+    error("UDIConnect() failed: %s\n", dfe_errmsg);
+
+  push_target (&udi_ops);
 
-#if defined (LOG_FILE)
-  log_file = fopen (LOG_FILE, "w");
-  if (log_file == NULL)
-    error ("udi_open: fopen(%s) %s", LOG_FILE, safe_strerror(errno));
-#endif
   /*
   ** Initialize target configuration structure (global)
   */
-  if(UDIGetTargetConfig( KnownMemory, &NumberOfRanges,
-               ChipVersions, &NumberOfChips))
+  if (UDIGetTargetConfig (KnownMemory, &NumberOfRanges,
+                         ChipVersions, &NumberOfChips))
     error ("UDIGetTargetConfig() failed");
-  if(NumberOfChips > 2)
-    fprintf(stderr,"Taret has more than one processor\n");
-  for(cnt=0; cnt<NumberOfRanges; cnt++)
-  {     switch(KnownMemory[cnt].Space)
+  if (NumberOfChips > 2)
+    fprintf_unfiltered(gdb_stderr,"Target has more than one processor\n");
+  for (cnt=0; cnt < NumberOfRanges; cnt++)
+    {
+      switch(KnownMemory[cnt].Space)
        {
-       default: fprintf(stderr, "UDIGetTargetConfig() unknown memory space\n");
-               break;
+       default:
+         fprintf_unfiltered(gdb_stderr, "UDIGetTargetConfig() unknown memory space\n");
+         break;
        case UDI29KCP_S:
-               break;
+         break;
        case UDI29KIROMSpace:
-               RMemStart = KnownMemory[cnt].Offset;
-               RMemSize = KnownMemory[cnt].Size;
-               break;
+         RMemStart = KnownMemory[cnt].Offset;
+         RMemSize = KnownMemory[cnt].Size;
+         break;
        case UDI29KIRAMSpace:
-               IMemStart = KnownMemory[cnt].Offset;
-               IMemSize = KnownMemory[cnt].Size;
-               break;
+         IMemStart = KnownMemory[cnt].Offset;
+         IMemSize = KnownMemory[cnt].Size;
+         break;
        case UDI29KDRAMSpace:
-               DMemStart = KnownMemory[cnt].Offset;
-               DMemSize = KnownMemory[cnt].Size;
-               break;
+         DMemStart = KnownMemory[cnt].Offset;
+         DMemSize = KnownMemory[cnt].Size;
+         break;
        }
-  }
+    }
 
-  /* Determine the processor revision level */
-  prl = (unsigned int)read_register(CFG_REGNUM) >> 24;
-  if ((prl&0xe0) == 0)
-  {   fprintf_filtered(stderr,
-               "Remote debugging Am29000 rev %c\n",'A'+(prl&0x1f));
-      processor_type = TYPE_A29000;
-  } else if ((prl&0xe0) == 0x40)       /* 29030 = 0x4* */
-  {   fprintf_filtered(stderr,
-               "Remote debugging Am2903* rev %c\n",'A'+(prl&0x1f));
-      processor_type = TYPE_A29030;
-  } else if ((prl&0xe0) == 0x20)       /* 29050 = 0x2* */
-  {   fprintf_filtered(stderr,
-               "Remote debugging Am29050 rev %c\n",'A'+(prl&0x1f));
-      processor_type = TYPE_A29050;
-  } else {
-      processor_type = TYPE_UNKNOWN;
-      fprintf_filtered(stderr,"WARNING: processor type unknown.\n");
-  }
-  if(UDICreateProcess(&PId))
-     fprintf(stderr, "UDICreateProcess() failed\n");
+  a29k_get_processor_type ();
+
+  if (UDICreateProcess (&PId))
+     fprintf_unfiltered(gdb_stderr, "UDICreateProcess() failed\n");
 
   /* Print out some stuff, letting the user now what's going on */
-  if(UDICapabilities( &TIPId, &TargetId, DFEId, DFE, &TIP, &DFEIPCId,
-       &TIPIPCId, sbuf))
+  if (UDICapabilities (&TIPId, &TargetId, DFEId, DFE, &TIP, &DFEIPCId,
+                      &TIPIPCId, sbuf))
     error ("UDICapabilities() failed");
-  if (from_tty) {
-    printf_filtered("Remote debugging an %s connected via UDI socket,\n\
+  if (from_tty)
+    {
+      printf_filtered ("Connected via UDI socket,\n\
  DFE-IPC version %x.%x.%x  TIP-IPC version %x.%x.%x  TIP version %x.%x.%x\n %s\n",
-       processor_name[processor_type],
-       (DFEIPCId>>8)&0xf, (DFEIPCId>>4)&0xf, DFEIPCId&0xf,
-       (TIPIPCId>>8)&0xf, (TIPIPCId>>4)&0xf, TIPIPCId&0xf,
-       (TargetId>>8)&0xf, (TargetId>>4)&0xf, TargetId&0xf,
-       sbuf);
-#ifdef ULTRA3
-    /* FIXME: can this restriction be removed? */
-    printf_filtered("Remote debugging using virtual addresses works only\n");
-    printf_filtered(" when virtual addresses map 1:1 to physical addresses.\n");
-#endif
-  }
-#ifdef ULTRA3
-  if (processor_type != TYPE_A29050) {
-        fprintf_filtered(stderr,
-        "Freeze-mode debugging can only be done on an Am29050,\n");
-        fprintf_filtered(stderr,
-        " unless GDB is being used with a 29K simulator.\n");
-  }
-#endif
+                      (DFEIPCId>>8)&0xf, (DFEIPCId>>4)&0xf, DFEIPCId&0xf,
+                      (TIPIPCId>>8)&0xf, (TIPIPCId>>4)&0xf, TIPIPCId&0xf,
+                      (TargetId>>8)&0xf, (TargetId>>4)&0xf, TargetId&0xf,
+                      sbuf);
+    }
 }
 
 /******************************************************************* UDI_CLOSE
@@ -376,32 +299,25 @@ static void
 udi_close (quitting)   /*FIXME: how is quitting used */
      int quitting;
 {
-  int  Terminate = -1;
-  DENTER("udi_close()");
-
   if (udi_session_id < 0)
-    error ("Can't close udi connection: not debugging remotely.");
+    return;
 
   /* We should never get here if there isn't something valid in
-     udi_session_id.
+     udi_session_id.  */
 
-  if(UDIDisconnect(udi_stream, Terminate);)
-    error ("UDIDisconnect() failed in udi_close");
+  if (UDIDisconnect (udi_session_id, UDITerminateSession))
+    {
+      if (quitting)
+       warning ("UDIDisconnect() failed in udi_close");
+      else
+       error ("UDIDisconnect() failed in udi_close");
+    }
 
   /* Do not try to close udi_session_id again, later in the program.  */
   udi_session_id = -1;
   inferior_pid = 0;
 
-#if defined (LOG_FILE)
-  if (ferror (log_file))
-    printf ("Error writing log file.\n");
-  if (fclose (log_file) != 0)
-    printf ("Error closing log file.\n");
-#endif
-
   printf_filtered ("  Ending remote debugging\n");
-
-  DEXIT("udi_close()");
 } 
 
 /**************************************************************** UDI_ATACH */
@@ -419,23 +335,20 @@ udi_attach (args, from_tty)
   UDISizeT     Size = 4;
   UDICount     CountDone;
   UDIBool      HostEndian = 0;
-  DENTER("udi_attach()");
+  UDIError     err;
 
   if (udi_session_id < 0)
-      printf ("UDI connection not opened yet, use the 'target udi' command.\n");
+      error ("UDI connection not opened yet, use the 'target udi' command.\n");
        
   if (from_tty)
-      printf ("Attaching to remote program %s...\n", prog_name);
+      printf_unfiltered ("Attaching to remote program %s...\n", prog_name);
 
-  mark_breakpoints_out ();
   UDIStop();
-  From.Space = 11;
-  From.Offset = UDI29KSpecialRegs;
-  if(UDIRead(From, &PC_adds, Count, Size, &CountDone, HostEndian))
+  From.Space = UDI29KSpecialRegs;
+  From.Offset = 11;
+  if (err = UDIRead(From, &PC_adds, Count, Size, &CountDone, HostEndian))
     error ("UDIRead failed in udi_attach");
-  printf ("Remote process is now halted, pc1 = 0x%x.\n", PC_adds);
-
-  DEXIT("udi_attach()");
+  printf_unfiltered ("Remote process is now halted, pc1 = 0x%x.\n", PC_adds);
 }
 /************************************************************* UDI_DETACH */
 /* Terminate the open connection to the TIP process.
@@ -446,14 +359,19 @@ udi_detach (args,from_tty)
      char *args;
      int from_tty;
 {
-  DENTER("udi_dettach()");
+
   remove_breakpoints();                /* Just in case there were any left in */
-  if(UDIDisconnect(udi_session_id))
+
+  if (UDIDisconnect (udi_session_id, UDIContinueSession))
     error ("UDIDisconnect() failed in udi_detach");
-  pop_target();                /* calls udi_close to do the real work */
+
+  /* calls udi_close to do the real work (which looks like it calls
+     UDIDisconnect with UDITerminateSession, FIXME).  */
+  pop_target();
+
+  /* FIXME, message too similar to what udi_close prints.  */
   if (from_tty)
-    printf ("Ending remote debugging\n");
-  DEXIT("udi_dettach()");
+    printf_unfiltered ("Ending remote debugging\n");
 }
 
 
@@ -461,26 +379,27 @@ udi_detach (args,from_tty)
 ** Tell the remote machine to resume.  */
 
 static void
-udi_resume (step, sig)
-     int step, sig;
+udi_resume (pid, step, sig)
+     int pid, step;
+     enum target_signal sig;
 {
-  UDIError     tip_error;
-  UDIUInt32    Steps = 1;
-  UDIStepType   StepType = UDIStepNatural;
-  UDIRange      Range;
-  DENTER("udi_resume()");
+  UDIError tip_error;
+  UDIUInt32 Steps = 1;
+  UDIStepType StepType = UDIStepNatural;
+  UDIRange Range;
+
   if (step)                    /* step 1 instruction */
-  {  tip_error = tip_error = UDIStep(Steps, StepType, Range);
-      if(tip_error)fprintf(stderr,  "UDIStep() error = %d\n", tip_error);
-      if(tip_error)error ("failed in udi_resume");
+    {
+      tip_error = UDIStep (Steps, StepType, Range);
+      if (!tip_error)
+       return;
 
-  }
-  else 
-  { if(UDIExecute())
-      error ("UDIExecute() failed in udi_resume");
-  }
+      fprintf_unfiltered (gdb_stderr,  "UDIStep() error = %d\n", tip_error);
+      error ("failed in udi_resume");
+    }
 
-  DEXIT("udi_resume()");
+  if (UDIExecute())
+    error ("UDIExecute() failed in udi_resume");
 }
 
 /******************************************************************** UDI_WAIT
@@ -488,8 +407,9 @@ udi_resume (step, sig)
    storing status in STATUS just as `wait' would.  */
 
 static int
-udi_wait (status)
-     WAITTYPE *status;
+udi_wait (pid, status)
+     int pid;
+     struct target_waitstatus *status;
 {
   UDIInt32     MaxTime;
   UDIPId       PId;
@@ -499,127 +419,221 @@ udi_wait (status)
   int          old_immediate_quit = immediate_quit;
   int          i;
 
-  DENTER("udi_wait()");
-  WSETEXIT ((*status), 0);
+  status->kind = TARGET_WAITKIND_EXITED;
+  status->value.integer = 0;
 
 /* wait for message to arrive. It should be:
   If the target stops executing, udi_wait() should return.
 */
   timeout = 0;                 /* Wait indefinetly for a message */
   immediate_quit = 1;          /* Helps ability to QUIT */
+
   while(1)
-  {
-    i = 0;
-    MaxTime = UDIWaitForever;
-    UDIWait(MaxTime, &PId, &StopReason);
-       QUIT;                   /* Let user quit if they want */
-    switch (StopReason & 0xff)
     {
-    default:
-       goto halted;
-    case UDIStdoutReady:
-       if(UDIGetStdout(sbuf, (UDISizeT)SBUF_MAX, &CountDone))
-         error("UDIGetStdin() failed in udi_wait");
-       while(CountDone--)putc(sbuf[i++], stdout);
-       fflush(stdout);
-       break;
-    case UDIStderrReady:
-       UDIGetStderr(sbuf, (UDISizeT)SBUF_MAX, &CountDone);
-       while(CountDone--)putc(sbuf[i++], stderr);
-       fflush(stderr);
-       fflush(stderr);
-       break;
-    case UDIStdinNeeded:
-       printf("DEBUG: stdin requested ... continue\n");
-/*     UDIPutStdin(sbuf, (UDISizeT)i, &CountDone); */
-       break;
-    case UDIStdinModeX:
-       break;
-    }
-  continue;
-  }
-halted:
-  if (StopReason & 0xff  == UDITrapped )  /* lower 8-bits == 0 */
-  {
-    if (StopReason >> 24  == 0)
-    { printf("Am290*0 received vector number 0 (break point)\n");
-      WSETSTOP ((*status), SIGTRAP);
-    }
-    else if (StopReason >> 24 == 1)
-    { printf("Am290*0 received vector 1\n");
-      WSETSTOP ((*status), SIGBUS);
-    }
-    else if (StopReason >> 24 == 3
-          || StopReason >> 24 == 4)
-    { printf("Am290*0 received vector number %d\n",
-         StopReason >> 24);
-      WSETSTOP ((*status), SIGFPE);
-    }
-    else if (StopReason >> 24 == 5)
-    { printf("Am290*0 received vector number %d\n",
-         StopReason >> 24);
-      WSETSTOP ((*status), SIGILL);
-    }
-    else if (StopReason >> 24 >= 6
-          && StopReason >> 24 <= 11)
-    { printf("Am290*0 received vector number %d\n",
-         StopReason >> 24);
-      WSETSTOP ((*status), SIGSEGV);
-    }
-    else if (StopReason >> 24 == 12
-          || StopReason >> 24 == 13)
-    { printf("Am290*0 received vector number %d\n",
-         StopReason >> 24);
-      WSETSTOP ((*status), SIGILL);
-    }
-    else if ((StopReason & 0xff) == 14)
-    { printf("Am290*0 received vector number %d\n",
-         StopReason >> 24);
-      WSETSTOP ((*status), SIGALRM);
-    }
-    else if ((StopReason & 0xff) == 15)
-      WSETSTOP ((*status), SIGTRAP);
-    else if ((StopReason >> 24) >= 16
-          && (StopReason >> 24) <= 21)
-    { printf("Am290*0 received vector number %d\n",
-         StopReason >> 24);
-      WSETSTOP ((*status), SIGINT);
+      i = 0;
+      MaxTime = UDIWaitForever;
+      UDIWait(MaxTime, &PId, &StopReason);
+      QUIT;                    /* Let user quit if they want */
+
+      switch (StopReason & UDIGrossState)
+       {
+       case UDIStdoutReady:
+         if (UDIGetStdout (sbuf, (UDISizeT)SBUF_MAX, &CountDone))
+           /* This is said to happen if the program tries to output
+              a whole bunch of output (more than SBUF_MAX, I would
+              guess).  It doesn't seem to happen with the simulator.  */
+           warning ("UDIGetStdout() failed in udi_wait");
+         fwrite (sbuf, 1, CountDone, gdb_stdout);
+         gdb_flush(gdb_stdout);
+         continue;
+
+       case UDIStderrReady:
+         UDIGetStderr (sbuf, (UDISizeT)SBUF_MAX, &CountDone);
+         fwrite (sbuf, 1, CountDone, gdb_stderr);
+         gdb_flush(gdb_stderr);
+         continue;
+
+       case UDIStdinNeeded:
+         {
+           int ch;
+           i = 0;
+           do
+             {
+               ch = getchar ();
+               if (ch == EOF)
+                 break;
+               sbuf[i++] = ch;
+             } while (i < SBUF_MAX && ch != '\n');
+           UDIPutStdin (sbuf, (UDISizeT)i, &CountDone);
+           continue;
+         }
+
+       case UDIRunning:
+         /* In spite of the fact that we told UDIWait to wait forever, it will
+            return spuriously sometimes.  */
+       case UDIStdinModeX:
+         continue;
+       default:
+         break;
+       }
+      break;
     }
-    else if ((StopReason & 0xff) == 22)
-    { printf("Am290*0 received vector number %d\n",
-         StopReason >> 24);
-      WSETSTOP ((*status), SIGILL);
+
+  switch (StopReason & UDIGrossState)
+    {
+    case UDITrapped:
+      printf_unfiltered("Am290*0 received vector number %d\n", StopReason >> 24);
+         
+      switch (StopReason >> 8)
+       {
+       case 0:                 /* Illegal opcode */
+         printf_unfiltered("   (break point)\n");
+         status->kind = TARGET_WAITKIND_STOPPED;
+         status->value.sig = TARGET_SIGNAL_TRAP;
+         break;
+       case 1:                 /* Unaligned Access */
+         status->kind = TARGET_WAITKIND_STOPPED;
+         status->value.sig = TARGET_SIGNAL_BUS;
+         break;
+       case 3:
+       case 4:
+         status->kind = TARGET_WAITKIND_STOPPED;
+         status->value.sig = TARGET_SIGNAL_FPE;
+         break;
+       case 5:                 /* Protection Violation */
+         status->kind = TARGET_WAITKIND_STOPPED;
+         /* Why not SEGV?  What is a Protection Violation?  */
+         status->value.sig = TARGET_SIGNAL_ILL;
+         break;
+       case 6:
+       case 7:
+       case 8:                 /* User Instruction Mapping Miss */
+       case 9:                 /* User Data Mapping Miss */
+       case 10:                /* Supervisor Instruction Mapping Miss */
+       case 11:                /* Supervisor Data Mapping Miss */
+         status->kind = TARGET_WAITKIND_STOPPED;
+         status->value.sig = TARGET_SIGNAL_SEGV;
+         break;
+       case 12:
+       case 13:
+         status->kind = TARGET_WAITKIND_STOPPED;
+         status->value.sig = TARGET_SIGNAL_ILL;
+         break;
+       case 14:                /* Timer */
+         status->kind = TARGET_WAITKIND_STOPPED;
+         status->value.sig = TARGET_SIGNAL_ALRM;
+         break;
+       case 15:                /* Trace */
+         status->kind = TARGET_WAITKIND_STOPPED;
+         status->value.sig = TARGET_SIGNAL_TRAP;
+         break;
+       case 16:                /* INTR0 */
+       case 17:                /* INTR1 */
+       case 18:                /* INTR2 */
+       case 19:                /* INTR3/Internal */
+       case 20:                /* TRAP0 */
+       case 21:                /* TRAP1 */
+         status->kind = TARGET_WAITKIND_STOPPED;
+         status->value.sig = TARGET_SIGNAL_INT;
+         break;
+       case 22:                /* Floating-Point Exception */
+         status->kind = TARGET_WAITKIND_STOPPED;
+         /* Why not FPE?  */
+         status->value.sig = TARGET_SIGNAL_ILL;
+         break;
+       case 77:                /* assert 77 */
+         status->kind = TARGET_WAITKIND_STOPPED;
+         status->value.sig = TARGET_SIGNAL_TRAP;
+         break;
+       default:
+         status->kind = TARGET_WAITKIND_EXITED;
+         status->value.integer = 0;
+       }
+      break;
+    case UDINotExecuting:
+      status->kind = TARGET_WAITKIND_STOPPED;
+      status->value.sig = TARGET_SIGNAL_TERM;
+      break;
+    case UDIStopped:
+      status->kind = TARGET_WAITKIND_STOPPED;
+      status->value.sig = TARGET_SIGNAL_TSTP;
+      break;
+    case UDIWarned:
+      status->kind = TARGET_WAITKIND_STOPPED;
+      status->value.sig = TARGET_SIGNAL_URG;
+      break;
+    case UDIStepped:
+    case UDIBreak:
+      status->kind = TARGET_WAITKIND_STOPPED;
+      status->value.sig = TARGET_SIGNAL_TRAP;
+      break;
+    case UDIWaiting:
+      status->kind = TARGET_WAITKIND_STOPPED;
+      status->value.sig = TARGET_SIGNAL_STOP;
+      break;
+    case UDIHalted:
+      status->kind = TARGET_WAITKIND_STOPPED;
+      status->value.sig = TARGET_SIGNAL_KILL;
+      break;
+    case UDIExited:
+    default:
+      status->kind = TARGET_WAITKIND_EXITED;
+      status->value.integer = 0;
     }
-    else if ((StopReason & 0xff) == 77)
-      WSETSTOP ((*status), SIGTRAP);
-    else
-exit:
-    WSETEXIT ((*status), 0);
-  }
-  else if ((StopReason & 0xff)  == UDIBreak)
-      WSETSTOP ((*status), SIGTRAP);
-  else if ((StopReason & 0xff)  == UDINotExecuting)
-      WSETSTOP ((*status), SIGTERM);
-  else if ((StopReason & 0xff)  == UDIRunning)
-      WSETSTOP ((*status), SIGILL);
-  else if ((StopReason & 0xff)  == UDIStopped)
-      WSETSTOP ((*status), SIGTSTP);
-  else if ((StopReason & 0xff)  == UDIWarned)
-      WSETSTOP ((*status), SIGLOST);
-  else if ((StopReason & 0xff)  == UDIStepped)
-      WSETSTOP ((*status), SIGTRAP);
-  else if ((StopReason & 0xff)  == UDIWaiting)
-      WSETSTOP ((*status), SIGSTOP);
-  else if ((StopReason & 0xff)  == UDIHalted)
-      WSETSTOP ((*status), SIGKILL);
-  else
-    WSETEXIT ((*status), 0);
 
   timeout = old_timeout;       /* Restore original timeout value */
   immediate_quit = old_immediate_quit;
-  DEXIT("udi_wait()");
-  return 0;
+  return inferior_pid;
+}
+
+#if 0
+/* Handy for debugging */
+udi_pc()
+{
+  UDIResource  From;
+  UDIUInt32    *To;
+  UDICount     Count;
+  UDISizeT     Size = 4;
+  UDICount     CountDone;
+  UDIBool      HostEndian = 0;
+  UDIError     err;
+  int pc[2];
+  unsigned long myregs[256];
+  int i;
+
+  From.Space = UDI29KPC;
+  From.Offset = 0;
+  To = (UDIUInt32 *)pc;
+  Count = 2;
+
+  err = UDIRead(From, To, Count, Size, &CountDone, HostEndian);
+
+  printf_unfiltered ("err = %d, CountDone = %d, pc[0] = 0x%x, pc[1] = 0x%x\n",
+         err, CountDone, pc[0], pc[1]);
+
+  udi_fetch_registers(-1);
+
+  printf_unfiltered("other pc1 = 0x%x, pc0 = 0x%x\n", *(int *)&registers[4 * PC_REGNUM],
+         *(int *)&registers[4 * NPC_REGNUM]);
+
+  /* Now, read all the registers globally */
+
+  From.Space = UDI29KGlobalRegs;
+  From.Offset = 0;
+  err = UDIRead(From, myregs, 256, 4, &CountDone, HostEndian);
+
+  printf ("err = %d, CountDone = %d\n", err, CountDone);
+
+  printf("\n");
+
+  for (i = 0; i < 256; i += 2)
+    printf("%d:\t%#10x\t%11d\t%#10x\t%11d\n", i, myregs[i], myregs[i],
+          myregs[i+1], myregs[i+1]);
+  printf("\n");
+
+  return pc[0];
 }
+#endif
 
 /********************************************************** UDI_FETCH_REGISTERS
  * Read a remote register 'regno'. 
@@ -635,6 +649,7 @@ int regno;
   UDISizeT     Size = 4;
   UDICount     CountDone;
   UDIBool      HostEndian = 0;
+  UDIError     err;
   int          i;
 
   if (regno >= 0)  {
@@ -648,7 +663,7 @@ int regno;
   From.Offset = 1;
   To = (UDIUInt32 *)&registers[4 * GR1_REGNUM];
   Count = 1;
-  if (UDIRead(From, To, Count, Size, &CountDone, HostEndian))
+  if (err = UDIRead(From, To, Count, Size, &CountDone, HostEndian))
     error("UDIRead() failed in udi_fetch_registers");
 
   register_valid[GR1_REGNUM] = 1;
@@ -661,7 +676,7 @@ int regno;
   From.Offset = 64;
   To = (UDIUInt32 *)&registers[4 * GR64_REGNUM];
   Count = 32;
-  if (UDIRead(From, To, Count, Size, &CountDone, HostEndian))
+  if (err = UDIRead(From, To, Count, Size, &CountDone, HostEndian))
     error("UDIRead() failed in udi_fetch_registers");
 
   for (i = GR64_REGNUM; i < GR64_REGNUM + 32; i++)
@@ -675,7 +690,7 @@ int regno;
   From.Offset = 96;
   To = (UDIUInt32 *)&registers[4 * GR96_REGNUM];
   Count = 32;
-  if (UDIRead(From, To, Count, Size, &CountDone, HostEndian))
+  if (err = UDIRead(From, To, Count, Size, &CountDone, HostEndian))
     error("UDIRead() failed in udi_fetch_registers");
 
   for (i = GR96_REGNUM; i < GR96_REGNUM + 32; i++)
@@ -687,7 +702,7 @@ int regno;
   From.Offset = 0;
   To = (UDIUInt32 *)&registers[4 * LR0_REGNUM];
   Count = 128;
-  if (UDIRead(From, To, Count, Size, &CountDone, HostEndian))
+  if (err = UDIRead(From, To, Count, Size, &CountDone, HostEndian))
     error("UDIRead() failed in udi_fetch_registers");
 
   for (i = LR0_REGNUM; i < LR0_REGNUM + 128; i++)
@@ -699,7 +714,7 @@ int regno;
   From.Offset = 0;
   To = (UDIUInt32 *)&registers[4 * SR_REGNUM(0)];
   Count = 15;
-  if (UDIRead(From, To, Count, Size, &CountDone, HostEndian))
+  if (err = UDIRead(From, To, Count, Size, &CountDone, HostEndian))
     error("UDIRead() failed in udi_fetch_registers");
 
   for (i = SR_REGNUM(0); i < SR_REGNUM(0) + 15; i++)
@@ -716,13 +731,21 @@ int       regno;
     From.Offset = 128;
     To = (UDIUInt32 *)&registers[4 * SR_REGNUM(128)];
     Count = 135-128 + 1;
-    if (UDIRead(From, To, Count, Size, &CountDone, HostEndian))
+    if (err = UDIRead(From, To, Count, Size, &CountDone, HostEndian))
       error("UDIRead() failed in udi_fetch_registers");
 
     for (i = SR_REGNUM(128); i < SR_REGNUM(128) + 135-128+1; i++)
       register_valid[i] = 1;
   }
 
+  if (remote_debug)
+    {
+      printf_unfiltered("Fetching all registers\n");
+      printf_unfiltered("Fetching PC0 = 0x%x, PC1 = 0x%x, PC2 = 0x%x\n",
+            read_register(NPC_REGNUM), read_register(PC_REGNUM),
+            read_register(PC2_REGNUM));
+    }
+
   /* There doesn't seem to be any way to get these.  */
   {
     int val = -1;
@@ -756,6 +779,13 @@ int regno;
       return;
     }
 
+  if (remote_debug)
+    {
+      printf_unfiltered("Storing all registers\n");
+      printf_unfiltered("PC0 = 0x%x, PC1 = 0x%x, PC2 = 0x%x\n", read_register(NPC_REGNUM),
+            read_register(PC_REGNUM), read_register(PC2_REGNUM));
+    }
+
 /* Gr1/rsp */
 
   From = (UDIUInt32 *)&registers[4 * GR1_REGNUM];
@@ -818,6 +848,15 @@ int regno;
   if(UDIWrite(From, To, Count, Size, &CountDone, HostEndian))
     error("UDIWrite() failed in udi_store_regisetrs");
 
+/* PC1 via UDI29KPC */
+
+  From = (UDIUInt32 *)&registers[4 * PC_REGNUM];
+  To.Space = UDI29KPC;
+  To.Offset = 0;                               /* PC1 */
+  Count = 1;
+  if (UDIWrite (From, To, Count, Size, &CountDone, HostEndian))
+    error ("UDIWrite() failed in udi_store_regisetrs");
+
   /* LRU and MMU */
 
   From = (UDIUInt32 *)&registers[4 * SR_REGNUM(13)];
@@ -894,7 +933,7 @@ udi_xfer_inferior_memory (memaddr, myaddr, len, write)
 static void
 udi_files_info ()
 {
-  printf ("\tAttached to UDI socket to %s and running program %s.\n",
+  printf_unfiltered ("\tAttached to UDI socket to %s and running program %s.\n",
           udi_config_id, prog_name);
 }
 
@@ -954,84 +993,290 @@ udi_remove_breakpoint (addr, contents_cache)
   error("UDIClearBreakpoint returned error code %d\n", err);
 }
 
-/***************************************************************** UDI_KILL */
 static void
 udi_kill(arg,from_tty)
-char    *arg;
-int     from_tty;
+     char *arg;
+     int from_tty;
 {
-       char    buf[4];
 
-       DENTER("udi_kill()");
-#if defined(ULTRA3) && defined(KERNEL_DEBUGGING)
-       /* We don't ever kill the kernel */
-       if (from_tty) {
-               printf_filtered("Kernel not killed, but left in current state.\n");
-               printf_filtered("Use detach to leave kernel running.\n");
-       }
-#else
-       UDIStop();
-       inferior_pid = 0;
-       if (from_tty) {
-               printf("Target has been stopped.");
-       }
-       pop_target();
-#endif 
-       DEXIT("udi_kill()");
-}
+#if 0
+/*
+UDIStop does not really work as advertised.  It causes the TIP to close it's
+connection, which usually results in GDB dying with a SIGPIPE.  For now, we
+just invoke udi_close, which seems to get things right.
+*/
+  UDIStop();
 
+  udi_session_id = -1;
+  inferior_pid = 0;
+
+  if (from_tty)
+    printf_unfiltered("Target has been stopped.");
+#endif /* 0 */
+#if 0
+  udi_close(0);
+  pop_target();
+#endif /* 0 */
+
+  /* Keep the target around, e.g. so "run" can do the right thing when
+     we are already debugging something.  FIXME-maybe: should we kill the
+     TIP with UDIDisconnect using UDITerminateSession, and then restart
+     it on the next "run"?  */
 
+  inferior_pid = 0;
+}
 
-/***************************************************************** UDI_LOAD */
 /* 
- * Load a program into the target.
- */
+   Load a program into the target.  Args are: `program {options}'.  The options
+   are used to control loading of the program, and are NOT passed onto the
+   loaded code as arguments.  (You need to use the `run' command to do that.)
+
+   The options are:
+               -ms %d  Set mem stack size to %d
+               -rs %d  Set regular stack size to %d
+               -i      send init info (default)
+               -noi    don't send init info
+               -[tT]   Load Text section
+               -[dD]   Load Data section
+               -[bB]   Load BSS section
+               -[lL]   Load Lit section
+  */
+
 static void
-udi_load(arg_string,from_tty)
-char   *arg_string;
-int    from_tty;
+download(load_arg_string, from_tty)
+     char *load_arg_string;
+     int from_tty;
 {
-#define MAX_TOKENS 25
-#define BUFFER_SIZE 256
-   int token_count;
-   char        *token[MAX_TOKENS];
-   char        cmd_line[BUFFER_SIZE];
+#define DEFAULT_MEM_STACK_SIZE                 0x6000
+#define DEFAULT_REG_STACK_SIZE                 0x2000
+
+  char *token;
+  char *filename;
+  asection *section;
+  bfd *pbfd;
+  UDIError err;
+  int load_text = 1, load_data = 1, load_bss = 1, load_lit = 1;
+
+  address_ranges[0].Space = UDI29KIRAMSpace;
+  address_ranges[0].Offset = 0xffffffff;
+  address_ranges[0].Size = 0;
+
+  address_ranges[1].Space = UDI29KDRAMSpace;
+  address_ranges[1].Offset = 0xffffffff;
+  address_ranges[1].Size = 0;
+
+  stack_sizes[0] = DEFAULT_REG_STACK_SIZE;
+  stack_sizes[1] = DEFAULT_MEM_STACK_SIZE;
 
   dont_repeat ();
 
-#if defined(KERNEL_DEBUGGING) && defined(ULTRA3)
-  printf("The kernel had better be loaded already!  Loading not done.\n");
-#else
-  if (arg_string == 0)
-    error ("The load command takes a file name");
-  arg_string = tilde_expand (arg_string);
-  sprintf(cmd_line,"y %s %s", prog_name, arg_string);
-
-  token_count = 0;
-  token[0] = cmd_line;
-
-  if (cmd_line[0] != '\0')
-  { token[token_count] = strtok(cmd_line, " \t,;\n\r");
-
-    if (token[token_count] != NULL)
-    { do {
-            token_count = token_count + 1;
-            token[token_count] = strtok((char *) NULL, " \t,;\n\r");
-         } while ((token[token_count] != NULL) &&
-                     (token_count < MAX_TOKENS));
+  filename = strtok(load_arg_string, " \t");
+  if (!filename)
+    error ("Must specify at least a file name with the load command");
+
+  filename = tilde_expand (filename);
+  make_cleanup (free, filename);
+
+  while (token = strtok (NULL, " \t"))
+    {
+      if (token[0] == '-')
+       {
+         token++;
+
+         if (STREQ (token, "ms"))
+           stack_sizes[1] = atol (strtok (NULL, " \t"));
+         else if (STREQ (token, "rs"))
+           stack_sizes[0] = atol (strtok (NULL, " \t"));
+         else
+           {
+             load_text = load_data = load_bss = load_lit = 0;
+
+             while (*token)
+               {
+                 switch (*token++)
+                   {
+                   case 't':
+                   case 'T':
+                     load_text = 1;
+                     break;
+                   case 'd':
+                   case 'D':
+                     load_data = 1;
+                     break;
+                   case 'b':
+                   case 'B':
+                     load_bss = 1;
+                     break;
+                   case 'l':
+                   case 'L':
+                     load_lit = 1;
+                     break;
+                   default:
+                     error ("Unknown UDI load option -%s", token-1);
+                   }
+               }
+           }
+       }
     }
-    else
-         *token[0] = '\0';
-  }
-  make_cleanup (free, arg_string);
+
+  pbfd = bfd_openr (filename, gnutarget);
+
+  if (!pbfd) 
+    perror_with_name (filename);
+  
+  make_cleanup (bfd_close, pbfd);
+
   QUIT;
   immediate_quit++;
-  if(yank_cmd(token, token_count))
-       error("Failure when tring to load program");
+
+  if (!bfd_check_format (pbfd, bfd_object)) 
+    error ("It doesn't seem to be an object file");
+  
+  for (section = pbfd->sections; section; section = section->next) 
+    {
+      if (bfd_get_section_flags (pbfd, section) & SEC_ALLOC)
+       {
+         UDIResource To;
+         UDICount Count;
+         unsigned long section_size, section_end;
+         const char *section_name;
+
+         section_name = bfd_get_section_name (pbfd, section);
+         if (STREQ (section_name, ".text") && !load_text)
+           continue;
+         else if (STREQ (section_name, ".data") && !load_data)
+           continue;
+         else if (STREQ (section_name, ".bss") && !load_bss)
+           continue;
+         else if (STREQ (section_name, ".lit") && !load_lit)
+           continue;
+
+         To.Offset = bfd_get_section_vma (pbfd, section);
+         section_size = bfd_section_size (pbfd, section);
+         section_end = To.Offset + section_size;
+
+         if (section_size == 0)
+           /* This is needed at least in the BSS case, where the code
+              below starts writing before it even checks the size.  */
+           continue;
+
+         printf_unfiltered("[Loading section %s at %x (%d bytes)]\n",
+                section_name,
+                To.Offset,
+                section_size);
+
+         if (bfd_get_section_flags (pbfd, section) & SEC_CODE)
+           {
+             To.Space = UDI29KIRAMSpace;
+
+             address_ranges[0].Offset = min (address_ranges[0].Offset,
+                                             To.Offset);
+             address_ranges[0].Size = max (address_ranges[0].Size,
+                                           section_end
+                                           - address_ranges[0].Offset);
+           }
+         else
+           {
+             To.Space = UDI29KDRAMSpace;
+
+             address_ranges[1].Offset = min (address_ranges[1].Offset,
+                                             To.Offset);
+             address_ranges[1].Size = max (address_ranges[1].Size,
+                                           section_end
+                                           - address_ranges[1].Offset);
+           }
+
+         if (bfd_get_section_flags (pbfd, section) & SEC_LOAD) /* Text, data or lit */
+           {
+             file_ptr fptr;
+
+             fptr = 0;
+
+             while (section_size > 0)
+               {
+                 char buffer[1024];
+
+                 Count = min (section_size, 1024);
+
+                 bfd_get_section_contents (pbfd, section, buffer, fptr,
+                                           Count);
+
+                 err = UDIWrite ((UDIHostMemPtr)buffer, /* From */
+                                 To,                   /* To */
+                                 Count,                /* Count */
+                                 (UDISizeT)1,          /* Size */
+                                 &Count,               /* CountDone */
+                                 (UDIBool)0);          /* HostEndian */
+                 if (err)
+                   error ("UDIWrite failed, error = %d", err);
+
+                 To.Offset += Count;
+                 fptr += Count;
+                 section_size -= Count;
+               }
+           }
+         else                  /* BSS */
+           {
+             UDIResource From;
+             unsigned long zero = 0;
+
+             /* Write a zero byte at the vma */
+             /* FIXME: Broken for sections of 1-3 bytes (we test for
+                zero above).  */
+             err = UDIWrite ((UDIHostMemPtr)&zero,     /* From */
+                             To,                       /* To */
+                             (UDICount)1,              /* Count */
+                             (UDISizeT)4,              /* Size */
+                             &Count,                   /* CountDone */
+                             (UDIBool)0);              /* HostEndian */
+             if (err)
+               error ("UDIWrite failed, error = %d", err);
+
+             From = To;
+             To.Offset+=4;
+
+             /* Now, duplicate it for the length of the BSS */
+             err = UDICopy (From,                      /* From */
+                            To,                        /* To */
+                            (UDICount)(section_size/4 - 1), /* Count */
+                            (UDISizeT)4,               /* Size */
+                            &Count,                    /* CountDone */
+                            (UDIBool)1);               /* Direction */
+             if (err)
+               {
+                 char message[100];
+                 int xerr;
+
+                 xerr = UDIGetErrorMsg(err, 100, message, &Count);
+                 if (!xerr)
+                   fprintf_unfiltered (gdb_stderr, "Error is %s\n", message);
+                 else
+                   fprintf_unfiltered (gdb_stderr, "xerr is %d\n", xerr);
+                 error ("UDICopy failed, error = %d", err);
+               }
+           }
+
+       }
+    }
+
+  entry.Space = UDI29KIRAMSpace;
+  entry.Offset = bfd_get_start_address (pbfd);
+  
   immediate_quit--;
-  symbol_file_add (arg_string, from_tty, 0, 0, 0, 0);/*DEBUG need to add text_addr */
-#endif
+}
+
+/* User interface to download an image into the remote target.  See download()
+ * for details on args.
+ */
 
+static void
+udi_load(args, from_tty)
+     char *args;
+     int from_tty;
+{
+  download (args, from_tty);
+
+  symbol_file_add (strtok (args, " \t"), from_tty, 0, 0, 0, 0);
 }
 
 /*************************************************** UDI_WRITE_INFERIOR_MEMORY
@@ -1051,9 +1296,7 @@ udi_write_inferior_memory (memaddr, myaddr, len)
   UDICount     CountDone = 0;
   UDIBool      HostEndian = 0;
   
-
-  /* DENTER("udi_write_inferior_memory()"); */
-  To.Space = udi_memory_space(memaddr);        
+  To.Space = udi_memory_space(memaddr);
   From = (UDIUInt32*)myaddr;
 
   while (nwritten < len)
@@ -1069,7 +1312,6 @@ udi_write_inferior_memory (memaddr, myaddr, len)
           From += CountDone;
        }
   }
-  /* DEXIT("udi_write_inferior_memory()"); */
   return(nwritten);
 }
 
@@ -1089,9 +1331,8 @@ udi_read_inferior_memory(memaddr, myaddr, len)
   UDISizeT     Size = 1;
   UDICount     CountDone = 0;
   UDIBool      HostEndian = 0;
+  UDIError     err;
   
-
-  /* DENTER("udi_read_inferior_memory()"); */
   From.Space = udi_memory_space(memaddr);      
   To = (UDIUInt32*)myaddr;
 
@@ -1099,8 +1340,8 @@ udi_read_inferior_memory(memaddr, myaddr, len)
   {    Count = len - nread;
        if (Count > MAXDATA) Count = MAXDATA;
        From.Offset = memaddr + nread;
-        if(UDIRead(From, To, Count, Size, &CountDone, HostEndian))
-       {  error("UDIWrite() failed in udi_read_inferrior_memory");
+        if(err = UDIRead(From, To, Count, Size, &CountDone, HostEndian))
+       {  error("UDIRead() failed in udi_read_inferrior_memory");
           break;       
        }
        else
@@ -1124,7 +1365,7 @@ int       num;
 /* Fetch a single register indicatated by 'regno'. 
  * Returns 0/-1 on success/failure.  
  */
-static int
+static void
 fetch_register (regno)
      int regno;
 {
@@ -1134,6 +1375,7 @@ fetch_register (regno)
   UDISizeT     Size = 4;
   UDICount     CountDone;
   UDIBool      HostEndian = 0;
+  UDIError     err;
   int                  result;
 
   if (regno == GR1_REGNUM)
@@ -1166,7 +1408,7 @@ fetch_register (regno)
     {
       int val = -1;
       supply_register(160 + (regno - FPE_REGNUM),(char *) &val);
-      return 0;                /* Pretend Success */
+      return;          /* Pretend Success */
     }
   else 
     {
@@ -1174,11 +1416,13 @@ fetch_register (regno)
       From.Offset = regnum_to_srnum(regno); 
     }
 
-  if (UDIRead(From, &To, Count, Size, &CountDone, HostEndian))
+  if (err = UDIRead(From, &To, Count, Size, &CountDone, HostEndian))
     error("UDIRead() failed in udi_fetch_registers");
 
   supply_register(regno, (char *) &To);
-  return result;
+
+  if (remote_debug)
+    printf_unfiltered("Fetching register %s = 0x%x\n", reg_names[regno], To);
 }
 /*****************************************************************************/ 
 /* Store a single register indicated by 'regno'. 
@@ -1196,54 +1440,70 @@ store_register (regno)
   UDICount     CountDone;
   UDIBool      HostEndian = 0;
 
-  DENTER("store_register()");
   From =  read_register (regno);       /* get data value */
 
+  if (remote_debug)
+    printf_unfiltered("Storing register %s = 0x%x\n", reg_names[regno], From);
+
   if (regno == GR1_REGNUM)
-  { To.Space = UDI29KGlobalRegs;
-    To.Offset = 1;
-    result = UDIWrite(&From, To, Count, Size, &CountDone, HostEndian);
-    /* Setting GR1 changes the numbers of all the locals, so invalidate the 
-     * register cache.  Do this *after* calling read_register, because we want 
-     * read_register to return the value that write_register has just stuffed 
-     * into the registers array, not the value of the register fetched from 
-     * the inferior.  
-     */
-    registers_changed ();
-  }
+    {
+      To.Space = UDI29KGlobalRegs;
+      To.Offset = 1;
+      result = UDIWrite(&From, To, Count, Size, &CountDone, HostEndian);
+      /* Setting GR1 changes the numbers of all the locals, so invalidate the 
+       * register cache.  Do this *after* calling read_register, because we want 
+       * read_register to return the value that write_register has just stuffed 
+       * into the registers array, not the value of the register fetched from 
+       * the inferior.  
+       */
+      registers_changed ();
+    }
 #if defined(GR64_REGNUM)
   else if (regno >= GR64_REGNUM && regno < GR64_REGNUM + 32 )
-  { To.Space = UDI29KGlobalRegs;
-    To.Offset = (regno - GR64_REGNUM) + 64;
-    result = UDIWrite(&From, To, Count, Size, &CountDone, HostEndian);
-  }
+    {
+      To.Space = UDI29KGlobalRegs;
+      To.Offset = (regno - GR64_REGNUM) + 64;
+      result = UDIWrite(&From, To, Count, Size, &CountDone, HostEndian);
+    }
 #endif /* GR64_REGNUM */
   else if (regno >= GR96_REGNUM && regno < GR96_REGNUM + 32)
-  { To.Space = UDI29KGlobalRegs;
-    To.Offset = (regno - GR96_REGNUM) + 96;
-    result = UDIWrite(&From, To, Count, Size, &CountDone, HostEndian);
-  }
+    {
+      To.Space = UDI29KGlobalRegs;
+      To.Offset = (regno - GR96_REGNUM) + 96;
+      result = UDIWrite(&From, To, Count, Size, &CountDone, HostEndian);
+    }
   else if (regno >= LR0_REGNUM && regno < LR0_REGNUM + 128)
-  { To.Space = UDI29KLocalRegs;
-    To.Offset = (regno - LR0_REGNUM);
-    result = UDIWrite(&From, To, Count, Size, &CountDone, HostEndian);
-  }
-  else if (regno>=FPE_REGNUM && regno<=EXO_REGNUM)  
-  { 
+    {
+      To.Space = UDI29KLocalRegs;
+      To.Offset = (regno - LR0_REGNUM);
+      result = UDIWrite(&From, To, Count, Size, &CountDone, HostEndian);
+    }
+  else if (regno >= FPE_REGNUM && regno <= EXO_REGNUM)  
     return 0;          /* Pretend Success */
-  }
+  else if (regno == PC_REGNUM)
+    {    
+      /* PC1 via UDI29KPC */
+
+      To.Space = UDI29KPC;
+      To.Offset = 0;           /* PC1 */
+      result = UDIWrite (&From, To, Count, Size, &CountDone, HostEndian);
+
+      /* Writing to this loc actually changes the values of pc0 & pc1 */
+
+      register_valid[PC_REGNUM] = 0; /* pc1 */
+      register_valid[NPC_REGNUM] = 0; /* pc0 */
+    }
   else         /* An unprotected or protected special register */
-  { To.Space = UDI29KSpecialRegs;
-    To.Offset = regnum_to_srnum(regno); 
-    result = UDIWrite(&From, To, Count, Size, &CountDone, HostEndian);
-  }
+    {
+      To.Space = UDI29KSpecialRegs;
+      To.Offset = regnum_to_srnum(regno); 
+      result = UDIWrite(&From, To, Count, Size, &CountDone, HostEndian);
+    }
 
-  DEXIT("store_register()");
-  if(result)
-  { result = -1;
+  if (result != 0)
     error("UDIWrite() failed in store_registers");
-  }
-  return result;
+
+  return 0;
 }
 /********************************************************** REGNUM_TO_SRNUM */
 /* 
@@ -1293,7 +1553,7 @@ int       regno;
  */
 static CPUSpace
 udi_memory_space(addr)
-CORE_ADDR      *addr;
+CORE_ADDR      addr;
 {
        UDIUInt32 tstart = IMemStart;
        UDIUInt32 tend   = tstart + IMemSize;  
@@ -1317,44 +1577,83 @@ CORE_ADDR       *addr;
 
 void  convert16() {;}
 void  convert32() {;}
-FILE* EchoFile = 0;            /* used for debugging */
+GDB_FILE * EchoFile = 0;               /* used for debugging */
 int   QuietMode = 0;           /* used for debugging */
-
-/****************************************************************************/
-/* 
- *  Define the target subroutine names 
- */
-static struct target_ops udi_ops = {
-        "udi", "Remote UDI connected TIP",
-       "Remote debug an Am290*0 using socket connection to TIP process ",
-        udi_open, udi_close,
-        udi_attach, udi_detach, udi_resume, udi_wait,
-        udi_fetch_registers, udi_store_registers,
-        udi_prepare_to_store, 0, 0,   /* conv_to, conv_from */
+\f
+#ifdef NO_HIF_SUPPORT
+service_HIF(msg)
+     union msg_t *msg;
+{
+  return(0);                   /* Emulate a failure */
+}
+#endif
+\f
+/* Target_ops vector.  Not static because there does not seem to be
+   any portable way to do a forward declaration of a static variable.
+   The RS/6000 doesn't like "extern" followed by "static"; SunOS
+   /bin/cc doesn't like "static" twice.  */
+
+struct target_ops udi_ops = {
+        "udi",
+       "Remote UDI connected TIP",
+       "Remote debug an AMD 29k using UDI socket connection to TIP process.\n\
+Arguments are\n\
+`configuration-id AF_INET hostname port-number'\n\
+    To connect via the network, where hostname and port-number specify the\n\
+    host and port where you can connect via UDI.\n\
+    configuration-id is unused.\n\
+\n\
+`configuration-id AF_UNIX socket-name tip-program'\n\
+    To connect using a local connection to the \"tip.exe\" program which is\n\
+    supplied by AMD.  If socket-name specifies an AF_UNIX socket then the\n\
+    tip program must already be started; connect to it using that socket.\n\
+    If not, start up tip-program, which should be the name of the tip\n\
+    program.  If appropriate, the PATH environment variable is searched.\n\
+    configuration-id is unused.\n\
+\n\
+`configuration-id'\n\
+    Look up the configuration in ./udi_soc or /etc/udi_soc, which\n\
+    are files containing lines in the above formats.  configuration-id is\n\
+    used to pick which line of the file to use.",
+        udi_open,
+       udi_close,
+        udi_attach,
+       udi_detach,
+       udi_resume,
+       udi_wait,
+        udi_fetch_registers,
+       udi_store_registers,
+        udi_prepare_to_store,
         udi_xfer_inferior_memory,
         udi_files_info,
-        udi_insert_breakpoint, udi_remove_breakpoint, /* Breakpoints */
-        0, 0, 0, 0, 0,          /* Terminal handling */
+        udi_insert_breakpoint,
+       udi_remove_breakpoint,
+        0,                     /* termial_init */
+       0,                      /* terminal_inferior */
+       0,                      /* terminal_ours_for_output */
+       0,                      /* terminal_ours */
+       0,                      /* terminal_info */
         udi_kill,              /* FIXME, kill */
         udi_load,
         0,                      /* lookup_symbol */
-        udi_create_inferior,  /* create_inferior */
-        udi_mourn,            /* mourn_inferior FIXME */
-        process_stratum, 0, /* next */
-        1, 1, 1, 1, 1,  /* all mem, mem, stack, regs, exec */
-       0, 0,                   /* Section pointers */
+        udi_create_inferior,
+        udi_mourn,             /* mourn_inferior FIXME */
+       0,                      /* can_run */
+       0,                      /* notice_signals */
+        process_stratum,
+       0,                      /* next */
+        1,                     /* has_all_memory */
+       1,                      /* has_memory */
+       1,                      /* has_stack */
+       1,                      /* has_registers */
+       1,                      /* has_execution */
+       0,                      /* sections */
+       0,                      /* sections_end */
        OPS_MAGIC,              /* Always the last thing */
 };
 
-void _initialize_remote_udi()
+void
+_initialize_remote_udi ()
 {
   add_target (&udi_ops);
 }
-
-#ifdef NO_HIF_SUPPORT
-service_HIF(msg)
-union msg_t    *msg;
-{
-       return(0);      /* Emulate a failure */
-}
-#endif
This page took 0.043888 seconds and 4 git commands to generate.