[PATCH 3/6] Opcodes changes for nanoMIPS support.

"Tsing" <[email protected]>
Newsgroups gmane.comp.gnu.binutils
Message-ID <[email protected]>
From: tsing <[email protected]>

include/
	* dis-asm.h: Add prototypes for print_insn_nanomips
		     and print_nanomips_disassembler_options.
	* opcode/nanomips.h: New file.
opcodes/
	* Makefile.am: Add nanoMIPS target.
        * Makefile.in: Regenerate.
	* configure: Add entry for bfd_nanomips_arch.
	* configure.ac: Regenerate.
	* disassemble.c (disassembler): Add support for naonmips.
			(disassembler_usage): Likewise.
	* nanomips-dis.c: New file.
	* nanomips-formats.h: New file.
	* nanomips-opc.c: New file.
---
 include/dis-asm.h          |    1 +
 include/opcode/nanomips.h  | 1238 ++++++++++++++++++++++++++++++++
 opcodes/Makefile.am        |    2 +
 opcodes/Makefile.in        |    4 +
 opcodes/configure          |    1 +
 opcodes/configure.ac       |    1 +
 opcodes/disassemble.c      |   14 +
 opcodes/disassemble.h      |    1 +
 opcodes/nanomips-dis.c     | 1394 ++++++++++++++++++++++++++++++++++++
 opcodes/nanomips-formats.h |  265 +++++++
 opcodes/nanomips-opc.c     |  807 +++++++++++++++++++++
 11 files changed, 3728 insertions(+)
 create mode 100644 include/opcode/nanomips.h
 create mode 100644 opcodes/nanomips-dis.c
 create mode 100644 opcodes/nanomips-formats.h
 create mode 100644 opcodes/nanomips-opc.c

diff --git a/include/dis-asm.h b/include/dis-asm.h
index c3d5d8c5438..4dcddefe420 100644
--- a/include/dis-asm.h
+++ b/include/dis-asm.h
@@ -386,6 +386,7 @@ extern disassembler_ftype cris_get_disassembler (bfd *);
 extern void print_aarch64_disassembler_options (FILE *);
 extern void print_i386_disassembler_options (FILE *);
 extern void print_mips_disassembler_options (FILE *);
+extern void print_nanomips_disassembler_options (FILE *);
 extern void print_nfp_disassembler_options (FILE *);
 extern void print_ppc_disassembler_options (FILE *);
 extern void print_riscv_disassembler_options (FILE *);
diff --git a/include/opcode/nanomips.h b/include/opcode/nanomips.h
new file mode 100644
index 00000000000..fb9d7b0ee9b
--- /dev/null
+++ b/include/opcode/nanomips.h
@@ -0,0 +1,1238 @@
+/* nanomips.h.  nanoMIPS opcode list for GDB, the GNU debugger.
+   Copyright (C) 2018-2026 Free Software Foundation, CIP United Inc.
+   Contributed by MIPS Tech LLC.
+   Written by Faraz Shahbazker <[email protected]>
+
+   This file is part of GDB, GAS, and the GNU binutils.
+
+   GDB, GAS, and the GNU binutils are free software; you can redistribute
+   them and/or modify them under the terms of the GNU General Public
+   License as published by the Free Software Foundation; either version 3,
+   or (at your option) any later version.
+
+   GDB, GAS, and the GNU binutils are distributed in the hope that they
+   will be useful, but WITHOUT ANY WARRANTY; without even the implied
+   warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
+   the GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this file; see the file COPYING3.  If not, write to the Free
+   Software Foundation, 51 Franklin Street - Fifth Floor, Boston,
+   MA 02110-1301, USA.  */
+
+#ifndef _NANOMIPS_H_
+#define _NANOMIPS_H_
+
+#include "bfd.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Enumerates the various types of nanoMIPS operand.  */
+enum nanomips_operand_type {
+  /* Described by nanomips_int_operand.  */
+  OP_INT,
+
+  /* Described by nanomips_mapped_int_operand.  */
+  OP_MAPPED_INT,
+
+  /* Described by nanomips_msb_operand.  */
+  OP_MSB,
+
+  /* Described by nanomips_reg_operand.  */
+  OP_REG,
+
+  /* Like OP_REG, but can be omitted if the register is the same as the
+     previous operand.  */
+  OP_OPTIONAL_REG,
+
+  /* Described by nanomips_reg_pair_operand.  */
+  OP_REG_PAIR,
+
+  /* Described by nanomips_pcrel_operand.  */
+  OP_PCREL,
+
+  /* The register list and frame size for a MIPS16 SAVE or RESTORE
+     instruction.  */
+  OP_SAVE_RESTORE_LIST,
+
+  /* A register operand that must match the destination register.  */
+  OP_REPEAT_DEST_REG,
+
+  /* A register operand that must match the previous register.  */
+  OP_REPEAT_PREV_REG,
+
+  /* Described by nanomips_prev_operand.  */
+  OP_CHECK_PREV,
+
+  /* A register operand that must not be zero.  */
+  OP_NON_ZERO_REG,
+
+ /* The floating-point register list for a nanoMIPS SAVE or RESTORE
+     instruction. */
+  OP_SAVE_RESTORE_FP_LIST,
+
+  /* Fractured upper immediate PC-offset for nanoMIPS */
+  OP_HI20_PCREL,
+
+  /* Fractured upper immediate 20-bit signed integer for nanoMIPS */
+  OP_HI20_INT,
+
+  /* Fractured upper immediate 20-bit scaled integer for nanoMIPS */
+  OP_HI20_SCALE,
+
+  /* A non-zero PC-relative offset.  */
+  OP_NON_ZERO_PCREL_S1,
+
+  /* To check a mapped register against a previous operand.  */
+  OP_MAPPED_CHECK_PREV,
+
+  /* Unsigned word operand.  */
+  OP_UINT_WORD,
+
+  /* Signed word operand.  */
+  OP_INT_WORD,
+
+  /* Immediate PC-relative word operand.  */
+  OP_PC_WORD,
+
+  /* Immediate GP-relative word operand.  */
+  OP_GPREL_WORD,
+
+  /* Don't care bits.  */
+  OP_DONT_CARE,
+
+  /* Immediate unsigned word operand, to be negated.  */
+  OP_NEG_INT,
+
+  /* Immediate (non-relocatable) integer operand.  */
+  OP_IMM_INT,
+
+  /* Immediate (non-relocatable) word operand.  */
+  OP_IMM_WORD,
+
+  /* Base register for limited types of offsets.  */
+  OP_BASE_CHECK_OFFSET,
+
+  /* Copy over bits from another part of instruction.  */
+  OP_COPY_BITS,
+
+  /* Select bits for a COP0 register.  */
+  OP_CP0SEL,
+};
+
+/* Enumerates the types of nanoMIPS register.  */
+enum nanomips_reg_operand_type {
+  /* General registers $0-$31.  Software names like $at can also be used.  */
+  OP_REG_GP,
+
+  /* Floating-point registers $f0-$f31.  */
+  OP_REG_FP,
+
+  /* DSP accumulator registers $ac0-$ac3.  */
+  OP_REG_ACC,
+
+  /* Coprocessor registers in numeric format, $0-$31.  */
+  OP_REG_COPRO,
+
+  /* Hardware registers $0-$31.  Mnemonic names like hwr_cpunum can
+     also be used in some contexts.  */
+  OP_REG_HW,
+
+  /* Co-processor 0 named registers.  */
+  OP_REG_CP0,
+
+  /* Co-processor 0 named registers with select.  */
+  OP_REG_CP0SEL
+};
+
+/* Base class for all operands.  */
+struct nanomips_operand
+{
+  /* The type of the operand.  */
+  enum nanomips_operand_type type;
+
+  /* The operand occupies SIZE bits of the instruction, starting at LSB.  */
+  unsigned short size;
+  unsigned short lsb;
+
+  /* These are used to split a value across two different
+     parts of the instruction encoding.  */
+  unsigned int size_top;
+  unsigned int lsb_top;
+};
+
+/* Describes an integer operand with a regular encoding pattern.  */
+struct nanomips_int_operand
+{
+  struct nanomips_operand root;
+
+  /* The low ROOT.SIZE bits of MAX_VAL encodes (MAX_VAL + BIAS) << SHIFT.
+     The cyclically previous field value encodes 1 << SHIFT less than that,
+     and so on.  E.g.
+
+     - for { { T, 4, L }, 14, 0, 0 }, field values 0...14 encode themselves,
+       but 15 encodes -1.
+
+     - { { T, 8, L }, 127, 0, 2 } is a normal signed 8-bit operand that is
+       shifted left two places.
+
+     - { { T, 3, L }, 8, 0, 0 } is a normal unsigned 3-bit operand except
+       that 0 encodes 8.
+
+     - { { ... }, 0, 1, 3 } means that N encodes (N + 1) << 3.  */
+  unsigned int max_val;
+  int bias;
+  unsigned int shift;
+
+  /* True if the operand should be printed as hex rather than decimal.  */
+  bool print_hex;
+};
+
+/* Uses a lookup table to describe a small integer operand.  */
+struct nanomips_mapped_int_operand
+{
+  struct nanomips_operand root;
+
+  /* Maps each encoding value to the integer that it represents.  */
+  const int *int_map;
+
+  /* True if the operand should be printed as hex rather than decimal.  */
+  bool print_hex;
+};
+
+/* An operand that encodes the most significant bit position of a bitfield.
+   Given a bitfield that spans bits [MSB, LSB], some operands of this type
+   encode MSB directly while others encode MSB - LSB.  Each operand of this
+   type is preceded by an integer operand that specifies LSB.
+
+   The assembly form varies between instructions.  For some instructions,
+   such as EXT, the operand is written as the bitfield size.  For others,
+   such as EXTS, it is written in raw MSB - LSB form.  */
+struct nanomips_msb_operand
+{
+  struct nanomips_operand root;
+
+  /* The assembly-level operand encoded by a field value of 0.  */
+  int bias;
+
+  /* True if the operand encodes MSB directly, false if it encodes
+     MSB - LSB.  */
+  bool add_lsb;
+
+  /* The maximum value of MSB + 1.  */
+  unsigned int opsize;
+};
+
+/* Describes a single register operand.  */
+struct nanomips_reg_operand
+{
+  struct nanomips_operand root;
+
+  /* The type of register.  */
+  enum nanomips_reg_operand_type reg_type;
+
+  /* If nonnull, REG_MAP[N] gives the register associated with encoding N,
+     otherwise the encoding is the same as the register number.  */
+  const unsigned char *reg_map;
+};
+
+/* Describes an operand that which must match a condition based on the
+   previous operand.  */
+struct nanomips_check_prev_operand
+{
+  struct nanomips_operand root;
+
+  bool greater_than_ok;
+  bool less_than_ok;
+  bool equal_ok;
+  bool zero_ok;
+};
+
+/* Describes an operand that encodes a pair of registers.  */
+struct nanomips_reg_pair_operand
+{
+  struct nanomips_operand root;
+
+  /* The type of register.  */
+  enum nanomips_reg_operand_type reg_type;
+
+  /* Encoding N represents REG1_MAP[N], REG2_MAP[N].  */
+  unsigned char *reg1_map;
+  unsigned char *reg2_map;
+};
+
+/* Describes an operand that is calculated relative to a base PC.
+   The base PC is usually the address of the following instruction,
+   but the rules for MIPS16 instructions like ADDIUPC are more complicated.  */
+struct nanomips_pcrel_operand
+{
+  /* Encodes the offset.  */
+  struct nanomips_int_operand root;
+
+  /* The low ALIGN_LOG2 bits of the base PC are cleared to give PC',
+     which is then added to the offset encoded by ROOT.  */
+  unsigned int align_log2 : 8;
+
+  /* If INCLUDE_ISA_BIT, the ISA bit of the original base PC is then
+     reinstated.  This is true for jumps and branches and false for
+     PC-relative data instructions.  */
+  unsigned int include_isa_bit : 1;
+
+  /* If FLIP_ISA_BIT, the ISA bit of the result is inverted.
+     This is true for JALX and false otherwise.  */
+  unsigned int flip_isa_bit : 1;
+};
+
+/* This structure holds information for a particular instruction.  */
+
+struct nanomips_opcode
+{
+  /* The name of the instruction.  */
+  const char *name;
+  /* An optional suffix.  */
+  const char *suffix;
+  /* A string describing the arguments for this instruction.  */
+  const char *args;
+  /* The basic opcode for the instruction.  When assembling, this
+     opcode is modified by the arguments to produce the actual opcode
+     that is used.  If pinfo is INSN_MACRO, then this is 0.  */
+  unsigned long match;
+  /* If pinfo is not INSN_MACRO, then this is a bit mask for the
+     relevant portions of the opcode when disassembling.  If the
+     actual opcode anded with the match field equals the opcode field,
+     then we have found the correct instruction.  If pinfo is
+     INSN_MACRO, then this field is the macro identifier.  */
+  unsigned long mask;
+  /* For a macro, this is INSN_MACRO.  Otherwise, it is a collection
+     of bits describing the instruction, notably any relevant hazard
+     information.  */
+  unsigned long pinfo;
+  /* A collection of additional bits describing the instruction. */
+  unsigned long pinfo2;
+  /* A collection of bits describing the instruction sets of which this
+     instruction or macro is a member. */
+  unsigned long membership;
+  /* A collection of bits describing the ASE of which this instruction
+     or macro is a member.  */
+  unsigned long ase;
+};
+
+/* Return true if the assembly syntax allows OPERAND to be omitted.  */
+
+static inline bool
+nanomips_optional_operand_p (const struct nanomips_operand *operand)
+{
+  return (operand->type == OP_OPTIONAL_REG
+	  || operand->type == OP_REPEAT_PREV_REG
+	  || (operand->type != OP_INT
+	      && operand->size == 0
+	      && operand->lsb == 0));
+}
+
+/* Return a version of INSN in which the field specified by OPERAND
+   has value UVAL.  */
+
+static inline unsigned int
+nanomips_insert_operand (const struct nanomips_operand *operand,
+			 unsigned int insn, unsigned int uval)
+{
+  unsigned int mask;
+  unsigned int size_bottom = operand->size - operand->size_top;
+
+  mask = (1 << size_bottom) - 1;
+  insn &= ~(mask << operand->lsb);
+  insn |= (uval & mask) << operand->lsb;
+
+  mask = (1 << operand->size_top) - 1;
+  insn &= ~(mask << operand->lsb_top);
+  insn |= ((uval & (mask << size_bottom)) >> size_bottom) << operand->lsb_top;
+  return insn;
+}
+
+/* Extract OPERAND from instruction INSN.  */
+
+static inline unsigned int
+nanomips_extract_operand (const struct nanomips_operand *operand,
+			  unsigned int insn)
+{
+  unsigned int uval;
+  unsigned int size_bottom = operand->size - operand->size_top;
+
+  uval = (insn >> operand->lsb_top) & ((1 << operand->size_top) - 1);
+  uval <<= size_bottom;
+  uval |= (insn >> operand->lsb) & ((1 << size_bottom) - 1);
+  return uval;
+}
+
+/* UVAL is the value encoded by OPERAND.  Return it in signed form.  */
+
+static inline int
+nanomips_signed_operand (const struct nanomips_operand *operand,
+			 unsigned int uval)
+{
+  unsigned int sign_bit, mask;
+
+  mask = (1 << operand->size) - 1;
+  sign_bit = 1 << (operand->size - 1);
+  return ((uval + sign_bit) & mask) - sign_bit;
+}
+
+/* Return the integer that OPERAND encodes as UVAL.  */
+
+static inline int
+nanomips_decode_int_operand (const struct nanomips_int_operand *operand,
+			     unsigned int uval)
+{
+  uval |= (operand->max_val - uval) & -(1 << operand->root.size);
+  uval += operand->bias;
+  uval <<= operand->shift;
+  return uval;
+}
+
+/* Return the maximum value that can be encoded by OPERAND.  */
+
+static inline int
+nanomips_int_operand_max (const struct nanomips_int_operand *operand)
+{
+  return (operand->max_val + operand->bias) << operand->shift;
+}
+
+/* Return the minimum value that can be encoded by OPERAND.  */
+
+static inline int
+nanomips_int_operand_min (const struct nanomips_int_operand *operand)
+{
+  unsigned int mask;
+
+  mask = (1 << operand->root.size) - 1;
+  return nanomips_int_operand_max (operand) - (mask << operand->shift);
+}
+
+/* Return the register that OPERAND encodes as UVAL.  */
+
+static inline int
+nanomips_decode_reg_operand (const struct nanomips_reg_operand *operand,
+			     unsigned int uval)
+{
+  if (operand->reg_map)
+    uval = operand->reg_map[uval];
+  return uval;
+}
+
+/* PC-relative operand OPERAND has value UVAL and is relative to BASE_PC.
+   Return the address that it encodes.  */
+
+static inline bfd_vma
+nanomips_decode_pcrel_operand (const struct nanomips_pcrel_operand *operand,
+			       bfd_vma base_pc, unsigned int uval)
+{
+  bfd_vma addr;
+
+  addr = base_pc & -(1 << operand->align_log2);
+  addr += nanomips_decode_int_operand (&operand->root, uval);
+  if (operand->include_isa_bit)
+    addr |= base_pc & 1;
+  if (operand->flip_isa_bit)
+    addr ^= 1;
+  return addr;
+}
+
+/* Describes an operand that encapsulates a mapped register with
+   a check against the previous operand.  */
+struct nanomips_mapped_check_prev_operand
+{
+  struct nanomips_operand root;
+
+  enum nanomips_reg_operand_type reg_type;
+  const unsigned char *reg_map;
+
+  bool greater_than_ok;
+  bool less_than_ok;
+  bool equal_ok;
+  bool zero_ok;
+};
+
+/* Describes an operand that encapsulates a base register with
+   a check against the type of offset.  */
+struct nanomips_base_check_offset_operand
+{
+  struct nanomips_operand root;
+
+  enum nanomips_reg_operand_type reg_type;
+
+  bool const_ok;
+  bool expr_ok;
+};
+
+/* Return true if MO is an instruction that requires 32-bit encoding.  */
+
+static inline bool
+nanomips_opcode_32bit_p (const struct nanomips_opcode *mo)
+{
+  return mo->mask >> 16 != 0;
+}
+
+static inline int
+nanomips_operand_mask (const struct nanomips_operand *operand)
+{
+  unsigned int mask;
+
+  mask = ((1 << operand->size_top) - 1) << operand->lsb_top;
+  mask |= ((1 << (operand->size - operand->size_top)) - 1) << operand->lsb;
+  return mask;
+}
+
+/* Return the UVAL encoding of REGNO as OPERAND.  */
+
+static inline unsigned int
+nanomips_encode_reg_operand (const struct nanomips_operand *operand,
+			     int regno)
+{
+  unsigned int uval;
+  const unsigned int num_vals = 1 << operand->size;
+  const struct nanomips_reg_operand *reg_op
+    = (const struct nanomips_reg_operand *) operand;
+
+  for (uval = 0; uval < num_vals; uval++)
+    if (reg_op->reg_map[uval] == regno)
+      break;
+  return uval;
+}
+
+/* Re-organize HI20 bits of OPERAND encoded as UVAL.  */
+
+#define SIGNEX_VALUE(OP) {OP_INT, OP->size - 1, 0, 0, 0}
+
+static inline int
+nanomips_decode_hi20_operand (const struct nanomips_operand *operand,
+			      unsigned int uval)
+{
+  const struct nanomips_operand op_ext = SIGNEX_VALUE (operand);
+  const struct nanomips_operand op_shuffle = {OP_INT, 19, 10, 10, 0};
+  unsigned int low19 = nanomips_extract_operand (&op_shuffle, uval);
+  return nanomips_insert_operand (&op_ext, uval, low19);
+}
+
+/* Decode HI20 signed integer.  */
+
+#define SIGNED_VALUE(OP) {OP_INT, OP->size, 0, 0, 0}
+
+static inline int
+nanomips_decode_hi20_int_operand (const struct nanomips_operand *operand,
+				  unsigned int uval)
+{
+  const struct nanomips_operand op_enc = SIGNED_VALUE (operand);
+  uval = nanomips_decode_hi20_operand (operand, uval);
+  return (nanomips_signed_operand (&op_enc, uval));
+}
+
+/* Decode HI20 PCREL  */
+
+#define PCREL_VALUE(OP) { { { OP_PCREL, OP->size, 0, 0, 0}, \
+	(1 << (OP->size - 1)) - 1, 0, 0, false}, 12, 0, 0}
+
+static inline bfd_vma
+nanomips_decode_hi20_pcrel_operand (const struct nanomips_operand *operand,
+				    bfd_vma base_pc, unsigned int uval)
+{
+  const struct nanomips_pcrel_operand pcrel_op = PCREL_VALUE (operand);
+  uval = nanomips_decode_hi20_operand (operand, uval);
+  return nanomips_decode_pcrel_operand (&pcrel_op, base_pc, uval << 12);
+}
+
+/* Return true if MO is an instruction that requires 48-bit encoding.  */
+
+static inline bool
+opcode_48bit_p (const struct nanomips_opcode *mo)
+{
+  return ((mo->mask >> 16 == 0)
+	  && ((mo->match >> 10) == 0x18));
+}
+
+/* These are the bits which may be set in the pinfo field of an
+   instructions, if it is not equal to INSN_MACRO.  */
+
+/* Writes to operand number N.  */
+#define INSN_WRITE_SHIFT            0
+#define INSN_WRITE_1                0x00000001
+#define INSN_WRITE_2                0x00000002
+#define INSN_WRITE_ALL              0x00000003
+/* Reads from operand number N.  */
+#define INSN_READ_SHIFT             2
+#define INSN_READ_1                 0x00000004
+#define INSN_READ_2                 0x00000008
+#define INSN_READ_3                 0x00000010
+#define INSN_READ_ALL               0x0000001c
+/* Modifies general purpose register 31.  */
+#define INSN_WRITE_GPR_31           0x00000020
+/* Reads coprocessor register other than floating point register.  */
+#define INSN_COP                    0x00000040
+/* Instruction loads value from memory.  */
+#define INSN_LOAD_MEMORY	    0x00000080
+/* Reads the accumulator register.  */
+#define INSN_READ_ACC		    0x00000100
+/* Modifies the HI register.  */
+#define INSN_WRITE_ACC		    0x00000200
+/* Instruction stores value into memory.  */
+#define INSN_STORE_MEMORY	0x00000400
+/* Instruction uses single precision floating point.  */
+#define INSN_FP_S		0x00000800
+/* Instruction uses double precision floating point.  */
+#define INSN_FP_D		0x00001000
+/* A user-defined instruction.  */
+#define INSN_UDI                    0x00002000
+/* Instruction is actually a macro.  It should be ignored by the
+   disassembler, and requires special treatment by the assembler.  */
+#define INSN_MACRO                  0xffffffff
+
+/* These are the bits which may be set in the pinfo2 field of an
+   instruction. */
+
+/* Instruction is a simple alias (I.E. "move" for daddu/addu/or) */
+#define	INSN2_ALIAS		    0x00000001
+/* Macro uses single-precision floating-point instructions.  This should
+   only be set for macros.  For instructions, FP_S in pinfo carries the
+   same information.  */
+#define INSN2_M_FP_S		    0x00000002
+/* Macro uses double-precision floating-point instructions.  This should
+   only be set for macros.  For instructions, FP_D in pinfo carries the
+   same information.  */
+#define INSN2_M_FP_D		    0x00000004
+/* Is an unconditional branch insn. */
+#define INSN2_UNCOND_BRANCH	    0x00000008
+/* Is a conditional branch insn. */
+#define INSN2_COND_BRANCH	    0x00000010
+/* This indicates delayed branch converted to compact branch.  */
+#define INSN2_CONVERTED_TO_COMPACT  0x00000020
+/* Marks the LI macro expansion as special, temporary.  */
+#define INSN2_MACRO		    0x00000040
+
+/* Masks used to mark instructions to indicate which MIPS ISA level
+   they were introduced in.  INSN_ISA_MASK masks an enumeration that
+   specifies the base ISA level(s).  The remainder of a 32-bit
+   word constructed using these macros is a bitmask of the remaining
+   INSN_* values below.  */
+
+#define INSN_ISA_MASK		  0x00000003ul
+
+/* We cannot start at zero due to ISA_UNKNOWN below.  */
+#define INSN_ISAN32R6   1
+#define INSN_ISAN64R6	2
+
+#define ISA_UNKNOWN	0               /* Gas internal use.  */
+
+#define ISA_NANOMIPS32R6	INSN_ISAN32R6
+#define ISA_NANOMIPS64R6	INSN_ISAN64R6
+
+/* CPU defines, use instead of hardcoding processor number. Keep this
+   in sync with bfd/archures.c in order for machine selection to work.  */
+#define CPU_UNKNOWN	0               /* Gas internal use.  */
+
+#define CPU_NANOMIPS32R6 32
+#define CPU_NANOMIPS64R6 64
+
+#define ISAF(X) (1 << (INSN_ISA##X - 1))
+
+/* The same information in table form: bit INSN_ISA<X> - 1 of index
+   INSN_UPTO<Y> - 1 is set if ISA Y includes ISA X.  */
+static const unsigned int nanomips_isa_table[] = {
+  ISAF(N32R6),
+  ISAF(N32R6) | ISAF(N64R6)
+};
+#undef ISAF
+
+/* MT ASE */
+#define ASE_MT			0x00000010
+/* Virtualization ASE */
+#define ASE_VIRT		0x00000020
+#define ASE_VIRT64		0x00000040
+/* Excluded for low power instruction subset for nanoMIPS.  */
+#define ASE_xNMS		0x00002000
+
+static inline bool
+nanomips_cpu_is_member (int cpu, unsigned int mask)
+{
+  switch (cpu)
+    {
+    case CPU_NANOMIPS32R6:
+      return (mask & INSN_ISA_MASK) == INSN_ISAN32R6;
+
+    case CPU_NANOMIPS64R6:
+      return ((mask & INSN_ISA_MASK) == INSN_ISAN32R6)
+	     || ((mask & INSN_ISA_MASK) == INSN_ISAN64R6);
+
+    default:
+      return false;
+    }
+}
+
+/* Test for membership in an ISA including chip specific ISAs.  INSN
+   is pointer to an element of the opcode table; ISA is the specified
+   ISA/ASE bitmask to test against; and CPU is the CPU specific ISA to
+   test, or zero if no CPU specific ISA test is desired.  Return true
+   if instruction INSN is available to the given ISA and CPU. */
+static inline bool
+nanomips_opcode_is_member (const struct nanomips_opcode *insn,
+			   int isa, int ase, int cpu)
+{
+  /* Test for ISA level compatibility.  */
+  if ((isa & INSN_ISA_MASK) != 0
+      && (insn->membership & INSN_ISA_MASK) != 0
+      && ((nanomips_isa_table[(isa & INSN_ISA_MASK) - 1]
+	   >> ((insn->membership & INSN_ISA_MASK) - 1)) & 1) != 0)
+    return true;
+
+  /* Test for ASE compatibility.  */
+  if (insn->ase != 0 && (ase & insn->ase) == insn->ase)
+    return true;
+
+  /* Test for processor-specific extensions.  */
+  if (nanomips_cpu_is_member (cpu, insn->membership))
+    return true;
+
+  return false;
+}
+
+/* This is a list of macro expanded instructions.
+
+   _I appended means immediate
+   _A appended means target address of a jump
+   _AB appended means address with (possibly zero) base register
+   _AC appended means either symbolic address with no base register
+   or constant offset with base register.
+   _D appended means 64 bit floating point constant
+   _S appended means 32 bit floating point constant.  */
+
+enum
+{
+  M_ABS,
+  M_ACLR_AC,
+  M_ADD_I,
+  M_ADDU_I,
+  M_AND_I,
+  M_ASET_AC,
+  M_BEQ,
+  M_BEQ_I,
+  M_BGE,
+  M_BGE_I,
+  M_BGEU,
+  M_BGEU_I,
+  M_BGEZ,
+  M_BGT,
+  M_BGT_I,
+  M_BGTU,
+  M_BGTU_I,
+  M_BGTZ,
+  M_BLE,
+  M_BLE_I,
+  M_BLEU,
+  M_BLEU_I,
+  M_BLEZ,
+  M_BLT,
+  M_BLT_I,
+  M_BLTU,
+  M_BLTU_I,
+  M_BLTZ,
+  M_BNE,
+  M_BNE_I,
+  M_CACHE_AC,
+  M_CACHEE_AC,
+  M_DABS,
+  M_DADD_I,
+  M_DADDU_I,
+  M_DLA_AB,
+  M_DLI,
+  M_DMUL,
+  M_DMUL_I,
+  M_DSUB_I,
+  M_DSUBU_I,
+  M_J_A,
+  M_JAL_A,
+  M_JRADDIUSP,
+  M_LA_AB,
+  M_LB_AC,
+  M_LBE_AC,
+  M_LBU_AC,
+  M_LBUE_AC,
+  M_LD_AC,
+  M_LDC1_AC,
+  M_LDC2_AC,
+  M_LDM_AC,
+  M_LH_AC,
+  M_LHE_AC,
+  M_LHU_AC,
+  M_LHUE_AC,
+  M_LI,
+  M_LI_D,
+  M_LI_DD,
+  M_LI_S,
+  M_LI_SS,
+  M_LL_AC,
+  M_LLD_AC,
+  M_LLE_AC,
+  M_LW_AC,
+  M_LWC1_AC,
+  M_LWC2_AC,
+  M_LWE_AC,
+  M_LWM_AC,
+  M_LWU_AC,
+  M_MUL,
+  M_MUL_I,
+  M_NOR_I,
+  M_OR_I,
+  M_PREF_AC,
+  M_PREFE_AC,
+  M_REM_3I,
+  M_DROL,
+  M_ROL,
+  M_DROL_I,
+  M_ROL_I,
+  M_ROR_I,
+  M_SC_AC,
+  M_SCD_AC,
+  M_SCE_AC,
+  M_SD_AC,
+  M_SDC1_AC,
+  M_SDC2_AC,
+  M_SDM_AC,
+  M_SEQ,
+  M_SEQ_I,
+  M_SGE,
+  M_SGE_I,
+  M_SGEU,
+  M_SGEU_I,
+  M_SGT,
+  M_SGT_I,
+  M_SGTU,
+  M_SGTU_I,
+  M_SLE,
+  M_SLE_I,
+  M_SLEU,
+  M_SLEU_I,
+  M_SLT_I,
+  M_SLTU_I,
+  M_SNE,
+  M_SNE_I,
+  M_SB_AC,
+  M_SBE_AC,
+  M_SH_AC,
+  M_SHE_AC,
+  M_SW_AC,
+  M_SWE_AC,
+  M_SWC1_AC,
+  M_SWC2_AC,
+  M_SWM_AC,
+  M_SUB_I,
+  M_SUBU_I,
+  M_TEQ_I,
+  M_TNE_I,
+  M_ULD_AC,
+  M_ULH_AC,
+  M_ULW_AC,
+  M_USH_AC,
+  M_USW_AC,
+  M_USD_AC,
+  M_XOR_I,
+  M_BGEZAL,
+  M_BLTZAL,
+  M_EXT,
+  M_INS,
+  M_MOD_I,
+  M_MODU_I,
+  M_DMOD_I,
+  M_DMODU_I,
+  M_DIV_I,
+  M_DIVU_I,
+  M_DDIV_I,
+  M_DDIVU_I,
+  M_NANOMIPS_NUM_MACROS
+};
+
+/* These are the bit masks and shift counts used for the different fields
+   in the nanoMIPS instruction formats.  No masks are provided for the
+   fixed portions of an instruction, since they are not needed.  */
+
+#define NANOMIPSOP_MASK_RS		0x1f
+#define NANOMIPSOP_SH_RS		16
+#define NANOMIPSOP_MASK_RT		0x1f
+#define NANOMIPSOP_SH_RT		21
+#define NANOMIPSOP_SH_MC		4
+#define NANOMIPSOP_SH_MD		7
+#define NANOMIPSOP_SH_MP		5
+#define NANOMIPSOP_SH_MM		7
+
+#define NANOMIPSOP_SH_CP0SEL		5
+#define NANOMIPSOP_MASK_CP0SEL		0x1f
+
+/* Describes a COP0 named register with a fixed select.  */
+struct nanomips_cp0_name
+{
+  const char *name;
+  unsigned int num;
+  unsigned int sel;
+};
+
+/* The reference list of COP0 named register with fixed selects.  */
+static const struct nanomips_cp0_name nanomips_cp0_3264r6[] = {
+    {"$index",		 0, 0},
+    {"$mvpcontrol",	 0, 1},
+    {"$mvpconf0",	 0, 2},
+    {"$mvpconf1",	 0, 3},
+    {"$vpcontrol",	 0, 4},
+    {"$random", 	 1, 0},
+    {"$vpecontrol",	 1, 1},
+    {"$vpeconf0",	 1, 2},
+    {"$vpeconf1",	 1, 3},
+    {"$yqmask", 	 1, 4},
+    {"$vpeschedule",	 1, 5},
+    {"$vpeschefback",	 1, 6},
+    {"$vpeopt", 	 1, 7},
+    {"$entrylo0",	 2, 0},
+    {"$tcstatus",	 2, 1},
+    {"$tcbind", 	 2, 2},
+    {"$tcrestart",	 2, 3},
+    {"$tchalt", 	 2, 4},
+    {"$tccontext",	 2, 5},
+    {"$tcschedule",	 2, 6},
+    {"$tcschefback",	 2, 7},
+    {"$entrylo1",	 3, 0},
+    {"$tcopt",		 3, 7},
+    {"$context",	 4, 0},
+    {"$contextconfig",	 4, 1},
+    {"$userlocal",	 4, 2},
+    {"$xcontextconfig",  4, 3},
+    {"$pagemask",	 5, 0},
+    {"$pagegrain",	 5, 1},
+    {"$segctl0",	 5, 2},
+    {"$segctl1",	 5, 3},
+    {"$segctl2",	 5, 4},
+    {"$pwbase", 	 5, 5},
+    {"$pwfield",	 5, 6},
+    {"$pwsize", 	 5, 7},
+    {"$wired",		 6, 0},
+    {"$srsconf0",	 6, 1},
+    {"$srsconf1",	 6, 2},
+    {"$srsconf2",	 6, 3},
+    {"$srsconf3",	 6, 4},
+    {"$srsconf4",	 6, 5},
+    {"$pwctl",		 6, 6},
+    {"$hwrena", 	 7, 0},
+    {"$badvaddr",	 8, 0},
+    {"$badinst",	 8, 1},
+    {"$badinstrp",	 8, 2},
+    {"$count",		 9, 0},
+    {"$entryhi",	10, 0},
+    {"$guestctl1",	10, 4},
+    {"$guestctl2",	10, 5},
+    {"$guestctl3",	10, 6},
+    {"$compare",	11, 0},
+    {"$guestctl0ext",	11, 4},
+    {"$status", 	12, 0},
+    {"$intctl", 	12, 1},
+    {"$srsctl", 	12, 2},
+    {"$srsmap", 	12, 3},
+    {"$view_ipl",	12, 4},
+    {"$srsmap2",	12, 5},
+    {"$guestctl0",	12, 6},
+    {"$gtoffset",	12, 7},
+    {"$cause",		13, 0},
+    {"$view_ripl",	13, 4},
+    {"$nestedexc",	13, 5},
+    {"$epc",		14, 0},
+    {"$nestedepc",	14, 2},
+    {"$prid",		15, 0},
+    {"$ebase",		15, 1},
+    {"$cdmmbase",	15, 2},
+    {"$cmgcrbase",	15, 3},
+    {"$config", 	16, 0},
+    {"$config1",	16, 1},
+    {"$config2",	16, 2},
+    {"$config3",	16, 3},
+    {"$config4",	16, 4},
+    {"$config5",	16, 5},
+    {"$lladdr", 	17, 0},
+    {"$xcontext",	20, 0},
+    {"$debug",		23, 0},
+    {"$tracecontrol",	23, 1},
+    {"$tracecontrol2",	23, 2},
+    {"$usertracedata1", 23, 3},
+    {"$traceibpc",	23, 4},
+    {"$tracedbpc",	23, 5},
+    {"$debug2", 	23, 6},
+    {"$depc",		24, 0},
+    {"$tracecontrol3",	24, 2},
+    {"$usertracedata2", 24, 3},
+    {"$errctl", 	26, 0},
+    {"$cacheerr",	27, 0},
+    {"$errorepc",	30, 0},
+    {"$desave", 	31, 0},
+    {"$kscratch1",	31, 2},
+    {"$kscratch2",	31, 3},
+    {"$kscratch3",	31, 4},
+    {"$kscratch4",	31, 5},
+    {"$kscratch5",	31, 6},
+    {"$kscratch6",	31, 7},
+    {NULL, 0, 0}
+};
+
+/* Describes a CP0 named register which permits various select values.  */
+  struct nanomips_cp0_select
+{
+  const char *name;
+  unsigned int num;
+  unsigned int selmask;
+};
+
+/* Currently recognized CP0 select patterns.  */
+
+#define NANOMIPS_CP0SEL_MASK_EVEN	0x55555555
+#define NANOMIPS_CP0SEL_MASK_ODD	0xaaaaaaaa
+#define NANOMIPS_CP0SEL_MASK_ANY	0xffffffff
+
+/* The reference list of CP0 named register with variable selects.  */
+static const struct nanomips_cp0_select nanomips_cp0sel_3264r6[] = {
+    {"$watchlo",	18, NANOMIPS_CP0SEL_MASK_ANY},
+    {"$watchhi",	19, NANOMIPS_CP0SEL_MASK_ANY},
+    {"$perfctl",	25, NANOMIPS_CP0SEL_MASK_EVEN},
+    {"$perfcnt",	25, NANOMIPS_CP0SEL_MASK_ANY},
+    {"$taglo",		28, NANOMIPS_CP0SEL_MASK_EVEN},
+    {"$datalo", 	28, NANOMIPS_CP0SEL_MASK_ODD},
+    {"$taghi",		29, NANOMIPS_CP0SEL_MASK_EVEN},
+    {"$datahi", 	29, NANOMIPS_CP0SEL_MASK_ODD},
+    {NULL, 0, 0}
+};
+
+/* These are the characters which may appears in the args field of a nanoMIPS
+   instruction.  They appear in the order in which the fields appear when the
+   instruction is used.  Commas and parentheses in the args string are ignored
+   when assembling, and written into the output when disassembling.
+
+   Operands for 16-bit nanoMIPS instructions.
+
+   "ma" must be $28
+   "mb" 5-bit non-zero GP register at bit 5
+   "mc" 3-bit nanoMIPS registers 4-7, 16-19 bit 4
+        The same register used as both source and target.
+   "md" 3-bit nanoMIPS registers 4-7, 16-19 at bit 7
+   "me" 3-bit nanoMIPS registers 4-7, 16-19 at bit 1
+   "mf" 3-bit nanoMIPS register 4-7, 16-19 at bit 7.
+        Must be larger than the last seen register.
+   "mg" 3-bit nanoMIPS register 4-7, 16-19 at bit 4.
+	Must be smaller than the last seen register.
+   "mh" 3-bit nanoMIPS register 4-7, 16-19 at bit 7.
+        Must be at least as large as the last seen register.
+   "mi" 3-bit nanoMIPS register 4-7, 16-19 at bit 4.
+	May be at most as large as the last seen register.
+
+   "mj" 5-bit nanoMIPS registers at bit 0
+   "mk" must be the same as the destination register
+   "ml" 3-bit nanoMIPS registers 4-7, 16-19 at bit 4
+   "mm" 3-bit nanoMIPS registers 0, 4-7, 17-19 at bit 7
+   "mn"	5-bit encoding of a save/restore register list
+   "mp" 5-bit nanoMIPS registers at bit 5
+   "mq" 2-bit pair at bits [8,3] maps to ($a0,$a1), ($a1,$a2), ($a2,$a3)
+        or ($a3,$a4)
+   "mr" 2-bit pair at bits [8,3] maps to ($a1,$a0), ($a2,$a1), ($a3,$a2)
+        or ($a4,$a3)
+   "ms" must be $29
+   "mt" must be the same as the previous register
+   "mu"	4-bit encoding of nanoMIPS destination register at bit 5
+   "mv"	4-bit encoding of nanoMIPS destination register at bit 0
+   "mw"	4-bit encoding of nanoMIPS source register at bit 5
+   "mx"	4-bit encoding of nanoMIPS source register at bit 0
+   "my" must be $31
+   "mz" must be literal 0
+
+   "mA" 7-bit relocatable GP offset (0 .. 127) << 2
+   "mB" 3-bit immediate at bit 0 (0, 4, 8, 12, 16, 20, 24, 28)
+   "mC" 4-bit immediate at bit 0 (0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11,
+        65535, 14, 15)
+   "mD" 10-bit signed branch address, split & scaled at bit 0 [S9:1,S10]
+   "mE" 7-bit signed branch address, split & scaled at bit 0 [S6:1,S7]
+   "mF" 4-bit unsigned branch address, scaled at bit 0 [U4:U1]
+   "mG" 4-bit scaled immediate at bit 4, (0 .. 15) << 4
+   "mH" 2-bit scaled immediate at bit 1, (0 .. 3) << 1
+   "mI" 7-bit immediate at bit 0, (-1 .. 126)
+   "mJ" 4-bit scaled immediate at bit 0, (0 .. 15) << 2
+   "mK" 3-bit BREAK/SDBBP code at bit 0
+   "mL" 2-bit immediate at bit 0, (0 .. 3)
+   "mM" 3-bit immediate at bit 0, (1 .. 8)
+   "mN" 2-bit split scaled immediate at bits 8 & 3 (0 .. 3) << 2
+   "mO" 7-bit immediate GP offset at bit 0, (0 .. 127) << 2
+   "mP"	2-bit SYSCALL/HYPCALL code at bit 0
+   "mQ"	4-bit immediate signed offset, (s3,s2:s0)
+   "mR" 5-bit immediate at bit 0, (0 .. 31) << 2
+   "mS" 6-bit immediate at bit 0, (0 .. 63) << 2
+   "mZ" must be zero
+
+   Operands for 32-bit nanoMIPS instructions.
+
+   "+1"	18-bit unsigned GP-relative offset, (u17:u0)
+   "+2"	18-bit scaled GP-relative offset, (u18:u2) << 2
+   "+3"	21-bit scaled GP-relative offset, (u18:u1) << 1
+   "+4" 18-bit GP-relative offset, (0 .. 2^18-1) << 3
+   "+5"	4-bit encoding of nanoMIPS source register at bit 21
+   "+6" 5-bit mask encoding, corresponding to (1 << X) - 1
+   "+7" 1-bit register at bit 24, (0,1) => ($a0,$a1)
+   "+8" 23-bit un-spec'ed value at bit 3 for UDIs.
+   "+9" 7-bit immediate at bit 11, (0 .. 127)
+
+   "+A" 5-bit INS/EXT/DINS/DEXT/DINSM/DEXTM position, which becomes
+        LSB.
+   "+B" 5-bit INS/DINS size, which becomes MSB
+	Requires that "+A" or "+E" occur first to set position.
+	Enforces: 0 < (pos+size) <= 32.
+   "+C" 5-bit EXT/DEXT size, which becomes MSBD.
+	Requires that "+A" or "+E" occur first to set position.
+	Enforces: 0 < (pos+size) <= 32.
+   "+D"	4-bit encoding of a floating point save/restore register list
+   "+E" 5-bit DINSU/DEXTU position, which becomes LSB-32.
+   "+F" 5-bit DINSM/DINSU size, which becomes MSB-32.
+	Requires that "+A" or "+E" occur first to set position.
+	Enforces: 32 < (pos+size) <= 64.
+   "+G" 5-bit DEXTM size, which becomes MSBD-32.
+	Requires that "+A" or "+E" occur first to set position.
+	Enforces: 32 < (pos+size) <= 64.
+   "+H" 5-bit DEXTU size, which becomes MSBD.
+	Requires that "+A" or "+E" occur first to set position.
+	Enforces: 32 < (pos+size) <= 64.
+   "+I" 5-bit EXTW/EXTD/PREPEND position, which becomes LSB.
+   "+J" 19-bit BREAK/SDBBP function code at bit 0
+   "+K"	Tri-part upper 20-bits of immediate value.
+   "+L" 10-bit WAIT code at bit 16
+   "+M"	18-bit SYSCALL/HYPCALL code at bit 0
+   "+N" 9-bit immediate at bit 3, (0 .. 511) << 3
+
+   "+i"	5-bit SYNC code type at bit 16, (0..31)
+   "+j"	9-bit signed offset (s7:s0,s8), (-256 .. 255)
+   "+k" 5-bit nanoMIPS registers at bit 3
+   "+p"	9-bit scaled signed offset, (s7:s2) << 2 for LL/SC*
+   "+q" 9-bit scaled signed offset, (s7:s3) << 3 for LLD/SCD*
+   "+r"	21-bit PC-relative branch offset (s19:s1,s20) << 1
+   "+s"	21-bit immediate offset for PC-relative operation ((s19:s1,s20) + 2) << 1
+   "+t" 5-bit non-zero GP register at bit 21
+   "+u"	25-bit PC-relative branch offset (s24:s1,s25) << 1
+   "+v"	5-bit mapping of R6 ALIGN byte-wise shift to EXTW bit-wise shift.
+   "+w"	2-bit shift for scaled address calculation at bit 9, (0..3)
+   "+*"	4-bit ROTX shift at bit 7, (0 .. 15) << 1
+   "+|"	1-bit ROTX stripe at bit 6, (0 .. 1)
+
+   "."	21-bit scaled GP-relative offset, (u21:u2) << 2
+   "<"	5-bit immediate shift value for bit operations, (0..31)
+   "|"	3-bit Element count for load/store multiple, (1..8)
+   "~"	11-bit branch offset, (s9:s1,s10) << 1
+   "^"	5-bit trap code at bit 11, (0..31)
+   "b"	5-bit base register at bit 16 for label or symbolic offsets
+   "c"	5-bit base register at bit 16, either used with immediate offset
+	or skipped with symbolic offset.
+   "d"	5-bit destination register specifier at bit 11
+   "g"	12-bit unsigned immediate at bit 0, (0..4095)
+   "h"	12-bit negative immediate at bit 0, (-4095..0)
+   "i"	12-bit unsigned immediate at bit 0, (0..4095)
+   "j"	16-bit unsigned immediate at bit 0, (0..65535)
+   "k"	5-bit cache operation code at bit 21, (0..31)
+   "n"	11-bit encoding of save/restore register list
+   "o"	12-bit offset at bit 0, (0..4095)
+   "p"	14-bit PC-relative branch offset (s13:s1,s14) << 1
+   "r"	5-bit same register at bit 16, used as both source and target
+   "s"	5-bit source register specifier at bit 16
+   "t"	5-bit target register specifier at bit 21
+   "u" 	Tri-part upper 20 bits of address
+   "x" 	Tri-part upper 20 bits of address, scaled by 12 bits
+   "v"	5-bit same register used as both source and destination at bit 15
+   "w"	5-bit same register used as both target and destination at bit 21
+   "z"	must be zero register
+
+   Used in special matching contexts:
+   "-a" 5-bit don't care at bit 16
+   "-b" 8-bit split don't care, 5@16 and 4@9
+   "-i" Ignored register operand, internally used for macro expansions.
+   "-m" Place-holder to copy 5 bits from bit 11 to bit 21
+   "-n" Place-holder to copy 5 bits from bit 11 to bit 16
+
+   Exclusively for 48-bit nanoMIPS instructions:
+
+   "+O" Signed GP-relative 32-bit offset in instruction byte order
+   "+P" Immediate signed 32-bit value in instruction byte order
+   "+Q"	Unsigned 32-bit value or address in instruction byte order
+   "+R" Signed 32-bit value in instruction byte order
+   "+S" Signed PC-relative 32-bit offset in instruction byte order
+
+   Coprocessor instructions:
+   "E" 5-bit target register
+   "G" 5-bit source register
+   "H" 5-bit sel field for (D)MTC* and (D)MFC*
+   "J" 5-bit select code at bit 11 for named COP1 registers, (0..31)
+   "K"	10-bit register+select encoding at bit 11 for named h/w register
+   "O"	10-bit register+select encoding at bit 11 for named COP1 register
+   "P"	5-bit named COP1 register at bit 16
+   "Q"	5-bit select code at bit 11
+   "U"	5-bit named HW register at bit 16
+
+   MT instructions:
+   "!"	1-bit u-mode for move to/from thread registers at bit 10, (0,1)
+   "$"	1-bit high-mode for move to/from thread registers at bit 3, (0,1)
+   "*"	2-bit accumulator register at bit 18, (0..3)
+
+   Floating point instructions:
+   "D" 5-bit destination register
+   "R" 5-bit fr destination register
+   "S" 5-bit fs source 1 register
+   "T" 5-bit ft source 2 register
+   "V" 5-bit same register used as floating source and destination or target
+
+   Macro instructions:
+   "A" general 32 bit expression
+   "I" 32-bit immediate (value placed in imm_expr).
+   "F" 64-bit floating point constant in memory
+   "L" 64-bit floating point constant in memory
+   "f" 32-bit floating point constant in memory
+   "l" 32-bit floating point constant in memory
+
+   CP2 instructions:
+   "C" 23-bit coprocessor function code at bit 3
+
+   Other:
+   "()" parens surrounding optional value
+   ","  separates operands
+   "+"  start of extension sequence
+
+   Characters used so far, for quick reference when adding more:
+   "12345 78 0"
+   ".<\|~@^!$*"
+   "A CDEFGHIJKL  OP RSTUV    "
+   " bcde ghijk  nop rstuvwx z"
+
+   Extension character sequences used so far ("+" followed by the
+   following), for quick reference when adding more:
+   "123456789 
+   "*|;"
+   "ABCDEFGHIJKLMNOPQRS       "
+   "        ij     pqrstuvw   "
+
+   Extension character sequences used so far ("m" followed by the
+   following), for quick reference when adding more:
+   ""
+   ""
+   "ABCDEFGHIJKLMNOPQRS      Z"
+   "abcdefghijklmn pqrstuvwxyz"
+
+   Extension character sequences used so far ("-" followed by the
+   following), for quick reference when adding more:
+   ""
+   ""
+   "                          "
+   "ab      i   mn            "
+*/
+  
+extern const struct nanomips_operand *decode_nanomips_operand (const char *);
+extern const struct nanomips_opcode nanomips_opcodes[];
+extern const int bfd_nanomips_num_opcodes;
+  
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _NANOMIPS_H_ */
diff --git a/opcodes/Makefile.am b/opcodes/Makefile.am
index a0fcf4d5ec7..0aa9836ece0 100644
--- a/opcodes/Makefile.am
+++ b/opcodes/Makefile.am
@@ -212,6 +212,8 @@ TARGET32_LIBOPCODES_CFILES = \
 	mt-dis.c \
 	mt-ibld.c \
 	mt-opc.c \
