home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Power Programming
/
powerprogramming1994.iso
/
progtool
/
crossasm
/
uasm.arc
/
UASM.C
< prev
next >
Wrap
C/C++ Source or Header
|
1986-04-06
|
22KB
|
873 lines
/*
UASM - UNIVERSAL CROSS ASSMEBLER uasm.c
CUSTOM COMPUTER CONSULTANTS
5 April 1986
*/
#include <stdio.h>
#include <uasm.h>
#define NHASH 512
#define HP1 7
#define HP2 2
/* Flags */
int sf, lf, hf, nolist ;
int pass1, pass2 ;
int lbl ;
int info ;
int valid ;
/* Numbers */
int i, j, k ;
int kk, r ;
int lineno, lnspp, pgno ;
int cc ; /* character count */
int mcc ; /* mark character count */
int ll ; /* line length */
int maxop ;
int maxpseudo ;
int ilc, active ;
int il[NSEG] ;
int instl ;
int parval ;
int num ;
int radix ;
int cput ; /* ib pointer */
int errcnt, esp ;
int syte, sytx ;
unsigned unpar ;
unsigned ht ; /* Record Type */
unsigned ha ; /* Record Start Address */
unsigned he ; /* Expected Address of next item */
unsigned hc ; /* Checksum Mod 256 */
unsigned hsp ; /* Hex String Pointer */
long start, finish, time() ;
#define NOW (0L)
/* Characters */
unsigned char ch ; /* last character */
unsigned char nch ; /* next character */
unsigned char sym ; /* last symbol */
/* Pointers */
char *iptr ; /* Input Buffer */
char *src ; /* Source File Name */
char *cp ; /* General Purpose */
/* Character Arrays */
char hex[13] ; /* Hex File Name */
char lst[13] ; /* List File Name */
char segtype[NSEG] ;
char id[AL] ; /* Last Identifier */
unsigned char ib[256] ; /* Instruction Byte Queue */
unsigned char ssym[256] ; /* character symbols */
unsigned char hs[MAXB] ;
char errstk[25] ;
unsigned char pv[200] ;
unsigned char px[80] ;
int pj[15] ;
int qhash[NHASH] ; /* Head indexes for hash chains */
int nlook, nprobe ;
int maxprobe ;
/* Pointer Arrays */
char *pc[80], *pseudo[15] ;
int (*pp[200])() ;
int (*ppo[15])() ;
/* I/O Buffers */
char ibuf[MAXLINE] ;
FILE *dibuf, *libuf, *hxbuf ;
struct symbol symtab[NSYM] ;
int psym[NSYM] ;
extern char push() ;
extern char pop() ;
extern int cpmf() ;
extern char *strcat() ;
extern char *version ;
/*
Control Programs
main() Open files, assemble, close files, exit
assemble() Process input and create tables
code() Generate object output
list() Generate Listing
*/
main(narg,argv)
int narg;
char **argv;
{
start = time(NOW) ;
puts("\033[2J") ; /* CLEAR_SCREEN */
puts("Universal Cross Assembler -- V1.4 4/5/86\n") ;
puts("(c) Custom Computer Consultants, 1986\n") ;
puts(version) ;
sf = lf = hf = nolist = FALSE ;
/* FILE OPERATIONS */
if( --narg > 0 ) {
dibuf = fopen( *(++argv), "r" ) ;
if( dibuf == NULL ) abort("Source ?\n") ;
src = *argv ; sf = TRUE ;
}
if( --narg > 0 ) {
j = 0 ;
while( **argv != '.' && j < 8 ) {
hex[j] = lst[j] = *(*argv)++ ;
++j ;
}
hex[j] = lst[j] = EOS ;
strcat( hex, ".HEX" ) ;
strcat( lst, ".LST" ) ;
++argv ;
while( ch = *(*argv)++ ) {
if((ch == 'L') || (ch == 'l')) {
libuf = fopen(lst,"w") ;
if( libuf == NULL ) abort("List ?\n") ;
lf = TRUE ;
}
else if((ch == 'O') || (ch == 'o')) {
hxbuf = fopen(hex,"w") ;
if( hxbuf == NULL ) abort("Hex ?\n") ;
hf = TRUE ;
}
else if((ch == 'N') || (ch == 'n')) nolist = TRUE ;
} /* END while(ch = *(*argv)++ ) */
} /* END if(--narg > 0) */
syte = pgno = lnspp = 0 ;
nlook = nprobe = maxprobe = 0 ;
setmem(ssym,256,NUL) ; /* NUL is the token value \200 */
setmem(qhash,2*NHASH,ERROR) ;
cp = "$+-*/(),;%~|&^'@#.<>\"" ;
while( ch = *cp++ ) ssym[ch]=ch ;
set_type() ;
maxpseudo = build_pseudo() ;
maxop = buildopc();
pass1 = sf ? TRUE : FALSE ;
pass2 = sf ? FALSE : TRUE ;
/* Main Assembler Loop */
while ( pass1 || pass2 ) {
if ( pass1 ) puts("Pass 1 : ") ;
if ( pass2 ) puts("Pass 2 : ") ;
lineno = 1;
set_il() ;
active = code_seg() ;
hsp = hc = ht = 0 ;
ha = he = ilc = il[active] ;
errcnt = 0 ;
radix = 10 ;
while(( getline(ibuf)) != EOF ) {
info = assemble() ;
code() ;
list() ;
lineno++ ;
ilc += instl ;
} /* end while on getline(ibuf) */
if ( sf ) {
fclose(dibuf) ;
dibuf = pass1 ? fopen(src,"r") : dibuf ;
if( dibuf == NULL ) abort("Source Reopen ?\n") ;
}
pass1 = FALSE ;
pass2 = pass2 ? FALSE : TRUE ;
finish = time(NOW) ;
printf("\t%5ld\tseconds\n",finish-start) ;
} /* end while on pass1 || pass2 */
/* Sort the Symbol Table */
if ( syte ) {
qsort(psym,syte,sizeof(int),cpmf) ;
}
/* Print the Symbol Table */
if( !nolist ) {
cprintf("\fSymbol Table\n\n") ;
for ( i = 0 ; i < syte ; i++ ) {
if ( i % 5 == 0 ) cprintf("\n") ;
sytx = psym[i] ;
cprintf("%-12s%04x%c ",symtab[sytx].name,
symtab[sytx].value,
segtype[symtab[sytx].flags & (NSEG-1)] ) ;
}
}
cprintf("\n\n") ;
if( errcnt > 0 ) {
cprintf("%04d ERRORS\n",errcnt) ;
if( nolist || lf ) printf("\n%04d ERRORS\n",errcnt) ;
}
else {
cprintf(" NO ERRORS\n") ;
if( nolist || lf ) puts("\n NO ERRORS\n") ;
}
if ( lf ) {
putc(CPMEOF,libuf) ;
fflush(libuf) ;
fclose(libuf) ;
}
if ( hf ) {
hsout() ;
fprintf(hxbuf,":00000001FF\n") ;
putc(CPMEOF,hxbuf) ;
fflush(hxbuf) ;
fclose(hxbuf) ;
}
puts("ASSEMBLY COMPLETE\n");
finish = time(NOW) ;
printf("\n%5ld\tseconds\n",finish-start) ;
printf("%5ld\tlines/minute\n",lineno*60/(finish-start)) ;
printf("%5d\tprobes\n%5d\tlookups\n",nprobe,nlook) ;
printf("%5.2f\tprobes/lookup\n",(float)nprobe/(float)nlook) ;
printf("%5d\tmaximum probe\n",maxprobe) ;
nprobe = 0 ;
for (nlook = 0 ; nlook < NHASH ; ++nlook ) {
if( qhash[nlook] != ERROR ) ++nprobe ;
}
printf("%5d\thash entries\n",nprobe) ;
printf("%5d\tpercent utilization\n",(100*nprobe)/nlook) ;
exit();
}
cpmf(a,b)
int *a, *b ;
{
return strcmp(symtab[*a].name,symtab[*b].name) ;
}
#define INFO 1
#define NOINFO 0
assemble()
{
setmem(ib,4,0) ; /* clear info bytes */
esp = 0 ; /* clear error stack */
instl = parval = valid = 0 ; /* clear length & val */
cput = 0 ; /* clear queue */
if( isin(ch,"*;\n") ) return NOINFO ;
/* process labels */
lbl = ERROR ;
if ( isalpha(ch) ) {
getsym() ;
if ( pass1 ) {
if ( append(id) == ERROR ) puts("Symbol Table Full\n") ;
else { symtab[syte].value = ilc ;
symtab[syte].flags = active ;
psym[syte] = syte ;
lbl= ++syte == NSYM ? (--syte , ERROR) : OK ;
}
}
if( ch == ':' ) getch() ; /* swallow colons */
}
getsym() ;
if( sym != IDENT ) return NOINFO ;
/*
search pseudo operation table
use index in case statement to determine action
*/
i = 0 ; k = maxpseudo - 1 ;
do {
j = ( i + k ) / 2 ;
mcc = sscmp(id,pseudo[j]) ;
if( mcc <= 0 ) k = j - 1 ;
if( mcc >= 0 ) i = j + 1 ;
} while( i <= k ) ;
if ( i - 1 > k ) {
j = pj[j] ;
return (*ppo[j])() ;
}
i = 0 ; k = maxop - 1 ;
do {
j = ( i + k ) / 2 ;
mcc = sscmp(id,pc[j]) ;
if( mcc <= 0 ) k = j - 1 ;
if( mcc >= 0 ) i = j + 1 ;
} while( i <= k ) ;
if ( i - 1 > k ) {
while ( isin(ch," \t") ) getch() ;
mcc = cc - 1 ;
for ( k = px[j] ; k < px[j+1] ; ++k ) {
valid = (*pp[k])() ;
if( valid ) break ;
else { iptr = &ibuf[cc=mcc] ; getch() ; }
}
valid ? TRUE : push('M') ;
}
else push('O') ;
return INFO ;
}
code()
{
if ( pass1 || !info ) return ;
if ( !hf ) return ;
if ( not_cseg(active) ) return ;
/* hex string output */
if ( (hsp>0) && (he != ilc) || hsp > MAXB - 1 ) {
hsout() ;
ha = ilc ;
}
for ( k = 0 ; k < instl ; k++ ) {
hs[hsp++] = ib[k] ;
hc += ib[k] ;
hc &= 0xFF ;
if( hsp > MAXB-1 ) {
hsout() ;
ha += MAXB ;
}
}
he = ilc + instl ;
return ;
}
list()
{
if ( pass1 || nolist ) return ;
lnspp -= esp + 1 ;
if ( lf != 0 && lnspp <= 0 ) {
pgno++ ;
lnspp = 55 ;
cprintf("\fCustom Computer Consultants\t\t\t\t\t\t") ;
cprintf("PAGE %-4d\n",pgno) ;
cprintf("%s\n",version) ;
cprintf("LN #\tLOC CODE\t\tSOURCE\n") ;
}
cprintf("%04d|\t",lineno) ;
if( instl ) cprintf("%04x%c\t",ilc,segtype[active]) ;
else cprintf("\t") ;
if (info) {
kk = ( instl <= 4 ) ? instl : 4 ;
r = instl - kk ;
i = ( kk <= 4 ) ? 4 - kk : 0 ;
j = 0 ;
while ( kk--) cprintf("%02x ",ib[j++]) ;
while ( i-- ) cprintf(" ") ;
cprintf("\t%s",ibuf) ;
while ( r ) {
kk = r <= 4 ? r : 4 ;
r -= kk ;
cprintf("\t\t") ;
while( kk-- ) cprintf("%02x ",ib[j++]) ;
cprintf("\n") ;
}
}
else cprintf("\t\t%s",ibuf) ;
while( ch = pop() ) {
errcnt++ ;
switch(ch) {
case 'R' : cprintf("R*** RELATIVE ADDRESS RANGE\n");
break;
case 'O' : cprintf("O*** ILLEGAL OPCODE\n") ;
break;
case 'M' : cprintf("M*** ADDRESSING MODE ERROR\n");
break;
case 'S' : cprintf("S*** SYNTAX ERROR\n") ;
break;
case 'P' : cprintf("P*** ILLEGAL OPERATOR\n") ;
break ;
case 'E' : cprintf("E*** SYMBOL TABLE EMPTY\n") ;
break;
case 'U' : cprintf("U*** UNDEFINED SYMBOL\n") ;
break ;
default : cprintf("E*** ERROR MESSAGE ERROR <%02x>\n",ch) ;
}
}
}
/*
getline -- assembles one line of input text from
the console input or from a buffered i/o
device.
*/
getline()
{
iptr = sf ? fgets(ibuf,MAXLINE,dibuf) :
strcat(gets(ibuf,MAXLINE),"\n" ) ;
if( !iptr || *iptr == CPMEOF ) return EOF ;
ll = strlen(ibuf) ;
cc = 0 ;
getch() ;
return ll ;
}
getch()
{ ch = cc < ll ? (++cc , *iptr++) : '\n' ;
nch = *iptr ;
}
getsym()
{
int k, np, rad, irad ;
char rc ;
while( isin(ch," \t") ) getch() ;
if( (sym = ssym[ch]) == ch ) return ;
else
if( isdigit(ch) ) {
sym = NUMBER ;
rad = radix ;
np = cc - 1 ;
do {
irad = rad ;
iptr = &ibuf[cc=np] ; getch() ;
num = 0 ;
while( ( k = _bc(ch,rad)) != ERROR ) {
num = num * rad + k ;
rc = ch ; /* possible radix overide */
getch() ;
}
if( isin(ch,"ABCDEF") ) { rad = 16 ; continue ; }
if( isin(ch,"doqbhx") ) rc = ch ;
switch(rc) {
case 'd' : rad = 10 ; getch() ; break ;
case 'o' :
case 'q' : rad = 8 ; getch() ; break ;
case 'b' : rad = 2 ; getch() ; break ;
case 'h' :
case 'x' : rad = 16 ; getch() ; break ;
}
} while( rad != irad ) ;
}
else
if( isalpha(ch) ) {
k = 0 ;
do {
if( k < AL ) id[k++] = ch ;
getch() ;
} while ( alphanum(ch) ) ;
sym = IDENT ;
if ( k >= AL ) --k ;
id[k] = EOS ;
}
}
isin(c,s)
char c ;
char *s ;
{
cp = s ;
do { if ( c == *s++ ) return s - cp ; } while ( *s ) ;
return FALSE ;
}
sscmp(s,t)
char *s, *t ;
{
char c ;
while ( (c = toupper(*s)) == *t ) {
if( c == EOS ) return 0 ;
++s ; ++t ;
}
return c - *t ;
}
nomatch(s)
char *s ;
{
while ( *s ) {
if ( toupper(ch) != *s++ ) return TRUE ;
getch() ;
}
return FALSE ;
}
notcomma()
{
if( ch != ',' ) return TRUE ;
getch() ;
return FALSE ;
}
alphanum(c)
char c ;
{ return isalpha(c) || isdigit(c) || c == '_' ; }
/*
Output Processing
hsout()
cprintf()
puts()
*/
hsout()
{
if( hsp == 0 ) return ;
hc += (( hsp + ( ha >> 8 ) + ha + ht ) & 0xFF ) ;
hs[hsp] = 256 - hc ;
fprintf(hxbuf,":%02x%04x%02x",hsp,ha,ht) ;
for ( j=0 ; j <= hsp ; j++ )
fprintf(hxbuf,"%02x",hs[j]) ;
fprintf(hxbuf,"\n") ;
hsp = hc = ht = 0 ;
}
cprintf(format,args)
unsigned char *format ;
unsigned args ;
{
extern int write() ;
int fn ;
if( nolist ) return ;
fn = lf ? fileno(libuf) : fileno(stdout) ;
return _fmtout(&write,fn,format,&args) ;
}
/* puts -- Replaces the version in the library
It does not do an explicit newline */
puts(s)
char *s ;
{
while(*s) putchar(*s++) ;
}
/*
Expression Analyzer
eval()
hier1()
hier2()
hier3()
hier4()
term()
factor()
_bc
*/
eval()
{
int val ;
val = hier1() ;
while( sym == '|' ) {
getch() ;
val |= hier1() ;
}
return val ;
}
hier1()
{
int val ;
val = hier2() ;
while( sym == '^' ) {
getch() ;
val ^= hier2() ;
}
return val ;
}
hier2()
{
int val ;
val = hier3() ;
while( sym == '&' ) {
getch() ;
val &= hier3() ;
}
return val ;
}
hier3()
{
int val ;
val = hier4() ;
while( isin(sym,"<>") ) {
getch() ;
switch(sym) {
case '<' : val <<= hier4() ;
break ;
case '>' : val >>= hier4() ;
}
}
return val ;
}
hier4()
{
int val ;
val = term() ;
while( isin(sym,".+-") ) {
getch() ;
switch(sym) {
case '.' :
case '+' : val += term() ;
break ;
case '-' : val -= term() ;
}
}
return val ;
}
term()
{
int val ;
val = factor() ;
while( isin(sym,"*/%") ) {
getch() ;
switch (sym) {
case '*' : val *= factor() ;
break ;
case '/' : val /= factor() ;
break ;
case '%' : val %= factor() ;
}
}
return val ;
}
factor()
{
int val, sx ;
char sign ;
val = 0 ; sign = '+' ; sytx = ERROR ;
getsym() ;
if( isin(sym,"+-~") ) {
sign = sym ;
getch() ;
getsym() ;
}
if( sym == IDENT ) {
sx = lookup(id) ;
if( sx == NSYM ) push('U') ;
else
if( sx == ERROR ) push('E') ;
else {
val = symtab[sx].value ;
sytx = sx ;
getsym() ;
}
}
else
if( sym == NUMBER ) {
val = num ;
getsym() ;
}
else
if( sym == '(' ) {
getch() ;
val = eval() ;
if( sym == ')' ) { getch() ; getsym() ; }
else push('S') ;
}
else
if( sym == '$' ) {
val = ilc ;
getch() ;
getsym() ;
}
else
if( sym == '\'' ) {
getch() ;
val = ch & 0xFF ;
getch() ;
if( ch == '\'' ) { getch() ; getsym() ; }
else push('S') ;
}
else push('S') ;
switch(sign) {
case '-' : val = -val ;
break ;
case '~' : val = ~val ;
default : break ;
}
return val ;
}
_bc(c,b)
char c, b ;
{
if(isalpha(c = toupper(c))) c -= 55 ;
else if(isdigit(c)) c -= 0x30 ;
else return ERROR ;
if(c > b-1) return ERROR ;
else return c ;
}
/*
Symbol Table Routines
append() adds a new symbol to the table
lookup() checks the table for a symbol
*/
hash(s,l)
unsigned char *s ;
unsigned int l ;
{
unsigned char c ;
if ( l == 0 ) l = strlen(s) ;
c = ( *s + *(s+l-1) ) >> 1 ;
return (( c * HP1 + l * HP2 ) & (NHASH-1));
}
append(s)
char *s ;
{
int h, q ;
int l ;
if ( syte == NSYM ) return ERROR ;
l = 1 + strlen(s) ;
symtab[syte].name = sbrk(l) ;
strcpy(symtab[syte].name , s ) ;
symtab[syte].flags = '\0' ;
symtab[syte].value = 0 ;
symtab[syte].link = ERROR ;
h = hash(s,l-1) ;
q = qhash[h] ;
if ( q == ERROR ) qhash[h] = syte ;
else {
while( symtab[q].link != ERROR ) q = symtab[q].link ;
symtab[q].link = syte ;
}
return OK ;
}
lookup(s)
char *s ;
{
int q, m ;
m = 0 ;
if ( syte == 0 ) return ERROR ; /* ST EMPTY */
++nlook ;
q = qhash[hash(s,0)] ;
while( q != ERROR ) {
++nprobe ; ++m ;
if( m > maxprobe ) maxprobe = m ;
if( strcmp(symtab[q].name,s) == 0 ) return q ;
q = symtab[q].link ;
}
return NSYM ; /* Not Found */
}
/* Error Processing
abort()
push()
pop()
*/
abort(s)
char *s ;
{ puts(s) ; exit() ; }
char push(c)
char c;
{
if( esp < 25 ) return (errstk[esp++] = c);
return '\0';
}
char pop()
{
if( esp > 0 ) return (errstk[--esp]);
return '\0';
}
/*
End of UASM.C
*/