From e8ef21bff548e7b307b7079d349f42187914d4b1 Mon Sep 17 00:00:00 2001 From: DJ Delorie Date: Fri, 17 Dec 2010 04:17:00 +0000 Subject: * 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). --- bfd/ChangeLog | 8 ++++++++ bfd/bfd-in2.h | 2 ++ bfd/elf32-rx.c | 2 ++ bfd/libbfd.h | 2 ++ bfd/reloc.c | 4 ++++ gas/ChangeLog | 6 ++++++ gas/config/tc-rx.c | 26 ++++++++++++++++++++++---- 7 files changed, 46 insertions(+), 4 deletions(-) diff --git a/bfd/ChangeLog b/bfd/ChangeLog index fcf2843..39524f6 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,11 @@ +2010-12-16 DJ Delorie + + * 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. + 2010-12-15 H.J. Lu * elf.c (_bfd_elf_new_section_hook): Special handling for diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h index e7805b6..7cf593b 100644 --- a/bfd/bfd-in2.h +++ b/bfd/bfd-in2.h @@ -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, diff --git a/bfd/elf32-rx.c b/bfd/elf32-rx.c index d7e15a0..ac587ef 100644 --- a/bfd/elf32-rx.c +++ b/bfd/elf32-rx.c @@ -250,7 +250,9 @@ static const struct rx_reloc_map rx_reloc_map [] = { 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 } diff --git a/bfd/libbfd.h b/bfd/libbfd.h index e706ce4..5687082 100644 --- a/bfd/libbfd.h +++ b/bfd/libbfd.h @@ -1802,7 +1802,9 @@ static const char *const bfd_reloc_code_real_names[] = { "@@uninitialized@@", "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", diff --git a/bfd/reloc.c b/bfd/reloc.c index 5a428a2..6d4eb85 100644 --- a/bfd/reloc.c +++ b/bfd/reloc.c @@ -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 diff --git a/gas/ChangeLog b/gas/ChangeLog index f16fbbc..507c046 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,3 +1,9 @@ +2010-12-16 DJ Delorie + + * config/tc-rx.c (rx_validate_fix_sub): Permit subtraction in more + cases. + (tc_gen_reloc): Fix handling of subtraction (esp wrt endianness). + 2010-12-16 Maciej W. Rozycki * symbols.c (symbol_clone_if_forward_ref): Call tc_new_dot_label 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; -- cgit v1.1