7db.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923
  1. #include <u.h>
  2. #include <libc.h>
  3. #include <bio.h>
  4. #include <mach.h>
  5. /*
  6. * Alpha-specific debugger interface
  7. */
  8. static char *alphaexcep(Map*, Rgetter);
  9. static int alphafoll(Map*, ulong, Rgetter, ulong*);
  10. static int alphainst(Map*, ulong, char, char*, int);
  11. static int alphadas(Map*, ulong, char*, int);
  12. static int alphainstlen(Map*, ulong);
  13. /*
  14. * Debugger interface
  15. */
  16. Machdata alphamach =
  17. {
  18. {0x80, 0, 0, 0}, /* break point */
  19. 4, /* break point size */
  20. leswab, /* short to local byte order */
  21. leswal, /* long to local byte order */
  22. leswav, /* vlong to local byte order */
  23. risctrace, /* C traceback */
  24. riscframe, /* Frame finder */
  25. alphaexcep, /* print exception */
  26. 0, /* breakpoint fixup */
  27. leieeesftos, /* single precision float printer */
  28. leieeedftos, /* double precisioin float printer */
  29. alphafoll, /* following addresses */
  30. alphainst, /* print instruction */
  31. alphadas, /* dissembler */
  32. alphainstlen, /* instruction size */
  33. };
  34. static char *illegaltype[] = {
  35. "breakpoint",
  36. "bugchk",
  37. "gentrap",
  38. "fen",
  39. "illegal instruction",
  40. };
  41. static char *
  42. alphaexcep(Map *map, Rgetter rget)
  43. {
  44. ulong type, a0, a1;
  45. static char buf[256];
  46. type = (*rget)(map, "TYPE");
  47. a0 = (*rget)(map, "A0");
  48. a1 = (*rget)(map, "A1");
  49. /* a2 = (*rget)(map, "A2"); */
  50. switch (type) {
  51. case 1: /* arith */
  52. sprint(buf, "trap: arithmetic trap 0x%lux", a0);
  53. break;
  54. case 2: /* bad instr or FEN */
  55. if (a0 <= 4)
  56. return illegaltype[a0];
  57. else
  58. sprint(buf, "illegal instr trap, unknown type %lud", a0);
  59. break;
  60. case 3: /* intr */
  61. sprint(buf, "interrupt type %lud", a0);
  62. break;
  63. case 4: /* memory fault */
  64. sprint(buf, "fault %s addr=0x%lux", (a1&1)?"write":"read", a0);
  65. break;
  66. case 5: /* syscall() */
  67. return "system call";
  68. case 6: /* alignment fault */
  69. sprint(buf, "unaligned op 0x%lux addr 0x%lux", a1, a0);
  70. break;
  71. default: /* cannot happen */
  72. sprint(buf, "unknown exception type %lud", type);
  73. break;
  74. }
  75. return buf;
  76. }
  77. /* alpha disassembler and related functions */
  78. static char FRAMENAME[] = ".frame";
  79. typedef struct {
  80. ulong addr;
  81. uchar op; /* bits 31-26 */
  82. uchar ra; /* bits 25-21 */
  83. uchar rb; /* bits 20-16 */
  84. uchar rc; /* bits 4-0 */
  85. long mem; /* bits 15-0 */
  86. long branch; /* bits 20-0 */
  87. uchar function; /* bits 11-5 */
  88. uchar literal; /* bits 20-13 */
  89. uchar islit; /* bit 12 */
  90. uchar fpfn; /* bits 10-5 */
  91. uchar fpmode; /* bits 15-11 */
  92. long w0;
  93. long w1;
  94. int size; /* instruction size */
  95. char *curr; /* fill point in buffer */
  96. char *end; /* end of buffer */
  97. char *err; /* error message */
  98. } Instr;
  99. static Map *mymap;
  100. static int
  101. decode(ulong pc, Instr *i)
  102. {
  103. long w;
  104. if (get4(mymap, pc, &w) < 0) {
  105. werrstr("can't read instruction: %r");
  106. return -1;
  107. }
  108. i->addr = pc;
  109. i->size = 1;
  110. i->op = (w >> 26) & 0x3F;
  111. i->ra = (w >> 21) & 0x1F;
  112. i->rb = (w >> 16) & 0x1F;
  113. i->rc = w & 0x1F;
  114. i->function = (w >> 5) & 0x7F;
  115. i->mem = w & 0xFFFF;
  116. if (i->mem & 0x8000)
  117. i->mem -= 0x10000;
  118. i->branch = w & 0x1FFFFF;
  119. if (i->branch & 0x100000)
  120. i->branch -= 0x200000;
  121. i->function = (w >> 5) & 0x7F;
  122. i->literal = (w >> 13) & 0xFF;
  123. i->islit = (w >> 12) & 0x01;
  124. i->fpfn = (w >> 5) & 0x3F;
  125. i->fpmode = (w >> 11) & 0x1F;
  126. i->w0 = w;
  127. return 1;
  128. }
  129. static int
  130. mkinstr(ulong pc, Instr *i)
  131. {
  132. /* Instr x; */
  133. if (decode(pc, i) < 0)
  134. return -1;
  135. #ifdef frommips
  136. /* we probably want to do something like this for alpha... */
  137. /*
  138. * if it's a LUI followed by an ORI,
  139. * it's an immediate load of a large constant.
  140. * fix the LUI immediate in any case.
  141. */
  142. if (i->op == 0x0F) {
  143. if (decode(pc+4, &x) < 0)
  144. return 0;
  145. i->immediate <<= 16;
  146. if (x.op == 0x0D && x.rs == x.rt && x.rt == i->rt) {
  147. i->immediate |= (x.immediate & 0xFFFF);
  148. i->w1 = x.w0;
  149. i->size++;
  150. return 1;
  151. }
  152. }
  153. #endif
  154. return 1;
  155. }
  156. static void
  157. bprint(Instr *i, char *fmt, ...)
  158. {
  159. va_list arg;
  160. va_start(arg, fmt);
  161. i->curr = vseprint(i->curr, i->end, fmt, arg);
  162. va_end(arg);
  163. }
  164. typedef struct Opcode Opcode;
  165. struct Opcode {
  166. char *mnemonic;
  167. void (*f)(Opcode *, Instr *);
  168. char *ken;
  169. };
  170. static void format(char *, Instr *, char *);
  171. static int
  172. plocal(Instr *i, char *m, char r, int store)
  173. {
  174. int offset;
  175. char *reg;
  176. Symbol s;
  177. if (!findsym(i->addr, CTEXT, &s) || !findlocal(&s, FRAMENAME, &s))
  178. return 0;
  179. if (s.value > i->mem) {
  180. if(!getauto(&s, s.value-i->mem, CAUTO, &s))
  181. return 0;
  182. reg = "(SP)";
  183. offset = i->mem;
  184. } else {
  185. offset = i->mem-s.value-8;
  186. if (!getauto(&s, offset, CPARAM, &s))
  187. return 0;
  188. reg = "(FP)";
  189. }
  190. if (store)
  191. bprint(i, "%s\t%c%d,%s+%d%s", m, r, i->ra, s.name, offset, reg);
  192. else
  193. bprint(i, "%s\t%s+%d%s,%c%d", m, s.name, offset, reg, r, i->ra);
  194. return 1;
  195. }
  196. static void
  197. _load(Opcode *o, Instr *i, char r)
  198. {
  199. char *m;
  200. m = o->mnemonic;
  201. if (i->rb == 30 && plocal(i, m, r, 0))
  202. return;
  203. if (i->rb == 29 && mach->sb) {
  204. bprint(i, "%s\t", m);
  205. i->curr += symoff(i->curr, i->end-i->curr, i->mem+mach->sb, CANY);
  206. bprint(i, "(SB),%c%d", r, i->ra);
  207. return;
  208. }
  209. format(m, i, o->ken);
  210. }
  211. static void
  212. load(Opcode *o, Instr *i)
  213. {
  214. _load(o, i, 'R');
  215. }
  216. static void
  217. loadf(Opcode *o, Instr *i)
  218. {
  219. _load(o, i, 'F');
  220. }
  221. static void
  222. _store(Opcode *o, Instr *i, char r)
  223. {
  224. char *m;
  225. m = o->mnemonic;
  226. if (i->rb == 30 && plocal(i, m, r, 1))
  227. return;
  228. if (i->rb == 29 && mach->sb) {
  229. bprint(i, "%s\t%c%d,", m, r, i->ra);
  230. i->curr += symoff(i->curr, i->end-i->curr, i->mem+mach->sb, CANY);
  231. bprint(i, "(SB)", r, i->ra);
  232. return;
  233. }
  234. format(o->mnemonic, i, o->ken);
  235. }
  236. static void
  237. store(Opcode *o, Instr *i)
  238. {
  239. _store(o, i, 'R');
  240. }
  241. static void
  242. storef(Opcode *o, Instr *i)
  243. {
  244. _store(o, i, 'F');
  245. }
  246. static void
  247. misc(Opcode *o, Instr *i)
  248. {
  249. char *f;
  250. USED(o);
  251. switch (i->mem&0xFFFF) {
  252. case 0x0000:
  253. f = "TRAPB";
  254. break;
  255. case 0x4000:
  256. f = "MB";
  257. break;
  258. case 0x8000:
  259. f = "FETCH\t0(R%b)";
  260. break;
  261. case 0xA000:
  262. f = "FETCH_M\t0(R%b)";
  263. break;
  264. case 0xC000:
  265. f = "RPCC\tR%a";
  266. break;
  267. case 0xE000:
  268. f = "RC\tR%a";
  269. break;
  270. case 0xF000:
  271. f = "RS\tR%a";
  272. break;
  273. default:
  274. f = "%w";
  275. }
  276. format(0, i, f);
  277. }
  278. static char *jmpcode[4] = { "JMP", "JSR", "RET", "JSR_COROUTINE" };
  279. static void
  280. jmp(Opcode *o, Instr *i)
  281. {
  282. int hint;
  283. char *m;
  284. USED(o);
  285. hint = (i->mem >> 14) & 3;
  286. m = jmpcode[hint];
  287. if (i->ra == 31) {
  288. if (hint == 2 && i->rb == 29)
  289. bprint(i, m);
  290. else
  291. format(m, i, "(R%b)");
  292. }
  293. else
  294. format(m, i, "R%a,(R%b)");
  295. }
  296. static void
  297. br(Opcode *o, Instr *i)
  298. {
  299. if (i->ra == 31)
  300. format(o->mnemonic, i, "%B");
  301. else
  302. format(o->mnemonic, i, o->ken);
  303. }
  304. static void
  305. bsr(Opcode *o, Instr *i)
  306. {
  307. if (i->ra == 26)
  308. format(o->mnemonic, i, "%B");
  309. else
  310. format(o->mnemonic, i, o->ken);
  311. }
  312. static void
  313. mult(Opcode *o, Instr *i)
  314. {
  315. char *m;
  316. switch (i->function) {
  317. case 0x00:
  318. m = "MULL";
  319. break;
  320. case 0x20:
  321. m = "MULQ";
  322. break;
  323. case 0x40:
  324. m = "MULL/V";
  325. break;
  326. case 0x60:
  327. m = "MULQ/V";
  328. break;
  329. case 0x30:
  330. m = "UMULH";
  331. break;
  332. default:
  333. format("???", i, "%w");
  334. return;
  335. }
  336. format(m, i, o->ken);
  337. }
  338. static char alphaload[] = "%l,R%a";
  339. static char alphafload[] = "%l,F%a";
  340. static char alphastore[] = "R%a,%l";
  341. static char alphafstore[] = "F%a,%l";
  342. static char alphabranch[] = "R%a,%B";
  343. static char alphafbranch[] = "F%a,%B";
  344. static char alphaint[] = "%v,R%a,R%c";
  345. static char alphafp[] = "F%b,F%a,F%c";
  346. static char alphafp2[] = "F%b,F%c";
  347. static char alphaxxx[] = "%w";
  348. static Opcode opcodes[64] = {
  349. "PAL", 0, alphaxxx,
  350. "OPC01", 0, alphaxxx,
  351. "OPC02", 0, alphaxxx,
  352. "OPC03", 0, alphaxxx,
  353. "OPC04", 0, alphaxxx,
  354. "OPC05", 0, alphaxxx,
  355. "OPC06", 0, alphaxxx,
  356. "OPC07", 0, alphaxxx,
  357. "MOVQA", load, alphaload,
  358. "MOVQAH", load, alphaload,
  359. "MOVBU", load, alphaload, /* v 3 */
  360. "MOVQU", load, alphaload,
  361. "MOVWU", load, alphaload, /* v 3 */
  362. "MOVWU", store, alphastore, /* v 3 */
  363. "MOVBU", store, alphastore, /* v 3 */
  364. "MOVQU", store, alphastore,
  365. 0, 0, 0, /* int arith */
  366. 0, 0, 0, /* logical */
  367. 0, 0, 0, /* shift */
  368. 0, mult, alphaint,
  369. "OPC14", 0, alphaxxx,
  370. "vax", 0, alphafp, /* vax */
  371. 0, 0, 0, /* ieee */
  372. 0, 0, 0, /* fp */
  373. 0, misc, alphaxxx,
  374. "PAL19 [HW_MFPR]", 0, alphaxxx,
  375. "JSR", jmp, 0,
  376. "PAL1B [HW_LD]", 0, alphaxxx,
  377. "OPC1C", 0, alphaxxx,
  378. "PAL1D [HW_MTPR]", 0, alphaxxx,
  379. "PAL1E [HW_REI]", 0, alphaxxx,
  380. "PAL1F [HW_ST]", 0, alphaxxx,
  381. "MOVF", loadf, alphafload,
  382. "MOVG", loadf, alphafload,
  383. "MOVS", loadf, alphafload,
  384. "MOVT", loadf, alphafload,
  385. "MOVF", storef, alphafstore,
  386. "MOVG", storef, alphafstore,
  387. "MOVS", storef, alphafstore,
  388. "MOVT", storef, alphafstore,
  389. "MOVL", load, alphaload,
  390. "MOVQ", load, alphaload,
  391. "MOVLL", load, alphaload,
  392. "MOVQL", load, alphaload,
  393. "MOVL", store, alphastore,
  394. "MOVQ", store, alphastore,
  395. "MOVLC", store, alphastore,
  396. "MOVQC", store, alphastore,
  397. "JMP", br, alphabranch,
  398. "FBEQ", 0, alphafbranch,
  399. "FBLT", 0, alphafbranch,
  400. "FBLE", 0, alphafbranch,
  401. "JSR", bsr, alphabranch,
  402. "FBNE", 0, alphafbranch,
  403. "FBGE", 0, alphafbranch,
  404. "FBGT", 0, alphafbranch,
  405. "BLBC", 0, alphafbranch,
  406. "BEQ", 0, alphabranch,
  407. "BLT", 0, alphabranch,
  408. "BLE", 0, alphabranch,
  409. "BLBS", 0, alphabranch,
  410. "BNE", 0, alphabranch,
  411. "BGE", 0, alphabranch,
  412. "BGT", 0, alphabranch,
  413. };
  414. static Opcode fpopcodes[64] = {
  415. "???", 0, alphaxxx,
  416. "???", 0, alphaxxx,
  417. "???", 0, alphaxxx,
  418. "???", 0, alphaxxx,
  419. "???", 0, alphaxxx,
  420. "???", 0, alphaxxx,
  421. "???", 0, alphaxxx,
  422. "???", 0, alphaxxx,
  423. "???", 0, alphaxxx,
  424. "???", 0, alphaxxx,
  425. "???", 0, alphaxxx,
  426. "???", 0, alphaxxx,
  427. "???", 0, alphaxxx,
  428. "???", 0, alphaxxx,
  429. "???", 0, alphaxxx,
  430. "???", 0, alphaxxx,
  431. "CVTLQ", 0, alphafp2,
  432. "???", 0, alphaxxx,
  433. "???", 0, alphaxxx,
  434. "???", 0, alphaxxx,
  435. "???", 0, alphaxxx,
  436. "???", 0, alphaxxx,
  437. "???", 0, alphaxxx,
  438. "???", 0, alphaxxx,
  439. "???", 0, alphaxxx,
  440. "???", 0, alphaxxx,
  441. "???", 0, alphaxxx,
  442. "???", 0, alphaxxx,
  443. "???", 0, alphaxxx,
  444. "???", 0, alphaxxx,
  445. "???", 0, alphaxxx,
  446. "???", 0, alphaxxx,
  447. "CPYS", 0, alphafp,
  448. "CPYSN", 0, alphafp,
  449. "CPYSE", 0, alphafp,
  450. "???", 0, alphaxxx,
  451. "MOVT", 0, "FPCR,F%a",
  452. "MOVT", 0, "F%a,FPCR",
  453. "???", 0, alphaxxx,
  454. "???", 0, alphaxxx,
  455. "???", 0, alphaxxx,
  456. "???", 0, alphaxxx,
  457. "FCMOVEQ", 0, alphafp,
  458. "FCMOVNE", 0, alphafp,
  459. "FCMOVLT", 0, alphafp,
  460. "FCMOVGE", 0, alphafp,
  461. "FCMOVLE", 0, alphafp,
  462. "FCMOVGT", 0, alphafp,
  463. "CVTQL", 0, alphafp2,
  464. "???", 0, alphaxxx,
  465. "???", 0, alphaxxx,
  466. "???", 0, alphaxxx,
  467. "???", 0, alphaxxx,
  468. "???", 0, alphaxxx,
  469. "???", 0, alphaxxx,
  470. "???", 0, alphaxxx,
  471. "???", 0, alphaxxx,
  472. "???", 0, alphaxxx,
  473. "???", 0, alphaxxx,
  474. "???", 0, alphaxxx,
  475. "???", 0, alphaxxx,
  476. "???", 0, alphaxxx,
  477. "???", 0, alphaxxx,
  478. "???", 0, alphaxxx,
  479. };
  480. static Opcode ieeeopcodes[64] = {
  481. "ADDS", 0, alphafp,
  482. "SUBS", 0, alphafp,
  483. "MULS", 0, alphafp,
  484. "DIVS", 0, alphafp,
  485. "???", 0, alphaxxx,
  486. "???", 0, alphaxxx,
  487. "???", 0, alphaxxx,
  488. "???", 0, alphaxxx,
  489. "???", 0, alphaxxx,
  490. "???", 0, alphaxxx,
  491. "???", 0, alphaxxx,
  492. "???", 0, alphaxxx,
  493. "???", 0, alphaxxx,
  494. "???", 0, alphaxxx,
  495. "???", 0, alphaxxx,
  496. "???", 0, alphaxxx,
  497. "???", 0, alphaxxx,
  498. "???", 0, alphaxxx,
  499. "???", 0, alphaxxx,
  500. "???", 0, alphaxxx,
  501. "???", 0, alphaxxx,
  502. "???", 0, alphaxxx,
  503. "???", 0, alphaxxx,
  504. "???", 0, alphaxxx,
  505. "???", 0, alphaxxx,
  506. "???", 0, alphaxxx,
  507. "???", 0, alphaxxx,
  508. "???", 0, alphaxxx,
  509. "???", 0, alphaxxx,
  510. "???", 0, alphaxxx,
  511. "???", 0, alphaxxx,
  512. "???", 0, alphaxxx,
  513. "ADDT", 0, alphafp,
  514. "SUBT", 0, alphafp,
  515. "MULT", 0, alphafp,
  516. "DIVT", 0, alphafp,
  517. "CMPTUN", 0, alphafp,
  518. "CMPTEQ", 0, alphafp,
  519. "CMPTLT", 0, alphafp,
  520. "CMPTLE", 0, alphafp,
  521. "???", 0, alphaxxx,
  522. "???", 0, alphaxxx,
  523. "???", 0, alphaxxx,
  524. "???", 0, alphaxxx,
  525. "CVTTS", 0, alphafp2,
  526. "???", 0, alphaxxx,
  527. "???", 0, alphaxxx,
  528. "CVTTQ", 0, alphafp2,
  529. "???", 0, alphaxxx,
  530. "???", 0, alphaxxx,
  531. "???", 0, alphaxxx,
  532. "???", 0, alphaxxx,
  533. "???", 0, alphaxxx,
  534. "???", 0, alphaxxx,
  535. "???", 0, alphaxxx,
  536. "???", 0, alphaxxx,
  537. "???", 0, alphaxxx,
  538. "???", 0, alphaxxx,
  539. "???", 0, alphaxxx,
  540. "???", 0, alphaxxx,
  541. "CVTQS", 0, alphafp2,
  542. "???", 0, alphaxxx,
  543. "CVTQT", 0, alphafp2,
  544. "???", 0, alphaxxx,
  545. };
  546. static uchar amap[128] = {
  547. [0x00] 1,
  548. [0x40] 2,
  549. [0x20] 3,
  550. [0x60] 4,
  551. [0x09] 5,
  552. [0x49] 6,
  553. [0x29] 7,
  554. [0x69] 8,
  555. [0x2D] 9,
  556. [0x4D] 10,
  557. [0x6D] 11,
  558. [0x1D] 12,
  559. [0x3D] 13,
  560. [0x0F] 14,
  561. [0x02] 15,
  562. [0x0B] 16,
  563. [0x12] 17,
  564. [0x1B] 18,
  565. [0x22] 19,
  566. [0x2B] 20,
  567. [0x32] 21,
  568. [0x3B] 22,
  569. };
  570. static Opcode arithopcodes[64] = {
  571. "???", 0, alphaxxx,
  572. "ADDL", 0, alphaint,
  573. "ADDL/V", 0, alphaint,
  574. "ADDQ", 0, alphaint,
  575. "ADDQ/V", 0, alphaint,
  576. "SUBL", 0, alphaint,
  577. "SUBL/V", 0, alphaint,
  578. "SUBQ", 0, alphaint,
  579. "SUBQ/V", 0, alphaint,
  580. "CMPEQ", 0, alphaint,
  581. "CMPLT", 0, alphaint,
  582. "CMPLE", 0, alphaint,
  583. "CMPULT", 0, alphaint,
  584. "CMPULE", 0, alphaint,
  585. "CMPBGE", 0, alphaint,
  586. "S4ADDL", 0, alphaint,
  587. "S4SUBL", 0, alphaint,
  588. "S8ADDL", 0, alphaint,
  589. "S8SUBL", 0, alphaint,
  590. "S4ADDQ", 0, alphaint,
  591. "S4SUBQ", 0, alphaint,
  592. "S8ADDQ", 0, alphaint,
  593. "S8SUBQ", 0, alphaint,
  594. };
  595. static uchar lmap[128] = {
  596. [0x00] 1,
  597. [0x20] 2,
  598. [0x40] 3,
  599. [0x08] 4,
  600. [0x28] 5,
  601. [0x48] 6,
  602. [0x24] 7,
  603. [0x44] 8,
  604. [0x64] 9,
  605. [0x26] 7,
  606. [0x46] 8,
  607. [0x66] 9,
  608. [0x14] 10,
  609. [0x16] 11,
  610. };
  611. static Opcode logicalopcodes[64] = {
  612. "???", 0, alphaxxx,
  613. "AND", 0, alphaint,
  614. "OR", 0, alphaint,
  615. "XOR", 0, alphaint,
  616. "ANDNOT", 0, alphaint,
  617. "ORNOT", 0, alphaint,
  618. "XORNOT", 0, alphaint,
  619. "CMOVEQ", 0, alphaint,
  620. "CMOVLT", 0, alphaint,
  621. "CMOVLE", 0, alphaint,
  622. "CMOVNE", 0, alphaint,
  623. "CMOVGE", 0, alphaint,
  624. "CMOVGT", 0, alphaint,
  625. "CMOVLBS", 0, alphaint,
  626. "CMOVLBC", 0, alphaint,
  627. };
  628. static uchar smap[128] = {
  629. [0x39] 1,
  630. [0x3C] 2,
  631. [0x34] 3,
  632. [0x06] 4,
  633. [0x16] 5,
  634. [0x26] 6,
  635. [0x36] 7,
  636. [0x5A] 8,
  637. [0x6A] 9,
  638. [0x7A] 10,
  639. [0x0B] 11,
  640. [0x1B] 12,
  641. [0x2B] 13,
  642. [0x3B] 14,
  643. [0x57] 15,
  644. [0x67] 16,
  645. [0x77] 17,
  646. [0x02] 18,
  647. [0x12] 19,
  648. [0x22] 20,
  649. [0x32] 21,
  650. [0x52] 22,
  651. [0x62] 23,
  652. [0x72] 24,
  653. [0x30] 25,
  654. [0x31] 26,
  655. };
  656. static Opcode shiftopcodes[64] = {
  657. "???", 0, alphaxxx,
  658. "SLLQ", 0, alphaint,
  659. "SRAQ", 0, alphaint,
  660. "SRLQ", 0, alphaint,
  661. "EXTBL", 0, alphaint,
  662. "EXTWL", 0, alphaint,
  663. "EXTLL", 0, alphaint,
  664. "EXTQL", 0, alphaint,
  665. "EXTWH", 0, alphaint,
  666. "EXTLH", 0, alphaint,
  667. "EXTQH", 0, alphaint,
  668. "INSBL", 0, alphaint,
  669. "INSWL", 0, alphaint,
  670. "INSLL", 0, alphaint,
  671. "INSQL", 0, alphaint,
  672. "INSWH", 0, alphaint,
  673. "INSLH", 0, alphaint,
  674. "INSQH", 0, alphaint,
  675. "MSKBL", 0, alphaint,
  676. "MSKWL", 0, alphaint,
  677. "MSKLL", 0, alphaint,
  678. "MSKQL", 0, alphaint,
  679. "MSKWH", 0, alphaint,
  680. "MSKLH", 0, alphaint,
  681. "MSKQH", 0, alphaint,
  682. "ZAP", 0, alphaint,
  683. "ZAPNOT", 0, alphaint,
  684. };
  685. static void
  686. format(char *mnemonic, Instr *i, char *f)
  687. {
  688. if (mnemonic)
  689. format(0, i, mnemonic);
  690. if (f == 0)
  691. return;
  692. if (mnemonic)
  693. if (i->curr < i->end)
  694. *i->curr++ = '\t';
  695. for ( ; *f && i->curr < i->end; f++) {
  696. if (*f != '%') {
  697. *i->curr++ = *f;
  698. continue;
  699. }
  700. switch (*++f) {
  701. case 'a':
  702. bprint(i, "%d", i->ra);
  703. break;
  704. case 'b':
  705. bprint(i, "%d", i->rb);
  706. break;
  707. case 'c':
  708. bprint(i, "%d", i->rc);
  709. break;
  710. case 'v':
  711. if (i->islit)
  712. bprint(i, "$%lx", i->literal);
  713. else
  714. bprint(i, "R%d", i->rb);
  715. break;
  716. case 'l':
  717. bprint(i, "%lx(R%d)", i->mem, i->rb);
  718. break;
  719. case 'i':
  720. bprint(i, "$%lx", i->mem);
  721. break;
  722. case 'B':
  723. i->curr += symoff(i->curr, i->end-i->curr,
  724. (i->branch<<2)+i->addr+4, CANY);
  725. break;
  726. case 'w':
  727. bprint(i, "[%lux]", i->w0);
  728. break;
  729. case '\0':
  730. *i->curr++ = '%';
  731. return;
  732. default:
  733. bprint(i, "%%%c", *f);
  734. break;
  735. }
  736. }
  737. *i->curr = 0;
  738. }
  739. static int
  740. printins(Map *map, ulong pc, char *buf, int n)
  741. {
  742. Instr i;
  743. Opcode *o;
  744. uchar op;
  745. i.curr = buf;
  746. i.end = buf+n-1;
  747. mymap = map;
  748. if (mkinstr(pc, &i) < 0)
  749. return -1;
  750. switch (i.op) {
  751. case 0x10: /* INTA */
  752. o = arithopcodes;
  753. op = amap[i.function];
  754. break;
  755. case 0x11: /* INTL */
  756. o = logicalopcodes;
  757. op = lmap[i.function];
  758. break;
  759. case 0x12: /* INTS */
  760. o = shiftopcodes;
  761. op = smap[i.function];
  762. break;
  763. case 0x16: /* FLTI */
  764. o = ieeeopcodes;
  765. op = i.fpfn;
  766. break;
  767. case 0x17: /* FLTL */
  768. o = fpopcodes;
  769. op = i.fpfn;
  770. break;
  771. default:
  772. o = opcodes;
  773. op = i.op;
  774. break;
  775. }
  776. if (o[op].f)
  777. (*o[op].f)(&o[op], &i);
  778. else
  779. format(o[op].mnemonic, &i, o[op].ken);
  780. return i.size*4;
  781. }
  782. static int
  783. alphainst(Map *map, ulong pc, char modifier, char *buf, int n)
  784. {
  785. USED(modifier);
  786. return printins(map, pc, buf, n);
  787. }
  788. static int
  789. alphadas(Map *map, ulong pc, char *buf, int n)
  790. {
  791. Instr i;
  792. i.curr = buf;
  793. i.end = buf+n;
  794. mymap = map;
  795. if (mkinstr(pc, &i) < 0)
  796. return -1;
  797. if (i.end-i.curr > 8)
  798. i.curr = _hexify(buf, i.w0, 7);
  799. if (i.size == 2 && i.end-i.curr > 9) {
  800. *i.curr++ = ' ';
  801. i.curr = _hexify(i.curr, i.w1, 7);
  802. }
  803. *i.curr = 0;
  804. return i.size*4;
  805. }
  806. static int
  807. alphainstlen(Map *map, ulong pc)
  808. {
  809. Instr i;
  810. mymap = map;
  811. if (mkinstr(pc, &i) < 0)
  812. return -1;
  813. return i.size*4;
  814. }
  815. static int
  816. alphafoll(Map *map, ulong pc, Rgetter rget, ulong *foll)
  817. {
  818. char buf[8];
  819. Instr i;
  820. mymap = map;
  821. if (mkinstr(pc, &i) < 0)
  822. return -1;
  823. switch(i.op) {
  824. case 0x1A: /* JMP/JSR/RET */
  825. sprint(buf, "R%d", i.rb);
  826. foll[0] = (*rget)(map, buf);
  827. return 1;
  828. case 0x30: /* BR */
  829. case 0x34: /* BSR */
  830. foll[0] = pc+4 + (i.branch<<2);
  831. return 1;
  832. default:
  833. if (i.op > 0x30) { /* cond */
  834. foll[0] = pc+4;
  835. foll[1] = pc+4 + (i.branch<<2);
  836. return 2;
  837. }
  838. foll[0] = pc+i.size*4;
  839. return 1;
  840. }
  841. }