aboutsummaryrefslogtreecommitdiff
path: root/gas
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 /gas
parentb1c8db38fceb8464f02f1673b52c926c56203593 (diff)
downloadgdb-d4cb0ea0caf03bea93ae6891017bb2301facb33f.zip
gdb-d4cb0ea0caf03bea93ae6891017bb2301facb33f.tar.gz
gdb-d4cb0ea0caf03bea93ae6891017bb2301facb33f.tar.bz2
* 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.
Diffstat (limited to 'gas')
-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
5 files changed, 166 insertions, 19 deletions
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 <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 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=<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 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