kdb.c 21 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060
  1. /*
  2. * This file is part of the UCB release of Plan 9. It is subject to the license
  3. * terms in the LICENSE file found in the top-level directory of this
  4. * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
  5. * part of the UCB release of Plan 9, including this file, may be copied,
  6. * modified, propagated, or distributed except according to the terms contained
  7. * in the LICENSE file.
  8. */
  9. #include <u.h>
  10. #include <libc.h>
  11. #include <bio.h>
  12. #include <mach.h>
  13. /*
  14. * Sparc-specific debugger interface
  15. */
  16. static char *sparcexcep(Map*, Rgetter);
  17. static int sparcfoll(Map*, uint64_t, Rgetter, uint64_t*);
  18. static int sparcinst(Map*, uint64_t, char, char*, int);
  19. static int sparcdas(Map*, uint64_t, char*, int);
  20. static int sparcinstlen(Map*, uint64_t);
  21. Machdata sparcmach =
  22. {
  23. {0x91, 0xd0, 0x20, 0x01}, /* breakpoint: TA $1 */
  24. 4, /* break point size */
  25. beswab, /* convert short to local byte order */
  26. beswal, /* convert long to local byte order */
  27. beswav, /* convert vlong to local byte order */
  28. risctrace, /* C traceback */
  29. riscframe, /* frame finder */
  30. sparcexcep, /* print exception */
  31. 0, /* breakpoint fixup */
  32. beieeesftos, /* single precision float printer */
  33. beieeedftos, /* double precision float printer */
  34. sparcfoll, /* following addresses */
  35. sparcinst, /* print instruction */
  36. sparcdas, /* dissembler */
  37. sparcinstlen, /* instruction size */
  38. };
  39. static char *trapname[] =
  40. {
  41. "reset",
  42. "instruction access exception",
  43. "illegal instruction",
  44. "privileged instruction",
  45. "fp disabled",
  46. "window overflow",
  47. "window underflow",
  48. "unaligned address",
  49. "fp exception",
  50. "data access exception",
  51. "tag overflow",
  52. };
  53. static char*
  54. excname(uint32_t tbr)
  55. {
  56. static char buf[32];
  57. if(tbr < sizeof trapname/sizeof(char*))
  58. return trapname[tbr];
  59. if(tbr >= 130)
  60. sprint(buf, "trap instruction %ld", tbr-128);
  61. else if(17<=tbr && tbr<=31)
  62. sprint(buf, "interrupt level %ld", tbr-16);
  63. else switch(tbr){
  64. case 36:
  65. return "cp disabled";
  66. case 40:
  67. return "cp exception";
  68. case 128:
  69. return "syscall";
  70. case 129:
  71. return "breakpoint";
  72. default:
  73. sprint(buf, "unknown trap %ld", tbr);
  74. }
  75. return buf;
  76. }
  77. static char*
  78. sparcexcep(Map *map, Rgetter rget)
  79. {
  80. int32_t tbr;
  81. tbr = (*rget)(map, "TBR");
  82. tbr = (tbr&0xFFF)>>4;
  83. return excname(tbr);
  84. }
  85. /* Sparc disassembler and related functions */
  86. struct opcode {
  87. char *mnemonic;
  88. void (*f)(struct instr*, char*);
  89. int flag;
  90. };
  91. static char FRAMENAME[] = ".frame";
  92. typedef struct instr Instr;
  93. struct instr {
  94. uint8_t op; /* bits 31-30 */
  95. uint8_t rd; /* bits 29-25 */
  96. uint8_t op2; /* bits 24-22 */
  97. uint8_t a; /* bit 29 */
  98. uint8_t cond; /* bits 28-25 */
  99. uint8_t op3; /* bits 24-19 */
  100. uint8_t rs1; /* bits 18-14 */
  101. uint8_t i; /* bit 13 */
  102. uint8_t asi; /* bits 12-05 */
  103. uint8_t rs2; /* bits 04-00 */
  104. int16_t simm13; /* bits 12-00, signed */
  105. uint16_t opf; /* bits 13-05 */
  106. uint32_t immdisp22; /* bits 21-00 */
  107. uint32_t simmdisp22; /* bits 21-00, signed */
  108. uint32_t disp30; /* bits 30-00 */
  109. uint32_t imm32; /* SETHI+ADD constant */
  110. int target; /* SETHI+ADD dest reg */
  111. int32_t w0;
  112. int32_t w1;
  113. uint64_t addr; /* pc of instruction */
  114. char *curr; /* current fill level in output buffer */
  115. char *end; /* end of buffer */
  116. int size; /* number of longs in instr */
  117. char *err; /* errmsg */
  118. };
  119. static Map *mymap; /* disassembler context */
  120. static int dascase;
  121. static int mkinstr(uint64_t, Instr*);
  122. static void bra1(Instr*, char*, char*[]);
  123. static void bra(Instr*, char*);
  124. static void fbra(Instr*, char*);
  125. static void cbra(Instr*, char*);
  126. static void unimp(Instr*, char*);
  127. static void fpop(Instr*, char*);
  128. static void shift(Instr*, char*);
  129. static void sethi(Instr*, char*);
  130. static void load(Instr*, char*);
  131. static void loada(Instr*, char*);
  132. static void store(Instr*, char*);
  133. static void storea(Instr*, char*);
  134. static void add(Instr*, char*);
  135. static void cmp(Instr*, char*);
  136. static void wr(Instr*, char*);
  137. static void jmpl(Instr*, char*);
  138. static void rd(Instr*, char*);
  139. static void loadf(Instr*, char*);
  140. static void storef(Instr*, char*);
  141. static void loadc(Instr*, char*);
  142. static void loadcsr(Instr*, char*);
  143. static void trap(Instr*, char*);
  144. static struct opcode sparcop0[8] = {
  145. [0] "UNIMP", unimp, 0, /* page 137 */
  146. [2] "B", bra, 0, /* page 119 */
  147. [4] "SETHI", sethi, 0, /* page 104 */
  148. [6] "FB", fbra, 0, /* page 121 */
  149. [7] "CB", cbra, 0, /* page 123 */
  150. };
  151. static struct opcode sparcop2[64] = {
  152. [0x00] "ADD", add, 0, /* page 108 */
  153. [0x10] "ADDCC", add, 0,
  154. [0x08] "ADDX", add, 0,
  155. [0x18] "ADDXCC", add, 0,
  156. [0x20] "TADD", add, 0, /* page 109 */
  157. [0x22] "TADDCCTV", add, 0,
  158. [0x04] "SUB", add, 0, /* page 110 */
  159. [0x14] "SUBCC", cmp, 0,
  160. [0x0C] "SUBX", add, 0,
  161. [0x1C] "SUBXCC", add, 0,
  162. [0x21] "TSUB", add, 0, /* page 111 */
  163. [0x23] "TSUBCCTV", add, 0,
  164. [0x24] "MULSCC", add, 0, /* page 112 */
  165. [0x0A] "UMUL", add, 0, /* page 113 */
  166. [0x0B] "SMUL", add, 0,
  167. [0x1A] "UMULCC", add, 0,
  168. [0x1B] "SMULCC", add, 0,
  169. [0x0E] "UDIV", add, 0, /* page 115 */
  170. [0x0F] "SDIV", add, 0,
  171. [0x1E] "UDIVCC", add, 0,
  172. [0x1F] "SDIVCC", add, 0,
  173. [0x01] "AND", add, 0, /* page 106 */
  174. [0x11] "ANDCC", add, 0,
  175. [0x05] "ANDN", add, 0,
  176. [0x15] "ANDNCC", add, 0,
  177. [0x02] "OR", add, 0,
  178. [0x12] "ORCC", add, 0,
  179. [0x06] "ORN", add, 0,
  180. [0x16] "ORNCC", add, 0,
  181. [0x03] "XOR", add, 0,
  182. [0x13] "XORCC", add, 0,
  183. [0x07] "XORN", add, 0,
  184. [0x17] "XORNCC", add, 0,
  185. [0x25] "SLL", shift, 0, /* page 107 */
  186. [0x26] "SRL", shift, 0,
  187. [0x27] "SRA", shift, 0,
  188. [0x3C] "SAVE", add, 0, /* page 117 */
  189. [0x3D] "RESTORE", add, 0,
  190. [0x38] "JMPL", jmpl, 0, /* page 126 */
  191. [0x39] "RETT", add, 0, /* page 127 */
  192. [0x3A] "T", trap, 0, /* page 129 */
  193. [0x28] "rdy", rd, 0, /* page 131 */
  194. [0x29] "rdpsr", rd, 0,
  195. [0x2A] "rdwim", rd, 0,
  196. [0x2B] "rdtbr", rd, 0,
  197. [0x30] "wry", wr, 0, /* page 133 */
  198. [0x31] "wrpsr", wr, 0,
  199. [0x32] "wrwim", wr, 0,
  200. [0x33] "wrtbr", wr, 0,
  201. [0x3B] "flush", add, 0, /* page 138 */
  202. [0x34] "FPOP", fpop, 0, /* page 140 */
  203. [0x35] "FPOP", fpop, 0,
  204. };
  205. static struct opcode sparcop3[64]={
  206. [0x09] "ldsb", load, 0, /* page 90 */
  207. [0x19] "ldsba", loada, 0,
  208. [0x0A] "ldsh", load, 0,
  209. [0x1A] "ldsha", loada, 0,
  210. [0x01] "ldub", load, 0,
  211. [0x11] "lduba", loada, 0,
  212. [0x02] "lduh", load, 0,
  213. [0x12] "lduha", loada, 0,
  214. [0x00] "ld", load, 0,
  215. [0x10] "lda", loada, 0,
  216. [0x03] "ldd", load, 0,
  217. [0x13] "ldda", loada, 0,
  218. [0x20] "ldf", loadf, 0, /* page 92 */
  219. [0x23] "lddf", loadf, 0,
  220. [0x21] "ldfsr", loadf,0,
  221. [0x30] "ldc", loadc, 0, /* page 94 */
  222. [0x33] "lddc", loadc, 0,
  223. [0x31] "ldcsr", loadcsr,0,
  224. [0x05] "stb", store, 0, /* page 95 */
  225. [0x15] "stba", storea, 0,
  226. [0x06] "sth", store, 0,
  227. [0x16] "stha", storea, 0,
  228. [0x04] "st", store, 0,
  229. [0x14] "sta", storea, 0,
  230. [0x07] "std", store, 0,
  231. [0x17] "stda", storea, 0,
  232. [0x24] "stf", storef, 0, /* page 97 */
  233. [0x27] "stdf", storef, 0,
  234. [0x25] "stfsr", storef,0,
  235. [0x26] "stdfq", storef,0,
  236. [0x34] "stc", loadc, 0, /* page 99 */
  237. [0x37] "stdc", loadc, 0,
  238. [0x35] "stcsr", loadcsr,0,
  239. [0x36] "stdcq", loadcsr,0,
  240. [0x0D] "ldstub", store, 0, /* page 101 */
  241. [0x1D] "ldstuba", storea, 0,
  242. [0x0F] "swap", load, 0, /* page 102 */
  243. [0x1F] "swapa", loada, 0,
  244. };
  245. #pragma varargck argpos bprint 2
  246. #pragma varargck type "T" char*
  247. /* convert to lower case from upper, according to dascase */
  248. static int
  249. Tfmt(Fmt *f)
  250. {
  251. char buf[128];
  252. char *s, *t, *oa;
  253. oa = va_arg(f->args, char*);
  254. if(dascase){
  255. for(s=oa,t=buf; *t = *s; s++,t++)
  256. if('A'<=*t && *t<='Z')
  257. *t += 'a'-'A';
  258. return fmtstrcpy(f, buf);
  259. }
  260. return fmtstrcpy(f, oa);
  261. }
  262. static void
  263. bprint(Instr *i, char *fmt, ...)
  264. {
  265. va_list arg;
  266. va_start(arg, fmt);
  267. i->curr = vseprint(i->curr, i->end, fmt, arg);
  268. va_end(arg);
  269. }
  270. static int
  271. decode(uint64_t pc, Instr *i)
  272. {
  273. uint32_t w;
  274. if (get4(mymap, pc, &w) < 0) {
  275. werrstr("can't read instruction: %r");
  276. return -1;
  277. }
  278. i->op = (w >> 30) & 0x03;
  279. i->rd = (w >> 25) & 0x1F;
  280. i->op2 = (w >> 22) & 0x07;
  281. i->a = (w >> 29) & 0x01;
  282. i->cond = (w >> 25) & 0x0F;
  283. i->op3 = (w >> 19) & 0x3F;
  284. i->rs1 = (w >> 14) & 0x1F;
  285. i->i = (w >> 13) & 0x01;
  286. i->asi = (w >> 5) & 0xFF;
  287. i->rs2 = (w >> 0) & 0x1F;
  288. i->simm13 = (w >> 0) & 0x1FFF;
  289. if(i->simm13 & (1<<12))
  290. i->simm13 |= ~((1<<13)-1);
  291. i->opf = (w >> 5) & 0x1FF;
  292. i->immdisp22 = (w >> 0) & 0x3FFFFF;
  293. i->simmdisp22 = i->immdisp22;
  294. if(i->simmdisp22 & (1<<21))
  295. i->simmdisp22 |= ~((1<<22)-1);
  296. i->disp30 = (w >> 0) & 0x3FFFFFFF;
  297. i->w0 = w;
  298. i->target = -1;
  299. i->addr = pc;
  300. i->size = 1;
  301. return 1;
  302. }
  303. static int
  304. mkinstr(uint64_t pc, Instr *i)
  305. {
  306. Instr xi;
  307. if (decode(pc, i) < 0)
  308. return -1;
  309. if(i->op==0 && i->op2==4 && !dascase){ /* SETHI */
  310. if (decode(pc+4, &xi) < 0)
  311. return -1;
  312. if(xi.op==2 && xi.op3==0) /* ADD */
  313. if(xi.i == 1 && xi.rs1 == i->rd){ /* immediate to same reg */
  314. i->imm32 = xi.simm13 + (i->immdisp22<<10);
  315. i->target = xi.rd;
  316. i->w1 = xi.w0;
  317. i->size++;
  318. return 1;
  319. }
  320. }
  321. if(i->op==2 && i->opf==1 && !dascase){ /* FMOVS */
  322. if (decode(pc+4, &xi) < 0)
  323. return -1;
  324. if(i->op==2 && i->opf==1) /* FMOVS */
  325. if(xi.rd==i->rd+1 && xi.rs2==i->rs2+1){ /* next pair */
  326. i->w1 = xi.w0;
  327. i->size++;
  328. }
  329. }
  330. return 1;
  331. }
  332. static int
  333. printins(Map *map, uint64_t pc, char *buf, int n)
  334. {
  335. Instr instr;
  336. void (*f)(Instr*, char*);
  337. mymap = map;
  338. memset(&instr, 0, sizeof(instr));
  339. instr.curr = buf;
  340. instr.end = buf+n-1;
  341. if (mkinstr(pc, &instr) < 0)
  342. return -1;
  343. switch(instr.op){
  344. case 0:
  345. f = sparcop0[instr.op2].f;
  346. if(f)
  347. (*f)(&instr, sparcop0[instr.op2].mnemonic);
  348. else
  349. bprint(&instr, "unknown %lux", instr.w0);
  350. break;
  351. case 1:
  352. bprint(&instr, "%T", "CALL\t");
  353. instr.curr += symoff(instr.curr, instr.end-instr.curr,
  354. pc+instr.disp30*4, CTEXT);
  355. if (!dascase)
  356. bprint(&instr, "(SB)");
  357. break;
  358. case 2:
  359. f = sparcop2[instr.op3].f;
  360. if(f)
  361. (*f)(&instr, sparcop2[instr.op3].mnemonic);
  362. else
  363. bprint(&instr, "unknown %lux", instr.w0);
  364. break;
  365. case 3:
  366. f = sparcop3[instr.op3].f;
  367. if(f)
  368. (*f)(&instr, sparcop3[instr.op3].mnemonic);
  369. else
  370. bprint(&instr, "unknown %lux", instr.w0);
  371. break;
  372. }
  373. if (instr.err) {
  374. if (instr.curr != buf)
  375. bprint(&instr, "\t\t;");
  376. bprint(&instr, instr.err);
  377. }
  378. return instr.size*4;
  379. }
  380. static int
  381. sparcinst(Map *map, uint64_t pc, char modifier, char *buf, int n)
  382. {
  383. static int fmtinstalled = 0;
  384. /* a modifier of 'I' toggles the dissassembler type */
  385. if (!fmtinstalled) {
  386. fmtinstalled = 1;
  387. fmtinstall('T', Tfmt);
  388. }
  389. if ((asstype == ASUNSPARC && modifier == 'i')
  390. || (asstype == ASPARC && modifier == 'I'))
  391. dascase = 'a'-'A';
  392. else
  393. dascase = 0;
  394. return printins(map, pc, buf, n);
  395. }
  396. static int
  397. sparcdas(Map *map, uint64_t pc, char *buf, int n)
  398. {
  399. Instr instr;
  400. mymap = map;
  401. memset(&instr, 0, sizeof(instr));
  402. instr.curr = buf;
  403. instr.end = buf+n-1;
  404. if (mkinstr(pc, &instr) < 0)
  405. return -1;
  406. if (instr.end-instr.curr > 8)
  407. instr.curr = _hexify(instr.curr, instr.w0, 7);
  408. if (instr.end-instr.curr > 9 && instr.size == 2) {
  409. *instr.curr++ = ' ';
  410. instr.curr = _hexify(instr.curr, instr.w1, 7);
  411. }
  412. *instr.curr = 0;
  413. return instr.size*4;
  414. }
  415. static int
  416. sparcinstlen(Map *map, uint64_t pc)
  417. {
  418. Instr i;
  419. mymap = map;
  420. if (mkinstr(pc, &i) < 0)
  421. return -1;
  422. return i.size*4;
  423. }
  424. static int
  425. plocal(Instr *i)
  426. {
  427. int offset;
  428. Symbol s;
  429. if (!findsym(i->addr, CTEXT, &s) || !findlocal(&s, FRAMENAME, &s))
  430. return -1;
  431. if (s.value > i->simm13) {
  432. if(getauto(&s, s.value-i->simm13, CAUTO, &s)) {
  433. bprint(i, "%s+%lld(SP)", s.name, s.value);
  434. return 1;
  435. }
  436. } else {
  437. offset = i->simm13-s.value;
  438. if (getauto(&s, offset-4, CPARAM, &s)) {
  439. bprint(i, "%s+%d(FP)", s.name, offset);
  440. return 1;
  441. }
  442. }
  443. return -1;
  444. }
  445. static void
  446. address(Instr *i)
  447. {
  448. Symbol s, s2;
  449. uint64_t off, off1;
  450. if (i->rs1 == 1 && plocal(i) >= 0)
  451. return;
  452. off = mach->sb+i->simm13;
  453. if(i->rs1 == 2 && findsym(off, CANY, &s)
  454. && s.value-off < 4096
  455. && (s.class == CDATA || s.class == CTEXT)) {
  456. if(off==s.value && s.name[0]=='$'){
  457. off1 = 0;
  458. geta(mymap, s.value, &off1);
  459. if(off1 && findsym(off1, CANY, &s2) && s2.value == off1){
  460. bprint(i, "$%s(SB)", s2.name);
  461. return;
  462. }
  463. }
  464. bprint(i, "%s", s.name);
  465. if (s.value != off)
  466. bprint(i, "+%llux", s.value-off);
  467. bprint(i, "(SB)");
  468. return;
  469. }
  470. bprint(i, "%ux(R%d)", i->simm13, i->rs1);
  471. }
  472. static void
  473. unimp(Instr *i, char *m)
  474. {
  475. bprint(i, "%T", m);
  476. }
  477. static char *bratab[16] = { /* page 91 */
  478. [0X8] "A",
  479. [0X0] "N",
  480. [0X9] "NE",
  481. [0X1] "E",
  482. [0XA] "G",
  483. [0X2] "LE",
  484. [0XB] "GE",
  485. [0X3] "L",
  486. [0XC] "GU",
  487. [0X4] "LEU",
  488. [0XD] "CC",
  489. [0X5] "CS",
  490. [0XE] "POS",
  491. [0X6] "NEG",
  492. [0XF] "VC",
  493. [0X7] "VS",
  494. };
  495. static char *fbratab[16] = { /* page 91 */
  496. [0X8] "A",
  497. [0X0] "N",
  498. [0X7] "U",
  499. [0X6] "G",
  500. [0X5] "UG",
  501. [0X4] "L",
  502. [0X3] "UL",
  503. [0X2] "LG",
  504. [0X1] "NE",
  505. [0X9] "E",
  506. [0XA] "UE",
  507. [0XB] "GE",
  508. [0XC] "UGE",
  509. [0XD] "LE",
  510. [0XE] "ULE",
  511. [0XF] "O",
  512. };
  513. static char *cbratab[16] = { /* page 91 */
  514. [0X8] "A",
  515. [0X0] "N",
  516. [0X7] "3",
  517. [0X6] "2",
  518. [0X5] "23",
  519. [0X4] "1",
  520. [0X3] "13",
  521. [0X2] "12",
  522. [0X1] "123",
  523. [0X9] "0",
  524. [0XA] "03",
  525. [0XB] "02",
  526. [0XC] "023",
  527. [0XD] "01",
  528. [0XE] "013",
  529. [0XF] "012",
  530. };
  531. static void
  532. bra1(Instr *i, char *m, char *tab[])
  533. {
  534. int32_t imm;
  535. imm = i->simmdisp22;
  536. if(i->a)
  537. bprint(i, "%T%T.%c\t", m, tab[i->cond], 'A'+dascase);
  538. else
  539. bprint(i, "%T%T\t", m, tab[i->cond]);
  540. i->curr += symoff(i->curr, i->end-i->curr, i->addr+4*imm, CTEXT);
  541. if (!dascase)
  542. bprint(i, "(SB)");
  543. }
  544. static void
  545. bra(Instr *i, char *m) /* page 91 */
  546. {
  547. bra1(i, m, bratab);
  548. }
  549. static void
  550. fbra(Instr *i, char *m) /* page 93 */
  551. {
  552. bra1(i, m, fbratab);
  553. }
  554. static void
  555. cbra(Instr *i, char *m) /* page 95 */
  556. {
  557. bra1(i, m, cbratab);
  558. }
  559. static void
  560. trap(Instr *i, char *m) /* page 101 */
  561. {
  562. if(i->i == 0)
  563. bprint(i, "%T%T\tR%d+R%d", m, bratab[i->cond], i->rs2, i->rs1);
  564. else
  565. bprint(i, "%T%T\t$%ux+R%d", m, bratab[i->cond], i->simm13, i->rs1);
  566. }
  567. static void
  568. sethi(Instr *i, char *m) /* page 89 */
  569. {
  570. uint32_t imm;
  571. imm = i->immdisp22<<10;
  572. if(dascase){
  573. bprint(i, "%T\t%lux, R%d", m, imm, i->rd);
  574. return;
  575. }
  576. if(imm==0 && i->rd==0){
  577. bprint(i, "NOP");
  578. return;
  579. }
  580. if(i->target < 0){
  581. bprint(i, "MOVW\t$%lux, R%d", imm, i->rd);
  582. return;
  583. }
  584. bprint(i, "MOVW\t$%lux, R%d", i->imm32, i->target);
  585. }
  586. static char ldtab[] = {
  587. 'W',
  588. 'B',
  589. 'H',
  590. 'D',
  591. };
  592. static char*
  593. moveinstr(int op3, char *m)
  594. {
  595. char *s;
  596. int c;
  597. static char buf[8];
  598. if(!dascase){
  599. /* batshit cases */
  600. if(op3 == 0xF || op3 == 0x1F)
  601. return "SWAP";
  602. if(op3 == 0xD || op3 == 0x1D)
  603. return "TAS"; /* really LDSTUB */
  604. c = ldtab[op3&3];
  605. s = "";
  606. if((op3&11)==1 || (op3&11)==2)
  607. s="U";
  608. sprint(buf, "MOV%c%s", c, s);
  609. return buf;
  610. }
  611. return m;
  612. }
  613. static void
  614. load(Instr *i, char *m) /* page 68 */
  615. {
  616. m = moveinstr(i->op3, m);
  617. if(i->i == 0)
  618. bprint(i, "%s\t(R%d+R%d), R%d", m, i->rs1, i->rs2, i->rd);
  619. else{
  620. bprint(i, "%s\t", m);
  621. address(i);
  622. bprint(i, ", R%d", i->rd);
  623. }
  624. }
  625. static void
  626. loada(Instr *i, char *m) /* page 68 */
  627. {
  628. m = moveinstr(i->op3, m);
  629. if(i->i == 0)
  630. bprint(i, "%s\t(R%d+R%d, %d), R%d", m, i->rs1, i->rs2, i->asi, i->rd);
  631. else
  632. bprint(i, "unknown ld asi %lux", i->w0);
  633. }
  634. static void
  635. store(Instr *i, char *m) /* page 74 */
  636. {
  637. m = moveinstr(i->op3, m);
  638. if(i->i == 0)
  639. bprint(i, "%s\tR%d, (R%d+R%d)",
  640. m, i->rd, i->rs1, i->rs2);
  641. else{
  642. bprint(i, "%s\tR%d, ", m, i->rd);
  643. address(i);
  644. }
  645. }
  646. static void
  647. storea(Instr *i, char *m) /* page 74 */
  648. {
  649. m = moveinstr(i->op3, m);
  650. if(i->i == 0)
  651. bprint(i, "%s\tR%d, (R%d+R%d, %d)", m, i->rd, i->rs1, i->rs2, i->asi);
  652. else
  653. bprint(i, "%s\tR%d, %d(R%d, %d), ???", m, i->rd, i->simm13, i->rs1, i->asi);
  654. }
  655. static void
  656. shift(Instr *i, char *m) /* page 88 */
  657. {
  658. if(i->i == 0){
  659. if(i->rs1 == i->rd)
  660. if(dascase)
  661. bprint(i, "%T\tR%d, R%d", m, i->rs1, i->rs2);
  662. else
  663. bprint(i, "%T\tR%d, R%d", m, i->rs2, i->rs1);
  664. else
  665. if(dascase)
  666. bprint(i, "%T\tR%d, R%d, R%d", m, i->rs1, i->rs2, i->rd);
  667. else
  668. bprint(i, "%T\tR%d, R%d, R%d", m, i->rs2, i->rs1, i->rd);
  669. }else{
  670. if(i->rs1 == i->rd)
  671. if(dascase)
  672. bprint(i, "%T\t$%d,R%d", m, i->simm13&0x1F, i->rs1);
  673. else
  674. bprint(i, "%T\tR%d, $%d", m, i->rs1, i->simm13&0x1F);
  675. else
  676. if(dascase)
  677. bprint(i, "%T\tR%d, $%d, R%d",m,i->rs1,i->simm13&0x1F,i->rd);
  678. else
  679. bprint(i, "%T\t$%d, R%d, R%d",m,i->simm13&0x1F,i->rs1,i->rd);
  680. }
  681. }
  682. static void
  683. add(Instr *i, char *m) /* page 82 */
  684. {
  685. if(i->i == 0){
  686. if(dascase)
  687. bprint(i, "%T\tR%d, R%d", m, i->rs1, i->rs2);
  688. else
  689. if(i->op3==2 && i->rs1==0 && i->rd) /* OR R2, R0, R1 */
  690. bprint(i, "MOVW\tR%d", i->rs2);
  691. else
  692. bprint(i, "%T\tR%d, R%d", m, i->rs2, i->rs1);
  693. }else{
  694. if(dascase)
  695. bprint(i, "%T\tR%d, $%ux", m, i->rs1, i->simm13);
  696. else
  697. if(i->op3==0 && i->rd && i->rs1==0) /* ADD $x, R0, R1 */
  698. bprint(i, "MOVW\t$%ux", i->simm13);
  699. else if(i->op3==0 && i->rd && i->rs1==2){
  700. /* ADD $x, R2, R1 -> MOVW $x(SB), R1 */
  701. bprint(i, "MOVW\t$");
  702. address(i);
  703. } else
  704. bprint(i, "%T\t$%ux, R%d", m, i->simm13, i->rs1);
  705. }
  706. if(i->rs1 != i->rd)
  707. bprint(i, ", R%d", i->rd);
  708. }
  709. static void
  710. cmp(Instr *i, char *m)
  711. {
  712. if(dascase || i->rd){
  713. add(i, m);
  714. return;
  715. }
  716. if(i->i == 0)
  717. bprint(i, "CMP\tR%d, R%d", i->rs1, i->rs2);
  718. else
  719. bprint(i, "CMP\tR%d, $%ux", i->rs1, i->simm13);
  720. }
  721. static char *regtab[4] = {
  722. "Y",
  723. "PSR",
  724. "WIM",
  725. "TBR",
  726. };
  727. static void
  728. wr(Instr *i, char *m) /* page 82 */
  729. {
  730. if(dascase){
  731. if(i->i == 0)
  732. bprint(i, "%s\tR%d, R%d", m, i->rs1, i->rs2);
  733. else
  734. bprint(i, "%s\tR%d, $%ux", m, i->rs1, i->simm13);
  735. }else{
  736. if(i->i && i->simm13==0)
  737. bprint(i, "MOVW\tR%d", i->rs1);
  738. else if(i->i == 0)
  739. bprint(i, "wr\tR%d, R%d", i->rs2, i->rs1);
  740. else
  741. bprint(i, "wr\t$%ux, R%d", i->simm13, i->rs1);
  742. }
  743. bprint(i, ", %s", regtab[i->op3&3]);
  744. }
  745. static void
  746. rd(Instr *i, char *m) /* page 103 */
  747. {
  748. if(i->rs1==15 && i->rd==0){
  749. m = "stbar";
  750. if(!dascase)
  751. m = "STBAR";
  752. bprint(i, "%s", m);
  753. }else{
  754. if(!dascase)
  755. m = "MOVW";
  756. bprint(i, "%s\t%s, R%d", m, regtab[i->op3&3], i->rd);
  757. }
  758. }
  759. static void
  760. jmpl(Instr *i, char *m) /* page 82 */
  761. {
  762. if(i->i == 0){
  763. if(i->rd == 15)
  764. bprint(i, "%T\t(R%d+R%d)", "CALL", i->rs2, i->rs1);
  765. else
  766. bprint(i, "%T\t(R%d+R%d), R%d", m, i->rs2, i->rs1, i->rd);
  767. }else{
  768. if(!dascase && i->simm13==8 && i->rs1==15 && i->rd==0)
  769. bprint(i, "RETURN");
  770. else{
  771. bprint(i, "%T\t", m);
  772. address(i);
  773. bprint(i, ", R%d", i->rd);
  774. }
  775. }
  776. }
  777. static void
  778. loadf(Instr *i, char *m) /* page 70 */
  779. {
  780. if(!dascase){
  781. m = "FMOVD";
  782. if(i->op3 == 0x20)
  783. m = "FMOVF";
  784. else if(i->op3 == 0x21)
  785. m = "MOVW";
  786. }
  787. if(i->i == 0)
  788. bprint(i, "%s\t(R%d+R%d)", m, i->rs1, i->rs2);
  789. else{
  790. bprint(i, "%s\t", m);
  791. address(i);
  792. }
  793. if(i->op3 == 0x21)
  794. bprint(i, ", FSR");
  795. else
  796. bprint(i, ", R%d", i->rd);
  797. }
  798. static void
  799. storef(Instr *i, char *m) /* page 70 */
  800. {
  801. if(!dascase){
  802. m = "FMOVD";
  803. if(i->op3 == 0x25 || i->op3 == 0x26)
  804. m = "MOVW";
  805. else if(i->op3 == 0x20)
  806. m = "FMOVF";
  807. }
  808. bprint(i, "%s\t", m);
  809. if(i->op3 == 0x25)
  810. bprint(i, "FSR, ");
  811. else if(i->op3 == 0x26)
  812. bprint(i, "FQ, ");
  813. else
  814. bprint(i, "R%d, ", i->rd);
  815. if(i->i == 0)
  816. bprint(i, "(R%d+R%d)", i->rs1, i->rs2);
  817. else
  818. address(i);
  819. }
  820. static void
  821. loadc(Instr *i, char *m) /* page 72 */
  822. {
  823. if(i->i == 0)
  824. bprint(i, "%s\t(R%d+R%d), C%d", m, i->rs1, i->rs2, i->rd);
  825. else{
  826. bprint(i, "%s\t", m);
  827. address(i);
  828. bprint(i, ", C%d", i->rd);
  829. }
  830. }
  831. static void
  832. loadcsr(Instr *i, char *m) /* page 72 */
  833. {
  834. if(i->i == 0)
  835. bprint(i, "%s\t(R%d+R%d), CSR", m, i->rs1, i->rs2);
  836. else{
  837. bprint(i, "%s\t", m);
  838. address(i);
  839. bprint(i, ", CSR");
  840. }
  841. }
  842. static struct{
  843. int opf;
  844. char *name;
  845. } fptab1[] = { /* ignores rs1 */
  846. 0xC4, "FITOS", /* page 109 */
  847. 0xC8, "FITOD",
  848. 0xCC, "FITOX",
  849. 0xD1, "FSTOI", /* page 110 */
  850. 0xD2, "FDTOI",
  851. 0xD3, "FXTOI",
  852. 0xC9, "FSTOD", /* page 111 */
  853. 0xCD, "FSTOX",
  854. 0xC6, "FDTOS",
  855. 0xCE, "FDTOX",
  856. 0xC7, "FXTOS",
  857. 0xCB, "FXTOD",
  858. 0x01, "FMOVS", /* page 112 */
  859. 0x05, "FNEGS",
  860. 0x09, "FABSS",
  861. 0x29, "FSQRTS", /* page 113 */
  862. 0x2A, "FSQRTD",
  863. 0x2B, "FSQRTX",
  864. 0, 0,
  865. };
  866. static struct{
  867. int opf;
  868. char *name;
  869. } fptab2[] = { /* uses rs1 */
  870. 0x41, "FADDS", /* page 114 */
  871. 0x42, "FADDD",
  872. 0x43, "FADDX",
  873. 0x45, "FSUBS",
  874. 0x46, "FSUBD",
  875. 0x47, "FSUBX",
  876. 0x49, "FMULS", /* page 115 */
  877. 0x4A, "FMULD",
  878. 0x4B, "FMULX",
  879. 0x4D, "FDIVS",
  880. 0x4E, "FDIVD",
  881. 0x4F, "FDIVX",
  882. 0x51, "FCMPS", /* page 116 */
  883. 0x52, "FCMPD",
  884. 0x53, "FCMPX",
  885. 0x55, "FCMPES",
  886. 0x56, "FCMPED",
  887. 0x57, "FCMPEX",
  888. 0, 0
  889. };
  890. static void
  891. fpop(Instr *i, char *m) /* page 108-116 */
  892. {
  893. int j;
  894. if(dascase==0 && i->size==2){
  895. bprint(i, "FMOVD\tF%d, F%d", i->rs2, i->rd);
  896. return;
  897. }
  898. for(j=0; fptab1[j].name; j++)
  899. if(fptab1[j].opf == i->opf){
  900. bprint(i, "%T\tF%d, F%d", fptab1[j].name, i->rs2, i->rd);
  901. return;
  902. }
  903. for(j=0; fptab2[j].name; j++)
  904. if(fptab2[j].opf == i->opf){
  905. bprint(i, "%T\tF%d, F%d, F%d", fptab2[j].name, i->rs1, i->rs2, i->rd);
  906. return;
  907. }
  908. bprint(i, "%T%ux\tF%d, F%d, F%d", m, i->opf, i->rs1, i->rs2, i->rd);
  909. }
  910. static int
  911. sparcfoll(Map *map, uint64_t pc, Rgetter rget, uint64_t *foll)
  912. {
  913. uint32_t w, r1, r2;
  914. char buf[8];
  915. Instr i;
  916. mymap = map;
  917. if (mkinstr(pc, &i) < 0)
  918. return -1;
  919. w = i.w0;
  920. switch(w & 0xC1C00000){
  921. case 0x00800000: /* branch on int cond */
  922. case 0x01800000: /* branch on fp cond */
  923. case 0x01C00000: /* branch on copr cond */
  924. foll[0] = pc+8;
  925. foll[1] = pc + (i.simmdisp22<<2);
  926. return 2;
  927. }
  928. if((w&0xC0000000) == 0x40000000){ /* CALL */
  929. foll[0] = pc + (i.disp30<<2);
  930. return 1;
  931. }
  932. if((w&0xC1F80000) == 0x81C00000){ /* JMPL */
  933. sprint(buf, "R%ld", (w>>14)&0xF);
  934. r1 = (*rget)(map, buf);
  935. if(w & 0x2000) /* JMPL R1+simm13 */
  936. r2 = i.simm13;
  937. else{ /* JMPL R1+R2 */
  938. sprint(buf, "R%ld", w&0xF);
  939. r2 = (*rget)(map, buf);
  940. }
  941. foll[0] = r1 + r2;
  942. return 1;
  943. }
  944. foll[0] = pc+i.size*4;
  945. return 1;
  946. }