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*
powerexcep(Map * map,Rgetter rget)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
bprint(Instr * i,char * fmt,...)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
decode(uvlong pc,Instr * i)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
mkinstr(uvlong pc,Instr * i)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
plocal(Instr * i)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
pglobal(Instr * i,uvlong off,int anyoff,char * reg)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
address(Instr * i)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
branch(Opcode * o,Instr * i)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
addi(Opcode * o,Instr * i)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
addis(Opcode * o,Instr * i)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
andi(Opcode * o,Instr * i)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
gencc(Opcode * o,Instr * i)431 gencc(Opcode *o, Instr *i)
432 {
433 format(o->mnemonic, i, o->ken);
434 }
435
436 static void
gen(Opcode * o,Instr * i)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
ldx(Opcode * o,Instr * i)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
stx(Opcode * o,Instr * i)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
fldx(Opcode * o,Instr * i)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
fstx(Opcode * o,Instr * i)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
dcb(Opcode * o,Instr * i)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
lw(Opcode * o,Instr * i,char r)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
load(Opcode * o,Instr * i)511 load(Opcode *o, Instr *i)
512 {
513 lw(o, i, 'R');
514 }
515
516 static void
fload(Opcode * o,Instr * i)517 fload(Opcode *o, Instr *i)
518 {
519 lw(o, i, 'F');
520 }
521
522 static void
sw(Opcode * o,Instr * i,char r)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
store(Opcode * o,Instr * i)551 store(Opcode *o, Instr *i)
552 {
553 sw(o, i, 'R');
554 }
555
556 static void
fstore(Opcode * o,Instr * i)557 fstore(Opcode *o, Instr *i)
558 {
559 sw(o, i, 'F');
560 }
561
562 static void
shifti(Opcode * o,Instr * i)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
shift(Opcode * o,Instr * i)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
add(Opcode * o,Instr * i)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
sub(Opcode * o,Instr * i)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
qdiv(Opcode * o,Instr * i)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
and(Opcode * o,Instr * i)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
or(Opcode * o,Instr * i)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
shifted(Opcode * o,Instr * i)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
neg(Opcode * o,Instr * i)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
shmask(uvlong * m)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
format(char * mnemonic,Instr * i,char * f)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
printins(Map * map,uvlong pc,char * buf,int n)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
powerinst(Map * map,uvlong pc,char modifier,char * buf,int n)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
powerdas(Map * map,uvlong pc,char * buf,int n)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
powerinstlen(Map * map,uvlong pc)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
powerfoll(Map * map,uvlong pc,Rgetter rget,uvlong * foll)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