From d4cb0ea0caf03bea93ae6891017bb2301facb33f Mon Sep 17 00:00:00 2001 From: Nick Clifton Date: Wed, 5 Oct 2011 14:13:31 +0000 Subject: [PATCH] * readelf.c (get_machine_dlags): Add support for RX's PID mode. * ld-scripts/phdrs.exp: Expect to fail for the RX. * elf32-rx.c: Add support for PID mode. (rx_elf_relocate_section): Add checks for unsafe PID relocations. Include addend in R_RX_SYM relocations. * config/rx-defs.h (rx_pid_register): New. (rx_gp_register): New. * config/rx-parse.y (rx_lex): Add support for %gpreg and %pidreg. (displacement): Add PID support. * config/tc-rx.c (rx_pid_mode): New. (rx_num_int_regs): New. (rx_pid_register): New. (rx_gp_register): New. (options): Add -mpid and -mint-register= options. (md_longopts): Likewise. (md_parse_option): Likewise. (md_show_usage): Likewise. (rx_pid_symbol): New. (rx_pidreg_symbol): New. (rx_gpreg_symbol): New. (md_begin): Support PID. (rx_validate_fix_sub): Support PID. (tc_gen_reloc): Support PID. * doc/c-rx.texi: Document PID support. * rx.h (E_FLAG_RX_PID): New. --- bfd/ChangeLog | 7 +++ bfd/elf32-rx.c | 72 +++++++++++++++++++++++++-- binutils/ChangeLog | 7 ++- binutils/readelf.c | 5 ++ binutils/testsuite/binutils-all/objdump.exp | 40 ++++++++------- gas/ChangeLog | 23 +++++++++ gas/config/rx-defs.h | 3 ++ gas/config/rx-parse.y | 31 ++++++++++++ gas/config/tc-rx.c | 77 ++++++++++++++++++++++++----- gas/doc/c-rx.texi | 51 ++++++++++++++++--- include/elf/ChangeLog | 4 ++ include/elf/rx.h | 3 +- ld/testsuite/ChangeLog | 4 ++ ld/testsuite/ld-scripts/phdrs.exp | 8 +++ 14 files changed, 292 insertions(+), 43 deletions(-) diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 3328999..53ce151 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,10 @@ +2011-10-05 DJ Delorie + Nick Clifton + + * elf32-rx.c: Add support for PID mode. + (rx_elf_relocate_section): Add checks for unsafe PID relocations. + Include addend in R_RX_SYM relocations. + 2011-09-30 Tristan Gingold * dwarf2.c (struct dwarf2_debug): Add field debug_sections. diff --git a/bfd/elf32-rx.c b/bfd/elf32-rx.c index f049f6e..99cffc0 100644 --- a/bfd/elf32-rx.c +++ b/bfd/elf32-rx.c @@ -462,6 +462,13 @@ rx_elf_relocate_section struct elf_link_hash_entry ** sym_hashes; Elf_Internal_Rela * rel; Elf_Internal_Rela * relend; + bfd_boolean pid_mode; + bfd_boolean saw_subtract = FALSE; + + if (elf_elfheader (output_bfd)->e_flags & E_FLAG_RX_PID) + pid_mode = TRUE; + else + pid_mode = FALSE; symtab_hdr = & elf_tdata (input_bfd)->symtab_hdr; sym_hashes = elf_sym_hashes (input_bfd); @@ -488,6 +495,9 @@ rx_elf_relocate_section sec = NULL; relocation = 0; + if (rx_stack_top == 0) + saw_subtract = FALSE; + if (r_symndx < symtab_hdr->sh_info) { sym = local_syms + r_symndx; @@ -553,6 +563,28 @@ rx_elf_relocate_section _bfd_error_handler (_("%B:%A: Warning: deprecated Red Hat reloc " type " detected against: %s."), \ input_bfd, input_section, name) + /* Check for unsafe relocs in PID mode. These are any relocs where + an absolute address is being computed. There are special cases + for relocs against symbols that are known to be referenced in + crt0.o before the PID base address register has been initialised. */ +#define UNSAFE_FOR_PID \ + do \ + { \ + if (pid_mode \ + && sec != NULL \ + && sec->flags & SEC_READONLY \ + && !(input_section->flags & SEC_DEBUGGING) \ + && strcmp (name, "__pid_base") != 0 \ + && strcmp (name, "__gp") != 0 \ + && strcmp (name, "__romdatastart") != 0 \ + && !saw_subtract) \ + _bfd_error_handler (_("%B(%A): unsafe PID relocation %s at 0x%08lx (against %s in %s)"), \ + input_bfd, input_section, howto->name, \ + input_section->output_section->vma + input_section->output_offset + rel->r_offset, \ + name, sec->name); \ + } \ + while (0) + /* Opcode relocs are always big endian. Data relocs are bi-endian. */ switch (r_type) { @@ -573,16 +605,19 @@ rx_elf_relocate_section WARN_REDHAT ("RX_RH_8_NEG"); relocation = - relocation; case R_RX_DIR8S_PCREL: + UNSAFE_FOR_PID; RANGE (-128, 127); OP (0) = relocation; break; case R_RX_DIR8S: + UNSAFE_FOR_PID; RANGE (-128, 255); OP (0) = relocation; break; case R_RX_DIR8U: + UNSAFE_FOR_PID; RANGE (0, 255); OP (0) = relocation; break; @@ -591,6 +626,7 @@ rx_elf_relocate_section WARN_REDHAT ("RX_RH_16_NEG"); relocation = - relocation; case R_RX_DIR16S_PCREL: + UNSAFE_FOR_PID; RANGE (-32768, 32767); #if RX_OPCODE_BIG_ENDIAN #else @@ -601,6 +637,7 @@ rx_elf_relocate_section case R_RX_RH_16_OP: WARN_REDHAT ("RX_RH_16_OP"); + UNSAFE_FOR_PID; RANGE (-32768, 32767); #if RX_OPCODE_BIG_ENDIAN OP (1) = relocation; @@ -612,6 +649,7 @@ rx_elf_relocate_section break; case R_RX_DIR16S: + UNSAFE_FOR_PID; RANGE (-32768, 65535); if (BIGE (output_bfd) && !(input_section->flags & SEC_CODE)) { @@ -626,6 +664,7 @@ rx_elf_relocate_section break; case R_RX_DIR16U: + UNSAFE_FOR_PID; RANGE (0, 65536); #if RX_OPCODE_BIG_ENDIAN OP (1) = relocation; @@ -637,6 +676,7 @@ rx_elf_relocate_section break; case R_RX_DIR16: + UNSAFE_FOR_PID; RANGE (-32768, 65536); #if RX_OPCODE_BIG_ENDIAN OP (1) = relocation; @@ -648,6 +688,7 @@ rx_elf_relocate_section break; case R_RX_DIR16_REV: + UNSAFE_FOR_PID; RANGE (-32768, 65536); #if RX_OPCODE_BIG_ENDIAN OP (0) = relocation; @@ -665,6 +706,7 @@ rx_elf_relocate_section break; case R_RX_RH_24_NEG: + UNSAFE_FOR_PID; WARN_REDHAT ("RX_RH_24_NEG"); relocation = - relocation; case R_RX_DIR24S_PCREL: @@ -681,6 +723,7 @@ rx_elf_relocate_section break; case R_RX_RH_24_OP: + UNSAFE_FOR_PID; WARN_REDHAT ("RX_RH_24_OP"); RANGE (-0x800000, 0x7fffff); #if RX_OPCODE_BIG_ENDIAN @@ -695,6 +738,7 @@ rx_elf_relocate_section break; case R_RX_DIR24S: + UNSAFE_FOR_PID; RANGE (-0x800000, 0x7fffff); if (BIGE (output_bfd) && !(input_section->flags & SEC_CODE)) { @@ -711,6 +755,7 @@ rx_elf_relocate_section break; case R_RX_RH_24_UNS: + UNSAFE_FOR_PID; WARN_REDHAT ("RX_RH_24_UNS"); RANGE (0, 0xffffff); #if RX_OPCODE_BIG_ENDIAN @@ -725,6 +770,7 @@ rx_elf_relocate_section break; case R_RX_RH_32_NEG: + UNSAFE_FOR_PID; WARN_REDHAT ("RX_RH_32_NEG"); relocation = - relocation; #if RX_OPCODE_BIG_ENDIAN @@ -741,6 +787,7 @@ rx_elf_relocate_section break; case R_RX_RH_32_OP: + UNSAFE_FOR_PID; WARN_REDHAT ("RX_RH_32_OP"); #if RX_OPCODE_BIG_ENDIAN OP (3) = relocation; @@ -920,6 +967,7 @@ rx_elf_relocate_section /* Complex reloc handling: */ case R_RX_ABS32: + UNSAFE_FOR_PID; RX_STACK_POP (relocation); #if RX_OPCODE_BIG_ENDIAN OP (3) = relocation; @@ -935,6 +983,7 @@ rx_elf_relocate_section break; case R_RX_ABS32_REV: + UNSAFE_FOR_PID; RX_STACK_POP (relocation); #if RX_OPCODE_BIG_ENDIAN OP (0) = relocation; @@ -951,6 +1000,7 @@ rx_elf_relocate_section case R_RX_ABS24S_PCREL: case R_RX_ABS24S: + UNSAFE_FOR_PID; RX_STACK_POP (relocation); RANGE (-0x800000, 0x7fffff); if (BIGE (output_bfd) && !(input_section->flags & SEC_CODE)) @@ -968,6 +1018,7 @@ rx_elf_relocate_section break; case R_RX_ABS16: + UNSAFE_FOR_PID; RX_STACK_POP (relocation); RANGE (-32768, 65535); #if RX_OPCODE_BIG_ENDIAN @@ -980,6 +1031,7 @@ rx_elf_relocate_section break; case R_RX_ABS16_REV: + UNSAFE_FOR_PID; RX_STACK_POP (relocation); RANGE (-32768, 65535); #if RX_OPCODE_BIG_ENDIAN @@ -1008,6 +1060,7 @@ rx_elf_relocate_section break; case R_RX_ABS16U: + UNSAFE_FOR_PID; RX_STACK_POP (relocation); RANGE (0, 65536); #if RX_OPCODE_BIG_ENDIAN @@ -1020,6 +1073,7 @@ rx_elf_relocate_section break; case R_RX_ABS16UL: + UNSAFE_FOR_PID; RX_STACK_POP (relocation); relocation >>= 2; RANGE (0, 65536); @@ -1033,6 +1087,7 @@ rx_elf_relocate_section break; case R_RX_ABS16UW: + UNSAFE_FOR_PID; RX_STACK_POP (relocation); relocation >>= 1; RANGE (0, 65536); @@ -1046,18 +1101,21 @@ rx_elf_relocate_section break; case R_RX_ABS8: + UNSAFE_FOR_PID; RX_STACK_POP (relocation); RANGE (-128, 255); OP (0) = relocation; break; case R_RX_ABS8U: + UNSAFE_FOR_PID; RX_STACK_POP (relocation); RANGE (0, 255); OP (0) = relocation; break; case R_RX_ABS8UL: + UNSAFE_FOR_PID; RX_STACK_POP (relocation); relocation >>= 2; RANGE (0, 255); @@ -1065,14 +1123,16 @@ rx_elf_relocate_section break; case R_RX_ABS8UW: + UNSAFE_FOR_PID; RX_STACK_POP (relocation); relocation >>= 1; RANGE (0, 255); OP (0) = relocation; break; - case R_RX_ABS8S_PCREL: case R_RX_ABS8S: + UNSAFE_FOR_PID; + case R_RX_ABS8S_PCREL: RX_STACK_POP (relocation); RANGE (-128, 127); OP (0) = relocation; @@ -1082,7 +1142,8 @@ rx_elf_relocate_section if (r_symndx < symtab_hdr->sh_info) RX_STACK_PUSH (sec->output_section->vma + sec->output_offset - + sym->st_value); + + sym->st_value + + rel->r_addend); else { if (h != NULL @@ -1090,7 +1151,8 @@ rx_elf_relocate_section || h->root.type == bfd_link_hash_defweak)) RX_STACK_PUSH (h->root.u.def.value + sec->output_section->vma - + sec->output_offset); + + sec->output_offset + + rel->r_addend); else _bfd_error_handler (_("Warning: RX_SYM reloc with an unknown symbol")); } @@ -1121,6 +1183,7 @@ rx_elf_relocate_section { int32_t tmp1, tmp2; + saw_subtract = TRUE; RX_STACK_POP (tmp1); RX_STACK_POP (tmp2); tmp2 -= tmp1; @@ -1143,6 +1206,7 @@ rx_elf_relocate_section { int32_t tmp1, tmp2; + saw_subtract = TRUE; RX_STACK_POP (tmp1); RX_STACK_POP (tmp2); tmp1 /= tmp2; @@ -2893,7 +2957,7 @@ rx_elf_merge_private_bfd_data (bfd * ibfd, bfd * obfd) } else if (old_flags != new_flags) { - flagword known_flags = E_FLAG_RX_64BIT_DOUBLES | E_FLAG_RX_DSP; + flagword known_flags = E_FLAG_RX_64BIT_DOUBLES | E_FLAG_RX_DSP | E_FLAG_RX_PID; if ((old_flags ^ new_flags) & known_flags) { diff --git a/binutils/ChangeLog b/binutils/ChangeLog index 9f10a2b..8d6e3c2 100644 --- a/binutils/ChangeLog +++ b/binutils/ChangeLog @@ -1,4 +1,9 @@ -2011-10-04 Paul Woegerer +2011-10-05 DJ Delorie + Nick Clifton + + * readelf.c (get_machine_dlags): Add support for RX's PID mode. + +2011-10-04 Paul Woegerer Carlos O'Donell * dwarf.c (display_debug_lines_decoded): Index directory_table with diff --git a/binutils/readelf.c b/binutils/readelf.c index 61064ca..d68cf27 100644 --- a/binutils/readelf.c +++ b/binutils/readelf.c @@ -2595,14 +2595,19 @@ get_machine_flags (unsigned e_flags, unsigned e_machine) strcat (buf, ", 64-bit doubles"); if (e_flags & E_FLAG_RX_DSP) strcat (buf, ", dsp"); + if (e_flags & E_FLAG_RX_PID) + strcat (buf, ", pid"); + break; case EM_S390: if (e_flags & EF_S390_HIGH_GPRS) strcat (buf, ", highgprs"); + break; case EM_TI_C6000: if ((e_flags & EF_C6000_REL)) strcat (buf, ", relocatable module"); + break; } } diff --git a/binutils/testsuite/binutils-all/objdump.exp b/binutils/testsuite/binutils-all/objdump.exp index ef5f246..3206a00 100644 --- a/binutils/testsuite/binutils-all/objdump.exp +++ b/binutils/testsuite/binutils-all/objdump.exp @@ -204,28 +204,32 @@ if { ![is_elf_format] } then { # Test objdump -WL on a file that contains line information for multiple files and search directories. -if { ![binutils_assemble $srcdir/$subdir/dw2-decodedline.S tmpdir/dw2-decodedline.o] } then { - fail "objdump decoded line" -} - -if [is_remote host] { - set decodedline_testfile [remote_download host tmpdir/dw2-decodedline.o] +if { ![is_elf_format] } then { + unsupported "objump decode line" } else { - set decodedline_testfile tmpdir/dw2-decodedline.o -} + if { ![binutils_assemble $srcdir/$subdir/dw2-decodedline.S tmpdir/dw2-decodedline.o] } then { + fail "objdump decoded line" + } + + if [is_remote host] { + set decodedline_testfile [remote_download host tmpdir/dw2-decodedline.o] + } else { + set decodedline_testfile tmpdir/dw2-decodedline.o + } -set got [remote_exec host "$OBJDUMP $OBJDUMPFLAGS -WL $decodedline_testfile" "" "/dev/null" "objdump.out"] + set got [remote_exec host "$OBJDUMP $OBJDUMPFLAGS -WL $decodedline_testfile" "" "/dev/null" "objdump.out"] -if { [lindex $got 0] != 0 || ![string match "" [lindex $got 1]] } then { - fail "objdump -WL (reason: unexpected output)" - send_log $got - send_log "\n" -} + if { [lindex $got 0] != 0 || ![string match "" [lindex $got 1]] } then { + fail "objdump -WL (reason: unexpected output)" + send_log $got + send_log "\n" + } -if { [regexp_diff objdump.out $srcdir/$subdir/objdump.WL] } then { - fail "objdump -WL" -} else { - pass "objdump -WL" + if { [regexp_diff objdump.out $srcdir/$subdir/objdump.WL] } then { + fail "objdump -WL" + } else { + pass "objdump -WL" + } } # Options which are not tested: -a -d -D -R -T -x -l --stabs diff --git a/gas/ChangeLog b/gas/ChangeLog index 79f7cac..958b401 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,3 +1,26 @@ +2011-10-05 DJ Delorie + Nick Clifton + + * config/rx-defs.h (rx_pid_register): New. + (rx_gp_register): New. + * config/rx-parse.y (rx_lex): Add support for %gpreg and %pidreg. + (displacement): Add PID support. + * config/tc-rx.c (rx_pid_mode): New. + (rx_num_int_regs): New. + (rx_pid_register): New. + (rx_gp_register): New. + (options): Add -mpid and -mint-register= options. + (md_longopts): Likewise. + (md_parse_option): Likewise. + (md_show_usage): Likewise. + (rx_pid_symbol): New. + (rx_pidreg_symbol): New. + (rx_gpreg_symbol): New. + (md_begin): Support PID. + (rx_validate_fix_sub): Support PID. + (tc_gen_reloc): Support PID. + * doc/c-rx.texi: Document PID support. + 2011-09-27 Kai Tietz * config/obj-coff.c (obj_coff_section): Add 'e' as specifier diff --git a/gas/config/rx-defs.h b/gas/config/rx-defs.h index c4648d2..868796e 100644 --- a/gas/config/rx-defs.h +++ b/gas/config/rx-defs.h @@ -34,6 +34,9 @@ #define RX_RELAX_IMM 2 #define RX_RELAX_DISP 3 +extern int rx_pid_register; +extern int rx_gp_register; + extern int rx_error (char *); extern void rx_lex_init (char *, char *); extern void rx_base1 (int); diff --git a/gas/config/rx-parse.y b/gas/config/rx-parse.y index 2d1f85e..b473788 100644 --- a/gas/config/rx-parse.y +++ b/gas/config/rx-parse.y @@ -1170,6 +1170,8 @@ rx_lex (void) return 0; if (ISALPHA (*rx_lex_start) + || (rx_pid_register != -1 && memcmp (rx_lex_start, "%pidreg", 7) == 0) + || (rx_gp_register != -1 && memcmp (rx_lex_start, "%gpreg", 6) == 0) || (*rx_lex_start == '.' && ISALPHA (rx_lex_start[1]))) { unsigned int i; @@ -1183,6 +1185,28 @@ rx_lex (void) save = *e; *e = 0; + if (strcmp (rx_lex_start, "%pidreg") == 0) + { + { + rx_lval.regno = rx_pid_register; + *e = save; + rx_lex_start = e; + rx_last_token = REG; + return REG; + } + } + + if (strcmp (rx_lex_start, "%gpreg") == 0) + { + { + rx_lval.regno = rx_gp_register; + *e = save; + rx_lex_start = e; + rx_last_token = REG; + return REG; + } + } + if (rx_last_token == 0) for (ci = 0; ci < NUM_CONDITION_OPCODES; ci ++) if (check_condition (condition_opcode_table[ci].string)) @@ -1482,6 +1506,13 @@ displacement (expressionS exp, int msize) } } + if (exp.X_op == O_subtract) + { + exp.X_md = BFD_RELOC_RX_DIFF; + O2 (exp); + return 2; + } + if (exp.X_op != O_constant) { rx_error (_("displacements must be constants")); diff --git a/gas/config/tc-rx.c b/gas/config/tc-rx.c index 56cda15..4fa0f67 100644 --- a/gas/config/tc-rx.c +++ b/gas/config/tc-rx.c @@ -1,5 +1,5 @@ /* tc-rx.c -- Assembler for the Renesas RX - Copyright 2008, 2009, 2010 + Copyright 2008, 2009, 2010, 2011 Free Software Foundation, Inc. This file is part of GAS, the GNU Assembler. @@ -51,6 +51,11 @@ static int elf_flags = 0; bfd_boolean rx_use_conventional_section_names = FALSE; static bfd_boolean rx_use_small_data_limit = FALSE; +static bfd_boolean rx_pid_mode = FALSE; +static int rx_num_int_regs = 0; +int rx_pid_register; +int rx_gp_register; + enum options { OPTION_BIG = OPTION_MD_BASE, @@ -60,7 +65,9 @@ enum options OPTION_CONVENTIONAL_SECTION_NAMES, OPTION_RENESAS_SECTION_NAMES, OPTION_SMALL_DATA_LIMIT, - OPTION_RELAX + OPTION_RELAX, + OPTION_PID, + OPTION_INT_REGS, }; #define RX_SHORTOPTS "" @@ -83,6 +90,8 @@ struct option md_longopts[] = {"muse-renesas-section-names", no_argument, NULL, OPTION_RENESAS_SECTION_NAMES}, {"msmall-data-limit", no_argument, NULL, OPTION_SMALL_DATA_LIMIT}, {"relax", no_argument, NULL, OPTION_RELAX}, + {"mpid", no_argument, NULL, OPTION_PID}, + {"mint-register", required_argument, NULL, OPTION_INT_REGS}, {NULL, no_argument, NULL, 0} }; size_t md_longopts_size = sizeof (md_longopts); @@ -123,6 +132,15 @@ md_parse_option (int c ATTRIBUTE_UNUSED, char * arg ATTRIBUTE_UNUSED) case OPTION_RELAX: linkrelax = 1; return 1; + + case OPTION_PID: + rx_pid_mode = TRUE; + elf_flags |= E_FLAG_RX_PID; + return 1; + + case OPTION_INT_REGS: + rx_num_int_regs = atoi (optarg); + return 1; } return 0; } @@ -138,6 +156,9 @@ md_show_usage (FILE * stream) fprintf (stream, _(" --muse-conventional-section-names\n")); fprintf (stream, _(" --muse-renesas-section-names [default]\n")); fprintf (stream, _(" --msmall-data-limit\n")); + fprintf (stream, _(" --mrelax\n")); + fprintf (stream, _(" --mpid\n")); + fprintf (stream, _(" --mint-register=\n")); } static void @@ -584,16 +605,44 @@ const pseudo_typeS md_pseudo_table[] = }; static asymbol * gp_symbol; +static asymbol * rx_pid_symbol; + +static symbolS * rx_pidreg_symbol; +static symbolS * rx_gpreg_symbol; void md_begin (void) { + /* Make the __gp and __pid_base symbols now rather + than after the symbol table is frozen. We only do this + when supporting small data limits because otherwise we + pollute the symbol table. */ + + /* The meta-registers %pidreg and %gpreg depend on what other + options are specified. The __rx_*_defined symbols exist so we + can .ifdef asm code based on what options were passed to gas, + without needing a preprocessor */ + + if (rx_pid_mode) + { + rx_pid_register = 13 - rx_num_int_regs; + rx_pid_symbol = symbol_get_bfdsym (symbol_find_or_make ("__pid_base")); + rx_pidreg_symbol = symbol_find_or_make ("__rx_pidreg_defined"); + S_SET_VALUE (rx_pidreg_symbol, rx_pid_register); + S_SET_SEGMENT (rx_pidreg_symbol, absolute_section); + } + if (rx_use_small_data_limit) - /* Make the __gp symbol now rather - than after the symbol table is frozen. We only do this - when supporting small data limits because otherwise we - pollute the symbol table. */ - gp_symbol = symbol_get_bfdsym (symbol_find_or_make ("__gp")); + { + if (rx_pid_mode) + rx_gp_register = rx_pid_register - 1; + else + rx_gp_register = 13 - rx_num_int_regs; + gp_symbol = symbol_get_bfdsym (symbol_find_or_make ("__gp")); + rx_gpreg_symbol = symbol_find_or_make ("__rx_gpreg_defined"); + S_SET_VALUE (rx_gpreg_symbol, rx_gp_register); + S_SET_SEGMENT (rx_gpreg_symbol, absolute_section); + } } char * rx_lex_start; @@ -1150,7 +1199,7 @@ rx_handle_align (fragS * frag) && subseg_text_p (now_seg)) { int count = (frag->fr_next->fr_address - - frag->fr_address + - frag->fr_address - frag->fr_fix); unsigned char *base = (unsigned char *)frag->fr_literal + frag->fr_fix; @@ -2222,10 +2271,10 @@ md_apply_fix (struct fix * f ATTRIBUTE_UNUSED, } arelent ** -tc_gen_reloc (asection * seg ATTRIBUTE_UNUSED, fixS * fixp) +tc_gen_reloc (asection * sec ATTRIBUTE_UNUSED, fixS * fixp) { static arelent * reloc[5]; - int is_opcode = 0; + bfd_boolean is_opcode = FALSE; if (fixp->fx_r_type == BFD_RELOC_NONE) { @@ -2250,9 +2299,11 @@ tc_gen_reloc (asection * seg ATTRIBUTE_UNUSED, fixS * fixp) && fixp->fx_subsy) { fixp->fx_r_type = BFD_RELOC_RX_DIFF; - is_opcode = 1; + is_opcode = TRUE; } - + else if (sec) + is_opcode = sec->flags & SEC_CODE; + /* Certain BFD relocations cannot be translated directly into a single (non-Red Hat) RX relocation, but instead need multiple RX relocations - handle them here. */ @@ -2283,6 +2334,8 @@ tc_gen_reloc (asection * seg ATTRIBUTE_UNUSED, fixS * fixp) case 2: if (!is_opcode && target_big_endian) reloc[3]->howto = bfd_reloc_type_lookup (stdoutput, BFD_RELOC_RX_ABS16_REV); + else if (is_opcode) + reloc[3]->howto = bfd_reloc_type_lookup (stdoutput, BFD_RELOC_RX_ABS16UL); else reloc[3]->howto = bfd_reloc_type_lookup (stdoutput, BFD_RELOC_RX_ABS16); break; diff --git a/gas/doc/c-rx.texi b/gas/doc/c-rx.texi index 183fbe3..cb89bd6 100644 --- a/gas/doc/c-rx.texi +++ b/gas/doc/c-rx.texi @@ -74,11 +74,25 @@ This is the default. @item -msmall-data-limit This option tells the assembler that the small data limit feature of the RX port of GCC is being used. This results in the assembler -generating an undefined reference to a symbol called __gp for use by -the relocations that are needed to support the small data limit +generating an undefined reference to a symbol called @code{__gp} for +use by the relocations that are needed to support the small data limit feature. This option is not enabled by default as it would otherwise pollute the symbol table. +@cindex @samp{-mpid} +@item -mpid +This option tells the assembler that the position independent data of the +RX port of GCC is being used. This results in the assembler +generating an undefined reference to a symbol called @code{__pid_base}, +and also setting the RX_PID flag bit in the e_flags field of the ELF +header of the object file. + +@cindex @samp{-mint-register} +@item -mint-register=@var{num} +This option tells the assembler how many registers have been reserved +for use by interrupt handlers. This is needed in order to compute the +correct values for the @code{%gpreg} and @code{%pidreg} meta registers. + @end table @node RX-Modifiers @@ -86,22 +100,45 @@ pollute the symbol table. @cindex RX modifiers @cindex syntax, RX +@cindex %gp -The assembler supports several modifiers when using symbol addresses +The assembler supports one modifier when using symbol addresses in RX instruction operands. The general syntax is the following: @smallexample -%modifier(symbol) +%gp(symbol) @end smallexample +The modifier returns the offset from the @var{__gp} symbol to the +specified symbol as a 16-bit value. The intent is that this offset +should be used in a register+offset move instruction when generating +references to small data. Ie, like this: + +@smallexample + mov.W %gp(_foo)[%gpreg], r1 +@end smallexample + +The assembler also supports two meta register names which can be used +to refer to registers whose values may not be known to the +programmer. These meta register names are: + @table @code -@cindex symbol modifiers -@item %gp -@c FIXME: Add documentation here. +@cindex @samp{%gpreg} +@item %gpreg +The small data address register. + +@cindex @samp{%pidreg} +@item %pidreg +The PID base address register. @end table +Both registers normally have the value r13, but this can change if +some registers have been reserved for use by interrupt handlers or if +both the small data limit and position independent data features are +being used at the same time. + @node RX-Directives @section Assembler Directives diff --git a/include/elf/ChangeLog b/include/elf/ChangeLog index e04b26d..eece8a8 100644 --- a/include/elf/ChangeLog +++ b/include/elf/ChangeLog @@ -1,3 +1,7 @@ +2011-10-05 DJ Delorie + + * rx.h (E_FLAG_RX_PID): New. + 2011-09-21 David S. Miller * sparc.h (Tag_GNU_Sparc_HWCAPS): New object attribute. diff --git a/include/elf/rx.h b/include/elf/rx.h index e8794f3..baaa1aa 100644 --- a/include/elf/rx.h +++ b/include/elf/rx.h @@ -116,7 +116,8 @@ END_RELOC_NUMBERS (R_RX_max) /* Values for the e_flags field in the ELF header. */ #define E_FLAG_RX_64BIT_DOUBLES (1 << 0) -#define E_FLAG_RX_DSP (1 << 1) /* Defined in the RX CPU Object file specification, but not explained. */ +#define E_FLAG_RX_DSP (1 << 1) /* Defined in the RX CPU Object file specification, but not explained. */ +#define E_FLAG_RX_PID (1 << 2) /* Unofficial - DJ */ /* These define the addend field of R_RX_RH_RELAX relocations. */ #define RX_RELAXA_IMM6 0x00000010 /* Imm8/16/24/32 at bit offset 6. */ diff --git a/ld/testsuite/ChangeLog b/ld/testsuite/ChangeLog index 54428dd..84e7dd5 100644 --- a/ld/testsuite/ChangeLog +++ b/ld/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2011-10-05 Nick Clifton + + * ld-scripts/phdrs.exp: Expect to fail for the RX. + 2011-09-30 Alan Modra * ld-powerpc/tocopt.d: Update. diff --git a/ld/testsuite/ld-scripts/phdrs.exp b/ld/testsuite/ld-scripts/phdrs.exp index c4e5699..b7f3682 100644 --- a/ld/testsuite/ld-scripts/phdrs.exp +++ b/ld/testsuite/ld-scripts/phdrs.exp @@ -60,6 +60,14 @@ if ![ld_simple_link $ld tmpdir/phdrs $ldopt] { set exec_output [prune_warnings $exec_output] verbose -log $exec_output + # The RX port sets the p_paddr of loadable segments to 0 in order + # to be compatible with Renesas tools. When an RX executable is + # loaded into a BFD based tool the code tries to reconstruct the + # correct vaddr and paddr values. This is not always possible + # however and this test is one example of where the reconstruction + # fails. + setup_xfail rx-*-* + if [regexp $phdrs_regexp $exec_output] { pass $testname } else { -- 2.7.4