qdb.c 27 KB

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