OSDN Git Service

* readelf.c (get_machine_dlags): Add support for RX's PID mode.
authornickc <nickc>
Wed, 5 Oct 2011 14:13:24 +0000 (14:13 +0000)
committernickc <nickc>
Wed, 5 Oct 2011 14:13:24 +0000 (14:13 +0000)
* 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.

14 files changed:
bfd/ChangeLog
bfd/elf32-rx.c
binutils/ChangeLog
binutils/readelf.c
binutils/testsuite/binutils-all/objdump.exp
gas/ChangeLog
gas/config/rx-defs.h
gas/config/rx-parse.y
gas/config/tc-rx.c
gas/doc/c-rx.texi
include/elf/ChangeLog
include/elf/rx.h
ld/testsuite/ChangeLog
ld/testsuite/ld-scripts/phdrs.exp

index 3328999..53ce151 100644 (file)
@@ -1,3 +1,10 @@
+2011-10-05  DJ Delorie  <dj@redhat.com>
+           Nick Clifton  <nickc@redhat.com>
+
+       * 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  <gingold@adacore.com>
 
        * dwarf2.c (struct dwarf2_debug): Add field debug_sections.
index f049f6e..99cffc0 100644 (file)
@@ -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)
        {
index 9f10a2b..8d6e3c2 100644 (file)
@@ -1,4 +1,9 @@
-2011-10-04  Paul Woegerer  <paul_woegerer@mentor.com> 
+2011-10-05  DJ Delorie  <dj@redhat.com>
+           Nick Clifton  <nickc@redhat.com>
+
+       * readelf.c (get_machine_dlags): Add support for RX's PID mode.
+
+2011-10-04  Paul Woegerer  <paul_woegerer@mentor.com>
            Carlos O'Donell  <carlos@codesourcery.com>
 
        * dwarf.c (display_debug_lines_decoded): Index directory_table with
index 61064ca..d68cf27 100644 (file)
@@ -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;
        }
     }
 
index ef5f246..3206a00 100644 (file)
@@ -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
index 79f7cac..958b401 100644 (file)
@@ -1,3 +1,26 @@
+2011-10-05  DJ Delorie  <dj@redhat.com>
+           Nick Clifton  <nickc@redhat.com>
+
+       * 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  <ktietz@redhat.com>
 
        * config/obj-coff.c (obj_coff_section): Add 'e' as specifier
index c4648d2..868796e 100644 (file)
@@ -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);
index 2d1f85e..b473788 100644 (file)
@@ -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"));
index 56cda15..4fa0f67 100644 (file)
@@ -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=<value>\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;
index 183fbe3..cb89bd6 100644 (file)
@@ -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
 
index e04b26d..eece8a8 100644 (file)
@@ -1,3 +1,7 @@
+2011-10-05  DJ Delorie  <dj@redhat.com>
+
+       * rx.h (E_FLAG_RX_PID): New.
+
 2011-09-21  David S. Miller  <davem@davemloft.net>
 
        * sparc.h (Tag_GNU_Sparc_HWCAPS): New object attribute.
index e8794f3..baaa1aa 100644 (file)
@@ -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.  */
index 54428dd..84e7dd5 100644 (file)
@@ -1,3 +1,7 @@
+2011-10-05  Nick Clifton  <nickc@redhat.com>
+
+       * ld-scripts/phdrs.exp: Expect to fail for the RX.
+
 2011-09-30  Alan Modra  <amodra@gmail.com>
 
        * ld-powerpc/tocopt.d: Update.
index c4e5699..b7f3682 100644 (file)
@@ -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 {