OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /or1k/trunk/gdb-5.0/gdb/nindy-share
    from Rev 107 to Rev 1765
    Reverse comparison

Rev 107 → Rev 1765

/Onindy.c
0,0 → 1,743
/* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
 
/* This started out life as code shared between the nindy monitor and
GDB. For various reasons, this is no longer true. Eventually, it
probably should be merged into remote-nindy.c. */
 
/******************************************************************************
*
* NINDY INTERFACE ROUTINES
*
* This version of the NINDY interface routines supports NINDY versions
* 2.13 and older. The older versions used a hex communication protocol,
* instead of the (faster) current binary protocol. These routines have
* been renamed by prepending the letter 'O' to their names, to avoid
* conflict with the current version. The old versions are kept only for
* backward compatibility, and well disappear in a future release.
*
**************************************************************************/
 
/* Having these in a separate file from nindy.c is really ugly, and should
be merged with nindy.c. */
 
#include <stdio.h>
#if 0
#include <sys/ioctl.h>
#include <sys/types.h> /* Needed by file.h on Sys V */
#include <sys/file.h>
#include <signal.h>
#include <sys/stat.h>
#include <fcntl.h> /* Needed on Sys V */
#include "ttycntl.h"
#endif
#include "defs.h"
#include "serial.h"
 
#include "block_io.h"
#include "gdb_wait.h"
#include "env.h"
 
/* Number of bytes that we send to nindy. I believe this is defined by
the protocol (it does not agree with REGISTER_BYTES). */
#define OLD_NINDY_REGISTER_BYTES ((36*4) + (4*8))
 
extern int quiet; /* 1 => stifle unnecessary messages */
 
/* tty connected to 960/NINDY board. */
extern serial_t nindy_serial;
 
static OninStrGet();
/****************************
* *
* MISCELLANEOUS UTILTIES *
* *
****************************/
 
 
/******************************************************************************
* fromhex:
* Convert a hex ascii digit h to a binary integer
******************************************************************************/
static
int
fromhex( h )
int h;
{
if (h >= '0' && h <= '9'){
h -= '0';
} else if (h >= 'a' && h <= 'f'){
h -= 'a' - 10;
} else {
h = 0;
}
return (h & 0xff);
}
 
 
/******************************************************************************
* hexbin:
* Convert a string of ASCII hex digits to a string of binary bytes.
******************************************************************************/
static
hexbin( n, hexp, binp )
int n; /* Number of bytes to convert (twice this many digits)*/
char *hexp; /* Get hex from here */
char *binp; /* Put binary here */
{
while ( n-- ){
*binp++ = (fromhex(*hexp) << 4) | fromhex(*(hexp+1));
hexp += 2;
}
}
 
 
/******************************************************************************
* binhex:
* Convert a string of binary bytes to a string of ASCII hex digits
******************************************************************************/
static
binhex( n, binp, hexp )
int n; /* Number of bytes to convert */
char *binp; /* Get binary from here */
char *hexp; /* Place hex here */
{
static char tohex[] = "0123456789abcdef";
 
while ( n-- ){
*hexp++ = tohex[ (*binp >> 4) & 0xf ];
*hexp++ = tohex[ *binp & 0xf ];
binp++;
}
}
 
/******************************************************************************
* byte_order:
* If the host byte order is different from 960 byte order (i.e., the
* host is big-endian), reverse the bytes in the passed value; otherwise,
* return the passed value unchanged.
*
******************************************************************************/
static
long
byte_order( n )
long n;
{
long rev;
int i;
static short test = 0x1234;
 
if (*((char *) &test) == 0x12) {
/*
* Big-endian host, swap the bytes.
*/
rev = 0;
for ( i = 0; i < sizeof(n); i++ ){
rev <<= 8;
rev |= n & 0xff;
n >>= 8;
}
n = rev;
}
return n;
}
 
/******************************************************************************
* say:
* This is a printf that takes at most two arguments (in addition to the
* format string) and that outputs nothing if verbose output has been
* suppressed.
******************************************************************************/
static
say( fmt, arg1, arg2 )
char *fmt;
int arg1, arg2;
{
if ( !quiet ){
printf( fmt, arg1, arg2 );
fflush( stdout );
}
}
/*****************************
* *
* LOW-LEVEL COMMUNICATION *
* *
*****************************/
 
/* Read a single character from the remote end. */
 
static int
readchar()
{
/* FIXME: Do we really want to be reading without a timeout? */
return SERIAL_READCHAR (nindy_serial, -1);
}
 
/******************************************************************************
* getpkt:
* Read a packet from a remote NINDY, with error checking, and return
* it in the indicated buffer.
******************************************************************************/
static
getpkt (buf)
char *buf;
{
unsigned char recv; /* Checksum received */
unsigned char csum; /* Checksum calculated */
char *bp; /* Poointer into the buffer */
int c;
 
while (1){
csum = 0;
bp = buf;
/* FIXME: check for error from readchar (). */
while ( (c = readchar()) != '#' ){
*bp++ = c;
csum += c;
}
*bp = 0;
 
/* FIXME: check for error from readchar (). */
recv = fromhex(readchar()) << 4;
recv |= fromhex(readchar());
if ( csum == recv ){
break;
}
fprintf(stderr,
"Bad checksum (recv=0x%02x; calc=0x%02x); retrying\r\n",
recv, csum );
SERIAL_WRITE (nindy_serial, "-", 1);
}
 
SERIAL_WRITE (nindy_serial, "+", 1);
}
 
 
/******************************************************************************
* putpkt:
* Checksum and send a gdb command to a remote NINDY, and wait for
* positive acknowledgement.
*
******************************************************************************/
static
putpkt( cmd )
char *cmd; /* Command to be sent, without lead ^P (\020)
* or trailing checksum
*/
{
char ack; /* Response received from NINDY */
char checksum[4];
char *p;
unsigned int s;
char resend;
 
for ( s='\020', p=cmd; *p; p++ ){
s += *p;
}
sprintf( checksum, "#%02x", s & 0xff );
 
/* Send checksummed message over and over until we get a positive ack
*/
resend = 1;
do {
if ( resend ) {
SERIAL_WRITE ( nindy_serial, "\020", 1 );
SERIAL_WRITE( nindy_serial, cmd, strlen(cmd) );
SERIAL_WRITE( nindy_serial, checksum, strlen(checksum) );
}
/* FIXME: do we really want to be reading without timeout? */
ack = SERIAL_READCHAR (nindy_serial, -1);
if (ack < 0)
{
fprintf (stderr, "error reading from serial port\n");
}
if ( ack == '-' ){
fprintf( stderr, "Remote NAK, resending\r\n" );
resend = 1;
} else if ( ack != '+' ){
fprintf( stderr, "Bad ACK, ignored: <%c>\r\n", ack );
resend = 0;
}
} while ( ack != '+' );
}
 
 
 
/******************************************************************************
* send:
* Send a message to a remote NINDY and return the reply in the same
* buffer (clobbers the input message). Check for error responses
* as indicated by the second argument.
*
******************************************************************************/
static
send( buf, ack_required )
char *buf; /* Message to be sent to NINDY; replaced by
* NINDY's response.
*/
int ack_required; /* 1 means NINDY's response MUST be either "X00" (no
* error) or an error code "Xnn".
* 0 means the it's OK as long as it doesn't
* begin with "Xnn".
*/
{
int errnum;
static char *errmsg[] = {
"", /* X00 */
"Buffer overflow", /* X01 */
"Unknown command", /* X02 */
"Wrong amount of data to load register(s)", /* X03 */
"Missing command argument(s)", /* X04 */
"Odd number of digits sent to load memory", /* X05 */
"Unknown register name", /* X06 */
"No such memory segment", /* X07 */
"No breakpoint available", /* X08 */
"Can't set requested baud rate", /* X09 */
};
# define NUMERRS ( sizeof(errmsg) / sizeof(errmsg[0]) )
 
static char err0[] = "NINDY failed to acknowledge command: <%s>\r\n";
static char err1[] = "Unknown error response from NINDY: <%s>\r\n";
static char err2[] = "Error response %s from NINDY: %s\r\n";
 
putpkt (buf);
getpkt (buf);
 
if ( buf[0] != 'X' ){
if ( ack_required ){
fprintf( stderr, err0, buf );
abort();
}
 
} else if ( strcmp(buf,"X00") ){
sscanf( &buf[1], "%x", &errnum );
if ( errnum > NUMERRS ){
fprintf( stderr, err1, buf );
} else{
fprintf( stderr, err2, buf, errmsg[errnum] );
}
abort();
}
}
/**********************************
* *
* NINDY INTERFACE ROUTINES *
* *
* ninConnect *MUST* be the first *
* one of these routines called. *
**********************************/
 
/******************************************************************************
* ninBptDel:
* Ask NINDY to delete the specified type of *hardware* breakpoint at
* the specified address. If the 'addr' is -1, all breakpoints of
* the specified type are deleted.
******************************************************************************/
OninBptDel( addr, data )
long addr; /* Address in 960 memory */
int data; /* '1' => data bkpt, '0' => instruction breakpoint */
{
char buf[100];
 
if ( addr == -1 ){
sprintf( buf, "b%c", data ? '1' : '0' );
} else {
sprintf( buf, "b%c%x", data ? '1' : '0', addr );
}
return send( buf, 0 );
}
 
 
/******************************************************************************
* ninBptSet:
* Ask NINDY to set the specified type of *hardware* breakpoint at
* the specified address.
******************************************************************************/
OninBptSet( addr, data )
long addr; /* Address in 960 memory */
int data; /* '1' => data bkpt, '0' => instruction breakpoint */
{
char buf[100];
 
sprintf( buf, "B%c%x", data ? '1' : '0', addr );
return send( buf, 0 );
}
 
