summaryrefslogtreecommitdiff
path: root/gas/config/tc-rx.c
diff options
context:
space:
mode:
authorDJ Delorie <dj@delorie.com>2010-12-17 04:16:55 +0000
committerDJ Delorie <dj@delorie.com>2010-12-17 04:16:55 +0000
commit19d6c3db22c88adfdda98e84408363210050d464 (patch)
treeab7da4408714b009afb8fd9074ceba19280580bf /gas/config/tc-rx.c
parent44d9b21d53efe92f5afe4f1816226c4d43533be9 (diff)
downloadbinutils-redhat-19d6c3db22c88adfdda98e84408363210050d464.tar.gz
* 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).
Diffstat (limited to 'gas/config/tc-rx.c')
-rw-r--r--gas/config/tc-rx.c26
1 files changed, 22 insertions, 4 deletions
diff --git a/gas/config/tc-rx.c b/gas/config/tc-rx.c
index 125686fbdc..aa582869d5 100644
--- a/gas/config/tc-rx.c
+++ b/gas/config/tc-rx.c
@@ -1943,10 +1943,14 @@ md_convert_frag (bfd * abfd ATTRIBUTE_UNUSED,
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_UNUSED, fixS * fixp)
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_UNUSED, fixS * fixp)
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;