This is the mail archive of the binutils-cvs@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[binutils-gdb] nds32: Remove the unsupported target feature.


https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=f9671640954362a918c669700bcc9a57be25782d

commit f9671640954362a918c669700bcc9a57be25782d
Author: Kuan-Lin Chen <kuanlinchentw@gmail.com>
Date:   Thu Mar 15 14:50:51 2018 +0800

    nds32: Remove the unsupported target feature.

Diff:
---
 bfd/ChangeLog            |   16 +
 bfd/elf32-nds32.c        | 2785 +---------------------------------------------
 ld/ChangeLog             |    5 +
 ld/emultempl/nds32elf.em |    8 -
 4 files changed, 22 insertions(+), 2792 deletions(-)

diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index fac9b62..d06541a 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -1,3 +1,19 @@
+2018-03-15  Kuan-Lin Chen  <kuanlinchentw@gmail.com>
+
+	* elf32-nds32.c (nds32_elf_ex9_build_hash_table): Removed.
+	Not support the target feature.
+	(nds32_elf_ex9_itb_base): Likewise.
+	(nds32_elf_ex9_import_table): Likewise.
+	(nds32_elf_ex9_finish): Likewise.
+	(nds32_elf_ex9_reloc_jmp): Likewise.
+	(nds32_elf_get_insn_with_reg): Likewise.
+	(nds32_get_local_syms): Likewise.
+	(nds32_elf_ex9_replace_instruction): Likewise.
+	(nds32_elf_ifc_calc): Likewise.
+	(nds32_elf_ifc_finish): Likewise.
+	(nds32_elf_ifc_replace): Likewise.
+	(nds32_elf_ifc_reloc): Likewise.
+
 2018-03-14  Alan Modra  <amodra@gmail.com>
 
 	* elf64-ppc.c (sfpr_define): Adjust for stub_sec size having
diff --git a/bfd/elf32-nds32.c b/bfd/elf32-nds32.c
index e240d31..449e834 100644
--- a/bfd/elf32-nds32.c
+++ b/bfd/elf32-nds32.c
@@ -62,23 +62,8 @@ static bfd_vma calculate_memory_address
 (bfd *, Elf_Internal_Rela *, Elf_Internal_Sym *, Elf_Internal_Shdr *);
 static int nds32_get_section_contents (bfd *, asection *,
 				       bfd_byte **, bfd_boolean);
-static bfd_boolean nds32_elf_ex9_build_hash_table
-(bfd *, asection *, struct bfd_link_info *);
-static bfd_boolean nds32_elf_ex9_itb_base (struct bfd_link_info *);
-static void nds32_elf_ex9_import_table (struct bfd_link_info *);
-static void nds32_elf_ex9_finish (struct bfd_link_info *);
-static void nds32_elf_ex9_reloc_jmp (struct bfd_link_info *);
-static void nds32_elf_get_insn_with_reg
-  (Elf_Internal_Rela *, uint32_t, uint32_t *);
 static int nds32_get_local_syms (bfd *, asection *ATTRIBUTE_UNUSED,
 				 Elf_Internal_Sym **);
