/*
 * 6800.c
 * Updated (?) for the new compiler
 */

/*)BUILD	# untested
*/

#include <stdio.h>

#define NCPS	8
#define NTSYM	128
#define NERR	10
#define NINPUT	128
#define NCODE	128
#define NTIT	64
#define	NSYM	256

#define NLIST	0
#define SLIST	1
#define ALIST	2
#define CLIST	3

#define	CMP	0x81
#define	ADD	0x8B
#define	SUB	0x80
#define CPX	0x8C
#define	ABA	0x1B
#define SBA	0x10
#define CBA	0x11
#define	JMP	0x4E
#define JSR	0x8D
#define	TAB	0x16
#define TBA	0x17
#define TAP	0x06
#define TPA	0x07
#define TSX	0x30
#define TXS	0x35
#define	LDA	0x86
#define STA	0x87
#define	LDS	0x8E
#define STS	0x8F
#define	INC	0x4C
#define	DEC	0x4A
#define	INX	0x08
#define DEX	0x09
#define INS	0x31
#define DES	0x34

#define	dot	(&sym[0])

struct	sym
{
	char	s_name[NCPS];
	char	s_type;
	char	s_flag;
	int	s_addr;
};

#define S_UND	0
#define S_ABS	1

#define S_OP0	2
#define S_OP1	3
#define S_OP2	4
#define S_OP3	5
#define S_OP4	6
#define S_OP5	7

#define	S_A	8
#define	S_B	9
#define	S_X	10
#define	S_S	11
#define	S_LIT	12
#define	S_INDEX	13
#define	S_P	14

#define S_BYTE	24
#define	S_WORD	25
#define S_ASCII	26
#define S_ASCIZ	27
#define S_BLKB	28
#define S_PAGE	29
#define S_TITLE	30
#define S_BYTE	31
#define S_HLIST	32
#define S_OLIST	33

#define	S_MDF	01		/* Mult. def */
#define S_ASG	02		/* Assigned def */
#define	S_LV	04		/* Lvalue required */
#define	S_16	010		/* 16 bit */

struct	tsym
{
	int	t_num;
	int	t_addr;
};

struct	tsymp
{
	struct	tsym *t_fp;
	struct	tsym *t_bp;
};

struct	addr
{
	int	a_type;
	int	a_addr;
};

int	line;
int	page;
int	lop;
int	pass;
int	nsym;
int	ntsym;
int	lflag;
int	oflag;
int	eflag;
int	sflag;
int	laddr;
int	lmode;
int	hlist;
char	*ep;
char	eb[NERR];
char	*ip;
char	ib[NINPUT];
char	*cp;
char	cb[NCODE];
char	tb[NTIT];

extern	struct	sym sym[];

struct	tsym tsym[NTSYM];
struct	tsymp tsymp[10];

FILE	*lfp;
FILE	*ofp;
FILE	*sfp;

#define	LETTER	0
#define	DIGIT	1
#define	BINOP	2
#define ETC	3
#define	ILL	4
#define	SPACE	5


char	ctype[128] = {
	ILL,	ILL,	ILL,	ILL,	ILL,	ILL,	ILL,	ILL,
	ILL,	SPACE,	ILL,	ILL,	SPACE,	ILL,	ILL,	ILL,
	ILL,	ILL,	ILL,	ILL,	ILL,	ILL,	ILL,	ILL,
	ILL,	ILL,	ILL,	ILL,	ILL,	ILL,	ILL,	ILL,
	SPACE,	ETC,	ETC,	ETC,	ETC,	BINOP,	BINOP,	ETC,
	ETC,	ETC,	BINOP,	BINOP,	ETC,	BINOP,	LETTER,	ETC,
	DIGIT,	DIGIT,	DIGIT,	DIGIT,	DIGIT,	DIGIT,	DIGIT,	DIGIT,
	DIGIT,	DIGIT,	ETC,	ETC,	BINOP,	ETC,	BINOP,	ETC,
	ETC,	LETTER,	LETTER,	LETTER,	LETTER,	LETTER,	LETTER,	LETTER,
	LETTER,	LETTER,	LETTER,	LETTER,	LETTER,	LETTER,	LETTER,	LETTER,
	LETTER,	LETTER,	LETTER,	LETTER,	LETTER,	LETTER,	LETTER,	LETTER,
	LETTER,	LETTER,	LETTER,	ETC,	ETC,	ETC,	BINOP,	LETTER,
	ETC,	LETTER,	LETTER,	LETTER,	LETTER,	LETTER,	LETTER,	LETTER,
	LETTER,	LETTER,	LETTER,	LETTER,	LETTER,	LETTER,	LETTER,	LETTER,
	LETTER,	LETTER,	LETTER,	LETTER,	LETTER,	LETTER,	LETTER,	LETTER,
	LETTER,	LETTER,	LETTER,	ETC,	BINOP,	ETC,	ETC,	ETC
};

