Blob


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>
11 /*
12 * PowerPC-specific debugger interface
13 * forsyth@plan9.cs.york.ac.uk
14 */
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);
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 };
59 static char*
60 powerexcep(Map *map, Regs *regs)
61 {
62 u64int c;
63 static char buf[32];
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 }
74 /*
75 * disassemble PowerPC opcodes
76 */
78 #define REGSP 1 /* should come from q.out.h, but there's a clash */
79 #define REGSB 2
81 /*static char FRAMENAME[] = ".frame"; */
83 static Map *mymap;
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;
141 #define IBF(v,a,b) (((ulong)(v)>>(32-(b)-1)) & ~(~0UL<<(((b)-(a)+1))))
142 #define IB(v,b) IBF((v),(b),(b))
144 static void
145 bprint(Instr *i, char *fmt, ...)
147 va_list arg;
149 va_start(arg, fmt);
150 i->curr = vseprint(i->curr, i->end, fmt, arg);
151 va_end(arg);
154 static int
155 decode(ulong pc, Instr *i)
157 u32int w;
159 if (get4(mymap, pc, &w) < 0) {
160 werrstr("can't read instruction: %r");
161 return -1;
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;
210 static int
211 mkinstr(ulong pc, Instr *i)
213 Instr x;
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;
231 return 1;
234 static int
235 plocal(Instr *i)
237 Symbol s;
238 Loc l, li;
240 l.type = LOFFSET;
241 l.offset = i->immediate;
242 l.reg = "SP";
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;
252 static int
253 pglobal(Instr *i, long off, int anyoff, char *reg)
255 Symbol s, s2;
256 u32int off1;
257 Loc l;
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;
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;
279 if(!anyoff)
280 return 0;
281 bprint(i, "%lux%s", off, reg);
282 return 1;
285 static void
286 address(Instr *i)
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);
298 static char *tcrbits[] = {"LT", "GT", "EQ", "VS"};
299 static char *fcrbits[] = {"GE", "LE", "NE", "VC"};
301 typedef struct Opcode Opcode;
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 };
313 static void format(char *, Instr *, char *);
315 static void
316 branch(Opcode *o, Instr *i)
318 char buf[8];
319 int bo, bi;
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);
342 static void
343 addi(Opcode *o, Instr *i)
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);
362 static void
363 addis(Opcode *o, Instr *i)
365 long v;
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);
386 static void
387 andi(Opcode *o, Instr *i)
389 if (i->ra == i->rs)
390 format(o->mnemonic, i, "%I,R%d");
391 else
392 format(o->mnemonic, i, o->ken);
395 static void
396 gencc(Opcode *o, Instr *i)
398 format(o->mnemonic, i, o->ken);
401 static void
402 gen(Opcode *o, Instr *i)
404 format(o->mnemonic, i, o->ken);
405 if (i->rc)
406 bprint(i, " [illegal Rc]");
409 static void
410 ldx(Opcode *o, Instr *i)
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]");
420 static void
421 stx(Opcode *o, Instr *i)
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]");
431 static void
432 fldx(Opcode *o, Instr *i)
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]");
442 static void
443 fstx(Opcode *o, Instr *i)
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]");
453 static void
454 dcb(Opcode *o, Instr *i)
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]");
466 static void
467 lw(Opcode *o, Instr *i, char r)
469 bprint(i, "%s\t", o->mnemonic);
470 address(i);
471 bprint(i, ",%c%d", r, i->rd);
474 static void
475 load(Opcode *o, Instr *i)
477 lw(o, i, 'R');
480 static void
481 fload(Opcode *o, Instr *i)
483 lw(o, i, 'F');
486 static void
487 sw(Opcode *o, Instr *i, char r)
489 char *m;
490 Symbol s;
491 Loc l;
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;
508 if (i->rs == REGSB && mach->sb) {
509 bprint(i, "%s\t%c%d,", m, r, i->rd);
510 address(i);
511 return;
513 if (r == 'F')
514 format(m, i, "F%d,%l");
515 else
516 format(m, i, o->ken);
519 static void
520 store(Opcode *o, Instr *i)
522 sw(o, i, 'R');
525 static void
526 fstore(Opcode *o, Instr *i)
528 sw(o, i, 'F');
531 static void
532 shifti(Opcode *o, Instr *i)
534 if (i->ra == i->rs)
535 format(o->mnemonic, i, "$%k,R%a");
536 else
537 format(o->mnemonic, i, o->ken);
540 static void
541 shift(Opcode *o, Instr *i)
543 if (i->ra == i->rs)
544 format(o->mnemonic, i, "R%b,R%a");
545 else
546 format(o->mnemonic, i, o->ken);
549 static void
550 add(Opcode *o, Instr *i)
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);
560 static void
561 sub(Opcode *o, Instr *i)
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);
573 #define div power_div
575 static void
576 div(Opcode *o, Instr *i)
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);
587 static void
588 and(Opcode *o, Instr *i)
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);
607 static void
608 or(Opcode *o, Instr *i)
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);
622 static void
623 shifted(Opcode *o, Instr *i)
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);
633 static void
634 neg(Opcode *o, Instr *i)
636 if (i->rd == i->ra)
637 format(o->mnemonic, i, "R%d");
638 else
639 format(o->mnemonic, i, o->ken);
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";
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 */
673 static Opcode opcodes[] = {
674 {31, 360, OEM, "ABS%V%C", 0, ir2}, /* POWER */
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},
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},
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)"},
696 {31, 531, ALL, "CLCS", gen, ir2}, /* POWER */
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"},
703 {31, 26, ALL, "CNTLZ%C", gencc, ir2},
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},
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},
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},
726 {31, 264, OEM, "DOZ%V%C", gencc, ir3r}, /* POWER */
727 {9, 0, 0, "DOZ", gen, ir2i}, /* POWER */
729 {31, 310, ALL, "ECIWX", ldx, 0},
730 {31, 438, ALL, "ECOWX", stx, 0},
731 {31, 854, ALL, "EIEIO", gen, 0},
733 {31, 284, ALL, "EQV%C", gencc, il3},
735 {31, 954, ALL, "EXTSB%C", gencc, il2},
736 {31, 922, ALL, "EXTSH%C", gencc, il2},
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},
764 {31, 982, ALL, "ICBI", dcb, 0},
765 {19, 150, ALL, "ISYNC", gen, 0},
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},
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 */
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"},
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)"},
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 */
826 {31, 235, OEM, "MULLW%V%C", gencc, ir3},
827 {7, 0, 0, "MULLW", div, "%i,R%a,R%d"},
829 {31, 488, OEM, "NABS%V%C", neg, ir2}, /* POWER */
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},
839 {19, 50, ALL, "RFI", gen, 0},
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},
846 {31, 537, ALL, "RRIB%C", gencc, il3}, /* POWER */
848 {17, 1, ALL, "SYSCALL", gen, 0},
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 */
857 {31, 24, ALL, "SLW%C", shift, il3},
859 {31, 920, ALL, "SRAQ%C", shift, il3}, /* POWER */
860 {31, 952, ALL, "SRAQ%C", shifti, il3s}, /* POWER */
862 {31, 792, ALL, "SRAW%C", shift, il3},
863 {31, 824, ALL, "SRAW%C", shifti, il3s},
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 */
873 {31, 536, ALL, "SRW%C", shift, il3},
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},
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},
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"},
917 {31, 316, ALL, "XOR", and, il3},
918 {26, 0, 0, "XOR", and, il2u},
919 {27, 0, 0, "XOR", shifted, 0},
921 {0},
922 };
924 typedef struct Spr Spr;
925 struct Spr {
926 int n;
927 char *name;
928 };
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 };
979 static void
980 format(char *mnemonic, Instr *i, char *f)
982 int n, s;
983 ulong mask;
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;
996 switch (*++f) {
997 case 'V':
998 if(i->oe)
999 bprint(i, "V");
1000 break;
1002 case 'C':
1003 if(i->rc)
1004 bprint(i, "CC");
1005 break;
1007 case 'a':
1008 bprint(i, "%d", i->ra);
1009 break;
1011 case 'b':
1012 bprint(i, "%d", i->rb);
1013 break;
1015 case 'c':
1016 bprint(i, "%d", i->frc);
1017 break;
1019 case 'd':
1020 case 's':
1021 bprint(i, "%d", i->rd);
1022 break;
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;
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;
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;
1049 case 'i':
1050 bprint(i, "$%ld", i->simm);
1051 break;
1053 case 'I':
1054 bprint(i, "$%lx", i->uimm);
1055 break;
1057 case 'w':
1058 bprint(i, "[%lux]", i->w0);
1059 break;
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;
1075 case 'n':
1076 bprint(i, "%d", i->nb==0? 32: i->nb); /* eg, pg 10-103 */
1077 break;
1079 case 'm':
1080 bprint(i, "%lx", i->crm);
1081 break;
1083 case 'M':
1084 bprint(i, "%lx", i->fm);
1085 break;
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;
1095 case 'k':
1096 bprint(i, "%d", i->sh);
1097 break;
1099 case 'K':
1100 bprint(i, "$%x", i->imm);
1101 break;
1103 case 'L':
1104 if(i->lk)
1105 bprint(i, "L");
1106 break;
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;
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;
1122 case '\0':
1123 bprint(i, "%%");
1124 return;
1126 default:
1127 bprint(i, "%%%c", *f);
1128 break;
1133 static int
1134 printins(Map *map, ulong pc, char *buf, int n)
1136 Instr i;
1137 Opcode *o;
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;
1153 bprint(&i, "unknown %lux", i.w0);
1154 return i.size*4;
1157 static int
1158 powerdas(Map *map, u64int pc, char modifier, char *buf, int n)
1160 USED(modifier);
1161 return printins(map, pc, buf, n);
1164 static int
1165 powerhexinst(Map *map, u64int pc, char *buf, int n)
1167 Instr instr;
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);
1181 *instr.curr = 0;
1182 return instr.size*4;
1185 static int
1186 powerinstlen(Map *map, u64int pc)
1188 Instr i;
1190 mymap = map;
1191 if (mkinstr(pc, &i) < 0)
1192 return -1;
1193 return i.size*4;
1196 static int
1197 powerfoll(Map *map, Regs *regs, u64int pc, u64int *foll)
1199 char *reg;
1200 Instr i;
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;
1211 case 18: /* branch */
1212 foll[0] = i.li;
1213 if(!i.aa)
1214 foll[0] += pc;
1215 break;
1217 case 16: /* conditional branch */
1218 foll[0] = i.bd;
1219 if(!i.aa)
1220 foll[0] += pc;
1221 break;
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;
1234 if(i.lk)
1235 return 2;
1236 return 1;
1239 #define REGOFF(x) (ulong) (&((struct Ureg *) 0)->x)
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))
1248 #define REGSIZE sizeof(struct Ureg)
1249 #define FPREGSIZE (8*33)
1251 Regdesc powerreglist[] =
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 }
1331 static char *powerwindregs[] =
1333 "PC",
1334 "SP",
1335 "LR",
1339 static int
1340 powerunwind(Map *map, Regs *regs, u64int *next, Symbol *sym)
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.
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;
1361 /* the machine description */
1362 Mach machpower =
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 */
1384 powerwindregs, /* locations unwound in stack trace */
1387 {0x02, 0x8F, 0xFF, 0xFF}, /* break point */ /* BUG */
1390 powerfoll, /* following addresses */
1391 powerexcep, /* print exception */
1392 powerunwind, /* stack unwind */
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 */
1401 powerdas, /* dissembler */
1402 powerdas, /* plan9-format disassembler */
1403 0, /* commercial disassembler */
1404 powerhexinst, /* print instruction */
1405 powerinstlen, /* instruction size calculation */