gdb: add target_ops::supports_displaced_step
[deliverable/binutils-gdb.git] / opcodes / nds32-dis.c
index c732e841c09a7fac6145462c5adf804be9b9f6b3..35e4ba029176cb4c832dbce82554ba1da3d0bc93 100644 (file)
@@ -1,5 +1,5 @@
 /* NDS32-specific support for 32-bit ELF.
-   Copyright (C) 2012-2013 Free Software Foundation, Inc.
+   Copyright (C) 2012-2020 Free Software Foundation, Inc.
    Contributed by Andes Technology Corporation.
 
    This file is part of BFD, the Binary File Descriptor library.
    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
-   02110-1301, USA.*/
-
+   02110-1301, USA.  */
 
 #include "sysdep.h"
 #include <stdio.h>
 #include "ansidecl.h"
-#include "dis-asm.h"
+#include "disassemble.h"
 #include "bfd.h"
 #include "symcat.h"
 #include "libiberty.h"
 #include "opintl.h"
 #include "bfd_stdint.h"
+#include "hashtab.h"
+#include "nds32-asm.h"
+#include "opcode/nds32.h"
 
-#define __MF(v, off, bs)       ((v & ((1 << (bs)) - 1)) << (off))
-#define __GF(v, off, bs)       ((v >> (off)) & ((1 << (bs)) - 1))
-#define __PF(v, off, bs, val)  do { v = __put_field (v, off, bs, val); } while (0)
-/* #define __SEXT(v, bs)       ((v ^ (1 << (bs - 1))) - (1 << (bs - 1))) */
-#define __SEXT(v, bs)          (((v & ((1 << bs) - 1)) ^ (1 << (bs - 1))) - (1 << (bs - 1)))
-#define __BIT(n)               (1 << n)
-
-/* Get fields */
-#define OP6(insn)      ((insn >> 25) & 0x3F)
-#define RT5(insn)      ((insn >> 20) & 0x1F)
-#define RA5(insn)      ((insn >> 15) & 0x1F)
-#define RB5(insn)      ((insn >> 10) & 0x1F)
-#define RD5(insn)      ((insn >> 5) & 0x1F)
-#define SUB5(insn)     ((insn >> 0) & 0x1F)
-#define SUB10(insn)    ((insn >> 0) & 0x3FF)
-#define IMMU(insn, bs) (insn & ((1 << bs) - 1))
-#define IMMS(insn, bs) __SEXT ((insn & ((1 << bs) - 1)), bs)
-#define IMM1U(insn)    IMMU ((insn >> 10), 5)
-#define IMM1S(insn)    IMMS ((insn >> 10), 5)
-#define IMM2U(insn)    IMMU ((insn >> 5), 5)
-#define IMM2S(insn)    IMMS ((insn >> 5), 5)
-
-/* Default text to print if an instruction isn't recognized.  */
-#define UNKNOWN_INSN_MSG _("*unknown*")
+/* Get fields macro define.  */
+#define MASK_OP(insn, mask)    ((insn) & (0x3f << 25 | (mask)))
 
-static const char *mnemonic_op6[] =
+/* For mapping symbol.  */
+enum map_type
 {
-  "lbi",  "lhi",   "lwi",  "ldi",    "lbi.bi",  "lhi.bi",  "lwi.bi",  "ldi.bi",
-  "sbi",  "shi",   "swi",  "sdi",    "sbi.bi",  "shi.bi",  "swi.bi",  "sdi.bi",
-  "lbsi", "lhsi",  "lwsi", "dprefi", "lbsi.bi", "lhsi.bi", "lwsi.bi", "lbgp",
-  "lwc",  "swc",   "ldc",  "sdc",    "mem",     "lsmw",    "hwgp",    "sbgp",
-  "alu1", "alu2",  "movi", "sethi",  "ji",      "jreg",    "br1",     "br2",
-  "addi", "subri", "andi", "xori",   "ori",     "br3",     "slti",    "sltsi",
-  "aext", "cext",  "misc", "bitci",  "op_64",   "cop"
+  MAP_DATA0,
+  MAP_DATA1,
+  MAP_DATA2,
+  MAP_DATA3,
+  MAP_DATA4,
+  MAP_CODE,
 };
 
-static const char *mnemonic_mem[] =
+struct nds32_private_data
 {
-  "lb",   "lh",  "lw",   "ld",    "lb.bi",  "lh.bi",  "lw.bi",  "ld.bi",
-  "sb",   "sh",  "sw",   "sd",    "sb.bi",  "sh.bi",  "sw.bi",  "sd.bi",
-  "lbs",  "lhs", "lws",  "dpref", "lbs.bi", "lhs.bi", "lws.bi", "27",
-  "llw",  "scw", "32",   "33",    "34",     "35",     "36",     "37",
-  "lbup", "41",  "lwup", "43",    "44",     "45",     "46",     "47",
-  "sbup", "51",  "swup"
-};
+  /* Whether any mapping symbols are present in the provided symbol
+     table.  -1 if we do not know yet, otherwise 0 or 1.  */
+  int has_mapping_symbols;
 
-static const char *mnemonic_alu1[] =
-{
-  "add",  "sub",  "and",   "xor",   "or",       "nor",      "slt",      "slts",
-  "slli", "srli", "srai",  "rotri", "sll",      "srl",      "sra",      "rotr",
-  "seb",  "seh",  "bitc",  "zeh",   "wsbh",     "or_srli",  "divsr",    "divr",
-  "sva",  "svs",  "cmovz", "cmovn", "add_srli", "sub_srli", "and_srli", "xor_srli"
+  /* Track the last type (although this doesn't seem to be useful).  */
+  enum map_type last_mapping_type;
+
+  /* Tracking symbol table information.  */
+  int last_symbol_index;
+  bfd_vma last_addr;
 };
 
+/* Default text to print if an instruction isn't recognized.  */
+#define UNKNOWN_INSN_MSG _("*unknown*")
+#define NDS32_PARSE_INSN16      0x01
+#define NDS32_PARSE_INSN32      0x02
 
-static const char *mnemonic_alu20[] =
-{
-  "max",     "min",    "ave",     "abs",    "clips",   "clip",   "clo",    "clz",
-  "bset",    "bclr",   "btgl",    "btst",   "bse",     "bsp",    "ffb",    "ffmism",
-  "add.sc",  "sub.sc", "add.wc",  "sub.wc", "24",      "25",     "26",     "ffzmism",
-  "qadd",    "qsub",   "32",      "33",     "34",      "35",     "36",     "37",
-  "mfusr",   "mtusr",  "42",      "43",     "mul",     "45",     "46",     "47",
-  "mults64", "mult64", "madds64", "madd64", "msubs64", "msub64", "divs", "div",
-  "60",      "mult32", "62",      "madd32", "64",      "msub32", "65",   "66",
-  "dmadd",   "dmaddc", "dmsub",   "dmsubc", "rmfhi",   "qmflo"
-};
+extern const field_t *nds32_field_table[NDS32_CORE_COUNT];
+extern opcode_t *nds32_opcode_table[NDS32_CORE_COUNT];
+extern keyword_t **nds32_keyword_table[NDS32_CORE_COUNT];
+extern struct nds32_opcode nds32_opcodes[];
+extern const field_t operand_fields[];
+extern keyword_t *keywords[];
+extern const keyword_t keyword_gpr[];
 
-static const char *mnemonic_alu21[] =
-{
-  "00",      "01",     "02", "03",      "04", "05",      "06",   "07",
-  "10",      "11",     "12", "13",      "14", "15",      "ffbi", "flmism",
-  "20",      "21",     "22", "23",      "24", "25",      "26",   "27",
-  "30",      "31",     "32", "33",      "34", "35",      "36",   "37",
-  "40",      "41",     "42", "43",      "44", "45",      "46",   "47",
-  "mulsr64", "mulr64", "52", "53",      "54", "55",      "56",   "57",
-  "60",      "61",     "62", "maddr32", "64", "msubr32", "66",   "67",
-  "70",      "71",     "72", "73",      "74", "75",      "76",   "77"
-};
+static uint32_t nds32_mask_opcode (uint32_t);
+static void nds32_special_opcode (uint32_t, struct nds32_opcode **);
+static int get_mapping_symbol_type (struct disassemble_info *, int,
+                                   enum map_type *);
+static int is_mapping_symbol (struct disassemble_info *, int,
+                             enum map_type *);
 
-static const char *mnemonic_br2[] =
-{
-  "ifcall", "01", "beqz", "bnez", "bgez",   "bltz",   "bgtz", "blez",
-  "10",     "11", "12",   "13",   "bgezal", "bltzal"
-};
+/* Hash function for disassemble.  */
 
-static const char *mnemonic_misc[] =
-{
-  "standby", "cctl", "mfsr",  "mtsr",    "iret",  "trap",  "teqz", "tnez",
-  "dsb",     "isb",  "break", "syscall", "msync", "isync", "tlbop"
-};
+static htab_t opcode_htab;
 
-static const char *mnemonic_hwgp[] =
-{
-  "lhi.gp", "lhi.gp", "lhsi.gp", "lhsi.gp",
-  "shi.gp", "shi.gp", "lwi.gp", "swi.gp"
-};
+/* Find the value map register name.  */
 
-static const char *keyword_dpref[] =
+static keyword_t *
+nds32_find_reg_keyword (keyword_t *reg, int value)
 {
-  "SRD", "MRD", "SWR", "MWR", "PTE", "CLWR", "6",  "7",
-  "8",   "9",   "10",  "11",  "12",  "13",   "14", "15"
-};
+  if (!reg)
+    return NULL;
 
-static const char *mnemonic_alu[] =
-{
-  "fadds",   "fsubs",   "fcpynss", "fcpyss",  "fmadds",
-  "fmsubs",  "fcmovns", "fcmovzs", "fnmadds", "fnmsubs",
-  "10",      "11",      "fmuls",   "fdivs",   "faddd",
-  "fsubd",   "fcpynsd", "fcpysd",  "fmaddd",  "fmsubd",
-  "fcmovnd", "fcmovzd", "fnmaddd", "fnmsubd", "24",
-  "25",      "fmuld",   "fdivd"
-};
+  while (reg->name != NULL && reg->value != value)
+    {
+      reg++;
+    }
+  if (reg->name == NULL)
+    return NULL;
+  return reg;
+}
 
-static const char *mnemonic_fpu_2op[] =
+static void
+nds32_parse_audio_ext (const field_t *pfd,
+                      disassemble_info *info, uint32_t insn)
 {
-  "fs2d",  "fsqrts",  "2",     "3",  "4",       "fabss",  "6",      "7",
-  "fui2s", "9",       "10",    "11", "fsi2s",   "13",     "14",     "15",
-  "fs2ui", "17",      "18",    "19", "fs2ui.z", "21",     "22",     "23",
-  "fs2si", "25",      "26",    "27", "fs2si.z", "fd2s",   "fsqrtd", "31",
-  "32",    "33",      "fabsd", "35", "36",      "fui2d",  "38",     "39",
-  "40",    "fsi2d",   "42",    "43", "44",      "fd2ui",  "46",     "47",
-  "48",    "fd2ui.z", "50",    "51", "52",      "fd2si",  "54",     "55",
-  "56",    "fd2si.z"
-};
+  fprintf_ftype func = info->fprintf_func;
+  void *stream = info->stream;
+  keyword_t *psys_reg;
+  int int_value, new_value;
 