main(argc, argv)
char *argv[];
{
	register char *p;
	register c, i;
	struct tsym *tp;
	char *fn;
	FILE *afile();

	fn = NULL;
	for (i=1; i<argc; ++i) {
		p = argv[i];
		if (*p == '-') {
			++p;
			while (c = *p++)
				switch(c) {

				case 'l':
				case 'L':
					++lflag;
					break;

				case 'o':
				case 'O':
					++oflag;
					break;

				case 's':
				case 'S':
					++sflag;
					break;

				default:
					usage();
				}
		} else
			fn = p;
	}
	if (fn == NULL)
		usage();
	sfp = afile(fn, 0);
	if (lflag)
		lfp = afile("6800.l", 1);
	if (oflag)
		ofp = afile("6800.o", 1);
	syminit();
	for (pass=0; pass<2; ++pass) {
		dot->s_type = S_ABS;
		dot->s_flag = S_ASG;
		dot->s_addr = 0;
		line = 0;
		page = 0;
		lop =  60;
		rewind(sfp);
		/*
		 * If second pass, reset the
		 * f-b table.
		 */
		if (pass == 1) {
			for (i=0; i<10; ++i) {
				tsymp[i].t_fp = NULL;
				tsymp[i].t_bp = NULL;
				tp = tsym;
				while (tp < &tsym[ntsym]) {
					if (tp->t_num == i) {
						tsymp[i].t_fp = tp;
						break;
					}
					++tp;
				}
			}
		}
		while (fgetss(ib, sizeof ib, sfp) != NULL) {	/* MM	*/
			++line;
			cp = cb;
			ep = eb;
			ip = ib;
			eflag = 0;
			setexit();
			if (eflag == 0)
				asm();
			if (pass == 1) {
				diag();
				list();
			}
		}
	}
}

FILE *
afile(fn, wf)
char *fn;
{
	register FILE *fp;

	fp = fopen(fn, wf?"w":"r");
	if (fp == NULL) {
		fprintf(stderr, "%s: cannot open.\n", fn);
		exit(1);
	}
	return (fp);
}

