|  | /* Disassemble MN10300 instructions. | 
|  | Copyright (C) 1996-2020 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 "opcode/mn10300.h" | 
|  | #include "disassemble.h" | 
|  | #include "opintl.h" | 
|  |  | 
|  | #define HAVE_AM33_2 (info->mach == AM33_2) | 
|  | #define HAVE_AM33   (info->mach == AM33 || HAVE_AM33_2) | 
|  | #define HAVE_AM30   (info->mach == AM30) | 
|  |  | 
|  | static void | 
|  | disassemble (bfd_vma memaddr, | 
|  | struct disassemble_info *info, | 
|  | unsigned long insn, | 
|  | unsigned int size) | 
|  | { | 
|  | struct mn10300_opcode *op = (struct mn10300_opcode *) mn10300_opcodes; | 
|  | const struct mn10300_operand *operand; | 
|  | bfd_byte buffer[4]; | 
|  | unsigned long extension = 0; | 
|  | int status, match = 0; | 
|  |  | 
|  | /* Find the opcode.  */ | 
|  | while (op->name) | 
|  | { | 
|  | int mysize, extra_shift; | 
|  |  | 
|  | if (op->format == FMT_S0) | 
|  | mysize = 1; | 
|  | else if (op->format == FMT_S1 | 
|  | || op->format == FMT_D0) | 
|  | mysize = 2; | 
|  | else if (op->format == FMT_S2 | 
|  | || op->format == FMT_D1) | 
|  | mysize = 3; | 
|  | else if (op->format == FMT_S4) | 
|  | mysize = 5; | 
|  | else if (op->format == FMT_D2) | 
|  | mysize = 4; | 
|  | else if (op->format == FMT_D3) | 
|  | mysize = 5; | 
|  | else if (op->format == FMT_D4) | 
|  | mysize = 6; | 
|  | else if (op->format == FMT_D6) | 
|  | mysize = 3; | 
|  | else if (op->format == FMT_D7 || op->format == FMT_D10) | 
|  | mysize = 4; | 
|  | else if (op->format == FMT_D8) | 
|  | mysize = 6; | 
|  | else if (op->format == FMT_D9) | 
|  | mysize = 7; | 
|  | else | 
|  | mysize = 7; | 
|  |  | 
|  | if ((op->mask & insn) == op->opcode | 
|  | && size == (unsigned int) mysize | 
|  | && (op->machine == 0 | 
|  | || (op->machine == AM33_2 && HAVE_AM33_2) | 
|  | || (op->machine == AM33 && HAVE_AM33) | 
|  | || (op->machine == AM30 && HAVE_AM30))) | 
|  | { | 
|  | const unsigned char *opindex_ptr; | 
|  | unsigned int nocomma; | 
|  | int paren = 0; | 
|  |  | 
|  | if (op->format == FMT_D1 || op->format == FMT_S1) | 
|  | extra_shift = 8; | 
|  | else if (op->format == FMT_D2 || op->format == FMT_D4 | 
|  | || op->format == FMT_S2 || op->format == FMT_S4 | 
|  | || op->format == FMT_S6 || op->format == FMT_D5) | 
|  | extra_shift = 16; | 
|  | else if (op->format == FMT_D7 | 
|  | || op->format == FMT_D8 | 
|  | || op->format == FMT_D9) | 
|  | extra_shift = 8; | 
|  | else | 
|  | extra_shift = 0; | 
|  |  | 
|  | if (size == 1 || size == 2) | 
|  | extension = 0; | 
|  |  | 
|  | else if (size == 3 | 
|  | && (op->format == FMT_D1 | 
|  | || op->opcode == 0xdf0000 | 
|  | || op->opcode == 0xde0000)) | 
|  | extension = 0; | 
|  |  | 
|  | else if (size == 3 | 
|  | && op->format == FMT_D6) | 
|  | extension = 0; | 
|  |  | 
|  | else if (size == 3) | 
|  | { | 
|  | insn &= 0xff0000; | 
|  | status = (*info->read_memory_func) (memaddr + 1, buffer, 2, info); | 
|  | if (status != 0) | 
|  | { | 
|  | (*info->memory_error_func) (status, memaddr, info); | 
|  | return; | 
|  | } | 
|  |  | 
|  | insn |= bfd_getl16 (buffer); | 
|  | extension = 0; | 
|  | } | 
|  | else if (size == 4 | 
|  | && (op->opcode == 0xfaf80000 | 
|  | || op->opcode == 0xfaf00000 | 
|  | || op->opcode == 0xfaf40000)) | 
|  | extension = 0; | 
|  |  | 
|  | else if (size == 4 | 
|  | && (op->format == FMT_D7 | 
|  | || op->format == FMT_D10)) | 
|  | extension = 0; | 
|  |  | 
|  | else if (size == 4) | 
|  | { | 
|  | insn &= 0xffff0000; | 
|  | status = (*info->read_memory_func) (memaddr + 2, buffer, 2, info); | 
|  | if (status != 0) | 
|  | { | 
|  | (*info->memory_error_func) (status, memaddr, info); | 
|  | return; | 
|  | } | 
|  |  | 
|  | insn |= bfd_getl16 (buffer); | 
|  | extension = 0; | 
|  | } | 
|  | else if (size == 5 && op->opcode == 0xdc000000) | 
|  | { | 
|  | unsigned long temp = 0; | 
|  |  | 
|  | status = (*info->read_memory_func) (memaddr + 1, buffer, 4, info); | 
|  | if (status != 0) | 
|  | { | 
|  | (*info->memory_error_func) (status, memaddr, info); | 
|  | return; | 
|  | } | 
|  | temp |= bfd_getl32 (buffer); | 
|  |  | 
|  | insn &= 0xff000000; | 
|  | insn |= (temp & 0xffffff00) >> 8; | 
|  | extension = temp & 0xff; | 
|  | } | 
|  | else if (size == 5 && op->format == FMT_D3) | 
|  | { | 
|  | status = (*info->read_memory_func) (memaddr + 2, buffer, 2, info); | 
|  | if (status != 0) | 
|  | { | 
|  | (*info->memory_error_func) (status, memaddr, info); | 
|  | return; | 
|  | } | 
|  | insn &= 0xffff0000; | 
|  | insn |= bfd_getl16 (buffer); | 
|  |  | 
|  | status = (*info->read_memory_func) (memaddr + 4, buffer, 1, info); | 
|  | if (status != 0) | 
|  | { | 
|  | (*info->memory_error_func) (status, memaddr, info); | 
|  | return; | 
|  | } | 
|  | extension = *(unsigned char *) buffer; | 
|  | } | 
|  | else if (size == 5) | 
|  | { | 
|  | unsigned long temp = 0; | 
|  |  | 
|  | status = (*info->read_memory_func) (memaddr + 1, buffer, 2, info); | 
|  | if (status != 0) | 
|  | { | 
|  | (*info->memory_error_func) (status, memaddr, info); | 
|  | return; | 
|  | } | 
|  | temp |= bfd_getl16 (buffer); | 
|  |  | 
|  | insn &= 0xff0000ff; | 
|  | insn |= temp << 8; | 
|  |  | 
|  | status = (*info->read_memory_func) (memaddr + 4, buffer, 1, info); | 
|  | if (status != 0) | 
|  | { | 
|  | (*info->memory_error_func) (status, memaddr, info); | 
|  | return; | 
|  | } | 
|  | extension = *(unsigned char *) buffer; | 
|  | } | 
|  | else if (size == 6 && op->format == FMT_D8) | 
|  | { | 
|  | insn &= 0xffffff00; | 
|  | status = (*info->read_memory_func) (memaddr + 5, buffer, 1, info); | 
|  | if (status != 0) | 
|  | { | 
|  | (*info->memory_error_func) (status, memaddr, info); | 
|  | return; | 
|  | } | 
|  | insn |= *(unsigned char *) buffer; | 
|  |  | 
|  | status = (*info->read_memory_func) (memaddr + 3, buffer, 2, info); | 
|  | if (status != 0) | 
|  | { | 
|  | (*info->memory_error_func) (status, memaddr, info); | 
|  | return; | 
|  | } | 
|  | extension = bfd_getl16 (buffer); | 
|  | } | 
|  | else if (size == 6) | 
|  | { | 
|  | unsigned long temp = 0; | 
|  |  | 
|  | status = (*info->read_memory_func) (memaddr + 2, buffer, 4, info); | 
|  | if (status != 0) | 
|  | { | 
|  | (*info->memory_error_func) (status, memaddr, info); | 
|  | return; | 
|  | } | 
|  | temp |= bfd_getl32 (buffer); | 
|  |  | 
|  | insn &= 0xffff0000; | 
|  | insn |= (temp >> 16) & 0xffff; | 
|  | extension = temp & 0xffff; | 
|  | } | 
|  | else if (size == 7 && op->format == FMT_D9) | 
|  | { | 
|  | insn &= 0xffffff00; | 
|  | status = (*info->read_memory_func) (memaddr + 3, buffer, 4, info); | 
|  | if (status != 0) | 
|  | { | 
|  | (*info->memory_error_func) (status, memaddr, info); | 
|  | return; | 
|  | } | 
|  | extension = bfd_getl32 (buffer); | 
|  | insn |= (extension & 0xff000000) >> 24; | 
|  | extension &= 0xffffff; | 
|  | } | 
|  | else if (size == 7 && op->opcode == 0xdd000000) | 
|  | { | 
|  | unsigned long temp = 0; | 
|  |  | 
|  | status = (*info->read_memory_func) (memaddr + 1, buffer, 4, info); | 
|  | if (status != 0) | 
|  | { | 
|  | (*info->memory_error_func) (status, memaddr, info); | 
|  | return; | 
|  | } | 
|  | temp |= bfd_getl32 (buffer); | 
|  |  | 
|  | insn &= 0xff000000; | 
|  | insn |= (temp >> 8) & 0xffffff; | 
|  | extension = (temp & 0xff) << 16; | 
|  |  | 
|  | status = (*info->read_memory_func) (memaddr + 5, buffer, 2, info); | 
|  | if (status != 0) | 
|  | { | 
|  | (*info->memory_error_func) (status, memaddr, info); | 
|  | return; | 
|  | } | 
|  | extension |= bfd_getb16 (buffer); | 
|  | } | 
|  | else if (size == 7) | 
|  | { | 
|  | unsigned long temp = 0; | 
|  |  | 
|  | status = (*info->read_memory_func) (memaddr + 2, buffer, 4, info); | 
|  | if (status != 0) | 
|  | { | 
|  | (*info->memory_error_func) (status, memaddr, info); | 
|  | return; | 
|  | } | 
|  | temp |= bfd_getl32 (buffer); | 
|  |  | 
|  | insn &= 0xffff0000; | 
|  | insn |= (temp >> 16) & 0xffff; | 
|  | extension = (temp & 0xffff) << 8; | 
|  |  | 
|  | status = (*info->read_memory_func) (memaddr + 6, buffer, 1, info); | 
|  | if (status != 0) | 
|  | { | 
|  | (*info->memory_error_func) (status, memaddr, info); | 
|  | return; | 
|  | } | 
|  | extension |= *(unsigned char *) buffer; | 
|  | } | 
|  |  | 
|  | match = 1; | 
|  | (*info->fprintf_func) (info->stream, "%s\t", op->name); | 
|  |  | 
|  | /* Now print the operands.  */ | 
|  | for (opindex_ptr = op->operands, nocomma = 1; | 
|  | *opindex_ptr != 0; | 
|  | opindex_ptr++) | 
|  | { | 
|  | unsigned long value; | 
|  |  | 
|  | operand = &mn10300_operands[*opindex_ptr]; | 
|  |  | 
|  | /* If this operand is a PLUS (autoincrement), then do not emit | 
|  | a comma before emitting the plus.  */ | 
|  | if ((operand->flags & MN10300_OPERAND_PLUS) != 0) | 
|  | nocomma = 1; | 
|  |  | 
|  | if ((operand->flags & MN10300_OPERAND_DREG) != 0 | 
|  | || (operand->flags & MN10300_OPERAND_AREG) != 0 | 
|  | || (operand->flags & MN10300_OPERAND_RREG) != 0 | 
|  | || (operand->flags & MN10300_OPERAND_XRREG) != 0) | 
|  | value = ((insn >> (operand->shift + extra_shift)) | 
|  | & ((1 << operand->bits) - 1)); | 
|  | else if ((operand->flags & MN10300_OPERAND_SPLIT) != 0) | 
|  | { | 
|  | unsigned long temp; | 
|  |  | 
|  | value = insn & ((1 << operand->bits) - 1); | 
|  | value <<= (32 - operand->bits); | 
|  | temp = extension >> operand->shift; | 
|  | temp &= ((1 << (32 - operand->bits)) - 1); | 
|  | value |= temp; | 
|  | value = ((value ^ (((unsigned long) 1) << 31)) | 
|  | - (((unsigned long) 1) << 31)); | 
|  | } | 
|  | else if ((operand->flags & MN10300_OPERAND_24BIT) != 0) | 
|  | { | 
|  | unsigned long temp; | 
|  |  | 
|  | value = insn & ((1 << operand->bits) - 1); | 
|  | value <<= (24 - operand->bits); | 
|  | temp = extension >> operand->shift; | 
|  | temp &= ((1 << (24 - operand->bits)) - 1); | 
|  | value |= temp; | 
|  | if ((operand->flags & MN10300_OPERAND_SIGNED) != 0) | 
|  | value = ((value & 0xffffff) ^ 0x800000) - 0x800000; | 
|  | } | 
|  | else if ((operand->flags & (MN10300_OPERAND_FSREG | 
|  | | MN10300_OPERAND_FDREG))) | 
|  | { | 
|  | /* See m10300-opc.c just before #define FSM0 for an | 
|  | explanation of these variables.  Note that | 
|  | FMT-implied shifts are not taken into account for | 
|  | FP registers.  */ | 
|  | unsigned long mask_low, mask_high; | 
|  | int shl_low, shr_high, shl_high; | 
|  |  | 
|  | switch (operand->bits) | 
|  | { | 
|  | case 5: | 
|  | /* Handle regular FP registers.  */ | 
|  | if (operand->shift >= 0) | 
|  | { | 
|  | /* This is an `m' register.  */ | 
|  | shl_low = operand->shift; | 
|  | shl_high = 8 + (8 & shl_low) + (shl_low & 4) / 4; | 
|  | } | 
|  | else | 
|  | { | 
|  | /* This is an `n' register.  */ | 
|  | shl_low = -operand->shift; | 
|  | shl_high = shl_low / 4; | 
|  | } | 
|  | mask_low = 0x0f; | 
|  | mask_high = 0x10; | 
|  | shr_high = 4; | 
|  | break; | 
|  |  | 
|  | case 3: | 
|  | /* Handle accumulators.  */ | 
|  | shl_low = -operand->shift; | 
|  | shl_high = 0; | 
|  | mask_low = 0x03; | 
|  | mask_high = 0x04; | 
|  | shr_high = 2; | 
|  | break; | 
|  |  | 
|  | default: | 
|  | abort (); | 
|  | } | 
|  | value = ((((insn >> shl_high) << shr_high) & mask_high) | 
|  | | ((insn >> shl_low) & mask_low)); | 
|  | } | 
|  | else if ((operand->flags & MN10300_OPERAND_EXTENDED) != 0) | 
|  | value = ((extension >> (operand->shift)) | 
|  | & ((1 << operand->bits) - 1)); | 
|  |  | 
|  | else | 
|  | value = ((insn >> (operand->shift)) | 
|  | & ((1 << operand->bits) - 1)); | 
|  |  | 
|  | if ((operand->flags & MN10300_OPERAND_SIGNED) != 0 | 
|  | /* These are properly extended by the code above.  */ | 
|  | && ((operand->flags & MN10300_OPERAND_24BIT) == 0)) | 
|  | value = ((value ^ (((unsigned long) 1) << (operand->bits - 1))) | 
|  | - (((unsigned long) 1) << (operand->bits - 1))); | 
|  |  | 
|  | if (!nocomma | 
|  | && (!paren | 
|  | || ((operand->flags & MN10300_OPERAND_PAREN) == 0))) | 
|  | (*info->fprintf_func) (info->stream, ","); | 
|  |  | 
|  | nocomma = 0; | 
|  |  | 
|  | if ((operand->flags & MN10300_OPERAND_DREG) != 0) | 
|  | (*info->fprintf_func) (info->stream, "d%d", (int) value); | 
|  |  | 
|  | else if ((operand->flags & MN10300_OPERAND_AREG) != 0) | 
|  | (*info->fprintf_func) (info->stream, "a%d", (int) value); | 
|  |  | 
|  | else if ((operand->flags & MN10300_OPERAND_SP) != 0) | 
|  | (*info->fprintf_func) (info->stream, "sp"); | 
|  |  | 
|  | else if ((operand->flags & MN10300_OPERAND_PSW) != 0) | 
|  | (*info->fprintf_func) (info->stream, "psw"); | 
|  |  | 
|  | else if ((operand->flags & MN10300_OPERAND_MDR) != 0) | 
|  | (*info->fprintf_func) (info->stream, "mdr"); | 
|  |  | 
|  | else if ((operand->flags & MN10300_OPERAND_RREG) != 0) | 
|  | { | 
|  | if (value < 8) | 
|  | (*info->fprintf_func) (info->stream, "r%d", (int) value); | 
|  | else if (value < 12) | 
|  | (*info->fprintf_func) (info->stream, "a%d", (int) value - 8); | 
|  | else | 
|  | (*info->fprintf_func) (info->stream, "d%d", (int) value - 12); | 
|  | } | 
|  |  | 
|  | else if ((operand->flags & MN10300_OPERAND_XRREG) != 0) | 
|  | { | 
|  | if (value == 0) | 
|  | (*info->fprintf_func) (info->stream, "sp"); | 
|  | else | 
|  | (*info->fprintf_func) (info->stream, "xr%d", (int) value); | 
|  | } | 
|  |  | 
|  | else if ((operand->flags & MN10300_OPERAND_FSREG) != 0) | 
|  | (*info->fprintf_func) (info->stream, "fs%d", (int) value); | 
|  |  | 
|  | else if ((operand->flags & MN10300_OPERAND_FDREG) != 0) | 
|  | (*info->fprintf_func) (info->stream, "fd%d", (int) value); | 
|  |  | 
|  | else if ((operand->flags & MN10300_OPERAND_FPCR) != 0) | 
|  | (*info->fprintf_func) (info->stream, "fpcr"); | 
|  |  | 
|  | else if ((operand->flags & MN10300_OPERAND_USP) != 0) | 
|  | (*info->fprintf_func) (info->stream, "usp"); | 
|  |  | 
|  | else if ((operand->flags & MN10300_OPERAND_SSP) != 0) | 
|  | (*info->fprintf_func) (info->stream, "ssp"); | 
|  |  | 
|  | else if ((operand->flags & MN10300_OPERAND_MSP) != 0) | 
|  | (*info->fprintf_func) (info->stream, "msp"); | 
|  |  | 
|  | else if ((operand->flags & MN10300_OPERAND_PC) != 0) | 
|  | (*info->fprintf_func) (info->stream, "pc"); | 
|  |  | 
|  | else if ((operand->flags & MN10300_OPERAND_EPSW) != 0) | 
|  | (*info->fprintf_func) (info->stream, "epsw"); | 
|  |  | 
|  | else if ((operand->flags & MN10300_OPERAND_PLUS) != 0) | 
|  | (*info->fprintf_func) (info->stream, "+"); | 
|  |  | 
|  | else if ((operand->flags & MN10300_OPERAND_PAREN) != 0) | 
|  | { | 
|  | if (paren) | 
|  | (*info->fprintf_func) (info->stream, ")"); | 
|  | else | 
|  | { | 
|  | (*info->fprintf_func) (info->stream, "("); | 
|  | nocomma = 1; | 
|  | } | 
|  | paren = !paren; | 
|  | } | 
|  |  | 
|  | else if ((operand->flags & MN10300_OPERAND_PCREL) != 0) | 
|  | (*info->print_address_func) ((long) value + memaddr, info); | 
|  |  | 
|  | else if ((operand->flags & MN10300_OPERAND_MEMADDR) != 0) | 
|  | (*info->print_address_func) (value, info); | 
|  |  | 
|  | else if ((operand->flags & MN10300_OPERAND_REG_LIST) != 0) | 
|  | { | 
|  | int comma = 0; | 
|  |  | 
|  | (*info->fprintf_func) (info->stream, "["); | 
|  | if (value & 0x80) | 
|  | { | 
|  | (*info->fprintf_func) (info->stream, "d2"); | 
|  | comma = 1; | 
|  | } | 
|  |  | 
|  | if (value & 0x40) | 
|  | { | 
|  | if (comma) | 
|  | (*info->fprintf_func) (info->stream, ","); | 
|  | (*info->fprintf_func) (info->stream, "d3"); | 
|  | comma = 1; | 
|  | } | 
|  |  | 
|  | if (value & 0x20) | 
|  | { | 
|  | if (comma) | 
|  | (*info->fprintf_func) (info->stream, ","); | 
|  | (*info->fprintf_func) (info->stream, "a2"); | 
|  | comma = 1; | 
|  | } | 
|  |  | 
|  | if (value & 0x10) | 
|  | { | 
|  | if (comma) | 
|  | (*info->fprintf_func) (info->stream, ","); | 
|  | (*info->fprintf_func) (info->stream, "a3"); | 
|  | comma = 1; | 
|  | } | 
|  |  | 
|  | if (value & 0x08) | 
|  | { | 
|  | if (comma) | 
|  | (*info->fprintf_func) (info->stream, ","); | 
|  | (*info->fprintf_func) (info->stream, "other"); | 
|  | comma = 1; | 
|  | } | 
|  |  | 
|  | if (value & 0x04) | 
|  | { | 
|  | if (comma) | 
|  | (*info->fprintf_func) (info->stream, ","); | 
|  | (*info->fprintf_func) (info->stream, "exreg0"); | 
|  | comma = 1; | 
|  | } | 
|  | if (value & 0x02) | 
|  | { | 
|  | if (comma) | 
|  | (*info->fprintf_func) (info->stream, ","); | 
|  | (*info->fprintf_func) (info->stream, "exreg1"); | 
|  | comma = 1; | 
|  | } | 
|  | if (value & 0x01) | 
|  | { | 
|  | if (comma) | 
|  | (*info->fprintf_func) (info->stream, ","); | 
|  | (*info->fprintf_func) (info->stream, "exother"); | 
|  | comma = 1; | 
|  | } | 
|  | (*info->fprintf_func) (info->stream, "]"); | 
|  | } | 
|  |  | 
|  | else | 
|  | (*info->fprintf_func) (info->stream, "%ld", (long) value); | 
|  | } | 
|  | /* All done. */ | 
|  | break; | 
|  | } | 
|  | op++; | 
|  | } | 
|  |  | 
|  | if (!match) | 
|  | /* xgettext:c-format */ | 
|  | (*info->fprintf_func) (info->stream, _("unknown\t0x%04lx"), insn); | 
|  | } | 
|  |  | 
|  | int | 
|  | print_insn_mn10300 (bfd_vma memaddr, struct disassemble_info *info) | 
|  | { | 
|  | int status; | 
|  | bfd_byte buffer[4]; | 
|  | unsigned long insn; | 
|  | unsigned int consume; | 
|  |  | 
|  | /* First figure out how big the opcode is.  */ | 
|  | status = (*info->read_memory_func) (memaddr, buffer, 1, info); | 
|  | if (status != 0) | 
|  | { | 
|  | (*info->memory_error_func) (status, memaddr, info); | 
|  | return -1; | 
|  | } | 
|  | insn = *(unsigned char *) buffer; | 
|  |  | 
|  | /* These are one byte insns.  */ | 
|  | if ((insn & 0xf3) == 0x00 | 
|  | || (insn & 0xf0) == 0x10 | 
|  | || (insn & 0xfc) == 0x3c | 
|  | || (insn & 0xf3) == 0x41 | 
|  | || (insn & 0xf3) == 0x40 | 
|  | || (insn & 0xfc) == 0x50 | 
|  | || (insn & 0xfc) == 0x54 | 
|  | || (insn & 0xf0) == 0x60 | 
|  | || (insn & 0xf0) == 0x70 | 
|  | || ((insn & 0xf0) == 0x80 | 
|  | && (insn & 0x0c) >> 2 != (insn & 0x03)) | 
|  | || ((insn & 0xf0) == 0x90 | 
|  | && (insn & 0x0c) >> 2 != (insn & 0x03)) | 
|  | || ((insn & 0xf0) == 0xa0 | 
|  | && (insn & 0x0c) >> 2 != (insn & 0x03)) | 
|  | || ((insn & 0xf0) == 0xb0 | 
|  | && (insn & 0x0c) >> 2 != (insn & 0x03)) | 
|  | || (insn & 0xff) == 0xcb | 
|  | || (insn & 0xfc) == 0xd0 | 
|  | || (insn & 0xfc) == 0xd4 | 
|  | || (insn & 0xfc) == 0xd8 | 
|  | || (insn & 0xf0) == 0xe0 | 
|  | || (insn & 0xff) == 0xff) | 
|  | { | 
|  | consume = 1; | 
|  | } | 
|  |  | 
|  | /* These are two byte insns.  */ | 
|  | else if ((insn & 0xf0) == 0x80 | 
|  | || (insn & 0xf0) == 0x90 | 
|  | || (insn & 0xf0) == 0xa0 | 
|  | || (insn & 0xf0) == 0xb0 | 
|  | || (insn & 0xfc) == 0x20 | 
|  | || (insn & 0xfc) == 0x28 | 
|  | || (insn & 0xf3) == 0x43 | 
|  | || (insn & 0xf3) == 0x42 | 
|  | || (insn & 0xfc) == 0x58 | 
|  | || (insn & 0xfc) == 0x5c | 
|  | || ((insn & 0xf0) == 0xc0 | 
|  | && (insn & 0xff) != 0xcb | 
|  | && (insn & 0xff) != 0xcc | 
|  | && (insn & 0xff) != 0xcd) | 
|  | || (insn & 0xff) == 0xf0 | 
|  | || (insn & 0xff) == 0xf1 | 
|  | || (insn & 0xff) == 0xf2 | 
|  | || (insn & 0xff) == 0xf3 | 
|  | || (insn & 0xff) == 0xf4 | 
|  | || (insn & 0xff) == 0xf5 | 
|  | || (insn & 0xff) == 0xf6) | 
|  | { | 
|  | status = (*info->read_memory_func) (memaddr, buffer, 2, info); | 
|  | if (status != 0) | 
|  | { | 
|  | (*info->memory_error_func) (status, memaddr, info); | 
|  | return -1; | 
|  | } | 
|  | insn = bfd_getb16 (buffer); | 
|  | consume = 2; | 
|  | } | 
|  |  | 
|  | /* These are three byte insns.  */ | 
|  | else if ((insn & 0xff) == 0xf8 | 
|  | || (insn & 0xff) == 0xcc | 
|  | || (insn & 0xff) == 0xf9 | 
|  | || (insn & 0xf3) == 0x01 | 
|  | || (insn & 0xf3) == 0x02 | 
|  | || (insn & 0xf3) == 0x03 | 
|  | || (insn & 0xfc) == 0x24 | 
|  | || (insn & 0xfc) == 0x2c | 
|  | || (insn & 0xfc) == 0x30 | 
|  | || (insn & 0xfc) == 0x34 | 
|  | || (insn & 0xfc) == 0x38 | 
|  | || (insn & 0xff) == 0xde | 
|  | || (insn & 0xff) == 0xdf | 
|  | || (insn & 0xff) == 0xf9 | 
|  | || (insn & 0xff) == 0xcc) | 
|  | { | 
|  | status = (*info->read_memory_func) (memaddr, buffer, 2, info); | 
|  | if (status != 0) | 
|  | { | 
|  | (*info->memory_error_func) (status, memaddr, info); | 
|  | return -1; | 
|  | } | 
|  | insn = bfd_getb16 (buffer); | 
|  | insn <<= 8; | 
|  | status = (*info->read_memory_func) (memaddr + 2, buffer, 1, info); | 
|  | if (status != 0) | 
|  | { | 
|  | (*info->memory_error_func) (status, memaddr, info); | 
|  | return -1; | 
|  | } | 
|  | insn |= *(unsigned char *) buffer; | 
|  | consume = 3; | 
|  | } | 
|  |  | 
|  | /* These are four byte insns.  */ | 
|  | else if ((insn & 0xff) == 0xfa | 
|  | || (insn & 0xff) == 0xf7 | 
|  | || (insn & 0xff) == 0xfb) | 
|  | { | 
|  | status = (*info->read_memory_func) (memaddr, buffer, 4, info); | 
|  | if (status != 0) | 
|  | { | 
|  | (*info->memory_error_func) (status, memaddr, info); | 
|  | return -1; | 
|  | } | 
|  | insn = bfd_getb32 (buffer); | 
|  | consume = 4; | 
|  | } | 
|  |  | 
|  | /* These are five byte insns.  */ | 
|  | else if ((insn & 0xff) == 0xcd | 
|  | || (insn & 0xff) == 0xdc) | 
|  | { | 
|  | status = (*info->read_memory_func) (memaddr, buffer, 4, info); | 
|  | if (status != 0) | 
|  | { | 
|  | (*info->memory_error_func) (status, memaddr, info); | 
|  | return -1; | 
|  | } | 
|  | insn = bfd_getb32 (buffer); | 
|  | consume = 5; | 
|  | } | 
|  |  | 
|  | /* These are six byte insns.  */ | 
|  | else if ((insn & 0xff) == 0xfd | 
|  | || (insn & 0xff) == 0xfc) | 
|  | { | 
|  | status = (*info->read_memory_func) (memaddr, buffer, 4, info); | 
|  | if (status != 0) | 
|  | { | 
|  | (*info->memory_error_func) (status, memaddr, info); | 
|  | return -1; | 
|  | } | 
|  |  | 
|  | insn = bfd_getb32 (buffer); | 
|  | consume = 6; | 
|  | } | 
|  |  | 
|  | /* Else its a seven byte insns (in theory).  */ | 
|  | else | 
|  | { | 
|  | status = (*info->read_memory_func) (memaddr, buffer, 4, info); | 
|  | if (status != 0) | 
|  | { | 
|  | (*info->memory_error_func) (status, memaddr, info); | 
|  | return -1; | 
|  | } | 
|  |  | 
|  | insn = bfd_getb32 (buffer); | 
|  | consume = 7; | 
|  | /* Handle the 5-byte extended instruction codes.  */ | 
|  | if ((insn & 0xfff80000) == 0xfe800000) | 
|  | consume = 5; | 
|  | } | 
|  |  | 
|  | disassemble (memaddr, info, insn, consume); | 
|  |  | 
|  | return consume; | 
|  | } |