/******************************************************************************
* ninGdbExit:
* Ask NINDY to leave GDB mode and print a NINDY prompt.
* Since it'll no longer be in GDB mode, don't wait for a response.
******************************************************************************/
OninGdbExit()
{
putpkt( "E" );
}
 
/******************************************************************************
* ninGo:
* Ask NINDY to start or continue execution of an application program
* in it's memory at the current ip.
******************************************************************************/
OninGo( step_flag )
int step_flag; /* 1 => run in single-step mode */
{
putpkt( step_flag ? "s" : "c" );
}
 
 
/******************************************************************************
* ninMemGet:
* Read a string of bytes from NINDY's address space (960 memory).
******************************************************************************/
OninMemGet(ninaddr, hostaddr, len)
long ninaddr; /* Source address, in the 960 memory space */
char *hostaddr; /* Destination address, in our memory space */
int len; /* Number of bytes to read */
{
/* How much do we send at a time? */
#define OLD_NINDY_MEMBYTES 1024
/* Buffer: hex in, binary out */
char buf[2*OLD_NINDY_MEMBYTES+20];
 
int cnt; /* Number of bytes in next transfer */
 
for ( ; len > 0; len -= OLD_NINDY_MEMBYTES ){
cnt = len > OLD_NINDY_MEMBYTES ? OLD_NINDY_MEMBYTES : len;
 
sprintf( buf, "m%x,%x", ninaddr, cnt );
send( buf, 0 );
hexbin( cnt, buf, hostaddr );
 
ninaddr += cnt;
hostaddr += cnt;
}
}
 
 
/******************************************************************************
* ninMemPut:
* Write a string of bytes into NINDY's address space (960 memory).
******************************************************************************/
OninMemPut( destaddr, srcaddr, len )
long destaddr; /* Destination address, in NINDY memory space */
char *srcaddr; /* Source address, in our memory space */
int len; /* Number of bytes to write */
{
char buf[2*OLD_NINDY_MEMBYTES+20]; /* Buffer: binary in, hex out */
char *p; /* Pointer into buffer */
int cnt; /* Number of bytes in next transfer */
 
for ( ; len > 0; len -= OLD_NINDY_MEMBYTES ){
cnt = len > OLD_NINDY_MEMBYTES ? OLD_NINDY_MEMBYTES : len;
 
sprintf( buf, "M%x,", destaddr );
p = buf + strlen(buf);
binhex( cnt, srcaddr, p );
*(p+(2*cnt)) = '\0';
send( buf, 1 );
 
srcaddr += cnt;
destaddr += cnt;
}
}
 
/******************************************************************************
* ninRegGet:
* Retrieve the contents of a 960 register, and return them as a long
* in host byte order.
*
* THIS ROUTINE CAN ONLY BE USED TO READ THE LOCAL, GLOBAL, AND
* ip/ac/pc/tc REGISTERS.
*
******************************************************************************/
long
OninRegGet( regname )
char *regname; /* Register name recognized by NINDY, subject to the
* above limitations.
*/
{
char buf[200];
long val;
 
sprintf( buf, "u%s", regname );
send( buf, 0 );
hexbin( 4, buf, (char *)&val );
return byte_order(val);
}
 
/******************************************************************************
* ninRegPut:
* Set the contents of a 960 register.
*
* THIS ROUTINE CAN ONLY BE USED TO SET THE LOCAL, GLOBAL, AND
* ip/ac/pc/tc REGISTERS.
*
******************************************************************************/
OninRegPut( regname, val )
char *regname; /* Register name recognized by NINDY, subject to the
* above limitations.
*/
long val; /* New contents of register, in host byte-order */
{
char buf[200];
 
sprintf( buf, "U%s,%08x", regname, byte_order(val) );
send( buf, 1 );
}
 
/******************************************************************************
* ninRegsGet:
* Get a dump of the contents of the entire 960 register set. The
* individual registers appear in the dump in the following order:
*
* pfp sp rip r3 r4 r5 r6 r7
* r8 r9 r10 r11 r12 r13 r14 r15
* g0 g1 g2 g3 g4 g5 g6 g7
* g8 g9 g10 g11 g12 g13 g14 fp
* pc ac ip tc fp0 fp1 fp2 fp3
*
* Each individual register comprises exactly 4 bytes, except for
* fp0-fp3, which are 8 bytes.
*
* WARNING:
* Each register value is in 960 (little-endian) byte order.
*
******************************************************************************/
OninRegsGet( regp )
char *regp; /* Where to place the register dump */
{
char buf[(2*OLD_NINDY_REGISTER_BYTES)+10]; /* Registers in ASCII hex */
 
strcpy( buf, "r" );
send( buf, 0 );
hexbin( OLD_NINDY_REGISTER_BYTES, buf, regp );
}
 
/******************************************************************************
* ninRegsPut:
* Initialize the entire 960 register set to a specified set of values.
* The format of the register value data should be the same as that
* returned by ninRegsGet.
*
* WARNING:
* Each register value should be in 960 (little-endian) byte order.
*
******************************************************************************/
OninRegsPut( regp )
char *regp; /* Pointer to desired values of registers */
{
char buf[(2*OLD_NINDY_REGISTER_BYTES)+10]; /* Registers in ASCII hex */
 
buf[0] = 'R';
binhex( OLD_NINDY_REGISTER_BYTES, regp, buf+1 );
buf[ (2*OLD_NINDY_REGISTER_BYTES)+1 ] = '\0';
 
send( buf, 1 );
}
 
 
/******************************************************************************
* ninReset:
* Ask NINDY to perform a soft reset; wait for the reset to complete.
******************************************************************************/
OninReset()
{
 
putpkt( "X" );
/* FIXME: check for error from readchar (). */
while ( readchar() != '+' ){
;
}
}
 
 
/******************************************************************************
* ninSrq:
* Assume NINDY has stopped execution of the 960 application program in
* order to process a host service request (srq). Ask NINDY for the
* srq arguments, perform the requested service, and send an "srq
* complete" message so NINDY will return control to the application.
*
******************************************************************************/
OninSrq()
{
/* FIXME: Imposes arbitrary limits on lengths of pathnames and such. */
char buf[BUFSIZE];
int retcode;
unsigned char srqnum;
char *p;
char *argp;
int nargs;
int arg[MAX_SRQ_ARGS];
 
 
/* Get srq number and arguments
*/
strcpy( buf, "!" );
send( buf, 0 );
hexbin( 1, buf, (char *)&srqnum );
 
/* Set up array of pointers the each of the individual
* comma-separated args
*/
nargs=0;
argp = p = buf+2;
while ( 1 ){
while ( *p != ',' && *p != '\0' ){
p++;
}
sscanf( argp, "%x", &arg[nargs++] );
if ( *p == '\0' || nargs == MAX_SRQ_ARGS ){
break;
}
argp = ++p;
}
 
/* Process Srq
*/
switch( srqnum ){
case BS_CLOSE:
/* args: file descriptor */
if ( arg[0] > 2 ){
retcode = close( arg[0] );
} else {
retcode = 0;
}
break;
case BS_CREAT:
/* args: filename, mode */
OninStrGet( arg[0], buf );
retcode = creat(buf,arg[1]);
break;
case BS_OPEN:
/* args: filename, flags, mode */
OninStrGet( arg[0], buf );
retcode = open(buf,arg[1],arg[2]);
break;
case BS_READ:
/* args: file descriptor, buffer, count */
retcode = read(arg[0],buf,arg[2]);
if ( retcode > 0 ){
OninMemPut( arg[1], buf, retcode );
}
break;
case BS_SEEK:
/* args: file descriptor, offset, whence */
retcode = lseek(arg[0],arg[1],arg[2]);
break;
case BS_WRITE:
/* args: file descriptor, buffer, count */
OninMemGet( arg[1], buf, arg[2] );
retcode = write(arg[0],buf,arg[2]);
break;
default:
retcode = -1;
break;
}
 
/* Tell NINDY to continue
*/
sprintf( buf, "e%x", retcode );
send( buf, 1 );
}
 
 
/******************************************************************************
* ninStopWhy:
* Assume the application program has stopped (i.e., a DLE was received
* from NINDY). Ask NINDY for status information describing the
* reason for the halt.
*
* Returns a non-zero value if the user program has exited, 0 otherwise.
* Also returns the following information, through passed pointers:
* - why: an exit code if program the exited; otherwise the reason
* why the program halted (see stop.h for values).
* - contents of register ip (little-endian byte order)
* - contents of register sp (little-endian byte order)
* - contents of register fp (little-endian byte order)
******************************************************************************/
char
OninStopWhy( whyp, ipp, fpp, spp )
char *whyp; /* Return the 'why' code through this pointer */
char *ipp; /* Return contents of register ip through this pointer */
char *fpp; /* Return contents of register fp through this pointer */
char *spp; /* Return contents of register sp through this pointer */
{
char buf[30];
char stop_exit;
 
strcpy( buf, "?" );
send( buf, 0 );
hexbin( 1, buf, &stop_exit );
hexbin( 1, buf+2, whyp );
hexbin( 4, buf+4, ipp );
hexbin( 4, buf+12, fpp );
hexbin( 4, buf+20, spp );
return stop_exit;
}
 
/******************************************************************************
* ninStrGet:
* Read a '\0'-terminated string of data out of the 960 memory space.
*
******************************************************************************/
static
OninStrGet( ninaddr, hostaddr )
unsigned long ninaddr; /* Address of string in NINDY memory space */
char *hostaddr; /* Address of the buffer to which string should
* be copied.
*/
{
/* FIXME: seems to be an arbitrary limit on the length of the string. */
char buf[BUFSIZE]; /* String as 2 ASCII hex digits per byte */
int numchars; /* Length of string in bytes. */
 
sprintf( buf, "\"%x", ninaddr );
send( buf, 0 );
numchars = strlen(buf)/2;
hexbin( numchars, buf, hostaddr );
hostaddr[numchars] = '\0';
}
 
