vdb.c 23 KB

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