174a4d8c2SCharles.Forsyth #include <lib9.h>
274a4d8c2SCharles.Forsyth #include <bio.h>
374a4d8c2SCharles.Forsyth #include "mach.h"
474a4d8c2SCharles.Forsyth
574a4d8c2SCharles.Forsyth /*
6d67b7dadSforsyth * PowerPC-specific debugger interface,
7d67b7dadSforsyth * including 64-bit modes
874a4d8c2SCharles.Forsyth * forsyth@terzarima.net
974a4d8c2SCharles.Forsyth */
1074a4d8c2SCharles.Forsyth
1174a4d8c2SCharles.Forsyth static char *powerexcep(Map*, Rgetter);
12d67b7dadSforsyth static int powerfoll(Map*, uvlong, Rgetter, uvlong*);
13d67b7dadSforsyth static int powerinst(Map*, uvlong, char, char*, int);
14d67b7dadSforsyth static int powerinstlen(Map*, uvlong);
15d67b7dadSforsyth static int powerdas(Map*, uvlong, char*, int);
1674a4d8c2SCharles.Forsyth
1774a4d8c2SCharles.Forsyth /*
1874a4d8c2SCharles.Forsyth * Machine description
1974a4d8c2SCharles.Forsyth */
2074a4d8c2SCharles.Forsyth Machdata powermach =
2174a4d8c2SCharles.Forsyth {
2274a4d8c2SCharles.Forsyth {0x07f, 0xe0, 0x00, 0x08}, /* breakpoint (tw 31,r0,r0) */
2374a4d8c2SCharles.Forsyth 4, /* break point size */
2474a4d8c2SCharles.Forsyth
25d67b7dadSforsyth beswab, /* short to local byte order */
26d67b7dadSforsyth beswal, /* long to local byte order */
2774a4d8c2SCharles.Forsyth beswav, /* vlong to local byte order */
2874a4d8c2SCharles.Forsyth risctrace, /* print C traceback */
2974a4d8c2SCharles.Forsyth riscframe, /* frame finder */
3074a4d8c2SCharles.Forsyth powerexcep, /* print exception */
3174a4d8c2SCharles.Forsyth 0, /* breakpoint fixup */
3274a4d8c2SCharles.Forsyth beieeesftos, /* single precision float printer */
3374a4d8c2SCharles.Forsyth beieeedftos, /* double precisioin float printer */
3474a4d8c2SCharles.Forsyth powerfoll, /* following addresses */
3574a4d8c2SCharles.Forsyth powerinst, /* print instruction */
3674a4d8c2SCharles.Forsyth powerdas, /* dissembler */
3774a4d8c2SCharles.Forsyth powerinstlen, /* instruction size */
3874a4d8c2SCharles.Forsyth };
3974a4d8c2SCharles.Forsyth
4074a4d8c2SCharles.Forsyth static char *excname[] =
4174a4d8c2SCharles.Forsyth {
4274a4d8c2SCharles.Forsyth "reserved 0",
4374a4d8c2SCharles.Forsyth "system reset",
4474a4d8c2SCharles.Forsyth "machine check",
4574a4d8c2SCharles.Forsyth "data access",
4674a4d8c2SCharles.Forsyth "instruction access",
4774a4d8c2SCharles.Forsyth "external interrupt",
4874a4d8c2SCharles.Forsyth "alignment",
4974a4d8c2SCharles.Forsyth "program exception",
5074a4d8c2SCharles.Forsyth "floating-point unavailable",
5174a4d8c2SCharles.Forsyth "decrementer",
5274a4d8c2SCharles.Forsyth "i/o controller interface error",
5374a4d8c2SCharles.Forsyth "reserved B",
5474a4d8c2SCharles.Forsyth "system call",
5574a4d8c2SCharles.Forsyth "trace trap",
5674a4d8c2SCharles.Forsyth "floating point assist",
5774a4d8c2SCharles.Forsyth "reserved",
5874a4d8c2SCharles.Forsyth "ITLB miss",
5974a4d8c2SCharles.Forsyth "DTLB load miss",
6074a4d8c2SCharles.Forsyth "DTLB store miss",
6174a4d8c2SCharles.Forsyth "instruction address breakpoint"
6274a4d8c2SCharles.Forsyth "SMI interrupt"
6374a4d8c2SCharles.Forsyth "reserved 15",
6474a4d8c2SCharles.Forsyth "reserved 16",
6574a4d8c2SCharles.Forsyth "reserved 17",
6674a4d8c2SCharles.Forsyth "reserved 18",
6774a4d8c2SCharles.Forsyth "reserved 19",
6874a4d8c2SCharles.Forsyth "reserved 1A",
6974a4d8c2SCharles.Forsyth /* the following are made up on a program exception */
70d67b7dadSforsyth "floating point exception", /* FPEXC */
71d67b7dadSforsyth "illegal instruction",
72d67b7dadSforsyth "privileged instruction",
73d67b7dadSforsyth "trap",
74d67b7dadSforsyth "illegal operation",
7574a4d8c2SCharles.Forsyth "breakpoint", /* 20 */
7674a4d8c2SCharles.Forsyth };
7774a4d8c2SCharles.Forsyth
7874a4d8c2SCharles.Forsyth static char*
powerexcep(Map * map,Rgetter rget)7974a4d8c2SCharles.Forsyth powerexcep(Map *map, Rgetter rget)
8074a4d8c2SCharles.Forsyth {
8174a4d8c2SCharles.Forsyth long c;
8274a4d8c2SCharles.Forsyth static char buf[32];
8374a4d8c2SCharles.Forsyth
8474a4d8c2SCharles.Forsyth c = (*rget)(map, "CAUSE") >> 8;
8574a4d8c2SCharles.Forsyth if(c < nelem(excname))
8674a4d8c2SCharles.Forsyth return excname[c];
8774a4d8c2SCharles.Forsyth sprint(buf, "unknown trap #%lx", c);
8874a4d8c2SCharles.Forsyth return buf;
8974a4d8c2SCharles.Forsyth }
9074a4d8c2SCharles.Forsyth
9174a4d8c2SCharles.Forsyth /*
9274a4d8c2SCharles.Forsyth * disassemble PowerPC opcodes
9374a4d8c2SCharles.Forsyth */
9474a4d8c2SCharles.Forsyth
9574a4d8c2SCharles.Forsyth #define REGSP 1 /* should come from q.out.h, but there's a clash */
9674a4d8c2SCharles.Forsyth #define REGSB 2
9774a4d8c2SCharles.Forsyth
9874a4d8c2SCharles.Forsyth static char FRAMENAME[] = ".frame";
9974a4d8c2SCharles.Forsyth
10074a4d8c2SCharles.Forsyth static Map *mymap;
10174a4d8c2SCharles.Forsyth
10274a4d8c2SCharles.Forsyth /*
10374a4d8c2SCharles.Forsyth * ibm conventions for these: bit 0 is top bit
10474a4d8c2SCharles.Forsyth * from table 10-1
10574a4d8c2SCharles.Forsyth */
10674a4d8c2SCharles.Forsyth typedef struct {
10774a4d8c2SCharles.Forsyth uchar aa; /* bit 30 */
10874a4d8c2SCharles.Forsyth uchar crba; /* bits 11-15 */
10974a4d8c2SCharles.Forsyth uchar crbb; /* bits 16-20 */
11074a4d8c2SCharles.Forsyth long bd; /* bits 16-29 */
11174a4d8c2SCharles.Forsyth uchar crfd; /* bits 6-8 */
11274a4d8c2SCharles.Forsyth uchar crfs; /* bits 11-13 */
11374a4d8c2SCharles.Forsyth uchar bi; /* bits 11-15 */
11474a4d8c2SCharles.Forsyth uchar bo; /* bits 6-10 */
11574a4d8c2SCharles.Forsyth uchar crbd; /* bits 6-10 */
11674a4d8c2SCharles.Forsyth /* union { */
11774a4d8c2SCharles.Forsyth short d; /* bits 16-31 */
11874a4d8c2SCharles.Forsyth short simm;
11974a4d8c2SCharles.Forsyth ushort uimm;
12074a4d8c2SCharles.Forsyth /*}; */
12174a4d8c2SCharles.Forsyth uchar fm; /* bits 7-14 */
12274a4d8c2SCharles.Forsyth uchar fra; /* bits 11-15 */
12374a4d8c2SCharles.Forsyth uchar frb; /* bits 16-20 */
12474a4d8c2SCharles.Forsyth uchar frc; /* bits 21-25 */
12574a4d8c2SCharles.Forsyth uchar frs; /* bits 6-10 */
12674a4d8c2SCharles.Forsyth uchar frd; /* bits 6-10 */
12774a4d8c2SCharles.Forsyth uchar crm; /* bits 12-19 */
12874a4d8c2SCharles.Forsyth long li; /* bits 6-29 || b'00' */
12974a4d8c2SCharles.Forsyth uchar lk; /* bit 31 */
13074a4d8c2SCharles.Forsyth uchar mb; /* bits 21-25 */
13174a4d8c2SCharles.Forsyth uchar me; /* bits 26-30 */
132d67b7dadSforsyth uchar xmbe; /* bits 26,21-25: mb[5] || mb[0:4], also xme */
133d67b7dadSforsyth uchar xsh; /* bits 30,16-20: sh[5] || sh[0:4] */
13474a4d8c2SCharles.Forsyth uchar nb; /* bits 16-20 */
13574a4d8c2SCharles.Forsyth uchar op; /* bits 0-5 */
13674a4d8c2SCharles.Forsyth uchar oe; /* bit 21 */
13774a4d8c2SCharles.Forsyth uchar ra; /* bits 11-15 */
13874a4d8c2SCharles.Forsyth uchar rb; /* bits 16-20 */
13974a4d8c2SCharles.Forsyth uchar rc; /* bit 31 */
14074a4d8c2SCharles.Forsyth /* union { */
14174a4d8c2SCharles.Forsyth uchar rs; /* bits 6-10 */
14274a4d8c2SCharles.Forsyth uchar rd;
14374a4d8c2SCharles.Forsyth /*};*/
14474a4d8c2SCharles.Forsyth uchar sh; /* bits 16-20 */
14574a4d8c2SCharles.Forsyth ushort spr; /* bits 11-20 */
14674a4d8c2SCharles.Forsyth uchar to; /* bits 6-10 */
14774a4d8c2SCharles.Forsyth uchar imm; /* bits 16-19 */
14874a4d8c2SCharles.Forsyth ushort xo; /* bits 21-30, 22-30, 26-30, or 30 (beware) */
149d67b7dadSforsyth uvlong imm64;
15074a4d8c2SCharles.Forsyth long w0;
15174a4d8c2SCharles.Forsyth long w1;
152d67b7dadSforsyth uvlong addr; /* pc of instruction */
15374a4d8c2SCharles.Forsyth short target;
154d67b7dadSforsyth short m64; /* 64-bit mode */
15574a4d8c2SCharles.Forsyth char *curr; /* current fill level in output buffer */
15674a4d8c2SCharles.Forsyth char *end; /* end of buffer */
15774a4d8c2SCharles.Forsyth int size; /* number of longs in instr */
15874a4d8c2SCharles.Forsyth char *err; /* errmsg */
15974a4d8c2SCharles.Forsyth } Instr;
16074a4d8c2SCharles.Forsyth
16174a4d8c2SCharles.Forsyth #define IBF(v,a,b) (((ulong)(v)>>(32-(b)-1)) & ~(~0L<<(((b)-(a)+1))))
16274a4d8c2SCharles.Forsyth #define IB(v,b) IBF((v),(b),(b))
16374a4d8c2SCharles.Forsyth
164d67b7dadSforsyth #pragma varargck argpos bprint 2
165d67b7dadSforsyth
16674a4d8c2SCharles.Forsyth static void
bprint(Instr * i,char * fmt,...)16774a4d8c2SCharles.Forsyth bprint(Instr *i, char *fmt, ...)
16874a4d8c2SCharles.Forsyth {
16974a4d8c2SCharles.Forsyth va_list arg;
17074a4d8c2SCharles.Forsyth
17174a4d8c2SCharles.Forsyth va_start(arg, fmt);
17274a4d8c2SCharles.Forsyth i->curr = vseprint(i->curr, i->end, fmt, arg);
17374a4d8c2SCharles.Forsyth va_end(arg);
17474a4d8c2SCharles.Forsyth }
17574a4d8c2SCharles.Forsyth
17674a4d8c2SCharles.Forsyth static int
decode(uvlong pc,Instr * i)177d67b7dadSforsyth decode(uvlong pc, Instr *i)
17874a4d8c2SCharles.Forsyth {
179d67b7dadSforsyth ulong w;
18074a4d8c2SCharles.Forsyth
18174a4d8c2SCharles.Forsyth if (get4(mymap, pc, &w) < 0) {
18274a4d8c2SCharles.Forsyth werrstr("can't read instruction: %r");
18374a4d8c2SCharles.Forsyth return -1;
18474a4d8c2SCharles.Forsyth }
185d67b7dadSforsyth i->m64 = asstype == APOWER64;
18674a4d8c2SCharles.Forsyth i->aa = IB(w, 30);
18774a4d8c2SCharles.Forsyth i->crba = IBF(w, 11, 15);
18874a4d8c2SCharles.Forsyth i->crbb = IBF(w, 16, 20);
18974a4d8c2SCharles.Forsyth i->bd = IBF(w, 16, 29)<<2;
19074a4d8c2SCharles.Forsyth if(i->bd & 0x8000)
19174a4d8c2SCharles.Forsyth i->bd |= ~0L<<16;
19274a4d8c2SCharles.Forsyth i->crfd = IBF(w, 6, 8);
19374a4d8c2SCharles.Forsyth i->crfs = IBF(w, 11, 13);
19474a4d8c2SCharles.Forsyth i->bi = IBF(w, 11, 15);
19574a4d8c2SCharles.Forsyth i->bo = IBF(w, 6, 10);
19674a4d8c2SCharles.Forsyth i->crbd = IBF(w, 6, 10);
19774a4d8c2SCharles.Forsyth i->uimm = IBF(w, 16, 31); /* also d, simm */
19874a4d8c2SCharles.Forsyth i->fm = IBF(w, 7, 14);
19974a4d8c2SCharles.Forsyth i->fra = IBF(w, 11, 15);
20074a4d8c2SCharles.Forsyth i->frb = IBF(w, 16, 20);
20174a4d8c2SCharles.Forsyth i->frc = IBF(w, 21, 25);
20274a4d8c2SCharles.Forsyth i->frs = IBF(w, 6, 10);
20374a4d8c2SCharles.Forsyth i->frd = IBF(w, 6, 10);
20474a4d8c2SCharles.Forsyth i->crm = IBF(w, 12, 19);
20574a4d8c2SCharles.Forsyth i->li = IBF(w, 6, 29)<<2;
20674a4d8c2SCharles.Forsyth if(IB(w, 6))
20774a4d8c2SCharles.Forsyth i->li |= ~0<<25;
20874a4d8c2SCharles.Forsyth i->lk = IB(w, 31);
20974a4d8c2SCharles.Forsyth i->mb = IBF(w, 21, 25);
21074a4d8c2SCharles.Forsyth i->me = IBF(w, 26, 30);
211d67b7dadSforsyth i->xmbe = (IB(w,26)<<5) | i->mb;
21274a4d8c2SCharles.Forsyth i->nb = IBF(w, 16, 20);
21374a4d8c2SCharles.Forsyth i->op = IBF(w, 0, 5);
21474a4d8c2SCharles.Forsyth i->oe = IB(w, 21);
21574a4d8c2SCharles.Forsyth i->ra = IBF(w, 11, 15);
21674a4d8c2SCharles.Forsyth i->rb = IBF(w, 16, 20);
21774a4d8c2SCharles.Forsyth i->rc = IB(w, 31);
21874a4d8c2SCharles.Forsyth i->rs = IBF(w, 6, 10); /* also rd */
21974a4d8c2SCharles.Forsyth i->sh = IBF(w, 16, 20);
220d67b7dadSforsyth i->xsh = (IB(w, 30)<<5) | i->sh;
22174a4d8c2SCharles.Forsyth i->spr = IBF(w, 11, 20);
22274a4d8c2SCharles.Forsyth i->to = IBF(w, 6, 10);
22374a4d8c2SCharles.Forsyth i->imm = IBF(w, 16, 19);
22474a4d8c2SCharles.Forsyth i->xo = IBF(w, 21, 30); /* bits 21-30, 22-30, 26-30, or 30 (beware) */
225d67b7dadSforsyth if(i->op == 58){ /* class of 64-bit loads */
226d67b7dadSforsyth i->xo = i->simm & 3;
227d67b7dadSforsyth i->simm &= ~3;
228d67b7dadSforsyth }
229d67b7dadSforsyth i->imm64 = i->simm;
23074a4d8c2SCharles.Forsyth if(i->op == 15)
231d67b7dadSforsyth i->imm64 <<= 16;
232d67b7dadSforsyth else if(i->op == 25 || i->op == 27 || i->op == 29)
233d67b7dadSforsyth i->imm64 = (uvlong)(i->uimm<<16);
23474a4d8c2SCharles.Forsyth i->w0 = w;
23574a4d8c2SCharles.Forsyth i->target = -1;
23674a4d8c2SCharles.Forsyth i->addr = pc;
23774a4d8c2SCharles.Forsyth i->size = 1;
23874a4d8c2SCharles.Forsyth return 1;
23974a4d8c2SCharles.Forsyth }
24074a4d8c2SCharles.Forsyth
24174a4d8c2SCharles.Forsyth static int
mkinstr(uvlong pc,Instr * i)242d67b7dadSforsyth mkinstr(uvlong pc, Instr *i)
24374a4d8c2SCharles.Forsyth {
24474a4d8c2SCharles.Forsyth Instr x;
24574a4d8c2SCharles.Forsyth
24674a4d8c2SCharles.Forsyth if(decode(pc, i) < 0)
24774a4d8c2SCharles.Forsyth return -1;
24874a4d8c2SCharles.Forsyth /*
24974a4d8c2SCharles.Forsyth * combine ADDIS/ORI (CAU/ORIL) into MOVW
250d67b7dadSforsyth * also ORIS/ORIL for unsigned in 64-bit mode
25174a4d8c2SCharles.Forsyth */
252d67b7dadSforsyth if ((i->op == 15 || i->op == 25) && i->ra==0) {
25374a4d8c2SCharles.Forsyth if(decode(pc+4, &x) < 0)
25474a4d8c2SCharles.Forsyth return -1;
25574a4d8c2SCharles.Forsyth if (x.op == 24 && x.rs == x.ra && x.ra == i->rd) {
256d67b7dadSforsyth i->imm64 |= (x.imm64 & 0xFFFF);
257d67b7dadSforsyth if(i->op != 15)
258d67b7dadSforsyth i->imm64 &= 0xFFFFFFFFUL;
25974a4d8c2SCharles.Forsyth i->w1 = x.w0;
26074a4d8c2SCharles.Forsyth i->target = x.rd;
26174a4d8c2SCharles.Forsyth i->size++;
26274a4d8c2SCharles.Forsyth return 1;
26374a4d8c2SCharles.Forsyth }
26474a4d8c2SCharles.Forsyth }
26574a4d8c2SCharles.Forsyth return 1;
26674a4d8c2SCharles.Forsyth }
26774a4d8c2SCharles.Forsyth
26874a4d8c2SCharles.Forsyth static int
plocal(Instr * i)26974a4d8c2SCharles.Forsyth plocal(Instr *i)
27074a4d8c2SCharles.Forsyth {
271d67b7dadSforsyth long offset;
27274a4d8c2SCharles.Forsyth Symbol s;
27374a4d8c2SCharles.Forsyth
27474a4d8c2SCharles.Forsyth if (!findsym(i->addr, CTEXT, &s) || !findlocal(&s, FRAMENAME, &s))
27574a4d8c2SCharles.Forsyth return -1;
276d67b7dadSforsyth offset = s.value - i->imm64;
27774a4d8c2SCharles.Forsyth if (offset > 0) {
27874a4d8c2SCharles.Forsyth if(getauto(&s, offset, CAUTO, &s)) {
279d67b7dadSforsyth bprint(i, "%s+%lld(SP)", s.name, s.value);
28074a4d8c2SCharles.Forsyth return 1;
28174a4d8c2SCharles.Forsyth }
28274a4d8c2SCharles.Forsyth } else {
28374a4d8c2SCharles.Forsyth if (getauto(&s, -offset-4, CPARAM, &s)) {
284d67b7dadSforsyth bprint(i, "%s+%ld(FP)", s.name, -offset);
28574a4d8c2SCharles.Forsyth return 1;
28674a4d8c2SCharles.Forsyth }
28774a4d8c2SCharles.Forsyth }
28874a4d8c2SCharles.Forsyth return -1;
28974a4d8c2SCharles.Forsyth }
29074a4d8c2SCharles.Forsyth
29174a4d8c2SCharles.Forsyth static int
pglobal(Instr * i,uvlong off,int anyoff,char * reg)292d67b7dadSforsyth pglobal(Instr *i, uvlong off, int anyoff, char *reg)
29374a4d8c2SCharles.Forsyth {
29474a4d8c2SCharles.Forsyth Symbol s, s2;
295d67b7dadSforsyth uvlong off1;
29674a4d8c2SCharles.Forsyth
29774a4d8c2SCharles.Forsyth if(findsym(off, CANY, &s) &&
298d67b7dadSforsyth s.value-off < 4096 &&
29974a4d8c2SCharles.Forsyth (s.class == CDATA || s.class == CTEXT)) {
30074a4d8c2SCharles.Forsyth if(off==s.value && s.name[0]=='$'){
30174a4d8c2SCharles.Forsyth off1 = 0;
302d67b7dadSforsyth geta(mymap, s.value, &off1);
30374a4d8c2SCharles.Forsyth if(off1 && findsym(off1, CANY, &s2) && s2.value == off1){
30474a4d8c2SCharles.Forsyth bprint(i, "$%s%s", s2.name, reg);
30574a4d8c2SCharles.Forsyth return 1;
30674a4d8c2SCharles.Forsyth }
30774a4d8c2SCharles.Forsyth }
30874a4d8c2SCharles.Forsyth bprint(i, "%s", s.name);
30974a4d8c2SCharles.Forsyth if (s.value != off)
310d67b7dadSforsyth bprint(i, "+%llux", off-s.value);
31174a4d8c2SCharles.Forsyth bprint(i, reg);
31274a4d8c2SCharles.Forsyth return 1;
31374a4d8c2SCharles.Forsyth }
31474a4d8c2SCharles.Forsyth if(!anyoff)
31574a4d8c2SCharles.Forsyth return 0;
316d67b7dadSforsyth bprint(i, "%llux%s", off, reg);
31774a4d8c2SCharles.Forsyth return 1;
31874a4d8c2SCharles.Forsyth }
31974a4d8c2SCharles.Forsyth
32074a4d8c2SCharles.Forsyth static void
address(Instr * i)32174a4d8c2SCharles.Forsyth address(Instr *i)
32274a4d8c2SCharles.Forsyth {
32374a4d8c2SCharles.Forsyth if (i->ra == REGSP && plocal(i) >= 0)
32474a4d8c2SCharles.Forsyth return;
325d67b7dadSforsyth if (i->ra == REGSB && mach->sb && pglobal(i, mach->sb+i->imm64, 0, "(SB)") >= 0)
32674a4d8c2SCharles.Forsyth return;
327d67b7dadSforsyth if(i->simm < 0)
328d67b7dadSforsyth bprint(i, "-%x(R%d)", -i->simm, i->ra);
32974a4d8c2SCharles.Forsyth else
330d67b7dadSforsyth bprint(i, "%llux(R%d)", i->imm64, i->ra);
33174a4d8c2SCharles.Forsyth }
33274a4d8c2SCharles.Forsyth
33374a4d8c2SCharles.Forsyth static char *tcrbits[] = {"LT", "GT", "EQ", "VS"};
33474a4d8c2SCharles.Forsyth static char *fcrbits[] = {"GE", "LE", "NE", "VC"};
33574a4d8c2SCharles.Forsyth
33674a4d8c2SCharles.Forsyth typedef struct Opcode Opcode;
33774a4d8c2SCharles.Forsyth
33874a4d8c2SCharles.Forsyth struct Opcode {
33974a4d8c2SCharles.Forsyth uchar op;
34074a4d8c2SCharles.Forsyth ushort xo;
34174a4d8c2SCharles.Forsyth ushort xomask;
34274a4d8c2SCharles.Forsyth char *mnemonic;
34374a4d8c2SCharles.Forsyth void (*f)(Opcode *, Instr *);
34474a4d8c2SCharles.Forsyth char *ken;
34574a4d8c2SCharles.Forsyth int flags;
34674a4d8c2SCharles.Forsyth };
34774a4d8c2SCharles.Forsyth
34874a4d8c2SCharles.Forsyth static void format(char *, Instr *, char *);
34974a4d8c2SCharles.Forsyth
35074a4d8c2SCharles.Forsyth static void
branch(Opcode * o,Instr * i)35174a4d8c2SCharles.Forsyth branch(Opcode *o, Instr *i)
35274a4d8c2SCharles.Forsyth {
35374a4d8c2SCharles.Forsyth char buf[8];
35474a4d8c2SCharles.Forsyth int bo, bi;
35574a4d8c2SCharles.Forsyth
35674a4d8c2SCharles.Forsyth bo = i->bo & ~1; /* ignore prediction bit */
35774a4d8c2SCharles.Forsyth if(bo==4 || bo==12 || bo==20) { /* simple forms */
35874a4d8c2SCharles.Forsyth if(bo != 20) {
35974a4d8c2SCharles.Forsyth bi = i->bi&3;
36074a4d8c2SCharles.Forsyth sprint(buf, "B%s%%L", bo==12? tcrbits[bi]: fcrbits[bi]);
361d67b7dadSforsyth format(buf, i, nil);
36274a4d8c2SCharles.Forsyth bprint(i, "\t");
36374a4d8c2SCharles.Forsyth if(i->bi > 4)
36474a4d8c2SCharles.Forsyth bprint(i, "CR(%d),", i->bi/4);
36574a4d8c2SCharles.Forsyth } else
366d67b7dadSforsyth format("BR%L\t", i, nil);
36774a4d8c2SCharles.Forsyth if(i->op == 16)
36874a4d8c2SCharles.Forsyth format(0, i, "%J");
36974a4d8c2SCharles.Forsyth else if(i->op == 19 && i->xo == 528)
37074a4d8c2SCharles.Forsyth format(0, i, "(CTR)");
37174a4d8c2SCharles.Forsyth else if(i->op == 19 && i->xo == 16)
37274a4d8c2SCharles.Forsyth format(0, i, "(LR)");
37374a4d8c2SCharles.Forsyth } else
37474a4d8c2SCharles.Forsyth format(o->mnemonic, i, o->ken);
37574a4d8c2SCharles.Forsyth }
37674a4d8c2SCharles.Forsyth
37774a4d8c2SCharles.Forsyth static void
addi(Opcode * o,Instr * i)37874a4d8c2SCharles.Forsyth addi(Opcode *o, Instr *i)
37974a4d8c2SCharles.Forsyth {
38074a4d8c2SCharles.Forsyth if (i->op==14 && i->ra == 0)
38174a4d8c2SCharles.Forsyth format("MOVW", i, "%i,R%d");
382d67b7dadSforsyth else if (i->ra == REGSB) {
38374a4d8c2SCharles.Forsyth bprint(i, "MOVW\t$");
38474a4d8c2SCharles.Forsyth address(i);
38574a4d8c2SCharles.Forsyth bprint(i, ",R%d", i->rd);
38674a4d8c2SCharles.Forsyth } else if(i->op==14 && i->simm < 0) {
38774a4d8c2SCharles.Forsyth bprint(i, "SUB\t$%d,R%d", -i->simm, i->ra);
38874a4d8c2SCharles.Forsyth if(i->rd != i->ra)
38974a4d8c2SCharles.Forsyth bprint(i, ",R%d", i->rd);
39074a4d8c2SCharles.Forsyth } else if(i->ra == i->rd) {
39174a4d8c2SCharles.Forsyth format(o->mnemonic, i, "%i");
39274a4d8c2SCharles.Forsyth bprint(i, ",R%d", i->rd);
39374a4d8c2SCharles.Forsyth } else
39474a4d8c2SCharles.Forsyth format(o->mnemonic, i, o->ken);
39574a4d8c2SCharles.Forsyth }
39674a4d8c2SCharles.Forsyth
39774a4d8c2SCharles.Forsyth static void
addis(Opcode * o,Instr * i)39874a4d8c2SCharles.Forsyth addis(Opcode *o, Instr *i)
39974a4d8c2SCharles.Forsyth {
40074a4d8c2SCharles.Forsyth long v;
40174a4d8c2SCharles.Forsyth
402d67b7dadSforsyth v = i->imm64;
403d67b7dadSforsyth if (i->op==15 && i->ra == 0)
404d67b7dadSforsyth bprint(i, "MOVW\t$%lux,R%d", v, i->rd);
405d67b7dadSforsyth else if (i->op==15 && i->ra == REGSB) {
40674a4d8c2SCharles.Forsyth bprint(i, "MOVW\t$");
40774a4d8c2SCharles.Forsyth address(i);
40874a4d8c2SCharles.Forsyth bprint(i, ",R%d", i->rd);
40974a4d8c2SCharles.Forsyth } else if(i->op==15 && v < 0) {
410d67b7dadSforsyth bprint(i, "SUB\t$%ld,R%d", -v, i->ra);
41174a4d8c2SCharles.Forsyth if(i->rd != i->ra)
41274a4d8c2SCharles.Forsyth bprint(i, ",R%d", i->rd);
41374a4d8c2SCharles.Forsyth } else {
414d67b7dadSforsyth format(o->mnemonic, i, nil);
41574a4d8c2SCharles.Forsyth bprint(i, "\t$%ld,R%d", v, i->ra);
41674a4d8c2SCharles.Forsyth if(i->rd != i->ra)
41774a4d8c2SCharles.Forsyth bprint(i, ",R%d", i->rd);
41874a4d8c2SCharles.Forsyth }
41974a4d8c2SCharles.Forsyth }
42074a4d8c2SCharles.Forsyth
42174a4d8c2SCharles.Forsyth static void
andi(Opcode * o,Instr * i)42274a4d8c2SCharles.Forsyth andi(Opcode *o, Instr *i)
42374a4d8c2SCharles.Forsyth {
42474a4d8c2SCharles.Forsyth if (i->ra == i->rs)
42574a4d8c2SCharles.Forsyth format(o->mnemonic, i, "%I,R%d");
42674a4d8c2SCharles.Forsyth else
42774a4d8c2SCharles.Forsyth format(o->mnemonic, i, o->ken);
42874a4d8c2SCharles.Forsyth }
42974a4d8c2SCharles.Forsyth
43074a4d8c2SCharles.Forsyth static void
gencc(Opcode * o,Instr * i)43174a4d8c2SCharles.Forsyth gencc(Opcode *o, Instr *i)
43274a4d8c2SCharles.Forsyth {
43374a4d8c2SCharles.Forsyth format(o->mnemonic, i, o->ken);
43474a4d8c2SCharles.Forsyth }
43574a4d8c2SCharles.Forsyth
43674a4d8c2SCharles.Forsyth static void
gen(Opcode * o,Instr * i)43774a4d8c2SCharles.Forsyth gen(Opcode *o, Instr *i)
43874a4d8c2SCharles.Forsyth {
43974a4d8c2SCharles.Forsyth format(o->mnemonic, i, o->ken);
44074a4d8c2SCharles.Forsyth if (i->rc)
44174a4d8c2SCharles.Forsyth bprint(i, " [illegal Rc]");
44274a4d8c2SCharles.Forsyth }
44374a4d8c2SCharles.Forsyth
44474a4d8c2SCharles.Forsyth static void
ldx(Opcode * o,Instr * i)44574a4d8c2SCharles.Forsyth ldx(Opcode *o, Instr *i)
44674a4d8c2SCharles.Forsyth {
44774a4d8c2SCharles.Forsyth if(i->ra == 0)
44874a4d8c2SCharles.Forsyth format(o->mnemonic, i, "(R%b),R%d");
44974a4d8c2SCharles.Forsyth else
45074a4d8c2SCharles.Forsyth format(o->mnemonic, i, "(R%b+R%a),R%d");
45174a4d8c2SCharles.Forsyth if(i->rc)
45274a4d8c2SCharles.Forsyth bprint(i, " [illegal Rc]");
45374a4d8c2SCharles.Forsyth }
45474a4d8c2SCharles.Forsyth
45574a4d8c2SCharles.Forsyth static void
stx(Opcode * o,Instr * i)45674a4d8c2SCharles.Forsyth stx(Opcode *o, Instr *i)
45774a4d8c2SCharles.Forsyth {
45874a4d8c2SCharles.Forsyth if(i->ra == 0)
45974a4d8c2SCharles.Forsyth format(o->mnemonic, i, "R%d,(R%b)");
46074a4d8c2SCharles.Forsyth else
46174a4d8c2SCharles.Forsyth format(o->mnemonic, i, "R%d,(R%b+R%a)");
46274a4d8c2SCharles.Forsyth if(i->rc && i->xo != 150)
46374a4d8c2SCharles.Forsyth bprint(i, " [illegal Rc]");
46474a4d8c2SCharles.Forsyth }
46574a4d8c2SCharles.Forsyth
46674a4d8c2SCharles.Forsyth static void
fldx(Opcode * o,Instr * i)46774a4d8c2SCharles.Forsyth fldx(Opcode *o, Instr *i)
46874a4d8c2SCharles.Forsyth {
46974a4d8c2SCharles.Forsyth if(i->ra == 0)
47074a4d8c2SCharles.Forsyth format(o->mnemonic, i, "(R%b),F%d");
47174a4d8c2SCharles.Forsyth else
47274a4d8c2SCharles.Forsyth format(o->mnemonic, i, "(R%b+R%a),F%d");
47374a4d8c2SCharles.Forsyth if(i->rc)
47474a4d8c2SCharles.Forsyth bprint(i, " [illegal Rc]");
47574a4d8c2SCharles.Forsyth }
47674a4d8c2SCharles.Forsyth
47774a4d8c2SCharles.Forsyth static void
fstx(Opcode * o,Instr * i)47874a4d8c2SCharles.Forsyth fstx(Opcode *o, Instr *i)
47974a4d8c2SCharles.Forsyth {
48074a4d8c2SCharles.Forsyth if(i->ra == 0)
48174a4d8c2SCharles.Forsyth format(o->mnemonic, i, "F%d,(R%b)");
48274a4d8c2SCharles.Forsyth else
48374a4d8c2SCharles.Forsyth format(o->mnemonic, i, "F%d,(R%b+R%a)");
48474a4d8c2SCharles.Forsyth if(i->rc)
48574a4d8c2SCharles.Forsyth bprint(i, " [illegal Rc]");
48674a4d8c2SCharles.Forsyth }
48774a4d8c2SCharles.Forsyth
48874a4d8c2SCharles.Forsyth static void
dcb(Opcode * o,Instr * i)48974a4d8c2SCharles.Forsyth dcb(Opcode *o, Instr *i)
49074a4d8c2SCharles.Forsyth {
49174a4d8c2SCharles.Forsyth if(i->ra == 0)
49274a4d8c2SCharles.Forsyth format(o->mnemonic, i, "(R%b)");
49374a4d8c2SCharles.Forsyth else
49474a4d8c2SCharles.Forsyth format(o->mnemonic, i, "(R%b+R%a)");
49574a4d8c2SCharles.Forsyth if(i->rd)
49674a4d8c2SCharles.Forsyth bprint(i, " [illegal Rd]");
49774a4d8c2SCharles.Forsyth if(i->rc)
49874a4d8c2SCharles.Forsyth bprint(i, " [illegal Rc]");
49974a4d8c2SCharles.Forsyth }
50074a4d8c2SCharles.Forsyth
50174a4d8c2SCharles.Forsyth static void
lw(Opcode * o,Instr * i,char r)50274a4d8c2SCharles.Forsyth lw(Opcode *o, Instr *i, char r)
50374a4d8c2SCharles.Forsyth {
504d67b7dadSforsyth format(o->mnemonic, i, nil);
505d67b7dadSforsyth bprint(i, "\t");
50674a4d8c2SCharles.Forsyth address(i);
50774a4d8c2SCharles.Forsyth bprint(i, ",%c%d", r, i->rd);
50874a4d8c2SCharles.Forsyth }
50974a4d8c2SCharles.Forsyth
51074a4d8c2SCharles.Forsyth static void
load(Opcode * o,Instr * i)51174a4d8c2SCharles.Forsyth load(Opcode *o, Instr *i)
51274a4d8c2SCharles.Forsyth {
51374a4d8c2SCharles.Forsyth lw(o, i, 'R');
51474a4d8c2SCharles.Forsyth }
51574a4d8c2SCharles.Forsyth
51674a4d8c2SCharles.Forsyth static void
fload(Opcode * o,Instr * i)51774a4d8c2SCharles.Forsyth fload(Opcode *o, Instr *i)
51874a4d8c2SCharles.Forsyth {
51974a4d8c2SCharles.Forsyth lw(o, i, 'F');
52074a4d8c2SCharles.Forsyth }
52174a4d8c2SCharles.Forsyth
52274a4d8c2SCharles.Forsyth static void
sw(Opcode * o,Instr * i,char r)52374a4d8c2SCharles.Forsyth sw(Opcode *o, Instr *i, char r)
52474a4d8c2SCharles.Forsyth {
52574a4d8c2SCharles.Forsyth int offset;
52674a4d8c2SCharles.Forsyth Symbol s;
52774a4d8c2SCharles.Forsyth
528d67b7dadSforsyth if (i->rs == REGSP) {
52974a4d8c2SCharles.Forsyth if (findsym(i->addr, CTEXT, &s) && findlocal(&s, FRAMENAME, &s)) {
530d67b7dadSforsyth offset = s.value-i->imm64;
53174a4d8c2SCharles.Forsyth if (offset > 0 && getauto(&s, offset, CAUTO, &s)) {
532d67b7dadSforsyth format(o->mnemonic, i, nil);
533d67b7dadSforsyth bprint(i, "\t%c%d,%s-%d(SP)", r, i->rd, s.name, offset);
53474a4d8c2SCharles.Forsyth return;
53574a4d8c2SCharles.Forsyth }
53674a4d8c2SCharles.Forsyth }
53774a4d8c2SCharles.Forsyth }
538d67b7dadSforsyth if (i->rs == REGSB && mach->sb) {
539d67b7dadSforsyth format(o->mnemonic, i, nil);
540d67b7dadSforsyth bprint(i, "\t%c%d,", r, i->rd);
54174a4d8c2SCharles.Forsyth address(i);
54274a4d8c2SCharles.Forsyth return;
54374a4d8c2SCharles.Forsyth }
54474a4d8c2SCharles.Forsyth if (r == 'F')
545d67b7dadSforsyth format(o->mnemonic, i, "F%d,%l");
54674a4d8c2SCharles.Forsyth else
547d67b7dadSforsyth format(o->mnemonic, i, o->ken);
54874a4d8c2SCharles.Forsyth }
54974a4d8c2SCharles.Forsyth
55074a4d8c2SCharles.Forsyth static void
store(Opcode * o,Instr * i)55174a4d8c2SCharles.Forsyth store(Opcode *o, Instr *i)
55274a4d8c2SCharles.Forsyth {
55374a4d8c2SCharles.Forsyth sw(o, i, 'R');
55474a4d8c2SCharles.Forsyth }
55574a4d8c2SCharles.Forsyth
55674a4d8c2SCharles.Forsyth static void
fstore(Opcode * o,Instr * i)55774a4d8c2SCharles.Forsyth fstore(Opcode *o, Instr *i)
55874a4d8c2SCharles.Forsyth {
55974a4d8c2SCharles.Forsyth sw(o, i, 'F');
56074a4d8c2SCharles.Forsyth }
56174a4d8c2SCharles.Forsyth
56274a4d8c2SCharles.Forsyth static void
shifti(Opcode * o,Instr * i)56374a4d8c2SCharles.Forsyth shifti(Opcode *o, Instr *i)
56474a4d8c2SCharles.Forsyth {
56574a4d8c2SCharles.Forsyth if (i->ra == i->rs)
56674a4d8c2SCharles.Forsyth format(o->mnemonic, i, "$%k,R%a");
56774a4d8c2SCharles.Forsyth else
56874a4d8c2SCharles.Forsyth format(o->mnemonic, i, o->ken);
56974a4d8c2SCharles.Forsyth }
57074a4d8c2SCharles.Forsyth
57174a4d8c2SCharles.Forsyth static void
shift(Opcode * o,Instr * i)57274a4d8c2SCharles.Forsyth shift(Opcode *o, Instr *i)
57374a4d8c2SCharles.Forsyth {
57474a4d8c2SCharles.Forsyth if (i->ra == i->rs)
57574a4d8c2SCharles.Forsyth format(o->mnemonic, i, "R%b,R%a");
57674a4d8c2SCharles.Forsyth else
57774a4d8c2SCharles.Forsyth format(o->mnemonic, i, o->ken);
57874a4d8c2SCharles.Forsyth }
57974a4d8c2SCharles.Forsyth
58074a4d8c2SCharles.Forsyth static void
add(Opcode * o,Instr * i)58174a4d8c2SCharles.Forsyth add(Opcode *o, Instr *i)
58274a4d8c2SCharles.Forsyth {
58374a4d8c2SCharles.Forsyth if (i->rd == i->ra)
58474a4d8c2SCharles.Forsyth format(o->mnemonic, i, "R%b,R%d");
58574a4d8c2SCharles.Forsyth else if (i->rd == i->rb)
58674a4d8c2SCharles.Forsyth format(o->mnemonic, i, "R%a,R%d");
58774a4d8c2SCharles.Forsyth else
58874a4d8c2SCharles.Forsyth format(o->mnemonic, i, o->ken);
58974a4d8c2SCharles.Forsyth }
59074a4d8c2SCharles.Forsyth
59174a4d8c2SCharles.Forsyth static void
sub(Opcode * o,Instr * i)59274a4d8c2SCharles.Forsyth sub(Opcode *o, Instr *i)
59374a4d8c2SCharles.Forsyth {
594d67b7dadSforsyth format(o->mnemonic, i, nil);
595d67b7dadSforsyth bprint(i, "\t");
59674a4d8c2SCharles.Forsyth if(i->op == 31) {
59774a4d8c2SCharles.Forsyth bprint(i, "\tR%d,R%d", i->ra, i->rb); /* subtract Ra from Rb */
59874a4d8c2SCharles.Forsyth if(i->rd != i->rb)
59974a4d8c2SCharles.Forsyth bprint(i, ",R%d", i->rd);
60074a4d8c2SCharles.Forsyth } else
60174a4d8c2SCharles.Forsyth bprint(i, "\tR%d,$%d,R%d", i->ra, i->simm, i->rd);
60274a4d8c2SCharles.Forsyth }
60374a4d8c2SCharles.Forsyth
60474a4d8c2SCharles.Forsyth static void
qmuldiv(Opcode * o,Instr * i)605b6b4a404Sforsyth qmuldiv(Opcode *o, Instr *i)
60674a4d8c2SCharles.Forsyth {
607d67b7dadSforsyth format(o->mnemonic, i, nil);
60874a4d8c2SCharles.Forsyth if(i->op == 31)
60974a4d8c2SCharles.Forsyth bprint(i, "\tR%d,R%d", i->rb, i->ra);
61074a4d8c2SCharles.Forsyth else
61174a4d8c2SCharles.Forsyth bprint(i, "\t$%d,R%d", i->simm, i->ra);
61274a4d8c2SCharles.Forsyth if(i->ra != i->rd)
61374a4d8c2SCharles.Forsyth bprint(i, ",R%d", i->rd);
61474a4d8c2SCharles.Forsyth }
61574a4d8c2SCharles.Forsyth
61674a4d8c2SCharles.Forsyth static void
and(Opcode * o,Instr * i)61774a4d8c2SCharles.Forsyth and(Opcode *o, Instr *i)
61874a4d8c2SCharles.Forsyth {
61974a4d8c2SCharles.Forsyth if (i->op == 31) {
62074a4d8c2SCharles.Forsyth /* Rb,Rs,Ra */
62174a4d8c2SCharles.Forsyth if (i->ra == i->rs)
62274a4d8c2SCharles.Forsyth format(o->mnemonic, i, "R%b,R%a");
62374a4d8c2SCharles.Forsyth else if (i->ra == i->rb)
62474a4d8c2SCharles.Forsyth format(o->mnemonic, i, "R%s,R%a");
62574a4d8c2SCharles.Forsyth else
62674a4d8c2SCharles.Forsyth format(o->mnemonic, i, o->ken);
62774a4d8c2SCharles.Forsyth } else {
62874a4d8c2SCharles.Forsyth /* imm,Rs,Ra */
62974a4d8c2SCharles.Forsyth if (i->ra == i->rs)
63074a4d8c2SCharles.Forsyth format(o->mnemonic, i, "%I,R%a");
63174a4d8c2SCharles.Forsyth else
63274a4d8c2SCharles.Forsyth format(o->mnemonic, i, o->ken);
63374a4d8c2SCharles.Forsyth }
63474a4d8c2SCharles.Forsyth }
63574a4d8c2SCharles.Forsyth
63674a4d8c2SCharles.Forsyth static void
or(Opcode * o,Instr * i)63774a4d8c2SCharles.Forsyth or(Opcode *o, Instr *i)
63874a4d8c2SCharles.Forsyth {
63974a4d8c2SCharles.Forsyth if (i->op == 31) {
64074a4d8c2SCharles.Forsyth /* Rb,Rs,Ra */
64174a4d8c2SCharles.Forsyth if (i->rs == 0 && i->ra == 0 && i->rb == 0)
642d67b7dadSforsyth format("NOP", i, nil);
64374a4d8c2SCharles.Forsyth else if (i->rs == i->rb)
64474a4d8c2SCharles.Forsyth format("MOVW", i, "R%b,R%a");
64574a4d8c2SCharles.Forsyth else
64674a4d8c2SCharles.Forsyth and(o, i);
64774a4d8c2SCharles.Forsyth } else
64874a4d8c2SCharles.Forsyth and(o, i);
64974a4d8c2SCharles.Forsyth }
65074a4d8c2SCharles.Forsyth
65174a4d8c2SCharles.Forsyth static void
shifted(Opcode * o,Instr * i)65274a4d8c2SCharles.Forsyth shifted(Opcode *o, Instr *i)
65374a4d8c2SCharles.Forsyth {
654d67b7dadSforsyth format(o->mnemonic, i, nil);
65574a4d8c2SCharles.Forsyth bprint(i, "\t$%lux,", (ulong)i->uimm<<16);
65674a4d8c2SCharles.Forsyth if (i->rs == i->ra)
65774a4d8c2SCharles.Forsyth bprint(i, "R%d", i->ra);
65874a4d8c2SCharles.Forsyth else
65974a4d8c2SCharles.Forsyth bprint(i, "R%d,R%d", i->rs, i->ra);
66074a4d8c2SCharles.Forsyth }
66174a4d8c2SCharles.Forsyth
66274a4d8c2SCharles.Forsyth static void
neg(Opcode * o,Instr * i)66374a4d8c2SCharles.Forsyth neg(Opcode *o, Instr *i)
66474a4d8c2SCharles.Forsyth {
66574a4d8c2SCharles.Forsyth if (i->rd == i->ra)
66674a4d8c2SCharles.Forsyth format(o->mnemonic, i, "R%d");
66774a4d8c2SCharles.Forsyth else
66874a4d8c2SCharles.Forsyth format(o->mnemonic, i, o->ken);
66974a4d8c2SCharles.Forsyth }
67074a4d8c2SCharles.Forsyth
67174a4d8c2SCharles.Forsyth static char ir2[] = "R%a,R%d"; /* reverse of IBM order */
67274a4d8c2SCharles.Forsyth static char ir3[] = "R%b,R%a,R%d";
67374a4d8c2SCharles.Forsyth static char ir3r[] = "R%a,R%b,R%d";
67474a4d8c2SCharles.Forsyth static char il3[] = "R%b,R%s,R%a";
675*45a20ab7Sforsyth static char il2u[] = "%I,R%d,R%a";
67674a4d8c2SCharles.Forsyth static char il3s[] = "$%k,R%s,R%a";
67774a4d8c2SCharles.Forsyth static char il2[] = "R%s,R%a";
67874a4d8c2SCharles.Forsyth static char icmp3[] = "R%a,R%b,%D";
67974a4d8c2SCharles.Forsyth static char cr3op[] = "%b,%a,%d";
68074a4d8c2SCharles.Forsyth static char ir2i[] = "%i,R%a,R%d";
68174a4d8c2SCharles.Forsyth static char fp2[] = "F%b,F%d";
68274a4d8c2SCharles.Forsyth static char fp3[] = "F%b,F%a,F%d";
68374a4d8c2SCharles.Forsyth static char fp3c[] = "F%c,F%a,F%d";
68474a4d8c2SCharles.Forsyth static char fp4[] = "F%a,F%c,F%b,F%d";
68574a4d8c2SCharles.Forsyth static char fpcmp[] = "F%a,F%b,%D";
68674a4d8c2SCharles.Forsyth static char ldop[] = "%l,R%d";
68774a4d8c2SCharles.Forsyth static char stop[] = "R%d,%l";
68874a4d8c2SCharles.Forsyth static char fldop[] = "%l,F%d";
68974a4d8c2SCharles.Forsyth static char fstop[] = "F%d,%l";
690d67b7dadSforsyth static char rldc[] = "R%b,R%s,$%E,R%a";
69174a4d8c2SCharles.Forsyth static char rlim[] = "R%b,R%s,$%z,R%a";
69274a4d8c2SCharles.Forsyth static char rlimi[] = "$%k,R%s,$%z,R%a";
693d67b7dadSforsyth static char rldi[] = "$%e,R%s,$%E,R%a";
69474a4d8c2SCharles.Forsyth
69574a4d8c2SCharles.Forsyth #define OEM IBF(~0,22,30)
69674a4d8c2SCharles.Forsyth #define FP4 IBF(~0,26,30)
697d67b7dadSforsyth #define ALL (~0)
698d67b7dadSforsyth #define RLDC 0xF
699d67b7dadSforsyth #define RLDI 0xE
70074a4d8c2SCharles.Forsyth /*
70174a4d8c2SCharles.Forsyth notes:
70274a4d8c2SCharles.Forsyth 10-26: crfD = rD>>2; rD&3 mbz
70374a4d8c2SCharles.Forsyth also, L bit (bit 10) mbz or selects 64-bit operands
70474a4d8c2SCharles.Forsyth */
70574a4d8c2SCharles.Forsyth
70674a4d8c2SCharles.Forsyth static Opcode opcodes[] = {
70774a4d8c2SCharles.Forsyth {31, 266, OEM, "ADD%V%C", add, ir3},
70874a4d8c2SCharles.Forsyth {31, 10, OEM, "ADDC%V%C", add, ir3},
70974a4d8c2SCharles.Forsyth {31, 138, OEM, "ADDE%V%C", add, ir3},
71074a4d8c2SCharles.Forsyth {14, 0, 0, "ADD", addi, ir2i},
71174a4d8c2SCharles.Forsyth {12, 0, 0, "ADDC", addi, ir2i},
71274a4d8c2SCharles.Forsyth {13, 0, 0, "ADDCCC", addi, ir2i},
71374a4d8c2SCharles.Forsyth {15, 0, 0, "ADD", addis, 0},
71474a4d8c2SCharles.Forsyth {31, 234, OEM, "ADDME%V%C", gencc, ir2},
71574a4d8c2SCharles.Forsyth {31, 202, OEM, "ADDZE%V%C", gencc, ir2},
71674a4d8c2SCharles.Forsyth
71774a4d8c2SCharles.Forsyth {31, 28, ALL, "AND%C", and, il3},
71874a4d8c2SCharles.Forsyth {31, 60, ALL, "ANDN%C", and, il3},
71974a4d8c2SCharles.Forsyth {28, 0, 0, "ANDCC", andi, il2u},
72074a4d8c2SCharles.Forsyth {29, 0, 0, "ANDCC", shifted, 0},
72174a4d8c2SCharles.Forsyth
72274a4d8c2SCharles.Forsyth {18, 0, 0, "B%L", gencc, "%j"},
72374a4d8c2SCharles.Forsyth {16, 0, 0, "BC%L", branch, "%d,%a,%J"},
72474a4d8c2SCharles.Forsyth {19, 528, ALL, "BC%L", branch, "%d,%a,(CTR)"},
72574a4d8c2SCharles.Forsyth {19, 16, ALL, "BC%L", branch, "%d,%a,(LR)"},
72674a4d8c2SCharles.Forsyth
72774a4d8c2SCharles.Forsyth {31, 0, ALL, "CMP", 0, icmp3},
72874a4d8c2SCharles.Forsyth {11, 0, 0, "CMP", 0, "R%a,%i,%D"},
72974a4d8c2SCharles.Forsyth {31, 32, ALL, "CMPU", 0, icmp3},
73074a4d8c2SCharles.Forsyth {10, 0, 0, "CMPU", 0, "R%a,%I,%D"},
73174a4d8c2SCharles.Forsyth
732d67b7dadSforsyth {31, 58, ALL, "CNTLZD%C", gencc, ir2}, /* 64 */
733d67b7dadSforsyth {31, 26, ALL, "CNTLZ%W%C", gencc, ir2},
73474a4d8c2SCharles.Forsyth
73574a4d8c2SCharles.Forsyth {19, 257, ALL, "CRAND", gen, cr3op},
73674a4d8c2SCharles.Forsyth {19, 129, ALL, "CRANDN", gen, cr3op},
73774a4d8c2SCharles.Forsyth {19, 289, ALL, "CREQV", gen, cr3op},
73874a4d8c2SCharles.Forsyth {19, 225, ALL, "CRNAND", gen, cr3op},
73974a4d8c2SCharles.Forsyth {19, 33, ALL, "CRNOR", gen, cr3op},
74074a4d8c2SCharles.Forsyth {19, 449, ALL, "CROR", gen, cr3op},
74174a4d8c2SCharles.Forsyth {19, 417, ALL, "CRORN", gen, cr3op},
74274a4d8c2SCharles.Forsyth {19, 193, ALL, "CRXOR", gen, cr3op},
74374a4d8c2SCharles.Forsyth
74474a4d8c2SCharles.Forsyth {31, 86, ALL, "DCBF", dcb, 0},
74574a4d8c2SCharles.Forsyth {31, 470, ALL, "DCBI", dcb, 0},
74674a4d8c2SCharles.Forsyth {31, 54, ALL, "DCBST", dcb, 0},
74774a4d8c2SCharles.Forsyth {31, 278, ALL, "DCBT", dcb, 0},
74874a4d8c2SCharles.Forsyth {31, 246, ALL, "DCBTST", dcb, 0},
74974a4d8c2SCharles.Forsyth {31, 1014, ALL, "DCBZ", dcb, 0},
750d67b7dadSforsyth {31, 454, ALL, "DCCCI", dcb, 0},
751d67b7dadSforsyth {31, 966, ALL, "ICCCI", dcb, 0},
75274a4d8c2SCharles.Forsyth
753b6b4a404Sforsyth {31, 489, OEM, "DIVD%V%C", qmuldiv, ir3}, /* 64 */
754b6b4a404Sforsyth {31, 457, OEM, "DIVDU%V%C", qmuldiv, ir3}, /* 64 */
755b6b4a404Sforsyth {31, 491, OEM, "DIVW%V%C", qmuldiv, ir3},
756b6b4a404Sforsyth {31, 459, OEM, "DIVWU%V%C", qmuldiv, ir3},
75774a4d8c2SCharles.Forsyth
75874a4d8c2SCharles.Forsyth {31, 310, ALL, "ECIWX", ldx, 0},
75974a4d8c2SCharles.Forsyth {31, 438, ALL, "ECOWX", stx, 0},
76074a4d8c2SCharles.Forsyth {31, 854, ALL, "EIEIO", gen, 0},
76174a4d8c2SCharles.Forsyth
76274a4d8c2SCharles.Forsyth {31, 284, ALL, "EQV%C", gencc, il3},
76374a4d8c2SCharles.Forsyth
76474a4d8c2SCharles.Forsyth {31, 954, ALL, "EXTSB%C", gencc, il2},
76574a4d8c2SCharles.Forsyth {31, 922, ALL, "EXTSH%C", gencc, il2},
766d67b7dadSforsyth {31, 986, ALL, "EXTSW%C", gencc, il2}, /* 64 */
76774a4d8c2SCharles.Forsyth
76874a4d8c2SCharles.Forsyth {63, 264, ALL, "FABS%C", gencc, fp2},
76974a4d8c2SCharles.Forsyth {63, 21, ALL, "FADD%C", gencc, fp3},
77074a4d8c2SCharles.Forsyth {59, 21, ALL, "FADDS%C", gencc, fp3},
77174a4d8c2SCharles.Forsyth {63, 32, ALL, "FCMPO", gen, fpcmp},
77274a4d8c2SCharles.Forsyth {63, 0, ALL, "FCMPU", gen, fpcmp},
773d67b7dadSforsyth {63, 846, ALL, "FCFID%C", gencc, fp2}, /* 64 */
774d67b7dadSforsyth {63, 814, ALL, "FCTID%C", gencc, fp2}, /* 64 */
775d67b7dadSforsyth {63, 815, ALL, "FCTIDZ%C", gencc, fp2}, /* 64 */
77674a4d8c2SCharles.Forsyth {63, 14, ALL, "FCTIW%C", gencc, fp2},
77774a4d8c2SCharles.Forsyth {63, 15, ALL, "FCTIWZ%C", gencc, fp2},
77874a4d8c2SCharles.Forsyth {63, 18, ALL, "FDIV%C", gencc, fp3},
77974a4d8c2SCharles.Forsyth {59, 18, ALL, "FDIVS%C", gencc, fp3},
78074a4d8c2SCharles.Forsyth {63, 29, FP4, "FMADD%C", gencc, fp4},
78174a4d8c2SCharles.Forsyth {59, 29, FP4, "FMADDS%C", gencc, fp4},
78274a4d8c2SCharles.Forsyth {63, 72, ALL, "FMOVD%C", gencc, fp2},
78374a4d8c2SCharles.Forsyth {63, 28, FP4, "FMSUB%C", gencc, fp4},
78474a4d8c2SCharles.Forsyth {59, 28, FP4, "FMSUBS%C", gencc, fp4},
78574a4d8c2SCharles.Forsyth {63, 25, FP4, "FMUL%C", gencc, fp3c},
78674a4d8c2SCharles.Forsyth {59, 25, FP4, "FMULS%C", gencc, fp3c},
78774a4d8c2SCharles.Forsyth {63, 136, ALL, "FNABS%C", gencc, fp2},
78874a4d8c2SCharles.Forsyth {63, 40, ALL, "FNEG%C", gencc, fp2},
78974a4d8c2SCharles.Forsyth {63, 31, FP4, "FNMADD%C", gencc, fp4},
79074a4d8c2SCharles.Forsyth {59, 31, FP4, "FNMADDS%C", gencc, fp4},
79174a4d8c2SCharles.Forsyth {63, 30, FP4, "FNMSUB%C", gencc, fp4},
79274a4d8c2SCharles.Forsyth {59, 30, FP4, "FNMSUBS%C", gencc, fp4},
793d67b7dadSforsyth {59, 24, ALL, "FRES%C", gencc, fp2}, /* optional */
79474a4d8c2SCharles.Forsyth {63, 12, ALL, "FRSP%C", gencc, fp2},
795d67b7dadSforsyth {63, 26, ALL, "FRSQRTE%C", gencc, fp2}, /* optional */
796d67b7dadSforsyth {63, 23, FP4, "FSEL%CC", gencc, fp4}, /* optional */
797d67b7dadSforsyth {63, 22, ALL, "FSQRT%C", gencc, fp2}, /* optional */
798d67b7dadSforsyth {59, 22, ALL, "FSQRTS%C", gencc, fp2}, /* optional */
79974a4d8c2SCharles.Forsyth {63, 20, FP4, "FSUB%C", gencc, fp3},
80074a4d8c2SCharles.Forsyth {59, 20, FP4, "FSUBS%C", gencc, fp3},
80174a4d8c2SCharles.Forsyth
802d67b7dadSforsyth {31, 982, ALL, "ICBI", dcb, 0}, /* optional */
80374a4d8c2SCharles.Forsyth {19, 150, ALL, "ISYNC", gen, 0},
80474a4d8c2SCharles.Forsyth
80574a4d8c2SCharles.Forsyth {34, 0, 0, "MOVBZ", load, ldop},
80674a4d8c2SCharles.Forsyth {35, 0, 0, "MOVBZU", load, ldop},
80774a4d8c2SCharles.Forsyth {31, 119, ALL, "MOVBZU", ldx, 0},
80874a4d8c2SCharles.Forsyth {31, 87, ALL, "MOVBZ", ldx, 0},
80974a4d8c2SCharles.Forsyth {50, 0, 0, "FMOVD", fload, fldop},
81074a4d8c2SCharles.Forsyth {51, 0, 0, "FMOVDU", fload, fldop},
81174a4d8c2SCharles.Forsyth {31, 631, ALL, "FMOVDU", fldx, 0},
81274a4d8c2SCharles.Forsyth {31, 599, ALL, "FMOVD", fldx, 0},
81374a4d8c2SCharles.Forsyth {48, 0, 0, "FMOVS", load, fldop},
81474a4d8c2SCharles.Forsyth {49, 0, 0, "FMOVSU", load, fldop},
81574a4d8c2SCharles.Forsyth {31, 567, ALL, "FMOVSU", fldx, 0},
81674a4d8c2SCharles.Forsyth {31, 535, ALL, "FMOVS", fldx, 0},
81774a4d8c2SCharles.Forsyth {42, 0, 0, "MOVH", load, ldop},
81874a4d8c2SCharles.Forsyth {43, 0, 0, "MOVHU", load, ldop},
81974a4d8c2SCharles.Forsyth {31, 375, ALL, "MOVHU", ldx, 0},
82074a4d8c2SCharles.Forsyth {31, 343, ALL, "MOVH", ldx, 0},
82174a4d8c2SCharles.Forsyth {31, 790, ALL, "MOVHBR", ldx, 0},
82274a4d8c2SCharles.Forsyth {40, 0, 0, "MOVHZ", load, ldop},
82374a4d8c2SCharles.Forsyth {41, 0, 0, "MOVHZU", load, ldop},
82474a4d8c2SCharles.Forsyth {31, 311, ALL, "MOVHZU", ldx, 0},
82574a4d8c2SCharles.Forsyth {31, 279, ALL, "MOVHZ", ldx, 0},
82674a4d8c2SCharles.Forsyth {46, 0, 0, "MOVMW", load, ldop},
82774a4d8c2SCharles.Forsyth {31, 597, ALL, "LSW", gen, "(R%a),$%n,R%d"},
82874a4d8c2SCharles.Forsyth {31, 533, ALL, "LSW", ldx, 0},
82974a4d8c2SCharles.Forsyth {31, 20, ALL, "LWAR", ldx, 0},
830d67b7dadSforsyth {31, 84, ALL, "LWARD", ldx, 0}, /* 64 */
83174a4d8c2SCharles.Forsyth
832d67b7dadSforsyth {58, 0, ALL, "MOVD", load, ldop}, /* 64 */
833d67b7dadSforsyth {58, 1, ALL, "MOVDU", load, ldop}, /* 64 */
834d67b7dadSforsyth {31, 53, ALL, "MOVDU", ldx, 0}, /* 64 */
835d67b7dadSforsyth {31, 21, ALL, "MOVD", ldx, 0}, /* 64 */
836d67b7dadSforsyth
837d67b7dadSforsyth {31, 534, ALL, "MOVWBR", ldx, 0},
838d67b7dadSforsyth
839d67b7dadSforsyth {58, 2, ALL, "MOVW", load, ldop}, /* 64 (lwa) */
840d67b7dadSforsyth {31, 373, ALL, "MOVWU", ldx, 0}, /* 64 */
841d67b7dadSforsyth {31, 341, ALL, "MOVW", ldx, 0}, /* 64 */
842d67b7dadSforsyth
843d67b7dadSforsyth {32, 0, 0, "MOVW%Z", load, ldop},
844d67b7dadSforsyth {33, 0, 0, "MOVW%ZU", load, ldop},
845d67b7dadSforsyth {31, 55, ALL, "MOVW%ZU", ldx, 0},
846d67b7dadSforsyth {31, 23, ALL, "MOVW%Z", ldx, 0},
84774a4d8c2SCharles.Forsyth
84874a4d8c2SCharles.Forsyth {19, 0, ALL, "MOVFL", gen, "%S,%D"},
84974a4d8c2SCharles.Forsyth {63, 64, ALL, "MOVCRFS", gen, "%S,%D"},
85074a4d8c2SCharles.Forsyth {31, 512, ALL, "MOVW", gen, "XER,%D"},
85174a4d8c2SCharles.Forsyth {31, 19, ALL, "MOVW", gen, "CR,R%d"},
85274a4d8c2SCharles.Forsyth
85374a4d8c2SCharles.Forsyth {63, 583, ALL, "MOVW%C", gen, "FPSCR, F%d"}, /* mffs */
85474a4d8c2SCharles.Forsyth {31, 83, ALL, "MOVW", gen, "MSR,R%d"},
85574a4d8c2SCharles.Forsyth {31, 339, ALL, "MOVW", gen, "%P,R%d"},
85674a4d8c2SCharles.Forsyth {31, 595, ALL, "MOVW", gen, "SEG(%a),R%d"},
85774a4d8c2SCharles.Forsyth {31, 659, ALL, "MOVW", gen, "SEG(R%b),R%d"},
858d67b7dadSforsyth {31, 323, ALL, "MOVW", gen, "DCR(%Q),R%d"},
859d67b7dadSforsyth {31, 451, ALL, "MOVW", gen, "R%s,DCR(%Q)"},
860*45a20ab7Sforsyth {31, 259, ALL, "MOVW", gen, "DCR(R%a),R%d"},
861*45a20ab7Sforsyth {31, 387, ALL, "MOVW", gen, "R%s,DCR(R%a)"},
86274a4d8c2SCharles.Forsyth {31, 144, ALL, "MOVFL", gen, "R%s,%m,CR"},
86374a4d8c2SCharles.Forsyth {63, 70, ALL, "MTFSB0%C", gencc, "%D"},
86474a4d8c2SCharles.Forsyth {63, 38, ALL, "MTFSB1%C", gencc, "%D"},
86574a4d8c2SCharles.Forsyth {63, 711, ALL, "MOVFL%C", gencc, "F%b,%M,FPSCR"}, /* mtfsf */
86674a4d8c2SCharles.Forsyth {63, 134, ALL, "MOVFL%C", gencc, "%K,%D"},
86774a4d8c2SCharles.Forsyth {31, 146, ALL, "MOVW", gen, "R%s,MSR"},
868d67b7dadSforsyth {31, 178, ALL, "MOVD", gen, "R%s,MSR"},
86974a4d8c2SCharles.Forsyth {31, 467, ALL, "MOVW", gen, "R%s,%P"},
87074a4d8c2SCharles.Forsyth {31, 210, ALL, "MOVW", gen, "R%s,SEG(%a)"},
87174a4d8c2SCharles.Forsyth {31, 242, ALL, "MOVW", gen, "R%s,SEG(R%b)"},
87274a4d8c2SCharles.Forsyth
873d67b7dadSforsyth {31, 73, ALL, "MULHD%C", gencc, ir3},
874d67b7dadSforsyth {31, 9, ALL, "MULHDU%C", gencc, ir3},
875d67b7dadSforsyth {31, 233, OEM, "MULLD%V%C", gencc, ir3},
87674a4d8c2SCharles.Forsyth
877d67b7dadSforsyth {31, 75, ALL, "MULHW%C", gencc, ir3},
878d67b7dadSforsyth {31, 11, ALL, "MULHWU%C", gencc, ir3},
87974a4d8c2SCharles.Forsyth {31, 235, OEM, "MULLW%V%C", gencc, ir3},
88074a4d8c2SCharles.Forsyth
881b6b4a404Sforsyth {7, 0, 0, "MULLW", qmuldiv, "%i,R%a,R%d"},
88274a4d8c2SCharles.Forsyth
88374a4d8c2SCharles.Forsyth {31, 476, ALL, "NAND%C", gencc, il3},
88474a4d8c2SCharles.Forsyth {31, 104, OEM, "NEG%V%C", neg, ir2},
88574a4d8c2SCharles.Forsyth {31, 124, ALL, "NOR%C", gencc, il3},
88674a4d8c2SCharles.Forsyth {31, 444, ALL, "OR%C", or, il3},
88774a4d8c2SCharles.Forsyth {31, 412, ALL, "ORN%C", or, il3},
88874a4d8c2SCharles.Forsyth {24, 0, 0, "OR", and, "%I,R%d,R%a"},
88974a4d8c2SCharles.Forsyth {25, 0, 0, "OR", shifted, 0},
89074a4d8c2SCharles.Forsyth
89174a4d8c2SCharles.Forsyth {19, 50, ALL, "RFI", gen, 0},
892d67b7dadSforsyth {19, 51, ALL, "RFCI", gen, 0},
89374a4d8c2SCharles.Forsyth
894d67b7dadSforsyth {30, 8, RLDC, "RLDCL%C", gencc, rldc}, /* 64 */
895d67b7dadSforsyth {30, 9, RLDC, "RLDCR%C", gencc, rldc}, /* 64 */
896d67b7dadSforsyth {30, 0, RLDI, "RLDCL%C", gencc, rldi}, /* 64 */
897d67b7dadSforsyth {30, 1<<1, RLDI, "RLDCR%C", gencc, rldi}, /* 64 */
898d67b7dadSforsyth {30, 2<<1, RLDI, "RLDC%C", gencc, rldi}, /* 64 */
899d67b7dadSforsyth {30, 3<<1, RLDI, "RLDMI%C", gencc, rldi}, /* 64 */
900d67b7dadSforsyth
90174a4d8c2SCharles.Forsyth {20, 0, 0, "RLWMI%C", gencc, rlimi},
90274a4d8c2SCharles.Forsyth {21, 0, 0, "RLWNM%C", gencc, rlimi},
90374a4d8c2SCharles.Forsyth {23, 0, 0, "RLWNM%C", gencc, rlim},
90474a4d8c2SCharles.Forsyth
90574a4d8c2SCharles.Forsyth {17, 1, ALL, "SYSCALL", gen, 0},
90674a4d8c2SCharles.Forsyth
907d67b7dadSforsyth {31, 27, ALL, "SLD%C", shift, il3}, /* 64 */
90874a4d8c2SCharles.Forsyth {31, 24, ALL, "SLW%C", shift, il3},
90974a4d8c2SCharles.Forsyth
910d67b7dadSforsyth {31, 794, ALL, "SRAD%C", shift, il3}, /* 64 */
911d67b7dadSforsyth {31, (413<<1)|0, ALL, "SRAD%C", shifti, il3s}, /* 64 */
912d67b7dadSforsyth {31, (413<<1)|1, ALL, "SRAD%C", shifti, il3s}, /* 64 */
91374a4d8c2SCharles.Forsyth {31, 792, ALL, "SRAW%C", shift, il3},
91474a4d8c2SCharles.Forsyth {31, 824, ALL, "SRAW%C", shifti, il3s},
91574a4d8c2SCharles.Forsyth
916d67b7dadSforsyth {31, 539, ALL, "SRD%C", shift, il3}, /* 64 */
91774a4d8c2SCharles.Forsyth {31, 536, ALL, "SRW%C", shift, il3},
91874a4d8c2SCharles.Forsyth
91974a4d8c2SCharles.Forsyth {38, 0, 0, "MOVB", store, stop},
92074a4d8c2SCharles.Forsyth {39, 0, 0, "MOVBU", store, stop},
92174a4d8c2SCharles.Forsyth {31, 247, ALL, "MOVBU", stx, 0},
92274a4d8c2SCharles.Forsyth {31, 215, ALL, "MOVB", stx, 0},
92374a4d8c2SCharles.Forsyth {54, 0, 0, "FMOVD", fstore, fstop},
92474a4d8c2SCharles.Forsyth {55, 0, 0, "FMOVDU", fstore, fstop},
92574a4d8c2SCharles.Forsyth {31, 759, ALL, "FMOVDU", fstx, 0},
92674a4d8c2SCharles.Forsyth {31, 727, ALL, "FMOVD", fstx, 0},
92774a4d8c2SCharles.Forsyth {52, 0, 0, "FMOVS", fstore, fstop},
92874a4d8c2SCharles.Forsyth {53, 0, 0, "FMOVSU", fstore, fstop},
92974a4d8c2SCharles.Forsyth {31, 695, ALL, "FMOVSU", fstx, 0},
93074a4d8c2SCharles.Forsyth {31, 663, ALL, "FMOVS", fstx, 0},
93174a4d8c2SCharles.Forsyth {44, 0, 0, "MOVH", store, stop},
93274a4d8c2SCharles.Forsyth {31, 918, ALL, "MOVHBR", stx, 0},
93374a4d8c2SCharles.Forsyth {45, 0, 0, "MOVHU", store, stop},
93474a4d8c2SCharles.Forsyth {31, 439, ALL, "MOVHU", stx, 0},
93574a4d8c2SCharles.Forsyth {31, 407, ALL, "MOVH", stx, 0},
93674a4d8c2SCharles.Forsyth {47, 0, 0, "MOVMW", store, stop},
93774a4d8c2SCharles.Forsyth {31, 725, ALL, "STSW", gen, "R%d,$%n,(R%a)"},
93874a4d8c2SCharles.Forsyth {31, 661, ALL, "STSW", stx, 0},
93974a4d8c2SCharles.Forsyth {36, 0, 0, "MOVW", store, stop},
94074a4d8c2SCharles.Forsyth {31, 662, ALL, "MOVWBR", stx, 0},
94174a4d8c2SCharles.Forsyth {31, 150, ALL, "STWCCC", stx, 0},
942d67b7dadSforsyth {31, 214, ALL, "STDCCC", stx, 0}, /* 64 */
94374a4d8c2SCharles.Forsyth {37, 0, 0, "MOVWU", store, stop},
94474a4d8c2SCharles.Forsyth {31, 183, ALL, "MOVWU", stx, 0},
94574a4d8c2SCharles.Forsyth {31, 151, ALL, "MOVW", stx, 0},
94674a4d8c2SCharles.Forsyth
947d67b7dadSforsyth {62, 0, 0, "MOVD%U", store, stop}, /* 64 */
948d67b7dadSforsyth {31, 149, ALL, "MOVD", stx, 0,}, /* 64 */
949d67b7dadSforsyth {31, 181, ALL, "MOVDU", stx, 0}, /* 64 */
950d67b7dadSforsyth
951d67b7dadSforsyth {31, 498, ALL, "SLBIA", gen, 0}, /* 64 */
952d67b7dadSforsyth {31, 434, ALL, "SLBIE", gen, "R%b"}, /* 64 */
953d67b7dadSforsyth {31, 466, ALL, "SLBIEX", gen, "R%b"}, /* 64 */
954d67b7dadSforsyth {31, 915, ALL, "SLBMFEE", gen, "R%b,R%d"}, /* 64 */
955d67b7dadSforsyth {31, 851, ALL, "SLBMFEV", gen, "R%b,R%d"}, /* 64 */
956d67b7dadSforsyth {31, 402, ALL, "SLBMTE", gen, "R%s,R%b"}, /* 64 */
957d67b7dadSforsyth
95874a4d8c2SCharles.Forsyth {31, 40, OEM, "SUB%V%C", sub, ir3},
95974a4d8c2SCharles.Forsyth {31, 8, OEM, "SUBC%V%C", sub, ir3},
96074a4d8c2SCharles.Forsyth {31, 136, OEM, "SUBE%V%C", sub, ir3},
96174a4d8c2SCharles.Forsyth {8, 0, 0, "SUBC", gen, "R%a,%i,R%d"},
96274a4d8c2SCharles.Forsyth {31, 232, OEM, "SUBME%V%C", sub, ir2},
96374a4d8c2SCharles.Forsyth {31, 200, OEM, "SUBZE%V%C", sub, ir2},
96474a4d8c2SCharles.Forsyth
965d67b7dadSforsyth {31, 598, ALL, "SYNC", gen, 0}, /* TO DO: there's a parameter buried in there */
966d67b7dadSforsyth {2, 0, 0, "TD", gen, "%d,R%a,%i"}, /* 64 */
967d67b7dadSforsyth {31, 370, ALL, "TLBIA", gen, 0}, /* optional */
968d67b7dadSforsyth {31, 306, ALL, "TLBIE", gen, "R%b"}, /* optional */
969d67b7dadSforsyth {31, 274, ALL, "TLBIEL", gen, "R%b"}, /* optional */
970d67b7dadSforsyth {31, 1010, ALL, "TLBLI", gen, "R%b"}, /* optional */
971d67b7dadSforsyth {31, 978, ALL, "TLBLD", gen, "R%b"}, /* optional */
972d67b7dadSforsyth {31, 566, ALL, "TLBSYNC", gen, 0}, /* optional */
973d67b7dadSforsyth {31, 68, ALL, "TD", gen, "%d,R%a,R%b"}, /* 64 */
97474a4d8c2SCharles.Forsyth {31, 4, ALL, "TW", gen, "%d,R%a,R%b"},
97574a4d8c2SCharles.Forsyth {3, 0, 0, "TW", gen, "%d,R%a,%i"},
97674a4d8c2SCharles.Forsyth
97774a4d8c2SCharles.Forsyth {31, 316, ALL, "XOR", and, il3},
97874a4d8c2SCharles.Forsyth {26, 0, 0, "XOR", and, il2u},
97974a4d8c2SCharles.Forsyth {27, 0, 0, "XOR", shifted, 0},
98074a4d8c2SCharles.Forsyth
98174a4d8c2SCharles.Forsyth {0},
98274a4d8c2SCharles.Forsyth };
98374a4d8c2SCharles.Forsyth
98474a4d8c2SCharles.Forsyth typedef struct Spr Spr;
98574a4d8c2SCharles.Forsyth struct Spr {
98674a4d8c2SCharles.Forsyth int n;
98774a4d8c2SCharles.Forsyth char *name;
98874a4d8c2SCharles.Forsyth };
98974a4d8c2SCharles.Forsyth
99074a4d8c2SCharles.Forsyth static Spr sprname[] = {
99174a4d8c2SCharles.Forsyth {0, "MQ"},
99274a4d8c2SCharles.Forsyth {1, "XER"},
99374a4d8c2SCharles.Forsyth {268, "TBL"},
99474a4d8c2SCharles.Forsyth {269, "TBU"},
99574a4d8c2SCharles.Forsyth {8, "LR"},
99674a4d8c2SCharles.Forsyth {9, "CTR"},
99774a4d8c2SCharles.Forsyth {528, "IBAT0U"},
99874a4d8c2SCharles.Forsyth {529, "IBAT0L"},
99974a4d8c2SCharles.Forsyth {530, "IBAT1U"},
100074a4d8c2SCharles.Forsyth {531, "IBAT1L"},
100174a4d8c2SCharles.Forsyth {532, "IBAT2U"},
100274a4d8c2SCharles.Forsyth {533, "IBAT2L"},
100374a4d8c2SCharles.Forsyth {534, "IBAT3U"},
100474a4d8c2SCharles.Forsyth {535, "IBAT3L"},
100574a4d8c2SCharles.Forsyth {536, "DBAT0U"},
100674a4d8c2SCharles.Forsyth {537, "DBAT0L"},
100774a4d8c2SCharles.Forsyth {538, "DBAT1U"},
100874a4d8c2SCharles.Forsyth {539, "DBAT1L"},
100974a4d8c2SCharles.Forsyth {540, "DBAT2U"},
101074a4d8c2SCharles.Forsyth {541, "DBAT2L"},
101174a4d8c2SCharles.Forsyth {542, "DBAT3U"},
101274a4d8c2SCharles.Forsyth {543, "DBAT3L"},
101374a4d8c2SCharles.Forsyth {25, "SDR1"},
101474a4d8c2SCharles.Forsyth {19, "DAR"},
101574a4d8c2SCharles.Forsyth {272, "SPRG0"},
101674a4d8c2SCharles.Forsyth {273, "SPRG1"},
101774a4d8c2SCharles.Forsyth {274, "SPRG2"},
101874a4d8c2SCharles.Forsyth {275, "SPRG3"},
101974a4d8c2SCharles.Forsyth {18, "DSISR"},
102074a4d8c2SCharles.Forsyth {26, "SRR0"},
102174a4d8c2SCharles.Forsyth {27, "SRR1"},
102274a4d8c2SCharles.Forsyth {284, "TBLW"},
102374a4d8c2SCharles.Forsyth {285, "TBUW"},
102474a4d8c2SCharles.Forsyth {22, "DEC"},
102574a4d8c2SCharles.Forsyth {282, "EAR"},
102674a4d8c2SCharles.Forsyth {1008, "HID0"},
102774a4d8c2SCharles.Forsyth {1009, "HID1"},
102874a4d8c2SCharles.Forsyth {976, "DMISS"},
102974a4d8c2SCharles.Forsyth {977, "DCMP"},
103074a4d8c2SCharles.Forsyth {978, "HASH1"},
103174a4d8c2SCharles.Forsyth {979, "HASH2"},
103274a4d8c2SCharles.Forsyth {980, "IMISS"},
103374a4d8c2SCharles.Forsyth {981, "ICMP"},
103474a4d8c2SCharles.Forsyth {982, "RPA"},
103574a4d8c2SCharles.Forsyth {1010, "IABR"},
103674a4d8c2SCharles.Forsyth {1013, "DABR"},
103774a4d8c2SCharles.Forsyth {0,0},
103874a4d8c2SCharles.Forsyth };
103974a4d8c2SCharles.Forsyth
1040d67b7dadSforsyth static int
shmask(uvlong * m)1041d67b7dadSforsyth shmask(uvlong *m)
1042d67b7dadSforsyth {
1043d67b7dadSforsyth int i;
1044d67b7dadSforsyth
1045d67b7dadSforsyth for(i=0; i<63; i++)
1046d67b7dadSforsyth if(*m & ((uvlong)1<<i))
1047d67b7dadSforsyth break;
1048d67b7dadSforsyth if(i > 63)
1049d67b7dadSforsyth return 0;
1050d67b7dadSforsyth if(*m & ~((uvlong)1<<i)){ /* more than one bit: do multiples of bytes */
1051d67b7dadSforsyth i = (i/8)*8;
1052d67b7dadSforsyth if(i == 0)
1053d67b7dadSforsyth return 0;
1054d67b7dadSforsyth }
1055d67b7dadSforsyth *m >>= i;
1056d67b7dadSforsyth return i;
1057d67b7dadSforsyth }
1058d67b7dadSforsyth
105974a4d8c2SCharles.Forsyth static void
format(char * mnemonic,Instr * i,char * f)106074a4d8c2SCharles.Forsyth format(char *mnemonic, Instr *i, char *f)
106174a4d8c2SCharles.Forsyth {
106274a4d8c2SCharles.Forsyth int n, s;
106374a4d8c2SCharles.Forsyth ulong mask;
1064d67b7dadSforsyth uvlong vmask;
106574a4d8c2SCharles.Forsyth
106674a4d8c2SCharles.Forsyth if (mnemonic)
106774a4d8c2SCharles.Forsyth format(0, i, mnemonic);
106874a4d8c2SCharles.Forsyth if (f == 0)
106974a4d8c2SCharles.Forsyth return;
107074a4d8c2SCharles.Forsyth if (mnemonic)
107174a4d8c2SCharles.Forsyth bprint(i, "\t");
107274a4d8c2SCharles.Forsyth for ( ; *f; f++) {
107374a4d8c2SCharles.Forsyth if (*f != '%') {
107474a4d8c2SCharles.Forsyth bprint(i, "%c", *f);
107574a4d8c2SCharles.Forsyth continue;
107674a4d8c2SCharles.Forsyth }
107774a4d8c2SCharles.Forsyth switch (*++f) {
107874a4d8c2SCharles.Forsyth
107974a4d8c2SCharles.Forsyth case 'a':
108074a4d8c2SCharles.Forsyth bprint(i, "%d", i->ra);
108174a4d8c2SCharles.Forsyth break;
108274a4d8c2SCharles.Forsyth
108374a4d8c2SCharles.Forsyth case 'b':
108474a4d8c2SCharles.Forsyth bprint(i, "%d", i->rb);
108574a4d8c2SCharles.Forsyth break;
108674a4d8c2SCharles.Forsyth
108774a4d8c2SCharles.Forsyth case 'c':
108874a4d8c2SCharles.Forsyth bprint(i, "%d", i->frc);
108974a4d8c2SCharles.Forsyth break;
109074a4d8c2SCharles.Forsyth
109174a4d8c2SCharles.Forsyth case 'd':
109274a4d8c2SCharles.Forsyth case 's':
109374a4d8c2SCharles.Forsyth bprint(i, "%d", i->rd);
109474a4d8c2SCharles.Forsyth break;
109574a4d8c2SCharles.Forsyth
1096d67b7dadSforsyth case 'C':
1097d67b7dadSforsyth if(i->rc)
1098d67b7dadSforsyth bprint(i, "CC");
109974a4d8c2SCharles.Forsyth break;
110074a4d8c2SCharles.Forsyth
110174a4d8c2SCharles.Forsyth case 'D':
110274a4d8c2SCharles.Forsyth if(i->rd & 3)
110374a4d8c2SCharles.Forsyth bprint(i, "CR(INVAL:%d)", i->rd);
110474a4d8c2SCharles.Forsyth else if(i->op == 63)
110574a4d8c2SCharles.Forsyth bprint(i, "FPSCR(%d)", i->crfd);
110674a4d8c2SCharles.Forsyth else
110774a4d8c2SCharles.Forsyth bprint(i, "CR(%d)", i->crfd);
110874a4d8c2SCharles.Forsyth break;
110974a4d8c2SCharles.Forsyth
1110d67b7dadSforsyth case 'e':
1111d67b7dadSforsyth bprint(i, "%d", i->xsh);
1112d67b7dadSforsyth break;
1113d67b7dadSforsyth
1114d67b7dadSforsyth case 'E':
1115d67b7dadSforsyth switch(IBF(i->w0,27,30)){ /* low bit is top bit of shift in rldiX cases */
1116d67b7dadSforsyth case 8: i->mb = i->xmbe; i->me = 63; break; /* rldcl */
1117d67b7dadSforsyth case 9: i->mb = 0; i->me = i->xmbe; break; /* rldcr */
1118d67b7dadSforsyth case 4: case 5:
1119d67b7dadSforsyth i->mb = i->xmbe; i->me = 63-i->xsh; break; /* rldic */
1120d67b7dadSforsyth case 0: case 1:
1121d67b7dadSforsyth i->mb = i->xmbe; i->me = 63; break; /* rldicl */
1122d67b7dadSforsyth case 2: case 3:
1123d67b7dadSforsyth i->mb = 0; i->me = i->xmbe; break; /* rldicr */
1124d67b7dadSforsyth case 6: case 7:
1125d67b7dadSforsyth i->mb = i->xmbe; i->me = 63-i->xsh; break; /* rldimi */
1126d67b7dadSforsyth }
1127d67b7dadSforsyth vmask = (~(uvlong)0>>i->mb) & (~(uvlong)0<<(63-i->me));
1128d67b7dadSforsyth s = shmask(&vmask);
1129d67b7dadSforsyth if(s)
1130d67b7dadSforsyth bprint(i, "(%llux<<%d)", vmask, s);
1131d67b7dadSforsyth else
1132d67b7dadSforsyth bprint(i, "%llux", vmask);
113374a4d8c2SCharles.Forsyth break;
113474a4d8c2SCharles.Forsyth
113574a4d8c2SCharles.Forsyth case 'i':
1136d67b7dadSforsyth bprint(i, "$%d", i->simm);
113774a4d8c2SCharles.Forsyth break;
113874a4d8c2SCharles.Forsyth
113974a4d8c2SCharles.Forsyth case 'I':
1140d67b7dadSforsyth bprint(i, "$%ux", i->uimm);
114174a4d8c2SCharles.Forsyth break;
114274a4d8c2SCharles.Forsyth
114374a4d8c2SCharles.Forsyth case 'j':
114474a4d8c2SCharles.Forsyth if(i->aa)
114574a4d8c2SCharles.Forsyth pglobal(i, i->li, 1, "(SB)");
114674a4d8c2SCharles.Forsyth else
114774a4d8c2SCharles.Forsyth pglobal(i, i->addr+i->li, 1, "");
114874a4d8c2SCharles.Forsyth break;
114974a4d8c2SCharles.Forsyth
115074a4d8c2SCharles.Forsyth case 'J':
115174a4d8c2SCharles.Forsyth if(i->aa)
115274a4d8c2SCharles.Forsyth pglobal(i, i->bd, 1, "(SB)");
115374a4d8c2SCharles.Forsyth else
115474a4d8c2SCharles.Forsyth pglobal(i, i->addr+i->bd, 1, "");
115574a4d8c2SCharles.Forsyth break;
115674a4d8c2SCharles.Forsyth
1157d67b7dadSforsyth case 'k':
1158d67b7dadSforsyth bprint(i, "%d", i->sh);
1159d67b7dadSforsyth break;
1160d67b7dadSforsyth
1161d67b7dadSforsyth case 'K':
1162d67b7dadSforsyth bprint(i, "$%x", i->imm);
1163d67b7dadSforsyth break;
1164d67b7dadSforsyth
1165d67b7dadSforsyth case 'L':
1166d67b7dadSforsyth if(i->lk)
1167d67b7dadSforsyth bprint(i, "L");
1168d67b7dadSforsyth break;
1169d67b7dadSforsyth
1170d67b7dadSforsyth case 'l':
1171d67b7dadSforsyth if(i->simm < 0)
1172d67b7dadSforsyth bprint(i, "-%x(R%d)", -i->simm, i->ra);
1173d67b7dadSforsyth else
1174d67b7dadSforsyth bprint(i, "%x(R%d)", i->simm, i->ra);
1175d67b7dadSforsyth break;
1176d67b7dadSforsyth
1177d67b7dadSforsyth case 'm':
1178d67b7dadSforsyth bprint(i, "%ux", i->crm);
1179d67b7dadSforsyth break;
1180d67b7dadSforsyth
1181d67b7dadSforsyth case 'M':
1182d67b7dadSforsyth bprint(i, "%ux", i->fm);
1183d67b7dadSforsyth break;
1184d67b7dadSforsyth
1185d67b7dadSforsyth case 'n':
1186d67b7dadSforsyth bprint(i, "%d", i->nb==0? 32: i->nb); /* eg, pg 10-103 */
1187d67b7dadSforsyth break;
1188d67b7dadSforsyth
1189d67b7dadSforsyth case 'P':
1190d67b7dadSforsyth n = ((i->spr&0x1f)<<5)|((i->spr>>5)&0x1f);
1191d67b7dadSforsyth for(s=0; sprname[s].name; s++)
1192d67b7dadSforsyth if(sprname[s].n == n)
1193d67b7dadSforsyth break;
1194d67b7dadSforsyth if(sprname[s].name) {
1195d67b7dadSforsyth if(s < 10)
1196d67b7dadSforsyth bprint(i, sprname[s].name);
1197d67b7dadSforsyth else
1198d67b7dadSforsyth bprint(i, "SPR(%s)", sprname[s].name);
1199d67b7dadSforsyth } else
1200d67b7dadSforsyth bprint(i, "SPR(%d)", n);
1201d67b7dadSforsyth break;
1202d67b7dadSforsyth
1203d67b7dadSforsyth case 'Q':
1204d67b7dadSforsyth n = ((i->spr&0x1f)<<5)|((i->spr>>5)&0x1f);
1205d67b7dadSforsyth bprint(i, "%d", n);
1206d67b7dadSforsyth break;
1207d67b7dadSforsyth
1208d67b7dadSforsyth case 'S':
1209d67b7dadSforsyth if(i->ra & 3)
1210d67b7dadSforsyth bprint(i, "CR(INVAL:%d)", i->ra);
1211d67b7dadSforsyth else if(i->op == 63)
1212d67b7dadSforsyth bprint(i, "FPSCR(%d)", i->crfs);
1213d67b7dadSforsyth else
1214d67b7dadSforsyth bprint(i, "CR(%d)", i->crfs);
1215d67b7dadSforsyth break;
1216d67b7dadSforsyth
1217d67b7dadSforsyth case 'U':
1218d67b7dadSforsyth if(i->rc)
1219d67b7dadSforsyth bprint(i, "U");
1220d67b7dadSforsyth break;
1221d67b7dadSforsyth
1222d67b7dadSforsyth case 'V':
1223d67b7dadSforsyth if(i->oe)
1224d67b7dadSforsyth bprint(i, "V");
1225d67b7dadSforsyth break;
1226d67b7dadSforsyth
1227d67b7dadSforsyth case 'w':
1228d67b7dadSforsyth bprint(i, "[%lux]", i->w0);
1229d67b7dadSforsyth break;
1230d67b7dadSforsyth
1231d67b7dadSforsyth case 'W':
1232d67b7dadSforsyth if(i->m64)
1233d67b7dadSforsyth bprint(i, "W");
1234d67b7dadSforsyth break;
1235d67b7dadSforsyth
1236d67b7dadSforsyth case 'Z':
1237d67b7dadSforsyth if(i->m64)
1238d67b7dadSforsyth bprint(i, "Z");
1239d67b7dadSforsyth break;
1240d67b7dadSforsyth
1241d67b7dadSforsyth case 'z':
1242d67b7dadSforsyth if(i->mb <= i->me)
1243d67b7dadSforsyth mask = ((ulong)~0L>>i->mb) & (~0L<<(31-i->me));
1244d67b7dadSforsyth else
1245d67b7dadSforsyth mask = ~(((ulong)~0L>>(i->me+1)) & (~0L<<(31-(i->mb-1))));
1246d67b7dadSforsyth bprint(i, "%lux", mask);
1247d67b7dadSforsyth break;
1248d67b7dadSforsyth
124974a4d8c2SCharles.Forsyth case '\0':
125074a4d8c2SCharles.Forsyth bprint(i, "%%");
125174a4d8c2SCharles.Forsyth return;
125274a4d8c2SCharles.Forsyth
125374a4d8c2SCharles.Forsyth default:
125474a4d8c2SCharles.Forsyth bprint(i, "%%%c", *f);
125574a4d8c2SCharles.Forsyth break;
125674a4d8c2SCharles.Forsyth }
125774a4d8c2SCharles.Forsyth }
125874a4d8c2SCharles.Forsyth }
125974a4d8c2SCharles.Forsyth
126074a4d8c2SCharles.Forsyth static int
printins(Map * map,uvlong pc,char * buf,int n)1261d67b7dadSforsyth printins(Map *map, uvlong pc, char *buf, int n)
126274a4d8c2SCharles.Forsyth {
126374a4d8c2SCharles.Forsyth Instr i;
126474a4d8c2SCharles.Forsyth Opcode *o;
126574a4d8c2SCharles.Forsyth
126674a4d8c2SCharles.Forsyth mymap = map;
126774a4d8c2SCharles.Forsyth memset(&i, 0, sizeof(i));
126874a4d8c2SCharles.Forsyth i.curr = buf;
126974a4d8c2SCharles.Forsyth i.end = buf+n-1;
127074a4d8c2SCharles.Forsyth if(mkinstr(pc, &i) < 0)
127174a4d8c2SCharles.Forsyth return -1;
127274a4d8c2SCharles.Forsyth for(o = opcodes; o->mnemonic != 0; o++)
127374a4d8c2SCharles.Forsyth if(i.op == o->op && (i.xo & o->xomask) == o->xo) {
127474a4d8c2SCharles.Forsyth if (o->f)
127574a4d8c2SCharles.Forsyth (*o->f)(o, &i);
127674a4d8c2SCharles.Forsyth else
127774a4d8c2SCharles.Forsyth format(o->mnemonic, &i, o->ken);
127874a4d8c2SCharles.Forsyth return i.size*4;
127974a4d8c2SCharles.Forsyth }
128074a4d8c2SCharles.Forsyth bprint(&i, "unknown %lux", i.w0);
128174a4d8c2SCharles.Forsyth return i.size*4;
128274a4d8c2SCharles.Forsyth }
128374a4d8c2SCharles.Forsyth
128474a4d8c2SCharles.Forsyth static int
powerinst(Map * map,uvlong pc,char modifier,char * buf,int n)1285d67b7dadSforsyth powerinst(Map *map, uvlong pc, char modifier, char *buf, int n)
128674a4d8c2SCharles.Forsyth {
128774a4d8c2SCharles.Forsyth USED(modifier);
128874a4d8c2SCharles.Forsyth return printins(map, pc, buf, n);
128974a4d8c2SCharles.Forsyth }
129074a4d8c2SCharles.Forsyth
129174a4d8c2SCharles.Forsyth static int
powerdas(Map * map,uvlong pc,char * buf,int n)1292d67b7dadSforsyth powerdas(Map *map, uvlong pc, char *buf, int n)
129374a4d8c2SCharles.Forsyth {
129474a4d8c2SCharles.Forsyth Instr instr;
129574a4d8c2SCharles.Forsyth
129674a4d8c2SCharles.Forsyth mymap = map;
129774a4d8c2SCharles.Forsyth memset(&instr, 0, sizeof(instr));
129874a4d8c2SCharles.Forsyth instr.curr = buf;
129974a4d8c2SCharles.Forsyth instr.end = buf+n-1;
130074a4d8c2SCharles.Forsyth if (mkinstr(pc, &instr) < 0)
130174a4d8c2SCharles.Forsyth return -1;
130274a4d8c2SCharles.Forsyth if (instr.end-instr.curr > 8)
130374a4d8c2SCharles.Forsyth instr.curr = _hexify(instr.curr, instr.w0, 7);
130474a4d8c2SCharles.Forsyth if (instr.end-instr.curr > 9 && instr.size == 2) {
130574a4d8c2SCharles.Forsyth *instr.curr++ = ' ';
130674a4d8c2SCharles.Forsyth instr.curr = _hexify(instr.curr, instr.w1, 7);
130774a4d8c2SCharles.Forsyth }
130874a4d8c2SCharles.Forsyth *instr.curr = 0;
130974a4d8c2SCharles.Forsyth return instr.size*4;
131074a4d8c2SCharles.Forsyth }
131174a4d8c2SCharles.Forsyth
131274a4d8c2SCharles.Forsyth static int
powerinstlen(Map * map,uvlong pc)1313d67b7dadSforsyth powerinstlen(Map *map, uvlong pc)
131474a4d8c2SCharles.Forsyth {
131574a4d8c2SCharles.Forsyth Instr i;
131674a4d8c2SCharles.Forsyth
131774a4d8c2SCharles.Forsyth mymap = map;
131874a4d8c2SCharles.Forsyth if (mkinstr(pc, &i) < 0)
131974a4d8c2SCharles.Forsyth return -1;
132074a4d8c2SCharles.Forsyth return i.size*4;
132174a4d8c2SCharles.Forsyth }
132274a4d8c2SCharles.Forsyth
132374a4d8c2SCharles.Forsyth static int
powerfoll(Map * map,uvlong pc,Rgetter rget,uvlong * foll)1324d67b7dadSforsyth powerfoll(Map *map, uvlong pc, Rgetter rget, uvlong *foll)
132574a4d8c2SCharles.Forsyth {
132674a4d8c2SCharles.Forsyth char *reg;
132774a4d8c2SCharles.Forsyth Instr i;
132874a4d8c2SCharles.Forsyth
132974a4d8c2SCharles.Forsyth mymap = map;
133074a4d8c2SCharles.Forsyth if (mkinstr(pc, &i) < 0)
133174a4d8c2SCharles.Forsyth return -1;
133274a4d8c2SCharles.Forsyth foll[0] = pc+4;
133374a4d8c2SCharles.Forsyth foll[1] = pc+4;
133474a4d8c2SCharles.Forsyth switch(i.op) {
133574a4d8c2SCharles.Forsyth default:
133674a4d8c2SCharles.Forsyth return 1;
133774a4d8c2SCharles.Forsyth
133874a4d8c2SCharles.Forsyth case 18: /* branch */
133974a4d8c2SCharles.Forsyth foll[0] = i.li;
134074a4d8c2SCharles.Forsyth if(!i.aa)
134174a4d8c2SCharles.Forsyth foll[0] += pc;
134274a4d8c2SCharles.Forsyth break;
134374a4d8c2SCharles.Forsyth
134474a4d8c2SCharles.Forsyth case 16: /* conditional branch */
134574a4d8c2SCharles.Forsyth foll[0] = i.bd;
134674a4d8c2SCharles.Forsyth if(!i.aa)
134774a4d8c2SCharles.Forsyth foll[0] += pc;
134874a4d8c2SCharles.Forsyth break;
134974a4d8c2SCharles.Forsyth
135074a4d8c2SCharles.Forsyth case 19: /* conditional branch to register */
135174a4d8c2SCharles.Forsyth if(i.xo == 528)
135274a4d8c2SCharles.Forsyth reg = "CTR";
135374a4d8c2SCharles.Forsyth else if(i.xo == 16)
135474a4d8c2SCharles.Forsyth reg = "LR";
135574a4d8c2SCharles.Forsyth else
135674a4d8c2SCharles.Forsyth return 1; /* not a branch */
135774a4d8c2SCharles.Forsyth foll[0] = (*rget)(map, reg);
135874a4d8c2SCharles.Forsyth break;
135974a4d8c2SCharles.Forsyth }
136074a4d8c2SCharles.Forsyth if(i.lk)
136174a4d8c2SCharles.Forsyth return 2;
136274a4d8c2SCharles.Forsyth return 1;
136374a4d8c2SCharles.Forsyth }
1364