5db.c 21 KB

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