[comp.sources.amiga] v89i055: moto-assem - m68k assember from motorola's bbs, Part01/02

page@swan.ulowell.edu (Bob Page) (03/16/89)

Submitted-by: gmg@hcx.uucp (Greg Garner)
Posting-number: Volume 89, Issue 55
Archive-name: langauges/moto-assem.1

These files came from the Motorola Freeware BBS. Their BBS now has an
amiga upload/download section (YEA!). I obtained explicit permission
to post these to comp.sources.amiga and also to give these files to
Fred Dish for inclusion in one of his disks.

#	This is a shell archive.
#	Remove everything above and including the cut line.
#	Then run the rest of the file through sh.
#----cut here-----cut here-----cut here-----cut here----#
#!/bin/sh
# shar:    Shell Archiver
#	Run the following text with /bin/sh to create:
#	AS.C
#	AS.H
#	AS0.C
#	AS1.C
#	AS11.C
#	AS4.C
#	AS5.C
#	AS9.C
#	DO0.C
#	DO1.C
#	DO11.C
#	DO4.C
#	DO5.C
#	DO9.C
#	FFWD.C
#	OUTPUT.C
#	PSEUDO.C
# This archive created: Wed Mar 15 13:33:52 1989
cat << \SHAR_EOF > AS.C
char mapdn();
char *alloc();
/*
 *	as ---	cross assembler main program
 */
main(argc,argv)
int	argc;
char	**argv;
{
	char	**np;
	char	*i;
	FILE	*fopen();
	int	j = 0;

	if(argc < 2){
		printf("Usage: %s [files]\n",argv[j]);
		exit(1);
		}
	  Argv = argv;
	  initialize();
	  while ((*argv[j] != '-') && (j<argc))
	   j++;
	  N_files = j-1;
	 if (j < argc )
	  {
	  argv[j]++;
	  while (j<argc)
	   {
	   for (i = argv[j]; *i != 0; i++)
	     if ((*i <= 'Z') && (*i >= 'A'))
	       *i = *i + 32;
	   if (strcmp(argv[j],"l")==0)
	     Lflag = 1;
	   else if (strcmp(argv[j],"nol")==0)
	     Lflag = 0;
	   else if (strcmp(argv[j],"c")==0)
	      Cflag = 1;
	   else if (strcmp(argv[j],"noc")==0)
	     Cflag = 0;
	   else if (strcmp(argv[j],"s")==0)
	     Sflag = 1;
	   else if (strcmp(argv[j],"cre")==0)
	     CREflag = 1;
	    j++;
	   }
	  }
	root = NULL;

	Cfn = 0;
	np = argv;
	Line_num = 0; /* reset line number */
	while( ++Cfn <= N_files )
		if((Fd = fopen(*++np,"r")) == NULL)
			printf("as: can't open %s\n",*np);
		else{
			make_pass();
			fclose(Fd);
		}
	if( Err_count == 0 ){
		Pass++;
		re_init();
		Cfn = 0;
		np = argv;
		Line_num = 0;
		while( ++Cfn <= N_files)
			if((Fd = fopen(*++np,"r")) != NULL)
			    {
				make_pass();
				fclose(Fd);
			     }
			if (Sflag == 1)
			  {
			    printf ("\f");
			    stable (root);
			  }
			if (CREflag == 1)
			  {
			    printf ("\f");
			    cross (root);
			  }
		fprintf(Objfil,"S9030000FC\r\n"); /* at least give a decent ending */
		}
	exit(Err_count);
}

initialize()
{
	FILE	*fopen();
	int	i = 0;

#ifdef DEBUG
	printf("Initializing\n");
#endif
	Err_count = 0;
	Pc	  = 0;
	Pass	  = 1;
	Lflag	  = 0;
	Cflag	  = 0;
	Ctotal	  = 0;
	Sflag	  = 0;
	CREflag   = 0;
	N_page	  = 0;
	Line[MAXBUF-1] = NEWLINE;

	strcpy(Obj_name,Argv[1]); /* copy first file name into array */
	do {
	    if (Obj_name[i]=='.')
	       Obj_name[i]=0;
	}
	while (Obj_name[i++] != 0);
	strcat(Obj_name,".s19");  /* append .out to file name. */
	if( (Objfil = fopen(Obj_name,"w")) == NULL)
		fatal("Can't create object file");
	fwdinit();	/* forward ref init */
	localinit();	/* target machine specific init. */
}

re_init()
{
#ifdef DEBUG
	printf("Reinitializing\n");
#endif
	Pc	= 0;
	E_total = 0;
	P_total = 0;
	Ctotal	= 0;
	N_page	= 0;
	fwdreinit();
}

make_pass()
{
	char	*fgets();

#ifdef DEBUG
	printf("Pass %d\n",Pass);
#endif
	while( fgets(Line,MAXBUF-1,Fd) != (char *)NULL ){
		Line_num++;
		P_force = 0;	/* No force unless bytes emitted */
		N_page = 0;
		   if(parse_line())
			process();
		if(Pass == 2 && Lflag && !N_page)
			print_line();
		P_total = 0;	/* reset byte count */
		Cycles = 0;	/* and per instruction cycle count */
		}
	f_record();
}


/*
 *	parse_line --- split input line into label, op and operand
 */
parse_line()
{
	register char *ptrfrm = Line;
	register char *ptrto = Label;
	char	*skip_white();

	if( *ptrfrm == '*' || *ptrfrm == '\n' )
		return(0);	/* a comment line */

	while( delim(*ptrfrm)== NO )
		*ptrto++ = *ptrfrm++;
	if(*--ptrto != ':')ptrto++;     /* allow trailing : */
	*ptrto = EOS;

	ptrfrm = skip_white(ptrfrm);

	ptrto = Op;
	while( delim(*ptrfrm) == NO)
		*ptrto++ = mapdn(*ptrfrm++);
	*ptrto = EOS;

	ptrfrm = skip_white(ptrfrm);

	ptrto = Operand;
	while( *ptrfrm != NEWLINE )
		*ptrto++ = *ptrfrm++;
	*ptrto = EOS;

#ifdef DEBUG
	printf("Label-%s-\n",Label);
	printf("Op----%s-\n",Op);
	printf("Operand-%s-\n",Operand);
#endif
	return(1);
}

/*
 *	process --- determine mnemonic class and act on it
 */
process()
{
	register struct oper *i;
	struct oper *mne_look();

	Old_pc = Pc;		/* setup `old' program counter */
	Optr = Operand; 	/* point to beginning of operand field */

	if(*Op==EOS){		/* no mnemonic */
		if(*Label != EOS)
			install(Label,Pc);
		}
	else if( (i = mne_look(Op))== NULL)
		error("Unrecognized Mnemonic");
	else if( i->class == PSEUDO )
		do_pseudo(i->opcode);
	else{
		if( *Label )install(Label,Pc);
		if(Cflag)Cycles = i->cycles;
		do_op(i->opcode,i->class);
		if(Cflag)Ctotal += Cycles;
		}
}
SHAR_EOF
cat << \SHAR_EOF > AS.H
/*
 *      machine independent definitions and global variables
 */

#define YES     1
#define NO      0
#define ERR     (-1)

#define MAXBUF  128
#define MAXOP   10      /* longest mnemonic */
#define MAXLAB  16
#define E_LIMIT 32
#define P_LIMIT 64

/*      Character Constants     */
#define NEWLINE '\n'
#define TAB     '\t'
#define BLANK   ' '
#define EOS     '\0'

