This is the mail archive of the binutils@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [PATCH] S12Z: opcodes: Separate the decoding of operations from their display.


Ping!

On Sat, Dec 08, 2018 at 11:08:30AM +0100, John Darrington wrote:
     This change adds an abstraction layer between the decoding of machine
     operations and their disassembled textual representation.  This allows
     the decoding routines to be re-used for other purposes (at the expense)
     of slightly slower running time.
     
     ChangeLog: opcodes/
     
        * s12z-opc.c: New file.
        * s12z-opc.h: New file.
        * s12z-dis.c: Removed all code not directly related to display
          of instructions.  Used the interface provided by the new files
          instead.
        * Makefile.am (TARGET_LIBOPCODES_CFILES) Add s12z-opc.c.
        * Makefile.in: regenerate.
        * configure.ac (bfd_s12z_arch): Correct the dependencies.
        * configure: regenerate.
     ---
      opcodes/Makefile.am  |    1 +
      opcodes/Makefile.in  |    2 +
      opcodes/configure    |    2 +-
      opcodes/configure.ac |    2 +-
      opcodes/s12z-dis.c   | 2828 +++++---------------------------------------------
      opcodes/s12z-opc.c   | 2701 +++++++++++++++++++++++++++++++++++++++++++++++
      opcodes/s12z-opc.h   |  267 +++++
      7 files changed, 3241 insertions(+), 2562 deletions(-)
      create mode 100644 opcodes/s12z-opc.c
      create mode 100644 opcodes/s12z-opc.h
     
     diff --git a/opcodes/Makefile.am b/opcodes/Makefile.am
     index cf26ddf4bc..ccffbb58c9 100644
     --- a/opcodes/Makefile.am
     +++ b/opcodes/Makefile.am
     @@ -176,6 +176,7 @@ TARGET_LIBOPCODES_CFILES = \
      	m68k-dis.c \
      	m68k-opc.c \
      	s12z-dis.c \
     +	s12z-opc.c \
      	mcore-dis.c \
      	mep-asm.c \
      	mep-desc.c \
     diff --git a/opcodes/configure.ac b/opcodes/configure.ac
     index 7384684bc0..d7b1e2ec88 100644
     --- a/opcodes/configure.ac
     +++ b/opcodes/configure.ac
     @@ -287,7 +287,7 @@ if test x${all_targets} = xfalse ; then
      	bfd_m68hc12_arch)	ta="$ta m68hc11-dis.lo m68hc11-opc.lo" ;;
      	bfd_m9s12x_arch)	ta="$ta m68hc11-dis.lo m68hc11-opc.lo" ;;
      	bfd_m9s12xg_arch)	ta="$ta m68hc11-dis.lo m68hc11-opc.lo" ;;
     -	bfd_s12z_arch)	ta="$ta s12z-dis.lo m68hc11-opc.lo" ;;
     +	bfd_s12z_arch)		ta="$ta s12z-dis.lo s12z-opc.lo" ;;
      	bfd_m68k_arch)		ta="$ta m68k-dis.lo m68k-opc.lo" ;;
      	bfd_mcore_arch)		ta="$ta mcore-dis.lo" ;;
      	bfd_mep_arch)		ta="$ta mep-asm.lo mep-desc.lo mep-dis.lo mep-ibld.lo mep-opc.lo" using_cgen=yes ;;
     diff --git a/opcodes/s12z-dis.c b/opcodes/s12z-dis.c
     index 719f172bcc..9c32209d0d 100644
     --- a/opcodes/s12z-dis.c
     +++ b/opcodes/s12z-dis.c
     @@ -29,266 +29,51 @@
      #include "bfd.h"
      #include "dis-asm.h"
      
     -
      #include "disassemble.h"
      
     -static int
     -read_memory (bfd_vma memaddr, bfd_byte* buffer, int size,
     -             struct disassemble_info* info)
     -{
     -  int status = (*info->read_memory_func) (memaddr, buffer, size, info);
     -  if (status != 0)
     -    {
     -      (*info->memory_error_func) (status, memaddr, info);
     -      return -1;
     -    }
     -  return 0;
     -}
     -
     -typedef int (* insn_bytes_f) (bfd_vma memaddr,
     -			      struct disassemble_info* info);
     -
     -typedef void (*operands_f) (bfd_vma memaddr, struct disassemble_info* info);
     -
     -enum OPR_MODE
     -  {
     -    OPR_IMMe4,
     -    OPR_REG,
     -    OPR_OFXYS,
     -    OPR_XY_PRE_INC,
     -    OPR_XY_POST_INC,
     -    OPR_XY_PRE_DEC,
     -    OPR_XY_POST_DEC,
     -    OPR_S_PRE_DEC,
     -    OPR_S_POST_INC,
     -    OPR_REG_DIRECT,
     -    OPR_REG_INDIRECT,
     -    OPR_IDX_DIRECT,
     -    OPR_IDX_INDIRECT,
     -    OPR_EXT1,
     -    OPR_IDX2_REG,
     -    OPR_IDX3_DIRECT,
     -    OPR_IDX3_INDIRECT,
     -
     -    OPR_EXT18,
     -    OPR_IDX3_DIRECT_REG,
     -    OPR_EXT3_DIRECT,
     -    OPR_EXT3_INDIRECT
     -  };
     -
     -struct opr_pb
     -{
     -  uint8_t mask;
     -  uint8_t value;
     -  int n_operands;
     -  enum OPR_MODE mode;
     -};
     -
     -static const  struct opr_pb opr_pb[] = {
     -  {0xF0, 0x70, 1, OPR_IMMe4},
     -  {0xF8, 0xB8, 1, OPR_REG},
     -  {0xC0, 0x40, 1, OPR_OFXYS},
     -  {0xEF, 0xE3, 1, OPR_XY_PRE_INC},
     -  {0xEF, 0xE7, 1, OPR_XY_POST_INC},
     -  {0xEF, 0xC3, 1, OPR_XY_PRE_DEC},
     -  {0xEF, 0xC7, 1, OPR_XY_POST_DEC},
     -  {0xFF, 0xFB, 1, OPR_S_PRE_DEC},
     -  {0xFF, 0xFF, 1, OPR_S_POST_INC},
     -  {0xC8, 0x88, 1, OPR_REG_DIRECT},
     -  {0xE8, 0xC8, 1, OPR_REG_INDIRECT},
     -
     -  {0xCE, 0xC0, 2, OPR_IDX_DIRECT},
     -  {0xCE, 0xC4, 2, OPR_IDX_INDIRECT},
     -  {0xC0, 0x00, 2, OPR_EXT1},
     -
     -  {0xC8, 0x80, 3, OPR_IDX2_REG},
     -  {0xFA, 0xF8, 3, OPR_EXT18},
     -
     -  {0xCF, 0xC2, 4, OPR_IDX3_DIRECT},
     -  {0xCF, 0xC6, 4, OPR_IDX3_INDIRECT},
     -
     -  {0xF8, 0xE8, 4, OPR_IDX3_DIRECT_REG},
     -  {0xFF, 0xFA, 4, OPR_EXT3_DIRECT},
     -  {0xFF, 0xFE, 4, OPR_EXT3_INDIRECT},
     -};
     -
     -
     -/* Return the number of bytes in a OPR operand, including the XB postbyte.
     -   It does not include any preceeding opcodes. */
     -static int
     -opr_n_bytes (bfd_vma memaddr, struct disassemble_info* info)
     -{
     -  bfd_byte xb;
     -  int status = read_memory (memaddr, &xb, 1, info);
     -  if (status < 0)
     -    return status;
     -
     -  size_t i;
     -  for (i = 0; i < sizeof (opr_pb) / sizeof (opr_pb[0]); ++i)
     -    {
     -      const struct opr_pb *pb = opr_pb + i;
     -      if ((xb & pb->mask) == pb->value)
     -	{
     -	  return pb->n_operands;
     -	}
     -    }
     -
     -  return 1;
     -}
     -
     -static int
     -opr_n_bytes_p1 (bfd_vma memaddr, struct disassemble_info* info)
     -{
     -  return 1 + opr_n_bytes (memaddr, info);
     -}
     -
     -static int
     -opr_n_bytes2 (bfd_vma memaddr, struct disassemble_info* info)
     -{
     -  int s = opr_n_bytes (memaddr, info);
     -  s += opr_n_bytes (memaddr + s, info);
     -  return s + 1;
     -}
     -
     -enum BB_MODE
     -  {
     -    BB_REG_REG_REG,
     -    BB_REG_REG_IMM,
     -    BB_REG_OPR_REG,
     -    BB_OPR_REG_REG,
     -    BB_REG_OPR_IMM,
     -    BB_OPR_REG_IMM
     -  };
     +#include "s12z-opc.h"
      
     -struct opr_bb
     +struct mem_read_abstraction
      {
     -  uint8_t mask;
     -  uint8_t value;
     -  int n_operands;
     -  bool opr;
     -  enum BB_MODE mode;
     +  struct mem_read_abstraction_base base;
     +  bfd_vma memaddr;
     +  struct disassemble_info* info;
      };
      
     -static const struct opr_bb bb_modes[] =
     -  {
     -    {0x60, 0x00, 2, false, BB_REG_REG_REG},
     -    {0x60, 0x20, 3, false, BB_REG_REG_IMM},
     -    {0x70, 0x40, 2, true,  BB_REG_OPR_REG},
     -    {0x70, 0x50, 2, true,  BB_OPR_REG_REG},
     -    {0x70, 0x60, 3, true,  BB_REG_OPR_IMM},
     -    {0x70, 0x70, 3, true,  BB_OPR_REG_IMM}
     -  };
     -
     -static int
     -bfextins_n_bytes (bfd_vma memaddr, struct disassemble_info* info)
     -{
     -  bfd_byte bb;
     -  int status = read_memory (memaddr, &bb, 1, info);
     -  if (status < 0)
     -    return status;
     -
     -  size_t i;
     -  const struct opr_bb *bbs = 0;
     -  for (i = 0; i < sizeof (bb_modes) / sizeof (bb_modes[0]); ++i)
     -    {
     -      bbs = bb_modes + i;
     -      if ((bb & bbs->mask) == bbs->value)
     -	{
     -	  break;
     -	}
     -    }
     -
     -  int n = bbs->n_operands;
     -  if (bbs->opr)
     -    n += opr_n_bytes (memaddr + n - 1, info);
     -
     -  return n;
     -}
     -
     -static int
     -single (bfd_vma memaddr ATTRIBUTE_UNUSED,
     -	struct disassemble_info* info ATTRIBUTE_UNUSED)
     -{
     -  return 1;
     -}
     -
     -static int
     -two (bfd_vma memaddr ATTRIBUTE_UNUSED,
     -     struct disassemble_info* info ATTRIBUTE_UNUSED)
     -{
     -  return 2;
     -}
     -
     -static int
     -three (bfd_vma memaddr ATTRIBUTE_UNUSED,
     -       struct disassemble_info* info ATTRIBUTE_UNUSED)
     -{
     -  return 3;
     -}
     -
     -static int
     -four (bfd_vma memaddr ATTRIBUTE_UNUSED,
     -      struct disassemble_info* info ATTRIBUTE_UNUSED)
     +static void
     +advance (struct mem_read_abstraction_base *b)
      {
     -  return 4;
     +  struct mem_read_abstraction *mra = (struct mem_read_abstraction *) b;
     +  mra->memaddr ++;
      }
      
     -static int
     -five (bfd_vma memaddr ATTRIBUTE_UNUSED,
     -      struct disassemble_info* info ATTRIBUTE_UNUSED)
     +static bfd_vma
     +posn (struct mem_read_abstraction_base *b)
      {
     -  return 5;
     +  struct mem_read_abstraction *mra = (struct mem_read_abstraction *) b;
     +  return mra->memaddr;
      }
      
      static int
     -pcrel_15bit (bfd_vma memaddr, struct disassemble_info* info)
     +abstract_read_memory (struct mem_read_abstraction_base *b,
     +		      int offset,
     +		      size_t n, bfd_byte *bytes)
      {
     -  bfd_byte byte;
     -  int status = read_memory (memaddr, &byte, 1, info);
     -  if (status < 0)
     -    return status;
     -  return (byte & 0x80) ? 3 : 2;
     -}
     +  struct mem_read_abstraction *mra = (struct mem_read_abstraction *) b;
      
     +  int status =
     +    (*mra->info->read_memory_func) (mra->memaddr + offset,
     +				    bytes, n, mra->info);
      
     -
     -
     -static void
     -operand_separator (struct disassemble_info *info)
     -{
     -  if ((info->flags & 0x2))
     -    {
     -      (*info->fprintf_func) (info->stream, ", ");
     -    }
     -  else
     +  if (status != 0)
          {
     -      (*info->fprintf_func) (info->stream, " ");
     +      (*mra->info->memory_error_func) (status, mra->memaddr, mra->info);
     +      return -1;
          }
     -
     -  info->flags |= 0x2;
     -}
     -
     -
     -
     -static void
     -imm1 (bfd_vma memaddr, struct disassemble_info* info)
     -{
     -  bfd_byte byte;
     -  int status = read_memory (memaddr, &byte, 1, info);
     -  if (status < 0)
     -    return;
     -
     -  operand_separator (info);
     -  (*info->fprintf_func) (info->stream, "#%d", byte);
     -}
     -
     -static void
     -trap_decode (bfd_vma memaddr, struct disassemble_info* info)
     -{
     -  imm1 (memaddr - 1, info);
     +  return 0;
      }
      
     -
     +/* Start of disassembly file.  */
      const struct reg registers[S12Z_N_REGISTERS] =
        {
          {"d2", 2},
     @@ -311,58 +96,128 @@ const struct reg registers[S12Z_N_REGISTERS] =
          {"ccw", 2}
        };
      
     -static char *
     -xys_from_postbyte (uint8_t postbyte)
     -{
     -  char *reg = "?";
     -  switch ((postbyte & 0x30) >> 4)
     -    {
     -    case 0:
     -      reg = "x";
     -      break;
     -    case 1:
     -      reg = "y";
     -      break;
     -    case 2:
     -      reg = "s";
     -      break;
     -    default:
     -      reg = "?";
     -      break;
     -    }
     -  return reg;
     -}
     +static const char *mnemonics[] =
     +  {
     +    "!!invalid!!",
     +    "psh",
     +    "pul",
     +    "tbne", "tbeq", "tbpl", "tbmi", "tbgt", "tble",
     +    "dbne", "dbeq", "dbpl", "dbmi", "dbgt", "dble",
     +    "sex",
     +    "exg",
     +    "lsl", "lsr",
     +    "asl", "asr",
     +    "rol", "ror",
     +    "bfins", "bfext",
     +
     +    "trap",
     +
     +    "ld",
     +    "st",
     +    "cmp",
     +
     +    "stop",
     +    "wai",
     +    "sys",
     +
     +    "minu",
     +    "mins",
     +    "maxu",
     +    "maxs",
     +
     +    "abs",
     +    "adc",
     +    "bit",
     +    "sbc",
     +    "rti",
     +    "clb",
     +    "eor",
     +
     +    "sat",
     +
     +    "nop",
     +    "bgnd",
     +    "brclr",
     +    "brset",
     +    "rts",
     +    "lea",
     +    "mov",
     +
     +    "bra",
     +    "bsr",
     +    "bhi",
     +    "bls",
     +    "bcc",
     +    "bcs",
     +    "bne",
     +    "beq",
     +    "bvc",
     +    "bvs",
     +    "bpl",
     +    "bmi",
     +    "bge",
     +    "blt",
     +    "bgt",
     +    "ble",
     +    "inc",
     +    "clr",
     +    "dec",
     +
     +    "add",
     +    "sub",
     +    "and",
     +    "or",
     +
     +    "tfr",
     +    "jmp",
     +    "jsr",
     +    "com",
     +    "andcc",
     +    "neg",
     +    "orcc",
     +    "bclr",
     +    "bset",
     +    "btgl",
     +    "swi",
     +
     +    "mulu",
     +    "divu",
     +    "modu",
     +    "macu",
     +    "qmulu",
     +
     +    "muls",
     +    "divs",
     +    "mods",
     +    "macs",
     +    "qmuls",
     +
     +    NULL
     +  };
     +
      
     -static char *
     -xysp_from_postbyte (uint8_t postbyte)
     +static void
     +operand_separator (struct disassemble_info *info)
      {
     -  char *reg = "?";
     -  switch ((postbyte & 0x30) >> 4)
     -    {
     -    case 0:
     -      reg = "x";
     -      break;
     -    case 1:
     -      reg = "y";
     -      break;
     -    case 2:
     -      reg = "s";
     -      break;
     -    default:
     -      reg = "p";
     -      break;
     -    }
     -  return reg;
     +  if ((info->flags & 0x2))
     +    (*info->fprintf_func) (info->stream, ",");
     +
     +  (*info->fprintf_func) (info->stream, " ");
     +
     +  info->flags |= 0x2;
      }
      
     -/* Render the symbol name whose value is ADDR or the adddress itself if there is
     -   no symbol. */
     +/* Render the symbol name whose value is ADDR + BASE or the adddress itself if
     +   there is no symbol.  If BASE is non zero, then the a PC relative adddress is
     +   assumend (ie BASE is the value in the PC.  */
      static void
     -decode_possible_symbol (bfd_vma addr, struct disassemble_info *info)
     +decode_possible_symbol (bfd_vma addr, bfd_vma base,
     +                        struct disassemble_info *info, bool relative)
      {
     -  if (!info->symbol_at_address_func (addr, info))
     +  const char *fmt = relative  ? "*%+" BFD_VMA_FMT "d" : "%" BFD_VMA_FMT "d";
     +  if (!info->symbol_at_address_func (addr + base, info))
          {
     -      (*info->fprintf_func) (info->stream, "%" BFD_VMA_FMT "d", addr);
     +      (*info->fprintf_func) (info->stream, fmt, addr);
          }
        else
          {
     @@ -371,7 +226,7 @@ decode_possible_symbol (bfd_vma addr, struct disassemble_info *info)
            for (j = 0; j < info->symtab_size; ++j)
      	{
      	  sym = info->symtab[j];
     -	  if (bfd_asymbol_value (sym) == addr)
     +	  if (bfd_asymbol_value (sym) == addr + base)
      	    {
      	      break;
      	    }
     @@ -379,2305 +234,158 @@ decode_possible_symbol (bfd_vma addr, struct disassemble_info *info)
            if (j < info->symtab_size)
      	(*info->fprintf_func) (info->stream, "%s", bfd_asymbol_name (sym));
            else
     -        (*info->fprintf_func) (info->stream, "%" BFD_VMA_FMT "d", addr);
     +        (*info->fprintf_func) (info->stream, fmt, addr);
          }
      }
      
     -static void ld_18bit_decode (bfd_vma memaddr, struct disassemble_info* info);
      
     +/* Emit the disassembled text for OPR */
      static void
     -ext24_decode (bfd_vma memaddr, struct disassemble_info* info)
     +opr_emit_disassembly (const struct operand *opr,
     +		      struct disassemble_info *info)
      {
     -  uint8_t buffer[3];
     -  int status = read_memory (memaddr, buffer, 3, info);
     -  if (status < 0)
     -    return;
     -
     -  int i;
     -  uint32_t addr = 0;
     -  for (i = 0; i < 3; ++i)
     -    {
     -      addr <<= 8;
     -      addr |= buffer[i];
     -    }
     -
        operand_separator (info);
     -  decode_possible_symbol (addr, info);
     -}
     -
     -
     -static uint32_t
     -decode_signed_value (bfd_vma memaddr, struct disassemble_info* info, short size)
     -{
     -  assert (size >0);
     -  assert (size <= 4);
     -  bfd_byte buffer[4];
     -  if (0 > read_memory (memaddr, buffer, size, info))
     -    {
     -      return 0;
     -    }
     -
     -  int i;
     -  uint32_t value = 0;
     -  for (i = 0; i < size; ++i)
     -    {
     -      value |= buffer[i] << (8 * (size - i - 1));
     -    }
     -
     -  if (buffer[0] & 0x80)
     -    {
     -      /* Deal with negative values */
     -      value -= 0x1UL << (size * 8);
     -    }
     -  return value;
     -}
     -
     -
     -static void
     -opr_decode (bfd_vma memaddr, struct disassemble_info* info)
     -{
     -  bfd_byte postbyte;
     -  int status = read_memory (memaddr, &postbyte, 1, info);
     -  if (status < 0)
     -    return;
     -
     -  enum OPR_MODE mode = -1;
     -  size_t i;
     -  for (i = 0; i < sizeof (opr_pb) / sizeof (opr_pb[0]); ++i)
     -    {
     -      const struct opr_pb *pb = opr_pb + i;
     -      if ((postbyte & pb->mask) == pb->value)
     -	{
     -	  mode = pb->mode;
     -	  break;
     -	}
     -    }
      
     -  operand_separator (info);
     -  switch (mode)
     +  switch (opr->cl)
          {
     -    case OPR_IMMe4:
     -      {
     -	int n;
     -	uint8_t x = (postbyte & 0x0F);
     -	if (x == 0)
     -	  n = -1;
     -	else
     -	  n = x;
     -
     -	(*info->fprintf_func) (info->stream, "#%d", n);
     -	break;
     -      }
     -    case OPR_REG:
     -      {
     -	uint8_t x = (postbyte & 0x07);
     -	(*info->fprintf_func) (info->stream, "%s", registers[x].name);
     -	break;
     -      }
     -    case OPR_OFXYS:
     -      {
     -	const char *reg  = xys_from_postbyte (postbyte);
     -	(*info->fprintf_func) (info->stream, "(%d,%s)", postbyte & 0x0F, reg);
     -	break;
     -      }
     -    case OPR_REG_DIRECT:
     -      {
     -	(*info->fprintf_func) (info->stream, "(%s,%s)", registers[postbyte & 0x07].name,
     -			       xys_from_postbyte (postbyte));
     -	break;
     -      }
     -    case OPR_REG_INDIRECT:
     -      {
     -	(*info->fprintf_func) (info->stream, "[%s,%s]", registers[postbyte & 0x07].name,
     -			       (postbyte & 0x10) ? "y": "x");
     -	break;
     -      }
     -
     -    case OPR_IDX_INDIRECT:
     -      {
     -	uint8_t x1;
     -	read_memory (memaddr + 1, &x1, 1, info);
     -	int idx = x1;
     -
     -	if (postbyte & 0x01)
     -	  {
     -	    /* Deal with negative values */
     -	    idx -= 0x1UL << 8;
     -	  }
     -
     -	(*info->fprintf_func) (info->stream, "[%d,%s]", idx,
     -			       xysp_from_postbyte (postbyte));
     -	break;
     -      }
     -
     -    case OPR_IDX3_DIRECT:
     -      {
     -	uint8_t x[3];
     -	read_memory (memaddr + 1, x, 3, info);
     -	int idx = x[0] << 16 | x[1] << 8 | x[2];
     -
     -	if (x[0] & 0x80)
     -	  {
     -	    /* Deal with negative values */
     -	    idx -= 0x1UL << 24;
     -	  }
     -
     -	(*info->fprintf_func) (info->stream, "(%d,%s)", idx,
     -			       xysp_from_postbyte (postbyte));
     -	break;
     -      }
     -
     -    case OPR_IDX3_DIRECT_REG:
     -      {
     -	uint8_t x[3];
     -	read_memory (memaddr + 1, x, 3, info);
     -	int idx = x[0] << 16 | x[1] << 8 | x[2];
     -
     -	if (x[0] & 0x80)
     -	  {
     -	    /* Deal with negative values */
     -	    idx -= 0x1UL << 24;
     -	  }
     -
     -	(*info->fprintf_func) (info->stream, "(%d,%s)", idx,
     -			       registers[postbyte & 0x07].name);
     -	break;
     -      }
     -
     -    case OPR_IDX3_INDIRECT:
     -      {
     -	uint8_t x[3];
     -	read_memory (memaddr + 1, x, 3, info);
     -	int idx = x[0] << 16 | x[1] << 8 | x[2];
     -
     -	if (x[0] & 0x80)
     -	  {
     -	    /* Deal with negative values */
     -	    idx -= 0x1UL << 24;
     -	  }
     -
     -	(*info->fprintf_func) (info->stream, "[%d,%s]", idx,
     -			       xysp_from_postbyte (postbyte));
     -	break;
     -      }
     -
     -    case OPR_IDX_DIRECT:
     -      {
     -	uint8_t x1;
     -	read_memory (memaddr + 1, &x1, 1, info);
     -	int idx = x1;
     -
     -	if (postbyte & 0x01)
     -	  {
     -	    /* Deal with negative values */
     -	    idx -= 0x1UL << 8;
     -	  }
     -
     -	(*info->fprintf_func) (info->stream, "(%d,%s)", idx,
     -			       xysp_from_postbyte (postbyte));
     -	break;
     -      }
     -
     -    case OPR_IDX2_REG:
     -      {
     -	uint8_t x[2];
     -	read_memory (memaddr + 1, x, 2, info);
     -	uint32_t offset = x[1] | x[0] << 8 ;
     -	offset |= (postbyte & 0x30) << 12;
     -
     -	(*info->fprintf_func) (info->stream, "(%d,%s)", offset,
     -			       registers[postbyte & 0x07].name);
     -	break;
     -      }
     -
     -    case OPR_XY_PRE_INC:
     -      {
     -	(*info->fprintf_func) (info->stream, "(+%s)",
     -			       (postbyte & 0x10) ? "y": "x");
     -
     -	break;
     -      }
     -    case OPR_XY_POST_INC:
     -      {
     -	(*info->fprintf_func) (info->stream, "(%s+)",
     -			       (postbyte & 0x10) ? "y": "x");
     -
     -	break;
     -      }
     -    case OPR_XY_PRE_DEC:
     -      {
     -	(*info->fprintf_func) (info->stream, "(-%s)",
     -			       (postbyte & 0x10) ? "y": "x");
     -
     -	break;
     -      }
     -    case OPR_XY_POST_DEC:
     -      {
     -	(*info->fprintf_func) (info->stream, "(%s-)",
     -			       (postbyte & 0x10) ? "y": "x");
     -
     -	break;
     -      }
     -    case OPR_S_PRE_DEC:
     -      {
     -	(*info->fprintf_func) (info->stream, "(-s)");
     -	break;
     -      }
     -    case OPR_S_POST_INC:
     -      {
     -	(*info->fprintf_func) (info->stream, "(s+)");
     -	break;
     -      }
     -
     -    case OPR_EXT18:
     -      {
     -	const size_t size = 2;
     -	bfd_byte buffer[4];
     -	status = read_memory (memaddr + 1, buffer, size, info);
     -	if (status < 0)
     -	  return;
     -
     -	uint32_t ext18 = 0;
     -	for (i = 0; i < size; ++i)
     -	  {
     -	    ext18 <<= 8;
     -	    ext18 |= buffer[i];
     -	  }
     -
     -	ext18 |= (postbyte & 0x01) << 16;
     -	ext18 |= (postbyte & 0x04) << 15;
     -
     -	decode_possible_symbol (ext18, info);
     -	break;
     -      }
     -
     -    case OPR_EXT1:
     +    case OPND_CL_IMMEDIATE:
     +      (*info->fprintf_func) (info->stream, "#%d",
     +			     ((struct immediate_operand *) opr)->value);
     +      break;
     +    case OPND_CL_REGISTER:
            {
     -	uint8_t x1 = 0;
     -	read_memory (memaddr + 1, &x1, 1, info);
     -	int16_t addr;
     -	addr = x1;
     -	addr |= (postbyte & 0x3f) << 8;
     -
     -	decode_possible_symbol (addr, info);
     -	break;
     +        int r = ((struct register_operand*) opr)->reg;
     +	(*info->fprintf_func) (info->stream, "%s", registers[r].name);
            }
     -
     -    case OPR_EXT3_DIRECT:
     +      break;
     +    case OPND_CL_REGISTER_ALL16:
     +      (*info->fprintf_func) (info->stream, "%s", "ALL16b");
     +      break;
     +    case OPND_CL_REGISTER_ALL:
     +      (*info->fprintf_func) (info->stream, "%s", "ALL");
     +      break;
     +    case OPND_CL_BIT_FIELD:
     +      (*info->fprintf_func) (info->stream, "#%d:%d",
     +                             ((struct bitfield_operand*)opr)->width,
     +                             ((struct bitfield_operand*)opr)->offset);
     +      break;
     +    case OPND_CL_SIMPLE_MEMORY:
            {
     -	const size_t size = 3;
     -	bfd_byte buffer[4];
     -	status = read_memory (memaddr + 1, buffer, size, info);
     -	if (status < 0)
     -	  return;
     -
     -	uint32_t ext24 = 0;
     -	for (i = 0; i < size; ++i)
     -	  {
     -	    ext24 |= buffer[i] << (8 * (size - i - 1));
     -	  }
     -
     -	decode_possible_symbol (ext24, info);
     -	break;
     +        struct simple_memory_operand *mo =
     +	  (struct simple_memory_operand *) opr;
     +	decode_possible_symbol (mo->addr, mo->base, info, mo->relative);
            }
     -
     -    case OPR_EXT3_INDIRECT:
     +      break;
     +    case OPND_CL_MEMORY:
            {
     -	const size_t size = 3;
     -	bfd_byte buffer[4];
     -	status = read_memory (memaddr + 1, buffer, size, info);
     -	if (status < 0)
     -	  return;
     +        int used_reg = 0;
     +        struct memory_operand *mo = (struct memory_operand *) opr;
     +	(*info->fprintf_func) (info->stream, "%c", mo->indirect ? '[' : '(');
      
     -	uint32_t ext24 = 0;
     -	for (i = 0; i < size; ++i)
     -	  {
     -	    ext24 |= buffer[i] << (8 * (size - i - 1));
     -	  }
     +        if (mo->base_offset != 0)
     +          {
     +            (*info->fprintf_func) (info->stream, "%d", mo->base_offset);
     +          }
     +        else if (mo->n_regs > 0)
     +          {
     +	    const char *fmt;
     +	    switch (mo->mutation)
     +	      {
     +	      case OPND_RM_PRE_DEC:
     +		fmt = "-%s";
     +		break;
     +	      case OPND_RM_PRE_INC:
     +		fmt = "+%s";
     +		break;
     +	      case OPND_RM_POST_DEC:
     +		fmt = "%s-";
     +		break;
     +	      case OPND_RM_POST_INC:
     +		fmt = "%s+";
     +		break;
     +	      case OPND_RM_NONE:
     +	      default:
     +		fmt = "%s";
     +		break;
     +	      }
     +            (*info->fprintf_func) (info->stream, fmt,
     +				   registers[mo->regs[0]].name);
     +            used_reg = 1;
     +          }
      
     -	(*info->fprintf_func) (info->stream, "[%d]", ext24);
     +        if (mo->n_regs > used_reg)
     +          {
     +            (*info->fprintf_func) (info->stream, ",%s",
     +				   registers[mo->regs[used_reg]].name);
     +          }
      
     -	break;
     +	(*info->fprintf_func) (info->stream, "%c",
     +			       mo->indirect ? ']' : ')');
            }
     -
     -    default:
     -      (*info->fprintf_func) (info->stream, "Unknown OPR mode #0x%x (%d)", postbyte, mode);
     -    }
     +      break;
     +    };
      }
      
     +static const char shift_size_table[] = {
     +  'b', 'w', 'p', 'l'
     +};
      
     -static void
     -opr_decode2 (bfd_vma memaddr, struct disassemble_info* info)
     +int
     +print_insn_s12z (bfd_vma memaddr, struct disassemble_info* info)
      {
     -  int n = opr_n_bytes (memaddr, info);
     -  opr_decode (memaddr, info);
     -  opr_decode (memaddr + n, info);
     -}
     +  enum operator operator = OP_INVALID;
     +  int n_operands = 0;
     +
     +  /* The longest instruction in S12Z can have 6 operands.
     +     (Most have 3 or less.  Only PSH and PUL have so many.  */
     +  struct operand *operands[6];
     +
     +  struct mem_read_abstraction mra;
     +  mra.base.read = (void *) abstract_read_memory ;
     +  mra.base.advance = advance ;
     +  mra.base.posn = posn;
     +  mra.memaddr = memaddr;
     +  mra.info = info;
     +
     +  short osize = -1;
     +  int n_bytes =
     +    decode_s12z (&operator, &osize, &n_operands, operands,
     +		 (struct mem_read_abstraction_base *) &mra);
     +
     +  (info->fprintf_func) (info->stream, "%s", mnemonics[(long)operator]);
     +  
     +  /* Ship out size sufficies for those instructions which
     +     need them.  */
     +  if (osize == -1)
     +    {
     +      bool suffix = false;
     +      for (int o = 0; o < n_operands; ++o)
     +	{
     +	  if (operands[o]->osize != -1)
     +	    {
     +	      if (!suffix)
     +		{
     +		  (*mra.info->fprintf_func) (mra.info->stream, "%c", '.');
     +		  suffix = true;
     +		}
     +	      (*mra.info->fprintf_func) (mra.info->stream, "%c",
     +				     shift_size_table[operands[o]->osize]);
     +	    }
     +	}
     +    }
     +  else
     +    {
     +      (*mra.info->fprintf_func) (mra.info->stream, ".%c",
     +			     shift_size_table[osize]);
     +    }
      
     -static void
     -imm1234 (bfd_vma memaddr, struct disassemble_info* info, int base)
     -{
     -  bfd_byte opcode;
     -  int status = read_memory (memaddr - 1, &opcode, 1, info);
     -  if (status < 0)
     -    return;
      
     -  opcode -= base;
     -
     -  int size = registers[opcode & 0xF].bytes;
     -
     -  uint32_t imm = decode_signed_value (memaddr, info, size);
     -  operand_separator (info);
     -  (*info->fprintf_func) (info->stream, "#%d", imm);
     -}
     -
     -
     -/* Special case of LD and CMP with register S and IMM operand */
     -static void
     -reg_s_imm (bfd_vma memaddr, struct disassemble_info* info)
     -{
     -  operand_separator (info);
     -  (*info->fprintf_func) (info->stream, "s");
     -
     -  uint32_t imm = decode_signed_value (memaddr, info, 3);
     -  operand_separator (info);
     -  (*info->fprintf_func) (info->stream, "#%d", imm);
     -}
     -
     -/* Special case of LD, CMP and ST with register S and OPR operand */
     -static void
     -reg_s_opr (bfd_vma memaddr, struct disassemble_info* info)
     -{
     -  operand_separator (info);
     -  (*info->fprintf_func) (info->stream, "s");
     -
     -  opr_decode (memaddr, info);
     -}
     -
     -static void
     -imm1234_8base (bfd_vma memaddr, struct disassemble_info* info)
     -{
     -  imm1234 (memaddr, info, 8);
     -}
     -
     -static void
     -imm1234_0base (bfd_vma memaddr, struct disassemble_info* info)
     -{
     -  imm1234 (memaddr, info, 0);
     -}
     -
     -static void
     -tfr (bfd_vma memaddr, struct disassemble_info* info)
     -{
     -  bfd_byte byte;
     -  int status = read_memory (memaddr, &byte, 1, info);
     -  if (status < 0)
     -    return;
     -
     -  operand_separator (info);
     -  (*info->fprintf_func) (info->stream, "%s, %s",
     -			 registers[byte >> 4].name,
     -			 registers[byte & 0xF].name);
     -}
     -
     -
     -static void
     -reg (bfd_vma memaddr, struct disassemble_info* info)
     -{
     -  bfd_byte byte;
     -  int status = read_memory (memaddr - 1, &byte, 1, info);
     -  if (status < 0)
     -    return;
     -
     -  operand_separator (info);
     -  (*info->fprintf_func) (info->stream, "%s", registers[byte & 0x07].name);
     -}
     -
     -static void
     -reg_xy (bfd_vma memaddr, struct disassemble_info* info)
     -{
     -  bfd_byte byte;
     -  int status = read_memory (memaddr - 1, &byte, 1, info);
     -  if (status < 0)
     -    return;
     -
     -  operand_separator (info);
     -  (*info->fprintf_func) (info->stream, "%s", (byte & 0x01) ? "y" : "x");
     -}
     -
     -static void
     -lea_reg_xys_opr (bfd_vma memaddr, struct disassemble_info* info)
     -{
     -  bfd_byte byte;
     -  int status = read_memory (memaddr - 1, &byte, 1, info);
     -  if (status < 0)
     -    return;
     -
     -  char *reg_xys = NULL;
     -  switch (byte & 0x03)
     -    {
     -    case 0x00:
     -      reg_xys = "x";
     -      break;
     -    case 0x01:
     -      reg_xys = "y";
     -      break;
     -    case 0x02:
     -      reg_xys = "s";
     -      break;
     -    }
     -
     -  operand_separator (info);
     -  (*info->fprintf_func) (info->stream, "%s", reg_xys);
     -  opr_decode (memaddr, info);
     -}
     -
     -
     -
     -static void
     -lea_reg_xys (bfd_vma memaddr, struct disassemble_info* info)
     -{
     -  bfd_byte byte;
     -  int status = read_memory (memaddr - 1, &byte, 1, info);
     -  if (status < 0)
     -    return;
     -
     -  char *reg_xys = NULL;
     -  switch (byte & 0x03)
     -    {
     -    case 0x00:
     -      reg_xys = "x";
     -      break;
     -    case 0x01:
     -      reg_xys = "y";
     -      break;
     -    case 0x02:
     -      reg_xys = "s";
     -      break;
     -    }
     -
     -  status = read_memory (memaddr, &byte, 1, info);
     -  if (status < 0)
     -    return;
     -
     -  int8_t v = byte;
     -
     -  operand_separator (info);
     -  (*info->fprintf_func) (info->stream, "%s, (%d,%s)", reg_xys, v, reg_xys);
     -}
     -
     -
     -/* PC Relative offsets of size 15 or 7 bits */
     -static void
     -rel_15_7 (bfd_vma memaddr, struct disassemble_info* info, int offset)
     -{
     -  bfd_byte upper;
     -  int status = read_memory (memaddr, &upper, 1, info);
     -  if (status < 0)
     -    return;
     -
     -  bool rel_size = (upper & 0x80);
     -
     -  int16_t addr = upper;
     -  if (rel_size)
     -    {
     -      /* 15 bits.  Get the next byte */
     -      bfd_byte lower;
     -      status = read_memory (memaddr + 1, &lower, 1, info);
     -      if (status < 0)
     -	return;
     -
     -      addr <<= 8;
     -      addr |= lower;
     -      addr &= 0x7FFF;
     -
     -      bool negative = (addr & 0x4000);
     -      addr &= 0x3FFF;
     -      if (negative)
     -	addr = addr - 0x4000;
     -    }
     -  else
     -    {
     -      /* 7 bits. */
     -      bool negative = (addr & 0x40);
     -      addr &= 0x3F;
     -      if (negative)
     -	addr = addr - 0x40;
     -    }
     -
     -  operand_separator (info);
     -  if (!info->symbol_at_address_func (addr + memaddr - offset, info))
     -    {
     -      (*info->fprintf_func) (info->stream, "*%+d", addr);
     -    }
     -  else
     -    {
     -      asymbol *sym = NULL;
     -      int i;
     -      for (i = 0; i < info->symtab_size; ++i)
     -	{
     -	  sym = info->symtab[i];
     -	  if (bfd_asymbol_value (sym) == addr + memaddr - offset)
     -	    {
     -	      break;
     -	    }
     -	}
     -      if (i < info->symtab_size)
     -	(*info->fprintf_func) (info->stream, "%s", bfd_asymbol_name (sym));
     -      else
     -        (*info->fprintf_func) (info->stream, "*%+d", addr);
     -    }
     -}
     -
     -
     -/* PC Relative offsets of size 15 or 7 bits */
     -static void
     -decode_rel_15_7 (bfd_vma memaddr, struct disassemble_info* info)
     -{
     -  rel_15_7 (memaddr, info, 1);
     -}
     -
     -struct opcode
     -{
     -  const char *mnemonic;
     -  insn_bytes_f insn_bytes;
     -  operands_f operands;
     -  operands_f operands2;
     -};
     -
     -static int shift_n_bytes (bfd_vma memaddr, struct disassemble_info* info);
     -static int mov_imm_opr_n_bytes (bfd_vma memaddr, struct disassemble_info* info);
     -static int loop_prim_n_bytes (bfd_vma memaddr, struct disassemble_info* info);
     -static void mov_imm_opr (bfd_vma memaddr, struct disassemble_info* info);
     -static void bm_rel_decode (bfd_vma memaddr, struct disassemble_info* info);
     -static int bm_rel_n_bytes (bfd_vma memaddr, struct disassemble_info* info);
     -static int mul_n_bytes (bfd_vma memaddr, struct disassemble_info* info);
     -static void mul_decode (bfd_vma memaddr, struct disassemble_info* info);
     -static int bm_n_bytes (bfd_vma memaddr, struct disassemble_info* info);
     -static void bm_decode (bfd_vma memaddr, struct disassemble_info* info);
     -
     -static void
     -cmp_xy (bfd_vma memaddr ATTRIBUTE_UNUSED, struct disassemble_info* info)
     -{
     -  operand_separator (info);
     -  (*info->fprintf_func) (info->stream, "x, y");
     -}
     -
     -static void
     -sub_d6_x_y (bfd_vma memaddr ATTRIBUTE_UNUSED, struct disassemble_info* info)
     -{
     -  operand_separator (info);
     -  (*info->fprintf_func) (info->stream, "d6, x, y");
     -}
     -
     -static void
     -sub_d6_y_x (bfd_vma memaddr ATTRIBUTE_UNUSED, struct disassemble_info* info)
     -{
     -  operand_separator (info);
     -  (*info->fprintf_func) (info->stream, "d6, y, x");
     -}
     -
     -static const char shift_size_table[] = {
     -  'b', 'w', 'p', 'l'
     -};
     -
     -static const struct opcode page2[] =
     -  {
     -    [0x00] = {"ld",  opr_n_bytes_p1, 0, reg_s_opr},
     -    [0x01] = {"st",  opr_n_bytes_p1, 0, reg_s_opr},
     -    [0x02] = {"cmp", opr_n_bytes_p1, 0, reg_s_opr},
     -    [0x03] = {"ld",  four, 0, reg_s_imm},
     -    [0x04] = {"cmp", four, 0, reg_s_imm},
     -    [0x05] = {"stop", single, 0, 0},
     -    [0x06] = {"wai",  single, 0, 0},
     -    [0x07] = {"sys",  single, 0, 0},
     -    [0x08] = {NULL,  bfextins_n_bytes, 0, 0},  /* BFEXT / BFINS */
     -    [0x09] = {NULL,  bfextins_n_bytes, 0, 0},
     -    [0x0a] = {NULL,  bfextins_n_bytes, 0, 0},
     -    [0x0b] = {NULL,  bfextins_n_bytes, 0, 0},
     -    [0x0c] = {NULL,  bfextins_n_bytes, 0, 0},
     -    [0x0d] = {NULL,  bfextins_n_bytes, 0, 0},
     -    [0x0e] = {NULL,  bfextins_n_bytes, 0, 0},
     -    [0x0f] = {NULL,  bfextins_n_bytes, 0, 0},
     -    [0x10] = {"minu", opr_n_bytes_p1, reg, opr_decode},
     -    [0x11] = {"minu", opr_n_bytes_p1, reg, opr_decode},
     -    [0x12] = {"minu", opr_n_bytes_p1, reg, opr_decode},
     -    [0x13] = {"minu", opr_n_bytes_p1, reg, opr_decode},
     -    [0x14] = {"minu", opr_n_bytes_p1, reg, opr_decode},
     -    [0x15] = {"minu", opr_n_bytes_p1, reg, opr_decode},
     -    [0x16] = {"minu", opr_n_bytes_p1, reg, opr_decode},
     -    [0x17] = {"minu", opr_n_bytes_p1, reg, opr_decode},
     -    [0x18] = {"maxu", opr_n_bytes_p1, reg, opr_decode},
     -    [0x19] = {"maxu", opr_n_bytes_p1, reg, opr_decode},
     -    [0x1a] = {"maxu", opr_n_bytes_p1, reg, opr_decode},
     -    [0x1b] = {"maxu", opr_n_bytes_p1, reg, opr_decode},
     -    [0x1c] = {"maxu", opr_n_bytes_p1, reg, opr_decode},
     -    [0x1d] = {"maxu", opr_n_bytes_p1, reg, opr_decode},
     -    [0x1e] = {"maxu", opr_n_bytes_p1, reg, opr_decode},
     -    [0x1f] = {"maxu", opr_n_bytes_p1, reg, opr_decode},
     -    [0x20] = {"mins", opr_n_bytes_p1, reg, opr_decode},
     -    [0x21] = {"mins", opr_n_bytes_p1, reg, opr_decode},
     -    [0x22] = {"mins", opr_n_bytes_p1, reg, opr_decode},
     -    [0x23] = {"mins", opr_n_bytes_p1, reg, opr_decode},
     -    [0x24] = {"mins", opr_n_bytes_p1, reg, opr_decode},
     -    [0x25] = {"mins", opr_n_bytes_p1, reg, opr_decode},
     -    [0x26] = {"mins", opr_n_bytes_p1, reg, opr_decode},
     -    [0x27] = {"mins", opr_n_bytes_p1, reg, opr_decode},
     -    [0x28] = {"maxs", opr_n_bytes_p1, reg, opr_decode},
     -    [0x29] = {"maxs", opr_n_bytes_p1, reg, opr_decode},
     -    [0x2a] = {"maxs", opr_n_bytes_p1, reg, opr_decode},
     -    [0x2b] = {"maxs", opr_n_bytes_p1, reg, opr_decode},
     -    [0x2c] = {"maxs", opr_n_bytes_p1, reg, opr_decode},
     -    [0x2d] = {"maxs", opr_n_bytes_p1, reg, opr_decode},
     -    [0x2e] = {"maxs", opr_n_bytes_p1, reg, opr_decode},
     -    [0x2f] = {"maxs", opr_n_bytes_p1, reg, opr_decode},
     -    [0x30] = {"div", mul_n_bytes, mul_decode, 0},
     -    [0x31] = {"div", mul_n_bytes, mul_decode, 0},
     -    [0x32] = {"div", mul_n_bytes, mul_decode, 0},
     -    [0x33] = {"div", mul_n_bytes, mul_decode, 0},
     -    [0x34] = {"div", mul_n_bytes, mul_decode, 0},
     -    [0x35] = {"div", mul_n_bytes, mul_decode, 0},
     -    [0x36] = {"div", mul_n_bytes, mul_decode, 0},
     -    [0x37] = {"div", mul_n_bytes, mul_decode, 0},
     -    [0x38] = {"mod", mul_n_bytes, mul_decode, 0},
     -    [0x39] = {"mod", mul_n_bytes, mul_decode, 0},
     -    [0x3a] = {"mod", mul_n_bytes, mul_decode, 0},
     -    [0x3b] = {"mod", mul_n_bytes, mul_decode, 0},
     -    [0x3c] = {"mod", mul_n_bytes, mul_decode, 0},
     -    [0x3d] = {"mod", mul_n_bytes, mul_decode, 0},
     -    [0x3e] = {"mod", mul_n_bytes, mul_decode, 0},
     -    [0x3f] = {"mod", mul_n_bytes, mul_decode, 0},
     -    [0x40] = {"abs", single, reg, 0},
     -    [0x41] = {"abs", single, reg, 0},
     -    [0x42] = {"abs", single, reg, 0},
     -    [0x43] = {"abs", single, reg, 0},
     -    [0x44] = {"abs", single, reg, 0},
     -    [0x45] = {"abs", single, reg, 0},
     -    [0x46] = {"abs", single, reg, 0},
     -    [0x47] = {"abs", single, reg, 0},
     -    [0x48] = {"mac", mul_n_bytes, mul_decode, 0},
     -    [0x49] = {"mac", mul_n_bytes, mul_decode, 0},
     -    [0x4a] = {"mac", mul_n_bytes, mul_decode, 0},
     -    [0x4b] = {"mac", mul_n_bytes, mul_decode, 0},
     -    [0x4c] = {"mac", mul_n_bytes, mul_decode, 0},
     -    [0x4d] = {"mac", mul_n_bytes, mul_decode, 0},
     -    [0x4e] = {"mac", mul_n_bytes, mul_decode, 0},
     -    [0x4f] = {"mac", mul_n_bytes, mul_decode, 0},
     -    [0x50] = {"adc", three, reg, imm1234_0base},
     -    [0x51] = {"adc", three, reg, imm1234_0base},
     -    [0x52] = {"adc", three, reg, imm1234_0base},
     -    [0x53] = {"adc", three, reg, imm1234_0base},
     -    [0x54] = {"adc", two,   reg, imm1234_0base},
     -    [0x55] = {"adc", two,   reg, imm1234_0base},
     -    [0x56] = {"adc", five,  reg, imm1234_0base},
     -    [0x57] = {"adc", five,  reg, imm1234_0base},
     -    [0x58] = {"bit", three, reg, imm1234_8base},
     -    [0x59] = {"bit", three, reg, imm1234_8base},
     -    [0x5a] = {"bit", three, reg, imm1234_8base},
     -    [0x5b] = {"bit", three, reg, imm1234_8base},
     -    [0x5c] = {"bit", two,   reg, imm1234_8base},
     -    [0x5d] = {"bit", two,   reg, imm1234_8base},
     -    [0x5e] = {"bit", five,  reg, imm1234_8base},
     -    [0x5f] = {"bit", five,  reg, imm1234_8base},
     -    [0x60] = {"adc", opr_n_bytes_p1, reg, opr_decode},
     -    [0x61] = {"adc", opr_n_bytes_p1, reg, opr_decode},
     -    [0x62] = {"adc", opr_n_bytes_p1, reg, opr_decode},
     -    [0x63] = {"adc", opr_n_bytes_p1, reg, opr_decode},
     -    [0x64] = {"adc", opr_n_bytes_p1, reg, opr_decode},
     -    [0x65] = {"adc", opr_n_bytes_p1, reg, opr_decode},
     -    [0x66] = {"adc", opr_n_bytes_p1, reg, opr_decode},
     -    [0x67] = {"adc", opr_n_bytes_p1, reg, opr_decode},
     -    [0x68] = {"bit", opr_n_bytes_p1, reg, opr_decode},
     -    [0x69] = {"bit", opr_n_bytes_p1, reg, opr_decode},
     -    [0x6a] = {"bit", opr_n_bytes_p1, reg, opr_decode},
     -    [0x6b] = {"bit", opr_n_bytes_p1, reg, opr_decode},
     -    [0x6c] = {"bit", opr_n_bytes_p1, reg, opr_decode},
     -    [0x6d] = {"bit", opr_n_bytes_p1, reg, opr_decode},
     -    [0x6e] = {"bit", opr_n_bytes_p1, reg, opr_decode},
     -    [0x6f] = {"bit", opr_n_bytes_p1, reg, opr_decode},
     -    [0x70] = {"sbc", three, reg, imm1234_0base},
     -    [0x71] = {"sbc", three, reg, imm1234_0base},
     -    [0x72] = {"sbc", three, reg, imm1234_0base},
     -    [0x73] = {"sbc", three, reg, imm1234_0base},
     -    [0x74] = {"sbc", two,   reg, imm1234_0base},
     -    [0x75] = {"sbc", two,   reg, imm1234_0base},
     -    [0x76] = {"sbc", five,  reg, imm1234_0base},
     -    [0x77] = {"sbc", five,  reg, imm1234_0base},
     -    [0x78] = {"eor", three, reg, imm1234_8base},
     -    [0x79] = {"eor", three, reg, imm1234_8base},
     -    [0x7a] = {"eor", three, reg, imm1234_8base},
     -    [0x7b] = {"eor", three, reg, imm1234_8base},
     -    [0x7c] = {"eor", two,   reg, imm1234_8base},
     -    [0x7d] = {"eor", two,   reg, imm1234_8base},
     -    [0x7e] = {"eor", five,  reg, imm1234_8base},
     -    [0x7f] = {"eor", five,  reg, imm1234_8base},
     -    [0x80] = {"sbc", opr_n_bytes_p1, reg, opr_decode},
     -    [0x81] = {"sbc", opr_n_bytes_p1, reg, opr_decode},
     -    [0x82] = {"sbc", opr_n_bytes_p1, reg, opr_decode},
     -    [0x83] = {"sbc", opr_n_bytes_p1, reg, opr_decode},
     -    [0x84] = {"sbc", opr_n_bytes_p1, reg, opr_decode},
     -    [0x85] = {"sbc", opr_n_bytes_p1, reg, opr_decode},
     -    [0x86] = {"sbc", opr_n_bytes_p1, reg, opr_decode},
     -    [0x87] = {"sbc", opr_n_bytes_p1, reg, opr_decode},
     -    [0x88] = {"eor", opr_n_bytes_p1, reg,    opr_decode},
     -    [0x89] = {"eor", opr_n_bytes_p1, reg,    opr_decode},
     -    [0x8a] = {"eor", opr_n_bytes_p1, reg,    opr_decode},
     -    [0x8b] = {"eor", opr_n_bytes_p1, reg,    opr_decode},
     -    [0x8c] = {"eor", opr_n_bytes_p1, reg,    opr_decode},
     -    [0x8d] = {"eor", opr_n_bytes_p1, reg,    opr_decode},
     -    [0x8e] = {"eor", opr_n_bytes_p1, reg,    opr_decode},
     -    [0x8f] = {"eor", opr_n_bytes_p1, reg,    opr_decode},
     -    [0x90] = {"rti",  single, 0, 0},
     -    [0x91] = {"clb",   two, tfr, 0},
     -    [0x92] = {"trap",  single, trap_decode, 0},
     -    [0x93] = {"trap",  single, trap_decode, 0},
     -    [0x94] = {"trap",  single, trap_decode, 0},
     -    [0x95] = {"trap",  single, trap_decode, 0},
     -    [0x96] = {"trap",  single, trap_decode, 0},
     -    [0x97] = {"trap",  single, trap_decode, 0},
     -    [0x98] = {"trap",  single, trap_decode, 0},
     -    [0x99] = {"trap",  single, trap_decode, 0},
     -    [0x9a] = {"trap",  single, trap_decode, 0},
     -    [0x9b] = {"trap",  single, trap_decode, 0},
     -    [0x9c] = {"trap",  single, trap_decode, 0},
     -    [0x9d] = {"trap",  single, trap_decode, 0},
     -    [0x9e] = {"trap",  single, trap_decode, 0},
     -    [0x9f] = {"trap",  single, trap_decode, 0},
     -    [0xa0] = {"sat", single, reg, 0},
     -    [0xa1] = {"sat", single, reg, 0},
     -    [0xa2] = {"sat", single, reg, 0},
     -    [0xa3] = {"sat", single, reg, 0},
     -    [0xa4] = {"sat", single, reg, 0},
     -    [0xa5] = {"sat", single, reg, 0},
     -    [0xa6] = {"sat", single, reg, 0},
     -    [0xa7] = {"sat", single, reg, 0},
     -    [0xa8] = {"trap",  single, trap_decode, 0},
     -    [0xa9] = {"trap",  single, trap_decode, 0},
     -    [0xaa] = {"trap",  single, trap_decode, 0},
     -    [0xab] = {"trap",  single, trap_decode, 0},
     -    [0xac] = {"trap",  single, trap_decode, 0},
     -    [0xad] = {"trap",  single, trap_decode, 0},
     -    [0xae] = {"trap",  single, trap_decode, 0},
     -    [0xaf] = {"trap",  single, trap_decode, 0},
     -    [0xb0] = {"qmul", mul_n_bytes, mul_decode, 0},
     -    [0xb1] = {"qmul", mul_n_bytes, mul_decode, 0},
     -    [0xb2] = {"qmul", mul_n_bytes, mul_decode, 0},
     -    [0xb3] = {"qmul", mul_n_bytes, mul_decode, 0},
     -    [0xb4] = {"qmul", mul_n_bytes, mul_decode, 0},
     -    [0xb5] = {"qmul", mul_n_bytes, mul_decode, 0},
     -    [0xb6] = {"qmul", mul_n_bytes, mul_decode, 0},
     -    [0xb7] = {"qmul", mul_n_bytes, mul_decode, 0},
     -    [0xb8] = {"trap",  single, trap_decode, 0},
     -    [0xb9] = {"trap",  single, trap_decode, 0},
     -    [0xba] = {"trap",  single, trap_decode, 0},
     -    [0xbb] = {"trap",  single, trap_decode, 0},
     -    [0xbc] = {"trap",  single, trap_decode, 0},
     -    [0xbd] = {"trap",  single, trap_decode, 0},
     -    [0xbe] = {"trap",  single, trap_decode, 0},
     -    [0xbf] = {"trap",  single, trap_decode, 0},
     -    [0xc0] = {"trap",  single, trap_decode, 0},
     -    [0xc1] = {"trap",  single, trap_decode, 0},
     -    [0xc2] = {"trap",  single, trap_decode, 0},
     -    [0xc3] = {"trap",  single, trap_decode, 0},
     -    [0xc4] = {"trap",  single, trap_decode, 0},
     -    [0xc5] = {"trap",  single, trap_decode, 0},
     -    [0xc6] = {"trap",  single, trap_decode, 0},
     -    [0xc7] = {"trap",  single, trap_decode, 0},
     -    [0xc8] = {"trap",  single, trap_decode, 0},
     -    [0xc9] = {"trap",  single, trap_decode, 0},
     -    [0xca] = {"trap",  single, trap_decode, 0},
     -    [0xcb] = {"trap",  single, trap_decode, 0},
     -    [0xcc] = {"trap",  single, trap_decode, 0},
     -    [0xcd] = {"trap",  single, trap_decode, 0},
     -    [0xce] = {"trap",  single, trap_decode, 0},
     -    [0xcf] = {"trap",  single, trap_decode, 0},
     -    [0xd0] = {"trap",  single, trap_decode, 0},
     -    [0xd1] = {"trap",  single, trap_decode, 0},
     -    [0xd2] = {"trap",  single, trap_decode, 0},
     -    [0xd3] = {"trap",  single, trap_decode, 0},
     -    [0xd4] = {"trap",  single, trap_decode, 0},
     -    [0xd5] = {"trap",  single, trap_decode, 0},
     -    [0xd6] = {"trap",  single, trap_decode, 0},
     -    [0xd7] = {"trap",  single, trap_decode, 0},
     -    [0xd8] = {"trap",  single, trap_decode, 0},
     -    [0xd9] = {"trap",  single, trap_decode, 0},
     -    [0xda] = {"trap",  single, trap_decode, 0},
     -    [0xdb] = {"trap",  single, trap_decode, 0},
     -    [0xdc] = {"trap",  single, trap_decode, 0},
     -    [0xdd] = {"trap",  single, trap_decode, 0},
     -    [0xde] = {"trap",  single, trap_decode, 0},
     -    [0xdf] = {"trap",  single, trap_decode, 0},
     -    [0xe0] = {"trap",  single, trap_decode, 0},
     -    [0xe1] = {"trap",  single, trap_decode, 0},
     -    [0xe2] = {"trap",  single, trap_decode, 0},
     -    [0xe3] = {"trap",  single, trap_decode, 0},
     -    [0xe4] = {"trap",  single, trap_decode, 0},
     -    [0xe5] = {"trap",  single, trap_decode, 0},
     -    [0xe6] = {"trap",  single, trap_decode, 0},
     -    [0xe7] = {"trap",  single, trap_decode, 0},
     -    [0xe8] = {"trap",  single, trap_decode, 0},
     -    [0xe9] = {"trap",  single, trap_decode, 0},
     -    [0xea] = {"trap",  single, trap_decode, 0},
     -    [0xeb] = {"trap",  single, trap_decode, 0},
     -    [0xec] = {"trap",  single, trap_decode, 0},
     -    [0xed] = {"trap",  single, trap_decode, 0},
     -    [0xee] = {"trap",  single, trap_decode, 0},
     -    [0xef] = {"trap",  single, trap_decode, 0},
     -    [0xf0] = {"trap",  single, trap_decode, 0},
     -    [0xf1] = {"trap",  single, trap_decode, 0},
     -    [0xf2] = {"trap",  single, trap_decode, 0},
     -    [0xf3] = {"trap",  single, trap_decode, 0},
     -    [0xf4] = {"trap",  single, trap_decode, 0},
     -    [0xf5] = {"trap",  single, trap_decode, 0},
     -    [0xf6] = {"trap",  single, trap_decode, 0},
     -    [0xf7] = {"trap",  single, trap_decode, 0},
     -    [0xf8] = {"trap",  single, trap_decode, 0},
     -    [0xf9] = {"trap",  single, trap_decode, 0},
     -    [0xfa] = {"trap",  single, trap_decode, 0},
     -    [0xfb] = {"trap",  single, trap_decode, 0},
     -    [0xfc] = {"trap",  single, trap_decode, 0},
     -    [0xfd] = {"trap",  single, trap_decode, 0},
     -    [0xfe] = {"trap",  single, trap_decode, 0},
     -    [0xff] = {"trap",  single, trap_decode, 0},
     -  };
     -
     -static const struct opcode page1[] =
     -  {
     -    [0x00] = {"bgnd", single, 0, 0},
     -    [0x01] = {"nop",  single, 0, 0},
     -    [0x02] = {"brclr", bm_rel_n_bytes, bm_rel_decode, 0},
     -    [0x03] = {"brset", bm_rel_n_bytes, bm_rel_decode, 0},
     -    [0x04] = {NULL,   two,    0, 0}, /* psh/pul */
     -    [0x05] = {"rts",  single, 0, 0},
     -    [0x06] = {"lea", opr_n_bytes_p1, reg, opr_decode},
     -    [0x07] = {"lea", opr_n_bytes_p1, reg, opr_decode},
     -    [0x08] = {"lea", opr_n_bytes_p1, lea_reg_xys_opr, 0},
     -    [0x09] = {"lea", opr_n_bytes_p1, lea_reg_xys_opr, 0},
     -    [0x0a] = {"lea", opr_n_bytes_p1, lea_reg_xys_opr, 0},
     -    [0x0b] = {NULL, loop_prim_n_bytes, 0, 0}, /* Loop primitives TBcc / DBcc */
     -    [0x0c] = {"mov.b", mov_imm_opr_n_bytes, mov_imm_opr, 0},
     -    [0x0d] = {"mov.w", mov_imm_opr_n_bytes, mov_imm_opr, 0},
     -    [0x0e] = {"mov.p", mov_imm_opr_n_bytes, mov_imm_opr, 0},
     -    [0x0f] = {"mov.l", mov_imm_opr_n_bytes, mov_imm_opr, 0},
     -    [0x10] = {NULL,   shift_n_bytes, 0, 0},  /* lsr/lsl/asl/asr/rol/ror */
     -    [0x11] = {NULL,   shift_n_bytes, 0, 0},
     -    [0x12] = {NULL,   shift_n_bytes, 0, 0},
     -    [0x13] = {NULL,   shift_n_bytes, 0, 0},
     -    [0x14] = {NULL,   shift_n_bytes, 0, 0},
     -    [0x15] = {NULL,   shift_n_bytes, 0, 0},
     -    [0x16] = {NULL,   shift_n_bytes, 0, 0},
     -    [0x17] = {NULL,   shift_n_bytes, 0, 0},
     -    [0x18] = {"lea",  two, lea_reg_xys, NULL},
     -    [0x19] = {"lea",  two, lea_reg_xys, NULL},
     -    [0x1a] = {"lea",  two, lea_reg_xys, NULL},
     -    /* 0x1b PG2 */
     -    [0x1c] = {"mov.b", opr_n_bytes2, 0, opr_decode2},
     -    [0x1d] = {"mov.w", opr_n_bytes2, 0, opr_decode2},
     -    [0x1e] = {"mov.p", opr_n_bytes2, 0, opr_decode2},
     -    [0x1f] = {"mov.l", opr_n_bytes2, 0, opr_decode2},
     -    [0x20] = {"bra",  pcrel_15bit, decode_rel_15_7, 0},
     -    [0x21] = {"bsr",  pcrel_15bit, decode_rel_15_7, 0},
     -    [0x22] = {"bhi",  pcrel_15bit, decode_rel_15_7, 0},
     -    [0x23] = {"bls",  pcrel_15bit, decode_rel_15_7, 0},
     -    [0x24] = {"bcc",  pcrel_15bit, decode_rel_15_7, 0},
     -    [0x25] = {"bcs",  pcrel_15bit, decode_rel_15_7, 0},
     -    [0x26] = {"bne",  pcrel_15bit, decode_rel_15_7, 0},
     -    [0x27] = {"beq",  pcrel_15bit, decode_rel_15_7, 0},
     -    [0x28] = {"bvc",  pcrel_15bit, decode_rel_15_7, 0},
     -    [0x29] = {"bvs",  pcrel_15bit, decode_rel_15_7, 0},
     -    [0x2a] = {"bpl",  pcrel_15bit, decode_rel_15_7, 0},
     -    [0x2b] = {"bmi",  pcrel_15bit, decode_rel_15_7, 0},
     -    [0x2c] = {"bge",  pcrel_15bit, decode_rel_15_7, 0},
     -    [0x2d] = {"blt",  pcrel_15bit, decode_rel_15_7, 0},
     -    [0x2e] = {"bgt",  pcrel_15bit, decode_rel_15_7, 0},
     -    [0x2f] = {"ble",  pcrel_15bit, decode_rel_15_7, 0},
     -    [0x30] = {"inc", single, reg, 0},
     -    [0x31] = {"inc", single, reg, 0},
     -    [0x32] = {"inc", single, reg, 0},
     -    [0x33] = {"inc", single, reg, 0},
     -    [0x34] = {"inc", single, reg, 0},
     -    [0x35] = {"inc", single, reg, 0},
     -    [0x36] = {"inc", single, reg, 0},
     -    [0x37] = {"inc", single, reg, 0},
     -    [0x38] = {"clr", single, reg, 0},
     -    [0x39] = {"clr", single, reg, 0},
     -    [0x3a] = {"clr", single, reg, 0},
     -    [0x3b] = {"clr", single, reg, 0},
     -    [0x3c] = {"clr", single, reg, 0},
     -    [0x3d] = {"clr", single, reg, 0},
     -    [0x3e] = {"clr", single, reg, 0},
     -    [0x3f] = {"clr", single, reg, 0},
     -    [0x40] = {"dec", single, reg, 0},
     -    [0x41] = {"dec", single, reg, 0},
     -    [0x42] = {"dec", single, reg, 0},
     -    [0x43] = {"dec", single, reg, 0},
     -    [0x44] = {"dec", single, reg, 0},
     -    [0x45] = {"dec", single, reg, 0},
     -    [0x46] = {"dec", single, reg, 0},
     -    [0x47] = {"dec", single, reg, 0},
     -    [0x48] = {"mul", mul_n_bytes, mul_decode, 0},
     -    [0x49] = {"mul", mul_n_bytes, mul_decode, 0},
     -    [0x4a] = {"mul", mul_n_bytes, mul_decode, 0},
     -    [0x4b] = {"mul", mul_n_bytes, mul_decode, 0},
     -    [0x4c] = {"mul", mul_n_bytes, mul_decode, 0},
     -    [0x4d] = {"mul", mul_n_bytes, mul_decode, 0},
     -    [0x4e] = {"mul", mul_n_bytes, mul_decode, 0},
     -    [0x4f] = {"mul", mul_n_bytes, mul_decode, 0},
     -    [0x50] = {"add", three, reg, imm1234_0base},
     -    [0x51] = {"add", three, reg, imm1234_0base},
     -    [0x52] = {"add", three, reg, imm1234_0base},
     -    [0x53] = {"add", three, reg, imm1234_0base},
     -    [0x54] = {"add", two,   reg, imm1234_0base},
     -    [0x55] = {"add", two,   reg, imm1234_0base},
     -    [0x56] = {"add", five,  reg, imm1234_0base},
     -    [0x57] = {"add", five,  reg, imm1234_0base},
     -    [0x58] = {"and", three, reg, imm1234_8base},
     -    [0x59] = {"and", three, reg, imm1234_8base},
     -    [0x5a] = {"and", three, reg, imm1234_8base},
     -    [0x5b] = {"and", three, reg, imm1234_8base},
     -    [0x5c] = {"and", two,   reg, imm1234_8base},
     -    [0x5d] = {"and", two,   reg, imm1234_8base},
     -    [0x5e] = {"and", five,  reg, imm1234_8base},
     -    [0x5f] = {"and", five,  reg, imm1234_8base},
     -    [0x60] = {"add", opr_n_bytes_p1, reg, opr_decode},
     -    [0x61] = {"add", opr_n_bytes_p1, reg, opr_decode},
     -    [0x62] = {"add", opr_n_bytes_p1, reg, opr_decode},
     -    [0x63] = {"add", opr_n_bytes_p1, reg, opr_decode},
     -    [0x64] = {"add", opr_n_bytes_p1, reg, opr_decode},
     -    [0x65] = {"add", opr_n_bytes_p1, reg, opr_decode},
     -    [0x66] = {"add", opr_n_bytes_p1, reg, opr_decode},
     -    [0x67] = {"add", opr_n_bytes_p1, reg, opr_decode},
     -    [0x68] = {"and", opr_n_bytes_p1, reg, opr_decode},
     -    [0x69] = {"and", opr_n_bytes_p1, reg, opr_decode},
     -    [0x6a] = {"and", opr_n_bytes_p1, reg, opr_decode},
     -    [0x6b] = {"and", opr_n_bytes_p1, reg, opr_decode},
     -    [0x6c] = {"and", opr_n_bytes_p1, reg, opr_decode},
     -    [0x6d] = {"and", opr_n_bytes_p1, reg, opr_decode},
     -    [0x6e] = {"and", opr_n_bytes_p1, reg, opr_decode},
     -    [0x6f] = {"and", opr_n_bytes_p1, reg, opr_decode},
     -    [0x70] = {"sub", three, reg, imm1234_0base},
     -    [0x71] = {"sub", three, reg, imm1234_0base},
     -    [0x72] = {"sub", three, reg, imm1234_0base},
     -    [0x73] = {"sub", three, reg, imm1234_0base},
     -    [0x74] = {"sub", two,   reg, imm1234_0base},
     -    [0x75] = {"sub", two,   reg, imm1234_0base},
     -    [0x76] = {"sub", five,  reg, imm1234_0base},
     -    [0x77] = {"sub", five,  reg, imm1234_0base},
     -    [0x78] = {"or", three, reg, imm1234_8base},
     -    [0x79] = {"or", three, reg, imm1234_8base},
     -    [0x7a] = {"or", three, reg, imm1234_8base},
     -    [0x7b] = {"or", three, reg, imm1234_8base},
     -    [0x7c] = {"or", two,   reg, imm1234_8base},
     -    [0x7d] = {"or", two,   reg, imm1234_8base},
     -    [0x7e] = {"or", five,  reg, imm1234_8base},
     -    [0x7f] = {"or", five,  reg, imm1234_8base},
     -    [0x80] = {"sub", opr_n_bytes_p1, reg,    opr_decode},
     -    [0x81] = {"sub", opr_n_bytes_p1, reg,    opr_decode},
     -    [0x82] = {"sub", opr_n_bytes_p1, reg,    opr_decode},
     -    [0x83] = {"sub", opr_n_bytes_p1, reg,    opr_decode},
     -    [0x84] = {"sub", opr_n_bytes_p1, reg,    opr_decode},
     -    [0x85] = {"sub", opr_n_bytes_p1, reg,    opr_decode},
     -    [0x86] = {"sub", opr_n_bytes_p1, reg,    opr_decode},
     -    [0x87] = {"sub", opr_n_bytes_p1, reg,    opr_decode},
     -    [0x88] = {"or", opr_n_bytes_p1, reg,    opr_decode},
     -    [0x89] = {"or", opr_n_bytes_p1, reg,    opr_decode},
     -    [0x8a] = {"or", opr_n_bytes_p1, reg,    opr_decode},
     -    [0x8b] = {"or", opr_n_bytes_p1, reg,    opr_decode},
     -    [0x8c] = {"or", opr_n_bytes_p1, reg,    opr_decode},
     -    [0x8d] = {"or", opr_n_bytes_p1, reg,    opr_decode},
     -    [0x8e] = {"or", opr_n_bytes_p1, reg,    opr_decode},
     -    [0x8f] = {"or", opr_n_bytes_p1, reg,    opr_decode},
     -    [0x90] = {"ld", three,  reg, imm1234_0base},
     -    [0x91] = {"ld", three,  reg, imm1234_0base},
     -    [0x92] = {"ld", three,  reg, imm1234_0base},
     -    [0x93] = {"ld", three,  reg, imm1234_0base},
     -    [0x94] = {"ld", two,    reg, imm1234_0base},
     -    [0x95] = {"ld", two,    reg, imm1234_0base},
     -    [0x96] = {"ld", five,   reg, imm1234_0base},
     -    [0x97] = {"ld", five,   reg, imm1234_0base},
     -    [0x98] = {"ld", four,   reg_xy, imm1234_0base},
     -    [0x99] = {"ld", four,   reg_xy, imm1234_0base},
     -    [0x9a] = {"clr", single, reg_xy, 0},
     -    [0x9b] = {"clr", single, reg_xy, 0},
     -    [0x9c] = {"inc.b", opr_n_bytes_p1, 0, opr_decode},
     -    [0x9d] = {"inc.w", opr_n_bytes_p1, 0, opr_decode},
     -    [0x9e] = {"tfr", two, tfr, NULL},
     -    [0x9f] = {"inc.l", opr_n_bytes_p1, 0, opr_decode},
     -    [0xa0] = {"ld", opr_n_bytes_p1, reg,    opr_decode},
     -    [0xa1] = {"ld", opr_n_bytes_p1, reg,    opr_decode},
     -    [0xa2] = {"ld", opr_n_bytes_p1, reg,    opr_decode},
     -    [0xa3] = {"ld", opr_n_bytes_p1, reg,    opr_decode},
     -    [0xa4] = {"ld", opr_n_bytes_p1, reg,    opr_decode},
     -    [0xa5] = {"ld", opr_n_bytes_p1, reg,    opr_decode},
     -    [0xa6] = {"ld", opr_n_bytes_p1, reg,    opr_decode},
     -    [0xa7] = {"ld", opr_n_bytes_p1, reg,    opr_decode},
     -    [0xa8] = {"ld", opr_n_bytes_p1, reg_xy, opr_decode},
     -    [0xa9] = {"ld", opr_n_bytes_p1, reg_xy, opr_decode},
     -    [0xaa] = {"jmp", opr_n_bytes_p1, opr_decode, 0},
     -    [0xab] = {"jsr", opr_n_bytes_p1, opr_decode, 0},
     -    [0xac] = {"dec.b", opr_n_bytes_p1, 0, opr_decode},
     -    [0xad] = {"dec.w", opr_n_bytes_p1, 0, opr_decode},
     -    [0xae] = {NULL,   two, 0, 0},  /* EXG / SEX */
     -    [0xaf] = {"dec.l", opr_n_bytes_p1, 0, opr_decode},
     -    [0xb0] = {"ld", four,  reg, ext24_decode},
     -    [0xb1] = {"ld", four,  reg, ext24_decode},
     -    [0xb2] = {"ld", four,  reg, ext24_decode},
     -    [0xb3] = {"ld", four,  reg, ext24_decode},
     -    [0xb4] = {"ld", four,  reg, ext24_decode},
     -    [0xb5] = {"ld", four,  reg, ext24_decode},
     -    [0xb6] = {"ld", four,  reg, ext24_decode},
     -    [0xb7] = {"ld", four,  reg, ext24_decode},
     -    [0xb8] = {"ld", four,  reg_xy, ext24_decode},
     -    [0xb9] = {"ld", four,  reg_xy, ext24_decode},
     -    [0xba] = {"jmp", four, ext24_decode, 0},
     -    [0xbb] = {"jsr", four, ext24_decode, 0},
     -    [0xbc] = {"clr.b", opr_n_bytes_p1, 0, opr_decode},
     -    [0xbd] = {"clr.w", opr_n_bytes_p1, 0, opr_decode},
     -    [0xbe] = {"clr.p", opr_n_bytes_p1, 0, opr_decode},
     -    [0xbf] = {"clr.l", opr_n_bytes_p1, 0, opr_decode},
     -    [0xc0] = {"st", opr_n_bytes_p1, reg,    opr_decode},
     -    [0xc1] = {"st", opr_n_bytes_p1, reg,    opr_decode},
     -    [0xc2] = {"st", opr_n_bytes_p1, reg,    opr_decode},
     -    [0xc3] = {"st", opr_n_bytes_p1, reg,    opr_decode},
     -    [0xc4] = {"st", opr_n_bytes_p1, reg,    opr_decode},
     -    [0xc5] = {"st", opr_n_bytes_p1, reg,    opr_decode},
     -    [0xc6] = {"st", opr_n_bytes_p1, reg,    opr_decode},
     -    [0xc7] = {"st", opr_n_bytes_p1, reg,    opr_decode},
     -    [0xc8] = {"st", opr_n_bytes_p1, reg_xy, opr_decode},
     -    [0xc9] = {"st", opr_n_bytes_p1, reg_xy, opr_decode},
     -    [0xca] = {"ld", three, reg_xy, ld_18bit_decode},
     -    [0xcb] = {"ld", three, reg_xy, ld_18bit_decode},
     -    [0xcc] = {"com.b", opr_n_bytes_p1, NULL, opr_decode},
     -    [0xcd] = {"com.w", opr_n_bytes_p1, NULL, opr_decode},
     -    [0xce] = {"andcc", two, imm1, 0},
     -    [0xcf] = {"com.l", opr_n_bytes_p1, NULL, opr_decode},
     -    [0xd0] = {"st", four,  reg, ext24_decode},
     -    [0xd1] = {"st", four,  reg, ext24_decode},
     -    [0xd2] = {"st", four,  reg, ext24_decode},
     -    [0xd3] = {"st", four,  reg, ext24_decode},
     -    [0xd4] = {"st", four,  reg, ext24_decode},
     -    [0xd5] = {"st", four,  reg, ext24_decode},
     -    [0xd6] = {"st", four,  reg, ext24_decode},
     -    [0xd7] = {"st", four,  reg, ext24_decode},
     -    [0xd8] = {"st", four,  reg_xy, ext24_decode},
     -    [0xd9] = {"st", four,  reg_xy, ext24_decode},
     -    [0xda] = {"ld", three, reg_xy, ld_18bit_decode},
     -    [0xdb] = {"ld", three, reg_xy, ld_18bit_decode},
     -    [0xdc] = {"neg.b", opr_n_bytes_p1, NULL, opr_decode},
     -    [0xdd] = {"neg.w", opr_n_bytes_p1, NULL, opr_decode},
     -    [0xde] = {"orcc",  two,  imm1, 0},
     -    [0xdf] = {"neg.l", opr_n_bytes_p1, NULL, opr_decode},
     -    [0xe0] = {"cmp", three,  reg, imm1234_0base},
     -    [0xe1] = {"cmp", three,  reg, imm1234_0base},
     -    [0xe2] = {"cmp", three,  reg, imm1234_0base},
     -    [0xe3] = {"cmp", three,  reg, imm1234_0base},
     -    [0xe4] = {"cmp", two,    reg, imm1234_0base},
     -    [0xe5] = {"cmp", two,    reg, imm1234_0base},
     -    [0xe6] = {"cmp", five,   reg, imm1234_0base},
     -    [0xe7] = {"cmp", five,   reg, imm1234_0base},
     -    [0xe8] = {"cmp", four,   reg_xy, imm1234_0base},
     -    [0xe9] = {"cmp", four,   reg_xy, imm1234_0base},
     -    [0xea] = {"ld", three, reg_xy, ld_18bit_decode},
     -    [0xeb] = {"ld", three, reg_xy, ld_18bit_decode},
     -    [0xec] = {"bclr", bm_n_bytes, bm_decode, 0},
     -    [0xed] = {"bset", bm_n_bytes, bm_decode, 0},
     -    [0xee] = {"btgl", bm_n_bytes, bm_decode, 0},
     -    [0xef] = {"!!invalid!!", NULL, NULL, NULL}, /* SPARE */
     -    [0xf0] = {"cmp", opr_n_bytes_p1, reg,    opr_decode},
     -    [0xf1] = {"cmp", opr_n_bytes_p1, reg,    opr_decode},
     -    [0xf2] = {"cmp", opr_n_bytes_p1, reg,    opr_decode},
     -    [0xf3] = {"cmp", opr_n_bytes_p1, reg,    opr_decode},
     -    [0xf4] = {"cmp", opr_n_bytes_p1, reg,    opr_decode},
     -    [0xf5] = {"cmp", opr_n_bytes_p1, reg,    opr_decode},
     -    [0xf6] = {"cmp", opr_n_bytes_p1, reg,    opr_decode},
     -    [0xf7] = {"cmp", opr_n_bytes_p1, reg,    opr_decode},
     -    [0xf8] = {"cmp", opr_n_bytes_p1, reg_xy, opr_decode},
     -    [0xf9] = {"cmp", opr_n_bytes_p1, reg_xy, opr_decode},
     -    [0xfa] = {"ld",  three, reg_xy, ld_18bit_decode},
     -    [0xfb] = {"ld",  three, reg_xy, ld_18bit_decode},
     -    [0xfc] = {"cmp", single, cmp_xy, 0},
     -    [0xfd] = {"sub", single, sub_d6_x_y, 0},
     -    [0xfe] = {"sub", single, sub_d6_y_x, 0},
     -    [0xff] = {"swi", single, 0, 0}
     -  };
     -
     -
     -static const char *oprregs1[] =
     -  {
     -    "d3", "d2", "d1", "d0", "ccl", "cch"
     -  };
     -
     -static const char *oprregs2[] =
     -  {
     -    "y", "x", "d7", "d6", "d5", "d4"
     -  };
     -
     -
     -
     -
     -enum MUL_MODE
     -  {
     -    MUL_REG_REG,
     -    MUL_REG_OPR,
     -    MUL_REG_IMM,
     -    MUL_OPR_OPR
     -  };
     -
     -struct mb
     -{
     -  uint8_t mask;
     -  uint8_t value;
     -  enum MUL_MODE mode;
     -};
     -
     -static const struct mb mul_table[] = {
     -  {0x40, 0x00, MUL_REG_REG},
     -
     -  {0x47, 0x40, MUL_REG_OPR},
     -  {0x47, 0x41, MUL_REG_OPR},
     -  {0x47, 0x43, MUL_REG_OPR},
     -
     -  {0x47, 0x44, MUL_REG_IMM},
     -  {0x47, 0x45, MUL_REG_IMM},
     -  {0x47, 0x47, MUL_REG_IMM},
     -
     -  {0x43, 0x42, MUL_OPR_OPR},
     -};
     -
     -static void
     -mul_decode (bfd_vma memaddr, struct disassemble_info* info)
     -{
     -  uint8_t mb;
     -  int status = read_memory (memaddr, &mb, 1, info);
     -  if (status < 0)
     -    return;
     -
     -
     -  uint8_t byte;
     -  status = read_memory (memaddr - 1, &byte, 1, info);
     -  if (status < 0)
     -    return;
     -
     -  (*info->fprintf_func) (info->stream, "%c", (mb & 0x80) ? 's' : 'u');
     -
     -  enum MUL_MODE mode = -1;
     -  size_t i;
     -  for (i = 0; i < sizeof (mul_table) / sizeof (mul_table[0]); ++i)
     -    {
     -      const struct mb *mm = mul_table + i;
     -      if ((mb & mm->mask) == mm->value)
     -	{
     -	  mode = mm->mode;
     -	  break;
     -	}
     -    }
     -
     -  switch (mode)
     -    {
     -    case MUL_REG_REG:
     -      break;
     -    case MUL_OPR_OPR:
     -      {
     -	int size1 = (mb & 0x30) >> 4;
     -	int size2 = (mb & 0x0c) >> 2;
     -	(*info->fprintf_func) (info->stream, ".%c%c",
     -			       shift_size_table [size1],
     -			       shift_size_table [size2]);
     -      }
     -      break;
     -    default:
     -      {
     -	int size = (mb & 0x3);
     -	(*info->fprintf_func) (info->stream, ".%c", shift_size_table [size]);
     -      }
     -      break;
     -    }
     -
     -  operand_separator (info);
     -  (*info->fprintf_func) (info->stream, "%s", registers[byte & 0x7].name);
     -
     -  switch (mode)
     -    {
     -    case MUL_REG_REG:
     -    case MUL_REG_IMM:
     -    case MUL_REG_OPR:
     -      operand_separator (info);
     -      (*info->fprintf_func) (info->stream, "%s", registers[(mb & 0x38) >> 3].name);
     -      break;
     -    default:
     -      break;
     -    }
     -
     -  switch (mode)
     -    {
     -    case MUL_REG_IMM:
     -      operand_separator (info);
     -      int size = (mb & 0x3);
     -      uint32_t imm = decode_signed_value (memaddr + 1, info, size + 1);
     -      (*info->fprintf_func) (info->stream, "#%d", imm);
     -      break;
     -    case MUL_REG_REG:
     -      operand_separator (info);
     -      (*info->fprintf_func) (info->stream, "%s", registers[mb & 0x07].name);
     -      break;
     -    case MUL_REG_OPR:
     -      opr_decode (memaddr + 1, info);
     -      break;
     -    case MUL_OPR_OPR:
     -      {
     -	int first = opr_n_bytes (memaddr + 1, info);
     -	opr_decode (memaddr + 1, info);
     -	opr_decode (memaddr + first + 1, info);
     -	break;
     -      }
     -    }
     -}
     -
     -
     -static int
     -mul_n_bytes (bfd_vma memaddr, struct disassemble_info* info)
     -{
     -  int nx = 2;
     -  uint8_t mb;
     -  int status = read_memory (memaddr, &mb, 1, info);
     -  if (status < 0)
     -    return 0;
     -
     -  enum MUL_MODE mode = -1;
     -  size_t i;
     -  for (i = 0; i < sizeof (mul_table) / sizeof (mul_table[0]); ++i)
     -    {
     -      const struct mb *mm = mul_table + i;
     -      if ((mb & mm->mask) == mm->value)
     -	{
     -	  mode = mm->mode;
     -	  break;
     -	}
     -    }
     -
     -  int size = (mb & 0x3) + 1;
     -
     -  switch (mode)
     -    {
     -    case MUL_REG_IMM:
     -      nx += size;
     -      break;
     -    case MUL_REG_REG:
     -      break;
     -    case MUL_REG_OPR:
     -      nx += opr_n_bytes (memaddr + 1, info);
     -      break;
     -    case MUL_OPR_OPR:
     -      {
     -	int first = opr_n_bytes (memaddr + nx - 1, info);
     -	nx += first;
     -	int second = opr_n_bytes (memaddr + nx - 1, info);
     -	nx += second;
     -      }
     -      break;
     -    }
     -
     -  return nx;
     -}
     -
     -
     - /* The NXP documentation is vague about BM_RESERVED0 and BM_RESERVED1,
     -    and contains obvious typos.
     -    However the Freescale tools and experiments with the chip itself
     -    seem to indicate that they behave like BM_REG_IMM and BM_OPR_REG
     -    respectively.  */
     -
     -enum BM_MODE {
     -  BM_REG_IMM,
     -  BM_RESERVED0,
     -  BM_OPR_B,
     -  BM_OPR_W,
     -  BM_OPR_L,
     -  BM_OPR_REG,
     -  BM_RESERVED1
     -};
     -
     -struct bm
     -{
     -  uint8_t mask;
     -  uint8_t value;
     -  enum BM_MODE mode;
     -};
     -
     -static const  struct bm bm_table[] = {
     -  { 0xC6, 0x04,     BM_REG_IMM},
     -  { 0x84, 0x00,     BM_REG_IMM},
     -  { 0x06, 0x06,     BM_REG_IMM},
     -  { 0xC6, 0x44,     BM_RESERVED0},
     -  // 00
     -  { 0x8F, 0x80,     BM_OPR_B},
     -  { 0x8E, 0x82,     BM_OPR_W},
     -  { 0x8C, 0x88,     BM_OPR_L},
     -
     -  { 0x83, 0x81,     BM_OPR_REG},
     -  { 0x87, 0x84,     BM_RESERVED1},
     -};
     -
     -static void
     -bm_decode (bfd_vma memaddr, struct disassemble_info* info)
     -{
     -  uint8_t bm;
     -  int status = read_memory (memaddr, &bm, 1, info);
     -  if (status < 0)
     -    return;
     -
     -  size_t i;
     -  enum BM_MODE mode = -1;
     -  for (i = 0; i < sizeof (bm_table) / sizeof (bm_table[0]); ++i)
     -    {
     -      const struct bm *bme = bm_table + i;
     -      if ((bm & bme->mask) == bme->value)
     -	{
     -	  mode = bme->mode;
     -	  break;
     -	}
     -    }
     -
     -  switch (mode)
     -    {
     -    case BM_REG_IMM:
     -    case BM_RESERVED0:
     -      operand_separator (info);
     -      (*info->fprintf_func) (info->stream, "%s", registers[bm & 0x07].name);
     -      break;
     -    case BM_OPR_B:
     -      (*info->fprintf_func) (info->stream, ".%c", 'b');
     -      opr_decode (memaddr + 1, info);
     -      break;
     -    case BM_OPR_W:
     -      (*info->fprintf_func) (info->stream, ".%c", 'w');
     -      opr_decode (memaddr + 1, info);
     -      break;
     -    case BM_OPR_L:
     -      (*info->fprintf_func) (info->stream, ".%c", 'l');
     -      opr_decode (memaddr + 1, info);
     -      break;
     -    case BM_OPR_REG:
     -    case BM_RESERVED1:
     -      {
     -	uint8_t xb;
     -	read_memory (memaddr + 1, &xb, 1, info);
     -	/* Don't emit a size suffix for register operands */
     -	if ((xb & 0xF8) != 0xB8)
     -	  (*info->fprintf_func) (info->stream, ".%c", shift_size_table[(bm & 0x0c) >> 2]);
     -	opr_decode (memaddr + 1, info);
     -      }
     -      break;
     -    }
     -
     -  uint8_t imm = 0;
     -  operand_separator (info);
     -  switch (mode)
     -    {
     -    case BM_REG_IMM:
     -      {
     -	imm = (bm & 0x38) >> 3;
     -	(*info->fprintf_func) (info->stream, "#%d", imm);
     -      }
     -      break;
     -    case BM_OPR_L:
     -      imm |= (bm & 0x03) << 3;
     -      /* fallthrough */
     -    case BM_OPR_W:
     -      imm |= (bm & 0x01) << 3;
     -      /* fallthrough */
     -    case BM_OPR_B:
     -      imm |= (bm & 0x70) >> 4;
     -      (*info->fprintf_func) (info->stream, "#%d", imm);
     -      break;
     -    case BM_OPR_REG:
     -    case BM_RESERVED1:
     -      (*info->fprintf_func) (info->stream, "%s", registers[(bm & 0x70) >> 4].name);
     -      break;
     -    case BM_RESERVED0:
     -      assert (0);
     -      break;
     -    }
     -}
     -
     -
     -static void
     -bm_rel_decode (bfd_vma memaddr, struct disassemble_info* info)
     -{
     -  uint8_t bm;
     -  int status = read_memory (memaddr, &bm, 1, info);
     -  if (status < 0)
     -    return;
     -
     -  size_t i;
     -  enum BM_MODE mode = -1;
     -  for (i = 0; i < sizeof (bm_table) / sizeof (bm_table[0]); ++i)
     -    {
     -      const struct bm *bme = bm_table + i;
     -      if ((bm & bme->mask) == bme->value)
     -	{
     -	  mode = bme->mode;
     -	  break;
     -	}
     -    }
     -
     -  switch (mode)
     -    {
     -    case BM_REG_IMM:
     -    case BM_RESERVED0:
     -      break;
     -    case BM_OPR_B:
     -      (*info->fprintf_func) (info->stream, ".%c", 'b');
     -      break;
     -    case BM_OPR_W:
     -      (*info->fprintf_func) (info->stream, ".%c", 'w');
     -      break;
     -    case BM_OPR_L:
     -      (*info->fprintf_func) (info->stream, ".%c", 'l');
     -      break;
     -    case BM_OPR_REG:
     -    case BM_RESERVED1:
     -      {
     -	uint8_t xb;
     -	read_memory (memaddr + 1, &xb, 1, info);
     -	/* Don't emit a size suffix for register operands */
     -	if ((xb & 0xF8) != 0xB8)
     -	  (*info->fprintf_func) (info->stream, ".%c",
     -				 shift_size_table[(bm & 0x0C) >> 2]);
     -      }
     -      break;
     -    }
     -
     -  int n = 1;
     -  switch (mode)
     -    {
     -    case BM_REG_IMM:
     -    case BM_RESERVED0:
     -      operand_separator (info);
     -      (*info->fprintf_func) (info->stream, "%s", registers[bm & 0x07].name);
     -      break;
     -    case BM_OPR_B:
     -    case BM_OPR_W:
     -    case BM_OPR_L:
     -      opr_decode (memaddr + 1, info);
     -      n = 1 + opr_n_bytes (memaddr + 1, info);
     -      break;
     -    case BM_OPR_REG:
     -    case BM_RESERVED1:
     -      opr_decode (memaddr + 1, info);
     -      break;
     -    }
     -
     -
     -  int imm = 0;
     -  operand_separator (info);
     -  switch (mode)
     -    {
     -    case BM_OPR_L:
     -      imm |= (bm & 0x02) << 3;
     -      /* fall through */
     -    case BM_OPR_W:
     -      imm |= (bm & 0x01) << 3;
     -      /* fall through */
     -    case BM_OPR_B:
     -      imm |= (bm & 0x70) >> 4;
     -      (*info->fprintf_func) (info->stream, "#%d", imm);
     -      break;
     -    case BM_RESERVED0:
     -      imm = (bm & 0x38) >> 3;
     -      (*info->fprintf_func) (info->stream, "#%d", imm);
     -      break;
     -    case BM_REG_IMM:
     -      imm = (bm & 0xF8) >> 3;
     -      (*info->fprintf_func) (info->stream, "#%d", imm);
     -      break;
     -    case BM_OPR_REG:
     -    case BM_RESERVED1:
     -      (*info->fprintf_func) (info->stream, "%s", registers[(bm & 0x70) >> 4].name);
     -      n += opr_n_bytes (memaddr + 1, info);
     -      break;
     -    }
     -
     -  rel_15_7 (memaddr + n, info, n + 1);
     -}
     -
     -static int
     -bm_n_bytes (bfd_vma memaddr, struct disassemble_info* info)
     -{
     -  uint8_t bm;
     -  int status = read_memory (memaddr, &bm, 1, info);
     -  if (status < 0)
     -    return status;
     -
     -  size_t i;
     -  enum BM_MODE mode = -1;
     -  for (i = 0; i < sizeof (bm_table) / sizeof (bm_table[0]); ++i)
     -    {
     -      const struct bm *bme = bm_table + i;
     -      if ((bm & bme->mask) == bme->value)
     -	{
     -	  mode = bme->mode;
     -	  break;
     -	}
     -    }
     -
     -  int n = 2;
     -  switch (mode)
     -    {
     -    case BM_REG_IMM:
     -    case BM_RESERVED0:
     -      break;
     -
     -    case BM_OPR_B:
     -    case BM_OPR_W:
     -    case BM_OPR_L:
     -      n += opr_n_bytes (memaddr + 1, info);
     -      break;
     -    case BM_OPR_REG:
     -    case BM_RESERVED1:
     -      n += opr_n_bytes (memaddr + 1, info);
     -      break;
     -  }
     -
     -  return n;
     -}
     -
     -static int
     -bm_rel_n_bytes (bfd_vma memaddr, struct disassemble_info* info)
     -{
     -  int n = 1 + bm_n_bytes (memaddr, info);
     -
     -  bfd_byte rb;
     -  int status = read_memory (memaddr + n - 2, &rb, 1, info);
     -  if (status != 0)
     -    return status;
     -
     -  if (rb & 0x80)
     -    n++;
     -
     -  return n;
     -}
     -
     -
     -
     -
     -
     -/* shift direction */
     -enum SB_DIR
     -  {
     -    SB_LEFT,
     -    SB_RIGHT
     -  };
     -
     -enum SB_TYPE
     -  {
     -    SB_ARITHMETIC,
     -    SB_LOGICAL
     -  };
     -
     -
     -enum SB_MODE
     -  {
     -    SB_REG_REG_N_EFF,
     -    SB_REG_REG_N,
     -    SB_REG_OPR_EFF,
     -    SB_ROT,
     -    SB_REG_OPR_OPR,
     -    SB_OPR_N
     -  };
     -
     -struct sb
     -{
     -  uint8_t mask;
     -  uint8_t value;
     -  enum SB_MODE mode;
     -};
     -
     -static const  struct sb sb_table[] = {
     -  {0x30, 0x00,     SB_REG_REG_N_EFF},
     -  {0x30, 0x10,     SB_REG_REG_N},
     -  {0x34, 0x20,     SB_REG_OPR_EFF},
     -  {0x34, 0x24,     SB_ROT},
     -  {0x34, 0x30,     SB_REG_OPR_OPR},
     -  {0x34, 0x34,     SB_OPR_N},
     -};
     -
     -static int
     -shift_n_bytes (bfd_vma memaddr, struct disassemble_info* info)
     -{
     -  bfd_byte sb;
     -  int status = read_memory (memaddr++, &sb, 1, info);
     -  if (status != 0)
     -    return status;
     -
     -  size_t i;
     -  enum SB_MODE mode = -1;
     -  for (i = 0; i < sizeof (sb_table) / sizeof (sb_table[0]); ++i)
     -    {
     -      const struct sb *sbe = sb_table + i;
     -      if ((sb & sbe->mask) == sbe->value)
     -	mode = sbe->mode;
     -    }
     -
     -  switch (mode)
     -    {
     -    case SB_REG_REG_N_EFF:
     -      return 2;
     -      break;
     -    case SB_REG_OPR_EFF:
     -    case SB_ROT:
     -	return 2 + opr_n_bytes (memaddr, info);
     -      break;
     -    case SB_REG_OPR_OPR:
     -      {
     -	int opr1 = opr_n_bytes (memaddr, info);
     -	int opr2 = 0;
     -	if ((sb & 0x30) != 0x20)
     -	  opr2 = opr_n_bytes (memaddr + opr1, info);
     -	return 2 + opr1 + opr2;
     -      }
     -      break;
     -    default:
     -      return 3;
     -    }
     -
     -  /* not reached */
     -  return -1;
     -}
     -
     -
     -static int
     -mov_imm_opr_n_bytes (bfd_vma memaddr, struct disassemble_info* info)
     -{
     -  bfd_byte byte;
     -  int status = read_memory (memaddr - 1, &byte, 1, info);
     -  if (status < 0)
     -    return status;
     -
     -  int size = byte - 0x0c + 1;
     -
     -  return size + opr_n_bytes (memaddr + size, info) + 1;
     -}
     -
     -static void
     -mov_imm_opr (bfd_vma memaddr, struct disassemble_info* info)
     -{
     -  bfd_byte byte;
     -  int status = read_memory (memaddr - 1, &byte, 1, info);
     -  if (status < 0)
     -    return ;
     -
     -  int size = byte - 0x0c + 1;
     -  uint32_t imm = decode_signed_value (memaddr, info, size);
     -
     -  operand_separator (info);
     -  (*info->fprintf_func) (info->stream, "#%d", imm);
     -  opr_decode (memaddr + size, info);
     -}
     -
     -
     -
     -static void
     -ld_18bit_decode (bfd_vma memaddr, struct disassemble_info* info)
     -{
     -  size_t size = 3;
     -  bfd_byte buffer[3];
     -  int status = read_memory (memaddr, buffer + 1, 2, info);
     -  if (status < 0)
     -    return ;
     -
     -
     -  status = read_memory (memaddr - 1, buffer, 1, info);
     -  if (status < 0)
     -    return ;
     -
     -  buffer[0] = (buffer[0] & 0x30) >> 4;
     -
     -  size_t i;
     -  uint32_t imm = 0;
     -  for (i = 0; i < size; ++i)
     -    {
     -      imm |= buffer[i] << (8 * (size - i - 1));
     -    }
     -
     -  operand_separator (info);
     -  (*info->fprintf_func) (info->stream, "#%d", imm);
     -}
     -
     -
     -
     -/* Loop Primitives */
     -
     -enum LP_MODE {
     -  LP_REG,
     -  LP_XY,
     -  LP_OPR
     -};
     -
     -struct lp
     -{
     -  uint8_t mask;
     -  uint8_t value;
     -  enum LP_MODE mode;
     -};
     -
     -static const struct lp lp_mode[] = {
     -  {0x08, 0x00, LP_REG},
     -  {0x0C, 0x08, LP_XY},
     -  {0x0C, 0x0C, LP_OPR},
     -};
     -
     -
     -static const char *lb_condition[] =
     -  {
     -    "ne", "eq", "pl", "mi", "gt", "le",
     -    "??", "??"
     -  };
     -
     -static int
     -loop_prim_n_bytes (bfd_vma memaddr, struct disassemble_info* info)
     -{
     -  int mx = 0;
     -  uint8_t lb;
     -  read_memory (memaddr + mx++, &lb, 1, info);
     -
     -  enum LP_MODE mode = -1;
     -  size_t i;
     -  for (i = 0; i < sizeof (lp_mode) / sizeof (lp_mode[0]); ++i)
     -    {
     -      const struct lp *pb = lp_mode + i;
     -      if ((lb & pb->mask) == pb->value)
     -	{
     -	  mode = pb->mode;
     -	  break;
     -	}
     -    }
     -
     -  if (mode == LP_OPR)
     -    {
     -      mx += opr_n_bytes (memaddr + mx, info) ;
     -    }
     -
     -  uint8_t rb;
     -  read_memory (memaddr + mx++, &rb, 1, info);
     -  if (rb & 0x80)
     -    mx++;
     -
     -  return mx + 1;
     -}
     -
     -
     -
     -
     -static int
     -print_insn_exg_sex (bfd_vma memaddr, struct disassemble_info* info)
     -{
     -  uint8_t eb;
     -  int status = read_memory (memaddr, &eb, 1, info);
     -  if (status < 0)
     -    return -1;
     -
     -  const struct reg *first =  &registers[(eb & 0xf0) >> 4];
     -  const struct reg *second = &registers[(eb & 0xf)];
     -
     -  if (first->bytes < second->bytes)
     -    (*info->fprintf_func) (info->stream, "sex");
     -  else
     -    (*info->fprintf_func) (info->stream, "exg");
     -
     -  operand_separator (info);
     -  (*info->fprintf_func) (info->stream, "%s", first->name);
     -  operand_separator (info);
     -  (*info->fprintf_func) (info->stream, "%s", second->name);
     -  return 0;
     -}
     -
     -
     -
     -static int
     -print_insn_loop_primitive (bfd_vma memaddr, struct disassemble_info* info)
     -{
     -  int offs = 1;
     -  uint8_t lb;
     -  int status = read_memory (memaddr, &lb, 1, info);
     -
     -  char mnemonic[7];
     -  int x = 0;
     -  mnemonic[x++] = (lb & 0x80) ? 'd' : 't';
     -  mnemonic[x++] = 'b';
     -  stpcpy (mnemonic + x, lb_condition [(lb & 0x70) >> 4]);
     -  x += 2;
     -
     -  const char *reg_dxy  = NULL;
     -  enum LP_MODE mode = -1;
     -  size_t i;
     -  for (i = 0; i < sizeof (lp_mode) / sizeof (lp_mode[0]); ++i)
     -    {
     -      const struct lp *pb = lp_mode + i;
     -      if ((lb & pb->mask) == pb->value)
     -	{
     -	  mode = pb->mode;
     -	  break;
     -	}
     -    }
     -
     -  switch (mode)
     -    {
     -    case LP_REG:
     -      reg_dxy = registers [lb & 0x07].name;
     -      break;
     -    case LP_XY:
     -      reg_dxy = (lb & 0x1) ? "y" : "x";
     -      break;
     -    case LP_OPR:
     -      mnemonic[x++] = '.';
     -      mnemonic[x++] = shift_size_table [lb & 0x03];
     -      offs += opr_n_bytes (memaddr + 1, info);
     -      break;
     -    }
     -
     -  mnemonic[x++] = '\0';
     -
     -  (*info->fprintf_func) (info->stream, "%s", mnemonic);
     -
     -  if (mode == LP_OPR)
     -    opr_decode (memaddr + 1, info);
     -  else
     -    {
     -      operand_separator (info);
     -      (*info->fprintf_func) (info->stream, "%s", reg_dxy);
     -    }
     -
     -  rel_15_7 (memaddr + offs, info, offs + 1);
     -
     -  return status;
     -}
     -
     -
     -static int
     -print_insn_shift (bfd_vma memaddr, struct disassemble_info* info, uint8_t byte)
     -{
     -  size_t i;
     -  uint8_t sb;
     -  int status = read_memory (memaddr, &sb, 1, info);
     -  if (status < 0)
     -    return status;
     -
     -  enum SB_DIR  dir = (sb & 0x40) ? SB_LEFT : SB_RIGHT;
     -  enum SB_TYPE type = (sb & 0x80) ? SB_ARITHMETIC : SB_LOGICAL;
     -  enum SB_MODE mode = -1;
     -  for (i = 0; i < sizeof (sb_table) / sizeof (sb_table[0]); ++i)
     -    {
     -      const struct sb *sbe = sb_table + i;
     -      if ((sb & sbe->mask) == sbe->value)
     -	mode = sbe->mode;
     -    }
     -
     -  char mnemonic[6];
     -  int x = 0;
     -  if (mode == SB_ROT)
     -    {
     -      mnemonic[x++] = 'r';
     -      mnemonic[x++] = 'o';
     -    }
     -  else
     -    {
     -      mnemonic[x++] = (type == SB_LOGICAL) ? 'l' : 'a';
     -      mnemonic[x++] = 's';
     -    }
     -
     -  mnemonic[x++] = (dir == SB_LEFT) ? 'l' : 'r';
     -
     -  switch (mode)
     -    {
     -    case SB_REG_OPR_EFF:
     -    case SB_ROT:
     -    case SB_REG_OPR_OPR:
     -      mnemonic[x++] = '.';
     -      mnemonic[x++] = shift_size_table[sb & 0x03];
     -      break;
     -    case SB_OPR_N:
     -      {
     -	uint8_t xb;
     -	read_memory (memaddr + 1, &xb, 1, info);
     -	/* The size suffix is not printed if the OPR operand refers
     -	   directly to a register, because the size is implied by the
     -	   size of that register. */
     -	if ((xb & 0xF8) != 0xB8)
     -	  {
     -	    mnemonic[x++] = '.';
     -	    mnemonic[x++] = shift_size_table[sb & 0x03];
     -	  }
     -      }
     -      break;
     -    default:
     -      break;
     -    };
     -
     -  mnemonic[x++] = '\0';
     -
     -  (*info->fprintf_func) (info->stream, "%s", mnemonic);
     -
     -  /* Destination register */
     -  switch (mode)
     -    {
     -    case SB_REG_REG_N_EFF:
     -    case SB_REG_REG_N:
     -    case SB_REG_OPR_EFF:
     -    case SB_REG_OPR_OPR:
     -      operand_separator (info);
     -      (*info->fprintf_func) (info->stream, "%s", registers[byte & 0x7].name);
     -      break;
     -
     -    case SB_ROT:
     -      opr_decode (memaddr + 1, info);
     -      break;
     -
     -    default:
     -      break;
     -    }
     -
     -  /* Source register */
     -  switch (mode)
     -    {
     -    case SB_REG_REG_N_EFF:
     -    case SB_REG_REG_N:
     -      operand_separator (info);
     -      (*info->fprintf_func) (info->stream, "%s", registers[sb & 0x7].name);
     -      break;
     -
     -    case SB_REG_OPR_OPR:
     -      opr_decode (memaddr + 1, info);
     -      break;
     -
     -    default:
     -      break;
     -    }
     -
     -  /* 3rd arg */
     -  switch (mode)
     -    {
     -    case SB_REG_OPR_EFF:
     -    case SB_OPR_N:
     -      opr_decode (memaddr + 1, info);
     -      break;
     -
     -    case SB_REG_REG_N:
     -      {
     -        uint8_t xb;
     -        read_memory (memaddr + 1, &xb, 1, info);
     -        /* This case is slightly unusual.
     -           If XB matches the binary pattern 0111XXXX, then instead of
     -           interpreting this as a general OPR postbyte in the IMMe4 mode,
     -           the XB byte is interpreted in s special way.  */
     -        if ((xb & 0xF0) == 0x70)
     -          {
     -            operand_separator (info);
     -            if (byte & 0x10)
     -              {
     -                int shift = ((sb & 0x08) >> 3) | ((xb & 0x0f) << 1);
     -                (*info->fprintf_func) (info->stream, "#%d", shift);
     -              }
     -            else
     -              {
     -                (*info->fprintf_func) (info->stream, "%s:%d", __FILE__, __LINE__);
     -              }
     -          }
     -        else
     -          {
     -            opr_decode (memaddr + 1, info);
     -          }
     -      }
     -      break;
     -    case SB_REG_OPR_OPR:
     -      {
     -      uint8_t xb;
     -      int n = opr_n_bytes (memaddr + 1, info);
     -      read_memory (memaddr + 1 + n, &xb, 1, info);
     -
     -      if ((xb & 0xF0) == 0x70)
     -	{
     -	  int imm = xb & 0x0F;
     -	  imm <<= 1;
     -	  imm |= (sb & 0x08) >> 3;
     -	  operand_separator (info);
     -	  (*info->fprintf_func) (info->stream, "#%d", imm);
     -	}
     -      else
     -	{
     -	  opr_decode (memaddr + 1 + n, info);
     -	}
     -      }
     -      break;
     -    default:
     -      break;
     -    }
     -
     -  switch (mode)
     -    {
     -    case SB_REG_REG_N_EFF:
     -    case SB_REG_OPR_EFF:
     -    case SB_OPR_N:
     -      operand_separator (info);
     -      (*info->fprintf_func) (info->stream, "#%d",
     -			     (sb & 0x08) ? 2 : 1);
     -      break;
     -
     -    default:
     -      break;
     -    }
     -
     -  return 0;
     -}
     -
     -int
     -print_insn_s12z (bfd_vma memaddr, struct disassemble_info* info)
     -{
     -  bfd_byte byte;
     -  int status = read_memory (memaddr++, &byte, 1, info);
     -  if (status != 0)
     -    return status;
     -
     -  const struct opcode *opc2 = NULL;
     -  const struct opcode *opc = page1 + byte;
     -  if (opc->mnemonic)
     -    {
     -      (*info->fprintf_func) (info->stream, "%s", opc->mnemonic);
     -    }
     -  else
     -    {
     -      /* The special cases ... */
     -      switch (byte)
     -	{
     -	case PAGE2_PREBYTE:
     -	  {
     -	    bfd_byte byte2;
     -	    read_memory (memaddr++, &byte2, 1, info);
     -	    opc2 = page2 + byte2;
     -	    if (opc2->mnemonic)
     -	      {
     -		(*info->fprintf_func) (info->stream, "%s", opc2->mnemonic);
     -
     -		if (opc2->operands)
     -		  {
     -		    opc2->operands (memaddr, info);
     -		  }
     -
     -		if (opc2->operands2)
     -		  {
     -		    opc2->operands2 (memaddr, info);
     -		  }
     -	      }
     -	    else if (byte2 >= 0x08 && byte2 <= 0x1F)
     -	      {
     -		bfd_byte bb;
     -		read_memory (memaddr, &bb, 1, info);
     -		if (bb & 0x80)
     -		  (*info->fprintf_func) (info->stream, "bfins");
     -		else
     -		  (*info->fprintf_func) (info->stream, "bfext");
     -
     -		enum BB_MODE mode = -1;
     -		size_t i;
     -		const struct opr_bb *bbs = 0;
     -		for (i = 0; i < sizeof (bb_modes) / sizeof (bb_modes[0]); ++i)
     -		  {
     -		    bbs = bb_modes + i;
     -		    if ((bb & bbs->mask) == bbs->value)
     -		      {
     -			mode = bbs->mode;
     -			break;
     -		      }
     -		  }
     -
     -		switch (mode)
     -		  {
     -		  case BB_REG_OPR_REG:
     -		  case BB_REG_OPR_IMM:
     -		  case BB_OPR_REG_REG:
     -		  case BB_OPR_REG_IMM:
     -		    {
     -		      int size = (bb >> 2) & 0x03;
     -		      (*info->fprintf_func) (info->stream, ".%c",
     -					     shift_size_table [size]);
     -		    }
     -		    break;
     -		  default:
     -		    break;
     -		  }
     -
     -		int reg1 = byte2 & 0x07;
     -		/* First operand */
     -		switch (mode)
     -		  {
     -		  case BB_REG_REG_REG:
     -		  case BB_REG_REG_IMM:
     -		  case BB_REG_OPR_REG:
     -		  case BB_REG_OPR_IMM:
     -		    operand_separator (info);
     -		    (*info->fprintf_func) (info->stream, "%s",
     -					   registers[reg1].name);
     -		    break;
     -		  case BB_OPR_REG_REG:
     -		    opr_decode (memaddr + 1, info);
     -		    break;
     -		  case BB_OPR_REG_IMM:
     -		    opr_decode (memaddr + 2, info);
     -		    break;
     -		  }
     -
     -		/* Second operand */
     -		switch (mode)
     -		  {
     -		  case BB_REG_REG_REG:
     -		  case BB_REG_REG_IMM:
     -		    {
     -		      int reg_src = (bb >> 2) & 0x07;
     -		      operand_separator (info);
     -		      (*info->fprintf_func) (info->stream, "%s",
     -					     registers[reg_src].name);
     -		    }
     -		    break;
     -		  case BB_OPR_REG_REG:
     -		  case BB_OPR_REG_IMM:
     -		    {
     -		      int reg_src = (byte2 & 0x07);
     -		      operand_separator (info);
     -		      (*info->fprintf_func) (info->stream, "%s",
     -					     registers[reg_src].name);
     -		    }
     -		    break;
     -		  case BB_REG_OPR_REG:
     -		    opr_decode (memaddr + 1, info);
     -		    break;
     -		  case BB_REG_OPR_IMM:
     -		    opr_decode (memaddr + 2, info);
     -		    break;
     -		  }
     -
     -		/* Third operand */
     -		operand_separator (info);
     -		switch (mode)
     -		  {
     -		  case BB_REG_REG_REG:
     -		  case BB_OPR_REG_REG:
     -		  case BB_REG_OPR_REG:
     -		    {
     -		      int reg_parm = bb & 0x03;
     -		      (*info->fprintf_func) (info->stream, "%s",
     -					     registers[reg_parm].name);
     -		    }
     -		    break;
     -		  case BB_REG_REG_IMM:
     -		  case BB_OPR_REG_IMM:
     -		  case BB_REG_OPR_IMM:
     -		    {
     -		      bfd_byte i1;
     -		      read_memory (memaddr + 1, &i1, 1, info);
     -		      int offset = i1 & 0x1f;
     -		      int width = bb & 0x03;
     -		      width <<= 3;
     -		      width |= i1 >> 5;
     -		      (*info->fprintf_func) (info->stream, "#%d:%d", width,  offset);
     -		    }
     -		    break;
     -		  }
     -	      }
     -	  }
     -	  break;
     -	case 0xae: /* EXG / SEX */
     -	  status = print_insn_exg_sex (memaddr, info);
     -	  break;
     -	case 0x0b:  /* Loop Primitives TBcc and DBcc */
     -	  status = print_insn_loop_primitive (memaddr, info);
     -	  break;
     -	case 0x10:  	    /* shift */
     -	case 0x11:  	    /* shift */
     -	case 0x12:  	    /* shift */
     -	case 0x13:  	    /* shift */
     -	case 0x14:  	    /* shift */
     -	case 0x15:  	    /* shift */
     -	case 0x16:  	    /* shift */
     -	case 0x17:  	    /* shift */
     -	  status = print_insn_shift (memaddr, info, byte);
     -	  break;
     -	case 0x04:  	    /* psh / pul */
     -	  {
     -	    read_memory (memaddr, &byte, 1, info);
     -	    (*info->fprintf_func) (info->stream, (byte & 0x80) ? "pul" : "psh");
     -	    int bit;
     -	    if (byte & 0x40)
     -	      {
     -		if ((byte & 0x3F) == 0)
     -		  {
     -		    operand_separator (info);
     -		    (*info->fprintf_func) (info->stream, "%s", "ALL16b");
     -		  }
     -		else
     -		  for (bit = 5; bit >= 0; --bit)
     -		    {
     -		      if (byte & (0x1 << bit))
     -			{
     -			  operand_separator (info);
     -			  (*info->fprintf_func) (info->stream, "%s", oprregs2[bit]);
     -			}
     -		    }
     -	      }
     -	    else
     -	      {
     -		if ((byte & 0x3F) == 0)
     -		  {
     -		    operand_separator (info);
     -		    (*info->fprintf_func) (info->stream, "%s", "ALL");
     -		  }
     -		else
     -		  for (bit = 5; bit >= 0; --bit)
     -		    {
     -		      if (byte & (0x1 << bit))
     -			{
     -			  operand_separator (info);
     -			  (*info->fprintf_func) (info->stream, "%s", oprregs1[bit]);
     -			}
     -		    }
     -	      }
     -	  }
     -	  break;
     -	default:
     -	  operand_separator (info);
     -	  (*info->fprintf_func) (info->stream, "???");
     -	  break;
     -	}
     -    }
     -
     -  if (opc2 == NULL)
     +  /* Ship out the operands.  */
     +  for (int o = 0; o < n_operands; ++o)
          {
     -      if (opc->operands)
     -	{
     -	  opc->operands (memaddr, info);
     -	}
     -
     -      if (opc->operands2)
     -	{
     -	  opc->operands2 (memaddr, info);
     -	}
     +      opr_emit_disassembly (operands[o], mra.info);
     +      free (operands[o]);
          }
      
     -  int n = 0;
     -
     -  /* Opcodes in page2 have an additional byte */
     -  if (opc2)
     -    n++;
     -
     -  if (opc2 && opc2->insn_bytes == 0)
     -    return n;
     -
     -  if (!opc2 && opc->insn_bytes == 0)
     -    return n;
     -
     -  if (opc2)
     -    n += opc2->insn_bytes (memaddr, info);
     -  else
     -    n += opc->insn_bytes (memaddr, info);
     -
     -  return n;
     +  return n_bytes;
      }
     diff --git a/opcodes/s12z-opc.c b/opcodes/s12z-opc.c
     new file mode 100644
     index 0000000000..36509b58dc
     --- /dev/null
     +++ b/opcodes/s12z-opc.c
     @@ -0,0 +1,2701 @@
     +/* s12z-decode.c -- Freescale S12Z disassembly
     +   Copyright (C) 2018 Free Software Foundation, Inc.
     +
     +   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 <stdio.h>
     +#include <stdint.h>
     +#include <stdbool.h>
     +#include <assert.h>
     +
     +#include "opcode/s12z.h"
     +
     +#include "bfd.h"
     +
     +#include "s12z-opc.h"
     +
     +
     +typedef int (* insn_bytes_f) (struct mem_read_abstraction_base *);
     +
     +typedef void (*operands_f) (struct mem_read_abstraction_base *,
     +			    int *n_operands, struct operand **operand);
     +
     +typedef enum operator (*discriminator_f) (struct mem_read_abstraction_base *,
     +					  enum operator hint);
     +
     +enum OPR_MODE
     +  {
     +    OPR_IMMe4,
     +    OPR_REG,
     +    OPR_OFXYS,
     +    OPR_XY_PRE_INC,
     +    OPR_XY_POST_INC,
     +    OPR_XY_PRE_DEC,
     +    OPR_XY_POST_DEC,
     +    OPR_S_PRE_DEC,
     +    OPR_S_POST_INC,
     +    OPR_REG_DIRECT,
     +    OPR_REG_INDIRECT,
     +    OPR_IDX_DIRECT,
     +    OPR_IDX_INDIRECT,
     +    OPR_EXT1,
     +    OPR_IDX2_REG,
     +    OPR_IDX3_DIRECT,
     +    OPR_IDX3_INDIRECT,
     +
     +    OPR_EXT18,
     +    OPR_IDX3_DIRECT_REG,
     +    OPR_EXT3_DIRECT,
     +    OPR_EXT3_INDIRECT
     +  };
     +
     +struct opr_pb
     +{
     +  uint8_t mask;
     +  uint8_t value;
     +  int n_operands;
     +  enum OPR_MODE mode;
     +};
     +
     +static const  struct opr_pb opr_pb[] = {
     +  {0xF0, 0x70, 1, OPR_IMMe4},
     +  {0xF8, 0xB8, 1, OPR_REG},
     +  {0xC0, 0x40, 1, OPR_OFXYS},
     +  {0xEF, 0xE3, 1, OPR_XY_PRE_INC},
     +  {0xEF, 0xE7, 1, OPR_XY_POST_INC},
     +  {0xEF, 0xC3, 1, OPR_XY_PRE_DEC},
     +  {0xEF, 0xC7, 1, OPR_XY_POST_DEC},
     +  {0xFF, 0xFB, 1, OPR_S_PRE_DEC},
     +  {0xFF, 0xFF, 1, OPR_S_POST_INC},
     +  {0xC8, 0x88, 1, OPR_REG_DIRECT},
     +  {0xE8, 0xC8, 1, OPR_REG_INDIRECT},
     +
     +  {0xCE, 0xC0, 2, OPR_IDX_DIRECT},
     +  {0xCE, 0xC4, 2, OPR_IDX_INDIRECT},
     +  {0xC0, 0x00, 2, OPR_EXT1},
     +
     +  {0xC8, 0x80, 3, OPR_IDX2_REG},
     +  {0xFA, 0xF8, 3, OPR_EXT18},
     +
     +  {0xCF, 0xC2, 4, OPR_IDX3_DIRECT},
     +  {0xCF, 0xC6, 4, OPR_IDX3_INDIRECT},
     +
     +  {0xF8, 0xE8, 4, OPR_IDX3_DIRECT_REG},
     +  {0xFF, 0xFA, 4, OPR_EXT3_DIRECT},
     +  {0xFF, 0xFE, 4, OPR_EXT3_INDIRECT},
     +};
     +
     +/* Return the number of bytes in a OPR operand, including the XB postbyte.
     +   It does not include any preceeding opcodes. */
     +static int
     +x_opr_n_bytes (struct mem_read_abstraction_base *mra, int offset)
     +{
     +  bfd_byte xb;
     +  int status = mra->read (mra, offset, 1, &xb);
     +  if (status < 0)
     +    return status;
     +
     +  size_t i;
     +  for (i = 0; i < sizeof (opr_pb) / sizeof (opr_pb[0]); ++i)
     +    {
     +      const struct opr_pb *pb = opr_pb + i;
     +      if ((xb & pb->mask) == pb->value)
     +	{
     +	  return pb->n_operands;
     +	}
     +    }
     +
     +  return 1;
     +}
     +
     +static int
     +opr_n_bytes_p1 (struct mem_read_abstraction_base *mra)
     +{
     +  return 1 + x_opr_n_bytes (mra, 0);
     +}
     +
     +static int
     +opr_n_bytes2 (struct mem_read_abstraction_base *mra)
     +{
     +  int s = x_opr_n_bytes (mra, 0);
     +  s += x_opr_n_bytes (mra, s);
     +  return s + 1;
     +}
     +
     +enum BB_MODE
     +  {
     +    BB_REG_REG_REG,
     +    BB_REG_REG_IMM,
     +    BB_REG_OPR_REG,
     +    BB_OPR_REG_REG,
     +    BB_REG_OPR_IMM,
     +    BB_OPR_REG_IMM
     +  };
     +
     +struct opr_bb
     +{
     +  uint8_t mask;
     +  uint8_t value;
     +  int n_operands;
     +  bool opr;
     +  enum BB_MODE mode;
     +};
     +
     +static const struct opr_bb bb_modes[] =
     +  {
     +    {0x60, 0x00, 2, false, BB_REG_REG_REG},
     +    {0x60, 0x20, 3, false, BB_REG_REG_IMM},
     +    {0x70, 0x40, 2, true,  BB_REG_OPR_REG},
     +    {0x70, 0x50, 2, true,  BB_OPR_REG_REG},
     +    {0x70, 0x60, 3, true,  BB_REG_OPR_IMM},
     +    {0x70, 0x70, 3, true,  BB_OPR_REG_IMM}
     +  };
     +
     +static int
     +bfextins_n_bytes (struct mem_read_abstraction_base *mra)
     +{
     +  bfd_byte bb;
     +  int status = mra->read (mra, 0, 1, &bb);
     +  if (status < 0)
     +    return status;
     +
     +  size_t i;
     +  const struct opr_bb *bbs = 0;
     +  for (i = 0; i < sizeof (bb_modes) / sizeof (bb_modes[0]); ++i)
     +    {
     +      bbs = bb_modes + i;
     +      if ((bb & bbs->mask) == bbs->value)
     +	{
     +	  break;
     +	}
     +    }
     +
     +  int n = bbs->n_operands;
     +  if (bbs->opr)
     +    n += x_opr_n_bytes (mra, n - 1);
     +
     +  return n;
     +}
     +
     +static int
     +single (struct mem_read_abstraction_base *mra ATTRIBUTE_UNUSED)
     +{
     +  return 1;
     +}
     +
     +static int
     +two (struct mem_read_abstraction_base *mra ATTRIBUTE_UNUSED)
     +{
     +  return 2;
     +}
     +
     +static int
     +three (struct mem_read_abstraction_base *mra ATTRIBUTE_UNUSED)
     +{
     +  return 3;
     +}
     +
     +static int
     +four (struct mem_read_abstraction_base *mra ATTRIBUTE_UNUSED)
     +{
     +  return 4;
     +}
     +
     +static int
     +five (struct mem_read_abstraction_base *mra ATTRIBUTE_UNUSED)
     +{
     +  return 5;
     +}
     +
     +static int
     +pcrel_15bit (struct mem_read_abstraction_base *mra)
     +{
     +  bfd_byte byte;
     +  int status = mra->read (mra, 0, 1, &byte);
     +  if (status < 0)
     +    return status;
     +  return (byte & 0x80) ? 3 : 2;
     +}
     +
     +
     +
     +static int
     +xysp_reg_from_postbyte (uint8_t postbyte)
     +{
     +  int reg = -1;
     +  switch ((postbyte & 0x30) >> 4)
     +    {
     +    case 0:
     +      reg = REG_X;
     +      break;
     +    case 1:
     +      reg = REG_Y;
     +      break;
     +    case 2:
     +      reg = REG_S;
     +      break;
     +    default:
     +      reg = REG_P;
     +    }
     +  return reg;
     +}
     +
     +static struct operand * create_immediate_operand (int value)
     +{
     +  struct immediate_operand *op = malloc (sizeof (*op));
     +
     +  ((struct operand *)op)->cl = OPND_CL_IMMEDIATE;
     +  op->value = value;
     +  ((struct operand *)op)->osize = -1;
     +
     +  return (struct operand *) op;
     +}
     +
     +static struct operand * create_bitfield_operand (int width, int offset)
     +{
     +  struct bitfield_operand *op = malloc (sizeof (*op));
     +
     +  ((struct operand *)op)->cl = OPND_CL_BIT_FIELD;
     +  op->width = width;
     +  op->offset = offset;
     +  ((struct operand *)op)->osize = -1;
     +
     +  return (struct operand *) op;
     +}
     +
     +static struct operand *
     +create_register_operand_with_size (int reg, short osize)
     +{
     +  struct register_operand *op = malloc (sizeof (*op));
     +
     +  ((struct operand *)op)->cl = OPND_CL_REGISTER;
     +  op->reg = reg;
     +  ((struct operand *)op)->osize = osize;
     +
     +  return (struct operand *) op;
     +}
     +
     +static struct operand *
     +create_register_operand (int reg)
     +{
     +  return create_register_operand_with_size (reg, -1);
     +}
     +
     +static struct operand * create_register_all_operand (void)
     +{
     +  struct register_operand *op = malloc (sizeof (*op));
     +
     +  ((struct operand *)op)->cl = OPND_CL_REGISTER_ALL;
     +  ((struct operand *)op)->osize = -1;
     +
     +  return (struct operand *) op;
     +}
     +
     +static struct operand * create_register_all16_operand (void)
     +{
     +  struct register_operand *op = malloc (sizeof (*op));
     +
     +  ((struct operand *)op)->cl = OPND_CL_REGISTER_ALL16;
     +  ((struct operand *)op)->osize = -1;
     +
     +  return (struct operand *) op;
     +}
     +
     +
     +static struct operand *
     +create_simple_memory_operand (bfd_vma addr, bfd_vma base, bool relative)
     +{
     +  struct simple_memory_operand *op = malloc (sizeof (*op));
     +
     +  ((struct operand *)op)->cl = OPND_CL_SIMPLE_MEMORY;
     +  op->addr = addr;
     +  op->base = base;
     +  op->relative = relative;
     +  ((struct operand *)op)->osize = -1;
     +
     +  assert (relative || base == 0);
     +
     +  return (struct operand *) op;
     +}
     +
     +static struct operand *
     +create_memory_operand (bool indirect, int base, int n_regs, int reg0, int reg1)
     +{
     +  struct memory_operand *op = malloc (sizeof (*op));
     +
     +  ((struct operand *)op)->cl = OPND_CL_MEMORY;
     +  op->indirect = indirect;
     +  op->base_offset = base;
     +  op->mutation = OPND_RM_NONE;
     +  op->n_regs = n_regs;
     +  op->regs[0] = reg0;
     +  op->regs[1] = reg1;
     +  ((struct operand *)op)->osize = -1;
     +
     +  return (struct operand *) op;
     +}
     +
     +static struct operand *
     +create_memory_auto_operand (enum op_reg_mutation mutation, int reg)
     +{
     +  struct memory_operand *op = malloc (sizeof (*op));
     +
     +  ((struct operand *)op)->cl = OPND_CL_MEMORY;
     +  op->indirect = false;
     +  op->base_offset = 0;
     +  op->mutation = mutation;
     +  op->n_regs = 1;
     +  op->regs[0] = reg;
     +  op->regs[1] = -1;
     +  ((struct operand *)op)->osize = -1;
     +
     +  return (struct operand *) op;
     +}
     +
     +
     +
     +static void
     +z_ext24_decode (struct mem_read_abstraction_base *mra, int *n_operands, struct operand **operand)
     +{
     +  uint8_t buffer[3];
     +  int status = mra->read (mra, 0, 3, buffer);
     +  if (status < 0)
     +    return;
     +
     +  int i;
     +  uint32_t addr = 0;
     +  for (i = 0; i < 3; ++i)
     +    {
     +      addr <<= 8;
     +      addr |= buffer[i];
     +    }
     +
     +  operand[(*n_operands)++] = create_simple_memory_operand (addr, 0, false);
     +}
     +
     +
     +static uint32_t
     +z_decode_signed_value (struct mem_read_abstraction_base *mra, int offset, short size)
     +{
     +  assert (size >0);
     +  assert (size <= 4);
     +  bfd_byte buffer[4];
     +  if (0 > mra->read (mra, offset, size, buffer))
     +    {
     +      return 0;
     +    }
     +
     +  int i;
     +  uint32_t value = 0;
     +  for (i = 0; i < size; ++i)
     +    {
     +      value |= buffer[i] << (8 * (size - i - 1));
     +    }
     +
     +  if (buffer[0] & 0x80)
     +    {
     +      /* Deal with negative values */
     +      value -= 0x1UL << (size * 8);
     +    }
     +  return value;
     +}
     +
     +static uint32_t
     +decode_signed_value (struct mem_read_abstraction_base *mra, short size)
     +{
     +  return z_decode_signed_value (mra, 0, size);
     +}
     +
     +static void
     +x_imm1 (struct mem_read_abstraction_base *mra,
     +	int offset,
     +	int *n_operands, struct operand **operand)
     +{
     +  bfd_byte byte;
     +  int status = mra->read (mra, offset, 1, &byte);
     +  if (status < 0)
     +    return;
     +
     +  operand[(*n_operands)++] = create_immediate_operand (byte);
     +}
     +
     +/* An eight bit immediate operand.  */
     +static void
     +imm1_decode (struct mem_read_abstraction_base *mra,
     +	int *n_operands, struct operand **operand)
     +{
     +  x_imm1 (mra, 0, n_operands, operand);
     +}
     +
     +static void
     +trap_decode (struct mem_read_abstraction_base *mra,
     +	     int *n_operands, struct operand **operand)
     +{
     +  x_imm1 (mra, -1, n_operands, operand);
     +}
     +
     +
     +static struct operand *
     +x_opr_decode_with_size (struct mem_read_abstraction_base *mra, int offset,
     +			short osize)
     +{
     +  bfd_byte postbyte;
     +  int status = mra->read (mra, offset, 1, &postbyte);
     +  if (status < 0)
     +    return NULL;
     +  offset++;
     +
     +  enum OPR_MODE mode = -1;
     +  size_t i;
     +  for (i = 0; i < sizeof (opr_pb) / sizeof (opr_pb[0]); ++i)
     +    {
     +      const struct opr_pb *pb = opr_pb + i;
     +      if ((postbyte & pb->mask) == pb->value)
     +	{
     +	  mode = pb->mode;
     +	  break;
     +	}
     +    }
     +
     +  struct operand *operand = NULL;
     +  switch (mode)
     +    {
     +    case OPR_IMMe4:
     +      {
     +	int n;
     +	uint8_t x = (postbyte & 0x0F);
     +	if (x == 0)
     +	  n = -1;
     +	else
     +	  n = x;
     +
     +        operand = create_immediate_operand (n);
     +	break;
     +      }
     +    case OPR_REG:
     +      {
     +	uint8_t x = (postbyte & 0x07);
     +        operand = create_register_operand (x);
     +	break;
     +      }
     +    case OPR_OFXYS:
     +      {
     +        operand = create_memory_operand (false, postbyte & 0x0F, 1,
     +					 xysp_reg_from_postbyte (postbyte), -1);
     +	break;
     +      }
     +    case OPR_REG_DIRECT:
     +      {
     +        operand = create_memory_operand (false, 0, 2, postbyte & 0x07,
     +					 xysp_reg_from_postbyte (postbyte));
     +	break;
     +      }
     +    case OPR_REG_INDIRECT:
     +      {
     +        operand = create_memory_operand (true, 0, 2, postbyte & 0x07,
     +					 (postbyte & 0x10) ? REG_Y : REG_X);
     +	break;
     +      }
     +
     +    case OPR_IDX_INDIRECT:
     +      {
     +	uint8_t x1;
     +	mra->read (mra, offset, 1, &x1);
     +	int idx = x1;
     +
     +	if (postbyte & 0x01)
     +	  {
     +	    /* Deal with negative values */
     +	    idx -= 0x1UL << 8;
     +	  }
     +
     +        operand = create_memory_operand (true, idx, 1,
     +					 xysp_reg_from_postbyte (postbyte), -1);
     +	break;
     +      }
     +
     +    case OPR_IDX3_DIRECT:
     +      {
     +	uint8_t x[3];
     +	mra->read (mra, offset, 3, x);
     +	int idx = x[0] << 16 | x[1] << 8 | x[2];
     +
     +	if (x[0] & 0x80)
     +	  {
     +	    /* Deal with negative values */
     +	    idx -= 0x1UL << 24;
     +	  }
     +
     +        operand = create_memory_operand (false, idx, 1,
     +					 xysp_reg_from_postbyte (postbyte), -1);
     +	break;
     +      }
     +
     +    case OPR_IDX3_DIRECT_REG:
     +      {
     +	uint8_t x[3];
     +	mra->read (mra, offset, 3, x);
     +	int idx = x[0] << 16 | x[1] << 8 | x[2];
     +
     +	if (x[0] & 0x80)
     +	  {
     +	    /* Deal with negative values */
     +	    idx -= 0x1UL << 24;
     +	  }
     +
     +        operand = create_memory_operand (false, idx, 1, postbyte & 0x07, -1);
     +	break;
     +      }
     +
     +    case OPR_IDX3_INDIRECT:
     +      {
     +	uint8_t x[3];
     +	mra->read (mra, offset, 3, x);
     +	int idx = x[0] << 16 | x[1] << 8 | x[2];
     +
     +	if (x[0] & 0x80)
     +	  {
     +	    /* Deal with negative values */
     +	    idx -= 0x1UL << 24;
     +	  }
     +
     +	operand = create_memory_operand (true, idx, 1,
     +					 xysp_reg_from_postbyte (postbyte), -1);
     +	break;
     +      }
     +
     +    case OPR_IDX_DIRECT:
     +      {
     +	uint8_t x1;
     +	mra->read (mra, offset, 1, &x1);
     +	int idx = x1;
     +
     +	if (postbyte & 0x01)
     +	  {
     +	    /* Deal with negative values */
     +	    idx -= 0x1UL << 8;
     +	  }
     +
     +        operand = create_memory_operand (false, idx, 1,
     +					 xysp_reg_from_postbyte (postbyte), -1);
     +	break;
     +      }
     +
     +    case OPR_IDX2_REG:
     +      {
     +	uint8_t x[2];
     +	mra->read (mra, offset, 2, x);
     +	uint32_t idx = x[1] | x[0] << 8 ;
     +	idx |= (postbyte & 0x30) << 12;
     +
     +        operand = create_memory_operand (false, idx, 1, postbyte & 0x07, -1);
     +	break;
     +      }
     +
     +    case OPR_XY_PRE_INC:
     +      {
     +	operand = create_memory_auto_operand (OPND_RM_PRE_INC,
     +					      (postbyte & 0x10) ? REG_Y: REG_X);
     +	break;
     +      }
     +    case OPR_XY_POST_INC:
     +      {
     +	operand = create_memory_auto_operand (OPND_RM_POST_INC,
     +					      (postbyte & 0x10) ? REG_Y: REG_X);
     +	break;
     +      }
     +    case OPR_XY_PRE_DEC:
     +      {
     +	operand = create_memory_auto_operand (OPND_RM_PRE_DEC,
     +					      (postbyte & 0x10) ? REG_Y: REG_X);
     +	break;
     +      }
     +    case OPR_XY_POST_DEC:
     +      {
     +	operand = create_memory_auto_operand (OPND_RM_POST_DEC,
     +					      (postbyte & 0x10) ? REG_Y: REG_X);
     +	break;
     +      }
     +    case OPR_S_PRE_DEC:
     +      {
     +	operand = create_memory_auto_operand (OPND_RM_PRE_DEC, REG_S);
     +	break;
     +      }
     +    case OPR_S_POST_INC:
     +      {
     +	operand = create_memory_auto_operand (OPND_RM_POST_INC, REG_S);
     +	break;
     +      }
     +
     +    case OPR_EXT18:
     +      {
     +	const size_t size = 2;
     +	bfd_byte buffer[4];
     +	status = mra->read (mra, offset, size, buffer);
     +	if (status < 0)
     +	  operand = NULL;
     +
     +	uint32_t ext18 = 0;
     +	for (i = 0; i < size; ++i)
     +	  {
     +	    ext18 <<= 8;
     +	    ext18 |= buffer[i];
     +	  }
     +
     +	ext18 |= (postbyte & 0x01) << 16;
     +	ext18 |= (postbyte & 0x04) << 15;
     +
     +	operand = create_simple_memory_operand (ext18, 0, false);
     +	break;
     +      }
     +
     +    case OPR_EXT1:
     +      {
     +	uint8_t x1 = 0;
     +	mra->read (mra, offset, 1, &x1);
     +	int16_t addr;
     +	addr = x1;
     +	addr |= (postbyte & 0x3f) << 8;
     +
     +	operand = create_simple_memory_operand (addr, 0, false);
     +	break;
     +      }
     +
     +    case OPR_EXT3_DIRECT:
     +      {
     +	const size_t size = 3;
     +	bfd_byte buffer[4];
     +	status = mra->read (mra, offset, size, buffer);
     +	if (status < 0)
     +	  operand = NULL;
     +
     +	uint32_t ext24 = 0;
     +	for (i = 0; i < size; ++i)
     +	  {
     +	    ext24 |= buffer[i] << (8 * (size - i - 1));
     +	  }
     +
     +	operand = create_simple_memory_operand (ext24, 0, false);
     +	break;
     +      }
     +
     +    case OPR_EXT3_INDIRECT:
     +      {
     +	const size_t size = 3;
     +	bfd_byte buffer[4];
     +	status = mra->read (mra, offset, size, buffer);
     +	if (status < 0)
     +	  operand = NULL;
     +
     +	uint32_t ext24 = 0;
     +	for (i = 0; i < size; ++i)
     +	  {
     +	    ext24 |= buffer[i] << (8 * (size - i - 1));
     +	  }
     +
     +        operand = create_memory_operand (true, ext24, 0, -1, -1);
     +	break;
     +      }
     +
     +    default:
     +      printf ("Unknown OPR mode #0x%x (%d)", postbyte, mode);
     +      abort ();
     +    }
     +
     +  operand->osize = osize;
     +
     +  return operand;
     +}
     +
     +static struct operand *
     +x_opr_decode (struct mem_read_abstraction_base *mra, int offset)
     +{
     +  return x_opr_decode_with_size (mra, offset, -1);
     +}
     +
     +static void
     +z_opr_decode (struct mem_read_abstraction_base *mra,
     +	      int *n_operands, struct operand **operand)
     +{
     +  operand[(*n_operands)++] = x_opr_decode (mra, 0);
     +}
     +
     +static void
     +z_opr_decode2 (struct mem_read_abstraction_base *mra,
     +	       int *n_operands, struct operand **operand)
     +{
     +  int n = x_opr_n_bytes (mra, 0);
     +
     +  operand[(*n_operands)++] = x_opr_decode (mra, 0);
     +  operand[(*n_operands)++] = x_opr_decode (mra, n);
     +}
     +
     +static void
     +imm1234 (struct mem_read_abstraction_base *mra, int base,
     +	 int *n_operands, struct operand **operand)
     +{
     +  bfd_byte opcode;
     +  int status = mra->read (mra, -1, 1, &opcode);
     +  if (status < 0)
     +    return;
     +
     +  opcode -= base;
     +
     +  int size = registers[opcode & 0xF].bytes;
     +
     +  uint32_t imm = decode_signed_value (mra, size);
     +
     +  operand[(*n_operands)++] = create_immediate_operand (imm);
     +}
     +
     +
     +/* Special case of LD and CMP with register S and IMM operand */
     +static void
     +reg_s_imm (struct mem_read_abstraction_base *mra, int *n_operands,
     +	   struct operand **operand)
     +{
     +  operand[(*n_operands)++] = create_register_operand (REG_S);
     +
     +  uint32_t imm = decode_signed_value (mra, 3);
     +  operand[(*n_operands)++] = create_immediate_operand (imm);
     +}
     +
     +/* Special case of LD, CMP and ST with register S and OPR operand */
     +static void
     +reg_s_opr (struct mem_read_abstraction_base *mra, int *n_operands,
     +	   struct operand **operand)
     +{
     +  operand[(*n_operands)++] = create_register_operand (REG_S);
     +  operand[(*n_operands)++] = x_opr_decode (mra, 0);
     +}
     +
     +static void
     +z_imm1234_8base (struct mem_read_abstraction_base *mra, int *n_operands,
     +		 struct operand **operand)
     +{
     +  imm1234 (mra, 8, n_operands, operand);
     +}
     +
     +static void
     +z_imm1234_0base (struct mem_read_abstraction_base *mra, int *n_operands,
     +		 struct operand **operand)
     +{
     +  imm1234 (mra, 0, n_operands, operand);
     +}
     +
     +
     +static void
     +z_tfr (struct mem_read_abstraction_base *mra, int *n_operands,
     +       struct operand **operand)
     +{
     +  bfd_byte byte;
     +  int status = mra->read (mra, 0, 1, &byte);
     +  if (status < 0)
     +    return;
     +
     +  operand[(*n_operands)++] = create_register_operand (byte >> 4);
     +  operand[(*n_operands)++] = create_register_operand (byte & 0x0F);
     +}
     +
     +static void
     +z_reg (struct mem_read_abstraction_base *mra, int *n_operands,
     +       struct operand **operand)
     +{
     +  bfd_byte byte;
     +  int status = mra->read (mra, -1, 1, &byte);
     +  if (status < 0)
     +    return;
     +
     +  operand[(*n_operands)++] = create_register_operand (byte & 0x07);
     +}
     +
     +
     +static void
     +reg_xy (struct mem_read_abstraction_base *mra,
     +	int *n_operands, struct operand **operand)
     +{
     +  bfd_byte byte;
     +  int status = mra->read (mra, -1, 1, &byte);
     +  if (status < 0)
     +    return;
     +
     +  operand[(*n_operands)++] =
     +    create_register_operand ((byte & 0x01) ? REG_Y : REG_X);
     +}
     +
     +static void
     +lea_reg_xys_opr (struct mem_read_abstraction_base *mra,
     +		 int *n_operands, struct operand **operand)
     +{
     +  bfd_byte byte;
     +  int status = mra->read (mra, -1, 1, &byte);
     +  if (status < 0)
     +    return;
     +
     +  int reg_xys = -1;
     +  switch (byte & 0x03)
     +    {
     +    case 0x00:
     +      reg_xys = REG_X;
     +      break;
     +    case 0x01:
     +      reg_xys = REG_Y;
     +      break;
     +    case 0x02:
     +      reg_xys = REG_S;
     +      break;
     +    }
     +
     +  operand[(*n_operands)++] = create_register_operand (reg_xys);
     +  operand[(*n_operands)++] = x_opr_decode (mra, 0);
     +}
     +
     +static void
     +lea_reg_xys (struct mem_read_abstraction_base *mra,
     +	     int *n_operands, struct operand **operand)
     +{
     +  bfd_byte byte;
     +  int status = mra->read (mra, -1, 1, &byte);
     +  if (status < 0)
     +    return;
     +
     +  int reg_n = -1;
     +  switch (byte & 0x03)
     +    {
     +    case 0x00:
     +      reg_n = REG_X;
     +      break;
     +    case 0x01:
     +      reg_n = REG_Y;
     +      break;
     +    case 0x02:
     +      reg_n = REG_S;
     +      break;
     +    }
     +
     +  status = mra->read (mra, 0, 1, &byte);
     +  if (status < 0)
     +    return;
     +
     +  operand[(*n_operands)++] = create_register_operand (reg_n);
     +  operand[(*n_operands)++] = create_memory_operand (false, (int8_t) byte,
     +						    1, reg_n, -1);
     +}
     +
     +
     +/* PC Relative offsets of size 15 or 7 bits */
     +static void
     +rel_15_7 (struct mem_read_abstraction_base *mra, int offset,
     +	  int *n_operands, struct operand **operands)
     +{
     +  bfd_byte upper;
     +  int status = mra->read (mra, offset - 1, 1, &upper);
     +  if (status < 0)
     +    return;
     +
     +  bool rel_size = (upper & 0x80);
     +
     +  int16_t addr = upper;
     +  if (rel_size)
     +    {
     +      /* 15 bits.  Get the next byte */
     +      bfd_byte lower;
     +      status = mra->read (mra, offset, 1, &lower);
     +      if (status < 0)
     +	return;
     +
     +      addr <<= 8;
     +      addr |= lower;
     +      addr &= 0x7FFF;
     +
     +      bool negative = (addr & 0x4000);
     +      addr &= 0x3FFF;
     +      if (negative)
     +	addr = addr - 0x4000;
     +    }
     +  else
     +    {
     +      /* 7 bits. */
     +      bool negative = (addr & 0x40);
     +      addr &= 0x3F;
     +      if (negative)
     +	addr = addr - 0x40;
     +    }
     +
     +  operands[(*n_operands)++] =
     +    create_simple_memory_operand (addr, mra->posn (mra) - 1, true);
     +}
     +
     +
     +/* PC Relative offsets of size 15 or 7 bits */
     +static void
     +decode_rel_15_7 (struct mem_read_abstraction_base *mra,
     +		 int *n_operands, struct operand **operand)
     +{
     +  rel_15_7 (mra, 1, n_operands, operand);
     +}
     +
     +static int shift_n_bytes (struct mem_read_abstraction_base *);
     +static int mov_imm_opr_n_bytes (struct mem_read_abstraction_base *);
     +static int loop_prim_n_bytes (struct mem_read_abstraction_base *);
     +static int bm_rel_n_bytes (struct mem_read_abstraction_base *);
     +static int mul_n_bytes (struct mem_read_abstraction_base *);
     +static int bm_n_bytes (struct mem_read_abstraction_base *);
     +
     +static void psh_pul_decode (struct mem_read_abstraction_base *mra, int *n_operands, struct operand **operand);
     +static void shift_decode (struct mem_read_abstraction_base *mra, int *n_operands, struct operand **operand);
     +static void mul_decode (struct mem_read_abstraction_base *mra, int *n_operands, struct operand **operand);
     +static void bm_decode (struct mem_read_abstraction_base *mra, int *n_operands, struct operand **operand);
     +static void bm_rel_decode (struct mem_read_abstraction_base *mra, int *n_operands, struct operand **operand);
     +static void mov_imm_opr (struct mem_read_abstraction_base *mra, int *n_operands, struct operand **operand);
     +static void loop_primitive_decode (struct mem_read_abstraction_base *mra, int *n_operands, struct operand **operands);
     +static void bit_field_decode (struct mem_read_abstraction_base *mra, int *n_operands, struct operand **operands);
     +static void exg_sex_decode (struct mem_read_abstraction_base *mra, int *n_operands, struct operand **operands);
     +
     +
     +static enum operator shift_discrim (struct mem_read_abstraction_base *mra, enum operator hint);
     +static enum operator psh_pul_discrim (struct mem_read_abstraction_base *mra, enum operator hint);
     +static enum operator mul_discrim (struct mem_read_abstraction_base *mra, enum operator hint);
     +static enum operator loop_primitive_discrim (struct mem_read_abstraction_base *mra, enum operator hint);
     +static enum operator bit_field_discrim (struct mem_read_abstraction_base *mra, enum operator hint);
     +static enum operator exg_sex_discrim (struct mem_read_abstraction_base *mra, enum operator hint);
     +
     +
     +static void
     +cmp_xy (struct mem_read_abstraction_base *mra ATTRIBUTE_UNUSED,
     +	int *n_operands, struct operand **operand)
     +{
     +  operand[(*n_operands)++] = create_register_operand (REG_X);
     +  operand[(*n_operands)++] = create_register_operand (REG_Y);
     +}
     +
     +static void
     +sub_d6_x_y (struct mem_read_abstraction_base *mra ATTRIBUTE_UNUSED,
     +	    int *n_operands, struct operand **operand)
     +{
     +  operand[(*n_operands)++] = create_register_operand (REG_D6);
     +  operand[(*n_operands)++] = create_register_operand (REG_X);
     +  operand[(*n_operands)++] = create_register_operand (REG_Y);
     +}
     +
     +static void
     +sub_d6_y_x (struct mem_read_abstraction_base *mra ATTRIBUTE_UNUSED,
     +	    int *n_operands, struct operand **operand)
     +{
     +  operand[(*n_operands)++] = create_register_operand (REG_D6);
     +  operand[(*n_operands)++] = create_register_operand (REG_Y);
     +  operand[(*n_operands)++] = create_register_operand (REG_X);
     +}
     +
     +static void ld_18bit_decode (struct mem_read_abstraction_base *mra, int *n_operands, struct operand **operand);
     +
     +static enum operator
     +mul_discrim (struct mem_read_abstraction_base *mra, enum operator hint)
     +{
     +  uint8_t mb;
     +  int status = mra->read (mra, 0, 1, &mb);
     +  if (status < 0)
     +    return OP_INVALID;
     +
     +  bool signed_op = (mb & 0x80);
     +
     +  switch (hint)
     +    {
     +    case OPBASE_mul:
     +      return signed_op ? OP_muls : OP_mulu;
     +      break;
     +    case OPBASE_div:
     +      return signed_op ? OP_divs : OP_divu;
     +      break;
     +    case OPBASE_mod:
     +      return signed_op ? OP_mods : OP_modu;
     +      break;
     +    case OPBASE_mac:
     +      return signed_op ? OP_macs : OP_macu;
     +      break;
     +    case OPBASE_qmul:
     +      return signed_op ? OP_qmuls : OP_qmulu;
     +      break;
     +    default:
     +      abort ();
     +    }
     +
     +  return OP_INVALID;
     +}
     +
     +struct opcode
     +{
     +  /* The operation that this opcode performs.  */
     +  enum operator operator;
     +
     +  /* The size of this operation.  May be -1 if it is implied
     +     in the operands or if size is not applicable.  */
     +  short osize;
     +
     +  /* Some operations need this function to work out which operation
     +   is intended.  */
     +  discriminator_f discriminator;
     +
     +  /* A function returning the number of bytes in this instruction.  */
     +  insn_bytes_f insn_bytes;
     +
     +  operands_f operands;
     +  operands_f operands2;
     +};
     +
     +static const struct opcode page2[] =
     +  {
     +    [0x00] = {OP_ld, -1, 0,  opr_n_bytes_p1, reg_s_opr, 0},
     +    [0x01] = {OP_st, -1, 0,  opr_n_bytes_p1, reg_s_opr, 0},
     +    [0x02] = {OP_cmp, -1, 0, opr_n_bytes_p1, reg_s_opr, 0},
     +    [0x03] = {OP_ld, -1, 0,  four, reg_s_imm, 0},
     +    [0x04] = {OP_cmp, -1, 0, four, reg_s_imm, 0},
     +    [0x05] = {OP_stop, -1, 0, single, 0, 0},
     +    [0x06] = {OP_wai, -1, 0,  single, 0, 0},
     +    [0x07] = {OP_sys, -1, 0,  single, 0, 0},
     +    [0x08] = {0xFFFF, -1, bit_field_discrim,  bfextins_n_bytes, bit_field_decode, 0},  /* BFEXT / BFINS */
     +    [0x09] = {0xFFFF, -1, bit_field_discrim,  bfextins_n_bytes, bit_field_decode, 0},
     +    [0x0a] = {0xFFFF, -1, bit_field_discrim,  bfextins_n_bytes, bit_field_decode, 0},
     +    [0x0b] = {0xFFFF, -1, bit_field_discrim,  bfextins_n_bytes, bit_field_decode, 0},
     +    [0x0c] = {0xFFFF, -1, bit_field_discrim,  bfextins_n_bytes, bit_field_decode, 0},
     +    [0x0d] = {0xFFFF, -1, bit_field_discrim,  bfextins_n_bytes, bit_field_decode, 0},
     +    [0x0e] = {0xFFFF, -1, bit_field_discrim,  bfextins_n_bytes, bit_field_decode, 0},
     +    [0x0f] = {0xFFFF, -1, bit_field_discrim,  bfextins_n_bytes, bit_field_decode, 0},
     +    [0x10] = {OP_minu, -1, 0, opr_n_bytes_p1, z_reg, z_opr_decode},
     +    [0x11] = {OP_minu, -1, 0, opr_n_bytes_p1, z_reg, z_opr_decode},
     +    [0x12] = {OP_minu, -1, 0, opr_n_bytes_p1, z_reg, z_opr_decode},
     +    [0x13] = {OP_minu, -1, 0, opr_n_bytes_p1, z_reg, z_opr_decode},
     +    [0x14] = {OP_minu, -1, 0, opr_n_bytes_p1, z_reg, z_opr_decode},
     +    [0x15] = {OP_minu, -1, 0, opr_n_bytes_p1, z_reg, z_opr_decode},
     +    [0x16] = {OP_minu, -1, 0, opr_n_bytes_p1, z_reg, z_opr_decode},
     +    [0x17] = {OP_minu, -1, 0, opr_n_bytes_p1, z_reg, z_opr_decode},
     +    [0x18] = {OP_maxu, -1, 0, opr_n_bytes_p1, z_reg, z_opr_decode},
     +    [0x19] = {OP_maxu, -1, 0, opr_n_bytes_p1, z_reg, z_opr_decode},
     +    [0x1a] = {OP_maxu, -1, 0, opr_n_bytes_p1, z_reg, z_opr_decode},
     +    [0x1b] = {OP_maxu, -1, 0, opr_n_bytes_p1, z_reg, z_opr_decode},
     +    [0x1c] = {OP_maxu, -1, 0, opr_n_bytes_p1, z_reg, z_opr_decode},
     +    [0x1d] = {OP_maxu, -1, 0, opr_n_bytes_p1, z_reg, z_opr_decode},
     +    [0x1e] = {OP_maxu, -1, 0, opr_n_bytes_p1, z_reg, z_opr_decode},
     +    [0x1f] = {OP_maxu, -1, 0, opr_n_bytes_p1, z_reg, z_opr_decode},
     +    [0x20] = {OP_mins, -1, 0, opr_n_bytes_p1, z_reg, z_opr_decode},
     +    [0x21] = {OP_mins, -1, 0, opr_n_bytes_p1, z_reg, z_opr_decode},
     +    [0x22] = {OP_mins, -1, 0, opr_n_bytes_p1, z_reg, z_opr_decode},
     +    [0x23] = {OP_mins, -1, 0, opr_n_bytes_p1, z_reg, z_opr_decode},
     +    [0x24] = {OP_mins, -1, 0, opr_n_bytes_p1, z_reg, z_opr_decode},
     +    [0x25] = {OP_mins, -1, 0, opr_n_bytes_p1, z_reg, z_opr_decode},
     +    [0x26] = {OP_mins, -1, 0, opr_n_bytes_p1, z_reg, z_opr_decode},
     +    [0x27] = {OP_mins, -1, 0, opr_n_bytes_p1, z_reg, z_opr_decode},
     +    [0x28] = {OP_maxs, -1, 0, opr_n_bytes_p1, z_reg, z_opr_decode},
     +    [0x29] = {OP_maxs, -1, 0, opr_n_bytes_p1, z_reg, z_opr_decode},
     +    [0x2a] = {OP_maxs, -1, 0, opr_n_bytes_p1, z_reg, z_opr_decode},
     +    [0x2b] = {OP_maxs, -1, 0, opr_n_bytes_p1, z_reg, z_opr_decode},
     +    [0x2c] = {OP_maxs, -1, 0, opr_n_bytes_p1, z_reg, z_opr_decode},
     +    [0x2d] = {OP_maxs, -1, 0, opr_n_bytes_p1, z_reg, z_opr_decode},
     +    [0x2e] = {OP_maxs, -1, 0, opr_n_bytes_p1, z_reg, z_opr_decode},
     +    [0x2f] = {OP_maxs, -1, 0, opr_n_bytes_p1, z_reg, z_opr_decode},
     +    [0x30] = {OPBASE_div, -1, mul_discrim, mul_n_bytes, mul_decode, 0},
     +    [0x31] = {OPBASE_div, -1, mul_discrim, mul_n_bytes, mul_decode, 0},
     +    [0x32] = {OPBASE_div, -1, mul_discrim, mul_n_bytes, mul_decode, 0},
     +    [0x33] = {OPBASE_div, -1, mul_discrim, mul_n_bytes, mul_decode, 0},
     +    [0x34] = {OPBASE_div, -1, mul_discrim, mul_n_bytes, mul_decode, 0},
     +    [0x35] = {OPBASE_div, -1, mul_discrim, mul_n_bytes, mul_decode, 0},
     +    [0x36] = {OPBASE_div, -1, mul_discrim, mul_n_bytes, mul_decode, 0},
     +    [0x37] = {OPBASE_div, -1, mul_discrim, mul_n_bytes, mul_decode, 0},
     +    [0x38] = {OPBASE_mod, -1, mul_discrim, mul_n_bytes, mul_decode, 0},
     +    [0x39] = {OPBASE_mod, -1, mul_discrim, mul_n_bytes, mul_decode, 0},
     +    [0x3a] = {OPBASE_mod, -1, mul_discrim, mul_n_bytes, mul_decode, 0},
     +    [0x3b] = {OPBASE_mod, -1, mul_discrim, mul_n_bytes, mul_decode, 0},
     +    [0x3c] = {OPBASE_mod, -1, mul_discrim, mul_n_bytes, mul_decode, 0},
     +    [0x3d] = {OPBASE_mod, -1, mul_discrim, mul_n_bytes, mul_decode, 0},
     +    [0x3e] = {OPBASE_mod, -1, mul_discrim, mul_n_bytes, mul_decode, 0},
     +    [0x3f] = {OPBASE_mod, -1, mul_discrim, mul_n_bytes, mul_decode, 0},
     +    [0x40] = {OP_abs, -1, 0, single, z_reg, 0},
     +    [0x41] = {OP_abs, -1, 0, single, z_reg, 0},
     +    [0x42] = {OP_abs, -1, 0, single, z_reg, 0},
     +    [0x43] = {OP_abs, -1, 0, single, z_reg, 0},
     +    [0x44] = {OP_abs, -1, 0, single, z_reg, 0},
     +    [0x45] = {OP_abs, -1, 0, single, z_reg, 0},
     +    [0x46] = {OP_abs, -1, 0, single, z_reg, 0},
     +    [0x47] = {OP_abs, -1, 0, single, z_reg, 0},
     +    [0x48] = {OPBASE_mac, -1, mul_discrim, mul_n_bytes, mul_decode, 0},
     +    [0x49] = {OPBASE_mac, -1, mul_discrim, mul_n_bytes, mul_decode, 0},
     +    [0x4a] = {OPBASE_mac, -1, mul_discrim, mul_n_bytes, mul_decode, 0},
     +    [0x4b] = {OPBASE_mac, -1, mul_discrim, mul_n_bytes, mul_decode, 0},
     +    [0x4c] = {OPBASE_mac, -1, mul_discrim, mul_n_bytes, mul_decode, 0},
     +    [0x4d] = {OPBASE_mac, -1, mul_discrim, mul_n_bytes, mul_decode, 0},
     +    [0x4e] = {OPBASE_mac, -1, mul_discrim, mul_n_bytes, mul_decode, 0},
     +    [0x4f] = {OPBASE_mac, -1, mul_discrim, mul_n_bytes, mul_decode, 0},
     +    [0x50] = {OP_adc, -1, 0, three, z_reg, z_imm1234_0base},
     +    [0x51] = {OP_adc, -1, 0, three, z_reg, z_imm1234_0base},
     +    [0x52] = {OP_adc, -1, 0, three, z_reg, z_imm1234_0base},
     +    [0x53] = {OP_adc, -1, 0, three, z_reg, z_imm1234_0base},
     +    [0x54] = {OP_adc, -1, 0, two,   z_reg, z_imm1234_0base},
     +    [0x55] = {OP_adc, -1, 0, two,   z_reg, z_imm1234_0base},
     +    [0x56] = {OP_adc, -1, 0, five,  z_reg, z_imm1234_0base},
     +    [0x57] = {OP_adc, -1, 0, five,  z_reg, z_imm1234_0base},
     +    [0x58] = {OP_bit, -1, 0, three, z_reg, z_imm1234_8base},
     +    [0x59] = {OP_bit, -1, 0, three, z_reg, z_imm1234_8base},
     +    [0x5a] = {OP_bit, -1, 0, three, z_reg, z_imm1234_8base},
     +    [0x5b] = {OP_bit, -1, 0, three, z_reg, z_imm1234_8base},
     +    [0x5c] = {OP_bit, -1, 0, two,   z_reg, z_imm1234_8base},
     +    [0x5d] = {OP_bit, -1, 0, two,   z_reg, z_imm1234_8base},
     +    [0x5e] = {OP_bit, -1, 0, five,  z_reg, z_imm1234_8base},
     +    [0x5f] = {OP_bit, -1, 0, five,  z_reg, z_imm1234_8base},
     +    [0x60] = {OP_adc, -1, 0, opr_n_bytes_p1, z_reg, z_opr_decode},
     +    [0x61] = {OP_adc, -1, 0, opr_n_bytes_p1, z_reg, z_opr_decode},
     +    [0x62] = {OP_adc, -1, 0, opr_n_bytes_p1, z_reg, z_opr_decode},
     +    [0x63] = {OP_adc, -1, 0, opr_n_bytes_p1, z_reg, z_opr_decode},
     +    [0x64] = {OP_adc, -1, 0, opr_n_bytes_p1, z_reg, z_opr_decode},
     +    [0x65] = {OP_adc, -1, 0, opr_n_bytes_p1, z_reg, z_opr_decode},
     +    [0x66] = {OP_adc, -1, 0, opr_n_bytes_p1, z_reg, z_opr_decode},
     +    [0x67] = {OP_adc, -1, 0, opr_n_bytes_p1, z_reg, z_opr_decode},
     +    [0x68] = {OP_bit, -1, 0, opr_n_bytes_p1, z_reg, z_opr_decode},
     +    [0x69] = {OP_bit, -1, 0, opr_n_bytes_p1, z_reg, z_opr_decode},
     +    [0x6a] = {OP_bit, -1, 0, opr_n_bytes_p1, z_reg, z_opr_decode},
     +    [0x6b] = {OP_bit, -1, 0, opr_n_bytes_p1, z_reg, z_opr_decode},
     +    [0x6c] = {OP_bit, -1, 0, opr_n_bytes_p1, z_reg, z_opr_decode},
     +    [0x6d] = {OP_bit, -1, 0, opr_n_bytes_p1, z_reg, z_opr_decode},
     +    [0x6e] = {OP_bit, -1, 0, opr_n_bytes_p1, z_reg, z_opr_decode},
     +    [0x6f] = {OP_bit, -1, 0, opr_n_bytes_p1, z_reg, z_opr_decode},
     +    [0x70] = {OP_sbc, -1, 0, three, z_reg, z_imm1234_0base},
     +    [0x71] = {OP_sbc, -1, 0, three, z_reg, z_imm1234_0base},
     +    [0x72] = {OP_sbc, -1, 0, three, z_reg, z_imm1234_0base},
     +    [0x73] = {OP_sbc, -1, 0, three, z_reg, z_imm1234_0base},
     +    [0x74] = {OP_sbc, -1, 0, two,   z_reg, z_imm1234_0base},
     +    [0x75] = {OP_sbc, -1, 0, two,   z_reg, z_imm1234_0base},
     +    [0x76] = {OP_sbc, -1, 0, five,  z_reg, z_imm1234_0base},
     +    [0x77] = {OP_sbc, -1, 0, five,  z_reg, z_imm1234_0base},
     +    [0x78] = {OP_eor, -1, 0, three, z_reg, z_imm1234_8base},
     +    [0x79] = {OP_eor, -1, 0, three, z_reg, z_imm1234_8base},
     +    [0x7a] = {OP_eor, -1, 0, three, z_reg, z_imm1234_8base},
     +    [0x7b] = {OP_eor, -1, 0, three, z_reg, z_imm1234_8base},
     +    [0x7c] = {OP_eor, -1, 0, two,   z_reg, z_imm1234_8base},
     +    [0x7d] = {OP_eor, -1, 0, two,   z_reg, z_imm1234_8base},
     +    [0x7e] = {OP_eor, -1, 0, five,  z_reg, z_imm1234_8base},
     +    [0x7f] = {OP_eor, -1, 0, five,  z_reg, z_imm1234_8base},
     +    [0x80] = {OP_sbc, -1, 0,  opr_n_bytes_p1, z_reg, z_opr_decode},
     +    [0x81] = {OP_sbc, -1, 0,  opr_n_bytes_p1, z_reg, z_opr_decode},
     +    [0x82] = {OP_sbc, -1, 0,  opr_n_bytes_p1, z_reg, z_opr_decode},
     +    [0x83] = {OP_sbc, -1, 0,  opr_n_bytes_p1, z_reg, z_opr_decode},
     +    [0x84] = {OP_sbc, -1, 0,  opr_n_bytes_p1, z_reg, z_opr_decode},
     +    [0x85] = {OP_sbc, -1, 0,  opr_n_bytes_p1, z_reg, z_opr_decode},
     +    [0x86] = {OP_sbc, -1, 0,  opr_n_bytes_p1, z_reg, z_opr_decode},
     +    [0x87] = {OP_sbc, -1, 0,  opr_n_bytes_p1, z_reg, z_opr_decode},
     +    [0x88] = {OP_eor, -1, 0,  opr_n_bytes_p1, z_reg, z_opr_decode},
     +    [0x89] = {OP_eor, -1, 0,  opr_n_bytes_p1, z_reg, z_opr_decode},
     +    [0x8a] = {OP_eor, -1, 0,  opr_n_bytes_p1, z_reg, z_opr_decode},
     +    [0x8b] = {OP_eor, -1, 0,  opr_n_bytes_p1, z_reg, z_opr_decode},
     +    [0x8c] = {OP_eor, -1, 0,  opr_n_bytes_p1, z_reg, z_opr_decode},
     +    [0x8d] = {OP_eor, -1, 0,  opr_n_bytes_p1, z_reg, z_opr_decode},
     +    [0x8e] = {OP_eor, -1, 0,  opr_n_bytes_p1, z_reg, z_opr_decode},
     +    [0x8f] = {OP_eor, -1, 0,  opr_n_bytes_p1, z_reg, z_opr_decode},
     +    [0x90] = {OP_rti, -1, 0,  single, 0, 0},
     +    [0x91] = {OP_clb, -1, 0,   two, z_tfr, 0},
     +    [0x92] = {OP_trap, -1, 0,  single, trap_decode, 0},
     +    [0x93] = {OP_trap, -1, 0,  single, trap_decode, 0},
     +    [0x94] = {OP_trap, -1, 0,  single, trap_decode, 0},
     +    [0x95] = {OP_trap, -1, 0,  single, trap_decode, 0},
     +    [0x96] = {OP_trap, -1, 0,  single, trap_decode, 0},
     +    [0x97] = {OP_trap, -1, 0,  single, trap_decode, 0},
     +    [0x98] = {OP_trap, -1, 0,  single, trap_decode, 0},
     +    [0x99] = {OP_trap, -1, 0,  single, trap_decode, 0},
     +    [0x9a] = {OP_trap, -1, 0,  single, trap_decode, 0},
     +    [0x9b] = {OP_trap, -1, 0,  single, trap_decode, 0},
     +    [0x9c] = {OP_trap, -1, 0,  single, trap_decode, 0},
     +    [0x9d] = {OP_trap, -1, 0,  single, trap_decode, 0},
     +    [0x9e] = {OP_trap, -1, 0,  single, trap_decode, 0},
     +    [0x9f] = {OP_trap, -1, 0,  single, trap_decode, 0},
     +    [0xa0] = {OP_sat, -1, 0, single, z_reg, 0},
     +    [0xa1] = {OP_sat, -1, 0, single, z_reg, 0},
     +    [0xa2] = {OP_sat, -1, 0, single, z_reg, 0},
     +    [0xa3] = {OP_sat, -1, 0, single, z_reg, 0},
     +    [0xa4] = {OP_sat, -1, 0, single, z_reg, 0},
     +    [0xa5] = {OP_sat, -1, 0, single, z_reg, 0},
     +    [0xa6] = {OP_sat, -1, 0, single, z_reg, 0},
     +    [0xa7] = {OP_sat, -1, 0, single, z_reg, 0},
     +    [0xa8] = {OP_trap, -1, 0,  single, trap_decode, 0},
     +    [0xa9] = {OP_trap, -1, 0,  single, trap_decode, 0},
     +    [0xaa] = {OP_trap, -1, 0,  single, trap_decode, 0},
     +    [0xab] = {OP_trap, -1, 0,  single, trap_decode, 0},
     +    [0xac] = {OP_trap, -1, 0,  single, trap_decode, 0},
     +    [0xad] = {OP_trap, -1, 0,  single, trap_decode, 0},
     +    [0xae] = {OP_trap, -1, 0,  single, trap_decode, 0},
     +    [0xaf] = {OP_trap, -1, 0,  single, trap_decode, 0},
     +    [0xb0] = {OPBASE_qmul, -1, mul_discrim, mul_n_bytes, mul_decode, 0},
     +    [0xb1] = {OPBASE_qmul, -1, mul_discrim, mul_n_bytes, mul_decode, 0},
     +    [0xb2] = {OPBASE_qmul, -1, mul_discrim, mul_n_bytes, mul_decode, 0},
     +    [0xb3] = {OPBASE_qmul, -1, mul_discrim, mul_n_bytes, mul_decode, 0},
     +    [0xb4] = {OPBASE_qmul, -1, mul_discrim, mul_n_bytes, mul_decode, 0},
     +    [0xb5] = {OPBASE_qmul, -1, mul_discrim, mul_n_bytes, mul_decode, 0},
     +    [0xb6] = {OPBASE_qmul, -1, mul_discrim, mul_n_bytes, mul_decode, 0},
     +    [0xb7] = {OPBASE_qmul, -1, mul_discrim, mul_n_bytes, mul_decode, 0},
     +    [0xb8] = {OP_trap, -1, 0,  single, trap_decode, 0},
     +    [0xb9] = {OP_trap, -1, 0,  single, trap_decode, 0},
     +    [0xba] = {OP_trap, -1, 0,  single, trap_decode, 0},
     +    [0xbb] = {OP_trap, -1, 0,  single, trap_decode, 0},
     +    [0xbc] = {OP_trap, -1, 0,  single, trap_decode, 0},
     +    [0xbd] = {OP_trap, -1, 0,  single, trap_decode, 0},
     +    [0xbe] = {OP_trap, -1, 0,  single, trap_decode, 0},
     +    [0xbf] = {OP_trap, -1, 0,  single, trap_decode, 0},
     +    [0xc0] = {OP_trap, -1, 0,  single, trap_decode, 0},
     +    [0xc1] = {OP_trap, -1, 0,  single, trap_decode, 0},
     +    [0xc2] = {OP_trap, -1, 0,  single, trap_decode, 0},
     +    [0xc3] = {OP_trap, -1, 0,  single, trap_decode, 0},
     +    [0xc4] = {OP_trap, -1, 0,  single, trap_decode, 0},
     +    [0xc5] = {OP_trap, -1, 0,  single, trap_decode, 0},
     +    [0xc6] = {OP_trap, -1, 0,  single, trap_decode, 0},
     +    [0xc7] = {OP_trap, -1, 0,  single, trap_decode, 0},
     +    [0xc8] = {OP_trap, -1, 0,  single, trap_decode, 0},
     +    [0xc9] = {OP_trap, -1, 0,  single, trap_decode, 0},
     +    [0xca] = {OP_trap, -1, 0,  single, trap_decode, 0},
     +    [0xcb] = {OP_trap, -1, 0,  single, trap_decode, 0},
     +    [0xcc] = {OP_trap, -1, 0,  single, trap_decode, 0},
     +    [0xcd] = {OP_trap, -1, 0,  single, trap_decode, 0},
     +    [0xce] = {OP_trap, -1, 0,  single, trap_decode, 0},
     +    [0xcf] = {OP_trap, -1, 0,  single, trap_decode, 0},
     +    [0xd0] = {OP_trap, -1, 0,  single, trap_decode, 0},
     +    [0xd1] = {OP_trap, -1, 0,  single, trap_decode, 0},
     +    [0xd2] = {OP_trap, -1, 0,  single, trap_decode, 0},
     +    [0xd3] = {OP_trap, -1, 0,  single, trap_decode, 0},
     +    [0xd4] = {OP_trap, -1, 0,  single, trap_decode, 0},
     +    [0xd5] = {OP_trap, -1, 0,  single, trap_decode, 0},
     +    [0xd6] = {OP_trap, -1, 0,  single, trap_decode, 0},
     +    [0xd7] = {OP_trap, -1, 0,  single, trap_decode, 0},
     +    [0xd8] = {OP_trap, -1, 0,  single, trap_decode, 0},
     +    [0xd9] = {OP_trap, -1, 0,  single, trap_decode, 0},
     +    [0xda] = {OP_trap, -1, 0,  single, trap_decode, 0},
     +    [0xdb] = {OP_trap, -1, 0,  single, trap_decode, 0},
     +    [0xdc] = {OP_trap, -1, 0,  single, trap_decode, 0},
     +    [0xdd] = {OP_trap, -1, 0,  single, trap_decode, 0},
     +    [0xde] = {OP_trap, -1, 0,  single, trap_decode, 0},
     +    [0xdf] = {OP_trap, -1, 0,  single, trap_decode, 0},
     +    [0xe0] = {OP_trap, -1, 0,  single, trap_decode, 0},
     +    [0xe1] = {OP_trap, -1, 0,  single, trap_decode, 0},
     +    [0xe2] = {OP_trap, -1, 0,  single, trap_decode, 0},
     +    [0xe3] = {OP_trap, -1, 0,  single, trap_decode, 0},
     +    [0xe4] = {OP_trap, -1, 0,  single, trap_decode, 0},
     +    [0xe5] = {OP_trap, -1, 0,  single, trap_decode, 0},
     +    [0xe6] = {OP_trap, -1, 0,  single, trap_decode, 0},
     +    [0xe7] = {OP_trap, -1, 0,  single, trap_decode, 0},
     +    [0xe8] = {OP_trap, -1, 0,  single, trap_decode, 0},
     +    [0xe9] = {OP_trap, -1, 0,  single, trap_decode, 0},
     +    [0xea] = {OP_trap, -1, 0,  single, trap_decode, 0},
     +    [0xeb] = {OP_trap, -1, 0,  single, trap_decode, 0},
     +    [0xec] = {OP_trap, -1, 0,  single, trap_decode, 0},
     +    [0xed] = {OP_trap, -1, 0,  single, trap_decode, 0},
     +    [0xee] = {OP_trap, -1, 0,  single, trap_decode, 0},
     +    [0xef] = {OP_trap, -1, 0,  single, trap_decode, 0},
     +    [0xf0] = {OP_trap, -1, 0,  single, trap_decode, 0},
     +    [0xf1] = {OP_trap, -1, 0,  single, trap_decode, 0},
     +    [0xf2] = {OP_trap, -1, 0,  single, trap_decode, 0},
     +    [0xf3] = {OP_trap, -1, 0,  single, trap_decode, 0},
     +    [0xf4] = {OP_trap, -1, 0,  single, trap_decode, 0},
     +    [0xf5] = {OP_trap, -1, 0,  single, trap_decode, 0},
     +    [0xf6] = {OP_trap, -1, 0,  single, trap_decode, 0},
     +    [0xf7] = {OP_trap, -1, 0,  single, trap_decode, 0},
     +    [0xf8] = {OP_trap, -1, 0,  single, trap_decode, 0},
     +    [0xf9] = {OP_trap, -1, 0,  single, trap_decode, 0},
     +    [0xfa] = {OP_trap, -1, 0,  single, trap_decode, 0},
     +    [0xfb] = {OP_trap, -1, 0,  single, trap_decode, 0},
     +    [0xfc] = {OP_trap, -1, 0,  single, trap_decode, 0},
     +    [0xfd] = {OP_trap, -1, 0,  single, trap_decode, 0},
     +    [0xfe] = {OP_trap, -1, 0,  single, trap_decode, 0},
     +    [0xff] = {OP_trap, -1, 0,  single, trap_decode, 0},
     +  };
     +
     +static const struct opcode page1[] =
     +  {
     +    [0x00] = {OP_bgnd, -1, 0, single, 0, 0},
     +    [0x01] = {OP_nop, -1, 0,  single, 0, 0},
     +    [0x02] = {OP_brclr, -1, 0, bm_rel_n_bytes, bm_rel_decode, 0},
     +    [0x03] = {OP_brset, -1, 0, bm_rel_n_bytes, bm_rel_decode, 0},
     +    [0x04] = {0xFFFF, -1, psh_pul_discrim,   two, psh_pul_decode, 0}, /* psh/pul */
     +    [0x05] = {OP_rts, -1, 0,  single, 0, 0},
     +    [0x06] = {OP_lea, -1, 0, opr_n_bytes_p1, z_reg, z_opr_decode},
     +    [0x07] = {OP_lea, -1, 0, opr_n_bytes_p1, z_reg, z_opr_decode},
     +    [0x08] = {OP_lea, -1, 0, opr_n_bytes_p1, lea_reg_xys_opr, 0},
     +    [0x09] = {OP_lea, -1, 0, opr_n_bytes_p1, lea_reg_xys_opr, 0},
     +    [0x0a] = {OP_lea, -1, 0, opr_n_bytes_p1, lea_reg_xys_opr, 0},
     +    [0x0b] = {0xFFFF, -1, loop_primitive_discrim, loop_prim_n_bytes, loop_primitive_decode, 0}, /* Loop primitives TBcc / DBcc */
     +    [0x0c] = {OP_mov, 0, 0, mov_imm_opr_n_bytes, mov_imm_opr, 0},
     +    [0x0d] = {OP_mov, 1, 0, mov_imm_opr_n_bytes, mov_imm_opr, 0},
     +    [0x0e] = {OP_mov, 2, 0, mov_imm_opr_n_bytes, mov_imm_opr, 0},
     +    [0x0f] = {OP_mov, 3, 0, mov_imm_opr_n_bytes, mov_imm_opr, 0},
     +    [0x10] = {0xFFFF, -1, shift_discrim,  shift_n_bytes, shift_decode, 0},  /* lsr/lsl/asl/asr/rol/ror */
     +    [0x11] = {0xFFFF, -1, shift_discrim,  shift_n_bytes, shift_decode, 0},
     +    [0x12] = {0xFFFF, -1, shift_discrim,  shift_n_bytes, shift_decode, 0},
     +    [0x13] = {0xFFFF, -1, shift_discrim,  shift_n_bytes, shift_decode, 0},
     +    [0x14] = {0xFFFF, -1, shift_discrim,  shift_n_bytes, shift_decode, 0},
     +    [0x15] = {0xFFFF, -1, shift_discrim,  shift_n_bytes, shift_decode, 0},
     +    [0x16] = {0xFFFF, -1, shift_discrim,  shift_n_bytes, shift_decode, 0},
     +    [0x17] = {0xFFFF, -1, shift_discrim,  shift_n_bytes, shift_decode, 0},
     +    [0x18] = {OP_lea, -1, 0,  two, lea_reg_xys, NULL},
     +    [0x19] = {OP_lea, -1, 0,  two, lea_reg_xys, NULL},
     +    [0x1a] = {OP_lea, -1, 0,  two, lea_reg_xys, NULL},
     +    /* 0x1b PG2 */
     +    [0x1c] = {OP_mov, 0, 0, opr_n_bytes2, z_opr_decode2, 0},
     +    [0x1d] = {OP_mov, 1, 0, opr_n_bytes2, z_opr_decode2, 0},
     +    [0x1e] = {OP_mov, 2, 0, opr_n_bytes2, z_opr_decode2, 0},
     +    [0x1f] = {OP_mov, 3, 0, opr_n_bytes2, z_opr_decode2, 0},
     +    [0x20] = {OP_bra, -1, 0,  pcrel_15bit, decode_rel_15_7, 0},
     +    [0x21] = {OP_bsr, -1, 0,  pcrel_15bit, decode_rel_15_7, 0},
     +    [0x22] = {OP_bhi, -1, 0,  pcrel_15bit, decode_rel_15_7, 0},
     +    [0x23] = {OP_bls, -1, 0,  pcrel_15bit, decode_rel_15_7, 0},
     +    [0x24] = {OP_bcc, -1, 0,  pcrel_15bit, decode_rel_15_7, 0},
     +    [0x25] = {OP_bcs, -1, 0,  pcrel_15bit, decode_rel_15_7, 0},
     +    [0x26] = {OP_bne, -1, 0,  pcrel_15bit, decode_rel_15_7, 0},
     +    [0x27] = {OP_beq, -1, 0,  pcrel_15bit, decode_rel_15_7, 0},
     +    [0x28] = {OP_bvc, -1, 0,  pcrel_15bit, decode_rel_15_7, 0},
     +    [0x29] = {OP_bvs, -1, 0,  pcrel_15bit, decode_rel_15_7, 0},
     +    [0x2a] = {OP_bpl, -1, 0,  pcrel_15bit, decode_rel_15_7, 0},
     +    [0x2b] = {OP_bmi, -1, 0,  pcrel_15bit, decode_rel_15_7, 0},
     +    [0x2c] = {OP_bge, -1, 0,  pcrel_15bit, decode_rel_15_7, 0},
     +    [0x2d] = {OP_blt, -1, 0,  pcrel_15bit, decode_rel_15_7, 0},
     +    [0x2e] = {OP_bgt, -1, 0,  pcrel_15bit, decode_rel_15_7, 0},
     +    [0x2f] = {OP_ble, -1, 0,  pcrel_15bit, decode_rel_15_7, 0},
     +    [0x30] = {OP_inc, -1, 0, single, z_reg, 0},
     +    [0x31] = {OP_inc, -1, 0, single, z_reg, 0},
     +    [0x32] = {OP_inc, -1, 0, single, z_reg, 0},
     +    [0x33] = {OP_inc, -1, 0, single, z_reg, 0},
     +    [0x34] = {OP_inc, -1, 0, single, z_reg, 0},
     +    [0x35] = {OP_inc, -1, 0, single, z_reg, 0},
     +    [0x36] = {OP_inc, -1, 0, single, z_reg, 0},
     +    [0x37] = {OP_inc, -1, 0, single, z_reg, 0},
     +    [0x38] = {OP_clr, -1, 0, single, z_reg, 0},
     +    [0x39] = {OP_clr, -1, 0, single, z_reg, 0},
     +    [0x3a] = {OP_clr, -1, 0, single, z_reg, 0},
     +    [0x3b] = {OP_clr, -1, 0, single, z_reg, 0},
     +    [0x3c] = {OP_clr, -1, 0, single, z_reg, 0},
     +    [0x3d] = {OP_clr, -1, 0, single, z_reg, 0},
     +    [0x3e] = {OP_clr, -1, 0, single, z_reg, 0},
     +    [0x3f] = {OP_clr, -1, 0, single, z_reg, 0},
     +    [0x40] = {OP_dec, -1, 0, single, z_reg, 0},
     +    [0x41] = {OP_dec, -1, 0, single, z_reg, 0},
     +    [0x42] = {OP_dec, -1, 0, single, z_reg, 0},
     +    [0x43] = {OP_dec, -1, 0, single, z_reg, 0},
     +    [0x44] = {OP_dec, -1, 0, single, z_reg, 0},
     +    [0x45] = {OP_dec, -1, 0, single, z_reg, 0},
     +    [0x46] = {OP_dec, -1, 0, single, z_reg, 0},
     +    [0x47] = {OP_dec, -1, 0, single, z_reg, 0},
     +    [0x48] = {OPBASE_mul, -1, mul_discrim, mul_n_bytes, mul_decode, 0},
     +    [0x49] = {OPBASE_mul, -1, mul_discrim, mul_n_bytes, mul_decode, 0},
     +    [0x4a] = {OPBASE_mul, -1, mul_discrim, mul_n_bytes, mul_decode, 0},
     +    [0x4b] = {OPBASE_mul, -1, mul_discrim, mul_n_bytes, mul_decode, 0},
     +    [0x4c] = {OPBASE_mul, -1, mul_discrim, mul_n_bytes, mul_decode, 0},
     +    [0x4d] = {OPBASE_mul, -1, mul_discrim, mul_n_bytes, mul_decode, 0},
     +    [0x4e] = {OPBASE_mul, -1, mul_discrim, mul_n_bytes, mul_decode, 0},
     +    [0x4f] = {OPBASE_mul, -1, mul_discrim, mul_n_bytes, mul_decode, 0},
     +    [0x50] = {OP_add, -1, 0, three, z_reg, z_imm1234_0base},
     +    [0x51] = {OP_add, -1, 0, three, z_reg, z_imm1234_0base},
     +    [0x52] = {OP_add, -1, 0, three, z_reg, z_imm1234_0base},
     +    [0x53] = {OP_add, -1, 0, three, z_reg, z_imm1234_0base},
     +    [0x54] = {OP_add, -1, 0, two,   z_reg, z_imm1234_0base},
     +    [0x55] = {OP_add, -1, 0, two,   z_reg, z_imm1234_0base},
     +    [0x56] = {OP_add, -1, 0, five,  z_reg, z_imm1234_0base},
     +    [0x57] = {OP_add, -1, 0, five,  z_reg, z_imm1234_0base},
     +    [0x58] = {OP_and, -1, 0, three, z_reg, z_imm1234_8base},
     +    [0x59] = {OP_and, -1, 0, three, z_reg, z_imm1234_8base},
     +    [0x5a] = {OP_and, -1, 0, three, z_reg, z_imm1234_8base},
     +    [0x5b] = {OP_and, -1, 0, three, z_reg, z_imm1234_8base},
     +    [0x5c] = {OP_and, -1, 0, two,   z_reg, z_imm1234_8base},
     +    [0x5d] = {OP_and, -1, 0, two,   z_reg, z_imm1234_8base},
     +    [0x5e] = {OP_and, -1, 0, five,  z_reg, z_imm1234_8base},
     +    [0x5f] = {OP_and, -1, 0, five,  z_reg, z_imm1234_8base},
     +    [0x60] = {OP_add, -1, 0, opr_n_bytes_p1, z_reg, z_opr_decode},
     +    [0x61] = {OP_add, -1, 0, opr_n_bytes_p1, z_reg, z_opr_decode},
     +    [0x62] = {OP_add, -1, 0, opr_n_bytes_p1, z_reg, z_opr_decode},
     +    [0x63] = {OP_add, -1, 0, opr_n_bytes_p1, z_reg, z_opr_decode},
     +    [0x64] = {OP_add, -1, 0, opr_n_bytes_p1, z_reg, z_opr_decode},
     +    [0x65] = {OP_add, -1, 0, opr_n_bytes_p1, z_reg, z_opr_decode},
     +    [0x66] = {OP_add, -1, 0, opr_n_bytes_p1, z_reg, z_opr_decode},
     +    [0x67] = {OP_add, -1, 0, opr_n_bytes_p1, z_reg, z_opr_decode},
     +    [0x68] = {OP_and, -1, 0, opr_n_bytes_p1, z_reg, z_opr_decode},
     +    [0x69] = {OP_and, -1, 0, opr_n_bytes_p1, z_reg, z_opr_decode},
     +    [0x6a] = {OP_and, -1, 0, opr_n_bytes_p1, z_reg, z_opr_decode},
     +    [0x6b] = {OP_and, -1, 0, opr_n_bytes_p1, z_reg, z_opr_decode},
     +    [0x6c] = {OP_and, -1, 0, opr_n_bytes_p1, z_reg, z_opr_decode},
     +    [0x6d] = {OP_and, -1, 0, opr_n_bytes_p1, z_reg, z_opr_decode},
     +    [0x6e] = {OP_and, -1, 0, opr_n_bytes_p1, z_reg, z_opr_decode},
     +    [0x6f] = {OP_and, -1, 0, opr_n_bytes_p1, z_reg, z_opr_decode},
     +    [0x70] = {OP_sub, -1, 0, three, z_reg, z_imm1234_0base},
     +    [0x71] = {OP_sub, -1, 0, three, z_reg, z_imm1234_0base},
     +    [0x72] = {OP_sub, -1, 0, three, z_reg, z_imm1234_0base},
     +    [0x73] = {OP_sub, -1, 0, three, z_reg, z_imm1234_0base},
     +    [0x74] = {OP_sub, -1, 0, two,   z_reg, z_imm1234_0base},
     +    [0x75] = {OP_sub, -1, 0, two,   z_reg, z_imm1234_0base},
     +    [0x76] = {OP_sub, -1, 0, five,  z_reg, z_imm1234_0base},
     +    [0x77] = {OP_sub, -1, 0, five,  z_reg, z_imm1234_0base},
     +    [0x78] = {OP_or, -1, 0, three, z_reg, z_imm1234_8base},
     +    [0x79] = {OP_or, -1, 0, three, z_reg, z_imm1234_8base},
     +    [0x7a] = {OP_or, -1, 0, three, z_reg, z_imm1234_8base},
     +    [0x7b] = {OP_or, -1, 0, three, z_reg, z_imm1234_8base},
     +    [0x7c] = {OP_or, -1, 0, two,   z_reg, z_imm1234_8base},
     +    [0x7d] = {OP_or, -1, 0, two,   z_reg, z_imm1234_8base},
     +    [0x7e] = {OP_or, -1, 0, five,  z_reg, z_imm1234_8base},
     +    [0x7f] = {OP_or, -1, 0, five,  z_reg, z_imm1234_8base},
     +    [0x80] = {OP_sub, -1, 0, opr_n_bytes_p1, z_reg,    z_opr_decode},
     +    [0x81] = {OP_sub, -1, 0, opr_n_bytes_p1, z_reg,    z_opr_decode},
     +    [0x82] = {OP_sub, -1, 0, opr_n_bytes_p1, z_reg,    z_opr_decode},
     +    [0x83] = {OP_sub, -1, 0, opr_n_bytes_p1, z_reg,    z_opr_decode},
     +    [0x84] = {OP_sub, -1, 0, opr_n_bytes_p1, z_reg,    z_opr_decode},
     +    [0x85] = {OP_sub, -1, 0, opr_n_bytes_p1, z_reg,    z_opr_decode},
     +    [0x86] = {OP_sub, -1, 0, opr_n_bytes_p1, z_reg,    z_opr_decode},
     +    [0x87] = {OP_sub, -1, 0, opr_n_bytes_p1, z_reg,    z_opr_decode},
     +    [0x88] = {OP_or, -1, 0, opr_n_bytes_p1, z_reg,    z_opr_decode},
     +    [0x89] = {OP_or, -1, 0, opr_n_bytes_p1, z_reg,    z_opr_decode},
     +    [0x8a] = {OP_or, -1, 0, opr_n_bytes_p1, z_reg,    z_opr_decode},
     +    [0x8b] = {OP_or, -1, 0, opr_n_bytes_p1, z_reg,    z_opr_decode},
     +    [0x8c] = {OP_or, -1, 0, opr_n_bytes_p1, z_reg,    z_opr_decode},
     +    [0x8d] = {OP_or, -1, 0, opr_n_bytes_p1, z_reg,    z_opr_decode},
     +    [0x8e] = {OP_or, -1, 0, opr_n_bytes_p1, z_reg,    z_opr_decode},
     +    [0x8f] = {OP_or, -1, 0, opr_n_bytes_p1, z_reg,    z_opr_decode},
     +    [0x90] = {OP_ld, -1, 0, three,  z_reg, z_imm1234_0base},
     +    [0x91] = {OP_ld, -1, 0, three,  z_reg, z_imm1234_0base},
     +    [0x92] = {OP_ld, -1, 0, three,  z_reg, z_imm1234_0base},
     +    [0x93] = {OP_ld, -1, 0, three,  z_reg, z_imm1234_0base},
     +    [0x94] = {OP_ld, -1, 0, two,    z_reg, z_imm1234_0base},
     +    [0x95] = {OP_ld, -1, 0, two,    z_reg, z_imm1234_0base},
     +    [0x96] = {OP_ld, -1, 0, five,   z_reg, z_imm1234_0base},
     +    [0x97] = {OP_ld, -1, 0, five,   z_reg, z_imm1234_0base},
     +    [0x98] = {OP_ld, -1, 0, four,   reg_xy, z_imm1234_0base},
     +    [0x99] = {OP_ld, -1, 0, four,   reg_xy, z_imm1234_0base},
     +    [0x9a] = {OP_clr, -1, 0, single, reg_xy, 0},
     +    [0x9b] = {OP_clr, -1, 0, single, reg_xy, 0},
     +    [0x9c] = {OP_inc, 0, 0, opr_n_bytes_p1, z_opr_decode, 0},
     +    [0x9d] = {OP_inc, 1, 0, opr_n_bytes_p1, z_opr_decode, 0},
     +    [0x9e] = {OP_tfr, -1, 0, two, z_tfr, NULL},
     +    [0x9f] = {OP_inc, 3, 0, opr_n_bytes_p1, z_opr_decode, 0},
     +    [0xa0] = {OP_ld, -1, 0, opr_n_bytes_p1, z_reg,    z_opr_decode},
     +    [0xa1] = {OP_ld, -1, 0, opr_n_bytes_p1, z_reg,    z_opr_decode},
     +    [0xa2] = {OP_ld, -1, 0, opr_n_bytes_p1, z_reg,    z_opr_decode},
     +    [0xa3] = {OP_ld, -1, 0, opr_n_bytes_p1, z_reg,    z_opr_decode},
     +    [0xa4] = {OP_ld, -1, 0, opr_n_bytes_p1, z_reg,    z_opr_decode},
     +    [0xa5] = {OP_ld, -1, 0, opr_n_bytes_p1, z_reg,    z_opr_decode},
     +    [0xa6] = {OP_ld, -1, 0, opr_n_bytes_p1, z_reg,    z_opr_decode},
     +    [0xa7] = {OP_ld, -1, 0, opr_n_bytes_p1, z_reg,    z_opr_decode},
     +    [0xa8] = {OP_ld, -1, 0, opr_n_bytes_p1, reg_xy, z_opr_decode},
     +    [0xa9] = {OP_ld, -1, 0, opr_n_bytes_p1, reg_xy, z_opr_decode},
     +    [0xaa] = {OP_jmp, -1, 0, opr_n_bytes_p1, z_opr_decode, 0},
     +    [0xab] = {OP_jsr, -1, 0, opr_n_bytes_p1, z_opr_decode, 0},
     +    [0xac] = {OP_dec, 0, 0, opr_n_bytes_p1, z_opr_decode, 0},
     +    [0xad] = {OP_dec, 1, 0, opr_n_bytes_p1, z_opr_decode, 0},
     +    [0xae] = {0xFFFF, -1, exg_sex_discrim,   two, exg_sex_decode, 0},  /* EXG / SEX */
     +    [0xaf] = {OP_dec, 3, 0, opr_n_bytes_p1, 0, z_opr_decode},
     +    [0xb0] = {OP_ld, -1, 0, four,  z_reg, z_ext24_decode},
     +    [0xb1] = {OP_ld, -1, 0, four,  z_reg, z_ext24_decode},
     +    [0xb2] = {OP_ld, -1, 0, four,  z_reg, z_ext24_decode},
     +    [0xb3] = {OP_ld, -1, 0, four,  z_reg, z_ext24_decode},
     +    [0xb4] = {OP_ld, -1, 0, four,  z_reg, z_ext24_decode},
     +    [0xb5] = {OP_ld, -1, 0, four,  z_reg, z_ext24_decode},
     +    [0xb6] = {OP_ld, -1, 0, four,  z_reg, z_ext24_decode},
     +    [0xb7] = {OP_ld, -1, 0, four,  z_reg, z_ext24_decode},
     +    [0xb8] = {OP_ld, -1, 0, four,  reg_xy, z_ext24_decode},
     +    [0xb9] = {OP_ld, -1, 0, four,  reg_xy, z_ext24_decode},
     +    [0xba] = {OP_jmp, -1, 0, four, z_ext24_decode, 0},
     +    [0xbb] = {OP_jsr, -1, 0, four, z_ext24_decode, 0},
     +    [0xbc] = {OP_clr, 0, 0, opr_n_bytes_p1, z_opr_decode, 0},
     +    [0xbd] = {OP_clr, 1, 0, opr_n_bytes_p1, z_opr_decode, 0},
     +    [0xbe] = {OP_clr, 2, 0, opr_n_bytes_p1, z_opr_decode, 0},
     +    [0xbf] = {OP_clr, 3, 0, opr_n_bytes_p1, z_opr_decode, 0},
     +    [0xc0] = {OP_st, -1, 0, opr_n_bytes_p1, z_reg,    z_opr_decode},
     +    [0xc1] = {OP_st, -1, 0, opr_n_bytes_p1, z_reg,    z_opr_decode},
     +    [0xc2] = {OP_st, -1, 0, opr_n_bytes_p1, z_reg,    z_opr_decode},
     +    [0xc3] = {OP_st, -1, 0, opr_n_bytes_p1, z_reg,    z_opr_decode},
     +    [0xc4] = {OP_st, -1, 0, opr_n_bytes_p1, z_reg,    z_opr_decode},
     +    [0xc5] = {OP_st, -1, 0, opr_n_bytes_p1, z_reg,    z_opr_decode},
     +    [0xc6] = {OP_st, -1, 0, opr_n_bytes_p1, z_reg,    z_opr_decode},
     +    [0xc7] = {OP_st, -1, 0, opr_n_bytes_p1, z_reg,    z_opr_decode},
     +    [0xc8] = {OP_st, -1, 0, opr_n_bytes_p1, reg_xy, z_opr_decode},
     +    [0xc9] = {OP_st, -1, 0, opr_n_bytes_p1, reg_xy, z_opr_decode},
     +    [0xca] = {OP_ld, -1, 0, three, reg_xy, ld_18bit_decode},
     +    [0xcb] = {OP_ld, -1, 0, three, reg_xy, ld_18bit_decode},
     +    [0xcc] = {OP_com, 0, 0, opr_n_bytes_p1, NULL, z_opr_decode},
     +    [0xcd] = {OP_com, 1, 0, opr_n_bytes_p1, NULL, z_opr_decode},
     +    [0xce] = {OP_andcc, -1, 0, two, imm1_decode, 0},
     +    [0xcf] = {OP_com, 3, 0, opr_n_bytes_p1, NULL, z_opr_decode},
     +    [0xd0] = {OP_st, -1, 0, four,  z_reg, z_ext24_decode},
     +    [0xd1] = {OP_st, -1, 0, four,  z_reg, z_ext24_decode},
     +    [0xd2] = {OP_st, -1, 0, four,  z_reg, z_ext24_decode},
     +    [0xd3] = {OP_st, -1, 0, four,  z_reg, z_ext24_decode},
     +    [0xd4] = {OP_st, -1, 0, four,  z_reg, z_ext24_decode},
     +    [0xd5] = {OP_st, -1, 0, four,  z_reg, z_ext24_decode},
     +    [0xd6] = {OP_st, -1, 0, four,  z_reg, z_ext24_decode},
     +    [0xd7] = {OP_st, -1, 0, four,  z_reg, z_ext24_decode},
     +    [0xd8] = {OP_st, -1, 0, four,  reg_xy, z_ext24_decode},
     +    [0xd9] = {OP_st, -1, 0, four,  reg_xy, z_ext24_decode},
     +    [0xda] = {OP_ld, -1, 0, three, reg_xy, ld_18bit_decode},
     +    [0xdb] = {OP_ld, -1, 0, three, reg_xy, ld_18bit_decode},
     +    [0xdc] = {OP_neg, 0, 0, opr_n_bytes_p1, NULL, z_opr_decode},
     +    [0xdd] = {OP_neg, 1, 0, opr_n_bytes_p1, NULL, z_opr_decode},
     +    [0xde] = {OP_orcc, -1, 0,  two,  imm1_decode, 0},
     +    [0xdf] = {OP_neg,  3, 0, opr_n_bytes_p1, NULL, z_opr_decode},
     +    [0xe0] = {OP_cmp, -1, 0, three,  z_reg, z_imm1234_0base},
     +    [0xe1] = {OP_cmp, -1, 0, three,  z_reg, z_imm1234_0base},
     +    [0xe2] = {OP_cmp, -1, 0, three,  z_reg, z_imm1234_0base},
     +    [0xe3] = {OP_cmp, -1, 0, three,  z_reg, z_imm1234_0base},
     +    [0xe4] = {OP_cmp, -1, 0, two,    z_reg, z_imm1234_0base},
     +    [0xe5] = {OP_cmp, -1, 0, two,    z_reg, z_imm1234_0base},
     +    [0xe6] = {OP_cmp, -1, 0, five,   z_reg, z_imm1234_0base},
     +    [0xe7] = {OP_cmp, -1, 0, five,   z_reg, z_imm1234_0base},
     +    [0xe8] = {OP_cmp, -1, 0, four,   reg_xy, z_imm1234_0base},
     +    [0xe9] = {OP_cmp, -1, 0, four,   reg_xy, z_imm1234_0base},
     +    [0xea] = {OP_ld, -1, 0, three, reg_xy, ld_18bit_decode},
     +    [0xeb] = {OP_ld, -1, 0, three, reg_xy, ld_18bit_decode},
     +    [0xec] = {OP_bclr, -1, 0, bm_n_bytes, bm_decode, 0},
     +    [0xed] = {OP_bset, -1, 0, bm_n_bytes, bm_decode, 0},
     +    [0xee] = {OP_btgl, -1, 0, bm_n_bytes, bm_decode, 0},
     +    [0xef] = {OP_INVALID, -1, 0, NULL, NULL, NULL}, /* SPARE */
     +    [0xf0] = {OP_cmp, -1, 0, opr_n_bytes_p1, z_reg,    z_opr_decode},
     +    [0xf1] = {OP_cmp, -1, 0, opr_n_bytes_p1, z_reg,    z_opr_decode},
     +    [0xf2] = {OP_cmp, -1, 0, opr_n_bytes_p1, z_reg,    z_opr_decode},
     +    [0xf3] = {OP_cmp, -1, 0, opr_n_bytes_p1, z_reg,    z_opr_decode},
     +    [0xf4] = {OP_cmp, -1, 0, opr_n_bytes_p1, z_reg,    z_opr_decode},
     +    [0xf5] = {OP_cmp, -1, 0, opr_n_bytes_p1, z_reg,    z_opr_decode},
     +    [0xf6] = {OP_cmp, -1, 0, opr_n_bytes_p1, z_reg,    z_opr_decode},
     +    [0xf7] = {OP_cmp, -1, 0, opr_n_bytes_p1, z_reg,    z_opr_decode},
     +    [0xf8] = {OP_cmp, -1, 0, opr_n_bytes_p1, reg_xy, z_opr_decode},
     +    [0xf9] = {OP_cmp, -1, 0, opr_n_bytes_p1, reg_xy, z_opr_decode},
     +    [0xfa] = {OP_ld, -1, 0,  three, reg_xy, ld_18bit_decode},
     +    [0xfb] = {OP_ld, -1, 0,  three, reg_xy, ld_18bit_decode},
     +    [0xfc] = {OP_cmp, -1, 0, single, cmp_xy, 0},
     +    [0xfd] = {OP_sub, -1, 0, single, sub_d6_x_y, 0},
     +    [0xfe] = {OP_sub, -1, 0, single, sub_d6_y_x, 0},
     +    [0xff] = {OP_swi, -1, 0, single, 0, 0}
     +  };
     +
     +static const int oprregs1[] =
     +  {
     +    REG_D3, REG_D2, REG_D1, REG_D0, REG_CCL, REG_CCH
     +  };
     +
     +static const int oprregs2[] =
     +  {
     +    REG_Y,  REG_X,  REG_D7, REG_D6, REG_D5,  REG_D4
     +  };
     +
     +
     +
     +
     +enum MUL_MODE
     +  {
     +    MUL_REG_REG,
     +    MUL_REG_OPR,
     +    MUL_REG_IMM,
     +    MUL_OPR_OPR
     +  };
     +
     +struct mb
     +{
     +  uint8_t mask;
     +  uint8_t value;
     +  enum MUL_MODE mode;
     +};
     +
     +static const struct mb mul_table[] = {
     +  {0x40, 0x00, MUL_REG_REG},
     +
     +  {0x47, 0x40, MUL_REG_OPR},
     +  {0x47, 0x41, MUL_REG_OPR},
     +  {0x47, 0x43, MUL_REG_OPR},
     +
     +  {0x47, 0x44, MUL_REG_IMM},
     +  {0x47, 0x45, MUL_REG_IMM},
     +  {0x47, 0x47, MUL_REG_IMM},
     +
     +  {0x43, 0x42, MUL_OPR_OPR},
     +};
     +
     +
     +static void
     +mul_decode (struct mem_read_abstraction_base *mra,
     +	    int *n_operands, struct operand **operand)
     +{
     +  uint8_t mb;
     +  int status = mra->read (mra, 0, 1, &mb);
     +  if (status < 0)
     +    return;
     +
     +  uint8_t byte;
     +  status = mra->read (mra, -1, 1, &byte);
     +  if (status < 0)
     +    return;
     +
     +  enum MUL_MODE mode = -1;
     +  size_t i;
     +  for (i = 0; i < sizeof (mul_table) / sizeof (mul_table[0]); ++i)
     +    {
     +      const struct mb *mm = mul_table + i;
     +      if ((mb & mm->mask) == mm->value)
     +	{
     +	  mode = mm->mode;
     +	  break;
     +	}
     +    }
     +  operand[(*n_operands)++] = create_register_operand (byte & 0x07);
     +
     +  switch (mode)
     +    {
     +    case MUL_REG_IMM:
     +      {
     +	int size = (mb & 0x3);
     +	operand[(*n_operands)++] =
     +	  create_register_operand_with_size ((mb & 0x38) >> 3, size);
     +	uint32_t imm = z_decode_signed_value (mra, 1, size + 1);
     +	operand[(*n_operands)++] = create_immediate_operand (imm);
     +      }
     +      break;
     +    case MUL_REG_REG:
     +      operand[(*n_operands)++] = create_register_operand ((mb & 0x38) >> 3);
     +      operand[(*n_operands)++] = create_register_operand (mb & 0x07);
     +      break;
     +    case MUL_REG_OPR:
     +      operand[(*n_operands)++] = create_register_operand ((mb & 0x38) >> 3);
     +      operand[(*n_operands)++] = x_opr_decode_with_size (mra, 1, mb & 0x3);
     +      break;
     +    case MUL_OPR_OPR:
     +      {
     +	int first = x_opr_n_bytes (mra, 1);
     +	operand[(*n_operands)++] = x_opr_decode_with_size (mra, 1,
     +							   (mb & 0x30) >> 4);
     +	operand[(*n_operands)++] = x_opr_decode_with_size (mra, first + 1,
     +							   (mb & 0x0c) >> 2);
     +	break;
     +      }
     +    }
     +}
     +
     +
     +static int
     +mul_n_bytes (struct mem_read_abstraction_base *mra)
     +{
     +  int nx = 2;
     +  uint8_t mb;
     +  int status = mra->read (mra, 0, 1, &mb);
     +  if (status < 0)
     +    return 0;
     +
     +  enum MUL_MODE mode = -1;
     +  size_t i;
     +  for (i = 0; i < sizeof (mul_table) / sizeof (mul_table[0]); ++i)
     +    {
     +      const struct mb *mm = mul_table + i;
     +      if ((mb & mm->mask) == mm->value)
     +	{
     +	  mode = mm->mode;
     +	  break;
     +	}
     +    }
     +
     +  int size = (mb & 0x3) + 1;
     +
     +  switch (mode)
     +    {
     +    case MUL_REG_IMM:
     +      nx += size;
     +      break;
     +    case MUL_REG_REG:
     +      break;
     +    case MUL_REG_OPR:
     +      nx += x_opr_n_bytes (mra, 1);
     +      break;
     +    case MUL_OPR_OPR:
     +      {
     +	int first = x_opr_n_bytes (mra, nx - 1);
     +	nx += first;
     +	int second = x_opr_n_bytes (mra, nx - 1);
     +	nx += second;
     +      }
     +      break;
     +    }
     +
     +  return nx;
     +}
     +
     +
     +/* The NXP documentation is vague about BM_RESERVED0 and BM_RESERVED1,
     +   and contains obvious typos.
     +   However the Freescale tools and experiments with the chip itself
     +   seem to indicate that they behave like BM_REG_IMM and BM_OPR_REG
     +   respectively.  */
     +
     +enum BM_MODE
     +{
     +  BM_REG_IMM,
     +  BM_RESERVED0,
     +  BM_OPR_B,
     +  BM_OPR_W,
     +  BM_OPR_L,
     +  BM_OPR_REG,
     +  BM_RESERVED1
     +};
     +
     +struct bm
     +{
     +  uint8_t mask;
     +  uint8_t value;
     +  enum BM_MODE mode;
     +};
     +
     +static const  struct bm bm_table[] = {
     +  { 0xC6, 0x04,     BM_REG_IMM},
     +  { 0x84, 0x00,     BM_REG_IMM},
     +  { 0x06, 0x06,     BM_REG_IMM},
     +  { 0xC6, 0x44,     BM_RESERVED0},
     +  // 00
     +  { 0x8F, 0x80,     BM_OPR_B},
     +  { 0x8E, 0x82,     BM_OPR_W},
     +  { 0x8C, 0x88,     BM_OPR_L},
     +
     +  { 0x83, 0x81,     BM_OPR_REG},
     +  { 0x87, 0x84,     BM_RESERVED1},
     +};
     +
     +static void
     +bm_decode (struct mem_read_abstraction_base *mra,
     +	   int *n_operands, struct operand **operand)
     +{
     +  uint8_t bm;
     +  int status = mra->read (mra, 0, 1, &bm);
     +  if (status < 0)
     +    return;
     +
     +  size_t i;
     +  enum BM_MODE mode = -1;
     +  for (i = 0; i < sizeof (bm_table) / sizeof (bm_table[0]); ++i)
     +    {
     +      const struct bm *bme = bm_table + i;
     +      if ((bm & bme->mask) == bme->value)
     +	{
     +	  mode = bme->mode;
     +	  break;
     +	}
     +    }
     +
     +  switch (mode)
     +    {
     +    case BM_REG_IMM:
     +    case BM_RESERVED0:
     +      operand[(*n_operands)++] = create_register_operand (bm & 0x07);
     +      break;
     +    case BM_OPR_B:
     +      operand[(*n_operands)++] = x_opr_decode_with_size (mra, 1, 0);
     +      break;
     +    case BM_OPR_W:
     +      operand[(*n_operands)++] = x_opr_decode_with_size (mra, 1, 1);
     +      break;
     +    case BM_OPR_L:
     +      operand[(*n_operands)++] = x_opr_decode_with_size (mra, 1, 3);
     +      break;
     +    case BM_OPR_REG:
     +    case BM_RESERVED1:
     +      {
     +	uint8_t xb;
     +	mra->read (mra, 1, 1, &xb);
     +	/* Don't emit a size suffix for register operands */
     +	if ((xb & 0xF8) != 0xB8)
     +	  operand[(*n_operands)++] =
     +	    x_opr_decode_with_size (mra, 1, (bm & 0x0c) >> 2);
     +	else
     +	  operand[(*n_operands)++] = x_opr_decode (mra, 1);
     +      }
     +      break;
     +    }
     +
     +  uint8_t imm = 0;
     +  switch (mode)
     +    {
     +    case BM_REG_IMM:
     +      imm = (bm & 0x38) >> 3;
     +      operand[(*n_operands)++] = create_immediate_operand (imm);
     +      break;
     +    case BM_OPR_L:
     +      imm |= (bm & 0x03) << 3;
     +      /* fallthrough */
     +    case BM_OPR_W:
     +      imm |= (bm & 0x01) << 3;
     +      /* fallthrough */
     +    case BM_OPR_B:
     +      imm |= (bm & 0x70) >> 4;
     +      operand[(*n_operands)++] = create_immediate_operand (imm);
     +      break;
     +    case BM_OPR_REG:
     +    case BM_RESERVED1:
     +      operand[(*n_operands)++] = create_register_operand ((bm & 0x70) >> 4);
     +      break;
     +    case BM_RESERVED0:
     +      assert (0);
     +      break;
     +    }
     +}
     +
     +
     +static void
     +bm_rel_decode (struct mem_read_abstraction_base *mra,
     +	       int *n_operands, struct operand **operand)
     +{
     +  uint8_t bm;
     +  int status = mra->read (mra, 0, 1, &bm);
     +  if (status < 0)
     +    return;
     +
     +  size_t i;
     +  enum BM_MODE mode = -1;
     +  for (i = 0; i < sizeof (bm_table) / sizeof (bm_table[0]); ++i)
     +    {
     +      const struct bm *bme = bm_table + i;
     +      if ((bm & bme->mask) == bme->value)
     +	{
     +	  mode = bme->mode;
     +	  break;
     +	}
     +    }
     +
     +  int n = 1;
     +  switch (mode)
     +    {
     +    case BM_REG_IMM:
     +    case BM_RESERVED0:
     +      operand[(*n_operands)++] = create_register_operand (bm & 0x07);
     +      break;
     +    case BM_OPR_B:
     +      operand[(*n_operands)++] = x_opr_decode_with_size (mra, 1, 0);
     +      n = 1 + x_opr_n_bytes (mra, 1);
     +      break;
     +    case BM_OPR_W:
     +      operand[(*n_operands)++] = x_opr_decode_with_size (mra, 1, 1);
     +      n = 1 + x_opr_n_bytes (mra, 1);
     +      break;
     +    case BM_OPR_L:
     +      operand[(*n_operands)++] = x_opr_decode_with_size (mra, 1, 3);
     +      n = 1 + x_opr_n_bytes (mra, 1);
     +      break;
     +    case BM_OPR_REG:
     +    case BM_RESERVED1:
     +      {
     +	uint8_t xb;
     +	mra->read (mra, +1, 1, &xb);
     +	/* Don't emit a size suffix for register operands */
     +	if ((xb & 0xF8) != 0xB8)
     +	  {
     +	    short os = (bm & 0x0c) >> 2;
     +	    operand[(*n_operands)++] = x_opr_decode_with_size (mra, 1, os);
     +	  }
     +	else
     +	  operand[(*n_operands)++] = x_opr_decode (mra, 1);
     +
     +      }
     +      break;
     +    }
     +
     +  int imm = 0;
     +  switch (mode)
     +    {
     +    case BM_OPR_L:
     +      imm |= (bm & 0x02) << 3;
     +      /* fall through */
     +    case BM_OPR_W:
     +      imm |= (bm & 0x01) << 3;
     +      /* fall through */
     +    case BM_OPR_B:
     +      imm |= (bm & 0x70) >> 4;
     +      operand[(*n_operands)++] = create_immediate_operand (imm);
     +      break;
     +    case BM_RESERVED0:
     +      imm = (bm & 0x38) >> 3;
     +      operand[(*n_operands)++] = create_immediate_operand (imm);
     +      break;
     +    case BM_REG_IMM:
     +      imm = (bm & 0xF8) >> 3;
     +      operand[(*n_operands)++] = create_immediate_operand (imm);
     +      break;
     +    case BM_OPR_REG:
     +    case BM_RESERVED1:
     +      operand[(*n_operands)++] = create_register_operand ((bm & 0x70) >> 4);
     +      n += x_opr_n_bytes (mra, 1);
     +      break;
     +    }
     +
     +  rel_15_7 (mra, n + 1, n_operands, operand);
     +}
     +
     +static int
     +bm_n_bytes (struct mem_read_abstraction_base *mra)
     +{
     +  uint8_t bm;
     +  int status = mra->read (mra, 0, 1, &bm);
     +  if (status < 0)
     +    return status;
     +
     +  size_t i;
     +  enum BM_MODE mode = -1;
     +  for (i = 0; i < sizeof (bm_table) / sizeof (bm_table[0]); ++i)
     +    {
     +      const struct bm *bme = bm_table + i;
     +      if ((bm & bme->mask) == bme->value)
     +	{
     +	  mode = bme->mode;
     +	  break;
     +	}
     +    }
     +
     +  int n = 2;
     +  switch (mode)
     +    {
     +    case BM_REG_IMM:
     +    case BM_RESERVED0:
     +      break;
     +
     +    case BM_OPR_B:
     +    case BM_OPR_W:
     +    case BM_OPR_L:
     +      n += x_opr_n_bytes (mra, 1);
     +      break;
     +    case BM_OPR_REG:
     +    case BM_RESERVED1:
     +      n += x_opr_n_bytes (mra, 1);
     +      break;
     +    }
     +
     +  return n;
     +}
     +
     +static int
     +bm_rel_n_bytes (struct mem_read_abstraction_base *mra)
     +{
     +  int n = 1 + bm_n_bytes (mra);
     +
     +  bfd_byte rb;
     +  int status = mra->read (mra, n - 2, 1, &rb);
     +  if (status != 0)
     +    return status;
     +
     +  if (rb & 0x80)
     +    n++;
     +
     +  return n;
     +}
     +
     +
     +
     +
     +
     +/* shift direction */
     +enum SB_DIR
     +  {
     +    SB_LEFT,
     +    SB_RIGHT
     +  };
     +
     +enum SB_TYPE
     +  {
     +    SB_ARITHMETIC,
     +    SB_LOGICAL
     +  };
     +
     +
     +enum SB_MODE
     +  {
     +    SB_REG_REG_N_EFF,
     +    SB_REG_REG_N,
     +    SB_REG_OPR_EFF,
     +    SB_ROT,
     +    SB_REG_OPR_OPR,
     +    SB_OPR_N
     +  };
     +
     +struct sb
     +{
     +  uint8_t mask;
     +  uint8_t value;
     +  enum SB_MODE mode;
     +};
     +
     +static const  struct sb sb_table[] = {
     +  {0x30, 0x00,     SB_REG_REG_N_EFF},
     +  {0x30, 0x10,     SB_REG_REG_N},
     +  {0x34, 0x20,     SB_REG_OPR_EFF},
     +  {0x34, 0x24,     SB_ROT},
     +  {0x34, 0x30,     SB_REG_OPR_OPR},
     +  {0x34, 0x34,     SB_OPR_N},
     +};
     +
     +static int
     +shift_n_bytes (struct mem_read_abstraction_base *mra)
     +{
     +  bfd_byte sb;
     +  int status = mra->read (mra, 0, 1, &sb);
     +  if (status != 0)
     +    return status;
     +
     +  size_t i;
     +  enum SB_MODE mode = -1;
     +  for (i = 0; i < sizeof (sb_table) / sizeof (sb_table[0]); ++i)
     +    {
     +      const struct sb *sbe = sb_table + i;
     +      if ((sb & sbe->mask) == sbe->value)
     +	mode = sbe->mode;
     +    }
     +
     +  switch (mode)
     +    {
     +    case SB_REG_REG_N_EFF:
     +      return 2;
     +      break;
     +    case SB_REG_OPR_EFF:
     +    case SB_ROT:
     +      return 2 + x_opr_n_bytes (mra, 1);
     +      break;
     +    case SB_REG_OPR_OPR:
     +      {
     +	int opr1 = x_opr_n_bytes (mra, 1);
     +	int opr2 = 0;
     +	if ((sb & 0x30) != 0x20)
     +	  opr2 = x_opr_n_bytes (mra, opr1 + 1);
     +	return 2 + opr1 + opr2;
     +      }
     +      break;
     +    default:
     +      return 3;
     +    }
     +
     +  /* not reached */
     +  return -1;
     +}
     +
     +
     +static int
     +
     +mov_imm_opr_n_bytes (struct mem_read_abstraction_base *mra)
     +{
     +  bfd_byte byte;
     +  int status = mra->read (mra, -1, 1,  &byte);
     +  if (status < 0)
     +    return status;
     +
     +  int size = byte - 0x0c + 1;
     +
     +  return size + x_opr_n_bytes (mra, size) + 1;
     +}
     +
     +static void
     +mov_imm_opr (struct mem_read_abstraction_base *mra,
     +	     int *n_operands, struct operand **operand)
     +{
     +  bfd_byte byte;
     +  int status = mra->read (mra, -1, 1, &byte);
     +  if (status < 0)
     +    return ;
     +
     +  int size = byte - 0x0c + 1;
     +  uint32_t imm = decode_signed_value (mra, size);
     +
     +  operand[(*n_operands)++] = create_immediate_operand (imm);
     +  operand[(*n_operands)++] = x_opr_decode (mra, size);
     +}
     +
     +
     +
     +static void
     +ld_18bit_decode (struct mem_read_abstraction_base *mra,
     +		 int *n_operands, struct operand **operand)
     +{
     +  size_t size = 3;
     +  bfd_byte buffer[3];
     +  int status = mra->read (mra, 0, 2, buffer + 1);
     +  if (status < 0)
     +    return ;
     +
     +  status = mra->read (mra, -1, 1, buffer);
     +  if (status < 0)
     +    return ;
     +
     +  buffer[0] = (buffer[0] & 0x30) >> 4;
     +
     +  size_t i;
     +  uint32_t imm = 0;
     +  for (i = 0; i < size; ++i)
     +    {
     +      imm |= buffer[i] << (8 * (size - i - 1));
     +    }
     +
     +  operand[(*n_operands)++] = create_immediate_operand (imm);
     +}
     +
     +
     +
     +/* Loop Primitives */
     +
     +enum LP_MODE {
     +  LP_REG,
     +  LP_XY,
     +  LP_OPR
     +};
     +
     +struct lp
     +{
     +  uint8_t mask;
     +  uint8_t value;
     +  enum LP_MODE mode;
     +};
     +
     +static const struct lp lp_mode[] = {
     +  {0x08, 0x00, LP_REG},
     +  {0x0C, 0x08, LP_XY},
     +  {0x0C, 0x0C, LP_OPR},
     +};
     +
     +
     +static int
     +loop_prim_n_bytes (struct mem_read_abstraction_base *mra)
     +{
     +  int mx = 0;
     +  uint8_t lb;
     +  mra->read (mra, mx++, 1, &lb);
     +
     +  enum LP_MODE mode = -1;
     +  size_t i;
     +  for (i = 0; i < sizeof (lp_mode) / sizeof (lp_mode[0]); ++i)
     +    {
     +      const struct lp *pb = lp_mode + i;
     +      if ((lb & pb->mask) == pb->value)
     +	{
     +	  mode = pb->mode;
     +	  break;
     +	}
     +    }
     +
     +  if (mode == LP_OPR)
     +    {
     +      mx += x_opr_n_bytes (mra, mx) ;
     +    }
     +
     +  uint8_t rb;
     +  mra->read (mra, mx++, 1, &rb);
     +  if (rb & 0x80)
     +    mx++;
     +
     +  return mx + 1;
     +}
     +
     +
     +
     +
     +static enum operator
     +exg_sex_discrim (struct mem_read_abstraction_base *mra, enum operator hint ATTRIBUTE_UNUSED)
     +{
     +  uint8_t eb;
     +  int status = mra->read (mra, 0, 1, &eb);
     +  if (status < 0)
     +    return OP_INVALID;
     +
     +  struct operand *op0 = create_register_operand ((eb & 0xf0) >> 4);
     +  struct operand *op1 = create_register_operand (eb & 0xf);
     +
     +  const struct reg *r0 = registers + ((struct register_operand *) op0)->reg;
     +  const struct reg *r1 = registers + ((struct register_operand *) op1)->reg;
     +
     +  enum operator operator = (r0->bytes < r1->bytes) ? OP_sex : OP_exg;
     +
     +  free (op0);
     +  free (op1);
     +  
     +  return operator;
     +}
     +
     +
     +static void
     +exg_sex_decode (struct mem_read_abstraction_base *mra,
     +		int *n_operands, struct operand **operands)
     +{
     +  uint8_t eb;
     +  int status = mra->read (mra, 0, 1, &eb);
     +  if (status < 0)
     +    return;
     +
     +  /* Ship out the operands.  */
     +  operands[(*n_operands)++] =  create_register_operand ((eb & 0xf0) >> 4);
     +  operands[(*n_operands)++] =  create_register_operand (eb & 0xf);
     +}
     +
     +static enum operator
     +loop_primitive_discrim (struct mem_read_abstraction_base *mra,
     +			enum operator hint ATTRIBUTE_UNUSED)
     +{
     +  uint8_t lb;
     +  int status = mra->read (mra, 0, 1, &lb);
     +  if (status < 0)
     +    return OP_INVALID;
     +
     +  enum operator opbase = (lb & 0x80) ? OP_dbNE : OP_tbNE;
     +  return opbase + ((lb & 0x70) >> 4);
     +}
     +
     +static void
     +loop_primitive_decode (struct mem_read_abstraction_base *mra,
     +		  int *n_operands, struct operand **operands)
     +{
     +  int offs = 1;
     +  uint8_t lb;
     +  int status = mra->read (mra, 0, 1, &lb);
     +  if (status < 0)
     +    return ;
     +
     +  enum LP_MODE mode = -1;
     +  size_t i;
     +  for (i = 0; i < sizeof (lp_mode) / sizeof (lp_mode[0]); ++i)
     +    {
     +      const struct lp *pb = lp_mode + i;
     +      if ((lb & pb->mask) == pb->value)
     +	{
     +	  mode = pb->mode;
     +	  break;
     +	}
     +    }
     +
     +  switch (mode)
     +    {
     +    case LP_REG:
     +      operands[(*n_operands)++] = create_register_operand (lb & 0x07);
     +      break;
     +    case LP_XY:
     +      operands[(*n_operands)++] =
     +	create_register_operand ((lb & 0x01) + REG_X);
     +      break;
     +    case LP_OPR:
     +      offs += x_opr_n_bytes (mra, 1);
     +      operands[(*n_operands)++] = x_opr_decode_with_size (mra, 1, lb & 0x03);
     +      break;
     +    }
     +
     +  rel_15_7 (mra, offs + 1, n_operands, operands);
     +}
     +
     +
     +static enum operator
     +shift_discrim (struct mem_read_abstraction_base *mra,  enum operator hint ATTRIBUTE_UNUSED)
     +{
     +  size_t i;
     +  uint8_t sb;
     +  int status = mra->read (mra, 0, 1, &sb);
     +  if (status < 0)
     +    return status;
     +
     +  enum SB_DIR  dir = (sb & 0x40) ? SB_LEFT : SB_RIGHT;
     +  enum SB_TYPE type = (sb & 0x80) ? SB_ARITHMETIC : SB_LOGICAL;
     +  enum SB_MODE mode = -1;
     +  for (i = 0; i < sizeof (sb_table) / sizeof (sb_table[0]); ++i)
     +    {
     +      const struct sb *sbe = sb_table + i;
     +      if ((sb & sbe->mask) == sbe->value)
     +	mode = sbe->mode;
     +    }
     +
     +  if (mode == SB_ROT)
     +    return (dir == SB_LEFT) ? OP_rol : OP_ror;
     +
     +  if (type == SB_LOGICAL)
     +    return (dir == SB_LEFT) ? OP_lsl : OP_lsr;
     +
     +  return (dir == SB_LEFT) ? OP_asl : OP_asr;
     +}
     +
     +
     +static void
     +shift_decode (struct mem_read_abstraction_base *mra,  int *n_operands, struct operand **operands)
     +{
     +  size_t i;
     +
     +  uint8_t byte;
     +  int status = mra->read (mra, -1, 1, &byte);
     +  if (status < 0)
     +    return ;
     +
     +  uint8_t sb;
     +  status = mra->read (mra, 0, 1, &sb);
     +  if (status < 0)
     +    return ;
     +
     +  enum SB_MODE mode = -1;
     +  for (i = 0; i < sizeof (sb_table) / sizeof (sb_table[0]); ++i)
     +    {
     +      const struct sb *sbe = sb_table + i;
     +      if ((sb & sbe->mask) == sbe->value)
     +	mode = sbe->mode;
     +    }
     +
     +  short osize = -1;
     +  switch (mode)
     +    {
     +    case SB_REG_OPR_EFF:
     +    case SB_ROT:
     +    case SB_REG_OPR_OPR:
     +      osize = sb & 0x03;
     +      break;
     +    case SB_OPR_N:
     +      {
     +	uint8_t xb;
     +	mra->read (mra, 1, 1, &xb);
     +	/* The size suffix is not printed if the OPR operand refers
     +	   directly to a register, because the size is implied by the
     +	   size of that register. */
     +	if ((xb & 0xF8) != 0xB8)
     +	  osize = sb & 0x03;
     +      }
     +      break;
     +    default:
     +      break;
     +    };
     +
     +  /* Destination register */
     +  switch (mode)
     +    {
     +    case SB_REG_REG_N_EFF:
     +    case SB_REG_REG_N:
     +      operands[(*n_operands)++] = create_register_operand (byte & 0x07);
     +      break;
     +    case SB_REG_OPR_EFF:
     +    case SB_REG_OPR_OPR:
     +      operands[(*n_operands)++] = create_register_operand (byte & 0x07);
     +      break;
     +
     +    case SB_ROT:
     +      operands[(*n_operands)++] = x_opr_decode_with_size (mra, 1, osize);
     +      break;
     +
     +    default:
     +      break;
     +    }
     +
     +  /* Source register */
     +  switch (mode)
     +    {
     +    case SB_REG_REG_N_EFF:
     +    case SB_REG_REG_N:
     +      operands[(*n_operands)++] =
     +	create_register_operand_with_size (sb & 0x07, osize);
     +      break;
     +
     +    case SB_REG_OPR_OPR:
     +      operands[(*n_operands)++] = x_opr_decode_with_size (mra, 1, osize);
     +      break;
     +
     +    default:
     +      break;
     +    }
     +
     +  /* 3rd arg */
     +  switch (mode)
     +    {
     +    case SB_REG_OPR_EFF:
     +    case SB_OPR_N:
     +      operands[(*n_operands)++] = x_opr_decode_with_size (mra, 1, osize);
     +      break;
     +
     +    case SB_REG_REG_N:
     +      {
     +        uint8_t xb;
     +        mra->read (mra, 1, 1, &xb);
     +
     +        /* This case is slightly unusual.
     +           If XB matches the binary pattern 0111XXXX, then instead of
     +           interpreting this as a general OPR postbyte in the IMMe4 mode,
     +           the XB byte is interpreted in s special way.  */
     +        if ((xb & 0xF0) == 0x70)
     +          {
     +            if (byte & 0x10)
     +              {
     +                int shift = ((sb & 0x08) >> 3) | ((xb & 0x0f) << 1);
     +                operands[(*n_operands)++] = create_immediate_operand (shift);
     +              }
     +            else
     +              {
     +                /* This should not happen.  */
     +                abort ();
     +              }
     +          }
     +        else
     +          {
     +            operands[(*n_operands)++] = x_opr_decode (mra, 1);
     +          }
     +      }
     +      break;
     +    case SB_REG_OPR_OPR:
     +      {
     +	uint8_t xb;
     +	int n = x_opr_n_bytes (mra, 1);
     +	mra->read (mra, 1 + n, 1, &xb);
     +
     +	if ((xb & 0xF0) == 0x70)
     +	  {
     +	    int imm = xb & 0x0F;
     +	    imm <<= 1;
     +	    imm |= (sb & 0x08) >> 3;
     +	    operands[(*n_operands)++] = create_immediate_operand (imm);
     +	  }
     +	else
     +	  {
     +	    operands[(*n_operands)++] = x_opr_decode (mra, 1 + n);
     +	  }
     +      }
     +      break;
     +    default:
     +      break;
     +    }
     +
     +  switch (mode)
     +    {
     +    case SB_REG_REG_N_EFF:
     +    case SB_REG_OPR_EFF:
     +    case SB_OPR_N:
     +      {
     +        int imm = (sb & 0x08) ? 2 : 1;
     +        operands[(*n_operands)++] = create_immediate_operand (imm);
     +      }
     +      break;
     +
     +    default:
     +      break;
     +    }
     +}
     +
     +static enum operator
     +psh_pul_discrim (struct mem_read_abstraction_base *mra,
     +		 enum operator hint ATTRIBUTE_UNUSED)
     +{
     +  uint8_t byte;
     +  int status = mra->read (mra, 0, 1, &byte);
     +  if (status != 0)
     +    return OP_INVALID;
     +
     +  return (byte & 0x80) ? OP_pull: OP_push;
     +}
     +
     +
     +static void
     +psh_pul_decode (struct mem_read_abstraction_base *mra,
     +		int *n_operands, struct operand **operand)
     +{
     +  uint8_t byte;
     +  int status = mra->read (mra, 0, 1, &byte);
     +  if (status != 0)
     +    return;
     +  int bit;
     +  if (byte & 0x40)
     +    {
     +      if ((byte & 0x3F) == 0)
     +        {
     +	  operand[(*n_operands)++] = create_register_all16_operand ();
     +        }
     +      else
     +	for (bit = 5; bit >= 0; --bit)
     +	  {
     +	    if (byte & (0x1 << bit))
     +	      {
     +		operand[(*n_operands)++] = create_register_operand (oprregs2[bit]);
     +	      }
     +	  }
     +    }
     +  else
     +    {
     +      if ((byte & 0x3F) == 0)
     +        {
     +	  operand[(*n_operands)++] = create_register_all_operand ();
     +        }
     +      else
     +	for (bit = 5; bit >= 0; --bit)
     +	  {
     +	    if (byte & (0x1 << bit))
     +	      {
     +		operand[(*n_operands)++] = create_register_operand (oprregs1[bit]);
     +	      }
     +	  }
     +    }
     +}
     +
     +static enum operator
     +bit_field_discrim (struct mem_read_abstraction_base *mra, enum operator hint ATTRIBUTE_UNUSED)
     +{
     +  int status;
     +  bfd_byte bb;
     +  status = mra->read (mra, 0, 1, &bb);
     +  if (status != 0)
     +    return OP_INVALID;
     +
     +  return  (bb & 0x80) ? OP_bfins : OP_bfext;
     +}
     +
     +static void
     +bit_field_decode (struct mem_read_abstraction_base *mra,
     +		  int *n_operands, struct operand **operands)
     +{
     +  int status;
     +
     +  bfd_byte byte2;
     +  status = mra->read (mra, -1, 1, &byte2);
     +  if (status != 0)
     +    return;
     +
     +  bfd_byte bb;
     +  status = mra->read (mra, 0, 1, &bb);
     +  if (status != 0)
     +    return;
     +
     +  enum BB_MODE mode = -1;
     +  size_t i;
     +  const struct opr_bb *bbs = 0;
     +  for (i = 0; i < sizeof (bb_modes) / sizeof (bb_modes[0]); ++i)
     +    {
     +      bbs = bb_modes + i;
     +      if ((bb & bbs->mask) == bbs->value)
     +        {
     +          mode = bbs->mode;
     +          break;
     +        }
     +    }
     +  int reg1 = byte2 & 0x07;
     +  /* First operand */
     +  switch (mode)
     +    {
     +    case BB_REG_REG_REG:
     +    case BB_REG_REG_IMM:
     +    case BB_REG_OPR_REG:
     +    case BB_REG_OPR_IMM:
     +      operands[(*n_operands)++] = create_register_operand (reg1);
     +      break;
     +    case BB_OPR_REG_REG:
     +      operands[(*n_operands)++] = x_opr_decode_with_size (mra, 1,
     +							  (bb >> 2) & 0x03);
     +      break;
     +    case BB_OPR_REG_IMM:
     +      operands[(*n_operands)++] = x_opr_decode_with_size (mra, 2,
     +							  (bb >> 2) & 0x03);
     +      break;
     +    }
     +
     +  /* Second operand */
     +  switch (mode)
     +    {
     +    case BB_REG_REG_REG:
     +    case BB_REG_REG_IMM:
     +      {
     +        int reg_src = (bb >> 2) & 0x07;
     +        operands[(*n_operands)++] = create_register_operand (reg_src);
     +      }
     +      break;
     +    case BB_OPR_REG_REG:
     +    case BB_OPR_REG_IMM:
     +      {
     +        int reg_src = (byte2 & 0x07);
     +        operands[(*n_operands)++] = create_register_operand (reg_src);
     +      }
     +      break;
     +    case BB_REG_OPR_REG:
     +      operands[(*n_operands)++] = x_opr_decode_with_size (mra, 1,
     +							  (bb >> 2) & 0x03);
     +      break;
     +    case BB_REG_OPR_IMM:
     +      operands[(*n_operands)++] = x_opr_decode_with_size (mra, 2,
     +							  (bb >> 2) & 0x03);
     +      break;
     +    }
     +
     +  /* Third operand */
     +  switch (mode)
     +    {
     +    case BB_REG_REG_REG:
     +    case BB_OPR_REG_REG:
     +    case BB_REG_OPR_REG:
     +      {
     +        int reg_parm = bb & 0x03;
     +	operands[(*n_operands)++] = create_register_operand (reg_parm);
     +      }
     +      break;
     +    case BB_REG_REG_IMM:
     +    case BB_OPR_REG_IMM:
     +    case BB_REG_OPR_IMM:
     +      {
     +        bfd_byte i1;
     +        mra->read (mra, 1, 1, &i1);
     +        int offset = i1 & 0x1f;
     +        int width = bb & 0x03;
     +        width <<= 3;
     +        width |= i1 >> 5;
     +        operands[(*n_operands)++] = create_bitfield_operand (width, offset);
     +      }
     +      break;
     +    }
     +}
     +
     +
     +/* Decode the next instruction at MRA, according to OPC.
     +   The operation to be performed is returned.
     +   The number of operands, will be placed in N_OPERANDS.
     +   The operands themselved into OPERANDS.  */
     +static enum operator
     +decode_operation (const struct opcode *opc,
     +		  struct mem_read_abstraction_base *mra,
     +		  int *n_operands, struct operand **operands)
     +{
     +  enum operator op = opc->operator;
     +  if (opc->discriminator)
     +    op = opc->discriminator (mra, opc->operator);
     +
     +  if (opc->operands)
     +    opc->operands (mra, n_operands, operands);
     +
     +  if (opc->operands2)
     +    opc->operands2 (mra, n_operands, operands);
     +
     +  return op;
     +}
     +
     +int
     +decode_s12z (enum operator *myoperator, short *osize,
     +	     int *n_operands, struct operand **operands,
     +	     struct mem_read_abstraction_base *mra)
     +{
     +  int n_bytes = 0;
     +  bfd_byte byte;
     +
     +  int status = mra->read (mra, 0, 1, &byte);
     +  if (status != 0)
     +    return status;
     +
     +  mra->advance (mra);
     +
     +  const struct opcode *opc = page1 + byte;
     +  if (byte == PAGE2_PREBYTE)
     +    {
     +      /* Opcodes in page2 have an additional byte */
     +      n_bytes++;
     +
     +      bfd_byte byte2;
     +      mra->read (mra, 0, 1, &byte2);
     +      mra->advance (mra);
     +      opc = page2 + byte2;
     +    }
     +  *myoperator = decode_operation (opc, mra, n_operands, operands);
     +  *osize = opc->osize;
     +
     +  /* Return the number of bytes in the instruction.  */
     +  n_bytes += (opc && opc->insn_bytes) ? opc->insn_bytes (mra) : 0;
     +
     +  return n_bytes;
     +}
     +
     diff --git a/opcodes/s12z-opc.h b/opcodes/s12z-opc.h
     new file mode 100644
     index 0000000000..186a7f29c3
     --- /dev/null
     +++ b/opcodes/s12z-opc.h
     @@ -0,0 +1,267 @@
     +/* s12z-dis.h -- Header file for s12z-dis.c and s12z-decode.c
     +   Copyright (C) 2019 Free Software Foundation, Inc.
     +
     +   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; see the file COPYING3. If not,
     +   see <http://www.gnu.org/licenses/>.  */
     +
     +#ifndef S12Z_OPC_H
     +#define S12Z_OPC_H
     +
     +#include <stdbool.h>
     +
     +/* An abstraction used to read machine code from a source.  */
     +struct mem_read_abstraction_base
     +{
     +  int (*read) (struct mem_read_abstraction_base *, int, size_t, bfd_byte *);
     +  void (*advance) (struct mem_read_abstraction_base *);
     +  bfd_vma (*posn) (struct mem_read_abstraction_base *);
     +};
     +
     +
     +/* Machine code operators.
     +   These *roughly* correspond to opcodes.
     +   But describe their purpose rather than their form.  */
     +enum operator
     +  {
     +    OP_INVALID = 0,
     +
     +    OP_push,
     +    OP_pull,
     +    /* Test and branch.  */
     +    OP_tbNE, OP_tbEQ, OP_tbPL, OP_tbMI, OP_tbGT, OP_tbLE,
     +    /* Decrement and branch.  */
     +    OP_dbNE, OP_dbEQ, OP_dbPL, OP_dbMI, OP_dbGT, OP_dbLE,
     +
     +    /* Note: sex and exg are the same opcode.
     +       They are mnemonic changes according to the operands.  */
     +    OP_sex,
     +    OP_exg,
     +
     +    /* Shifters.  */
     +    OP_lsl, OP_lsr,
     +    OP_asl, OP_asr,
     +    OP_rol, OP_ror,
     +    /* Bit field operations.  */
     +    OP_bfins, OP_bfext,
     +    OP_trap,
     +
     +    OP_ld,
     +    OP_st,
     +    OP_cmp,
     +
     +    OP_stop,
     +    OP_wai,
     +    OP_sys,
     +
     +    OP_minu,
     +    OP_mins,
     +    OP_maxu,
     +    OP_maxs,
     +
     +    OP_abs,
     +    OP_adc,
     +    OP_bit,
     +    OP_sbc,
     +    OP_rti,
     +    OP_clb,
     +    OP_eor,
     +
     +    OP_sat,
     +
     +    OP_nop,
     +    OP_bgnd,
     +    OP_brclr,
     +    OP_brset,
     +    OP_rts,
     +    OP_lea,
     +    OP_mov,
     +
     +    OP_bra,
     +    OP_bsr,
     +    OP_bhi,
     +    OP_bls,
     +    OP_bcc,
     +    OP_bcs,
     +    OP_bne,
     +    OP_beq,
     +    OP_bvc,
     +    OP_bvs,
     +    OP_bpl,
     +    OP_bmi,
     +    OP_bge,
     +    OP_blt,
     +    OP_bgt,
     +    OP_ble,
     +    OP_inc,
     +    OP_clr,
     +    OP_dec,
     +
     +    OP_add,
     +    OP_sub,
     +    OP_and,
     +    OP_or,
     +
     +    OP_tfr,
     +    OP_jmp,
     +    OP_jsr,
     +    OP_com,
     +    OP_andcc,
     +    OP_neg,
     +    OP_orcc,
     +    OP_bclr,
     +    OP_bset,
     +    OP_btgl,
     +    OP_swi,
     +
     +    OP_mulu,
     +    OP_divu,
     +    OP_modu,
     +    OP_macu,
     +    OP_qmulu,
     +
     +    OP_muls,
     +    OP_divs,
     +    OP_mods,
     +    OP_macs,
     +    OP_qmuls,
     +
     +    OPBASE_mul = 0x4000,
     +    OPBASE_div,
     +    OPBASE_mod,
     +    OPBASE_mac,
     +    OPBASE_qmul,
     +
     +    n_OPS
     +  };
     +
     +
     +/* Used for operands which mutate their index/base registers.
     +   Eg  ld d0, (s+).  */
     +enum op_reg_mutation
     +  {
     +    OPND_RM_NONE,
     +    OPND_RM_PRE_DEC,
     +    OPND_RM_PRE_INC,
     +    OPND_RM_POST_DEC,
     +    OPND_RM_POST_INC
     +  };
     +
     +/* The class of an operand.  */
     +enum opnd_class
     +  {
     +    OPND_CL_IMMEDIATE,
     +    OPND_CL_MEMORY,
     +    OPND_CL_REGISTER,
     +    OPND_CL_REGISTER_ALL,   /* Used only for psh/pul.  */
     +    OPND_CL_REGISTER_ALL16, /* Used only for psh/pul.  */
     +    OPND_CL_SIMPLE_MEMORY,
     +    OPND_CL_BIT_FIELD
     +  };
     +
     +
     +/* Base structure of all operands.  */
     +struct operand
     +{
     +  enum opnd_class cl;
     +
     +  /* OSIZE determines the size of memory access for
     +     the  operation in which the operand participates.
     +     It may be -1 which indicates either unknown
     +     (must be determined by other operands) or if
     +     it is not applicable for this operation.  */
     +  int osize;
     +};
     +
     +/* Immediate operands.  Eg: #23  */
     +struct immediate_operand
     +{
     +  struct operand parent;
     +  int value;
     +};
     +
     +/* Bitfield operands.   Used only in bfext and bfins
     +   instructions.  */
     +struct bitfield_operand
     +{
     +  struct operand parent;
     +  int width;
     +  int offset;
     +};
     +
     +/* Register operands.  */
     +struct register_operand
     +{
     +  struct operand parent;
     +  int reg;
     +};
     +
     +
     +/* Simple memory operands.  ie, direct memory,
     +   no index, no pre/post inc/dec.  May be either relative or absolute.
     +   Eg st d0, 0x123456  */
     +struct simple_memory_operand
     +{
     +  struct operand parent;
     +
     +  bfd_vma addr;
     +  bfd_vma base;
     +  bool relative;
     +};
     +
     +
     +/* Memory operands.    Should be able to represent all memory
     +   operands in the S12Z instruction set which are not simple
     +   memory operands.  */
     +struct memory_operand
     +{
     +  struct operand parent;
     +
     +  /* True for indirect operands: eg [0x123456]   */
     +  bool indirect;
     +
     +  /* The value of any offset.  eg 45 in (45,d7) */
     +    int base_offset;
     +
     +  /* Does this operand increment or decrement
     +     its participating registers.  Eg (-s) */
     +  enum op_reg_mutation mutation;
     +
     +  /* The number of registers participating in this operand.
     +     For S12Z this is always in the range [0, 6] (but for most
     +     instructions it's <= 2).  */
     +  int n_regs;
     +
     +  /* The participating registers.  */
     +  int regs[6];
     +};
     +
     +
     +/* Decode a single instruction.
     +   OPERATOR, OSIZE, N_OPERANDS and OPERANDS are pointers to
     +   variables which must be provided by the caller.
     +   N_OPERANDS will be incremented by the number of operands read, so
     +   you should assign it to something before calling this function.
     +   OPERANDS must be large enough to contain all operands read
     +   (which may be up to 6).
     +   It is the responsibility of the caller to free all operands
     +   when they are no longer needed.
     +   Returns the number of bytes read.  */
     +int decode_s12z (enum operator *myoperator, short *osize,
     +		 int *n_operands, struct operand **operands,
     +		 struct mem_read_abstraction_base *);
     +
     +
     +#endif /* S12Z_OPC_H  */
     -- 
     2.11.0

-- 
Avoid eavesdropping.  Send strong encrypted email.
PGP Public key ID: 1024D/2DE827B3 
fingerprint = 8797 A26D 0854 2EAB 0285  A290 8A67 719C 2DE8 27B3
See http://sks-keyservers.net or any PGP keyserver for public key.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]