#if 0
/* never used. */
 
/******************************************************************************
* ninVersion:
* Ask NINDY for version information about itself.
* The information is sent as an ascii string in the form "x.xx,<arch>",
* where,
* x.xx is the version number
* <arch> is the processor architecture: "KA", "KB", "MC", "CA" *
*
******************************************************************************/
int
OninVersion( p )
char *p; /* Where to place version string */
{
/* FIXME: this is an arbitrary limit on the length of version string. */
char buf[BUFSIZE];
 
strcpy( buf, "v" );
send( buf, 0 );
strcpy( p, buf );
return strlen( buf );
}
#endif
/nindy.c
0,0 → 1,1154
/* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
 
/* This started out life as code shared between the nindy monitor and
GDB. For various reasons, this is no longer true. Eventually, it
probably should be merged into remote-nindy.c. */
 
/******************************************************************************
*
* NINDY INTERFACE ROUTINES
*
* The caller of these routines should be aware that:
*
* (1) ninConnect() should be called to open communications with the
* remote NINDY board before any of the other routines are invoked.
*
* (2) almost all interactions are driven by the host: nindy sends information
* in response to host commands.
*
* (3) the lone exception to (2) is the single character DLE (^P, 0x10).
* Receipt of a DLE from NINDY indicates that the application program
* running under NINDY has stopped execution and that NINDY is now
* available to talk to the host (all other communication received after
* the application has been started should be presumed to come from the
* application and should be passed on by the host to stdout).
*
* (4) the reason the application program stopped can be determined with the
* ninStopWhy() function. There are three classes of stop reasons:
*
* (a) the application has terminated execution.
* The host should take appropriate action.
*
* (b) the application had a fault or trace event.
* The host should take appropriate action.
*
* (c) the application wishes to make a service request (srq) of the host;
* e.g., to open/close a file, read/write a file, etc. The ninSrq()
* function should be called to determine the nature of the request
* and process it.
*/
 
#include <stdio.h>
#include "defs.h"
#include "serial.h"
#ifdef ANSI_PROTOTYPES
#include <stdarg.h>
#else
#include <varargs.h>
#endif
 
#if !defined (HAVE_TERMIOS) && !defined (HAVE_TERMIO) && !defined (HAVE_SGTTY)
#define HAVE_SGTTY
#endif
 
#ifdef HAVE_SGTTY
#include <sys/ioctl.h>
#endif
 
#include <sys/types.h> /* Needed by file.h on Sys V */
#include <sys/file.h>
#include <signal.h>
#include <sys/stat.h>
 
#if 0
#include "ttycntl.h"
#endif
#include "block_io.h"
#include "gdb_wait.h"
#include "env.h"
 
#define DLE 0x10 /* ^P */
#define XON 0x11 /* ^Q */
#define XOFF 0x13 /* ^S */
#define ESC 0x1b
 
#define TIMEOUT -1
 
int quiet = 0; /* 1 => stifle unnecessary messages */
serial_t nindy_serial;
 
static int old_nindy = 0; /* 1 => use old (hex) communication protocol */
static ninStrGet();
/****************************
* *
* MISCELLANEOUS UTILTIES *
* *
****************************/
 
/******************************************************************************
* say:
* This is a printf that takes at most two arguments (in addition to the
* format string) and that outputs nothing if verbose output has been
* suppressed.
*****************************************************************************/
 
/* VARARGS */
static void
#ifdef ANSI_PROTOTYPES
say (char *fmt, ...)
#else
say (va_alist)
va_dcl
#endif
{
va_list args;
#ifdef ANSI_PROTOTYPES
va_start(args, fmt);
#else
char *fmt;
 
va_start (args);
fmt = va_arg (args, char *);
#endif
 
if (!quiet)
{
vfprintf_unfiltered (gdb_stdout, fmt, args);
gdb_flush (gdb_stdout);
}
va_end (args);
}
 
/******************************************************************************
* exists:
* Creates a full pathname by concatenating up to three name components
* onto a specified base name; optionally looks up the base name as a
* runtime environment variable; and checks to see if the file or
* directory specified by the pathname actually exists.
*
* Returns: the full pathname if it exists, NULL otherwise.
* (returned pathname is in malloc'd memory and must be freed
* by caller).
*****************************************************************************/
static char *
exists( base, c1, c2, c3, env )
char *base; /* Base directory of path */
char *c1, *c2, *c3; /* Components (subdirectories and/or file name) to be
* appended onto the base directory name. One or
* more may be omitted by passing NULL pointers.
*/
int env; /* If 1, '*base' is the name of an environment variable
* to be examined for the base directory name;
* otherwise, '*base' is the actual name of the
* base directory.
*/
{
struct stat buf;/* For call to 'stat' -- never examined */
char *path; /* Pointer to full pathname (malloc'd memory) */
int len; /* Length of full pathname (incl. terminator) */
extern char *getenv();
 
 
if ( env ){
base = getenv( base );
if ( base == NULL ){
return NULL;
}
}
 
len = strlen(base) + 4;
/* +4 for terminator and "/" before each component */
if ( c1 != NULL ){
len += strlen(c1);
}
if ( c2 != NULL ){
len += strlen(c2);
}
if ( c3 != NULL ){
len += strlen(c3);
}
 
path = xmalloc (len);
 
strcpy( path, base );
if ( c1 != NULL ){
strcat( path, "/" );
strcat( path, c1 );
if ( c2 != NULL ){
strcat( path, "/" );
strcat( path, c2 );
if ( c3 != NULL ){
strcat( path, "/" );
strcat( path, c3 );
}
}
}
 
if ( stat(path,&buf) != 0 ){
free( path );
path = NULL;
}
return path;
}
/*****************************
* *
* LOW-LEVEL COMMUNICATION *
* *
*****************************/
 
/* Read *exactly* N characters from the NINDY tty, and put them in
*BUF. Translate escape sequences into single characters, counting
each such sequence as 1 character.
 
An escape sequence consists of ESC and a following character. The
ESC is discarded and the other character gets bit 0x40 cleared --
thus ESC P == ^P, ESC S == ^S, ESC [ == ESC, etc.
 
Return 1 if successful, 0 if more than TIMEOUT seconds pass without
any input. */
 
static int
rdnin (buf,n,timeout)
unsigned char * buf; /* Where to place characters read */
int n; /* Number of characters to read */
int timeout; /* Timeout, in seconds */
{
int escape_seen; /* 1 => last character of a read was an ESC */
int c;
 
escape_seen = 0;
while (n)
{
c = SERIAL_READCHAR (nindy_serial, timeout);
switch (c)
{
case SERIAL_ERROR:
case SERIAL_TIMEOUT:
case SERIAL_EOF:
return 0;
 
case ESC:
escape_seen = 1;
break;
 
default:
if (escape_seen)
{
escape_seen = 0;
c &= ~0x40;
}
*buf++ = c;
--n;
break;
}
}
return 1;
}
 
 
/******************************************************************************
* getpkt:
* Read a packet from a remote NINDY, with error checking, into the
* indicated buffer.
*
* Return packet status byte on success, TIMEOUT on failure.
******************************************************************************/
static
int
getpkt(buf)
unsigned char *buf;
{
int i;
unsigned char hdr[3]; /* Packet header:
* hdr[0] = low byte of message length
* hdr[1] = high byte of message length
* hdr[2] = message status
*/
int cnt; /* Message length (status byte + data) */
unsigned char cs_calc; /* Checksum calculated */
unsigned char cs_recv; /* Checksum received */
static char errfmt[] =
"Bad checksum (recv=0x%02x; calc=0x%02x); retrying\r\n";
 
while (1){
if ( !rdnin(hdr,3,5) ){
return TIMEOUT;
}
cnt = (hdr[1]<<8) + hdr[0] - 1;
/* -1 for status byte (already read) */
 
/* Caller's buffer may only be big enough for message body,
* without status byte and checksum, so make sure to read
* checksum into a separate buffer.
*/
if ( !rdnin(buf,cnt,5) || !rdnin(&cs_recv,1,5) ){
return TIMEOUT;
}
 
/* Calculate checksum
*/
cs_calc = hdr[0] + hdr[1] + hdr[2];
for ( i = 0; i < cnt; i++ ){
cs_calc += buf[i];
}
if ( cs_calc == cs_recv ){
SERIAL_WRITE (nindy_serial, "+", 1);
return hdr[2];
}
/* Bad checksum: report, send NAK, and re-receive
*/
fprintf(stderr, errfmt, cs_recv, cs_calc );
SERIAL_WRITE (nindy_serial, "-", 1);
}
}
 
 
/******************************************************************************
* putpkt:
* Send a packet to NINDY, checksumming it and converting special
* characters to escape sequences.
******************************************************************************/
 
/* This macro puts the character 'c' into the buffer pointed at by 'p',
* and increments the pointer. If 'c' is one of the 4 special characters
* in the transmission protocol, it is converted into a 2-character
* escape sequence.
*/
#define PUTBUF(c,p) \
if ( c == DLE || c == ESC || c == XON || c == XOFF ){ \
*p++ = ESC; \
*p++ = c | 0x40; \
} else { \
*p++ = c; \
}
 
