This is the mail archive of the
binutils@sources.redhat.com
mailing list for the binutils project.
d10v: swapping insns requires swapping relocs
- From: Alexandre Oliva <aoliva at redhat dot com>
- To: binutils at sources dot redhat dot com
- Date: 29 Nov 2001 15:20:51 -0200
- Subject: d10v: swapping insns requires swapping relocs
- Organization: GCC Team, Red Hat
The d10v assembler may sometimes swap instructions in a package
without adjusting the relocations. Therefore, it may happen that a
10_PCREL_[LR] relocation ends up being applied to the wrong container.
This patch is supposed to fix all such situations, but I'm not
positive fx always points to the right fix-ups. There were no
regressions in the testsuite, FWIW. I'd appreciate a careful look at
these patches from someone who better understands what's going on. Ok
to install?
Index: gas/ChangeLog
from Alexandre Oliva <aoliva@redhat.com>
* config/tc-d10v.c (write_2_short): Mark L reloc insn when
L and R are swapped.
Index: gas/config/tc-d10v.c
===================================================================
RCS file: /cvs/src/src/gas/config/tc-d10v.c,v
retrieving revision 1.19
diff -u -p -r1.19 tc-d10v.c
--- gas/config/tc-d10v.c 2001/11/15 21:28:55 1.19
+++ gas/config/tc-d10v.c 2001/11/29 17:16:02
@@ -767,6 +767,7 @@ write_2_short (opcode1, insn1, opcode2,
unsigned long insn;
char *f;
int i, j, where;
+ int swapped = 0;
if ((exec_type != PACK_PARALLEL)
&& ((opcode1->exec_type & PARONLY) || (opcode2->exec_type & PARONLY)))
@@ -790,9 +791,15 @@ write_2_short (opcode1, insn1, opcode2,
{
/* Parallel. */
if (opcode1->unit == IU)
- insn = FM00 | (insn2 << 15) | insn1;
+ {
+ swapped = 1;
+ insn = FM00 | (insn2 << 15) | insn1;
+ }
else if (opcode2->unit == MU)
- insn = FM00 | (insn2 << 15) | insn1;
+ {
+ swapped = 1;
+ insn = FM00 | (insn2 << 15) | insn1;
+ }
else
{
insn = FM00 | (insn1 << 15) | insn2;
@@ -801,8 +808,11 @@ write_2_short (opcode1, insn1, opcode2,
}
}
else if (opcode1->unit == IU)
- /* Reverse sequential with IU opcode1 on right and done first. */
- insn = FM10 | (insn2 << 15) | insn1;
+ {
+ /* Reverse sequential with IU opcode1 on right and done first. */
+ insn = FM10 | (insn2 << 15) | insn1;
+ swapped = 1;
+ }
else
{
/* Sequential with non-IU opcode1 on left and done first. */
@@ -822,6 +832,7 @@ write_2_short (opcode1, insn1, opcode2,
as_fatal (_("Two IU instructions may not be executed in parallel"));
if (!flag_warn_suppress_instructionswap)
as_warn (_("Swapping instruction order"));
+ swapped = 1;
insn = FM00 | (insn2 << 15) | insn1;
}
else if (opcode2->unit == MU)
@@ -830,6 +841,7 @@ write_2_short (opcode1, insn1, opcode2,
as_fatal (_("Two MU instructions may not be executed in parallel"));
if (!flag_warn_suppress_instructionswap)
as_warn (_("Swapping instruction order"));
+ swapped = 1;
insn = FM00 | (insn2 << 15) | insn1;
}
else
@@ -847,6 +859,7 @@ write_2_short (opcode1, insn1, opcode2,
{
if (!flag_warn_suppress_instructionswap)
as_warn (_("Swapping instruction order"));
+ swapped = 1;
insn = FM10 | (insn2 << 15) | insn1;
}
else
@@ -864,6 +877,7 @@ write_2_short (opcode1, insn1, opcode2,
{
if (!flag_warn_suppress_instructionswap)
as_warn (_("Swapping instruction order"));
+ swapped = 1;
insn = FM01 | (insn2 << 15) | insn1;
}
else
@@ -882,12 +896,7 @@ write_2_short (opcode1, insn1, opcode2,
number_to_chars_bigendian (f, insn, 4);
/* Process fixup chains.
- Note that the packing code above advanced fx conditionally.
- dlindsay@cygnus.com: There's something subtle going on here involving
- _dummy_first_bfd_reloc_code_real. This is related to the
- difference between BFD_RELOC_D10V_10_PCREL_R and _L, ie whether
- a fixup is done in the L or R container. A bug in this code
- can pass Plum Hall fine, yet still affect hand-written assembler. */
+ Note that the packing code above advanced fx conditionally. */
for (j = 0; j < 2; j++)
{
@@ -899,7 +908,14 @@ write_2_short (opcode1, insn1, opcode2,
if (fx->fix[i].size == 2)
where += 2;
- if ((fx->fix[i].reloc == BFD_RELOC_D10V_10_PCREL_R) && (j == 0))
+ /* A BFD_RELOC_D10V_10_PCREL_R relocation applied to the
+ instruction in the L container has to be adjusted to
+ BDF_RELOC_D10V_10_PCREL_L. When processing the L
+ container, j == 0, unless we swapped the containers,
+ in which case the L instruction gets j == 1, i.e.,
+ the L container gets j == swapped. */
+ if (fx->fix[i].reloc == BFD_RELOC_D10V_10_PCREL_R
+ && j == swapped)
fx->fix[i].operand |= 1024;
if (fx->fix[i].reloc == BFD_RELOC_D10V_18)
--
Alexandre Oliva Enjoy Guarana', see http://www.ic.unicamp.br/~oliva/
Red Hat GCC Developer aoliva@{cygnus.com, redhat.com}
CS PhD student at IC-Unicamp oliva@{lsd.ic.unicamp.br, gnu.org}
Free Software Evangelist *Please* write to mailing lists, not to me