| /* Disassemble MN10300 instructions. |
| Copyright (C) 1996-2016 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 "dis-asm.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_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) |
| { |
| value = ((insn >> (operand->shift + extra_shift)) |
| & ((1 << operand->bits) - 1)); |
| (*info->fprintf_func) (info->stream, "d%d", (int) value); |
| } |
| |
| else if ((operand->flags & MN10300_OPERAND_AREG) != 0) |
| { |
| value = ((insn >> (operand->shift + extra_shift)) |
| & ((1 << operand->bits) - 1)); |
| (*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) |
| { |
| value = ((insn >> (operand->shift + extra_shift)) |
| & ((1 << operand->bits) - 1)); |
| 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) |
| { |
| value = ((insn >> (operand->shift + extra_shift)) |
| & ((1 << operand->bits) - 1)); |
| 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; |
| } |