das-arm.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535
  1. #include <lib9.h>
  2. typedef struct Instr Instr;
  3. struct Instr
  4. {
  5. ulong w;
  6. ulong addr;
  7. uchar op; /* super opcode */
  8. uchar cond; /* bits 28-31 */
  9. uchar store; /* bit 20 */
  10. uchar rd; /* bits 12-15 */
  11. uchar rn; /* bits 16-19 */
  12. uchar rs; /* bits 0-11 */
  13. long imm; /* rotated imm */
  14. char* curr; /* fill point in buffer */
  15. char* end; /* end of buffer */
  16. char* err; /* error message */
  17. };
  18. typedef struct Opcode Opcode;
  19. struct Opcode
  20. {
  21. char* o;
  22. void (*f)(Opcode*, Instr*);
  23. char* a;
  24. };
  25. static void format(char*, Instr*, char*);
  26. static int arminst(ulong, char, char*, int);
  27. static int armdas(ulong, char*, int);
  28. static
  29. char* cond[16] =
  30. {
  31. "EQ", "NE", "CS", "CC",
  32. "MI", "PL", "VS", "VC",
  33. "HI", "LS", "GE", "LT",
  34. "GT", "LE", 0, "NV"
  35. };
  36. static
  37. char* shtype[4] =
  38. {
  39. "<<", ">>", "->", "@>"
  40. };
  41. static int
  42. get4(ulong addr, long *v)
  43. {
  44. *v = *(ulong*)addr;
  45. return 1;
  46. }
  47. static char *
  48. _hexify(char *buf, ulong p, int zeros)
  49. {
  50. ulong d;
  51. d = p/16;
  52. if(d)
  53. buf = _hexify(buf, d, zeros-1);
  54. else
  55. while(zeros--)
  56. *buf++ = '0';
  57. *buf++ = "0123456789abcdef"[p&0x0f];
  58. return buf;
  59. }
  60. int
  61. armclass(long w)
  62. {
  63. int op;
  64. op = (w >> 25) & 0x7;
  65. switch(op) {
  66. case 0: /* data processing r,r,r */
  67. op = ((w >> 4) & 0xf);
  68. if(op == 0x9) {
  69. op = 48+16; /* mul */
  70. if(w & (1<<24)) {
  71. op += 2;
  72. if(w & (1<<22))
  73. op++; /* swap */
  74. break;
  75. }
  76. if(w & (1<<21))
  77. op++; /* mla */
  78. break;
  79. }
  80. op = (w >> 21) & 0xf;
  81. if(w & (1<<4))
  82. op += 32;
  83. else
  84. if(w & (31<<7))
  85. op += 16;
  86. break;
  87. case 1: /* data processing i,r,r */
  88. op = (48) + ((w >> 21) & 0xf);
  89. break;
  90. case 2: /* load/store byte/word i(r) */
  91. op = (48+20) + ((w >> 22) & 0x1) + ((w >> 19) & 0x2);
  92. break;
  93. case 3: /* load/store byte/word (r)(r) */
  94. op = (48+20+4) + ((w >> 22) & 0x1) + ((w >> 19) & 0x2);
  95. break;
  96. case 4: /* block data transfer (r)(r) */
  97. op = (48+20+4+4) + ((w >> 20) & 0x1);
  98. break;
  99. case 5: /* branch / branch link */
  100. op = (48+20+4+4+2) + ((w >> 24) & 0x1);
  101. break;
  102. case 7: /* coprocessor crap */
  103. op = (48+20+4+4+2+2) + ((w >> 3) & 0x2) + ((w >> 20) & 0x1);
  104. break;
  105. default:
  106. op = (48+20+4+4+2+2+4);
  107. break;
  108. }
  109. return op;
  110. }
  111. static int
  112. decode(ulong pc, Instr *i)
  113. {
  114. long w;
  115. get4(pc, &w);
  116. i->w = w;
  117. i->addr = pc;
  118. i->cond = (w >> 28) & 0xF;
  119. i->op = armclass(w);
  120. return 1;
  121. }
  122. static void
  123. bprint(Instr *i, char *fmt, ...)
  124. {
  125. va_list arg;
  126. va_start(arg, fmt);
  127. i->curr = vseprint(i->curr, i->end, fmt, arg);
  128. va_end(arg);
  129. }
  130. static void
  131. armdps(Opcode *o, Instr *i)
  132. {
  133. i->store = (i->w >> 20) & 1;
  134. i->rn = (i->w >> 16) & 0xf;
  135. i->rd = (i->w >> 12) & 0xf;
  136. i->rs = (i->w >> 0) & 0xf;
  137. if(i->rn == 15 && i->rs == 0) {
  138. if(i->op == 8) {
  139. format("MOVW", i,"CPSR, R%d");
  140. return;
  141. } else
  142. if(i->op == 10) {
  143. format("MOVW", i,"SPSR, R%d");
  144. return;
  145. }
  146. } else
  147. if(i->rn == 9 && i->rd == 15) {
  148. if(i->op == 9) {
  149. format("MOVW", i, "R%s, CPSR");
  150. return;
  151. } else
  152. if(i->op == 11) {
  153. format("MOVW", i, "R%s, SPSR");
  154. return;
  155. }
  156. }
  157. format(o->o, i, o->a);
  158. }
  159. static void
  160. armdpi(Opcode *o, Instr *i)
  161. {
  162. ulong v;
  163. int c;
  164. v = (i->w >> 0) & 0xff;
  165. c = (i->w >> 8) & 0xf;
  166. while(c) {
  167. v = (v<<30) | (v>>2);
  168. c--;
  169. }
  170. i->imm = v;
  171. i->store = (i->w >> 20) & 1;
  172. i->rn = (i->w >> 16) & 0xf;
  173. i->rd = (i->w >> 12) & 0xf;
  174. i->rs = i->w&0x0f;
  175. /* RET is encoded as ADD #0,R14,R15 */
  176. if(i->w == 0xe282f000){
  177. format("RET", i, "");
  178. return;
  179. } else
  180. format(o->o, i, o->a);
  181. }
  182. static void
  183. armsdti(Opcode *o, Instr *i)
  184. {
  185. ulong v;
  186. v = (i->w >> 0) & 0xfff;
  187. if(!(i->w & (1<<23)))
  188. v = -v;
  189. i->store = ((i->w >> 23) & 0x2) | ((i->w >>21) & 0x1);
  190. i->imm = v;
  191. i->rn = (i->w >> 16) & 0xf;
  192. i->rd = (i->w >> 12) & 0xf;
  193. /* convert load of offset(PC) to a load immediate */
  194. if(i->rn == 15 && (i->w & (1<<20)) && get4(i->addr+v+8, &i->imm) > 0)
  195. format(o->o, i, "$#%i,R%d");
  196. else
  197. format(o->o, i, o->a);
  198. }
  199. static void
  200. armsdts(Opcode *o, Instr *i)
  201. {
  202. i->store = ((i->w >> 23) & 0x2) | ((i->w >>21) & 0x1);
  203. i->rs = (i->w >> 0) & 0xf;
  204. i->rn = (i->w >> 16) & 0xf;
  205. i->rd = (i->w >> 12) & 0xf;
  206. format(o->o, i, o->a);
  207. }
  208. static void
  209. armbdt(Opcode *o, Instr *i)
  210. {
  211. i->store = (i->w >> 21) & 0x3; /* S & W bits */
  212. i->rn = (i->w >> 16) & 0xf;
  213. i->imm = i->w & 0xffff;
  214. if(i->w == 0xe8fd8000)
  215. format("RFE", i, "");
  216. else
  217. format(o->o, i, o->a);
  218. }
  219. static void
  220. armund(Opcode *o, Instr *i)
  221. {
  222. format(o->o, i, o->a);
  223. }
  224. static void
  225. armcdt(Opcode *o, Instr *i)
  226. {
  227. format(o->o, i, o->a);
  228. }
  229. static void
  230. armunk(Opcode *o, Instr *i)
  231. {
  232. format(o->o, i, o->a);
  233. }
  234. static void
  235. armb(Opcode *o, Instr *i)
  236. {
  237. ulong v;
  238. v = i->w & 0xffffff;
  239. if(v & 0x800000)
  240. v |= ~0xffffff;
  241. i->imm = (v<<2) + i->addr + 8;
  242. format(o->o, i, o->a);
  243. }
  244. static void
  245. armco(Opcode *o, Instr *i) /* coprocessor instructions */
  246. {
  247. int op, p, cp;
  248. char buf[1024];
  249. i->rn = (i->w >> 16) & 0xf;
  250. i->rd = (i->w >> 12) & 0xf;
  251. i->rs = i->w&0xf;
  252. cp = (i->w >> 8) & 0xf;
  253. p = (i->w >> 5) & 0x7;
  254. if(i->w&0x10) {
  255. op = (i->w >> 20) & 0x0f;
  256. snprint(buf, sizeof(buf), "#%x, #%x, R%d, C(%d), C(%d), #%x\n", cp, op, i->rd, i->rn, i->rs, p);
  257. } else {
  258. op = (i->w >> 21) & 0x07;
  259. snprint(buf, sizeof(buf), "#%x, #%x, C(%d), C(%d), C(%d), #%x\n", cp, op, i->rd, i->rn, i->rs, p);
  260. }
  261. format(o->o, i, buf);
  262. }
  263. static Opcode opcodes[] =
  264. {
  265. "AND%C%S", armdps, "R%s,R%n,R%d",
  266. "EOR%C%S", armdps, "R%s,R%n,R%d",
  267. "SUB%C%S", armdps, "R%s,R%n,R%d",
  268. "RSB%C%S", armdps, "R%s,R%n,R%d",
  269. "ADD%C%S", armdps, "R%s,R%n,R%d",
  270. "ADC%C%S", armdps, "R%s,R%n,R%d",
  271. "SBC%C%S", armdps, "R%s,R%n,R%d",
  272. "RSC%C%S", armdps, "R%s,R%n,R%d",
  273. "TST%C%S", armdps, "R%s,R%n,",
  274. "TEQ%C%S", armdps, "R%s,R%n,",
  275. "CMP%C%S", armdps, "R%s,R%n,",
  276. "CMN%C%S", armdps, "R%s,R%n,",
  277. "ORR%C%S", armdps, "R%s,R%n,R%d",
  278. "MOVW%C%S", armdps, "R%s,R%d",
  279. "BIC%C%S", armdps, "R%s,R%n,R%d",
  280. "MVN%C%S", armdps, "R%s,R%d",
  281. "AND%C%S", armdps, "(R%s%h#%m),R%n,R%d",
  282. "EOR%C%S", armdps, "(R%s%h#%m),R%n,R%d",
  283. "SUB%C%S", armdps, "(R%s%h#%m),R%n,R%d",
  284. "RSB%C%S", armdps, "(R%s%h#%m),R%n,R%d",
  285. "ADD%C%S", armdps, "(R%s%h#%m),R%n,R%d",
  286. "ADC%C%S", armdps, "(R%s%h#%m),R%n,R%d",
  287. "SBC%C%S", armdps, "(R%s%h#%m),R%n,R%d",
  288. "RSC%C%S", armdps, "(R%s%h#%m),R%n,R%d",
  289. "TST%C%S", armdps, "(R%s%h#%m),R%n,",
  290. "TEQ%C%S", armdps, "(R%s%h#%m),R%n,",
  291. "CMP%C%S", armdps, "(R%s%h#%m),R%n,",
  292. "CMN%C%S", armdps, "(R%s%h#%m),R%n,",
  293. "ORR%C%S", armdps, "(R%s%h#%m),R%n,R%d",
  294. "MOVW%C%S", armdps, "(R%s%h#%m),R%d",
  295. "BIC%C%S", armdps, "(R%s%h#%m),R%n,R%d",
  296. "MVN%C%S", armdps, "(R%s%h#%m),R%d",
  297. "AND%C%S", armdps, "(R%s%hR%m),R%n,R%d",
  298. "EOR%C%S", armdps, "(R%s%hR%m),R%n,R%d",
  299. "SUB%C%S", armdps, "(R%s%hR%m),R%n,R%d",
  300. "RSB%C%S", armdps, "(R%s%hR%m),R%n,R%d",
  301. "ADD%C%S", armdps, "(R%s%hR%m),R%n,R%d",
  302. "ADC%C%S", armdps, "(R%s%hR%m),R%n,R%d",
  303. "SBC%C%S", armdps, "(R%s%hR%m),R%n,R%d",
  304. "RSC%C%S", armdps, "(R%s%hR%m),R%n,R%d",
  305. "TST%C%S", armdps, "(R%s%hR%m),R%n,",
  306. "TEQ%C%S", armdps, "(R%s%hR%m),R%n,",
  307. "CMP%C%S", armdps, "(R%s%hR%m),R%n,",
  308. "CMN%C%S", armdps, "(R%s%hR%m),R%n,",
  309. "ORR%C%S", armdps, "(R%s%hR%m),R%n,R%d",
  310. "MOVW%C%S", armdps, "(R%s%hR%m),R%d",
  311. "BIC%C%S", armdps, "(R%s%hR%m),R%n,R%d",
  312. "MVN%C%S", armdps, "(R%s%hR%m),R%d",
  313. "AND%C%S", armdpi, "$#%i,R%n,R%d",
  314. "EOR%C%S", armdpi, "$#%i,R%n,R%d",
  315. "SUB%C%S", armdpi, "$#%i,R%n,R%d",
  316. "RSB%C%S", armdpi, "$#%i,R%n,R%d",
  317. "ADD%C%S", armdpi, "$#%i,R%n,R%d",
  318. "ADC%C%S", armdpi, "$#%i,R%n,R%d",
  319. "SBC%C%S", armdpi, "$#%i,R%n,R%d",
  320. "RSC%C%S", armdpi, "$#%i,R%n,R%d",
  321. "TST%C%S", armdpi, "$#%i,R%n,",
  322. "TEQ%C%S", armdpi, "$#%i,R%n,",
  323. "CMP%C%S", armdpi, "$#%i,R%n,",
  324. "CMN%C%S", armdpi, "$#%i,R%n,",
  325. "ORR%C%S", armdpi, "$#%i,R%n,R%d",
  326. "MOVW%C%S", armdpi, "$#%i,,R%d",
  327. "BIC%C%S", armdpi, "$#%i,R%n,R%d",
  328. "MVN%C%S", armdpi, "$#%i,,R%d",
  329. "MUL%C%S", armdpi, "R%s,R%m,R%n",
  330. "MULA%C%S", armdpi, "R%s,R%m,R%n,R%d",
  331. "SWPW", armdpi, "R%s,(R%n),R%d",
  332. "SWPB", armdpi, "R%s,(R%n),R%d",
  333. "MOVW%C%p", armsdti,"R%d,#%i(R%n)",
  334. "MOVB%C%p", armsdti,"R%d,#%i(R%n)",
  335. "MOVW%C%p", armsdti,"#%i(R%n),R%d",
  336. "MOVB%C%p", armsdti,"#%i(R%n),R%d",
  337. "MOVW%C%p", armsdts,"R%d,%D(R%s%h#%m)(R%n)",
  338. "MOVB%C%p", armsdts,"R%d,%D(R%s%h#%m)(R%n)",
  339. "MOVW%C%p", armsdts,"%D(R%s%h#%m)(R%n),R%d",
  340. "MOVB%C%p", armsdts,"%D(R%s%h#%m)(R%n),R%d",
  341. "MOVM%C%P%a", armbdt, "R%n,[%r]",
  342. "MOVM%C%P%a", armbdt, "[%r],R%n",
  343. "B%C", armb, "%b",
  344. "BL%C", armb, "%b",
  345. "CDP%C", armco, "",
  346. "CDP%C", armco, "",
  347. "MCR%C", armco, "",
  348. "MRC%C", armco, "",
  349. "UNK", armunk, "",
  350. };
  351. static char *mode[] = { 0, "IA", "DB", "IB" };
  352. static char *pw[] = { "P", "PW", 0, "W" };
  353. static char *sw[] = { 0, "W", "S", "SW" };
  354. static void
  355. format(char *mnemonic, Instr *i, char *f)
  356. {
  357. int j, k, m, n;
  358. if(mnemonic)
  359. format(0, i, mnemonic);
  360. if(f == 0)
  361. return;
  362. if(mnemonic)
  363. if(i->curr < i->end)
  364. *i->curr++ = '\t';
  365. for ( ; *f && i->curr < i->end; f++) {
  366. if(*f != '%') {
  367. *i->curr++ = *f;
  368. continue;
  369. }
  370. switch (*++f) {
  371. case 'C': /* .CONDITION */
  372. if(cond[i->cond])
  373. bprint(i, ".%s", cond[i->cond]);
  374. break;
  375. case 'S': /* .STORE */
  376. if(i->store)
  377. bprint(i, ".S");
  378. break;
  379. case 'P': /* P & U bits for block move */
  380. n = (i->w >>23) & 0x3;
  381. if (mode[n])
  382. bprint(i, ".%s", mode[n]);
  383. break;
  384. case 'D': /* ~U bit for single data xfer */
  385. if((i->w & (1<<23)) == 0)
  386. bprint(i, "-");
  387. break;
  388. case 'p': /* P & W bits for single data xfer*/
  389. if (pw[i->store])
  390. bprint(i, ".%s", pw[i->store]);
  391. break;
  392. case 'a': /* S & W bits for single data xfer*/
  393. if (sw[i->store])
  394. bprint(i, ".%s", sw[i->store]);
  395. break;
  396. case 's':
  397. bprint(i, "%d", i->rs & 0xf);
  398. break;
  399. case 'm':
  400. bprint(i, "%d", (i->w>>7) & 0x1f);
  401. break;
  402. case 'h':
  403. bprint(i, "%s", shtype[(i->w>>5) & 0x3]);
  404. break;
  405. case 'n':
  406. bprint(i, "%d", i->rn);
  407. break;
  408. case 'd':
  409. bprint(i, "%d", i->rd);
  410. break;
  411. case 'i':
  412. bprint(i, "%lux", i->imm);
  413. break;
  414. case 'b':
  415. bprint(i, "%lux", i->imm);
  416. break;
  417. case 'r':
  418. n = i->imm&0xffff;
  419. j = 0;
  420. k = 0;
  421. while(n) {
  422. m = j;
  423. while(n&0x1) {
  424. j++;
  425. n >>= 1;
  426. }
  427. if(j != m) {
  428. if(k)
  429. bprint(i, ",");
  430. if(j == m+1)
  431. bprint(i, "R%d", m);
  432. else
  433. bprint(i, "R%d-R%d", m, j-1);
  434. k = 1;
  435. }
  436. j++;
  437. n >>= 1;
  438. }
  439. break;
  440. case '\0':
  441. *i->curr++ = '%';
  442. return;
  443. default:
  444. bprint(i, "%%%c", *f);
  445. break;
  446. }
  447. }
  448. *i->curr = 0;
  449. }
  450. void
  451. das(ulong *x, int n)
  452. {
  453. ulong pc;
  454. Instr i;
  455. char buf[128];
  456. pc = (ulong)x;
  457. while(n > 0) {
  458. i.curr = buf;
  459. i.end = buf+sizeof(buf)-1;
  460. if(decode(pc, &i) < 0)
  461. sprint(buf, "???");
  462. else
  463. (*opcodes[i.op].f)(&opcodes[i.op], &i);
  464. print("%.8lux %.8lux\t%s\n", pc, i.w, buf);
  465. pc += 4;
  466. n--;
  467. }
  468. }