aboutsummaryrefslogtreecommitdiff
path: root/gas/config/tc-tic6x.c
diff options
context:
space:
mode:
authorJoseph Myers <joseph@codesourcery.com>2010-04-20 22:03:00 +0000
committerJoseph Myers <joseph@codesourcery.com>2010-04-20 22:03:00 +0000
commit418205099be3d614ad92c8c78486b1a60b498916 (patch)
tree59ac53127fc8941692ce65e25b6667f9af220bf9 /gas/config/tc-tic6x.c
parent31ef98ae61505d87f8d3098c5fc1dcb19035a6a1 (diff)
downloadgdb-418205099be3d614ad92c8c78486b1a60b498916.zip
gdb-418205099be3d614ad92c8c78486b1a60b498916.tar.gz
gdb-418205099be3d614ad92c8c78486b1a60b498916.tar.bz2
bfd:
* elf32-tic6x.h: New. * elf-bfd.h (enum elf_target_id): Define TIC6X_ELF_DATA. * elf32-tic6x.c (struct elf32_tic6x_obj_tdata, elf32_tic6x_tdata, elf32_tic6x_howto_table_rel, elf32_tic6x_info_to_howto_rel, elf32_tic6x_set_use_rela_p, elf32_tic6x_mkobject, elf32_tic6x_new_section_hook, elf32_tic6x_rel_relocation_p, bfd_elf32_mkobject, bfd_elf32_new_section_hook): New. (elf32_tic6x_reloc_type_lookup, elf32_tic6x_reloc_name_lookup, elf32_tic6x_relocate_section): Handle REL relocations. (elf_info_to_howto_rel): Define to elf32_tic6x_info_to_howto_rel. gas: * config/tc-tic6x.c (OPTION_MGENERATE_REL): New. (md_longopts): Add -mgenerate-rel. (tic6x_generate_rela): New. (md_parse_option): Handle -mgenerate-rel. (md_show_usage): Add comment that -mgenerate-rel is undocumented. (tic6x_init_after_args): New. (md_apply_fix): Correct shift calculations for SB-relative relocations. (md_pcrel_from): Change to tic6x_pcrel_from_section. Do not adjust addresses for relocations referencing symbols in other sections. (tc_gen_reloc): Adjust addend calculations for REL relocations. * config/tc-tic6x.h (MD_PCREL_FROM_SECTION, tic6x_pcrel_from_section, tc_init_after_args, tic6x_init_after_args): New. ld/testsuite: * ld-tic6x/data-reloc-global-rel.d, ld-tic6x/data-reloc-global-rel.s, ld-tic6x/data-reloc-local-r-rel.d, ld-tic6x/data-reloc-local-rel.d, ld-tic6x/mvk-reloc-global-rel.d, ld-tic6x/mvk-reloc-global-rel.s, ld-tic6x/mvk-reloc-local-1-rel.s, ld-tic6x/mvk-reloc-local-2-rel.s, ld-tic6x/mvk-reloc-local-r-rel.d, ld-tic6x/mvk-reloc-local-rel.d, ld-tic6x/pcrel-reloc-global-rel.d, ld-tic6x/pcrel-reloc-local-r-rel.d, ld-tic6x/pcrel-reloc-local-rel.d, ld-tic6x/sbr-reloc-global-rel.d, ld-tic6x/sbr-reloc-global-rel.s, ld-tic6x/sbr-reloc-local-1-rel.s, ld-tic6x/sbr-reloc-local-2-rel.s, ld-tic6x/sbr-reloc-local-r-rel.d, ld-tic6x/sbr-reloc-local-rel.d: New.
Diffstat (limited to 'gas/config/tc-tic6x.c')
-rw-r--r--gas/config/tc-tic6x.c73
1 files changed, 68 insertions, 5 deletions
diff --git a/gas/config/tc-tic6x.c b/gas/config/tc-tic6x.c
index 730b786..d746f94 100644
--- a/gas/config/tc-tic6x.c
+++ b/gas/config/tc-tic6x.c
@@ -24,6 +24,7 @@
#include "safe-ctype.h"
#include "subsegs.h"
#include "opcode/tic6x.h"
+#include "elf32-tic6x.h"
/* Truncate and sign-extend at 32 bits, so that building on a 64-bit
host gives identical results to a 32-bit host. */
@@ -45,7 +46,8 @@ enum
OPTION_MATOMIC,
OPTION_MNO_ATOMIC,
OPTION_MBIG_ENDIAN,
- OPTION_MLITTLE_ENDIAN
+ OPTION_MLITTLE_ENDIAN,
+ OPTION_MGENERATE_REL
};
struct option md_longopts[] =
@@ -55,6 +57,7 @@ struct option md_longopts[] =
{ "mno-atomic", no_argument, NULL, OPTION_MNO_ATOMIC },
{ "mbig-endian", no_argument, NULL, OPTION_MBIG_ENDIAN },
{ "mlittle-endian", no_argument, NULL, OPTION_MLITTLE_ENDIAN },
+ { "mgenerate-rel", no_argument, NULL, OPTION_MGENERATE_REL },
{ NULL, no_argument, NULL, 0 }
};
size_t md_longopts_size = sizeof (md_longopts);
@@ -95,6 +98,9 @@ static bfd_boolean tic6x_long_data_constraints;
/* Whether compact instructions are available. */
static bfd_boolean tic6x_compact_insns;
+/* Whether to generate RELA relocations. */
+static bfd_boolean tic6x_generate_rela = TRUE;
+
/* Table of supported architecture variants. */
typedef struct
{
@@ -162,6 +168,10 @@ md_parse_option (int c, char *arg)
target_big_endian = 0;
break;
+ case OPTION_MGENERATE_REL:
+ tic6x_generate_rela = FALSE;
+ break;
+
default:
return 0;
}
@@ -180,6 +190,8 @@ md_show_usage (FILE *stream ATTRIBUTE_UNUSED)
fprintf (stream, _(" -mno-atomic disable atomic operation instructions\n"));
fprintf (stream, _(" -mbig-endian generate big-endian code\n"));
fprintf (stream, _(" -mlittle-endian generate little-endian code\n"));
+ /* -mgenerate-rel is only for testsuite use and is deliberately
+ undocumented. */
fputc ('\n', stream);
fprintf (stream, _("Supported ARCH values are:"));
@@ -512,6 +524,15 @@ tic6x_cleanup (void)
tic6x_end_of_line ();
}
+/* Do target-specific initialization after arguments have been
+ processed and the output file created. */
+
+void
+tic6x_init_after_args (void)
+{
+ elf32_tic6x_set_use_rela_p (stdoutput, tic6x_generate_rela);
+}
+
/* Handle a data alignment of N bytes. */
void
@@ -3111,8 +3132,25 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED)
if (fixP->fx_done || !seg->use_rela_p)
{
offsetT newval = md_chars_to_number (buf, 4);
+ int shift;
+
+ switch (fixP->fx_r_type)
+ {
+ case BFD_RELOC_C6000_SBR_L16_H:
+ shift = 1;
+ break;
+
+ case BFD_RELOC_C6000_SBR_L16_W:
+ case BFD_RELOC_C6000_SBR_GOT_L16_W:
+ shift = 2;
+ break;
+
+ default:
+ shift = 0;
+ break;
+ }
- MODIFY_VALUE (newval, value, 0, 7, 16);
+ MODIFY_VALUE (newval, value, shift, 7, 16);
if ((value < -0x8000 || value > 0x7fff)
&& (fixP->fx_r_type == BFD_RELOC_C6000_ABS_S16
|| fixP->fx_r_type == BFD_RELOC_C6000_SBR_S16))
@@ -3135,8 +3173,25 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED)
if (fixP->fx_done || !seg->use_rela_p)
{
offsetT newval = md_chars_to_number (buf, 4);
+ int shift;
+
+ switch (fixP->fx_r_type)
+ {
+ case BFD_RELOC_C6000_SBR_H16_H:
+ shift = 17;
+ break;
+
+ case BFD_RELOC_C6000_SBR_H16_W:
+ case BFD_RELOC_C6000_SBR_GOT_H16_W:
+ shift = 18;
+ break;
- MODIFY_VALUE (newval, value, 16, 7, 16);
+ default:
+ shift = 16;
+ break;
+ }
+
+ MODIFY_VALUE (newval, value, shift, 7, 16);
md_number_to_chars (buf, newval, 4);
}
@@ -3348,8 +3403,12 @@ md_operand (expressionS *op ATTRIBUTE_UNUSED)
packet. */
long
-md_pcrel_from (fixS *fixp)
+tic6x_pcrel_from_section (fixS *fixp, segT sec)
{
+ if (fixp->fx_addsy != NULL
+ && (!S_IS_DEFINED (fixp->fx_addsy)
+ || S_GET_SEGMENT (fixp->fx_addsy) != sec))
+ return 0;
return (fixp->fx_where + fixp->fx_frag->fr_address) & ~(long) 0x1f;
}
@@ -3386,7 +3445,7 @@ tc_gen_reloc (asection *section ATTRIBUTE_UNUSED, fixS *fixp)
reloc->sym_ptr_ptr = xmalloc (sizeof (asymbol *));
*reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
- reloc->addend = fixp->fx_offset;
+ reloc->addend = (tic6x_generate_rela ? fixp->fx_offset : 0);
r_type = fixp->fx_r_type;
reloc->howto = bfd_reloc_type_lookup (stdoutput, r_type);
@@ -3398,5 +3457,9 @@ tc_gen_reloc (asection *section ATTRIBUTE_UNUSED, fixS *fixp)
return NULL;
}
+ /* Correct for adjustments bfd_install_relocation will make. */
+ if (reloc->howto->pcrel_offset && reloc->howto->partial_inplace)
+ reloc->addend += reloc->address;
+
return reloc;
}