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

📄 asm.c

📁 motorola自己开发的针对coldfire 5272的Dbug bootloader程序
💻 C
📖 第 1 页 / 共 4 页
字号:
/*
 * File:		asm.c	
 * Purpose:		Assembly routines for ColdFire Debuggers
 *
 * Notes:
 *
 */
#include "src/include/dbug.h"
#include "src/uif/sym.h"
#include "src/cpu/coldfire/ea.h"

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

#define MAX_OPERAND 30

/* Globals */
int8 size = 0;		/* written by check_size_and_label(), used by afun's 	*/
int8 word_sel =0;  /* written by getwordselect(), used by afun's */
uint8 error;			/* global error flag					*/
uint8 reg_error;		/* global error flag set in get_XXXX_register()		*/
uint8 ext_word_flag;	/* used in handle_ext_words(), set if ext_word exists	*/ 
uint8 ext_long_flag;	/* used in handle_ext_words(), set if ext_long exists	*/ 
uint8 opword2_flag;	/* used in handle_ext_words(), set if opword2 exists	*/ 
uint32 addr_mode;  	/* written by get_ea(), used by afun26 (MOVE)		*/
uint16 opword2;		/* written by various afun's, used in handle_ext_words()*/
uint16 ext_word;  	/* written in get_ea() and afun's, used by "		*/
uint32 ext_long;		/*  "							*/
int success; 		/* global error flag set by get_value()			*/
char user_input[UIF_MAX_LINE];	/* raw user input, unparsed		*/
char *instruct[UIF_MAX_ARGS];		/* parsed inputs			*/
ADDRESS asm_pc;			/* address where opcode is written	*/
static const char ERR_ADDR_REG[] = "Not a valid address register: %s\n";
static const char ERR_DATA_REG[] = "Not a valid data register: %s\n";
static const char ERR_REG[] = "Not a valid register: %s\n";
static const char ERR_OPER[]= "Not a valid operand: %s\n";

static const char data_register[8][3] = {"D0","D1","D2","D3","D4","D5","D6","D7"};
static const char addr_register[8][3] = {"A0","A1","A2","A3","A4","A5","A6","A7"};

/****************************************************************/
static void
get_word_select(int operand)
{ 
	int i,j;

	j=operand;
 
    for (i=2; (instruct[j][i] != ':') && (instruct[j][i] != '.')  && (instruct[j][i] != '\0') ; i++)
    {}
	
	if (instruct[j][i] == '\0')      /* No word select found !*/
    { 
		word_sel = 0;				 /* default to "lower word" (L) */ 
	}
	else if((instruct[j][i] == '.') || (instruct[j][i] == ':'))
	{
		switch (instruct[j][i+1])
		{
			case 'l':
			case 'L':
				word_sel=0;
				break;
			case 'u':
			case 'U':
				word_sel=1;
				break;
			default:
				error = TRUE;
				printf("Not a valid attribute %s\n",instruct[j]);
				break;
		}

		instruct[j][i] = '\0';
	}
	else
	{
		word_sel = -1;				/* error */
	}

}

