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! Ping!

On Wed, Dec 19, 2018 at 06:30:09PM +0100, John Darrington wrote:
     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.

-- 
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]