home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Simtel MSDOS 1992 September
/
Simtel20_Sept92.cdr
/
msdos
/
ddjmag
/
ddj8610.arc
/
CAMPLST.OCT
next >
Wrap
Text File
|
1986-10-31
|
33KB
|
1,196 lines
Listing One
/*
.ll 79
A Z80 - N320XX translator
R. A. Campbell - 03/26/86
TNZH.C - header/global definitions
*/
#define BANNER ";Z80 - NS320XX Translater; RAC 03/26/86\n"
#define NOPCDS 70 /* number of opcodes/registers in table */
#define FGERR 0 /* error or eof fgets return */
#define CR 0x0d /* cpm new/line */
#define COMMBEG ';' /* comment marker */
#define SYMBEND ':' /* end of symbol, fluff */
#define LETTER 'a'
#define DIGIT '0'
#define SPACE ' ' /* space (or tab) */
#define MAXCODE 150 /* maximum bytes / line of code */
#define MAXWORD 10
/* opcode types */
#define TMASK 0xF000 /* mask to opcode-type */
#define ISFLG 0xF000 /* is a conditional flag */
#define ISREG 0xE000 /* is a register */
#define ISSPC 0xD000 /* is a special operation */
#define ISPBIT 0xA000 /* is a PSR bit operation */
#define ISBIT 0x9000 /* is a bit operation */
#define BYTEPS 0x8000 /* is a byte/word pseudo-op */
#define ENDPS 0x7000 /* end pseudo-op */
#define ISMOV 0x5000 /* is a move instruction */
#define NOOPRS 0x4000 /* no fancy operands */
#define ISRET 0x3000 /* is a return instruction */
#define ISBSR 0x2000 /* is a call/BSR */
#define ISBR 0x1000 /* is a branch */
#define NADST 0x0800 /* operation needs destination- B,A */
#define NASRC 0x0400 /* needs a source */
#define NAONE 0x0200 /* needs a one, 0=-1, 1=+1 */
#define ISPRB 0x0100 /* is a problem translation */
#define ISPOS 0x0008 /* is a +1 */
#define ISREV 0x0004 /* operands reversed */
/* operand modifiers */
#define ISPAR 0x0080 /* operand is parenthesized */
#define ISSYM 0x0040 /* operand is a symbol */
/* opmod's */
#define ISCMP 0x8000 /* is a compare operation */
#define ISARI 0x4000 /* is an arithmetic oper */
#define ISXXX 0x2000 /* is call/branch, ?? */
#define ISNOT 0x1000 /* is a nothing; mov */
/* Following are pseudo ops */
#define BEGINPS 0x64 /* begin procedure */
#define BLKPS 0x66 /* space block define */
#define EQUPS 0x70 /* equ pseudo-op */
#define LOCPS 0x76 /* LOC pseudo-op */
#define PROCPS 0x78 /* procedure definition */
#define WORDPS 0x7e /* define a word - 2 bytes */
#define SETCFG 0x080e /* setcfg opcode */
char **argv, /* input arg pointer */
symfound, /* switch for tree finds */
innamebf[14], /* for assembling file name */
outnamebf[14], /* for output file */
switbuf[10], /* for assembling switches */
wordbuf[MAXWORD+2], /* for incoming words */
linebuf[130], /* incoming line buffer */
codebuf[130], /* for output produced */
tmpbuf[18], /* temporary buffer */
symsave[18], /* to save symbol equ's */
opcsave[18], /* save opcode */
errorbuf[18], /* to save errors */
*allocp, /* next free position */
symstart, /* for symbol table start */
*allocend, /* last free position */
cparenth, /* parenthesis count */
cerror, /* current error, if any */
swstinit, /* initialize, make code, static variables */
swsym, /* switch to insert symbol */
swdebug, /* debug switch */
swlist, /* listing output switch */
swoutput, /* output code switch */
swsymbol; /* symbol table switch */
#ifdef Z80
char inbuf[BUFSIZ], /* for incoming disk data */
outbuf[BUFSIZ]; /* for output */
#define long int
#else
#define unsigned long
#define inbuf infd
#define outbuf outfd
#endif
/* integer variables */
int argc, /* calling argument count */
curfile, /* for counting source files */
c, t, /* for actual text characters */
csize, /* current data size */
cursym, /* current symbol number */
lsttype, /* for last instr type */
infd, /* input file open */
outfd, /* output file descriptor */
copr, /* index for current operand */
copclass, /* for current opcode class */
coptype, /* current opcode type, class AND F000h */
copmod, /* for current opcode modifier */
inbcount, /* input byte count / pointer */
nlines, /* for number of lines processed */
passno, /* pass number */
i, x, xx, /* miscelaneous transient variables */
n, /* counting number for searches */
nerrors, /* error count */
bquit; /* set if need to quit */
struct oprs /* for operands */
{ char opr[12]; /* for operator */
int ofl; /* for opclass */
int opm; /* for op-mods */
} oprt[4]; /* table for operands */
struct key /* for opcodes */
{ char inword[6]; /* in-opcode */
char outword[8]; /* out-opcode */
int opclass;
int opmod; /* operator modifier */
} keytab[NOPCDS];
/* end of global definitions 03/26/86 */
/*
.ll 79
TNZ.C Translator; NS-320XX from Z80
by R. A. Campbell, 03/26/86 - main file
clink TNZ, TNZ2; TNZH= header, TNZO= opcodes
*/
/* for Z80, uncomment following
*/
#define Z80 1
#include "bdscio.h"
/* for non-Z80, uncomment following
#include "niohe.c"
*/
/* always */
#include "tnzh.c"
#ifdef Z80
main( rgc, rgv )
char *rgc;
char **rgv;
#else
main( rgc, rgv, mbeg )
char *rgc;
char **rgv;
char *mbeg;
#endif
{ argc = rgc; /* this foolishness */
argv = rgv; /* to get argc,argv as globals */
#ifdef Z80
allocp = endext (); /* initialize free position */
allocend = topofmem () - 500; /* allow for stack */
#else
allocp = mbeg;
allocend = &rgc - 500;
#endif
initas (); /* go initialize */
printf(" Translating;%9s Options; %s\n", argv[1], switbuf);
nlines = 0;
passno = 1; /* set for first pass */
doscan (); /* scan file */
}
doscan() /* scan input file(s) */
{ curfile = 1;
nerrors = 0;
while ( curfile < argc )
{ strcpy (innamebf,argv[curfile++]); /* get file name */
strcat (innamebf,".Z80");
#ifdef Z80
if ((infd = fopen (innamebf,inbuf)) == ERROR )
#else
if (( infd = fopen (innamebf, "R")) == ERROR )
#endif
{ printf (" Unable to open: %s\n", innamebf);
exit ();
} /* else, keep going */
if ( curfile == 2 ) /* gets ++'d above */
dostart ();
symsave[0] = 0;
lsttype = bquit = 0;
while ( bquit == 0 )
{ rdline (); /* get & read the line */
++nlines;
if ( copclass != 0 || symsave[0] != 0 )
doline (); /* to operand(s) */
if ( t == COMMBEG || cerror != 0 )
{ if ( t == COMMBEG ) /* else is a \n */
chrcat (codebuf, t );
if ( t == COMMBEG )
{while (( t = typeof ((c= getchr ()) )) != '\n' )
chrcat (codebuf, c );
}
if ( cerror != 0 )
{ ++nerrors;
strcat ( codebuf, ";???");
}
}
chrcat (codebuf, '\r' ); /* for CP/M */
chrcat (codebuf, '\n');
if ( swlist != 0 )
listout (); /* listing output */
outcode ();
if (( xx = ( copmod & 0xef00 )) != 0 )
{if (( copclass & 0xfff0 ) == 0x4200 /* is dec/inc */
&& csize == 'W' )
; /* ignore, is dec/inc hl, etc. */
else
lsttype = xx; /* copy last type */
}
} /* bquit != 0 */
dofinish ();
if ( fclose (inbuf) == -1)
printf("\n Unable to close file \n");
} /* end of one file */
} /* end of doscan */
rdline() /* read line */
{ quitck (); /* see if should quit */
csize = i = inbcount = copmod = 0;
copr = cerror = coptype = copclass = 0; /* impossible opclass */
codebuf[0] = opcsave[0] = 0;
oprt[copr].opr[0] = oprt[copr].ofl = 0;
if ( fgets (linebuf,inbuf) == FGERR ) /* get a line */
{ printf ("Unable to Read: %s\n", innamebf );
bquit++; /* out of file */
return; /* done with file */
}
if (( t = getword ( )) == '\n' || t == COMMBEG)
return; /* empty line */
if ( t != SPACE )
rdsymbol (); /* read symbol, if there */
while (( t = getword ( ) ) == SPACE
|| t == SYMBEND ) /* walk to 1st non-space */
; /* skip spaces, tabs */
if ( t == '\n' || t == 0 || t == COMMBEG )
return;
rdopcode (); /* read opcode, if any */
if ( t == '\n' || t == 0 || t == COMMBEG )
return;
rdoperands (); /* read operand(s) */
}
rdsymbol() /* do symbol, if present */
{ if (t == LETTER) /* is symbol */
{ if ( symsave[0] != 0 ) /* have one hanging */
strcat ( symsave, "\r\n" );
strcat (symsave,wordbuf); /* copy through */
chrcat ( symsave, ':' ); /* add colon */
}
}
rdopcode() /* read opcode, if any */
{ if ( t != LETTER )
return;
cwdbftl ();
if ( ( n = binary ( wordbuf) ) >= 0 )
{ copclass = keytab[n].opclass;
coptype = copclass & TMASK;
copmod = keytab[n].opmod;
strcat (opcsave, keytab[n].outword);
if (( copclass & ISPRB) != 0 )
++cerror; /* is problem opcode */
if ( coptype == ENDPS )
++bquit;
}
else
{ strcat (opcsave,wordbuf);
copclass = NOOPRS; /* put something in */
++cerror; /* unknown opcode */
}
}
rdoperands() /* read operands */
{
oprnew: /* clear flags */
cparenth = 0;
oprcont:
switch (( t = getword () ) ) /* see what it is */
{ case LETTER: /* see if is symbol or register */
strcpy ( tmpbuf, wordbuf ); /* save */
cwdbftl (); /* convert to lower case */
if ( ( n = binary ( wordbuf ) ) >= 0
&& ( keytab[n].opclass & ISREG) == ISREG ) /* reg-flag */
{ oprt[copr].opm = keytab[n].opmod;
xx = keytab[n].opclass;
oprt[copr].ofl |= xx;
if ( xx == 0xe052 )
strcpy ( oprt[copr].opr, keytab[n].outword );
else
strcat (oprt[copr].opr, keytab[n].outword );
if (( xx & ISPRB ) != 0 )
++cerror;
if ( (xx & TMASK) == ISREG /* is register only */
&& csize == 0 ) /* 1st size, dest */
{ xx &= 3; /* strip to size */
if ( xx == 1 )
csize = 'B';
else if ( xx == 2 )
csize = 'W';
}
}
else
{ strcpy ( oprt[copr].opr,tmpbuf );
oprt[copr].ofl |= ISSYM; /* mark as symbol */
}
goto oprcont;
case DIGIT:
chrcat (oprt[copr].opr, c );
while (( t = typeof (( c = getchr ()))) == DIGIT || t == LETTER )
chrcat ( oprt[copr].opr, c );
ugetch ();
goto oprcont;
case '(':
oprt[copr].ofl |= ISPAR; /* mark as paren, fall thru */
chrcat (oprt[copr].opr, c); /* symbol will overwrite */
goto oprcont;
case '+':
case '-':
if (( oprt[copr].ofl & (ISPAR|ISREG)) == (ISPAR|ISREG) )
{ oprt[copr].ofl |= ISPOS; /* final paren */
chrcat ( oprt[copr].opr, ')' );
} /* have an (IX+?), make (IX)+/- ? */
chrcat (oprt[copr].opr, c); /* copy through */
goto oprcont;
case ')':
if (( oprt[copr].ofl & 0xff78) == ISREG ) /* not if EX (SP),?? */
chrcat (oprt[copr].opr, c); /* not; (IY+), (SP) copy */
goto oprcont;
case ''': /* ASCII string/char, transfer */
chrcat (oprt[copr].opr, c );
if (( c = getchr ()) == ''' ) /* have a '''? */
chrcat ( oprt[copr].opr, c );
else
ugetch (); /* no, go back */
while (( c = getchr ()) != ''' )
chrcat ( oprt[copr].opr, c ); /* put in ASCII */
chrcat ( oprt[copr].opr, c ); /* put in terminating ''' */
goto oprcont;
case SPACE: /* ignore it */
goto oprcont;
case ',': /* to permit mixes of strings and bytes */
if ( coptype == BYTEPS )
{ chrcat (oprt[copr].opr, c );
goto oprcont;
}
else
goto oprend;
case '\n': case COMMBEG:
return; /* done */
default:
chrcat (oprt[copr].opr, c ); /* copy char */
goto oprcont;
} /* end of switch t */
oprend:
if ( copr == 3 )
return; /* done!!!! */
++copr; /* inc current operand */
oprt[copr].opr[0] = 0;
oprt[copr].ofl = 0; /* clear out next oprt's */
goto oprnew;
}
doline() /* put out operands */
{ i = 0;
dosym ();
chrcat ( codebuf, '\t' ); /* tab over */
spcchk (); /* check for special operations */
if ( coptype == ISSPC )
dospcs (); /* do special operations */
else if ( coptype <= ISRET ) /* program flow oper */
doprfl ();
else
doarmov (); /* arith/move operation */
if ( i != 0 )
chrcat ( codebuf, '\t' );
}
dosym()
{ i = 0;
if ( symsave[0] != 0 )
{ strcpy ( codebuf, symsave );
symsave[0] = 0; /* null for next time */
}
}
spcchk() /* check for special operations, check size */
{ if ( copr == 0 )
{ if ( coptype == ISBR )
{ if ( (oprt[0].ofl & TMASK) == ISREG )
/* compute absol addrs */
{ strcat ( codebuf, "ADDR Q_start,R7\r\n" );
strcat ( codebuf, "\tADD.D R7," );
if ( oprt[0].opm == 12 )
strcat ( codebuf, "R3" );
else if ( oprt[0].opm == 13 )
strcat ( codebuf, "R4" );
else
strcat ( codebuf, "R5" );
strcat ( codebuf, "\r\n\t" );
coptype = NOOPRS; /* don't add "R" to opcode */
strcpy ( opcsave, "JUMP" ); /* go do armov */
}
else if ( oprt[0].ofl == 0 ) /* is an absolute jump */
{ coptype = NOOPRS; /* don't add "R" to opcode */
strcpy ( opcsave, "JUMP" );
}
} /* end of ISBR */
else if ( coptype == ISPBIT )
{ if (( xx = copmod & 0xf ) == 1 )
{ csize = 'B';
strcpy ( oprt[0].opr, "1" ); /* carry bit */
}
else if ( xx = 12 )
{ csize = 'W';
strcpy ( oprt[0].opr, "800H" ); /* intrupt */
}
}
else if (( copclass & 0xf3ff ) == 0x4032 ) /* push/pop */
{ csize = 'D'; /* double size */
if ( oprt[copr].ofl == 0xE031 ) /* push/pop AF */
{ copclass &= 0x0f0f; /* strip type */
copclass |= 0xd032; /* special#3, W-size */
coptype = ISSPC;
csize = 'B'; /* 2-byte, 1-word push/pops */
}
}
else if ( (oprt[0].ofl & ISPAR ) != 0 )
csize = 'B'; /* something (HL) */
} /* end of copr == 0 */
else /* copr != 0 */
{ xx = oprt[1].ofl & 3;
if (( x = oprt[0].ofl & 3 ) != 0
&& xx != 0 ) /* two sizes */
{ if (x != xx ) /* two different sizes */
csize = 'B';
}
else if ( xx == 2 && (oprt[1].ofl & ISPAR ) != 0 )
csize = 'B';
else if ( x == 2 && (oprt[0].ofl & ISPAR ) != 0 )
csize = 'B';
/* is LD HL,SYMB? */
if ( ( copclass & ISREV ) != 0 )
{ strcpy ( tmpbuf, oprt[0].opr );
strcpy ( oprt[0].opr, oprt[1].opr );
strcpy ( oprt[1].opr, tmpbuf ); /* reverse operands */
}
if ( coptype == ISMOV && x == 2 && oprt[1].ofl == ISSYM )
{ csize = 0;
strcpy ( opcsave, "ADDR" ); /* need address */
}
if ( coptype != ISSPC && oprt[0].ofl == 0xe052 )
/* move to R7 */
{ strcat ( codebuf, "SPR.D SP,R7\r\n\t" );
strcat ( codebuf, opcsave ); /* do to R7 */
if ( csize != 0 ) /* is ADDR? */
strcat ( codebuf, ".W" );
chrcat (codebuf, 9 ); /* tab */
strcat ( codebuf, oprt[1].opr );
strcat ( codebuf, ",R7\r\n\t" );
strcpy ( oprt[0].opr, "R7" ); /* do to R7 */
csize = 'D'; /* make long */
strcpy ( opcsave, "LPR" ); /* > LPR.W SP,?? */
strcpy ( oprt[1].opr, "SP" ); /* is now TOS */
} /* above is a LD/ADD SP,?? - not an EX */
else if ( coptype != ISSPC && oprt[1].ofl == 0xe052 )
{ if ( coptype == ISMOV ) /* is an ld ??,sp */
{ strcpy ( opcsave, "SPR" ); /* > SPR.D SP,?? */
csize = 'D'; /* make long */
strcpy ( oprt[1].opr, "SP" ); /* is now TOS */
}
else /* is an add ??,sp */
{strcat ( codebuf, "SPR.D SP,R7\r\n\t" ); /* move to R7 */
strcpy ( oprt[1].opr, "R7" ); /* change operand */
}
}
}
}
dospcs() /* do special operations */
{ int sptype;
if ((sptype=( copclass & 0x00f0) ) == 0x0010 ) /* is an EX DE,HL */
{ strcat ( codebuf, "MOV.D\t"); /* or EX (SP),?? */
strcat ( codebuf, oprt[0].opr );
strcat ( codebuf, ",R7\r\n\t");
csize = 'D'; /* make long */
doarmov ();
strcat ( codebuf, "\r\n\tMOV.D\tR7,");
strcat ( codebuf, oprt[1].opr );
chrcat ( codebuf, '\t');
}
else if ( sptype == 0x0030 ) /* is a push/pop AF */
{ if (( copclass & NADST ) != 0 ) /* is a push AF */
{strcat (codebuf, "MOVQ.W 0,TOS\r\n\t" ); /* two bytes */
doarmov (); /* then push 'A', then PSR */
strcat (codebuf, "\r\n\tSPR.B\tPSR,TOS");
} /* push AF so if pop BC, A > B */
else /* is pop AF; A > B,D,H; PSR > C,E,L */
{ strcat (codebuf, "AND.B\t0xfd,TOS\r\n\t");
strcat (codebuf, "LPR.B\tPSR,TOS\r\n\t");
doarmov (); /* now pop 'A' */
strcat ( codebuf, "\r\n\t");
strcat (codebuf, "MOV.W TOS,R7" );/* two bytes */
} /* strip 'T' bit , then pop; C,E,L into PSR */
}
else
doarmov (); /* so get something */
}
doarmov()
{ if ( opcsave[0] != 0 )
{ ++i; /* have something */
strcat ( codebuf, opcsave );
if ( csize == 0 /* have no size */
&& (copclass & (NASRC|NADST)) != 0 ) /* should have */
csize = 'B';
if ( csize != 0 )
{ chrcat ( codebuf, '.' );
chrcat ( codebuf, csize );
}
chrcat ( codebuf, '\t' );
}
xx = copr;
while ( xx != 0 )
{ strcat ( codebuf, oprt[xx].opr );
chrcat ( codebuf, ',' );
--xx;
}
if ( copr == 0 )
{ if ((copclass & NAONE ) != 0 )
{ if ((copclass & ISPOS ) != 0 ) /* ADDQ/ASH +1, */
strcat (codebuf, "+1");
else /* ADDQ/ASH/ACB -1 */
strcat (codebuf, "-1");
if (( copclass & NADST ) == 0 )
chrcat ( codebuf, ',' ); /* dont need 2 */
}
if (( copclass & NASRC ) != 0 )
{ if (( x = copclass & 3 ) == 3 )
strcat ( codebuf, "RB" ); /* djnz */
if ( x == 2 )
strcat ( codebuf, "TOS" );
else if ( x == 1 )
strcat ( codebuf, "R0");
if (( copclass & NADST )== 0 || oprt[xx].opr[0] != 0)
chrcat ( codebuf, ',' ); /* dont need 2 */
}
}
if ( oprt[xx].opr[0] != 0 )
strcat ( codebuf, oprt[xx].opr );
if ( copr == 0 && ( copclass & NADST) != 0 )
{ if ((copclass & 3 ) == 2 )
strcat ( codebuf, ",TOS" );
else
strcat ( codebuf, ",R0" );
}
}
doprfl()
{ ++i; /* have something */
if ( coptype == ISRET && oprt[0].opr[0] != 0 )
dofprfl (); /* have a cond return */
else if ( coptype == ISBSR && copr != 0 )
dofprfl (); /* have a cond call */
else /* have uncond call, return or cond. BR; handle here */
{ if ( copr != 0 ) /* have a conditional BR */
{ i = oprt[0].ofl & 7;
docond ( i + 10 );
strcat ( codebuf, tmpbuf ); /* copy docond */
}
else
{ strcat ( codebuf, opcsave );
if ( coptype == ISBR ) /* have only a 'B' */
chrcat ( codebuf, 'R' );
}
chrcat ( codebuf, '\t' );
if ( oprt[copr].opr[0] != 0 )
strcat ( codebuf, oprt[copr].opr );
else /* have a unconditional ret */
lsttype = 0; /* clear last-type */
}
}
/* on conditional calls or returns, perform test (reversed)
over call or return, put in branch symbol.
ie;
CALL Z,SYMB
becomes;
BNE XYZ#
BSR SYMB
XYZ#:
*/
dofprfl() /* do fancy program-flow */
{
i = oprt[0].ofl & 7; /* isolate condition */
docond ( i ); /* do the conditional */
strcat ( codebuf, tmpbuf ); /* now put in */
strcat ( codebuf, "\t" ); /* do short branch */
sprintf ( tmpbuf, "XYZ%d",++cursym ); /* put in branch destination */
strcat (codebuf, tmpbuf );
strcat ( codebuf, "\r\n" ); /* new line */
chrcat ( codebuf, '\t' ); /* tab over */
strcat ( codebuf, opcsave ); /* put out opcode */
if ( coptype == ISBSR ) /* have a conditional call*/
{ chrcat ( codebuf, '\t' );
strcat ( codebuf, oprt[copr].opr );
}
strcat (symsave, tmpbuf ); /* put in for next line */
chrcat ( symsave, ':' ); /* add colon */
}
/* i's 1 to 6 = comp flags reversed.
10 - 16 = comp flags
20 - 26 = arithm flags reversed.
30 - 36 = arithm flags.
Remember, Z-80 comps are; A vs ??, NS are ?? vs R0,
Ie., reversed.
*/
docond( cond )
int cond;
{ i = cond % 10; /* see what is */
if ( lsttype == ISARI )
{ if ( i == 1 || i == 2 ) /* is a C, NC test */
cond += 20; /* make arithmet test */
else /* do zero, sign test */
strcat (codebuf,"CMPQ.B 0,R0\r\n\t"); /* compare */
}
else if ( lsttype != ISXXX && lsttype != ISCMP )
{ strcat (codebuf,"CMPQ.B 0,R0\r\n\t"); /* compare */
}
chrcat ( codebuf, 'B' ); /* OK to put in now */
switch ( cond )
{ case 1: /* are for reversed compar flags */
strcpy (tmpbuf,"LS"); /* orig=C > LS */
break;
case 2:
strcpy (tmpbuf,"HI"); /* orig=NC > HI */
break;
case 3:
strcpy (tmpbuf,"NE"); /* orig=Z > NE */
break;
case 4:
strcpy (tmpbuf,"EQ"); /* orig=NZ > EQ */
break;
case 5:
strcpy (tmpbuf,"LE"); /* orig=M > LE 0 */
break;
case 6:
strcpy (tmpbuf,"GT"); /* orig=P > GT 0 */
break;
case 11: /* are for direct cmp flags */
strcpy (tmpbuf,"HI"); /* orig=C > HI */
break;
case 12:
strcpy (tmpbuf,"LS"); /* orig=NC > LS */
break;
case 13:
strcpy (tmpbuf,"EQ"); /* orig=Z > NE */
break;
case 14:
strcpy (tmpbuf,"NE"); /* orig=NZ > EQ */
break;
case 15:
strcpy (tmpbuf,"GT"); /* orig=M > GT 00H */
break;
case 16:
strcpy (tmpbuf,"LE"); /* orig=P > LE 00H */
break;
case 21: /* are for reversed arith flags */
strcpy (tmpbuf,"CC"); /* orig=C > CC */
break;
case 22:
strcpy (tmpbuf,"CS"); /* orig=NC > CS */
break;
case 31: /* are direct arith flags */
strcpy (tmpbuf,"CS"); /* orig=C > CS */
break;
case 32:
strcpy (tmpbuf,"CC"); /* orig=NC > CC */
break;
default:
strcpy ( tmpbuf,"??");
++cerror;
}
}
chrcat( ptr, chr ) /* character concatenate */
char *ptr;
char chr;
{
while ( *ptr != 0)
++ptr; /* go to null */
*ptr++ = chr;
*ptr = 0;
}
/* end of TNZ.C 03/26/86, R. A. Campbell */
/*
.ll 79
TNZ2.C I/O routines and utilities
TNZH.C is header/definitions,
TNZO.C is opcode/register table
for Z80 to NS-320XX Translater
CLINK - TNZ, TNZ2 - R. A. Campbell; 03/26/86
*/
/* If Z80, uncomment following two lines
*/
#define Z80 1
#include "bdscio.h"
/* if not Z80, uncomment following line
#include "niohe.c"
*/
/* always; */
#include "tnzh.c"
initas() /* check input mode, open disk files */
{ int lnum; /* declare local n */
printf(BANNER);
if (argc < 2)
{ printf(" Aborting; No Filename(s) specified \n");
exit ();
}
switbuf[0] = 0; /* rescue switches */
if ( *argv[argc-1] == '-' )
{ strcpy (switbuf,argv[argc-1]);
argc--; /* decrm arg count */
}
i = swlist = swsymbol = swdebug = bquit = 0;
cursym = swstinit = 0;
swoutput = 'M';
if (( t = switbuf[i++] ) != 0 )
{ while ( ( t = switbuf[i++] ) != 0 )
{ switch ( t )
{ case '0': /* turn off all switches */
{ swsymbol = swlist = NULL;
swoutput = swdebug = NULL;
break;
}
case 'D': /* CP/M capitalizes */
{ swsymbol = swlist = swdebug = t;
swoutput = 0;
break;
}
case 'L': /* listing output */
swlist = t;
break;
case ',':
break; /* walk over commas */
default:
badswitch ();
}
}
}
if ( swoutput != 0 ) /* are to output? */
{ strcpy (outnamebf,argv[1]); /* setup output name */
strcat (outnamebf,".N32"); /* translated output */
#ifdef Z80
if (( outfd = fcreat (outnamebf,outbuf)) == ERROR )
#else
if (( outfd = fopen (outnamebf, "W" )) == ERROR )
#endif
{ printf (" Unable to open: %s\n", outnamebf);
exit ();
}
}
#ifdef Z80
if ((infd = fopen ("TNZO.C",inbuf)) == ERROR )
#else
if ((infd = fopen ("TNZO.C", "R")) == ERROR)
#endif
{ printf ("Unable to open Table File\n");
exit ();
}
lnum = 0;
while ( bquit == NULL && (fgets (linebuf,inbuf) != FGERR )
&& (lnum < NOPCDS)) /* chck one line of opcd table */
{ inbcount = 0; /* start line */
t = getword ( );
if (t == LETTER)
{ strcpy ( keytab[lnum].inword, wordbuf);
while ( getword () == SPACE ) /* ignore tab/space */
; /* next word */
strcpy ( keytab[lnum].outword, wordbuf);
keytab[lnum].opclass = getint ();
keytab[lnum].opmod = getint ();
lnum++;
}
} /* keep reading file */
if ( infd = fclose (inbuf) == -1 ) /* close file */
printf("\n Unable to close OPC file \n");
}
badswitch()
{ printf( "Incorrect switches; %s \n", switbuf);
printf(" Must start with a '-', minus\n");
printf("Choices are; 0= no outputs, errors only;\n");
printf(" D= debug; L= listing;\n");
exit ();
}
#ifdef Z80
quitck() /* check for user quitting */
{ char c;
if ( kbhit () ) /* character waiting? */
{ c = getchar ();
if ( c < ' ' ) /* a control char ? */
exit ();
}
}
#endif
listout() /* printouts for listing */
{ x = 0;
if ( swdebug != 0 )
{ printf ("I= "); /* indicat input text */
printf("%s",linebuf); /* print source text */
printf ("O= "); /* indicate output */
}
printf("%s",codebuf); /* print source text */
}
chnpage() /* increment line count, new page?? */
{
}
outcode() /* output code */
{ if ( swoutput == 0 )
return; /* not to output */
i = 0;
while ( codebuf[i] != 0 )
{ if ( putc ( codebuf[i++] , outbuf ) == ERROR )
{ printf("\n Aborting; Write Error \n");
exit ();
}
}
}
dostart() /* output id stuff at beginning of file */
{ pout ( BANNER ); /* identify translation */
pout ( "\tSTATIC 0" ); /* RA is in real R4; safe, comparison */
pout ( "RC: BYTE" ); /* stored high - low, reverse */
pout ( "RB: BYTE" ); /* make longs, if pointer */
pout ( " WORD" ); /* for pointers */
pout ( "RE: BYTE" );
pout ( "RD: BYTE" );
pout ( " WORD" ); /* for pointers */
pout ( "RL: BYTE" );
pout ( "RH: BYTE" );
pout ( " WORD" ); /* for pointers */
pout ( "RX: LONG" );
pout ( "RY: LONG" );
pout ( "\tPROGRAM" );
pout ( "Q_start:\tJUMP Q_shell" );
pout ( "\tIMPORT Q_shell" ); /* nlint puts in # */
pout ( "Qmain:" ); /* for linking & (HL) jumps */
}
pout ( ptr )
char *ptr;
{ strcpy ( codebuf, ptr);
strcat ( codebuf, "\r\n" );
if ( swdebug != 0 || swlist != 0 )
printf ( "%s", codebuf );
outcode ();
}
dofinish()
{
for ( x = 0; x<128; ++x )
putchr (CPMEOF);
fflush ( outbuf );
fclose ( outbuf );
printf (" %d Lines Processed, %d Problems\n", nlines, nerrors );
}
binary( sptr ) /* find word in keytab[0] .. tab [n-1] */
char *sptr;
{ register long low, high, mid, cond;
low = 0;
high = NOPCDS -1;
while (low <= high)
{ mid = (low + high) / 2;
if (( cond = strcmp( sptr, keytab[mid].inword)) < 0)
high = mid -1;
else if (cond > 0)
low = mid + 1;
else
return mid;
}
return -1;
}
putchr( chr )
char chr;
{ if ( putc ( chr,outbuf ) == ERROR )
{ printf("\n Write Error \n");
fclose ( outbuf );
exit ();
}
}
getint() /* get integer from input */
{ int val, ishex, sign;
unsigned valh;
char c;
ishex = val = valh = 0;
sign = 1;
while ( (c = getchr ()) == ' ' || c == '\t' )
; /* skip white space */
ugetch (); /* back up */
if ( c == '+' )
; /* ignore it */
else if ( c == '-' )
sign = -1;
if ( isdigit (c) == 0 )
return valh;
while ( isdigit (c = getchr () )
|| (( c = toupper (c)-7) > '9' && c < '@')
|| c == 'X'-7 || c == 'H'-7 ) /* is digit/H,X */
{ if ( c == 'X'-7 || c == 'H'-7 ) ishex = 1;
else
{ val = val * 10 + c - '0';
valh=(valh<<4) + c-'0';
}
}
if ( ishex != 0 )
return valh;
val *= sign;
return val;
}
cwdbftl() /* convert word buffer to lower case */
{ x = 0;
while ( ( c = wordbuf[x] ) != 0 )
{ if (c >= 'A' && c <= 'Z') /* conv upper to lower */
wordbuf[x] = c + 32;
x++;
}
}
getword( ) /* get word from input */
{ char *w; /* put in wordbuf */
int lim, t;
lim = MAXWORD;
w = wordbuf;
if ( ( t = typeof ( *w++ = c = getchr () ) ) != LETTER)
{ *w = '\0';
return t;
}
while (--lim > 0)
{ t = typeof ( *w++ = c = getchr () );
if ( t != LETTER && t != DIGIT
&& t != '.' && t != '_' )
{ ugetch ();
break;
}
}
*( w-1 ) = '\0';
if ( cerror == 0 ) /* copy for error report */
strcpy (errorbuf, wordbuf );
if ( lim > 0 )
return LETTER;
while ( t = typeof ( getchr () ) == LETTER || t == DIGIT )
; /* walk over rest of word */
ugetch ();
return LETTER ;
}
ugetch()
{ inbcount--;
}
getchr() /* get character from disk file */
{ int c;
c = getdin (); /* get input from disk file */
if ( c == 0 || c == EOF || c == CPMEOF )
{ c = '\n'; /* new line */
bquit++;
}
return ( c );
}
getdin() /* get character from disk file */
{ int c;
c = linebuf [inbcount++] & 0x7F;
return c;
}
typeof(c) /* return type of ASCII character */
char c;
{ if ( c >= 'a' && c <= 'z')
return LETTER;
else if ( c >= 'A' && c <= 'Z' )
return LETTER;
else if ( c >= '0' && c <= '9' )
return DIGIT; /* if digit */
else if ( c == SPACE || c == '\t' )
return SPACE;
else if ( c == 0xa || c ==0xd )
return '\n'; /* an end of line!!! */
else
return c;
}
/* end TNZ2.C 03/26/86 */
/* Input/ output opcodes for Z80 to NS320XX Translater,
/* MUST BE IN ALPHABETICAL ORDER FOR BINARY SEARCH TO WORK
/* FIRST CHAR OF LINE MUST BE 'LETTER' OTHERWISE
/* LINE SKIPPED, RAC 03/26/86. HAS 70 entries
/* classes are (all numbers in hex) */
/* TMASK = 0Xf000 - mask for type of opc/operand */
/* ISFLG = 0XF000 - is a flag */
/* ISREG = 0XE000 - is a register */
/* ISSPC = 0XD000 - is a special operation; EX, */
/* ISPBIT= 0XA000 - is a PSR bit operation */
/* ISBIT = 0X9000 - is a bit operation */
/* BYTEPS= 0X8000 - define byte(s) */
/* ENDPS = 0X7000 - end pseudo-operator */
/* ISMOV = 0X5000 - is a ld/mov instruction */
/* NOOPRS = 0X4000 - simple opcode, no fancy stuff */
/* these prog-flow must be from 0X1000 to 0X3000 */
/* ISRET = 0X3000 - is a return instruction */
/* ISBSR = 0X2000 - is a call/branch to subroutine */
/* ISBR = 0X1000 - is a branch/jump */
/* modifiers */
/* NADST = 0X0800 - needs a destination */
/* NASRC = 0X0400 - needs a source */
/* NAONE = 0X0200 - needs a +1 or -1 */
/* ISPRB = 0X0100 - may be a problem */
/* ISPOS = 0X0008 - is a +1 */
/* ISREV = 0X0004 - operands reversed */
/* opmod modifiers */
/* ISCMP = 0X8000 - is a comparision, re flags */
/* ISARI = 0X4000 - is an arithmetic */
/* ISXXX = 0X2000 - is altering; call */
/* ISNOT = 0X1000 - is a 'nothing' operation re flags */
/* ISLOG = 0X0800 - is a logical operation */
/* Following are pseudo-ops */
/* REGISTERS
/* Z-80 = NS-320XX
/* A, AF = R0
/* C, BC = R1
/* E, DE = R2
/* L, HL = R3
/* IX = R4
/* IY = R5 */
/* name - opcode - class - mod - comment */
a R0 0xe001 0x0000 /* single register, use R0 */
adc ADDC 0x4801 0x4000 /* opcode + data byte */
add ADD 0x4801 0x4000 /* may need byte dest */
af R0 0xe031 0x0000 /* double register, R0 & spc */
and AND 0x4801 0x0800
b RB 0xe001 0x0000 /* register 'B' */
bc R1 0xe002 0x0000 /* double register 'BC' */
bit TBIT 0x4005 0x0000 /* test bit */
c R1 0xe001 0x0000 /* register 'C', also carry flag */
call BSR 0x2000 0x2000
ccf BICPSR 0xa101 0x0001 /* compl carry flag, psr bit 1 */
cp CMP 0x4801 0x8000
cpl COM 0x4c01 0x0800
d RD 0xe001 0x0000
de R2 0xe002 0x0000 /* register */
dec ADDQ 0x4200 0x4000 /* needs a -1 */
defb BYTE 0x8000 0x1000 /* define byte(s) */
defi WORD 0x8000 0x1000 /* define item(bytes reversed) */
defs BLK.B 0x4000 0x1000 /* define space */
defw WORD 0x8000 0x1000 /* define two-byte word */
di BICPSR 0xa400 0x100c /* clear psr bit indicated */
djnz ACB 0x4603 0x1000 /* decrement B, jump if not zero */
e R2 0xe001 0x0000
ei BISPSR 0xa002 0x000c /* set 12th bit */
end END 0x7000 0x1000 /* pseudo op */
equ EQU 0x4000 0x0000 /* pseudo op */
ex MOV 0xd012 0x1000 /* special operation, word-size */
extrn EXTRN 0x4000 0x0000
h RH 0xe001 0x0000
halt WAIT 0x4000 0x1000
hl R3 0xe002 0x000c /* register */
in NOP 0x4100 0x0000
inc ADDQ 0x4208 0x4000 /* needs a +1 */
ix R4 0xe002 0x000d
iy R5 0xe002 0x000e /* IX, IY registers */
jp B 0x1020 0x1000
jr B 0x1020 0xl000
l R3 0xe001 0x0000
ld MOV 0x5000 0x1000
lddr MOV 0xd091 0x8000
ldir MOV 0xd071 0x8000 /* special, byte sized */
loff LOFF 0x4000 0x1000 /* turn printer on/ off */
lon LON 0x4000 0x1000
m LS 0xf105 0x0000
nc CC 0xf102 0x0000
neg NEG 0x4c01 0x0800
nop NOP 0x4000 0x1000
nz NE 0xf004 0x0000
or OR 0x4801 0x0800
org LOC 0x4000 0x0000 /* org pseudo-op */
out NOP 0x4100 0x0000
p HI 0xf106 0x0000
pop MOV 0x4432 0x1000 /* needs source */
push MOV 0x4832 0x1000 /* needs destination */
res BIC 0x4005 0x1000
ret RET 0x3000 0x1000
rl ROT 0x4219 0x0800
rla ROT 0x4b19 0x0800
rlc ROT 0x4219 0x0800
rlca ROT 0x4b19 0x0800
rr ROT 0x4211 0x0800
rra ROT 0x4b11 0x0800
rrca ROT 0x4b11 0x0800
sbc SUBC 0x4801 0x4000
scf BISPSR 0xa001 0x4001 /* set carry bit */
set BIS 0x4005 0x1000
sp TOS 0xe052 0x0000 /* privileged register */
sub SUB 0x4801 0x4000
xor XOR 0x4801 0x0800
z EQ 0xf003 0x0000