-static bfd_boolean nds32_elf_ex9_replace_instruction
-  (struct bfd_link_info *, bfd *, asection *);
-static bfd_boolean nds32_elf_ifc_calc (struct bfd_link_info *, bfd *,
-				       asection *);
-static bfd_boolean nds32_elf_ifc_finish (struct bfd_link_info *);
-static bfd_boolean nds32_elf_ifc_replace (struct bfd_link_info *);
-static bfd_boolean nds32_elf_ifc_reloc (void);
 static bfd_boolean  nds32_relax_fp_as_gp
   (struct bfd_link_info *link_info, bfd *abfd, asection *sec,
    Elf_Internal_Rela *internal_relocs, Elf_Internal_Rela *irelend,
@@ -163,7 +148,6 @@ enum
 /* Size of small data/bss sections, used to calculate SDA_BASE.  */
 static long got_size = 0;
 static int is_SDA_BASE_set = 0;
-static int is_ITB_BASE_set = 0;
 
 /* Convert ELF-VER in eflags to string for debugging purpose.  */
 static const char *const nds32_elfver_strtab[] =
@@ -212,7 +196,6 @@ struct elf_nds32_link_hash_entry
 
 #define FP_BASE_NAME "_FP_BASE_"
 static int check_start_export_sym = 0;
-static size_t ex9_relax_size = 0;		/* Save ex9 predicted reducing size.  */
 
 /* The offset for executable tls relaxation.  */
 #define TP_OFFSET 0x0
@@ -4415,26 +4398,6 @@ nds32_elf_relocate_section (bfd *		   output_bfd ATTRIBUTE_UNUSED,
 	return FALSE;
     }
 
-  if (is_ITB_BASE_set == 0)
-    {
-      /* Set the _ITB_BASE_.  */
-      if (!nds32_elf_ex9_itb_base (info))
-	{
-	  _bfd_error_handler (_("%pB: error: cannot set %s"),
-			      output_bfd, "_ITB_BASE_");
-	  bfd_set_error (bfd_error_bad_value);
-	}
-    }
-
-  if (table->target_optimize & NDS32_RELAX_JUMP_IFC_ON)
-    if (!nds32_elf_ifc_reloc ())
-      _bfd_error_handler (_("error: IFC relocation error"));
-
- /* Relocation for .ex9.itable.  */
-  if (table->target_optimize & NDS32_RELAX_EX9_ON
-      || (table->ex9_import_file && table->update_ex9_table))
-    nds32_elf_ex9_reloc_jmp (info);
-
   /* Use gp as fp to prevent truncated fit.  Because in relaxation time
      the fp value is set as gp, and it has be reverted for instruction
      setting fp.  */
@@ -11583,118 +11546,6 @@ nds32_relax_adjust_label (bfd *abfd, asection *sec,
   return TRUE;
 }
 
-/* Pick relaxation round.  */
-
-static int
-nds32_elf_pick_relax (bfd_boolean init, asection *sec, bfd_boolean *again,
-		      struct elf_nds32_link_hash_table *table,
-		      struct bfd_link_info *link_info)
-{
-  static asection *final_sec, *first_sec = NULL;
-  static bfd_boolean normal_again = FALSE;
-  static bfd_boolean set = FALSE;
-  static bfd_boolean first = TRUE;
-  int round_table[] = {
-      NDS32_RELAX_NORMAL_ROUND,
-      NDS32_RELAX_JUMP_IFC_ROUND,
-      NDS32_RELAX_EX9_BUILD_ROUND,
-      NDS32_RELAX_EX9_REPLACE_ROUND,
-  };
-  static int pass = 0;
-  static int relax_round;
-
-  /* The new round.  */
-  if (init && first_sec == sec)
-    {
-      set = TRUE;
-      normal_again = FALSE;
-    }
-
-  if (first)
-    {
-      /* Run an empty run to get the final section.  */
-      relax_round = NDS32_RELAX_EMPTY_ROUND;
-
-      /* It has to enter relax again because we can
-	 not make sure what the final turn is.  */
-      *again = TRUE;
-
-      first = FALSE;
-      first_sec = sec;
-    }
-
-  if (!set)
-    {
-      /* Not reenter yet.  */
-      final_sec = sec;
-      return relax_round;
-    }
-
-  relax_round = round_table[pass];
-
-  if (!init && relax_round == NDS32_RELAX_NORMAL_ROUND && *again)
-    normal_again = TRUE;
-
-  if (!init && final_sec == sec)
-    {
-      switch (relax_round)
-	{
-	case NDS32_RELAX_NORMAL_ROUND:
-	  if (!normal_again)
-	    {
-	      /* Normal relaxation done.  */
-	      if (table->target_optimize & NDS32_RELAX_JUMP_IFC_ON)
-		{
-		  pass++;
-		  *again = TRUE;
-		}
-	      else if (table->target_optimize & NDS32_RELAX_EX9_ON)
-		{
-		  pass += 2;	/* NDS32_RELAX_EX9_BUILD_ROUND */
-		  *again = TRUE;
-		}
-	      else if (table->ex9_import_file)
-		{
-		  /* Import ex9 table.  */
-		  if (table->update_ex9_table)
-		    pass += 2;	/* NDS32_RELAX_EX9_BUILD_ROUND */
-		  else
-		    pass += 3;	/* NDS32_RELAX_EX9_REPLACE_ROUND */
-		  nds32_elf_ex9_import_table (link_info);
-		  *again = TRUE;
-		}
-	    }
-	  break;
-	case NDS32_RELAX_JUMP_IFC_ROUND:
-	  if (!nds32_elf_ifc_finish (link_info))
-	    _bfd_error_handler (_("error: jump IFC fail"));
-	  if (table->target_optimize & NDS32_RELAX_EX9_ON)
-	    {
-	      pass++;
-	      *again = TRUE;
-	    }
-	  break;
-	case NDS32_RELAX_EX9_BUILD_ROUND:
-	  nds32_elf_ex9_finish (link_info);
-	  pass++;
-	  *again = TRUE;
-	  break;
-	case NDS32_RELAX_EX9_REPLACE_ROUND:
-	  if (table->target_optimize & NDS32_RELAX_JUMP_IFC_ON)
-	    {
-	      /* Do jump IFC optimization again.  */
-	      if (!nds32_elf_ifc_finish (link_info))
-		_bfd_error_handler (_("error: jump IFC fail"));
-	    }
-	  break;
-	default:
-	  break;
-	}
-    }
-
-  return relax_round;
-}
-
 static bfd_boolean
 nds32_elf_relax_section (bfd *abfd, asection *sec,
 			 struct bfd_link_info *link_info, bfd_boolean *again)
@@ -11715,7 +11566,6 @@ nds32_elf_relax_section (bfd *abfd, asection *sec,
   /* Target dependnet option.  */
   struct elf_nds32_link_hash_table *table;
   int load_store_relax;
-  int relax_round;
 
   relax_blank_list = NULL;
 
@@ -11743,41 +11593,6 @@ nds32_elf_relax_section (bfd *abfd, asection *sec,
   /* The optimization type to do.  */
 
   table = nds32_elf_hash_table (link_info);
-  relax_round = nds32_elf_pick_relax (TRUE, sec, again, table, link_info);
-  switch (relax_round)
-    {
-    case NDS32_RELAX_JUMP_IFC_ROUND:
-      /* Here is the entrance of ifc jump relaxation.  */
-      if (!nds32_elf_ifc_calc (link_info, abfd, sec))
-	return FALSE;
-      nds32_elf_pick_relax (FALSE, sec, again, table, link_info);
-      return TRUE;
-
-    case NDS32_RELAX_EX9_BUILD_ROUND:
-      /* Here is the entrance of ex9 relaxation.  There are two pass of
-	 ex9 relaxation.  The one is to traverse all instructions and build
-	 the hash table.  The other one is to compare instructions and replace
-	 it by ex9.it.  */
-      if (!nds32_elf_ex9_build_hash_table (abfd, sec, link_info))
-	return FALSE;
-      nds32_elf_pick_relax (FALSE, sec, again, table, link_info);
-      return TRUE;
-
-    case NDS32_RELAX_EX9_REPLACE_ROUND:
-      if (!nds32_elf_ex9_replace_instruction (link_info, abfd, sec))
-	return FALSE;
-      return TRUE;
-
-    case NDS32_RELAX_EMPTY_ROUND:
-      nds32_elf_pick_relax (FALSE, sec, again, table, link_info);
-      return TRUE;
-
-    case NDS32_RELAX_NORMAL_ROUND:
-    default:
-      if (sec->reloc_count == 0)
-	return TRUE;
-      break;
-    }
 
   /* The begining of general relaxation.  */
 
@@ -11790,17 +11605,6 @@ nds32_elf_relax_section (bfd *abfd, asection *sec,
       relax_range_measurement (abfd);
     }
 
-  if (is_ITB_BASE_set == 0)
-    {
-      /* Set the _ITB_BASE_.  */
-      if (!nds32_elf_ex9_itb_base (link_info))
-	{
-	  _bfd_error_handler (_("%pB: error: cannot set %s"),
-			      abfd, "_ITB_BASE_");
-	  bfd_set_error (bfd_error_bad_value);
-	}
-    }
-
   symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
   /* Relocations MUST be kept in memory, because relaxation adjust them.  */
   internal_relocs = _bfd_elf_link_read_relocs (abfd, sec, NULL, NULL,
@@ -11818,10 +11622,7 @@ nds32_elf_relax_section (bfd *abfd, asection *sec,
   if (ELF32_R_TYPE (irel->r_info) == R_NDS32_RELAX_ENTRY)
     {
       if (irel->r_addend & R_NDS32_RELAX_ENTRY_DISABLE_RELAX_FLAG)
-	{
-	  nds32_elf_pick_relax (FALSE, sec, again, table, link_info);
-	  return TRUE;
-	}
+	return TRUE;
 
       if (irel->r_addend & R_NDS32_RELAX_ENTRY_OPTIMIZE_FLAG)
 	optimize = 1;
@@ -12075,8 +11876,6 @@ nds32_elf_relax_section (bfd *abfd, asection *sec,
 	}
     }
 
-  nds32_elf_pick_relax (FALSE, sec, again, table, link_info);
-
   if (!*again)
     {
       if (!nds32_relax_adjust_label (abfd, sec, internal_relocs, contents,
@@ -12865,2588 +12664,6 @@ error_return:
   return NULL;
 }
 
-/* Link-time IFC relaxation.
-   In this optimization, we chains jump instructions
-   of the same destination with ifcall.  */
-
-
-/* List to save jal and j relocation.  */
-struct elf_nds32_ifc_symbol_entry
-{
-  asection *sec;
-  struct elf_link_hash_entry *h;
-  struct elf_nds32_ifc_irel_list *irel_head;
-  unsigned long insn;
-  int times;
-  int enable;		/* Apply ifc.  */
-  int ex9_enable;	/* Apply ifc after ex9.  */
-  struct elf_nds32_ifc_symbol_entry *next;
-};
-
-struct elf_nds32_ifc_irel_list
-{
-  Elf_Internal_Rela *irel;
-  asection *sec;
-  bfd_vma addr;
-  /* If this is set, then it is the last instruction for
-     ifc-chain, so it must be keep for the actual branching.  */
-  int keep;
-  struct elf_nds32_ifc_irel_list *next;
-};
-
-static struct elf_nds32_ifc_symbol_entry *ifc_symbol_head = NULL;
-
-/* Insert symbol of jal and j for ifc.  */
-
-static void
-nds32_elf_ifc_insert_symbol (asection *sec,
-			     struct elf_link_hash_entry *h,
-			     Elf_Internal_Rela *irel,
-			     unsigned long insn)
-{
-  struct elf_nds32_ifc_symbol_entry *ptr = ifc_symbol_head;
-
-  /* Check there is target of existing entry the same as the new one.  */
-  while (ptr != NULL)
-    {
-      if (((h == NULL && ptr->sec == sec
-	    && ELF32_R_SYM (ptr->irel_head->irel->r_info) == ELF32_R_SYM (irel->r_info)
-	    && ptr->irel_head->irel->r_addend == irel->r_addend)
-	   || h != NULL)
-	  && ptr->h == h
-	  && ptr->insn == insn)
-	{
-	  /* The same target exist, so insert into list.  */
-	  struct elf_nds32_ifc_irel_list *irel_list = ptr->irel_head;
-
-	  while (irel_list->next != NULL)
-	    irel_list = irel_list->next;
-	  irel_list->next = bfd_malloc (sizeof (struct elf_nds32_ifc_irel_list));
-	  irel_list = irel_list->next;
-	  irel_list->irel = irel;
-	  irel_list->keep = 1;
-
-	  if (h == NULL)
-	    irel_list->sec = NULL;
-	  else
-	    irel_list->sec = sec;
-	  irel_list->next = NULL;
-	  return;
-	}
-      if (ptr->next == NULL)
-	break;
-      ptr = ptr->next;
-    }
-
-  /* There is no same target entry, so build a new one.  */
-  if (ifc_symbol_head == NULL)
-    {
-      ifc_symbol_head = bfd_malloc (sizeof (struct elf_nds32_ifc_symbol_entry));
-      ptr = ifc_symbol_head;
-    }
-  else
-    {
-      ptr->next = bfd_malloc (sizeof (struct elf_nds32_ifc_symbol_entry));
-      ptr = ptr->next;
-    }
-
-  ptr->h = h;
-  ptr->irel_head = bfd_malloc (sizeof (struct elf_nds32_ifc_irel_list));
-  ptr->irel_head->irel = irel;
-  ptr->insn = insn;
-  ptr->irel_head->keep = 1;
-
-  if (h == NULL)
-    {
-      /* Local symbols.  */
-      ptr->sec = sec;
-      ptr->irel_head->sec = NULL;
-    }
-  else
-    {
-      /* Global symbol.  */
-      ptr->sec = NULL;
-      ptr->irel_head->sec = sec;
-    }
-
-  ptr->irel_head->next = NULL;
-  ptr->times = 0;
-  ptr->enable = 0;
-  ptr->ex9_enable = 0;
-  ptr->next = NULL;
-}
-
-/* Gather all jal and j instructions.  */
-
-static bfd_boolean
-nds32_elf_ifc_calc (struct bfd_link_info *info,
-		    bfd *abfd, asection *sec)
-{
-  Elf_Internal_Rela *internal_relocs;
-  Elf_Internal_Rela *irelend;
-  Elf_Internal_Rela *irel;
-  Elf_Internal_Shdr *symtab_hdr;
-  bfd_byte *contents = NULL;
-  uint32_t insn, insn_with_reg;
-  unsigned long r_symndx;
-  struct elf_link_hash_entry *h;
-  struct elf_link_hash_entry **sym_hashes = elf_sym_hashes (abfd);
-  struct elf_nds32_link_hash_table *table;
-  bfd_boolean ifc_loop_aware;
-
-  internal_relocs = _bfd_elf_link_read_relocs (abfd, sec, NULL, NULL,
-					       TRUE /* keep_memory */);
-  irelend = internal_relocs + sec->reloc_count;
-  symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
-
-  /* Check if the object enable ifc.  */
-  irel = find_relocs_at_address (internal_relocs, internal_relocs, irelend,
-				 R_NDS32_RELAX_ENTRY);
-
-  if (irel == NULL
-      || irel >= irelend
-      || ELF32_R_TYPE (irel->r_info) != R_NDS32_RELAX_ENTRY
-      || (ELF32_R_TYPE (irel->r_info) == R_NDS32_RELAX_ENTRY
-	  && !(irel->r_addend & R_NDS32_RELAX_ENTRY_IFC_FLAG)))
-    return TRUE;
-
-  if (!nds32_get_section_contents (abfd, sec, &contents, TRUE))
-    return FALSE;
-
-  table = nds32_elf_hash_table (info);
-  ifc_loop_aware = table->ifc_loop_aware;
-  while (irel != NULL && irel < irelend)
-    {
-      /* Traverse all relocation and gather all of them to build the list.  */
-
-      if (ELF32_R_TYPE (irel->r_info) == R_NDS32_RELAX_REGION_BEGIN)
-	{
-	  if (ifc_loop_aware == 1
-	      && (irel->r_addend & R_NDS32_RELAX_REGION_INNERMOST_LOOP_FLAG) != 0)
-	    {
-	      /* Check the region if loop or not.  If it is true and
-		 ifc-loop-aware is true, ignore the region till region end.  */
-	      while (irel != NULL
-		     && irel < irelend
-		     && (ELF32_R_TYPE (irel->r_info) != R_NDS32_RELAX_REGION_END
-			 || (irel->r_addend & R_NDS32_RELAX_REGION_INNERMOST_LOOP_FLAG) != 0))
-		irel++;
-	    }
-	}
-
-      if (ELF32_R_TYPE (irel->r_info) == R_NDS32_25_PCREL_RELA)
-	{
-	  insn = bfd_getb32 (contents + irel->r_offset);
-	  nds32_elf_get_insn_with_reg (irel, insn, &insn_with_reg);
-	  r_symndx = ELF32_R_SYM (irel->r_info);
-	  if (r_symndx < symtab_hdr->sh_info)
-	    {
-	      /* Local symbol.  */
-	      nds32_elf_ifc_insert_symbol (sec, NULL, irel, insn_with_reg);
-	    }
-	  else
-	    {
-	      /* External symbol.  */
-	      h = sym_hashes[r_symndx - symtab_hdr->sh_info];
-	      nds32_elf_ifc_insert_symbol (sec, h, irel, insn_with_reg);
-	    }
-	}
-      irel++;
-    }
-  return TRUE;
-}
-
-/* Determine whether j and jal should be substituted.  */
-
-static void
-nds32_elf_ifc_filter (struct bfd_link_info *info)
-{
-  struct elf_nds32_ifc_symbol_entry *ptr = ifc_symbol_head;
-  struct elf_nds32_ifc_irel_list *irel_ptr = NULL;
-  struct elf_nds32_ifc_irel_list *irel_keeper = NULL;
-  struct elf_nds32_link_hash_table *table;
-  int target_optimize;
-  bfd_vma address;
-
-  table = nds32_elf_hash_table (info);
-  target_optimize = table->target_optimize;
-  while (ptr)
-    {
-      irel_ptr = ptr->irel_head;
-      if (ptr->h == NULL)
-	{
-	  /* Local symbol.  */
-	  irel_keeper = irel_ptr;
-	  while (irel_ptr && irel_ptr->next)
-	    {
-	      /* Check there is jump target can be used.  */
-	      if ((irel_ptr->next->irel->r_offset
-		   - irel_keeper->irel->r_offset) > 1022)
-		irel_keeper = irel_ptr->next;
-	      else
-		{
-		  ptr->enable = 1;
-		  irel_ptr->keep = 0;
-		}
-	      irel_ptr = irel_ptr->next;
-	    }
-	}
-      else
-	{
-	  /* Global symbol.  */
-	  /* We have to get the absolute address and decide
-	     whether to keep it or not.  */
-	  while (irel_ptr)
-	    {
-	      address = (irel_ptr->irel->r_offset
-			 + irel_ptr->sec->output_section->vma
-			 + irel_ptr->sec->output_offset);
-	      irel_ptr->addr = address;
-	      irel_ptr = irel_ptr->next;
-	    }
-
-	  irel_ptr = ptr->irel_head;
-	  while (irel_ptr)
-	    {
-	      /* Sort by address.  */
-	      struct elf_nds32_ifc_irel_list *irel_dest = irel_ptr;
-	      struct elf_nds32_ifc_irel_list *irel_temp = irel_ptr;
-	      struct elf_nds32_ifc_irel_list *irel_ptr_prev = NULL;
-	      struct elf_nds32_ifc_irel_list *irel_dest_prev = NULL;
-
-	      /* Get the smallest one.  */
-	      while (irel_temp->next)
-		{
-		  if (irel_temp->next->addr < irel_dest->addr)
-		    {
-		      irel_dest_prev = irel_temp;
-		      irel_dest = irel_temp->next;
-		    }
-		  irel_temp = irel_temp->next;
-		}
-
-	      if (irel_dest != irel_ptr)
-		{
-		  if (irel_ptr_prev)
-		    irel_ptr_prev->next = irel_dest;
-		  if (irel_dest_prev)
-		    irel_dest_prev->next = irel_ptr;
-		  irel_temp = irel_ptr->next;
-		  irel_ptr->next = irel_dest->next;
-		  irel_dest->next = irel_temp;
-		}
-	      irel_ptr_prev = irel_ptr;
-	      irel_ptr = irel_ptr->next;
-	    }
-
-	  irel_ptr = ptr->irel_head;
-	  irel_keeper = irel_ptr;
-	  while (irel_ptr && irel_ptr->next)
-	    {
-	      if ((irel_ptr->next->addr - irel_keeper->addr) > 1022)
-		irel_keeper = irel_ptr->next;
-	      else
-		{
-		  ptr->enable = 1;
-		  irel_ptr->keep = 0;
-		}
-	      irel_ptr = irel_ptr->next;
-	    }
-	}
-
-	/* Ex9 enable.  Reserve it for ex9.  */
-      if ((target_optimize & NDS32_RELAX_EX9_ON)
-	  && ptr->irel_head != irel_keeper)
-	ptr->enable = 0;
-      ptr = ptr->next;
-    }
-}
-
-/* Determine whether j and jal should be substituted after ex9 done.  */
-
-static void
-nds32_elf_ifc_filter_after_ex9 (void)
-{
-  struct elf_nds32_ifc_symbol_entry *ptr = ifc_symbol_head;
-  struct elf_nds32_ifc_irel_list *irel_ptr = NULL;
-
-  while (ptr)
-    {
-      if (ptr->enable == 0)
-	{
-	  /* Check whether ifc is applied or not.  */
-	  irel_ptr = ptr->irel_head;
-	  ptr->ex9_enable = 1;
-	  while (irel_ptr)
-	    {
-	      if (ELF32_R_TYPE (irel_ptr->irel->r_info) == R_NDS32_TRAN)
-		{
-		  /* Ex9 already.  */
-		  ptr->ex9_enable = 0;
-		  break;
-		}
-	      irel_ptr = irel_ptr->next;
-	    }
-	}
-      ptr = ptr->next;
-    }
-}
-
-/* Wrapper to do ifc relaxation.  */
-
-bfd_boolean
-nds32_elf_ifc_finish (struct bfd_link_info *info)
-{
-  int relax_status;
-  struct elf_nds32_link_hash_table *table;
-
-  table = nds32_elf_hash_table (info);
-  relax_status = table->relax_status;
-
-  if (!(relax_status & NDS32_RELAX_JUMP_IFC_DONE))
-    nds32_elf_ifc_filter (info);
-  else
-    nds32_elf_ifc_filter_after_ex9 ();
-
-  if (!nds32_elf_ifc_replace (info))
-    return FALSE;
-
-  if (table)
-    table->relax_status |= NDS32_RELAX_JUMP_IFC_DONE;
-  return TRUE;
-}
-
-/* Traverse the result of ifc filter and replace it with ifcall9.  */
-
-static bfd_boolean
-nds32_elf_ifc_replace (struct bfd_link_info *info)
-{
-  struct elf_nds32_ifc_symbol_entry *ptr = ifc_symbol_head;
-  struct elf_nds32_ifc_irel_list *irel_ptr = NULL;
-  nds32_elf_blank_t *relax_blank_list = NULL;
-  bfd_byte *contents = NULL;
-  Elf_Internal_Rela *internal_relocs;
-  Elf_Internal_Rela *irel;
-  Elf_Internal_Rela *irelend;
-  unsigned short insn16 = INSN_IFCALL9;
-  struct elf_nds32_link_hash_table *table;
-  int relax_status;
-
-  table = nds32_elf_hash_table (info);
-  relax_status = table->relax_status;
-
-  while (ptr)
-    {
-      /* Traverse the ifc gather list, and replace the
-	 filter entries by ifcall9.  */
-      if ((!(relax_status & NDS32_RELAX_JUMP_IFC_DONE) && ptr->enable == 1)
-	  || ((relax_status & NDS32_RELAX_JUMP_IFC_DONE)
-	      && ptr->ex9_enable == 1))
-	{
-	  irel_ptr = ptr->irel_head;
-	  if (ptr->h == NULL)
-	    {
-	      /* Local symbol.  */
-	      internal_relocs = _bfd_elf_link_read_relocs
-		(ptr->sec->owner, ptr->sec, NULL, NULL, TRUE /* keep_memory */);
-	      irelend = internal_relocs + ptr->sec->reloc_count;
-
-	      if (!nds32_get_section_contents (ptr->sec->owner, ptr->sec,
-					       &contents, TRUE))
-		return FALSE;
-
-	      while (irel_ptr)
-		{
-		  if (irel_ptr->keep == 0 && irel_ptr->next)
-		    {
-		      /* The one can be replaced.  We have to check whether
-			 there is any alignment point in the region.  */
-		      irel = irel_ptr->irel;
-		      while (((irel_ptr->next->keep == 0
-			       && irel < irel_ptr->next->irel)
-			      || (irel_ptr->next->keep == 1 && irel < irelend))
-			     && !(ELF32_R_TYPE (irel->r_info) == R_NDS32_LABEL
-				  && (irel->r_addend & 0x1f) == 2))
-			irel++;
-		      if (irel >= irelend
-			  || !(ELF32_R_TYPE (irel->r_info) == R_NDS32_LABEL
-			       && (irel->r_addend & 0x1f) == 2
-			       && ((irel->r_offset - get_nds32_elf_blank_total
-				    (&relax_blank_list, irel->r_offset, 1))
-				   & 0x02) == 0))
-			{
-			  /* Replace by ifcall9.  */
-			  bfd_putb16 (insn16, contents + irel_ptr->irel->r_offset);
-			  if (!insert_nds32_elf_blank_recalc_total
-			      (&relax_blank_list, irel_ptr->irel->r_offset + 2, 2))
-			    return FALSE;
-			  irel_ptr->irel->r_info =
-			    ELF32_R_INFO (ELF32_R_SYM (irel_ptr->irel->r_info),
-					  R_NDS32_10IFCU_PCREL_RELA);
-			}
-		    }
-		  irel_ptr = irel_ptr->next;
-		}
-
-	      /* Delete the redundant code.  */
-	      if (relax_blank_list)
-		{
-		  nds32_elf_relax_delete_blanks (ptr->sec->owner, ptr->sec,
-						 relax_blank_list);
-		  relax_blank_list = NULL;
-		}
-	    }
-	  else
-	    {
-	      /* Global symbol.  */
-	      while (irel_ptr)
-		{
-		  if (irel_ptr->keep == 0 && irel_ptr->next)
-		    {
-		      /* The one can be replaced, and we have to check
-			 whether there is any alignment point in the region.  */
-		      internal_relocs = _bfd_elf_link_read_relocs
-			(irel_ptr->sec->owner, irel_ptr->sec, NULL, NULL,
-			 TRUE /* keep_memory */);
-		      irelend = internal_relocs + irel_ptr->sec->reloc_count;
-		      if (!nds32_get_section_contents (irel_ptr->sec->owner,
-						       irel_ptr->sec, &contents,
-						       TRUE))
-			return FALSE;
-
-		      irel = irel_ptr->irel;
-		      while (((irel_ptr->sec == irel_ptr->next->sec
-			       && irel_ptr->next->keep == 0
-			       && irel < irel_ptr->next->irel)
-			      || ((irel_ptr->sec != irel_ptr->next->sec
-				   || irel_ptr->next->keep == 1)
-				  && irel < irelend))
-			     && !(ELF32_R_TYPE (irel->r_info) == R_NDS32_LABEL
-				  && (irel->r_addend & 0x1f) == 2))
-			irel++;
-		      if (irel >= irelend
-			  || !(ELF32_R_TYPE (irel->r_info) == R_NDS32_LABEL
-			       && (irel->r_addend & 0x1f) == 2
-			       && ((irel->r_offset
-				    - get_nds32_elf_blank_total (&relax_blank_list,
-							    irel->r_offset, 1)) & 0x02) == 0))
-			{
-			  /* Replace by ifcall9.  */
-			  bfd_putb16 (insn16, contents + irel_ptr->irel->r_offset);
-			  if (!insert_nds32_elf_blank_recalc_total
-			      (&relax_blank_list, irel_ptr->irel->r_offset + 2, 2))
-			    return FALSE;
-
-			  /* Delete the redundant code, and clear the relocation.  */
-			  nds32_elf_relax_delete_blanks (irel_ptr->sec->owner,
-							 irel_ptr->sec,
-							 relax_blank_list);
-			  irel_ptr->irel->r_info =
-			    ELF32_R_INFO (ELF32_R_SYM (irel_ptr->irel->r_info),
-					  R_NDS32_10IFCU_PCREL_RELA);
-			  relax_blank_list = NULL;
-			}
-		    }
-
-		  irel_ptr = irel_ptr->next;
-		}
-	    }
-	}
-      ptr = ptr->next;
-    }
-
-  return TRUE;
-}
-
-/* Relocate ifcall.  */
-
-static bfd_boolean
-nds32_elf_ifc_reloc (void)
-{
-  struct elf_nds32_ifc_symbol_entry *ptr = ifc_symbol_head;
-  struct elf_nds32_ifc_irel_list *irel_ptr = NULL;
-  struct elf_nds32_ifc_irel_list *irel_keeper = NULL;
-  bfd_vma relocation, address;
-  unsigned short insn16;
-  bfd_byte *contents = NULL;
-  static bfd_boolean done = FALSE;
-
-  if (done)
-    return TRUE;
-
-  done = TRUE;
-
-  while (ptr)
-    {
-      /* Check the entry is enable ifcall.  */
-      if (ptr->enable == 1 || ptr->ex9_enable == 1)
-	{
-	  /* Get the reserve jump.  */
-	  irel_ptr = ptr->irel_head;
-	  while (irel_ptr)
-	    {
-	      if (irel_ptr->keep == 1)
-		{
-		  irel_keeper = irel_ptr;
-		  break;
-		}
-	      irel_ptr = irel_ptr->next;
-	    }
-
-	  irel_ptr = ptr->irel_head;
-	  if (ptr->h == NULL)
-	    {
-	      /* Local symbol.  */
-	      if (!nds32_get_section_contents (ptr->sec->owner, ptr->sec,
-					       &contents, TRUE))
-		return FALSE;
-
-	      while (irel_ptr)
-		{
-		  if (irel_ptr->keep == 0
-		      && ELF32_R_TYPE (irel_ptr->irel->r_info) == R_NDS32_10IFCU_PCREL_RELA)
-		    {
-		      relocation = irel_keeper->irel->r_offset;
-		      relocation = relocation - irel_ptr->irel->r_offset;
-		      while (irel_keeper && relocation > 1022)
-			{
-			  irel_keeper = irel_keeper->next;
-			  if (irel_keeper && irel_keeper->keep == 1)
-			    {
-			      relocation = irel_keeper->irel->r_offset;
-			      relocation = relocation - irel_ptr->irel->r_offset;
-			    }
-			}
-		      if (relocation > 1022)
-			{
-			  /* Double check.  */
-			  irel_keeper = ptr->irel_head;
-			  while (irel_keeper)
-			    {
-			      if (irel_keeper->keep == 1)
-				{
-				  relocation = irel_keeper->irel->r_offset;
-				  relocation = relocation - irel_ptr->irel->r_offset;
-				}
-			      if (relocation <= 1022)
-				break;
-			      irel_keeper = irel_keeper->next;
-			    }
-			  if (!irel_keeper)
-			    return FALSE;
-			}
-		      irel_ptr->irel->r_info =
-			ELF32_R_INFO (ELF32_R_SYM (irel_ptr->irel->r_info),
-				      R_NDS32_NONE);
-		      insn16 = INSN_IFCALL9 | (relocation >> 1);
-		      bfd_putb16 (insn16, contents + irel_ptr->irel->r_offset);
-		    }
-		  irel_ptr = irel_ptr->next;
-		}
-	    }
-	  else
-	    {
-	      /* Global symbol.  */
-	      while (irel_ptr)
-		{
-		  if (irel_ptr->keep == 0
-		      && ELF32_R_TYPE (irel_ptr->irel->r_info) == R_NDS32_10IFCU_PCREL_RELA)
-		    {
-		      /* Get the distance between ifcall and jump.  */
-		      relocation = (irel_keeper->irel->r_offset
-				    + irel_keeper->sec->output_section->vma
-				    + irel_keeper->sec->output_offset);
-		      address = (irel_ptr->irel->r_offset
-				 + irel_ptr->sec->output_section->vma
-				 + irel_ptr->sec->output_offset);
-		      relocation = relocation - address;
-
-		      /* The distance is over ragne, find callee again.  */
-		      while (irel_keeper && relocation > 1022)
-			{
-			  irel_keeper = irel_keeper->next;
-			  if (irel_keeper && irel_keeper->keep ==1)
-			    {
-			      relocation = (irel_keeper->irel->r_offset
-					    + irel_keeper->sec->output_section->vma
-					    + irel_keeper->sec->output_offset);
-			      relocation = relocation - address;
-			    }
-			}
-
-		      if (relocation > 1022)
-			{
-			  /* Double check.  */
-			  irel_keeper = ptr->irel_head;
-			  while (irel_keeper)
-			    {
-			      if (irel_keeper->keep == 1)
-				{
-
-				  relocation = (irel_keeper->irel->r_offset
-						+ irel_keeper->sec->output_section->vma
-						+ irel_keeper->sec->output_offset);
-				  relocation = relocation - address;
-				}
-			      if (relocation <= 1022)
-				break;
-			      irel_keeper = irel_keeper->next;
-			    }
-			  if (!irel_keeper)
-			    return FALSE;
-			}
-		      if (!nds32_get_section_contents
-			  (irel_ptr->sec->owner, irel_ptr->sec, &contents, TRUE))
-			return FALSE;
-		      insn16 = INSN_IFCALL9 | (relocation >> 1);
-		      bfd_putb16 (insn16, contents + irel_ptr->irel->r_offset);
-		      irel_ptr->irel->r_info =
-			ELF32_R_INFO (ELF32_R_SYM (irel_ptr->irel->r_info),
-				      R_NDS32_NONE);
-		    }
-		  irel_ptr =irel_ptr->next;
-		}
-	    }
-	}
-      ptr = ptr->next;
-    }
-
-  return TRUE;
-}
-
-/* End of IFC relaxation.  */
-
-/* EX9 Instruction Table Relaxation.  */
-
-/* Global hash list.  */
-struct elf_link_hash_entry_list
-{
-  struct elf_link_hash_entry *h;
-  struct elf_link_hash_entry_list *next;
-};
-
-/* Save different destination but same insn.  */
-struct elf_link_hash_entry_mul_list
-{
-  /* Global symbol times.  */
-  int times;
-  /* Save relocation for each global symbol but useful??  */
-  Elf_Internal_Rela *irel;
-  /* For sethi, two sethi may have the same high-part but different low-parts.  */
-  Elf_Internal_Rela rel_backup;
-  struct elf_link_hash_entry_list *h_list;
-  struct elf_link_hash_entry_mul_list *next;
-};
-
-/* Instruction hash table.  */
-struct elf_nds32_code_hash_entry
-{
-  struct bfd_hash_entry root;
-  int times;
-  /* For insn that can use relocation or constant ex: sethi.  */
-  int const_insn;
-  asection *sec;
-  struct elf_link_hash_entry_mul_list *m_list;
-  /* Using r_addend.  */
-  Elf_Internal_Rela *irel;
-  /* Using r_info.  */
-  Elf_Internal_Rela rel_backup;
-};
-
-/* Instruction count list.  */
-struct elf_nds32_insn_times_entry
-{
-  const char *string;
-  int times;
-  int order;
-  asection *sec;
-  struct elf_link_hash_entry_mul_list *m_list;
-  Elf_Internal_Rela *irel;
-  Elf_Internal_Rela rel_backup;
-  struct elf_nds32_insn_times_entry *next;
-};
-
-/* J and JAL symbol list.  */
-struct elf_nds32_symbol_entry
-{
-  char *string;
-  unsigned long insn;
-  struct elf_nds32_symbol_entry *next;
-};
-
-/* Relocation list.  */
-struct elf_nds32_irel_entry
-{
-  Elf_Internal_Rela *irel;
-  struct elf_nds32_irel_entry *next;
-};
-
-/* ex9.it insn need to be fixed.  */
-struct elf_nds32_ex9_refix
-{
-  Elf_Internal_Rela *irel;
-  asection *sec;
-  struct elf_link_hash_entry *h;
-  int order;
-  struct elf_nds32_ex9_refix *next;
-};
-
-static struct bfd_hash_table ex9_code_table;
-static struct elf_nds32_insn_times_entry *ex9_insn_head = NULL;
-static struct elf_nds32_ex9_refix *ex9_refix_head = NULL;
-
-/* EX9 hash function.  */
-
-static struct bfd_hash_entry *
-nds32_elf_code_hash_newfunc (struct bfd_hash_entry *entry,
-			     struct bfd_hash_table *table,
-			     const char *string)
-{
-  struct elf_nds32_code_hash_entry *ret;
-
-  /* Allocate the structure if it has not already been allocated by a
-     subclass.  */
-  if (entry == NULL)
-    {
-      entry = (struct bfd_hash_entry *)
-	bfd_hash_allocate (table, sizeof (*ret));
-      if (entry == NULL)
-	return entry;
-    }
-
-  /* Call the allocation method of the superclass.  */
-  entry = bfd_hash_newfunc (entry, table, string);
-  if (entry == NULL)
-    return entry;
-
-  ret = (struct elf_nds32_code_hash_entry*) entry;
-  ret->times = 0;
-  ret->const_insn = 0;
-  ret->m_list = NULL;
-  ret->sec = NULL;
-  ret->irel = NULL;
-  return &ret->root;
-}
-
-/* Insert ex9 entry
-   this insert must be stable sorted by times.  */
-
-static void
-nds32_elf_ex9_insert_entry (struct elf_nds32_insn_times_entry *ptr)
-{
-  struct elf_nds32_insn_times_entry *temp;
-  struct elf_nds32_insn_times_entry *temp2;
-
-  if (ex9_insn_head == NULL)
-    {
-      ex9_insn_head = ptr;
-      ptr->next = NULL;
-    }
-  else
-    {
-      temp = ex9_insn_head;
-      temp2 = ex9_insn_head;
-      while (temp->next &&
-	     (temp->next->times >= ptr->times
-	      || temp->times == -1))
-	{
-	  if (temp->times == -1)
-	    temp2 = temp;
-	  temp = temp->next;
-	}
-      if (ptr->times > temp->times && temp->times != -1)
-	{
-	  ptr->next = temp;
-	  if (temp2->times == -1)
-	    temp2->next = ptr;
-	  else
-	    ex9_insn_head = ptr;
-	}
-      else if (temp->next == NULL)
-	{
-	  temp->next = ptr;
-	  ptr->next = NULL;
-	}
-      else
-	{
-	  ptr->next = temp->next;
-	  temp->next = ptr;
-	}
-    }
-}
-
-/* Examine each insn times in hash table.
-   Handle multi-link hash entry.
-
-   TODO: This function doesn't assign so much info since it is fake.  */
-
-static int
-nds32_elf_examine_insn_times (struct elf_nds32_code_hash_entry *h)
-{
-  struct elf_nds32_insn_times_entry *ptr;
-  int times;
-
-  if (h->m_list == NULL)
-    {
-      /* Local symbol insn or insn without relocation.  */
-      if (h->times < 3)
-	return TRUE;
-
-      ptr = (struct elf_nds32_insn_times_entry *)
-	bfd_malloc (sizeof (struct elf_nds32_insn_times_entry));
-      ptr->times = h->times;
-      ptr->string = h->root.string;
-      ptr->m_list = NULL;
-      ptr->sec = h->sec;
-      ptr->irel = h->irel;
-      ptr->rel_backup = h->rel_backup;
-      nds32_elf_ex9_insert_entry (ptr);
-    }
-  else
-    {
-      /* Global symbol insn.  */
-      /* Only sethi insn has multiple m_list.  */
-      struct elf_link_hash_entry_mul_list *m_list = h->m_list;
-
-      times = 0;
-      while (m_list)
-	{
-	  times += m_list->times;
-	  m_list = m_list->next;
-	}
-      if (times >= 3)
-	{
-	  m_list = h->m_list;
-	  ptr = (struct elf_nds32_insn_times_entry *)
-	    bfd_malloc (sizeof (struct elf_nds32_insn_times_entry));
-	  ptr->times = times; /* Use the total times.  */
-	  ptr->string = h->root.string;
-	  ptr->m_list = m_list;
-	  ptr->sec = h->sec;
-	  ptr->irel = m_list->irel;
-	  ptr->rel_backup = m_list->rel_backup;
-	  nds32_elf_ex9_insert_entry (ptr);
-	}
-      if (h->const_insn == 1)
-	{
-	  /* sethi with constant value.  */
-	  if (h->times < 3)
-	    return TRUE;
-
-	  ptr = (struct elf_nds32_insn_times_entry *)
-	    bfd_malloc (sizeof (struct elf_nds32_insn_times_entry));
-	  ptr->times = h->times;
-	  ptr->string = h->root.string;
-	  ptr->m_list = NULL;
-	  ptr->sec = NULL;
-	  ptr->irel = NULL;
-	  ptr->rel_backup = h->rel_backup;
-	  nds32_elf_ex9_insert_entry (ptr);
-	}
-    }
-  return TRUE;
-}
-
-/* Count each insn times in hash table.
-   Handle multi-link hash entry.  */
-
-static int
-nds32_elf_count_insn_times (struct elf_nds32_code_hash_entry *h)
-{
-  int reservation, times;
-  unsigned long relocation, min_relocation;
-  struct elf_nds32_insn_times_entry *ptr;
-
-  if (h->m_list == NULL)
-    {
-      /* Local symbol insn or insn without relocation.  */
-      if (h->times < 3)
-	return TRUE;
-      ptr = (struct elf_nds32_insn_times_entry *)
-	bfd_malloc (sizeof (struct elf_nds32_insn_times_entry));
-      ptr->times = h->times;
-      ptr->string = h->root.string;
-      ptr->m_list = NULL;
-      ptr->sec = h->sec;
-      ptr->irel = h->irel;
-      ptr->rel_backup = h->rel_backup;
-      nds32_elf_ex9_insert_entry (ptr);
-    }
-  else
-    {
-      /* Global symbol insn.  */
-      /* Only sethi insn has multiple m_list.  */
-      struct elf_link_hash_entry_mul_list *m_list = h->m_list;
-
-      if (ELF32_R_TYPE (m_list->rel_backup.r_info) == R_NDS32_HI20_RELA
-	  && m_list->next != NULL)
-	{
-	  /* Sethi insn has different symbol or addend but has same hi20.  */
-	  times = 0;
-	  reservation = 1;
-	  relocation = 0;
-	  min_relocation = 0xffffffff;
-	  while (m_list)
-	    {
-	      /* Get the minimum sethi address
-		 and calculate how many entry the sethi-list have to use.  */
-	      if ((m_list->h_list->h->root.type == bfd_link_hash_defined
-		   || m_list->h_list->h->root.type == bfd_link_hash_defweak)
-		  && (m_list->h_list->h->root.u.def.section != NULL
-		      && m_list->h_list->h->root.u.def.section->output_section != NULL))
-		{
-		  relocation = (m_list->h_list->h->root.u.def.value +
-				m_list->h_list->h->root.u.def.section->output_section->vma +
-				m_list->h_list->h->root.u.def.section->output_offset);
-		  relocation += m_list->irel->r_addend;
-		}
-	      else
-		relocation = 0;
-	      if (relocation < min_relocation)
-		min_relocation = relocation;
-	      times += m_list->times;
-	      m_list = m_list->next;
-	    }
-	  if (min_relocation < ex9_relax_size)
-	    reservation = (min_relocation >> 12) + 1;
-	  else
-	    reservation = (min_relocation >> 12)
-			  - ((min_relocation - ex9_relax_size) >> 12) + 1;
-	  if (reservation < (times / 3))
-	    {
-	      /* Efficient enough to use ex9.  */
-	      int i;
-
-	      for (i = reservation ; i > 0; i--)
-		{
-		  /* Allocate number of reservation ex9 entry.  */
-		  ptr = (struct elf_nds32_insn_times_entry *)
-		    bfd_malloc (sizeof (struct elf_nds32_insn_times_entry));
-		  ptr->times = h->m_list->times / reservation;
-		  ptr->string = h->root.string;
-		  ptr->m_list = h->m_list;
-		  ptr->sec = h->sec;
-		  ptr->irel = h->m_list->irel;
-		  ptr->rel_backup = h->m_list->rel_backup;
-		  nds32_elf_ex9_insert_entry (ptr);
-		}
-	    }
-	}
-      else
-	{
-	  /* Normal global symbol that means no different address symbol
-	     using same ex9 entry.  */
-	  if (m_list->times >= 3)
-	    {
-	      ptr = (struct elf_nds32_insn_times_entry *)
-		bfd_malloc (sizeof (struct elf_nds32_insn_times_entry));
-	      ptr->times = m_list->times;
-	      ptr->string = h->root.string;
-	      ptr->m_list = h->m_list;
-	      ptr->sec = h->sec;
-	      ptr->irel = h->m_list->irel;
-	      ptr->rel_backup = h->m_list->rel_backup;
-	      nds32_elf_ex9_insert_entry (ptr);
-	    }
-	}
-
-      if (h->const_insn == 1)
-	{
-	  /* sethi with constant value.  */
-	  if (h->times < 3)
-	    return TRUE;
-
-	  ptr = (struct elf_nds32_insn_times_entry *)
-	    bfd_malloc (sizeof (struct elf_nds32_insn_times_entry));
-	  ptr->times = h->times;
-	  ptr->string = h->root.string;
-	  ptr->m_list = NULL;
-	  ptr->sec = NULL;
-	  ptr->irel = NULL;
-	  ptr->rel_backup = h->rel_backup;
-	  nds32_elf_ex9_insert_entry (ptr);
-	}
-    }
-
-  return TRUE;
-}
-
-/* Hash table traverse function.  */
-
-static void
-nds32_elf_code_hash_traverse (int (*func) (struct elf_nds32_code_hash_entry*))
-{
-  unsigned int i;
-
-  ex9_code_table.frozen = 1;
-  for (i = 0; i < ex9_code_table.size; i++)
-    {
-      struct bfd_hash_entry *p;
-
-      for (p = ex9_code_table.table[i]; p != NULL; p = p->next)
-	if (!func ((struct elf_nds32_code_hash_entry *) p))
-	  goto out;
-    }
-out:
-  ex9_code_table.frozen = 0;
-}
-
-
-/* Give order number to insn list.  */
-
-static void
-nds32_elf_order_insn_times (struct bfd_link_info *info)
-{
-  struct elf_nds32_insn_times_entry *ex9_insn;
-  struct elf_nds32_insn_times_entry *temp = NULL;
-  struct elf_nds32_link_hash_table *table;
-  int ex9_limit;
-  int number = 0;
-
-  if (ex9_insn_head == NULL)
-    return;
-
-/* The max number of entries is 512.  */
-  ex9_insn = ex9_insn_head;
-  table = nds32_elf_hash_table (info);
-  ex9_limit = table->ex9_limit;
-
-  ex9_insn = ex9_insn_head;
-
-  while (ex9_insn != NULL && number < ex9_limit)
-    {
-      ex9_insn->order = number;
-      number++;
-      temp = ex9_insn;
-      ex9_insn = ex9_insn->next;
-    }
-
-  if (ex9_insn && temp)
-    temp->next = NULL;
-
-  while (ex9_insn != NULL)
-    {
-      /* Free useless entry.  */
-      temp = ex9_insn;
-      ex9_insn = ex9_insn->next;
-      free (temp);
-    }
-}
-
-/* Build .ex9.itable section.  */
-
-static void
-nds32_elf_ex9_build_itable (struct bfd_link_info *link_info)
-{
-  asection *table_sec;
-  struct elf_nds32_insn_times_entry *ptr;
-  bfd *it_abfd;
-  int number = 0;
-  bfd_byte *contents = NULL;
-
-  for (it_abfd = link_info->input_bfds; it_abfd != NULL;
-       it_abfd = it_abfd->link.next)
-    {
-      /* Find the section .ex9.itable, and put all entries into it.  */
-      table_sec = bfd_get_section_by_name (it_abfd, ".ex9.itable");
-      if (table_sec != NULL)
-	{
-	  if (!nds32_get_section_contents (it_abfd, table_sec, &contents, TRUE))
-	    return;
-
-	  for (ptr = ex9_insn_head; ptr !=NULL ; ptr = ptr->next)
-	    number++;
-
-	  table_sec->size = number * 4;
-
-	  if (number == 0)
-	    return;
-
-	  elf_elfheader (link_info->output_bfd)->e_flags |= E_NDS32_HAS_EX9_INST;
-	  number = 0;
-	  for (ptr = ex9_insn_head; ptr !=NULL ; ptr = ptr->next)
-	    {
-	      long val;
-
-	      val = strtol (ptr->string, NULL, 16);
-	      bfd_putb32 ((bfd_vma) val, (char *) contents + (number * 4));
-	      number++;
-	    }
-	  break;
-	}
-    }
-}
-
-/* Get insn with regs according to relocation type.  */
-
-static void
-nds32_elf_get_insn_with_reg (Elf_Internal_Rela *irel,
-			     uint32_t insn, uint32_t *insn_with_reg)
-{
-  reloc_howto_type *howto = NULL;
-
-  if (irel == NULL
-      || (ELF32_R_TYPE (irel->r_info) >= (int) ARRAY_SIZE (nds32_elf_howto_table)
-	  && (ELF32_R_TYPE (irel->r_info) - R_NDS32_RELAX_ENTRY)
-	     >= (int) ARRAY_SIZE (nds32_elf_relax_howto_table)))
-    {
-      *insn_with_reg = insn;
-      return;
-    }
-
-  howto = bfd_elf32_bfd_reloc_type_table_lookup (ELF32_R_TYPE (irel->r_info));
-  *insn_with_reg = insn & (0xffffffff ^ howto->dst_mask);
-}
-
-/* Mask number of address bits according to relocation.  */
-
-static unsigned long
-nds32_elf_irel_mask (Elf_Internal_Rela *irel)
-{
-  reloc_howto_type *howto = NULL;
-
-  if (irel == NULL
-      || (ELF32_R_TYPE (irel->r_info) >= (int) ARRAY_SIZE (nds32_elf_howto_table)
-	  && (ELF32_R_TYPE (irel->r_info) - R_NDS32_RELAX_ENTRY)
-	     >= (int) ARRAY_SIZE (nds32_elf_relax_howto_table)))
-    return 0;
-
-  howto = bfd_elf32_bfd_reloc_type_table_lookup (ELF32_R_TYPE (irel->r_info));
-  return howto->dst_mask;
-}
-
-static void
-nds32_elf_insert_irel_entry (struct elf_nds32_irel_entry **irel_list,
-			     struct elf_nds32_irel_entry *irel_ptr)
-{
-  if (*irel_list == NULL)
-    {
-      *irel_list = irel_ptr;
-      irel_ptr->next = NULL;
-    }
-  else
-    {
-      irel_ptr->next = *irel_list;
-      *irel_list = irel_ptr;
-    }
-}
-
-static void
-nds32_elf_ex9_insert_fix (asection * sec, Elf_Internal_Rela * irel,
-			  struct elf_link_hash_entry *h, int order)
-{
-  struct elf_nds32_ex9_refix *ptr;
-
-  ptr = bfd_malloc (sizeof (struct elf_nds32_ex9_refix));
-  ptr->sec = sec;
-  ptr->irel = irel;
-  ptr->h = h;
-  ptr->order = order;
-  ptr->next = NULL;
-
-  if (ex9_refix_head == NULL)
-    ex9_refix_head = ptr;
-  else
-    {
-      struct elf_nds32_ex9_refix *temp = ex9_refix_head;
-
-      while (temp->next != NULL)
-	temp = temp->next;
-      temp->next = ptr;
-    }
-}
-
-enum
-{
-  DATA_EXIST = 1,
-  CLEAN_PRE = 1 << 1,
-  PUSH_PRE = 1 << 2
-};
-
-/* Check relocation type if supporting for ex9.  */
-
-static int
-nds32_elf_ex9_relocation_check (struct bfd_link_info *info,
-				Elf_Internal_Rela **irel,
-				Elf_Internal_Rela *irelend,
-				nds32_elf_blank_t *relax_blank_list,
-				asection *sec,bfd_vma *off,
-				bfd_byte *contents)
-{
-  /* Suppress ex9 if `.no_relax ex9' or inner loop.  */
-  bfd_boolean nested_ex9, nested_loop;
-  bfd_boolean ex9_loop_aware;
-  /* We use the highest 1 byte of result to record
-     how many bytes location counter has to move.  */
-  int result = 0;
-  Elf_Internal_Rela *irel_save = NULL;
-  struct elf_nds32_link_hash_table *table;
-
-  table = nds32_elf_hash_table (info);
-  ex9_loop_aware = table->ex9_loop_aware;
-
-  while ((*irel) != NULL && (*irel) < irelend && *off == (*irel)->r_offset)
-    {
-      switch (ELF32_R_TYPE ((*irel)->r_info))
-	{
-	case R_NDS32_RELAX_REGION_BEGIN:
-	  /* Ignore code block.  */
-	  nested_ex9 = FALSE;
-	  nested_loop = FALSE;
-	  if (((*irel)->r_addend & R_NDS32_RELAX_REGION_NO_EX9_FLAG)
-	      || (ex9_loop_aware
-		  && ((*irel)->r_addend & R_NDS32_RELAX_REGION_INNERMOST_LOOP_FLAG)))
-	    {
-	      /* Check the region if loop or not.  If it is true and
-		 ex9-loop-aware is true, ignore the region till region end.  */
-	      /* To save the status for in .no_relax ex9 region and
-		 loop region to conform the block can do ex9 relaxation.  */
-	      nested_ex9 = ((*irel)->r_addend & R_NDS32_RELAX_REGION_NO_EX9_FLAG);
-	      nested_loop = (ex9_loop_aware
-			     && ((*irel)->r_addend & R_NDS32_RELAX_REGION_INNERMOST_LOOP_FLAG));
-	      while ((*irel) && (*irel) < irelend && (nested_ex9 || nested_loop))
-		{
-		  (*irel)++;
-		  if (ELF32_R_TYPE ((*irel)->r_info) == R_NDS32_RELAX_REGION_BEGIN)
-		    {
-		      /* There may be nested region.  */
-		      if (((*irel)->r_addend & R_NDS32_RELAX_REGION_NO_EX9_FLAG) != 0)
-			nested_ex9 = TRUE;
-		      else if (ex9_loop_aware
-			       && ((*irel)->r_addend & R_NDS32_RELAX_REGION_INNERMOST_LOOP_FLAG))
-			nested_loop = TRUE;
-		    }
-		  else if (ELF32_R_TYPE ((*irel)->r_info) == R_NDS32_RELAX_REGION_END)
-		    {
-		      /* The end of region.  */
-		      if (((*irel)->r_addend & R_NDS32_RELAX_REGION_NO_EX9_FLAG) != 0)
-			nested_ex9 = FALSE;
-		      else if (ex9_loop_aware
-			       && ((*irel)->r_addend & R_NDS32_RELAX_REGION_INNERMOST_LOOP_FLAG))
-			nested_loop = FALSE;
-		    }
-		  else if (ELF32_R_TYPE ((*irel)->r_info) == R_NDS32_LABEL
-			   && ((*irel)->r_addend & 0x1f) == 2)
-		    {
-		      /* Alignment exist in the region.  */
-		      result |= CLEAN_PRE;
-		      if (((*irel)->r_offset -
-			   get_nds32_elf_blank_total (&relax_blank_list,
-						      (*irel)->r_offset, 0)) & 0x02)
-			result |= PUSH_PRE;
-		    }
-		}
-	      if ((*irel) >= irelend)
-		*off = sec->size;
-	      else
-		*off = (*irel)->r_offset;
-
-	      /* The final instruction in the region, regard this one as data to ignore it.  */
-	      result |= DATA_EXIST;
-	      return result;
-	    }
-	  break;
-
-	case R_NDS32_LABEL:
-	  if (((*irel)->r_addend & 0x1f) == 2)
-	    {
-	      /* Check this point is align and decide to do ex9 or not.  */
-	      result |= CLEAN_PRE;
-	      if (((*irel)->r_offset -
-		   get_nds32_elf_blank_total (&relax_blank_list,
-					      (*irel)->r_offset, 0)) & 0x02)
-		result |= PUSH_PRE;
-	    }
-	  break;
-	case R_NDS32_32_RELA:
-	  /* Data.  */
-	  result |= (4 << 24);
-	  result |= DATA_EXIST;
-	  break;
-	case R_NDS32_16_RELA:
-	  /* Data.  */
-	  result |= (2 << 24);
-	  result |= DATA_EXIST;
-	  break;
-	case R_NDS32_DATA:
-	  /* Data.  */
-	  /* The least code alignment is 2.  If the data is only one byte,
-	     we have to shift one more byte.  */
-	  if ((*irel)->r_addend == 1)
-	    result |= ((*irel)->r_addend << 25) ;
-	  else
-	    result |= ((*irel)->r_addend << 24) ;
-
-	  result |= DATA_EXIST;
-	  break;
-
-	case R_NDS32_25_PCREL_RELA:
-	case R_NDS32_SDA16S3_RELA:
-	case R_NDS32_SDA15S3_RELA:
-	case R_NDS32_SDA15S3:
-	case R_NDS32_SDA17S2_RELA:
-	case R_NDS32_SDA15S2_RELA:
-	case R_NDS32_SDA12S2_SP_RELA:
-	case R_NDS32_SDA12S2_DP_RELA:
-	case R_NDS32_SDA15S2:
-	case R_NDS32_SDA18S1_RELA:
-	case R_NDS32_SDA15S1_RELA:
-	case R_NDS32_SDA15S1:
-	case R_NDS32_SDA19S0_RELA:
-	case R_NDS32_SDA15S0_RELA:
-	case R_NDS32_SDA15S0:
-	case R_NDS32_HI20_RELA:
-	case R_NDS32_LO12S0_ORI_RELA:
-	case R_NDS32_LO12S0_RELA:
-	case R_NDS32_LO12S1_RELA:
-	case R_NDS32_LO12S2_RELA:
-	  /* These relocation is supported ex9 relaxation currently.  */
-	  /* We have to save the relocation for using later, since we have
-	     to check there is any alignment in the same address.  */
-	  irel_save = *irel;
-	  break;
-	default:
-	  /* Not support relocations.  */
-	  if (ELF32_R_TYPE ((*irel)->r_info) < ARRAY_SIZE (nds32_elf_howto_table)
-	      && ELF32_R_TYPE ((*irel)->r_info) != R_NDS32_NONE
-	      && ELF32_R_TYPE ((*irel)->r_info) != R_NDS32_INSN16)
-	    {
-	      /* Note: To optimize aggressively, it maybe can ignore R_NDS32_INSN16 here.
-		 But we have to consider if there is any side-effect.  */
-	      if (!(result & DATA_EXIST))
-		{
-		  /* We have to confirm there is no data relocation in the
-		     same address.  In general case, this won't happen.  */
-		  /* We have to do ex9 conservative, for those relocation not
-		     considerd we ignore instruction.  */
-		  result |= DATA_EXIST;
-		  if (*(contents + *off) & 0x80)
-		    result |= (2 << 24);
-		  else
-		    result |= (4 << 24);
-		  break;
-		}
-	    }
-	}
-      if ((*irel) < irelend
-	  && ((*irel) + 1) < irelend
-	  && (*irel)->r_offset == ((*irel) + 1)->r_offset)
-	/* There are relocations pointing to the same address, we have to
-	   check all of them.  */
-	(*irel)++;
-      else
-	{
-	  if (irel_save)
-	    *irel = irel_save;
-	  return result;
-	}
-    }
-  return result;
-}
-
-/* Replace with ex9 instruction.  */
-
-static bfd_boolean
-nds32_elf_ex9_push_insn (uint16_t insn16, bfd_byte *contents, bfd_vma pre_off,
-			 nds32_elf_blank_t **relax_blank_list,
-			 struct elf_nds32_irel_entry *pre_irel_ptr,
-			 struct elf_nds32_irel_entry **irel_list)
-{
-  if (insn16 != 0)
-    {
-      /* Implement the ex9 relaxation.  */
-      bfd_putb16 (insn16, contents + pre_off);
-      if (!insert_nds32_elf_blank_recalc_total (relax_blank_list,
-						pre_off + 2, 2))
-	return FALSE;
-      if (pre_irel_ptr != NULL)
-	nds32_elf_insert_irel_entry (irel_list, pre_irel_ptr);
-    }
-  return TRUE;
-}
-
-/* Replace input file instruction which is in ex9 itable.  */
-
-static bfd_boolean
-nds32_elf_ex9_replace_instruction (struct bfd_link_info *info, bfd *abfd, asection *sec)
-{
-  struct elf_nds32_insn_times_entry *ex9_insn = ex9_insn_head;
-  bfd_byte *contents = NULL;
-  bfd_vma off;
-  uint16_t insn16, insn_ex9;
-  /* `pre_*' are used to track previous instruction that can use ex9.it.  */
-  bfd_vma pre_off = -1;
-  uint16_t pre_insn16 = 0;
-  struct elf_nds32_irel_entry *pre_irel_ptr = NULL;
-  Elf_Internal_Rela *internal_relocs;
-  Elf_Internal_Rela *irel;
-  Elf_Internal_Rela *irelend;
-  Elf_Internal_Shdr *symtab_hdr;
-  Elf_Internal_Sym *isym = NULL;
-  nds32_elf_blank_t *relax_blank_list = NULL;
-  uint32_t insn = 0;
-  uint32_t insn_with_reg = 0;
-  uint32_t it_insn;
-  uint32_t it_insn_with_reg;
-  unsigned long r_symndx;
-  asection *isec;
-  struct elf_nds32_irel_entry *irel_list = NULL;
-  struct elf_link_hash_entry **sym_hashes = elf_sym_hashes (abfd);
-  int data_flag, do_replace, save_irel;
-  struct elf_link_hash_entry_list *h_list;
-
-
-  /* Load section instructions, relocations, and symbol table.  */
-  if (!nds32_get_section_contents (abfd, sec, &contents, TRUE)
-      || !nds32_get_local_syms (abfd, sec, &isym))
-    return FALSE;
-  internal_relocs =
-    _bfd_elf_link_read_relocs (abfd, sec, NULL, NULL, TRUE /* keep_memory */);
-  irelend = internal_relocs + sec->reloc_count;
-  symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
-
-  off = 0;
-
-  /* Check if the object enable ex9.  */
-  irel = find_relocs_at_address (internal_relocs, internal_relocs,
-				 irelend, R_NDS32_RELAX_ENTRY);
-
-  /* Check this section trigger ex9 relaxation.  */
-  if (irel == NULL
-      || irel >= irelend
-      || ELF32_R_TYPE (irel->r_info) != R_NDS32_RELAX_ENTRY
-      || (ELF32_R_TYPE (irel->r_info) == R_NDS32_RELAX_ENTRY
-	  && !(irel->r_addend & R_NDS32_RELAX_ENTRY_EX9_FLAG)))
-    return TRUE;
-
-  irel = internal_relocs;
-
-  /* Check alignment and fetch proper relocation.  */
-  while (off < sec->size)
-    {
-      struct elf_link_hash_entry *h = NULL;
-      struct elf_nds32_irel_entry *irel_ptr = NULL;
-
-      /* Syn the instruction and the relocation.  */
-      while (irel != NULL && irel < irelend && irel->r_offset < off)
-	irel++;
-
-      data_flag = nds32_elf_ex9_relocation_check (info, &irel, irelend,
-						  relax_blank_list, sec,
-						  &off, contents);
-      if (data_flag & PUSH_PRE)
-	if (!nds32_elf_ex9_push_insn (pre_insn16, contents, pre_off,
-				      &relax_blank_list, pre_irel_ptr,
-				      &irel_list))
-	  return FALSE;
-
-      if (data_flag & CLEAN_PRE)
-	{
-	  pre_off = 0;
-	  pre_insn16 = 0;
-	  pre_irel_ptr = NULL;
-	}
-      if (data_flag & DATA_EXIST)
-	{
-	  /* We save the move offset in the highest byte.  */
-	  off += (data_flag >> 24);
-	  continue;
-	}
-
-      if (*(contents + off) & 0x80)
-	{
-	  /* 2-byte instruction.  */
-	  off += 2;
-	  continue;
-	}
-
-      /* Load the instruction and its opcode with register for comparing.  */
-      ex9_insn = ex9_insn_head;
-      insn = bfd_getb32 (contents + off);
-      insn_with_reg = 0;
-      while (ex9_insn)
-	{
-	  it_insn = strtol (ex9_insn->string, NULL, 16);
-	  it_insn_with_reg = 0;
-	  do_replace = 0;
-	  save_irel = 0;
-
-	  if (irel != NULL && irel < irelend && irel->r_offset == off)
-	    {
-	      /* Insn with relocation.  */
-	      nds32_elf_get_insn_with_reg (irel, insn, &insn_with_reg);
-
-	      if (ex9_insn->irel != NULL)
-		nds32_elf_get_insn_with_reg (ex9_insn->irel, it_insn,
-					     &it_insn_with_reg);
-
-	      if (ex9_insn->irel != NULL
-		  && (ELF32_R_TYPE (irel->r_info) ==
-		      ELF32_R_TYPE (ex9_insn->irel->r_info))
-		  && (insn_with_reg == it_insn_with_reg))
-		{
-		  /* Insn relocation and format is the same as table entry.  */
-
-		  if (ELF32_R_TYPE (irel->r_info) == R_NDS32_25_PCREL_RELA
-		      || ELF32_R_TYPE (irel->r_info) == R_NDS32_LO12S0_ORI_RELA
-		      || ELF32_R_TYPE (irel->r_info) == R_NDS32_LO12S0_RELA
-		      || ELF32_R_TYPE (irel->r_info) == R_NDS32_LO12S1_RELA
-		      || ELF32_R_TYPE (irel->r_info) == R_NDS32_LO12S2_RELA
-		      || (ELF32_R_TYPE (irel->r_info) >= R_NDS32_SDA15S3
-			  && ELF32_R_TYPE (irel->r_info) <= R_NDS32_SDA15S0)
-		      || (ELF32_R_TYPE (irel->r_info) >= R_NDS32_SDA15S3_RELA
-			  && ELF32_R_TYPE (irel->r_info) <= R_NDS32_SDA15S0_RELA)
-		      || (ELF32_R_TYPE (irel->r_info) >= R_NDS32_SDA12S2_DP_RELA
-			  && ELF32_R_TYPE (irel->r_info) <=
-			  R_NDS32_SDA12S2_SP_RELA)
-		      || (ELF32_R_TYPE (irel->r_info) >= R_NDS32_SDA16S3_RELA
-			  && ELF32_R_TYPE (irel->r_info) <= R_NDS32_SDA19S0_RELA))
-		    {
-		      r_symndx = ELF32_R_SYM (irel->r_info);
-		      if (r_symndx < symtab_hdr->sh_info)
-			{
-			  /* Local symbol.  */
-			  int shndx = isym[r_symndx].st_shndx;
-
-			  isec = elf_elfsections (abfd)[shndx]->bfd_section;
-			  if (ex9_insn->sec == isec
-			      && ex9_insn->irel->r_addend == irel->r_addend
-			      && ex9_insn->irel->r_info == irel->r_info)
-			    {
-			      do_replace = 1;
-			      save_irel = 1;
-			    }
-			}
-		      else
-			{
-			  /* External symbol.  */
-			  h = sym_hashes[r_symndx - symtab_hdr->sh_info];
-			  if (ex9_insn->m_list)
-			    {
-			      h_list = ex9_insn->m_list->h_list;
-			      while (h_list)
-				{
-				  if (h == h_list->h
-				      && (ex9_insn->m_list->irel->r_addend ==
-					  irel->r_addend))
-				    {
-				      do_replace = 1;
-				      save_irel = 1;
-				      break;
-				    }
-				  h_list = h_list->next;
-				}
-			    }
-			}
-		    }
-		  else if (ELF32_R_TYPE (irel->r_info) == R_NDS32_HI20_RELA)
-		    {
-		      r_symndx = ELF32_R_SYM (irel->r_info);
-		      if (r_symndx < symtab_hdr->sh_info)
-			{
-			  /* Local symbols.  Compare its base symbol and offset.  */
-			  int shndx = isym[r_symndx].st_shndx;
-
-			  isec = elf_elfsections (abfd)[shndx]->bfd_section;
-			  if (ex9_insn->sec == isec
-			      && ex9_insn->irel->r_addend == irel->r_addend
-			      && ex9_insn->irel->r_info == irel->r_info)
-			    {
-			      do_replace = 1;
-			      save_irel = 1;
-			    }
-			}
-		      else
-			{
-			  /* External symbol.  */
-			  struct elf_link_hash_entry_mul_list *m_list;
-
-			  h = sym_hashes[r_symndx - symtab_hdr->sh_info];
-			  m_list = ex9_insn->m_list;
-
-			  while (m_list)
-			    {
-			      h_list = m_list->h_list;
-
-			      while (h_list)
-				{
-				  if (h == h_list->h
-				      && (m_list->irel->r_addend
-					  == irel->r_addend))
-				    {
-				      do_replace = 1;
-				      save_irel = 1;
-				      if (ex9_insn->next
-					  && ex9_insn->m_list
-					  && ex9_insn->m_list == ex9_insn->next->m_list)
-					{
-					  /* sethi multiple entry must be fixed */
-					  nds32_elf_ex9_insert_fix (sec, irel,
-								    h, ex9_insn->order);
-					}
-				      break;
-				    }
-				  h_list = h_list->next;
-				}
-			      m_list = m_list->next;
-			    }
-			}
-		    }
-		}
-
-	      /* Import table: Check the symbol hash table and the
-		 jump target.  Only R_NDS32_25_PCREL_RELA now.  */
-	      else if (ex9_insn->times == -1
-		       && ELF32_R_TYPE (irel->r_info) == R_NDS32_25_PCREL_RELA)
-		{
-		  nds32_elf_get_insn_with_reg (irel, it_insn, &it_insn_with_reg);
-		  if (insn_with_reg == it_insn_with_reg)
-		    {
-		      char code[10];
-		      bfd_vma relocation;
-
-		      r_symndx = ELF32_R_SYM (irel->r_info);
-		      if (r_symndx >= symtab_hdr->sh_info)
-			{
-			  h = sym_hashes[r_symndx - symtab_hdr->sh_info];
-			  if ((h->root.type == bfd_link_hash_defined
-			       || h->root.type == bfd_link_hash_defweak)
-			      && h->root.u.def.section != NULL
-			      && h->root.u.def.section->output_section != NULL
-			      && h->root.u.def.section->gc_mark == 1
-			      && bfd_is_abs_section (h->root.u.def.section)
-			      && h->root.u.def.value > sec->size)
-			    {
-			      relocation = h->root.u.def.value +
-				h->root.u.def.section->output_section->vma +
-				h->root.u.def.section->output_offset;
-			      relocation += irel->r_addend;
-			      insn = insn_with_reg
-				| ((relocation >> 1) & 0xffffff);
-			      snprintf (code, sizeof (code), "%08x", insn);
-			      if (strcmp (code, ex9_insn->string) == 0)
-				{
-				  do_replace = 1;
-				  save_irel = 1;
-				}
-			    }
-			}
-		    }
-		}
-	      else if (ELF32_R_TYPE (irel->r_info) == R_NDS32_RELAX_REGION_BEGIN
-		       || ELF32_R_TYPE (irel->r_info) == R_NDS32_RELAX_REGION_END
-		       || ELF32_R_TYPE (irel->r_info) == R_NDS32_NONE)
-		{
-		  /* These relocations do not have to relocate contens, so it can
-		     be regard as instruction without relocation.  */
-		  if (insn == it_insn && ex9_insn->irel == NULL)
-		    do_replace = 1;
-		}
-	    }
-	  else
-	    {
-	      /* Instruction without relocation, we only
-		 have to compare their byte code.  */
-	      if (insn == it_insn && ex9_insn->irel == NULL)
-		do_replace = 1;
-	    }
-
-	  /* Insntruction match so replacing the code here.  */
-	  if (do_replace == 1)
-	    {
-	      /* There are two formats of ex9 instruction.  */
-	      if (ex9_insn->order < 32)
-		insn_ex9 = INSN_EX9_IT_2;
-	      else
-		insn_ex9 = INSN_EX9_IT_1;
-	      insn16 = insn_ex9 | ex9_insn->order;
-
-	      /* Insert ex9 instruction.  */
-	      nds32_elf_ex9_push_insn (pre_insn16, contents, pre_off,
-				       &relax_blank_list, pre_irel_ptr,
-				       &irel_list);
-	      pre_off = off;
-	      pre_insn16 = insn16;
-
-	      if (save_irel)
-		{
-		  /* For instuction with relocation do relax.  */
-		  irel_ptr = (struct elf_nds32_irel_entry *)
-		    bfd_malloc (sizeof (struct elf_nds32_irel_entry));
-		  irel_ptr->irel = irel;
-		  irel_ptr->next = NULL;
-		  pre_irel_ptr = irel_ptr;
-		}
-	      else
-		pre_irel_ptr = NULL;
-	      break;
-	    }
-	  ex9_insn = ex9_insn->next;
-	}
-      off += 4;
-    }
-
-  /* Insert ex9 instruction.  */
-  nds32_elf_ex9_push_insn (pre_insn16, contents, pre_off,
-			   &relax_blank_list, pre_irel_ptr,
-			   &irel_list);
-
-  /* Delete the redundant code.  */
-  if (relax_blank_list)
-    {
-      nds32_elf_relax_delete_blanks (abfd, sec, relax_blank_list);
-      relax_blank_list = NULL;
-    }
-
-  /* Clear the relocation that is replaced by ex9.  */
-  while (irel_list)
-    {
-      struct elf_nds32_irel_entry *irel_ptr;
-
-      irel_ptr = irel_list;
-      irel_list = irel_ptr->next;
-      irel_ptr->irel->r_info =
-	ELF32_R_INFO (ELF32_R_SYM (irel_ptr->irel->r_info), R_NDS32_TRAN);
-      free (irel_ptr);
-    }
-  return TRUE;
-}
-
-/* Initialize ex9 hash table.  */
-
-int
-nds32_elf_ex9_init (void)
-{
-  if (!bfd_hash_table_init_n (&ex9_code_table, nds32_elf_code_hash_newfunc,
-			      sizeof (struct elf_nds32_code_hash_entry),
-			      1023))
-    {
-      _bfd_error_handler (_("cannot init ex9 hash table error"));
-      return FALSE;
-    }
-  return TRUE;
-}
-
-/* Predict how many bytes will be relaxed with ex9 and ifc.  */
-
-static void
-nds32_elf_ex9_total_relax (struct bfd_link_info *info)
-{
-  struct elf_nds32_insn_times_entry *ex9_insn;
-  struct elf_nds32_insn_times_entry *temp;
-  int target_optimize;
-  struct elf_nds32_link_hash_table *table;
-
-  if (ex9_insn_head == NULL)
-    return;
-
-  table = nds32_elf_hash_table (info);
-  target_optimize  = table->target_optimize;
-  ex9_insn = ex9_insn_head;
-  while (ex9_insn)
-    {
-      ex9_relax_size = ex9_insn->times * 2 + ex9_relax_size;
-      temp = ex9_insn;
-      ex9_insn = ex9_insn->next;
-      free (temp);
-    }
-  ex9_insn_head = NULL;
-
-  if ((target_optimize & NDS32_RELAX_JUMP_IFC_ON))
-    {
-      /* Examine ifc reduce size.  */
-      struct elf_nds32_ifc_symbol_entry *ifc_ent = ifc_symbol_head;
-      struct elf_nds32_ifc_irel_list *irel_ptr = NULL;
-      int size = 0;
-
-      while (ifc_ent)
-	{
-	  if (ifc_ent->enable == 0)
-	    {
-	      /* Not ifc yet.  */
-	      irel_ptr = ifc_ent->irel_head;
-	      while (irel_ptr)
-		{
-		  size += 2;
-		  irel_ptr = irel_ptr->next;
-		}
-	    }
-	  size -= 2;
-	  ifc_ent = ifc_ent->next;
-	}
-      ex9_relax_size += size;
-    }
-}
-
-/* Finish ex9 table.  */
-
-void
-nds32_elf_ex9_finish (struct bfd_link_info *link_info)
-{
-  nds32_elf_code_hash_traverse (nds32_elf_examine_insn_times);
-  nds32_elf_order_insn_times (link_info);
-  nds32_elf_ex9_total_relax (link_info);
-  /* Traverse the hash table and count its times.  */
-  nds32_elf_code_hash_traverse (nds32_elf_count_insn_times);
-  nds32_elf_order_insn_times (link_info);
-  nds32_elf_ex9_build_itable (link_info);
-}
-
-/* Relocate the entries in ex9 table.  */
-
-static bfd_vma
-nds32_elf_ex9_reloc_insn (struct elf_nds32_insn_times_entry *ptr,
-			  struct bfd_link_info *link_info)
-{
-  Elf_Internal_Sym *isym = NULL;
-  bfd_vma relocation = -1;
-  struct elf_link_hash_entry *h;
-
-  if (ptr->m_list != NULL)
-    {
-      /* Global symbol.  */
-      h = ptr->m_list->h_list->h;
-      if ((h->root.type == bfd_link_hash_defined
-	   || h->root.type == bfd_link_hash_defweak)
-	  && h->root.u.def.section != NULL
-	  && h->root.u.def.section->output_section != NULL)
-	{
-
-	  relocation = h->root.u.def.value +
-	    h->root.u.def.section->output_section->vma +
-	    h->root.u.def.section->output_offset;
-	  relocation += ptr->m_list->irel->r_addend;
-	}
-      else
-	relocation = 0;
-    }
-  else if (ptr->sec !=NULL)
-    {
-      /* Local symbol.  */
-      Elf_Internal_Sym sym;
-      asection *sec = NULL;
-      asection isec;
-      asection *isec_ptr = &isec;
-      Elf_Internal_Rela irel_backup = *(ptr->irel);
-      asection *sec_backup = ptr->sec;
-      bfd *abfd = ptr->sec->owner;
-
-      if (!nds32_get_local_syms (abfd, sec, &isym))
-	return FALSE;
-      isym = isym + ELF32_R_SYM (ptr->irel->r_info);
-
-      sec = bfd_section_from_elf_index (abfd, isym->st_shndx);
-      if (sec != NULL)
-	*isec_ptr = *sec;
-      sym = *isym;
-
-      /* The purpose is same as elf_link_input_bfd.  */
-      if (isec_ptr != NULL
-	  && isec_ptr->sec_info_type == SEC_INFO_TYPE_MERGE
-	  && ELF_ST_TYPE (isym->st_info) != STT_SECTION)
-	{
-	  sym.st_value =
-	    _bfd_merged_section_offset (ptr->sec->output_section->owner, &isec_ptr,
-					elf_section_data (isec_ptr)->sec_info,
-					isym->st_value);
-	}
-      relocation = _bfd_elf_rela_local_sym (link_info->output_bfd, &sym,
-					    &ptr->sec, ptr->irel);
-      if (ptr->irel != NULL)
-	relocation += ptr->irel->r_addend;
-
-      /* Restore origin value since there may be some insntructions that
-	 could not be replaced with ex9.it.  */
-      *(ptr->irel) = irel_backup;
-      ptr->sec = sec_backup;
-    }
-
-  return relocation;
-}
-
-/* Import ex9 table and build list.  */
-
-void
-nds32_elf_ex9_import_table (struct bfd_link_info *info)
-{
-  int num = 0;
-  bfd_byte *contents;
-  FILE *ex9_import_file;
-  int update_ex9_table;
-  struct elf_nds32_link_hash_table *table;
-
-  table = nds32_elf_hash_table (info);
-  ex9_import_file = table->ex9_import_file;
-  rewind (table->ex9_import_file);
-
-  contents = bfd_malloc (sizeof (bfd_byte) * 4);
-
-  /* Read instructions from the input file and build the list.  */
-  while (!feof (ex9_import_file))
-    {
-      unsigned long insn;
-      char *code;
-      struct elf_nds32_insn_times_entry *ptr;
-      size_t nread;
-
-      nread = fread (contents, sizeof (bfd_byte) * 4, 1, ex9_import_file);
-      /* Ignore the final byte 0x0a.  */
-      if (nread < 1)
-	break;
-      insn = bfd_getb32 (contents);
-      code = bfd_malloc (sizeof (char) * 9);
-      snprintf (code, 9, "%08lx", (insn & 0xffffffff));
-      ptr = bfd_malloc (sizeof (struct elf_nds32_insn_times_entry));
-      ptr->string = code;
-      ptr->order = num;
-      ptr->times = -1;
-      ptr->sec = NULL;
-      ptr->m_list = NULL;
-      ptr->rel_backup.r_offset = 0;
-      ptr->rel_backup.r_info = 0;
-      ptr->rel_backup.r_addend = 0;
-      ptr->irel = NULL;
-      ptr->next = NULL;
-      nds32_elf_ex9_insert_entry (ptr);
-      num++;
-    }
-
-  update_ex9_table = table->update_ex9_table;
-  if (update_ex9_table == 1)
-    {
-      /* It has to consider of sethi need to use multiple page
-	 but it not be done yet.  */
-      nds32_elf_code_hash_traverse (nds32_elf_examine_insn_times);
-      nds32_elf_order_insn_times (info);
-    }
-}
-
-/* Export ex9 table.  */
-
-static void
-nds32_elf_ex9_export (struct bfd_link_info *info,
-		      bfd_byte *contents, int size)
-{
-  FILE *ex9_export_file;
-  struct elf_nds32_link_hash_table *table;
-
-  table = nds32_elf_hash_table (info);
-  ex9_export_file = table->ex9_export_file;
-  fwrite (contents, sizeof (bfd_byte), size, ex9_export_file);
-  fclose (ex9_export_file);
-}
-
-/* Adjust relocations of J and JAL in ex9.itable.
-   Export ex9 table.  */
-
-static void
-nds32_elf_ex9_reloc_jmp (struct bfd_link_info *link_info)
-{
-  asection *table_sec = NULL;
-  struct elf_nds32_insn_times_entry *ex9_insn = ex9_insn_head;
-  struct elf_nds32_insn_times_entry *temp_ptr, *temp_ptr2;
-  bfd *it_abfd;
-  uint32_t insn, insn_with_reg, source_insn;
-  bfd_byte *contents = NULL, *source_contents = NULL;
-  int size = 0;
-  bfd_vma gp;
-  int shift, update_ex9_table, offset = 0;
-  reloc_howto_type *howto = NULL;
-  Elf_Internal_Rela rel_backup;
-  unsigned short insn_ex9;
-  struct elf_nds32_link_hash_table *table;
-  FILE *ex9_export_file;
-  static bfd_boolean done = FALSE;
-
-  if (done)
-    return;
-
-  done = TRUE;
-
-  table = nds32_elf_hash_table (link_info);
-  if (table)
-    table->relax_status |= NDS32_RELAX_EX9_DONE;
-
-
-  update_ex9_table = table->update_ex9_table;
-  /* Generated ex9.itable exactly.  */
-  if (update_ex9_table == 0)
-    {
-      for (it_abfd = link_info->input_bfds; it_abfd != NULL;
-	   it_abfd = it_abfd->link.next)
-	{
-	  table_sec = bfd_get_section_by_name (it_abfd, ".ex9.itable");
-	  if (table_sec != NULL)
-	    break;
-	}
-
-      if (table_sec != NULL)
-	{
-	  bfd *output_bfd;
-
-	  output_bfd = table_sec->output_section->owner;
-	  nds32_elf_final_sda_base (output_bfd, link_info, &gp, FALSE);
-	  if (table_sec->size == 0)
-	    return;
-
-	  if (!nds32_get_section_contents (it_abfd, table_sec, &contents, TRUE))
-	    return;
-	}
-    }
-  else
-    {
-      /* Set gp.  */
-      bfd *output_bfd;
-
-      output_bfd = link_info->input_bfds->sections->output_section->owner;
-      nds32_elf_final_sda_base (output_bfd, link_info, &gp, FALSE);
-      contents = bfd_malloc (sizeof (bfd_byte) * 2048);
-    }
-
-  /* Relocate instruction.  */
-  while (ex9_insn)
-    {
-      bfd_vma relocation, min_relocation = 0xffffffff;
-
-      insn = strtol (ex9_insn->string, NULL, 16);
-      insn_with_reg = 0;
-      if (ex9_insn->m_list != NULL || ex9_insn->sec != NULL)
-	{
-	  if (ex9_insn->m_list)
-	    rel_backup = ex9_insn->m_list->rel_backup;
-	  else
-	    rel_backup = ex9_insn->rel_backup;
-
-	  nds32_elf_get_insn_with_reg (&rel_backup, insn, &insn_with_reg);
-	  howto =
-	    bfd_elf32_bfd_reloc_type_table_lookup (ELF32_R_TYPE
-						   (rel_backup.r_info));
-	  shift = howto->rightshift;
-	  if (ELF32_R_TYPE (rel_backup.r_info) == R_NDS32_25_PCREL_RELA
-	      || ELF32_R_TYPE (rel_backup.r_info) == R_NDS32_LO12S0_ORI_RELA
-	      || ELF32_R_TYPE (rel_backup.r_info) == R_NDS32_LO12S0_RELA
-	      || ELF32_R_TYPE (rel_backup.r_info) == R_NDS32_LO12S1_RELA
-	      || ELF32_R_TYPE (rel_backup.r_info) == R_NDS32_LO12S2_RELA)
-	    {
-	      relocation = nds32_elf_ex9_reloc_insn (ex9_insn, link_info);
-	      insn =
-		insn_with_reg | ((relocation >> shift) &
-				 nds32_elf_irel_mask (&rel_backup));
-	      bfd_putb32 (insn, contents + (ex9_insn->order) * 4);
-	    }
-	  else if ((ELF32_R_TYPE (rel_backup.r_info) >= R_NDS32_SDA15S3
-		    && ELF32_R_TYPE (rel_backup.r_info) <= R_NDS32_SDA15S0)
-		   || (ELF32_R_TYPE (rel_backup.r_info) >= R_NDS32_SDA15S3_RELA
-		       && ELF32_R_TYPE (rel_backup.r_info) <= R_NDS32_SDA15S0_RELA)
-		   || (ELF32_R_TYPE (rel_backup.r_info) >= R_NDS32_SDA12S2_DP_RELA
-		       && ELF32_R_TYPE (rel_backup.r_info) <= R_NDS32_SDA12S2_SP_RELA)
-		   || (ELF32_R_TYPE (rel_backup.r_info) >= R_NDS32_SDA16S3_RELA
-		       && ELF32_R_TYPE (rel_backup.r_info) <= R_NDS32_SDA19S0_RELA))
-	    {
-	      relocation = nds32_elf_ex9_reloc_insn (ex9_insn, link_info);
-	      insn =
-		insn_with_reg | (((relocation - gp) >> shift) &
-				 nds32_elf_irel_mask (&rel_backup));
-	      bfd_putb32 (insn, contents + (ex9_insn->order) * 4);
-	    }
-	  else if (ELF32_R_TYPE (rel_backup.r_info) == R_NDS32_HI20_RELA)
-	    {
-	      /* Sethi may be multiple entry for one insn.  */
-	      if (ex9_insn->next && ex9_insn->m_list
-		  && ex9_insn->m_list == ex9_insn->next->m_list)
-		{
-		  struct elf_link_hash_entry_mul_list *m_list;
-		  struct elf_nds32_ex9_refix *fix_ptr;
-		  struct elf_link_hash_entry *h;
-
-		  temp_ptr = ex9_insn;
-		  temp_ptr2 = ex9_insn;
-		  m_list = ex9_insn->m_list;
-		  while (m_list)
-		    {
-		      h = m_list->h_list->h;
-		      relocation = h->root.u.def.value +
-			h->root.u.def.section->output_section->vma +
-			h->root.u.def.section->output_offset;
-		      relocation += m_list->irel->r_addend;
-
-		      if (relocation < min_relocation)
-			min_relocation = relocation;
-		      m_list = m_list->next;
-		    }
-		  relocation = min_relocation;
-
-		  /* Put insntruction into ex9 table.  */
-		  insn = insn_with_reg
-		    | ((relocation >> shift) & nds32_elf_irel_mask (&rel_backup));
-		  bfd_putb32 (insn, contents + (ex9_insn->order) * 4);
-		  relocation = relocation + 0x1000;	/* hi20 */
-
-		  while (ex9_insn->next && ex9_insn->m_list
-			 && ex9_insn->m_list == ex9_insn->next->m_list)
-		    {
-		      /* Multiple sethi.  */
-		      ex9_insn = ex9_insn->next;
-		      size += 4;
-		      insn =
-			insn_with_reg | ((relocation >> shift) &
-					 nds32_elf_irel_mask (&rel_backup));
-		      bfd_putb32 (insn, contents + (ex9_insn->order) * 4);
-		      relocation = relocation + 0x1000;	/* hi20 */
-		    }
-
-		  fix_ptr = ex9_refix_head;
-		  while (fix_ptr)
-		    {
-		      /* Fix ex9 insn.  */
-		      /* temp_ptr2 points to the head of multiple sethi.  */
-		      temp_ptr = temp_ptr2;
-		      while (fix_ptr->order != temp_ptr->order && fix_ptr->next)
-			{
-			  fix_ptr = fix_ptr->next;
-			}
-		      if (fix_ptr->order != temp_ptr->order)
-			break;
-
-		      /* Set source insn.  */
-		      relocation =
-			fix_ptr->h->root.u.def.value +
-			fix_ptr->h->root.u.def.section->output_section->vma +
-			fix_ptr->h->root.u.def.section->output_offset;
-		      relocation += fix_ptr->irel->r_addend;
-		      /* sethi imm is imm20s.  */
-		      source_insn = insn_with_reg | ((relocation >> shift) & 0xfffff);
-
-		      while (temp_ptr)
-			{
-			  /* Match entry and source code.  */
-			  insn = bfd_getb32 (contents + (temp_ptr->order) * 4 + offset);
-			  if (insn == source_insn)
-			    {
-			      /* Fix the ex9 insn.  */
-			      if (temp_ptr->order != fix_ptr->order)
-				{
-				  if (!nds32_get_section_contents
-					 (fix_ptr->sec->owner, fix_ptr->sec,
-					  &source_contents, TRUE))
-				    _bfd_error_handler
-				      (_("error: cannot fix ex9 relocation"));
-				  if (temp_ptr->order < 32)
-				    insn_ex9 = INSN_EX9_IT_2;
-				  else
-				    insn_ex9 = INSN_EX9_IT_1;
-				  insn_ex9 = insn_ex9 | temp_ptr->order;
-				  bfd_putb16 (insn_ex9, source_contents + fix_ptr->irel->r_offset);
-				}
-				break;
-			    }
-			  else
-			    {
-			      if (!temp_ptr->next || temp_ptr->m_list != temp_ptr->next->m_list)
-				_bfd_error_handler
-				  (_("Linker: error cannot fixed ex9 relocation \n"));
-			      else
-				temp_ptr = temp_ptr->next;
-			    }
-			}
-		      fix_ptr = fix_ptr->next;
-		    }
-		}
-	      else
-		{
-		  relocation = nds32_elf_ex9_reloc_insn (ex9_insn, link_info);
-		  insn = insn_with_reg
-			 | ((relocation >> shift) & nds32_elf_irel_mask (&rel_backup));
-		  bfd_putb32 (insn, contents + (ex9_insn->order) * 4);
-		}
-	    }
-	}
-      else
-	{
-	  /* Insn without relocation does not have to be fixed
-	     if need to update export table.  */
-	  if (update_ex9_table == 1)
-	    bfd_putb32 (insn, contents + (ex9_insn->order) * 4);
-	}
-      ex9_insn = ex9_insn->next;
-      size += 4;
-    }
-
-  ex9_export_file = table->ex9_export_file;
-  if (ex9_export_file != NULL)
-    nds32_elf_ex9_export (link_info, contents, table_sec->size);
-  else if (update_ex9_table == 1)
-    {
-      table->ex9_export_file = table->ex9_import_file;
-      rewind (table->ex9_export_file);
-      nds32_elf_ex9_export (link_info, contents, size);
-    }
-}
-
-/* Generate ex9 hash table.  */
-
-static bfd_boolean
-nds32_elf_ex9_build_hash_table (bfd *abfd, asection *sec,
-				struct bfd_link_info *link_info)
-{
-  Elf_Internal_Rela *internal_relocs;
-  Elf_Internal_Rela *irelend;
-  Elf_Internal_Rela *irel;
-  Elf_Internal_Rela *jrel;
-  Elf_Internal_Rela rel_backup;
-  Elf_Internal_Shdr *symtab_hdr;
-  Elf_Internal_Sym *isym = NULL;
-  asection *isec;
-  struct elf_link_hash_entry **sym_hashes;
-  bfd_byte *contents = NULL;
-  bfd_vma off = 0;
-  unsigned long r_symndx;
-  uint32_t insn, insn_with_reg;
-  struct elf_link_hash_entry *h;
-  int data_flag, shift, align;
-  bfd_vma relocation;
-  /* Suppress ex9 if `.no_relax ex9' or inner loop.  */
-  reloc_howto_type *howto = NULL;
-
-  sym_hashes = elf_sym_hashes (abfd);
-  /* Load section instructions, relocations, and symbol table.  */
-  if (!nds32_get_section_contents (abfd, sec, &contents, TRUE))
-    return FALSE;
-
-  internal_relocs = _bfd_elf_link_read_relocs (abfd, sec, NULL, NULL,
-					       TRUE /* keep_memory */);
-  irelend = internal_relocs + sec->reloc_count;
-  symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
-  if (!nds32_get_local_syms (abfd, sec, &isym))
-    return FALSE;
-
-  /* Check the object if enable ex9.  */
-  irel = find_relocs_at_address (internal_relocs, internal_relocs, irelend,
-				 R_NDS32_RELAX_ENTRY);
-
-  /* Check this section trigger ex9 relaxation.  */
-  if (irel == NULL
-      || irel >= irelend
-      || ELF32_R_TYPE (irel->r_info) != R_NDS32_RELAX_ENTRY
-      || (ELF32_R_TYPE (irel->r_info) == R_NDS32_RELAX_ENTRY
-	  && !(irel->r_addend & R_NDS32_RELAX_ENTRY_EX9_FLAG)))
-    return TRUE;
-
-  irel = internal_relocs;
-
-  /* Push each insn into hash table.  */
-  while (off < sec->size)
-    {
-      char code[10];
-      struct elf_nds32_code_hash_entry *entry;
-
-      while (irel != NULL && irel < irelend && irel->r_offset < off)
-	irel++;
-
-      data_flag = nds32_elf_ex9_relocation_check (link_info, &irel, irelend,
-						  NULL, sec, &off, contents);
-      if (data_flag & DATA_EXIST)
-	{
-	  /* We save the move offset in the highest byte.  */
-	  off += (data_flag >> 24);
-	  continue;
-	}
-
-      if (*(contents + off) & 0x80)
-	{
-	  off += 2;
-	}
-      else
-	{
-	  h = NULL;
-	  isec = NULL;
-	  jrel = NULL;
-	  rel_backup.r_info = 0;
-	  rel_backup.r_offset = 0;
-	  rel_backup.r_addend = 0;
-	  /* Load the instruction and its opcode with register for comparing.  */
-	  insn = bfd_getb32 (contents + off);
-	  insn_with_reg = 0;
-	  if (irel != NULL && irel < irelend && irel->r_offset == off)
-	    {
-	      nds32_elf_get_insn_with_reg (irel, insn, &insn_with_reg);
-	      howto = bfd_elf32_bfd_reloc_type_table_lookup (ELF32_R_TYPE (irel->r_info));
-	      shift = howto->rightshift;
-	      align = (1 << shift) - 1;
-	      if (ELF32_R_TYPE (irel->r_info) == R_NDS32_25_PCREL_RELA
-		  || ELF32_R_TYPE (irel->r_info) == R_NDS32_HI20_RELA
-		  || ELF32_R_TYPE (irel->r_info) == R_NDS32_LO12S0_ORI_RELA
-		  || ELF32_R_TYPE (irel->r_info) == R_NDS32_LO12S0_RELA
-		  || ELF32_R_TYPE (irel->r_info) == R_NDS32_LO12S1_RELA
-		  || ELF32_R_TYPE (irel->r_info) == R_NDS32_LO12S2_RELA
-		  ||(ELF32_R_TYPE (irel->r_info) >= R_NDS32_SDA15S3
-		     && ELF32_R_TYPE (irel->r_info) <= R_NDS32_SDA15S0)
-		  || (ELF32_R_TYPE (irel->r_info) >= R_NDS32_SDA15S3_RELA
-		      && ELF32_R_TYPE (irel->r_info) <= R_NDS32_SDA15S0_RELA)
-		  || (ELF32_R_TYPE (irel->r_info) >= R_NDS32_SDA12S2_DP_RELA
-		      && ELF32_R_TYPE (irel->r_info) <= R_NDS32_SDA12S2_SP_RELA)
-		  || (ELF32_R_TYPE (irel->r_info) >= R_NDS32_SDA16S3_RELA
-		      && ELF32_R_TYPE (irel->r_info) <= R_NDS32_SDA19S0_RELA))
-		{
-		  r_symndx = ELF32_R_SYM (irel->r_info);
-		  jrel = irel;
-		  rel_backup = *irel;
-		  if (r_symndx < symtab_hdr->sh_info)
-		    {
-		      /* Local symbol.  */
-		      int shndx = isym[r_symndx].st_shndx;
-
-		      bfd_vma st_value = (isym + r_symndx)->st_value;
-		      isec = elf_elfsections (abfd)[shndx]->bfd_section;
-		      relocation = (isec->output_section->vma + isec->output_offset
-				    + st_value + irel->r_addend);
-		    }
-		  else
-		    {
-		      /* External symbol.  */
-		      bfd_boolean warned ATTRIBUTE_UNUSED;
-		      bfd_boolean ignored ATTRIBUTE_UNUSED;
-		      bfd_boolean unresolved_reloc ATTRIBUTE_UNUSED;
-		      asection *sym_sec;
-
-		      /* Maybe there is a better way to get h and relocation */
-		      RELOC_FOR_GLOBAL_SYMBOL (link_info, abfd, sec, irel,
-					       r_symndx, symtab_hdr, sym_hashes,
-					       h, sym_sec, relocation,
-					       unresolved_reloc, warned, ignored);
-		      relocation += irel->r_addend;
-		      if ((h->root.type != bfd_link_hash_defined
-			   && h->root.type != bfd_link_hash_defweak)
-			  || strcmp (h->root.root.string, "_FP_BASE_") == 0)
-			{
-			  off += 4;
-			  continue;
-			}
-		    }
-
-		  /* Check for gp relative instruction alignment.  */
-		  if ((ELF32_R_TYPE (irel->r_info) >= R_NDS32_SDA15S3
-		       && ELF32_R_TYPE (irel->r_info) <= R_NDS32_SDA15S0)
-		      || (ELF32_R_TYPE (irel->r_info) >= R_NDS32_SDA15S3_RELA
-			  && ELF32_R_TYPE (irel->r_info) <= R_NDS32_SDA15S0_RELA)
-		      || (ELF32_R_TYPE (irel->r_info) >= R_NDS32_SDA12S2_DP_RELA
-			  && ELF32_R_TYPE (irel->r_info) <= R_NDS32_SDA12S2_SP_RELA)
-		      || (ELF32_R_TYPE (irel->r_info) >= R_NDS32_SDA16S3_RELA
-			  && ELF32_R_TYPE (irel->r_info) <= R_NDS32_SDA19S0_RELA))
-		    {
-		      bfd_vma gp;
-		      bfd *output_bfd = sec->output_section->owner;
-		      bfd_reloc_status_type r;
-
-		      /* If the symbol is in the abs section, the out_bfd will be null.
-			 This happens when the relocation has a symbol@GOTOFF.  */
-		      r = nds32_elf_final_sda_base (output_bfd, link_info, &gp, FALSE);
-		      if (r != bfd_reloc_ok)
-			{
-			  off += 4;
-			  continue;
-			}
-
-		      relocation -= gp;
-
-		      /* Make sure alignment is correct.  */
-		      if (relocation & align)
-			{
-			  /* Incorrect alignment.  */
-			  _bfd_error_handler
-			    /* xgettext:c-format */
-			    (_("%pB: warning: unaligned small data access "
-			       "for entry: {%" PRId64 ", %" PRId64 ", %" PRId64
-			       "}, addr = %#" PRIx64 ", align = %#x"),
-			     abfd, (int64_t) irel->r_offset,
-			     (int64_t) irel->r_info, (int64_t) irel->r_addend,
-			     (uint64_t) relocation, align);
-			  off += 4;
-			  continue;
-			}
-		    }
-
-		  insn = insn_with_reg
-		    | ((relocation >> shift) & nds32_elf_irel_mask (irel));
-		}
-	      else if (ELF32_R_TYPE (irel->r_info) == R_NDS32_RELAX_REGION_BEGIN
-		       || ELF32_R_TYPE (irel->r_info) == R_NDS32_RELAX_REGION_END
-		       || ELF32_R_TYPE (irel->r_info) == R_NDS32_NONE)
-		{
-		  /* These relocations do not have to relocate contens, so it can
-		     be regard as instruction without relocation.  */
-		}
-	      else
-		{
-		  off += 4;
-		  continue;
-		}
-	    }
-
-	  snprintf (code, sizeof (code), "%08x", insn);
-	  /* Copy "code".  */
-	  entry = (struct elf_nds32_code_hash_entry*)
-	    bfd_hash_lookup (&ex9_code_table, code, TRUE, TRUE);
-	  if (entry == NULL)
-	    {
-	      _bfd_error_handler
-		(_("failed creating ex9.it %s hash table entry"), code);
-	      return FALSE;
-	    }
-	  if (h)
-	    {
-	      if (h->root.type == bfd_link_hash_undefined)
-		return TRUE;
-	      /* Global symbol.  */
-	      /* In order to do sethi with different symbol but same value.  */
-	      if (entry->m_list == NULL)
-		{
-		  struct elf_link_hash_entry_mul_list *m_list_new;
-		  struct elf_link_hash_entry_list *h_list_new;
-
-		  m_list_new = (struct elf_link_hash_entry_mul_list *)
-		    bfd_malloc (sizeof (struct elf_link_hash_entry_mul_list));
-		  h_list_new = (struct elf_link_hash_entry_list *)
-		    bfd_malloc (sizeof (struct elf_link_hash_entry_list));
-		  entry->m_list = m_list_new;
-		  m_list_new->h_list = h_list_new;
-		  m_list_new->rel_backup = rel_backup;
-		  m_list_new->times = 1;
-		  m_list_new->irel = jrel;
-		  m_list_new->next = NULL;
-		  h_list_new->h = h;
-		  h_list_new->next = NULL;
-		}
-	      else
-		{
-		  struct elf_link_hash_entry_mul_list *m_list = entry->m_list;
-		  struct elf_link_hash_entry_list *h_list;
-
-		  while (m_list)
-		    {
-		      /* Build the different symbols that point to the same address.  */
-		      h_list = m_list->h_list;
-		      if (h_list->h->root.u.def.value == h->root.u.def.value
-			  && h_list->h->root.u.def.section->output_section->vma
-			     == h->root.u.def.section->output_section->vma
-			  && h_list->h->root.u.def.section->output_offset
-			     == h->root.u.def.section->output_offset
-			  && m_list->rel_backup.r_addend == rel_backup.r_addend)
-			{
-			  m_list->times++;
-			  m_list->irel = jrel;
-			  while (h_list->h != h && h_list->next)
-			    h_list = h_list->next;
-			  if (h_list->h != h)
-			    {
-			      struct elf_link_hash_entry_list *h_list_new;
-
-			      h_list_new = (struct elf_link_hash_entry_list *)
-				bfd_malloc (sizeof (struct elf_link_hash_entry_list));
-			      h_list->next = h_list_new;
-			      h_list_new->h = h;
-			      h_list_new->next = NULL;
-			    }
-			  break;
-			}
-		      /* The sethi case may have different address but the
-			 hi20 is the same.  */
-		      else if (ELF32_R_TYPE (jrel->r_info) == R_NDS32_HI20_RELA
-			       && m_list->next == NULL)
-			{
-			  struct elf_link_hash_entry_mul_list *m_list_new;
-			  struct elf_link_hash_entry_list *h_list_new;
-
-			  m_list_new = (struct elf_link_hash_entry_mul_list *)
-			    bfd_malloc (sizeof (struct elf_link_hash_entry_mul_list));
-			  h_list_new = (struct elf_link_hash_entry_list *)
-			    bfd_malloc (sizeof (struct elf_link_hash_entry_list));
-			  m_list->next = m_list_new;
-			  m_list_new->h_list = h_list_new;
-			  m_list_new->rel_backup = rel_backup;
-			  m_list_new->times = 1;
-			  m_list_new->irel = jrel;
-			  m_list_new->next = NULL;
-			  h_list_new->h = h;
-			  h_list_new->next = NULL;
-			  break;
-			}
-		      m_list = m_list->next;
-		    }
-		  if (!m_list)
-		    {
-		      off += 4;
-		      continue;
-		    }
-		}
-	    }
-	  else
-	    {
-	      /* Local symbol and insn without relocation*/
-	      entry->times++;
-	      entry->rel_backup = rel_backup;
-	    }
-
-	  /* Use in sethi insn with constant and global symbol in same format.  */
-	  if (!jrel)
-	    entry->const_insn = 1;
-	  else
-	    entry->irel = jrel;
-	  entry->sec = isec;
-	  off += 4;
-	}
-    }
-  return TRUE;
-}
-
-/* Set the _ITB_BASE, and point it to ex9 table.  */
-
-bfd_boolean
-nds32_elf_ex9_itb_base (struct bfd_link_info *link_info)
-{
-  bfd *abfd;
-  asection *sec;
-  bfd *output_bfd = NULL;
-  struct bfd_link_hash_entry *bh = NULL;
-
-  if (is_ITB_BASE_set == 1)
-    return TRUE;
-
-  is_ITB_BASE_set = 1;
-
-  bh = bfd_link_hash_lookup (link_info->hash, "_ITB_BASE_", FALSE, FALSE, TRUE);
-
-  if (bh && (bh->type == bfd_link_hash_defined
-	     || bh->type == bfd_link_hash_defweak))
-    return TRUE;
-
-  for (abfd = link_info->input_bfds; abfd != NULL;
-       abfd = abfd->link.next)
-    {
-      sec = bfd_get_section_by_name (abfd, ".ex9.itable");
-      if (sec != NULL)
-	{
-	  output_bfd = sec->output_section->owner;
-	  break;
-	}
-    }
-  if (output_bfd == NULL)
-    {
-      output_bfd = link_info->output_bfd;
-      if (output_bfd->sections == NULL)
-	return TRUE;
-      else
-	sec = bfd_abs_section_ptr;
-    }
-  bh = bfd_link_hash_lookup (link_info->hash, "_ITB_BASE_",
-			     FALSE, FALSE, TRUE);
-  return (_bfd_generic_link_add_one_symbol
-	  (link_info, output_bfd, "_ITB_BASE_",
-	   BSF_GLOBAL | BSF_WEAK, sec, 0,
-	   (const char *) NULL, FALSE, get_elf_backend_data
-	   (output_bfd)->collect, &bh));
-} /* End EX9.IT  */
-
 
 #define ELF_ARCH				bfd_arch_nds32
 #define ELF_MACHINE_CODE			EM_NDS32
diff --git a/ld/ChangeLog b/ld/ChangeLog
index e74f722..ab27208 100644
--- a/ld/ChangeLog
+++ b/ld/ChangeLog
@@ -1,3 +1,8 @@
+2018-03-15  Kuan-Lin Chen  <kuanlinchentw@gmail.com>
+
+	* emultempl/nds32elf.em (nds32_elf_after_allocation): Remove
+	unsupported target feature.
+
 2018-03-14  H.J. Lu  <hongjiu.lu@intel.com>
 
 	PR ld/20882
diff --git a/ld/emultempl/nds32elf.em b/ld/emultempl/nds32elf.em
index 3ea0ea2..eb29d04 100644
--- a/ld/emultempl/nds32elf.em
+++ b/ld/emultempl/nds32elf.em
@@ -191,14 +191,6 @@ nds32_elf_after_open (void)
 static void
 nds32_elf_after_allocation (void)
 {
-  if (target_optimize & NDS32_RELAX_EX9_ON
-      || (ex9_import_file != NULL && update_ex9_table == 1))
-    {
-      /* Initialize ex9 hash table.  */
-      if (!nds32_elf_ex9_init ())
-	return;
-    }
-
   /* Call default after allocation callback.
      1. This is where relaxation is done.
      2. It calls gld${EMULATION_NAME}_map_segments to build ELF segment table.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]