asm()
{
	register c, t1, t2;
	struct tsym *tp;
	struct sym  *sp;
	struct addr a1, a2;
	int a, b, d, op;
	char id[NCPS], *p;
	struct sym *lookup();

	laddr = dot->s_addr;
	lmode = SLIST;
loop:
	while ((c = getnb()) == ';')
		;
	if (c == '\0' || c == '/')
		return;
	if (ctype[c] == DIGIT) {
		if (getnb() != ':')
			qerr();
		c -= '0';
		if (pass == 0) {
			if (ntsym >= NTSYM) {
				fprintf(stderr, "Too many temp. symbols!\n");
				exit(1);
			}
			tsym[ntsym].t_num = c;
			tsym[ntsym].t_addr = dot->s_addr;
			++ntsym;
		}
		tp = tsymp[c].t_fp;
		tsymp[c].t_bp = tp;
		tsymp[c].t_fp = NULL;
		++tp;
		while (tp < &tsym[ntsym]) {
			if (tp->t_num == c) {
				tsymp[c].t_fp = tp;
				break;
			}
			++tp;
		}
		goto loop;
	}
	if (ctype[c] != LETTER)
		qerr();
	getid(c, id);
	if ((c = getnb()) == ':') {
		sp = lookup(id, 1);
		if (pass == 0) {
			if (sp->s_type!=S_UND && (sp->s_flag&S_ASG)==0)
				sp->s_flag |= S_MDF;
			sp->s_type = S_ABS;
			sp->s_addr = dot->s_addr;
		} else {
			if ((sp->s_flag&S_MDF) != 0)
				err('m');
			if (sp->s_type!=S_ABS || sp->s_addr!=dot->s_addr)
				err('p');
		}
		lmode = ALIST;
		goto loop;
	}
	if (c == '=') {
		sp = lookup(id, 1);
		if (sp->s_type!=S_UND && (sp->s_flag&S_ASG)==0)
			err('m');
		expr(&a1);
		sp->s_type = a1.a_type;
		sp->s_addr = laddr = a1.a_addr;
		sp->s_flag = S_ASG;
		lmode = ALIST;
		goto loop;
	}
	unget(c);
	lmode = CLIST;
	if ((sp = lookup(id, 0)) == NULL) {
		err('o');
		return;
	}
	op = sp->s_addr;
	switch (sp->s_type) {

	case S_BYTE:
	case S_WORD:
		do {
			expr(&a1);
			a = a1.a_addr;
			if (sp->s_type == S_BYTE) {
				byte(a);
				outb(a);
			} else
				outw(a);
		} while ((c = getnb()) == ',');
		unget(c);
		break;

	case S_ASCII:
	case S_ASCIZ:
		if ((d = getnb()) == '\0')
			qerr();
		while ((c = get())!='\0' && c!=d)
			outb(c);
		if (c == '\0')
			qerr();
		if (sp->s_type == S_ASCIZ)
			outb(0);
		break;

	case S_BLKB:
		expr(&a1);
		a = a1.a_addr;
		if ((c = getnb()) == ',') {
			expr(&a1);
			b = a1.a_addr;
		} else {
			unget(c);
			b = 0;
		}
		while (a--)
			outb(b);
		lmode = ALIST;
		break;

	case S_TITLE:
		p = tb;
		if ((c = getnb()) != '\0') {
			do {
				if (p < &tb[NTIT-1])
					*p++ = c;
			} while ((c = get()) != '\0');
		}
		*p = '\0';
		unget(c);

	case S_PAGE:
		lop = 60;
		lmode = NLIST;
		break;

	case S_HLIST:
		hlist = 1;
		lmode = NLIST;
		break;

	case S_OLIST:
		hlist = 0;
		lmode = NLIST;
		break;

	case S_OP0:
		outb(op);
		break;

	case S_OP1:
		t1 = addr(&a1);
		if (op == INC) {
			if (t1 == S_X) {
				outb(INX);
				break;
			}
			if (t1 == S_S) {
				outb(INS);
				break;
			}
		}
		if (op == DEC) {
			if (t1 == S_X) {
				outb(DEX);
				break;
			}
			if (t1 == S_S) {
				outb(DES);
				break;
			}
		}
		if (t1==S_A || t1==S_B) {
			if (op==JSR || op==JMP)
				aerr();
			if (t1 == S_B)
				op |= 0x10;
			outb(op);
			break;
		}
		if (t1 == S_INDEX) {
			outx(op, a1.a_addr);
			break;
		}
		if (t1 == S_ABS) {
			outb(op | 0x30);
			outw(a1.a_addr);
			break;
		}
		aerr();
		break;

	case S_OP2:
		expr(&a1);
		a = a1.a_addr - dot->s_addr - 2;
		outb(op);
		byte(a);
		outb(a);
		break;

	case S_OP3:
		addr(op==CMP ? &a2 : &a1);
		comma();
		addr(op==CMP ? &a1 : &a2);
		t1 = a1.a_type;
		t2 = a2.a_type;
		if (t1==S_B && t2==S_A) {
			if (op == ADD) {
				outb(ABA);
				break;
			}
			if (op == SUB) {
				outb(SBA);
				break;
			}
			if (op == CMP) {
				outb(CBA);
				break;
			}
		}
		if (t2 == S_X) {
			if (op != CMP)
				aerr();
			outd(CPX, 0, &a1, S_16);
			break;
		}
		if (t2==S_A || t2==S_B) {
			outd(op, t2, &a1, 0);
			break;
		}
		aerr();
		break;

	case S_OP4:
		t1 = addr(&a1);
		comma();
		t2 = addr(&a2);
		if (t1==S_A && t2==S_P) {
			outb(TAP);
			break;
		}
		if (t1==S_P && t2==S_A) {
			outb(TPA);
			break;
		}
		if (t1==S_A && t2==S_B) {
			outb(TAB);
			break;
		}
		if (t1==S_B && t2==S_A) {
			outb(TBA);
			break;
		}
		if (t1==S_S && t2==S_X) {
			outb(TSX);
			break;
		}
		if (t1==S_X && t2==S_S) {
			outb(TXS);
			break;
		}
		if (t1==S_A || t1==S_B) {
			outd(STA, t1, &a2, S_LV);
			break;
		}
		if (t2==S_A || t2==S_B) {
			outd(LDA, t2, &a1, 0);
			break;
		}
		if (t1==S_S || t1==S_X) {
			outd(STS, t1, &a2, S_LV|S_16);
			break;
		}
		if (t2==S_S || t2==S_X) {
			outd(LDS, t2, &a1, S_16);
			break;
		}
		aerr();
		break;

	case S_OP5:
		t1 = addr(&a1);
		if (t1==S_A || t1==S_B) {
			if (t1 == S_B)
				op |= 0x01;
			outb(op);
			break;
		}
		aerr();
		break;

	default:
		err('o');
	}
	goto loop;
}