-static const char *mnemonic_fs2_cmp[] =
-{
-  "fcmpeqs", "fcmpeqs.e", "fcmplts", "fcmplts.e",
-  "fcmples", "fcmples.e", "fcmpuns", "fcmpuns.e"
-};
+  if (pfd->hw_res == HW_INT || pfd->hw_res == HW_UINT)
+    {
+      if (pfd->hw_res == HW_INT)
+       int_value = (unsigned) N32_IMMS (insn >> pfd->bitpos,
+                                        pfd->bitsize) << pfd->shift;
+      else
+       int_value = __GF (insn, pfd->bitpos, pfd->bitsize) << pfd->shift;
 
-static const char *mnemonic_fd2_cmp[] =
-{
-  "fcmpeqd", "fcmpeqd.e", "fcmpltd", "fcmpltd.e",
-  "fcmpled", "fcmpled.e", "fcmpund", "fcmpund.e"
-};
+      if (int_value < 10)
+       func (stream, "#%d", int_value);
+      else
+       func (stream, "#0x%x", int_value);
+      return;
+    }
+  int_value =
+    __GF (insn, pfd->bitpos, pfd->bitsize) << pfd->shift;
+  new_value = int_value;
+  psys_reg = (keyword_t*) keywords[pfd->hw_res];
+
+  /* p = bit[4].bit[1:0], r = bit[4].bit[3:2].  */
+  if (strcmp (pfd->name, "im5_i") == 0)
+    {
+      new_value = int_value & 0x03;
+      new_value |= ((int_value & 0x10) >> 2);
+    }
+  else if (strcmp (pfd->name, "im5_m") == 0)
+    {
+      new_value = ((int_value & 0x1C) >> 2);
+    }
+  /* p = 0.bit[1:0], r = 0.bit[3:2].  */
+  /* q = 1.bit[1:0], s = 1.bit[5:4].  */
+  else if (strcmp (pfd->name, "im6_iq") == 0)
+    {
+      new_value |= 0x04;
+    }
+  else if (strcmp (pfd->name, "im6_ms") == 0)
+    {
+      new_value |= 0x04;
+    }
+  /*  Rt CONCAT(c, t21, t0).  */
+  else if (strcmp (pfd->name, "a_rt21") == 0)
+    {
+      new_value = (insn & 0x00000020) >> 5;
+      new_value |= (insn & 0x00000C00) >> 9;
+      new_value |= (insn & 0x00008000) >> 12;
+    }
+  else if (strcmp (pfd->name, "a_rte") == 0)
+    {
+      new_value = (insn & 0x00000C00) >> 9;
+      new_value |= (insn & 0x00008000) >> 12;
+    }
+  else if (strcmp (pfd->name, "a_rte1") == 0)
+    {
+      new_value = (insn & 0x00000C00) >> 9;
+      new_value |= (insn & 0x00008000) >> 12;
+      new_value |= 0x01;
+    }
+  else if (strcmp (pfd->name, "a_rte69") == 0)
+    {
+      new_value = int_value << 1;
+    }
+  else if (strcmp (pfd->name, "a_rte69_1") == 0)
+    {
+      new_value = int_value << 1;
+      new_value |= 0x01;
+    }
+
+  psys_reg = nds32_find_reg_keyword (psys_reg, new_value);
+  if (!psys_reg)
+    func (stream, "???");
+  else
+    func (stream, "$%s", psys_reg->name);
+}
 
-/* Register name table.  */
-/* General purpose register.  */
+/* Match instruction opcode with keyword table.  */
 
-static const char *gpr_map[] =
+static field_t *
+match_field (char *name)
 {
-  "$r0", "$r1", "$r2", "$r3", "$r4", "$r5", "$r6", "$r7",
-  "$r8", "$r9", "$r10", "$r11", "$r12", "$r13", "$r14", "$r15",
-  "$r16", "$r17", "$r18", "$r19", "$r20", "$r21", "$r22", "$r23",
-  "$r24", "$r25", "$r26", "$r27", "$fp", "$gp", "$lp", "$sp"
-};
+  field_t *pfd;
+  int k;
 
-/* User special register.  */
+  for (k = 0; k < NDS32_CORE_COUNT; k++)
+    {
+      pfd = (field_t *) nds32_field_table[k];
+      while (1)
+       {
+         if (pfd->name == NULL)
+           break;
+         if (strcmp (name, pfd->name) == 0)
+           return pfd;
+         pfd++;
+       }
+    }
 
-static const char *usr_map[][32] =
-{
-  {
-    "d0.lo", "d0.hi", "d1.lo", "d1.hi", "4",  "5",  "6",  "7",
-    "8",     "9",     "10",    "11",    "12", "13", "14", "15",
-    "16",    "17",    "18",    "19",    "20", "21", "22", "23",
-    "24",    "25",    "26",    "27",    "28", "29", "30", "pc"
-  },
-  {
-    "DMA_CFG",     "DMA_GCSW",    "DMA_CHNSEL", "DMA_ACT",    "DMA_SETUP",
-    "DMA_ISADDR",  "DMA_ESADDR",  "DMA_TCNT",   "DMA_STATUS", "DMA_2DSET",
-    "10",          "11",          "12",         "13",         "14",
-    "15",          "16",          "17",         "18",         "19",
-    "20",          "21",          "22",         "23",         "24",
-    "DMA_2DSCTL"
-  },
-  {
-    "PFMC0", "PFMC1", "PFMC2", "3", "PFM_CTL"
-  }
-};
+  return NULL;
+}
 
-/* System register.  */
-/* Major Minor Extension.  */
-static const char *sr_map[8][16][8] =
-{
-  {
-    {"CPU_VER", "CORE_ID"},
-    {"ICM_CFG"},
-    {"DCM_CFG"},
-    {"MMU_CFG"},
-    {"MSC_CFG"}
-  },
-  {
-    {"PSW", "IPSW", "P_IPSW"},
-    {"0", "IVB", "INT_CTRL"},
-    {"0", "EVA", "P_EVA"},
-    {"0", "ITYPE", "P_ITYPE"},
-    {"0", "MERR"},
-    {"0", "IPC", "P_IPC", "OIPC"},
-    {"0", "1", "P_P0"},
-    {"0", "1", "P_P1"},
-    {"INT_MASK", "INT_MASK2"},
-    {"INT_PEND", "INT_PEND2", "2", "3", "INT_TRIGGER"},
-    {"SP_USR", "SP_PRIV"},
-    {"INT_PRI", "INT_PRI2"}
-  },
-  {
-    {"MMU_CTL"},
-    {"L1_PPTB"},
-    {"TLB_VPN"},
-    {"TLB_DATA"},
-    {"TLB_MISC"},
-    {"VLPT_IDX"},
-    {"ILMB"},
-    {"DLMB"},
-    {"CACHE_CTL"},
-    {"HSMP_SADDR", "HSMP_EADDR"},
-    {"0"},
-    {"0"},
-    {"0"},
-    {"0"},
-    {"0"},
-    {"SDZ_CTL", "MISC_CTL"}
-  },
-  {
-    {"BPC0", "BPC1", "BPC2", "BPC3", "BPC4", "BPC5", "BPC6", "BPC7"},
-    {"BPA0", "BPA1", "BPA2", "BPA3", "BPA4", "BPA5", "BPA6", "BPA7"},
-    {"BPAM0", "BPAM1", "BPAM2", "BPAM3", "BPAM4", "BPAM5", "BPAM6", "BPAM7"},
-    {"BPV0", "BPV1", "BPV2", "BPV3", "BPV4", "BPV5", "BPV6", "BPV7"},
-    {"BPCID0", "BPCID1", "BPCID2", "BPCID3", "BPCID4", "BPCID5", "BPCID6", "BPCID7"},
-    {"EDM_CFG"},
-    {"EDMSW"},
-    {"EDM_CTL"},
-    {"EDM_DTR"},
-    {"BPMTC"},
-    {"DIMBR"},
-    {"EDM_PROBE"},
-    {"0"},
-    {"0"},
-    {"TECR0", "TECR1"}
-  },
-  {
-    {"PFMC0", "PFMC1", "PFMC2"},
-    {"PFM_CTL"},
-    {"0"},
-    {"0"},
-    {"PRUSR_ACC_CTL"},
-    {"FUCOP_CTL"}
-  },
-  {
-    {"DMA_CFG"},
-    {"DMA_GCSW"},
-    {"DMA_CHNSEL"},
-    {"DMA_ACT"},
-    {"DMA_SETUP"},
-    {"DMA_ISADDR"},
-    {"DMA_ESADDR"},
-    {"DMA_TCNT"},
-    {"DMA_STATUS"},
-    {"DMA_2DSET", "DMA_2DSCTL"}
-  }
-};
+/* Dump instruction.  If the opcode is unknown, return FALSE.  */
 
 static void
