5db.c 22 KB

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