qdb.c 30 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363
  1. #include <u.h>
  2. #include <libc.h>
  3. #include <bio.h>
  4. #include <mach.h>
  5. /*
  6. * PowerPC-specific debugger interface,
  7. * including 64-bit modes
  8. * forsyth@terzarima.net
  9. */
  10. static char *powerexcep(Map*, Rgetter);
  11. static int powerfoll(Map*, uvlong, Rgetter, uvlong*);
  12. static int powerinst(Map*, uvlong, char, char*, int);
  13. static int powerinstlen(Map*, uvlong);
  14. static int powerdas(Map*, uvlong, char*, int);
  15. /*
  16. * Machine description
  17. */
  18. Machdata powermach =
  19. {
  20. {0x02, 0x8f, 0xff, 0xff}, /* break point */ /* BUG */
  21. 4, /* break point size */
  22. beswab, /* short to local byte order */
  23. beswal, /* long to local byte order */
  24. beswav, /* vlong to local byte order */
  25. risctrace, /* print C traceback */
  26. riscframe, /* frame finder */
  27. powerexcep, /* print exception */
  28. 0, /* breakpoint fixup */
  29. beieeesftos, /* single precision float printer */
  30. beieeedftos, /* double precisioin float printer */
  31. powerfoll, /* following addresses */
  32. powerinst, /* print instruction */
  33. powerdas, /* dissembler */
  34. powerinstlen, /* instruction size */
  35. };
  36. static char *excname[] =
  37. {
  38. "reserved 0",
  39. "system reset",
  40. "machine check",
  41. "data access",
  42. "instruction access",
  43. "external interrupt",
  44. "alignment",
  45. "program exception",
  46. "floating-point unavailable",
  47. "decrementer",
  48. "i/o controller interface error",
  49. "reserved B",
  50. "system call",
  51. "trace trap",
  52. "floating point assist",
  53. "reserved",
  54. "ITLB miss",
  55. "DTLB load miss",
  56. "DTLB store miss",
  57. "instruction address breakpoint"
  58. "SMI interrupt"
  59. "reserved 15",
  60. "reserved 16",
  61. "reserved 17",
  62. "reserved 18",
  63. "reserved 19",
  64. "reserved 1A",
  65. /* the following are made up on a program exception */
  66. "floating point exception", /* FPEXC */
  67. "illegal instruction",
  68. "privileged instruction",
  69. "trap",
  70. "illegal operation",
  71. };
  72. static char*
  73. powerexcep(Map *map, Rgetter rget)
  74. {
  75. long c;
  76. static char buf[32];
  77. c = (*rget)(map, "CAUSE") >> 8;
  78. if(c < nelem(excname))
  79. return excname[c];
  80. sprint(buf, "unknown trap #%lx", c);
  81. return buf;
  82. }
  83. /*
  84. * disassemble PowerPC opcodes
  85. */
  86. #define REGSP 1 /* should come from q.out.h, but there's a clash */
  87. #define REGSB 2
  88. static char FRAMENAME[] = ".frame";
  89. static Map *mymap;
  90. /*
  91. * ibm conventions for these: bit 0 is top bit
  92. * from table 10-1
  93. */
  94. typedef struct {
  95. uchar aa; /* bit 30 */
  96. uchar crba; /* bits 11-15 */
  97. uchar crbb; /* bits 16-20 */
  98. long bd; /* bits 16-29 */
  99. uchar crfd; /* bits 6-8 */
  100. uchar crfs; /* bits 11-13 */
  101. uchar bi; /* bits 11-15 */
  102. uchar bo; /* bits 6-10 */
  103. uchar crbd; /* bits 6-10 */
  104. union {
  105. short d; /* bits 16-31 */
  106. short simm;
  107. ushort uimm;
  108. };
  109. uchar fm; /* bits 7-14 */
  110. uchar fra; /* bits 11-15 */
  111. uchar frb; /* bits 16-20 */
  112. uchar frc; /* bits 21-25 */
  113. uchar frs; /* bits 6-10 */
  114. uchar frd; /* bits 6-10 */
  115. uchar crm; /* bits 12-19 */
  116. long li; /* bits 6-29 || b'00' */
  117. uchar lk; /* bit 31 */
  118. uchar mb; /* bits 21-25 */
  119. uchar me; /* bits 26-30 */
  120. uchar xmbe; /* bits 26,21-25: mb[5] || mb[0:4], also xme */
  121. uchar xsh; /* bits 30,16-20: sh[5] || sh[0:4] */
  122. uchar nb; /* bits 16-20 */
  123. uchar op; /* bits 0-5 */
  124. uchar oe; /* bit 21 */
  125. uchar ra; /* bits 11-15 */
  126. uchar rb; /* bits 16-20 */
  127. uchar rc; /* bit 31 */
  128. union {
  129. uchar rs; /* bits 6-10 */
  130. uchar rd;
  131. };
  132. uchar sh; /* bits 16-20 */
  133. ushort spr; /* bits 11-20 */
  134. uchar to; /* bits 6-10 */
  135. uchar imm; /* bits 16-19 */
  136. ushort xo; /* bits 21-30, 22-30, 26-30, or 30 (beware) */
  137. uvlong imm64;
  138. long w0;
  139. long w1;
  140. uvlong addr; /* pc of instruction */
  141. short target;
  142. short m64; /* 64-bit mode */
  143. char *curr; /* current fill level in output buffer */
  144. char *end; /* end of buffer */
  145. int size; /* number of longs in instr */
  146. char *err; /* errmsg */
  147. } Instr;
  148. #define IBF(v,a,b) (((ulong)(v)>>(32-(b)-1)) & ~(~0L<<(((b)-(a)+1))))
  149. #define IB(v,b) IBF((v),(b),(b))
  150. #pragma varargck argpos bprint 2
  151. static void
  152. bprint(Instr *i, char *fmt, ...)
  153. {
  154. va_list arg;
  155. va_start(arg, fmt);
  156. i->curr = vseprint(i->curr, i->end, fmt, arg);
  157. va_end(arg);
  158. }
  159. static int
  160. decode(uvlong pc, Instr *i)
  161. {
  162. ulong w;
  163. if (get4(mymap, pc, &w) < 0) {
  164. werrstr("can't read instruction: %r");
  165. return -1;
  166. }
  167. i->m64 = asstype == APOWER64;
  168. i->aa = IB(w, 30);
  169. i->crba = IBF(w, 11, 15);
  170. i->crbb = IBF(w, 16, 20);
  171. i->bd = IBF(w, 16, 29)<<2;
  172. if(i->bd & 0x8000)
  173. i->bd |= ~0L<<16;
  174. i->crfd = IBF(w, 6, 8);
  175. i->crfs = IBF(w, 11, 13);
  176. i->bi = IBF(w, 11, 15);
  177. i->bo = IBF(w, 6, 10);
  178. i->crbd = IBF(w, 6, 10);
  179. i->uimm = IBF(w, 16, 31); /* also d, simm */
  180. i->fm = IBF(w, 7, 14);
  181. i->fra = IBF(w, 11, 15);
  182. i->frb = IBF(w, 16, 20);
  183. i->frc = IBF(w, 21, 25);
  184. i->frs = IBF(w, 6, 10);
  185. i->frd = IBF(w, 6, 10);
  186. i->crm = IBF(w, 12, 19);
  187. i->li = IBF(w, 6, 29)<<2;
  188. if(IB(w, 6))
  189. i->li |= ~0<<25;
  190. i->lk = IB(w, 31);
  191. i->mb = IBF(w, 21, 25);
  192. i->me = IBF(w, 26, 30);
  193. i->xmbe = (IB(w,26)<<5) | i->mb;
  194. i->nb = IBF(w, 16, 20);
  195. i->op = IBF(w, 0, 5);
  196. i->oe = IB(w, 21);
  197. i->ra = IBF(w, 11, 15);
  198. i->rb = IBF(w, 16, 20);
  199. i->rc = IB(w, 31);
  200. i->rs = IBF(w, 6, 10); /* also rd */
  201. i->sh = IBF(w, 16, 20);
  202. i->xsh = (IB(w, 30)<<5) | i->sh;
  203. i->spr = IBF(w, 11, 20);
  204. i->to = IBF(w, 6, 10);
  205. i->imm = IBF(w, 16, 19);
  206. i->xo = IBF(w, 21, 30); /* bits 21-30, 22-30, 26-30, or 30 (beware) */
  207. if(i->op == 58){ /* class of 64-bit loads */
  208. i->xo = i->simm & 3;
  209. i->simm &= ~3;
  210. }
  211. i->imm64 = i->simm;
  212. if(i->op == 15)
  213. i->imm64 <<= 16;
  214. else if(i->op == 25 || i->op == 27 || i->op == 29)
  215. i->imm64 = (uvlong)(i->uimm<<16);
  216. i->w0 = w;
  217. i->target = -1;
  218. i->addr = pc;
  219. i->size = 1;
  220. return 1;
  221. }
  222. static int
  223. mkinstr(uvlong pc, Instr *i)
  224. {
  225. Instr x;
  226. if(decode(pc, i) < 0)
  227. return -1;
  228. /*
  229. * combine ADDIS/ORI (CAU/ORIL) into MOVW
  230. * also ORIS/ORIL for unsigned in 64-bit mode
  231. */
  232. if ((i->op == 15 || i->op == 25) && i->ra==0) {
  233. if(decode(pc+4, &x) < 0)
  234. return -1;
  235. if (x.op == 24 && x.rs == x.ra && x.ra == i->rd) {
  236. i->imm64 |= (x.imm64 & 0xFFFF);
  237. if(i->op != 15)
  238. i->imm64 &= 0xFFFFFFFFUL;
  239. i->w1 = x.w0;
  240. i->target = x.rd;
  241. i->size++;
  242. return 1;
  243. }
  244. }
  245. return 1;
  246. }
  247. static int
  248. plocal(Instr *i)
  249. {
  250. long offset;
  251. Symbol s;
  252. if (!findsym(i->addr, CTEXT, &s) || !findlocal(&s, FRAMENAME, &s))
  253. return -1;
  254. offset = s.value - i->imm64;
  255. if (offset > 0) {
  256. if(getauto(&s, offset, CAUTO, &s)) {
  257. bprint(i, "%s+%lld(SP)", s.name, s.value);
  258. return 1;
  259. }
  260. } else {
  261. if (getauto(&s, -offset-4, CPARAM, &s)) {
  262. bprint(i, "%s+%ld(FP)", s.name, -offset);
  263. return 1;
  264. }
  265. }
  266. return -1;
  267. }
  268. static int
  269. pglobal(Instr *i, uvlong off, int anyoff, char *reg)
  270. {
  271. Symbol s, s2;
  272. uvlong off1;
  273. if(findsym(off, CANY, &s) &&
  274. off-s.value < 4096 &&
  275. (s.class == CDATA || s.class == CTEXT)) {
  276. if(off==s.value && s.name[0]=='$'){
  277. off1 = 0;
  278. geta(mymap, s.value, &off1);
  279. if(off1 && findsym(off1, CANY, &s2) && s2.value == off1){
  280. bprint(i, "$%s%s", s2.name, reg);
  281. return 1;
  282. }
  283. }
  284. bprint(i, "%s", s.name);
  285. if (s.value != off)
  286. bprint(i, "+%llux", off-s.value);
  287. bprint(i, reg);
  288. return 1;
  289. }
  290. if(!anyoff)
  291. return 0;
  292. bprint(i, "%llux%s", off, reg);
  293. return 1;
  294. }
  295. static void
  296. address(Instr *i)
  297. {
  298. if (i->ra == REGSP && plocal(i) >= 0)
  299. return;
  300. if (i->ra == REGSB && mach->sb && pglobal(i, mach->sb+i->imm64, 0, "(SB)"))
  301. return;
  302. if(i->simm < 0)
  303. bprint(i, "-%x(R%d)", -i->simm, i->ra);
  304. else
  305. bprint(i, "%llux(R%d)", i->imm64, i->ra);
  306. }
  307. static char *tcrbits[] = {"LT", "GT", "EQ", "VS"};
  308. static char *fcrbits[] = {"GE", "LE", "NE", "VC"};
  309. typedef struct Opcode Opcode;
  310. struct Opcode {
  311. uchar op;
  312. ushort xo;
  313. ushort xomask;
  314. char *mnemonic;
  315. void (*f)(Opcode *, Instr *);
  316. char *ken;
  317. int flags;
  318. };
  319. static void format(char *, Instr *, char *);
  320. static void
  321. branch(Opcode *o, Instr *i)
  322. {
  323. char buf[8];
  324. int bo, bi;
  325. bo = i->bo & ~1; /* ignore prediction bit */
  326. if(bo==4 || bo==12 || bo==20) { /* simple forms */
  327. if(bo != 20) {
  328. bi = i->bi&3;
  329. sprint(buf, "B%s%%L", bo==12? tcrbits[bi]: fcrbits[bi]);
  330. format(buf, i, nil);
  331. bprint(i, "\t");
  332. if(i->bi > 4)
  333. bprint(i, "CR(%d),", i->bi/4);
  334. } else
  335. format("BR%L\t", i, nil);
  336. if(i->op == 16)
  337. format(0, i, "%J");
  338. else if(i->op == 19 && i->xo == 528)
  339. format(0, i, "(CTR)");
  340. else if(i->op == 19 && i->xo == 16)
  341. format(0, i, "(LR)");
  342. } else
  343. format(o->mnemonic, i, o->ken);
  344. }
  345. static void
  346. addi(Opcode *o, Instr *i)
  347. {
  348. if (i->op==14 && i->ra == 0)
  349. format("MOVW", i, "%i,R%d");
  350. else if (i->ra == REGSB) {
  351. bprint(i, "MOVW\t$");
  352. address(i);
  353. bprint(i, ",R%d", i->rd);
  354. } else if(i->op==14 && i->simm < 0) {
  355. bprint(i, "SUB\t$%d,R%d", -i->simm, i->ra);
  356. if(i->rd != i->ra)
  357. bprint(i, ",R%d", i->rd);
  358. } else if(i->ra == i->rd) {
  359. format(o->mnemonic, i, "%i");
  360. bprint(i, ",R%d", i->rd);
  361. } else
  362. format(o->mnemonic, i, o->ken);
  363. }
  364. static void
  365. addis(Opcode *o, Instr *i)
  366. {
  367. long v;
  368. v = i->imm64;
  369. if (i->op==15 && i->ra == 0)
  370. bprint(i, "MOVW\t$%lux,R%d", v, i->rd);
  371. else if (i->op==15 && i->ra == REGSB) {
  372. bprint(i, "MOVW\t$");
  373. address(i);
  374. bprint(i, ",R%d", i->rd);
  375. } else if(i->op==15 && v < 0) {
  376. bprint(i, "SUB\t$%ld,R%d", -v, i->ra);
  377. if(i->rd != i->ra)
  378. bprint(i, ",R%d", i->rd);
  379. } else {
  380. format(o->mnemonic, i, nil);
  381. bprint(i, "\t$%ld,R%d", v, i->ra);
  382. if(i->rd != i->ra)
  383. bprint(i, ",R%d", i->rd);
  384. }
  385. }
  386. static void
  387. andi(Opcode *o, Instr *i)
  388. {
  389. if (i->ra == i->rs)
  390. format(o->mnemonic, i, "%I,R%d");
  391. else
  392. format(o->mnemonic, i, o->ken);
  393. }
  394. static void
  395. gencc(Opcode *o, Instr *i)
  396. {
  397. format(o->mnemonic, i, o->ken);
  398. }
  399. static void
  400. gen(Opcode *o, Instr *i)
  401. {
  402. format(o->mnemonic, i, o->ken);
  403. if (i->rc)
  404. bprint(i, " [illegal Rc]");
  405. }
  406. static void
  407. ldx(Opcode *o, Instr *i)
  408. {
  409. if(i->ra == 0)
  410. format(o->mnemonic, i, "(R%b),R%d");
  411. else
  412. format(o->mnemonic, i, "(R%b+R%a),R%d");
  413. if(i->rc)
  414. bprint(i, " [illegal Rc]");
  415. }
  416. static void
  417. stx(Opcode *o, Instr *i)
  418. {
  419. if(i->ra == 0)
  420. format(o->mnemonic, i, "R%d,(R%b)");
  421. else
  422. format(o->mnemonic, i, "R%d,(R%b+R%a)");
  423. if(i->rc && i->xo != 150)
  424. bprint(i, " [illegal Rc]");
  425. }
  426. static void
  427. fldx(Opcode *o, Instr *i)
  428. {
  429. if(i->ra == 0)
  430. format(o->mnemonic, i, "(R%b),F%d");
  431. else
  432. format(o->mnemonic, i, "(R%b+R%a),F%d");
  433. if(i->rc)
  434. bprint(i, " [illegal Rc]");
  435. }
  436. static void
  437. fstx(Opcode *o, Instr *i)
  438. {
  439. if(i->ra == 0)
  440. format(o->mnemonic, i, "F%d,(R%b)");
  441. else
  442. format(o->mnemonic, i, "F%d,(R%b+R%a)");
  443. if(i->rc)
  444. bprint(i, " [illegal Rc]");
  445. }
  446. static void
  447. dcb(Opcode *o, Instr *i)
  448. {
  449. if(i->ra == 0)
  450. format(o->mnemonic, i, "(R%b)");
  451. else
  452. format(o->mnemonic, i, "(R%b+R%a)");
  453. if(i->rd)
  454. bprint(i, " [illegal Rd]");
  455. if(i->rc)
  456. bprint(i, " [illegal Rc]");
  457. }
  458. static void
  459. lw(Opcode *o, Instr *i, char r)
  460. {
  461. format(o->mnemonic, i, nil);
  462. bprint(i, "\t");
  463. address(i);
  464. bprint(i, ",%c%d", r, i->rd);
  465. }
  466. static void
  467. load(Opcode *o, Instr *i)
  468. {
  469. lw(o, i, 'R');
  470. }
  471. static void
  472. fload(Opcode *o, Instr *i)
  473. {
  474. lw(o, i, 'F');
  475. }
  476. static void
  477. sw(Opcode *o, Instr *i, char r)
  478. {
  479. int offset;
  480. Symbol s;
  481. if (i->rs == REGSP) {
  482. if (findsym(i->addr, CTEXT, &s) && findlocal(&s, FRAMENAME, &s)) {
  483. offset = s.value-i->imm64;
  484. if (offset > 0 && getauto(&s, offset, CAUTO, &s)) {
  485. format(o->mnemonic, i, nil);
  486. bprint(i, "\t%c%d,%s-%d(SP)", r, i->rd, s.name, offset);
  487. return;
  488. }
  489. }
  490. }
  491. if (i->rs == REGSB && mach->sb) {
  492. format(o->mnemonic, i, nil);
  493. bprint(i, "\t%c%d,", r, i->rd);
  494. address(i);
  495. return;
  496. }
  497. if (r == 'F')
  498. format(o->mnemonic, i, "F%d,%l");
  499. else
  500. format(o->mnemonic, i, o->ken);
  501. }
  502. static void
  503. store(Opcode *o, Instr *i)
  504. {
  505. sw(o, i, 'R');
  506. }
  507. static void
  508. fstore(Opcode *o, Instr *i)
  509. {
  510. sw(o, i, 'F');
  511. }
  512. static void
  513. shifti(Opcode *o, Instr *i)
  514. {
  515. if (i->ra == i->rs)
  516. format(o->mnemonic, i, "$%k,R%a");
  517. else
  518. format(o->mnemonic, i, o->ken);
  519. }
  520. static void
  521. shift(Opcode *o, Instr *i)
  522. {
  523. if (i->ra == i->rs)
  524. format(o->mnemonic, i, "R%b,R%a");
  525. else
  526. format(o->mnemonic, i, o->ken);
  527. }
  528. static void
  529. add(Opcode *o, Instr *i)
  530. {
  531. if (i->rd == i->ra)
  532. format(o->mnemonic, i, "R%b,R%d");
  533. else if (i->rd == i->rb)
  534. format(o->mnemonic, i, "R%a,R%d");
  535. else
  536. format(o->mnemonic, i, o->ken);
  537. }
  538. static void
  539. sub(Opcode *o, Instr *i)
  540. {
  541. format(o->mnemonic, i, nil);
  542. bprint(i, "\t");
  543. if(i->op == 31) {
  544. bprint(i, "\tR%d,R%d", i->ra, i->rb); /* subtract Ra from Rb */
  545. if(i->rd != i->rb)
  546. bprint(i, ",R%d", i->rd);
  547. } else
  548. bprint(i, "\tR%d,$%d,R%d", i->ra, i->simm, i->rd);
  549. }
  550. static void
  551. qdiv(Opcode *o, Instr *i)
  552. {
  553. format(o->mnemonic, i, nil);
  554. if(i->op == 31)
  555. bprint(i, "\tR%d,R%d", i->rb, i->ra);
  556. else
  557. bprint(i, "\t$%d,R%d", i->simm, i->ra);
  558. if(i->ra != i->rd)
  559. bprint(i, ",R%d", i->rd);
  560. }
  561. static void
  562. and(Opcode *o, Instr *i)
  563. {
  564. if (i->op == 31) {
  565. /* Rb,Rs,Ra */
  566. if (i->ra == i->rs)
  567. format(o->mnemonic, i, "R%b,R%a");
  568. else if (i->ra == i->rb)
  569. format(o->mnemonic, i, "R%s,R%a");
  570. else
  571. format(o->mnemonic, i, o->ken);
  572. } else {
  573. /* imm,Rs,Ra */
  574. if (i->ra == i->rs)
  575. format(o->mnemonic, i, "%I,R%a");
  576. else
  577. format(o->mnemonic, i, o->ken);
  578. }
  579. }
  580. static void
  581. or(Opcode *o, Instr *i)
  582. {
  583. if (i->op == 31) {
  584. /* Rb,Rs,Ra */
  585. if (i->rs == 0 && i->ra == 0 && i->rb == 0)
  586. format("NOP", i, nil);
  587. else if (i->rs == i->rb)
  588. format("MOVW", i, "R%b,R%a");
  589. else
  590. and(o, i);
  591. } else
  592. and(o, i);
  593. }
  594. static void
  595. shifted(Opcode *o, Instr *i)
  596. {
  597. format(o->mnemonic, i, nil);
  598. bprint(i, "\t$%lux,", (ulong)i->uimm<<16);
  599. if (i->rs == i->ra)
  600. bprint(i, "R%d", i->ra);
  601. else
  602. bprint(i, "R%d,R%d", i->rs, i->ra);
  603. }
  604. static void
  605. neg(Opcode *o, Instr *i)
  606. {
  607. if (i->rd == i->ra)
  608. format(o->mnemonic, i, "R%d");
  609. else
  610. format(o->mnemonic, i, o->ken);
  611. }
  612. static char ir2[] = "R%a,R%d"; /* reverse of IBM order */
  613. static char ir3[] = "R%b,R%a,R%d";
  614. static char ir3r[] = "R%a,R%b,R%d";
  615. static char il3[] = "R%b,R%s,R%a";
  616. static char il2u[] = "%I,R%d,R%a";
  617. static char il3s[] = "$%k,R%s,R%a";
  618. static char il2[] = "R%s,R%a";
  619. static char icmp3[] = "R%a,R%b,%D";
  620. static char cr3op[] = "%b,%a,%d";
  621. static char ir2i[] = "%i,R%a,R%d";
  622. static char fp2[] = "F%b,F%d";
  623. static char fp3[] = "F%b,F%a,F%d";
  624. static char fp3c[] = "F%c,F%a,F%d";
  625. static char fp4[] = "F%a,F%c,F%b,F%d";
  626. static char fpcmp[] = "F%a,F%b,%D";
  627. static char ldop[] = "%l,R%d";
  628. static char stop[] = "R%d,%l";
  629. static char fldop[] = "%l,F%d";
  630. static char fstop[] = "F%d,%l";
  631. static char rldc[] = "R%b,R%s,$%E,R%a";
  632. static char rlim[] = "R%b,R%s,$%z,R%a";
  633. static char rlimi[] = "$%k,R%s,$%z,R%a";
  634. static char rldi[] = "$%e,R%s,$%E,R%a";
  635. #define OEM IBF(~0,22,30)
  636. #define FP4 IBF(~0,26,30)
  637. #define ALL (~0)
  638. #define RLDC 0xF
  639. #define RLDI 0xE
  640. /*
  641. notes:
  642. 10-26: crfD = rD>>2; rD&3 mbz
  643. also, L bit (bit 10) mbz or selects 64-bit operands
  644. */
  645. static Opcode opcodes[] = {
  646. {31, 266, OEM, "ADD%V%C", add, ir3},
  647. {31, 10, OEM, "ADDC%V%C", add, ir3},
  648. {31, 138, OEM, "ADDE%V%C", add, ir3},
  649. {14, 0, 0, "ADD", addi, ir2i},
  650. {12, 0, 0, "ADDC", addi, ir2i},
  651. {13, 0, 0, "ADDCCC", addi, ir2i},
  652. {15, 0, 0, "ADD", addis, 0},
  653. {31, 234, OEM, "ADDME%V%C", gencc, ir2},
  654. {31, 202, OEM, "ADDZE%V%C", gencc, ir2},
  655. {31, 28, ALL, "AND%C", and, il3},
  656. {31, 60, ALL, "ANDN%C", and, il3},
  657. {28, 0, 0, "ANDCC", andi, il2u},
  658. {29, 0, 0, "ANDCC", shifted, 0},
  659. {18, 0, 0, "B%L", gencc, "%j"},
  660. {16, 0, 0, "BC%L", branch, "%d,%a,%J"},
  661. {19, 528, ALL, "BC%L", branch, "%d,%a,(CTR)"},
  662. {19, 16, ALL, "BC%L", branch, "%d,%a,(LR)"},
  663. {31, 0, ALL, "CMP", 0, icmp3},
  664. {11, 0, 0, "CMP", 0, "R%a,%i,%D"},
  665. {31, 32, ALL, "CMPU", 0, icmp3},
  666. {10, 0, 0, "CMPU", 0, "R%a,%I,%D"},
  667. {31, 58, ALL, "CNTLZD%C", gencc, ir2}, /* 64 */
  668. {31, 26, ALL, "CNTLZ%W%C", gencc, ir2},
  669. {19, 257, ALL, "CRAND", gen, cr3op},
  670. {19, 129, ALL, "CRANDN", gen, cr3op},
  671. {19, 289, ALL, "CREQV", gen, cr3op},
  672. {19, 225, ALL, "CRNAND", gen, cr3op},
  673. {19, 33, ALL, "CRNOR", gen, cr3op},
  674. {19, 449, ALL, "CROR", gen, cr3op},
  675. {19, 417, ALL, "CRORN", gen, cr3op},
  676. {19, 193, ALL, "CRXOR", gen, cr3op},
  677. {31, 86, ALL, "DCBF", dcb, 0},
  678. {31, 470, ALL, "DCBI", dcb, 0},
  679. {31, 54, ALL, "DCBST", dcb, 0},
  680. {31, 278, ALL, "DCBT", dcb, 0},
  681. {31, 246, ALL, "DCBTST", dcb, 0},
  682. {31, 1014, ALL, "DCBZ", dcb, 0},
  683. {31, 454, ALL, "DCCCI", dcb, 0},
  684. {31, 966, ALL, "ICCCI", dcb, 0},
  685. {31, 489, OEM, "DIVD%V%C", qdiv, ir3}, /* 64 */
  686. {31, 457, OEM, "DIVDU%V%C", qdiv, ir3}, /* 64 */
  687. {31, 491, OEM, "DIVW%V%C", qdiv, ir3},
  688. {31, 459, OEM, "DIVWU%V%C", qdiv, ir3},
  689. {31, 310, ALL, "ECIWX", ldx, 0},
  690. {31, 438, ALL, "ECOWX", stx, 0},
  691. {31, 854, ALL, "EIEIO", gen, 0},
  692. {31, 284, ALL, "EQV%C", gencc, il3},
  693. {31, 954, ALL, "EXTSB%C", gencc, il2},
  694. {31, 922, ALL, "EXTSH%C", gencc, il2},
  695. {31, 986, ALL, "EXTSW%C", gencc, il2}, /* 64 */
  696. {63, 264, ALL, "FABS%C", gencc, fp2},
  697. {63, 21, ALL, "FADD%C", gencc, fp3},
  698. {59, 21, ALL, "FADDS%C", gencc, fp3},
  699. {63, 32, ALL, "FCMPO", gen, fpcmp},
  700. {63, 0, ALL, "FCMPU", gen, fpcmp},
  701. {63, 846, ALL, "FCFID%C", gencc, fp2}, /* 64 */
  702. {63, 814, ALL, "FCTID%C", gencc, fp2}, /* 64 */
  703. {63, 815, ALL, "FCTIDZ%C", gencc, fp2}, /* 64 */
  704. {63, 14, ALL, "FCTIW%C", gencc, fp2},
  705. {63, 15, ALL, "FCTIWZ%C", gencc, fp2},
  706. {63, 18, ALL, "FDIV%C", gencc, fp3},
  707. {59, 18, ALL, "FDIVS%C", gencc, fp3},
  708. {63, 29, FP4, "FMADD%C", gencc, fp4},
  709. {59, 29, FP4, "FMADDS%C", gencc, fp4},
  710. {63, 72, ALL, "FMOVD%C", gencc, fp2},
  711. {63, 28, FP4, "FMSUB%C", gencc, fp4},
  712. {59, 28, FP4, "FMSUBS%C", gencc, fp4},
  713. {63, 25, FP4, "FMUL%C", gencc, fp3c},
  714. {59, 25, FP4, "FMULS%C", gencc, fp3c},
  715. {63, 136, ALL, "FNABS%C", gencc, fp2},
  716. {63, 40, ALL, "FNEG%C", gencc, fp2},
  717. {63, 31, FP4, "FNMADD%C", gencc, fp4},
  718. {59, 31, FP4, "FNMADDS%C", gencc, fp4},
  719. {63, 30, FP4, "FNMSUB%C", gencc, fp4},
  720. {59, 30, FP4, "FNMSUBS%C", gencc, fp4},
  721. {59, 24, ALL, "FRES%C", gencc, fp2}, /* optional */
  722. {63, 12, ALL, "FRSP%C", gencc, fp2},
  723. {63, 26, ALL, "FRSQRTE%C", gencc, fp2}, /* optional */
  724. {63, 23, FP4, "FSEL%CC", gencc, fp4}, /* optional */
  725. {63, 22, ALL, "FSQRT%C", gencc, fp2}, /* optional */
  726. {59, 22, ALL, "FSQRTS%C", gencc, fp2}, /* optional */
  727. {63, 20, FP4, "FSUB%C", gencc, fp3},
  728. {59, 20, FP4, "FSUBS%C", gencc, fp3},
  729. {31, 982, ALL, "ICBI", dcb, 0}, /* optional */
  730. {19, 150, ALL, "ISYNC", gen, 0},
  731. {34, 0, 0, "MOVBZ", load, ldop},
  732. {35, 0, 0, "MOVBZU", load, ldop},
  733. {31, 119, ALL, "MOVBZU", ldx, 0},
  734. {31, 87, ALL, "MOVBZ", ldx, 0},
  735. {50, 0, 0, "FMOVD", fload, fldop},
  736. {51, 0, 0, "FMOVDU", fload, fldop},
  737. {31, 631, ALL, "FMOVDU", fldx, 0},
  738. {31, 599, ALL, "FMOVD", fldx, 0},
  739. {48, 0, 0, "FMOVS", load, fldop},
  740. {49, 0, 0, "FMOVSU", load, fldop},
  741. {31, 567, ALL, "FMOVSU", fldx, 0},
  742. {31, 535, ALL, "FMOVS", fldx, 0},
  743. {42, 0, 0, "MOVH", load, ldop},
  744. {43, 0, 0, "MOVHU", load, ldop},
  745. {31, 375, ALL, "MOVHU", ldx, 0},
  746. {31, 343, ALL, "MOVH", ldx, 0},
  747. {31, 790, ALL, "MOVHBR", ldx, 0},
  748. {40, 0, 0, "MOVHZ", load, ldop},
  749. {41, 0, 0, "MOVHZU", load, ldop},
  750. {31, 311, ALL, "MOVHZU", ldx, 0},
  751. {31, 279, ALL, "MOVHZ", ldx, 0},
  752. {46, 0, 0, "MOVMW", load, ldop},
  753. {31, 597, ALL, "LSW", gen, "(R%a),$%n,R%d"},
  754. {31, 533, ALL, "LSW", ldx, 0},
  755. {31, 20, ALL, "LWAR", ldx, 0},
  756. {31, 84, ALL, "LWARD", ldx, 0}, /* 64 */
  757. {58, 0, ALL, "MOVD", load, ldop}, /* 64 */
  758. {58, 1, ALL, "MOVDU", load, ldop}, /* 64 */
  759. {31, 53, ALL, "MOVDU", ldx, 0}, /* 64 */
  760. {31, 21, ALL, "MOVD", ldx, 0}, /* 64 */
  761. {31, 534, ALL, "MOVWBR", ldx, 0},
  762. {58, 2, ALL, "MOVW", load, ldop}, /* 64 (lwa) */
  763. {31, 373, ALL, "MOVWU", ldx, 0}, /* 64 */
  764. {31, 341, ALL, "MOVW", ldx, 0}, /* 64 */
  765. {32, 0, 0, "MOVW%Z", load, ldop},
  766. {33, 0, 0, "MOVW%ZU", load, ldop},
  767. {31, 55, ALL, "MOVW%ZU", ldx, 0},
  768. {31, 23, ALL, "MOVW%Z", ldx, 0},
  769. {19, 0, ALL, "MOVFL", gen, "%S,%D"},
  770. {63, 64, ALL, "MOVCRFS", gen, "%S,%D"},
  771. {31, 512, ALL, "MOVW", gen, "XER,%D"},
  772. {31, 19, ALL, "MOVW", gen, "CR,R%d"},
  773. {63, 583, ALL, "MOVW%C", gen, "FPSCR, F%d"}, /* mffs */
  774. {31, 83, ALL, "MOVW", gen, "MSR,R%d"},
  775. {31, 339, ALL, "MOVW", gen, "%P,R%d"},
  776. {31, 595, ALL, "MOVW", gen, "SEG(%a),R%d"},
  777. {31, 659, ALL, "MOVW", gen, "SEG(R%b),R%d"},
  778. {31, 323, ALL, "MOVW", gen, "DCR(%Q),R%d"},
  779. {31, 451, ALL, "MOVW", gen, "R%s,DCR(%Q)"},
  780. {31, 259, ALL, "MOVW", gen, "DCR(R%a),R%d"},
  781. {31, 387, ALL, "MOVW", gen, "R%s,DCR(R%a)"},
  782. {31, 144, ALL, "MOVFL", gen, "R%s,%m,CR"},
  783. {63, 70, ALL, "MTFSB0%C", gencc, "%D"},
  784. {63, 38, ALL, "MTFSB1%C", gencc, "%D"},
  785. {63, 711, ALL, "MOVFL%C", gencc, "F%b,%M,FPSCR"}, /* mtfsf */
  786. {63, 134, ALL, "MOVFL%C", gencc, "%K,%D"},
  787. {31, 146, ALL, "MOVW", gen, "R%s,MSR"},
  788. {31, 178, ALL, "MOVD", gen, "R%s,MSR"},
  789. {31, 467, ALL, "MOVW", gen, "R%s,%P"},
  790. {31, 210, ALL, "MOVW", gen, "R%s,SEG(%a)"},
  791. {31, 242, ALL, "MOVW", gen, "R%s,SEG(R%b)"},
  792. {31, 73, ALL, "MULHD%C", gencc, ir3},
  793. {31, 9, ALL, "MULHDU%C", gencc, ir3},
  794. {31, 233, OEM, "MULLD%V%C", gencc, ir3},
  795. {31, 75, ALL, "MULHW%C", gencc, ir3},
  796. {31, 11, ALL, "MULHWU%C", gencc, ir3},
  797. {31, 235, OEM, "MULLW%V%C", gencc, ir3},
  798. {7, 0, 0, "MULLW", qdiv, "%i,R%a,R%d"},
  799. {31, 476, ALL, "NAND%C", gencc, il3},
  800. {31, 104, OEM, "NEG%V%C", neg, ir2},
  801. {31, 124, ALL, "NOR%C", gencc, il3},
  802. {31, 444, ALL, "OR%C", or, il3},
  803. {31, 412, ALL, "ORN%C", or, il3},
  804. {24, 0, 0, "OR", and, "%I,R%d,R%a"},
  805. {25, 0, 0, "OR", shifted, 0},
  806. {19, 50, ALL, "RFI", gen, 0},
  807. {19, 51, ALL, "RFCI", gen, 0},
  808. {30, 8, RLDC, "RLDCL%C", gencc, rldc}, /* 64 */
  809. {30, 9, RLDC, "RLDCR%C", gencc, rldc}, /* 64 */
  810. {30, 0, RLDI, "RLDCL%C", gencc, rldi}, /* 64 */
  811. {30, 1<<1, RLDI, "RLDCR%C", gencc, rldi}, /* 64 */
  812. {30, 2<<1, RLDI, "RLDC%C", gencc, rldi}, /* 64 */
  813. {30, 3<<1, RLDI, "RLDMI%C", gencc, rldi}, /* 64 */
  814. {20, 0, 0, "RLWMI%C", gencc, rlimi},
  815. {21, 0, 0, "RLWNM%C", gencc, rlimi},
  816. {23, 0, 0, "RLWNM%C", gencc, rlim},
  817. {17, 1, ALL, "SYSCALL", gen, 0},
  818. {31, 27, ALL, "SLD%C", shift, il3}, /* 64 */
  819. {31, 24, ALL, "SLW%C", shift, il3},
  820. {31, 794, ALL, "SRAD%C", shift, il3}, /* 64 */
  821. {31, (413<<1)|0, ALL, "SRAD%C", shifti, il3s}, /* 64 */
  822. {31, (413<<1)|1, ALL, "SRAD%C", shifti, il3s}, /* 64 */
  823. {31, 792, ALL, "SRAW%C", shift, il3},
  824. {31, 824, ALL, "SRAW%C", shifti, il3s},
  825. {31, 539, ALL, "SRD%C", shift, il3}, /* 64 */
  826. {31, 536, ALL, "SRW%C", shift, il3},
  827. {38, 0, 0, "MOVB", store, stop},
  828. {39, 0, 0, "MOVBU", store, stop},
  829. {31, 247, ALL, "MOVBU", stx, 0},
  830. {31, 215, ALL, "MOVB", stx, 0},
  831. {54, 0, 0, "FMOVD", fstore, fstop},
  832. {55, 0, 0, "FMOVDU", fstore, fstop},
  833. {31, 759, ALL, "FMOVDU", fstx, 0},
  834. {31, 727, ALL, "FMOVD", fstx, 0},
  835. {52, 0, 0, "FMOVS", fstore, fstop},
  836. {53, 0, 0, "FMOVSU", fstore, fstop},
  837. {31, 695, ALL, "FMOVSU", fstx, 0},
  838. {31, 663, ALL, "FMOVS", fstx, 0},
  839. {44, 0, 0, "MOVH", store, stop},
  840. {31, 918, ALL, "MOVHBR", stx, 0},
  841. {45, 0, 0, "MOVHU", store, stop},
  842. {31, 439, ALL, "MOVHU", stx, 0},
  843. {31, 407, ALL, "MOVH", stx, 0},
  844. {47, 0, 0, "MOVMW", store, stop},
  845. {31, 725, ALL, "STSW", gen, "R%d,$%n,(R%a)"},
  846. {31, 661, ALL, "STSW", stx, 0},
  847. {36, 0, 0, "MOVW", store, stop},
  848. {31, 662, ALL, "MOVWBR", stx, 0},
  849. {31, 150, ALL, "STWCCC", stx, 0},
  850. {31, 214, ALL, "STDCCC", stx, 0}, /* 64 */
  851. {37, 0, 0, "MOVWU", store, stop},
  852. {31, 183, ALL, "MOVWU", stx, 0},
  853. {31, 151, ALL, "MOVW", stx, 0},
  854. {62, 0, 0, "MOVD%U", store, stop}, /* 64 */
  855. {31, 149, ALL, "MOVD", stx, 0,}, /* 64 */
  856. {31, 181, ALL, "MOVDU", stx, 0}, /* 64 */
  857. {31, 498, ALL, "SLBIA", gen, 0}, /* 64 */
  858. {31, 434, ALL, "SLBIE", gen, "R%b"}, /* 64 */
  859. {31, 466, ALL, "SLBIEX", gen, "R%b"}, /* 64 */
  860. {31, 915, ALL, "SLBMFEE", gen, "R%b,R%d"}, /* 64 */
  861. {31, 851, ALL, "SLBMFEV", gen, "R%b,R%d"}, /* 64 */
  862. {31, 402, ALL, "SLBMTE", gen, "R%s,R%b"}, /* 64 */
  863. {31, 40, OEM, "SUB%V%C", sub, ir3},
  864. {31, 8, OEM, "SUBC%V%C", sub, ir3},
  865. {31, 136, OEM, "SUBE%V%C", sub, ir3},
  866. {8, 0, 0, "SUBC", gen, "R%a,%i,R%d"},
  867. {31, 232, OEM, "SUBME%V%C", sub, ir2},
  868. {31, 200, OEM, "SUBZE%V%C", sub, ir2},
  869. {31, 598, ALL, "SYNC", gen, 0}, /* TO DO: there's a parameter buried in there */
  870. {2, 0, 0, "TD", gen, "%d,R%a,%i"}, /* 64 */
  871. {31, 370, ALL, "TLBIA", gen, 0}, /* optional */
  872. {31, 306, ALL, "TLBIE", gen, "R%b"}, /* optional */
  873. {31, 274, ALL, "TLBIEL", gen, "R%b"}, /* optional */
  874. {31, 1010, ALL, "TLBLI", gen, "R%b"}, /* optional */
  875. {31, 978, ALL, "TLBLD", gen, "R%b"}, /* optional */
  876. {31, 566, ALL, "TLBSYNC", gen, 0}, /* optional */
  877. {31, 68, ALL, "TD", gen, "%d,R%a,R%b"}, /* 64 */
  878. {31, 4, ALL, "TW", gen, "%d,R%a,R%b"},
  879. {3, 0, 0, "TW", gen, "%d,R%a,%i"},
  880. {31, 316, ALL, "XOR", and, il3},
  881. {26, 0, 0, "XOR", and, il2u},
  882. {27, 0, 0, "XOR", shifted, 0},
  883. {0},
  884. };
  885. typedef struct Spr Spr;
  886. struct Spr {
  887. int n;
  888. char *name;
  889. };
  890. static Spr sprname[] = {
  891. {0, "MQ"},
  892. {1, "XER"},
  893. {268, "TBL"},
  894. {269, "TBU"},
  895. {8, "LR"},
  896. {9, "CTR"},
  897. {528, "IBAT0U"},
  898. {529, "IBAT0L"},
  899. {530, "IBAT1U"},
  900. {531, "IBAT1L"},
  901. {532, "IBAT2U"},
  902. {533, "IBAT2L"},
  903. {534, "IBAT3U"},
  904. {535, "IBAT3L"},
  905. {536, "DBAT0U"},
  906. {537, "DBAT0L"},
  907. {538, "DBAT1U"},
  908. {539, "DBAT1L"},
  909. {540, "DBAT2U"},
  910. {541, "DBAT2L"},
  911. {542, "DBAT3U"},
  912. {543, "DBAT3L"},
  913. {25, "SDR1"},
  914. {19, "DAR"},
  915. {272, "SPRG0"},
  916. {273, "SPRG1"},
  917. {274, "SPRG2"},
  918. {275, "SPRG3"},
  919. {18, "DSISR"},
  920. {26, "SRR0"},
  921. {27, "SRR1"},
  922. {284, "TBLW"},
  923. {285, "TBUW"},
  924. {22, "DEC"},
  925. {282, "EAR"},
  926. {1008, "HID0"},
  927. {1009, "HID1"},
  928. {976, "DMISS"},
  929. {977, "DCMP"},
  930. {978, "HASH1"},
  931. {979, "HASH2"},
  932. {980, "IMISS"},
  933. {981, "ICMP"},
  934. {982, "RPA"},
  935. {1010, "IABR"},
  936. {1013, "DABR"},
  937. {0,0},
  938. };
  939. static int
  940. shmask(uvlong *m)
  941. {
  942. int i;
  943. for(i=0; i<63; i++)
  944. if(*m & ((uvlong)1<<i))
  945. break;
  946. if(i > 63)
  947. return 0;
  948. if(*m & ~((uvlong)1<<i)){ /* more than one bit: do multiples of bytes */
  949. i = (i/8)*8;
  950. if(i == 0)
  951. return 0;
  952. }
  953. *m >>= i;
  954. return i;
  955. }
  956. static void
  957. format(char *mnemonic, Instr *i, char *f)
  958. {
  959. int n, s;
  960. ulong mask;
  961. uvlong vmask;
  962. if (mnemonic)
  963. format(0, i, mnemonic);
  964. if (f == 0)
  965. return;
  966. if (mnemonic)
  967. bprint(i, "\t");
  968. for ( ; *f; f++) {
  969. if (*f != '%') {
  970. bprint(i, "%c", *f);
  971. continue;
  972. }
  973. switch (*++f) {
  974. case 'a':
  975. bprint(i, "%d", i->ra);
  976. break;
  977. case 'b':
  978. bprint(i, "%d", i->rb);
  979. break;
  980. case 'c':
  981. bprint(i, "%d", i->frc);
  982. break;
  983. case 'd':
  984. case 's':
  985. bprint(i, "%d", i->rd);
  986. break;
  987. case 'C':
  988. if(i->rc)
  989. bprint(i, "CC");
  990. break;
  991. case 'D':
  992. if(i->rd & 3)
  993. bprint(i, "CR(INVAL:%d)", i->rd);
  994. else if(i->op == 63)
  995. bprint(i, "FPSCR(%d)", i->crfd);
  996. else
  997. bprint(i, "CR(%d)", i->crfd);
  998. break;
  999. case 'e':
  1000. bprint(i, "%d", i->xsh);
  1001. break;
  1002. case 'E':
  1003. switch(IBF(i->w0,27,30)){ /* low bit is top bit of shift in rldiX cases */
  1004. case 8: i->mb = i->xmbe; i->me = 63; break; /* rldcl */
  1005. case 9: i->mb = 0; i->me = i->xmbe; break; /* rldcr */
  1006. case 4: case 5:
  1007. i->mb = i->xmbe; i->me = 63-i->xsh; break; /* rldic */
  1008. case 0: case 1:
  1009. i->mb = i->xmbe; i->me = 63; break; /* rldicl */
  1010. case 2: case 3:
  1011. i->mb = 0; i->me = i->xmbe; break; /* rldicr */
  1012. case 6: case 7:
  1013. i->mb = i->xmbe; i->me = 63-i->xsh; break; /* rldimi */
  1014. }
  1015. vmask = (~(uvlong)0>>i->mb) & (~(uvlong)0<<(63-i->me));
  1016. s = shmask(&vmask);
  1017. if(s)
  1018. bprint(i, "(%llux<<%d)", vmask, s);
  1019. else
  1020. bprint(i, "%llux", vmask);
  1021. break;
  1022. case 'i':
  1023. bprint(i, "$%d", i->simm);
  1024. break;
  1025. case 'I':
  1026. bprint(i, "$%ux", i->uimm);
  1027. break;
  1028. case 'j':
  1029. if(i->aa)
  1030. pglobal(i, i->li, 1, "(SB)");
  1031. else
  1032. pglobal(i, i->addr+i->li, 1, "");
  1033. break;
  1034. case 'J':
  1035. if(i->aa)
  1036. pglobal(i, i->bd, 1, "(SB)");
  1037. else
  1038. pglobal(i, i->addr+i->bd, 1, "");
  1039. break;
  1040. case 'k':
  1041. bprint(i, "%d", i->sh);
  1042. break;
  1043. case 'K':
  1044. bprint(i, "$%x", i->imm);
  1045. break;
  1046. case 'L':
  1047. if(i->lk)
  1048. bprint(i, "L");
  1049. break;
  1050. case 'l':
  1051. if(i->simm < 0)
  1052. bprint(i, "-%x(R%d)", -i->simm, i->ra);
  1053. else
  1054. bprint(i, "%x(R%d)", i->simm, i->ra);
  1055. break;
  1056. case 'm':
  1057. bprint(i, "%ux", i->crm);
  1058. break;
  1059. case 'M':
  1060. bprint(i, "%ux", i->fm);
  1061. break;
  1062. case 'n':
  1063. bprint(i, "%d", i->nb==0? 32: i->nb); /* eg, pg 10-103 */
  1064. break;
  1065. case 'P':
  1066. n = ((i->spr&0x1f)<<5)|((i->spr>>5)&0x1f);
  1067. for(s=0; sprname[s].name; s++)
  1068. if(sprname[s].n == n)
  1069. break;
  1070. if(sprname[s].name) {
  1071. if(s < 10)
  1072. bprint(i, sprname[s].name);
  1073. else
  1074. bprint(i, "SPR(%s)", sprname[s].name);
  1075. } else
  1076. bprint(i, "SPR(%d)", n);
  1077. break;
  1078. case 'Q':
  1079. n = ((i->spr&0x1f)<<5)|((i->spr>>5)&0x1f);
  1080. bprint(i, "%d", n);
  1081. break;
  1082. case 'S':
  1083. if(i->ra & 3)
  1084. bprint(i, "CR(INVAL:%d)", i->ra);
  1085. else if(i->op == 63)
  1086. bprint(i, "FPSCR(%d)", i->crfs);
  1087. else
  1088. bprint(i, "CR(%d)", i->crfs);
  1089. break;
  1090. case 'U':
  1091. if(i->rc)
  1092. bprint(i, "U");
  1093. break;
  1094. case 'V':
  1095. if(i->oe)
  1096. bprint(i, "V");
  1097. break;
  1098. case 'w':
  1099. bprint(i, "[%lux]", i->w0);
  1100. break;
  1101. case 'W':
  1102. if(i->m64)
  1103. bprint(i, "W");
  1104. break;
  1105. case 'Z':
  1106. if(i->m64)
  1107. bprint(i, "Z");
  1108. break;
  1109. case 'z':
  1110. if(i->mb <= i->me)
  1111. mask = ((ulong)~0L>>i->mb) & (~0L<<(31-i->me));
  1112. else
  1113. mask = ~(((ulong)~0L>>(i->me+1)) & (~0L<<(31-(i->mb-1))));
  1114. bprint(i, "%lux", mask);
  1115. break;
  1116. case '\0':
  1117. bprint(i, "%%");
  1118. return;
  1119. default:
  1120. bprint(i, "%%%c", *f);
  1121. break;
  1122. }
  1123. }
  1124. }
  1125. static int
  1126. printins(Map *map, uvlong pc, char *buf, int n)
  1127. {
  1128. Instr i;
  1129. Opcode *o;
  1130. mymap = map;
  1131. memset(&i, 0, sizeof(i));
  1132. i.curr = buf;
  1133. i.end = buf+n-1;
  1134. if(mkinstr(pc, &i) < 0)
  1135. return -1;
  1136. for(o = opcodes; o->mnemonic != 0; o++)
  1137. if(i.op == o->op && (i.xo & o->xomask) == o->xo) {
  1138. if (o->f)
  1139. (*o->f)(o, &i);
  1140. else
  1141. format(o->mnemonic, &i, o->ken);
  1142. return i.size*4;
  1143. }
  1144. bprint(&i, "unknown %lux", i.w0);
  1145. return i.size*4;
  1146. }
  1147. static int
  1148. powerinst(Map *map, uvlong pc, char modifier, char *buf, int n)
  1149. {
  1150. USED(modifier);
  1151. return printins(map, pc, buf, n);
  1152. }
  1153. static int
  1154. powerdas(Map *map, uvlong pc, char *buf, int n)
  1155. {
  1156. Instr instr;
  1157. mymap = map;
  1158. memset(&instr, 0, sizeof(instr));
  1159. instr.curr = buf;
  1160. instr.end = buf+n-1;
  1161. if (mkinstr(pc, &instr) < 0)
  1162. return -1;
  1163. if (instr.end-instr.curr > 8)
  1164. instr.curr = _hexify(instr.curr, instr.w0, 7);
  1165. if (instr.end-instr.curr > 9 && instr.size == 2) {
  1166. *instr.curr++ = ' ';
  1167. instr.curr = _hexify(instr.curr, instr.w1, 7);
  1168. }
  1169. *instr.curr = 0;
  1170. return instr.size*4;
  1171. }
  1172. static int
  1173. powerinstlen(Map *map, uvlong pc)
  1174. {
  1175. Instr i;
  1176. mymap = map;
  1177. if (mkinstr(pc, &i) < 0)
  1178. return -1;
  1179. return i.size*4;
  1180. }
  1181. static int
  1182. powerfoll(Map *map, uvlong pc, Rgetter rget, uvlong *foll)
  1183. {
  1184. char *reg;
  1185. Instr i;
  1186. mymap = map;
  1187. if (mkinstr(pc, &i) < 0)
  1188. return -1;
  1189. foll[0] = pc+4;
  1190. foll[1] = pc+4;
  1191. switch(i.op) {
  1192. default:
  1193. return 1;
  1194. case 18: /* branch */
  1195. foll[0] = i.li;
  1196. if(!i.aa)
  1197. foll[0] += pc;
  1198. break;
  1199. case 16: /* conditional branch */
  1200. foll[0] = i.bd;
  1201. if(!i.aa)
  1202. foll[0] += pc;
  1203. break;
  1204. case 19: /* conditional branch to register */
  1205. if(i.xo == 528)
  1206. reg = "CTR";
  1207. else if(i.xo == 16)
  1208. reg = "LR";
  1209. else
  1210. return 1; /* not a branch */
  1211. foll[0] = (*rget)(map, reg);
  1212. break;
  1213. }
  1214. if(i.lk)
  1215. return 2;
  1216. return 1;
  1217. }