/*      Opcode Classes          */
#define INH     0       /* Inherent                     */
#define GEN     1       /* General Addressing           */
#define IMM     2       /* Immediate only               */
#define REL     3       /* Short Relative               */
#define P2REL   4       /* Long Relative                */
#define P1REL   5       /* Long Relative (LBRA and LBSR)*/
#define NOIMM   6       /* General except for Immediate */
#define P2GEN   7       /* Page 2 General               */
#define P3GEN   8       /* Page 3 General               */
#define RTOR    9       /* Register To Register         */
#define INDEXED 10      /* Indexed only                 */
#define RLIST   11      /* Register List                */
#define P2NOIMM 12      /* Page 2 No Immediate          */
#define P2INH   13      /* Page 2 Inherent              */
#define P3INH   14      /* Page 3 Inherent              */
#define GRP2    15      /* Group 2 (Read/Modify/Write)  */
#define LONGIMM 16      /* Immediate mode takes 2 bytes */
#define BTB     17      /* Bit test and branch          */
#define SETCLR  18      /* Bit set or clear             */
#define CPD     19      /* compare d               6811 */
#define XLIMM   20      /* LONGIMM for X           6811 */
#define XNOIMM  21      /* NOIMM for X             6811 */
#define YLIMM   22      /* LONGIMM for Y           6811 */
#define YNOIMM  23      /* NOIMM for Y             6811 */
#define FAKE    24      /* convenience mnemonics   6804 */
#define APOST   25      /* A accum after opcode    6804 */
#define BPM     26      /* branch reg plus/minus   6804 */
#define CLRX    27      /* mvi x,0                 6804 */
#define CLRY    28      /* mvi y,0                 6804 */
#define LDX     29      /* mvi x,expr              6804 */
#define LDY     30      /* mvi y,expr              6804 */
#define MVI     31      /* mvi                     6804 */
#define EXT     32      /* extended                6804 */
#define BIT     33      /* bit manipulation        6301 */
#define SYS     34      /* syscalls (really swi)        */
#define PSEUDO  35      /* Pseudo ops                   */

/* global variables */
int     Line_num =0;            /* current line number          */
int     Err_count =0;           /* total number of errors       */
char    Line[MAXBUF] = {0};     /* input line buffer            */
char    Label[MAXLAB] = {0};    /* label on current line        */
char    Op[MAXOP] = {0};        /* opcode mnemonic on current line      */
char    Operand[MAXBUF] = {0};  /* remainder of line after op           */
char    *Optr =0;               /* pointer into current Operand field   */
int     Result =0;              /* result of expression evaluation      */
int     Force_word =0;          /* Result should be a word when set     */
int     Force_byte =0;          /* Result should be a byte when set     */
int     Pc =0;                  /* Program Counter              */
int     Old_pc =0;              /* Program Counter at beginning */

int     Last_sym =0;            /* result of last lookup        */

int     Pass =0;                /* Current pass #               */
int     N_files =0;             /* Number of files to assemble  */
FILE    *Fd =0;                 /* Current input file structure */
int     Cfn =0;                 /* Current file number 1...n    */
int     Ffn =0;                 /* forward ref file #           */
int     F_ref =0;               /* next line with forward ref   */
char    **Argv =0;              /* pointer to file names        */

int     E_total =0;             /* total # bytes for one line   */
int     E_bytes[E_LIMIT] = {0}; /* Emitted held bytes           */
int     E_pc =0;                /* Pc at beginning of collection*/

int     Lflag = 0;              /* listing flag 0=nolist, 1=list*/

int     P_force = 0;            /* force listing line to include Old_pc */
int     P_total =0;             /* current number of bytes collected    */
int     P_bytes[P_LIMIT] = {0}; /* Bytes collected for listing  */

int     Cflag = 0;              /* cycle count flag */
int     Cycles = 0;             /* # of cycles per instruction  */
long    Ctotal = 0;             /* # of cycles seen so far */
int     Sflag = 0;              /* symbol table flag, 0=no symbol */
int     N_page = 0;             /* new page flag */
int     Page_num = 2;           /* page number */
int     CREflag = 0;            /* cross reference table flag */

struct link { /* linked list to hold line numbers */
       int L_num; /* line number */
       struct link *next; /* pointer to next node */
};

struct nlist { /* basic symbol table entry */
        char    *name;
        int     def;
        struct nlist *Lnext ; /* left node of the tree leaf */
        struct nlist *Rnext; /* right node of the tree leaf */ 
        struct link *L_list; /* pointer to linked list of line numbers */
};

struct oper {   /* an entry in the mnemonic table */
        char    *mnemonic;      /* its name */
        char    class;          /* its class */
        int     opcode;         /* its base opcode */
        char    cycles;         /* its base # of cycles */
};

struct  nlist *root;            /* root node of the tree */
  
FILE    *Objfil =0;             /* object file's file descriptor*/
char    Obj_name[] = {"             "};
SHAR_EOF
cat << \SHAR_EOF > AS0.C
#include <stdio.h>
#include "as.h"
#include "table0.h"
#include "as.c"
#include "do0.c"
#include "pseudo.c"
#include "eval.c"
#include "symtab.c"
#include "util.c"
#include "ffwd.c"
#include "output.c"
SHAR_EOF
cat << \SHAR_EOF > AS1.C
#include <stdio.h>
#include "as.h"
#include "table1.h"
#include "as.c"
#include "do1.c"
#include "pseudo.c"
#include "eval.c"
#include "symtab.c"
#include "util.c"
#include "ffwd.c"
#include "output.c"

SHAR_EOF
cat << \SHAR_EOF > AS11.C
#include <stdio.h>
#include "as.h"
#include "table11.h"
#include "as.c"
#include "do11.c"
#include "pseudo.c"
#include "eval.c"
#include "symtab.c"
#include "util.c"
#include "ffwd.c"
#include "output.c"
SHAR_EOF
cat << \SHAR_EOF > AS4.C
#include <stdio.h>
#include "as.h"
#include "table4.h"
#include "as.c"
#include "do4.c"
#include "pseudo.c"
#include "eval.c"
#include "symtab.c"
#include "util.c"
#include "ffwd.c"
#include "output.c"
SHAR_EOF
cat << \SHAR_EOF > AS5.C
#include <stdio.h>
#include "as.h"
#include "table5.h"
#include "as.c"
#include "do5.c"
#include "pseudo.c"
#include "eval.c"
#include "symtab.c"
#include "util.c"
#include "ffwd.c"
#include "output.c"

SHAR_EOF
cat << \SHAR_EOF > AS9.C
#include <stdio.h>
#include "as.h"
#include "table9.h"
#include "as.c"
#include "do9.c"
#include "pseudo.c"
#include "eval.c"
#include "symtab.c"
#include "util.c"
#include "ffwd.c"
#include "output.c"

SHAR_EOF
cat << \SHAR_EOF > DO0.C
/*
 *	MC6800/02 specific processing
 */

/* addressing modes */
#define IMMED	0	/* immediate */
#define IND	1	/* indexed */
#define OTHER	2	/* NOTA */

/*
 *	localinit --- machine specific initialization
 */
localinit()
{
}

/*
 *	do_op --- process mnemonic
 *
 *	Called with the base opcode and it's class. Optr points to
 *	the beginning of the operand field.
 */
