mirror of
https://github.com/espressif/binutils-gdb.git
synced 2025-06-28 23:39:35 +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
|
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>
|
||||||
|
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user