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