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 start-sanitize-sky
Mon Sep 21 13:08:01 1998 Doug Evans <devans@canuck.cygnus.com> 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 comment_chars[] = ";";
const char line_comment_chars[] = "#"; const char line_comment_chars[] = "#";
const char line_separator_chars[] = ""; const char line_separator_chars[] = "";
const char *md_shortopts = "OnN"; const char *md_shortopts = "OnNcC";
const char EXP_CHARS[] = "eE"; const char EXP_CHARS[] = "eE";
const char FLT_CHARS[] = "dD"; const char FLT_CHARS[] = "dD";
@ -36,6 +36,7 @@ const char FLT_CHARS[] = "dD";
#define NOP_ALL 2 #define NOP_ALL 2
static int warn_nops = 0; static int warn_nops = 0;
static int Optimizing = 0; static int Optimizing = 0;
static int warn_register_name_conflicts = 1;
#define FORCE_SHORT 1 #define FORCE_SHORT 1
#define FORCE_LONG 2 #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)); expressionS ops[],int fsize, int cmp_hack));
static long long build_insn PARAMS ((struct d30v_insn *opcode, expressionS *opers)); 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_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, 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)); 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, static long long do_assemble PARAMS ((char *str, struct d30v_insn *opcode,
@ -166,6 +168,13 @@ reg_name_search (name)
low = 0; low = 0;
high = reg_name_cnt () - 1; 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 do
{ {
middle = (low + high) / 2; middle = (low + high) / 2;
@ -175,9 +184,10 @@ reg_name_search (name)
else if (cmp > 0) else if (cmp > 0)
low = middle + 1; low = middle + 1;
else else
return pre_defined_registers[middle].value; return pre_defined_registers[middle].value;
} }
while (low <= high); while (low <= high);
return -1; return -1;
} }
@ -263,8 +273,10 @@ md_show_usage (stream)
fprintf (stream, _("\nD30V options:\n\ fprintf (stream, _("\nD30V options:\n\
-O Make adjacent short instructions parallel if possible.\n\ -O Make adjacent short instructions parallel if possible.\n\
-n Warn about all NOPs inserted by the assembler.\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 int
md_parse_option (c, arg) md_parse_option (c, arg)
@ -289,6 +301,14 @@ md_parse_option (c, arg)
warn_nops = NOP_MULTIPLY; warn_nops = NOP_MULTIPLY;
break; break;
case 'c':
warn_register_name_conflicts = 1;
break;
case 'C':
warn_register_name_conflicts = 0;
break;
default: default:
return 0; 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 static void
write_1_short (opcode, insn, fx) write_1_short (opcode, insn, fx, use_sequential)
struct d30v_insn *opcode; struct d30v_insn *opcode;
long long insn; long long insn;
Fixups *fx; Fixups *fx;
int use_sequential;
{ {
char *f = frag_more (8); char *f = frag_more (8);
int i, where; int i, where;
if (warn_nops == NOP_ALL) 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 */ /* The other container needs to be NOP. */
/* according to 4.3.1: for FM=00, sub-instructions performed only if (use_sequential)
by IU cannot be encoded in L-container. */ {
/* 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) if (opcode->op->unit == IU)
insn |= FM00 | NOP_LEFT; /* right container */ insn |= FM00 | NOP_LEFT; /* right container */
else else
insn = FM00 | (insn << 32) | NOP_RIGHT; /* left container */ insn = FM00 | (insn << 32) | NOP_RIGHT; /* left container */
}
d30v_number_to_chars (f, insn, 8); 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 */ /* subroutines must be called from 32-bit boundaries */
/* so the return address will be correct */ /* so the return address will be correct */
write_1_short (opcode1, insn1, fx->next); write_1_short (opcode1, insn1, fx->next, false);
return (1); return 1;
} }
switch (exec_type) switch (exec_type)
@ -1097,7 +1137,7 @@ md_assemble (str)
if ((prev_insn != -1) && prev_seg if ((prev_insn != -1) && prev_seg
&& ((prev_seg != now_seg) || (prev_subseg != now_subseg))) && ((prev_seg != now_seg) || (prev_subseg != now_subseg)))
d30v_cleanup (); d30v_cleanup (false);
if (d30v_current_align < 3) if (d30v_current_align < 3)
d30v_align (3, NULL, d30v_last_label); 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 /* if two instructions are present and we already have one saved
then first write it out */ then first write it out */
d30v_cleanup (); d30v_cleanup (false);
/* assemble first instruction and save it */ /* assemble first instruction and save it */
prev_insn = do_assemble (str, &prev_opcode, 1, 0); prev_insn = do_assemble (str, &prev_opcode, 1, 0);
@ -1193,29 +1233,32 @@ md_assemble (str)
else else
{ {
/* Can't parallelize, flush previous instruction and emit a word of NOPS, /* 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. */ as this will generate a word of NOPs for us. */
if (prev_insn != -1 && (strcmp (prev_opcode.op->name, "nop") == 0)) if (prev_insn != -1 && (strcmp (prev_opcode.op->name, "nop") == 0))
{ d30v_cleanup (false);
d30v_cleanup ();
}
else else
{ {
char * f; char * f;
d30v_cleanup (); if (prev_insn != -1)
d30v_cleanup (true);
f = frag_more (8); else
d30v_number_to_chars (f, NOP2, 8);
if (warn_nops == NOP_ALL || warn_nops == NOP_MULTIPLY)
{ {
if (opcode.op->flags_used & FLAG_MEM) f = frag_more (8);
as_warn (_("word of NOPs added between word multiply and load")); d30v_number_to_chars (f, NOP2, 8);
else
as_warn (_("word of NOPs added between word multiply and 16-bit multiply")); 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; extype = EXEC_UNKNOWN;
} }
} }
@ -1223,23 +1266,8 @@ md_assemble (str)
&& cur_mul32_p && cur_mul32_p
&& (prev_opcode.op->flags_used & (FLAG_MEM | FLAG_MUL16))) && (prev_opcode.op->flags_used & (FLAG_MEM | FLAG_MUL16)))
{ {
/* Can't parallelize, flush current instruction and emit a word of NOPS */ /* Can't parallelize, flush current instruction and add a sequential NOP. */
write_1_short (& opcode, (long) insn, fixups->next->next); write_1_short (& opcode, (long) insn, fixups->next->next, true);
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"));
}
}
/* Make the previous instruction the current one. */ /* Make the previous instruction the current one. */
extype = EXEC_UNKNOWN; extype = EXEC_UNKNOWN;
@ -1249,6 +1277,7 @@ md_assemble (str)
prev_insn = -1; prev_insn = -1;
cur_mul32_p = prev_mul32_p; cur_mul32_p = prev_mul32_p;
prev_mul32_p = 0; prev_mul32_p = 0;
memcpy (&opcode, &prev_opcode, sizeof (prev_opcode));
} }
/* If this is a long instruction, write it and any previous short instruction. */ /* If this is a long instruction, write it and any previous short instruction. */
@ -1256,7 +1285,7 @@ md_assemble (str)
{ {
if (extype != EXEC_UNKNOWN) if (extype != EXEC_UNKNOWN)
as_fatal (_("Unable to mix instructions as specified")); as_fatal (_("Unable to mix instructions as specified"));
d30v_cleanup (); d30v_cleanup (false);
write_long (&opcode, insn, fixups); write_long (&opcode, insn, fixups);
prev_insn = -1; prev_insn = -1;
} }
@ -1512,7 +1541,9 @@ find_format (opcode, myops, fsize, cmp_hack)
{ {
if (X_op != O_register if (X_op != O_register
|| ((flags & OPERAND_ACC) && !(num & OPERAND_ACC)) || ((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_FLAG) && (num & OPERAND_FLAG))
|| ((flags & OPERAND_CONTROL) || ((flags & OPERAND_CONTROL)
&& !(num & (OPERAND_CONTROL | OPERAND_FLAG)))) && !(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. */ /* 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. */ /* Turn an expression into a symbol for later resolution. */
if (X_op != O_absent && X_op != O_constant if (X_op != O_absent && X_op != O_constant
&& X_op != O_symbol && X_op != O_register && 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 instructions to see if it can package them with the next instruction, there may
be a short instruction that still needs written. */ be a short instruction that still needs written. */
int int
d30v_cleanup () d30v_cleanup (use_sequential)
int use_sequential;
{ {
segT seg; segT seg;
subsegT subseg; subsegT subseg;
@ -1805,9 +1846,11 @@ d30v_cleanup ()
seg = now_seg; seg = now_seg;
subseg = now_subseg; subseg = now_subseg;
subseg_set (prev_seg, prev_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); subseg_set (seg, subseg);
prev_insn = -1; prev_insn = -1;
if (use_sequential)
prev_mul32_p = false;
} }
return 1; return 1;
} }
@ -1840,7 +1883,7 @@ d30v_start_line ()
c++; c++;
if (*c == '.') if (*c == '.')
d30v_cleanup (); d30v_cleanup (false);
} }
static void static void
@ -1872,7 +1915,7 @@ d30v_frob_label (lab)
symbolS *lab; symbolS *lab;
{ {
/* Emit any pending instructions. */ /* Emit any pending instructions. */
d30v_cleanup (); d30v_cleanup (false);
/* Update the label's address with the current output pointer. */ /* Update the label's address with the current output pointer. */
lab->sy_frag = frag_now; 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 can be changed under our feet, for example by a .ascii
directive in the source code. cf testsuite/gas/d30v/reloc.s */ directive in the source code. cf testsuite/gas/d30v/reloc.s */
d30v_cleanup (); d30v_cleanup (false);
if (pfill == NULL) if (pfill == NULL)
{ {