static
putpkt( msg, len )
unsigned char *msg; /* Command to be sent, without lead ^P (\020) or checksum */
int len; /* Number of bytes in message */
{
static char *buf = NULL;/* Local buffer -- build packet here */
static int maxbuf = 0; /* Current length of buffer */
unsigned char ack; /* Response received from NINDY */
unsigned char checksum; /* Packet checksum */
char *p; /* Pointer into buffer */
int lenhi, lenlo; /* High and low bytes of message length */
int i;
 
 
/* Make sure local buffer is big enough. Must include space for
* packet length, message body, and checksum. And in the worst
* case, each character would expand into a 2-character escape
* sequence.
*/
if ( maxbuf < ((2*len)+10) ){
if ( buf ){
free( buf );
}
buf = xmalloc( maxbuf=((2*len)+10) );
}
 
/* Attention, NINDY!
*/
SERIAL_WRITE (nindy_serial, "\020", 1);
 
 
lenlo = len & 0xff;
lenhi = (len>>8) & 0xff;
checksum = lenlo + lenhi;
p = buf;
 
PUTBUF( lenlo, p );
PUTBUF( lenhi, p );
 
for ( i=0; i<len; i++ ){
PUTBUF( msg[i], p );
checksum += msg[i];
}
 
PUTBUF( checksum, p );
 
/* Send checksummed message over and over until we get a positive ack
*/
SERIAL_WRITE (nindy_serial, buf, p - buf);
while (1){
if ( !rdnin(&ack,1,5) ){
/* timed out */
fprintf(stderr,"ACK timed out; resending\r\n");
/* Attention, NINDY! */
SERIAL_WRITE (nindy_serial, "\020", 1);
SERIAL_WRITE (nindy_serial, buf, p - buf);
} else if ( ack == '+' ){
return;
} else if ( ack == '-' ){
fprintf( stderr, "Remote NAK; resending\r\n" );
SERIAL_WRITE (nindy_serial, buf, p - buf);
} else {
fprintf( stderr, "Bad ACK, ignored: <%c>\r\n", ack );
}
}
}
 
 
 
/******************************************************************************
* send:
* Send a message to a remote NINDY. Check message status byte
* for error responses. If no error, return NINDY reponse (if any).
******************************************************************************/
static
send( out, len, in )
unsigned char *out; /* Message to be sent to NINDY */
int len; /* Number of meaningful bytes in out buffer */
unsigned char *in; /* Where to put response received from NINDY */
{
char *fmt;
int status;
static char *errmsg[] = {
"", /* 0 */
"Buffer overflow", /* 1 */
"Unknown command", /* 2 */
"Wrong amount of data to load register(s)", /* 3 */
"Missing command argument(s)", /* 4 */
"Odd number of digits sent to load memory", /* 5 */
"Unknown register name", /* 6 */
"No such memory segment", /* 7 */
"No breakpoint available", /* 8 */
"Can't set requested baud rate", /* 9 */
};
# define NUMERRS ( sizeof(errmsg) / sizeof(errmsg[0]) )
 
static char err1[] = "Unknown error response from NINDY: #%d\r\n";
static char err2[] = "Error response #%d from NINDY: %s\r\n";
 
while (1){
putpkt(out,len);
status = getpkt(in);
if ( status == TIMEOUT ){
fprintf( stderr, "Response timed out; resending\r\n" );
} else {
break;
}
}
 
if ( status ){
fmt = status > NUMERRS ? err1 : err2;
fprintf( stderr, fmt, status, errmsg[status] );
abort();
}
}
/************************
* *
* BAUD RATE ROUTINES *
* *
************************/
 
/* Table of baudrates known to be acceptable to NINDY. Each baud rate
* appears both as character string and as a Unix baud rate constant.
*/
struct baudrate {
char *string;
int rate;
};
 
static struct baudrate baudtab[] = {
"1200", 1200,
"2400", 2400,
"4800", 4800,
"9600", 9600,
"19200", 19200,
"38400", 38400,
NULL, 0 /* End of table */
};
 
/******************************************************************************
* parse_baudrate:
* Look up the passed baud rate in the baudrate table. If found, change
* our internal record of the current baud rate, but don't do anything
* about the tty just now.
*
* Return pointer to baudrate structure on success, NULL on failure.
******************************************************************************/
static
struct baudrate *
parse_baudrate(s)
char *s; /* Desired baud rate, as an ASCII (decimal) string */
{
int i;
 
for ( i=0; baudtab[i].string != NULL; i++ ){
if ( !strcmp(baudtab[i].string,s) ){
return &baudtab[i];
}
}
return NULL;
}
 
/******************************************************************************
* try_baudrate:
* Try speaking to NINDY via the specified file descriptor at the
* specified baudrate. Assume success if we can send an empty command
* with a bogus checksum and receive a NAK (response of '-') back within
* one second.
*
* Return 1 on success, 0 on failure.
***************************************************************************/
 
static int
try_baudrate (serial, brp)
serial_t serial;
struct baudrate *brp;
{
unsigned char c;
 
/* Set specified baud rate and flush all pending input */
SERIAL_SETBAUDRATE (serial, brp->rate);
tty_flush (serial);
 
/* Send empty command with bad checksum, hope for NAK ('-') response */
SERIAL_WRITE (serial, "\020\0\0\001", 4);
 
/* Anything but a quick '-', including error, eof, or timeout, means that
this baudrate doesn't work. */
return SERIAL_READCHAR (serial, 1) == '-';
}
 
/******************************************************************************
* autobaud:
* Get NINDY talking over the specified file descriptor at the specified
* baud rate. First see if NINDY's already talking at 'baudrate'. If
* not, run through all the legal baudrates in 'baudtab' until one works,
* and then tell NINDY to talk at 'baudrate' instead.
******************************************************************************/
static
autobaud( serial, brp )
serial_t serial;
struct baudrate *brp;
{
int i;
int failures;
 
say("NINDY at wrong baud rate? Trying to autobaud...\n");
failures = i = 0;
while (1)
{
say( "\r%s... ", baudtab[i].string );
if (try_baudrate(serial, &baudtab[i]))
{
break;
}
if (baudtab[++i].string == NULL)
{
/* End of table -- wraparound */
i = 0;
if ( failures++ )
{
say("\nAutobaud failed again. Giving up.\n");
exit(1);
}
else
{
say("\nAutobaud failed. Trying again...\n");
}
}
}
 
/* Found NINDY's current baud rate; now change it. */
say("Changing NINDY baudrate to %s\n", brp->string);
ninBaud (brp->string);
 
/* Change our baud rate back to rate to which we just set NINDY. */
SERIAL_SETBAUDRATE (serial, brp->rate);
}
/**********************************
* *
* NINDY INTERFACE ROUTINES *
* *
* ninConnect *MUST* be the first *
* one of these routines called. *
**********************************/
 
 
/******************************************************************************
* ninBaud:
* Ask NINDY to change the baud rate on its serial port.
* Assumes we know the baud rate at which NINDY's currently talking.
******************************************************************************/
ninBaud( baudrate )
char *baudrate; /* Desired baud rate, as a string of ASCII decimal
* digits.
*/
{
unsigned char msg[100];
 
tty_flush (nindy_serial);
 
if (old_nindy)
{
char *p; /* Pointer into buffer */
unsigned char csum; /* Calculated checksum */
 
/* Can't use putpkt() because after the baudrate change NINDY's
ack/nak will look like gibberish. */
 
for (p=baudrate, csum=020+'z'; *p; p++)
{
csum += *p;
}
sprintf (msg, "\020z%s#%02x", baudrate, csum);
SERIAL_WRITE (nindy_serial, msg, strlen (msg));
}
else
{
/* Can't use "send" because NINDY reply will be unreadable after
baud rate change. */
sprintf( msg, "z%s", baudrate );
putpkt( msg, strlen(msg)+1 ); /* "+1" to send terminator too */
}
}
 
/******************************************************************************
* ninBptDel:
* Ask NINDY to delete the specified type of *hardware* breakpoint at
* the specified address. If the 'addr' is -1, all breakpoints of
* the specified type are deleted.
***************************************************************************/
ninBptDel( addr, type )
long addr; /* Address in 960 memory */
char type; /* 'd' => data bkpt, 'i' => instruction breakpoint */
{
unsigned char buf[10];
 
if ( old_nindy ){
OninBptDel( addr, type == 'd' ? 1 : 0 );
return;
}
 
buf[0] = 'b';
buf[1] = type;
 
if ( addr == -1 ){
send( buf, 2, NULL );
} else {
store_unsigned_integer (&buf[2], 4, addr);
send( buf, 6, NULL );
}
}
 
 
/******************************************************************************
* ninBptSet:
* Ask NINDY to set the specified type of *hardware* breakpoint at
* the specified address.
******************************************************************************/
ninBptSet( addr, type )
long addr; /* Address in 960 memory */
char type; /* 'd' => data bkpt, 'i' => instruction breakpoint */
{
unsigned char buf[10];
 
if ( old_nindy ){
OninBptSet( addr, type == 'd' ? 1 : 0 );
return;
}
 
 
buf[0] = 'B';
buf[1] = type;
store_unsigned_integer (&buf[2], 4, addr);
send( buf, 6, NULL );
}
 
 
/******************************************************************************
* ninConnect:
* Open the specified tty. Get communications working at the specified
* baud rate. Flush any pending I/O on the tty.
*
* Return the file descriptor, or -1 on failure.
******************************************************************************/
int
ninConnect( name, baudrate, brk, silent, old_protocol )
char *name; /* "/dev/ttyXX" to be opened */
char *baudrate;/* baud rate: a string of ascii decimal digits (eg,"9600")*/
int brk; /* 1 => send break to tty first thing after opening it*/
int silent; /* 1 => stifle unnecessary messages when talking to
* this tty.
*/
int old_protocol;
{
int i;
char *p;
struct baudrate *brp;
 
/* We will try each of the following paths when trying to open the tty
*/
static char *prefix[] = { "", "/dev/", "/dev/tty", NULL };
 
if ( old_protocol ){
old_nindy = 1;
}
 
quiet = silent; /* Make global to this file */
 
for ( i=0; prefix[i] != NULL; i++ ){
p = xmalloc(strlen(prefix[i]) + strlen(name) + 1 );
strcpy( p, prefix[i] );
strcat( p, name );
nindy_serial = SERIAL_OPEN (p);
if (nindy_serial != NULL) {
#ifdef TIOCEXCL
/* Exclusive use mode (hp9000 does not support it) */
ioctl(nindy_serial->fd,TIOCEXCL,NULL);
#endif
SERIAL_RAW (nindy_serial);
 
if (brk)
{
SERIAL_SEND_BREAK (nindy_serial);
}
 
brp = parse_baudrate( baudrate );
if ( brp == NULL ){
say("Illegal baudrate %s ignored; using 9600\n",
baudrate);
brp = parse_baudrate( "9600" );
}
 
if ( !try_baudrate(nindy_serial, brp) ){
autobaud(nindy_serial, brp);
}
tty_flush (nindy_serial);
say( "Connected to %s\n", p );
free(p);
break;
}
free(p);
}
return 0;
}
 
