⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 disasm.c

📁 motorola自己开发的针对coldfire 5272的Dbug bootloader程序
💻 C
📖 第 1 页 / 共 4 页
字号:
/*
 * File:		src/cpu/coldfire/disasm.c
 * Purpose:		MCF5206 definitions
 *
 * Notes:		This file contains the routines necessary to disassemble
 * 				MC680x0 and MCF52xx compatible instructions.  This file 
 *				is a standalone, and the main entry point is cpu_disasm().
 */

/********************************************************************/

#include "src/include/dbug.h"
#include "src/uif/uif.h"
#include "src/cpu/coldfire/ea.h"

/********************************************************************/

#define SYMBOL_TABLE

#define SIZE_BYTE	SIZE_8
#define SIZE_WORD	SIZE_16
#define SIZE_LONG	SIZE_32 

#define ADDRESS_REGISTER -2
#define DATA_REGISTER    -3

/********************************************************************/


/********************************************************************/

static char
dstr[80];

static ADDRESS
disasm_pc;

static int
disasm_op_size;

static int
valid_instruction;

/********************************************************************/
static void
inc_disasm_pc (unsigned int num)
{
	disasm_pc = (ADDRESS)((unsigned int)disasm_pc +
		(unsigned int)num);
}

/********************************************************************/
static void
append_instruction (char *buf, char *instruction)
{
	sprintf(buf,"%-10s",instruction);
}

/********************************************************************/

#define append_string(a,b)	strcat(a,b)

/********************************************************/
static void
append_value (char *buf, int value, int size)
{
	/*
	 * This routine appends a value in hex notation.
	 */
	char buffer[11];

	buffer[0] = '\0';
	switch (size)
	{
		case SIZE_BYTE:
			sprintf(buffer,"0x%02X",value & 0x000000FF);
			break;
		case SIZE_WORD:
			sprintf(buffer,"0x%04X",value & 0x0000FFFF);
			break;
		case SIZE_LONG:
			sprintf(buffer,"0x%08X",value);
			break;
	}
	strcat(buf,buffer);
}

/********************************************************************/
static int
append_size2 (char *buf, int opword, int size_offset, int instr_size)
{
	/*
	 * This field accepts `opword' and then determines according
	 * to the offset which size is specified.
	 *
	 * The `offset' are given by the bit number as listed in the
	 * M68000 Family Programmer's Reference, Chapter 8. [15 .. 0]
	 */
	int i, j, mask;

	mask = 0x3;	/* 2 bits */
	for (i = 1; i < size_offset; i++)
		mask = mask << 1;
	i = (opword & mask) >> (size_offset - 1);

	if (instr_size)
	{
		for (j = 0; *(char *)((int)buf +j) != ' '; ++j)
			;
		buf[j] = '.';
		switch (i)
		{
			case 1:
				buf[++j] = 'B';
				disasm_op_size = SIZE_BYTE;
				break;
			case 2:
				buf[++j] = 'L';
				disasm_op_size = SIZE_LONG;
				break;
			case 3:
				buf[++j] = 'W';
				disasm_op_size = SIZE_WORD;
				break;
			default:
				valid_instruction = FALSE;
				break;
		}
	}
	else
	{
		switch (i)
		{
			case 1:
				strcat(buf,".B");
				break;
			case 2:
				strcat(buf,".L");
				break;
			case 3:
				strcat(buf,".W");
				break;
			default:
				valid_instruction = FALSE;
				break;
		}
	}
	return i;
}

/********************************************************************/
static int
append_size (char *buf, int opword, int size_offset, int instr_size)
{
	/*
	 * This field accepts `opword' and then determines according
	 * to the offset which size is specified.
	 *
	 * The `offset' are given by the bit number as listed in the
	 * M68000 Family Programmer's Reference, Chapter 8. [15 .. 0]
	 */
	int i, j, mask;

	mask = 0x3;	/* 2 bits */
	for (i = 1; i < size_offset; i++)
		mask = mask << 1;
	i = (opword & mask) >> (size_offset - 1);

	disasm_op_size = -1;
	if (instr_size)
	{
		for (j = 0; *(char *)((int)buf +j) != ' '; ++j)
			;
		buf[j] = '.';
		switch (i)
		{
			case 0:
				buf[++j] = 'B';
				disasm_op_size = SIZE_BYTE;
				break;
			case 1:
				buf[++j] = 'W';
				disasm_op_size = SIZE_WORD;
				break;
			case 2:
				buf[++j] = 'L';
				disasm_op_size = SIZE_LONG;
				break;
			default:
				valid_instruction = FALSE;
				break;
		}
	}
	else
	{
		switch (i)
		{
			case 0:
				strcat(buf,".B");
				break;
			case 1:
				strcat(buf,".W");
				break;
			case 2:
				strcat(buf,".L");
				break;
			default:
				valid_instruction = FALSE;
				break;
		}
	}
	return i;
}

