]> git.lizzy.rs Git - plan9front.git/blob - sys/src/libmach/qdb.c
add HISTORY to various man pages
[plan9front.git] / sys / src / libmach / qdb.c
1 #include <u.h>
2 #include <libc.h>
3 #include <bio.h>
4 #include <mach.h>
5
6 /*
7  * PowerPC-specific debugger interface,
8  * including 64-bit modes
9  *      forsyth@terzarima.net
10  */
11
12 static  char    *powerexcep(Map*, Rgetter);
13 static  int     powerfoll(Map*, uvlong, Rgetter, uvlong*);
14 static  int     powerinst(Map*, uvlong, char, char*, int);
15 static  int     powerinstlen(Map*, uvlong);
16 static  int     powerdas(Map*, uvlong, char*, int);
17
18 /*
19  *      Machine description
20  */
21 Machdata powermach =
22 {
23         {0x02, 0x8f, 0xff, 0xff},               /* break point */       /* BUG */
24         4,                      /* break point size */
25
26         beswab,                 /* short to local byte order */
27         beswal,                 /* long to local byte order */
28         beswav,                 /* vlong to local byte order */
29         risctrace,              /* print C traceback */
30         riscframe,              /* frame finder */
31         powerexcep,             /* print exception */
32         0,                      /* breakpoint fixup */
33         beieeesftos,            /* single precision float printer */
34         beieeedftos,            /* double precisioin float printer */
35         powerfoll,              /* following addresses */
36         powerinst,              /* print instruction */
37         powerdas,               /* dissembler */
38         powerinstlen,           /* instruction size */
39 };
40
41 static char *excname[] =
42 {
43         "reserved 0",
44         "system reset",
45         "machine check",
46         "data access",
47         "instruction access",
48         "external interrupt",
49         "alignment",
50         "program exception",
51         "floating-point unavailable",
52         "decrementer",
53         "i/o controller interface error",
54         "reserved B",
55         "system call",
56         "trace trap",
57         "floating point assist",
58         "reserved",
59         "ITLB miss",
60         "DTLB load miss",
61         "DTLB store miss",
62         "instruction address breakpoint"
63         "SMI interrupt"
64         "reserved 15",
65         "reserved 16",
66         "reserved 17",
67         "reserved 18",
68         "reserved 19",
69         "reserved 1A",
70         /* the following are made up on a program exception */
71         "floating point exception",             /* FPEXC */
72         "illegal instruction",
73         "privileged instruction",
74         "trap",
75         "illegal operation",
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            off-s.value < 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)"))
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 qdiv(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",     qdiv,   ir3},   /* 64 */
754         {31,    457,    OEM,    "DIVDU%V%C",    qdiv,   ir3},   /* 64 */
755         {31,    491,    OEM,    "DIVW%V%C",     qdiv,   ir3},
756         {31,    459,    OEM,    "DIVWU%V%C",    qdiv,   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",        qdiv,   "%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 }