From aa7bf2a890bb3365a79d57b03eb479826a160769 Mon Sep 17 00:00:00 2001 From: Nick Clifton Date: Tue, 22 Sep 1998 22:48:42 +0000 Subject: [PATCH] Fix PR 17135 (whilst keeping PR14827 fixed) by prefering register names over symbolic names, except where the register name is unacceptable. --- gas/ChangeLog | 11 ++++ gas/config/tc-d30v.c | 145 ++++++++++++++++++++++++++++--------------- 2 files changed, 105 insertions(+), 51 deletions(-) diff --git a/gas/ChangeLog b/gas/ChangeLog index 2f71e920b9..a9bb037c7d 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,3 +1,14 @@ +Tue Sep 22 15:44:21 1998 Nick Clifton + + * 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 diff --git a/gas/config/tc-d30v.c b/gas/config/tc-d30v.c index e0b5959b7e..b0f81bc163 100644 --- a/gas/config/tc-d30v.c +++ b/gas/config/tc-d30v.c @@ -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) { -- 2.34.1