home *** CD-ROM | disk | FTP | other *** search
- /*
- ** MAC2.c -- Small-Mac Assembler -- Part 2: pass 1 and 2 Functions
- **
- ** Copyright 1985 J. E. Hendrix
- */
- #include <stdio.h>
- #include "mac.h"
- #include "rel.h"
- #include "ext.h"
- #define NOCCARGC
-
- extern int iloc; /* instr location */
-
- /*
- ** add a new symbol to the table
- */
- addsym() {
- char *dest, *sour;
- if(*stptr) error("- Symbol Table Overflow");
- stp[stn++] = stptr; /* set symbol pointer */
- dest = stptr; sour = stsym;
- while(*dest++ = toupper(*sour++));
- }
-
- /*
- ** determine if an assembler insrtruction
- */
- aifind() {
- char *cp; cp = lp;
- while(isgraph(*lp)) ++lp;
- while(isspace(*lp)) ++lp;
- if(fldcmp(cp, "DW") == 0) return (DW);
- else if(fldcmp(cp, "DB") == 0) return (DB);
- else if(fldcmp(cp, "DS") == 0) return (DS);
- else if(fldcmp(cp, "EXT") == 0) return (EX);
- else if(fldcmp(cp, "SET") == 0) return (SET);
- else if(fldcmp(cp, "EQU") == 0) return (EQU);
- else if(fldcmp(cp, "ORG") == 0) return (ORG);
- else if(fldcmp(cp, "END") == 0) return (END);
- return (ERR);
- }
-
- /*
- ** begin a line in the listing
- */
- begline() {
- char str[6];
- if(pass == 2 && list) {
- if(begpage()) {
- puts("line loc ----object---- source"); puts("");
- lline += 2;
- }
- itou(lin, str, 5); fputs(str, stdout);
- itox(loc, str, 6); fputs(str, stdout);
- putchar(' '); ccnt = 0; ++lline;
- }
- }
-
- /*
- ** begin a page?
- */
- begpage() {
- char str[4];
- if(lline >= 58) {
- lline = 2;
- ++lpage;
- if(lpage > 1) puts("\n\n\n\n\n\n\n");
- fputs("file: ", stdout); fputs(srcfn, stdout);
- itou(lpage, str, 4);
- fputs(" page: ", stdout); puts(str); puts("");
- return (YES);
- }
- return (NO);
- }
-
- /*
- ** detect assembler instruction and process it
- */
- doasm() {
- int j;
- if(atend(*lp) && (!stsym[0] || gotlabel)) return;
- if((j = aifind()) == ERR) { /* lp -> 2nd field or end */
- lp = skip(1, line); /* lp -> 1st field */
- j = aifind();
- stsym[0] = NULL; /* declare no symble */
- }
- switch(j) {
- case EX: doext(); return;
- case DW: dodat(INTSZ); return;
- case DB: dodat(1); return;
- case DS: doloc(YES); return;
- case ORG: doloc(NO); return;
- case SET: doval(SETBIT); return;
- case EQU: doval(0); return;
- case END: doend(); return;
- }
- oprerr();
- }
-
- /*
- ** define data (DB & DW)
- */
- dodat(sz) int sz; {
- int dlm;
- while(!atend(*lp)) {
- if(isspace(*lp) || *lp == ',') ++lp;
- else if(*lp == '\"' || *lp == '\'') { /* string? */
- dlm = *lp;
- while(!atend(*++lp)) {
- if(*lp == dlm && *++lp != dlm) break;
- if(pass == 2) {field = *lp; genabs(sz);}
- else loc += sz;
- }
- }
- else {
- ep = lp; /* expression? */
- expr(&field, &type);
- lp = ep;
- if(pass == 2) {
- type &= RELBITS;
- if(type == ABS) genabs(sz);
- else {
- if(sz == 1) {relerr(); genabs(1);} /* 1-byte relocatable? */
- else genrel(); /* output relocatable item */
- }
- }
- else loc += sz;
- }
- }
- }
-
- /*
- ** process END instruction
- */
- doend() {
- eom = YES; /* flag end of module */
- onexpr();
- if((type & RELBITS) == PREL) {
- endt = PREL;
- endv = field;
- }
- else if(field) relerr();
- }
-
- /*
- ** define external reference (ECT)
- */
- doext() {
- while(!atend(*lp)) {
- while(isspace(*lp) || *lp == ',') {++lp; continue;}
- lp = getsym(lp, NO); /* fetch the next symbol */
- if(badsym) {symerr(); continue;} /* symbol error */
- else if(stfind()) { /* already in table? */
- if(stptr[STFLAG] & (LABBIT|EQUBIT|SETBIT)) {rederr(); continue;}
- }
- else addsym(); /* not yet defined */
- if(pass == 1) stptr[STFLAG] |= XRBIT|ABS; /* 1st ext ref is ABS 0 */
- }
- }
-
- /*
- ** detect label and stow it away
- */
- dolabel() {
- lp = skip(1, line); /* locatefirst field */
- lp = getsym(lp, NO); /* fetch a symble */
- if(gotlabel) { /* got label */
- if(badsym) {laberr(); return;}
- if(stfind()) { /* already in table */
- if(pass == 1) {
- if(stptr[STFLAG] & (LABBIT|EQUBIT|SETBIT|XRBIT))
- {rederr(); return;}
- }
- else if(stptr[STFLAG] & (LABBIT2|EQUBIT|SETBIT|XRBIT))
- {rederr(); return;}
- else stptr[STFLAG] |= LABBIT2;
- }
- else addsym(); /* not defined, stow it */
- if(pass == 1) {
- putint(stptr + STVALUE, loc); /* value */
- if(gotep) /* flags */
- stptr[STFLAG] = LABBIT|PREL|EPBIT;
- else stptr[STFLAG] = LABBIT|PREL;
- }
- }
- }
-
- /*
- ** set location counter (ORG, DS)
- */
- doloc(bump) int bump; {
- if(onexpr()) {
- if(bump) field = loc += field;
- else if(loc <= field) loc = field;
- else bakerr();
- if(pass == 2) {item = SETLC; type = PREL; putrel();}
- }
- }
-
- /*
- ** detect machine instruction and process it
- */
- domach() {
- char *fmt, *cp;
- if(gotlabel) cp = lp;
- else cp = skip(1, line); /* backup if no label */
- if(fmt = find(cp)) { /* machine instruction? */
- fmt += INTSZ; /* locate format byte in mit */
- if(pass == 2) domac2(fmt); /* do pass 2 processing */
- else loc += (*fmt & 3) + 1; /* bump location counter */
- return (YES);
- }
- return (NO); /* may be pseudo-op */
- }
-
- /*
- ** detect machine instruction and generate object code
- */
- domac2(ptr) char *ptr; {
- int format, len, ilen, pcr, t, v, opcode, holding;
- format = getint(ptr++); /* ptr is now 1 byte early */
- len = ilen = (format & 7) + 1;
- format >>= 3; /* first code/expr bit */
- iloc = loc; /* preserve istr loc for $ */
- holding = NO;
- ep = expbuf; /* set up for expr() */
- while(len-- > 0) { /* for each byte of code */
- if(format & 1) { /* expression */
- if(holding) {
- holding = NO;
- field = opcode + opadj; /* adjust last byte before expr */
- opadj = 0;
- genabs(1);
- }
- expr(&v, &t); /* evaluate next expression */
- format >>= 1; /* pc relative bit */
- if(format & 1) {
- if((t & RELBITS) == PREL) {
- v -= ilen + iloc; /* calc offset from this instr */
- t = (t & ~RELBITS) + ABS; /* now abs, may be 1 byte */
- }
- else v -= ilen; /* adjust offset from this instr */
- pcr = YES; /* remember it's pc relative */
- }
- else pcr = NO;
- format >>= 1; /* size bit */
- if(format & 1) { /* 2-byte expr */
- if(t & XRBIT) { /* ext ref */
- if(v) { /* must be offset from ext ref */
- item = XPOFF;
- type = ABS;
- field = v;
- listcode(2, "+ "); /* list offset */
- putrel(); /* write 2-byte offset */
- }
- field = prior; /* will link to prior ref */
- }
- else field = v; /* expr value */
- if((t & RELBITS) == ABS)
- genabs(2); /* write 2 absolute bytes */
- else genrel(); /* write 2 relocatable bytes */
- --len;
- }
- else { /* 1-byte expr */
- if((t & RELBITS) == PREL)
- relerr(); /* 1 byte can't be relocatable */
- if(pcr && (v > 127 || v < -128))
- rngerr(); /* range error */
- field = v; /* expr value */
- genabs(1); /* write 1 absolute byte */
- }
- }
- else { /* code byte */
- if(holding) {
- field = opcode; /* don't adjust, not last byte */
- genabs(1); /* write prior code byte */
- }
- opcode = *++ptr & 255; /* hold this one, may be more */
- holding = YES;
- }
- format >>= 1;
- }
- if(holding) {
- field = opcode + opadj;
- genabs(1); /* write last code byte */
- }
- }
-
- /*
- ** define a symbol value (SET, EQU)
- */
- doval(set) int set; {
- char *ptr; int found;
- if(!stsym[0] || badsym || gotlabel) {symerr(); return;}
- if((found = stfind()) == 0) addsym();/* not defined */
- ptr = stptr; /* preserve stptr */
- onexpr(); /* evaluate expression */
- if(pass == 1 || set) {
- if(found == 0 || ptr[STFLAG] & set) {
- putint(ptr + STVALUE, field); /* value */
- ptr[STFLAG] = set|type; /* flags */
- }
- else rederr();
- }
- else if(ptr[STFLAG] & (LABBIT|EQUBIT|SETBIT|XRBIT)) rederr();
- else ptr[STFLAG] |= EQUBIT;
- if(pass == 2) { /* list value */
- if((ptr[STFLAG] & RELBITS) == PREL)
- listcode(2, "' =");
- else listcode(2, " =");
- }
- }
-
- /*
- ** end a line in the listing
- */
- endline() {
- char *cp; int col; col = 0;
- if(pass == 2 && list) {
- if(part1) puts("");
- else {
- part1 = YES;
- while(ccnt++ < 16) putchar(' ');
- cp = line;
- while(*cp) {
- if(*cp != '\t') {++col; putchar(*cp++);}
- else {do putchar(' '); while(++col % 8); ++cp;}
- }
- }
- }
- }
-
- /*
- ** generate an absolute value of sz bytes
- */
- genabs(sz) int sz; {
- listcode(sz, " ");
- loc += sz; /* bump location counter */
- item = ABS;
- while(sz--) {putrel(); field >>= 8;}
- }
-
- /*
- ** generate a relocatable item
- */
- genrel() {
- listcode(2, "' ");
- loc += 2; /* bump location counter */
- item = PREL;
- putrel(); /* write 2-byte relocatable item */
- }
-
- /*
- ** gripe about errors in a line
- */
- gripe() {
- if(lerr) {
- if(!list) outerr(line);
- if(lerr & 1) outerr("- Backward Movement\n");
- if(lerr & 2) outerr("- Bad Number\n");
- if(lerr & 4) outerr("- Bad Expression\n");
- if(lerr & 8) outerr("- Bad Label\n");
- if(lerr & 16) outerr("- Bad Operation\n");
- if(lerr & 32) outerr("- Redundant Definition\n");
- if(lerr & 64) outerr("- Bad Symbol\n");
- if(lerr & 128) outerr("- Relocation Error\n");
- if(lerr & 256) outerr("- Undefined Symbol\n");
- if(lerr & 512) outerr("- Bad Parameter\n");
- if(lerr & 1024) outerr("- Range Error\n");
- if(pause) wait();
- outerr("\n");
- err = YES;
- }
- }
-
- bakerr() {lerr |= 1;}
- numerr() {lerr |= 2;}
- experr() {lerr |= 4;}
- laberr() {lerr |= 8;}
- oprerr() {lerr |= 16;}
- rederr() {lerr |= 32;}
- symerr() {lerr |= 64;}
- relerr() {lerr |= 128;}
- underr() {lerr |= 256;}
- parerr() {lerr |= 512;}
- rngerr() {lerr |= 1024;}
-
- /*
- ** list a code item
- */
- listcode(sz, suff) int sz; char suff[]; {
- int i; char str[3];
- if(list) {
- i = sz + sz + strlen(suff);
- if((ccnt + i) > 16) {endline(); begline();}
- while(sz--) {
- if(sz) itox((field >> 8) & 255, str, 3);
- else itox(field & 255, str, 3);
- if(*str == ' ') *str = '0';
- fputs(str, stdout);
- }
- fputs(suff, stdout);
- ccnt += i;
- }
- }
-
- /*
- ** output an error line
- */
- outerr(str) char *str; {
- begpage(); fputs(str, stdout); ++lline;
- }
-
- /*
- ** require one expression only
- */
- onexpr() {
- ep = lp;
- expr(&field, &type);
- if(atend(*ep)) return (YES);
- experr();
- return (NO);
- }
-
- /*
- ** output end of program and file
- */
- putend() {
- item = EPROG; type = endt; field = endv; putrel();
- item = EFILE; type = ABS; field = 0; putrel();
- }
-
- /*
- ** output entry points
- */
- putent() {
- char *cp;
- cp = st;
- while(cp < stend) {
- poll(YES);
- if(*cp) {
- if(cp[STFLAG] & EPBIT) { /* entry point **/
- item = ENAME;
- strncpy(symbol, cp, MAXSYM + 1);
- putrel();
- }
- }
- cp += STENTRY;
- }
- }
-
- /*
- ** output entry point or external reference
- */
- putex(cp, i) char *cp; int i; {
- item = i;
- type = cp[STFLAG] & RELBITS;
- field = getint(cp + STVALUE);
- strncpy(symbol, cp, MAXSYM + 1);
- putrel();
- }
-
- /*
- ** output ent pnt and ext ref symbols
- */
- putexs() {
- int i; char *cp;
- ccnt = 0; /* init for show() */
- shell(0, stn - 1); /* sort the symbols */
- if(list && !begpage()) {++lline; puts("");}
- for(i = 0; i < stn; ++i) {
- poll(YES);
- cp = stp[i];
- if(list) show(cp);
- if(cp[STFLAG] & XRBIT) putex(cp, XCHAIN);
- if(cp[STFLAG] & EPBIT) putex(cp, EPOINT);
- }
- puts("");
- }
-
- /*
- ** output module name
- */
- putname() {
- int i, j;
- item = PNAME;
- if(objfn[1] == ':') i = 2; else i = 0;
- j = 0;
- while(objfn[i] && objfn[i] != '.' && j < MAXSYM)
- symbol[j++] = objfn[i++];
- symbol[j] = NULL;
- putrel();
- }
-
- /*
- ** output program size
- */
- putsz() {
- item = PSIZE;
- type = PREL;
- field = loc;
- putrel();
- }
-
- /*
- ** shell sort the symbols
- */
- shell(l, u) int l, u; {
- int gap, i, j, k, jg;
- gap = (u - l + 1) >> 1;
- while(gap > 0) {
- i = gap + l;
- while(i <= u) {
- j = i++ - gap;
- while(j >= l) {
- jg = j + gap;
- if(strcmp(stp[j], stp[jg]) <= 0) break;
- k = stp[jg]; stp[jg] = stp[j]; stp[j] = k;
- j -= gap;
- }
- }
- gap >>= 1;
- }
- }
-
- /*
- ** show a symbol
- */
- show(cp) char *cp; {
- char str[5];
- begpage();
- itox(getint(cp + STVALUE), str, 5); fputs(str, stdout);
- if((cp[STFLAG] & RELBITS) == PREL) fputs("' ", stdout);
- else fputs(" ", stdout);
- fputs(cp, stdout);
- ccnt += 6 + strlen(cp);
- if(cp[STFLAG] & LABBIT) {putchar(':'); ++ccnt;}
- if(cp[STFLAG] & EPBIT) {putchar(":"); ++ccnt;}
- if(cp[STFLAG] & XRBIT) {fputs("##", stdout); ccnt += 2;}
- if(ccnt < 60)
- while(ccnt % 20) {putchar(' '); ++ccnt;}
- else {puts(""); ++lline; ccnt = 0;}
- }
-
- /*
- ** find stsym in symbol table
- ** leave stptr pointing to desired or null entry
- ** return true if found, else false
- */
- stfind(){
- char *start;
- stptr = start = st + hash(stsym, stmax) * STENTRY;
- while(*stptr) {
- if(strcmp(stsym, stptr) == 0) return (YES);
- if((stptr += STENTRY) >= stend) stptr = st;
- if(stptr == start) break;
- }
- return (NO);
- }
- return (YES);
- if((stptr += STENTRY) >= stend) stptr = st;
- if(stptr == start) break;
- }
- ret