sparc64db.c 22 KB

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