📄 asm.c
字号:
/*
* File: asm.c
* Purpose: Assembly routines for ColdFire dBUG
*
* Notes:
*
*/
#include "src/include/dbug.h"
#include "src/uif/sym.h"
#include "src/cpu/coldfire/mcf5xxx/ea.h"
/********************************************************************/
#define MAX_OPERAND 10
/* 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 *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] != NULL) ; i++)
{}
if (instruct[j][i] == NULL) /* 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] = NULL;
}
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] == NULL)
{
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] == NULL)
{
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] == NULL)
{
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] = ©[0];
if (copy[0] == '(')
{
parens++;
tstr[0] = ©[1];
}
for (i=0; (tstr[0][i] != '.' && tstr[0][i] != NULL); i++) {}
if (tstr[0][i] == '.')
{
tstr[0][i] = NULL;
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] != NULL && copy[i] != ')'); i++) {}
if (copy[i] == ')')
{
parens--;
copy[i] = NULL;
}
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] != NULL && strg[1][0] != NULL && strg[2][0] == NULL)
{
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] != NULL && strg[1][0] != NULL && strg[2][0] != NULL)
{
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);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -