Charles.Forsyth20060303a828770d19 years agoHistory
457 lines · 8.8 KB · C
RawDownload
#include "lib9.h"#include "isa.h"#include "interp.h" /* s800 disassembler. *//* does not handle stuff that won't be generated */ typedef struct instr Instr; struct instr{	ulong	value;		/* bits 31-00 */	uchar	op;		/* bits 31-26 */	uchar	subop;		/* bits 11-05 */	uchar	sysop;		/* bits 12-05 */	uchar	reg0;		/* bits 25-21 */	uchar	reg1;		/* bits 20-16 */	uchar	reg2;		/* bits 4-0 */	uchar	space;		/* bits 15-14 */	uchar	indexed;	/* bit 13 */	uchar	cond;		/* bits 15-13 */	uchar	sr;		/* bits 13,15,14 */	uchar	ftype;		/* bits 12-9 */	uchar	simm;		/* bit 12 */	uchar	store;		/* bit 9 */	uchar	size;		/* bits 8-6 */	uchar	mod;		/* bit 5 */	uchar	shz;		/* bit 9-5 */	long	imm21;		/* bits 20-00 */	short	simm14;		/* bits 13-01, sign 00 */	short	simm11;		/* bits 10-01, sign 00 */	short	simm5;		/* bits 4-1, sign 0 */	short	off;		/* bits 13-02, sign 00 */	char	csimm5;		/* bits 20-17, sign 16 */	char	*curr;		/* current fill level in output buffer */	char	*end;		/* end of buffer */}; typedef struct opdec	Opdec; struct opdec{	char	*mnem;	void	(*func)(Instr *, char *);}; static char	ill[]	= "ILL";static char	sizes[]	= "BHWXXXXX"; static char	*conds[8]	={	"never",	"equal",	"less",	"leq",	"lessu",	"lequ",	"sv",	"odd",}; static char	*fconds[8]	={	"F",	"==",	"<",	"<=",	">",	">=",	"!=",	"T",}; static void	das_nil(Instr *, char *);static void	das_sys(Instr *, char *);static void	das_arith(Instr *, char *);static void	das_ldwx(Instr *, char *);static void	das_ld(Instr *, char *);static void	das_ldil(Instr *, char *);static void	das_ldo(Instr *, char *);static void	das_st(Instr *, char *);static void	das_fldst(Instr *, char *);static void	das_fltc(Instr *, char *);static void	das_combt(Instr *, char *);static void	das_ibt(Instr *, char *);static void	das_combf(Instr *, char *);static void	das_ibf(Instr *, char *);static void	das_extrs(Instr *, char *);static void	das_be(Instr *, char *);static void	das_bx(Instr *, char *); Opdec	dastab[1 << 6]	={	{ill,		das_sys},	/* 0x00 */	{ill,		das_nil},	/* 0x01 */	{ill,		das_arith},	/* 0x02 */	{ill,		das_ldwx},	/* 0x03 */	{ill,		das_nil},	/* 0x04 */	{ill,		das_nil},	/* 0x05 */	{ill,		das_nil},	/* 0x06 */	{ill,		das_nil},	/* 0x07 */	{ill,		das_ldil},	/* 0x08 */	{ill,		das_nil},	/* 0x09 */	{ill,		das_nil},	/* 0x0A */	{ill,		das_fldst},	/* 0x0B */	{ill,		das_fltc},	/* 0x0C */	{ill,		das_ldo},	/* 0x0D */	{ill,		das_nil},	/* 0x0E */	{ill,		das_nil},	/* 0x0F */ 	{"LDB",		das_ld},	/* 0x10 */	{"LDH",		das_ld},	/* 0x11 */	{"LDW",		das_ld},	/* 0x12 */	{ill,		das_nil},	/* 0x13 */	{ill,		das_nil},	/* 0x14 */	{ill,		das_nil},	/* 0x15 */	{ill,		das_nil},	/* 0x16 */	{ill,		das_nil},	/* 0x17 */	{"STB",		das_st},	/* 0x18 */	{"STH",		das_st},	/* 0x19 */	{"STW",		das_st},	/* 0x1A */	{ill,		das_nil},	/* 0x1B */	{ill,		das_nil},	/* 0x1C */	{ill,		das_nil},	/* 0x1D */	{ill,		das_nil},	/* 0x1E */	{ill,		das_nil},	/* 0x1F */ 	{ill,		das_combt},	/* 0x20 */	{"COM",		das_ibt},	/* 0x21 */	{ill,		das_combf},	/* 0x22 */	{"COM",		das_ibf},	/* 0x23 */	{ill,		das_nil},	/* 0x24 */	{ill,		das_nil},	/* 0x25 */	{ill,		das_nil},	/* 0x26 */	{ill,		das_nil},	/* 0x27 */	{ill,		das_nil},	/* 0x28 */	{"ADD",		das_ibt},	/* 0x29 */	{ill,		das_nil},	/* 0x2A */	{"ADD",		das_ibf},	/* 0x2B */	{ill,		das_nil},	/* 0x2C */	{ill,		das_nil},	/* 0x2D */	{ill,		das_nil},	/* 0x2E */	{ill,		das_nil},	/* 0x2F */ 	{ill,		das_nil},	/* 0x30 */	{ill,		das_nil},	/* 0x31 */	{ill,		das_nil},	/* 0x32 */	{ill,		das_nil},	/* 0x33 */	{ill,		das_extrs},	/* 0x34 */	{ill,		das_nil},	/* 0x35 */	{ill,		das_nil},	/* 0x36 */	{ill,		das_nil},	/* 0x37 */	{"BE",		das_be},	/* 0x38 */	{"BLE",		das_be},	/* 0x39 */	{ill,		das_bx},	/* 0x3A */	{ill,		das_nil},	/* 0x3B */	{ill,		das_nil},	/* 0x3C */	{ill,		das_nil},	/* 0x3D */	{ill,		das_nil},	/* 0x3E */	{ill,		das_nil},	/* 0x3F */}; static voidbprint(Instr *i, char *fmt, ...){	va_list arg; 	va_start(arg, fmt);	i->curr = vseprint(i->curr, i->end, fmt, arg);	va_end(arg);} static voiddecode(ulong *pc, Instr *i){	ulong w;	int t; 	w = *pc; 	i->value = w;	i->op = (w >> 26) & 0x3F;	i->subop = (w >> 5) & 0x7F;	i->sysop = (w >> 5) & 0xFF;	i->reg0 = (w >> 21) & 0x1F;	i->reg1 = (w >> 16) & 0x1F;	i->reg2 = w & 0x1F;	i->space = (w >> 14) & 0x03;	i->indexed = (w >> 13) & 0x01;	i->cond = (w >> 13) & 0x07;	i->sr = (i->cond >> 1) | ((i->cond & 1) << 2);	i->ftype = (w >> 9) & 0xF;	i->simm = (w >> 12) & 0x01;	i->store = (w >> 9) & 0x01;	i->size = (w >> 6) & 0x07;	i->mod = (w >> 5) & 0x01;	i->shz = (w >> 5) & 0x1F;	i->imm21 = w & 0x01FFFFF;	i->simm14 = (w >> 1) & 0x1FFF;	i->simm11 = (w >> 1) & 0x03FF;	i->simm5 = (w >> 1) & 0x0F;	i->off = ((w >> 3) & 0x3FF) | ((w & (1 << 2)) << 8);	i->csimm5 = (w >> 17) & 0x0F;	if(w & 1) {		i->simm14 |= ~((1 << 13) - 1);		i->simm11 |= ~((1 << 10) - 1);		i->simm5 |= ~((1 << 4) - 1);		i->off |= ~((1 << 10) - 1);	}	if(w & (1 << 16))		i->csimm5 |= ~((1 << 4) - 1);} static voiddas_ill(Instr *i){	das_nil(i, ill);} static voiddas_nil(Instr *i, char *m){	bprint(i, "%s\t%lx", m, i->value);} static voiddas_sys(Instr *i, char *m){	switch(i->sysop) {	case 0x85:		bprint(i, "LDSID\t(sr%d,r%d),r%d", i->sr, i->reg0, i->reg2);		break;	case 0xC1:		bprint(i, "MTSP\tr%d,sr%d", i->reg1, i->sr);		break;	default:		das_ill(i);	}} static voiddas_arith(Instr *i, char *m){	switch(i->subop) {	case 0x10:		m = "AND";		break;	case 0x12:		if (i->reg1 + i->reg0 + i->reg2 == 0) {			bprint(i, "NOP");			return;		}		m = "OR";		break;	case 0x14:		m = "XOR";		break;	case 0x20:		m = "SUB";		break;	case 0x30:		m = "ADD";		break;	case 0x32:		m = "SH1ADD";		break;	case 0x34:		m = "SH2ADD";		break;	default:		das_ill(i);		return;	} 	bprint(i, "%s\tr%d,r%d,r%d", m, i->reg1, i->reg0, i->reg2);} static voiddas_ldwx(Instr *i, char *m){	bprint(i, "LD%cX\tr%d(r%d),r%d", sizes[i->size], i->reg0, i->reg1, i->reg2);} static voiddas_ld(Instr *i, char *m){	bprint(i, "%s\t%d(r%d),r%d", m, i->simm14, i->reg0, i->reg1);} static ulongunfrig17(ulong v){	ulong r; 	r = ((v >> 3) & 0x3FF) |		((v & (1 << 2)) << 8) |		((v & (0x1F << 16)) >> 5);	if (v & 1)		r |= ~((1 << 16) - 1);	return r << 2;} static ulongunfrig21(ulong v){	return (((v & 1) << 20) |		((v & (0x7FF << 1)) << 8) |		((v >> 12) & 3) |		((v & (3 << 14)) >> 7) |		((v & (0x1F << 16)) >> 14)) << 11;} static voiddas_ldil(Instr *i, char *m){	bprint(i, "LDIL\tL%%0x%lx,r%d", unfrig21(i->imm21), i->reg0);} static voiddas_ldo(Instr *i, char *m){	bprint(i, "LDO\t%d(r%d),r%d", i->simm14, i->reg0, i->reg1);} static voiddas_st(Instr *i, char *m){	bprint(i, "%s\tr%d,%d(r%d)", m, i->reg1, i->simm14, i->reg0);} static voiddas_fldst(Instr *i, char *m){	if (i->simm) {		if (i->store)			bprint(i, "FSTDS\tfr%d,%d(r%d)", i->reg2, i->csimm5, i->reg0);		else			bprint(i, "FLDDS\t%d(r%d),fr%d", i->reg0, i->csimm5, i->reg2);	}	else {		if (i->store)			bprint(i, "FSTDX\tfr%d,r%d(r%d)", i->reg2, i->reg1, i->reg0);		else			bprint(i, "FLDDX\tr%d(r%d),fr%d", i->reg0, i->reg1, i->reg2);	}} static voiddas_fltc(Instr *i, char *m){	char *o; 	switch (i->ftype) {	case 2:		bprint(i, "FTEST");		break;	case 6:		bprint(i, "FCMP\tfr%d,%s,fr%d", i->reg0, fconds[i->reg2 >> 2], i->reg1);		break;	case 7:		switch (i->cond) {		case 0:			o = "ADD";			break;		case 1:			o = "SUB";			break;		case 2:			o = "MUL";			break;		case 3:			o = "DIV";			break;		default:			das_ill(i);			return;		}		bprint(i, "F%s\tfr%d,fr%d,fr%d", o, i->reg0, i->reg1, i->reg2);		break;	default:		das_ill(i);	}} static voiddas_combt(Instr *i, char *m){	bprint(i, "COMBT,%s\tr%d,r%d,%d", conds[i->cond], i->reg1, i->reg0, i->off);} static voiddas_ibt(Instr *i, char *m){	bprint(i, "%sIBT,%s\t%d,r%d,%d", m, conds[i->cond], i->csimm5, i->reg0, i->off);} static voiddas_combf(Instr *i, char *m){	bprint(i, "COMBF,%s\tr%d,r%d,%d", conds[i->cond], i->reg1, i->reg0, i->off);} static voiddas_ibf(Instr *i, char *m){	bprint(i, "%sIBF,%s\t%d,r%d,%d", m, conds[i->cond], i->csimm5, i->reg0, i->off);} static voiddas_extrs(Instr *i, char *m){	bprint(i, "EXTRS\tr%d,%d,%d,r%d", i->reg0, i->shz, 32 - i->reg2, i->reg1);} static voiddas_be(Instr *i, char *m){	bprint(i, "%s\t%d(sr%d,r%d)", m, unfrig17(i->value), i->sr, i->reg0);} static voiddas_bx(Instr *i, char *m){	switch(i->cond) {	case 0:		bprint(i, "BL\t%d,r%d", unfrig17(i->value), i->reg0);		break;	case 6:		bprint(i, "BV\tr%d(r%d)", i->reg1, i->reg0);		break;	default:		das_ill(i);	}} static intinst(ulong *pc){	Instr instr;	static char buf[128]; 	decode(pc, &instr);	instr.curr = buf;	instr.end = buf + sizeof(buf) - 1;	(*dastab[instr.op].func)(&instr, dastab[instr.op].mnem);	if (cflag > 5)		print("\t%.8lux %.8lux %s\n", pc, *pc, buf);	else		print("\t%.8lux %s\n", pc, buf);} voiddas(ulong *x, int n){	while (--n >= 0)		inst(x++);}