/* nds32_insertion_sort sorts an array with nmemb elements of size size.
    This prototype is the same as qsort ().  */
 
-void
+static void
 nds32_insertion_sort (void *base, size_t nmemb, size_t size,
                      int (*compar) (const void *lhs, const void *rhs))
 {
 
 extern int elf32_nds32_unify_relax_group (bfd *, asection *);
 extern int nds32_elf_unify_tls_model (bfd *, asection *, bfd_byte *,
                                      struct bfd_link_info *);
-extern void nds32_insertion_sort
-(void *, size_t, size_t, int (*) (const void *, const void *));
 
 extern int        nds32_convert_32_to_16 (bfd *, uint32_t, uint16_t *, int *);
 extern int        nds32_convert_16_to_32 (bfd *, uint16_t, uint32_t *);
 
   return false;
 }
 
-/* Sort relocation by address.
-
-   We didn't use qsort () in stdlib, because quick-sort is not a stable
-   sorting algorithm.  Relocations at the same address (r_offset) must keep
-   their relative order.  For example, RELAX_ENTRY must be the very first
-   relocation entry.
-
-   Currently, this function implements insertion-sort.  */
-
-static int
-compar_relent (const void *lhs, const void *rhs)
-{
-  const arelent **l = (const arelent **) lhs;
-  const arelent **r = (const arelent **) rhs;
-
-  if ((*l)->address > (*r)->address)
-    return 1;
-  else if ((*l)->address == (*r)->address)
-    return 0;
-  else
-    return -1;
-}
-
-/* SET_SECTION_RELOCS ()
-
-   Although this macro is originally used to set a relocation for each section,
-   we use it to sort relocations in the same section by the address of the
-   relocation.  */
-
-void
-nds32_set_section_relocs (asection *sec ATTRIBUTE_UNUSED,
-                         arelent **relocs, unsigned int n)
-{
-  if (n <= 1)
-    return;
-
-  nds32_insertion_sort (relocs, n, sizeof (*relocs), compar_relent);
-}
-
 long
 nds32_pcrel_from_section (fixS *fixP, segT sec ATTRIBUTE_UNUSED)
 {
 
 extern void elf_nds32_final_processing (void);
 extern int nds32_validate_fix_sub (struct fix *, segT);
 extern int nds32_force_relocation (struct fix *);
-extern void nds32_set_section_relocs (asection *, arelent ** , unsigned int);
 
 /* Fill in rs_align_code fragments.  TODO: Review this.  */
 extern void nds32_handle_align (fragS *);
    || TC_FORCE_RELOCATION (FIX))
 #define TC_FORCE_RELOCATION(fix)               nds32_force_relocation (fix)
 #define TC_VALIDATE_FIX_SUB(FIX,SEG)           nds32_validate_fix_sub (FIX,SEG)
-#define SET_SECTION_RELOCS(sec, relocs, n)     nds32_set_section_relocs (sec, relocs, n)
+#define GAS_SORT_RELOCS                                1
 /* Values passed to md_apply_fix don't include the symbol value.  */
 #define MD_APPLY_SYM_VALUE(FIX)                        0
 #define HANDLE_ALIGN(f)                                nds32_handle_align (f)
 
 
 #define md_pre_output_hook riscv_pre_output_hook ()
 extern void riscv_pre_output_hook (void);
+#define GAS_SORT_RELOCS 1
 
 /* Let the linker resolve all the relocs due to relaxation.  */
 #define tc_fix_adjustable(fixp) 0
 
                }
              r = r->next;
            }
-         relocs[n++] = *reloc;
+#ifdef GAS_SORT_RELOCS
+         if (n != 0 && (*reloc)->address < relocs[n - 1]->address)
+           {
+             size_t lo = 0;
+             size_t hi = n - 1;
+             bfd_vma look = (*reloc)->address;
+             while (lo < hi)
+               {
+                 size_t mid = (lo + hi) / 2;
+                 if (relocs[mid]->address > look)
+                   hi = mid;
+                 else
+                   {
+                     lo = mid + 1;
+                     if (relocs[mid]->address == look)
+                       break;
+                   }
+               }
+             while (lo < hi && relocs[lo]->address == look)
+               lo++;
+             memmove (relocs + lo + 1, relocs + lo,
+                      (n - lo) * sizeof (*relocs));
+             n++;
+             relocs[lo] = *reloc;
+           }
+         else
+#endif
+           relocs[n++] = *reloc;
          install_reloc (sec, *reloc, fixp->fx_frag,
                         fixp->fx_file, fixp->fx_line);
 #ifndef RELOC_EXPANSION_POSSIBLE