📄 asm.c
字号:
printf(ERR_OPER,instruct[4]);
error=FALSE;
return;
}
}
else
{
if ((reg=get_data_register(instruct[4]))==8) /* Get Rw Destination field */
{
if ((reg=get_addr_register(instruct[4])) != 8) /* Rw could be an address register */
{
opword2 = (uint16)(opword2 | (reg << 12) | 0x8000 ); /* Rw IS an address register */
}
else /* Rw is NOT a data or address register */
{
printf(ERR_OPER,instruct[4]);
return;
}
}
else
{
opword2 = (uint16)(opword2 | (reg << 12)); /* Rw is a Data register */
}
}
/* handle instruct[5] IF !NULL */
if(instruct[5] != NULL)
{
if ((reg=get_data_register(instruct[5]))==8) /* Get Rw Destination field */
{
if ((reg=get_addr_register(instruct[5])) != 8) /* Rw could be an address register */
opword2 = (uint16)(opword2 | (reg << 12) | 0x8000 ); /* Rw IS an address register */
else /* Rw is NOT a data or address register */
{
printf(ERR_OPER,instruct[5]);
return;
}
}
else
opword2 = (uint16)(opword2 | (reg << 12)); /* Rw is a Data register */
}
write_data(16,opword);
handle_ext_words();
}
/****************************************************************/
void
afun30 (int ea_mask, uint16 opword)
{
/* INTOUCH <Ay> */
int reg;
(void) ea_mask;
if ((reg=get_addr_register(instruct[1])) != 8) /* Ay could be an address register */
opword = (uint16)(opword | reg); /* Ay IS an address register */
else
{
printf(ERR_ADDR_REG,instruct[1]);
return;
}
write_data(16,opword);
handle_ext_words();
}
/****************************************************************/
void
afun31 (int ea_mask, uint16 opword)
{
/* MOV3Q #<data>,<ea> */
/* XXXX|DATa|XXX|MOD|REG */
uint16 data;
data = (uint16)get_imm_data(instruct[1],0);
if (!error)
{
if (data == 0xffff)
data = 0;
else if ((data > 7)||(data == 0 ))
{
printf(ERR_OPER,instruct[1]);
return;
}
opword = (uint16)(opword | (data << 9));
afun8b(ea_mask,opword,0);
}
}
/****************************************************************/
void
afun32 (int ea_mask, uint16 opword)
{
/* MVS <ea>y,Dx */
/* MVZ <ea>y,Dx */
/* XXXX|REG|XX|S|MOD|REG */
uint16 ea;
int reg;
switch (size)
{
case 0:
/* byte-sized input operands */
break;
case 1:
opword = (uint16)(opword | (1 << 6)); /* word-sized input operands */
break;
case 2:
printf("Invalid size: .B or .W only\n"); /* NO long-sized input operands */
return;
default:
/* default to byte-sized input operands */
break;
}
ea=get_ea(instruct[1],ea_mask,0);
if(!error)
opword = (uint16)(opword | ea);
else
{
printf(ERR_OPER,instruct[1]);
error=FALSE;
return;
}
if ((reg=get_data_register(instruct[2])) != 8)
opword = (uint16)(opword | (reg<<9));
else
{
printf(ERR_DATA_REG,instruct[2]);
return;
}
write_data(16,opword);
handle_ext_words();
}
/****************************************************************/
void
afun33 (int ea_mask, uint16 opword)
{
/* TAS */
/* opword: XXXXXXXXXX|MOD|REG */
if((size==1)||(size==2))
{
printf("Invalid size: .B only\n"); /*Byte-sized input operands only*/
return;
}
else
afun8(ea_mask,opword);
}
/****************************************************************/
void
afun34 (int ea_mask, uint16 opword)
{
/* CMPA <ea>,An */
/* XXXX|REG|XXXXXX|MOD|REG */
int An;
#if (defined(CPU_MCF5407))
opword= 0xB000;
switch (size)
{
case 0:
/* byte */
printf("Invalid size: .W and .L only\n");
return;
case 1:
opword = (uint16)(opword | (3 << 6));
break;
case 2:
opword = (uint16)(opword | (7 << 6));
ext_long_flag=1;
break;
default:
opword = (uint16)(opword | (7 << 6));
ext_long_flag=1;
break;
}
An = get_addr_register(instruct[2]);
if (!reg_error)
{
opword = (uint16)(opword | (An << 9));
afun8(ea_mask,opword);
}
else
printf(ERR_ADDR_REG,instruct[2]);
#else
if (size_is_long())
{
An = get_addr_register(instruct[2]);
if (!reg_error)
{
ext_long_flag=1;
opword = (uint16)(opword | (An << 9));
afun8(ea_mask,opword);
}
else
printf(ERR_ADDR_REG,instruct[2]);
}
#endif
}
/****************************************************************/
void
afun35 (int ea_mask, uint16 opword)
{
/* CMPI #<data>,Dn */
#if (defined(CPU_MCF5407))
opword= 0x0C00;
switch (size)
{
case 0:
/* byte */
ext_word = (uint16)get_imm_data(instruct[1],0x0);
ext_word_flag=1;
break;
case 1:
opword = (uint16)(opword | (1 << 6));
ext_word = (uint16)get_imm_data(instruct[1],0x0);
ext_word_flag=1;
break;
case 2:
opword = (uint16)(opword | (1 << 7));
ext_long = get_imm_data(instruct[1],0x0);
ext_long_flag=1;
break;
default:
opword = (uint16)(opword | (1 << 7));
ext_long = get_imm_data(instruct[1],0x0);
ext_long_flag=1;
break;
}
if (!error)
{
afun5(ea_mask,opword);
}
#else
if (size_is_long())
{
ext_long = get_imm_data(instruct[1],0x0);
if (!error)
{
ext_long_flag = 1;
afun5(ea_mask,opword);
}
}
#endif
}
/****************************************************************/
void
afun36 (int ea_mask, uint16 opword)
{
/* DIVS.L DIVU.L DIVS.W DIVU.W*/
int Dn;
switch (size)
{
case 0:
error = TRUE;
printf("Invalid size specified: .W or .L only\n");
break;
case 1:
if (strcasecmp(instruct[0],"DIVS") == 0)
opword = 0x81C0;
else /* DIVU */
opword = 0x80C0;
ea_mask = EA_DATA;
afun15b(ea_mask,opword,0);
break;
case 2:
default:
opword = 0x4C40;
ea_mask = (DRD | ARI | ARIPO | ARIPR | ARID);
if (strcasecmp(instruct[0],"DIVS") == 0)
opword2 = 0x0800;
Dn = get_data_register(instruct[2]);
if (!reg_error)
{
opword2 = (uint16)(opword2 | (Dn << 12) | Dn);
opword2_flag = 1;
afun8(ea_mask,opword);
}
break;
}
}
/****************************************************************/
void
afun37 (int ea_mask, uint16 opword)
{
/* REMS.L REMU.L*/
int Dn,Dw, i;
switch (size)
{
case 0:
error = TRUE;
printf("Invalid size specified: .W or .L only\n");
break;
case 1:
error = TRUE;
printf("Invalid size specified: .W or .L only\n");
break;
case 2:
default:
if (strcasecmp(instruct[0],"REMS") == 0)
opword2 = 0x0800;
for (i=0; (instruct[2][i] != ':') && (instruct[2][i] != '\0') ; i++)
{}
if (instruct[2][i] == ':')
{
instruct[2][i] ='\0';
instruct[3]=&instruct[2][i+1];
}
else
{
/* error there is no ":", no second register!*/
printf(ERR_OPER,instruct[2]);
return;
}
Dn = get_data_register(instruct[3]);
if (!reg_error)
{
Dw = get_data_register(instruct[2]);
if (!reg_error)
{
opword2 = (uint16)(opword2 | (Dn << 12) | Dw);
opword2_flag = 1;
afun8(ea_mask,opword);
}
}
break;
}
}
/****************************************************************/
static int
check_equ(void)
{ /* Function looks for occurance of 'EQUATE' statement.
* If one is present, the symbol and value are stored
* in the symbol table and a '0' is returned.
*/
int value, temp_base, i;
if ((strcasecmp(instruct[1],"equ") == 0) ||
(instruct[1][0] == '.' && strcasecmp(&instruct[1][1],"equ") == 0))
{
if (instruct[2] != NULL)
{
check_base(instruct[2], &temp_base);
value = get_value(instruct[2],&success,temp_base);
if (success)
{
for (i=1; instruct[0][i] != ':' && instruct[0][i] != '\0'; i++)
{}
if (instruct[0][i] == ':')
instruct[0][i] = '\0';
symtab_add (instruct[0],value);
}
else
printf(INVALUE,instruct[0]);
return 1; /* found 'equ', get new user_input */
}
}
return 0; /* no 'equ', user input is an instruction */
}
#if 0
/****************************************************************/
static void
get_instr (int flag)
{
/*This do-while loop prints the current address where
*an instruction will be written. It then gets the input
*from the user and prompts until it gets a printable
*character (ie. not just a CR). If an EQUATE statement
*is present, the value of the symbol is stored in the symbol
*table, and the user is prompted again. If the input 'flag'
*is 1, then only one instruction is to be assembled.
*/
int num_args = 0;
switch (flag)
{
case 0:
while (num_args == 0)
{
printf("%08lX: ",(ADDRESS)asm_pc);
get_history_line(user_input);
num_args = make_argv(user_input, instruct);
if (num_args)
num_args = check_equ();
}
return;
case 1: /* only one instruction to be assembled */
return;
}
}
#endif
/****************************************************************/
static void
sep_operands (void)
{ /* Fuction parses the operands in instruct[1] and stores the
* source operand in instruct[1] and the destination operand
* in instruct[2] (if present).
*/
int i,j, parens = 0;
for (j=1; (instruct[j] != NULL); j++)
{
for (i=0; ((instruct[j][i] != ',') || parens) && (instruct[j][i] != '\0'); i++)
{
if (instruct[j][i] == '(')
parens++;
if (instruct[j][i] == ')')
parens--;
}
if (instruct[j][i] == ',')
{
instruct[j][i] = '\0';
instruct[j+1] = &instruct[j][i+1];
}
else
instruct[j+1] = NULL;
}
}
#if 0
/****************************************************************/
static void
init_globals(void)
{
error = FALSE;
opword2 = ext_word = ext_long = 0;
opword2_flag = ext_word_flag = ext_long_flag = 0;
}
#endif
/****************************************************************/
static void
check_size_and_label(void)
{
int i;
for (i=1; instruct[0][i] != ':' && instruct[0][i] != '\0' && instruct[0][i] != '.'; i++)
{}
if (instruct[0][i] == ':') /* found a label */
{
instruct[0][i] = '\0';
symtab_add (instruct[0], asm_pc);
if (instruct[1])
instruct[0] = instruct[1];
else
instruct[0] = NULL;
if (instruct[2])
instruct[1] = instruct[2];
else
instruct[1] = NULL;
instruct[2] = NULL;
for (i=1; instruct[0][i] != '\0' && instruct[0][i] != '.'; i++)
{}
}
if (instruct[0][i] == '.')
{
switch (instruct[0][i+1])
{
case 'b':
case 'B': /*byte*/
size = 0;
break;
case 'w':
case 'W': /*word*/
size = 1;
break;
case 'l':
case 'L': /*long*/
size = 2;
break;
default:
error = TRUE;
printf("Not a valid ColdFire instruction: %s\n",instruct[0]);
break;
}
instruct[0][i] = '\0';
}
else
size = -1; /* no size entered */
}
#if 0
/****************************************************************/
ADDRESS
cpu_asm (ADDRESS ass_addr, int single_isa, char **argv,int offset)
{
/*
* This routine assembles ColdFire instructions, and
* returns when a '.' is entered by the user. The
* address where the next instruction can be written
* is returned.
*/
int index, opword, done, valid_instruction;
extern const int ISASIZE;
asm_pc = ass_addr;
if (single_isa)
{
for (index=0; argv[index+offset] != NULL; index++)
instruct[index] = argv[index+offset];
}
get_instr(single_isa);
while (*instruct[0] != '.' && !done)
{
init_globals();
valid_instruction = FALSE;
check_size_and_label ();
if (instruct[0] != '\0' && !(error)) /* check to see if only a label was entered */
{ for (index=0; index < ISASIZE; index++) /* or false size specifier */
{
if ((strcasecmp(instruct[0],isa[index].instruction)) == 0)
{
valid_instruction = TRUE;
sep_operands ();
opword = isa[index].match;
if (isa[index].asm_func)
isa[index].asm_func(isa[index].ea_mask, opword);
else
printf("Assembler operation not found!\n");
break;
}
}
if (!valid_instruction)
printf("Not a valid instruction: %s\n",instruct[0]);
}
if (single_isa)
done = TRUE;
get_instr(single_isa);
}
return asm_pc;
}
/****************************************************************/
/********************************************************************/
#else
ADDRESS
cpu_asm (ADDRESS pc, char **args)
{
int index;
uint16 opword;
extern const int ISASIZE;
error = FALSE;
for (index = 0; args[index] != NULL; index++)
instruct[index] = args[index];
asm_pc = pc;
/* Is this an equate statement? */
if (check_equ())
goto done;
check_size_and_label();
/* Go to done if error or only a label was entered */
if (error || (instruct[0] == '\0'))
goto done;
for (index = 0; index < ISASIZE; index++)
{
if (strcasecmp(instruct[0], isa[index].instruction) == 0)
{
opword2 = 0;
ext_word = 0;
ext_long = 0;
opword2_flag = 0;
ext_word_flag = 0;
ext_long_flag = 0;
opword = isa[index].match;
sep_operands();
isa[index].asm_func(isa[index].ea_mask, opword);
break;
}
}
done:
if ((index == ISASIZE) || error)
printf("Error: Invalid instruction: %s\n",instruct[0]);
return asm_pc;
}
#endif
/********************************************************************/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -