plan9port

fork of plan9port with libvec, libstr and libsdb
Log | Files | Refs | README | LICENSE

machpower.c (31762B)


      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*
     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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    396 gencc(Opcode *o, Instr *i)
    397 {
    398 	format(o->mnemonic, i, o->ken);
    399 }
    400 
    401 static void
    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
    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
    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
    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
    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
    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
    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
    475 load(Opcode *o, Instr *i)
    476 {
    477 	lw(o, i, 'R');
    478 }
    479 
    480 static void
    481 fload(Opcode *o, Instr *i)
    482 {
    483 	lw(o, i, 'F');
    484 }
    485 
    486 static void
    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
    520 store(Opcode *o, Instr *i)
    521 {
    522 	sw(o, i, 'R');
    523 }
    524 
    525 static void
    526 fstore(Opcode *o, Instr *i)
    527 {
    528 	sw(o, i, 'F');
    529 }
    530 
    531 static void
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
   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
   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
   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
   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
   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
   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 };