d10v fixes.

This commit is contained in:
Tom Rix 2002-05-30 16:16:30 +00:00
parent 8c2784a5a4
commit 8ade06a814
2 changed files with 77 additions and 72 deletions

View File

@ -1,3 +1,16 @@
2002-05-30 Diego Novillo <dnovillo@redhat.com>
* gas/config/tc-d10v.c (check_resource_conflict): Only check
write-write conflicts.
(md_assemble): Reformat introductory comment.
(parallel_ok): Prevent packing only if the first
instruction cannot be packed.
2002-05-30 Jason Eckhardt <jle@redhat.com>
Tom Rix <trix@redhat.com>
* config/tc-d10v.c (build_insn): Check for immediates.
2002-05-28 Thiemo Seufer <seufer@csv.ica.uni-stuttgart.de>
* config/tc-mips.c: Replace GP in comments by $gp.

View File

@ -99,9 +99,9 @@ static int parallel_ok PARAMS ((struct d10v_opcode *opcode1, unsigned long insn1
struct d10v_opcode *opcode2, unsigned long insn2,
packing_type exec_type));
static void check_resource_conflict PARAMS ((struct d10v_opcode *opcode1,
unsigned long insn1,
struct d10v_opcode *opcode2,
static void check_resource_conflict PARAMS ((struct d10v_opcode *opcode1,
unsigned long insn1,
struct d10v_opcode *opcode2,
unsigned long insn2));
static symbolS * find_symbol_matching_register PARAMS ((expressionS *));
@ -647,8 +647,15 @@ build_insn (opcode, opers, insn)
opers[i].X_add_number = number;
}
else
fixups->fix[fixups->fc].reloc =
get_reloc ((struct d10v_operand *) &d10v_operands[opcode->operands[i]]);
{
fixups->fix[fixups->fc].reloc =
get_reloc ((struct d10v_operand *) &d10v_operands[opcode->operands[i]]);
/* Check that a immediate was passed to ops that expect one. */
if ((flags & OPERAND_NUM)
&& (fixups->fix[fixups->fc].reloc == 0))
as_bad (_("operand is not an immediate"));
}
if (fixups->fix[fixups->fc].reloc == BFD_RELOC_16 ||
fixups->fix[fixups->fc].reloc == BFD_RELOC_D10V_18)
@ -662,7 +669,7 @@ build_insn (opcode, opers, insn)
(flags & OPERAND_ADDR) ? true : false;
(fixups->fc)++;
}
/* Truncate to the proper number of bits. */
if ((opers[i].X_op == O_constant) && check_range (number, bits, flags))
as_bad (_("operand out of range: %lu"), number);
@ -670,8 +677,8 @@ build_insn (opcode, opers, insn)
insn = insn | (number << shift);
}
/* kludge: for DIVS, we need to put the operands in twice on the second
pass, format is changed to LONG_R to force the second set of operands
/* kludge: for DIVS, we need to put the operands in twice on the second
pass, format is changed to LONG_R to force the second set of operands
to not be shifted over 15. */
if ((opcode->opcode == OPCODE_DIVS) && (format == LONG_L))
insn = build_insn (opcode, opers, insn);
@ -728,8 +735,8 @@ write_1_short (opcode, insn, fx)
if (opcode->exec_type & PARONLY)
as_fatal (_("Instruction must be executed in parallel with another instruction."));
/* The other container needs to be NOP.
According to 4.3.1: for FM=00, sub-instructions performed only by IU
/* 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. */
if (opcode->unit == IU)
insn |= FM00 | (NOP << 15); /* Right container. */
@ -941,11 +948,10 @@ parallel_ok (op1, insn1, op2, insn2, exec_type)
|| (op1->unit == MU && op2->unit == MU))
return 0;
/* If this is auto parallization, and either instruction is a branch,
don't parallel. */
/* If this is auto parallelization, and the first instruction is a
branch or should not be packed, then don't parallelize. */
if (exec_type == PACK_UNSPEC
&& (op1->exec_type & (ALONE | BRANCH)
|| op2->exec_type & (ALONE | BRANCH)))
&& (op1->exec_type & (ALONE | BRANCH)))
return 0;
/* The idea here is to create two sets of bitmasks (mod and used)
@ -963,8 +969,8 @@ parallel_ok (op1, insn1, op2, insn2, exec_type)
and the second reads the PSW (which includes C, F0, and F1), then
they cannot operate safely in parallel. */
/* The bitmasks (mod and used) look like this (bit 31 = MSB).
r0-r15 0-15
/* The bitmasks (mod and used) look like this (bit 31 = MSB).
r0-r15 0-15
a0-a1 16-17
cr (not psw) 18
psw 19
@ -1051,13 +1057,13 @@ parallel_ok (op1, insn1, op2, insn2, exec_type)
/* Determine if there are any resource conflicts among two manually
parallelized instructions. Some of this was lifted from parallel_ok. */
static void
static void
check_resource_conflict (op1, insn1, op2, insn2)
struct d10v_opcode *op1, *op2;
unsigned long insn1, insn2;
{
int i, j, flags, mask, shift, regno;
unsigned long ins, mod[2], used[2];
unsigned long ins, mod[2];
struct d10v_opcode *op;
if ((op1->exec_type & SEQ)
@ -1076,20 +1082,17 @@ check_resource_conflict (op1, insn1, op2, insn2)
return;
}
/* The idea here is to create two sets of bitmasks (mod and used)
which indicate which registers are modified or used by each
instruction. The operation can only be done in parallel if
instruction 1 and instruction 2 modify different registers, and
the first instruction does not modify registers that the second
is using (The second instruction can modify registers that the
first is using as they are only written back after the first
instruction has completed). Accesses to control registers
and memory are treated as accesses to a single register. So if
both instructions write memory or if the first instruction writes
memory and the second reads, then they cannot be done in
parallel. We treat reads to the PSW (which includes C, F0, and F1)
in isolation. So simultaneously writing C and F0 in two different
sub-instructions is permitted. */
/* See if both instructions write to the same resource.
The idea here is to create two sets of bitmasks (mod and used) which
indicate which registers are modified or used by each instruction.
The operation can only be done in parallel if neither instruction
modifies the same register. Accesses to control registers and memory
are treated as accesses to a single register. So if both instructions
write memory or if the first instruction writes memory and the second
reads, then they cannot be done in parallel. We treat reads to the PSW
(which includes C, F0, and F1) in isolation. So simultaneously writing
C and F0 in two different sub-instructions is permitted. */
/* The bitmasks (mod and used) look like this (bit 31 = MSB).
r0-r15 0-15
@ -1112,7 +1115,7 @@ check_resource_conflict (op1, insn1, op2, insn2)
op = op2;
ins = insn2;
}
mod[j] = used[j] = 0;
mod[j] = 0;
if (op->exec_type & BRANCH_LINK)
mod[j] |= 1 << 13;
@ -1127,54 +1130,43 @@ check_resource_conflict (op1, insn1, op2, insn2)
if (flags & (OPERAND_ACC0 | OPERAND_ACC1))
regno += 16;
else if (flags & OPERAND_CONTROL) /* mvtc or mvfc */
{
{
if (regno == 0)
regno = 19;
else
regno = 18;
regno = 18;
}
else if (flags & OPERAND_FFLAG)
regno = 22;
else if (flags & OPERAND_CFLAG)
regno = 21;
if ( flags & OPERAND_DEST )
if (flags & OPERAND_DEST
/* Auto inc/dec also modifies the register. */
|| (op->operands[i + 1] != 0
&& (d10v_operands[op->operands[i + 1]].flags
& (OPERAND_PLUS | OPERAND_MINUS)) != 0))
{
mod[j] |= 1 << regno;
if (flags & OPERAND_EVEN)
mod[j] |= 1 << (regno + 1);
}
else
{
used[j] |= 1 << regno ;
if (flags & OPERAND_EVEN)
used[j] |= 1 << (regno + 1);
/* Auto inc/dec also modifies the register. */
if (op->operands[i+1] != 0
&& (d10v_operands[op->operands[i+1]].flags
& (OPERAND_PLUS | OPERAND_MINUS)) != 0)
mod[j] |= 1 << regno;
}
}
else if (flags & OPERAND_ATMINUS)
{
/* SP implicitly used/modified. */
mod[j] |= 1 << 15;
used[j] |= 1 << 15;
}
}
if (op->exec_type & RMEM)
used[j] |= 1 << 20;
else if (op->exec_type & WMEM)
if (op->exec_type & WMEM)
mod[j] |= 1 << 20;
else if (op->exec_type & RF0)
used[j] |= 1 << 22;
else if (op->exec_type & WF0)
mod[j] |= 1 << 22;
else if (op->exec_type & WCAR)
mod[j] |= 1 << 21;
}
if ((mod[0] & mod[1]) == 0)
return;
else
@ -1198,7 +1190,7 @@ check_resource_conflict (op1, insn1, op2, insn2)
}
/* This is the main entry point for the machine-dependent assembler.
STR points to a machine-dependent instruction. This function is
str points to a machine-dependent instruction. This function is
supposed to emit the frags/bytes it assembles to. For the D10V, it
mostly handles the special VLIW parsing and packing and leaves the
difficult stuff to do_assemble(). */
@ -1294,7 +1286,7 @@ md_assemble (str)
d10v_cleanup ();
if (prev_opcode
&& (0 == write_2_short (prev_opcode, prev_insn, opcode, insn, extype,
&& (0 == write_2_short (prev_opcode, prev_insn, opcode, insn, extype,
fixups)))
{
/* No instructions saved. */
@ -1520,7 +1512,7 @@ find_opcode (opcode, myops)
}
match = 0;
/* Now search the opcode table table for one with operands
that matches what we've got. */
while (!match)
@ -1562,19 +1554,19 @@ find_opcode (opcode, myops)
break;
}
/* Unfortunatly, for the indirect operand in instructions such
as ``ldb r1, @(c,r14)'' this function can be passed
X_op == O_register (because 'c' is a valid register name).
However we cannot just ignore the case when X_op == O_register
but flags & OPERAND_REG is null, so we check to see if a symbol
of the same name as the register exists. If the symbol does
exist, then the parser was unable to distinguish the two cases
/* Unfortunatly, for the indirect operand in instructions such
as ``ldb r1, @(c,r14)'' this function can be passed
X_op == O_register (because 'c' is a valid register name).
However we cannot just ignore the case when X_op == O_register
but flags & OPERAND_REG is null, so we check to see if a symbol
of the same name as the register exists. If the symbol does
exist, then the parser was unable to distinguish the two cases
and we fix things here. (Ref: PR14826) */
if (!(flags & OPERAND_REG) && (X_op == O_register))
{
symbolS * sym;
sym = find_symbol_matching_register (& myops[i]);
if (sym != NULL)
@ -1769,13 +1761,13 @@ md_apply_fix3 (fixP, valP, seg)
XXX - Do we have to worry about branches to a symbol + offset ? */
if (fixP->fx_addsy != NULL
&& S_IS_EXTERN (fixP->fx_addsy) )
{
segT fseg = S_GET_SEGMENT (fixP->fx_addsy);
segment_info_type *segf = seg_info(fseg);
{
segT fseg = S_GET_SEGMENT (fixP->fx_addsy);
segment_info_type *segf = seg_info(fseg);
if ( segf && segf->sym != fixP->fx_addsy)
value = 0;
}
}
/* Drop through. */
case BFD_RELOC_D10V_18:
/* Instruction addresses are always right-shifted by 2. */
@ -1789,9 +1781,9 @@ md_apply_fix3 (fixP, valP, seg)
rep = (struct d10v_opcode *) hash_find (d10v_hash, "rep");
repi = (struct d10v_opcode *) hash_find (d10v_hash, "repi");
if ((insn & FM11) == FM11
&& ((repi != NULL
&& ((repi != NULL
&& (insn & repi->mask) == (unsigned) repi->opcode)
|| (rep != NULL
|| (rep != NULL
&& (insn & rep->mask) == (unsigned) rep->opcode))
&& value < 4)
as_fatal