💾 Archived View for uscoffings.net › retro-computing › systems › TI994a › assemblers › tiasm › src ›… captured on 2022-06-04 at 01:13:41.
-=-=-=-=-=-=-
#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; } }