From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mail-wy0-f175.google.com ([74.125.82.175]) by linuxtogo.org with esmtp (Exim 4.72) (envelope-from ) id 1R22Da-0005nt-Oq for openembedded-devel@lists.openembedded.org; Fri, 09 Sep 2011 16:38:22 +0200 Received: by wyf19 with SMTP id 19so1567494wyf.6 for ; Fri, 09 Sep 2011 07:33:06 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=from:to:cc:subject:date:message-id:x-mailer:in-reply-to:references; bh=zLGiYL97QY+STS/ZVlCZS6SbXZAx23fYoBxpRoS4YCQ=; b=QA9c0Nt47cPiJ1ElIAH0VffzC/5b14Rz5uv34hv7MWqD+djMIEKz/1igltpHlSFH3n 0/nIbNu21XTf6EmToLNOWXQT0uipOv1ymCaw7KTiNLbkbfFLB8QssQatXJ3pDW5bQ8iL Bp2EeiBeZoVN/wigE9sPpgHPEvW4zWt4FWlqc= Received: by 10.227.3.2 with SMTP id 2mr2179000wbl.4.1315578773625; Fri, 09 Sep 2011 07:32:53 -0700 (PDT) Received: from localhost.localdomain (host86-135-215-249.range86-135.btcentralplus.com [86.135.215.249]) by mx.google.com with ESMTPS id et17sm7734129wbb.0.2011.09.09.07.30.28 (version=TLSv1/SSLv3 cipher=OTHER); Fri, 09 Sep 2011 07:32:43 -0700 (PDT) From: Ilya Dmitrichenko To: openembedded-devel@lists.openembedded.org Date: Fri, 9 Sep 2011 16:30:23 +0100 Message-Id: <1315582224-5245-1-git-send-email-errordeveloper@gmail.com> X-Mailer: git-send-email 1.7.3.4 In-Reply-To: <1315579610-3943-1-git-send-email-errordeveloper@gmail.com> References: <1315579610-3943-1-git-send-email-errordeveloper@gmail.com> Subject: [PATCH v2] binutils: Update from 2.20.1 to 2.20.1a X-BeenThere: openembedded-devel@lists.openembedded.org X-Mailman-Version: 2.1.11 Precedence: list Reply-To: openembedded-devel@lists.openembedded.org List-Id: Using the OpenEmbedded metadata to build Distributions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 09 Sep 2011 14:38:22 -0000 Signed-off-by: Ilya Dmitrichenko --- .../binutils-2.20.1/110-arm-eabi-conf.patch | 22 - .../binutils-2.20.1/binutils-2.16.1-e300c2c3.patch | 18 - .../binutils-2.19.1-ld-sysroot.patch | 36 - .../binutils-2.20.1/binutils-nios2-files.patch |41026 -------------------- .../binutils/binutils-2.20.1/binutils-nios2.patch | 650 - .../binutils-uclibc-100-uclibc-conf.patch | 34 - ...binutils-uclibc-300-001_ld_makefile_patch.patch | 50 - ...binutils-uclibc-300-006_better_file_error.patch | 43 - ...ils-uclibc-300-012_check_ldrunpath_length.patch | 47 - .../binutils-uclibc-gas-needs-libm.patch | 38 - .../binutils-x86_64_i386_biarch.patch | 26 - .../binutils-2.20.1/libtool-2.4-update.patch |31174 --------------- .../binutils/binutils-2.20.1/libtool-update.patch | 473 - .../binutils-2.20.1a/110-arm-eabi-conf.patch | 22 + .../binutils-2.16.1-e300c2c3.patch | 18 + .../binutils-2.19.1-ld-sysroot.patch | 36 + .../binutils-2.20.1a/binutils-nios2-files.patch |41026 ++++++++++++++++++++ .../binutils/binutils-2.20.1a/binutils-nios2.patch | 650 + .../binutils-uclibc-100-uclibc-conf.patch | 34 + ...binutils-uclibc-300-001_ld_makefile_patch.patch | 50 + ...binutils-uclibc-300-006_better_file_error.patch | 43 + ...ils-uclibc-300-012_check_ldrunpath_length.patch | 47 + .../binutils-uclibc-gas-needs-libm.patch | 38 + .../binutils-x86_64_i386_biarch.patch | 26 + .../binutils-2.20.1a/libtool-2.4-update.patch |31174 +++++++++++++++ .../binutils/binutils-2.20.1a/libtool-update.patch | 473 + recipes/binutils/binutils-cross-sdk_2.20.1.bb | 4 - recipes/binutils/binutils-cross-sdk_2.20.1a.bb | 4 + recipes/binutils/binutils-cross_2.20.1.bb | 4 - recipes/binutils/binutils-cross_2.20.1a.bb | 4 + recipes/binutils/binutils_2.20.1.bb | 33 - recipes/binutils/binutils_2.20.1a.bb | 33 + 32 files changed, 73678 insertions(+), 73678 deletions(-) delete mode 100644 recipes/binutils/binutils-2.20.1/110-arm-eabi-conf.patch delete mode 100644 recipes/binutils/binutils-2.20.1/binutils-2.16.1-e300c2c3.patch delete mode 100644 recipes/binutils/binutils-2.20.1/binutils-2.19.1-ld-sysroot.patch delete mode 100644 recipes/binutils/binutils-2.20.1/binutils-nios2-files.patch delete mode 100644 recipes/binutils/binutils-2.20.1/binutils-nios2.patch delete mode 100644 recipes/binutils/binutils-2.20.1/binutils-uclibc-100-uclibc-conf.patch delete mode 100644 recipes/binutils/binutils-2.20.1/binutils-uclibc-300-001_ld_makefile_patch.patch delete mode 100644 recipes/binutils/binutils-2.20.1/binutils-uclibc-300-006_better_file_error.patch delete mode 100644 recipes/binutils/binutils-2.20.1/binutils-uclibc-300-012_check_ldrunpath_length.patch delete mode 100644 recipes/binutils/binutils-2.20.1/binutils-uclibc-gas-needs-libm.patch delete mode 100644 recipes/binutils/binutils-2.20.1/binutils-x86_64_i386_biarch.patch delete mode 100644 recipes/binutils/binutils-2.20.1/libtool-2.4-update.patch delete mode 100644 recipes/binutils/binutils-2.20.1/libtool-update.patch create mode 100644 recipes/binutils/binutils-2.20.1a/110-arm-eabi-conf.patch create mode 100644 recipes/binutils/binutils-2.20.1a/binutils-2.16.1-e300c2c3.patch create mode 100644 recipes/binutils/binutils-2.20.1a/binutils-2.19.1-ld-sysroot.patch create mode 100644 recipes/binutils/binutils-2.20.1a/binutils-nios2-files.patch create mode 100644 recipes/binutils/binutils-2.20.1a/binutils-nios2.patch create mode 100644 recipes/binutils/binutils-2.20.1a/binutils-uclibc-100-uclibc-conf.patch create mode 100644 recipes/binutils/binutils-2.20.1a/binutils-uclibc-300-001_ld_makefile_patch.patch create mode 100644 recipes/binutils/binutils-2.20.1a/binutils-uclibc-300-006_better_file_error.patch create mode 100644 recipes/binutils/binutils-2.20.1a/binutils-uclibc-300-012_check_ldrunpath_length.patch create mode 100644 recipes/binutils/binutils-2.20.1a/binutils-uclibc-gas-needs-libm.patch create mode 100644 recipes/binutils/binutils-2.20.1a/binutils-x86_64_i386_biarch.patch create mode 100644 recipes/binutils/binutils-2.20.1a/libtool-2.4-update.patch create mode 100644 recipes/binutils/binutils-2.20.1a/libtool-update.patch delete mode 100644 recipes/binutils/binutils-cross-sdk_2.20.1.bb create mode 100644 recipes/binutils/binutils-cross-sdk_2.20.1a.bb delete mode 100644 recipes/binutils/binutils-cross_2.20.1.bb create mode 100644 recipes/binutils/binutils-cross_2.20.1a.bb delete mode 100644 recipes/binutils/binutils_2.20.1.bb create mode 100644 recipes/binutils/binutils_2.20.1a.bb diff --git a/recipes/binutils/binutils-2.20.1/110-arm-eabi-conf.patch b/recipes/binutils/binutils-2.20.1/110-arm-eabi-conf.patch deleted file mode 100644 index 2623301..0000000 --- a/recipes/binutils/binutils-2.20.1/110-arm-eabi-conf.patch +++ /dev/null @@ -1,22 +0,0 @@ ---- /tmp/configure.ac 2008-06-22 14:14:59.000000000 +0200 -+++ binutils-2.18.50.0.7/configure.ac 2008-06-22 14:15:30.000000000 +0200 -@@ -561,7 +561,7 @@ - noconfigdirs="$noconfigdirs target-libffi target-qthreads" - libgloss_dir=arm - ;; -- arm*-*-linux-gnueabi) -+ arm*-*-linux-gnueabi | arm*-*-linux-uclibcgnueabi) - noconfigdirs="$noconfigdirs target-qthreads" - noconfigdirs="$noconfigdirs target-libobjc" - case ${with_newlib} in ---- /tmp/configure 2008-06-22 14:17:11.000000000 +0200 -+++ binutils-2.18.50.0.7/configure 2008-06-22 14:17:56.000000000 +0200 -@@ -2307,7 +2307,7 @@ - noconfigdirs="$noconfigdirs target-libffi target-qthreads" - libgloss_dir=arm - ;; -- arm*-*-linux-gnueabi) -+ arm*-*-linux-gnueabi | arm*-*-linux-uclibcgnueabi) - noconfigdirs="$noconfigdirs target-qthreads" - noconfigdirs="$noconfigdirs target-libobjc" - case ${with_newlib} in diff --git a/recipes/binutils/binutils-2.20.1/binutils-2.16.1-e300c2c3.patch b/recipes/binutils/binutils-2.20.1/binutils-2.16.1-e300c2c3.patch deleted file mode 100644 index dfe9b18..0000000 --- a/recipes/binutils/binutils-2.20.1/binutils-2.16.1-e300c2c3.patch +++ /dev/null @@ -1,18 +0,0 @@ -Adds support for Freescale Power architecture e300c2 and e300c3 cores. -http://www.bitshrine.org/gpp/tc-fsl-x86lnx-e300c3-nptl-4.0.2-2.src.rpm - -Leon Woestenberg - -Index: binutils-2.19.51.0.3/opcodes/ppc-dis.c -=================================================================== ---- binutils-2.19.51.0.3.orig/opcodes/ppc-dis.c 2009-04-16 00:38:45.000000000 -0700 -+++ binutils-2.19.51.0.3/opcodes/ppc-dis.c 2009-04-16 00:43:56.000000000 -0700 -@@ -132,6 +132,8 @@ - | PPC_OPCODE_POWER6 | PPC_OPCODE_POWER7 | PPC_OPCODE_ALTIVEC - | PPC_OPCODE_VSX), - 0 }, -+ { "pmr", (PPC_OPCODE_PMR), -+ 0 }, - { "ppc", (PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC | PPC_OPCODE_32), - 0 }, - { "ppc32", (PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC | PPC_OPCODE_32), diff --git a/recipes/binutils/binutils-2.20.1/binutils-2.19.1-ld-sysroot.patch b/recipes/binutils/binutils-2.20.1/binutils-2.19.1-ld-sysroot.patch deleted file mode 100644 index b252196..0000000 --- a/recipes/binutils/binutils-2.20.1/binutils-2.19.1-ld-sysroot.patch +++ /dev/null @@ -1,36 +0,0 @@ -http://sourceware.org/bugzilla/show_bug.cgi?id=10340 - -Signed-off-by: Sven Rebhan - -Always try to prepend the sysroot prefix to absolute filenames first. - ---- a/ld/ldfile.c 2009-06-14 12:46:19.000000000 +0200 -+++ b/ld/ldfile.c.new 2009-06-14 12:46:04.000000000 +0200 -@@ -308,18 +308,24 @@ - directory first. */ - if (! entry->is_archive) - { -- if (entry->sysrooted && IS_ABSOLUTE_PATH (entry->filename)) -+ /* For absolute pathnames, try to always open the file in the -+ sysroot first. If this fails, try to open the file at the -+ given location. */ -+ entry->sysrooted = is_sysrooted_pathname(entry->filename, FALSE); -+ if (IS_ABSOLUTE_PATH (entry->filename) && ld_sysroot && ! entry->sysrooted) - { - char *name = concat (ld_sysroot, entry->filename, - (const char *) NULL); - if (ldfile_try_open_bfd (name, entry)) - { - entry->filename = name; -+ entry->sysrooted = TRUE; - return TRUE; - } - free (name); - } -- else if (ldfile_try_open_bfd (entry->filename, entry)) -+ -+ if (ldfile_try_open_bfd (entry->filename, entry)) - { - entry->sysrooted = IS_ABSOLUTE_PATH (entry->filename) - && is_sysrooted_pathname (entry->filename, TRUE); - diff --git a/recipes/binutils/binutils-2.20.1/binutils-nios2-files.patch b/recipes/binutils/binutils-2.20.1/binutils-nios2-files.patch deleted file mode 100644 index 0601aeb..0000000 --- a/recipes/binutils/binutils-2.20.1/binutils-nios2-files.patch +++ /dev/null @@ -1,41026 +0,0 @@ -Index: binutils-2.20.1/bfd/cpu-nios2.c -=================================================================== ---- /dev/null -+++ binutils-2.20.1/bfd/cpu-nios2.c -@@ -0,0 +1,71 @@ -+/* NOT ASSIGNED TO FSF. COPYRIGHT ALTERA. */ -+/* bfd back-end for Altera Nios II support -+ -+ Copyright (C) 2003 -+ by Nigel Gray (ngray@altera.com). -+ -+This file is part of BFD, the Binary File Descriptor library. -+ -+This program is free software; you can redistribute it and/or modify -+it under the terms of the GNU General Public License as published by -+the Free Software Foundation; either version 2 of the License, or -+(at your option) any later version. -+ -+This program is distributed in the hope that it will be useful, -+but WITHOUT ANY WARRANTY; without even the implied warranty of -+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+GNU General Public License for more details. -+ -+You should have received a copy of the GNU General Public License -+along with this program; if not, write to the Free Software -+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -+ -+#include "bfd.h" -+#include "sysdep.h" -+#include "libbfd.h" -+ -+static const bfd_arch_info_type *nios2_compatible -+ (const bfd_arch_info_type *, const bfd_arch_info_type *); -+ -+/* The default routine tests bits_per_word, which is wrong on mips as -+ mips word size doesn't correlate with reloc size. */ -+ -+static const bfd_arch_info_type * -+nios2_compatible (const bfd_arch_info_type *a, const bfd_arch_info_type *b) -+{ -+ if (a->arch != b->arch) -+ return NULL; -+ -+ /* Machine compatibility is checked in -+ _bfd_mips_elf_merge_private_bfd_data. */ -+ -+ return a; -+} -+ -+#define N(BITS_WORD, BITS_ADDR, NUMBER, PRINT, DEFAULT, NEXT) \ -+ { \ -+ BITS_WORD, /* bits in a word */ \ -+ BITS_ADDR, /* bits in an address */ \ -+ 8, /* 8 bits in a byte */ \ -+ bfd_arch_nios2, \ -+ NUMBER, \ -+ "nios2", \ -+ PRINT, \ -+ 3, \ -+ DEFAULT, \ -+ nios2_compatible, \ -+ bfd_default_scan, \ -+ NEXT, \ -+ } -+ -+#define NN(index) (&arch_info_struct[(index) + 1]) -+ -+static const bfd_arch_info_type arch_info_struct[] = -+{ -+ N (32, 32, bfd_mach_nios2, "nios2", FALSE, 0), -+}; -+ -+/* There is only one architecture - but we give the default a machine number of 0 -+ so the linker can distinguish it */ -+const bfd_arch_info_type bfd_nios2_arch = -+N (32, 32, 0, "nios2", TRUE, &arch_info_struct[0]); -Index: binutils-2.20.1/bfd/elf32-nios2.c -=================================================================== ---- /dev/null -+++ binutils-2.20.1/bfd/elf32-nios2.c -@@ -0,0 +1,5003 @@ -+/* NOT ASSIGNED TO FSF. COPYRIGHT ALTERA. */ -+/* New Jersey-specific support for 32-bit ELF -+ -+ Copyright (C) 2005 -+ by Nigel Gray (ngray@altera.com). -+ -+ Copyright (C) 2008, CodeSourcery Inc. -+ -+ -+This file is part of BFD, the Binary File Descriptor library. -+ -+This program is free software; you can redistribute it and/or modify -+it under the terms of the GNU General Public License as published by -+the Free Software Foundation; either version 2 of the License, or -+(at your option) any later version. -+ -+This program is distributed in the hope that it will be useful, -+but WITHOUT ANY WARRANTY; without even the implied warranty of -+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+GNU General Public License for more details. -+ -+You should have received a copy of the GNU General Public License -+along with this program; if not, write to the Free Software -+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -+ -+/* This file handles Altera New Jersey ELF targets */ -+ -+#include "bfd.h" -+#include "sysdep.h" -+#include "libbfd.h" -+#include "bfdlink.h" -+#include "genlink.h" -+#include "elf-bfd.h" -+#include "elf/nios2.h" -+#include "opcode/nios2.h" -+ -+/* Use RELA relocations. */ -+#ifndef USE_RELA -+#define USE_RELA -+#endif -+ -+#ifdef USE_REL -+#undef USE_REL -+#endif -+ -+/* Function prototypes. */ -+ -+static reloc_howto_type *nios2_elf32_bfd_reloc_type_lookup -+ (bfd *, bfd_reloc_code_real_type); -+ -+static bfd_boolean nios2_elf32_relax_section -+ (bfd *, asection *, struct bfd_link_info *, bfd_boolean *); -+#if 0 -+static bfd_boolean nios2_elf32_relax_delete_bytes -+ (bfd *, asection *, bfd_vma, int); -+#endif -+static reloc_howto_type *nios2_elf32_rtype_to_howto -+ (unsigned int r_type, bfd_boolean rela_p); -+ -+static void nios2_elf32_info_to_howto -+ (bfd * abfd, arelent * cache_ptr, Elf_Internal_Rela * dst); -+ -+static bfd_boolean nios2_elf32_relocate_section -+ (bfd * output_bfd, struct bfd_link_info * info, bfd * input_bfd, -+ asection * input_section, bfd_byte * contents, -+ Elf_Internal_Rela * relocs, Elf_Internal_Sym * local_syms, -+ asection ** local_sections); -+ -+static reloc_howto_type *lookup_howto (unsigned int rtype); -+ -+static bfd_reloc_status_type nios2_elf_final_gp -+ (bfd *, asymbol *, bfd_boolean, char **, bfd_vma *, -+ struct bfd_link_info *); -+ -+static bfd_boolean nios2_elf_assign_gp -+ (bfd *, bfd_vma *, struct bfd_link_info *); -+ -+static bfd_reloc_status_type nios2_elf32_ignore_reloc -+ (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **); -+ -+static bfd_reloc_status_type nios2_elf32_hi16_relocate -+ (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **); -+ -+static bfd_reloc_status_type nios2_elf32_lo16_relocate -+ (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **); -+ -+static bfd_reloc_status_type nios2_elf32_hiadj16_relocate -+ (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **); -+ -+static bfd_reloc_status_type nios2_elf32_pcrel_lo16_relocate -+ (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **); -+ -+static bfd_reloc_status_type nios2_elf32_pcrel_hiadj16_relocate -+ (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **); -+ -+static bfd_reloc_status_type nios2_elf32_pcrel16_relocate -+ (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **); -+ -+static bfd_reloc_status_type nios2_elf32_call26_relocate -+ (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **); -+ -+static bfd_reloc_status_type nios2_elf32_gprel_relocate -+ (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **); -+ -+static bfd_reloc_status_type nios2_elf32_ujmp_relocate -+ (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **); -+ -+static bfd_reloc_status_type nios2_elf32_cjmp_relocate -+ (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **); -+ -+static bfd_reloc_status_type nios2_elf32_callr_relocate -+ (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **); -+ -+static bfd_reloc_status_type nios2_elf32_do_hi16_relocate -+ (bfd *, reloc_howto_type *, asection *, -+ bfd_byte *, bfd_vma, bfd_vma, bfd_vma); -+ -+static bfd_reloc_status_type nios2_elf32_do_lo16_relocate -+ (bfd *, reloc_howto_type *, asection *, -+ bfd_byte *, bfd_vma, bfd_vma, bfd_vma); -+ -+static bfd_reloc_status_type nios2_elf32_do_hiadj16_relocate -+ (bfd *, reloc_howto_type *, asection *, -+ bfd_byte *, bfd_vma, bfd_vma, bfd_vma); -+ -+static bfd_reloc_status_type nios2_elf32_do_pcrel_lo16_relocate -+ (bfd *, reloc_howto_type *, asection *, -+ bfd_byte *, bfd_vma, bfd_vma, bfd_vma); -+ -+static bfd_reloc_status_type nios2_elf32_do_pcrel_hiadj16_relocate -+ (bfd *, reloc_howto_type *, asection *, -+ bfd_byte *, bfd_vma, bfd_vma, bfd_vma); -+ -+static bfd_reloc_status_type nios2_elf32_do_pcrel16_relocate -+ (bfd *, reloc_howto_type *, asection *, -+ bfd_byte *, bfd_vma, bfd_vma, bfd_vma); -+ -+static bfd_reloc_status_type nios2_elf32_do_call26_relocate -+ (bfd *, reloc_howto_type *, asection *, -+ bfd_byte *, bfd_vma, bfd_vma, bfd_vma); -+ -+static bfd_reloc_status_type nios2_elf32_do_gprel_relocate -+ (bfd *, reloc_howto_type *, asection *, -+ bfd_byte *, bfd_vma, bfd_vma, bfd_vma); -+ -+static bfd_reloc_status_type nios2_elf32_do_ujmp_relocate -+ (bfd *, reloc_howto_type *, asection *, -+ bfd_byte *, bfd_vma, bfd_vma, bfd_vma); -+ -+static bfd_reloc_status_type nios2_elf32_do_cjmp_relocate -+ (bfd *, reloc_howto_type *, asection *, -+ bfd_byte *, bfd_vma, bfd_vma, bfd_vma); -+ -+static bfd_reloc_status_type nios2_elf32_do_callr_relocate -+ (bfd *, reloc_howto_type *, asection *, -+ bfd_byte *, bfd_vma, bfd_vma, bfd_vma); -+ -+static bfd_boolean nios2_elf32_section_from_shdr -+ (bfd *, Elf_Internal_Shdr *, const char *name, int shindex); -+ -+static bfd_boolean nios2_elf32_section_flags -+ (flagword *, const Elf_Internal_Shdr *); -+ -+static bfd_boolean nios2_elf32_fake_sections -+ (bfd *, Elf_Internal_Shdr *, asection *); -+ -+ -+ -+static bfd_boolean nios2_elf32_check_relocs -+ (bfd *, struct bfd_link_info *, asection *, -+ const Elf_Internal_Rela *); -+ -+static asection *nios2_elf32_gc_mark_hook (asection * sec, -+ struct bfd_link_info * -+ info, -+ Elf_Internal_Rela * rel, -+ struct elf_link_hash_entry -+ * h, -+ Elf_Internal_Sym * sym); -+ -+void -+_bfd_set_link_info (struct bfd_link_info *info); -+ -+void -+_bfd_set_force_make_executable (bfd_boolean force); -+ -+ -+/* Target vector. */ -+extern const bfd_target bfd_elf32_littlenios2_vec; -+extern const bfd_target bfd_elf32_bignios2_vec; -+ -+/* Offset of tp and dtp pointers from start of TLS block. */ -+#define TP_OFFSET 0x7000 -+#define DTP_OFFSET 0x8000 -+ -+/* The relocation table used for SHT_REL sections. */ -+ -+static reloc_howto_type elf_nios2_howto_table_rel[] = { -+ /* No relocation. */ -+ HOWTO (R_NIOS2_NONE, /* type */ -+ 0, /* rightshift */ -+ 0, /* size (0 = byte, 1 = short, 2 = long) */ -+ 0, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_dont, /* complain_on_overflow */ -+ bfd_elf_generic_reloc, /* special_function */ -+ "R_NIOS2_NONE", /* name */ -+ FALSE, /* partial_inplace */ -+ 0, /* src_mask */ -+ 0, /* dst_mask */ -+ FALSE), /* pcrel_offset */ -+ -+ /* 16-bit signed immediate relocation */ -+ HOWTO (R_NIOS2_S16, /* type */ -+ 0, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 16, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 6, /* bitpos */ -+ complain_overflow_signed, /* complain on overflow */ -+ bfd_elf_generic_reloc, /* special function */ -+ "R_NIOS2_S16", /* name */ -+ FALSE, /* partial_inplace */ -+ 0x003fffc0, /* src_mask */ -+ 0x003fffc0, /* dest_mask */ -+ FALSE), /* pcrel_offset */ -+ -+ /* 16-bit unsigned immediate relocation */ -+ HOWTO (R_NIOS2_U16, /* type */ -+ 0, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 16, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 6, /* bitpos */ -+ complain_overflow_unsigned, /* complain on overflow */ -+ bfd_elf_generic_reloc, /* special function */ -+ "R_NIOS2_U16", /* name */ -+ FALSE, /* partial_inplace */ -+ 0x003fffc0, /* src_mask */ -+ 0x003fffc0, /* dest_mask */ -+ FALSE), /* pcrel_offset */ -+ -+ HOWTO (R_NIOS2_PCREL16, /* type */ -+ 0, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 16, /* bitsize */ -+ TRUE, /* pc_relative */ -+ 6, /* bitpos */ -+ complain_overflow_signed, /* complain on overflow */ -+ nios2_elf32_pcrel16_relocate, /* special function */ -+ "R_NIOS2_PCREL16", /* name */ -+ FALSE, /* partial_inplace */ -+ 0x003fffc0, /* src_mask */ -+ 0x003fffc0, /* dest_mask */ -+ TRUE), /* pcrel_offset */ -+ -+ HOWTO (R_NIOS2_CALL26, /* type */ -+ 2, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 26, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 6, /* bitpos */ -+ complain_overflow_dont, /* complain on overflow */ -+ nios2_elf32_call26_relocate, /* special function */ -+ "R_NIOS2_CALL26", /* name */ -+ FALSE, /* partial_inplace */ -+ 0xffffffc0, /* src_mask */ -+ 0xffffffc0, /* dst_mask */ -+ FALSE), /* pcrel_offset */ -+ -+ HOWTO (R_NIOS2_IMM5, -+ 0, -+ 2, -+ 5, -+ FALSE, -+ 6, -+ complain_overflow_bitfield, -+ bfd_elf_generic_reloc, -+ "R_NIOS2_IMM5", -+ FALSE, -+ 0x000007c0, -+ 0x000007c0, -+ FALSE), -+ -+ HOWTO (R_NIOS2_CACHE_OPX, -+ 0, -+ 2, -+ 5, -+ FALSE, -+ 22, -+ complain_overflow_bitfield, -+ bfd_elf_generic_reloc, -+ "R_NIOS2_CACHE_OPX", -+ FALSE, -+ 0x07c00000, -+ 0x07c00000, -+ FALSE), -+ -+ HOWTO (R_NIOS2_IMM6, -+ 0, -+ 2, -+ 6, -+ FALSE, -+ 6, -+ complain_overflow_bitfield, -+ bfd_elf_generic_reloc, -+ "R_NIOS2_IMM6", -+ FALSE, -+ 0x00000fc0, -+ 0x00000fc0, -+ FALSE), -+ -+ HOWTO (R_NIOS2_IMM8, -+ 0, -+ 2, -+ 8, -+ FALSE, -+ 6, -+ complain_overflow_bitfield, -+ bfd_elf_generic_reloc, -+ "R_NIOS2_IMM8", -+ FALSE, -+ 0x00003fc0, -+ 0x00003fc0, -+ FALSE), -+ -+ HOWTO (R_NIOS2_HI16, -+ 0, -+ 2, -+ 32, -+ FALSE, -+ 6, -+ complain_overflow_dont, -+ nios2_elf32_hi16_relocate, -+ "R_NIOS2_HI16", -+ FALSE, -+ 0x003fffc0, -+ 0x003fffc0, -+ FALSE), -+ -+ HOWTO (R_NIOS2_LO16, -+ 0, -+ 2, -+ 32, -+ FALSE, -+ 6, -+ complain_overflow_dont, -+ nios2_elf32_lo16_relocate, -+ "R_NIOS2_LO16", -+ FALSE, -+ 0x003fffc0, -+ 0x003fffc0, -+ FALSE), -+ -+ HOWTO (R_NIOS2_HIADJ16, -+ 0, -+ 2, -+ 32, -+ FALSE, -+ 6, -+ complain_overflow_dont, -+ nios2_elf32_hiadj16_relocate, -+ "R_NIOS2_HIADJ16", -+ FALSE, -+ 0x003fffc0, -+ 0x003fffc0, -+ FALSE), -+ -+ HOWTO (R_NIOS2_BFD_RELOC_32, -+ 0, -+ 2, /* long */ -+ 32, -+ FALSE, -+ 0, -+ complain_overflow_dont, -+ bfd_elf_generic_reloc, -+ "R_NIOS2_BFD_RELOC32", -+ FALSE, -+ 0xffffffff, -+ 0xffffffff, -+ FALSE), -+ -+ HOWTO (R_NIOS2_BFD_RELOC_16, -+ 0, -+ 1, /* short */ -+ 16, -+ FALSE, -+ 0, -+ complain_overflow_bitfield, -+ bfd_elf_generic_reloc, -+ "R_NIOS2_BFD_RELOC16", -+ FALSE, -+ 0x0000ffff, -+ 0x0000ffff, -+ FALSE), -+ -+ HOWTO (R_NIOS2_BFD_RELOC_8, -+ 0, -+ 0, /* byte */ -+ 8, -+ FALSE, -+ 0, -+ complain_overflow_bitfield, -+ bfd_elf_generic_reloc, -+ "R_NIOS2_BFD_RELOC8", -+ FALSE, -+ 0x000000ff, -+ 0x000000ff, -+ FALSE), -+ -+ HOWTO (R_NIOS2_GPREL, -+ 0, -+ 2, -+ 32, -+ FALSE, -+ 6, -+ complain_overflow_dont, -+ nios2_elf32_gprel_relocate, -+ "R_NIOS2_GPREL", -+ FALSE, -+ 0x003fffc0, -+ 0x003fffc0, -+ FALSE), -+ -+ HOWTO (R_NIOS2_GNU_VTINHERIT, -+ 0, -+ 2, /* short */ -+ 0, -+ FALSE, -+ 0, -+ complain_overflow_dont, -+ NULL, -+ "R_NIOS2_GNU_VTINHERIT", -+ FALSE, -+ 0, -+ 0, -+ FALSE), -+ -+ HOWTO (R_NIOS2_GNU_VTENTRY, -+ 0, -+ 2, /* byte */ -+ 0, -+ FALSE, -+ 0, -+ complain_overflow_dont, -+ _bfd_elf_rel_vtable_reloc_fn, -+ "R_NIOS2_GNU_VTENTRY", -+ FALSE, -+ 0, -+ 0, -+ FALSE), -+ -+ HOWTO (R_NIOS2_UJMP, -+ 0, -+ 2, -+ 32, -+ FALSE, -+ 6, -+ complain_overflow_dont, -+ nios2_elf32_ujmp_relocate, -+ "R_NIOS2_UJMP", -+ FALSE, -+ 0x003fffc0, -+ 0x003fffc0, -+ FALSE), -+ -+ HOWTO (R_NIOS2_CJMP, -+ 0, -+ 2, -+ 32, -+ FALSE, -+ 6, -+ complain_overflow_dont, -+ nios2_elf32_cjmp_relocate, -+ "R_NIOS2_CJMP", -+ FALSE, -+ 0x003fffc0, -+ 0x003fffc0, -+ FALSE), -+ -+ HOWTO (R_NIOS2_CALLR, -+ 0, -+ 2, -+ 32, -+ FALSE, -+ 6, -+ complain_overflow_dont, -+ nios2_elf32_callr_relocate, -+ "R_NIOS2_CALLR", -+ FALSE, -+ 0x003fffc0, -+ 0x003fffc0, -+ FALSE), -+ -+ HOWTO (R_NIOS2_ALIGN, -+ 0, -+ 2, -+ 0, -+ FALSE, -+ 0, -+ complain_overflow_dont, -+ nios2_elf32_ignore_reloc, -+ "R_NIOS2_ALIGN", -+ FALSE, -+ 0, -+ 0, -+ TRUE), -+ -+ -+ HOWTO (R_NIOS2_GOT16, -+ 0, -+ 2, -+ 16, -+ FALSE, -+ 6, -+ complain_overflow_bitfield, -+ bfd_elf_generic_reloc, -+ "R_NIOS2_GOT16", -+ FALSE, -+ 0x003fffc0, -+ 0x003fffc0, -+ FALSE), -+ -+ HOWTO (R_NIOS2_CALL16, -+ 0, -+ 2, -+ 16, -+ FALSE, -+ 6, -+ complain_overflow_bitfield, -+ bfd_elf_generic_reloc, -+ "R_NIOS2_CALL16", -+ FALSE, -+ 0x003fffc0, -+ 0x003fffc0, -+ FALSE), -+ -+ HOWTO (R_NIOS2_GOTOFF_LO, -+ 0, -+ 2, -+ 16, -+ FALSE, -+ 6, -+ complain_overflow_dont, -+ bfd_elf_generic_reloc, -+ "R_NIOS2_GOTOFF_LO", -+ FALSE, -+ 0x003fffc0, -+ 0x003fffc0, -+ FALSE), -+ -+ HOWTO (R_NIOS2_GOTOFF_HA, -+ 0, -+ 2, -+ 16, -+ FALSE, -+ 6, -+ complain_overflow_dont, -+ bfd_elf_generic_reloc, -+ "R_NIOS2_GOTOFF_HA", -+ FALSE, -+ 0x003fffc0, -+ 0x003fffc0, -+ FALSE), -+ -+ HOWTO (R_NIOS2_PCREL_LO, -+ 0, -+ 2, -+ 16, -+ TRUE, -+ 6, -+ complain_overflow_dont, -+ nios2_elf32_pcrel_lo16_relocate, -+ "R_NIOS2_PCREL_LO", -+ FALSE, -+ 0x003fffc0, -+ 0x003fffc0, -+ TRUE), -+ -+ HOWTO (R_NIOS2_PCREL_HA, -+ 0, -+ 2, -+ 16, -+ FALSE, /* This is a PC-relative relocation, but we need to subtract -+ PC ourselves before the HIADJ. */ -+ 6, -+ complain_overflow_dont, -+ nios2_elf32_pcrel_hiadj16_relocate, -+ "R_NIOS2_PCREL_HA", -+ FALSE, -+ 0x003fffc0, -+ 0x003fffc0, -+ TRUE), -+ -+ HOWTO (R_NIOS2_TLS_GD16, -+ 0, -+ 2, -+ 16, -+ FALSE, -+ 6, -+ complain_overflow_bitfield, -+ bfd_elf_generic_reloc, -+ "R_NIOS2_TLS_GD16", -+ FALSE, -+ 0x003fffc0, -+ 0x003fffc0, -+ FALSE), -+ -+ HOWTO (R_NIOS2_TLS_LDM16, -+ 0, -+ 2, -+ 16, -+ FALSE, -+ 6, -+ complain_overflow_bitfield, -+ bfd_elf_generic_reloc, -+ "R_NIOS2_TLS_LDM16", -+ FALSE, -+ 0x003fffc0, -+ 0x003fffc0, -+ FALSE), -+ -+ HOWTO (R_NIOS2_TLS_LDO16, -+ 0, -+ 2, -+ 16, -+ FALSE, -+ 6, -+ complain_overflow_bitfield, -+ bfd_elf_generic_reloc, -+ "R_NIOS2_TLS_LDO16", -+ FALSE, -+ 0x003fffc0, -+ 0x003fffc0, -+ FALSE), -+ -+ HOWTO (R_NIOS2_TLS_IE16, -+ 0, -+ 2, -+ 16, -+ FALSE, -+ 6, -+ complain_overflow_bitfield, -+ bfd_elf_generic_reloc, -+ "R_NIOS2_TLS_IE16", -+ FALSE, -+ 0x003fffc0, -+ 0x003fffc0, -+ FALSE), -+ -+ HOWTO (R_NIOS2_TLS_LE16, -+ 0, -+ 2, -+ 16, -+ FALSE, -+ 6, -+ complain_overflow_bitfield, -+ bfd_elf_generic_reloc, -+ "R_NIOS2_TLS_LE16", -+ FALSE, -+ 0x003fffc0, -+ 0x003fffc0, -+ FALSE), -+ -+ HOWTO (R_NIOS2_TLS_DTPMOD, -+ 0, -+ 2, -+ 32, -+ FALSE, -+ 0, -+ complain_overflow_dont, -+ bfd_elf_generic_reloc, -+ "R_NIOS2_TLS_DTPMOD", -+ FALSE, -+ 0xffffffff, -+ 0xffffffff, -+ FALSE), -+ -+ HOWTO (R_NIOS2_TLS_DTPREL, -+ 0, -+ 2, -+ 32, -+ FALSE, -+ 0, -+ complain_overflow_dont, -+ bfd_elf_generic_reloc, -+ "R_NIOS2_TLS_DTPREL", -+ FALSE, -+ 0xffffffff, -+ 0xffffffff, -+ FALSE), -+ -+ HOWTO (R_NIOS2_TLS_TPREL, -+ 0, -+ 2, -+ 32, -+ FALSE, -+ 0, -+ complain_overflow_dont, -+ bfd_elf_generic_reloc, -+ "R_NIOS2_TLS_TPREL", -+ FALSE, -+ 0xffffffff, -+ 0xffffffff, -+ FALSE), -+ -+ HOWTO (R_NIOS2_COPY, -+ 0, -+ 2, -+ 32, -+ FALSE, -+ 0, -+ complain_overflow_dont, -+ bfd_elf_generic_reloc, -+ "R_NIOS2_COPY", -+ FALSE, -+ 0, -+ 0, -+ FALSE), -+ -+ HOWTO (R_NIOS2_GLOB_DAT, -+ 0, -+ 2, -+ 32, -+ FALSE, -+ 0, -+ complain_overflow_dont, -+ bfd_elf_generic_reloc, -+ "R_NIOS2_GLOB_DAT", -+ FALSE, -+ 0xffffffff, -+ 0xffffffff, -+ FALSE), -+ -+ HOWTO (R_NIOS2_JUMP_SLOT, -+ 0, -+ 2, -+ 32, -+ FALSE, -+ 0, -+ complain_overflow_dont, -+ bfd_elf_generic_reloc, -+ "R_NIOS2_JUMP_SLOT", -+ FALSE, -+ 0xffffffff, -+ 0xffffffff, -+ FALSE), -+ -+ HOWTO (R_NIOS2_RELATIVE, -+ 0, -+ 2, -+ 32, -+ FALSE, -+ 0, -+ complain_overflow_dont, -+ bfd_elf_generic_reloc, -+ "R_NIOS2_RELATIVE", -+ FALSE, -+ 0xffffffff, -+ 0xffffffff, -+ FALSE), -+ -+ HOWTO (R_NIOS2_GOTOFF, -+ 0, -+ 2, -+ 32, -+ FALSE, -+ 0, -+ complain_overflow_dont, -+ bfd_elf_generic_reloc, -+ "R_NIOS2_GOTOFF", -+ FALSE, -+ 0xffffffff, -+ 0xffffffff, -+ FALSE), -+ -+/* Add other relocations here. */ -+}; -+ -+static unsigned char elf_code_to_howto_index[R_NIOS2_ILLEGAL + 1]; -+ -+static reloc_howto_type * -+lookup_howto (unsigned int rtype) -+{ -+ static int initialized = 0; -+ int i; -+ int howto_tbl_size = (int) (sizeof (elf_nios2_howto_table_rel) -+ / sizeof (elf_nios2_howto_table_rel[0])); -+ -+ if (!initialized) -+ { -+ initialized = 1; -+ memset (elf_code_to_howto_index, 0xff, -+ sizeof (elf_code_to_howto_index)); -+ for (i = 0; i < howto_tbl_size; i++) -+ elf_code_to_howto_index[elf_nios2_howto_table_rel[i].type] = i; -+ } -+ -+ BFD_ASSERT (rtype <= R_NIOS2_ILLEGAL); -+ i = elf_code_to_howto_index[rtype]; -+ if (i >= howto_tbl_size) -+ return 0; -+ return elf_nios2_howto_table_rel + i; -+} -+ -+/* Map for converting BFD reloc types to New Jersey reloc types. */ -+struct elf_reloc_map -+{ -+ bfd_reloc_code_real_type bfd_val; -+ enum elf_nios2_reloc_type elf_val; -+}; -+ -+static const struct elf_reloc_map nios2_reloc_map[] = { -+ {BFD_RELOC_NIOS2_S16, R_NIOS2_S16}, -+ {BFD_RELOC_NIOS2_U16, R_NIOS2_U16}, -+ {BFD_RELOC_16_PCREL, R_NIOS2_PCREL16}, -+ {BFD_RELOC_NIOS2_CALL26, R_NIOS2_CALL26}, -+ {BFD_RELOC_NIOS2_IMM5, R_NIOS2_IMM5}, -+ {BFD_RELOC_NIOS2_CACHE_OPX, R_NIOS2_CACHE_OPX}, -+ {BFD_RELOC_NIOS2_IMM6, R_NIOS2_IMM6}, -+ {BFD_RELOC_NIOS2_IMM8, R_NIOS2_IMM8}, -+ {BFD_RELOC_NIOS2_HI16, R_NIOS2_HI16}, -+ {BFD_RELOC_NIOS2_LO16, R_NIOS2_LO16}, -+ {BFD_RELOC_NIOS2_HIADJ16, R_NIOS2_HIADJ16}, -+ {BFD_RELOC_32, R_NIOS2_BFD_RELOC_32}, -+ {BFD_RELOC_16, R_NIOS2_BFD_RELOC_16}, -+ {BFD_RELOC_8, R_NIOS2_BFD_RELOC_8}, -+ {BFD_RELOC_NIOS2_GPREL, R_NIOS2_GPREL}, -+ {BFD_RELOC_VTABLE_INHERIT, R_NIOS2_GNU_VTINHERIT}, -+ {BFD_RELOC_VTABLE_ENTRY, R_NIOS2_GNU_VTENTRY}, -+ {BFD_RELOC_NIOS2_UJMP, R_NIOS2_UJMP}, -+ {BFD_RELOC_NIOS2_CJMP, R_NIOS2_CJMP}, -+ {BFD_RELOC_NIOS2_CALLR, R_NIOS2_CALLR}, -+ {BFD_RELOC_NIOS2_ALIGN, R_NIOS2_ALIGN}, -+ {BFD_RELOC_NIOS2_GOT16, R_NIOS2_GOT16}, -+ {BFD_RELOC_NIOS2_CALL16, R_NIOS2_CALL16}, -+ {BFD_RELOC_NIOS2_GOTOFF_LO, R_NIOS2_GOTOFF_LO}, -+ {BFD_RELOC_NIOS2_GOTOFF_HA, R_NIOS2_GOTOFF_HA}, -+ {BFD_RELOC_NIOS2_PCREL_LO, R_NIOS2_PCREL_LO}, -+ {BFD_RELOC_NIOS2_PCREL_HA, R_NIOS2_PCREL_HA}, -+ {BFD_RELOC_NIOS2_TLS_GD16, R_NIOS2_TLS_GD16}, -+ {BFD_RELOC_NIOS2_TLS_LDM16, R_NIOS2_TLS_LDM16}, -+ {BFD_RELOC_NIOS2_TLS_LDO16, R_NIOS2_TLS_LDO16}, -+ {BFD_RELOC_NIOS2_TLS_IE16, R_NIOS2_TLS_IE16}, -+ {BFD_RELOC_NIOS2_TLS_LE16, R_NIOS2_TLS_LE16}, -+ {BFD_RELOC_NIOS2_TLS_DTPMOD, R_NIOS2_TLS_DTPMOD}, -+ {BFD_RELOC_NIOS2_TLS_DTPREL, R_NIOS2_TLS_DTPREL}, -+ {BFD_RELOC_NIOS2_TLS_TPREL, R_NIOS2_TLS_TPREL}, -+ {BFD_RELOC_NIOS2_COPY, R_NIOS2_COPY}, -+ {BFD_RELOC_NIOS2_GLOB_DAT, R_NIOS2_GLOB_DAT}, -+ {BFD_RELOC_NIOS2_JUMP_SLOT, R_NIOS2_JUMP_SLOT}, -+ {BFD_RELOC_NIOS2_RELATIVE, R_NIOS2_RELATIVE}, -+ {BFD_RELOC_NIOS2_GOTOFF, R_NIOS2_GOTOFF} -+}; -+ -+/* The Nios II linker needs to keep track of the number of relocs that it -+ decides to copy as dynamic relocs in check_relocs for each symbol. -+ This is so that it can later discard them if they are found to be -+ unnecessary. We store the information in a field extending the -+ regular ELF linker hash table. */ -+ -+struct elf32_nios2_dyn_relocs -+{ -+ struct elf32_nios2_dyn_relocs *next; -+ -+ /* The input section of the reloc. */ -+ asection *sec; -+ -+ /* Total number of relocs copied for the input section. */ -+ bfd_size_type count; -+ -+ /* Number of pc-relative relocs copied for the input section. */ -+ bfd_size_type pc_count; -+}; -+ -+/* Nios II ELF linker hash entry. */ -+ -+struct elf32_nios2_link_hash_entry -+{ -+ struct elf_link_hash_entry root; -+ -+ /* Track dynamic relocs copied for this symbol. */ -+ struct elf32_nios2_dyn_relocs *dyn_relocs; -+ -+#define GOT_UNKNOWN 0 -+#define GOT_NORMAL 1 -+#define GOT_TLS_GD 2 -+#define GOT_TLS_IE 4 -+ unsigned char tls_type; -+ -+ /* We need to detect and take special action for symbols which are only -+ referenced with %call() and not with %got(). Such symbols do not need -+ a dynamic GOT reloc in shared objects, only a dynamic PLT reloc. Lazy -+ linking will not work if the dynamic GOT reloc exists. -+ To check for this condition efficiently, we compare got_types_used against -+ CALL16_USED, meaning -+ (got_types_used & (GOT16_USED | CALL16_USED)) == CALL16_USED. */ -+#define GOT16_USED 1 -+#define CALL16_USED 2 -+ unsigned char got_types_used; -+}; -+ -+#define elf32_nios2_hash_entry(ent) \ -+ ((struct elf32_nios2_link_hash_entry *) (ent)) -+ -+/* Get the Nios II elf linker hash table from a link_info structure. */ -+#define elf32_nios2_hash_table(info) \ -+ ((struct elf32_nios2_link_hash_table *) ((info)->hash)) -+ -+/* Nios II ELF linker hash table. */ -+struct elf32_nios2_link_hash_table -+ { -+ /* The main hash table. */ -+ struct elf_link_hash_table root; -+ -+ /* Short-cuts to get to dynamic linker sections. */ -+ asection *sgot; -+ asection *sgotplt; -+ asection *srelgot; -+ asection *splt; -+ asection *srelplt; -+ asection *sdynbss; -+ asection *srelbss; -+ asection *sbss; -+ -+ union { -+ bfd_signed_vma refcount; -+ bfd_vma offset; -+ } tls_ldm_got; -+ -+ /* Small local sym to section mapping cache. */ -+ struct sym_cache sym_sec; -+ -+ bfd_vma res_n_size; -+ }; -+ -+struct nios2_elf32_obj_tdata -+{ -+ struct elf_obj_tdata root; -+ -+ /* tls_type for each local got entry. */ -+ char *local_got_tls_type; -+ -+ /* TRUE if TLS GD relocs have been seen for this object. */ -+ bfd_boolean has_tlsgd; -+}; -+ -+#define elf32_nios2_tdata(abfd) \ -+ ((struct nios2_elf32_obj_tdata *) (abfd)->tdata.any) -+ -+#define elf32_nios2_local_got_tls_type(abfd) \ -+ (elf32_nios2_tdata (abfd)->local_got_tls_type) -+ -+#define is_nios2_elf(bfd) \ -+ (bfd_get_flavour (bfd) == bfd_target_elf_flavour \ -+ && elf_object_id (bfd) == NIOS2_ELF_TDATA) -+/* The name of the dynamic interpreter. This is put in the .interp -+ section. */ -+ -+#define ELF_DYNAMIC_INTERPRETER "/lib/ld.so.1" -+ -+/* PLT implementation for position-dependent code. */ -+ -+static const bfd_vma nios2_plt_entry[] = { /* .PLTn: */ -+ 0x03c00034, /* movhi r15, %hiadj(plt_got_slot_address) */ -+ 0x7bc00017, /* ldw r15, %lo(plt_got_slot_address)(r15) */ -+ 0x7800683a /* jmp r15 */ -+}; -+ -+static const bfd_vma nios2_plt0_entry[] = { /* .PLTresolve */ -+ 0x03800034, /* movhi r14, %hiadj(res_0) */ -+ 0x73800004, /* addi r14, r14, %lo(res_0) */ -+ 0x7b9fc83a, /* sub r15, r15, r14 */ -+ 0x03400034, /* movhi r13, %hiadj(_GLOBAL_OFFSET_TABLE_) */ -+ 0x6b800017, /* ldw r14, %lo(_GLOBAL_OFFSET_TABLE_+4)(r13) */ -+ 0x6b400017, /* ldw r13, %lo(_GLOBAL_OFFSET_TABLE_+8)(r13) */ -+ 0x6800683a /* jmp r13 */ -+}; -+ -+/* PLT implementation for position-independent code. */ -+ -+static const bfd_vma nios2_so_plt_entry[] = { /* .PLTn */ -+ 0x03c00034, /* movhi r15, %hiadj(index * 4) */ -+ 0x7bc00004, /* addi r15, r15, %lo(index * 4) */ -+ 0x00000006 /* br .PLTresolve */ -+}; -+ -+static const bfd_vma nios2_so_plt0_entry[] = { /* .PLTresolve */ -+ 0x001ce03a, /* nextpc r14 */ -+ 0x03400034, /* movhi r13, %hiadj(_GLOBAL_OFFSET_TABLE_) */ -+ 0x6b9b883a, /* add r13, r13, r14 */ -+ 0x6b800017, /* ldw r14, %lo(_GLOBAL_OFFSET_TABLE_+4)(r13) */ -+ 0x6b400017, /* ldw r13, %lo(_GLOBAL_OFFSET_TABLE_+8)(r13) */ -+ 0x6800683a /* jmp r13 */ -+}; -+ -+/* Support for core dump NOTE sections */ -+static bfd_boolean -+nios2_grok_prstatus (bfd *abfd, Elf_Internal_Note *note) -+{ -+ int offset; -+ size_t size; -+ -+ switch (note->descsz) -+ { -+ default: -+ return FALSE; -+ -+ case 212: /* Linux/Nios II */ -+ /* pr_cursig */ -+ elf_tdata (abfd)->core_signal = bfd_get_16 (abfd, note->descdata + 12); -+ -+ /* pr_pid */ -+ elf_tdata (abfd)->core_pid = bfd_get_32 (abfd, note->descdata + 24); -+ -+ /* pr_reg */ -+ offset = 72; -+ size = 136; -+ -+ break; -+ } -+ -+ /* Make a ".reg/999" section. */ -+ return _bfd_elfcore_make_pseudosection (abfd, ".reg", -+ size, note->descpos + offset); -+} -+ -+static bfd_boolean -+nios2_grok_psinfo (bfd *abfd, Elf_Internal_Note *note) -+{ -+ switch (note->descsz) -+ { -+ default: -+ return FALSE; -+ -+ case 124: /* Linux/Nios II elf_prpsinfo */ -+ elf_tdata (abfd)->core_program -+ = _bfd_elfcore_strndup (abfd, note->descdata + 28, 16); -+ elf_tdata (abfd)->core_command -+ = _bfd_elfcore_strndup (abfd, note->descdata + 44, 80); -+ } -+ -+ /* Note that for some reason, a spurious space is tacked -+ onto the end of the args in some (at least one anyway) -+ implementations, so strip it off if it exists. */ -+ -+ { -+ char *command = elf_tdata (abfd)->core_command; -+ int n = strlen (command); -+ -+ if (0 < n && command[n - 1] == ' ') -+ command[n - 1] = '\0'; -+ } -+ -+ return TRUE; -+} -+ -+/* Create an entry in a Nios II ELF linker hash table. */ -+ -+static struct bfd_hash_entry * -+link_hash_newfunc (struct bfd_hash_entry *entry, -+ struct bfd_hash_table *table, const char *string) -+{ -+ /* Allocate the structure if it has not already been allocated by a -+ subclass. */ -+ if (entry == NULL) -+ { -+ entry = bfd_hash_allocate (table, -+ sizeof (struct elf32_nios2_link_hash_entry)); -+ if (entry == NULL) -+ return entry; -+ } -+ -+ /* Call the allocation method of the superclass. */ -+ entry = _bfd_elf_link_hash_newfunc (entry, table, string); -+ if (entry != NULL) -+ { -+ struct elf32_nios2_link_hash_entry *eh; -+ -+ eh = (struct elf32_nios2_link_hash_entry *) entry; -+ eh->dyn_relocs = NULL; -+ eh->tls_type = GOT_UNKNOWN; -+ eh->got_types_used = 0; -+ } -+ -+ return entry; -+} -+ -+/* Given a BFD reloc type, return a howto structure. */ -+ -+static reloc_howto_type * -+nios2_elf32_bfd_reloc_type_lookup (bfd * abfd ATTRIBUTE_UNUSED, -+ bfd_reloc_code_real_type code) -+{ -+ int i; -+ for (i = 0; -+ i < (int) (sizeof (nios2_reloc_map) / sizeof (struct elf_reloc_map)); -+ ++i) -+ { -+ if (nios2_reloc_map[i].bfd_val == code) -+ return &elf_nios2_howto_table_rel[(int) nios2_reloc_map[i].elf_val]; -+ } -+ -+ return NULL; -+} -+ -+/* Given a reloc name, return a howto structure. */ -+ -+static reloc_howto_type * -+nios2_elf32_bfd_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, -+ const char *r_name) -+{ -+ unsigned int i; -+ for (i = 0; -+ i < (sizeof (elf_nios2_howto_table_rel) -+ / sizeof (elf_nios2_howto_table_rel[0])); -+ i++) -+ if (elf_nios2_howto_table_rel[i].name != NULL -+ && strcasecmp (elf_nios2_howto_table_rel[i].name, r_name) == 0) -+ return &elf_nios2_howto_table_rel[i]; -+ -+ return NULL; -+} -+ -+/* Helper function for nios2_elf32_info_to_howto. */ -+ -+static reloc_howto_type * -+nios2_elf32_rtype_to_howto (unsigned int r_type, -+ bfd_boolean rela_p ATTRIBUTE_UNUSED) -+{ -+ BFD_ASSERT (r_type < R_NIOS2_ILLEGAL); -+ return &elf_nios2_howto_table_rel[r_type]; -+} -+ -+/* Given a ELF32 relocation, fill in a arelent structure. */ -+ -+static void -+nios2_elf32_info_to_howto (bfd * abfd ATTRIBUTE_UNUSED, arelent * cache_ptr, -+ Elf_Internal_Rela * dst) -+{ -+ unsigned int r_type; -+ -+ r_type = ELF32_R_TYPE (dst->r_info); -+ cache_ptr->howto = nios2_elf32_rtype_to_howto (r_type, FALSE); -+ -+ /* FIXME - do we need to do anything else here??? */ -+} -+ -+/* Return the base VMA address which should be subtracted from real addresses -+ when resolving @dtpoff relocation. -+ This is PT_TLS segment p_vaddr. */ -+ -+static bfd_vma -+dtpoff_base (struct bfd_link_info *info) -+{ -+ /* If tls_sec is NULL, we should have signalled an error already. */ -+ if (elf_hash_table (info)->tls_sec == NULL) -+ return 0; -+ return elf_hash_table (info)->tls_sec->vma; -+} -+ -+/* Return the relocation value for @tpoff relocation -+ if STT_TLS virtual address is ADDRESS. */ -+ -+static bfd_vma -+tpoff (struct bfd_link_info *info, bfd_vma address) -+{ -+ struct elf_link_hash_table *htab = elf_hash_table (info); -+ -+ /* If tls_sec is NULL, we should have signalled an error already. */ -+ if (htab->tls_sec == NULL) -+ return 0; -+ return address - htab->tls_sec->vma; -+} -+ -+/* The assembler has output long jmp/call sequences for all calls -+ and pc-relative branches that it cannot guarantee are within -+ range, so the linker must attempt to "relax" these sequences to -+ short branches and calls if it can. We avoid having to re-relax by -+ replacing redundant instructions with nops instead of deleting them. */ -+static bfd_boolean -+nios2_elf32_relax_section (bfd * abfd, -+ asection * sec, -+ struct bfd_link_info *link_info, bfd_boolean * again) -+{ -+ Elf_Internal_Shdr *symtab_hdr; -+ Elf_Internal_Rela *internal_relocs; -+ Elf_Internal_Rela *irel, *irelend; -+ bfd_byte *contents = NULL; -+ Elf_Internal_Sym *isymbuf = NULL; -+ -+#define OP_MATCH_NOP 0x0001883a -+ -+ /* Assume nothing changes. */ -+ *again = FALSE; -+ -+ /* We don't have to do anything for a relocatable link, if -+ this section does not have relocs, or if this is not a -+ code section. */ -+ if (link_info->relocatable -+ || (sec->flags & SEC_RELOC) == 0 -+ || sec->reloc_count == 0 || (sec->flags & SEC_CODE) == 0) -+ return TRUE; -+ -+ /* If this is the first time we have been called for this section, -+ initialize the cooked size. */ -+ if (sec->size == 0) -+ sec->size = sec->rawsize; -+ -+ symtab_hdr = &elf_tdata (abfd)->symtab_hdr; -+ -+ /* Get a copy of the native relocations. */ -+ internal_relocs = (_bfd_elf_link_read_relocs -+ (abfd, sec, (void *) NULL, (Elf_Internal_Rela *) NULL, -+ link_info->keep_memory)); -+ if (internal_relocs == NULL) -+ goto error_return; -+ -+ /* Walk through them looking for relaxing opportunities. */ -+ irelend = internal_relocs + sec->reloc_count; -+ for (irel = internal_relocs; irel < irelend; irel++) -+ { -+ bfd_vma symval; -+ -+ /* If this isn't something that can be relaxed, then ignore -+ this reloc. */ -+ if (ELF32_R_TYPE (irel->r_info) != (int) R_NIOS2_UJMP -+ && ELF32_R_TYPE (irel->r_info) != (int) R_NIOS2_CJMP -+ && ELF32_R_TYPE (irel->r_info) != (int) R_NIOS2_CALLR) -+ { -+ continue; -+ } -+ -+ /* Get the section contents if we haven't done so already. */ -+ if (contents == NULL) -+ { -+ /* Get cached copy if it exists. */ -+ if (elf_section_data (sec)->this_hdr.contents != NULL) -+ contents = elf_section_data (sec)->this_hdr.contents; -+ else -+ { -+ /* Go get them off disk. */ -+ contents = (bfd_byte *) bfd_malloc (sec->rawsize); -+ if (contents == NULL) -+ goto error_return; -+ -+ if (!bfd_get_section_contents (abfd, sec, contents, -+ (file_ptr) 0, sec->rawsize)) -+ goto error_return; -+ } -+ } -+ -+ /* Read this BFD's local symbols if we haven't done so already. */ -+ if (isymbuf == NULL && symtab_hdr->sh_info != 0) -+ { -+ isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents; -+ if (isymbuf == NULL) -+ isymbuf = bfd_elf_get_elf_syms (abfd, symtab_hdr, -+ symtab_hdr->sh_info, 0, -+ NULL, NULL, NULL); -+ if (isymbuf == NULL) -+ goto error_return; -+ } -+ -+ /* Get the value of the symbol referred to by the reloc. */ -+ if (ELF32_R_SYM (irel->r_info) < symtab_hdr->sh_info) -+ { -+ /* A local symbol. */ -+ Elf_Internal_Sym *isym; -+ asection *sym_sec; -+ -+ isym = isymbuf + ELF32_R_SYM (irel->r_info); -+ if (isym->st_shndx == SHN_UNDEF) -+ sym_sec = bfd_und_section_ptr; -+ else if (isym->st_shndx == SHN_ABS) -+ sym_sec = bfd_abs_section_ptr; -+ else if (isym->st_shndx == SHN_COMMON) -+ sym_sec = bfd_com_section_ptr; -+ else -+ sym_sec = bfd_section_from_elf_index (abfd, isym->st_shndx); -+ symval = (isym->st_value -+ + sym_sec->output_section->vma + sym_sec->output_offset); -+ } -+ else -+ { -+ unsigned long indx; -+ struct elf_link_hash_entry *h; -+ -+ /* An external symbol. */ -+ indx = ELF32_R_SYM (irel->r_info) - symtab_hdr->sh_info; -+ h = elf_sym_hashes (abfd)[indx]; -+ BFD_ASSERT (h != NULL); -+ if (h->root.type != bfd_link_hash_defined -+ && h->root.type != bfd_link_hash_defweak) -+ { -+ /* This appears to be a reference to an undefined -+ symbol. Just ignore it--it will be caught by the -+ regular reloc processing. */ -+ continue; -+ } -+ -+ symval = (h->root.u.def.value -+ + h->root.u.def.section->output_section->vma -+ + h->root.u.def.section->output_offset); -+ } -+ -+ /* For simplicity of coding, we are going to modify the section -+ contents, the section relocs, and the BFD symbol table. We -+ must tell the rest of the code not to free up this -+ information. It would be possible to instead create a table -+ of changes which have to be made, as is done in coff-mips.c; -+ that would be more work, but would require less memory when -+ the linker is run. */ -+ -+ /* try to turn : -+ * movhi at, %hi(symbol) -+ * movui at, %lo(symbol) -+ * callr at -+ * into: -+ * call symbol -+ */ -+ if (ELF32_R_TYPE (irel->r_info) == (int) R_NIOS2_CALLR) -+ { -+ bfd_vma targ_addr = symval + irel->r_addend; -+ bfd_vma curr_addr = (sec->output_section->vma + sec->output_offset); -+ bfd_vma targ_page, curr_page; -+ targ_page = targ_addr & 0xf0000000; -+ curr_page = curr_addr & 0xf0000000; -+ -+ if (targ_page == curr_page) -+ { -+ /* change the opcode to a call */ -+ bfd_put_32 (abfd, OP_MATCH_CALL, contents + irel->r_offset); -+ /* Note that we've changed the relocs, section contents, etc. */ -+ elf_section_data (sec)->relocs = internal_relocs; -+ elf_section_data (sec)->this_hdr.contents = contents; -+ symtab_hdr->contents = (unsigned char *) isymbuf; -+ -+ /* Fix the relocation's type. */ -+ irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info), -+ R_NIOS2_CALL26); -+ -+ /* replace next two instructions with nops */ -+ bfd_put_32 (abfd, OP_MATCH_NOP, contents + irel->r_offset + 4); -+ bfd_put_32 (abfd, OP_MATCH_NOP, contents + irel->r_offset + 8); -+ } -+ } -+ -+ /* try to turn : -+ * movhi at, %hi(symbol) -+ * movui at, %lo(symbol) -+ * jmp at -+ * into: -+ * br symbol -+ */ -+ if (ELF32_R_TYPE (irel->r_info) == (int) R_NIOS2_UJMP) -+ { -+ bfd_vma pcrel_offset; -+ Elf_Internal_Rela *irelalign = NULL; -+ Elf_Internal_Rela *irela = elf_section_data (sec)->relocs; -+ Elf_Internal_Rela *irelend = irel + sec->reloc_count; -+ -+ for (; irela < irelend; irela++) -+ { -+ if (ELF32_R_TYPE (irela->r_info) == (int) R_NIOS2_ALIGN -+ && irela->r_offset > irel->r_offset + 4 -+ && 8 < (1 << irela->r_addend)) -+ { -+ irelalign = irela; -+ break; -+ } -+ } -+ -+ /* calculate the pcrelative offset from current location */ -+ pcrel_offset = symval; -+ pcrel_offset -= (sec->output_section->vma + sec->output_offset); -+ pcrel_offset += irel->r_addend; -+ -+ /* we need to compute the pcrel_offset from the next instruction */ -+ pcrel_offset -= (irel->r_offset + 4); -+ -+ /* does this value fit in 16 bits */ -+ if ((irelalign == NULL && (long) pcrel_offset <= 0x8004 -+ && (long) pcrel_offset >= -0x8000) || (irelalign != NULL -+ && (long) pcrel_offset -+ <= 0x7ffc -+ && (long) pcrel_offset -+ >= -0x8000)) -+ { -+ /* change the opcode to an unconditional branch */ -+ bfd_put_32 (abfd, OP_MATCH_BR, contents + irel->r_offset); -+ /* Note that we've changed the relocs, section contents, etc. */ -+ elf_section_data (sec)->relocs = internal_relocs; -+ elf_section_data (sec)->this_hdr.contents = contents; -+ symtab_hdr->contents = (unsigned char *) isymbuf; -+ -+ /* Fix the relocation's type. */ -+ irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info), -+ R_NIOS2_PCREL16); -+ -+ /* replace next two instructions with nops */ -+ bfd_put_32 (abfd, OP_MATCH_NOP, contents + irel->r_offset + 4); -+ bfd_put_32 (abfd, OP_MATCH_NOP, contents + irel->r_offset + 8); -+ } -+ } -+ -+ /* try to turn : -+ * b{cond} a, b skip -+ * movhi at, %hi(symbol) -+ * movui at, %lo(symbol) -+ * jmp at -+ * skip: -+ * ... -+ * into: -+ * br{opp_cond} a, b, symbol -+ */ -+ if (ELF32_R_TYPE (irel->r_info) == (int) R_NIOS2_CJMP) -+ { -+ bfd_vma pcrel_offset; -+ Elf_Internal_Rela *irelalign = NULL; -+ Elf_Internal_Rela *irela = elf_section_data (sec)->relocs; -+ Elf_Internal_Rela *irelend = irel + sec->reloc_count; -+ -+ for (; irela < irelend; irela++) -+ { -+ if (ELF32_R_TYPE (irela->r_info) == (int) R_NIOS2_ALIGN -+ && irela->r_offset > irel->r_offset + 4 -+ && 8 < (1 << irela->r_addend)) -+ { -+ irelalign = irela; -+ break; -+ } -+ } -+ -+ /* calculate the pcrelative offset from current location */ -+ pcrel_offset = symval; -+ pcrel_offset -= (sec->output_section->vma + sec->output_offset); -+ pcrel_offset += irel->r_addend; -+ -+ /* we need to compute the pcrel_offset from this instruction -+ * ie the movhi */ -+ pcrel_offset -= (irel->r_offset); -+ -+ /* does this value fit in 16 bits */ -+ if ((irelalign == NULL && (long) pcrel_offset <= 0x8008 -+ && (long) pcrel_offset >= -0x8000) || (irelalign != NULL -+ && (long) pcrel_offset -+ <= 0x7ffc -+ && (long) pcrel_offset -+ >= -0x8000)) -+ { -+ unsigned long opcode, op_a, op_b; -+ /* get the conditional branch opcode */ -+ opcode = bfd_get_32 (abfd, contents + irel->r_offset - 4); -+ /* reverse the condition */ -+ switch (opcode & OP_MASK_OP) -+ { -+ case OP_MATCH_BEQ: -+ opcode = (opcode & ~OP_MASK_OP) | OP_MATCH_BNE; -+ break; -+ case OP_MATCH_BNE: -+ opcode = (opcode & ~OP_MASK_OP) | OP_MATCH_BEQ; -+ break; -+ case OP_MATCH_BGE: -+ case OP_MATCH_BGEU: -+ case OP_MATCH_BLT: -+ case OP_MATCH_BLTU: -+ /* swap the operands */ -+ op_a = (opcode & OP_MASK_RRT) << 5; -+ op_b = (opcode & OP_MASK_RRS) >> 5; -+ opcode = -+ (opcode & ~(OP_MASK_RRS | OP_MASK_RRT)) | op_a | op_b; -+ break; -+ default: -+ fprintf (stderr, -+ "relaxation error - expecting conditional branch, " -+ "aborting\n"); -+ abort (); -+ break; -+ } -+ -+ /* We must set the branch target to zero so that the skip over -+ the jmp doesn't get added to the jmp. */ -+ opcode = opcode & (~OP_MASK_IMM16); -+ -+ /* Change the opcode to the reversed conditional branch. */ -+ bfd_put_32 (abfd, opcode, contents + irel->r_offset - 4); -+ /* Note that we've changed the relocs, section contents, etc. */ -+ elf_section_data (sec)->relocs = internal_relocs; -+ elf_section_data (sec)->this_hdr.contents = contents; -+ symtab_hdr->contents = (unsigned char *) isymbuf; -+ -+ /* Fix the relocation's type. */ -+ irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info), -+ R_NIOS2_PCREL16); -+ -+ /* This relocation's offset has also been reduced by 4 bytes. */ -+ irel->r_offset -= 4; -+ -+ /* Replace next two instructions with nops. */ -+ bfd_put_32 (abfd, OP_MATCH_NOP, contents + irel->r_offset + 4); -+ bfd_put_32 (abfd, OP_MATCH_NOP, contents + irel->r_offset + 8); -+ bfd_put_32 (abfd, OP_MATCH_NOP, contents + irel->r_offset + 12); -+ } -+ } -+ -+ /* Otherwise, leave alone. */ -+ } -+ -+ if (isymbuf != NULL && symtab_hdr->contents != (unsigned char *) isymbuf) -+ { -+ if (!link_info->keep_memory) -+ free (isymbuf); -+ else -+ { -+ /* Cache the symbols for elf_link_input_bfd. */ -+ symtab_hdr->contents = (unsigned char *) isymbuf; -+ } -+ } -+ -+ if (contents != NULL -+ && elf_section_data (sec)->this_hdr.contents != contents) -+ { -+ if (!link_info->keep_memory) -+ free (contents); -+ else -+ { -+ /* Cache the section contents for elf_link_input_bfd. */ -+ elf_section_data (sec)->this_hdr.contents = contents; -+ } -+ } -+ -+ if (internal_relocs != NULL -+ && elf_section_data (sec)->relocs != internal_relocs) -+ free (internal_relocs); -+ -+ -+ return TRUE; -+ -+error_return: -+ if (isymbuf != NULL && symtab_hdr->contents != (unsigned char *) isymbuf) -+ free (isymbuf); -+ if (contents != NULL -+ && elf_section_data (sec)->this_hdr.contents != contents) -+ free (contents); -+ if (internal_relocs != NULL -+ && elf_section_data (sec)->relocs != internal_relocs) -+ free (internal_relocs); -+ -+ return FALSE; -+} -+#if 0 -+/* Delete some bytes from a section while relaxing. -+ * Copied from mn10200 port */ -+ -+static bfd_boolean -+nios2_elf32_relax_delete_bytes (bfd * abfd, -+ asection * sec, bfd_vma addr, int count) -+{ -+ Elf_Internal_Shdr *symtab_hdr; -+ unsigned int sec_shndx; -+ bfd_byte *contents; -+ Elf_Internal_Rela *irel, *irelend; -+ Elf_Internal_Rela *irelalign; -+ bfd_vma toaddr; -+ Elf_Internal_Sym *isym; -+ Elf_Internal_Sym *isymend; -+ struct elf_link_hash_entry **sym_hashes; -+ struct elf_link_hash_entry **end_hashes; -+ unsigned int symcount; -+ asection *asec; -+ -+ sec_shndx = _bfd_elf_section_from_bfd_section (abfd, sec); -+ -+ contents = elf_section_data (sec)->this_hdr.contents; -+ -+ /* The deletion must stop at the next ALIGN reloc for an aligment -+ power larger than the number of bytes we are deleting. */ -+ -+ irelalign = NULL; -+ /* +1 because we need to readjust symbols at end of section */ -+ toaddr = sec->size + 1; -+ -+ irel = elf_section_data (sec)->relocs; -+ irelend = irel + sec->reloc_count; -+ -+ for (; irel < irelend; irel++) -+ { -+ if (ELF32_R_TYPE (irel->r_info) == (int) R_NIOS2_ALIGN -+ && irel->r_offset > addr && count < (1 << irel->r_addend)) -+ { -+ irelalign = irel; -+ /* +1 because we need to readjust symbols at end of section */ -+ toaddr = irel->r_offset + 1; -+ break; -+ } -+ } -+ -+ -+ /* Actually delete the bytes. */ -+ memmove (contents + addr, contents + addr + count, -+ (size_t) ((toaddr - 1) - addr - count)); -+ -+ if (irelalign == NULL) -+ sec->size -= count; -+ else -+ { -+ int i; -+ -+#define NOP_OPCODE (0x0001883a) -+ -+ BFD_ASSERT ((count & 3) == 0); -+ for (i = 0; i < count; i += 4) -+ bfd_put_32 (abfd, (bfd_vma) NOP_OPCODE, -+ contents + (toaddr - 1) - count + i); -+ } -+ -+ /* get the symbol table */ -+ symtab_hdr = &elf_tdata (abfd)->symtab_hdr; -+ isym = (Elf_Internal_Sym *) symtab_hdr->contents; -+ -+ /* Adjust all the reloc offsets in this section. */ -+ for (irel = elf_section_data (sec)->relocs; irel < irelend; irel++) -+ { -+ /* Get the new reloc address. */ -+ if ((irel->r_offset > addr && irel->r_offset < toaddr)) -+ irel->r_offset -= count; -+ } -+ -+ /* Adjust relocations against targets in this section whose positions -+ * have moved as a result of the relaxation */ -+ -+ for (asec = abfd->sections; asec; asec = asec->next) -+ { -+ irelend = elf_section_data (asec)->relocs + asec->reloc_count; -+ for (irel = elf_section_data (asec)->relocs; irel < irelend; irel++) -+ { -+ Elf_Internal_Sym *sym; -+ /* if the symbol which this reloc is against doesn't change -+ * we need to change the reloc addend */ -+ -+ sym = isym + ELF32_R_SYM (irel->r_info); -+ if (sym->st_shndx == sec_shndx -+ && !(sym->st_value > addr && sym->st_value < toaddr) -+ && sym->st_value + irel->r_addend > addr -+ && sym->st_value + irel->r_addend < toaddr) -+ { -+ irel->r_addend -= count; -+ } -+ -+ } -+ } -+ -+ /* Adjust the local symbols defined in this section. */ -+ for (isymend = isym + symtab_hdr->sh_info; isym < isymend; isym++) -+ { -+ if (isym->st_shndx == sec_shndx -+ && isym->st_value > addr && isym->st_value < toaddr) -+ isym->st_value -= count; -+ -+ -+ } -+ -+ /* Now adjust the global symbols defined in this section. */ -+ symcount = (symtab_hdr->sh_size / sizeof (Elf32_External_Sym) -+ - symtab_hdr->sh_info); -+ sym_hashes = elf_sym_hashes (abfd); -+ end_hashes = sym_hashes + symcount; -+ for (; sym_hashes < end_hashes; sym_hashes++) -+ { -+ struct elf_link_hash_entry *sym_hash = *sym_hashes; -+ if ((sym_hash->root.type == bfd_link_hash_defined -+ || sym_hash->root.type == bfd_link_hash_defweak) -+ && sym_hash->root.u.def.section == sec -+ && sym_hash->root.u.def.value > addr -+ && sym_hash->root.u.def.value < toaddr) -+ { -+ sym_hash->root.u.def.value -= count; -+ } -+ } -+ -+ return TRUE; -+} -+#endif -+struct bfd_link_info *nios2_link_info = NULL; -+ -+void -+_bfd_set_link_info (struct bfd_link_info *info) -+{ -+ nios2_link_info = info; -+} -+ -+bfd_boolean linker_force_make_executable = FALSE; -+ -+void -+_bfd_set_force_make_executable (bfd_boolean force) -+{ -+ linker_force_make_executable = force; -+} -+ -+/* Set the GP value for OUTPUT_BFD. Returns FALSE if this is a -+ dangerous relocation. */ -+ -+static bfd_boolean -+nios2_elf_assign_gp (bfd *output_bfd, bfd_vma *pgp, struct bfd_link_info *info) -+{ -+ -+ bfd_boolean gp_found; -+ struct bfd_hash_entry *h; -+ struct bfd_link_hash_entry *lh; -+ -+ /* If we've already figured out what GP will be, just return it. */ -+ *pgp = _bfd_get_gp_value (output_bfd); -+ if (*pgp) -+ return TRUE; -+ -+ h = bfd_hash_lookup (&info->hash->table, "_gp", FALSE, FALSE); -+ lh = (struct bfd_link_hash_entry *) h; -+lookup: -+ if (lh) -+ { -+ switch (lh->type) -+ { -+ case bfd_link_hash_undefined: -+ case bfd_link_hash_undefweak: -+ case bfd_link_hash_common: -+ gp_found = FALSE; -+ break; -+ case bfd_link_hash_defined: -+ case bfd_link_hash_defweak: -+ gp_found = TRUE; -+ *pgp = lh->u.def.value; -+ break; -+ case bfd_link_hash_indirect: -+ case bfd_link_hash_warning: -+ lh = lh->u.i.link; -+ /* @@FIXME ignoring warning for now */ -+ goto lookup; -+ case bfd_link_hash_new: -+ default: -+ abort (); -+ } -+ } -+ else -+ gp_found = FALSE; -+ -+ if (!gp_found) -+ { -+ /* Only get the error once. */ -+ *pgp = 4; -+ _bfd_set_gp_value (output_bfd, *pgp); -+ return FALSE; -+ } -+ -+ _bfd_set_gp_value (output_bfd, *pgp); -+ -+ return TRUE; -+} -+ -+/* We have to figure out the gp value, so that we can adjust the -+ symbol value correctly. We look up the symbol _gp in the output -+ BFD. If we can't find it, we're stuck. We cache it in the ELF -+ target data. We don't need to adjust the symbol value for an -+ external symbol if we are producing relocatable output. */ -+ -+static bfd_reloc_status_type -+nios2_elf_final_gp (bfd *output_bfd, asymbol *symbol, bfd_boolean relocatable, -+ char **error_message, bfd_vma *pgp, -+ struct bfd_link_info *info) -+{ -+ if (bfd_is_und_section (symbol->section) && !relocatable) -+ { -+ *pgp = 0; -+ return bfd_reloc_undefined; -+ } -+ -+ *pgp = _bfd_get_gp_value (output_bfd); -+ if (*pgp == 0 && (!relocatable || (symbol->flags & BSF_SECTION_SYM) != 0)) -+ { -+ /* if this is called without link_info, then -+ we cannot be doing a final link */ -+ if (info == NULL) -+ relocatable = TRUE; -+ -+ if (relocatable) -+ { -+ /* Make up a value. */ -+ *pgp = symbol->section->output_section->vma + 0x4000; -+ _bfd_set_gp_value (output_bfd, *pgp); -+ } -+ else if (!nios2_elf_assign_gp (output_bfd, pgp, info)) -+ { -+ *error_message = -+ (char *) -+ _("global pointer relative relocation when _gp not defined"); -+ return bfd_reloc_dangerous; -+ } -+ } -+ -+ return bfd_reloc_ok; -+} -+ -+ -+/* Relocations that require special handling */ -+ -+/* This is for relocations used only when relaxing to ensure -+ changes in size of section don't screw up .align. */ -+static bfd_reloc_status_type -+nios2_elf32_ignore_reloc (bfd *abfd ATTRIBUTE_UNUSED, arelent *reloc_entry, -+ asymbol *symbol ATTRIBUTE_UNUSED, -+ void *data ATTRIBUTE_UNUSED, asection *input_section, -+ bfd *output_bfd, -+ char **error_message ATTRIBUTE_UNUSED) -+{ -+ if (output_bfd != NULL) -+ reloc_entry->address += input_section->output_offset; -+ return bfd_reloc_ok; -+} -+ -+static bfd_reloc_status_type -+nios2_elf32_hi16_relocate (bfd *abfd, arelent *reloc_entry, asymbol *symbol, -+ void *data, asection *input_section, -+ bfd *output_bfd, -+ char **error_message ATTRIBUTE_UNUSED) -+{ -+ /* This part is from bfd_elf_generic_reloc. */ -+ if (output_bfd != (bfd *) NULL -+ && (symbol->flags & BSF_SECTION_SYM) == 0 -+ && (!reloc_entry->howto->partial_inplace || reloc_entry->addend == 0)) -+ { -+ reloc_entry->address += input_section->output_offset; -+ return bfd_reloc_ok; -+ } -+ -+ if (output_bfd != NULL) -+ /* FIXME: See bfd_perform_relocation. Is this right? */ -+ return bfd_reloc_ok; -+ -+ return nios2_elf32_do_hi16_relocate (abfd, reloc_entry->howto, -+ input_section, -+ data, reloc_entry->address, -+ (symbol->value -+ + symbol->section->output_section->vma -+ + symbol->section->output_offset), -+ reloc_entry->addend); -+} -+ -+static bfd_reloc_status_type -+nios2_elf32_lo16_relocate (bfd *abfd, arelent *reloc_entry, asymbol *symbol, -+ void *data, asection *input_section, -+ bfd *output_bfd, -+ char **error_message ATTRIBUTE_UNUSED) -+{ -+/* This part is from bfd_elf_generic_reloc. */ -+ if (output_bfd != (bfd *) NULL -+ && (symbol->flags & BSF_SECTION_SYM) == 0 -+ && (!reloc_entry->howto->partial_inplace || reloc_entry->addend == 0)) -+ { -+ reloc_entry->address += input_section->output_offset; -+ return bfd_reloc_ok; -+ } -+ -+ if (output_bfd != NULL) -+ /* FIXME: See bfd_perform_relocation. Is this right? */ -+ return bfd_reloc_ok; -+ -+ return nios2_elf32_do_lo16_relocate (abfd, reloc_entry->howto, -+ input_section, -+ data, reloc_entry->address, -+ (symbol->value -+ + symbol->section->output_section->vma -+ + symbol->section->output_offset), -+ reloc_entry->addend); -+} -+ -+static bfd_reloc_status_type -+nios2_elf32_hiadj16_relocate (bfd *abfd, arelent *reloc_entry, asymbol *symbol, -+ void *data, asection *input_section, -+ bfd *output_bfd, -+ char **error_message ATTRIBUTE_UNUSED) -+{ -+ /* This part is from bfd_elf_generic_reloc. */ -+ if (output_bfd != (bfd *) NULL -+ && (symbol->flags & BSF_SECTION_SYM) == 0 -+ && (!reloc_entry->howto->partial_inplace || reloc_entry->addend == 0)) -+ { -+ reloc_entry->address += input_section->output_offset; -+ return bfd_reloc_ok; -+ } -+ -+ if (output_bfd != NULL) -+ /* FIXME: See bfd_perform_relocation. Is this right? */ -+ return bfd_reloc_ok; -+ -+ return nios2_elf32_do_hiadj16_relocate (abfd, reloc_entry->howto, -+ input_section, -+ data, reloc_entry->address, -+ (symbol->value -+ + -+ symbol->section->output_section-> -+ vma + -+ symbol->section->output_offset), -+ reloc_entry->addend); -+} -+ -+static bfd_reloc_status_type -+nios2_elf32_pcrel_lo16_relocate (bfd *abfd, arelent *reloc_entry, -+ asymbol *symbol, void *data, -+ asection *input_section, bfd *output_bfd, -+ char **error_message ATTRIBUTE_UNUSED) -+{ -+ /* This part is from bfd_elf_generic_reloc. */ -+ if (output_bfd != (bfd *) NULL -+ && (symbol->flags & BSF_SECTION_SYM) == 0 -+ && (!reloc_entry->howto->partial_inplace || reloc_entry->addend == 0)) -+ { -+ reloc_entry->address += input_section->output_offset; -+ return bfd_reloc_ok; -+ } -+ -+ if (output_bfd != NULL) -+ /* FIXME: See bfd_perform_relocation. Is this right? */ -+ return bfd_reloc_ok; -+ -+ return nios2_elf32_do_pcrel_lo16_relocate ( -+ abfd, reloc_entry->howto, input_section, data, reloc_entry->address, -+ (symbol->value + symbol->section->output_section->vma + -+ symbol->section->output_offset), -+ reloc_entry->addend); -+} -+ -+static bfd_reloc_status_type -+nios2_elf32_pcrel_hiadj16_relocate (bfd *abfd, arelent *reloc_entry, -+ asymbol *symbol, void *data, -+ asection *input_section, bfd *output_bfd, -+ char **error_message ATTRIBUTE_UNUSED) -+{ -+ /* This part is from bfd_elf_generic_reloc. */ -+ if (output_bfd != (bfd *) NULL -+ && (symbol->flags & BSF_SECTION_SYM) == 0 -+ && (!reloc_entry->howto->partial_inplace || reloc_entry->addend == 0)) -+ { -+ reloc_entry->address += input_section->output_offset; -+ return bfd_reloc_ok; -+ } -+ -+ if (output_bfd != NULL) -+ /* FIXME: See bfd_perform_relocation. Is this right? */ -+ return bfd_reloc_ok; -+ -+ return nios2_elf32_do_pcrel_hiadj16_relocate ( -+ abfd, reloc_entry->howto, input_section, data, reloc_entry->address, -+ (symbol->value + symbol->section->output_section->vma + -+ symbol->section->output_offset), -+ reloc_entry->addend); -+} -+ -+static bfd_reloc_status_type -+nios2_elf32_pcrel16_relocate (bfd *abfd, arelent *reloc_entry, asymbol *symbol, -+ void *data, asection *input_section, -+ bfd *output_bfd, -+ char **error_message ATTRIBUTE_UNUSED) -+{ -+ /* This part is from bfd_elf_generic_reloc. */ -+ if (output_bfd != (bfd *) NULL -+ && (symbol->flags & BSF_SECTION_SYM) == 0 -+ && (!reloc_entry->howto->partial_inplace || reloc_entry->addend == 0)) -+ { -+ reloc_entry->address += input_section->output_offset; -+ return bfd_reloc_ok; -+ } -+ -+ if (output_bfd != NULL) -+ /* FIXME: See bfd_perform_relocation. Is this right? */ -+ return bfd_reloc_ok; -+ -+ return nios2_elf32_do_pcrel16_relocate (abfd, reloc_entry->howto, -+ input_section, -+ data, reloc_entry->address, -+ (symbol->value -+ + -+ symbol->section->output_section-> -+ vma + -+ symbol->section->output_offset), -+ reloc_entry->addend); -+} -+ -+static bfd_reloc_status_type -+nios2_elf32_call26_relocate (bfd *abfd, arelent *reloc_entry, asymbol *symbol, -+ void *data, asection *input_section, -+ bfd *output_bfd, -+ char **error_message ATTRIBUTE_UNUSED) -+{ -+ /* This part is from bfd_elf_generic_reloc. */ -+ if (output_bfd != (bfd *) NULL -+ && (symbol->flags & BSF_SECTION_SYM) == 0 -+ && (!reloc_entry->howto->partial_inplace || reloc_entry->addend == 0)) -+ { -+ reloc_entry->address += input_section->output_offset; -+ return bfd_reloc_ok; -+ } -+ -+ if (output_bfd != NULL) -+ /* FIXME: See bfd_perform_relocation. Is this right? */ -+ return bfd_reloc_ok; -+ -+ return nios2_elf32_do_call26_relocate (abfd, reloc_entry->howto, -+ input_section, -+ data, reloc_entry->address, -+ (symbol->value -+ + -+ symbol->section->output_section-> -+ vma + -+ symbol->section->output_offset), -+ reloc_entry->addend); -+} -+ -+static bfd_reloc_status_type -+nios2_elf32_gprel_relocate (bfd *abfd, arelent *reloc_entry, asymbol *symbol, -+ void *data, asection *input_section, -+ bfd *output_bfd, char **msg) -+{ -+ bfd_vma relocation; -+ bfd_vma gp; -+ bfd_reloc_status_type r; -+ -+ -+ /* This part is from bfd_elf_generic_reloc. */ -+ if (output_bfd != (bfd *) NULL -+ && (symbol->flags & BSF_SECTION_SYM) == 0 -+ && (!reloc_entry->howto->partial_inplace || reloc_entry->addend == 0)) -+ { -+ reloc_entry->address += input_section->output_offset; -+ return bfd_reloc_ok; -+ } -+ -+ if (output_bfd != NULL) -+ /* FIXME: See bfd_perform_relocation. Is this right? */ -+ return bfd_reloc_ok; -+ -+ relocation = symbol->value -+ + symbol->section->output_section->vma + symbol->section->output_offset; -+ -+ if ((r = -+ nios2_elf_final_gp (abfd, symbol, FALSE, msg, &gp, -+ nios2_link_info)) == bfd_reloc_ok) -+ { -+ relocation = relocation + reloc_entry->addend - gp; -+ reloc_entry->addend = 0; -+ if ((signed) relocation < -32768 || (signed) relocation > 32767) -+ { -+ *msg = _("global pointer relative address out of range"); -+ r = bfd_reloc_outofrange; -+ } -+ else -+ { -+ r = nios2_elf32_do_gprel_relocate (abfd, reloc_entry->howto, -+ input_section, -+ data, reloc_entry->address, -+ relocation, reloc_entry->addend); -+ } -+ } -+ -+ return r; -+} -+ -+static bfd_reloc_status_type -+nios2_elf32_ujmp_relocate (bfd *abfd, arelent *reloc_entry, asymbol *symbol, -+ void *data, asection *input_section, -+ bfd *output_bfd, char **msg ATTRIBUTE_UNUSED) -+{ -+ /* This part is from bfd_elf_generic_reloc. */ -+ if (output_bfd != (bfd *) NULL -+ && (symbol->flags & BSF_SECTION_SYM) == 0 -+ && (!reloc_entry->howto->partial_inplace || reloc_entry->addend == 0)) -+ { -+ reloc_entry->address += input_section->output_offset; -+ return bfd_reloc_ok; -+ } -+ -+ if (output_bfd != NULL) -+ /* FIXME: See bfd_perform_relocation. Is this right? */ -+ return bfd_reloc_ok; -+ -+ return nios2_elf32_do_ujmp_relocate (abfd, reloc_entry->howto, -+ input_section, -+ data, reloc_entry->address, -+ (symbol->value -+ + symbol->section->output_section->vma -+ + symbol->section->output_offset), -+ reloc_entry->addend); -+} -+ -+static bfd_reloc_status_type -+nios2_elf32_cjmp_relocate (bfd *abfd, arelent *reloc_entry, asymbol *symbol, -+ void *data, asection *input_section, -+ bfd *output_bfd, char **msg ATTRIBUTE_UNUSED) -+{ -+ /* This part is from bfd_elf_generic_reloc. */ -+ if (output_bfd != (bfd *) NULL -+ && (symbol->flags & BSF_SECTION_SYM) == 0 -+ && (!reloc_entry->howto->partial_inplace || reloc_entry->addend == 0)) -+ { -+ reloc_entry->address += input_section->output_offset; -+ return bfd_reloc_ok; -+ } -+ -+ if (output_bfd != NULL) -+ /* FIXME: See bfd_perform_relocation. Is this right? */ -+ return bfd_reloc_ok; -+ -+ return nios2_elf32_do_cjmp_relocate (abfd, reloc_entry->howto, -+ input_section, -+ data, reloc_entry->address, -+ (symbol->value -+ + symbol->section->output_section->vma -+ + symbol->section->output_offset), -+ reloc_entry->addend); -+} -+ -+static bfd_reloc_status_type -+nios2_elf32_callr_relocate (bfd *abfd, arelent *reloc_entry, asymbol *symbol, -+ void *data, asection *input_section, -+ bfd *output_bfd, char **msg ATTRIBUTE_UNUSED) -+{ -+ /* This part is from bfd_elf_generic_reloc. */ -+ if (output_bfd != (bfd *) NULL -+ && (symbol->flags & BSF_SECTION_SYM) == 0 -+ && (!reloc_entry->howto->partial_inplace || reloc_entry->addend == 0)) -+ { -+ reloc_entry->address += input_section->output_offset; -+ return bfd_reloc_ok; -+ } -+ -+ if (output_bfd != NULL) -+ /* FIXME: See bfd_perform_relocation. Is this right? */ -+ return bfd_reloc_ok; -+ -+ -+ return nios2_elf32_do_callr_relocate (abfd, reloc_entry->howto, -+ input_section, -+ data, reloc_entry->address, -+ (symbol->value -+ + -+ symbol->section->output_section-> -+ vma + -+ symbol->section->output_offset), -+ reloc_entry->addend); -+} -+ -+/* Do the relocations which require special handling. */ -+ -+static bfd_reloc_status_type -+nios2_elf32_do_hi16_relocate (bfd *abfd, reloc_howto_type *howto, -+ asection *input_section ATTRIBUTE_UNUSED, -+ bfd_byte *data, bfd_vma offset, -+ bfd_vma symbol_value, bfd_vma addend) -+{ -+ symbol_value = symbol_value + addend; -+ addend = 0; -+ symbol_value = (symbol_value >> 16) & 0xffff; -+ return _bfd_final_link_relocate (howto, abfd, input_section, -+ data, offset, symbol_value, addend); -+} -+ -+ -+static bfd_reloc_status_type -+nios2_elf32_do_lo16_relocate (bfd *abfd, reloc_howto_type *howto, -+ asection *input_section ATTRIBUTE_UNUSED, -+ bfd_byte *data, bfd_vma offset, -+ bfd_vma symbol_value, bfd_vma addend) -+{ -+ symbol_value = symbol_value + addend; -+ addend = 0; -+ symbol_value = symbol_value & 0xffff; -+ return _bfd_final_link_relocate (howto, abfd, input_section, -+ data, offset, symbol_value, addend); -+} -+ -+/* The usual way of loading a 32-bit constant into a Nios II register is to -+ load the high 16 bits in one instruction and then add the low 16 bits with -+ a signed add. This means that the high halfword needs to be adjusted to -+ compensate for the sign bit of the low halfword. This function returns the -+ adjusted high halfword for a given 32-bit constant. */ -+ -+static bfd_vma hiadj(bfd_vma symbol_value) -+{ -+ return -+ (((symbol_value >> 16) & 0xffff) + ((symbol_value >> 15) & 0x01)) & 0xffff; -+} -+ -+static bfd_reloc_status_type -+nios2_elf32_do_hiadj16_relocate (bfd *abfd, reloc_howto_type *howto, -+ asection *input_section ATTRIBUTE_UNUSED, -+ bfd_byte *data, bfd_vma offset, -+ bfd_vma symbol_value, bfd_vma addend) -+{ -+ symbol_value = symbol_value + addend; -+ addend = 0; -+ symbol_value = hiadj(symbol_value); -+ return _bfd_final_link_relocate (howto, abfd, input_section, data, offset, -+ symbol_value, addend); -+} -+ -+static bfd_reloc_status_type -+nios2_elf32_do_pcrel_lo16_relocate (bfd *abfd, reloc_howto_type *howto, -+ asection *input_section ATTRIBUTE_UNUSED, -+ bfd_byte *data, bfd_vma offset, -+ bfd_vma symbol_value, bfd_vma addend) -+{ -+ symbol_value = symbol_value + addend; -+ addend = 0; -+ symbol_value = symbol_value & 0xffff; -+ return _bfd_final_link_relocate (howto, abfd, input_section, -+ data, offset, symbol_value, addend); -+} -+ -+static bfd_reloc_status_type -+nios2_elf32_do_pcrel_hiadj16_relocate (bfd *abfd, reloc_howto_type *howto, -+ asection *input_section -+ ATTRIBUTE_UNUSED, -+ bfd_byte *data, bfd_vma offset, -+ bfd_vma symbol_value, bfd_vma addend) -+{ -+ symbol_value = symbol_value + addend; -+ symbol_value -= (input_section->output_section->vma + -+ input_section->output_offset); -+ symbol_value -= offset; -+ addend = 0; -+ symbol_value = hiadj(symbol_value); -+ return _bfd_final_link_relocate (howto, abfd, input_section, data, offset, -+ symbol_value, addend); -+} -+ -+static bfd_reloc_status_type -+nios2_elf32_do_pcrel16_relocate (bfd *abfd, reloc_howto_type *howto, -+ asection *input_section ATTRIBUTE_UNUSED, -+ bfd_byte *data, bfd_vma offset, -+ bfd_vma symbol_value, bfd_vma addend) -+{ -+ /* NIOS2 pc relative relocations are relative to the next 32-bit instruction -+ so we need to subtract 4 before doing a final_link_relocate. */ -+ symbol_value = symbol_value + addend - 4; -+ addend = 0; -+ return _bfd_final_link_relocate (howto, abfd, input_section, -+ data, offset, symbol_value, addend); -+} -+ -+static bfd_reloc_status_type -+nios2_elf32_do_call26_relocate (bfd *abfd, reloc_howto_type *howto, -+ asection *input_section ATTRIBUTE_UNUSED, -+ bfd_byte *data, bfd_vma offset, -+ bfd_vma symbol_value, bfd_vma addend) -+{ -+ /* Check that the relocation is in the same page as the current address. */ -+ if (((symbol_value + addend) & 0xf0000000) -+ != ((input_section->output_section->vma + offset) & 0xf0000000)) -+ return bfd_reloc_overflow; -+ -+ return _bfd_final_link_relocate (howto, abfd, input_section, -+ data, offset, symbol_value, addend); -+} -+ -+ -+static bfd_reloc_status_type -+nios2_elf32_do_gprel_relocate (bfd *abfd, reloc_howto_type *howto, -+ asection *input_section ATTRIBUTE_UNUSED, -+ bfd_byte *data, bfd_vma offset, -+ bfd_vma symbol_value, bfd_vma addend) -+{ -+ /* Because we need the output_bfd, the special handling is done -+ in nios2_elf32_relocate_section or in nios2_elf32_gprel_relocate. */ -+ return _bfd_final_link_relocate (howto, abfd, input_section, -+ data, offset, symbol_value, addend); -+} -+ -+static bfd_reloc_status_type -+nios2_elf32_do_ujmp_relocate (bfd *abfd, reloc_howto_type *howto, -+ asection *input_section ATTRIBUTE_UNUSED, -+ bfd_byte *data, bfd_vma offset, -+ bfd_vma symbol_value, bfd_vma addend) -+{ -+ bfd_vma symbol_lo16, symbol_hi16; -+ bfd_reloc_status_type r; -+ symbol_value = symbol_value + addend; -+ addend = 0; -+ symbol_hi16 = (symbol_value >> 16) & 0xffff; -+ symbol_lo16 = symbol_value & 0xffff; -+ -+ r = _bfd_final_link_relocate (howto, abfd, input_section, -+ data, offset, symbol_hi16, addend); -+ -+ if (r == bfd_reloc_ok) -+ return _bfd_final_link_relocate (howto, abfd, input_section, -+ data, offset + 4, symbol_lo16, addend); -+ -+ return r; -+} -+ -+static bfd_reloc_status_type -+nios2_elf32_do_cjmp_relocate (bfd *abfd, reloc_howto_type *howto, -+ asection *input_section ATTRIBUTE_UNUSED, -+ bfd_byte *data, bfd_vma offset, -+ bfd_vma symbol_value, bfd_vma addend) -+{ -+ bfd_vma symbol_lo16, symbol_hi16; -+ bfd_reloc_status_type r; -+ symbol_value = symbol_value + addend; -+ addend = 0; -+ symbol_hi16 = (symbol_value >> 16) & 0xffff; -+ symbol_lo16 = symbol_value & 0xffff; -+ -+ r = _bfd_final_link_relocate (howto, abfd, input_section, -+ data, offset, symbol_hi16, addend); -+ -+ if (r == bfd_reloc_ok) -+ return _bfd_final_link_relocate (howto, abfd, input_section, -+ data, offset + 4, symbol_lo16, addend); -+ -+ return r; -+} -+ -+static bfd_reloc_status_type -+nios2_elf32_do_callr_relocate (bfd *abfd, reloc_howto_type *howto, -+ asection *input_section ATTRIBUTE_UNUSED, -+ bfd_byte *data, bfd_vma offset, -+ bfd_vma symbol_value, bfd_vma addend) -+{ -+ bfd_vma symbol_lo16, symbol_hi16; -+ bfd_reloc_status_type r; -+ symbol_value = symbol_value + addend; -+ addend = 0; -+ symbol_hi16 = (symbol_value >> 16) & 0xffff; -+ symbol_lo16 = symbol_value & 0xffff; -+ -+ r = _bfd_final_link_relocate (howto, abfd, input_section, -+ data, offset, symbol_hi16, addend); -+ -+ if (r == bfd_reloc_ok) -+ return _bfd_final_link_relocate (howto, abfd, input_section, -+ data, offset + 4, symbol_lo16, addend); -+ -+ return r; -+} -+ -+/* The function nios2_elf32_relocate_section is used by the linker -+ to perform relocations. */ -+static bfd_boolean -+nios2_elf32_relocate_section (bfd * output_bfd, -+ struct bfd_link_info *info, -+ bfd * input_bfd, -+ asection * input_section, -+ bfd_byte * contents, -+ Elf_Internal_Rela * relocs, -+ Elf_Internal_Sym * local_syms, -+ asection ** local_sections) -+{ -+ Elf_Internal_Shdr *symtab_hdr; -+ struct elf_link_hash_entry **sym_hashes; -+ Elf_Internal_Rela *rel; -+ Elf_Internal_Rela *relend; -+ struct elf32_nios2_link_hash_table *htab; -+ asection *sgot; -+ asection *splt; -+ asection *sreloc = NULL; -+ bfd_vma *local_got_offsets; -+ bfd *dynobj = NULL; -+ -+ symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr; -+ sym_hashes = elf_sym_hashes (input_bfd); -+ relend = relocs + input_section->reloc_count; -+ -+ htab = elf32_nios2_hash_table (info); -+ sgot = htab->sgot; -+ splt = htab->splt; -+ local_got_offsets = elf_local_got_offsets (input_bfd); -+ -+ dynobj = elf_hash_table (info)->dynobj; -+ -+#if 0 -+ size_t psymalloc = 0; -+ _bfd_generic_link_output_symbols(output_bfd, input_bfd, info, &psymalloc); -+#endif -+ for (rel = relocs; rel < relend; rel++) -+ { -+ reloc_howto_type *howto; -+ unsigned long r_symndx; -+ Elf_Internal_Sym *sym; -+ asection *sec; -+ struct elf_link_hash_entry *h; -+ struct elf32_nios2_link_hash_entry *eh; -+ bfd_vma relocation; -+ bfd_vma gp; -+ bfd_vma reloc_address; -+ bfd_reloc_status_type r = bfd_reloc_ok; -+ const char *name = NULL; -+ int r_type; -+ const char *format; -+ char msgbuf[256]; -+ const char* msg = (const char*) NULL; -+ bfd_boolean unresolved_reloc; -+ bfd_vma off; -+ int use_plt; -+ -+ -+ -+ r_type = ELF32_R_TYPE (rel->r_info); -+ -+ r_symndx = ELF32_R_SYM (rel->r_info); -+ -+ if (info->relocatable) -+ { -+ /* This is a relocatable link. We don't have to change -+ anything, unless the reloc is against a section symbol, -+ in which case we have to adjust according to where the -+ section symbol winds up in the output section. */ -+ if (r_symndx < symtab_hdr->sh_info) -+ { -+ sym = local_syms + r_symndx; -+ -+ if (ELF_ST_TYPE (sym->st_info) == STT_SECTION) -+ { -+ sec = local_sections[r_symndx]; -+ rel->r_addend += sec->output_offset + sym->st_value; -+ } -+ } -+ continue; -+ } -+ -+ /* This is a final link. */ -+ howto = lookup_howto ((unsigned) ELF32_R_TYPE (rel->r_info)); -+ h = NULL; -+ sym = NULL; -+ sec = NULL; -+ -+ if (r_symndx < symtab_hdr->sh_info) -+ { -+ sym = local_syms + r_symndx; -+ sec = local_sections[r_symndx]; -+ relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel); -+ } -+ else -+ { -+ bfd_boolean warned; -+ -+ RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel, -+ r_symndx, symtab_hdr, sym_hashes, -+ h, sec, relocation, -+ unresolved_reloc, warned); -+ } -+ -+ if (sec != NULL && elf_discarded_section (sec)) -+ { -+ /* For relocs against symbols from removed linkonce sections, -+ or sections discarded by a linker script, we just want the -+ section contents zeroed. Avoid any special processing. */ -+ _bfd_clear_contents (howto, input_bfd, contents + rel->r_offset); -+ rel->r_info = 0; -+ rel->r_addend = 0; -+ continue; -+ } -+ -+ if (sec && sec->output_section != NULL) -+ reloc_address = sec->output_section->vma + sec->output_offset + -+ rel->r_offset; -+ else -+ reloc_address = 0; -+ -+ if (howto != NULL) -+ { -+ switch (howto->type) -+ { -+ case R_NIOS2_HI16: -+ r = -+ nios2_elf32_do_hi16_relocate (input_bfd, howto, input_section, -+ contents, rel->r_offset, -+ relocation, rel->r_addend); -+ break; -+ case R_NIOS2_LO16: -+ r = -+ nios2_elf32_do_lo16_relocate (input_bfd, howto, input_section, -+ contents, rel->r_offset, -+ relocation, rel->r_addend); -+ break; -+ case R_NIOS2_PCREL_LO: -+ r = -+ nios2_elf32_do_pcrel_lo16_relocate (input_bfd, howto, -+ input_section, contents, -+ rel->r_offset, relocation, -+ rel->r_addend); -+ break; -+ case R_NIOS2_HIADJ16: -+ r = -+ nios2_elf32_do_hiadj16_relocate (input_bfd, howto, -+ input_section, contents, -+ rel->r_offset, relocation, -+ rel->r_addend); -+ break; -+ case R_NIOS2_PCREL_HA: -+ r = -+ nios2_elf32_do_pcrel_hiadj16_relocate (input_bfd, howto, -+ input_section, contents, -+ rel->r_offset, -+ relocation, -+ rel->r_addend); -+ break; -+ case R_NIOS2_PCREL16: -+ r = -+ nios2_elf32_do_pcrel16_relocate (input_bfd, howto, -+ input_section, contents, -+ rel->r_offset, relocation, -+ rel->r_addend); -+ break; -+ case R_NIOS2_GPREL: -+ /* Turns an absolute address into a gp-relative address. */ -+ if (!nios2_elf_assign_gp (output_bfd, &gp, info)) -+ { -+ format = _("global pointer relative relocation at address " -+ "0x%08x when _gp not defined\n"); -+ sprintf(msgbuf, format, reloc_address); -+ msg = msgbuf; -+ r = bfd_reloc_dangerous; -+ } -+ else -+ { -+ bfd_vma symbol_address = rel->r_addend + relocation; -+ relocation = relocation + rel->r_addend - gp; -+ rel->r_addend = 0; -+ if ((signed) relocation < -32768 -+ || (signed) relocation > 32767) -+ { -+ format = _("Unable to reach %s (at 0x%08x) from the " -+ "global pointer (at 0x%08x) because the " -+ "offset (%d) is out of the allowed range, " -+ "-32678 to 32767.\n" ); -+ sprintf(msgbuf, format, name, symbol_address, gp, -+ (signed)relocation); -+ msg = msgbuf; -+ r = bfd_reloc_outofrange; -+ } -+ else -+ { -+ r = -+ _bfd_final_link_relocate (howto, input_bfd, -+ input_section, contents, -+ rel->r_offset, relocation, -+ rel->r_addend); -+ } -+ } -+ -+ break; -+ case R_NIOS2_UJMP: -+ r = -+ nios2_elf32_do_ujmp_relocate (input_bfd, howto, input_section, -+ contents, rel->r_offset, -+ relocation, rel->r_addend); -+ break; -+ case R_NIOS2_CJMP: -+ r = -+ nios2_elf32_do_cjmp_relocate (input_bfd, howto, input_section, -+ contents, rel->r_offset, -+ relocation, rel->r_addend); -+ break; -+ case R_NIOS2_CALLR: -+ r = -+ nios2_elf32_do_callr_relocate (input_bfd, howto, -+ input_section, contents, -+ rel->r_offset, relocation, -+ rel->r_addend); -+ break; -+ case R_NIOS2_CALL26: -+ /* Handle relocations which should use the PLT entry. -+ NIOS2_BFD_RELOC_32 relocations will use the symbol's value, -+ which may point to a PLT entry, but we don't need to handle -+ that here. If we created a PLT entry, all branches in this -+ object should go to it. */ -+ if (h != NULL && splt != NULL && h->plt.offset != (bfd_vma) -1) -+ { -+ /* If we've created a .plt section, and assigned a PLT entry -+ to this function, it should not be known to bind locally. -+ If it were, we would have cleared the PLT entry. */ -+ BFD_ASSERT (!SYMBOL_CALLS_LOCAL (info, h)); -+ -+ relocation = (splt->output_section->vma -+ + splt->output_offset -+ + h->plt.offset); -+ -+ unresolved_reloc = FALSE; -+ } -+ r = -+ nios2_elf32_do_call26_relocate (input_bfd, howto, -+ input_section, contents, -+ rel->r_offset, relocation, -+ rel->r_addend); -+ break; -+ case R_NIOS2_ALIGN: -+ r = bfd_reloc_ok; -+ /* For symmetry this would be -+ r = nios2_elf32_do_ignore_reloc (input_bfd, howto, -+ input_section, contents, -+ rel->r_offset, relocation, -+ rel->r_addend); -+ but do_ignore_reloc would do no more than return bfd_reloc_ok. -+ */ -+ break; -+ -+ case R_NIOS2_GOT16: -+ case R_NIOS2_CALL16: -+ /* Relocation is to the entry for this symbol in the -+ global offset table. */ -+ if (sgot == NULL) -+ { -+ r = bfd_reloc_notsupported; -+ break; -+ } -+ -+ use_plt = 0; -+ -+ if (h != NULL) -+ { -+ bfd_boolean dyn; -+ -+ eh = (struct elf32_nios2_link_hash_entry *)h; -+ use_plt = (eh->got_types_used == CALL16_USED && -+ h->plt.offset != (bfd_vma) -1); -+ -+ off = h->got.offset; -+ BFD_ASSERT (off != (bfd_vma) -1); -+ dyn = elf_hash_table (info)->dynamic_sections_created; -+ if (! WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, info->shared, h) -+ || (info->shared -+ && SYMBOL_REFERENCES_LOCAL (info, h)) -+ || (ELF_ST_VISIBILITY (h->other) -+ && h->root.type == bfd_link_hash_undefweak)) -+ { -+ /* This is actually a static link, or it is a -Bsymbolic -+ link and the symbol is defined locally. We must -+ initialize this entry in the global offset table. -+ Since the offset must always be a multiple of 4, we -+ use the least significant bit to record whether we -+ have initialized it already. -+ -+ When doing a dynamic link, we create a .rela.got -+ relocation entry to initialize the value. This is -+ done in the finish_dynamic_symbol routine. */ -+ if ((off & 1) != 0) -+ off &= ~1; -+ else -+ { -+ bfd_put_32 (output_bfd, relocation, -+ sgot->contents + off); -+ h->got.offset |= 1; -+ } -+ } -+ else -+ unresolved_reloc = FALSE; -+ } -+ else -+ { -+ BFD_ASSERT (local_got_offsets != NULL && -+ local_got_offsets[r_symndx] != (bfd_vma) -1); -+ -+ off = local_got_offsets[r_symndx]; -+ -+ /* The offset must always be a multiple of 4. We use the -+ least significant bit to record whether we have already -+ generated the necessary reloc. */ -+ if ((off & 1) != 0) -+ off &= ~1; -+ else -+ { -+ bfd_put_32 (output_bfd, relocation, -+ sgot->contents + off); -+ -+ if (info->shared) -+ { -+ asection * srelgot; -+ Elf_Internal_Rela outrel; -+ bfd_byte *loc; -+ -+ srelgot = htab->srelgot; -+ BFD_ASSERT (srelgot != NULL); -+ -+ outrel.r_addend = relocation; -+ outrel.r_offset = (sgot->output_section->vma -+ + sgot->output_offset -+ + off); -+ outrel.r_info = ELF32_R_INFO (0, R_NIOS2_RELATIVE); -+ loc = srelgot->contents; -+ loc += (srelgot->reloc_count++ * -+ sizeof (Elf32_External_Rela)); -+ bfd_elf32_swap_reloca_out (output_bfd, &outrel, loc); -+ } -+ -+ local_got_offsets[r_symndx] |= 1; -+ } -+ } -+ -+ if (use_plt && info->shared) -+ { -+ off = ((h->plt.offset - 24) / 12 + 3) * 4; -+ relocation = htab->sgotplt->output_offset + off; -+ } -+ else -+ relocation = sgot->output_offset + off; -+ -+ /* This relocation does not use the addend. */ -+ rel->r_addend = 0; -+ -+ r = _bfd_final_link_relocate (howto, input_bfd, input_section, -+ contents, rel->r_offset, -+ relocation, rel->r_addend); -+ break; -+ -+ case R_NIOS2_GOTOFF_LO: -+ case R_NIOS2_GOTOFF_HA: -+ case R_NIOS2_GOTOFF: -+ /* Relocation is relative to the start of the -+ global offset table. */ -+ -+ BFD_ASSERT (sgot != NULL); -+ if (sgot == NULL) -+ { -+ r = bfd_reloc_notsupported; -+ break; -+ } -+ -+ /* Note that sgot->output_offset is not involved in this -+ calculation. We always want the start of .got. If we -+ define _GLOBAL_OFFSET_TABLE in a different way, as is -+ permitted by the ABI, we might have to change this -+ calculation. */ -+ relocation -= sgot->output_section->vma; -+ switch (howto->type) -+ { -+ case R_NIOS2_GOTOFF_LO: -+ r = nios2_elf32_do_lo16_relocate (input_bfd, howto, -+ input_section, contents, -+ rel->r_offset, relocation, -+ rel->r_addend); -+ break; -+ case R_NIOS2_GOTOFF_HA: -+ r = nios2_elf32_do_hiadj16_relocate (input_bfd, howto, -+ input_section, contents, -+ rel->r_offset, -+ relocation, -+ rel->r_addend); -+ break; -+ default: -+ r = _bfd_final_link_relocate (howto, input_bfd, -+ input_section, contents, -+ rel->r_offset, relocation, -+ rel->r_addend); -+ break; -+ } -+ break; -+ -+ case R_NIOS2_TLS_LDO16: -+ relocation -= dtpoff_base (info) + DTP_OFFSET; -+ -+ r = _bfd_final_link_relocate (howto, input_bfd, input_section, -+ contents, rel->r_offset, -+ relocation, rel->r_addend); -+ break; -+ case R_NIOS2_TLS_LDM16: -+ { -+ bfd_vma off; -+ -+ if (htab->sgot == NULL) -+ abort (); -+ -+ off = htab->tls_ldm_got.offset; -+ -+ if ((off & 1) != 0) -+ off &= ~1; -+ else -+ { -+ /* If we don't know the module number, create a relocation -+ for it. */ -+ if (info->shared) -+ { -+ Elf_Internal_Rela outrel; -+ bfd_byte *loc; -+ -+ if (htab->srelgot == NULL) -+ abort (); -+ -+ outrel.r_addend = 0; -+ outrel.r_offset = (htab->sgot->output_section->vma -+ + htab->sgot->output_offset -+ + off); -+ outrel.r_info = ELF32_R_INFO (0, R_NIOS2_TLS_DTPMOD); -+ -+ loc = htab->srelgot->contents; -+ loc += (htab->srelgot->reloc_count++ -+ * sizeof (Elf32_External_Rela)); -+ bfd_elf32_swap_reloca_out (output_bfd, &outrel, loc); -+ } -+ else -+ bfd_put_32 (output_bfd, 1, -+ htab->sgot->contents + off); -+ -+ htab->tls_ldm_got.offset |= 1; -+ } -+ -+ relocation = (htab->sgot->output_offset + off); -+ -+ r = _bfd_final_link_relocate (howto, input_bfd, -+ input_section, contents, -+ rel->r_offset, relocation, -+ rel->r_addend); -+ } -+ -+ break; -+ case R_NIOS2_TLS_GD16: -+ case R_NIOS2_TLS_IE16: -+ { -+ bfd_vma off; -+ int indx; -+ char tls_type; -+ -+ if (htab->sgot == NULL) -+ abort (); -+ -+ indx = 0; -+ if (h != NULL) -+ { -+ bfd_boolean dyn; -+ dyn = htab->root.dynamic_sections_created; -+ if (WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, info->shared, h) -+ && (!info->shared -+ || !SYMBOL_REFERENCES_LOCAL (info, h))) -+ { -+ unresolved_reloc = FALSE; -+ indx = h->dynindx; -+ } -+ off = h->got.offset; -+ tls_type = (((struct elf32_nios2_link_hash_entry *) h) -+ ->tls_type); -+ } -+ else -+ { -+ if (local_got_offsets == NULL) -+ abort (); -+ off = local_got_offsets[r_symndx]; -+ tls_type = (elf32_nios2_local_got_tls_type (input_bfd) -+ [r_symndx]); -+ } -+ -+ if (tls_type == GOT_UNKNOWN) -+ abort (); -+ -+ if ((off & 1) != 0) -+ off &= ~1; -+ else -+ { -+ bfd_boolean need_relocs = FALSE; -+ Elf_Internal_Rela outrel; -+ bfd_byte *loc = NULL; -+ int cur_off = off; -+ -+ /* The GOT entries have not been initialized yet. Do it -+ now, and emit any relocations. If both an IE GOT and a -+ GD GOT are necessary, we emit the GD first. */ -+ -+ if ((info->shared || indx != 0) -+ && (h == NULL -+ || ELF_ST_VISIBILITY (h->other) == STV_DEFAULT -+ || h->root.type != bfd_link_hash_undefweak)) -+ { -+ need_relocs = TRUE; -+ if (htab->srelgot == NULL) -+ abort (); -+ loc = htab->srelgot->contents; -+ loc += (htab->srelgot->reloc_count * -+ sizeof (Elf32_External_Rela)); -+ } -+ -+ if (tls_type & GOT_TLS_GD) -+ { -+ if (need_relocs) -+ { -+ outrel.r_addend = 0; -+ outrel.r_offset = (htab->sgot->output_section->vma -+ + htab->sgot->output_offset -+ + cur_off); -+ outrel.r_info = ELF32_R_INFO (indx, -+ R_NIOS2_TLS_DTPMOD); -+ -+ bfd_elf32_swap_reloca_out (output_bfd, &outrel, -+ loc); -+ htab->srelgot->reloc_count++; -+ loc += sizeof (Elf32_External_Rela); -+ -+ if (indx == 0) -+ bfd_put_32 (output_bfd, -+ (relocation - dtpoff_base (info) - -+ DTP_OFFSET), -+ htab->sgot->contents + cur_off + 4); -+ else -+ { -+ outrel.r_addend = 0; -+ outrel.r_info = ELF32_R_INFO (indx, -+ R_NIOS2_TLS_DTPREL); -+ outrel.r_offset += 4; -+ -+ bfd_elf32_swap_reloca_out (output_bfd, &outrel, -+ loc); -+ htab->srelgot->reloc_count++; -+ loc += sizeof (Elf32_External_Rela); -+ } -+ } -+ else -+ { -+ /* If we are not emitting relocations for a -+ general dynamic reference, then we must be in a -+ static link or an executable link with the -+ symbol binding locally. Mark it as belonging -+ to module 1, the executable. */ -+ bfd_put_32 (output_bfd, 1, -+ htab->sgot->contents + cur_off); -+ bfd_put_32 (output_bfd, (relocation - -+ dtpoff_base (info) - -+ DTP_OFFSET), -+ htab->sgot->contents + cur_off + 4); -+ } -+ -+ cur_off += 8; -+ } -+ -+ if (tls_type & GOT_TLS_IE) -+ { -+ if (need_relocs) -+ { -+ if (indx == 0) -+ outrel.r_addend = (relocation - -+ dtpoff_base (info)); -+ else -+ outrel.r_addend = 0; -+ outrel.r_offset = (htab->sgot->output_section->vma -+ + htab->sgot->output_offset -+ + cur_off); -+ outrel.r_info = ELF32_R_INFO (indx, -+ R_NIOS2_TLS_TPREL); -+ -+ bfd_elf32_swap_reloca_out (output_bfd, &outrel, -+ loc); -+ htab->srelgot->reloc_count++; -+ loc += sizeof (Elf32_External_Rela); -+ } -+ else -+ bfd_put_32 (output_bfd, (tpoff (info, relocation) -+ - TP_OFFSET), -+ htab->sgot->contents + cur_off); -+ cur_off += 4; -+ } -+ -+ if (h != NULL) -+ h->got.offset |= 1; -+ else -+ local_got_offsets[r_symndx] |= 1; -+ } -+ -+ if ((tls_type & GOT_TLS_GD) && r_type != R_NIOS2_TLS_GD16) -+ off += 8; -+ relocation = (htab->sgot->output_offset + off); -+ -+ r = _bfd_final_link_relocate (howto, input_bfd, input_section, -+ contents, rel->r_offset, -+ relocation, rel->r_addend); -+ } -+ -+ break; -+ case R_NIOS2_TLS_LE16: -+ if (info->shared) -+ { -+ (*_bfd_error_handler) -+ (_("%B(%A+0x%lx): R_NIOS2_TLS_LE16 relocation not " -+ "permitted in shared object"), -+ input_bfd, input_section, -+ (long) rel->r_offset, howto->name); -+ return FALSE; -+ } -+ else -+ relocation = tpoff (info, relocation) - TP_OFFSET; -+ -+ r = _bfd_final_link_relocate (howto, input_bfd, input_section, -+ contents, rel->r_offset, -+ relocation, rel->r_addend); -+ break; -+ -+ case R_NIOS2_BFD_RELOC_32: -+ if (info->shared -+ && (input_section->flags & SEC_ALLOC) != 0 -+ && (h == NULL -+ || ELF_ST_VISIBILITY (h->other) == STV_DEFAULT -+ || h->root.type != bfd_link_hash_undefweak)) -+ { -+ Elf_Internal_Rela outrel; -+ bfd_byte *loc; -+ bfd_boolean skip, relocate; -+ -+ /* When generating a shared object, these relocations -+ are copied into the output file to be resolved at run -+ time. */ -+ -+ skip = FALSE; -+ relocate = FALSE; -+ -+ outrel.r_offset = -+ _bfd_elf_section_offset (output_bfd, info, input_section, -+ rel->r_offset); -+ if (outrel.r_offset == (bfd_vma) -1) -+ skip = TRUE; -+ else if (outrel.r_offset == (bfd_vma) -2) -+ skip = TRUE, relocate = TRUE; -+ outrel.r_offset += (input_section->output_section->vma -+ + input_section->output_offset); -+ -+ if (skip) -+ memset (&outrel, 0, sizeof outrel); -+ else if (h != NULL -+ && h->dynindx != -1 -+ && (!info->shared -+ || !info->symbolic -+ || !h->def_regular)) -+ { -+ outrel.r_info = ELF32_R_INFO (h->dynindx, r_type); -+ outrel.r_addend = rel->r_addend; -+ } -+ else -+ { -+ /* This symbol is local, or marked to become local. */ -+ outrel.r_addend = relocation + rel->r_addend; -+ relocate = TRUE; -+ outrel.r_info = ELF32_R_INFO (0, R_NIOS2_RELATIVE); -+ } -+ -+ sreloc = elf_section_data (input_section)->sreloc; -+ if (sreloc == NULL) -+ abort (); -+ -+ loc = sreloc->contents; -+ loc += sreloc->reloc_count++ * sizeof (Elf32_External_Rela); -+ bfd_elf32_swap_reloca_out (output_bfd, &outrel, loc); -+ -+ /* This reloc will be computed at runtime, so there's no -+ need to do anything now, except for R_NIOS2_BFD_RELOC_32 -+ relocations that have been turned into -+ R_NIOS2_RELATIVE. */ -+ if (!relocate) -+ break; -+ } -+ -+ r = _bfd_final_link_relocate (howto, input_bfd, -+ input_section, contents, -+ rel->r_offset, relocation, -+ rel->r_addend); -+ break; -+ -+ case R_NIOS2_TLS_DTPREL: -+ relocation -= dtpoff_base (info); -+ /* Fall through. */ -+ -+ default: -+ r = _bfd_final_link_relocate (howto, input_bfd, -+ input_section, contents, -+ rel->r_offset, relocation, -+ rel->r_addend); -+ break; -+ } -+ } -+ else -+ { -+ r = bfd_reloc_notsupported; -+ } -+ -+ if (r != bfd_reloc_ok) -+ { -+ if (h != NULL) -+ name = h->root.root.string; -+ else -+ { -+ name = (bfd_elf_string_from_elf_section -+ (input_bfd, symtab_hdr->sh_link, sym->st_name)); -+ if (name == NULL || *name == '\0') -+ name = bfd_section_name (input_bfd, sec); -+ } -+ -+ switch (r) -+ { -+ case bfd_reloc_overflow: -+ r = info->callbacks->reloc_overflow -+ (info, NULL, name, howto->name, (bfd_vma) 0, -+ input_bfd, input_section, rel->r_offset); -+ break; -+ -+ case bfd_reloc_undefined: -+ r = info->callbacks->undefined_symbol -+ (info, name, input_bfd, input_section, rel->r_offset, TRUE); -+ break; -+ -+ case bfd_reloc_outofrange: -+ if (msg == NULL) -+ msg = _("relocation out of range"); -+ break; -+ -+ case bfd_reloc_notsupported: -+ if (msg == NULL) -+ msg = _("unsupported relocation"); -+ break; -+ -+ case bfd_reloc_dangerous: -+ if (msg == NULL) -+ msg = _("dangerous relocation"); -+ break; -+ -+ default: -+ if (msg == NULL) -+ msg = _("unknown error"); -+ break; -+ } -+ -+ if (msg) -+ { -+ r = info->callbacks->warning -+ (info, msg, name, input_bfd, input_section, rel->r_offset); -+ return linker_force_make_executable; -+ } -+ } -+ } -+ return TRUE; -+} -+ -+ -+ -+/* Handle an NIOS2 specific section when reading an object file. This -+ is called when elfcode.h finds a section with an unknown type. -+ FIXME: We need to handle the SHF_NIOS2_GPREL flag. */ -+ -+static bfd_boolean -+nios2_elf32_section_from_shdr (bfd *abfd, -+ Elf_Internal_Shdr *hdr, const char *name, int shindex) -+{ -+ asection *newsect; -+ -+ /* NG - I'm keeping this code commented out at the moment -+ in case we add a .mdebug section. */ -+ -+ /* -+ switch (hdr->sh_type) -+ { -+ case SHT_NIOS2_DEBUG: -+ if (strcmp (name, ".mdebug") != 0) -+ return FALSE; -+ break; -+ default: -+ return FALSE; -+ } -+ */ -+ -+ if (!_bfd_elf_make_section_from_shdr (abfd, hdr, name, shindex)) -+ return FALSE; -+ -+ newsect = hdr->bfd_section; -+ -+ /* ditto */ -+ /* -+ if (hdr->sh_type == SHT_NIOS2_DEBUG) -+ { -+ if (! bfd_set_section_flags (abfd, newsect, -+ (bfd_get_section_flags (abfd, newsect) -+ | SEC_DEBUGGING))) -+ return FALSE; -+ } -+ */ -+ return TRUE; -+} -+ -+/* Convert NIOS2 specific section flags to bfd internal section flags. */ -+ -+static bfd_boolean -+nios2_elf32_section_flags (flagword *flags, const Elf_Internal_Shdr *hdr) -+{ -+ if (hdr->sh_flags & SHF_NIOS2_GPREL) -+ *flags |= SEC_SMALL_DATA; -+ -+ return TRUE; -+} -+ -+/* Set the correct type for an NIOS2 ELF section. We do this by the -+ section name, which is a hack, but ought to work. */ -+ -+static bfd_boolean -+nios2_elf32_fake_sections (bfd *abfd ATTRIBUTE_UNUSED, -+ Elf_Internal_Shdr *hdr, asection *sec) -+{ -+ register const char *name; -+ -+ name = bfd_get_section_name (abfd, sec); -+ -+ if (strcmp (name, ".mdebug") == 0) -+ { -+ /* we don't yet have an .mdebug section, but I'm leaving this here -+ in case we ever do -+ hdr->sh_type = SHT_NIOS2_DEBUG; -+ -+ if ((abfd->flags & DYNAMIC) != 0 ) -+ hdr->sh_entsize = 0; -+ else -+ hdr->sh_entsize = 1; -+ */ -+ } -+ else if ((sec->flags & SEC_SMALL_DATA) -+ || strcmp (name, ".sdata") == 0 -+ || strcmp (name, ".sbss") == 0 -+ || strcmp (name, ".lit4") == 0 || strcmp (name, ".lit8") == 0) -+ hdr->sh_flags |= SHF_NIOS2_GPREL; -+ -+ return TRUE; -+} -+ -+/* Create .got, .gotplt, and .rela.got sections in DYNOBJ, and set up -+ shortcuts to them in our hash table. */ -+ -+static bfd_boolean -+create_got_section (bfd *dynobj, struct bfd_link_info *info) -+{ -+ struct elf32_nios2_link_hash_table *htab; -+ -+ htab = elf32_nios2_hash_table (info); -+ -+ if (! _bfd_elf_create_got_section (dynobj, info)) -+ return FALSE; -+ -+ htab->sgot = bfd_get_section_by_name (dynobj, ".got"); -+ htab->sgotplt = bfd_get_section_by_name (dynobj, ".got.plt"); -+ if (!htab->sgot || !htab->sgotplt) -+ abort (); -+ -+ /* In order for the two loads in .PLTresolve to share the same %hiadj, -+ _GLOBAL_OFFSET_TABLE_ must be aligned to a 16-byte boundary. */ -+ if (!bfd_set_section_alignment (dynobj, htab->sgotplt, 4)) -+ return FALSE; -+ -+ htab->srelgot = bfd_make_section_with_flags (dynobj, -+ ".rela.got", -+ (SEC_ALLOC | SEC_LOAD -+ | SEC_HAS_CONTENTS -+ | SEC_IN_MEMORY -+ | SEC_LINKER_CREATED -+ | SEC_READONLY)); -+ if (htab->srelgot == NULL -+ || ! bfd_set_section_alignment (dynobj, htab->srelgot, 2)) -+ return FALSE; -+ return TRUE; -+} -+ -+/* Create .plt, .rela.plt, .got, .got.plt, .rela.got, .dynbss, and -+ .rela.bss sections in DYNOBJ, and set up shortcuts to them in our -+ hash table. */ -+ -+static bfd_boolean -+nios2_elf32_create_dynamic_sections (bfd *dynobj, struct bfd_link_info *info) -+{ -+ struct elf32_nios2_link_hash_table *htab; -+ -+ htab = elf32_nios2_hash_table (info); -+ if (!htab->sgot && !create_got_section (dynobj, info)) -+ return FALSE; -+ -+ _bfd_elf_create_dynamic_sections (dynobj, info); -+ -+ htab->splt = bfd_get_section_by_name (dynobj, ".plt"); -+ -+ /* In order for the two loads in a shared object .PLTresolve to share the -+ same %hiadj, the start of the PLT (as well as the GOT) must be aligned -+ to a 16-byte boundary. This is because the addresses for these loads -+ include the -(.plt+4) PIC correction. */ -+ if (!bfd_set_section_alignment (dynobj, htab->splt, 4)) -+ return FALSE; -+ -+ htab->srelplt = bfd_get_section_by_name (dynobj, ".rela.plt"); -+ htab->sdynbss = bfd_get_section_by_name (dynobj, ".dynbss"); -+ if (!htab->splt || !htab->srelplt || !htab->sdynbss) -+ return FALSE; -+ if (!info->shared) -+ { -+ htab->srelbss = bfd_get_section_by_name (dynobj, ".rela.bss"); -+ if (!htab->srelbss) -+ return FALSE; -+ } -+ -+ return TRUE; -+} -+ -+/* Copy the extra info we tack onto an elf_link_hash_entry. */ -+ -+static void -+nios2_elf32_copy_indirect_symbol (struct bfd_link_info *info, -+ struct elf_link_hash_entry *dir, -+ struct elf_link_hash_entry *ind) -+{ -+ struct elf32_nios2_link_hash_entry *edir, *eind; -+ -+ edir = (struct elf32_nios2_link_hash_entry *) dir; -+ eind = (struct elf32_nios2_link_hash_entry *) ind; -+ -+ if (eind->dyn_relocs != NULL) -+ { -+ if (edir->dyn_relocs != NULL) -+ { -+ struct elf32_nios2_dyn_relocs **pp; -+ struct elf32_nios2_dyn_relocs *p; -+ -+ /* Add reloc counts against the indirect sym to the direct sym -+ list. Merge any entries against the same section. */ -+ for (pp = &eind->dyn_relocs; (p = *pp) != NULL; ) -+ { -+ struct elf32_nios2_dyn_relocs *q; -+ -+ for (q = edir->dyn_relocs; q != NULL; q = q->next) -+ if (q->sec == p->sec) -+ { -+ q->pc_count += p->pc_count; -+ q->count += p->count; -+ *pp = p->next; -+ break; -+ } -+ if (q == NULL) -+ pp = &p->next; -+ } -+ *pp = edir->dyn_relocs; -+ } -+ -+ edir->dyn_relocs = eind->dyn_relocs; -+ eind->dyn_relocs = NULL; -+ } -+ -+ if (ind->root.type == bfd_link_hash_indirect -+ && dir->got.refcount <= 0) -+ { -+ edir->tls_type = eind->tls_type; -+ eind->tls_type = GOT_UNKNOWN; -+ } -+ -+ edir->got_types_used |= eind->got_types_used; -+ -+ _bfd_elf_link_hash_copy_indirect (info, dir, ind); -+} -+ -+/* Look through the relocs for a section during the first phase. */ -+ -+static bfd_boolean -+nios2_elf32_check_relocs (bfd *abfd, struct bfd_link_info *info, -+ asection *sec, const Elf_Internal_Rela *relocs) -+{ -+ bfd *dynobj; -+ Elf_Internal_Shdr *symtab_hdr; -+ struct elf_link_hash_entry **sym_hashes, **sym_hashes_end; -+ const Elf_Internal_Rela *rel; -+ const Elf_Internal_Rela *rel_end; -+ struct elf32_nios2_link_hash_table *htab; -+ asection *sgot; -+ asection *srelgot; -+ asection *sreloc = NULL; -+ bfd_signed_vma *local_got_refcounts; -+ -+ if (info->relocatable) -+ return TRUE; -+ -+ dynobj = elf_hash_table (info)->dynobj; -+ symtab_hdr = &elf_tdata (abfd)->symtab_hdr; -+ sym_hashes = elf_sym_hashes (abfd); -+ sym_hashes_end = -+ sym_hashes + symtab_hdr->sh_size / sizeof (Elf32_External_Sym); -+ if (!elf_bad_symtab (abfd)) -+ sym_hashes_end -= symtab_hdr->sh_info; -+ local_got_refcounts = elf_local_got_refcounts (abfd); -+ -+ htab = elf32_nios2_hash_table (info); -+ sgot = htab->sgot; -+ srelgot = htab->srelgot; -+ -+ rel_end = relocs + sec->reloc_count; -+ for (rel = relocs; rel < rel_end; rel++) -+ { -+ unsigned int r_type; -+ struct elf_link_hash_entry *h; -+ unsigned long r_symndx; -+ -+ r_symndx = ELF32_R_SYM (rel->r_info); -+ if (r_symndx < symtab_hdr->sh_info) -+ h = NULL; -+ else -+ { -+ h = sym_hashes[r_symndx - symtab_hdr->sh_info]; -+ while (h->root.type == bfd_link_hash_indirect -+ || h->root.type == bfd_link_hash_warning) -+ h = (struct elf_link_hash_entry *) h->root.u.i.link; -+ } -+ -+ r_type = ELF32_R_TYPE (rel->r_info); -+ -+ switch (r_type) -+ { -+ case R_NIOS2_GOT16: -+ case R_NIOS2_CALL16: -+ case R_NIOS2_TLS_GD16: -+ case R_NIOS2_TLS_IE16: -+ /* This symbol requires a global offset table entry. */ -+ { -+ int tls_type, old_tls_type; -+ -+ switch (r_type) -+ { -+ default: -+ case R_NIOS2_GOT16: -+ case R_NIOS2_CALL16: -+ tls_type = GOT_NORMAL; -+ break; -+ case R_NIOS2_TLS_GD16: -+ tls_type = GOT_TLS_GD; -+ break; -+ case R_NIOS2_TLS_IE16: -+ tls_type = GOT_TLS_IE; -+ break; -+ } -+ -+ if (dynobj == NULL) -+ { -+ /* Create the .got section. */ -+ elf_hash_table (info)->dynobj = dynobj = abfd; -+ nios2_elf32_create_dynamic_sections (dynobj, info); -+ } -+ -+ if (sgot == NULL) -+ { -+ sgot = htab->sgot; -+ BFD_ASSERT (sgot != NULL); -+ } -+ -+ if (srelgot == NULL -+ && (h != NULL || info->shared)) -+ { -+ srelgot = bfd_get_section_by_name (dynobj, ".rela.got"); -+ BFD_ASSERT (srelgot != NULL); -+ } -+ -+ if (h != NULL) -+ { -+ struct elf32_nios2_link_hash_entry *eh = -+ (struct elf32_nios2_link_hash_entry *)h; -+ h->got.refcount++; -+ old_tls_type = elf32_nios2_hash_entry(h)->tls_type; -+ if (r_type == R_NIOS2_CALL16) -+ { -+ /* Make sure a plt entry is created for this symbol if it -+ turns out to be a function defined by a dynamic object. -+ */ -+ h->plt.refcount++; -+ -+ h->needs_plt = 1; -+ -+ h->type = STT_FUNC; -+ -+ eh->got_types_used |= CALL16_USED; -+ } -+ else -+ eh->got_types_used |= GOT16_USED; -+ } -+ else -+ { -+ /* This is a global offset table entry for a local symbol. */ -+ if (local_got_refcounts == NULL) -+ { -+ bfd_size_type size; -+ -+ size = symtab_hdr->sh_info; -+ size *= (sizeof (bfd_signed_vma) + sizeof(char)); -+ local_got_refcounts = ((bfd_signed_vma *) -+ bfd_zalloc (abfd, size)); -+ if (local_got_refcounts == NULL) -+ return FALSE; -+ elf_local_got_refcounts (abfd) = local_got_refcounts; -+ elf32_nios2_local_got_tls_type (abfd) = -+ (char *) (local_got_refcounts + symtab_hdr->sh_info); -+ } -+ local_got_refcounts[r_symndx]++; -+ old_tls_type = -+ elf32_nios2_local_got_tls_type (abfd) [r_symndx]; -+ } -+ -+ /* We will already have issued an error message if there is a -+ TLS / non-TLS mismatch, based on the symbol type. We don't -+ support any linker relaxations. So just combine any TLS -+ types needed. */ -+ if (old_tls_type != GOT_UNKNOWN && old_tls_type != GOT_NORMAL -+ && tls_type != GOT_NORMAL) -+ tls_type |= old_tls_type; -+ -+ if (old_tls_type != tls_type) -+ { -+ if (h != NULL) -+ elf32_nios2_hash_entry (h)->tls_type = tls_type; -+ else -+ elf32_nios2_local_got_tls_type (abfd) [r_symndx] = tls_type; -+ } -+ } -+ /* Fall through */ -+ case R_NIOS2_TLS_LDM16: -+ if (r_type == R_NIOS2_TLS_LDM16) -+ htab->tls_ldm_got.refcount++; -+ -+ if (htab->sgot == NULL) -+ { -+ if (htab->root.dynobj == NULL) -+ htab->root.dynobj = abfd; -+ if (!create_got_section (htab->root.dynobj, info)) -+ return FALSE; -+ } -+ break; -+ -+ /* This relocation describes the C++ object vtable hierarchy. -+ Reconstruct it for later use during GC. */ -+ case R_NIOS2_GNU_VTINHERIT: -+ if (!bfd_elf_gc_record_vtinherit (abfd, sec, h, rel->r_offset)) -+ return FALSE; -+ break; -+ -+ /* This relocation describes which C++ vtable entries are actually -+ used. Record for later use during GC. */ -+ case R_NIOS2_GNU_VTENTRY: -+ if (!bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_addend)) -+ return FALSE; -+ break; -+ -+ case R_NIOS2_BFD_RELOC_32: -+ case R_NIOS2_CALL26: -+ case R_NIOS2_HIADJ16: -+ case R_NIOS2_LO16: -+ -+ if (h != NULL) -+ { -+ /* If this reloc is in a read-only section, we might -+ need a copy reloc. We can't check reliably at this -+ stage whether the section is read-only, as input -+ sections have not yet been mapped to output sections. -+ Tentatively set the flag for now, and correct in -+ adjust_dynamic_symbol. */ -+ if (!info->shared) -+ h->non_got_ref = 1; -+ -+ /* Make sure a plt entry is created for this symbol if it -+ turns out to be a function defined by a dynamic object. */ -+ h->plt.refcount++; -+ -+ if (r_type == R_NIOS2_CALL26) -+ h->needs_plt = 1; -+ } -+ -+ /* If we are creating a shared library, we need to copy the -+ reloc into the shared library. */ -+ if (info->shared -+ && (sec->flags & SEC_ALLOC) != 0 -+ && (r_type == R_NIOS2_BFD_RELOC_32 -+ || (h != NULL && ! h->needs_plt -+ && (! info->symbolic || ! h->def_regular)))) -+ { -+ struct elf32_nios2_dyn_relocs *p; -+ struct elf32_nios2_dyn_relocs **head; -+ -+ /* When creating a shared object, we must copy these -+ reloc types into the output file. We create a reloc -+ section in dynobj and make room for this reloc. */ -+ if (sreloc == NULL) -+ { -+ const char *name; -+ -+ name = (bfd_elf_string_from_elf_section -+ (abfd, -+ elf_elfheader (abfd)->e_shstrndx, -+ elf_section_data (sec)->rel_hdr.sh_name)); -+ if (name == NULL) -+ return FALSE; -+ -+ BFD_ASSERT (CONST_STRNEQ (name, ".rela") -+ && strcmp (bfd_get_section_name (abfd, sec), -+ name + 5) == 0); -+ -+ sreloc = bfd_get_section_by_name (dynobj, name); -+ if (sreloc == NULL) -+ { -+ sreloc = bfd_make_section_with_flags ( -+ dynobj, -+ name, -+ (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | -+ SEC_IN_MEMORY | SEC_LINKER_CREATED | SEC_READONLY)); -+ if (sreloc == NULL || -+ !bfd_set_section_alignment (dynobj, sreloc, 2)) -+ return FALSE; -+ } -+ elf_section_data (sec)->sreloc = sreloc; -+ } -+ -+ /* If this is a global symbol, we count the number of -+ relocations we need for this symbol. */ -+ if (h != NULL) -+ head = &((struct elf32_nios2_link_hash_entry *) h)->dyn_relocs; -+ else -+ { -+ /* Track dynamic relocs needed for local syms too. -+ We really need local syms available to do this -+ easily. Oh well. */ -+ -+ asection *s; -+ void *vpp; -+ Elf_Internal_Sym *isym; -+ -+ isym = bfd_sym_from_r_symndx (&htab->sym_sec, -+ abfd, r_symndx); -+ if (isym == NULL) -+ return FALSE; -+ -+ s = bfd_section_from_elf_index (abfd, isym->st_shndx); -+ if (s == NULL) -+ s = sec; -+ -+ vpp = &elf_section_data (s)->local_dynrel; -+ head = (struct _bfd_nios2_elf_dyn_relocs **) vpp; -+ } -+ -+ p = *head; -+ if (p == NULL || p->sec != sec) -+ { -+ bfd_size_type amt = sizeof *p; -+ p = ((struct elf32_nios2_dyn_relocs *) -+ bfd_alloc (htab->root.dynobj, amt)); -+ if (p == NULL) -+ return FALSE; -+ p->next = *head; -+ *head = p; -+ p->sec = sec; -+ p->count = 0; -+ p->pc_count = 0; -+ } -+ -+ p->count += 1; -+ -+ } -+ break; -+ } -+ } -+ -+ return TRUE; -+} -+ -+ -+/* Return the section that should be marked against GC for a given -+ relocation. */ -+ -+asection * -+nios2_elf32_gc_mark_hook (asection *sec, -+ struct bfd_link_info *info ATTRIBUTE_UNUSED, -+ Elf_Internal_Rela *rel, -+ struct elf_link_hash_entry *h, -+ Elf_Internal_Sym *sym) -+{ -+ if (h != NULL) -+ switch (ELF32_R_TYPE (rel->r_info)) -+ { -+ case R_NIOS2_GNU_VTINHERIT: -+ case R_NIOS2_GNU_VTENTRY: -+ return NULL; -+ } -+ return _bfd_elf_gc_mark_hook (sec, info, rel, h, sym); -+} -+ -+/* Update the got entry reference counts for the section being removed. */ -+ -+static bfd_boolean -+nios2_elf32_gc_sweep_hook (bfd *abfd, -+ struct bfd_link_info *info, -+ asection *sec, -+ const Elf_Internal_Rela *relocs) -+{ -+ Elf_Internal_Shdr *symtab_hdr; -+ struct elf_link_hash_entry **sym_hashes; -+ bfd_signed_vma *local_got_refcounts; -+ const Elf_Internal_Rela *rel, *relend; -+ bfd *dynobj; -+ asection *sgot; -+ asection *srelgot; -+ struct elf32_nios2_link_hash_table *htab; -+ -+ htab = elf32_nios2_hash_table (info); -+ sgot = htab->sgot; -+ srelgot = htab->srelgot; -+ -+ elf_section_data (sec)->local_dynrel = NULL; -+ -+ dynobj = elf_hash_table (info)->dynobj; -+ if (dynobj == NULL) -+ return TRUE; -+ -+ symtab_hdr = &elf_tdata (abfd)->symtab_hdr; -+ sym_hashes = elf_sym_hashes (abfd); -+ local_got_refcounts = elf_local_got_refcounts (abfd); -+ -+ relend = relocs + sec->reloc_count; -+ for (rel = relocs; rel < relend; rel++) -+ { -+ unsigned long r_symndx; -+ struct elf_link_hash_entry *h = NULL; -+ int r_type; -+ -+ r_symndx = ELF32_R_SYM (rel->r_info); -+ if (r_symndx >= symtab_hdr->sh_info) -+ { -+ h = sym_hashes[r_symndx - symtab_hdr->sh_info]; -+ while (h->root.type == bfd_link_hash_indirect -+ || h->root.type == bfd_link_hash_warning) -+ h = (struct elf_link_hash_entry *) h->root.u.i.link; -+ } -+ -+ r_type = ELF32_R_TYPE (rel->r_info); -+ switch (r_type) -+ { -+ case R_NIOS2_GOT16: -+ case R_NIOS2_CALL16: -+ if (h != NULL) -+ { -+ if (h->got.refcount > 0) -+ --h->got.refcount; -+ } -+ else if (local_got_refcounts != NULL) -+ { -+ if (local_got_refcounts[r_symndx] > 0) -+ --local_got_refcounts[r_symndx]; -+ } -+ break; -+ -+ case R_NIOS2_PCREL_LO: -+ case R_NIOS2_PCREL_HA: -+ case R_NIOS2_BFD_RELOC_32: -+ case R_NIOS2_CALL26: -+ if (h != NULL) -+ { -+ struct elf32_nios2_link_hash_entry *eh; -+ struct elf32_nios2_dyn_relocs **pp; -+ struct elf32_nios2_dyn_relocs *p; -+ -+ eh = (struct elf32_nios2_link_hash_entry *) h; -+ -+ if (h->plt.refcount > 0) -+ --h->plt.refcount; -+ -+ if (r_type == R_NIOS2_PCREL_LO || r_type == R_NIOS2_PCREL_HA || -+ r_type == R_NIOS2_BFD_RELOC_32) -+ { -+ for (pp = &eh->dyn_relocs; (p = *pp) != NULL; -+ pp = &p->next) -+ if (p->sec == sec) -+ { -+ p->count -= 1; -+ if (p->count == 0) -+ *pp = p->next; -+ break; -+ } -+ } -+ } -+ break; -+ -+ default: -+ break; -+ } -+ } -+ -+ return TRUE; -+} -+ -+/* Install 16-bit immediate value VALUE at offset OFFSET into section SEC. */ -+ -+static void -+nios2_elf32_install_imm16 (asection *sec, bfd_vma offset, bfd_vma value) -+{ -+ bfd_vma word = bfd_get_32 (sec->owner, sec->contents + offset); -+ -+ BFD_ASSERT(value <= 0xffff); -+ -+ bfd_put_32 (sec->owner, word | ((value & 0xffff) << 6), -+ sec->contents + offset); -+} -+ -+/* Install COUNT 32-bit values DATA starting at offset OFFSET into section SEC. -+ */ -+ -+static void -+nios2_elf32_install_data (asection *sec, const bfd_vma *data, bfd_vma offset, -+ int count) -+{ -+ while (count--) -+ { -+ bfd_put_32 (sec->owner, *data, sec->contents + offset); -+ offset += 4; -+ ++data; -+ } -+} -+ -+ -+/* Finish up dynamic symbol handling. We set the contents of various -+ dynamic sections here. */ -+ -+static bfd_boolean -+nios2_elf32_finish_dynamic_symbol (bfd * output_bfd, -+ struct bfd_link_info * info, -+ struct elf_link_hash_entry * h, -+ Elf_Internal_Sym * sym) -+{ -+ struct elf32_nios2_link_hash_table *htab; -+ struct elf32_nios2_link_hash_entry *eh = -+ (struct elf32_nios2_link_hash_entry *)h; -+ bfd *dynobj; -+ int use_plt; -+ -+ htab = elf32_nios2_hash_table (info); -+ -+ dynobj = elf_hash_table (info)->dynobj; -+ -+ if (h->plt.offset != (bfd_vma) -1) -+ { -+ asection *splt; -+ asection *sgotplt; -+ asection *srela; -+ bfd_vma plt_index; -+ bfd_vma got_offset; -+ Elf_Internal_Rela rela; -+ bfd_byte *loc; -+ bfd_vma got_address; -+ -+ /* This symbol has an entry in the procedure linkage table. Set -+ it up. */ -+ -+ BFD_ASSERT (h->dynindx != -1); -+ -+ splt = htab->splt; -+ sgotplt = htab->sgotplt; -+ srela = htab->srelplt; -+ BFD_ASSERT (splt != NULL && sgotplt != NULL && srela != NULL); -+ -+ /* Emit the PLT entry. */ -+ if (info->shared) -+ { -+ nios2_elf32_install_data (splt, nios2_so_plt_entry, h->plt.offset, -+ 3); -+ plt_index = (h->plt.offset - 24) / 12; -+ got_offset = (plt_index + 3) * 4; -+ nios2_elf32_install_imm16 (splt, h->plt.offset, -+ hiadj(plt_index * 4)); -+ nios2_elf32_install_imm16 (splt, h->plt.offset + 4, -+ (plt_index * 4) & 0xffff); -+ nios2_elf32_install_imm16 (splt, h->plt.offset + 8, -+ 0xfff4 - h->plt.offset); -+ got_address = (sgotplt->output_section->vma + sgotplt->output_offset -+ + got_offset); -+ -+ /* Fill in the entry in the global offset table. There are no -+ res_n slots for a shared object PLT, instead the .got.plt entries -+ point to the PLT entries. */ -+ bfd_put_32 (output_bfd, -+ splt->output_section->vma + splt->output_offset -+ + h->plt.offset, sgotplt->contents + got_offset); -+ } -+ else -+ { -+ plt_index = (h->plt.offset - 28 - htab->res_n_size) / 12; -+ got_offset = (plt_index + 3) * 4; -+ -+ nios2_elf32_install_data (splt, nios2_plt_entry, h->plt.offset, 3); -+ got_address = (sgotplt->output_section->vma + sgotplt->output_offset -+ + got_offset); -+ nios2_elf32_install_imm16 (splt, h->plt.offset, hiadj(got_address)); -+ nios2_elf32_install_imm16 (splt, h->plt.offset + 4, -+ got_address & 0xffff); -+ -+ /* Fill in the entry in the global offset table. */ -+ bfd_put_32 (output_bfd, -+ splt->output_section->vma + splt->output_offset -+ + plt_index * 4, sgotplt->contents + got_offset); -+ } -+ -+ /* Fill in the entry in the .rela.plt section. */ -+ rela.r_offset = got_address; -+ rela.r_info = ELF32_R_INFO (h->dynindx, R_NIOS2_JUMP_SLOT); -+ rela.r_addend = 0; -+ loc = srela->contents + plt_index * sizeof (Elf32_External_Rela); -+ bfd_elf32_swap_reloca_out (output_bfd, &rela, loc); -+ -+ if (!h->def_regular) -+ { -+ /* Mark the symbol as undefined, rather than as defined in -+ the .plt section. Leave the value alone. */ -+ sym->st_shndx = SHN_UNDEF; -+ /* If the symbol is weak, we do need to clear the value. -+ Otherwise, the PLT entry would provide a definition for -+ the symbol even if the symbol wasn't defined anywhere, -+ and so the symbol would never be NULL. */ -+ if (!h->ref_regular_nonweak) -+ sym->st_value = 0; -+ } -+ } -+ -+ use_plt = (eh->got_types_used == CALL16_USED && -+ h->plt.offset != (bfd_vma) -1); -+ -+ if (!use_plt && h->got.offset != (bfd_vma) -1 -+ && (elf32_nios2_hash_entry (h)->tls_type & GOT_TLS_GD) == 0 -+ && (elf32_nios2_hash_entry (h)->tls_type & GOT_TLS_IE) == 0) -+ { -+ asection *sgot; -+ asection *srela; -+ Elf_Internal_Rela rela; -+ bfd_byte *loc; -+ bfd_vma offset; -+ -+ /* This symbol has an entry in the global offset table. Set it -+ up. */ -+ -+ sgot = htab->sgot; -+ srela = htab->srelgot; -+ BFD_ASSERT (sgot != NULL && srela != NULL); -+ -+ offset = (h->got.offset & ~(bfd_vma) 1); -+ rela.r_offset = (sgot->output_section->vma -+ + sgot->output_offset + offset); -+ -+ /* If this is a -Bsymbolic link, and the symbol is defined -+ locally, we just want to emit a RELATIVE reloc. Likewise if -+ the symbol was forced to be local because of a version file. -+ The entry in the global offset table will already have been -+ initialized in the relocate_section function. */ -+ -+ if (info->shared && SYMBOL_REFERENCES_LOCAL (info, h)) -+ { -+ rela.r_info = ELF32_R_INFO (0, R_NIOS2_RELATIVE); -+ rela.r_addend = bfd_get_signed_32 (output_bfd, -+ (sgot->contents + offset)); -+ bfd_put_32 (output_bfd, (bfd_vma) 0, sgot->contents + offset); -+ } -+ else -+ { -+ bfd_put_32 (output_bfd, (bfd_vma) 0, -+ sgot->contents + offset); -+ rela.r_info = ELF32_R_INFO (h->dynindx, R_NIOS2_GLOB_DAT); -+ rela.r_addend = 0; -+ } -+ -+ loc = srela->contents; -+ loc += srela->reloc_count++ * sizeof (Elf32_External_Rela); -+ bfd_elf32_swap_reloca_out (output_bfd, &rela, loc); -+ } -+ -+ if (use_plt && h->got.offset != (bfd_vma) -1) -+ { -+ bfd_vma offset = (h->got.offset & ~(bfd_vma) 1); -+ asection *sgot = htab->sgot; -+ asection *splt = htab->splt; -+ bfd_put_32 (output_bfd, (splt->output_section->vma + splt->output_offset -+ + h->plt.offset), sgot->contents + offset); -+ } -+ -+ if (h->needs_copy) -+ { -+ asection *s; -+ Elf_Internal_Rela rela; -+ bfd_byte *loc; -+ -+ /* This symbol needs a copy reloc. Set it up. */ -+ -+ BFD_ASSERT (h->dynindx != -1 -+ && (h->root.type == bfd_link_hash_defined -+ || h->root.type == bfd_link_hash_defweak)); -+ -+ s = bfd_get_section_by_name (h->root.u.def.section->owner, -+ ".rela.bss"); -+ BFD_ASSERT (s != NULL); -+ -+ rela.r_offset = (h->root.u.def.value -+ + h->root.u.def.section->output_section->vma -+ + h->root.u.def.section->output_offset); -+ rela.r_info = ELF32_R_INFO (h->dynindx, R_NIOS2_COPY); -+ rela.r_addend = 0; -+ loc = s->contents + s->reloc_count++ * sizeof (Elf32_External_Rela); -+ bfd_elf32_swap_reloca_out (output_bfd, &rela, loc); -+ } -+ -+ /* Mark _DYNAMIC and _GLOBAL_OFFSET_TABLE_ as absolute. */ -+ if (strcmp (h->root.root.string, "_DYNAMIC") == 0 -+ || h == elf_hash_table (info)->hgot) -+ sym->st_shndx = SHN_ABS; -+ -+ return TRUE; -+} -+ -+/* Finish up the dynamic sections. */ -+ -+static bfd_boolean -+nios2_elf32_finish_dynamic_sections (bfd * output_bfd, -+ struct bfd_link_info * info) -+{ -+ bfd *dynobj; -+ asection *sgotplt; -+ asection *sdyn; -+ struct elf32_nios2_link_hash_table *htab; -+ -+ htab = elf32_nios2_hash_table (info); -+ -+ dynobj = elf_hash_table (info)->dynobj; -+ -+ sgotplt = htab->sgotplt; -+ BFD_ASSERT (sgotplt != NULL); -+ sdyn = bfd_get_section_by_name (dynobj, ".dynamic"); -+ -+ if (elf_hash_table (info)->dynamic_sections_created) -+ { -+ asection *splt; -+ Elf32_External_Dyn *dyncon, *dynconend; -+ -+ splt = htab->splt; -+ BFD_ASSERT (splt != NULL && sdyn != NULL); -+ -+ dyncon = (Elf32_External_Dyn *) sdyn->contents; -+ dynconend = (Elf32_External_Dyn *) (sdyn->contents + sdyn->size); -+ for (; dyncon < dynconend; dyncon++) -+ { -+ Elf_Internal_Dyn dyn; -+ const char *name; -+ asection *s; -+ -+ bfd_elf32_swap_dyn_in (dynobj, dyncon, &dyn); -+ -+ switch (dyn.d_tag) -+ { -+ default: -+ break; -+ -+ case DT_PLTGOT: -+ name = ".got"; -+ goto get_vma; -+ case DT_JMPREL: -+ name = ".rela.plt"; -+ get_vma: -+ s = bfd_get_section_by_name (output_bfd, name); -+ BFD_ASSERT (s != NULL); -+ dyn.d_un.d_ptr = s->vma; -+ bfd_elf32_swap_dyn_out (output_bfd, &dyn, dyncon); -+ break; -+ -+ case DT_PLTRELSZ: -+ s = bfd_get_section_by_name (output_bfd, ".rela.plt"); -+ BFD_ASSERT (s != NULL); -+ dyn.d_un.d_val = s->size; -+ bfd_elf32_swap_dyn_out (output_bfd, &dyn, dyncon); -+ break; -+ -+ case DT_RELASZ: -+ /* The procedure linkage table relocs (DT_JMPREL) should -+ not be included in the overall relocs (DT_RELA). -+ Therefore, we override the DT_RELASZ entry here to -+ make it not include the JMPREL relocs. Since the -+ linker script arranges for .rela.plt to follow all -+ other relocation sections, we don't have to worry -+ about changing the DT_RELA entry. */ -+ s = bfd_get_section_by_name (output_bfd, ".rela.plt"); -+ if (s != NULL) -+ dyn.d_un.d_val -= s->size; -+ bfd_elf32_swap_dyn_out (output_bfd, &dyn, dyncon); -+ break; -+ -+ case DT_NIOS2_GP: -+ s = bfd_get_section_by_name (output_bfd, ".got"); -+ BFD_ASSERT (s != NULL); -+ dyn.d_un.d_ptr = s->vma + 0x7ff0; -+ bfd_elf32_swap_dyn_out (output_bfd, &dyn, dyncon); -+ break; -+ } -+ } -+ -+ /* Fill in the first entry in the procedure linkage table. */ -+ if (splt->size > 0) -+ { -+ bfd_vma got_address = (sgotplt->output_section->vma + -+ sgotplt->output_offset); -+ if (info->shared) -+ { -+ bfd_vma corrected = got_address - (splt->output_section->vma + -+ splt->output_offset + 4); -+ nios2_elf32_install_data (splt, nios2_so_plt0_entry, 0, 6); -+ nios2_elf32_install_imm16 (splt, 4, hiadj (corrected)); -+ nios2_elf32_install_imm16 (splt, 12, (corrected & 0xffff) + 4); -+ nios2_elf32_install_imm16 (splt, 16, (corrected & 0xffff) + 8); -+ -+ elf_section_data (splt->output_section)->this_hdr.sh_entsize -+ = 24; -+ } -+ else -+ { -+ /* Divide by 4 here, not 3 because we already corrected for the -+ res_N branches. */ -+ bfd_vma res_size = (splt->size - 28) / 4; -+ bfd_vma res_start = (splt->output_section->vma + -+ splt->output_offset); -+ bfd_vma res_offset; -+ -+ for (res_offset = 0; res_offset < res_size; res_offset += 4) -+ bfd_put_32 (output_bfd, -+ 6 | ((res_size - (res_offset + 4)) << 6), -+ splt->contents + res_offset); -+ -+ nios2_elf32_install_data (splt, nios2_plt0_entry, res_size, 7); -+ nios2_elf32_install_imm16 (splt, res_size, hiadj (res_start)); -+ nios2_elf32_install_imm16 (splt, res_size + 4, -+ res_start & 0xffff); -+ nios2_elf32_install_imm16 (splt, res_size + 12, -+ hiadj (got_address)); -+ nios2_elf32_install_imm16 (splt, res_size + 16, -+ (got_address & 0xffff) + 4); -+ nios2_elf32_install_imm16 (splt, res_size + 20, -+ (got_address & 0xffff) + 8); -+ -+ elf_section_data (splt->output_section)->this_hdr.sh_entsize -+ = 28 + res_size; -+ } -+ } -+ } -+ /* Fill in the first three entries in the global offset table. */ -+ if (sgotplt->size > 0) -+ { -+ if (sdyn == NULL) -+ bfd_put_32 (output_bfd, (bfd_vma) 0, sgotplt->contents); -+ else -+ bfd_put_32 (output_bfd, -+ sdyn->output_section->vma + sdyn->output_offset, -+ sgotplt->contents); -+ bfd_put_32 (output_bfd, (bfd_vma) 0, sgotplt->contents + 4); -+ bfd_put_32 (output_bfd, (bfd_vma) 0, sgotplt->contents + 8); -+ } -+ -+ elf_section_data (sgotplt->output_section)->this_hdr.sh_entsize = 4; -+ -+ return TRUE; -+} -+ -+/* Adjust a symbol defined by a dynamic object and referenced by a -+ regular object. The current definition is in some section of the -+ dynamic object, but we're not including those sections. We have to -+ change the definition to something the rest of the link can -+ understand. */ -+ -+static bfd_boolean -+nios2_elf32_adjust_dynamic_symbol (struct bfd_link_info * info, -+ struct elf_link_hash_entry * h) -+{ -+ struct elf32_nios2_link_hash_table *htab; -+ bfd *dynobj; -+ asection *s; -+ unsigned align2; -+ -+ htab = elf32_nios2_hash_table (info); -+ dynobj = elf_hash_table (info)->dynobj; -+ -+ /* Make sure we know what is going on here. */ -+ BFD_ASSERT (dynobj != NULL -+ && (h->needs_plt -+ || h->u.weakdef != NULL -+ || (h->def_dynamic -+ && h->ref_regular -+ && !h->def_regular))); -+ -+ /* If this is a function, put it in the procedure linkage table. We -+ will fill in the contents of the procedure linkage table later, -+ when we know the address of the .got section. */ -+ if (h->type == STT_FUNC -+ || h->needs_plt) -+ { -+ if (h->plt.refcount <= 0 -+ || SYMBOL_CALLS_LOCAL (info, h) -+ || (ELF_ST_VISIBILITY (h->other) != STV_DEFAULT -+ && h->root.type == bfd_link_hash_undefweak)) -+ { -+ /* This case can occur if we saw a PLT reloc in an input -+ file, but the symbol was never referred to by a dynamic -+ object, or if all references were garbage collected. In -+ such a case, we don't actually need to build a procedure -+ linkage table, and we can just do a PCREL reloc instead. */ -+ h->plt.offset = (bfd_vma) -1; -+ h->needs_plt = 0; -+ } -+ -+ return TRUE; -+ } -+ -+ /* Reinitialize the plt offset now that it is not used as a reference -+ count any more. */ -+ h->plt.offset = (bfd_vma) -1; -+ -+ /* If this is a weak symbol, and there is a real definition, the -+ processor independent code will have arranged for us to see the -+ real definition first, and we can just use the same value. */ -+ if (h->u.weakdef != NULL) -+ { -+ BFD_ASSERT (h->u.weakdef->root.type == bfd_link_hash_defined -+ || h->u.weakdef->root.type == bfd_link_hash_defweak); -+ h->root.u.def.section = h->u.weakdef->root.u.def.section; -+ h->root.u.def.value = h->u.weakdef->root.u.def.value; -+ return TRUE; -+ } -+ -+ /* If there are no non-GOT references, we do not need a copy -+ relocation. */ -+ if (!h->non_got_ref) -+ return TRUE; -+ -+ /* This is a reference to a symbol defined by a dynamic object which -+ is not a function. */ -+ -+ /* If we are creating a shared library, we must presume that the -+ only references to the symbol are via the global offset table. -+ For such cases we need not do anything here; the relocations will -+ be handled correctly by relocate_section. */ -+ if (info->shared) -+ return TRUE; -+ -+ if (h->size == 0) -+ { -+ (*_bfd_error_handler) (_("dynamic variable `%s' is zero size"), -+ h->root.root.string); -+ return TRUE; -+ } -+ -+ /* We must allocate the symbol in our .dynbss section, which will -+ become part of the .bss section of the executable. There will be -+ an entry for this symbol in the .dynsym section. The dynamic -+ object will contain position independent code, so all references -+ from the dynamic object to this symbol will go through the global -+ offset table. The dynamic linker will use the .dynsym entry to -+ determine the address it must put in the global offset table, so -+ both the dynamic object and the regular object will refer to the -+ same memory location for the variable. */ -+ -+ s = htab->sdynbss; -+ BFD_ASSERT (s != NULL); -+ -+ /* We must generate a R_NIOS2_COPY reloc to tell the dynamic linker to -+ copy the initial value out of the dynamic object and into the -+ runtime process image. We need to remember the offset into the -+ .rela.bss section we are going to use. */ -+ if ((h->root.u.def.section->flags & SEC_ALLOC) != 0) -+ { -+ asection *srel; -+ -+ srel = htab->srelbss; -+ BFD_ASSERT (srel != NULL); -+ srel->size += sizeof (Elf32_External_Rela); -+ h->needs_copy = 1; -+ } -+ -+ align2 = bfd_log2 (h->size); -+ if (align2 > h->root.u.def.section->alignment_power) -+ align2 = h->root.u.def.section->alignment_power; -+ -+ /* align dynbss */ -+ s->size = BFD_ALIGN (s->size, (bfd_size_type)1 << align2); -+ if (align2 > bfd_get_section_alignment (dynobj, s) -+ && !bfd_set_section_alignment (dynobj, s, align2)) -+ return FALSE; -+ -+ /* Define the symbol as being at this point in the section. */ -+ h->root.u.def.section = s; -+ h->root.u.def.value = s->size; -+ -+ /* Increment the section size to make room for the symbol. */ -+ s->size += h->size; -+ -+ return TRUE; -+} -+ -+static bfd_boolean -+adjust_dynrelocs (struct elf_link_hash_entry *h, PTR inf) -+{ -+ struct bfd_link_info *info; -+ struct elf32_nios2_link_hash_table *htab; -+ -+ if (h->root.type == bfd_link_hash_indirect) -+ return TRUE; -+ -+ if (h->root.type == bfd_link_hash_warning) -+ /* When warning symbols are created, they **replace** the "real" -+ entry in the hash table, thus we never get to see the real -+ symbol in a hash traversal. So look at it now. */ -+ h = (struct elf_link_hash_entry *) h->root.u.i.link; -+ -+ info = (struct bfd_link_info *) inf; -+ htab = elf32_nios2_hash_table (info); -+ -+ if (h->plt.offset != (bfd_vma)-1) -+ h->plt.offset += htab->res_n_size; -+ if (htab->splt == h->root.u.def.section) -+ h->root.u.def.value += htab->res_n_size; -+ -+ return TRUE; -+} -+ -+/* Allocate space in .plt, .got and associated reloc sections for -+ dynamic relocs. */ -+ -+static bfd_boolean -+allocate_dynrelocs (struct elf_link_hash_entry *h, PTR inf) -+{ -+ struct bfd_link_info *info; -+ struct elf32_nios2_link_hash_table *htab; -+ struct elf32_nios2_link_hash_entry *eh; -+ struct elf32_nios2_dyn_relocs *p; -+ int use_plt; -+ -+ if (h->root.type == bfd_link_hash_indirect) -+ return TRUE; -+ -+ if (h->root.type == bfd_link_hash_warning) -+ /* When warning symbols are created, they **replace** the "real" -+ entry in the hash table, thus we never get to see the real -+ symbol in a hash traversal. So look at it now. */ -+ h = (struct elf_link_hash_entry *) h->root.u.i.link; -+ -+ info = (struct bfd_link_info *) inf; -+ htab = elf32_nios2_hash_table (info); -+ -+ if (htab->root.dynamic_sections_created -+ && h->plt.refcount > 0) -+ { -+ /* Make sure this symbol is output as a dynamic symbol. -+ Undefined weak syms won't yet be marked as dynamic. */ -+ if (h->dynindx == -1 -+ && !h->forced_local) -+ { -+ if (! bfd_elf_link_record_dynamic_symbol (info, h)) -+ return FALSE; -+ } -+ -+ if (WILL_CALL_FINISH_DYNAMIC_SYMBOL (1, info->shared, h)) -+ { -+ asection *s = htab->splt; -+ -+ /* Allocate room for the header. */ -+ if (s->size == 0) -+ { -+ if (info->shared) -+ s->size = 24; -+ else -+ s->size = 28; -+ } -+ -+ h->plt.offset = s->size; -+ -+ /* If this symbol is not defined in a regular file, and we are -+ not generating a shared library, then set the symbol to this -+ location in the .plt. This is required to make function -+ pointers compare as equal between the normal executable and -+ the shared library. */ -+ if (! info->shared -+ && !h->def_regular) -+ { -+ h->root.u.def.section = s; -+ h->root.u.def.value = h->plt.offset; -+ } -+ -+ /* Make room for this entry. */ -+ s->size += 12; -+ -+ /* We also need to make an entry in the .rela.plt section. */ -+ htab->srelplt->size += sizeof (Elf32_External_Rela); -+ -+ /* And the .got.plt section. */ -+ htab->sgotplt->size += 4; -+ } -+ else -+ { -+ h->plt.offset = (bfd_vma) -1; -+ h->needs_plt = 0; -+ } -+ } -+ else -+ { -+ h->plt.offset = (bfd_vma) -1; -+ h->needs_plt = 0; -+ } -+ -+ eh = (struct elf32_nios2_link_hash_entry *) h; -+ use_plt = (eh->got_types_used == CALL16_USED && -+ h->plt.offset != (bfd_vma) -1); -+ -+ if (h->got.refcount > 0) -+ { -+ asection *s; -+ bfd_boolean dyn; -+ int tls_type = eh->tls_type; -+ int indx; -+ -+ /* Make sure this symbol is output as a dynamic symbol. -+ Undefined weak syms won't yet be marked as dynamic. */ -+ if (h->dynindx == -1 -+ && !h->forced_local) -+ { -+ if (! bfd_elf_link_record_dynamic_symbol (info, h)) -+ return FALSE; -+ } -+ -+ s = htab->sgot; -+ h->got.offset = s->size; -+ -+ if (tls_type == GOT_UNKNOWN) -+ abort (); -+ -+ if (tls_type == GOT_NORMAL) -+ /* Non-TLS symbols need one GOT slot. */ -+ s->size += 4; -+ else -+ { -+ if (tls_type & GOT_TLS_GD) -+ /* R_NIOS2_TLS_GD16 needs 2 consecutive GOT slots. */ -+ s->size += 8; -+ if (tls_type & GOT_TLS_IE) -+ /* R_NIOS2_TLS_IE16 needs one GOT slot. */ -+ s->size += 4; -+ } -+ -+ dyn = htab->root.dynamic_sections_created; -+ -+ indx = 0; -+ if (WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, info->shared, h) -+ && (!info->shared -+ || !SYMBOL_REFERENCES_LOCAL (info, h))) -+ indx = h->dynindx; -+ -+ if (tls_type != GOT_NORMAL -+ && (info->shared || indx != 0) -+ && (ELF_ST_VISIBILITY (h->other) == STV_DEFAULT -+ || h->root.type != bfd_link_hash_undefweak)) -+ { -+ if (tls_type & GOT_TLS_IE) -+ htab->srelgot->size += sizeof (Elf32_External_Rela); -+ -+ if (tls_type & GOT_TLS_GD) -+ htab->srelgot->size += sizeof (Elf32_External_Rela); -+ -+ if ((tls_type & GOT_TLS_GD) && indx != 0) -+ htab->srelgot->size += sizeof (Elf32_External_Rela); -+ } -+ else if ((ELF_ST_VISIBILITY (h->other) == STV_DEFAULT -+ || h->root.type != bfd_link_hash_undefweak) -+ && !use_plt && (info->shared -+ || WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, 0, h))) -+ htab->srelgot->size += sizeof (Elf32_External_Rela); -+ } -+ else -+ h->got.offset = (bfd_vma) -1; -+ -+ if (eh->dyn_relocs == NULL) -+ return TRUE; -+ -+ /* In the shared -Bsymbolic case, discard space allocated for -+ dynamic pc-relative relocs against symbols which turn out to be -+ defined in regular objects. For the normal shared case, discard -+ space for pc-relative relocs that have become local due to symbol -+ visibility changes. */ -+ -+ if (info->shared) -+ { -+ if (h->def_regular -+ && (h->forced_local -+ || info->symbolic)) -+ { -+ struct elf32_nios2_dyn_relocs **pp; -+ -+ for (pp = &eh->dyn_relocs; (p = *pp) != NULL; ) -+ { -+ p->count -= p->pc_count; -+ p->pc_count = 0; -+ if (p->count == 0) -+ *pp = p->next; -+ else -+ pp = &p->next; -+ } -+ } -+ -+ /* Also discard relocs on undefined weak syms with non-default -+ visibility. */ -+ if (eh->dyn_relocs != NULL -+ && h->root.type == bfd_link_hash_undefweak) -+ { -+ if (ELF_ST_VISIBILITY (h->other) != STV_DEFAULT) -+ eh->dyn_relocs = NULL; -+ -+ /* Make sure undefined weak symbols are output as a dynamic -+ symbol in PIEs. */ -+ else if (h->dynindx == -1 -+ && !h->forced_local) -+ { -+ if (! bfd_elf_link_record_dynamic_symbol (info, h)) -+ return FALSE; -+ } -+ } -+ } -+ else -+ { -+ /* For the non-shared case, discard space for relocs against -+ symbols which turn out to need copy relocs or are not -+ dynamic. */ -+ -+ if (!h->non_got_ref -+ && ((h->def_dynamic -+ && !h->def_regular) -+ || (htab->root.dynamic_sections_created -+ && (h->root.type == bfd_link_hash_undefweak -+ || h->root.type == bfd_link_hash_undefined)))) -+ { -+ /* Make sure this symbol is output as a dynamic symbol. -+ Undefined weak syms won't yet be marked as dynamic. */ -+ if (h->dynindx == -1 -+ && !h->forced_local) -+ { -+ if (! bfd_elf_link_record_dynamic_symbol (info, h)) -+ return FALSE; -+ } -+ -+ /* If that succeeded, we know we'll be keeping all the -+ relocs. */ -+ if (h->dynindx != -1) -+ goto keep; -+ } -+ -+ eh->dyn_relocs = NULL; -+ -+ keep: ; -+ } -+ -+ /* Finally, allocate space. */ -+ for (p = eh->dyn_relocs; p != NULL; p = p->next) -+ { -+ asection *sreloc = elf_section_data (p->sec)->sreloc; -+ sreloc->size += p->count * sizeof (Elf32_External_Rela); -+ } -+ -+ return TRUE; -+} -+ -+/* Set the sizes of the dynamic sections. */ -+ -+static bfd_boolean -+nios2_elf32_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED, -+ struct bfd_link_info *info) -+{ -+ bfd *dynobj; -+ asection *s; -+ bfd_boolean plt; -+ bfd_boolean got; -+ bfd_boolean relocs; -+ bfd *ibfd; -+ struct elf32_nios2_link_hash_table *htab; -+ -+ htab = elf32_nios2_hash_table (info); -+ dynobj = elf_hash_table (info)->dynobj; -+ BFD_ASSERT (dynobj != NULL); -+ -+ htab->res_n_size = 0; -+ if (elf_hash_table (info)->dynamic_sections_created) -+ { -+ /* Set the contents of the .interp section to the interpreter. */ -+ if (info->executable) -+ { -+ s = bfd_get_section_by_name (dynobj, ".interp"); -+ BFD_ASSERT (s != NULL); -+ s->size = sizeof ELF_DYNAMIC_INTERPRETER; -+ s->contents = (unsigned char *) ELF_DYNAMIC_INTERPRETER; -+ } -+ } -+ else -+ { -+ /* We may have created entries in the .rela.got section. -+ However, if we are not creating the dynamic sections, we will -+ not actually use these entries. Reset the size of .rela.got, -+ which will cause it to get stripped from the output file -+ below. */ -+ s = htab->srelgot; -+ if (s != NULL) -+ s->size = 0; -+ } -+ -+ /* Set up .got offsets for local syms, and space for local dynamic -+ relocs. */ -+ for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link_next) -+ { -+ bfd_signed_vma *local_got; -+ bfd_signed_vma *end_local_got; -+ char *local_tls_type; -+ bfd_size_type locsymcount; -+ Elf_Internal_Shdr *symtab_hdr; -+ asection *srel; -+ -+ if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour) -+ continue; -+ -+ for (s = ibfd->sections; s != NULL; s = s->next) -+ { -+ struct elf32_nios2_dyn_relocs *p; -+ -+ for (p = elf_section_data (s)->local_dynrel; p != NULL; p = p->next) -+ { -+ if (!bfd_is_abs_section (p->sec) -+ && bfd_is_abs_section (p->sec->output_section)) -+ { -+ /* Input section has been discarded, either because -+ it is a copy of a linkonce section or due to -+ linker script /DISCARD/, so we'll be discarding -+ the relocs too. */ -+ } -+ else if (p->count != 0) -+ { -+ srel = elf_section_data (p->sec)->sreloc; -+ srel->size += p->count * sizeof (Elf32_External_Rela); -+ if ((p->sec->output_section->flags & SEC_READONLY) != 0) -+ info->flags |= DF_TEXTREL; -+ } -+ } -+ } -+ -+ local_got = elf_local_got_refcounts (ibfd); -+ if (!local_got) -+ continue; -+ -+ symtab_hdr = &elf_tdata (ibfd)->symtab_hdr; -+ locsymcount = symtab_hdr->sh_info; -+ end_local_got = local_got + locsymcount; -+ local_tls_type = elf32_nios2_local_got_tls_type (ibfd); -+ s = htab->sgot; -+ srel = htab->srelgot; -+ for (; local_got < end_local_got; ++local_got, ++local_tls_type) -+ { -+ if (*local_got > 0) -+ { -+ *local_got = s->size; -+ if (*local_tls_type & GOT_TLS_GD) -+ /* TLS_GD relocs need an 8-byte structure in the GOT. */ -+ s->size += 8; -+ if (*local_tls_type & GOT_TLS_IE) -+ s->size += 4; -+ if (*local_tls_type == GOT_NORMAL) -+ s->size += 4; -+ -+ if (info->shared || *local_tls_type == GOT_TLS_GD) -+ srel->size += sizeof (Elf32_External_Rela); -+ } -+ else -+ *local_got = (bfd_vma) -1; -+ } -+ } -+ -+ if (htab->tls_ldm_got.refcount > 0) -+ { -+ /* Allocate two GOT entries and one dynamic relocation (if necessary) -+ for R_NIOS2_TLS_LDM16 relocations. */ -+ htab->tls_ldm_got.offset = htab->sgot->size; -+ htab->sgot->size += 8; -+ if (info->shared) -+ htab->srelgot->size += sizeof (Elf32_External_Rela); -+ } -+ else -+ htab->tls_ldm_got.offset = -1; -+ -+ /* Allocate global sym .plt and .got entries, and space for global -+ sym dynamic relocs. */ -+ elf_link_hash_traverse (& htab->root, allocate_dynrelocs, info); -+ -+ /* The check_relocs and adjust_dynamic_symbol entry points have -+ determined the sizes of the various dynamic sections. Allocate -+ memory for them. */ -+ plt = FALSE; -+ got = FALSE; -+ relocs = FALSE; -+ for (s = dynobj->sections; s != NULL; s = s->next) -+ { -+ const char *name; -+ -+ if ((s->flags & SEC_LINKER_CREATED) == 0) -+ continue; -+ -+ /* It's OK to base decisions on the section name, because none -+ of the dynobj section names depend upon the input files. */ -+ name = bfd_get_section_name (dynobj, s); -+ -+ if (strcmp (name, ".plt") == 0) -+ { -+ /* Remember whether there is a PLT. */ -+ plt = s->size != 0; -+ -+ /* Correct for the number of res_N branches. */ -+ if (plt && !info->shared) -+ { -+ htab->res_n_size = (s->size-28) / 3; -+ s->size += htab->res_n_size; -+ } -+ } -+ else if (CONST_STRNEQ (name, ".rela")) -+ { -+ if (s->size != 0) -+ { -+ relocs = TRUE; -+ -+ /* We use the reloc_count field as a counter if we need -+ to copy relocs into the output file. */ -+ s->reloc_count = 0; -+ } -+ } -+ else if (CONST_STRNEQ (name, ".got")) -+ got = s->size != 0; -+ else if (strcmp (name, ".dynbss") != 0) -+ { -+ /* It's not one of our sections, so don't allocate space. */ -+ continue; -+ } -+ -+ if (s->size == 0) -+ { -+ /* If we don't need this section, strip it from the -+ output file. This is mostly to handle .rela.bss and -+ .rela.plt. We must create both sections in -+ create_dynamic_sections, because they must be created -+ before the linker maps input sections to output -+ sections. The linker does that before -+ adjust_dynamic_symbol is called, and it is that -+ function which decides whether anything needs to go -+ into these sections. */ -+ s->flags |= SEC_EXCLUDE; -+ continue; -+ } -+ -+ if ((s->flags & SEC_HAS_CONTENTS) == 0) -+ continue; -+ -+ /* Allocate memory for the section contents. */ -+ /* FIXME: This should be a call to bfd_alloc not bfd_zalloc. -+ Unused entries should be reclaimed before the section's contents -+ are written out, but at the moment this does not happen. Thus in -+ order to prevent writing out garbage, we initialise the section's -+ contents to zero. */ -+ s->contents = (bfd_byte *) bfd_zalloc (dynobj, s->size); -+ if (s->contents == NULL) -+ return FALSE; -+ } -+ -+ /* Adjust dynamic symbols that point to the plt to account for the -+ now-known number of resN slots. */ -+ if (htab->res_n_size) -+ elf_link_hash_traverse (& htab->root, adjust_dynrelocs, info); -+ -+ if (elf_hash_table (info)->dynamic_sections_created) -+ { -+ /* Add some entries to the .dynamic section. We fill in the -+ values later, in elf_nios2_finish_dynamic_sections, but we -+ must add the entries now so that we get the correct size for -+ the .dynamic section. The DT_DEBUG entry is filled in by the -+ dynamic linker and used by the debugger. */ -+#define add_dynamic_entry(TAG, VAL) \ -+ _bfd_elf_add_dynamic_entry (info, TAG, VAL) -+ -+ if (!info->shared) -+ { -+ if (!add_dynamic_entry (DT_DEBUG, 0)) -+ return FALSE; -+ } -+ -+ if (got) -+ if (!add_dynamic_entry (DT_PLTGOT, 0)) -+ return FALSE; -+ -+ if (plt) -+ if (!add_dynamic_entry (DT_PLTRELSZ, 0) -+ || !add_dynamic_entry (DT_PLTREL, DT_RELA) -+ || !add_dynamic_entry (DT_JMPREL, 0)) -+ return FALSE; -+ -+ if (relocs) -+ { -+ if (!add_dynamic_entry (DT_RELA, 0) -+ || !add_dynamic_entry (DT_RELASZ, 0) -+ || !add_dynamic_entry (DT_RELAENT, sizeof (Elf32_External_Rela))) -+ return FALSE; -+ } -+ -+ if (!info->shared) -+ { -+ if (!add_dynamic_entry (DT_NIOS2_GP, 0)) -+ return FALSE; -+ } -+ -+ if ((info->flags & DF_TEXTREL) != 0) -+ { -+ if (!add_dynamic_entry (DT_TEXTREL, 0)) -+ return FALSE; -+ } -+ } -+#undef add_dynamic_entry -+ -+ return TRUE; -+} -+ -+/* Create a Nios II elf linker hash table. */ -+ -+static struct bfd_link_hash_table * -+nios2_elf32_link_hash_table_create (bfd *abfd) -+{ -+ struct elf32_nios2_link_hash_table *ret; -+ bfd_size_type amt = sizeof (struct elf32_nios2_link_hash_table); -+ -+ ret = bfd_malloc (amt); -+ if (ret == NULL) -+ return NULL; -+ -+ if (!_bfd_elf_link_hash_table_init (& ret->root, abfd, -+ link_hash_newfunc, -+ sizeof (struct -+ elf32_nios2_link_hash_entry))) -+ { -+ free (ret); -+ return NULL; -+ } -+ -+ ret->sgot = NULL; -+ ret->sgotplt = NULL; -+ ret->srelgot = NULL; -+ ret->splt = NULL; -+ ret->srelplt = NULL; -+ ret->sdynbss = NULL; -+ ret->srelbss = NULL; -+ ret->sbss = NULL; -+ ret->tls_ldm_got.refcount = 0; -+ ret->sym_sec.abfd = NULL; -+ return &ret->root.root; -+} -+ -+static enum elf_reloc_type_class -+nios2_elf32_reloc_type_class (const Elf_Internal_Rela *rela) -+{ -+ switch ((int) ELF32_R_TYPE (rela->r_info)) -+ { -+ case R_NIOS2_RELATIVE: -+ return reloc_class_relative; -+ case R_NIOS2_JUMP_SLOT: -+ return reloc_class_plt; -+ case R_NIOS2_COPY: -+ return reloc_class_copy; -+ default: -+ return reloc_class_normal; -+ } -+} -+ -+/* Return 1 if target is one of ours. */ -+ -+static bfd_boolean -+is_nios2_elf_target (const struct bfd_target *targ) -+{ -+ return (targ == &bfd_elf32_littlenios2_vec -+ || targ == &bfd_elf32_bignios2_vec); -+} -+ -+/* Hook called by the linker routine which adds symbols from an object -+ file. We use it to put .comm items in .sbss, and not .bss. */ -+ -+static bfd_boolean -+nios2_elf_add_symbol_hook (bfd *abfd, -+ struct bfd_link_info *info, -+ Elf_Internal_Sym *sym, -+ const char **namep ATTRIBUTE_UNUSED, -+ flagword *flagsp ATTRIBUTE_UNUSED, -+ asection **secp, -+ bfd_vma *valp) -+{ -+ bfd *dynobj; -+ -+ if (sym->st_shndx == SHN_COMMON -+ && !info->relocatable -+ && is_nios2_elf (info->output_bfd) -+ && sym->st_size <= elf_gp_size (abfd)) -+ { -+ /* Common symbols less than or equal to -G nn bytes are automatically -+ put into .sbss. */ -+ struct elf32_nios2_link_hash_table *htab; -+ -+ htab = elf32_nios2_hash_table (info); -+ if (htab->sbss == NULL) -+ { -+ flagword flags = SEC_IS_COMMON | SEC_LINKER_CREATED; -+ -+ dynobj = elf_hash_table (info)->dynobj; -+ if (!dynobj) -+ dynobj = abfd; -+ -+ htab->sbss = bfd_make_section_anyway_with_flags (dynobj, ".sbss", -+ flags); -+ if (htab->sbss == NULL) -+ return FALSE; -+ } -+ -+ *secp = htab->sbss; -+ *valp = sym->st_size; -+ } -+ -+ if (ELF_ST_TYPE (sym->st_info) == STT_GNU_IFUNC) -+ elf_tdata (info->output_bfd)->has_ifunc_symbols = TRUE; -+ -+ return TRUE; -+} -+ -+/* Decide whether to attempt to turn absptr or lsda encodings in -+ shared libraries into pcrel within the given input section. */ -+ -+static bfd_boolean -+nios2_elf32_can_make_relative_eh_frame(bfd *input_bfd ATTRIBUTE_UNUSED, -+ struct bfd_link_info *info -+ ATTRIBUTE_UNUSED, -+ asection *eh_frame_section -+ ATTRIBUTE_UNUSED) -+{ -+ /* We can't use PC-relative encodings in the .eh_frame section. */ -+ return FALSE; -+} -+ -+#define ELF_ARCH bfd_arch_nios2 -+#define ELF_MACHINE_CODE EM_ALTERA_NIOS2 -+ -+/* The Nios II MMU uses a 4K page size. */ -+ -+#define ELF_MAXPAGESIZE 0x1000 -+ -+#define bfd_elf32_bfd_link_hash_table_create \ -+ nios2_elf32_link_hash_table_create -+ -+/* Relocation table lookup macros. */ -+ -+#define bfd_elf32_bfd_reloc_type_lookup nios2_elf32_bfd_reloc_type_lookup -+#define bfd_elf32_bfd_reloc_name_lookup nios2_elf32_bfd_reloc_name_lookup -+ -+/* JUMP_TABLE_LINK macros. */ -+ -+#define bfd_elf32_bfd_relax_section nios2_elf32_relax_section -+ -+/* elf_info_to_howto (using RELA relocations). */ -+ -+#define elf_info_to_howto nios2_elf32_info_to_howto -+ -+/* elf backend functions. */ -+ -+#define elf_backend_can_gc_sections 1 -+#define elf_backend_can_refcount 1 -+#define elf_backend_plt_readonly 1 -+#define elf_backend_want_got_plt 1 -+ -+#define elf_backend_relocate_section nios2_elf32_relocate_section -+#define elf_backend_section_from_shdr nios2_elf32_section_from_shdr -+#define elf_backend_section_flags nios2_elf32_section_flags -+#define elf_backend_fake_sections nios2_elf32_fake_sections -+#define elf_backend_check_relocs nios2_elf32_check_relocs -+ -+#define elf_backend_gc_mark_hook nios2_elf32_gc_mark_hook -+#define elf_backend_gc_sweep_hook nios2_elf32_gc_sweep_hook -+#define elf_backend_create_dynamic_sections \ -+ nios2_elf32_create_dynamic_sections -+#define elf_backend_finish_dynamic_symbol nios2_elf32_finish_dynamic_symbol -+#define elf_backend_finish_dynamic_sections \ -+ nios2_elf32_finish_dynamic_sections -+#define elf_backend_adjust_dynamic_symbol nios2_elf32_adjust_dynamic_symbol -+#define elf_backend_reloc_type_class nios2_elf32_reloc_type_class -+#define elf_backend_size_dynamic_sections nios2_elf32_size_dynamic_sections -+#define elf_backend_add_symbol_hook nios2_elf_add_symbol_hook -+#define elf_backend_copy_indirect_symbol nios2_elf32_copy_indirect_symbol -+ -+#define elf_backend_grok_prstatus nios2_grok_prstatus -+#define elf_backend_grok_psinfo nios2_grok_psinfo -+ -+#undef elf_backend_can_make_relative_eh_frame -+#define elf_backend_can_make_relative_eh_frame \ -+ nios2_elf32_can_make_relative_eh_frame -+ -+/* Support for SGI-ish mips targets. */ -+#define TARGET_LITTLE_SYM bfd_elf32_littlenios2_vec -+#define TARGET_LITTLE_NAME "elf32-littlenios2" -+#define TARGET_BIG_SYM bfd_elf32_bignios2_vec -+#define TARGET_BIG_NAME "elf32-bignios2" -+ -+#define elf_backend_got_header_size 12 -+ -+#include "elf32-target.h" -Index: binutils-2.20.1/gas/config/tc-nios2.c -=================================================================== ---- /dev/null -+++ binutils-2.20.1/gas/config/tc-nios2.c -@@ -0,0 +1,3361 @@ -+/* NOT ASSIGNED TO FSF. COPYRIGHT ALTERA. */ -+/* tc-nios2.c -- assemble code for a New Jersey processor. -+ -+ Copyright (C) 2003 -+ by Nigel Gray (ngray@altera.com). -+ -+ -+ This file is part of GAS. -+ -+ GAS is free software; you can redistribute it and/or modify -+ it under the terms of the GNU General Public License as published by -+ the Free Software Foundation; either version 2, or (at your option) -+ any later version. -+ -+ GAS is distributed in the hope that it will be useful, -+ but WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ GNU General Public License for more details. -+ -+ You should have received a copy of the GNU General Public License -+ along with GAS; see the file COPYING. If not, write to the Free -+ Software Foundation, 59 Temple Place - Suite 330, Boston, MA -+ 02111-1307, USA. */ -+ -+ -+#include -+#include -+#include -+#include -+#include "as.h" -+#include "opcode/nios2.h" -+#include "elf/nios2.h" -+#include "tc-nios2.h" -+#include "bfd.h" -+#include "dwarf2dbg.h" -+#include "subsegs.h" -+#include "safe-ctype.h" -+#include "dw2gencfi.h" -+ -+/* We can choose our endianness at run-time, regardless of configuration. */ -+extern int target_big_endian; -+ -+#ifndef OBJ_ELF -+ /* We are not supporting any other target -+ so we throw a compile time error. */ -+OBJ_ELF not defined -+#endif -+ typedef enum -+{ -+ relax_section = 0, -+ relax_none, -+ relax_all -+} -+relax_optionT; -+ -+ -+/* Struct contains all assembler options set with .set. */ -+struct -+{ -+ /* .set noat -> noat = 1 allows assembly code to use at without warning -+ and macro expansions will generate a warning. -+ .set at -> noat = 0, assembly code using at will warn -+ macro expansions will not generate warnings. */ -+ bfd_boolean noat; -+ -+ /* .set nobreak -> nobreak = 1 allows assembly code to use ba,bt without -+ warning. -+ .set break -> nobreak = 0, assembly code using ba,bt will warn. */ -+ bfd_boolean nobreak; -+ -+ /* .cmd line option -relax-all allows all branches and calls to be replaced -+ with longer versions. -+ -no-relax inhibits branch/call conversion. -+ default value is relax_section, which relaxes branches within a section. -+ */ -+ relax_optionT relax; -+ -+} -+nios2_as_options = -+{ -+FALSE, FALSE, relax_section}; -+ -+ -+typedef struct nios2_insn_reloc -+{ -+ /* Any expression in the instruction is parsed into -+ this field which is passed to fix_new_exp() to -+ generate a fixup. */ -+ expressionS reloc_expression; -+ -+ /* The type of the relocation to be applied. */ -+ bfd_reloc_code_real_type reloc_type; -+ -+ /* pc relative. */ -+ unsigned int reloc_pcrel; -+ -+ /* The next relocation to be applied to the instruction. */ -+ struct nios2_insn_reloc *reloc_next; -+} -+nios2_insn_relocS; -+ -+ -+/* ------------------------------------------------------------------ -+ This struct is used by the functions in tc-nios2.c to assemble an -+ instruction -+ ------------------------------------------------------------------*/ -+ -+typedef struct nios2_insn_info -+{ -+ /* Assembled instruction. */ -+ unsigned long insn_code; -+ /* Pointer to the relevant bit of the opcode table. */ -+ const struct nios2_opcode *insn_nios2_opcode; -+ /* After parsing ptrs to the tokens in the instruction fill this array -+ it is terminated with a null pointer (hence the first +1). -+ The second +1 is because in some parts of the code the opcode -+ is not counted as a token, but still placed in this array. */ -+ const char *insn_tokens[NIOS2_MAX_INSN_TOKENS + 1 + 1]; -+ -+ /* This holds information used to generate fixups -+ and eventually relocations if it is not null. */ -+ nios2_insn_relocS *insn_reloc; -+} -+nios2_insn_infoS; -+ -+ -+/* This struct associates an argument assemble function with -+ an argument syntax string. Used by the assembler to find out -+ how to parse and assemble a set of instruction operands and -+ return the instruction field values. */ -+ -+typedef struct nios2_arg_info -+{ -+ const char *args; -+ void (*assemble_args_func) (nios2_insn_infoS * insn_info); -+} -+nios2_arg_infoS; -+ -+/* This struct is used to convert New Jersey pseudo-ops into the -+ corresponding real op. */ -+typedef struct nios2_ps_insn_info -+{ -+ const char *pseudo_insn; -+ const char *insn; -+ const char *arg_modifier; -+ void (*arg_modifer_func) (const char *arg, char **parsedArgs, int numArg, -+ int startIndex); -+ int num; -+ int index; -+} -+nios2_ps_insn_infoS; -+ -+ -+ -+/* Function prototypes. */ -+static void NIOS2_CHECK_ASSEMBLY (unsigned int opcode, -+ const char *exp_opcode); -+static void s_nios2_sdata (int); -+void nios2_assemble_args_dst (nios2_insn_infoS * insn_info); -+void nios2_assemble_args_tsi (nios2_insn_infoS * insn_info); -+void nios2_assemble_args_tsu (nios2_insn_infoS * insn_info); -+void nios2_assemble_args_o (nios2_insn_infoS * insn_info); -+void nios2_assemble_args_m (nios2_insn_infoS * insn_info); -+void nios2_assemble_args_s (nios2_insn_infoS * insn_info); -+void nios2_assemble_args_tis (nios2_insn_infoS * insn_info); -+void nios2_assemble_args_dc (nios2_insn_infoS * insn_info); -+void nios2_assemble_args_cs (nios2_insn_infoS * insn_info); -+void nios2_assemble_args_ldst (nios2_insn_infoS * insn_info); -+void nios2_assemble_args_none (nios2_insn_infoS * insn_info); -+void nios2_assemble_args_dsj (nios2_insn_infoS * insn_info); -+void nios2_assemble_args_is (nios2_insn_infoS * insn_info); -+void nios2_assemble_args_sto (nios2_insn_infoS * insn_info); -+void nios2_assemble_args_d (nios2_insn_infoS * insn_info); -+void nios2_assemble_args_b (nios2_insn_infoS * insn_info); -+ -+nios2_insn_relocS *nios2_insn_reloc_new (bfd_reloc_code_real_type reloc_type, -+ unsigned int pcrel); -+void nios2_insn_reloc_destroy (nios2_insn_relocS * reloc); -+unsigned long nios2_assemble_expression (const char *exprstr, -+ nios2_insn_infoS * insn, -+ nios2_insn_relocS * prev_reloc, -+ bfd_reloc_code_real_type reloc_type, -+ unsigned int pcrel); -+char *nios2_consume_separator (char *argStr, const char *separator); -+char *nios2_consume_arg (char *argStr, const char *argType); -+void nios2_parse_args (char *argStr, const char *parseStr, char **parsedArgs); -+ -+void nios2_modify_arg (const char *modifier, char **parsedArgs, int unused, -+ int index); -+void nios2_append_arg (const char *append, char **parsedArgs, int numAppend, -+ int startIndex); -+void nios2_insert_arg (const char *insert, char **parsedArgs, int numInsert, -+ int startIndex); -+void nios2_swap_args (const char *unused, char **parsedArgs, int index_1, -+ int index_2); -+void nios2_negate_arg (const char *modifier ATTRIBUTE_UNUSED, -+ char **parsedArgs, int unused ATTRIBUTE_UNUSED, -+ int index); -+void nios2_translate_pseudo_insn (nios2_insn_infoS * insn); -+void md_apply_fix (fixS * fixP, valueT * valP, segT seg ATTRIBUTE_UNUSED); -+valueT md_chars_to_number (char *buf, int n); -+void md_number_to_imm (char *buf, valueT val, int n); -+void md_number_to_disp (char *buf, valueT val, int n); -+void md_number_to_field (char *buf, valueT val, int n); -+static void nios2_align (int log_size, const char *pfill, symbolS * sym); -+static void s_nios2_ucons (int nbytes); -+static void s_nios2_set (int equiv); -+static void s_nios2_align (int ignore); -+static void s_nios2_text (int); -+static void s_nios2_data (int); -+static void s_nios2_section (int); -+static bfd_boolean nios2_coproc_reg (const char *reg_name); -+static void output_insn (void); -+static void output_ubranch (void); -+static void output_cbranch (void); -+static void output_call (void); -+static void output_movia (void); -+static void output_andi (void); -+static void output_addi (void); -+static void output_ori (void); -+static void output_xori (void); -+static int can_evaluate_expr (void); -+static int get_expr_value (void); -+ -+ -+bfd_boolean nios2_check_overflow (valueT fixup, reloc_howto_type * howto); -+ -+/* The known current alignment of the current section. */ -+static int nios2_current_align; -+static segT nios2_current_align_seg; -+ -+/* The last seen label in the current section. This is used to auto-align -+ labels preceeding instructions. */ -+static symbolS *nios2_last_label; -+ -+ -+static int nios2_auto_align_on = 1; -+ -+/* This array holds the chars that always start a comment. If the -+ pre-processor is disabled, these aren't very useful. */ -+const char comment_chars[] = "#"; -+ -+/* This array holds the chars that only start a comment at the beginning of -+ a line. If the line seems to have the form '# 123 filename' -+ .line and .file directives will appear in the pre-processed output. */ -+/* Note that input_file.c hand checks for '#' at the beginning of the -+ first line of the input file. This is because the compiler outputs -+ #NO_APP at the beginning of its output. */ -+/* Also note that C style comments are always supported. */ -+const char line_comment_chars[] = "#"; -+ -+/* This array holds machine specific line separator characters. */ -+const char line_separator_chars[] = ";"; -+ -+/* Chars that can be used to separate mant from exp in floating point nums. */ -+const char EXP_CHARS[] = "eE"; -+ -+/* Chars that mean this number is a floating point constant. */ -+/* As in 0f12.456 */ -+/* or 0d1.2345e12 */ -+const char FLT_CHARS[] = "rRsSfFdDxXpP"; -+ -+/* Also be aware that MAXIMUM_NUMBER_OF_CHARS_FOR_FLOAT may have to be -+ changed in read.c. Ideally it shouldn't have to know about it at all, -+ but nothing is ideal around here. */ -+ -+/* Handle of the OPCODE hash table. */ -+static struct hash_control *nios2_opcode_hash = NULL; -+ -+/* Handle of the Register hash table. */ -+static struct hash_control *nios2_reg_hash = NULL; -+ -+/* Handle of the parse args hash table. */ -+static struct hash_control *nios2_arg_hash = NULL; -+ -+/* Pseudo-op hash table. */ -+static struct hash_control *nios2_ps_hash = NULL; -+ -+#ifdef OBJ_ELF -+/* Pre-defined "_GLOBAL_OFFSET_TABLE_" */ -+symbolS * GOT_symbol; -+#endif -+ -+#define streq(a, b) (strcmp (a, b) == 0) -+ -+/* Mode of the assembler. */ -+typedef enum -+{ -+ NIOS2_MODE_ASSEMBLE, /* Ordinary operation. */ -+ NIOS2_MODE_TEST /* Hidden mode used for self testing. */ -+} -+NIOS2_MODE; -+ -+static NIOS2_MODE nios2_mode = NIOS2_MODE_ASSEMBLE; -+ -+/* This function is used to in self-checking mode -+ to check the assembled instruction -+ opcode should be the assembled opcode, and exp_opcode -+ the parsed string representing the expected opcode. */ -+void -+NIOS2_CHECK_ASSEMBLY (unsigned int opcode, const char *exp_opcode) -+{ -+ if (nios2_mode == NIOS2_MODE_TEST) -+ { -+ if ((exp_opcode) == NULL) -+ { -+ as_bad (_("expecting opcode string in self test mode")); -+ } -+ else if ((opcode) != strtoul ((exp_opcode), NULL, 16)) -+ { -+ as_bad (_("assembly 0x%08x, expected %s"), (opcode), (exp_opcode)); -+ } -+ } -+} -+ -+/* Machine-dependent command-line options. */ -+ -+const char *md_shortopts = "r"; -+ -+struct option md_longopts[] = { -+#define OPTION_RELAX_ALL (OPTION_MD_BASE + 0) -+ {"relax-all", no_argument, NULL, OPTION_RELAX_ALL}, -+#define OPTION_NORELAX (OPTION_MD_BASE + 1) -+ {"no-relax", no_argument, NULL, OPTION_NORELAX}, -+#define OPTION_RELAX_SECTION (OPTION_MD_BASE + 2) -+ {"relax-section", no_argument, NULL, OPTION_RELAX_SECTION}, -+#define OPTION_EB (OPTION_MD_BASE + 3) -+ {"EB", no_argument, NULL, OPTION_EB}, -+#define OPTION_EL (OPTION_MD_BASE + 4) -+ {"EL", no_argument, NULL, OPTION_EL} -+}; -+ -+size_t md_longopts_size = sizeof (md_longopts); -+ -+/* Machine dependent pseudo-ops. -+ These are actually assembler directives. -+ Format of each entry is: -+ -+ { "directive", handler_func, param } */ -+const pseudo_typeS md_pseudo_table[] = { -+ {"align", s_nios2_align, 0}, -+ {"text", s_nios2_text, 0}, -+ {"data", s_nios2_data, 0}, -+ {"section", s_nios2_section, 0}, -+ {"section.s", s_nios2_section, 0}, -+ {"sect", s_nios2_section, 0}, -+ {"sect.s", s_nios2_section, 0}, -+ /* .dword and .half are included for compatibility with MIPS. */ -+ {"dword", cons, 8}, -+ {"half", cons, 2}, -+ /* NIOS2 native word size is 4 bytes, so we override -+ the GAS default of 2. */ -+ {"word", cons, 4}, -+ /* Explicitly unaligned directives. */ -+ {"2byte", s_nios2_ucons, 2}, -+ {"4byte", s_nios2_ucons, 4}, -+ {"8byte", s_nios2_ucons, 8}, -+ {"16byte", s_nios2_ucons, 16}, -+#ifdef OBJ_ELF -+ {"sdata", s_nios2_sdata, 0}, -+#endif -+ {"set", s_nios2_set, 0}, -+ {NULL, NULL, 0} -+}; -+ -+#define BYTE_F 32764 -+#define BYTE_B -32768 -+#define ABS (long)0xffffffff /* Special value to indicate -+ non-pc relative jmp. */ -+ -+#define UBRANCH 1 -+#define UJMP 2 -+#define CBRANCH 3 -+#define CJMP 4 -+ -+ -+#define RELAX_MAX_SIZE(type) nios2_relax_table[nios2_relax_table[type \ -+ ].rlx_more].rlx_length -+#define RELAX_SIZE(type) nios2_relax_table[type].rlx_length -+#define RELAX_SUBSTATE(type) type -+ -+/* Machine dependent relaxations. */ -+struct relax_type nios2_relax_table[] = { -+ /* First entry unused (ends relaxation sequence). */ -+ {1, 1, 0, 0}, -+ /* Unconditional branch. */ -+ {BYTE_F, BYTE_B, 4, 2}, /* br label (label is in range) */ -+ /* Unconditional jmp. */ -+ {ABS, ABS, 12, 0}, /* movhi at, %hi(label) ; -+ ori at, %lo(label) ; jmp at */ -+ /* Conditional branch. */ -+ {BYTE_F, BYTE_B, 4, 4}, /* br{cond} label (label is in range) */ -+ /* Conditional jmp. */ -+ {ABS, ABS, 16, 0}, /* br{opp_cond} skip ; movhi at, %hi(label) ; -+ ori at, %lo(label) ; jmp at ; skip: } */ -+}; -+ -+ -+/* This is just the generic relax_frag function but -+ amended to include absolute jmps in the relax table. */ -+ -+long -+nios2_relax_frag (segT segment, fragS * fragP, long stretch) -+{ -+ const relax_typeS *this_type; -+ const relax_typeS *start_type; -+ relax_substateT next_state; -+ relax_substateT this_state; -+ long growth; -+ offsetT aim; -+ addressT target; -+ addressT address; -+ symbolS *symbolP; -+ const relax_typeS *table; -+ -+ target = fragP->fr_offset; -+ address = fragP->fr_address; -+ table = nios2_relax_table; -+ this_state = fragP->fr_subtype; -+ start_type = this_type = table + this_state; -+ symbolP = fragP->fr_symbol; -+ -+ if (symbolP) -+ { -+ fragS *sym_frag; -+ -+ sym_frag = symbol_get_frag (symbolP); -+ -+#ifndef DIFF_EXPR_OK -+#if 0 -+#if !defined (MANY_SEGMENTS) && !defined (BFD_ASSEMBLER) -+ know ((S_GET_SEGMENT (symbolP) == SEG_ABSOLUTE) -+ || (S_GET_SEGMENT (symbolP) == SEG_DATA) -+ || (S_GET_SEGMENT (symbolP) == SEG_BSS) -+ || (S_GET_SEGMENT (symbolP) == SEG_TEXT)); -+#endif -+#endif -+ know (sym_frag != NULL); -+#endif -+ know (!(S_GET_SEGMENT (symbolP) == absolute_section) -+ || sym_frag == &zero_address_frag); -+ target += S_GET_VALUE (symbolP); -+ -+ /* If frag has yet to be reached on this pass, -+ assume it will move by STRETCH just as we did. -+ If this is not so, it will be because some frag -+ between grows, and that will force another pass. */ -+ -+ if (stretch != 0 -+ && sym_frag->relax_marker != fragP->relax_marker -+ && S_GET_SEGMENT (symbolP) == segment) -+ { -+ target += stretch; -+ } -+ } -+ -+ -+ /* NG we subtract 4 because all pc relative branches are -+ from the next instruction. */ -+ aim = target - address - fragP->fr_fix - 4; -+ -+ if (aim < 0) -+ { -+ /* Look backwards. */ -+ for (next_state = this_type->rlx_more; next_state;) -+ { -+ if (aim >= this_type->rlx_backward -+ || this_type->rlx_backward == ABS) -+ next_state = 0; -+ else -+ { -+ /* Grow to next state. */ -+ this_state = next_state; -+ this_type = table + this_state; -+ next_state = this_type->rlx_more; -+ } -+ } -+ } -+ else -+ { -+ /* Look forwards. */ -+ -+ for (next_state = this_type->rlx_more; next_state;) -+ { -+ if (aim <= this_type->rlx_forward || this_type->rlx_forward == ABS) -+ next_state = 0; -+ else -+ { -+ /* Grow to next state. */ -+ this_state = next_state; -+ this_type = table + this_state; -+ next_state = this_type->rlx_more; -+ } -+ } -+ } -+ -+ -+ growth = this_type->rlx_length - start_type->rlx_length; -+ -+ if (growth != 0) -+ fragP->fr_subtype = this_state; -+ -+ return growth; -+} -+ -+/*-------------------------------------------------------------------------------- -+ The next table associates pointers to functions which parse the arguments to an -+ instruction and fill in the relevant fields of the instruction -+ --------------------------------------------------------------------------------*/ -+ -+const nios2_arg_infoS nios2_arg_info_structs[] = { -+ /* args, assemble_args_func */ -+ {"d,s,t", nios2_assemble_args_dst}, -+ {"d,s,t,E", nios2_assemble_args_dst}, -+ {"t,s,i", nios2_assemble_args_tsi}, -+ {"t,s,i,E", nios2_assemble_args_tsi}, -+ {"t,s,u", nios2_assemble_args_tsu}, -+ {"t,s,u,E", nios2_assemble_args_tsu}, -+ {"s,t,o", nios2_assemble_args_sto}, -+ {"s,t,o,E", nios2_assemble_args_sto}, -+ {"o", nios2_assemble_args_o}, -+ {"o,E", nios2_assemble_args_o}, -+ {"s", nios2_assemble_args_s}, -+ {"s,E", nios2_assemble_args_s}, -+ {"", nios2_assemble_args_none}, -+ {"E", nios2_assemble_args_none}, -+ {"i(s)", nios2_assemble_args_is}, -+ {"i(s)E", nios2_assemble_args_is}, -+ {"m", nios2_assemble_args_m}, -+ {"m,E", nios2_assemble_args_m}, -+ {"t,i(s)", nios2_assemble_args_tis}, -+ {"t,i(s)E", nios2_assemble_args_tis}, -+ {"d,c", nios2_assemble_args_dc}, -+ {"d,c,E", nios2_assemble_args_dc}, -+ {"c,s", nios2_assemble_args_cs}, -+ {"c,s,E", nios2_assemble_args_cs}, -+ {"l,d,s,t", nios2_assemble_args_ldst}, -+ {"l,d,s,t,E", nios2_assemble_args_ldst}, -+ {"d,s,j", nios2_assemble_args_dsj}, -+ {"d,s,j,E", nios2_assemble_args_dsj}, -+ {"d", nios2_assemble_args_d}, -+ {"d,E", nios2_assemble_args_d}, -+ {"b", nios2_assemble_args_b}, -+ {"b,E", nios2_assemble_args_b} -+}; -+ -+#define NIOS2_NUM_ARGS \ -+ ((sizeof(nios2_arg_info_structs)/sizeof(nios2_arg_info_structs[0]))) -+const int nios2_num_arg_info_structs = NIOS2_NUM_ARGS; -+ -+ -+const nios2_ps_insn_infoS nios2_ps_insn_info_structs[] = { -+ /* pseudo-op, real-op, arg, arg_modifier_func, num, index */ -+ {"mov", "add", "zero", nios2_append_arg, 1, 3}, -+ {"movi", "addi", "zero", nios2_insert_arg, 1, 2}, -+ {"movhi", "orhi", "zero", nios2_insert_arg, 1, 2}, -+ {"movui", "ori", "zero", nios2_insert_arg, 1, 2}, -+ {"movia", "orhi", "zero", nios2_insert_arg, 1, 2}, -+ {"nop", "add", "zero", nios2_append_arg, 3, 1}, -+ {"bgt", "blt", "", nios2_swap_args, 1, 2}, -+ {"bgtu", "bltu", "", nios2_swap_args, 1, 2}, -+ {"ble", "bge", "", nios2_swap_args, 1, 2}, -+ {"bleu", "bgeu", "", nios2_swap_args, 1, 2}, -+ {"cmpgt", "cmplt", "", nios2_swap_args, 2, 3}, -+ {"cmpgtu", "cmpltu", "", nios2_swap_args, 2, 3}, -+ {"cmple", "cmpge", "", nios2_swap_args, 2, 3}, -+ {"cmpleu", "cmpgeu", "", nios2_swap_args, 2, 3}, -+ {"cmpgti", "cmpgei", "+1", nios2_modify_arg, 0, 3}, -+ {"cmpgtui", "cmpgeui", "+1", nios2_modify_arg, 0, 3}, -+ {"cmplei", "cmplti", "+1", nios2_modify_arg, 0, 3}, -+ {"cmpleui", "cmpltui", "+1", nios2_modify_arg, 0, 3}, -+ {"subi", "addi", "", nios2_negate_arg, 0, 3} -+ /* Add further pseudo-ops here. */ -+}; -+ -+#define NIOS2_NUM_PSEUDO_INSNS \ -+ ((sizeof(nios2_ps_insn_info_structs)/ \ -+ sizeof(nios2_ps_insn_info_structs[0]))) -+const int nios2_num_ps_insn_info_structs = NIOS2_NUM_PSEUDO_INSNS; -+ -+/* Special relocation directive strings. */ -+ -+struct nios2_special_relocS -+{ -+ const char *string; -+ bfd_reloc_code_real_type reloc_type; -+}; -+ -+struct nios2_special_relocS nios2_special_reloc[] = { -+ {"%hiadj", BFD_RELOC_NIOS2_HIADJ16}, -+ {"%hi", BFD_RELOC_NIOS2_HI16}, -+ {"%lo", BFD_RELOC_NIOS2_LO16}, -+ {"%gprel", BFD_RELOC_NIOS2_GPREL}, -+ {"%call", BFD_RELOC_NIOS2_CALL16}, -+ {"%gotoff_lo", BFD_RELOC_NIOS2_GOTOFF_LO}, -+ {"%gotoff_hiadj", BFD_RELOC_NIOS2_GOTOFF_HA}, -+ {"%tls_gd", BFD_RELOC_NIOS2_TLS_GD16}, -+ {"%tls_ldm", BFD_RELOC_NIOS2_TLS_LDM16}, -+ {"%tls_ldo", BFD_RELOC_NIOS2_TLS_LDO16}, -+ {"%tls_ie", BFD_RELOC_NIOS2_TLS_IE16}, -+ {"%tls_le", BFD_RELOC_NIOS2_TLS_LE16}, -+ {"%gotoff", BFD_RELOC_NIOS2_GOTOFF}, -+ {"%got", BFD_RELOC_NIOS2_GOT16} -+}; -+ -+#define NIOS2_NUM_SPECIAL_RELOCS \ -+ (sizeof(nios2_special_reloc)/sizeof(nios2_special_reloc[0])) -+const int nios2_num_special_relocs = NIOS2_NUM_SPECIAL_RELOCS; -+ -+/* The function nios2_modify_arg appends the string modifier to the string -+ contained in the argument at index in the array parsedArgs[]. */ -+void -+nios2_modify_arg (const char *modifier, -+ char **parsedArgs, int unused ATTRIBUTE_UNUSED, int index) -+{ -+ gas_assert (index < NIOS2_MAX_INSN_TOKENS); -+ -+ /* We can't just strcat here because strcat will free the memory pointed -+ to by the first argument and allocate new memory - but at this stage, -+ parsedArgs[index] may point into the middle of a block of allocated -+ memory, so trying to free it will cause a seg fault. */ -+ char *tmp = parsedArgs[index]; -+ parsedArgs[index] = -+ (char *) malloc (strlen (parsedArgs[index]) + strlen (modifier) + 1); -+ strcpy (parsedArgs[index], tmp); -+ strcat (parsedArgs[index], modifier); -+} -+ -+ -+void -+nios2_negate_arg (const char *modifier ATTRIBUTE_UNUSED, -+ char **parsedArgs, int unused ATTRIBUTE_UNUSED, int index) -+{ -+ char *tmp = parsedArgs[index]; -+ parsedArgs[index] = -+ (char *) malloc (strlen ("~(") + strlen (parsedArgs[index]) + -+ strlen (")+1") + 1); -+ -+ strcpy (parsedArgs[index], "~("); -+ strcat (parsedArgs[index], tmp); -+ strcat (parsedArgs[index], ")+1"); -+} -+ -+/* The function nios2_swap_args swaps the pointers at indices index_1 and -+ index_2 in the array parsedArgs[] - this is used for operand swapping -+ for comparison operations. */ -+void -+nios2_swap_args (const char *unused ATTRIBUTE_UNUSED, -+ char **parsedArgs, int index_1, int index_2) -+{ -+ char *tmp; -+ gas_assert (index_1 < NIOS2_MAX_INSN_TOKENS && index_2 < NIOS2_MAX_INSN_TOKENS); -+ tmp = parsedArgs[index_1]; -+ parsedArgs[index_1] = parsedArgs[index_2]; -+ parsedArgs[index_2] = tmp; -+} -+ -+/* This function appends the string append to the array of strings in -+ parsedArgs numAppend times starting at index startIndex in the array. */ -+void -+nios2_append_arg (const char *append, char **parsedArgs, int numAppend, -+ int startIndex) -+{ -+ int i, count; -+ char *tmp; -+ -+ gas_assert ((startIndex + numAppend) < NIOS2_MAX_INSN_TOKENS); -+ i = startIndex; -+ count = numAppend; -+ -+ if (nios2_mode == NIOS2_MODE_TEST) -+ tmp = parsedArgs[startIndex]; -+ else -+ tmp = NULL; -+ -+ while (count > 0) -+ { -+ parsedArgs[i] = (char *) append; -+ ++i; -+ --count; -+ } -+ -+ gas_assert (i == (startIndex + numAppend)); -+ parsedArgs[i] = tmp; -+ parsedArgs[i + 1] = NULL; -+} -+ -+/* This function inserts the string insert numInsert times in the array -+ parsedArgs, starting at the index startIndex. */ -+void -+nios2_insert_arg (const char *insert, char **parsedArgs, int numInsert, -+ int startIndex) -+{ -+ int i, count, from, to; -+ -+ gas_assert ((startIndex + numInsert) < NIOS2_MAX_INSN_TOKENS); -+ -+ to = startIndex + numInsert; -+ from = startIndex; -+ -+ /* Move the existing arguments up to create space. */ -+ i = NIOS2_MAX_INSN_TOKENS; -+ while ((i - numInsert) >= startIndex) -+ { -+ parsedArgs[i] = parsedArgs[i - numInsert]; -+ --i; -+ } -+ -+ i = startIndex; -+ count = numInsert; -+ while (count > 0) -+ { -+ parsedArgs[i] = (char *) insert; -+ ++i; -+ --count; -+ } -+} -+ -+/* This function swaps the pseudo-op for a real op. -+ FIXME - only works for 1-to-1 correspondence. */ -+void -+nios2_translate_pseudo_insn (nios2_insn_infoS * insn) -+{ -+ -+ nios2_ps_insn_infoS *ps_insn; -+ -+ /* Find which real insn the pseudo-op transates to and -+ switch the insn_info ptr to point to it. */ -+ ps_insn = -+ (nios2_ps_insn_infoS *) hash_find (nios2_ps_hash, -+ insn->insn_nios2_opcode->name); -+ -+ if (ps_insn != NULL) -+ { -+ insn->insn_nios2_opcode = -+ (struct nios2_opcode *) hash_find (nios2_opcode_hash, ps_insn->insn); -+ insn->insn_tokens[0] = insn->insn_nios2_opcode->name; -+ /* Modify the args so they work with the real insn. */ -+ ps_insn->arg_modifer_func (ps_insn->arg_modifier, -+ (char **) insn->insn_tokens, ps_insn->num, -+ ps_insn->index); -+ } -+ else -+ { -+ /* we cannot recover from this. */ -+ as_fatal (_("unrecognized pseudo-instruction %s"), -+ ps_insn->pseudo_insn); -+ } -+} -+ -+/******************************************************************** -+ The following functions are called by machine-independent parts of -+ the assembler -+ ********************************************************************/ -+ -+int -+md_parse_option (int c, char *arg ATTRIBUTE_UNUSED) -+{ -+ switch (c) -+ { -+ case 'r': -+ /* hidden option for self-test mode */ -+ nios2_mode = NIOS2_MODE_TEST; -+ break; -+ case OPTION_RELAX_ALL: -+ nios2_as_options.relax = relax_all; -+ break; -+ case OPTION_NORELAX: -+ nios2_as_options.relax = relax_none; -+ break; -+ case OPTION_RELAX_SECTION: -+ nios2_as_options.relax = relax_section; -+ break; -+ case OPTION_EB: -+ target_big_endian = 1; -+ break; -+ case OPTION_EL: -+ target_big_endian = 0; -+ break; -+ default: -+ return 0; -+ break; -+ } -+ -+ return 1; -+} -+ -+/* We can choose to be big-endian or little-endian at runtime based -+ on a switch. */ -+const char * -+nios2_target_format (void) -+{ -+ return target_big_endian ? "elf32-bignios2" : "elf32-littlenios2"; -+} -+ -+/* Machine-dependent usage message. */ -+void -+md_show_usage (FILE * stream) -+{ -+ fprintf (stream, " NIOS2 options:\n" -+ " -relax-all replace all branch and call " -+ "instructions with jmp and callr sequences\n" -+ " -relax-section replace identified out of range " -+ "branches with jmp sequences (default)\n" -+ " -no-relax do not replace any branches or calls\n" -+ " -EB force big-endian byte ordering\n" -+ " -EL force little-endian byte ordering\n"); -+} -+ -+/* This function is called once, at assembler startup time. -+ It should set up all the tables, etc. that the MD part of the -+ assembler will need. */ -+void -+md_begin (void) -+{ -+ int i; -+ const char *inserted; -+ -+ /* Create and fill a hashtable for the New Jersey opcodes, registers and -+ arguments. */ -+ nios2_opcode_hash = hash_new (); -+ nios2_reg_hash = hash_new (); -+ nios2_arg_hash = hash_new (); -+ nios2_ps_hash = hash_new (); -+ -+ for (i = 0; i < NUMOPCODES; ++i) -+ { -+ inserted = -+ hash_insert (nios2_opcode_hash, nios2_opcodes[i].name, -+ (PTR) & nios2_opcodes[i]); -+ if (inserted != NULL) -+ { -+ fprintf (stderr, _("internal error: can't hash `%s': %s\n"), -+ nios2_opcodes[i].name, inserted); -+ /* Probably a memory allocation problem? Give up now. */ -+ as_fatal (_("Broken assembler. No assembly attempted.")); -+ } -+ } -+ -+ for (i = 0; i < nios2_num_regs; ++i) -+ { -+ inserted = -+ hash_insert (nios2_reg_hash, nios2_regs[i].name, -+ (PTR) & nios2_regs[i]); -+ if (inserted != NULL) -+ { -+ fprintf (stderr, _("internal error: can't hash `%s': %s\n"), -+ nios2_regs[i].name, inserted); -+ /* Probably a memory allocation problem? Give up now. */ -+ as_fatal (_("Broken assembler. No assembly attempted.")); -+ } -+ -+ } -+ -+ for (i = 0; i < nios2_num_arg_info_structs; ++i) -+ { -+ inserted = -+ hash_insert (nios2_arg_hash, nios2_arg_info_structs[i].args, -+ (PTR) & nios2_arg_info_structs[i]); -+ if (inserted != NULL) -+ { -+ fprintf (stderr, _("internal error: can't hash `%s': %s\n"), -+ nios2_arg_info_structs[i].args, inserted); -+ /* Probably a memory allocation problem? Give up now. */ -+ as_fatal (_("Broken assembler. No assembly attempted.")); -+ } -+ } -+ -+ for (i = 0; i < nios2_num_ps_insn_info_structs; ++i) -+ { -+ inserted = -+ hash_insert (nios2_ps_hash, nios2_ps_insn_info_structs[i].pseudo_insn, -+ (PTR) & nios2_ps_insn_info_structs[i]); -+ if (inserted != NULL) -+ { -+ fprintf (stderr, _("internal error: can't hash `%s': %s\n"), -+ nios2_ps_insn_info_structs[i].pseudo_insn, inserted); -+ /* Probably a memory allocation problem? Give up now. */ -+ as_fatal (_("Broken assembler. No assembly attempted.")); -+ } -+ } -+ -+ /* Assembler option defaults. */ -+ nios2_as_options.noat = FALSE; -+ nios2_as_options.nobreak = FALSE; -+ -+ /* Debug information is incompatible with relaxation. */ -+ if (debug_type != DEBUG_UNSPECIFIED) -+ { -+ nios2_as_options.relax = relax_none; -+ } -+ -+ /* Initialize the alignment data. */ -+ nios2_current_align_seg = now_seg; -+ nios2_last_label = NULL; -+ nios2_current_align = 0; -+} -+ -+ -+ -+ -+/* Made this global to avoid changing one function prototype. */ -+nios2_insn_infoS insn; -+ -+/* Assembles a single line of Nios II assembly language. */ -+void -+md_assemble (char *op_str) -+{ -+ char *argstr; -+ char *op_strdup; -+ nios2_arg_infoS *arg_info; -+ unsigned long saved_pinfo = 0; -+ -+ /* Make sure we are aligned on a 4-byte boundary. */ -+ if (nios2_current_align < 2) -+ nios2_align (2, NULL, nios2_last_label); -+ else if (nios2_current_align > 2) -+ nios2_current_align = 2; -+ nios2_last_label = NULL; -+ -+ -+ /* We don't want to clobber to op_str -+ because we want to be able to use it in messages. */ -+ op_strdup = strdup (op_str); -+ -+ insn.insn_tokens[0] = strtok (op_strdup, " "); -+ argstr = strtok (NULL, ""); -+ -+ /* Assemble the opcode. */ -+ insn.insn_nios2_opcode = -+ (struct nios2_opcode *) hash_find (nios2_opcode_hash, -+ insn.insn_tokens[0]); -+ insn.insn_reloc = NULL; -+ -+ if (insn.insn_nios2_opcode != NULL) -+ { -+ /* Set the opcode for the instruction. */ -+ insn.insn_code = insn.insn_nios2_opcode->match; -+ -+ /* Parse the arguments pointed to by argstr. */ -+ if (nios2_mode == NIOS2_MODE_ASSEMBLE) -+ { -+ nios2_parse_args (argstr, insn.insn_nios2_opcode->args, -+ (char **) &insn.insn_tokens[1]); -+ } -+ else -+ { -+ nios2_parse_args (argstr, insn.insn_nios2_opcode->args_test, -+ (char **) &insn.insn_tokens[1]); -+ } -+ -+ /* We need to preserve the MOVIA macro as this is clobbered by -+ translate_pseudo_insn. */ -+ if (insn.insn_nios2_opcode->pinfo == NIOS2_INSN_MACRO_MOVIA) -+ { -+ saved_pinfo = NIOS2_INSN_MACRO_MOVIA; -+ } -+ /* If the instruction is an pseudo-instruction, we want to replace it -+ with its real equivalent, and then continue. */ -+ if ((insn.insn_nios2_opcode->pinfo & NIOS2_INSN_MACRO) == -+ NIOS2_INSN_MACRO) -+ { -+ nios2_translate_pseudo_insn (&insn); -+ } -+ -+ /* Find the assemble function, and call it. */ -+ arg_info = -+ (nios2_arg_infoS *) hash_find (nios2_arg_hash, -+ insn.insn_nios2_opcode->args); -+ if (arg_info != NULL) -+ { -+ arg_info->assemble_args_func (&insn); -+ -+ if (nios2_as_options.relax != relax_none -+ && insn.insn_nios2_opcode->pinfo & NIOS2_INSN_UBRANCH) -+ output_ubranch (); -+ else if (nios2_as_options.relax != relax_none -+ && insn.insn_nios2_opcode->pinfo & NIOS2_INSN_CBRANCH) -+ output_cbranch (); -+ else if (nios2_as_options.relax == relax_all -+ && insn.insn_nios2_opcode->pinfo & NIOS2_INSN_CALL) -+ output_call (); -+ else if (insn.insn_nios2_opcode->pinfo & NIOS2_INSN_ANDI) -+ output_andi (); -+ else if (insn.insn_nios2_opcode->pinfo & NIOS2_INSN_ORI) -+ output_ori (); -+ else if (insn.insn_nios2_opcode->pinfo & NIOS2_INSN_XORI) -+ output_xori (); -+ else if (insn.insn_nios2_opcode->pinfo & NIOS2_INSN_ADDI) -+ output_addi (); -+ else if (saved_pinfo == NIOS2_INSN_MACRO_MOVIA) -+ output_movia (); -+ else -+ output_insn (); -+ } -+ else -+ { -+ /* The assembler is broken. */ -+ fprintf (stderr, -+ _("internal error: %s is not a valid argument syntax\n"), -+ insn.insn_nios2_opcode->args); -+ /* Probably a memory allocation problem. Give up now. */ -+ as_fatal (_("Broken assembler. No assembly attempted.")); -+ } -+ } -+ else -+ { -+ /* Unrecognised instruction - error. */ -+ as_bad (_("unrecognised instruction %s"), insn.insn_tokens[0]); -+ } -+} -+ -+/* Output a normal instruction. */ -+static void -+output_insn () -+{ -+ char *f; -+ nios2_insn_relocS *reloc; -+ -+ f = frag_more (4); -+ /* This allocates enough space for the instruction -+ and puts it in the current frag. */ -+ md_number_to_chars (f, insn.insn_code, 4); -+ /* Emit debug info. */ -+ dwarf2_emit_insn (4); -+ /* Create any fixups. */ -+ reloc = insn.insn_reloc; -+ while (reloc != NULL) -+ { -+ /* This creates any fixups to be acted on later. */ -+ fix_new_exp (frag_now, f - frag_now->fr_literal, 4, -+ &reloc->reloc_expression, reloc->reloc_pcrel, -+ reloc->reloc_type); -+ reloc = reloc->reloc_next; -+ } -+} -+ -+/* Output an unconditional branch. */ -+static void -+output_ubranch (void) -+{ -+ char *f; -+ nios2_insn_relocS *reloc; -+ symbolS *symp; -+ offsetT offset; -+ -+ reloc = insn.insn_reloc; -+ -+ /* If the reloc is NULL, there was an error assembling the branch. */ -+ if (reloc != NULL) -+ { -+ -+ symp = reloc->reloc_expression.X_add_symbol; -+ offset = reloc->reloc_expression.X_add_number; -+ -+ /* We must tag debug info here since we can't do it after -+ calling frag_var. */ -+ dwarf2_emit_insn (4); -+ -+ /* We create a machine dependent frag which can grow -+ to accommodate the largest possible instruction sequence -+ this may generate. */ -+ f = frag_var (rs_machine_dependent, -+ RELAX_MAX_SIZE (UBRANCH), -+ RELAX_SIZE (UBRANCH), -+ RELAX_SUBSTATE (UBRANCH), symp, offset, NULL); -+ -+ md_number_to_chars (f, insn.insn_code, 4); -+ -+ /* We leave fixup generation to md_convert_frag. */ -+ } -+} -+ -+/* Output a conditional branch. */ -+static void -+output_cbranch (void) -+{ -+ char *f; -+ nios2_insn_relocS *reloc; -+ symbolS *symp; -+ offsetT offset; -+ -+ reloc = insn.insn_reloc; -+ -+ /* If the reloc is NULL, there was an error assembling the branch. */ -+ if (reloc != NULL) -+ { -+ -+ symp = reloc->reloc_expression.X_add_symbol; -+ offset = reloc->reloc_expression.X_add_number; -+ -+ /* We must tag debug info here since we can't do it after -+ calling frag_var. */ -+ dwarf2_emit_insn (4); -+ -+ /* We create a machine dependent frag which can grow -+ to accommodate the largest possible instruction sequence -+ this may generate. */ -+ f = frag_var (rs_machine_dependent, -+ RELAX_MAX_SIZE (CBRANCH), -+ RELAX_SIZE (CBRANCH), -+ RELAX_SUBSTATE (CBRANCH), symp, offset, NULL); -+ -+ md_number_to_chars (f, insn.insn_code, 4); -+ -+ -+ /* We leave fixup generation to md_convert_frag. */ -+ } -+} -+ -+/* Output a call sequence. Since calls are not pc-relative for NIOS2, -+ but are page-relative, we cannot tell at any stage in assembly -+ whether a call will be out of range since a section may be linked -+ at any address. So if we are relaxing, we convert all call instructions -+ to long call sequences, and rely on the linker to relax them back to -+ short calls. */ -+static void -+output_call (void) -+{ -+ char *f; -+ nios2_insn_relocS *reloc; -+ f = frag_more (12); -+ /* This allocates enough space for the instruction -+ and puts it in the current frag. */ -+ reloc = insn.insn_reloc; -+ -+ /* If the reloc is NULL, there was an error assembling the branch. */ -+ if (reloc != NULL) -+ { -+ md_number_to_chars (f, OP_MATCH_ORHI | 0x00400000, 4); -+ dwarf2_emit_insn (4); -+ md_number_to_chars (f + 4, OP_MATCH_ORI | 0x08400000, 4); -+ dwarf2_emit_insn (4); -+ md_number_to_chars (f + 8, OP_MATCH_CALLR | 0x08000000, 4); -+ dwarf2_emit_insn (4); -+ fix_new (frag_now, f - frag_now->fr_literal, 4, -+ reloc->reloc_expression.X_add_symbol, -+ reloc->reloc_expression.X_add_number, 0, -+ BFD_RELOC_NIOS2_CALLR); -+ -+ -+ } -+} -+ -+ -+static int -+can_evaluate_expr (void) -+{ -+ /* Remove this check for null and the invalid insn "ori r9, 1234" seg faults. */ -+ if (!insn.insn_reloc) -+ { -+ /* ??? Ideally we should do something other than as_fatal here as we can -+ continue to assemble. -+ However this function (actually the output_* functions) should not -+ have been called in the first place once an illegal instruction had -+ been encountered. */ -+ as_fatal (_("Invalid instruction encountered, cannot recover. No assembly attempted.")); -+ } -+ -+ if (insn.insn_reloc->reloc_expression.X_op == O_constant) -+ return 1; -+ -+ return 0; -+} -+ -+static int -+get_expr_value (void) -+{ -+ int value = 0; -+ if (insn.insn_reloc->reloc_expression.X_op == O_constant) -+ value = insn.insn_reloc->reloc_expression.X_add_number; -+ return value; -+} -+ -+/* Output an addi - will silently convert to -+ orhi if rA = r0 and (expr & 0xffff0000) == 0. */ -+static void -+output_addi (void) -+{ -+ int expr_val = 0; -+ if (can_evaluate_expr ()) -+ { -+ expr_val = get_expr_value (); -+ if (GET_INSN_FIELD (RRS, insn.insn_code) == 0 && -+ (expr_val & 0xffff) == 0 && expr_val != 0) -+ { -+ -+ /* We really want a movhi (orhi) here. */ -+ insn.insn_code = (insn.insn_code & ~OP_MATCH_ADDI) | OP_MATCH_ORHI; -+ insn.insn_reloc->reloc_expression.X_add_number = -+ (insn.insn_reloc->reloc_expression.X_add_number >> 16) & 0xffff; -+ insn.insn_reloc->reloc_type = BFD_RELOC_NIOS2_U16; -+ } -+ } -+ -+ /* Output an instruction. */ -+ output_insn (); -+} -+ -+static void -+output_andi (void) -+{ -+ int expr_val = 0; -+ if (can_evaluate_expr ()) -+ { -+ expr_val = get_expr_value (); -+ if (expr_val != 0 && (expr_val & 0xffff) == 0) -+ { -+ /* We really want a movhi (orhi) here. */ -+ insn.insn_code = (insn.insn_code & ~OP_MATCH_ANDI) | OP_MATCH_ANDHI; -+ insn.insn_reloc->reloc_expression.X_add_number = -+ (insn.insn_reloc->reloc_expression.X_add_number >> 16) & 0xffff; -+ insn.insn_reloc->reloc_type = BFD_RELOC_NIOS2_U16; -+ } -+ } -+ -+ /* Output an instruction. */ -+ output_insn (); -+} -+ -+static void -+output_ori (void) -+{ -+ int expr_val = 0; -+ if (can_evaluate_expr ()) -+ { -+ expr_val = get_expr_value (); -+ if (expr_val != 0 && (expr_val & 0xffff) == 0) -+ { -+ /* We really want a movhi (orhi) here. */ -+ insn.insn_code = (insn.insn_code & ~OP_MATCH_ORI) | OP_MATCH_ORHI; -+ insn.insn_reloc->reloc_expression.X_add_number = -+ (insn.insn_reloc->reloc_expression.X_add_number >> 16) & 0xffff; -+ insn.insn_reloc->reloc_type = BFD_RELOC_NIOS2_U16; -+ } -+ } -+ -+ /* Output an instruction. */ -+ output_insn (); -+} -+ -+static void -+output_xori (void) -+{ -+ int expr_val = 0; -+ if (can_evaluate_expr ()) -+ { -+ expr_val = get_expr_value (); -+ if (expr_val != 0 && (expr_val & 0xffff) == 0) -+ { -+ /* We really want a movhi (orhi) here. */ -+ insn.insn_code = (insn.insn_code & ~OP_MATCH_XORI) | OP_MATCH_XORHI; -+ insn.insn_reloc->reloc_expression.X_add_number = -+ (insn.insn_reloc->reloc_expression.X_add_number >> 16) & 0xffff; -+ insn.insn_reloc->reloc_type = BFD_RELOC_NIOS2_U16; -+ } -+ } -+ -+ /* Output an instruction. */ -+ output_insn (); -+} -+ -+ -+/* Output a movhi/addi pair for the movia pseudo-op. */ -+static void -+output_movia (void) -+{ -+ char *f; -+ nios2_insn_relocS *reloc; -+ f = frag_more (8); -+ unsigned long reg_index = GET_INSN_FIELD (IRT, insn.insn_code); -+ -+ /* This allocates enough space for the instruction -+ and puts it in the current frag. */ -+ reloc = insn.insn_reloc; -+ -+ /* If the reloc is NULL, there was an error assembling the movia. */ -+ if (reloc != NULL) -+ { -+ md_number_to_chars (f, insn.insn_code, 4); -+ dwarf2_emit_insn (4); -+ md_number_to_chars (f + 4, -+ OP_MATCH_ADDI | (reg_index << OP_SH_IRT) | -+ (reg_index << OP_SH_IRS), 4); -+ dwarf2_emit_insn (4); -+ fix_new (frag_now, f - frag_now->fr_literal, 4, -+ reloc->reloc_expression.X_add_symbol, -+ reloc->reloc_expression.X_add_number, 0, -+ BFD_RELOC_NIOS2_HIADJ16); -+ fix_new (frag_now, f + 4 - frag_now->fr_literal, 4, -+ reloc->reloc_expression.X_add_symbol, -+ reloc->reloc_expression.X_add_number, 0, BFD_RELOC_NIOS2_LO16); -+ -+ } -+} -+ -+/* Function md_chars_to_number takes the sequence of -+ bytes in buf and returns the corresponding value -+ in an int. n must be 1, 2 or 4. */ -+valueT -+md_chars_to_number (char *buf, int n) -+{ -+ int i; -+ valueT val; -+ -+ gas_assert (n == 1 || n == 2 || n == 4); -+ -+ val = 0; -+ if (target_big_endian) -+ { -+ for (i = 0; i < n; ++i) -+ { -+ val = val | ((buf[i] & 0xff) << 8 * (n - (i + 1))); -+ } -+ } -+ else -+ { -+ for (i = 0; i < n; ++i) -+ { -+ val = val | ((buf[i] & 0xff) << 8 * i); -+ } -+ } -+ return val; -+} -+ -+ -+/* This function turns a C long int, short int or char -+ into the series of bytes that represent the number -+ on the target machine. */ -+void -+md_number_to_chars (char *buf, valueT val, int n) -+{ -+ gas_assert (n == 1 || n == 2 || n == 4); -+ if (target_big_endian) -+ { -+ number_to_chars_bigendian (buf, val, n); -+ } -+ else -+ { -+ number_to_chars_littleendian (buf, val, n); -+ } -+} -+ -+/* This function is identical to md_number_to_chars. */ -+void -+md_number_to_imm (char *buf, valueT val, int n) -+{ -+ md_number_to_chars (buf, val, n); -+} -+ -+/* This function is identical to md_number_to_chars. */ -+void -+md_number_to_disp (char *buf, valueT val, int n) -+{ -+ md_number_to_chars (buf, val, n); -+} -+ -+/* This function is identical to md_number_to_chars. */ -+void -+md_number_to_field (char *buf, valueT val, int n) -+{ -+ md_number_to_chars (buf, val, n); -+} -+ -+/* Turn a string in input_line_pointer into a floating point constant -+ of type TYPE, and store the appropriate bytes in *LITP. The number -+ of LITTLENUMS emitted is stored in *SIZEP. An error message is -+ returned, or NULL on OK. */ -+char * -+md_atof (int type, char *litP, int *sizeP) -+{ -+ int prec; -+ LITTLENUM_TYPE words[4]; -+ char *t; -+ int i; -+ -+ switch (type) -+ { -+ case 'f': -+ prec = 2; -+ break; -+ case 'd': -+ prec = 4; -+ break; -+ default: -+ *sizeP = 0; -+ return _("bad call to md_atof"); -+ } -+ -+ t = atof_ieee (input_line_pointer, type, words); -+ if (t) -+ input_line_pointer = t; -+ -+ *sizeP = prec * 2; -+ -+ if (! target_big_endian) -+ { -+ for (i = prec - 1; i >= 0; i--) -+ { -+ md_number_to_chars (litP, (valueT) words[i], 2); -+ litP += 2; -+ } -+ } -+ else -+ { -+ for (i = 0; i < prec; i++) -+ { -+ md_number_to_chars (litP, (valueT) words[i], 2); -+ litP += 2; -+ } -+ } -+ -+ return NULL; -+} -+ -+ -+ -+int md_short_jump_size; -+int md_long_jump_size; -+ -+void -+md_create_short_jump (char *result_ptr ATTRIBUTE_UNUSED, -+ addressT from_addr ATTRIBUTE_UNUSED, -+ addressT to_addr ATTRIBUTE_UNUSED, -+ fragS * frag ATTRIBUTE_UNUSED, -+ symbolS * to_symbol ATTRIBUTE_UNUSED) -+{ -+ abort (); -+} -+ -+void -+md_create_long_jump (char *ptr ATTRIBUTE_UNUSED, -+ addressT from_addr ATTRIBUTE_UNUSED, -+ addressT to_addr ATTRIBUTE_UNUSED, -+ fragS * frag ATTRIBUTE_UNUSED, -+ symbolS * to_symbol ATTRIBUTE_UNUSED) -+{ -+ abort (); -+} -+ -+int -+md_estimate_size_before_relax (fragS * fragp, segT segment ATTRIBUTE_UNUSED) -+{ -+ /* We only support ELF targets. */ -+ -+ switch (nios2_as_options.relax) -+ { -+ case relax_none: -+ case relax_section: -+ break; -+ case relax_all: -+ /* The NIOS2 linker performs relaxation so the assembler -+ always assumes the worst case, so that the linker can -+ replace with a better case if possible - this way, linker -+ relaxation can never cause a short branch to be out of range. */ -+ while (nios2_relax_table[fragp->fr_subtype].rlx_more != 0) -+ fragp->fr_subtype = nios2_relax_table[fragp->fr_subtype].rlx_more; -+ break; -+ default: -+ abort (); -+ break; -+ } -+ -+ /* Return the estimated size of the frag. */ -+ return nios2_relax_table[fragp->fr_subtype].rlx_length; -+} -+ -+ -+void -+md_convert_frag (bfd * headers ATTRIBUTE_UNUSED, segT seg ATTRIBUTE_UNUSED, -+ fragS * fragp) -+{ -+ unsigned char *buffer = fragp->fr_literal + fragp->fr_fix; -+ relax_substateT subtype = fragp->fr_subtype; -+ unsigned int growth = RELAX_SIZE (subtype); -+ unsigned int br_opcode, br_op_a, br_op_b; -+ -+ switch (subtype) -+ { -+ case UBRANCH: -+ /* We just need to generate the fixup for the symbol and offset. */ -+ fix_new (fragp, fragp->fr_fix, 4, fragp->fr_symbol, fragp->fr_offset, 1, -+ BFD_RELOC_16_PCREL); -+ break; -+ case UJMP: -+ /* Replace ubranch at fr_fix with : -+ movhi at, %hi(symbol+offset) -+ ori at, %lo(symbol+offset) -+ jmp at -+ */ -+ md_number_to_chars (buffer, OP_MATCH_ORHI | 0x00400000, 4); -+ md_number_to_chars (buffer + 4, OP_MATCH_ORI | 0x08400000, 4); -+ md_number_to_chars (buffer + 8, OP_MATCH_JMP | 0x08000000, 4); -+ fix_new (fragp, fragp->fr_fix, 4, fragp->fr_symbol, fragp->fr_offset, 0, -+ BFD_RELOC_NIOS2_UJMP); -+ break; -+ case CBRANCH: -+ /* We just need to generate the fixup for the symbol and offset. */ -+ fix_new (fragp, fragp->fr_fix, 4, fragp->fr_symbol, fragp->fr_offset, 1, -+ BFD_RELOC_16_PCREL); -+ break; -+ case CJMP: -+ /* Replace cbranch at fr_fix with : -+ b(opposite condition) r, s, skip -+ movhi at, %hi(symbol+offset) -+ ori at, %lo(symbol+offset) -+ jmp at -+ skip: -+ ... -+ */ -+ br_opcode = md_chars_to_number (buffer, 4); -+ -+ switch (br_opcode & OP_MASK_OP) -+ { -+ case OP_MATCH_BEQ: -+ br_opcode = -+ (br_opcode & ~OP_MASK_OP) | OP_MATCH_BNE | (12 << OP_SH_IMM16); -+ break; -+ case OP_MATCH_BNE: -+ br_opcode = -+ (br_opcode & ~OP_MASK_OP) | OP_MATCH_BEQ | (12 << OP_SH_IMM16); -+ break; -+ case OP_MATCH_BGE: -+ case OP_MATCH_BGEU: -+ case OP_MATCH_BLT: -+ case OP_MATCH_BLTU: -+ /* Swap the operands. */ -+ br_op_a = (br_opcode & OP_MASK_RRT) << 5; -+ br_op_b = (br_opcode & OP_MASK_RRS) >> 5; -+ br_opcode = -+ (br_opcode & ~(OP_MASK_RRS | OP_MASK_RRT)) | br_op_a | br_op_b | -+ (12 << OP_SH_IMM16); -+ break; -+ default: -+ as_bad_where (fragp->fr_file, fragp->fr_line, -+ _("expecting conditional branch for relaxation\n")); -+ abort (); -+ } -+ -+ md_number_to_chars (buffer, br_opcode, 4); -+ md_number_to_chars (buffer + 4, OP_MATCH_ORHI | 0x00400000, 4); -+ md_number_to_chars (buffer + 8, OP_MATCH_ORI | 0x08400000, 4); -+ md_number_to_chars (buffer + 12, OP_MATCH_JMP | 0x08000000, 4); -+ fix_new (fragp, fragp->fr_fix + 4, 4, fragp->fr_symbol, -+ fragp->fr_offset, 0, BFD_RELOC_NIOS2_CJMP); -+ break; -+ default: -+ as_bad_where (fragp->fr_file, fragp->fr_line, -+ _("can't relax instruction\n")); -+ abort (); -+ break; -+ } -+ -+ fragp->fr_fix += growth; -+} -+ -+ -+/* Round up section size. */ -+valueT -+md_section_align (asection * seg ATTRIBUTE_UNUSED, valueT size) -+{ -+ /* I think byte alignment is fine here */ -+ return size; -+} -+ -+ -+int -+nios2_force_relocation (fixS * fixp) -+{ -+ if (fixp->fx_r_type == BFD_RELOC_VTABLE_INHERIT -+ || fixp->fx_r_type == BFD_RELOC_VTABLE_ENTRY -+ || fixp->fx_r_type == BFD_RELOC_NIOS2_ALIGN) -+ return 1; -+ -+ return generic_force_reloc (fixp); -+} -+ -+/* nios2_fix_adjustable is called to see whether a reloc against a defined -+ symbol should be converted into a reloc against a section. */ -+int -+nios2_fix_adjustable (fixS * fixp) -+{ -+ if (fixp->fx_addsy == NULL) -+ return 1; -+ -+#ifdef OBJ_ELF -+ /* Prevent all adjustments to global symbols. */ -+ if (OUTPUT_FLAVOR == bfd_target_elf_flavour -+ && (S_IS_EXTERNAL (fixp->fx_addsy) || S_IS_WEAK (fixp->fx_addsy))) -+ return 0; -+#endif -+ if (fixp->fx_r_type == BFD_RELOC_VTABLE_INHERIT -+ || fixp->fx_r_type == BFD_RELOC_VTABLE_ENTRY) -+ return 0; -+ -+ /* Preserve relocations against symbols with function type. */ -+ if (symbol_get_bfdsym (fixp->fx_addsy)->flags & BSF_FUNCTION) -+ return 0; -+ -+ /* Don't allow symbols to be discarded on GOT related relocs. */ -+ if (fixp->fx_r_type == BFD_RELOC_NIOS2_GOT16 -+ || fixp->fx_r_type == BFD_RELOC_NIOS2_CALL16 -+ || fixp->fx_r_type == BFD_RELOC_NIOS2_GOTOFF_LO -+ || fixp->fx_r_type == BFD_RELOC_NIOS2_GOTOFF_HA -+ || fixp->fx_r_type == BFD_RELOC_NIOS2_TLS_GD16 -+ || fixp->fx_r_type == BFD_RELOC_NIOS2_TLS_LDM16 -+ || fixp->fx_r_type == BFD_RELOC_NIOS2_TLS_LDO16 -+ || fixp->fx_r_type == BFD_RELOC_NIOS2_TLS_IE16 -+ || fixp->fx_r_type == BFD_RELOC_NIOS2_TLS_LE16 -+ || fixp->fx_r_type == BFD_RELOC_NIOS2_TLS_DTPMOD -+ || fixp->fx_r_type == BFD_RELOC_NIOS2_TLS_DTPREL -+ || fixp->fx_r_type == BFD_RELOC_NIOS2_TLS_TPREL -+ || fixp->fx_r_type == BFD_RELOC_NIOS2_GOTOFF) -+ return 0; -+ -+ return 1; -+} -+ -+/* nios2_frob_symbol is called in adjust_reloc_syms through the macro -+ tc_frob_symbol - it is used to remove *ABS* references from the -+ symbol table. */ -+int -+nios2_frob_symbol (symbolS * symp) -+{ -+ if ((OUTPUT_FLAVOR == bfd_target_elf_flavour -+ && (symp) == section_symbol (absolute_section)) -+ || !S_IS_DEFINED (symp)) -+ return 1; -+ else -+ return 0; -+} -+ -+/* The function tc_gen_reloc creates a relocation structure for the -+ fixup fixp, and returns a pointer to it. This structure is passed -+ to bfd_install_relocation so that it can be written to the object -+ file for linking. -+*/ -+arelent * -+tc_gen_reloc (asection * section ATTRIBUTE_UNUSED, fixS * fixp) -+{ -+ arelent *reloc; -+ reloc = (arelent *) xmalloc (sizeof (arelent)); -+ reloc->sym_ptr_ptr = (asymbol **) 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; // fixp->fx_addnumber; -+ -+ if (fixp->fx_pcrel) -+ { -+ switch (fixp->fx_r_type) -+ { -+ case BFD_RELOC_16: -+ fixp->fx_r_type = BFD_RELOC_16_PCREL; -+ break; -+ case BFD_RELOC_NIOS2_LO16: -+ fixp->fx_r_type = BFD_RELOC_NIOS2_PCREL_LO; -+ break; -+ case BFD_RELOC_NIOS2_HIADJ16: -+ fixp->fx_r_type = BFD_RELOC_NIOS2_PCREL_HA; -+ break; -+ default: -+ break; -+ } -+ } -+ -+ reloc->howto = bfd_reloc_type_lookup (stdoutput, fixp->fx_r_type); -+ if (reloc->howto == NULL) -+ { -+ as_bad_where (fixp->fx_file, fixp->fx_line, -+ _("can't represent relocation type %s"), -+ bfd_get_reloc_code_name (fixp->fx_r_type)); -+ -+ /* Set howto to a garbage value so that we can keep going. */ -+ reloc->howto = bfd_reloc_type_lookup (stdoutput, BFD_RELOC_32); -+ gas_assert (reloc->howto != NULL); -+ } -+ return reloc; -+} -+ -+long -+md_pcrel_from (fixS * fixP ATTRIBUTE_UNUSED) -+{ -+ return 0; -+} -+ -+ -+/* Apply a fixup to the object file. */ -+void -+md_apply_fix (fixS * fixP, valueT * valP, segT seg ATTRIBUTE_UNUSED) -+{ -+ const struct nios2_opcode *opcode; -+ enum overflow_type overflow_msg_type; -+ bfd_boolean overflowed = FALSE; -+ valueT fixup = 0; -+ -+ /* Assert that the fixup is one we can handle. */ -+ gas_assert (fixP != NULL && valP != NULL && -+ (fixP->fx_r_type == BFD_RELOC_8 || -+ fixP->fx_r_type == BFD_RELOC_16 || -+ fixP->fx_r_type == BFD_RELOC_32 || -+ fixP->fx_r_type == BFD_RELOC_NIOS2_S16 || -+ fixP->fx_r_type == BFD_RELOC_NIOS2_U16 || -+ fixP->fx_r_type == BFD_RELOC_16_PCREL || -+ fixP->fx_r_type == BFD_RELOC_NIOS2_CALL26 || -+ fixP->fx_r_type == BFD_RELOC_NIOS2_IMM5 || -+ fixP->fx_r_type == BFD_RELOC_NIOS2_CACHE_OPX || -+ fixP->fx_r_type == BFD_RELOC_NIOS2_IMM6 || -+ fixP->fx_r_type == BFD_RELOC_NIOS2_IMM8 || -+ fixP->fx_r_type == BFD_RELOC_NIOS2_HI16 || -+ fixP->fx_r_type == BFD_RELOC_NIOS2_LO16 || -+ fixP->fx_r_type == BFD_RELOC_NIOS2_HIADJ16 || -+ fixP->fx_r_type == BFD_RELOC_NIOS2_GPREL || -+ fixP->fx_r_type == BFD_RELOC_VTABLE_INHERIT || -+ fixP->fx_r_type == BFD_RELOC_VTABLE_ENTRY || -+ fixP->fx_r_type == BFD_RELOC_NIOS2_UJMP || -+ fixP->fx_r_type == BFD_RELOC_NIOS2_CJMP || -+ fixP->fx_r_type == BFD_RELOC_NIOS2_CALLR || -+ fixP->fx_r_type == BFD_RELOC_NIOS2_ALIGN || -+ fixP->fx_r_type == BFD_RELOC_NIOS2_GOT16 || -+ fixP->fx_r_type == BFD_RELOC_NIOS2_CALL16 || -+ fixP->fx_r_type == BFD_RELOC_NIOS2_GOTOFF_LO || -+ fixP->fx_r_type == BFD_RELOC_NIOS2_GOTOFF_HA || -+ fixP->fx_r_type == BFD_RELOC_NIOS2_TLS_GD16 || -+ fixP->fx_r_type == BFD_RELOC_NIOS2_TLS_LDM16 || -+ fixP->fx_r_type == BFD_RELOC_NIOS2_TLS_LDO16 || -+ fixP->fx_r_type == BFD_RELOC_NIOS2_TLS_IE16 || -+ fixP->fx_r_type == BFD_RELOC_NIOS2_TLS_LE16 || -+ fixP->fx_r_type == BFD_RELOC_NIOS2_GOTOFF || -+ fixP->fx_r_type == BFD_RELOC_NIOS2_TLS_DTPREL -+ /* Add other relocs here as we generate them. */ -+ )); -+ -+ -+ /* The value passed in valP can be the value of a fully -+ resolved expression, or it can be the value of a partially -+ resolved expression. In the former case, both fixP->fx_addsy -+ and fixP->fx_subsy are NULL, and fixP->fx_offset == *valP, and -+ we can fix up the instruction that fixP relates to. -+ In the latter case, one or both of fixP->fx_addsy and -+ fixP->fx_subsy are not NULL, and fixP->fx_offset may or may not -+ equal *valP. We don't need to check for fixP->fx_subsy being null -+ because the generic part of the assembler generates an error if -+ it is not an absolute symbol. */ -+ -+ if (fixP->fx_addsy != NULL) -+ { -+ fixP->fx_addnumber = fixP->fx_offset; -+ fixP->fx_done = 0; -+ -+ switch (fixP->fx_r_type) -+ { -+ case BFD_RELOC_NIOS2_TLS_GD16: -+ case BFD_RELOC_NIOS2_TLS_LDM16: -+ case BFD_RELOC_NIOS2_TLS_LDO16: -+ case BFD_RELOC_NIOS2_TLS_IE16: -+ case BFD_RELOC_NIOS2_TLS_LE16: -+ case BFD_RELOC_NIOS2_TLS_DTPMOD: -+ case BFD_RELOC_NIOS2_TLS_DTPREL: -+ case BFD_RELOC_NIOS2_TLS_TPREL: -+ S_SET_THREAD_LOCAL (fixP->fx_addsy); -+ break; -+ default: -+ break; -+ } -+ } -+ else -+ { -+ valueT value; -+ -+ char *buf; -+ reloc_howto_type *howto; -+ howto = bfd_reloc_type_lookup (stdoutput, fixP->fx_r_type); -+ -+ if (howto == NULL) -+ { -+ as_bad_where (fixP->fx_file, fixP->fx_line, -+ _("relocation is not supported")); -+ } -+ else -+ { -+ fixup += *valP; -+ -+ /* If this is a pc-relative relocation, we need to -+ subtract the current offset within the object file -+ FIXME : for some reason fixP->fx_pcrel isn't 1 when it should be -+ so I'm using the howto structure instead to determine this. */ -+ if (howto->pc_relative == 1) -+ fixup = fixup - (fixP->fx_frag->fr_address + fixP->fx_where + 4); -+ -+ -+ -+ /* Get the instruction to be fixed up. */ -+ buf = fixP->fx_frag->fr_literal + fixP->fx_where; -+ value = md_chars_to_number (buf, 4); -+ -+ /* What opcode is the instruction? This will determine -+ whether we check for overflow in immediate values -+ and what error message we get. */ -+ opcode = nios2_find_opcode_hash (value); -+ overflow_msg_type = opcode->overflow_msg; -+ -+ overflowed = nios2_check_overflow (fixup, howto); -+ -+ -+ if (overflowed) -+ { -+ unsigned int range_min; -+ unsigned int range_max; -+ unsigned int address; -+ switch (overflow_msg_type) -+ { -+ case call_target_overflow: -+ range_min = -+ ((fixP->fx_frag->fr_address + -+ fixP->fx_where) & 0xf0000000); -+ range_max = range_min + 0x0fffffff; -+ address = fixup | range_min; -+ -+ as_bad_where (fixP->fx_file, fixP->fx_line, -+ _(overflow_msgs[call_target_overflow]), -+ address, range_min, range_max); -+ break; -+ case branch_target_overflow: -+ as_bad_where (fixP->fx_file, fixP->fx_line, -+ _(overflow_msgs[branch_target_overflow]), -+ fixup, BYTE_B, BYTE_F); -+ break; -+ case address_offset_overflow: -+ as_bad_where (fixP->fx_file, fixP->fx_line, -+ _(overflow_msgs[address_offset_overflow]), -+ opcode->name, fixup, -32768, 32767); -+ break; -+ case signed_immed16_overflow: -+ as_bad_where (fixP->fx_file, fixP->fx_line, -+ _(overflow_msgs[signed_immed16_overflow]), -+ fixup, -32768, 32767); -+ break; -+ case unsigned_immed16_overflow: -+ as_bad_where (fixP->fx_file, fixP->fx_line, -+ _(overflow_msgs[unsigned_immed16_overflow]), -+ fixup, 0, 65535); -+ break; -+ case unsigned_immed5_overflow: -+ as_bad_where (fixP->fx_file, fixP->fx_line, -+ _(overflow_msgs[unsigned_immed5_overflow]), -+ fixup, 0, 31); -+ break; -+ case custom_opcode_overflow: -+ as_bad_where (fixP->fx_file, fixP->fx_line, -+ _(overflow_msgs[custom_opcode_overflow]), -+ fixup, 0, 255); -+ break; -+ default: -+ as_bad_where (fixP->fx_file, fixP->fx_line, -+ _ -+ ("unspecified overflow in immediate argument")); -+ break; -+ } -+ } -+ -+ -+ /* Apply the rightshift. */ -+ fixup = ((signed)fixup) >> howto->rightshift; -+ -+ /* Truncate the fixup to right size. */ -+ switch (fixP->fx_r_type) -+ { -+ case BFD_RELOC_NIOS2_HI16: -+ fixup = (fixup >> 16) & 0xFFFF; -+ break; -+ case BFD_RELOC_NIOS2_LO16: -+ fixup = fixup & 0xFFFF; -+ break; -+ case BFD_RELOC_NIOS2_HIADJ16: -+ fixup = ((fixup >> 16) & 0xFFFF) + ((fixup >> 15) & 0x01); -+ break; -+ default: -+ fixup = -+ (fixup << (32 - howto->bitsize)) >> (32 - howto->bitsize); -+ break; -+ } -+ -+ /* Fixup the instruction. */ -+ value = (value & ~howto->dst_mask) | (fixup << howto->bitpos); -+ md_number_to_chars (buf, value, 4); -+ } -+ -+ fixP->fx_done = 1; -+ } -+ -+ if (fixP->fx_r_type == BFD_RELOC_VTABLE_INHERIT) -+ { -+ fixP->fx_done = 0; -+ if (fixP->fx_addsy -+ && !S_IS_DEFINED (fixP->fx_addsy) && !S_IS_WEAK (fixP->fx_addsy)) -+ S_SET_WEAK (fixP->fx_addsy); -+ } -+ else if (fixP->fx_r_type == BFD_RELOC_VTABLE_ENTRY) -+ { -+ fixP->fx_done = 0; -+ } -+} -+ -+bfd_boolean -+nios2_check_overflow (valueT fixup, reloc_howto_type * howto) -+{ -+ /* Apply the rightshift before checking for overflow. */ -+ fixup = ((signed)fixup) >> howto->rightshift; -+ -+ /* Check for overflow - return TRUE if overflow, FALSE if not. */ -+ switch (howto->complain_on_overflow) -+ { -+ case complain_overflow_dont: -+ break; -+ case complain_overflow_bitfield: -+ if ((fixup >> howto->bitsize) != 0) -+ return TRUE; -+ break; -+ case complain_overflow_signed: -+ if ((fixup & 0x80000000) > 0) -+ { -+ /* Check for negative overflow. */ -+ if ((signed) fixup < ((signed) 0x80000000 >> howto->bitsize)) -+ return TRUE; -+ } -+ else -+ { -+ /* Check for positive overflow. */ -+ if (fixup >= ((unsigned) 1 << (howto->bitsize - 1))) -+ return TRUE; -+ } -+ break; -+ case complain_overflow_unsigned: -+ if ((fixup >> howto->bitsize) != 0) -+ return TRUE; -+ break; -+ default: -+ as_bad (_("error checking for overflow - broken assembler")); -+ break; -+ } -+ -+ return FALSE; -+} -+ -+/* Called just before the assembler exits. */ -+void -+md_end () -+{ -+ /* FIXME - not yet implemented */ -+} -+ -+/* Under ELF we need to default _GLOBAL_OFFSET_TABLE. -+ Otherwise we have no need to default values of symbols. */ -+ -+symbolS * -+md_undefined_symbol (char * name ATTRIBUTE_UNUSED) -+{ -+#ifdef OBJ_ELF -+ if (name[0] == '_' && name[1] == 'G' -+ && streq (name, GLOBAL_OFFSET_TABLE_NAME)) -+ { -+ if (!GOT_symbol) -+ { -+ if (symbol_find (name)) -+ as_bad ("GOT already in the symbol table"); -+ -+ GOT_symbol = symbol_new (name, undefined_section, -+ (valueT) 0, & zero_address_frag); -+ } -+ -+ return GOT_symbol; -+ } -+#endif -+ -+ return 0; -+} -+ -+ -+/* Creates a new nios2_insn_relocS and returns a pointer to it. */ -+nios2_insn_relocS * -+nios2_insn_reloc_new (bfd_reloc_code_real_type reloc_type, unsigned int pcrel) -+{ -+ nios2_insn_relocS *retval; -+ retval = (nios2_insn_relocS *) malloc (sizeof (nios2_insn_relocS)); -+ if (retval == NULL) -+ { -+ as_bad (_("can't create relocation")); -+ abort (); -+ } -+ -+ /* Fill out the fields with default values. */ -+ retval->reloc_next = NULL; -+ retval->reloc_type = reloc_type; -+ retval->reloc_pcrel = pcrel; -+ return retval; -+} -+ -+/* Frees up memory previously allocated by nios2_insn_reloc_new(). */ -+void -+nios2_insn_reloc_destroy (nios2_insn_relocS * reloc) -+{ -+ gas_assert (reloc != NULL); -+ free (reloc); -+} -+ -+/* The various nios2_assemble_* functions call this -+ function to generate an expression from a string representing an expression. -+ It then tries to evaluate the expression, and if it can, returns its value. -+ If not, it creates a new nios2_insn_relocS and stores the expression and -+ reloc_type for future use. */ -+unsigned long -+nios2_assemble_expression (const char *exprstr, -+ nios2_insn_infoS * insn, -+ nios2_insn_relocS * prev_reloc, -+ bfd_reloc_code_real_type reloc_type, -+ unsigned int pcrel) -+{ -+ nios2_insn_relocS *reloc; -+ char *saved_line_ptr; -+ unsigned short value; -+ int i; -+ -+ gas_assert (exprstr != NULL); -+ gas_assert (insn != NULL); -+ -+ /* Check for relocation operators. -+ Change the relocation type and advance the ptr to the start of -+ the expression proper. */ -+ for (i = 0; i < nios2_num_special_relocs; i++) -+ { -+ if (strstr (exprstr, nios2_special_reloc[i].string) != NULL) -+ { -+ reloc_type = nios2_special_reloc[i].reloc_type; -+ exprstr += strlen (nios2_special_reloc[i].string) + 1; -+ -+ /* %lo and %hiadj have different meanings for PC-relative -+ expressions. */ -+ if (pcrel) -+ { -+ if (reloc_type == BFD_RELOC_NIOS2_LO16) -+ reloc_type = BFD_RELOC_NIOS2_PCREL_LO; -+ if (reloc_type == BFD_RELOC_NIOS2_HIADJ16) -+ reloc_type = BFD_RELOC_NIOS2_PCREL_HA; -+ } -+ -+ break; -+ } -+ } -+ -+ /* We potentially have a relocation. */ -+ reloc = nios2_insn_reloc_new (reloc_type, pcrel); -+ if (prev_reloc != NULL) -+ prev_reloc->reloc_next = reloc; -+ else -+ insn->insn_reloc = reloc; -+ -+ /* Parse the expression string. */ -+ saved_line_ptr = input_line_pointer; -+ input_line_pointer = (char *) exprstr; -+ expression (&reloc->reloc_expression); -+ input_line_pointer = saved_line_ptr; -+ -+ /* This is redundant as the fixup will put this into -+ the instruction, but it is included here so that -+ self-test mode (-r) works. */ -+ value = 0; -+ if (nios2_mode == NIOS2_MODE_TEST) -+ { -+ if (reloc->reloc_expression.X_op == O_constant) -+ value = reloc->reloc_expression.X_add_number; -+ } -+ -+ return (unsigned long) value; -+} -+ -+/* The function consume_separate takes a pointer into a string -+ of instruction tokens (args) and a pointer into a string representing -+ the expected sequence of tokens and separators. It finds the first -+ instance of the character pointed to by separator in argStr, and -+ returns a pointer to the next element of argStr, which is the -+ following token in the sequence. */ -+char * -+nios2_consume_separator (char *argStr, const char *separator) -+{ -+ char *argPtr; -+ -+ /* If we have a opcode reg, expr(reg) type instruction, and -+ * we are separating the expr from the (reg), we find the last -+ * (, just in case the expression has brackets. */ -+ -+ if (*separator == '(') -+ argPtr = strrchr (argStr, *separator); -+ else -+ argPtr = strchr (argStr, *separator); -+ -+ if (argPtr != NULL) -+ *argPtr++ = 0; -+ else -+ as_bad (_("expecting %c near %s"), *separator, argStr); -+ return argPtr; -+} -+ -+/* The function consume_arg takes a pointer into a string -+ of instruction tokens (args) and a pointer into a string -+ representing the expected sequence of tokens and separators. -+ It checks whether the first argument in argStr is of the -+ expected type, throwing an error if it is not, and returns -+ the pointer argStr. */ -+char * -+nios2_consume_arg (char *argStr, const char *argType) -+{ -+ char *temp; -+ int regno = -1; -+ -+ switch (*argType) -+ { -+ case 'c': -+ if (strncmp (argStr, "ctl", strlen ("ctl")) != 0 -+ && strncmp (argStr, "cpuid", strlen ("cpuid")) != 0 -+ && strncmp (argStr, "status", strlen ("status")) != 0 -+ && strncmp (argStr, "estatus", strlen ("estatus")) != 0 -+ && strncmp (argStr, "bstatus", strlen ("bstatus")) != 0 -+ && strncmp (argStr, "ienable", strlen ("ienable")) != 0 -+ && strncmp (argStr, "ipending", strlen ("ipending")) != 0 -+ && strncmp (argStr, "exception", strlen ("exception")) != 0 -+ && strncmp (argStr, "pteaddr", strlen ("pteaddr")) != 0 -+ && strncmp (argStr, "tlbacc", strlen ("tlbacc")) != 0 -+ && strncmp (argStr, "tlbmisc", strlen ("tlbmisc")) != 0 -+ && strncmp (argStr, "fstatus", strlen ("fstatus")) != 0 -+ && strncmp (argStr, "config", strlen ("config")) != 0 -+ && strncmp (argStr, "mpubase", strlen ("mpubase")) != 0 -+ && strncmp (argStr, "mpuacc", strlen ("mpuacc")) != 0 -+ && strncmp (argStr, "badaddr", strlen ("badaddr")) != 0) -+ { -+ as_bad (_("expecting control register")); -+ } -+ break; -+ case 'd': -+ case 's': -+ case 't': -+ -+ /* We check to make sure we don't have a control register. */ -+ if (strncmp (argStr, "ctl", strlen ("ctl")) == 0 -+ || strncmp (argStr, "cpuid", strlen ("cpuid")) == 0 -+ || strncmp (argStr, "status", strlen ("status")) == 0 -+ || strncmp (argStr, "estatus", strlen ("estatus")) == 0 -+ || strncmp (argStr, "bstatus", strlen ("bstatus")) == 0 -+ || strncmp (argStr, "ienable", strlen ("ienable")) == 0 -+ || strncmp (argStr, "ipending", strlen ("ipending")) == 0 -+ || strncmp (argStr, "exception", strlen ("exception")) == 0 -+ || strncmp (argStr, "pteaddr", strlen ("pteaddr")) == 0 -+ || strncmp (argStr, "tlbacc", strlen ("tlbacc")) == 0 -+ || strncmp (argStr, "tlbmisc", strlen ("tlbmisc")) == 0 -+ || strncmp (argStr, "fstatus", strlen ("fstatus")) == 0 -+ || strncmp (argStr, "config", strlen ("config")) == 0 -+ || strncmp (argStr, "mpubase", strlen ("mpubase")) == 0 -+ || strncmp (argStr, "mpuacc", strlen ("mpuacc")) == 0 -+ || strncmp (argStr, "badaddr", strlen ("badaddr")) == 0) -+ { -+ as_bad (_("illegal use of control register")); -+ } -+ -+ /* And whether coprocessor registers are valid here. */ -+ if (nios2_coproc_reg (argStr) -+ && insn.insn_nios2_opcode->match != OP_MATCH_CUSTOM) -+ { -+ as_bad (_("illegal use of coprocessor register\n")); -+ } -+ -+ -+ /* Extract a register number if the register is of the -+ form r[0-9]+, if it is a normal register, set -+ regno to its number (0-31), else set regno to -1. */ -+ if (argStr[0] == 'r' && ISDIGIT (argStr[1])) -+ { -+ char *p = argStr; -+ -+ ++p; -+ regno = 0; -+ do -+ { -+ regno *= 10; -+ regno += *p - '0'; -+ ++p; -+ } -+ while (ISDIGIT (*p)); -+ } -+ else -+ regno = -1; -+ -+ /* And whether we are using at. */ -+ if (!nios2_as_options.noat -+ && (regno == 1 -+ || strncmp (argStr, "at", strlen ("at")) == 0)) -+ as_warn (_("Register at (r1) can sometimes be corrupted by assembler " -+ "optimizations.\n" -+ "Use .set noat to turn off those optimizations (and this " -+ "warning).")); -+ -+ /* And whether we are using oci registers. */ -+ if (!nios2_as_options.nobreak -+ && (regno == 25 -+ || strncmp (argStr, "bt", strlen ("bt")) == 0)) -+ as_warn (_("The debugger will corrupt bt (r25). If you don't need to " -+ "debug this\n" -+ "code then use .set nobreak to turn off this warning.")); -+ -+ if (!nios2_as_options.nobreak -+ && (regno == 30 -+ || strncmp (argStr, "ba", strlen ("ba")) == 0)) -+ as_warn (_("The debugger will corrupt ba (r30). If you don't need to " -+ "debug this\n" -+ "code then use .set nobreak to turn off this warning.")); -+ break; -+ case 'i': -+ case 'u': -+ if (*argStr == '%') -+ { -+ if (strstr (argStr, "%hi(") || strstr (argStr, "%lo(") -+ || strstr (argStr, "%hiadj(") || strstr (argStr, "%gprel(") -+ || strstr (argStr, "%got(") || strstr (argStr, "%call(") -+ || strstr (argStr, "%gotoff_lo(") -+ || strstr (argStr, "%gotoff_hiadj(") -+ || strstr (argStr, "%tls_gd(") || strstr (argStr, "%tls_ldm(") -+ || strstr (argStr, "%tls_ldo(") || strstr (argStr, "%tls_ie(") -+ || strstr (argStr, "%tls_le(") || strstr (argStr, "%gotoff(")) -+ { -+ /* We zap the brackets because we don't want them confused with -+ separators. */ -+ temp = strchr (argStr, '('); -+ if (temp != NULL) -+ *temp = ' '; -+ temp = strchr (argStr, ')'); -+ if (temp != NULL) -+ *temp = ' '; -+ } -+ else -+ as_bad (_("badly formed expression near %s"), argStr); -+ } -+ break; -+ case 'm': -+ case 'j': -+ case 'k': -+ case 'l': -+ case 'b': -+ /* We can't have %hi, %lo or %hiadj here. */ -+ if (*argStr == '%') -+ as_bad (_("badly formed expression near %s"), argStr); -+ break; -+ default: -+ break; -+ } -+ -+#if 0 -+ /* ??? SPR:173865 This is actually supported by the HW but the documentation -+ is a bit funny. -+ The compiler really want the extra register, so let it have it! */ -+ /* checks for jmp 31 */ -+ /* TODO: move test that insn is jmp to somewhere better.*/ -+ if ((strncmp (insn.insn_nios2_opcode->name, "jmp", strlen ("jmp")) == 0) -+ && (regno == 31 -+ || strncmp (argStr, "ra", strlen ("ra")) == 0)) -+ as_bad (_("It is illegal to jump to the address contained in register ra " -+ "(r31). " -+ "To return from subroutines called by call or callr, use ret " -+ "instead of jmp.")); -+#endif -+ -+ return argStr; -+} -+ -+/* The principal argument parsing function which takes a string -+ representing the instruction arguments, and extracts the argument -+ tokens. */ -+void -+nios2_parse_args (char *argStr, const char *parseStr, char **parsedArgs) -+{ -+ char *p; -+ char *end = NULL; -+ int i; -+ p = argStr; -+ i = 0; -+ bfd_boolean terminate = FALSE; -+ -+ /* This rest of this function is it too fragile and it mostly works, -+ therefore special case this one. */ -+ if (*parseStr == 0 && argStr != 0) -+ { -+ as_bad (_("too many arguments")); -+ parsedArgs[0] = NULL; -+ return; -+ } -+ -+ -+ while (p != NULL && !terminate && i < NIOS2_MAX_INSN_TOKENS) -+ { -+ parsedArgs[i] = nios2_consume_arg (p, parseStr); -+ ++parseStr; -+ if (*parseStr != '\0') -+ { -+ p = nios2_consume_separator (p, parseStr); -+ ++parseStr; -+ } -+ else -+ { -+ /* Check that the argument string has no trailing arguments. */ -+ /* If we've got a %lo etc relocation, we've zapped the brackets with -+ spaces. */ -+ if (strstr (p, "%lo") == p || strstr (p, "%hi") == p -+ || strstr (p, "%hiadj") == p || strstr (p, "%gprel") == p -+ || strstr (p, "%got") == p || strstr (argStr, "%call") -+ || strstr (p, "%gotoff_lo") == p -+ || strstr (p, "%gotoff_hiadj") == p -+ || strstr (p, "%tls_gd") == p || strstr (p, "%tls_ldm") == p -+ || strstr (p, "%tls_ldo") == p || strstr (p, "%tls_ie") == p -+ || strstr (p, "%tls_le") == p || strstr (p, "%gotoff") == p) -+ end = strpbrk (p, ","); -+ else -+ end = strpbrk (p, " ,"); -+ -+ if (end != NULL) -+ as_bad (_("too many arguments")); -+ } -+ -+ if (*parseStr == '\0' || (p != NULL && *p == '\0')) -+ terminate = TRUE; -+ ++i; -+ } -+ -+ parsedArgs[i] = NULL; -+ -+ if (*parseStr != '\0' && insn.insn_nios2_opcode->match != OP_MATCH_BREAK) -+ as_bad (_("missing argument")); -+ -+} -+ -+ -+/* Checks whether the register name is a coprocessor -+ register - returns TRUE if it is, FALSE otherwise. */ -+static bfd_boolean -+nios2_coproc_reg (const char *reg_name) -+{ -+ gas_assert (reg_name != NULL); -+ -+ /* Check that we do have a valid register name and that it is a -+ coprocessor register. -+ It must begin with c, not be a control register, and be a valid -+ register name. */ -+ -+ if (strncmp (reg_name, "c", 1) == 0 && -+ strncmp (reg_name, "ctl", strlen ("ctl")) != 0 && -+ hash_find (nios2_reg_hash, reg_name) != NULL) -+ return TRUE; -+ else -+ return FALSE; -+} -+ -+ -+/********************************************************************* -+ Argument assemble functions -+ -+ Description : All take an instruction argument string, and a pointer -+ to an instruction opcode. Upon return the insn_opcode -+ has the relevant fields filled in to represent the arg -+ string. The return value is NULL if successful, or -+ an error message if an error was detected -+ *********************************************************************/ -+ -+/* Assembles register arguments "dst, src1, src2". */ -+void -+nios2_assemble_args_dst (nios2_insn_infoS * insn_info) -+{ -+ struct nios2_reg *dst, *src1, *src2; -+ -+ if (insn_info->insn_tokens[1] != NULL && -+ insn_info->insn_tokens[2] != NULL && insn_info->insn_tokens[3] != NULL) -+ { -+ dst = -+ (struct nios2_reg *) hash_find (nios2_reg_hash, -+ insn_info->insn_tokens[1]); -+ src1 = -+ (struct nios2_reg *) hash_find (nios2_reg_hash, -+ insn_info->insn_tokens[2]); -+ src2 = -+ (struct nios2_reg *) hash_find (nios2_reg_hash, -+ insn_info->insn_tokens[3]); -+ -+ if (dst == NULL) -+ as_bad (_("unknown register %s"), insn_info->insn_tokens[1]); -+ else -+ SET_INSN_FIELD (RRD, insn_info->insn_code, dst->index); -+ -+ if (src1 == NULL) -+ as_bad (_("unknown register %s"), insn_info->insn_tokens[2]); -+ else -+ SET_INSN_FIELD (RRS, insn_info->insn_code, src1->index); -+ -+ if (src2 == NULL) -+ as_bad (_("unknown register %s"), insn_info->insn_tokens[3]); -+ else -+ SET_INSN_FIELD (RRT, insn_info->insn_code, src2->index); -+ -+ -+ NIOS2_CHECK_ASSEMBLY (insn_info->insn_code, insn_info->insn_tokens[4]); -+ } -+} -+ -+ -+/* Assembles arguments successfully parsed by nios2_parse_args_tsi. */ -+void -+nios2_assemble_args_tsi (nios2_insn_infoS * insn_info) -+{ -+ struct nios2_reg *dst, *src1; -+ unsigned int src2; -+ -+ if (insn_info->insn_tokens[1] != NULL && -+ insn_info->insn_tokens[2] != NULL && insn_info->insn_tokens[3] != NULL) -+ { -+ dst = -+ (struct nios2_reg *) hash_find (nios2_reg_hash, -+ insn_info->insn_tokens[1]); -+ src1 = -+ (struct nios2_reg *) hash_find (nios2_reg_hash, -+ insn_info->insn_tokens[2]); -+ src2 = -+ nios2_assemble_expression (insn_info->insn_tokens[3], insn_info, -+ insn_info->insn_reloc, BFD_RELOC_NIOS2_S16, -+ 0); -+ -+ if (dst == NULL) -+ as_bad (_("unknown register %s"), insn_info->insn_tokens[1]); -+ else -+ SET_INSN_FIELD (IRT, insn_info->insn_code, dst->index); -+ -+ if (src1 == NULL) -+ as_bad (_("unknown register %s"), insn_info->insn_tokens[2]); -+ else -+ SET_INSN_FIELD (IRS, insn_info->insn_code, src1->index); -+ -+ SET_INSN_FIELD (IMM16, insn_info->insn_code, src2); -+ NIOS2_CHECK_ASSEMBLY (insn_info->insn_code, insn_info->insn_tokens[4]); -+ -+ SET_INSN_FIELD (IMM16, insn_info->insn_code, 0); -+ } -+} -+ -+ -+/* Assembles args successfully parsed by nios2_parse_args_tsu. */ -+void -+nios2_assemble_args_tsu (nios2_insn_infoS * insn_info) -+{ -+ struct nios2_reg *dst, *src1; -+ unsigned int src2; -+ -+ if (insn_info->insn_tokens[1] != NULL && -+ insn_info->insn_tokens[2] != NULL && insn_info->insn_tokens[3] != NULL) -+ { -+ dst = -+ (struct nios2_reg *) hash_find (nios2_reg_hash, -+ insn_info->insn_tokens[1]); -+ src1 = -+ (struct nios2_reg *) hash_find (nios2_reg_hash, -+ insn_info->insn_tokens[2]); -+ src2 = -+ nios2_assemble_expression (insn_info->insn_tokens[3], insn_info, -+ insn_info->insn_reloc, BFD_RELOC_NIOS2_U16, -+ 0); -+ -+ if (dst == NULL) -+ as_bad (_("unknown register %s"), insn_info->insn_tokens[1]); -+ else -+ SET_INSN_FIELD (IRT, insn_info->insn_code, dst->index); -+ -+ if (src1 == NULL) -+ as_bad (_("unknown register %s"), insn_info->insn_tokens[2]); -+ else -+ SET_INSN_FIELD (IRS, insn_info->insn_code, src1->index); -+ -+ SET_INSN_FIELD (IMM16, insn_info->insn_code, src2); -+ NIOS2_CHECK_ASSEMBLY (insn_info->insn_code, insn_info->insn_tokens[4]); -+ -+ SET_INSN_FIELD (IMM16, insn_info->insn_code, 0); -+ } -+} -+ -+ -+/* Assembles args successfully parsed by nios2_parse_args_sti. */ -+void -+nios2_assemble_args_sto (nios2_insn_infoS * insn_info) -+{ -+ struct nios2_reg *dst, *src1; -+ unsigned int src2; -+ -+ if (insn_info->insn_tokens[1] != NULL && -+ insn_info->insn_tokens[2] != NULL && insn_info->insn_tokens[3] != NULL) -+ { -+ dst = -+ (struct nios2_reg *) hash_find (nios2_reg_hash, -+ insn_info->insn_tokens[1]); -+ src1 = -+ (struct nios2_reg *) hash_find (nios2_reg_hash, -+ insn_info->insn_tokens[2]); -+ src2 = -+ nios2_assemble_expression (insn_info->insn_tokens[3], insn_info, -+ insn_info->insn_reloc, BFD_RELOC_16_PCREL, -+ 1); -+ -+ if (dst == NULL) -+ as_bad (_("unknown register %s"), insn_info->insn_tokens[1]); -+ else -+ SET_INSN_FIELD (IRS, insn_info->insn_code, dst->index); -+ -+ if (src1 == NULL) -+ as_bad (_("unknown register %s"), insn_info->insn_tokens[2]); -+ else -+ SET_INSN_FIELD (IRT, insn_info->insn_code, src1->index); -+ -+ SET_INSN_FIELD (IMM16, insn_info->insn_code, src2); -+ NIOS2_CHECK_ASSEMBLY (insn_info->insn_code, insn_info->insn_tokens[4]); -+ -+ SET_INSN_FIELD (IMM16, insn_info->insn_code, 0); -+ } -+} -+ -+ -+void -+nios2_assemble_args_o (nios2_insn_infoS * insn_info) -+{ -+ unsigned long immed; -+ -+ if (insn_info->insn_tokens[1] != NULL) -+ { -+ immed = -+ nios2_assemble_expression (insn_info->insn_tokens[1], insn_info, -+ insn_info->insn_reloc, BFD_RELOC_16_PCREL, -+ 1); -+ SET_INSN_FIELD (IMM16, insn_info->insn_code, immed); -+ -+ NIOS2_CHECK_ASSEMBLY (insn_info->insn_code, insn_info->insn_tokens[2]); -+ -+ SET_INSN_FIELD (IMM16, insn_info->insn_code, 0); -+ } -+} -+ -+ -+void -+nios2_assemble_args_is (nios2_insn_infoS * insn_info) -+{ -+ struct nios2_reg *addr_src; -+ unsigned long immed; -+ -+ if (insn_info->insn_tokens[1] != NULL && insn_info->insn_tokens[2] != NULL) -+ { -+ addr_src = -+ (struct nios2_reg *) hash_find (nios2_reg_hash, -+ insn_info->insn_tokens[2]); -+ -+ immed = -+ nios2_assemble_expression (insn_info->insn_tokens[1], insn_info, -+ insn_info->insn_reloc, BFD_RELOC_NIOS2_S16, -+ 0); -+ -+ SET_INSN_FIELD (IMM16, insn_info->insn_code, immed); -+ -+ if (addr_src == NULL) -+ as_bad (_("unknown base register %s"), insn_info->insn_tokens[2]); -+ else -+ SET_INSN_FIELD (RRS, insn_info->insn_code, addr_src->index); -+ -+ NIOS2_CHECK_ASSEMBLY (insn_info->insn_code, insn_info->insn_tokens[3]); -+ -+ SET_INSN_FIELD (IMM16, insn_info->insn_code, 0); -+ } -+} -+ -+ -+void -+nios2_assemble_args_m (nios2_insn_infoS * insn_info) -+{ -+ unsigned long immed; -+ if (insn_info->insn_tokens[1] != NULL) -+ { -+ immed = -+ nios2_assemble_expression (insn_info->insn_tokens[1], insn_info, -+ insn_info->insn_reloc, -+ BFD_RELOC_NIOS2_CALL26, 0); -+ -+ SET_INSN_FIELD (IMM26, insn_info->insn_code, immed); -+ -+ NIOS2_CHECK_ASSEMBLY (insn_info->insn_code, insn_info->insn_tokens[2]); -+ -+ SET_INSN_FIELD (IMM26, insn_info->insn_code, 0); -+ } -+} -+ -+ -+void -+nios2_assemble_args_s (nios2_insn_infoS * insn_info) -+{ -+ struct nios2_reg *src; -+ -+ if (insn_info->insn_tokens[1] != NULL) -+ { -+ src = -+ (struct nios2_reg *) hash_find (nios2_reg_hash, -+ insn_info->insn_tokens[1]); -+ -+ if (src == NULL) -+ as_bad (_("unknown register %s"), insn_info->insn_tokens[1]); -+ else -+ SET_INSN_FIELD (RRS, insn_info->insn_code, src->index); -+ -+ NIOS2_CHECK_ASSEMBLY (insn_info->insn_code, insn_info->insn_tokens[2]); -+ } -+} -+ -+ -+void -+nios2_assemble_args_tis (nios2_insn_infoS * insn_info) -+{ -+ struct nios2_reg *addr_src, *dst; -+ unsigned long immed; -+ -+ if (insn_info->insn_tokens[1] != NULL && -+ insn_info->insn_tokens[2] != NULL && insn_info->insn_tokens[3] != NULL) -+ { -+ -+ dst = -+ (struct nios2_reg *) hash_find (nios2_reg_hash, -+ insn_info->insn_tokens[1]); -+ addr_src = -+ (struct nios2_reg *) hash_find (nios2_reg_hash, -+ insn_info->insn_tokens[3]); -+ immed = -+ nios2_assemble_expression (insn_info->insn_tokens[2], insn_info, -+ insn_info->insn_reloc, BFD_RELOC_NIOS2_S16, -+ 0); -+ -+ -+ if (addr_src == NULL) -+ as_bad (_("unknown register %s"), insn_info->insn_tokens[3]); -+ else -+ SET_INSN_FIELD (RRS, insn_info->insn_code, addr_src->index); -+ -+ if (dst == NULL) -+ as_bad (_("unknown register %s"), insn_info->insn_tokens[1]); -+ else -+ SET_INSN_FIELD (RRT, insn_info->insn_code, dst->index); -+ -+ SET_INSN_FIELD (IMM16, insn_info->insn_code, immed); -+ -+ NIOS2_CHECK_ASSEMBLY (insn_info->insn_code, insn_info->insn_tokens[4]); -+ -+ SET_INSN_FIELD (IMM16, insn_info->insn_code, 0); -+ } -+} -+ -+ -+/* Assemble rdctl dst, ctl. */ -+void -+nios2_assemble_args_dc (nios2_insn_infoS * insn_info) -+{ -+ struct nios2_reg *dst, *ctl; -+ -+ if (insn_info->insn_tokens[1] != NULL && insn_info->insn_tokens[2] != NULL) -+ { -+ ctl = -+ (struct nios2_reg *) hash_find (nios2_reg_hash, -+ insn_info->insn_tokens[2]); -+ dst = -+ (struct nios2_reg *) hash_find (nios2_reg_hash, -+ insn_info->insn_tokens[1]); -+ -+ if (ctl == NULL) -+ as_bad (_("unknown register %s"), insn_info->insn_tokens[1]); -+ else -+ SET_INSN_FIELD (RCTL, insn_info->insn_code, ctl->index); -+ -+ if (dst == NULL) -+ as_bad (_("unknown register %s"), insn_info->insn_tokens[2]); -+ else -+ SET_INSN_FIELD (RRD, insn_info->insn_code, dst->index); -+ -+ NIOS2_CHECK_ASSEMBLY (insn_info->insn_code, insn_info->insn_tokens[3]); -+ } -+} -+ -+ -+/* Assemble wrctl ctl, src. */ -+void -+nios2_assemble_args_cs (nios2_insn_infoS * insn_info) -+{ -+ struct nios2_reg *src, *ctl; -+ -+ if (insn_info->insn_tokens[1] != NULL && insn_info->insn_tokens[2] != NULL) -+ { -+ ctl = -+ (struct nios2_reg *) hash_find (nios2_reg_hash, -+ insn_info->insn_tokens[1]); -+ src = -+ (struct nios2_reg *) hash_find (nios2_reg_hash, -+ insn_info->insn_tokens[2]); -+ -+ if (ctl == NULL) -+ as_bad (_("unknown register %s"), insn_info->insn_tokens[1]); -+ else if (ctl->index == 4) -+ as_bad (_("ipending control register (ctl4) is read-only\n")); -+ else -+ SET_INSN_FIELD (RCTL, insn_info->insn_code, ctl->index); -+ -+ if (src == NULL) -+ as_bad (_("unknown register %s"), insn_info->insn_tokens[2]); -+ else -+ SET_INSN_FIELD (RRS, insn_info->insn_code, src->index); -+ -+ NIOS2_CHECK_ASSEMBLY (insn_info->insn_code, insn_info->insn_tokens[3]); -+ } -+} -+ -+ -+ -+void -+nios2_assemble_args_ldst (nios2_insn_infoS * insn_info) -+{ -+ struct nios2_reg *dst, *src1, *src2; -+ unsigned long custom_n; -+ -+ if (insn_info->insn_tokens[1] != NULL && -+ insn_info->insn_tokens[2] != NULL && -+ insn_info->insn_tokens[3] != NULL && insn_info->insn_tokens[4] != NULL) -+ { -+#if 0 /* ??? Unused/half commented out code */ -+ char *end_p; -+ /* custom_n = nios2_strtoul(insn_info->insn_tokens[1], &end_p); */ -+#endif -+ custom_n = -+ nios2_assemble_expression (insn_info->insn_tokens[1], insn_info, -+ insn_info->insn_reloc, -+ BFD_RELOC_NIOS2_IMM8, 0); -+ -+ dst = -+ (struct nios2_reg *) hash_find (nios2_reg_hash, -+ insn_info->insn_tokens[2]); -+ src1 = -+ (struct nios2_reg *) hash_find (nios2_reg_hash, -+ insn_info->insn_tokens[3]); -+ src2 = -+ (struct nios2_reg *) hash_find (nios2_reg_hash, -+ insn_info->insn_tokens[4]); -+ -+ SET_INSN_FIELD (CUSTOM_N, insn_info->insn_code, custom_n); -+ -+ if (dst == NULL) -+ as_bad (_("unknown register %s"), insn_info->insn_tokens[2]); -+ else -+ SET_INSN_FIELD (RRD, insn_info->insn_code, dst->index); -+ -+ if (src1 == NULL) -+ as_bad (_("unknown register %s"), insn_info->insn_tokens[3]); -+ else -+ SET_INSN_FIELD (RRS, insn_info->insn_code, src1->index); -+ -+ if (src2 == NULL) -+ as_bad (_("unknown register %s"), insn_info->insn_tokens[4]); -+ else -+ SET_INSN_FIELD (RRT, insn_info->insn_code, src2->index); -+ -+ /* Set or clear the bits to indicate whether coprocessor registers are -+ used. */ -+ if (nios2_coproc_reg (insn_info->insn_tokens[2])) -+ SET_INSN_FIELD (CUSTOM_C, insn_info->insn_code, 0); -+ else -+ SET_INSN_FIELD (CUSTOM_C, insn_info->insn_code, 1); -+ -+ if (nios2_coproc_reg (insn_info->insn_tokens[3])) -+ SET_INSN_FIELD (CUSTOM_A, insn_info->insn_code, 0); -+ else -+ SET_INSN_FIELD (CUSTOM_A, insn_info->insn_code, 1); -+ -+ if (nios2_coproc_reg (insn_info->insn_tokens[4])) -+ SET_INSN_FIELD (CUSTOM_B, insn_info->insn_code, 0); -+ else -+ SET_INSN_FIELD (CUSTOM_B, insn_info->insn_code, 1); -+ -+ -+ NIOS2_CHECK_ASSEMBLY (insn_info->insn_code, insn_info->insn_tokens[5]); -+ } -+} -+ -+ -+void -+nios2_assemble_args_none (nios2_insn_infoS * insn_info ATTRIBUTE_UNUSED) -+{ -+ /* Nothing to do. */ -+} -+ -+ -+void -+nios2_assemble_args_dsj (nios2_insn_infoS * insn_info) -+{ -+ struct nios2_reg *dst, *src1; -+ unsigned int src2; -+ -+ if (insn_info->insn_tokens[1] != NULL && -+ insn_info->insn_tokens[2] != NULL && insn_info->insn_tokens[3] != NULL) -+ { -+ dst = -+ (struct nios2_reg *) hash_find (nios2_reg_hash, -+ insn_info->insn_tokens[1]); -+ src1 = -+ (struct nios2_reg *) hash_find (nios2_reg_hash, -+ insn_info->insn_tokens[2]); -+ -+ /* A 5-bit constant expression. */ -+ src2 = -+ nios2_assemble_expression (insn_info->insn_tokens[3], insn_info, -+ insn_info->insn_reloc, -+ BFD_RELOC_NIOS2_IMM5, 0); -+ -+ if (dst == NULL) -+ as_bad (_("unknown register %s"), insn_info->insn_tokens[1]); -+ else -+ SET_INSN_FIELD (RRD, insn_info->insn_code, dst->index); -+ -+ if (src1 == NULL) -+ as_bad (_("unknown register %s"), insn_info->insn_tokens[2]); -+ else -+ SET_INSN_FIELD (RRS, insn_info->insn_code, src1->index); -+ -+ SET_INSN_FIELD (IMM5, insn_info->insn_code, src2); -+ -+ NIOS2_CHECK_ASSEMBLY (insn_info->insn_code, insn_info->insn_tokens[4]); -+ -+ SET_INSN_FIELD (IMM5, insn_info->insn_code, 0); -+ } -+} -+ -+ -+/* Assembles register arguments "dst". */ -+void -+nios2_assemble_args_d (nios2_insn_infoS * insn_info) -+{ -+ struct nios2_reg *dst; -+ -+ if (insn_info->insn_tokens[1] != NULL) -+ { -+ dst = -+ (struct nios2_reg *) hash_find (nios2_reg_hash, -+ insn_info->insn_tokens[1]); -+ -+ if (dst == NULL) -+ as_bad (_("unknown register %s"), insn_info->insn_tokens[1]); -+ else -+ SET_INSN_FIELD (RRD, insn_info->insn_code, dst->index); -+ -+ NIOS2_CHECK_ASSEMBLY (insn_info->insn_code, insn_info->insn_tokens[2]); -+ } -+} -+ -+/* Assemble break op. */ -+void -+nios2_assemble_args_b (nios2_insn_infoS * insn_info) -+{ -+ unsigned int imm5 = 0; -+ -+ if (insn_info->insn_tokens[1] != NULL) -+ { -+ /* A 5-bit constant expression. */ -+ imm5 = -+ nios2_assemble_expression (insn_info->insn_tokens[1], insn_info, -+ insn_info->insn_reloc, -+ BFD_RELOC_NIOS2_IMM5, 0); -+ -+ SET_INSN_FIELD (TRAP_IMM5, insn_info->insn_code, imm5); -+ -+ NIOS2_CHECK_ASSEMBLY (insn_info->insn_code, insn_info->insn_tokens[2]); -+ } -+ -+ SET_INSN_FIELD (TRAP_IMM5, insn_info->insn_code, imm5); -+ -+ NIOS2_CHECK_ASSEMBLY (insn_info->insn_code, insn_info->insn_tokens[2]); -+} -+ -+/* Machine-dependent assembler directive handling follows */ -+ -+/* .set sets assembler options eg noat/at and is also used -+ to set symbol values (.equ, .equiv ). */ -+void -+s_nios2_set (int equiv) -+{ -+ char *directive = input_line_pointer; -+ char delim = get_symbol_end (); -+ char *endline; -+ endline = input_line_pointer; -+ *endline = delim; -+ -+ /* We only want to handle ".set XXX" if the -+ user has tried ".set XXX, YYY" they are not -+ trying a directive. This prevents -+ us from polluting the name space. */ -+ -+ SKIP_WHITESPACE (); -+ -+ if (is_end_of_line[(unsigned char) *input_line_pointer]) -+ { -+ bfd_boolean done = FALSE; -+ *endline = 0; -+ -+ if (!strcmp (directive, "noat")) -+ { -+ done = TRUE; -+ nios2_as_options.noat = TRUE; -+ } -+ -+ if (!strcmp (directive, "at")) -+ { -+ done = TRUE; -+ nios2_as_options.noat = FALSE; -+ } -+ -+ if (!strcmp (directive, "nobreak")) -+ { -+ done = TRUE; -+ nios2_as_options.nobreak = TRUE; -+ } -+ -+ if (!strcmp (directive, "break")) -+ { -+ done = TRUE; -+ nios2_as_options.nobreak = FALSE; -+ } -+ -+ if (!strcmp (directive, "norelax")) -+ { -+ done = TRUE; -+ nios2_as_options.relax = relax_none; -+ } -+ else if (!strcmp (directive, "relaxsection")) -+ { -+ done = TRUE; -+ nios2_as_options.relax = relax_section; -+ } -+ else if (!strcmp (directive, "relaxall")) -+ { -+ done = TRUE; -+ nios2_as_options.relax = relax_all; -+ } -+ -+ -+ if (done) -+ { -+ *endline = delim; -+ demand_empty_rest_of_line (); -+ return; -+ } -+ } -+ -+ -+ /* If we fall through to here, either we have ".set XXX, YYY" -+ or we have ".set XXX" where XXX is unknown or we have -+ a syntax error. */ -+ input_line_pointer = directive; -+ *endline = delim; -+ s_set (equiv); -+} -+ -+/* nop fill pattern for text section. */ -+static char const nop[4] = { 0x3a, 0x88, 0x01, 0x00 }; -+ -+/* nios2_frob_label() is called when after a label is recognized. */ -+ -+void -+nios2_frob_label (symbolS * lab) -+{ -+ /* Update the label's address with the current output pointer. */ -+ symbol_set_frag (lab, frag_now); -+ S_SET_VALUE (lab, (valueT) frag_now_fix ()); -+ -+ /* Record this label for future adjustment after we find out what -+ kind of data it references, and the required alignment therewith. */ -+ nios2_last_label = lab; -+} -+ -+ -+ -+/* Hook into cons for auto-alignment. */ -+ -+void -+nios2_cons_align (int size) -+{ -+ int log_size; -+ const char *pfill = NULL; -+ -+ log_size = 0; -+ while ((size >>= 1) != 0) -+ ++log_size; -+ -+ if (subseg_text_p (now_seg)) -+ { -+ pfill = (const char *) &nop; -+ } -+ else -+ pfill = NULL; -+ -+ if (nios2_auto_align_on) -+ nios2_align (log_size, pfill, NULL); -+ -+ nios2_last_label = NULL; -+} -+ -+static void -+s_nios2_sdata (int ignore ATTRIBUTE_UNUSED) -+{ -+ int temp; -+ -+ temp = get_absolute_expression (); -+ subseg_new (".sdata", 0); -+ demand_empty_rest_of_line (); -+} -+ -+/* Map 's' to SHF_NIOS2_GPREL. */ -+/* This is from the Alpha code tc-alpha.c. */ -+int -+nios2_elf_section_letter (int letter, char **ptr_msg) -+{ -+ if (letter == 's') -+ return SHF_NIOS2_GPREL; -+ -+ *ptr_msg = _("Bad .section directive: want a,s,w,x,M,S,G,T in string"); -+ return 0; -+} -+ -+/* Map SHF_ALPHA_GPREL to SEC_SMALL_DATA. */ -+/* This is from the Alpha code tc-alpha.c. */ -+flagword -+nios2_elf_section_flags (flagword flags, int attr, int type ATTRIBUTE_UNUSED) -+{ -+ if (attr & SHF_NIOS2_GPREL) -+ flags |= SEC_SMALL_DATA; -+ return flags; -+} -+ -+/* Explicitly unaligned cons. */ -+ -+static void -+s_nios2_ucons (int nbytes) -+{ -+ int hold; -+ hold = nios2_auto_align_on; -+ nios2_auto_align_on = 0; -+ cons (nbytes); -+ nios2_auto_align_on = hold; -+} -+ -+static int nios2_tls_ldo_reloc; -+ -+void -+nios2_cons (expressionS *exp, int size) -+{ -+ /* Handle %tls_ldo(...) */ -+ -+ nios2_tls_ldo_reloc = 0; -+ -+ SKIP_WHITESPACE (); -+ if (input_line_pointer[0] == '%') -+ { -+ if (strncmp (input_line_pointer + 1, "tls_ldo", 7) == 0) -+ { -+ if (size != 4) -+ as_bad (_("Illegal operands: %%tls_ldo in %d-byte data field"), -+ size); -+ else -+ { -+ input_line_pointer += 8; -+ nios2_tls_ldo_reloc = 1; -+ } -+ } -+ if (nios2_tls_ldo_reloc) -+ { -+ SKIP_WHITESPACE (); -+ if (input_line_pointer[0] != '(') -+ as_bad (_("Illegal operands: %%tls_ldo requires arguments in ()")); -+ else -+ { -+ int c; -+ char *end = ++input_line_pointer; -+ int npar = 0; -+ -+ while (! is_end_of_line[(c = *end)]) -+ { -+ if (c == '(') -+ npar++; -+ else if (c == ')') -+ { -+ if (!npar) -+ break; -+ npar--; -+ } -+ end++; -+ } -+ -+ if (c != ')') -+ as_bad (_("Illegal operands: %%tls_ldo requires arguments in ()")); -+ else -+ { -+ *end = '\0'; -+ expression (exp); -+ *end = c; -+ if (input_line_pointer != end) -+ as_bad (_("Illegal operands: %%tls_ldo requires arguments in ()")); -+ else -+ { -+ input_line_pointer++; -+ SKIP_WHITESPACE (); -+ c = *input_line_pointer; -+ if (! is_end_of_line[c] && c != ',') -+ as_bad (_("Illegal operands: garbage after %%tls_ldo()")); -+ } -+ } -+ } -+ } -+ } -+ if (!nios2_tls_ldo_reloc) -+ expression (exp); -+} -+ -+void -+nios2_cons_fix_new (fragS *frag, int where, unsigned int nbytes, -+ expressionS *exp) -+{ -+ bfd_reloc_code_real_type r; -+ -+ r = (nbytes == 1 ? BFD_RELOC_8 : -+ (nbytes == 2 ? BFD_RELOC_16 : -+ (nbytes == 4 ? BFD_RELOC_32 : BFD_RELOC_64))); -+ -+ if (nios2_tls_ldo_reloc) -+ r = BFD_RELOC_NIOS2_TLS_DTPREL; -+ -+ fix_new_exp (frag, where, (int) nbytes, exp, 0, r); -+ nios2_tls_ldo_reloc = 0; -+} -+ -+/* Handles all machine-dependent alignment needs. */ -+static void -+nios2_align (int log_size, const char *pfill, symbolS * label) -+{ -+ int align; -+ long max_alignment = 15; -+ -+ /* The front end is prone to changing segments out from under us -+ temporarily when -g is in effect. */ -+ int switched_seg_p = (nios2_current_align_seg != now_seg); -+ -+ align = log_size; -+ if (align > max_alignment) -+ { -+ align = max_alignment; -+ as_bad (_("Alignment too large: %d. assumed"), align); -+ } -+ else if (align < 0) -+ { -+ as_warn (_("Alignment negative: 0 assumed")); -+ align = 0; -+ } -+ -+ if (align != 0) -+ { -+ if (subseg_text_p (now_seg) && align >= 2) -+ { -+ /* First, make sure we're on a four-byte boundary, in case -+ someone has been putting .byte values the text section. */ -+ if (nios2_current_align < 2 || switched_seg_p) -+ frag_align (2, 0, 0); -+ -+ /* Now fill in the alignment pattern. */ -+ if (pfill != NULL) -+ frag_align_pattern (align, pfill, sizeof nop, 0); -+ else -+ frag_align (align, 0, 0); -+ } -+ else -+ { -+ frag_align (align, 0, 0); -+ } -+ -+ if (!switched_seg_p) -+ nios2_current_align = align; -+ -+ /* If the last label was in a different section we can't align it. */ -+ if (label != NULL && !switched_seg_p) -+ { -+ symbolS *sym; -+ int label_seen = FALSE; -+ struct frag *old_frag; -+ valueT old_value; -+ valueT new_value; -+ -+ gas_assert (S_GET_SEGMENT (label) == now_seg); -+ -+ old_frag = symbol_get_frag (label); -+ old_value = S_GET_VALUE (label); -+ new_value = (valueT) frag_now_fix (); -+ -+ /* It is possible to have more than one label at a particular -+ address, especially if debugging is enabled, so we must -+ take care to adjust all the labels at this address in this -+ fragment. To save time we search from the end of the symbol -+ list, backwards, since the symbols we are interested in are -+ almost certainly the ones that were most recently added. -+ Also to save time we stop searching once we have seen at least -+ one matching label, and we encounter a label that is no longer -+ in the target fragment. Note, this search is guaranteed to -+ find at least one match when sym == label, so no special case -+ code is necessary. */ -+ for (sym = symbol_lastP; sym != NULL; sym = symbol_previous (sym)) -+ { -+ if (symbol_get_frag (sym) == old_frag -+ && S_GET_VALUE (sym) == old_value) -+ { -+ label_seen = TRUE; -+ symbol_set_frag (sym, frag_now); -+ S_SET_VALUE (sym, new_value); -+ } -+ else if (label_seen && symbol_get_frag (sym) != old_frag) -+ break; -+ } -+ } -+ record_alignment (now_seg, align); -+ } -+} -+ -+/* This is called from HANDLE_ALIGN in tc-nios2.h. */ -+ -+void -+nios2_handle_align (fragS * fragp) -+{ -+ /* If we are expecting to relax in the linker, then we must output a relocation -+ * to tell the linker we are aligning code. */ -+ if (nios2_as_options.relax == relax_all -+ && (fragp->fr_type == rs_align -+ || fragp->fr_type == rs_align_code) -+ && fragp->fr_address + fragp->fr_fix > 0 -+ && fragp->fr_offset > 1 && now_seg != bss_section) -+ fix_new (fragp, fragp->fr_fix, 4, &abs_symbol, fragp->fr_offset, 0, -+ BFD_RELOC_NIOS2_ALIGN); -+ -+} -+ -+/* Handle the .align pseudo-op. This aligns to a power of two. It -+ also adjusts any current instruction label. We treat this the same -+ way the MIPS port does: .align 0 turns off auto alignment. */ -+ -+static void -+s_nios2_align (int ignore ATTRIBUTE_UNUSED) -+{ -+ int align; -+ char fill; -+ const char *pfill = NULL; -+ long max_alignment = 15; -+ -+ -+ align = get_absolute_expression (); -+ if (align > max_alignment) -+ { -+ align = max_alignment; -+ as_bad (_("Alignment too large: %d. assumed"), align); -+ } -+ else if (align < 0) -+ { -+ as_warn (_("Alignment negative: 0 assumed")); -+ align = 0; -+ } -+ -+ if (*input_line_pointer == ',') -+ { -+ input_line_pointer++; -+ fill = get_absolute_expression (); -+ pfill = (const char *) &fill; -+ } -+ else if (subseg_text_p (now_seg)) -+ { -+ pfill = (const char *) &nop; -+ } -+ else -+ { -+ pfill = NULL; -+ nios2_last_label = NULL; -+ } -+ -+ if (align != 0) -+ { -+ nios2_auto_align_on = 1; -+ nios2_align (align, pfill, nios2_last_label); -+ nios2_last_label = NULL; -+ } -+ else -+ { -+ nios2_auto_align_on = 0; -+ } -+ -+ demand_empty_rest_of_line (); -+} -+ -+ -+/* Handle the .text pseudo-op. This is like the usual one, but it -+ clears the saved last label and resets known alignment. */ -+ -+static void -+s_nios2_text (int i) -+{ -+ s_text (i); -+ nios2_last_label = NULL; -+ nios2_current_align = 0; -+ nios2_current_align_seg = now_seg; -+} -+ -+/* Handle the .data pseudo-op. This is like the usual one, but it -+ clears the saved last label and resets known alignment. */ -+ -+static void -+s_nios2_data (int i) -+{ -+ s_data (i); -+ nios2_last_label = NULL; -+ nios2_current_align = 0; -+ nios2_current_align_seg = now_seg; -+} -+ -+/* Handle the .section pseudo-op. This is like the usual one, but it -+ clears the saved last label and resets known alignment. */ -+ -+static void -+s_nios2_section (int ignore) -+{ -+ obj_elf_section (ignore); -+ nios2_last_label = NULL; -+ nios2_current_align = 0; -+ nios2_current_align_seg = now_seg; -+} -+ -+/* Convert REGNAME to a DWARF-2 register number. */ -+ -+int -+tc_nios2_regname_to_dw2regnum (char *regname) -+{ -+ struct nios2_reg *r = (struct nios2_reg *) hash_find (nios2_reg_hash, -+ regname); -+ if (r == NULL) -+ return -1; -+ return r->index; -+} -+ -+/* Initialize the DWARF-2 unwind information for this procedure. */ -+ -+void -+tc_nios2_frame_initial_instructions (void) -+{ -+ cfi_add_CFA_def_cfa (27, 0); -+} -Index: binutils-2.20.1/gas/config/tc-nios2.h -=================================================================== ---- /dev/null -+++ binutils-2.20.1/gas/config/tc-nios2.h -@@ -0,0 +1,124 @@ -+/* NOT ASSIGNED TO FSF. COPYRIGHT ALTERA. */ -+/* tc-nios2.h -- header file for tc-nios2.c. -+ -+ Copyright (C) 2003 -+ by Nigel Gray (ngray@altera.com). -+ -+ This file is part of GAS. -+ -+ GAS is free software; you can redistribute it and/or modify -+ it under the terms of the GNU General Public License as published by -+ the Free Software Foundation; either version 2, or (at your option) -+ any later version. -+ -+ GAS is distributed in the hope that it will be useful, -+ but WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ GNU General Public License for more details. -+ -+ You should have received a copy of the GNU General Public License -+ along with GAS; see the file COPYING. If not, write to the Free -+ Software Foundation, 59 Temple Place - Suite 330, Boston, MA -+ 02111-1307, USA. */ -+ -+#ifndef TC_NIOS2 -+#define TC_NIOS2 -+ -+/* -+ * If unspecified, default to little endian. We can explicitly specify -+ * a big-endian default by configuring with --target=nios2eb-elf. We -+ * can override the default with the -EB and -EL options. -+ */ -+#ifndef TARGET_BYTES_BIG_ENDIAN -+#define TARGET_BYTES_BIG_ENDIAN 0 -+#endif -+ -+#ifdef OBJ_ELF -+extern const char *nios2_target_format (void); -+#define TARGET_FORMAT nios2_target_format () -+#define TARGET_ARCH bfd_arch_nios2 -+#endif -+ -+/* An NIOS2 instruction consists of tokens and separator characters -+// the tokens are things like the instruction name (add, or jmp etc), -+// the register indices ($5, $7 etc), and constant expressions. The -+// separator characters are commas, brackets and space. -+// The instruction name is always separated from other tokens by a space -+// The maximum number of tokens in an instruction is 5 (the instruction name, -+// 3 arguments, and a 4th string representing the expected instructin opcode -+// after assembly. The latter is only used when the assemble is running in -+// self test mode, otherwise its presence will generate an error. */ -+#define NIOS2_MAX_INSN_TOKENS 6 -+ -+/* There are no machine-specific operands so we #define this to nothing */ -+#define md_operand(x) -+ -+/* function prototypes exported to rest of GAS */ -+extern void md_assemble (char *op_str); -+extern void md_end (void); -+extern void md_begin (void); -+ -+#define TC_FORCE_RELOCATION(fixp) nios2_force_relocation (fixp) -+extern int nios2_force_relocation (struct fix *); -+ -+#define tc_fix_adjustable(fixp) nios2_fix_adjustable (fixp) -+extern int nios2_fix_adjustable (struct fix *); -+ -+#define tc_frob_label(lab) nios2_frob_label(lab) -+extern void nios2_frob_label (symbolS *); -+ -+#define tc_frob_symbol(symp, punt) punt = nios2_frob_symbol(symp) ? 1 : punt -+extern int nios2_frob_symbol (symbolS * symp); -+ -+#define md_cons_align(nbytes) nios2_cons_align (nbytes) -+extern void nios2_cons_align (int); -+ -+extern void md_convert_frag (bfd * headers, segT sec, fragS * fragP); -+ -+/* When relaxing, we need to generate relocations for alignment -+ directives. */ -+#define HANDLE_ALIGN(frag) nios2_handle_align (frag) -+extern void nios2_handle_align (fragS *); -+ -+extern int tc_nios2_regname_to_dw2regnum (char *regname); -+ -+extern void tc_nios2_frame_initial_instructions (void); -+ -+#define md_relax_frag nios2_relax_frag -+extern long nios2_relax_frag -+ (segT segment, fragS * fragP, long stretch); -+ -+#ifdef OBJ_ELF -+#define ELF_TC_SPECIAL_SECTIONS \ -+ { ".sdata", SHT_PROGBITS, SHF_ALLOC + SHF_WRITE + SHF_NIOS2_GPREL }, \ -+ { ".sbss", SHT_NOBITS, SHF_ALLOC + SHF_WRITE + SHF_NIOS2_GPREL }, \ -+ { ".lit4", SHT_PROGBITS, SHF_ALLOC + SHF_WRITE + SHF_NIOS2_GPREL }, \ -+ { ".lit8", SHT_PROGBITS, SHF_ALLOC + SHF_WRITE + SHF_NIOS2_GPREL }, -+ -+/* Processor specific section directives */ -+#define md_elf_section_letter nios2_elf_section_letter -+extern int nios2_elf_section_letter (int, char **); -+#define md_elf_section_flags nios2_elf_section_flags -+extern flagword nios2_elf_section_flags (flagword, int, int); -+#endif -+ -+#define GLOBAL_OFFSET_TABLE_NAME "_GLOBAL_OFFSET_TABLE_" -+ -+#define DIFF_EXPR_OK -+ -+#define TC_PARSE_CONS_EXPRESSION(EXP, NBYTES) nios2_cons (EXP, NBYTES) -+extern void nios2_cons (expressionS *exp, int size); -+ -+#define TC_CONS_FIX_NEW nios2_cons_fix_new -+extern void nios2_cons_fix_new(struct frag *frag, int where, -+ unsigned int nbytes, struct expressionS *exp); -+ -+/* We want .cfi_* pseudo-ops for generating unwind info. */ -+#define TARGET_USE_CFIPOP 1 -+#define DWARF2_DEFAULT_RETURN_COLUMN 31 -+#define DWARF2_CIE_DATA_ALIGNMENT (-4) -+#define tc_regname_to_dw2regnum tc_nios2_regname_to_dw2regnum -+#define tc_cfi_frame_initial_instructions tc_nios2_frame_initial_instructions -+#define tc_cfi_no_pcrel_expr 1 -+ -+#endif // TC_NIOS2 -Index: binutils-2.20.1/gas/doc/c-nios2.texi -=================================================================== ---- /dev/null -+++ binutils-2.20.1/gas/doc/c-nios2.texi -@@ -0,0 +1,223 @@ -+@c NOT ASSIGNED TO FSF. COPYRIGHT ALTERA. -+@c Copyright 2004 -+@c This is part of the GAS manual. -+@c For copying conditions, see the file as.texinfo. -+@ifset GENERIC -+@page -+@node NiosII-Dependent -+@chapter Altera Nios II Dependent Features -+@end ifset -+@ifclear GENERIC -+@node Machine Dependencies -+@chapter ltera Nios II Dependent Features -+@end ifclear -+ -+@cindex Altera Nios II support -+@cindex Nios support -+@cindex Nios II support -+@menu -+* Nios II Options:: Options -+* Nios II Syntax:: Syntax -+* Nios II Relocations:: Relocations -+* Nios II Directives:: Nios II Machine Directives -+* Nios II Opcodes:: Opcodes -+@end menu -+ -+@node Nios II Options -+@section Options -+@cindex Nios II options -+@cindex options for Nios II -+ -+@table @code -+ -+@cindex @code{relax-all} command line option, Nios II -+@item -relax-all -+Replace all branch and call instructions with @code{jmp} and @code{callr} sequences -+ -+@cindex @code{relax-section} command line option, Nios II -+@item -relax-section -+Replace identified out of range branches with @code{jmp} sequences (default) -+ -+@cindex @code{no-relax} command line option, Nios II -+@item -no-relax -+Do not replace any branches or calls -+ -+@cindex @code{EB} command line option, Nios II -+@item -EB -+Generate big-endian output -+ -+@cindex @code{EL} command line option, Nios II -+@item -EL -+Generate little-endian output -+ -+@end table -+ -+ -+@node Nios II Syntax -+@section Syntax -+@menu -+* Nios II Chars:: Special Characters -+@end menu -+ -+ -+@node Nios II Chars -+@subsection Special Characters -+ -+@cindex line comment character, Nios II -+@cindex Nios II line comment character -+@samp{#} is the line comment character. -+ -+@cindex line separator character, Nios II -+@cindex Nios II line separator character -+@samp{;} is the line separator character. -+ -+ -+@node Nios II Relocations -+@section Nios II Machine Relocations -+ -+@cindex machine relocations, Nios II -+@cindex Nios II machine relocations -+ -+@table @code -+@cindex @code{hiadj} directive, Nios II -+@item %hiadj(@var{expression}) -+Extract the upper 16-bits of @var{expression} and add -+one if the 15th bit is set. -+ -+The value of %hiadj is: -+((@var{expression} >> 16) & 0xffff) + ((@var{expression} >> 15) & 0x01). -+ -+The intention of the @code{%hiadj} relocation is to be used with -+an @code{addi}, @code{ld} or @code{st} instructions -+along with a @code{%lo}. -+ -+@smallexample -+movhi r2, %hiadj(symbol) -+addi r2, r2, %lo(symbol) -+@end smallexample -+ -+@cindex @code{hi} directive, Nios II -+@item %hi(@var{expression}) -+Extract the upper 16-bits of @var{expression}. -+ -+ -+@cindex @code{lo} directive, Nios II -+@item %lo(@var{expression}) -+Extract the lower 16-bits of @var{expression}. -+ -+ -+@cindex @code{gprel} directive, Nios II -+@item %gprel(@var{expression}) -+Subtract the value of the symbol @code{_gp} from -+@var{expression}. -+ -+The intention of the @code{%gprel} relocation is -+to have a fast small area of memory which only -+takes a 16-bit immediate to access. -+ -+@smallexample -+ .section .sdata -+fastint: -+ .int 123 -+ .section .text -+ ldw r4, %gprel(fastint)(gp) -+@end smallexample -+ -+ -+@end table -+ -+ -+@node Nios II Directives -+@section Nios II Machine Directives -+ -+@cindex machine directives, Nios II -+@cindex Nios II machine directives -+ -+@table @code -+ -+@cindex @code{align} directive, Nios II -+@item .align @var{expression} [, @var{expression}] -+This is the generic @var{.align} directive, however -+this aligns to a power of two. -+ -+@cindex @code{half} directive, Nios II -+@item .half @var{expression} -+Create an aligned constant 2-bytes in size -+ -+@cindex @code{word} directive, Nios II -+@item .word @var{expression} -+Create an aligned constant 4-bytes in size -+ -+@cindex @code{dword} directive, Nios II -+@item .dword @var{expression} -+Create an aligned constant 8-bytes in size -+ -+@cindex @code{2byte} directive, Nios II -+@item .2byte @var{expression} -+Create an un-aligned constant 2-bytes in size -+ -+@cindex @code{4byte} directive, Nios II -+@item .4byte @var{expression} -+Create an un-aligned constant 4-bytes in size -+ -+@cindex @code{8byte} directive, Nios II -+@item .8byte @var{expression} -+Create an un-aligned constant 8-bytes in size -+ -+@cindex @code{16byte} directive, Nios II -+@item .16byte @var{expression} -+Create an un-aligned constant 16-bytes in size -+ -+@cindex @code{set noat} directive, Nios II -+@item .set noat -+Allows assembly code to use @code{at} register without -+warning and macro or relaxation expansions will -+generate a warning. -+ -+@cindex @code{set at} directive, Nios II -+@item .set at -+Assembly code using @code{at} register will generate -+warnings, and macro expansion and relaxation will be -+enabled. -+ -+@cindex @code{set nobreak} directive, Nios II -+@item .set nobreak -+Allows assembly code to use @code{ba}, @code{bt}, -+registers without warning. -+ -+@cindex @code{set break} directive, Nios II -+@item .set break -+Turns warnings back on for using @code{ba}, @code{bt} -+registers. -+ -+@cindex @code{set norelax} directive, Nios II -+@item .set norelax -+Do not replace any branches or calls. -+ -+@cindex @code{set relaxsection} directive, Nios II -+@item .set relaxsection -+Replace identified out of range branches with -+@code{jmp} sequences (default). -+ -+@cindex @code{set relaxall} directive, Nios II -+@item .set relaxsection -+Replace all branch and call instructions with -+@code{jmp} and @code{callr} sequences. -+ -+@cindex @code{set} directive, Nios II -+@item .set @dots{} -+All other @code{.set} are the normal use. -+ -+@end table -+ -+@node Nios II Opcodes -+@section Opcodes -+ -+@cindex Nios II opcodes -+@cindex opcodes for Nios II -+@code{@value{AS}} implements all the standard Nios II opcodes. No -+additional pseudo-instructions are needed on this family. -+ -+For information on the Nios II machine instruction set, see the @cite{Nios II -+User's Manual} -+ -Index: binutils-2.20.1/gas/testsuite/gas/nios2/add.d -=================================================================== ---- /dev/null -+++ binutils-2.20.1/gas/testsuite/gas/nios2/add.d -@@ -0,0 +1,16 @@ -+#objdump: -dr --prefix-addresses -+#name: NIOS2 add -+ -+# Test the add instruction -+ -+.*: +file format elf32-littlenios2 -+ -+Disassembly of section .text: -+0+0000 <[^>]*> add r4,r4,r4 -+0+0004 <[^>]*> addi r4,r4,32767 -+0+0008 <[^>]*> addi r4,r4,-32768 -+0+000c <[^>]*> addi r4,r4,0 -+0+0010 <[^>]*> addi r4,r4,-1 -+0+0014 <[^>]*> addi r4,r4,-1 -+0+0018 <[^>]*> addi r4,r4,13398 -+0+001c <[^>]*> nop -Index: binutils-2.20.1/gas/testsuite/gas/nios2/add.s -=================================================================== ---- /dev/null -+++ binutils-2.20.1/gas/testsuite/gas/nios2/add.s -@@ -0,0 +1,13 @@ -+# Source file used to test the add and addi instructions. -+ -+foo: -+ add r4,r4,r4 -+ addi r4,r4,0x7fff -+ addi r4,r4,-0x8000 -+ addi r4,r4,0x0 -+ addi r4,r4,-0x01 -+ subi r4,r4,0x01 -+ addi r4,r4,0x3456 -+ -+# should disassemble to add r0,0,r0 -+ nop -Index: binutils-2.20.1/gas/testsuite/gas/nios2/align_fill.d -=================================================================== ---- /dev/null -+++ binutils-2.20.1/gas/testsuite/gas/nios2/align_fill.d -@@ -0,0 +1,23 @@ -+#objdump: -dr --prefix-addresses -+#name: NIOS2 align_fill -+ -+# Test the and macro. -+ -+.*: +file format elf32-littlenios2 -+ -+Disassembly of section .text: -+0+0000 <[^>]*> addi sp,sp,-8 -+0+0004 <[^>]*> stw fp,4\(sp\) -+0+0008 <[^>]*> mov fp,sp -+0+000c <[^>]*> mov r3,zero -+0+0010 <[^>]*> nop -+0+0014 <[^>]*> nop -+0+0018 <[^>]*> nop -+0+001c <[^>]*> nop -+0+0020 <[^>]*> addi r3,r3,1 -+0+0024 <[^>]*> cmplti r2,r3,100 -+0+0028 <[^>]*> bne r2,zero,0+0020 <[^>*]*> -+0+002c <[^>]*> ldw fp,4\(sp\) -+0+0030 <[^>]*> addi sp,sp,8 -+0+0034 <[^>]*> ret -+ ... -Index: binutils-2.20.1/gas/testsuite/gas/nios2/align_fill.s -=================================================================== ---- /dev/null -+++ binutils-2.20.1/gas/testsuite/gas/nios2/align_fill.s -@@ -0,0 +1,20 @@ -+ .file "a.c" -+ .section .text -+ .align 3 -+ .global x -+ .type x, @function -+x: -+ addi sp, sp, -8 -+ stw fp, 4(sp) -+ mov fp, sp -+ mov r3, zero -+ .align 5 -+.L6: -+ addi r3, r3, 1 -+ cmplti r2, r3, 100 -+ bne r2, zero, .L6 -+ ldw fp, 4(sp) -+ addi sp, sp, 8 -+ ret -+ .size x, .-x -+ .ident "GCC: (GNU) 3.3.3 (Altera Nios II 1.0 b302)" -Index: binutils-2.20.1/gas/testsuite/gas/nios2/align_text.d -=================================================================== ---- /dev/null -+++ binutils-2.20.1/gas/testsuite/gas/nios2/align_text.d -@@ -0,0 +1,22 @@ -+#objdump: -dr -+#name: NIOS2 align_test -+ -+# Test alignment in text sections. -+ -+.*: +file format elf32-littlenios2 -+ -+Disassembly of section .text: -+00000000 : -+ 0: 00000000 call 0 -+ 4: 0001883a nop -+ 8: 0001883a nop -+ c: 0001883a nop -+ 10: 0001883a nop -+ 14: 0001883a nop -+ 18: 0001883a nop -+ 1c: 0001883a nop -+ -+00000020