dis_ppc.c

来自「umon bootloader source code, support mip」· C语言 代码 · 共 1,329 行 · 第 1/2 页

C
1,329
字号
/* 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
#endif

void 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	rsrt

int 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_NAMES
struct 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" },
};
#endif

char *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.
 */
int
Dis(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);
}

int
aalk(ulong instr)
{
	switch (instr & (AA | LK)) {
	case (AA | LK):
		return(3);
	case (AA):
		return(2);
	case (LK):
		return(1);
	default:
		return(0);
	}
}

short
d(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);
}

ushort
nb(ulong instr)
{
	return((instr & NB) >> 11);
}

int
oerc(ulong instr)
{
	switch (instr & (OE | RC)) {
	case (OE | RC):
		return(3);
	case (OE):
		return(2);
	case (RC):
		return(1);
	default:
		return(0);
	}
}

ushort
xo_nooe(ulong instr)
{
	return((ushort)((instr & XO_NOOE) >> 1));
}

ushort
xo_oe(ulong instr)
{
	return((ushort)((instr & XO_OE) >> 1));
}

short
mb(ulong instr)
{
	return((instr & MB) >> 6);
}

short
me(ulong instr)
{
	return((instr & ME) >> 1);
}

short
to(ulong instr)
{
	return((instr & TO) >> 21);
}

short
sh(ulong instr)
{
	return((instr & SH) >> 11);
}

ushort
fxm(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.
 */
void
prnem(char *mnem)
{
	int	spacecount;

	spacecount = 8 - strlen(mnem);
	puts(mnem);
	while(spacecount > 0) {
		putchar(' ');
		spacecount--;
	}
}

void
prnemdot(char *mnem, int dot)
{
	int	spacecount;

	spacecount = 8 - strlen(mnem);
	puts(mnem);
	if (dot) {
		putchar('.');
		spacecount--;
	}
	while(spacecount > 0) {
		putchar(' ');
		spacecount--;
	}
}

int
bf_ra(char *mnemonic, ulong instr)
{
	prnem(mnemonic);
	printf("%s,0,%s,0x%04X\n",bf(instr),ra(instr),(ushort)(instr&IM));
	return(0);
}

int
rt_ra_x(char *mnemonic, ulong instr)
{
	prnem(mnemonic);
	printf("%s,%s,0x%04X\n",rt(instr),ra(instr),(ushort)(instr&IM));
	return(0);
}

int
rt_d_ra(char *mnemonic, ulong instr)
{
	prnem(mnemonic);
	printf("%s,%d(%s)\n",rt(instr),d(instr),ra(instr));
	return(0);
}

int
rs_d_ra(char *mnemonic, ulong instr)
{
	prnem(mnemonic);
	printf("%s,%d(%s)\n",rs(instr),d(instr),ra(instr));
	return(0);
}

int
bt_ba_bb(char *mnemonic, ulong instr)
{
	prnem(mnemonic);
	printf("%s,%s,%s\n",bt(instr),ba(instr),bb(instr));
	return(0);
}

int
ra_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);
}

int
ra_rs(char *mnemonic, ulong instr)
{
	prnem(mnemonic);
	printf("%s,%s,0x%04X\n",ra(instr),rs(instr),(ushort)(instr&IM));
	return(0);
}

int
rt_ra_rb(char *mnemonic, ulong instr)
{
	prnem(mnemonic);
	printf("%s,%s,%s\n", rt(instr),ra(instr),rb(instr));
	return(0);
}

int
rs_ra_rb(char *mnemonic,ulong instr)
{
	prnem(mnemonic);
	printf("%s,%s,%s\n",rs(instr),ra(instr),rb(instr));
	return(0);
}

int
ra_rb(char *mnemonic,ulong instr)
{
	prnem(mnemonic);
	printf("%s,%s\n",ra(instr),rb(instr));
	return(0);
}

int
rt_ra(char *mnemonic, ulong instr)
{
	prnem(mnemonic);
	printf("%s,%s\n", rt(instr),ra(instr));
	return(0);
}

int
opcodeXX(ulong instr)
{
	uchar	*cp;

	cp = (uchar *)&instr;
	printf("data    %02x%02x%02x%02x\n",cp[0],cp[1],cp[2],cp[3]);
	return(0);
}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?