From 4b0c052e456421a3c6d7b4c98be3ad0b3bd2ad27 Mon Sep 17 00:00:00 2001 From: Andrew Burgess Date: Wed, 30 Mar 2016 00:02:19 +0100 Subject: arc/nps400 : New cmem instructions and associated relocation Add support for arc/nps400 cmem instructions, these load and store instructions are hard-wired to access "0x57f00000 + 16-bit-offset". Supporting this relocation required some additions to the arc relocation handling in the bfd library, as well as the standard changes required to add a new relocation type. There's a test of the new instructions in the assembler, and a test of the relocation in the linker. bfd/ChangeLog: * reloc.c: Add BFD_RELOC_ARC_NPS_CMEM16 entry. * bfd-in2.h: Regenerate. * libbfd.h: Regenerate. * elf32-arc.c: Add 'opcode/arc.h' include. (struct arc_relocation_data): Add symbol_name. (arc_special_overflow_checks): New function. (arc_do_relocation): Use arc_special_overflow_checks, reindent as required, add an extra comment. (elf_arc_relocate_section): Setup symbol_name in reloc_data. gas/ChangeLog: * testsuite/gas/arc/nps400-3.d: New file. * testsuite/gas/arc/nps400-3.s: New file. include/ChangeLog: * elf/arc-reloc.def: Add ARC_NPS_CMEM16 reloc. * opcode/arc.h (NPS_CMEM_HIGH_VALUE): Define. ld/ChangeLog: * testsuite/ld-arc/arc.exp: New file. * testsuite/ld-arc/nps-1.s: New file. * testsuite/ld-arc/nps-1a.d: New file. * testsuite/ld-arc/nps-1b.d: New file. * testsuite/ld-arc/nps-1b.err: New file. opcodes/ChangeLog: * arc-nps400-tbl.h: Add xldb, xldw, xld, xstb, xstw, and xst instructions. * arc-opc.c (insert_nps_cmem_uimm16): New function. (extract_nps_cmem_uimm16): New function. (arc_operands): Add NPS_XLDST_UIMM16 operand. --- bfd/elf32-arc.c | 93 +++++++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 74 insertions(+), 19 deletions(-) (limited to 'bfd/elf32-arc.c') diff --git a/bfd/elf32-arc.c b/bfd/elf32-arc.c index d67e88c..2df91b1 100644 --- a/bfd/elf32-arc.c +++ b/bfd/elf32-arc.c @@ -26,6 +26,7 @@ #include "elf/arc.h" #include "libiberty.h" #include "opcode/arc-func.h" +#include "opcode/arc.h" #include "arc-plt.h" #ifdef DEBUG @@ -722,6 +723,8 @@ struct arc_relocation_data bfd_signed_vma got_symbol_vma; bfd_boolean should_relocate; + + const char * symbol_name; }; static void @@ -788,6 +791,52 @@ middle_endian_convert (bfd_vma insn, bfd_boolean do_it) return insn; } +/* This function is called for relocations that are otherwise marked as NOT + requiring overflow checks. In here we perform non-standard checks of + the relocation value. */ + +static inline bfd_reloc_status_type +arc_special_overflow_checks (const struct arc_relocation_data reloc_data, + bfd_signed_vma relocation, + struct bfd_link_info *info ATTRIBUTE_UNUSED) +{ + switch (reloc_data.howto->type) + { + case R_ARC_NPS_CMEM16: + if (((relocation >> 16) & 0xffff) != NPS_CMEM_HIGH_VALUE) + { + if (reloc_data.reloc_addend == 0) + (*_bfd_error_handler) + (_("%B(%A+0x%lx): CMEM relocation to `%s' is invalid, " + "16 MSB should be 0x%04x (value is 0x%lx)"), + reloc_data.input_section->owner, + reloc_data.input_section, + reloc_data.reloc_offset, + reloc_data.symbol_name, + NPS_CMEM_HIGH_VALUE, + (relocation)); + else + (*_bfd_error_handler) + (_("%B(%A+0x%lx): CMEM relocation to `%s+0x%lx' is invalid, " + "16 MSB should be 0x%04x (value is 0x%lx)"), + reloc_data.input_section->owner, + reloc_data.input_section, + reloc_data.reloc_offset, + reloc_data.symbol_name, + reloc_data.reloc_addend, + NPS_CMEM_HIGH_VALUE, + (relocation)); + return bfd_reloc_overflow; + } + break; + + default: + break; + } + + return bfd_reloc_ok; +} + #define ME(reloc) (reloc) #define IS_ME(FORMULA,BFD) ((strstr (FORMULA, "ME") != NULL) \ @@ -896,6 +945,7 @@ arc_do_relocation (bfd_byte * contents, bfd_vma orig_insn ATTRIBUTE_UNUSED; bfd * abfd = reloc_data.input_section->owner; struct elf_link_hash_table *htab ATTRIBUTE_UNUSED = elf_hash_table (info); + bfd_reloc_status_type flag; if (reloc_data.should_relocate == FALSE) return bfd_reloc_ok; @@ -936,34 +986,34 @@ arc_do_relocation (bfd_byte * contents, /* Check for relocation overflow. */ if (reloc_data.howto->complain_on_overflow != complain_overflow_dont) - { - bfd_reloc_status_type flag; - flag = bfd_check_overflow (reloc_data.howto->complain_on_overflow, - reloc_data.howto->bitsize, - reloc_data.howto->rightshift, - bfd_arch_bits_per_address (abfd), - relocation); + flag = bfd_check_overflow (reloc_data.howto->complain_on_overflow, + reloc_data.howto->bitsize, + reloc_data.howto->rightshift, + bfd_arch_bits_per_address (abfd), + relocation); + else + flag = arc_special_overflow_checks (reloc_data, relocation, info); #undef DEBUG_ARC_RELOC #define DEBUG_ARC_RELOC(A) debug_arc_reloc (A) - if (flag != bfd_reloc_ok) - { - PR_DEBUG ( "Relocation overflows !!!!\n"); + if (flag != bfd_reloc_ok) + { + PR_DEBUG ( "Relocation overflows !!!!\n"); - DEBUG_ARC_RELOC (reloc_data); + DEBUG_ARC_RELOC (reloc_data); - PR_DEBUG ( - "Relocation value = signed -> %d, unsigned -> %u" - ", hex -> (0x%08x)\n", - (int) relocation, - (unsigned int) relocation, - (unsigned int) relocation); - return flag; - } + PR_DEBUG ( + "Relocation value = signed -> %d, unsigned -> %u" + ", hex -> (0x%08x)\n", + (int) relocation, + (unsigned int) relocation, + (unsigned int) relocation); + return flag; } #undef DEBUG_ARC_RELOC #define DEBUG_ARC_RELOC(A) + /* Write updated instruction back to memory. */ switch (reloc_data.howto->size) { case 2: @@ -1168,6 +1218,10 @@ elf_arc_relocate_section (bfd * output_bfd, reloc_data.sym_value = sym->st_value; reloc_data.sym_section = sec; + reloc_data.symbol_name = + bfd_elf_string_from_elf_section (input_bfd, + symtab_hdr->sh_link, + sym->st_name); /* Mergeable section handling. */ if ((sec->flags & SEC_MERGE) @@ -1284,6 +1338,7 @@ elf_arc_relocate_section (bfd * output_bfd, h = (struct elf_link_hash_entry *) h->root.u.i.link; BFD_ASSERT ((h->dynindx == -1) >= (h->forced_local != 0)); + reloc_data.symbol_name = h->root.root.string; /* If we have encountered a definition for this symbol. */ if (h->root.type == bfd_link_hash_defined || h->root.type == bfd_link_hash_defweak) -- cgit v1.1