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