mirror of
https://github.com/espressif/binutils-gdb.git
synced 2025-07-15 05:01:13 +08:00
Foixes for PR16116 and ER15940 - improve parallel insn handling.
This commit is contained in:
@ -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);
|
||||
}
|
||||
|
Reference in New Issue
Block a user