-print_insn16 (bfd_vma pc, disassemble_info *info, uint32_t insn)
+nds32_parse_opcode (struct nds32_opcode *opc, bfd_vma pc ATTRIBUTE_UNUSED,
+                   disassemble_info *info, uint32_t insn,
+                   uint32_t parse_mode)
 {
-  static char r4map[] =
-    {
-      0, 1, 2, 3, 4, 5, 6, 7,
-      8, 9, 10, 11, 16, 17, 18, 19
-    };
-  const int rt5 = __GF (insn, 5, 5);
-  const int ra5 = __GF (insn, 0, 5);
-  const int rt4 = r4map[__GF (insn, 5, 4)];
-  const int imm5u = IMMU (insn, 5);
-  const int imm9u = IMMU (insn, 9);
-  const int rt3 = __GF (insn, 6, 3);
-  const int ra3 = __GF (insn, 3, 3);
-  const int rb3 = __GF (insn, 0, 3);
-  const int rt38 = __GF (insn, 8, 3);
-  const int imm3u = rb3;
+  int op = 0;
   fprintf_ftype func = info->fprintf_func;
   void *stream = info->stream;
-
-  static const char *mnemonic_96[] =
-  {
-    "0x1",        "0x1",       "0x2",     "0x3",
-    "add45",      "sub45",     "addi45",  "subi45",
-    "srai45",     "srli45",    "slli333", "0xb",
-    "add333",     "sub333",    "addi333", "subi333",
-    "lwi333",     "lwi333.bi", "lhi333",  "lbi333",
-    "swi333",     "swi333.bi", "shi333",  "sbi333",
-    "addri36.sp", "lwi45.fe",  "lwi450",  "swi450",
-    "0x1c",       "0x1d",      "0x1e",    "0x1f",
-    "0x20",       "0x21",      "0x22",    "0x23",
-    "0x24",       "0x25",      "0x26",    "0x27",
-    "0x28",       "0x29",      "0x2a",    "0x2b",
-    "0x2c",       "0x2d",      "0x2e",    "0x2f",
-    "slts45",     "slt45",     "sltsi45", "slti45",
-    "0x34",       "0x35",      "0x36",    "0x37",
-    "0x38",       "0x39",      "0x3a",    "0x3b",
-    "ifcall9",    "movpi45"
-  };
-
-  static const char *mnemonic_misc33[] =
-  {
-    "misc33_0", "misc33_1", "neg33", "not33", "mul33", "xor33", "and33", "or33",
-  };
-
-  static const char *mnemonic_0xb[] =
-  {
-    "zeb33", "zeh33", "seb33", "seh33", "xlsb33", "x11b33", "bmski33", "fexti33"
-  };
-
-  static const char *mnemonic_bnes38[] =
-  {
-    "jr5", "jral5", "ex9.it", "?", "ret5", "add5.pc"
-  };
-
-  switch (__GF (insn, 7, 8))
+  const char *pstr_src;
+  char *pstr_tmp;
+  char tmp_string[16];
+  unsigned int push25gpr = 0, lsmwRb, lsmwRe, lsmwEnb4, checkbit, i;
+  int int_value, ifthe1st = 1;
+  const field_t *pfd;
+  keyword_t *psys_reg;
+
+  if (opc == NULL)
     {
-    case 0xf8:                 /* push25 */
-    case 0xf9:                 /* pop25 */
-      {
-       uint32_t res[] = { 6, 8, 10, 14 };
-       uint32_t re = res[__GF (insn, 5, 2)];
-
-       func (stream, "%s\t%s, %d", (insn & __BIT (7)) ? "pop25" : "push25",
-             gpr_map[re], imm5u << 3);
-      }
+      func (stream, UNKNOWN_INSN_MSG);
       return;
     }
 
-  if (__GF (insn, 8, 7) == 0x7d)       /* movd44 */
+  pstr_src = opc->instruction;
+  if (*pstr_src == 0)
     {
-      int rt5e = __GF (insn, 4, 4) << 1;
-      int ra5e = IMMU (insn, 4) << 1;
-
-      func (stream, "movd44\t%s, %d", gpr_map[rt5e], ra5e);
+      func (stream, "%s", opc->opcode);
       return;
     }
-
-  switch (__GF (insn, 9, 6))
+  /* NDS32_PARSE_INSN16.  */
+  if (parse_mode & NDS32_PARSE_INSN16)
     {
-    case 0x4:                  /* add45 */
-    case 0x5:                  /* sub45 */
-    case 0x30:                 /* slts45 */
-    case 0x31:                 /* slt45 */
-      func (stream, "%s\t%s, %s", mnemonic_96[__GF (insn, 9, 6)],
-           gpr_map[rt4], gpr_map[ra5]);
-      return;
-    case 0x6:                  /* addi45 */
-    case 0x7:                  /* subi45 */
-    case 0x8:                  /* srai45 */
-    case 0x9:                  /* srli45 */
-    case 0x32:                 /* sltsi45 */
-    case 0x33:                 /* slti45 */
-      func (stream, "%s\t%s, %d", mnemonic_96[__GF (insn, 9, 6)],
-           gpr_map[rt4], ra5);
-      return;
-    case 0xc:                  /* add333 */
-    case 0xd:                  /* sub333 */
-      func (stream, "%s\t%s, %s, %s", mnemonic_96[__GF (insn, 9, 6)],
-           gpr_map[rt3], gpr_map[ra3], gpr_map[rb3]);
-      return;
-    case 0xa:                  /* slli333 */
-    case 0xe:                  /* addi333 */
-    case 0xf:                  /* subi333 */
-      func (stream, "%s\t%s, %s, %d", mnemonic_96[__GF (insn, 9, 6)],
-           gpr_map[rt3], gpr_map[ra3], imm3u);
-      return;
-    case 0x10:                 /* lwi333 */
-    case 0x14:                 /* swi333 */
-      func (stream, "%s\t%s, [%s + %d]", mnemonic_96[__GF (insn, 9, 6)],
-           gpr_map[rt3], gpr_map[ra3], imm3u << 2);
-      return;
-    case 0x12:                 /* lhi333 */
-    case 0x16:                 /* shi333 */
-      func (stream, "%s\t%s, [%s + %d]", mnemonic_96[__GF (insn, 9, 6)],
-           gpr_map[rt3], gpr_map[ra3], imm3u << 1);
-      return;
-    case 0x13:                 /* lbi333 */
-    case 0x17:                 /* sbi333 */
-      func (stream, "%s\t%s, [%s + %d]", mnemonic_96[__GF (insn, 9, 6)],
-           gpr_map[rt3], gpr_map[ra3], imm3u);
-      return;
-    case 0x11:                 /* lwi333.bi */
-    case 0x15:                 /* swi333.bi */
-      func (stream, "%s\t%s, [%s], %d", mnemonic_96[__GF (insn, 9, 6)],
-           gpr_map[rt3], gpr_map[ra3], imm3u << 2);
-      return;
-    case 0x18:                 /* addri36.sp */
-      func (stream, "%s\t%s, %d", mnemonic_96[__GF (insn, 9, 6)],
-           gpr_map[rt3], IMMU (insn, 6) << 2);
-      return;
-    case 0x19:                 /* lwi45.fe */
-      func (stream, "%s\t%s, %d", mnemonic_96[__GF (insn, 9, 6)],
-           gpr_map[rt4], -((32 - imm5u) << 2));
-      return;
-    case 0x1a:                 /* lwi450 */
-    case 0x1b:                 /* swi450 */
-      func (stream, "%s\t%s, [%s]", mnemonic_96[__GF (insn, 9, 6)],
-           gpr_map[rt4], gpr_map[ra5]);
-      return;
-    case 0x34:                 /* beqzs8, bnezs8 */
-      func (stream, "%s\t", ((insn & __BIT (8)) ? "bnezs8" : "beqzs8"));
-      info->print_address_func ((IMMS (insn, 8) << 1) + pc, info);
-      return;
-    case 0x35:                 /* break16, ex9.it */
-      /* FIXME: Check bfd_mach.  */
-      if (imm9u < 32)          /* break16 */
-        func (stream, "break16\t%d", imm9u);
-      else
-        func (stream, "ex9.it\t%d", imm9u);
-      return;
-    case 0x3c:                 /* ifcall9 */
-      func (stream, "%s\t", mnemonic_96[__GF (insn, 9, 6)]);
-      info->print_address_func ((IMMU (insn, 9) << 1) + pc, info);
-      return;
-    case 0x3d:                 /* movpi45 */
-      func (stream, "%s\t%s, %d", mnemonic_96[__GF (insn, 9, 6)],
-           gpr_map[rt4], ra5 + 16);
-      return;
-    case 0x3f:                 /* MISC33 */
-      func (stream, "%s\t%s, %s", mnemonic_misc33[rb3],
-           gpr_map[rt3], gpr_map[ra3]);
-      return;
-    case 0xb:                  /* ...  */
-      func (stream, "%s\t%s, %s", mnemonic_0xb[rb3],
-          gpr_map[rt3], gpr_map[ra3]);
-      return;
+      func (stream, "%s ", opc->opcode);
     }
 
-  switch (__GF (insn, 10, 5))
+  /* NDS32_PARSE_INSN32.  */
+  else
     {
-    case 0x0:                  /* mov55 or ifret16 */
-      /* FIXME: Check bfd_mach.  */
-      if (rt5 == ra5 && rt5 == 31)
-        func (stream, "ifret16");
+      op = N32_OP6 (insn);
+      if (op == N32_OP6_LSMW)
+       func (stream, "%s.", opc->opcode);
+      else if (strstr (opc->instruction, "tito"))
+       func (stream, "%s", opc->opcode);
       else
-        func (stream, "mov55\t%s, %s", gpr_map[rt5], gpr_map[ra5]);
-      return;
-    case 0x1:                  /* movi55 */
-      func (stream, "movi55\t%s, %d", gpr_map[rt5], IMMS (insn, 5));
-      return;
-    case 0x1b:                 /* addi10s (V2) */
-      func (stream, "addi10s\t%d", IMMS (insn, 10));
-      return;
+       func (stream, "%s\t", opc->opcode);
     }
 
-  switch (__GF (insn, 11, 4))
+  while (*pstr_src)
     {
-    case 0x7:                  /* lwi37.fp/swi37.fp */
-      func (stream, "%s\t%s, [$fp + 0x%x]",
-           ((insn & __BIT (7)) ? "swi37" : "lwi37"),
-           gpr_map[rt38], IMMU (insn, 7) << 2);
-      return;
-    case 0x8:                  /* beqz38 */
-    case 0x9:                  /* bnez38 */
-      func (stream, "%s\t%s, ",
-           ((__GF (insn, 11, 4) & 1) ? "bnez38" : "beqz38"), gpr_map[rt38]);
-      info->print_address_func ((IMMS (insn, 8) << 1) + pc, info);
-      return;
-    case 0xa:                  /* beqs38/j8, implied r5 */
-      if (rt38 == 5)
-       {
-         func (stream, "j8\t");
-         info->print_address_func ((IMMS (insn, 8) << 1) + pc, info);
-       }
-     else
+      switch (*pstr_src)
        {
-         func (stream, "beqs38\t%s, ", gpr_map[rt38]);
-         info->print_address_func ((IMMS (insn, 8) << 1) + pc, info);
-       }
-      return;
-    case 0xb:                  /* bnes38 and others */
-      if (rt38 == 5)
-       {
-         switch (__GF (insn, 5, 3))
+       case '%':
+       case '=':
+       case '&':
+         pstr_src++;
+         /* Compare with operand_fields[].name.  */
+         pstr_tmp = &tmp_string[0];
+         while (*pstr_src)
            {
-           case 0:             /* jr5 */
-           case 1:             /* jral5 */
-           case 4:             /* ret5 */
-             func (stream, "%s\t%s", mnemonic_bnes38[__GF (insn, 5, 3)],
-                   gpr_map[ra5]);
-             return;
-           case 2:             /* ex9.it imm5 */
-           case 5:             /* add5.pc */
-             func (stream, "%s\t%d", mnemonic_bnes38[__GF (insn, 5, 3)], ra5);
-             return;
-           default:
-             func (stream, UNKNOWN_INSN_MSG);
-             return;
+             if ((*pstr_src == ',') || (*pstr_src == ' ')
+                 || (*pstr_src == '{') || (*pstr_src == '}')
+                 || (*pstr_src == '[') || (*pstr_src == ']')
+                 || (*pstr_src == '(') || (*pstr_src == ')')
+                 || (*pstr_src == '+') || (*pstr_src == '<'))
+               break;
+             *pstr_tmp++ = *pstr_src++;
            }
+         *pstr_tmp = 0;
+
+         if ((pfd = match_field (&tmp_string[0])) == NULL)
+           return;
+
+         /* For insn-16.  */
+         if (parse_mode & NDS32_PARSE_INSN16)
+           {
+             if (pfd->hw_res == HW_GPR)
+               {
+                 int_value =
+                   __GF (insn, pfd->bitpos, pfd->bitsize) << pfd->shift;
+                 /* push25/pop25.  */
+                 if ((opc->value == 0xfc00) || (opc->value == 0xfc80))
+                   {
+                     if (int_value == 0)
+                       int_value = 6;
+                     else
+                       int_value = (6 + (0x01 << int_value));
+                     push25gpr = int_value;
+                   }
+                 else if (strcmp (pfd->name, "rt4") == 0)
+                   {
+                     int_value = nds32_r45map[int_value];
+                   }
+                 func (stream, "$%s", keyword_gpr[int_value].name);
+               }
+             else if ((pfd->hw_res == HW_INT) || (pfd->hw_res == HW_UINT))
+               {
+                 if (pfd->hw_res == HW_INT)
+                   int_value
+                     = (unsigned) N32_IMMS (insn >> pfd->bitpos,
+                                            pfd->bitsize) << pfd->shift;
+                 else
+                   int_value =
+                     __GF (insn, pfd->bitpos, pfd->bitsize) << pfd->shift;
+
+                 /* movpi45.  */
+                 if (opc->value == 0xfa00)
+                   {
+                     int_value += 16;
+                     func (stream, "#0x%x", int_value);
+                   }
+                 /* lwi45.fe.  */
+                 else if (opc->value == 0xb200)
+                   {
+                     int_value = 0 - (128 - int_value);
+                     func (stream, "#%d", int_value);
+                   }
+                 /* beqz38/bnez38/beqs38/bnes38/j8/beqzs8/bnezs8.  */
+                 else if ((opc->value == 0xc000) || (opc->value == 0xc800)
+                          || (opc->value == 0xd000) || (opc->value == 0xd800)
+                          || (opc->value == 0xd500) || (opc->value == 0xe800)
+                          || (opc->value == 0xe900))
+                   {
+                     info->print_address_func (int_value + pc, info);
+                   }
+                 /* push25/pop25.  */
+                 else if ((opc->value == 0xfc00) || (opc->value == 0xfc80))
+                   {
+                     func (stream, "#%d    ! {$r6", int_value);
+                     if (push25gpr != 6)
+                       func (stream, "~$%s", keyword_gpr[push25gpr].name);
+                     func (stream, ", $fp, $gp, $lp}");
+                   }
+                 else if (pfd->hw_res == HW_INT)
+                   {
+                     if (int_value < 10)
+                       func (stream, "#%d", int_value);
+                     else
+                       func (stream, "#0x%x", int_value);
+                   }
+                 else /* if (pfd->hw_res == HW_UINT).  */
+                   {
+                     if (int_value < 10)
+                       func (stream, "#%u", int_value);
+                     else
+                       func (stream, "#0x%x", int_value);
+                   }
+               }
+
+           }
+         /* for audio-ext.  */
+         else if (op == N32_OP6_AEXT)
+           {
+             nds32_parse_audio_ext (pfd, info, insn);
+           }
+         /* for insn-32.  */
+         else if (pfd->hw_res < HW_INT)
+           {
+             int_value =
+               __GF (insn, pfd->bitpos, pfd->bitsize) << pfd->shift;
+
+             psys_reg = *(nds32_keyword_table[pfd->hw_res >> 8]
+                          + (pfd->hw_res & 0xff));
+
+             psys_reg = nds32_find_reg_keyword (psys_reg, int_value);
+             /* For HW_SR, dump the index when it can't
+                map the register name.  */
+             if (!psys_reg && pfd->hw_res == HW_SR)
+               func (stream, "%d", int_value);
+             else if (!psys_reg)
+               func (stream, "???");
+             else
+               {
+                 if (pfd->hw_res == HW_GPR || pfd->hw_res == HW_CPR
+                     || pfd->hw_res == HW_FDR || pfd->hw_res == HW_FSR
+                     || pfd->hw_res == HW_DXR || pfd->hw_res == HW_SR
+                     || pfd->hw_res == HW_USR)
+                   func (stream, "$%s", psys_reg->name);
+                 else if (pfd->hw_res == HW_DTITON
+                          || pfd->hw_res == HW_DTITOFF)
+                   func (stream, ".%s", psys_reg->name);
+                 else
+                   func (stream, "%s", psys_reg->name);
+               }
+           }
+         else if ((pfd->hw_res == HW_INT) || (pfd->hw_res == HW_UINT))
+           {
+             if (pfd->hw_res == HW_INT)
+               int_value = (unsigned) N32_IMMS (insn >> pfd->bitpos,
+                                                pfd->bitsize) << pfd->shift;
+             else
+               int_value =
+                 __GF (insn, pfd->bitpos, pfd->bitsize) << pfd->shift;
+
+             if ((op == N32_OP6_BR1) || (op == N32_OP6_BR2))
+               {
+                 info->print_address_func (int_value + pc, info);
+               }
+             else if ((op == N32_OP6_BR3) && (pfd->bitpos == 0))
+               {
+                 info->print_address_func (int_value + pc, info);
+               }
+             else if (op == N32_OP6_JI)
+               {
+                 /* FIXME: Handle relocation.  */
+                 if (info->flags & INSN_HAS_RELOC)
+                   pc = 0;
+                 info->print_address_func (int_value + pc, info);
+               }
+             else if (op == N32_OP6_LSMW)
+               {
+                 /* lmw.adm/smw.adm.  */
+                 func (stream, "#0x%x    ! {", int_value);
+                 lsmwEnb4 = int_value;
+                 lsmwRb = ((insn >> 20) & 0x1F);
+                 lsmwRe = ((insn >> 10) & 0x1F);
+
+                 /* If [Rb, Re] specifies at least one register,
+                    Rb(4,0) <= Re(4,0) and 0 <= Rb(4,0), Re(4,0) < 28.
+                    Disassembling does not consider this currently because of
+                    the convience comparing with bsp320.  */
+                 if (lsmwRb != 31 || lsmwRe != 31)
+                   {
+                     func (stream, "$%s", keyword_gpr[lsmwRb].name);
+                     if (lsmwRb != lsmwRe)
+                       func (stream, "~$%s", keyword_gpr[lsmwRe].name);
+                     ifthe1st = 0;
+                   }
+                 if (lsmwEnb4 != 0)
+                   {
+                     /* $fp, $gp, $lp, $sp.  */
+                     checkbit = 0x08;
+                     for (i = 0; i < 4; i++)
+                       {
+                         if (lsmwEnb4 & checkbit)
+                           {
+                             if (ifthe1st == 1)
+                               {
+                                 ifthe1st = 0;
+                                 func (stream, "$%s", keyword_gpr[28 + i].name);
+                               }
+                             else
+                               func (stream, ", $%s", keyword_gpr[28 + i].name);
+                           }
+                         checkbit >>= 1;
+                       }
+                   }
+                 func (stream, "}");
+               }
+             else if (pfd->hw_res == HW_INT)
+               {
+                 if (int_value < 10)
+                   func (stream, "#%d", int_value);
+                 else
+                   func (stream, "#0x%x", int_value);
+               }
+             else /* if (pfd->hw_res == HW_UINT).  */
+               {
+                 if (int_value < 10)
+                   func (stream, "#%u", int_value);
+                 else
+                   func (stream, "#0x%x", int_value);
+               }
+           }
+         break;
+
+       case '{':
+       case '}':
+         pstr_src++;
+         break;
+
+       case ',':
+         func (stream, ", ");
+         pstr_src++;
+         break;
+         
+       case '+':
+         func (stream, " + ");
+         pstr_src++;
+         break;
+         
+       case '<':
+         if (pstr_src[1] == '<')
+           {
+             func (stream, " << ");
+             pstr_src += 2;
+           }
+         else
+           {
+             func (stream, " <");
+             pstr_src++;
+           }
+         break;
+         
+       default:
+         func (stream, "%c", *pstr_src++);
+         break;
        }
-      else
-       {
-         func (stream, "bnes38\t%s", gpr_map[rt3]);
-         info->print_address_func ((IMMS (insn, 8) << 1) + pc, info);
-       }
-      return;
-    case 0xe:                  /* lwi37/swi37 */
-      func (stream, "%s\t%s, [+ 0x%x]",
-           ((insn & __BIT (7)) ? "swi37.sp" : "lwi37.sp"),
-           gpr_map[rt38], IMMU (insn, 7) << 2);
-      return;
     }
 }
 
