5db.c 21 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073
  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. ulong 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. ulong (*foll)(Map*, Rgetter, Instr*, ulong);
  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*, ulong, Rgetter, ulong*);
  42. static int arminst(Map*, ulong, char, char*, int);
  43. static int armdas(Map*, ulong, char*, int);
  44. static int arminstlen(Map*, ulong);
  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. long c;
  70. c = (*rget)(map, "TYPE");
  71. switch (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, ulong pc, Instr *i)
  176. {
  177. long 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 @%lux: %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. ulong 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 ulong
  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 ulong
  572. armfadd(Map *map, Rgetter rget, Instr *i, ulong 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 ulong
  584. armfmovm(Map *map, Rgetter rget, Instr *i, ulong 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, (long*)&v) < 0) {
  593. werrstr("can't read addr: %r");
  594. return -1;
  595. }
  596. return v;
  597. }
  598. static ulong
  599. armfbranch(Map *map, Rgetter rget, Instr *i, ulong 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 ulong
  606. armfmov(Map *map, Rgetter rget, Instr *i, ulong pc)
  607. {
  608. ulong rd;
  609. ulong v;
  610. rd = (i->w >> 12) & 0xf;
  611. if(rd != 15 || !armcondpass(map, rget, (i->w>>28)&0xf))
  612. return pc+4;
  613. /* LDR */
  614. /* BUG: Needs LDH/B, too */
  615. if((i->w>>26)&0x3 == 1) {
  616. if(get4(map, armaddr(map, rget, i), (long*)&v) < 0) {
  617. werrstr("can't read instruction: %r");
  618. return pc+4;
  619. }
  620. return v;
  621. }
  622. /* MOV */
  623. v = armshiftval(map, rget, i);
  624. return v;
  625. }
  626. static Opcode opcodes[] =
  627. {
  628. "AND%C%S", armdps, 0, "R%s,R%n,R%d",
  629. "EOR%C%S", armdps, 0, "R%s,R%n,R%d",
  630. "SUB%C%S", armdps, 0, "R%s,R%n,R%d",
  631. "RSB%C%S", armdps, 0, "R%s,R%n,R%d",
  632. "ADD%C%S", armdps, armfadd, "R%s,R%n,R%d",
  633. "ADC%C%S", armdps, 0, "R%s,R%n,R%d",
  634. "SBC%C%S", armdps, 0, "R%s,R%n,R%d",
  635. "RSC%C%S", armdps, 0, "R%s,R%n,R%d",
  636. "TST%C%S", armdps, 0, "R%s,R%n",
  637. "TEQ%C%S", armdps, 0, "R%s,R%n",
  638. "CMP%C%S", armdps, 0, "R%s,R%n",
  639. "CMN%C%S", armdps, 0, "R%s,R%n",
  640. "ORR%C%S", armdps, 0, "R%s,R%n,R%d",
  641. "MOVW%C%S", armdps, armfmov, "R%s,R%d",
  642. "BIC%C%S", armdps, 0, "R%s,R%n,R%d",
  643. "MVN%C%S", armdps, 0, "R%s,R%d",
  644. /* 16 */
  645. "AND%C%S", armdps, 0, "(R%s%h%m),R%n,R%d",
  646. "EOR%C%S", armdps, 0, "(R%s%h%m),R%n,R%d",
  647. "SUB%C%S", armdps, 0, "(R%s%h%m),R%n,R%d",
  648. "RSB%C%S", armdps, 0, "(R%s%h%m),R%n,R%d",
  649. "ADD%C%S", armdps, armfadd, "(R%s%h%m),R%n,R%d",
  650. "ADC%C%S", armdps, 0, "(R%s%h%m),R%n,R%d",
  651. "SBC%C%S", armdps, 0, "(R%s%h%m),R%n,R%d",
  652. "RSC%C%S", armdps, 0, "(R%s%h%m),R%n,R%d",
  653. "TST%C%S", armdps, 0, "(R%s%h%m),R%n",
  654. "TEQ%C%S", armdps, 0, "(R%s%h%m),R%n",
  655. "CMP%C%S", armdps, 0, "(R%s%h%m),R%n",
  656. "CMN%C%S", armdps, 0, "(R%s%h%m),R%n",
  657. "ORR%C%S", armdps, 0, "(R%s%h%m),R%n,R%d",
  658. "MOVW%C%S", armdps, armfmov, "(R%s%h%m),R%d",
  659. "BIC%C%S", armdps, 0, "(R%s%h%m),R%n,R%d",
  660. "MVN%C%S", armdps, 0, "(R%s%h%m),R%d",
  661. /* 32 */
  662. "AND%C%S", armdps, 0, "(R%s%hR%M),R%n,R%d",
  663. "EOR%C%S", armdps, 0, "(R%s%hR%M),R%n,R%d",
  664. "SUB%C%S", armdps, 0, "(R%s%hR%M),R%n,R%d",
  665. "RSB%C%S", armdps, 0, "(R%s%hR%M),R%n,R%d",
  666. "ADD%C%S", armdps, armfadd, "(R%s%hR%M),R%n,R%d",
  667. "ADC%C%S", armdps, 0, "(R%s%hR%M),R%n,R%d",
  668. "SBC%C%S", armdps, 0, "(R%s%hR%M),R%n,R%d",
  669. "RSC%C%S", armdps, 0, "(R%s%hR%M),R%n,R%d",
  670. "TST%C%S", armdps, 0, "(R%s%hR%M),R%n",
  671. "TEQ%C%S", armdps, 0, "(R%s%hR%M),R%n",
  672. "CMP%C%S", armdps, 0, "(R%s%hR%M),R%n",
  673. "CMN%C%S", armdps, 0, "(R%s%hR%M),R%n",
  674. "ORR%C%S", armdps, 0, "(R%s%hR%M),R%n,R%d",
  675. "MOVW%C%S", armdps, armfmov, "(R%s%hR%M),R%d",
  676. "BIC%C%S", armdps, 0, "(R%s%hR%M),R%n,R%d",
  677. "MVN%C%S", armdps, 0, "(R%s%hR%M),R%d",
  678. /* 48 */
  679. "AND%C%S", armdpi, 0, "$#%i,R%n,R%d",
  680. "EOR%C%S", armdpi, 0, "$#%i,R%n,R%d",
  681. "SUB%C%S", armdpi, 0, "$#%i,R%n,R%d",
  682. "RSB%C%S", armdpi, 0, "$#%i,R%n,R%d",
  683. "ADD%C%S", armdpi, armfadd, "$#%i,R%n,R%d",
  684. "ADC%C%S", armdpi, 0, "$#%i,R%n,R%d",
  685. "SBC%C%S", armdpi, 0, "$#%i,R%n,R%d",
  686. "RSC%C%S", armdpi, 0, "$#%i,R%n,R%d",
  687. "TST%C%S", armdpi, 0, "$#%i,R%n",
  688. "TEQ%C%S", armdpi, 0, "$#%i,R%n",
  689. "CMP%C%S", armdpi, 0, "$#%i,R%n",
  690. "CMN%C%S", armdpi, 0, "$#%i,R%n",
  691. "ORR%C%S", armdpi, 0, "$#%i,R%n,R%d",
  692. "MOVW%C%S", armdpi, armfmov, "$#%i,R%d",
  693. "BIC%C%S", armdpi, 0, "$#%i,R%n,R%d",
  694. "MVN%C%S", armdpi, 0, "$#%i,R%d",
  695. /* 48+16 */
  696. "MUL%C%S", armdpi, 0, "R%M,R%s,R%n",
  697. "MULA%C%S", armdpi, 0, "R%M,R%s,R%n,R%d",
  698. "SWPW", armdpi, 0, "R%s,(R%n),R%d",
  699. "SWPB", armdpi, 0, "R%s,(R%n),R%d",
  700. /* 48+16+4 */
  701. "MOV%u%C%p", armhwby, 0, "R%d,(R%n%UR%M)",
  702. "MOV%u%C%p", armhwby, 0, "R%d,%I",
  703. "MOV%u%C%p", armhwby, armfmov, "(R%n%UR%M),R%d",
  704. "MOV%u%C%p", armhwby, armfmov, "%I,R%d",
  705. /* 48+24 */
  706. "MOVW%C%p", armsdti, 0, "R%d,%I",
  707. "MOVB%C%p", armsdti, 0, "R%d,%I",
  708. "MOVW%C%p", armsdti, armfmov, "%I,R%d",
  709. "MOVBU%C%p", armsdti, armfmov, "%I,R%d",
  710. "MOVW%C%p", armsdts, 0, "R%d,(R%s%h%m)(R%n)",
  711. "MOVB%C%p", armsdts, 0, "R%d,(R%s%h%m)(R%n)",
  712. "MOVW%C%p", armsdts, armfmov, "(R%s%h%m)(R%n),R%d",
  713. "MOVBU%C%p", armsdts, armfmov, "(R%s%h%m)(R%n),R%d",
  714. "MOVM%C%P%a", armbdt, armfmovm, "[%r],(R%n)",
  715. "MOVM%C%P%a", armbdt, armfmovm, "(R%n),[%r]",
  716. "B%C", armb, armfbranch, "%b",
  717. "BL%C", armb, armfbranch, "%b",
  718. "CDP%C", armco, 0, "",
  719. "CDP%C", armco, 0, "",
  720. "MCR%C", armco, 0, "",
  721. "MRC%C", armco, 0, "",
  722. /* 48+24+4+4+2+2+4 */
  723. "MULLU%C%S", armdpi, 0, "R%M,R%s,(R%n,R%d)",
  724. "MULALU%C%S", armdpi, 0, "R%M,R%s,(R%n,R%d)",
  725. "MULL%C%S", armdpi, 0, "R%M,R%s,(R%n,R%d)",
  726. "MULAL%C%S", armdpi, 0, "R%M,R%s,(R%n,R%d)",
  727. /* 48+24+4+4+2+2+4+4 */
  728. "UNK", armunk, 0, "",
  729. };
  730. static void
  731. gaddr(Instr *i)
  732. {
  733. *i->curr++ = '$';
  734. i->curr += gsymoff(i->curr, i->end-i->curr, i->imm, CANY);
  735. }
  736. static char *mode[] = { 0, "IA", "DB", "IB" };
  737. static char *pw[] = { "P", "PW", 0, "W" };
  738. static char *sw[] = { 0, "W", "S", "SW" };
  739. static void
  740. format(char *mnemonic, Instr *i, char *f)
  741. {
  742. int j, k, m, n;
  743. int g;
  744. char *fmt;
  745. if(mnemonic)
  746. format(0, i, mnemonic);
  747. if(f == 0)
  748. return;
  749. if(mnemonic)
  750. if(i->curr < i->end)
  751. *i->curr++ = '\t';
  752. for ( ; *f && i->curr < i->end; f++) {
  753. if(*f != '%') {
  754. *i->curr++ = *f;
  755. continue;
  756. }
  757. switch (*++f) {
  758. case 'C': /* .CONDITION */
  759. if(cond[i->cond])
  760. bprint(i, ".%s", cond[i->cond]);
  761. break;
  762. case 'S': /* .STORE */
  763. if(i->store)
  764. bprint(i, ".S");
  765. break;
  766. case 'P': /* P & U bits for block move */
  767. n = (i->w >>23) & 0x3;
  768. if (mode[n])
  769. bprint(i, ".%s", mode[n]);
  770. break;
  771. case 'p': /* P & W bits for single data xfer*/
  772. if (pw[i->store])
  773. bprint(i, ".%s", pw[i->store]);
  774. break;
  775. case 'a': /* S & W bits for single data xfer*/
  776. if (sw[i->store])
  777. bprint(i, ".%s", sw[i->store]);
  778. break;
  779. case 's':
  780. bprint(i, "%d", i->rs & 0xf);
  781. break;
  782. case 'M':
  783. bprint(i, "%d", (i->w>>8) & 0xf);
  784. break;
  785. case 'm':
  786. bprint(i, "%d", (i->w>>7) & 0x1f);
  787. break;
  788. case 'h':
  789. bprint(i, shtype[(i->w>>5) & 0x3]);
  790. break;
  791. case 'u': /* Signed/unsigned Byte/Halfword */
  792. bprint(i, hb[(i->w>>5) & 0x3]);
  793. break;
  794. case 'I':
  795. if (i->rn == 13) {
  796. if (plocal(i))
  797. break;
  798. }
  799. g = 0;
  800. fmt = "#%lx(R%d)";
  801. if (i->rn == 15) {
  802. /* convert load of offset(PC) to a load immediate */
  803. if (get4(i->map, i->addr+i->imm+8, &i->imm) > 0)
  804. {
  805. g = 1;
  806. fmt = "";
  807. }
  808. }
  809. if (mach->sb)
  810. {
  811. if (i->rd == 11) {
  812. ulong nxti;
  813. if (get4(i->map, i->addr+4, (long*)&nxti) > 0) {
  814. if ((nxti & 0x0e0f0fff) == 0x060c000b) {
  815. i->imm += mach->sb;
  816. g = 1;
  817. fmt = "-SB";
  818. }
  819. }
  820. }
  821. if (i->rn == 12)
  822. {
  823. i->imm += mach->sb;
  824. g = 1;
  825. fmt = "-SB(SB)";
  826. }
  827. }
  828. if (g)
  829. {
  830. gaddr(i);
  831. bprint(i, fmt, i->rn);
  832. }
  833. else
  834. bprint(i, fmt, i->imm, i->rn);
  835. break;
  836. case 'U': /* Add/subtract from base */
  837. bprint(i, addsub[(i->w >> 23) & 1]);
  838. break;
  839. case 'n':
  840. bprint(i, "%d", i->rn);
  841. break;
  842. case 'd':
  843. bprint(i, "%d", i->rd);
  844. break;
  845. case 'i':
  846. bprint(i, "%lux", i->imm);
  847. break;
  848. case 'b':
  849. i->curr += symoff(i->curr, i->end-i->curr,
  850. i->imm, CTEXT);
  851. break;
  852. case 'g':
  853. i->curr += gsymoff(i->curr, i->end-i->curr,
  854. i->imm, CANY);
  855. break;
  856. case 'r':
  857. n = i->imm&0xffff;
  858. j = 0;
  859. k = 0;
  860. while(n) {
  861. m = j;
  862. while(n&0x1) {
  863. j++;
  864. n >>= 1;
  865. }
  866. if(j != m) {
  867. if(k)
  868. bprint(i, ",");
  869. if(j == m+1)
  870. bprint(i, "R%d", m);
  871. else
  872. bprint(i, "R%d-R%d", m, j-1);
  873. k = 1;
  874. }
  875. j++;
  876. n >>= 1;
  877. }
  878. break;
  879. case '\0':
  880. *i->curr++ = '%';
  881. return;
  882. default:
  883. bprint(i, "%%%c", *f);
  884. break;
  885. }
  886. }
  887. *i->curr = 0;
  888. }
  889. static int
  890. printins(Map *map, ulong pc, char *buf, int n)
  891. {
  892. Instr i;
  893. i.curr = buf;
  894. i.end = buf+n-1;
  895. if(decode(map, pc, &i) < 0)
  896. return -1;
  897. (*opcodes[i.op].fmt)(&opcodes[i.op], &i);
  898. return 4;
  899. }
  900. static int
  901. arminst(Map *map, ulong pc, char modifier, char *buf, int n)
  902. {
  903. USED(modifier);
  904. return printins(map, pc, buf, n);
  905. }
  906. static int
  907. armdas(Map *map, ulong pc, char *buf, int n)
  908. {
  909. Instr i;
  910. i.curr = buf;
  911. i.end = buf+n;
  912. if(decode(map, pc, &i) < 0)
  913. return -1;
  914. if(i.end-i.curr > 8)
  915. i.curr = _hexify(buf, i.w, 7);
  916. *i.curr = 0;
  917. return 4;
  918. }
  919. static int
  920. arminstlen(Map *map, ulong pc)
  921. {
  922. Instr i;
  923. if(decode(map, pc, &i) < 0)
  924. return -1;
  925. return 4;
  926. }
  927. static int
  928. armfoll(Map *map, ulong pc, Rgetter rget, ulong *foll)
  929. {
  930. ulong d;
  931. Instr i;
  932. if(decode(map, pc, &i) < 0)
  933. return -1;
  934. if(opcodes[i.op].foll) {
  935. d = (*opcodes[i.op].foll)(map, rget, &i, pc);
  936. if(d == -1)
  937. return -1;
  938. } else
  939. d = pc+4;
  940. foll[0] = d;
  941. return 1;
  942. }