/********************************************************************/
static void
append_register (char *buf, int opword, int reg_offset, int reg_num_offset)
{
	/*
	 * This field accepts `opword' and then determines according
	 * to the offsets which register (A0..A7,D0..D7) is specified.
	 * The register name is then concatenated to the end of the
	 * disasm_stmt.
	 *
	 * The `offsets' are given by the bit number as listed in the
	 * M68000 Family Programmer's Reference, Chapter 8. [15 .. 0]
	 */
	int i, mask;
	char regnum[3];

	/* Determine what kind of register */
	if (reg_offset == ADDRESS_REGISTER)
	{
		strcat(buf,"A");
	}
	else
	{
		if (reg_offset == DATA_REGISTER)
		{
		strcat(buf,"D");
		}
		else
		{
			mask = 1;
			for (i = 0; i < reg_offset; i++)
				mask = mask << 1;
			if (opword & mask)
				strcat(buf,"A");
			else
				strcat(buf,"D");
		}
	}

	/* determine register number */
	/* The offset given is the msb of the 3 bit field containing */
	/* the register number. */
	mask = 0x7;	/* 3 bits */
	for (i = 2; i < reg_num_offset; i++)
		mask = mask << 1;
	i = (opword & mask) >> (reg_num_offset - 2);
	sprintf(regnum,"%d",i);
	strcat(buf,regnum);
}

/********************************************************************/
static void
append_displacement (char *buf, int extension, int disp_offset)
{
	/*
	 * This function determines and appends a 16 or 32 bit disp.
	 * The `offsets' are given by the bit number as listed in the
	 * M68000 Family Programmer's Reference, Chapter 2. [15 .. 0]
	 */
	int i, mask, disp;

	mask = 0x3;	/* 2 bits */
	for (i = 1; i < disp_offset; i++)
		mask = mask << 1;
	i = (extension & mask) >> (disp_offset - 1);

	switch (i)
	{
		case 0:
		case 1:
			break;
		case 2:
			disp = (int)((int16)cpu_read_data(disasm_pc, SIZE_16));
			inc_disasm_pc(2);
			append_value(buf, disp, SIZE_16);
			break;
		case 3:
			disp = (int)((int32)cpu_read_data(disasm_pc, SIZE_32));
			inc_disasm_pc(4);
			append_value(buf, disp, SIZE_32);
			break;
	}
}

/********************************************************************/
static void
append_size_scale (char *buf, int extension, int size_offset, int scale_offset)
{
	/*
	 * This function determines the size and scale information
	 * for addressing modes that require it.
	 * 
	 * The `offsets' are given by the bit number as listed in the
	 * M68000 Family Programmer's Reference, Chapter 2. [15 .. 0]
	 */
	int i, mask, size, scale;

	mask = 0x1;	/* 1 bits */
	for (i = 0; i < size_offset; i++)
		mask = mask << 1;
	size = (extension & mask) >> size_offset;

	mask = 0x3;	/* 2 bits */
	for (i = 1; i < scale_offset; i++)
		mask = mask << 1;
	scale = (extension & mask) >> (scale_offset - 1);

	if (size)
		append_string(buf,".L");
	else
		append_string(buf,".W");

	switch (scale)
	{
		case 0:
			append_string(buf,"*1");
			break;
		case 1:
			append_string(buf,"*2");
			break;
		case 2:
			append_string(buf,"*4");
			break;
		case 3:
			/* valid_instruction = FALSE; */
			append_string(buf,"*8");
			break;
	}
}

