This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
[patch] rx: add/fix subtraction-of-symbols relocs
- From: DJ Delorie <dj at redhat dot com>
- To: binutils at sourceware dot org
- Date: Thu, 16 Dec 2010 23:17:02 -0500
- Subject: [patch] rx: add/fix subtraction-of-symbols relocs
This patch fixes some bugs with subtraction-of-symbols, and adds
support for such in opcode operands. Applied.
* reloc.c (BFD_RELOC_RX_ABS16_REV): Add.
(BFD_RELOC_RX_ABS32_REV): Add.
* bfd-in2.h: Regenerate.
* libbfd.h: Regenerate.
* elf32-rx.c (rx_reloc_map): Add them.
* config/tc-rx.c (rx_validate_fix_sub): Permit subtraction in more
cases.
(tc_gen_reloc): Fix handling of subtraction (esp wrt endianness).
Index: bfd/bfd-in2.h
===================================================================
RCS file: /cvs/src/src/bfd/bfd-in2.h,v
retrieving revision 1.524
diff -p -U3 -r1.524 bfd-in2.h
--- bfd/bfd-in2.h 11 Nov 2010 10:23:35 -0000 1.524
+++ bfd/bfd-in2.h 17 Dec 2010 04:09:09 -0000
@@ -3991,7 +3991,9 @@ instructions */
BFD_RELOC_RX_OP_SUBTRACT,
BFD_RELOC_RX_ABS8,
BFD_RELOC_RX_ABS16,
+ BFD_RELOC_RX_ABS16_REV,
BFD_RELOC_RX_ABS32,
+ BFD_RELOC_RX_ABS32_REV,
BFD_RELOC_RX_ABS16U,
BFD_RELOC_RX_ABS16UW,
BFD_RELOC_RX_ABS16UL,
Index: bfd/elf32-rx.c
===================================================================
RCS file: /cvs/src/src/bfd/elf32-rx.c,v
retrieving revision 1.5
diff -p -U3 -r1.5 elf32-rx.c
--- bfd/elf32-rx.c 25 Oct 2010 15:54:14 -0000 1.5
+++ bfd/elf32-rx.c 17 Dec 2010 04:09:09 -0000
@@ -250,7 +250,9 @@ static const struct rx_reloc_map rx_relo
{ BFD_RELOC_RX_OP_SUBTRACT, R_RX_OPsub },
{ BFD_RELOC_RX_ABS8, R_RX_ABS8 },
{ BFD_RELOC_RX_ABS16, R_RX_ABS16 },
+ { BFD_RELOC_RX_ABS16_REV, R_RX_ABS16_REV },
{ BFD_RELOC_RX_ABS32, R_RX_ABS32 },
+ { BFD_RELOC_RX_ABS32_REV, R_RX_ABS32_REV },
{ BFD_RELOC_RX_ABS16UL, R_RX_ABS16UL },
{ BFD_RELOC_RX_ABS16UW, R_RX_ABS16UW },
{ BFD_RELOC_RX_ABS16U, R_RX_ABS16U }
Index: bfd/libbfd.h
===================================================================
RCS file: /cvs/src/src/bfd/libbfd.h,v
retrieving revision 1.243
diff -p -U3 -r1.243 libbfd.h
--- bfd/libbfd.h 29 Oct 2010 12:10:24 -0000 1.243
+++ bfd/libbfd.h 17 Dec 2010 04:09:10 -0000
@@ -1802,7 +1802,9 @@ static const char *const bfd_reloc_code_
"BFD_RELOC_RX_OP_SUBTRACT",
"BFD_RELOC_RX_ABS8",
"BFD_RELOC_RX_ABS16",
+ "BFD_RELOC_RX_ABS16_REV",
"BFD_RELOC_RX_ABS32",
+ "BFD_RELOC_RX_ABS32_REV",
"BFD_RELOC_RX_ABS16U",
"BFD_RELOC_RX_ABS16UW",
"BFD_RELOC_RX_ABS16UL",
Index: bfd/reloc.c
===================================================================
RCS file: /cvs/src/src/bfd/reloc.c,v
retrieving revision 1.208
diff -p -U3 -r1.208 reloc.c
--- bfd/reloc.c 29 Oct 2010 12:10:24 -0000 1.208
+++ bfd/reloc.c 17 Dec 2010 04:09:10 -0000
@@ -4262,8 +4262,12 @@ ENUMX
ENUMX
BFD_RELOC_RX_ABS16
ENUMX
+ BFD_RELOC_RX_ABS16_REV
+ENUMX
BFD_RELOC_RX_ABS32
ENUMX
+ BFD_RELOC_RX_ABS32_REV
+ENUMX
BFD_RELOC_RX_ABS16U
ENUMX
BFD_RELOC_RX_ABS16UW
Index: gas/config/tc-rx.c
===================================================================
RCS file: /cvs/src/src/gas/config/tc-rx.c,v
retrieving revision 1.5
diff -p -U3 -r1.5 tc-rx.c
--- gas/config/tc-rx.c 16 Jul 2010 06:32:46 -0000 1.5
+++ gas/config/tc-rx.c 17 Dec 2010 04:09:10 -0000
@@ -1943,10 +1943,14 @@ md_convert_frag (bfd * abfd ATTRIBUTE_
int
rx_validate_fix_sub (struct fix * f)
{
- /* We permit the subtraction of two symbols as a 32-bit relocation. */
+ /* We permit the subtraction of two symbols in a few cases. */
+ /* mov #sym1-sym2, R3 */
+ if (f->fx_r_type == BFD_RELOC_RX_32_OP)
+ return 1;
+ /* .long sym1-sym2 */
if (f->fx_r_type == BFD_RELOC_RX_DIFF
&& ! f->fx_pcrel
- && f->fx_size == 4)
+ && (f->fx_size == 4 || f->fx_size == 2 || f->fx_size == 1))
return 1;
return 0;
}
@@ -2206,6 +2210,7 @@ arelent **
tc_gen_reloc (asection * seg ATTRIBUTE_UNUSED, fixS * fixp)
{
static arelent * reloc[5];
+ int is_opcode = 0;
if (fixp->fx_r_type == BFD_RELOC_NONE)
{
@@ -2226,6 +2231,13 @@ tc_gen_reloc (asection * seg ATTRIBUTE_U
reloc[0]->address = fixp->fx_frag->fr_address + fixp->fx_where;
reloc[0]->addend = fixp->fx_offset;
+ if (fixp->fx_r_type == BFD_RELOC_RX_32_OP
+ && fixp->fx_subsy)
+ {
+ fixp->fx_r_type = BFD_RELOC_RX_DIFF;
+ is_opcode = 1;
+ }
+
/* Certain BFD relocations cannot be translated directly into
a single (non-Red Hat) RX relocation, but instead need
multiple RX relocations - handle them here. */
@@ -2254,10 +2266,16 @@ tc_gen_reloc (asection * seg ATTRIBUTE_U
reloc[3]->howto = bfd_reloc_type_lookup (stdoutput, BFD_RELOC_RX_ABS8);
break;
case 2:
- reloc[3]->howto = bfd_reloc_type_lookup (stdoutput, BFD_RELOC_RX_ABS16);
+ if (!is_opcode && target_big_endian)
+ reloc[3]->howto = bfd_reloc_type_lookup (stdoutput, BFD_RELOC_RX_ABS16_REV);
+ else
+ reloc[3]->howto = bfd_reloc_type_lookup (stdoutput, BFD_RELOC_RX_ABS16);
break;
case 4:
- reloc[3]->howto = bfd_reloc_type_lookup (stdoutput, BFD_RELOC_RX_ABS32);
+ if (!is_opcode && target_big_endian)
+ reloc[3]->howto = bfd_reloc_type_lookup (stdoutput, BFD_RELOC_RX_ABS32_REV);
+ else
+ reloc[3]->howto = bfd_reloc_type_lookup (stdoutput, BFD_RELOC_RX_ABS32);
break;
}
reloc[3]->addend = 0;