addr(ap)
register struct addr *ap;
{
	register c;
	struct addr x;

	if ((c = getnb()) == '$') {
		expr(ap);
		ap->a_type = S_LIT;
		return (S_LIT);
	}
	if (c == '(') {
		expr(&x);
		if (x.a_type!=S_X || getnb()!=')')
			qerr();
		ap->a_type = S_INDEX;
		ap->a_addr = 0;
		return (S_INDEX);
	}
	unget(c);
	expr(ap);
	if (ap->a_type == S_ABS) {
		c = getnb();
		if (c == '(') {
			expr(&x);
			if (x.a_type!=S_X || getnb()!=')')
				qerr();
			ap->a_type = S_INDEX;
		} else
			unget(c);
	}
	return (ap->a_type);
}

expr(ap)
register struct addr *ap;
{
	register c;
	struct addr rop;

	term(ap);
	if (ap->a_type != S_ABS)
		return;
	for (;;) {
		c = getnb();
		if ((c=='<' || c=='>') && c!=getnb())
			qerr();
		if (ctype[c] != BINOP) {
			unget(c);
			break;
		}
		term(&rop);
		if (c == '^') {
			ap->a_type = rop.a_type;
			continue;
		}
		switch(c) {

		case '+':
			ap->a_addr += rop.a_addr;
			break;

		case '-':
			ap->a_addr -= rop.a_addr;
			break;

		case '*':
			ap->a_addr *= rop.a_addr;
			break;

		case '%':
			ap->a_addr /= rop.a_addr;
			break;

		case '&':
			ap->a_addr &= rop.a_addr;
			break;

		case '|':
			ap->a_addr |= rop.a_addr;
			break;

		case '>':
			ap->a_addr >>= rop.a_addr;
			break;

		case '<':
			ap->a_addr <<= rop.a_addr;
		}
	}
}

term(ap)
register struct addr *ap;
{
	register c, n;
	char id[NCPS];
	struct sym *sp;
	struct tsym *tp;
	int r, v;

	if ((c = getnb()) == '[') {
		expr(ap);
		if (getnb() != ']')
			qerr();
		return;
	}
	if (c == '-') {
		expr(ap);
		ap->a_addr = -ap->a_addr;
		return;
	}
	if (c == '!') {
		expr(ap);
		ap->a_addr = ~ap->a_addr;
		return;
	}
	if (c == '\'') {
		if ((c = get()) == '\0')
			qerr();
		ap->a_type = S_ABS;
		ap->a_addr = c;
		return;
	}
	if (ctype[c] == DIGIT) {
		ap->a_type = S_ABS;
		r = 10;
		if (c == '0') {
			r = 8;
			if ((c = get()) == 'x') {
				r = 16;
				c = get();
			}
		}
		n = 0;
		while ((v = digit(c, r)) >= 0) {
			n = r*n + v;
			c = get();
		}
		if (c=='f' || c=='b') {
			if (n < 10) {
				if (c == 'f')
					tp = tsymp[n].t_fp; else
					tp = tsymp[n].t_bp;
				if (tp != NULL) {
					ap->a_addr = tp->t_addr;
					return;
				}
			}
			err('u');
			ap->a_addr = 256;
			return;
		}
		unget(c);
		ap->a_addr = n;
		return;
	}
	if (ctype[c] == LETTER) {
		getid(c, id);
		if ((sp = lookup(id, 0)) != NULL) {
			ap->a_type = sp->s_type;
			ap->a_addr = sp->s_addr;
			return;
		}
		err('u');
		ap->a_type = S_ABS;
		ap->a_addr = 256;
		return;
	}
	qerr();
}

digit(c, r)
register c, r;
{
	if (r == 16) {
		if (c >= 'A' && c <= 'F')
			return (c - 'A' + 10);
		if (c >= 'a' && c <= 'f')
			return (c - 'a' + 10);
	}
	if (c >= '0' && c <= '9')
		return (c - '0');
	return (-1);
}

