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