Foixes for PR16116 and ER15940 - improve parallel insn handling.

This commit is contained in:
Nick Clifton
1998-06-09 01:33:23 +00:00
parent f79ebb2c0f
commit 7a0f469b1c
2 changed files with 118 additions and 61 deletions

@ -1,3 +1,13 @@
Mon Jun 8 18:32:01 1998 Nick Clifton <nickc@cygnus.com>
* config/tc-d30v.c (md_assemble): Fix handling of reverse
sequential word multiply instructions.
(do_assemble): Add extra command line argument, to allow mul32
attribute to be preserved across parallel insns.
(md_assemble): Insert NOPs between explicitly parallel insns which
contain an 32 bit multiply and a 16 multiply.
start-sanitize-sky
Mon Jun 8 15:41:43 1998 Doug Evans <devans@canuck.cygnus.com>

@ -111,7 +111,7 @@ static void write_1_short PARAMS ((struct d30v_insn *opcode, long long insn, Fix
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,
int shortp));
int shortp, int is_parallel));
static int parallel_ok PARAMS ((struct d30v_insn *opcode1, unsigned long insn1,
struct d30v_insn *opcode2, unsigned long insn2,
exec_type_enum exec_type));
@ -1119,7 +1119,7 @@ md_assemble (str)
d30v_cleanup ();
/* assemble first instruction and save it */
prev_insn = do_assemble (str, &prev_opcode, 1);
prev_insn = do_assemble (str, &prev_opcode, 1, 0);
if (prev_insn == -1)
as_fatal (_("Cannot assemble instruction"));
if (prev_opcode.form->form >= LONG)
@ -1132,7 +1132,8 @@ md_assemble (str)
}
insn = do_assemble (str, &opcode,
(extype != EXEC_UNKNOWN || etype != EXEC_UNKNOWN));
(extype != EXEC_UNKNOWN || etype != EXEC_UNKNOWN),
extype == EXEC_PARALLEL);
if (insn == -1)
{
if (extype != EXEC_UNKNOWN)
@ -1151,11 +1152,12 @@ md_assemble (str)
/* Word multiply instructions must not be followed by either a load or a
16-bit multiply instruction in the next cycle. */
if (prev_mul32_p && (opcode.op->flags_used & (FLAG_MEM | FLAG_MUL16)))
if ( (extype != EXEC_REVSEQ)
&& prev_mul32_p
&& (opcode.op->flags_used & (FLAG_MEM | FLAG_MUL16)))
{
/* However, load and multiply should able to be combined in a parallel
operation, so check for that first. */
if (prev_insn != -1
&& (opcode.op->flags_used & FLAG_MEM)
&& opcode.form->form < LONG
@ -1169,11 +1171,20 @@ md_assemble (str)
prev_insn = -1;
return;
}
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,
as this will generate a word of NOPs for us. */
/* Can't parallelize, flush current instruction and emit a word of NOPS */
if (prev_insn != -1 && (strcmp (prev_opcode.op->name, "nop") == 0))
{
d30v_cleanup ();
}
else
{
char * f;
d30v_cleanup ();
f = frag_more (8);
@ -1185,33 +1196,63 @@ md_assemble (str)
else
as_warn (_("word of NOPs added between word multiply and 16-bit multiply"));
}
}
extype = EXEC_UNKNOWN;
}
}
else if ( (extype == EXEC_REVSEQ)
&& 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 this is a long instruction, write it and any previous short instruction */
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. */
extype = EXEC_UNKNOWN;
insn = prev_insn;
now_seg = prev_seg;
now_subseg = prev_subseg;
prev_insn = -1;
cur_mul32_p = prev_mul32_p;
prev_mul32_p = 0;
}
/* If this is a long instruction, write it and any previous short instruction. */
if (opcode.form->form >= LONG)
{
if (extype)
if (extype != EXEC_UNKNOWN)
as_fatal (_("Unable to mix instructions as specified"));
d30v_cleanup ();
write_long (&opcode, insn, fixups);
prev_insn = -1;
return;
}
if ((prev_insn != -1) &&
else if ((prev_insn != -1) &&
(write_2_short (&prev_opcode, (long)prev_insn, &opcode, (long)insn, extype, fixups) == 0))
{
/* no instructions saved */
/* No instructions saved. */
prev_insn = -1;
}
else
{
if (extype)
if (extype != EXEC_UNKNOWN)
as_fatal (_("Unable to mix instructions as specified"));
/* save off last instruction so it may be packed on next pass */
/* Save off last instruction so it may be packed on next pass. */
memcpy (&prev_opcode, &opcode, sizeof (prev_opcode));
prev_insn = insn;
prev_seg = now_seg;
@ -1225,10 +1266,11 @@ md_assemble (str)
/* it returns -1 (an invalid opcode) on error */
static long long
do_assemble (str, opcode, shortp)
do_assemble (str, opcode, shortp, is_parallel)
char *str;
struct d30v_insn *opcode;
int shortp;
int is_parallel;
{
unsigned char *op_start, *save;
unsigned char *op_end;
@ -1352,10 +1394,15 @@ do_assemble (str, opcode, shortp)
/* Propigate multiply status */
if (insn != -1)
{
if (is_parallel && prev_mul32_p)
cur_mul32_p = 1;
else
{
prev_mul32_p = cur_mul32_p;
cur_mul32_p = (opcode->op->flags_used & FLAG_MUL32) != 0;
}
}
return (insn);
}