#include "dis48.h"

char	*InStr80[16] = {
	"out.s\t\tc", "out.x\t\tc", "in.4\t\ta", "in.4\t\tc", "uncnfg",
	"config", "move.a\t\tid, c", "shutdn", NULL, "add.a\t\tp+1, c", "reset",
	"buscc", NULL, NULL, "sreq", NULL
};

char	*InStr808[16] = {
	"inton", NULL, NULL, "buscb", NULL, NULL, NULL, NULL, NULL, NULL,
	NULL, NULL, "jump.a\t\t@a", "buscd", "jump.a\t\t@c", "intoff"
};

char *
#ifdef ANSI
Instr80(char *mem, NAddr *addr, char *out)
#else
Instr80(mem, addr, out)
char	*mem;
NAddr	*addr;
char	*out;
#endif
{
	Nybble	n;
	Nybble	fn;
	char	*p;
	char	c;
	NAddr	pc;
	int	disp;
	
	n = GetNybble(mem, (*addr)++);
	if ((p = InStr80[n]) != NULL)
		return(AppendStr(out, p));
		
	switch (n) {
	case 8:
		fn = GetNybble(mem, (*addr)++);
		if ((p = InStr808[fn]) != NULL) {
			if ((n == 0xc) || (n == 0xe))
				itype = ujump;
				
			return(AppendStr(out, p));
		}
			
		switch (fn) {
		case 1:
			n = GetNybble(mem, (*addr)++);
			p = AppendStr(out, (n == 0) ? "rsi" : "???");
			break;
			
		case 2:
			p = AppendStr(out, "move.p");
			n = GetNybble(mem, (*addr)++);
			p = Append16(p, n);
			APPEND_TAB(p);
			if ((p - out) < 8)
				APPEND_TAB(p);
				
			p = AppendImmNyb(p, mem, addr, n + 1);
			p = AppendStr(p, ", a");
			break;
			
		case 4:
		case 5:
		case 8:
		case 9:
			p = AppendStr(out, (fn & 1) ? "setb\t\t" : "clrb\t\t");
			p = AppendImmNyb(p, mem, addr, 1);
			p = AppendStr(p, (fn & 8) ? ", c" : ", a");
			break;
			
		case 6:
		case 7:
		case 0xa:
		case 0xb:
			c = (fn < 0xa) ? 'a' : 'c';
			pc = *addr + 1;
			n = GetNybble(mem, (*addr)++);
			disp = GetInt(mem, addr, 2);
			p = AppendStr(out, (disp == 0) ? "ret" : "br");
			p = AppendStr(p, (fn & 1) ? "bs\t\t" : "bc\t\t");
			APPEND_IMMMARK(p);
			APPEND_HEXMARK(p);
			APPEND_CHAR(p, hex[n]);
			APPEND_COMMA(p);
			APPEND_CHAR(p, c);
			if (disp != 0) {
				APPEND_COMMA(p);
				p = AppendRAddr(p, pc, disp, 2, 5);
			} else
				target = NOADDR;
			
			itype = branch;
			break;
		}
		
		break;
		
	case 0xc:
	case 0xf:
		p = AppendStr(out, (n == 0xc) ? "move" : "swap");
		p = AppendStr(p, ".1\t\tp, c, ");
		p = AppendImmNyb(p, mem, addr, 1);
		break;
		
	case 0xd:
		p = AppendStr(out, "move.1\t\tc, ");
		p = AppendImmNyb(p, mem, addr, 1);
		p = AppendStr(p, ", p");
		break;
	}
	
	return(p);
}

char	*InStr81b[8] = {
	NULL, NULL, "jump.a\t\ta", "jump.a\t\tc", "move.a\t\tpc, a",
	"move.a\t\tpc, c", "swap.a\t\ta, pc", "swap.a\t\tc, pc"
};

char	OpChr81[4] = {'a', 'b', 'c', 'd'};

