diff options
author | DJ Delorie <dj@redhat.com> | 2010-12-17 04:17:00 +0000 |
---|---|---|
committer | DJ Delorie <dj@redhat.com> | 2010-12-17 04:17:00 +0000 |
commit | e8ef21bff548e7b307b7079d349f42187914d4b1 (patch) | |
tree | aab0bbebed6f76d1435f4dbc834152fd1b199ff8 /gas/config/tc-rx.c | |
parent | aeacb1880cc80f8d599ed11c09067b324f4926ca (diff) | |
download | gdb-e8ef21bff548e7b307b7079d349f42187914d4b1.zip gdb-e8ef21bff548e7b307b7079d349f42187914d4b1.tar.gz gdb-e8ef21bff548e7b307b7079d349f42187914d4b1.tar.bz2 |
* 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.c | 26 |
1 files changed, 22 insertions, 4 deletions
diff --git a/gas/config/tc-rx.c b/gas/config/tc-rx.c index 125686f..aa58286 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; |