💾 Archived View for uscoffings.net › retro-computing › systems › TI994a › assemblers › tiasm › src ›… captured on 2022-06-04 at 01:13:41.

View Raw

More Information

-=-=-=-=-=-=-

#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;
	}
}