#if 0
 
/* Currently unused; shouldn't we be doing this on target_kill and
perhaps target_mourn? FIXME. */
 
/******************************************************************************
* ninGdbExit:
* Ask NINDY to leave GDB mode and print a NINDY prompt.
****************************************************************************/
ninGdbExit()
{
if ( old_nindy ){
OninGdbExit();
return;
}
putpkt((unsigned char *) "E", 1 );
}
#endif
 
/******************************************************************************
* ninGo:
* Ask NINDY to start or continue execution of an application program
* in it's memory at the current ip.
******************************************************************************/
ninGo( step_flag )
int step_flag; /* 1 => run in single-step mode */
{
if ( old_nindy ){
OninGo( step_flag );
return;
}
putpkt((unsigned char *) (step_flag ? "s" : "c"), 1 );
}
 
 
/******************************************************************************
* ninMemGet:
* Read a string of bytes from NINDY's address space (960 memory).
******************************************************************************/
int
ninMemGet(ninaddr, hostaddr, len)
long ninaddr; /* Source address, in the 960 memory space */
unsigned char *hostaddr; /* Destination address, in our memory space */
int len; /* Number of bytes to read */
{
unsigned char buf[BUFSIZE+20];
int cnt; /* Number of bytes in next transfer */
int origlen = len;
 
if ( old_nindy ){
OninMemGet(ninaddr, hostaddr, len);
return;
}
 
for ( ; len > 0; len -= BUFSIZE ){
cnt = len > BUFSIZE ? BUFSIZE : len;
 
buf[0] = 'm';
store_unsigned_integer (&buf[1], 4, ninaddr);
buf[5] = cnt & 0xff;
buf[6] = (cnt>>8) & 0xff;
 
send( buf, 7, hostaddr );
 
ninaddr += cnt;
hostaddr += cnt;
}
return origlen;
}
 
 
/******************************************************************************
* ninMemPut:
* Write a string of bytes into NINDY's address space (960 memory).
******************************************************************************/
int
ninMemPut( ninaddr, hostaddr, len )
long ninaddr; /* Destination address, in NINDY memory space */
unsigned char *hostaddr; /* Source address, in our memory space */
int len; /* Number of bytes to write */
{
unsigned char buf[BUFSIZE+20];
int cnt; /* Number of bytes in next transfer */
int origlen = len;
 
if ( old_nindy ){
OninMemPut( ninaddr, hostaddr, len );
return;
}
for ( ; len > 0; len -= BUFSIZE ){
cnt = len > BUFSIZE ? BUFSIZE : len;
 
buf[0] = 'M';
store_unsigned_integer (&buf[1], 4, ninaddr);
memcpy(buf + 5, hostaddr, cnt);
send( buf, cnt+5, NULL );
 
ninaddr += cnt;
hostaddr += cnt;
}
return origlen;
}
 
/******************************************************************************
* ninRegGet:
* Retrieve the contents of a 960 register, and return them as a long
* in host byte order.
*
* THIS ROUTINE CAN ONLY BE USED TO READ THE LOCAL, GLOBAL, AND
* ip/ac/pc/tc REGISTERS.
*
******************************************************************************/
long
ninRegGet( regname )
char *regname; /* Register name recognized by NINDY, subject to the
* above limitations.
*/
{
unsigned char outbuf[10];
unsigned char inbuf[20];
 
if ( old_nindy ){
return OninRegGet( regname );
}
 
sprintf( outbuf, "u%s:", regname );
send( outbuf, strlen(outbuf), inbuf );
return extract_unsigned_integer (inbuf, 4);
}
 
/******************************************************************************
* ninRegPut:
* Set the contents of a 960 register.
*
* THIS ROUTINE CAN ONLY BE USED TO SET THE LOCAL, GLOBAL, AND
* ip/ac/pc/tc REGISTERS.
*
******************************************************************************/
ninRegPut( regname, val )
char *regname; /* Register name recognized by NINDY, subject to the
* above limitations.
*/
long val; /* New contents of register, in host byte-order */
{
unsigned char buf[20];
int len;
 
if ( old_nindy ){
OninRegPut( regname, val );
return;
}
 
sprintf( buf, "U%s:", regname );
len = strlen(buf);
store_unsigned_integer (&buf[len], 4, val);
send( buf, len+4, NULL );
}
 
/******************************************************************************
* ninRegsGet:
* Get a dump of the contents of the entire 960 register set. The
* individual registers appear in the dump in the following order:
*
* pfp sp rip r3 r4 r5 r6 r7
* r8 r9 r10 r11 r12 r13 r14 r15
* g0 g1 g2 g3 g4 g5 g6 g7
* g8 g9 g10 g11 g12 g13 g14 fp
* pc ac ip tc fp0 fp1 fp2 fp3
*
* Each individual register comprises exactly 4 bytes, except for
* fp0-fp3, which are 8 bytes. All register values are in 960
* (little-endian) byte order.
*
******************************************************************************/
ninRegsGet( regp )
unsigned char *regp; /* Where to place the register dump */
{
if ( old_nindy ){
OninRegsGet( regp );
return;
}
send( (unsigned char *) "r", 1, regp );
}
 
 
/******************************************************************************
* ninRegsPut:
* Initialize the entire 960 register set to a specified set of values.
* The format of the register value data should be the same as that
* returned by ninRegsGet.
*
* WARNING:
* All register values must be in 960 (little-endian) byte order.
*
******************************************************************************/
ninRegsPut( regp )
char *regp; /* Pointer to desired values of registers */
{
/* Number of bytes that we send to nindy. I believe this is defined by
the protocol (it does not agree with REGISTER_BYTES). */
#define NINDY_REGISTER_BYTES ((36*4) + (4*8))
unsigned char buf[NINDY_REGISTER_BYTES+10];
 
if ( old_nindy ){
OninRegsPut( regp );
return;
}
 
buf[0] = 'R';
memcpy(buf+1, regp, NINDY_REGISTER_BYTES );
send( buf, NINDY_REGISTER_BYTES+1, NULL );
}
 
 
/******************************************************************************
* ninReset:
* Ask NINDY to perform a soft reset; wait for the reset to complete.
*
******************************************************************************/
ninReset()
{
unsigned char ack;
 
if ( old_nindy ){
OninReset();
return;
}
 
while (1){
putpkt((unsigned char *) "X", 1 );
while (1){
if ( !rdnin(&ack,1,5) ){
/* Timed out */
break; /* Resend */
}
if ( ack == '+' ){
return;
}
}
}
}
 
 
/******************************************************************************
* ninSrq:
* Assume NINDY has stopped execution of the 960 application program in
* order to process a host service request (srq). Ask NINDY for the
* srq arguments, perform the requested service, and send an "srq
* complete" message so NINDY will return control to the application.
*
******************************************************************************/
ninSrq()
{
/* FIXME: Imposes arbitrary limits on lengths of pathnames and such. */
unsigned char buf[BUFSIZE];
int retcode;
unsigned char srqnum;
int i;
int offset;
int arg[MAX_SRQ_ARGS];
 
if ( old_nindy ){
OninSrq();
return;
}
 
 
/* Get srq number and arguments
*/
send((unsigned char *) "!", 1, buf );
 
srqnum = buf[0];
for ( i=0, offset=1; i < MAX_SRQ_ARGS; i++, offset+=4 ){
arg[i] = extract_unsigned_integer (&buf[offset], 4);
}
 
/* Process Srq
*/
switch( srqnum ){
case BS_CLOSE:
/* args: file descriptor */
if ( arg[0] > 2 ){
retcode = close( arg[0] );
} else {
retcode = 0;
}
break;
case BS_CREAT:
/* args: filename, mode */
ninStrGet( arg[0], buf );
retcode = creat(buf,arg[1]);
break;
case BS_OPEN:
/* args: filename, flags, mode */
ninStrGet( arg[0], buf );
retcode = open(buf,arg[1],arg[2]);
break;
case BS_READ:
/* args: file descriptor, buffer, count */
retcode = read(arg[0],buf,arg[2]);
if ( retcode > 0 ){
ninMemPut( arg[1], buf, retcode );
}
break;
case BS_SEEK:
/* args: file descriptor, offset, whence */
retcode = lseek(arg[0],arg[1],arg[2]);
break;
case BS_WRITE:
/* args: file descriptor, buffer, count */
ninMemGet( arg[1], buf, arg[2] );
retcode = write(arg[0],buf,arg[2]);
break;
default:
retcode = -1;
break;
}
 
/* Send request termination status to NINDY
*/
buf[0] = 'e';
store_unsigned_integer (&buf[1], 4, retcode);
send( buf, 5, NULL );
}
 
 
/******************************************************************************
* ninStopWhy:
* Assume the application program has stopped (i.e., a DLE was received
* from NINDY). Ask NINDY for status information describing the
* reason for the halt.
*
* Returns a non-zero value if the user program has exited, 0 otherwise.
* Also returns the following information, through passed pointers:
* - why: an exit code if program the exited; otherwise the reason
* why the program halted (see stop.h for values).
* - contents of register ip (little-endian byte order)
* - contents of register sp (little-endian byte order)
* - contents of register fp (little-endian byte order)
******************************************************************************/
char
ninStopWhy( whyp, ipp, fpp, spp )
unsigned char *whyp; /* Return the 'why' code through this pointer */
long *ipp; /* Return contents of register ip through this pointer */
long *fpp; /* Return contents of register fp through this pointer */
long *spp; /* Return contents of register sp through this pointer */
{
unsigned char buf[30];
extern char OninStopWhy ();
 
if ( old_nindy ){
return OninStopWhy( whyp, ipp, fpp, spp );
}
send((unsigned char *) "?", 1, buf );
 
*whyp = buf[1];
memcpy ((char *)ipp, &buf[2], sizeof (*ipp));
memcpy ((char *)fpp, &buf[6], sizeof (*ipp));
memcpy ((char *)spp, &buf[10], sizeof (*ipp));
return buf[0];
}
 
