vcodas.c 10 KB

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