/****************************************************************/
static int
get_data_register (char *reg)
{
	int Dn, i;
	Dn = 8;		/* return value of 8 is error */  
	for (i=0; i<8; i++)
	{
		if (strncasecmp(reg,data_register[i],2) == 0)
		{
			Dn = i;
			reg_error = FALSE;
			break;
		}
	}
	if (Dn == 8)
		reg_error = TRUE;

	return Dn;
}	
/****************************************************************/
static int
get_addr_register (char *reg)
{
	int An, i;
	An = 8;		/* return value of 8 is error */  
	for (i=0; i<8; i++)
	{
		if (strncasecmp(reg,addr_register[i],2) == 0)
		{
			An = i;
			reg_error = FALSE;
			break;
		}
	}
	/* A7 is SP  */
	if (strncasecmp(reg,"sp",2) == 0)
	{
		An = 7;
		reg_error = FALSE;
	}
	if (An == 8)
		reg_error = TRUE;
	return An;
}	
/****************************************************************/
static void
check_base (char *data, int *temp_base)
{
	if (data[0] == '0' && (data[1] == 'x' || data[1] == 'X'))
		*temp_base = 16;
	else if (data[0] == '$')
		*temp_base = 16;
	else if (data[0] == '%')
		*temp_base = 2;
	else if (data[0] == '@')
		*temp_base = 8;
	else
		*temp_base = 10;
}
/****************************************************************/
static void 
write_data(int size, int data)
{
	switch (size)
	{
		case SIZE_16:
			*((uint16 *) asm_pc) = (uint16)data;
			asm_pc += 2;
			break;
		case SIZE_32:
			*((uint32 *) asm_pc) = (uint32)data;
			asm_pc += 4;
			break;
	}
}
/****************************************************************/
static void
handle_ext_words(void)
{
	if (opword2_flag)
		write_data (16,opword2);

	/* Extend uint16 operand to uint32 opcode */
	if (ext_word_flag && ext_long_flag)
	{
		ext_long = (uint32)ext_word;
		write_data (32,ext_long);
	}
	else if (ext_word_flag)
		write_data (16,ext_word);
	else if (ext_long_flag)
		write_data (32,ext_long);
}
/****************************************************************/
static uint32
get_imm_data (char *data_str,uint32 mask)
{
	int temp_base, offset;
	uint32 imm_data;


	if (data_str[0] != '#')
	{
		error = TRUE;
  		printf("Not valid immediate data: %s\n", data_str);
		printf("It might help if you use '#'.\n");
		return 0;
	}
	check_base(&data_str[1],&temp_base);
	
	/* adjust string so call to stroul in get_value() doesn't 
	 * choke on special base indication characters
	 */
	if (data_str[1] == '$' || data_str[1] == '%' || data_str[1] == '@')
		offset = 2;
	else 
		offset = 1;

	imm_data = get_value(&data_str[offset],&success,temp_base);
	if (success == 0)
	{
		error = TRUE;
		printf(INVALUE,&data_str[1]);
		return 0;
	}
	else if (imm_data & mask)
	{
		error = TRUE;
		printf("Not valid immediate data: %s\n",&data_str[1]);
		printf("Value is larger than specified.\n");
		return 0;
	}
	else
		return imm_data;
}
/****************************************************************/
static int
size_is_long(void)
{
	switch (size)
	{
		case 0:
		case 1:
			printf("Invalid size: .L only\n");
			return 0;
		case 2:
		case -1:
			return 1;
	}
	return 0;
}
/****************************************************************/
static int
is_DRD (int* reg, int* mod, char* raw)
{
	if ((*reg = get_data_register(raw)) != 8)
	{	/* Dn */
		*mod = 0x0;
		addr_mode = DRD;
        	return 1;
	}
	return 0;
}
static int
is_ARD (int* reg, int* mod, char* raw)
{
	if ((*reg = get_addr_register(raw)) != 8)
	{	/* An */
		*mod = 0x1;
                addr_mode = ARD;
        	return 1;
	}
        return 0;
}
static int
is_ARI (int* reg, int* mod, char* raw)
{
 	if (raw[0] == '(' && raw[3] == ')' && raw[4] == '\0')
	{
		if ((*reg = get_addr_register(&raw[1])) != 8)
		{
			*mod = 0x2;
			addr_mode = ARI;
			return 1;
                }
	}
	return 0;
}
static int
is_ARIPR (int* reg, int* mod, char* raw)
{
  	if (raw[0] == '-' && raw[1] == '(' && raw[4] == ')' && raw[5] == '\0')
	{
		if ((*reg = get_addr_register(&raw[2])) != 8)
		{
			*mod = 0x4;
			addr_mode = ARIPR;
			return 1;
                }
	}
	return 0;
}
static int
is_ARIPO (int* reg, int* mod, char* raw)
{
	if (raw[0] == '(' && raw[3] == ')' && raw[4] == '+' && raw[5] == '\0')
	{
		if ((*reg = get_addr_register(&raw[1])) != 8)
		{
			*mod = 0x3;
			addr_mode = ARIPO;
			return 1;
                }
	}
	return 0;
}
static int
is_IM (int* reg, int* mod, char* raw)
{
	int32 temp;

	if (raw[0] == '#')
	{
     	*reg = 0x4;
		*mod = 0x7;
		addr_mode = IM;
		temp = (uint32)get_imm_data(raw,0x0);	/* FIX !!! usage of temp */
		if (!error || symtab_convert_string(raw,(ADDRESS *)&temp))
		{
            if (temp & 0xFFFF0000)
			{
              	ext_long = temp; 
				ext_long_flag = 1;
			}
            else  
			{
               	ext_word = (uint16)temp; 
				ext_word_flag = 1;
			}
                	return 1;
		}
	}
        return 0;
}
static int
is_AS_AL (int* reg, int* mod, char* raw)
{	/* (xxx).W  or  (xxx).L */
	int i, force = 0, parens = 0;
	uint32 temp;
	char *tstr[1], copy[MAX_OPERAND];
	
	strcpy(copy,raw);
	tstr[0] = &copy[0];

	if (copy[0] == '(')
	{
		parens++;
		tstr[0] = &copy[1];
	}
	for (i=0; (tstr[0][i] != '.' && tstr[0][i] != '\0'); i++) {}
	if (tstr[0][i] == '.')
	{
		tstr[0][i] = '\0';
		switch (tstr[0][i+1])
		{
			case 'w':
			case 'W':
				break;
			case 'l':
			case 'L':
				force = 1;
				break;
			default:
				return 0;
		}
		if (tstr[0][i+2] == ')')
			parens--;
	}
	for (i=1; (copy[i] != '\0' && copy[i] != ')'); i++) {}
	if (copy[i] == ')')
	{
		parens--;
		copy[i] = '\0';
	}
	if (parens)
		return 0;

	if (((tstr[0][0] == '0' && (tstr[0][1] == 'x' || tstr[0][1] == 'X')) 
	   || tstr[0][0] == '$') || (symtab_convert_string(raw,(ADDRESS *)&temp)))
	{       
       		*mod = 0x7;
                temp = get_value(tstr[0],&success,16);
                if (success && ((temp & 0xffff0000) || force))
        	{       /* Absolute Long */
			*reg = 0x1;
                	addr_mode = AL;
                	ext_long = temp;
			ext_long_flag = 1;
			return 1;
		}
                else if (success)
                {       /* Absolute Short */
                       	*reg = 0x0;
                       	addr_mode = AS;
                       	ext_word = (uint16)temp;
			ext_word_flag = 1;
			return 1;
		}
                else
			return 0;
	}
        return 0;
}
static int
is_ARID_PCID (int* reg, int* mod, char **strg)
{
	int temp_base, go_ahead = 0;
	int32 temp;
	
	if (strg[0][0] != '\0' && strg[1][0] != '\0' && strg[2][0] == '\0')
	{
		if ((*reg = get_addr_register(strg[1])) != 8)
		{
			go_ahead = 1;
			addr_mode = ARID;
			*mod = 0x5;
		}
		else if (strncasecmp(strg[1],"pc",2) == 0)
		{
			go_ahead = 1;
			addr_mode = PCID;
			*mod = 0x7;
			*reg = 0x2;
		}
		if (go_ahead)
		{
			check_base(strg[0],&temp_base);
			temp = get_value(strg[0],&success,temp_base);
			/* 16-bit */
			if (success && temp >= -32768 && temp <= 32767)
			{
				ext_word_flag = 1;
				ext_word = (uint16)temp;
				return 1;
			}
		}	
	}
	return 0;
}
static int
is_ARII8_PCII8 (int* reg, int* reg2, int* mod, char **strg)
{
	int temp_base, go_ahead = 0;
	int32 temp;

	if (strg[0][0] != '\0' && strg[1][0] != '\0' && strg[2][0] != '\0')
	{
		if ((*reg = get_addr_register(strg[1])) != 8)
		{
			go_ahead = 1;
			addr_mode = ARII8;
			*mod = 0x6;
		}
		else if (strncasecmp(strg[1],"pc",2) == 0)
		{
			go_ahead = 1;
			addr_mode = PCII8;
			*mod = 0x7;
			*reg = 0x3;
		}
		if (go_ahead)
		{
			check_base(strg[0],&temp_base);
			temp = get_value(strg[0],&success,temp_base);
			/* 8-bit */
			if (success && temp >= -128 && temp <= 127)
			{
				ext_word_flag = 1;
				ext_word = (uint16)(temp & 0x00FF);
				if ((*reg2 = get_data_register(strg[2])) != 8)
					temp = 0x0;	/* write Data bit */
				else if ((*reg2 = get_addr_register(strg[2])) != 8)
					temp = 0x8000;	/* write Addr bit */
				else 
				{
					error = TRUE;
					return 0;
				}	
				ext_word = (uint16)(ext_word | temp | (*reg2 << 12) | 0x800);
				strg[2] = &strg[2][2];
                                if (strg[2][0] == '.')
                                {
                                        switch (strg[2][1])
                                        {
                                           	case 'L':
                                           	case 'l':
						/* wrote .L above with XXX | 0x800; */
                                               		break; 
                                           	default:
                                               		error = TRUE;
                                               		return 0;
                                        }
                                        strg[2] = &strg[2][2];
                                }        
                                if (strg[2][0] == '*')
                                {
                                        switch (strg[2][1])
                                        {
                                                case '1':
                                                        break;
                                                case '2':
                                                        ext_word = ext_word | 0x200;
                                                        break;
                                                case '4':
                                                        ext_word = ext_word | 0x400;
                                                        break;
                                                case '8':
                                                        ext_word = ext_word | 0x600;
                                                        break;
                                                default:
							error = TRUE;
							return 0;
					}
					strg[2] = &strg[2][2];
				}
			 	if (strg[2][0] != '\0')
				{
					error = TRUE;
					return 0;
				}		
				return 1;
			}
		}	
	}
	return 0;
}
/****************************************************************/
static int
parse_operand (char *temp[], char *raw)
{
	int i, j, parens;
	
	i = j = parens = 0;
	temp[0] = raw;
	temp[1] = temp [2] = '\0';

	if (raw[0] == '(')
	{
		temp[0] = &raw[1];
		parens++;
		i++;
	}		
	while (raw[i] != '\0')
	{
		if (raw[i] == '(' || raw[i] == ',' || raw[i] == ')')
		{
			j++;
		        if (raw[i] == '(')
                	        parens++;
                        if (raw[i] == ')')
                                parens--;
                        raw[i] = '\0';
                        temp[j] = &raw[i+1];
                }
                i++;
        }
	if (parens != 0)
		return 0;
	else
		return 1;
}
/****************************************************************/
static uint16
get_ea (char *operand, int ea_mask, int force_long)
{
	uint16 ea; 
	int reg, reg2, mode;
	char *tstr[3], raw[MAX_OPERAND];

	strcpy(raw,operand);

	if (is_DRD(&reg, &mode, raw))
	{}
	else if (is_ARD(&reg, &mode, raw))
	{}
	else if (is_ARI(&reg, &mode, raw))
	{}
	else if (is_ARIPO(&reg, &mode, raw))
	{}
	else if (is_ARIPR(&reg, &mode, raw))
	{}
	else if (is_IM(&reg, &mode, raw))
	{
		if (force_long && ext_word_flag)
		{
			ext_long_flag = 1;
			ext_long = (uint32) ext_word;
			ext_word_flag = 0;
		}	
	}
	else if (is_AS_AL(&reg, &mode, raw))
	{}
	else /* Must seperate the operand */     
	{
		if (parse_operand(tstr, raw))
		{
			if (is_ARID_PCID(&reg, &mode, tstr))
			{}
			else if (is_ARII8_PCII8(&reg, &reg2, &mode, tstr))
			{}
			else
			{ 
				printf("Invalid operand: %s\n",operand);
				error = TRUE;
				return 0;
			}
		}
		else
		{
			printf("Syntax Error: %s\n",operand);
			error = TRUE;
			return 0;
		}
	}
	if (!(addr_mode & ea_mask))
	{
		error = TRUE;
		printf("Invalid addressing mode for '%s' instruction\n",instruct[0]);
		return 0;
	}
	ea = (uint16)((mode << 3) | reg);
	return ea;
}
/****************************************************************/
void 
afun1 (int ea_mask, uint16 opword) /* funcs already have access to instruct[] */
{
	(void) ea_mask;
	/* This function is used for all instructions 
	 * whose opcode is written entirely in the isa table
	 * RTS, NOP, HALT, PULSE, RTE 
	 */ 

⌨️ 快捷键说明

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