Add new files for 29K and Ultracomputer support.
authorJohn Gilmore <gnu@cygnus>
Fri, 13 Sep 1991 01:07:53 +0000 (01:07 +0000)
committerJohn Gilmore <gnu@cygnus>
Fri, 13 Sep 1991 01:07:53 +0000 (01:07 +0000)
gdb/minimon.h [new file with mode: 0644]
gdb/remote-adapt.c [new file with mode: 0644]
gdb/remote-mm.c [new file with mode: 0644]
gdb/ultra3-xdep.c [new file with mode: 0644]
gdb/xm-rtbsd.h [new file with mode: 0644]
gdb/xm-ultra3.h [new file with mode: 0644]

diff --git a/gdb/minimon.h b/gdb/minimon.h
new file mode 100644 (file)
index 0000000..7084f4f
--- /dev/null
@@ -0,0 +1,562 @@
+/* Definitions and macros for support of AMD's remote debugger, MiniMON.
+   Copyright (C) 1990, 1991 Free Software Foundation, Inc.
+
+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 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
+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; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+/*
+ * Some basic types.  FIXME, this should be done by declaring bitfield
+ * sizes in the structs.  We can't portably depend on a "long int" being
+ * 32 bits, etc.
+ */
+typedef long int INT32;            /* 32 bit integer */
+typedef unsigned long int UINT32;  /* 32 bit integer (unsigned) */
+typedef unsigned long int ADDR32;  /* 32 bit address */
+typedef unsigned long int INST32;  /* 32 bit instruction */
+typedef long int BOOLEAN;          /* Boolean value (32 bit) */
+typedef unsigned char BYTE;        /* byte (8 bit) */
+typedef short int INT16;           /* 16 bit integer */
+typedef unsigned short int UINT16; /* 16 bit integer (unsigned) */
+
+/****************************************************************************/
+/************************* Message Information ******************************/
+/****************************************************************************/
+
+/*
+ * Error codes 
+ */
+
+/* General errors */
+#define EMUSAGE     1  /* Bad args / flags               */
+#define EMFAIL      2  /* Unrecoverable error            */
+#define EMBADADDR   3  /* Illegal address                */
+#define EMBADREG    4  /* Illegal register               */
+#define EMSYNTAX    5  /* Illegal command syntax         */
+#define EMACCESS    6  /* Could not access memory        */
+#define EMALLOC     7  /* Could not allocate memory      */
+#define EMTARGET    8  /* Unknown target type            */
+#define EMHINIT     9  /* Could not initialize host      */
+#define EMCOMM     10  /* Could not open communication channel */
+
+/* Message errors */
+#define EMBADMSG   11  /* Unknown message type           */
+#define EMMSG2BIG  12  /* Message to large for buffer    */
+#define EMNOSEND   13  /* Could not send message         */
+#define EMNORECV   14  /* Could not receive message      */
+
+#define EMRESET    15  /* Could not RESET target         */
+#define EMCONFIG   16  /* Could not get target CONFIG    */
+#define EMSTATUS   17  /* Could not get target STATUS    */
+#define EMREAD     18  /* Could not READ target memory   */
+#define EMWRITE    19  /* Could not WRITE target memory  */
+#define EMBKPTSET  20  /* Could not set breakpoint       */
+#define EMBKPTRM   21  /* Could not remove breakpoint    */
+#define EMBKPTSTAT 22  /* Could not get breakpoint status */
+#define EMBKPTNONE 23  /* All breakpoints in use         */
+#define EMBKPTUSED 24  /* Breakpoints already in use     */
+#define EMCOPY     25  /* Could not COPY target memory   */
+#define EMFILL     26  /* Could not FILL target memory   */
+#define EMINIT     27  /* Could not initialize target memory */
+#define EMGO       28  /* Could not start execution      */
+#define EMSTEP     29  /* Could not single step          */
+#define EMBREAK    30  /* Could not BREAK                */
+#define EMHIF      31  /* Could not perform HIF service  */
+#define EMCHANNEL0 32  /* Could not read CHANNEL0        */
+#define EMCHANNEL1 33  /* Could not write CHANNEL1       */
+
+/* COFF file loader errors */
+#define EMOPEN     34  /* Could not open COFF file       */
+#define EMHDR      35  /* Could not read COFF header     */
+#define EMMAGIC    36  /* Bad magic number               */
+#define EMAOUT     37  /* Could not read COFF a.out header */
+#define EMSCNHDR   38  /* Could not read COFF section header */
+#define EMSCN      39  /* Could not read COFF section    */
+#define EMCLOSE    40  /* Could not close COFF file      */
+
+/* Log file errors */
+#define EMLOGOPEN  41  /* Could not open log file        */
+#define EMLOGREAD  42  /* Could not read log file        */
+#define EMLOGWRITE 43  /* Could not write to log file    */
+#define EMLOGCLOSE 44  /* Could not close log file       */
+
+/* Command file errors */
+#define EMCMDOPEN  45  /* Could not open command file    */
+#define EMCMDREAD  46  /* Could not read command file    */
+#define EMCMDWRITE 47  /* Could not write to command file */
+#define EMCMDCLOSE 48  /* Could not close comand file    */
+
+#define EMTIMEOUT  49  /* Host timed out waiting for a message */
+#define EMCOMMTYPE 50  /* A '-t' flag must be specified  */
+#define EMCOMMERR  51  /* Communication error            */
+#define EMBAUD     52  /* Invalid baud rate specified    */
+/*
+ * Memory Spaces
+ */
+#define LOCAL_REG    0  /* Local processor register     */
+#define GLOBAL_REG   1  /* Global processor register    */
+#define SPECIAL_REG  2  /* Special processor register   */
+#define TLB_REG      3  /* Translation Lookaside Buffer */
+#define COPROC_REG   4  /* Coprocessor register         */
+#define I_MEM        5  /* Instruction Memory           */
+#define D_MEM        6  /* Data Memory                  */
+#define I_ROM        7  /* Instruction ROM              */
+#define D_ROM        8  /* Data ROM                     */
+#define I_O          9  /* Input/Output                 */
+#define I_CACHE     10  /* Instruction Cache            */
+#define D_CACHE     11  /* Data Cache                   */
+
+/* To supress warnings for zero length array definitions */
+#define DUMMY 1
+
+/*
+** Host to target definitions
+*/
+
+#define RESET          0
+#define CONFIG_REQ     1
+#define STATUS_REQ     2
+#define READ_REQ       3
+#define WRITE_REQ      4
+#define BKPT_SET       5
+#define BKPT_RM        6
+#define BKPT_STAT      7
+#define COPY           8
+#define FILL           9
+#define INIT          10
+#define GO            11
+#define STEP          12
+#define BREAK         13
+
+#define HIF_CALL_RTN  64
+#define CHANNEL0      65
+#define CHANNEL1_ACK  66
+
+
+/*
+** Target to host definitions
+*/
+
+#define RESET_ACK     32
+#define CONFIG        33
+#define STATUS        34
+#define READ_ACK      35
+#define WRITE_ACK     36
+#define BKPT_SET_ACK  37
+#define BKPT_RM_ACK   38
+#define BKPT_STAT_ACK 39
+#define COPY_ACK      40
+#define FILL_ACK      41
+#define INIT_ACK      42
+#define HALT          43
+
+#define ERROR         63
+
+#define HIF_CALL      96
+#define CHANNEL0_ACK  97
+#define CHANNEL1      98
+
+
+/* A "generic" message */
+struct generic_msg_t {
+          INT32    code;  /* generic */
+          INT32    length;
+          BYTE     byte[DUMMY];
+};
+
+
+/* A "generic" message (with an INT32 array) */
+struct generic_int32_msg_t {
+          INT32    code;  /* generic */
+          INT32    length;
+          INT32    int32[DUMMY];
+};
+
+
+/*
+** Host to target messages
+*/
+
+struct reset_msg_t {
+          INT32    code;  /* 0 */
+          INT32    length;
+};
+
+
+struct config_req_msg_t {
+          INT32    code;  /* 1 */
+          INT32    length;
+};
+
+
+struct status_req_msg_t {
+          INT32    code;  /* 2 */
+          INT32    length;
+};
+
+
+struct read_req_msg_t {
+          INT32    code;  /* 3 */
+          INT32    length;
+          INT32    memory_space;
+          ADDR32   address;
+          INT32    byte_count;
+};
+
+
+struct write_req_msg_t {
+          INT32    code;  /* 4 */
+          INT32    length;
+          INT32    memory_space;
+          ADDR32   address;
+          INT32    byte_count;
+          BYTE     data[DUMMY];
+};
+
+
+struct write_r_msg_t {
+          INT32    code;  /* 4 */
+          INT32    length;
+          INT32    memory_space;
+          ADDR32   address;
+          INT32    byte_count;
+          INT32    data[DUMMY];
+};
+
+
+struct bkpt_set_msg_t {
+          INT32    code;  /* 5 */
+          INT32    length;
+          INT32    memory_space;
+          ADDR32   bkpt_addr;
+          INT32    pass_count;
+          INT32    bkpt_type;
+};
+
+
+struct bkpt_rm_msg_t {
+          INT32    code;  /* 6 */
+          INT32    length;
+          INT32    memory_space;
+          ADDR32   bkpt_addr;
+};
+
+
+struct bkpt_stat_msg_t {
+          INT32    code;  /* 7 */
+          INT32    length;
+          INT32    memory_space;
+          ADDR32   bkpt_addr;
+};
+
+
+struct copy_msg_t {
+          INT32    code;  /* 8 */
+          INT32    length;
+          INT32    source_space;
+          ADDR32   source_addr;
+          INT32    dest_space;
+          ADDR32   dest_addr;
+          INT32    byte_count;
+};
+
+
+struct fill_msg_t {
+          INT32    code;  /* 9 */
+          INT32    length;
+          INT32    memory_space;
+          ADDR32   start_addr;
+          INT32    fill_count;
+          INT32    byte_count;
+          BYTE     fill_data[DUMMY];
+};
+
+
+struct init_msg_t {
+          INT32    code;  /* 10 */
+          INT32    length;
+          ADDR32   text_start;
+          ADDR32   text_end;
+          ADDR32   data_start;
+          ADDR32   data_end;
+          ADDR32   entry_point;
+          INT32    mem_stack_size;
+          INT32    reg_stack_size;
+          ADDR32   arg_start;
+          INT32    os_control;
+};
+
+
+struct go_msg_t {
+          INT32    code;  /* 11 */
+          INT32    length;
+};
+
+
+struct step_msg_t {
+          INT32    code;  /* 12 */
+          INT32    length;
+          INT32    count;
+};
+
+
+struct break_msg_t {
+          INT32    code;  /* 13 */
+          INT32    length;
+};
+
+
+struct hif_call_rtn_msg_t {
+          INT32    code;  /* 64 */
+          INT32    length;
+          INT32    service_number;
+          INT32    gr121;
+          INT32    gr96;
+          INT32    gr97;
+};
+
+
+struct channel0_msg_t {
+          INT32    code;  /* 65 */
+          INT32    length;
+          BYTE     data;
+};
+
+
+struct channel1_ack_msg_t {
+          INT32    code;  /* 66 */
+          INT32    length;
+};
+
+
+/*
+** Target to host messages
+*/
+
+
+struct reset_ack_msg_t {
+          INT32    code;  /* 32 */
+          INT32    length;
+};
+
+
+struct config_msg_t {
+          INT32    code;  /* 33 */
+          INT32    length;
+          INT32    processor_id;
+          INT32    version;
+          ADDR32   I_mem_start;
+          INT32    I_mem_size;
+          ADDR32   D_mem_start;
+          INT32    D_mem_size;
+          ADDR32   ROM_start;
+          INT32    ROM_size;
+          INT32    max_msg_size;
+          INT32    max_bkpts;
+          INT32    coprocessor;
+          INT32    reserved;
+};
+
+
+struct status_msg_t {
+          INT32    code;  /* 34 */
+          INT32    length;
+          INT32    msgs_sent;
+          INT32    msgs_received;
+          INT32    errors;
+          INT32    bkpts_hit;
+          INT32    bkpts_free;
+          INT32    traps;
+          INT32    fills;
+          INT32    spills;
+          INT32    cycles;
+          INT32    reserved;
+};
+
+
+struct read_ack_msg_t {
+          INT32    code;  /* 35 */
+          INT32    length;
+          INT32    memory_space;
+          ADDR32   address;
+          INT32    byte_count;
+          BYTE     data[DUMMY];
+};
+
+struct read_r_ack_msg_t {
+          INT32    code;  /* 35 */
+          INT32    length;
+          INT32    memory_space;
+          ADDR32   address;
+          INT32    byte_count;
+          INT32    data[DUMMY];
+};
+
+
+struct write_ack_msg_t {
+          INT32    code;  /* 36 */
+          INT32    length;
+          INT32    memory_space;
+          ADDR32   address;
+          INT32    byte_count;
+};
+
+
+struct bkpt_set_ack_msg_t {
+          INT32    code;  /* 37 */
+          INT32    length;
+          INT32    memory_space;
+          ADDR32   address;
+          INT32    pass_count;
+          INT32    bkpt_type;
+};
+
+
+struct bkpt_rm_ack_msg_t {
+          INT32    code;  /* 38 */
+          INT32    length;
+          INT32    memory_space;
+          ADDR32   address;
+};
+
+
+struct bkpt_stat_ack_msg_t {
+          INT32    code;  /* 39 */
+          INT32    length; 
+          INT32    memory_space;
+          ADDR32   address;
+          INT32    pass_count;
+          INT32    bkpt_type;
+};
+
+
+struct copy_ack_msg_t {
+          INT32    code;  /* 40 */
+          INT32    length;
+          INT32    source_space;
+          ADDR32   source_addr;
+          INT32    dest_space;
+          ADDR32   dest_addr;
+          INT32    byte_count;
+};
+
+
+struct fill_ack_msg_t {
+          INT32    code;  /* 41 */
+          INT32    length;
+          INT32    memory_space;
+          ADDR32   start_addr;
+          INT32    fill_count;
+          INT32    byte_count;
+};
+
+
+struct init_ack_msg_t {
+          INT32    code;  /* 42 */
+          INT32    length;
+};
+
+
+struct halt_msg_t {
+          INT32    code;  /* 43 */
+          INT32    length;
+          INT32    memory_space;
+          ADDR32   pc0;
+          ADDR32   pc1;
+          INT32    trap_number;
+};
+
+
+struct error_msg_t {
+          INT32    code;  /* 63 */
+          INT32    length;
+          INT32    error_code;
+          INT32    memory_space;
+          ADDR32   address;
+};
+
+
+struct hif_call_msg_t {
+          INT32    code;  /* 96 */
+          INT32    length;
+          INT32    service_number;
+          INT32    lr2;
+          INT32    lr3;
+          INT32    lr4;
+};
+
+
+struct channel0_ack_msg_t {
+          INT32    code;  /* 97 */
+          INT32    length;
+};
+
+
+struct channel1_msg_t {
+          INT32    code;  /* 98 */
+          INT32    length;
+          BYTE     data[DUMMY];
+};
+
+
+
+/*
+** Union all of the message types together
+*/
+
+union msg_t {
+         struct generic_msg_t        generic_msg;
+         struct generic_int32_msg_t  generic_int32_msg;
+
+         struct reset_msg_t          reset_msg;
+         struct config_req_msg_t     config_req_msg;
+         struct status_req_msg_t     status_req_msg;
+         struct read_req_msg_t       read_req_msg;
+         struct write_req_msg_t      write_req_msg;
+         struct write_r_msg_t        write_r_msg;
+         struct bkpt_set_msg_t       bkpt_set_msg;
+         struct bkpt_rm_msg_t        bkpt_rm_msg;
+         struct bkpt_stat_msg_t      bkpt_stat_msg;
+         struct copy_msg_t           copy_msg;
+         struct fill_msg_t           fill_msg;
+         struct init_msg_t           init_msg;
+         struct go_msg_t             go_msg;
+         struct step_msg_t           step_msg;
+         struct break_msg_t          break_msg;
+
+         struct hif_call_rtn_msg_t   hif_call_rtn_msg;
+         struct channel0_msg_t       channel0_msg;
+         struct channel1_ack_msg_t   channel1_ack_msg;
+
+         struct reset_ack_msg_t      reset_ack_msg;
+         struct config_msg_t         config_msg;
+         struct status_msg_t         status_msg;
+         struct read_ack_msg_t       read_ack_msg;
+         struct read_r_ack_msg_t     read_r_ack_msg;
+         struct write_ack_msg_t      write_ack_msg;
+         struct bkpt_set_ack_msg_t   bkpt_set_ack_msg;
+         struct bkpt_rm_ack_msg_t    bkpt_rm_ack_msg;
+         struct bkpt_stat_ack_msg_t  bkpt_stat_ack_msg;
+         struct copy_ack_msg_t       copy_ack_msg;
+         struct fill_ack_msg_t       fill_ack_msg;
+         struct init_ack_msg_t       init_ack_msg;
+         struct halt_msg_t           halt_msg;
+
+         struct error_msg_t          error_msg;
+
+         struct hif_call_msg_t       hif_call_msg;
+         struct channel0_ack_msg_t   channel0_ack_msg;
+         struct channel1_msg_t       channel1_msg;
+};
diff --git a/gdb/remote-adapt.c b/gdb/remote-adapt.c
new file mode 100644 (file)
index 0000000..7900d46
--- /dev/null
@@ -0,0 +1,1447 @@
+/* Remote debugging interface for AMD 290*0 Adapt Monitor Version 2.1d18. 
+   Copyright 1990, 1991 Free Software Foundation, Inc.
+   Contributed by David Wood at New York University (wood@lab.ultra.nyu.edu).
+   Adapted from work done at Cygnus Support in remote-eb.c.
+
+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 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
+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; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+/* This is like remote.c but is for an esoteric situation--
+   having a 29k board attached to an Adapt inline monitor. 
+   The  monitor is connected via serial line to a unix machine 
+   running gdb. 
+
+   3/91 -  developed on Sun3 OS 4.1, by David Wood
+       o - I can't get binary coff to load. 
+       o - I can't get 19200 baud rate to work. 
+   7/91 o - Freeze mode tracing can be done on a 29050.  */
+
+#include <stdio.h>
+#include <string.h>
+#include "defs.h"
+#include "tm.h"
+#include "param-no-tm.h"
+#include "inferior.h"
+#include "wait.h"
+#include "value.h"
+#include <ctype.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <errno.h>
+#include "terminal.h"
+#include "target.h"
+#include "gdbcore.h"
+
+/* External data declarations */
+extern int stop_soon_quietly;           /* for wait_for_inferior */
+
+/* External function declarations */
+extern struct value *call_function_by_hand();
+
+/* Forward data declarations */
+extern struct target_ops adapt_ops;            /* Forward declaration */
+
+/* Forward function declarations */
+static void adapt_fetch_registers ();
+static int  adapt_store_registers ();
+static void   adapt_close ();
+
+/* 
+ * Processor types. It is assumed that the adapt has the correct 
+ * ROM for the given processor. 
+ */
+#define TYPE_UNKNOWN   0
+#define TYPE_A29000    1
+#define TYPE_A29030    2
+#define TYPE_A29050    3
+static char *processor_name[] = { "Unknown", "A29000", "A29030", "A29050" };
+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 DEBUG       /* */
+#ifdef DEBUG
+# define DENTER(NAME)   (printf_filtered("Entering %s\n",NAME), fflush(stdout))
+# define DEXIT(NAME)    (printf_filtered("Exiting  %s\n",NAME), fflush(stdout))
+#else
+# define DENTER(NAME)
+# define DEXIT(NAME)
+#endif
+
+/* Can't seem to get binary coff working */
+#define ASCII_COFF             /* Adapt will be downloaded with ascii coff */
+
+#define LOG_FILE "adapt.log"
+#if defined (LOG_FILE)
+FILE *log_file=NULL;
+#endif
+
+static int timeout = 5;
+static char *dev_name;
+
+/* Descriptor for I/O to remote machine.  Initialize it to -1 so that
+   adapt_open knows that we don't have a file open when the program
+   starts.  */
+int adapt_desc = -1;
+
+/* stream which is fdopen'd from adapt_desc.  Only valid when
+   adapt_desc != -1.  */
+FILE *adapt_stream;
+
+#define ON     1
+#define OFF    0
+static void
+rawmode(desc, turnon)
+int    desc;
+int    turnon;
+{
+  TERMINAL sg;
+
+  if (desc < 0)
+    return;
+
+  ioctl (desc, TIOCGETP, &sg);
+
+  if (turnon) {
+#ifdef HAVE_TERMIO
+       sg.c_lflag &= ~(ICANON);
+#else
+       sg.sg_flags |= RAW;
+#endif
+  } else {
+#ifdef HAVE_TERMIO
+       sg.c_lflag |= ICANON;
+#else
+       sg.sg_flags &= ~(RAW);
+#endif
+  }
+  ioctl (desc, TIOCSETP, &sg);
+}
+
+/* Suck up all the input from the adapt */
+slurp_input()
+{
+  char buf[8];
+
+#ifdef HAVE_TERMIO
+  /* termio does the timeout for us.  */
+  while (read (adapt_desc, buf, 8) > 0);
+#else
+  alarm (timeout);
+  while (read (adapt_desc, buf, 8) > 0);
+  alarm (0);
+#endif
+}
+
+/* Read a character from the remote system, doing all the fancy
+   timeout stuff.  */
+static int
+readchar ()
+{
+  char buf;
+
+  buf = '\0';
+#ifdef HAVE_TERMIO
+  /* termio does the timeout for us.  */
+  read (adapt_desc, &buf, 1);
+#else
+  alarm (timeout);
+  if (read (adapt_desc, &buf, 1) < 0)
+    {
+      if (errno == EINTR)
+       error ("Timeout reading from remote system.");
+      else
+       perror_with_name ("remote");
+    }
+  alarm (0);
+#endif
+
+  if (buf == '\0')
+    error ("Timeout reading from remote system.");
+#if defined (LOG_FILE)
+  putc (buf & 0x7f, log_file);
+#endif
+  return buf & 0x7f;
+}
+
+/* Keep discarding input from the remote system, until STRING is found. 
+   Let the user break out immediately.  */
+static void
+expect (string)
+     char *string;
+{
+  char *p = string;
+
+  fflush(adapt_stream);
+  immediate_quit = 1;
+  while (1)
+    {
+      if (readchar() == *p)
+       {
+         p++;
+         if (*p == '\0')
+           {
+             immediate_quit = 0;
+             return;
+           }
+       }
+      else
+       p = string;
+    }
+}
+
+/* Keep discarding input until we see the adapt prompt.
+
+   The convention for dealing with the prompt is that you
+   o give your command
+   o *then* wait for the prompt.
+
+   Thus the last thing that a procedure does with the serial line
+   will be an expect_prompt().  Exception:  adapt_resume does not
+   wait for the prompt, because the terminal is being handed over
+   to the inferior.  However, the next thing which happens after that
+   is a adapt_wait which does wait for the prompt.
+   Note that this includes abnormal exit, e.g. error().  This is
+   necessary to prevent getting into states from which we can't
+   recover.  */
+static void
+expect_prompt ()
+{
+#if defined (LOG_FILE)
+  /* This is a convenient place to do this.  The idea is to do it often
+     enough that we never lose much data if we terminate abnormally.  */
+  fflush (log_file);
+#endif
+  fflush(adapt_stream);
+  expect ("\n# ");
+}
+
+/* Get a hex digit from the remote system & return its value.
+   If ignore_space is nonzero, ignore spaces (not newline, tab, etc).  */
+static int
+get_hex_digit (ignore_space)
+     int ignore_space;
+{
+  int ch;
+  while (1)
+    {
+      ch = readchar ();
+      if (ch >= '0' && ch <= '9')
+       return ch - '0';
+      else if (ch >= 'A' && ch <= 'F')
+       return ch - 'A' + 10;
+      else if (ch >= 'a' && ch <= 'f')
+       return ch - 'a' + 10;
+      else if (ch == ' ' && ignore_space)
+       ;
+      else
+       {
+         expect_prompt ();
+         error ("Invalid hex digit from remote system.");
+       }
+    }
+}
+
+/* Get a byte from adapt_desc and put it in *BYT.  Accept any number
+   leading spaces.  */
+static void
+get_hex_byte (byt)
+     char *byt;
+{
+  int val;
+
+  val = get_hex_digit (1) << 4;
+  val |= get_hex_digit (0);
+  *byt = val;
+}
+
+/* Read a 32-bit hex word from the adapt, preceded by a space  */
+static long 
+get_hex_word()
+{
+  long val;
+  int j;
+      
+  val = 0;
+  for (j = 0; j < 8; j++)
+       val = (val << 4) + get_hex_digit (j == 0);
+  return val;
+}
+/* Get N 32-bit hex words from remote, each preceded by a space 
+   and put them in registers starting at REGNO.  */
+static void
+get_hex_regs (n, regno)
+     int n;
+     int regno;
+{
+       long val;
+       while (n--) {
+               val = get_hex_word();
+               supply_register(regno++,&val);
+       }
+}
+/* Called when SIGALRM signal sent due to alarm() timeout.  */
+#ifndef HAVE_TERMIO
+
+#ifndef __STDC__
+# ifndef volatile
+#  define volatile /**/
+# endif
+#endif
+volatile int n_alarms;
+
+void
+adapt_timer ()
+{
+#if 0
+  if (kiodebug)
+    printf ("adapt_timer called\n");
+#endif
+  n_alarms++;
+}
+#endif
+
+/* 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 adapt_wait should just return
+   SIGTRAP without actually waiting for anything.  */
+
+static int need_artificial_trap = 0;
+
+void
+adapt_kill(arg,from_tty)
+char   *arg;
+int    from_tty;
+{
+       DENTER("adapt_kill()");
+       fprintf (adapt_stream, "K");
+       fprintf (adapt_stream, "\r");
+       expect_prompt ();
+       DEXIT("adapt_kill()");
+}
+/*
+ * Download a file specified in 'args', to the adapt. 
+ * FIXME: Assumes the file to download is a binary coff file.
+ */
+static void
+adapt_load(args,fromtty)
+char   *args;
+int    fromtty;
+{
+       FILE *fp;
+       int     n;
+       char    buffer[1024];
+       
+       DENTER("adapt_load()");
+       if (!adapt_stream) {
+               printf_filtered("Adapt not open. Use 'target' command to open adapt\n");
+               return;
+       }
+
+       /* OK, now read in the file.  Y=read, C=COFF, T=dTe port
+               0=start address.  */
+
+#ifdef ASCII_COFF      /* Ascii coff */
+       fprintf (adapt_stream, "YA T,0\r");
+       fflush(adapt_stream);   /* Just in case */
+       /* FIXME: should check args for only 1 argument */
+       sprintf(buffer,"cat %s | btoa > /tmp/#adapt-btoa",args);
+       system(buffer);
+       fp = fopen("/tmp/#adapt-btoa","r");
+       rawmode(adapt_desc,OFF);        
+       while (n=fread(buffer,1,1024,fp)) {
+               do { n -= write(adapt_desc,buffer,n); } while (n>0);
+               if (n<0) { perror("writing ascii coff"); break; }
+       }
+       fclose(fp);
+       rawmode(adapt_desc,ON); 
+       system("rm /tmp/#adapt-btoa");
+#else  /* Binary coff - can't get it to work .*/
+       fprintf (adapt_stream, "YC T,0\r");
+       fflush(adapt_stream);   /* Just in case */
+       if (!(fp = fopen(args,"r"))) {
+               printf_filtered("Can't open %s\n",args);
+               return;
+       }
+       while (n=fread(buffer,1,512,fp)) {
+               do { n -= write(adapt_desc,buffer,n); } while (n>0);
+               if (n<0) { perror("writing ascii coff"); break; }
+       }
+       fclose(fp);
+#endif
+       expect_prompt ();       /* Skip garbage that comes out */
+       fprintf (adapt_stream, "\r");
+       expect_prompt ();
+       DEXIT("adapt_load()");
+}
+
+/* This is called not only when we first attach, but also when the
+   user types "run" after having attached.  */
+void
+adapt_create_inferior (execfile, args, env)
+     char *execfile;
+     char *args;
+     char **env;
+{
+  int entry_pt;
+
+  DENTER("adapt_create_inferior()");
+
+  if (args && *args)
+    error ("Can't pass arguments to remote adapt process.");
+
+  if (execfile == 0 || exec_bfd == 0)
+    error ("No exec file specified");
+
+  entry_pt = (int) bfd_get_start_address (exec_bfd);
+
+  if (adapt_stream) {
+       adapt_kill(NULL,NULL);   
+       adapt_clear_breakpoints();
+       init_wait_for_inferior ();
+       /* Clear the input because what the adapt sends back is different
+        * depending on whether it was running or not.
+        */
+       slurp_input();  /* After this there should be a prompt */
+       fprintf(adapt_stream,"\r"); 
+       expect_prompt();
+       printf_filtered("Do you want to download '%s' (y/n)? [y] : ",prog_name);
+       {       
+               char buffer[10];
+               gets(buffer);
+               if (*buffer != 'n') {
+                       adapt_load(prog_name,0);
+               }
+       }
+
+#ifdef NOTDEF
+       /* Set the PC and wait for a go/cont */
+         fprintf (adapt_stream, "G %x,N\r",entry_pt);
+         printf_filtered("Now use the 'continue' command to start.\n"); 
+         expect_prompt ();
+#else
+       insert_breakpoints ();  /* Needed to get correct instruction in cache */
+       proceed(entry_pt, -1, 0);
+#endif
+
+  } else {
+       printf_filtered("Adapt not open yet.\n");
+  }
+  DEXIT("adapt_create_inferior()");
+}
+
+/* Translate baud rates from integers to damn B_codes.  Unix should
+   have outgrown this crap years ago, but even POSIX wouldn't buck it.  */
+
+#ifndef B19200
+#define B19200 EXTA
+#endif
+#ifndef B38400
+#define B38400 EXTB
+#endif
+
+static struct {int rate, damn_b;} baudtab[] = {
+       {0, B0},
+       {50, B50},
+       {75, B75},
+       {110, B110},
+       {134, B134},
+       {150, B150},
+       {200, B200},
+       {300, B300},
+       {600, B600},
+       {1200, B1200},
+       {1800, B1800},
+       {2400, B2400},
+       {4800, B4800},
+       {9600, B9600},
+       {19200, B19200},
+       {38400, B38400},
+       {-1, -1},
+};
+
+static int damn_b (rate)
+     int rate;
+{
+  int i;
+
+  for (i = 0; baudtab[i].rate != -1; i++)
+    if (rate == baudtab[i].rate) return baudtab[i].damn_b;
+  return B38400;       /* Random */
+}
+
+
+/* Open a connection to a remote debugger.
+   NAME is the filename used for communication, then a space,
+   then the baud rate.
+ */
+
+static int baudrate = 9600;
+static void
+adapt_open (name, from_tty)
+     char *name;
+     int from_tty;
+{
+  TERMINAL sg;
+  unsigned int prl;
+  char *p;
+
+  DENTER("adapt_open()");
+  /* Find the first whitespace character, it separates dev_name from
+     prog_name.  */
+  if (name == 0)
+    goto erroid;
+
+  for (p = name;
+       *p != '\0' && !isspace (*p); p++)
+    ;
+  if (*p == '\0')
+erroid:
+    error ("\
+Please include the name of the device for the serial port,\n\
+the baud rate, and the name of the program to run on the remote system.");
+  dev_name = (char*)malloc(p - name + 1);
+  strncpy (dev_name, name, p - name);
+  dev_name[p - name] = '\0';
+
+  /* Skip over the whitespace after dev_name */
+  for (; isspace (*p); p++)
+    /*EMPTY*/;
+  
+  if (1 != sscanf (p, "%d ", &baudrate))
+    goto erroid;
+
+  /* Skip the number and then the spaces */
+  for (; isdigit (*p); p++)
+    /*EMPTY*/;
+  for (; isspace (*p); p++)
+    /*EMPTY*/;
+  
+  if (prog_name != NULL)
+    free (prog_name);
+  prog_name = savestring (p, strlen (p));
+
+  adapt_close (0);
+
+  adapt_desc = open (dev_name, O_RDWR);
+  if (adapt_desc < 0)
+    perror_with_name (dev_name);
+  ioctl (adapt_desc, TIOCGETP, &sg);
+#ifdef HAVE_TERMIO
+  sg.c_cc[VMIN] = 0;           /* read with timeout.  */
+  sg.c_cc[VTIME] = timeout * 10;
+  sg.c_lflag &= ~(ICANON | ECHO);
+  sg.c_cflag = (sg.c_cflag & ~CBAUD) | damn_b (baudrate);
+#else
+  sg.sg_ispeed = damn_b (baudrate);
+  sg.sg_ospeed = damn_b (baudrate);
+  sg.sg_flags |= RAW | ANYP;
+  sg.sg_flags &= ~ECHO;
+#endif
+
+  ioctl (adapt_desc, TIOCSETP, &sg);
+  adapt_stream = fdopen (adapt_desc, "r+");
+
+  push_target (&adapt_ops);
+  /* start_remote ();              /* Initialize gdb process mechanisms */
+
+
+#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)
+    perror ("adapt_open: error in siginterrupt");
+#endif
+
+  /* Set up read timeout timer.  */
+  if ((void (*)) signal (SIGALRM, adapt_timer) == (void (*)) -1)
+    perror ("adapt_open: error in signal");
+#endif
+
+#if defined (LOG_FILE)
+  log_file = fopen (LOG_FILE, "w");
+  if (log_file == NULL)
+    perror_with_name (LOG_FILE);
+#endif
+
+  /* Put this port into NORMAL mode, send the 'normal' character */
+  write(adapt_desc, "\ 1", 1);   /* Control A */
+  write(adapt_desc, "\r", 1);  
+  expect_prompt ();
+  
+  /* Hello?  Are you there?  */
+  write (adapt_desc, "\r", 1);
+  expect_prompt ();
+
+  /* Clear any break points */
+  adapt_clear_breakpoints();
+
+  /* Determine the processor revision level */
+  prl = (unsigned int)read_register(CFG_REGNUM) >> 24;
+  if (prl == 0x03) { 
+       processor_type = TYPE_A29000;  
+  } else if ((prl&0xf0) == 0x40) {     /* 29030 = 0x4* */
+       processor_type = TYPE_A29030;  
+       fprintf_filtered(stderr,"WARNING: debugging of A29030 not tested.\n");
+  } else if ((prl&0xf0) == 0x20) {     /* 29050 = 0x2* */
+       processor_type = TYPE_A29050;  
+       fprintf_filtered(stderr,"WARNING: debugging of A29050 not tested.\n");
+  } else {
+       processor_type = TYPE_UNKNOWN;  
+       fprintf_filtered(stderr,"WARNING: processor type unknown.\n");
+  }
+
+  /* Print out some stuff, letting the user now what's going on */
+  printf_filtered("Remote debugging on an %s connect to an Adapt via %s.\n",
+               processor_name[processor_type],dev_name);
+    /* FIXME: can this restriction be removed? */
+  printf_filtered("Remote debugging using virtual addresses works only\n");
+  printf_filtered("\twhen virtual addresses map 1:1 to physical addresses.\n"); 
+  if (processor_type != TYPE_A29050) {
+       fprintf_filtered(stderr,
+       "Freeze-mode debugging not available, and can only be done on an A29050.\n");
+  }
+  DEXIT("adapt_open()");
+}
+
+/* Close out all files and local state before this target loses control. */
+
+static void
+adapt_close (quitting)
+     int quitting;
+{
+
+  DENTER("adapt_close()");
+
+  /* Clear any break points */
+  adapt_clear_breakpoints();
+
+  /* Put this port back into REMOTE mode */ 
+  if (adapt_stream) {
+     fflush(adapt_stream);
+     sleep(1);         /* Let any output make it all the way back */
+     write(adapt_desc, "R\r", 2);
+  }
+
+  /* Due to a bug in Unix, fclose closes not only the stdio stream,
+     but also the file descriptor.  So we don't actually close
+     adapt_desc.  */
+  if (adapt_stream)
+    fclose (adapt_stream);     /* This also closes adapt_desc */
+  if (adapt_desc >= 0)
+    /* close (adapt_desc); */
+
+  /* Do not try to close adapt_desc again, later in the program.  */
+  adapt_stream = NULL;
+  adapt_desc = -1;
+
+#if defined (LOG_FILE)
+  if (log_file) {
+    if (ferror (log_file))
+      printf_filtered ("Error writing log file.\n");
+    if (fclose (log_file) != 0)
+      printf_filtered ("Error closing log file.\n");
+    log_file = NULL;
+  }
+#endif
+  DEXIT("adapt_close()");
+}
+
+/* Attach to the target that is already loaded and possibly running */
+static void
+adapt_attach (args, from_tty)
+     char *args;
+     int from_tty;
+{
+
+  DENTER("adapt_attach()");
+  if (from_tty)
+      printf_filtered ("Attaching to remote program %s.\n", prog_name);
+
+  /* push_target(&adapt_ops);  /* This done in adapt_open() */
+
+  mark_breakpoints_out ();
+
+  /* Send the adapt a kill. It is ok if it is not already running */
+  fprintf(adapt_stream, "K\r"); fflush(adapt_stream);
+  expect_prompt();             /* Slurp the echo */
+
+  /* We will get a task spawn event immediately.  */
+  init_wait_for_inferior ();
+  clear_proceed_status ();
+  stop_soon_quietly = 1;
+  wait_for_inferior ();
+  stop_soon_quietly = 0;
+  normal_stop ();
+  DEXIT("adapt_attach()");
+}
+
+
+/* Terminate the open connection to the remote debugger.
+   Use this when you want to detach and do something else
+   with your gdb.  */
+void
+adapt_detach (args,from_tty)
+     char *args;
+     int from_tty;
+{
+  DENTER("adapt_detach()");
+  if (adapt_stream) { /* Send it on its way (tell it to continue)  */
+       adapt_clear_breakpoints();
+       fprintf(adapt_stream,"G\r");
+  }
+  pop_target();                /* calls adapt_close to do the real work */
+  if (from_tty)
+    printf_filtered ("Ending remote %s debugging\n", target_shortname);
+  DEXIT("adapt_detach()");
+}
+/* Tell the remote machine to resume.  */
+
+void
+adapt_resume (step, sig)
+     int step, sig;
+{
+  DENTER("adapt_resume()");
+  if (step)    
+    {
+      write (adapt_desc, "t 1,s\r", 6);
+      /* Wait for the echo.  */
+      expect ("t 1,s\r\n");
+      /* Then comes a line containing the instruction we stepped to.  */
+      expect ("@");
+      /* Then we get the prompt.  */
+      expect_prompt ();
+
+      /* Force the next adapt_wait to return a trap.  Not doing anything
+         about I/O from the target means that the user has to type
+         "continue" to see any.  FIXME, this should be fixed.  */
+      need_artificial_trap = 1;
+    }
+  else
+    {
+      write (adapt_desc, "G\r", 2);
+      /* Swallow the echo.  */
+      expect_prompt(); 
+    }
+  DEXIT("adapt_resume()");
+}
+
+/* Wait until the remote machine stops, then return,
+   storing status in STATUS just as `wait' would.  */
+
+int
+adapt_wait (status)
+     WAITTYPE *status;
+{
+  /* Strings to look for.  '?' means match any single character.  
+     Note that with the algorithm we use, the initial character
+     of the string cannot recur in the string, or we will not
+     find some cases of the string in the input.  */
+  
+  static char bpt[] = "@";
+  /* It would be tempting to look for "\n[__exit + 0x8]\n"
+     but that requires loading symbols with "yc i" and even if
+     we did do that we don't know that the file has symbols.  */
+  static char exitmsg[] = "@????????I    JMPTI     GR121,LR0";
+  char *bp = bpt;
+  char *ep = exitmsg;
+
+  /* Large enough for either sizeof (bpt) or sizeof (exitmsg) chars.  */
+  char swallowed[50];
+  /* Current position in swallowed.  */
+  char *swallowed_p = swallowed;
+
+  int ch;
+  int ch_handled;
+  int old_timeout = timeout;
+  int old_immediate_quit = immediate_quit;
+
+  DENTER("adapt_wait()");
+
+  WSETEXIT ((*status), 0);
+
+  if (need_artificial_trap != 0)
+    {
+      WSETSTOP ((*status), SIGTRAP);
+      need_artificial_trap--;
+      return 0;
+    }
+
+  timeout = 0;         /* Don't time out -- user program is running. */
+  immediate_quit = 1;  /* Helps ability to QUIT */
+  while (1) {
+      QUIT;            /* Let user quit and leave process running */
+      ch_handled = 0;
+      ch = readchar ();
+      if (ch == *bp) {
+         bp++;
+         if (*bp == '\0')
+           break;
+         ch_handled = 1;
+
+         *swallowed_p++ = ch;
+      } else
+       bp = bpt;
+      if (ch == *ep || *ep == '?') {
+         ep++;
+         if (*ep == '\0')
+           break;
+
+         if (!ch_handled)
+           *swallowed_p++ = ch;
+         ch_handled = 1;
+      } else
+       ep = exitmsg;
+      if (!ch_handled) {
+         char *p;
+         /* Print out any characters which have been swallowed.  */
+         for (p = swallowed; p < swallowed_p; ++p)
+           putc (*p, stdout);
+         swallowed_p = swallowed;
+         putc (ch, stdout);
+      }
+  }
+  expect_prompt ();
+  if (*bp== '\0')
+    WSETSTOP ((*status), SIGTRAP);
+  else
+    WSETEXIT ((*status), 0);
+  timeout = old_timeout;
+  immediate_quit = old_immediate_quit;
+  DEXIT("adapt_wait()");
+  return 0;
+}
+
+/* Return the name of register number REGNO
+   in the form input and output by adapt.
+
+   Returns a pointer to a static buffer containing the answer.  */
+static char *
+get_reg_name (regno)
+     int regno;
+{
+  static char buf[80];
+  if (regno >= GR96_REGNUM && regno < GR96_REGNUM + 32 )
+    sprintf (buf, "GR%03d", regno - GR96_REGNUM + 96);
+#if defined(GR64_REGNUM)
+  else if (regno >= GR64_REGNUM && regno < GR64_REGNUM + 32 )
+    sprintf (buf, "GR%03d", regno - GR64_REGNUM + 64);
+#endif
+  else if (regno >= LR0_REGNUM && regno < LR0_REGNUM + 128)
+    sprintf (buf, "LR%03d", regno - LR0_REGNUM);
+  else if (regno == Q_REGNUM) 
+    strcpy (buf, "SR131");
+  else if (regno >= BP_REGNUM && regno <= CR_REGNUM)
+    sprintf (buf, "SR%03d", regno - BP_REGNUM + 133);
+  else if (regno == ALU_REGNUM)
+    strcpy (buf, "SR132");
+  else if (regno >= IPC_REGNUM && regno <= IPB_REGNUM)
+    sprintf (buf, "SR%03d", regno - IPC_REGNUM + 128);
+  else if (regno >= VAB_REGNUM && regno <= LRU_REGNUM) {
+    /* When a 29050 is in freeze-mode, read shadow pcs instead */
+    if ((regno >= NPC_REGNUM && regno <= PC2_REGNUM) && USE_SHADOW_PC)
+       sprintf (buf, "SR%03d", regno - NPC_REGNUM + 20);
+    else
+       sprintf (buf, "SR%03d", regno - VAB_REGNUM);
+  }
+  else if (regno == GR1_REGNUM)
+    strcpy (buf, "GR001");
+  return buf;
+}
+
+/* Read the remote registers.  */
+
+static void
+adapt_fetch_registers ()
+{
+  int reg_index;
+  int regnum_index;
+  char tempbuf[10];
+  int  sreg_buf[16];
+  int i,j;
+
+  DENTER("adapt_fetch_registers()");
+
+/* 
+ * Global registers
+ */
+#if defined(GR64_REGNUM)
+  write (adapt_desc, "dw gr64,gr95\r", 13);
+  for (reg_index = 64, regnum_index = GR64_REGNUM;
+       reg_index < 96;
+       reg_index += 4, regnum_index += 4)
+    {
+      sprintf (tempbuf, "GR%03d ", reg_index);
+      expect (tempbuf);
+      get_hex_regs (4, regnum_index);
+      expect ("\n");
+    }
+#endif
+  write (adapt_desc, "dw gr96,gr127\r", 14);
+  for (reg_index = 96, regnum_index = GR96_REGNUM;
+       reg_index < 128;
+       reg_index += 4, regnum_index += 4)
+    {
+      sprintf (tempbuf, "GR%03d ", reg_index);
+      expect (tempbuf);
+      get_hex_regs (4, regnum_index);
+      expect ("\n");
+    }
+
+/* 
+ * Local registers
+ */
+  for (i = 0; i < 128; i += 32)
+    {
+      /* The PC has a tendency to hang if we get these
+        all in one fell swoop ("dw lr0,lr127").  */
+      sprintf (tempbuf, "dw lr%d\r", i);
+      write (adapt_desc, tempbuf, strlen (tempbuf));
+      for (reg_index = i, regnum_index = LR0_REGNUM + i;
+          reg_index < i + 32;
+          reg_index += 4, regnum_index += 4)
+       {
+         sprintf (tempbuf, "LR%03d ", reg_index);
+         expect (tempbuf);
+         get_hex_regs (4, regnum_index);
+         expect ("\n");
+       }
+    }
+
+/* 
+ * Special registers
+ */
+  sprintf (tempbuf, "dw sr0\r");
+  write (adapt_desc, tempbuf, strlen (tempbuf));
+  for (i=0 ; i<4 ; i++) {                      /* SR0 - SR14 */
+        sprintf (tempbuf, "SR%3d",i*4);
+       expect(tempbuf);
+       for (j=0 ; j < (i==3 ? 3 : 4) ; j++)
+               sreg_buf[i*4 + j] = get_hex_word();
+  }            
+  expect_prompt();
+  /* 
+   * Read the pcs individually if we are in freeze mode.
+   * See get_reg_name(), it translates the register names for the pcs to
+   * the names of the shadow pcs.
+   */ 
+  if (USE_SHADOW_PC)  {
+         sreg_buf[10] = read_register(NPC_REGNUM);     /* pc0 */
+         sreg_buf[11] = read_register(PC_REGNUM);      /* pc1 */
+         sreg_buf[12] = read_register(PC2_REGNUM);     /* pc2 */
+  }
+  for (i=0 ; i<14 ; i++)               /* Supply vab -> lru */
+       supply_register(VAB_REGNUM+i,&sreg_buf[i]);
+  sprintf (tempbuf, "dw sr128\r");
+  write (adapt_desc, tempbuf, strlen (tempbuf));
+  for (i=0 ; i<2 ; i++) {                      /* SR128 - SR135 */
+        sprintf (tempbuf, "SR%3d",128 + i*4);
+       expect(tempbuf);
+       for (j=0 ; j<4 ; j++)
+               sreg_buf[i*4 + j] = get_hex_word();
+  }            
+  expect_prompt();
+  supply_register(IPC_REGNUM,&sreg_buf[0]);
+  supply_register(IPA_REGNUM,&sreg_buf[1]);
+  supply_register(IPB_REGNUM,&sreg_buf[2]);
+  supply_register(Q_REGNUM,  &sreg_buf[3]);
+               /* Skip ALU */
+  supply_register(BP_REGNUM, &sreg_buf[5]);
+  supply_register(FC_REGNUM, &sreg_buf[6]);
+  supply_register(CR_REGNUM, &sreg_buf[7]);
+
+  /* There doesn't seem to be any way to get these.  */
+  {
+    int val = -1;
+    supply_register (FPE_REGNUM, &val);
+    supply_register (INT_REGNUM, &val);
+    supply_register (FPS_REGNUM, &val);
+    supply_register (EXO_REGNUM, &val);
+  }
+
+  write (adapt_desc, "dw gr1,gr1\r", 11);
+  expect ("GR001 ");
+  get_hex_regs (1, GR1_REGNUM);
+  expect_prompt ();
+
+  DEXIT("adapt_fetch_registers()");
+}
+
+/* Fetch register REGNO, or all registers if REGNO is -1.
+ */
+static void
+adapt_fetch_register (regno)
+     int regno;
+{
+  DENTER("adapt_fetch_register()");
+  if (regno == -1)
+    adapt_fetch_registers ();
+  else
+    {
+      char *name = get_reg_name (regno);
+      fprintf (adapt_stream, "dw %s,%s\r", name, name);
+      expect (name);
+      expect (" ");
+      get_hex_regs (1, regno);
+      expect_prompt ();
+    }
+  DEXIT("adapt_fetch_register()");
+}
+
+/* Store the remote registers from the contents of the block REGS.  */
+
+static int 
+adapt_store_registers ()
+{
+  int i, j;
+
+  DENTER("adapt_store_registers()");
+  fprintf (adapt_stream, "s gr1,%x\r", read_register (GR1_REGNUM));
+  expect_prompt ();
+
+#if defined(GR64_REGNUM)
+  for (j = 0; j < 32; j += 16)
+    {
+      fprintf (adapt_stream, "s gr%d,", j + 64);
+      for (i = 0; i < 15; ++i) 
+       fprintf (adapt_stream, "%x,", read_register (GR64_REGNUM + j + i));
+      fprintf (adapt_stream, "%x\r", read_register (GR64_REGNUM + j + 15));
+      expect_prompt ();
+    }
+#endif
+  for (j = 0; j < 32; j += 16)
+    {
+      fprintf (adapt_stream, "s gr%d,", j + 96);
+      for (i = 0; i < 15; ++i) 
+       fprintf (adapt_stream, "%x,", read_register (GR96_REGNUM + j + i));
+      fprintf (adapt_stream, "%x\r", read_register (GR96_REGNUM + j + 15));
+      expect_prompt ();
+    }
+
+  for (j = 0; j < 128; j += 16)
+    {
+      fprintf (adapt_stream, "s lr%d,", j);
+      for (i = 0; i < 15; ++i) 
+       fprintf (adapt_stream, "%x,", read_register (LR0_REGNUM + j + i));
+      fprintf (adapt_stream, "%x\r", read_register (LR0_REGNUM + j + 15));
+      expect_prompt ();
+    }
+
+  fprintf (adapt_stream, "s sr128,%x,%x,%x\r", read_register (IPC_REGNUM),
+          read_register (IPA_REGNUM), read_register (IPB_REGNUM));
+  expect_prompt ();
+  fprintf (adapt_stream, "s sr133,%x,%x,%x\r", read_register (BP_REGNUM),
+          read_register (FC_REGNUM), read_register (CR_REGNUM));
+  expect_prompt ();
+  fprintf (adapt_stream, "s sr131,%x\r", read_register (Q_REGNUM));
+  expect_prompt ();
+  fprintf (adapt_stream, "s sr0,");
+  for (i=0 ; i<7 ; ++i)
+    fprintf (adapt_stream, "%x,", read_register (VAB_REGNUM + i));
+  expect_prompt ();
+  fprintf (adapt_stream, "s sr7,");
+  for (i=7; i<14 ; ++i)
+    fprintf (adapt_stream, "%x,", read_register (VAB_REGNUM + i));
+  expect_prompt ();
+}
+
+/* Store register REGNO, or all if REGNO == -1.
+   Return errno value.  */
+int
+adapt_store_register (regno)
+     int regno;
+{
+  /* printf("adapt_store_register() called.\n"); fflush(stdout); /* */
+  if (regno == -1)
+    adapt_store_registers ();
+  else
+    {
+      char *name = get_reg_name (regno);
+      fprintf (adapt_stream, "s %s,%x\r", name, read_register (regno));
+      /* 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.  */
+      if (regno == GR1_REGNUM)
+       registers_changed ();
+      expect_prompt ();
+    }
+  DEXIT("adapt_store_registers()");
+  return 0;
+}
+
+/* Get ready to modify the registers array.  On machines which store
+   individual registers, this doesn't need to do anything.  On machines
+   which store all the registers in one fell swoop, this makes sure
+   that registers contains all the registers from the program being
+   debugged.  */
+
+void
+adapt_prepare_to_store ()
+{
+  /* Do nothing, since we can store individual regs */
+}
+
+static CORE_ADDR 
+translate_addr(addr)
+CORE_ADDR addr;
+{
+#if defined(KERNEL_DEBUGGING)
+       /* Check for a virtual address in the kernel */
+       /* Assume physical address of ublock is in  paddr_u register */
+       if (addr >= UVADDR) {
+               /* PADDR_U register holds the physical address of the ublock */
+               CORE_ADDR i = (CORE_ADDR)read_register(PADDR_U_REGNUM); 
+               return(i + addr - (CORE_ADDR)UVADDR);
+       } else {
+               return(addr);
+       }
+#else
+       return(addr);
+#endif
+}
+
+
+/* FIXME!  Merge these two.  */
+int
+adapt_xfer_inferior_memory (memaddr, myaddr, len, write)
+     CORE_ADDR memaddr;
+     char *myaddr;
+     int len;
+     int write;
+{
+
+  memaddr = translate_addr(memaddr);
+
+  if (write)
+    return adapt_write_inferior_memory (memaddr, myaddr, len);
+  else
+    return adapt_read_inferior_memory (memaddr, myaddr, len);
+}
+
+void
+adapt_files_info ()
+{
+  printf_filtered("\tAttached to %s at %d baud and running program %s\n",
+         dev_name, baudrate, prog_name);
+  printf_filtered("\ton an %s processor.\n", processor_name[processor_type]);
+}
+
+/* Copy LEN bytes of data from debugger memory at MYADDR
+   to inferior's memory at MEMADDR.  Returns errno value.  
+ * sb/sh instructions don't work on unaligned addresses, when TU=1. 
+ */
+int
+adapt_write_inferior_memory (memaddr, myaddr, len)
+     CORE_ADDR memaddr;
+     char *myaddr;
+     int len;
+{
+  int i;
+  unsigned int cps;
+
+  /* DENTER("adapt_write_inferior_memory()"); */
+
+/* Turn TU bit off so we can do 'sb' commands */
+  cps = read_register(CPS_REGNUM);
+  if (cps & 0x00000800)
+       write_register(CPS_REGNUM,cps&~(0x00000800));
+
+  for (i = 0; i < len; i++)
+    {
+      if ((i % 16) == 0)
+       fprintf (adapt_stream, "sb %x,", memaddr + i);
+      if ((i % 16) == 15 || i == len - 1)
+       {
+         fprintf (adapt_stream, "%x\r", ((unsigned char *)myaddr)[i]);
+         expect_prompt ();
+       }
+      else
+       fprintf (adapt_stream, "%x,", ((unsigned char *)myaddr)[i]);
+    }
+  /* Restore the old value of cps if the TU bit was on */
+  if (cps & 0x00000800)
+       write_register(CPS_REGNUM,cps);
+  /* DEXIT("adapt_write_inferior_memory()"); */
+  return len;
+}
+
+/* Read LEN bytes from inferior memory at MEMADDR.  Put the result
+   at debugger address MYADDR.  Returns errno value.  */
+int
+adapt_read_inferior_memory(memaddr, myaddr, len)
+     CORE_ADDR memaddr;
+     char *myaddr;
+     int len;
+{
+  int i;
+
+  /* Number of bytes read so far.  */
+  int count;
+
+  /* Starting address of this pass.  */
+  unsigned long startaddr;
+
+  /* Number of bytes to read in this pass.  */
+  int len_this_pass;
+
+  /* Note that this code works correctly if startaddr is just less
+     than UINT_MAX (well, really CORE_ADDR_MAX if there was such a
+     thing).  That is, something like
+     adapt_read_bytes (CORE_ADDR_MAX - 4, foo, 4)
+     works--it never adds len to memaddr and gets 0.  */
+  /* However, something like
+     adapt_read_bytes (CORE_ADDR_MAX - 3, foo, 4)
+     doesn't need to work.  Detect it and give up if there's an attempt
+     to do that.  */
+  /* DENTER("adapt_read_inferior_memory()"); */
+
+  if (((memaddr - 1) + len) < memaddr)
+    return EIO;
+  
+  startaddr = memaddr;
+  count = 0;
+  while (count < len)
+    {
+      len_this_pass = 16;
+      if ((startaddr % 16) != 0)
+       len_this_pass -= startaddr % 16;
+      if (len_this_pass > (len - count))
+       len_this_pass = (len - count);
+
+      fprintf (adapt_stream, "db %x,%x\r", startaddr,
+              (startaddr - 1) + len_this_pass);
+
+#ifdef NOTDEF  /* Why do this */
+      expect ("\n");
+      /* Look for 8 hex digits.  */
+      i = 0;
+      while (1)
+       {
+         if (isxdigit (readchar ()))
+           ++i;
+         else
+           {
+             expect_prompt ();
+             error ("Hex digit expected from remote system.");
+           }
+         if (i >= 8)
+           break;
+       }
+#endif /* NOTDEF */
+
+      expect ("  ");
+
+      for (i = 0; i < len_this_pass; i++)
+       get_hex_byte (&myaddr[count++]);
+
+      expect_prompt ();
+
+      startaddr += len_this_pass;
+    }
+
+  /* DEXIT("adapt_read_inferior_memory()"); */
+  return count;
+}
+
+#define MAX_BREAKS     8
+static int num_brkpts=0;
+static int
+adapt_insert_breakpoint(addr, save)
+CORE_ADDR      addr;
+char           *save;  /* Throw away, let adapt save instructions */
+{
+  DENTER("adapt_insert_breakpoint()"); 
+  if (num_brkpts < MAX_BREAKS) {
+       num_brkpts++;
+       fprintf (adapt_stream, "B %x", addr);
+       fprintf (adapt_stream, "\r");
+       expect_prompt ();
+       DEXIT("adapt_insert_breakpoint() success"); 
+       return(0);      /* Success */
+  } else {
+       fprintf_filtered(stderr,
+               "Too many break points, break point not installed\n");
+       DEXIT("adapt_insert_breakpoint() failure"); 
+       return(1);      /* Failure */
+  }
+
+}
+static int
+adapt_remove_breakpoint(addr, save)
+CORE_ADDR      addr;
+char           *save;  /* Throw away, let adapt save instructions */
+{
+  DENTER("adapt_remove_breakpoint()");
+  if (num_brkpts > 0) {
+         num_brkpts--;
+         fprintf (adapt_stream, "BR %x", addr);
+         fprintf (adapt_stream, "\r");
+         fflush (adapt_stream);
+         expect_prompt ();
+  }
+  DEXIT("adapt_remove_breakpoint()");
+  return(0);
+}
+
+/* Clear the adapts notion of what the break points are */
+static int
+adapt_clear_breakpoints() 
+{ 
+  DENTER("adapt_clear_breakpoint()");
+  if (adapt_stream) {
+       fprintf (adapt_stream, "BR");   /* Clear all break points */
+       fprintf (adapt_stream, "\r");
+       fflush(adapt_stream);
+       expect_prompt ();
+  }
+  num_brkpts = 0;
+  DEXIT("adapt_clear_breakpoint()");
+}
+static void
+adapt_mourn() 
+{ 
+  DENTER("adapt_mourn()");
+  adapt_clear_breakpoints();
+  pop_target ();                /* Pop back to no-child state */
+  generic_mourn_inferior ();
+  DEXIT("adapt_mourn()");
+}
+
+/* Display everthing we read in from the adapt until we match/see the
+ * specified string
+ */
+static int
+display_until(str)
+char   *str;
+{
+       int     i=0,j,c;
+
+       while (c=readchar()) {
+               if (c==str[i]) {
+                       i++;
+                       if (i == strlen(str)) return;
+               } else {
+                       if (i) {
+                           for (j=0 ; j<i ; j++) /* Put everthing we matched */
+                               putchar(str[j]);
+                           i=0;
+                       }
+                       putchar(c);
+               }       
+       }
+
+}
+
+
+/* Put a command string, in args, out to the adapt.  The adapt is assumed to
+   be in raw mode, all writing/reading done through adapt_desc.
+   Ouput from the adapt is placed on the users terminal until the
+   prompt from the adapt is seen.
+   FIXME: Can't handle commands that take input.  */
+
+void
+adapt_com (args, fromtty)
+     char      *args;
+     int       fromtty;
+{
+       if (!adapt_stream) {
+               printf_filtered("Adapt not open.  Use the 'target' command to open.\n");
+               return;
+       }
+
+       /* Clear all input so only command relative output is displayed */
+       slurp_input();  
+
+       switch(islower(args[0]) ? toupper(args[0]) : args[0]) {
+       default:
+               printf_filtered("Unknown/Unimplemented adapt command '%s'\n",args);
+               break;
+       case 'G':       /* Go, begin execution */
+               write(adapt_desc,args,strlen(args));
+               write(adapt_desc,"\r",1);
+               expect_prompt();
+               break;
+       case 'B':       /* Break points, B or BR */
+       case 'C':       /* Check current 29k status (running/halted) */
+       case 'D':       /* Display data/registers */ 
+       case 'I':       /* Input from i/o space */
+       case 'J':       /* Jam an instruction */
+       case 'K':       /* Kill, stop execution */
+       case 'L':       /* Disassemble */
+       case 'O':       /* Output to i/o space */
+       case 'T':       /* Trace */ 
+       case 'P':       /* Pulse an input line */ 
+       case 'X':       /* Examine special purpose registers */ 
+       case 'Z':       /* Display trace buffer */ 
+               write(adapt_desc,args,strlen(args));
+               write(adapt_desc,"\r",1);
+               expect(args);           /* Don't display the command */
+               display_until("# ");
+               break;
+       /* Begin commands that take input in the form 'c x,y[,z...]' */
+       case 'S':       /* Set memory or register */
+               if (index(args,',')) {  /* Assume it is properly formatted */
+                       write(adapt_desc,args,strlen(args));
+                       write(adapt_desc,"\r",1);
+                       expect_prompt();
+               }
+               break;
+       }
+}
+
+/* Define the target subroutine names */
+
+struct target_ops adapt_ops = {
+       "adapt", "Remote AMD `Adapt' target",
+       "Remote debug an AMD 290*0 using an `Adapt' monitor via RS232",
+       adapt_open, adapt_close, 
+       adapt_attach, adapt_detach, adapt_resume, adapt_wait,
+       adapt_fetch_register, adapt_store_register,
+       adapt_prepare_to_store, 0, 0,   /* conv_to, conv_from */
+       adapt_xfer_inferior_memory, 
+       adapt_files_info,
+       adapt_insert_breakpoint, adapt_remove_breakpoint, /* Breakpoints */
+       0, 0, 0, 0, 0,          /* Terminal handling */
+       adapt_kill,             /* FIXME, kill */
+       adapt_load, 
+       call_function_by_hand,
+       0,                      /* lookup_symbol */
+       adapt_create_inferior,  /* create_inferior */ 
+       adapt_mourn,            /* mourn_inferior FIXME */
+       process_stratum, 0, /* next */
+       1, 1, 1, 1, 1,  /* all mem, mem, stack, regs, exec */
+       0,0,            /* Section pointers */
+       OPS_MAGIC,              /* Always the last thing */
+};
+
+void
+_initialize_remote_adapt ()
+{
+  add_target (&adapt_ops);
+  add_com ("adapt <command>", class_obscure, adapt_com,
+       "Send a command to the AMD Adapt remote monitor.");
+}
diff --git a/gdb/remote-mm.c b/gdb/remote-mm.c
new file mode 100644 (file)
index 0000000..d3c67e6
--- /dev/null
@@ -0,0 +1,1684 @@
+/* Remote debugging interface for Am290*0 running MiniMON monitor, for GDB.
+   Copyright (C) 1990, 1991 Free Software Foundation, Inc.
+   Originally written by Daniel Mann at 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 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
+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; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+/* This is like remote.c but ecpects MiniMON to be running on the Am29000 
+   target hardware.
+ - 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.  */
+#include <stdio.h>
+#include "defs.h"
+#include "inferior.h"
+#include "wait.h"
+#include "value.h"
+#include <ctype.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <errno.h>
+#include <string.h>
+#include "terminal.h"
+#include "minimon.h"
+#include "target.h"
+
+/* Offset of member MEMBER in a struct of type TYPE.  */
+#define offsetof(TYPE, MEMBER) ((int) &((TYPE *)0)->MEMBER)
+
+/* #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 
+
+#define DRAIN_INPUT()  (msg_recv_serial((union msg_t*)0))
+
+extern int stop_soon_quietly;           /* for wait_for_inferior */
+
+extern struct value *call_function_by_hand();
+
+static void mm_resume();
+static void mm_fetch_registers ();
+static int fetch_register ();
+static int mm_store_registers ();
+static int store_register ();
+static int regnum_to_srnum();
+static void  mm_close ();
+static char* msg_str();
+static char* error_msg_str();
+static int expect_msg();
+static void init_target_mm();
+static int mm_memory_space();
+
+/*
+ * Processor types. 
+ */
+#define TYPE_UNKNOWN    0
+#define TYPE_A29000     1
+#define TYPE_A29030     2
+#define TYPE_A29050     3
+static  char *processor_name[] = { "Unknown", "A29000", "A29030", "A29050" };
+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 "minimon.log"
+#if defined (LOG_FILE)
+FILE *log_file;
+#endif
+
+/*  
+ * Size of message buffers.  I couldn't get memory reads to work when
+ * the byte_count was larger than 512 (it may be a baud rate problem).
+ */
+#define BUFER_SIZE  512                
+/* 
+ * Size of data area in message buffer on the TARGET (remote system).
+ */
+#define MAXDATA_T  (target_config.max_msg_size - \
+                       offsetof(struct write_r_msg_t,data[0]))
+/*              
+ * Size of data area in message buffer on the HOST (gdb). 
+ */
+#define MAXDATA_H  (BUFER_SIZE - offsetof(struct write_r_msg_t,data[0]))
+/* 
+ * Defined as the minimum size of data areas of the two message buffers 
+ */
+#define MAXDATA           (MAXDATA_H < MAXDATA_T ? MAXDATA_H : MAXDATA_T)
+
+static char out_buf[BUFER_SIZE];
+static char  in_buf[BUFER_SIZE];
+
+int msg_recv_serial();
+int msg_send_serial();
+
+#define MAX_RETRIES 5000
+extern struct target_ops mm_ops;             /* Forward declaration */
+struct config_msg_t  target_config;    /* HIF needs this */
+union msg_t  *out_msg_buf = (union msg_t*)out_buf;
+union msg_t  *in_msg_buf  = (union msg_t*)in_buf;
+
+static int timeout = 5;
+
+/* Descriptor for I/O to remote machine.  Initialize it to -1 so that
+   mm_open knows that we don't have a file open when the program
+   starts.  */
+int mm_desc = -1;
+
+/* stream which is fdopen'd from mm_desc.  Only valid when
+   mm_desc != -1.  */
+FILE *mm_stream;
+
+/* 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
+mm_timer ()
+{
+#if 0
+  if (kiodebug)
+    printf ("mm_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 mm_wait should just return
+   SIGTRAP without actually waiting for anything.  */
+
+/**************************************************** REMOTE_CREATE_INFERIOR */
+/* This is called not only when we first attach, but also when the
+   user types "run" after having attached.  */
+static void
+mm_create_inferior (execfile, args, env)
+     char *execfile;
+     char *args;
+     char **env;
+{
+#define MAX_TOKENS 25
+#define BUFFER_SIZE 256
+   int token_count;
+   int result;
+   char        *token[MAX_TOKENS];
+   char        cmd_line[BUFFER_SIZE];
+
+  DENTER("mm_create_inferior()");
+
+  if (args && *args)
+    error ("Can't pass arguments to remote mm process (yet).");
+
+  if (execfile == 0 /* || exec_bfd == 0 */ )
+    error ("No exec file specified");
+
+  if (!mm_stream) {
+        printf("Minimon not open yet.\n");
+       return;
+  }
+
+  /* On ultra3 (NYU) we assume the kernel is already running so there is
+     no file to download.
+     FIXME: Fixed required here -> load your program, possibly with mm_load().
+     */
+  printf_filtered ("\n\
+Assuming you are at NYU debuging a kernel, i.e., no need to download.\n\n");
+
+  /* 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
+  init_wait_for_inferior ();
+  clear_proceed_status ();
+  stop_soon_quietly = 1;
+  proceed(-1,-1,0);
+  normal_stop ();
+#endif
+  DEXIT("mm_create_inferior()");
+}
+/**************************************************** REMOTE_MOURN_INFERIOR */
+static void
+mm_mourn()
+{
+  DENTER("mm_mourn()");
+        pop_target ();                /* Pop back to no-child state */
+        generic_mourn_inferior ();
+  DEXIT("mm_mourn()");
+}
+
+/********************************************************************** damn_b
+*/
+/* Translate baud rates from integers to damn B_codes.  Unix should
+   have outgrown this crap years ago, but even POSIX wouldn't buck it.  */
+
+#ifndef B19200
+#define B19200 EXTA
+#endif
+#ifndef B38400
+#define B38400 EXTB
+#endif
+
+static struct {int rate, damn_b;} baudtab[] = {
+       {0, B0},
+       {50, B50},
+       {75, B75},
+       {110, B110},
+       {134, B134},
+       {150, B150},
+       {200, B200},
+       {300, B300},
+       {600, B600},
+       {1200, B1200},
+       {1800, B1800},
+       {2400, B2400},
+       {4800, B4800},
+       {9600, B9600},
+       {19200, B19200},
+       {38400, B38400},
+       {-1, -1},
+};
+
+static int damn_b (rate)
+     int rate;
+{
+  int i;
+
+  for (i = 0; baudtab[i].rate != -1; i++)
+    if (rate == baudtab[i].rate) return baudtab[i].damn_b;
+  return B38400;       /* Random */
+}
+
+
+/***************************************************************** REMOTE_OPEN
+** Open a connection to remote minimon.
+   NAME is the filename used for communication, then a space,
+   then the baud rate.
+   'target adapt /dev/ttya 9600 [prognam]' for example.
+ */
+
+static char *dev_name;
+int baudrate = 9600;
+static void
+mm_open (name, from_tty)
+     char *name;
+     int from_tty;
+{
+  TERMINAL sg;
+  unsigned int prl;
+  char *p;
+
+  DENTER("mm_open()");
+
+  /* Find the first whitespace character, it separates dev_name from
+     prog_name.  */
+  for (p = name;
+       *p != '\0' && !isspace (*p); p++)
+    ;
+  if (*p == '\0')
+erroid:
+    error ("Usage : <command> <serial-device> <baud-rate> [progname]");
+  dev_name = (char*)malloc (p - name + 1);
+  strncpy (dev_name, name, p - name);
+  dev_name[p - name] = '\0';
+
+  /* Skip over the whitespace after dev_name */
+  for (; isspace (*p); p++)
+    /*EMPTY*/;
+  
+  if (1 != sscanf (p, "%d ", &baudrate))
+    goto erroid;
+
+  /* Skip the number and then the spaces */
+  for (; isdigit (*p); p++)
+    /*EMPTY*/;
+  for (; isspace (*p); p++)
+    /*EMPTY*/;
+  
+  if (prog_name != NULL)
+    free (prog_name);
+  prog_name = savestring (p, strlen (p));
+
+
+  if (mm_desc >= 0)
+    close (mm_desc);
+
+  mm_desc = open (dev_name, O_RDWR);
+  if (mm_desc < 0)
+    perror_with_name (dev_name);
+  ioctl (mm_desc, TIOCGETP, &sg);
+#ifdef HAVE_TERMIO
+  sg.c_cc[VMIN] = 0;           /* read with timeout.  */
+  sg.c_cc[VTIME] = timeout * 10;
+  sg.c_lflag &= ~(ICANON | ECHO);
+  sg.c_cflag = (sg.c_cflag & ~CBAUD) | damn_b (baudrate);
+#else
+  sg.sg_ispeed = damn_b (baudrate);
+  sg.sg_ospeed = damn_b (baudrate);
+  sg.sg_flags |= RAW;
+  sg.sg_flags |= ANYP;
+  sg.sg_flags &= ~ECHO;
+#endif
+
+
+  ioctl (mm_desc, TIOCSETP, &sg);
+  mm_stream = fdopen (mm_desc, "r+");
+
+  push_target (&mm_ops);
+
+#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)
+    perror ("mm_open: error in siginterrupt");
+#endif
+
+  /* Set up read timeout timer.  */
+  if ((void (*)) signal (SIGALRM, mm_timer) == (void (*)) -1)
+    perror ("mm_open: error in signal");
+#endif
+
+#if defined (LOG_FILE)
+  log_file = fopen (LOG_FILE, "w");
+  if (log_file == NULL)
+    perror_with_name (LOG_FILE);
+#endif
+   /*
+   ** Initialize target configuration structure (global)
+   */
+   DRAIN_INPUT();
+   out_msg_buf->config_req_msg.code = CONFIG_REQ;
+   out_msg_buf->config_req_msg.length = 4*0;
+   msg_send_serial(out_msg_buf); /* send config request message */
+
+   expect_msg(CONFIG,in_msg_buf,1);
+
+  /* Determine the processor revision level */
+  /* FIXME: this code is the same as in remote-adapt.c */
+  prl = (unsigned int)read_register(CFG_REGNUM) >> 24;
+  if (prl == 0x03) {
+        processor_type = TYPE_A29000;
+  } else if ((prl&0xf0) == 0x40) {      /* 29030 = 0x4* */
+        processor_type = TYPE_A29030;
+        fprintf_filtered(stderr,"WARNING: debugging of A29030 not tested.\n");
+  } else if ((prl&0xf0) == 0x20) {      /* 29050 = 0x2* */
+        processor_type = TYPE_A29050;
+        fprintf_filtered(stderr,"WARNING: debugging of A29050 not tested.\n");
+  } else {
+        processor_type = TYPE_UNKNOWN;
+        fprintf_filtered(stderr,"WARNING: processor type unknown.\n");
+  }
+
+  /* Print out some stuff, letting the user now what's going on */
+  printf_filtered("Remote debugging on an %s connect to MiniMon via %s.\n",
+                processor_name[processor_type],dev_name);
+    /* FIXME: can this restriction be removed? */
+  printf_filtered("Remote debugging using virtual addresses works only\n");
+  printf_filtered("\twhen virtual addresses map 1:1 to physical addresses.\n")
+;
+  if (processor_type != TYPE_A29050) {
+        fprintf_filtered(stderr,
+        "Freeze-mode debugging not available, and can only be done on an A29050.\n");
+  }
+
+   target_config.code = CONFIG;
+   target_config.length = 0;
+   target_config.processor_id = in_msg_buf->config_msg.processor_id;
+   target_config.version = in_msg_buf->config_msg.version;
+   target_config.I_mem_start = in_msg_buf->config_msg.I_mem_start;
+   target_config.I_mem_size = in_msg_buf->config_msg.I_mem_size;
+   target_config.D_mem_start = in_msg_buf->config_msg.D_mem_start;
+   target_config.D_mem_size = in_msg_buf->config_msg.D_mem_size;
+   target_config.ROM_start = in_msg_buf->config_msg.ROM_start;
+   target_config.ROM_size =  in_msg_buf->config_msg.ROM_size;
+   target_config.max_msg_size = in_msg_buf->config_msg.max_msg_size;
+   target_config.max_bkpts = in_msg_buf->config_msg.max_bkpts;
+   target_config.coprocessor = in_msg_buf->config_msg.coprocessor;
+   target_config.reserved = in_msg_buf->config_msg.reserved;
+   if (from_tty) {
+       printf("Connected to MiniMON :\n");
+       printf("    Debugcore version            %d.%d\n",
+               0x0f & (target_config.version >> 4),
+               0x0f & (target_config.version ) );
+       printf("    Configuration version        %d.%d\n",
+               0x0f & (target_config.version >> 12),
+               0x0f & (target_config.version >>  8) );
+       printf("    Message system version       %d.%d\n",
+               0x0f & (target_config.version >> 20),
+               0x0f & (target_config.version >> 16) );
+       printf("    Communication driver version %d.%d\n",
+               0x0f & (target_config.version >> 28),
+               0x0f & (target_config.version >> 24) );
+   }
+
+  /* Leave the target running... 
+   * The above message stopped the target in the dbg core (MiniMon),  
+   * so restart the target out of MiniMon, 
+   */
+  out_msg_buf->go_msg.code = GO;
+  out_msg_buf->go_msg.length = 0;
+  msg_send_serial(out_msg_buf);
+  /* No message to expect after a GO */
+
+  DEXIT("mm_open()");
+}
+
+/**************************************************************** REMOTE_CLOSE
+** Close the open connection to the minimon debugger.
+   Use this when you want to detach and do something else
+   with your gdb.  */
+static void
+mm_close (quitting)    /*FIXME: how is quitting used */
+     int quitting;
+{
+  DENTER("mm_close()");
+
+  if (mm_desc < 0)
+    error ("Can't close remote connection: not debugging remotely.");
+
+  /* We should never get here if there isn't something valid in
+     mm_desc and mm_stream.  
+
+     Due to a bug in Unix, fclose closes not only the stdio stream,
+     but also the file descriptor.  So we don't actually close
+     mm_desc.  */
+  DRAIN_INPUT();
+  fclose (mm_stream);  
+  /* close (mm_desc); */
+
+  /* Do not try to close mm_desc again, later in the program.  */
+  mm_stream = NULL;
+  mm_desc = -1;
+
+#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 ("Ending remote debugging\n");
+
+  DEXIT("mm_close()");
+
+} 
+
+/************************************************************* REMOTE_ATACH */
+/* Attach to a program that is already loaded and running 
+ * Upon exiting the process's execution is stopped.
+ */
+static void
+mm_attach (args, from_tty)
+     char *args;
+     int from_tty;
+{
+
+  DENTER("mm_attach()");
+
+  if (!mm_stream)
+      printf ("MiniMon not opened yet, use the 'target minimon' command.\n");
+       
+  dont_repeat();
+
+  if (from_tty)
+      printf ("Attaching to remote program %s...\n", prog_name);
+
+
+  /* Make sure the target is currently running, it is supposed to be. */
+  /* FIXME: is it ok to send MiniMon a BREAK if it is already stopped in 
+   *   the dbg core.  If so, we don't need to send this GO.
+   */
+  out_msg_buf->go_msg.code = GO;
+  out_msg_buf->go_msg.length = 0;
+  msg_send_serial(out_msg_buf);
+  sleep(2);    /* At the worst it will stop, receive a message, continue */
+  /* Send the mm a break. */ 
+  out_msg_buf->break_msg.code = BREAK;
+  out_msg_buf->break_msg.length = 0;
+  msg_send_serial(out_msg_buf);
+
+  mark_breakpoints_out ();
+  init_wait_for_inferior ();
+  clear_proceed_status ();
+  stop_soon_quietly = 1;
+  wait_for_inferior ();
+  stop_soon_quietly = 0;
+  normal_stop ();
+
+  DEXIT("mm_attach()");
+}
+/********************************************************** REMOTE_DETACH */
+/* Terminate the open connection to the remote debugger.
+   Use this when you want to detach and do something else
+   with your gdb.  Leave remote process running (with no breakpoints set). */
+static void
+mm_detach (args,from_tty)
+     char *args;
+     int from_tty;
+{
+  DENTER("mm_dettach()");
+  remove_breakpoints();                /* Just in case there were any left in */
+  out_msg_buf->go_msg.code = GO;
+  out_msg_buf->go_msg.length = 0;
+  msg_send_serial(out_msg_buf);
+  pop_target();                /* calls mm_close to do the real work */
+  DEXIT("mm_dettach()");
+}
+
+
+/*************************************************************** REMOTE_RESUME
+** Tell the remote machine to resume.  */
+
+static void
+mm_resume (step, sig)
+     int step, sig;
+{
+  DENTER("mm_resume()");
+
+  if (sig)
+    error ("Can't send signals to a remote MiniMon system.");
+
+  if (step) {
+      out_msg_buf->step_msg.code= STEP;
+      out_msg_buf->step_msg.length = 1*4;
+      out_msg_buf->step_msg.count = 1;         /* step 1 instruction */
+      msg_send_serial(out_msg_buf);
+  } else {
+      out_msg_buf->go_msg.code= GO;
+      out_msg_buf->go_msg.length = 0;
+      msg_send_serial(out_msg_buf);
+  }
+
+  DEXIT("mm_resume()");
+}
+
+/***************************************************************** REMOTE_WAIT
+** Wait until the remote machine stops, then return,
+   storing status in STATUS just as `wait' would.  */
+
+static int
+mm_wait (status)
+     WAITTYPE *status;
+{
+  int i, result;
+  int old_timeout = timeout;
+  int old_immediate_quit = immediate_quit;
+
+  DENTER("mm_wait()");
+  WSETEXIT ((*status), 0);
+
+
+/* wait for message to arrive. It should be:
+       - A HIF service request.
+       - A HIF exit service request.
+       - A CHANNEL0_ACK.
+       - A CHANNEL1 request.
+       - a debugcore HALT message.
+  HIF services must be responded too, and while-looping continued.
+  If the target stops executing, mm_wait() should return.
+*/
+  timeout = 0; /* Wait indefinetly for a message */
+  immediate_quit = 1;   /* Helps ability to QUIT */
+  while(1)
+  {
+    while(msg_recv_serial(in_msg_buf)) {
+       QUIT;   /* Let user quit if they want */
+    }
+    switch (in_msg_buf->halt_msg.code)
+    {
+    case HIF_CALL:
+       i = in_msg_buf->hif_call_rtn_msg.service_number;
+       result=service_HIF(in_msg_buf);
+       if(i == 1) /* EXIT */
+           goto exit;
+       if(result)
+           printf("Warning: failure during HIF service %d\n", i);
+       break;
+    case CHANNEL0_ACK:
+       service_HIF(in_msg_buf);
+       break;
+    case CHANNEL1:
+        i=in_msg_buf->channel1_msg.length;
+        in_msg_buf->channel1_msg.data[i] = '\0';
+        printf("%s", in_msg_buf->channel1_msg.data);
+       fflush(stdout);
+        /* Send CHANNEL1_ACK message */
+        out_msg_buf->channel1_ack_msg.code = CHANNEL1_ACK;
+        out_msg_buf->channel1_ack_msg.length = 0;
+        result = msg_send_serial(out_msg_buf);
+       break;
+    case HALT:
+       goto halted;
+    default:
+       goto halted;
+    }
+  }
+halted:
+  /* FIXME, these printfs should not be here.  This is a source level 
+     debugger, guys!  */
+  if (in_msg_buf->halt_msg.trap_number== 0)
+  { printf("Am290*0 received vector number %d (break point)\n",
+       in_msg_buf->halt_msg.trap_number);
+    WSETSTOP ((*status), SIGTRAP);
+  }
+  else if (in_msg_buf->halt_msg.trap_number== 1)
+  { printf("Am290*0 received vector number %d\n",
+       in_msg_buf->halt_msg.trap_number);
+    WSETSTOP ((*status), SIGBUS);
+  }
+  else if (in_msg_buf->halt_msg.trap_number== 3
+        || in_msg_buf->halt_msg.trap_number== 4)
+  { printf("Am290*0 received vector number %d\n",
+       in_msg_buf->halt_msg.trap_number);
+    WSETSTOP ((*status), SIGFPE);
+  }
+  else if (in_msg_buf->halt_msg.trap_number== 5)
+  { printf("Am290*0 received vector number %d\n",
+       in_msg_buf->halt_msg.trap_number);
+    WSETSTOP ((*status), SIGILL);
+  }
+  else if (in_msg_buf->halt_msg.trap_number >= 6
+        && in_msg_buf->halt_msg.trap_number <= 11)
+  { printf("Am290*0 received vector number %d\n",
+       in_msg_buf->halt_msg.trap_number);
+    WSETSTOP ((*status), SIGSEGV);
+  }
+  else if (in_msg_buf->halt_msg.trap_number== 12
+        || in_msg_buf->halt_msg.trap_number== 13)
+  { printf("Am290*0 received vector number %d\n",
+       in_msg_buf->halt_msg.trap_number);
+    WSETSTOP ((*status), SIGILL);
+  }
+  else if (in_msg_buf->halt_msg.trap_number== 14)
+  { printf("Am290*0 received vector number %d\n",
+       in_msg_buf->halt_msg.trap_number);
+    WSETSTOP ((*status), SIGALRM);
+  }
+  else if (in_msg_buf->halt_msg.trap_number== 15)
+    WSETSTOP ((*status), SIGTRAP);
+  else if (in_msg_buf->halt_msg.trap_number >= 16
+        && in_msg_buf->halt_msg.trap_number <= 21)
+  { printf("Am290*0 received vector number %d\n",
+       in_msg_buf->halt_msg.trap_number);
+    WSETSTOP ((*status), SIGINT);
+  }
+  else if (in_msg_buf->halt_msg.trap_number== 22)
+  { printf("Am290*0 received vector number %d\n",
+       in_msg_buf->halt_msg.trap_number);
+    WSETSTOP ((*status), SIGILL);
+  } /* BREAK message was sent */
+  else if (in_msg_buf->halt_msg.trap_number== 75)
+    WSETSTOP ((*status), SIGTRAP);
+  else
+exit:
+    WSETEXIT ((*status), 0);
+
+  timeout = old_timeout;       /* Restore original timeout value */
+  immediate_quit = old_immediate_quit;
+  DEXIT("mm_wait()");
+  return 0;
+}
+
+/******************************************************* REMOTE_FETCH_REGISTERS
+ * Read a remote register 'regno'. 
+ * If regno==-1 then read all the registers.
+ */
+static void 
+mm_fetch_registers (regno)
+int    regno;
+{
+  INT32 *data_p;
+
+  if (regno >= 0)  {
+       fetch_register(regno);
+       return;
+  }
+
+  DENTER("mm_fetch_registers()");
+
+/* Gr1/rsp */
+  out_msg_buf->read_req_msg.byte_count = 4*1;
+  out_msg_buf->read_req_msg.memory_space = GLOBAL_REG;
+  out_msg_buf->read_req_msg.address = 1;
+  msg_send_serial(out_msg_buf);
+  expect_msg(READ_ACK,in_msg_buf,1);
+  data_p = &(in_msg_buf->read_r_ack_msg.data[0]);
+  supply_register (GR1_REGNUM , data_p);
+
+#if defined(GR64_REGNUM)       /* Read gr64-127 */
+/* Global Registers gr64-gr95 */ 
+  out_msg_buf->read_req_msg.code= READ_REQ;
+  out_msg_buf->read_req_msg.length = 4*3;
+  out_msg_buf->read_req_msg.byte_count = 4*32;
+  out_msg_buf->read_req_msg.memory_space = GLOBAL_REG;
+  out_msg_buf->read_req_msg.address = 64;
+  msg_send_serial(out_msg_buf);
+  expect_msg(READ_ACK,in_msg_buf,1);
+  data_p = &(in_msg_buf->read_r_ack_msg.data[0]);
+
+  for (regno=GR64_REGNUM; regno<GR64_REGNUM+32; regno++) {
+      supply_register (regno, data_p++);
+  }
+#endif /*  GR64_REGNUM */
+
+/* Global Registers gr96-gr127 */ 
+  out_msg_buf->read_req_msg.code= READ_REQ;
+  out_msg_buf->read_req_msg.length = 4*3;
+  out_msg_buf->read_req_msg.byte_count = 4 * 32;
+  out_msg_buf->read_req_msg.memory_space = GLOBAL_REG;
+  out_msg_buf->read_req_msg.address = 96;
+  msg_send_serial(out_msg_buf);
+  expect_msg(READ_ACK,in_msg_buf,1);
+  data_p = &(in_msg_buf->read_r_ack_msg.data[0]);
+
+  for (regno=GR96_REGNUM; regno<GR96_REGNUM+32; regno++) {
+      supply_register (regno, data_p++);
+  }
+
+/* Local Registers */ 
+  out_msg_buf->read_req_msg.byte_count = 4 * (128);
+  out_msg_buf->read_req_msg.memory_space = LOCAL_REG;
+  out_msg_buf->read_req_msg.address = 0;
+  msg_send_serial(out_msg_buf);
+  expect_msg(READ_ACK,in_msg_buf,1);
+  data_p = &(in_msg_buf->read_r_ack_msg.data[0]);
+
+  for (regno=LR0_REGNUM; regno<LR0_REGNUM+128; regno++) {
+      supply_register (regno, data_p++);
+  }
+
+/* Protected Special Registers */ 
+  out_msg_buf->read_req_msg.byte_count = 4*15;
+  out_msg_buf->read_req_msg.memory_space = SPECIAL_REG;
+  out_msg_buf->read_req_msg.address = 0;
+  msg_send_serial( out_msg_buf);
+  expect_msg(READ_ACK,in_msg_buf,1);
+  data_p = &(in_msg_buf->read_r_ack_msg.data[0]);
+
+  for (regno=0; regno<=14; regno++) {
+      supply_register (SR_REGNUM(regno), data_p++);
+  }
+  if (USE_SHADOW_PC) { /* Let regno_to_srnum() handle the register number */
+       fetch_register(NPC_REGNUM);
+       fetch_register(PC_REGNUM);
+       fetch_register(PC2_REGNUM);
+  }
+
+/* Unprotected Special Registers */ 
+  out_msg_buf->read_req_msg.byte_count = 4*8;
+  out_msg_buf->read_req_msg.memory_space = SPECIAL_REG;
+  out_msg_buf->read_req_msg.address = 128;
+  msg_send_serial( out_msg_buf);
+  expect_msg(READ_ACK,in_msg_buf,1);
+  data_p = &(in_msg_buf->read_r_ack_msg.data[0]);
+
+  for (regno=128; regno<=135; regno++) {
+      supply_register (SR_REGNUM(regno), data_p++);
+  }
+
+  /* There doesn't seem to be any way to get these.  */
+  {
+    int val = -1;
+    supply_register (FPE_REGNUM, &val);
+    supply_register (INT_REGNUM, &val);
+    supply_register (FPS_REGNUM, &val);
+    supply_register (EXO_REGNUM, &val);
+  }
+
+  DEXIT("mm_fetch_registerS()");
+}
+
+
+/****************************************************** REMOTE_STORE_REGISTERS
+** Store register regno into the target.  
+ * If regno==-1 then store all the registers.
+ */
+
+static int 
+mm_store_registers (regno)
+int regno;
+{
+  
+  if (regno >= 0)
+       return(store_register(regno));
+
+  DENTER("mm_store_registers()");
+
+  out_msg_buf->write_r_msg.code= WRITE_REQ;
+
+/* Gr1/rsp */
+  out_msg_buf->write_r_msg.byte_count = 4*1;
+  out_msg_buf->write_r_msg.length = 3*4 + out_msg_buf->write_r_msg.byte_count;
+  out_msg_buf->write_r_msg.memory_space = GLOBAL_REG;
+  out_msg_buf->write_r_msg.address = 1;
+  out_msg_buf->write_r_msg.data[0] = read_register (GR1_REGNUM);
+
+  msg_send_serial( out_msg_buf);
+  expect_msg(WRITE_ACK,in_msg_buf,1);
+
+#if defined(GR64_REGNUM)
+/* Global registers gr64-gr95 */
+  out_msg_buf->write_r_msg.byte_count = 4* (32);
+  out_msg_buf->write_r_msg.length = 3*4 + out_msg_buf->write_r_msg.byte_count;
+  out_msg_buf->write_r_msg.address = 64;
+
+  for (regno=GR64_REGNUM ; regno<GR64_REGNUM+32 ; regno++)
+    {
+      out_msg_buf->write_r_msg.data[regno-GR64_REGNUM] = read_register (regno);
+    }
+  msg_send_serial(out_msg_buf);
+  expect_msg(WRITE_ACK,in_msg_buf,1);
+#endif /* GR64_REGNUM */
+
+/* Global registers gr96-gr127 */
+  out_msg_buf->write_r_msg.byte_count = 4* (32);
+  out_msg_buf->write_r_msg.length = 3*4 + out_msg_buf->write_r_msg.byte_count;
+  out_msg_buf->write_r_msg.address = 96;
+  for (regno=GR96_REGNUM ; regno<GR96_REGNUM+32 ; regno++)
+    {
+      out_msg_buf->write_r_msg.data[regno-GR96_REGNUM] = read_register (regno);
+    }
+  msg_send_serial( out_msg_buf);
+  expect_msg(WRITE_ACK,in_msg_buf,1);
+
+/* Local Registers */
+  out_msg_buf->write_r_msg.memory_space = LOCAL_REG;
+  out_msg_buf->write_r_msg.byte_count = 4*128;
+  out_msg_buf->write_r_msg.length = 3*4 + out_msg_buf->write_r_msg.byte_count;
+  out_msg_buf->write_r_msg.address = 0;
+
+  for (regno = LR0_REGNUM ; regno < LR0_REGNUM+128 ; regno++)
+    {
+      out_msg_buf->write_r_msg.data[regno-LR0_REGNUM] = read_register (regno);
+    }
+  msg_send_serial( out_msg_buf);
+  expect_msg(WRITE_ACK,in_msg_buf,1);
+
+/* Protected Special Registers */ 
+  /* VAB through TMR */
+  out_msg_buf->write_r_msg.memory_space = SPECIAL_REG;
+  out_msg_buf->write_r_msg.byte_count = 4* 10;
+  out_msg_buf->write_r_msg.length = 3*4 + out_msg_buf->write_r_msg.byte_count;
+  out_msg_buf->write_r_msg.address = 0;
+  for (regno = 0 ; regno<=9 ; regno++) /* VAB through TMR */
+    out_msg_buf->write_r_msg.data[regno] = read_register (SR_REGNUM(regno));
+  msg_send_serial( out_msg_buf);
+  expect_msg(WRITE_ACK,in_msg_buf,1);
+
+  /* PC0, PC1, PC2 possibly as shadow registers */
+  out_msg_buf->write_r_msg.byte_count = 4* 3;
+  out_msg_buf->write_r_msg.length = 3*4 + out_msg_buf->write_r_msg.byte_count;
+  for (regno=10 ; regno<=12 ; regno++) /* LRU and MMU */
+    out_msg_buf->write_r_msg.data[regno-10] = read_register (SR_REGNUM(regno));
+  if (USE_SHADOW_PC) 
+    out_msg_buf->write_r_msg.address = 20;     /* SPC0 */
+  else 
+    out_msg_buf->write_r_msg.address = 10;     /* PC0 */
+  msg_send_serial( out_msg_buf);
+  expect_msg(WRITE_ACK,in_msg_buf,1);
+
+  /* LRU and MMU */
+  out_msg_buf->write_r_msg.byte_count = 4* 2;
+  out_msg_buf->write_r_msg.length = 3*4 + out_msg_buf->write_r_msg.byte_count;
+  out_msg_buf->write_r_msg.address = 13;
+  for (regno=13 ; regno<=14 ; regno++) /* LRU and MMU */
+    out_msg_buf->write_r_msg.data[regno-13] = read_register (SR_REGNUM(regno));
+  msg_send_serial( out_msg_buf);
+  expect_msg(WRITE_ACK,in_msg_buf,1);
+
+/* Unprotected Special Registers */ 
+  out_msg_buf->write_r_msg.byte_count = 4*8;
+  out_msg_buf->write_r_msg.length = 3*4 + out_msg_buf->write_r_msg.byte_count;
+  out_msg_buf->write_r_msg.address = 128;
+  for (regno = 128 ; regno<=135 ; regno++)
+    out_msg_buf->write_r_msg.data[regno-128] = read_register(SR_REGNUM(regno));
+  msg_send_serial( out_msg_buf);
+  expect_msg(WRITE_ACK,in_msg_buf,1);
+  registers_changed ();
+  DEXIT("mm_store_registers()");
+}
+
+/*************************************************** REMOTE_PREPARE_TO_STORE */
+/* Get ready to modify the registers array.  On machines which store
+   individual registers, this doesn't need to do anything.  On machines
+   which store all the registers in one fell swoop, this makes sure
+   that registers contains all the registers from the program being
+   debugged.  */
+
+static void
+mm_prepare_to_store ()
+{
+  /* Do nothing, since we can store individual regs */
+}
+
+/******************************************************* REMOTE_XFER_MEMORY */
+static CORE_ADDR
+translate_addr(addr)
+CORE_ADDR addr;
+{
+#if defined(KERNEL_DEBUGGING)
+        /* Check for a virtual address in the kernel */
+        /* Assume physical address of ublock is in  paddr_u register */
+       /* FIXME: doesn't work for user virtual addresses */
+        if (addr >= UVADDR) {
+                /* PADDR_U register holds the physical address of the ublock */
+                CORE_ADDR i = (CORE_ADDR)read_register(PADDR_U_REGNUM);
+                return(i + addr - (CORE_ADDR)UVADDR);
+        } else {
+               return(addr);
+        }
+#else
+        return(addr);
+#endif
+}
+/* FIXME!  Merge these two.  */
+static int
+mm_xfer_inferior_memory (memaddr, myaddr, len, write)
+     CORE_ADDR memaddr;
+     char *myaddr;
+     int len;
+     int write;
+{
+
+  memaddr = translate_addr(memaddr);
+
+  if (write)
+    return mm_write_inferior_memory (memaddr, myaddr, len);
+  else
+    return mm_read_inferior_memory (memaddr, myaddr, len);
+}
+
+/******************************************************* REMOTE_FILES_INFO */
+static void
+mm_files_info ()
+{
+  printf ("\tAttached to %s at %d baud and running program %s.\n",
+          dev_name, baudrate, prog_name);
+}
+
+/************************************************* REMOTE_INSERT_BREAKPOINT */
+static int
+mm_insert_breakpoint (addr, contents_cache)
+     CORE_ADDR addr;
+     char *contents_cache;
+{
+  DENTER("mm_insert_breakpoint()");
+  out_msg_buf->bkpt_set_msg.code = BKPT_SET;
+  out_msg_buf->bkpt_set_msg.length = 4*4;
+  out_msg_buf->bkpt_set_msg.memory_space = I_MEM;
+  out_msg_buf->bkpt_set_msg.bkpt_addr = (ADDR32) addr;
+  out_msg_buf->bkpt_set_msg.pass_count = 1;
+  out_msg_buf->bkpt_set_msg.bkpt_type = -1;    /* use illop for 29000 */
+  msg_send_serial( out_msg_buf);
+  if (expect_msg(BKPT_SET_ACK,in_msg_buf,1)) {
+       DEXIT("mm_insert_breakpoint() success");
+       return 0;               /* Success */
+  } else {
+       DEXIT("mm_insert_breakpoint() failure");
+       return 1;               /* Failure */
+  }
+}
+
+/************************************************* REMOTE_DELETE_BREAKPOINT */
+static int
+mm_remove_breakpoint (addr, contents_cache)
+     CORE_ADDR addr;
+     char *contents_cache;
+{
+  DENTER("mm_remove_breakpoint()");
+  out_msg_buf->bkpt_rm_msg.code = BKPT_RM;
+  out_msg_buf->bkpt_rm_msg.length = 4*3;
+  out_msg_buf->bkpt_rm_msg.memory_space = I_MEM;
+  out_msg_buf->bkpt_rm_msg.bkpt_addr = (ADDR32) addr;
+  msg_send_serial( out_msg_buf);
+  if (expect_msg(BKPT_RM_ACK,in_msg_buf,1)) {
+       DEXIT("mm_remove_breakpoint()");
+       return 0;               /* Success */
+  } else {
+       DEXIT("mm_remove_breakpoint()");
+       return 1;               /* Failure */
+  }
+}
+
+
+/******************************************************* REMOTE_KILL */
+static void
+mm_kill(arg,from_tty)
+char    *arg;
+int     from_tty;
+{
+       char    buf[4];
+
+       DENTER("mm_kill()");
+#if defined(KERNEL_DEBUGGING)
+       /* We don't ever kill the kernel */
+       if (from_tty) {
+               printf("Kernel not killed, but left in current state.\n");
+               printf("Use detach to leave kernel running.\n");
+       }
+#else
+       out_msg_buf->break_msg.code = BREAK;
+       out_msg_buf->bkpt_set_msg.length = 4*0;
+       expect_msg(HALT,in_msg_buf,from_tty);
+       if (from_tty) {
+               printf("Target has been stopped.");
+               printf("Would you like to do a hardware reset (y/n) [n] ");
+               fgets(buf,3,stdin);     
+               if (buf[0] == 'y') {
+                       out_msg_buf->reset_msg.code = RESET;
+                       out_msg_buf->bkpt_set_msg.length = 4*0;
+                       expect_msg(RESET_ACK,in_msg_buf,from_tty);
+                       printf("Target has been reset.");
+               }
+       }
+       pop_target();
+#endif 
+       DEXIT("mm_kill()");
+}
+
+
+
+/***************************************************************************/
+/* 
+ * Load a program into the target.
+ */
+static void
+mm_load(arg_string,from_tty)
+char   *arg_string;
+int    from_tty;
+{
+  dont_repeat ();
+
+#if defined(KERNEL_DEBUGGING)
+  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);
+  make_cleanup (free, arg_string);
+  QUIT;
+  immediate_quit++;
+  error("File loading is not yet supported for MiniMon.");
+  /* FIXME, code to load your file here... */
+  /* You may need to do an init_target_mm() */
+  /* init_target_mm(?,?,?,?,?,?,?,?); */
+  immediate_quit--;
+  symbol_file_add (arg_string, from_tty, text_addr, 0);
+#endif
+
+}
+
+/************************************************ REMOTE_WRITE_INFERIOR_MEMORY
+** Copy LEN bytes of data from debugger memory at MYADDR
+   to inferior's memory at MEMADDR.  Returns number of bytes written.  */
+static int
+mm_write_inferior_memory (memaddr, myaddr, len)
+     CORE_ADDR memaddr;
+     char *myaddr;
+     int len;
+{
+  int i,nwritten;
+
+  /* DENTER("mm_write_inferior_memory()"); */
+  out_msg_buf->write_req_msg.code= WRITE_REQ;
+  out_msg_buf->write_req_msg.memory_space = mm_memory_space(memaddr);  
+
+  nwritten=0;
+  while (nwritten < len) {
+       int num_to_write = len - nwritten;
+       if (num_to_write > MAXDATA) num_to_write = MAXDATA;
+       for (i=0 ; i < num_to_write ; i++)
+               out_msg_buf->write_req_msg.data[i] = myaddr[i+nwritten];
+       out_msg_buf->write_req_msg.byte_count = num_to_write;
+       out_msg_buf->write_req_msg.length = 3*4 + num_to_write; 
+       out_msg_buf->write_req_msg.address = memaddr + nwritten;
+       msg_send_serial(out_msg_buf);
+
+       if (expect_msg(WRITE_ACK,in_msg_buf,1)) {
+               nwritten += in_msg_buf->write_ack_msg.byte_count;
+       } else {
+               break;  
+       }
+  }
+  /* DEXIT("mm_write_inferior_memory()"); */
+  return(nwritten);
+}
+
+/************************************************* REMOTE_READ_INFERIOR_MEMORY
+** Read LEN bytes from inferior memory at MEMADDR.  Put the result
+   at debugger address MYADDR.  Returns number of bytes read.  */
+static int
+mm_read_inferior_memory(memaddr, myaddr, len)
+     CORE_ADDR memaddr;
+     char *myaddr;
+     int len;
+{
+  int i,nread;
+
+  /* DENTER("mm_read_inferior_memory()"); */
+  out_msg_buf->read_req_msg.code= READ_REQ;
+  out_msg_buf->read_req_msg.memory_space = mm_memory_space(memaddr);
+
+  nread=0;
+  while (nread < len) {
+       int num_to_read = (len - nread);
+       if (num_to_read > MAXDATA) num_to_read = MAXDATA;
+       out_msg_buf->read_req_msg.byte_count = num_to_read; 
+       out_msg_buf->read_req_msg.length = 3*4 + num_to_read; 
+       out_msg_buf->read_req_msg.address = memaddr + nread;
+       msg_send_serial(out_msg_buf);
+
+       if (expect_msg(READ_ACK,in_msg_buf,1)) {
+               for (i=0 ; i<in_msg_buf->read_ack_msg.byte_count ; i++)
+                       myaddr[i+nread] = in_msg_buf->read_ack_msg.data[i];
+               nread += in_msg_buf->read_ack_msg.byte_count;
+       } else {
+               break;  
+       }
+  }
+  return(nread);
+}
+
+/********************************************************** MSG_SEND_SERIAL
+** This function is used to send a message over the
+** serial line.
+**
+** If the message is successfully sent, a zero is
+** returned.  If the message was not sendable, a -1
+** is returned.  This function blocks.  That is, it
+** does not return until the message is completely
+** sent, or until an error is encountered.
+**
+*/
+
+int
+msg_send_serial(msg_ptr)
+   union  msg_t  *msg_ptr;
+{
+   INT32  message_size;
+   int    byte_count;
+   int    result;
+   char   c;
+
+   /* Send message header */
+   byte_count = 0;
+   message_size = msg_ptr->generic_msg.length + (2 * sizeof(INT32));
+   do {
+      c = *((char *)msg_ptr+byte_count);
+      result = write(mm_desc, &c, 1);
+      if (result == 1) {
+         byte_count = byte_count + 1;
+      }
+   } while ((byte_count < message_size) );
+
+   return(0);
+}  /* end msg_send_serial() */
+
+/********************************************************** MSG_RECV_SERIAL
+** This function is used to receive a message over a
+** serial line.
+**
+** If the message is waiting in the buffer, a zero is
+** returned and the buffer pointed to by msg_ptr is filled
+** in.  If no message was available, a -1 is returned.
+** If timeout==0, wait indefinetly for a character.
+**
+*/
+
+int
+msg_recv_serial(msg_ptr)
+union  msg_t  *msg_ptr;
+{
+   static INT32  length=0;
+   static INT32  byte_count=0;
+   int    result;
+   char   c;
+  if(msg_ptr == 0)             /* re-sync request */
+  {  length=0;
+     byte_count=0;
+#ifdef HAVE_TERMIO
+     /* The timeout here is the prevailing timeout set with VTIME */
+     ->"timeout==0 semantics not supported"
+     read(mm_desc, in_buf, BUFER_SIZE);
+#else
+     alarm (1);
+     read(mm_desc, in_buf, BUFER_SIZE);
+     alarm (0);
+#endif
+     return(0);
+  }
+   /* Receive message */
+#ifdef HAVE_TERMIO
+/* Timeout==0, help support the mm_wait() routine */
+   ->"timeout==0 semantics not supported (and its nice if they are)"
+   result = read(mm_desc, &c, 1);
+#else
+  alarm(timeout);
+  result = read(mm_desc, &c, 1);
+  alarm (0);
+#endif
+  if ( result < 0) {
+      if (errno == EINTR) {
+       error ("Timeout reading from remote system.");
+      } else
+       perror_with_name ("remote");
+  } else if (result == 1) {
+      *((char *)msg_ptr+byte_count) = c;
+      byte_count = byte_count + 1;
+  }
+
+   /* Message header received.  Save message length. */
+  if (byte_count == (2 * sizeof(INT32)))
+      length = msg_ptr->generic_msg.length;
+
+  if (byte_count >= (length + (2 * sizeof(INT32)))) {
+      /* Message received */
+      byte_count = 0;
+      return(0);
+  } else
+      return (-1);
+
+}  /* end msg_recv_serial() */
+
+/********************************************************************* KBD_RAW
+** This function is used to put the keyboard in "raw"
+** mode for BSD Unix.  The original status is saved
+** so that it may be restored later.
+*/
+TERMINAL kbd_tbuf;
+
+int
+kbd_raw() {
+   int    result;
+   TERMINAL tbuf;
+
+   /* Get keyboard termio (to save to restore original modes) */
+#ifdef HAVE_TERMIO
+   result = ioctl(0, TCGETA, &kbd_tbuf);
+#else
+   result = ioctl(0, TIOCGETP, &kbd_tbuf);
+#endif
+   if (result == -1)
+      return (errno);
+
+   /* Get keyboard TERMINAL (for modification) */
+#ifdef HAVE_TERMIO
+   result = ioctl(0, TCGETA, &tbuf);
+#else
+   result = ioctl(0, TIOCGETP, &tbuf);
+#endif
+   if (result == -1)
+      return (errno);
+
+   /* Set up new parameters */
+#ifdef HAVE_TERMIO
+   tbuf.c_iflag = tbuf.c_iflag &
+      ~(INLCR | ICRNL | IUCLC | ISTRIP | IXON | BRKINT);
+   tbuf.c_lflag = tbuf.c_lflag & ~(ICANON | ISIG | ECHO);
+   tbuf.c_cc[4] = 0;  /* MIN */
+   tbuf.c_cc[5] = 0;  /* TIME */
+#else
+   /* FIXME: not sure if this is correct (matches HAVE_TERMIO). */
+   tbuf.sg_flags |= RAW;
+   tbuf.sg_flags |= ANYP;
+   tbuf.sg_flags &= ~ECHO;
+#endif
+
+   /* Set keyboard termio to new mode (RAW) */
+#ifdef HAVE_TERMIO
+   result = ioctl(0, TCSETAF, &tbuf);
+#else
+   result = ioctl(0, TIOCSETP, &tbuf);
+#endif 
+   if (result == -1)
+      return (errno);
+
+   return (0);
+}  /* end kbd_raw() */
+
+
+
+/***************************************************************** KBD_RESTORE
+** This function is used to put the keyboard back in the
+** mode it was in before kbk_raw was called.  Note that
+** kbk_raw() must have been called at least once before
+** kbd_restore() is called.
+*/
+
+int
+kbd_restore() {
+   int result;
+
+   /* Set keyboard termio to original mode */
+#ifdef HAVE_TERMIO
+   result = ioctl(0, TCSETAF, &kbd_tbuf);
+#else
+   result = ioctl(0, TIOCGETP, &kbd_tbuf);
+#endif
+
+   if (result == -1)
+      return (errno);
+
+   return(0);
+}  /* end kbd_cooked() */
+
+
+/*****************************************************************************/ 
+/* Fetch a single register indicatated by 'regno'. 
+ * Returns 0/-1 on success/failure.  
+ */
+static int
+fetch_register (regno)
+     int regno;
+{
+     int  result;
+  DENTER("mm_fetch_register()");
+  out_msg_buf->read_req_msg.code= READ_REQ;
+  out_msg_buf->read_req_msg.length = 4*3;
+  out_msg_buf->read_req_msg.byte_count = 4;
+
+  if (regno == GR1_REGNUM)
+  { out_msg_buf->read_req_msg.memory_space = GLOBAL_REG;
+    out_msg_buf->read_req_msg.address = 1;
+  }
+  else if (regno >= GR96_REGNUM && regno < GR96_REGNUM + 32)
+  { out_msg_buf->read_req_msg.memory_space = GLOBAL_REG;
+    out_msg_buf->read_req_msg.address = (regno - GR96_REGNUM) + 96;
+  }
+#if defined(GR64_REGNUM)
+  else if (regno >= GR64_REGNUM && regno < GR64_REGNUM + 32 )
+  { out_msg_buf->read_req_msg.memory_space = GLOBAL_REG;
+    out_msg_buf->read_req_msg.address = (regno - GR64_REGNUM) + 64;
+  }
+#endif /* GR64_REGNUM */
+  else if (regno >= LR0_REGNUM && regno < LR0_REGNUM + 128)
+  { out_msg_buf->read_req_msg.memory_space = LOCAL_REG;
+    out_msg_buf->read_req_msg.address = (regno - LR0_REGNUM);
+  }
+  else if (regno>=FPE_REGNUM && regno<=EXO_REGNUM)  
+  { int val = -1;
+    supply_register(160 + (regno - FPE_REGNUM),&val);
+    return 0;          /* Pretend Success */
+  }
+  else 
+  { out_msg_buf->read_req_msg.memory_space = SPECIAL_REG;
+    out_msg_buf->read_req_msg.address = regnum_to_srnum(regno); 
+  } 
+
+  msg_send_serial(out_msg_buf);
+
+  if (expect_msg(READ_ACK,in_msg_buf,1)) {
+       supply_register (regno, &(in_msg_buf->read_r_ack_msg.data[0]));
+       result = 0;
+  } else {
+       result = -1;
+  }
+  DEXIT("mm_fetch_register()");
+  return result;
+}
+/*****************************************************************************/ 
+/* Store a single register indicated by 'regno'. 
+ * Returns 0/-1 on success/failure.  
+ */
+static int
+store_register (regno)
+     int regno;
+{
+     int  result;
+
+  DENTER("store_register()");
+  out_msg_buf->write_req_msg.code= WRITE_REQ;
+  out_msg_buf->write_req_msg.length = 4*4;
+  out_msg_buf->write_req_msg.byte_count = 4;
+  out_msg_buf->write_r_msg.data[0] = read_register (regno);
+
+  if (regno == GR1_REGNUM)
+  { out_msg_buf->write_req_msg.memory_space = GLOBAL_REG;
+    out_msg_buf->write_req_msg.address = 1;
+    /* 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 )
+  { out_msg_buf->write_req_msg.memory_space = GLOBAL_REG;
+    out_msg_buf->write_req_msg.address = (regno - GR64_REGNUM) + 64;
+  }
+#endif /* GR64_REGNUM */
+  else if (regno >= GR96_REGNUM && regno < GR96_REGNUM + 32)
+  { out_msg_buf->write_req_msg.memory_space = GLOBAL_REG;
+    out_msg_buf->write_req_msg.address = (regno - GR96_REGNUM) + 96;
+  }
+  else if (regno >= LR0_REGNUM && regno < LR0_REGNUM + 128)
+  { out_msg_buf->write_req_msg.memory_space = LOCAL_REG;
+    out_msg_buf->write_req_msg.address = (regno - LR0_REGNUM);
+  }
+  else if (regno>=FPE_REGNUM && regno<=EXO_REGNUM)  
+  { 
+    return 0;          /* Pretend Success */
+  }
+  else         /* An unprotected or protected special register */
+  { out_msg_buf->write_req_msg.memory_space = SPECIAL_REG;
+    out_msg_buf->write_req_msg.address = regnum_to_srnum(regno); 
+  } 
+
+  msg_send_serial(out_msg_buf);
+
+  if (expect_msg(WRITE_ACK,in_msg_buf,1)) {
+       result = 0;
+  } else {
+       result = -1;
+  }
+  DEXIT("store_register()");
+  return result;
+}
+/****************************************************************************/
+/* 
+ * Convert a gdb special register number to a 29000 special register number.
+ */
+static int
+regnum_to_srnum(regno)
+int    regno;
+{
+       switch(regno) {
+               case VAB_REGNUM: return(0); 
+               case OPS_REGNUM: return(1); 
+               case CPS_REGNUM: return(2); 
+               case CFG_REGNUM: return(3); 
+               case CHA_REGNUM: return(4); 
+               case CHD_REGNUM: return(5); 
+               case CHC_REGNUM: return(6); 
+               case RBP_REGNUM: return(7); 
+               case TMC_REGNUM: return(8); 
+               case TMR_REGNUM: return(9); 
+               case NPC_REGNUM: return(USE_SHADOW_PC ? (20) : (10));
+               case PC_REGNUM:  return(USE_SHADOW_PC ? (21) : (11));
+               case PC2_REGNUM: return(USE_SHADOW_PC ? (22) : (12));
+               case MMU_REGNUM: return(13); 
+               case LRU_REGNUM: return(14); 
+               case IPC_REGNUM: return(128); 
+               case IPA_REGNUM: return(129); 
+               case IPB_REGNUM: return(130); 
+               case Q_REGNUM:   return(131); 
+               case ALU_REGNUM: return(132); 
+               case BP_REGNUM:  return(133); 
+               case FC_REGNUM:  return(134); 
+               case CR_REGNUM:  return(135); 
+               case FPE_REGNUM: return(160); 
+               case INT_REGNUM: return(161); 
+               case FPS_REGNUM: return(162); 
+               case EXO_REGNUM:return(164); 
+               default:
+                       return(255);    /* Failure ? */
+       }
+}
+/****************************************************************************/
+/* 
+ * Initialize the target debugger (minimon only).
+ */
+static void
+init_target_mm(tstart,tend,dstart,dend,entry,ms_size,rs_size,arg_start)
+ADDR32 tstart,tend,dstart,dend,entry;
+INT32  ms_size,rs_size;
+ADDR32 arg_start;
+{
+       out_msg_buf->init_msg.code = INIT;
+       out_msg_buf->init_msg.length= sizeof(struct init_msg_t)-2*sizeof(INT32);
+       out_msg_buf->init_msg.text_start = tstart;
+       out_msg_buf->init_msg.text_end = tend;
+       out_msg_buf->init_msg.data_start = dstart;
+       out_msg_buf->init_msg.data_end = dend;
+       out_msg_buf->init_msg.entry_point = entry;
+       out_msg_buf->init_msg.mem_stack_size = ms_size;
+       out_msg_buf->init_msg.reg_stack_size = rs_size;
+       out_msg_buf->init_msg.arg_start = arg_start;
+       msg_send_serial(out_msg_buf);
+       expect_msg(INIT_ACK,in_msg_buf,1);
+}
+/****************************************************************************/
+/* 
+ * Return a pointer to a string representing the given message code.
+ * Not all messages are represented here, only the ones that we expect
+ * to be called with.
+ */
+static char*
+msg_str(code)
+INT32  code;
+{
+       static char cbuf[32];
+
+       switch (code) {
+       case BKPT_SET_ACK: sprintf(cbuf,"%s (%d)","BKPT_SET_ACK",code); break; 
+       case BKPT_RM_ACK: sprintf(cbuf,"%s (%d)","BKPT_RM_ACK",code); break; 
+       case INIT_ACK:    sprintf(cbuf,"%s (%d)","INIT_ACK",code); break; 
+       case READ_ACK:    sprintf(cbuf,"%s (%d)","READ_ACK",code); break; 
+       case WRITE_ACK:   sprintf(cbuf,"%s (%d)","WRITE_ACK",code); break; 
+       case ERROR:       sprintf(cbuf,"%s (%d)","ERROR",code); break; 
+       case HALT:      sprintf(cbuf,"%s (%d)","HALT",code); break; 
+       default:        sprintf(cbuf,"UNKNOWN (%d)",code); break; 
+       }
+       return(cbuf);
+}
+/****************************************************************************/
+/*
+ * Selected (not all of them) error codes that we might get.
+ */
+static char* 
+error_msg_str(code)
+INT32  code;
+{
+       static char cbuf[50];
+
+       switch (code) {
+       case EMFAIL:    return("EMFAIL: unrecoverable error"); 
+       case EMBADADDR: return("EMBADADDR: Illegal address"); 
+       case EMBADREG:  return("EMBADREG: Illegal register "); 
+       case EMACCESS:  return("EMACCESS: Could not access memory");
+       case EMBADMSG:  return("EMBADMSG: Unknown message type"); 
+       case EMMSG2BIG: return("EMMSG2BIG: Message to large"); 
+       case EMNOSEND:  return("EMNOSEND: Could not send message"); 
+       case EMNORECV:  return("EMNORECV: Could not recv message"); 
+       case EMRESET:   return("EMRESET: Could not RESET target"); 
+       case EMCONFIG:  return("EMCONFIG: Could not get target CONFIG"); 
+       case EMSTATUS:  return("EMSTATUS: Could not get target STATUS"); 
+       case EMREAD:    return("EMREAD: Could not READ target memory"); 
+       case EMWRITE:   return("EMWRITE: Could not WRITE target memory"); 
+       case EMBKPTSET: return("EMBKPTSET: Could not set breakpoint"); 
+       case EMBKPTRM:  return("EMBKPTRM: Could not remove breakpoint"); 
+       case EMBKPTSTAT:return("EMBKPTSTAT: Could not get breakpoint status"); 
+       case EMBKPTNONE:return("EMBKPTNONE: All breakpoints in use"); 
+       case EMBKPTUSED:return("EMBKPTUSED: Breakpoints already in use"); 
+       case EMINIT:    return("EMINIT: Could not init target memory"); 
+       case EMGO:      return("EMGO: Could not start execution"); 
+       case EMSTEP:    return("EMSTEP: Could not single step"); 
+       case EMBREAK:   return("EMBREAK: Could not BREAK"); 
+       case EMCOMMERR: return("EMCOMMERR: Communication error"); 
+       default:        sprintf(cbuf,"error number %d",code); break;
+       } /* end switch */
+
+       return (cbuf);
+}
+/****************************************************************************/
+/* 
+ *  Receive a message and expect it to be of type msgcode.
+ *  Returns 0/1 on failure/success.
+ */
+static int
+expect_msg(msgcode,msg_buf,from_tty)
+INT32  msgcode;                /* Msg code we expect */
+union msg_t *msg_buf;          /* Where to put  the message received */
+int    from_tty;               /* Print message on error if non-zero */
+{
+  /* DENTER("expect_msg()"); */
+  int  retries=0;
+  while(msg_recv_serial(msg_buf) && (retries++<MAX_RETRIES)); 
+  if (retries >= MAX_RETRIES) {
+       printf("Expected msg %s, ",msg_str(msgcode));
+       printf("no message received!\n");
+        /* DEXIT("expect_msg() failure"); */
+        return(0);             /* Failure */
+  }
+
+  if (msg_buf->generic_msg.code != msgcode) {
+     if (from_tty) {
+       printf("Expected msg %s, ",msg_str(msgcode));
+       printf("got msg %s\n",msg_str(msg_buf->generic_msg.code));
+        if (msg_buf->generic_msg.code == ERROR) 
+               printf("%s\n",error_msg_str(msg_buf->error_msg.error_code));
+     }
+     /* DEXIT("expect_msg() failure"); */
+     return(0);                        /* Failure */
+  }
+  /* DEXIT("expect_msg() success"); */
+  return(1);                   /* Success */
+}      
+/****************************************************************************/
+/*
+ * Determine the MiniMon memory space qualifier based on the addr. 
+ * FIXME: Can't distinguis I_ROM/D_ROM.  
+ * FIXME: Doesn't know anything about I_CACHE/D_CACHE.
+ */
+static int
+mm_memory_space(addr)
+CORE_ADDR      *addr;
+{
+       ADDR32 tstart = target_config.I_mem_start;
+       ADDR32 tend   = tstart + target_config.I_mem_size;  
+       ADDR32 dstart = target_config.D_mem_start;
+       ADDR32 dend   = tstart + target_config.D_mem_size;  
+       ADDR32 rstart = target_config.ROM_start;
+       ADDR32 rend   = tstart + target_config.ROM_size;  
+
+       if (((ADDR32)addr >= tstart) && ((ADDR32)addr < tend)) { 
+               return I_MEM;
+       } else if (((ADDR32)addr >= dstart) && ((ADDR32)addr < dend)) { 
+               return D_MEM;
+       } else if (((ADDR32)addr >= rstart) && ((ADDR32)addr < rend)) {
+               /* FIXME: how do we determine between D_ROM and I_ROM */
+               return D_ROM;
+       } else  /* FIXME: what do me do now? */
+               return D_MEM;   /* Hmmm! */
+}
+
+/****************************************************************************/
+/* 
+ *  Define the target subroutine names 
+ */
+struct target_ops mm_ops = {
+        "minimon", "Remote AMD/Minimon target",
+       "Remote debug an AMD 290*0 using the MiniMon dbg core on the target",
+        mm_open, mm_close,
+        mm_attach, mm_detach, mm_resume, mm_wait,
+        mm_fetch_registers, mm_store_registers,
+        mm_prepare_to_store, 0, 0,   /* conv_to, conv_from */
+        mm_xfer_inferior_memory,
+        mm_files_info,
+        mm_insert_breakpoint, mm_remove_breakpoint, /* Breakpoints */
+        0, 0, 0, 0, 0,          /* Terminal handling */
+        mm_kill,               /* FIXME, kill */
+        mm_load, 
+        call_function_by_hand,
+        0,                      /* lookup_symbol */
+        mm_create_inferior,  /* create_inferior */
+        mm_mourn,            /* mourn_inferior FIXME */
+        process_stratum, 0, /* next */
+        1, 1, 1, 1, 1,  /* all mem, mem, stack, regs, exec */
+       0,0,            /* sections, sections_end */
+        OPS_MAGIC,              /* Always the last thing */
+};
+
+void
+_initialize_remote_mm()
+{
+  add_target (&mm_ops);
+}
+
+#ifdef NO_HIF_SUPPORT
+service_HIF(msg)
+union msg_t    *msg;
+{
+       return(0);      /* Emulate a failure */
+}
+#endif
diff --git a/gdb/ultra3-xdep.c b/gdb/ultra3-xdep.c
new file mode 100644 (file)
index 0000000..c910e3d
--- /dev/null
@@ -0,0 +1,393 @@
+/* Host-dependent code for GDB, for NYU Ultra3 running Sym1 OS.
+   Copyright (C) 1988, 1989, 1991 Free Software Foundation, Inc.
+   Contributed by David Wood (wood@nyu.edu) at New York University.
+
+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 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
+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; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+#define DEBUG
+#include <stdio.h>
+#include "defs.h"
+#include "param.h"
+#include "frame.h"
+#include "inferior.h"
+#include "symtab.h"
+#include "value.h"
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <signal.h>
+#include <sys/ioctl.h>
+#include <fcntl.h>  
+
+#include "gdbcore.h"
+
+#include <sys/file.h>
+#include <sys/stat.h>
+#include <sys/ptrace.h>
+
+/* Assumes support for AMD's Binary Compatibility Standard
+   for ptrace().  If you define ULTRA3, the ultra3 extensions to
+   ptrace() are used allowing the reading of more than one register
+   at a time. 
+
+   This file assumes KERNEL_DEBUGGING is turned off.  This means
+   that if the user/gdb tries to read gr64-gr95 or any of the 
+   protected special registers we silently return -1 (see the
+   CANNOT_STORE/FETCH_REGISTER macros).  */
+#define        ULTRA3
+
+#if !defined (offsetof)
+# define offsetof(TYPE, MEMBER) ((unsigned long) &((TYPE *)0)->MEMBER)
+#endif
+
+extern int errno;
+struct ptrace_user pt_struct;
+
+/* 
+ * Fetch an individual register (and supply it).
+ * return 0 on success, -1 on failure.
+ * NOTE: Assumes AMD's Binary Compatibility Standard for ptrace().
+ */
+static void
+fetch_register (regno)
+     int regno;
+{
+  char buf[128];
+  int  val;
+
+  if (CANNOT_FETCH_REGISTER(regno)) {
+    val = -1;
+    supply_register (regno, &val);
+  } else {
+    errno = 0;
+    val = ptrace (PT_READ_U, inferior_pid, (int*)register_addr(regno,0), 0);
+    if (errno != 0) {
+      sprintf(buf,"reading register %s (#%d)",reg_names[regno],regno);
+      perror_with_name (buf);
+    } else {
+      supply_register (regno, &val);
+    }
+  }
+}
+
+/* Get all available registers from the inferior.  Registers that are
+ * defined in REGISTER_NAMES, but not available to the user/gdb are
+ * supplied as -1.  This may include gr64-gr95 and the protected special
+ * purpose registers.
+ */
+
+void
+fetch_inferior_registers (regno)
+  int regno;
+{
+  register int i,j,ret_val=0;
+  char buf[128];
+
+  if (regno != -1) {
+    fetch_register (regno);
+    return;
+  }
+
+/* Global Registers */
+#ifdef ULTRA3
+  errno = 0;
+  ptrace (PT_READ_STRUCT, inferior_pid, (int*)register_addr(GR96_REGNUM,0), 
+                                       (int)&pt_struct.pt_gr[0], 32*4);
+  if (errno != 0) {
+      perror_with_name ("reading global registers");
+      ret_val = -1;
+  } else for (regno=GR96_REGNUM, j=0 ; j<32 ; regno++, j++)  {
+      supply_register (regno, &pt_struct.pt_gr[j]);
+  }
+#else
+  for (regno=GR96_REGNUM ; !ret_val && regno < GR96_REGNUM+32 ; regno++)
+    fetch_register(regno);
+#endif
+
+/* Local Registers */
+#ifdef ULTRA3
+  errno = 0;
+  ptrace (PT_READ_STRUCT, inferior_pid, (int*)register_addr(LR0_REGNUM,0), 
+                                       (int)&pt_struct.pt_lr[0], 128*4);
+  if (errno != 0) {
+      perror_with_name ("reading local registers");
+      ret_val = -1;
+  } else for (regno=LR0_REGNUM, j=0 ; j<128 ; regno++, j++)  {
+      supply_register (regno, &pt_struct.pt_lr[j]);
+  }
+#else
+  for (regno=LR0_REGNUM ; !ret_val && regno < LR0_REGNUM+128 ; regno++)
+    fetch_register(regno);
+#endif
+
+/* Special Registers */
+  fetch_register(GR1_REGNUM);
+  fetch_register(CPS_REGNUM);
+  fetch_register(PC_REGNUM);
+  fetch_register(NPC_REGNUM);
+  fetch_register(PC2_REGNUM);
+  fetch_register(IPC_REGNUM);
+  fetch_register(IPA_REGNUM);
+  fetch_register(IPB_REGNUM);
+  fetch_register(Q_REGNUM);
+  fetch_register(BP_REGNUM);
+  fetch_register(FC_REGNUM);
+
+/* Fake any registers that are in REGISTER_NAMES, but not available to gdb */ 
+  registers_fetched();
+}
+
+/* Store our register values back into the inferior.
+ * If REGNO is -1, do this for all registers.
+ * Otherwise, REGNO specifies which register (so we can save time).  
+ * NOTE: Assumes AMD's binary compatibility standard. 
+ */
+
+int
+store_inferior_registers (regno)
+     int regno;
+{
+  register unsigned int regaddr;
+  char buf[80];
+
+  if (regno >= 0)
+    {
+      if (CANNOT_STORE_REGISTER(regno)) 
+       return 0;                       /*  Pretend success */
+      regaddr = register_addr (regno, 0);
+      errno = 0;
+      ptrace (PT_WRITE_U, inferior_pid,(int*)regaddr,read_register(regno));
+      if (errno != 0)
+       {
+         sprintf (buf, "writing register %s (#%d)", reg_names[regno],regno);
+         perror_with_name (buf);
+       }
+    }
+  else
+    {
+#ifdef ULTRA3
+      pt_struct.pt_gr1 = read_register(GR1_REGNUM);
+      for (regno = GR96_REGNUM; regno < GR96_REGNUM+32; regno++)
+       pt_struct.pt_gr[regno] = read_register(regno);
+      for (regno = LR0_REGNUM; regno < LR0_REGNUM+128; regno++)
+       pt_struct.pt_gr[regno] = read_register(regno);
+      errno = 0;
+      ptrace (PT_WRITE_STRUCT, inferior_pid, (int*)register_addr(GR1_REGNUM,0), 
+                               (int)&pt_struct.pt_gr1,(1*32*128)*4);
+      if (errno != 0)
+       {
+          sprintf (buf, "writing all local/global registers");
+          perror_with_name (buf);
+       }
+      pt_struct.pt_psr = read_register(CPS_REGNUM);
+      pt_struct.pt_pc0 = read_register(NPC_REGNUM);
+      pt_struct.pt_pc1 = read_register(PC_REGNUM);
+      pt_struct.pt_pc2 = read_register(PC2_REGNUM);
+      pt_struct.pt_ipc = read_register(IPC_REGNUM);
+      pt_struct.pt_ipa = read_register(IPA_REGNUM);
+      pt_struct.pt_ipb = read_register(IPB_REGNUM);
+      pt_struct.pt_q   = read_register(Q_REGNUM);
+      pt_struct.pt_bp  = read_register(BP_REGNUM);
+      pt_struct.pt_fc  = read_register(FC_REGNUM);
+      errno = 0;
+      ptrace (PT_WRITE_STRUCT, inferior_pid, (int*)register_addr(CPS_REGNUM,0), 
+                               (int)&pt_struct.pt_psr,(10)*4);
+      if (errno != 0)
+       {
+          sprintf (buf, "writing all special registers");
+          perror_with_name (buf);
+          return -1;
+       }
+#else
+      store_inferior_registers(GR1_REGNUM);
+      for (regno=GR96_REGNUM ; regno<GR96_REGNUM+32 ; regno++)
+       store_inferior_registers(regno);
+      for (regno=LR0_REGNUM ; regno<LR0_REGNUM+128 ; regno++)
+       store_inferior_registers(regno);
+      store_inferior_registers(CPS_REGNUM);
+      store_inferior_registers(PC_REGNUM);
+      store_inferior_registers(NPC_REGNUM);
+      store_inferior_registers(PC2_REGNUM);
+      store_inferior_registers(IPC_REGNUM);
+      store_inferior_registers(IPA_REGNUM);
+      store_inferior_registers(IPB_REGNUM);
+      store_inferior_registers(Q_REGNUM);
+      store_inferior_registers(BP_REGNUM);
+      store_inferior_registers(FC_REGNUM);
+#endif /* ULTRA3 */
+    }
+  return 0;
+}
+
+/* 
+ * Read AMD's Binary Compatibilty Standard conforming core file.
+ * struct ptrace_user is the first thing in the core file
+ */
+void
+fetch_core_registers ()
+{
+  register int regno;
+  int  val;
+  char buf[4];
+
+  for (regno = 0 ; regno < NUM_REGS; regno++) {
+    if (!CANNOT_FETCH_REGISTER(regno)) {
+      val = bfd_seek (core_bfd, register_addr (regno, 0), 0);
+      if (val < 0 || (val = bfd_read (buf, sizeof buf, 1, core_bfd)) < 0) {
+        char * buffer = (char *) alloca (strlen (reg_names[regno]) + 35);
+        strcpy (buffer, "Reading core register ");
+        strcat (buffer, reg_names[regno]);
+        perror_with_name (buffer);
+      }
+      supply_register (regno, buf);
+    }
+  }
+
+  /* Fake any registers that are in REGISTER_NAMES, but not available to gdb */ 
+  registers_fetched();
+}
+
+
+/*  
+ * Takes a register number as defined in tm.h via REGISTER_NAMES, and maps
+ * it to an offset in a struct ptrace_user defined by AMD's BCS.
+ * That is, it defines the mapping between gdb register numbers and items in
+ * a struct ptrace_user.
+ * A register protection scheme is set up here.  If a register not
+ * available to the user is specified in 'regno', then an address that
+ * will cause ptrace() to fail is returned.
+ */
+unsigned int 
+register_addr (regno,blockend)
+     unsigned int      regno;
+     char              *blockend;
+{
+  if ((regno >= LR0_REGNUM) && (regno < LR0_REGNUM + 128)) {
+    return(offsetof(struct ptrace_user,pt_lr[regno-LR0_REGNUM]));
+  } else if ((regno >= GR96_REGNUM) && (regno < GR96_REGNUM + 32)) {
+    return(offsetof(struct ptrace_user,pt_gr[regno-GR96_REGNUM]));
+  } else {
+    switch (regno) {
+       case GR1_REGNUM: return(offsetof(struct ptrace_user,pt_gr1));
+       case CPS_REGNUM: return(offsetof(struct ptrace_user,pt_psr));
+       case NPC_REGNUM: return(offsetof(struct ptrace_user,pt_pc0));
+       case PC_REGNUM:  return(offsetof(struct ptrace_user,pt_pc1));
+       case PC2_REGNUM: return(offsetof(struct ptrace_user,pt_pc2));
+       case IPC_REGNUM: return(offsetof(struct ptrace_user,pt_ipc));
+       case IPA_REGNUM: return(offsetof(struct ptrace_user,pt_ipa));
+       case IPB_REGNUM: return(offsetof(struct ptrace_user,pt_ipb));
+       case Q_REGNUM:   return(offsetof(struct ptrace_user,pt_q));
+       case BP_REGNUM:  return(offsetof(struct ptrace_user,pt_bp));
+       case FC_REGNUM:  return(offsetof(struct ptrace_user,pt_fc));
+       default:
+            fprintf_filtered(stderr,"register_addr():Bad register %s (%d)\n", 
+                               reg_names[regno],regno);
+            return(0xffffffff);        /* Should make ptrace() fail */
+    }
+  }
+}
+
+
+/* Assorted operating system circumventions */
+
+#ifdef SYM1
+
+/* FIXME: Kludge this for now. It really should be system call. */
+int
+getpagesize()
+{ return(8192); }
+
+/* FIXME: Fake out the fcntl() call, which we don't have.  */
+fcntl(fd, cmd, arg)
+int fd, cmd, arg;
+{
+
+  switch (cmd) {
+       case F_GETFL: return(O_RDONLY); break;
+       default:        
+               printf("Ultra3's fcntl() failing, cmd = %d.\n",cmd);
+               return(-1);
+  }
+}
+
+
+/* 
+ * 4.2 Signal support, requires linking with libjobs.
+ */
+static int     _SigMask;
+#define sigbit(s)       (1L << ((s)-1))
+
+init_SigMask()
+{
+       /* Taken from the sym1 kernel in machdep.c:startup() */
+       _SigMask = sigbit (SIGTSTP) | sigbit (SIGTTOU) | sigbit (SIGTTIN) |
+                        sigbit (SIGCHLD) | sigbit (SIGTINT);
+}
+
+sigmask(signo)
+       int signo;
+{
+       return (1 << (signo-1));
+}
+
+sigsetmask(sigmask)
+unsigned int sigmask;
+{
+       int i, mask = 1;
+       int lastmask = _SigMask;
+
+       for (i=0 ; i<NSIG ; i++) {
+               if (sigmask & mask) { 
+                       if (!(_SigMask & mask)) {
+                               sighold(i+1);
+                               _SigMask |= mask;
+                       }
+               } else if (_SigMask & mask) {
+                       sigrelse(i+1);
+                       _SigMask &= ~mask;
+               }
+               mask <<= 1;
+       }
+       return (lastmask);
+}
+
+sigblock(sigmask)
+unsigned int sigmask;
+{
+       int i, mask = 1;
+       int lastmask = _SigMask;
+
+       for (i=0 ; i<NSIG ; i++) {
+               if ((sigmask & mask) && !(_SigMask & mask)) {
+                       sighold(i+1);
+                       _SigMask |= mask;
+               }
+               mask <<= 1;
+       }
+       return (lastmask);
+}
+#endif /* SYM1 */
+
+
+/* Initialization code for this module.  */
+
+_initialize_ultra3 ()
+{
+#ifdef SYM1
+       init_SigMask();
+#endif
+}
diff --git a/gdb/xm-rtbsd.h b/gdb/xm-rtbsd.h
new file mode 100644 (file)
index 0000000..109d0ad
--- /dev/null
@@ -0,0 +1,46 @@
+/* Definitions to host GDB on an IBM RT/PC running BSD Unix. 
+   Copyright (C) 1986, 1987, 1989, 1991 Free Software Foundation, Inc.
+   Contributed by David Wood @ New York University (wood@lab.ultra.nyu.edu).
+
+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 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
+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; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+/* Get rid of any system-imposed stack limit if possible.  */
+#define SET_STACK_LIMIT_HUGE
+
+/* This machine is most significant byte first */
+#define HOST_BYTE_ORDER BIG_ENDIAN
+
+/* This OS has the wait structure */
+#define HAVE_WAIT_STRUCT
+
+/* This unix does not have a libc with vprintf */
+#define MISSING_VPRINTF
+
+#ifdef HOSTING_ONLY
+/*
+ * This next two defines are to get GDB up and running as a host to
+ * do remote debugging.  I know there is a gdb for the RT, but there wasn't
+ * an xconfig/rt* file.  
+ */
+#define KERNEL_U_ADDR_BSD  /* This may be correct, but hasn't been tested */
+#define REGISTER_U_ADDR(a,b,c)    \
+       (printf("GDB can not debug IBM RT/PC BSD executables (yet)\n"),\
+       quit(),0)
+#else
+# include      "GDB for the RT is not included in the distribution" 
+#endif
+
diff --git a/gdb/xm-ultra3.h b/gdb/xm-ultra3.h
new file mode 100644 (file)
index 0000000..e913409
--- /dev/null
@@ -0,0 +1,74 @@
+/* Host definitions for GDB running on a 29k NYU Ultracomputer
+   Copyright (C) 1986, 1987, 1989, 1991 Free Software Foundation, Inc.
+   Contributed by David Wood (wood@lab.ultra.nyu.edu).
+
+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 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
+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; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+/* Here at NYU we have what we call an ULTRA3 PE board.  So
+   ifdefs for ULTRA3 are my doing.  At this point in time,
+   I don't know of any other Unixi running on the 29k.  */
+
+#define HOST_BYTE_ORDER BIG_ENDIAN
+
+#define HAVE_WAIT_STRUCT
+
+#ifndef L_SET
+# define L_SET   0 /* set the seek pointer */
+# define L_INCR  1 /* increment the seek pointer */
+# define L_XTND  2 /* extend the file size */
+#endif
+
+#ifndef O_RDONLY
+# define O_RDONLY 0
+# define O_WRONLY 1
+# define O_RDWR          2
+#endif
+
+#ifndef F_OK
+# define R_OK 4
+# define W_OK 2
+# define X_OK 1
+# define F_OK 0
+#endif
+
+/* For dirbuf[] in main.c */
+#ifndef MAXPATHLEN
+#define MAXPATHLEN (1024)
+#endif
+
+/* Get rid of any system-imposed stack limit if possible */
+
+#define        SET_STACK_LIMIT_HUGE
+
+/* Override copies of {fetch,store}_inferior_registers in infptrace.c.  */
+#define FETCH_INFERIOR_REGISTERS
+
+/* If we ever *do* end up using the standard fetch_inferior_registers,
+   this is the right value for U_REGS_OFFSET.  */
+#define        U_REGS_OFFSET   0
+
+/* System doesn't provide a list of signal names. */
+#define        SYS_SIGLIST_MISSING
+
+/* System doesn't provide siginterrupt().  */
+#define        NO_SIGINTERRUPT
+
+/* System uses a `short' to hold a process group ID.  */
+#define        SHORT_PGRP
+
+/* No vfork in this system.  */
+#define        vfork() fork()