Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Posting-Version: version B 2.10.1 6/24/83; site unmvax.UUCP From: lee@unmvax.UUCP Newsgroups: net.sources Subject: TI 99 assembler, the assembler itself Message-ID: <374@unmvax.UUCP> Date: Sun, 22-Jul-84 13:15:47 EDT Article-I.D.: unmvax.374 Posted: Sun Jul 22 13:15:47 1984 Date-Received: Mon, 30-Jul-84 00:18:51 EDT Organization: Univ. of New Mexico, Albuquerque Lines: 2456 To unarchive, remove the first line through and including the dashed line. Then type: % sh 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 /* 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 #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 /* 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 #include /* 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 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 #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 #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 OPTYP1 1 %token OPTYP2 2 %token OPTYP3 3 %token OPTYP4 4 %token OPTYP5 5 %token OPTYP6 6 %token OPTYP7 7 %token OPTYP8 8 %token OPTYP9 9 %token OPTYP10 10 %token OPTYP11 11 %token STRINGDIR %token EXTNLDIR %token WORDDIR %token DATADIR %token REG %token IDENT %token STRING %token NUMBER %token ERROR %type mopnd %type pcrel %type indir %type iauto %type symbol %type isymb %type 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 /* 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 #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 #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