do_op(opcode,class)
int opcode;	/* base opcode */
int class;	/* mnemonic class */
{
	int	dist;	/* relative branch distance */
	int	amode;	/* indicated addressing mode */
	char	*peek;

	/* guess at addressing mode */
	peek = Optr;
	amode = OTHER;
	while( !delim(*peek) && *peek != EOS)  /* check for comma in operand field */
		if( *peek++ == ',' ){
			amode = IND;
			break;
			}
	if( *Optr == '#' ) amode = IMMED;

	switch(class){
		case INH:			/* inherent addressing */
			emit(opcode);
			return;
		case GEN:			/* general addressing */
			do_gen(opcode,amode);
			return;
		case REL:			/* relative branches */
			eval();
			dist = Result - (Pc+2);
			emit(opcode);
			if( (dist >127 || dist <-128) && Pass==2){
				error("Branch out of Range");
				emit(lobyte(-2));
				return;
				}
			emit(lobyte(dist));
			return;
		case NOIMM:
			if( amode == IMMED){
				error("Immediate Addressing Illegal");
				return;
				}
			if((opcode == 0x8D) && (amode == IND)){
				Cycles-=2;
				}
			do_gen(opcode,amode);

			return;
		case LONGIMM:
			if( amode == IMMED ){
				emit(opcode);
				Optr++;
				eval();
				eword(Result);
				return;
				}
			do_gen(opcode,amode);
			return;
		case GRP2:
			if( amode == IND ){
				Cycles++;
				do_indexed(opcode);
				return;
				}
			/* extended addressing */
			eval();
			emit(opcode+0x10);
			eword(Result);
			return;
		default:
			fatal("Error in Mnemonic table");
		}
}

/*
 *	do_gen --- process general addressing modes
 */
do_gen(op,mode)
int	op;
int	mode;
{
	if( mode == IMMED){
		Optr++;
		emit(op);
		eval();
		emit(lobyte(Result));
		return;
		}
	else if( mode == IND ){
		Cycles+=3;
		do_indexed(op+0x20);
		return;
		}
	else if( mode == OTHER){
		eval();
		if(Force_word){
			emit(op+0x30);
			eword(Result);
			Cycles+=2;
			return;
			}
		if(Force_byte){
			emit(op+0x10);
			emit(lobyte(Result));
			Cycles++;
			return;
			}
		if(Result>=0 && Result <=0xFF){
			emit(op+0x10);
			emit(lobyte(Result));
			Cycles++;
			return;
			}
		else {
			emit(op+0x30);
			eword(Result);
			Cycles+=2;
			return;
			}
		}
	else {
		error("Unknown Addressing Mode");
		return;
		}
}

/*
 *	do_indexed --- handle all wierd stuff for indexed addressing
 */
do_indexed(op)
int op;
{
	emit(op);
	eval();
	if( mapdn(*++Optr) != 'x' )
		warn("Indexed Addressing Assumed");
	if( Result < 0 || Result > 255)
		warn("Value Truncated");
	emit(lobyte(Result));
}
SHAR_EOF
cat << \SHAR_EOF > DO1.C
/*
 *      MC6801 specific processing
 */

/* addressing modes */
#define IMMED   0       /* immediate */
#define IND     1       /* indexed */
#define OTHER   2       /* NOTA */

/*
 *      localinit --- machine specific initialization
 */
localinit()
{
}

/*
 *      do_op --- process mnemonic
 *
 *	Called with the base opcode and it's class. Optr points to
 *	the beginning of the operand field.
 */
do_op(opcode,class)
int opcode;	/* base opcode */
int class;	/* mnemonic class */
{
	int     dist;   /* relative branch distance */
	int     amode;  /* indicated addressing mode */
	char	*peek;

	/* guess at addressing mode */
	peek = Optr;
	amode = OTHER;
	while( !delim(*peek) && *peek != EOS)  /* check for comma in operand field */
		if( *peek++ == ',' ){
			amode = IND;
			break;
			}
	if( *Optr == '#' ) amode = IMMED;

	switch(class){
		case INH:                       /* inherent addressing */
			emit(opcode);
			return;
		case GEN:                       /* general addressing */
			do_gen(opcode,amode);
			return;
		case REL:                       /* relative branches */
			eval();
			dist = Result - (Pc+2);
			emit(opcode);
			if( (dist >127 || dist <-128) && Pass==2){
				error("Branch out of Range");
				emit(lobyte(-2));
				return;
				}
			emit(lobyte(dist));
			return;
		case NOIMM:
			if( amode == IMMED){
				error("Immediate Addressing Illegal");
				return;
				}
			do_gen(opcode,amode);
			return;
		case LONGIMM:
			if( amode == IMMED ){
				emit(opcode);
				Optr++;
				eval();
				eword(Result);
				return;
				}
			do_gen(opcode,amode);
			return;
		case GRP2:
			if( amode == IND ){
				do_indexed(opcode);
				return;
				}
			/* extended addressing */
			eval();
			emit(opcode+0x10);
			eword(Result);
			return;
		default:
			fatal("Error in Mnemonic table");
		}
}

/*
 *      do_gen --- process general addressing modes
 */
do_gen(op,mode)
int     op;
int     mode;
{
	if( mode == IMMED){
		Optr++;
		emit(op);
		eval();
		emit(lobyte(Result));
		return;
		}
	else if( mode == IND ){
		Cycles+=2;
		do_indexed(op+0x20);
		return;
		}
	else if( mode == OTHER){
		eval();
		if(Force_word){
			emit(op+0x30);
			eword(Result);
			Cycles+=2;
			return;
			}
		if(Force_byte){
			emit(op+0x10);
			emit(lobyte(Result));
			Cycles++;
			return;
			}
		if(Result>=0 && Result <=0xFF){
			emit(op+0x10);
			emit(lobyte(Result));
			Cycles++;
			return;
			}
		else {
			emit(op+0x30);
			eword(Result);
			Cycles+=2;
			return;
			}
		}
	else {
		error("Unknown Addressing Mode");
		return;
		}
}

/*
 *      do_indexed --- handle all wierd stuff for indexed addressing
 */
do_indexed(op)
int op;
{
	emit(op);
	eval();
	if( mapdn(*++Optr) != 'x' )
		warn("Indexed Addressing Assumed");
	if( Result < 0 || Result > 255)
		warn("Value Truncated");
	emit(lobyte(Result));
}
SHAR_EOF
cat << \SHAR_EOF > DO11.C
/*
 *      MC68HC11 specific processing
 */

#define PAGE1   0x00
#define PAGE2   0x18
#define PAGE3   0x1A
#define PAGE4   0xCD

/* addressing modes */
#define IMMED   0
#define INDX    1
#define INDY    2
#define LIMMED  3       /* long immediate */
#define OTHER   4

int     yflag = 0;      /* YNOIMM, YLIMM, and CPD flag */

/*
 *      localinit --- machine specific initialization
 */
localinit()
{
}

/*
 *      do_op --- process mnemonic
 *
 *	Called with the base opcode and it's class. Optr points to
 *	the beginning of the operand field.
 */
