| /* s12z-decode.c -- Freescale S12Z disassembly | 
 |    Copyright (C) 2018-2023 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 int (*operands_f) (struct mem_read_abstraction_base *, | 
 | 			   int *n_operands, struct operand **operand); | 
 |  | 
 | typedef enum optr (*discriminator_f) (struct mem_read_abstraction_base *, | 
 | 				      enum optr 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) | 
 | { | 
 |   int n = x_opr_n_bytes (mra, 0); | 
 |   if (n < 0) | 
 |     return n; | 
 |   return 1 + n; | 
 | } | 
 |  | 
 | static int | 
 | opr_n_bytes2 (struct mem_read_abstraction_base *mra) | 
 | { | 
 |   int s = x_opr_n_bytes (mra, 0); | 
 |   if (s < 0) | 
 |     return s; | 
 |   int n = x_opr_n_bytes (mra, s); | 
 |   if (n < 0) | 
 |     return n; | 
 |   return s + n + 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) | 
 |     { | 
 |       int x = x_opr_n_bytes (mra, n - 1); | 
 |       if (x < 0) | 
 | 	return x; | 
 |       n += x; | 
 |     } | 
 |  | 
 |   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)); | 
 |  | 
 |   if (op != NULL) | 
 |     { | 
 |       op->parent.cl = OPND_CL_IMMEDIATE; | 
 |       op->parent.osize = -1; | 
 |       op->value = value; | 
 |     } | 
 |   return (struct operand *) op; | 
 | } | 
 |  | 
 | static struct operand * | 
 | create_bitfield_operand (int width, int offset) | 
 | { | 
 |   struct bitfield_operand *op = malloc (sizeof (*op)); | 
 |  | 
 |   if (op != NULL) | 
 |     { | 
 |       op->parent.cl = OPND_CL_BIT_FIELD; | 
 |       op->parent.osize = -1; | 
 |       op->width = width; | 
 |       op->offset = offset; | 
 |     } | 
 |   return (struct operand *) op; | 
 | } | 
 |  | 
 | static struct operand * | 
 | create_register_operand_with_size (int reg, short osize) | 
 | { | 
 |   struct register_operand *op = malloc (sizeof (*op)); | 
 |  | 
 |   if (op != NULL) | 
 |     { | 
 |       op->parent.cl = OPND_CL_REGISTER; | 
 |       op->parent.osize = osize; | 
 |       op->reg = reg; | 
 |     } | 
 |   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)); | 
 |  | 
 |   if (op != NULL) | 
 |     { | 
 |       op->parent.cl = OPND_CL_REGISTER_ALL; | 
 |       op->parent.osize = -1; | 
 |     } | 
 |   return (struct operand *) op; | 
 | } | 
 |  | 
 | static struct operand * | 
 | create_register_all16_operand (void) | 
 | { | 
 |   struct register_operand *op = malloc (sizeof (*op)); | 
 |  | 
 |   if (op != NULL) | 
 |     { | 
 |       op->parent.cl = OPND_CL_REGISTER_ALL16; | 
 |       op->parent.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; | 
 |  | 
 |   assert (relative || base == 0); | 
 |   op = malloc (sizeof (*op)); | 
 |   if (op != NULL) | 
 |     { | 
 |       op->parent.cl = OPND_CL_SIMPLE_MEMORY; | 
 |       op->parent.osize = -1; | 
 |       op->addr = addr; | 
 |       op->base = base; | 
 |       op->relative = relative; | 
 |     } | 
 |   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)); | 
 |  | 
 |   if (op != NULL) | 
 |     { | 
 |       op->parent.cl = OPND_CL_MEMORY; | 
 |       op->parent.osize = -1; | 
 |       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; | 
 |     } | 
 |   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)); | 
 |  | 
 |   if (op != NULL) | 
 |     { | 
 |       op->parent.cl = OPND_CL_MEMORY; | 
 |       op->parent.osize = -1; | 
 |       op->indirect = false; | 
 |       op->base_offset = 0; | 
 |       op->mutation = mutation; | 
 |       op->n_regs = 1; | 
 |       op->regs[0] = reg; | 
 |       op->regs[1] = -1; | 
 |     } | 
 |   return (struct operand *) op; | 
 | } | 
 |  | 
 |  | 
 |  | 
 | static int | 
 | z_ext24_decode (struct mem_read_abstraction_base *mra, int *n_operands, | 
 | 		struct operand **operand) | 
 | { | 
 |   struct operand *op; | 
 |   uint8_t buffer[3]; | 
 |   int status = mra->read (mra, 0, 3, buffer); | 
 |   if (status < 0) | 
 |     return status; | 
 |  | 
 |   int i; | 
 |   uint32_t addr = 0; | 
 |   for (i = 0; i < 3; ++i) | 
 |     { | 
 |       addr <<= 8; | 
 |       addr |= buffer[i]; | 
 |     } | 
 |  | 
 |   op = create_simple_memory_operand (addr, 0, false); | 
 |   if (op == NULL) | 
 |     return -1; | 
 |   operand[(*n_operands)++] = op; | 
 |   return 0; | 
 | } | 
 |  | 
 |  | 
 | static int | 
 | z_decode_signed_value (struct mem_read_abstraction_base *mra, int offset, | 
 | 		       short size, uint32_t *result) | 
 | { | 
 |   assert (size >0); | 
 |   assert (size <= 4); | 
 |   bfd_byte buffer[4]; | 
 |   int status = mra->read (mra, offset, size, buffer); | 
 |   if (status < 0) | 
 |     return status; | 
 |  | 
 |   int i; | 
 |   uint32_t value = 0; | 
 |   for (i = 0; i < size; ++i) | 
 |     value = (value << 8) | buffer[i]; | 
 |  | 
 |   if (buffer[0] & 0x80) | 
 |     { | 
 |       /* Deal with negative values */ | 
 |       value -= 1u << (size * 4) << (size * 4); | 
 |     } | 
 |   *result = value; | 
 |   return 0; | 
 | } | 
 |  | 
 | static int | 
 | decode_signed_value (struct mem_read_abstraction_base *mra, short size, | 
 | 		     uint32_t *result) | 
 | { | 
 |   return z_decode_signed_value (mra, 0, size, result); | 
 | } | 
 |  | 
 | static int | 
 | x_imm1 (struct mem_read_abstraction_base *mra, | 
 | 	int offset, | 
 | 	int *n_operands, struct operand **operand) | 
 | { | 
 |   struct operand *op; | 
 |   bfd_byte byte; | 
 |   int status = mra->read (mra, offset, 1, &byte); | 
 |   if (status < 0) | 
 |     return status; | 
 |  | 
 |   op = create_immediate_operand (byte); | 
 |   if (op == NULL) | 
 |     return -1; | 
 |   operand[(*n_operands)++] = op; | 
 |   return 0; | 
 | } | 
 |  | 
 | /* An eight bit immediate operand.  */ | 
 | static int | 
 | imm1_decode (struct mem_read_abstraction_base *mra, | 
 | 	     int *n_operands, struct operand **operand) | 
 | { | 
 |   return x_imm1 (mra, 0, n_operands, operand); | 
 | } | 
 |  | 
 | static int | 
 | trap_decode (struct mem_read_abstraction_base *mra, | 
 | 	     int *n_operands, struct operand **operand) | 
 | { | 
 |   return 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; | 
 | 	status = mra->read (mra, offset, 1, &x1); | 
 | 	if (status < 0) | 
 | 	  return NULL; | 
 | 	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]; | 
 | 	status = mra->read (mra, offset, 3, x); | 
 | 	if (status < 0) | 
 | 	  return NULL; | 
 | 	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]; | 
 | 	status = mra->read (mra, offset, 3, x); | 
 | 	if (status < 0) | 
 | 	  return NULL; | 
 | 	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]; | 
 | 	status = mra->read (mra, offset, 3, x); | 
 | 	if (status < 0) | 
 | 	  return NULL; | 
 | 	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; | 
 | 	status = mra->read (mra, offset, 1, &x1); | 
 | 	if (status < 0) | 
 | 	  return NULL; | 
 | 	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]; | 
 | 	status = mra->read (mra, offset, 2, x); | 
 | 	if (status < 0) | 
 | 	  return NULL; | 
 | 	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) | 
 | 	  return 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; | 
 | 	status = mra->read (mra, offset, 1, &x1); | 
 | 	if (status < 0) | 
 | 	  return NULL; | 
 | 	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) | 
 | 	  return 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) | 
 | 	  return 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 (); | 
 |     } | 
 |  | 
 |   if (operand != NULL) | 
 |     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 int | 
 | z_opr_decode (struct mem_read_abstraction_base *mra, | 
 | 	      int *n_operands, struct operand **operand) | 
 | { | 
 |   struct operand *op = x_opr_decode (mra, 0); | 
 |   if (op == NULL) | 
 |     return -1; | 
 |   operand[(*n_operands)++] = op; | 
 |   return 0; | 
 | } | 
 |  | 
 | static int | 
 | z_opr_decode2 (struct mem_read_abstraction_base *mra, | 
 | 	       int *n_operands, struct operand **operand) | 
 | { | 
 |   int n = x_opr_n_bytes (mra, 0); | 
 |   if (n < 0) | 
 |     return n; | 
 |   struct operand *op = x_opr_decode (mra, 0); | 
 |   if (op == NULL) | 
 |     return -1; | 
 |   operand[(*n_operands)++] = op; | 
 |   op = x_opr_decode (mra, n); | 
 |   if (op == NULL) | 
 |     return -1; | 
 |   operand[(*n_operands)++] = op; | 
 |   return 0; | 
 | } | 
 |  | 
 | static int | 
 | imm1234 (struct mem_read_abstraction_base *mra, int base, | 
 | 	 int *n_operands, struct operand **operand) | 
 | { | 
 |   struct operand *op; | 
 |   bfd_byte opcode; | 
 |   int status = mra->read (mra, -1, 1, &opcode); | 
 |   if (status < 0) | 
 |     return status; | 
 |  | 
 |   opcode -= base; | 
 |  | 
 |   int size = registers[opcode & 0xF].bytes; | 
 |  | 
 |   uint32_t imm; | 
 |   if (decode_signed_value (mra, size, &imm) < 0) | 
 |     return -1; | 
 |  | 
 |   op = create_immediate_operand (imm); | 
 |   if (op == NULL) | 
 |     return -1; | 
 |   operand[(*n_operands)++] = op; | 
 |   return 0; | 
 | } | 
 |  | 
 |  | 
 | /* Special case of LD and CMP with register S and IMM operand */ | 
 | static int | 
 | reg_s_imm (struct mem_read_abstraction_base *mra, int *n_operands, | 
 | 	   struct operand **operand) | 
 | { | 
 |   struct operand *op; | 
 |  | 
 |   op = create_register_operand (REG_S); | 
 |   if (op == NULL) | 
 |     return -1; | 
 |   operand[(*n_operands)++] = op; | 
 |  | 
 |   uint32_t imm; | 
 |   if (decode_signed_value (mra, 3, &imm) < 0) | 
 |     return -1; | 
 |   op = create_immediate_operand (imm); | 
 |   if (op == NULL) | 
 |     return -1; | 
 |   operand[(*n_operands)++] = op; | 
 |   return 0; | 
 | } | 
 |  | 
 | /* Special case of LD, CMP and ST with register S and OPR operand */ | 
 | static int | 
 | reg_s_opr (struct mem_read_abstraction_base *mra, int *n_operands, | 
 | 	   struct operand **operand) | 
 | { | 
 |   struct operand *op; | 
 |  | 
 |   op = create_register_operand (REG_S); | 
 |   if (op == NULL) | 
 |     return -1; | 
 |   operand[(*n_operands)++] = op; | 
 |   op = x_opr_decode (mra, 0); | 
 |   if (op == NULL) | 
 |     return -1; | 
 |   operand[(*n_operands)++] = op; | 
 |   return 0; | 
 | } | 
 |  | 
 | static int | 
 | z_imm1234_8base (struct mem_read_abstraction_base *mra, int *n_operands, | 
 | 		 struct operand **operand) | 
 | { | 
 |   return imm1234 (mra, 8, n_operands, operand); | 
 | } | 
 |  | 
 | static int | 
 | z_imm1234_0base (struct mem_read_abstraction_base *mra, int *n_operands, | 
 | 		 struct operand **operand) | 
 | { | 
 |   return imm1234 (mra, 0, n_operands, operand); | 
 | } | 
 |  | 
 |  | 
 | static int | 
 | z_tfr (struct mem_read_abstraction_base *mra, int *n_operands, | 
 |        struct operand **operand) | 
 | { | 
 |   struct operand *op; | 
 |   bfd_byte byte; | 
 |   int status = mra->read (mra, 0, 1, &byte); | 
 |   if (status < 0) | 
 |     return status; | 
 |  | 
 |   op = create_register_operand (byte >> 4); | 
 |   if (op == NULL) | 
 |     return -1; | 
 |   operand[(*n_operands)++] = op; | 
 |   op = create_register_operand (byte & 0x0F); | 
 |   if (op == NULL) | 
 |     return -1; | 
 |   operand[(*n_operands)++] = op; | 
 |   return 0; | 
 | } | 
 |  | 
 | static int | 
 | z_reg (struct mem_read_abstraction_base *mra, int *n_operands, | 
 |        struct operand **operand) | 
 | { | 
 |   struct operand *op; | 
 |   bfd_byte byte; | 
 |   int status = mra->read (mra, -1, 1, &byte); | 
 |   if (status < 0) | 
 |     return status; | 
 |  | 
 |   op = create_register_operand (byte & 0x07); | 
 |   if (op == NULL) | 
 |     return -1; | 
 |   operand[(*n_operands)++] = op; | 
 |   return 0; | 
 | } | 
 |  | 
 |  | 
 | static int | 
 | reg_xy (struct mem_read_abstraction_base *mra, | 
 | 	int *n_operands, struct operand **operand) | 
 | { | 
 |   struct operand *op; | 
 |   bfd_byte byte; | 
 |   int status = mra->read (mra, -1, 1, &byte); | 
 |   if (status < 0) | 
 |     return status; | 
 |  | 
 |   op = create_register_operand ((byte & 0x01) ? REG_Y : REG_X); | 
 |   if (op == NULL) | 
 |     return -1; | 
 |   operand[(*n_operands)++] = op; | 
 |   return 0; | 
 | } | 
 |  | 
 | static int | 
 | lea_reg_xys_opr (struct mem_read_abstraction_base *mra, | 
 | 		 int *n_operands, struct operand **operand) | 
 | { | 
 |   struct operand *op; | 
 |   bfd_byte byte; | 
 |   int status = mra->read (mra, -1, 1, &byte); | 
 |   if (status < 0) | 
 |     return status; | 
 |  | 
 |   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; | 
 |     } | 
 |  | 
 |   op = create_register_operand (reg_xys); | 
 |   if (op == NULL) | 
 |     return -1; | 
 |   operand[(*n_operands)++] = op; | 
 |   op = x_opr_decode (mra, 0); | 
 |   if (op == NULL) | 
 |     return -1; | 
 |   operand[(*n_operands)++] = op; | 
 |   return 0; | 
 | } | 
 |  | 
 | static int | 
 | lea_reg_xys (struct mem_read_abstraction_base *mra, | 
 | 	     int *n_operands, struct operand **operand) | 
 | { | 
 |   struct operand *op; | 
 |   bfd_byte byte; | 
 |   int status = mra->read (mra, -1, 1, &byte); | 
 |   if (status < 0) | 
 |     return status; | 
 |  | 
 |   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 status; | 
 |  | 
 |   op = create_register_operand (reg_n); | 
 |   if (op == NULL) | 
 |     return -1; | 
 |   operand[(*n_operands)++] = op; | 
 |   op = create_memory_operand (false, (int8_t) byte, 1, reg_n, -1); | 
 |   if (op == NULL) | 
 |     return -1; | 
 |   operand[(*n_operands)++] = op; | 
 |   return 0; | 
 | } | 
 |  | 
 |  | 
 | /* PC Relative offsets of size 15 or 7 bits */ | 
 | static int | 
 | rel_15_7 (struct mem_read_abstraction_base *mra, int offset, | 
 | 	  int *n_operands, struct operand **operands) | 
 | { | 
 |   struct operand *op; | 
 |   bfd_byte upper; | 
 |   int status = mra->read (mra, offset - 1, 1, &upper); | 
 |   if (status < 0) | 
 |     return status; | 
 |  | 
 |   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 status; | 
 |  | 
 |       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; | 
 |     } | 
 |  | 
 |   op = create_simple_memory_operand (addr, mra->posn (mra) - 1, true); | 
 |   if (op == NULL) | 
 |     return -1; | 
 |   operands[(*n_operands)++] = op; | 
 |   return 0; | 
 | } | 
 |  | 
 |  | 
 | /* PC Relative offsets of size 15 or 7 bits */ | 
 | static int | 
 | decode_rel_15_7 (struct mem_read_abstraction_base *mra, | 
 | 		 int *n_operands, struct operand **operand) | 
 | { | 
 |   return 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 int psh_pul_decode (struct mem_read_abstraction_base *mra, int *n_operands, struct operand **operand); | 
 | static int shift_decode (struct mem_read_abstraction_base *mra, int *n_operands, struct operand **operand); | 
 | static int mul_decode (struct mem_read_abstraction_base *mra, int *n_operands, struct operand **operand); | 
 | static int bm_decode (struct mem_read_abstraction_base *mra, int *n_operands, struct operand **operand); | 
 | static int bm_rel_decode (struct mem_read_abstraction_base *mra, int *n_operands, struct operand **operand); | 
 | static int mov_imm_opr (struct mem_read_abstraction_base *mra, int *n_operands, struct operand **operand); | 
 | static int loop_primitive_decode (struct mem_read_abstraction_base *mra, int *n_operands, struct operand **operands); | 
 | static int bit_field_decode (struct mem_read_abstraction_base *mra, int *n_operands, struct operand **operands); | 
 | static int exg_sex_decode (struct mem_read_abstraction_base *mra, int *n_operands, struct operand **operands); | 
 |  | 
 |  | 
 | static enum optr shift_discrim (struct mem_read_abstraction_base *mra, enum optr hint); | 
 | static enum optr psh_pul_discrim (struct mem_read_abstraction_base *mra, enum optr hint); | 
 | static enum optr mul_discrim (struct mem_read_abstraction_base *mra, enum optr hint); | 
 | static enum optr loop_primitive_discrim (struct mem_read_abstraction_base *mra, enum optr hint); | 
 | static enum optr bit_field_discrim (struct mem_read_abstraction_base *mra, enum optr hint); | 
 | static enum optr exg_sex_discrim (struct mem_read_abstraction_base *mra, enum optr hint); | 
 |  | 
 |  | 
 | static int | 
 | cmp_xy (struct mem_read_abstraction_base *mra ATTRIBUTE_UNUSED, | 
 | 	int *n_operands, struct operand **operand) | 
 | { | 
 |   struct operand *op; | 
 |  | 
 |   op = create_register_operand (REG_X); | 
 |   if (op == NULL) | 
 |     return -1; | 
 |   operand[(*n_operands)++] = op; | 
 |   op = create_register_operand (REG_Y); | 
 |   if (op == NULL) | 
 |     return -1; | 
 |   operand[(*n_operands)++] = op; | 
 |   return 0; | 
 | } | 
 |  | 
 | static int | 
 | sub_d6_x_y (struct mem_read_abstraction_base *mra ATTRIBUTE_UNUSED, | 
 | 	    int *n_operands, struct operand **operand) | 
 | { | 
 |   struct operand *op; | 
 |  | 
 |   op = create_register_operand (REG_D6); | 
 |   if (op == NULL) | 
 |     return -1; | 
 |   operand[(*n_operands)++] = op; | 
 |   op = create_register_operand (REG_X); | 
 |   if (op == NULL) | 
 |     return -1; | 
 |   operand[(*n_operands)++] = op; | 
 |   op = create_register_operand (REG_Y); | 
 |   if (op == NULL) | 
 |     return -1; | 
 |   operand[(*n_operands)++] = op; | 
 |   return 0; | 
 | } | 
 |  | 
 | static int | 
 | sub_d6_y_x (struct mem_read_abstraction_base *mra ATTRIBUTE_UNUSED, | 
 | 	    int *n_operands, struct operand **operand) | 
 | { | 
 |   struct operand *op; | 
 |  | 
 |   op = create_register_operand (REG_D6); | 
 |   if (op == NULL) | 
 |     return -1; | 
 |   operand[(*n_operands)++] = op; | 
 |   op = create_register_operand (REG_Y); | 
 |   if (op == NULL) | 
 |     return -1; | 
 |   operand[(*n_operands)++] = op; | 
 |   op = create_register_operand (REG_X); | 
 |   if (op == NULL) | 
 |     return -1; | 
 |   operand[(*n_operands)++] = op; | 
 |   return 0; | 
 | } | 
 |  | 
 | static int | 
 | ld_18bit_decode (struct mem_read_abstraction_base *mra, int *n_operands, | 
 | 		 struct operand **operand); | 
 |  | 
 | static enum optr | 
 | mul_discrim (struct mem_read_abstraction_base *mra, enum optr 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 optr 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 int | 
 | mul_decode (struct mem_read_abstraction_base *mra, | 
 | 	    int *n_operands, struct operand **operand) | 
 | { | 
 |   uint8_t mb; | 
 |   struct operand *op; | 
 |   int status = mra->read (mra, 0, 1, &mb); | 
 |   if (status < 0) | 
 |     return status; | 
 |  | 
 |   uint8_t byte; | 
 |   status = mra->read (mra, -1, 1, &byte); | 
 |   if (status < 0) | 
 |     return status; | 
 |  | 
 |   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; | 
 | 	} | 
 |     } | 
 |   op = create_register_operand (byte & 0x07); | 
 |   if (op == NULL) | 
 |     return -1; | 
 |   operand[(*n_operands)++] = op; | 
 |  | 
 |   switch (mode) | 
 |     { | 
 |     case MUL_REG_IMM: | 
 |       { | 
 | 	int size = (mb & 0x3); | 
 | 	op = create_register_operand_with_size ((mb & 0x38) >> 3, size); | 
 | 	if (op == NULL) | 
 | 	  return -1; | 
 | 	operand[(*n_operands)++] = op; | 
 |  | 
 | 	uint32_t imm; | 
 | 	if (z_decode_signed_value (mra, 1, size + 1, &imm) < 0) | 
 | 	  return -1; | 
 | 	op = create_immediate_operand (imm); | 
 | 	if (op == NULL) | 
 | 	  return -1; | 
 | 	operand[(*n_operands)++] = op; | 
 |       } | 
 |       break; | 
 |     case MUL_REG_REG: | 
 |       op = create_register_operand ((mb & 0x38) >> 3); | 
 |       if (op == NULL) | 
 | 	return -1; | 
 |       operand[(*n_operands)++] = op; | 
 |       op = create_register_operand (mb & 0x07); | 
 |       if (op == NULL) | 
 | 	return -1; | 
 |       operand[(*n_operands)++] = op; | 
 |       break; | 
 |     case MUL_REG_OPR: | 
 |       op = create_register_operand ((mb & 0x38) >> 3); | 
 |       if (op == NULL) | 
 | 	return -1; | 
 |       operand[(*n_operands)++] = op; | 
 |       op = x_opr_decode_with_size (mra, 1, mb & 0x3); | 
 |       if (op == NULL) | 
 | 	return -1; | 
 |       operand[(*n_operands)++] = op; | 
 |       break; | 
 |     case MUL_OPR_OPR: | 
 |       { | 
 | 	int first = x_opr_n_bytes (mra, 1); | 
 | 	if (first < 0) | 
 | 	  return first; | 
 | 	op = x_opr_decode_with_size (mra, 1, (mb & 0x30) >> 4); | 
 | 	if (op == NULL) | 
 | 	  return -1; | 
 | 	operand[(*n_operands)++] = op; | 
 | 	op = x_opr_decode_with_size (mra, first + 1, (mb & 0x0c) >> 2); | 
 | 	if (op == NULL) | 
 | 	  return -1; | 
 | 	operand[(*n_operands)++] = op; | 
 | 	break; | 
 |       } | 
 |     } | 
 |   return 0; | 
 | } | 
 |  | 
 |  | 
 | static int | 
 | mul_n_bytes (struct mem_read_abstraction_base *mra) | 
 | { | 
 |   int nx = 2; | 
 |   int first, second; | 
 |   uint8_t mb; | 
 |   int status = mra->read (mra, 0, 1, &mb); | 
 |   if (status < 0) | 
 |     return status; | 
 |  | 
 |   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: | 
 |       first = x_opr_n_bytes (mra, 1); | 
 |       if (first < 0) | 
 | 	return first; | 
 |       nx += first; | 
 |       break; | 
 |     case MUL_OPR_OPR: | 
 |       first = x_opr_n_bytes (mra, nx - 1); | 
 |       if (first < 0) | 
 | 	return first; | 
 |       nx += first; | 
 |       second = x_opr_n_bytes (mra, nx - 1); | 
 |       if (second < 0) | 
 | 	return second; | 
 |       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}, | 
 |  | 
 |   { 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 int | 
 | bm_decode (struct mem_read_abstraction_base *mra, | 
 | 	   int *n_operands, struct operand **operand) | 
 | { | 
 |   struct operand *op; | 
 |   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; | 
 | 	} | 
 |     } | 
 |  | 
 |   switch (mode) | 
 |     { | 
 |     case BM_REG_IMM: | 
 |     case BM_RESERVED0: | 
 |       op = create_register_operand (bm & 0x07); | 
 |       if (op == NULL) | 
 | 	return -1; | 
 |       operand[(*n_operands)++] = op; | 
 |       break; | 
 |     case BM_OPR_B: | 
 |       op = x_opr_decode_with_size (mra, 1, 0); | 
 |       if (op == NULL) | 
 | 	return -1; | 
 |       operand[(*n_operands)++] = op; | 
 |       break; | 
 |     case BM_OPR_W: | 
 |       op = x_opr_decode_with_size (mra, 1, 1); | 
 |       if (op == NULL) | 
 | 	return -1; | 
 |       operand[(*n_operands)++] = op; | 
 |       break; | 
 |     case BM_OPR_L: | 
 |       op = x_opr_decode_with_size (mra, 1, 3); | 
 |       if (op == NULL) | 
 | 	return -1; | 
 |       operand[(*n_operands)++] = op; | 
 |       break; | 
 |     case BM_OPR_REG: | 
 |     case BM_RESERVED1: | 
 |       { | 
 | 	uint8_t xb; | 
 | 	status = mra->read (mra, 1, 1, &xb); | 
 | 	if (status < 0) | 
 | 	  return status; | 
 | 	/* Don't emit a size suffix for register operands */ | 
 | 	if ((xb & 0xF8) != 0xB8) | 
 | 	  op = x_opr_decode_with_size (mra, 1, (bm & 0x0c) >> 2); | 
 | 	else | 
 | 	  op = x_opr_decode (mra, 1); | 
 | 	if (op == NULL) | 
 | 	  return -1; | 
 | 	operand[(*n_operands)++] = op; | 
 |       } | 
 |       break; | 
 |     } | 
 |  | 
 |   uint8_t imm = 0; | 
 |   switch (mode) | 
 |     { | 
 |     case BM_REG_IMM: | 
 |     case BM_RESERVED0: | 
 |       imm = (bm & 0x38) >> 3; | 
 |       op = create_immediate_operand (imm); | 
 |       if (op == NULL) | 
 | 	return -1; | 
 |       operand[(*n_operands)++] = op; | 
 |       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; | 
 |       op = create_immediate_operand (imm); | 
 |       if (op == NULL) | 
 | 	return -1; | 
 |       operand[(*n_operands)++] = op; | 
 |       break; | 
 |     case BM_OPR_REG: | 
 |     case BM_RESERVED1: | 
 |       op = create_register_operand ((bm & 0x70) >> 4); | 
 |       if (op == NULL) | 
 | 	return -1; | 
 |       operand[(*n_operands)++] = op; | 
 |       break; | 
 |     } | 
 |   return 0; | 
 | } | 
 |  | 
 |  | 
 | static int | 
 | bm_rel_decode (struct mem_read_abstraction_base *mra, | 
 | 	       int *n_operands, struct operand **operand) | 
 | { | 
 |   struct operand *op; | 
 |   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 = 1; | 
 |   switch (mode) | 
 |     { | 
 |     case BM_REG_IMM: | 
 |     case BM_RESERVED0: | 
 |       op = create_register_operand (bm & 0x07); | 
 |       if (op == NULL) | 
 | 	return -1; | 
 |       operand[(*n_operands)++] = op; | 
 |       break; | 
 |     case BM_OPR_B: | 
 |       op = x_opr_decode_with_size (mra, 1, 0); | 
 |       if (op == NULL) | 
 | 	return -1; | 
 |       operand[(*n_operands)++] = op; | 
 |       n = x_opr_n_bytes (mra, 1); | 
 |       if (n < 0) | 
 | 	return n; | 
 |       n += 1; | 
 |       break; | 
 |     case BM_OPR_W: | 
 |       op = x_opr_decode_with_size (mra, 1, 1); | 
 |       if (op == NULL) | 
 | 	return -1; | 
 |       operand[(*n_operands)++] = op; | 
 |       n = x_opr_n_bytes (mra, 1); | 
 |       if (n < 0) | 
 | 	return n; | 
 |       n += 1; | 
 |       break; | 
 |     case BM_OPR_L: | 
 |       op = x_opr_decode_with_size (mra, 1, 3); | 
 |       if (op == NULL) | 
 | 	return -1; | 
 |       operand[(*n_operands)++] = op; | 
 |       n = x_opr_n_bytes (mra, 1); | 
 |       if (n < 0) | 
 | 	return n; | 
 |       n += 1; | 
 |       break; | 
 |     case BM_OPR_REG: | 
 |     case BM_RESERVED1: | 
 |       { | 
 | 	uint8_t xb; | 
 | 	status = mra->read (mra, +1, 1, &xb); | 
 | 	if (status < 0) | 
 | 	  return status; | 
 | 	/* Don't emit a size suffix for register operands */ | 
 | 	if ((xb & 0xF8) != 0xB8) | 
 | 	  { | 
 | 	    short os = (bm & 0x0c) >> 2; | 
 | 	    op = x_opr_decode_with_size (mra, 1, os); | 
 | 	  } | 
 | 	else | 
 | 	  op = x_opr_decode (mra, 1); | 
 | 	if (op == NULL) | 
 | 	  return -1; | 
 | 	operand[(*n_operands)++] = op; | 
 |       } | 
 |       break; | 
 |     } | 
 |  | 
 |   int x, 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; | 
 |       op = create_immediate_operand (imm); | 
 |       if (op == NULL) | 
 | 	return -1; | 
 |       operand[(*n_operands)++] = op; | 
 |       break; | 
 |     case BM_RESERVED0: | 
 |       imm = (bm & 0x38) >> 3; | 
 |       op = create_immediate_operand (imm); | 
 |       if (op == NULL) | 
 | 	return -1; | 
 |       operand[(*n_operands)++] = op; | 
 |       break; | 
 |     case BM_REG_IMM: | 
 |       imm = (bm & 0xF8) >> 3; | 
 |       op = create_immediate_operand (imm); | 
 |       if (op == NULL) | 
 | 	return -1; | 
 |       operand[(*n_operands)++] = op; | 
 |       break; | 
 |     case BM_OPR_REG: | 
 |     case BM_RESERVED1: | 
 |       op = create_register_operand ((bm & 0x70) >> 4); | 
 |       if (op == NULL) | 
 | 	return -1; | 
 |       operand[(*n_operands)++] = op; | 
 |       x = x_opr_n_bytes (mra, 1); | 
 |       if (x < 0) | 
 | 	return x; | 
 |       n += x; | 
 |       break; | 
 |     } | 
 |  | 
 |   return 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 = 0; | 
 |   switch (mode) | 
 |     { | 
 |     case BM_REG_IMM: | 
 |     case BM_RESERVED0: | 
 |       break; | 
 |  | 
 |     case BM_OPR_B: | 
 |     case BM_OPR_W: | 
 |     case BM_OPR_L: | 
 |     case BM_OPR_REG: | 
 |     case BM_RESERVED1: | 
 |       n = x_opr_n_bytes (mra, 1); | 
 |       if (n < 0) | 
 | 	return n; | 
 |       break; | 
 |     } | 
 |  | 
 |   return n + 2; | 
 | } | 
 |  | 
 | 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 opr1, opr2; | 
 |   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; | 
 |     case SB_REG_OPR_EFF: | 
 |     case SB_ROT: | 
 |       opr1 = x_opr_n_bytes (mra, 1); | 
 |       if (opr1 < 0) | 
 | 	return opr1; | 
 |       return 2 + opr1; | 
 |     case SB_REG_OPR_OPR: | 
 |       opr1 = x_opr_n_bytes (mra, 1); | 
 |       if (opr1 < 0) | 
 | 	return opr1; | 
 |       opr2 = 0; | 
 |       if ((sb & 0x30) != 0x20) | 
 | 	{ | 
 | 	  opr2 = x_opr_n_bytes (mra, opr1 + 1); | 
 | 	  if (opr2 < 0) | 
 | 	    return opr2; | 
 | 	} | 
 |       return 2 + opr1 + opr2; | 
 |     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; | 
 |   int n = x_opr_n_bytes (mra, size); | 
 |   if (n < 0) | 
 |     return n; | 
 |  | 
 |   return size + n + 1; | 
 | } | 
 |  | 
 | static int | 
 | mov_imm_opr (struct mem_read_abstraction_base *mra, | 
 | 	     int *n_operands, struct operand **operand) | 
 | { | 
 |   struct operand *op; | 
 |   bfd_byte byte; | 
 |   int status = mra->read (mra, -1, 1, &byte); | 
 |   if (status < 0) | 
 |     return status; | 
 |  | 
 |   int size = byte - 0x0c + 1; | 
 |   uint32_t imm; | 
 |   if (decode_signed_value (mra, size, &imm)) | 
 |     return -1; | 
 |  | 
 |   op = create_immediate_operand (imm); | 
 |   if (op == NULL) | 
 |     return -1; | 
 |   operand[(*n_operands)++] = op; | 
 |   op = x_opr_decode (mra, size); | 
 |   if (op == NULL) | 
 |     return -1; | 
 |   operand[(*n_operands)++] = op; | 
 |   return 0; | 
 | } | 
 |  | 
 |  | 
 |  | 
 | static int | 
 | ld_18bit_decode (struct mem_read_abstraction_base *mra, | 
 | 		 int *n_operands, struct operand **operand) | 
 | { | 
 |   struct operand *op; | 
 |   size_t size = 3; | 
 |   bfd_byte buffer[3]; | 
 |   int status = mra->read (mra, 0, 2, buffer + 1); | 
 |   if (status < 0) | 
 |     return status; | 
 |  | 
 |   status = mra->read (mra, -1, 1, buffer); | 
 |   if (status < 0) | 
 |     return status; | 
 |  | 
 |   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)); | 
 |     } | 
 |  | 
 |   op = create_immediate_operand (imm); | 
 |   if (op == NULL) | 
 |     return -1; | 
 |   operand[(*n_operands)++] = op; | 
 |   return 0; | 
 | } | 
 |  | 
 |  | 
 |  | 
 | /* 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; | 
 |   int status = mra->read (mra, mx++, 1, &lb); | 
 |   if (status < 0) | 
 |     return status; | 
 |  | 
 |   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) | 
 |     { | 
 |       int n = x_opr_n_bytes (mra, mx); | 
 |       if (n < 0) | 
 | 	return n; | 
 |       mx += n; | 
 |     } | 
 |  | 
 |   uint8_t rb; | 
 |   status = mra->read (mra, mx++, 1, &rb); | 
 |   if (status < 0) | 
 |     return status; | 
 |   if (rb & 0x80) | 
 |     mx++; | 
 |  | 
 |   return mx + 1; | 
 | } | 
 |  | 
 |  | 
 |  | 
 |  | 
 | static enum optr | 
 | exg_sex_discrim (struct mem_read_abstraction_base *mra, | 
 | 		 enum optr hint ATTRIBUTE_UNUSED) | 
 | { | 
 |   uint8_t eb; | 
 |   int status = mra->read (mra, 0, 1, &eb); | 
 |   enum optr operator = OP_INVALID; | 
 |   if (status < 0) | 
 |     return operator; | 
 |  | 
 |   struct operand *op0 = create_register_operand ((eb & 0xf0) >> 4); | 
 |   if (op0 == NULL) | 
 |     return -1; | 
 |   struct operand *op1 = create_register_operand (eb & 0xf); | 
 |   if (op1 == NULL) | 
 |     return -1; | 
 |  | 
 |   int reg0 = ((struct register_operand *) op0)->reg; | 
 |   int reg1 = ((struct register_operand *) op1)->reg; | 
 |   if (reg0 >= 0 && reg0 < S12Z_N_REGISTERS | 
 |       && reg1 >= 0 && reg1 < S12Z_N_REGISTERS) | 
 |     { | 
 |       const struct reg *r0 = registers + reg0; | 
 |       const struct reg *r1 = registers + reg1; | 
 |  | 
 |       operator = r0->bytes < r1->bytes ? OP_sex : OP_exg; | 
 |     } | 
 |  | 
 |   free (op0); | 
 |   free (op1); | 
 |  | 
 |   return operator; | 
 | } | 
 |  | 
 |  | 
 | static int | 
 | exg_sex_decode (struct mem_read_abstraction_base *mra, | 
 | 		int *n_operands, struct operand **operands) | 
 | { | 
 |   struct operand *op; | 
 |   uint8_t eb; | 
 |   int status = mra->read (mra, 0, 1, &eb); | 
 |   if (status < 0) | 
 |     return status; | 
 |  | 
 |   /* Ship out the operands.  */ | 
 |   op = create_register_operand ((eb & 0xf0) >> 4); | 
 |   if (op == NULL) | 
 |     return -1; | 
 |   operands[(*n_operands)++] = op; | 
 |   op = create_register_operand (eb & 0xf); | 
 |   if (op == NULL) | 
 |     return -1; | 
 |   operands[(*n_operands)++] = op; | 
 |   return 0; | 
 | } | 
 |  | 
 | static enum optr | 
 | loop_primitive_discrim (struct mem_read_abstraction_base *mra, | 
 | 			enum optr hint ATTRIBUTE_UNUSED) | 
 | { | 
 |   uint8_t lb; | 
 |   int status = mra->read (mra, 0, 1, &lb); | 
 |   if (status < 0) | 
 |     return OP_INVALID; | 
 |  | 
 |   enum optr opbase = (lb & 0x80) ? OP_dbNE : OP_tbNE; | 
 |   return opbase + ((lb & 0x70) >> 4); | 
 | } | 
 |  | 
 | static int | 
 | loop_primitive_decode (struct mem_read_abstraction_base *mra, | 
 | 		       int *n_operands, struct operand **operands) | 
 | { | 
 |   struct operand *op; | 
 |   int n, offs = 1; | 
 |   uint8_t lb; | 
 |   int status = mra->read (mra, 0, 1, &lb); | 
 |   if (status < 0) | 
 |     return status; | 
 |  | 
 |   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: | 
 |       op = create_register_operand (lb & 0x07); | 
 |       if (op == NULL) | 
 | 	return -1; | 
 |       operands[(*n_operands)++] = op; | 
 |       break; | 
 |     case LP_XY: | 
 |       op = create_register_operand ((lb & 0x01) + REG_X); | 
 |       if (op == NULL) | 
 | 	return -1; | 
 |       operands[(*n_operands)++] = op; | 
 |       break; | 
 |     case LP_OPR: | 
 |       n = x_opr_n_bytes (mra, 1); | 
 |       if (n < 0) | 
 | 	return n; | 
 |       offs += n; | 
 |       op = x_opr_decode_with_size (mra, 1, lb & 0x03); | 
 |       if (op == NULL) | 
 | 	return -1; | 
 |       operands[(*n_operands)++] = op; | 
 |       break; | 
 |     } | 
 |  | 
 |   return rel_15_7 (mra, offs + 1, n_operands, operands); | 
 | } | 
 |  | 
 |  | 
 | static enum optr | 
 | shift_discrim (struct mem_read_abstraction_base *mra, | 
 | 	       enum optr hint ATTRIBUTE_UNUSED) | 
 | { | 
 |   size_t i; | 
 |   uint8_t sb; | 
 |   int status = mra->read (mra, 0, 1, &sb); | 
 |   if (status < 0) | 
 |     return OP_INVALID; | 
 |  | 
 |   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 int | 
 | shift_decode (struct mem_read_abstraction_base *mra, int *n_operands, | 
 | 	      struct operand **operands) | 
 | { | 
 |   struct operand *op; | 
 |   size_t i; | 
 |   uint8_t byte; | 
 |   int status = mra->read (mra, -1, 1, &byte); | 
 |   if (status < 0) | 
 |     return status; | 
 |  | 
 |   uint8_t sb; | 
 |   status = mra->read (mra, 0, 1, &sb); | 
 |   if (status < 0) | 
 |     return status; | 
 |  | 
 |   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; | 
 | 	status = mra->read (mra, 1, 1, &xb); | 
 | 	if (status < 0) | 
 | 	  return status; | 
 | 	/* 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: | 
 |       op = create_register_operand (byte & 0x07); | 
 |       if (op == NULL) | 
 | 	return -1; | 
 |       operands[(*n_operands)++] = op; | 
 |       break; | 
 |     case SB_REG_OPR_EFF: | 
 |     case SB_REG_OPR_OPR: | 
 |       op = create_register_operand (byte & 0x07); | 
 |       if (op == NULL) | 
 | 	return -1; | 
 |       operands[(*n_operands)++] = op; | 
 |       break; | 
 |  | 
 |     case SB_ROT: | 
 |       op = x_opr_decode_with_size (mra, 1, osize); | 
 |       if (op == NULL) | 
 | 	return -1; | 
 |       operands[(*n_operands)++] = op; | 
 |       break; | 
 |  | 
 |     default: | 
 |       break; | 
 |     } | 
 |  | 
 |   /* Source register */ | 
 |   switch (mode) | 
 |     { | 
 |     case SB_REG_REG_N_EFF: | 
 |     case SB_REG_REG_N: | 
 |       op = create_register_operand_with_size (sb & 0x07, osize); | 
 |       if (op == NULL) | 
 | 	return -1; | 
 |       operands[(*n_operands)++] = op; | 
 |       break; | 
 |  | 
 |     case SB_REG_OPR_OPR: | 
 |       op = x_opr_decode_with_size (mra, 1, osize); | 
 |       if (op == NULL) | 
 | 	return -1; | 
 |       operands[(*n_operands)++] = op; | 
 |       break; | 
 |  | 
 |     default: | 
 |       break; | 
 |     } | 
 |  | 
 |   /* 3rd arg */ | 
 |   switch (mode) | 
 |     { | 
 |     case SB_REG_OPR_EFF: | 
 |     case SB_OPR_N: | 
 |       op = x_opr_decode_with_size (mra, 1, osize); | 
 |       if (op == NULL) | 
 | 	return -1; | 
 |       operands[(*n_operands)++] = op; | 
 |       break; | 
 |  | 
 |     case SB_REG_REG_N: | 
 |       { | 
 | 	uint8_t xb; | 
 | 	status = mra->read (mra, 1, 1, &xb); | 
 | 	if (status < 0) | 
 | 	  return status; | 
 |  | 
 | 	/* 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); | 
 | 		op = create_immediate_operand (shift); | 
 | 		if (op == NULL) | 
 | 		  return -1; | 
 | 		operands[(*n_operands)++] = op; | 
 | 	      } | 
 | 	    else | 
 | 	      { | 
 | 		/* This should not happen.  */ | 
 | 		abort (); | 
 | 	      } | 
 | 	  } | 
 | 	else | 
 | 	  { | 
 | 	    op = x_opr_decode (mra, 1); | 
 | 	    if (op == NULL) | 
 | 	      return -1; | 
 | 	    operands[(*n_operands)++] = op; | 
 | 	  } | 
 |       } | 
 |       break; | 
 |     case SB_REG_OPR_OPR: | 
 |       { | 
 | 	uint8_t xb; | 
 | 	int n = x_opr_n_bytes (mra, 1); | 
 | 	if (n < 0) | 
 | 	  return n; | 
 | 	status = mra->read (mra, 1 + n, 1, &xb); | 
 | 	if (status < 0) | 
 | 	  return status; | 
 |  | 
 | 	if ((xb & 0xF0) == 0x70) | 
 | 	  { | 
 | 	    int imm = xb & 0x0F; | 
 | 	    imm <<= 1; | 
 | 	    imm |= (sb & 0x08) >> 3; | 
 | 	    op = create_immediate_operand (imm); | 
 | 	    if (op == NULL) | 
 | 	      return -1; | 
 | 	    operands[(*n_operands)++] = op; | 
 | 	  } | 
 | 	else | 
 | 	  { | 
 | 	    op = x_opr_decode (mra, 1 + n); | 
 | 	    if (op == NULL) | 
 | 	      return -1; | 
 | 	    operands[(*n_operands)++] = op; | 
 | 	  } | 
 |       } | 
 |       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; | 
 | 	op = create_immediate_operand (imm); | 
 | 	if (op == NULL) | 
 | 	  return -1; | 
 | 	operands[(*n_operands)++] = op; | 
 |       } | 
 |       break; | 
 |  | 
 |     default: | 
 |       break; | 
 |     } | 
 |   return 0; | 
 | } | 
 |  | 
 | static enum optr | 
 | psh_pul_discrim (struct mem_read_abstraction_base *mra, | 
 | 		 enum optr 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 int | 
 | psh_pul_decode (struct mem_read_abstraction_base *mra, | 
 | 		int *n_operands, struct operand **operand) | 
 | { | 
 |   struct operand *op; | 
 |   uint8_t byte; | 
 |   int status = mra->read (mra, 0, 1, &byte); | 
 |   if (status != 0) | 
 |     return status; | 
 |   int bit; | 
 |   if (byte & 0x40) | 
 |     { | 
 |       if ((byte & 0x3F) == 0) | 
 | 	{ | 
 | 	  op = create_register_all16_operand (); | 
 | 	  if (op == NULL) | 
 | 	    return -1; | 
 | 	  operand[(*n_operands)++] = op; | 
 | 	} | 
 |       else | 
 | 	for (bit = 5; bit >= 0; --bit) | 
 | 	  { | 
 | 	    if (byte & (0x1 << bit)) | 
 | 	      { | 
 | 		op = create_register_operand (oprregs2[bit]); | 
 | 		if (op == NULL) | 
 | 		  return -1; | 
 | 		operand[(*n_operands)++] = op; | 
 | 	      } | 
 | 	  } | 
 |     } | 
 |   else | 
 |     { | 
 |       if ((byte & 0x3F) == 0) | 
 | 	{ | 
 | 	  op = create_register_all_operand (); | 
 | 	  if (op == NULL) | 
 | 	    return -1; | 
 | 	  operand[(*n_operands)++] = op; | 
 | 	} | 
 |       else | 
 | 	for (bit = 5; bit >= 0; --bit) | 
 | 	  { | 
 | 	    if (byte & (0x1 << bit)) | 
 | 	      { | 
 | 		op = create_register_operand (oprregs1[bit]); | 
 | 		if (op == NULL) | 
 | 		  return -1; | 
 | 		operand[(*n_operands)++] = op; | 
 | 	      } | 
 | 	  } | 
 |     } | 
 |   return 0; | 
 | } | 
 |  | 
 | static enum optr | 
 | bit_field_discrim (struct mem_read_abstraction_base *mra, | 
 | 		   enum optr 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 int | 
 | bit_field_decode (struct mem_read_abstraction_base *mra, | 
 | 		  int *n_operands, struct operand **operands) | 
 | { | 
 |   struct operand *op; | 
 |   int status; | 
 |  | 
 |   bfd_byte byte2; | 
 |   status = mra->read (mra, -1, 1, &byte2); | 
 |   if (status != 0) | 
 |     return status; | 
 |  | 
 |   bfd_byte bb; | 
 |   status = mra->read (mra, 0, 1, &bb); | 
 |   if (status != 0) | 
 |     return status; | 
 |  | 
 |   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: | 
 |       op = create_register_operand (reg1); | 
 |       if (op == NULL) | 
 | 	return -1; | 
 |       operands[(*n_operands)++] = op; | 
 |       break; | 
 |     case BB_OPR_REG_REG: | 
 |       op = x_opr_decode_with_size (mra, 1, (bb >> 2) & 0x03); | 
 |       if (op == NULL) | 
 | 	return -1; | 
 |       operands[(*n_operands)++] = op; | 
 |       break; | 
 |     case BB_OPR_REG_IMM: | 
 |       op = x_opr_decode_with_size (mra, 2, (bb >> 2) & 0x03); | 
 |       if (op == NULL) | 
 | 	return -1; | 
 |       operands[(*n_operands)++] = op; | 
 |       break; | 
 |     } | 
 |  | 
 |   /* Second operand */ | 
 |   switch (mode) | 
 |     { | 
 |     case BB_REG_REG_REG: | 
 |     case BB_REG_REG_IMM: | 
 |       { | 
 | 	int reg_src = (bb >> 2) & 0x07; | 
 | 	op = create_register_operand (reg_src); | 
 | 	if (op == NULL) | 
 | 	  return -1; | 
 | 	operands[(*n_operands)++] = op; | 
 |       } | 
 |       break; | 
 |     case BB_OPR_REG_REG: | 
 |     case BB_OPR_REG_IMM: | 
 |       { | 
 | 	int reg_src = (byte2 & 0x07); | 
 | 	op = create_register_operand (reg_src); | 
 | 	if (op == NULL) | 
 | 	  return -1; | 
 | 	operands[(*n_operands)++] = op; | 
 |       } | 
 |       break; | 
 |     case BB_REG_OPR_REG: | 
 |       op = x_opr_decode_with_size (mra, 1, (bb >> 2) & 0x03); | 
 |       if (op == NULL) | 
 | 	return -1; | 
 |       operands[(*n_operands)++] = op; | 
 |       break; | 
 |     case BB_REG_OPR_IMM: | 
 |       op = x_opr_decode_with_size (mra, 2, (bb >> 2) & 0x03); | 
 |       if (op == NULL) | 
 | 	return -1; | 
 |       operands[(*n_operands)++] = op; | 
 |       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; | 
 | 	op = create_register_operand (reg_parm); | 
 | 	if (op == NULL) | 
 | 	  return -1; | 
 | 	operands[(*n_operands)++] = op; | 
 |       } | 
 |       break; | 
 |     case BB_REG_REG_IMM: | 
 |     case BB_OPR_REG_IMM: | 
 |     case BB_REG_OPR_IMM: | 
 |       { | 
 | 	bfd_byte i1; | 
 | 	status = mra->read (mra, 1, 1, &i1); | 
 | 	if (status < 0) | 
 | 	  return status; | 
 | 	int offset = i1 & 0x1f; | 
 | 	int width = bb & 0x03; | 
 | 	width <<= 3; | 
 | 	width |= i1 >> 5; | 
 | 	op = create_bitfield_operand (width, offset); | 
 | 	if (op == NULL) | 
 | 	  return -1; | 
 | 	operands[(*n_operands)++] = op; | 
 |       } | 
 |       break; | 
 |     } | 
 |   return 0; | 
 | } | 
 |  | 
 |  | 
 | /* 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 optr | 
 | decode_operation (const struct opcode *opc, | 
 | 		  struct mem_read_abstraction_base *mra, | 
 | 		  int *n_operands, struct operand **operands) | 
 | { | 
 |   enum optr op = opc->operator; | 
 |   if (opc->discriminator) | 
 |     { | 
 |       op = opc->discriminator (mra, opc->operator); | 
 |       if (op == OP_INVALID) | 
 | 	return op; | 
 |     } | 
 |  | 
 |   if (opc->operands) | 
 |     if (opc->operands (mra, n_operands, operands) < 0) | 
 |       return OP_INVALID; | 
 |  | 
 |   if (opc->operands2) | 
 |     if (opc->operands2 (mra, n_operands, operands) < 0) | 
 |       return OP_INVALID; | 
 |  | 
 |   return op; | 
 | } | 
 |  | 
 | int | 
 | decode_s12z (enum optr *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; | 
 |       status = mra->read (mra, 0, 1, &byte2); | 
 |       if (status < 0) | 
 | 	return status; | 
 |       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.  */ | 
 |   if (*myoperator != OP_INVALID && opc->insn_bytes) | 
 |     { | 
 |       int n = opc->insn_bytes (mra); | 
 |       if (n < 0) | 
 | 	return n; | 
 |       n_bytes += n; | 
 |     } | 
 |   else | 
 |     n_bytes += 1; | 
 |  | 
 |   return n_bytes; | 
 | } | 
 |  |