5db.c 22 KB

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