char *
#ifdef ANSI
Instr81(char *mem, NAddr *addr, char *out)
#else
Instr81(mem, addr, out)
char	*mem;
NAddr	*addr;
char	*out;
#endif
{
	Nybble	n;
	Nybble	fn;
	char	*p;
	char	c;
	
	switch (n = GetNybble(mem, (*addr)++)) {
	case 0: case 1: case 2: case 3:
		p = AppendStr(out, "rln.w\t\t");
		APPEND_CHAR(p, OpChr81[n & 3]);
		break;
		
	case 4: case 5: case 6: case 7:
		p = AppendStr(out, "rrn.w\t\t");
		APPEND_CHAR(p, OpChr81[n & 3]);
		break;
		
	case 8:
		fn = GetNybble(mem, (*addr)++);
		n = GetNybble(mem, (*addr)++);
		p = AppendStr(out, (n < 8) ? "add" : "sub");
		p = AppendField(p, fn);
		if ((p - out) < 9)
			APPEND_TAB(p);
			
		fn = GetNybble(mem, (*addr)++);
		APPEND_IMMMARK(p);
		p = Append16(p, fn);
		APPEND_COMMA(p);
		APPEND_CHAR(p, OpChr81[n & 3]);
		break;
		
	case 9:
		p = AppendStr(out, "srb");
		p = AppendField(p, GetNybble(mem, (*addr)++));
		if ((p - out) < 9)
			APPEND_TAB(p);
			
		APPEND_CHAR(p, OpChr81[GetNybble(mem, (*addr)++) & 3]);
		break;
	
	case 0xa:
		fn = GetNybble(mem, (*addr)++);
		n = GetNybble(mem, (*addr)++);
		p = AppendStr(out, (n == 2) ? "swap" : "move");
		p = AppendField(p, fn);
		if ((p - out) < 9)
			APPEND_TAB(p);
			
		fn = GetNybble(mem, (*addr)++);
		c = (fn < 8) ? 'a' : 'c';
		fn = (fn & 7) + '0';
		if (n == 1) {
			APPEND_CHAR(p, 'r');
			APPEND_CHAR(p, fn);
		} else
			APPEND_CHAR(p, c);
			
		APPEND_COMMA(p);
		if (n == 1)
			APPEND_CHAR(p, c);
		else {
			APPEND_CHAR(p, 'r');
			APPEND_CHAR(p, fn);
		}
		
		break;
		
	case 0xb:
		n = GetNybble(mem, (*addr)++);
		p = AppendStr(out, ((n < 2) || (n > 7)) ? "???" : InStr81b[n]);
		itype = ujump;
		break;
		
	case 0xc: case 0xd: case 0xe: case 0xf:
		p = AppendStr(out, "srb.w\t\t");
		APPEND_CHAR(p, OpChr81[n & 3]);
		break;	
	}
	
	return(p);
}

char *
#ifdef ANSI
Instr8(char *mem, NAddr *addr, char *out)
#else
Instr8(mem, addr, out)
char	*mem;
NAddr	*addr;
char	*out;
#endif
{
	Nybble	n;
	Nybble	fn;
	char	*p;
	char	c;
	int	disp, pc;

	switch (fn = GetNybble(mem, (*addr)++)) {
	case 0:
		p = Instr80(mem, addr, out);
		break;
		
	case 1:
		p = Instr81(mem, addr, out);
		break;
	
	case 2:
		p = AppendStr(out, "clrb\t\t");
		p = AppendStBits(p, GetNybble(mem, (*addr)++));
		break;
		
	case 3:
		n = GetNybble(mem, (*addr)++);
		pc = *addr;
		disp = GetInt(mem, addr, 2);
		p = AppendStr(out, (disp == 0) ? "retbc\t\t" : "brbc\t\t");
		p = AppendStBits(p, n);
		if (disp != 0) {
			APPEND_COMMA(p);
			p = AppendRAddr(p, pc, disp, 2, 3);
		} else
			target = NOADDR;
		
		itype = branch;
		break;
	
	case 4:
	case 5:
		p = AppendStr(out, (fn == 4) ? "clrb\t\t" : "setb\t\t");
		p = AppendImmNyb(p, mem, addr, 1);
		p = AppendStr(p, ", st");
		break;
		
	case 6:
	case 7:
		c = (fn == 6) ? 'c' : 's';
		n = GetNybble(mem, (*addr)++);
		pc = *addr;
		disp = GetInt(mem, addr, 2);
		p = AppendStr(out, (disp == 0) ? "retb" : "brb");
		APPEND_CHAR(p, c);
		APPEND_TAB(p);
		APPEND_TAB(p);
		APPEND_IMMMARK(p);
		APPEND_HEXMARK(p);
		APPEND_CHAR(p, hex[n]);
		p = AppendStr(p, ", st");
		if (disp != 0) {
			APPEND_COMMA(p);
			p = AppendRAddr(p, pc, disp, 2, 3);
		} else
			target = NOADDR;
		
		itype = branch;
		break;
	
	case 8:
	case 9:
		n = GetNybble(mem, (*addr)++);
		pc = *addr;
		disp = GetInt(mem, addr, 2);
		p = AppendStr(out, (disp == 0) ?  "ret" : "br");
		p = AppendStr(p, (fn == 8) ? "ne" : "eq");
		p = AppendStr(p, "\t\tp, ");
		APPEND_IMMMARK(p);
		APPEND_CHAR(p, hex[n]);
		if (disp != 0) {
			APPEND_COMMA(p);
			p = AppendRAddr(p, pc, disp, 2, 3);
		} else
			target = NOADDR;
		
		itype = branch;
		break;
	
	case 0xc:
	case 0xe:
		pc = *addr;
		if (fn == 0xe)
			pc += 4;
			
		disp = GetInt(mem, addr, 4);
		p = AppendStr(out, (fn == 0xc) ? "jump" : "call");
		p = AppendStr(p, ".4\t\t");
		p = AppendRAddr(p, pc, disp, 4, (fn == 0xc) ? 2 : 6);
		itype = (fn == 0xc) ? jump : call;
		break;
		
	case 0xd:
	case 0xf:
		p = AppendStr(out, (fn == 0xd) ? "jump" : "call");
		p = AppendStr(p, ".a\t\t");
		pc = GetInt(mem, addr, 5);
		p = AppendAddr(p, pc);
		itype = (fn == 0xd) ? jump : call;
		target = pc;
		break;
	}

	return(p);	
}