do_op(opcode,class)
int opcode;	/* base opcode */
int class;	/* mnemonic class */
{
	int     dist;   /* relative branch distance */
	int     amode;  /* indicated addressing mode */
	char	*peek;

	/* guess at addressing mode */
	peek = Optr;
	amode = OTHER;
	while( !delim(*peek) && *peek != EOS)  /* check for comma in operand field */
		if( *peek++ == ',' ){
			if( mapdn(*peek) == 'y' )
				amode = INDY;
			else
				amode = INDX;
			break;
			}
	if( *Optr == '#' ) amode = IMMED;

	yflag = 0;
	switch(class){
		case P2INH:
			emit(PAGE2);
		case INH:                       /* inherent addressing */
			emit(opcode);
			return;
		case REL:                       /* relative branches */
			eval();
			dist = Result - (Pc+2);
			emit(opcode);
			if( (dist >127 || dist <-128) && Pass==2){
				error("Branch out of Range");
				emit(lobyte(-2));
				return;
				}
			emit(lobyte(dist));
			return;
		case LONGIMM:
			if( amode == IMMED )
				amode = LIMMED;
		case NOIMM:
			if( amode == IMMED ){
				error("Immediate Addressing Illegal");
				return;
				}
		case GEN:                       /* general addressing */
			do_gen(opcode,amode,PAGE1,PAGE1,PAGE2);
			return;
		case GRP2:
			if( amode == INDY ){
				Cycles++;
				emit(PAGE2);
				amode = INDX;
				}
			if( amode == INDX )
				do_indexed(opcode);
			else{   /* extended addressing */
				eval();
				emit(opcode+0x10);
				eword(Result);
				}
			return;
		case CPD:               /* cmpd */
			if( amode == IMMED )
				amode = LIMMED;
			if( amode == INDY )
				yflag=1;
			do_gen(opcode,amode,PAGE3,PAGE3,PAGE4);
			return;
		case XNOIMM:            /* stx */
			if( amode == IMMED ){
				error("Immediate Addressing Illegal");
				return;
				}
		case XLIMM:             /* cpx, ldx */
			if( amode == IMMED )
				amode = LIMMED;
			do_gen(opcode,amode,PAGE1,PAGE1,PAGE4);
			return;
		case YNOIMM:            /* sty */
			if( amode == IMMED ){
				error("Immediate Addressing Illegal");
				return;
				}
		case YLIMM:             /* cpy, ldy */
			if(amode == INDY)
				yflag=1;
			if( amode == IMMED )
				amode = LIMMED;
			do_gen(opcode,amode,PAGE2,PAGE3,PAGE2);
			return;
		case BTB:               /* bset, bclr */
		case SETCLR:            /* brset, brclr */
			opcode = bitop(opcode,amode,class);

			if (amode == INDX)
				Cycles++;
			if( amode == INDY ){
				Cycles+=2;
				emit(PAGE2);
				amode = INDX;
				}
			emit(opcode);
			eval();
			emit(lobyte(Result));   /* address */
			if( amode == INDX )
				Optr += 2;      /* skip ,x or ,y */
			Optr = skip_white(Optr);
			eval();
			emit(lobyte(Result));   /* mask */
			if( class == SETCLR )
				return;
			Optr = skip_white(Optr);
			eval();
			dist = Result - (Pc+1);
			if( (dist >127 || dist <-128) && Pass==2){
				error("Branch out of Range");
				dist = Old_pc - (Pc+1);
				}
			emit(lobyte(dist));
			return;
		default:
			fatal("Error in Mnemonic table");
		}
}

/*
 *      bitop --- adjust opcode on bit manipulation instructions
 */
bitop(op,mode,class)
int op;
int mode;
int class;
{
	if( mode == INDX || mode == INDY )
		return(op);
	if( class == SETCLR )
		return(op-8);
	else if(class==BTB)
		return(op-12);
	else
		fatal("bitop");
}

/*
 *      do_gen --- process general addressing modes
 */
do_gen(op,mode,pnorm,px,py)
int     op;     /* base opcode */
int     mode;   /* addressing mode */
int     pnorm;  /* page for normal addressing modes: IMM,DIR,EXT */
int     px;     /* page for INDX addressing */
int     py;     /* page for INDY addressing */
{
	switch(mode){
	case LIMMED:
		Optr++;
		epage(pnorm);
		emit(op);
		eval();
		eword(Result);
		break;
	case IMMED:
		Optr++;
		epage(pnorm);
		emit(op);
		eval();
		emit(lobyte(Result));
		break;
	case INDY:
		if(yflag)
			Cycles += 2;
		else
			Cycles += 3;
		epage(py);
		do_indexed(op+0x20);
		break;
	case INDX:
		Cycles+=2;
		epage(px);
		do_indexed(op+0x20);
		break;
	case OTHER:
		eval();
		epage(pnorm);
		if(Force_word){
			emit(op+0x30);
			eword(Result);
			Cycles+=2;
			break;
			}
		if(Force_byte){
			emit(op+0x10);
			emit(lobyte(Result));
			Cycles++;
			break;
			}
		if(Result>=0 && Result <=0xFF){
			emit(op+0x10);
			emit(lobyte(Result));
			Cycles++;
			break;
			}
		else {
			emit(op+0x30);
			eword(Result);
			Cycles+=2;
			break;
			}
		break;
	default:
		error("Unknown Addressing Mode");
	}
}

/*
 *      do_indexed --- handle all wierd stuff for indexed addressing
 */
do_indexed(op)
int op;
{
	char c;

	emit(op);
	eval();
	if( *Optr++ != ',' )
		error("Syntax");
	c = mapdn(*Optr++);
	if( c != 'x' && c != 'y')
		warn("Indexed Addressing Assumed");
	if( Result < 0 || Result > 255)
		warn("Value Truncated");
	emit(lobyte(Result));
}

/*
 *      epage --- emit page prebyte
 */
epage(p)
int p;
{
	if( p != PAGE1 )        /* PAGE1 means no prebyte */
		emit(p);
}
SHAR_EOF
cat << \SHAR_EOF > DO4.C
/*
 *      MC6804 specific processing
 */

#define IMMED   0
#define IND     1
#define OTHER   2

/* special addresses */
#define XREG    0x80
#define YREG    0x81
#define SD1REG  0x82
#define SD2REG  0x83
#define ACCUM   0xFF

/*
 *      localinit --- machine specific initialization
 */
localinit()
{
	install("x",XREG);
	install("X",XREG);
	install("y",YREG);
	install("Y",YREG);
	install("a",ACCUM);
	install("A",ACCUM);
}

/*
 *      do_op --- process mnemonic
 */
