123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260 |
- #include <u.h>
- #include <libc.h>
- #include <bio.h>
- #include <mach.h>
- /*
- * PowerPC-specific debugger interface
- * forsyth@terzarima.net
- */
- static char *powerexcep(Map*, Rgetter);
- static int powerfoll(Map*, uvlong, Rgetter, uvlong*);
- static int powerinst(Map*, uvlong, char, char*, int);
- static int powerinstlen(Map*, uvlong);
- static int powerdas(Map*, uvlong, char*, int);
- /*
- * Machine description
- */
- Machdata powermach =
- {
- {0x02, 0x8f, 0xff, 0xff}, /* break point */ /* BUG */
- 4, /* break point size */
- beswab, /* short to local byte order */
- beswal, /* long to local byte order */
- beswav, /* vlong to local byte order */
- risctrace, /* print C traceback */
- riscframe, /* frame finder */
- powerexcep, /* print exception */
- 0, /* breakpoint fixup */
- beieeesftos, /* single precision float printer */
- beieeedftos, /* double precisioin float printer */
- powerfoll, /* following addresses */
- powerinst, /* print instruction */
- powerdas, /* dissembler */
- powerinstlen, /* instruction size */
- };
- static char *excname[] =
- {
- "reserved 0",
- "system reset",
- "machine check",
- "data access",
- "instruction access",
- "external interrupt",
- "alignment",
- "program exception",
- "floating-point unavailable",
- "decrementer",
- "i/o controller interface error",
- "reserved B",
- "system call",
- "trace trap",
- "floating point assist",
- "reserved",
- "ITLB miss",
- "DTLB load miss",
- "DTLB store miss",
- "instruction address breakpoint"
- "SMI interrupt"
- "reserved 15",
- "reserved 16",
- "reserved 17",
- "reserved 18",
- "reserved 19",
- "reserved 1A",
- /* the following are made up on a program exception */
- "floating point exception", /* FPEXC */
- "illegal instruction",
- "privileged instruction",
- "trap",
- "illegal operation",
- };
- static char*
- powerexcep(Map *map, Rgetter rget)
- {
- long c;
- static char buf[32];
- c = (*rget)(map, "CAUSE") >> 8;
- if(c < nelem(excname))
- return excname[c];
- sprint(buf, "unknown trap #%lx", c);
- return buf;
- }
- /*
- * disassemble PowerPC opcodes
- */
- #define REGSP 1 /* should come from q.out.h, but there's a clash */
- #define REGSB 2
- static char FRAMENAME[] = ".frame";
- static Map *mymap;
- /*
- * ibm conventions for these: bit 0 is top bit
- * from table 10-1
- */
- typedef struct {
- uchar aa; /* bit 30 */
- uchar crba; /* bits 11-15 */
- uchar crbb; /* bits 16-20 */
- long bd; /* bits 16-29 */
- uchar crfd; /* bits 6-8 */
- uchar crfs; /* bits 11-13 */
- uchar bi; /* bits 11-15 */
- uchar bo; /* bits 6-10 */
- uchar crbd; /* bits 6-10 */
- union {
- short d; /* bits 16-31 */
- short simm;
- ushort uimm;
- };
- uchar fm; /* bits 7-14 */
- uchar fra; /* bits 11-15 */
- uchar frb; /* bits 16-20 */
- uchar frc; /* bits 21-25 */
- uchar frs; /* bits 6-10 */
- uchar frd; /* bits 6-10 */
- uchar crm; /* bits 12-19 */
- long li; /* bits 6-29 || b'00' */
- uchar lk; /* bit 31 */
- uchar mb; /* bits 21-25 */
- uchar me; /* bits 26-30 */
- uchar nb; /* bits 16-20 */
- uchar op; /* bits 0-5 */
- uchar oe; /* bit 21 */
- uchar ra; /* bits 11-15 */
- uchar rb; /* bits 16-20 */
- uchar rc; /* bit 31 */
- union {
- uchar rs; /* bits 6-10 */
- uchar rd;
- };
- uchar sh; /* bits 16-20 */
- ushort spr; /* bits 11-20 */
- uchar to; /* bits 6-10 */
- uchar imm; /* bits 16-19 */
- ushort xo; /* bits 21-30, 22-30, 26-30, or 30 (beware) */
- long immediate;
- long w0;
- long w1;
- uvlong addr; /* pc of instruction */
- short target;
- char *curr; /* current fill level in output buffer */
- char *end; /* end of buffer */
- int size; /* number of longs in instr */
- char *err; /* errmsg */
- } Instr;
- #define IBF(v,a,b) (((ulong)(v)>>(32-(b)-1)) & ~(~0L<<(((b)-(a)+1))))
- #define IB(v,b) IBF((v),(b),(b))
- #pragma varargck argpos bprint 2
- static void
- bprint(Instr *i, char *fmt, ...)
- {
- va_list arg;
- va_start(arg, fmt);
- i->curr = vseprint(i->curr, i->end, fmt, arg);
- va_end(arg);
- }
- static int
- decode(uvlong pc, Instr *i)
- {
- ulong w;
- if (get4(mymap, pc, &w) < 0) {
- werrstr("can't read instruction: %r");
- return -1;
- }
- i->aa = IB(w, 30);
- i->crba = IBF(w, 11, 15);
- i->crbb = IBF(w, 16, 20);
- i->bd = IBF(w, 16, 29)<<2;
- if(i->bd & 0x8000)
- i->bd |= ~0L<<16;
- i->crfd = IBF(w, 6, 8);
- i->crfs = IBF(w, 11, 13);
- i->bi = IBF(w, 11, 15);
- i->bo = IBF(w, 6, 10);
- i->crbd = IBF(w, 6, 10);
- i->uimm = IBF(w, 16, 31); /* also d, simm */
- i->fm = IBF(w, 7, 14);
- i->fra = IBF(w, 11, 15);
- i->frb = IBF(w, 16, 20);
- i->frc = IBF(w, 21, 25);
- i->frs = IBF(w, 6, 10);
- i->frd = IBF(w, 6, 10);
- i->crm = IBF(w, 12, 19);
- i->li = IBF(w, 6, 29)<<2;
- if(IB(w, 6))
- i->li |= ~0<<25;
- i->lk = IB(w, 31);
- i->mb = IBF(w, 21, 25);
- i->me = IBF(w, 26, 30);
- i->nb = IBF(w, 16, 20);
- i->op = IBF(w, 0, 5);
- i->oe = IB(w, 21);
- i->ra = IBF(w, 11, 15);
- i->rb = IBF(w, 16, 20);
- i->rc = IB(w, 31);
- i->rs = IBF(w, 6, 10); /* also rd */
- i->sh = IBF(w, 16, 20);
- i->spr = IBF(w, 11, 20);
- i->to = IBF(w, 6, 10);
- i->imm = IBF(w, 16, 19);
- i->xo = IBF(w, 21, 30); /* bits 21-30, 22-30, 26-30, or 30 (beware) */
- i->immediate = i->simm;
- if(i->op == 15)
- i->immediate <<= 16;
- i->w0 = w;
- i->target = -1;
- i->addr = pc;
- i->size = 1;
- return 1;
- }
- static int
- mkinstr(uvlong pc, Instr *i)
- {
- Instr x;
- if(decode(pc, i) < 0)
- return -1;
- /*
- * combine ADDIS/ORI (CAU/ORIL) into MOVW
- */
- if (i->op == 15 && i->ra==0) {
- if(decode(pc+4, &x) < 0)
- return -1;
- if (x.op == 24 && x.rs == x.ra && x.ra == i->rd) {
- i->immediate |= (x.immediate & 0xFFFF);
- i->w1 = x.w0;
- i->target = x.rd;
- i->size++;
- return 1;
- }
- }
- return 1;
- }
- static int
- plocal(Instr *i)
- {
- long offset;
- Symbol s;
- if (!findsym(i->addr, CTEXT, &s) || !findlocal(&s, FRAMENAME, &s))
- return -1;
- offset = s.value - i->immediate;
- if (offset > 0) {
- if(getauto(&s, offset, CAUTO, &s)) {
- bprint(i, "%s+%lld(SP)", s.name, s.value);
- return 1;
- }
- } else {
- if (getauto(&s, -offset-4, CPARAM, &s)) {
- bprint(i, "%s+%ld(FP)", s.name, -offset);
- return 1;
- }
- }
- return -1;
- }
- static int
- pglobal(Instr *i, uvlong off, int anyoff, char *reg)
- {
- Symbol s, s2;
- uvlong off1;
- if(findsym(off, CANY, &s) &&
- s.value-off < 4096 &&
- (s.class == CDATA || s.class == CTEXT)) {
- if(off==s.value && s.name[0]=='$'){
- off1 = 0;
- geta(mymap, s.value, &off1);
- if(off1 && findsym(off1, CANY, &s2) && s2.value == off1){
- bprint(i, "$%s%s", s2.name, reg);
- return 1;
- }
- }
- bprint(i, "%s", s.name);
- if (s.value != off)
- bprint(i, "+%llux", off-s.value);
- bprint(i, reg);
- return 1;
- }
- if(!anyoff)
- return 0;
- bprint(i, "%llux%s", off, reg);
- return 1;
- }
- static void
- address(Instr *i)
- {
- if (i->ra == REGSP && plocal(i) >= 0)
- return;
- if (i->ra == REGSB && mach->sb && pglobal(i, mach->sb+i->immediate, 0, "(SB)") >= 0)
- return;
- if(i->simm < 0)
- bprint(i, "-%x(R%d)", -i->simm, i->ra);
- else
- bprint(i, "%lux(R%d)", i->immediate, i->ra);
- }
- static char *tcrbits[] = {"LT", "GT", "EQ", "VS"};
- static char *fcrbits[] = {"GE", "LE", "NE", "VC"};
- typedef struct Opcode Opcode;
- struct Opcode {
- uchar op;
- ushort xo;
- ushort xomask;
- char *mnemonic;
- void (*f)(Opcode *, Instr *);
- char *ken;
- int flags;
- };
- static void format(char *, Instr *, char *);
- static void
- branch(Opcode *o, Instr *i)
- {
- char buf[8];
- int bo, bi;
- bo = i->bo & ~1; /* ignore prediction bit */
- if(bo==4 || bo==12 || bo==20) { /* simple forms */
- if(bo != 20) {
- bi = i->bi&3;
- sprint(buf, "B%s%%L", bo==12? tcrbits[bi]: fcrbits[bi]);
- format(buf, i, 0);
- bprint(i, "\t");
- if(i->bi > 4)
- bprint(i, "CR(%d),", i->bi/4);
- } else
- format("BR%L\t", i, 0);
- if(i->op == 16)
- format(0, i, "%J");
- else if(i->op == 19 && i->xo == 528)
- format(0, i, "(CTR)");
- else if(i->op == 19 && i->xo == 16)
- format(0, i, "(LR)");
- } else
- format(o->mnemonic, i, o->ken);
- }
- static void
- addi(Opcode *o, Instr *i)
- {
- if (i->op==14 && i->ra == 0)
- format("MOVW", i, "%i,R%d");
- else if (i->ra == REGSB) {
- bprint(i, "MOVW\t$");
- address(i);
- bprint(i, ",R%d", i->rd);
- } else if(i->op==14 && i->simm < 0) {
- bprint(i, "SUB\t$%d,R%d", -i->simm, i->ra);
- if(i->rd != i->ra)
- bprint(i, ",R%d", i->rd);
- } else if(i->ra == i->rd) {
- format(o->mnemonic, i, "%i");
- bprint(i, ",R%d", i->rd);
- } else
- format(o->mnemonic, i, o->ken);
- }
- static void
- addis(Opcode *o, Instr *i)
- {
- long v;
- v = i->immediate;
- if (i->op==15 && i->ra == 0)
- bprint(i, "MOVW\t$%lux,R%d", v, i->rd);
- else if (i->op==15 && i->ra == REGSB) {
- bprint(i, "MOVW\t$");
- address(i);
- bprint(i, ",R%d", i->rd);
- } else if(i->op==15 && v < 0) {
- bprint(i, "SUB\t$%ld,R%d", -v, i->ra);
- if(i->rd != i->ra)
- bprint(i, ",R%d", i->rd);
- } else {
- format(o->mnemonic, i, 0);
- bprint(i, "\t$%ld,R%d", v, i->ra);
- if(i->rd != i->ra)
- bprint(i, ",R%d", i->rd);
- }
- }
- static void
- andi(Opcode *o, Instr *i)
- {
- if (i->ra == i->rs)
- format(o->mnemonic, i, "%I,R%d");
- else
- format(o->mnemonic, i, o->ken);
- }
- static void
- gencc(Opcode *o, Instr *i)
- {
- format(o->mnemonic, i, o->ken);
- }
- static void
- gen(Opcode *o, Instr *i)
- {
- format(o->mnemonic, i, o->ken);
- if (i->rc)
- bprint(i, " [illegal Rc]");
- }
- static void
- ldx(Opcode *o, Instr *i)
- {
- if(i->ra == 0)
- format(o->mnemonic, i, "(R%b),R%d");
- else
- format(o->mnemonic, i, "(R%b+R%a),R%d");
- if(i->rc)
- bprint(i, " [illegal Rc]");
- }
- static void
- stx(Opcode *o, Instr *i)
- {
- if(i->ra == 0)
- format(o->mnemonic, i, "R%d,(R%b)");
- else
- format(o->mnemonic, i, "R%d,(R%b+R%a)");
- if(i->rc && i->xo != 150)
- bprint(i, " [illegal Rc]");
- }
- static void
- fldx(Opcode *o, Instr *i)
- {
- if(i->ra == 0)
- format(o->mnemonic, i, "(R%b),F%d");
- else
- format(o->mnemonic, i, "(R%b+R%a),F%d");
- if(i->rc)
- bprint(i, " [illegal Rc]");
- }
- static void
- fstx(Opcode *o, Instr *i)
- {
- if(i->ra == 0)
- format(o->mnemonic, i, "F%d,(R%b)");
- else
- format(o->mnemonic, i, "F%d,(R%b+R%a)");
- if(i->rc)
- bprint(i, " [illegal Rc]");
- }
- static void
- dcb(Opcode *o, Instr *i)
- {
- if(i->ra == 0)
- format(o->mnemonic, i, "(R%b)");
- else
- format(o->mnemonic, i, "(R%b+R%a)");
- if(i->rd)
- bprint(i, " [illegal Rd]");
- if(i->rc)
- bprint(i, " [illegal Rc]");
- }
- static void
- lw(Opcode *o, Instr *i, char r)
- {
- bprint(i, "%s\t", o->mnemonic);
- address(i);
- bprint(i, ",%c%d", r, i->rd);
- }
- static void
- load(Opcode *o, Instr *i)
- {
- lw(o, i, 'R');
- }
- static void
- fload(Opcode *o, Instr *i)
- {
- lw(o, i, 'F');
- }
- static void
- sw(Opcode *o, Instr *i, char r)
- {
- int offset;
- char *m;
- Symbol s;
- m = o->mnemonic;
- if (i->rs == REGSP) {
- if (findsym(i->addr, CTEXT, &s) && findlocal(&s, FRAMENAME, &s)) {
- offset = s.value-i->immediate;
- if (offset > 0 && getauto(&s, offset, CAUTO, &s)) {
- bprint(i, "%s\t%c%d,%s-%d(SP)", m, r, i->rd,
- s.name, offset);
- return;
- }
- }
- }
- if (i->rs == REGSB && mach->sb) {
- bprint(i, "%s\t%c%d,", m, r, i->rd);
- address(i);
- return;
- }
- if (r == 'F')
- format(m, i, "F%d,%l");
- else
- format(m, i, o->ken);
- }
- static void
- store(Opcode *o, Instr *i)
- {
- sw(o, i, 'R');
- }
- static void
- fstore(Opcode *o, Instr *i)
- {
- sw(o, i, 'F');
- }
- static void
- shifti(Opcode *o, Instr *i)
- {
- if (i->ra == i->rs)
- format(o->mnemonic, i, "$%k,R%a");
- else
- format(o->mnemonic, i, o->ken);
- }
- static void
- shift(Opcode *o, Instr *i)
- {
- if (i->ra == i->rs)
- format(o->mnemonic, i, "R%b,R%a");
- else
- format(o->mnemonic, i, o->ken);
- }
- static void
- add(Opcode *o, Instr *i)
- {
- if (i->rd == i->ra)
- format(o->mnemonic, i, "R%b,R%d");
- else if (i->rd == i->rb)
- format(o->mnemonic, i, "R%a,R%d");
- else
- format(o->mnemonic, i, o->ken);
- }
- static void
- sub(Opcode *o, Instr *i)
- {
- format(o->mnemonic, i, 0);
- bprint(i, "\t");
- if(i->op == 31) {
- bprint(i, "\tR%d,R%d", i->ra, i->rb); /* subtract Ra from Rb */
- if(i->rd != i->rb)
- bprint(i, ",R%d", i->rd);
- } else
- bprint(i, "\tR%d,$%d,R%d", i->ra, i->simm, i->rd);
- }
- static void
- qdiv(Opcode *o, Instr *i)
- {
- format(o->mnemonic, i, 0);
- if(i->op == 31)
- bprint(i, "\tR%d,R%d", i->rb, i->ra);
- else
- bprint(i, "\t$%d,R%d", i->simm, i->ra);
- if(i->ra != i->rd)
- bprint(i, ",R%d", i->rd);
- }
- static void
- and(Opcode *o, Instr *i)
- {
- if (i->op == 31) {
- /* Rb,Rs,Ra */
- if (i->ra == i->rs)
- format(o->mnemonic, i, "R%b,R%a");
- else if (i->ra == i->rb)
- format(o->mnemonic, i, "R%s,R%a");
- else
- format(o->mnemonic, i, o->ken);
- } else {
- /* imm,Rs,Ra */
- if (i->ra == i->rs)
- format(o->mnemonic, i, "%I,R%a");
- else
- format(o->mnemonic, i, o->ken);
- }
- }
- static void
- or(Opcode *o, Instr *i)
- {
- if (i->op == 31) {
- /* Rb,Rs,Ra */
- if (i->rs == 0 && i->ra == 0 && i->rb == 0)
- format("NOP", i, 0);
- else if (i->rs == i->rb)
- format("MOVW", i, "R%b,R%a");
- else
- and(o, i);
- } else
- and(o, i);
- }
- static void
- shifted(Opcode *o, Instr *i)
- {
- format(o->mnemonic, i, 0);
- bprint(i, "\t$%lux,", (ulong)i->uimm<<16);
- if (i->rs == i->ra)
- bprint(i, "R%d", i->ra);
- else
- bprint(i, "R%d,R%d", i->rs, i->ra);
- }
- static void
- neg(Opcode *o, Instr *i)
- {
- if (i->rd == i->ra)
- format(o->mnemonic, i, "R%d");
- else
- format(o->mnemonic, i, o->ken);
- }
- static char ir2[] = "R%a,R%d"; /* reverse of IBM order */
- static char ir3[] = "R%b,R%a,R%d";
- static char ir3r[] = "R%a,R%b,R%d";
- static char il3[] = "R%b,R%s,R%a";
- static char il2u[] = "%I,R%a,R%d";
- static char il3s[] = "$%k,R%s,R%a";
- static char il2[] = "R%s,R%a";
- static char icmp3[] = "R%a,R%b,%D";
- static char cr3op[] = "%b,%a,%d";
- static char ir2i[] = "%i,R%a,R%d";
- static char fp2[] = "F%b,F%d";
- static char fp3[] = "F%b,F%a,F%d";
- static char fp3c[] = "F%c,F%a,F%d";
- static char fp4[] = "F%a,F%c,F%b,F%d";
- static char fpcmp[] = "F%a,F%b,%D";
- static char ldop[] = "%l,R%d";
- static char stop[] = "R%d,%l";
- static char fldop[] = "%l,F%d";
- static char fstop[] = "F%d,%l";
- static char rlim[] = "R%b,R%s,$%z,R%a";
- static char rlimi[] = "$%k,R%s,$%z,R%a";
- #define OEM IBF(~0,22,30)
- #define FP4 IBF(~0,26,30)
- #define ALL (~0)
- /*
- notes:
- 10-26: crfD = rD>>2; rD&3 mbz
- also, L bit (bit 10) mbz or selects 64-bit operands
- */
- static Opcode opcodes[] = {
- {31, 360, OEM, "ABS%V%C", 0, ir2}, /* POWER */
- {31, 266, OEM, "ADD%V%C", add, ir3},
- {31, 10, OEM, "ADDC%V%C", add, ir3},
- {31, 138, OEM, "ADDE%V%C", add, ir3},
- {14, 0, 0, "ADD", addi, ir2i},
- {12, 0, 0, "ADDC", addi, ir2i},
- {13, 0, 0, "ADDCCC", addi, ir2i},
- {15, 0, 0, "ADD", addis, 0},
- {31, 234, OEM, "ADDME%V%C", gencc, ir2},
- {31, 202, OEM, "ADDZE%V%C", gencc, ir2},
- {31, 28, ALL, "AND%C", and, il3},
- {31, 60, ALL, "ANDN%C", and, il3},
- {28, 0, 0, "ANDCC", andi, il2u},
- {29, 0, 0, "ANDCC", shifted, 0},
- {18, 0, 0, "B%L", gencc, "%j"},
- {16, 0, 0, "BC%L", branch, "%d,%a,%J"},
- {19, 528, ALL, "BC%L", branch, "%d,%a,(CTR)"},
- {19, 16, ALL, "BC%L", branch, "%d,%a,(LR)"},
- {31, 531, ALL, "CLCS", gen, ir2}, /* POWER */
- {31, 0, ALL, "CMP", 0, icmp3},
- {11, 0, 0, "CMP", 0, "R%a,%i,%D"},
- {31, 32, ALL, "CMPU", 0, icmp3},
- {10, 0, 0, "CMPU", 0, "R%a,%I,%D"},
- {31, 26, ALL, "CNTLZ%C", gencc, ir2},
- {19, 257, ALL, "CRAND", gen, cr3op},
- {19, 129, ALL, "CRANDN", gen, cr3op},
- {19, 289, ALL, "CREQV", gen, cr3op},
- {19, 225, ALL, "CRNAND", gen, cr3op},
- {19, 33, ALL, "CRNOR", gen, cr3op},
- {19, 449, ALL, "CROR", gen, cr3op},
- {19, 417, ALL, "CRORN", gen, cr3op},
- {19, 193, ALL, "CRXOR", gen, cr3op},
- {31, 86, ALL, "DCBF", dcb, 0},
- {31, 470, ALL, "DCBI", dcb, 0},
- {31, 54, ALL, "DCBST", dcb, 0},
- {31, 278, ALL, "DCBT", dcb, 0},
- {31, 246, ALL, "DCBTST", dcb, 0},
- {31, 1014, ALL, "DCBZ", dcb, 0},
- {31, 454, ALL, "DCCCI", dcb, 0},
- {31, 966, ALL, "ICCCI", dcb, 0},
- {31, 331, OEM, "DIV%V%C", qdiv, ir3}, /* POWER */
- {31, 363, OEM, "DIVS%V%C", qdiv, ir3}, /* POWER */
- {31, 491, OEM, "DIVW%V%C", qdiv, ir3},
- {31, 459, OEM, "DIVWU%V%C", qdiv, ir3},
- {31, 264, OEM, "DOZ%V%C", gencc, ir3r}, /* POWER */
- {9, 0, 0, "DOZ", gen, ir2i}, /* POWER */
- {31, 310, ALL, "ECIWX", ldx, 0},
- {31, 438, ALL, "ECOWX", stx, 0},
- {31, 854, ALL, "EIEIO", gen, 0},
- {31, 284, ALL, "EQV%C", gencc, il3},
- {31, 954, ALL, "EXTSB%C", gencc, il2},
- {31, 922, ALL, "EXTSH%C", gencc, il2},
- {63, 264, ALL, "FABS%C", gencc, fp2},
- {63, 21, ALL, "FADD%C", gencc, fp3},
- {59, 21, ALL, "FADDS%C", gencc, fp3},
- {63, 32, ALL, "FCMPO", gen, fpcmp},
- {63, 0, ALL, "FCMPU", gen, fpcmp},
- {63, 14, ALL, "FCTIW%C", gencc, fp2},
- {63, 15, ALL, "FCTIWZ%C", gencc, fp2},
- {63, 18, ALL, "FDIV%C", gencc, fp3},
- {59, 18, ALL, "FDIVS%C", gencc, fp3},
- {63, 29, FP4, "FMADD%C", gencc, fp4},
- {59, 29, FP4, "FMADDS%C", gencc, fp4},
- {63, 72, ALL, "FMOVD%C", gencc, fp2},
- {63, 28, FP4, "FMSUB%C", gencc, fp4},
- {59, 28, FP4, "FMSUBS%C", gencc, fp4},
- {63, 25, FP4, "FMUL%C", gencc, fp3c},
- {59, 25, FP4, "FMULS%C", gencc, fp3c},
- {63, 136, ALL, "FNABS%C", gencc, fp2},
- {63, 40, ALL, "FNEG%C", gencc, fp2},
- {63, 31, FP4, "FNMADD%C", gencc, fp4},
- {59, 31, FP4, "FNMADDS%C", gencc, fp4},
- {63, 30, FP4, "FNMSUB%C", gencc, fp4},
- {59, 30, FP4, "FNMSUBS%C", gencc, fp4},
- {63, 12, ALL, "FRSP%C", gencc, fp2},
- {63, 20, FP4, "FSUB%C", gencc, fp3},
- {59, 20, FP4, "FSUBS%C", gencc, fp3},
- {31, 982, ALL, "ICBI", dcb, 0},
- {19, 150, ALL, "ISYNC", gen, 0},
- {34, 0, 0, "MOVBZ", load, ldop},
- {35, 0, 0, "MOVBZU", load, ldop},
- {31, 119, ALL, "MOVBZU", ldx, 0},
- {31, 87, ALL, "MOVBZ", ldx, 0},
- {50, 0, 0, "FMOVD", fload, fldop},
- {51, 0, 0, "FMOVDU", fload, fldop},
- {31, 631, ALL, "FMOVDU", fldx, 0},
- {31, 599, ALL, "FMOVD", fldx, 0},
- {48, 0, 0, "FMOVS", load, fldop},
- {49, 0, 0, "FMOVSU", load, fldop},
- {31, 567, ALL, "FMOVSU", fldx, 0},
- {31, 535, ALL, "FMOVS", fldx, 0},
- {42, 0, 0, "MOVH", load, ldop},
- {43, 0, 0, "MOVHU", load, ldop},
- {31, 375, ALL, "MOVHU", ldx, 0},
- {31, 343, ALL, "MOVH", ldx, 0},
- {31, 790, ALL, "MOVHBR", ldx, 0},
- {40, 0, 0, "MOVHZ", load, ldop},
- {41, 0, 0, "MOVHZU", load, ldop},
- {31, 311, ALL, "MOVHZU", ldx, 0},
- {31, 279, ALL, "MOVHZ", ldx, 0},
- {46, 0, 0, "MOVMW", load, ldop},
- {31, 277, ALL, "LSCBX%C", ldx, 0}, /* POWER */
- {31, 597, ALL, "LSW", gen, "(R%a),$%n,R%d"},
- {31, 533, ALL, "LSW", ldx, 0},
- {31, 20, ALL, "LWAR", ldx, 0},
- {31, 534, ALL, "MOVWBR", ldx, 0},
- {32, 0, 0, "MOVW", load, ldop},
- {33, 0, 0, "MOVWU", load, ldop},
- {31, 55, ALL, "MOVWU", ldx, 0},
- {31, 23, ALL, "MOVW", ldx, 0},
- {31, 29, ALL, "MASKG%C", gencc, "R%s:R%b,R%d"}, /* POWER */
- {31, 541, ALL, "MASKIR%C", gencc, "R%s,R%b,R%a"}, /* POWER */
- {19, 0, ALL, "MOVFL", gen, "%S,%D"},
- {63, 64, ALL, "MOVCRFS", gen, "%S,%D"},
- {31, 512, ALL, "MOVW", gen, "XER,%D"},
- {31, 19, ALL, "MOVW", gen, "CR,R%d"},
- {63, 583, ALL, "MOVW%C", gen, "FPSCR, F%d"}, /* mffs */
- {31, 83, ALL, "MOVW", gen, "MSR,R%d"},
- {31, 339, ALL, "MOVW", gen, "%P,R%d"},
- {31, 595, ALL, "MOVW", gen, "SEG(%a),R%d"},
- {31, 659, ALL, "MOVW", gen, "SEG(R%b),R%d"},
- {31, 323, ALL, "MOVW", gen, "DCR(%Q),R%d"},
- {31, 451, ALL, "MOVW", gen, "R%s,DCR(%Q)"},
- {31, 144, ALL, "MOVFL", gen, "R%s,%m,CR"},
- {63, 70, ALL, "MTFSB0%C", gencc, "%D"},
- {63, 38, ALL, "MTFSB1%C", gencc, "%D"},
- {63, 711, ALL, "MOVFL%C", gencc, "F%b,%M,FPSCR"}, /* mtfsf */
- {63, 134, ALL, "MOVFL%C", gencc, "%K,%D"},
- {31, 146, ALL, "MOVW", gen, "R%s,MSR"},
- {31, 467, ALL, "MOVW", gen, "R%s,%P"},
- {31, 210, ALL, "MOVW", gen, "R%s,SEG(%a)"},
- {31, 242, ALL, "MOVW", gen, "R%s,SEG(R%b)"},
- {31, 107, OEM, "MUL%V%C", gencc, ir3}, /* POWER */
- {31, 75, ALL, "MULHW%C", gencc, ir3}, /* POWER */
- {31, 11, ALL, "MULHWU%C", gencc, ir3}, /* POWER */
- {31, 235, OEM, "MULLW%V%C", gencc, ir3},
- {7, 0, 0, "MULLW", qdiv, "%i,R%a,R%d"},
- {31, 488, OEM, "NABS%V%C", neg, ir2}, /* POWER */
- {31, 476, ALL, "NAND%C", gencc, il3},
- {31, 104, OEM, "NEG%V%C", neg, ir2},
- {31, 124, ALL, "NOR%C", gencc, il3},
- {31, 444, ALL, "OR%C", or, il3},
- {31, 412, ALL, "ORN%C", or, il3},
- {24, 0, 0, "OR", and, "%I,R%d,R%a"},
- {25, 0, 0, "OR", shifted, 0},
- {19, 50, ALL, "RFI", gen, 0},
- {19, 51, ALL, "RFCI", gen, 0},
- {22, 0, 0, "RLMI%C", gencc, rlim}, /* POWER */
- {20, 0, 0, "RLWMI%C", gencc, rlimi},
- {21, 0, 0, "RLWNM%C", gencc, rlimi},
- {23, 0, 0, "RLWNM%C", gencc, rlim},
- {31, 537, ALL, "RRIB%C", gencc, il3}, /* POWER */
- {17, 1, ALL, "SYSCALL", gen, 0},
- {31, 153, ALL, "SLE%C", shift, il3}, /* POWER */
- {31, 217, ALL, "SLEQ%C", shift, il3}, /* POWER */
- {31, 184, ALL, "SLQ%C", shifti, il3s}, /* POWER */
- {31, 248, ALL, "SLLQ%C", shifti, il3s}, /* POWER */
- {31, 216, ALL, "SLLQ%C", shift, il3}, /* POWER */
- {31, 152, ALL, "SLQ%C", shift, il3}, /* POWER */
- {31, 24, ALL, "SLW%C", shift, il3},
- {31, 920, ALL, "SRAQ%C", shift, il3}, /* POWER */
- {31, 952, ALL, "SRAQ%C", shifti, il3s}, /* POWER */
- {31, 792, ALL, "SRAW%C", shift, il3},
- {31, 824, ALL, "SRAW%C", shifti, il3s},
- {31, 665, ALL, "SRE%C", shift, il3}, /* POWER */
- {31, 921, ALL, "SREA%C", shift, il3}, /* POWER */
- {31, 729, ALL, "SREQ%C", shift, il3}, /* POWER */
- {31, 696, ALL, "SRQ%C", shifti, il3s}, /* POWER */
- {31, 760, ALL, "SRLQ%C", shifti, il3s}, /* POWER */
- {31, 728, ALL, "SRLQ%C", shift, il3}, /* POWER */
- {31, 664, ALL, "SRQ%C", shift, il3}, /* POWER */
- {31, 536, ALL, "SRW%C", shift, il3},
- {38, 0, 0, "MOVB", store, stop},
- {39, 0, 0, "MOVBU", store, stop},
- {31, 247, ALL, "MOVBU", stx, 0},
- {31, 215, ALL, "MOVB", stx, 0},
- {54, 0, 0, "FMOVD", fstore, fstop},
- {55, 0, 0, "FMOVDU", fstore, fstop},
- {31, 759, ALL, "FMOVDU", fstx, 0},
- {31, 727, ALL, "FMOVD", fstx, 0},
- {52, 0, 0, "FMOVS", fstore, fstop},
- {53, 0, 0, "FMOVSU", fstore, fstop},
- {31, 695, ALL, "FMOVSU", fstx, 0},
- {31, 663, ALL, "FMOVS", fstx, 0},
- {44, 0, 0, "MOVH", store, stop},
- {31, 918, ALL, "MOVHBR", stx, 0},
- {45, 0, 0, "MOVHU", store, stop},
- {31, 439, ALL, "MOVHU", stx, 0},
- {31, 407, ALL, "MOVH", stx, 0},
- {47, 0, 0, "MOVMW", store, stop},
- {31, 725, ALL, "STSW", gen, "R%d,$%n,(R%a)"},
- {31, 661, ALL, "STSW", stx, 0},
- {36, 0, 0, "MOVW", store, stop},
- {31, 662, ALL, "MOVWBR", stx, 0},
- {31, 150, ALL, "STWCCC", stx, 0},
- {37, 0, 0, "MOVWU", store, stop},
- {31, 183, ALL, "MOVWU", stx, 0},
- {31, 151, ALL, "MOVW", stx, 0},
- {31, 40, OEM, "SUB%V%C", sub, ir3},
- {31, 8, OEM, "SUBC%V%C", sub, ir3},
- {31, 136, OEM, "SUBE%V%C", sub, ir3},
- {8, 0, 0, "SUBC", gen, "R%a,%i,R%d"},
- {31, 232, OEM, "SUBME%V%C", sub, ir2},
- {31, 200, OEM, "SUBZE%V%C", sub, ir2},
- {31, 598, ALL, "SYNC", gen, 0},
- {31, 370, ALL, "TLBIA", gen, 0},
- {31, 306, ALL, "TLBIE", gen, "R%b"},
- {31, 1010, ALL, "TLBLI", gen, "R%b"},
- {31, 978, ALL, "TLBLD", gen, "R%b"},
- {31, 4, ALL, "TW", gen, "%d,R%a,R%b"},
- {3, 0, 0, "TW", gen, "%d,R%a,%i"},
- {31, 316, ALL, "XOR", and, il3},
- {26, 0, 0, "XOR", and, il2u},
- {27, 0, 0, "XOR", shifted, 0},
- {0},
- };
- typedef struct Spr Spr;
- struct Spr {
- int n;
- char *name;
- };
- static Spr sprname[] = {
- {0, "MQ"},
- {1, "XER"},
- {268, "TBL"},
- {269, "TBU"},
- {8, "LR"},
- {9, "CTR"},
- {528, "IBAT0U"},
- {529, "IBAT0L"},
- {530, "IBAT1U"},
- {531, "IBAT1L"},
- {532, "IBAT2U"},
- {533, "IBAT2L"},
- {534, "IBAT3U"},
- {535, "IBAT3L"},
- {536, "DBAT0U"},
- {537, "DBAT0L"},
- {538, "DBAT1U"},
- {539, "DBAT1L"},
- {540, "DBAT2U"},
- {541, "DBAT2L"},
- {542, "DBAT3U"},
- {543, "DBAT3L"},
- {25, "SDR1"},
- {19, "DAR"},
- {272, "SPRG0"},
- {273, "SPRG1"},
- {274, "SPRG2"},
- {275, "SPRG3"},
- {18, "DSISR"},
- {26, "SRR0"},
- {27, "SRR1"},
- {284, "TBLW"},
- {285, "TBUW"},
- {22, "DEC"},
- {282, "EAR"},
- {1008, "HID0"},
- {1009, "HID1"},
- {976, "DMISS"},
- {977, "DCMP"},
- {978, "HASH1"},
- {979, "HASH2"},
- {980, "IMISS"},
- {981, "ICMP"},
- {982, "RPA"},
- {1010, "IABR"},
- {1013, "DABR"},
- {0,0},
- };
- static void
- format(char *mnemonic, Instr *i, char *f)
- {
- int n, s;
- ulong mask;
- if (mnemonic)
- format(0, i, mnemonic);
- if (f == 0)
- return;
- if (mnemonic)
- bprint(i, "\t");
- for ( ; *f; f++) {
- if (*f != '%') {
- bprint(i, "%c", *f);
- continue;
- }
- switch (*++f) {
- case 'V':
- if(i->oe)
- bprint(i, "V");
- break;
- case 'C':
- if(i->rc)
- bprint(i, "CC");
- break;
- case 'a':
- bprint(i, "%d", i->ra);
- break;
- case 'b':
- bprint(i, "%d", i->rb);
- break;
- case 'c':
- bprint(i, "%d", i->frc);
- break;
- case 'd':
- case 's':
- bprint(i, "%d", i->rd);
- break;
- case 'S':
- if(i->ra & 3)
- bprint(i, "CR(INVAL:%d)", i->ra);
- else if(i->op == 63)
- bprint(i, "FPSCR(%d)", i->crfs);
- else
- bprint(i, "CR(%d)", i->crfs);
- break;
- case 'D':
- if(i->rd & 3)
- bprint(i, "CR(INVAL:%d)", i->rd);
- else if(i->op == 63)
- bprint(i, "FPSCR(%d)", i->crfd);
- else
- bprint(i, "CR(%d)", i->crfd);
- break;
- case 'l':
- if(i->simm < 0)
- bprint(i, "-%x(R%d)", -i->simm, i->ra);
- else
- bprint(i, "%x(R%d)", i->simm, i->ra);
- break;
- case 'i':
- bprint(i, "$%d", i->simm);
- break;
- case 'I':
- bprint(i, "$%ux", i->uimm);
- break;
- case 'w':
- bprint(i, "[%lux]", i->w0);
- break;
- case 'P':
- n = ((i->spr&0x1f)<<5)|((i->spr>>5)&0x1f);
- for(s=0; sprname[s].name; s++)
- if(sprname[s].n == n)
- break;
- if(sprname[s].name) {
- if(s < 10)
- bprint(i, sprname[s].name);
- else
- bprint(i, "SPR(%s)", sprname[s].name);
- } else
- bprint(i, "SPR(%d)", n);
- break;
- case 'Q':
- n = ((i->spr&0x1f)<<5)|((i->spr>>5)&0x1f);
- bprint(i, "%d", n);
- break;
- case 'n':
- bprint(i, "%d", i->nb==0? 32: i->nb); /* eg, pg 10-103 */
- break;
- case 'm':
- bprint(i, "%ux", i->crm);
- break;
- case 'M':
- bprint(i, "%ux", i->fm);
- break;
- case 'z':
- if(i->mb <= i->me)
- mask = ((ulong)~0L>>i->mb) & (~0L<<(31-i->me));
- else
- mask = ~(((ulong)~0L>>(i->me+1)) & (~0L<<(31-(i->mb-1))));
- bprint(i, "%lux", mask);
- break;
- case 'k':
- bprint(i, "%d", i->sh);
- break;
- case 'K':
- bprint(i, "$%x", i->imm);
- break;
- case 'L':
- if(i->lk)
- bprint(i, "L");
- break;
- case 'j':
- if(i->aa)
- pglobal(i, i->li, 1, "(SB)");
- else
- pglobal(i, i->addr+i->li, 1, "");
- break;
- case 'J':
- if(i->aa)
- pglobal(i, i->bd, 1, "(SB)");
- else
- pglobal(i, i->addr+i->bd, 1, "");
- break;
- case '\0':
- bprint(i, "%%");
- return;
- default:
- bprint(i, "%%%c", *f);
- break;
- }
- }
- }
- static int
- printins(Map *map, uvlong pc, char *buf, int n)
- {
- Instr i;
- Opcode *o;
- mymap = map;
- memset(&i, 0, sizeof(i));
- i.curr = buf;
- i.end = buf+n-1;
- if(mkinstr(pc, &i) < 0)
- return -1;
- for(o = opcodes; o->mnemonic != 0; o++)
- if(i.op == o->op && (i.xo & o->xomask) == o->xo) {
- if (o->f)
- (*o->f)(o, &i);
- else
- format(o->mnemonic, &i, o->ken);
- return i.size*4;
- }
- bprint(&i, "unknown %lux", i.w0);
- return i.size*4;
- }
- static int
- powerinst(Map *map, uvlong pc, char modifier, char *buf, int n)
- {
- USED(modifier);
- return printins(map, pc, buf, n);
- }
- static int
- powerdas(Map *map, uvlong pc, char *buf, int n)
- {
- Instr instr;
- mymap = map;
- memset(&instr, 0, sizeof(instr));
- instr.curr = buf;
- instr.end = buf+n-1;
- if (mkinstr(pc, &instr) < 0)
- return -1;
- if (instr.end-instr.curr > 8)
- instr.curr = _hexify(instr.curr, instr.w0, 7);
- if (instr.end-instr.curr > 9 && instr.size == 2) {
- *instr.curr++ = ' ';
- instr.curr = _hexify(instr.curr, instr.w1, 7);
- }
- *instr.curr = 0;
- return instr.size*4;
- }
- static int
- powerinstlen(Map *map, uvlong pc)
- {
- Instr i;
- mymap = map;
- if (mkinstr(pc, &i) < 0)
- return -1;
- return i.size*4;
- }
- static int
- powerfoll(Map *map, uvlong pc, Rgetter rget, uvlong *foll)
- {
- char *reg;
- Instr i;
- mymap = map;
- if (mkinstr(pc, &i) < 0)
- return -1;
- foll[0] = pc+4;
- foll[1] = pc+4;
- switch(i.op) {
- default:
- return 1;
- case 18: /* branch */
- foll[0] = i.li;
- if(!i.aa)
- foll[0] += pc;
- break;
-
- case 16: /* conditional branch */
- foll[0] = i.bd;
- if(!i.aa)
- foll[0] += pc;
- break;
- case 19: /* conditional branch to register */
- if(i.xo == 528)
- reg = "CTR";
- else if(i.xo == 16)
- reg = "LR";
- else
- return 1; /* not a branch */
- foll[0] = (*rget)(map, reg);
- break;
- }
- if(i.lk)
- return 2;
- return 1;
- }
|