summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNick Clifton <nickc@redhat.com>2011-10-05 14:13:31 +0000
committerNick Clifton <nickc@redhat.com>2011-10-05 14:13:31 +0000
commitd4cb0ea0caf03bea93ae6891017bb2301facb33f (patch)
treecf3cb39ee841888cd026e0063f36241cc514fefb
parentb1c8db38fceb8464f02f1673b52c926c56203593 (diff)
downloadbinutils-gdb-d4cb0ea0caf03bea93ae6891017bb2301facb33f.tar.gz
* 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.
-rw-r--r--bfd/ChangeLog7
-rw-r--r--bfd/elf32-rx.c72
-rw-r--r--binutils/ChangeLog7
-rw-r--r--binutils/readelf.c5
-rw-r--r--binutils/testsuite/binutils-all/objdump.exp40
-rw-r--r--gas/ChangeLog23
-rw-r--r--gas/config/rx-defs.h3
-rw-r--r--gas/config/rx-parse.y31
-rw-r--r--gas/config/tc-rx.c77
-rw-r--r--gas/doc/c-rx.texi51
-rw-r--r--include/elf/ChangeLog4
-rw-r--r--include/elf/rx.h3
-rw-r--r--ld/testsuite/ChangeLog4
-rw-r--r--ld/testsuite/ld-scripts/phdrs.exp8
14 files changed, 292 insertions, 43 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index 3328999b606..53ce1512289 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -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.
diff --git a/bfd/elf32-rx.c b/bfd/elf32-rx.c
index f049f6e3390..99cffc0e009 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 9f10a2ba759..8d6e3c21eeb 100644
--- a/binutils/ChangeLog
+++ b/binutils/ChangeLog
@@ -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
diff --git a/binutils/readelf.c b/binutils/readelf.c
index 61064ca2b7c..d68cf270b49 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 ef5f24610b6..3206a00c13f 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 79f7cac7aac..958b401c9e1 100644
--- a/gas/ChangeLog
+++ b/gas/ChangeLog
@@ -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
diff --git a/gas/config/rx-defs.h b/gas/config/rx-defs.h
index c4648d2190a..868796efd27 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 2d1f85e9f4c..b473788cc04 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 56cda154173..4fa0f6737a5 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=<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;
diff --git a/gas/doc/c-rx.texi b/gas/doc/c-rx.texi
index 183fbe385eb..cb89bd66c27 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 e04b26d5de8..eece8a8f1a0 100644
--- a/include/elf/ChangeLog
+++ b/include/elf/ChangeLog
@@ -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.
diff --git a/include/elf/rx.h b/include/elf/rx.h
index e8794f35297..baaa1aa9e3c 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 54428dd6631..84e7dd5d0d0 100644
--- a/ld/testsuite/ChangeLog
+++ b/ld/testsuite/ChangeLog
@@ -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.
diff --git a/ld/testsuite/ld-scripts/phdrs.exp b/ld/testsuite/ld-scripts/phdrs.exp
index c4e56995d79..b7f3682afd5 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 {