do_op(opcode,class)
{
	int     dist;   /* relative branch distance */
	int     amode;  /* indicated addressing mode */
	int     r1;     /* first eval() for mvi */

	if (( *Operand == '[' ) || ( *Operand == ','))
		amode = IND;
	else if( *Operand == '#' )
		amode = IMMED;
	else
		amode = OTHER;

	switch(class){
		case INH:                       /* inherent addressing */
			emit(opcode);
			return;
		case APOST:             /* A address in mem follows opcode */
			emit(opcode);
			emit(ACCUM);
			return;
		case REL:                       /* short relative branches */
			eval();
			dist = Result - (Pc+1);
			if( (dist >15 || dist <-16) && Pass==2){
				error("Branch out of Range");
				dist = -1;
				}
			emit(opcode + (dist&0x1F));
			return;
		case BTB:
		case SETCLR:
			eval();
			if(Result <0 || Result >7){
				error("Bit Number must be 0-7");
				return;
				}
			emit( opcode + Result);
			if(*Optr++ != ',')error("SYNTAX");
			eval();
			emit(lobyte(Result));
			if( class == SETCLR )
				return;
			if(*Optr++ != ',')error("SYNTAX");
			eval();
			dist = Result - (Old_pc+3);
			if( (dist >127 || dist <-128) && Pass==2){
				error("Branch out of Range");
				dist = -3;
				return;
				}
			emit(lobyte(dist));
			return;
		case EXT:               /* jsr, jmp */
			eval();
			emit(opcode | (hibyte(Result) & 0x0F));
			emit(lobyte(Result));
			return;
		case BPM:       /* brset/clr 7,accum,target */
			emit(opcode);
			emit(ACCUM);
			eval();
			dist = Result - (Old_pc + 3);
			if ((dist > 127 || dist < -128) && Pass == 2) {
				error("Branch out of range");
				dist = -3;
				return;
				}
			emit(lobyte(dist));
			return;
		case MVI:
			eval();
			r1 = Result;    /* save result */
			if (*Optr++ != ',')
				warn("Missing ','");
			eval();
			mvi(opcode,r1,Result);
			return;
		case CLRX:      /* mvi xreg,0 */
			mvi(opcode,XREG,0);
			return;
		case CLRY:      /* mvi yreg,0 */
			mvi(opcode,YREG,0);
			return;
		case LDX:       /* mvi xreg data */
			if (amode == IMMED) Optr++;
			eval();
			mvi(opcode,XREG,Result);
			return;
		case LDY:       /* mvi yreg data */
			if (amode == IMMED) Optr++;
			eval();
			mvi(opcode,YREG,Result);
			return;
		case NOIMM:
			if( amode == IMMED ){
				error("Immediate Addressing Illegal");
				return;
				}
		case GEN:
			if ( amode == IMMED ) {
				Optr++;
				eval();
				emit(opcode | 0x08);
				emit(Result);
				return;
				}
			if( amode == IND ){
				Optr++;
				eval();
				if ((*Optr != ']') && (*Operand != ','))
					warn("Missing ']'");
				if (Result != XREG && Result != YREG) {
					error("Operand must be $80 or $81");
					emit(opcode);
					return;
				}
				emit(opcode | ((Result&0x01)<<4));
				return;
				}
			eval();
			if (XREG <= Result && Result <=SD2REG){
				/*check for short direct cases*/
				if ( opcode==0xE6 ) {   /* inc */
					emit(0xA8 + (Result-XREG));
					return;
					}
				if ( opcode==0xE7 ) { /* dec */
					emit(0xB8 + (Result-XREG));
					return;
					}
				if ( opcode==0xE0 ) { /* lda */
					emit(0xAC | (Result-XREG));
					return;
					}
				if ( opcode==0xE1 ) { /* sta */
					emit(0xBC | (Result-XREG));
					return;
					}
				}
			/* else direct addressing */
			emit( opcode | 0x18);
			emit(lobyte(Result));
			return;
		default:
			fatal("Error in Mnemonic table");
		}
}

mvi(op,to,from)
int op,to,from;
{
	emit(op);
	emit(to);
	emit(from);
}
SHAR_EOF
cat << \SHAR_EOF > DO5.C
/*
 *      MC6805 specific processing
 */

/* addressing modes */
#define IMMED   0       /* immediate */
#define IND     1       /* indexed */
#define OTHER   2       /* NOTA */

/*
 *      localinit --- machine specific initialization
 */
localinit()
{
}

/*
 *      do_op --- process mnemonic
 *
 *	Called with the base opcode and it's class. Optr points to
 *	the beginning of the operand field.
 */
do_op(opcode,class)
int opcode;	/* base opcode */
int class;	/* mnemonic class */
{
	int     dist;   /* relative branch distance */
	int     amode;  /* indicated addressing mode */
	char	*peek;

	/* guess at addressing mode */
	peek = Optr;
	amode = OTHER;
	while( !delim(*peek) && *peek != EOS)  /* check for comma in operand field */
		if( *peek++ == ',' ){
			amode = IND;
			break;
			}
	if( *Optr == '#' ) amode = IMMED;

	switch(class){
		case INH:                       /* inherent addressing */
			emit(opcode);
			return;
		case GEN:                       /* general addressing */
			do_gen(opcode,amode);
			return;
		case REL:                       /* short relative branches */
			eval();
			dist = Result - (Pc+2);
			emit(opcode);
			if( (dist >127 || dist <-128) && Pass==2){
				error("Branch out of Range");
				emit(lobyte(-2));
				return;
				}
			emit(lobyte(dist));
			return;
		case NOIMM:
			if( amode == IMMED ){
				error("Immediate Addressing Illegal");
				return;
				}
			do_gen(opcode,amode);
			return;
		case GRP2:
			if( amode == IND ){
				do_indexed(opcode+0x20);
				return;
				}
			eval();
			Cycles += 2;
			if(Force_byte){
				emit(opcode);
				emit(lobyte(Result));
				return;
				}
			if(Result>=0 && Result <=0xFF){
				emit(opcode);
				emit(lobyte(Result));
				return;
				}
			error("Extended Addressing not allowed");
			return;
		case SETCLR:
		case BTB:
			eval();
			if(Result <0 || Result >7){
				error("Bit Number must be 0-7");
				return;
				}
			emit( opcode | (Result << 1));
			if(*Optr++ != ',')error("SYNTAX");
			eval();
			emit(lobyte(Result));
			if(class==SETCLR)
				return;
			/* else it's bit test and branch */
			if(*Optr++ != ',')error("SYNTAX");
			eval();
			dist = Result - (Old_pc+3);
			if( (dist >127 || dist <-128) && Pass==2){
				error("Branch out of Range");
				emit(lobyte(-3));
				return;
				}
			emit(lobyte(dist));
			return;
		default:
			fatal("Error in Mnemonic table");
		}
}

/*
 *      do_gen --- process general addressing
 */
do_gen(op,mode)
int     op;
int     mode;
{
	if( mode == IMMED){
		Optr++;
		emit(op);
		eval();
		emit(lobyte(Result));
		return;
		}
	else if( mode == IND ){
		do_indexed(op+0x30);
		return;
		}
	else if( mode == OTHER){        /* direct or extended addressing */
		eval();
		if(Force_word){
			emit(op+0x20);
			eword(Result);
			Cycles += 3;
			return;
			}
		if(Force_byte){
			emit(op+0x10);
			emit(lobyte(Result));
			Cycles += 2;
			return;
			}
		if(Result >= 0 && Result <= 0xFF){
			emit(op+0x10);
			emit(lobyte(Result));
			Cycles += 2;
			return;
			}
		else {
			emit(op+0x20);
			eword(Result);
			Cycles += 3;
			return;
			}
		}
	else {
		error("Unknown Addressing Mode");
		return;
		}
}

/*
 *      do_indexed --- handle all wierd stuff for indexed addressing
 */
do_indexed(op)
int op;
{
	eval();
	if(!(*Optr++ == ',' && (*Optr == 'x' || *Optr == 'X')))
		warn("Indexed Addressing Assumed");
	if(Force_word){
		if(op < 0x80 ){ /* group 2, no extended addressing */
			emit(op+0x10); /* default to one byte indexed */
			emit(lobyte(Result));
			Cycles += 3;
			return;
			}
		emit(op);
		eword(Result);
		Cycles += 4;
		return;
		}
	Cycles += 3;    /* assume 1 byte indexing */
	if(Force_byte){
		emit(op+0x10);
		emit(lobyte(Result));
		return;
		}
	if(Result==0){
		emit(op+0x20);
		Cycles--;       /* ,x slightly faster */
		return;
		}
	if(Result>0 && Result <=0xFF){
		emit(op+0x10);
		emit(lobyte(Result));
		return;
		}
	if( op < 0x80 ){
		warn("Value Truncated");
		emit(op+0x10);
		emit(lobyte(Result));
		return;
		}
	emit(op);
	eword(Result);
	Cycles++;       /* 2 byte slightly slower */
	return;
}
SHAR_EOF
cat << \SHAR_EOF > DO9.C
/*
 *      MC6809 specific processing
 */