list()
{
	register char *wp;
	register nb;

	if (lfp==NULL || lmode==NLIST)
		return;
	slew();
	while (ep < &eb[NERR])
		*ep++ = ' ';
	fprintf(lfp, "%.10s", eb);
	if (lmode == SLIST) {
		fprintf(lfp, "%24s%5d %s\n", "", line, ib);
		return;
	}
	fprintf(lfp, hlist?"   %04x":" %06o", laddr);
	if (lmode == ALIST) {
		fprintf(lfp, "%17s%5d %s\n", "", line, ib);
		return;
	}
	wp = cb;
	nb = cp - cb;
	list1(wp, nb, 1);
	fprintf(lfp, " %5d %s\n", line, ib);
	while ((nb -= 4) > 0) {
		wp += 4;
		slew();
		fprintf(lfp, "%17s", "");
		list1(wp, nb, 0);
		putc('\n', lfp);
	}
}

list1(wp, nb, f)
register char *wp;
register nb;
{
	register i;

	if (nb > 4)
		nb = 4;
	for (i=0; i<nb; ++i)
		fprintf(lfp, hlist?"  %02x":" %03o", (*wp++)&0377);
	if (f)
		while (i < 4) {
			fprintf(lfp, "    ");
			++i;
		}
}

slew()
{
	if (lop++ >= 60) {
		fprintf(lfp, "\fM6800 assembler, page %d\n", ++page);
		fprintf(lfp, "%s\n\n", tb);
		lop = 4;
	}
}

byte(n)
register n;
{
	if ((n&0200) != 0)
		n |= ~0377;
	if (n<-128 || n>127)
		err('a');
}

comma()
{
	if (getnb() != ',')
		qerr();
}

getid(c, id)
register c;
char *id;
{
	register char *p;

	p = id;
	do {
		if (p < &id[NCPS])
			*p++ = c;
	} while (ctype[c=get()]==LETTER || ctype[c]==DIGIT);
	unget(c);
	while (p < &id[NCPS])
		*p++ = 0;
}

getnb()
{
	register c;

	while ((c=get())==' ' || c=='\t')
		;
	return (c);
}

get()
{
	register c;

	if ((c = *ip) != '\0')
		++ip;
	return (c);
}

unget(c)
{
	if (c != '\0')
		--ip;
}

usage()
{
	fprintf(stderr, "Usage: 6800 [-los] file.\n");
	exit(1);
}

syminit()
{
	register struct sym *sp;

	sp = &sym[0];
	while (sp < &sym[NSYM]) {
		if (sp->s_name[0] == 0)
			break;
		++nsym;
		++sp;
	}
}

struct sym *
lookup(id, f)
char *id;
{
	register struct sym *sp;
	register char *p1, *p2;

	sp = sym;
	while (sp < &sym[nsym]) {
		p1 = id;
		p2 = sp->s_name;
		while (p1 < &id[NCPS]) {
			if (*p1 != *p2++)
				break;
			++p1;
		}
		if (p1 == &id[NCPS])
			return (sp);
		++sp;
	}
	if (f == 0)
		return (NULL);
	if (nsym >= NSYM) {
		fprintf(stderr, "Too many symbols!\n");
		exit(1);
	}
	p1 = id;
	p2 = sp->s_name;
	while (p1 < &id[NCPS])
		*p2++ = *p1++;
	sp->s_type = S_UND;
	sp->s_flag = 0;
	sp->s_addr = 256; /* Force ext. */
	++nsym;
	return (sp);
}

aerr()
{
	err('a');
}

qerr()
{
	err('q');
}

err(c)
register c;
{
	register char *p;

	p = eb;
	while (p < ep)
		if (c == *p++)
			return;
	if (p < &eb[NERR]) {
		*p++ = c;
		ep = p;
	}
	if (c == 'q') {
		++eflag;
		unwind();
	}
}

diag()
{
	register char *p;
	register n;

	if (ep > eb) {
		p = eb;
		n = 0;
		while (p < ep) {
			putchar(*p++);
			++n;
		}
		while (n < NERR) {
			putchar(' ');
			++n;
		}
		printf(" %4d %s\n", line, ib);
	}
}