/********************************************************************/
static int
append_ea (char *buf, int opword, int offset, int ea_mask)
{
	/*
	 * This routine creates the addressing mode.  The
	 * extensions for the addressing mode, if necessary,
	 * start at disasm_pc
	 */
	int i, mask, mode, reg, ea;
	char buffer[9];
#if (defined(SYMBOL_TABLE))
	char tstr[100];
#endif

	ea = EA_NONE;

	/* get addressing mode */
	mask = 0x7;	/* 3 bits */
	for (i = 2; i < offset; i++)
		mask = mask << 1;
	mode = (opword & mask) >> (offset - 2);

	/* get register */
	mask = 0x7;	/* 3 bits */
	for (i = 2; i < (offset - 3); i++)
		mask = mask << 1;
	reg = (opword & mask) >> (offset -3 - 2);

	switch (mode)
	{
		case 0:	/* data register direct mode */
			append_register(buf,reg,DATA_REGISTER,2);
			ea = DRD;
			break;
		case 1:	/* address register direct mode */
			append_register(buf,reg,ADDRESS_REGISTER,2);
			ea = ARD;
			break;
		case 2:	/* address register indirect mode (ARI) */
			append_string(buf,"(");
			append_register(buf,reg,ADDRESS_REGISTER,2);
			append_string(buf,")");
			ea = ARI;
			break;
		case 3:	/* ARI with postincrement mode */
			append_string(buf,"(");
			append_register(buf,reg,ADDRESS_REGISTER,2);
			append_string(buf,")+");
			ea = ARIPO;
			break;
		case 4:	/* ARI with predecrement mode */
			append_string(buf,"-(");
			append_register(buf,reg,ADDRESS_REGISTER,2);
			append_string(buf,")");
			ea = ARIPR;
			break;
		case 5:	/* ARI with displacement mode */
			{
				int disp;
				disp = (int)((int16)cpu_read_data((ADDRESS)disasm_pc,16));
				inc_disasm_pc(2);
				sprintf(buffer,"%d",disp);
				append_string(buf,buffer);
				append_string(buf,"(");
				append_register(buf,reg,ADDRESS_REGISTER,2);
				append_string(buf,")");
				ea = ARID;
			}
			break;
		case 6:
			{
				/* this mode is overloaded.  the encoding in the */
				/* extension byte indicate which of the 4 modes  */
				/*                                               */
				/* [xxxxxxx0xxxx0000] ARI 8bit displacement      */
				/* [xxxxxxx1xxxx0000] ARI base displacement      */
				/* [xxxxxxx1xxxx00xx] memory indirect pre index  */
				/* [xxxxxxx1xxxx01xx] memory indirect post index */
				/*                                               */

				int extension;

				extension = (int)*(uint16 *)disasm_pc;
				inc_disasm_pc(2);

				if (extension & 0x0100)
				{
					/* ARI base or memory indirects */
					if (extension & 0x0007)
					{
						/* memory indirects */
						if (extension & 0x0004)
						{
							/* memory indirect post index */
							append_string(buf,"(");
							append_string(buf,"[");
							append_displacement(buf,extension,5);
							append_string(buf,",");
							append_register(buf,reg,ADDRESS_REGISTER,2);
							append_string(buf,"]");
							append_string(buf,",");
							append_register(buf,extension,15,14);
							append_size_scale(buf,extension,11,10);
							append_string(buf,",");
							append_displacement(buf,extension,1);
							ea = MIPO;
						}
						else
						{
							/* memory indirect pre index */
							append_string(buf,"(");
							append_string(buf,"[");
							append_displacement(buf,extension,5);
							append_string(buf,",");
							append_register(buf,reg,ADDRESS_REGISTER,2);
							append_string(buf,",");
							append_register(buf,extension,15,14);
							append_size_scale(buf,extension,11,10);
							append_string(buf,"]");
							append_string(buf,",");
							append_displacement(buf,extension,1);
							ea = MIPR;
						}
					}
					else
					{
						/* ARI with BASE displacement */
						append_string(buf,"(");
						append_displacement(buf,extension,5);
						append_string(buf,",");
						append_register(buf,reg,ADDRESS_REGISTER,2);
						append_string(buf,",");
						append_register(buf,extension,15,14);
						append_size_scale(buf,extension,11,10);
						ea = ARIIB;
					}
				}
				else
				{
					int8 disp8;

					disp8 = (int8)(extension & 0x00FF);
					sprintf(buffer,"%d",disp8);
					append_string(buf,buffer);
					append_string(buf,"(");
					append_register(buf,reg,ADDRESS_REGISTER,2);
					append_string(buf,",");
					append_register(buf,extension,15,14);
					append_size_scale(buf,extension,11,10);
					ea = ARII8;
				}
			append_string(buf,")");
			}
			break;
		case 7:
			switch (reg)
			{
				case 0x0:
					{
						int data;
						data = (int)((int16)cpu_read_data((ADDRESS)disasm_pc,16));
						inc_disasm_pc(2);
						append_string(buf,"(");
						append_value(buf,data,16);
						append_string(buf,".W");
						append_string(buf,")");
					}
					ea = AS;
					break;
				case 0x1:
					{
						int data;
						data = (int)((int32)cpu_read_data((ADDRESS)disasm_pc,32));
						inc_disasm_pc(4);

#if (defined(SYMBOL_TABLE))
						if (symtab_convert_address((ADDRESS)data,tstr))
						{
							append_string(buf,tstr);
						}
						else
						{
							append_string(buf,"(");
							append_value(buf,data,32);
							append_string(buf,".L");
							append_string(buf,")");
						}
#else
						append_string(buf,"(");
						append_value(buf,data,32);
						append_string(buf,".L");
						append_string(buf,")");
#endif
					}
					ea = AL;
					break;
				case 0x2:
					{
						int disp;
						disp = (int)((int16)cpu_read_data((ADDRESS)disasm_pc,16));
						inc_disasm_pc(2);
						sprintf(buffer,"%d",disp);
						append_string(buf,buffer);
						append_string(buf,"(PC)");
					}
					ea = PCID;
					break;
				case 0x3:
					{
						int extension, disp;

						extension = (int)*(uint16 *)disasm_pc;
						inc_disasm_pc(2);

						/* this mode is overloaded.  the encoding in the */
						/* extension byte indicate which of the 4 modes  */
						/*                                               */
						/* [xxxxxxx0xxxx0000] PC  8bit displacement      */
						/* [xxxxxxx1xxxx0000] PC  base displacement      */
						/* [xxxxxxx1xxxx00xx] PC mem indirect pre index  */
						/* [xxxxxxx1xxxx01xx] PC mem indirect post index */
						/*                                               */

						if (extension & 0x0100)
						{
							/* PC base or PC memory indirects */
							if (extension & 0x0007)
							{
								/* PC memory indirects */
								if (extension & 0x0004)
								{
									/* memory indirect post index */
									append_string(buf,"(");
									append_string(buf,"[");
									append_displacement(buf,extension,5);
									append_string(buf,",PC],");
									append_register(buf,extension,15,14);
									append_size_scale(buf,extension,11,10);
									append_string(buf,",");
									append_displacement(buf,extension,1);
									ea = PCMIPO;
								}
								else
								{
									/* memory indirect pre index */
									append_string(buf,"(");
									append_string(buf,"[");
									append_displacement(buf,extension,5);
									append_string(buf,",PC,");
									append_register(buf,extension,15,14);
									append_size_scale(buf,extension,11,10);
									append_string(buf,"]");
									append_string(buf,",");
									append_displacement(buf,extension,1);
									ea = PCMIPR;
								}
							}
							else
							{
								/* base disp */
								append_string(buf,"(");
								append_displacement(buf,extension,5);
								append_string(buf,",PC,");
								append_register(buf,extension,15,14);
								append_size_scale(buf,extension,11,10);
								ea = PCIIB;
							}
						}
						else
						{
							disp = (int)((int8)(extension & 0x00FF));
							sprintf(buffer,"%d",disp);
							append_string(buf,buffer);
							append_string(buf,"(PC,");
							append_register(buf,extension,15,14);
							append_size_scale(buf,extension,11,10);
							append_string(buf,")");
							ea = PCII8;
						}
					}
					break;
				case 0x4:
					{
						int data;
						switch (disasm_op_size)
						{
							case SIZE_BYTE:
								data = (int)((uint16)cpu_read_data((ADDRESS)disasm_pc,16));
								inc_disasm_pc(2);
								data = (int)(data & 0x00FF);
								append_string(buf,"#");
								append_value(buf,data,8);
								break;
							case SIZE_WORD:
								data = (int)((uint16)cpu_read_data((ADDRESS)disasm_pc,16));
								inc_disasm_pc(2);
								append_string(buf,"#");
								append_value(buf,data,16);
								break;
							case SIZE_LONG:
								data = (int)((uint32)cpu_read_data((ADDRESS)disasm_pc,32));
								inc_disasm_pc(4);
								append_string(buf,"#");
#if (defined(SYMBOL_TABLE))
								if (symtab_convert_address((ADDRESS)data,tstr))
								{
									append_string(buf,tstr);
								}
								else
									append_value(buf,data,32);
#else
								append_value(buf,data,32);
#endif
								break;
							default:
								break;
						}

⌨️ 快捷键说明

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