#define PAGE2	0x10
#define PAGE3	0x11
#define IPBYTE	0x9F	/* extended indirect postbyte */
#define SWI     0x3F

/* register names */

#define RD	0
#define RX	1
#define RY	2
#define RU	3
#define RS	4
#define RPC	5
#define RA	8
#define RB	9
#define RCC	10
#define RDP	11
#define RPCR	12

/* convert tfr/exg reg number into psh/pul format */
int     regs[] = { 6,16,32,64,64,128,0,0,2,4,1,8,0};
int     rcycl[]= { 2,2, 2, 2, 2, 2,  0,0,1,1,1,1,0};

/* addressing modes */
#define IMMED   0       /* immediate */
#define IND     1       /* indexed */
#define INDIR   2       /* indirect */
#define OTHER   3       /* NOTA */

/*
 *      localinit --- machine specific initialization
 */
localinit()
{
}

/*
 *      do_op --- process mnemonic
 *
 *	Called with the base opcode and it's class. Optr points to
 *	the beginning of the operand field.
 */
do_op(opcode,class)
int opcode;	/* base opcode */
int class;	/* mnemonic class */
{
	int     dist;   /* relative branch distance */
	int     src,dst;/* source and destination registers */
	int     pbyte;  /* postbyte value */
	int     amode;  /* indicated addressing mode */
	int	j;

	amode = set_mode();     /* pickup indicated addressing mode */

	switch(class){
		case INH:                       /* inherent addressing */
			emit(opcode);
			return;
		case GEN:                       /* general addressing */
			do_gen(opcode,amode);
			return;
		case IMM:                       /* immediate addressing */
			if( amode != IMMED ){
				error("Immediate Operand Required");
				return;
				}
			Optr++;
			eval();
			emit(opcode);
			emit(lobyte(Result));
			return;
		case REL:                       /* short relative branches */
			eval();
			dist = Result - (Pc+2);
			emit(opcode);
			if( (dist >127 || dist <-128) && Pass==2){
				error("Branch out of Range");
				emit(lobyte(-2));
				return;
				}
			emit(lobyte(dist));
			return;
		case P2REL:                     /* long relative branches */
			eval();
			dist = Result - (Pc+4);
			emit(PAGE2);
			emit(opcode);
			eword(dist);
			return;
		case P1REL:                     /* lbra and lbsr */
			if( amode == IMMED)
				Optr++; /* kludge for C compiler */
			eval();
			dist = Result - (Pc+3);
			emit(opcode);
			eword(dist);
			return;
		case NOIMM:
			if( amode == IMMED ){
				error("Immediate Addressing Illegal");
				return;
				}
			do_gen(opcode,amode);
			return;
		case P2GEN:
			emit(PAGE2);
			if( amode == IMMED ){
				emit(opcode);
				Optr++;
				eval();
				eword(Result);
				return;
				}
			do_gen(opcode,amode);
			return;
		case P3GEN:
			emit(PAGE3);
			if( amode == IMMED ){
				emit(opcode);
				Optr++;
				eval();
				eword(Result);
				return;
				}
			do_gen(opcode,amode);
			return;
		case RTOR:                      /* tfr and exg */
			emit(opcode);
			src = regnum();
			while(alpha(*Optr))Optr++;
			if(src==ERR){
				error("Register Name Required");
				emit(0);
				return;
				}
			if(*Optr++ != ','){
				error("Missing ,");
				emit(0);
				return;
				}
			dst = regnum();
			while(alpha(*Optr))Optr++;
			if(dst==ERR){
				error("Register Name Required");
				emit(0);
				return;
				}
			if( src==RPCR || dst==RPCR){
				error("PCR illegal here");
				emit(0);
				return;
				}
			if( (src <=5 && dst >=8) ||
			    (src >=8 && dst <=5)){
				error("Register Size Mismatch");
				emit(0);
				return;
				}
			emit( (src<<4)+dst );
			return;
		case INDEXED:                   /* indexed addressing only */
			if( *Optr == '#'){
				Optr++;         /* kludge city */
				amode = IND;
				}
			if( amode != IND ){
				error("Indexed Addressing Required");
				return;
				}
			do_indexed(opcode);
			return;
		case RLIST:                     /* pushes and pulls */
			if(*Operand == EOS){
				error("Register List Required");
				return;
				}
			emit(opcode);
			pbyte = 0;
			do{
				j = regnum();
				if( j == ERR || j==RPCR)
					error("Illegal Register Name");
				else if(j==RS && (opcode==52))
					error("Can't Push S on S");
				else if(j==RU && (opcode==54))
					error("Can't Push U on U");
				else if(j==RS && (opcode==53))
					error("Can't Pull S from S");
				else if(j==RU && (opcode==55))
					error("Can't Pull U from U");
				else{
					pbyte |= regs[j];
					Cycles += rcycl[j];
					}
				while(*Optr != EOS && alpha(*Optr))Optr++;
			}while( *Optr++ == ',' );
			emit(lobyte(pbyte));
			return;
		case P2NOIMM:
			if( amode == IMMED )
				error("Immediate Addressing Illegal");
			else{
				emit(PAGE2);
				do_gen(opcode,amode);
				}
			return;
		case P2INH:                     /* Page 2 inherent */
			emit(PAGE2);
			emit(opcode);
			return;
		case P3INH:                     /* Page 3 inherent */
			emit(PAGE3);
			emit(opcode);
			return;
		case LONGIMM:
			if( amode == IMMED ){
				emit(opcode);
				Optr++;
				eval();
				eword(Result);
				}
			else
				do_gen(opcode,amode);
			return;
		case GRP2:
			if( amode == IND ){
				do_indexed(opcode+0x60);
				return;
				}
			else if( amode == INDIR){
				Optr++;
				emit(opcode + 0x60);
				emit(IPBYTE);
				eval();
				eword(Result);
				Cycles += 7;
				if(*Optr == ']'){
					Optr++;
					return;
					}
				error("Missing ']'");
				return;
				}
			eval();
			if(Force_word){
				emit(opcode+0x70);
				eword(Result);
				Cycles += 3;
				return;
				}
			if(Force_byte){
				emit(opcode);
				emit(lobyte(Result));
				Cycles += 2;
				return;
				}
			if(Result>=0 && Result <=0xFF){
				emit(opcode);
				emit(lobyte(Result));
				Cycles += 2;
				return;
				}
			else {
				emit(opcode+0x70);
				eword(Result);
				Cycles += 3;
				return;
				}
		case SYS:                       /* system call */
			emit(SWI);
			eval();
			emit(lobyte(Result));
			return;
		default:
			fatal("Error in Mnemonic table");
		}
}


/*
 *      do_gen --- process general addressing mode stuff
 */
do_gen(op,mode)
int     op;
int     mode;
{
	if( mode == IMMED){
		Optr++;
		emit(op);
		eval();
		emit(lobyte(Result));
		return;
		}
	else if( mode == IND ){
		do_indexed(op+0x20);
		return;
		}
	else if( mode == INDIR){
		Optr++;
		emit(op+0x20);
		emit(IPBYTE);
		eval();
		eword(Result);
		Cycles += 7;
		if(*Optr == ']'){
			Optr++;
			return;
			}
		error("Missing ']'");
		return;
		}
	else if( mode == OTHER){
		eval();
		if(Force_word){
			emit(op+0x30);
			eword(Result);
			Cycles += 3;
			return;
			}
		if(Force_byte){
			emit(op+0x10);
			emit(lobyte(Result));
			Cycles += 2;
			return;
			}
		if(Result>=0 && Result <=0xFF){
			emit(op+0x10);
			emit(lobyte(Result));
			Cycles += 2;
			return;
			}
		else {
			emit(op+0x30);
			eword(Result);
			Cycles += 3;
			return;
			}
		}
	else {
		error("Unknown Addressing Mode");
		return;
		}
}