+	nanomips-dis.c \
+	nanomips-opc.c \
 	nds32-asm.c \
 	nds32-dis.c \
 	ns32k-dis.c \
diff --git a/opcodes/Makefile.in b/opcodes/Makefile.in
index c5449bebf54..1f81ba70efc 100644
--- a/opcodes/Makefile.in
+++ b/opcodes/Makefile.in
@@ -618,6 +618,8 @@ TARGET32_LIBOPCODES_CFILES = \
 	mt-dis.c \
 	mt-ibld.c \
 	mt-opc.c \
+	nanomips-dis.c \
+	nanomips-opc.c \
 	nds32-asm.c \
 	nds32-dis.c \
 	ns32k-dis.c \
@@ -998,6 +1000,8 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mt-dis.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mt-ibld.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mt-opc.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nanomips-dis.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nanomips-opc.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nds32-asm.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nds32-dis.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nfp-dis.Plo@am__quote@
diff --git a/opcodes/configure b/opcodes/configure
index 3e0962b9408..c544b7a569d 100755
--- a/opcodes/configure
+++ b/opcodes/configure
@@ -14369,6 +14369,7 @@ if test x${all_targets} = xfalse ; then
 	bfd_mn10300_arch)	ta="$ta m10300-dis.lo m10300-opc.lo" ;;
 	bfd_mt_arch)		ta="$ta mt-asm.lo mt-desc.lo mt-dis.lo mt-ibld.lo mt-opc.lo" using_cgen=yes ;;
 	bfd_msp430_arch)	ta="$ta msp430-dis.lo msp430-decode.lo" ;;
+	bfd_nanomips_arch)	ta="$ta nanomips-dis.lo nanomips-opc.lo" ;;
 	bfd_nds32_arch)		ta="$ta nds32-asm.lo nds32-dis.lo" ;;
 	bfd_nfp_arch)		ta="$ta nfp-dis.lo" ;;
 	bfd_ns32k_arch)		ta="$ta ns32k-dis.lo" ;;
diff --git a/opcodes/configure.ac b/opcodes/configure.ac
index 2c2556598c9..a54c26ee880 100644
--- a/opcodes/configure.ac
+++ b/opcodes/configure.ac
@@ -308,6 +308,7 @@ if test x${all_targets} = xfalse ; then
 	bfd_mn10300_arch)	ta="$ta m10300-dis.lo m10300-opc.lo" ;;
 	bfd_mt_arch)		ta="$ta mt-asm.lo mt-desc.lo mt-dis.lo mt-ibld.lo mt-opc.lo" using_cgen=yes ;;
 	bfd_msp430_arch)	ta="$ta msp430-dis.lo msp430-decode.lo" ;;
