* config/tc-mn10300.h (pre_defined_registers) Remove.
(system_registers, cc_names): Likewise. (address_registers, data_registers, other_registers): New register arrays. (register_name, system_register_name, cc_name): Remove. (mn10300_reloc_prefix): Likewise. (data_register_name): New function. (address_register_name, other_register_name): Likewise. (md_assemble): Rough cut at parsing operands. Remove lots of unwanted code. (md_apply_fix3): Disable for now. Checkpointing today's Matsushita work.
This commit is contained in:
parent
7d6669623a
commit
1217102f2c
2 changed files with 242 additions and 197 deletions
|
@ -1,3 +1,17 @@
|
|||
Mon Oct 7 16:53:23 1996 Jeffrey A Law (law@cygnus.com)
|
||||
|
||||
* config/tc-mn10300.h (pre_defined_registers) Remove.
|
||||
(system_registers, cc_names): Likewise.
|
||||
(address_registers, data_registers, other_registers): New register
|
||||
arrays.
|
||||
(register_name, system_register_name, cc_name): Remove.
|
||||
(mn10300_reloc_prefix): Likewise.
|
||||
(data_register_name): New function.
|
||||
(address_register_name, other_register_name): Likewise.
|
||||
(md_assemble): Rough cut at parsing operands. Remove lots of
|
||||
unwanted code.
|
||||
(md_apply_fix3): Disable for now.
|
||||
|
||||
Mon Oct 7 11:38:34 1996 Andreas Schwab <schwab@issan.informatik.uni-dortmund.de>
|
||||
|
||||
* config/tc-m68k.c (select_control_regs): New function, extracted
|
||||
|
|
|
@ -61,7 +61,6 @@ static int reg_name_search PARAMS ((const struct reg_name *, int, const char *))
|
|||
static boolean register_name PARAMS ((expressionS *expressionP));
|
||||
static boolean system_register_name PARAMS ((expressionS *expressionP));
|
||||
static boolean cc_name PARAMS ((expressionS *expressionP));
|
||||
static bfd_reloc_code_real_type mn10300_reloc_prefix PARAMS ((void));
|
||||
|
||||
|
||||
/* fixups */
|
||||
|
@ -91,85 +90,31 @@ const pseudo_typeS md_pseudo_table[] =
|
|||
static struct hash_control *mn10300_hash;
|
||||
|
||||
/* This table is sorted. Suitable for searching by a binary search. */
|
||||
static const struct reg_name pre_defined_registers[] =
|
||||
static const struct reg_name data_registers[] =
|
||||
{
|
||||
{ "ep", 30 }, /* ep - element ptr */
|
||||
{ "gp", 4 }, /* gp - global ptr */
|
||||
{ "lp", 31 }, /* lp - link ptr */
|
||||
{ "r0", 0 },
|
||||
{ "r1", 1 },
|
||||
{ "r10", 10 },
|
||||
{ "r11", 11 },
|
||||
{ "r12", 12 },
|
||||
{ "r13", 13 },
|
||||
{ "r14", 14 },
|
||||
{ "r15", 15 },
|
||||
{ "r16", 16 },
|
||||
{ "r17", 17 },
|
||||
{ "r18", 18 },
|
||||
{ "r19", 19 },
|
||||
{ "r2", 2 },
|
||||
{ "r20", 20 },
|
||||
{ "r21", 21 },
|
||||
{ "r22", 22 },
|
||||
{ "r23", 23 },
|
||||
{ "r24", 24 },
|
||||
{ "r25", 25 },
|
||||
{ "r26", 26 },
|
||||
{ "r27", 27 },
|
||||
{ "r28", 28 },
|
||||
{ "r29", 29 },
|
||||
{ "r3", 3 },
|
||||
{ "r30", 30 },
|
||||
{ "r31", 31 },
|
||||
{ "r4", 4 },
|
||||
{ "r5", 5 },
|
||||
{ "r6", 6 },
|
||||
{ "r7", 7 },
|
||||
{ "r8", 8 },
|
||||
{ "r9", 9 },
|
||||
{ "sp", 3 }, /* sp - stack ptr */
|
||||
{ "tp", 5 }, /* tp - text ptr */
|
||||
{ "zero", 0 },
|
||||
{ "d0", 0 },
|
||||
{ "d1", 1 },
|
||||
{ "d2", 2 },
|
||||
{ "d3", 3 },
|
||||
};
|
||||
#define REG_NAME_CNT (sizeof(pre_defined_registers) / sizeof(struct reg_name))
|
||||
#define DATA_REG_NAME_CNT (sizeof(data_registers) / sizeof(struct reg_name))
|
||||
|
||||
|
||||
static const struct reg_name system_registers[] =
|
||||
static const struct reg_name address_registers[] =
|
||||
{
|
||||
{ "eipc", 0 },
|
||||
{ "eipsw", 1 },
|
||||
{ "fepc", 2 },
|
||||
{ "fepsw", 3 },
|
||||
{ "ecr", 4 },
|
||||
{ "psw", 5 },
|
||||
{ "a0", 0 },
|
||||
{ "a1", 1 },
|
||||
{ "a2", 2 },
|
||||
{ "a3", 3 },
|
||||
};
|
||||
#define SYSREG_NAME_CNT (sizeof(system_registers) / sizeof(struct reg_name))
|
||||
#define ADDRESS_REG_NAME_CNT (sizeof(address_registers) / sizeof(struct reg_name))
|
||||
|
||||
static const struct reg_name cc_names[] =
|
||||
static const struct reg_name other_registers[] =
|
||||
{
|
||||
{ "c", 0x1 },
|
||||
{ "ge", 0xe },
|
||||
{ "gt", 0xf },
|
||||
{ "h", 0xb },
|
||||
{ "l", 0x1 },
|
||||
{ "le", 0x7 },
|
||||
{ "lt", 0x6 },
|
||||
{ "n", 0x4 },
|
||||
{ "nc", 0x9 },
|
||||
{ "nh", 0x3 },
|
||||
{ "nl", 0x9 },
|
||||
{ "ns", 0xc },
|
||||
{ "nv", 0x8 },
|
||||
{ "nz", 0xa },
|
||||
{ "p", 0xc },
|
||||
{ "s", 0x4 },
|
||||
{ "sa", 0xd },
|
||||
{ "t", 0x5 },
|
||||
{ "v", 0x0 },
|
||||
{ "z", 0x2 },
|
||||
{ "mdr", 0 },
|
||||
{ "psw", 0 },
|
||||
{ "sp", 0 },
|
||||
};
|
||||
#define CC_NAME_CNT (sizeof(cc_names) / sizeof(struct reg_name))
|
||||
#define OTHER_REG_NAME_CNT (sizeof(other_registers) / sizeof(struct reg_name))
|
||||
|
||||
/* reg_name_search does a binary search of the given register table
|
||||
to see if "name" is a valid regiter name. Returns the register
|
||||
|
@ -214,7 +159,7 @@ reg_name_search (regs, regcount, name)
|
|||
* its original state.
|
||||
*/
|
||||
static boolean
|
||||
register_name (expressionP)
|
||||
data_register_name (expressionP)
|
||||
expressionS *expressionP;
|
||||
{
|
||||
int reg_number;
|
||||
|
@ -226,7 +171,7 @@ register_name (expressionP)
|
|||
start = name = input_line_pointer;
|
||||
|
||||
c = get_symbol_end ();
|
||||
reg_number = reg_name_search (pre_defined_registers, REG_NAME_CNT, name);
|
||||
reg_number = reg_name_search (data_registers, DATA_REG_NAME_CNT, name);
|
||||
|
||||
/* look to see if it's in the register table */
|
||||
if (reg_number >= 0)
|
||||
|
@ -249,7 +194,7 @@ register_name (expressionP)
|
|||
}
|
||||
}
|
||||
|
||||
/* Summary of system_register_name().
|
||||
/* Summary of register_name().
|
||||
*
|
||||
* in: Input_line_pointer points to 1st char of operand.
|
||||
*
|
||||
|
@ -260,7 +205,7 @@ register_name (expressionP)
|
|||
* its original state.
|
||||
*/
|
||||
static boolean
|
||||
system_register_name (expressionP)
|
||||
address_register_name (expressionP)
|
||||
expressionS *expressionP;
|
||||
{
|
||||
int reg_number;
|
||||
|
@ -272,7 +217,7 @@ system_register_name (expressionP)
|
|||
start = name = input_line_pointer;
|
||||
|
||||
c = get_symbol_end ();
|
||||
reg_number = reg_name_search (system_registers, SYSREG_NAME_CNT, name);
|
||||
reg_number = reg_name_search (address_registers, ADDRESS_REG_NAME_CNT, name);
|
||||
|
||||
/* look to see if it's in the register table */
|
||||
if (reg_number >= 0)
|
||||
|
@ -295,7 +240,7 @@ system_register_name (expressionP)
|
|||
}
|
||||
}
|
||||
|
||||
/* Summary of cc_name().
|
||||
/* Summary of register_name().
|
||||
*
|
||||
* in: Input_line_pointer points to 1st char of operand.
|
||||
*
|
||||
|
@ -306,7 +251,7 @@ system_register_name (expressionP)
|
|||
* its original state.
|
||||
*/
|
||||
static boolean
|
||||
cc_name (expressionP)
|
||||
other_register_name (expressionP)
|
||||
expressionS *expressionP;
|
||||
{
|
||||
int reg_number;
|
||||
|
@ -318,12 +263,12 @@ cc_name (expressionP)
|
|||
start = name = input_line_pointer;
|
||||
|
||||
c = get_symbol_end ();
|
||||
reg_number = reg_name_search (cc_names, CC_NAME_CNT, name);
|
||||
reg_number = reg_name_search (other_registers, OTHER_REG_NAME_CNT, name);
|
||||
|
||||
/* look to see if it's in the register table */
|
||||
if (reg_number >= 0)
|
||||
{
|
||||
expressionP->X_op = O_constant;
|
||||
expressionP->X_op = O_register;
|
||||
expressionP->X_add_number = reg_number;
|
||||
|
||||
/* make the rest nice */
|
||||
|
@ -450,30 +395,6 @@ md_begin ()
|
|||
}
|
||||
}
|
||||
|
||||
static bfd_reloc_code_real_type
|
||||
mn10300_reloc_prefix()
|
||||
{
|
||||
if (strncmp(input_line_pointer, "hi0(", 4) == 0)
|
||||
{
|
||||
input_line_pointer += 4;
|
||||
return BFD_RELOC_HI16;
|
||||
}
|
||||
if (strncmp(input_line_pointer, "hi(", 3) == 0)
|
||||
{
|
||||
input_line_pointer += 3;
|
||||
return BFD_RELOC_HI16_S;
|
||||
}
|
||||
if (strncmp (input_line_pointer, "lo(", 3) == 0)
|
||||
{
|
||||
input_line_pointer += 3;
|
||||
return BFD_RELOC_LO16;
|
||||
}
|
||||
|
||||
/* FIXME: implement sda, tda, zda here */
|
||||
|
||||
return BFD_RELOC_UNUSED;
|
||||
}
|
||||
|
||||
void
|
||||
md_assemble (str)
|
||||
char *str;
|
||||
|
@ -512,15 +433,19 @@ md_assemble (str)
|
|||
for(;;)
|
||||
{
|
||||
const char *errmsg = NULL;
|
||||
int op_idx;
|
||||
int parens = 0;
|
||||
char *hold;
|
||||
|
||||
fc = 0;
|
||||
match = 0;
|
||||
next_opindex = 0;
|
||||
insn = opcode->opcode;
|
||||
for (opindex_ptr = opcode->operands; *opindex_ptr != 0; opindex_ptr++)
|
||||
for (op_idx = 1, opindex_ptr = opcode->operands;
|
||||
*opindex_ptr != 0;
|
||||
opindex_ptr++, op_idx++)
|
||||
{
|
||||
const struct mn10300_operand *operand;
|
||||
char *hold;
|
||||
expressionS ex;
|
||||
|
||||
if (next_opindex == 0)
|
||||
|
@ -542,55 +467,101 @@ md_assemble (str)
|
|||
hold = input_line_pointer;
|
||||
input_line_pointer = str;
|
||||
|
||||
|
||||
/* lo(), hi(), hi0(), etc... */
|
||||
if ((reloc = mn10300_reloc_prefix()) != BFD_RELOC_UNUSED)
|
||||
#if 1
|
||||
if (*str == '(')
|
||||
{
|
||||
str++;
|
||||
input_line_pointer++;
|
||||
parens++;
|
||||
}
|
||||
#endif
|
||||
/* See if we can match the operands. */
|
||||
if (operand->flags & MN10300_OPERAND_DREG)
|
||||
{
|
||||
expression(&ex);
|
||||
|
||||
if (*input_line_pointer++ != ')')
|
||||
if (!data_register_name (&ex))
|
||||
{
|
||||
errmsg = "syntax error: expected `)'";
|
||||
input_line_pointer = hold;
|
||||
str = hold;
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (ex.X_op == O_constant)
|
||||
}
|
||||
else if (operand->flags & MN10300_OPERAND_AREG)
|
||||
{
|
||||
if (!address_register_name (&ex))
|
||||
{
|
||||
switch (reloc)
|
||||
{
|
||||
case BFD_RELOC_LO16:
|
||||
ex.X_add_number &= 0xffff;
|
||||
break;
|
||||
|
||||
case BFD_RELOC_HI16:
|
||||
ex.X_add_number = ((ex.X_add_number >> 16) & 0xffff);
|
||||
break;
|
||||
|
||||
case BFD_RELOC_HI16_S:
|
||||
ex.X_add_number = ((ex.X_add_number >> 16) & 0xffff)
|
||||
+ ((ex.X_add_number >> 15) & 1);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
insn = mn10300_insert_operand (insn, operand, ex.X_add_number,
|
||||
(char *) NULL, 0);
|
||||
input_line_pointer = hold;
|
||||
str = hold;
|
||||
goto error;
|
||||
}
|
||||
else
|
||||
}
|
||||
else if (operand->flags & MN10300_OPERAND_SP)
|
||||
{
|
||||
char *start = input_line_pointer;
|
||||
char c = get_symbol_end ();
|
||||
|
||||
if (strcmp (start, "sp") != 0)
|
||||
{
|
||||
if (fc > MAX_INSN_FIXUPS)
|
||||
as_fatal ("too many fixups");
|
||||
|
||||
fixups[fc].exp = ex;
|
||||
fixups[fc].opindex = *opindex_ptr;
|
||||
fixups[fc].reloc = reloc;
|
||||
fc++;
|
||||
*input_line_pointer = c;
|
||||
input_line_pointer = hold;
|
||||
str = hold;
|
||||
goto error;
|
||||
}
|
||||
*input_line_pointer = c;
|
||||
goto keep_going;
|
||||
}
|
||||
else if (operand->flags & MN10300_OPERAND_PSW)
|
||||
{
|
||||
char *start = input_line_pointer;
|
||||
char c = get_symbol_end ();
|
||||
|
||||
if (strcmp (start, "psw") != 0)
|
||||
{
|
||||
*input_line_pointer = c;
|
||||
input_line_pointer = hold;
|
||||
str = hold;
|
||||
goto error;
|
||||
}
|
||||
*input_line_pointer = c;
|
||||
goto keep_going;
|
||||
}
|
||||
else if (operand->flags & MN10300_OPERAND_MDR)
|
||||
{
|
||||
char *start = input_line_pointer;
|
||||
char c = get_symbol_end ();
|
||||
|
||||
if (strcmp (start, "mdr") != 0)
|
||||
{
|
||||
*input_line_pointer = c;
|
||||
input_line_pointer = hold;
|
||||
str = hold;
|
||||
goto error;
|
||||
}
|
||||
*input_line_pointer = c;
|
||||
goto keep_going;
|
||||
}
|
||||
else if (data_register_name (&ex))
|
||||
{
|
||||
input_line_pointer = hold;
|
||||
str = hold;
|
||||
goto error;
|
||||
}
|
||||
else if (address_register_name (&ex))
|
||||
{
|
||||
input_line_pointer = hold;
|
||||
str = hold;
|
||||
goto error;
|
||||
}
|
||||
else if (other_register_name (&ex))
|
||||
{
|
||||
input_line_pointer = hold;
|
||||
str = hold;
|
||||
goto error;
|
||||
}
|
||||
else
|
||||
{
|
||||
expression (&ex);
|
||||
}
|
||||
|
||||
switch (ex.X_op)
|
||||
{
|
||||
case O_illegal:
|
||||
|
@ -600,17 +571,44 @@ md_assemble (str)
|
|||
errmsg = "missing operand";
|
||||
goto error;
|
||||
case O_register:
|
||||
if (operand->flags & (MN10300_OPERAND_DREG
|
||||
| MN10300_OPERAND_AREG) == 0)
|
||||
{
|
||||
input_line_pointer = hold;
|
||||
str = hold;
|
||||
goto error;
|
||||
}
|
||||
|
||||
insn = mn10300_insert_operand (insn, operand, ex.X_add_number,
|
||||
(char *) NULL, 0);
|
||||
break;
|
||||
|
||||
case O_constant:
|
||||
/* If this operand can be promoted, and it doesn't
|
||||
fit into the allocated bitfield for this insn,
|
||||
then promote it (ie this opcode does not match). */
|
||||
if (operand->flags & MN10300_OPERAND_PROMOTE
|
||||
&& ! check_operand (insn, operand, ex.X_add_number))
|
||||
{
|
||||
input_line_pointer = hold;
|
||||
str = hold;
|
||||
goto error;
|
||||
}
|
||||
|
||||
insn = mn10300_insert_operand (insn, operand, ex.X_add_number,
|
||||
(char *) NULL, 0);
|
||||
break;
|
||||
|
||||
default:
|
||||
/* If this operand can be promoted, then this opcode didn't
|
||||
match since we can't know if it needed promotion! */
|
||||
if (operand->flags & MN10300_OPERAND_PROMOTE)
|
||||
{
|
||||
input_line_pointer = hold;
|
||||
str = hold;
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* We need to generate a fixup for this expression. */
|
||||
if (fc >= MAX_INSN_FIXUPS)
|
||||
as_fatal ("too many fixups");
|
||||
|
@ -621,15 +619,26 @@ md_assemble (str)
|
|||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
keep_going:
|
||||
str = input_line_pointer;
|
||||
input_line_pointer = hold;
|
||||
|
||||
while (*str == ' ' || *str == ',' || *str == '[' || *str == ']')
|
||||
++str;
|
||||
|
||||
if (*str == ')')
|
||||
{
|
||||
str++;
|
||||
parens--;
|
||||
}
|
||||
}
|
||||
if (parens == 0 && *str != ',')
|
||||
match = 1;
|
||||
else
|
||||
{
|
||||
input_line_pointer = hold;
|
||||
str = hold;
|
||||
}
|
||||
match = 1;
|
||||
|
||||
error:
|
||||
if (match == 0)
|
||||
|
@ -655,57 +664,38 @@ md_assemble (str)
|
|||
|
||||
input_line_pointer = str;
|
||||
|
||||
/* Write out the instruction.
|
||||
/* XXX */
|
||||
if (opcode->format == 1)
|
||||
size = 1;
|
||||
|
||||
Four byte insns have an opcode with the two high bits on. */
|
||||
if ((insn & 0x0600) == 0x0600)
|
||||
size = 4;
|
||||
else
|
||||
if (opcode->format == 2 || opcode->format == 6)
|
||||
size = 2;
|
||||
|
||||
if (opcode->format == 3 || opcode->format == 7)
|
||||
size = 3;
|
||||
|
||||
if (opcode->format == 4)
|
||||
size = 5;
|
||||
|
||||
if (opcode->format == 5)
|
||||
size = 7;
|
||||
|
||||
if (opcode->format == 8)
|
||||
size = 4;
|
||||
|
||||
if (opcode->format == 9)
|
||||
size = 6;
|
||||
|
||||
if (opcode->format == 10)
|
||||
size = 8;
|
||||
|
||||
|
||||
/* Write out the instruction. */
|
||||
|
||||
f = frag_more (size);
|
||||
if (size > 4)
|
||||
size = 4;
|
||||
md_number_to_chars (f, insn, size);
|
||||
|
||||
/* Create any fixups. At this point we do not use a
|
||||
bfd_reloc_code_real_type, but instead just use the
|
||||
BFD_RELOC_UNUSED plus the operand index. This lets us easily
|
||||
handle fixups for any operand type, although that is admittedly
|
||||
not a very exciting feature. We pick a BFD reloc type in
|
||||
md_apply_fix. */
|
||||
for (i = 0; i < fc; i++)
|
||||
{
|
||||
const struct mn10300_operand *operand;
|
||||
|
||||
operand = &mn10300_operands[fixups[i].opindex];
|
||||
if (fixups[i].reloc != BFD_RELOC_UNUSED)
|
||||
{
|
||||
reloc_howto_type *reloc_howto = bfd_reloc_type_lookup (stdoutput, fixups[i].reloc);
|
||||
int size;
|
||||
int offset;
|
||||
fixS *fixP;
|
||||
|
||||
if (!reloc_howto)
|
||||
abort();
|
||||
|
||||
size = bfd_get_reloc_size (reloc_howto);
|
||||
offset = 4 - size;
|
||||
|
||||
if (size < 1 || size > 4)
|
||||
abort();
|
||||
|
||||
fixP = fix_new_exp (frag_now, f - frag_now->fr_literal + offset, size,
|
||||
&fixups[i].exp,
|
||||
reloc_howto->pc_relative,
|
||||
fixups[i].reloc);
|
||||
}
|
||||
else
|
||||
{
|
||||
fix_new_exp (frag_now, f - frag_now->fr_literal, 4,
|
||||
&fixups[i].exp,
|
||||
1 /* FIXME: MN10300_OPERAND_RELATIVE ??? */,
|
||||
((bfd_reloc_code_real_type)
|
||||
(fixups[i].opindex + (int) BFD_RELOC_UNUSED)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -762,6 +752,9 @@ md_apply_fix3 (fixp, valuep, seg)
|
|||
valueT value;
|
||||
char *where;
|
||||
|
||||
fixp->fx_done = 1;
|
||||
return 0;
|
||||
|
||||
if (fixp->fx_addsy == (symbolS *) NULL)
|
||||
{
|
||||
value = *valuep;
|
||||
|
@ -841,7 +834,6 @@ md_apply_fix3 (fixp, valuep, seg)
|
|||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/* Insert an operand value into an instruction. */
|
||||
|
||||
static unsigned long
|
||||
|
@ -852,11 +844,17 @@ mn10300_insert_operand (insn, operand, val, file, line)
|
|||
char *file;
|
||||
unsigned int line;
|
||||
{
|
||||
if (operand->bits != 16)
|
||||
if (operand->bits != 32)
|
||||
{
|
||||
long min, max;
|
||||
offsetT test;
|
||||
|
||||
if ((operand->flags & MN10300_OPERAND_SIGNED) != 0)
|
||||
{
|
||||
max = (1 << (operand->bits - 1)) - 1;
|
||||
min = - (1 << (operand->bits - 1));
|
||||
}
|
||||
else
|
||||
{
|
||||
max = (1 << operand->bits) - 1;
|
||||
min = 0;
|
||||
|
@ -882,3 +880,36 @@ mn10300_insert_operand (insn, operand, val, file, line)
|
|||
insn |= (((long) val & ((1 << operand->bits) - 1)) << operand->shift);
|
||||
return insn;
|
||||
}
|
||||
|
||||
static unsigned long
|
||||
check_operand (insn, operand, val)
|
||||
unsigned long insn;
|
||||
const struct mn10300_operand *operand;
|
||||
offsetT val;
|
||||
{
|
||||
if (operand->bits != 32)
|
||||
{
|
||||
long min, max;
|
||||
offsetT test;
|
||||
|
||||
if ((operand->flags & MN10300_OPERAND_SIGNED) != 0)
|
||||
{
|
||||
max = (1 << (operand->bits - 1)) - 1;
|
||||
min = - (1 << (operand->bits - 1));
|
||||
}
|
||||
else
|
||||
{
|
||||
max = (1 << operand->bits) - 1;
|
||||
min = 0;
|
||||
}
|
||||
|
||||
test = val;
|
||||
|
||||
|
||||
if (test < (offsetT) min || test > (offsetT) max)
|
||||
return 0;
|
||||
else
|
||||
return 1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue