Move struc-symbol.h to symbols.c
[deliverable/binutils-gdb.git] / gas / config / tc-nds32.c
index 353a1657c3dd6af2ee4f43bc4c10e207ce781d5d..e85316d260a439229cc74dafd352b247d7eca5d0 100644 (file)
@@ -1,5 +1,5 @@
 /* tc-nds32.c -- Assemble for the nds32
-   Copyright (C) 2012-2014 Free Software Foundation, Inc.
+   Copyright (C) 2012-2018 Free Software Foundation, Inc.
    Contributed by Andes Technology Corporation.
 
    This file is part of GAS, the GNU Assembler.
 #include "hash.h"
 #include "sb.h"
 #include "macro.h"
-#include "struc-symbol.h"
 #include "opcode/nds32.h"
 
 #include <stdio.h>
+#include <errno.h>
+#include <limits.h>
 
 /* GAS definitions.  */
 
@@ -66,14 +67,15 @@ struct nds32_relocs_pattern
   struct nds32_opcode *opcode;
   char *where;
   struct nds32_relocs_pattern *next;
+  /* Assembled instruction bytes.  */
+  uint32_t insn;
 };
 
 /* Suffix name and relocation.  */
 struct suffix_name
 {
-  char *suffix;
+  const char *suffix;
   short unsigned int reloc;
-  int pic;
 };
 static int vec_size = 0;
 /* If the assembly code is generated by compiler, it is supposed to have
@@ -87,11 +89,7 @@ static struct hash_control *nds32_hint_hash;
 
 /* Generate relocation for relax or not, and the default is true.  */
 static int enable_relax_relocs = 1;
-/* The value will be used in RELAX_ENTRY.  */
-static int enable_relax_ex9 = 0;
-/* The value will be used in RELAX_ENTRY.  */
-static int enable_relax_ifc = 0;
-/* Save option -O for perfomance.  */
+/* Save option -O for performance.  */
 static int optimize = 0;
 /* Save option -Os for code size.  */
 static int optimize_for_space = 0;
@@ -102,61 +100,86 @@ static int in_omit_fp = 0;
 extern struct nds32_keyword keyword_gpr[];
 /* Tag there is relax relocation having to link.  */
 static bfd_boolean relaxing = FALSE;
+/* ICT model.  */
+enum ict_option {
+  ICT_NONE = 0,
+  ICT_SMALL,
+  ICT_LARGE
+};
+static enum ict_option ict_flag = ICT_NONE;
 \f
+
 static struct hash_control *nds32_relax_info_hash;
+
+/* Branch patterns.  */
 static relax_info_t relax_table[] =
 {
   {
-    "jal",                                     /* opcode */
-    BR_RANGE_S16M,                             /* br_range */
-    {{0, 0, 0, FALSE}},                        /* cond_field */
-    {
+    .opcode = "jal",
+    .br_range = BR_RANGE_S16M,
+    .cond_field =
       {
-        INSN_JAL /* jal label */
-      }, /* BR_RANGE_S256 */
+       {0, 0, 0, FALSE}
+      },
+    .relax_code_seq[BR_RANGE_S256] =
       {
-        INSN_JAL /* jal label */
-      }, /* BR_RANGE_S16K */
+       INSN_JAL        /* jal label */
+      },
+    .relax_code_size[BR_RANGE_S256] = 4,
+    .relax_branch_isize[BR_RANGE_S256] = 4,
+    .relax_fixup[BR_RANGE_S256] =
       {
-        INSN_JAL /* jal label */
-      }, /* BR_RANGE_S64K */
+       {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
+       {0, 0, 0, 0}
+      },
+
+    .relax_code_seq[BR_RANGE_S16K] =
       {
-        INSN_JAL /* jal label */
-      }, /* BR_RANGE_S16M */
+       INSN_JAL        /* jal label */
+      },
+    .relax_code_size[BR_RANGE_S16K] = 4,
+    .relax_branch_isize[BR_RANGE_S16K] = 4,
+    .relax_fixup[BR_RANGE_S16K] =
       {
-        INSN_SETHI_TA, /* sethi $ta, label */
-        INSN_ORI_TA, /* ori $ta, $ta, label */
-        INSN_JRAL_TA
-      }, /* BR_RANGE_U4G */
-    },                                         /* relax_code_seq */
-    {
-      {{0, 0, 0, FALSE}}, /* BR_RANGE_S256 */
-      {{0, 0, 0, FALSE}}, /* BR_RANGE_S16K */
-      {{0, 0, 0, FALSE}}, /* BR_RANGE_S64K */
-      {{0, 0, 0, FALSE}}, /* BR_RANGE_S16M */
-      {{0, 0, 0, FALSE}} /* BR_RANGE_U4G */
-    },                                         /* relax_code_condition */
-    {4, 4, 4, 4, 12},                          /* relax_code_size */
-    {4, 4, 4, 4, 4},                           /* relax_branch_isize */
-    {
+       {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
+       {0, 0, 0, 0}
+      },
+
+    .relax_code_seq[BR_RANGE_S64K] =
       {
-        {0, 4, 0, BFD_RELOC_NDS32_25_PCREL},
-        {0, 0, 0, 0}
-      }, /* BR_RANGE_S256 */
+       INSN_JAL        /* jal label */
+      },
+    .relax_code_size[BR_RANGE_S64K] = 4,
+    .relax_branch_isize[BR_RANGE_S64K] = 4,
+    .relax_fixup[BR_RANGE_S64K] =
       {
-        {0, 4, 0, BFD_RELOC_NDS32_25_PCREL},
-        {0, 0, 0, 0}
-      }, /* BR_RANGE_S16K */
+       {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
+       {0, 0, 0, 0}
+      },
+
+    .relax_code_seq[BR_RANGE_S16M] =
+      {
+       INSN_JAL        /* jal label */
+      },
+    .relax_code_size[BR_RANGE_S16M] = 4,
+    .relax_branch_isize[BR_RANGE_S16M] = 4,
+    .relax_fixup[BR_RANGE_S16M] =
       {
-        {0, 4, 0, BFD_RELOC_NDS32_25_PCREL},
-        {0, 0, 0, 0}
-      }, /* BR_RANGE_S64K */
+       {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
+       {0, 0, 0, 0}
+      },
+
+    .relax_code_seq[BR_RANGE_U4G] =
       {
-        {0, 4, 0, BFD_RELOC_NDS32_25_PCREL},
-        {0, 0, 0, 0}
-      }, /* BR_RANGE_S16M */
+       INSN_SETHI_TA,  /* sethi $ta, label */
+       INSN_ORI_TA,    /* ori $ta, $ta, label */
+       INSN_JRAL_TA    /* jral $ta */
+      },
+    .relax_code_size[BR_RANGE_U4G] = 12,
+    .relax_branch_isize[BR_RANGE_U4G] = 4,
+    .relax_fixup[BR_RANGE_U4G] =
       {
-        {0, 4, 0, BFD_RELOC_NDS32_HI20},
+       {0, 4, 0, BFD_RELOC_NDS32_HI20},
        {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGCALL4},
        {4, 4, NDS32_HINT | NDS32_FIX, BFD_RELOC_NDS32_LO12S0_ORI},
        {4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR},
@@ -164,169 +187,213 @@ static relax_info_t relax_table[] =
        {8, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY},
        {8, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
        {0, 0, 0, 0}
-      } /* BR_RANGE_U4G */
-    }                                          /* relax_fixup */
+      },
   },
   {
-    "bltzal",                                  /* opcode */
-    BR_RANGE_S64K,                             /* br_range */
-    {
-      {0, 20, 0x1F, FALSE},
-      {0, 0, 0, FALSE}
-    },                                                 /* cond_field */
-    {
-      {
-        INSN_BLTZAL /* bltzal $rt, label */
-      }, /* BR_RANGE_S256 */
-      {
-        INSN_BLTZAL /* bltzal $rt, label */
-      }, /* BR_RANGE_S16K */
-      {
-        INSN_BLTZAL /* bltzal $rt, label */
-      }, /* BR_RANGE_S64K */
+    .opcode = "bgezal",
+    .br_range = BR_RANGE_S64K,
+    .cond_field =
+      {
+       {0, 20, 0x1F, FALSE},
+       {0, 0, 0, FALSE}
+      },
+    .relax_code_seq[BR_RANGE_S256] =
+      {
+         INSN_BGEZAL   /* bgezal $rt, label */
+      },
+    .relax_code_condition[BR_RANGE_S256] =
+      {
+       {0, 20, 0x1F, FALSE},
+       {0, 0, 0, FALSE},
+      },
+    .relax_code_size[BR_RANGE_S256] = 4,
+    .relax_branch_isize[BR_RANGE_S256] = 4,
+    .relax_fixup[BR_RANGE_S256] =
+      {
+       {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
+       {0, 0, 0, 0}
+      },
+
+    .relax_code_seq[BR_RANGE_S16K] =
       {
-       INSN_BGEZ, /* bgez $rt, $1 */
-        INSN_JAL /* jal label */
-      }, /* BR_RANGE_S16M */
+       INSN_BGEZAL     /* bgezal $rt, label */
+      },
+    .relax_code_condition[BR_RANGE_S16K] =
       {
-       INSN_BGEZ, /* bgez $rt, $1 */
-        INSN_SETHI_TA, /* sethi $ta, label */
-        INSN_ORI_TA, /* ori $ta, $ta, label */
-        INSN_JRAL_TA /* jral $ta */
-      } /* BR_RANGE_U4G */
-    },                                         /* relax_code_seq */
-    {
+       {0, 20, 0x1F, FALSE},
+       {0, 0, 0, FALSE},
+      },
+    .relax_code_size[BR_RANGE_S16K] = 4,
+    .relax_branch_isize[BR_RANGE_S16K] = 4,
+    .relax_fixup[BR_RANGE_S16K] =
       {
-        {0, 20, 0x1F, FALSE},
-        {0, 0, 0, FALSE}
-      }, /* BR_RANGE_S256 */
+       {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
+       {0, 0, 0, 0}
+      },
+
+    .relax_code_seq[BR_RANGE_S64K] =
       {
-        {0, 20, 0x1F, FALSE},
-        {0, 0, 0, FALSE}
-      }, /* BR_RANGE_S16K */
+       INSN_BGEZAL     /* bgezal $rt, label */
+      },
+    .relax_code_condition[BR_RANGE_S64K] =
       {
-        {0, 20, 0x1F, FALSE},
-        {0, 0, 0, FALSE}
-      }, /* BR_RANGE_S64K */
+       {0, 20, 0x1F, FALSE},
+       {0, 0, 0, FALSE},
+      },
+    .relax_code_size[BR_RANGE_S64K] = 4,
+    .relax_branch_isize[BR_RANGE_S64K] = 4,
+    .relax_fixup[BR_RANGE_S64K] =
       {
-        {0, 20, 0x1F, FALSE},
-        {0, 0, 0, FALSE}
-      }, /* BR_RANGE_S16M */
+       {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
+       {0, 0, 0, 0}
+      },
+
+    .relax_code_seq[BR_RANGE_S16M] =
       {
-        {0, 20, 0x1F, FALSE},
-        {0, 0, 0, FALSE}
-      } /* BR_RANGE_U4G */
-    },                                         /* relax_code_condition */
-    {4, 4, 4, 8, 16},                          /* relax_code_size */
-    {4, 4, 4, 4, 4},                           /* relax_branch_isize */
-    {
+       INSN_BLTZ,      /* bltz $rt, $1 */
+       INSN_JAL        /* jal label */
+      },
+    .relax_code_condition[BR_RANGE_S16M] =
       {
-        {0, 4, 0, BFD_RELOC_NDS32_17_PCREL},
-        {0, 0, 0, 0}
-      }, /* BR_RANGE_S256 */
+       {0, 20, 0x1F, FALSE},
+       {0, 0, 0, FALSE},
+      },
+    .relax_code_size[BR_RANGE_S16M] = 8,
+    .relax_branch_isize[BR_RANGE_S16M] = 4,
+    .relax_fixup[BR_RANGE_S16M] =
       {
-        {0, 4, 0, BFD_RELOC_NDS32_17_PCREL},
-        {0, 0, 0, 0}
-      }, /* BR_RANGE_S16K */
+       {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
+       {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGCALL5},
+       {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
+       {0, 0, 0, 0}
+      },
+
+    .relax_code_seq[BR_RANGE_U4G] =
       {
-        {0, 4, 0, BFD_RELOC_NDS32_17_PCREL},
-        {0, 0, 0, 0}
-      }, /* BR_RANGE_S64K */
+       INSN_BLTZ,      /* bltz $rt, $1 */
+       INSN_SETHI_TA,  /* sethi $ta, label */
+       INSN_ORI_TA,    /* ori $ta, $ta, label */
+       INSN_JRAL_TA    /* jral $ta */
+      },
+    .relax_code_condition[BR_RANGE_U4G] =
       {
-        {0, 4, NDS32_CREATE_LABEL, BFD_RELOC_NDS32_17_PCREL},
-       {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGCALL5},
-        {4, 4, 0, BFD_RELOC_NDS32_25_PCREL},
-        {0, 0, 0, 0}
-      }, /* BR_RANGE_S16M */
+       {0, 20, 0x1F, FALSE},
+       {0, 0, 0, FALSE},
+      },
+    .relax_code_size[BR_RANGE_U4G] = 16,
+    .relax_branch_isize[BR_RANGE_U4G] = 4,
+    .relax_fixup[BR_RANGE_U4G] =
       {
-        {0, 4, NDS32_CREATE_LABEL, BFD_RELOC_NDS32_17_PCREL},
+       {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
        {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGCALL6},
-        {4, 4, 0, BFD_RELOC_NDS32_HI20},
+       {4, 4, 0, BFD_RELOC_NDS32_HI20},
        {4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR},
        {8, 4, NDS32_FIX | NDS32_HINT, BFD_RELOC_NDS32_LO12S0_ORI},
        {8, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR},
        {12, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED},
        {12, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY},
        {12, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
-        {0, 0, 0, 0}
-      } /* BR_RANGE_U4G */
-    }                                          /* relax_fixup */
+       {0, 0, 0, 0}
+      },
   },
   {
-    "bgezal",                                  /* opcode */
-    BR_RANGE_S64K,                             /* br_range */
-    {
-      {0, 20, 0x1F, FALSE},
-      {0, 0, 0, FALSE}
-    },                                                 /* cond_field */
-    {
-      {
-        INSN_BGEZAL /* bgezal $rt, label */
-      }, /* BR_RANGE_S256 */
-      {
-        INSN_BGEZAL /* bgezal $rt, label */
-      }, /* BR_RANGE_S16K */
+    .opcode = "bltzal",
+    .br_range = BR_RANGE_S64K,
+    .cond_field =
+      {
+       {0, 20, 0x1F, FALSE},
+       {0, 0, 0, FALSE}
+      },
+    .relax_code_seq[BR_RANGE_S256] =
+      {
+         INSN_BLTZAL   /* bltzal $rt, label */
+      },
+    .relax_code_condition[BR_RANGE_S256] =
+      {
+       {0, 20, 0x1F, FALSE},
+       {0, 0, 0, FALSE},
+      },
+    .relax_code_size[BR_RANGE_S256] = 4,
+    .relax_branch_isize[BR_RANGE_S256] = 4,
+    .relax_fixup[BR_RANGE_S256] =
+      {
+       {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
+       {0, 0, 0, 0}
+      },
+
+    .relax_code_seq[BR_RANGE_S16K] =
       {
-        INSN_BGEZAL /* bgezal $rt, label */
-      }, /* BR_RANGE_S64K */
+       INSN_BLTZAL     /* bltzal $rt, label */
+      },
+    .relax_code_condition[BR_RANGE_S16K] =
       {
-        INSN_BLTZ, /* bltz $rt, $1 */
-        INSN_JAL /* jal label */
-      }, /* BR_RANGE_S16M */
+       {0, 20, 0x1F, FALSE},
+       {0, 0, 0, FALSE},
+      },
+    .relax_code_size[BR_RANGE_S16K] = 4,
+    .relax_branch_isize[BR_RANGE_S16K] = 4,
+    .relax_fixup[BR_RANGE_S16K] =
       {
-        INSN_BLTZ, /* bltz $rt, $1 */
-        INSN_SETHI_TA, /* sethi $ta, label */
-        INSN_ORI_TA, /* ori $ta, $ta, label */
-        INSN_JRAL_TA /* jral $ta */
-      } /* BR_RANGE_U4G */
-    },                                         /* relax_code_seq */
-    {
-      {
-        {0, 20, 0x1F, FALSE},
-        {0, 0, 0, FALSE}
-      }, /* BR_RANGE_S256 */
+       {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
+       {0, 0, 0, 0}
+      },
+
+    .relax_code_seq[BR_RANGE_S64K] =
       {
-        {0, 20, 0x1F, FALSE},
-        {0, 0, 0, FALSE}
-      }, /* BR_RANGE_S16K */
+       INSN_BLTZAL     /* bltzal $rt, label */
+      },
+    .relax_code_condition[BR_RANGE_S64K] =
       {
-        {0, 20, 0x1F, FALSE},
-        {0, 0, 0, FALSE}
-      }, /* BR_RANGE_S64K */
+       {0, 20, 0x1F, FALSE},
+       {0, 0, 0, FALSE},
+      },
+    .relax_code_size[BR_RANGE_S64K] = 4,
+    .relax_branch_isize[BR_RANGE_S64K] = 4,
+    .relax_fixup[BR_RANGE_S64K] =
       {
-        {0, 20, 0x1F, FALSE},
-        {0, 0, 0, FALSE}
-      }, /* BR_RANGE_S16M */
+       {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
+       {0, 0, 0, 0}
+      },
+
+    .relax_code_seq[BR_RANGE_S16M] =
       {
-        {0, 20, 0x1F, FALSE},
-        {0, 0, 0, FALSE}
-      } /* BR_RANGE_U4G */
-    },                                         /* relax_code_condition */
-    {4, 4, 4, 8, 16},                          /* relax_code_size */
-    {4, 4, 4, 4, 4},                           /* relax_branch_isize */
-    {
+       INSN_BGEZ,      /* bgez $rt, $1 */
+       INSN_JAL        /* jal label */
+      },
+    .relax_code_condition[BR_RANGE_S16M] =
       {
-        {0, 4, 0, BFD_RELOC_NDS32_17_PCREL},
-        {0, 0, 0, 0}
-      }, /* BR_RANGE_S256 */
+       {0, 20, 0x1F, FALSE},
+       {0, 0, 0, FALSE},
+      },
+    .relax_code_size[BR_RANGE_S16M] = 8,
+    .relax_branch_isize[BR_RANGE_S16M] = 4,
+    .relax_fixup[BR_RANGE_S16M] =
       {
-        {0, 4, 0, BFD_RELOC_NDS32_17_PCREL},
-        {0, 0, 0, 0}
-      }, /* BR_RANGE_S16K */
+       {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
+       {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGCALL5},
+       {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
+       {0, 0, 0, 0}
+      },
+
+    .relax_code_seq[BR_RANGE_U4G] =
       {
-        {0, 4, 0, BFD_RELOC_NDS32_17_PCREL},
-        {0, 0, 0, 0}
-      }, /* BR_RANGE_S64K */
+       INSN_BGEZ,      /* bgez $rt, $1 */
+       INSN_SETHI_TA,  /* sethi $ta, label */
+       INSN_ORI_TA,    /* ori $ta, $ta, label */
+       INSN_JRAL_TA    /* jral $ta */
+      },
+    .relax_code_condition[BR_RANGE_U4G] =
       {
-        {0, 4, NDS32_CREATE_LABEL, BFD_RELOC_NDS32_17_PCREL},
-       {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGCALL5},
-        {4, 4, 0, BFD_RELOC_NDS32_25_PCREL},
-        {0, 0, 0, 0}
-      }, /* BR_RANGE_S16M */
+       {0, 20, 0x1F, FALSE},
+       {0, 0, 0, FALSE},
+      },
+    .relax_code_size[BR_RANGE_U4G] = 16,
+    .relax_branch_isize[BR_RANGE_U4G] = 4,
+    .relax_fixup[BR_RANGE_U4G] =
       {
-        {0, 4, NDS32_CREATE_LABEL, BFD_RELOC_NDS32_17_PCREL},
+       {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
        {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGCALL6},
-        {4, 4, 0, BFD_RELOC_NDS32_HI20},
+       {4, 4, 0, BFD_RELOC_NDS32_HI20},
        {4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR},
        {8, 4, NDS32_FIX | NDS32_HINT, BFD_RELOC_NDS32_LO12S0_ORI},
        {8, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR},
@@ -334,60 +401,74 @@ static relax_info_t relax_table[] =
        {12, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY},
        {12, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
        {0, 0, 0, 0}
-      } /* BR_RANGE_U4G */
-    }                                          /* relax_fixup */
+      },
   },
   {
-    "j",                                       /* opcode */
-    BR_RANGE_S16M,                             /* br_range */
-    {{0, 0, 0, FALSE}},                        /* cond_field */
-    {
+    .opcode = "j",
+    .br_range = BR_RANGE_S16M,
+    .cond_field =
+      {
+       {0, 0, 0, FALSE}
+      },
+    .relax_code_seq[BR_RANGE_S256] =
       {
-        (INSN_J8 << 16) /* j8 label */
-      }, /* BR_RANGE_S256 */
+       (INSN_J8 << 16) /* j8 label */
+      },
+    .relax_code_size[BR_RANGE_S256] = 2,
+    .relax_branch_isize[BR_RANGE_S256] = 2,
+    .relax_fixup[BR_RANGE_S256] =
       {
-        INSN_J /* j label */
-      }, /* BR_RANGE_S16K */
+       {0, 2, NDS32_PCREL, BFD_RELOC_NDS32_9_PCREL},
+       {0, 0, 0, 0}
+      },
+
+    .relax_code_seq[BR_RANGE_S16K] =
       {
-        INSN_J /* j label */
-      }, /* BR_RANGE_S64K */
+       INSN_J          /* j label */
+      },
+    . relax_code_size[BR_RANGE_S16K] = 4,
+    .relax_branch_isize[BR_RANGE_S16K] = 4,
+    .relax_fixup[BR_RANGE_S16K] =
       {
-        INSN_J /* j label */
-      }, /* BR_RANGE_S16M */
+       {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
+       {0, 0, 0, 0}
+      },
+
+    .relax_code_seq[BR_RANGE_S64K] =
       {
-        INSN_SETHI_TA, /* sethi $ta, label */
-        INSN_ORI_TA, /* ori $ta, $ta, label */
-        INSN_JR_TA /* jr $ta */
-      }, /* BR_RANGE_U4G */
-    },                                         /* relax_code_seq */
-    {
-      {{0, 0, 0, FALSE}}, /* BR_RANGE_S256 */
-      {{0, 0, 0, FALSE}}, /* BR_RANGE_S16K */
-      {{0, 0, 0, FALSE}}, /* BR_RANGE_S64K */
-      {{0, 0, 0, FALSE}}, /* BR_RANGE_S16M */
-      {{0, 0, 0, FALSE}} /* BR_RANGE_U4G */
-    },                                         /* relax_code_condition */
-    {2, 4, 4, 4, 12},                          /* relax_code_size */
-    {2, 4, 4, 4, 4},                           /* relax_branch_isize */
-    {
+       INSN_J          /* j label */
+      },
+    .relax_code_size[BR_RANGE_S64K] = 4,
+    .relax_branch_isize[BR_RANGE_S64K] = 4,
+    .relax_fixup[BR_RANGE_S64K] =
       {
-        {0, 2, 0, BFD_RELOC_NDS32_9_PCREL},
-        {0, 0, 0, 0}
-      }, /* BR_RANGE_S256 */
+       {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
+       {0, 0, 0, 0}
+      },
+
+    .relax_code_seq[BR_RANGE_S16M] =
       {
-        {0, 4, 0, BFD_RELOC_NDS32_25_PCREL},
-        {0, 0, 0, 0}
-      }, /* BR_RANGE_S16K */
+       INSN_J          /* j label */
+      },
+    .relax_code_size[BR_RANGE_S16M] = 4,
+    .relax_branch_isize[BR_RANGE_S16M] = 4,
+    .relax_fixup[BR_RANGE_S16M] =
       {
-        {0, 4, 0, BFD_RELOC_NDS32_25_PCREL},
-        {0, 0, 0, 0}
-      }, /* BR_RANGE_S64K */
+       {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
+       {0, 0, 0, 0}
+      },
+
+    .relax_code_seq[BR_RANGE_U4G] =
       {
-        {0, 4, 0, BFD_RELOC_NDS32_25_PCREL},
-        {0, 0, 0, 0}
-      }, /* BR_RANGE_S16M */
+       INSN_SETHI_TA,  /* sethi $ta, label */
+       INSN_ORI_TA,    /* ori $ta, $ta, label */
+       INSN_JR_TA      /* jr $ta */
+      },
+    .relax_code_size[BR_RANGE_U4G] = 12,
+    .relax_branch_isize[BR_RANGE_U4G] = 4,
+    .relax_fixup[BR_RANGE_U4G] =
       {
-        {0, 4, 0, BFD_RELOC_NDS32_HI20},
+       {0, 4, 0, BFD_RELOC_NDS32_HI20},
        {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP4},
        {4, 4, NDS32_HINT | NDS32_FIX, BFD_RELOC_NDS32_LO12S0_ORI},
        {4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR},
@@ -395,60 +476,74 @@ static relax_info_t relax_table[] =
        {8, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY},
        {8, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
        {0, 0, 0, 0}
-      } /* BR_RANGE_U4G */
-    }                                          /* relax_fixup */
+      },
   },
   {
-    "j8",                                      /* opcode */
-    BR_RANGE_S256,                             /* br_range */
-    {{0, 0, 0, FALSE}},                        /* cond_field */
-    {
+    .opcode = "j8",
+    .br_range = BR_RANGE_S256,
+    .cond_field =
       {
-        (INSN_J8 << 16) /* j8 label */
-      }, /* BR_RANGE_S256 */
+       {0, 0, 0, FALSE}
+      },
+    .relax_code_seq[BR_RANGE_S256] =
       {
-        INSN_J /* j label */
-      }, /* BR_RANGE_S16K */
+       (INSN_J8 << 16) /* j8 label */
+      },
+    .relax_code_size[BR_RANGE_S256] = 2,
+    .relax_branch_isize[BR_RANGE_S256] = 2,
+    .relax_fixup[BR_RANGE_S256] =
       {
-        INSN_J /* j label */
-      }, /* BR_RANGE_S64K */
+       {0, 2, NDS32_PCREL, BFD_RELOC_NDS32_9_PCREL},
+       {0, 0, 0, 0}
+      },
+
+    .relax_code_seq[BR_RANGE_S16K] =
       {
-        INSN_J /* j label */
-      }, /* BR_RANGE_S16M */
+       INSN_J          /* j label */
+      },
+    .relax_code_size[BR_RANGE_S16K] = 4,
+    .relax_branch_isize[BR_RANGE_S16K] = 4,
+    .relax_fixup[BR_RANGE_S16K] =
       {
-        INSN_SETHI_TA, /* sethi $ta, label */
-        INSN_ORI_TA, /* ori $ta, $ta, label */
-        INSN_JR_TA /* jr $ta */
-      }, /* BR_RANGE_U4G */
-    },                                         /* relax_code_seq */
-    {
-      {{0, 0, 0, FALSE}}, /* BR_RANGE_S256 */
-      {{0, 0, 0, FALSE}}, /* BR_RANGE_S16K */
-      {{0, 0, 0, FALSE}}, /* BR_RANGE_S64K */
-      {{0, 0, 0, FALSE}}, /* BR_RANGE_S16M */
-      {{0, 0, 0, FALSE}} /* BR_RANGE_U4G */
-    },                                         /* relax_code_condition */
-    {2, 4, 4, 4, 12},                          /* relax_code_size */
-    {2, 4, 4, 4, 4},                           /* relax_branch_isize */
-    {
+       {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
+       {0, 0, 0, 0}
+      },
+
+    .relax_code_seq[BR_RANGE_S64K] =
       {
-        {0, 2, 0, BFD_RELOC_NDS32_9_PCREL},
-        {0, 0, 0, 0}
-      }, /* BR_RANGE_S256 */
+       INSN_J          /* j label */
+      },
+    .relax_code_size[BR_RANGE_S64K] = 4,
+    .relax_branch_isize[BR_RANGE_S64K] = 4,
+    .relax_fixup[BR_RANGE_S64K] =
       {
-        {0, 4, 0, BFD_RELOC_NDS32_25_PCREL},
-        {0, 0, 0, 0}
-      }, /* BR_RANGE_S16K */
+       {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
+       {0, 0, 0, 0}
+      },
+
+    .relax_code_seq[BR_RANGE_S16M] =
+      {
+       INSN_J          /* j label */
+      },
+    .relax_code_size[BR_RANGE_S16M] = 4,
+    .relax_branch_isize[BR_RANGE_S16M] = 4,
+    .relax_fixup[BR_RANGE_S16M] =
       {
-        {0, 4, 0, BFD_RELOC_NDS32_25_PCREL},
-        {0, 0, 0, 0}
-      }, /* BR_RANGE_S64K */
+       {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
+       {0, 0, 0, 0}
+      },
+
+    .relax_code_seq[BR_RANGE_U4G] =
       {
-        {0, 4, 0, BFD_RELOC_NDS32_25_PCREL},
-        {0, 0, 0, 0}
-      }, /* BR_RANGE_S16M */
+       INSN_SETHI_TA,  /* sethi $ta, label */
+       INSN_ORI_TA,    /* ori $ta, $ta, label */
+       INSN_JR_TA      /* jr $ta */
+      },
+    .relax_code_size[BR_RANGE_U4G] = 12,
+    .relax_branch_isize[BR_RANGE_U4G] = 4,
+    .relax_fixup[BR_RANGE_U4G] =
       {
-        {0, 4, 0, BFD_RELOC_NDS32_HI20},
+       {0, 4, 0, BFD_RELOC_NDS32_HI20},
        {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP4},
        {4, 4, NDS32_HINT | NDS32_FIX, BFD_RELOC_NDS32_LO12S0_ORI},
        {4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR},
@@ -456,85 +551,113 @@ static relax_info_t relax_table[] =
        {8, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY},
        {8, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
        {0, 0, 0, 0}
-      } /* BR_RANGE_U4G */
-    }                                          /* relax_fixup */
+      },
   },
   {
-    "beqz",                                    /* opcode */
-    BR_RANGE_S64K,                             /* br_range */
-    {
-      {0, 20, 0x1F, FALSE},
-      {0, 0, 0, FALSE}
-    },                                                 /* cond_field */
-    {
-      {
-        INSN_BEQZ /* beqz $rt, label */
-      }, /* BR_RANGE_S256 */
-      {
-        INSN_BEQZ /* beqz $rt, label */
-      }, /* BR_RANGE_S16K */
-      {
-        INSN_BEQZ /* beqz $rt, label */
-      }, /* BR_RANGE_S64K */
-      {
-        INSN_BNEZ, /* bnez $rt, $1 */
-        INSN_J /* j label */
-      }, /* BR_RANGE_S16M */
-      {
-        INSN_BNEZ, /* bnez $rt, $1 */
-        INSN_SETHI_TA, /* sethi $ta, label */
-        INSN_ORI_TA, /* ori $ta, $ta, label */
-        INSN_JR_TA /* jr $ta */
-      } /* BR_RANGE_U4G */
-    },                                         /* relax_code_seq */
-    {
-      {
-        {0, 20, 0x1F, FALSE},
-        {0, 0, 0, FALSE}
-      }, /* BR_RANGE_S256 */
-      {
-        {0, 20, 0x1F, FALSE},
-        {0, 0, 0, FALSE}
-      }, /* BR_RANGE_S16K */
-      {
-        {0, 20, 0x1F, FALSE},
-        {0, 0, 0, FALSE}
-      }, /* BR_RANGE_S64K */
+    .opcode = "beqz",
+    .br_range = BR_RANGE_S64K,
+    .cond_field =
+      {
+       {0, 20, 0x1F, FALSE},
+       {0, 0, 0, FALSE}
+      },
+    /* We do not use beqz38 and beqzs8 here directly because we
+       don't want to check register number for specail condition.  */
+    .relax_code_seq[BR_RANGE_S256] =
+      {
+         INSN_BEQZ     /* beqz $rt, label */
+      },
+    .relax_code_condition[BR_RANGE_S256] =
+      {
+       {0, 20, 0x1F, FALSE},
+       {0, 0, 0, FALSE},
+      },
+    .relax_code_size[BR_RANGE_S256] = 4,
+    .relax_branch_isize[BR_RANGE_S256] = 4,
+    .relax_fixup[BR_RANGE_S256] =
+      {
+       {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
+       {0, 4, NDS32_INSN16 , BFD_RELOC_NDS32_INSN16},
+       {0, 0, 0, 0}
+      },
+
+    .relax_code_seq[BR_RANGE_S16K] =
       {
-        {0, 20, 0x1F, FALSE},
-        {0, 0, 0, FALSE}
-      }, /* BR_RANGE_S16M */
+       INSN_BEQZ       /* beqz $rt, label */
+      },
+    .relax_code_condition[BR_RANGE_S16K] =
       {
-        {0, 20, 0x1F, FALSE},
-        {0, 0, 0, FALSE}
-      } /* BR_RANGE_U4G */
-    },                                         /* relax_code_condition */
-    {4, 4, 4, 8, 16},                          /* relax_code_size */
-    {4, 4, 4, 4, 4},                           /* relax_branch_isize */
-    {
+       {0, 20, 0x1F, FALSE},
+       {0, 0, 0, FALSE},
+      },
+    .relax_code_size[BR_RANGE_S16K] = 4,
+    .relax_branch_isize[BR_RANGE_S16K] = 4,
+    .relax_fixup[BR_RANGE_S16K] =
       {
-       {0, 4, 0, BFD_RELOC_NDS32_17_PCREL},
-       {0, 4, NDS32_INSN16 , BFD_RELOC_NDS32_INSN16},
-        {0, 0, 0, 0}
-      }, /* BR_RANGE_S256 */
+       {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
+       {0, 0, 0, 0}
+      },
+
+    .relax_code_seq[BR_RANGE_S64K] =
       {
-        {0, 4, 0, BFD_RELOC_NDS32_17_PCREL},
-        {0, 0, 0, 0}
-      }, /* BR_RANGE_S16K */
+       INSN_BEQZ       /* beqz $rt, label */
+      },
+    .relax_code_condition[BR_RANGE_S64K] =
       {
-        {0, 4, 0, BFD_RELOC_NDS32_17_PCREL},
-        {0, 0, 0, 0}
-      }, /* BR_RANGE_S64K */
+       {0, 20, 0x1F, FALSE},
+       {0, 0, 0, FALSE},
+      },
+    .relax_code_size[BR_RANGE_S64K] = 4,
+    .relax_branch_isize[BR_RANGE_S64K] = 4,
+    .relax_fixup[BR_RANGE_S64K] =
       {
-       {0, 4, NDS32_CREATE_LABEL, BFD_RELOC_NDS32_15_PCREL},
+       {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
+       {0, 0, 0, 0}
+      },
+
+    .relax_code_seq[BR_RANGE_S16M] =
+      {
+       INSN_BNEZ,      /* bnez $rt, $1 */
+       INSN_J          /* j label */
+      },
+    .relax_code_condition[BR_RANGE_S16M] =
+      {
+       {0, 20, 0x1F, FALSE},
+       {0, 0, 0, FALSE},
+      },
+    .relax_code_size[BR_RANGE_S16M] = 8,
+    .relax_branch_isize[BR_RANGE_S16M] = 4,
+    .relax_fixup[BR_RANGE_S16M] =
+      {
+       /* bnez range is 17 pcrel, but it use 15 pcrel here since link time
+          relaxtion.  If 17 pcrel can reach, it do not have to use S16M.
+          Therefore, 15 pcrel is just for linker to distinguish LONGJUMP5
+          and LONGJUMP6.  */
+       {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
        {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
        {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5},
-       {4, 4, 0, BFD_RELOC_NDS32_25_PCREL},
+       {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
        {4, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
        {0, 0, 0, 0}
-      }, /* BR_RANGE_S16M */
+      },
+
+    .relax_code_seq[BR_RANGE_U4G] =
+      {
+       INSN_BNEZ,      /* bnez $rt, $1 */
+       INSN_SETHI_TA,  /* sethi $ta, label */
+       INSN_ORI_TA,    /* ori $ta, $ta, label */
+       INSN_JR_TA      /* jr $ta */
+      },
+    .relax_code_condition[BR_RANGE_U4G] =
+      {
+       {0, 20, 0x1F, FALSE},
+       {0, 0, 0, FALSE},
+      },
+    .relax_code_size[BR_RANGE_U4G] = 16,
+    .relax_branch_isize[BR_RANGE_U4G] = 4,
+    .relax_fixup[BR_RANGE_U4G] =
       {
-        {0, 4, NDS32_CREATE_LABEL, BFD_RELOC_NDS32_15_PCREL},
+       {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
        {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
        {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP6},
        {4, 4, 0, BFD_RELOC_NDS32_HI20},
@@ -544,83 +667,104 @@ static relax_info_t relax_table[] =
        {12, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED},
        {12, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY},
        {12, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
-        {0, 0, 0, 0}
-      } /* BR_RANGE_U4G */
-    }                                          /* relax_fixup */
+       {0, 0, 0, 0}
+      },
   },
   {
-    "bgez",                                    /* opcode */
-    BR_RANGE_S64K,                             /* br_range */
-    {
-      {0, 20, 0x1F, FALSE},
-      {0, 0, 0, FALSE}
-    },                                                 /* cond_field */
-    {
-      {
-        INSN_BGEZ /* bgez $rt, label */
-      }, /* BR_RANGE_S256 */
-      {
-        INSN_BGEZ /* bgez $rt, label */
-      }, /* BR_RANGE_S16K */
-      {
-        INSN_BGEZ /* bgez $rt, label */
-      }, /* BR_RANGE_S64K */
-      {
-        INSN_BLTZ, /* bltz $rt, $1 */
-        INSN_J /* j label */
-      }, /* BR_RANGE_S16M */
-      {
-        INSN_BLTZ, /* bltz $rt, $1 */
-        INSN_SETHI_TA, /* sethi $ta, label */
-        INSN_ORI_TA, /* ori $ta, $ta, label */
-        INSN_JR_TA /* jr $ta */
-      } /* BR_RANGE_U4G */
-    },                                         /* relax_code_seq */
-    {
+    .opcode = "bgez",
+    .br_range = BR_RANGE_S64K,
+    .cond_field =
+      {
+       {0, 20, 0x1F, FALSE},
+       {0, 0, 0, FALSE}
+      },
+    .relax_code_seq[BR_RANGE_S256] =
+      {
+       INSN_BGEZ       /* bgez $rt, label */
+      },
+    .relax_code_condition[BR_RANGE_S256] =
+      {
+       {0, 20, 0x1F, FALSE},
+       {0, 0, 0, FALSE},
+      },
+    .relax_code_size[BR_RANGE_S256] = 4,
+    .relax_branch_isize[BR_RANGE_S256] = 4,
+    .relax_fixup[BR_RANGE_S256] =
+      {
+       {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
+       {0, 0, 0, 0}
+      },
+
+    .relax_code_seq[BR_RANGE_S16K] =
       {
-        {0, 20, 0x1F, FALSE},
-        {0, 0, 0, FALSE}
-      }, /* BR_RANGE_S256 */
+       INSN_BGEZ       /* bgez $rt, label */
+      },
+    .relax_code_condition[BR_RANGE_S16K] =
       {
-        {0, 20, 0x1F, FALSE},
-        {0, 0, 0, FALSE}
-      }, /* BR_RANGE_S16K */
+       {0, 20, 0x1F, FALSE},
+       {0, 0, 0, FALSE},
+      },
+    .relax_code_size[BR_RANGE_S16K] = 4,
+    .relax_branch_isize[BR_RANGE_S16K] = 4,
+    .relax_fixup[BR_RANGE_S16K] =
       {
-        {0, 20, 0x1F, FALSE},
-        {0, 0, 0, FALSE}
-      }, /* BR_RANGE_S64K */
+       {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
+       {0, 0, 0, 0}
+      },
+
+    .relax_code_seq[BR_RANGE_S64K] =
       {
-        {0, 20, 0x1F, FALSE},
-        {0, 0, 0, FALSE}
-      }, /* BR_RANGE_S16M */
+       INSN_BGEZ       /* bgez $rt, label */
+      },
+    .relax_code_condition[BR_RANGE_S64K] =
       {
-        {0, 20, 0x1F, FALSE},
-        {0, 0, 0, FALSE}
-      } /* BR_RANGE_U4G */
-    },                                         /* relax_code_condition */
-    {4, 4, 4, 8, 16},                          /* relax_code_size */
-    {4, 4, 4, 4, 4},                           /* relax_branch_isize */
-    {
+       {0, 20, 0x1F, FALSE},
+       {0, 0, 0, FALSE},
+      },
+    .relax_code_size[BR_RANGE_S64K] = 4,
+    .relax_branch_isize[BR_RANGE_S64K] = 4,
+    .relax_fixup[BR_RANGE_S64K] =
       {
-        {0, 4, 0, BFD_RELOC_NDS32_17_PCREL},
-        {0, 0, 0, 0}
-      }, /* BR_RANGE_S256 */
+       {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
+       {0, 0, 0, 0}
+      },
+
+    .relax_code_seq[BR_RANGE_S16M] =
       {
-        {0, 4, 0, BFD_RELOC_NDS32_17_PCREL},
-        {0, 0, 0, 0}
-      }, /* BR_RANGE_S16K */
+       INSN_BLTZ,      /* bltz $rt, $1 */
+       INSN_J          /* j label */
+      },
+    .relax_code_condition[BR_RANGE_S16M] =
       {
-        {0, 4, 0, BFD_RELOC_NDS32_17_PCREL},
-        {0, 0, 0, 0}
-      }, /* BR_RANGE_S64K */
+       {0, 20, 0x1F, FALSE},
+       {0, 0, 0, FALSE},
+      },
+    .relax_code_size[BR_RANGE_S16M] = 8,
+    .relax_branch_isize[BR_RANGE_S16M] = 4,
+    .relax_fixup[BR_RANGE_S16M] =
       {
-       {0, 4, NDS32_CREATE_LABEL, BFD_RELOC_NDS32_15_PCREL},
+       {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
        {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5},
-        {4, 4, 0, BFD_RELOC_NDS32_25_PCREL},
-        {0, 0, 0, 0}
-      }, /* BR_RANGE_S16M */
-      {
-        {0, 4, NDS32_CREATE_LABEL, BFD_RELOC_NDS32_15_PCREL},
+       {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
+       {0, 0, 0, 0}
+      },
+    .relax_code_seq[BR_RANGE_U4G] =
+      {
+       INSN_BLTZ,      /* bltz $rt, $1 */
+       INSN_SETHI_TA,  /* sethi $ta, label */
+       INSN_ORI_TA,    /* ori $ta, $ta, label */
+       INSN_JR_TA      /* jr $ta */
+      },
+    .relax_code_condition[BR_RANGE_U4G] =
+      {
+       {0, 20, 0x1F, FALSE},
+       {0, 0, 0, FALSE},
+      },
+    .relax_code_size[BR_RANGE_U4G] = 16,
+    .relax_branch_isize[BR_RANGE_U4G] = 4,
+    .relax_fixup[BR_RANGE_U4G] =
+      {
+       {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
        {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP6},
        {4, 4, 0, BFD_RELOC_NDS32_HI20},
        {4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR},
@@ -630,85 +774,107 @@ static relax_info_t relax_table[] =
        {12, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY},
        {12, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
        {0, 0, 0, 0}
-      } /* BR_RANGE_U4G */
-    }                                          /* relax_fixup */
+      },
   },
   {
-    "bnez",                                    /* opcode */
-    BR_RANGE_S64K,                             /* br_range */
-    {
-      {0, 20, 0x1F, FALSE},
-      {0, 0, 0, FALSE}
-    },                                                 /* cond_field */
-    {
-      {
-        INSN_BNEZ /* bnez $rt, label */
-      }, /* BR_RANGE_S256 */
-      {
-        INSN_BNEZ /* bnez $rt, label */
-      }, /* BR_RANGE_S16K */
-      {
-        INSN_BNEZ /* bnez $rt, label */
-      }, /* BR_RANGE_S64K */
-      {
-        INSN_BEQZ, /* beqz $rt, $1 */
-        INSN_J /* j label */
-      }, /* BR_RANGE_S16M */
-      {
-        INSN_BEQZ, /* beqz $rt, $1 */
-        INSN_SETHI_TA, /* sethi $ta, label */
-        INSN_ORI_TA, /* ori $ta, $ta, label */
-        INSN_JR_TA /* jr $ta */
-      } /* BR_RANGE_U4G */
-    },                                         /* relax_code_seq */
-    {
+    .opcode = "bnez",
+    .br_range = BR_RANGE_S64K,
+    .cond_field =
+      {
+       {0, 20, 0x1F, FALSE},
+       {0, 0, 0, FALSE}
+      },
+    .relax_code_seq[BR_RANGE_S256] =
+      {
+       INSN_BNEZ       /* bnez $rt, label */
+      },
+    .relax_code_condition[BR_RANGE_S256] =
+      {
+       {0, 20, 0x1F, FALSE},
+       {0, 0, 0, FALSE},
+      },
+    .relax_code_size[BR_RANGE_S256] = 4,
+    .relax_branch_isize[BR_RANGE_S256] = 4,
+    .relax_fixup[BR_RANGE_S256] =
+      {
+       {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
+       {0, 4, NDS32_INSN16, BFD_RELOC_NDS32_INSN16},
+       {0, 0, 0, 0}
+      },
+
+    .relax_code_seq[BR_RANGE_S16K] =
       {
-        {0, 20, 0x1F, FALSE},
-        {0, 0, 0, FALSE}
-      }, /* BR_RANGE_S256 */
+       INSN_BNEZ       /* bnez $rt, label */
+      },
+    .relax_code_condition[BR_RANGE_S16K] =
       {
-        {0, 20, 0x1F, FALSE},
-        {0, 0, 0, FALSE}
-      }, /* BR_RANGE_S16K */
+       {0, 20, 0x1F, FALSE},
+       {0, 0, 0, FALSE},
+      },
+    .relax_code_size[BR_RANGE_S16K] = 4,
+    .relax_branch_isize[BR_RANGE_S16K] = 4,
+    .relax_fixup[BR_RANGE_S16K] =
       {
-        {0, 20, 0x1F, FALSE},
-        {0, 0, 0, FALSE}
-      }, /* BR_RANGE_S64K */
+       {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
+       {0, 0, 0, 0}
+      },
+
+    .relax_code_seq[BR_RANGE_S64K] =
       {
-        {0, 20, 0x1F, FALSE},
-        {0, 0, 0, FALSE}
-      }, /* BR_RANGE_S16M */
+       INSN_BNEZ       /* bnez $rt, label */
+      },
+    .relax_code_condition[BR_RANGE_S64K] =
       {
-        {0, 20, 0x1F, FALSE},
-        {0, 0, 0, FALSE}
-      } /* BR_RANGE_U4G */
-    },                                         /* relax_code_condition */
-    {4, 4, 4, 8, 16},                          /* relax_code_size */
-    {4, 4, 4, 4, 4},                           /* relax_branch_isize */
-    {
+       {0, 20, 0x1F, FALSE},
+       {0, 0, 0, FALSE},
+      },
+    .relax_code_size[BR_RANGE_S64K] = 4,
+    .relax_branch_isize[BR_RANGE_S64K] = 4,
+    .relax_fixup[BR_RANGE_S64K] =
       {
-       {0, 4, 0, BFD_RELOC_NDS32_17_PCREL},
-       {0, 4, NDS32_INSN16 , BFD_RELOC_NDS32_INSN16},
-        {0, 0, 0, 0}
-      }, /* BR_RANGE_S256 */
+       {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
+       {0, 0, 0, 0}
+      },
+
+    .relax_code_seq[BR_RANGE_S16M] =
       {
-        {0, 4, 0, BFD_RELOC_NDS32_17_PCREL},
-        {0, 0, 0, 0}
-      }, /* BR_RANGE_S16K */
+       INSN_BEQZ,      /* beqz $rt, $1 */
+       INSN_J          /* j label */
+      },
+    .relax_code_condition[BR_RANGE_S16M] =
       {
-        {0, 4, 0, BFD_RELOC_NDS32_17_PCREL},
-        {0, 0, 0, 0}
-      }, /* BR_RANGE_S64K */
+       {0, 20, 0x1F, FALSE},
+       {0, 0, 0, FALSE},
+      },
+    .relax_code_size[BR_RANGE_S16M] = 8,
+    .relax_branch_isize[BR_RANGE_S16M] = 4,
+    .relax_fixup[BR_RANGE_S16M] =
       {
-       {0, 4, NDS32_CREATE_LABEL, BFD_RELOC_NDS32_15_PCREL},
+       {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
        {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
        {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5},
-       {4, 4, 0, BFD_RELOC_NDS32_25_PCREL},
+       {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
        {4, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
-        {0, 0, 0, 0}
-      }, /* BR_RANGE_S16M */
+       {0, 0, 0, 0}
+      },
+
+    .relax_code_seq[BR_RANGE_U4G] =
       {
-        {0, 4, NDS32_CREATE_LABEL, BFD_RELOC_NDS32_15_PCREL},
+       INSN_BEQZ,      /* beqz $rt, $1 */
+       INSN_SETHI_TA,  /* sethi $ta, label */
+       INSN_ORI_TA,    /* ori $ta, $ta, label */
+       INSN_JR_TA      /* jr $ta */
+      },
+    .relax_code_condition[BR_RANGE_U4G] =
+      {
+       {0, 20, 0x1F, FALSE},
+       {0, 0, 0, FALSE},
+      },
+    .relax_code_size[BR_RANGE_U4G] = 16,
+    .relax_branch_isize[BR_RANGE_U4G] = 4,
+    .relax_fixup[BR_RANGE_U4G] =
+      {
+       {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
        {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
        {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP6},
        {4, 4, 0, BFD_RELOC_NDS32_HI20},
@@ -719,82 +885,104 @@ static relax_info_t relax_table[] =
        {12, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY},
        {12, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
        {0, 0, 0, 0}
-      } /* BR_RANGE_U4G */
-    }                                          /* relax_fixup */
+      },
   },
   {
-    "bgtz",                                    /* opcode */
-    BR_RANGE_S64K,                             /* br_range */
-    {
-      {0, 20, 0x1F, FALSE},
-      {0, 0, 0, FALSE}
-    },                                                 /* cond_field */
-    {
-      {
-        INSN_BGTZ /* bgtz $rt, label */
-      }, /* BR_RANGE_S256 */
-      {
-        INSN_BGTZ /* bgtz $rt, label */
-      }, /* BR_RANGE_S16K */
-      {
-        INSN_BGTZ /* bgtz $rt, label */
-      }, /* BR_RANGE_S64K */
+    .opcode = "bgtz",
+    .br_range = BR_RANGE_S64K,
+    .cond_field =
+      {
+       {0, 20, 0x1F, FALSE},
+       {0, 0, 0, FALSE}
+      },
+    .relax_code_seq[BR_RANGE_S256] =
+      {
+       INSN_BGTZ       /* bgtz $rt, label */
+      },
+    .relax_code_condition[BR_RANGE_S256] =
+      {
+       {0, 20, 0x1F, FALSE},
+       {0, 0, 0, FALSE},
+      },
+    .relax_code_size[BR_RANGE_S256] = 4,
+    .relax_branch_isize[BR_RANGE_S256] = 4,
+    .relax_fixup[BR_RANGE_S256] =
+      {
+       {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
+       {0, 0, 0, 0}
+      },
+
+    .relax_code_seq[BR_RANGE_S16K] =
       {
-        INSN_BLEZ, /* blez $rt, $1 */
-        INSN_J /* j label */
-      }, /* BR_RANGE_S16M */
+       INSN_BGTZ       /* bgtz $rt, label */
+      },
+    .relax_code_condition[BR_RANGE_S16K] =
       {
-        INSN_BLEZ, /* blez $rt, $1 */
-        INSN_SETHI_TA, /* sethi $ta, label */
-        INSN_ORI_TA, /* ori $ta, $ta, label */
-        INSN_JR_TA /* jr $ta */
-      } /* BR_RANGE_U4G */
-    },                                         /* relax_code_seq */
-    {
+       {0, 20, 0x1F, FALSE},
+       {0, 0, 0, FALSE},
+      },
+    .relax_code_size[BR_RANGE_S16K] = 4,
+    .relax_branch_isize[BR_RANGE_S16K] = 4,
+    .relax_fixup[BR_RANGE_S16K] =
       {
-        {0, 20, 0x1F, FALSE},
-        {0, 0, 0, FALSE}
-      }, /* BR_RANGE_S256 */
+       {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
+       {0, 0, 0, 0}
+      },
+
+    .relax_code_seq[BR_RANGE_S64K] =
       {
-        {0, 20, 0x1F, FALSE},
-        {0, 0, 0, FALSE}
-      }, /* BR_RANGE_S16K */
+       INSN_BGTZ       /* bgtz $rt, label */
+      },
+    .relax_code_condition[BR_RANGE_S64K] =
       {
-        {0, 20, 0x1F, FALSE},
-        {0, 0, 0, FALSE}
-      }, /* BR_RANGE_S64K */
+       {0, 20, 0x1F, FALSE},
+       {0, 0, 0, FALSE},
+      },
+    .relax_code_size[BR_RANGE_S64K] = 4,
+    .relax_branch_isize[BR_RANGE_S64K] = 4,
+    .relax_fixup[BR_RANGE_S64K] =
       {
-        {0, 20, 0x1F, FALSE},
-        {0, 0, 0, FALSE}
-      }, /* BR_RANGE_S16M */
+       {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
+       {0, 0, 0, 0}
+      },
+
+    .relax_code_seq[BR_RANGE_S16M] =
       {
-        {0, 20, 0x1F, FALSE},
-        {0, 0, 0, FALSE}
-      } /* BR_RANGE_U4G */
-    },                                         /* relax_code_condition */
-    {4, 4, 4, 8, 16},                          /* relax_code_size */
-    {4, 4, 4, 4, 4},                           /* relax_branch_isize */
-    {
+       INSN_BLEZ,      /* blez $rt, $1 */
+       INSN_J          /* j label */
+      },
+    .relax_code_condition[BR_RANGE_S16M] =
       {
-        {0, 4, 0, BFD_RELOC_NDS32_17_PCREL},
-        {0, 0, 0, 0}
-      }, /* BR_RANGE_S256 */
+       {0, 20, 0x1F, FALSE},
+       {0, 0, 0, FALSE},
+      },
+    .relax_code_size[BR_RANGE_S16M] = 8,
+    .relax_branch_isize[BR_RANGE_S16M] = 4,
+    .relax_fixup[BR_RANGE_S16M] =
       {
-        {0, 4, 0, BFD_RELOC_NDS32_17_PCREL},
-        {0, 0, 0, 0}
-      }, /* BR_RANGE_S16K */
+       {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
+       {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5},
+       {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
+       {0, 0, 0, 0}
+      },
+
+    .relax_code_seq[BR_RANGE_U4G] =
       {
-        {0, 4, 0, BFD_RELOC_NDS32_17_PCREL},
-        {0, 0, 0, 0}
-      }, /* BR_RANGE_S64K */
+       INSN_BLEZ,      /* blez $rt, $1 */
+       INSN_SETHI_TA,  /* sethi $ta, label */
+       INSN_ORI_TA,    /* ori $ta, $ta, label */
+       INSN_JR_TA      /* jr $ta */
+      },
+    .relax_code_condition[BR_RANGE_U4G] =
       {
-       {0, 4, NDS32_CREATE_LABEL, BFD_RELOC_NDS32_15_PCREL},
-       {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5},
-        {4, 4, 0, BFD_RELOC_NDS32_25_PCREL},
-        {0, 0, 0, 0}
-      }, /* BR_RANGE_S16M */
+       {0, 20, 0x1F, FALSE},
+       {0, 0, 0, FALSE},
+      },
+    .relax_code_size[BR_RANGE_U4G] = 16,
+    .relax_branch_isize[BR_RANGE_U4G] = 4,
+    .relax_fixup[BR_RANGE_U4G] =
       {
-        {0, 4, NDS32_CREATE_LABEL, BFD_RELOC_NDS32_15_PCREL},
+       {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
        {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP6},
        {4, 4, 0, BFD_RELOC_NDS32_HI20},
        {4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR},
@@ -804,82 +992,104 @@ static relax_info_t relax_table[] =
        {12, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY},
        {12, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
        {0, 0, 0, 0}
-      } /* BR_RANGE_U4G */
-    }                                          /* relax_fixup */
+      },
   },
   {
-    "blez",                                    /* opcode */
-    BR_RANGE_S64K,                             /* br_range */
-    {
-      {0, 20, 0x1F, FALSE},
-      {0, 0, 0, FALSE}
-    },                                         /* cond_field */
-    {
-      {
-        INSN_BLEZ /* blez $rt, label */
-      }, /* BR_RANGE_S256 */
-      {
-        INSN_BLEZ /* blez $rt, label */
-      }, /* BR_RANGE_S16K */
-      {
-        INSN_BLEZ /* blez $rt, label */
-      }, /* BR_RANGE_S64K */
+    .opcode = "blez",
+    .br_range = BR_RANGE_S64K,
+    .cond_field =
+      {
+       {0, 20, 0x1F, FALSE},
+       {0, 0, 0, FALSE}
+      },
+    .relax_code_seq[BR_RANGE_S256] =
+      {
+       INSN_BLEZ       /* blez $rt, label */
+      },
+    .relax_code_condition[BR_RANGE_S256] =
+      {
+       {0, 20, 0x1F, FALSE},
+       {0, 0, 0, FALSE},
+      },
+    .relax_code_size[BR_RANGE_S256] = 4,
+    .relax_branch_isize[BR_RANGE_S256] = 4,
+    .relax_fixup[BR_RANGE_S256] =
+      {
+       {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
+       {0, 0, 0, 0}
+      },
+
+    .relax_code_seq[BR_RANGE_S16K] =
       {
-        INSN_BGTZ, /* bgtz $rt, $1 */
-        INSN_J /* j label */
-      }, /* BR_RANGE_S16M */
+       INSN_BLEZ       /* blez $rt, label */
+      },
+    .relax_code_condition[BR_RANGE_S16K] =
       {
-        INSN_BGTZ, /* bgtz $rt, $1 */
-        INSN_SETHI_TA, /* sethi $ta, label */
-        INSN_ORI_TA, /* ori $ta, $ta, label */
-        INSN_JR_TA /* jr $ta */
-      } /* BR_RANGE_U4G */
-    },                                         /* relax_code_seq */
-    {
+       {0, 20, 0x1F, FALSE},
+       {0, 0, 0, FALSE},
+      },
+    .relax_code_size[BR_RANGE_S16K] = 4,
+    .relax_branch_isize[BR_RANGE_S16K] = 4,
+    .relax_fixup[BR_RANGE_S16K] =
       {
-        {0, 20, 0x1F, FALSE},
-        {0, 0, 0, FALSE}
-      }, /* BR_RANGE_S256 */
+       {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
+       {0, 0, 0, 0}
+      },
+
+    .relax_code_seq[BR_RANGE_S64K] =
       {
-        {0, 20, 0x1F, FALSE},
-        {0, 0, 0, FALSE}
-      }, /* BR_RANGE_S16K */
+       INSN_BLEZ       /* blez $rt, label */
+      },
+    .relax_code_condition[BR_RANGE_S64K] =
       {
-        {0, 20, 0x1F, FALSE},
-        {0, 0, 0, FALSE}
-      }, /* BR_RANGE_S64K */
+       {0, 20, 0x1F, FALSE},
+       {0, 0, 0, FALSE},
+      },
+    .relax_code_size[BR_RANGE_S64K] = 4,
+    .relax_branch_isize[BR_RANGE_S64K] = 4,
+    .relax_fixup[BR_RANGE_S64K] =
       {
-        {0, 20, 0x1F, FALSE},
-        {0, 0, 0, FALSE}
-      }, /* BR_RANGE_S16M */
+       {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
+       {0, 0, 0, 0}
+      },
+
+    .relax_code_seq[BR_RANGE_S16M] =
       {
-        {0, 20, 0x1F, FALSE},
-        {0, 0, 0, FALSE}
-      } /* BR_RANGE_U4G */
-    },                                         /* relax_code_condition */
-    {4, 4, 4, 8, 16},                          /* relax_code_size */
-    {4, 4, 4, 4, 4},                           /* relax_branch_isize */
-    {
+       INSN_BGTZ,      /* bgtz $rt, $1 */
+       INSN_J          /* j label */
+      },
+    .relax_code_condition[BR_RANGE_S16M] =
       {
-        {0, 4, 0, BFD_RELOC_NDS32_17_PCREL},
-        {0, 0, 0, 0}
-      }, /* BR_RANGE_S256 */
+       {0, 20, 0x1F, FALSE},
+       {0, 0, 0, FALSE},
+      },
+    .relax_code_size[BR_RANGE_S16M] = 8,
+    .relax_branch_isize[BR_RANGE_S16M] = 4,
+    .relax_fixup[BR_RANGE_S16M] =
       {
-        {0, 4, 0, BFD_RELOC_NDS32_17_PCREL},
-        {0, 0, 0, 0}
-      }, /* BR_RANGE_S16K */
+       {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
+       {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5},
+       {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
+       {0, 0, 0, 0}
+      },
+
+    .relax_code_seq[BR_RANGE_U4G] =
       {
-        {0, 4, 0, BFD_RELOC_NDS32_17_PCREL},
-        {0, 0, 0, 0}
-      }, /* BR_RANGE_S64K */
+       INSN_BGTZ,      /* bgtz $rt, $1 */
+       INSN_SETHI_TA,  /* sethi $ta, label */
+       INSN_ORI_TA,    /* ori $ta, $ta, label */
+       INSN_JR_TA      /* jr $ta */
+      },
+    .relax_code_condition[BR_RANGE_U4G] =
       {
-       {0, 4, NDS32_CREATE_LABEL, BFD_RELOC_NDS32_15_PCREL},
-       {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5},
-        {4, 4, 0, BFD_RELOC_NDS32_25_PCREL},
-        {0, 0, 0, 0}
-      }, /* BR_RANGE_S16M */
+       {0, 20, 0x1F, FALSE},
+       {0, 0, 0, FALSE},
+      },
+    .relax_code_size[BR_RANGE_U4G] = 16,
+    .relax_branch_isize[BR_RANGE_U4G] = 4,
+    .relax_fixup[BR_RANGE_U4G] =
       {
-        {0, 4, NDS32_CREATE_LABEL, BFD_RELOC_NDS32_15_PCREL},
+       {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
        {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP6},
        {4, 4, 0, BFD_RELOC_NDS32_HI20},
        {4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR},
@@ -889,82 +1099,104 @@ static relax_info_t relax_table[] =
        {12, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY},
        {12, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
        {0, 0, 0, 0}
-      } /* BR_RANGE_U4G */
-    }                                          /* relax_fixup */
+      },
   },
   {
-    "bltz",                                    /* opcode */
-    BR_RANGE_S64K,                             /* br_range */
-    {
-      {0, 20, 0x1F, FALSE},
-      {0, 0, 0, FALSE}
-    },                                                 /* cond_field */
-    {
-      {
-        INSN_BLTZ /* bltz $rt, label */
-      }, /* BR_RANGE_S256 */
-      {
-        INSN_BLTZ /* bltz $rt, label */
-      }, /* BR_RANGE_S16K */
-      {
-        INSN_BLTZ /* bltz $rt, label */
-      }, /* BR_RANGE_S64K */
+    .opcode = "bltz",
+    .br_range = BR_RANGE_S64K,
+    .cond_field =
+      {
+       {0, 20, 0x1F, FALSE},
+       {0, 0, 0, FALSE}
+      },
+    .relax_code_seq[BR_RANGE_S256] =
+      {
+       INSN_BLTZ       /* bltz $rt, label */
+      },
+    .relax_code_condition[BR_RANGE_S256] =
+      {
+       {0, 20, 0x1F, FALSE},
+       {0, 0, 0, FALSE},
+      },
+    .relax_code_size[BR_RANGE_S256] = 4,
+    .relax_branch_isize[BR_RANGE_S256] = 4,
+    .relax_fixup[BR_RANGE_S256] =
+      {
+       {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
+       {0, 0, 0, 0}
+      },
+
+    .relax_code_seq[BR_RANGE_S16K] =
       {
-        INSN_BGEZ, /* bgez $rt, $1 */
-        INSN_J /* j label */
-      }, /* BR_RANGE_S16M */
+       INSN_BLTZ       /* bltz $rt, label */
+      },
+    .relax_code_condition[BR_RANGE_S16K] =
       {
-        INSN_BGEZ, /* bgez $rt, $1 */
-        INSN_SETHI_TA, /* sethi $ta, label */
-        INSN_ORI_TA, /* ori $ta, $ta, label */
-        INSN_JR_TA /* jr $ta */
-      } /* BR_RANGE_U4G */
-    },                                         /* relax_code_seq */
-    {
+       {0, 20, 0x1F, FALSE},
+       {0, 0, 0, FALSE},
+      },
+    .relax_code_size[BR_RANGE_S16K] = 4,
+    .relax_branch_isize[BR_RANGE_S16K] = 4,
+    .relax_fixup[BR_RANGE_S16K] =
       {
-        {0, 20, 0x1F, FALSE},
-        {0, 0, 0, FALSE}
-      }, /* BR_RANGE_S256 */
+       {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
+       {0, 0, 0, 0}
+      },
+
+    .relax_code_seq[BR_RANGE_S64K] =
       {
-        {0, 20, 0x1F, FALSE},
-        {0, 0, 0, FALSE}
-      }, /* BR_RANGE_S16K */
+       INSN_BLTZ       /* bltz $rt, label */
+      },
+    .relax_code_condition[BR_RANGE_S64K] =
       {
-        {0, 20, 0x1F, FALSE},
-        {0, 0, 0, FALSE}
-      }, /* BR_RANGE_S64K */
+       {0, 20, 0x1F, FALSE},
+       {0, 0, 0, FALSE},
+      },
+    .relax_code_size[BR_RANGE_S64K] = 4,
+    .relax_branch_isize[BR_RANGE_S64K] = 4,
+    .relax_fixup[BR_RANGE_S64K] =
       {
-        {0, 20, 0x1F, FALSE},
-        {0, 0, 0, FALSE}
-      }, /* BR_RANGE_S16M */
+       {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
+       {0, 0, 0, 0}
+      },
+
+    .relax_code_seq[BR_RANGE_S16M] =
       {
-        {0, 20, 0x1F, FALSE},
-        {0, 0, 0, FALSE}
-      } /* BR_RANGE_U4G */
-    },                                         /* relax_code_condition */
-    {4, 4, 4, 8, 16},                          /* relax_code_size */
-    {4, 4, 4, 4, 4},                           /* relax_branch_isize */
-    {
+       INSN_BGEZ,      /* bgez $rt, $1 */
+       INSN_J          /* j label */
+      },
+    .relax_code_condition[BR_RANGE_S16M] =
       {
-        {0, 4, 0, BFD_RELOC_NDS32_17_PCREL},
-        {0, 0, 0, 0}
-      }, /* BR_RANGE_S256 */
+       {0, 20, 0x1F, FALSE},
+       {0, 0, 0, FALSE},
+      },
+    .relax_code_size[BR_RANGE_S16M] = 8,
+    .relax_branch_isize[BR_RANGE_S16M] = 4,
+    .relax_fixup[BR_RANGE_S16M] =
       {
-        {0, 4, 0, BFD_RELOC_NDS32_17_PCREL},
-        {0, 0, 0, 0}
-      }, /* BR_RANGE_S16K */
+       {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
+       {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5},
+       {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
+       {0, 0, 0, 0}
+      },
+
+    .relax_code_seq[BR_RANGE_U4G] =
       {
-        {0, 4, 0, BFD_RELOC_NDS32_17_PCREL},
-        {0, 0, 0, 0}
-      }, /* BR_RANGE_S64K */
+       INSN_BGEZ,      /* bgez $rt, $1 */
+       INSN_SETHI_TA,  /* sethi $ta, label */
+       INSN_ORI_TA,    /* ori $ta, $ta, label */
+       INSN_JR_TA      /* jr $ta */
+      },
+    .relax_code_condition[BR_RANGE_U4G] =
       {
-       {0, 4, NDS32_CREATE_LABEL, BFD_RELOC_NDS32_15_PCREL},
-       {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5},
-        {4, 4, 0, BFD_RELOC_NDS32_25_PCREL},
-        {0, 0, 0, 0}
-      }, /* BR_RANGE_S16M */
+       {0, 20, 0x1F, FALSE},
+       {0, 0, 0, FALSE},
+      },
+    .relax_code_size[BR_RANGE_U4G] = 16,
+    .relax_branch_isize[BR_RANGE_U4G] = 4,
+    .relax_fixup[BR_RANGE_U4G] =
       {
-        {0, 4, NDS32_CREATE_LABEL, BFD_RELOC_NDS32_15_PCREL},
+       {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
        {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP6},
        {4, 4, 0, BFD_RELOC_NDS32_HI20},
        {4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR},
@@ -974,97 +1206,118 @@ static relax_info_t relax_table[] =
        {12, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY},
        {12, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
        {0, 0, 0, 0}
-      } /* BR_RANGE_U4G */
-    }                                          /* relax_fixup */
+      },
   },
   {
-    "beq",                                     /* opcode */
-    BR_RANGE_S16K,                             /* br_range */
-    {
-      {0, 20, 0x1F, FALSE},
-      {0, 15, 0x1F, FALSE},
-      {0, 0, 0, FALSE}
-    },                                                 /* cond_field */
-    {
-      {
-        INSN_BEQ /* beq $rt, $ra, label */
-      }, /* BR_RANGE_S256 */
-      {
-        INSN_BEQ /* beq $rt, $ra, label */
-      }, /* BR_RANGE_S16K */
-      {
-        INSN_BNE, /* bne $rt, $ra, $1 */
-        INSN_J /* j label */
-      }, /* BR_RANGE_S64K */
-      {
-        INSN_BNE, /* bne $rt, $ra, $1 */
-        INSN_J /* j label */
-      }, /* BR_RANGE_S16M */
-      {
-        INSN_BNE, /* bne $rt, $ra, $1 */
-        INSN_SETHI_TA, /* sethi $ta, label */
-        INSN_ORI_TA, /* ori $ta, $ta, label */
-        INSN_JR_TA /* jr $ta */
-      } /* BR_RANGE_U4G */
-    },                                         /* relax_code_seq */
-    {
-      {
-        {0, 20, 0x1F, FALSE},
-        {0, 15, 0x1F, FALSE},
-        {0, 0, 0, FALSE}
-      }, /* BR_RANGE_S256 */
-      {
-        {0, 20, 0x1F, FALSE},
-        {0, 15, 0x1F, FALSE},
-        {0, 0, 0, FALSE}
-      }, /* BR_RANGE_S16K */
+    .opcode = "beq",
+    .br_range = BR_RANGE_S16K,
+    .cond_field =
+      {
+       {0, 20, 0x1F, FALSE},
+       {0, 15, 0x1F, FALSE},
+       {0, 0, 0, FALSE}
+      },
+    .relax_code_seq[BR_RANGE_S256] =
+      {
+       INSN_BEQ        /* beq $rt, $ra, label */
+      },
+    .relax_code_condition[BR_RANGE_S256] =
+      {
+       {0, 20, 0x1F, FALSE},
+       {0, 15, 0x1F, FALSE},
+       {0, 0, 0, FALSE}
+      },
+    .relax_code_size[BR_RANGE_S256] = 4,
+    .relax_branch_isize[BR_RANGE_S256] = 4,
+    .relax_fixup[BR_RANGE_S256] =
+      {
+       {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
+       {0, 4, NDS32_INSN16, BFD_RELOC_NDS32_INSN16},
+       {0, 0, 0, 0}
+      },
+
+    .relax_code_seq[BR_RANGE_S16K] =
       {
-        {0, 20, 0x1F, FALSE},
-        {0, 15, 0x1F, FALSE},
-        {0, 0, 0, FALSE}
-      }, /* BR_RANGE_S64K */
+       INSN_BEQ        /* beq $rt, $ra, label */
+      },
+    .relax_code_condition[BR_RANGE_S16K] =
       {
-        {0, 20, 0x1F, FALSE},
-        {0, 15, 0x1F, FALSE},
-        {0, 0, 0, FALSE}
-      }, /* BR_RANGE_S16M */
+       {0, 20, 0x1F, FALSE},
+       {0, 15, 0x1F, FALSE},
+       {0, 0, 0, FALSE}
+      },
+    .relax_code_size[BR_RANGE_S16K] = 4,
+    .relax_branch_isize[BR_RANGE_S16K] = 4,
+    .relax_fixup[BR_RANGE_S16K] =
       {
-        {0, 20, 0x1F, FALSE},
-        {0, 15, 0x1F, FALSE},
-        {0, 0, 0, FALSE}
-      } /* BR_RANGE_U4G */
-    },                                         /* relax_code_condition */
-    {4, 4, 8, 8, 16},                          /* relax_code_size */
-    {4, 4, 4, 4, 4},                           /* relax_branch_isize */
-    {
+       {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
+       {0, 0, 0, 0}
+      },
+
+    .relax_code_seq[BR_RANGE_S64K] =
       {
-        {0, 4, 0, BFD_RELOC_NDS32_15_PCREL},
-        {0, 4, NDS32_INSN16, BFD_RELOC_NDS32_INSN16},
-        {0, 0, 0, 0}
-      }, /* BR_RANGE_S256 */
+       INSN_BNE,       /* bne $rt, $ra, $1 */
+       INSN_J          /* j label */
+      },
+    .relax_code_condition[BR_RANGE_S64K] =
       {
-        {0, 4, 0, BFD_RELOC_NDS32_15_PCREL},
-        {0, 0, 0, 0}
-      }, /* BR_RANGE_S16K */
+       {0, 20, 0x1F, FALSE},
+       {0, 15, 0x1F, FALSE},
+       {0, 0, 0, FALSE}
+      },
+    .relax_code_size[BR_RANGE_S64K] = 8,
+    .relax_branch_isize[BR_RANGE_S64K] = 4,
+    .relax_fixup[BR_RANGE_S64K] =
       {
-       {0, 4, NDS32_CREATE_LABEL, BFD_RELOC_NDS32_15_PCREL},
+       {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
        {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
        {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5},
-       {4, 4, 0, BFD_RELOC_NDS32_25_PCREL},
+       {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
        {4, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
-        {0, 0, 0, 0}
-      }, /* BR_RANGE_S64K */
+       {0, 0, 0, 0}
+      },
+
+    .relax_code_seq[BR_RANGE_S16M] =
+      {
+       INSN_BNE,       /* bne $rt, $ra, $1 */
+       INSN_J          /* j label */
+      },
+    .relax_code_condition[BR_RANGE_S16M] =
+      {
+       {0, 20, 0x1F, FALSE},
+       {0, 15, 0x1F, FALSE},
+       {0, 0, 0, FALSE}
+      },
+    .relax_code_size[BR_RANGE_S16M] = 8,
+    .relax_branch_isize[BR_RANGE_S16M] = 4,
+    .relax_fixup[BR_RANGE_S16M] =
       {
-       {0, 4, NDS32_CREATE_LABEL, BFD_RELOC_NDS32_15_PCREL},
+       {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
        {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
        {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5},
-       {4, 4, 0, BFD_RELOC_NDS32_25_PCREL},
-       {4, 4, NDS32_ABS, BFD_RELOC_NDS32_EMPTY},
+       {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
        {4, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
-        {0, 0, 0, 0}
-      }, /* BR_RANGE_S16M */
-      {
-        {0, 4, NDS32_CREATE_LABEL, BFD_RELOC_NDS32_15_PCREL},
+       {0, 0, 0, 0}
+      },
+
+    .relax_code_seq[BR_RANGE_U4G] =
+      {
+       INSN_BNE,       /* bne $rt, $ra, $1 */
+       INSN_SETHI_TA,  /* sethi $ta, label */
+       INSN_ORI_TA,    /* ori $ta, $ta, label */
+       INSN_JR_TA      /* jr $ta */
+      },
+    .relax_code_condition[BR_RANGE_U4G] =
+      {
+       {0, 20, 0x1F, FALSE},
+       {0, 15, 0x1F, FALSE},
+       {0, 0, 0, FALSE}
+      },
+    .relax_code_size[BR_RANGE_U4G] = 16,
+    .relax_branch_isize[BR_RANGE_U4G] = 4,
+    .relax_fixup[BR_RANGE_U4G] =
+      {
+       {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
        {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
        {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP6},
        {4, 4, 0, BFD_RELOC_NDS32_HI20},
@@ -1075,96 +1328,118 @@ static relax_info_t relax_table[] =
        {12, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY},
        {12, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
        {0, 0, 0, 0}
-      } /* BR_RANGE_U4G */
-    }                                          /* relax_fixup */
+      },
   },
   {
-    "bne",                                     /* opcode */
-    BR_RANGE_S16K,                             /* br_range */
-    {
-      {0, 20, 0x1F, FALSE},
-      {0, 15, 0x1F, FALSE},
-      {0, 0, 0, FALSE}
-    },                                         /* cond_field */
-    {
-      {
-        INSN_BNE /* bne $rt, $ra, label */
-      }, /* BR_RANGE_S256 */
-      {
-        INSN_BNE /* bne $rt, $ra, label */
-      }, /* BR_RANGE_S16K */
-      {
-        INSN_BEQ, /* beq $rt, $ra, $1 */
-        INSN_J /* j label */
-      }, /* BR_RANGE_S64K */
-      {
-        INSN_BEQ, /* beq $rt, $ra, $1 */
-        INSN_J /* j label */
-      }, /* BR_RANGE_S16M */
-      {
-        INSN_BEQ, /* beq $rt, $ra, $1 */
-        INSN_SETHI_TA, /* sethi $ta, label */
-        INSN_ORI_TA, /* ori $ta, $ta, label */
-        INSN_JR_TA /* jr $ta */
-      } /* BR_RANGE_U4G */
-    },                                         /* relax_code_seq */
-    {
-      {
-        {0, 20, 0x1F, FALSE},
-        {0, 15, 0x1F, FALSE},
-        {0, 0, 0, FALSE}
-      }, /* BR_RANGE_S256 */
-      {
-        {0, 20, 0x1F, FALSE},
-        {0, 15, 0x1F, FALSE},
-        {0, 0, 0, FALSE}
-      }, /* BR_RANGE_S16K */
+    .opcode = "bne",
+    .br_range = BR_RANGE_S16K,
+    .cond_field =
+      {
+       {0, 20, 0x1F, FALSE},
+       {0, 15, 0x1F, FALSE},
+       {0, 0, 0, FALSE}
+      },
+    .relax_code_seq[BR_RANGE_S256] =
+      {
+       INSN_BNE        /* bne $rt, $ra, label */
+      },
+    .relax_code_condition[BR_RANGE_S256] =
+      {
+       {0, 20, 0x1F, FALSE},
+       {0, 15, 0x1F, FALSE},
+       {0, 0, 0, FALSE}
+      },
+    .relax_code_size[BR_RANGE_S256] = 4,
+    .relax_branch_isize[BR_RANGE_S256] = 4,
+    .relax_fixup[BR_RANGE_S256] =
+      {
+       {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
+       {0, 4, NDS32_INSN16, BFD_RELOC_NDS32_INSN16},
+       {0, 0, 0, 0}
+      },
+
+    .relax_code_seq[BR_RANGE_S16K] =
       {
-        {0, 20, 0x1F, FALSE},
-        {0, 15, 0x1F, FALSE},
-        {0, 0, 0, FALSE}
-      }, /* BR_RANGE_S64K */
+       INSN_BNE        /* bne $rt, $ra, label */
+      },
+    .relax_code_condition[BR_RANGE_S16K] =
       {
-        {0, 20, 0x1F, FALSE},
-        {0, 15, 0x1F, FALSE},
-        {0, 0, 0, FALSE}
-      }, /* BR_RANGE_S16M */
+       {0, 20, 0x1F, FALSE},
+       {0, 15, 0x1F, FALSE},
+       {0, 0, 0, FALSE}
+      },
+    .relax_code_size[BR_RANGE_S16K] = 4,
+    .relax_branch_isize[BR_RANGE_S16K] = 4,
+    .relax_fixup[BR_RANGE_S16K] =
       {
-        {0, 20, 0x1F, FALSE},
-        {0, 15, 0x1F, FALSE},
-        {0, 0, 0, FALSE}
-      } /* BR_RANGE_U4G */
-    },                                         /* relax_code_condition */
-    {4, 4, 8, 8, 16},                          /* relax_code_size */
-    {4, 4, 4, 4, 4},                           /* relax_branch_isize */
-    {
+       {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
+       {0, 0, 0, 0}
+      },
+
+    .relax_code_seq[BR_RANGE_S64K] =
       {
-        {0, 4, 0, BFD_RELOC_NDS32_15_PCREL},
-        {0, 4, NDS32_INSN16, BFD_RELOC_NDS32_INSN16},
-        {0, 0, 0, 0}
-      }, /* BR_RANGE_S256 */
+       INSN_BEQ,       /* beq $rt, $ra, $1 */
+       INSN_J          /* j label */
+      },
+    .relax_code_condition[BR_RANGE_S64K] =
       {
-        {0, 4, 0, BFD_RELOC_NDS32_15_PCREL},
-        {0, 0, 0, 0}
-      }, /* BR_RANGE_S16K */
+       {0, 20, 0x1F, FALSE},
+       {0, 15, 0x1F, FALSE},
+       {0, 0, 0, FALSE}
+      },
+    .relax_code_size[BR_RANGE_S64K] = 8,
+    .relax_branch_isize[BR_RANGE_S64K] = 4,
+    .relax_fixup[BR_RANGE_S64K] =
       {
-       {0, 4, NDS32_CREATE_LABEL, BFD_RELOC_NDS32_15_PCREL},
+       {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
        {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
        {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5},
-       {4, 4, 0, BFD_RELOC_NDS32_25_PCREL},
+       {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
        {4, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
-        {0, 0, 0, 0}
-      }, /* BR_RANGE_S64K */
+       {0, 0, 0, 0}
+      },
+
+    .relax_code_seq[BR_RANGE_S16M] =
       {
-       {0, 4, NDS32_CREATE_LABEL, BFD_RELOC_NDS32_15_PCREL},
+       INSN_BEQ,       /* beq $rt, $ra, $1 */
+       INSN_J          /* j label */
+      },
+    .relax_code_condition[BR_RANGE_S16M] =
+      {
+       {0, 20, 0x1F, FALSE},
+       {0, 15, 0x1F, FALSE},
+       {0, 0, 0, FALSE}
+      },
+    .relax_code_size[BR_RANGE_S16M] = 8,
+    .relax_branch_isize[BR_RANGE_S16M] = 4,
+    .relax_fixup[BR_RANGE_S16M] =
+      {
+       {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
        {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
        {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5},
-       {4, 4, 0, BFD_RELOC_NDS32_25_PCREL},
+       {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
        {4, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
-        {0, 0, 0, 0}
-      }, /* BR_RANGE_S16M */
-      {
-        {0, 4, NDS32_CREATE_LABEL, BFD_RELOC_NDS32_15_PCREL},
+       {0, 0, 0, 0}
+      },
+
+    .relax_code_seq[BR_RANGE_U4G] =
+      {
+       INSN_BEQ,       /* beq $rt, $ra, $1 */
+       INSN_SETHI_TA,  /* sethi $ta, label */
+       INSN_ORI_TA,    /* ori $ta, $ta, label */
+       INSN_JR_TA      /* jr $ta */
+      },
+    .relax_code_condition[BR_RANGE_U4G] =
+      {
+       {0, 20, 0x1F, FALSE},
+       {0, 15, 0x1F, FALSE},
+       {0, 0, 0, FALSE}
+      },
+    .relax_code_size[BR_RANGE_U4G] = 16,
+    .relax_branch_isize[BR_RANGE_U4G] = 4,
+    .relax_fixup[BR_RANGE_U4G] =
+      {
+       {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
        {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
        {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP6},
        {4, 4, 0, BFD_RELOC_NDS32_HI20},
@@ -1175,84 +1450,106 @@ static relax_info_t relax_table[] =
        {12, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY},
        {12, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
        {0, 0, 0, 0}
-      } /* BR_RANGE_U4G */
-    }                                          /* relax_fixup */
+      },
   },
   {
-    "beqz38",                                  /* opcode */
-    BR_RANGE_S256,                             /* br_range */
-    {
-      {0, 8, 0x7, FALSE},
-      {0, 0, 0, FALSE}
-    },                                         /* cond_field */
-    {
-      {
-        INSN_BEQZ38 << 16 /* beqz $rt, label */
-      }, /* BR_RANGE_S256 */
-      {
-        INSN_BEQZ /* beqz $rt, label */
-      }, /* BR_RANGE_S16K */
-      {
-        INSN_BEQZ /* beqz $rt, label */
-      }, /* BR_RANGE_S64K */
-      {
-        INSN_BNEZ, /* bnez $rt, $1 */
-        INSN_J /* j label */
-      }, /* BR_RANGE_S16M */
-      {
-        INSN_BNEZ, /* bnez $rt, $1 */
-        INSN_SETHI_TA, /* sethi $ta, label */
-        INSN_ORI_TA, /* ori $ta, $ta, label */
-        INSN_JR_TA /* jr $ta */
-      } /* BR_RANGE_U4G */
-    },                                         /* relax_code_seq */
-    {
+    .opcode = "beqz38",
+    .br_range = BR_RANGE_S256,
+    .cond_field =
+      {
+       {0, 8, 0x7, FALSE},
+       {0, 0, 0, FALSE}
+      },
+    .relax_code_seq[BR_RANGE_S256] =
+      {
+       INSN_BEQZ38 << 16       /* beqz $rt, label */
+      },
+    .relax_code_condition[BR_RANGE_S256] =
+      {
+       {0, 8, 0x7, FALSE},
+       {0, 0, 0, FALSE}
+      },
+    .relax_code_size[BR_RANGE_S256] = 2,
+    .relax_branch_isize[BR_RANGE_S256] = 2,
+    .relax_fixup[BR_RANGE_S256] =
+      {
+       {0, 2, NDS32_PCREL, BFD_RELOC_NDS32_9_PCREL},
+       {0, 0, 0, 0}
+      },
+
+    .relax_code_seq[BR_RANGE_S16K] =
       {
-        {0, 8, 0x7, FALSE},
-        {0, 0, 0, FALSE}
-      }, /* BR_RANGE_S256 */
+       INSN_BEQZ       /* beqz $rt, label */
+      },
+    .relax_code_condition[BR_RANGE_S16K] =
       {
-        {0, 20, 0x1F, FALSE},
-        {0, 0, 0, FALSE}
-      }, /* BR_RANGE_S16K */
+       {0, 20, 0x1F, FALSE},
+       {0, 0, 0, FALSE}
+      },
+    .relax_code_size[BR_RANGE_S16K] = 4,
+    .relax_branch_isize[BR_RANGE_S16K] = 4,
+    .relax_fixup[BR_RANGE_S16K] =
       {
-        {0, 20, 0x1F, FALSE},
-        {0, 0, 0, FALSE}
-      }, /* BR_RANGE_S64K */
+       {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
+       {0, 0, 0, 0}
+      },
+
+    .relax_code_seq[BR_RANGE_S64K] =
       {
-        {0, 20, 0x1F, FALSE},
-        {0, 0, 0, FALSE}
-      }, /* BR_RANGE_S16M */
+       INSN_BEQZ       /* beqz $rt, label */
+      },
+    .relax_code_condition[BR_RANGE_S64K] =
       {
-        {0, 20, 0x1F, FALSE},
-        {0, 0, 0, FALSE}
-      } /* BR_RANGE_U4G */
-    },                                         /* relax_code_condition */
-    {2, 4, 4, 8, 16},                          /* relax_code_size */
-    {2, 4, 4, 4, 4},                           /* relax_branch_isize */
-    {
+       {0, 20, 0x1F, FALSE},
+       {0, 0, 0, FALSE}
+      },
+    .relax_code_size[BR_RANGE_S64K] = 4,
+    .relax_branch_isize[BR_RANGE_S64K] = 4,
+    .relax_fixup[BR_RANGE_S64K] =
       {
-       {0, 2, 0, BFD_RELOC_NDS32_9_PCREL},
-        {0, 0, 0, 0}
-      }, /* BR_RANGE_S256 */
+       {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
+       {0, 0, 0, 0}
+      },
+
+    .relax_code_seq[BR_RANGE_S16M] =
       {
-        {0, 4, 0, BFD_RELOC_NDS32_17_PCREL},
-        {0, 0, 0, 0}
-      }, /* BR_RANGE_S16K */
+       INSN_BNEZ,      /* bnez $rt, $1 */
+       INSN_J          /* j label */
+      },
+    .relax_code_condition[BR_RANGE_S16M] =
       {
-        {0, 4, 0, BFD_RELOC_NDS32_17_PCREL},
-        {0, 0, 0, 0}
-      }, /* BR_RANGE_S64K */
+       {0, 20, 0x1F, FALSE},
+       {0, 0, 0, FALSE}
+      },
+    .relax_code_size[BR_RANGE_S16M] = 8,
+    .relax_branch_isize[BR_RANGE_S16M] = 4,
+    .relax_fixup[BR_RANGE_S16M] =
       {
-       {0, 4, NDS32_CREATE_LABEL, BFD_RELOC_NDS32_15_PCREL},
+       {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
        {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
        {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5},
-       {4, 4, 0, BFD_RELOC_NDS32_25_PCREL},
+       {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
        {4, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
-        {0, 0, 0, 0}
-      }, /* BR_RANGE_S16M */
+       {0, 0, 0, 0}
+      },
+
+    .relax_code_seq[BR_RANGE_U4G] =
+      {
+       INSN_BNEZ,      /* bnez $rt, $1 */
+       INSN_SETHI_TA,  /* sethi $ta, label */
+       INSN_ORI_TA,    /* ori $ta, $ta, label */
+       INSN_JR_TA      /* jr $ta */
+      },
+    .relax_code_condition[BR_RANGE_U4G] =
       {
-        {0, 4, NDS32_CREATE_LABEL, BFD_RELOC_NDS32_15_PCREL},
+       {0, 20, 0x1F, FALSE},
+       {0, 0, 0, FALSE}
+      },
+    .relax_code_size[BR_RANGE_U4G] = 16,
+    .relax_branch_isize[BR_RANGE_U4G] = 4,
+    .relax_fixup[BR_RANGE_U4G] =
+      {
+       {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
        {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
        {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP6},
        {4, 4, 0, BFD_RELOC_NDS32_HI20},
@@ -1263,84 +1560,106 @@ static relax_info_t relax_table[] =
        {12, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY},
        {12, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
        {0, 0, 0, 0}
-      } /* BR_RANGE_U4G */
-    }                                          /* relax_fixup */
+      },
   },
   {
-    "bnez38",                                  /* opcode */
-    BR_RANGE_S256,                             /* br_range */
-    {
-      {0, 8, 0x7, FALSE},
-      {0, 0, 0, FALSE}
-    },                                                 /* cond_field */
-    {
-      {
-        INSN_BNEZ38 << 16 /* bnez $rt, label */
-      }, /* BR_RANGE_S256 */
-      {
-        INSN_BNEZ /* bnez $rt, label */
-      }, /* BR_RANGE_S16K */
-      {
-        INSN_BNEZ /* bnez $rt, label */
-      }, /* BR_RANGE_S64K */
-      {
-        INSN_BEQZ, /* beqz $rt, $1 */
-        INSN_J /* j label */
-      }, /* BR_RANGE_S16M */
-      {
-        INSN_BEQZ, /* beqz $rt, $1 */
-        INSN_SETHI_TA, /* sethi $ta, label */
-        INSN_ORI_TA, /* ori $ta, $ta, label */
-        INSN_JR_TA /* jr $ta */
-      } /* BR_RANGE_U4G */
-    },                                         /* relax_code_seq */
-    {
+    .opcode = "bnez38",
+    .br_range = BR_RANGE_S256,
+    .cond_field =
+      {
+       {0, 8, 0x7, FALSE},
+       {0, 0, 0, FALSE}
+      },
+    .relax_code_seq[BR_RANGE_S256] =
+      {
+       INSN_BNEZ38 << 16       /* bnez $rt, label */
+      },
+    .relax_code_condition[BR_RANGE_S256] =
+      {
+       {0, 8, 0x7, FALSE},
+       {0, 0, 0, FALSE}
+      },
+    .relax_code_size[BR_RANGE_S256] = 2,
+    .relax_branch_isize[BR_RANGE_S256] = 2,
+    .relax_fixup[BR_RANGE_S256] =
+      {
+       {0, 2, NDS32_PCREL, BFD_RELOC_NDS32_9_PCREL},
+       {0, 0, 0, 0}
+      },
+
+    .relax_code_seq[BR_RANGE_S16K] =
       {
-        {0, 8, 0x7, FALSE},
-        {0, 0, 0, FALSE}
-      }, /* BR_RANGE_S256 */
+       INSN_BNEZ       /* bnez $rt, label */
+      },
+    .relax_code_condition[BR_RANGE_S16K] =
       {
-        {0, 20, 0x1F, FALSE},
-        {0, 0, 0, FALSE}
-      }, /* BR_RANGE_S16K */
+       {0, 20, 0x1F, FALSE},
+       {0, 0, 0, FALSE}
+      },
+    .relax_code_size[BR_RANGE_S16K] = 4,
+    .relax_branch_isize[BR_RANGE_S16K] = 4,
+    .relax_fixup[BR_RANGE_S16K] =
       {
-        {0, 20, 0x1F, FALSE},
-        {0, 0, 0, FALSE}
-      }, /* BR_RANGE_S64K */
+       {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
+       {0, 0, 0, 0}
+      },
+
+    .relax_code_seq[BR_RANGE_S64K] =
       {
-        {0, 20, 0x1F, FALSE},
-        {0, 0, 0, FALSE}
-      }, /* BR_RANGE_S16M */
+       INSN_BNEZ       /* bnez $rt, label */
+      },
+    .relax_code_condition[BR_RANGE_S64K] =
       {
-        {0, 20, 0x1F, FALSE},
-        {0, 0, 0, FALSE}
-      } /* BR_RANGE_U4G */
-    },                                         /* relax_code_condition */
-    {2, 4, 4, 8, 16},                          /* relax_code_size */
-    {2, 4, 4, 4, 4},                           /* relax_branch_isize */
-    {
+       {0, 20, 0x1F, FALSE},
+       {0, 0, 0, FALSE}
+      },
+    .relax_code_size[BR_RANGE_S64K] = 4,
+    .relax_branch_isize[BR_RANGE_S64K] = 4,
+    .relax_fixup[BR_RANGE_S64K] =
       {
-       {0, 2, 0, BFD_RELOC_NDS32_9_PCREL},
-        {0, 0, 0, 0}
-      }, /* BR_RANGE_S256 */
+       {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
+       {0, 0, 0, 0}
+      },
+
+    .relax_code_seq[BR_RANGE_S16M] =
       {
-        {0, 4, 0, BFD_RELOC_NDS32_17_PCREL},
-        {0, 0, 0, 0}
-      }, /* BR_RANGE_S16K */
+       INSN_BEQZ,      /* beqz $rt, $1 */
+       INSN_J          /* j label */
+      },
+    .relax_code_condition[BR_RANGE_S16M] =
       {
-        {0, 4, 0, BFD_RELOC_NDS32_17_PCREL},
-        {0, 0, 0, 0}
-      }, /* BR_RANGE_S64K */
+       {0, 20, 0x1F, FALSE},
+       {0, 0, 0, FALSE}
+      },
+    .relax_code_size[BR_RANGE_S16M] = 8,
+    .relax_branch_isize[BR_RANGE_S16M] = 4,
+    .relax_fixup[BR_RANGE_S16M] =
       {
-       {0, 4, NDS32_CREATE_LABEL, BFD_RELOC_NDS32_15_PCREL},
+       {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
        {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
        {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5},
-       {4, 4, 0, BFD_RELOC_NDS32_25_PCREL},
+       {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
        {4, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
-        {0, 0, 0, 0}
-      }, /* BR_RANGE_S16M */
+       {0, 0, 0, 0}
+      },
+
+    .relax_code_seq[BR_RANGE_U4G] =
+      {
+       INSN_BEQZ,      /* beqz $rt, $1 */
+       INSN_SETHI_TA,  /* sethi $ta, label */
+       INSN_ORI_TA,    /* ori $ta, $ta, label */
+       INSN_JR_TA      /* jr $ta */
+      },
+    .relax_code_condition[BR_RANGE_U4G] =
       {
-        {0, 4, NDS32_CREATE_LABEL, BFD_RELOC_NDS32_15_PCREL},
+       {0, 20, 0x1F, FALSE},
+       {0, 0, 0, FALSE}
+      },
+    .relax_code_size[BR_RANGE_U4G] = 16,
+    .relax_branch_isize[BR_RANGE_U4G] = 4,
+    .relax_fixup[BR_RANGE_U4G] =
+      {
+       {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
        {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
        {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP6},
        {4, 4, 0, BFD_RELOC_NDS32_HI20},
@@ -1351,66 +1670,80 @@ static relax_info_t relax_table[] =
        {12, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY},
        {12, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
        {0, 0, 0, 0}
-      } /* BR_RANGE_U4G */
-    }                                          /* relax_fixup */
+      },
   },
   {
-    "beqzs8",                                  /* opcode */
-    BR_RANGE_S256,                             /* br_range */
-    {{0, 0, 0, FALSE}},                        /* cond_field */
-    {
+    .opcode = "beqzs8",
+    .br_range = BR_RANGE_S256,
+    .cond_field =
       {
-        INSN_BEQZS8 << 16 /* beqz $r15, label */
-      }, /* BR_RANGE_S256 */
+       {0, 0, 0, FALSE}
+      },
+    .relax_code_seq[BR_RANGE_S256] =
       {
-        INSN_BEQZ_TA /* bnez $rt, label */
-      }, /* BR_RANGE_S16K */
+       INSN_BEQZS8 << 16       /* beqz $r15, label */
+      },
+    .relax_code_size[BR_RANGE_S256] = 2,
+    .relax_branch_isize[BR_RANGE_S256] = 2,
+    .relax_fixup[BR_RANGE_S256] =
       {
-        INSN_BEQZ_TA /* bnez $rt, label */
-      }, /* BR_RANGE_S64K */
+       {0, 2, NDS32_PCREL, BFD_RELOC_NDS32_9_PCREL},
+       {0, 0, 0, 0}
+      },
+
+    .relax_code_seq[BR_RANGE_S16K] =
       {
-        INSN_BNEZ_TA, /* bnez $r15, $1 */
-        INSN_J /* j label */
-      }, /* BR_RANGE_S16M */
+       INSN_BEQZ_TA    /* beqz $r15, label */
+      },
+    .relax_code_size[BR_RANGE_S16K] = 4,
+    .relax_branch_isize[BR_RANGE_S16K] = 4,
+    .relax_fixup[BR_RANGE_S16K] =
       {
-        INSN_BNEZ_TA, /* bnez $r15, $1 */
-        INSN_SETHI_TA, /* sethi $ta, label */
-        INSN_ORI_TA, /* ori $ta, $ta, label */
-        INSN_JR_TA /* jr $ta */
-      } /* BR_RANGE_U4G */
-    },                                         /* relax_code_seq */
-    {
-      {{0, 0, 0, FALSE}}, /* BR_RANGE_S256 */
-      {{0, 0, 0, FALSE}}, /* BR_RANGE_S16K */
-      {{0, 0, 0, FALSE}}, /* BR_RANGE_S64K */
-      {{0, 0, 0, FALSE}}, /* BR_RANGE_S16M */
-      {{0, 0, 0, FALSE}} /* BR_RANGE_U4G */
-    },                                         /* relax_code_condition */
-    {2, 4, 4, 8, 16},                          /* relax_code_size */
-    {2, 4, 4, 4, 4},                           /* relax_branch_isize */
-    {
+       {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
+       {0, 0, 0, 0}
+      },
+
+    .relax_code_seq[BR_RANGE_S64K] =
       {
-       {0, 2, 0, BFD_RELOC_NDS32_9_PCREL},
-        {0, 0, 0, 0}
-      }, /* BR_RANGE_S256 */
+       INSN_BEQZ_TA    /* beqz $r15, label */
+      },
+    .relax_code_size[BR_RANGE_S64K] = 4,
+    .relax_branch_isize[BR_RANGE_S64K] = 4,
+    .relax_fixup[BR_RANGE_S64K] =
       {
-        {0, 4, 0, BFD_RELOC_NDS32_17_PCREL},
-        {0, 0, 0, 0}
-      }, /* BR_RANGE_S16K */
+       {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
+       {0, 0, 0, 0}
+      },
+
+    .relax_code_seq[BR_RANGE_S16M] =
       {
-        {0, 4, 0, BFD_RELOC_NDS32_17_PCREL},
-        {0, 0, 0, 0}
-      }, /* BR_RANGE_S64K */
+       INSN_BNEZ_TA,   /* bnez $r15, $1 */
+       INSN_J          /* j label */
+      },
+    .relax_code_size[BR_RANGE_S16M] = 8,
+    .relax_branch_isize[BR_RANGE_S16M] = 4,
+    .relax_fixup[BR_RANGE_S16M] =
       {
-       {0, 4, NDS32_CREATE_LABEL, BFD_RELOC_NDS32_15_PCREL},
+       {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
        {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
        {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5},
-       {4, 4, 0, BFD_RELOC_NDS32_25_PCREL},
+       {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
        {4, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
-        {0, 0, 0, 0}
-      }, /* BR_RANGE_S16M */
+       {0, 0, 0, 0}
+      },
+
+    .relax_code_seq[BR_RANGE_U4G] =
+      {
+       INSN_BNEZ_TA,   /* bnez $r15, $1 */
+       INSN_SETHI_TA,  /* sethi $ta, label */
+       INSN_ORI_TA,    /* ori $ta, $ta, label */
+       INSN_JR_TA      /* jr $ta */
+      },
+    .relax_code_size[BR_RANGE_U4G] = 16,
+    .relax_branch_isize[BR_RANGE_U4G] = 4,
+    .relax_fixup[BR_RANGE_U4G] =
       {
-        {0, 4, NDS32_CREATE_LABEL, BFD_RELOC_NDS32_15_PCREL},
+       {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
        {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
        {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP6},
        {4, 4, 0, BFD_RELOC_NDS32_HI20},
@@ -1420,67 +1753,81 @@ static relax_info_t relax_table[] =
        {12, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED},
        {12, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY},
        {12, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
-        {0, 0, 0, 0}
-      } /* BR_RANGE_U4G */
-    }                                          /* relax_fixup */
+       {0, 0, 0, 0}
+      },
   },
   {
-    "bnezs8",                                  /* opcode */
-    BR_RANGE_S256,                             /* br_range */
-    {{0, 0, 0, FALSE}},                        /* cond_field */
-    {
+    .opcode = "bnezs8",
+    .br_range = BR_RANGE_S256,
+    .cond_field =
       {
-        INSN_BNEZS8 << 16 /* bnez $r15, label */
-      }, /* BR_RANGE_S256 */
+       {0, 0, 0, FALSE}
+      },
+    .relax_code_seq[BR_RANGE_S256] =
       {
-        INSN_BNEZ_TA /* bnez $r15, label */
-      }, /* BR_RANGE_S16K */
+       INSN_BNEZS8 << 16       /* bnez $r15, label */
+      },
+    .relax_code_size[BR_RANGE_S256] = 2,
+    .relax_branch_isize[BR_RANGE_S256] = 2,
+    .relax_fixup[BR_RANGE_S256] =
       {
-        INSN_BNEZ_TA /* bnez $r15, label */
-      }, /* BR_RANGE_S64K */
+       {0, 2, NDS32_PCREL, BFD_RELOC_NDS32_9_PCREL},
+       {0, 0, 0, 0}
+      },
+
+    .relax_code_seq[BR_RANGE_S16K] =
       {
-        INSN_BEQZ_TA, /* beqz $r15, $1 */
-        INSN_J /* j label */
-      }, /* BR_RANGE_S16M */
+       INSN_BNEZ_TA    /* bnez $r15, label */
+      },
+    .relax_code_size[BR_RANGE_S16K] = 4,
+    .relax_branch_isize[BR_RANGE_S16K] = 4,
+    .relax_fixup[BR_RANGE_S16K] =
       {
-        INSN_BEQZ_TA, /* beqz $r15, $1 */
-        INSN_SETHI_TA, /* sethi $ta, label */
-        INSN_ORI_TA, /* ori $ta, $ta, label */
-        INSN_JR_TA /* jr $ta */
-      } /* BR_RANGE_U4G */
-    },                                         /* relax_code_seq */
-    {
-      {{0, 0, 0, FALSE}}, /* BR_RANGE_S256 */
-      {{0, 0, 0, FALSE}}, /* BR_RANGE_S16K */
-      {{0, 0, 0, FALSE}}, /* BR_RANGE_S64K */
-      {{0, 0, 0, FALSE}}, /* BR_RANGE_S16M */
-      {{0, 0, 0, FALSE}} /* BR_RANGE_U4G */
-    },                                         /* relax_code_condition */
-    {2, 4, 4, 8, 16},                          /* relax_code_size */
-    {2, 4, 4, 4, 4},                           /* relax_branch_isize */
-    {
+       {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
+       {0, 0, 0, 0}
+      },
+
+    .relax_code_seq[BR_RANGE_S64K] =
       {
-       {0, 2, 0, BFD_RELOC_NDS32_9_PCREL},
-        {0, 0, 0, 0}
-      }, /* BR_RANGE_S256 */
+       INSN_BNEZ_TA    /* bnez $r15, label */
+      },
+    .relax_code_size[BR_RANGE_S64K] = 4,
+    .relax_branch_isize[BR_RANGE_S64K] = 4,
+    .relax_fixup[BR_RANGE_S64K] =
       {
-        {0, 4, 0, BFD_RELOC_NDS32_17_PCREL},
-        {0, 0, 0, 0}
-      }, /* BR_RANGE_S16K */
+       {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
+       {0, 0, 0, 0}
+      },
+
+    .relax_code_seq[BR_RANGE_S16M] =
       {
-        {0, 4, 0, BFD_RELOC_NDS32_17_PCREL},
-        {0, 0, 0, 0}
-      }, /* BR_RANGE_S64K */
+       INSN_BEQZ_TA,   /* beqz $r15, $1 */
+       INSN_J          /* j label */
+      },
+    .relax_code_size[BR_RANGE_S16M] = 8,
+    .relax_branch_isize[BR_RANGE_S16M] = 4,
+    .relax_fixup[BR_RANGE_S16M] =
       {
-       {0, 4, NDS32_CREATE_LABEL, BFD_RELOC_NDS32_15_PCREL},
+       {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
        {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
        {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5},
-       {4, 4, 0, BFD_RELOC_NDS32_25_PCREL},
+       {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
        {4, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
-        {0, 0, 0, 0}
-      }, /* BR_RANGE_S16M */
+       {0, 0, 0, 0}
+      },
+
+    .relax_code_seq[BR_RANGE_U4G] =
       {
-        {0, 4, NDS32_CREATE_LABEL, BFD_RELOC_NDS32_15_PCREL},
+       INSN_BEQZ_TA,   /* beqz $r15, $1 */
+       INSN_SETHI_TA,  /* sethi $ta, label */
+       INSN_ORI_TA,    /* ori $ta, $ta, label */
+       INSN_JR_TA      /* jr $ta */
+      },
+    .relax_code_size[BR_RANGE_U4G] = 16,
+    .relax_branch_isize[BR_RANGE_U4G] = 4,
+    .relax_fixup[BR_RANGE_U4G] =
+      {
+       {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
        {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
        {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP6},
        {4, 4, 0, BFD_RELOC_NDS32_HI20},
@@ -1491,89 +1838,111 @@ static relax_info_t relax_table[] =
        {12, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY},
        {12, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
        {0, 0, 0, 0}
-      } /* BR_RANGE_U4G */
-    }                                          /* relax_fixup */
+      },
   },
   {
-    "bnes38",                                  /* opcode */
-    BR_RANGE_S256,                             /* br_range */
-    {
-      {0, 8, 0x7, FALSE},
-      {0, 0, 0, FALSE}
-    },                                                 /* cond_field */
-    {
-      {
-        INSN_BNES38 << 16 /* bne $rt, $R5, label */
-      }, /* BR_RANGE_S256 */
-      {
-        INSN_BNE_R5 /* bne $rt, $R5, label */
-      }, /* BR_RANGE_S16K */
-      {
-        INSN_BEQ_R5, /* beq $rt, $R5, $1 */
-        INSN_J /* j label */
-      }, /* BR_RANGE_S64K */
-      {
-        INSN_BEQ_R5, /* beq $rt, $R5, $1 */
-        INSN_J /* j label */
-      }, /* BR_RANGE_S16M */
-      {
-        INSN_BEQ_R5, /* beq $rt, $R5, $1 */
-        INSN_SETHI_TA, /* sethi $ta, label */
-        INSN_ORI_TA, /* ori $ta, $ta, label */
-        INSN_JR_TA /* jr $ta */
-      } /* BR_RANGE_U4G */
-    },                                         /* relax_code_seq */
-    {
-      {
-        {0, 8, 0x7, FALSE},
-        {0, 0, 0, FALSE}
-      }, /* BR_RANGE_S256 */
-      {
-        {0, 20, 0x1F, FALSE},
-        {0, 0, 0, FALSE}
-      }, /* BR_RANGE_S16K */
+    .opcode = "bnes38",
+    .br_range = BR_RANGE_S256,
+    .cond_field =
+      {
+       {0, 8, 0x7, FALSE},
+       {0, 0, 0, FALSE}
+      },
+    .relax_code_seq[BR_RANGE_S256] =
+      {
+       INSN_BNES38 << 16       /* bne $rt, $r5, label */
+      },
+    .relax_code_condition[BR_RANGE_S256] =
+      {
+       {0, 8, 0x7, FALSE},
+       {0, 0, 0, FALSE}
+      },
+    .relax_code_size[BR_RANGE_S256] = 2,
+    .relax_branch_isize[BR_RANGE_S256] = 2,
+    .relax_fixup[BR_RANGE_S256] =
+      {
+       {0, 2, NDS32_PCREL, BFD_RELOC_NDS32_9_PCREL},
+       {0, 0, 0, 0}
+      },
+
+    .relax_code_seq[BR_RANGE_S16K] =
       {
-        {0, 20, 0x1F, FALSE},
-        {0, 0, 0, FALSE}
-      }, /* BR_RANGE_S64K */
+       INSN_BNE_R5     /* bne $rt, $r5, label */
+      },
+    .relax_code_condition[BR_RANGE_S16K] =
       {
-        {0, 20, 0x1F, FALSE},
-        {0, 0, 0, FALSE}
-      }, /* BR_RANGE_S16M */
+       {0, 20, 0x1F, FALSE},
+       {0, 0, 0, FALSE}
+      },
+    .relax_code_size[BR_RANGE_S16K] = 4,
+    .relax_branch_isize[BR_RANGE_S16K] = 4,
+    .relax_fixup[BR_RANGE_S16K] =
       {
-        {0, 20, 0x1F, FALSE},
-        {0, 0, 0, FALSE}
-      } /* BR_RANGE_U4G */
-    },                                         /* relax_code_condition */
-    {2, 4, 8, 8, 16},                          /* relax_code_size */
-    {2, 4, 4, 4, 4},                           /* relax_branch_isize */
-    {
+       {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
+       {0, 0, 0, 0}
+      },
+
+    .relax_code_seq[BR_RANGE_S64K] =
       {
-       {0, 2, 0, BFD_RELOC_NDS32_9_PCREL},
-        {0, 0, 0, 0}
-      }, /* BR_RANGE_S256 */
+       INSN_BEQ_R5,    /* beq $rt, $r5, $1 */
+       INSN_J          /* j label */
+      },
+    .relax_code_condition[BR_RANGE_S64K] =
       {
-        {0, 4, 0, BFD_RELOC_NDS32_15_PCREL},
-        {0, 0, 0, 0}
-      }, /* BR_RANGE_S16K */
+       {0, 20, 0x1F, FALSE},
+       {0, 0, 0, FALSE}
+      },
+    .relax_code_size[BR_RANGE_S64K] = 8,
+    .relax_branch_isize[BR_RANGE_S64K] = 4,
+    .relax_fixup[BR_RANGE_S64K] =
       {
-       {0, 4, NDS32_CREATE_LABEL, BFD_RELOC_NDS32_15_PCREL},
+       {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
        {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
        {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5},
-       {4, 4, 0, BFD_RELOC_NDS32_25_PCREL},
+       {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
        {4, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
-        {0, 0, 0, 0}
-      }, /* BR_RANGE_S64K */
+       {0, 0, 0, 0}
+      },
+
+    .relax_code_seq[BR_RANGE_S16M] =
+      {
+       INSN_BEQ_R5,    /* beq $rt, $r5, $1 */
+       INSN_J          /* j label */
+      },
+    .relax_code_condition[BR_RANGE_S16M] =
       {
-       {0, 4, NDS32_CREATE_LABEL, BFD_RELOC_NDS32_15_PCREL},
+       {0, 20, 0x1F, FALSE},
+       {0, 0, 0, FALSE}
+      },
+    .relax_code_size[BR_RANGE_S16M] = 8,
+    .relax_branch_isize[BR_RANGE_S16M] = 4,
+    .relax_fixup[BR_RANGE_S16M] =
+      {
+       {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
        {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
        {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5},
-       {4, 4, 0, BFD_RELOC_NDS32_25_PCREL},
+       {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
        {4, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
-        {0, 0, 0, 0}
-      }, /* BR_RANGE_S16M */
+       {0, 0, 0, 0}
+      },
+
+    .relax_code_seq[BR_RANGE_U4G] =
       {
-        {0, 4, NDS32_CREATE_LABEL, BFD_RELOC_NDS32_15_PCREL},
+       INSN_BEQ_R5,    /* beq $rt, $r5, $1 */
+       INSN_SETHI_TA,  /* sethi $ta, label */
+       INSN_ORI_TA,    /* ori $ta, $ta, label */
+       INSN_JR_TA      /* jr $ta */
+      },
+    .relax_code_condition[BR_RANGE_U4G] =
+      {
+       {0, 20, 0x1F, FALSE},
+       {0, 0, 0, FALSE}
+      },
+    .relax_code_size[BR_RANGE_U4G] = 16,
+    .relax_branch_isize[BR_RANGE_U4G] = 4,
+    .relax_fixup[BR_RANGE_U4G] =
+      {
+       {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
        {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
        {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP6},
        {4, 4, 0, BFD_RELOC_NDS32_HI20},
@@ -1584,89 +1953,111 @@ static relax_info_t relax_table[] =
        {12, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY},
        {12, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
        {0, 0, 0, 0}
-      } /* BR_RANGE_U4G */
-    }                                          /* relax_fixup */
+      },
   },
   {
-    "beqs38",                                  /* opcode */
-    BR_RANGE_S256,                             /* br_range */
-    {
-      {0, 8, 0x7, FALSE},
-      {0, 0, 0, FALSE}
-    },                                                 /* cond_field */
-    {
-      {
-        INSN_BEQS38 << 16 /* beq $rt, $R5, label */
-      }, /* BR_RANGE_S256 */
-      {
-        INSN_BEQ_R5 /* beq $rt, $R5, label */
-      }, /* BR_RANGE_S16K */
-      {
-        INSN_BNE_R5, /* bne $rt, $R5, $1 */
-        INSN_J /* j label */
-      }, /* BR_RANGE_S64K */
-      {
-        INSN_BNE_R5, /* bne $rt, $R5, $1 */
-        INSN_J /* j label */
-      }, /* BR_RANGE_S16M */
-      {
-        INSN_BNE_R5, /* bne $rt, $R5, $1 */
-        INSN_SETHI_TA, /* sethi $ta, label */
-        INSN_ORI_TA, /* ori $ta, $ta, label */
-        INSN_JR_TA /* jr $ta */
-      } /* BR_RANGE_U4G */
-    },                                         /* relax_code_seq */
-    {
-      {
-        {0, 8, 0x7, FALSE},
-        {0, 0, 0, FALSE}
-      }, /* BR_RANGE_S256 */
-      {
-        {0, 20, 0x1F, FALSE},
-        {0, 0, 0, FALSE}
-      }, /* BR_RANGE_S16K */
+    .opcode = "beqs38",
+    .br_range = BR_RANGE_S256,
+    .cond_field =
+      {
+       {0, 8, 0x7, FALSE},
+       {0, 0, 0, FALSE}
+      },
+    .relax_code_seq[BR_RANGE_S256] =
+      {
+       INSN_BEQS38 << 16       /* beq $rt, $r5, label */
+      },
+    .relax_code_condition[BR_RANGE_S256] =
+      {
+       {0, 8, 0x7, FALSE},
+       {0, 0, 0, FALSE}
+      },
+    .relax_code_size[BR_RANGE_S256] = 2,
+    .relax_branch_isize[BR_RANGE_S256] = 2,
+    .relax_fixup[BR_RANGE_S256] =
+      {
+       {0, 2, NDS32_PCREL, BFD_RELOC_NDS32_9_PCREL},
+       {0, 0, 0, 0}
+      },
+
+    .relax_code_seq[BR_RANGE_S16K] =
       {
-        {0, 20, 0x1F, FALSE},
-        {0, 0, 0, FALSE}
-      }, /* BR_RANGE_S64K */
+       INSN_BEQ_R5     /* beq $rt, $r5, label */
+      },
+    .relax_code_condition[BR_RANGE_S16K] =
       {
-        {0, 20, 0x1F, FALSE},
-        {0, 0, 0, FALSE}
-      }, /* BR_RANGE_S16M */
+       {0, 20, 0x1F, FALSE},
+       {0, 0, 0, FALSE}
+      },
+    .relax_code_size[BR_RANGE_S16K] = 4,
+    .relax_branch_isize[BR_RANGE_S16K] = 4,
+    .relax_fixup[BR_RANGE_S16K] =
       {
-        {0, 20, 0x1F, FALSE},
-        {0, 0, 0, FALSE}
-      } /* BR_RANGE_U4G */
-    },                                         /* relax_code_condition */
-    {2, 4, 8, 8, 16},                          /* relax_code_size */
-    {2, 4, 4, 4, 4},                           /* relax_branch_isize */
-    {
+       {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
+       {0, 0, 0, 0}
+      },
+
+    .relax_code_seq[BR_RANGE_S64K] =
       {
-       {0, 2, 0, BFD_RELOC_NDS32_9_PCREL},
-        {0, 0, 0, 0}
-      }, /* BR_RANGE_S256 */
+       INSN_BNE_R5,    /* bne $rt, $r5, $1 */
+       INSN_J          /* j label */
+      },
+    .relax_code_condition[BR_RANGE_S64K] =
       {
-        {0, 4, 0, BFD_RELOC_NDS32_15_PCREL},
-        {0, 0, 0, 0}
-      }, /* BR_RANGE_S16K */
+       {0, 20, 0x1F, FALSE},
+       {0, 0, 0, FALSE}
+      },
+    .relax_code_size[BR_RANGE_S64K] = 8,
+    .relax_branch_isize[BR_RANGE_S64K] = 4,
+    .relax_fixup[BR_RANGE_S64K] =
       {
-       {0, 4, NDS32_CREATE_LABEL, BFD_RELOC_NDS32_15_PCREL},
+       {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
        {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
        {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5},
-       {4, 4, 0, BFD_RELOC_NDS32_25_PCREL},
+       {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
        {4, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
-        {0, 0, 0, 0}
-      }, /* BR_RANGE_S64K */
+       {0, 0, 0, 0}
+      },
+
+    .relax_code_seq[BR_RANGE_S16M] =
       {
-       {0, 4, NDS32_CREATE_LABEL, BFD_RELOC_NDS32_15_PCREL},
+       INSN_BNE_R5,    /* bne $rt, $r5, $1 */
+       INSN_J          /* j label */
+      },
+    .relax_code_condition[BR_RANGE_S16M] =
+      {
+       {0, 20, 0x1F, FALSE},
+       {0, 0, 0, FALSE}
+      },
+    .relax_code_size[BR_RANGE_S16M] = 8,
+    .relax_branch_isize[BR_RANGE_S16M] = 4,
+    .relax_fixup[BR_RANGE_S16M] =
+      {
+       {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
        {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
        {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5},
-       {4, 4, 0, BFD_RELOC_NDS32_25_PCREL},
+       {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
        {4, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
-        {0, 0, 0, 0}
-      }, /* BR_RANGE_S16M */
+       {0, 0, 0, 0}
+      },
+
+    .relax_code_seq[BR_RANGE_U4G] =
+      {
+       INSN_BNE_R5,    /* bne $rt, $r5, $1 */
+       INSN_SETHI_TA,  /* sethi $ta, label */
+       INSN_ORI_TA,    /* ori $ta, $ta, label */
+       INSN_JR_TA      /* jr $ta */
+      },
+    .relax_code_condition[BR_RANGE_U4G] =
+      {
+       {0, 20, 0x1F, FALSE},
+       {0, 0, 0, FALSE}
+      },
+    .relax_code_size[BR_RANGE_U4G] = 16,
+    .relax_branch_isize[BR_RANGE_U4G] = 4,
+    .relax_fixup[BR_RANGE_U4G] =
       {
-        {0, 4, NDS32_CREATE_LABEL, BFD_RELOC_NDS32_15_PCREL},
+       {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
        {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
        {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP6},
        {4, 4, 0, BFD_RELOC_NDS32_HI20},
@@ -1677,201 +2068,238 @@ static relax_info_t relax_table[] =
        {12, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY},
        {12, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
        {0, 0, 0, 0}
-      } /* BR_RANGE_U4G */
-    }                                          /* relax_fixup */
+      },
   },
   {
-    "beqc",                                    /* opcode */
-    BR_RANGE_S256,                             /* br_range */
-    {
-      {0, 8, 0x7FF, TRUE},
-      {0, 20, 0x1F, FALSE},
-      {0, 0, 0, FALSE}
-    },                                                 /* cond_field */
-    {
-      {
-        INSN_BEQC /* beqc $rt, imm11s, label */
-      }, /* BR_RANGE_S256 */
-      {
-        INSN_MOVI_TA, /* movi $ta, imm11s */
-        INSN_BEQ_TA /* beq $rt, $ta, label */
-      }, /* BR_RANGE_S16K */
-      {
-        INSN_BNEC, /* bnec $rt, imm11s, $1 */
-        INSN_J /* j label */
-      }, /* BR_RANGE_S64K */
+    .opcode = "beqc",
+    .br_range = BR_RANGE_S256,
+    .cond_field =
+      {
+       {0, 8, 0x7FF, TRUE},
+       {0, 20, 0x1F, FALSE},
+       {0, 0, 0, FALSE}
+      },
+    .relax_code_seq[BR_RANGE_S256] =
+      {
+       INSN_BEQC       /* beqc $rt, imm11s, label */
+      },
+    .relax_code_condition[BR_RANGE_S256] =
+      {
+       {0, 8, 0x7FF, FALSE},
+       {0, 20, 0x1F, FALSE},
+       {0, 0, 0, FALSE}
+      },
+    .relax_code_size[BR_RANGE_S256] = 4,
+    .relax_branch_isize[BR_RANGE_S256] = 4,
+    .relax_fixup[BR_RANGE_S256] =
+      {
+       {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_WORD_9_PCREL},
+       {0, 0, 0, 0}
+      },
+
+    .relax_code_seq[BR_RANGE_S16K] =
       {
-        INSN_BNEC, /* bnec $rt, imm11s, $1 */
-        INSN_J /* j label */
-      }, /* BR_RANGE_S16M */
+       INSN_MOVI_TA,   /* movi $ta, imm11s */
+       INSN_BEQ_TA     /* beq $rt, $ta, label */
+      },
+    .relax_code_condition[BR_RANGE_S16K] =
       {
-        INSN_BNEC, /* bnec $rt, imm11s, $1 */
-        INSN_SETHI_TA, /* sethi $ta, label */
-        INSN_ORI_TA, /* ori $ta, $ta, label */
-        INSN_JR_TA /* jr $ta */
-      } /* BR_RANGE_U4G */
-    },                                         /* relax_code_seq */
-    {
+       {0, 0, 0xFFFFF, FALSE},
+       {4, 20, 0x1F, FALSE},
+       {0, 0, 0, FALSE}
+      },
+    .relax_code_size[BR_RANGE_S16K] = 8,
+    .relax_branch_isize[BR_RANGE_S16K] = 4,
+    .relax_fixup[BR_RANGE_S16K] =
       {
-        {0, 8, 0x7FF, TRUE},
-        {0, 20, 0x1F, FALSE},
-        {0, 0, 0, FALSE}
-      }, /* BR_RANGE_S256 */
+       {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
+       {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP7},
+       {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
+       {0, 0, 0, 0}
+      },
+
+    .relax_code_seq[BR_RANGE_S64K] =
       {
-        {0, 0, 0xFFFFF, FALSE},
-        {4, 20, 0x1F, FALSE},
-        {0, 0, 0, FALSE}
-      }, /* BR_RANGE_S16K */
+       INSN_BNEC,      /* bnec $rt, imm11s, $1 */
+       INSN_J          /* j label */
+      },
+    .relax_code_condition[BR_RANGE_S64K] =
       {
-        {0, 8, 0x7FF, FALSE},
-        {0, 20, 0x1F, FALSE},
-        {0, 0, 0, FALSE}
-      }, /* BR_RANGE_S64K */
+       {0, 8, 0x7FF, FALSE},
+       {0, 20, 0x1F, FALSE},
+       {0, 0, 0, FALSE}
+      },
+    .relax_code_size[BR_RANGE_S64K] = 8,
+    .relax_branch_isize[BR_RANGE_S64K] = 4,
+    .relax_fixup[BR_RANGE_S64K] =
       {
-        {0, 8, 0x7FF, FALSE},
-        {0, 20, 0x1F, FALSE},
-        {0, 0, 0, FALSE}
-      }, /* BR_RANGE_S16M */
+       {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_WORD_9_PCREL},
+       {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
+       {0, 0, 0, 0}
+      },
+
+    .relax_code_seq[BR_RANGE_S16M] =
       {
-        {0, 8, 0x7FF, FALSE},
-        {0, 20, 0x1F, FALSE},
-        {0, 0, 0, FALSE}
-      } /* BR_RANGE_U4G */
-    },                                         /* relax_code_condition */
-    {4, 8, 8, 8, 16},                          /* relax_code_size */
-    {4, 4, 4, 4, 4},                           /* relax_branch_isize */
-    {
+       INSN_BNEC,      /* bnec $rt, imm11s, $1 */
+       INSN_J          /* j label */
+      },
+    .relax_code_condition[BR_RANGE_S16M] =
       {
-        {0, 4, 0, BFD_RELOC_NDS32_WORD_9_PCREL},
-        {0, 0, 0, 0}
-      }, /* BR_RANGE_S256 */
+       {0, 8, 0x7FF, FALSE},
+       {0, 20, 0x1F, FALSE},
+       {0, 0, 0, FALSE}
+      },
+    .relax_code_size[BR_RANGE_S16M] = 8,
+    .relax_branch_isize[BR_RANGE_S16M] = 4,
+    .relax_fixup[BR_RANGE_S16M] =
       {
-       {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
-       {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP7},
-        {4, 4, 0, BFD_RELOC_NDS32_15_PCREL},
-        {0, 0, 0, 0}
-      }, /* BR_RANGE_S16K */
-      {
-        {0, 4, NDS32_CREATE_LABEL, BFD_RELOC_NDS32_WORD_9_PCREL},
-        {4, 4, 0, BFD_RELOC_NDS32_25_PCREL},
-        {0, 0, 0, 0}
-      }, /* BR_RANGE_S64K */
-      {
-        {0, 4, NDS32_CREATE_LABEL, BFD_RELOC_NDS32_WORD_9_PCREL},
-        {4, 4, 0, BFD_RELOC_NDS32_25_PCREL},
-        {0, 0, 0, 0}
-      }, /* BR_RANGE_S16M */
-      {
-        {0, 4, NDS32_CREATE_LABEL, BFD_RELOC_NDS32_WORD_9_PCREL},
-        {4, 4, 0, BFD_RELOC_NDS32_HI20},
+       {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_WORD_9_PCREL},
+       {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
+       {0, 0, 0, 0}
+      },
+
+    .relax_code_seq[BR_RANGE_U4G] =
+      {
+       INSN_BNEC,      /* bnec $rt, imm11s, $1 */
+       INSN_SETHI_TA,  /* sethi $ta, label */
+       INSN_ORI_TA,    /* ori $ta, $ta, label */
+       INSN_JR_TA      /* jr $ta */
+      },
+    .relax_code_condition[BR_RANGE_U4G] =
+      {
+       {0, 8, 0x7FF, FALSE},
+       {0, 20, 0x1F, FALSE},
+       {0, 0, 0, FALSE}
+      },
+    .relax_code_size[BR_RANGE_U4G] = 16,
+    .relax_branch_isize[BR_RANGE_U4G] = 4,
+    .relax_fixup[BR_RANGE_U4G] =
+      {
+       {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_WORD_9_PCREL},
+       {4, 4, 0, BFD_RELOC_NDS32_HI20},
        {8, 4, 0, BFD_RELOC_NDS32_LO12S0_ORI},
        {12, 4, NDS32_INSN16, BFD_RELOC_NDS32_INSN16},
-        {0, 0, 0, 0}
-      } /* BR_RANGE_U4G */
-    }                                          /* relax_fixup */
+       {0, 0, 0, 0}
+      },
   },
   {
-    "bnec",                                    /* opcode */
-    BR_RANGE_S256,                             /* br_range */
-    {
-      {0, 8, 0x7FF, TRUE},
-      {0, 20, 0x1F, FALSE},
-      {0, 0, 0, FALSE}
-    },                                                 /* cond_field */
-    {
-      {
-        INSN_BNEC /* bnec $rt, imm11s, label */
-      }, /* BR_RANGE_S256 */
-      {
-        INSN_MOVI_TA, /* movi $ta, imm11s */
-        INSN_BNE_TA /* bne $rt, $ta, label */
-      }, /* BR_RANGE_S16K */
-      {
-        INSN_BEQC, /* beqc $rt, imm11s, $1 */
-        INSN_J /* j label */
-      }, /* BR_RANGE_S64K */
+    .opcode = "bnec",
+    .br_range = BR_RANGE_S256,
+    .cond_field =
+      {
+       {0, 8, 0x7FF, TRUE},
+       {0, 20, 0x1F, FALSE},
+       {0, 0, 0, FALSE}
+      },
+    .relax_code_seq[BR_RANGE_S256] =
+      {
+         INSN_BNEC     /* bnec $rt, imm11s, label */
+      },
+    .relax_code_condition[BR_RANGE_S256] =
+      {
+       {0, 8, 0x7FF, FALSE},
+       {0, 20, 0x1F, FALSE},
+       {0, 0, 0, FALSE}
+      },
+    .relax_code_size[BR_RANGE_S256] = 4,
+    .relax_branch_isize[BR_RANGE_S256] = 4,
+    .relax_fixup[BR_RANGE_S256] =
+      {
+       {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_WORD_9_PCREL},
+       {0, 0, 0, 0}
+      },
+
+    .relax_code_seq[BR_RANGE_S16K] =
       {
-        INSN_BEQC, /* beqc $rt, imm11s, $1 */
-        INSN_J /* j label */
-      }, /* BR_RANGE_S16M */
+       INSN_MOVI_TA,   /* movi $ta, imm11s */
+       INSN_BNE_TA     /* bne $rt, $ta, label */
+      },
+    .relax_code_condition[BR_RANGE_S16K] =
       {
-        INSN_BEQC, /* beqc $rt, imm11s, $1 */
-        INSN_SETHI_TA, /* sethi $ta, label */
-        INSN_ORI_TA, /* ori $ta, $ta, label */
-        INSN_JR_TA /* jr $ta */
-      } /* BR_RANGE_U4G */
-    },                                         /* relax_code_seq */
-    {
+       {0, 0, 0xFFFFF, FALSE},
+       {4, 20, 0x1F, FALSE},
+       {0, 0, 0, FALSE}
+      },
+    .relax_code_size[BR_RANGE_S16K] = 8,
+    .relax_branch_isize[BR_RANGE_S16K] = 4,
+    .relax_fixup[BR_RANGE_S16K] =
       {
-        {0, 8, 0x7FF, TRUE},
-        {0, 20, 0x1F, FALSE},
-        {0, 0, 0, FALSE}
-      }, /* BR_RANGE_S256 */
+       {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
+       {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP7},
+       {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
+       {0, 0, 0, 0}
+      },
+
+    .relax_code_seq[BR_RANGE_S64K] =
       {
-        {0, 0, 0xFFFFF, FALSE},
-        {4, 20, 0x1F, FALSE},
-        {0, 0, 0, FALSE}
-      }, /* BR_RANGE_S16K */
+       INSN_BEQC,      /* beqc $rt, imm11s, $1 */
+       INSN_J          /* j label */
+      },
+    .relax_code_condition[BR_RANGE_S64K] =
       {
-        {0, 8, 0x7FF, FALSE},
-        {0, 20, 0x1F, FALSE},
-        {0, 0, 0, FALSE}
-      }, /* BR_RANGE_S64K */
+       {0, 8, 0x7FF, FALSE},
+       {0, 20, 0x1F, FALSE},
+       {0, 0, 0, FALSE}
+      },
+    .relax_code_size[BR_RANGE_S64K] = 8,
+    .relax_branch_isize[BR_RANGE_S64K] = 4,
+    .relax_fixup[BR_RANGE_S64K] =
       {
-        {0, 8, 0x7FF, FALSE},
-        {0, 20, 0x1F, FALSE},
-        {0, 0, 0, FALSE}
-      }, /* BR_RANGE_S16M */
+       {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_WORD_9_PCREL},
+       {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
+       {0, 0, 0, 0}
+      },
+
+    .relax_code_seq[BR_RANGE_S16M] =
       {
-        {0, 8, 0x7FF, FALSE},
-        {0, 20, 0x1F, FALSE},
-        {0, 0, 0, FALSE}
-      } /* BR_RANGE_U4G */
-    },                                         /* relax_code_condition */
-    {4, 8, 8, 8, 16},                          /* relax_code_size */
-    {4, 4, 4, 4, 4},                           /* relax_branch_isize */
-    {
+       INSN_BEQC,      /* beqc $rt, imm11s, $1 */
+       INSN_J          /* j label */
+      },
+    .relax_code_condition[BR_RANGE_S16M] =
       {
-        {0, 4, 0, BFD_RELOC_NDS32_WORD_9_PCREL},
-        {0, 0, 0, 0}
-      }, /* BR_RANGE_S256 */
+       {0, 8, 0x7FF, FALSE},
+       {0, 20, 0x1F, FALSE},
+       {0, 0, 0, FALSE}
+      },
+    .relax_code_size[BR_RANGE_S16M] = 8,
+    .relax_branch_isize[BR_RANGE_S16M] = 4,
+    .relax_fixup[BR_RANGE_S16M] =
       {
-       {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
-       {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP7},
-       {4, 4, 0, BFD_RELOC_NDS32_15_PCREL},
-        {0, 0, 0, 0}
-      }, /* BR_RANGE_S16K */
-      {
-        {0, 4, NDS32_CREATE_LABEL, BFD_RELOC_NDS32_WORD_9_PCREL},
-        {4, 4, 0, BFD_RELOC_NDS32_25_PCREL},
-        {0, 0, 0, 0}
-      }, /* BR_RANGE_S64K */
-      {
-        {0, 4, NDS32_CREATE_LABEL, BFD_RELOC_NDS32_WORD_9_PCREL},
-        {4, 4, 0, BFD_RELOC_NDS32_25_PCREL},
-        {0, 0, 0, 0}
-      }, /* BR_RANGE_S16M */
-      {
-        {0, 4, NDS32_CREATE_LABEL, BFD_RELOC_NDS32_WORD_9_PCREL},
-        {4, 4, 0, BFD_RELOC_NDS32_HI20},
-        {8, 4, 0, BFD_RELOC_NDS32_LO12S0_ORI},
+       {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_WORD_9_PCREL},
+       {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
+       {0, 0, 0, 0}
+      },
+
+    .relax_code_seq[BR_RANGE_U4G] =
+      {
+       INSN_BEQC,      /* beqc $rt, imm11s, $1 */
+       INSN_SETHI_TA,  /* sethi $ta, label */
+       INSN_ORI_TA,    /* ori $ta, $ta, label */
+       INSN_JR_TA      /* jr $ta */
+      },
+    .relax_code_condition[BR_RANGE_U4G] =
+      {
+       {0, 8, 0x7FF, FALSE},
+       {0, 20, 0x1F, FALSE},
+       {0, 0, 0, FALSE}
+      },
+    .relax_code_size[BR_RANGE_U4G] = 16,
+    .relax_branch_isize[BR_RANGE_U4G] = 4,
+    .relax_fixup[BR_RANGE_U4G] =
+      {
+       {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_WORD_9_PCREL},
+       {4, 4, 0, BFD_RELOC_NDS32_HI20},
+       {8, 4, 0, BFD_RELOC_NDS32_LO12S0_ORI},
        {12, 4, NDS32_INSN16, BFD_RELOC_NDS32_INSN16},
-        {0, 0, 0, 0}
-      } /* BR_RANGE_U4G */
-    }                                          /* relax_fixup */
+       {0, 0, 0, 0}
+      },
   },
   {
-    NULL,                                      /* opcode */
-    0,                                         /* br_range */
-    {{0, 0, 0, FALSE}},                        /* cond_field */
-    {{0}},                                     /* relax_code_seq */
-    {{{0, 0, 0, FALSE}}},                      /* relax_code_condition */
-    {0},                                       /* relax_code_size */
-    {0},                                       /* relax_branch_isize */
-    {{{0, 0, 0, 0}}},                          /* relax_fixup */
+    .opcode = NULL,
   },
 };
 \f
+
 /* GAS definitions for command-line options.  */
 enum options
 {
@@ -1912,16 +2340,16 @@ size_t md_longopts_size = sizeof (md_longopts);
 struct nds32_parse_option_table
 {
   const char *name;            /* Option string.  */
-  char *help;                  /* Help description.  */
-  int (*func) (char *arg);     /* How to parse it.  */
+  const char *help;                    /* Help description.  */
+  int (*func) (const char *arg);       /* How to parse it.  */
 };
 
 
 /* The value `-1' represents this option has *NOT* been set.  */
 #ifdef NDS32_DEFAULT_ARCH_NAME
-static char* nds32_arch_name = NDS32_DEFAULT_ARCH_NAME;
+static const char* nds32_arch_name = NDS32_DEFAULT_ARCH_NAME;
 #else
-static char* nds32_arch_name = "v3";
+static const char* nds32_arch_name = "v3";
 #endif
 static int nds32_baseline = -1;
 static int nds32_gpr16 = -1;
@@ -1934,10 +2362,13 @@ static int nds32_abi = -1;
 static int nds32_elf_flags = 0;
 static int nds32_fpu_com = 0;
 
-static int nds32_parse_arch (char *str);
-static int nds32_parse_baseline (char *str);
-static int nds32_parse_freg (char *str);
-static int nds32_parse_abi (char *str);
+static int nds32_parse_arch (const char *str);
+static int nds32_parse_baseline (const char *str);
+static int nds32_parse_freg (const char *str);
+static int nds32_parse_abi (const char *str);
+static void add_mapping_symbol (enum mstate state,
+                               unsigned int padding_byte,
+                               unsigned int align);
 
 static struct nds32_parse_option_table parse_opts [] =
 {
@@ -1962,11 +2393,13 @@ static struct nds32_parse_option_table parse_opts [] =
 static int nds32_mac = 1;
 static int nds32_div = 1;
 static int nds32_16bit_ext = 1;
-static int nds32_dx_regs = 1;
-static int nds32_perf_ext = 1;
-static int nds32_perf_ext2 = 1;
-static int nds32_string_ext = 1;
-static int nds32_audio_ext = 1;
+static int nds32_dx_regs = NDS32_DEFAULT_DX_REGS;
+static int nds32_perf_ext = NDS32_DEFAULT_PERF_EXT;
+static int nds32_perf_ext2 = NDS32_DEFAULT_PERF_EXT2;
+static int nds32_string_ext = NDS32_DEFAULT_STRING_EXT;
+static int nds32_audio_ext = NDS32_DEFAULT_AUDIO_EXT;
+static int nds32_dsp_ext = NDS32_DEFAULT_DSP_EXT;
+static int nds32_zol_ext = NDS32_DEFAULT_ZOL_EXT;
 static int nds32_fpu_fma = 0;
 static int nds32_pic = 0;
 static int nds32_relax_fp_as_gp = 1;
@@ -1975,7 +2408,7 @@ static int nds32_relax_all = 1;
 struct nds32_set_option_table
 {
   const char *name;            /* Option string.  */
-  char *help;                  /* Help description.  */
+  const char *help;                    /* Help description.  */
   int *var;                    /* Variable to be set.  */
   int value;                   /* Value to set.  */
 };
@@ -1997,6 +2430,8 @@ static struct nds32_set_option_table toggle_opts [] =
   {"fpu-sp-ext", N_("FPU SP extension"), &nds32_fpu_sp_ext, 1},
   {"fpu-dp-ext", N_("FPU DP extension"), &nds32_fpu_dp_ext, 1},
   {"fpu-fma", N_("FPU fused-multiply-add instructions"), &nds32_fpu_fma, 1},
+  {"dsp-ext", N_("DSP extension"), &nds32_dsp_ext, 1},
+  {"zol-ext", N_("hardware loop extension"), &nds32_zol_ext, 1},
   {NULL, NULL, NULL, 0}
 };
 
@@ -2010,7 +2445,7 @@ nds32_asm_parse_operand (struct nds32_asm_desc *pdesc,
                         char **pstr, int64_t *value);
 
 \f
-struct nds32_asm_desc asm_desc;
+static struct nds32_asm_desc asm_desc;
 
 /* md_after_parse_args ()
 
@@ -2100,13 +2535,13 @@ nds32_start_line_hook (void)
  * Pseudo opcodes
  */
 
-typedef void (*nds32_pseudo_opcode_func) (int argc, char *argv[], int pv);
+typedef void (*nds32_pseudo_opcode_func) (int argc, char *argv[], unsigned int pv);
 struct nds32_pseudo_opcode
 {
   const char *opcode;
   int argc;
   nds32_pseudo_opcode_func proc;
-  int pseudo_val;
+  unsigned int pseudo_val;
 
   /* Some instructions are not pseudo opcode, but they might still be
      expanded or changed with other instruction combination for some
@@ -2139,7 +2574,9 @@ static struct hash_control *nds32_pseudo_opcode_hash = NULL;
 static int
 builtin_isreg (const char *s, const char *x ATTRIBUTE_UNUSED)
 {
-  return s[0] == '$';
+  if (s [0] == '$' && hash_find (nds32_gprs_hash, (s + 1)))
+    return 1;
+  return 0;
 }
 
 static int
@@ -2172,7 +2609,7 @@ builtin_addend (const char *s, char *x ATTRIBUTE_UNUSED)
 }
 
 static void
-md_assemblef (char *format, ...)
+md_assemblef (const char *format, ...)
 {
   /* FIXME: hope this is long enough.  */
   char line[1024];
@@ -2187,21 +2624,22 @@ md_assemblef (char *format, ...)
 }
 
 /* Some prototypes here, since some op may use another op.  */
-static void do_pseudo_li_internal (char *rt, int imm32s);
+static void do_pseudo_li_internal (const char *rt, int imm32s);
 static void do_pseudo_move_reg_internal (char *dst, char *src);
 
 static void
-do_pseudo_b (int argc ATTRIBUTE_UNUSED, char *argv[], int pv ATTRIBUTE_UNUSED)
+do_pseudo_b (int argc ATTRIBUTE_UNUSED, char *argv[], 
+            unsigned int pv ATTRIBUTE_UNUSED)
 {
   char *arg_label = argv[0];
   relaxing = TRUE;
   /* b   label */
-  if (nds32_pic && strstr (arg_label, "@PLT"))
+  if (nds32_pic)
     {
       md_assemblef ("sethi $ta,hi20(%s)", arg_label);
       md_assemblef ("ori $ta,$ta,lo12(%s)", arg_label);
-      md_assemble  ("add $ta,$ta,$gp");
-      md_assemble  ("jr $ta");
+      md_assemble  ((char *) "add $ta,$ta,$gp");
+      md_assemble  ((char *) "jr $ta");
     }
   else
     {
@@ -2211,18 +2649,18 @@ do_pseudo_b (int argc ATTRIBUTE_UNUSED, char *argv[], int pv ATTRIBUTE_UNUSED)
 }
 
 static void
-do_pseudo_bal (int argc ATTRIBUTE_UNUSED, char *argv[], int pv ATTRIBUTE_UNUSED)
+do_pseudo_bal (int argc ATTRIBUTE_UNUSED, char *argv[], 
+              unsigned int pv ATTRIBUTE_UNUSED)
 {
   char *arg_label = argv[0];
   relaxing = TRUE;
   /* bal|call  label */
-  if (nds32_pic
-      && (strstr (arg_label, "@GOT") || strstr (arg_label, "@PLT")))
+  if (nds32_pic)
     {
       md_assemblef ("sethi $ta,hi20(%s)", arg_label);
       md_assemblef ("ori $ta,$ta,lo12(%s)", arg_label);
-      md_assemble  ("add $ta,$ta,$gp");
-      md_assemble ("jral $ta");
+      md_assemble ((char *) "add $ta,$ta,$gp");
+      md_assemble ((char *) "jral $ta");
     }
   else
     {
@@ -2232,7 +2670,8 @@ do_pseudo_bal (int argc ATTRIBUTE_UNUSED, char *argv[], int pv ATTRIBUTE_UNUSED)
 }
 
 static void
-do_pseudo_bge (int argc ATTRIBUTE_UNUSED, char *argv[], int pv ATTRIBUTE_UNUSED)
+do_pseudo_bge (int argc ATTRIBUTE_UNUSED, char *argv[], 
+              unsigned int pv ATTRIBUTE_UNUSED)
 {
   /* rt5, ra5, label */
   md_assemblef ("slt $ta,%s,%s", argv[0], argv[1]);
@@ -2240,7 +2679,8 @@ do_pseudo_bge (int argc ATTRIBUTE_UNUSED, char *argv[], int pv ATTRIBUTE_UNUSED)
 }
 
 static void
-do_pseudo_bges (int argc ATTRIBUTE_UNUSED, char *argv[], int pv ATTRIBUTE_UNUSED)
+do_pseudo_bges (int argc ATTRIBUTE_UNUSED, char *argv[], 
+               unsigned int pv ATTRIBUTE_UNUSED)
 {
   /* rt5, ra5, label */
   md_assemblef ("slts $ta,%s,%s", argv[0], argv[1]);
@@ -2248,7 +2688,8 @@ do_pseudo_bges (int argc ATTRIBUTE_UNUSED, char *argv[], int pv ATTRIBUTE_UNUSED
 }
 
 static void
-do_pseudo_bgt (int argc ATTRIBUTE_UNUSED, char *argv[], int pv ATTRIBUTE_UNUSED)
+do_pseudo_bgt (int argc ATTRIBUTE_UNUSED, char *argv[], 
+              unsigned int pv ATTRIBUTE_UNUSED)
 {
   /* bgt rt5, ra5, label */
   md_assemblef ("slt $ta,%s,%s", argv[1], argv[0]);
@@ -2256,7 +2697,8 @@ do_pseudo_bgt (int argc ATTRIBUTE_UNUSED, char *argv[], int pv ATTRIBUTE_UNUSED)
 }
 
 static void
-do_pseudo_bgts (int argc ATTRIBUTE_UNUSED, char *argv[], int pv ATTRIBUTE_UNUSED)
+do_pseudo_bgts (int argc ATTRIBUTE_UNUSED, char *argv[], 
+               unsigned int pv ATTRIBUTE_UNUSED)
 {
   /* bgt rt5, ra5, label */
   md_assemblef ("slts $ta,%s,%s", argv[1], argv[0]);
@@ -2264,7 +2706,8 @@ do_pseudo_bgts (int argc ATTRIBUTE_UNUSED, char *argv[], int pv ATTRIBUTE_UNUSED
 }
 
 static void
-do_pseudo_ble (int argc ATTRIBUTE_UNUSED, char *argv[], int pv ATTRIBUTE_UNUSED)
+do_pseudo_ble (int argc ATTRIBUTE_UNUSED, char *argv[], 
+              unsigned int pv ATTRIBUTE_UNUSED)
 {
   /* bgt rt5, ra5, label */
   md_assemblef ("slt $ta,%s,%s", argv[1], argv[0]);
@@ -2272,7 +2715,8 @@ do_pseudo_ble (int argc ATTRIBUTE_UNUSED, char *argv[], int pv ATTRIBUTE_UNUSED)
 }
 
 static void
-do_pseudo_bles (int argc ATTRIBUTE_UNUSED, char *argv[], int pv ATTRIBUTE_UNUSED)
+do_pseudo_bles (int argc ATTRIBUTE_UNUSED, char *argv[], 
+               unsigned int pv ATTRIBUTE_UNUSED)
 {
   /* bgt rt5, ra5, label */
   md_assemblef ("slts $ta,%s,%s", argv[1], argv[0]);
@@ -2280,7 +2724,8 @@ do_pseudo_bles (int argc ATTRIBUTE_UNUSED, char *argv[], int pv ATTRIBUTE_UNUSED
 }
 
 static void
-do_pseudo_blt (int argc ATTRIBUTE_UNUSED, char *argv[], int pv ATTRIBUTE_UNUSED)
+do_pseudo_blt (int argc ATTRIBUTE_UNUSED, char *argv[], 
+              unsigned int pv ATTRIBUTE_UNUSED)
 {
   /* rt5, ra5, label */
   md_assemblef ("slt $ta,%s,%s", argv[0], argv[1]);
@@ -2288,7 +2733,8 @@ do_pseudo_blt (int argc ATTRIBUTE_UNUSED, char *argv[], int pv ATTRIBUTE_UNUSED)
 }
 
 static void
-do_pseudo_blts (int argc ATTRIBUTE_UNUSED, char *argv[], int pv ATTRIBUTE_UNUSED)
+do_pseudo_blts (int argc ATTRIBUTE_UNUSED, char *argv[], 
+               unsigned int pv ATTRIBUTE_UNUSED)
 {
   /* rt5, ra5, label */
   md_assemblef ("slts $ta,%s,%s", argv[0], argv[1]);
@@ -2296,13 +2742,15 @@ do_pseudo_blts (int argc ATTRIBUTE_UNUSED, char *argv[], int pv ATTRIBUTE_UNUSED
 }
 
 static void
-do_pseudo_br (int argc ATTRIBUTE_UNUSED, char *argv[], int pv ATTRIBUTE_UNUSED)
+do_pseudo_br (int argc ATTRIBUTE_UNUSED, char *argv[], 
+             unsigned int pv ATTRIBUTE_UNUSED)
 {
   md_assemblef ("jr %s", argv[0]);
 }
 
 static void
-do_pseudo_bral (int argc, char *argv[], int pv ATTRIBUTE_UNUSED)
+do_pseudo_bral (int argc, char *argv[], 
+               unsigned int pv ATTRIBUTE_UNUSED)
 {
   if (argc == 1)
     md_assemblef ("jral $lp,%s", argv[0]);
@@ -2311,12 +2759,21 @@ do_pseudo_bral (int argc, char *argv[], int pv ATTRIBUTE_UNUSED)
 }
 
 static void
-do_pseudo_la_internal (const char *arg_reg, const char *arg_label,
+do_pseudo_la_internal (const char *arg_reg, char *arg_label,
                       const char *line)
 {
+  expressionS exp;
+
+  parse_expression (arg_label, &exp);
+  if (exp.X_op != O_symbol)
+    {
+      as_bad (_("la must use with symbol. '%s'"), line);
+      return;
+    }
+
   relaxing = TRUE;
   /* rt, label */
-  if (!nds32_pic && !strstr(arg_label, "@"))
+  if (!nds32_pic && !strstr (arg_label, "@"))
     {
       md_assemblef ("sethi %s,hi20(%s)", arg_reg, arg_label);
       md_assemblef ("ori %s,%s,lo12(%s)", arg_reg, arg_reg, arg_label);
@@ -2368,13 +2825,14 @@ do_pseudo_la_internal (const char *arg_reg, const char *arg_label,
 }
 
 static void
-do_pseudo_la (int argc ATTRIBUTE_UNUSED, char *argv[], int pv ATTRIBUTE_UNUSED)
+do_pseudo_la (int argc ATTRIBUTE_UNUSED, char *argv[], 
+             unsigned int pv ATTRIBUTE_UNUSED)
 {
   do_pseudo_la_internal (argv[0], argv[1], argv[argc]);
 }
 
 static void
-do_pseudo_li_internal (char *rt, int imm32s)
+do_pseudo_li_internal (const char *rt, int imm32s)
 {
   if (enable_16bit && imm32s <= 0xf && imm32s >= -0x10)
     md_assemblef ("movi55 %s,%d", rt, imm32s);
@@ -2390,7 +2848,8 @@ do_pseudo_li_internal (char *rt, int imm32s)
 }
 
 static void
-do_pseudo_li (int argc ATTRIBUTE_UNUSED, char *argv[], int pv ATTRIBUTE_UNUSED)
+do_pseudo_li (int argc ATTRIBUTE_UNUSED, char *argv[], 
+             unsigned int pv ATTRIBUTE_UNUSED)
 {
   /* Validate argv[1] for constant expression.  */
   expressionS exp;
@@ -2406,7 +2865,8 @@ do_pseudo_li (int argc ATTRIBUTE_UNUSED, char *argv[], int pv ATTRIBUTE_UNUSED)
 }
 
 static void
-do_pseudo_ls_bhw (int argc ATTRIBUTE_UNUSED, char *argv[], int pv)
+do_pseudo_ls_bhw (int argc ATTRIBUTE_UNUSED, char *argv[], 
+                 unsigned int pv)
 {
   char ls = 'r';
   char size = 'x';
@@ -2472,7 +2932,7 @@ do_pseudo_ls_bhw (int argc ATTRIBUTE_UNUSED, char *argv[], int pv)
          /* lw */
          md_assemblef ("sethi $ta,hi20(%s)", argv[1]);
          md_assemblef ("ori $ta,$ta,lo12(%s)", argv[1]);
-         md_assemble ("lw $ta,[$gp+$ta]");     /* Load address word.  */
+         md_assemble ((char *) "lw $ta,[$gp+$ta]");    /* Load address word.  */
          if (addend < 0x10000 && addend >= -0x10000)
            {
              md_assemblef ("%c%c%si %s,[$ta+(%d)]", ls, size, sign, argv[0], addend);
@@ -2493,7 +2953,8 @@ do_pseudo_ls_bhw (int argc ATTRIBUTE_UNUSED, char *argv[], int pv)
 }
 
 static void
-do_pseudo_ls_bhwp (int argc ATTRIBUTE_UNUSED, char *argv[], int pv)
+do_pseudo_ls_bhwp (int argc ATTRIBUTE_UNUSED, char *argv[], 
+                  unsigned int pv)
 {
   char *arg_rt = argv[0];
   char *arg_label = argv[1];
@@ -2520,7 +2981,8 @@ do_pseudo_ls_bhwp (int argc ATTRIBUTE_UNUSED, char *argv[], int pv)
 }
 
 static void
-do_pseudo_ls_bhwpc (int argc ATTRIBUTE_UNUSED, char *argv[], int pv)
+do_pseudo_ls_bhwpc (int argc ATTRIBUTE_UNUSED, char *argv[],
+                   unsigned int pv)
 {
   char *arg_rt = argv[0];
   char *arg_inc = argv[1];
@@ -2545,7 +3007,8 @@ do_pseudo_ls_bhwpc (int argc ATTRIBUTE_UNUSED, char *argv[], int pv)
 }
 
 static void
-do_pseudo_ls_bhwi (int argc ATTRIBUTE_UNUSED, char *argv[], int pv)
+do_pseudo_ls_bhwi (int argc ATTRIBUTE_UNUSED, char *argv[], 
+                  unsigned int pv)
 {
   char ls = 'r';
   char size = 'x';
@@ -2578,43 +3041,49 @@ do_pseudo_move_reg_internal (char *dst, char *src)
 }
 
 static void
-do_pseudo_move (int argc ATTRIBUTE_UNUSED, char *argv[], int pv ATTRIBUTE_UNUSED)
+do_pseudo_move (int argc ATTRIBUTE_UNUSED, char *argv[], 
+               unsigned int pv ATTRIBUTE_UNUSED)
 {
   expressionS exp;
 
-  parse_expression (argv[1], &exp);
-
   if (builtin_isreg (argv[1], NULL))
     do_pseudo_move_reg_internal (argv[0], argv[1]);
-  else if (exp.X_op == O_constant)
-    /* move $rt, imm  -> li $rt, imm  */
-    do_pseudo_li_internal (argv[0], exp.X_add_number);
   else
-    /* l.w $rt, var  -> l.w $rt, var  */
-    do_pseudo_ls_bhw (argc, argv, 2);
+    {
+      parse_expression (argv[1], &exp);
+      if (exp.X_op == O_constant)
+       /* move $rt, imm  -> li $rt, imm  */
+       do_pseudo_li_internal (argv[0], exp.X_add_number);
+      else
+       /* l.w $rt, var  -> l.w $rt, var  */
+       do_pseudo_ls_bhw (argc, argv, 2);
+    }
 }
 
 static void
-do_pseudo_neg (int argc ATTRIBUTE_UNUSED, char *argv[], int pv ATTRIBUTE_UNUSED)
+do_pseudo_neg (int argc ATTRIBUTE_UNUSED, char *argv[], 
+              unsigned int pv ATTRIBUTE_UNUSED)
 {
   /* Instead of "subri".  */
   md_assemblef ("subri %s,%s,0", argv[0], argv[1]);
 }
 
 static void
-do_pseudo_not (int argc ATTRIBUTE_UNUSED, char *argv[], int pv ATTRIBUTE_UNUSED)
+do_pseudo_not (int argc ATTRIBUTE_UNUSED, char *argv[],
+              unsigned int pv ATTRIBUTE_UNUSED)
 {
   md_assemblef ("nor %s,%s,%s", argv[0], argv[1], argv[1]);
 }
 
 static void
-do_pseudo_pushpopm (int argc, char *argv[], int pv ATTRIBUTE_UNUSED)
+do_pseudo_pushpopm (int argc, char *argv[],
+                   unsigned int pv ATTRIBUTE_UNUSED)
 {
   /* posh/pop $ra, $rb */
   /* SMW.{b | a}{i | d}{m?} Rb, [Ra], Re, Enable4 */
   int rb, re, ra, en4;
   int i;
-  char *opc = "pushpopm";
+  const char *opc = "pushpopm";
 
   if (argc == 3)
     as_bad ("'pushm/popm $ra5, $rb5, $label' is deprecated.  "
@@ -2658,11 +3127,11 @@ do_pseudo_pushpopm (int argc, char *argv[], int pv ATTRIBUTE_UNUSED)
   /* Reduce register.  */
   if (nds32_gpr16 && re > 10 && !(rb == 31 && re == 31))
     {
-      if (re >= 15 && strstr(opc, "smw") != NULL)
+      if (re >= 15 && strstr (opc, "smw") != NULL)
        md_assemblef ("%s $r15,[$sp],$r15,%d", opc, en4);
       if (rb <= 10)
        md_assemblef ("%s $r%d,[$sp],$r10, 0x0", opc, rb);
-      if (re >= 15 && strstr(opc, "lmw") != NULL)
+      if (re >= 15 && strstr (opc, "lmw") != NULL)
        md_assemblef ("%s $r15,[$sp],$r15,%d", opc, en4);
     }
   else
@@ -2670,7 +3139,8 @@ do_pseudo_pushpopm (int argc, char *argv[], int pv ATTRIBUTE_UNUSED)
 }
 
 static void
-do_pseudo_pushpop (int argc, char *argv[], int pv ATTRIBUTE_UNUSED)
+do_pseudo_pushpop (int argc, char *argv[],
+                  unsigned int pv ATTRIBUTE_UNUSED)
 {
   /* push/pop $ra5, $label=$sp */
   char *argvm[3];
@@ -2686,13 +3156,15 @@ do_pseudo_pushpop (int argc, char *argv[], int pv ATTRIBUTE_UNUSED)
 }
 
 static void
-do_pseudo_v3push (int argc ATTRIBUTE_UNUSED, char *argv[], int pv ATTRIBUTE_UNUSED)
+do_pseudo_v3push (int argc ATTRIBUTE_UNUSED, char *argv[],
+                 unsigned int pv ATTRIBUTE_UNUSED)
 {
   md_assemblef ("push25 %s,%s", argv[0], argv[1]);
 }
 
 static void
-do_pseudo_v3pop (int argc ATTRIBUTE_UNUSED, char *argv[], int pv ATTRIBUTE_UNUSED)
+do_pseudo_v3pop (int argc ATTRIBUTE_UNUSED, char *argv[], 
+                unsigned int pv ATTRIBUTE_UNUSED)
 {
   md_assemblef ("pop25 %s,%s", argv[0], argv[1]);
 }
@@ -2701,7 +3173,8 @@ do_pseudo_v3pop (int argc ATTRIBUTE_UNUSED, char *argv[], int pv ATTRIBUTE_UNUSE
    pv != 0, parsing "pop.s" pseudo instruction operands.  */
 
 static void
-do_pseudo_pushpop_stack (int argc, char *argv[], int pv)
+do_pseudo_pushpop_stack (int argc, char *argv[],
+                        unsigned int pv)
 {
   /* push.s Rb,Re,{$fp $gp $lp $sp}  ==>  smw.adm Rb,[$sp],Re,Eable4  */
   /* pop.s Rb,Re,{$fp $gp $lp $sp}   ==>  lmw.bim Rb,[$sp],Re,Eable4  */
@@ -2709,7 +3182,7 @@ do_pseudo_pushpop_stack (int argc, char *argv[], int pv)
   int rb, re;
   int en4;
   int last_arg_index;
-  char *opc = (pv == 0) ? "smw.adm" : "lmw.bim";
+  const char *opc = (pv == 0) ? "smw.adm" : "lmw.bim";
 
   rb = re = 0;
 
@@ -2765,7 +3238,8 @@ do_pseudo_pushpop_stack (int argc, char *argv[], int pv)
 }
 
 static void
-do_pseudo_push_bhwd (int argc ATTRIBUTE_UNUSED, char *argv[], int pv ATTRIBUTE_UNUSED)
+do_pseudo_push_bhwd (int argc ATTRIBUTE_UNUSED, char *argv[],
+                    unsigned int pv ATTRIBUTE_UNUSED)
 {
   char size = 'x';
   /* If users omit push location, use $sp as default value.  */
@@ -2796,7 +3270,8 @@ do_pseudo_push_bhwd (int argc ATTRIBUTE_UNUSED, char *argv[], int pv ATTRIBUTE_U
 }
 
 static void
-do_pseudo_pop_bhwd (int argc ATTRIBUTE_UNUSED, char *argv[], int pv ATTRIBUTE_UNUSED)
+do_pseudo_pop_bhwd (int argc ATTRIBUTE_UNUSED, char *argv[],
+                   unsigned int pv ATTRIBUTE_UNUSED)
 {
   char size = 'x';
   /* If users omit pop location, use $sp as default value.  */
@@ -2827,7 +3302,8 @@ do_pseudo_pop_bhwd (int argc ATTRIBUTE_UNUSED, char *argv[], int pv ATTRIBUTE_UN
 }
 
 static void
-do_pseudo_pusha (int argc ATTRIBUTE_UNUSED, char *argv[], int pv ATTRIBUTE_UNUSED)
+do_pseudo_pusha (int argc ATTRIBUTE_UNUSED, char *argv[],
+                unsigned int pv ATTRIBUTE_UNUSED)
 {
   /* If users omit push location, use $sp as default value.  */
   char location[8] = "$sp";  /* 8 is enough for register name.  */
@@ -2843,7 +3319,8 @@ do_pseudo_pusha (int argc ATTRIBUTE_UNUSED, char *argv[], int pv ATTRIBUTE_UNUSE
 }
 
 static void
-do_pseudo_pushi (int argc ATTRIBUTE_UNUSED, char *argv[], int pv ATTRIBUTE_UNUSED)
+do_pseudo_pushi (int argc ATTRIBUTE_UNUSED, char *argv[],
+                unsigned int pv ATTRIBUTE_UNUSED)
 {
   /* If users omit push location, use $sp as default value.  */
   char location[8] = "$sp";  /* 8 is enough for register name.  */
@@ -2858,7 +3335,7 @@ do_pseudo_pushi (int argc ATTRIBUTE_UNUSED, char *argv[], int pv ATTRIBUTE_UNUSE
   md_assemblef ("smw.adm $ta,[%s],$ta", location);
 }
 
-struct nds32_pseudo_opcode nds32_pseudo_opcode_table[] =
+static struct nds32_pseudo_opcode nds32_pseudo_opcode_table[] =
 {
   {"b",      1, do_pseudo_b,      0, 0},
   {"bal",    1, do_pseudo_bal,    0, 0},
@@ -2934,8 +3411,8 @@ struct nds32_pseudo_opcode nds32_pseudo_opcode_table[] =
   {"v3pop",  2, do_pseudo_v3pop,  0, 0},
 
   /* Support pseudo instructions of pushing/poping registers into/from stack
-       push.s  Rb, Re, { $fp $gp $lp $sp }  ==>  smw.adm  Rb,[$sp],Re,Enable4
-       pop.s   Rb, Re, { $fp $gp $lp $sp }  ==>  lmw.bim  Rb,[$sp],Re,Enable4 */
+     push.s  Rb, Re, { $fp $gp $lp $sp }  ==>  smw.adm  Rb,[$sp],Re,Enable4
+     pop.s   Rb, Re, { $fp $gp $lp $sp }  ==>  lmw.bim  Rb,[$sp],Re,Enable4 */
   { "push.s", 3, do_pseudo_pushpop_stack, 0, 0 },
   { "pop.s", 3, do_pseudo_pushpop_stack, 1, 0 },
   { "push.b", 2, do_pseudo_push_bhwd, 0, 0 },
@@ -2973,24 +3450,25 @@ nds32_init_nds32_pseudo_opcodes (void)
 }
 
 static struct nds32_pseudo_opcode *
-nds32_lookup_pseudo_opcode (char *str)
+nds32_lookup_pseudo_opcode (const char *str)
 {
+  struct nds32_pseudo_opcode *result;
   int i = 0;
-  /* Assume pseudo-opcode are less than 16-char in length.  */
-  char op[16] = {0};
 
-  for (i = 0; i < (int)ARRAY_SIZE (op); i++)
+  /* (*op) is the first word of current source line (*str)  */
+  int maxlen = strlen (str);
+  char *op = xmalloc (maxlen + 1);
+
+  for (i = 0; i < maxlen; i++)
     {
       if (ISSPACE (op[i] = str[i]))
        break;
     }
-
-  if (i >= (int)ARRAY_SIZE (op))
-    return NULL;
-
   op[i] = '\0';
 
-  return hash_find (nds32_pseudo_opcode_hash, op);
+  result = hash_find (nds32_pseudo_opcode_hash, op);
+  free (op);
+  return result;
 }
 
 static void
@@ -3034,7 +3512,7 @@ end:
    Thus, if the value of option has been set, keep the value the way it is.  */
 
 static int
-nds32_parse_arch (char *str)
+nds32_parse_arch (const char *str)
 {
   static const struct nds32_arch
   {
@@ -3084,7 +3562,7 @@ nds32_parse_arch (char *str)
 /* This function parses "baseline" specified.  */
 
 static int
-nds32_parse_baseline (char *str)
+nds32_parse_baseline (const char *str)
 {
   if (strcmp (str, "v3") == 0)
     nds32_baseline = ISA_V3;
@@ -3105,7 +3583,7 @@ nds32_parse_baseline (char *str)
 /* This function parses "fpu-freg" specified.  */
 
 static int
-nds32_parse_freg (char *str)
+nds32_parse_freg (const char *str)
 {
   if (strcmp (str, "2") == 0)
     nds32_freg = E_NDS32_FPU_REG_32SP_16DP;
@@ -3128,7 +3606,7 @@ nds32_parse_freg (char *str)
 /* This function parse "abi=" specified.  */
 
 static int
-nds32_parse_abi (char *str)
+nds32_parse_abi (const char *str)
 {
   if (strcmp (str, "v2") == 0)
     nds32_abi = E_NDS_ABI_AABI;
@@ -3165,6 +3643,10 @@ nds32_all_ext (void)
   nds32_fpu_fma = 1;
   nds32_fpu_sp_ext = 1;
   nds32_fpu_dp_ext = 1;
+  nds32_dsp_ext = 1;
+  nds32_zol_ext = 1;
+  /* Turn off reduced register.  */
+  nds32_gpr16 = 0;
 
   return 1;
 }
@@ -3176,11 +3658,11 @@ nds32_all_ext (void)
    recognized.  This will be handled by the generic code.  */
 
 int
-nds32_parse_option (int c, char *arg)
+nds32_parse_option (int c, const char *arg)
 {
   struct nds32_parse_option_table *coarse_tune;
   struct nds32_set_option_table *fine_tune;
-  char *ptr_arg = NULL;
+  const char *ptr_arg = NULL;
 
   switch (c)
     {
@@ -3376,24 +3858,39 @@ nds32_seg (int i)
 }
 
 /* Set if label adjustment is needed.  I should not adjust .xbyte in dwarf.  */
-static symbolS *nds32_last_label;      /* Last label for aligment.  */
+static symbolS *nds32_last_label;      /* Last label for alignment.  */
+
+static void
+add_mapping_symbol_for_align (int shift, valueT addr, int is_data_align)
+{
+  if ((shift > 1) && (addr & 1))
+    {
+      int n = (1 << shift) - 1;
+      if (!is_data_align)
+       add_mapping_symbol (MAP_CODE, 1, 0);
+      else if ((int) (addr & n) != n)
+       add_mapping_symbol (MAP_CODE, 1, 0);
+    }
+  else if ((shift > 1) && ((int) (addr & 1) == 0))
+    add_mapping_symbol (MAP_CODE, 0, 0);
+}
 
-/* This code is referred from D30V for adjust label to be with pedning
-   aligment.  For example,
+/* This code is referred from D30V for adjust label to be with pending
+   alignment.  For example,
      LBYTE: .byte      0x12
      LHALF: .half      0x12
      LWORD: .word      0x12
-   Without this, the above label will not attatch to incoming data.  */
+   Without this, the above label will not attach to incoming data.  */
 
 static void
 nds32_adjust_label (int n)
 {
-  /* FIXME: I think adjust lable and alignment is
-     the programmer's obligation.  Saddly, VLSI team doesn't
+  /* FIXME: I think adjust label and alignment is
+     the programmer's obligation.  Sadly, VLSI team doesn't
      properly use .align for their test cases.
      So I re-implement cons_align and auto adjust labels, again.
 
-     I think d30v's implmentation is simple and good enough.  */
+     I think d30v's implementation is simple and good enough.  */
 
   symbolS *label = nds32_last_label;
   nds32_last_label = NULL;
@@ -3411,7 +3908,10 @@ nds32_adjust_label (int n)
   if (frag_now_fix () & ((1 << n) -1 ))
     {
       if (subseg_text_p (now_seg))
-       frag_align_code (n, 0);
+       {
+         add_mapping_symbol_for_align (n, frag_now_fix (), 1);
+         frag_align_code (n, 0);
+       }
       else
        frag_align (n, 0, 0);
 
@@ -3460,7 +3960,7 @@ nds32_cons_align (int size ATTRIBUTE_UNUSED)
 
      There are two things should be done for auto-adjust-label.
      1. Align data/instructions and adjust label to be attached to them.
-     2. Clear auto-adjust state, so incommng data/instructions will not
+     2. Clear auto-adjust state, so incoming data/instructions will not
        adjust the label.
 
      For example,
@@ -3476,16 +3976,70 @@ nds32_cons_align (int size ATTRIBUTE_UNUSED)
      I think we should just adjust label in `nds32_aligned_X_cons' instead of here.  */
 }
 
+static void
+make_mapping_symbol (enum mstate state, valueT value, fragS * frag, unsigned int align)
+{
+  symbolS *symbol_p = NULL;
+  const char *symbol_name = NULL;
+  switch (state)
+    {
+    case MAP_DATA:
+      if (align == 0)
+       symbol_name = "$d0";
+      else if (align == 1)
+       symbol_name = "$d1";
+      else if (align == 2)
+       symbol_name = "$d2";
+      else if (align == 3)
+       symbol_name = "$d3";
+      else if (align == 4)
+       symbol_name = "$d4";
+      break;
+    case MAP_CODE:
+      symbol_name = "$c";
+      break;
+    default:
+      abort ();
+    }
+
+  symbol_p = symbol_new (symbol_name, now_seg, value, frag);
+  /* local scope attribute  */
+  symbol_get_bfdsym (symbol_p)->flags |= BSF_NO_FLAGS | BSF_LOCAL;
+}
+
+static void
+add_mapping_symbol (enum mstate state, unsigned int padding_byte,
+                   unsigned int align)
+{
+  enum mstate current_mapping_state =
+    seg_info (now_seg)->tc_segment_info_data.mapstate;
+
+  if (state == MAP_CODE
+      && current_mapping_state == state)
+    return;
+
+  if (!SEG_NORMAL (now_seg)
+      || !subseg_text_p (now_seg))
+    return;
+
+  /* start adding mapping symbol  */
+  seg_info (now_seg)->tc_segment_info_data.mapstate = state;
+  make_mapping_symbol (state, (valueT) frag_now_fix () + padding_byte,
+                      frag_now, align);
+}
+
 static void
 nds32_aligned_cons (int idx)
 {
   nds32_adjust_label (idx);
+  add_mapping_symbol (MAP_DATA, 0, idx);
   /* Call default handler.  */
   cons (1 << idx);
   if (now_seg->flags & SEC_CODE
       && now_seg->flags & SEC_ALLOC && now_seg->flags & SEC_RELOC)
     {
-      /* Use BFD_RELOC_NDS32_DATA to avoid EX9 optimization replacing data.  */
+      /* Use BFD_RELOC_NDS32_DATA to avoid linker
+        optimization replacing data.  */
       expressionS exp;
 
       exp.X_add_number = 0;
@@ -3544,8 +4098,8 @@ nds32_relax_relocs (int relax)
   char saved_char;
   char *name;
   int i;
-  char *subtype_relax[] =
-    {"", "", "ex9", "ifc"};
+  const char *subtype_relax[] =
+    {"", "",};
 
   name = input_line_pointer;
   while (*input_line_pointer && !ISSPACE (*input_line_pointer))
@@ -3562,14 +4116,6 @@ nds32_relax_relocs (int relax)
            case 0:
            case 1:
              enable_relax_relocs = relax & enable_relax_relocs;
-             enable_relax_ex9 = relax & enable_relax_ex9;
-             enable_relax_ifc = relax & enable_relax_ifc;
-             break;
-           case 2:
-             enable_relax_ex9 = relax;
-             break;
-           case 3:
-             enable_relax_ifc = relax;
              break;
            default:
              break;
@@ -3619,31 +4165,6 @@ nds32_omit_fp_begin (int mode)
     }
 }
 
-/* Insert relocations to mark the begin and end of ex9 region,
-   for further relaxation use.
-   bit[i] for $ri */
-
-static void
-nds32_no_ex9_begin (int mode)
-{
-  expressionS exp;
-
-  exp.X_op = O_symbol;
-  exp.X_add_symbol = abs_section_sym;
-  if (mode == 1)
-    {
-      exp.X_add_number = R_NDS32_RELAX_REGION_NO_EX9_FLAG;
-      fix_new_exp (frag_now, frag_now_fix (), 0, &exp, 0,
-                  BFD_RELOC_NDS32_RELAX_REGION_BEGIN);
-    }
-  else
-    {
-      exp.X_add_number = R_NDS32_RELAX_REGION_NO_EX9_FLAG;
-      fix_new_exp (frag_now, frag_now_fix (), 0, &exp, 0,
-                  BFD_RELOC_NDS32_RELAX_REGION_END);
-    }
-}
-
 static void
 nds32_loop_begin (int mode)
 {
@@ -3673,16 +4194,49 @@ struct nds32_relocs_group
 };
 
 static struct nds32_relocs_group *nds32_relax_hint_current = NULL;
+/* Used to reorder the id for ".relax_hint id".  */
+static int relax_hint_bias = 0;
+/* Record current relax hint id.  */
+static int relax_hint_id_current = -1;
+int reset_bias = 0;
+/* If ".relax_hint begin" is triggered?  */
+int relax_hint_begin = 0;
+
+/* Record the reordered relax hint id.  */
+
+struct relax_hint_id
+{
+  int old_id;
+  int new_id;
+  struct relax_hint_id *next;
+};
+
+/* FIXME: Need to find somewhere to free the list.  */
+struct relax_hint_id *record_id_head = NULL;
+
+/* Is the buffer large enough?  */
+#define MAX_BUFFER 12
+
+static char *nds_itoa (int n);
+
+static char *
+nds_itoa (int n)
+{
+  char *buf = xmalloc (MAX_BUFFER * sizeof (char));
+  snprintf (buf, MAX_BUFFER, "%d", n);
+  return buf;
+}
 
 /* Insert a relax hint.  */
 
 static void
 nds32_relax_hint (int mode ATTRIBUTE_UNUSED)
 {
-  char *name;
+  char *name = NULL;
   char saved_char;
   struct nds32_relocs_pattern *relocs = NULL;
   struct nds32_relocs_group *group, *new;
+  struct relax_hint_id *record_id;
 
   name = input_line_pointer;
   while (*input_line_pointer && !ISSPACE (*input_line_pointer))
@@ -3691,20 +4245,66 @@ nds32_relax_hint (int mode ATTRIBUTE_UNUSED)
   *input_line_pointer = 0;
   name = strdup (name);
 
+  if (name && strcmp (name, "begin") == 0)
+    {
+      if (relax_hint_id_current == -1)
+       reset_bias = 1;
+      relax_hint_bias++;
+      relax_hint_id_current++;
+      relax_hint_begin = 1;
+    }
+
+  /* Original case ".relax_hint id".  It's id may need to be reordered. */
+  if (!relax_hint_begin)
+    {
+      int tmp = strtol (name, NULL, 10);
+      record_id = record_id_head;
+      while (record_id)
+       {
+         if (record_id->old_id == tmp)
+           {
+             name = nds_itoa (record_id->new_id);
+             goto reordered_id;
+           }
+         record_id = record_id->next;
+       }
+      if (reset_bias)
+       {
+         relax_hint_bias = relax_hint_id_current - atoi (name) + 1;
+         reset_bias = 0;
+       }
+      relax_hint_id_current = tmp + relax_hint_bias;
+
+      /* Insert the element to the head of the link list.  */
+      struct relax_hint_id *tmp_id = malloc (sizeof (struct relax_hint_id));
+      tmp_id->old_id = tmp;
+      tmp_id->new_id = relax_hint_id_current;
+      tmp_id->next = record_id_head;
+      record_id_head = tmp_id;
+    }
+
+  if (name && strcmp (name, "end") == 0)
+    relax_hint_begin = 0;
+  name = nds_itoa (relax_hint_id_current);
+
+reordered_id:
+
   /* Find relax hint entry for next instruction, and all member will be
      initialized at that time.  */
   relocs = hash_find (nds32_hint_hash, name);
   if (relocs == NULL)
     {
-      relocs = malloc (sizeof (struct nds32_relocs_pattern));
+      relocs = XNEW (struct nds32_relocs_pattern);
+      memset (relocs, 0, sizeof (struct nds32_relocs_pattern));
       hash_insert (nds32_hint_hash, name, relocs);
     }
   else
     {
       while (relocs->next)
        relocs=relocs->next;
-      relocs->next = malloc (sizeof (struct nds32_relocs_pattern));
+      relocs->next = XNEW (struct nds32_relocs_pattern);
       relocs = relocs->next;
+      memset (relocs, 0, sizeof (struct nds32_relocs_pattern));
     }
 
   relocs->next = NULL;
@@ -3716,7 +4316,8 @@ nds32_relax_hint (int mode ATTRIBUTE_UNUSED)
   /* It has to build this list because there are maybe more than one
      instructions relative to the same instruction.  It to connect to
      next instruction after md_assemble.  */
-  new = malloc (sizeof (struct nds32_relocs_group));
+  new = XNEW (struct nds32_relocs_group);
+  memset (new, 0, sizeof (struct nds32_relocs_group));
   new->pattern = relocs;
   new->next = NULL;
   group = nds32_relax_hint_current;
@@ -3770,7 +4371,7 @@ nds32_flag (int ignore ATTRIBUTE_UNUSED)
   char *name;
   char saved_char;
   int i;
-  char *possible_flags[] = { "verbatim" };
+  const char *possible_flags[] = { "verbatim" };
 
   /* Skip whitespaces.  */
   name = input_line_pointer;
@@ -3801,6 +4402,46 @@ nds32_flag (int ignore ATTRIBUTE_UNUSED)
   ignore_rest_of_line ();
 }
 
+static void
+ict_model (int ignore ATTRIBUTE_UNUSED)
+{
+  char *name;
+  char saved_char;
+  int i;
+  const char *possible_flags[] = { "small", "large" };
+
+  /* Skip whitespaces.  */
+  name = input_line_pointer;
+  while (*input_line_pointer && !ISSPACE (*input_line_pointer))
+    input_line_pointer++;
+  saved_char = *input_line_pointer;
+  *input_line_pointer = 0;
+
+  for (i = 0; i < (int) ARRAY_SIZE (possible_flags); i++)
+    {
+      if (strcmp (name, possible_flags[i]) == 0)
+       {
+         switch (i)
+           {
+           case 0:
+             /* flag: verbatim  */
+             ict_flag = ICT_SMALL;
+             break;
+           case 1:
+             ict_flag = ICT_LARGE;
+             break;
+           default:
+             break;
+           }
+         /* Already found the flag, no need to continue next loop.   */
+         break;
+       }
+    }
+
+  *input_line_pointer = saved_char;
+  ignore_rest_of_line ();
+}
+
 static void
 nds32_n12hc (int ignore ATTRIBUTE_UNUSED)
 {
@@ -3861,13 +4502,12 @@ const pseudo_typeS md_pseudo_table[] =
   {"hint_func_args", nds32_set_hint_func_args, 0}, /* Abandon??  */
   {"omit_fp_begin", nds32_omit_fp_begin, 1},
   {"omit_fp_end", nds32_omit_fp_begin, 0},
-  {"no_ex9_begin", nds32_no_ex9_begin, 1},
-  {"no_ex9_end", nds32_no_ex9_begin, 0},
   {"vec_size", nds32_vec_size, 0},
   {"flag", nds32_flag, 0},
   {"innermost_loop_begin", nds32_loop_begin, 1},
   {"innermost_loop_end", nds32_loop_begin, 0},
   {"relax_hint", nds32_relax_hint, 0},
+  {"ict_model", ict_model, 0},
   {NULL, NULL, 0}
 };
 
@@ -3882,10 +4522,12 @@ nds32_pre_do_align (int n, char *fill, int len, int max)
        {
          if (subseg_text_p (now_seg))
            {
+             dwarf2_emit_insn (0);
              fragP = frag_now;
+             add_mapping_symbol_for_align (n, frag_now_fix (), 0);
              frag_align_code (n, max);
 
-             /* Tag this alignment when there is a lable before it.  */
+             /* Tag this alignment when there is a label before it.  */
              if (label_exist)
                {
                  fragP->tc_frag_data.flag = NDS32_FRAG_LABEL;
@@ -3970,14 +4612,17 @@ md_begin (void)
 {
   struct nds32_keyword *k;
   relax_info_t *relax_info;
+  int flags = 0;
 
   bfd_set_arch_mach (stdoutput, TARGET_ARCH, nds32_baseline);
 
   nds32_init_nds32_pseudo_opcodes ();
   asm_desc.parse_operand = nds32_asm_parse_operand;
-  nds32_asm_init (&asm_desc, 0);
+  if (nds32_gpr16)
+    flags |= NASM_OPEN_REDUCED_REG;
+  nds32_asm_init (&asm_desc, flags);
 
-  /* Initial general pupose registers hash table.  */
+  /* Initial general purpose registers hash table.  */
   nds32_gprs_hash = hash_new ();
   for (k = keyword_gpr; k->name; k++)
     hash_insert (nds32_gprs_hash, k->name, k);
@@ -4103,13 +4748,14 @@ get_range_type (const struct nds32_field *field)
 /* Save pseudo instruction relocation list.  */
 
 static struct nds32_relocs_pattern*
-nds32_elf_save_pseudo_pattern (fixS* fixP, struct nds32_opcode *opcode,
+nds32_elf_save_pseudo_pattern (fixS* fixP, struct nds32_asm_insn *insn,
                               char *out, symbolS *sym,
                               struct nds32_relocs_pattern *reloc_ptr,
                               fragS *fragP)
 {
+  struct nds32_opcode *opcode = insn->opcode;
   if (!reloc_ptr)
-    reloc_ptr = malloc (sizeof (struct nds32_relocs_pattern));
+    reloc_ptr = XNEW (struct nds32_relocs_pattern);
   reloc_ptr->seg = now_seg;
   reloc_ptr->sym = sym;
   reloc_ptr->frag = fragP;
@@ -4117,6 +4763,7 @@ nds32_elf_save_pseudo_pattern (fixS* fixP, struct nds32_opcode *opcode,
   reloc_ptr->fixP = fixP;
   reloc_ptr->opcode = opcode;
   reloc_ptr->where = out;
+  reloc_ptr->insn = insn->insn;
   reloc_ptr->next = NULL;
   return reloc_ptr;
 }
@@ -4124,7 +4771,7 @@ nds32_elf_save_pseudo_pattern (fixS* fixP, struct nds32_opcode *opcode,
 /* Check X_md to transform relocation.  */
 
 static fixS*
-nds32_elf_record_fixup_exp (fragS *fragP, char *str,
+nds32_elf_record_fixup_exp (fragS *fragP, const char *str,
                            const struct nds32_field *fld,
                            expressionS *pexp, char* out,
                            struct nds32_asm_insn *insn)
@@ -4158,10 +4805,18 @@ nds32_elf_record_fixup_exp (fragS *fragP, char *str,
          reloc = BFD_RELOC_NDS32_TLS_LE_HI20;
          break;
        case BFD_RELOC_NDS32_GOTTPOFF:  /* @GOTTPOFF */
-         reloc = BFD_RELOC_NDS32_TLS_IE_HI20;
+         reloc = nds32_pic ? BFD_RELOC_NDS32_TLS_IEGP_HI20 : BFD_RELOC_NDS32_TLS_IE_HI20;
          break;
-       default:        /* No suffix.  */
-         reloc = BFD_RELOC_NDS32_HI20;
+       case BFD_RELOC_NDS32_TLS_DESC:  /* @TLSDESC */
+         reloc = BFD_RELOC_NDS32_TLS_DESC_HI20;
+         break;
+       default:        /* No suffix */
+         if (nds32_pic)
+           /* When the file is pic, the address must be offset to gp.
+              It may define another relocation or use GOTOFF.  */
+           reloc = BFD_RELOC_NDS32_PLT_GOTREL_HI20;
+         else
+           reloc = BFD_RELOC_NDS32_HI20;
          break;
        }
       fixP = fix_new_exp (fragP, out - fragP->fr_literal, insn->opcode->isize,
@@ -4193,8 +4848,19 @@ nds32_elf_record_fixup_exp (fragS *fragP, char *str,
            case BFD_RELOC_NDS32_TPOFF:         /* @TPOFF */
              reloc = BFD_RELOC_NDS32_TLS_LE_LO12;
              break;
-           default:    /* No suffix.  */
-             reloc = BFD_RELOC_NDS32_LO12S0;
+           case BFD_RELOC_NDS32_GOTTPOFF:      /* @GOTTPOFF */
+             reloc = nds32_pic ? BFD_RELOC_NDS32_TLS_IEGP_LO12 : BFD_RELOC_NDS32_TLS_IE_LO12;
+             break;
+           case BFD_RELOC_NDS32_TLS_DESC:      /* @TLSDESC */
+             reloc = BFD_RELOC_NDS32_TLS_DESC_LO12;
+             break;
+           default:    /* No suffix */
+             if (nds32_pic)
+               /* When the file is pic, the address must be offset to gp.
+                  It may define another relocation or use GOTOFF.  */
+               reloc = BFD_RELOC_NDS32_PLT_GOTREL_LO12;
+             else
+               reloc = BFD_RELOC_NDS32_LO12S0;
              break;
            }
        }
@@ -4206,9 +4872,9 @@ nds32_elf_record_fixup_exp (fragS *fragP, char *str,
          switch (pexp->X_md)
            {
            case BFD_RELOC_NDS32_GOTTPOFF:      /* @GOTTPOFF */
-             reloc = BFD_RELOC_NDS32_TLS_IE_LO12S2;
+             reloc = nds32_pic ? BFD_RELOC_NDS32_TLS_IEGP_LO12S2 : BFD_RELOC_NDS32_TLS_IE_LO12S2;
              break;
-           default:    /* No suffix */
+           default:    /* No suffix */
              reloc = BFD_RELOC_NDS32_LO12S2;
              break;
            }
@@ -4216,7 +4882,7 @@ nds32_elf_record_fixup_exp (fragS *fragP, char *str,
       else if (fld->bitsize == 15 && fld->shift == 3)
        reloc = BFD_RELOC_NDS32_LO12S3;         /* [ls]di */
       else if (fld->bitsize == 12 && fld->shift == 2)
-       reloc = R_NDS32_LO12S2_SP_RELA;         /* f[ls][sd]i */
+       reloc = BFD_RELOC_NDS32_LO12S2_SP;      /* f[ls][sd]i */
 
       fixP = fix_new_exp (fragP, out - fragP->fr_literal, insn->opcode->isize,
                          insn->info, 0 /* pcrel */, reloc);
@@ -4272,20 +4938,6 @@ nds32_elf_record_fixup_exp (fragS *fragP, char *str,
       else
        abort ();
 
-      fixP = fix_new_exp (fragP, out - fragP->fr_literal, insn->opcode->isize,
-                  insn->info, 1 /* pcrel */, reloc);
-    }
-  else if (fld && fld->bitpos == 0 && (insn->attr & NASM_ATTR_IFC_EXT))
-    {
-      /* Relocation for ifcall instruction.  */
-      if (insn->opcode->isize == 2 && fld->bitsize == 9 && fld->shift == 1)
-       reloc = BFD_RELOC_NDS32_10IFCU_PCREL;
-      else if (insn->opcode->isize == 4 && fld->bitsize == 16
-              && fld->shift == 1)
-       reloc = BFD_RELOC_NDS32_17IFC_PCREL;
-      else
-       abort ();
-
       fixP = fix_new_exp (fragP, out - fragP->fr_literal, insn->opcode->isize,
                   insn->info, 1 /* pcrel */, reloc);
     }
@@ -4300,8 +4952,9 @@ nds32_elf_record_fixup_exp (fragS *fragP, char *str,
 
 static void
 nds32_elf_build_relax_relation (fixS *fixP, expressionS *pexp, char* out,
-                               struct nds32_opcode *opcode, fragS *fragP,
-                               const struct nds32_field *fld)
+                               struct nds32_asm_insn *insn, fragS *fragP,
+                               const struct nds32_field *fld,
+                               bfd_boolean pseudo_hint)
 {
   struct nds32_relocs_pattern *reloc_ptr;
   struct nds32_relocs_group *group;
@@ -4311,10 +4964,32 @@ nds32_elf_build_relax_relation (fixS *fixP, expressionS *pexp, char* out,
   if (fld)
     sym = pexp->X_add_symbol;
 
-  if (pseudo_opcode)
+  if (pseudo_hint)
+    {
+      /* We cannot know how many instructions will be expanded for
+        the pseudo instruction here.  The first expanded instruction fills
+        the memory created by relax_hint.  The follower will created and link
+        here.  */
+      group = nds32_relax_hint_current;
+      while (group)
+       {
+         if (group->pattern->opcode == NULL)
+           nds32_elf_save_pseudo_pattern (fixP, insn, out, sym,
+                                          group->pattern, fragP);
+         else
+           {
+             group->pattern->next =
+               nds32_elf_save_pseudo_pattern (fixP, insn, out, sym,
+                                              NULL, fragP);
+             group->pattern = group->pattern->next;
+           }
+         group = group->next;
+       }
+    }
+  else if (pseudo_opcode)
     {
       /* Save instruction relation for pseudo instruction expanding pattern.  */
-      reloc_ptr = nds32_elf_save_pseudo_pattern (fixP, opcode, out, sym,
+      reloc_ptr = nds32_elf_save_pseudo_pattern (fixP, insn, out, sym,
                                                 NULL, fragP);
       if (!relocs_list)
        relocs_list = reloc_ptr;
@@ -4332,7 +5007,7 @@ nds32_elf_build_relax_relation (fixS *fixP, expressionS *pexp, char* out,
       group = nds32_relax_hint_current;
       while (group)
        {
-         nds32_elf_save_pseudo_pattern (fixP, opcode, out, sym,
+         nds32_elf_save_pseudo_pattern (fixP, insn, out, sym,
                                         group->pattern, fragP);
          group = group->next;
          free (nds32_relax_hint_current);
@@ -4348,40 +5023,199 @@ nds32_elf_build_relax_relation (fixS *fixP, expressionS *pexp, char* out,
 #define N32_MEM_EXT(insn) ((N32_OP6_MEM << 25) | insn)
 
 /* Relax pattern for link time relaxation.  */
+/* Relaxation types only! relocation types are not necessary.  */
+/* Refer to nds32_elf_record_fixup_exp ().  */
 
 static struct nds32_relax_hint_table relax_ls_table[] =
 {
   {
-    /* Set address: la -> sethi ori.  */
-    NDS32_RELAX_HINT_LA,       /* main_type */
-    8,                         /* relax_code_size */
-    {
-      OP6 (SETHI),
-      OP6 (ORI),
-    },                         /* relax_code_seq */
-    {
-      {0, 4, NDS32_HINT | NDS32_ADDEND, BFD_RELOC_NDS32_LOADSTORE},
-      {4, 4, NDS32_HINT | NDS32_ABS, BFD_RELOC_NDS32_INSN16}
-    }                          /* relax_fixup */
+    /* LA and Floating LSI.  */
+    .main_type = NDS32_RELAX_HINT_LA_FLSI,
+    .relax_code_size = 12,
+    .relax_code_seq =
+      {
+       OP6 (SETHI),
+       OP6 (ORI),
+       OP6 (LBI),
+      },
+    .relax_fixup =
+      {
+       {0, 4, NDS32_HINT | NDS32_ADDEND, BFD_RELOC_NDS32_LOADSTORE},
+       {4, 4, NDS32_HINT | NDS32_PTR, BFD_RELOC_NDS32_PTR},
+       {4, 4, NDS32_HINT | NDS32_INSN16, BFD_RELOC_NDS32_INSN16},
+       {8, 4, NDS32_HINT | NDS32_SYM, BFD_RELOC_NDS32_LSI},
+       {8, 4, NDS32_HINT | NDS32_ABS, BFD_RELOC_NDS32_PTR_RESOLVED},
+       {8, 4, NDS32_HINT | NDS32_INSN16, BFD_RELOC_NDS32_INSN16},
+       {0, 0, 0, 0}
+      }
   },
   {
-    /* Set address: l.w -> sethi ori.  */
-    NDS32_RELAX_HINT_LS,       /* main_type */
-    8,                         /* relax_code_size */
-    {
-      OP6 (SETHI),
-      OP6 (LBI),
-    },                         /* relax_code_seq */
-    {
-      {0, 4, NDS32_HINT | NDS32_ADDEND, BFD_RELOC_NDS32_LOADSTORE},
-      {4, 4, NDS32_HINT | NDS32_ABS, BFD_RELOC_NDS32_INSN16}
-    }                          /* relax_fixup */
+    /* Load Address / Load-Store (LALS).  */
+    .main_type = NDS32_RELAX_HINT_LALS,
+    .relax_code_size = 12,
+    .relax_code_seq =
+      {
+       OP6 (SETHI),
+       OP6 (ORI),
+       OP6 (LBI),
+      },
+    .relax_fixup =
+      {
+       {0, 4, NDS32_HINT | NDS32_ADDEND, BFD_RELOC_NDS32_LOADSTORE},
+       {4, 4, NDS32_HINT | NDS32_INSN16, BFD_RELOC_NDS32_INSN16},
+       {8, 4, NDS32_HINT | NDS32_INSN16, BFD_RELOC_NDS32_INSN16},
+       {0, 0, 0, 0}
+      }
   },
   {
-    0,
-    0,
-    {0},
-    {{0, 0 , 0, 0}}
+    /* B(AL) symbol@PLT  */
+    .main_type = NDS32_RELAX_HINT_LA_PLT,
+    .relax_code_size = 16,
+    .relax_code_seq =
+      {
+       OP6 (SETHI),
+       OP6 (ORI),
+       OP6 (ALU1),
+       OP6 (JREG),
+      },
+    .relax_fixup =
+      {
+       {0, 4, NDS32_HINT | NDS32_ADDEND, BFD_RELOC_NDS32_LOADSTORE},
+       {4, 4, NDS32_HINT | NDS32_PTR, BFD_RELOC_NDS32_PTR},
+       {8, 4, NDS32_HINT | NDS32_PTR, BFD_RELOC_NDS32_PTR},
+       {12, 4, NDS32_HINT | NDS32_ABS, BFD_RELOC_NDS32_PLT_GOT_SUFF},
+       {12, 4, NDS32_HINT | NDS32_ABS, BFD_RELOC_NDS32_PTR_RESOLVED},
+       {12, 4, NDS32_HINT | NDS32_INSN16, BFD_RELOC_NDS32_INSN16},
+       {0, 0, 0, 0}
+      }
+  },
+  {
+    /* LA (@GOT).  */
+    .main_type = NDS32_RELAX_HINT_LA_GOT,
+    .relax_code_size = 12,
+    .relax_code_seq =
+      {
+       OP6 (SETHI),
+       OP6 (ORI),
+       OP6 (MEM),
+      },
+    .relax_fixup =
+      {
+       {0, 4, NDS32_HINT | NDS32_ADDEND, BFD_RELOC_NDS32_LOADSTORE},
+       {4, 4, NDS32_HINT | NDS32_PTR, BFD_RELOC_NDS32_PTR},
+       {8, 4, NDS32_HINT | NDS32_ABS, BFD_RELOC_NDS32_PTR_RESOLVED},
+       {8, 4, NDS32_HINT | NDS32_ABS, BFD_RELOC_NDS32_GOT_SUFF},
+       {0, 0, 0, 0}
+      }
+  },
+  {
+    /* LA (@GOTOFF).  */
+    .main_type = NDS32_RELAX_HINT_LA_GOTOFF,
+    .relax_code_size = 16,
+    .relax_code_seq =
+      {
+       OP6 (SETHI),
+       OP6 (ORI),
+       OP6 (ALU1),
+       OP6 (MEM),
+      },
+    .relax_fixup =
+      {
+       {0, 4, NDS32_HINT | NDS32_ADDEND, BFD_RELOC_NDS32_LOADSTORE},
+       {4, 4, NDS32_HINT | NDS32_PTR, BFD_RELOC_NDS32_PTR},
+       {8, 4, NDS32_HINT | NDS32_ABS, BFD_RELOC_NDS32_PTR_RESOLVED},
+       {8, 4, NDS32_HINT | NDS32_ABS, BFD_RELOC_NDS32_GOTOFF_SUFF},
+       {12, 4, NDS32_HINT | NDS32_ABS, BFD_RELOC_NDS32_PTR_RESOLVED},
+       {12, 4, NDS32_HINT | NDS32_ABS, BFD_RELOC_NDS32_GOTOFF_SUFF},
+       {0, 0, 0, 0}
+      }
+  },
+  {
+    /* TLS LE LS|LA */
+    .main_type = NDS32_RELAX_HINT_TLS_LE_LS,
+    .relax_code_size = 16,
+    .relax_code_seq =
+      {
+       OP6(SETHI),
+       OP6(ORI),
+       OP6(MEM),
+       OP6(ALU1),
+      },
+    .relax_fixup =
+      {
+       {0, 4, NDS32_HINT | NDS32_ADDEND, BFD_RELOC_NDS32_LOADSTORE},
+       {4, 4, NDS32_HINT | NDS32_PTR_MULTIPLE, BFD_RELOC_NDS32_PTR},
+       {8, 4, NDS32_HINT | NDS32_ABS, BFD_RELOC_NDS32_PTR_RESOLVED},
+       {8, 4, NDS32_HINT | NDS32_SYM, BFD_RELOC_NDS32_TLS_LE_LS},
+       {12, 4, NDS32_HINT | NDS32_ABS, BFD_RELOC_NDS32_PTR_RESOLVED},
+       {12, 4, NDS32_HINT | NDS32_SYM, BFD_RELOC_NDS32_TLS_LE_ADD},
+       {0, 0, 0, 0}
+      }
+  },
+  {
+    /* TLS IE LA */
+    .main_type = NDS32_RELAX_HINT_TLS_IE_LA,
+    .relax_code_size = 8,
+    .relax_code_seq =
+      {
+       OP6(SETHI),
+       OP6(LBI),
+      },
+    .relax_fixup =
+      {
+       {0, 4, NDS32_HINT | NDS32_ADDEND, BFD_RELOC_NDS32_LOADSTORE},
+       {4, 4, NDS32_HINT | NDS32_INSN16, BFD_RELOC_NDS32_INSN16},
+       {0, 0, 0, 0}
+      }
+  },
+  {
+    /* TLS IEGP LA */
+    .main_type = NDS32_RELAX_HINT_TLS_IEGP_LA,
+    .relax_code_size = 12,
+    .relax_code_seq =
+      {
+       OP6 (SETHI),
+       OP6 (ORI),
+       OP6 (MEM),
+      },
+    .relax_fixup =
+      {
+       {0, 4, NDS32_HINT | NDS32_ADDEND, BFD_RELOC_NDS32_LOADSTORE},
+       {4, 4, NDS32_HINT | NDS32_PTR_PATTERN, BFD_RELOC_NDS32_PTR},
+       {8, 4, NDS32_HINT | NDS32_ABS, BFD_RELOC_NDS32_PTR_RESOLVED},
+       {8, 4, NDS32_HINT | NDS32_SYM, BFD_RELOC_NDS32_TLS_IEGP_LW},
+       {0, 0, 0, 0}
+      }
+  },
+  {
+    /* TLS DESC LS:  */
+    .main_type = NDS32_RELAX_HINT_TLS_DESC_LS,
+    .relax_code_size = 24,
+    .relax_code_seq =
+      {
+       OP6 (SETHI),
+       OP6 (ORI),
+       OP6 (ALU1),
+       OP6 (LBI),      /* load argument */
+       OP6 (JREG),
+       OP6 (MEM),      /* load/store variable or load argument */
+      },
+    .relax_fixup =
+      {
+       {0, 4, NDS32_HINT | NDS32_ADDEND, BFD_RELOC_NDS32_LOADSTORE},
+       {4, 4, NDS32_HINT | NDS32_PTR_PATTERN, BFD_RELOC_NDS32_PTR},
+       {8, 4, NDS32_HINT | NDS32_ABS, BFD_RELOC_NDS32_PTR_RESOLVED},
+       {8, 4, NDS32_HINT | NDS32_SYM, BFD_RELOC_NDS32_TLS_DESC_ADD},
+       {12, 4, NDS32_HINT | NDS32_SYM, BFD_RELOC_NDS32_TLS_DESC_FUNC},
+       {16, 4, NDS32_HINT | NDS32_SYM, BFD_RELOC_NDS32_TLS_DESC_CALL},
+       {20, 4, NDS32_HINT | NDS32_SYM_DESC_MEM, BFD_RELOC_NDS32_TLS_DESC_MEM},
+       {0, 0, 0, 0}
+      }
+  },
+  {
+    .main_type = 0,
+    .relax_code_seq = {0},
+    .relax_fixup = {{0, 0 , 0, 0}}
   }
 };
 
@@ -4428,136 +5262,204 @@ nds32_elf_sethi_range (struct nds32_relocs_pattern *pattern)
          break;
        case INSN_ORI:
          range = NDS32_LOADSTORE_IMM;
-         break;
-       default:
-         range = NDS32_LOADSTORE_NONE;
-         break;
-       }
-      if (range != NDS32_LOADSTORE_NONE)
-       break;
-      pattern = pattern->next;
-    }
-  return range;
-}
-
-/* The args means: instruction size, the 1st instruction is converted to 16 or
-   not, optimize option, 16 bit instruction is enable.  */
-#define SET_ADDEND(size, convertible, optimize, insn16_on) \
-  (((size) & 0xff) | ((convertible) ? 1 << 31 : 0) \
-   | ((optimize) ? 1<< 30 : 0) | (insn16_on ? 1 << 29 : 0))
-
-static void
-nds32_set_elf_flags_by_insn (struct nds32_asm_insn * insn)
-{
-  /* Set E_NDS32_HAS_EXT_INST.  */
-  if (insn->opcode->attr & NASM_ATTR_PERF_EXT)
-    {
-      if (nds32_perf_ext)
-       nds32_elf_flags |= E_NDS32_HAS_EXT_INST;
-      else
-       as_bad (_("instruction %s requires enabling performance extension"),
-               insn->opcode->opcode);
-    }
-  else if (insn->opcode->attr & NASM_ATTR_PERF2_EXT)
-    {
-      if (nds32_perf_ext2)
-       nds32_elf_flags |= E_NDS32_HAS_EXT2_INST;
-      else
-       as_bad (_("instruction %s requires enabling performance extension II"),
-               insn->opcode->opcode);
-    }
-  else if (insn->opcode->attr & NASM_ATTR_AUDIO_ISAEXT)
-    {
-      if (nds32_audio_ext)
-       nds32_elf_flags |= E_NDS32_HAS_AUDIO_INST;
-      else
-       as_bad (_("instruction %s requires enabling AUDIO extension"),
-               insn->opcode->opcode);
-    }
-  else if (insn->opcode->attr & NASM_ATTR_STR_EXT)
-    {
-      if (nds32_string_ext)
-       nds32_elf_flags |= E_NDS32_HAS_STRING_INST;
-      else
-       as_bad (_("instruction %s requires enabling STRING extension"),
-               insn->opcode->opcode);
-    }
-  else if ((insn->opcode->attr & NASM_ATTR_DIV)
-          && (insn->opcode->attr & NASM_ATTR_DXREG))
-    {
-      if (nds32_div && nds32_dx_regs)
-       nds32_elf_flags |= E_NDS32_HAS_DIV_DX_INST;
-      else
-       as_bad (_("instruction %s requires enabling DIV & DX_REGS extension"),
-               insn->opcode->opcode);
-    }
-  else if (insn->opcode->attr & NASM_ATTR_FPU)
-    {
-      if (nds32_fpu_sp_ext || nds32_fpu_dp_ext)
-       {
-         if (!(nds32_elf_flags & (E_NDS32_HAS_FPU_INST | E_NDS32_HAS_FPU_DP_INST)))
-           nds32_fpu_com = 1;
-       }
-      else
-       as_bad (_("instruction %s requires enabling FPU extension"),
-               insn->opcode->opcode);
-    }
-  else if (insn->opcode->attr & NASM_ATTR_FPU_SP_EXT)
-    {
-      if (nds32_fpu_sp_ext)
-       nds32_elf_flags |= E_NDS32_HAS_FPU_INST;
-      else
-       as_bad (_("instruction %s requires enabling FPU_SP extension"),
-               insn->opcode->opcode);
-    }
-  else if ((insn->opcode->attr & NASM_ATTR_FPU_SP_EXT)
-          && (insn->opcode->attr & NASM_ATTR_MAC))
-    {
-      if (nds32_fpu_sp_ext && nds32_mac)
-       {
-         nds32_elf_flags |= E_NDS32_HAS_FPU_MAC_INST;
-         nds32_elf_flags |= E_NDS32_HAS_FPU_INST;
+         break;
+       default:
+         range = NDS32_LOADSTORE_NONE;
+         break;
        }
-      else
-       as_bad (_("instruction %s requires enabling FPU_MAC extension"),
-               insn->opcode->opcode);
-    }
-  else if (insn->opcode->attr & NASM_ATTR_FPU_DP_EXT)
-    {
-      if (nds32_fpu_dp_ext)
-       nds32_elf_flags |= E_NDS32_HAS_FPU_DP_INST;
-      else
-       as_bad (_("instruction %s requires enabling FPU_DP extension"),
-               insn->opcode->opcode);
+      if (range != NDS32_LOADSTORE_NONE)
+       break;
+      pattern = pattern->next;
     }
-  else if ((insn->opcode->attr & NASM_ATTR_FPU_DP_EXT)
-          && (insn->opcode->attr & NASM_ATTR_MAC))
+  return range;
+}
+
+/* The args means: instruction size, the 1st instruction is converted to 16 or
+   not, optimize option, 16 bit instruction is enable.  */
+
+#define SET_ADDEND(size, convertible, optimize, insn16_on) \
+  (((size) & 0xff) | ((convertible) ? 1 << 31 : 0) \
+   | ((optimize) ? 1<< 30 : 0) | (insn16_on ? 1 << 29 : 0))
+#define MAC_COMBO (E_NDS32_HAS_FPU_MAC_INST|E_NDS32_HAS_MAC_DX_INST)
+
+static void
+nds32_set_elf_flags_by_insn (struct nds32_asm_insn * insn)
+{
+  static int skip_flags = NASM_ATTR_FPU_FMA
+    | NASM_ATTR_BRANCH | NASM_ATTR_SATURATION_EXT
+    | NASM_ATTR_GPREL | NASM_ATTR_DXREG
+    | NASM_ATTR_ISA_V1 | NASM_ATTR_ISA_V2
+    | NASM_ATTR_ISA_V3 | NASM_ATTR_ISA_V3M
+    | NASM_ATTR_PCREL;
+
+  int new_flags = insn->opcode->attr & ~skip_flags;
+  while (new_flags)
     {
-      if (nds32_fpu_dp_ext && nds32_mac)
+      int next = 1 << (ffs (new_flags) - 1);
+      new_flags &= ~next;
+      switch (next)
        {
-         nds32_elf_flags |= E_NDS32_HAS_FPU_MAC_INST;
-         nds32_elf_flags |= E_NDS32_HAS_FPU_DP_INST;
+       case NASM_ATTR_PERF_EXT:
+         {
+           if (nds32_perf_ext)
+             {
+               nds32_elf_flags |= E_NDS32_HAS_EXT_INST;
+               skip_flags |= NASM_ATTR_PERF_EXT;
+             }
+           else
+             as_bad (_("instruction %s requires enabling performance "
+                       "extension"), insn->opcode->opcode);
+         }
+         break;
+       case NASM_ATTR_PERF2_EXT:
+         {
+           if (nds32_perf_ext2)
+             {
+               nds32_elf_flags |= E_NDS32_HAS_EXT2_INST;
+               skip_flags |= NASM_ATTR_PERF2_EXT;
+             }
+           else
+             as_bad (_("instruction %s requires enabling performance "
+                       "extension II"), insn->opcode->opcode);
+         }
+         break;
+       case NASM_ATTR_AUDIO_ISAEXT:
+         {
+           if (nds32_audio_ext)
+             {
+               nds32_elf_flags |= E_NDS32_HAS_AUDIO_INST;
+               skip_flags |= NASM_ATTR_AUDIO_ISAEXT;
+             }
+           else
+             as_bad (_("instruction %s requires enabling AUDIO extension"),
+                     insn->opcode->opcode);
+         }
+         break;
+       case NASM_ATTR_STR_EXT:
+         {
+           if (nds32_string_ext)
+             {
+               nds32_elf_flags |= E_NDS32_HAS_STRING_INST;
+               skip_flags |= NASM_ATTR_STR_EXT;
+             }
+           else
+             as_bad (_("instruction %s requires enabling STRING extension"),
+                     insn->opcode->opcode);
+         }
+         break;
+       case NASM_ATTR_DIV:
+         {
+           if (insn->opcode->attr & NASM_ATTR_DXREG)
+             {
+               if (nds32_div && nds32_dx_regs)
+                 {
+                   nds32_elf_flags |= E_NDS32_HAS_DIV_DX_INST;
+                   skip_flags |= NASM_ATTR_DIV;
+                 }
+               else
+                 as_bad (_("instruction %s requires enabling DIV & DX_REGS "
+                           "extension"), insn->opcode->opcode);
+             }
+         }
+         break;
+       case NASM_ATTR_FPU:
+         {
+           if (nds32_fpu_sp_ext || nds32_fpu_dp_ext)
+             {
+               if (!(nds32_elf_flags
+                     & (E_NDS32_HAS_FPU_INST | E_NDS32_HAS_FPU_DP_INST)))
+                 nds32_fpu_com = 1;
+               skip_flags |= NASM_ATTR_FPU;
+             }
+           else
+             as_bad (_("instruction %s requires enabling FPU extension"),
+                     insn->opcode->opcode);
+         }
+         break;
+       case NASM_ATTR_FPU_SP_EXT:
+         {
+           if (nds32_fpu_sp_ext)
+             {
+               nds32_elf_flags |= E_NDS32_HAS_FPU_INST;
+               skip_flags |= NASM_ATTR_FPU_SP_EXT;
+             }
+           else
+             as_bad (_("instruction %s requires enabling FPU_SP extension"),
+                     insn->opcode->opcode);
+         }
+         break;
+       case NASM_ATTR_FPU_DP_EXT:
+         {
+           if (nds32_fpu_dp_ext)
+             {
+               nds32_elf_flags |= E_NDS32_HAS_FPU_DP_INST;
+               skip_flags |= NASM_ATTR_FPU_DP_EXT;
+             }
+           else
+             as_bad (_("instruction %s requires enabling FPU_DP extension"),
+                     insn->opcode->opcode);
+         }
+         break;
+       case NASM_ATTR_MAC:
+         {
+           if (insn->opcode->attr & NASM_ATTR_FPU_SP_EXT)
+             {
+               if (nds32_fpu_sp_ext && nds32_mac)
+                 nds32_elf_flags |= E_NDS32_HAS_FPU_MAC_INST;
+               else
+                 as_bad (_("instruction %s requires enabling FPU_MAC "
+                           "extension"), insn->opcode->opcode);
+             }
+           else if (insn->opcode->attr & NASM_ATTR_FPU_DP_EXT)
+             {
+               if (nds32_fpu_dp_ext && nds32_mac)
+                 nds32_elf_flags |= E_NDS32_HAS_FPU_MAC_INST;
+               else
+                 as_bad (_("instruction %s requires enabling FPU_MAC "
+                           "extension"), insn->opcode->opcode);
+             }
+           else if (insn->opcode->attr & NASM_ATTR_DXREG)
+             {
+               if (nds32_dx_regs && nds32_mac)
+                 nds32_elf_flags |= E_NDS32_HAS_MAC_DX_INST;
+               else
+                 as_bad (_("instruction %s requires enabling DX_REGS "
+                           "extension"), insn->opcode->opcode);
+             }
+
+           if (MAC_COMBO == (MAC_COMBO & nds32_elf_flags))
+             skip_flags |= NASM_ATTR_MAC;
+         }
+         break;
+       case NASM_ATTR_DSP_ISAEXT:
+         {
+           if (nds32_dsp_ext)
+             {
+               nds32_elf_flags |= E_NDS32_HAS_DSP_INST;
+               skip_flags |= NASM_ATTR_DSP_ISAEXT;
+             }
+           else
+             as_bad (_("instruction %s requires enabling dsp extension"),
+                     insn->opcode->opcode);
+         }
+         break;
+       case NASM_ATTR_ZOL:
+         {
+           if (nds32_zol_ext)
+             {
+               nds32_elf_flags |= E_NDS32_HAS_ZOL;
+               skip_flags |= NASM_ATTR_ZOL;
+             }
+           else
+             as_bad (_("instruction %s requires enabling zol extension"),
+                     insn->opcode->opcode);
+         }
+         break;
+       default:
+         as_bad (_("internal error: unknown instruction attribute: 0x%08x"),
+                 next);
        }
-      else
-       as_bad (_("instruction %s requires enabling FPU_MAC extension"),
-               insn->opcode->opcode);
-    }
-  /* TODO: FPU_BOTH */
-  else if ((insn->opcode->attr & NASM_ATTR_MAC)
-          && (insn->opcode->attr & NASM_ATTR_DXREG))
-    {
-      if (nds32_mac && nds32_dx_regs)
-       nds32_elf_flags |= E_NDS32_HAS_MAC_DX_INST;
-      else
-       as_bad (_("instruction %s requires enabling DX_REGS extension"),
-               insn->opcode->opcode);
-    }
-  /* TODO: for DX_REG set but not for MAC, DIV, AUDIO */
-  else if (insn->opcode->attr & NASM_ATTR_IFC_EXT)
-    {
-      nds32_elf_flags |= E_NDS32_HAS_IFC_INST;
     }
-  /* TODO: E_NDS32_HAS_SATURATION_INST */
 }
 
 /* Flag for analysis relaxation type.  */
@@ -4572,97 +5474,199 @@ enum nds32_insn_type
   N32_RELAX_ORI = (1 << 5),
   N32_RELAX_MEM = (1 << 6),
   N32_RELAX_MOVI = (1 << 7),
+  N32_RELAX_ALU1 = (1 << 8),
+  N32_RELAX_16BIT = (1 << 9),
 };
 
 struct nds32_hint_map
 {
+  /* the preamble relocation */
   bfd_reloc_code_real_type hi_type;
-  char *opc;
+  /* mnemonic */
+  const char *opc;
+  /* relax pattern ID */
   enum nds32_relax_hint_type hint_type;
+  /* range */
   enum nds32_br_range range;
+  /* pattern character flags */
   enum nds32_insn_type insn_list;
+  /* optional pattern character flags */
+  enum nds32_insn_type option_list;
 };
 
 /* Table to match instructions with hint and relax pattern.  */
 
 static struct nds32_hint_map hint_map [] =
 {
-    {
-      /* LONGCALL4.  */
-      BFD_RELOC_NDS32_HI20,
-      "jal",
-      NDS32_RELAX_HINT_NONE,
-      BR_RANGE_U4G,
-      N32_RELAX_SETHI | N32_RELAX_ORI | N32_RELAX_CALL
-    },
-    {
-      /* LONGCALL5.  */
-      _dummy_first_bfd_reloc_code_real,
-      "bgezal",
-      NDS32_RELAX_HINT_NONE,
-      BR_RANGE_S16M,
-      N32_RELAX_BR | N32_RELAX_CALL
-    },
-    {
-      /* LONGCALL6.  */
-      BFD_RELOC_NDS32_HI20,
-      "bgezal",
-      NDS32_RELAX_HINT_NONE,
-      BR_RANGE_U4G,
-      N32_RELAX_BR | N32_RELAX_SETHI | N32_RELAX_ORI | N32_RELAX_CALL
-    },
-    {
-      /* LONGJUMP4.  */
-      BFD_RELOC_NDS32_HI20,
-      "j",
-      NDS32_RELAX_HINT_NONE,
-      BR_RANGE_U4G,
-      N32_RELAX_SETHI | N32_RELAX_ORI | N32_RELAX_JUMP
-    },
-    {
-      /* LONGJUMP5.  */
-      /* There is two kinds of veriation of LONGJUMP5.  One of them
-        generate EMPTY relocation for converted INSN16 if needed.
-        But we don't distinguish them here.  */
-      _dummy_first_bfd_reloc_code_real,
-      "beq",
-      NDS32_RELAX_HINT_NONE,
-      BR_RANGE_S16M,
-      N32_RELAX_BR | N32_RELAX_JUMP
-    },
-    {
-      /* LONGJUMP6.  */
-      BFD_RELOC_NDS32_HI20,
-      "beq",
-      NDS32_RELAX_HINT_NONE,
-      BR_RANGE_U4G,
-      N32_RELAX_SETHI | N32_RELAX_ORI | N32_RELAX_BR | N32_RELAX_JUMP
-    },
-    {
-      /* LONGJUMP7.  */
-      _dummy_first_bfd_reloc_code_real,
-      "beqc",
-      NDS32_RELAX_HINT_NONE,
-      BR_RANGE_S16K,
-      N32_RELAX_MOVI | N32_RELAX_BR
-    },
-    {
-      /* LOADSTORE ADDRESS.  */
-      BFD_RELOC_NDS32_HI20,
-      NULL,
-      NDS32_RELAX_HINT_LA,
-      BR_RANGE_U4G,
-      N32_RELAX_SETHI | N32_RELAX_ORI
-    },
-    {
-      /* LOADSTORE ADDRESS.  */
-      BFD_RELOC_NDS32_HI20,
-      NULL,
-      NDS32_RELAX_HINT_LS,
-      BR_RANGE_U4G,
-      N32_RELAX_SETHI | N32_RELAX_LSI
-    },
-    {0, NULL, 0, 0 ,0}
+  {
+    /* LONGCALL4.  */
+    BFD_RELOC_NDS32_HI20,
+    "jal",
+    NDS32_RELAX_HINT_NONE,
+    BR_RANGE_U4G,
+    N32_RELAX_SETHI | N32_RELAX_ORI | N32_RELAX_CALL,
+    0,
+  },
+  {
+    /* LONGCALL5.  */
+    _dummy_first_bfd_reloc_code_real,
+    "bgezal",
+    NDS32_RELAX_HINT_NONE,
+    BR_RANGE_S16M,
+    N32_RELAX_BR | N32_RELAX_CALL,
+    0,
+  },
+  {
+    /* LONGCALL6.  */
+    BFD_RELOC_NDS32_HI20,
+    "bgezal",
+    NDS32_RELAX_HINT_NONE,
+    BR_RANGE_U4G,
+    N32_RELAX_BR | N32_RELAX_SETHI | N32_RELAX_ORI | N32_RELAX_CALL,
+    0,
+  },
+  {
+    /* LONGJUMP4.  */
+    BFD_RELOC_NDS32_HI20,
+    "j",
+    NDS32_RELAX_HINT_NONE,
+    BR_RANGE_U4G,
+    N32_RELAX_SETHI | N32_RELAX_ORI | N32_RELAX_JUMP,
+    0,
+  },
+  {
+    /* LONGJUMP5.  */
+    /* There is two kinds of variation of LONGJUMP5.  One of them
+       generate EMPTY relocation for converted INSN16 if needed.
+       But we don't distinguish them here.  */
+    _dummy_first_bfd_reloc_code_real,
+    "beq",
+    NDS32_RELAX_HINT_NONE,
+    BR_RANGE_S16M,
+    N32_RELAX_BR | N32_RELAX_JUMP,
+    0,
+  },
+  {
+    /* LONGJUMP6.  */
+    BFD_RELOC_NDS32_HI20,
+    "beq",
+    NDS32_RELAX_HINT_NONE,
+    BR_RANGE_U4G,
+    N32_RELAX_SETHI | N32_RELAX_ORI | N32_RELAX_BR | N32_RELAX_JUMP,
+    0,
+  },
+  {
+    /* LONGJUMP7.  */
+    _dummy_first_bfd_reloc_code_real,
+    "beqc",
+    NDS32_RELAX_HINT_NONE,
+    BR_RANGE_S16K,
+    N32_RELAX_MOVI | N32_RELAX_BR,
+    0,
+  },
+  {
+    /* LONGCALL (BAL|JR|LA symbol@PLT).  */
+    BFD_RELOC_NDS32_PLT_GOTREL_HI20,
+    NULL,
+    NDS32_RELAX_HINT_LA_PLT,
+    BR_RANGE_U4G,
+    N32_RELAX_SETHI | N32_RELAX_ORI,
+    N32_RELAX_ALU1 | N32_RELAX_CALL | N32_RELAX_JUMP,
+  },
+  /* relative issue: #12566 */
+  {
+    /* LA and Floating LSI.  */
+    BFD_RELOC_NDS32_HI20,
+    NULL,
+    NDS32_RELAX_HINT_LA_FLSI,
+    BR_RANGE_U4G,
+    N32_RELAX_SETHI | N32_RELAX_ORI | N32_RELAX_LSI,
+    0,
+  },
+  /* relative issue: #11685 #11602 */
+  {
+    /* load address / load-store (LALS).  */
+    BFD_RELOC_NDS32_HI20,
+    NULL,
+    NDS32_RELAX_HINT_LALS,
+    BR_RANGE_U4G,
+    N32_RELAX_SETHI,
+    N32_RELAX_ORI | N32_RELAX_LSI,
+  },
+  {
+    /* setup $GP (_GLOBAL_OFFSET_TABLE_)  */
+    BFD_RELOC_NDS32_GOTPC_HI20,
+    NULL,
+    NDS32_RELAX_HINT_LALS,
+    BR_RANGE_U4G,
+    N32_RELAX_SETHI | N32_RELAX_ORI,
+    0,
+  },
+  {
+    /* GOT LA/LS (symbol@GOT)  */
+    BFD_RELOC_NDS32_GOT_HI20,
+    NULL,
+    NDS32_RELAX_HINT_LA_GOT,
+    BR_RANGE_U4G,
+    N32_RELAX_SETHI | N32_RELAX_ORI,
+    N32_RELAX_MEM,
+  },
+  {
+    /* GOTOFF LA/LS (symbol@GOTOFF)  */
+    BFD_RELOC_NDS32_GOTOFF_HI20,
+    NULL,
+    NDS32_RELAX_HINT_LA_GOTOFF,
+    BR_RANGE_U4G,
+    N32_RELAX_SETHI | N32_RELAX_ORI,
+    N32_RELAX_ALU1  | N32_RELAX_MEM, /* | N32_RELAX_LSI, */
+  },
+  {
+    /* TLS LE LA|LS (@TPOFF)  */
+    BFD_RELOC_NDS32_TLS_LE_HI20,
+    NULL,
+    NDS32_RELAX_HINT_TLS_LE_LS,
+    BR_RANGE_U4G,
+    N32_RELAX_SETHI | N32_RELAX_ORI,
+    N32_RELAX_ALU1 | N32_RELAX_MEM,
+  },
+  {
+    /* TLS IE LA */
+    BFD_RELOC_NDS32_TLS_IE_HI20,
+    NULL,
+    NDS32_RELAX_HINT_TLS_IE_LA,
+    BR_RANGE_U4G,
+    N32_RELAX_SETHI | N32_RELAX_LSI,
+    0,
+  },
+{
+    /* TLS IE LS */
+    BFD_RELOC_NDS32_TLS_IE_HI20,
+    NULL,
+    NDS32_RELAX_HINT_TLS_IE_LS,
+    BR_RANGE_U4G,
+    N32_RELAX_SETHI | N32_RELAX_LSI | N32_RELAX_MEM,
+    0,
+  },
+  {
+    /* TLS IEGP LA */
+    BFD_RELOC_NDS32_TLS_IEGP_HI20,
+    NULL,
+    NDS32_RELAX_HINT_TLS_IEGP_LA,
+    BR_RANGE_U4G,
+    N32_RELAX_SETHI | N32_RELAX_ORI | N32_RELAX_MEM,
+    0,
+  },
+  {
+    /* TLS DESC LS */
+    BFD_RELOC_NDS32_TLS_DESC_HI20,
+    NULL,
+    NDS32_RELAX_HINT_TLS_DESC_LS,
+    BR_RANGE_U4G,
+    N32_RELAX_SETHI | N32_RELAX_ORI | N32_RELAX_ALU1 | N32_RELAX_CALL,
+    N32_RELAX_LSI | N32_RELAX_MEM,
+  },
+  /* last one */
+  {0, NULL, 0, 0 ,0, 0}
 };
 
 /* Find the relaxation pattern according to instructions.  */
@@ -4674,7 +5678,7 @@ nds32_find_reloc_table (struct nds32_relocs_pattern *relocs_pattern,
   unsigned int opcode, seq_size;
   enum nds32_br_range range;
   struct nds32_relocs_pattern *pattern, *hi_pattern = NULL;
-  char *opc = NULL;
+  const char *opc = NULL;
   relax_info_t *relax_info = NULL;
   nds32_relax_fixup_info_t *fixup_info, *hint_fixup;
   enum nds32_relax_hint_type hint_type = NDS32_RELAX_HINT_NONE;
@@ -4683,7 +5687,7 @@ nds32_find_reloc_table (struct nds32_relocs_pattern *relocs_pattern,
   enum nds32_insn_type relax_type = 0;
   struct nds32_hint_map *map_ptr = hint_map;
   unsigned int i;
-  char *check_insn[] =
+  const char *check_insn[] =
     { "bnes38", "beqs38", "bnez38", "bnezs8", "beqz38", "beqzs8" };
 
   /* TODO: PLT GOT.  */
@@ -4704,6 +5708,9 @@ nds32_find_reloc_table (struct nds32_relocs_pattern *relocs_pattern,
            case N32_OP6_MEM:
              relax_type |= N32_RELAX_MEM;
              break;
+           case N32_OP6_ALU1:
+             relax_type |= N32_RELAX_ALU1;
+             break;
            case N32_OP6_ORI:
              relax_type |= N32_RELAX_ORI;
              break;
@@ -4725,6 +5732,8 @@ nds32_find_reloc_table (struct nds32_relocs_pattern *relocs_pattern,
            case N32_OP6_SWI:
            case N32_OP6_LWC:
            case N32_OP6_SWC:
+           case N32_OP6_LDC:
+           case N32_OP6_SDC:
              relax_type |= N32_RELAX_LSI;
              break;
            case N32_OP6_JREG:
@@ -4747,18 +5756,20 @@ nds32_find_reloc_table (struct nds32_relocs_pattern *relocs_pattern,
        }
       else
        {
-         /* 2 byte instruction.  Compare by opcode name because the opcode of
-            2byte instruction is not regular.  */
-         for (i = 0; i < sizeof (check_insn) / sizeof (check_insn[0]); i++)
+         /* 2 byte instruction.  Compare by opcode name because
+            the opcode of 2byte instruction is not regular.  */
+         int is_matched = 0;
+         for (i = 0; i < ARRAY_SIZE (check_insn); i++)
            {
              if (strcmp (pattern->opcode->opcode, check_insn[i]) == 0)
                {
                  relax_type |= N32_RELAX_BR;
+                 is_matched += 1;
                  break;
                }
            }
-         if (strcmp (pattern->opcode->opcode, "movi55") == 0)
-           relax_type |= N32_RELAX_MOVI;
+         if (!is_matched)
+           relax_type |= N32_RELAX_16BIT;
        }
       pattern = pattern->next;
     }
@@ -4766,23 +5777,35 @@ nds32_find_reloc_table (struct nds32_relocs_pattern *relocs_pattern,
   /* Analysis instruction flag to choose relaxation table.  */
   while (map_ptr->insn_list != 0)
     {
-      if (map_ptr->insn_list == relax_type
-         && (!hi_pattern
-             || (hi_pattern->fixP
-                 && hi_pattern->fixP->fx_r_type == map_ptr->hi_type)))
+      struct nds32_hint_map *hint = map_ptr++;
+      enum nds32_insn_type must = hint->insn_list;
+      enum nds32_insn_type optional = hint->option_list;
+      enum nds32_insn_type extra;
+
+      if (must != (must & relax_type))
+       continue;
+
+      extra = relax_type ^ must;
+      if (extra != (extra & optional))
+       continue;
+
+      if (!hi_pattern
+         || (hi_pattern->fixP
+             && hi_pattern->fixP->fx_r_type == hint->hi_type))
        {
-         opc = map_ptr->opc;
-         hint_type = map_ptr->hint_type;
-         range = map_ptr->range;
+         opc = hint->opc;
+         hint_type = hint->hint_type;
+         range = hint->range;
+         map_ptr = hint;
          break;
        }
-      map_ptr++;
     }
 
   if (map_ptr->insn_list == 0)
     {
-      as_warn (_("Can not find match relax hint. line : %d"),
-              relocs_pattern->frag->fr_line);
+      if (!nds32_pic)
+       as_warn (_("Can not find match relax hint.  Line: %d"),
+                relocs_pattern->frag->fr_line);
       return FALSE;
     }
 
@@ -4833,7 +5856,7 @@ nds32_find_reloc_table (struct nds32_relocs_pattern *relocs_pattern,
     }
   /* Clear final relocation.  */
   memset (hint_fixup, 0, sizeof (nds32_relax_fixup_info_t));
-  /* Copy code sequance.  */
+  /* Copy code sequence.  */
   memcpy (hint_code, code_seq, seq_size);
   return TRUE;
 }
@@ -4841,12 +5864,14 @@ nds32_find_reloc_table (struct nds32_relocs_pattern *relocs_pattern,
 /* Because there are a lot of variant of load-store, check
    all these type here.  */
 
-#define CLEAN_REG(insn) ((insn) & 0xff0003ff)
+#define CLEAN_REG(insn) ((insn) & 0xfe0003ff)
+#define GET_OPCODE(insn) ((insn) & 0xfe000000)
+
 static bfd_boolean
 nds32_match_hint_insn (struct nds32_opcode *opcode, uint32_t seq)
 {
-  char *check_insn[] =
-    { "bnes38", "beqs38", "bnez38", "bnezs8", "beqz38", "beqzs8" };
+  const char *check_insn[] =
+    { "bnes38", "beqs38", "bnez38", "bnezs8", "beqz38", "beqzs8", "jral5" };
   uint32_t insn = opcode->value;
   unsigned int i;
 
@@ -4862,22 +5887,23 @@ nds32_match_hint_insn (struct nds32_opcode *opcode, uint32_t seq)
       if (insn == OP6 (LBI) || insn == OP6 (SBI) || insn == OP6 (LBSI)
          || insn == OP6 (LHI) || insn == OP6 (SHI) || insn == OP6 (LHSI)
          || insn == OP6 (LWI) || insn == OP6 (SWI)
-         || insn == OP6 (LWC) || insn == OP6 (SWC))
-        return TRUE;
+         || insn == OP6 (LWC) || insn == OP6 (SWC)
+         || insn == OP6 (LDC) || insn == OP6 (SDC))
+       return TRUE;
       break;
     case OP6 (BR2):
       /* This is for LONGCALL5 and LONGCALL6.  */
       if (insn == OP6 (BR2))
-        return TRUE;
+       return TRUE;
       break;
     case OP6 (BR1):
       /* This is for LONGJUMP5 and LONGJUMP6.  */
       if (opcode->isize == 4
          && (insn == OP6 (BR1) || insn == OP6 (BR2) || insn == OP6 (BR3)))
-        return TRUE;
+       return TRUE;
       else if (opcode->isize == 2)
        {
-         for (i = 0; i < sizeof (check_insn) / sizeof (check_insn[0]); i++)
+         for (i = 0; i < ARRAY_SIZE (check_insn); i++)
            if (strcmp (opcode->opcode, check_insn[i]) == 0)
              return TRUE;
        }
@@ -4885,8 +5911,28 @@ nds32_match_hint_insn (struct nds32_opcode *opcode, uint32_t seq)
     case OP6 (MOVI):
       /* This is for LONGJUMP7.  */
       if (opcode->isize == 2 && strcmp (opcode->opcode, "movi55") == 0)
-        return TRUE;
+       return TRUE;
       break;
+    case OP6 (MEM):
+      if (OP6 (MEM) == GET_OPCODE (insn))
+       return TRUE;
+      break;
+    case OP6 (JREG):
+      /* bit 24: N32_JI_JAL  */ /* feed me!  */
+      if ((insn & ~(N32_BIT (24))) == JREG (JRAL))
+       return TRUE;
+      break;
+    default:
+      if (opcode->isize == 2)
+       {
+         for (i = 0; i < ARRAY_SIZE (check_insn); i++)
+           if (strcmp (opcode->opcode, check_insn[i]) == 0)
+             return TRUE;
+
+         if ((strcmp (opcode->opcode, "add5.pc") == 0) ||
+             (strcmp (opcode->opcode, "add45") == 0))
+           return TRUE;
+       }
     }
   return FALSE;
 }
@@ -4894,7 +5940,7 @@ nds32_match_hint_insn (struct nds32_opcode *opcode, uint32_t seq)
 /* Append relax relocation for link time relaxing.  */
 
 static void
-nds32_elf_append_relax_relocs (const char *key ATTRIBUTE_UNUSED, void *value)
+nds32_elf_append_relax_relocs (const char *key, void *value)
 {
   struct nds32_relocs_pattern *relocs_pattern =
     (struct nds32_relocs_pattern *) value;
@@ -4907,12 +5953,13 @@ nds32_elf_append_relax_relocs (const char *key ATTRIBUTE_UNUSED, void *value)
   struct nds32_relax_hint_table hint_info;
   nds32_relax_fixup_info_t *hint_fixup, *fixup_now;
   size_t fixup_size;
-  offsetT branch_offset;
+  offsetT branch_offset, hi_branch_offset = 0;
   fixS *fixP;
   int range, offset;
   unsigned int ptr_offset, hint_count, relax_code_size, count = 0;
   uint32_t *code_seq, code_insn;
   char *where;
+  int pcrel;
 
   if (!relocs_pattern)
     return;
@@ -4927,6 +5974,7 @@ nds32_elf_append_relax_relocs (const char *key ATTRIBUTE_UNUSED, void *value)
       if (pattern_now->opcode->value == OP6 (SETHI))
        {
          hi_sym = pattern_now->sym;
+         hi_branch_offset = pattern_now->fixP->fx_offset;
          break;
        }
       pattern_now = pattern_now->next;
@@ -4943,15 +5991,37 @@ nds32_elf_append_relax_relocs (const char *key ATTRIBUTE_UNUSED, void *value)
   relax_code_size = hint_info.relax_code_size;
   pattern_now = relocs_pattern;
 
+#ifdef NDS32_LINUX_TOOLCHAIN
+  /* prepare group relocation ID (number).  */
+  long group_id = 0;
+  if (key)
+    {
+      /* convert .relax_hint key to number */
+      errno = 0;
+      group_id = strtol (key, NULL, 10);
+      if ((errno == ERANGE && (group_id == LONG_MAX || group_id == LONG_MIN))
+         || (errno != 0 && group_id == 0))
+       {
+         as_bad (_("Internal error: .relax_hint KEY is not a number!"));
+         goto restore;
+       }
+    }
+#endif
+
   /* Insert relaxation.  */
   exp.X_op = O_symbol;
 
+  /* For each instruction in the hint group.  */
   while (pattern_now)
     {
+      if (count >= relax_code_size / 4)
+       count = 0;
+
       /* Choose the match fixup by instruction.  */
       code_insn = CLEAN_REG (*(code_seq + count));
       if (!nds32_match_hint_insn (pattern_now->opcode, code_insn))
        {
+         /* Try search from head again */
          count = 0;
          code_insn = CLEAN_REG (*(code_seq + count));
 
@@ -4960,8 +6030,11 @@ nds32_elf_append_relax_relocs (const char *key ATTRIBUTE_UNUSED, void *value)
              count++;
              if (count >= relax_code_size / 4)
                {
-                 as_bad (_("Internal error: Relax hint error. %s: %x"),
-                         now_seg->name, pattern_now->opcode->value);
+                 as_bad (_("Internal error: Relax hint (%s) error. %s: %s (%x)"),
+                         key,
+                         now_seg->name,
+                         pattern_now->opcode->opcode,
+                         pattern_now->opcode->value);
                  goto restore;
                }
              code_insn = CLEAN_REG (*(code_seq + count));
@@ -4993,6 +6066,7 @@ nds32_elf_append_relax_relocs (const char *key ATTRIBUTE_UNUSED, void *value)
        {
          /* Set the real instruction size in element.  */
          fixup_size = pattern_now->opcode->isize;
+         pcrel = ((fixup_now->ramp & NDS32_PCREL) != 0) ? 1 : 0;
          if (fixup_now->ramp & NDS32_FIX)
            {
              /* Convert original relocation.  */
@@ -5056,7 +6130,109 @@ nds32_elf_append_relax_relocs (const char *key ATTRIBUTE_UNUSED, void *value)
            {
              /* For EMPTY relocation save the true symbol.  */
              exp.X_add_symbol = hi_sym;
-             exp.X_add_number = branch_offset;
+             exp.X_add_number = hi_branch_offset;
+           }
+         else if (NDS32_SYM_DESC_MEM & fixup_now->ramp)
+           {
+             /* Do the same as NDS32_SYM.  */
+             exp.X_add_symbol = hi_sym;
+             exp.X_add_number = hi_branch_offset;
+
+             /* Extra to NDS32_SYM.  */
+             /* Detect if DESC_FUNC relax type do apply.  */
+             if ((REG_GP == N32_RA5 (pattern_now->insn))
+                 || (REG_GP == N32_RB5 (pattern_now->insn)))
+               {
+                 fixP = fix_new_exp (fragP, where - fragP->fr_literal,
+                                     fixup_size, &exp, pcrel,
+                                     BFD_RELOC_NDS32_TLS_DESC_FUNC);
+                 fixP->fx_addnumber = fixP->fx_offset;
+
+                 fixup_size = 0;
+               }
+             /* Else do as usual.  */
+           }
+         else if (fixup_now->ramp & NDS32_PTR_PATTERN)
+           {
+             /* Find out PTR_RESOLVED code pattern.  */
+             nds32_relax_fixup_info_t *next_fixup = fixup_now + 1;
+             uint32_t resolved_pattern = 0;
+             while (next_fixup->offset)
+               {
+                 if (next_fixup->r_type == BFD_RELOC_NDS32_PTR_RESOLVED)
+                   {
+                     uint32_t new_pattern = code_seq[next_fixup->offset >> 2];
+                     if (!resolved_pattern)
+                       resolved_pattern = new_pattern;
+                     else if (new_pattern != resolved_pattern)
+                       {
+                         as_warn (_("Multiple BFD_RELOC_NDS32_PTR_RESOLVED "
+                                    "patterns are not supported yet!"));
+                         break;
+                       }
+                   }
+                 ++next_fixup;
+               }
+
+             /* Find matched code and insert fix-ups.  */
+             struct nds32_relocs_pattern *next_pattern = pattern_now->next;
+             /* This relocation has to point to another instruction.
+                Make sure each resolved relocation has to be pointed.  */
+             /* All instruction in relax_table should be 32-bit.  */
+             while (next_pattern)
+               {
+                 uint32_t cur_pattern = GET_OPCODE (next_pattern->opcode->value);
+                 if (cur_pattern == resolved_pattern)
+                   {
+                     ptr_offset = next_pattern->where
+                       - next_pattern->frag->fr_literal;
+                     exp.X_add_symbol = symbol_temp_new (now_seg, ptr_offset,
+                                                         next_pattern->frag);
+                     exp.X_add_number = 0;
+                     fixP = fix_new_exp (fragP, where - fragP->fr_literal,
+                                         fixup_size, &exp, 0,
+                                         fixup_now->r_type);
+                     fixP->fx_addnumber = fixP->fx_offset;
+                   }
+                 next_pattern = next_pattern->next;
+               }
+
+             fixup_size = 0;
+           }
+         else if (fixup_now->ramp & NDS32_PTR_MULTIPLE)
+           {
+             /* Find each PTR_RESOLVED pattern after PTR.  */
+             nds32_relax_fixup_info_t *next_fixup = fixup_now + 1;
+             while (next_fixup->offset)
+               {
+                 if (next_fixup->r_type == BFD_RELOC_NDS32_PTR_RESOLVED)
+                   {
+                     uint32_t pattern = code_seq[next_fixup->offset >> 2];
+                     /* Find matched code to insert fix-ups.  */
+                     struct nds32_relocs_pattern *next_insn = pattern_now->next;
+                     while (next_insn)
+                       {
+                         uint32_t insn_pattern = GET_OPCODE (next_insn->opcode->value);
+                         if (insn_pattern == pattern)
+                           {
+                             ptr_offset = next_insn->where
+                               - next_insn->frag->fr_literal;
+                             exp.X_add_symbol = symbol_temp_new (now_seg,
+                                                                 ptr_offset,
+                                                                 next_insn->frag);
+                             exp.X_add_number = 0;
+                             fixP = fix_new_exp (fragP,
+                                                 where - fragP->fr_literal,
+                                                 fixup_size, &exp, 0,
+                                                 fixup_now->r_type);
+                             fixP->fx_addnumber = fixP->fx_offset;
+                           }
+                         next_insn = next_insn->next;
+                       }
+                   }
+                 ++next_fixup;
+               }
+             fixup_size = 0;
            }
          else
            {
@@ -5066,13 +6242,26 @@ nds32_elf_append_relax_relocs (const char *key ATTRIBUTE_UNUSED, void *value)
 
          if (fixup_size != 0)
            {
-             fixP = fix_new_exp (fragP, where - fragP->fr_literal,
-                                 fixup_size, &exp, 0, fixup_now->r_type);
+             fixP = fix_new_exp (fragP, where - fragP->fr_literal, fixup_size,
+                                 &exp, pcrel, fixup_now->r_type);
              fixP->fx_addnumber = fixP->fx_offset;
            }
          fixup_now++;
          fixup_size = fixup_now->size;
        }
+
+#ifdef NDS32_LINUX_TOOLCHAIN
+      /* Insert group relocation for each relax hint.  */
+      if (key)
+       {
+         exp.X_add_symbol = hi_sym; /* for eyes only */
+         exp.X_add_number = group_id;
+         fixP = fix_new_exp (fragP, where - fragP->fr_literal, fixup_size,
+                             &exp, pcrel, BFD_RELOC_NDS32_GROUP);
+         fixP->fx_addnumber = fixP->fx_offset;
+       }
+#endif
+
       if (count < relax_code_size / 4)
        count++;
       pattern_now = pattern_now->next;
@@ -5083,13 +6272,49 @@ restore:
   frchain_now = frchain_bak;
 }
 
+static void
+nds32_str_tolower (const char *src, char *dest)
+{
+  unsigned int i, len;
+
+  len = strlen (src);
+
+  for (i = 0; i < len; i++)
+    *(dest + i) = TOLOWER (*(src + i));
+
+  *(dest + i) = '\0';
+}
+
 /* Check instruction if it can be used for the baseline.  */
 
 static bfd_boolean
-nds32_check_insn_available (struct nds32_asm_insn insn, char *str)
+nds32_check_insn_available (struct nds32_asm_insn insn, const char *str)
 {
   int attr = insn.attr & ATTR_ALL;
   static int baseline_isa = 0;
+  char *s;
+
+  s = xmalloc (strlen (str) + 1);
+  nds32_str_tolower (str, s);
+  if (verbatim
+      && (((insn.opcode->value == ALU2 (MTUSR)
+           || insn.opcode->value == ALU2 (MFUSR))
+          && (strstr (s, "lc")
+              || strstr (s, "le")
+              || strstr (s, "lb")))
+         || (insn.attr & NASM_ATTR_ZOL)))
+    {
+      as_bad (_("Not support instruction %s in verbatim."), str);
+      return FALSE;
+    }
+  free (s);
+
+  if (!enable_16bit && insn.opcode->isize == 2)
+    {
+      as_bad (_("16-bit instruction is disabled: %s."), str);
+      return FALSE;
+    }
+
   /* No isa setting or all isa can use.  */
   if (attr == 0 || attr == ATTR_ALL)
     return TRUE;
@@ -5113,7 +6338,7 @@ nds32_check_insn_available (struct nds32_asm_insn insn, char *str)
 
   if  ((baseline_isa & attr) == 0)
     {
-      as_bad (_("Not support instrcution %s in the baseline."), str);
+      as_bad (_("Instruction %s not supported in the baseline."), str);
       return FALSE;
     }
   return TRUE;
@@ -5131,9 +6356,10 @@ md_assemble (char *str)
   fixS *fixP;
   uint16_t insn_16;
   struct nds32_relocs_pattern *relocs_temp;
-  expressionS *pexp;
+  struct nds32_relocs_group *group_temp;
   fragS *fragP;
   int label = label_exist;
+  static bfd_boolean pseudo_hint = FALSE;
 
   popcode = nds32_lookup_pseudo_opcode (str);
   /* Note that we need to check 'verbatim' and
@@ -5142,11 +6368,23 @@ md_assemble (char *str)
      need to perform pseudo instruction expansion/transformation.  */
   if (popcode && !(verbatim && popcode->physical_op))
     {
+      /* Pseudo instruction is with relax_hint.  */
+      if (relaxing)
+       pseudo_hint = TRUE;
       pseudo_opcode = TRUE;
       nds32_pseudo_opcode_wrapper (str, popcode);
       pseudo_opcode = FALSE;
+      pseudo_hint = FALSE;
       nds32_elf_append_relax_relocs (NULL, relocs_list);
 
+      /* Free relax_hint group list.  */
+      while (nds32_relax_hint_current)
+       {
+         group_temp = nds32_relax_hint_current->next;
+         free (nds32_relax_hint_current);
+         nds32_relax_hint_current = group_temp;
+       }
+
       /* Free pseudo list.  */
       relocs_temp = relocs_list;
       while (relocs_temp)
@@ -5160,7 +6398,8 @@ md_assemble (char *str)
     }
 
   label_exist = 0;
-  insn.info = (expressionS *) alloca (sizeof (expressionS));
+  insn.info = XNEW (expressionS);
+  asm_desc.result = NASM_OK;
   nds32_assemble (&asm_desc, &insn, str);
 
   switch (asm_desc.result)
@@ -5172,7 +6411,7 @@ md_assemble (char *str)
       as_bad (_("Incorrect syntax, %s."), str);
       return;
     case NASM_ERR_OPERAND:
-      as_bad (_("Unrecognized operand, %s."), str);
+      as_bad (_("Unrecognized operand/register, %s."), str);
       return;
     case NASM_ERR_OUT_OF_RANGE:
       as_bad (_("Operand out of range, %s."), str);
@@ -5194,13 +6433,15 @@ md_assemble (char *str)
   if (!nds32_check_insn_available (insn, str))
     return;
 
-  /* Make sure the begining of text being 2-byte align.  */
+  /* Make sure the beginning of text being 2-byte align.  */
   nds32_adjust_label (1);
+  add_mapping_symbol (MAP_CODE, 0, 0);
   fld = insn.field;
   /* Try to allocate the max size to guarantee relaxable same branch
      instructions in the same fragment.  */
   frag_grow (NDS32_MAXCHAR);
   fragP = frag_now;
+
   if (fld && (insn.attr & NASM_ATTR_BRANCH)
       && (pseudo_opcode || (insn.opcode->value != INSN_JAL
                            && insn.opcode->value != INSN_J))
@@ -5208,7 +6449,7 @@ md_assemble (char *str)
     {
       /* User assembly code branch relax for it.  */
       /* If fld is not NULL, it is a symbol.  */
-      /* Branch msut relax to proper pattern in user assembly code exclude
+      /* Branch must relax to proper pattern in user assembly code exclude
         J and JAL.  Keep these two in original type for users which wants
         to keep their size be fixed.  In general, assembler does not convert
         instruction generated by compiler.  But jump instruction may be
@@ -5218,8 +6459,8 @@ md_assemble (char *str)
       /* Get branch range type.  */
       dwarf2_emit_insn (0);
       enum nds32_br_range range_type;
+      expressionS *pexp = insn.info;
 
-      pexp = insn.info;
       range_type = get_range_type (fld);
 
       out = frag_var (rs_machine_dependent, NDS32_MAXCHAR,
@@ -5235,27 +6476,39 @@ md_assemble (char *str)
       else if (insn.opcode->isize == 2)
        bfd_putb16 (insn.insn, out);
       fragP->tc_frag_data.flag |= NDS32_FRAG_BRANCH;
+
+      free (insn.info);
       return;
       /* md_convert_frag will insert relocations.  */
     }
-  else if (!fld && !relaxing && enable_16bit && (optimize || optimize_for_space)
-          && ((!verbatim && insn.opcode->isize == 4
+  else if (!relaxing && enable_16bit && (optimize || optimize_for_space)
+          && ((!fld && !verbatim && insn.opcode->isize == 4
                && nds32_convert_32_to_16 (stdoutput, insn.insn, &insn_16, NULL))
               || (insn.opcode->isize == 2
                   && nds32_convert_16_to_32 (stdoutput, insn.insn, NULL))))
     {
       /* Record this one is relaxable.  */
+      expressionS *pexp = insn.info;
       dwarf2_emit_insn (0);
-      out = frag_var (rs_machine_dependent,
-                     4, /* Max size is 32-bit instruction.  */
-                     0, /* VAR is un-used.  */
-                     0, NULL, 0, NULL);
+      if (fld)
+       {
+         out = frag_var (rs_machine_dependent,
+                         4, /* Max size is 32-bit instruction.  */
+                         0, /* VAR is un-used.  */
+                         0, pexp->X_add_symbol, pexp->X_add_number, 0);
+         fragP->tc_frag_data.flag |= NDS32_FRAG_RELAXABLE_BRANCH;
+       }
+      else
+       out = frag_var (rs_machine_dependent,
+                       4, /* Max size is 32-bit instruction.  */
+                       0, /* VAR is un-used.  */
+                       0, NULL, 0, NULL);
       fragP->tc_frag_data.flag |= NDS32_FRAG_RELAXABLE;
       fragP->tc_frag_data.opcode = insn.opcode;
       fragP->tc_frag_data.insn = insn.insn;
       fragP->fr_fix += 2;
 
-      /* In original, we don't relax the instrucion with label on it,
+      /* In original, we don't relax the instruction with label on it,
         but this may cause some redundant nop16.  Therefore, tag this
         relaxable instruction and relax it carefully.  */
       if (label)
@@ -5265,6 +6518,8 @@ md_assemble (char *str)
        bfd_putb16 (insn_16, out);
       else if (insn.opcode->isize == 2)
        bfd_putb16 (insn.insn, out);
+
+      free (insn.info);
       return;
     }
   else if ((verbatim || !relaxing) && optimize && label)
@@ -5273,7 +6528,7 @@ md_assemble (char *str)
       expressionS exp;
       out = frag_var (rs_machine_dependent, insn.opcode->isize,
                      0, 0, NULL, 0, NULL);
-      /* If this insturction is branch target, it is not relaxable.  */
+      /* If this instruction is branch target, it is not relaxable.  */
       fragP->tc_frag_data.flag = NDS32_FRAG_LABEL;
       fragP->tc_frag_data.opcode = insn.opcode;
       fragP->tc_frag_data.insn = insn.insn;
@@ -5283,7 +6538,10 @@ md_assemble (char *str)
          exp.X_op = O_symbol;
          exp.X_add_symbol = abs_section_sym;
          exp.X_add_number = 0;
-         fixP = fix_new_exp (fragP, 0, 0, &exp, 0, BFD_RELOC_NDS32_LABEL);
+         fixP = fix_new_exp (fragP, fragP->fr_fix - 4, 0, &exp,
+                             0, BFD_RELOC_NDS32_LABEL);
+         if (!verbatim)
+           fragP->tc_frag_data.flag = NDS32_FRAG_ALIGN;
        }
     }
   else
@@ -5291,18 +6549,21 @@ md_assemble (char *str)
 
   if (insn.opcode->isize == 4)
     bfd_putb32 (insn.insn, out);
-  if (insn.opcode->isize == 2)
+  else if (insn.opcode->isize == 2)
     bfd_putb16 (insn.insn, out);
 
   dwarf2_emit_insn (insn.opcode->isize);
 
   /* Compiler generating code and user assembly pseudo load-store, insert
      fixup here.  */
-  pexp = insn.info;
+  expressionS *pexp = insn.info;
   fixP = nds32_elf_record_fixup_exp (fragP, str, fld, pexp, out, &insn);
   /* Build relaxation pattern when relaxing is enable.  */
   if (relaxing)
-    nds32_elf_build_relax_relation (fixP, pexp, out, insn.opcode, fragP, fld);
+    nds32_elf_build_relax_relation (fixP, pexp, out, &insn, fragP, fld,
+                                   pseudo_hint);
+
+  free (insn.info);
 }
 
 /* md_macro_start  */
@@ -5350,7 +6611,7 @@ md_section_align (segT segment, valueT size)
 {
   int align = bfd_get_section_alignment (stdoutput, segment);
 
-  return ((size + (1 << align) - 1) & (-1 << align));
+  return ((size + (1 << align) - 1) & ((valueT) -1 << align));
 }
 
 /* GAS will call this function when a symbol table lookup fails, before it
@@ -5426,7 +6687,7 @@ nds32_convert_to_range_type (long offset)
   return range_type;
 }
 
-/* Set insntruction register mask.  */
+/* Set instruction register mask.  */
 
 static void
 nds32_elf_get_set_cond (relax_info_t *relax_info, int offset, uint32_t *insn,
@@ -5453,7 +6714,6 @@ nds32_elf_get_set_cond (relax_info_t *relax_info, int offset, uint32_t *insn,
     }
 }
 
-
 static int
 nds32_relax_branch_instructions (segT segment, fragS *fragP,
                                 long stretch ATTRIBUTE_UNUSED,
@@ -5477,20 +6737,41 @@ nds32_relax_branch_instructions (segT segment, fragS *fragP,
   if (fragP->fr_symbol == NULL)
     return adjust;
 
-  /* If frag_var is not enough room, the previos frag is fr_full and with
+  /* If frag_var is not enough room, the previous frag is fr_full and with
      opcode.  The new one is rs_dependent but without opcode.  */
   if (opcode == NULL)
     return adjust;
 
+  /* Use U4G mode for b and bal in verbatim mode because lto may combine
+     functions into a file.  And order the file in the last when linking.
+     Once there is multiple definition, the same function will be kicked.
+     This may cause relocation truncated error.  */
+  if (verbatim && !nds32_pic
+      && (strcmp (opcode->opcode, "j") == 0
+         || strcmp (opcode->opcode, "jal") == 0))
+    {
+      fragP->fr_subtype = BR_RANGE_U4G;
+      if (init)
+       return 8;
+      else
+       return 0;
+    }
+
   relax_info = hash_find (nds32_relax_info_hash, opcode->opcode);
 
   if (relax_info == NULL)
     return adjust;
 
   if (init)
-    branch_range_type = relax_info->br_range;
+    {
+      branch_range_type = relax_info->br_range;
+      i = BR_RANGE_S256;
+    }
   else
-    branch_range_type = fragP->fr_subtype;
+    {
+      branch_range_type = fragP->fr_subtype;
+      i = branch_range_type;
+    }
 
   offset = nds32_calc_branch_offset (segment, fragP, stretch,
                                     relax_info, branch_range_type);
@@ -5499,15 +6780,21 @@ nds32_relax_branch_instructions (segT segment, fragS *fragP,
 
   /* If actual range is equal to instruction jump range, do nothing.  */
   if (real_range_type == branch_range_type)
-    return adjust;
+    {
+      fragP->fr_subtype = real_range_type;
+      return adjust;
+    }
 
   /* Find out proper relaxation code sequence.  */
-  for (i = BR_RANGE_S256; i < BR_RANGE_NUM; i++)
+  for (; i < BR_RANGE_NUM; i++)
     {
       if (real_range_type <= (unsigned int) i)
        {
          if (init)
            diff = relax_info->relax_code_size[i] - opcode->isize;
+         else if (real_range_type < (unsigned int) i)
+           diff = relax_info->relax_code_size[real_range_type]
+             - relax_info->relax_code_size[branch_range_type];
          else
            diff = relax_info->relax_code_size[i]
              - relax_info->relax_code_size[branch_range_type];
@@ -5540,7 +6827,7 @@ nds32_relax_branch_instructions (segT segment, fragS *fragP,
            }
 
          /* Update fr_subtype to new NDS32_BR_RANGE.  */
-         fragP->fr_subtype = i;
+         fragP->fr_subtype = real_range_type;
          break;
        }
     }
@@ -5579,19 +6866,19 @@ nds32_get_align (addressT address, int align)
 {
   addressT mask, new_address;
 
-  mask = ~((~0) << align);
+  mask = ~((addressT) (~0) << align);
   new_address = (address + mask) & (~mask);
   return (new_address - address);
 }
 
 /* Check the prev_frag is legal.  */
 static void
-invalid_prev_frag (fragS * fragP, fragS **prev_frag)
+invalid_prev_frag (fragS * fragP, fragS **prev_frag, bfd_boolean relax)
 {
   addressT address;
   fragS *frag_start = *prev_frag;
 
-  if (!frag_start)
+  if (!frag_start || !relax)
     return;
 
   if (frag_start->last_fr_address >= fragP->last_fr_address)
@@ -5607,13 +6894,13 @@ invalid_prev_frag (fragS * fragP, fragS **prev_frag)
          || frag_t->fr_type == rs_align_code
          || frag_t->fr_type == rs_align_test)
        {
-         /* Relax instruction can not walk across lable.  */
+         /* Relax instruction can not walk across label.  */
          if (frag_t->tc_frag_data.flag & NDS32_FRAG_LABEL)
            {
              prev_frag = NULL;
              return;
            }
-         /* Relax previos relaxable to align rs_align frag.  */
+         /* Relax previous relaxable to align rs_align frag.  */
          address = frag_t->fr_address + frag_t->fr_fix;
          addressT offset = nds32_get_align (address, (int) frag_t->fr_offset);
          if (offset & 0x2)
@@ -5629,6 +6916,22 @@ invalid_prev_frag (fragS * fragP, fragS **prev_frag)
        }
       frag_t = frag_t->fr_next;
     }
+
+  if (fragP->tc_frag_data.flag & NDS32_FRAG_ALIGN)
+    {
+      address = fragP->fr_address;
+      addressT offset = nds32_get_align (address, 2);
+      if (offset & 0x2)
+       {
+         /* If there is label on the prev_frag, check if it is aligned.  */
+         if (!((*prev_frag)->tc_frag_data.flag & NDS32_FRAG_LABEL)
+             || (((*prev_frag)->fr_address + (*prev_frag)->fr_fix  - 2 )
+                 & 0x2) == 0)
+           nds32_adjust_relaxable_frag (*prev_frag, fragP);
+       }
+      *prev_frag = NULL;
+      return;
+    }
 }
 
 /* md_relax_frag  */
@@ -5643,7 +6946,7 @@ nds32_relax_frag (segT segment, fragS *fragP, long stretch ATTRIBUTE_UNUSED)
   static fragS *prev_frag = NULL;
   int adjust = 0;
 
-  invalid_prev_frag (fragP, &prev_frag);
+  invalid_prev_frag (fragP, &prev_frag, TRUE);
 
   if (fragP->tc_frag_data.flag & NDS32_FRAG_BRANCH)
     adjust = nds32_relax_branch_instructions (segment, fragP, stretch, 0);
@@ -5652,8 +6955,8 @@ nds32_relax_frag (segT segment, fragS *fragP, long stretch ATTRIBUTE_UNUSED)
   if (fragP->tc_frag_data.flag & NDS32_FRAG_RELAXABLE
       && (fragP->tc_frag_data.flag & NDS32_FRAG_RELAXED) == 0)
     /* Here is considered relaxed case originally.  But it may cause
-       unendless loop when relaxing.  Once the instruction is relaxed,
-       it can not be undo.  */
+       an endless loop when relaxing.  Once the instruction is relaxed,
+       it can not be undone.  */
     prev_frag = fragP;
 
   return adjust;
@@ -5676,11 +6979,11 @@ md_estimate_size_before_relax (fragS *fragP, segT segment)
      1. relax for branch
      2. relax for 32-bits to 16-bits  */
 
-  /* Save previos relaxable frag.  */
+  /* Save previous relaxable frag.  */
   static fragS *prev_frag = NULL;
   int adjust = 0;
 
-  invalid_prev_frag (fragP, &prev_frag);
+  invalid_prev_frag (fragP, &prev_frag, FALSE);
 
   if (fragP->tc_frag_data.flag & NDS32_FRAG_BRANCH)
     adjust = nds32_relax_branch_instructions (segment, fragP, 0, 1);
@@ -5714,7 +7017,6 @@ md_convert_frag (bfd *abfd ATTRIBUTE_UNUSED, segT sec, fragS *fragP)
   enum nds32_br_range branch_range_type = fragP->fr_subtype;
   struct nds32_opcode *opcode = fragP->tc_frag_data.opcode;
   uint32_t origin_insn = fragP->tc_frag_data.insn;
-  int backup_endian;
   relax_info_t *relax_info;
   char *fr_buffer;
   int fr_where;
@@ -5725,26 +7027,65 @@ md_convert_frag (bfd *abfd ATTRIBUTE_UNUSED, segT sec, fragS *fragP)
   uint32_t *code_seq;
   uint32_t insn;
   int code_size, insn_size, offset, fixup_size;
-  int buf_offset;
+  int buf_offset, pcrel;
   int i, k;
   uint16_t insn_16;
   nds32_relax_fixup_info_t fixup_info[MAX_RELAX_FIX];
   /* Save the 1st instruction is converted to 16 bit or not.  */
   unsigned int branch_size;
+  enum bfd_reloc_code_real final_r_type;
 
   /* Replace with gas_assert (branch_symbol != NULL); */
   if (branch_symbol == NULL && !(fragP->tc_frag_data.flag & NDS32_FRAG_RELAXED))
     return;
 
-  /* If frag_var is not enough room, the previos frag is fr_full and with
+  /* If frag_var is not enough room, the previous frag is fr_full and with
      opcode.  The new one is rs_dependent but without opcode.  */
   if (opcode == NULL)
     return;
 
-  /* Relax the insntruction.  */
-  if (fragP->tc_frag_data.flag & NDS32_FRAG_RELAXED)
+  if (fragP->tc_frag_data.flag & NDS32_FRAG_RELAXABLE_BRANCH)
+    {
+      relax_info = hash_find (nds32_relax_info_hash, opcode->opcode);
+
+      if (relax_info == NULL)
+       return;
+
+      i = BR_RANGE_S256;
+      while (i < BR_RANGE_NUM
+            && relax_info->relax_code_size[i]
+            != (fragP->tc_frag_data.flag & NDS32_FRAG_RELAXED ? 4 : 2))
+       i++;
+
+      if (i >= BR_RANGE_NUM)
+       as_bad ("Internal error: Cannot find relocation of"
+               "relaxable branch.");
+
+      exp.X_op = O_symbol;
+      exp.X_add_symbol = branch_symbol;
+      exp.X_add_number = branch_offset;
+      pcrel = ((relax_info->relax_fixup[i][0].ramp & NDS32_PCREL) != 0) ? 1 : 0;
+      fr_where = fragP->fr_fix - 2;
+      fixP = fix_new_exp (fragP, fr_where, relax_info->relax_fixup[i][0].size,
+                         &exp, pcrel, relax_info->relax_fixup[i][0].r_type);
+      fixP->fx_addnumber = fixP->fx_offset;
+
+      if (fragP->tc_frag_data.flag & NDS32_FRAG_RELAXED)
+       {
+         insn_16 = fragP->tc_frag_data.insn;
+         nds32_convert_16_to_32 (stdoutput, insn_16, &insn);
+         fr_buffer = fragP->fr_literal + fr_where;
+         fragP->fr_fix += 2;
+         exp.X_op = O_symbol;
+         exp.X_add_symbol = abs_section_sym;
+         exp.X_add_number = 0;
+         fix_new_exp (fragP, fr_where, 4,
+                      &exp, 0, BFD_RELOC_NDS32_INSN16);
+         number_to_chars_bigendian (fr_buffer, insn, 4);
+       }
+    }
+  else if (fragP->tc_frag_data.flag & NDS32_FRAG_RELAXED)
     {
-      expressionS exp_t;
       if (fragP->tc_frag_data.opcode->isize == 2)
        {
          insn_16 = fragP->tc_frag_data.insn;
@@ -5755,14 +7096,14 @@ md_convert_frag (bfd *abfd ATTRIBUTE_UNUSED, segT sec, fragS *fragP)
       fragP->fr_fix += 2;
       fr_where = fragP->fr_fix - 4;
       fr_buffer = fragP->fr_literal + fr_where;
-      exp_t.X_op = O_symbol;
-      exp_t.X_add_symbol = abs_section_sym;
-      exp_t.X_add_number = 0;
-      fix_new_exp (fragP, fr_where, 4, &exp_t, 0,
+      exp.X_op = O_symbol;
+      exp.X_add_symbol = abs_section_sym;
+      exp.X_add_number = 0;
+      fix_new_exp (fragP, fr_where, 4, &exp, 0,
                   BFD_RELOC_NDS32_INSN16);
       number_to_chars_bigendian (fr_buffer, insn, 4);
     }
-  else
+  else if (fragP->tc_frag_data.flag & NDS32_FRAG_BRANCH)
     {
       /* Branch instruction adjust and append relocations.  */
       relax_info = hash_find (nds32_relax_info_hash, opcode->opcode);
@@ -5770,9 +7111,6 @@ md_convert_frag (bfd *abfd ATTRIBUTE_UNUSED, segT sec, fragS *fragP)
       if (relax_info == NULL)
        return;
 
-      backup_endian = target_big_endian;
-      target_big_endian = 1;
-
       fr_where = fragP->fr_fix - opcode->isize;
       fr_buffer = fragP->fr_literal + fr_where;
 
@@ -5819,14 +7157,14 @@ md_convert_frag (bfd *abfd ATTRIBUTE_UNUSED, segT sec, fragS *fragP)
                                  origin_insn, branch_range_type);
 
          /* Try to convert to 16-bits instruction.  Currently, only the first
-            insntruction in pattern can be converted.  EX: bnez sethi ori jr,
+            instruction in pattern can be converted.  EX: bnez sethi ori jr,
             only bnez can be converted to 16 bit and ori can't.  */
 
          while (fixup_info[k].size != 0
                 && relax_info->relax_fixup[branch_range_type][k].offset < offset)
            k++;
 
-         md_number_to_chars (fr_buffer + buf_offset, insn, insn_size);
+         number_to_chars_bigendian (fr_buffer + buf_offset, insn, insn_size);
          buf_offset += insn_size;
 
          offset += insn_size;
@@ -5839,6 +7177,7 @@ md_convert_frag (bfd *abfd ATTRIBUTE_UNUSED, segT sec, fragS *fragP)
       for (i = 0; fixup_info[i].size != 0; i++)
        {
          fixup_size = fixup_info[i].size;
+         pcrel = ((fixup_info[i].ramp & NDS32_PCREL) != 0) ? 1 : 0;
 
          if ((fixup_info[i].ramp & NDS32_CREATE_LABEL) != 0)
            {
@@ -5875,15 +7214,15 @@ md_convert_frag (bfd *abfd ATTRIBUTE_UNUSED, segT sec, fragS *fragP)
 
          if (fixup_info[i].r_type != 0)
            {
+             final_r_type = fixup_info[i].r_type;
              fixP = fix_new_exp (fragP, fr_where + fixup_info[i].offset,
-                                 fixup_size, &exp, 0, fixup_info[i].r_type);
+                                 fixup_size, &exp, pcrel,
+                                 final_r_type);
              fixP->fx_addnumber = fixP->fx_offset;
            }
        }
 
       fragP->fr_fix = fr_where + buf_offset;
-
-      target_big_endian = backup_endian;
     }
 }
 
@@ -5983,7 +7322,7 @@ md_number_to_chars (char *buf, valueT val, int n)
 /* This function is called to convert an ASCII string into a floating point
    value in format used by the CPU.  */
 
-char *
+const char *
 md_atof (int type, char *litP, int *sizeP)
 {
   int i;
@@ -6102,12 +7441,12 @@ nds32_insert_relax_entry (bfd *abfd ATTRIBUTE_UNUSED, asection *sec,
   seginfo = seg_info (sec);
   if (!seginfo || !symbol_rootP || !subseg_text_p (sec) || sec->size == 0)
     return;
-  /* If there is no relocation and relax is disabled, it is not necessary to
-     insert R_NDS32_RELAX_ENTRY for linker do EX9 or IFC optimization.  */
+
   for (fixp = seginfo->fix_root; fixp; fixp = fixp->fx_next)
     if (!fixp->fx_done)
       break;
-  if (!fixp && !enable_relax_ex9 && !verbatim)
+
+  if (!fixp && !verbatim && ict_flag == ICT_NONE)
     return;
 
   subseg_change (sec, 0);
@@ -6115,21 +7454,21 @@ nds32_insert_relax_entry (bfd *abfd ATTRIBUTE_UNUSED, asection *sec,
   /* Set RELAX_ENTRY flags for linker.  */
   fragP = seginfo->frchainP->frch_root;
   exp.X_op = O_symbol;
-  exp.X_add_symbol = section_symbol (sec);
+  exp.X_add_symbol = abs_section_sym;
   exp.X_add_number = 0;
   if (!enable_relax_relocs)
     exp.X_add_number |= R_NDS32_RELAX_ENTRY_DISABLE_RELAX_FLAG;
   else
     {
       /* These flags are only enabled when global relax is enabled.
-        Maybe we can check DISABLE_RELAX_FLAG at linke-time,
+        Maybe we can check DISABLE_RELAX_FLAG at link-time,
         so we set them anyway.  */
-      if (enable_relax_ex9)
-       exp.X_add_number |= R_NDS32_RELAX_ENTRY_EX9_FLAG;
-      if (enable_relax_ifc)
-       exp.X_add_number |= R_NDS32_RELAX_ENTRY_IFC_FLAG;
       if (verbatim)
        exp.X_add_number |= R_NDS32_RELAX_ENTRY_VERBATIM_FLAG;
+      if (ict_flag == ICT_SMALL)
+       exp.X_add_number |= R_NDS32_RELAX_ENTRY_ICT_SMALL;
+      else if (ict_flag == ICT_LARGE)
+       exp.X_add_number |= R_NDS32_RELAX_ENTRY_ICT_LARGE;
     }
   if (optimize)
     exp.X_add_number |= R_NDS32_RELAX_ENTRY_OPTIMIZE_FLAG;
@@ -6148,9 +7487,42 @@ nds32_elf_analysis_relax_hint (void)
   hash_traverse (nds32_hint_hash, nds32_elf_append_relax_relocs);
 }
 
+static void
+nds32_elf_insert_final_frag (void)
+{
+  struct frchain *frchainP;
+  asection *s;
+  fragS *fragP;
+
+  if (!optimize)
+    return;
+
+  for (s = stdoutput->sections; s; s = s->next)
+    {
+      segment_info_type *seginfo = seg_info (s);
+      if (!seginfo)
+       continue;
+
+      for (frchainP = seginfo->frchainP; frchainP != NULL;
+          frchainP = frchainP->frch_next)
+       {
+         subseg_set (s, frchainP->frch_subseg);
+
+         if (subseg_text_p (now_seg))
+           {
+             fragP = frag_now;
+             frag_var (rs_machine_dependent, 2, /* Max size.  */
+                       0, /* VAR is un-used.  */ 0, NULL, 0, NULL);
+             fragP->tc_frag_data.flag |= NDS32_FRAG_FINAL;
+           }
+       }
+    }
+}
+
 void
 md_end (void)
 {
+  nds32_elf_insert_final_frag ();
   nds32_elf_analysis_relax_hint ();
   bfd_map_over_sections (stdoutput, nds32_insert_leb128_fixes, NULL);
 }
@@ -6305,7 +7677,7 @@ elf_nds32_final_processing (void)
   elf_elfheader (stdoutput)->e_flags |= nds32_elf_flags;
 }
 
-/* Implement md_apply_fix.  Apply the fix-up or tranform the fix-up for
+/* Implement md_apply_fix.  Apply the fix-up or transform the fix-up for
    later relocation generation.  */
 
 void
@@ -6328,13 +7700,13 @@ nds32_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED)
       fixP->fx_addnumber = value;
       fixP->tc_fix_data = NULL;
 
-      /* Tranform specific relocations here for later relocation generation.
-        Tag data here for ex9 relaxtion and tag tls data for linker.  */
+      /* Transform specific relocations here for later relocation generation.
+        Tag tls data for linker.  */
       switch (fixP->fx_r_type)
        {
        case BFD_RELOC_NDS32_DATA:
-         if (!enable_relax_ex9)
-           fixP->fx_done = 1;
+         /* This reloc is obselete, we do not need it so far.  */
+         fixP->fx_done = 1;
          break;
        case BFD_RELOC_NDS32_TPOFF:
        case BFD_RELOC_NDS32_TLS_LE_HI20:
@@ -6344,6 +7716,12 @@ nds32_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED)
        case BFD_RELOC_NDS32_GOTTPOFF:
        case BFD_RELOC_NDS32_TLS_IE_HI20:
        case BFD_RELOC_NDS32_TLS_IE_LO12S2:
+       case BFD_RELOC_NDS32_TLS_DESC_HI20:
+       case BFD_RELOC_NDS32_TLS_DESC_LO12:
+       case BFD_RELOC_NDS32_TLS_IE_LO12:
+       case BFD_RELOC_NDS32_TLS_IEGP_HI20:
+       case BFD_RELOC_NDS32_TLS_IEGP_LO12:
+       case BFD_RELOC_NDS32_TLS_IEGP_LO12S2:
          S_SET_THREAD_LOCAL (fixP->fx_addsy);
          break;
        default:
@@ -6384,7 +7762,7 @@ nds32_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED)
         ---- 8< ---- 8< ---- 8< ---- 8< ----
 
         We use a single relocation entry for this expression.
-        * The initial distance value is stored direcly in that location
+        * The initial distance value is stored directly in that location
           specified by r_offset (i.e., foo in this example.)
         * The begin of the region, i.e., .LBEGIN, is specified by
           r_info/R_SYM and r_addend, e.g., .text + 0x32.
@@ -6470,6 +7848,7 @@ nds32_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED)
          break;
        case BFD_RELOC_64:
          md_number_to_chars (where, value, 8);
+         break;
        default:
          as_bad_where (fixP->fx_file, fixP->fx_line,
                        _("Internal error: Unknown fixup type %d (`%s')"),
@@ -6488,9 +7867,9 @@ tc_gen_reloc (asection *section ATTRIBUTE_UNUSED, fixS *fixP)
   arelent *reloc;
   bfd_reloc_code_real_type code;
 
-  reloc = (arelent *) xmalloc (sizeof (arelent));
+  reloc = XNEW (arelent);
 
-  reloc->sym_ptr_ptr = (asymbol **) xmalloc (sizeof (asymbol *));
+  reloc->sym_ptr_ptr = XNEW (asymbol *);
   *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixP->fx_addsy);
   reloc->address = fixP->fx_frag->fr_address + fixP->fx_where;
 
@@ -6525,13 +7904,14 @@ tc_gen_reloc (asection *section ATTRIBUTE_UNUSED, fixS *fixP)
   return reloc;
 }
 
-struct suffix_name suffix_table[] =
+static struct suffix_name suffix_table[] =
 {
-  {"GOTOFF",   BFD_RELOC_NDS32_GOTOFF, 1},
-  {"GOT",      BFD_RELOC_NDS32_GOT20,  1},
-  {"TPOFF",    BFD_RELOC_NDS32_TPOFF,  0},
-  {"PLT",      BFD_RELOC_NDS32_25_PLTREL,      1},
-  {"GOTTPOFF", BFD_RELOC_NDS32_GOTTPOFF,       0}
+  {"GOTOFF",   BFD_RELOC_NDS32_GOTOFF},
+  {"GOT",      BFD_RELOC_NDS32_GOT20},
+  {"TPOFF",    BFD_RELOC_NDS32_TPOFF},
+  {"PLT",      BFD_RELOC_NDS32_25_PLTREL},
+  {"GOTTPOFF", BFD_RELOC_NDS32_GOTTPOFF},
+  {"TLSDESC",  BFD_RELOC_NDS32_TLS_DESC},
 };
 
 /* Implement md_parse_name.  */
@@ -6541,6 +7921,8 @@ nds32_parse_name (char const *name, expressionS *exprP,
                  enum expr_mode mode ATTRIBUTE_UNUSED,
                  char *nextcharP ATTRIBUTE_UNUSED)
 {
+  segT segment;
+
   exprP->X_op_symbol = NULL;
   exprP->X_md = BFD_RELOC_UNUSED;
 
@@ -6548,6 +7930,11 @@ nds32_parse_name (char const *name, expressionS *exprP,
   exprP->X_op = O_symbol;
   exprP->X_add_number = 0;
 
+  /* Check the special name if a symbol.  */
+  segment = S_GET_SEGMENT (exprP->X_add_symbol);
+  if ((segment != undefined_section) && (*nextcharP != '@'))
+    return 0;
+
   if (strcmp (name, GOT_NAME) == 0 && *nextcharP != '@')
     {
       /* Set for _GOT_OFFSET_TABLE_.  */
@@ -6559,13 +7946,11 @@ nds32_parse_name (char const *name, expressionS *exprP,
       char *next;
       for (i = 0; i < ARRAY_SIZE (suffix_table); i++)
        {
-         next = input_line_pointer + 1 + strlen(suffix_table[i].suffix);
+         next = input_line_pointer + 1 + strlen (suffix_table[i].suffix);
          if (strncasecmp (input_line_pointer + 1, suffix_table[i].suffix,
                           strlen (suffix_table[i].suffix)) == 0
              && !is_part_of_name (*next))
            {
-             if (!nds32_pic && suffix_table[i].pic)
-               as_bad (_("need PIC qualifier with symbol."));
              exprP->X_md = suffix_table[i].reloc;
              *input_line_pointer = *nextcharP;
              input_line_pointer = next;
@@ -6575,6 +7960,7 @@ nds32_parse_name (char const *name, expressionS *exprP,
            }
        }
     }
+
   return 1;
 }
 
This page took 0.154404 seconds and 4 git commands to generate.