outd(op, r, ap, f)
register struct addr *ap;
{
	register a, t;

	a = ap->a_addr;
	t = ap->a_type;
	if (r==S_B || r==S_X)
		op |= 0x40;
	if (t == S_LIT) {
		if ((f&S_LV) != 0)
			aerr();
		outb(op);
		if ((f&S_16) != 0)
			outw(ap->a_addr); else
			outb(ap->a_addr);
		return;
	}
	if (t == S_INDEX) {
		outx(op, a);
		return;
	}
	if (t == S_ABS) {
		if (a < 0x100) {
			outb(op | 0x10);
			outb(a);
		} else {
			outb(op | 0x30);
			outw(a);
		}
		return;
	}
	aerr();
}

outx(op, a)
{
	outb(op | 0x20);
	byte(a);
	outb(a);
}

outw(w)
register w;
{
	outb(w>>8);
	outb(w);
}

outb(b)
register b;
{
	if (cp < &cb[NCODE])
		*cp++ = b;
	++dot->s_addr;
}

struct	sym	sym[NSYM] = {

	".",		S_ABS,		0,	0,

	".byte",	S_BYTE,		0,	0,
	".word",	S_WORD,		0,	0,
	".ascii",	S_ASCII,	0,	0,
	".asciz",	S_ASCIZ,	0,	0,
	".blkb",	S_BLKB,		0,	0,
	".page",	S_PAGE,		0,	0,
	".title",	S_TITLE,	0,	0,
	".hlist",	S_HLIST,	0,	0,
	".olist",	S_OLIST,	0,	0,

	"a",		S_A,		0,	0,
	"b",		S_B,		0,	0,
	"s",		S_S,		0,	0,
	"x",		S_X,		0,	0,
	"p",		S_P,		0,	0,

	"nop",		S_OP0,		0,	0x01,
	"clv",		S_OP0,		0,	0x0A,
	"sev",		S_OP0,		0,	0x0B,
	"clc",		S_OP0,		0,	0x0C,
	"sec",		S_OP0,		0,	0x0D,
	"cli",		S_OP0,		0,	0x0E,
	"sei",		S_OP0,		0,	0x0F,
	"daa",		S_OP0,		0,	0x19,
	"rts",		S_OP0,		0,	0x39,
	"rti",		S_OP0,		0,	0x3B,
	"wait",		S_OP0,		0,	0x3E,
	"sys",		S_OP0,		0,	0x3F,

	"neg",		S_OP1,		0,	0x40,
	"com",		S_OP1,		0,	0x43,
	"lsr",		S_OP1,		0,	0x44,
	"ror",		S_OP1,		0,	0x46,
	"asr",		S_OP1,		0,	0x47,
	"asl",		S_OP1,		0,	0x48,
	"rol",		S_OP1,		0,	0x49,
	"dec",		S_OP1,		0,	0x4A,
	"inc",		S_OP1,		0,	0x4C,
	"tst",		S_OP1,		0,	0x4D,
	"clr",		S_OP1,		0,	0x4F,
	"jmp",		S_OP1,		S_LV,	0x4E,
	"jsr",		S_OP1,		S_LV,	0x8D,

	"br",		S_OP2,		0,	0x20,
	"bhi",		S_OP2,		0,	0x22,
	"blos",		S_OP2,		0,	0x23,
	"bcc",		S_OP2,		0,	0x24,
	"bcs",		S_OP2,		0,	0x25,
	"bne",		S_OP2,		0,	0x26,
	"beq",		S_OP2,		0,	0x27,
	"bvc",		S_OP2,		0,	0x28,
	"bvs",		S_OP2,		0,	0x29,
	"bpl",		S_OP2,		0,	0x2A,
	"bmi",		S_OP2,		0,	0x2B,
	"bge",		S_OP2,		0,	0x2C,
	"blt",		S_OP2,		0,	0x2D,
	"bgt",		S_OP2,		0,	0x2E,
	"ble",		S_OP2,		0,	0x2F,
	"bhis",		S_OP2,		0,	0x24,
	"blo",		S_OP2,		0,	0x25,
	"bsr",		S_OP2,		0,	0x8D,

	"sub",		S_OP3,		0,	0x80,
	"cmp",		S_OP3,		0,	0x81,
	"sbc",		S_OP3,		0,	0x82,
	"and",		S_OP3,		0,	0x84,
	"bit",		S_OP3,		0,	0x85,
	"xor",		S_OP3,		0,	0x88,
	"adc",		S_OP3,		0,	0x89,
	"or",		S_OP3,		0,	0x8A,
	"add",		S_OP3,		0,	0x8B,

	"mov",		S_OP4,		0,	0,

	"push",		S_OP5,		0,	0x36,
	"pop",		S_OP5,		0,	0x32
};
