Charles.Forsyth20060303a828770d19 years agoHistory
961 lines · 20.2 KB · C
RawDownload
#include <lib9.h> /* * disassemble PowerPC opcodes in Plan9 format * Copyright © 1997 C H Forsyth (forsyth@terzarima.net) */ /* * ibm conventions for these: bit 0 is top bit *	from table 10-1 */typedef struct {	uchar	aa;		/* bit 30 */	uchar	crba;		/* bits 11-15 */	uchar	crbb;		/* bits 16-20 */	long	bd;		/* bits 16-29 */	uchar	crfd;		/* bits 6-8 */	uchar	crfs;		/* bits 11-13 */	uchar	bi;		/* bits 11-15 */	uchar	bo;		/* bits 6-10 */	uchar	crbd;		/* bits 6-10 */	union {		short	d;	/* bits 16-31 */		short	simm;		ushort	uimm;	};	uchar	fm;		/* bits 7-14 */	uchar	fra;		/* bits 11-15 */	uchar	frb;		/* bits 16-20 */	uchar	frc;		/* bits 21-25 */	uchar	frs;		/* bits 6-10 */	uchar	frd;		/* bits 6-10 */	uchar	crm;		/* bits 12-19 */	long	li;		/* bits 6-29 || b'00' */	uchar	lk;		/* bit 31 */	uchar	mb;		/* bits 21-25 */	uchar	me;		/* bits 26-30 */	uchar	nb;		/* bits 16-20 */	uchar	op;		/* bits 0-5 */	uchar	oe;		/* bit 21 */	uchar	ra;		/* bits 11-15 */	uchar	rb;		/* bits 16-20 */	uchar	rc;		/* bit 31 */	union {		uchar	rs;	/* bits 6-10 */		uchar	rd;	};	uchar	sh;		/* bits 16-20 */	ushort	spr;		/* bits 11-20 */	uchar	to;		/* bits 6-10 */	uchar	imm;		/* bits 16-19 */	ushort	xo;		/* bits 21-30, 22-30, 26-30, or 30 (beware) */	long	immediate;	long w0;	long w1;	ulong	addr;		/* pc of instruction */	short	target;	char	*curr;		/* current fill level in output buffer */	char	*end;		/* end of buffer */	int 	size;		/* number of longs in instr */	char	*err;		/* errmsg */} Instr; #define	IBF(v,a,b) (((ulong)(v)>>(32-(b)-1)) & ~(~0L<<(((b)-(a)+1))))#define	IB(v,b) IBF((v),(b),(b)) 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->aa = IB(w, 30);	i->crba = IBF(w, 11, 15);	i->crbb = IBF(w, 16, 20);	i->bd = IBF(w, 16, 29)<<2;	if(i->bd & 0x8000)		i->bd |= ~0L<<16;	i->crfd = IBF(w, 6, 8);	i->crfs = IBF(w, 11, 13);	i->bi = IBF(w, 11, 15);	i->bo = IBF(w, 6, 10);	i->crbd = IBF(w, 6, 10);	i->uimm = IBF(w, 16, 31);	/* also d, simm */	i->fm = IBF(w, 7, 14);	i->fra = IBF(w, 11, 15);	i->frb = IBF(w, 16, 20);	i->frc = IBF(w, 21, 25);	i->frs = IBF(w, 6, 10);	i->frd = IBF(w, 6, 10);	i->crm = IBF(w, 12, 19);	i->li = IBF(w, 6, 29)<<2;	if(IB(w, 6))		i->li |= ~0<<25;	i->lk = IB(w, 31);	i->mb = IBF(w, 21, 25);	i->me = IBF(w, 26, 30);	i->nb = IBF(w, 16, 20);	i->op = IBF(w, 0, 5);	i->oe = IB(w, 21);	i->ra = IBF(w, 11, 15);	i->rb = IBF(w, 16, 20);	i->rc = IB(w, 31);	i->rs = IBF(w, 6, 10);	/* also rd */	i->sh = IBF(w, 16, 20);	i->spr = IBF(w, 11, 20);	i->to = IBF(w, 6, 10);	i->imm = IBF(w, 16, 19);	i->xo = IBF(w, 21, 30);		/* bits 21-30, 22-30, 26-30, or 30 (beware) */	i->immediate = i->simm;	if(i->op == 15)		i->immediate <<= 16;	i->w0 = w;	i->target = -1;	i->addr = (ulong)pc;	i->size = 1;	return 1;} static intmkinstr(ulong *pc, Instr *i){	Instr x; 	if(decode(pc, i) < 0)		return -1;	/*	 * combine ADDIS/ORI (CAU/ORIL) into MOVW	 */	if (i->op == 15 && i->ra==0) {		if(decode(pc+1, &x) < 0)			return -1;		if (x.op == 24 && x.rs == x.ra && x.ra == i->rd) {			i->immediate |= (x.immediate & 0xFFFF);			i->w1 = x.w0;			i->target = x.rd;			i->size++;			return 1;		}	}	return 1;} static voidpglobal(Instr *i, long off, char *reg){	bprint(i, "%lux%s", off, reg);} static voidaddress(Instr *i){	if(i->simm < 0)		bprint(i, "-%lx(R%d)", -i->simm, i->ra);	else		bprint(i, "%lux(R%d)", i->immediate, i->ra);} static	char	*tcrbits[] = {"LT", "GT", "EQ", "VS"};static	char	*fcrbits[] = {"GE", "LE", "NE", "VC"}; typedef struct Opcode Opcode; struct Opcode {	uchar	op;	ushort	xo;	ushort	xomask;	char	*mnemonic;	void	(*f)(Opcode *, Instr *);	char	*ken;	int	flags;}; static void format(char *, Instr *, char *); static voidbranch(Opcode *o, Instr *i){	char buf[8];	int bo, bi; 	bo = i->bo & ~1;	/* ignore prediction bit */	if(bo==4 || bo==12 || bo==20) {	/* simple forms */		if(bo != 20) {			bi = i->bi&3;			sprint(buf, "B%s%%L", bo==12? tcrbits[bi]: fcrbits[bi]);			format(buf, i, 0);			bprint(i, "\t");			if(i->bi > 4)				bprint(i, "CR(%d),", i->bi/4);		} else			format("BR%L\t", i, 0);		if(i->op == 16)			format(0, i, "%J");		else if(i->op == 19 && i->xo == 528)			format(0, i, "(CTR)");		else if(i->op == 19 && i->xo == 16)			format(0, i, "(LR)");	} else		format(o->mnemonic, i, o->ken);} static voidaddi(Opcode *o, Instr *i){	if (i->op==14 && i->ra == 0)		format("MOVW", i, "%i,R%d");	else if(i->op==14 && i->simm < 0) {		bprint(i, "SUB\t$%d,R%d", -i->simm, i->ra);		if(i->rd != i->ra)			bprint(i, ",R%d", i->rd);	} else if(i->ra == i->rd) {		format(o->mnemonic, i, "%i");		bprint(i, ",R%d", i->rd);	} else		format(o->mnemonic, i, o->ken);} static voidaddis(Opcode *o, Instr *i){	long v; 	v = i->immediate;	if (i->op==15 && i->ra == 0)		bprint(i, "MOVW\t$%lux,R%d", v, i->rd);	else if(i->op==15 && v < 0) {		bprint(i, "SUB\t$%d,R%d", -v, i->ra);		if(i->rd != i->ra)			bprint(i, ",R%d", i->rd);	} else {		format(o->mnemonic, i, 0);		bprint(i, "\t$%ld,R%d", v, i->ra);		if(i->rd != i->ra)			bprint(i, ",R%d", i->rd);	}} static voidandi(Opcode *o, Instr *i){	if (i->ra == i->rs)		format(o->mnemonic, i, "%I,R%d");	else		format(o->mnemonic, i, o->ken);} static voidgencc(Opcode *o, Instr *i){	format(o->mnemonic, i, o->ken);} static voidgen(Opcode *o, Instr *i){	format(o->mnemonic, i, o->ken);	if (i->rc)		bprint(i, " [illegal Rc]");} static voidldx(Opcode *o, Instr *i){	if(i->ra == 0)		format(o->mnemonic, i, "(R%b),R%d");	else		format(o->mnemonic, i, "(R%b+R%a),R%d");	if(i->rc)		bprint(i, " [illegal Rc]");} static voidstx(Opcode *o, Instr *i){	if(i->ra == 0)		format(o->mnemonic, i, "R%d,(R%b)");	else		format(o->mnemonic, i, "R%d,(R%b+R%a)");	if(i->rc && i->xo != 150)		bprint(i, " [illegal Rc]");} static voidfldx(Opcode *o, Instr *i){	if(i->ra == 0)		format(o->mnemonic, i, "(R%b),F%d");	else		format(o->mnemonic, i, "(R%b+R%a),F%d");	if(i->rc)		bprint(i, " [illegal Rc]");} static voidfstx(Opcode *o, Instr *i){	if(i->ra == 0)		format(o->mnemonic, i, "F%d,(R%b)");	else		format(o->mnemonic, i, "F%d,(R%b+R%a)");	if(i->rc)		bprint(i, " [illegal Rc]");} static voiddcb(Opcode *o, Instr *i){	if(i->ra == 0)		format(o->mnemonic, i, "(R%b)");	else		format(o->mnemonic, i, "(R%b+R%a)");	if(i->rd)		bprint(i, " [illegal Rd]");	if(i->rc)		bprint(i, " [illegal Rc]");} static voidlw(Opcode *o, Instr *i, char r){	bprint(i, "%s\t", o->mnemonic);	address(i);	bprint(i, ",%c%d", r, i->rd);} static voidload(Opcode *o, Instr *i){	lw(o, i, 'R');} static voidfload(Opcode *o, Instr *i){	lw(o, i, 'F');} static voidsw(Opcode *o, Instr *i, char r){	char *m; 	m = o->mnemonic;	if (r == 'F')		format(m, i, "F%d,%l");	else		format(m, i, o->ken);} static voidstore(Opcode *o, Instr *i){	sw(o, i, 'R');} static voidfstore(Opcode *o, Instr *i){	sw(o, i, 'F');} static voidshifti(Opcode *o, Instr *i){	if (i->ra == i->rs)		format(o->mnemonic, i, "$%k,R%a");	else		format(o->mnemonic, i, o->ken);} static voidshift(Opcode *o, Instr *i){	if (i->ra == i->rs)		format(o->mnemonic, i, "R%b,R%a");	else		format(o->mnemonic, i, o->ken);} static voidadd(Opcode *o, Instr *i){	if (i->rd == i->ra)		format(o->mnemonic, i, "R%b,R%d");	else if (i->rd == i->rb)		format(o->mnemonic, i, "R%a,R%d");	else		format(o->mnemonic, i, o->ken);} static voidsub(Opcode *o, Instr *i){	format(o->mnemonic, i, 0);	bprint(i, "\t");	if(i->op == 31) {		bprint(i, "\tR%d,R%d", i->ra, i->rb);	/* subtract Ra from Rb */		if(i->rd != i->rb)			bprint(i, ",R%d", i->rd);	} else		bprint(i, "\tR%d,$%d,R%d", i->ra, i->simm, i->rd);} static voiddiv(Opcode *o, Instr *i){	format(o->mnemonic, i, 0);	if(i->op == 31)		bprint(i, "\tR%d,R%d", i->rb, i->ra);	else		bprint(i, "\t$%d,R%d", i->simm, i->ra);	if(i->ra != i->rd)		bprint(i, ",R%d", i->rd);} static voidand(Opcode *o, Instr *i){	if (i->op == 31) {		/* Rb,Rs,Ra */		if (i->ra == i->rs)			format(o->mnemonic, i, "R%b,R%a");		else if (i->ra == i->rb)			format(o->mnemonic, i, "R%s,R%a");		else			format(o->mnemonic, i, o->ken);	} else {		/* imm,Rs,Ra */		if (i->ra == i->rs)			format(o->mnemonic, i, "%I,R%a");		else			format(o->mnemonic, i, o->ken);	}} static voidor(Opcode *o, Instr *i){	if (i->op == 31) {		/* Rb,Rs,Ra */		if (i->rs == 0 && i->ra == 0 && i->rb == 0)			format("NOP", i, 0);		else if (i->rs == i->rb)			format("MOVW", i, "R%b,R%a");		else			and(o, i);	} else		and(o, i);} static voidshifted(Opcode *o, Instr *i){	format(o->mnemonic, i, 0);	bprint(i, "\t$%lux,", (ulong)i->uimm<<16);	if (i->rs == i->ra)		bprint(i, "R%d", i->ra);	else		bprint(i, "R%d,R%d", i->rs, i->ra);} static voidneg(Opcode *o, Instr *i){	if (i->rd == i->ra)		format(o->mnemonic, i, "R%d");	else		format(o->mnemonic, i, o->ken);} static	char	ir2[] = "R%a,R%d";		/* reverse of IBM order */static	char	ir3[] = "R%b,R%a,R%d";static	char	ir3r[] = "R%a,R%b,R%d";static	char	il3[] = "R%b,R%s,R%a";static	char	il2u[] = "%I,R%s,R%a";static	char	il3s[] = "$%k,R%s,R%a";static	char	il2[] = "R%s,R%a";static	char	icmp3[] = "R%a,R%b,%D";static	char	cr3op[] = "%b,%a,%d";static	char	ir2i[] = "%i,R%a,R%d";static	char	fp2[] = "F%b,F%d";static	char	fp3[] = "F%b,F%a,F%d";static	char	fp3c[] = "F%c,F%a,F%d";static	char	fp4[] = "F%a,F%c,F%b,F%d";static	char	fpcmp[] = "F%a,F%b,%D";static	char	ldop[] = "%l,R%d";static	char	stop[] = "R%d,%l";static	char	fldop[] = "%l,F%d";static	char	fstop[] = "F%d,%l";

Lines 1–500 of 961.