/*
 *      do_indexed --- handle all wierd stuff for indexed addressing
 */
do_indexed(op)
int op;
{
	int     pbyte;
	int     j,k;
	int     predec,pstinc;

	Cycles += 2;    /* indexed is always 2+ base cycle count */
	predec=0;
	pstinc=0;
	pbyte=128;
	emit(op);
	if(*Optr=='['){
		pbyte |= 0x10;    /* set indirect bit */
		Optr++;
		if( !any((char)']',Optr))
			error("Missing ']'");
		Cycles += 3;    /* indirection takes this much longer */
		}
	j=regnum();
	if(j==RA){
		Cycles++;
		abd_index(pbyte+6);
		return;
		}
	if(j==RB){
		Cycles++;
		abd_index(pbyte+5);
		return;
		}
	if(j==RD){
		Cycles += 4;
		abd_index(pbyte+11);
		return;
		}
	eval();
	Optr++;
	while(*Optr=='-'){
		predec++;
		Optr++;
		}
	j=regnum();
	while( alpha(*Optr) )Optr++;
	while(*Optr=='+'){
		pstinc++;
		Optr++;
		}
	if(j==RPC || j==RPCR){
		if( pstinc || predec ){
			error("Auto Inc/Dec Illegal on PC");
			return;
			}
		if(j==RPC){
			if(Force_word){
				emit(pbyte+13);
				eword(Result);
				Cycles += 5;
				return;
				}
			if(Force_byte){
				emit(pbyte+12);
				emit(lobyte(Result));
				Cycles++;
				return;
				}
			if(Result>=-128 && Result <=127){
				emit(pbyte+12);
				emit(lobyte(Result));
				Cycles++;
				return;
				}
			else {
				emit(pbyte+13);
				eword(Result);
				Cycles += 5;
				return;
				}
			}
		/* PCR addressing */
		if(Force_word){
			emit(pbyte+13);
			eword(Result-(Pc+2));
			Cycles += 5;
			return;
			}
		if(Force_byte){
			emit(pbyte+12);
			emit(lobyte(Result-(Pc+1)));
			Cycles++;
			return;
			}
		k=Result-(Pc+2);
		if( k >= -128 && k <= 127){
			emit(pbyte+12);
			emit(lobyte(Result-(Pc+1)));
			Cycles++;
			return;
			}
		else{
			emit(pbyte+13);
			eword(Result-(Pc+2));
			Cycles += 5;
			return;
			}
		}
	if(predec || pstinc){
		if(Result != 0){
			error("Offset must be Zero");
			return;
			}
		if(predec>2 || pstinc>2){
			error("Auto Inc/Dec by 1 or 2 only");
			return;
			}
		if((predec==1 && (pbyte&0x10) != 0) ||
		   (pstinc==1 && (pbyte&0x10) != 0)){
			error("No Auto Inc/Dec by 1 for Indirect");
			return;
			}
		if(predec && pstinc){
			error("Can't do both!");
			return;
			}
		if(predec)
			pbyte += predec+1;
		if(pstinc)
			pbyte += pstinc-1;
		pbyte += rtype(j);
		emit(pbyte);
		Cycles += 1 + predec + pstinc;
		return;
		}
	pbyte += rtype(j);
	if(Force_word){
		emit(pbyte+0x09);
		eword(Result);
		Cycles += 4;
		return;
		}
	if(Force_byte){
		emit(pbyte+0x08);
		emit(lobyte(Result));
		Cycles++;
		return;
		}
	if(Result==0){
		emit(pbyte+0x04);
		return;
		}
	if((Result >= -16) && (Result <= 15) && ((pbyte&16)==0)){
		pbyte &= 127;
		pbyte += Result&31;
		emit(pbyte);
		Cycles++;
		return;
		}
	if(Result >= -128 && Result <= 127){
		emit(pbyte+0x08);
		emit(lobyte(Result));
		Cycles++;
		return;
		}
	emit(pbyte+0x09);
	eword(Result);
	Cycles += 4;
	return;
}


/*
 *      abd_index --- a,b or d indexed
 */

abd_index(pbyte)
int pbyte;
{
	int     k;

	Optr += 2;
	k=regnum();
	pbyte += rtype(k);
	emit(pbyte);
	return;
}

/*
 *      rtype --- return register type in post-byte format
 */
rtype(r)
int r;
{
	switch(r){
	case RX:        return(0x00);
	case RY:        return(0x20);
	case RU:        return(0x40);
	case RS:        return(0x60);
		}
	error("Illegal Register for Indexed");
	return(0);
}

/*
 *      set_mode --- determine addressing mode from operand field
 */
set_mode()
{
	register char *p;

	if( *Operand == '#' )
		return(IMMED);          /* immediate addressing */
	p = Operand;
	while( *p != EOS && *p != BLANK && *p != TAB){/* any , before break */
		if( *p == ',')
			return(IND);    /* indexed addressing */
		p++;
		}
	if( *Operand == '[')
		return(INDIR);          /* indirect addressing */
	return(OTHER);                  /* NOTA */
}

/*
 *      regnum --- return register number of *Optr
 */
regnum()
{
	if( head(Optr,"D" ))return(RD);
	if( head(Optr,"d" ))return(RD);
	if( head(Optr,"X" ))return(RX);
	if( head(Optr,"x" ))return(RX);
	if( head(Optr,"Y" ))return(RY);
	if( head(Optr,"y" ))return(RY);
	if( head(Optr,"U" ))return(RU);
	if( head(Optr,"u" ))return(RU);
	if( head(Optr,"S" ))return(RS);
	if( head(Optr,"s" ))return(RS);
	if( head(Optr,"PC" ))return(RPC);
	if( head(Optr,"pc" ))return(RPC);
	if( head(Optr,"PCR" ))return(RPCR);
	if( head(Optr,"pcr" ))return(RPCR);
	if( head(Optr,"A" ))return(RA);
	if( head(Optr,"a" ))return(RA);
	if( head(Optr,"B" ))return(RB);
	if( head(Optr,"b" ))return(RB);
	if( head(Optr,"CC" ))return(RCC);
	if( head(Optr,"cc" ))return(RCC);
	if( head(Optr,"DP" ))return(RDP);
	if( head(Optr,"dp" ))return(RDP);
	return(ERR);
}

SHAR_EOF
cat << \SHAR_EOF > FFWD.C
/*
 *      file I/O version of forward ref handler
 */

#define	FILEMODE	0644	/* file creat mode */
#define	UPDATE		2	/* file open mode */
#define	ABS		0	/* absolute seek */

int	Forward =0;		/* temp file's file descriptor	*/
char	Fwd_name[] = { "Fwd_refs" } ;

/*
 *      fwdinit --- initialize forward ref file
 */
fwdinit()
{
	Forward = creat(Fwd_name,FILEMODE);
	if(Forward <0)
		fatal("Can't create temp file");
	close(Forward); /* close and reopen for reads and writes */
	Forward = open(Fwd_name,UPDATE);
	if(Forward <0)
		fatal("Forward ref file has gone.");
#ifndef DEBUG
	unlink(Fwd_name);
#endif
}

/*
 *      fwdreinit --- reinitialize forward ref file
 */
