* 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.
This commit is contained in:
Nick Clifton 2011-10-05 14:13:31 +00:00
parent b1c8db38fc
commit d4cb0ea0ca
14 changed files with 293 additions and 44 deletions

View 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> 2011-09-30 Tristan Gingold <gingold@adacore.com>
* dwarf2.c (struct dwarf2_debug): Add field debug_sections. * dwarf2.c (struct dwarf2_debug): Add field debug_sections.

View file

@ -462,6 +462,13 @@ rx_elf_relocate_section
struct elf_link_hash_entry ** sym_hashes; struct elf_link_hash_entry ** sym_hashes;
Elf_Internal_Rela * rel; Elf_Internal_Rela * rel;
Elf_Internal_Rela * relend; 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; symtab_hdr = & elf_tdata (input_bfd)->symtab_hdr;
sym_hashes = elf_sym_hashes (input_bfd); sym_hashes = elf_sym_hashes (input_bfd);
@ -488,6 +495,9 @@ rx_elf_relocate_section
sec = NULL; sec = NULL;
relocation = 0; relocation = 0;
if (rx_stack_top == 0)
saw_subtract = FALSE;
if (r_symndx < symtab_hdr->sh_info) if (r_symndx < symtab_hdr->sh_info)
{ {
sym = local_syms + r_symndx; 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."), \ _bfd_error_handler (_("%B:%A: Warning: deprecated Red Hat reloc " type " detected against: %s."), \
input_bfd, input_section, name) 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. */ /* Opcode relocs are always big endian. Data relocs are bi-endian. */
switch (r_type) switch (r_type)
{ {
@ -573,16 +605,19 @@ rx_elf_relocate_section
WARN_REDHAT ("RX_RH_8_NEG"); WARN_REDHAT ("RX_RH_8_NEG");
relocation = - relocation; relocation = - relocation;
case R_RX_DIR8S_PCREL: case R_RX_DIR8S_PCREL:
UNSAFE_FOR_PID;
RANGE (-128, 127); RANGE (-128, 127);
OP (0) = relocation; OP (0) = relocation;
break; break;
case R_RX_DIR8S: case R_RX_DIR8S:
UNSAFE_FOR_PID;
RANGE (-128, 255); RANGE (-128, 255);
OP (0) = relocation; OP (0) = relocation;
break; break;
case R_RX_DIR8U: case R_RX_DIR8U:
UNSAFE_FOR_PID;
RANGE (0, 255); RANGE (0, 255);
OP (0) = relocation; OP (0) = relocation;
break; break;
@ -591,6 +626,7 @@ rx_elf_relocate_section
WARN_REDHAT ("RX_RH_16_NEG"); WARN_REDHAT ("RX_RH_16_NEG");
relocation = - relocation; relocation = - relocation;
case R_RX_DIR16S_PCREL: case R_RX_DIR16S_PCREL:
UNSAFE_FOR_PID;
RANGE (-32768, 32767); RANGE (-32768, 32767);
#if RX_OPCODE_BIG_ENDIAN #if RX_OPCODE_BIG_ENDIAN
#else #else
@ -601,6 +637,7 @@ rx_elf_relocate_section
case R_RX_RH_16_OP: case R_RX_RH_16_OP:
WARN_REDHAT ("RX_RH_16_OP"); WARN_REDHAT ("RX_RH_16_OP");
UNSAFE_FOR_PID;
RANGE (-32768, 32767); RANGE (-32768, 32767);
#if RX_OPCODE_BIG_ENDIAN #if RX_OPCODE_BIG_ENDIAN
OP (1) = relocation; OP (1) = relocation;
@ -612,6 +649,7 @@ rx_elf_relocate_section
break; break;
case R_RX_DIR16S: case R_RX_DIR16S:
UNSAFE_FOR_PID;
RANGE (-32768, 65535); RANGE (-32768, 65535);
if (BIGE (output_bfd) && !(input_section->flags & SEC_CODE)) if (BIGE (output_bfd) && !(input_section->flags & SEC_CODE))
{ {
@ -626,6 +664,7 @@ rx_elf_relocate_section
break; break;
case R_RX_DIR16U: case R_RX_DIR16U:
UNSAFE_FOR_PID;
RANGE (0, 65536); RANGE (0, 65536);
#if RX_OPCODE_BIG_ENDIAN #if RX_OPCODE_BIG_ENDIAN
OP (1) = relocation; OP (1) = relocation;
@ -637,6 +676,7 @@ rx_elf_relocate_section
break; break;
case R_RX_DIR16: case R_RX_DIR16:
UNSAFE_FOR_PID;
RANGE (-32768, 65536); RANGE (-32768, 65536);
#if RX_OPCODE_BIG_ENDIAN #if RX_OPCODE_BIG_ENDIAN
OP (1) = relocation; OP (1) = relocation;
@ -648,6 +688,7 @@ rx_elf_relocate_section
break; break;
case R_RX_DIR16_REV: case R_RX_DIR16_REV:
UNSAFE_FOR_PID;
RANGE (-32768, 65536); RANGE (-32768, 65536);
#if RX_OPCODE_BIG_ENDIAN #if RX_OPCODE_BIG_ENDIAN
OP (0) = relocation; OP (0) = relocation;
@ -665,6 +706,7 @@ rx_elf_relocate_section
break; break;
case R_RX_RH_24_NEG: case R_RX_RH_24_NEG:
UNSAFE_FOR_PID;
WARN_REDHAT ("RX_RH_24_NEG"); WARN_REDHAT ("RX_RH_24_NEG");
relocation = - relocation; relocation = - relocation;
case R_RX_DIR24S_PCREL: case R_RX_DIR24S_PCREL:
@ -681,6 +723,7 @@ rx_elf_relocate_section
break; break;
case R_RX_RH_24_OP: case R_RX_RH_24_OP:
UNSAFE_FOR_PID;
WARN_REDHAT ("RX_RH_24_OP"); WARN_REDHAT ("RX_RH_24_OP");
RANGE (-0x800000, 0x7fffff); RANGE (-0x800000, 0x7fffff);
#if RX_OPCODE_BIG_ENDIAN #if RX_OPCODE_BIG_ENDIAN
@ -695,6 +738,7 @@ rx_elf_relocate_section
break; break;
case R_RX_DIR24S: case R_RX_DIR24S:
UNSAFE_FOR_PID;
RANGE (-0x800000, 0x7fffff); RANGE (-0x800000, 0x7fffff);
if (BIGE (output_bfd) && !(input_section->flags & SEC_CODE)) if (BIGE (output_bfd) && !(input_section->flags & SEC_CODE))
{ {
@ -711,6 +755,7 @@ rx_elf_relocate_section
break; break;
case R_RX_RH_24_UNS: case R_RX_RH_24_UNS:
UNSAFE_FOR_PID;
WARN_REDHAT ("RX_RH_24_UNS"); WARN_REDHAT ("RX_RH_24_UNS");
RANGE (0, 0xffffff); RANGE (0, 0xffffff);
#if RX_OPCODE_BIG_ENDIAN #if RX_OPCODE_BIG_ENDIAN
@ -725,6 +770,7 @@ rx_elf_relocate_section
break; break;
case R_RX_RH_32_NEG: case R_RX_RH_32_NEG:
UNSAFE_FOR_PID;
WARN_REDHAT ("RX_RH_32_NEG"); WARN_REDHAT ("RX_RH_32_NEG");
relocation = - relocation; relocation = - relocation;
#if RX_OPCODE_BIG_ENDIAN #if RX_OPCODE_BIG_ENDIAN
@ -741,6 +787,7 @@ rx_elf_relocate_section
break; break;
case R_RX_RH_32_OP: case R_RX_RH_32_OP:
UNSAFE_FOR_PID;
WARN_REDHAT ("RX_RH_32_OP"); WARN_REDHAT ("RX_RH_32_OP");
#if RX_OPCODE_BIG_ENDIAN #if RX_OPCODE_BIG_ENDIAN
OP (3) = relocation; OP (3) = relocation;
@ -920,6 +967,7 @@ rx_elf_relocate_section
/* Complex reloc handling: */ /* Complex reloc handling: */
case R_RX_ABS32: case R_RX_ABS32:
UNSAFE_FOR_PID;
RX_STACK_POP (relocation); RX_STACK_POP (relocation);
#if RX_OPCODE_BIG_ENDIAN #if RX_OPCODE_BIG_ENDIAN
OP (3) = relocation; OP (3) = relocation;
@ -935,6 +983,7 @@ rx_elf_relocate_section
break; break;
case R_RX_ABS32_REV: case R_RX_ABS32_REV:
UNSAFE_FOR_PID;
RX_STACK_POP (relocation); RX_STACK_POP (relocation);
#if RX_OPCODE_BIG_ENDIAN #if RX_OPCODE_BIG_ENDIAN
OP (0) = relocation; OP (0) = relocation;
@ -951,6 +1000,7 @@ rx_elf_relocate_section
case R_RX_ABS24S_PCREL: case R_RX_ABS24S_PCREL:
case R_RX_ABS24S: case R_RX_ABS24S:
UNSAFE_FOR_PID;
RX_STACK_POP (relocation); RX_STACK_POP (relocation);
RANGE (-0x800000, 0x7fffff); RANGE (-0x800000, 0x7fffff);
if (BIGE (output_bfd) && !(input_section->flags & SEC_CODE)) if (BIGE (output_bfd) && !(input_section->flags & SEC_CODE))
@ -968,6 +1018,7 @@ rx_elf_relocate_section
break; break;
case R_RX_ABS16: case R_RX_ABS16:
UNSAFE_FOR_PID;
RX_STACK_POP (relocation); RX_STACK_POP (relocation);
RANGE (-32768, 65535); RANGE (-32768, 65535);
#if RX_OPCODE_BIG_ENDIAN #if RX_OPCODE_BIG_ENDIAN
@ -980,6 +1031,7 @@ rx_elf_relocate_section
break; break;
case R_RX_ABS16_REV: case R_RX_ABS16_REV:
UNSAFE_FOR_PID;
RX_STACK_POP (relocation); RX_STACK_POP (relocation);
RANGE (-32768, 65535); RANGE (-32768, 65535);
#if RX_OPCODE_BIG_ENDIAN #if RX_OPCODE_BIG_ENDIAN
@ -1008,6 +1060,7 @@ rx_elf_relocate_section
break; break;
case R_RX_ABS16U: case R_RX_ABS16U:
UNSAFE_FOR_PID;
RX_STACK_POP (relocation); RX_STACK_POP (relocation);
RANGE (0, 65536); RANGE (0, 65536);
#if RX_OPCODE_BIG_ENDIAN #if RX_OPCODE_BIG_ENDIAN
@ -1020,6 +1073,7 @@ rx_elf_relocate_section
break; break;
case R_RX_ABS16UL: case R_RX_ABS16UL:
UNSAFE_FOR_PID;
RX_STACK_POP (relocation); RX_STACK_POP (relocation);
relocation >>= 2; relocation >>= 2;
RANGE (0, 65536); RANGE (0, 65536);
@ -1033,6 +1087,7 @@ rx_elf_relocate_section
break; break;
case R_RX_ABS16UW: case R_RX_ABS16UW:
UNSAFE_FOR_PID;
RX_STACK_POP (relocation); RX_STACK_POP (relocation);
relocation >>= 1; relocation >>= 1;
RANGE (0, 65536); RANGE (0, 65536);
@ -1046,18 +1101,21 @@ rx_elf_relocate_section
break; break;
case R_RX_ABS8: case R_RX_ABS8:
UNSAFE_FOR_PID;
RX_STACK_POP (relocation); RX_STACK_POP (relocation);
RANGE (-128, 255); RANGE (-128, 255);
OP (0) = relocation; OP (0) = relocation;
break; break;
case R_RX_ABS8U: case R_RX_ABS8U:
UNSAFE_FOR_PID;
RX_STACK_POP (relocation); RX_STACK_POP (relocation);
RANGE (0, 255); RANGE (0, 255);
OP (0) = relocation; OP (0) = relocation;
break; break;
case R_RX_ABS8UL: case R_RX_ABS8UL:
UNSAFE_FOR_PID;
RX_STACK_POP (relocation); RX_STACK_POP (relocation);
relocation >>= 2; relocation >>= 2;
RANGE (0, 255); RANGE (0, 255);
@ -1065,14 +1123,16 @@ rx_elf_relocate_section
break; break;
case R_RX_ABS8UW: case R_RX_ABS8UW:
UNSAFE_FOR_PID;
RX_STACK_POP (relocation); RX_STACK_POP (relocation);
relocation >>= 1; relocation >>= 1;
RANGE (0, 255); RANGE (0, 255);
OP (0) = relocation; OP (0) = relocation;
break; break;
case R_RX_ABS8S_PCREL:
case R_RX_ABS8S: case R_RX_ABS8S:
UNSAFE_FOR_PID;
case R_RX_ABS8S_PCREL:
RX_STACK_POP (relocation); RX_STACK_POP (relocation);
RANGE (-128, 127); RANGE (-128, 127);
OP (0) = relocation; OP (0) = relocation;
@ -1082,7 +1142,8 @@ rx_elf_relocate_section
if (r_symndx < symtab_hdr->sh_info) if (r_symndx < symtab_hdr->sh_info)
RX_STACK_PUSH (sec->output_section->vma RX_STACK_PUSH (sec->output_section->vma
+ sec->output_offset + sec->output_offset
+ sym->st_value); + sym->st_value
+ rel->r_addend);
else else
{ {
if (h != NULL if (h != NULL
@ -1090,7 +1151,8 @@ rx_elf_relocate_section
|| h->root.type == bfd_link_hash_defweak)) || h->root.type == bfd_link_hash_defweak))
RX_STACK_PUSH (h->root.u.def.value RX_STACK_PUSH (h->root.u.def.value
+ sec->output_section->vma + sec->output_section->vma
+ sec->output_offset); + sec->output_offset
+ rel->r_addend);
else else
_bfd_error_handler (_("Warning: RX_SYM reloc with an unknown symbol")); _bfd_error_handler (_("Warning: RX_SYM reloc with an unknown symbol"));
} }
@ -1121,6 +1183,7 @@ rx_elf_relocate_section
{ {
int32_t tmp1, tmp2; int32_t tmp1, tmp2;
saw_subtract = TRUE;
RX_STACK_POP (tmp1); RX_STACK_POP (tmp1);
RX_STACK_POP (tmp2); RX_STACK_POP (tmp2);
tmp2 -= tmp1; tmp2 -= tmp1;
@ -1143,6 +1206,7 @@ rx_elf_relocate_section
{ {
int32_t tmp1, tmp2; int32_t tmp1, tmp2;
saw_subtract = TRUE;
RX_STACK_POP (tmp1); RX_STACK_POP (tmp1);
RX_STACK_POP (tmp2); RX_STACK_POP (tmp2);
tmp1 /= tmp2; tmp1 /= tmp2;
@ -2893,7 +2957,7 @@ rx_elf_merge_private_bfd_data (bfd * ibfd, bfd * obfd)
} }
else if (old_flags != new_flags) 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) if ((old_flags ^ new_flags) & known_flags)
{ {

View file

@ -1,3 +1,8 @@
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> 2011-10-04 Paul Woegerer <paul_woegerer@mentor.com>
Carlos O'Donell <carlos@codesourcery.com> Carlos O'Donell <carlos@codesourcery.com>

View file

@ -2595,14 +2595,19 @@ get_machine_flags (unsigned e_flags, unsigned e_machine)
strcat (buf, ", 64-bit doubles"); strcat (buf, ", 64-bit doubles");
if (e_flags & E_FLAG_RX_DSP) if (e_flags & E_FLAG_RX_DSP)
strcat (buf, ", dsp"); strcat (buf, ", dsp");
if (e_flags & E_FLAG_RX_PID)
strcat (buf, ", pid");
break;
case EM_S390: case EM_S390:
if (e_flags & EF_S390_HIGH_GPRS) if (e_flags & EF_S390_HIGH_GPRS)
strcat (buf, ", highgprs"); strcat (buf, ", highgprs");
break;
case EM_TI_C6000: case EM_TI_C6000:
if ((e_flags & EF_C6000_REL)) if ((e_flags & EF_C6000_REL))
strcat (buf, ", relocatable module"); strcat (buf, ", relocatable module");
break;
} }
} }

View file

@ -204,6 +204,9 @@ if { ![is_elf_format] } then {
# Test objdump -WL on a file that contains line information for multiple files and search directories. # Test objdump -WL on a file that contains line information for multiple files and search directories.
if { ![is_elf_format] } then {
unsupported "objump decode line"
} else {
if { ![binutils_assemble $srcdir/$subdir/dw2-decodedline.S tmpdir/dw2-decodedline.o] } then { if { ![binutils_assemble $srcdir/$subdir/dw2-decodedline.S tmpdir/dw2-decodedline.o] } then {
fail "objdump decoded line" fail "objdump decoded line"
} }
@ -227,6 +230,7 @@ if { [regexp_diff objdump.out $srcdir/$subdir/objdump.WL] } then {
} else { } else {
pass "objdump -WL" pass "objdump -WL"
} }
}
# Options which are not tested: -a -d -D -R -T -x -l --stabs # Options which are not tested: -a -d -D -R -T -x -l --stabs
# I don't see any generic way to test any of these other than -a. # I don't see any generic way to test any of these other than -a.

View 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> 2011-09-27 Kai Tietz <ktietz@redhat.com>
* config/obj-coff.c (obj_coff_section): Add 'e' as specifier * config/obj-coff.c (obj_coff_section): Add 'e' as specifier

View file

@ -34,6 +34,9 @@
#define RX_RELAX_IMM 2 #define RX_RELAX_IMM 2
#define RX_RELAX_DISP 3 #define RX_RELAX_DISP 3
extern int rx_pid_register;
extern int rx_gp_register;
extern int rx_error (char *); extern int rx_error (char *);
extern void rx_lex_init (char *, char *); extern void rx_lex_init (char *, char *);
extern void rx_base1 (int); extern void rx_base1 (int);

View file

@ -1170,6 +1170,8 @@ rx_lex (void)
return 0; return 0;
if (ISALPHA (*rx_lex_start) 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]))) || (*rx_lex_start == '.' && ISALPHA (rx_lex_start[1])))
{ {
unsigned int i; unsigned int i;
@ -1183,6 +1185,28 @@ rx_lex (void)
save = *e; save = *e;
*e = 0; *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) if (rx_last_token == 0)
for (ci = 0; ci < NUM_CONDITION_OPCODES; ci ++) for (ci = 0; ci < NUM_CONDITION_OPCODES; ci ++)
if (check_condition (condition_opcode_table[ci].string)) 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) if (exp.X_op != O_constant)
{ {
rx_error (_("displacements must be constants")); rx_error (_("displacements must be constants"));

View file

@ -1,5 +1,5 @@
/* tc-rx.c -- Assembler for the Renesas RX /* tc-rx.c -- Assembler for the Renesas RX
Copyright 2008, 2009, 2010 Copyright 2008, 2009, 2010, 2011
Free Software Foundation, Inc. Free Software Foundation, Inc.
This file is part of GAS, the GNU Assembler. 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; bfd_boolean rx_use_conventional_section_names = FALSE;
static bfd_boolean rx_use_small_data_limit = 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 enum options
{ {
OPTION_BIG = OPTION_MD_BASE, OPTION_BIG = OPTION_MD_BASE,
@ -60,7 +65,9 @@ enum options
OPTION_CONVENTIONAL_SECTION_NAMES, OPTION_CONVENTIONAL_SECTION_NAMES,
OPTION_RENESAS_SECTION_NAMES, OPTION_RENESAS_SECTION_NAMES,
OPTION_SMALL_DATA_LIMIT, OPTION_SMALL_DATA_LIMIT,
OPTION_RELAX OPTION_RELAX,
OPTION_PID,
OPTION_INT_REGS,
}; };
#define RX_SHORTOPTS "" #define RX_SHORTOPTS ""
@ -83,6 +90,8 @@ struct option md_longopts[] =
{"muse-renesas-section-names", no_argument, NULL, OPTION_RENESAS_SECTION_NAMES}, {"muse-renesas-section-names", no_argument, NULL, OPTION_RENESAS_SECTION_NAMES},
{"msmall-data-limit", no_argument, NULL, OPTION_SMALL_DATA_LIMIT}, {"msmall-data-limit", no_argument, NULL, OPTION_SMALL_DATA_LIMIT},
{"relax", no_argument, NULL, OPTION_RELAX}, {"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} {NULL, no_argument, NULL, 0}
}; };
size_t md_longopts_size = sizeof (md_longopts); 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: case OPTION_RELAX:
linkrelax = 1; linkrelax = 1;
return 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; return 0;
} }
@ -138,6 +156,9 @@ md_show_usage (FILE * stream)
fprintf (stream, _(" --muse-conventional-section-names\n")); fprintf (stream, _(" --muse-conventional-section-names\n"));
fprintf (stream, _(" --muse-renesas-section-names [default]\n")); fprintf (stream, _(" --muse-renesas-section-names [default]\n"));
fprintf (stream, _(" --msmall-data-limit\n")); fprintf (stream, _(" --msmall-data-limit\n"));
fprintf (stream, _(" --mrelax\n"));
fprintf (stream, _(" --mpid\n"));
fprintf (stream, _(" --mint-register=<value>\n"));
} }
static void static void
@ -584,16 +605,44 @@ const pseudo_typeS md_pseudo_table[] =
}; };
static asymbol * gp_symbol; static asymbol * gp_symbol;
static asymbol * rx_pid_symbol;
static symbolS * rx_pidreg_symbol;
static symbolS * rx_gpreg_symbol;
void void
md_begin (void) md_begin (void)
{ {
if (rx_use_small_data_limit) /* Make the __gp and __pid_base symbols now rather
/* Make the __gp symbol now rather
than after the symbol table is frozen. We only do this than after the symbol table is frozen. We only do this
when supporting small data limits because otherwise we when supporting small data limits because otherwise we
pollute the symbol table. */ 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)
{
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")); 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; char * rx_lex_start;
@ -2222,10 +2271,10 @@ md_apply_fix (struct fix * f ATTRIBUTE_UNUSED,
} }
arelent ** arelent **
tc_gen_reloc (asection * seg ATTRIBUTE_UNUSED, fixS * fixp) tc_gen_reloc (asection * sec ATTRIBUTE_UNUSED, fixS * fixp)
{ {
static arelent * reloc[5]; static arelent * reloc[5];
int is_opcode = 0; bfd_boolean is_opcode = FALSE;
if (fixp->fx_r_type == BFD_RELOC_NONE) if (fixp->fx_r_type == BFD_RELOC_NONE)
{ {
@ -2250,8 +2299,10 @@ tc_gen_reloc (asection * seg ATTRIBUTE_UNUSED, fixS * fixp)
&& fixp->fx_subsy) && fixp->fx_subsy)
{ {
fixp->fx_r_type = BFD_RELOC_RX_DIFF; 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 /* Certain BFD relocations cannot be translated directly into
a single (non-Red Hat) RX relocation, but instead need a single (non-Red Hat) RX relocation, but instead need
@ -2283,6 +2334,8 @@ tc_gen_reloc (asection * seg ATTRIBUTE_UNUSED, fixS * fixp)
case 2: case 2:
if (!is_opcode && target_big_endian) if (!is_opcode && target_big_endian)
reloc[3]->howto = bfd_reloc_type_lookup (stdoutput, BFD_RELOC_RX_ABS16_REV); 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 else
reloc[3]->howto = bfd_reloc_type_lookup (stdoutput, BFD_RELOC_RX_ABS16); reloc[3]->howto = bfd_reloc_type_lookup (stdoutput, BFD_RELOC_RX_ABS16);
break; break;

View file

@ -74,11 +74,25 @@ This is the default.
@item -msmall-data-limit @item -msmall-data-limit
This option tells the assembler that the small data limit feature of 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 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 generating an undefined reference to a symbol called @code{__gp} for
the relocations that are needed to support the small data limit 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 feature. This option is not enabled by default as it would otherwise
pollute the symbol table. 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 @end table
@node RX-Modifiers @node RX-Modifiers
@ -86,22 +100,45 @@ pollute the symbol table.
@cindex RX modifiers @cindex RX modifiers
@cindex syntax, RX @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: in RX instruction operands. The general syntax is the following:
@smallexample @smallexample
%modifier(symbol) %gp(symbol)
@end smallexample @end smallexample
@table @code The modifier returns the offset from the @var{__gp} symbol to the
@cindex symbol modifiers 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:
@item %gp @smallexample
@c FIXME: Add documentation here. 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 @samp{%gpreg}
@item %gpreg
The small data address register.
@cindex @samp{%pidreg}
@item %pidreg
The PID base address register.
@end table @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 @node RX-Directives
@section Assembler Directives @section Assembler Directives

View 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> 2011-09-21 David S. Miller <davem@davemloft.net>
* sparc.h (Tag_GNU_Sparc_HWCAPS): New object attribute. * sparc.h (Tag_GNU_Sparc_HWCAPS): New object attribute.

View file

@ -117,6 +117,7 @@ END_RELOC_NUMBERS (R_RX_max)
/* Values for the e_flags field in the ELF header. */ /* Values for the e_flags field in the ELF header. */
#define E_FLAG_RX_64BIT_DOUBLES (1 << 0) #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. */ /* These define the addend field of R_RX_RH_RELAX relocations. */
#define RX_RELAXA_IMM6 0x00000010 /* Imm8/16/24/32 at bit offset 6. */ #define RX_RELAXA_IMM6 0x00000010 /* Imm8/16/24/32 at bit offset 6. */

View 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> 2011-09-30 Alan Modra <amodra@gmail.com>
* ld-powerpc/tocopt.d: Update. * ld-powerpc/tocopt.d: Update.

View file

@ -60,6 +60,14 @@ if ![ld_simple_link $ld tmpdir/phdrs $ldopt] {
set exec_output [prune_warnings $exec_output] set exec_output [prune_warnings $exec_output]
verbose -log $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] { if [regexp $phdrs_regexp $exec_output] {
pass $testname pass $testname
} else { } else {