qdb.c 27 KB

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