Fix PR 17135 (whilst keeping PR14827 fixed) by prefering register names over

symbolic names, except where the register name is unacceptable.
This commit is contained in:
Nick Clifton 1998-09-22 22:48:42 +00:00
parent 7b46dd00e4
commit aa7bf2a890
2 changed files with 105 additions and 51 deletions

View File

@ -1,3 +1,14 @@
Tue Sep 22 15:44:21 1998 Nick Clifton <nickc@cygnus.com>
* config/tc-d30v.c (find_format): Do not accept flag registers as
general purpose registers.
(find_format): If an immediate value is expected at a given place
in a format, but a register name has been provided instead, check
to see if that register name matches the name of a predefined
symbol and if it does, then use the symbol instead.
(reg_name_search): If a register name matches a symbol name,
prefer the register name to the symbol name.
start-sanitize-sky
Mon Sep 21 13:08:01 1998 Doug Evans <devans@canuck.cygnus.com>

View File

@ -28,7 +28,7 @@
const char comment_chars[] = ";";
const char line_comment_chars[] = "#";
const char line_separator_chars[] = "";
const char *md_shortopts = "OnN";
const char *md_shortopts = "OnNcC";
const char EXP_CHARS[] = "eE";
const char FLT_CHARS[] = "dD";
@ -36,6 +36,7 @@ const char FLT_CHARS[] = "dD";
#define NOP_ALL 2
static int warn_nops = 0;
static int Optimizing = 0;
static int warn_register_name_conflicts = 1;
#define FORCE_SHORT 1
#define FORCE_LONG 2
@ -112,7 +113,8 @@ static struct d30v_format *find_format PARAMS ((struct d30v_opcode *opcode,
expressionS ops[],int fsize, int cmp_hack));
static long long build_insn PARAMS ((struct d30v_insn *opcode, expressionS *opers));
static void write_long PARAMS ((struct d30v_insn *opcode, long long insn, Fixups *fx));
static void write_1_short PARAMS ((struct d30v_insn *opcode, long long insn, Fixups *fx));
static void write_1_short PARAMS ((struct d30v_insn *opcode, long long insn,
Fixups *fx, int use_sequential));
static int write_2_short PARAMS ((struct d30v_insn *opcode1, long long insn1,
struct d30v_insn *opcode2, long long insn2, exec_type_enum exec_type, Fixups *fx));
static long long do_assemble PARAMS ((char *str, struct d30v_insn *opcode,
@ -166,6 +168,13 @@ reg_name_search (name)
low = 0;
high = reg_name_cnt () - 1;
if (symbol_find (name) != NULL)
{
if (warn_register_name_conflicts)
as_warn ("Register name %s conflicts with symbol of the same name",
name);
}
do
{
middle = (low + high) / 2;
@ -175,9 +184,10 @@ reg_name_search (name)
else if (cmp > 0)
low = middle + 1;
else
return pre_defined_registers[middle].value;
return pre_defined_registers[middle].value;
}
while (low <= high);
return -1;
}
@ -263,8 +273,10 @@ md_show_usage (stream)
fprintf (stream, _("\nD30V options:\n\
-O Make adjacent short instructions parallel if possible.\n\
-n Warn about all NOPs inserted by the assembler.\n\
-N Warn about NOPs inserted after word multiplies.\n"));
}
-N Warn about NOPs inserted after word multiplies.\n\
-c Warn about symbols whoes names match register names.\n\
-C Opposite of -C. -c is the default.\n"));
}
int
md_parse_option (c, arg)
@ -289,6 +301,14 @@ md_parse_option (c, arg)
warn_nops = NOP_MULTIPLY;
break;
case 'c':
warn_register_name_conflicts = 1;
break;
case 'C':
warn_register_name_conflicts = 0;
break;
default:
return 0;
}
@ -663,26 +683,46 @@ write_long (opcode, insn, fx)
}
/* write out a short form instruction by itself */
/* Write out a short form instruction by itself. */
static void
write_1_short (opcode, insn, fx)
write_1_short (opcode, insn, fx, use_sequential)
struct d30v_insn *opcode;
long long insn;
Fixups *fx;
int use_sequential;
{
char *f = frag_more (8);
int i, where;
if (warn_nops == NOP_ALL)
as_warn (_("NOP inserted"));
as_warn (_("%s NOP inserted"), use_sequential ?
_("sequential") : _("parallel"));
/* the other container needs to be NOP */
/* according to 4.3.1: for FM=00, sub-instructions performed only
by IU cannot be encoded in L-container. */
/* The other container needs to be NOP. */
if (use_sequential)
{
/* Use a sequential NOP rather than a parallel one,
as the current instruction is a FLAG_MUL32 type one
and the next instruction is a load. */
/* According to 4.3.1: for FM=01, sub-instructions performed
only by IU cannot be encoded in L-container. */
if (opcode->op->unit == IU)
insn |= FM10 | NOP_LEFT; /* right then left */
else
insn = FM01 | (insn << 32) | NOP_RIGHT; /* left then right */
}
else
{
/* According to 4.3.1: for FM=00, sub-instructions performed
only by IU cannot be encoded in L-container. */
if (opcode->op->unit == IU)
insn |= FM00 | NOP_LEFT; /* right container */
else
insn = FM00 | (insn << 32) | NOP_RIGHT; /* left container */
}
d30v_number_to_chars (f, insn, 8);
@ -720,8 +760,8 @@ write_2_short (opcode1, insn1, opcode2, insn2, exec_type, fx)
{
/* subroutines must be called from 32-bit boundaries */
/* so the return address will be correct */
write_1_short (opcode1, insn1, fx->next);
return (1);
write_1_short (opcode1, insn1, fx->next, false);
return 1;
}
switch (exec_type)
@ -1097,7 +1137,7 @@ md_assemble (str)
if ((prev_insn != -1) && prev_seg
&& ((prev_seg != now_seg) || (prev_subseg != now_subseg)))
d30v_cleanup ();
d30v_cleanup (false);
if (d30v_current_align < 3)
d30v_align (3, NULL, d30v_last_label);
@ -1135,7 +1175,7 @@ md_assemble (str)
/* if two instructions are present and we already have one saved
then first write it out */
d30v_cleanup ();
d30v_cleanup (false);
/* assemble first instruction and save it */
prev_insn = do_assemble (str, &prev_opcode, 1, 0);
@ -1193,29 +1233,32 @@ md_assemble (str)
else
{
/* Can't parallelize, flush previous instruction and emit a word of NOPS,
unless the previous instruction is a NOP, in whcih case just flush it,
unless the previous instruction is a NOP, in which case just flush it,
as this will generate a word of NOPs for us. */
if (prev_insn != -1 && (strcmp (prev_opcode.op->name, "nop") == 0))
{
d30v_cleanup ();
}
d30v_cleanup (false);
else
{
char * f;
d30v_cleanup ();
f = frag_more (8);
d30v_number_to_chars (f, NOP2, 8);
if (warn_nops == NOP_ALL || warn_nops == NOP_MULTIPLY)
if (prev_insn != -1)
d30v_cleanup (true);
else
{
if (opcode.op->flags_used & FLAG_MEM)
as_warn (_("word of NOPs added between word multiply and load"));
else
as_warn (_("word of NOPs added between word multiply and 16-bit multiply"));
f = frag_more (8);
d30v_number_to_chars (f, NOP2, 8);
if (warn_nops == NOP_ALL || warn_nops == NOP_MULTIPLY)
{
if (opcode.op->flags_used & FLAG_MEM)
as_warn (_("word of NOPs added between word multiply and load"));
else
as_warn (_("word of NOPs added between word multiply and 16-bit multiply"));
}
}
}
extype = EXEC_UNKNOWN;
}
}
@ -1223,23 +1266,8 @@ md_assemble (str)
&& cur_mul32_p
&& (prev_opcode.op->flags_used & (FLAG_MEM | FLAG_MUL16)))
{
/* Can't parallelize, flush current instruction and emit a word of NOPS */
write_1_short (& opcode, (long) insn, fixups->next->next);
if (strcmp (opcode.op->name, "nop") != 0)
{
char * f;
f = frag_more (8);
d30v_number_to_chars (f, NOP2, 8);
if (warn_nops == NOP_ALL || warn_nops == NOP_MULTIPLY)
{
if (opcode.op->flags_used & FLAG_MEM)
as_warn (_("word of NOPs added between word multiply and load"));
else
as_warn (_("word of NOPs added between word multiply and 16-bit multiply"));
}
}
/* Can't parallelize, flush current instruction and add a sequential NOP. */
write_1_short (& opcode, (long) insn, fixups->next->next, true);
/* Make the previous instruction the current one. */
extype = EXEC_UNKNOWN;
@ -1249,6 +1277,7 @@ md_assemble (str)
prev_insn = -1;
cur_mul32_p = prev_mul32_p;
prev_mul32_p = 0;
memcpy (&opcode, &prev_opcode, sizeof (prev_opcode));
}
/* If this is a long instruction, write it and any previous short instruction. */
@ -1256,7 +1285,7 @@ md_assemble (str)
{
if (extype != EXEC_UNKNOWN)
as_fatal (_("Unable to mix instructions as specified"));
d30v_cleanup ();
d30v_cleanup (false);
write_long (&opcode, insn, fixups);
prev_insn = -1;
}
@ -1512,7 +1541,9 @@ find_format (opcode, myops, fsize, cmp_hack)
{
if (X_op != O_register
|| ((flags & OPERAND_ACC) && !(num & OPERAND_ACC))
|| (!(flags & OPERAND_ACC) && (num & OPERAND_ACC))
|| ((flags & OPERAND_FLAG) && !(num & OPERAND_FLAG))
|| (!(flags & OPERAND_FLAG) && (num & OPERAND_FLAG))
|| ((flags & OPERAND_CONTROL)
&& !(num & (OPERAND_CONTROL | OPERAND_FLAG))))
{
@ -1536,6 +1567,15 @@ find_format (opcode, myops, fsize, cmp_hack)
{
/* A number can be a constant or symbol expression. */
/* If we have found a register name, but that name also
matches a symbol, then re-parse the name as an expression. */
if (X_op == O_register
&& symbol_find ((char *) myops[j].X_op_symbol))
{
input_line_pointer = (char *) myops[j].X_op_symbol;
expression (& myops[j]);
}
/* Turn an expression into a symbol for later resolution. */
if (X_op != O_absent && X_op != O_constant
&& X_op != O_symbol && X_op != O_register
@ -1795,7 +1835,8 @@ md_apply_fix3 (fixp, valuep, seg)
instructions to see if it can package them with the next instruction, there may
be a short instruction that still needs written. */
int
d30v_cleanup ()
d30v_cleanup (use_sequential)
int use_sequential;
{
segT seg;
subsegT subseg;
@ -1805,9 +1846,11 @@ d30v_cleanup ()
seg = now_seg;
subseg = now_subseg;
subseg_set (prev_seg, prev_subseg);
write_1_short (&prev_opcode, (long)prev_insn, fixups->next);
write_1_short (&prev_opcode, (long)prev_insn, fixups->next, use_sequential);
subseg_set (seg, subseg);
prev_insn = -1;
if (use_sequential)
prev_mul32_p = false;
}
return 1;
}
@ -1840,7 +1883,7 @@ d30v_start_line ()
c++;
if (*c == '.')
d30v_cleanup ();
d30v_cleanup (false);
}
static void
@ -1872,7 +1915,7 @@ d30v_frob_label (lab)
symbolS *lab;
{
/* Emit any pending instructions. */
d30v_cleanup ();
d30v_cleanup (false);
/* Update the label's address with the current output pointer. */
lab->sy_frag = frag_now;
@ -1923,7 +1966,7 @@ d30v_align (n, pfill, label)
can be changed under our feet, for example by a .ascii
directive in the source code. cf testsuite/gas/d30v/reloc.s */
d30v_cleanup ();
d30v_cleanup (false);
if (pfill == NULL)
{