forsyth20121205-174063a80cc13 years agoHistory
833 lines · 17.0 KB · C
RawDownload
#include <lib9.h> 	/* Sparc disassembler and related functions */ typedef struct instr Instr; struct opcode{	char	*mnemonic;	void	(*f)(Instr*, char*);	int	flag;}; static	char FRAMENAME[] = ".frame";  struct instr{	uchar	op;		/* bits 31-30 */	uchar	rd;		/* bits 29-25 */	uchar	op2;		/* bits 24-22 */	uchar	a;		/* bit  29    */	uchar	cond;		/* bits 28-25 */	uchar	op3;		/* bits 24-19 */	uchar	rs1;		/* bits 18-14 */	uchar	i;		/* bit  13    */	uchar	asi;		/* bits 12-05 */	uchar	rs2;		/* bits 04-00 */	short	simm13;		/* bits 12-00, signed */	ushort	opf;		/* bits 13-05 */	ulong	immdisp22;	/* bits 21-00 */	ulong	simmdisp22;	/* bits 21-00, signed */	ulong	disp30;		/* bits 30-00 */	ulong	imm32;		/* SETHI+ADD constant */	int	target;		/* SETHI+ADD dest reg */	long	w0;	long	w1;	ulong	addr;		/* pc of instruction */	char*	curr;		/* current fill level in output buffer */	char*	end;		/* end of buffer */	int 	size;		/* number of longs in instr */	char*	err;		/* errmsg */}; static	int	dascase; static int	mkinstr(ulong*, Instr*);static void	bra1(Instr*, char*, char*[]);static void	bra(Instr*, char*);static void	fbra(Instr*, char*);static void	cbra(Instr*, char*);static void	unimp(Instr*, char*);static void	fpop(Instr*, char*);static void	shift(Instr*, char*);static void	sethi(Instr*, char*);static void	load(Instr*, char*);static void	loada(Instr*, char*);static void	store(Instr*, char*);static void	storea(Instr*, char*);static void	add(Instr*, char*);static void	cmp(Instr*, char*);static void	wr(Instr*, char*);static void	jmpl(Instr*, char*);static void	rd(Instr*, char*);static void	loadf(Instr*, char*);static void	storef(Instr*, char*);static void	loadc(Instr*, char*);static void	loadcsr(Instr*, char*);static void	trap(Instr*, char*); static struct opcode sparcop0[8] = {	/* [0] */	"UNIMP",	unimp,	0,	/* page 137 */		0,		0,	0,	/* [2] */	"B",		bra,	0,	/* page 119 */		0,		0,	0,	/* [4] */	"SETHI",	sethi,	0,	/* page 104 */		0,		0,	0,	/* [6] */	"FB",		fbra,	0,	/* page 121 */	/* [7] */	"CB",		cbra,	0,	/* page 123 */}; static struct opcode sparcop2[64] = {	/* [0x00] */	"ADD",		add,	0,	/* page 108 */	/* [0x01] */	"AND",		add,	0,	/* page 106 */	/* [0x02] */	"OR",		add,	0,	/* [0x03] */	"XOR",		add,	0,	/* [0x04] */	"SUB",		add,	0,	/* page 110 */	/* [0x05] */	"ANDN",		add,	0,	/* [0x06] */	"ORN",		add,	0,	/* [0x07] */	"XORN",		add,	0,	/* [0x08] */	"ADDX",		add,	0,			0,		0,	0,	/* [0x0A] */	"UMUL",		add,	0,	/* page 113 */	/* [0x0B] */	"SMUL",		add,	0,	/* [0x0C] */	"SUBX",		add,	0,			0,		0,	0,	/* [0x0E] */	"UDIV",		add,	0,	/* page 115 */	/* [0x0F] */	"SDIV",		add,	0,	/* [0x10] */	"ADDCC",	add,	0,	/* [0x11] */	"ANDCC",	add,	0,	/* [0x12] */	"ORCC",		add,	0,	/* [0x13] */	"XORCC",	add,	0,	/* [0x14] */	"SUBCC",	cmp,	0,	/* [0x15] */	"ANDNCC",	add,	0,	/* [0x16] */	"ORNCC",	add,	0,	/* [0x17] */	"XORNCC",	add,	0,	/* [0x18] */	"ADDXCC",	add,	0,			0,		0,	0,	/* [0x1A] */	"UMULCC",	add,	0,	/* [0x1B] */	"SMULCC",	add,	0,	/* [0x1C] */	"SUBXCC",	add,	0,			0,		0,	0,	/* [0x1E] */	"UDIVCC",	add,	0,	/* [0x1F] */	"SDIVCC",	add,	0,	/* [0x20] */	"TADD",		add,	0,	/* page 109 */	/* [0x21] */	"TSUB",		add,	0,	/* page 111 */	/* [0x22] */	"TADDCCTV",	add,	0,	/* [0x23] */	"TSUBCCTV",	add,	0,	/* [0x24] */	"MULSCC",	add,	0,	/* page 112 */	/* [0x25] */	"SLL",		shift,	0,	/* page 107 */	/* [0x26] */	"SRL",		shift,	0,	/* [0x27] */	"SRA",		shift,	0,	/* [0x28] */	"rdy",		rd,	0,	/* page 131 */	/* [0x29] */	"rdpsr",	rd,	0,	/* [0x2A] */	"rdwim",	rd,	0,	/* [0x2B] */	"rdtbr",	rd,	0,			0,		0,	0,			0,		0,	0,			0,		0,	0,			0,		0,	0,	/* [0x30] */	"wry",		wr,	0,	/* page 133 */	/* [0x31] */	"wrpsr",	wr,	0,	/* [0x32] */	"wrwim",	wr,	0,	/* [0x33] */	"wrtbr",	wr,	0,	/* [0x34] */	"FPOP",		fpop,	0,	/* page 140 */	/* [0x35] */	"FPOP",		fpop,	0,			0,		0,	0,			0,		0,	0,	/* [0x38] */	"JMPL",		jmpl,	0,	/* page 126 */	/* [0x39] */	"RETT",		add,	0,	/* page 127 */	/* [0x3A] */	"T",		trap,	0,	/* page 129 */	/* [0x3B] */	"flush",	add,	0,	/* page 138 */	/* [0x3C] */	"SAVE",		add,	0,	/* page 117 */	/* [0x3D] */	"RESTORE",	add,	0,}; static struct opcode sparcop3[64]={	/* [0x00] */	"ld",		load,	0,	/* [0x01] */	"ldub",		load,	0,	/* [0x02] */	"lduh",		load,	0,	/* [0x03] */	"ldd",		load,	0,	/* [0x04] */	"st",		store,	0,	/* [0x05] */	"stb",		store,	0,	/* page 95 */	/* [0x06] */	"sth",		store,	0,	/* [0x07] */	"std",		store,	0,			0,		0,	0,	/* [0x09] */	"ldsb",		load,	0,	/* page 90 */	/* [0x0A] */	"ldsh",		load,	0,			0,		0,	0,			0,		0,	0,	/* [0x0D] */	"ldstub",	store,	0,	/* page 101 */			0,		0,	0,	/* [0x0F] */	"swap",		load,	0,	/* page 102 */	/* [0x10] */	"lda",		loada,	0,	/* [0x11] */	"lduba",	loada,	0,	/* [0x12] */	"lduha",	loada,	0,	/* [0x13] */	"ldda",		loada,	0,	/* [0x14] */	"sta",		storea,	0,	/* [0x15] */	"stba",		storea,	0,	/* [0x16] */	"stha",		storea,	0,	/* [0x17] */	"stda",		storea,	0,			0,		0,	0,	/* [0x19] */	"ldsba",	loada,	0,	/* [0x1A] */	"ldsha",	loada,	0,			0,		0,	0,			0,		0,	0,	/* [0x1D] */	"ldstuba",	storea,	0,			0,		0,	0,	/* [0x1F] */	"swapa",	loada,	0,	/* [0x20] */	"ldf",		loadf,	0,	/* page 92 */	/* [0x21] */	"ldfsr",	loadf,	0,			0,		0,	0,	/* [0x23] */	"lddf",		loadf,	0,	/* [0x24] */	"stf",		storef,	0,	/* page 97 */	/* [0x25] */	"stfsr",	storef,	0,	/* [0x26] */	"stdfq",	storef,	0,	/* [0x27] */	"stdf",		storef,	0,			0,		0,	0,			0,		0,	0,			0,		0,	0,			0,		0,	0,			0,		0,	0,			0,		0,	0,			0,		0,	0,			0,		0,	0,	/* [0x30] */	"ldc",		loadc,	0,	/* page 94 */	/* [0x31] */	"ldcsr",	loadcsr,0,			0,		0,	0,	/* [0x33] */	"lddc",		loadc,	0,	/* [0x34] */	"stc",		loadc,	0,	/* page 99 */	/* [0x35] */	"stcsr",	loadcsr,0,	/* [0x36] */	"stdcq",	loadcsr,0,	/* [0x37] */	"stdc",		loadc,	0,}; 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 intdecode(ulong *pc, Instr *i){	ulong w; 	w = *pc; 	i->op = (w >> 30) & 0x03;	i->rd = (w >> 25) & 0x1F;	i->op2 = (w >> 22) & 0x07;	i->a = (w >> 29) & 0x01;	i->cond = (w >> 25) & 0x0F;	i->op3 = (w >> 19) & 0x3F;	i->rs1 = (w >> 14) & 0x1F;	i->i = (w >> 13) & 0x01;	i->asi = (w >> 5) & 0xFF;	i->rs2 = (w >> 0) & 0x1F;	i->simm13 = (w >> 0) & 0x1FFF;	if(i->simm13 & (1<<12))		i->simm13 |= ~((1<<13)-1);	i->opf = (w >> 5) & 0x1FF;	i->immdisp22 = (w >> 0) & 0x3FFFFF;	i->simmdisp22 = i->immdisp22;	if(i->simmdisp22 & (1<<21))		i->simmdisp22 |= ~((1<<22)-1);	i->disp30 = (w >> 0) & 0x3FFFFFFF;	i->w0 = w;	i->target = -1;	i->addr = (ulong)pc;	i->size = 1;	return 1;} static intmkinstr(ulong *pc, Instr *i){	Instr xi; 	if (decode(pc, i) < 0)		return -1;	if(i->op==0 && i->op2==4 && !dascase){		/* SETHI */		if(decode(pc+1, &xi) < 0)			return -1;		if(xi.op == 2 && xi.op3 == 0)		/* ADD */		if(xi.i == 1 && xi.rs1 == i->rd){	/* immediate to same reg */			i->imm32 = xi.simm13 + (i->immdisp22<<10);			i->target = xi.rd;			i->w1 = xi.w0;			i->size++;			return 1;		}	}	if(i->op==2 && i->opf==1 && !dascase){		/* FMOVS */		if (decode(pc+1, &xi) < 0)			return -1;		if(i->op==2 && i->opf==1)		/* FMOVS */		if(xi.rd==i->rd+1 && xi.rs2==i->rs2+1){	/* next pair */			i->w1 = xi.w0;			i->size++;		}	}	return 1;} static intinst(ulong *pc){	long disp;	Instr instr;	static char buf[128];	void (*f)(Instr*, char*); 	memset(&instr, 0, sizeof(instr));	instr.curr = buf;	instr.end = buf+sizeof(buf)-1;	if(mkinstr(pc, &instr) < 0)		return 4;	switch(instr.op){	case 0:		f = sparcop0[instr.op2].f;		if(f)			(*f)(&instr, sparcop0[instr.op2].mnemonic);		else			bprint(&instr, "unknown 0x%lux", instr.w0);		break; 	case 1:		disp = instr.disp30;		disp = (disp<<2)>>2;		bprint(&instr, "CALL\t0x%lux", pc+disp);		if (!dascase)			bprint(&instr, "(SB)");		break; 	case 2:		f = sparcop2[instr.op3].f;		if(f)			(*f)(&instr, sparcop2[instr.op3].mnemonic);		else			bprint(&instr, "unknown 0x%lux", instr.w0);		break; 	case 3:		f = sparcop3[instr.op3].f;		if(f)			(*f)(&instr, sparcop3[instr.op3].mnemonic);		else			bprint(&instr, "unknown 0x%lux", instr.w0);		break;	}	if (instr.err) {		if (instr.curr != buf)			bprint(&instr, "\t\t;");		bprint(&instr, instr.err);	}	print("\t%.8lux %s\n", (ulong)pc, buf); 	return instr.size;} voiddas(ulong *pc, int n){	ulong *e; 	e = pc + n;	while(pc < e)		pc += inst(pc);} static voidaddress(Instr *i){	bprint(i, "0x%lux(R%d)", i->simm13, i->rs1);} static voidunimp(Instr *i, char *m){	bprint(i, "%s", m);} static char	*bratab[16] = {	/* page 91 */	/* [0x0] */	"N",	/* [0x1] */	"E",	/* [0x2] */	"LE",	/* [0x3] */	"L",	/* [0x4] */	"LEU",	/* [0x5] */	"CS",	/* [0x6] */	"NEG",	/* [0x7] */	"VS",	/* [0x8] */	"A",	/* [0x9] */	"NE",	/* [0xA] */	"G",	/* [0xB] */	"GE",	/* [0xC] */	"GU",	/* [0xD] */	"CC",	/* [0xE] */	"POS",	/* [0xF] */	"VC",}; static char	*fbratab[16] = {	/* page 91 */	/* [0x0] */	"N",	/* [0x1] */	"NE",	/* [0x2] */	"LG",	/* [0x3] */	"UL",	/* [0x4] */	"L",	/* [0x5] */	"UG",	/* [0x6] */	"G",	/* [0x7] */	"U",	/* [0x8] */	"A",	/* [0x9] */	"E",	/* [0xA] */	"UE",	/* [0xB] */	"GE",	/* [0xC] */	"UGE",	/* [0xD] */	"LE",	/* [0xE] */	"ULE",	/* [0xF] */	"O",}; static char	*cbratab[16] = {	/* page 91 */	/* [0x0] */	"N",	/* [0x1] */	"123",	/* [0x2] */	"12",	/* [0x3] */	"13",	/* [0x4] */	"1",	/* [0x5] */	"23",	/* [0x6] */	"2",	/* [0x7] */	"3",	/* [0x8] */	"A",	/* [0x9] */	"0",	/* [0xA] */	"03",	/* [0xB] */	"02",	/* [0xC] */	"023",	/* [0xD] */	"01",	/* [0xE] */	"013",	/* [0xF] */	"012",}; static voidbra1(Instr *i, char *m, char *tab[]){	long imm; 	imm = i->simmdisp22;	if(i->a)		bprint(i, "%s%s.%c\t", m, tab[i->cond], 'A'+dascase);	else		bprint(i, "%s%s\t", m, tab[i->cond]);	bprint(i, "0x%lux", i->addr+4*imm);	if (!dascase)		bprint(i, "(SB)");} static voidbra(Instr *i, char *m)			/* page 91 */{	bra1(i, m, bratab);} static voidfbra(Instr *i, char *m)			/* page 93 */{	bra1(i, m, fbratab);} static voidcbra(Instr *i, char *m)			/* page 95 */{	bra1(i, m, cbratab);} static voidtrap(Instr *i, char *m)			/* page 101 */{	if(i->i == 0)		bprint(i, "%s%s\tR%d+R%d", m, bratab[i->cond], i->rs2, i->rs1);	else		bprint(i, "%s%s\t$0x%lux+R%d", m, bratab[i->cond], i->simm13, i->rs1);} static voidsethi(Instr *i, char *m)		/* page 89 */{	ulong imm; 	imm = i->immdisp22<<10;	if(dascase){		bprint(i, "%s\t0x%lux, R%d", m, imm, i->rd);		return;	}	if(imm==0 && i->rd==0){		bprint(i, "NOP");		return;	}	if(i->target < 0){		bprint(i, "MOVW\t$0x%lux, R%d", imm, i->rd);		return;	}	bprint(i, "MOVW\t$0x%lux, R%d", i->imm32, i->target);} static char ldtab[] = {	'W',	'B',	'H',	'D',}; static char*moveinstr(int op3, char *m){	char *s;	int c;	static char buf[8]; 	if(!dascase){		/* batshit cases */		if(op3 == 0xF || op3 == 0x1F)			return "SWAP";		if(op3 == 0xD || op3 == 0x1D)			return "TAS";	/* really LDSTUB */		c = ldtab[op3&3];		s = "";		if((op3&11)==1 || (op3&11)==2)

Lines 1–500 of 833.