+/* Filter instructions with some bits must be fixed.  */
 
 static void
-print_insn32_mem (bfd_vma pc ATTRIBUTE_UNUSED, disassemble_info *info,
-                 uint32_t insn)
+nds32_filter_unknown_insn (uint32_t insn, struct nds32_opcode **opc)
 {
-  const int rt = RT5 (insn);
-  const int ra = RA5 (insn);
-  const int rb = RB5 (insn);
-  const int sv = __GF (insn, 8, 2);
-  const int op = insn & 0xFF;
-  fprintf_ftype func = info->fprintf_func;
-  void *stream = info->stream;
+  if (!(*opc))
+    return;
 
-  switch (op)
+  switch ((*opc)->value)
     {
-    case 0x0:                  /* lb */
-    case 0x1:                  /* lh */
-    case 0x2:                  /* lw */
-    case 0x3:                  /* ld */
-    case 0x8:                  /* sb */
-    case 0x9:                  /* sh */
-    case 0xa:                  /* sw */
-    case 0xb:                  /* sd */
-    case 0x10:                 /* lbs */
-    case 0x11:                 /* lhs */
-    case 0x12:                 /* lws */
-    case 0x18:                 /* llw */
-    case 0x19:                 /* scw */
-    case 0x20:                 /* lbup */
-    case 0x22:                 /* lwup */
-    case 0x28:                 /* sbup */
-    case 0x2a:                 /* swup */
-      func (stream, "%s\t%s, [%s + (%s << %d)]",
-           mnemonic_mem[op], gpr_map[rt], gpr_map[ra], gpr_map[rb], sv);
+    case JREG (JR):
+    case JREG (JRNEZ):
+      /* jr jr.xtoff */
+      if (__GF (insn, 6, 2) != 0 || __GF (insn, 15, 10) != 0)
+        *opc = NULL;
       break;
-    case 0x4:                  /* lb.bi */
-    case 0x5:                  /* lh.bi */
-    case 0x6:                  /* lw.bi */
-    case 0x7:                  /* ld.bi */
-    case 0xc:                  /* sb.bi */
-    case 0xd:                  /* sh.bi */
-    case 0xe:                  /* sw.bi */
-    case 0xf:                  /* sd.bi */
-    case 0x14:                 /* lbs.bi */
-    case 0x15:                 /* lhs.bi */
-    case 0x16:                 /* lws.bi */
-      func (stream, "%s\t%s, [%s], (%s << %d)",
-           mnemonic_mem[op], gpr_map[rt], gpr_map[ra], gpr_map[rb], sv);
+    case MISC (STANDBY):
+      if (__GF (insn, 7, 18) != 0)
+        *opc = NULL;
       break;
-    case 0x13:                 /* dpref */
-      {
-       const char *subtype = "???";
-
-       if ((rt & 0xf) < ARRAY_SIZE (keyword_dpref))
-         subtype = keyword_dpref[rt & 0xf];
-
-       func (stream, "%s\t%s, [%s + (%s << %d)]",
-             "dpref", subtype, gpr_map[ra], gpr_map[rb], sv);
-      }
+    case SIMD (PBSAD):
+    case SIMD (PBSADA):
+      if (__GF (insn, 5, 5) != 0)
+        *opc = NULL;
+      break;
+    case BR2 (SOP0):
+      if (__GF (insn, 20, 5) != 0)
+        *opc = NULL;
+      break;
+    case JREG (JRAL):
+      if (__GF (insn, 5, 3) != 0 || __GF (insn, 15, 5) != 0)
+        *opc = NULL;
+      break;
+    case ALU1 (NOR):
+    case ALU1 (SLT):
+    case ALU1 (SLTS):
+    case ALU1 (SLLI):
+    case ALU1 (SRLI):
+    case ALU1 (SRAI):
+    case ALU1 (ROTRI):
+    case ALU1 (SLL):
+    case ALU1 (SRL):
+    case ALU1 (SRA):
+    case ALU1 (ROTR):
+    case ALU1 (SEB):
+    case ALU1 (SEH):
+    case ALU1 (ZEH):
+    case ALU1 (WSBH):
+    case ALU1 (SVA):
+    case ALU1 (SVS):
+    case ALU1 (CMOVZ):
+    case ALU1 (CMOVN):
+      if (__GF (insn, 5, 5) != 0)
+        *opc = NULL;
+      break;
+    case MISC (IRET):
+    case MISC (ISB):
+    case MISC (DSB):
+      if (__GF (insn, 5, 20) != 0)
+        *opc = NULL;
       break;
-    default:
-      func (stream, UNKNOWN_INSN_MSG);
-      return;
     }
 }
 
 static void
-print_insn32_alu1 (bfd_vma pc ATTRIBUTE_UNUSED, disassemble_info *info, uint32_t insn)
+print_insn32 (bfd_vma pc, disassemble_info *info, uint32_t insn,
+             uint32_t parse_mode)
 {
-  int op = insn & 0x1f;
-  const int rt = RT5 (insn);
-  const int ra = RA5 (insn);
-  const int rb = RB5 (insn);
-  const int rd = RD5 (insn);
-  fprintf_ftype func = info->fprintf_func;
-  void *stream = info->stream;
+  /* Get the final correct opcode and parse.  */
+  struct nds32_opcode *opc;
+  uint32_t opcode = nds32_mask_opcode (insn);
+  opc = (struct nds32_opcode *) htab_find (opcode_htab, &opcode);
+
+  nds32_special_opcode (insn, &opc);
+  nds32_filter_unknown_insn (insn, &opc);
+  nds32_parse_opcode (opc, pc, info, insn, parse_mode);
+}
 
