kdb.c 21 KB

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