7db.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925
  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*, uvlong, Rgetter, uvlong*);
  10. static int alphainst(Map*, uvlong, char, char*, int);
  11. static int alphadas(Map*, uvlong, char*, int);
  12. static int alphainstlen(Map*, uvlong);
  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. uvlong 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(uvlong pc, Instr *i)
  102. {
  103. ulong 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(uvlong 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. #pragma varargck argpos bprint 2
  157. static void
  158. bprint(Instr *i, char *fmt, ...)
  159. {
  160. va_list arg;
  161. va_start(arg, fmt);
  162. i->curr = vseprint(i->curr, i->end, fmt, arg);
  163. va_end(arg);
  164. }
  165. typedef struct Opcode Opcode;
  166. struct Opcode {
  167. char *mnemonic;
  168. void (*f)(Opcode *, Instr *);
  169. char *ken;
  170. };
  171. static void format(char *, Instr *, char *);
  172. static int
  173. plocal(Instr *i, char *m, char r, int store)
  174. {
  175. int offset;
  176. char *reg;
  177. Symbol s;
  178. if (!findsym(i->addr, CTEXT, &s) || !findlocal(&s, FRAMENAME, &s))
  179. return 0;
  180. if (s.value > i->mem) {
  181. if(!getauto(&s, s.value-i->mem, CAUTO, &s))
  182. return 0;
  183. reg = "(SP)";
  184. offset = i->mem;
  185. } else {
  186. offset = i->mem-s.value-8;
  187. if (!getauto(&s, offset, CPARAM, &s))
  188. return 0;
  189. reg = "(FP)";
  190. }
  191. if (store)
  192. bprint(i, "%s\t%c%d,%s+%d%s", m, r, i->ra, s.name, offset, reg);
  193. else
  194. bprint(i, "%s\t%s+%d%s,%c%d", m, s.name, offset, reg, r, i->ra);
  195. return 1;
  196. }
  197. static void
  198. _load(Opcode *o, Instr *i, char r)
  199. {
  200. char *m;
  201. m = o->mnemonic;
  202. if (i->rb == 30 && plocal(i, m, r, 0))
  203. return;
  204. if (i->rb == 29 && mach->sb) {
  205. bprint(i, "%s\t", m);
  206. i->curr += symoff(i->curr, i->end-i->curr, i->mem+mach->sb, CANY);
  207. bprint(i, "(SB),%c%d", r, i->ra);
  208. return;
  209. }
  210. format(m, i, o->ken);
  211. }
  212. static void
  213. load(Opcode *o, Instr *i)
  214. {
  215. _load(o, i, 'R');
  216. }
  217. static void
  218. loadf(Opcode *o, Instr *i)
  219. {
  220. _load(o, i, 'F');
  221. }
  222. static void
  223. _store(Opcode *o, Instr *i, char r)
  224. {
  225. char *m;
  226. m = o->mnemonic;
  227. if (i->rb == 30 && plocal(i, m, r, 1))
  228. return;
  229. if (i->rb == 29 && mach->sb) {
  230. bprint(i, "%s\t%c%d,", m, r, i->ra);
  231. i->curr += symoff(i->curr, i->end-i->curr, i->mem+mach->sb, CANY);
  232. bprint(i, "(SB)");
  233. return;
  234. }
  235. format(o->mnemonic, i, o->ken);
  236. }
  237. static void
  238. store(Opcode *o, Instr *i)
  239. {
  240. _store(o, i, 'R');
  241. }
  242. static void
  243. storef(Opcode *o, Instr *i)
  244. {
  245. _store(o, i, 'F');
  246. }
  247. static void
  248. misc(Opcode *o, Instr *i)
  249. {
  250. char *f;
  251. USED(o);
  252. switch (i->mem&0xFFFF) {
  253. case 0x0000:
  254. f = "TRAPB";
  255. break;
  256. case 0x4000:
  257. f = "MB";
  258. break;
  259. case 0x8000:
  260. f = "FETCH\t0(R%b)";
  261. break;
  262. case 0xA000:
  263. f = "FETCH_M\t0(R%b)";
  264. break;
  265. case 0xC000:
  266. f = "RPCC\tR%a";
  267. break;
  268. case 0xE000:
  269. f = "RC\tR%a";
  270. break;
  271. case 0xF000:
  272. f = "RS\tR%a";
  273. break;
  274. default:
  275. f = "%w";
  276. }
  277. format(0, i, f);
  278. }
  279. static char *jmpcode[4] = { "JMP", "JSR", "RET", "JSR_COROUTINE" };
  280. static void
  281. jmp(Opcode *o, Instr *i)
  282. {
  283. int hint;
  284. char *m;
  285. USED(o);
  286. hint = (i->mem >> 14) & 3;
  287. m = jmpcode[hint];
  288. if (i->ra == 31) {
  289. if (hint == 2 && i->rb == 29)
  290. bprint(i, m);
  291. else
  292. format(m, i, "(R%b)");
  293. }
  294. else
  295. format(m, i, "R%a,(R%b)");
  296. }
  297. static void
  298. br(Opcode *o, Instr *i)
  299. {
  300. if (i->ra == 31)
  301. format(o->mnemonic, i, "%B");
  302. else
  303. format(o->mnemonic, i, o->ken);
  304. }
  305. static void
  306. bsr(Opcode *o, Instr *i)
  307. {
  308. if (i->ra == 26)
  309. format(o->mnemonic, i, "%B");
  310. else
  311. format(o->mnemonic, i, o->ken);
  312. }
  313. static void
  314. mult(Opcode *o, Instr *i)
  315. {
  316. char *m;
  317. switch (i->function) {
  318. case 0x00:
  319. m = "MULL";
  320. break;
  321. case 0x20:
  322. m = "MULQ";
  323. break;
  324. case 0x40:
  325. m = "MULL/V";
  326. break;
  327. case 0x60:
  328. m = "MULQ/V";
  329. break;
  330. case 0x30:
  331. m = "UMULH";
  332. break;
  333. default:
  334. format("???", i, "%w");
  335. return;
  336. }
  337. format(m, i, o->ken);
  338. }
  339. static char alphaload[] = "%l,R%a";
  340. static char alphafload[] = "%l,F%a";
  341. static char alphastore[] = "R%a,%l";
  342. static char alphafstore[] = "F%a,%l";
  343. static char alphabranch[] = "R%a,%B";
  344. static char alphafbranch[] = "F%a,%B";
  345. static char alphaint[] = "%v,R%a,R%c";
  346. static char alphafp[] = "F%b,F%a,F%c";
  347. static char alphafp2[] = "F%b,F%c";
  348. static char alphaxxx[] = "%w";
  349. static Opcode opcodes[64] = {
  350. "PAL", 0, alphaxxx,
  351. "OPC01", 0, alphaxxx,
  352. "OPC02", 0, alphaxxx,
  353. "OPC03", 0, alphaxxx,
  354. "OPC04", 0, alphaxxx,
  355. "OPC05", 0, alphaxxx,
  356. "OPC06", 0, alphaxxx,
  357. "OPC07", 0, alphaxxx,
  358. "MOVQA", load, alphaload,
  359. "MOVQAH", load, alphaload,
  360. "MOVBU", load, alphaload, /* v 3 */
  361. "MOVQU", load, alphaload,
  362. "MOVWU", load, alphaload, /* v 3 */
  363. "MOVWU", store, alphastore, /* v 3 */
  364. "MOVBU", store, alphastore, /* v 3 */
  365. "MOVQU", store, alphastore,
  366. 0, 0, 0, /* int arith */
  367. 0, 0, 0, /* logical */
  368. 0, 0, 0, /* shift */
  369. 0, mult, alphaint,
  370. "OPC14", 0, alphaxxx,
  371. "vax", 0, alphafp, /* vax */
  372. 0, 0, 0, /* ieee */
  373. 0, 0, 0, /* fp */
  374. 0, misc, alphaxxx,
  375. "PAL19 [HW_MFPR]",0, alphaxxx,
  376. "JSR", jmp, 0,
  377. "PAL1B [HW_LD]",0, alphaxxx,
  378. "OPC1C", 0, alphaxxx,
  379. "PAL1D [HW_MTPR]",0, alphaxxx,
  380. "PAL1E [HW_REI]",0, alphaxxx,
  381. "PAL1F [HW_ST]",0, alphaxxx,
  382. "MOVF", loadf, alphafload,
  383. "MOVG", loadf, alphafload,
  384. "MOVS", loadf, alphafload,
  385. "MOVT", loadf, alphafload,
  386. "MOVF", storef, alphafstore,
  387. "MOVG", storef, alphafstore,
  388. "MOVS", storef, alphafstore,
  389. "MOVT", storef, alphafstore,
  390. "MOVL", load, alphaload,
  391. "MOVQ", load, alphaload,
  392. "MOVLL", load, alphaload,
  393. "MOVQL", load, alphaload,
  394. "MOVL", store, alphastore,
  395. "MOVQ", store, alphastore,
  396. "MOVLC", store, alphastore,
  397. "MOVQC", store, alphastore,
  398. "JMP", br, alphabranch,
  399. "FBEQ", 0, alphafbranch,
  400. "FBLT", 0, alphafbranch,
  401. "FBLE", 0, alphafbranch,
  402. "JSR", bsr, alphabranch,
  403. "FBNE", 0, alphafbranch,
  404. "FBGE", 0, alphafbranch,
  405. "FBGT", 0, alphafbranch,
  406. "BLBC", 0, alphafbranch,
  407. "BEQ", 0, alphabranch,
  408. "BLT", 0, alphabranch,
  409. "BLE", 0, alphabranch,
  410. "BLBS", 0, alphabranch,
  411. "BNE", 0, alphabranch,
  412. "BGE", 0, alphabranch,
  413. "BGT", 0, alphabranch,
  414. };
  415. static Opcode fpopcodes[64] = {
  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. "???", 0, alphaxxx,
  432. "CVTLQ", 0, alphafp2,
  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. "???", 0, alphaxxx,
  448. "CPYS", 0, alphafp,
  449. "CPYSN", 0, alphafp,
  450. "CPYSE", 0, alphafp,
  451. "???", 0, alphaxxx,
  452. "MOVT", 0, "FPCR,F%a",
  453. "MOVT", 0, "F%a,FPCR",
  454. "???", 0, alphaxxx,
  455. "???", 0, alphaxxx,
  456. "???", 0, alphaxxx,
  457. "???", 0, alphaxxx,
  458. "FCMOVEQ", 0, alphafp,
  459. "FCMOVNE", 0, alphafp,
  460. "FCMOVLT", 0, alphafp,
  461. "FCMOVGE", 0, alphafp,
  462. "FCMOVLE", 0, alphafp,
  463. "FCMOVGT", 0, alphafp,
  464. "CVTQL", 0, alphafp2,
  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. "???", 0, alphaxxx,
  480. };
  481. static Opcode ieeeopcodes[64] = {
  482. "ADDS", 0, alphafp,
  483. "SUBS", 0, alphafp,
  484. "MULS", 0, alphafp,
  485. "DIVS", 0, alphafp,
  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. "???", 0, alphaxxx,
  514. "ADDT", 0, alphafp,
  515. "SUBT", 0, alphafp,
  516. "MULT", 0, alphafp,
  517. "DIVT", 0, alphafp,
  518. "CMPTUN", 0, alphafp,
  519. "CMPTEQ", 0, alphafp,
  520. "CMPTLT", 0, alphafp,
  521. "CMPTLE", 0, alphafp,
  522. "???", 0, alphaxxx,
  523. "???", 0, alphaxxx,
  524. "???", 0, alphaxxx,
  525. "???", 0, alphaxxx,
  526. "CVTTS", 0, alphafp2,
  527. "???", 0, alphaxxx,
  528. "???", 0, alphaxxx,
  529. "CVTTQ", 0, alphafp2,
  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. "???", 0, alphaxxx,
  542. "CVTQS", 0, alphafp2,
  543. "???", 0, alphaxxx,
  544. "CVTQT", 0, alphafp2,
  545. "???", 0, alphaxxx,
  546. };
  547. static uchar amap[128] = {
  548. [0x00] 1,
  549. [0x40] 2,
  550. [0x20] 3,
  551. [0x60] 4,
  552. [0x09] 5,
  553. [0x49] 6,
  554. [0x29] 7,
  555. [0x69] 8,
  556. [0x2D] 9,
  557. [0x4D] 10,
  558. [0x6D] 11,
  559. [0x1D] 12,
  560. [0x3D] 13,
  561. [0x0F] 14,
  562. [0x02] 15,
  563. [0x0B] 16,
  564. [0x12] 17,
  565. [0x1B] 18,
  566. [0x22] 19,
  567. [0x2B] 20,
  568. [0x32] 21,
  569. [0x3B] 22,
  570. };
  571. static Opcode arithopcodes[64] = {
  572. "???", 0, alphaxxx,
  573. "ADDL", 0, alphaint,
  574. "ADDL/V", 0, alphaint,
  575. "ADDQ", 0, alphaint,
  576. "ADDQ/V", 0, alphaint,
  577. "SUBL", 0, alphaint,
  578. "SUBL/V", 0, alphaint,
  579. "SUBQ", 0, alphaint,
  580. "SUBQ/V", 0, alphaint,
  581. "CMPEQ", 0, alphaint,
  582. "CMPLT", 0, alphaint,
  583. "CMPLE", 0, alphaint,
  584. "CMPULT", 0, alphaint,
  585. "CMPULE", 0, alphaint,
  586. "CMPBGE", 0, alphaint,
  587. "S4ADDL", 0, alphaint,
  588. "S4SUBL", 0, alphaint,
  589. "S8ADDL", 0, alphaint,
  590. "S8SUBL", 0, alphaint,
  591. "S4ADDQ", 0, alphaint,
  592. "S4SUBQ", 0, alphaint,
  593. "S8ADDQ", 0, alphaint,
  594. "S8SUBQ", 0, alphaint,
  595. };
  596. static uchar lmap[128] = {
  597. [0x00] 1,
  598. [0x20] 2,
  599. [0x40] 3,
  600. [0x08] 4,
  601. [0x28] 5,
  602. [0x48] 6,
  603. [0x24] 7,
  604. [0x44] 8,
  605. [0x64] 9,
  606. [0x26] 7,
  607. [0x46] 8,
  608. [0x66] 9,
  609. [0x14] 10,
  610. [0x16] 11,
  611. };
  612. static Opcode logicalopcodes[64] = {
  613. "???", 0, alphaxxx,
  614. "AND", 0, alphaint,
  615. "OR", 0, alphaint,
  616. "XOR", 0, alphaint,
  617. "ANDNOT", 0, alphaint,
  618. "ORNOT", 0, alphaint,
  619. "XORNOT", 0, alphaint,
  620. "CMOVEQ", 0, alphaint,
  621. "CMOVLT", 0, alphaint,
  622. "CMOVLE", 0, alphaint,
  623. "CMOVNE", 0, alphaint,
  624. "CMOVGE", 0, alphaint,
  625. "CMOVGT", 0, alphaint,
  626. "CMOVLBS", 0, alphaint,
  627. "CMOVLBC", 0, alphaint,
  628. };
  629. static uchar smap[128] = {
  630. [0x39] 1,
  631. [0x3C] 2,
  632. [0x34] 3,
  633. [0x06] 4,
  634. [0x16] 5,
  635. [0x26] 6,
  636. [0x36] 7,
  637. [0x5A] 8,
  638. [0x6A] 9,
  639. [0x7A] 10,
  640. [0x0B] 11,
  641. [0x1B] 12,
  642. [0x2B] 13,
  643. [0x3B] 14,
  644. [0x57] 15,
  645. [0x67] 16,
  646. [0x77] 17,
  647. [0x02] 18,
  648. [0x12] 19,
  649. [0x22] 20,
  650. [0x32] 21,
  651. [0x52] 22,
  652. [0x62] 23,
  653. [0x72] 24,
  654. [0x30] 25,
  655. [0x31] 26,
  656. };
  657. static Opcode shiftopcodes[64] = {
  658. "???", 0, alphaxxx,
  659. "SLLQ", 0, alphaint,
  660. "SRAQ", 0, alphaint,
  661. "SRLQ", 0, alphaint,
  662. "EXTBL", 0, alphaint,
  663. "EXTWL", 0, alphaint,
  664. "EXTLL", 0, alphaint,
  665. "EXTQL", 0, alphaint,
  666. "EXTWH", 0, alphaint,
  667. "EXTLH", 0, alphaint,
  668. "EXTQH", 0, alphaint,
  669. "INSBL", 0, alphaint,
  670. "INSWL", 0, alphaint,
  671. "INSLL", 0, alphaint,
  672. "INSQL", 0, alphaint,
  673. "INSWH", 0, alphaint,
  674. "INSLH", 0, alphaint,
  675. "INSQH", 0, alphaint,
  676. "MSKBL", 0, alphaint,
  677. "MSKWL", 0, alphaint,
  678. "MSKLL", 0, alphaint,
  679. "MSKQL", 0, alphaint,
  680. "MSKWH", 0, alphaint,
  681. "MSKLH", 0, alphaint,
  682. "MSKQH", 0, alphaint,
  683. "ZAP", 0, alphaint,
  684. "ZAPNOT", 0, alphaint,
  685. };
  686. static void
  687. format(char *mnemonic, Instr *i, char *f)
  688. {
  689. if (mnemonic)
  690. format(0, i, mnemonic);
  691. if (f == 0)
  692. return;
  693. if (mnemonic)
  694. if (i->curr < i->end)
  695. *i->curr++ = '\t';
  696. for ( ; *f && i->curr < i->end; f++) {
  697. if (*f != '%') {
  698. *i->curr++ = *f;
  699. continue;
  700. }
  701. switch (*++f) {
  702. case 'a':
  703. bprint(i, "%d", i->ra);
  704. break;
  705. case 'b':
  706. bprint(i, "%d", i->rb);
  707. break;
  708. case 'c':
  709. bprint(i, "%d", i->rc);
  710. break;
  711. case 'v':
  712. if (i->islit)
  713. bprint(i, "$%ux", i->literal);
  714. else
  715. bprint(i, "R%d", i->rb);
  716. break;
  717. case 'l':
  718. bprint(i, "%lx(R%d)", i->mem, i->rb);
  719. break;
  720. case 'i':
  721. bprint(i, "$%lx", i->mem);
  722. break;
  723. case 'B':
  724. i->curr += symoff(i->curr, i->end-i->curr,
  725. (i->branch<<2)+i->addr+4, CANY);
  726. break;
  727. case 'w':
  728. bprint(i, "[%lux]", i->w0);
  729. break;
  730. case '\0':
  731. *i->curr++ = '%';
  732. return;
  733. default:
  734. bprint(i, "%%%c", *f);
  735. break;
  736. }
  737. }
  738. *i->curr = 0;
  739. }
  740. static int
  741. printins(Map *map, uvlong pc, char *buf, int n)
  742. {
  743. Instr i;
  744. Opcode *o;
  745. uchar op;
  746. i.curr = buf;
  747. i.end = buf+n-1;
  748. mymap = map;
  749. if (mkinstr(pc, &i) < 0)
  750. return -1;
  751. switch (i.op) {
  752. case 0x10: /* INTA */
  753. o = arithopcodes;
  754. op = amap[i.function];
  755. break;
  756. case 0x11: /* INTL */
  757. o = logicalopcodes;
  758. op = lmap[i.function];
  759. break;
  760. case 0x12: /* INTS */
  761. o = shiftopcodes;
  762. op = smap[i.function];
  763. break;
  764. case 0x16: /* FLTI */
  765. o = ieeeopcodes;
  766. op = i.fpfn;
  767. break;
  768. case 0x17: /* FLTL */
  769. o = fpopcodes;
  770. op = i.fpfn;
  771. break;
  772. default:
  773. o = opcodes;
  774. op = i.op;
  775. break;
  776. }
  777. if (o[op].f)
  778. (*o[op].f)(&o[op], &i);
  779. else
  780. format(o[op].mnemonic, &i, o[op].ken);
  781. return i.size*4;
  782. }
  783. static int
  784. alphainst(Map *map, uvlong pc, char modifier, char *buf, int n)
  785. {
  786. USED(modifier);
  787. return printins(map, pc, buf, n);
  788. }
  789. static int
  790. alphadas(Map *map, uvlong pc, char *buf, int n)
  791. {
  792. Instr i;
  793. i.curr = buf;
  794. i.end = buf+n;
  795. mymap = map;
  796. if (mkinstr(pc, &i) < 0)
  797. return -1;
  798. if (i.end-i.curr > 8)
  799. i.curr = _hexify(buf, i.w0, 7);
  800. if (i.size == 2 && i.end-i.curr > 9) {
  801. *i.curr++ = ' ';
  802. i.curr = _hexify(i.curr, i.w1, 7);
  803. }
  804. *i.curr = 0;
  805. return i.size*4;
  806. }
  807. static int
  808. alphainstlen(Map *map, uvlong pc)
  809. {
  810. Instr i;
  811. mymap = map;
  812. if (mkinstr(pc, &i) < 0)
  813. return -1;
  814. return i.size*4;
  815. }
  816. static int
  817. alphafoll(Map *map, uvlong pc, Rgetter rget, uvlong *foll)
  818. {
  819. char buf[8];
  820. Instr i;
  821. mymap = map;
  822. if (mkinstr(pc, &i) < 0)
  823. return -1;
  824. switch(i.op) {
  825. case 0x1A: /* JMP/JSR/RET */
  826. sprint(buf, "R%d", i.rb);
  827. foll[0] = (*rget)(map, buf);
  828. return 1;
  829. case 0x30: /* BR */
  830. case 0x34: /* BSR */
  831. foll[0] = pc+4 + (i.branch<<2);
  832. return 1;
  833. default:
  834. if (i.op > 0x30) { /* cond */
  835. foll[0] = pc+4;
  836. foll[1] = pc+4 + (i.branch<<2);
  837. return 2;
  838. }
  839. foll[0] = pc+i.size*4;
  840. return 1;
  841. }
  842. }