home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
CP/M
/
CPM_CDROM.iso
/
cpm
/
utils
/
asmutl
/
smmaclnk.ark
/
MAC2.C
< prev
next >
Wrap
Text File
|
1987-09-10
|
14KB
|
564 lines
/*
** 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