vdb.c 22 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147
  1. #include <u.h>
  2. #include <libc.h>
  3. #include <bio.h>
  4. #include <mach.h>
  5. /*
  6. * Mips-specific debugger interface
  7. */
  8. static char *mipsexcep(Map*, Rgetter);
  9. static int mipsfoll(Map*, uvlong, Rgetter, uvlong*);
  10. static int mipsinst(Map*, uvlong, char, char*, int);
  11. static int mipsdas(Map*, uvlong, char*, int);
  12. static int mipsinstlen(Map*, uvlong);
  13. /*
  14. * Debugger interface
  15. */
  16. Machdata mipsmach =
  17. {
  18. {0, 0, 0, 0xD}, /* break point */
  19. 4, /* break point size */
  20. beswab, /* short to local byte order */
  21. beswal, /* long to local byte order */
  22. beswav, /* vlong to local byte order */
  23. risctrace, /* C traceback */
  24. riscframe, /* Frame finder */
  25. mipsexcep, /* print exception */
  26. 0, /* breakpoint fixup */
  27. beieeesftos, /* single precision float printer */
  28. beieeedftos, /* double precisioin float printer */
  29. mipsfoll, /* following addresses */
  30. mipsinst, /* print instruction */
  31. mipsdas, /* dissembler */
  32. mipsinstlen, /* instruction size */
  33. };
  34. /*
  35. * mips r4k little-endian
  36. */
  37. Machdata mipsmach2le =
  38. {
  39. {0, 0, 0, 0xD}, /* break point */
  40. 4, /* break point size */
  41. leswab, /* short to local byte order */
  42. leswal, /* long to local byte order */
  43. leswav, /* vlong to local byte order */
  44. risctrace, /* C traceback */
  45. riscframe, /* Frame finder */
  46. mipsexcep, /* print exception */
  47. 0, /* breakpoint fixup */
  48. leieeesftos, /* single precision float printer */
  49. leieeedftos, /* double precisioin float printer */
  50. mipsfoll, /* following addresses */
  51. mipsinst, /* print instruction */
  52. mipsdas, /* dissembler */
  53. mipsinstlen, /* instruction size */
  54. };
  55. /*
  56. * mips r4k big-endian
  57. */
  58. Machdata mipsmach2be =
  59. {
  60. {0, 0, 0, 0xD}, /* break point */
  61. 4, /* break point size */
  62. beswab, /* short to local byte order */
  63. beswal, /* long to local byte order */
  64. beswav, /* vlong to local byte order */
  65. risctrace, /* C traceback */
  66. riscframe, /* Frame finder */
  67. mipsexcep, /* print exception */
  68. 0, /* breakpoint fixup */
  69. beieeesftos, /* single precision float printer */
  70. beieeedftos, /* double precisioin float printer */
  71. mipsfoll, /* following addresses */
  72. mipsinst, /* print instruction */
  73. mipsdas, /* dissembler */
  74. mipsinstlen, /* instruction size */
  75. };
  76. static char *excname[] =
  77. {
  78. "external interrupt",
  79. "TLB modification",
  80. "TLB miss (load or fetch)",
  81. "TLB miss (store)",
  82. "address error (load or fetch)",
  83. "address error (store)",
  84. "bus error (fetch)",
  85. "bus error (data load or store)",
  86. "system call",
  87. "breakpoint",
  88. "reserved instruction",
  89. "coprocessor unusable",
  90. "arithmetic overflow",
  91. "undefined 13",
  92. "undefined 14",
  93. "system call",
  94. /* the following is made up */
  95. "floating point exception" /* FPEXC */
  96. };
  97. static char*
  98. mipsexcep(Map *map, Rgetter rget)
  99. {
  100. int e;
  101. long c;
  102. c = (*rget)(map, "CAUSE");
  103. if(c & 0x00002000) /* INTR3 */
  104. e = 16; /* Floating point exception */
  105. else
  106. e = (c>>2)&0x0F;
  107. return excname[e];
  108. }
  109. /* mips disassembler and related functions */
  110. static char FRAMENAME[] = ".frame";
  111. typedef struct {
  112. uvlong addr;
  113. uchar op; /* bits 31-26 */
  114. uchar rs; /* bits 25-21 */
  115. uchar rt; /* bits 20-16 */
  116. uchar rd; /* bits 15-11 */
  117. uchar sa; /* bits 10-6 */
  118. uchar function; /* bits 5-0 */
  119. long immediate; /* bits 15-0 */
  120. ulong cofun; /* bits 24-0 */
  121. ulong target; /* bits 25-0 */
  122. long w0;
  123. long w1;
  124. int size; /* instruction size */
  125. char *curr; /* fill point in buffer */
  126. char *end; /* end of buffer */
  127. char *err; /* error message */
  128. } Instr;
  129. static Map *mymap;
  130. static int
  131. decode(uvlong pc, Instr *i)
  132. {
  133. ulong w;
  134. extern Mach mmips2le;
  135. if (get4(mymap, pc, &w) < 0) {
  136. werrstr("can't read instruction: %r");
  137. return -1;
  138. }
  139. i->addr = pc;
  140. i->size = 1;
  141. i->op = (w >> 26) & 0x3F;
  142. i->rs = (w >> 21) & 0x1F;
  143. i->rt = (w >> 16) & 0x1F;
  144. i->rd = (w >> 11) & 0x1F;
  145. i->sa = (w >> 6) & 0x1F;
  146. i->function = w & 0x3F;
  147. i->immediate = w & 0x0000FFFF;
  148. if (i->immediate & 0x8000)
  149. i->immediate |= ~0x0000FFFF;
  150. i->cofun = w & 0x01FFFFFF;
  151. i->target = w & 0x03FFFFFF;
  152. i->w0 = w;
  153. return 1;
  154. }
  155. static int
  156. mkinstr(uvlong pc, Instr *i)
  157. {
  158. Instr x;
  159. if (decode(pc, i) < 0)
  160. return -1;
  161. /*
  162. * if it's a LUI followed by an ORI,
  163. * it's an immediate load of a large constant.
  164. * fix the LUI immediate in any case.
  165. */
  166. if (i->op == 0x0F) {
  167. if (decode(pc+4, &x) < 0)
  168. return 0;
  169. i->immediate <<= 16;
  170. if (x.op == 0x0D && x.rs == x.rt && x.rt == i->rt) {
  171. i->immediate |= (x.immediate & 0xFFFF);
  172. i->w1 = x.w0;
  173. i->size++;
  174. return 1;
  175. }
  176. }
  177. /*
  178. * if it's a LWC1 followed by another LWC1
  179. * into an adjacent register, it's a load of
  180. * a floating point double.
  181. */
  182. else if (i->op == 0x31 && (i->rt & 0x01)) {
  183. if (decode(pc+4, &x) < 0)
  184. return 0;
  185. if (x.op == 0x31 && x.rt == (i->rt - 1) && x.rs == i->rs) {
  186. i->rt -= 1;
  187. i->w1 = x.w0;
  188. i->size++;
  189. return 1;
  190. }
  191. }
  192. /*
  193. * similarly for double stores
  194. */
  195. else if (i->op == 0x39 && (i->rt & 0x01)) {
  196. if (decode(pc+4, &x) < 0)
  197. return 0;
  198. if (x.op == 0x39 && x.rt == (i->rt - 1) && x.rs == i->rs) {
  199. i->rt -= 1;
  200. i->w1 = x.w0;
  201. i->size++;
  202. }
  203. }
  204. return 1;
  205. }
  206. #pragma varargck argpos bprint 2
  207. static void
  208. bprint(Instr *i, char *fmt, ...)
  209. {
  210. va_list arg;
  211. va_start(arg, fmt);
  212. i->curr = vseprint(i->curr, i->end, fmt, arg);
  213. va_end(arg);
  214. }
  215. typedef struct Opcode Opcode;
  216. struct Opcode {
  217. char *mnemonic;
  218. void (*f)(Opcode *, Instr *);
  219. char *ken;
  220. };
  221. static void format(char *, Instr *, char *);
  222. static void
  223. branch(Opcode *o, Instr *i)
  224. {
  225. if (i->rs == 0 && i->rt == 0)
  226. format("JMP", i, "%b");
  227. else if (i->rs == 0)
  228. format(o->mnemonic, i, "R%t,%b");
  229. else if (i->rt < 2)
  230. format(o->mnemonic, i, "R%s,%b");
  231. else
  232. format(o->mnemonic, i, "R%s,R%t,%b");
  233. }
  234. static void
  235. addi(Opcode *o, Instr *i)
  236. {
  237. if (i->rs == i->rt)
  238. format(o->mnemonic, i, "%i,R%t");
  239. else if (i->rs == 0)
  240. format("MOVW", i, "%i,R%t");
  241. else if (i->rs == 30) {
  242. bprint(i, "MOVW\t$");
  243. i->curr += symoff(i->curr, i->end-i->curr,
  244. i->immediate+mach->sb, CANY);
  245. bprint(i, "(SB),R%d", i->rt);
  246. }
  247. else
  248. format(o->mnemonic, i, o->ken);
  249. }
  250. static void
  251. andi(Opcode *o, Instr *i)
  252. {
  253. if (i->rs == i->rt)
  254. format(o->mnemonic, i, "%i,R%t");
  255. else
  256. format(o->mnemonic, i, o->ken);
  257. }
  258. static int
  259. plocal(Instr *i, char *m, char r, int store)
  260. {
  261. int offset;
  262. char *reg;
  263. Symbol s;
  264. if (!findsym(i->addr, CTEXT, &s) || !findlocal(&s, FRAMENAME, &s))
  265. return 0;
  266. if (s.value > i->immediate) {
  267. if(!getauto(&s, s.value-i->immediate, CAUTO, &s))
  268. return 0;
  269. reg = "(SP)";
  270. offset = i->immediate;
  271. } else {
  272. offset = i->immediate-s.value;
  273. if (!getauto(&s, offset-4, CPARAM, &s))
  274. return 0;
  275. reg = "(FP)";
  276. }
  277. if (store)
  278. bprint(i, "%s\t%c%d,%s+%d%s", m, r, i->rt, s.name, offset, reg);
  279. else
  280. bprint(i, "%s\t%s+%d%s,%c%d", m, s.name, offset, reg, r, i->rt);
  281. return 1;
  282. }
  283. static void
  284. lw(Opcode *o, Instr *i, char r)
  285. {
  286. char *m;
  287. if (r == 'F') {
  288. if (i->size == 2)
  289. m = "MOVD";
  290. else
  291. m = "MOVF";
  292. }
  293. else
  294. m = o->mnemonic;
  295. if (i->rs == 29 && plocal(i, m, r, 0))
  296. return;
  297. if (i->rs == 30 && mach->sb) {
  298. bprint(i, "%s\t", m);
  299. i->curr += symoff(i->curr, i->end-i->curr, i->immediate+mach->sb, CANY);
  300. bprint(i, "(SB),%c%d", r, i->rt);
  301. return;
  302. }
  303. if (r == 'F')
  304. format(m, i, "%l,F%t");
  305. else
  306. format(m, i, o->ken);
  307. }
  308. static void
  309. load(Opcode *o, Instr *i)
  310. {
  311. lw(o, i, 'R');
  312. }
  313. static void
  314. lwc1(Opcode *o, Instr *i)
  315. {
  316. lw(o, i, 'F');
  317. }
  318. static void
  319. sw(Opcode *o, Instr *i, char r)
  320. {
  321. char *m;
  322. if (r == 'F') {
  323. if (i->size == 2)
  324. m = "MOVD";
  325. else
  326. m = "MOVF";
  327. }
  328. else
  329. m = o->mnemonic;
  330. if (i->rs == 29 && plocal(i, m, r, 1))
  331. return;
  332. if (i->rs == 30 && mach->sb) {
  333. bprint(i, "%s\t%c%d,", m, r, i->rt);
  334. i->curr += symoff(i->curr, i->end-i->curr, i->immediate+mach->sb, CANY);
  335. bprint(i, "(SB)");
  336. return;
  337. }
  338. if (r == 'F')
  339. format(m, i, "F%t,%l");
  340. else
  341. format(m, i, o->ken);
  342. }
  343. static void
  344. store(Opcode *o, Instr *i)
  345. {
  346. sw(o, i, 'R');
  347. }
  348. static void
  349. swc1(Opcode *o, Instr *i)
  350. {
  351. sw(o, i, 'F');
  352. }
  353. static void
  354. sll(Opcode *o, Instr *i)
  355. {
  356. if (i->w0 == 0)
  357. bprint(i, "NOOP");
  358. else if (i->rd == i->rt)
  359. format(o->mnemonic, i, "$%a,R%d");
  360. else
  361. format(o->mnemonic, i, o->ken);
  362. }
  363. static void
  364. sl32(Opcode *o, Instr *i)
  365. {
  366. i->sa += 32;
  367. if (i->rd == i->rt)
  368. format(o->mnemonic, i, "$%a,R%d");
  369. else
  370. format(o->mnemonic, i, o->ken);
  371. }
  372. static void
  373. sllv(Opcode *o, Instr *i)
  374. {
  375. if (i->rd == i->rt)
  376. format(o->mnemonic, i, "R%s,R%d");
  377. else
  378. format(o->mnemonic, i, o->ken);
  379. }
  380. static void
  381. jal(Opcode *o, Instr *i)
  382. {
  383. if (i->rd == 31)
  384. format("JAL", i, "(R%s)");
  385. else
  386. format(o->mnemonic, i, o->ken);
  387. }
  388. static void
  389. add(Opcode *o, Instr *i)
  390. {
  391. if (i->rd == i->rs)
  392. format(o->mnemonic, i, "R%t,R%d");
  393. else if (i->rd == i->rt)
  394. format(o->mnemonic, i, "R%s,R%d");
  395. else
  396. format(o->mnemonic, i, o->ken);
  397. }
  398. static void
  399. sub(Opcode *o, Instr *i)
  400. {
  401. if (i->rd == i->rs)
  402. format(o->mnemonic, i, "R%t,R%d");
  403. else
  404. format(o->mnemonic, i, o->ken);
  405. }
  406. static void
  407. or(Opcode *o, Instr *i)
  408. {
  409. if (i->rs == 0 && i->rt == 0)
  410. format("MOVW", i, "$0,R%d");
  411. else if (i->rs == 0)
  412. format("MOVW", i, "R%t,R%d");
  413. else if (i->rt == 0)
  414. format("MOVW", i, "R%s,R%d");
  415. else
  416. add(o, i);
  417. }
  418. static void
  419. nor(Opcode *o, Instr *i)
  420. {
  421. if (i->rs == 0 && i->rt == 0 && i->rd == 0)
  422. format("NOP", i, 0);
  423. else
  424. add(o, i);
  425. }
  426. static char mipscoload[] = "r%t,%l";
  427. static char mipsload[] = "%l,R%t";
  428. static char mipsstore[] = "R%t,%l";
  429. static char mipsalui[] = "%i,R%s,R%t";
  430. static char mipsalu3op[] = "R%t,R%s,R%d";
  431. static char mipsrtrs[] = "R%t,R%s";
  432. static char mipscorsrt[] = "r%s,r%t";
  433. static char mipscorsi[] = "r%s,%i";
  434. static char mipscoxxx[] = "%w";
  435. static char mipscofp3[] = "f%a,f%d,f%t"; /* fd,fs,ft */
  436. static char mipsfp3[] = "F%t,F%d,F%a";
  437. static char mipscofp2[] = "f%a,f%d"; /* fd,fs */
  438. static char mipsfp2[] = "F%d,F%a";
  439. static char mipscofpc[] = "f%d,f%t"; /* fs,ft */
  440. static char mipsfpc[] = "F%t,F%d";
  441. static Opcode opcodes[64] = {
  442. 0, 0, 0,
  443. 0, 0, 0,
  444. "JMP", 0, "%j",
  445. "JAL", 0, "%j",
  446. "BEQ", branch, 0,
  447. "BNE", branch, 0,
  448. "BLEZ", branch, 0,
  449. "BGTZ", branch, 0,
  450. "ADD", addi, mipsalui,
  451. "ADDU", addi, mipsalui,
  452. "SGT", 0, mipsalui,
  453. "SGTU", 0, mipsalui,
  454. "AND", andi, mipsalui,
  455. "OR", andi, mipsalui,
  456. "XOR", andi, mipsalui,
  457. "MOVW", 0, "$%u,R%t",
  458. "cop0", 0, 0,
  459. "cop1", 0, 0,
  460. "cop2", 0, 0,
  461. "cop3", 0, 0,
  462. "BEQL", branch, 0,
  463. "BNEL", branch, 0,
  464. "BLEZL", branch, 0,
  465. "BGTZL", branch, 0,
  466. "instr18", 0, mipscoxxx,
  467. "instr19", 0, mipscoxxx,
  468. "MOVVL", load, mipsload,
  469. "MOVVR", load, mipsload,
  470. "instr1C", 0, mipscoxxx,
  471. "instr1D", 0, mipscoxxx,
  472. "instr1E", 0, mipscoxxx,
  473. "instr1F", 0, mipscoxxx,
  474. "MOVB", load, mipsload,
  475. "MOVH", load, mipsload,
  476. "lwl", 0, mipscoload,
  477. "MOVW", load, mipsload,
  478. "MOVBU", load, mipsload,
  479. "MOVHU", load, mipsload,
  480. "lwr", 0, mipscoload,
  481. "instr27", 0, mipscoxxx,
  482. "MOVB", store, mipsstore,
  483. "MOVH", store, mipsstore,
  484. "swl", 0, mipscoload,
  485. "MOVW", store, mipsstore,
  486. "MOVVL", store, mipsstore,
  487. "MOVVR", store, mipsstore,
  488. "swr", 0, mipscoload,
  489. "CACHE", 0, "%C,%l",
  490. "ll", 0, mipscoload,
  491. "MOVW", lwc1, mipscoload,
  492. "lwc2", 0, mipscoload,
  493. "lwc3", 0, mipscoload,
  494. "instr34", 0, mipscoxxx,
  495. "ldc1", 0, mipscoload,
  496. "ldc2", 0, mipscoload,
  497. "MOVV", load, mipsload,
  498. "sc", 0, mipscoload,
  499. "swc1", swc1, mipscoload,
  500. "swc2", 0, mipscoload,
  501. "swc3", 0, mipscoload,
  502. "instr3C", 0, mipscoxxx,
  503. "sdc1", 0, mipscoload,
  504. "sdc2", 0, mipscoload,
  505. "MOVV", store, mipsstore,
  506. };
  507. static Opcode sopcodes[64] = {
  508. "SLL", sll, "$%a,R%t,R%d",
  509. "special01", 0, mipscoxxx,
  510. "SRL", sll, "$%a,R%t,R%d",
  511. "SRA", sll, "$%a,R%t,R%d",
  512. "SLL", sllv, "R%s,R%t,R%d",
  513. "special05", 0, mipscoxxx,
  514. "SRL", sllv, "R%s,R%t,R%d",
  515. "SRA", sllv, "R%s,R%t,R%d",
  516. "JMP", 0, "(R%s)",
  517. "jal", jal, "r%d,r%s",
  518. "special0A", 0, mipscoxxx,
  519. "special0B", 0, mipscoxxx,
  520. "SYSCALL", 0, 0,
  521. "BREAK", 0, 0,
  522. "special0E", 0, mipscoxxx,
  523. "SYNC", 0, 0,
  524. "MOVW", 0, "HI,R%d",
  525. "MOVW", 0, "R%s,HI",
  526. "MOVW", 0, "LO,R%d",
  527. "MOVW", 0, "R%s,LO",
  528. "SLLV", sllv, "R%s,R%t,R%d",
  529. "special15", 0, mipscoxxx,
  530. "SRLV", sllv, "R%s,R%t,R%d",
  531. "SRAV", sllv, "R%s,R%t,R%d",
  532. "MUL", 0, mipsrtrs,
  533. "MULU", 0, mipsrtrs,
  534. "DIV", 0, mipsrtrs,
  535. "DIVU", 0, mipsrtrs,
  536. "special1C", 0, mipscoxxx,
  537. "special1D", 0, mipscoxxx,
  538. "DDIV", 0, "R%s,R%t",
  539. "special1F", 0, mipscoxxx,
  540. "ADD", add, mipsalu3op,
  541. "ADDU", add, mipsalu3op,
  542. "SUB", sub, mipsalu3op,
  543. "SUBU", sub, mipsalu3op,
  544. "AND", add, mipsalu3op,
  545. "OR", or, mipsalu3op,
  546. "XOR", add, mipsalu3op,
  547. "NOR", nor, mipsalu3op,
  548. "special28", 0, mipscoxxx,
  549. "special29", 0, mipscoxxx,
  550. "SGT", 0, mipsalu3op,
  551. "SGTU", 0, mipsalu3op,
  552. "special2C", 0, mipscoxxx,
  553. "special2D", 0, mipscoxxx,
  554. "special2E", 0, mipscoxxx,
  555. "DSUBU", 0, "R%s,R%t,R%d",
  556. "tge", 0, mipscorsrt,
  557. "tgeu", 0, mipscorsrt,
  558. "tlt", 0, mipscorsrt,
  559. "tltu", 0, mipscorsrt,
  560. "teq", 0, mipscorsrt,
  561. "special35", 0, mipscoxxx,
  562. "tne", 0, mipscorsrt,
  563. "special37", 0, mipscoxxx,
  564. "SLLV", sll, "$%a,R%t,R%d",
  565. "special39", 0, mipscoxxx,
  566. "SRLV", sll, "$%a,R%t,R%d",
  567. "SRAV", sll, "$%a,R%t,R%d",
  568. "SLLV", sl32, "$%a,R%t,R%d",
  569. "special3D", 0, mipscoxxx,
  570. "SRLV", sl32, "$%a,R%t,R%d",
  571. "SRAV", sl32, "$%a,R%t,R%d",
  572. };
  573. static Opcode ropcodes[32] = {
  574. "BLTZ", branch, 0,
  575. "BGEZ", branch, 0,
  576. "BLTZL", branch, 0,
  577. "BGEZL", branch, 0,
  578. "regimm04", 0, mipscoxxx,
  579. "regimm05", 0, mipscoxxx,
  580. "regimm06", 0, mipscoxxx,
  581. "regimm07", 0, mipscoxxx,
  582. "tgei", 0, mipscorsi,
  583. "tgeiu", 0, mipscorsi,
  584. "tlti", 0, mipscorsi,
  585. "tltiu", 0, mipscorsi,
  586. "teqi", 0, mipscorsi,
  587. "regimm0D", 0, mipscoxxx,
  588. "tnei", 0, mipscorsi,
  589. "regimm0F", 0, mipscoxxx,
  590. "BLTZAL", branch, 0,
  591. "BGEZAL", branch, 0,
  592. "BLTZALL", branch, 0,
  593. "BGEZALL", branch, 0,
  594. "regimm14", 0, mipscoxxx,
  595. "regimm15", 0, mipscoxxx,
  596. "regimm16", 0, mipscoxxx,
  597. "regimm17", 0, mipscoxxx,
  598. "regimm18", 0, mipscoxxx,
  599. "regimm19", 0, mipscoxxx,
  600. "regimm1A", 0, mipscoxxx,
  601. "regimm1B", 0, mipscoxxx,
  602. "regimm1C", 0, mipscoxxx,
  603. "regimm1D", 0, mipscoxxx,
  604. "regimm1E", 0, mipscoxxx,
  605. "regimm1F", 0, mipscoxxx,
  606. };
  607. static Opcode fopcodes[64] = {
  608. "ADD%f", 0, mipsfp3,
  609. "SUB%f", 0, mipsfp3,
  610. "MUL%f", 0, mipsfp3,
  611. "DIV%f", 0, mipsfp3,
  612. "sqrt.%f", 0, mipscofp2,
  613. "ABS%f", 0, mipsfp2,
  614. "MOV%f", 0, mipsfp2,
  615. "NEG%f", 0, mipsfp2,
  616. "finstr08", 0, mipscoxxx,
  617. "finstr09", 0, mipscoxxx,
  618. "finstr0A", 0, mipscoxxx,
  619. "finstr0B", 0, mipscoxxx,
  620. "round.w.%f", 0, mipscofp2,
  621. "trunc.w%f", 0, mipscofp2,
  622. "ceil.w%f", 0, mipscofp2,
  623. "floor.w%f", 0, mipscofp2,
  624. "finstr10", 0, mipscoxxx,
  625. "finstr11", 0, mipscoxxx,
  626. "finstr12", 0, mipscoxxx,
  627. "finstr13", 0, mipscoxxx,
  628. "finstr14", 0, mipscoxxx,
  629. "finstr15", 0, mipscoxxx,
  630. "finstr16", 0, mipscoxxx,
  631. "finstr17", 0, mipscoxxx,
  632. "finstr18", 0, mipscoxxx,
  633. "finstr19", 0, mipscoxxx,
  634. "finstr1A", 0, mipscoxxx,
  635. "finstr1B", 0, mipscoxxx,
  636. "finstr1C", 0, mipscoxxx,
  637. "finstr1D", 0, mipscoxxx,
  638. "finstr1E", 0, mipscoxxx,
  639. "finstr1F", 0, mipscoxxx,
  640. "cvt.s.%f", 0, mipscofp2,
  641. "cvt.d.%f", 0, mipscofp2,
  642. "cvt.e.%f", 0, mipscofp2,
  643. "cvt.q.%f", 0, mipscofp2,
  644. "cvt.w.%f", 0, mipscofp2,
  645. "finstr25", 0, mipscoxxx,
  646. "finstr26", 0, mipscoxxx,
  647. "finstr27", 0, mipscoxxx,
  648. "finstr28", 0, mipscoxxx,
  649. "finstr29", 0, mipscoxxx,
  650. "finstr2A", 0, mipscoxxx,
  651. "finstr2B", 0, mipscoxxx,
  652. "finstr2C", 0, mipscoxxx,
  653. "finstr2D", 0, mipscoxxx,
  654. "finstr2E", 0, mipscoxxx,
  655. "finstr2F", 0, mipscoxxx,
  656. "c.f.%f", 0, mipscofpc,
  657. "c.un.%f", 0, mipscofpc,
  658. "CMPEQ%f", 0, mipsfpc,
  659. "c.ueq.%f", 0, mipscofpc,
  660. "c.olt.%f", 0, mipscofpc,
  661. "c.ult.%f", 0, mipscofpc,
  662. "c.ole.%f", 0, mipscofpc,
  663. "c.ule.%f", 0, mipscofpc,
  664. "c.sf.%f", 0, mipscofpc,
  665. "c.ngle.%f", 0, mipscofpc,
  666. "c.seq.%f", 0, mipscofpc,
  667. "c.ngl.%f", 0, mipscofpc,
  668. "CMPGT%f", 0, mipsfpc,
  669. "c.nge.%f", 0, mipscofpc,
  670. "CMPGE%f", 0, mipsfpc,
  671. "c.ngt.%f", 0, mipscofpc,
  672. };
  673. static char *cop0regs[32] = {
  674. "INDEX", "RANDOM", "TLBPHYS", "EntryLo0",
  675. "CONTEXT", "PageMask", "Wired", "Error",
  676. "BADVADDR", "Count", "TLBVIRT", "Compare",
  677. "STATUS", "CAUSE", "EPC", "PRID",
  678. "Config", "LLadr", "WatchLo", "WatchHi",
  679. "20", "21", "22", "23",
  680. "24", "25", "26", "CacheErr",
  681. "TagLo", "TagHi", "ErrorEPC", "31"
  682. };
  683. static char fsub[16] = {
  684. 'F', 'D', 'e', 'q', 'W', '?', '?', '?',
  685. '?', '?', '?', '?', '?', '?', '?', '?'
  686. };
  687. static char *cacheps[] = {
  688. "I", "D", "SI", "SD"
  689. };
  690. static char *cacheop[] = {
  691. "IWBI", "ILT", "IST", "CDE", "HI", "HWBI", "HWB", "HSV"
  692. };
  693. static void
  694. format(char *mnemonic, Instr *i, char *f)
  695. {
  696. if (mnemonic)
  697. format(0, i, mnemonic);
  698. if (f == 0)
  699. return;
  700. if (mnemonic)
  701. if (i->curr < i->end)
  702. *i->curr++ = '\t';
  703. for ( ; *f && i->curr < i->end; f++) {
  704. if (*f != '%') {
  705. *i->curr++ = *f;
  706. continue;
  707. }
  708. switch (*++f) {
  709. case 's':
  710. bprint(i, "%d", i->rs);
  711. break;
  712. case 't':
  713. bprint(i, "%d", i->rt);
  714. break;
  715. case 'd':
  716. bprint(i, "%d", i->rd);
  717. break;
  718. case 'a':
  719. bprint(i, "%d", i->sa);
  720. break;
  721. case 'l':
  722. bprint(i, "%lx(R%d)",i->immediate, i->rs);
  723. break;
  724. case 'i':
  725. bprint(i, "$%lx", i->immediate);
  726. break;
  727. case 'u':
  728. i->curr += symoff(i->curr, i->end-i->curr, i->immediate, CANY);
  729. bprint(i, "(SB)");
  730. break;
  731. case 'j':
  732. i->curr += symoff(i->curr, i->end-i->curr,
  733. (i->target<<2)|(i->addr & 0xF0000000), CANY);
  734. bprint(i, "(SB)");
  735. break;
  736. case 'b':
  737. i->curr += symoff(i->curr, i->end-i->curr,
  738. (i->immediate<<2)+i->addr+4, CANY);
  739. break;
  740. case 'c':
  741. bprint(i, "$%lx", i->cofun);
  742. break;
  743. case 'w':
  744. bprint(i, "[%lux]", i->w0);
  745. break;
  746. case 'm':
  747. bprint(i, "M(%s)", cop0regs[i->rd]);
  748. break;
  749. case 'f':
  750. *i->curr++ = fsub[i->rs & 0x0F];
  751. break;
  752. case 'C':
  753. bprint(i, "%s%s", cacheps[i->rt & 3], cacheop[(i->rt>>2) & 7]);
  754. break;
  755. case '\0':
  756. *i->curr++ = '%';
  757. return;
  758. default:
  759. bprint(i, "%%%c", *f);
  760. break;
  761. }
  762. }
  763. *i->curr = 0;
  764. }
  765. static void
  766. copz(int cop, Instr *i)
  767. {
  768. char *f, *m, buf[16];
  769. m = buf;
  770. f = "%t,%d";
  771. switch (i->rs) {
  772. case 0:
  773. sprint(buf, "mfc%d", cop);
  774. break;
  775. case 2:
  776. sprint(buf, "cfc%d", cop);
  777. break;
  778. case 4:
  779. sprint(buf, "mtc%d", cop);
  780. break;
  781. case 6:
  782. sprint(buf, "ctc%d", cop);
  783. break;
  784. case 8:
  785. f = "%b";
  786. switch (i->rt) {
  787. case 0:
  788. sprint(buf, "bc%df", cop);
  789. break;
  790. case 1:
  791. sprint(buf, "bc%dt", cop);
  792. break;
  793. case 2:
  794. sprint(buf, "bc%dfl", cop);
  795. break;
  796. case 3:
  797. sprint(buf, "bc%dtl", cop);
  798. break;
  799. default:
  800. sprint(buf, "cop%d", cop);
  801. f = mipscoxxx;
  802. break;
  803. }
  804. break;
  805. default:
  806. sprint(buf, "cop%d", cop);
  807. if (i->rs & 0x10)
  808. f = "function %c";
  809. else
  810. f = mipscoxxx;
  811. break;
  812. }
  813. format(m, i, f);
  814. }
  815. static void
  816. cop0(Instr *i)
  817. {
  818. char *m = 0;
  819. if (i->rs < 8) {
  820. switch (i->rs) {
  821. case 0:
  822. case 1:
  823. format("MOVW", i, "%m,R%t");
  824. return;
  825. case 4:
  826. case 5:
  827. format("MOVW", i, "R%t,%m");
  828. return;
  829. }
  830. }
  831. else if (i->rs >= 0x10) {
  832. switch (i->cofun) {
  833. case 1:
  834. m = "TLBR";
  835. break;
  836. case 2:
  837. m = "TLBWI";
  838. break;
  839. case 6:
  840. m = "TLBWR";
  841. break;
  842. case 8:
  843. m = "TLBP";
  844. break;
  845. case 16:
  846. m = "RFE";
  847. break;
  848. case 32:
  849. m = "ERET";
  850. break;
  851. }
  852. if (m) {
  853. format(m, i, 0);
  854. return;
  855. }
  856. }
  857. copz(0, i);
  858. }
  859. static void
  860. cop1(Instr *i)
  861. {
  862. char *m = "MOVW";
  863. switch (i->rs) {
  864. case 0:
  865. format(m, i, "F%d,R%t");
  866. return;
  867. case 2:
  868. format(m, i, "FCR%d,R%t");
  869. return;
  870. case 4:
  871. format(m, i, "R%t,F%d");
  872. return;
  873. case 6:
  874. format(m, i, "R%t,FCR%d");
  875. return;
  876. case 8:
  877. switch (i->rt) {
  878. case 0:
  879. format("BFPF", i, "%b");
  880. return;
  881. case 1:
  882. format("BFPT", i, "%b");
  883. return;
  884. }
  885. break;
  886. }
  887. copz(1, i);
  888. }
  889. static int
  890. printins(Map *map, uvlong pc, char *buf, int n)
  891. {
  892. Instr i;
  893. Opcode *o;
  894. uchar op;
  895. i.curr = buf;
  896. i.end = buf+n-1;
  897. mymap = map;
  898. if (mkinstr(pc, &i) < 0)
  899. return -1;
  900. switch (i.op) {
  901. case 0x00: /* SPECIAL */
  902. o = sopcodes;
  903. op = i.function;
  904. break;
  905. case 0x01: /* REGIMM */
  906. o = ropcodes;
  907. op = i.rt;
  908. break;
  909. case 0x10: /* COP0 */
  910. cop0(&i);
  911. return i.size*4;
  912. case 0x11: /* COP1 */
  913. if (i.rs & 0x10) {
  914. o = fopcodes;
  915. op = i.function;
  916. break;
  917. }
  918. cop1(&i);
  919. return i.size*4;
  920. case 0x12: /* COP2 */
  921. case 0x13: /* COP3 */
  922. copz(i.op-0x10, &i);
  923. return i.size*4;
  924. default:
  925. o = opcodes;
  926. op = i.op;
  927. break;
  928. }
  929. if (o[op].f)
  930. (*o[op].f)(&o[op], &i);
  931. else
  932. format(o[op].mnemonic, &i, o[op].ken);
  933. return i.size*4;
  934. }
  935. extern int _mipscoinst(Map *, uvlong, char*, int);
  936. /* modifier 'I' toggles the default disassembler type */
  937. static int
  938. mipsinst(Map *map, uvlong pc, char modifier, char *buf, int n)
  939. {
  940. if ((asstype == AMIPSCO && modifier == 'i')
  941. || (asstype == AMIPS && modifier == 'I'))
  942. return _mipscoinst(map, pc, buf, n);
  943. else
  944. return printins(map, pc, buf, n);
  945. }
  946. static int
  947. mipsdas(Map *map, uvlong pc, char *buf, int n)
  948. {
  949. Instr i;
  950. i.curr = buf;
  951. i.end = buf+n;
  952. mymap = map;
  953. if (mkinstr(pc, &i) < 0)
  954. return -1;
  955. if (i.end-i.curr > 8)
  956. i.curr = _hexify(buf, i.w0, 7);
  957. if (i.size == 2 && i.end-i.curr > 9) {
  958. *i.curr++ = ' ';
  959. i.curr = _hexify(i.curr, i.w1, 7);
  960. }
  961. *i.curr = 0;
  962. return i.size*4;
  963. }
  964. static int
  965. mipsinstlen(Map *map, uvlong pc)
  966. {
  967. Instr i;
  968. mymap = map;
  969. if (mkinstr(pc, &i) < 0)
  970. return -1;
  971. return i.size*4;
  972. }
  973. static int
  974. mipsfoll(Map *map, uvlong pc, Rgetter rget, uvlong *foll)
  975. {
  976. ulong w, l;
  977. char buf[8];
  978. Instr i;
  979. mymap = map;
  980. if (mkinstr(pc, &i) < 0)
  981. return -1;
  982. w = i.w0;
  983. if((w&0xF3600000) == 0x41000000){ /* branch on coprocessor */
  984. Conditional:
  985. foll[0] = pc+8;
  986. l = ((w&0xFFFF)<<2);
  987. if(w & 0x8000)
  988. l |= 0xFFFC0000;
  989. foll[1] = pc+4 + l;
  990. return 2;
  991. }
  992. l = (w&0xFC000000)>>26;
  993. switch(l){
  994. case 0: /* SPECIAL */
  995. if((w&0x3E) == 0x08){ /* JR, JALR */
  996. sprint(buf, "R%ld", (w>>21)&0x1F);
  997. foll[0] = (*rget)(map, buf);
  998. return 1;
  999. }
  1000. foll[0] = pc+i.size*4;
  1001. return 1;
  1002. case 0x30: /* Load-Linked followed by NOP, STC */
  1003. foll[0] = pc+12;
  1004. return 1;
  1005. case 1: /* BCOND */
  1006. case 4: /* BEQ */
  1007. case 20: /* BEQL */
  1008. case 5: /* BNE */
  1009. case 21: /* BNEL */
  1010. case 6: /* BLEZ */
  1011. case 22: /* BLEZL */
  1012. case 7: /* BGTZ */
  1013. case 23: /* BGTZL */
  1014. goto Conditional;
  1015. case 2: /* J */
  1016. case 3: /* JAL */
  1017. foll[0] = (pc&0xF0000000) | ((w&0x03FFFFFF)<<2);
  1018. return 1;
  1019. }
  1020. foll[0] = pc+i.size*4;
  1021. return 1;
  1022. }