+	bfd_nanomips_arch)	ta="$ta nanomips-dis.lo nanomips-opc.lo" ;;
 	bfd_nds32_arch)		ta="$ta nds32-asm.lo nds32-dis.lo" ;;
 	bfd_nfp_arch)		ta="$ta nfp-dis.lo" ;;
 	bfd_ns32k_arch)		ta="$ta ns32k-dis.lo" ;;
diff --git a/opcodes/disassemble.c b/opcodes/disassemble.c
index 77d44bb08db..8760b28d107 100644
--- a/opcodes/disassemble.c
+++ b/opcodes/disassemble.c
@@ -102,6 +102,7 @@
 #define ARCH_xtensa
 #define ARCH_z80
 #define ARCH_z8k
+#define ARCH_nanomips
 #endif
 
 #ifdef ARCH_m32c
@@ -294,6 +295,11 @@ disassembler (enum bfd_architecture a,
       disassemble = print_insn_msp430;
       break;
 #endif
+#ifdef ARCH_nanomips
+    case bfd_arch_nanomips:
+      disassemble = print_insn_nanomips;
+      break;
+#endif
 #ifdef ARCH_nds32
     case bfd_arch_nds32:
       disassemble = print_insn_nds32;
@@ -556,6 +562,9 @@ disassembler_usage (FILE *stream ATTRIBUTE_UNUSED)
 #ifdef ARCH_nfp
   print_nfp_disassembler_options (stream);
 #endif
+#ifdef ARCH_nanomips
+  print_nanomips_disassembler_options (stream);
+#endif
 #ifdef ARCH_powerpc
   print_ppc_disassembler_options (stream);
 #endif
@@ -683,6 +692,11 @@ disassemble_init_for_target (struct disassemble_info * info)
       info->created_styled_output = true;
       break;
 #endif
+#ifdef ARCH_nanomips
+    case bfd_arch_nanomips:
+      info->disassembler_needs_relocs = true;
+      break;
+#endif
 #ifdef ARCH_pru
     case bfd_arch_pru:
       info->disassembler_needs_relocs = true;
diff --git a/opcodes/disassemble.h b/opcodes/disassemble.h
index 2157790c947..901df877a0b 100644
--- a/opcodes/disassemble.h
+++ b/opcodes/disassemble.h
@@ -73,6 +73,7 @@ extern int print_insn_mn10300		(bfd_vma, disassemble_info *);
 extern int print_insn_moxie		(bfd_vma, disassemble_info *);
 extern int print_insn_msp430		(bfd_vma, disassemble_info *);
 extern int print_insn_mt                (bfd_vma, disassemble_info *);
+extern int print_insn_nanomips		(bfd_vma, disassemble_info *);
 extern int print_insn_nds32		(bfd_vma, disassemble_info *);
 extern int print_insn_nfp		(bfd_vma, disassemble_info *);
 extern int print_insn_ns32k		(bfd_vma, disassemble_info *);
diff --git a/opcodes/nanomips-dis.c b/opcodes/nanomips-dis.c
new file mode 100644
index 00000000000..195d2408d94
--- /dev/null
+++ b/opcodes/nanomips-dis.c
@@ -0,0 +1,1394 @@
+/* Print nanoMIPS instructions for GDB, the GNU debugger, or for objdump.
+   Copyright (C) 2018-2026 Free Software Foundation, CIP United Inc.
+   Contributed by MIPS Tech LLC.
+   Written by Faraz Shahbazker <[email protected]>
+
+   This file is part of the GNU opcodes library.
+
+   This library is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3, or (at your option)
+   any later version.
+
+   It is distributed in the hope that it will be useful, but WITHOUT
+   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
+   License for more details.
+
+   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.  */
+
+#include "sysdep.h"
+#include "dis-asm.h"
+#include "libiberty.h"
+#include "opcode/nanomips.h"
+#include "opintl.h"
+#include "disassemble.h"
+
+#if !defined(EMBEDDED_ENV)
+#include "elf-bfd.h"
+#include "elf/nanomips.h"
+#include "elfxx-nanomips.h"
+#endif
+
+/* FIXME: These should be shared with gdb somehow.  */
+
+static const char * const nanomips_gpr_names_numeric[32] = {
+  "$0",   "$1",   "$2",   "$3",   "$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",  "$31"
+};
+
+static const char * const nanomips_gpr_names_symbolic[32] = {
+  "zero", "at",   "t4",   "t5",   "a0",   "a1",   "a2",   "a3",
+  "a4",   "a5",   "a6",   "a7",   "t0",   "t1",   "t2",   "t3",
+  "s0",   "s1",   "s2",   "s3",   "s4",   "s5",   "s6",   "s7",
+  "t8",   "t9",   "k0",   "k1",   "gp",   "sp",   "fp",   "ra"
+};
+
+static const char * const nanomips_fpr_names_numeric[32] = {
+  "$f0",  "$f1",  "$f2",  "$f3",  "$f4",  "$f5",  "$f6",  "$f7",
+  "$f8",  "$f9",  "$f10", "$f11", "$f12", "$f13", "$f14", "$f15",
+  "$f16", "$f17", "$f18", "$f19", "$f20", "$f21", "$f22", "$f23",
+  "$f24", "$f25", "$f26", "$f27", "$f28", "$f29", "$f30", "$f31"
+};
+
+static const char * const nanomips_fpr_names_64[32] = {
+  "fv0",  "ft12", "fv1",  "ft13", "ft0",  "ft1",  "ft2",  "ft3",
+  "ft4",  "ft5",  "ft6",  "ft7",  "fa0",  "fa1",  "fa2",  "fa3",
+  "fa4",  "fa5",  "fa6",  "fa7",  "ft8",  "ft9",  "ft10", "ft11",
+  "fs0",  "fs1",  "fs2",  "fs3",  "fs4",  "fs5",  "fs6",  "fs7"
+};
+
+static const char * const nanomips_cp0_names_numeric[32] =
+{
+  "$0",   "$1",   "$2",   "$3",   "$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",  "$31"
+};
+
+static const char * const nanomips_hwr_names_numeric[32] = {
+  "$0",   "$1",   "$2",   "$3",   "$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",  "$31"
+};
+
+static const char * const nanomips_hwr_names_3264r6[32] = {
+  "hwr_cpunum",   "hwr_synci_step", "hwr_cc",     "hwr_ccres",
+  "hwr_perfcnt",  "hwr_xnp", 		"$6",           "$7",
+  "$8",   "$9",   "$10",  "$11",  "$12",  "$13",  "$14",  "$15",
+  "$16",  "$17",  "$18",  "$19",  "$20",  "$21",  "$22",  "$23",
+  "$24",  "$25",  "$26",  "$27",  "$28",  "hwr_userlocal",
+  "$30",  "$31"
+};
+
+/* The empty-list of CP0 registers serves as an indicator to fall-back to
+   numeric register names.  */
+static const struct nanomips_cp0_name nanomips_cp0_numeric[] = {
+  {NULL, 0, 0}
+};
+static const struct nanomips_cp0_select nanomips_cp0sel_numeric[] = {
+  {NULL, 0, 0}
+};
+
+struct nanomips_abi_choice
+{
+  const char *name;
+  const char *const *gpr_names;
+  const char *const *fpr_names;
+};
+
+struct nanomips_abi_choice nanomips_abi_choices[] = {
+  {"numeric", nanomips_gpr_names_numeric, nanomips_fpr_names_numeric},
+  {"p32", nanomips_gpr_names_symbolic, nanomips_fpr_names_64},
+  {"p64", nanomips_gpr_names_symbolic, nanomips_fpr_names_64},
+};
+
+struct nanomips_arch_choice
+{
+  const char *name;
+  int bfd_mach_valid;
+  unsigned long bfd_mach;
+  int processor;
+  int isa;
+  int ase;
+  const struct nanomips_cp0_name *cp0_names;
+  const struct nanomips_cp0_select *cp0sel_names;
+  const char *const *hwr_names;
+};
+
+const struct nanomips_arch_choice nanomips_arch_choices[] = {
+  {"numeric", 0, 0, 0, 0, 0,
+   nanomips_cp0_numeric, nanomips_cp0sel_numeric, nanomips_hwr_names_numeric},
+
+  {"32r6", 1, bfd_mach_nanomipsisa32r6, CPU_NANOMIPS32R6, ISA_NANOMIPS32R6,
+   (ASE_VIRT | ASE_MT | ASE_xNMS),
+   nanomips_cp0_3264r6, nanomips_cp0sel_3264r6, nanomips_hwr_names_3264r6},
+
+  {"32r6s", 1, bfd_mach_nanomipsisa32r6, CPU_NANOMIPS32R6, ISA_NANOMIPS32R6,
+   (ASE_VIRT | ASE_MT),
+   nanomips_cp0_3264r6, nanomips_cp0sel_3264r6, nanomips_hwr_names_3264r6},
+
+  {"64r6", 1, bfd_mach_nanomipsisa64r6, CPU_NANOMIPS64R6, ISA_NANOMIPS64R6,
+   (ASE_VIRT | ASE_MT | ASE_xNMS),
+   nanomips_cp0_3264r6, nanomips_cp0sel_3264r6, nanomips_hwr_names_3264r6},
+};
+
+/* ISA and processor type to disassemble for, and register names to use.
+   set_default_nanomips_dis_options and parse_nanomips_dis_options fill in
+   these values.  */
+
+static int nanomips_processor;
+static int nanomips_ase;
+static int nanomips_isa;
+static const char *const *nanomips_gpr_names;
+static const char *const *nanomips_fpr_names;
+static const struct nanomips_cp0_name *nanomips_cp0_names;
+static const struct nanomips_cp0_select *nanomips_cp0sel_names;
+static const char *const *nanomips_hwr_names;
+
+/* Other options */
+static int no_aliases;	/* If set, disassemble as most general inst.  */
+static bool show_arch_insn; 	/* Mnemonics with suffix.  */
+
+/* Map ABI name to nanomips_abi_choice descriptor.  */
+
+static const struct nanomips_abi_choice *
+choose_abi_by_name (const char *name, unsigned int namelen)
+{
+  const struct nanomips_abi_choice *c;
+  unsigned int i;
+
+  for (i = 0, c = NULL; i < ARRAY_SIZE (nanomips_abi_choices) && c == NULL;
+       i++)
+    if (strncmp (nanomips_abi_choices[i].name, name, namelen) == 0
+	&& strlen (nanomips_abi_choices[i].name) == namelen)
+      c = &nanomips_abi_choices[i];
+
+  return c;
+}
+
+/* Map architecture name to nanomips_arch_choice descriptor.  */
+
+static const struct nanomips_arch_choice *
+choose_arch_by_name (const char *name, unsigned int namelen)
+{
+  const struct nanomips_arch_choice *c = NULL;
+  unsigned int i;
+
+  for (i = 0, c = NULL; i < ARRAY_SIZE (nanomips_arch_choices) && c == NULL;
+       i++)
+    if (strncmp (nanomips_arch_choices[i].name, name, namelen) == 0
+	&& strlen (nanomips_arch_choices[i].name) == namelen)
+      c = &nanomips_arch_choices[i];
+
+  return c;
+}
+
+/* Map BFD architecture to nanomips_arch_choice descriptor.  */
+
+static const struct nanomips_arch_choice *
+choose_arch_by_number (unsigned long mach)
+{
+  static unsigned long hint_bfd_mach;
+  static const struct nanomips_arch_choice *hint_arch_choice;
+  const struct nanomips_arch_choice *c;
+  unsigned int i;
+
+  /* We optimize this because even if the user specifies no
+     flags, this will be done for every instruction!  */
+  if (hint_bfd_mach == mach
+      && hint_arch_choice != NULL
+      && hint_arch_choice->bfd_mach == hint_bfd_mach)
+    return hint_arch_choice;
+
+  for (i = 0, c = NULL; i < ARRAY_SIZE (nanomips_arch_choices) && c == NULL;
+       i++)
+    {
+      if (nanomips_arch_choices[i].bfd_mach_valid
+	  && nanomips_arch_choices[i].bfd_mach == mach)
+	{
+	  c = &nanomips_arch_choices[i];
+	  hint_bfd_mach = mach;
+	  hint_arch_choice = c;
+	}
+    }
+  return c;
+}
+
+/* Select default descriptors and initial mode for the default
+   architecture.  */
+
+static void
+set_default_nanomips_dis_options (struct disassemble_info *info)
+{
+  const struct nanomips_arch_choice *chosen_arch;
+
+  nanomips_isa = ISA_NANOMIPS32R6;
+  nanomips_processor = CPU_NANOMIPS32R6;
+  nanomips_isa = true;
+  nanomips_ase = 0;
+  nanomips_fpr_names = nanomips_fpr_names_numeric;
+  nanomips_cp0_names = nanomips_cp0_numeric;
+  nanomips_cp0sel_names = nanomips_cp0sel_numeric;
+  nanomips_hwr_names = nanomips_hwr_names_numeric;
+  no_aliases = 0;
+  show_arch_insn = false;
+
+  nanomips_gpr_names = nanomips_gpr_names_symbolic;
+
+  /* Set ISA, architecture, and cp0 register names as best we can.  */
+  chosen_arch = choose_arch_by_number (info->mach);
+  if (chosen_arch != NULL)
+    {
+      nanomips_processor = chosen_arch->processor;
+      nanomips_isa = chosen_arch->isa;
+      nanomips_ase = chosen_arch->ase;
+      nanomips_cp0_names = chosen_arch->cp0_names;
+      nanomips_cp0sel_names = chosen_arch->cp0sel_names;
+      nanomips_hwr_names = chosen_arch->hwr_names;
+    }
+}
+
+/* Parse and translate a command-line options to internal state.  */
+
+static void
+parse_nanomips_dis_option (const char *option, unsigned int len)
+{
+  unsigned int i, optionlen, vallen;
+  const char *val;
+  const struct nanomips_abi_choice *chosen_abi;
+  const struct nanomips_arch_choice *chosen_arch;
+
+  /* Try to match options that are simple flags */
+  if (startswith (option, "show-arch-insn"))
+    {
+      show_arch_insn = true;
+      return;
+    }
+
+  if (startswith (option, "no-aliases"))
+    {
+      no_aliases = 1;
+      return;
+    }
+
+  if (startswith (option, "virt"))
+    {
+      nanomips_ase |= ASE_VIRT;
+
+      if (nanomips_isa & ISA_NANOMIPS64R6)
+	nanomips_ase |= ASE_VIRT64;
+    }
+
+  /* Look for the = that delimits the end of the option name.  */
+  for (i = 0; i < len; i++)
+    if (option[i] == '=')
+      break;
+
+  if (i == 0)		/* Invalid option: no name before '='.  */
+    return;
+  if (i == len)		/* Invalid option: no '='.  */
+    return;
+  if (i == (len - 1))	/* Invalid option: no value after '='.  */
+    return;
+
+  optionlen = i;
+  val = option + (optionlen + 1);
+  vallen = len - (optionlen + 1);
+
+  if (strncmp ("gpr-names", option, optionlen) == 0
+      && strlen ("gpr-names") == optionlen)
+    {
+      chosen_abi = choose_abi_by_name (val, vallen);
+      if (chosen_abi != NULL)
+	nanomips_gpr_names = chosen_abi->gpr_names;
+      return;
+    }
+
+  if (strncmp ("fpr-names", option, optionlen) == 0
+      && strlen ("fpr-names") == optionlen)
+    {
+      chosen_abi = choose_abi_by_name (val, vallen);
+      if (chosen_abi != NULL)
+	nanomips_fpr_names = chosen_abi->fpr_names;
+      return;
+    }
+
+  if (strncmp ("cp0-names", option, optionlen) == 0
+      && strlen ("cp0-names") == optionlen)
+    {
+      chosen_arch = choose_arch_by_name (val, vallen);
+      if (chosen_arch != NULL)
+	{
+	  nanomips_cp0_names = chosen_arch->cp0_names;
+	  nanomips_cp0sel_names = chosen_arch->cp0sel_names;
+	}
+      return;
+    }
+
+  if (strncmp ("hwr-names", option, optionlen) == 0
+      && strlen ("hwr-names") == optionlen)
+    {
+      chosen_arch = choose_arch_by_name (val, vallen);
+      if (chosen_arch != NULL)
+	nanomips_hwr_names = chosen_arch->hwr_names;
+      return;
+    }
+
+  if (strncmp ("reg-names", option, optionlen) == 0
+      && strlen ("reg-names") == optionlen)
+    {
+      /* We check both ABI and ARCH here unconditionally, so
+         that "numeric" will do the desirable thing: select
+         numeric register names for all registers.  Other than
+         that, a given name probably won't match both.  */
+      chosen_abi = choose_abi_by_name (val, vallen);
+      if (chosen_abi != NULL)
+	{
+	  nanomips_gpr_names = chosen_abi->gpr_names;
+	  nanomips_fpr_names = chosen_abi->fpr_names;
+	}
+      chosen_arch = choose_arch_by_name (val, vallen);
+      if (chosen_arch != NULL)
+	{
+	  nanomips_cp0_names = chosen_arch->cp0_names;
+	  nanomips_cp0sel_names = chosen_arch->cp0sel_names;
+	  nanomips_hwr_names = chosen_arch->hwr_names;
+	}
+      return;
+    }
+}
+
+/* Loop to parse nanoMIPS-specific command-line options.  */
+
+static void
+parse_nanomips_dis_options (const char *options)
+{
+  const char *option_end;
+
+  if (options == NULL)
+    return;
+
+  while (*options != '\0')
+    {
+      /* Skip empty options.  */
+      if (*options == ',')
+	{
+	  options++;
+	  continue;
+	}
+      /* We know that *options is neither NUL or a comma.  */
+      option_end = options + 1;
+      while (*option_end != ',' && *option_end != '\0')
+	option_end++;
+
+      parse_nanomips_dis_option (options, option_end - options);
+
+      /* Go on to the next one.  If option_end points to a comma, it
+         will be skipped above.  */
+      options = option_end;
+    }
+}
+
+/* Look-up and print the symbolic name of a named CP0 register with
+   a fixed select value.  Fall-back to numeric format if no match is
+   found.  */
+
+static void
+print_cp0_reg (struct disassemble_info *info, int regno)
+{
+  const fprintf_styled_ftype infprintf = info->fprintf_styled_func;
+
+  int i;
+  unsigned int selnum = regno & NANOMIPSOP_MASK_CP0SEL;
+  unsigned int cp0_regno = regno >> NANOMIPSOP_SH_CP0SEL;
+
+  if (nanomips_cp0_names != nanomips_cp0_numeric)
+    for (i = cp0_regno; nanomips_cp0_names[i].name; i++)
+      {
+	if (nanomips_cp0_names[i].num == cp0_regno
+	    && nanomips_cp0_names[i].sel == selnum)
+	  {
+	    infprintf (info->stream, dis_style_register, "%s",
+				nanomips_cp0_names[i].name + 1);
+	    return;
+	  }
+      }
+
+  /* A select value of 0 is deemed optional.  */
+  if (selnum == 0)
+    infprintf (info->stream, dis_style_register, "$%d", cp0_regno);
+  else
+    infprintf (info->stream, dis_style_register, "$%d,%d", cp0_regno, selnum);
+}
+
+/* Look-up and print the symbolic name of a named CP0 register with
+   a variable select value.  Fall-back to numeric format if no match is
+   found.  */
+
+static void
+print_cp0sel_reg (struct disassemble_info *info, unsigned int regno,
+		  unsigned int selnum)
+{
+  const fprintf_styled_ftype infprintf = info->fprintf_styled_func;
+  int i;
+
+  for (i = 0; nanomips_cp0sel_names[i].name; i++)
+    {
+      if (nanomips_cp0sel_names[i].num == regno
+	  && ((1 << selnum) & nanomips_cp0sel_names[i].selmask) != 0)
+	{
+	  infprintf (info->stream, dis_style_register, "%s,%d",
+			      nanomips_cp0sel_names[i].name + 1, selnum);
+	  return;
+	}
+    }
+
+  /* A select value of 0 is deemed optional.  */
+  if (selnum == 0)
+    infprintf (info->stream, dis_style_register, "$%d", regno);
+  else
+    infprintf (info->stream, dis_style_register, "$%d,%d", regno, selnum);
+}
+
+/* Print register REGNO, of type TYPE, for instruction OPCODE.  */
+
+static void
+print_reg (struct disassemble_info *info,
+	   const struct nanomips_opcode *opcode,
+	   enum nanomips_reg_operand_type type, int regno)
+{
+  const fprintf_styled_ftype infprintf = info->fprintf_styled_func;
+
+  switch (type)
+    {
+    case OP_REG_GP:
+      infprintf (info->stream, dis_style_register, "%s", nanomips_gpr_names[regno]);
+      break;
+
+    case OP_REG_FP:
+      infprintf (info->stream, dis_style_register, "%s", nanomips_fpr_names[regno]);
+      break;
+
+    case OP_REG_ACC:
+      infprintf (info->stream, dis_style_register, "$ac%d", regno);
+      break;
+
+    case OP_REG_COPRO:
+      if (opcode->name[strlen (opcode->name) - 1] == '1')
+	infprintf (info->stream, dis_style_register, "%s", nanomips_cp0_names[regno]);
+      else
+	infprintf (info->stream, dis_style_register, "$%d", regno);
+      break;
+
+    case OP_REG_HW:
+      info->fprintf_func (info->stream, "%s", nanomips_hwr_names[regno]);
+      break;
+
+    case OP_REG_CP0:
+      print_cp0_reg (info, regno);
+      break;
+
+    case OP_REG_CP0SEL:
+      /* Need to check select bits againt mask, defer output to next operand.  */
+      break;
+    }
+}
+
+/* Used to track the state carried over from previous operands in
+   an instruction.  */
+
+struct nanomips_print_arg_state
+{
+  /* The value of the last OP_INT seen.  We only use this for OP_MSB,
+     where the value is known to be unsigned and small.  */
+  unsigned int last_int;
+
+  /* The type and number of the last OP_REG seen.  We only use this for
+     OP_REPEAT_DEST_REG and OP_REPEAT_PREV_REG.  */
+  enum nanomips_reg_operand_type last_reg_type;
+  unsigned int last_regno;
+  unsigned int dest_regno;
+  unsigned int seen_dest;
+};
+
+/* Initialize STATE for the start of an instruction.  */
+
+static inline void
+init_print_arg_state (struct nanomips_print_arg_state *state)
+{
+  memset (state, 0, sizeof (*state));
+}
+
+/* Record information about a register operand.  */
+
+static void
+nanomips_seen_register (struct nanomips_print_arg_state *state,
+			unsigned int regno,
+			enum nanomips_reg_operand_type reg_type)
+{
+  state->last_reg_type = reg_type;
+  state->last_regno = regno;
+
+  if (!state->seen_dest)
+    {
+      state->seen_dest = 1;
+      state->dest_regno = regno;
+    }
+}
+
+/* Pretty-print a save/restore register list.  */
+
+static void
+nanomips_print_save_restore (struct disassemble_info *info,
+			     unsigned int uval, bool mode16)
+{
+  const fprintf_styled_ftype infprintf = info->fprintf_styled_func;
+  void *is = info->stream;
+  char *comma = ",";
+  unsigned int pending = 0;
+  unsigned int freg, fp, count, gp, ra;
+  fp = gp = ra = 0;
+
+  if (mode16)
+    {
+      freg = 30 | (uval >> 4);
+      count = uval & 0xf;
+    }
+  else
+    {
+      freg = (uval >> 6) & 0x1f;
+      count = (uval >> 1) & 0xf;
+      if (count > 0)
+	gp = uval & 1;
+    }
+
+  if (freg == 30 && count > 0)
+    fp = 1;
+  if ((freg == 31 && count > 0) || (freg == 30 && count > 1))
+    ra = 1;
+
+  if (freg + count == 45)
+    gp = 1;
+
+  count = count - gp;
+  if (fp && count > 0)
+    {
+      freg = (freg & 0x10) | ((freg + 1) % 32);
+      count--;
+    }
+
+  if (ra && count > 0)
+    {
+      freg = (freg & 0x10) | ((freg + 1) % 32);
+      count--;
+    }
+
+  if (fp)
+    {
+      infprintf (is, dis_style_register, "%s", nanomips_gpr_names[30]);
+      pending = 1;
+    }
+
+  if (ra)
+    {
+      infprintf (is, dis_style_register, "%s%s", (pending ? comma : ""), nanomips_gpr_names[31]);
+      pending = 1;
+    }
+
+  if (count > 0)
+    {
+      if (count > 1)
+	infprintf (is, dis_style_register, "%s%s-%s", (pending ? comma : ""),
+		   nanomips_gpr_names[freg],
+		   nanomips_gpr_names[freg + count - 1]);
+      else
+	infprintf (is, dis_style_register, "%s%s", (pending ? comma : ""),
+		   nanomips_gpr_names[freg]);
+      pending = 1;
+    }
+
+  if (gp)
+    infprintf (is, dis_style_register, "%s%s", (pending ? comma : ""), nanomips_gpr_names[28]);
+}
+
+/* Pretty-print save/restore floating-point register list.  */
+
+static void
+nanomips_print_save_restore_fp (struct disassemble_info *info,
+				unsigned int count)
+{
+  const fprintf_styled_ftype infprintf = info->fprintf_styled_func;
+  void *is = info->stream;
+
+  if (count == 1)
+    infprintf (is, dis_style_register, "%s", nanomips_fpr_names[0]);
+  else
+    infprintf (is, dis_style_register, "%s-%s", nanomips_fpr_names[0],
+	       nanomips_fpr_names[count - 1]);
+}
+
+/* Print operand OPERAND of OPCODE, using STATE to track inter-operand state.
+   UVAL is the encoding of the operand (shifted into bit 0) and BASE_PC is
+   the base address for OP_PCREL operands.  */
+
+static void
+print_insn_arg (struct disassemble_info *info,
+		struct nanomips_print_arg_state *state,
+		const struct nanomips_opcode *opcode,
+		const struct nanomips_operand *operand,
+		bfd_vma base_pc, unsigned int uval)
+{
+  const fprintf_styled_ftype infprintf = info->fprintf_styled_func;
+  void *is = info->stream;
+
+  switch (operand->type)
+    {
+    case OP_INT:
+    case OP_IMM_INT:
+      {
+	const struct nanomips_int_operand *int_op;
+
+	int_op = (const struct nanomips_int_operand *) operand;
+	uval = nanomips_decode_int_operand (int_op, uval);
+	state->last_int = uval;
+	if (int_op->print_hex)
+	  infprintf (is, dis_style_immediate, "0x%x", uval);
+	else
+	  infprintf (is, dis_style_immediate, "%d", uval);
+      }
+      break;
+
+    case OP_MAPPED_INT:
+      {
+	const struct nanomips_mapped_int_operand *mint_op;
+
+	mint_op = (const struct nanomips_mapped_int_operand *) operand;
+	uval = mint_op->int_map[uval];
+	state->last_int = uval;
+	if (mint_op->print_hex)
+	  infprintf (is, dis_style_immediate, "0x%x", uval);
+	else
+	  infprintf (is, dis_style_immediate, "%d", uval);
+      }
+      break;
+
+    case OP_MSB:
+      {
+	const struct nanomips_msb_operand *msb_op;
+
+	msb_op = (const struct nanomips_msb_operand *) operand;
+	uval += msb_op->bias;
+	if (msb_op->add_lsb)
+	  uval -= state->last_int;
+	infprintf (is, dis_style_immediate, "%d", uval);
+      }
+      break;
+
+    case OP_REG:
+    case OP_OPTIONAL_REG:
+    case OP_MAPPED_CHECK_PREV:
+    case OP_BASE_CHECK_OFFSET:
+      {
+	const struct nanomips_reg_operand *reg_op;
+
+	reg_op = (const struct nanomips_reg_operand *) operand;
+	uval = nanomips_decode_reg_operand (reg_op, uval);
+	print_reg (info, opcode, reg_op->reg_type, uval);
+
+	nanomips_seen_register (state, uval, reg_op->reg_type);
+      }
+      break;
+
+    case OP_REG_PAIR:
+      {
+	const struct nanomips_reg_pair_operand *pair_op;
+
+	pair_op = (const struct nanomips_reg_pair_operand *) operand;
+	print_reg (info, opcode, pair_op->reg_type, pair_op->reg1_map[uval]);
+	infprintf (is, dis_style_text, ",");
+	print_reg (info, opcode, pair_op->reg_type, pair_op->reg2_map[uval]);
+      }
+      break;
+
+    case OP_PCREL:
+      {
+	const struct nanomips_pcrel_operand *pcrel_op;
+
+	pcrel_op = (const struct nanomips_pcrel_operand *) operand;
+	info->target = nanomips_decode_pcrel_operand (pcrel_op, base_pc, uval);
+
+	/* Preserve the ISA bit for the GDB disassembler,
+	   otherwise clear it.  */
+	if (info->flavour != bfd_target_unknown_flavour)
+	  info->target &= -2;
+
+	(*info->print_address_func) (info->target, info);
+      }
+      break;
+
+    case OP_NON_ZERO_PCREL_S1:
+      {
+	const struct nanomips_pcrel_operand pcrel_op = {
+	  {{OP_PCREL, operand->size, operand->lsb, 0, 0},
+	   (1 << operand->size) - 1, 0, 1, true}, 0, 0, 0
+	};
+
+	if ((info->flags & INSN_HAS_RELOC) == 0)
+	  info->target = nanomips_decode_pcrel_operand (&pcrel_op, base_pc,
+							uval);
+	else
+	  info->target = 0;
+	(*info->print_address_func) (info->target, info);
+      }
+      break;
+
+    case OP_CHECK_PREV:
+    case OP_NON_ZERO_REG:
+      {
+	print_reg (info, opcode, OP_REG_GP, uval & 31);
+	nanomips_seen_register (state, uval, OP_REG_GP);
+      }
+      break;
+
+    case OP_SAVE_RESTORE_LIST:
+      nanomips_print_save_restore (info, uval, opcode->mask >> 16 == 0);
+      break;
+
+    case OP_SAVE_RESTORE_FP_LIST:
+      nanomips_print_save_restore_fp (info, uval + 1);
+      break;
+
+    case OP_REPEAT_PREV_REG:
+      print_reg (info, opcode, state->last_reg_type, state->last_regno);
+      break;
+
+    case OP_REPEAT_DEST_REG:
+      print_reg (info, opcode, state->last_reg_type, state->dest_regno);
+      break;
+
+    case OP_HI20_PCREL:
+      {
+	if ((info->flags & INSN_HAS_RELOC) == 0)
+	  {
+	    uval = nanomips_decode_hi20_int_operand (operand, uval);
+	    infprintf (is, dis_style_immediate, "0x%x", uval & 0xfffff);
+	  }
+	else
+	  {
+	    info->target = nanomips_decode_hi20_pcrel_operand (operand, base_pc,
+							       uval);
+	    infprintf (is, dis_style_text, "%%pcrel_hi(");
+	    (*info->print_address_func) (info->target, info);
+	    infprintf (is, dis_style_text, ")");
+	  }
+      }
+      break;
+
+    case OP_HI20_SCALE:
+      {
+	uval = nanomips_decode_hi20_int_operand (operand, uval);
+	state->last_int = uval;
+	infprintf (is, dis_style_immediate, "0x%x", uval & 0xfffff);
+      }
+      break;
+
+    case OP_HI20_INT:
+      {
+	uval = nanomips_decode_hi20_int_operand (operand, uval);
+	state->last_int = uval;
+	if ((info->flags & INSN_HAS_RELOC) != 0 || uval == 0)
+	  infprintf (is, dis_style_immediate, "0x%x", uval & 0xfffff);
+	else
+	  infprintf (is, dis_style_immediate, "%%hi(0x%x)", (uval & 0xfffff) << 12);
+      }
+      break;
+
+    case OP_IMM_WORD:
+      {
+	const struct nanomips_int_operand *int_op;
+	int_op = (const struct nanomips_int_operand *) operand;
+	state->last_int = ((uval >> 16) & 0xffff) | (uval << 16);
+	state->last_int += int_op->bias;
+	infprintf (is, dis_style_immediate, "%d", state->last_int);
+      }
+      break;
+
+    case OP_INT_WORD:
+    case OP_GPREL_WORD:
+      {
+	state->last_int = ((uval >> 16) & 0xffff) | (uval << 16);
+	infprintf (is, dis_style_immediate, "%d", state->last_int);
+      }
+      break;
+
+    case OP_UINT_WORD:
+      {
+	state->last_int = ((uval >> 16) & 0xffff) | (uval << 16);
+	infprintf (is, dis_style_immediate, "0x%x", state->last_int);
+      }
+      break;
+
+    case OP_PC_WORD:
+      {
+	info->target = base_pc + (((uval >> 16) & 0xffff) | (uval << 16));
+	(*info->print_address_func) (info->target, info);
+      }
+      break;
+
+    case OP_NEG_INT:
+      infprintf (is, dis_style_immediate, "-%d", uval);
+      break;
+
+    case OP_CP0SEL:
+      print_cp0sel_reg (info, state->last_regno, uval);
+      break;
+
+    case OP_DONT_CARE:
+    case OP_COPY_BITS:
+    default:
+      break;
+    }
+}
+
+/* Check if register+select map to a valid CP0 select sequence.  */
+
+static bool
+validate_cp0_reg_operand (unsigned int uval)
+{
+  int i;
+  unsigned int regno, selnum;
+  regno = uval >> NANOMIPSOP_SH_CP0SEL;
+  selnum = uval & NANOMIPSOP_MASK_CP0SEL;
+
+  for (i = 0; nanomips_cp0_3264r6[i].name; i++)
+    if (regno == nanomips_cp0_3264r6[i].num
+	&& selnum == nanomips_cp0_3264r6[i].sel)
+      break;
+    else if (regno < nanomips_cp0_3264r6[i].num)
+      return false;
+
+  if (nanomips_cp0_3264r6[i].name == NULL)
+    return false;
+
+  return true;
+}
+
+/* Validate the arguments for INSN, which is described by OPCODE.
+   Use DECODE_OPERAND to get the encoding of each operand.  */
+
+static bool
+validate_insn_args (const struct nanomips_opcode *opcode,
+		    const struct nanomips_operand *(*decode_operand) (const char *),
+		    unsigned int insn, struct disassemble_info *info)
+{
+  struct nanomips_print_arg_state state;
+  const struct nanomips_operand *operand;
+  const char *s;
+  unsigned int uval;
+
+  init_print_arg_state (&state);
+  for (s = opcode->args; *s; ++s)
+    {
+      switch (*s)
+	{
+	case ',':
+	case '(':
+	case ')':
+	  break;
+
+	case '#':
+	  ++s;
+	  break;
+
+	default:
+	  operand = decode_operand (s);
+
+	  if (!operand)
+	    continue;
+
+	  uval = nanomips_extract_operand (operand, insn);
+	  switch (operand->type)
+	    {
+	    case OP_REG:
+	    case OP_OPTIONAL_REG:
+	    case OP_BASE_CHECK_OFFSET:
+	      {
+		const struct nanomips_reg_operand *reg_op;
+
+		reg_op = (const struct nanomips_reg_operand *) operand;
+
+		if (operand->type == OP_REG
+		    && reg_op->reg_type == OP_REG_CP0
+		    && !validate_cp0_reg_operand (uval))
+		  return false;
+
+		uval = nanomips_decode_reg_operand (reg_op, uval);
+		nanomips_seen_register (&state, uval, reg_op->reg_type);
+	      }
+	      break;
+
+	    case OP_CHECK_PREV:
+	      {
+		const struct nanomips_check_prev_operand *prev_op
+		  = (const struct nanomips_check_prev_operand *) operand;
+
+		if (!prev_op->zero_ok && uval == 0)
+		  return false;
+
+		if (((prev_op->less_than_ok && uval < state.last_regno)
+		     || (prev_op->greater_than_ok && uval > state.last_regno)
+		     || (prev_op->equal_ok && uval == state.last_regno)))
+		  break;
+
+		return false;
+	      }
+
+	    case OP_MAPPED_CHECK_PREV:
+	      {
+		const struct nanomips_mapped_check_prev_operand *prev_op =
+		  (const struct nanomips_mapped_check_prev_operand *) operand;
+		unsigned int last_uval =
+		  nanomips_encode_reg_operand (operand, state.last_regno);
+
+		if (((prev_op->less_than_ok && uval < last_uval)
+		     || (prev_op->greater_than_ok && uval > last_uval)
+		     || (prev_op->equal_ok && uval == last_uval)))
+		  break;
+
+		return false;
+	      }
+
+	    case OP_NON_ZERO_REG:
+	      if (uval == 0)
+		return false;
+	      break;
+
+	    case OP_NON_ZERO_PCREL_S1:
+	      if (uval == 0 && (info->flags & INSN_HAS_RELOC) == 0)
+		return false;
+	      break;
+
+	    case OP_SAVE_RESTORE_LIST:
+	      {
+		/* The operand for SAVE/RESTORE is split into 3 pieces
+		   rather than just 2 but we only support a 2-way split
+		   decode the last bit of the instruction here.  */
+		if (opcode->mask >> 16 != 0 && ((insn >> 20) & 0x1) != 0)
+		  return false;
+	      }
+	      break;
+
+	    case OP_IMM_INT:
+	    case OP_IMM_WORD:
+	    case OP_NEG_INT:
+	    case OP_INT:
+	    case OP_MAPPED_INT:
+	    case OP_MSB:
+	    case OP_REG_PAIR:
+	    case OP_PCREL:
+	    case OP_REPEAT_PREV_REG:
+	    case OP_REPEAT_DEST_REG:
+	    case OP_SAVE_RESTORE_FP_LIST:
+	    case OP_HI20_INT:
+	    case OP_HI20_PCREL:
+	    case OP_INT_WORD:
+	    case OP_UINT_WORD:
+	    case OP_PC_WORD:
+	    case OP_GPREL_WORD:
+	    case OP_DONT_CARE:
+	    case OP_HI20_SCALE:
+	    case OP_COPY_BITS:
+	    case OP_CP0SEL:
+	      break;
+	    }
+
+	  if (*s == 'm' || *s == '+' || *s == '-' || *s == '`')
+	    ++s;
+	}
+    }
+  return true;
+}
+
+/* Print the arguments for INSN, which is described by OPCODE.
+   Use DECODE_OPERAND to get the encoding of each operand.  Use BASE_PC
+   as the base of OP_PCREL operands, adjusting by LENGTH if the OP_PCREL
+   operand is for a branch or jump.  */
+
+static void
+print_insn_args (struct disassemble_info *info,
+		 const struct nanomips_opcode *opcode,
+		 const struct nanomips_operand *(*decode_operand) (const char *),
+		 uint64_t insn, bfd_vma insn_pc, unsigned int length)
+{
+  const fprintf_styled_ftype infprintf = info->fprintf_styled_func;
+  void *is = info->stream;
+  struct nanomips_print_arg_state state;
+  const struct nanomips_operand *operand;
+  const char *s;
+  bool pending_sep = false;
+  bool pending_space = true;
+
+  init_print_arg_state (&state);
+  for (s = opcode->args; *s; ++s)
+    {
+      switch (*s)
+	{
+	case ',':
+	  pending_sep = true;
+	  break;
+	case '(':
+	  if (pending_sep)
+	    {
+	      infprintf (is, dis_style_text, ",");
+	      pending_sep = false;
+	    }
+	  /* fall-through */
+	case ')':
+	  infprintf (is, dis_style_text, "%c", *s);
+	  break;
+
+	case '#':
+	  ++s;
+	  infprintf (is, dis_style_text, "%c%c", *s, *s);
+	  break;
+
+	default:
+	  operand = decode_operand (s);
+	  if (!operand)
+	    {
+	      /* xgettext:c-format */
+	      infprintf (is, dis_style_text,
+			 _("# internal error, undefined operand in `%s %s'"),
+			 opcode->name, opcode->args);
+	      return;
+	    }
+
+	  /* Defer printing the comma separator for CP0-select values since
+	     the preceding register output is also defered.  */
+	  if (operand->type != OP_DONT_CARE
+	      && operand->type != OP_CP0SEL
+	      && pending_sep)
+	    {
+	      infprintf (is, dis_style_text, ",");
+	      pending_sep = false;
+	    }
+
+	  if (operand->type != OP_DONT_CARE && pending_space)
+	    infprintf (is, dis_style_text, "\t");
+	  pending_space = false;
+
+	  {
+	    bfd_vma base_pc = 0;
+	    bool have_reloc = ((info->flags & INSN_HAS_RELOC) != 0);
+
+	    if (!have_reloc)
+	      base_pc = insn_pc;
+
+	    if ((operand->type == OP_PCREL
+		 || operand->type == OP_HI20_PCREL
+		 || operand->type == OP_NON_ZERO_PCREL_S1
+		 || operand->type == OP_PC_WORD)
+		&& !have_reloc)
+	      base_pc += length;
+
+	    if (operand->type == OP_INT_WORD
+		|| operand->type == OP_UINT_WORD
+		|| operand->type == OP_PC_WORD
+		|| operand->type == OP_GPREL_WORD
+		|| operand->type == OP_IMM_WORD)
+	      print_insn_arg (info, &state, opcode, operand, base_pc,
+			      insn >> 32);
+	    else if (operand->type != OP_DONT_CARE)
+	      print_insn_arg (info, &state, opcode, operand, base_pc,
+			      nanomips_extract_operand (operand, insn));
+	  }
+	  if (*s == 'm' || *s == '+' || *s == '-' || *s == '`')
+	    ++s;
+	  break;
+	}
+    }
+}
+
+enum match_kind
+{
+  MATCH_NONE,
+  MATCH_FULL,
+  MATCH_SHORT
+};
+
+/* Disassemble nanoMIPS instructions.  */
+
+static int
+_print_insn_nanomips (bfd_vma memaddr_base, struct disassemble_info *info)
+{
+  const fprintf_styled_ftype infprintf = info->fprintf_styled_func;
+  const struct nanomips_opcode *op, *opend;
+  void *is = info->stream;
+  bfd_byte buffer[2];
+  uint64_t higher = 0;
+  unsigned int length;
+  int status;
+  uint64_t insn;
+
+  bfd_vma memaddr = memaddr_base;
+
+  info->bytes_per_chunk = 2;
+  info->display_endian = info->endian;
+  info->insn_info_valid = 1;
+  info->branch_delay_insns = 0;
+  info->data_size = 0;
+  info->insn_type = dis_nonbranch;
+  info->target = 0;
+  info->target2 = 0;
+
+  status = (*info->read_memory_func) (memaddr, buffer, 2, info);
+  if (status != 0)
+    {
+      (*info->memory_error_func) (status, memaddr, info);
+      return -1;
+    }
+
+  length = 2;
+
+  if (info->endian == BFD_ENDIAN_BIG)
+    insn = bfd_getb16 (buffer);
+  else
+    insn = bfd_getl16 (buffer);
+
+  if ((insn & 0xfc00) == 0x6000)
+    {
+      unsigned imm;
+      /* This is a 48-bit nanoMIPS instruction. */
+      status = (*info->read_memory_func) (memaddr + 2, buffer, 4, info);
+      if (status != 0)
+	{
+	  infprintf (is, dis_style_text, "0x%x (expected 48 bits): ",
+		     (unsigned) insn);
+	  (*info->memory_error_func) (status, memaddr + 2, info);
+	  return -1;
+	}
+      if (info->endian == BFD_ENDIAN_BIG)
+	imm = bfd_getb16 (buffer);
+      else
+	imm = bfd_getl16 (buffer);
+      higher = (imm << 16);
+
+      status = (*info->read_memory_func) (memaddr + 4, buffer, 2, info);
+
+      if (info->endian == BFD_ENDIAN_BIG)
+	imm = bfd_getb16 (buffer);
+      else
+	imm = bfd_getl16 (buffer);
+      higher = higher | imm;
+
+      length += 4;
+    }
+  else if ((insn & 0x1000) == 0x0)
+    {
+      /* This is a 32-bit nanoMIPS instruction.  */
+      higher = insn;
+
+      status = (*info->read_memory_func) (memaddr + 2, buffer, 2, info);
+      if (status != 0)
+	{
+	  infprintf (is, dis_style_text, "0x%x (expected 32 bits): ",
+		     (unsigned) higher);
+	  (*info->memory_error_func) (status, memaddr + 2, info);
+	  return -1;
+	}
+
+      if (info->endian == BFD_ENDIAN_BIG)
+	insn = bfd_getb16 (buffer);
+      else
+	insn = bfd_getl16 (buffer);
+
+      insn = insn | (higher << 16);
+
+      length += 2;
+    }
+
+  /* FIXME: Should probably use a hash table on the major opcode here.  */
+  const struct nanomips_opcode *opcodes;
+  int num_opcodes;
+  struct nanomips_operand const *(*decode) (const char *);
+
+  opcodes = nanomips_opcodes;
+  num_opcodes = bfd_nanomips_num_opcodes;
+  decode = decode_nanomips_operand;
+
+  opend = opcodes + num_opcodes;
+  for (op = opcodes; op < opend; op++)
+    {
+      if (op->pinfo != INSN_MACRO
+	  && !(no_aliases && (op->pinfo2 & INSN2_ALIAS))
+	  && (insn & op->mask) == op->match
+	  && ((length == 2 && (op->mask & 0xffff0000) == 0)
+	      || (length == 6
+		  && (op->mask & 0xffff0000) == 0)
+	      || (length == 4 && (op->mask & 0xffff0000) != 0)))
+	{
+	  if (!nanomips_opcode_is_member (op, nanomips_isa, nanomips_ase,
+					  nanomips_processor)
+	      || (op->pinfo2 & INSN2_CONVERTED_TO_COMPACT))
+	    continue;
+
+	  if (!validate_insn_args (op, decode, insn, info))
+	    continue;
+
+	  infprintf (is, dis_style_mnemonic, "%s%s", op->name,
+		     (show_arch_insn ? op->suffix : ""));
+
+	  if (length == 6)
+	    insn |= (higher << 32);
+
+	  if (op->args[0])
+	    print_insn_args (info, op, decode, insn, memaddr, length);
+
+	  /* Figure out instruction type and branch delay information.  */
+	  if ((op->pinfo2 & INSN2_UNCOND_BRANCH) != 0)
+	    {
+	      if ((op->pinfo & (INSN_WRITE_GPR_31 | INSN_WRITE_1)) != 0)
+		info->insn_type = dis_jsr;
+	      else
+		info->insn_type = dis_branch;
+	    }
+	  else if ((op->pinfo2 & INSN2_COND_BRANCH) != 0)
+	    {
+	      if ((op->pinfo & INSN_WRITE_GPR_31) != 0)
+		info->insn_type = dis_condjsr;
+	      else
+		info->insn_type = dis_condbranch;
+	    }
+	  else if ((op->pinfo & (INSN_STORE_MEMORY | INSN_LOAD_MEMORY)) != 0)
+	    info->insn_type = dis_dref;
+
+	  return length;
+	}
+    }
+
+  infprintf (is, dis_style_immediate, "0x%x", (unsigned) insn);
+  info->insn_type = dis_noninsn;
+
+  return length;
+}
+
+/* Set up the options and disassemble.  */
+
+int
+print_insn_nanomips (bfd_vma memaddr, struct disassemble_info *info)
+{
+  set_default_nanomips_dis_options (info);
+  parse_nanomips_dis_options (info->disassembler_options);
+
+  return _print_insn_nanomips (memaddr, info);
+}
+
+/* Print description of nanoMIPS-specific command-line options.  */
+
+void
+print_nanomips_disassembler_options (FILE *stream)
+{
+  unsigned int i;
+
+  fprintf (stream, _("\n\
+The following nanoMIPS specific disassembler options are supported for use\n\
+with the -M switch (multiple options should be separated by commas):\n"));
+
+  fprintf (stream, _("\n\
+  no-aliases     Use canonical instruction forms.\n"));
+
+  fprintf (stream, _("\n\
+  show-arch-insn Print extended mnemonics in disassembly including\n\
+                 suffix as in the architecture reference manual.\n"));
+
+  fprintf (stream, _("\n\
+  virt           Recognize the virtualization ASE instructions.\n"));
+
+  fprintf (stream, _("\n\
+  mxu            Recognize the MXU ASE instructions.\n"));
+
+  fprintf (stream, _("\n\
+  gpr-names=ABI            Print GPR names according to  specified ABI.\n\
+                           Default: based on binary being disassembled.\n"));
+
+  fprintf (stream, _("\n\
+  fpr-names=ABI            Print FPR names according to specified ABI.\n\
+                           Default: numeric.\n"));
+
+  fprintf (stream, _("\n\
+  cp0-names=ARCH           Print CP0 register names according to\n\
+                           specified architecture.\n\
+                           Default: based on binary being disassembled.\n"));
+
+  fprintf (stream, _("\n\
+  hwr-names=ARCH           Print HWR names according to specified \n\
+			   architecture.\n\
+                           Default: based on binary being disassembled.\n"));
+
+  fprintf (stream, _("\n\
+  reg-names=ABI            Print GPR and FPR names according to\n\
+                           specified ABI.\n"));
+
+  fprintf (stream, _("\n\
+  reg-names=ARCH           Print CP0 register and HWR names according to\n\
+                           specified architecture.\n"));
+
+  fprintf (stream, _("\n\
+  For the options above, the following values are supported for \"ABI\":\n\
+   "));
+  for (i = 0; i < ARRAY_SIZE (nanomips_abi_choices); i++)
+    fprintf (stream, " %s", nanomips_abi_choices[i].name);
+  fprintf (stream, _("\n"));
+
+  fprintf (stream, _("\n\
+  For the options above, The following values are supported for \"ARCH\":\n\
+   "));
+  for (i = 0; i < ARRAY_SIZE (nanomips_arch_choices); i++)
+    if (*nanomips_arch_choices[i].name != '\0')
+      fprintf (stream, " %s", nanomips_arch_choices[i].name);
+  fprintf (stream, _("\n"));
+
+  fprintf (stream, _("\n"));
+}
+
+/* nanoMIPS hook to predict instruction length from opcode bits.  */
+
+int
+nanomips_predict_insn_length (bfd_vma memaddr_base,
+			      int previous_octect ATTRIBUTE_UNUSED,
+			      struct disassemble_info *info)
+{
+  bfd_byte buffer[2];
+  unsigned int length;
+  uint64_t insn;
+  bfd_vma memaddr = memaddr_base;
+  int status;
+
+  status = (*info->read_memory_func) (memaddr, buffer, 2, info);
+  if (status != 0)
+    {
+      (*info->memory_error_func) (status, memaddr, info);
+      return -1;
+    }
+
+  length = 2;
+
+  if (info->endian == BFD_ENDIAN_BIG)
+    insn = bfd_getb16 (buffer);
+  else
+    insn = bfd_getl16 (buffer);
+
+  if ((insn & 0xfc00) == 0x6000)
+    length += 4;
+  else if ((insn & 0x1000) == 0x0)
+    length += 2;
+
+  return length;
+}
diff --git a/opcodes/nanomips-formats.h b/opcodes/nanomips-formats.h
new file mode 100644
index 00000000000..e477313886d
--- /dev/null
+++ b/opcodes/nanomips-formats.h
@@ -0,0 +1,265 @@
+/* nanomips-formats.h
+   Copyright (C) 2018-2026 Free Software Foundation, CIP United Inc.
+   Contributed by MIPS Tech LLC.
+   Written by Faraz Shahbazker <[email protected]>
+
+   This library is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3, or (at your option)
+   any later version.
+
+   It is distributed in the hope that it will be useful, but WITHOUT
+   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
+   License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; see the file COPYING3. If not,
+   see <http://www.gnu.org/licenses/>.  */
+
+#include "libiberty.h"
+
+#define INT_BIAS(SIZE, LSB, MAX_VAL, BIAS, SHIFT, PRINT_HEX)		\
+  {									\
+    static const struct nanomips_int_operand op = {			\
+      { OP_INT, SIZE, LSB, 0, 0 }, MAX_VAL, BIAS, SHIFT, PRINT_HEX	\
+    };									\
+    return &op.root;							\
+  }
+
+#define INT_ADJ(SIZE, LSB, MAX_VAL, SHIFT, PRINT_HEX)			\
+  INT_BIAS(SIZE, LSB, MAX_VAL, 0, SHIFT, PRINT_HEX)
+
+#define UINT(SIZE, LSB)							\
+  INT_ADJ(SIZE, LSB, (1 << (SIZE)) - 1, 0, false)
+
+#define SINT(SIZE, LSB)							\
+  INT_ADJ(SIZE, LSB, (1 << ((SIZE) - 1)) - 1, 0, false)
+
+#define HINT(SIZE, LSB)							\
+  INT_ADJ(SIZE, LSB, (1 << (SIZE)) - 1, 0, true)
+
+#define BIT(SIZE, LSB, BIAS)						\
+  {									\
+    static const struct nanomips_int_operand op = {			\
+      { OP_INT, SIZE, LSB, 0, 0 }, (1 << (SIZE)) - 1, BIAS, 0, false	\
+    };									\
+    return &op.root;							\
+  }
+
+#define MAPPED_INT(SIZE, LSB, MAP, PRINT_HEX)			\
+  {								\
+    typedef char ATTRIBUTE_UNUSED				\
+      static_assert[(1 << (SIZE)) == ARRAY_SIZE (MAP)];		\
+    static const struct nanomips_mapped_int_operand op = {	\
+      { OP_MAPPED_INT, SIZE, LSB, 0, 0 }, MAP, PRINT_HEX	\
+    };								\
+    return &op.root;						\
+  }
+
+#define MSB(SIZE, LSB, BIAS, ADD_LSB, OPSIZE)			\
+  {								\
+    static const struct nanomips_msb_operand op = {		\
+      { OP_MSB, SIZE, LSB, 0, 0 }, BIAS, ADD_LSB, OPSIZE	\
+    };								\
+    return &op.root;						\
+  }
+
+#define REG(SIZE, LSB, BANK)				\
+  {							\
+    static const struct nanomips_reg_operand op = {	\
+      { OP_REG, SIZE, LSB, 0, 0 }, OP_REG_##BANK, 0	\
+    };							\
+    return &op.root;					\
+  }
+
+#define OPTIONAL_REG(SIZE, LSB, BANK)				\
+  {								\
+    static const struct nanomips_reg_operand op = {		\
+      { OP_OPTIONAL_REG, SIZE, LSB, 0, 0 }, OP_REG_##BANK, 0	\
+    };								\
+    return &op.root;						\
+  }
+
+#define MAPPED_REG(SIZE, LSB, BANK, MAP)		\
+  {							\
+    typedef char ATTRIBUTE_UNUSED			\
+      static_assert[(1 << (SIZE)) == ARRAY_SIZE (MAP)]; \
+    static const struct nanomips_reg_operand op = {	\
+      { OP_REG, SIZE, LSB, 0, 0 }, OP_REG_##BANK, MAP	\
+    };							\
+    return &op.root;					\
+  }
+
+#define SPLIT_MAPPED_REG(SIZE, LSB, SIZE_T, LSB_T, BANK, MAP)	\
+  {								\
+    typedef char ATTRIBUTE_UNUSED				\
+      static_assert[(1 << (SIZE)) == ARRAY_SIZE (MAP)];		\
+    static const struct nanomips_reg_operand op = {		\
+      { OP_REG, SIZE, LSB, SIZE_T, LSB_T }, OP_REG_##BANK, MAP	\
+    };								\
+    return &op.root;						\
+  }
+
+#define OPTIONAL_MAPPED_REG(SIZE, LSB, BANK, MAP)		\
+  {								\
+    typedef char ATTRIBUTE_UNUSED				\
+      static_assert[(1 << (SIZE)) == ARRAY_SIZE (MAP)];		\
+    static const struct nanomips_reg_operand op = {		\
+      { OP_OPTIONAL_REG, SIZE, LSB, 0, 0 }, OP_REG_##BANK, MAP	\
+    };								\
+    return &op.root;						\
+  }
+
+#define REG_PAIR(SIZE, LSB, BANK, MAP)					\
+  {									\
+    typedef char ATTRIBUTE_UNUSED					\
+      static_assert1[(1 << (SIZE)) == ARRAY_SIZE (MAP##1)];		\
+    typedef char ATTRIBUTE_UNUSED					\
+      static_assert2[(1 << (SIZE)) == ARRAY_SIZE (MAP##2)];		\
+    static const struct nanomips_reg_pair_operand op = {		\
+      { OP_REG_PAIR, SIZE, LSB, 0, 0 }, OP_REG_##BANK, MAP##1, MAP##2	\
+    };									\
+    return &op.root;							\
+  }
+
+#define PCREL(SIZE, LSB, IS_SIGNED, SHIFT, ALIGN_LOG2, INCLUDE_ISA_BIT, \
+              FLIP_ISA_BIT)						\
+  {									\
+    static const struct nanomips_pcrel_operand op = {			\
+      { { OP_PCREL, SIZE, LSB, 0, 0 },					\
+	(1 << ((SIZE) - (IS_SIGNED))) - 1, 0, SHIFT, true },		\
+      ALIGN_LOG2, INCLUDE_ISA_BIT, FLIP_ISA_BIT				\
+    };									\
+    return &op.root.root;						\
+  }
+
+#define JUMP(SIZE, LSB, SHIFT)						\
+  PCREL (SIZE, LSB, false, SHIFT, SIZE + SHIFT, true, false)
+
+#define JALX(SIZE, LSB, SHIFT)						\
+  PCREL (SIZE, LSB, false, SHIFT, SIZE + SHIFT, true, true)
+
+#define BRANCH(SIZE, LSB, SHIFT)					\
+  PCREL (SIZE, LSB, true, SHIFT, 0, true, false)
+
+#define SPECIAL(SIZE, LSB, TYPE)					\
+  {									\
+    static const struct nanomips_operand op = { OP_##TYPE, SIZE, LSB, 0, 0 }; \
+    return &op;								\
+  }
+
+#define PREV_CHECK(SIZE, LSB, GT_OK, LT_OK, EQ_OK, ZERO_OK)		\
+  {									\
+    static const struct nanomips_check_prev_operand op = {		\
+      { OP_CHECK_PREV, SIZE, LSB, 0, 0 }, GT_OK, LT_OK, EQ_OK, ZERO_OK	\
+    };									\
+    return &op.root;							\
+  }
+
+#define IMM_INT_BIAS(SIZE, LSB, MAX_VAL, BIAS, SHIFT, PRINT_HEX)	\
+  {									\
+    static const struct nanomips_int_operand op = {			\
+      { OP_IMM_INT, SIZE, LSB, 0, 0 }, MAX_VAL, BIAS, SHIFT, PRINT_HEX	\
+    };									\
+    return &op.root;							\
+  }
+
+#define IMM_INT_ADJ(SIZE, LSB, MAX_VAL, SHIFT, PRINT_HEX)	\
+  IMM_INT_BIAS(SIZE, LSB, MAX_VAL, 0, SHIFT, PRINT_HEX)
+
+#define UINT_SPLIT(SIZE, LSB, SHIFT, SIZE_TOP, LSB_TOP)		\
+  {								\
+    static const struct nanomips_int_operand op = {		\
+      { OP_INT, SIZE, LSB, SIZE_TOP, LSB_TOP },			\
+      (1 << (SIZE)) - 1, 0, SHIFT, 0				\
+    };								\
+    return &op.root;						\
+  }
+
+#define SINT_SPLIT(SIZE, LSB, SHIFT, SIZE_TOP, LSB_TOP, BIAS)	\
+  {								\
+    static const struct nanomips_int_operand op = {		\
+      { OP_INT, SIZE, LSB, SIZE_TOP, LSB_TOP },			\
+      (1 << ((SIZE) -1)) - 1, BIAS, SHIFT, 0			\
+    };								\
+    return &op.root;						\
+  }
+
+#define IMM_SINT_SPLIT(SIZE, LSB, SHIFT, SIZE_TOP, LSB_TOP, BIAS)	\
+  {									\
+    static const struct nanomips_int_operand op = {			\
+      { OP_IMM_INT, SIZE, LSB, SIZE_TOP, LSB_TOP },			\
+      (1 << ((SIZE) -1)) - 1, BIAS, SHIFT, false			\
+    };									\
+    return &op.root;							\
+  }
+
+#define HINT_SPLIT(SIZE, LSB, SIZE_T, LSB_T)				\
+  SINT_SPLIT(SIZE, LSB, 0, SIZE_T, LSB_T)
+
+#define SPLIT_MAPPED_REG_PAIR(SIZE, LSB, SIZE_T, LSB_T, BANK, MAP1, MAP2) \
+  {									\
+    typedef char ATTRIBUTE_UNUSED					\
+      static_assert1[(1 << (SIZE)) == ARRAY_SIZE (MAP1)];		\
+    typedef char ATTRIBUTE_UNUSED					\
+      static_assert2[(1 << (SIZE)) == ARRAY_SIZE (MAP2)];		\
+    static const struct nanomips_reg_pair_operand op = {		\
+      { OP_REG_PAIR, SIZE, LSB, SIZE_T, LSB_T }, OP_REG_##BANK,		\
+      MAP1, MAP2							\
+    };									\
+    return &op.root;							\
+  }
+
+#define BRANCH_UNORD_SPLIT(SIZE, SHIFT)		\
+  {							\
+    static const struct nanomips_pcrel_operand op = {	\
+      { { OP_PCREL, SIZE, 1, 1, 0 },			\
+	(1 << ((SIZE) - 1)) - 1, 0, SHIFT, true },	\
+      0, false, false					\
+    };							\
+    return &op.root.root;				\
+  }
+
+#define BRANCH_SPLIT(SIZE, LSB, SHIFT, SIZE_TOP, LSB_TOP)	\
+  {								\
+    static const struct nanomips_pcrel_operand op = {		\
+      { { OP_PCREL, SIZE, 1, SIZE_TOP, LSB_TOP },		\
+	(1 << ((SIZE) - 1)) - 1, LSB, SHIFT, true },		\
+      0, false, false						\
+    };								\
+    return &op.root.root;					\
+  }
+
+#define SPECIAL_SPLIT(SIZE, LSB, SIZE_T, LSB_T, TYPE)			\
+  {									\
+    static const struct nanomips_operand op = { OP_##TYPE, SIZE, LSB, SIZE_T, LSB_T }; \
+    return &op;								\
+  }
+
+#define SPECIAL_WORD(BIAS, TYPE)					\
+  {									\
+    static const struct nanomips_int_operand op = { { OP_##TYPE, 0, 0, 0, 0 }, \
+						    0x7fffffff, BIAS, 0, false }; \
+    return &op.root;							\
+  }
+
+#define MAPPED_PREV_CHECK(SIZE, LSB, BANK, MAP, GT_OK, LT_OK, EQ_OK, ZERO_OK) \
+  {									\
+    typedef char ATTRIBUTE_UNUSED					\
+      static_assert[(1 << (SIZE)) == ARRAY_SIZE (MAP)];			\
+    static const struct nanomips_mapped_check_prev_operand op = {	\
+      { OP_MAPPED_CHECK_PREV, SIZE, LSB, 0, 0 }, OP_REG_##BANK, MAP,	\
+      GT_OK, LT_OK, EQ_OK, ZERO_OK					\
+    };									\
+    return &op.root;							\
+  }
+
+#define BASE_OFFSET_CHECK(SIZE, LSB, CONST_OK, EXPR_OK)			\
+  {									\
+    static const struct nanomips_base_check_offset_operand op = {	\
+      { OP_BASE_CHECK_OFFSET, SIZE, LSB, 0, 0 }, OP_REG_GP,		\
+      CONST_OK, EXPR_OK							\
+    };									\
+    return &op.root;							\
+  }
diff --git a/opcodes/nanomips-opc.c b/opcodes/nanomips-opc.c
new file mode 100644
index 00000000000..d6e5523fc56
--- /dev/null
+++ b/opcodes/nanomips-opc.c
@@ -0,0 +1,807 @@
+/* nanomips-opc.c.  nanoMIPS opcode table.
+   Copyright (C) 2018-2026 Free Software Foundation, CIP United Inc.
+   Contributed by MIPS Tech LLC.
+   Written by Faraz Shahbazker <[email protected]>
+
+   This file is part of the GNU opcodes library.
+
+   This library is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3, or (at your option)
+   any later version.
+
+   It is distributed in the hope that it will be useful, but WITHOUT
+   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
+   License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this file; see the file COPYING.  If not, write to the
+   Free Software Foundation, 51 Franklin Street - Fifth Floor, Boston,
+   MA 02110-1301, USA.  */
+
+#include "sysdep.h"
+#include "opcode/nanomips.h"
+#include "nanomips-formats.h"
+
+static unsigned char reg_0_map[] = { 0 };
+static unsigned char reg_28_map[] = { 28 };
+static unsigned char reg_29_map[] = { 29 };
+static unsigned char reg_31_map[] = { 31 };
+static unsigned char reg_m16_map[] = { 16, 17, 18, 19, 4, 5, 6, 7 };
+static unsigned char reg_q_map[] = { 0, 17, 18, 19, 4, 5, 6, 7 };
+
+static unsigned char reg_4to5_map[] = {
+  8, 9, 10, 11, 4, 5, 6, 7,
+  16, 17, 18, 19, 20, 21, 22, 23
+};
+
+static unsigned char reg_4to5_srcmap[] = {
+  8, 9, 10, 0, 4, 5, 6, 7,
+  16, 17, 18, 19, 20, 21, 22, 23
+};
+
+static unsigned char reg_4or5_map[] = { 4, 5 };
+
+static unsigned char reg_gpr2d_map1[] = { 4, 5, 6, 7 };
+static unsigned char reg_gpr2d_map2[] = { 5, 6, 7, 8 };
+
+static int int_b_map[] = {
+  0, 4, 8, 12, 16, 20, 24, 28
+};
+
+static int int_c_map[] = {
+  0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 255, 65535, 14, 15
+};
+
+static int word_byte_map[] = {
+  0, 0, 0, 0, 0, 0, 0, 0,
+  3, 0, 0, 0, 0, 0, 0, 0,
+  2, 0, 0, 0, 0, 0, 0, 0,
+  1, 0, 0, 0, 0, 0, 0, 0
+};
+
+static int int_mask_map[] = {
+  0x1, 0x3, 0x7, 0xf,
+  0x1f, 0x3f, 0x7f, 0xff,
+  0x1ff, 0x3ff, 0x7ff, 0xfff,
+  0x1fff, 0x3fff, 0x7fff, 0xffff,
+  0x1ffff, 0x3ffff, 0x7ffff, 0xfffff,
+  0x1fffff, 0x3fffff, 0x7fffff, 0xffffff,
+  0x1ffffff,0x3ffffff,0x7ffffff,0xfffffff,
+  0x1fffffff, 0x3fffffff, 0x7fffffff, 0xffffffff
+};
+
+/* Return the nanomips_operand structure for the operand at the
+   beginning of P.  */
+
+/* FIXME: Unused cases left commented in-place for quick reminder
+   of which character strings are unused.  */
+const struct nanomips_operand *
+decode_nanomips_operand (const char *p)
+{
+  switch (p[0])
+    {
+    case 'm':
+      switch (p[1])
+	{
+	case 'a': MAPPED_REG (0, 0, GP, reg_28_map);
+	case 'b': SPECIAL (5, 5, NON_ZERO_REG);
+	case 'c': OPTIONAL_MAPPED_REG (3, 4, GP, reg_m16_map);
+	case 'd': MAPPED_REG (3, 7, GP, reg_m16_map);
+	case 'e': MAPPED_REG (3, 1, GP, reg_m16_map);
+	case 'f': MAPPED_PREV_CHECK (3, 7, GP, reg_m16_map, true, false, false, false);
+	case 'g': MAPPED_PREV_CHECK (3, 4, GP, reg_m16_map, false, true, false, false);
+	case 'h': MAPPED_PREV_CHECK (3, 7, GP, reg_m16_map, false, true, true, false);
+	case 'i': MAPPED_PREV_CHECK (3, 4, GP, reg_m16_map, true, false, true, false);
+	case 'j': REG (5, 0, GP);
+	case 'k': SPECIAL (0, 0, REPEAT_DEST_REG);
+	case 'l': MAPPED_REG (3, 4, GP, reg_m16_map);
+	case 'm': MAPPED_REG (3, 7, GP, reg_q_map);
+	case 'n': SPECIAL_SPLIT (5, 0, 1, 9, SAVE_RESTORE_LIST);
+	case 'p': REG (5, 5, GP);
+	case 'q': SPLIT_MAPPED_REG_PAIR (2, 8, 1, 3, GP, reg_gpr2d_map1,
+					 reg_gpr2d_map2);
+	case 'r': SPLIT_MAPPED_REG_PAIR (2, 8, 1, 3, GP, reg_gpr2d_map2,
+					 reg_gpr2d_map1);
+	case 's': MAPPED_REG (0, 0, GP, reg_29_map);
+	case 't': SPECIAL (0, 0, REPEAT_PREV_REG);
+	case 'u': SPLIT_MAPPED_REG (4, 5, 1, 9, GP, reg_4to5_map);
+	case 'v': SPLIT_MAPPED_REG (4, 0, 1, 4, GP, reg_4to5_map);
+	case 'w': SPLIT_MAPPED_REG (4, 5, 1, 9, GP, reg_4to5_srcmap);
+	case 'x': SPLIT_MAPPED_REG (4, 0, 1, 4, GP, reg_4to5_srcmap);
+	case 'y': MAPPED_REG (0, 0, GP, reg_31_map);
+	case 'z': UINT (0, 0); 	/* Literal 0 */
+	case 'A': INT_ADJ (7, 0, 127, 2, false);	 /* (0 .. 127) << 2 */
+	case 'B': MAPPED_INT (3, 0, int_b_map, false);
+	case 'C': MAPPED_INT (4, 0, int_c_map, true);
+	case 'D': BRANCH_UNORD_SPLIT (10, 1);
+	case 'E': BRANCH_UNORD_SPLIT (7, 1);
+	case 'F': SPECIAL (4, 0, NON_ZERO_PCREL_S1);
+	case 'G': INT_ADJ (4, 4, 15, 4, false);
+	case 'H': INT_ADJ (2, 1, 3, 1, false);	 /* (0 .. 3) << 1 */
+	case 'I': INT_ADJ (7, 0, 126, 0, false); /* (-1 .. 126) */
+	case 'J': INT_ADJ (4, 0, 15, 2, false);	 /* (0 .. 15) << 2 */
+	case 'K': HINT (3, 0);
+	case 'L': UINT (2, 0);	 /* (0 .. 3) */
+	case 'M': INT_ADJ (3, 0, 8, 0, false);   /* (1 .. 8) */
+	case 'N': UINT_SPLIT (2, 8, 2, 1, 3); /* split encoded 2-bit offset << 2 */
+	case 'O': IMM_INT_ADJ (7, 0, 127, 2, false);	 /* (0 .. 127) << 2 */
+	case 'P': HINT (2, 0);
+	case 'Q': SINT_SPLIT (4, 0, 0, 1, 4, 0);
+	case 'R': INT_ADJ (5, 0, 31, 2, false);	 /* (0 .. 31) << 2 */
+	case 'S': INT_ADJ (6, 0, 63, 2, false);	 /* (0 .. 63) << 2 */
+	case 'Z': UINT (0, 0);			 /* 0 only */
+	}
+      break;
+
+    case '-':
+      switch (p[1])
+	{
+	case 'a': SPECIAL (5, 16, DONT_CARE);
+	case 'b': SPECIAL_SPLIT (8, 9, 5, 16, DONT_CARE);
+	case 'i': REG (0, 0, GP); /* Ignored register operand.  */
+	case 'm': SPECIAL_SPLIT (5, 11, 5, 21, COPY_BITS);
+	case 'n': SPECIAL_SPLIT (5, 11, 5, 16, COPY_BITS);
+	}
+      break;
+
+    case '+':
+      switch (p[1])
+	{
+	case 'A': BIT (5, 0, 0);		 /* (0 .. 31) */
+	case 'B': MSB (5, 6, 1, true, 32);	 /* (1 .. 32), 32-bit op */
+	case 'C': MSB (5, 6, 1, false, 32);	 /* (1 .. 32), 32-bit op */
+	case 'D': SPECIAL (4, 16, SAVE_RESTORE_FP_LIST);
+	case 'E': BIT (5, 0, 32);		 /* (32 .. 63) */
+	case 'F': MSB (5, 6, 33, true, 64);	 /* (33 .. 64), 64-bit op */
+	case 'G': MSB (5, 6, 33, false, 64);	 /* (33 .. 64), 64-bit op */
+	case 'H': MSB (5, 6, 1, false, 64);	 /* (1 .. 32), 64-bit op */
+	case 'I': BIT (5, 6, 0); /* (0 .. 31) */
+	case 'J': HINT (19, 0);
+	case 'K': SPECIAL_SPLIT (20, 2, 1, 0, HI20_PCREL); /* tri-part 20-bit */
+	case 'L': HINT (10, 16);
+	case 'M': HINT (18, 0);
+	case 'N': INT_ADJ (9, 3, 511, 3, false);	/* 9-bit << 3 */
+	case 'O': SPECIAL_WORD (0, GPREL_WORD);
+	case 'P': SPECIAL_WORD (6, IMM_WORD);
+	case 'Q': SPECIAL_WORD (0, UINT_WORD);
+	case 'R': SPECIAL_WORD (0, INT_WORD);
+	case 'S': SPECIAL_WORD (0, PC_WORD);
+
+	case 'i': HINT (5, 16);
+	case 'j': SINT_SPLIT (9, 0, 0, 1, 15, 0);
+	case 'p': SINT_SPLIT (7, 2, 2, 1, 15, 0); /* split 7-bit signed << 2 */
+	case 'q': SINT_SPLIT (6, 3, 3, 1, 15, 0); /* split 6-bit signed << 3 */
+	case 'r': BRANCH_UNORD_SPLIT (21, 1); /* split 21-bit signed << 1 */
+	case 's': IMM_SINT_SPLIT (21, 1, 1, 1, 0, 2); /* split (21-bit signed + 2) << 1 */
+	case 't': SPECIAL (5, 21, NON_ZERO_REG);
+	case 'u': BRANCH_UNORD_SPLIT (25, 1);
+	case 'v': MAPPED_INT (5, 6, word_byte_map, false);
+	case 'w': BIT (2, 9, 0);		/* (0 .. 3) */
+
+	case '*': INT_ADJ (4, 7, 15, 1, false); /* (0 .. 15) << 1 */
+	case '|': UINT (1, 6);			/* 0/1 */
+	case ';': UINT (2, 21);			/* (0 .. 3) */
+	case '1': UINT (18, 0);
+	case '2': INT_ADJ (16, 2, (1<<16) - 1, 2, false);
+	case '3': INT_ADJ (17, 1, (1<<17) - 1, 1, false);
+	case '4': INT_ADJ (18, 3, (1<<18)-1, 3, false); /* 18-bit << 3 */
+	case '5': SPLIT_MAPPED_REG (4, 21, 1, 25, GP, reg_4to5_srcmap);
+	case '6': MAPPED_INT (5, 6, int_mask_map, true);
+	case '7': MAPPED_REG (1, 24, GP, reg_4or5_map);
+	case '8': HINT (23, 3);
+	case '9': UINT (7, 11);
+	}
+      break;
+
+    case '.': INT_ADJ (19, 2, (1<<19) - 1, 2, false);
+    case '<': BIT (5, 0, 0);			 /* (0 .. 31) */
+/*     case '>': BIT (5, 11, 32);			 /\* (32 .. 63) *\/ */
+    case '\\': BIT (3, 21, 0);			 /* (0 .. 7) */
+    case '|': INT_ADJ (3, 12, 8, 0, false);	/* 1 .. 8 */
+    case '~': BRANCH_UNORD_SPLIT (11, 1);	/* split 11-bit signed << 1 */
+    case '@': SINT (10, 11);
+    case '^': HINT (5, 11);
+    case '!': UINT (1, 10);
+    case '$': UINT (1, 3);
+    case '*': REG (2, 18, ACC);
+/*     case '&': REG (2, 23, ACC); */
+
+    case '0': SINT (6, 16);
+    case '1': BIT (5, 11, 0);			 /* (0 .. 31) */
+    case '2': BIT (5, 16, 0);		/* (0 .. 31) */
+    case '3': BIT (3, 13, 0);
+    case '4': BIT (4, 12, 0);
+    case '5': HINT (8, 13);
+    case '7': REG (2, 14, ACC);
+    case '8': HINT (7, 14);
+
+    case 'C': HINT (23, 3);
+    case 'D': REG (5, 11, FP);
+    case 'E': REG (5, 21, COPRO);
+    case 'G': REG (5, 16, COPRO);
+    case 'H': UINT (5, 11);
+    case 'J': SPECIAL (5, 11, CP0SEL);
+    case 'K': REG (5, 16, HW);
+/*     case 'M': REG (3, 13, CCC); */
+/*     case 'N': REG (3, 18, CCC); */
+    case 'O': REG (10, 11, CP0);
+    case 'P': REG (5, 16, CP0SEL);
+/*     case 'Q': UINT (5, 11); */
+    case 'R': REG (5, 11, FP);
+    case 'S': REG (5, 16, FP);
+    case 'T': REG (5, 21, FP);
+    case 'V': OPTIONAL_REG (5, 16, FP);
+
+/*     case 'a': JUMP (26, 0, 1); */
+    case 'b': REG (5, 16, GP);
+    case 'c': BASE_OFFSET_CHECK (5, 16, true, false);
+    case 'd': REG (5, 11, GP);
+    case 'e': REG (5, 3, GP);
+    case 'g': HINT (12, 0);
+    case 'h': SPECIAL (12, 0, NEG_INT);
+    case 'i': UINT (12, 0);
+    case 'j': UINT (16, 0);
+    case 'k': HINT (5, 21);
+    case 'n': SPECIAL_SPLIT (11, 2, 10, 16, SAVE_RESTORE_LIST);
+    case 'o': UINT (12, 0);
+    case 'p': BRANCH_UNORD_SPLIT (14, 1);
+/*     case 'q': BRANCH_UNORD_SPLIT (20, 1); - unused */
+    case 'r': OPTIONAL_REG (5, 16, GP);
+    case 's': REG (5, 16, GP);
+    case 't': REG (5, 21, GP);
+    case 'u': SPECIAL_SPLIT (20, 2, 1, 0, HI20_INT);  /* tri-part 20-bit */
+    case 'v': OPTIONAL_REG (5, 16, GP);
+    case 'w': OPTIONAL_REG (5, 21, GP);
+    case 'x': SPECIAL_SPLIT (20, 2, 1, 0, HI20_SCALE);  /* tri-part 20-bit */
+    case 'z': MAPPED_REG (0, 0, GP, reg_0_map);
+    }
+  return 0;
+}
+
+#define LM	INSN_LOAD_MEMORY
+#define SM	INSN_STORE_MEMORY
+
+#define WR_1	INSN_WRITE_1
+#define WR_2	INSN_WRITE_2
+#define RD_1	INSN_READ_1
+#define RD_2	INSN_READ_2
+#define RD_3	INSN_READ_3
+#define MOD_1	(WR_1|RD_1)
+#define MOD_2	(WR_2|RD_2)
+#define FP_S	INSN_FP_S
+#define FP_D	INSN_FP_D
+
+ /* Write dsp accumulators */
+#define WR_a	INSN_WRITE_ACC
+ /* Read dsp accumulators */
+#define RD_a	INSN_READ_ACC
+
+/* Flags used in pinfo2.  */
+#define CTC	INSN2_CONVERTED_TO_COMPACT
+#define UBR	INSN2_UNCOND_BRANCH
+#define CBR	INSN2_COND_BRANCH
+#define ALIAS	INSN2_ALIAS
+
+/* For 32-bit nanoMIPS instructions.  */
+#define WR_31	INSN_WRITE_GPR_31
+
+/* nanoMIPS MT ASE support.  */
+#define MT32	ASE_MT
+
+/* nanoMIPS instruction subset.  */
+#define xNMS	ASE_xNMS
+
+/* Base ISA for nanoMIPS. */
+#define I38	INSN_ISAN32R6
+#define I70	INSN_ISAN64R6
+
+const struct nanomips_opcode nanomips_opcodes[] = {
+/* These instructions appear first so that the disassembler will find
+   them first.  The assemblers uses a hash table based on the
+   instruction name anyhow.  */
+/* name,	suffix,		args,		match,		mask,	     pinfo	pinfo2,	 membership, ase */
+/* Pure macros */
+{"la",		"",		"t,A(b)",	0,    (int) M_LA_AB,	INSN_MACRO,		0,	I38,	0},
+{"dla", 	"",		"t,A(b)",	0,    (int) M_DLA_AB,	INSN_MACRO,		0,	I38,	0},
+/* Precedence=1 */
+{"aluipc",	"",		"t,+K", 	0xe0000002, 0xfc000002, WR_1,			0,	I38,	0}, /* ALUIPC */
+{"break",	"[16]", 	"",		0x1010, 	0xffff,	0,		INSN2_ALIAS,	I38,	0},
+{"break",	"[16]", 	"mK",		0x1010, 	0xfff8,	0,			0,	I38,	0},
+{"break",	"[32]", 	"",		0x00100000, 0xffffffff,		0,	INSN2_ALIAS,	I38,	0},
+{"break",	"[32]", 	"+J",		0x00100000, 0xfff80000,		0,		0,	I38,	0},
+{"dvp", 	"",		"-a",		0x20000390, 0xffe0ffff,		0,	INSN2_ALIAS,	I38,	0}, /* DVP */
+{"dvp", 	"",		"t,-a", 	0x20000390, 0xfc00ffff,		WR_1,		0,	I38,	0},
+{"nop", 	"[16]", 	"",		0x9008,		0xffff,		0,		0,	I38,	0}, /* NOP[16] */
+{"nop", 	"[32]", 	"",		0x8000c000, 0xffffffff,		0,		0,	I38,	0}, /* NOP */
+{"sdbbp",	"[16]", 	"",		0x1018,		0xffff,		0,	INSN2_ALIAS,	I38,	0},
+{"sdbbp",	"[16]", 	"mK",		0x1018,		0xfff8,		0,		0,	I38,	0},
+{"sdbbp",	"[32]", 	"",		0x00180000, 0xffffffff,		0,	INSN2_ALIAS,	I38,	0},
+{"sdbbp",	"[32]", 	"+J",		0x00180000, 0xfff80000,		0,		0,	I38,	0},
+{"move",	"",		"mb,mj",	0x1000,		0xfc00,	WR_1|RD_2,		0,	I38,	0}, /* preceded by BREAK, SDBBP */
+{"move",	"",		"d,s",		0x20000290, 0xffe007ff, WR_1|RD_2,	INSN2_ALIAS,	I38,	0}, /* OR */
+{"move",	"",		"d,s",		0x20000150, 0xffe007ff, WR_1|RD_2,	INSN2_ALIAS,	I38,	0}, /* ADDU */
+{"sigrie",	"",		"+J",		0x00000000, 0xfff80000,	0,			0,	I38,	0},
+{"synci",	"[u12]",	"o(b)", 	0x87e03000, 0xffe0f000,	RD_2,			0,	I38,	0}, /* SYNCI[U12] */
+{"synci",	"[s9]", 	"+j(b)",	0xa7e01800, 0xffe07f00,	RD_2,			0,	I38,	0}, /* SYNCI[S9] */
+{"jrc", 	"[16]", 	"mp",		0xd800, 	0xfc1f,	RD_1,			0,	I38,	0}, /* JRC[16] */
+{"jrc", 	"[32]", 	"s",		0x48000000, 0xffe0ffff,	RD_1,		INSN2_ALIAS,	I38,	0}, /* JALRC */
+{"jalrc",	"[16]", 	"mp",		0xd810, 	0xfc1f,	WR_31|RD_1,		0,	I38,	0}, /* JALRC[16] */
+{"jalrc",	"[16]", 	"my,mp",	0xd810, 	0xfc1f,	WR_31|RD_1,	INSN2_ALIAS,	I38,	0}, /* JALRC[16] */
+{"jalrc",	"[32]", 	"s",		0x4be00000, 0xffe0ffff,	RD_1,		INSN2_ALIAS,	I38,	0}, /* JALRC[32] */
+{"jalrc",	"[32]", 	"t,s",		0x48000000, 0xfc00ffff,	WR_1|RD_2,		0,	I38,	0},
+{"jalrc",	"",		"mp,-i",	0xd810, 	0xfc1f,	WR_31|RD_1,	INSN2_ALIAS,	I38,	0}, /* JALRC[16] */
+{"jalrc",	"",		"s,-i", 	0x4be00000, 0xffe0ffff,	RD_1,		INSN2_ALIAS,	I38,	0}, /* JALRC[32] */
+{"jr",		"",		"mp",		0xd800, 	0xfc1f,	RD_1,	    INSN2_ALIAS|UBR|CTC, I38,	0}, /* JRC */
+{"jr",		"",		"s",		0x48000000, 0xffe0ffff,	RD_1,	    INSN2_ALIAS|UBR|CTC, I38,	0}, /* JALRC */
+{"jalr",	"",		"my,mp",	0xd810, 	0xfc1f,	WR_31|RD_1, INSN2_ALIAS|UBR|CTC, I38,	0}, /* JALRC[16] */
+{"jalr",	"",		"mp",		0xd810, 	0xfc1f,	WR_31|RD_1, INSN2_ALIAS|UBR|CTC, I38,	0}, /* JALRC[16] */
+{"jalr",	"",		"s",		0x4be00000, 0xffe0ffff,	RD_1,	    INSN2_ALIAS|UBR|CTC, I38,	0}, /* JALRC */
+{"jalr",	"",		"t,s",		0x48000000, 0xfc00ffff,	WR_1|RD_2,  INSN2_ALIAS|UBR|CTC, I38,	0}, /* JALRC */
+{"lui", 	"",		"t,u",		0xe0000000, 0xfc000002,	WR_1,			0,	I38,	0},
+{"li",		"[16]", 	"md,mI",	0xd000, 	0xfc00,	WR_1,			0,	I38,	0}, /* LI[16] */
+{"li",		"",		"mb,mZ",	0x1000, 	0xfc1f,	WR_1,		INSN2_ALIAS,	I38,	0}, /* MOVE[16] */
+{"li",		"[32]", 	"+t,j", 	0x00000000, 0xfc1f0000,	WR_1,		INSN2_ALIAS,	I38,	0}, /* ADDIU[32] */
+{"li",		"[neg]",	 "t,h", 	0x80008000, 0xfc1ff000,	WR_1,		INSN2_ALIAS,	I38,	0}, /* ADDIU[NEG] */
+{"li",		"",		"t,x",		0xe0000000, 0xfc000002,	WR_1,		INSN2_ALIAS,	I38,	0}, /* LUI */
+{"li",		"[48]", 	"mp,+Q",	0x6000, 	0xfc1f,	WR_1,			0,	0,	xNMS}, /* LI[48] */
+{"li",		"",		"+t,A", 	0,		(int) M_LI,	INSN_MACRO,	INSN2_MACRO,	I38,	0},
+{"ext", 	"",		"t,r,+A,+C",	0x8000f000, 0xfc00f820,	WR_1|RD_2,		0,	0,	xNMS},
+{"ext", 	"",		"t,r,+A,+C",	0,	   (int) M_EXT,	INSN_MACRO,		0,	I38,	0},
+
+/* Precedence=0 */
+{"abs", 	"",		"d,v",		0,	   (int) M_ABS,	INSN_MACRO,		0,	I38,	0},
+{"add", 	"",		"d,v,t",	0x20000110, 0xfc0007ff, WR_1|RD_2|RD_3,		0,	0,	xNMS},
+{"add", 	"",		"t,r,I",	0,    (int) M_ADD_I,	INSN_MACRO,		0,	0,	xNMS},
+{"addi",	"",		"t,r,I",	0,    (int) M_ADD_I,	INSN_MACRO,		0,	0,	xNMS},
+{"addiu",	"[r1.sp]",	"md,ms,mS",	0x7040, 	0xfc40,	WR_1|RD_2,		0,	I38,	0}, /* ADDIU[R1.SP] */
+{"addiu",	"[r2]", 	"md,mc,mB",	0x9000, 	0xfc08,	WR_1|RD_2,		0,	I38,	0}, /* ADDIU[R2] */
+{"addiu",	"[rs5]",	"mp,mk,mQ",	0x9008, 	0xfc08,	MOD_1,		INSN2_ALIAS,	I38,	0}, /* ADDIU[RS5] */
+{"addiu",	"[rs5]",	"mp,mQ",	0x9008, 	0xfc08,	MOD_1,			0,	I38,	0}, /* ADDIU[RS5], preceded by NOP[16] */
+{"addiu",	"[gp.b]",	"t,ma,+1",	0x440c0000, 0xfc1c0000,	WR_1|RD_2,		0,	I38,	0}, /* ADDIU[GP.B] */
+{"addiu",	"[gp.w]",	"t,ma,.",	0x40000000, 0xfc000003,	WR_1|RD_2,		0,	I38,	0}, /* ADDIU[GP.W] */
+{"addiu",	"[32]", 	"+t,r,j",	0x00000000, 0xfc000000,	WR_1|RD_2,		0,	I38,	0}, /* preceded by SIGRIE */
+{"addiu",	"[neg]",	"t,r,h",	0x80008000, 0xfc00f000,	WR_1|RD_2,		0,	I38,	0}, /* ADDIU[NEG] */
+{"addiu",	"[48]", 	"mp,mt,+R",	0x6001, 	0xfc1f,	MOD_1,			0,	0,	xNMS}, /* ADDIU[48] */
+{"addiu",	"[gp48]",	"mp,ma,+O",	0x6002, 	0xfc1f,	WR_1|RD_2,		0,	0,	xNMS}, /* ADDIU[GP48] */
+{"lapc",	"[32]", 	"t,+r", 	0x04000000, 0xfc000000, WR_1,		INSN2_ALIAS,	I38,	0}, /* ADDIUPC */
+{"lapc",	"[48]", 	"mp,+S",	0x6003, 	0xfc1f,	WR_1,		INSN2_ALIAS,	0,	xNMS}, /* ADDIUPC[48] */
+{"addiupc",	"[32]", 	"t,+s", 	0x04000000, 0xfc000000, WR_1,			0,	I38,	0},
+{"addiupc",	"[48]", 	"mp,+P",	0x6003, 	0xfc1f,	WR_1,			0,	0,	xNMS}, /* ADDIUPC[48] */
+{"addiu.b",	"",		"t,ma,+1",	0x440c0000, 0xfc1c0000,	WR_1|RD_2,	INSN2_ALIAS,	I38,	0}, /* ADDIU[GP.B] */
+{"addiu.w",	"",		"t,ma,.",	0x40000000, 0xfc000003,	WR_1|RD_2,	INSN2_ALIAS,	I38,	0}, /* ADDIU[GP.W] */
+{"addu",	"[16]", 	"me,mc,md",	0xb000,		0xfc01, WR_1|RD_2|RD_3,		0,	I38,	0}, /* ADDU[16] */
+{"addu",	"[4x4]",	"mu,mt,mv",	0x3c00,		0xfd08,	MOD_1|RD_3,		0,	0,	xNMS}, /* ADDU[4X4] */
+{"addu",	"[4x4]",	"mu,mv,mk",	0x3c00,		0xfd08,	MOD_1|RD_2,	INSN2_ALIAS,	0,	xNMS}, /* ADDU[4X4] */
+{"addu",	"[32]", 	"d,v,t",	0x20000150, 0xfc0007ff, WR_1|RD_2|RD_3,		0,	I38,	0},
+{"addu",	"",		"t,r,I",	0,    (int) M_ADDU_I,	INSN_MACRO,		0,	I38,	0},
+{"extw",	"",		"d,s,t,+I",	0x2000001f, 0xfc00003f, WR_1|RD_2|RD_3,		0,	I38,	0},
+{"align",	"",		"mb,-i,mj,mz",	0x1000, 	0xfc00,	WR_1|RD_3,	INSN2_ALIAS,	I38,	0}, /* MOVE[16] */
+{"align",	"",		"d,-i,s,mz",	0x20000290, 0xffe007ff, WR_1|RD_3,	INSN2_ALIAS,	I38,	0}, /* MOVE[32] */
+{"align",	"",		"d,s,t,+v",	0x2000001f, 0xfc00003f, WR_1|RD_2|RD_3,	INSN2_ALIAS,	I38,	0}, /* EXTW */
+{"and", 	"[16]", 	"md,mk,ml",	0x5008,		0xfc0f,	MOD_1|RD_3,	INSN2_ALIAS,	I38,	0}, /* AND[16] */
+{"and", 	"[16]", 	"md,ml,mk",	0x5008,		0xfc0f,	MOD_1|RD_2,	INSN2_ALIAS,	I38,	0}, /* AND[16] */
+{"and", 	"[16]", 	"md,ml",	0x5008,		0xfc0f,	MOD_1|RD_2,		0,	I38,	0}, /* AND[16] */
+{"and", 	"[32]", 	"d,v,t",	0x20000250, 0xfc0007ff, WR_1|RD_2|RD_3,		0,	I38,	0},
+{"and", 	"[32]", 	"t,r,I",	0,    (int) M_AND_I,	INSN_MACRO,		0,	I38,	0},
+{"andi",	"[16]", 	"md,mc,mC",	0xf000,		0xfc00,	WR_1|RD_2,		0,	I38,	0}, /* ANDI[16] */
+{"andi",	"[32]", 	"t,r,g",	0x80002000, 0xfc00f000,	WR_1|RD_2,		0,	I38,	0},
+{"andi",	"",		"t,r,+6",	0x8000f000, 0xfc00f83f,	WR_1|RD_2,	INSN2_ALIAS,	0,	xNMS}, /* EXT */
+{"balc",	"[16]", 	"mD",		0x3800, 	0xfc00,		WR_31,		0,	I38,	0}, /* BALC[16] */
+{"balc",	"[32]", 	"+u",		0x2a000000, 0xfe000000,		WR_31,		0,	I38,	0},
+{"bal", 	"",		"mD",		0x3800, 	0xfc00,	WR_31,	INSN2_ALIAS|UBR|CTC,	I38,	0}, /* BALC[16] */
+{"bal", 	"",		"+u",		0x2a000000, 0xfe000000,	WR_31,	INSN2_ALIAS|UBR|CTC,	I38,	0}, /* BALC */
+{"balrsc",	"",		"+t,s", 	0x48008000, 0xfc00ffff,	WR_1|RD_2,		0,	I38,	0},
+{"balrsc",	"",		"s",		0x4be08000, 0xffe0ffff,	RD_1|WR_31,	INSN2_ALIAS,	I38,	0}, /* BALRSC */
+{"bbeqzc",	"",		"t,1,~",	0xc8040000, 0xfc1f0000,	RD_1,			0,	0,	xNMS},
+{"bbnezc",	"",		"t,1,~",	0xc8140000, 0xfc1f0000,	RD_1,			0,	0,	xNMS},
+{"bc",		"[16]", 	"mD",		0x1800, 	0xfc00,	0,			0,	I38,	0}, /* BC[16] */
+{"bc",		"[32]", 	"+u",		0x28000000, 0xfe000000,	0,			0,	I38,	0},
+{"b",		"",		"mD",		0x1800, 	0xfc00,	0,	INSN2_ALIAS|UBR|CTC,	I38,	0}, /* BC[16] */
+{"b",		"",		"+u",		0x28000000, 0xfe000000,	0,	INSN2_ALIAS|UBR|CTC,	I38,	0}, /* BC */
+{"beqzc",	"[16]", 	"md,mE",	0x9800, 	0xfc00,	RD_1,			0,	I38,	0}, /* BEQZC[16] */
+{"beqzc",	"[32]", 	"t,p",		0x88000000, 0xfc1fc000,	RD_1,		INSN2_ALIAS,	I38,	0}, /* BEQC */
+{"beqzc",	"[32]", 	"s,p",		0x88000000, 0xffe0c000,	RD_1,		INSN2_ALIAS,	I38,	0}, /* BEQC */
+{"beqz",	"",		"md,mE",	0x9800, 	0xfc00,	RD_1,	INSN2_ALIAS|CBR|CTC,	I38,	0}, /* BEQZC[16] */
+{"beqz",	"",		"t,p",		0x88000000, 0xfc1fc000,	RD_1,	INSN2_ALIAS|CBR|CTC,	I38,	0}, /* BEQC */
+{"beqz",	"",		"s,p",		0x88000000, 0xffe0c000,	RD_1,	INSN2_ALIAS|CBR|CTC,	I38,	0}, /* BEQC */
+{"beqc",	"[16]", 	"md,z,mE",	0x9800, 	0xfc00,	RD_1,		INSN2_ALIAS,	I38,	0}, /* BEQZC[16] */
+{"beqc",	"[16]", 	"z,md,mE",	0x9800, 	0xfc00,	RD_1,		INSN2_ALIAS,	I38,	0}, /* BEQZC[16] */
+{"beqc",	"[16]", 	"ml,mf,mF",	0xd800, 	0xfc00,	RD_1|RD_2,		0,	0,	xNMS}, /* BEQC[16], with rs3<rt3 && u[4:1]!=0 */
+{"beqc",	"[16]", 	"md,mg,mF",	0xd800, 	0xfc00,	RD_1|RD_2,	INSN2_ALIAS,	0,	xNMS}, /* BEQC[16], with operands commutated */
+{"beqc",	"[32]", 	"s,t,p",	0x88000000, 0xfc00c000,	RD_1|RD_2,		0,	I38,	0},
+{"beq", 	"",		"md,z,mE",	0x9800, 	0xfc00,	RD_1,	INSN2_ALIAS|CBR|CTC,	I38,	0}, /* BEQZC[16] */
+{"beq", 	"",		"z,md,mE",	0x9800, 	0xfc00,	RD_1,	INSN2_ALIAS|CBR|CTC,	I38,	0}, /* BEQZC[16] */
+{"beq", 	"",		"ml,mf,mF",	0xd800, 	0xfc00,	RD_1|RD_2, INSN2_ALIAS|CBR|CTC,	0,	xNMS}, /* BEQC[16], with rs3<rt3 && u[4:1]!=0 */
+{"beq", 	"",		"md,mg,mF",	0xd800, 	0xfc00,	RD_1|RD_2, INSN2_ALIAS|CBR|CTC,	0,	xNMS}, /* BEQC[16], with operands commutated */
+{"beq", 	"",		"s,t,p",	0x88000000, 0xfc00c000,	RD_1|RD_2, INSN2_ALIAS|CBR|CTC,	I38,	0}, /* BEQC */
+{"beq", 	"",		"s,I,p",	0,    (int) M_BEQ_I,	INSN_MACRO,		0,	I38,	0},
+{"beqic",	"",		"t,+9,~",	0xc8000000, 0xfc1c0000,	RD_1,			0,	I38,	0},
+{"blezc",	"",		"t,p",		0x88008000, 0xfc1fc000,	RD_1,		INSN2_ALIAS,	I38,	0}, /* BGEC $0, t */
+{"blez",	"",		"t,p",		0x88008000, 0xfc1fc000,	RD_1,	INSN2_ALIAS|CBR|CTC,	I38,	0}, /* BGEC $0, t */
+{"bgezc",	"",		"s,p",		0x88008000, 0xffe0c000,	RD_1,		INSN2_ALIAS,	I38,	0}, /* BGEC s, $0 */
+{"bgez",	"",		"s,p",		0x88008000, 0xffe0c000,	RD_1,	INSN2_ALIAS|CBR|CTC,	I38,	0}, /* BGEC s, $0 */
+{"bgec",	"",		"s,t,p",	0x88008000, 0xfc00c000,	RD_1|RD_2,		0,	I38,	0},
+{"bge", 	"",		"s,t,p",	0x88008000, 0xfc00c000,	RD_1|RD_2, INSN2_ALIAS|CBR|CTC,	I38,	0}, /* BGEC */
+{"bge", 	"",		"s,I,p",	0,    (int) M_BGE_I,	INSN_MACRO,		0,	I38,	0},
+{"bgt", 	"",		"s,t,p",	0,    (int) M_BGT,	INSN_MACRO,		0,	I38,	0},
+{"bgt", 	"",		"s,I,p",	0,    (int) M_BGT_I,	INSN_MACRO,		0,	I38,	0},
+{"bgtu",	"",		"s,t,p",	0,    (int) M_BGTU,	INSN_MACRO,		0,	I38,	0},
+{"bgtu",	"",		"s,I,p",	0,    (int) M_BGTU_I,	INSN_MACRO,		0,	I38,	0},
+{"ble", 	"",		"s,t,p",	0,    (int) M_BLE,	INSN_MACRO,		0,	I38,	0},
+{"ble", 	"",		"s,I,p",	0,    (int) M_BLE_I,	INSN_MACRO,		0,	I38,	0},
+{"bleu",	"",		"s,t,p",	0,    (int) M_BLEU,	INSN_MACRO,		0,	I38,	0},
+{"bleu",	"",		"s,I,p",	0,    (int) M_BLEU_I,	INSN_MACRO,		0,	I38,	0},
+{"bgezal",	"",		"s,p",		0,    (int) M_BGEZAL,	INSN_MACRO,		0,	I38,	0},
+{"bgeic",	"",		"t,+9,~",	0xc8080000, 0xfc1c0000,	RD_1,			0,	I38,	0},
+{"bgeuc",	"",		"s,t,p",	0x8800c000, 0xfc00c000,	RD_1|RD_2,		0,	I38,	0},
+{"bgeu",	"",		"s,t,p",	0x8800c000, 0xfc00c000,	RD_1|RD_2, INSN2_ALIAS|CBR|CTC,	I38,	0}, /* BGEUC */
+{"bgeu",	"",		"s,I,p",	0,    (int) M_BGEU_I,	INSN_MACRO,		0,	I38,	0},
+{"bgeiuc",	"",		"t,+9,~",	0xc80c0000, 0xfc1c0000,	RD_1,			0,	I38,	0},
+{"bitrevb",	"",		"t,r",		0x8000d247, 0xfc00ffff,	WR_1|RD_2,	INSN2_ALIAS,	0,	xNMS}, /* ROTX t,s,7,8,1 */
+{"bitrevh",	"",		"t,r",		0x8000d40f, 0xfc00ffff,	WR_1|RD_2,	INSN2_ALIAS,	0,	xNMS}, /* ROTX t,s,15,16 */
+{"bitrevw",	"",		"t,r",		0x8000d01f, 0xfc00ffff,	WR_1|RD_2,	INSN2_ALIAS,	0,	xNMS}, /* ROTX t,s,31,0*/
+{"bitswap",	"",		"t,r",		0x8000d247, 0xfc00ffff,	WR_1|RD_2,	INSN2_ALIAS,	0,	xNMS}, /* ROTX t,s,7,8,1*/
+{"bgtzc",	"",		"t,p",		0xa8008000, 0xfc1fc000,	RD_1,		INSN2_ALIAS,	I38,	0}, /* BLTC $0, t */
+{"bgtz",	"",		"t,p",		0xa8008000, 0xfc1fc000,	RD_1, 	INSN2_ALIAS|CBR|CTC,	I38,	0}, /* BLTC $0, t */
+{"bltzc",	"",		"s,p",		0xa8008000, 0xffe0c000,	RD_1,		INSN2_ALIAS,	I38,	0}, /* BLTC s, $0 */
+{"bltz",	"",		"s,p",		0xa8008000, 0xffe0c000,	RD_1,	INSN2_ALIAS|CBR|CTC,	I38,	0}, /* BLTC s, $0 */
+{"bltc",	"",		"s,t,p",	0xa8008000, 0xfc00c000,	RD_1|RD_2,		0,	I38,	0},
+{"blt", 	"",		"s,t,p",	0xa8008000, 0xfc00c000,	RD_1|RD_2, INSN2_ALIAS|CBR|CTC,	I38,	0}, /* BLTC */
+{"blt", 	"",		"s,I,p",	0,    (int) M_BLT_I,	INSN_MACRO,		0,	I38,	0},
+{"bltzal",	"",		"s,p",		0,    (int) M_BLTZAL,	INSN_MACRO,		0,	I38,	0},
+{"bltic",	"",		"t,+9,~",	0xc8180000, 0xfc1c0000,		RD_1,		0,	I38,	0},
+{"bltuc",	"",		"s,t,p",	0xa800c000, 0xfc00c000,	RD_1|RD_2,		0,	I38,	0},
+{"bltu",	"",		"s,t,p",	0xa800c000, 0xfc00c000,	RD_1|RD_2, INSN2_ALIAS|CBR|CTC,	I38,	0}, /* BLTUC */
+{"bltu",	"",		"s,I,p",	0,    (int) M_BLTU_I,	INSN_MACRO,		0,	I38,	0},
+{"bltiuc",	"",		"t,+9,~",	0xc81c0000, 0xfc1c0000, RD_1,			0,	I38,	0},
+{"bnezc",	"[16]", 	"md,mE",	0xb800, 	0xfc00, RD_1,			0,	I38,	0}, /* BNEZC[16] */
+{"bnezc",	"[32]", 	"t,p",		0xa8000000, 0xfc1fc000, RD_1,		INSN2_ALIAS,	I38,	0}, /* BNEC */
+{"bnezc",	"[32]", 	"s,p",		0xa8000000, 0xffe0c000, RD_1,		INSN2_ALIAS,	I38,	0}, /* BNEC */
+{"bnez",	"",		"md,mE",	0xb800, 	0xfc00, RD_1,	INSN2_ALIAS|CBR|CTC,	I38,	0}, /* BNEZC[16] */
+{"bnez",	"",		"t,p",		0xa8000000, 0xfc1fc000, RD_1,	INSN2_ALIAS|CBR|CTC,	I38,	0}, /* BNEC */
+{"bnez",	"",		"s,p",		0xa8000000, 0xffe0c000,	RD_1,		INSN2_ALIAS,	I38,	0}, /* BNEC */
+{"bnec",	"[16]", 	"md,z,mE",	0xb800, 	0xfc00,	RD_1,		INSN2_ALIAS,	I38,	0}, /* BNEZC[16] */
+{"bnec",	"[16]", 	"z,md,mE",	0xb800, 	0xfc00,	RD_2,		INSN2_ALIAS,	I38,	0}, /* BNEZC[16] */
+{"bnec",	"[16]", 	"ml,mh,mF",	0xd800, 	0xfc00,	RD_1|RD_2,		0,	0,	xNMS}, /* BNEC[16], with rs3>=rt3 && u[4:1]!=0 */
+{"bnec",	"[16]", 	"md,mi,mF",	0xd800, 	0xfc00,	RD_1|RD_2,	INSN2_ALIAS,	0,	xNMS}, /* BNEC[16], with operands commutated */
+{"bnec",	"[32]", 	"s,t,p",	0xa8000000, 0xfc00c000,	RD_1|RD_2,		0,	I38,	0},
+{"bne", 	"",		"md,z,mE",	0xb800, 	0xfc00,	RD_1, INSN2_ALIAS|CBR|CTC,	I38,	0}, /* BNEZC[16] */
+{"bne", 	"",		"z,md,mE",	0xb800, 	0xfc00,	RD_2, INSN2_ALIAS|CBR|CTC,	I38,	0}, /* BNEZC[16] */
+{"bne", 	"",		"ml,mh,mF",	0xd800, 	0xfc00,	RD_1|RD_2, INSN2_ALIAS|CBR|CTC,	0,	xNMS}, /* BNEC[16], with rs3>=rt3 && u[4:1]!=0 */
+{"bne", 	"",		"md,mi,mF",	0xd800, 	0xfc00,	RD_1|RD_2, INSN2_ALIAS|CBR|CTC,	0,	xNMS}, /* BNEC[16], with operands commutated */
+{"bne", 	"",		"s,t,p",	0xa8000000, 0xfc00c000,	RD_1|RD_2, INSN2_ALIAS|CBR|CTC,	I38,	0}, /* BNEC */
+{"bne", 	"",		"s,I,p",	0,    (int) M_BNE_I,	INSN_MACRO,		0,	I38,	0},
+{"bneic",	"",		"t,+9,~",	0xc8100000, 0xfc1c0000,	RD_1,			0,	I38,	0},
+{"brsc",	"",		"s",		0x48008000, 0xffe0ffff,	RD_1,			0,	I38,	0},
+{"byterevh",	"",		"t,r",		0x8000d608, 0xfc00ffff,	WR_1|RD_2,	INSN2_ALIAS,	0,	xNMS}, /* ROTX t,s,8,24 */
+{"byterevw",	"",		"t,r",		0x8000d218, 0xfc00ffff,	WR_1|RD_2,	INSN2_ALIAS,	0,	xNMS}, /* ROTX t,s,24,8 */
+{"cache",	"",		"k,+j(b)",	0xa4003900, 0xfc007f00,	RD_3,			0,	I38,	0},
+{"cache",	"",		"k,A(c)",	0,    (int) M_CACHE_AC,	INSN_MACRO,		0,	I38,	0},
+{"cfc1",	"",		"t,G",		0xa000103b, 0xfc00ffff,	WR_1|RD_2,	INSN2_ALIAS,	I38,	0},
+{"cfc1",	"",		"t,S",		0xa000103b, 0xfc00ffff,	WR_1|RD_2,		0,	I38,	0},
+{"cftc1",	"",		"t,G",		0x20001e30, 0xfc00ffff,	WR_1|RD_2,	INSN2_ALIAS,	0,	MT32}, /* MFTR */
+{"cftc1",	"",		"t,S",		0x20001e30, 0xfc00ffff,	WR_1|RD_2,	INSN2_ALIAS,	0,	MT32}, /* MFTR */
+{"cftc2",	"",		"t,G",		0x20002e30, 0xfc00ffff,	WR_1|RD_2,	INSN2_ALIAS,	0,	MT32}, /* MFTR */
+{"clo", 	"",		"t,s",		0x20004b3f, 0xfc00ffff,	WR_1|RD_2,		0,	0,	xNMS},
+{"clz", 	"",		"t,s",		0x20005b3f, 0xfc00ffff,	WR_1|RD_2,		0,	0,	xNMS},
+{"cop2_1",	"",		"C",		0x20000002, 0xfc000007,		0,		0,	I38,	0},
+{"ctc1",	"",		"t,G",		0xa000183b, 0xfc00ffff,	RD_1|WR_2,	INSN2_ALIAS,	I38,	0},
+{"ctc1",	"",		"t,S",		0xa000183b, 0xfc00ffff,	RD_1|WR_2,		0,	I38,	0},
+{"cttc1",	"",		"t,G",		0x20001e70, 0xfc00ffff,	RD_1|WR_2,	INSN2_ALIAS,	0,	MT32}, /* MTTR */
+{"cttc1",	"",		"t,S",		0x20001e70, 0xfc00ffff,	RD_1|WR_2,	INSN2_ALIAS,	0,	MT32}, /* MTTR */
+{"cttc2",	"",		"t,G",		0x20002e70, 0xfc00ffff,	RD_1|WR_2,	INSN2_ALIAS,	0,	MT32}, /* MTTR */
+{"dabs",	"",		"d,v",		0,	  (int) M_DABS,	INSN_MACRO,		0,	I38,	0},
+{"daddiu",	"[neg]",	"t,r,h",	0x80008000, 0xfc00f000,	WR_1|RD_2,		0,	I38,	0}, /* DADDIU[NEG] */
+{"deret",	"",		"",		0x2000e37f, 0xffffffff,		0,		0,	I38,	0},
+{"di",		"",		"",		0x2000477f, 0xffffffff,	0,		INSN2_ALIAS,	I38,	0},
+{"di",		"",		"w",		0x2000477f, 0xfc1fffff,	WR_1,			0,	I38,	0},
+{"div", 	"",		"d,v,t",	0x20000118, 0xfc0007ff, WR_1|RD_2|RD_3,		0,	I38,	0},
+{"div", 	"",		"d,v,I",	0,    (int) M_DIV_I,	INSN_MACRO,		0,	I38,	0},
+{"divu",	"",		"d,v,t",	0x20000198, 0xfc0007ff, WR_1|RD_2|RD_3,		0,	I38,	0},
+{"divu",	"",		"d,v,I",	0,    (int) M_DIVU_I,	INSN_MACRO,		0,	I38,	0},
+{"dmt", 	"",		"",		0x20010ab0, 0xffffffff,	0,		INSN2_ALIAS,	0,	MT32},
+{"dmt", 	"",		"t",		0x20010ab0, 0xfc1fffff,	WR_1,			0,	0,	MT32},
+{"dvpe",	"",		"",		0x20000ab0, 0xffffffff,	0,		INSN2_ALIAS,	0,	MT32}, /* DVPE */
+{"dvpe",	"",		"t",		0x20000ab0, 0xfc1fffff,	WR_1,			0,	0,	MT32},
+{"ehb", 	"",		"",		0x8000c003, 0xffffffff,	0,			0,	I38,	0},
+{"ei",		"",		"",		0x2000577f, 0xffffffff,	0,		INSN2_ALIAS,	I38,	0},
+{"ei",		"",		"t",		0x2000577f, 0xfc1fffff,	WR_1,			0,	I38,	0},
+{"emt", 	"",		"",		0x20010eb0, 0xffffffff,	0,		INSN2_ALIAS,	0,	MT32},
+{"emt", 	"",		"t",		0x20010eb0, 0xfc1fffff, WR_1,			0,	0,	MT32},
+{"eret",	"",		"",		0x2000f37f, 0xffffffff,	0,			0,	I38,	0},
+{"eretnc",	"",		"",		0x2001f37f, 0xffffffff,	0,			0,	I38,	0},
+{"evpe",	"",		"",		0x20000eb0, 0xffffffff,	0,		INSN2_ALIAS,	0,	MT32}, /* EVPE */
+{"evpe",	"",		"t",		0x20000eb0, 0xfc1fffff,	WR_1,			0,	0,	MT32},
+{"evp", 	"",		"-a",		0x20000790, 0xffe0ffff,	0,		INSN2_ALIAS,	I38,	0}, /* EVP */
+{"evp", 	"",		"t,-a",		0x20000790, 0xfc00ffff,	WR_1,			0,	I38,	0},
+{"fork",	"",		"d,s,t",	0x20000228, 0xfc0007ff,	WR_1|RD_2|RD_3,		0,	0,	MT32},
+{"ins", 	"",		"t,r,+A,+B",	0x8000e000, 0xfc00f820,	WR_1|RD_2,		0,	0,	xNMS},
+{"ins", 	"",		"t,r,+A,+B",	0,    (int) M_INS,	INSN_MACRO,		0,	I38,	0},
+{"j",		"",		"mp",		0xd800, 	0xfc1f,	RD_1,	INSN2_ALIAS|UBR|CTC,	I38,	0},
+{"j",		"",		"+u",		0x28000000, 0xfe000000,	0, 	INSN2_ALIAS|UBR|CTC,	I38,	0}, /* BC */
+{"j",		"",		"s",		0x48000000, 0xffe0ffff,	RD_1,	INSN2_ALIAS|UBR|CTC,	I38,	0}, /* JALRC */
+{"jrc.hb",	"",		"s",		0x48001000, 0xffe0ffff,	RD_1,		INSN2_ALIAS,	I38,	0}, /* JALRC.HB */
+{"jr.hb",	"",		"s",		0x48001000, 0xffe0ffff,	RD_1,	INSN2_ALIAS|UBR|CTC,	I38,	0}, /* JALRC.HB */
+{"jalrc.hb",	"",		"s",		0x4be01000, 0xffe0ffff,	RD_1,		INSN2_ALIAS,	I38,	0}, /* JALRC.HB */
+{"jalrc.hb",	"",		"t,s",		0x48001000, 0xfc00ffff,	WR_1|RD_2,		0,	I38,	0},
+{"jalr.hb",	"",		"s",		0x4be01000, 0xffe0ffff,	RD_1,	INSN2_ALIAS|UBR|CTC,	I38,	0}, /* JALRC.HB */
+{"jalr.hb",	"",		"t,s",		0x48001000, 0xfc00ffff,	WR_1|RD_2, INSN2_ALIAS|UBR|CTC,	I38,	0}, /* JALRC.HB */
+/* SVR4 PIC code requires special handling for jal, so it must be a macro.  */
+{"jal", 	"",		"my,mp",	0xd810, 	0xfc1f,	WR_31|RD_1, INSN2_ALIAS|UBR|CTC, I38,	0}, /* JALRC[16] */
+{"jal", 	"",		"mp",		0xd810, 	0xfc1f,	WR_31|RD_1, INSN2_ALIAS|UBR|CTC, I38,	0}, /* JALRC[16] */
+{"jal", 	"",		"s",		0x4be00000, 0xffe0ffff,	RD_1,	INSN2_ALIAS|UBR|CTC,	I38,	0}, /* JALRC */
+{"jal", 	"",		"t,s",		0x48000000, 0xfc00ffff,	WR_1|RD_2, INSN2_ALIAS|UBR|CTC, I38,	0}, /* JALRC */
+{"jal", 	"",		"A",		0,    (int) M_JAL_A,	INSN_MACRO,		0,	I38,	0},
+{"jal", 	"",		"+u",		0x2a000000, 0xfe000000,	WR_31,	INSN2_ALIAS|UBR|CTC,	I38,	0}, /* BALC */
+{"lb",		"[16]", 	"md,mL(ml)",	0x5c00, 	0xfc0c,	WR_1|RD_3,		0,	I38,	0}, /* LB[16] */
+{"lb",		"[gp]", 	"t,+1(ma)",	0x44000000, 0xfc1c0000,	WR_1|RD_3,		0,	I38,	0}, /* LB[GP] */
+{"lb",		"[u12]",	"t,o(b)",	0x84000000, 0xfc00f000,	WR_1|RD_3,		0,	I38,	0}, /* LB[U12] */
+{"lb",		"[s9]", 	"t,+j(b)",	0xa4000000, 0xfc007f00,	WR_1|RD_3,		0,	I38,	0}, /* LB[S9] */
+{"lb",		"",		"t,A(c)",	0,	(int) M_LB_AC,	INSN_MACRO,		0,	I38,	0},
+{"lbu", 	"[16]", 	"md,mL(ml)",	0x5c08, 	0xfc0c,	WR_1|RD_3,		0,	I38,	0}, /* LBU[16] */
+{"lbu", 	"[gp]", 	"t,+1(ma)",	0x44080000, 0xfc1c0000,	WR_1|RD_3,		0,	I38,	0}, /* LBU[GP] */
+{"lbu", 	"[u12]",	"t,o(b)",	0x84002000, 0xfc00f000,	WR_1|RD_3,		0,	I38,	0}, /* LBU[U12] */
+{"lbu", 	"[s9]", 	"t,+j(b)",	0xa4001000, 0xfc007f00,	WR_1|RD_3,		0,	I38,	0}, /* LBU[S9] */
+{"lbu", 	"",		"t,A(c)",	0,	(int) M_LBU_AC,	INSN_MACRO,		0,	I38,	0},
+{"lbux",	"",		"d,s(t)",	0x20000107, 0xfc0007ff, WR_1|RD_2|RD_3,		0,	I38,	0},
+{"lbx", 	"",		"d,s(t)",	0x20000007, 0xfc0007ff, WR_1|RD_2|RD_3,		0,	I38,	0},
+{"ld",		"",		"t,A(c)",	0,	(int) M_LD_AC,	INSN_MACRO,		0,	I38,	0},
+{"lh",		"[16]", 	"md,mH(ml)",	0x7c00, 	0xfc09,	WR_1|RD_3,		0,	I38,	0}, /* LH[16] */
+{"lh",		"[gp]", 	"t,+3(ma)",	0x44100000, 0xfc1c0001,	WR_1|RD_3,		0,	I38,	0}, /* LH[GP] */
+{"lh",		"[u12]",	 "t,o(b)",	0x84004000, 0xfc00f000,	WR_1|RD_3,		0,	I38,	0}, /* LH[U12] */
+{"lh",		"[s9]", 	"t,+j(b)",	0xa4002000, 0xfc007f00,	WR_1|RD_3,		0,	I38,	0}, /* LH[S9] */
+{"lh",		"",		"t,A(c)",	0,	(int) M_LH_AC,	INSN_MACRO,		0,	I38,	0},
+{"lhu", 	"[16]", 	"md,mH(ml)",	0x7c08,		0xfc09,	WR_1|RD_3,		0,	I38,	0}, /* LHU[16] */
+{"lhu", 	"[gp]", 	"t,+3(ma)",	0x44100001, 0xfc1c0001,	WR_1|RD_3,		0,	I38,	0}, /* LHU[GP] */
+{"lhu", 	"[u12]",	 "t,o(b)",	0x84006000, 0xfc00f000,	WR_1|RD_3,		0,	I38,	0}, /* LHU[U12] */
+{"lhu", 	"[s9]", 	"t,+j(b)",	0xa4003000, 0xfc007f00,	WR_1|RD_3,		0,	I38,	0}, /* LHU[S9] */
+{"lhu", 	"",		"t,A(c)",	0,	(int) M_LHU_AC,	INSN_MACRO,		0,	I38,	0},
+{"lhux",	"",		"d,s(t)",	0x20000307, 0xfc0007ff, WR_1|RD_2|RD_3,		0,	I38,	0},
+{"lhuxs",	"",		"d,s(t)",	0x20000347, 0xfc0007ff, WR_1|RD_2|RD_3,		0,	I38,	0},
+{"lhx", 	"",		"d,s(t)",	0x20000207, 0xfc0007ff, WR_1|RD_2|RD_3,		0,	I38,	0},
+{"lhxs",	"",		"d,s(t)",	0x20000247, 0xfc0007ff, WR_1|RD_2|RD_3,		0,	I38,	0},
+{"li.d",	"",		"t,F",		0,	(int) M_LI_D,	INSN_MACRO,		0,	I38,	0},
+{"li.s",	"",		"t,f",		0,	(int) M_LI_S,	INSN_MACRO,		0,	I38,	0},
+{"ll",		"",		"t,+p(b)",	0xa4005100, 0xfc007f03,	WR_1|RD_3,		0,	I38,	0},
+{"ll",		"",		"t,A(c)",	0,	(int) M_LL_AC,	INSN_MACRO,		0,	I38,	0},
+{"llwp",	"",		"t,e,(b)",	0xa4005101, 0xfc00ff07, WR_1|WR_2|RD_3,		0,	0,	xNMS},
+{"lsa", 	"",		"d,v,t,+w",	0x2000000f, 0xfc0001ff, WR_1|RD_2|RD_3,		0,	I38,	0},
+{"lw",		"[16]", 	"md,mJ(ml)",	0x1400, 	0xfc00,	WR_1|RD_3,		0,	I38,	0}, /* LW[16] */
+{"lw",		"[4x4]",	"mu,mN(mv)",	0x7400, 	0xfc00,	WR_1|RD_3,		0,	0,	xNMS}, /* LW[4X4] */
+{"lw",		"[sp]", 	"mp,mR(ms)",	0x3400, 	0xfc00,	WR_1|RD_3,		0,	I38,	0}, /* LW[SP] */
+{"lw",		"[gp16]",	"md,mO(ma)",	0x5400, 	0xfc00,	WR_1|RD_3,		0,	I38,	0}, /* LW[GP16] */
+{"lw",		"[gp]", 	"t,.(ma)",	0x40000002, 0xfc000003,	WR_1|RD_3,		0,	I38,	0}, /* LW[GP] */
+{"lw",		"[gp16]",	"md,mA(ma)",	0x5400, 	0xfc00,	WR_1|RD_3,		0,	I38,	0}, /* LW[GP16] */
+{"lw",		"[u12]",	"t,o(b)",	0x84008000, 0xfc00f000,	WR_1|RD_3,		0,	I38,	0}, /* LW[U12] */
+{"lw",		"[s9]", 	"t,+j(b)",	0xa4004000, 0xfc007f00,	WR_1|RD_3,		0,	I38,	0}, /* LW[S9] */
+{"lw",		"",		"t,A(c)",	0,	(int) M_LW_AC,	INSN_MACRO,		0,	I38,	0},
+{"lwm", 	"",		"t,+j(b),|",	0xa4000400, 0xfc000f00,	WR_1|RD_3,		0,	0,	xNMS}, /* LWM */
+{"lwpc",	"[48]", 	"mp,+S",	0x600b, 	0xfc1f,	WR_1,			0,	0,	xNMS}, /* LWPC[48] */
+{"lwx", 	"",		"d,s(t)",	0x20000407, 0xfc0007ff, WR_1|RD_2|RD_3,		0,	I38,	0},
+{"lwxs",	"[16]", 	"me,ml(md)",	0x5001, 	0xfc01, WR_1|RD_2|RD_3,		0,	I38,	0}, /* LWXS[16] */
+{"lwxs",	"[32]", 	"d,s(t)",	0x20000447, 0xfc0007ff, WR_1|RD_2|RD_3,		0,	I38,	0},
+{"mfc0",	"",		"t,O",		0x20000030, 0xfc0007ff,	WR_1,		INSN2_ALIAS,	I38,	0}, /* MFC0 with named register */
+{"mfc0",	"",		"t,P,J",	0x20000030, 0xfc0007ff,	WR_1,		INSN2_ALIAS,	I38,	0}, /* MFC0 with named register & select */
+{"mfc0",	"",		"t,G,J",	0x20000030, 0xfc0007ff,	WR_1,			0,	I38,	0},
+{"mfhc0",	"",		"t,O",		0x20000038, 0xfc0007ff,	WR_1,		INSN2_ALIAS,	I38,	0}, /* MFHC0 with named register */
+{"mfhc0",	"",		"t,P,J",	0x20000038, 0xfc0007ff,	WR_1,		INSN2_ALIAS,	I38,	0}, /* MFHC0 with named register & select*/
+{"mfhc0",	"",		"t,G,J",	0x20000038, 0xfc0007ff,	WR_1,			0,	I38,	0},
+{"mftc0",	"",		"t,O",		0x20000230, 0xfc0007ff,	WR_1,		INSN2_ALIAS,	0,	MT32}, /* MFTR with named register */
+{"mftc0",	"",		"t,P,J",	0x20000230, 0xfc0007ff,	WR_1,		INSN2_ALIAS,	0,	MT32}, /* MFTR with named register & select */
+{"mfthc0",	"",		"t,O",		0x20000238, 0xfc0007ff,	WR_1,		INSN2_ALIAS,	0,	MT32}, /* MFTR with named register */
+{"mfthc0",	"",		"t,P,J",	0x20000238, 0xfc0007ff,	WR_1,		INSN2_ALIAS,	0,	MT32}, /* MFTR with named register & select*/
+{"mftc1",	"",		"t,S",		0x20001630, 0xfc00ffff,	WR_1|RD_2|FP_S,	INSN2_ALIAS,	0,	MT32}, /* MFTR */
+{"mftc1",	"",		"t,G",		0x20001630, 0xfc00ffff,	WR_1|RD_2|FP_S,	INSN2_ALIAS,	0,	MT32}, /* MFTR */
+{"mftc2",	"",		"t,G",		0x20002630, 0xfc00ffff,	WR_1,		INSN2_ALIAS,	0,	MT32}, /* MFTR */
+{"mftdsp",	"",		"t",		0x20100e30, 0xfc1fffff,	WR_1,		INSN2_ALIAS,	0,	MT32}, /* MFTR */
+{"mftgpr",	"",		"t,s",		0x20000630, 0xfc00ffff,	WR_1|RD_2,	INSN2_ALIAS,	0,	MT32}, /* MFTR */
+{"mfthc1",	"",		"t,S",		0x20001638, 0xfc00ffff,	WR_1|RD_2|FP_D,	INSN2_ALIAS,	0,	MT32}, /* MFTR */
+{"mfthc1",	"",		"t,G",		0x20001638, 0xfc00ffff,	WR_1|RD_2|FP_D,	INSN2_ALIAS,	0,	MT32}, /* MFTR */
+{"mfthc2",	"",		"t,G",		0x20002638, 0xfc00ffff,	WR_1,		INSN2_ALIAS,	0,	MT32}, /* MFTR */
+{"mfthi",	"",		"t",		0x20010e30, 0xfc1fffff,	WR_1|RD_a,	INSN2_ALIAS,	0,	MT32}, /* MFTR */
+{"mfthi",	"",		"t,*",		0x20010e30, 0xfc13ffff,	WR_1|RD_a,	INSN2_ALIAS,	0,	MT32}, /* MFTR */
+{"mftlo",	"",		"t",		0x20000e30, 0xfc1fffff,	WR_1|RD_a,	INSN2_ALIAS,	0,	MT32}, /* MFTR */
+{"mftlo",	"",		"t,*",		0x20000e30, 0xfc13ffff,	WR_1|RD_a,	INSN2_ALIAS,	0,	MT32}, /* MFTR */
+{"mftr",	"",		"t,s,!,H,$",	0x20000230, 0xfc0003f7,	WR_1,			0,	0,	MT32},
+{"mod", 	"",		"d,v,t",	0x20000158, 0xfc0007ff, WR_1|RD_2|RD_3,		0,	I38,	0},
+{"mod", 	"",		"d,v,I",	0,	(int) M_MOD_I,	INSN_MACRO,		0,	I38,	0},
+{"modu",	"",		"d,v,t",	0x200001d8, 0xfc0007ff, WR_1|RD_2|RD_3,		0,	I38,	0},
+{"modu",	"",		"d,v,I",	0,	(int) M_MODU_I,	INSN_MACRO,		0,	I38,	0},
+{"move.balc",	"",		"+7,+5,+r",	0x08000000, 0xfc000000,	WR_1|RD_2,		0,	0,	xNMS},
+{"move.bal",	"",		"+7,+5,+r",	0x08000000, 0xfc000000,	WR_1|RD_2,	INSN2_ALIAS|UBR|CTC, 0,	xNMS}, /* MOVE.BALC */
+{"movep",	"",		"mq,mx,mw",	0xbc00, 	0xfc00,	WR_1|RD_2|RD_3,		0,	0,	xNMS}, /* MOVEP */
+{"movep",	"",		"mr,mw,mx",	0xbc00, 	0xfc00,	WR_1|RD_2|RD_3,	INSN2_ALIAS,	0,	xNMS}, /* MOVEP */
+{"movep",	"[rev]",	"mv,mu,mq",	0xfc00, 	0xfc00,	WR_1|WR_2|RD_3,		0,	0,	xNMS}, /* MOVEP[REV] */
+{"movep",	"[rev]",	"mu,mv,mr",	0xfc00, 	0xfc00,	WR_1|WR_2|RD_3,	INSN2_ALIAS,	0,	xNMS}, /* MOVEP[REV] */
+{"movn",	"",		"d,v,t",	0x20000610, 0xfc0007ff, WR_1|RD_2|RD_3,		0,	I38,	0},
+{"movz",	"",		"d,v,t",	0x20000210, 0xfc0007ff, WR_1|RD_2|RD_3,		0,	I38,	0},
+{"mtc0",	"",		"t,O",		0x20000070, 0xfc0007ff,	RD_1,		INSN2_ALIAS,	I38,	0}, /* MTC0 with named register */
+{"mtc0",	"",		"t,P,J",	0x20000070, 0xfc0007ff,	RD_1,		INSN2_ALIAS,	I38,	0}, /* MTCO with named register & select */
+{"mtc0",	"",		"t,G,J",	0x20000070, 0xfc0007ff,	RD_1,			0,	I38,	0},
+{"mthc0",	"",		"t,O",		0x20000078, 0xfc0007ff,	RD_1,		INSN2_ALIAS,	I38,	0}, /* MTHC0 with named register */
+{"mthc0",	"",		"t,P,J",	0x20000078, 0xfc0007ff,	RD_1,		INSN2_ALIAS,	I38,	0}, /* MTHC0 with named register & select */
+{"mthc0",	"",		"t,G,J",	0x20000078, 0xfc0007ff,	RD_1,			0,	I38,	0},
+{"mttc0",	"",		"t,O",		0x20000270, 0xfc0007ff,	RD_1,		INSN2_ALIAS,	0,	MT32}, /* MTTR with named register */
+{"mttc0",	"",		"t,P,J",	0x20000270, 0xfc0007ff,	RD_1,		INSN2_ALIAS,	0,	MT32}, /* MTTR with named register & select */
+{"mtthc0",	"",		"t,O",		0x20000278, 0xfc0007ff,	RD_1,		INSN2_ALIAS,	0,	MT32}, /* MTTR with named register*/
+{"mtthc0",	"",		"t,P,J",	0x20000278, 0xfc0007ff,	RD_1,		INSN2_ALIAS,	0,	MT32}, /* MTTR with named register & select */
+{"mttc1",	"",		"t,S",		0x20001670, 0xfc00ffff,	RD_1|WR_2|FP_S,	INSN2_ALIAS,	0,	MT32}, /* MTTR */
+{"mttc1",	"",		"t,G",		0x20001670, 0xfc00ffff,	RD_1|WR_2|FP_S,	INSN2_ALIAS,	0,	MT32}, /* MTTR */
+{"mttc2",	"",		"t,G",		0x20002670, 0xfc00ffff,	RD_1,		INSN2_ALIAS,	0,	MT32}, /* MTTR */
+{"mttgpr",	"",		"t,s",		0x20000670, 0xfc00ffff,	RD_1|WR_2,	INSN2_ALIAS,	0,	MT32}, /* MTTR */
+{"mtthc1",	"",		"t,S",		0x20001678, 0xfc00ffff,	RD_1|WR_2|FP_D,	INSN2_ALIAS,	0,	MT32}, /* MTTR */
+{"mtthc1",	"",		"t,G",		0x20001678, 0xfc00ffff,	RD_1|WR_2|FP_D,	INSN2_ALIAS,	0,	MT32}, /* MTTR */
+{"mtthc2",	"",		"t,G",		0x20002678, 0xfc00ffff,	RD_1,		INSN2_ALIAS,	0,	MT32}, /* MTTR */
+{"mtthi",	"",		"t",		0x20010e70, 0xfc1fffff,	RD_1|WR_a,	INSN2_ALIAS,	0,	MT32}, /* MTTR */
+{"mtthi",	"",		"t,*",		0x20010e70, 0xfc13ffff,	RD_1|WR_a,	INSN2_ALIAS,	0,	MT32}, /* MTTR */
+{"mttlo",	"",		"t",		0x20000e70, 0xfc1fffff,	RD_1|WR_a,	INSN2_ALIAS,	0,	MT32}, /* MTTR */
+{"mttlo",	"",		"t,*",		0x20000e70, 0xfc13ffff,	RD_1|WR_a,	INSN2_ALIAS,	0,	MT32}, /* MTTR */
+{"mttdsp",	"",		"t",		0x20100e70, 0xfc1fffff,	RD_1,		INSN2_ALIAS,	0,	MT32}, /* MTTR */
+{"mttr",	"",		"t,s,!,H,$",	0x20000270, 0xfc0003f7,	RD_1,			0,	0,	MT32},
+{"muh", 	"",		"d,v,t",	0x20000058, 0xfc0007ff, WR_1|RD_2|RD_3,		0,	I38,	0},
+{"muhu",	"",		"d,v,t",	0x200000d8, 0xfc0007ff, WR_1|RD_2|RD_3,		0,	I38,	0},
+{"mul", 	"[4x4]",	"mu,mt,mv",	0x3c08, 	0xfd08,	MOD_1|RD_3,		0,	0,	xNMS}, /* MUL[4X4] */
+{"mul", 	"[4x4]",	"mu,mv,mk",	0x3c08, 	0xfd08,	MOD_1|RD_2,	INSN2_ALIAS,	0,	xNMS}, /* MUL[4X4] */
+{"mul", 	"[32]", 	"d,v,t",	0x20000018, 0xfc0007ff, WR_1|RD_2|RD_3,		0,	I38,	0},
+{"mul", 	"",		"d,v,I",	0,	(int) M_MUL_I,	INSN_MACRO,		0,	I38,	0},
+{"mulu",	"",		"d,v,t",	0x20000098, 0xfc0007ff, WR_1|RD_2|RD_3,		0,	I38,	0},
+{"neg", 	"",		"d,w",		0x20000190, 0xfc1f07ff, WR_1|RD_2,	INSN2_ALIAS,	0,	xNMS}, /* SUB */
+{"negu",	"",		"d,w",		0x200001d0, 0xfc1f07ff, WR_1|RD_2,	INSN2_ALIAS,	I38,	0}, /* SUBU */
+{"not", 	"[16]", 	"md,ml",	0x5000, 	0xfc0f,	WR_1|RD_2,		0,	I38,	0}, /* NOT[16] */
+{"not", 	"[32]", 	"d,v",		0x200002d0, 0xffe007ff, WR_1|RD_2,	INSN2_ALIAS,	I38,	0}, /* NOR */
+{"nor", 	"",		"d,v,t",	0x200002d0, 0xfc0007ff, WR_1|RD_2|RD_3,		0,	I38,	0},
+{"nor", 	"",		"t,r,I",	0,    (int) M_NOR_I,	INSN_MACRO,		0,	I38,	0},
+{"or",		"[16]", 	"md,mk,ml",	0x500c, 	0xfc0f,	WR_1|RD_3,	INSN2_ALIAS,	I38,	0}, /* OR[16] */
+{"or",		"[16]", 	"md,ml,mk",	0x500c, 	0xfc0f,	WR_1|RD_2,	INSN2_ALIAS,	I38,	0}, /* OR[16] */
+{"or",		"[16]", 	"md,ml",	0x500c, 	0xfc0f,	WR_1|RD_2,		0,	I38,	0}, /* OR[16] */
+{"or",		"[32]", 	"d,v,t",	0x20000290, 0xfc0007ff, WR_1|RD_2|RD_3,		0,	I38,	0},
+{"or",		"",		"t,r,I",	0,	(int) M_OR_I,	INSN_MACRO,		0,	I38,	0},
+{"ori", 	"",		"t,r,g",	0x80000000, 0xfc00f000,	WR_1|RD_2,		0,	I38,	0},
+{"pause",	"",		"",		0x8000c005, 0xffffffff,	0,			0,	I38,	0},
+{"pref",	"[u12]",	"k,o(b)",	0x84003000, 0xfc00f000,	RD_3,			0,	I38,	0}, /* PREF[U12] */
+{"pref",	"[s9]", 	"k,+j(b)",	0xa4001800, 0xfc007f00,	RD_3,			0,	I38,	0}, /* PREF[S9], preceded by SYNCI[S9] */
+{"pref",	"",		"k,A(c)",	0,     (int) M_PREF_AC,	INSN_MACRO,		0,	I38,	0},
+{"rdhwr",	"",		"t,K",		0x200001c0, 0xfc00ffff,	WR_1|RD_2,	INSN2_ALIAS,	0,	xNMS},
+{"rdpgpr",	"",		"t,s",		0x2000e17f, 0xfc00ffff,	WR_1|RD_2,		0,	I38,	0},
+{"rem", 	"",		"d,v,t",	0x20000158, 0xfc0007ff, WR_1|RD_2|RD_3,	INSN2_ALIAS,	I38,	0}, /* MOD */
+{"rem", 	"",		"d,v,I",	0,	(int) M_REM_3I,	INSN_MACRO,		0,	I38,	0},
+{"remu",	"",		"d,v,t",	0x200001d8, 0xfc0007ff, WR_1|RD_2|RD_3,	INSN2_ALIAS,	I38,	0}, /* MODU */
+{"restore",	"[32]", 	"+N,n", 	0x80003002, 0xfc00f003,	0,			0,	I38,	0},
+{"restore.jrc", "[16]", 	"mG",		0x1d00, 	0xff0f,	0,			0,	I38,	0}, /* RESTORE.JRC[16] */
+{"restore.jrc", "[16]", 	"mG,mn",	0x1d00, 	0xfd00,	0,			0,	I38,	0}, /* RESTORE.JRC[16], preceded by RESTORE[16] */
+{"restore.jrc", "[32]", 	"+N",		0x80003003, 0xfffff007,	0,			0,	I38,	0}, /* RESTORE.JRC[32] */
+{"restore.jrc", "[32]", 	"+N,n", 	0x80003003, 0xfc00f003,	0,			0,	I38,	0},
+{"jraddiusp",	"",		"mG",		0x1d00, 	0xff0f,	0,		INSN2_ALIAS,	I38,	0}, /* RESTORE.JRC[16] */
+{"jraddiusp",	"",		"+N",		0x80003003, 0xfffff007,	0,		INSN2_ALIAS,	I38,	0}, /* RESTORE.JRC[32] */
+{"jraddiusp",	"",		"I",		0,   (int) M_JRADDIUSP,	INSN_MACRO,		0,	I38,	0},
+{"rol", 	"",		"d,v,t",	0,	(int) M_ROL,	INSN_MACRO,		0,	I38,	0},
+{"rol", 	"",		"d,v,I",	0,	(int) M_ROL_I,	INSN_MACRO,		0,	I38,	0},
+{"rotrv",	"",		"d,s,t",	0x200000d0, 0xfc0007ff, WR_1|RD_2|RD_3,		0,	I38,	0},
+{"rotr",	"",		"t,r,<",	0x8000c0c0, 0xfc00ffe0,	WR_1|RD_2,		0,	I38,	0},
+{"rotr",	"",		"d,v,t",	0x200000d0, 0xfc0007ff, WR_1|RD_2|RD_3,	INSN2_ALIAS,	I38,	0}, /* ROTRV */
+{"ror", 	"",		"t,r,<",	0x8000c0c0, 0xfc00ffe0,	WR_1|RD_2,	INSN2_ALIAS,	I38,	0}, /* ROTR */
+{"ror", 	"",		"d,v,t",	0x200000d0, 0xfc0007ff, WR_1|RD_2|RD_3,	INSN2_ALIAS,	I38,	0}, /* ROTRV */
+{"ror", 	"",		"d,v,I",	0,    (int) M_ROR_I,	INSN_MACRO,		0,	I38,	0},
+{"rorv",	"",		"t,r,<",	0x8000c0c0, 0xfc00ffe0,	WR_1|RD_2,	INSN2_ALIAS,	I38,	0}, /* ROTR */
+{"rorv",	"",		"d,v,t",	0x200000d0, 0xfc0007ff, WR_1|RD_2|RD_3,	INSN2_ALIAS,	I38,	0}, /* ROTRV */
+{"rotl",	"",		"d,v,t",	0,    (int) M_ROL,	INSN_MACRO,		0,	I38,	0},
+{"rotl",	"",		"d,v,I",	0,    (int) M_ROL_I,	INSN_MACRO,		0,	I38,	0},
+{"wsbh",	"",		"t,r",		0x8000d608, 0xfc00ffff,	WR_1|RD_2,	INSN2_ALIAS,	0,	xNMS}, /* ROTX t,s,8,24*/
+{"rotx",	"",		"t,r,<,+*",	0x8000d000, 0xfc00f860, WR_1|RD_2,	INSN2_ALIAS,	0,	xNMS},
+{"rotx",	"",		"t,r,<,+*,+|",	0x8000d000, 0xfc00f820, WR_1|RD_2,		0,	0,	xNMS},
+{"save",	"[16]", 	"mG",		0x1c00, 	0xff0f,	0,			0,	I38,	0}, /* SAVE[16] */
+{"save",	"[16]", 	"mG,mn",	0x1c00, 	0xfd00,	0,			0,	I38,	0}, /* SAVE[16] */
+{"save",	"[32]", 	"+N,n",		0x80003000, 0xfc00f003,	0,			0,	I38,	0},
+{"sb",		"[16]", 	"mm,mL(ml)",	0x5c04, 	0xfc0c,	RD_1|RD_3,		0,	I38,	0}, /* SB[16] */
+{"sb",		"[gp]", 	"t,+1(ma)",	0x44040000, 0xfc1c0000,	RD_1|RD_3,		0,	I38,	0}, /* SB[GP] */
+{"sb",		"[u12]",	"t,o(b)",	0x84001000, 0xfc00f000,	RD_1|RD_3,		0,	I38,	0}, /* SB[U12] */
+{"sb",		"[s9]", 	"t,+j(b)",	0xa4000800, 0xfc007f00,	RD_1|RD_3,		0,	I38,	0}, /* SB[S9] */
+{"sb",		"",		"t,A(c)",	0,	(int) M_SB_AC,	INSN_MACRO,		0,	I38,	0},
+{"sbx", 	"",		"d,s(t)",	0x20000087, 0xfc0007ff, RD_1|RD_2|RD_3,		0,	0,	xNMS},
+{"sc",		"",		"t,+p(b)",	0xa4005900, 0xfc007f03,	MOD_1|RD_3,		0,	I38,	0},
+{"sc",		"",		"t,A(c)",	0,	(int) M_SC_AC,	INSN_MACRO,		0,	I38,	0},
+{"scwp",	"",		"t,e,(b)",	0xa4005901, 0xfc00ff07,	MOD_1|WR_2|RD_3,		0,	0,	xNMS},
+{"sd",		"",		"t,A(c)",	0,	(int) M_SD_AC,	INSN_MACRO,		0,	I38,	0},
+{"seb", 	"", 		"t,r",		0x20000008, 0xfc00ffff,	WR_1|RD_2,		0,	0,	xNMS},
+{"seh", 	"", 		"t,r",		0x20000048, 0xfc00ffff,	WR_1|RD_2,		0,	I38,	0},
+{"seqi",	"",		"t,r,i",	0x80006000, 0xfc00f000, WR_1|RD_2,		0,	I38,	0},
+{"seq", 	"", 		"d,v,t",	0,	(int) M_SEQ,	INSN_MACRO,		0,	I38,	0},
+{"seq", 	"", 		"d,v,I",	0,	(int) M_SEQ_I,	INSN_MACRO,		0,	I38,	0},
+{"sge", 	"", 		"d,v,t",	0,	(int) M_SGE,	INSN_MACRO,		0,	I38,	0},
+{"sge", 	"", 		"d,v,I",	0,	(int) M_SGE_I,	INSN_MACRO,		0,	I38,	0},
+{"sgeu",	"",		"d,v,t",	0,	(int) M_SGEU,	INSN_MACRO,		0,	I38,	0},
+{"sgeu",	"",		"d,v,I",	0,     (int) M_SGEU_I,	INSN_MACRO,		0,	I38,	0},
+{"sgt", 	"", 		"d,v,t",	0,	(int) M_SGT,	INSN_MACRO,		0,	I38,	0},
+{"sgt", 	"", 		"d,v,I",	0,	(int) M_SGT_I,	INSN_MACRO,		0,	I38,	0},
+{"sgtu",	"",		"d,v,t",	0,	(int) M_SGTU,	INSN_MACRO,		0,	I38,	0},
+{"sgtu",	"",		"d,v,I",	0,     (int) M_SGTU_I,	INSN_MACRO,		0,	I38,	0},
+{"sh",		"[16]", 	"mm,mH(ml)",	0x7c01, 	0xfc09,	RD_1|RD_3,		0,	I38,	0}, /* SH[16] */
+{"sh",		"[gp]", 	"t,+3(ma)",	0x44140000, 0xfc1c0001,	RD_1|RD_3,		0,	I38,	0}, /* SH[GP] */
+{"sh",		"[u12]",	 "t,o(b)",	0x84005000, 0xfc00f000,	RD_1|RD_3,		0,	I38,	0}, /* SH[U12] */
+{"sh",		"[s9]", 	"t,+j(b)",	0xa4002800, 0xfc007f00,	RD_1|RD_3,		0,	I38,	0}, /* SH[S9] */
+{"sh",		"",		"t,A(c)", 	0,	(int) M_SH_AC,	INSN_MACRO,	0,	I38,	0},
+{"shx", 	"",		"d,s(t)",	0x20000287, 0xfc0007ff, RD_1|RD_2|RD_3,		0,	0,	xNMS},
+{"shxs",	"",		"d,s(t)",	0x200002c7, 0xfc0007ff, RD_1|RD_2|RD_3,		0,	0,	xNMS},
+{"sync",	"",		"",		0x8000c006, 0xffffffff,		0,		0,	I38,	0},
+{"sync",	"",		"+i",		0x8000c006, 0xffe0ffff,		0,		0,	I38,	0},
+{"sle", 	"",		"d,v,t",	0,	(int) M_SLE,	INSN_MACRO,		0,	I38,	0},
+{"sle", 	"",		"d,v,I",	0,	(int) M_SLE_I,	INSN_MACRO,		0,	I38,	0},
+{"sleu",	"",		"d,v,t",	0,	(int) M_SLEU,	INSN_MACRO,		0,	I38,	0},
+{"sleu",	"",		"d,v,I",	0,	(int) M_SLEU_I,	INSN_MACRO,		0,	I38,	0},
+{"sllv",	"",		"d,s,t",	0x20000010, 0xfc0007ff, WR_1|RD_2|RD_3,		0,	I38,	0},
+{"sll", 	"[16]", 	"md,mc,mM",	0x3000,		0xfc08,	WR_1|RD_2,		0,	I38,	0}, /* SLL[16] */
+{"sll", 	"[32]", 	"t,r,<",	0x8000c000, 0xfc00ffe0,	WR_1|RD_2,		0,	I38,	0}, /* preceded by EHB, PAUSE, SYNC */
+{"sll", 	"[32]", 	"d,v,t",	0x20000010, 0xfc0007ff, WR_1|RD_2|RD_3,	INSN2_ALIAS,	I38,	0}, /* SLLV */
+{"slt", 	"",		"d,v,t",	0x20000350, 0xfc0007ff, WR_1|RD_2|RD_3,		0,	I38,	0},
+{"slt", 	"",		"d,v,I",	0,	(int) M_SLT_I,	INSN_MACRO,		0,	I38,	0},
+{"slti",	"",		"t,r,i",	0x80004000, 0xfc00f000,	WR_1|RD_2,		0,	I38,	0},
+{"sltiu",	"",		"t,r,i",	0x80005000, 0xfc00f000,	WR_1|RD_2,		0,	I38,	0},
+{"sltu",	"",		"d,v,t",	0x20000390, 0xfc0007ff, WR_1|RD_2|RD_3,		0,	I38,	0}, /* preceded by DVP */
+{"sltu",	"",		"d,v,I",	0,	(int) M_SLTU_I,	INSN_MACRO,		0,	I38,	0},
+{"sne", 	"",		"d,v,t",	0,	(int) M_SNE,	INSN_MACRO,		0,	I38,	0},
+{"sne", 	"",		"d,v,I",	0,	(int) M_SNE_I,	INSN_MACRO,		0,	I38,	0},
+{"sov", 	"",		"d,v,t",	0x200003d0, 0xfc0007ff, WR_1|RD_2|RD_3,		0,	I38,	0},
+{"srav",	"",		"d,s,t",	0x20000090, 0xfc0007ff, WR_1|RD_2|RD_3,		0,	I38,	0},
+{"sra", 	"",		"t,r,<",	0x8000c080, 0xfc00ffe0,	WR_1|RD_2,		0,	I38,	0},
+{"sra", 	"",		"d,v,t",	0x20000090, 0xfc0007ff, WR_1|RD_2|RD_3,	INSN2_ALIAS,	I38,	0}, /* SRAV */
+{"srlv",	"",		"d,s,t",	0x20000050, 0xfc0007ff, WR_1|RD_2|RD_3,		0,	I38,	0},
+{"srl", 	"[16]", 	"md,mc,mM",	0x3008, 	0xfc08,	WR_1|RD_2,		0,	I38,	0}, /* SRL[16] */
+{"srl", 	"[32]", 	"t,r,<",	0x8000c040, 0xfc00ffe0,	WR_1|RD_2,		0,	I38,	0},
+{"srl", 	"[32]", 	"d,v,t",	0x20000050, 0xfc0007ff, WR_1|RD_2|RD_3,	INSN2_ALIAS,	I38,	0}, /* SRLV */
+{"sub", 	"",		"d,v,t",	0x20000190, 0xfc0007ff, WR_1|RD_2|RD_3,		0,	0,	xNMS},
+{"sub", 	"",		"t,r,I",	0,	(int) M_SUB_I,	INSN_MACRO,		0,	0,	xNMS},
+{"subu",	"[16]", 	"me,mc,md",	0xb001, 	0xfc01, WR_1|RD_2|RD_3,		0,	I38,	0}, /* SUBU[16] */
+{"subu",	"[32]", 	"d,v,t",	0x200001d0, 0xfc0007ff, WR_1|RD_2|RD_3,		0,	I38,	0},
+{"subu",	"",		"d,v,I",	0,	(int) M_SUBU_I,	INSN_MACRO,		0,	I38,	0},
+{"sw",		"[16]", 	"mm,mJ(ml)",	0x9400, 	0xfc00,	RD_1|RD_3,		0,	I38,	0}, /* SW[16] */
+{"sw",		"[sp]", 	"mp,mR(ms)",	0xb400, 	0xfc00,	RD_1|RD_3,		0,	I38,	0}, /* SW[SP] */
+{"sw",		"[4x4]",	"mw,mN(mv)",	0xf400, 	0xfc00,	RD_1|RD_3,		0,	0,	xNMS}, /* SW[4X4] */
+{"sw",		"[gp16]",	"mm,mO(ma)",	0xd400, 	0xfc00,	RD_1|RD_3,		0,	I38,	0}, /* SW[GP16] */
+{"sw",		"[gp]", 	"t,.(ma)",	0x40000003, 0xfc000003,	RD_1|RD_3,		0,	I38,	0}, /* SW[GP] */
+{"sw",		"[gp16]",	"mm,mA(ma)",	0xd400, 	0xfc00,	RD_1|RD_3,		0,	I38,	0}, /* SW[GP16] */
+{"sw",		"[u12]",	"t,o(b)",	0x84009000, 0xfc00f000,	RD_1|RD_3,		0,	I38,	0}, /* SW[U12] */
+{"sw",		"[s9]", 	"t,+j(b)",	0xa4004800, 0xfc007f00,	RD_1|RD_3,		0,	I38,	0}, /* SW[S9] */
+{"sw",		"",		"t,A(c)",	0,	 (int) M_SW_AC,	INSN_MACRO,		0,	I38,	0},
+{"swm", 	"",		"t,+j(b),|",	0xa4000c00, 0xfc000f00,	RD_1|RD_3,		0,	0,	xNMS}, /* SWM */
+{"swpc",	"[48]", 	"mp,+S",	0x600f, 	0xfc1f,	WR_1,			0,	0,	xNMS}, /* SWPC[48] */
+{"swx", 	"",		"d,s(t)",	0x20000487, 0xfc0007ff, RD_1|RD_2|RD_3,		0,	0,	xNMS},
+{"swxs",	"",		"d,s(t)",	0x200004c7, 0xfc0007ff, RD_1|RD_2|RD_3,		0,	0,	xNMS},
+{"syscall",	"[16]", 	"",		0x1008, 	0xffff,		0,	INSN2_ALIAS,	I38,	0}, /* SYSCALL[16] */
+{"syscall",	"[16]", 	"mP",		0x1008, 	0xfffc,		0,		0,	I38,	0}, /* SYSCALL[16] */
+{"syscall",	"[32]", 	"",		0x00080000, 0xffffffff,		0,	INSN2_ALIAS,	I38,	0},
+{"syscall",	"[32]", 	"+M",		0x00080000, 0xfffc0000,		0,		0,	I38,	0},
+{"teq", 	"",		"s,t",		0x20000000, 0xfc00ffff,	RD_1|RD_2,	INSN2_ALIAS,	0,	xNMS}, /* TEQ */
+{"teq", 	"",		"s,t,^",	0x20000000, 0xfc0007ff,	RD_1|RD_2,		0,	0,	xNMS}, /* TEQ */
+{"teq", 	"",		"s,I",		0, 	 (int) M_TEQ_I,	INSN_MACRO,		0,	0,	xNMS},
+{"tne", 	"",		"s,t",		0x20000400, 0xfc00ffff,	RD_1|RD_2,	INSN2_ALIAS,	0,	xNMS}, /* TNE */
+{"tne", 	"",		"s,t,^",	0x20000400, 0xfc0007ff,	RD_1|RD_2,		0,	0,	xNMS}, /* TNE */
+{"tne", 	"",		"s,I",		0, 	 (int) M_TNE_I,	INSN_MACRO,		0,	0,	xNMS},
+{"ualh",	"",		"t,+j(b)",	0xa4002100, 0xfc007f00,	WR_1|RD_3,		0,	0,	xNMS},
+{"ualw",	"",		"t,+j(b)",	0xa4001500, 0xfc007f00,	WR_1|RD_3,	INSN2_ALIAS,	0,	xNMS}, /* UALWM */
+{"ualwm",	"",		"t,+j(b),|",	0xa4000500, 0xfc000f00,	WR_1|RD_3,		0,	0,	xNMS}, /* UALWM */
+{"uash",	"",		"t,+j(b)",	0xa4002900, 0xfc007f00,	RD_1|RD_3,		0,	0,	xNMS},
+{"uasw",	"",		"t,+j(b)",	0xa4001d00, 0xfc007f00,	RD_1|RD_3,	INSN2_ALIAS,	0,	xNMS}, /* UASWM */
+{"uaswm",	"",		"t,+j(b),|",	0xa4000d00, 0xfc000f00,	RD_1|RD_3,		0,	0,	xNMS}, /* UASWM */
+{"uld", 	"",		"t,A(c)",	0,	(int) M_ULD_AC,	INSN_MACRO,		0,	0,	xNMS},
+{"ulh", 	"",		"t,A(c)",	0,	(int) M_ULH_AC,	INSN_MACRO,		0,	0,	xNMS},
+{"ulw", 	"",		"t,A(c)",	0,	(int) M_ULW_AC,	INSN_MACRO,		0,	0,	xNMS},
+{"usd", 	"",		"t,A(c)",	0,	(int) M_USD_AC,	INSN_MACRO,		0,	0,	xNMS},
+{"ush", 	"",		"t,A(c)",	0,	(int) M_USH_AC,	INSN_MACRO,		0,	0,	xNMS},
+{"usw", 	"",		"t,A(c)",	0,	(int) M_USW_AC,	INSN_MACRO,		0,	0,	xNMS},
+{"wait",	"",		"",		0x2000c37f, 0xffffffff,		0,	INSN2_ALIAS,	I38,	0},
+{"wait",	"",		"+L",		0x2000c37f, 0xfc00ffff,		0,		0,	I38,	0},
+{"wrpgpr",	"",		"t,r",		0x2000f17f, 0xfc00ffff,	WR_1|RD_2,		0,	I38,	0},
+{"xor", 	"[16]", 	"md,mk,ml",	0x5004, 	0xfc0f,	WR_1|RD_3,	INSN2_ALIAS,	I38,	0}, /* XOR[16] */
+{"xor", 	"[16]", 	"md,ml,mk",	0x5004, 	0xfc0f,	WR_1|RD_2,	INSN2_ALIAS,	I38,	0}, /* XOR[16] */
+{"xor", 	"[16]", 	"md,ml",	0x5004, 	0xfc0f,	WR_1|RD_2,		0,	I38,	0}, /* XOR[16] */
+{"xor", 	"[32]", 	"d,v,t",	0x20000310, 0xfc0007ff, WR_1|RD_2|RD_3,		0,	I38,	0},
+{"xor", 	"",		"t,r,I",	0,	(int) M_XOR_I,	INSN_MACRO,		0,	I38,	0},
+{"xori",	"",		"t,r,g",	0x80001000, 0xfc00f000,	WR_1|RD_2,		0,	I38,	0},
+{"yield",	"",		"s",		0x20000268, 0xffe0ffff,	RD_1,		INSN2_ALIAS,	0,	MT32},
+{"yield",	"",		"t,s",		0x20000268, 0xfc00ffff,	WR_1|RD_2,		0,	0,	MT32},
+};
+
+const int bfd_nanomips_num_opcodes =
+  ((sizeof nanomips_opcodes) / (sizeof (nanomips_opcodes[0])));
-- 
2.39.5
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.