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.
 /* 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.
    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
    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 "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 "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
 
 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;
   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;
     }
 
       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;
     }
       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
       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
 
 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;
       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;
       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;
       break;
-    default:
-      func (stream, UNKNOWN_INSN_MSG);
-      return;
     }
 }
 
 static void
     }
 }
 
 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:
     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
 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;
       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;
     }
       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
        {
       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
              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
          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
       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
       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.056781 seconds and 4 git commands to generate.