* SEE THE FILE "stop.h" IN THE NINDY MONITOR SOURCE CODE FOR A LIST
* OF STOP CODES.
*
- ******************************************************************************/
+ ***************************************************************************/
#include "defs.h"
#include <signal.h>
#include "target.h"
#include "gdbcore.h"
#include "command.h"
-#include "ieee-float.h"
+#include "floatformat.h"
#include "wait.h"
-#include <sys/ioctl.h>
#include <sys/file.h>
#include <ctype.h>
#include "serial.h"
-#if 0
-#include "nindy-share/ttycntl.h"
-#include "nindy-share/demux.h"
-#endif
#include "nindy-share/env.h"
#include "nindy-share/stop.h"
+#include "dcache.h"
+#include "remote-utils.h"
+
+static DCACHE *nindy_dcache;
+
extern int unlink();
extern char *getenv();
extern char *mktemp();
extern void generic_mourn_inferior ();
extern struct target_ops nindy_ops;
-extern FILE *instream;
-extern struct ext_format ext_format_i960; /* i960-tdep.c */
+extern GDB_FILE *instream;
extern char ninStopWhy ();
+extern int ninMemGet ();
+extern int ninMemPut ();
int nindy_initial_brk; /* nonzero if want to send an initial BREAK to nindy */
int nindy_old_protocol; /* nonzero if want to use old protocol */
extern char *exists();
-static void
-dcache_flush (), dcache_poke (), dcache_init();
-
-static int
-dcache_fetch ();
-
static void
nindy_fetch_registers PARAMS ((int));
}
/* Open a connection to a remote debugger.
- FIXME, there should be a way to specify the various options that are
- now specified with gdb command-line options. (baud_rate, old_protocol,
- and initial_brk) */
+ FIXME, there should be "set" commands for the options that are
+ now specified with gdb command-line options (old_protocol,
+ and initial_brk). */
void
nindy_open (name, from_tty)
char *name; /* "/dev/ttyXX", "ttyXX", or "XX": tty to be opened */
int from_tty;
{
+ char baudrate[1024];
if (!name)
error_no_arg ("serial port device name");
target_preopen (from_tty);
-
+
nindy_close (0);
have_regs = regs_changed = 0;
- dcache_init();
+ nindy_dcache = dcache_init(ninMemGet, ninMemPut);
/* Allow user to interrupt the following -- we could hang if there's
no NINDY at the other end of the remote tty. */
immediate_quit++;
- ninConnect(name, baud_rate ? baud_rate : "9600",
+ /* If baud_rate is -1, then ninConnect will not recognize the baud rate
+ and will deal with the situation in a (more or less) reasonable
+ fashion. */
+ sprintf(baudrate, "%d", baud_rate);
+ ninConnect(name, baudrate,
nindy_initial_brk, !from_tty, nindy_old_protocol);
immediate_quit--;
static void
nindy_files_info ()
{
- printf("\tAttached to %s at %s bps%s%s.\n", savename,
- baud_rate? baud_rate: "9600",
+ /* FIXME: this lies about the baud rate if we autobauded. */
+ printf_unfiltered("\tAttached to %s at %d bits per second%s%s.\n", savename,
+ baud_rate,
nindy_old_protocol? " in old protocol": "",
nindy_initial_brk? " with initial break": "");
}
void
nindy_resume (pid, step, siggnal)
- int pid, step, siggnal;
+ int pid, step;
+ enum target_signal siggnal;
{
- if (siggnal != 0 && siggnal != stop_signal)
- error ("Can't send signals to remote NINDY targets.");
+ if (siggnal != TARGET_SIGNAL_0 && siggnal != stop_signal)
+ warning ("Can't send signals to remote NINDY targets.");
- dcache_flush();
+ dcache_flush(nindy_dcache);
if ( regs_changed ){
nindy_store_registers (-1);
regs_changed = 0;
serial_ttystate state;
serial_t serial;
};
+static struct clean_up_tty_args tty_args;
static void
clean_up_tty (ptrarg)
struct clean_up_tty_args *args = (struct clean_up_tty_args *) ptrarg;
SERIAL_SET_TTY_STATE (args->serial, args->state);
free (args->state);
- warning ("\n\n\
-You may need to reset the 80960 and/or reload your program.\n");
+ warning ("\n\nYou may need to reset the 80960 and/or reload your program.\n");
+}
+
+/* Recover from ^Z or ^C while remote process is running */
+static void (*old_ctrlc)();
+#ifdef SIGTSTP
+static void (*old_ctrlz)();
+#endif
+
+static void
+clean_up_int()
+{
+ SERIAL_SET_TTY_STATE (tty_args.serial, tty_args.state);
+ free (tty_args.state);
+
+ signal(SIGINT, old_ctrlc);
+#ifdef SIGTSTP
+ signal(SIGTSTP, old_ctrlz);
+#endif
+ error("\n\nYou may need to reset the 80960 and/or reload your program.\n");
}
/* Wait until the remote machine stops. While waiting, operate in passthrough
- * mode; i.e., pass everything NINDY sends to stdout, and everything from
+ * mode; i.e., pass everything NINDY sends to gdb_stdout, and everything from
* stdin to NINDY.
*
* Return to caller, storing status in 'status' just as `wait' would.
*/
static int
-nindy_wait( status )
- WAITTYPE *status;
+nindy_wait( pid, status )
+ int pid;
+ struct target_waitstatus *status;
{
fd_set fds;
- char buf[500]; /* FIXME, what is "500" here? */
+ int c;
+ char buf[2];
int i, n;
unsigned char stop_exit;
unsigned char stop_code;
- struct clean_up_tty_args tty_args;
struct cleanup *old_cleanups;
long ip_value, fp_value, sp_value; /* Reg values from stop */
- WSETEXIT( (*status), 0 );
+ status->kind = TARGET_WAITKIND_EXITED;
+ status->value.integer = 0;
/* OPERATE IN PASSTHROUGH MODE UNTIL NINDY SENDS A DLE CHARACTER */
/* Save current tty attributes, and restore them when done. */
tty_args.serial = SERIAL_FDOPEN (0);
tty_args.state = SERIAL_GET_TTY_STATE (tty_args.serial);
+ old_ctrlc = signal( SIGINT, clean_up_int );
+#ifdef SIGTSTP
+ old_ctrlz = signal( SIGTSTP, clean_up_int );
+#endif
+
old_cleanups = make_cleanup (clean_up_tty, &tty_args);
/* Pass input from keyboard to NINDY as it arrives. NINDY will interpret
while (1)
{
- /* Wait for input on either the remote port or stdin. */
- FD_ZERO (&fds);
- FD_SET (0, &fds);
- FD_SET (nindy_serial->fd, &fds);
- if (select (nindy_serial->fd + 1, &fds, 0, 0, 0) <= 0)
- continue;
-
- /* Pass input through to correct place */
- if (FD_ISSET (0, &fds))
- {
- /* Input on stdin */
- n = read (0, buf, sizeof (buf));
- if (n)
+ /* Input on remote */
+ c = SERIAL_READCHAR (nindy_serial, -1);
+ if (c == SERIAL_ERROR)
{
- SERIAL_WRITE (nindy_serial, buf, n );
+ error ("Cannot read from serial line");
}
- }
-
- if (FD_ISSET (nindy_serial->fd, &fds))
- {
- /* Input on remote */
- n = read (nindy_serial->fd, buf, sizeof (buf));
- if (n)
+ else if (c == 0x1b) /* ESC */
+ {
+ c = SERIAL_READCHAR (nindy_serial, -1);
+ c &= ~0x40;
+ }
+ else if (c != 0x10) /* DLE */
+ /* Write out any characters preceding DLE */
+ {
+ buf[0] = (char)c;
+ write (1, buf, 1);
+ }
+ else
{
- /* Write out any characters in buffer preceding DLE */
- i = non_dle( buf, n );
- if ( i > 0 )
- {
- write (1, buf, i);
- }
-
- if (i != n)
- {
- /* There *was* a DLE in the buffer */
stop_exit = ninStopWhy(&stop_code,
&ip_value, &fp_value, &sp_value);
if (!stop_exit && (stop_code == STOP_SRQ))
(char *)&sp_value);
break;
}
- }
}
- }
}
- do_cleanups (old_cleanups);
+ SERIAL_SET_TTY_STATE (tty_args.serial, tty_args.state);
+ free (tty_args.state);
+ discard_cleanups (old_cleanups);
if (stop_exit)
{
- /* User program exited */
- WSETEXIT ((*status), stop_code);
+ status->kind = TARGET_WAITKIND_EXITED;
+ status->value.integer = stop_code;
}
else
{
- /* Fault or trace */
- switch (stop_code)
- {
- case STOP_GDB_BPT:
- case TRACE_STEP:
- /* Breakpoint or single stepping. */
- stop_code = SIGTRAP;
- break;
- default:
- /* The target is not running Unix, and its faults/traces do
- not map nicely into Unix signals. Make sure they do not
- get confused with Unix signals by numbering them with
- values higher than the highest legal Unix signal. code
- in i960_print_fault(), called via PRINT_RANDOM_SIGNAL,
- will interpret the value. */
- stop_code += NSIG;
- break;
- }
- WSETSTOP ((*status), stop_code);
+ /* nindy has some special stop code need to be handled */
+ if (stop_code == STOP_GDB_BPT)
+ stop_code = TRACE_STEP;
+ status->kind = TARGET_WAITKIND_STOPPED;
+ status->value.sig = i960_fault_to_signal (stop_code);
}
return inferior_pid;
}
&nindy_regs.fp_as_double[8 * (regnum - FP0_REGNUM)],
&inv);
/* dub now in host byte order */
- double_to_ieee_extended (&ext_format_i960, &dub,
+ floatformat_from_double (&floatformat_i960_ext, &dub,
®isters[REGISTER_BYTE (regnum)]);
}
int regno;
{
struct nindy_regs nindy_regs;
- int regnum, inv;
+ int regnum;
double dub;
memcpy (nindy_regs.local_regs, ®isters[REGISTER_BYTE (R0_REGNUM)], 16*4);
memcpy (nindy_regs.pcw_acw, ®isters[REGISTER_BYTE (PCW_REGNUM)], 2*4);
memcpy (nindy_regs.ip, ®isters[REGISTER_BYTE (IP_REGNUM)], 1*4);
memcpy (nindy_regs.tcw, ®isters[REGISTER_BYTE (TCW_REGNUM)], 1*4);
- /* Float regs. Only works on IEEE_FLOAT hosts. FIXME! */
- for (regnum = FP0_REGNUM; regnum < FP0_REGNUM + 4; regnum++) {
- ieee_extended_to_double (&ext_format_i960,
+ for (regnum = FP0_REGNUM; regnum < FP0_REGNUM + 4; regnum++)
+ {
+ floatformat_to_double (&floatformat_i960_ext,
®isters[REGISTER_BYTE (regnum)], &dub);
- /* dub now in host byte order */
- /* FIXME-someday, the arguments to unpack_double are backward.
- It expects a target double and returns a host; we pass the opposite.
- This mostly works but not quite. */
- dub = unpack_double (builtin_type_double, (char *)&dub, &inv);
- /* dub now in target byte order */
- memcpy (&nindy_regs.fp_as_double[8 * (regnum - FP0_REGNUM)], &dub, 8);
- }
+ store_floating (&nindy_regs.fp_as_double[8 * (regnum - FP0_REGNUM)],
+ REGISTER_VIRTUAL_SIZE (regnum),
+ dub);
+ }
immediate_quit++;
ninRegsPut( (char *) &nindy_regs );
nindy_fetch_word (addr)
CORE_ADDR addr;
{
- return dcache_fetch (addr);
+ return dcache_fetch (nindy_dcache, addr);
}
/* Write a word WORD into remote address ADDR.
CORE_ADDR addr;
int word;
{
- dcache_poke (addr, word);
+ dcache_poke (nindy_dcache, addr, word);
}
/* Copy LEN bytes to or from inferior's memory starting at MEMADDR
return len;
}
\f
-/* The data cache records all the data read from the remote machine
- since the last time it stopped.
-
- Each cache block holds 16 bytes of data
- starting at a multiple-of-16 address. */
-
-#define DCACHE_SIZE 64 /* Number of cache blocks */
-
-struct dcache_block {
- struct dcache_block *next, *last;
- unsigned int addr; /* Address for which data is recorded. */
- int data[4];
-};
-
-struct dcache_block dcache_free, dcache_valid;
-
-/* Free all the data cache blocks, thus discarding all cached data. */
-static
-void
-dcache_flush ()
-{
- register struct dcache_block *db;
-
- while ((db = dcache_valid.next) != &dcache_valid)
- {
- remque (db);
- insque (db, &dcache_free);
- }
-}
-
-/*
- * If addr is present in the dcache, return the address of the block
- * containing it.
- */
-static
-struct dcache_block *
-dcache_hit (addr)
- unsigned int addr;
-{
- register struct dcache_block *db;
-
- if (addr & 3)
- abort ();
-
- /* Search all cache blocks for one that is at this address. */
- db = dcache_valid.next;
- while (db != &dcache_valid)
- {
- if ((addr & 0xfffffff0) == db->addr)
- return db;
- db = db->next;
- }
- return NULL;
-}
-
-/* Return the int data at address ADDR in dcache block DC. */
-static
-int
-dcache_value (db, addr)
- struct dcache_block *db;
- unsigned int addr;
-{
- if (addr & 3)
- abort ();
- return (db->data[(addr>>2)&3]);
-}
-
-/* Get a free cache block, put or keep it on the valid list,
- and return its address. The caller should store into the block
- the address and data that it describes, then remque it from the
- free list and insert it into the valid list. This procedure
- prevents errors from creeping in if a ninMemGet is interrupted
- (which used to put garbage blocks in the valid list...). */
-static
-struct dcache_block *
-dcache_alloc ()
-{
- register struct dcache_block *db;
-
- if ((db = dcache_free.next) == &dcache_free)
- {
- /* If we can't get one from the free list, take last valid and put
- it on the free list. */
- db = dcache_valid.last;
- remque (db);
- insque (db, &dcache_free);
- }
-
- remque (db);
- insque (db, &dcache_valid);
- return (db);
-}
-
-/* Return the contents of the word at address ADDR in the remote machine,
- using the data cache. */
-static
-int
-dcache_fetch (addr)
- CORE_ADDR addr;
-{
- register struct dcache_block *db;
-
- db = dcache_hit (addr);
- if (db == 0)
- {
- db = dcache_alloc ();
- immediate_quit++;
- ninMemGet(addr & ~0xf, (unsigned char *)db->data, 16);
- immediate_quit--;
- db->addr = addr & ~0xf;
- remque (db); /* Off the free list */
- insque (db, &dcache_valid); /* On the valid list */
- }
- return (dcache_value (db, addr));
-}
-
-/* Write the word at ADDR both in the data cache and in the remote machine. */
-static void
-dcache_poke (addr, data)
- CORE_ADDR addr;
- int data;
-{
- register struct dcache_block *db;
-
- /* First make sure the word is IN the cache. DB is its cache block. */
- db = dcache_hit (addr);
- if (db == 0)
- {
- db = dcache_alloc ();
- immediate_quit++;
- ninMemGet(addr & ~0xf, (unsigned char *)db->data, 16);
- immediate_quit--;
- db->addr = addr & ~0xf;
- remque (db); /* Off the free list */
- insque (db, &dcache_valid); /* On the valid list */
- }
-
- /* Modify the word in the cache. */
- db->data[(addr>>2)&3] = data;
-
- /* Send the changed word. */
- immediate_quit++;
- ninMemPut(addr, (unsigned char *)&data, 4);
- immediate_quit--;
-}
-
-/* The cache itself. */
-struct dcache_block the_cache[DCACHE_SIZE];
-
-/* Initialize the data cache. */
-static void
-dcache_init ()
-{
- register i;
- register struct dcache_block *db;
-
- db = the_cache;
- dcache_free.next = dcache_free.last = &dcache_free;
- dcache_valid.next = dcache_valid.last = &dcache_valid;
- for (i=0;i<DCACHE_SIZE;i++,db++)
- insque (db, &dcache_free);
-}
-
-
static void
nindy_create_inferior (execfile, args, env)
char *execfile;
pid = 42;
-#ifdef CREATE_INFERIOR_HOOK
- CREATE_INFERIOR_HOOK (pid);
-#endif
-
-/* The "process" (board) is already stopped awaiting our commands, and
- the program is already downloaded. We just set its PC and go. */
+ /* The "process" (board) is already stopped awaiting our commands, and
+ the program is already downloaded. We just set its PC and go. */
inferior_pid = pid; /* Needed for wait_for_inferior below */
target_terminal_inferior ();
/* insert_step_breakpoint (); FIXME, do we need this? */
- proceed ((CORE_ADDR)entry_pt, -1, 0); /* Let 'er rip... */
+ /* Let 'er rip... */
+ proceed ((CORE_ADDR)entry_pt, TARGET_SIGNAL_DEFAULT, 0);
}
static void
return 1;
}
+static void
+nindy_load( filename, from_tty )
+ char *filename;
+ int from_tty;
+{
+ asection *s;
+ /* Can't do unix style forking on a VMS system, so we'll use bfd to do
+ all the work for us
+ */
+
+ bfd *file = bfd_openr(filename,0);
+ if (!file)
+ {
+ perror_with_name(filename);
+ return;
+ }
+
+ if (!bfd_check_format(file, bfd_object))
+ {
+ error("can't prove it's an object file\n");
+ return;
+ }
+
+ for ( s = file->sections; s; s=s->next)
+ {
+ if (s->flags & SEC_LOAD)
+ {
+ char *buffer = xmalloc(s->_raw_size);
+ bfd_get_section_contents(file, s, buffer, 0, s->_raw_size);
+ printf("Loading section %s, size %x vma %x\n",
+ s->name,
+ s->_raw_size,
+ s->vma);
+ ninMemPut(s->vma, buffer, s->_raw_size);
+ free(buffer);
+ }
+ }
+ bfd_close(file);
+}
+
static int
load_stub (arg)
char *arg;
char ttyname[100];
char *p, *p2;
- while (current_target != &nindy_ops) { /* remote tty not specified yet */
+ while (target_stack->target_ops != &nindy_ops) /* What is this crap??? */
+ { /* remote tty not specified yet */
if ( instream == stdin ){
- printf("\nAttach /dev/ttyNN -- specify NN, or \"quit\" to quit: ");
- fflush( stdout );
+ printf_unfiltered("\nAttach /dev/ttyNN -- specify NN, or \"quit\" to quit: ");
+ gdb_flush( gdb_stdout );
}
fgets( ttyname, sizeof(ttyname)-1, stdin );
nindy_fetch_registers, nindy_store_registers,
nindy_prepare_to_store,
nindy_xfer_inferior_memory, nindy_files_info,
- 0, 0, /* insert_breakpoint, remove_breakpoint, */
+ memory_insert_breakpoint,
+ memory_remove_breakpoint,
0, 0, 0, 0, 0, /* Terminal crud */
nindy_kill,
- generic_load,
+ nindy_load,
0, /* lookup_symbol */
nindy_create_inferior,
nindy_mourn_inferior,
0, /* can_run */
0, /* notice_signals */
+ 0, /* to_stop */
process_stratum, 0, /* next */
1, 1, 1, 1, 1, /* all mem, mem, stack, regs, exec */
0, 0, /* Section pointers */