vcodas.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569
  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. /* mips native disassembler */
  14. typedef struct {
  15. uint64_t addr; /* pc of instr */
  16. uint8_t op; /* bits 31-26 */
  17. uint8_t rs; /* bits 25-21 */
  18. uint8_t rt; /* bits 20-16 */
  19. uint8_t rd; /* bits 15-11 */
  20. uint8_t sa; /* bits 10-6 */
  21. uint8_t function; /* bits 5-0 */
  22. int32_t immediate; /* bits 15-0 */
  23. uint32_t cofun; /* bits 24-0 */
  24. uint32_t target; /* bits 25-0 */
  25. int32_t w0;
  26. char *curr; /* current fill point */
  27. char *end; /* end of buffer */
  28. char *err;
  29. } Instr;
  30. typedef struct {
  31. char *mnemonic;
  32. char *mipsco;
  33. } Opcode;
  34. static char mipscoload[] = "r%t,%l";
  35. static char mipscoalui[] = "r%t,r%s,%i";
  36. static char mipscoalu3op[] = "r%d,r%s,r%t";
  37. static char mipscoboc[] = "r%s,r%t,%b";
  38. static char mipscoboc0[] = "r%s,%b";
  39. static char mipscorsrt[] = "r%s,r%t";
  40. static char mipscorsi[] = "r%s,%i";
  41. static char mipscoxxx[] = "%w";
  42. static char mipscofp3[] = "f%a,f%d,f%t"; /* fd,fs,ft */
  43. static char mipscofp2[] = "f%a,f%d"; /* fd,fs */
  44. static char mipscofpc[] = "f%d,f%t"; /* fs,ft */
  45. static Opcode opcodes[64] = {
  46. 0, 0,
  47. 0, 0,
  48. "j", "%j",
  49. "jal", "%j",
  50. "beq", mipscoboc,
  51. "bne", mipscoboc,
  52. "blez", mipscoboc0,
  53. "bgtz", mipscoboc0,
  54. "addi", mipscoalui,
  55. "addiu", mipscoalui,
  56. "slti", mipscoalui,
  57. "sltiu", mipscoalui,
  58. "andi", mipscoalui,
  59. "ori", mipscoalui,
  60. "xori", mipscoalui,
  61. "lui", "r%t,%u",
  62. "cop0", 0,
  63. "cop1", 0,
  64. "cop2", 0,
  65. "cop3", 0,
  66. "beql", mipscoboc,
  67. "bnel", mipscoboc,
  68. "blezl", mipscoboc0,
  69. "bgtzl", mipscoboc0,
  70. "instr18", mipscoxxx,
  71. "instr19", mipscoxxx,
  72. "instr1A", mipscoxxx,
  73. "instr1B", mipscoxxx,
  74. "instr1C", mipscoxxx,
  75. "instr1D", mipscoxxx,
  76. "instr1E", mipscoxxx,
  77. "instr1F", mipscoxxx,
  78. "lb", mipscoload,
  79. "lh", mipscoload,
  80. "lwl", mipscoload,
  81. "lw", mipscoload,
  82. "lbu", mipscoload,
  83. "lhu", mipscoload,
  84. "lwr", mipscoload,
  85. "instr27", mipscoxxx,
  86. "sb", mipscoload,
  87. "sh", mipscoload,
  88. "swl", mipscoload,
  89. "sw", mipscoload,
  90. "instr2C", mipscoxxx,
  91. "instr2D", mipscoxxx,
  92. "swr", mipscoload,
  93. "cache", "",
  94. "ll", mipscoload,
  95. "lwc1", mipscoload,
  96. "lwc2", mipscoload,
  97. "lwc3", mipscoload,
  98. "instr34", mipscoxxx,
  99. "ld", mipscoload,
  100. "ld", mipscoload,
  101. "ld", mipscoload,
  102. "sc", mipscoload,
  103. "swc1", mipscoload,
  104. "swc2", mipscoload,
  105. "swc3", mipscoload,
  106. "instr3C", mipscoxxx,
  107. "sd", mipscoload,
  108. "sd", mipscoload,
  109. "sd", mipscoload,
  110. };
  111. static Opcode sopcodes[64] = {
  112. "sll", "r%d,r%t,$%a",
  113. "special01", mipscoxxx,
  114. "srl", "r%d,r%t,$%a",
  115. "sra", "r%d,r%t,$%a",
  116. "sllv", "r%d,r%t,R%s",
  117. "special05", mipscoxxx,
  118. "srlv", "r%d,r%t,r%s",
  119. "srav", "r%d,r%t,r%s",
  120. "jr", "r%s",
  121. "jalr", "r%d,r%s",
  122. "special0A", mipscoxxx,
  123. "special0B", mipscoxxx,
  124. "syscall", "",
  125. "break", "",
  126. "special0E", mipscoxxx,
  127. "sync", "",
  128. "mfhi", "r%d",
  129. "mthi", "r%s",
  130. "mflo", "r%d",
  131. "mtlo", "r%s",
  132. "special14", mipscoxxx,
  133. "special15", mipscoxxx,
  134. "special16", mipscoxxx,
  135. "special17", mipscoxxx,
  136. "mult", mipscorsrt,
  137. "multu", mipscorsrt,
  138. "div", mipscorsrt,
  139. "divu", mipscorsrt,
  140. "special1C", mipscoxxx,
  141. "special1D", mipscoxxx,
  142. "special1E", mipscoxxx,
  143. "special1F", mipscoxxx,
  144. "add", mipscoalu3op,
  145. "addu", mipscoalu3op,
  146. "sub", mipscoalu3op,
  147. "subu", mipscoalu3op,
  148. "and", mipscoalu3op,
  149. "or", mipscoalu3op,
  150. "xor", mipscoalu3op,
  151. "nor", mipscoalu3op,
  152. "special28", mipscoxxx,
  153. "special29", mipscoxxx,
  154. "slt", mipscoalu3op,
  155. "sltu", mipscoalu3op,
  156. "special2C", mipscoxxx,
  157. "special2D", mipscoxxx,
  158. "special2E", mipscoxxx,
  159. "special2F", mipscoxxx,
  160. "tge", mipscorsrt,
  161. "tgeu", mipscorsrt,
  162. "tlt", mipscorsrt,
  163. "tltu", mipscorsrt,
  164. "teq", mipscorsrt,
  165. "special35", mipscoxxx,
  166. "tne", mipscorsrt,
  167. "special37", mipscoxxx,
  168. "special38", mipscoxxx,
  169. "special39", mipscoxxx,
  170. "special3A", mipscoxxx,
  171. "special3B", mipscoxxx,
  172. "special3C", mipscoxxx,
  173. "special3D", mipscoxxx,
  174. "special3E", mipscoxxx,
  175. "special3F", mipscoxxx,
  176. };
  177. static Opcode ropcodes[32] = {
  178. "bltz", mipscoboc0,
  179. "bgez", mipscoboc0,
  180. "bltzl", mipscoboc0,
  181. "bgezl", mipscoboc0,
  182. "regimm04", mipscoxxx,
  183. "regimm05", mipscoxxx,
  184. "regimm06", mipscoxxx,
  185. "regimm07", mipscoxxx,
  186. "tgei", mipscorsi,
  187. "tgeiu", mipscorsi,
  188. "tlti", mipscorsi,
  189. "tltiu", mipscorsi,
  190. "teqi", mipscorsi,
  191. "regimm0D", mipscoxxx,
  192. "tnei", mipscorsi,
  193. "regimm0F", mipscoxxx,
  194. "bltzal", mipscoboc0,
  195. "bgezal", mipscoboc0,
  196. "bltzall", mipscoboc0,
  197. "bgezall", mipscoboc0,
  198. "regimm14", mipscoxxx,
  199. "regimm15", mipscoxxx,
  200. "regimm16", mipscoxxx,
  201. "regimm17", mipscoxxx,
  202. "regimm18", mipscoxxx,
  203. "regimm19", mipscoxxx,
  204. "regimm1A", mipscoxxx,
  205. "regimm1B", mipscoxxx,
  206. "regimm1C", mipscoxxx,
  207. "regimm1D", mipscoxxx,
  208. "regimm1E", mipscoxxx,
  209. "regimm1F", mipscoxxx,
  210. };
  211. static Opcode fopcodes[64] = {
  212. "add.%f", mipscofp3,
  213. "sub.%f", mipscofp3,
  214. "mul.%f", mipscofp3,
  215. "div.%f", mipscofp3,
  216. "sqrt.%f", mipscofp2,
  217. "abs.%f", mipscofp2,
  218. "mov.%f", mipscofp2,
  219. "neg.%f", mipscofp2,
  220. "finstr08", mipscoxxx,
  221. "finstr09", mipscoxxx,
  222. "finstr0A", mipscoxxx,
  223. "finstr0B", mipscoxxx,
  224. "round.w.%f", mipscofp2,
  225. "trunc.w%f", mipscofp2,
  226. "ceil.w%f", mipscofp2,
  227. "floor.w%f", mipscofp2,
  228. "finstr10", mipscoxxx,
  229. "finstr11", mipscoxxx,
  230. "finstr12", mipscoxxx,
  231. "finstr13", mipscoxxx,
  232. "finstr14", mipscoxxx,
  233. "finstr15", mipscoxxx,
  234. "finstr16", mipscoxxx,
  235. "finstr17", mipscoxxx,
  236. "finstr18", mipscoxxx,
  237. "finstr19", mipscoxxx,
  238. "finstr1A", mipscoxxx,
  239. "finstr1B", mipscoxxx,
  240. "finstr1C", mipscoxxx,
  241. "finstr1D", mipscoxxx,
  242. "finstr1E", mipscoxxx,
  243. "finstr1F", mipscoxxx,
  244. "cvt.s.%f", mipscofp2,
  245. "cvt.d.%f", mipscofp2,
  246. "cvt.e.%f", mipscofp2,
  247. "cvt.q.%f", mipscofp2,
  248. "cvt.w.%f", mipscofp2,
  249. "finstr25", mipscoxxx,
  250. "finstr26", mipscoxxx,
  251. "finstr27", mipscoxxx,
  252. "finstr28", mipscoxxx,
  253. "finstr29", mipscoxxx,
  254. "finstr2A", mipscoxxx,
  255. "finstr2B", mipscoxxx,
  256. "finstr2C", mipscoxxx,
  257. "finstr2D", mipscoxxx,
  258. "finstr2E", mipscoxxx,
  259. "finstr2F", mipscoxxx,
  260. "c.f.%f", mipscofpc,
  261. "c.un.%f", mipscofpc,
  262. "c.eq.%f", mipscofpc,
  263. "c.ueq.%f", mipscofpc,
  264. "c.olt.%f", mipscofpc,
  265. "c.ult.%f", mipscofpc,
  266. "c.ole.%f", mipscofpc,
  267. "c.ule.%f", mipscofpc,
  268. "c.sf.%f", mipscofpc,
  269. "c.ngle.%f", mipscofpc,
  270. "c.seq.%f", mipscofpc,
  271. "c.ngl.%f", mipscofpc,
  272. "c.lt.%f", mipscofpc,
  273. "c.nge.%f", mipscofpc,
  274. "c.le.%f", mipscofpc,
  275. "c.ngt.%f", mipscofpc,
  276. };
  277. static char fsub[16] = {
  278. 's', 'd', 'e', 'q', 'w', '?', '?', '?',
  279. '?', '?', '?', '?', '?', '?', '?', '?'
  280. };
  281. static int
  282. mkinstr(Instr *i, Map *map, uint64_t pc)
  283. {
  284. uint32_t w;
  285. if (get4(map, pc, &w) < 0) {
  286. werrstr("can't read instruction: %r");
  287. return -1;
  288. }
  289. i->addr = pc;
  290. i->op = (w >> 26) & 0x3F;
  291. i->rs = (w >> 21) & 0x1F;
  292. i->rt = (w >> 16) & 0x1F;
  293. i->rd = (w >> 11) & 0x1F;
  294. i->sa = (w >> 6) & 0x1F;
  295. i->function = w & 0x3F;
  296. i->immediate = w & 0x0000FFFF;
  297. if (i->immediate & 0x8000)
  298. i->immediate |= ~0x0000FFFF;
  299. i->cofun = w & 0x01FFFFFF;
  300. i->target = w & 0x03FFFFFF;
  301. i->w0 = w;
  302. return 1;
  303. }
  304. #pragma varargck argpos bprint 2
  305. static void
  306. bprint(Instr *i, char *fmt, ...)
  307. {
  308. va_list arg;
  309. va_start(arg, fmt);
  310. i->curr = vseprint(i->curr, i->end, fmt, arg);
  311. va_end(arg);
  312. }
  313. static void
  314. format(char *mnemonic, Instr *i, char *f)
  315. {
  316. if (mnemonic)
  317. format(0, i, mnemonic);
  318. if (f == 0)
  319. return;
  320. if (i->curr < i->end)
  321. *i->curr++ = '\t';
  322. for ( ; *f && i->curr < i->end; f++) {
  323. if (*f != '%') {
  324. *i->curr++ = *f;
  325. continue;
  326. }
  327. switch (*++f) {
  328. case 's':
  329. bprint(i, "%d", i->rs);
  330. break;
  331. case 't':
  332. bprint(i, "%d", i->rt);
  333. break;
  334. case 'd':
  335. bprint(i, "%d", i->rd);
  336. break;
  337. case 'a':
  338. bprint(i, "%d", i->sa);
  339. break;
  340. case 'l':
  341. if (i->rs == 30) {
  342. i->curr += symoff(i->curr, i->end-i->curr, i->immediate+mach->sb, CANY);
  343. bprint(i, "(SB)");
  344. } else
  345. bprint(i, "%lx(r%d)", i->immediate, i->rs);
  346. break;
  347. case 'i':
  348. bprint(i, "$%lx", i->immediate);
  349. break;
  350. case 'u':
  351. *i->curr++ = '$';
  352. i->curr += symoff(i->curr, i->end-i->curr, i->immediate, CANY);
  353. bprint(i, "(SB)");
  354. break;
  355. case 'j':
  356. i->curr += symoff(i->curr, i->end-i->curr,
  357. (i->target<<2)|(i->addr & 0xF0000000), CANY);
  358. bprint(i, "(SB)");
  359. break;
  360. case 'b':
  361. i->curr += symoff(i->curr, i->end-i->curr,
  362. (i->immediate<<2)+i->addr+4, CANY);
  363. break;
  364. case 'c':
  365. bprint(i, "%lux", i->cofun);
  366. break;
  367. case 'w':
  368. bprint(i, "[%lux]", i->w0);
  369. break;
  370. case 'f':
  371. *i->curr++ = fsub[i->rs & 0x0F];
  372. break;
  373. case '\0':
  374. *i->curr++ = '%';
  375. return;
  376. default:
  377. bprint(i, "%%%c", *f);
  378. break;
  379. }
  380. }
  381. }
  382. static void
  383. copz(int cop, Instr *i)
  384. {
  385. char *f, *m, buf[16];
  386. m = buf;
  387. f = "%t,%d";
  388. switch (i->rs) {
  389. case 0:
  390. sprint(buf, "mfc%d", cop);
  391. break;
  392. case 2:
  393. sprint(buf, "cfc%d", cop);
  394. break;
  395. case 4:
  396. sprint(buf, "mtc%d", cop);
  397. break;
  398. case 6:
  399. sprint(buf, "ctc%d", cop);
  400. break;
  401. case 8:
  402. f = "%b";
  403. switch (i->rt) {
  404. case 0:
  405. sprint(buf, "bc%df", cop);
  406. break;
  407. case 1:
  408. sprint(buf, "bc%dt", cop);
  409. break;
  410. case 2:
  411. sprint(buf, "bc%dfl", cop);
  412. break;
  413. case 3:
  414. sprint(buf, "bc%dtl", cop);
  415. break;
  416. default:
  417. sprint(buf, "cop%d", cop);
  418. f = mipscoxxx;
  419. break;
  420. }
  421. break;
  422. default:
  423. sprint(buf, "cop%d", cop);
  424. if (i->rs & 0x10)
  425. f = "function %c";
  426. else
  427. f = mipscoxxx;
  428. break;
  429. }
  430. format(m, i, f);
  431. }
  432. static void
  433. cop0(Instr *i)
  434. {
  435. char *m = 0;
  436. if (i->rs >= 0x10) {
  437. switch (i->cofun) {
  438. case 1:
  439. m = "tlbr";
  440. break;
  441. case 2:
  442. m = "tlbwi";
  443. break;
  444. case 6:
  445. m = "tlbwr";
  446. break;
  447. case 8:
  448. m = "tlbp";
  449. break;
  450. case 16:
  451. m = "rfe";
  452. break;
  453. case 24:
  454. m = "eret";
  455. break;
  456. case 32:
  457. m = "wait";
  458. break;
  459. }
  460. if (m) {
  461. format(m, i, 0);
  462. if (i->curr < i->end)
  463. *i->curr++ = 0;
  464. return;
  465. }
  466. }
  467. copz(0, i);
  468. }
  469. int
  470. _mipscoinst(Map *map, uint64_t pc, char *buf, int n)
  471. {
  472. Instr i;
  473. Opcode *o;
  474. uint8_t op;
  475. i.curr = buf;
  476. i.end = buf+n-1;
  477. if (mkinstr(&i, map, pc) < 0)
  478. return -1;
  479. switch (i.op) {
  480. case 0x00: /* SPECIAL */
  481. o = sopcodes;
  482. op = i.function;
  483. break;
  484. case 0x01: /* REGIMM */
  485. o = ropcodes;
  486. op = i.rt;
  487. break;
  488. case 0x10: /* COP0 */
  489. cop0(&i);
  490. return 4;
  491. case 0x11: /* COP1 */
  492. if (i.rs & 0x10) {
  493. o = fopcodes;
  494. op = i.function;
  495. break;
  496. }
  497. /*FALLTHROUGH*/
  498. case 0x12: /* COP2 */
  499. case 0x13: /* COP3 */
  500. copz(i.op-0x10, &i);
  501. return 4;
  502. default:
  503. o = opcodes;
  504. op = i.op;
  505. break;
  506. }
  507. format(o[op].mnemonic, &i, o[op].mipsco);
  508. return 4;
  509. }