123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535 |
- #include <lib9.h>
- typedef struct Instr Instr;
- struct Instr
- {
- ulong w;
- ulong addr;
- uchar op; /* super opcode */
- uchar cond; /* bits 28-31 */
- uchar store; /* bit 20 */
- uchar rd; /* bits 12-15 */
- uchar rn; /* bits 16-19 */
- uchar rs; /* bits 0-11 */
- long imm; /* rotated imm */
- char* curr; /* fill point in buffer */
- char* end; /* end of buffer */
- char* err; /* error message */
- };
- typedef struct Opcode Opcode;
- struct Opcode
- {
- char* o;
- void (*f)(Opcode*, Instr*);
- char* a;
- };
- static void format(char*, Instr*, char*);
- static int arminst(ulong, char, char*, int);
- static int armdas(ulong, char*, int);
- static
- char* cond[16] =
- {
- "EQ", "NE", "CS", "CC",
- "MI", "PL", "VS", "VC",
- "HI", "LS", "GE", "LT",
- "GT", "LE", 0, "NV"
- };
- static
- char* shtype[4] =
- {
- "<<", ">>", "->", "@>"
- };
- static int
- get4(ulong addr, long *v)
- {
- *v = *(ulong*)addr;
- return 1;
- }
- static char *
- _hexify(char *buf, ulong p, int zeros)
- {
- ulong d;
- d = p/16;
- if(d)
- buf = _hexify(buf, d, zeros-1);
- else
- while(zeros--)
- *buf++ = '0';
- *buf++ = "0123456789abcdef"[p&0x0f];
- return buf;
- }
- int
- armclass(long w)
- {
- int op;
- op = (w >> 25) & 0x7;
- switch(op) {
- case 0: /* data processing r,r,r */
- op = ((w >> 4) & 0xf);
- if(op == 0x9) {
- op = 48+16; /* mul */
- if(w & (1<<24)) {
- op += 2;
- if(w & (1<<22))
- op++; /* swap */
- break;
- }
- if(w & (1<<21))
- op++; /* mla */
- break;
- }
- op = (w >> 21) & 0xf;
- if(w & (1<<4))
- op += 32;
- else
- if(w & (31<<7))
- op += 16;
- break;
- case 1: /* data processing i,r,r */
- op = (48) + ((w >> 21) & 0xf);
- break;
- case 2: /* load/store byte/word i(r) */
- op = (48+20) + ((w >> 22) & 0x1) + ((w >> 19) & 0x2);
- break;
- case 3: /* load/store byte/word (r)(r) */
- op = (48+20+4) + ((w >> 22) & 0x1) + ((w >> 19) & 0x2);
- break;
- case 4: /* block data transfer (r)(r) */
- op = (48+20+4+4) + ((w >> 20) & 0x1);
- break;
- case 5: /* branch / branch link */
- op = (48+20+4+4+2) + ((w >> 24) & 0x1);
- break;
- case 7: /* coprocessor crap */
- op = (48+20+4+4+2+2) + ((w >> 3) & 0x2) + ((w >> 20) & 0x1);
- break;
- default:
- op = (48+20+4+4+2+2+4);
- break;
- }
- return op;
- }
- static int
- decode(ulong pc, Instr *i)
- {
- long w;
- get4(pc, &w);
- i->w = w;
- i->addr = pc;
- i->cond = (w >> 28) & 0xF;
- i->op = armclass(w);
- return 1;
- }
- 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 void
- armdps(Opcode *o, Instr *i)
- {
- i->store = (i->w >> 20) & 1;
- i->rn = (i->w >> 16) & 0xf;
- i->rd = (i->w >> 12) & 0xf;
- i->rs = (i->w >> 0) & 0xf;
- if(i->rn == 15 && i->rs == 0) {
- if(i->op == 8) {
- format("MOVW", i,"CPSR, R%d");
- return;
- } else
- if(i->op == 10) {
- format("MOVW", i,"SPSR, R%d");
- return;
- }
- } else
- if(i->rn == 9 && i->rd == 15) {
- if(i->op == 9) {
- format("MOVW", i, "R%s, CPSR");
- return;
- } else
- if(i->op == 11) {
- format("MOVW", i, "R%s, SPSR");
- return;
- }
- }
- format(o->o, i, o->a);
- }
- static void
- armdpi(Opcode *o, Instr *i)
- {
- ulong v;
- int c;
- v = (i->w >> 0) & 0xff;
- c = (i->w >> 8) & 0xf;
- while(c) {
- v = (v<<30) | (v>>2);
- c--;
- }
- i->imm = v;
- i->store = (i->w >> 20) & 1;
- i->rn = (i->w >> 16) & 0xf;
- i->rd = (i->w >> 12) & 0xf;
- i->rs = i->w&0x0f;
- /* RET is encoded as ADD #0,R14,R15 */
- if(i->w == 0xe282f000){
- format("RET", i, "");
- return;
- } else
- format(o->o, i, o->a);
- }
- static void
- armsdti(Opcode *o, Instr *i)
- {
- ulong v;
- v = (i->w >> 0) & 0xfff;
- if(!(i->w & (1<<23)))
- v = -v;
- i->store = ((i->w >> 23) & 0x2) | ((i->w >>21) & 0x1);
- i->imm = v;
- i->rn = (i->w >> 16) & 0xf;
- i->rd = (i->w >> 12) & 0xf;
- /* convert load of offset(PC) to a load immediate */
- if(i->rn == 15 && (i->w & (1<<20)) && get4(i->addr+v+8, &i->imm) > 0)
- format(o->o, i, "$#%i,R%d");
- else
- format(o->o, i, o->a);
- }
- static void
- armsdts(Opcode *o, Instr *i)
- {
- i->store = ((i->w >> 23) & 0x2) | ((i->w >>21) & 0x1);
- i->rs = (i->w >> 0) & 0xf;
- i->rn = (i->w >> 16) & 0xf;
- i->rd = (i->w >> 12) & 0xf;
- format(o->o, i, o->a);
- }
- static void
- armbdt(Opcode *o, Instr *i)
- {
- i->store = (i->w >> 21) & 0x3; /* S & W bits */
- i->rn = (i->w >> 16) & 0xf;
- i->imm = i->w & 0xffff;
- if(i->w == 0xe8fd8000)
- format("RFE", i, "");
- else
- format(o->o, i, o->a);
- }
- static void
- armund(Opcode *o, Instr *i)
- {
- format(o->o, i, o->a);
- }
- static void
- armcdt(Opcode *o, Instr *i)
- {
- format(o->o, i, o->a);
- }
- static void
- armunk(Opcode *o, Instr *i)
- {
- format(o->o, i, o->a);
- }
- static void
- armb(Opcode *o, Instr *i)
- {
- ulong v;
- v = i->w & 0xffffff;
- if(v & 0x800000)
- v |= ~0xffffff;
- i->imm = (v<<2) + i->addr + 8;
- format(o->o, i, o->a);
- }
- static void
- armco(Opcode *o, Instr *i) /* coprocessor instructions */
- {
- int op, p, cp;
- char buf[1024];
- i->rn = (i->w >> 16) & 0xf;
- i->rd = (i->w >> 12) & 0xf;
- i->rs = i->w&0xf;
- cp = (i->w >> 8) & 0xf;
- p = (i->w >> 5) & 0x7;
- if(i->w&0x10) {
- op = (i->w >> 20) & 0x0f;
- snprint(buf, sizeof(buf), "#%x, #%x, R%d, C(%d), C(%d), #%x\n", cp, op, i->rd, i->rn, i->rs, p);
- } else {
- op = (i->w >> 21) & 0x07;
- snprint(buf, sizeof(buf), "#%x, #%x, C(%d), C(%d), C(%d), #%x\n", cp, op, i->rd, i->rn, i->rs, p);
- }
- format(o->o, i, buf);
- }
- static Opcode opcodes[] =
- {
- "AND%C%S", armdps, "R%s,R%n,R%d",
- "EOR%C%S", armdps, "R%s,R%n,R%d",
- "SUB%C%S", armdps, "R%s,R%n,R%d",
- "RSB%C%S", armdps, "R%s,R%n,R%d",
- "ADD%C%S", armdps, "R%s,R%n,R%d",
- "ADC%C%S", armdps, "R%s,R%n,R%d",
- "SBC%C%S", armdps, "R%s,R%n,R%d",
- "RSC%C%S", armdps, "R%s,R%n,R%d",
- "TST%C%S", armdps, "R%s,R%n,",
- "TEQ%C%S", armdps, "R%s,R%n,",
- "CMP%C%S", armdps, "R%s,R%n,",
- "CMN%C%S", armdps, "R%s,R%n,",
- "ORR%C%S", armdps, "R%s,R%n,R%d",
- "MOVW%C%S", armdps, "R%s,R%d",
- "BIC%C%S", armdps, "R%s,R%n,R%d",
- "MVN%C%S", armdps, "R%s,R%d",
- "AND%C%S", armdps, "(R%s%h#%m),R%n,R%d",
- "EOR%C%S", armdps, "(R%s%h#%m),R%n,R%d",
- "SUB%C%S", armdps, "(R%s%h#%m),R%n,R%d",
- "RSB%C%S", armdps, "(R%s%h#%m),R%n,R%d",
- "ADD%C%S", armdps, "(R%s%h#%m),R%n,R%d",
- "ADC%C%S", armdps, "(R%s%h#%m),R%n,R%d",
- "SBC%C%S", armdps, "(R%s%h#%m),R%n,R%d",
- "RSC%C%S", armdps, "(R%s%h#%m),R%n,R%d",
- "TST%C%S", armdps, "(R%s%h#%m),R%n,",
- "TEQ%C%S", armdps, "(R%s%h#%m),R%n,",
- "CMP%C%S", armdps, "(R%s%h#%m),R%n,",
- "CMN%C%S", armdps, "(R%s%h#%m),R%n,",
- "ORR%C%S", armdps, "(R%s%h#%m),R%n,R%d",
- "MOVW%C%S", armdps, "(R%s%h#%m),R%d",
- "BIC%C%S", armdps, "(R%s%h#%m),R%n,R%d",
- "MVN%C%S", armdps, "(R%s%h#%m),R%d",
- "AND%C%S", armdps, "(R%s%hR%m),R%n,R%d",
- "EOR%C%S", armdps, "(R%s%hR%m),R%n,R%d",
- "SUB%C%S", armdps, "(R%s%hR%m),R%n,R%d",
- "RSB%C%S", armdps, "(R%s%hR%m),R%n,R%d",
- "ADD%C%S", armdps, "(R%s%hR%m),R%n,R%d",
- "ADC%C%S", armdps, "(R%s%hR%m),R%n,R%d",
- "SBC%C%S", armdps, "(R%s%hR%m),R%n,R%d",
- "RSC%C%S", armdps, "(R%s%hR%m),R%n,R%d",
- "TST%C%S", armdps, "(R%s%hR%m),R%n,",
- "TEQ%C%S", armdps, "(R%s%hR%m),R%n,",
- "CMP%C%S", armdps, "(R%s%hR%m),R%n,",
- "CMN%C%S", armdps, "(R%s%hR%m),R%n,",
- "ORR%C%S", armdps, "(R%s%hR%m),R%n,R%d",
- "MOVW%C%S", armdps, "(R%s%hR%m),R%d",
- "BIC%C%S", armdps, "(R%s%hR%m),R%n,R%d",
- "MVN%C%S", armdps, "(R%s%hR%m),R%d",
- "AND%C%S", armdpi, "$#%i,R%n,R%d",
- "EOR%C%S", armdpi, "$#%i,R%n,R%d",
- "SUB%C%S", armdpi, "$#%i,R%n,R%d",
- "RSB%C%S", armdpi, "$#%i,R%n,R%d",
- "ADD%C%S", armdpi, "$#%i,R%n,R%d",
- "ADC%C%S", armdpi, "$#%i,R%n,R%d",
- "SBC%C%S", armdpi, "$#%i,R%n,R%d",
- "RSC%C%S", armdpi, "$#%i,R%n,R%d",
- "TST%C%S", armdpi, "$#%i,R%n,",
- "TEQ%C%S", armdpi, "$#%i,R%n,",
- "CMP%C%S", armdpi, "$#%i,R%n,",
- "CMN%C%S", armdpi, "$#%i,R%n,",
- "ORR%C%S", armdpi, "$#%i,R%n,R%d",
- "MOVW%C%S", armdpi, "$#%i,,R%d",
- "BIC%C%S", armdpi, "$#%i,R%n,R%d",
- "MVN%C%S", armdpi, "$#%i,,R%d",
- "MUL%C%S", armdpi, "R%s,R%m,R%n",
- "MULA%C%S", armdpi, "R%s,R%m,R%n,R%d",
- "SWPW", armdpi, "R%s,(R%n),R%d",
- "SWPB", armdpi, "R%s,(R%n),R%d",
- "MOVW%C%p", armsdti,"R%d,#%i(R%n)",
- "MOVB%C%p", armsdti,"R%d,#%i(R%n)",
- "MOVW%C%p", armsdti,"#%i(R%n),R%d",
- "MOVB%C%p", armsdti,"#%i(R%n),R%d",
- "MOVW%C%p", armsdts,"R%d,%D(R%s%h#%m)(R%n)",
- "MOVB%C%p", armsdts,"R%d,%D(R%s%h#%m)(R%n)",
- "MOVW%C%p", armsdts,"%D(R%s%h#%m)(R%n),R%d",
- "MOVB%C%p", armsdts,"%D(R%s%h#%m)(R%n),R%d",
- "MOVM%C%P%a", armbdt, "R%n,[%r]",
- "MOVM%C%P%a", armbdt, "[%r],R%n",
- "B%C", armb, "%b",
- "BL%C", armb, "%b",
- "CDP%C", armco, "",
- "CDP%C", armco, "",
- "MCR%C", armco, "",
- "MRC%C", armco, "",
- "UNK", armunk, "",
- };
- static char *mode[] = { 0, "IA", "DB", "IB" };
- static char *pw[] = { "P", "PW", 0, "W" };
- static char *sw[] = { 0, "W", "S", "SW" };
- static void
- format(char *mnemonic, Instr *i, char *f)
- {
- int j, k, m, n;
- if(mnemonic)
- format(0, i, mnemonic);
- if(f == 0)
- return;
- if(mnemonic)
- if(i->curr < i->end)
- *i->curr++ = '\t';
- for ( ; *f && i->curr < i->end; f++) {
- if(*f != '%') {
- *i->curr++ = *f;
- continue;
- }
- switch (*++f) {
- case 'C': /* .CONDITION */
- if(cond[i->cond])
- bprint(i, ".%s", cond[i->cond]);
- break;
- case 'S': /* .STORE */
- if(i->store)
- bprint(i, ".S");
- break;
- case 'P': /* P & U bits for block move */
- n = (i->w >>23) & 0x3;
- if (mode[n])
- bprint(i, ".%s", mode[n]);
- break;
- case 'D': /* ~U bit for single data xfer */
- if((i->w & (1<<23)) == 0)
- bprint(i, "-");
- break;
- case 'p': /* P & W bits for single data xfer*/
- if (pw[i->store])
- bprint(i, ".%s", pw[i->store]);
- break;
- case 'a': /* S & W bits for single data xfer*/
- if (sw[i->store])
- bprint(i, ".%s", sw[i->store]);
- break;
- case 's':
- bprint(i, "%d", i->rs & 0xf);
- break;
-
- case 'm':
- bprint(i, "%d", (i->w>>7) & 0x1f);
- break;
- case 'h':
- bprint(i, "%s", shtype[(i->w>>5) & 0x3]);
- break;
- case 'n':
- bprint(i, "%d", i->rn);
- break;
- case 'd':
- bprint(i, "%d", i->rd);
- break;
- case 'i':
- bprint(i, "%lux", i->imm);
- break;
- case 'b':
- bprint(i, "%lux", i->imm);
- break;
- case 'r':
- n = i->imm&0xffff;
- j = 0;
- k = 0;
- while(n) {
- m = j;
- while(n&0x1) {
- j++;
- n >>= 1;
- }
- if(j != m) {
- if(k)
- bprint(i, ",");
- if(j == m+1)
- bprint(i, "R%d", m);
- else
- bprint(i, "R%d-R%d", m, j-1);
- k = 1;
- }
- j++;
- n >>= 1;
- }
- break;
- case '\0':
- *i->curr++ = '%';
- return;
- default:
- bprint(i, "%%%c", *f);
- break;
- }
- }
- *i->curr = 0;
- }
- void
- das(ulong *x, int n)
- {
- ulong pc;
- Instr i;
- char buf[128];
- pc = (ulong)x;
- while(n > 0) {
- i.curr = buf;
- i.end = buf+sizeof(buf)-1;
- if(decode(pc, &i) < 0)
- sprint(buf, "???");
- else
- (*opcodes[i.op].f)(&opcodes[i.op], &i);
- print("%.8lux %.8lux\t%s\n", pc, i.w, buf);
- pc += 4;
- n--;
- }
- }
|