TI 99 assembler, the assembler itself
lee at unmvax.UUCP
lee at unmvax.UUCP
Mon Jul 23 03:15:47 AEST 1984
To unarchive, remove the first line through and
including the dashed line. Then type:
% sh <thisfilename>
Don't forget to strip off the .signature at the end!
-------------------------------------------
: Run this with sh NOT csh!
echo extracting Makefile
cat << //*FUNKYSTUFF*// > Makefile
YACC= yacc -d -v
LEX= lex
LIBS= -ll
CFLAGS= -g -DLEXDEBUG -DYYDEBUG -DDEBUG
PR= pr
LPR= lpr
DESTDIR= /usr/local/bin
DESTLIB= /usr/local/lib
CSRC= util.c aabort.c hash.c main.c rsrvd.c tiasm.c filutil.c Tild.c adrinf.c \\
tiload.c
OBJ= hash.o y.tab.o lex.yy.o util.o main.o rsrvd.o filutil.o aabort.o adrinf.o
FRONTEND= tiasm.o
LOADO= Tild.o hash.o aabort.o adrinf.o
install: all
install tiasm \$(DESTDIR)
install tiasm1 \$(DESTLIB)
install tild \$(DESTDIR)
all: tiasm tiasm1 tild tiload
tiasm: \$(FRONTEND)
cc \$(CFLAGS) \$(LDFLAGS) -o tiasm \$(FRONTEND)
tiasm1: \$(OBJ)
cc \$(CFLAGS) \$(LDFLAGS) -o tiasm1 \$(OBJ) \$(LIBS)
tild: \$(LOADO)
cc \$(CFLAGS) \$(LDFLAGS) -o tild \$(LOADO)
tiload: tiload.o
cc \$(CFLAGS) \$(LDFLAGS) -o tiload tiload.o
print: \$(CSRC) lex.lex parse.y TIasm.h opcodes.h mio.h TI.out.h
\$(PR) TIasm.h opcodes.h parse.y lex.lex \$(CSRC) \\
mio.h TI.out.h \\
| \$(LPR)
clean:
@-rm *.o core tiasm y.tab.h y.tab.c lex.yy.c tiasm1 y.output tild \\
tiload
y.tab.c: parse.y
\$(YACC) parse.y
lex.yy.c: lex.lex y.tab.h
\$(LEX) lex.lex
y.tab.h: y.tab.c
\$(OBJ) y.tab.c lex.yy.c: TIasm.h
rsrvd.o: opcodes.h
//*FUNKYSTUFF*//
echo extracting TI.out.h
cat << //*FUNKYSTUFF*// > TI.out.h
/* Format for an object file and loadable image */
/* Magic numbers */
#define OMAGIC 0x100 /* This is an obj file, not link edited yet */
#define BOBJ 0x80 /* Down loadable binary */
struct format {
short f_magic; /* Magic number */
short f_laddr; /* Load address */
short f_saddr; /* Start address */
short f_csiz; /* Size (in bytes) of executable */
};
/* Max size of an identifier */
#define IDENTSIZ 6
struct symbol {
char s_symnm[IDENTSIZ]; /* Symbol name */
short s_flags; /* Flags from st_type */
short s_raddr; /* Resolution address */
short s_naddr; /* Addresses to 16-bit patch */
};
//*FUNKYSTUFF*//
echo extracting TIasm.h
cat << //*FUNKYSTUFF*// > TIasm.h
#include "TI.out.h"
/* Size of vector for internal symbol table
* Not only is this a magic number but it SHOULD be the lower of twin
* primes and large enough to make the lists of buckets small.
*/
#define SYMVECSIZ 1103
/* Maximum number of files that can be assembled */
#define NFILES 50
/* Template for temp file names */
#define TFILNM "/tmp/TiXXXXXX"
/* Location of pass1 */
#define PASS1 "/usr/local/lib/tiasm1"
#ifdef DEBUG
#undef DEBUG
#define DEBUG(l,s,a) if (Debug > (l)) fprintf (stderr, (s), (a))
#else DEBUG
#define DEBUG(l,s,a)
#endif DEBUG
#define TRUE 1
#define FALSE 0
typedef short flag;
/* Types of entries in the symbol table */
#define TYRSRVD 0x1
#define TYLCLID 0x2
#define TYEXTID 0x4
#define TYRSLVD 0x8
#define TYDIR 0x10
/* A member of the list of addresses referencing an identifier */
struct a_lst {
short a_addr; /* address of opnd making ref */
struct a_lst *a_next; /* next member of list */
};
/* A symbol table entry */
struct stab {
char st_symnm[IDENTSIZ + 1]; /* Identifier/keyword name */
short st_type; /* Type of this entry */
union st_ent {
struct op_info {
unsigned short op_cod; /* opcode */
unsigned char op_fmt; /* Format code */
} en_op;
struct r_info {
struct a_lst *ri_lst; /* List of references */
struct j_lst *ri_jl; /* Jumps having this target */
short ri_addr; /* Resolution address */
} en_rinf;
} st_ent;
struct stab *st_next; /* Next bucket */
};
#define st_opc st_ent.en_op.op_cod
#define st_fmt st_ent.en_op.op_fmt
#define en_lst st_ent.en_rinf.ri_lst
#define en_addr st_ent.en_rinf.ri_addr
#define en_jl st_ent.en_rinf.ri_jl
/* A structure to store info about a symbol (absolute address or
* pointer to symbol table entry.
*/
struct symb {
short sy_tag; /* Tag */
union {
struct stab *sy_stb;
short sy_loc;
} sy_un;
};
#define SYMTAG 0x1 /* Operand is indexed */
#define RELOCATABLE 0x2 /* Relocatable as opposed to absolute */
/* Information about an operand specifier */
struct infop {
int t; /* T code */
int r; /* register */
struct symb sy_info;
};
#define in_stb sy_info.sy_un.sy_stb
#define in_loc sy_info.sy_un.sy_loc
#define in_tag sy_info.sy_tag
/* A member of the list of addresses and targets necessary to resolve jumps */
struct j_lst {
short j_addr; /* Word address for patch */
struct j_lst *j_next; /* Next member in list */
};
#define j_tag j_trgt.sy_tag
#define j_loc j_trgt.sy_un.sy_loc
#define j_stb j_trgt.sy_un.sy_stb
/* Structure for the initialization tables.
* op_fmt is for machine type formats 1 through 9
* op_fmt of zero is reserved to this program.
* op_code would be the opcode to plug in to the object file providing
* it is a valid machine format.
*/
struct ops {
char *op_name;
unsigned short op_code;
unsigned char op_fmt;
};
/* The following is used to reclaim space in the list of forward referencing
* jumps. It, obviously, will need to be changed if another storage method
* is used.
*/
#define rmjinf(x) (free((x)))
/* Is arg (integer) an odd number */
#define odd(x) ((x) % 2)
//*FUNKYSTUFF*//
echo extracting mio.h
cat << //*FUNKYSTUFF*// > mio.h
/* Some absolutely RUDE macros for doing portable (buffered) reads and writes.
* The open routine should be a macro but is just too large.
* The ideas behind these is that they will look EXACTLY like
* the UNIX primitives read, write and open but do their stuff
* buffered to keep us from going to the kernel too often.
* Close must be a routine as it must return something.
*/
extern int fread(), fwrite();
#define read(fd,bf,sz) fread((char *)&(bf),1,(sz),Sdvec[(fd)])
#define write(fd,bf,sz) fwrite((char *)&(bf),1,(sz),Sdvec[(fd)])
#define lseek(fd,x,w) fseek(Sdvec[(fd)],(x),(w))
/* Macros to do error checking */
#define xwrite(fd,bf,sz) if(Ferror == FALSE)if(write(fd,bf,sz) != sz)\\
aabort("Write error")
#define xseek(fd,x,w) if(Ferror == FALSE)if(lseek((fd),(x),(w)) == -1)\\
aabort("Seek error")
/* Is arg (integer) an odd number */
#define odd(x) ((x) % 2)
//*FUNKYSTUFF*//
echo extracting opcodes.h
cat << //*FUNKYSTUFF*// > opcodes.h
/* Machine instructions */
#define LI 0x200 /* Load Immediate */
#define AI 0x220 /* Add Immediate */
#define ANDI 0x240 /* AND Immediate */
#define ORI 0x0260 /* OR Immediate */
#define CI 0x0280 /* Compare Immediate */
#define STWP 0x02a0 /* STore Workspace Pointer */
#define STST 0x02c0 /* STore STatus register */
#define LWPI 0x02e0 /* Load Workspace Pointer Immediate */
#define LIMI 0x0300 /* Load Interrupt Mask Immediate */
#define IDLE 0x0340 /* IDLE */
#define RSET 0x0360 /* ReSET arithmetic unit */
#define RTWP 0x0380 /* ReTurn to old Workspace Pointer */
#define CKON 0x03a0 /* user defined */
#define CKOF 0x03c0 /* user defined */
#define LREX 0x03e0 /* Load Register and EXecute */
#define BLWP 0x0400 /* Branch, Load new Workspace Pointer */
#define B 0x0440 /* Branch */
#define X 0x0480 /* eXecute */
#define CLR 0x04c0 /* CLeaR to zeros */
#define NEG 0x0500 /* NEGate to ones */
#define INV 0x0540 /* INVert */
#define INC 0x0580 /* INCrement by one */
#define INCT 0x05c0 /* Increment by Two */
#define DEC 0x0600 /* DECrement by one */
#define DECT 0x0640 /* DECrement by two */
#define BL 0x0680 /* Branch and Link */
#define SWPB 0x06c0 /* SWaP Bytes */
#define SETO 0x0700 /* SET to Ones */
#define ABS 0x0740 /* ABSolute value */
#define SRA 0x0800 /* Shift Right Arithmetic */
#define SRL 0x0900 /* Shift Right Logical */
#define SLA 0x0a00 /* Shift Left Arithmetic */
#define SRC 0x0b00 /* Shift Right Circular */
#define JMP 0x1000 /* unconditional JuMP */
#define JLT 0x1100 /* Jump on Less Than */
#define JLE 0x1200 /* Jump on Less than or Equal */
#define JEQ 0x1300 /* Jump on EQual */
#define JHE 0x1400 /* Jump on High or Equal */
#define JGT 0x1500 /* Jump on Greater Than */
#define JNE 0x1600 /* Jump on Not Equal */
#define JNC 0x1700 /* Jump on No Carry */
#define JOC 0x1800 /* Jump on Overflow/Carry */
#define JNO 0x1900 /* Jump on No Overflow */
#define JL 0x1a00 /* Jump on Low */
#define JH 0x1b00 /* Jump on High */
#define JOP 0x1c00 /* Jump on Odd Parity */
#define SBO 0x1d00 /* Set cru Bits to Ones */
#define SBZ 0x1e00 /* Set cru Bits to Zeros */
#define TB 0x1f00 /* Test cru Bit */
#define COC 0x2000 /* Compare Ones Corresponding */
#define CZC 0x2400 /* Compare Zeros Corresponding */
#define XOR 0x2800 /* eXclusive OR */
#define LDCR 0x3000 /* LoaD CRu */
#define STCR 0x3400 /* STore CRu */
#define MPY 0x3800 /* MultiPlY */
#define DIV 0x3c00 /* DIVide */
#define SZC 0x4000 /* Set Zeros Corresponding (word) */
#define SZCB 0x5000 /* Set Zeros Corresponding (Byte) */
#define S 0x6000 /* Subtract (word) */
#define SB 0x7000 /* Subtract (Byte) */
#define C 0x8000 /* Compare (word) */
#define CB 0x9000 /* Compare (Byte) */
#define A 0xa000 /* Add (word) */
#define AB 0xb000 /* Add (Byte) */
#define MOV 0xc000 /* MOVe (word) */
#define MOVB 0xd000 /* MOVe (Byte) */
#define SOC 0xe000 /* Set Ones Corresponding (word) */
#define SOCB 0xf000 /* Set Ones Corresponding (Byte) */
#define XOP 0x2c00 /* eXtended OPeration */
//*FUNKYSTUFF*//
echo extracting Tild.c
cat << //*FUNKYSTUFF*// > Tild.c
#include "TIasm.h"
#include <stdio.h>
/* Some globals */
short laddr = 0x200; /* Default load address of bin file */
short saddr = 0x200; /* Default start address */
int Ofd; /* The fildes for the bin file */
short locctr = 0; /* The location counter */
short Debug;
main (argc, argv)
int argc;
char *argv[];
{
char *fvec[BUFSIZ]; /* Should be enough */
char *tmp, **avec, *arg;
char *outfil = "ti.out"; /* The output file */
int x;
int filcnt = 0; /* Number of files to edit */
struct format header;
argv[argc] = NULL;
avec = &argv[1];
while (*avec != NULL)
if (**avec != '-')
fvec[filcnt++] = *avec++;
else {
arg = *avec++;
while (*++arg != NULL)
switch (*arg) {
case 'd': /* Debug */
break;
case 's': /* Start address */
if (sscanf (*avec++,
"%x", &saddr) != 1) {
fprintf (stderr,
"Bad start address\\n");
exit (1);
}
break;
case 'l': /* Load adress */
if (sscanf (*avec++,
"%x", &laddr) != 1) {
fprintf (stderr,
"Bad load address\\n");
exit (1);
}
break;
default:
fprintf (stderr, "Unknown switch -%c\\n",
*arg);
}
}
if ((Ofd = creat(outfil, 0777)) < 0) {
fprintf (stderr, "cannot create \\"%s\\", aborting!\\n", outfil);
exit (1);
}
/* First write the execute header */
header.f_magic = BOBJ;
header.f_laddr = laddr;
header.f_saddr = saddr;
header.f_csiz = 0; /* Don't need this */
if (write(Ofd, (char *)&header, sizeof(header)) != sizeof(header))
aabort ("Error writing header");
for (x = 0; x < filcnt; ++x)
grabit (fvec[x]);
}
/* grabit
*
* Grab the file from the object module and copy it over to the .out. When
* done we get the symbol table info out and attempt to make patches. If we
* can't we'll save 'em for later. The routine that figures out what to do with
* the symbols makes the patches or whatever....
*
* RETURNS:
* nothing
*/
grabit (file)
char *file;
{
int ifd;
int x;
int nbytes, rmnng;
struct format header;
char buf[BUFSIZ];
if ((ifd = open(file, 0)) < 0) {
fprintf (stderr, "Could not open %s\\n", file);
exit (1);
}
/* Read in the header */
mread (ifd, (char *)&header, sizeof(header));
/* Check the magic number and abort if incorrect */
if (header.f_magic != OMAGIC) {
switch (header.f_magic) {
case BOBJ: /* Already link edited */
fprintf (stderr, "File \\"%s\\" has been link edited!\\n",
file);
break;
default:
fprintf (stderr, "What is \\"%s\\" ????\\n", file);
break;
}
exit (1);
}
/* Copy the code section across (buffered no less) */
for (x = 0; x < header.f_csiz; ) {
rmnng = header.f_csiz - x;
x += nbytes = rmnng / BUFSIZ > 0 ? BUFSIZ : rmnng;
if (read(ifd, buf, nbytes) != nbytes) {
/* Arghh!!!!!!! */
fprintf (stderr, "Read error on %s\\n", file);
exit (1);
}
if (write(Ofd, buf, nbytes) != nbytes) {
/* Geez, just can't win! */
fprintf (stderr, "Write error\\n");
exit (1);
}
}
/* Ok, we have everything positioned to grab the symbol table info
* out. So, what are ya waitin' fer...
*/
getsymb (ifd);
/* Last thing, bump the location counter */
locctr += header.f_csiz;
}
/* getsymb
*
* Here we get the symbol table info out of the file and deal with it. If
* a given symbol's address is already known we just make the patch. If the
* symbol was not defined but is by a particular symbol we patch all the
* addresses we have been saving up for just such an occasion. If it is
* just a reference then, alas, we save it up for christmas when all the
* little symbols come running home.
*
* RETURNS:
* nothing
*
*/
getsymb (ifd)
int ifd;
{
struct a_lst *tmp;
struct stab *ent;
struct symbol symb;
struct stab *lookup(), *insert(), *newent();
struct a_lst *build();
void splice();
void resolve();
extern void mseek();
/* Read in each entry until EOF */
while (read(ifd, &symb, sizeof(symb)) == sizeof(symb))
/* Has the symbol been resolved? */
if (!(symb.s_flags & TYRSLVD)) {
/* Ok, do we have it in the symbol table? */
if ((ent = lookup(symb.s_symnm)) == NULL) {
/* Do not have to deal with externel
* definitions here as it would mean a
* reference and not a resolution was declared
* externel. Which is, of course, IMPOSSIBLE!
*
* Ok, let us build it then..
*/
ent = newent (symb.s_symnm);
strncpy (ent->st_symnm, symb.s_symnm, IDENTSIZ);
ent->st_type = symb.s_flags;
/* Now, build a linked list of addresses that
* need to be patched and attach them to the
* symbol table entry.
*/
ent->en_lst = build (ifd, symb.s_naddr);
/* And, finally, enter it */
if (insert(ent) == NULL)
aabort ("Symbol table overflow!");
} else {
/* Is in symbol table */
tmp = build (ifd, symb.s_naddr);
splice (ent->en_lst, tmp);
if (ent->st_type & TYEXTID) {
/* Ok, resolve them now! */
resolve (ent->en_lst, ent->en_addr);
ent->en_lst = NULL; /* Chuck it! */
}
}
} else {
/* Is resolved */
tmp = build (ifd, symb.s_naddr);
resolve (tmp, symb.s_raddr + locctr);
/* Now then, is it externally declared? */
if (symb.s_flags & TYEXTID) {
/* Then we need to enter it into the table */
if ((ent = lookup(symb.s_symnm)) == NULL) {
ent = newent(symb.s_symnm);
strncpy (ent->st_symnm, symb.s_symnm,
IDENTSIZ);
if (insert(ent) == NULL)
aabort (
"Symbol table overflow!");
} else
if (ent->st_type & TYEXTID) {
fprintf (stderr,
"Symbol %s multiply defined\\n",
ent->st_symnm);
exit (1);
}
ent->en_addr = symb.s_raddr + locctr;
ent->st_type = symb.s_flags;
/* resolve the references we may have picked
* up from earlier
*/
if (ent->en_lst != NULL)
resolve (ent->en_lst, ent->en_addr);
}
}
/* Put Ofd back at EOF as those resolves could have left
* the file positioned ANYWHERE!
*/
mseek (Ofd, 0L, 2);
}
/* mseek
*
* Seek on a file. Do error checking and abort on same.
*
* RETURNS:
* nothing
*
*/
void mseek (fd, offset, whence)
int fd;
long offset;
int whence;
{
if (lseek(fd, offset, whence) < 0)
aabort ("Seek error");
}
/* mread
*
* Do a read. Check for error. Premature EOF is considered an error.
*
* RETURNS:
* nada
*
*/
mread (fd, buf, nbytes)
int fd;
char *buf;
int nbytes;
{
if (read(fd, buf, nbytes) == nbytes)
return;
fprintf (stderr, "Read error\\n");
exit (1);
}
struct a_lst *build (fd, naddr)
int fd;
short naddr;
{
short buf[30];
int x, rmnng, y, nwrds;
struct stab fakeit; /* adrinf wants a stab ent */
fakeit.en_lst = NULL;
for (x = 0; x < naddr; x += nwrds) {
rmnng = naddr - x;
nwrds = 30 / rmnng == 0 ? 30 : rmnng;
mread (fd, (char *)buf, rmnng * sizeof(short));
for (y = 0; y < nwrds; ++y)
/* Add the location counter and offset for header
* so we get the addresses right.
*/
adrinf (&fakeit,
buf[y] + locctr + sizeof(struct format));
}
return (fakeit.en_lst);
}
/* splice
*
* Take the two a_lsts and splice them into one. The second will be added
* onto the end of the second. I guess this is really a concatenation, huh?
* Oh well, the name is already this, so there!
*
* RETURNS:
* nothing
*/
void splice (l1, l2)
struct a_lst *l1, *l2;
{
struct a_lst *tmp;
for (tmp = l1; tmp->a_next != NULL; tmp = tmp->a_next)
;
tmp->a_next = l2;
}
/* resolve
*
* resolve a list of references to the given address.
* Throw the list away as we go through it. Leaves the fd pointed wherever
* it pleases.
*
* RETURNS:
* nothing
*
* NOTE: May abort on a seek or write error
*/
void resolve (lst, addr)
struct a_lst *lst;
short addr;
{
struct a_lst *tmp;
addr += laddr;
while (lst) {
mseek(Ofd, (long )lst->a_addr, 0);
if (write (Ofd, &addr, sizeof(addr)) != sizeof(addr))
aabort ("Write error on resolve");
tmp = lst->a_next;
free (lst);
lst = tmp;
}
}
//*FUNKYSTUFF*//
echo extracting aabort.c
cat << //*FUNKYSTUFF*// > aabort.c
#include <stdio.h>
#include "TIasm.h"
extern flag Debug;
/* aabort
* An error internal to the assembler has been discovered. abort processing.
* print a short but cryptic message intended for maintainers.
*
* Does NOT return
*/
void aabort (string)
char *string;
{
fflush (stdout);
fprintf (stderr, "Internal error: %s\\n", string);
fflush (stderr);
exit (1);
}
//*FUNKYSTUFF*//
echo extracting adrinf.c
cat << //*FUNKYSTUFF*// > adrinf.c
#include "TIasm.h"
#include <stdio.h>
/* adrinf
*
* Add an address to be relocated in to the list in the symbol table entry
* reserved for just such a purpose.
*
* RETURNS:
* nothing
*
* NOTE: May abort if the malloc fails.
*/
void adrinf (stab, loc)
struct stab *stab;
short loc;
{
struct a_lst *ainfo;
extern char *malloc();
if ((ainfo = (struct a_lst *)malloc(sizeof(struct a_lst))) == NULL)
aabort ("adrinf: no mem!");
ainfo->a_addr = loc;
ainfo->a_next = stab->en_lst;
stab->en_lst = ainfo;
}
//*FUNKYSTUFF*//
echo extracting filutil.c
cat << //*FUNKYSTUFF*// > filutil.c
/* File utilities, open and close */
#include <stdio.h>
#include <sys/param.h>
/* For mapping purposes */
FILE *Sdvec[NOFILE];
/* xopen
* Open a file buffered but make it look like the UNIX "open" sys call.
*
* returns:
* fd for a successful open.
* -1 for a failure
*/
int xopen (file, mode)
char *file;
int mode;
{
char *md;
int fd;
extern FILE *fdopen();
switch (mode) {
case 0: /* read */
md = "r";
break;
case 1: /* write */
md = "w";
break;
case 2: /* read & write */
md = "r+";
break;
default:
return (-1);
}
if (file == NULL || (fd = open(file, mode) < 0))
return (-1);
if ((Sdvec[fd] = fdopen(fd, md)) == NULL) {
close (fd);
return (-1);
}
return (fd);
}
/* xclose
* close a file
*
* returns:
* 0 if succesful
* -1 for error
*/
int xclose (fd)
int fd;
{
if (fd < 0 || fd >= NOFILE)
return (-1);
if (fclose (Sdvec[fd]) == EOF)
return (-1);
Sdvec[fd] = NULL;
return (0);
}
/* xcreat
* create a file
*
* returns:
* fildes for success
* -1 on error
*/
int xcreat (file, modes)
char *file;
int modes;
{
int fd;
FILE *fdopen();
if (file == NULL || (fd = creat(file, modes)) < 0)
return (-1);
if ((Sdvec[fd] = fdopen(fd, "w+")) == NULL)
return (-1);
return (fd);
}
//*FUNKYSTUFF*//
echo extracting hash.c
cat << //*FUNKYSTUFF*// > hash.c
#include "TIasm.h"
#include <stdio.h>
extern int Debug;
struct stab *Symtab[SYMVECSIZ];
/* initab
* Init the hash table.
*
* Returns:
* Nothing.
*/
void initab()
{
register struct stab **tptr;
register int x;
tptr = Symtab;
for (x = 0; x < SYMVECSIZ; ++x)
*tptr++ = NULL;
}
/* hash
* return a hash key based on the symbol.
*/
int hash (symbol)
register char *symbol;
{
register int ac = 0; /* Accumulator */
register int x;
for (x = 0; x < IDENTSIZ && *symbol != NULL; ++x) {
DEBUG (200, "hash: adding %d to ", (int )*symbol);
DEBUG (200, "accumulator which is %d\\n", ac);
ac += (int )*symbol++;
}
DEBUG (200, "hash: returning %d\\n", ac % SYMVECSIZ);
return (ac % SYMVECSIZ);
}
/* lookup
* Look up a symbol in the symbol table.
*
* Returns:
* pointer to entry if succesful.
* NULL if not found.
*/
struct stab *lookup(symbol)
char *symbol;
{
struct stab *entry;
DEBUG (100, "lookup: symbol is \\"%s\\"\\n", symbol);
DEBUG (100, "lookup: hashcode = %d\\n", hash(symbol));
if ((entry = Symtab[hash(symbol)]) == NULL)
return (NULL); /* The vector was empty */
do
if (strcmp(symbol, entry->st_symnm) == 0)
return (entry);
while ((entry = entry->st_next) != NULL);
return (NULL); /* Doesn't exist */
}
/* insert
* Insert a symbol table entry into the symbol table.
*
* Returns:
* The entry inserted.
*
* NOTE: The return here is fairly redundant as this CANNOT fail. But,
* should a quadratic hashing scheme ever be implemented the fail here is
* possible. So, for the sake of modularity, I include the redundant return.
* A fail would be signified by a NULL return.
*/
struct stab *insert(entry)
struct stab *entry;
{
struct stab *list, *eolist;
int key;
DEBUG (100, "insert: Inserting \\"%s\\" to vector", entry->st_symnm);
DEBUG (100, " %d\\n", hash(entry->st_symnm));
if ((list = Symtab[(key = hash(entry->st_symnm))]) == NULL) {
/* vector was empty */
Symtab[key] = entry;
return (entry);
}
/* Find the end of the list */
do {
eolist = list;
list = list->st_next;
} while (list != NULL);
/* Do the actual insert */
eolist->st_next = entry;
return (entry);
}
/* newent
* This routine creates and initializes to NULL's a symbol table entry.
*
* Returns:
* NULL on error (malloc failed)
* pointer to an initialized entry on success
*/
struct stab *newent()
{
extern char *calloc();
return ((struct stab *)calloc(1, sizeof(struct stab)));
}
/* The following routines and global variables are for use when dumping
* the symbol table.
*/
static int vec; /* Which vector we are currently on */
static struct stab *stent; /* Which entry we are on */
/* sstab
*
* Set up to dump the table. Zero the globals.
*
* RETURNS:
* nothing
*/
void sstab ()
{
vec = 0;
while (vec < SYMVECSIZ && Symtab[vec] == NULL)
++vec;
stent = Symtab[vec];
}
/* nxtent
*
* Return the next entry in the table. Does not return reserved words or
* directives.
*
* RETURNS:
* A symbol table entry on success
* NULL if the table is empty
*/
struct stab *nxtent ()
{
struct stab *tmp;
while (vec < SYMVECSIZ) {
while (stent != NULL) {
if (!(stent->st_type & TYRSRVD ||
stent->st_type & TYDIR)) {
tmp = stent;
stent = stent->st_next;
return (tmp);
}
stent = stent->st_next;
}
++vec;
stent = Symtab[vec];
}
/* Oops, all done */
return (NULL);
}
//*FUNKYSTUFF*//
echo extracting lex.lex
cat << //*FUNKYSTUFF*// > lex.lex
%{
#include "TIasm.h"
#include "y.tab.h"
extern int Lincnt;
extern int Debug;
extern flag Ferror;
extern flag Error;
extern struct stab *lookup(), *newsym();
extern void aabort();
%}
%%
\\"[^\\"\\n]* {
/* Special operators in string possibly */
if (yytext[yyleng - 1] == '\\\\')
yymore();
else {
if ((yytext[yyleng++] = input()) == '\\n')
unput(yytext[--yyleng]);
yytext[yyleng++] = NULL;
}
DEBUG (11, "Lex finds string \\"%s\\"\\n", yytext);
return (STRING);
}
[\\t ]* /* Eat white space. This goes after the string stuff so
* we don't eat white space inside the string.
*/
;
"\\n" ++Lincnt;
[rR][0-9]+ {
DEBUG (11, "lex finds register \\"%s\\"\\n", yytext);
switch (atoi(&yytext[1])) {
case 0:
yylval.val = 0;
return (REG);
/* NOTREACHED */
break;
case 1:
yylval.val = 1;
return (REG);
/* NOTREACHED */
break;
case 2:
yylval.val = 2;
return (REG);
/* NOTREACHED */
break;
case 3:
yylval.val = 3;
return (REG);
/* NOTREACHED */
break;
case 4:
yylval.val = 4;
return (REG);
/* NOTREACHED */
break;
case 5:
yylval.val = 5;
return (REG);
/* NOTREACHED */
break;
case 6:
yylval.val = 6;
return (REG);
/* NOTREACHED */
break;
case 7:
yylval.val = 7;
return (REG);
/* NOTREACHED */
break;
case 8:
yylval.val = 8;
return (REG);
/* NOTREACHED */
break;
case 9:
yylval.val = 9;
return (REG);
/* NOTREACHED */
break;
case 10:
yylval.val = 10;
return (REG);
/* NOTREACHED */
break;
case 11:
yylval.val = 11;
return (REG);
/* NOTREACHED */
break;
case 12:
yylval.val = 12;
return (REG);
/* NOTREACHED */
break;
case 13:
yylval.val = 13;
return (REG);
/* NOTREACHED */
break;
case 14:
yylval.val = 14;
return (REG);
/* NOTREACHED */
break;
case 15:
yylval.val = 15;
return (REG);
/* NOTREACHED */
break;
default:
/* It isn't a register. Try something else. */
REJECT;
break;
}
};
[+\\-]0[xX][0-9a-fA-F]+ {
yylval.val = getnum(yytext);
DEBUG (11, "lex: +/- hexnum = %d\\n", yylval.val);
if (Error == TRUE) {
DEBUG (12, "lex: error for +/- hexnum \\"%s\\"\\n", yytext);
return (ERROR); /* Will cause syntax error */
}
return (NUMBER);
}
0[xX][0-9a-fA-F]+ {
yylval.val = getnum(yytext);
DEBUG (11, "lex: hexnum = %d\\n", yylval.val);
if (Error == TRUE) {
DEBUG (12, "lex: error for hexnum \\"%s\\"\\n", yytext);
return (ERROR); /* Will cause syntax error */
}
return (NUMBER);
}
[+\\-]0[oO][0-7]+ {
yylval.val = getnum(yytext);
DEBUG (11, "lex: +/- octnum = %d\\n", yylval.val);
if (Error == TRUE) {
DEBUG (12, "lex: error for +/- octnum\\"%s\\"\\n", yytext);
return (ERROR); /* Will cause syntax error */
}
return (NUMBER);
}
0[oO][0-7]+ {
yylval.val = getnum(yytext);
DEBUG (11, "lex: octnum = %d\\n", yylval.val);
if (Error == TRUE) {
DEBUG (12, "lex: error for octnum \\"%s\\"\\n", yytext);
return (ERROR); /* Will cause syntax error */
}
return (NUMBER);
}
[+\\-]0[bB][01]+ {
yylval.val = getnum(yytext);
DEBUG (11, "lex: +/- binnum = %d\\n", yylval.val);
if (Error == TRUE) {
DEBUG (12, "lex: error for +/- binnum\\"%s\\"\\n", yytext);
return (ERROR); /* Will cause syntax error */
}
return (NUMBER);
}
0[bB][01]+ {
yylval.val = getnum(yytext);
DEBUG (11, "lex: binnum = %d\\n", yylval.val);
if (Error == TRUE) {
DEBUG (12, "lex: error for binnum \\"%s\\"\\n", yytext);
return (ERROR); /* Will cause syntax error */
}
return (NUMBER);
}
[+\\-][dD][0-9]+ {
yylval.val = getnum(yytext);
DEBUG (11, "lex: +/- decnum = %d\\n", yylval.val);
if (Error == TRUE) {
DEBUG (12, "lex: err for +/- decnum \\"%s\\"\\n", yytext);
return (ERROR); /* Will cause syntax error */
}
return (NUMBER);
}
[dD][0-9]+ {
yylval.val = getnum(yytext);
DEBUG (11, "lex: decnum = %d\\n", yylval.val);
if (Error == TRUE) {
DEBUG (12, "lex: error for decnum \\"%s\\"\\n", yytext);
return (ERROR); /* Will cause syntax error */
}
return (NUMBER);
}
[0-9]+ {
yylval.val = getnum(yytext);
DEBUG (11, "lex: undcl num = %d\\n", yylval.val);
if (Error == TRUE) {
DEBUG (12, "lex: error for undcl num\\"%s\\"\\n", yytext);
return (ERROR); /* Will cause syntax error */
}
return (NUMBER);
}
[+\\-][0-9]+ {
yylval.val = getnum(yytext);
DEBUG (11, "lex: +/- undcl num = %d\\n", yylval.val);
if (Error == TRUE) {
DEBUG (12, "lex: error for +/- undcl \\"%s\\"\\n", yytext);
return (ERROR); /* Will cause syntax error */
}
return (NUMBER);
}
";" {
/* Eat comments */
while (input() != '\\n')
;
unput ('\\n');
};
"'"."'" {
yylval.val = (short )yytext[1];
return (NUMBER);
};
[+-]"'"."'" {
yylval.val = (short )yytext[2];
if (yytext[0] == '-')
/* Make negative in that case */
yylval.val *= -1;
return (NUMBER);
};
"."[_a-zA-Z][\\-_a-zA-Z0-9]* {
struct stab *Entry;
DEBUG (11, "lex: directive ===== \\"%s\\"\\n", yytext);
if ((Entry = lookup(yytext)) == NULL) {
/* No such directive */
DEBUG (12, "lex: No directive \\"%s\\"\\n", yytext);
return (ERROR);
}
return (Entry->st_opc);
}
[_a-zA-Z][\\-_a-zA-Z0-9]* {
extern struct stab *lookup();
if ((yylval.sinfo.pntr = lookup(yytext)) == NULL) {
/* Create the symbol table entry for this ident */
yylval.sinfo.pntr = newsym (yytext);
yylval.sinfo.pntr->st_type = TYLCLID;
yylval.sinfo.enterd = FALSE;
DEBUG (11, "lex creates \\"%s\\"\\n", yytext);
return (IDENT);
} else {
if (yylval.sinfo.pntr->st_type & TYRSRVD) {
/* This is a reserved word. Return the format */
DEBUG (11, "lex returns RSRVD fmt = %d\\n",
yylval.sinfo.pntr->st_fmt);
return (yylval.sinfo.pntr->st_fmt);
}
if (yylval.sinfo.pntr->st_type & TYLCLID
|| yylval.sinfo.pntr->st_type & TYEXTID) {
DEBUG (11, "lex returns LCL or EXTNL IDENT\\n",
NULL);
yylval.sinfo.enterd = TRUE;
return (IDENT);
}
DEBUG (11, "ERR: stab, name = \\"%s\\"\\n",
yylval.sinfo.pntr->st_symnm);
DEBUG (11, "ERR: stab, type = 0o%o\\n",
yylval.sinfo.pntr->st_type);
aabort ("lex: Null stab ent");
}
};
\\, { return (','); }
\\: { return (':'); }
\\( { return ('('); }
\\) { return (')'); }
\\[ { return ('['); }
\\] { return (']'); }
\\+ { return ('+'); }
. { return (ERROR); }
%%
//*FUNKYSTUFF*//
echo extracting main.c
cat << //*FUNKYSTUFF*// > main.c
#include "TIasm.h"
#include <stdio.h>
#include "mio.h"
/* Globals */
flag Ferror; /* To flag an error in assembly */
int Lincnt = 1; /* To count the lines in the source */
struct stab *Entry; /* Current symbol table entry */
int Debug; /* debug flag */
int Ofd; /* Object file descriptor */
char objtfl[40]; /* Temp file for object */
extern short lcctr; /* The (re)location counter */
main(argc, argv)
int argc;
char *argv[];
{
char *tmp;
int x;
int fcnt = 0;
int fd;
char *outfil;
struct format header;
struct stab *ent;
struct symbol symb;
struct a_lst *atmp;
extern void resrv();
extern yydebug;
extern debug;
extern struct stab *nxtent();
extern Sdvec[];
argv[argc] = NULL;
umask (0111); /* No execute bit set */
/* Parse switches */
for (x = 1; x < argc - 1; ++x)
if (*(tmp = argv[x]) != '-')
/* Should have been handled by the front end */
aabort ("Non-switch");
else {
++tmp;
while (*tmp != NULL)
switch (*tmp++) {
case 'd':
++x;
Debug = atoi(argv[x]);
break;
case 'o':
++x;
outfil = argv[x];
break;
default:
aabort ("Unrecognized switch\\n");
}
}
if ((Ofd = xcreat(outfil, 0777)) < 0)
aabort ("Cannot create output file");
xwrite (Ofd, header, sizeof(header));
resrv();
Ferror = FALSE;
yyparse();
/* Put the header together */
header.f_csiz = lcctr;
header.f_magic = OMAGIC;
xseek (Ofd, 0L, 0);
xwrite (Ofd, header, sizeof(header));
xseek (Ofd, 0L, 2);
/* Write out the symbol table info */
sstab();
while ((ent = nxtent()) != NULL) {
for (x = 0, atmp = ent->en_lst; atmp != NULL;
atmp = atmp->a_next)
++x;
if (x == 0)
continue;
/* if (ent->st_type & TYEXTID)
x *= -1;
*/
strncpy (symb.s_symnm, ent->st_symnm, IDENTSIZ);
symb.s_flags = ent->st_type;
symb.s_raddr = ent->en_addr;
/* Cheaper to count */
symb.s_naddr = (short )x;
xwrite (Ofd, symb, sizeof(symb));
for (atmp = ent->en_lst; atmp != NULL; atmp = atmp->a_next) {
DEBUG (10, "\\"%s\\" ref'd at ", symb.s_symnm);
DEBUG (10, "0x%x\\n", atmp->a_addr);
xwrite (Ofd, atmp->a_addr, sizeof(atmp->a_addr));
}
}
}
//*FUNKYSTUFF*//
echo extracting parse.y
cat << //*FUNKYSTUFF*// > parse.y
%start list
%{
#include "TIasm.h"
#include <stdio.h>
#include "mio.h"
short isbuf; /* A place to build object */
short lcctr = 0; /* The relocation counter */
extern int Ofd; /* The object file */
extern FILE *Sdvec[]; /* For doing our funny I/O */
extern char yytext[];
extern int yyleng;
extern flag Ferror;
extern flag Error;
extern int Debug;
%}
%union {
short val; /* Any old integer */
struct p { /* Pointer to a stab ent */
struct stab *pntr;
flag enterd;
} sinfo;
struct infop opspec; /* Operand spec info */
}
%token <sinfo> OPTYP1 1
%token <sinfo> OPTYP2 2
%token <sinfo> OPTYP3 3
%token <sinfo> OPTYP4 4
%token <sinfo> OPTYP5 5
%token <sinfo> OPTYP6 6
%token <sinfo> OPTYP7 7
%token <sinfo> OPTYP8 8
%token <sinfo> OPTYP9 9
%token <sinfo> OPTYP10 10
%token <sinfo> OPTYP11 11
%token <val> STRINGDIR
%token <val> EXTNLDIR
%token <val> WORDDIR
%token <val> DATADIR
%token <val> REG
%token <sinfo> IDENT
%token <val> STRING
%token <val> NUMBER
%token <val> ERROR
%type <opspec> mopnd
%type <val> pcrel
%type <val> indir
%type <val> iauto
%type <opspec> symbol
%type <opspec> isymb
%type <sinfo> ident
%%
list : /* EMPTY */
{
DEBUG (10, "list -> EMPTY\\n", NULL);
DEBUG (10, "lcctr = 0X%x\\n", lcctr);
}
| list line
{
DEBUG (10, "list -> list line\\n", NULL);
DEBUG (10, "lcctr = 0X%x\\n", lcctr);
}
| error
{
DEBUG (10, "list -> error\\n", NULL);
DEBUG (10, "lcctr = 0X%x\\n", lcctr);
}
;
line : ident ':'
{
struct j_lst *tptr, *t2ptr;
unsigned tmp;
DEBUG (10, "line -> ident ':'\\n", NULL);
/* The ONLY place an address may be resolved is here */
if (\$1.pntr->st_type & TYRSLVD) {
yyerror ("Redeclaration error");
YYERROR;
}
\$1.pntr->st_type |= TYRSLVD;
\$1.pntr->en_addr = lcctr;
DEBUG (9, "Resolving \\"%s\\"", \$1.pntr->st_symnm);
DEBUG (9, " to addr 0X%x\\n", \$1.pntr->en_addr);
/* Now resolve jumps and make these patches */
for (tptr = \$1.pntr->en_jl; tptr != NULL; ) {
DEBUG (9, "Resolving jumps, addr = 0x%x\\n",
tptr->j_addr);
DEBUG (9, "0x%x - ", lcctr);
DEBUG (9, "0x%x / 2 = ", tptr->j_addr);
DEBUG (9, "0x%x\\n", (lcctr - tptr->j_addr) / 2);
/* We KNOW this is a forward reference so
* we can just make the following subtraction.
*/
if ((tmp = (lcctr - tptr->j_addr) / 2) > 0x7f) {
yyerror ("Jump target out of range");
} else {
/* Offset size of execute header */
xseek (Ofd, (long )tptr->j_addr
+ sizeof(struct format) - 1, 0);
xwrite (Ofd, tmp, 1);
xseek (Ofd, (long )0, 2);
}
t2ptr = tptr;
tptr = tptr->j_next;
rmjinf (t2ptr);
}
/* It is possible to trip through the above loop
* again. So......
*/
\$1.pntr->en_jl = NULL;
}
| stmnt
{
DEBUG (10, "line -> stmnt\\n", NULL);
}
;
stmnt : OPTYP1 mopnd ',' mopnd
{
DEBUG (10, "stmnt -> OPTYP1 mopnd ',' mopnd\\n", NULL);
isbuf = \$1.pntr->st_opc;
/* Source */
isbuf |= ((0x3 & \$2.t) << 4);
isbuf |= (0xf & \$2.r);
/* Destination */
isbuf |= ((0x3 & \$4.t) << 10);
isbuf |= ((0xf & \$4.r) << 6);
lcctr += sizeof(isbuf);
xwrite (Ofd, isbuf, sizeof(isbuf));
if (\$2.in_tag & SYMTAG) {
if (\$2.in_tag & RELOCATABLE)
adrinf(\$2.in_stb, lcctr);
lcctr += sizeof(\$2.in_loc);
xwrite (Ofd, \$2.in_loc, sizeof(\$2.in_loc));
} if (\$4.in_tag & SYMTAG) {
if (\$4.in_tag & RELOCATABLE)
adrinf(\$4.in_stb, lcctr);
lcctr += sizeof(\$4.in_loc);
xwrite (Ofd, \$4.in_loc, sizeof(\$4.in_loc));
}
}
| OPTYP2 pcrel
{
DEBUG (10, "fmt2 -> OPTYP2 pcrel\\n", NULL);
isbuf = \$1.pntr->st_opc;
isbuf |= (0xff & \$2);
lcctr += sizeof(isbuf);
xwrite (Ofd, isbuf, sizeof(isbuf));
}
| OPTYP2 symbol
{
int tmp;
DEBUG (10, "fmt2 -> OPTYP2 symbol\\n", NULL);
isbuf = \$1.pntr->st_opc;
if (\$2.in_stb->st_type & TYRSLVD) {
DEBUG (9, "fmt2: Label resolved do jump now\\n",
NULL);
/* This reference is definately rearward
* so the following is legal.
*/
tmp = (\$2.in_stb->en_addr - lcctr - 2) / 2;
if ( tmp < -0x7f) {
yyerror ("Jump target out of range");
YYERROR;
} else
isbuf |= (0xff & (unsigned )tmp);
} else {
DEBUG (9, "fmt2: Not resolved, save addr\\n",
NULL);
adjinf (\$2.in_stb, lcctr + 1);
}
lcctr += sizeof(isbuf);
xwrite (Ofd, isbuf, sizeof(isbuf));
}
| OPTYP3 mopnd ',' REG
{
DEBUG (10, "fmt3 -> OPTYP3 mopnd ',' REG\\n", NULL);
isbuf = \$1.pntr->st_opc;
/* source */
isbuf |= ((0x3 & \$2.t) << 4);
isbuf |= (0xf & \$2.r);
/* Destination register */
isbuf |= ((0xf & \$4) << 6);
lcctr += sizeof(isbuf);
xwrite (Ofd, isbuf, sizeof(isbuf));
if (\$2.in_tag & SYMTAG) {
if (\$2.in_tag & RELOCATABLE)
adrinf(\$2.in_stb, lcctr);
lcctr += sizeof(\$2.in_loc);
xwrite (Ofd, \$2.in_loc, sizeof(\$2.in_loc));
}
}
| OPTYP4 mopnd ',' NUMBER
{
DEBUG (10, "fmt4 -> OPTYP4 mopnd ',' NUMBER\\n", NULL);
isbuf = \$1.pntr->st_opc;
/* Register */
isbuf |= ((0x3 & \$2.t) << 4);
isbuf |= (0xf & \$2.r);
/* count */
if (\$4 < 0) {
yyerror("transfer/shift count < 0");
YYERROR;
}
if (\$4 > 0xf) {
yyerror ("transfer/shift count > 0xf");
YYERROR;
}
isbuf |= ((0xf & \$4) << 6);
lcctr += sizeof(isbuf);
xwrite (Ofd, isbuf, sizeof(isbuf));
if (\$2.in_tag & SYMTAG) {
if (\$2.in_tag & RELOCATABLE)
adrinf(\$2.in_stb, lcctr);
lcctr += sizeof(\$2.in_loc);
xwrite (Ofd, \$2.in_loc, sizeof(\$2.in_loc));
}
}
| OPTYP5 REG ',' NUMBER
{
DEBUG (10, "fmt5 -> OPTYP5 REG ',' NUMBER\\n", NULL);
isbuf = \$1.pntr->st_opc;
/* register */
isbuf |= (0xf & \$2);
/* Count/shift */
if (\$4 < 0) {
yyerror("transfer/shift count < 0");
YYERROR;
}
if (\$4 > 0xf) {
yyerror("transfer/shift count > 0xf");
YYERROR;
}
isbuf |= ((0xf & \$4) << 4);
lcctr += sizeof(isbuf);
xwrite (Ofd, isbuf, sizeof(isbuf));
}
| OPTYP6 mopnd
{
DEBUG (10, "fmt6 -> OPTYP6 mopnd\\n", NULL);
isbuf = \$1.pntr->st_opc;
/* Source */
isbuf |= ((0x3 & \$2.t) << 4);
isbuf |= (0xf & \$2.r);
lcctr += sizeof(isbuf);
xwrite (Ofd, isbuf, sizeof(isbuf));
if (\$2.in_tag & SYMTAG) {
if (\$2.in_tag & RELOCATABLE)
adrinf (\$2.in_stb, lcctr);
lcctr += sizeof(\$2.in_loc);
xwrite (Ofd, \$2.in_loc, sizeof(\$2.in_loc));
}
}
| OPTYP7
{
DEBUG (10, "fmt7 -> OPTYP7\\n", NULL);
isbuf = \$1.pntr->st_opc;
lcctr += sizeof(isbuf);
xwrite (Ofd, isbuf, sizeof(isbuf));
}
| OPTYP8 REG ',' symbol
{
DEBUG (10, "fmt8 -> OPTYP8 REG ',' symbol\\n", NULL);
isbuf = \$1.pntr->st_opc;
/* Destination */
isbuf |= (0xf & \$2);
lcctr += sizeof(isbuf);
xwrite (Ofd, isbuf, sizeof(isbuf));
/* Source */
if (\$4.in_tag & RELOCATABLE)
adrinf (\$4.in_stb, lcctr);
lcctr += sizeof(\$4.in_loc);
xwrite (Ofd, \$4.in_loc, sizeof(\$4.in_loc));
}
| OPTYP9 mopnd ',' NUMBER
{
DEBUG (10, "OPTYP9 mopnd ',' NUM (%d)\\n", \$4);
isbuf = \$1.pntr->st_opc;
/* Destination register */
isbuf |= ((0xf & \$4) << 6);
/* Source */
isbuf |= ((0x3 & \$2.t) << 4);
isbuf |= (0xf & \$2.r);
lcctr += sizeof(isbuf);
xwrite (Ofd, isbuf, sizeof(isbuf));
if (\$2.in_tag & SYMTAG) {
if (\$2.in_tag & RELOCATABLE)
/* Enter it to the list of addrs.
* So, there is garbage in the slot;
* We need to reserve space for the
* patch anyway. Who cares what is in
* there?
*/
adrinf(\$2.in_stb, lcctr);
lcctr += sizeof(\$2.in_loc);
xwrite (Ofd, \$2.in_loc, sizeof(\$2.in_loc));
}
}
| OPTYP10 symbol
{
DEBUG (10, "stmnt -> OPTYP10\\n", NULL);
isbuf = \$1.pntr->st_opc;
lcctr += sizeof(isbuf);
xwrite (Ofd, isbuf, sizeof(isbuf));
if (\$2.in_tag & RELOCATABLE)
adrinf (\$2.in_stb, lcctr);
lcctr += sizeof(\$2.in_loc);
xwrite (Ofd, \$2.in_loc, sizeof(\$2.in_loc));
}
| OPTYP11 REG
{
DEBUG (10, "stmnt -> OPTYP11\\n", NULL);
isbuf = \$1.pntr->st_opc;
isbuf |= (0xf & \$2);
lcctr += sizeof(isbuf);
xwrite (Ofd, isbuf, sizeof(isbuf));
}
| dirctv
{
DEBUG (10, "stmnt -> dirctv\\n", NULL);
}
;
dirctv : STRINGDIR STRING
{
char null = NULL; /* Will want address, so.... */
DEBUG (10, "dirctv -> STRINGDIR STRING\\n", NULL);
dostr (yytext, &yyleng);
if (Error == TRUE) {
yyerror ("Illegal meta-character(s) in string");
YYERROR;
}
lcctr += yyleng;
/* The I/O macros force this..... BE CAREFUL if
* you change them!
*/
xwrite (Ofd, yytext[0], yyleng);
/* If odd length, then align */
if (odd(yyleng)) {
lcctr += 1;
xwrite (Ofd, null, 1);
}
}
| EXTNLDIR ident
{
DEBUG (10, "dirctv -> EXTNLDIR ident\\n", NULL);
\$2.pntr->st_type |= TYEXTID;
}
| WORDDIR NUMBER
{
short awrd;
short x;
DEBUG (10, "dirctv -> WORDDIR number\\n", NULL);
lcctr += \$2 * 2;
for (x = 0; x < \$2; ++x)
xwrite (Ofd, awrd, sizeof(awrd));
}
| WORDDIR
{
short awrd;
DEBUG (10, "dirctv -> WORDDIR\\n", NULL);
lcctr += 2;
xwrite (Ofd, awrd, sizeof(awrd));
}
| DATADIR symbol
{
DEBUG (10, "dirctv -> DATADIR symbol\\n", NULL);
xwrite (Ofd, \$2.in_loc, sizeof(\$2.in_loc));
if (\$2.in_tag & RELOCATABLE)
adrinf (\$2.in_stb, lcctr);
lcctr += 2;
}
;
mopnd : REG
{
DEBUG (10, "mopnd -> REG\\n", NULL);
\$$.t = 0;
\$$.r = \$1;
\$$.in_tag &= ~SYMTAG; /* Paranoid */
}
| iauto
{
DEBUG (10, "mopnd -> iauto\\n", NULL);
\$$.t = 03;
\$$.r = \$1;
\$$.in_tag &= ~SYMTAG; /* Paranoid */
}
| isymb
{
DEBUG (10, "mopnd -> isymb\\n", NULL);
\$$ = \$1;
\$$.t = 02;
/* Register to index off of is already set */
}
| symbol
{
DEBUG (10, "mopnd -> symbol\\n", NULL);
\$$ = \$1;
\$$.t = 02;
\$$.r = 0; /* Force non-indexed */
}
| indir
{
DEBUG (10, "mopnd -> indir\\n", NULL);
\$$.t = 01;
\$$.r = \$1;
\$$.in_tag &= ~SYMTAG; /* Paranoid */
}
;
pcrel : '\$'
{
DEBUG (10, "pcrel -> '\$'\\n", NULL);
\$$ = lcctr;
}
| '\$' '+' NUMBER
{
DEBUG (10, "pcrel -> '\$' '+' NUMBER\\n", NULL);
\$$ = lcctr + \$3;
/* Check signed 8 bit jump range */
if (abs(\$$) > 0x7f) {
yyerror ("Jump target out of range");
YYERROR;
}
}
| '\$' '-' NUMBER
{
DEBUG (10, "pcrel -> '\$' '-' NUMBER\\n", NULL);
\$$ = lcctr - \$3;
/* Check signed 8 bit jump range */
if (abs(\$$) > 0xff) {
yyerror ("Jump out of range");
YYERROR;
}
}
;
indir : '(' REG ')'
{
DEBUG (10, "indir -> '(' REG ')'\\n", NULL);
\$$ = \$2;
}
;
iauto : '(' REG ')' '+'
{
DEBUG (10, "iauto -> '(' REG ')' '+'\\n", NULL);
\$$ = \$2;
}
;
isymb : symbol '[' REG ']'
{
DEBUG (10, "isymb -> symbol '[' REG ']'\\n", NULL);
/* The identifier/absolute address */
\$$ = \$1;
\$$.r = \$3; /* Change this field to reflect indexed */
}
;
symbol : ident
{
DEBUG (10, "symbol -> ident\\n", NULL);
/* The identifier is entered into the relocation
* table already.
*/
\$$.in_tag = SYMTAG | RELOCATABLE;
\$$.in_stb = \$1.pntr;
}
| NUMBER
{
DEBUG (10, "symbol -> NUMBER\\n", NULL);
/* An absolute address */
\$$.in_tag |= SYMTAG & ~RELOCATABLE;
\$$.in_loc = \$1;
}
;
ident : IDENT
{
/* This way so that we can enter it into the
* relocation table here
*/
extern struct stab *insert();
DEBUG (10, "ident -> IDENT; name = %s\\n",
\$1.pntr->st_symnm);
if (\$1.enterd != TRUE) {
/* Mark it as entered */
\$1.enterd = TRUE;
/* And, enter it */
if (insert(\$1.pntr) == NULL)
aabort ("Symbol table overflow\\n");
}
\$$ = \$1;
}
;
%%
/* yyerror
* The assemblers error reporting, flagging, clearing routine.
*
* Returns:
* Nothing, though for consistency it must be declared int
*/
int yyerror (string)
char *string;
{
char c;
extern flag Ferror;
extern int Lincnt;
fprintf (stderr, "%d: %s\\n", Lincnt, string);
/*
while ((c = input()) != '\\n' && c != 0)
;
unput(c);
*/
Ferror = TRUE;
}
//*FUNKYSTUFF*//
echo extracting rsrvd.c
cat << //*FUNKYSTUFF*// > rsrvd.c
#include "TIasm.h"
#include "opcodes.h"
#include "y.tab.h"
#include <stdio.h>
/* Actual opcodes for the machine */
struct ops Optab[] = {
"LI", LI, 8,
"AI", AI, 8,
"ANDI", ANDI, 8,
"ORI", ORI, 8,
"CI", CI, 8,
"STWP", STWP, 11,
"STST", STST, 11,
"LWPI", LWPI, 10,
"LIMI", LIMI, 10,
"IDLE", IDLE, 7,
"RSET", RSET, 7,
"RTWP", RTWP, 7,
"CKON", CKON, 7,
"CKOF", CKOF, 7,
"LREX", LREX, 7,
"BLWP", BLWP, 6,
"B", B, 6,
"X", X, 6,
"CLR", CLR, 6,
"NEG", NEG, 6,
"INV", INV, 6,
"INC", INC, 6,
"INCT", INCT, 6,
"DEC", DEC, 6,
"DECT", DECT, 6,
"BL", BL, 6,
"SWPB", SWPB, 6,
"SETO", SETO, 6,
"ABS", ABS, 6,
"SRA", SRA, 5,
"SRL", SRL, 5,
"SLA", SLA, 5,
"SRC", SRC, 5,
"JMP", JMP, 2,
"JLT", JLT, 2,
"JLE", JLE, 2,
"JEQ", JEQ, 2,
"JHE", JHE, 2,
"JGT", JGT, 2,
"JNE", JNE, 2,
"JNC", JNC, 2,
"JOC", JOC, 2,
"JNO", JNO, 2,
"JL", JL, 2,
"JH", JH, 2,
"JOP", JOP, 2,
"SBO", SBO, 2,
"SBZ", SBZ, 2,
"TB", TB, 2,
"COC", COC, 3,
"CZC", CZC, 3,
"XOR", XOR, 3,
"LDCR", LDCR, 4,
"STCR", STCR, 4,
"MPY", MPY, 3,
"DIV", DIV, 3,
"SZC", SZC, 1,
"SZCB", SZCB, 1,
"S", S, 1,
"SB", SB, 1,
"C", C, 1,
"CB", CB, 1,
"A", A, 1,
"AB", AB, 1,
"MOV", MOV, 1,
"MOVB", MOVB, 1,
"SOC", SOC, 1,
"SOCB", SOCB, 1,
"XOP", XOP, 9,
NULL, 0, 0,
};
/* Directives */
struct ops Dirtab[] = {
".str", STRINGDIR, STRINGDIR,
".extern", EXTNLDIR, EXTNLDIR,
".word", WORDDIR, WORDDIR,
".data", DATADIR, DATADIR,
NULL, 0, 0,
};
//*FUNKYSTUFF*//
echo extracting tiasm.c
cat << //*FUNKYSTUFF*// > tiasm.c
#include <stdio.h>
#include "TIasm.h"
int Debug;
main (argc,argv)
int argc;
char *argv[];
{
char **avec, *arg;
FILE *isd, *psd;
int x, filcnt = 0;
char *tmp, *fpart;
char c;
char cbuf[BUFSIZ], swbuf[BUFSIZ], *fvec[BUFSIZ];
char *rindex();
FILE *popen();
flag skippit = FALSE;
avec = &argv[1];
while (*avec != NULL)
if (**avec != '-')
fvec[filcnt++] = *avec++;
else {
arg = *avec++;
while (*++arg != NULL)
switch (*arg) {
case 'd': /* Debug */
strcat (swbuf, "-d ");
Debug = atoi(*avec);
strcat (swbuf, *avec++);
break;
default:
fprintf (stderr, "Unknown switch -%c\\n",
*arg);
}
}
sprintf (cbuf, "%s %s -o ", PASS1, swbuf);
fpart = cbuf + strlen(cbuf);
for (x = 0; x < filcnt; ++x) {
/* Look for ".a" and replace by ".o" for output part */
tmp = rindex(fvec[x], '.');
if (tmp == NULL || *++tmp != 'a') {
fprintf (stderr,
"%s does not end in \\".a\\", skipping..\\n",
fvec[x]);
skippit = TRUE;
}
if ((isd = fopen(fvec[x], "r")) == NULL) {
fprintf (stderr,
"Cannot open %s, skipping...\\n",
fvec[x]);
skippit = TRUE;
}
if (skippit == TRUE)
skippit = FALSE;
else {
*tmp = 'o';
/* Now to find basename so we leave output here */
tmp = rindex(fvec[x],'/');
tmp = tmp != NULL ? tmp + 1: fvec[x];
*fpart = NULL;
strcat (fpart, tmp);
DEBUG (1, "%s\\n", cbuf);
if ((psd = popen(cbuf, "w")) == NULL) {
fprintf (stderr,
"Cannot popen pass1, aborting\\n");
exit (1);
}
/* Now give pass1 the file */
while ((c = fgetc(isd)) != EOF)
if (fputc(c, psd) == EOF) {
fprintf (stderr,
"I/O error, aborting\\n");
exit (1);
}
fclose (isd);
pclose (psd);
}
}
}
//*FUNKYSTUFF*//
echo extracting util.c
cat << //*FUNKYSTUFF*// > util.c
#include <stdio.h>
#include "TIasm.h"
extern flag Debug;
flag Error; /* To indicate an error for routines
* that can't pass back bad values
*/
/* getnum
* Based on certain format specifiers in the string (which have already
* been validated) convert a character representation to a number no larger
* than a 16 bit word. Overflow is checked.
*
* Returns:
* 0 on error
* the internal representation on success
*
* Note:
* A possible abort.
*/
short getnum (string)
char *string;
{
flag fminus = FALSE; /* number should be negative */
flag radix = 10; /* radix to interpret number */
short ac; /* An accumulator */
short tmp; /* A temporary */
extern flag Error;
void aabort();
void yyeror();
if (*string == '-') {
fminus = TRUE;
++string;
} else
if (*string == '+')
++string;
/* Next char is a '0'? Then it is a literal specification */
if (*string == '0' && *(string + 1) != NULL) {
++string;
/* Next is the radix of the number */
switch (*string++) {
case 'o':
case 'O':
radix = 8;
break;
case 'x':
case 'X':
radix = 16;
break;
case 'b':
case 'B':
radix = 2;
break;
case 'D':
case 'd':
radix = 10;
break;
default:
/* Number starts with a zero but has
* no declerator. Assume octal.
*/
radix = 8;
--string; /* Adjust string */
break;
/*NOTREACHED*/
}
}
/* Ok, now get the number performing radix "conversion" in a portable
* (non character dependent) manner. Hey, check for overflow too!
*/
ac = 0;
while (*string != NULL) {
ac *= radix;
switch (*string++) {
case '0':
tmp = 0;
break;
case '1':
tmp = 1;
break;
case '2':
tmp = 2;
break;
case '3':
tmp = 3;
break;
case '4':
tmp = 4;
break;
case '5':
tmp = 5;
break;
case '6':
tmp = 6;
break;
case '7':
tmp = 7;
break;
case '8':
tmp = 8;
break;
case '9':
tmp = 9;
break;
case 'a':
case 'A':
tmp = 10;
break;
case 'b':
case 'B':
tmp = 11;
break;
case 'c':
case 'C':
tmp = 12;
break;
case 'd':
case 'D':
tmp = 13;
break;
case 'e':
case 'E':
tmp = 14;
break;
case 'f':
case 'F':
tmp = 15;
break;
default:
/* This CANNOT happen! */
aabort ("getnum2");
/*NOTREACHED*/
break;
}
/* Magic number is MAXINT for 16 bit word size */
if (tmp > 0xffff - ac ) {
yyerror ("literal greater than word size");
Error = TRUE;
return (0);
}
ac += tmp;
}
/* Negative number? */
if (fminus == TRUE)
ac *= -1;
return (ac);
}
/* adjinf
*
* Add an address that is a jump instruction's target. These lists in the
* symbol table entries will hold ONLY forward references to save on
* space.
*
* RETURNS:
* nothing
*
* NOTE: May abort if the malloc fails.
*/
void adjinf (stab, loc)
struct stab *stab;
short loc;
{
struct j_lst *jinfo;
extern char *malloc();
if ((jinfo = (struct j_lst *)malloc(sizeof(struct j_lst))) == NULL)
aabort ("adjinf: no mem!");
jinfo->j_addr = loc;
jinfo->j_next = stab->en_jl;
stab->en_jl = jinfo;
}
/* The translation table for escaped characters */
char ctab[] = {
'\\a', '\\b', '\\c', '\\d', '\\e', '\\f', '\\g', '\\h', '\\i', '\\j',
'\\k', '\\l', '\\m', '\\n', '\\o', '\\p', '\\q', '\\r', '\\s', '\\t',
'\\u', '\\v', '\\w', '\\x', '\\y', '\\z', 0
};
/* dostr
* Interpret a string directives argument.
*
* RETURNS:
*
* modified buf arg
* new length of string (by reference)
*
* Note: Error may be set here for an illegal meta-character
*/
void dostr (buf, leng)
char buf[];
int *leng;
{
char null = NULL;
char *tmp, *begin;
extern int Ofd;
extern FILE *Sdvec[];
tmp = begin = buf;
/* Find first quote */
while (*tmp++ != '"')
;
/* Now transfer characters to the start of buf and interpret
* special characters as we go.
*/
while (*tmp != '"' && *tmp != NULL)
if (*tmp == '\\\\') {
++tmp;
if (*tmp >= 'a' && *tmp <= 'z')
*begin++ = ctab[*tmp++ - 'a'];
else switch (*tmp) {
case '\\\\':
case '"':
*begin++ = *tmp++;
default:
Error = TRUE;
}
} else {
*begin++ = *tmp++;
}
/* Null terminate */
*begin = NULL;
/* Find new length */
*leng = begin - buf;
}
/* resrv
* make the entries in the tables reserved. They may NOT be declared again.
*
* Returns:
* Nothing
*
* NOTE:
* May abort if any errors occur loading the symbol table
*/
void resrv()
{
register struct stab *entry;
register struct ops *tptr;
register char *ctmp;
extern struct stab *newent(), *insert();
extern struct ops Optab[];
extern void aabort(), initab();
extern struct ops Dirtab[];
initab(); /* Init the symbol table */
/* First the opcodes as they will be accessed most often.
* Use pointers for speed.
*/
tptr = Optab;
while ((ctmp = tptr->op_name) != NULL) {
if((entry = newent()) == NULL)
aabort ("Symbol table overflow\\n");
strcpy(entry->st_symnm, ctmp);
entry->st_type = TYRSRVD;
entry->st_opc = tptr->op_code;
entry->st_fmt = tptr->op_fmt;
if (insert (entry) == NULL)
aabort ("reserv: Could not insert\\n");
++tptr; /* Get next entry */
}
/* Now, the directives */
tptr = Dirtab;
while ((ctmp = tptr->op_name) != NULL) {
if((entry = newent()) == NULL)
aabort ("Symbol table overflow\\n");
strcpy(entry->st_symnm, ctmp);
entry->st_type = TYDIR;
entry->st_opc = tptr->op_code;
entry->st_fmt = tptr->op_fmt;
if (insert (entry) == NULL)
aabort ("rsrv: Could not insert directive");
++tptr; /* Get next entry */
}
}
/* newsym
* Create and partially initialize a symbol table entry. The entry is
* NOT inserted here! st_type is left blank so that the parser may determine
* that it is a new entry and do the insert.
*
* Returns:
* NUll on error.
* The partially initialized entry on success.
*/
struct stab *newsym (ident)
char *ident;
{
struct stab *ent;
extern struct stab *newent();
if ((ent = newent()) == NULL)
return (NULL);
strncpy (ent->st_symnm, ident, IDENTSIZ);
return (ent);
}
//*FUNKYSTUFF*//
--
--Lee (Ward)
{ucbvax,convex,gatech,pur-ee}!unmvax!lee
More information about the Comp.sources.unix
mailing list