fwdreinit()
{
	F_ref   = 0;
	Ffn     = 0;
	lseek(Forward,0L,ABS);   /* rewind forward refs */
	read(Forward,&Ffn,sizeof(Ffn));
	read(Forward,&F_ref,sizeof(F_ref)); /* read first forward ref into mem */
#ifdef DEBUG
	printf("First fwd ref: %d,%d\n",Ffn,F_ref);
#endif
}

/*
 *      fwdmark --- mark current file/line as containing a forward ref
 */
fwdmark()
{
	write(Forward,&Cfn,sizeof(Cfn));
	write(Forward,&Line_num,sizeof(Line_num));
}

/*
 *      fwdnext --- get next forward ref
 */
fwdnext()
{
	int stat;

	stat = read(Forward,&Ffn,sizeof(Ffn));
#ifdef DEBUG
	printf("Ffn stat=%d ",stat);
#endif
	stat = read(Forward,&F_ref,sizeof(F_ref));
#ifdef DEBUG
	printf("F_ref stat=%d  ",stat);
#endif
	if( stat < 2 ){
		F_ref=0;Ffn=0;
		}
#ifdef DEBUG
	printf("Next Fwd ref: %d,%d\n",Ffn,F_ref);
#endif
}
SHAR_EOF
cat << \SHAR_EOF > OUTPUT.C
/*
 *  stable --- prints the symbol table in alphabetical order
 */
stable(ptr)

struct nlist *ptr;
{
  if (ptr != NULL)
    {
      stable (ptr->Lnext);
        printf ("%-10s %04x\n",ptr->name,ptr->def);
      stable (ptr->Rnext);
    }
}
/*
 *  cross  --  prints the cross reference table 
 */
cross(point)

struct nlist *point;
{
struct link *tp;
int i = 1;
  if (point != NULL)
    {
      cross (point->Lnext);
        printf ("%-10s %04x *",point->name,point->def);
         tp = point->L_list;
          while (tp != NULL)
           {
             if (i++>10)
              {
               i=1;
               printf("\n                      ");
              }
              printf ("%04d ",tp->L_num);
               tp = tp->next;
           }
         printf ("\n");
      cross (point->Rnext);
    }
}
SHAR_EOF
cat << \SHAR_EOF > PSEUDO.C
/*
 *      pseudo --- pseudo op processing
 */

#define RMB     0       /* Reserve Memory Bytes         */
#define FCB     1       /* Form Constant Bytes          */
#define FDB     2       /* Form Double Bytes (words)    */
#define FCC     3       /* Form Constant Characters     */
#define ORG     4       /* Origin                       */
#define EQU     5       /* Equate                       */
#define ZMB     6       /* Zero memory bytes            */
#define FILL    7       /* block fill constant bytes    */
#define OPT     8       /* assembler option             */
#define NULL_OP 9       /* null pseudo op               */
#define PAGE    10      /* new page                     */

struct oper pseudo[] = {
"bsz",  PSEUDO, ZMB,    0,
"end",  PSEUDO, NULL_OP,0,
"equ",  PSEUDO, EQU,    0,
"fcb",  PSEUDO, FCB,    0,
"fcc",  PSEUDO, FCC,    0,
"fdb",  PSEUDO, FDB,    0,
"fill", PSEUDO, FILL,   0,
"nam",  PSEUDO, NULL_OP,0,
"name", PSEUDO, NULL_OP,0,
"opt",  PSEUDO, OPT,    0,
"org",  PSEUDO, ORG,    0,
"pag",  PSEUDO, PAGE,   0,
"page", PSEUDO, PAGE,   0,
"rmb",  PSEUDO, RMB,    0,
"spc",  PSEUDO, NULL_OP,0,
"ttl",  PSEUDO, NULL_OP,0,
"zmb",  PSEUDO, ZMB,    0
};

/*
 *      do_pseudo --- do pseudo op processing
 */
do_pseudo(op)
int op; /* which op */
{
        char    fccdelim;
        int     j;
        int     fill;
        char    *skip_white();

        if( op != EQU && *Label )
                install(Label,Pc);

        P_force++;
        switch(op){
                case RMB:                       /* reserve memory bytes */
                        if( eval() ){
                                Pc +=  Result;
                                f_record();     /* flush out bytes */
                                }
                        else
                                error("Undefined Operand during Pass One");
                        break;
                case ZMB:                       /* zero memory bytes */
                        if( eval() )
                                while( Result-- )
                                        emit(0);
                        else
                                error("Undefined Operand during Pass One");
                        break;
                case FILL:                      /* fill memory with constant */
                        eval();
                        fill = Result;
                        if( *Optr++ != ',' )
                                error("Bad fill");
                        else{
                                Optr = skip_white(Optr);
                                eval();
                                while( Result-- )
                                        emit(fill);
                                }
                        break;
                case FCB:                       /* form constant byte(s) */
                        do{
                                Optr = skip_white(Optr);
                                eval();
                                if( Result > 0xFF ){
                                        if(!Force_byte)
                                                warn("Value truncated");
                                        Result = lobyte(Result);
                                        }
                                emit(Result);
                        }while( *Optr++ == ',' );
                        break;
                case FDB:                       /* form double byte(s) */
                        do{
                                Optr = skip_white(Optr);
                                eval();
                                eword(Result);
                        }while( *Optr++ == ',' );
                        break;
                case FCC:                       /* form constant characters */
                        if(*Operand==EOS)
                                break;
                        fccdelim = *Optr++;
                        while( *Optr != EOS && *Optr != fccdelim)
                                emit(*Optr++);
                        if(*Optr == fccdelim)
                                Optr++;
                        else
                                error("Missing Delimiter");
                        break;
                case ORG:                       /* origin */
                        if( eval() ){
                                Old_pc = Pc = Result;
                                f_record();     /* flush out any bytes */
                                }
                        else
                                error("Undefined Operand during Pass One");
                        break;
                case EQU:                       /* equate */
                        if(*Label==EOS){
                                error("EQU requires label");
                                break;
                                }
                        if( eval() ){
                                install(Label,Result);
                                Old_pc = Result;        /* override normal */
                                }
                        else
                                error("Undefined Operand during Pass One");
                        break;
                case OPT:                       /* assembler option */
                        P_force=0;
                        if( head(Operand,"l") )
                                Lflag=1;
                        else if( head(Operand,"nol"))
                                Lflag=0;
                        else if( head(Operand,"c")){
                                Cflag=1;
                                Ctotal=0;
                                }
                        else if( head(Operand,"noc"))
                                Cflag=0;
                        else if( head(Operand,"contc")){
                                Cflag=1;
                                }
                        else if ( head(Operand,"s"))
                                Sflag = 1;
                        else if ( head(Operand,"cre"))
                                CREflag = 1;
                        else
                                error("Unrecognized OPT");
                        break;
                case PAGE:                      /* go to a new page */
                        P_force=0;
                        N_page = 1;
                        if (Pass == 2 )
                         if (Lflag)  
                          {
                           printf ("\f");
                           printf ("%-10s",Argv[Cfn]);
                           printf ("                                   ");
                           printf ("page %3d\n",Page_num++);
                          }
                        break;
                case NULL_OP:                   /* ignored psuedo ops */
                        P_force=0;
                        break;
                default:
                        fatal("Pseudo error");
                }
}
SHAR_EOF
#	End of shell archive
exit 0
-- 
Bob Page, U of Lowell CS Dept.  page@swan.ulowell.edu  ulowell!page
Have five nice days.