5db.c 25 KB

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