forsyth20121205-174063a80cc13 years agoHistory
535 lines · 10.4 KB · C
RawDownload
#include <lib9.h> typedef struct	Instr	Instr;struct	Instr{	ulong	w;	ulong	addr;	uchar	op;			/* super opcode */ 	uchar	cond;			/* bits 28-31 */	uchar	store;			/* bit 20 */ 	uchar	rd;			/* bits 12-15 */	uchar	rn;			/* bits 16-19 */	uchar	rs;			/* bits 0-11 */ 	long	imm;			/* rotated imm */	char*	curr;			/* fill point in buffer */	char*	end;			/* end of buffer */	char*	err;			/* error message */}; typedef struct Opcode Opcode;struct Opcode{	char*	o;	void	(*f)(Opcode*, Instr*);	char*	a;}; static	void	format(char*, Instr*, char*);static	int	arminst(ulong, char, char*, int);static	int	armdas(ulong, char*, int); staticchar*	cond[16] ={	"EQ",	"NE",	"CS",	"CC",	"MI",	"PL",	"VS",	"VC",	"HI",	"LS",	"GE",	"LT",	"GT",	"LE",	0,	"NV"}; staticchar*	shtype[4] ={	"<<",	">>",	"->",	"@>"}; static intget4(ulong addr, long *v){	*v = *(ulong*)addr;	return 1;	} static char *_hexify(char *buf, ulong p, int zeros){	ulong d; 	d = p/16;	if(d)		buf = _hexify(buf, d, zeros-1);	else		while(zeros--)			*buf++ = '0';	*buf++ = "0123456789abcdef"[p&0x0f];	return buf;} intarmclass(long w){	int op; 	op = (w >> 25) & 0x7;	switch(op) {	case 0:	/* data processing r,r,r */		op = ((w >> 4) & 0xf);		if(op == 0x9) {			op = 48+16;		/* mul */			if(w & (1<<24)) {				op += 2;				if(w & (1<<22))					op++;	/* swap */				break;			}			if(w & (1<<21))				op++;		/* mla */			break;		}		op = (w >> 21) & 0xf;		if(w & (1<<4))			op += 32;		else		if(w & (31<<7))			op += 16;		break;	case 1:	/* data processing i,r,r */		op = (48) + ((w >> 21) & 0xf);		break;	case 2:	/* load/store byte/word i(r) */		op = (48+20) + ((w >> 22) & 0x1) + ((w >> 19) & 0x2);		break;	case 3:	/* load/store byte/word (r)(r) */		op = (48+20+4) + ((w >> 22) & 0x1) + ((w >> 19) & 0x2);		break;	case 4:	/* block data transfer (r)(r) */		op = (48+20+4+4) + ((w >> 20) & 0x1);		break;	case 5:	/* branch / branch link */		op = (48+20+4+4+2) + ((w >> 24) & 0x1);		break;	case 7:	/* coprocessor crap */		op = (48+20+4+4+2+2) + ((w >> 3) & 0x2) + ((w >> 20) & 0x1);		break;	default:		op = (48+20+4+4+2+2+4);		break;	}	return op;} static intdecode(ulong pc, Instr *i){	long w; 	get4(pc, &w);	i->w = w;	i->addr = pc;	i->cond = (w >> 28) & 0xF;	i->op = armclass(w);	return 1;} 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 voidarmdps(Opcode *o, Instr *i){	i->store = (i->w >> 20) & 1;	i->rn = (i->w >> 16) & 0xf;	i->rd = (i->w >> 12) & 0xf;	i->rs = (i->w >> 0) & 0xf;	if(i->rn == 15 && i->rs == 0) {		if(i->op == 8) {			format("MOVW", i,"CPSR, R%d");			return;		} else		if(i->op == 10) {			format("MOVW", i,"SPSR, R%d");			return;		}	} else	if(i->rn == 9 && i->rd == 15) {		if(i->op == 9) {			format("MOVW", i, "R%s, CPSR");			return;		} else		if(i->op == 11) {			format("MOVW", i, "R%s, SPSR");			return;		}	}	format(o->o, i, o->a);} static voidarmdpi(Opcode *o, Instr *i){	ulong v;	int c; 	v = (i->w >> 0) & 0xff;	c = (i->w >> 8) & 0xf;	while(c) {		v = (v<<30) | (v>>2);		c--;	}	i->imm = v;	i->store = (i->w >> 20) & 1;	i->rn = (i->w >> 16) & 0xf;	i->rd = (i->w >> 12) & 0xf;	i->rs = i->w&0x0f; 		/* RET is encoded as ADD #0,R14,R15 */	if(i->w == 0xe282f000){		format("RET", i, "");		return;	} else	format(o->o, i, o->a);} static voidarmsdti(Opcode *o, Instr *i){	ulong v; 	v = (i->w >> 0) & 0xfff;	if(!(i->w & (1<<23)))		v = -v;	i->store = ((i->w >> 23) & 0x2) | ((i->w >>21) & 0x1);	i->imm = v;	i->rn = (i->w >> 16) & 0xf;	i->rd = (i->w >> 12) & 0xf;		/* convert load of offset(PC) to a load immediate */	if(i->rn == 15 && (i->w & (1<<20)) && get4(i->addr+v+8, &i->imm) > 0)		format(o->o, i, "$#%i,R%d");	else		format(o->o, i, o->a);} static voidarmsdts(Opcode *o, Instr *i){	i->store = ((i->w >> 23) & 0x2) | ((i->w >>21) & 0x1);	i->rs = (i->w >> 0) & 0xf;	i->rn = (i->w >> 16) & 0xf;	i->rd = (i->w >> 12) & 0xf;	format(o->o, i, o->a);} static voidarmbdt(Opcode *o, Instr *i){	i->store = (i->w >> 21) & 0x3;		/* S & W bits */	i->rn = (i->w >> 16) & 0xf;	i->imm = i->w & 0xffff;	if(i->w == 0xe8fd8000)		format("RFE", i, "");	else		format(o->o, i, o->a);} static voidarmund(Opcode *o, Instr *i){	format(o->o, i, o->a);} static voidarmcdt(Opcode *o, Instr *i){	format(o->o, i, o->a);} static voidarmunk(Opcode *o, Instr *i){	format(o->o, i, o->a);} static voidarmb(Opcode *o, Instr *i){	ulong v; 	v = i->w & 0xffffff;	if(v & 0x800000)		v |= ~0xffffff;	i->imm = (v<<2) + i->addr + 8;	format(o->o, i, o->a);} static voidarmco(Opcode *o, Instr *i)		/* coprocessor instructions */{	int op, p, cp; 	char buf[1024]; 	i->rn = (i->w >> 16) & 0xf;	i->rd = (i->w >> 12) & 0xf;	i->rs = i->w&0xf;	cp = (i->w >> 8) & 0xf;	p = (i->w >> 5) & 0x7;	if(i->w&0x10) {		op = (i->w >> 20) & 0x0f;		snprint(buf, sizeof(buf), "#%x, #%x, R%d, C(%d), C(%d), #%x\n", cp, op, i->rd, i->rn, i->rs, p);	} else {		op = (i->w >> 21) & 0x07;		snprint(buf, sizeof(buf), "#%x, #%x, C(%d), C(%d), C(%d), #%x\n", cp, op, i->rd, i->rn, i->rs, p);	}	format(o->o, i, buf);} static Opcode opcodes[] ={	"AND%C%S",	armdps,	"R%s,R%n,R%d",	"EOR%C%S",	armdps,	"R%s,R%n,R%d",	"SUB%C%S",	armdps,	"R%s,R%n,R%d",	"RSB%C%S",	armdps,	"R%s,R%n,R%d",	"ADD%C%S",	armdps,	"R%s,R%n,R%d",	"ADC%C%S",	armdps,	"R%s,R%n,R%d",	"SBC%C%S",	armdps,	"R%s,R%n,R%d",	"RSC%C%S",	armdps,	"R%s,R%n,R%d",	"TST%C%S",	armdps,	"R%s,R%n,",	"TEQ%C%S",	armdps,	"R%s,R%n,",	"CMP%C%S",	armdps,	"R%s,R%n,",	"CMN%C%S",	armdps,	"R%s,R%n,",	"ORR%C%S",	armdps,	"R%s,R%n,R%d",	"MOVW%C%S",	armdps,	"R%s,R%d",	"BIC%C%S",	armdps,	"R%s,R%n,R%d",	"MVN%C%S",	armdps,	"R%s,R%d", 	"AND%C%S",	armdps,	"(R%s%h#%m),R%n,R%d",	"EOR%C%S",	armdps,	"(R%s%h#%m),R%n,R%d",	"SUB%C%S",	armdps,	"(R%s%h#%m),R%n,R%d",	"RSB%C%S",	armdps,	"(R%s%h#%m),R%n,R%d",	"ADD%C%S",	armdps,	"(R%s%h#%m),R%n,R%d",	"ADC%C%S",	armdps,	"(R%s%h#%m),R%n,R%d",	"SBC%C%S",	armdps,	"(R%s%h#%m),R%n,R%d",	"RSC%C%S",	armdps,	"(R%s%h#%m),R%n,R%d",	"TST%C%S",	armdps,	"(R%s%h#%m),R%n,",	"TEQ%C%S",	armdps,	"(R%s%h#%m),R%n,",	"CMP%C%S",	armdps,	"(R%s%h#%m),R%n,",	"CMN%C%S",	armdps,	"(R%s%h#%m),R%n,",	"ORR%C%S",	armdps,	"(R%s%h#%m),R%n,R%d",	"MOVW%C%S",	armdps,	"(R%s%h#%m),R%d",	"BIC%C%S",	armdps,	"(R%s%h#%m),R%n,R%d",	"MVN%C%S",	armdps,	"(R%s%h#%m),R%d", 	"AND%C%S",	armdps,	"(R%s%hR%m),R%n,R%d",	"EOR%C%S",	armdps,	"(R%s%hR%m),R%n,R%d",	"SUB%C%S",	armdps,	"(R%s%hR%m),R%n,R%d",	"RSB%C%S",	armdps,	"(R%s%hR%m),R%n,R%d",	"ADD%C%S",	armdps,	"(R%s%hR%m),R%n,R%d",	"ADC%C%S",	armdps,	"(R%s%hR%m),R%n,R%d",	"SBC%C%S",	armdps,	"(R%s%hR%m),R%n,R%d",	"RSC%C%S",	armdps,	"(R%s%hR%m),R%n,R%d",	"TST%C%S",	armdps,	"(R%s%hR%m),R%n,",	"TEQ%C%S",	armdps,	"(R%s%hR%m),R%n,",	"CMP%C%S",	armdps,	"(R%s%hR%m),R%n,",	"CMN%C%S",	armdps,	"(R%s%hR%m),R%n,",	"ORR%C%S",	armdps,	"(R%s%hR%m),R%n,R%d",	"MOVW%C%S",	armdps,	"(R%s%hR%m),R%d",	"BIC%C%S",	armdps,	"(R%s%hR%m),R%n,R%d",	"MVN%C%S",	armdps,	"(R%s%hR%m),R%d", 	"AND%C%S",	armdpi,	"$#%i,R%n,R%d",	"EOR%C%S",	armdpi,	"$#%i,R%n,R%d",	"SUB%C%S",	armdpi,	"$#%i,R%n,R%d",	"RSB%C%S",	armdpi,	"$#%i,R%n,R%d",	"ADD%C%S",	armdpi,	"$#%i,R%n,R%d",	"ADC%C%S",	armdpi,	"$#%i,R%n,R%d",	"SBC%C%S",	armdpi,	"$#%i,R%n,R%d",	"RSC%C%S",	armdpi,	"$#%i,R%n,R%d",	"TST%C%S",	armdpi,	"$#%i,R%n,",	"TEQ%C%S",	armdpi,	"$#%i,R%n,",	"CMP%C%S",	armdpi,	"$#%i,R%n,",	"CMN%C%S",	armdpi,	"$#%i,R%n,",	"ORR%C%S",	armdpi,	"$#%i,R%n,R%d",	"MOVW%C%S",	armdpi,	"$#%i,,R%d",	"BIC%C%S",	armdpi,	"$#%i,R%n,R%d",	"MVN%C%S",	armdpi,	"$#%i,,R%d", 	"MUL%C%S",	armdpi,	"R%s,R%m,R%n",	"MULA%C%S",	armdpi,	"R%s,R%m,R%n,R%d",	"SWPW",		armdpi,	"R%s,(R%n),R%d",	"SWPB",		armdpi,	"R%s,(R%n),R%d", 	"MOVW%C%p",	armsdti,"R%d,#%i(R%n)",	"MOVB%C%p",	armsdti,"R%d,#%i(R%n)",	"MOVW%C%p",	armsdti,"#%i(R%n),R%d",	"MOVB%C%p",	armsdti,"#%i(R%n),R%d", 	"MOVW%C%p",	armsdts,"R%d,%D(R%s%h#%m)(R%n)",	"MOVB%C%p",	armsdts,"R%d,%D(R%s%h#%m)(R%n)",	"MOVW%C%p",	armsdts,"%D(R%s%h#%m)(R%n),R%d",	"MOVB%C%p",	armsdts,"%D(R%s%h#%m)(R%n),R%d", 	"MOVM%C%P%a",	armbdt,	"R%n,[%r]",	"MOVM%C%P%a",	armbdt,	"[%r],R%n", 	"B%C",		armb,	"%b",	"BL%C",		armb,	"%b", 	"CDP%C",	armco,	"",	"CDP%C",	armco,	"",	"MCR%C",	armco,	"",	"MRC%C",	armco,	"", 	"UNK",		armunk,	"",}; static	char *mode[] = { 0, "IA", "DB", "IB" };static	char *pw[] = { "P", "PW", 0, "W" };static	char *sw[] = { 0, "W", "S", "SW" }; static voidformat(char *mnemonic, Instr *i, char *f){	int j, k, m, n; 	if(mnemonic)		format(0, i, mnemonic);	if(f == 0)		return;	if(mnemonic)		if(i->curr < i->end)			*i->curr++ = '\t';	for ( ; *f && i->curr < i->end; f++) {		if(*f != '%') {			*i->curr++ = *f;			continue;		}		switch (*++f) { 		case 'C':	/* .CONDITION */			if(cond[i->cond])				bprint(i, ".%s", cond[i->cond]);			break; 		case 'S':	/* .STORE */			if(i->store)				bprint(i, ".S");			break; 		case 'P':	/* P & U bits for block move */			n = (i->w >>23) & 0x3;			if (mode[n])				bprint(i, ".%s", mode[n]);			break; 		case 'D':	/* ~U bit for single data xfer */			if((i->w & (1<<23)) == 0)				bprint(i, "-");			break; 		case 'p':	/* P & W bits for single data xfer*/			if (pw[i->store])				bprint(i, ".%s", pw[i->store]);			break; 		case 'a':	/* S & W bits for single data xfer*/			if (sw[i->store])				bprint(i, ".%s", sw[i->store]);			break; 		case 's':			bprint(i, "%d", i->rs & 0xf);			break;						case 'm':			bprint(i, "%d", (i->w>>7) & 0x1f);			break; 		case 'h':			bprint(i, "%s", shtype[(i->w>>5) & 0x3]);			break; 		case 'n':			bprint(i, "%d", i->rn);			break; 		case 'd':			bprint(i, "%d", i->rd);			break; 		case 'i':			bprint(i, "%lux", i->imm);			break; 		case 'b':			bprint(i, "%lux", i->imm);			break; 		case 'r':			n = i->imm&0xffff;			j = 0;			k = 0;			while(n) {				m = j;				while(n&0x1) {					j++;					n >>= 1;				}				if(j != m) {					if(k)						bprint(i, ",");					if(j == m+1)						bprint(i, "R%d", m);					else						bprint(i, "R%d-R%d", m, j-1);					k = 1;				}				j++;				n >>= 1;			}			break;

Lines 1–500 of 535.