xref: /inferno-os/utils/libmach/qdb.c (revision d3641b487cf5cdc46e9b537d30eb37736e5c7b1a)
1 #include <lib9.h>
2 #include <bio.h>
3 #include "mach.h"
4 
5 /*
6  * PowerPC-specific debugger interface,
7  * including 64-bit modes
8  *	forsyth@terzarima.net
9  */
10 
11 static	char	*powerexcep(Map*, Rgetter);
12 static	int	powerfoll(Map*, uvlong, Rgetter, uvlong*);
13 static	int	powerinst(Map*, uvlong, char, char*, int);
14 static	int	powerinstlen(Map*, uvlong);
15 static	int	powerdas(Map*, uvlong, char*, int);
16 
17 /*
18  *	Machine description
19  */
20 Machdata powermach =
21 {
22 	{0x07f, 0xe0, 0x00, 0x08},		/* breakpoint (tw 31,r0,r0) */
23 	4,			/* break point size */
24 
25 	beswab,			/* short to local byte order */
26 	beswal,			/* long to local byte order */
27 	beswav,			/* vlong to local byte order */
28 	risctrace,		/* print C traceback */
29 	riscframe,		/* frame finder */
30 	powerexcep,		/* print exception */
31 	0,			/* breakpoint fixup */
32 	beieeesftos,		/* single precision float printer */
33 	beieeedftos,		/* double precisioin float printer */
34 	powerfoll,		/* following addresses */
35 	powerinst,		/* print instruction */
36 	powerdas,		/* dissembler */
37 	powerinstlen,		/* instruction size */
38 };
39 
40 static char *excname[] =
41 {
42 	"reserved 0",
43 	"system reset",
44 	"machine check",
45 	"data access",
46 	"instruction access",
47 	"external interrupt",
48 	"alignment",
49 	"program exception",
50 	"floating-point unavailable",
51 	"decrementer",
52 	"i/o controller interface error",
53 	"reserved B",
54 	"system call",
55 	"trace trap",
56 	"floating point assist",
57 	"reserved",
58 	"ITLB miss",
59 	"DTLB load miss",
60 	"DTLB store miss",
61 	"instruction address breakpoint"
62 	"SMI interrupt"
63 	"reserved 15",
64 	"reserved 16",
65 	"reserved 17",
66 	"reserved 18",
67 	"reserved 19",
68 	"reserved 1A",
69 	/* the following are made up on a program exception */
70 	"floating point exception",		/* FPEXC */
71 	"illegal instruction",
72 	"privileged instruction",
73 	"trap",
74 	"illegal operation",
75 	"breakpoint",	/* 20 */
76 };
77 
78 static char*
79 powerexcep(Map *map, Rgetter rget)
80 {
81 	long c;
82 	static char buf[32];
83 
84 	c = (*rget)(map, "CAUSE") >> 8;
85 	if(c < nelem(excname))
86 		return excname[c];
87 	sprint(buf, "unknown trap #%lx", c);
88 	return buf;
89 }
90 
91 /*
92  * disassemble PowerPC opcodes
93  */
94 
95 #define	REGSP	1	/* should come from q.out.h, but there's a clash */
96 #define	REGSB	2
97 
98 static	char FRAMENAME[] = ".frame";
99 
100 static Map *mymap;
101 
102 /*
103  * ibm conventions for these: bit 0 is top bit
104  *	from table 10-1
105  */
106 typedef struct {
107 	uchar	aa;		/* bit 30 */
108 	uchar	crba;		/* bits 11-15 */
109 	uchar	crbb;		/* bits 16-20 */
110 	long	bd;		/* bits 16-29 */
111 	uchar	crfd;		/* bits 6-8 */
112 	uchar	crfs;		/* bits 11-13 */
113 	uchar	bi;		/* bits 11-15 */
114 	uchar	bo;		/* bits 6-10 */
115 	uchar	crbd;		/* bits 6-10 */
116 	/* union { */
117 		short	d;	/* bits 16-31 */
118 		short	simm;
119 		ushort	uimm;
120 	/*}; */
121 	uchar	fm;		/* bits 7-14 */
122 	uchar	fra;		/* bits 11-15 */
123 	uchar	frb;		/* bits 16-20 */
124 	uchar	frc;		/* bits 21-25 */
125 	uchar	frs;		/* bits 6-10 */
126 	uchar	frd;		/* bits 6-10 */
127 	uchar	crm;		/* bits 12-19 */
128 	long	li;		/* bits 6-29 || b'00' */
129 	uchar	lk;		/* bit 31 */
130 	uchar	mb;		/* bits 21-25 */
131 	uchar	me;		/* bits 26-30 */
132 	uchar	xmbe;		/* bits 26,21-25: mb[5] || mb[0:4], also xme */
133 	uchar	xsh;		/* bits 30,16-20: sh[5] || sh[0:4] */
134 	uchar	nb;		/* bits 16-20 */
135 	uchar	op;		/* bits 0-5 */
136 	uchar	oe;		/* bit 21 */
137 	uchar	ra;		/* bits 11-15 */
138 	uchar	rb;		/* bits 16-20 */
139 	uchar	rc;		/* bit 31 */
140 	/* union { */
141 		uchar	rs;	/* bits 6-10 */
142 		uchar	rd;
143 	/*};*/
144 	uchar	sh;		/* bits 16-20 */
145 	ushort	spr;		/* bits 11-20 */
146 	uchar	to;		/* bits 6-10 */
147 	uchar	imm;		/* bits 16-19 */
148 	ushort	xo;		/* bits 21-30, 22-30, 26-30, or 30 (beware) */
149 	uvlong	imm64;
150 	long w0;
151 	long w1;
152 	uvlong	addr;		/* pc of instruction */
153 	short	target;
154 	short	m64;		/* 64-bit mode */
155 	char	*curr;		/* current fill level in output buffer */
156 	char	*end;		/* end of buffer */
157 	int 	size;		/* number of longs in instr */
158 	char	*err;		/* errmsg */
159 } Instr;
160 
161 #define	IBF(v,a,b) (((ulong)(v)>>(32-(b)-1)) & ~(~0L<<(((b)-(a)+1))))
162 #define	IB(v,b) IBF((v),(b),(b))
163 
164 #pragma	varargck	argpos	bprint		2
165 
166 static void
167 bprint(Instr *i, char *fmt, ...)
168 {
169 	va_list arg;
170 
171 	va_start(arg, fmt);
172 	i->curr = vseprint(i->curr, i->end, fmt, arg);
173 	va_end(arg);
174 }
175 
176 static int
177 decode(uvlong pc, Instr *i)
178 {
179 	ulong w;
180 
181 	if (get4(mymap, pc, &w) < 0) {
182 		werrstr("can't read instruction: %r");
183 		return -1;
184 	}
185 	i->m64 = asstype == APOWER64;
186 	i->aa = IB(w, 30);
187 	i->crba = IBF(w, 11, 15);
188 	i->crbb = IBF(w, 16, 20);
189 	i->bd = IBF(w, 16, 29)<<2;
190 	if(i->bd & 0x8000)
191 		i->bd |= ~0L<<16;
192 	i->crfd = IBF(w, 6, 8);
193 	i->crfs = IBF(w, 11, 13);
194 	i->bi = IBF(w, 11, 15);
195 	i->bo = IBF(w, 6, 10);
196 	i->crbd = IBF(w, 6, 10);
197 	i->uimm = IBF(w, 16, 31);	/* also d, simm */
198 	i->fm = IBF(w, 7, 14);
199 	i->fra = IBF(w, 11, 15);
200 	i->frb = IBF(w, 16, 20);
201 	i->frc = IBF(w, 21, 25);
202 	i->frs = IBF(w, 6, 10);
203 	i->frd = IBF(w, 6, 10);
204 	i->crm = IBF(w, 12, 19);
205 	i->li = IBF(w, 6, 29)<<2;
206 	if(IB(w, 6))
207 		i->li |= ~0<<25;
208 	i->lk = IB(w, 31);
209 	i->mb = IBF(w, 21, 25);
210 	i->me = IBF(w, 26, 30);
211 	i->xmbe = (IB(w,26)<<5) | i->mb;
212 	i->nb = IBF(w, 16, 20);
213 	i->op = IBF(w, 0, 5);
214 	i->oe = IB(w, 21);
215 	i->ra = IBF(w, 11, 15);
216 	i->rb = IBF(w, 16, 20);
217 	i->rc = IB(w, 31);
218 	i->rs = IBF(w, 6, 10);	/* also rd */
219 	i->sh = IBF(w, 16, 20);
220 	i->xsh = (IB(w, 30)<<5) | i->sh;
221 	i->spr = IBF(w, 11, 20);
222 	i->to = IBF(w, 6, 10);
223 	i->imm = IBF(w, 16, 19);
224 	i->xo = IBF(w, 21, 30);		/* bits 21-30, 22-30, 26-30, or 30 (beware) */
225 	if(i->op == 58){	/* class of 64-bit loads */
226 		i->xo = i->simm & 3;
227 		i->simm &= ~3;
228 	}
229 	i->imm64 = i->simm;
230 	if(i->op == 15)
231 		i->imm64 <<= 16;
232 	else if(i->op == 25 || i->op == 27 || i->op == 29)
233 		i->imm64 = (uvlong)(i->uimm<<16);
234 	i->w0 = w;
235 	i->target = -1;
236 	i->addr = pc;
237 	i->size = 1;
238 	return 1;
239 }
240 
241 static int
242 mkinstr(uvlong pc, Instr *i)
243 {
244 	Instr x;
245 
246 	if(decode(pc, i) < 0)
247 		return -1;
248 	/*
249 	 * combine ADDIS/ORI (CAU/ORIL) into MOVW
250 	 * also ORIS/ORIL for unsigned in 64-bit mode
251 	 */
252 	if ((i->op == 15 || i->op == 25) && i->ra==0) {
253 		if(decode(pc+4, &x) < 0)
254 			return -1;
255 		if (x.op == 24 && x.rs == x.ra && x.ra == i->rd) {
256 			i->imm64 |= (x.imm64 & 0xFFFF);
257 			if(i->op != 15)
258 				i->imm64 &= 0xFFFFFFFFUL;
259 			i->w1 = x.w0;
260 			i->target = x.rd;
261 			i->size++;
262 			return 1;
263 		}
264 	}
265 	return 1;
266 }
267 
268 static int
269 plocal(Instr *i)
270 {
271 	long offset;
272 	Symbol s;
273 
274 	if (!findsym(i->addr, CTEXT, &s) || !findlocal(&s, FRAMENAME, &s))
275 		return -1;
276 	offset = s.value - i->imm64;
277 	if (offset > 0) {
278 		if(getauto(&s, offset, CAUTO, &s)) {
279 			bprint(i, "%s+%lld(SP)", s.name, s.value);
280 			return 1;
281 		}
282 	} else {
283 		if (getauto(&s, -offset-4, CPARAM, &s)) {
284 			bprint(i, "%s+%ld(FP)", s.name, -offset);
285 			return 1;
286 		}
287 	}
288 	return -1;
289 }
290 
291 static int
292 pglobal(Instr *i, uvlong off, int anyoff, char *reg)
293 {
294 	Symbol s, s2;
295 	uvlong off1;
296 
297 	if(findsym(off, CANY, &s) &&
298 	   s.value-off < 4096 &&
299 	   (s.class == CDATA || s.class == CTEXT)) {
300 		if(off==s.value && s.name[0]=='$'){
301 			off1 = 0;
302 			geta(mymap, s.value, &off1);
303 			if(off1 && findsym(off1, CANY, &s2) && s2.value == off1){
304 				bprint(i, "$%s%s", s2.name, reg);
305 				return 1;
306 			}
307 		}
308 		bprint(i, "%s", s.name);
309 		if (s.value != off)
310 			bprint(i, "+%llux", off-s.value);
311 		bprint(i, reg);
312 		return 1;
313 	}
314 	if(!anyoff)
315 		return 0;
316 	bprint(i, "%llux%s", off, reg);
317 	return 1;
318 }
319 
320 static void
321 address(Instr *i)
322 {
323 	if (i->ra == REGSP && plocal(i) >= 0)
324 		return;
325 	if (i->ra == REGSB && mach->sb && pglobal(i, mach->sb+i->imm64, 0, "(SB)") >= 0)
326 		return;
327 	if(i->simm < 0)
328 		bprint(i, "-%x(R%d)", -i->simm, i->ra);
329 	else
330 		bprint(i, "%llux(R%d)", i->imm64, i->ra);
331 }
332 
333 static	char	*tcrbits[] = {"LT", "GT", "EQ", "VS"};
334 static	char	*fcrbits[] = {"GE", "LE", "NE", "VC"};
335 
336 typedef struct Opcode Opcode;
337 
338 struct Opcode {
339 	uchar	op;
340 	ushort	xo;
341 	ushort	xomask;
342 	char	*mnemonic;
343 	void	(*f)(Opcode *, Instr *);
344 	char	*ken;
345 	int	flags;
346 };
347 
348 static void format(char *, Instr *, char *);
349 
350 static void
351 branch(Opcode *o, Instr *i)
352 {
353 	char buf[8];
354 	int bo, bi;
355 
356 	bo = i->bo & ~1;	/* ignore prediction bit */
357 	if(bo==4 || bo==12 || bo==20) {	/* simple forms */
358 		if(bo != 20) {
359 			bi = i->bi&3;
360 			sprint(buf, "B%s%%L", bo==12? tcrbits[bi]: fcrbits[bi]);
361 			format(buf, i, nil);
362 			bprint(i, "\t");
363 			if(i->bi > 4)
364 				bprint(i, "CR(%d),", i->bi/4);
365 		} else
366 			format("BR%L\t", i, nil);
367 		if(i->op == 16)
368 			format(0, i, "%J");
369 		else if(i->op == 19 && i->xo == 528)
370 			format(0, i, "(CTR)");
371 		else if(i->op == 19 && i->xo == 16)
372 			format(0, i, "(LR)");
373 	} else
374 		format(o->mnemonic, i, o->ken);
375 }
376 
377 static void
378 addi(Opcode *o, Instr *i)
379 {
380 	if (i->op==14 && i->ra == 0)
381 		format("MOVW", i, "%i,R%d");
382 	else if (i->ra == REGSB) {
383 		bprint(i, "MOVW\t$");
384 		address(i);
385 		bprint(i, ",R%d", i->rd);
386 	} else if(i->op==14 && i->simm < 0) {
387 		bprint(i, "SUB\t$%d,R%d", -i->simm, i->ra);
388 		if(i->rd != i->ra)
389 			bprint(i, ",R%d", i->rd);
390 	} else if(i->ra == i->rd) {
391 		format(o->mnemonic, i, "%i");
392 		bprint(i, ",R%d", i->rd);
393 	} else
394 		format(o->mnemonic, i, o->ken);
395 }
396 
397 static void
398 addis(Opcode *o, Instr *i)
399 {
400 	long v;
401 
402 	v = i->imm64;
403 	if (i->op==15 && i->ra == 0)
404 		bprint(i, "MOVW\t$%lux,R%d", v, i->rd);
405 	else if (i->op==15 && i->ra == REGSB) {
406 		bprint(i, "MOVW\t$");
407 		address(i);
408 		bprint(i, ",R%d", i->rd);
409 	} else if(i->op==15 && v < 0) {
410 		bprint(i, "SUB\t$%ld,R%d", -v, i->ra);
411 		if(i->rd != i->ra)
412 			bprint(i, ",R%d", i->rd);
413 	} else {
414 		format(o->mnemonic, i, nil);
415 		bprint(i, "\t$%ld,R%d", v, i->ra);
416 		if(i->rd != i->ra)
417 			bprint(i, ",R%d", i->rd);
418 	}
419 }
420 
421 static void
422 andi(Opcode *o, Instr *i)
423 {
424 	if (i->ra == i->rs)
425 		format(o->mnemonic, i, "%I,R%d");
426 	else
427 		format(o->mnemonic, i, o->ken);
428 }
429 
430 static void
431 gencc(Opcode *o, Instr *i)
432 {
433 	format(o->mnemonic, i, o->ken);
434 }
435 
436 static void
437 gen(Opcode *o, Instr *i)
438 {
439 	format(o->mnemonic, i, o->ken);
440 	if (i->rc)
441 		bprint(i, " [illegal Rc]");
442 }
443 
444 static void
445 ldx(Opcode *o, Instr *i)
446 {
447 	if(i->ra == 0)
448 		format(o->mnemonic, i, "(R%b),R%d");
449 	else
450 		format(o->mnemonic, i, "(R%b+R%a),R%d");
451 	if(i->rc)
452 		bprint(i, " [illegal Rc]");
453 }
454 
455 static void
456 stx(Opcode *o, Instr *i)
457 {
458 	if(i->ra == 0)
459 		format(o->mnemonic, i, "R%d,(R%b)");
460 	else
461 		format(o->mnemonic, i, "R%d,(R%b+R%a)");
462 	if(i->rc && i->xo != 150)
463 		bprint(i, " [illegal Rc]");
464 }
465 
466 static void
467 fldx(Opcode *o, Instr *i)
468 {
469 	if(i->ra == 0)
470 		format(o->mnemonic, i, "(R%b),F%d");
471 	else
472 		format(o->mnemonic, i, "(R%b+R%a),F%d");
473 	if(i->rc)
474 		bprint(i, " [illegal Rc]");
475 }
476 
477 static void
478 fstx(Opcode *o, Instr *i)
479 {
480 	if(i->ra == 0)
481 		format(o->mnemonic, i, "F%d,(R%b)");
482 	else
483 		format(o->mnemonic, i, "F%d,(R%b+R%a)");
484 	if(i->rc)
485 		bprint(i, " [illegal Rc]");
486 }
487 
488 static void
489 dcb(Opcode *o, Instr *i)
490 {
491 	if(i->ra == 0)
492 		format(o->mnemonic, i, "(R%b)");
493 	else
494 		format(o->mnemonic, i, "(R%b+R%a)");
495 	if(i->rd)
496 		bprint(i, " [illegal Rd]");
497 	if(i->rc)
498 		bprint(i, " [illegal Rc]");
499 }
500 
501 static void
502 lw(Opcode *o, Instr *i, char r)
503 {
504 	format(o->mnemonic, i, nil);
505 	bprint(i, "\t");
506 	address(i);
507 	bprint(i, ",%c%d", r, i->rd);
508 }
509 
510 static void
511 load(Opcode *o, Instr *i)
512 {
513 	lw(o, i, 'R');
514 }
515 
516 static void
517 fload(Opcode *o, Instr *i)
518 {
519 	lw(o, i, 'F');
520 }
521 
522 static void
523 sw(Opcode *o, Instr *i, char r)
524 {
525 	int offset;
526 	Symbol s;
527 
528 	if (i->rs == REGSP) {
529 		if (findsym(i->addr, CTEXT, &s) && findlocal(&s, FRAMENAME, &s)) {
530 			offset = s.value-i->imm64;
531 			if (offset > 0 && getauto(&s, offset, CAUTO, &s)) {
532 				format(o->mnemonic, i, nil);
533 				bprint(i, "\t%c%d,%s-%d(SP)", r, i->rd, s.name, offset);
534 				return;
535 			}
536 		}
537 	}
538 	if (i->rs == REGSB && mach->sb) {
539 		format(o->mnemonic, i, nil);
540 		bprint(i, "\t%c%d,", r, i->rd);
541 		address(i);
542 		return;
543 	}
544 	if (r == 'F')
545 		format(o->mnemonic, i, "F%d,%l");
546 	else
547 		format(o->mnemonic, i, o->ken);
548 }
549 
550 static void
551 store(Opcode *o, Instr *i)
552 {
553 	sw(o, i, 'R');
554 }
555 
556 static void
557 fstore(Opcode *o, Instr *i)
558 {
559 	sw(o, i, 'F');
560 }
561 
562 static void
563 shifti(Opcode *o, Instr *i)
564 {
565 	if (i->ra == i->rs)
566 		format(o->mnemonic, i, "$%k,R%a");
567 	else
568 		format(o->mnemonic, i, o->ken);
569 }
570 
571 static void
572 shift(Opcode *o, Instr *i)
573 {
574 	if (i->ra == i->rs)
575 		format(o->mnemonic, i, "R%b,R%a");
576 	else
577 		format(o->mnemonic, i, o->ken);
578 }
579 
580 static void
581 add(Opcode *o, Instr *i)
582 {
583 	if (i->rd == i->ra)
584 		format(o->mnemonic, i, "R%b,R%d");
585 	else if (i->rd == i->rb)
586 		format(o->mnemonic, i, "R%a,R%d");
587 	else
588 		format(o->mnemonic, i, o->ken);
589 }
590 
591 static void
592 sub(Opcode *o, Instr *i)
593 {
594 	format(o->mnemonic, i, nil);
595 	bprint(i, "\t");
596 	if(i->op == 31) {
597 		bprint(i, "\tR%d,R%d", i->ra, i->rb);	/* subtract Ra from Rb */
598 		if(i->rd != i->rb)
599 			bprint(i, ",R%d", i->rd);
600 	} else
601 		bprint(i, "\tR%d,$%d,R%d", i->ra, i->simm, i->rd);
602 }
603 
604 static void
605 qmuldiv(Opcode *o, Instr *i)
606 {
607 	format(o->mnemonic, i, nil);
608 	if(i->op == 31)
609 		bprint(i, "\tR%d,R%d", i->rb, i->ra);
610 	else
611 		bprint(i, "\t$%d,R%d", i->simm, i->ra);
612 	if(i->ra != i->rd)
613 		bprint(i, ",R%d", i->rd);
614 }
615 
616 static void
617 and(Opcode *o, Instr *i)
618 {
619 	if (i->op == 31) {
620 		/* Rb,Rs,Ra */
621 		if (i->ra == i->rs)
622 			format(o->mnemonic, i, "R%b,R%a");
623 		else if (i->ra == i->rb)
624 			format(o->mnemonic, i, "R%s,R%a");
625 		else
626 			format(o->mnemonic, i, o->ken);
627 	} else {
628 		/* imm,Rs,Ra */
629 		if (i->ra == i->rs)
630 			format(o->mnemonic, i, "%I,R%a");
631 		else
632 			format(o->mnemonic, i, o->ken);
633 	}
634 }
635 
636 static void
637 or(Opcode *o, Instr *i)
638 {
639 	if (i->op == 31) {
640 		/* Rb,Rs,Ra */
641 		if (i->rs == 0 && i->ra == 0 && i->rb == 0)
642 			format("NOP", i, nil);
643 		else if (i->rs == i->rb)
644 			format("MOVW", i, "R%b,R%a");
645 		else
646 			and(o, i);
647 	} else
648 		and(o, i);
649 }
650 
651 static void
652 shifted(Opcode *o, Instr *i)
653 {
654 	format(o->mnemonic, i, nil);
655 	bprint(i, "\t$%lux,", (ulong)i->uimm<<16);
656 	if (i->rs == i->ra)
657 		bprint(i, "R%d", i->ra);
658 	else
659 		bprint(i, "R%d,R%d", i->rs, i->ra);
660 }
661 
662 static void
663 neg(Opcode *o, Instr *i)
664 {
665 	if (i->rd == i->ra)
666 		format(o->mnemonic, i, "R%d");
667 	else
668 		format(o->mnemonic, i, o->ken);
669 }
670 
671 static	char	ir2[] = "R%a,R%d";		/* reverse of IBM order */
672 static	char	ir3[] = "R%b,R%a,R%d";
673 static	char	ir3r[] = "R%a,R%b,R%d";
674 static	char	il3[] = "R%b,R%s,R%a";
675 static	char	il2u[] = "%I,R%d,R%a";
676 static	char	il3s[] = "$%k,R%s,R%a";
677 static	char	il2[] = "R%s,R%a";
678 static	char	icmp3[] = "R%a,R%b,%D";
679 static	char	cr3op[] = "%b,%a,%d";
680 static	char	ir2i[] = "%i,R%a,R%d";
681 static	char	fp2[] = "F%b,F%d";
682 static	char	fp3[] = "F%b,F%a,F%d";
683 static	char	fp3c[] = "F%c,F%a,F%d";
684 static	char	fp4[] = "F%a,F%c,F%b,F%d";
685 static	char	fpcmp[] = "F%a,F%b,%D";
686 static	char	ldop[] = "%l,R%d";
687 static	char	stop[] = "R%d,%l";
688 static	char	fldop[] = "%l,F%d";
689 static	char	fstop[] = "F%d,%l";
690 static	char	rldc[] = "R%b,R%s,$%E,R%a";
691 static	char	rlim[] = "R%b,R%s,$%z,R%a";
692 static	char	rlimi[] = "$%k,R%s,$%z,R%a";
693 static	char	rldi[] = "$%e,R%s,$%E,R%a";
694 
695 #define	OEM	IBF(~0,22,30)
696 #define	FP4	IBF(~0,26,30)
697 #define	ALL	(~0)
698 #define	RLDC	0xF
699 #define	RLDI	0xE
700 /*
701 notes:
702 	10-26: crfD = rD>>2; rD&3 mbz
703 		also, L bit (bit 10) mbz or selects 64-bit operands
704 */
705 
706 static Opcode opcodes[] = {
707 	{31,	266,	OEM,	"ADD%V%C",	add,	ir3},
708 	{31,	 10,	OEM,	"ADDC%V%C",	add,	ir3},
709 	{31,	138,	OEM,	"ADDE%V%C",	add,	ir3},
710 	{14,	0,	0,	"ADD",		addi,	ir2i},
711 	{12,	0,	0,	"ADDC",		addi,	ir2i},
712 	{13,	0,	0,	"ADDCCC",	addi,	ir2i},
713 	{15,	0,	0,	"ADD",		addis,	0},
714 	{31,	234,	OEM,	"ADDME%V%C",	gencc,	ir2},
715 	{31,	202,	OEM,	"ADDZE%V%C",	gencc,	ir2},
716 
717 	{31,	28,	ALL,	"AND%C",	and,	il3},
718 	{31,	60,	ALL,	"ANDN%C",	and,	il3},
719 	{28,	0,	0,	"ANDCC",	andi,	il2u},
720 	{29,	0,	0,	"ANDCC",	shifted, 0},
721 
722 	{18,	0,	0,	"B%L",		gencc,	"%j"},
723 	{16,	0,	0,	"BC%L",		branch,	"%d,%a,%J"},
724 	{19,	528,	ALL,	"BC%L",		branch,	"%d,%a,(CTR)"},
725 	{19,	16,	ALL,	"BC%L",		branch,	"%d,%a,(LR)"},
726 
727 	{31,	0,	ALL,	"CMP",		0,	icmp3},
728 	{11,	0,	0,	"CMP",		0,	"R%a,%i,%D"},
729 	{31,	32,	ALL,	"CMPU",		0,	icmp3},
730 	{10,	0,	0,	"CMPU",		0,	"R%a,%I,%D"},
731 
732 	{31,	58,	ALL,	"CNTLZD%C",	gencc,	ir2},	/* 64 */
733 	{31,	26,	ALL,	"CNTLZ%W%C",	gencc,	ir2},
734 
735 	{19,	257,	ALL,	"CRAND",	gen,	cr3op},
736 	{19,	129,	ALL,	"CRANDN",	gen,	cr3op},
737 	{19,	289,	ALL,	"CREQV",	gen,	cr3op},
738 	{19,	225,	ALL,	"CRNAND",	gen,	cr3op},
739 	{19,	33,	ALL,	"CRNOR",	gen,	cr3op},
740 	{19,	449,	ALL,	"CROR",		gen,	cr3op},
741 	{19,	417,	ALL,	"CRORN",	gen,	cr3op},
742 	{19,	193,	ALL,	"CRXOR",	gen,	cr3op},
743 
744 	{31,	86,	ALL,	"DCBF",		dcb,	0},
745 	{31,	470,	ALL,	"DCBI",		dcb,	0},
746 	{31,	54,	ALL,	"DCBST",	dcb,	0},
747 	{31,	278,	ALL,	"DCBT",		dcb,	0},
748 	{31,	246,	ALL,	"DCBTST",	dcb,	0},
749 	{31,	1014,	ALL,	"DCBZ",		dcb,	0},
750 	{31,	454,	ALL,	"DCCCI",	dcb,	0},
751 	{31,	966,	ALL,	"ICCCI",	dcb,	0},
752 
753 	{31,	489,	OEM,	"DIVD%V%C",	qmuldiv,	ir3},	/* 64 */
754 	{31,	457,	OEM,	"DIVDU%V%C",	qmuldiv,	ir3},	/* 64 */
755 	{31,	491,	OEM,	"DIVW%V%C",	qmuldiv,	ir3},
756 	{31,	459,	OEM,	"DIVWU%V%C",	qmuldiv,	ir3},
757 
758 	{31,	310,	ALL,	"ECIWX",	ldx,	0},
759 	{31,	438,	ALL,	"ECOWX",	stx,	0},
760 	{31,	854,	ALL,	"EIEIO",	gen,	0},
761 
762 	{31,	284,	ALL,	"EQV%C",	gencc,	il3},
763 
764 	{31,	954,	ALL,	"EXTSB%C",	gencc,	il2},
765 	{31,	922,	ALL,	"EXTSH%C",	gencc,	il2},
766 	{31,	986,	ALL,	"EXTSW%C",	gencc,	il2},	/* 64 */
767 
768 	{63,	264,	ALL,	"FABS%C",	gencc,	fp2},
769 	{63,	21,	ALL,	"FADD%C",	gencc,	fp3},
770 	{59,	21,	ALL,	"FADDS%C",	gencc,	fp3},
771 	{63,	32,	ALL,	"FCMPO",	gen,	fpcmp},
772 	{63,	0,	ALL,	"FCMPU",	gen,	fpcmp},
773 	{63,	846,	ALL,	"FCFID%C",	gencc,	fp2},	/* 64 */
774 	{63,	814,	ALL,	"FCTID%C",	gencc,	fp2},	/* 64 */
775 	{63,	815,	ALL,	"FCTIDZ%C",	gencc,	fp2},	/* 64 */
776 	{63,	14,	ALL,	"FCTIW%C",	gencc,	fp2},
777 	{63,	15,	ALL,	"FCTIWZ%C",	gencc,	fp2},
778 	{63,	18,	ALL,	"FDIV%C",	gencc,	fp3},
779 	{59,	18,	ALL,	"FDIVS%C",	gencc,	fp3},
780 	{63,	29,	FP4,	"FMADD%C",	gencc,	fp4},
781 	{59,	29,	FP4,	"FMADDS%C",	gencc,	fp4},
782 	{63,	72,	ALL,	"FMOVD%C",	gencc,	fp2},
783 	{63,	28,	FP4,	"FMSUB%C",	gencc,	fp4},
784 	{59,	28,	FP4,	"FMSUBS%C",	gencc,	fp4},
785 	{63,	25,	FP4,	"FMUL%C",	gencc,	fp3c},
786 	{59,	25,	FP4,	"FMULS%C",	gencc,	fp3c},
787 	{63,	136,	ALL,	"FNABS%C",	gencc,	fp2},
788 	{63,	40,	ALL,	"FNEG%C",	gencc,	fp2},
789 	{63,	31,	FP4,	"FNMADD%C",	gencc,	fp4},
790 	{59,	31,	FP4,	"FNMADDS%C",	gencc,	fp4},
791 	{63,	30,	FP4,	"FNMSUB%C",	gencc,	fp4},
792 	{59,	30,	FP4,	"FNMSUBS%C",	gencc,	fp4},
793 	{59,	24,	ALL,	"FRES%C",	gencc,	fp2},	/* optional */
794 	{63,	12,	ALL,	"FRSP%C",	gencc,	fp2},
795 	{63,	26,	ALL,	"FRSQRTE%C",	gencc,	fp2},	/* optional */
796 	{63,	23,	FP4,	"FSEL%CC",	gencc,	fp4},	/* optional */
797 	{63,	22,	ALL,	"FSQRT%C",	gencc,	fp2},	/* optional */
798 	{59,	22,	ALL,	"FSQRTS%C",	gencc,	fp2},	/* optional */
799 	{63,	20,	FP4,	"FSUB%C",	gencc,	fp3},
800 	{59,	20,	FP4,	"FSUBS%C",	gencc,	fp3},
801 
802 	{31,	982,	ALL,	"ICBI",		dcb,	0},	/* optional */
803 	{19,	150,	ALL,	"ISYNC",	gen,	0},
804 
805 	{34,	0,	0,	"MOVBZ",	load,	ldop},
806 	{35,	0,	0,	"MOVBZU",	load,	ldop},
807 	{31,	119,	ALL,	"MOVBZU",	ldx,	0},
808 	{31,	87,	ALL,	"MOVBZ",	ldx,	0},
809 	{50,	0,	0,	"FMOVD",	fload,	fldop},
810 	{51,	0,	0,	"FMOVDU",	fload,	fldop},
811 	{31,	631,	ALL,	"FMOVDU",	fldx,	0},
812 	{31,	599,	ALL,	"FMOVD",	fldx,	0},
813 	{48,	0,	0,	"FMOVS",	load,	fldop},
814 	{49,	0,	0,	"FMOVSU",	load,	fldop},
815 	{31,	567,	ALL,	"FMOVSU",	fldx,	0},
816 	{31,	535,	ALL,	"FMOVS",	fldx,	0},
817 	{42,	0,	0,	"MOVH",		load,	ldop},
818 	{43,	0,	0,	"MOVHU",	load,	ldop},
819 	{31,	375,	ALL,	"MOVHU",	ldx,	0},
820 	{31,	343,	ALL,	"MOVH",		ldx,	0},
821 	{31,	790,	ALL,	"MOVHBR",	ldx,	0},
822 	{40,	0,	0,	"MOVHZ",	load,	ldop},
823 	{41,	0,	0,	"MOVHZU",	load,	ldop},
824 	{31,	311,	ALL,	"MOVHZU",	ldx,	0},
825 	{31,	279,	ALL,	"MOVHZ",	ldx,	0},
826 	{46,	0,	0,	"MOVMW",	load,	ldop},
827 	{31,	597,	ALL,	"LSW",		gen,	"(R%a),$%n,R%d"},
828 	{31,	533,	ALL,	"LSW",		ldx,	0},
829 	{31,	20,	ALL,	"LWAR",		ldx,	0},
830 	{31,	84,	ALL,	"LWARD",	ldx,	0},	/* 64 */
831 
832 	{58,	0,	ALL,	"MOVD",		load,	ldop},	/* 64 */
833 	{58,	1,	ALL,	"MOVDU",	load,	ldop},	/* 64 */
834 	{31,	53,	ALL,	"MOVDU",	ldx,	0},	/* 64 */
835 	{31,	21,	ALL,	"MOVD",		ldx,	0},	/* 64 */
836 
837 	{31,	534,	ALL,	"MOVWBR",	ldx,	0},
838 
839 	{58,	2,	ALL,	"MOVW",		load,	ldop},	/* 64 (lwa) */
840 	{31,	373,	ALL,	"MOVWU",	ldx,	0},	/* 64 */
841 	{31,	341,	ALL,	"MOVW",		ldx,	0},	/* 64 */
842 
843 	{32,	0,	0,	"MOVW%Z",	load,	ldop},
844 	{33,	0,	0,	"MOVW%ZU",	load,	ldop},
845 	{31,	55,	ALL,	"MOVW%ZU",	ldx,	0},
846 	{31,	23,	ALL,	"MOVW%Z",	ldx,	0},
847 
848 	{19,	0,	ALL,	"MOVFL",	gen,	"%S,%D"},
849 	{63,	64,	ALL,	"MOVCRFS",	gen,	"%S,%D"},
850 	{31,	512,	ALL,	"MOVW",		gen,	"XER,%D"},
851 	{31,	19,	ALL,	"MOVW",		gen,	"CR,R%d"},
852 
853 	{63,	583,	ALL,	"MOVW%C",	gen,	"FPSCR, F%d"},	/* mffs */
854 	{31,	83,	ALL,	"MOVW",		gen,	"MSR,R%d"},
855 	{31,	339,	ALL,	"MOVW",		gen,	"%P,R%d"},
856 	{31,	595,	ALL,	"MOVW",		gen,	"SEG(%a),R%d"},
857 	{31,	659,	ALL,	"MOVW",		gen,	"SEG(R%b),R%d"},
858 	{31,	323,	ALL,	"MOVW",		gen,	"DCR(%Q),R%d"},
859 	{31,	451,	ALL,	"MOVW",		gen,	"R%s,DCR(%Q)"},
860 	{31,	259,	ALL,	"MOVW",		gen,	"DCR(R%a),R%d"},
861 	{31,	387,	ALL,	"MOVW",		gen,	"R%s,DCR(R%a)"},
862 	{31,	144,	ALL,	"MOVFL",	gen,	"R%s,%m,CR"},
863 	{63,	70,	ALL,	"MTFSB0%C",	gencc,	"%D"},
864 	{63,	38,	ALL,	"MTFSB1%C",	gencc,	"%D"},
865 	{63,	711,	ALL,	"MOVFL%C",	gencc,	"F%b,%M,FPSCR"},	/* mtfsf */
866 	{63,	134,	ALL,	"MOVFL%C",	gencc,	"%K,%D"},
867 	{31,	146,	ALL,	"MOVW",		gen,	"R%s,MSR"},
868 	{31,	178,	ALL,	"MOVD",		gen,	"R%s,MSR"},
869 	{31,	467,	ALL,	"MOVW",		gen,	"R%s,%P"},
870 	{31,	210,	ALL,	"MOVW",		gen,	"R%s,SEG(%a)"},
871 	{31,	242,	ALL,	"MOVW",		gen,	"R%s,SEG(R%b)"},
872 
873 	{31,	73,	ALL,	"MULHD%C",	gencc,	ir3},
874 	{31,	9,	ALL,	"MULHDU%C",	gencc,	ir3},
875 	{31,	233,	OEM,	"MULLD%V%C",	gencc,	ir3},
876 
877 	{31,	75,	ALL,	"MULHW%C",	gencc,	ir3},
878 	{31,	11,	ALL,	"MULHWU%C",	gencc,	ir3},
879 	{31,	235,	OEM,	"MULLW%V%C",	gencc,	ir3},
880 
881 	{7,	0,	0,	"MULLW",	qmuldiv,	"%i,R%a,R%d"},
882 
883 	{31,	476,	ALL,	"NAND%C",	gencc,	il3},
884 	{31,	104,	OEM,	"NEG%V%C",	neg,	ir2},
885 	{31,	124,	ALL,	"NOR%C",	gencc,	il3},
886 	{31,	444,	ALL,	"OR%C",		or,	il3},
887 	{31,	412,	ALL,	"ORN%C",	or,	il3},
888 	{24,	0,	0,	"OR",		and,	"%I,R%d,R%a"},
889 	{25,	0,	0,	"OR",		shifted, 0},
890 
891 	{19,	50,	ALL,	"RFI",		gen,	0},
892 	{19,	51,	ALL,	"RFCI",		gen,	0},
893 
894 	{30,	8,	RLDC,	"RLDCL%C",	gencc,	rldc},	/* 64 */
895 	{30,	9,	RLDC,	"RLDCR%C",	gencc,	rldc},	/* 64 */
896 	{30,	0,	RLDI,	"RLDCL%C",	gencc,	rldi},	/* 64 */
897 	{30,	1<<1, RLDI,	"RLDCR%C",	gencc,	rldi},	/* 64 */
898 	{30,	2<<1, RLDI,	"RLDC%C",	gencc,	rldi},	/* 64 */
899 	{30,	3<<1, RLDI,	"RLDMI%C",	gencc,	rldi},	/* 64 */
900 
901 	{20,	0,	0,	"RLWMI%C",	gencc,	rlimi},
902 	{21,	0,	0,	"RLWNM%C",	gencc,	rlimi},
903 	{23,	0,	0,	"RLWNM%C",	gencc,	rlim},
904 
905 	{17,	1,	ALL,	"SYSCALL",	gen,	0},
906 
907 	{31,	27,	ALL,	"SLD%C",	shift,	il3},	/* 64 */
908 	{31,	24,	ALL,	"SLW%C",	shift,	il3},
909 
910 	{31,	794,	ALL,	"SRAD%C",	shift,	il3},	/* 64 */
911 	{31,	(413<<1)|0,	ALL,	"SRAD%C",	shifti,	il3s},	/* 64 */
912 	{31,	(413<<1)|1,	ALL,	"SRAD%C",	shifti,	il3s},	/* 64 */
913 	{31,	792,	ALL,	"SRAW%C",	shift,	il3},
914 	{31,	824,	ALL,	"SRAW%C",	shifti,	il3s},
915 
916 	{31,	539,	ALL,	"SRD%C",	shift,	il3},	/* 64 */
917 	{31,	536,	ALL,	"SRW%C",	shift,	il3},
918 
919 	{38,	0,	0,	"MOVB",		store,	stop},
920 	{39,	0,	0,	"MOVBU",	store,	stop},
921 	{31,	247,	ALL,	"MOVBU",	stx,	0},
922 	{31,	215,	ALL,	"MOVB",		stx,	0},
923 	{54,	0,	0,	"FMOVD",	fstore,	fstop},
924 	{55,	0,	0,	"FMOVDU",	fstore,	fstop},
925 	{31,	759,	ALL,	"FMOVDU",	fstx,	0},
926 	{31,	727,	ALL,	"FMOVD",	fstx,	0},
927 	{52,	0,	0,	"FMOVS",	fstore,	fstop},
928 	{53,	0,	0,	"FMOVSU",	fstore,	fstop},
929 	{31,	695,	ALL,	"FMOVSU",	fstx,	0},
930 	{31,	663,	ALL,	"FMOVS",	fstx,	0},
931 	{44,	0,	0,	"MOVH",		store,	stop},
932 	{31,	918,	ALL,	"MOVHBR",	stx,	0},
933 	{45,	0,	0,	"MOVHU",	store,	stop},
934 	{31,	439,	ALL,	"MOVHU",	stx,	0},
935 	{31,	407,	ALL,	"MOVH",		stx,	0},
936 	{47,	0,	0,	"MOVMW",	store,	stop},
937 	{31,	725,	ALL,	"STSW",		gen,	"R%d,$%n,(R%a)"},
938 	{31,	661,	ALL,	"STSW",		stx,	0},
939 	{36,	0,	0,	"MOVW",		store,	stop},
940 	{31,	662,	ALL,	"MOVWBR",	stx,	0},
941 	{31,	150,	ALL,	"STWCCC",	stx,	0},
942 	{31,	214,	ALL,	"STDCCC",	stx,	0},	/* 64 */
943 	{37,	0,	0,	"MOVWU",	store,	stop},
944 	{31,	183,	ALL,	"MOVWU",	stx,	0},
945 	{31,	151,	ALL,	"MOVW",		stx,	0},
946 
947 	{62,	0,	0,	"MOVD%U",	store,	stop},	/* 64 */
948 	{31,	149,	ALL,	"MOVD",		stx,	0,},	/* 64 */
949 	{31,	181,	ALL,	"MOVDU",	stx,	0},	/* 64 */
950 
951 	{31,	498,	ALL,	"SLBIA",	gen,	0},	/* 64 */
952 	{31,	434,	ALL,	"SLBIE",	gen,	"R%b"},	/* 64 */
953 	{31,	466,	ALL,	"SLBIEX",	gen,	"R%b"},	/* 64 */
954 	{31,	915,	ALL,	"SLBMFEE",	gen,	"R%b,R%d"},	/* 64 */
955 	{31,	851,	ALL,	"SLBMFEV",	gen,	"R%b,R%d"},	/* 64 */
956 	{31,	402,	ALL,	"SLBMTE",	gen,	"R%s,R%b"},	/* 64 */
957 
958 	{31,	40,	OEM,	"SUB%V%C",	sub,	ir3},
959 	{31,	8,	OEM,	"SUBC%V%C",	sub,	ir3},
960 	{31,	136,	OEM,	"SUBE%V%C",	sub,	ir3},
961 	{8,	0,	0,	"SUBC",		gen,	"R%a,%i,R%d"},
962 	{31,	232,	OEM,	"SUBME%V%C",	sub,	ir2},
963 	{31,	200,	OEM,	"SUBZE%V%C",	sub,	ir2},
964 
965 	{31,	598,	ALL,	"SYNC",		gen,	0},	/* TO DO: there's a parameter buried in there */
966 	{2,	0,	0,	"TD",		gen,	"%d,R%a,%i"},	/* 64 */
967 	{31,	370,	ALL,	"TLBIA",	gen,	0},	/* optional */
968 	{31,	306,	ALL,	"TLBIE",	gen,	"R%b"},	/* optional */
969 	{31,	274,	ALL,	"TLBIEL",	gen,	"R%b"},	/* optional */
970 	{31,	1010,	ALL,	"TLBLI",	gen,	"R%b"},	/* optional */
971 	{31,	978,	ALL,	"TLBLD",	gen,	"R%b"},	/* optional */
972 	{31,	566,	ALL,	"TLBSYNC",	gen,	0},	/* optional */
973 	{31,	68,	ALL,	"TD",		gen,	"%d,R%a,R%b"},	/* 64 */
974 	{31,	4,	ALL,	"TW",		gen,	"%d,R%a,R%b"},
975 	{3,	0,	0,	"TW",		gen,	"%d,R%a,%i"},
976 
977 	{31,	316,	ALL,	"XOR",		and,	il3},
978 	{26,	0,	0,	"XOR",		and,	il2u},
979 	{27,	0,	0,	"XOR",		shifted, 0},
980 
981 	{0},
982 };
983 
984 typedef struct Spr Spr;
985 struct Spr {
986 	int	n;
987 	char	*name;
988 };
989 
990 static	Spr	sprname[] = {
991 	{0, "MQ"},
992 	{1, "XER"},
993 	{268, "TBL"},
994 	{269, "TBU"},
995 	{8, "LR"},
996 	{9, "CTR"},
997 	{528, "IBAT0U"},
998 	{529, "IBAT0L"},
999 	{530, "IBAT1U"},
1000 	{531, "IBAT1L"},
1001 	{532, "IBAT2U"},
1002 	{533, "IBAT2L"},
1003 	{534, "IBAT3U"},
1004 	{535, "IBAT3L"},
1005 	{536, "DBAT0U"},
1006 	{537, "DBAT0L"},
1007 	{538, "DBAT1U"},
1008 	{539, "DBAT1L"},
1009 	{540, "DBAT2U"},
1010 	{541, "DBAT2L"},
1011 	{542, "DBAT3U"},
1012 	{543, "DBAT3L"},
1013 	{25, "SDR1"},
1014 	{19, "DAR"},
1015 	{272, "SPRG0"},
1016 	{273, "SPRG1"},
1017 	{274, "SPRG2"},
1018 	{275, "SPRG3"},
1019 	{18, "DSISR"},
1020 	{26, "SRR0"},
1021 	{27, "SRR1"},
1022 	{284, "TBLW"},
1023 	{285, "TBUW"},
1024 	{22, "DEC"},
1025 	{282, "EAR"},
1026 	{1008, "HID0"},
1027 	{1009, "HID1"},
1028 	{976, "DMISS"},
1029 	{977, "DCMP"},
1030 	{978, "HASH1"},
1031 	{979, "HASH2"},
1032 	{980, "IMISS"},
1033 	{981, "ICMP"},
1034 	{982, "RPA"},
1035 	{1010, "IABR"},
1036 	{1013, "DABR"},
1037 	{0,0},
1038 };
1039 
1040 static int
1041 shmask(uvlong *m)
1042 {
1043 	int i;
1044 
1045 	for(i=0; i<63; i++)
1046 		if(*m & ((uvlong)1<<i))
1047 			break;
1048 	if(i > 63)
1049 		return 0;
1050 	if(*m & ~((uvlong)1<<i)){	/* more than one bit: do multiples of bytes */
1051 		i = (i/8)*8;
1052 		if(i == 0)
1053 			return 0;
1054 	}
1055 	*m >>= i;
1056 	return i;
1057 }
1058 
1059 static void
1060 format(char *mnemonic, Instr *i, char *f)
1061 {
1062 	int n, s;
1063 	ulong mask;
1064 	uvlong vmask;
1065 
1066 	if (mnemonic)
1067 		format(0, i, mnemonic);
1068 	if (f == 0)
1069 		return;
1070 	if (mnemonic)
1071 		bprint(i, "\t");
1072 	for ( ; *f; f++) {
1073 		if (*f != '%') {
1074 			bprint(i, "%c", *f);
1075 			continue;
1076 		}
1077 		switch (*++f) {
1078 
1079 		case 'a':
1080 			bprint(i, "%d", i->ra);
1081 			break;
1082 
1083 		case 'b':
1084 			bprint(i, "%d", i->rb);
1085 			break;
1086 
1087 		case 'c':
1088 			bprint(i, "%d", i->frc);
1089 			break;
1090 
1091 		case 'd':
1092 		case 's':
1093 			bprint(i, "%d", i->rd);
1094 			break;
1095 
1096 		case 'C':
1097 			if(i->rc)
1098 				bprint(i, "CC");
1099 			break;
1100 
1101 		case 'D':
1102 			if(i->rd & 3)
1103 				bprint(i, "CR(INVAL:%d)", i->rd);
1104 			else if(i->op == 63)
1105 				bprint(i, "FPSCR(%d)", i->crfd);
1106 			else
1107 				bprint(i, "CR(%d)", i->crfd);
1108 			break;
1109 
1110 		case 'e':
1111 			bprint(i, "%d", i->xsh);
1112 			break;
1113 
1114 		case 'E':
1115 			switch(IBF(i->w0,27,30)){	/* low bit is top bit of shift in rldiX cases */
1116 			case 8:	i->mb = i->xmbe; i->me = 63; break;	/* rldcl */
1117 			case 9:	i->mb = 0; i->me = i->xmbe; break;	/* rldcr */
1118 			case 4: case 5:
1119 					i->mb = i->xmbe; i->me = 63-i->xsh; break;	/* rldic */
1120 			case 0: case 1:
1121 					i->mb = i->xmbe; i->me = 63; break;	/* rldicl */
1122 			case 2: case 3:
1123 					i->mb = 0; i->me = i->xmbe; break;	/* rldicr */
1124 			case 6: case 7:
1125 					i->mb = i->xmbe; i->me = 63-i->xsh; break;	/* rldimi */
1126 			}
1127 			vmask = (~(uvlong)0>>i->mb) & (~(uvlong)0<<(63-i->me));
1128 			s = shmask(&vmask);
1129 			if(s)
1130 				bprint(i, "(%llux<<%d)", vmask, s);
1131 			else
1132 				bprint(i, "%llux", vmask);
1133 			break;
1134 
1135 		case 'i':
1136 			bprint(i, "$%d", i->simm);
1137 			break;
1138 
1139 		case 'I':
1140 			bprint(i, "$%ux", i->uimm);
1141 			break;
1142 
1143 		case 'j':
1144 			if(i->aa)
1145 				pglobal(i, i->li, 1, "(SB)");
1146 			else
1147 				pglobal(i, i->addr+i->li, 1, "");
1148 			break;
1149 
1150 		case 'J':
1151 			if(i->aa)
1152 				pglobal(i, i->bd, 1, "(SB)");
1153 			else
1154 				pglobal(i, i->addr+i->bd, 1, "");
1155 			break;
1156 
1157 		case 'k':
1158 			bprint(i, "%d", i->sh);
1159 			break;
1160 
1161 		case 'K':
1162 			bprint(i, "$%x", i->imm);
1163 			break;
1164 
1165 		case 'L':
1166 			if(i->lk)
1167 				bprint(i, "L");
1168 			break;
1169 
1170 		case 'l':
1171 			if(i->simm < 0)
1172 				bprint(i, "-%x(R%d)", -i->simm, i->ra);
1173 			else
1174 				bprint(i, "%x(R%d)", i->simm, i->ra);
1175 			break;
1176 
1177 		case 'm':
1178 			bprint(i, "%ux", i->crm);
1179 			break;
1180 
1181 		case 'M':
1182 			bprint(i, "%ux", i->fm);
1183 			break;
1184 
1185 		case 'n':
1186 			bprint(i, "%d", i->nb==0? 32: i->nb);	/* eg, pg 10-103 */
1187 			break;
1188 
1189 		case 'P':
1190 			n = ((i->spr&0x1f)<<5)|((i->spr>>5)&0x1f);
1191 			for(s=0; sprname[s].name; s++)
1192 				if(sprname[s].n == n)
1193 					break;
1194 			if(sprname[s].name) {
1195 				if(s < 10)
1196 					bprint(i, sprname[s].name);
1197 				else
1198 					bprint(i, "SPR(%s)", sprname[s].name);
1199 			} else
1200 				bprint(i, "SPR(%d)", n);
1201 			break;
1202 
1203 		case 'Q':
1204 			n = ((i->spr&0x1f)<<5)|((i->spr>>5)&0x1f);
1205 			bprint(i, "%d", n);
1206 			break;
1207 
1208 		case 'S':
1209 			if(i->ra & 3)
1210 				bprint(i, "CR(INVAL:%d)", i->ra);
1211 			else if(i->op == 63)
1212 				bprint(i, "FPSCR(%d)", i->crfs);
1213 			else
1214 				bprint(i, "CR(%d)", i->crfs);
1215 			break;
1216 
1217 		case 'U':
1218 			if(i->rc)
1219 				bprint(i, "U");
1220 			break;
1221 
1222 		case 'V':
1223 			if(i->oe)
1224 				bprint(i, "V");
1225 			break;
1226 
1227 		case 'w':
1228 			bprint(i, "[%lux]", i->w0);
1229 			break;
1230 
1231 		case 'W':
1232 			if(i->m64)
1233 				bprint(i, "W");
1234 			break;
1235 
1236 		case 'Z':
1237 			if(i->m64)
1238 				bprint(i, "Z");
1239 			break;
1240 
1241 		case 'z':
1242 			if(i->mb <= i->me)
1243 				mask = ((ulong)~0L>>i->mb) & (~0L<<(31-i->me));
1244 			else
1245 				mask = ~(((ulong)~0L>>(i->me+1)) & (~0L<<(31-(i->mb-1))));
1246 			bprint(i, "%lux", mask);
1247 			break;
1248 
1249 		case '\0':
1250 			bprint(i, "%%");
1251 			return;
1252 
1253 		default:
1254 			bprint(i, "%%%c", *f);
1255 			break;
1256 		}
1257 	}
1258 }
1259 
1260 static int
1261 printins(Map *map, uvlong pc, char *buf, int n)
1262 {
1263 	Instr i;
1264 	Opcode *o;
1265 
1266 	mymap = map;
1267 	memset(&i, 0, sizeof(i));
1268 	i.curr = buf;
1269 	i.end = buf+n-1;
1270 	if(mkinstr(pc, &i) < 0)
1271 		return -1;
1272 	for(o = opcodes; o->mnemonic != 0; o++)
1273 		if(i.op == o->op && (i.xo & o->xomask) == o->xo) {
1274 			if (o->f)
1275 				(*o->f)(o, &i);
1276 			else
1277 				format(o->mnemonic, &i, o->ken);
1278 			return i.size*4;
1279 		}
1280 	bprint(&i, "unknown %lux", i.w0);
1281 	return i.size*4;
1282 }
1283 
1284 static int
1285 powerinst(Map *map, uvlong pc, char modifier, char *buf, int n)
1286 {
1287 	USED(modifier);
1288 	return printins(map, pc, buf, n);
1289 }
1290 
1291 static int
1292 powerdas(Map *map, uvlong pc, char *buf, int n)
1293 {
1294 	Instr instr;
1295 
1296 	mymap = map;
1297 	memset(&instr, 0, sizeof(instr));
1298 	instr.curr = buf;
1299 	instr.end = buf+n-1;
1300 	if (mkinstr(pc, &instr) < 0)
1301 		return -1;
1302 	if (instr.end-instr.curr > 8)
1303 		instr.curr = _hexify(instr.curr, instr.w0, 7);
1304 	if (instr.end-instr.curr > 9 && instr.size == 2) {
1305 		*instr.curr++ = ' ';
1306 		instr.curr = _hexify(instr.curr, instr.w1, 7);
1307 	}
1308 	*instr.curr = 0;
1309 	return instr.size*4;
1310 }
1311 
1312 static int
1313 powerinstlen(Map *map, uvlong pc)
1314 {
1315 	Instr i;
1316 
1317 	mymap = map;
1318 	if (mkinstr(pc, &i) < 0)
1319 		return -1;
1320 	return i.size*4;
1321 }
1322 
1323 static int
1324 powerfoll(Map *map, uvlong pc, Rgetter rget, uvlong *foll)
1325 {
1326 	char *reg;
1327 	Instr i;
1328 
1329 	mymap = map;
1330 	if (mkinstr(pc, &i) < 0)
1331 		return -1;
1332 	foll[0] = pc+4;
1333 	foll[1] = pc+4;
1334 	switch(i.op) {
1335 	default:
1336 		return 1;
1337 
1338 	case 18:	/* branch */
1339 		foll[0] = i.li;
1340 		if(!i.aa)
1341 			foll[0] += pc;
1342 		break;
1343 
1344 	case 16:	/* conditional branch */
1345 		foll[0] = i.bd;
1346 		if(!i.aa)
1347 			foll[0] += pc;
1348 		break;
1349 
1350 	case 19:	/* conditional branch to register */
1351 		if(i.xo == 528)
1352 			reg = "CTR";
1353 		else if(i.xo == 16)
1354 			reg = "LR";
1355 		else
1356 			return 1;	/* not a branch */
1357 		foll[0] = (*rget)(map, reg);
1358 		break;
1359 	}
1360 	if(i.lk)
1361 		return 2;
1362 	return 1;
1363 }
1364