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

View File

@ -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 start-sanitize-sky
Mon Jun 8 15:41:43 1998 Doug Evans <devans@canuck.cygnus.com> Mon Jun 8 15:41:43 1998 Doug Evans <devans@canuck.cygnus.com>

View File

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