xref: /plan9/sys/src/libmach/qdb.c (revision 6891d8578618fb7ccda4a131c122d4d0e6580c4b)
17dd7cddfSDavid du Colombier #include <u.h>
27dd7cddfSDavid du Colombier #include <libc.h>
37dd7cddfSDavid du Colombier #include <bio.h>
47dd7cddfSDavid du Colombier #include <mach.h>
57dd7cddfSDavid du Colombier 
67dd7cddfSDavid du Colombier /*
747ad9175SDavid du Colombier  * PowerPC-specific debugger interface,
847ad9175SDavid du Colombier  * including 64-bit modes
9b0dcc5a8SDavid du Colombier  *	forsyth@terzarima.net
107dd7cddfSDavid du Colombier  */
117dd7cddfSDavid du Colombier 
127dd7cddfSDavid du Colombier static	char	*powerexcep(Map*, Rgetter);
134de34a7eSDavid du Colombier static	int	powerfoll(Map*, uvlong, Rgetter, uvlong*);
144de34a7eSDavid du Colombier static	int	powerinst(Map*, uvlong, char, char*, int);
154de34a7eSDavid du Colombier static	int	powerinstlen(Map*, uvlong);
164de34a7eSDavid du Colombier static	int	powerdas(Map*, uvlong, char*, int);
177dd7cddfSDavid du Colombier 
187dd7cddfSDavid du Colombier /*
197dd7cddfSDavid du Colombier  *	Machine description
207dd7cddfSDavid du Colombier  */
217dd7cddfSDavid du Colombier Machdata powermach =
227dd7cddfSDavid du Colombier {
237dd7cddfSDavid du Colombier 	{0x02, 0x8f, 0xff, 0xff},		/* break point */	/* BUG */
247dd7cddfSDavid du Colombier 	4,			/* break point size */
257dd7cddfSDavid du Colombier 
267dd7cddfSDavid du Colombier 	beswab,			/* short to local byte order */
277dd7cddfSDavid du Colombier 	beswal,			/* long to local byte order */
287dd7cddfSDavid du Colombier 	beswav,			/* vlong to local byte order */
297dd7cddfSDavid du Colombier 	risctrace,		/* print C traceback */
307dd7cddfSDavid du Colombier 	riscframe,		/* frame finder */
317dd7cddfSDavid du Colombier 	powerexcep,		/* print exception */
327dd7cddfSDavid du Colombier 	0,			/* breakpoint fixup */
337dd7cddfSDavid du Colombier 	beieeesftos,		/* single precision float printer */
347dd7cddfSDavid du Colombier 	beieeedftos,		/* double precisioin float printer */
357dd7cddfSDavid du Colombier 	powerfoll,		/* following addresses */
367dd7cddfSDavid du Colombier 	powerinst,		/* print instruction */
377dd7cddfSDavid du Colombier 	powerdas,		/* dissembler */
387dd7cddfSDavid du Colombier 	powerinstlen,		/* instruction size */
397dd7cddfSDavid du Colombier };
407dd7cddfSDavid du Colombier 
417dd7cddfSDavid du Colombier static char *excname[] =
427dd7cddfSDavid du Colombier {
437dd7cddfSDavid du Colombier 	"reserved 0",
447dd7cddfSDavid du Colombier 	"system reset",
457dd7cddfSDavid du Colombier 	"machine check",
467dd7cddfSDavid du Colombier 	"data access",
477dd7cddfSDavid du Colombier 	"instruction access",
487dd7cddfSDavid du Colombier 	"external interrupt",
497dd7cddfSDavid du Colombier 	"alignment",
507dd7cddfSDavid du Colombier 	"program exception",
517dd7cddfSDavid du Colombier 	"floating-point unavailable",
527dd7cddfSDavid du Colombier 	"decrementer",
537dd7cddfSDavid du Colombier 	"i/o controller interface error",
547dd7cddfSDavid du Colombier 	"reserved B",
557dd7cddfSDavid du Colombier 	"system call",
567dd7cddfSDavid du Colombier 	"trace trap",
577dd7cddfSDavid du Colombier 	"floating point assist",
587dd7cddfSDavid du Colombier 	"reserved",
597dd7cddfSDavid du Colombier 	"ITLB miss",
607dd7cddfSDavid du Colombier 	"DTLB load miss",
617dd7cddfSDavid du Colombier 	"DTLB store miss",
627dd7cddfSDavid du Colombier 	"instruction address breakpoint"
637dd7cddfSDavid du Colombier 	"SMI interrupt"
647dd7cddfSDavid du Colombier 	"reserved 15",
657dd7cddfSDavid du Colombier 	"reserved 16",
667dd7cddfSDavid du Colombier 	"reserved 17",
677dd7cddfSDavid du Colombier 	"reserved 18",
687dd7cddfSDavid du Colombier 	"reserved 19",
697dd7cddfSDavid du Colombier 	"reserved 1A",
707dd7cddfSDavid du Colombier 	/* the following are made up on a program exception */
717dd7cddfSDavid du Colombier 	"floating point exception",		/* FPEXC */
727dd7cddfSDavid du Colombier 	"illegal instruction",
737dd7cddfSDavid du Colombier 	"privileged instruction",
747dd7cddfSDavid du Colombier 	"trap",
757dd7cddfSDavid du Colombier 	"illegal operation",
767dd7cddfSDavid du Colombier };
777dd7cddfSDavid du Colombier 
787dd7cddfSDavid du Colombier static char*
powerexcep(Map * map,Rgetter rget)797dd7cddfSDavid du Colombier powerexcep(Map *map, Rgetter rget)
807dd7cddfSDavid du Colombier {
817dd7cddfSDavid du Colombier 	long c;
827dd7cddfSDavid du Colombier 	static char buf[32];
837dd7cddfSDavid du Colombier 
847dd7cddfSDavid du Colombier 	c = (*rget)(map, "CAUSE") >> 8;
857dd7cddfSDavid du Colombier 	if(c < nelem(excname))
867dd7cddfSDavid du Colombier 		return excname[c];
877dd7cddfSDavid du Colombier 	sprint(buf, "unknown trap #%lx", c);
887dd7cddfSDavid du Colombier 	return buf;
897dd7cddfSDavid du Colombier }
907dd7cddfSDavid du Colombier 
917dd7cddfSDavid du Colombier /*
927dd7cddfSDavid du Colombier  * disassemble PowerPC opcodes
937dd7cddfSDavid du Colombier  */
947dd7cddfSDavid du Colombier 
957dd7cddfSDavid du Colombier #define	REGSP	1	/* should come from q.out.h, but there's a clash */
967dd7cddfSDavid du Colombier #define	REGSB	2
977dd7cddfSDavid du Colombier 
987dd7cddfSDavid du Colombier static	char FRAMENAME[] = ".frame";
997dd7cddfSDavid du Colombier 
1007dd7cddfSDavid du Colombier static Map *mymap;
1017dd7cddfSDavid du Colombier 
1027dd7cddfSDavid du Colombier /*
1037dd7cddfSDavid du Colombier  * ibm conventions for these: bit 0 is top bit
1047dd7cddfSDavid du Colombier  *	from table 10-1
1057dd7cddfSDavid du Colombier  */
1067dd7cddfSDavid du Colombier typedef struct {
1077dd7cddfSDavid du Colombier 	uchar	aa;		/* bit 30 */
1087dd7cddfSDavid du Colombier 	uchar	crba;		/* bits 11-15 */
1097dd7cddfSDavid du Colombier 	uchar	crbb;		/* bits 16-20 */
1107dd7cddfSDavid du Colombier 	long	bd;		/* bits 16-29 */
1117dd7cddfSDavid du Colombier 	uchar	crfd;		/* bits 6-8 */
1127dd7cddfSDavid du Colombier 	uchar	crfs;		/* bits 11-13 */
1137dd7cddfSDavid du Colombier 	uchar	bi;		/* bits 11-15 */
1147dd7cddfSDavid du Colombier 	uchar	bo;		/* bits 6-10 */
1157dd7cddfSDavid du Colombier 	uchar	crbd;		/* bits 6-10 */
1167dd7cddfSDavid du Colombier 	union {
1177dd7cddfSDavid du Colombier 		short	d;	/* bits 16-31 */
1187dd7cddfSDavid du Colombier 		short	simm;
1197dd7cddfSDavid du Colombier 		ushort	uimm;
1207dd7cddfSDavid du Colombier 	};
1217dd7cddfSDavid du Colombier 	uchar	fm;		/* bits 7-14 */
1227dd7cddfSDavid du Colombier 	uchar	fra;		/* bits 11-15 */
1237dd7cddfSDavid du Colombier 	uchar	frb;		/* bits 16-20 */
1247dd7cddfSDavid du Colombier 	uchar	frc;		/* bits 21-25 */
1257dd7cddfSDavid du Colombier 	uchar	frs;		/* bits 6-10 */
1267dd7cddfSDavid du Colombier 	uchar	frd;		/* bits 6-10 */
1277dd7cddfSDavid du Colombier 	uchar	crm;		/* bits 12-19 */
1287dd7cddfSDavid du Colombier 	long	li;		/* bits 6-29 || b'00' */
1297dd7cddfSDavid du Colombier 	uchar	lk;		/* bit 31 */
1307dd7cddfSDavid du Colombier 	uchar	mb;		/* bits 21-25 */
1317dd7cddfSDavid du Colombier 	uchar	me;		/* bits 26-30 */
13247ad9175SDavid du Colombier 	uchar	xmbe;		/* bits 26,21-25: mb[5] || mb[0:4], also xme */
13347ad9175SDavid du Colombier 	uchar	xsh;		/* bits 30,16-20: sh[5] || sh[0:4] */
1347dd7cddfSDavid du Colombier 	uchar	nb;		/* bits 16-20 */
1357dd7cddfSDavid du Colombier 	uchar	op;		/* bits 0-5 */
1367dd7cddfSDavid du Colombier 	uchar	oe;		/* bit 21 */
1377dd7cddfSDavid du Colombier 	uchar	ra;		/* bits 11-15 */
1387dd7cddfSDavid du Colombier 	uchar	rb;		/* bits 16-20 */
1397dd7cddfSDavid du Colombier 	uchar	rc;		/* bit 31 */
1407dd7cddfSDavid du Colombier 	union {
1417dd7cddfSDavid du Colombier 		uchar	rs;	/* bits 6-10 */
1427dd7cddfSDavid du Colombier 		uchar	rd;
1437dd7cddfSDavid du Colombier 	};
1447dd7cddfSDavid du Colombier 	uchar	sh;		/* bits 16-20 */
1457dd7cddfSDavid du Colombier 	ushort	spr;		/* bits 11-20 */
1467dd7cddfSDavid du Colombier 	uchar	to;		/* bits 6-10 */
1477dd7cddfSDavid du Colombier 	uchar	imm;		/* bits 16-19 */
1487dd7cddfSDavid du Colombier 	ushort	xo;		/* bits 21-30, 22-30, 26-30, or 30 (beware) */
14947ad9175SDavid du Colombier 	uvlong	imm64;
1507dd7cddfSDavid du Colombier 	long w0;
1517dd7cddfSDavid du Colombier 	long w1;
1524de34a7eSDavid du Colombier 	uvlong	addr;		/* pc of instruction */
1537dd7cddfSDavid du Colombier 	short	target;
15447ad9175SDavid du Colombier 	short	m64;		/* 64-bit mode */
1557dd7cddfSDavid du Colombier 	char	*curr;		/* current fill level in output buffer */
1567dd7cddfSDavid du Colombier 	char	*end;		/* end of buffer */
1577dd7cddfSDavid du Colombier 	int 	size;		/* number of longs in instr */
1587dd7cddfSDavid du Colombier 	char	*err;		/* errmsg */
1597dd7cddfSDavid du Colombier } Instr;
1607dd7cddfSDavid du Colombier 
1617dd7cddfSDavid du Colombier #define	IBF(v,a,b) (((ulong)(v)>>(32-(b)-1)) & ~(~0L<<(((b)-(a)+1))))
1627dd7cddfSDavid du Colombier #define	IB(v,b) IBF((v),(b),(b))
1637dd7cddfSDavid du Colombier 
1641bd28109SDavid du Colombier #pragma	varargck	argpos	bprint		2
1651bd28109SDavid du Colombier 
1667dd7cddfSDavid du Colombier static void
bprint(Instr * i,char * fmt,...)1677dd7cddfSDavid du Colombier bprint(Instr *i, char *fmt, ...)
1687dd7cddfSDavid du Colombier {
1697dd7cddfSDavid du Colombier 	va_list arg;
1707dd7cddfSDavid du Colombier 
1717dd7cddfSDavid du Colombier 	va_start(arg, fmt);
1729a747e4fSDavid du Colombier 	i->curr = vseprint(i->curr, i->end, fmt, arg);
1737dd7cddfSDavid du Colombier 	va_end(arg);
1747dd7cddfSDavid du Colombier }
1757dd7cddfSDavid du Colombier 
1767dd7cddfSDavid du Colombier static int
decode(uvlong pc,Instr * i)1774de34a7eSDavid du Colombier decode(uvlong pc, Instr *i)
1787dd7cddfSDavid du Colombier {
1794de34a7eSDavid du Colombier 	ulong w;
1807dd7cddfSDavid du Colombier 
1817dd7cddfSDavid du Colombier 	if (get4(mymap, pc, &w) < 0) {
1827dd7cddfSDavid du Colombier 		werrstr("can't read instruction: %r");
1837dd7cddfSDavid du Colombier 		return -1;
1847dd7cddfSDavid du Colombier 	}
18547ad9175SDavid du Colombier 	i->m64 = asstype == APOWER64;
1867dd7cddfSDavid du Colombier 	i->aa = IB(w, 30);
1877dd7cddfSDavid du Colombier 	i->crba = IBF(w, 11, 15);
1887dd7cddfSDavid du Colombier 	i->crbb = IBF(w, 16, 20);
1897dd7cddfSDavid du Colombier 	i->bd = IBF(w, 16, 29)<<2;
1907dd7cddfSDavid du Colombier 	if(i->bd & 0x8000)
1917dd7cddfSDavid du Colombier 		i->bd |= ~0L<<16;
1927dd7cddfSDavid du Colombier 	i->crfd = IBF(w, 6, 8);
1937dd7cddfSDavid du Colombier 	i->crfs = IBF(w, 11, 13);
1947dd7cddfSDavid du Colombier 	i->bi = IBF(w, 11, 15);
1957dd7cddfSDavid du Colombier 	i->bo = IBF(w, 6, 10);
1967dd7cddfSDavid du Colombier 	i->crbd = IBF(w, 6, 10);
1977dd7cddfSDavid du Colombier 	i->uimm = IBF(w, 16, 31);	/* also d, simm */
1987dd7cddfSDavid du Colombier 	i->fm = IBF(w, 7, 14);
1997dd7cddfSDavid du Colombier 	i->fra = IBF(w, 11, 15);
2007dd7cddfSDavid du Colombier 	i->frb = IBF(w, 16, 20);
2017dd7cddfSDavid du Colombier 	i->frc = IBF(w, 21, 25);
2027dd7cddfSDavid du Colombier 	i->frs = IBF(w, 6, 10);
2037dd7cddfSDavid du Colombier 	i->frd = IBF(w, 6, 10);
2047dd7cddfSDavid du Colombier 	i->crm = IBF(w, 12, 19);
2057dd7cddfSDavid du Colombier 	i->li = IBF(w, 6, 29)<<2;
2067dd7cddfSDavid du Colombier 	if(IB(w, 6))
2077dd7cddfSDavid du Colombier 		i->li |= ~0<<25;
2087dd7cddfSDavid du Colombier 	i->lk = IB(w, 31);
2097dd7cddfSDavid du Colombier 	i->mb = IBF(w, 21, 25);
2107dd7cddfSDavid du Colombier 	i->me = IBF(w, 26, 30);
21147ad9175SDavid du Colombier 	i->xmbe = (IB(w,26)<<5) | i->mb;
2127dd7cddfSDavid du Colombier 	i->nb = IBF(w, 16, 20);
2137dd7cddfSDavid du Colombier 	i->op = IBF(w, 0, 5);
2147dd7cddfSDavid du Colombier 	i->oe = IB(w, 21);
2157dd7cddfSDavid du Colombier 	i->ra = IBF(w, 11, 15);
2167dd7cddfSDavid du Colombier 	i->rb = IBF(w, 16, 20);
2177dd7cddfSDavid du Colombier 	i->rc = IB(w, 31);
2187dd7cddfSDavid du Colombier 	i->rs = IBF(w, 6, 10);	/* also rd */
2197dd7cddfSDavid du Colombier 	i->sh = IBF(w, 16, 20);
22047ad9175SDavid du Colombier 	i->xsh = (IB(w, 30)<<5) | i->sh;
2217dd7cddfSDavid du Colombier 	i->spr = IBF(w, 11, 20);
2227dd7cddfSDavid du Colombier 	i->to = IBF(w, 6, 10);
2237dd7cddfSDavid du Colombier 	i->imm = IBF(w, 16, 19);
2247dd7cddfSDavid du Colombier 	i->xo = IBF(w, 21, 30);		/* bits 21-30, 22-30, 26-30, or 30 (beware) */
22547ad9175SDavid du Colombier 	if(i->op == 58){	/* class of 64-bit loads */
22647ad9175SDavid du Colombier 		i->xo = i->simm & 3;
22747ad9175SDavid du Colombier 		i->simm &= ~3;
22847ad9175SDavid du Colombier 	}
22947ad9175SDavid du Colombier 	i->imm64 = i->simm;
2307dd7cddfSDavid du Colombier 	if(i->op == 15)
23147ad9175SDavid du Colombier 		i->imm64 <<= 16;
23247ad9175SDavid du Colombier 	else if(i->op == 25 || i->op == 27 || i->op == 29)
23347ad9175SDavid du Colombier 		i->imm64 = (uvlong)(i->uimm<<16);
2347dd7cddfSDavid du Colombier 	i->w0 = w;
2357dd7cddfSDavid du Colombier 	i->target = -1;
2367dd7cddfSDavid du Colombier 	i->addr = pc;
2377dd7cddfSDavid du Colombier 	i->size = 1;
2387dd7cddfSDavid du Colombier 	return 1;
2397dd7cddfSDavid du Colombier }
2407dd7cddfSDavid du Colombier 
2417dd7cddfSDavid du Colombier static int
mkinstr(uvlong pc,Instr * i)2424de34a7eSDavid du Colombier mkinstr(uvlong pc, Instr *i)
2437dd7cddfSDavid du Colombier {
2447dd7cddfSDavid du Colombier 	Instr x;
2457dd7cddfSDavid du Colombier 
2467dd7cddfSDavid du Colombier 	if(decode(pc, i) < 0)
2477dd7cddfSDavid du Colombier 		return -1;
2487dd7cddfSDavid du Colombier 	/*
2497dd7cddfSDavid du Colombier 	 * combine ADDIS/ORI (CAU/ORIL) into MOVW
25047ad9175SDavid du Colombier 	 * also ORIS/ORIL for unsigned in 64-bit mode
2517dd7cddfSDavid du Colombier 	 */
25247ad9175SDavid du Colombier 	if ((i->op == 15 || i->op == 25) && i->ra==0) {
2537dd7cddfSDavid du Colombier 		if(decode(pc+4, &x) < 0)
2547dd7cddfSDavid du Colombier 			return -1;
2557dd7cddfSDavid du Colombier 		if (x.op == 24 && x.rs == x.ra && x.ra == i->rd) {
25647ad9175SDavid du Colombier 			i->imm64 |= (x.imm64 & 0xFFFF);
25747ad9175SDavid du Colombier 			if(i->op != 15)
25847ad9175SDavid du Colombier 				i->imm64 &= 0xFFFFFFFFUL;
2597dd7cddfSDavid du Colombier 			i->w1 = x.w0;
2607dd7cddfSDavid du Colombier 			i->target = x.rd;
2617dd7cddfSDavid du Colombier 			i->size++;
2627dd7cddfSDavid du Colombier 			return 1;
2637dd7cddfSDavid du Colombier 		}
2647dd7cddfSDavid du Colombier 	}
2657dd7cddfSDavid du Colombier 	return 1;
2667dd7cddfSDavid du Colombier }
2677dd7cddfSDavid du Colombier 
2687dd7cddfSDavid du Colombier static int
plocal(Instr * i)2697dd7cddfSDavid du Colombier plocal(Instr *i)
2707dd7cddfSDavid du Colombier {
2711bd28109SDavid du Colombier 	long offset;
2727dd7cddfSDavid du Colombier 	Symbol s;
2737dd7cddfSDavid du Colombier 
2747dd7cddfSDavid du Colombier 	if (!findsym(i->addr, CTEXT, &s) || !findlocal(&s, FRAMENAME, &s))
2757dd7cddfSDavid du Colombier 		return -1;
27647ad9175SDavid du Colombier 	offset = s.value - i->imm64;
2777dd7cddfSDavid du Colombier 	if (offset > 0) {
2787dd7cddfSDavid du Colombier 		if(getauto(&s, offset, CAUTO, &s)) {
2791bd28109SDavid du Colombier 			bprint(i, "%s+%lld(SP)", s.name, s.value);
2807dd7cddfSDavid du Colombier 			return 1;
2817dd7cddfSDavid du Colombier 		}
2827dd7cddfSDavid du Colombier 	} else {
2837dd7cddfSDavid du Colombier 		if (getauto(&s, -offset-4, CPARAM, &s)) {
2841bd28109SDavid du Colombier 			bprint(i, "%s+%ld(FP)", s.name, -offset);
2857dd7cddfSDavid du Colombier 			return 1;
2867dd7cddfSDavid du Colombier 		}
2877dd7cddfSDavid du Colombier 	}
2887dd7cddfSDavid du Colombier 	return -1;
2897dd7cddfSDavid du Colombier }
2907dd7cddfSDavid du Colombier 
2917dd7cddfSDavid du Colombier static int
pglobal(Instr * i,uvlong off,int anyoff,char * reg)2924de34a7eSDavid du Colombier pglobal(Instr *i, uvlong off, int anyoff, char *reg)
2937dd7cddfSDavid du Colombier {
2947dd7cddfSDavid du Colombier 	Symbol s, s2;
2954de34a7eSDavid du Colombier 	uvlong off1;
2967dd7cddfSDavid du Colombier 
2977dd7cddfSDavid du Colombier 	if(findsym(off, CANY, &s) &&
298*6891d857SDavid du Colombier 	   off-s.value < 4096 &&
2997dd7cddfSDavid du Colombier 	   (s.class == CDATA || s.class == CTEXT)) {
3007dd7cddfSDavid du Colombier 		if(off==s.value && s.name[0]=='$'){
3017dd7cddfSDavid du Colombier 			off1 = 0;
3024de34a7eSDavid du Colombier 			geta(mymap, s.value, &off1);
3037dd7cddfSDavid du Colombier 			if(off1 && findsym(off1, CANY, &s2) && s2.value == off1){
3047dd7cddfSDavid du Colombier 				bprint(i, "$%s%s", s2.name, reg);
3057dd7cddfSDavid du Colombier 				return 1;
3067dd7cddfSDavid du Colombier 			}
3077dd7cddfSDavid du Colombier 		}
3087dd7cddfSDavid du Colombier 		bprint(i, "%s", s.name);
3097dd7cddfSDavid du Colombier 		if (s.value != off)
3101bd28109SDavid du Colombier 			bprint(i, "+%llux", off-s.value);
3117dd7cddfSDavid du Colombier 		bprint(i, reg);
3127dd7cddfSDavid du Colombier 		return 1;
3137dd7cddfSDavid du Colombier 	}
3147dd7cddfSDavid du Colombier 	if(!anyoff)
3157dd7cddfSDavid du Colombier 		return 0;
3161bd28109SDavid du Colombier 	bprint(i, "%llux%s", off, reg);
3177dd7cddfSDavid du Colombier 	return 1;
3187dd7cddfSDavid du Colombier }
3197dd7cddfSDavid du Colombier 
3207dd7cddfSDavid du Colombier static void
address(Instr * i)3217dd7cddfSDavid du Colombier address(Instr *i)
3227dd7cddfSDavid du Colombier {
3237dd7cddfSDavid du Colombier 	if (i->ra == REGSP && plocal(i) >= 0)
3247dd7cddfSDavid du Colombier 		return;
325*6891d857SDavid du Colombier 	if (i->ra == REGSB && mach->sb && pglobal(i, mach->sb+i->imm64, 0, "(SB)"))
3267dd7cddfSDavid du Colombier 		return;
3277dd7cddfSDavid du Colombier 	if(i->simm < 0)
3281bd28109SDavid du Colombier 		bprint(i, "-%x(R%d)", -i->simm, i->ra);
3297dd7cddfSDavid du Colombier 	else
33047ad9175SDavid du Colombier 		bprint(i, "%llux(R%d)", i->imm64, i->ra);
3317dd7cddfSDavid du Colombier }
3327dd7cddfSDavid du Colombier 
3337dd7cddfSDavid du Colombier static	char	*tcrbits[] = {"LT", "GT", "EQ", "VS"};
3347dd7cddfSDavid du Colombier static	char	*fcrbits[] = {"GE", "LE", "NE", "VC"};
3357dd7cddfSDavid du Colombier 
3367dd7cddfSDavid du Colombier typedef struct Opcode Opcode;
3377dd7cddfSDavid du Colombier 
3387dd7cddfSDavid du Colombier struct Opcode {
3397dd7cddfSDavid du Colombier 	uchar	op;
3407dd7cddfSDavid du Colombier 	ushort	xo;
3417dd7cddfSDavid du Colombier 	ushort	xomask;
3427dd7cddfSDavid du Colombier 	char	*mnemonic;
3437dd7cddfSDavid du Colombier 	void	(*f)(Opcode *, Instr *);
3447dd7cddfSDavid du Colombier 	char	*ken;
3457dd7cddfSDavid du Colombier 	int	flags;
3467dd7cddfSDavid du Colombier };
3477dd7cddfSDavid du Colombier 
3487dd7cddfSDavid du Colombier static void format(char *, Instr *, char *);
3497dd7cddfSDavid du Colombier 
3507dd7cddfSDavid du Colombier static void
branch(Opcode * o,Instr * i)3517dd7cddfSDavid du Colombier branch(Opcode *o, Instr *i)
3527dd7cddfSDavid du Colombier {
3537dd7cddfSDavid du Colombier 	char buf[8];
3547dd7cddfSDavid du Colombier 	int bo, bi;
3557dd7cddfSDavid du Colombier 
3567dd7cddfSDavid du Colombier 	bo = i->bo & ~1;	/* ignore prediction bit */
3577dd7cddfSDavid du Colombier 	if(bo==4 || bo==12 || bo==20) {	/* simple forms */
3587dd7cddfSDavid du Colombier 		if(bo != 20) {
3597dd7cddfSDavid du Colombier 			bi = i->bi&3;
3607dd7cddfSDavid du Colombier 			sprint(buf, "B%s%%L", bo==12? tcrbits[bi]: fcrbits[bi]);
361*6891d857SDavid du Colombier 			format(buf, i, nil);
3627dd7cddfSDavid du Colombier 			bprint(i, "\t");
3637dd7cddfSDavid du Colombier 			if(i->bi > 4)
3647dd7cddfSDavid du Colombier 				bprint(i, "CR(%d),", i->bi/4);
3657dd7cddfSDavid du Colombier 		} else
366*6891d857SDavid du Colombier 			format("BR%L\t", i, nil);
3677dd7cddfSDavid du Colombier 		if(i->op == 16)
3687dd7cddfSDavid du Colombier 			format(0, i, "%J");
3697dd7cddfSDavid du Colombier 		else if(i->op == 19 && i->xo == 528)
3707dd7cddfSDavid du Colombier 			format(0, i, "(CTR)");
3717dd7cddfSDavid du Colombier 		else if(i->op == 19 && i->xo == 16)
3727dd7cddfSDavid du Colombier 			format(0, i, "(LR)");
3737dd7cddfSDavid du Colombier 	} else
3747dd7cddfSDavid du Colombier 		format(o->mnemonic, i, o->ken);
3757dd7cddfSDavid du Colombier }
3767dd7cddfSDavid du Colombier 
3777dd7cddfSDavid du Colombier static void
addi(Opcode * o,Instr * i)3787dd7cddfSDavid du Colombier addi(Opcode *o, Instr *i)
3797dd7cddfSDavid du Colombier {
3807dd7cddfSDavid du Colombier 	if (i->op==14 && i->ra == 0)
3817dd7cddfSDavid du Colombier 		format("MOVW", i, "%i,R%d");
3827dd7cddfSDavid du Colombier 	else if (i->ra == REGSB) {
3837dd7cddfSDavid du Colombier 		bprint(i, "MOVW\t$");
3847dd7cddfSDavid du Colombier 		address(i);
3857dd7cddfSDavid du Colombier 		bprint(i, ",R%d", i->rd);
3867dd7cddfSDavid du Colombier 	} else if(i->op==14 && i->simm < 0) {
3877dd7cddfSDavid du Colombier 		bprint(i, "SUB\t$%d,R%d", -i->simm, i->ra);
3887dd7cddfSDavid du Colombier 		if(i->rd != i->ra)
3897dd7cddfSDavid du Colombier 			bprint(i, ",R%d", i->rd);
3907dd7cddfSDavid du Colombier 	} else if(i->ra == i->rd) {
3917dd7cddfSDavid du Colombier 		format(o->mnemonic, i, "%i");
3927dd7cddfSDavid du Colombier 		bprint(i, ",R%d", i->rd);
3937dd7cddfSDavid du Colombier 	} else
3947dd7cddfSDavid du Colombier 		format(o->mnemonic, i, o->ken);
3957dd7cddfSDavid du Colombier }
3967dd7cddfSDavid du Colombier 
3977dd7cddfSDavid du Colombier static void
addis(Opcode * o,Instr * i)3987dd7cddfSDavid du Colombier addis(Opcode *o, Instr *i)
3997dd7cddfSDavid du Colombier {
4007dd7cddfSDavid du Colombier 	long v;
4017dd7cddfSDavid du Colombier 
40247ad9175SDavid du Colombier 	v = i->imm64;
4037dd7cddfSDavid du Colombier 	if (i->op==15 && i->ra == 0)
4047dd7cddfSDavid du Colombier 		bprint(i, "MOVW\t$%lux,R%d", v, i->rd);
4057dd7cddfSDavid du Colombier 	else if (i->op==15 && i->ra == REGSB) {
4067dd7cddfSDavid du Colombier 		bprint(i, "MOVW\t$");
4077dd7cddfSDavid du Colombier 		address(i);
4087dd7cddfSDavid du Colombier 		bprint(i, ",R%d", i->rd);
4097dd7cddfSDavid du Colombier 	} else if(i->op==15 && v < 0) {
4101bd28109SDavid du Colombier 		bprint(i, "SUB\t$%ld,R%d", -v, i->ra);
4117dd7cddfSDavid du Colombier 		if(i->rd != i->ra)
4127dd7cddfSDavid du Colombier 			bprint(i, ",R%d", i->rd);
4137dd7cddfSDavid du Colombier 	} else {
414*6891d857SDavid du Colombier 		format(o->mnemonic, i, nil);
4157dd7cddfSDavid du Colombier 		bprint(i, "\t$%ld,R%d", v, i->ra);
4167dd7cddfSDavid du Colombier 		if(i->rd != i->ra)
4177dd7cddfSDavid du Colombier 			bprint(i, ",R%d", i->rd);
4187dd7cddfSDavid du Colombier 	}
4197dd7cddfSDavid du Colombier }
4207dd7cddfSDavid du Colombier 
4217dd7cddfSDavid du Colombier static void
andi(Opcode * o,Instr * i)4227dd7cddfSDavid du Colombier andi(Opcode *o, Instr *i)
4237dd7cddfSDavid du Colombier {
4247dd7cddfSDavid du Colombier 	if (i->ra == i->rs)
4257dd7cddfSDavid du Colombier 		format(o->mnemonic, i, "%I,R%d");
4267dd7cddfSDavid du Colombier 	else
4277dd7cddfSDavid du Colombier 		format(o->mnemonic, i, o->ken);
4287dd7cddfSDavid du Colombier }
4297dd7cddfSDavid du Colombier 
4307dd7cddfSDavid du Colombier static void
gencc(Opcode * o,Instr * i)4317dd7cddfSDavid du Colombier gencc(Opcode *o, Instr *i)
4327dd7cddfSDavid du Colombier {
4337dd7cddfSDavid du Colombier 	format(o->mnemonic, i, o->ken);
4347dd7cddfSDavid du Colombier }
4357dd7cddfSDavid du Colombier 
4367dd7cddfSDavid du Colombier static void
gen(Opcode * o,Instr * i)4377dd7cddfSDavid du Colombier gen(Opcode *o, Instr *i)
4387dd7cddfSDavid du Colombier {
4397dd7cddfSDavid du Colombier 	format(o->mnemonic, i, o->ken);
4407dd7cddfSDavid du Colombier 	if (i->rc)
4417dd7cddfSDavid du Colombier 		bprint(i, " [illegal Rc]");
4427dd7cddfSDavid du Colombier }
4437dd7cddfSDavid du Colombier 
4447dd7cddfSDavid du Colombier static void
ldx(Opcode * o,Instr * i)4457dd7cddfSDavid du Colombier ldx(Opcode *o, Instr *i)
4467dd7cddfSDavid du Colombier {
4477dd7cddfSDavid du Colombier 	if(i->ra == 0)
4487dd7cddfSDavid du Colombier 		format(o->mnemonic, i, "(R%b),R%d");
4497dd7cddfSDavid du Colombier 	else
4507dd7cddfSDavid du Colombier 		format(o->mnemonic, i, "(R%b+R%a),R%d");
4517dd7cddfSDavid du Colombier 	if(i->rc)
4527dd7cddfSDavid du Colombier 		bprint(i, " [illegal Rc]");
4537dd7cddfSDavid du Colombier }
4547dd7cddfSDavid du Colombier 
4557dd7cddfSDavid du Colombier static void
stx(Opcode * o,Instr * i)4567dd7cddfSDavid du Colombier stx(Opcode *o, Instr *i)
4577dd7cddfSDavid du Colombier {
4587dd7cddfSDavid du Colombier 	if(i->ra == 0)
4597dd7cddfSDavid du Colombier 		format(o->mnemonic, i, "R%d,(R%b)");
4607dd7cddfSDavid du Colombier 	else
4617dd7cddfSDavid du Colombier 		format(o->mnemonic, i, "R%d,(R%b+R%a)");
4627dd7cddfSDavid du Colombier 	if(i->rc && i->xo != 150)
4637dd7cddfSDavid du Colombier 		bprint(i, " [illegal Rc]");
4647dd7cddfSDavid du Colombier }
4657dd7cddfSDavid du Colombier 
4667dd7cddfSDavid du Colombier static void
fldx(Opcode * o,Instr * i)4677dd7cddfSDavid du Colombier fldx(Opcode *o, Instr *i)
4687dd7cddfSDavid du Colombier {
4697dd7cddfSDavid du Colombier 	if(i->ra == 0)
4707dd7cddfSDavid du Colombier 		format(o->mnemonic, i, "(R%b),F%d");
4717dd7cddfSDavid du Colombier 	else
4727dd7cddfSDavid du Colombier 		format(o->mnemonic, i, "(R%b+R%a),F%d");
4737dd7cddfSDavid du Colombier 	if(i->rc)
4747dd7cddfSDavid du Colombier 		bprint(i, " [illegal Rc]");
4757dd7cddfSDavid du Colombier }
4767dd7cddfSDavid du Colombier 
4777dd7cddfSDavid du Colombier static void
fstx(Opcode * o,Instr * i)4787dd7cddfSDavid du Colombier fstx(Opcode *o, Instr *i)
4797dd7cddfSDavid du Colombier {
4807dd7cddfSDavid du Colombier 	if(i->ra == 0)
4817dd7cddfSDavid du Colombier 		format(o->mnemonic, i, "F%d,(R%b)");
4827dd7cddfSDavid du Colombier 	else
4837dd7cddfSDavid du Colombier 		format(o->mnemonic, i, "F%d,(R%b+R%a)");
4847dd7cddfSDavid du Colombier 	if(i->rc)
4857dd7cddfSDavid du Colombier 		bprint(i, " [illegal Rc]");
4867dd7cddfSDavid du Colombier }
4877dd7cddfSDavid du Colombier 
4887dd7cddfSDavid du Colombier static void
dcb(Opcode * o,Instr * i)4897dd7cddfSDavid du Colombier dcb(Opcode *o, Instr *i)
4907dd7cddfSDavid du Colombier {
4917dd7cddfSDavid du Colombier 	if(i->ra == 0)
4927dd7cddfSDavid du Colombier 		format(o->mnemonic, i, "(R%b)");
4937dd7cddfSDavid du Colombier 	else
4947dd7cddfSDavid du Colombier 		format(o->mnemonic, i, "(R%b+R%a)");
4957dd7cddfSDavid du Colombier 	if(i->rd)
4967dd7cddfSDavid du Colombier 		bprint(i, " [illegal Rd]");
4977dd7cddfSDavid du Colombier 	if(i->rc)
4987dd7cddfSDavid du Colombier 		bprint(i, " [illegal Rc]");
4997dd7cddfSDavid du Colombier }
5007dd7cddfSDavid du Colombier 
5017dd7cddfSDavid du Colombier static void
lw(Opcode * o,Instr * i,char r)5027dd7cddfSDavid du Colombier lw(Opcode *o, Instr *i, char r)
5037dd7cddfSDavid du Colombier {
504*6891d857SDavid du Colombier 	format(o->mnemonic, i, nil);
50547ad9175SDavid du Colombier 	bprint(i, "\t");
5067dd7cddfSDavid du Colombier 	address(i);
5077dd7cddfSDavid du Colombier 	bprint(i, ",%c%d", r, i->rd);
5087dd7cddfSDavid du Colombier }
5097dd7cddfSDavid du Colombier 
5107dd7cddfSDavid du Colombier static void
load(Opcode * o,Instr * i)5117dd7cddfSDavid du Colombier load(Opcode *o, Instr *i)
5127dd7cddfSDavid du Colombier {
5137dd7cddfSDavid du Colombier 	lw(o, i, 'R');
5147dd7cddfSDavid du Colombier }
5157dd7cddfSDavid du Colombier 
5167dd7cddfSDavid du Colombier static void
fload(Opcode * o,Instr * i)5177dd7cddfSDavid du Colombier fload(Opcode *o, Instr *i)
5187dd7cddfSDavid du Colombier {
5197dd7cddfSDavid du Colombier 	lw(o, i, 'F');
5207dd7cddfSDavid du Colombier }
5217dd7cddfSDavid du Colombier 
5227dd7cddfSDavid du Colombier static void
sw(Opcode * o,Instr * i,char r)5237dd7cddfSDavid du Colombier sw(Opcode *o, Instr *i, char r)
5247dd7cddfSDavid du Colombier {
5257dd7cddfSDavid du Colombier 	int offset;
5267dd7cddfSDavid du Colombier 	Symbol s;
5277dd7cddfSDavid du Colombier 
5287dd7cddfSDavid du Colombier 	if (i->rs == REGSP) {
5297dd7cddfSDavid du Colombier 		if (findsym(i->addr, CTEXT, &s) && findlocal(&s, FRAMENAME, &s)) {
53047ad9175SDavid du Colombier 			offset = s.value-i->imm64;
5317dd7cddfSDavid du Colombier 			if (offset > 0 && getauto(&s, offset, CAUTO, &s)) {
532*6891d857SDavid du Colombier 				format(o->mnemonic, i, nil);
533*6891d857SDavid du Colombier 				bprint(i, "\t%c%d,%s-%d(SP)", r, i->rd, s.name, offset);
5347dd7cddfSDavid du Colombier 				return;
5357dd7cddfSDavid du Colombier 			}
5367dd7cddfSDavid du Colombier 		}
5377dd7cddfSDavid du Colombier 	}
5387dd7cddfSDavid du Colombier 	if (i->rs == REGSB && mach->sb) {
539*6891d857SDavid du Colombier 		format(o->mnemonic, i, nil);
540*6891d857SDavid du Colombier 		bprint(i, "\t%c%d,", r, i->rd);
5417dd7cddfSDavid du Colombier 		address(i);
5427dd7cddfSDavid du Colombier 		return;
5437dd7cddfSDavid du Colombier 	}
5447dd7cddfSDavid du Colombier 	if (r == 'F')
545*6891d857SDavid du Colombier 		format(o->mnemonic, i, "F%d,%l");
5467dd7cddfSDavid du Colombier 	else
547*6891d857SDavid du Colombier 		format(o->mnemonic, i, o->ken);
5487dd7cddfSDavid du Colombier }
5497dd7cddfSDavid du Colombier 
5507dd7cddfSDavid du Colombier static void
store(Opcode * o,Instr * i)5517dd7cddfSDavid du Colombier store(Opcode *o, Instr *i)
5527dd7cddfSDavid du Colombier {
5537dd7cddfSDavid du Colombier 	sw(o, i, 'R');
5547dd7cddfSDavid du Colombier }
5557dd7cddfSDavid du Colombier 
5567dd7cddfSDavid du Colombier static void
fstore(Opcode * o,Instr * i)5577dd7cddfSDavid du Colombier fstore(Opcode *o, Instr *i)
5587dd7cddfSDavid du Colombier {
5597dd7cddfSDavid du Colombier 	sw(o, i, 'F');
5607dd7cddfSDavid du Colombier }
5617dd7cddfSDavid du Colombier 
5627dd7cddfSDavid du Colombier static void
shifti(Opcode * o,Instr * i)5637dd7cddfSDavid du Colombier shifti(Opcode *o, Instr *i)
5647dd7cddfSDavid du Colombier {
5657dd7cddfSDavid du Colombier 	if (i->ra == i->rs)
5667dd7cddfSDavid du Colombier 		format(o->mnemonic, i, "$%k,R%a");
5677dd7cddfSDavid du Colombier 	else
5687dd7cddfSDavid du Colombier 		format(o->mnemonic, i, o->ken);
5697dd7cddfSDavid du Colombier }
5707dd7cddfSDavid du Colombier 
5717dd7cddfSDavid du Colombier static void
shift(Opcode * o,Instr * i)5727dd7cddfSDavid du Colombier shift(Opcode *o, Instr *i)
5737dd7cddfSDavid du Colombier {
5747dd7cddfSDavid du Colombier 	if (i->ra == i->rs)
5757dd7cddfSDavid du Colombier 		format(o->mnemonic, i, "R%b,R%a");
5767dd7cddfSDavid du Colombier 	else
5777dd7cddfSDavid du Colombier 		format(o->mnemonic, i, o->ken);
5787dd7cddfSDavid du Colombier }
5797dd7cddfSDavid du Colombier 
5807dd7cddfSDavid du Colombier static void
add(Opcode * o,Instr * i)5817dd7cddfSDavid du Colombier add(Opcode *o, Instr *i)
5827dd7cddfSDavid du Colombier {
5837dd7cddfSDavid du Colombier 	if (i->rd == i->ra)
5847dd7cddfSDavid du Colombier 		format(o->mnemonic, i, "R%b,R%d");
5857dd7cddfSDavid du Colombier 	else if (i->rd == i->rb)
5867dd7cddfSDavid du Colombier 		format(o->mnemonic, i, "R%a,R%d");
5877dd7cddfSDavid du Colombier 	else
5887dd7cddfSDavid du Colombier 		format(o->mnemonic, i, o->ken);
5897dd7cddfSDavid du Colombier }
5907dd7cddfSDavid du Colombier 
5917dd7cddfSDavid du Colombier static void
sub(Opcode * o,Instr * i)5927dd7cddfSDavid du Colombier sub(Opcode *o, Instr *i)
5937dd7cddfSDavid du Colombier {
594*6891d857SDavid du Colombier 	format(o->mnemonic, i, nil);
5957dd7cddfSDavid du Colombier 	bprint(i, "\t");
5967dd7cddfSDavid du Colombier 	if(i->op == 31) {
5977dd7cddfSDavid du Colombier 		bprint(i, "\tR%d,R%d", i->ra, i->rb);	/* subtract Ra from Rb */
5987dd7cddfSDavid du Colombier 		if(i->rd != i->rb)
5997dd7cddfSDavid du Colombier 			bprint(i, ",R%d", i->rd);
6007dd7cddfSDavid du Colombier 	} else
6017dd7cddfSDavid du Colombier 		bprint(i, "\tR%d,$%d,R%d", i->ra, i->simm, i->rd);
6027dd7cddfSDavid du Colombier }
6037dd7cddfSDavid du Colombier 
6047dd7cddfSDavid du Colombier static void
qdiv(Opcode * o,Instr * i)605b0dcc5a8SDavid du Colombier qdiv(Opcode *o, Instr *i)
6067dd7cddfSDavid du Colombier {
607*6891d857SDavid du Colombier 	format(o->mnemonic, i, nil);
6087dd7cddfSDavid du Colombier 	if(i->op == 31)
6097dd7cddfSDavid du Colombier 		bprint(i, "\tR%d,R%d", i->rb, i->ra);
6107dd7cddfSDavid du Colombier 	else
6117dd7cddfSDavid du Colombier 		bprint(i, "\t$%d,R%d", i->simm, i->ra);
6127dd7cddfSDavid du Colombier 	if(i->ra != i->rd)
6137dd7cddfSDavid du Colombier 		bprint(i, ",R%d", i->rd);
6147dd7cddfSDavid du Colombier }
6157dd7cddfSDavid du Colombier 
6167dd7cddfSDavid du Colombier static void
and(Opcode * o,Instr * i)6177dd7cddfSDavid du Colombier and(Opcode *o, Instr *i)
6187dd7cddfSDavid du Colombier {
6197dd7cddfSDavid du Colombier 	if (i->op == 31) {
6207dd7cddfSDavid du Colombier 		/* Rb,Rs,Ra */
6217dd7cddfSDavid du Colombier 		if (i->ra == i->rs)
6227dd7cddfSDavid du Colombier 			format(o->mnemonic, i, "R%b,R%a");
6237dd7cddfSDavid du Colombier 		else if (i->ra == i->rb)
6247dd7cddfSDavid du Colombier 			format(o->mnemonic, i, "R%s,R%a");
6257dd7cddfSDavid du Colombier 		else
6267dd7cddfSDavid du Colombier 			format(o->mnemonic, i, o->ken);
6277dd7cddfSDavid du Colombier 	} else {
6287dd7cddfSDavid du Colombier 		/* imm,Rs,Ra */
6297dd7cddfSDavid du Colombier 		if (i->ra == i->rs)
6307dd7cddfSDavid du Colombier 			format(o->mnemonic, i, "%I,R%a");
6317dd7cddfSDavid du Colombier 		else
6327dd7cddfSDavid du Colombier 			format(o->mnemonic, i, o->ken);
6337dd7cddfSDavid du Colombier 	}
6347dd7cddfSDavid du Colombier }
6357dd7cddfSDavid du Colombier 
6367dd7cddfSDavid du Colombier static void
or(Opcode * o,Instr * i)6377dd7cddfSDavid du Colombier or(Opcode *o, Instr *i)
6387dd7cddfSDavid du Colombier {
6397dd7cddfSDavid du Colombier 	if (i->op == 31) {
6407dd7cddfSDavid du Colombier 		/* Rb,Rs,Ra */
6417dd7cddfSDavid du Colombier 		if (i->rs == 0 && i->ra == 0 && i->rb == 0)
642*6891d857SDavid du Colombier 			format("NOP", i, nil);
6437dd7cddfSDavid du Colombier 		else if (i->rs == i->rb)
6447dd7cddfSDavid du Colombier 			format("MOVW", i, "R%b,R%a");
6457dd7cddfSDavid du Colombier 		else
6467dd7cddfSDavid du Colombier 			and(o, i);
6477dd7cddfSDavid du Colombier 	} else
6487dd7cddfSDavid du Colombier 		and(o, i);
6497dd7cddfSDavid du Colombier }
6507dd7cddfSDavid du Colombier 
6517dd7cddfSDavid du Colombier static void
shifted(Opcode * o,Instr * i)6527dd7cddfSDavid du Colombier shifted(Opcode *o, Instr *i)
6537dd7cddfSDavid du Colombier {
654*6891d857SDavid du Colombier 	format(o->mnemonic, i, nil);
6557dd7cddfSDavid du Colombier 	bprint(i, "\t$%lux,", (ulong)i->uimm<<16);
6567dd7cddfSDavid du Colombier 	if (i->rs == i->ra)
6577dd7cddfSDavid du Colombier 		bprint(i, "R%d", i->ra);
6587dd7cddfSDavid du Colombier 	else
6597dd7cddfSDavid du Colombier 		bprint(i, "R%d,R%d", i->rs, i->ra);
6607dd7cddfSDavid du Colombier }
6617dd7cddfSDavid du Colombier 
6627dd7cddfSDavid du Colombier static void
neg(Opcode * o,Instr * i)6637dd7cddfSDavid du Colombier neg(Opcode *o, Instr *i)
6647dd7cddfSDavid du Colombier {
6657dd7cddfSDavid du Colombier 	if (i->rd == i->ra)
6667dd7cddfSDavid du Colombier 		format(o->mnemonic, i, "R%d");
6677dd7cddfSDavid du Colombier 	else
6687dd7cddfSDavid du Colombier 		format(o->mnemonic, i, o->ken);
6697dd7cddfSDavid du Colombier }
6707dd7cddfSDavid du Colombier 
6717dd7cddfSDavid du Colombier static	char	ir2[] = "R%a,R%d";		/* reverse of IBM order */
6727dd7cddfSDavid du Colombier static	char	ir3[] = "R%b,R%a,R%d";
6737dd7cddfSDavid du Colombier static	char	ir3r[] = "R%a,R%b,R%d";
6747dd7cddfSDavid du Colombier static	char	il3[] = "R%b,R%s,R%a";
675*6891d857SDavid du Colombier static	char	il2u[] = "%I,R%d,R%a";
6767dd7cddfSDavid du Colombier static	char	il3s[] = "$%k,R%s,R%a";
6777dd7cddfSDavid du Colombier static	char	il2[] = "R%s,R%a";
6787dd7cddfSDavid du Colombier static	char	icmp3[] = "R%a,R%b,%D";
6797dd7cddfSDavid du Colombier static	char	cr3op[] = "%b,%a,%d";
6807dd7cddfSDavid du Colombier static	char	ir2i[] = "%i,R%a,R%d";
6817dd7cddfSDavid du Colombier static	char	fp2[] = "F%b,F%d";
6827dd7cddfSDavid du Colombier static	char	fp3[] = "F%b,F%a,F%d";
6837dd7cddfSDavid du Colombier static	char	fp3c[] = "F%c,F%a,F%d";
6847dd7cddfSDavid du Colombier static	char	fp4[] = "F%a,F%c,F%b,F%d";
6857dd7cddfSDavid du Colombier static	char	fpcmp[] = "F%a,F%b,%D";
6867dd7cddfSDavid du Colombier static	char	ldop[] = "%l,R%d";
6877dd7cddfSDavid du Colombier static	char	stop[] = "R%d,%l";
6887dd7cddfSDavid du Colombier static	char	fldop[] = "%l,F%d";
6897dd7cddfSDavid du Colombier static	char	fstop[] = "F%d,%l";
69047ad9175SDavid du Colombier static	char	rldc[] = "R%b,R%s,$%E,R%a";
6917dd7cddfSDavid du Colombier static	char	rlim[] = "R%b,R%s,$%z,R%a";
6927dd7cddfSDavid du Colombier static	char	rlimi[] = "$%k,R%s,$%z,R%a";
69347ad9175SDavid du Colombier static	char	rldi[] = "$%e,R%s,$%E,R%a";
6947dd7cddfSDavid du Colombier 
6957dd7cddfSDavid du Colombier #define	OEM	IBF(~0,22,30)
6967dd7cddfSDavid du Colombier #define	FP4	IBF(~0,26,30)
6977dd7cddfSDavid du Colombier #define	ALL	(~0)
69847ad9175SDavid du Colombier #define	RLDC	0xF
69947ad9175SDavid du Colombier #define	RLDI	0xE
7007dd7cddfSDavid du Colombier /*
7017dd7cddfSDavid du Colombier notes:
7027dd7cddfSDavid du Colombier 	10-26: crfD = rD>>2; rD&3 mbz
7037dd7cddfSDavid du Colombier 		also, L bit (bit 10) mbz or selects 64-bit operands
7047dd7cddfSDavid du Colombier */
7057dd7cddfSDavid du Colombier 
7067dd7cddfSDavid du Colombier static Opcode opcodes[] = {
7077dd7cddfSDavid du Colombier 	{31,	266,	OEM,	"ADD%V%C",	add,	ir3},
7087dd7cddfSDavid du Colombier 	{31,	 10,	OEM,	"ADDC%V%C",	add,	ir3},
7097dd7cddfSDavid du Colombier 	{31,	138,	OEM,	"ADDE%V%C",	add,	ir3},
7107dd7cddfSDavid du Colombier 	{14,	0,	0,	"ADD",		addi,	ir2i},
7117dd7cddfSDavid du Colombier 	{12,	0,	0,	"ADDC",		addi,	ir2i},
7127dd7cddfSDavid du Colombier 	{13,	0,	0,	"ADDCCC",	addi,	ir2i},
7137dd7cddfSDavid du Colombier 	{15,	0,	0,	"ADD",		addis,	0},
7147dd7cddfSDavid du Colombier 	{31,	234,	OEM,	"ADDME%V%C",	gencc,	ir2},
7157dd7cddfSDavid du Colombier 	{31,	202,	OEM,	"ADDZE%V%C",	gencc,	ir2},
7167dd7cddfSDavid du Colombier 
7177dd7cddfSDavid du Colombier 	{31,	28,	ALL,	"AND%C",	and,	il3},
7187dd7cddfSDavid du Colombier 	{31,	60,	ALL,	"ANDN%C",	and,	il3},
7197dd7cddfSDavid du Colombier 	{28,	0,	0,	"ANDCC",	andi,	il2u},
7207dd7cddfSDavid du Colombier 	{29,	0,	0,	"ANDCC",	shifted, 0},
7217dd7cddfSDavid du Colombier 
7227dd7cddfSDavid du Colombier 	{18,	0,	0,	"B%L",		gencc,	"%j"},
7237dd7cddfSDavid du Colombier 	{16,	0,	0,	"BC%L",		branch,	"%d,%a,%J"},
7247dd7cddfSDavid du Colombier 	{19,	528,	ALL,	"BC%L",		branch,	"%d,%a,(CTR)"},
7257dd7cddfSDavid du Colombier 	{19,	16,	ALL,	"BC%L",		branch,	"%d,%a,(LR)"},
7267dd7cddfSDavid du Colombier 
7277dd7cddfSDavid du Colombier 	{31,	0,	ALL,	"CMP",		0,	icmp3},
7287dd7cddfSDavid du Colombier 	{11,	0,	0,	"CMP",		0,	"R%a,%i,%D"},
7297dd7cddfSDavid du Colombier 	{31,	32,	ALL,	"CMPU",		0,	icmp3},
7307dd7cddfSDavid du Colombier 	{10,	0,	0,	"CMPU",		0,	"R%a,%I,%D"},
7317dd7cddfSDavid du Colombier 
73247ad9175SDavid du Colombier 	{31,	58,	ALL,	"CNTLZD%C",	gencc,	ir2},	/* 64 */
73347ad9175SDavid du Colombier 	{31,	26,	ALL,	"CNTLZ%W%C",	gencc,	ir2},
7347dd7cddfSDavid du Colombier 
7357dd7cddfSDavid du Colombier 	{19,	257,	ALL,	"CRAND",	gen,	cr3op},
7367dd7cddfSDavid du Colombier 	{19,	129,	ALL,	"CRANDN",	gen,	cr3op},
7377dd7cddfSDavid du Colombier 	{19,	289,	ALL,	"CREQV",	gen,	cr3op},
7387dd7cddfSDavid du Colombier 	{19,	225,	ALL,	"CRNAND",	gen,	cr3op},
7397dd7cddfSDavid du Colombier 	{19,	33,	ALL,	"CRNOR",	gen,	cr3op},
7407dd7cddfSDavid du Colombier 	{19,	449,	ALL,	"CROR",		gen,	cr3op},
7417dd7cddfSDavid du Colombier 	{19,	417,	ALL,	"CRORN",	gen,	cr3op},
7427dd7cddfSDavid du Colombier 	{19,	193,	ALL,	"CRXOR",	gen,	cr3op},
7437dd7cddfSDavid du Colombier 
7447dd7cddfSDavid du Colombier 	{31,	86,	ALL,	"DCBF",		dcb,	0},
7457dd7cddfSDavid du Colombier 	{31,	470,	ALL,	"DCBI",		dcb,	0},
7467dd7cddfSDavid du Colombier 	{31,	54,	ALL,	"DCBST",	dcb,	0},
7477dd7cddfSDavid du Colombier 	{31,	278,	ALL,	"DCBT",		dcb,	0},
7487dd7cddfSDavid du Colombier 	{31,	246,	ALL,	"DCBTST",	dcb,	0},
7497dd7cddfSDavid du Colombier 	{31,	1014,	ALL,	"DCBZ",		dcb,	0},
750b0dcc5a8SDavid du Colombier 	{31,	454,	ALL,	"DCCCI",	dcb,	0},
751b0dcc5a8SDavid du Colombier 	{31,	966,	ALL,	"ICCCI",	dcb,	0},
7527dd7cddfSDavid du Colombier 
75347ad9175SDavid du Colombier 	{31,	489,	OEM,	"DIVD%V%C",	qdiv,	ir3},	/* 64 */
75447ad9175SDavid du Colombier 	{31,	457,	OEM,	"DIVDU%V%C",	qdiv,	ir3},	/* 64 */
755b0dcc5a8SDavid du Colombier 	{31,	491,	OEM,	"DIVW%V%C",	qdiv,	ir3},
756b0dcc5a8SDavid du Colombier 	{31,	459,	OEM,	"DIVWU%V%C",	qdiv,	ir3},
7577dd7cddfSDavid du Colombier 
7587dd7cddfSDavid du Colombier 	{31,	310,	ALL,	"ECIWX",	ldx,	0},
7597dd7cddfSDavid du Colombier 	{31,	438,	ALL,	"ECOWX",	stx,	0},
7607dd7cddfSDavid du Colombier 	{31,	854,	ALL,	"EIEIO",	gen,	0},
7617dd7cddfSDavid du Colombier 
7627dd7cddfSDavid du Colombier 	{31,	284,	ALL,	"EQV%C",	gencc,	il3},
7637dd7cddfSDavid du Colombier 
7647dd7cddfSDavid du Colombier 	{31,	954,	ALL,	"EXTSB%C",	gencc,	il2},
7657dd7cddfSDavid du Colombier 	{31,	922,	ALL,	"EXTSH%C",	gencc,	il2},
76647ad9175SDavid du Colombier 	{31,	986,	ALL,	"EXTSW%C",	gencc,	il2},	/* 64 */
7677dd7cddfSDavid du Colombier 
7687dd7cddfSDavid du Colombier 	{63,	264,	ALL,	"FABS%C",	gencc,	fp2},
7697dd7cddfSDavid du Colombier 	{63,	21,	ALL,	"FADD%C",	gencc,	fp3},
7707dd7cddfSDavid du Colombier 	{59,	21,	ALL,	"FADDS%C",	gencc,	fp3},
7717dd7cddfSDavid du Colombier 	{63,	32,	ALL,	"FCMPO",	gen,	fpcmp},
7727dd7cddfSDavid du Colombier 	{63,	0,	ALL,	"FCMPU",	gen,	fpcmp},
77347ad9175SDavid du Colombier 	{63,	846,	ALL,	"FCFID%C",	gencc,	fp2},	/* 64 */
77447ad9175SDavid du Colombier 	{63,	814,	ALL,	"FCTID%C",	gencc,	fp2},	/* 64 */
77547ad9175SDavid du Colombier 	{63,	815,	ALL,	"FCTIDZ%C",	gencc,	fp2},	/* 64 */
7767dd7cddfSDavid du Colombier 	{63,	14,	ALL,	"FCTIW%C",	gencc,	fp2},
7777dd7cddfSDavid du Colombier 	{63,	15,	ALL,	"FCTIWZ%C",	gencc,	fp2},
7787dd7cddfSDavid du Colombier 	{63,	18,	ALL,	"FDIV%C",	gencc,	fp3},
7797dd7cddfSDavid du Colombier 	{59,	18,	ALL,	"FDIVS%C",	gencc,	fp3},
7807dd7cddfSDavid du Colombier 	{63,	29,	FP4,	"FMADD%C",	gencc,	fp4},
7817dd7cddfSDavid du Colombier 	{59,	29,	FP4,	"FMADDS%C",	gencc,	fp4},
7827dd7cddfSDavid du Colombier 	{63,	72,	ALL,	"FMOVD%C",	gencc,	fp2},
7837dd7cddfSDavid du Colombier 	{63,	28,	FP4,	"FMSUB%C",	gencc,	fp4},
7847dd7cddfSDavid du Colombier 	{59,	28,	FP4,	"FMSUBS%C",	gencc,	fp4},
7857dd7cddfSDavid du Colombier 	{63,	25,	FP4,	"FMUL%C",	gencc,	fp3c},
7867dd7cddfSDavid du Colombier 	{59,	25,	FP4,	"FMULS%C",	gencc,	fp3c},
7877dd7cddfSDavid du Colombier 	{63,	136,	ALL,	"FNABS%C",	gencc,	fp2},
7887dd7cddfSDavid du Colombier 	{63,	40,	ALL,	"FNEG%C",	gencc,	fp2},
7897dd7cddfSDavid du Colombier 	{63,	31,	FP4,	"FNMADD%C",	gencc,	fp4},
7907dd7cddfSDavid du Colombier 	{59,	31,	FP4,	"FNMADDS%C",	gencc,	fp4},
7917dd7cddfSDavid du Colombier 	{63,	30,	FP4,	"FNMSUB%C",	gencc,	fp4},
7927dd7cddfSDavid du Colombier 	{59,	30,	FP4,	"FNMSUBS%C",	gencc,	fp4},
79347ad9175SDavid du Colombier 	{59,	24,	ALL,	"FRES%C",	gencc,	fp2},	/* optional */
7947dd7cddfSDavid du Colombier 	{63,	12,	ALL,	"FRSP%C",	gencc,	fp2},
79547ad9175SDavid du Colombier 	{63,	26,	ALL,	"FRSQRTE%C",	gencc,	fp2},	/* optional */
79647ad9175SDavid du Colombier 	{63,	23,	FP4,	"FSEL%CC",	gencc,	fp4},	/* optional */
79747ad9175SDavid du Colombier 	{63,	22,	ALL,	"FSQRT%C",	gencc,	fp2},	/* optional */
79847ad9175SDavid du Colombier 	{59,	22,	ALL,	"FSQRTS%C",	gencc,	fp2},	/* optional */
7997dd7cddfSDavid du Colombier 	{63,	20,	FP4,	"FSUB%C",	gencc,	fp3},
8007dd7cddfSDavid du Colombier 	{59,	20,	FP4,	"FSUBS%C",	gencc,	fp3},
8017dd7cddfSDavid du Colombier 
80247ad9175SDavid du Colombier 	{31,	982,	ALL,	"ICBI",		dcb,	0},	/* optional */
8037dd7cddfSDavid du Colombier 	{19,	150,	ALL,	"ISYNC",	gen,	0},
8047dd7cddfSDavid du Colombier 
8057dd7cddfSDavid du Colombier 	{34,	0,	0,	"MOVBZ",	load,	ldop},
8067dd7cddfSDavid du Colombier 	{35,	0,	0,	"MOVBZU",	load,	ldop},
8077dd7cddfSDavid du Colombier 	{31,	119,	ALL,	"MOVBZU",	ldx,	0},
8087dd7cddfSDavid du Colombier 	{31,	87,	ALL,	"MOVBZ",	ldx,	0},
8097dd7cddfSDavid du Colombier 	{50,	0,	0,	"FMOVD",	fload,	fldop},
8107dd7cddfSDavid du Colombier 	{51,	0,	0,	"FMOVDU",	fload,	fldop},
8117dd7cddfSDavid du Colombier 	{31,	631,	ALL,	"FMOVDU",	fldx,	0},
8127dd7cddfSDavid du Colombier 	{31,	599,	ALL,	"FMOVD",	fldx,	0},
8137dd7cddfSDavid du Colombier 	{48,	0,	0,	"FMOVS",	load,	fldop},
8147dd7cddfSDavid du Colombier 	{49,	0,	0,	"FMOVSU",	load,	fldop},
8157dd7cddfSDavid du Colombier 	{31,	567,	ALL,	"FMOVSU",	fldx,	0},
8167dd7cddfSDavid du Colombier 	{31,	535,	ALL,	"FMOVS",	fldx,	0},
8177dd7cddfSDavid du Colombier 	{42,	0,	0,	"MOVH",		load,	ldop},
8187dd7cddfSDavid du Colombier 	{43,	0,	0,	"MOVHU",	load,	ldop},
8197dd7cddfSDavid du Colombier 	{31,	375,	ALL,	"MOVHU",	ldx,	0},
8207dd7cddfSDavid du Colombier 	{31,	343,	ALL,	"MOVH",		ldx,	0},
8217dd7cddfSDavid du Colombier 	{31,	790,	ALL,	"MOVHBR",	ldx,	0},
8227dd7cddfSDavid du Colombier 	{40,	0,	0,	"MOVHZ",	load,	ldop},
8237dd7cddfSDavid du Colombier 	{41,	0,	0,	"MOVHZU",	load,	ldop},
8247dd7cddfSDavid du Colombier 	{31,	311,	ALL,	"MOVHZU",	ldx,	0},
8257dd7cddfSDavid du Colombier 	{31,	279,	ALL,	"MOVHZ",	ldx,	0},
8267dd7cddfSDavid du Colombier 	{46,	0,	0,	"MOVMW",	load,	ldop},
8277dd7cddfSDavid du Colombier 	{31,	597,	ALL,	"LSW",		gen,	"(R%a),$%n,R%d"},
8287dd7cddfSDavid du Colombier 	{31,	533,	ALL,	"LSW",		ldx,	0},
8297dd7cddfSDavid du Colombier 	{31,	20,	ALL,	"LWAR",		ldx,	0},
83047ad9175SDavid du Colombier 	{31,	84,	ALL,	"LWARD",	ldx,	0},	/* 64 */
8317dd7cddfSDavid du Colombier 
83247ad9175SDavid du Colombier 	{58,	0,	ALL,	"MOVD",		load,	ldop},	/* 64 */
83347ad9175SDavid du Colombier 	{58,	1,	ALL,	"MOVDU",	load,	ldop},	/* 64 */
83447ad9175SDavid du Colombier 	{31,	53,	ALL,	"MOVDU",	ldx,	0},	/* 64 */
83547ad9175SDavid du Colombier 	{31,	21,	ALL,	"MOVD",		ldx,	0},	/* 64 */
83647ad9175SDavid du Colombier 
83747ad9175SDavid du Colombier 	{31,	534,	ALL,	"MOVWBR",	ldx,	0},
83847ad9175SDavid du Colombier 
83947ad9175SDavid du Colombier 	{58,	2,	ALL,	"MOVW",		load,	ldop},	/* 64 (lwa) */
84047ad9175SDavid du Colombier 	{31,	373,	ALL,	"MOVWU",	ldx,	0},	/* 64 */
84147ad9175SDavid du Colombier 	{31,	341,	ALL,	"MOVW",		ldx,	0},	/* 64 */
84247ad9175SDavid du Colombier 
84347ad9175SDavid du Colombier 	{32,	0,	0,	"MOVW%Z",	load,	ldop},
84447ad9175SDavid du Colombier 	{33,	0,	0,	"MOVW%ZU",	load,	ldop},
84547ad9175SDavid du Colombier 	{31,	55,	ALL,	"MOVW%ZU",	ldx,	0},
84647ad9175SDavid du Colombier 	{31,	23,	ALL,	"MOVW%Z",	ldx,	0},
8477dd7cddfSDavid du Colombier 
8487dd7cddfSDavid du Colombier 	{19,	0,	ALL,	"MOVFL",	gen,	"%S,%D"},
8497dd7cddfSDavid du Colombier 	{63,	64,	ALL,	"MOVCRFS",	gen,	"%S,%D"},
8507dd7cddfSDavid du Colombier 	{31,	512,	ALL,	"MOVW",		gen,	"XER,%D"},
8517dd7cddfSDavid du Colombier 	{31,	19,	ALL,	"MOVW",		gen,	"CR,R%d"},
8527dd7cddfSDavid du Colombier 
8537dd7cddfSDavid du Colombier 	{63,	583,	ALL,	"MOVW%C",	gen,	"FPSCR, F%d"},	/* mffs */
8547dd7cddfSDavid du Colombier 	{31,	83,	ALL,	"MOVW",		gen,	"MSR,R%d"},
8557dd7cddfSDavid du Colombier 	{31,	339,	ALL,	"MOVW",		gen,	"%P,R%d"},
8567dd7cddfSDavid du Colombier 	{31,	595,	ALL,	"MOVW",		gen,	"SEG(%a),R%d"},
8577dd7cddfSDavid du Colombier 	{31,	659,	ALL,	"MOVW",		gen,	"SEG(R%b),R%d"},
858b0dcc5a8SDavid du Colombier 	{31,	323,	ALL,	"MOVW",		gen,	"DCR(%Q),R%d"},
859b0dcc5a8SDavid du Colombier 	{31,	451,	ALL,	"MOVW",		gen,	"R%s,DCR(%Q)"},
860*6891d857SDavid du Colombier 	{31,	259,	ALL,	"MOVW",		gen,	"DCR(R%a),R%d"},
861*6891d857SDavid du Colombier 	{31,	387,	ALL,	"MOVW",		gen,	"R%s,DCR(R%a)"},
8627dd7cddfSDavid du Colombier 	{31,	144,	ALL,	"MOVFL",	gen,	"R%s,%m,CR"},
8637dd7cddfSDavid du Colombier 	{63,	70,	ALL,	"MTFSB0%C",	gencc,	"%D"},
8647dd7cddfSDavid du Colombier 	{63,	38,	ALL,	"MTFSB1%C",	gencc,	"%D"},
8657dd7cddfSDavid du Colombier 	{63,	711,	ALL,	"MOVFL%C",	gencc,	"F%b,%M,FPSCR"},	/* mtfsf */
8667dd7cddfSDavid du Colombier 	{63,	134,	ALL,	"MOVFL%C",	gencc,	"%K,%D"},
8677dd7cddfSDavid du Colombier 	{31,	146,	ALL,	"MOVW",		gen,	"R%s,MSR"},
86847ad9175SDavid du Colombier 	{31,	178,	ALL,	"MOVD",		gen,	"R%s,MSR"},
8697dd7cddfSDavid du Colombier 	{31,	467,	ALL,	"MOVW",		gen,	"R%s,%P"},
8707dd7cddfSDavid du Colombier 	{31,	210,	ALL,	"MOVW",		gen,	"R%s,SEG(%a)"},
8717dd7cddfSDavid du Colombier 	{31,	242,	ALL,	"MOVW",		gen,	"R%s,SEG(R%b)"},
8727dd7cddfSDavid du Colombier 
87347ad9175SDavid du Colombier 	{31,	73,	ALL,	"MULHD%C",	gencc,	ir3},
87447ad9175SDavid du Colombier 	{31,	9,	ALL,	"MULHDU%C",	gencc,	ir3},
87547ad9175SDavid du Colombier 	{31,	233,	OEM,	"MULLD%V%C",	gencc,	ir3},
8767dd7cddfSDavid du Colombier 
87747ad9175SDavid du Colombier 	{31,	75,	ALL,	"MULHW%C",	gencc,	ir3},
87847ad9175SDavid du Colombier 	{31,	11,	ALL,	"MULHWU%C",	gencc,	ir3},
8797dd7cddfSDavid du Colombier 	{31,	235,	OEM,	"MULLW%V%C",	gencc,	ir3},
8807dd7cddfSDavid du Colombier 
88147ad9175SDavid du Colombier 	{7,	0,	0,	"MULLW",	qdiv,	"%i,R%a,R%d"},
8827dd7cddfSDavid du Colombier 
8837dd7cddfSDavid du Colombier 	{31,	476,	ALL,	"NAND%C",	gencc,	il3},
8847dd7cddfSDavid du Colombier 	{31,	104,	OEM,	"NEG%V%C",	neg,	ir2},
8857dd7cddfSDavid du Colombier 	{31,	124,	ALL,	"NOR%C",	gencc,	il3},
8867dd7cddfSDavid du Colombier 	{31,	444,	ALL,	"OR%C",		or,	il3},
8877dd7cddfSDavid du Colombier 	{31,	412,	ALL,	"ORN%C",	or,	il3},
8887dd7cddfSDavid du Colombier 	{24,	0,	0,	"OR",		and,	"%I,R%d,R%a"},
8897dd7cddfSDavid du Colombier 	{25,	0,	0,	"OR",		shifted, 0},
8907dd7cddfSDavid du Colombier 
8917dd7cddfSDavid du Colombier 	{19,	50,	ALL,	"RFI",		gen,	0},
892b0dcc5a8SDavid du Colombier 	{19,	51,	ALL,	"RFCI",		gen,	0},
8937dd7cddfSDavid du Colombier 
89447ad9175SDavid du Colombier 	{30,	8,	RLDC,	"RLDCL%C",	gencc,	rldc},	/* 64 */
89547ad9175SDavid du Colombier 	{30,	9,	RLDC,	"RLDCR%C",	gencc,	rldc},	/* 64 */
89647ad9175SDavid du Colombier 	{30,	0,	RLDI,	"RLDCL%C",	gencc,	rldi},	/* 64 */
89747ad9175SDavid du Colombier 	{30,	1<<1, RLDI,	"RLDCR%C",	gencc,	rldi},	/* 64 */
89847ad9175SDavid du Colombier 	{30,	2<<1, RLDI,	"RLDC%C",	gencc,	rldi},	/* 64 */
89947ad9175SDavid du Colombier 	{30,	3<<1, RLDI,	"RLDMI%C",	gencc,	rldi},	/* 64 */
90047ad9175SDavid du Colombier 
9017dd7cddfSDavid du Colombier 	{20,	0,	0,	"RLWMI%C",	gencc,	rlimi},
9027dd7cddfSDavid du Colombier 	{21,	0,	0,	"RLWNM%C",	gencc,	rlimi},
9037dd7cddfSDavid du Colombier 	{23,	0,	0,	"RLWNM%C",	gencc,	rlim},
9047dd7cddfSDavid du Colombier 
9057dd7cddfSDavid du Colombier 	{17,	1,	ALL,	"SYSCALL",	gen,	0},
9067dd7cddfSDavid du Colombier 
90747ad9175SDavid du Colombier 	{31,	27,	ALL,	"SLD%C",	shift,	il3},	/* 64 */
9087dd7cddfSDavid du Colombier 	{31,	24,	ALL,	"SLW%C",	shift,	il3},
9097dd7cddfSDavid du Colombier 
91047ad9175SDavid du Colombier 	{31,	794,	ALL,	"SRAD%C",	shift,	il3},	/* 64 */
911*6891d857SDavid du Colombier 	{31,	(413<<1)|0,	ALL,	"SRAD%C",	shifti,	il3s},	/* 64 */
912*6891d857SDavid du Colombier 	{31,	(413<<1)|1,	ALL,	"SRAD%C",	shifti,	il3s},	/* 64 */
9137dd7cddfSDavid du Colombier 	{31,	792,	ALL,	"SRAW%C",	shift,	il3},
9147dd7cddfSDavid du Colombier 	{31,	824,	ALL,	"SRAW%C",	shifti,	il3s},
9157dd7cddfSDavid du Colombier 
91647ad9175SDavid du Colombier 	{31,	539,	ALL,	"SRD%C",	shift,	il3},	/* 64 */
9177dd7cddfSDavid du Colombier 	{31,	536,	ALL,	"SRW%C",	shift,	il3},
9187dd7cddfSDavid du Colombier 
9197dd7cddfSDavid du Colombier 	{38,	0,	0,	"MOVB",		store,	stop},
9207dd7cddfSDavid du Colombier 	{39,	0,	0,	"MOVBU",	store,	stop},
9217dd7cddfSDavid du Colombier 	{31,	247,	ALL,	"MOVBU",	stx,	0},
9227dd7cddfSDavid du Colombier 	{31,	215,	ALL,	"MOVB",		stx,	0},
9237dd7cddfSDavid du Colombier 	{54,	0,	0,	"FMOVD",	fstore,	fstop},
9247dd7cddfSDavid du Colombier 	{55,	0,	0,	"FMOVDU",	fstore,	fstop},
9257dd7cddfSDavid du Colombier 	{31,	759,	ALL,	"FMOVDU",	fstx,	0},
9267dd7cddfSDavid du Colombier 	{31,	727,	ALL,	"FMOVD",	fstx,	0},
9277dd7cddfSDavid du Colombier 	{52,	0,	0,	"FMOVS",	fstore,	fstop},
9287dd7cddfSDavid du Colombier 	{53,	0,	0,	"FMOVSU",	fstore,	fstop},
9297dd7cddfSDavid du Colombier 	{31,	695,	ALL,	"FMOVSU",	fstx,	0},
9307dd7cddfSDavid du Colombier 	{31,	663,	ALL,	"FMOVS",	fstx,	0},
9317dd7cddfSDavid du Colombier 	{44,	0,	0,	"MOVH",		store,	stop},
9327dd7cddfSDavid du Colombier 	{31,	918,	ALL,	"MOVHBR",	stx,	0},
9337dd7cddfSDavid du Colombier 	{45,	0,	0,	"MOVHU",	store,	stop},
9347dd7cddfSDavid du Colombier 	{31,	439,	ALL,	"MOVHU",	stx,	0},
9357dd7cddfSDavid du Colombier 	{31,	407,	ALL,	"MOVH",		stx,	0},
9367dd7cddfSDavid du Colombier 	{47,	0,	0,	"MOVMW",	store,	stop},
9377dd7cddfSDavid du Colombier 	{31,	725,	ALL,	"STSW",		gen,	"R%d,$%n,(R%a)"},
9387dd7cddfSDavid du Colombier 	{31,	661,	ALL,	"STSW",		stx,	0},
9397dd7cddfSDavid du Colombier 	{36,	0,	0,	"MOVW",		store,	stop},
9407dd7cddfSDavid du Colombier 	{31,	662,	ALL,	"MOVWBR",	stx,	0},
9417dd7cddfSDavid du Colombier 	{31,	150,	ALL,	"STWCCC",	stx,	0},
94247ad9175SDavid du Colombier 	{31,	214,	ALL,	"STDCCC",	stx,	0},	/* 64 */
9437dd7cddfSDavid du Colombier 	{37,	0,	0,	"MOVWU",	store,	stop},
9447dd7cddfSDavid du Colombier 	{31,	183,	ALL,	"MOVWU",	stx,	0},
9457dd7cddfSDavid du Colombier 	{31,	151,	ALL,	"MOVW",		stx,	0},
9467dd7cddfSDavid du Colombier 
94747ad9175SDavid du Colombier 	{62,	0,	0,	"MOVD%U",	store,	stop},	/* 64 */
94847ad9175SDavid du Colombier 	{31,	149,	ALL,	"MOVD",		stx,	0,},	/* 64 */
94947ad9175SDavid du Colombier 	{31,	181,	ALL,	"MOVDU",	stx,	0},	/* 64 */
95047ad9175SDavid du Colombier 
95147ad9175SDavid du Colombier 	{31,	498,	ALL,	"SLBIA",	gen,	0},	/* 64 */
95247ad9175SDavid du Colombier 	{31,	434,	ALL,	"SLBIE",	gen,	"R%b"},	/* 64 */
95347ad9175SDavid du Colombier 	{31,	466,	ALL,	"SLBIEX",	gen,	"R%b"},	/* 64 */
95447ad9175SDavid du Colombier 	{31,	915,	ALL,	"SLBMFEE",	gen,	"R%b,R%d"},	/* 64 */
95547ad9175SDavid du Colombier 	{31,	851,	ALL,	"SLBMFEV",	gen,	"R%b,R%d"},	/* 64 */
95647ad9175SDavid du Colombier 	{31,	402,	ALL,	"SLBMTE",	gen,	"R%s,R%b"},	/* 64 */
95747ad9175SDavid du Colombier 
9587dd7cddfSDavid du Colombier 	{31,	40,	OEM,	"SUB%V%C",	sub,	ir3},
9597dd7cddfSDavid du Colombier 	{31,	8,	OEM,	"SUBC%V%C",	sub,	ir3},
9607dd7cddfSDavid du Colombier 	{31,	136,	OEM,	"SUBE%V%C",	sub,	ir3},
9617dd7cddfSDavid du Colombier 	{8,	0,	0,	"SUBC",		gen,	"R%a,%i,R%d"},
9627dd7cddfSDavid du Colombier 	{31,	232,	OEM,	"SUBME%V%C",	sub,	ir2},
9637dd7cddfSDavid du Colombier 	{31,	200,	OEM,	"SUBZE%V%C",	sub,	ir2},
9647dd7cddfSDavid du Colombier 
96547ad9175SDavid du Colombier 	{31,	598,	ALL,	"SYNC",		gen,	0},	/* TO DO: there's a parameter buried in there */
96647ad9175SDavid du Colombier 	{2,	0,	0,	"TD",		gen,	"%d,R%a,%i"},	/* 64 */
96747ad9175SDavid du Colombier 	{31,	370,	ALL,	"TLBIA",	gen,	0},	/* optional */
96847ad9175SDavid du Colombier 	{31,	306,	ALL,	"TLBIE",	gen,	"R%b"},	/* optional */
96947ad9175SDavid du Colombier 	{31,	274,	ALL,	"TLBIEL",	gen,	"R%b"},	/* optional */
97047ad9175SDavid du Colombier 	{31,	1010,	ALL,	"TLBLI",	gen,	"R%b"},	/* optional */
97147ad9175SDavid du Colombier 	{31,	978,	ALL,	"TLBLD",	gen,	"R%b"},	/* optional */
97247ad9175SDavid du Colombier 	{31,	566,	ALL,	"TLBSYNC",	gen,	0},	/* optional */
97347ad9175SDavid du Colombier 	{31,	68,	ALL,	"TD",		gen,	"%d,R%a,R%b"},	/* 64 */
9747dd7cddfSDavid du Colombier 	{31,	4,	ALL,	"TW",		gen,	"%d,R%a,R%b"},
9757dd7cddfSDavid du Colombier 	{3,	0,	0,	"TW",		gen,	"%d,R%a,%i"},
9767dd7cddfSDavid du Colombier 
9777dd7cddfSDavid du Colombier 	{31,	316,	ALL,	"XOR",		and,	il3},
9787dd7cddfSDavid du Colombier 	{26,	0,	0,	"XOR",		and,	il2u},
9797dd7cddfSDavid du Colombier 	{27,	0,	0,	"XOR",		shifted, 0},
9807dd7cddfSDavid du Colombier 
9817dd7cddfSDavid du Colombier 	{0},
9827dd7cddfSDavid du Colombier };
9837dd7cddfSDavid du Colombier 
9847dd7cddfSDavid du Colombier typedef struct Spr Spr;
9857dd7cddfSDavid du Colombier struct Spr {
9867dd7cddfSDavid du Colombier 	int	n;
9877dd7cddfSDavid du Colombier 	char	*name;
9887dd7cddfSDavid du Colombier };
9897dd7cddfSDavid du Colombier 
9907dd7cddfSDavid du Colombier static	Spr	sprname[] = {
9917dd7cddfSDavid du Colombier 	{0, "MQ"},
9927dd7cddfSDavid du Colombier 	{1, "XER"},
9937dd7cddfSDavid du Colombier 	{268, "TBL"},
9947dd7cddfSDavid du Colombier 	{269, "TBU"},
9957dd7cddfSDavid du Colombier 	{8, "LR"},
9967dd7cddfSDavid du Colombier 	{9, "CTR"},
9977dd7cddfSDavid du Colombier 	{528, "IBAT0U"},
9987dd7cddfSDavid du Colombier 	{529, "IBAT0L"},
9997dd7cddfSDavid du Colombier 	{530, "IBAT1U"},
10007dd7cddfSDavid du Colombier 	{531, "IBAT1L"},
10017dd7cddfSDavid du Colombier 	{532, "IBAT2U"},
10027dd7cddfSDavid du Colombier 	{533, "IBAT2L"},
10037dd7cddfSDavid du Colombier 	{534, "IBAT3U"},
10047dd7cddfSDavid du Colombier 	{535, "IBAT3L"},
10057dd7cddfSDavid du Colombier 	{536, "DBAT0U"},
10067dd7cddfSDavid du Colombier 	{537, "DBAT0L"},
10077dd7cddfSDavid du Colombier 	{538, "DBAT1U"},
10087dd7cddfSDavid du Colombier 	{539, "DBAT1L"},
10097dd7cddfSDavid du Colombier 	{540, "DBAT2U"},
10107dd7cddfSDavid du Colombier 	{541, "DBAT2L"},
10117dd7cddfSDavid du Colombier 	{542, "DBAT3U"},
10127dd7cddfSDavid du Colombier 	{543, "DBAT3L"},
10137dd7cddfSDavid du Colombier 	{25, "SDR1"},
10147dd7cddfSDavid du Colombier 	{19, "DAR"},
10157dd7cddfSDavid du Colombier 	{272, "SPRG0"},
10167dd7cddfSDavid du Colombier 	{273, "SPRG1"},
10177dd7cddfSDavid du Colombier 	{274, "SPRG2"},
10187dd7cddfSDavid du Colombier 	{275, "SPRG3"},
10197dd7cddfSDavid du Colombier 	{18, "DSISR"},
10207dd7cddfSDavid du Colombier 	{26, "SRR0"},
10217dd7cddfSDavid du Colombier 	{27, "SRR1"},
10227dd7cddfSDavid du Colombier 	{284, "TBLW"},
10237dd7cddfSDavid du Colombier 	{285, "TBUW"},
10247dd7cddfSDavid du Colombier 	{22, "DEC"},
10257dd7cddfSDavid du Colombier 	{282, "EAR"},
10267dd7cddfSDavid du Colombier 	{1008, "HID0"},
10277dd7cddfSDavid du Colombier 	{1009, "HID1"},
10287dd7cddfSDavid du Colombier 	{976, "DMISS"},
10297dd7cddfSDavid du Colombier 	{977, "DCMP"},
10307dd7cddfSDavid du Colombier 	{978, "HASH1"},
10317dd7cddfSDavid du Colombier 	{979, "HASH2"},
10327dd7cddfSDavid du Colombier 	{980, "IMISS"},
10337dd7cddfSDavid du Colombier 	{981, "ICMP"},
10347dd7cddfSDavid du Colombier 	{982, "RPA"},
10357dd7cddfSDavid du Colombier 	{1010, "IABR"},
1036b0dcc5a8SDavid du Colombier 	{1013, "DABR"},
10377dd7cddfSDavid du Colombier 	{0,0},
10387dd7cddfSDavid du Colombier };
10397dd7cddfSDavid du Colombier 
104047ad9175SDavid du Colombier static int
shmask(uvlong * m)104147ad9175SDavid du Colombier shmask(uvlong *m)
104247ad9175SDavid du Colombier {
104347ad9175SDavid du Colombier 	int i;
104447ad9175SDavid du Colombier 
104547ad9175SDavid du Colombier 	for(i=0; i<63; i++)
104647ad9175SDavid du Colombier 		if(*m & ((uvlong)1<<i))
104747ad9175SDavid du Colombier 			break;
104847ad9175SDavid du Colombier 	if(i > 63)
104947ad9175SDavid du Colombier 		return 0;
105047ad9175SDavid du Colombier 	if(*m & ~((uvlong)1<<i)){	/* more than one bit: do multiples of bytes */
105147ad9175SDavid du Colombier 		i = (i/8)*8;
105247ad9175SDavid du Colombier 		if(i == 0)
105347ad9175SDavid du Colombier 			return 0;
105447ad9175SDavid du Colombier 	}
105547ad9175SDavid du Colombier 	*m >>= i;
105647ad9175SDavid du Colombier 	return i;
105747ad9175SDavid du Colombier }
105847ad9175SDavid du Colombier 
10597dd7cddfSDavid du Colombier static void
format(char * mnemonic,Instr * i,char * f)10607dd7cddfSDavid du Colombier format(char *mnemonic, Instr *i, char *f)
10617dd7cddfSDavid du Colombier {
10627dd7cddfSDavid du Colombier 	int n, s;
10637dd7cddfSDavid du Colombier 	ulong mask;
106447ad9175SDavid du Colombier 	uvlong vmask;
10657dd7cddfSDavid du Colombier 
10667dd7cddfSDavid du Colombier 	if (mnemonic)
10677dd7cddfSDavid du Colombier 		format(0, i, mnemonic);
10687dd7cddfSDavid du Colombier 	if (f == 0)
10697dd7cddfSDavid du Colombier 		return;
10707dd7cddfSDavid du Colombier 	if (mnemonic)
10717dd7cddfSDavid du Colombier 		bprint(i, "\t");
10727dd7cddfSDavid du Colombier 	for ( ; *f; f++) {
10737dd7cddfSDavid du Colombier 		if (*f != '%') {
10747dd7cddfSDavid du Colombier 			bprint(i, "%c", *f);
10757dd7cddfSDavid du Colombier 			continue;
10767dd7cddfSDavid du Colombier 		}
10777dd7cddfSDavid du Colombier 		switch (*++f) {
10787dd7cddfSDavid du Colombier 
10797dd7cddfSDavid du Colombier 		case 'a':
10807dd7cddfSDavid du Colombier 			bprint(i, "%d", i->ra);
10817dd7cddfSDavid du Colombier 			break;
10827dd7cddfSDavid du Colombier 
10837dd7cddfSDavid du Colombier 		case 'b':
10847dd7cddfSDavid du Colombier 			bprint(i, "%d", i->rb);
10857dd7cddfSDavid du Colombier 			break;
10867dd7cddfSDavid du Colombier 
10877dd7cddfSDavid du Colombier 		case 'c':
10887dd7cddfSDavid du Colombier 			bprint(i, "%d", i->frc);
10897dd7cddfSDavid du Colombier 			break;
10907dd7cddfSDavid du Colombier 
10917dd7cddfSDavid du Colombier 		case 'd':
10927dd7cddfSDavid du Colombier 		case 's':
10937dd7cddfSDavid du Colombier 			bprint(i, "%d", i->rd);
10947dd7cddfSDavid du Colombier 			break;
10957dd7cddfSDavid du Colombier 
109647ad9175SDavid du Colombier 		case 'C':
109747ad9175SDavid du Colombier 			if(i->rc)
109847ad9175SDavid du Colombier 				bprint(i, "CC");
10997dd7cddfSDavid du Colombier 			break;
11007dd7cddfSDavid du Colombier 
11017dd7cddfSDavid du Colombier 		case 'D':
11027dd7cddfSDavid du Colombier 			if(i->rd & 3)
11037dd7cddfSDavid du Colombier 				bprint(i, "CR(INVAL:%d)", i->rd);
11047dd7cddfSDavid du Colombier 			else if(i->op == 63)
11057dd7cddfSDavid du Colombier 				bprint(i, "FPSCR(%d)", i->crfd);
11067dd7cddfSDavid du Colombier 			else
11077dd7cddfSDavid du Colombier 				bprint(i, "CR(%d)", i->crfd);
11087dd7cddfSDavid du Colombier 			break;
11097dd7cddfSDavid du Colombier 
111047ad9175SDavid du Colombier 		case 'e':
111147ad9175SDavid du Colombier 			bprint(i, "%d", i->xsh);
111247ad9175SDavid du Colombier 			break;
111347ad9175SDavid du Colombier 
111447ad9175SDavid du Colombier 		case 'E':
111547ad9175SDavid du Colombier 			switch(IBF(i->w0,27,30)){	/* low bit is top bit of shift in rldiX cases */
111647ad9175SDavid du Colombier 			case 8:	i->mb = i->xmbe; i->me = 63; break;	/* rldcl */
111747ad9175SDavid du Colombier 			case 9:	i->mb = 0; i->me = i->xmbe; break;	/* rldcr */
111847ad9175SDavid du Colombier 			case 4: case 5:
111947ad9175SDavid du Colombier 					i->mb = i->xmbe; i->me = 63-i->xsh; break;	/* rldic */
112047ad9175SDavid du Colombier 			case 0: case 1:
112147ad9175SDavid du Colombier 					i->mb = i->xmbe; i->me = 63; break;	/* rldicl */
112247ad9175SDavid du Colombier 			case 2: case 3:
112347ad9175SDavid du Colombier 					i->mb = 0; i->me = i->xmbe; break;	/* rldicr */
112447ad9175SDavid du Colombier 			case 6: case 7:
112547ad9175SDavid du Colombier 					i->mb = i->xmbe; i->me = 63-i->xsh; break;	/* rldimi */
112647ad9175SDavid du Colombier 			}
112747ad9175SDavid du Colombier 			vmask = (~(uvlong)0>>i->mb) & (~(uvlong)0<<(63-i->me));
112847ad9175SDavid du Colombier 			s = shmask(&vmask);
112947ad9175SDavid du Colombier 			if(s)
113047ad9175SDavid du Colombier 				bprint(i, "(%llux<<%d)", vmask, s);
11317dd7cddfSDavid du Colombier 			else
113247ad9175SDavid du Colombier 				bprint(i, "%llux", vmask);
11337dd7cddfSDavid du Colombier 			break;
11347dd7cddfSDavid du Colombier 
11357dd7cddfSDavid du Colombier 		case 'i':
11361bd28109SDavid du Colombier 			bprint(i, "$%d", i->simm);
11377dd7cddfSDavid du Colombier 			break;
11387dd7cddfSDavid du Colombier 
11397dd7cddfSDavid du Colombier 		case 'I':
11401bd28109SDavid du Colombier 			bprint(i, "$%ux", i->uimm);
11417dd7cddfSDavid du Colombier 			break;
11427dd7cddfSDavid du Colombier 
114347ad9175SDavid du Colombier 		case 'j':
114447ad9175SDavid du Colombier 			if(i->aa)
114547ad9175SDavid du Colombier 				pglobal(i, i->li, 1, "(SB)");
114647ad9175SDavid du Colombier 			else
114747ad9175SDavid du Colombier 				pglobal(i, i->addr+i->li, 1, "");
114847ad9175SDavid du Colombier 			break;
114947ad9175SDavid du Colombier 
115047ad9175SDavid du Colombier 		case 'J':
115147ad9175SDavid du Colombier 			if(i->aa)
115247ad9175SDavid du Colombier 				pglobal(i, i->bd, 1, "(SB)");
115347ad9175SDavid du Colombier 			else
115447ad9175SDavid du Colombier 				pglobal(i, i->addr+i->bd, 1, "");
115547ad9175SDavid du Colombier 			break;
115647ad9175SDavid du Colombier 
115747ad9175SDavid du Colombier 		case 'k':
115847ad9175SDavid du Colombier 			bprint(i, "%d", i->sh);
115947ad9175SDavid du Colombier 			break;
116047ad9175SDavid du Colombier 
116147ad9175SDavid du Colombier 		case 'K':
116247ad9175SDavid du Colombier 			bprint(i, "$%x", i->imm);
116347ad9175SDavid du Colombier 			break;
116447ad9175SDavid du Colombier 
116547ad9175SDavid du Colombier 		case 'L':
116647ad9175SDavid du Colombier 			if(i->lk)
116747ad9175SDavid du Colombier 				bprint(i, "L");
116847ad9175SDavid du Colombier 			break;
116947ad9175SDavid du Colombier 
117047ad9175SDavid du Colombier 		case 'l':
117147ad9175SDavid du Colombier 			if(i->simm < 0)
117247ad9175SDavid du Colombier 				bprint(i, "-%x(R%d)", -i->simm, i->ra);
117347ad9175SDavid du Colombier 			else
117447ad9175SDavid du Colombier 				bprint(i, "%x(R%d)", i->simm, i->ra);
117547ad9175SDavid du Colombier 			break;
117647ad9175SDavid du Colombier 
117747ad9175SDavid du Colombier 		case 'm':
117847ad9175SDavid du Colombier 			bprint(i, "%ux", i->crm);
117947ad9175SDavid du Colombier 			break;
118047ad9175SDavid du Colombier 
118147ad9175SDavid du Colombier 		case 'M':
118247ad9175SDavid du Colombier 			bprint(i, "%ux", i->fm);
118347ad9175SDavid du Colombier 			break;
118447ad9175SDavid du Colombier 
118547ad9175SDavid du Colombier 		case 'n':
118647ad9175SDavid du Colombier 			bprint(i, "%d", i->nb==0? 32: i->nb);	/* eg, pg 10-103 */
11877dd7cddfSDavid du Colombier 			break;
11887dd7cddfSDavid du Colombier 
11897dd7cddfSDavid du Colombier 		case 'P':
11907dd7cddfSDavid du Colombier 			n = ((i->spr&0x1f)<<5)|((i->spr>>5)&0x1f);
11917dd7cddfSDavid du Colombier 			for(s=0; sprname[s].name; s++)
11927dd7cddfSDavid du Colombier 				if(sprname[s].n == n)
11937dd7cddfSDavid du Colombier 					break;
11947dd7cddfSDavid du Colombier 			if(sprname[s].name) {
11957dd7cddfSDavid du Colombier 				if(s < 10)
11967dd7cddfSDavid du Colombier 					bprint(i, sprname[s].name);
11977dd7cddfSDavid du Colombier 				else
11987dd7cddfSDavid du Colombier 					bprint(i, "SPR(%s)", sprname[s].name);
11997dd7cddfSDavid du Colombier 			} else
12007dd7cddfSDavid du Colombier 				bprint(i, "SPR(%d)", n);
12017dd7cddfSDavid du Colombier 			break;
12027dd7cddfSDavid du Colombier 
1203b0dcc5a8SDavid du Colombier 		case 'Q':
1204b0dcc5a8SDavid du Colombier 			n = ((i->spr&0x1f)<<5)|((i->spr>>5)&0x1f);
1205b0dcc5a8SDavid du Colombier 			bprint(i, "%d", n);
1206b0dcc5a8SDavid du Colombier 			break;
1207b0dcc5a8SDavid du Colombier 
120847ad9175SDavid du Colombier 		case 'S':
120947ad9175SDavid du Colombier 			if(i->ra & 3)
121047ad9175SDavid du Colombier 				bprint(i, "CR(INVAL:%d)", i->ra);
121147ad9175SDavid du Colombier 			else if(i->op == 63)
121247ad9175SDavid du Colombier 				bprint(i, "FPSCR(%d)", i->crfs);
121347ad9175SDavid du Colombier 			else
121447ad9175SDavid du Colombier 				bprint(i, "CR(%d)", i->crfs);
12157dd7cddfSDavid du Colombier 			break;
12167dd7cddfSDavid du Colombier 
121747ad9175SDavid du Colombier 		case 'U':
121847ad9175SDavid du Colombier 			if(i->rc)
121947ad9175SDavid du Colombier 				bprint(i, "U");
12207dd7cddfSDavid du Colombier 			break;
12217dd7cddfSDavid du Colombier 
122247ad9175SDavid du Colombier 		case 'V':
122347ad9175SDavid du Colombier 			if(i->oe)
122447ad9175SDavid du Colombier 				bprint(i, "V");
122547ad9175SDavid du Colombier 			break;
122647ad9175SDavid du Colombier 
122747ad9175SDavid du Colombier 		case 'w':
122847ad9175SDavid du Colombier 			bprint(i, "[%lux]", i->w0);
122947ad9175SDavid du Colombier 			break;
123047ad9175SDavid du Colombier 
123147ad9175SDavid du Colombier 		case 'W':
123247ad9175SDavid du Colombier 			if(i->m64)
123347ad9175SDavid du Colombier 				bprint(i, "W");
123447ad9175SDavid du Colombier 			break;
123547ad9175SDavid du Colombier 
123647ad9175SDavid du Colombier 		case 'Z':
123747ad9175SDavid du Colombier 			if(i->m64)
123847ad9175SDavid du Colombier 				bprint(i, "Z");
12397dd7cddfSDavid du Colombier 			break;
12407dd7cddfSDavid du Colombier 
12417dd7cddfSDavid du Colombier 		case 'z':
12427dd7cddfSDavid du Colombier 			if(i->mb <= i->me)
12437dd7cddfSDavid du Colombier 				mask = ((ulong)~0L>>i->mb) & (~0L<<(31-i->me));
12447dd7cddfSDavid du Colombier 			else
12457dd7cddfSDavid du Colombier 				mask = ~(((ulong)~0L>>(i->me+1)) & (~0L<<(31-(i->mb-1))));
12467dd7cddfSDavid du Colombier 			bprint(i, "%lux", mask);
12477dd7cddfSDavid du Colombier 			break;
12487dd7cddfSDavid du Colombier 
12497dd7cddfSDavid du Colombier 		case '\0':
12507dd7cddfSDavid du Colombier 			bprint(i, "%%");
12517dd7cddfSDavid du Colombier 			return;
12527dd7cddfSDavid du Colombier 
12537dd7cddfSDavid du Colombier 		default:
12547dd7cddfSDavid du Colombier 			bprint(i, "%%%c", *f);
12557dd7cddfSDavid du Colombier 			break;
12567dd7cddfSDavid du Colombier 		}
12577dd7cddfSDavid du Colombier 	}
12587dd7cddfSDavid du Colombier }
12597dd7cddfSDavid du Colombier 
12607dd7cddfSDavid du Colombier static int
printins(Map * map,uvlong pc,char * buf,int n)12614de34a7eSDavid du Colombier printins(Map *map, uvlong pc, char *buf, int n)
12627dd7cddfSDavid du Colombier {
12637dd7cddfSDavid du Colombier 	Instr i;
12647dd7cddfSDavid du Colombier 	Opcode *o;
12657dd7cddfSDavid du Colombier 
12667dd7cddfSDavid du Colombier 	mymap = map;
12677dd7cddfSDavid du Colombier 	memset(&i, 0, sizeof(i));
12687dd7cddfSDavid du Colombier 	i.curr = buf;
12697dd7cddfSDavid du Colombier 	i.end = buf+n-1;
12707dd7cddfSDavid du Colombier 	if(mkinstr(pc, &i) < 0)
12717dd7cddfSDavid du Colombier 		return -1;
12727dd7cddfSDavid du Colombier 	for(o = opcodes; o->mnemonic != 0; o++)
12737dd7cddfSDavid du Colombier 		if(i.op == o->op && (i.xo & o->xomask) == o->xo) {
12747dd7cddfSDavid du Colombier 			if (o->f)
12757dd7cddfSDavid du Colombier 				(*o->f)(o, &i);
12767dd7cddfSDavid du Colombier 			else
12777dd7cddfSDavid du Colombier 				format(o->mnemonic, &i, o->ken);
12787dd7cddfSDavid du Colombier 			return i.size*4;
12797dd7cddfSDavid du Colombier 		}
12807dd7cddfSDavid du Colombier 	bprint(&i, "unknown %lux", i.w0);
12817dd7cddfSDavid du Colombier 	return i.size*4;
12827dd7cddfSDavid du Colombier }
12837dd7cddfSDavid du Colombier 
12847dd7cddfSDavid du Colombier static int
powerinst(Map * map,uvlong pc,char modifier,char * buf,int n)12854de34a7eSDavid du Colombier powerinst(Map *map, uvlong pc, char modifier, char *buf, int n)
12867dd7cddfSDavid du Colombier {
12877dd7cddfSDavid du Colombier 	USED(modifier);
12887dd7cddfSDavid du Colombier 	return printins(map, pc, buf, n);
12897dd7cddfSDavid du Colombier }
12907dd7cddfSDavid du Colombier 
12917dd7cddfSDavid du Colombier static int
powerdas(Map * map,uvlong pc,char * buf,int n)12924de34a7eSDavid du Colombier powerdas(Map *map, uvlong pc, char *buf, int n)
12937dd7cddfSDavid du Colombier {
12947dd7cddfSDavid du Colombier 	Instr instr;
12957dd7cddfSDavid du Colombier 
12967dd7cddfSDavid du Colombier 	mymap = map;
12977dd7cddfSDavid du Colombier 	memset(&instr, 0, sizeof(instr));
12987dd7cddfSDavid du Colombier 	instr.curr = buf;
12997dd7cddfSDavid du Colombier 	instr.end = buf+n-1;
13007dd7cddfSDavid du Colombier 	if (mkinstr(pc, &instr) < 0)
13017dd7cddfSDavid du Colombier 		return -1;
13027dd7cddfSDavid du Colombier 	if (instr.end-instr.curr > 8)
13037dd7cddfSDavid du Colombier 		instr.curr = _hexify(instr.curr, instr.w0, 7);
13047dd7cddfSDavid du Colombier 	if (instr.end-instr.curr > 9 && instr.size == 2) {
13057dd7cddfSDavid du Colombier 		*instr.curr++ = ' ';
13067dd7cddfSDavid du Colombier 		instr.curr = _hexify(instr.curr, instr.w1, 7);
13077dd7cddfSDavid du Colombier 	}
13087dd7cddfSDavid du Colombier 	*instr.curr = 0;
13097dd7cddfSDavid du Colombier 	return instr.size*4;
13107dd7cddfSDavid du Colombier }
13117dd7cddfSDavid du Colombier 
13127dd7cddfSDavid du Colombier static int
powerinstlen(Map * map,uvlong pc)13134de34a7eSDavid du Colombier powerinstlen(Map *map, uvlong pc)
13147dd7cddfSDavid du Colombier {
13157dd7cddfSDavid du Colombier 	Instr i;
13167dd7cddfSDavid du Colombier 
13177dd7cddfSDavid du Colombier 	mymap = map;
13187dd7cddfSDavid du Colombier 	if (mkinstr(pc, &i) < 0)
13197dd7cddfSDavid du Colombier 		return -1;
13207dd7cddfSDavid du Colombier 	return i.size*4;
13217dd7cddfSDavid du Colombier }
13227dd7cddfSDavid du Colombier 
13237dd7cddfSDavid du Colombier static int
powerfoll(Map * map,uvlong pc,Rgetter rget,uvlong * foll)13244de34a7eSDavid du Colombier powerfoll(Map *map, uvlong pc, Rgetter rget, uvlong *foll)
13257dd7cddfSDavid du Colombier {
13267dd7cddfSDavid du Colombier 	char *reg;
13277dd7cddfSDavid du Colombier 	Instr i;
13287dd7cddfSDavid du Colombier 
13297dd7cddfSDavid du Colombier 	mymap = map;
13307dd7cddfSDavid du Colombier 	if (mkinstr(pc, &i) < 0)
13317dd7cddfSDavid du Colombier 		return -1;
13327dd7cddfSDavid du Colombier 	foll[0] = pc+4;
13337dd7cddfSDavid du Colombier 	foll[1] = pc+4;
13347dd7cddfSDavid du Colombier 	switch(i.op) {
13357dd7cddfSDavid du Colombier 	default:
13367dd7cddfSDavid du Colombier 		return 1;
13377dd7cddfSDavid du Colombier 
13387dd7cddfSDavid du Colombier 	case 18:	/* branch */
13397dd7cddfSDavid du Colombier 		foll[0] = i.li;
13407dd7cddfSDavid du Colombier 		if(!i.aa)
13417dd7cddfSDavid du Colombier 			foll[0] += pc;
13427dd7cddfSDavid du Colombier 		break;
13437dd7cddfSDavid du Colombier 
13447dd7cddfSDavid du Colombier 	case 16:	/* conditional branch */
13457dd7cddfSDavid du Colombier 		foll[0] = i.bd;
13467dd7cddfSDavid du Colombier 		if(!i.aa)
13477dd7cddfSDavid du Colombier 			foll[0] += pc;
13487dd7cddfSDavid du Colombier 		break;
13497dd7cddfSDavid du Colombier 
13507dd7cddfSDavid du Colombier 	case 19:	/* conditional branch to register */
13517dd7cddfSDavid du Colombier 		if(i.xo == 528)
13527dd7cddfSDavid du Colombier 			reg = "CTR";
13537dd7cddfSDavid du Colombier 		else if(i.xo == 16)
13547dd7cddfSDavid du Colombier 			reg = "LR";
13557dd7cddfSDavid du Colombier 		else
13567dd7cddfSDavid du Colombier 			return 1;	/* not a branch */
13577dd7cddfSDavid du Colombier 		foll[0] = (*rget)(map, reg);
13587dd7cddfSDavid du Colombier 		break;
13597dd7cddfSDavid du Colombier 	}
13607dd7cddfSDavid du Colombier 	if(i.lk)
13617dd7cddfSDavid du Colombier 		return 2;
13627dd7cddfSDavid du Colombier 	return 1;
13637dd7cddfSDavid du Colombier }
1364