-  switch (op)
+static void
+print_insn16 (bfd_vma pc, disassemble_info *info,
+             uint32_t insn, uint32_t parse_mode)
+{
+  struct nds32_opcode *opc;
+  uint32_t opcode;
+
+  /* Get highest 7 bit in default.  */
+  unsigned int mask = 0xfe00;
+
+  /* Classify 16-bit instruction to 4 sets by bit 13 and 14.  */
+  switch (__GF (insn, 13, 2))
     {
-    case 0x0:                  /* add, add_slli */
-    case 0x1:                  /* sub, sub_slli */
-    case 0x2:                  /* and, add_slli */
-    case 0x3:                  /* xor, xor_slli */
-    case 0x4:                  /* or, or_slli */
-      if (rd != 0)
+    case 0x0:
+      /* mov55 movi55 */
+      if (__GF (insn, 11, 2) == 0)
        {
-         func (stream, "%s_slli\t%s, %s, %s, #%d",
-               mnemonic_alu1[op], gpr_map[rt], gpr_map[ra], gpr_map[rb], rd);
+         mask = 0xfc00;
+         /* ifret16 = mov55 $sp, $sp*/
+         if (__GF (insn, 0, 11) == 0x3ff)
+           mask = 0xffff;
        }
-      else
+      else if (__GF (insn, 9, 4) == 0xb)
+       mask = 0xfe07;
+      break;
+    case 0x1:
+      /* lwi37 swi37 */
+      if (__GF (insn, 11, 2) == 0x3)
+       mask = 0xf880;
+      break;
+    case 0x2:
+      mask = 0xf800;
+      /* Exclude beqz38, bnez38, beqs38, and bnes38.  */
+      if (__GF (insn, 12, 1) == 0x1
+         && __GF (insn, 8, 3) == 0x5)
        {
-         func (stream, "%s\t%s, %s, %s",
-               mnemonic_alu1[op], gpr_map[rt], gpr_map[ra], gpr_map[rb]);
+         if (__GF (insn, 11, 1) == 0x0)
+           mask = 0xff00;
+         else
+           mask = 0xffe0;
        }
-      return;
-    case 0x1c:                 /* add_srli */
-    case 0x1d:                 /* sub_srli */
-    case 0x1e:                 /* and_srli */
-    case 0x1f:                 /* xor_srli */
-    case 0x15:                 /* or_srli */
-      func (stream, "%s\t%s, %s, %s, #%d",
-           mnemonic_alu1[op], gpr_map[rt], gpr_map[ra], gpr_map[rb], rd);
-      return;
-    case 0x5:                  /* nor */
-    case 0x6:                  /* slt */
-    case 0x7:                  /* slts */
-    case 0xc:                  /* sll */
-    case 0xd:                  /* srl */
-    case 0xe:                  /* sra */
-    case 0xf:                  /* rotr */
-    case 0x12:                 /* bitc */
-    case 0x18:                 /* sva */
-    case 0x19:                 /* svs */
-    case 0x1a:                 /* cmovz */
-    case 0x1b:                 /* cmovn */
-      func (stream, "%s\t%s, %s, %s",
-           mnemonic_alu1[op], gpr_map[rt], gpr_map[ra], gpr_map[rb]);
-      return;
-    case 0x9:                  /* srli */
-      if (ra ==0 && rb == 0 && rb==0)
+      break;
+    case 0x3:
+      switch (__GF (insn, 11, 2))
        {
-         func (stream, "nop");
-         return;
+       case 0x1:
+         /* beqzs8 bnezs8 */
+         if (__GF (insn, 9, 2) == 0x0)
+           mask = 0xff00;
+         /* addi10s */
+         else if (__GF(insn, 10, 1) == 0x1)
+           mask = 0xfc00;
+         break;
+       case 0x2:
+         /* lwi37.sp swi37.sp */
+         mask = 0xf880;
+         break;
+       case 0x3:
+         if (__GF (insn, 8, 3) == 0x5)
+           mask = 0xff00;
+         else if (__GF (insn, 8, 3) == 0x4)
+           mask = 0xff80;
+         else if (__GF (insn, 9 , 2) == 0x3)
+           mask = 0xfe07;
+         break;
        }
-    case 0x8:                  /* slli */
-    case 0xa:                  /* srai */
-    case 0xb:                  /* rotri */
-      func (stream, "%s\t%s, %s, #%d",
-           mnemonic_alu1[op], gpr_map[rt], gpr_map[ra], rb);
-      return;
-    case 0x10:                 /* seb */
-    case 0x11:                 /* seh */
-    case 0x13:                 /* zeh */
-    case 0x14:                 /* wsbh */
-      func (stream, "%s\t%s, %s",
-           mnemonic_alu1[op], gpr_map[rt], gpr_map[ra]);
-      return;
-    case 0x16:                 /* divsr */
-    case 0x17:                 /* divr */
-      func (stream, "%s\t%s, %s, %s, %s",
-           mnemonic_alu1[op], gpr_map[rt], gpr_map[rd], gpr_map[ra], gpr_map[rb]);
-      return;
-    default:
-      func (stream, UNKNOWN_INSN_MSG);
-      return;
+      break;
     }
+  opcode = insn & mask;
+  opc = (struct nds32_opcode *) htab_find (opcode_htab, &opcode);
 
-  return;
+  nds32_special_opcode (insn, &opc);
+  /* Get the final correct opcode and parse it.  */
+  nds32_parse_opcode (opc, pc, info, insn, parse_mode);
 }
 
-static void
-print_insn32_alu2 (bfd_vma pc ATTRIBUTE_UNUSED,
-                  disassemble_info *info,
-                  uint32_t insn)
+static hashval_t
+htab_hash_hash (const void *p)
 {
-  int op = insn & 0x3ff;
-  const int rt = RT5 (insn);
-  const int ra = RA5 (insn);
-  const int rb = RB5 (insn);
-  fprintf_ftype func = info->fprintf_func;
-  void *stream = info->stream;
-
-  if ((insn & 0x7f) == 0x4e)   /* ffbi */
-    {
-      func (stream, "ffbi\t%s, %s, #0x%x",
-           gpr_map[rt], gpr_map[ra], __GF (insn, 7, 8));
-      return;
-    }
+  return (*(unsigned int *) p) % 49;
+}
 
