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%d,R%a"; 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, 259, ALL, "MOVW", gen, "DCR(R%a),R%d"}, 861 {31, 387, ALL, "MOVW", gen, "R%s,DCR(R%a)"}, 862 {31, 144, ALL, "MOVFL", gen, "R%s,%m,CR"}, 863 {63, 70, ALL, "MTFSB0%C", gencc, "%D"}, 864 {63, 38, ALL, "MTFSB1%C", gencc, "%D"}, 865 {63, 711, ALL, "MOVFL%C", gencc, "F%b,%M,FPSCR"}, /* mtfsf */ 866 {63, 134, ALL, "MOVFL%C", gencc, "%K,%D"}, 867 {31, 146, ALL, "MOVW", gen, "R%s,MSR"}, 868 {31, 178, ALL, "MOVD", gen, "R%s,MSR"}, 869 {31, 467, ALL, "MOVW", gen, "R%s,%P"}, 870 {31, 210, ALL, "MOVW", gen, "R%s,SEG(%a)"}, 871 {31, 242, ALL, "MOVW", gen, "R%s,SEG(R%b)"}, 872 873 {31, 73, ALL, "MULHD%C", gencc, ir3}, 874 {31, 9, ALL, "MULHDU%C", gencc, ir3}, 875 {31, 233, OEM, "MULLD%V%C", gencc, ir3}, 876 877 {31, 75, ALL, "MULHW%C", gencc, ir3}, 878 {31, 11, ALL, "MULHWU%C", gencc, ir3}, 879 {31, 235, OEM, "MULLW%V%C", gencc, ir3}, 880 881 {7, 0, 0, "MULLW", qmuldiv, "%i,R%a,R%d"}, 882 883 {31, 476, ALL, "NAND%C", gencc, il3}, 884 {31, 104, OEM, "NEG%V%C", neg, ir2}, 885 {31, 124, ALL, "NOR%C", gencc, il3}, 886 {31, 444, ALL, "OR%C", or, il3}, 887 {31, 412, ALL, "ORN%C", or, il3}, 888 {24, 0, 0, "OR", and, "%I,R%d,R%a"}, 889 {25, 0, 0, "OR", shifted, 0}, 890 891 {19, 50, ALL, "RFI", gen, 0}, 892 {19, 51, ALL, "RFCI", gen, 0}, 893 894 {30, 8, RLDC, "RLDCL%C", gencc, rldc}, /* 64 */ 895 {30, 9, RLDC, "RLDCR%C", gencc, rldc}, /* 64 */ 896 {30, 0, RLDI, "RLDCL%C", gencc, rldi}, /* 64 */ 897 {30, 1<<1, RLDI, "RLDCR%C", gencc, rldi}, /* 64 */ 898 {30, 2<<1, RLDI, "RLDC%C", gencc, rldi}, /* 64 */ 899 {30, 3<<1, RLDI, "RLDMI%C", gencc, rldi}, /* 64 */ 900 901 {20, 0, 0, "RLWMI%C", gencc, rlimi}, 902 {21, 0, 0, "RLWNM%C", gencc, rlimi}, 903 {23, 0, 0, "RLWNM%C", gencc, rlim}, 904 905 {17, 1, ALL, "SYSCALL", gen, 0}, 906 907 {31, 27, ALL, "SLD%C", shift, il3}, /* 64 */ 908 {31, 24, ALL, "SLW%C", shift, il3}, 909 910 {31, 794, ALL, "SRAD%C", shift, il3}, /* 64 */ 911 {31, (413<<1)|0, ALL, "SRAD%C", shifti, il3s}, /* 64 */ 912 {31, (413<<1)|1, ALL, "SRAD%C", shifti, il3s}, /* 64 */ 913 {31, 792, ALL, "SRAW%C", shift, il3}, 914 {31, 824, ALL, "SRAW%C", shifti, il3s}, 915 916 {31, 539, ALL, "SRD%C", shift, il3}, /* 64 */ 917 {31, 536, ALL, "SRW%C", shift, il3}, 918 919 {38, 0, 0, "MOVB", store, stop}, 920 {39, 0, 0, "MOVBU", store, stop}, 921 {31, 247, ALL, "MOVBU", stx, 0}, 922 {31, 215, ALL, "MOVB", stx, 0}, 923 {54, 0, 0, "FMOVD", fstore, fstop}, 924 {55, 0, 0, "FMOVDU", fstore, fstop}, 925 {31, 759, ALL, "FMOVDU", fstx, 0}, 926 {31, 727, ALL, "FMOVD", fstx, 0}, 927 {52, 0, 0, "FMOVS", fstore, fstop}, 928 {53, 0, 0, "FMOVSU", fstore, fstop}, 929 {31, 695, ALL, "FMOVSU", fstx, 0}, 930 {31, 663, ALL, "FMOVS", fstx, 0}, 931 {44, 0, 0, "MOVH", store, stop}, 932 {31, 918, ALL, "MOVHBR", stx, 0}, 933 {45, 0, 0, "MOVHU", store, stop}, 934 {31, 439, ALL, "MOVHU", stx, 0}, 935 {31, 407, ALL, "MOVH", stx, 0}, 936 {47, 0, 0, "MOVMW", store, stop}, 937 {31, 725, ALL, "STSW", gen, "R%d,$%n,(R%a)"}, 938 {31, 661, ALL, "STSW", stx, 0}, 939 {36, 0, 0, "MOVW", store, stop}, 940 {31, 662, ALL, "MOVWBR", stx, 0}, 941 {31, 150, ALL, "STWCCC", stx, 0}, 942 {31, 214, ALL, "STDCCC", stx, 0}, /* 64 */ 943 {37, 0, 0, "MOVWU", store, stop}, 944 {31, 183, ALL, "MOVWU", stx, 0}, 945 {31, 151, ALL, "MOVW", stx, 0}, 946 947 {62, 0, 0, "MOVD%U", store, stop}, /* 64 */ 948 {31, 149, ALL, "MOVD", stx, 0,}, /* 64 */ 949 {31, 181, ALL, "MOVDU", stx, 0}, /* 64 */ 950 951 {31, 498, ALL, "SLBIA", gen, 0}, /* 64 */ 952 {31, 434, ALL, "SLBIE", gen, "R%b"}, /* 64 */ 953 {31, 466, ALL, "SLBIEX", gen, "R%b"}, /* 64 */ 954 {31, 915, ALL, "SLBMFEE", gen, "R%b,R%d"}, /* 64 */ 955 {31, 851, ALL, "SLBMFEV", gen, "R%b,R%d"}, /* 64 */ 956 {31, 402, ALL, "SLBMTE", gen, "R%s,R%b"}, /* 64 */ 957 958 {31, 40, OEM, "SUB%V%C", sub, ir3}, 959 {31, 8, OEM, "SUBC%V%C", sub, ir3}, 960 {31, 136, OEM, "SUBE%V%C", sub, ir3}, 961 {8, 0, 0, "SUBC", gen, "R%a,%i,R%d"}, 962 {31, 232, OEM, "SUBME%V%C", sub, ir2}, 963 {31, 200, OEM, "SUBZE%V%C", sub, ir2}, 964 965 {31, 598, ALL, "SYNC", gen, 0}, /* TO DO: there's a parameter buried in there */ 966 {2, 0, 0, "TD", gen, "%d,R%a,%i"}, /* 64 */ 967 {31, 370, ALL, "TLBIA", gen, 0}, /* optional */ 968 {31, 306, ALL, "TLBIE", gen, "R%b"}, /* optional */ 969 {31, 274, ALL, "TLBIEL", gen, "R%b"}, /* optional */ 970 {31, 1010, ALL, "TLBLI", gen, "R%b"}, /* optional */ 971 {31, 978, ALL, "TLBLD", gen, "R%b"}, /* optional */ 972 {31, 566, ALL, "TLBSYNC", gen, 0}, /* optional */ 973 {31, 68, ALL, "TD", gen, "%d,R%a,R%b"}, /* 64 */ 974 {31, 4, ALL, "TW", gen, "%d,R%a,R%b"}, 975 {3, 0, 0, "TW", gen, "%d,R%a,%i"}, 976 977 {31, 316, ALL, "XOR", and, il3}, 978 {26, 0, 0, "XOR", and, il2u}, 979 {27, 0, 0, "XOR", shifted, 0}, 980 981 {0}, 982 }; 983 984 typedef struct Spr Spr; 985 struct Spr { 986 int n; 987 char *name; 988 }; 989 990 static Spr sprname[] = { 991 {0, "MQ"}, 992 {1, "XER"}, 993 {268, "TBL"}, 994 {269, "TBU"}, 995 {8, "LR"}, 996 {9, "CTR"}, 997 {528, "IBAT0U"}, 998 {529, "IBAT0L"}, 999 {530, "IBAT1U"}, 1000 {531, "IBAT1L"}, 1001 {532, "IBAT2U"}, 1002 {533, "IBAT2L"}, 1003 {534, "IBAT3U"}, 1004 {535, "IBAT3L"}, 1005 {536, "DBAT0U"}, 1006 {537, "DBAT0L"}, 1007 {538, "DBAT1U"}, 1008 {539, "DBAT1L"}, 1009 {540, "DBAT2U"}, 1010 {541, "DBAT2L"}, 1011 {542, "DBAT3U"}, 1012 {543, "DBAT3L"}, 1013 {25, "SDR1"}, 1014 {19, "DAR"}, 1015 {272, "SPRG0"}, 1016 {273, "SPRG1"}, 1017 {274, "SPRG2"}, 1018 {275, "SPRG3"}, 1019 {18, "DSISR"}, 1020 {26, "SRR0"}, 1021 {27, "SRR1"}, 1022 {284, "TBLW"}, 1023 {285, "TBUW"}, 1024 {22, "DEC"}, 1025 {282, "EAR"}, 1026 {1008, "HID0"}, 1027 {1009, "HID1"}, 1028 {976, "DMISS"}, 1029 {977, "DCMP"}, 1030 {978, "HASH1"}, 1031 {979, "HASH2"}, 1032 {980, "IMISS"}, 1033 {981, "ICMP"}, 1034 {982, "RPA"}, 1035 {1010, "IABR"}, 1036 {1013, "DABR"}, 1037 {0,0}, 1038 }; 1039 1040 static int 1041 shmask(uvlong *m) 1042 { 1043 int i; 1044 1045 for(i=0; i<63; i++) 1046 if(*m & ((uvlong)1<<i)) 1047 break; 1048 if(i > 63) 1049 return 0; 1050 if(*m & ~((uvlong)1<<i)){ /* more than one bit: do multiples of bytes */ 1051 i = (i/8)*8; 1052 if(i == 0) 1053 return 0; 1054 } 1055 *m >>= i; 1056 return i; 1057 } 1058 1059 static void 1060 format(char *mnemonic, Instr *i, char *f) 1061 { 1062 int n, s; 1063 ulong mask; 1064 uvlong vmask; 1065 1066 if (mnemonic) 1067 format(0, i, mnemonic); 1068 if (f == 0) 1069 return; 1070 if (mnemonic) 1071 bprint(i, "\t"); 1072 for ( ; *f; f++) { 1073 if (*f != '%') { 1074 bprint(i, "%c", *f); 1075 continue; 1076 } 1077 switch (*++f) { 1078 1079 case 'a': 1080 bprint(i, "%d", i->ra); 1081 break; 1082 1083 case 'b': 1084 bprint(i, "%d", i->rb); 1085 break; 1086 1087 case 'c': 1088 bprint(i, "%d", i->frc); 1089 break; 1090 1091 case 'd': 1092 case 's': 1093 bprint(i, "%d", i->rd); 1094 break; 1095 1096 case 'C': 1097 if(i->rc) 1098 bprint(i, "CC"); 1099 break; 1100 1101 case 'D': 1102 if(i->rd & 3) 1103 bprint(i, "CR(INVAL:%d)", i->rd); 1104 else if(i->op == 63) 1105 bprint(i, "FPSCR(%d)", i->crfd); 1106 else 1107 bprint(i, "CR(%d)", i->crfd); 1108 break; 1109 1110 case 'e': 1111 bprint(i, "%d", i->xsh); 1112 break; 1113 1114 case 'E': 1115 switch(IBF(i->w0,27,30)){ /* low bit is top bit of shift in rldiX cases */ 1116 case 8: i->mb = i->xmbe; i->me = 63; break; /* rldcl */ 1117 case 9: i->mb = 0; i->me = i->xmbe; break; /* rldcr */ 1118 case 4: case 5: 1119 i->mb = i->xmbe; i->me = 63-i->xsh; break; /* rldic */ 1120 case 0: case 1: 1121 i->mb = i->xmbe; i->me = 63; break; /* rldicl */ 1122 case 2: case 3: 1123 i->mb = 0; i->me = i->xmbe; break; /* rldicr */ 1124 case 6: case 7: 1125 i->mb = i->xmbe; i->me = 63-i->xsh; break; /* rldimi */ 1126 } 1127 vmask = (~(uvlong)0>>i->mb) & (~(uvlong)0<<(63-i->me)); 1128 s = shmask(&vmask); 1129 if(s) 1130 bprint(i, "(%llux<<%d)", vmask, s); 1131 else 1132 bprint(i, "%llux", vmask); 1133 break; 1134 1135 case 'i': 1136 bprint(i, "$%d", i->simm); 1137 break; 1138 1139 case 'I': 1140 bprint(i, "$%ux", i->uimm); 1141 break; 1142 1143 case 'j': 1144 if(i->aa) 1145 pglobal(i, i->li, 1, "(SB)"); 1146 else 1147 pglobal(i, i->addr+i->li, 1, ""); 1148 break; 1149 1150 case 'J': 1151 if(i->aa) 1152 pglobal(i, i->bd, 1, "(SB)"); 1153 else 1154 pglobal(i, i->addr+i->bd, 1, ""); 1155 break; 1156 1157 case 'k': 1158 bprint(i, "%d", i->sh); 1159 break; 1160 1161 case 'K': 1162 bprint(i, "$%x", i->imm); 1163 break; 1164 1165 case 'L': 1166 if(i->lk) 1167 bprint(i, "L"); 1168 break; 1169 1170 case 'l': 1171 if(i->simm < 0) 1172 bprint(i, "-%x(R%d)", -i->simm, i->ra); 1173 else 1174 bprint(i, "%x(R%d)", i->simm, i->ra); 1175 break; 1176 1177 case 'm': 1178 bprint(i, "%ux", i->crm); 1179 break; 1180 1181 case 'M': 1182 bprint(i, "%ux", i->fm); 1183 break; 1184 1185 case 'n': 1186 bprint(i, "%d", i->nb==0? 32: i->nb); /* eg, pg 10-103 */ 1187 break; 1188 1189 case 'P': 1190 n = ((i->spr&0x1f)<<5)|((i->spr>>5)&0x1f); 1191 for(s=0; sprname[s].name; s++) 1192 if(sprname[s].n == n) 1193 break; 1194 if(sprname[s].name) { 1195 if(s < 10) 1196 bprint(i, sprname[s].name); 1197 else 1198 bprint(i, "SPR(%s)", sprname[s].name); 1199 } else 1200 bprint(i, "SPR(%d)", n); 1201 break; 1202 1203 case 'Q': 1204 n = ((i->spr&0x1f)<<5)|((i->spr>>5)&0x1f); 1205 bprint(i, "%d", n); 1206 break; 1207 1208 case 'S': 1209 if(i->ra & 3) 1210 bprint(i, "CR(INVAL:%d)", i->ra); 1211 else if(i->op == 63) 1212 bprint(i, "FPSCR(%d)", i->crfs); 1213 else 1214 bprint(i, "CR(%d)", i->crfs); 1215 break; 1216 1217 case 'U': 1218 if(i->rc) 1219 bprint(i, "U"); 1220 break; 1221 1222 case 'V': 1223 if(i->oe) 1224 bprint(i, "V"); 1225 break; 1226 1227 case 'w': 1228 bprint(i, "[%lux]", i->w0); 1229 break; 1230 1231 case 'W': 1232 if(i->m64) 1233 bprint(i, "W"); 1234 break; 1235 1236 case 'Z': 1237 if(i->m64) 1238 bprint(i, "Z"); 1239 break; 1240 1241 case 'z': 1242 if(i->mb <= i->me) 1243 mask = ((ulong)~0L>>i->mb) & (~0L<<(31-i->me)); 1244 else 1245 mask = ~(((ulong)~0L>>(i->me+1)) & (~0L<<(31-(i->mb-1)))); 1246 bprint(i, "%lux", mask); 1247 break; 1248 1249 case '\0': 1250 bprint(i, "%%"); 1251 return; 1252 1253 default: 1254 bprint(i, "%%%c", *f); 1255 break; 1256 } 1257 } 1258 } 1259 1260 static int 1261 printins(Map *map, uvlong pc, char *buf, int n) 1262 { 1263 Instr i; 1264 Opcode *o; 1265 1266 mymap = map; 1267 memset(&i, 0, sizeof(i)); 1268 i.curr = buf; 1269 i.end = buf+n-1; 1270 if(mkinstr(pc, &i) < 0) 1271 return -1; 1272 for(o = opcodes; o->mnemonic != 0; o++) 1273 if(i.op == o->op && (i.xo & o->xomask) == o->xo) { 1274 if (o->f) 1275 (*o->f)(o, &i); 1276 else 1277 format(o->mnemonic, &i, o->ken); 1278 return i.size*4; 1279 } 1280 bprint(&i, "unknown %lux", i.w0); 1281 return i.size*4; 1282 } 1283 1284 static int 1285 powerinst(Map *map, uvlong pc, char modifier, char *buf, int n) 1286 { 1287 USED(modifier); 1288 return printins(map, pc, buf, n); 1289 } 1290 1291 static int 1292 powerdas(Map *map, uvlong pc, char *buf, int n) 1293 { 1294 Instr instr; 1295 1296 mymap = map; 1297 memset(&instr, 0, sizeof(instr)); 1298 instr.curr = buf; 1299 instr.end = buf+n-1; 1300 if (mkinstr(pc, &instr) < 0) 1301 return -1; 1302 if (instr.end-instr.curr > 8) 1303 instr.curr = _hexify(instr.curr, instr.w0, 7); 1304 if (instr.end-instr.curr > 9 && instr.size == 2) { 1305 *instr.curr++ = ' '; 1306 instr.curr = _hexify(instr.curr, instr.w1, 7); 1307 } 1308 *instr.curr = 0; 1309 return instr.size*4; 1310 } 1311 1312 static int 1313 powerinstlen(Map *map, uvlong pc) 1314 { 1315 Instr i; 1316 1317 mymap = map; 1318 if (mkinstr(pc, &i) < 0) 1319 return -1; 1320 return i.size*4; 1321 } 1322 1323 static int 1324 powerfoll(Map *map, uvlong pc, Rgetter rget, uvlong *foll) 1325 { 1326 char *reg; 1327 Instr i; 1328 1329 mymap = map; 1330 if (mkinstr(pc, &i) < 0) 1331 return -1; 1332 foll[0] = pc+4; 1333 foll[1] = pc+4; 1334 switch(i.op) { 1335 default: 1336 return 1; 1337 1338 case 18: /* branch */ 1339 foll[0] = i.li; 1340 if(!i.aa) 1341 foll[0] += pc; 1342 break; 1343 1344 case 16: /* conditional branch */ 1345 foll[0] = i.bd; 1346 if(!i.aa) 1347 foll[0] += pc; 1348 break; 1349 1350 case 19: /* conditional branch to register */ 1351 if(i.xo == 528) 1352 reg = "CTR"; 1353 else if(i.xo == 16) 1354 reg = "LR"; 1355 else 1356 return 1; /* not a branch */ 1357 foll[0] = (*rget)(map, reg); 1358 break; 1359 } 1360 if(i.lk) 1361 return 2; 1362 return 1; 1363 } 1364