Line 1... |
Line 1... |
/* 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.
|
|
|
GAS is free software; you can redistribute it and/or modify
|
GAS is free software; you can redistribute it and/or modify
|
Line 49... |
Line 49... |
static int elf_flags = 0;
|
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,
|
OPTION_LITTLE,
|
OPTION_LITTLE,
|
OPTION_32BIT_DOUBLES,
|
OPTION_32BIT_DOUBLES,
|
OPTION_64BIT_DOUBLES,
|
OPTION_64BIT_DOUBLES,
|
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 ""
|
const char * md_shortopts = RX_SHORTOPTS;
|
const char * md_shortopts = RX_SHORTOPTS;
|
|
|
Line 81... |
Line 88... |
as many of their tests assume conventional section naming. */
|
as many of their tests assume conventional section naming. */
|
{"muse-conventional-section-names", no_argument, NULL, OPTION_CONVENTIONAL_SECTION_NAMES},
|
{"muse-conventional-section-names", no_argument, NULL, OPTION_CONVENTIONAL_SECTION_NAMES},
|
{"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);
|
|
|
int
|
int
|
Line 121... |
Line 130... |
return 1;
|
return 1;
|
|
|
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;
|
}
|
}
|
|
|
void
|
void
|
Line 136... |
Line 154... |
fprintf (stream, _(" --m32bit-doubles [default]\n"));
|
fprintf (stream, _(" --m32bit-doubles [default]\n"));
|
fprintf (stream, _(" --m64bit-doubles\n"));
|
fprintf (stream, _(" --m64bit-doubles\n"));
|
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
|
s_bss (int ignore ATTRIBUTE_UNUSED)
|
s_bss (int ignore ATTRIBUTE_UNUSED)
|
{
|
{
|
Line 582... |
Line 603... |
/* End of list marker. */
|
/* End of list marker. */
|
{ NULL, NULL, 0 }
|
{ NULL, NULL, 0 }
|
};
|
};
|
|
|
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;
|
char * rx_lex_end;
|
char * rx_lex_end;
|
|
|
Line 2220... |
Line 2269... |
if (f->fx_addsy == NULL)
|
if (f->fx_addsy == NULL)
|
f->fx_done = 1;
|
f->fx_done = 1;
|
}
|
}
|
|
|
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)
|
{
|
{
|
reloc[0] = NULL;
|
reloc[0] = NULL;
|
return reloc;
|
return reloc;
|
Line 2248... |
Line 2297... |
|
|
if (fixp->fx_r_type == BFD_RELOC_RX_32_OP
|
if (fixp->fx_r_type == BFD_RELOC_RX_32_OP
|
&& 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
|
multiple RX relocations - handle them here. */
|
multiple RX relocations - handle them here. */
|
switch (fixp->fx_r_type)
|
switch (fixp->fx_r_type)
|
Line 2281... |
Line 2332... |
reloc[3]->howto = bfd_reloc_type_lookup (stdoutput, BFD_RELOC_RX_ABS8);
|
reloc[3]->howto = bfd_reloc_type_lookup (stdoutput, BFD_RELOC_RX_ABS8);
|
break;
|
break;
|
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;
|
case 4:
|
case 4:
|
if (!is_opcode && target_big_endian)
|
if (!is_opcode && target_big_endian)
|