/******************************************************************************
* ninStrGet:
* Read a '\0'-terminated string of data out of the 960 memory space.
*
******************************************************************************/
static
ninStrGet( ninaddr, hostaddr )
unsigned long ninaddr; /* Address of string in NINDY memory space */
unsigned char *hostaddr; /* Address of the buffer to which string should
* be copied.
*/
{
unsigned char cmd[5];
 
cmd[0] = '"';
store_unsigned_integer (&cmd[1], 4, ninaddr);
send( cmd, 5, hostaddr );
}
 
#if 0
/* Not used. */
 
/******************************************************************************
* ninVersion:
* Ask NINDY for version information about itself.
* The information is sent as an ascii string in the form "x.xx,<arch>",
* where,
* x.xx is the version number
* <arch> is the processor architecture: "KA", "KB", "MC", "CA" *
*
******************************************************************************/
int
ninVersion( p )
unsigned char *p; /* Where to place version string */
{
 
if ( old_nindy ){
return OninVersion( p );
}
send((unsigned char *) "v", 1, p );
return strlen(p);
}
#endif /* 0 */
/coff.h
0,0 → 1,336
/* Copyright 1990, 1992 Free Software Foundation, Inc.
*
* This code was donated by Intel Corp.
*
* This is a coff version of a.out.h to support 80960 debugging from
* a Unix (possibly BSD) host. It's used by:
* o gdb960 to symbols in code generated with Intel (non-GNU) tools.
* o comm960 to convert a b.out file to a coff file for download.
*/
 
 
/********************** FILE HEADER **********************/
 
struct filehdr {
unsigned short f_magic; /* magic number */
unsigned short f_nscns; /* number of sections */
long f_timdat; /* time & date stamp */
long f_symptr; /* file pointer to symtab */
long f_nsyms; /* number of symtab entries */
unsigned short f_opthdr; /* sizeof(optional hdr) */
unsigned short f_flags; /* flags */
};
 
 
/* Bits for f_flags:
* F_RELFLG relocation info stripped from file
* F_EXEC file is executable (no unresolved externel references)
* F_LNNO line nunbers stripped from file
* F_LSYMS local symbols stripped from file
* F_AR32WR file has byte ordering of an AR32WR machine (e.g. vax)
*/
#define F_RELFLG 0000001
#define F_EXEC 0000002
#define F_LNNO 0000004
#define F_LSYMS 0000010
#define F_AR32WR 0000400
 
 
/*
* Intel 80960 (I960) processor flags.
* F_I960TYPE == mask for processor type field.
*/
#define F_I960TYPE 0170000
#define F_I960CA 0010000
#define F_I960FLOAT 0020000
#define F_I960BA 0030000
#define F_I960XA 0040000
 
/*
* i80960 Magic Numbers
*/
#define I960ROMAGIC 0540 /* read-only text segments */
#define I960RWMAGIC 0541 /* read-write text segments */
 
#define I960BADMAG(x) (((x).f_magic!=I960ROMAGIC) && ((x).f_magic!=I960RWMAGIC))
 
#define FILHDR struct filehdr
#define FILHSZ sizeof(FILHDR)
 
 
/********************** AOUT "OPTIONAL HEADER" **********************/
 
typedef struct {
unsigned long phys_addr;
unsigned long bitarray;
} TAGBITS;
 
typedef struct aouthdr {
short magic; /* type of file */
short vstamp; /* version stamp */
unsigned long tsize; /* text size in bytes, padded to FW bdry*/
unsigned long dsize; /* initialized data " " */
unsigned long bsize; /* uninitialized data " " */
#if U3B
unsigned long dum1;
unsigned long dum2; /* pad to entry point */
#endif
unsigned long entry; /* entry pt. */
unsigned long text_start; /* base of text used for this file */
unsigned long data_start; /* base of data used for this file */
unsigned long tagentries; /* number of tag entries to follow */
} AOUTHDR;
 
/* return a pointer to the tag bits array */
 
#define TAGPTR(aout) ((TAGBITS *) (&(aout.tagentries)+1))
 
/* compute size of a header */
 
#define AOUTSZ(aout) (sizeof(AOUTHDR)+(aout.tagentries*sizeof(TAGBITS)))
 
/********************** STORAGE CLASSES **********************/
 
#define C_EFCN -1 /* physical end of function */
#define C_NULL 0
#define C_AUTO 1 /* automatic variable */
#define C_EXT 2 /* external symbol */
#define C_STAT 3 /* static */
#define C_REG 4 /* register variable */
#define C_EXTDEF 5 /* external definition */
#define C_LABEL 6 /* label */
#define C_ULABEL 7 /* undefined label */
#define C_MOS 8 /* member of structure */
#define C_ARG 9 /* function argument */
#define C_STRTAG 10 /* structure tag */
#define C_MOU 11 /* member of union */
#define C_UNTAG 12 /* union tag */
#define C_TPDEF 13 /* type definition */
#define C_USTATIC 14 /* undefined static */
#define C_ENTAG 15 /* enumeration tag */
#define C_MOE 16 /* member of enumeration */
#define C_REGPARM 17 /* register parameter */
#define C_FIELD 18 /* bit field */
#define C_BLOCK 100 /* ".bb" or ".eb" */
#define C_FCN 101 /* ".bf" or ".ef" */
#define C_EOS 102 /* end of structure */
#define C_FILE 103 /* file name */
#define C_LINE 104 /* line # reformatted as symbol table entry */
#define C_ALIAS 105 /* duplicate tag */
#define C_HIDDEN 106 /* ext symbol in dmert public lib */
 
/* New storage classes for 80960 */
#define C_SCALL 107 /* Procedure reachable via system call */
#define C_LEAFPROC 108 /* Leaf procedure, "call" via BAL */
 
 
/********************** SECTION HEADER **********************/
 
struct scnhdr {
char s_name[8]; /* section name */
long s_paddr; /* physical address, aliased s_nlib */
long s_vaddr; /* virtual address */
long s_size; /* section size */
long s_scnptr; /* file ptr to raw data for section */
long s_relptr; /* file ptr to relocation */
long s_lnnoptr; /* file ptr to line numbers */
unsigned short s_nreloc; /* number of relocation entries */
unsigned short s_nlnno; /* number of line number entries*/
long s_flags; /* flags */
unsigned long s_align; /* section alignment */
};
 
/*
* names of "special" sections
*/
#define _TEXT ".text"
#define _DATA ".data"
#define _BSS ".bss"
 
/*
* s_flags "type"
*/
#define STYP_TEXT 0x20 /* section contains text only */
#define STYP_DATA 0x40 /* section contains data only */
#define STYP_BSS 0x80 /* section contains bss only */
 
#define SCNHDR struct scnhdr
#define SCNHSZ sizeof(SCNHDR)
 
 
/********************** LINE NUMBERS **********************/
 
/* 1 line number entry for every "breakpointable" source line in a section.
* Line numbers are grouped on a per function basis; first entry in a function
* grouping will have l_lnno = 0 and in place of physical address will be the
* symbol table index of the function name.
*/
struct lineno{
union {
long l_symndx; /* function name symbol index, iff l_lnno == 0*/
long l_paddr; /* (physical) address of line number */
} l_addr;
unsigned short l_lnno; /* line number */
char padding[2]; /* force alignment */
};
 
#define LINENO struct lineno
#define LINESZ sizeof(LINENO)
 
 
/********************** SYMBOLS **********************/
 
#define SYMNMLEN 8 /* # characters in a symbol name */
#define FILNMLEN 14 /* # characters in a file name */
#define DIMNUM 4 /* # array dimensions in auxiliary entry */
 
 
struct syment {
union {
char _n_name[SYMNMLEN]; /* old COFF version */
struct {
long _n_zeroes; /* new == 0 */
long _n_offset; /* offset into string table */
} _n_n;
char *_n_nptr[2]; /* allows for overlaying */
} _n;
long n_value; /* value of symbol */
short n_scnum; /* section number */
char pad1[2]; /* force alignment */
unsigned long n_type; /* type and derived type */
char n_sclass; /* storage class */
char n_numaux; /* number of aux. entries */
char pad2[2]; /* force alignment */
};
 
#define n_name _n._n_name
#define n_zeroes _n._n_n._n_zeroes
#define n_offset _n._n_n._n_offset
 
/*
* Relocatable symbols have number of the section in which they are defined,
* or one of the following:
*/
#define N_UNDEF 0 /* undefined symbol */
#define N_ABS -1 /* value of symbol is absolute */
#define N_DEBUG -2 /* debugging symbol -- symbol value is meaningless */
 
/*
* Type of a symbol, in low 4 bits of the word
*/
#define T_NULL 0
#define T_VOID 1 /* function argument (only used by compiler) */
#define T_CHAR 2 /* character */
#define T_SHORT 3 /* short integer */
#define T_INT 4 /* integer */
#define T_LONG 5 /* long integer */
#define T_FLOAT 6 /* floating point */
#define T_DOUBLE 7 /* double word */
#define T_STRUCT 8 /* structure */
#define T_UNION 9 /* union */
#define T_ENUM 10 /* enumeration */
#define T_MOE 11 /* member of enumeration*/
#define T_UCHAR 12 /* unsigned character */
#define T_USHORT 13 /* unsigned short */
#define T_UINT 14 /* unsigned integer */
#define T_ULONG 15 /* unsigned long */
#define T_LNGDBL 16 /* long double */
 
 
/*
* derived types
*/
#define DT_PTR 1 /* pointer */
#define DT_FCN 2 /* function */
#define DT_ARY 3 /* array */
 