-  switch (op)
-    {
-    case 0x0:                  /* max */
-    case 0x1:                  /* min */
-    case 0x2:                  /* ave */
-    case 0xc:                  /* bse */
-    case 0xd:                  /* bsp */
-    case 0xe:                  /* ffb */
-    case 0xf:                  /* ffmism */
-    case 0x17:                 /* ffzmism */
-    case 0x24:                 /* mul */
-      func (stream, "%s\t%s, %s, %s", mnemonic_alu20[op],
-           gpr_map[rt], gpr_map[ra], gpr_map[rb]);
-      return;
+static int
+htab_hash_eq (const void *p, const void *q)
+{
+  uint32_t pinsn = ((struct nds32_opcode *) p)->value;
+  uint32_t qinsn = *((uint32_t *) q);
 
-    case 0x3:                  /* abs */
-    case 0x6:                  /* clo */
-    case 0x7:                  /* clz */
-      func (stream, "%s\t%s, %s", mnemonic_alu20[op], gpr_map[rt], gpr_map[ra]);
-      return;
+  return (pinsn == qinsn);
+}
 
-    case 0x4:                  /* clips */
-    case 0x5:                  /* clip */
-    case 0x8:                  /* bset */
-    case 0x9:                  /* bclr */
-    case 0xa:                  /* btgl */
-    case 0xb:                  /* btst */
-      func (stream, "%s\t%s, %s, #%d", mnemonic_alu20[op],
-           gpr_map[rt], gpr_map[ra], IMM1U (insn));
-      return;
+/* Get the format of instruction.  */
 
-    case 0x20:                 /* mfusr */
-    case 0x21:                 /* mtusr */
-      func (stream, "%s\t%s, $%s", mnemonic_alu20[op],
-           gpr_map[rt], usr_map[__GF (insn, 10, 5)][__GF (insn, 15, 5)]);
-      return;
-    case 0x28:                 /* mults64 */
-    case 0x29:                 /* mult64 */
-    case 0x2a:                 /* madds64 */
-    case 0x2b:                 /* madd64 */
-    case 0x2c:                 /* msubs64 */
-    case 0x2d:                 /* msub64 */
-    case 0x2e:                 /* divs */
-    case 0x2f:                 /* div */
-    case 0x31:                 /* mult32 */
-    case 0x33:                 /* madd32 */
-    case 0x35:                 /* msub32 */
-      func (stream, "%s\t$d%d, %s, %s", mnemonic_alu20[op],
-           rt >> 1, gpr_map[ra], gpr_map[rb]);
-      return;
-
-    case 0x4f:                 /* flmism */
-    case 0x68:                 /* mulsr64 */
-    case 0x69:                 /* mulr64 */
-    case 0x73:                 /* maddr32 */
-    case 0x75:                 /* msubr32 */
-      op = insn & 0x3f;
-      func (stream, "%s\t%s, %s, %s", mnemonic_alu21[op],
-           gpr_map[rt], gpr_map[ra], gpr_map[rb]);
-      return;
+static uint32_t
+nds32_mask_opcode (uint32_t insn)
+{
+  uint32_t opcode = N32_OP6 (insn);
+  switch (opcode)
+    {
+    case N32_OP6_LBI:
+    case N32_OP6_LHI:
+    case N32_OP6_LWI:
+    case N32_OP6_LDI:
+    case N32_OP6_LBI_BI:
+    case N32_OP6_LHI_BI:
+    case N32_OP6_LWI_BI:
+    case N32_OP6_LDI_BI:
+    case N32_OP6_SBI:
+    case N32_OP6_SHI:
+    case N32_OP6_SWI:
+    case N32_OP6_SDI:
+    case N32_OP6_SBI_BI:
+    case N32_OP6_SHI_BI:
+    case N32_OP6_SWI_BI:
+    case N32_OP6_SDI_BI:
+    case N32_OP6_LBSI:
+    case N32_OP6_LHSI:
+    case N32_OP6_LWSI:
+    case N32_OP6_LBSI_BI:
+    case N32_OP6_LHSI_BI:
+    case N32_OP6_LWSI_BI:
+    case N32_OP6_MOVI:
+    case N32_OP6_SETHI:
+    case N32_OP6_ADDI:
+    case N32_OP6_SUBRI:
+    case N32_OP6_ANDI:
+    case N32_OP6_XORI:
+    case N32_OP6_ORI:
+    case N32_OP6_SLTI:
+    case N32_OP6_SLTSI:
+    case N32_OP6_CEXT:
+    case N32_OP6_BITCI:
+      return MASK_OP (insn, 0);
+    case N32_OP6_ALU2:
+      /* FFBI */
+      if (__GF (insn, 0, 7) == (N32_ALU2_FFBI | N32_BIT (6)))
+       return MASK_OP (insn, 0x7f);
+      else if (__GF (insn, 0, 7) == (N32_ALU2_MFUSR | N32_BIT (6))
+              || __GF (insn, 0, 7) == (N32_ALU2_MTUSR | N32_BIT (6)))
+       /* RDOV CLROV */
+       return MASK_OP (insn, 0xf81ff);
+      else if (__GF (insn, 0, 10) == (N32_ALU2_ONEOP | N32_BIT (7)))
+       {
+         /* INSB */
+         if (__GF (insn, 12, 3) == 4)
+           return MASK_OP (insn, 0x73ff);
+         return MASK_OP (insn, 0x7fff);
+       }
+      return MASK_OP (insn, 0x3ff);
+    case N32_OP6_ALU1:
+    case N32_OP6_SIMD:
+      return MASK_OP (insn, 0x1f);
+    case N32_OP6_MEM:
+      return MASK_OP (insn, 0xff);
+    case N32_OP6_JREG:
+      return MASK_OP (insn, 0x7f);
+    case N32_OP6_LSMW:
+      return MASK_OP (insn, 0x23);
+    case N32_OP6_SBGP:
+    case N32_OP6_LBGP:
+      return MASK_OP (insn, 0x1 << 19);
+    case N32_OP6_HWGP:
+      if (__GF (insn, 18, 2) == 0x3)
+       return MASK_OP (insn, 0x7 << 17);
+      return MASK_OP (insn, 0x3 << 18);
+    case N32_OP6_DPREFI:
+      return MASK_OP (insn, 0x1 << 24);
+    case N32_OP6_LWC:
+    case N32_OP6_SWC:
+    case N32_OP6_LDC:
+    case N32_OP6_SDC:
+      return MASK_OP (insn, 0x1 << 12);
+    case N32_OP6_JI:
+      return MASK_OP (insn, 0x1 << 24);
+    case N32_OP6_BR1:
+      return MASK_OP (insn, 0x1 << 14);
+    case N32_OP6_BR2:
+      if (__GF (insn, 16, 4) == 0)
+       return MASK_OP (insn, 0x1ff << 16);
+      else
+       return MASK_OP (insn, 0xf << 16);
+    case N32_OP6_BR3:
+      return MASK_OP (insn, 0x1 << 19);
+    case N32_OP6_MISC:
+      switch (__GF (insn, 0, 5))
+       {
+       case N32_MISC_MTSR:
+         /* SETGIE and SETEND  */
+         if (__GF (insn, 5, 5) == 0x1 || __GF (insn, 5, 5) == 0x2)
+           return MASK_OP (insn, 0x1fffff);
+         return MASK_OP (insn, 0x1f);
+       case N32_MISC_TLBOP:
+         if (__GF (insn, 5, 5) == 5 || __GF (insn, 5, 5) == 7)
+           /* PB FLUA  */
+           return MASK_OP (insn, 0x3ff);
+         return MASK_OP (insn, 0x1f);
+       default:
+         return MASK_OP (insn, 0x1f);
+       }
+    case N32_OP6_COP:
+      if (__GF (insn, 4, 2) == 0)
+       {
+         /* FPU */
+         switch (__GF (insn, 0, 4))
+           {
+           case 0x0:
+           case 0x8:
+             /* FS1/F2OP FD1/F2OP */
+             if (__GF (insn, 6, 4) == 0xf)
+               return MASK_OP (insn, 0x7fff);
+             /* FS1 FD1 */
+             return MASK_OP (insn, 0x3ff);
+           case 0x4:
+           case 0xc:
+             /* FS2 */
+             return MASK_OP (insn, 0x3ff);
+           case 0x1:
+           case 0x9:
+             /* XR */
+             if (__GF (insn, 6, 4) == 0xc)
+               return MASK_OP (insn, 0x7fff);
+             /* MFCP MTCP */
+             return MASK_OP (insn, 0x3ff);
+           default:
+             return MASK_OP (insn, 0xff);
+           }
+       }
+      else if  (__GF (insn, 0, 2) == 0)
+       return MASK_OP (insn, 0xf);
+      return MASK_OP (insn, 0xcf);
+    case N32_OP6_AEXT:
+      /* AUDIO */
+      switch (__GF (insn, 23, 2))
+       {
+       case 0x0:
+         if (__GF (insn, 5, 4) == 0)
+           /* AMxxx AMAyyS AMyyS AMAWzS AMWzS */
+           return MASK_OP (insn, (0x1f << 20) | 0x1ff);
+         else if (__GF (insn, 5, 4) == 1)
+           /* ALR ASR ALA ASA AUPI */
+           return MASK_OP (insn, (0x1f << 20) | (0xf << 5));
+         else if (__GF (insn, 20, 3) == 0 && __GF (insn, 6, 3) == 1)
+           /* ALR2 */
+           return MASK_OP (insn, (0x1f << 20) | (0x7 << 6));
+         else if (__GF (insn, 20 ,3) == 2 && __GF (insn, 6, 3) == 1)
+           /* AWEXT ASATS48 */
+           return MASK_OP (insn, (0x1f << 20) | (0xf << 5));
+         else if (__GF (insn, 20 ,3) == 3 && __GF (insn, 6, 3) == 1)
+           /* AMTAR AMTAR2 AMFAR AMFAR2 */
+           return MASK_OP (insn, (0x1f << 20) | (0x1f << 5));
+         else if (__GF (insn, 7, 2) == 3)
+           /* AMxxxSA */
+           return MASK_OP (insn, (0x1f << 20) | (0x3 << 7));
+         else if (__GF (insn, 6, 3) == 2)
+           /* AMxxxL.S  */
+           return MASK_OP (insn, (0x1f << 20) | (0xf << 5));
+         else
+           /* AmxxxL.l AmxxxL2.S AMxxxL2.L  */
+           return MASK_OP (insn, (0x1f << 20) | (0x7 << 6));
+       case 0x1:
+         if (__GF (insn, 20, 3) == 0)
+           /* AADDL ASUBL */
+           return MASK_OP (insn, (0x1f << 20) | (0x1 << 5));
+         else if (__GF (insn, 20, 3) == 1)
+           /* AMTARI Ix AMTARI Mx */
+           return MASK_OP (insn, (0x1f << 20));
+         else if (__GF (insn, 6, 3) == 2)
+           /* AMAWzSl.S AMWzSl.S */
+           return MASK_OP (insn, (0x1f << 20) | (0xf << 5));
+         else if (__GF (insn, 7, 2) == 3)
+           /* AMAWzSSA AMWzSSA */
+           return MASK_OP (insn, (0x1f << 20) | (0x3 << 7));
+         else
+           /* AMAWzSL.L AMAWzSL2.S AMAWzSL2.L
+              AMWzSL.L AMWzSL.L AMWzSL2.S */
+           return MASK_OP (insn, (0x1f << 20) | (0x7 << 6));
+       case 0x2:
+         if (__GF (insn, 6, 3) == 2)
+           /* AMAyySl.S AMWyySl.S */
+           return MASK_OP (insn, (0x1f << 20) | (0xf << 5));
+         else if (__GF (insn, 7, 2) == 3)
+           /* AMAWyySSA AMWyySSA */
+           return MASK_OP (insn, (0x1f << 20) | (0x3 << 7));
+         else
+           /* AMAWyySL.L AMAWyySL2.S AMAWyySL2.L
+              AMWyySL.L AMWyySL.L AMWyySL2.S */
+           return MASK_OP (insn, (0x1f << 20) | (0x7 << 6));
+       }
+      return MASK_OP (insn, 0x1f << 20);
     default:
-      func (stream, UNKNOWN_INSN_MSG);
-      return;
+      return 1u << 31;
     }
 }
 
+/* Define cctl subtype.  */
+static char *cctl_subtype [] =
+{
+  /* 0x0 */
+  "st0", "st0", "st0", "st2", "st2", "st3", "st3", "st4",
+  "st1", "st1", "st1", "st0", "st0", NULL, NULL, "st5",
+  /* 0x10 */
+  "st0", NULL, NULL, "st2", "st2", "st3", "st3", NULL,
+  "st1", NULL, NULL, "st0", "st0", NULL, NULL, NULL
+};
+
+/* Check the subset of opcode.  */
+
 static void
-print_insn32_jreg (bfd_vma pc ATTRIBUTE_UNUSED, disassemble_info *info, uint32_t insn)
+nds32_special_opcode (uint32_t insn, struct nds32_opcode **opc)
 {
-  int op = insn & 0xff;
-  const int rt = RT5 (insn);
-  const int rb = RB5 (insn);
-  const char *dtit_on[] = { "", ".iton", ".dton", ".ton" };
-  const char *dtit_off[] = { "", ".itoff", ".dtoff", ".toff" };
-  const char *mnemonic_jreg[] = { "jr", "jral", "jrnez", "jralnez" };
-  const char *mnemonic_ret[] = { "jr", "ret", NULL, "ifret" };
-  const int dtit = __GF (insn, 8, 2);
-  fprintf_ftype func = info->fprintf_func;
-  void *stream = info->stream;
+  char *string = NULL;
+  uint32_t op;
 
-  switch (op)
-    {
-    case 0:            /* jr */
-      func (stream, "%s%s\t%s", mnemonic_ret[op >> 5],
-           dtit_on[dtit], gpr_map[rb]);
-      return;
+  if (!(*opc))
+    return;
 
-    case 0x20:         /* ret */
-      func (stream, "%s%s\t%s", mnemonic_ret[op >> 5],
-           dtit_off[dtit], gpr_map[rb]);
-      return;
-    case 0x60:         /* ifret */
+  /* Check if special case.  */
+  switch ((*opc)->value)
+    {
+    case OP6 (LWC):
+    case OP6 (SWC):
+    case OP6 (LDC):
+    case OP6 (SDC):
+    case FPU_RA_IMMBI (LWC):
+    case FPU_RA_IMMBI (SWC):
+    case FPU_RA_IMMBI (LDC):
+    case FPU_RA_IMMBI (SDC):
+      /* Check if cp0 => FPU.  */
+      if (__GF (insn, 13, 2) == 0)
+      {
+       while (!((*opc)->attr & ATTR (FPU)) && (*opc)->next)
+         *opc = (*opc)->next;
+      }
       break;
-    case 1:            /* jral */
-    case 2:            /* jrnez */
-    case 3:            /* jralnez */
-      func (stream, "%s%s\t%s, %s", mnemonic_jreg[op],
-           dtit_on[dtit], gpr_map[rt], gpr_map[rb]);
-      return;
-    default:           /* unknown */
-      func (stream, UNKNOWN_INSN_MSG);
+    case ALU1 (ADD):
+    case ALU1 (SUB):
+    case ALU1 (AND):
+    case ALU1 (XOR):
+    case ALU1 (OR):
+      /* Check if (add/add_slli) (sub/sub_slli) (and/and_slli).  */
+      if (N32_SH5(insn) != 0)
+        string = "sh";
+      break;
+    case ALU1 (SRLI):
+      /* Check if nop.  */
+      if (__GF (insn, 10, 15) == 0)
+        string = "nop";
+      break;
+    case MISC (CCTL):
+      string = cctl_subtype [__GF (insn, 5, 5)];
+      break;
+    case JREG (JR):
+    case JREG (JRAL):
+    case JREG (JR) | JREG_RET:
+      if (__GF (insn, 8, 2) != 0)
+       string = "tit";
+      break;
+    case N32_OP6_COP:
+      break;
+    case 0x9200:
+      /* nop16 */
+      if (__GF (insn, 0, 9) == 0)
+       string = "nop16";
       break;
     }
-}
-
-static void
-print_insn32_misc (bfd_vma pc ATTRIBUTE_UNUSED, disassemble_info *info,
-                  uint32_t insn)
-{
-  int op = insn & 0x1f;
-  int rt = RT5 (insn);
-  unsigned int id;
-  fprintf_ftype func = info->fprintf_func;
-  void *stream = info->stream;
 
-  static const char *keyword_standby[] =
+  if (string)
     {
-      "no_wake_grant", "wake_grant", "wait_done",
-    };
-  static const char *keyword_tlbop[] =
-    {
-      "TRD", "TWR", "RWR", "RWLK", "UNLK", "PB", "INV", "FLUA"
-    };
+      while (strstr ((*opc)->opcode, string) == NULL
+            && strstr ((*opc)->instruction, string) == NULL && (*opc)->next)
+       *opc = (*opc)->next;
+      return;
+    }
 
-  switch (op)
+  /* Classify instruction is COP or FPU.  */
+  op = N32_OP6 (insn);
+  if (op == N32_OP6_COP && __GF (insn, 4, 2) != 0)
     {
-    case 0x0:                  /* standby */
-      id = __GF (insn, 5, 20);
-      if (id < ARRAY_SIZE (keyword_standby))
-       func (stream, "standby\t%s", keyword_standby[id]);
-      else
-       func (stream, "standby\t%d", id);
-      return;
-    case 0x1:                  /* cctl */
-      func (stream, "cctl\t!FIXME");
-      return;
-    case 0x8:                  /* dsb */
-    case 0x9:                  /* isb */
-    case 0xd:                  /* isync */
-    case 0xc:                  /* msync */
-    case 0x4:                  /* iret */
-      func (stream, "%s", mnemonic_misc[op]);
-      return;
-    case 0x5:                  /* trap */
-    case 0xa:                  /* break */
-    case 0xb:                  /* syscall */
-      id = __GF (insn, 5, 15);
-      func (stream, "%s\t%d", mnemonic_misc[op], id);
-      return;
-    case 0x2:                  /* mfsr */
-    case 0x3:                  /* mtsr */
-      /* FIXME: setend, setgie.  */
-      func (stream, "%s\t%s, $%s", mnemonic_misc[op], gpr_map[rt],
-           sr_map[__GF(insn, 17, 3)][__GF(insn, 13, 4)][__GF(insn, 10, 3)]);
-      return;
-    case 0x6:                  /* teqz */
-    case 0x7:                  /* tnez */
-      id = __GF (insn, 5, 15);
-      func (stream, "%s\t%s, %d", mnemonic_misc[op], gpr_map[rt], id);
-      return;
-    case 0xe:                  /* tlbop */
-      id = __GF (insn, 5, 5);
-      if (id < ARRAY_SIZE (keyword_tlbop))
-       func (stream, "tlbop\t%s", keyword_tlbop[id]);
-      else
-       func (stream, "tlbop\t%d", id);
-      return;
+      while (((*opc)->attr & ATTR (FPU)) != 0 && (*opc)->next)
+       *opc = (*opc)->next;
     }
 }
 
-static void
-print_insn32_fpu (bfd_vma pc ATTRIBUTE_UNUSED, disassemble_info *info,
-                 uint32_t insn)
+int
+print_insn_nds32 (bfd_vma pc, disassemble_info *info)
 {
-  int op = insn & 0xf;
-  int mask_sub_op = (insn & 0x3c0) >> 6;
-  int mask_bi = (insn & 0x80) >> 7;
-  int mask_cfg = (insn & 0x7c00) >> 10;
-  int mask_f2op = (insn & 0x7c00) >> 10;
-  int dp = 0;
-  int dp_insn = 0;
-  char wd = 's';
-  const int rt = RT5 (insn);
-  const int ra = RA5 (insn);
-  const int rb = RB5 (insn);
-  const int sv = __GF (insn, 8, 2);
-  fprintf_ftype func = info->fprintf_func;
-  void *stream = info->stream;
+  int status;
+  bfd_byte buf[4];
+  bfd_byte buf_data[16];
+  uint64_t given;
+  uint64_t given1;
+  uint32_t insn;
+  int n;
+  int last_symbol_index = -1;
+  bfd_vma addr;
+  int is_data = FALSE;
+  bfd_boolean found = FALSE;
+  struct nds32_private_data *private_data;
+  unsigned int size;
+  enum map_type mapping_type = MAP_CODE;
+
+  if (info->private_data == NULL)
+    {
+      /* Note: remain lifecycle throughout whole execution.  */
+      static struct nds32_private_data private;
+      private.has_mapping_symbols = -1;        /* unknown yet.  */
+      private.last_symbol_index = -1;
+      private.last_addr = 0;
+      info->private_data = &private;
+    }
+  private_data = info->private_data;
 
-  switch (op)
+  if (info->symtab_size != 0)
     {
-    case 0x0:                  /* fs1 */
-    case 0x8:                  /* fd1 */
-      dp = (op & 0x8) ? 1 : 0;
-      if (dp)
-       {
-         wd = 'd';
-         dp_insn = 14;
-       }
+      int start;
+      if (pc == 0)
+       start = 0;
       else
        {
-         wd = 's';
-         dp_insn = 0;
+         start = info->symtab_pos;
+         if (start < private_data->last_symbol_index)
+           start = private_data->last_symbol_index;
        }
-      switch (mask_sub_op)
+
+      if (0 > start)
+       start = 0;
+
+      if (private_data->has_mapping_symbols != 0
+         && ((strncmp (".text", info->section->name, 5) == 0)))
        {
-       case 0x0:
-       case 0x1:
-       case 0x2:
-       case 0x3:
-       case 0x4:
-       case 0x5:
-       case 0x8:
-       case 0x9:
-       case 0xc:
-       case 0xd:
-         func (stream, "%s\t$f%c%d, $f%c%d, $f%c%d",
-               mnemonic_alu[mask_sub_op + dp_insn],
-               wd, rt, wd, ra, wd, rb);
-         return;
-       case 0x6:
-       case 0x7:
-         func (stream, "%s\t$f%c%d, $f%c%d, $fs%d",
-               mnemonic_alu[mask_sub_op + dp_insn],
-               wd, rt, wd, ra, rb);
-         return;
-       case 0xf:
-         if (dp)
+         for (n = start; n < info->symtab_size; n++)
            {
-             wd = 'd';
-             dp_insn = 0x1d;
+             addr = bfd_asymbol_value (info->symtab[n]);
+             if (addr > pc)
+               break;
+             if (get_mapping_symbol_type (info, n, &mapping_type))
+               {
+                 last_symbol_index = n;
+                 found = TRUE;
+               }
            }
-         else
+
+         if (found)
+           private_data->has_mapping_symbols = 1;
+         else if (!found && private_data->has_mapping_symbols == -1)
+           {
+             /* Make sure there are no any mapping symbol.  */
+             for (n = 0; n < info->symtab_size; n++)
+               {
+                 if (is_mapping_symbol (info, n, &mapping_type))
+                   {
+                     private_data->has_mapping_symbols = -1;
+                     break;
+                   }
+               }
+             if (private_data->has_mapping_symbols == -1)
+               private_data->has_mapping_symbols = 0;
+           }
+
+         private_data->last_symbol_index = last_symbol_index;
+         private_data->last_mapping_type = mapping_type;
+         is_data = (private_data->last_mapping_type == MAP_DATA0
+                    || private_data->last_mapping_type == MAP_DATA1
+                    || private_data->last_mapping_type == MAP_DATA2
+                    || private_data->last_mapping_type == MAP_DATA3
+                    || private_data->last_mapping_type == MAP_DATA4);
+       }
+    }
+
+  /* Wonder data or instruction.  */
+  if (is_data)
+    {
+      unsigned int i1;
+
+      /* Fix corner case: there is no next mapping symbol,
+        let mapping type decides size */
+      size = 16;
+      if (last_symbol_index + 1 >= info->symtab_size)
+       {
+         if (mapping_type == MAP_DATA0)
+           size = 1;
+         if (mapping_type == MAP_DATA1)
+           size = 2;
+         if (mapping_type == MAP_DATA2)
+           size = 4;
+         if (mapping_type == MAP_DATA3)
+           size = 8;
+         if (mapping_type == MAP_DATA4)
+           size = 16;
+       }
+      for (n = last_symbol_index + 1; n < info->symtab_size; n++)
+       {
+         addr = bfd_asymbol_value (info->symtab[n]);
+
+         enum map_type fake_mapping_type;
+         if (get_mapping_symbol_type (info, n, &fake_mapping_type)
+             && (addr > pc
+                 && ((info->section == NULL)
+                     || (info->section == info->symtab[n]->section)))
+             && (addr - pc < size))
            {
-             wd = 's';
-             dp_insn = 0;
+             size = addr - pc;
+             break;
            }
+       }
+
+      if (size == 3)
+       size = (pc & 1) ? 1 : 2;
 
-         switch (mask_f2op)
+      /* Read bytes from BFD.  */
+      info->read_memory_func (pc, buf_data, size, info);
+      given = 0;
+      given1 = 0;
+      /* Start assembling data.  */
+      /* Little endian of data.  */
+      if (info->endian == BFD_ENDIAN_LITTLE)
+       {
+         for (i1 = size - 1;; i1--)
            {
-           case 0x0:
-             if (dp)
-               func (stream, "%s\t$fs%d, $fd%d",
-                     mnemonic_fpu_2op[mask_f2op + dp_insn], rt, ra);
+             if (i1 >= 8)
+               given1 = buf_data[i1] | (given1 << 8);
              else
-               func (stream, "%s\t$fd%d, $fs%d",
-                     mnemonic_fpu_2op[mask_f2op + dp_insn], rt, ra);
-             return;
-           case 0x1:
-           case 0x5:
-             func (stream, "%s\t$f%c%d, $f%c%d",
-                   mnemonic_fpu_2op[mask_f2op + dp_insn], wd, rt, wd, ra);
-             return;
-           case 0x8:
-           case 0xc:
-             func (stream, "%s\t$f%c%d, $fs%d",
-                   mnemonic_fpu_2op[mask_f2op + dp_insn], wd, rt, ra);
-             return;
-           case 0x10:
-           case 0x14:
-           case 0x18:
-           case 0x1c:
-             func (stream, "%s\t$fs%d, $f%c%d",
-                   mnemonic_fpu_2op[mask_f2op + dp_insn], rt, wd, ra);
-             return;
+               given = buf_data[i1] | (given << 8);
+
+             if (i1 == 0)
+               break;
            }
        }
-    case 0x1:                  /* mfcp */
-      switch (mask_sub_op)
+      else
        {
-       case 0x0:
-         func (stream, "fmfsr\t%s, $fs%d", gpr_map[rt], ra);
-         return;
-       case 0x1:
-         func (stream, "fmfdr\t%s, $fd%d", gpr_map[rt], ra);
-         return;
-       case 0xc:
-         if (mask_cfg)
-           func (stream, "fmfcsr\t%s", gpr_map[rt]);
+         /* Big endian of data.  */
+         for (i1 = 0; i1 < size; i1++)
+           {
+             if (i1 <= 7)
+               given = buf_data[i1] | (given << 8);
+             else
+               given1 = buf_data[i1] | (given1 << 8);
+           }
+       }
+
+      info->bytes_per_line = 4;
+
+      if (size == 16)
+       info->fprintf_func (info->stream, ".qword\t0x%016" PRIx64 "%016" PRIx64,
+                           given, given1);
+      else if (size == 8)
+       info->fprintf_func (info->stream, ".dword\t0x%016" PRIx64, given);
+      else if (size == 4)
+       info->fprintf_func (info->stream, ".word\t0x%08" PRIx64, given);
+      else if (size == 2)
+       {
+         /* short */
+         if (mapping_type == MAP_DATA0)
+           info->fprintf_func (info->stream, ".byte\t0x%02" PRIx64,
+                               given & 0xFF);
          else
-           func (stream, "fmfcfg\t%s", gpr_map[rt]);
-         return;
+           info->fprintf_func (info->stream, ".short\t0x%04" PRIx64, given);
        }
-    case 0x2:                  /* fls */
-      if (mask_bi)
-       func (stream, "fls.bi\t$fs%d, [%s], (%s << %d)",
-             rt, gpr_map[ra], gpr_map[rb], sv);
       else
-       func (stream, "fls\t$fs%d, [%s + (%s << %d)]",
-             rt, gpr_map[ra], gpr_map[rb], sv);
-      return;
-    case 0x3:                  /* fld */
-      if (mask_bi)
-       func (stream, "fld.bi\t$fd%d, [%s], (%s << %d)",
-             rt, gpr_map[ra], gpr_map[rb], sv);
-      else
-       func (stream, "fld\t$fd%d, [%s + (%s << %d)]",
-             rt, gpr_map[ra], gpr_map[rb], sv);
-      return;
-    case 0x4:                  /* fs2 */
-      func (stream, "%s\t$fs%d, $fs%d, $fs%d",
-           mnemonic_fs2_cmp[mask_sub_op], rt, ra, rb);
-      return;
-    case 0x9:                  /* mtcp */
-      switch (mask_sub_op)
        {
-       case 0x0:
-         func (stream, "fmtsr\t%s, $fs%d", gpr_map[rt], ra);
-         return;
-       case 0x1:
-         func (stream, "fmtdr\t%s, $fd%d", gpr_map[rt], ra);
-         return;
-       case 0xc:
-           func (stream, "fmtcsr\t%s", gpr_map[rt]);
-         return;
+         /* byte */
+         info->fprintf_func (info->stream, ".byte\t0x%02" PRIx64, given);
        }
-    case 0xa:                  /* fss */
-      if (mask_bi)
-       func (stream, "fss.bi\t$fs%d, [%s], (%s << %d)",
-             rt, gpr_map[ra], gpr_map[rb], sv);
-      else
-       func (stream, "fss\t$fs%d, [%s + (%s << %d)]",
-             rt, gpr_map[ra], gpr_map[rb], sv);
-      return;
-    case 0xb:                  /* fsd */
-      if (mask_bi)
-       func (stream, "fsd.bi\t$fd%d, [%s], (%s << %d)",
-             rt, gpr_map[ra], gpr_map[rb], sv);
-      else
-       func (stream, "fsd\t$fd%d, [%s + (%s << %d)]",
-             rt, gpr_map[ra], gpr_map[rb], sv);
-      return;
-    case 0xc:                  /* fd2 */
-      func (stream, "%s\t$fs%d, $fd%d, $fd%d",
-           mnemonic_fd2_cmp[mask_sub_op], rt, ra, rb);
-      return;
+
+      return size;
     }
+
+  size = 4;
+  status = info->read_memory_func (pc, buf, 4, info);
+  if (status)
+    {
+      /* For the last 16-bit instruction.  */
+      size = 2;
+      status = info->read_memory_func (pc, buf, 2, info);
+      if (status)
+       {
+         (*info->memory_error_func) (status, pc, info);
+         return -1;
+       }
+      buf[2] = 0;
+      buf[3] = 0;
+    }
+
+  insn = bfd_getb32 (buf);
+  /* 16-bit instruction.  */
+  if (insn & 0x80000000)
+    {
+      print_insn16 (pc, info, (insn >> 16), NDS32_PARSE_INSN16);
+      return 2;
+    }
+
+  /* 32-bit instructions.  */
+  if (size == 4)
+    print_insn32 (pc, info, insn, NDS32_PARSE_INSN32);
+  else
+    info->fprintf_func (info->stream,
+                       _("insufficient data to decode instruction"));
+  return 4;
 }
 
-static void
-print_insn32 (bfd_vma pc, disassemble_info *info, uint32_t insn)
+/* Ignore disassembling unnecessary name.  */
+
+static bfd_boolean
+nds32_symbol_is_valid (asymbol *sym,
+                      struct disassemble_info *info ATTRIBUTE_UNUSED)
 {
-  int op = OP6 (insn);
-  const int rt = RT5 (insn);
-  const int ra = RA5 (insn);
-  const int rb = RB5 (insn);
-  const int imm15s = IMMS (insn, 15);
-  const int imm15u = IMMU (insn, 15);
-  uint32_t shift;
-  fprintf_ftype func = info->fprintf_func;
-  void *stream = info->stream;
+  const char *name;
 
-  switch (op)
-    {
-    case 0x0:                  /* lbi */
-    case 0x1:                  /* lhi */
-    case 0x2:                  /* lwi */
-    case 0x3:                  /* ldi */
-    case 0x8:                  /* sbi */
-    case 0x9:                  /* shi */
-    case 0xa:                  /* swi */
-    case 0xb:                  /* sdi */
-    case 0x10:                 /* lbsi */
-    case 0x11:                 /* lhsi */
-    case 0x12:                 /* lwsi */
-      shift = op & 0x3;
-      func (stream, "%s\t%s, [%s + #%d]",
-           mnemonic_op6[op], gpr_map[rt], gpr_map[ra], imm15s << shift);
-      return;
-    case 0x4:                  /* lbi.bi */
-    case 0x5:                  /* lhi.bi */
-    case 0x6:                  /* lwi.bi */
-    case 0x7:                  /* ldi.bi */
-    case 0xc:                  /* sbi.bi */
-    case 0xd:                  /* shi.bi */
-    case 0xe:                  /* swi.bi */
-    case 0xf:                  /* sdi.bi */
-    case 0x14:                 /* lbsi.bi */
-    case 0x15:                 /* lhsi.bi */
-    case 0x16:                 /* lwsi.bi */
-      shift = op & 0x3;
-      func (stream, "%s\t%s, [%s], #%d",
-           mnemonic_op6[op], gpr_map[rt], gpr_map[ra], imm15s << shift);
-      return;
-    case 0x13:                 /* dprefi */
-      {
-       const char *subtype = "???";
-       char wd = 'w';
+  if (sym == NULL)
+    return FALSE;
 
-       shift = 2;
+  name = bfd_asymbol_name (sym);
 
-       /* d-bit */
-       if (rt & 0x10)
-         {
-           wd = 'd';
-           shift = 3;
-         }
+  /* Mapping symbol is invalid.  */
+  if (name[0] == '$')
+    return FALSE;
+  return TRUE;
+}
 
-       if ((rt & 0xf) < ARRAY_SIZE (keyword_dpref))
-         subtype = keyword_dpref[rt & 0xf];
+static void
+nds32_add_opcode_hash_table (unsigned indx)
+{
+  opcode_t *opc;
 
-       func (stream, "%s.%c\t%s, [%s + #%d]",
-             mnemonic_op6[op], wd, subtype, gpr_map[ra], imm15s << shift);
-      }
-      return;
-    case 0x17:                 /* LBGP */
-      func (stream, "%s\t%s, [+ %d]",
-           ((insn & __BIT (19)) ? "lbsi.gp" : "lbi.gp"),
-           gpr_map[rt], IMMS (insn, 19));
-      return;
-    case 0x18:                 /* LWC */
-    case 0x19:                 /* SWC */
-    case 0x1a:                 /* LDC */
-    case 0x1b:                 /* SDC */
-      if (__GF (insn, 13, 2) == 0)
-       {
-         char ls = (op & 1) ? 's' : 'l';
-         char wd = (op & 2) ? 'd' : 's';
+  opc = nds32_opcode_table[indx];
+  if (opc == NULL)
+    return;
 
-         if (insn & __BIT (12))
-           {
-             func (stream, "f%c%ci.bi\t$f%c%d, [%s], %d", ls, wd,
-                   wd, rt, gpr_map[ra], IMMS (insn, 12) << 2);
-           }
-         else
-           {
-             func (stream, "f%c%ci\t$f%c%d, [%s + %d]", ls, wd,
-                   wd, rt, gpr_map[ra], IMMS (insn, 12) << 2);
-           }
-       }
-      else
-       {
-         char ls = (op & 1) ? 's' : 'l';
-         char wd = (op & 2) ? 'd' : 'w';
-         int cp = __GF (insn, 13, 2);
+  while (opc->opcode != NULL)
+    {
+      opcode_t **slot;
 
-         if (insn & __BIT (12))
-           {
-             func (stream, "cp%c%ci\tcp%d, $cpr%d, [%s], %d", ls, wd,
-                   cp, rt, gpr_map[ra], IMMS (insn, 12) << 2);
-           }
-         else
-           {
-             func (stream, "cp%c%ci\tcp%d, $cpr%d, [%s + %d]", ls, wd,
-                   cp, rt, gpr_map[ra], IMMS (insn, 12) << 2);
-           }
-       }
-      return;
-    case 0x1c:                 /* MEM */
-      print_insn32_mem (pc, info, insn);
-      return;
-    case 0x1d:                 /* LSMW */
-      {
-       int enb4 = __GF (insn, 6, 4);
-       char ls = (insn & __BIT (5)) ? 's' : 'l';
-       char ab = (insn & __BIT (4)) ? 'a' : 'b';
-       char *di = (insn & __BIT (3)) ? "d" : "i";
-       char *m = (insn & __BIT (2)) ? "m" : "";
-       static const char *s[] = {"", "a", "zb", "?"};
-
-       /* lsmwzb only always increase.  */
-       if ((insn & 0x3) == 2)
-         di = "";
-
-       func (stream, "%cmw%s.%c%s%s\t%s, [%s], %s, 0x%x",
-             ls, s[insn & 0x3], ab, di, m, gpr_map[rt],
-             gpr_map[ra], gpr_map[rb], enb4);
-      }
-      return;
-    case 0x1e:                 /* HWGP */
-      op = __GF (insn, 17, 3);
-      switch (op)
+      slot = (opcode_t **) htab_find_slot
+       (opcode_htab, &opc->value, INSERT);
+      if (*slot == NULL)
        {
-       case 0: case 1:         /* lhi.gp */
-       case 2: case 3:         /* lhsi.gp */
-       case 4: case 5:         /* shi.gp */
-         func (stream, "%s\t%s, [+ %d]",
-               mnemonic_hwgp[op], gpr_map[rt], IMMS (insn, 18) << 1);
-         return;
-       case 6:                 /* lwi.gp */
-       case 7:                 /* swi.gp */
-         func (stream, "%s\t%s, [+ %d]",
-               mnemonic_hwgp[op], gpr_map[rt], IMMS (insn, 17) << 2);
-         return;
+         /* This is the new one.  */
+         *slot = opc;
        }
-      return;
-    case 0x1f:                 /* SBGP */
-      if (insn & __BIT (19))
-       func (stream, "addi.gp\t%s, %d",
-             gpr_map[rt], IMMS (insn, 19));
       else
-       func (stream, "sbi.gp\t%s, [+ %d]",
-             gpr_map[rt], IMMS (insn, 19));
-      return;
-    case 0x20:                 /* ALU_1 */
-      print_insn32_alu1 (pc, info, insn);
-      return;
-    case 0x21:                 /* ALU_2 */
-      print_insn32_alu2 (pc, info, insn);
-      return;
-    case 0x22:                 /* movi */
-      func (stream, "movi\t%s, %d", gpr_map[rt], IMMS (insn, 20));
-      return;
-    case 0x23:                 /* sethi */
-      func (stream, "sethi\t%s, 0x%x", gpr_map[rt], IMMU (insn, 20));
-      return;
-    case 0x24:                 /* ji, jal */
-      /* FIXME: Handle relocation.  */
-      if (info->flags & INSN_HAS_RELOC)
-       pc = 0;
-      func (stream, "%s\t", ((insn & __BIT (24)) ? "jal" : "j"));
-      info->print_address_func ((IMMS (insn, 24) << 1) + pc, info);
-      return;
-    case 0x25:                 /* jreg */
-      print_insn32_jreg (pc, info, insn);
-      return;
-    case 0x26:                 /* br1 */
-      func (stream, "%s\t%s, %s, ", ((insn & __BIT (14)) ? "bne" : "beq"),
-           gpr_map[rt], gpr_map[ra]);
-      info->print_address_func ((IMMS (insn, 14) << 1) + pc, info);
-      return;
-    case 0x27:                 /* br2 */
-      func (stream, "%s\t%s, ", mnemonic_br2[__GF (insn, 16, 4)],
-           gpr_map[rt]);
-      info->print_address_func ((IMMS (insn, 16) << 1) + pc, info);
-      return;
-    case 0x28:                 /* addi */
-    case 0x2e:                 /* slti */
-    case 0x2f:                 /* sltsi */
-    case 0x29:                 /* subri */
-      func (stream, "%s\t%s, %s, %d",
-           mnemonic_op6[op], gpr_map[rt], gpr_map[ra], imm15s);
-      return;
-    case 0x2a:                 /* andi */
-    case 0x2b:                 /* xori */
-    case 0x2c:                 /* ori */
-    case 0x33:                 /* bitci */
-      func (stream, "%s\t%s, %s, %d",
-           mnemonic_op6[op], gpr_map[rt], gpr_map[ra], imm15u);
-      return;
-    case 0x2d:                 /* br3, beqc, bnec */
-      func (stream, "%s\t%s, %d, ", ((insn & __BIT (19)) ? "bnec" : "beqc"),
-           gpr_map[rt], __SEXT (__GF (insn, 8, 11), 11));
-      info->print_address_func ((IMMS (insn, 8) << 1) + pc, info);
-      return;
-    case 0x32:                 /* misc */
-      print_insn32_misc (pc, info, insn);
-      return;
-    case 0x35:                 /* FPU */
-      print_insn32_fpu (pc, info, insn);
-      return;
+       {
+         opcode_t *tmp;
+
+         /* Already exists.  Append to the list.  */
+         tmp = *slot;
+         while (tmp->next)
+           tmp = tmp->next;
+         tmp->next = opc;
+         opc->next = NULL;
+       }
+      opc++;
     }
 }
 
-int
-print_insn_nds32 (bfd_vma pc, disassemble_info *info)
+void
+disassemble_init_nds32 (struct disassemble_info *info)
 {
-  int status;
-  bfd_byte buf[4];
-  uint32_t insn;
+  static unsigned init_done = 0;
+  unsigned k;
 
-  status = info->read_memory_func (pc, (bfd_byte *) buf, 2, info);
-  if (status)
-    return -1;
+  /* Set up symbol checking function.  */
+  info->symbol_is_valid = nds32_symbol_is_valid;
 
-  /* 16-bit instruction.  */
-  if (buf[0] & 0x80)
+  /* Only need to initialize once:
+     High level will call this function for every object file.
+     For example, when disassemble all members of a library.  */
+  if (init_done)
+    return;
+
+  /* Setup main core.  */
+  nds32_keyword_table[NDS32_MAIN_CORE] = &keywords[0];
+  nds32_opcode_table[NDS32_MAIN_CORE] = &nds32_opcodes[0];
+  nds32_field_table[NDS32_MAIN_CORE] = &operand_fields[0];
+
+  /* Build opcode table.  */
+  opcode_htab = htab_create_alloc (1024, htab_hash_hash, htab_hash_eq,
+                                  NULL, xcalloc, free);
+
+  for (k = 0; k < NDS32_CORE_COUNT; k++)
     {
-      insn = bfd_getb16 (buf);
-      print_insn16 (pc, info, insn);
-      return 2;
+      /* Add op-codes.  */
+      nds32_add_opcode_hash_table (k);
     }
 
-  /* 32-bit instructions.  */
-  status = info->read_memory_func (pc + 2, (bfd_byte *) buf + 2, 2, info);
-  if (status)
-    return -1;
+  init_done = 1;
+}
 
-  insn = bfd_getb32 (buf);
-  print_insn32 (pc, info, insn);
+static int
+is_mapping_symbol (struct disassemble_info *info, int n,
+                  enum map_type *map_type)
+{
+  const char *name = NULL;
 
-  return 4;
+  /* Get symbol name.  */
+  name = bfd_asymbol_name (info->symtab[n]);
+
+  if (name[1] == 'c')
+    {
+      *map_type = MAP_CODE;
+      return TRUE;
+    }
+  else if (name[1] == 'd' && name[2] == '0')
+    {
+      *map_type = MAP_DATA0;
+      return TRUE;
+    }
+  else if (name[1] == 'd' && name[2] == '1')
+    {
+      *map_type = MAP_DATA1;
+      return TRUE;
+    }
+  else if (name[1] == 'd' && name[2] == '2')
+    {
+      *map_type = MAP_DATA2;
+      return TRUE;
+    }
+  else if (name[1] == 'd' && name[2] == '3')
+    {
+      *map_type = MAP_DATA3;
+      return TRUE;
+    }
+  else if (name[1] == 'd' && name[2] == '4')
+    {
+      *map_type = MAP_DATA4;
+      return TRUE;
+    }
+
+  return FALSE;
+}
+
+static int
+get_mapping_symbol_type (struct disassemble_info *info, int n,
+                        enum map_type *map_type)
+{
+  /* If the symbol is in a different section, ignore it.  */
+  if (info->section != NULL
+      && info->section != info->symtab[n]->section)
+    return FALSE;
+
+  return is_mapping_symbol (info, n, map_type);
 }
This page took 0.045487 seconds and 4 git commands to generate.