📄 dis_ppc.c
字号:
/* Power PC (403-GA) disassembler. * * General notice: * This code is part of a boot-monitor package developed as a generic base * platform for embedded system designs. As such, it is likely to be * distributed to various projects beyond the control of the original * author. Please notify the author of any enhancements made or bugs found * so that all may benefit from the changes. In addition, notification back * to the author will allow the new user to pick up changes that may have * been made by other users after this version of the code was distributed. * * Note1: the majority of this code was edited with 4-space tabs. * Note2: as more and more contributions are accepted, the term "author" * is becoming a mis-representation of credit. * * Original author: Ed Sutter * Email: esutter@lucent.com */#include "config.h"#include "genlib.h"#include "stddefs.h"#if INCLUDE_DISASSEMBLER#ifndef USE_SPRDCR_NAMES#define USE_SPRDCR_NAMES 0#endifvoid prdata();/* Instruction fields taken from chapter 10: */#define AA 0x00000002#define BA 0x001F0000#define BB 0x0000F800#define BD 0x0000FFFC#define BD_NEGATIVE 0x00008000#define BF 0x03800000#define BFA 0x001C0000#define BI 0x001F0000#define BO 0x03E00000#define BO_0 0x02000000#define BO_1 0x01000000#define BO_2 0x00800000#define BO_3 0x00400000#define BO_4 0x00200000#define BT 0x03E00000#define D 0x0000FFFF#define DCRN 0x001FF800#define FXM 0x000FF000#define IM 0x0000FFFF#define LI 0x03FFFFFC#define LI_NEGATIVE 0x02000000#define LK 0x00000001#define MB 0x000007C0#define ME 0x0000003E#define NB 0x0000F800#define OPCD 0xFC000000#define OE 0x00000400#define RA 0x001F0000#define RB 0x0000F800#define RC 0x00000001#define RSRT 0x03E00000#define SH 0x0000F800#define SPRF 0x001FF800#define TO 0x03E00000#define XO_OE 0x000007FE#define XO_NOOE 0x000003FE#define XO_SC 0x00000002#define XO_STWCX 0x00000001#define SYNC 0x7c0004ac#define ISYNC 0x4c00012c#define rs rsrt#define rt rsrtint opcodeXX(), opcode03(), opcode07();int opcode08(), opcode10(), opcode11();int opcode12(), opcode13(), opcode14(), opcode15();int opcode16(), opcode17(), opcode18(), opcode19();int opcode20(), opcode21(), opcode23();int opcode24(), opcode25(), opcode26(), opcode27();int opcode28(), opcode29(), opcode31();int opcode32(), opcode33(), opcode34(), opcode35();int opcode36(), opcode37(), opcode38(), opcode39();int opcode40(), opcode41(), opcode42(), opcode43();int opcode44(), opcode45(), opcode46(), opcode47();int (*opfuncs[])() = { opcodeXX, opcodeXX, opcodeXX, opcode03, opcodeXX, opcodeXX, opcodeXX, opcode07, opcode08, opcodeXX, opcode10, opcode11, opcode12, opcode13, opcode14, opcode15, opcode16, opcode17, opcode18, opcode19, opcode20, opcode21, opcodeXX, opcode23, opcode24, opcode25, opcode26, opcode27, opcode28, opcode29, opcodeXX, opcode31, opcode32, opcode33, opcode34, opcode35, opcode36, opcode37, opcode38, opcode39, opcode40, opcode41, opcode42, opcode43, opcode44, opcode45, opcode46, opcode47, opcodeXX, opcodeXX, opcodeXX, opcodeXX, opcodeXX, opcodeXX, opcodeXX, opcodeXX, opcodeXX, opcodeXX, opcodeXX, opcodeXX, opcodeXX, opcodeXX, opcodeXX, opcodeXX,};#if USE_SPRDCR_NAMESstruct sprdat { ushort val; char *name;} sprtbl[] = { { 0x03d7, "cdbcr" }, { 0x0009, "ctr" }, { 0x03f6, "dac1" }, { 0x03f7, "dac2" }, { 0x03f2, "dbcr" }, { 0x03f0, "dbsr" }, { 0x03fa, "dccr" }, { 0x03d5, "dear" }, { 0x03d4, "esr" }, { 0x03d6, "evpr" }, { 0x03f4, "iac1" }, { 0x03f5, "iac2" }, { 0x03fb, "iccr" }, { 0x03d3, "icdbdr" }, { 0x0008, "lr" }, { 0x03fc, "pbl1" }, { 0x03fe, "pbl2" }, { 0x03fd, "pbu1" }, { 0x03ff, "pbu2" }, { 0x03db, "pit" }, { 0x011f, "pvr" }, { 0x0110, "sprg0" }, { 0x0111, "sprg1" }, { 0x0112, "sprg2" }, { 0x0113, "sprg3" }, { 0x001a, "srr0" }, { 0x001b, "srr1" }, { 0x03de, "srr2" }, { 0x03df, "srr3" }, { 0x03dc, "tbhi" }, { 0x03dd, "tblo" }, { 0x03da, "tcr" }, { 0x03d8, "tsr" }, { 0x0001, "xer" }, { 0x03b9, "sgr" }, /* 403-GC only */ { 0x03ba, "dcwr" }, /* 403-GC only */ { 0x0000, "rsvd0" }, { 0x0010, "rsvd1" }, { 0x03d0, "rsvd2" }, { 0x03d1, "rsvd3" }, { 0x03d2, "rsvd4" }, { 0x03d9, "rsvd5" }, { 0x03f1, "rsvd6" }, { 0x03f3, "rsvd7" }, { 0x03f8, "rsvd8" }, { 0x03f9, "rsvd9" },};struct dcrdat { ushort val; char *name;} dcrtbl[] = { { 0x0090, "bear" }, { 0x0091, "besr" }, { 0x0080, "br0" }, { 0x0081, "br1" }, { 0x0082, "br2" }, { 0x0083, "br3" }, { 0x0084, "br4" }, { 0x0085, "br5" }, { 0x0086, "br6" }, { 0x0087, "br7" }, { 0x00c4, "dmacc0" }, { 0x00cc, "dmacc1" }, { 0x00d4, "dmacc2" }, { 0x00dc, "dmacc3" }, { 0x00c0, "dmacr0" }, { 0x00c8, "dmacr1" }, { 0x00d0, "dmacr2" }, { 0x00d8, "dmacr3" }, { 0x00c1, "dmact0" }, { 0x00c9, "dmact1" }, { 0x00d1, "dmact2" }, { 0x00d9, "dmact3" }, { 0x00c2, "dmada0" }, { 0x00ca, "dmada1" }, { 0x00d2, "dmada2" }, { 0x00da, "dmada3" }, { 0x00c3, "dmasa0" }, { 0x00cb, "dmasa1" }, { 0x00d3, "dmasa2" }, { 0x00db, "dmasa3" }, { 0x00e0, "dmasr" }, { 0x0042, "exier" }, { 0x0040, "exisr" }, { 0x00a0, "iocr" }, { 0x0041, "rsvd" }, { 0x00e1, "rsvd" },};#endifchar *crfld[] = { "CRf00", "CRf01", "CRf02", "CRf03", "CRf04", "CRf05", "CRf06", "CRf07",};char *crbit[] = { "CRb00", "CRb01", "CRb02", "CRb03", "CRb04", "CRb05", "CRb06", "CRb07", "CRb08", "CRb09", "CRb10", "CRb11", "CRb12", "CRb13", "CRb14", "CRb15", "CRb16", "CRb17", "CRb18", "CRb19", "CRb20", "CRb21", "CRb22", "CRb23", "CRb24", "CRb25", "CRb26", "CRb27", "CRb28", "CRb29", "CRb30", "CRb31",};char *Regs[] = { "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23", "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",};char *tbl1[] = { "add", "add.", "addo", "addo." };char *tbl2[] = { "addc", "addc.", "addco", "addco." };char *tbl3[] = { "adde", "adde.", "addeo", "addeo." };char *tbl4[] = { "addme", "addme.", "addmeo", "addmeo." };char *tbl5[] = { "addze", "addze.", "addzeo", "addzeo." };char *tbl6[] = { "b", "bl", "ba", "bla" };char *tbl7[] = { "bc", "bca", "bcl", "bcla" };char *tbl8[] = { "divw", "divw.", "divwo", "divwo." };char *tbl9[] = { "divwu", "divwu.", "divwuo", "divwuo." };char *tbl10[] = { "mullw", "mullw.", "mullwo", "mullwo." };char *tbl11[] = { "neg", "neg.", "nego", "nego." };char *tbl12[] = { "subf", "subf.", "subfo", "subfo." };char *tbl13[] = { "subfc", "subfc.", "subfco", "subfco." };char *tbl14[] = { "subfe", "subfe.", "subfeo", "subfeo." };char *tbl15[] = { "subfme", "subfme.", "subfmeo", "subfmeo." };char *tbl16[] = { "subfze", "subfze.", "subfzeo", "subfzeo." };char *tbl17[] = { "bdnz", "bdnza", "bdnzl", "bdnzla" };char *tbl18[] = { "bdnzf", "bdnzfa", "bdnzfl", "bdnzfla" };char *tbl19[] = { "bdnzt", "bdnzta", "bdnztl", "bdnztla" };char *tbl20[] = { "bdz", "bdza", "bdzl", "bdzla" };char *tbl21[] = { "bdzf", "bdzfa", "bdzfl", "bdzfla" };char *tbl22[] = { "bdzt", "bdzta", "bdztl", "bdztla" };char *DisHelp[] = { "Disassemble memory", "-[m] {address} [linecount]", 0,};/* DisAddr: * This variable can be used by the opcodeXX() functions if there is * good reason to know the address of the disassembly. */static ulong *DisAddr;/* disppc.c: * Disassembler for POWER-PC * * Dis(): * Use the upper 6 bits of the opcode as an offset into a table of * function pointers. Opon entry into the function, break down the * remaining fields and print the mnemonic. Note that the program is * intentionally left un-optimized. There's absolutely nothing tricky * about it so it should be trivial to add other POWER-PC instructions * to this disassembler. * NOTE: The branch instructions need work. */intDis(argc,argv)int argc;char *argv[];{ extern int optind; int opt, i, count, more; uchar *cp; more = 0; while ((opt = getopt(argc,argv,"m")) != -1) { switch(opt) { case 'm': more = 1; break; default: return(0); } } if (argc == optind+1) count = 1; else if (argc == optind+2) count = strtol(argv[optind+1],0,0); else return(-1); DisAddr = (ulong *)strtoul(argv[optind],0,0);again: for(i=0;i<count;i++) { cp = (uchar *)DisAddr; printf("%08lx: %02x%02x%02x%02x ", (ulong)DisAddr,cp[0],cp[1],cp[2],cp[3]); opfuncs[((cp[0] & 0xfc) >> 2)](*DisAddr); DisAddr++; } if (more) { if (More()) goto again; } return(0);}intaalk(ulong instr){ switch (instr & (AA | LK)) { case (AA | LK): return(3); case (AA): return(2); case (LK): return(1); default: return(0); }}shortd(ulong instr) /* 16 bit 2's compliment */{ return(instr & D);}/* sprf(): * This function attempts to replace the SPR number with some * name. Since this is somewhat CPU dependent, I have turned * this off for now.. */char *sprf(ulong instr){ static uchar buf[16]; ushort hi, lo, sprval; hi = lo = (ushort)((instr & DCRN) >> 11); hi &= 0x03e0; lo &= 0x001f; hi >>= 5; lo <<= 5; sprval = hi | lo;#if USE_SPRDCR_NAMES /* see above note */ for(int i=0;i<sizeof sprtbl/sizeof(struct sprdat);i++) { if (sprval == sprtbl[i].val) return(sprtbl[i].name); } sprintf(buf,"spr %d",sprval);#else sprintf(buf,"%d",sprval);#endif return(buf);}char *dcrn(ulong instr){ static uchar buf[16]; ushort hi, lo, dcrnval; hi = lo = (ushort)((instr & DCRN) >> 11); hi &= 0x03e0; lo &= 0x001f; hi >>= 5; lo <<= 5; dcrnval = hi | lo;#if USE_SPRDCR_NAMES for(int i=0;i<sizeof dcrtbl/sizeof(struct dcrdat);i++) { if (dcrnval == dcrtbl[i].val) return(dcrtbl[i].name); } sprintf(buf,"dcrn=0x%x",dcrnval);#else sprintf(buf,"%d",dcrnval);#endif return(buf);}ushortnb(ulong instr){ return((instr & NB) >> 11);}intoerc(ulong instr){ switch (instr & (OE | RC)) { case (OE | RC): return(3); case (OE): return(2); case (RC): return(1); default: return(0); }}ushortxo_nooe(ulong instr){ return((ushort)((instr & XO_NOOE) >> 1));}ushortxo_oe(ulong instr){ return((ushort)((instr & XO_OE) >> 1));}shortmb(ulong instr){ return((instr & MB) >> 6);}shortme(ulong instr){ return((instr & ME) >> 1);}shortto(ulong instr){ return((instr & TO) >> 21);}shortsh(ulong instr){ return((instr & SH) >> 11);}ushortfxm(ulong instr){ return((instr & FXM) >> 12);}char *ra(ulong instr) /* GPR used as source or target */{ return(Regs[(uchar)((instr & RA) >> 16)]);}char *rb(ulong instr) /* GPR used as source */{ return(Regs[(uchar)((instr & RB) >> 11)]);}char *ba(ulong instr){ return(crbit[(uchar)(((instr & BA) >> 16) & 0x1f)]);}char *bb(ulong instr){ return(crbit[(uchar)(((instr & BB) >> 11) & 0x1f)]);}char *bt(ulong instr){ return(crbit[(uchar)(((instr & BT) >> 21) & 0x1f)]);}char *bo(ulong instr){ static char bostr[32]; bostr[0] = 0; if ((instr & BO_0) == 0) { if (instr & BO_1) strcat(bostr,"if crbit=1 "); else strcat(bostr,"if crbit!=1 "); } if ((instr & BO_2) == 0) { if (instr & BO_3) strcat(bostr,"if --ctr=0 "); else strcat(bostr,"if --ctr!=0 "); } if (instr & BO_4) strcat(bostr,"bpr"); return(bostr);}char *bfa(ulong instr){ return(crfld[(uchar)(((instr & BFA) >> 18) & 0x3)]);}char *bf(ulong instr){ return(crfld[(uchar)(((instr & BF) >> 23) & 0x3)]);}char *bi(ulong instr){ return(crbit[(uchar)(((instr & BI) >> 16) & 0x1f)]);}char *rsrt(ulong instr) /* GPR used as source (rs) or destination (rt) */{ return(Regs[(uchar)(((instr & RSRT) >> 21) & 0x1f)]);}/* prnem(): * Print the mnemonic and append the number of spaces needed * so that the total length is 8 characters. */voidprnem(char *mnem){ int spacecount; spacecount = 8 - strlen(mnem); puts(mnem); while(spacecount > 0) { putchar(' '); spacecount--; }}voidprnemdot(char *mnem, int dot){ int spacecount; spacecount = 8 - strlen(mnem); puts(mnem); if (dot) { putchar('.'); spacecount--; } while(spacecount > 0) { putchar(' '); spacecount--; }}intbf_ra(char *mnemonic, ulong instr){ prnem(mnemonic); printf("%s,0,%s,0x%04X\n",bf(instr),ra(instr),(ushort)(instr&IM)); return(0);}intrt_ra_x(char *mnemonic, ulong instr){ prnem(mnemonic); printf("%s,%s,0x%04X\n",rt(instr),ra(instr),(ushort)(instr&IM)); return(0);}intrt_d_ra(char *mnemonic, ulong instr){ prnem(mnemonic); printf("%s,%d(%s)\n",rt(instr),d(instr),ra(instr)); return(0);}intrs_d_ra(char *mnemonic, ulong instr){ prnem(mnemonic); printf("%s,%d(%s)\n",rs(instr),d(instr),ra(instr)); return(0);}intbt_ba_bb(char *mnemonic, ulong instr){ prnem(mnemonic); printf("%s,%s,%s\n",bt(instr),ba(instr),bb(instr)); return(0);}intra_rs_sh_mb_me(char *mnemonic, ulong instr){ prnemdot(mnemonic,instr & RC); printf("%s,%s,0x%04X,0x%04X,0x%04X\n", ra(instr),rs(instr),sh(instr),mb(instr),me(instr)); return(0);}intra_rs(char *mnemonic, ulong instr){ prnem(mnemonic); printf("%s,%s,0x%04X\n",ra(instr),rs(instr),(ushort)(instr&IM)); return(0);}intrt_ra_rb(char *mnemonic, ulong instr){ prnem(mnemonic); printf("%s,%s,%s\n", rt(instr),ra(instr),rb(instr)); return(0);}intrs_ra_rb(char *mnemonic,ulong instr){ prnem(mnemonic); printf("%s,%s,%s\n",rs(instr),ra(instr),rb(instr)); return(0);}intra_rb(char *mnemonic,ulong instr){ prnem(mnemonic); printf("%s,%s\n",ra(instr),rb(instr)); return(0);}intrt_ra(char *mnemonic, ulong instr){ prnem(mnemonic); printf("%s,%s\n", rt(instr),ra(instr)); return(0);}intopcodeXX(ulong instr){ uchar *cp;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -