From d4cb0ea0caf03bea93ae6891017bb2301facb33f Mon Sep 17 00:00:00 2001 From: Nick Clifton Date: Wed, 5 Oct 2011 14:13:31 +0000 Subject: * 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. --- 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 +++++++++++++++++++++++++++++----- 5 files changed, 166 insertions(+), 19 deletions(-) (limited to 'gas') 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 -- cgit v1.1