#define N_BTMASK 037
#define N_TMASK 0140
#define N_BTSHFT 5
#define N_TSHIFT 2
 
#define BTYPE(x) ((x) & N_BTMASK)
 
 
#define ISPTR(x) (((x) & N_TMASK) == (DT_PTR << N_BTSHFT))
#define ISFCN(x) (((x) & N_TMASK) == (DT_FCN << N_BTSHFT))
#define ISARY(x) (((x) & N_TMASK) == (DT_ARY << N_BTSHFT))
 
#define DECREF(x) ((((x)>>N_TSHIFT)&~N_BTMASK)|((x)&N_BTMASK))
 
union auxent {
struct {
long x_tagndx; /* str, un, or enum tag indx */
union {
struct {
unsigned short x_lnno; /* declaration line number */
unsigned short x_size; /* str/union/array size */
} x_lnsz;
long x_fsize; /* size of function */
} x_misc;
union {
struct { /* if ISFCN, tag, or .bb */
long x_lnnoptr; /* ptr to fcn line # */
long x_endndx; /* entry ndx past block end */
} x_fcn;
struct { /* if ISARY, up to 4 dimen. */
unsigned short x_dimen[DIMNUM];
} x_ary;
} x_fcnary;
unsigned short x_tvndx; /* tv index */
} x_sym;
 
union {
char x_fname[FILNMLEN];
struct {
long x_zeroes;
long x_offset;
} x_n;
} x_file;
 
struct {
long x_scnlen; /* section length */
unsigned short x_nreloc; /* # relocation entries */
unsigned short x_nlinno; /* # line numbers */
} x_scn;
 
struct {
long x_stdindx;
} x_sc;
 
struct {
unsigned long x_balntry;
} x_bal;
 
char a[sizeof(struct syment)]; /* force auxent/syment sizes to match */
};
 
#define SYMENT struct syment
#define SYMESZ sizeof(SYMENT)
#define AUXENT union auxent
#define AUXESZ sizeof(AUXENT)
 
#if VAX || I960
# define _ETEXT "_etext"
#else
# define _ETEXT "etext"
#endif
 
/********************** RELOCATION DIRECTIVES **********************/
 
struct reloc {
long r_vaddr; /* Virtual address of reference */
long r_symndx; /* Index into symbol table */
unsigned short r_type; /* Relocation type */
char pad[2]; /* Unused */
};
 
/* Only values of r_type GNU/960 cares about */
#define R_RELLONG 17 /* Direct 32-bit relocation */
#define R_IPRMED 25 /* 24-bit ip-relative relocation */
#define R_OPTCALL 27 /* 32-bit optimizable call (leafproc/sysproc) */
 
 
#define RELOC struct reloc
#define RELSZ sizeof(RELOC)
/ttyflush.c
0,0 → 1,53
/* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
 
/* This started out life as code shared between the nindy monitor and
GDB. For various reasons, this is no longer true. Eventually, it
probably should be merged into remote-nindy.c. */
 
#include <stdio.h>
#include "defs.h"
#include "serial.h"
 
#ifdef _MSC_VER
# include <stdlib.h>
# define sleep _sleep
#endif
 
/* Flush all pending input and output for SERIAL, wait for a second, and
then if there is a character pending, discard it and flush again. */
 
int
tty_flush (serial)
serial_t serial;
{
while (1)
{
SERIAL_FLUSH_INPUT (serial);
SERIAL_FLUSH_OUTPUT (serial);
sleep(1);
switch (SERIAL_READCHAR (serial, 0))
{
case SERIAL_TIMEOUT:
case SERIAL_ERROR:
case SERIAL_EOF:
return 0;
default:
/* We read something. Eeek. Try again. */
break;
}
}
}
/VERSION
0,0 → 1,53
1.2
/block_io.h
0,0 → 1,68
/******************************************************************
Copyright 1990, 1992 Free Software Foundation, Inc.
 
This code was donated by Intel Corp.
 
Intel hereby grants you permission to copy, modify, and
distribute this software and its documentation. Intel grants
this permission provided that the above copyright notice
appears in all copies and that both the copyright notice and
this permission notice appear in supporting documentation. In
addition, Intel grants this permission provided that you
prominently mark as not part of the original any modifications
made to this software or documentation, and that the name of
Intel Corporation not be used in advertising or publicity
pertaining to distribution of the software or the documentation
without specific, written prior permission.
 
Intel Corporation does not warrant, guarantee or make any
representations regarding the use of, or the results of the use
of, the software and documentation in terms of correctness,
accuracy, reliability, currentness, or otherwise; and you rely
on the software, documentation and results solely at your own
risk. */
/******************************************************************/
 
/*****************************************************************************
* Structures and definitions supporting NINDY requests for services by a
* remote host. Used by NINDY monitor, library libnin, comm960, gdb960,
* etc. Also contains some defines for NINDY console I/O requests.
*****************************************************************************/
 
/* the following four are hardware dependent */
#define BIT_16 short
#define BIT_32 int
#define UBIT_16 unsigned short
#define UBIT_32 unsigned int
 
/* Service request numbers -- these are the services that can be asked of the
* host.
*/
#define BS_ACCESS 0x10
#define BS_CLOSE 0x20
#define BS_CREAT 0x30
#define BS_SEEK 0x40
#define BS_OPEN 0x50
#define BS_READ 0x60
#define BS_STAT 0x70
#define BS_SYSTEMD 0x80
#define BS_TIME 0x90
#define BS_UNMASK 0xa0
#define BS_UNLINK 0xb0
#define BS_WRITE 0xc0
 
 
/* Maximum number of arguments to any of the above service requests
* (in addition to the request number).
*/
#define MAX_SRQ_ARGS 3
 
/* Number of bytes of data that can be read or written by a single I/O request
*/
#define BUFSIZE 1024
 
/* NINDY console I/O requests: CO sends a single character to stdout,
* CI reads one.
*/
#define CI 0
#define CO 1
/stop.h
0,0 → 1,86
/******************************************************************
Copyright 1990, 1992 Free Software Foundation, Inc.
 
This code was donated by Intel Corp.
 
Intel hereby grants you permission to copy, modify, and
distribute this software and its documentation. Intel grants
this permission provided that the above copyright notice
appears in all copies and that both the copyright notice and
this permission notice appear in supporting documentation. In
addition, Intel grants this permission provided that you
prominently mark as not part of the original any modifications
made to this software or documentation, and that the name of
Intel Corporation not be used in advertising or publicity
pertaining to distribution of the software or the documentation
without specific, written prior permission.
 
Intel Corporation does not warrant, guarantee or make any
representations regarding the use of, or the results of the use
of, the software and documentation in terms of correctness,
accuracy, reliability, currentness, or otherwise; and you rely
on the software, documentation and results solely at your own
risk. */
/******************************************************************/
 
 
/******************************************************************
*
* REASONS WHY NINDY CAN STOP EXECUTING AN APPLICATION PROGRAM
*
* When NINDY stops executing an application program that was running
* under remote host ("gdb") control, it signals the host by sending
* a single ^P. The host can then query as to the reason for the halt.
* NINDY responds with two bytes of information.
*
* The first byte is a boolean flag that indicates whether or not
* the application has exited.
*
* If the flag is true, the second byte contains the exit code.
*
* If the flag is false, the second byte contains a "reason for
* stopping" code. This file defines the possible values of that
* code.
*
* There are three categories of reasons why the halt may have occurred:
* faults, traces, and software interactions. The first two categories
* are processor-dependent; the values of these codes are tightly coupled
* to the hardware and should not be changed without first examining
* src/nindy/common/fault.c. The software interactions involve
* communication between NINDY and the host debugger; their codes are
* arbitrary.
*
******************************************************************/
 
#define FAULT_PARALLEL 0x00
#define FAULT_UNKNOWN 0x01
#define FAULT_OPERATION 0x02
#define FAULT_ARITH 0x03
#define FAULT_FP 0x04
#define FAULT_CONSTR 0x05
#define FAULT_VM 0x06
#define FAULT_PROTECT 0x07
#define FAULT_MACHINE 0x08
#define FAULT_STRUCT 0x09
#define FAULT_TYPE 0x0a
/* 0x0b reserved */
#define FAULT_PROCESS 0x0c
#define FAULT_DESC 0x0d
#define FAULT_EVENT 0x0e
/* 0x0f reserved */
 
#define LAST_FAULT 0x0f
 
#define TRACE_STEP 0x10
#define TRACE_BRANCH 0x11
#define TRACE_CALL 0x12
#define TRACE_RET 0x13
#define TRACE_PRERET 0x14
#define TRACE_SVC 0x15
#define TRACE_BKPT 0x16
 
#define STOP_SRQ 0xfe
/* Application program has service request to make of host */
 
#define STOP_GDB_BPT 0xff
/* Application program has reached breakpoint (fmark) set by host */
/Makefile
0,0 → 1,117
#Copyright 1992 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 
#-----------------------------------------------------------------------------
# Makefile for toolib.a -- host code shAred by more than one tool
#-----------------------------------------------------------------------------
 
RANLIB = ranlib
 
# The following lines should be uncommented for system V (i386v).
#__i386v__#USG = -DUSG
#__i386v__#SYSV_INCL = ${IPATH}/sysv.h
#__i386v__#RANLIB = echo >/dev/null
 
