X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=gdb%2Fremote-nindy.c;h=f9cac2bad2681ccb6bf17c20fe4f5fb9550c5bce;hb=c20c1bdf992a90db69c4abb73594b2ff58154ef6;hp=1dda7afb2100e4e3d407d4a710131d5726e2bdb4;hpb=71607f9d62c125cdd1770ff7f8f07024bfa94410;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/remote-nindy.c b/gdb/remote-nindy.c index 1dda7afb21..f9cac2bad2 100644 --- a/gdb/remote-nindy.c +++ b/gdb/remote-nindy.c @@ -93,7 +93,7 @@ NINDY ROM monitor at the other end of the line. * SEE THE FILE "stop.h" IN THE NINDY MONITOR SOURCE CODE FOR A LIST * OF STOP CODES. * - ******************************************************************************/ + ***************************************************************************/ #include "defs.h" #include @@ -102,34 +102,38 @@ NINDY ROM monitor at the other end of the line. #include "frame.h" #include "inferior.h" +#include "bfd.h" +#include "symfile.h" #include "target.h" #include "gdbcore.h" #include "command.h" -#include "bfd.h" #include "ieee-float.h" #include "wait.h" -#include #include #include -#include "nindy-share/ttycntl.h" -#include "nindy-share/demux.h" +#include "serial.h" #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 char *coffstrip(); extern void generic_mourn_inferior (); extern struct target_ops nindy_ops; -extern jmp_buf to_top_level; -extern FILE *instream; +extern GDB_FILE *instream; extern struct ext_format ext_format_i960; /* i960-tdep.c */ 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 */ @@ -140,73 +144,29 @@ char *nindy_ttyname; /* name of tty to talk to nindy on, or null */ #define TRUE 1 #define FALSE 0 -int nindy_fd = 0; /* Descriptor for I/O to NINDY */ +/* From nindy-share/nindy.c. */ +extern serial_t nindy_serial; + static int have_regs = 0; /* 1 iff regs read since i960 last halted */ static int regs_changed = 0; /* 1 iff regs were modified since last read */ extern char *exists(); -static void -dcache_flush (), dcache_poke (), dcache_init(); - -static int -dcache_fetch (); - static void nindy_fetch_registers PARAMS ((int)); static void nindy_store_registers PARAMS ((int)); -/* FIXME, we can probably use the normal terminal_inferior stuff here. - We have to do terminal_inferior and then set up the passthrough - settings initially. Thereafter, terminal_ours and terminal_inferior - will automatically swap the settings around for us. */ - -/* Restore TTY to normal operation */ - -static TTY_STRUCT orig_tty; /* TTY attributes before entering passthrough */ - -static void -restore_tty() -{ - ioctl( 0, TIOCSETN, &orig_tty ); -} - - -/* Recover from ^Z or ^C while remote process is running */ - -static void (*old_ctrlc)(); /* Signal handlers before entering passthrough */ - -#ifdef SIGTSTP -static void (*old_ctrlz)(); -#endif - -static -#ifdef USG -void -#endif -cleanup() -{ - restore_tty(); - 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"); -} - -/* Clean up anything that needs cleaning when losing control. */ - static char *savename; static void nindy_close (quitting) int quitting; { - if (nindy_fd) - close (nindy_fd); - nindy_fd = 0; + if (nindy_serial != NULL) + SERIAL_CLOSE (nindy_serial); + nindy_serial = NULL; if (savename) free (savename); @@ -214,41 +174,45 @@ nindy_close (quitting) } /* 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(); + have_regs = regs_changed = 0; + 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++; - nindy_fd = ninConnect( name, baud_rate? baud_rate: "9600", - nindy_initial_brk, !from_tty, nindy_old_protocol ); - immediate_quit--; + /* Allow user to interrupt the following -- we could hang if there's + no NINDY at the other end of the remote tty. */ + immediate_quit++; + /* 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--; - if ( nindy_fd < 0 ){ - nindy_fd = 0; - error( "Can't open tty '%s'", name ); - } + if (nindy_serial == NULL) + { + perror_with_name (name); + } - savename = savestring (name, strlen (name)); - push_target (&nindy_ops); - target_fetch_registers(-1); + savename = savestring (name, strlen (name)); + push_target (&nindy_ops); + target_fetch_registers(-1); } /* User-initiated quit of nindy operations. */ @@ -266,63 +230,15 @@ nindy_detach (name, from_tty) 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": ""); } -/****************************************************************************** - * remote_load: - * Download an object file to the remote system by invoking the "comm960" - * utility. We look for "comm960" in $G960BIN, $G960BASE/bin, and - * DEFAULT_BASE/bin/HOST/bin where - * DEFAULT_BASE is defined in env.h, and - * HOST must be defined on the compiler invocation line. - ******************************************************************************/ - -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); -} - -/* Return the number of characters in the buffer before the first DLE character. - */ +/* Return the number of characters in the buffer before + the first DLE character. */ static int @@ -343,13 +259,14 @@ non_dle( buf, n ) /* Tell the remote machine to resume. */ void -nindy_resume (step, siggnal) - int step, siggnal; +nindy_resume (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; @@ -357,119 +274,138 @@ nindy_resume (step, siggnal) have_regs = 0; ninGo( step ); } + +/* FIXME, we can probably use the normal terminal_inferior stuff here. + We have to do terminal_inferior and then set up the passthrough + settings initially. Thereafter, terminal_ours and terminal_inferior + will automatically swap the settings around for us. */ + +struct clean_up_tty_args { + serial_ttystate state; + serial_t serial; +}; + +static void +clean_up_tty (ptrarg) + PTR 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"); +} /* 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; { - DEMUX_DECL; /* OS-dependent data needed by DEMUX... macros */ - char buf[500]; /* FIXME, what is "500" here? */ - int i, n; - unsigned char stop_exit; - unsigned char stop_code; - TTY_STRUCT tty; - long ip_value, fp_value, sp_value; /* Reg values from stop */ - - - WSETEXIT( (*status), 0 ); - - /* OPERATE IN PASSTHROUGH MODE UNTIL NINDY SENDS A DLE CHARACTER */ - - /* Save current tty attributes, set up signals to restore them. - */ - ioctl( 0, TIOCGETP, &orig_tty ); - old_ctrlc = signal( SIGINT, cleanup ); -#ifdef SIGTSTP - old_ctrlz = signal( SIGTSTP, cleanup ); -#endif - - /* Pass input from keyboard to NINDY as it arrives. - * NINDY will interpret and perform echo. - */ - tty = orig_tty; - TTY_NINDYTERM( tty ); - ioctl( 0, TIOCSETN, &tty ); - - while ( 1 ){ - /* Go to sleep until there's something for us on either - * the remote port or stdin. - */ - - DEMUX_WAIT( nindy_fd ); - - /* Pass input through to correct place */ - - n = DEMUX_READ( 0, buf, sizeof(buf) ); - if ( n ){ /* Input on stdin */ - write( nindy_fd, buf, n ); - } + fd_set fds; + char buf[500]; /* FIXME, what is "500" here? */ + 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 */ + + 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_cleanups = make_cleanup (clean_up_tty, &tty_args); + + /* Pass input from keyboard to NINDY as it arrives. NINDY will interpret + and perform echo. */ + /* This used to set CBREAK and clear ECHO and CRMOD. I hope this is close + enough. */ + SERIAL_RAW (tty_args.serial); + + 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) + { + SERIAL_WRITE (nindy_serial, buf, n ); + } + } - n = DEMUX_READ( nindy_fd, buf, sizeof(buf) ); - if ( n ){ /* Input on remote */ - /* 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) ){ - immediate_quit++; - ninSrq(); - immediate_quit--; - } else { - /* Get out of loop */ - supply_register (IP_REGNUM, - (char *)&ip_value); - supply_register (FP_REGNUM, - (char *)&fp_value); - supply_register (SP_REGNUM, - (char *)&sp_value); - break; - } - } + if (FD_ISSET (nindy_serial->fd, &fds)) + { + /* Input on remote */ + n = read (nindy_serial->fd, buf, sizeof (buf)); + if (n) + { + /* Write out any characters in buffer preceding DLE */ + i = non_dle( buf, n ); + if ( i > 0 ) + { + write (1, buf, i); } - } - signal( SIGINT, old_ctrlc ); -#ifdef SIGTSTP - signal( SIGTSTP, old_ctrlz ); -#endif - restore_tty(); - - if ( stop_exit ){ /* User program exited */ - WSETEXIT( (*status), stop_code ); - } else { /* Fault or trace */ - switch (stop_code){ - case STOP_GDB_BPT: - case TRACE_STEP: - /* Make it look like a VAX trace trap */ - 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; + 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)) + { + immediate_quit++; + ninSrq(); + immediate_quit--; + } + else + { + /* Get out of loop */ + supply_register (IP_REGNUM, + (char *)&ip_value); + supply_register (FP_REGNUM, + (char *)&fp_value); + supply_register (SP_REGNUM, + (char *)&sp_value); + break; + } } - WSETSTOP( (*status), stop_code ); + } } - return inferior_pid; + } + + do_cleanups (old_cleanups); + + if (stop_exit) + { + status->kind = TARGET_WAITKIND_EXITED; + status->value.integer = stop_code; + } + else + { + status->kind = TARGET_WAITKIND_STOPPED; + status->value.sig = i960_fault_to_signal (stop_code); + } + return inferior_pid; } /* Read the remote registers into the block REGS. */ @@ -496,11 +432,11 @@ nindy_fetch_registers(regno) ninRegsGet( (char *) &nindy_regs ); immediate_quit--; - bcopy (nindy_regs.local_regs, ®isters[REGISTER_BYTE (R0_REGNUM)], 16*4); - bcopy (nindy_regs.global_regs, ®isters[REGISTER_BYTE (G0_REGNUM)], 16*4); - bcopy (nindy_regs.pcw_acw, ®isters[REGISTER_BYTE (PCW_REGNUM)], 2*4); - bcopy (nindy_regs.ip, ®isters[REGISTER_BYTE (IP_REGNUM)], 1*4); - bcopy (nindy_regs.tcw, ®isters[REGISTER_BYTE (TCW_REGNUM)], 1*4); + memcpy (®isters[REGISTER_BYTE (R0_REGNUM)], nindy_regs.local_regs, 16*4); + memcpy (®isters[REGISTER_BYTE (G0_REGNUM)], nindy_regs.global_regs, 16*4); + memcpy (®isters[REGISTER_BYTE (PCW_REGNUM)], nindy_regs.pcw_acw, 2*4); + memcpy (®isters[REGISTER_BYTE (IP_REGNUM)], nindy_regs.ip, 1*4); + memcpy (®isters[REGISTER_BYTE (TCW_REGNUM)], nindy_regs.tcw, 1*4); for (regnum = FP0_REGNUM; regnum < FP0_REGNUM + 4; regnum++) { dub = unpack_double (builtin_type_double, &nindy_regs.fp_as_double[8 * (regnum - FP0_REGNUM)], @@ -525,27 +461,22 @@ nindy_store_registers(regno) int regno; { struct nindy_regs nindy_regs; - int regnum, inv; + int regnum; double dub; - bcopy (®isters[REGISTER_BYTE (R0_REGNUM)], nindy_regs.local_regs, 16*4); - bcopy (®isters[REGISTER_BYTE (G0_REGNUM)], nindy_regs.global_regs, 16*4); - bcopy (®isters[REGISTER_BYTE (PCW_REGNUM)], nindy_regs.pcw_acw, 2*4); - bcopy (®isters[REGISTER_BYTE (IP_REGNUM)], nindy_regs.ip, 1*4); - bcopy (®isters[REGISTER_BYTE (TCW_REGNUM)], nindy_regs.tcw, 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, - ®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 */ - bcopy ((char *)&dub, &nindy_regs.fp_as_double[8 * (regnum - FP0_REGNUM)], - 8); - } + memcpy (nindy_regs.local_regs, ®isters[REGISTER_BYTE (R0_REGNUM)], 16*4); + memcpy (nindy_regs.global_regs, ®isters[REGISTER_BYTE (G0_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); + for (regnum = FP0_REGNUM; regnum < FP0_REGNUM + 4; regnum++) + { + ieee_extended_to_double (&ext_format_i960, + ®isters[REGISTER_BYTE (regnum)], &dub); + store_floating (&nindy_regs.fp_as_double[8 * (regnum - FP0_REGNUM)], + REGISTER_VIRTUAL_SIZE (regnum), + dub); + } immediate_quit++; ninRegsPut( (char *) &nindy_regs ); @@ -559,7 +490,7 @@ int 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. @@ -570,7 +501,7 @@ nindy_store_word (addr, word) 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 @@ -615,7 +546,7 @@ nindy_xfer_inferior_memory(memaddr, myaddr, len, write, target) /* Copy data to be written over corresponding part of buffer */ - bcopy (myaddr, (char *) buffer + (memaddr & (sizeof (int) - 1)), len); + memcpy ((char *) buffer + (memaddr & (sizeof (int) - 1)), myaddr, len); /* Write the entire buffer. */ @@ -640,175 +571,11 @@ nindy_xfer_inferior_memory(memaddr, myaddr, len, write, target) } /* Copy appropriate bytes out of the buffer. */ - bcopy ((char *) buffer + (memaddr & (sizeof (int) - 1)), myaddr, len); + memcpy (myaddr, (char *) buffer + (memaddr & (sizeof (int) - 1)), len); } return len; } -/* 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