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