5db.c 21 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072
  1. #include <u.h>
  2. #include <libc.h>
  3. #include <bio.h>
  4. #include <mach.h>
  5. static int debug = 0;
  6. #define BITS(a, b) ((1<<(b+1))-(1<<a))
  7. #define LSR(v, s) ((ulong)(v) >> (s))
  8. #define ASR(v, s) ((long)(v) >> (s))
  9. #define ROR(v, s) (LSR((v), (s)) | (((v) & ((1 << (s))-1)) << (32 - (s))))
  10. typedef struct Instr Instr;
  11. struct Instr
  12. {
  13. Map *map;
  14. ulong w;
  15. uvlong addr;
  16. uchar op; /* super opcode */
  17. uchar cond; /* bits 28-31 */
  18. uchar store; /* bit 20 */
  19. uchar rd; /* bits 12-15 */
  20. uchar rn; /* bits 16-19 */
  21. uchar rs; /* bits 0-11 (shifter operand) */
  22. long imm; /* rotated imm */
  23. char* curr; /* fill point in buffer */
  24. char* end; /* end of buffer */
  25. char* err; /* error message */
  26. };
  27. typedef struct Opcode Opcode;
  28. struct Opcode
  29. {
  30. char* o;
  31. void (*fmt)(Opcode*, Instr*);
  32. uvlong (*foll)(Map*, Rgetter, Instr*, uvlong);
  33. char* a;
  34. };
  35. static void format(char*, Instr*, char*);
  36. static char FRAMENAME[] = ".frame";
  37. /*
  38. * Arm-specific debugger interface
  39. */
  40. static char *armexcep(Map*, Rgetter);
  41. static int armfoll(Map*, uvlong, Rgetter, uvlong*);
  42. static int arminst(Map*, uvlong, char, char*, int);
  43. static int armdas(Map*, uvlong, char*, int);
  44. static int arminstlen(Map*, uvlong);
  45. /*
  46. * Debugger interface
  47. */
  48. Machdata armmach =
  49. {
  50. {0, 0, 0, 0xD}, /* break point */
  51. 4, /* break point size */
  52. leswab, /* short to local byte order */
  53. leswal, /* long to local byte order */
  54. leswav, /* long to local byte order */
  55. risctrace, /* C traceback */
  56. riscframe, /* Frame finder */
  57. armexcep, /* print exception */
  58. 0, /* breakpoint fixup */
  59. 0, /* single precision float printer */
  60. 0, /* double precision float printer */
  61. armfoll, /* following addresses */
  62. arminst, /* print instruction */
  63. armdas, /* dissembler */
  64. arminstlen, /* instruction size */
  65. };
  66. static char*
  67. armexcep(Map *map, Rgetter rget)
  68. {
  69. uvlong c;
  70. c = (*rget)(map, "TYPE");
  71. switch ((int)c&0x1f) {
  72. case 0x11:
  73. return "Fiq interrupt";
  74. case 0x12:
  75. return "Mirq interrupt";
  76. case 0x13:
  77. return "SVC/SWI Exception";
  78. case 0x17:
  79. return "Prefetch Abort/Data Abort";
  80. case 0x18:
  81. return "Data Abort";
  82. case 0x1b:
  83. return "Undefined instruction/Breakpoint";
  84. case 0x1f:
  85. return "Sys trap";
  86. default:
  87. return "Undefined trap";
  88. }
  89. }
  90. static
  91. char* cond[16] =
  92. {
  93. "EQ", "NE", "CS", "CC",
  94. "MI", "PL", "VS", "VC",
  95. "HI", "LS", "GE", "LT",
  96. "GT", "LE", 0, "NV"
  97. };
  98. static
  99. char* shtype[4] =
  100. {
  101. "<<", ">>", "->", "@>"
  102. };
  103. static
  104. char *hb[4] =
  105. {
  106. "???", "HU", "B", "H"
  107. };
  108. static
  109. char* addsub[2] =
  110. {
  111. "-", "+",
  112. };
  113. int
  114. armclass(long w)
  115. {
  116. int op;
  117. op = (w >> 25) & 0x7;
  118. switch(op) {
  119. case 0: /* data processing r,r,r */
  120. op = ((w >> 4) & 0xf);
  121. if(op == 0x9) {
  122. op = 48+16; /* mul */
  123. if(w & (1<<24)) {
  124. op += 2;
  125. if(w & (1<<22))
  126. op++; /* swap */
  127. break;
  128. }
  129. if(w & (1<<23)) { /* mullu */
  130. op = (48+24+4+4+2+2+4);
  131. if(w & (1<<22)) /* mull */
  132. op += 2;
  133. }
  134. if(w & (1<<21))
  135. op++; /* mla */
  136. break;
  137. }
  138. if((op & 0x9) == 0x9) /* ld/st byte/half s/u */
  139. {
  140. op = (48+16+4) + ((w >> 22) & 0x1) + ((w >> 19) & 0x2);
  141. break;
  142. }
  143. op = (w >> 21) & 0xf;
  144. if(w & (1<<4))
  145. op += 32;
  146. else
  147. if((w & (31<<7)) || (w & (1<<5)))
  148. op += 16;
  149. break;
  150. case 1: /* data processing i,r,r */
  151. op = (48) + ((w >> 21) & 0xf);
  152. break;
  153. case 2: /* load/store byte/word i(r) */
  154. op = (48+24) + ((w >> 22) & 0x1) + ((w >> 19) & 0x2);
  155. break;
  156. case 3: /* load/store byte/word (r)(r) */
  157. op = (48+24+4) + ((w >> 22) & 0x1) + ((w >> 19) & 0x2);
  158. break;
  159. case 4: /* block data transfer (r)(r) */
  160. op = (48+24+4+4) + ((w >> 20) & 0x1);
  161. break;
  162. case 5: /* branch / branch link */
  163. op = (48+24+4+4+2) + ((w >> 24) & 0x1);
  164. break;
  165. case 7: /* coprocessor crap */
  166. op = (48+24+4+4+2+2) + ((w >> 3) & 0x2) + ((w >> 20) & 0x1);
  167. break;
  168. default:
  169. op = (48+24+4+4+2+2+4+4);
  170. break;
  171. }
  172. return op;
  173. }
  174. static int
  175. decode(Map *map, uvlong pc, Instr *i)
  176. {
  177. ulong w;
  178. if(get4(map, pc, &w) < 0) {
  179. werrstr("can't read instruction: %r");
  180. return -1;
  181. }
  182. i->w = w;
  183. i->addr = pc;
  184. i->cond = (w >> 28) & 0xF;
  185. i->op = armclass(w);
  186. i->map = map;
  187. return 1;
  188. }
  189. static void
  190. bprint(Instr *i, char *fmt, ...)
  191. {
  192. va_list arg;
  193. va_start(arg, fmt);
  194. i->curr = vseprint(i->curr, i->end, fmt, arg);
  195. va_end(arg);
  196. }
  197. static int
  198. plocal(Instr *i)
  199. {
  200. char *reg;
  201. Symbol s;
  202. char *fn;
  203. int class;
  204. int offset;
  205. if(!findsym(i->addr, CTEXT, &s)) {
  206. if(debug)fprint(2,"fn not found @%llux: %r\n", i->addr);
  207. return 0;
  208. }
  209. fn = s.name;
  210. if (!findlocal(&s, FRAMENAME, &s)) {
  211. if(debug)fprint(2,"%s.%s not found @%s: %r\n", fn, FRAMENAME, s.name);
  212. return 0;
  213. }
  214. if(s.value > i->imm) {
  215. class = CAUTO;
  216. offset = s.value-i->imm;
  217. reg = "(SP)";
  218. } else {
  219. class = CPARAM;
  220. offset = i->imm-s.value-4;
  221. reg = "(FP)";
  222. }
  223. if(!getauto(&s, offset, class, &s)) {
  224. if(debug)fprint(2,"%s %s not found @%ux: %r\n", fn,
  225. class == CAUTO ? " auto" : "param", offset);
  226. return 0;
  227. }
  228. bprint(i, "%s%c%d%s", s.name, class == CPARAM ? '+' : '-', s.value, reg);
  229. return 1;
  230. }
  231. /*
  232. * Print value v as name[+offset]
  233. */
  234. static int
  235. gsymoff(char *buf, int n, long v, int space)
  236. {
  237. Symbol s;
  238. int r;
  239. long delta;
  240. r = delta = 0; /* to shut compiler up */
  241. if (v) {
  242. r = findsym(v, space, &s);
  243. if (r)
  244. delta = v-s.value;
  245. if (delta < 0)
  246. delta = -delta;
  247. }
  248. if (v == 0 || r == 0 || delta >= 4096)
  249. return snprint(buf, n, "#%lux", v);
  250. if (strcmp(s.name, ".string") == 0)
  251. return snprint(buf, n, "#%lux", v);
  252. if (!delta)
  253. return snprint(buf, n, "%s", s.name);
  254. if (s.type != 't' && s.type != 'T')
  255. return snprint(buf, n, "%s+%llux", s.name, v-s.value);
  256. else
  257. return snprint(buf, n, "#%lux", v);
  258. }
  259. static void
  260. armdps(Opcode *o, Instr *i)
  261. {
  262. i->store = (i->w >> 20) & 1;
  263. i->rn = (i->w >> 16) & 0xf;
  264. i->rd = (i->w >> 12) & 0xf;
  265. i->rs = (i->w >> 0) & 0xf;
  266. if(i->rn == 15 && i->rs == 0) {
  267. if(i->op == 8) {
  268. format("MOVW", i,"CPSR, R%d");
  269. return;
  270. } else
  271. if(i->op == 10) {
  272. format("MOVW", i,"SPSR, R%d");
  273. return;
  274. }
  275. } else
  276. if(i->rn == 9 && i->rd == 15) {
  277. if(i->op == 9) {
  278. format("MOVW", i, "R%s, CPSR");
  279. return;
  280. } else
  281. if(i->op == 11) {
  282. format("MOVW", i, "R%s, SPSR");
  283. return;
  284. }
  285. }
  286. format(o->o, i, o->a);
  287. }
  288. static void
  289. armdpi(Opcode *o, Instr *i)
  290. {
  291. ulong v;
  292. int c;
  293. v = (i->w >> 0) & 0xff;
  294. c = (i->w >> 8) & 0xf;
  295. while(c) {
  296. v = (v<<30) | (v>>2);
  297. c--;
  298. }
  299. i->imm = v;
  300. i->store = (i->w >> 20) & 1;
  301. i->rn = (i->w >> 16) & 0xf;
  302. i->rd = (i->w >> 12) & 0xf;
  303. i->rs = i->w&0x0f;
  304. /* RET is encoded as ADD #0,R14,R15 */
  305. if((i->w & 0x0fffffff) == 0x028ef000){
  306. format("RET%C", i, "");
  307. return;
  308. }
  309. if((i->w & 0x0ff0ffff) == 0x0280f000){
  310. format("B%C", i, "0(R%n)");
  311. return;
  312. }
  313. format(o->o, i, o->a);
  314. }
  315. static void
  316. armsdti(Opcode *o, Instr *i)
  317. {
  318. ulong v;
  319. v = i->w & 0xfff;
  320. if(!(i->w & (1<<23)))
  321. v = -v;
  322. i->store = ((i->w >> 23) & 0x2) | ((i->w >>21) & 0x1);
  323. i->imm = v;
  324. i->rn = (i->w >> 16) & 0xf;
  325. i->rd = (i->w >> 12) & 0xf;
  326. /* RET is encoded as LW.P x,R13,R15 */
  327. if ((i->w & 0x0ffff000) == 0x049df000)
  328. {
  329. format("RET%C%p", i, "%I");
  330. return;
  331. }
  332. format(o->o, i, o->a);
  333. }
  334. /* arm V4 ld/st halfword, signed byte */
  335. static void
  336. armhwby(Opcode *o, Instr *i)
  337. {
  338. i->store = ((i->w >> 23) & 0x2) | ((i->w >>21) & 0x1);
  339. i->imm = (i->w & 0xf) | ((i->w >> 8) & 0xf);
  340. if (!(i->w & (1 << 23)))
  341. i->imm = - i->imm;
  342. i->rn = (i->w >> 16) & 0xf;
  343. i->rd = (i->w >> 12) & 0xf;
  344. i->rs = (i->w >> 0) & 0xf;
  345. format(o->o, i, o->a);
  346. }
  347. static void
  348. armsdts(Opcode *o, Instr *i)
  349. {
  350. i->store = ((i->w >> 23) & 0x2) | ((i->w >>21) & 0x1);
  351. i->rs = (i->w >> 0) & 0xf;
  352. i->rn = (i->w >> 16) & 0xf;
  353. i->rd = (i->w >> 12) & 0xf;
  354. format(o->o, i, o->a);
  355. }
  356. static void
  357. armbdt(Opcode *o, Instr *i)
  358. {
  359. i->store = (i->w >> 21) & 0x3; /* S & W bits */
  360. i->rn = (i->w >> 16) & 0xf;
  361. i->imm = i->w & 0xffff;
  362. if(i->w == 0xe8fd8000)
  363. format("RFE", i, "");
  364. else
  365. format(o->o, i, o->a);
  366. }
  367. static void
  368. armund(Opcode *o, Instr *i)
  369. {
  370. format(o->o, i, o->a);
  371. }
  372. static void
  373. armcdt(Opcode *o, Instr *i)
  374. {
  375. format(o->o, i, o->a);
  376. }
  377. static void
  378. armunk(Opcode *o, Instr *i)
  379. {
  380. format(o->o, i, o->a);
  381. }
  382. static void
  383. armb(Opcode *o, Instr *i)
  384. {
  385. ulong v;
  386. v = i->w & 0xffffff;
  387. if(v & 0x800000)
  388. v |= ~0xffffff;
  389. i->imm = (v<<2) + i->addr + 8;
  390. format(o->o, i, o->a);
  391. }
  392. static void
  393. armco(Opcode *o, Instr *i) /* coprocessor instructions */
  394. {
  395. int op, p, cp;
  396. char buf[1024];
  397. i->rn = (i->w >> 16) & 0xf;
  398. i->rd = (i->w >> 12) & 0xf;
  399. i->rs = i->w&0xf;
  400. cp = (i->w >> 8) & 0xf;
  401. p = (i->w >> 5) & 0x7;
  402. if(i->w&(1<<4)) {
  403. op = (i->w >> 21) & 0x07;
  404. snprint(buf, sizeof(buf), "#%x, #%x, R%d, C(%d), C(%d), #%x\n", cp, op, i->rd, i->rn, i->rs, p);
  405. } else {
  406. op = (i->w >> 20) & 0x0f;
  407. snprint(buf, sizeof(buf), "#%x, #%x, C(%d), C(%d), C(%d), #%x\n", cp, op, i->rd, i->rn, i->rs, p);
  408. }
  409. format(o->o, i, buf);
  410. }
  411. static int
  412. armcondpass(Map *map, Rgetter rget, uchar cond)
  413. {
  414. uvlong psr;
  415. uchar n;
  416. uchar z;
  417. uchar c;
  418. uchar v;
  419. psr = rget(map, "PSR");
  420. n = (psr >> 31) & 1;
  421. z = (psr >> 30) & 1;
  422. c = (psr >> 29) & 1;
  423. v = (psr >> 28) & 1;
  424. switch(cond) {
  425. case 0: return z;
  426. case 1: return !z;
  427. case 2: return c;
  428. case 3: return !c;
  429. case 4: return n;
  430. case 5: return !n;
  431. case 6: return v;
  432. case 7: return !v;
  433. case 8: return c && !z;
  434. case 9: return !c || z;
  435. case 10: return n == v;
  436. case 11: return n != v;
  437. case 12: return !z && (n == v);
  438. case 13: return z && (n != v);
  439. case 14: return 1;
  440. case 15: return 0;
  441. }
  442. }
  443. static ulong
  444. armshiftval(Map *map, Rgetter rget, Instr *i)
  445. {
  446. if(i->w & (1 << 25)) { /* immediate */
  447. ulong imm = i->w & BITS(0, 7);
  448. ulong s = (i->w & BITS(8, 11)) >> 7; /* this contains the *2 */
  449. return ROR(imm, s);
  450. } else {
  451. char buf[8];
  452. ulong v;
  453. ulong s = (i->w & BITS(7,11)) >> 7;
  454. sprint(buf, "R%ld", i->w & 0xf);
  455. v = rget(map, buf);
  456. switch((i->w & BITS(4, 6)) >> 4) {
  457. case 0: /* LSLIMM */
  458. return v << s;
  459. case 1: /* LSLREG */
  460. sprint(buf, "R%lud", s >> 1);
  461. s = rget(map, buf) & 0xFF;
  462. if(s >= 32) return 0;
  463. return v << s;
  464. case 2: /* LSRIMM */
  465. return LSR(v, s);
  466. case 3: /* LSRREG */
  467. sprint(buf, "R%ld", s >> 1);
  468. s = rget(map, buf) & 0xFF;
  469. if(s >= 32) return 0;
  470. return LSR(v, s);
  471. case 4: /* ASRIMM */
  472. if(s == 0) {
  473. if((v & (1U<<31)) == 0)
  474. return 0;
  475. return 0xFFFFFFFF;
  476. }
  477. return ASR(v, s);
  478. case 5: /* ASRREG */
  479. sprint(buf, "R%ld", s >> 1);
  480. s = rget(map, buf) & 0xFF;
  481. if(s >= 32) {
  482. if((v & (1U<<31)) == 0)
  483. return 0;
  484. return 0xFFFFFFFF;
  485. }
  486. return ASR(v, s);
  487. case 6: /* RORIMM */
  488. if(s == 0) {
  489. ulong c = (rget(map, "PSR") >> 29) & 1;
  490. return (c << 31) | LSR(v, 1);
  491. }
  492. return ROR(v, s);
  493. case 7: /* RORREG */
  494. sprint(buf, "R%ld", (s>>1)&0xF);
  495. s = rget(map, buf);
  496. if(s == 0 || (s & 0xF) == 0)
  497. return v;
  498. return ROR(v, s & 0xF);
  499. }
  500. }
  501. }
  502. static int
  503. nbits(ulong v)
  504. {
  505. int n = 0;
  506. int i;
  507. for(i=0; i < 32 ; i++) {
  508. if(v & 1) ++n;
  509. v >>= 1;
  510. }
  511. return n;
  512. }
  513. static ulong
  514. armmaddr(Map *map, Rgetter rget, Instr *i)
  515. {
  516. ulong v;
  517. ulong nb;
  518. char buf[8];
  519. ulong rn;
  520. rn = (i->w >> 16) & 0xf;
  521. sprint(buf,"R%ld", rn);
  522. v = rget(map, buf);
  523. nb = nbits(i->w & ((1 << 15) - 1));
  524. switch((i->w >> 23) & 3) {
  525. case 0: return (v - (nb*4)) + 4;
  526. case 1: return v;
  527. case 2: return v - (nb*4);
  528. case 3: return v + 4;
  529. }
  530. }
  531. static uvlong
  532. armaddr(Map *map, Rgetter rget, Instr *i)
  533. {
  534. char buf[8];
  535. ulong rn;
  536. sprint(buf, "R%ld", (i->w >> 16) & 0xf);
  537. rn = rget(map, buf);
  538. if((i->w & (1<<24)) == 0) { /* POSTIDX */
  539. sprint(buf, "R%ld", rn);
  540. return rget(map, buf);
  541. }
  542. if((i->w & (1<<25)) == 0) { /* OFFSET */
  543. sprint(buf, "R%ld", rn);
  544. if(i->w & (1U<<23))
  545. return rget(map, buf) + (i->w & BITS(0,11));
  546. return rget(map, buf) - (i->w & BITS(0,11));
  547. } else { /* REGOFF */
  548. ulong index = 0;
  549. uchar c;
  550. uchar rm;
  551. sprint(buf, "R%ld", i->w & 0xf);
  552. rm = rget(map, buf);
  553. switch((i->w & BITS(5,6)) >> 5) {
  554. case 0: index = rm << ((i->w & BITS(7,11)) >> 7); break;
  555. case 1: index = LSR(rm, ((i->w & BITS(7,11)) >> 7)); break;
  556. case 2: index = ASR(rm, ((i->w & BITS(7,11)) >> 7)); break;
  557. case 3:
  558. if((i->w & BITS(7,11)) == 0) {
  559. c = (rget(map, "PSR") >> 29) & 1;
  560. index = c << 31 | LSR(rm, 1);
  561. } else {
  562. index = ROR(rm, ((i->w & BITS(7,11)) >> 7));
  563. }
  564. break;
  565. }
  566. if(i->w & (1<<23))
  567. return rn + index;
  568. return rn - index;
  569. }
  570. }
  571. static uvlong
  572. armfadd(Map *map, Rgetter rget, Instr *i, uvlong pc)
  573. {
  574. char buf[8];
  575. int r;
  576. r = (i->w >> 12) & 0xf;
  577. if(r != 15 || !armcondpass(map, rget, (i->w >> 28) & 0xf))
  578. return pc+4;
  579. r = (i->w >> 16) & 0xf;
  580. sprint(buf, "R%d", r);
  581. return rget(map, buf) + armshiftval(map, rget, i);
  582. }
  583. static uvlong
  584. armfmovm(Map *map, Rgetter rget, Instr *i, uvlong pc)
  585. {
  586. ulong v;
  587. ulong addr;
  588. v = i->w & 1<<15;
  589. if(!v || !armcondpass(map, rget, (i->w>>28)&0xf))
  590. return pc+4;
  591. addr = armmaddr(map, rget, i) + nbits(i->w & BITS(0,15));
  592. if(get4(map, addr, &v) < 0) {
  593. werrstr("can't read addr: %r");
  594. return -1;
  595. }
  596. return v;
  597. }
  598. static uvlong
  599. armfbranch(Map *map, Rgetter rget, Instr *i, uvlong pc)
  600. {
  601. if(!armcondpass(map, rget, (i->w >> 28) & 0xf))
  602. return pc+4;
  603. return pc + (((signed long)i->w << 8) >> 6) + 8;
  604. }
  605. static uvlong
  606. armfmov(Map *map, Rgetter rget, Instr *i, uvlong pc)
  607. {
  608. ulong rd, v;
  609. rd = (i->w >> 12) & 0xf;
  610. if(rd != 15 || !armcondpass(map, rget, (i->w>>28)&0xf))
  611. return pc+4;
  612. /* LDR */
  613. /* BUG: Needs LDH/B, too */
  614. if((i->w>>26)&0x3 == 1) {
  615. if(get4(map, armaddr(map, rget, i), &v) < 0) {
  616. werrstr("can't read instruction: %r");
  617. return pc+4;
  618. }
  619. return v;
  620. }
  621. /* MOV */
  622. v = armshiftval(map, rget, i);
  623. return v;
  624. }
  625. static Opcode opcodes[] =
  626. {
  627. "AND%C%S", armdps, 0, "R%s,R%n,R%d",
  628. "EOR%C%S", armdps, 0, "R%s,R%n,R%d",
  629. "SUB%C%S", armdps, 0, "R%s,R%n,R%d",
  630. "RSB%C%S", armdps, 0, "R%s,R%n,R%d",
  631. "ADD%C%S", armdps, armfadd, "R%s,R%n,R%d",
  632. "ADC%C%S", armdps, 0, "R%s,R%n,R%d",
  633. "SBC%C%S", armdps, 0, "R%s,R%n,R%d",
  634. "RSC%C%S", armdps, 0, "R%s,R%n,R%d",
  635. "TST%C%S", armdps, 0, "R%s,R%n",
  636. "TEQ%C%S", armdps, 0, "R%s,R%n",
  637. "CMP%C%S", armdps, 0, "R%s,R%n",
  638. "CMN%C%S", armdps, 0, "R%s,R%n",
  639. "ORR%C%S", armdps, 0, "R%s,R%n,R%d",
  640. "MOVW%C%S", armdps, armfmov, "R%s,R%d",
  641. "BIC%C%S", armdps, 0, "R%s,R%n,R%d",
  642. "MVN%C%S", armdps, 0, "R%s,R%d",
  643. /* 16 */
  644. "AND%C%S", armdps, 0, "(R%s%h%m),R%n,R%d",
  645. "EOR%C%S", armdps, 0, "(R%s%h%m),R%n,R%d",
  646. "SUB%C%S", armdps, 0, "(R%s%h%m),R%n,R%d",
  647. "RSB%C%S", armdps, 0, "(R%s%h%m),R%n,R%d",
  648. "ADD%C%S", armdps, armfadd, "(R%s%h%m),R%n,R%d",
  649. "ADC%C%S", armdps, 0, "(R%s%h%m),R%n,R%d",
  650. "SBC%C%S", armdps, 0, "(R%s%h%m),R%n,R%d",
  651. "RSC%C%S", armdps, 0, "(R%s%h%m),R%n,R%d",
  652. "TST%C%S", armdps, 0, "(R%s%h%m),R%n",
  653. "TEQ%C%S", armdps, 0, "(R%s%h%m),R%n",
  654. "CMP%C%S", armdps, 0, "(R%s%h%m),R%n",
  655. "CMN%C%S", armdps, 0, "(R%s%h%m),R%n",
  656. "ORR%C%S", armdps, 0, "(R%s%h%m),R%n,R%d",
  657. "MOVW%C%S", armdps, armfmov, "(R%s%h%m),R%d",
  658. "BIC%C%S", armdps, 0, "(R%s%h%m),R%n,R%d",
  659. "MVN%C%S", armdps, 0, "(R%s%h%m),R%d",
  660. /* 32 */
  661. "AND%C%S", armdps, 0, "(R%s%hR%M),R%n,R%d",
  662. "EOR%C%S", armdps, 0, "(R%s%hR%M),R%n,R%d",
  663. "SUB%C%S", armdps, 0, "(R%s%hR%M),R%n,R%d",
  664. "RSB%C%S", armdps, 0, "(R%s%hR%M),R%n,R%d",
  665. "ADD%C%S", armdps, armfadd, "(R%s%hR%M),R%n,R%d",
  666. "ADC%C%S", armdps, 0, "(R%s%hR%M),R%n,R%d",
  667. "SBC%C%S", armdps, 0, "(R%s%hR%M),R%n,R%d",
  668. "RSC%C%S", armdps, 0, "(R%s%hR%M),R%n,R%d",
  669. "TST%C%S", armdps, 0, "(R%s%hR%M),R%n",
  670. "TEQ%C%S", armdps, 0, "(R%s%hR%M),R%n",
  671. "CMP%C%S", armdps, 0, "(R%s%hR%M),R%n",
  672. "CMN%C%S", armdps, 0, "(R%s%hR%M),R%n",
  673. "ORR%C%S", armdps, 0, "(R%s%hR%M),R%n,R%d",
  674. "MOVW%C%S", armdps, armfmov, "(R%s%hR%M),R%d",
  675. "BIC%C%S", armdps, 0, "(R%s%hR%M),R%n,R%d",
  676. "MVN%C%S", armdps, 0, "(R%s%hR%M),R%d",
  677. /* 48 */
  678. "AND%C%S", armdpi, 0, "$#%i,R%n,R%d",
  679. "EOR%C%S", armdpi, 0, "$#%i,R%n,R%d",
  680. "SUB%C%S", armdpi, 0, "$#%i,R%n,R%d",
  681. "RSB%C%S", armdpi, 0, "$#%i,R%n,R%d",
  682. "ADD%C%S", armdpi, armfadd, "$#%i,R%n,R%d",
  683. "ADC%C%S", armdpi, 0, "$#%i,R%n,R%d",
  684. "SBC%C%S", armdpi, 0, "$#%i,R%n,R%d",
  685. "RSC%C%S", armdpi, 0, "$#%i,R%n,R%d",
  686. "TST%C%S", armdpi, 0, "$#%i,R%n",
  687. "TEQ%C%S", armdpi, 0, "$#%i,R%n",
  688. "CMP%C%S", armdpi, 0, "$#%i,R%n",
  689. "CMN%C%S", armdpi, 0, "$#%i,R%n",
  690. "ORR%C%S", armdpi, 0, "$#%i,R%n,R%d",
  691. "MOVW%C%S", armdpi, armfmov, "$#%i,R%d",
  692. "BIC%C%S", armdpi, 0, "$#%i,R%n,R%d",
  693. "MVN%C%S", armdpi, 0, "$#%i,R%d",
  694. /* 48+16 */
  695. "MUL%C%S", armdpi, 0, "R%M,R%s,R%n",
  696. "MULA%C%S", armdpi, 0, "R%M,R%s,R%n,R%d",
  697. "SWPW", armdpi, 0, "R%s,(R%n),R%d",
  698. "SWPB", armdpi, 0, "R%s,(R%n),R%d",
  699. /* 48+16+4 */
  700. "MOV%u%C%p", armhwby, 0, "R%d,(R%n%UR%M)",
  701. "MOV%u%C%p", armhwby, 0, "R%d,%I",
  702. "MOV%u%C%p", armhwby, armfmov, "(R%n%UR%M),R%d",
  703. "MOV%u%C%p", armhwby, armfmov, "%I,R%d",
  704. /* 48+24 */
  705. "MOVW%C%p", armsdti, 0, "R%d,%I",
  706. "MOVB%C%p", armsdti, 0, "R%d,%I",
  707. "MOVW%C%p", armsdti, armfmov, "%I,R%d",
  708. "MOVBU%C%p", armsdti, armfmov, "%I,R%d",
  709. "MOVW%C%p", armsdts, 0, "R%d,(R%s%h%m)(R%n)",
  710. "MOVB%C%p", armsdts, 0, "R%d,(R%s%h%m)(R%n)",
  711. "MOVW%C%p", armsdts, armfmov, "(R%s%h%m)(R%n),R%d",
  712. "MOVBU%C%p", armsdts, armfmov, "(R%s%h%m)(R%n),R%d",
  713. "MOVM%C%P%a", armbdt, armfmovm, "[%r],(R%n)",
  714. "MOVM%C%P%a", armbdt, armfmovm, "(R%n),[%r]",
  715. "B%C", armb, armfbranch, "%b",
  716. "BL%C", armb, armfbranch, "%b",
  717. "CDP%C", armco, 0, "",
  718. "CDP%C", armco, 0, "",
  719. "MCR%C", armco, 0, "",
  720. "MRC%C", armco, 0, "",
  721. /* 48+24+4+4+2+2+4 */
  722. "MULLU%C%S", armdpi, 0, "R%M,R%s,(R%n,R%d)",
  723. "MULALU%C%S", armdpi, 0, "R%M,R%s,(R%n,R%d)",
  724. "MULL%C%S", armdpi, 0, "R%M,R%s,(R%n,R%d)",
  725. "MULAL%C%S", armdpi, 0, "R%M,R%s,(R%n,R%d)",
  726. /* 48+24+4+4+2+2+4+4 */
  727. "UNK", armunk, 0, "",
  728. };
  729. static void
  730. gaddr(Instr *i)
  731. {
  732. *i->curr++ = '$';
  733. i->curr += gsymoff(i->curr, i->end-i->curr, i->imm, CANY);
  734. }
  735. static char *mode[] = { 0, "IA", "DB", "IB" };
  736. static char *pw[] = { "P", "PW", 0, "W" };
  737. static char *sw[] = { 0, "W", "S", "SW" };
  738. static void
  739. format(char *mnemonic, Instr *i, char *f)
  740. {
  741. int j, k, m, n;
  742. int g;
  743. char *fmt;
  744. if(mnemonic)
  745. format(0, i, mnemonic);
  746. if(f == 0)
  747. return;
  748. if(mnemonic)
  749. if(i->curr < i->end)
  750. *i->curr++ = '\t';
  751. for ( ; *f && i->curr < i->end; f++) {
  752. if(*f != '%') {
  753. *i->curr++ = *f;
  754. continue;
  755. }
  756. switch (*++f) {
  757. case 'C': /* .CONDITION */
  758. if(cond[i->cond])
  759. bprint(i, ".%s", cond[i->cond]);
  760. break;
  761. case 'S': /* .STORE */
  762. if(i->store)
  763. bprint(i, ".S");
  764. break;
  765. case 'P': /* P & U bits for block move */
  766. n = (i->w >>23) & 0x3;
  767. if (mode[n])
  768. bprint(i, ".%s", mode[n]);
  769. break;
  770. case 'p': /* P & W bits for single data xfer*/
  771. if (pw[i->store])
  772. bprint(i, ".%s", pw[i->store]);
  773. break;
  774. case 'a': /* S & W bits for single data xfer*/
  775. if (sw[i->store])
  776. bprint(i, ".%s", sw[i->store]);
  777. break;
  778. case 's':
  779. bprint(i, "%d", i->rs & 0xf);
  780. break;
  781. case 'M':
  782. bprint(i, "%d", (i->w>>8) & 0xf);
  783. break;
  784. case 'm':
  785. bprint(i, "%d", (i->w>>7) & 0x1f);
  786. break;
  787. case 'h':
  788. bprint(i, shtype[(i->w>>5) & 0x3]);
  789. break;
  790. case 'u': /* Signed/unsigned Byte/Halfword */
  791. bprint(i, hb[(i->w>>5) & 0x3]);
  792. break;
  793. case 'I':
  794. if (i->rn == 13) {
  795. if (plocal(i))
  796. break;
  797. }
  798. g = 0;
  799. fmt = "#%lx(R%d)";
  800. if (i->rn == 15) {
  801. /* convert load of offset(PC) to a load immediate */
  802. if (get4(i->map, i->addr+i->imm+8, (ulong*)&i->imm) > 0)
  803. {
  804. g = 1;
  805. fmt = "";
  806. }
  807. }
  808. if (mach->sb)
  809. {
  810. if (i->rd == 11) {
  811. ulong nxti;
  812. if (get4(i->map, i->addr+4, &nxti) > 0) {
  813. if ((nxti & 0x0e0f0fff) == 0x060c000b) {
  814. i->imm += mach->sb;
  815. g = 1;
  816. fmt = "-SB";
  817. }
  818. }
  819. }
  820. if (i->rn == 12)
  821. {
  822. i->imm += mach->sb;
  823. g = 1;
  824. fmt = "-SB(SB)";
  825. }
  826. }
  827. if (g)
  828. {
  829. gaddr(i);
  830. bprint(i, fmt, i->rn);
  831. }
  832. else
  833. bprint(i, fmt, i->imm, i->rn);
  834. break;
  835. case 'U': /* Add/subtract from base */
  836. bprint(i, addsub[(i->w >> 23) & 1]);
  837. break;
  838. case 'n':
  839. bprint(i, "%d", i->rn);
  840. break;
  841. case 'd':
  842. bprint(i, "%d", i->rd);
  843. break;
  844. case 'i':
  845. bprint(i, "%lux", i->imm);
  846. break;
  847. case 'b':
  848. i->curr += symoff(i->curr, i->end-i->curr,
  849. i->imm, CTEXT);
  850. break;
  851. case 'g':
  852. i->curr += gsymoff(i->curr, i->end-i->curr,
  853. i->imm, CANY);
  854. break;
  855. case 'r':
  856. n = i->imm&0xffff;
  857. j = 0;
  858. k = 0;
  859. while(n) {
  860. m = j;
  861. while(n&0x1) {
  862. j++;
  863. n >>= 1;
  864. }
  865. if(j != m) {
  866. if(k)
  867. bprint(i, ",");
  868. if(j == m+1)
  869. bprint(i, "R%d", m);
  870. else
  871. bprint(i, "R%d-R%d", m, j-1);
  872. k = 1;
  873. }
  874. j++;
  875. n >>= 1;
  876. }
  877. break;
  878. case '\0':
  879. *i->curr++ = '%';
  880. return;
  881. default:
  882. bprint(i, "%%%c", *f);
  883. break;
  884. }
  885. }
  886. *i->curr = 0;
  887. }
  888. static int
  889. printins(Map *map, uvlong pc, char *buf, int n)
  890. {
  891. Instr i;
  892. i.curr = buf;
  893. i.end = buf+n-1;
  894. if(decode(map, pc, &i) < 0)
  895. return -1;
  896. (*opcodes[i.op].fmt)(&opcodes[i.op], &i);
  897. return 4;
  898. }
  899. static int
  900. arminst(Map *map, uvlong pc, char modifier, char *buf, int n)
  901. {
  902. USED(modifier);
  903. return printins(map, pc, buf, n);
  904. }
  905. static int
  906. armdas(Map *map, uvlong pc, char *buf, int n)
  907. {
  908. Instr i;
  909. i.curr = buf;
  910. i.end = buf+n;
  911. if(decode(map, pc, &i) < 0)
  912. return -1;
  913. if(i.end-i.curr > 8)
  914. i.curr = _hexify(buf, i.w, 7);
  915. *i.curr = 0;
  916. return 4;
  917. }
  918. static int
  919. arminstlen(Map *map, uvlong pc)
  920. {
  921. Instr i;
  922. if(decode(map, pc, &i) < 0)
  923. return -1;
  924. return 4;
  925. }
  926. static int
  927. armfoll(Map *map, uvlong pc, Rgetter rget, uvlong *foll)
  928. {
  929. uvlong d;
  930. Instr i;
  931. if(decode(map, pc, &i) < 0)
  932. return -1;
  933. if(opcodes[i.op].foll) {
  934. d = (*opcodes[i.op].foll)(map, rget, &i, pc);
  935. if(d == -1)
  936. return -1;
  937. } else
  938. d = pc+4;
  939. foll[0] = d;
  940. return 1;
  941. }