# The following line should be uncommented for HP-UX
#__hp9000__#USG = -DUSG
#__hp9000__#SYSV_INCL = ${IPATH}/sysv.h
#__hp9000__#RANLIB = echo >/dev/null
 
# Essential under System V, harmless elsewhere
SHELL = /bin/sh
 
#'HOST' will be defined in the host-specific makefile by 'make make'
 
TARG = toolib.a
OPT = -g
IPATH = ../../include
CFLAGS = ${OPT} ${USG} -I${IPATH} -DHOST=\"${HOST}\"
OBJS = coffstrip.o nindy.o ttybreak.o ttyflush.o Onindy.o
 
${TARG}: ${OBJS} VERSION
make ver960.o
rm -f ${TARG}
ar cvr ${TARG} ${OBJS} ver960.o
${RANLIB} ${TARG}
 
coffstrip.o: ${IPATH}/b.out.h ${IPATH}/coff.h ${IPATH}/sysv.h
nindy.o: ${IPATH}/block_io.h ${IPATH}/env.h ${IPATH}/sysv.h
nindy.o: ${IPATH}/ttycntl.h ${IPATH}/wait.h
ttybreak.o: ${IPATH}/ttycntl.h
ttyflush.o: ${IPATH}/ttycntl.h
Onindy.o: ${IPATH}/block_io.h ${IPATH}/env.h ${IPATH}/sysv.h
Onindy.o: ${IPATH}/ttycntl.h ${IPATH}/wait.h
 
 
#-----------------------------------------------------------------------------
# 'STANDARD' GNU/960 TARGETS BELOW THIS POINT
#
# 'VERSION' file must be present and contain a string of the form "x.y"
#-----------------------------------------------------------------------------
 
ver960.c: FORCE
rm -f ver960.c
echo "char toolib_ver[]= \"${TARG} `cat VERSION`, `date`\";" > ver960.c
 
 
# This target should be invoked before building a new release.
# 'VERSION' file must be present and contain a string of the form "x.y"
#
roll:
@V=`cat VERSION` ; \
MAJ=`sed 's/\..*//' VERSION` ; \
MIN=`sed 's/.*\.//' VERSION` ; \
V=$$MAJ.`expr $$MIN + 1` ; \
rm -f VERSION ; \
echo $$V >VERSION ; \
echo Version $$V
 
# Dummy target to force execution of dependent targets.
#
FORCE:
 
# 'G960BASE' will be defined at invocation
#
install:
make ${TARG}
mv -f ${TARG} ${G960BASE}/lib
 
clean:
rm -f ${TARG} *.o core
 
# Target to uncomment host-specific lines in this makefile. Such lines must
# have the following string beginning in column 1: #__<hostname>__#
# Original Makefile is backed up as 'Makefile.old'.
#
# Invoke with: make make HOST=xxx
#
make:
-@if test $(HOST)x = x ; then \
echo 'Specify "make make HOST=???"'; \
exit 1; \
fi ; \
grep -s "^#The next line was generated by 'make make'" Makefile; \
if test $$? = 0 ; then \
echo "Makefile has already been processed with 'make make'";\
exit 1; \
fi ; \
mv -f Makefile Makefile.old; \
echo "#The next line was generated by 'make make'" >Makefile ; \
echo "HOST=$(HOST)" >>Makefile ; \
echo >>Makefile ; \
sed "s/^#__$(HOST)__#//" < Makefile.old >>Makefile
/README
0,0 → 1,3
The files in this directory started out life as code shared between
the nindy monitor and GDB. For various reasons, this is no longer
true. Eventually, they probably should be merged into remote-nindy.c.
/b.out.h
0,0 → 1,158
/* Copyright 1992 Free Software Foundation, Inc.
*
* This file is a modified version of 'a.out.h'. It is to be used in all
* all GNU tools modified to support the i80960 (or tools that operate on
* object files created by such tools).
*
* All i80960 development is done in a CROSS-DEVELOPMENT environment. I.e.,
* object code is generated on, and executed under the direction of a symbolic
* debugger running on, a host system. We do not want to be subject to the
* vagaries of which host it is or whether it supports COFF or a.out format,
* or anything else. We DO want to:
*
* o always generate the same format object files, regardless of host.
*
* o have an 'a.out' header that we can modify for our own purposes
* (the 80960 is typically an embedded processor and may require
* enhanced linker support that the normal a.out.h header can't
* accommodate).
*
* As for byte-ordering, the following rules apply:
*
* o Text and data that is actually downloaded to the target is always
* in i80960 (little-endian) order.
*
* o All other numbers (in the header, symbols, relocation directives)
* are in host byte-order: object files CANNOT be lifted from a
* little-end host and used on a big-endian (or vice versa) without
* modification.
*
* o The downloader ('comm960') takes care to generate a pseudo-header
* with correct (i80960) byte-ordering before shipping text and data
* off to the NINDY monitor in the target systems. Symbols and
* relocation info are never sent to the target.
*/
 
 
#define BMAGIC 0415
/* We don't accept the following (see N_BADMAG macro).
* They're just here so GNU code will compile.
*/
#define OMAGIC 0407 /* old impure format */
#define NMAGIC 0410 /* read-only text */
#define ZMAGIC 0413 /* demand load format */
 
/* FILE HEADER
* All 'lengths' are given as a number of bytes.
* All 'alignments' are for relinkable files only; an alignment of
* 'n' indicates the corresponding segment must begin at an
* address that is a multiple of (2**n).
*/
struct exec {
/* Standard stuff */
unsigned long a_magic; /* Identifies this as a b.out file */
unsigned long a_text; /* Length of text */
unsigned long a_data; /* Length of data */
unsigned long a_bss; /* Length of runtime uninitialized data area */
unsigned long a_syms; /* Length of symbol table */
unsigned long a_entry; /* Runtime start address */
unsigned long a_trsize; /* Length of text relocation info */
unsigned long a_drsize; /* Length of data relocation info */
 
/* Added for i960 */
unsigned long a_tload; /* Text runtime load address */
unsigned long a_dload; /* Data runtime load address */
unsigned char a_talign; /* Alignment of text segment */
unsigned char a_dalign; /* Alignment of data segment */
unsigned char a_balign; /* Alignment of bss segment */
unsigned char unused; /* (Just to make struct size a multiple of 4) */
};
 
#define N_BADMAG(x) (((x).a_magic)!=BMAGIC)
#define N_TXTOFF(x) ( sizeof(struct exec) )
#define N_DATOFF(x) ( N_TXTOFF(x) + (x).a_text )
#define N_TROFF(x) ( N_DATOFF(x) + (x).a_data )
#define N_DROFF(x) ( N_TROFF(x) + (x).a_trsize )
#define N_SYMOFF(x) ( N_DROFF(x) + (x).a_drsize )
#define N_STROFF(x) ( N_SYMOFF(x) + (x).a_syms )
 
/* A single entry in the symbol table
*/
struct nlist {
union {
char *n_name;
struct nlist *n_next;
long n_strx; /* Index into string table */
} n_un;
unsigned char n_type; /* See below */
char n_other; /* Used in i80960 support -- see below */
short n_desc;
unsigned long n_value;
};
 
 
/* Legal values of n_type
*/
#define N_UNDF 0 /* Undefined symbol */
#define N_ABS 2 /* Absolute symbol */
#define N_TEXT 4 /* Text symbol */
#define N_DATA 6 /* Data symbol */
#define N_BSS 8 /* BSS symbol */
#define N_FN 31 /* Filename symbol */
 
#define N_EXT 1 /* External symbol (OR'd in with one of above) */
#define N_TYPE 036 /* Mask for all the type bits */
#define N_STAB 0340 /* Mask for all bits used for SDB entries */
 
/* MEANING OF 'n_other'
*
* If non-zero, the 'n_other' fields indicates either a leaf procedure or
* a system procedure, as follows:
*
* 1 <= n_other <= 32 :
* The symbol is the entry point to a system procedure.
* 'n_value' is the address of the entry, as for any other
* procedure. The system procedure number (which can be used in
* a 'calls' instruction) is (n_other-1). These entries come from
* '.sysproc' directives.
*
* n_other == N_CALLNAME
* the symbol is the 'call' entry point to a leaf procedure.
* The *next* symbol in the symbol table must be the corresponding
* 'bal' entry point to the procedure (see following). These
* entries come from '.leafproc' directives in which two different
* symbols are specified (the first one is represented here).
*
*
* n_other == N_BALNAME
* the symbol is the 'bal' entry point to a leaf procedure.
* These entries result from '.leafproc' directives in which only
* one symbol is specified, or in which the same symbol is
* specified twice.
*
* Note that an N_CALLNAME entry *must* have a corresponding N_BALNAME entry,
* but not every N_BALNAME entry must have an N_CALLNAME entry.
*/
#define N_CALLNAME -1
#define N_BALNAME -2
 
 
struct relocation_info {
int r_address; /* File address of item to be relocated */
unsigned
r_symbolnum:24,/* Index of symbol on which relocation is based*/
r_pcrel:1, /* 1 => relocate PC-relative; else absolute
* On i960, pc-relative implies 24-bit
* address, absolute implies 32-bit.
*/
r_length:2, /* Number of bytes to relocate:
* 0 => 1 byte
* 1 => 2 bytes
* 2 => 4 bytes -- only value used for i960
*/
r_extern:1,
r_bsr:1, /* Something for the GNU NS32K assembler */
r_disp:1, /* Something for the GNU NS32K assembler */
r_callj:1, /* 1 if relocation target is an i960 'callj' */
nuthin:1; /* Unused */
};
/env.h
0,0 → 1,12
/* Copyright 1990, 1992 Free Software Foundation, Inc.
*
* This code was donated by Intel Corp.
*
* GNU/960 tool runtime environment
*/
 
 
/* Base directory at which GNU/960 tools are assumed to be installed, if
* the environment variable G960BASE is not defined.
*/
#define DEFAULT_BASE "/usr/local/g960"

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.