summaryrefslogtreecommitdiff
path: root/opcodes/visium-dis.c
diff options
context:
space:
mode:
authorEric Botcazou <ebotcazou@gcc.gnu.org>2014-12-06 16:25:55 +0100
committerEric Botcazou <ebotcazou@gcc.gnu.org>2014-12-06 16:25:55 +0100
commit1945cfa59de0a6093011891e1974ac2b6d25658f (patch)
treee5ce6439d91746f66df8e2b49241690fa244d58c /opcodes/visium-dis.c
parentbb5f7690917fd192b98c2fcace1884252c5f6f02 (diff)
downloadbinutils-gdb-1945cfa59de0a6093011891e1974ac2b6d25658f.tar.gz
Add Visium support to opcodes
include/ * dis-asm.h (print_insn_visium): Declare. include/opcode/ * visium.h: New file. opcodes/ * configure.ac: Add Visium support. * configure: Regenerate. * Makefile.am (TARGET_LIBOPCODES_CFILES): Add visium-dis.c and visium-opc.c. * Makefile.in: Regenerate. * disassemble.c (ARCH_visium): Define if ARCH_all. (disassembler): Deal with bfd_arch_visium if ARCH_visium. * visium-dis.c: New file. * visium-opc.c: Likewise. * po/POTFILES.in: Regenerate.
Diffstat (limited to 'opcodes/visium-dis.c')
-rw-r--r--opcodes/visium-dis.c834
1 files changed, 834 insertions, 0 deletions
diff --git a/opcodes/visium-dis.c b/opcodes/visium-dis.c
new file mode 100644
index 00000000000..96be9721b1d
--- /dev/null
+++ b/opcodes/visium-dis.c
@@ -0,0 +1,834 @@
+/* Single instruction disassembler for the Visium.
+
+ Copyright (C) 2002-2014 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 "dis-asm.h"
+#include "opcode/visium.h"
+
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <setjmp.h>
+
+/* Maximum length of an instruction. */
+#define MAXLEN 4
+
+struct private
+{
+ /* Points to first byte not fetched. */
+ bfd_byte *max_fetched;
+ bfd_byte the_buffer[MAXLEN];
+ bfd_vma insn_start;
+ jmp_buf bailout;
+};
+
+/* Make sure that bytes from INFO->PRIVATE_DATA->BUFFER (inclusive)
+ to ADDR (exclusive) are valid. Returns 1 for success, longjmps
+ on error. */
+#define FETCH_DATA(info, addr) \
+ ((addr) <= ((struct private *)(info->private_data))->max_fetched \
+ ? 1 : fetch_data ((info), (addr)))
+
+static int fetch_data (struct disassemble_info *info, bfd_byte * addr);
+
+static int
+fetch_data (struct disassemble_info *info, bfd_byte *addr)
+{
+ int status;
+ struct private *priv = (struct private *) info->private_data;
+ bfd_vma start = priv->insn_start + (priv->max_fetched - priv->the_buffer);
+
+ status = (*info->read_memory_func) (start,
+ priv->max_fetched,
+ addr - priv->max_fetched, info);
+ if (status != 0)
+ {
+ (*info->memory_error_func) (status, start, info);
+ longjmp (priv->bailout, 1);
+ }
+ else
+ priv->max_fetched = addr;
+ return 1;
+}
+
+static char *size_names[] = { "?", "b", "w", "?", "l", "?", "?", "?" };
+
+static char *cc_names[] =
+{
+ "fa", "eq", "cs", "os", "ns", "ne", "cc", "oc",
+ "nc", "ge", "gt", "hi", "le", "ls", "lt", "tr"
+};
+
+/* Disassemble non-storage relative instructions. */
+
+static int
+disassem_class0 (disassemble_info *info, unsigned int ins)
+{
+ int opcode = (ins >> 21) & 0x000f;
+
+ if (ins & CLASS0_UNUSED_MASK)
+ goto illegal_opcode;
+
+ switch (opcode)
+ {
+ case 0:
+ /* BRR instruction. */
+ {
+ unsigned cbf = (ins >> 27) & 0x000f;
+ int displacement = ((int) (ins << 16)) >> 16;
+
+ if (ins == 0)
+ (*info->fprintf_func) (info->stream, "nop");
+ else
+ (*info->fprintf_func) (info->stream, "brr %s,%+d",
+ cc_names[cbf], displacement);
+ }
+ break;
+ case 1:
+ /* Illegal opcode. */
+ goto illegal_opcode;
+ break;
+ case 2:
+ /* Illegal opcode. */
+ goto illegal_opcode;
+ break;
+ case 3:
+ /* Illegal opcode. */
+ goto illegal_opcode;
+ break;
+ case 4:
+ /* Illegal opcode. */
+ goto illegal_opcode;
+ break;
+ case 5:
+ /* Illegal opcode. */
+ goto illegal_opcode;
+ break;
+ case 6:
+ /* Illegal opcode. */
+ goto illegal_opcode;
+ break;
+ case 7:
+ /* Illegal opcode. */
+ goto illegal_opcode;
+ break;
+ case 8:
+ /* Illegal opcode. */
+ goto illegal_opcode;
+ break;
+ case 9:
+ /* Illegal opcode. */
+ goto illegal_opcode;
+ break;
+ case 10:
+ /* Illegal opcode. */
+ goto illegal_opcode;
+ break;
+ case 11:
+ /* Illegal opcode. */
+ goto illegal_opcode;
+ break;
+ case 12:
+ /* Illegal opcode. */
+ goto illegal_opcode;
+ break;
+ case 13:
+ /* Illegal opcode. */
+ goto illegal_opcode;
+ break;
+ case 14:
+ /* Illegal opcode. */
+ goto illegal_opcode;
+ break;
+ case 15:
+ /* Illegal opcode. */
+ goto illegal_opcode;
+ break;
+ }
+ return 0;
+
+illegal_opcode:
+ return -1;
+}
+
+/* Disassemble non-storage register class instructions. */
+
+static int
+disassem_class1 (disassemble_info *info, unsigned int ins)
+{
+ int opcode = (ins >> 21) & 0xf;
+ int source_a = (ins >> 16) & 0x1f;
+ int source_b = (ins >> 4) & 0x1f;
+ int indx = (ins >> 10) & 0x1f;
+
+ int size = ins & 0x7;
+
+ if (ins & CLASS1_UNUSED_MASK)
+ goto illegal_opcode;
+
+ switch (opcode)
+ {
+ case 0:
+ /* Stop. */
+ (*info->fprintf_func) (info->stream, "stop");
+ break;
+ case 1:
+ /* BMI - Block Move Indirect. */
+ if (ins != BMI)
+ goto illegal_opcode;
+
+ (*info->fprintf_func) (info->stream, "bmi r1,r2,r3");
+ break;
+ case 2:
+ /* Illegal opcode. */
+ goto illegal_opcode;
+ break;
+ case 3:
+ /* BMD - Block Move Direct. */
+ if (ins != BMD)
+ goto illegal_opcode;
+
+ (*info->fprintf_func) (info->stream, "bmd r1,r2,r3");
+ break;
+ case 4:
+ /* DSI - Disable Interrupts. */
+ if (ins != DSI)
+ goto illegal_opcode;
+
+ (*info->fprintf_func) (info->stream, "dsi");
+ break;
+
+ case 5:
+ /* ENI - Enable Interrupts. */
+ if (ins != ENI)
+ goto illegal_opcode;
+
+ (*info->fprintf_func) (info->stream, "eni");
+ break;
+
+ case 6:
+ /* Illegal opcode (was EUT). */
+ goto illegal_opcode;
+ break;
+ case 7:
+ /* RFI - Return from Interrupt. */
+ if (ins != RFI)
+ goto illegal_opcode;
+
+ (*info->fprintf_func) (info->stream, "rfi");
+ break;
+ case 8:
+ /* Illegal opcode. */
+ goto illegal_opcode;
+ break;
+ case 9:
+ /* Illegal opcode. */
+ goto illegal_opcode;
+ break;
+ case 10:
+ /* Illegal opcode. */
+ goto illegal_opcode;
+ break;
+ case 11:
+ /* Illegal opcode. */
+ goto illegal_opcode;
+ break;
+ case 12:
+ /* Illegal opcode. */
+ goto illegal_opcode;
+ break;
+ case 13:
+ goto illegal_opcode;
+ break;
+ case 14:
+ goto illegal_opcode;
+ break;
+ case 15:
+ if (ins & EAM_SELECT_MASK)
+ {
+ /* Extension arithmetic module write */
+ int fp_ins = (ins >> 27) & 0xf;
+
+ if (size != 4)
+ goto illegal_opcode;
+
+ if (ins & FP_SELECT_MASK)
+ {
+ /* Which floating point instructions don't need a fsrcB
+ register. */
+ const int no_fsrcb[16] = { 1, 0, 0, 0, 0, 1, 1, 1,
+ 1, 1, 0, 0, 1, 0, 0, 0
+ };
+ if (no_fsrcb[fp_ins] && source_b)
+ goto illegal_opcode;
+
+ /* Check that none of the floating register register numbers
+ is higher than 15. (If this is fload, then srcA is a
+ general register. */
+ if (ins & ((1 << 14) | (1 << 8)) || (fp_ins && ins & (1 << 20)))
+ goto illegal_opcode;
+
+ switch (fp_ins)
+ {
+ case 0:
+ (*info->fprintf_func) (info->stream, "fload f%d,r%d",
+ indx, source_a);
+ break;
+ case 1:
+ (*info->fprintf_func) (info->stream, "fadd f%d,f%d,f%d",
+ indx, source_a, source_b);
+ break;
+ case 2:
+ (*info->fprintf_func) (info->stream, "fsub f%d,f%d,f%d",
+ indx, source_a, source_b);
+ break;
+ case 3:
+ (*info->fprintf_func) (info->stream, "fmult f%d,f%d,f%d",
+ indx, source_a, source_b);
+ break;
+ case 4:
+ (*info->fprintf_func) (info->stream, "fdiv f%d,f%d,f%d",
+ indx, source_a, source_b);
+ break;
+ case 5:
+ (*info->fprintf_func) (info->stream, "fsqrt f%d,f%d",
+ indx, source_a);
+ break;
+ case 6:
+ (*info->fprintf_func) (info->stream, "fneg f%d,f%d",
+ indx, source_a);
+ break;
+ case 7:
+ (*info->fprintf_func) (info->stream, "fabs f%d,f%d",
+ indx, source_a);
+ break;
+ case 8:
+ (*info->fprintf_func) (info->stream, "ftoi f%d,f%d",
+ indx, source_a);
+ break;
+ case 9:
+ (*info->fprintf_func) (info->stream, "itof f%d,f%d",
+ indx, source_a);
+ break;
+ case 12:
+ (*info->fprintf_func) (info->stream, "fmove f%d,f%d",
+ indx, source_a);
+ break;
+ default:
+ (*info->fprintf_func) (info->stream,
+ "fpinst %d,f%d,f%d,f%d", fp_ins,
+ indx, source_a, source_b);
+ break;
+ }
+ }
+ else
+ {
+ /* Which EAM operations do not need a srcB register. */
+ const int no_srcb[32] =
+ { 0, 0, 1, 1, 0, 1, 1, 1,
+ 0, 1, 1, 1, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0
+ };
+
+ if (no_srcb[indx] && source_b)
+ goto illegal_opcode;
+
+ if (fp_ins)
+ goto illegal_opcode;
+
+ switch (indx)
+ {
+ case 0:
+ (*info->fprintf_func) (info->stream, "mults r%d,r%d",
+ source_a, source_b);
+ break;
+ case 1:
+ (*info->fprintf_func) (info->stream, "multu r%d,r%d",
+ source_a, source_b);
+ break;
+ case 2:
+ (*info->fprintf_func) (info->stream, "divs r%d",
+ source_a);
+ break;
+ case 3:
+ (*info->fprintf_func) (info->stream, "divu r%d",
+ source_a);
+ break;
+ case 4:
+ (*info->fprintf_func) (info->stream, "writemd r%d,r%d",
+ source_a, source_b);
+ break;
+ case 5:
+ (*info->fprintf_func) (info->stream, "writemdc r%d",
+ source_a);
+ break;
+ case 6:
+ (*info->fprintf_func) (info->stream, "divds r%d",
+ source_a);
+ break;
+ case 7:
+ (*info->fprintf_func) (info->stream, "divdu r%d",
+ source_a);
+ break;
+ case 9:
+ (*info->fprintf_func) (info->stream, "asrd r%d",
+ source_a);
+ break;
+ case 10:
+ (*info->fprintf_func) (info->stream, "lsrd r%d",
+ source_a);
+ break;
+ case 11:
+ (*info->fprintf_func) (info->stream, "asld r%d",
+ source_a);
+ break;
+ default:
+ (*info->fprintf_func) (info->stream,
+ "eamwrite %d,r%d,r%d", indx,
+ source_a, source_b);
+ break;
+ }
+ }
+ }
+ else
+ {
+ /* WRITE - write to memory. */
+ (*info->fprintf_func) (info->stream, "write.%s %d(r%d),r%d",
+ size_names[size], indx, source_a, source_b);
+ }
+ break;
+ }
+
+ return 0;
+
+illegal_opcode:
+ return -1;
+}
+
+/* Disassemble storage immediate class instructions. */
+
+static int
+disassem_class2 (disassemble_info *info, unsigned int ins)
+{
+ int opcode = (ins >> 21) & 0xf;
+ int source_a = (ins >> 16) & 0x1f;
+ unsigned immediate = ins & 0x0000ffff;
+
+ if (ins & CC_MASK)
+ goto illegal_opcode;
+
+ switch (opcode)
+ {
+ case 0:
+ /* ADDI instruction. */
+ (*info->fprintf_func) (info->stream, "addi r%d,%d", source_a,
+ immediate);
+ break;
+ case 1:
+ /* Illegal opcode. */
+ goto illegal_opcode;
+ break;
+ case 2:
+ /* SUBI instruction. */
+ (*info->fprintf_func) (info->stream, "subi r%d,%d", source_a,
+ immediate);
+ break;
+ case 3:
+ /* Illegal opcode. */
+ goto illegal_opcode;
+ break;
+ case 4:
+ /* MOVIL instruction. */
+ (*info->fprintf_func) (info->stream, "movil r%d,0x%04X", source_a,
+ immediate);
+ break;
+ case 5:
+ /* MOVIU instruction. */
+ (*info->fprintf_func) (info->stream, "moviu r%d,0x%04X", source_a,
+ immediate);
+ break;
+ case 6:
+ /* MOVIQ instruction. */
+ (*info->fprintf_func) (info->stream, "moviq r%d,%u", source_a,
+ immediate);
+ break;
+ case 7:
+ /* Illegal opcode. */
+ goto illegal_opcode;
+ break;
+ case 8:
+ /* WRTL instruction. */
+ if (source_a != 0)
+ goto illegal_opcode;
+
+ (*info->fprintf_func) (info->stream, "wrtl 0x%04X", immediate);
+ break;
+ case 9:
+ /* WRTU instruction. */
+ if (source_a != 0)
+ goto illegal_opcode;
+
+ (*info->fprintf_func) (info->stream, "wrtu 0x%04X", immediate);
+ break;
+ case 10:
+ /* Illegal opcode. */
+ goto illegal_opcode;
+ break;
+ case 11:
+ /* Illegal opcode. */
+ goto illegal_opcode;
+ break;
+ case 12:
+ /* Illegal opcode. */
+ goto illegal_opcode;
+ break;
+ case 13:
+ /* Illegal opcode. */
+ goto illegal_opcode;
+ break;
+ case 14:
+ /* Illegal opcode. */
+ goto illegal_opcode;
+ break;
+ case 15:
+ /* Illegal opcode. */
+ goto illegal_opcode;
+ break;
+ }
+
+ return 0;
+
+illegal_opcode:
+ return -1;
+}
+
+/* Disassemble storage register class instructions. */
+
+static int
+disassem_class3 (disassemble_info *info, unsigned int ins)
+{
+ int opcode = (ins >> 21) & 0xf;
+ int source_b = (ins >> 4) & 0x1f;
+ int source_a = (ins >> 16) & 0x1f;
+ int size = ins & 0x7;
+ int dest = (ins >> 10) & 0x1f;
+
+ /* Those instructions that don't have a srcB register. */
+ const int no_srcb[16] =
+ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0 };
+
+ /* These are instructions which can take an immediate srcB value. */
+ const int srcb_immed[16] =
+ { 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1 };
+
+ /* User opcodes should not provide a non-zero srcB register
+ when none is required. Only a BRA or floating point
+ instruction should have a non-zero condition code field.
+ Only a WRITE or EAMWRITE (opcode 15) should select an EAM
+ or floating point operation. Note that FP_SELECT_MASK is
+ the same bit (bit 3) as the interrupt bit which
+ distinguishes SYS1 from BRA and SYS2 from RFLAG. */
+ if ((no_srcb[opcode] && source_b)
+ || (!srcb_immed[opcode] && ins & CLASS3_SOURCEB_IMMED)
+ || (opcode != 12 && opcode != 15 && ins & CC_MASK)
+ || (opcode != 15 && ins & (EAM_SELECT_MASK | FP_SELECT_MASK)))
+ goto illegal_opcode;
+
+
+ switch (opcode)
+ {
+ case 0:
+ /* ADD instruction. */
+ (*info->fprintf_func) (info->stream, "add.%s r%d,r%d,r%d",
+ size_names[size], dest, source_a, source_b);
+ break;
+ case 1:
+ /* ADC instruction. */
+ (*info->fprintf_func) (info->stream, "adc.%s r%d,r%d,r%d",
+ size_names[size], dest, source_a, source_b);
+ break;
+ case 2:
+ /* SUB instruction. */
+ if (dest == 0)
+ (*info->fprintf_func) (info->stream, "cmp.%s r%d,r%d",
+ size_names[size], source_a, source_b);
+ else
+ (*info->fprintf_func) (info->stream, "sub.%s r%d,r%d,r%d",
+ size_names[size], dest, source_a, source_b);
+ break;
+ case 3:
+ /* SUBC instruction. */
+ if (dest == 0)
+ (*info->fprintf_func) (info->stream, "cmpc.%s r%d,r%d",
+ size_names[size], source_a, source_b);
+ else
+ (*info->fprintf_func) (info->stream, "subc.%s r%d,r%d,r%d",
+ size_names[size], dest, source_a, source_b);
+ break;
+ case 4:
+ /* EXTW instruction. */
+ if (size == 1)
+ goto illegal_opcode;
+
+ (*info->fprintf_func) (info->stream, "extw.%s r%d,r%d",
+ size_names[size], dest, source_a);
+ break;
+ case 5:
+ /* ASR instruction. */
+ if (ins & CLASS3_SOURCEB_IMMED)
+ (*info->fprintf_func) (info->stream, "asr.%s r%d,r%d,%d",
+ size_names[size], dest, source_a, source_b);
+ else
+ (*info->fprintf_func) (info->stream, "asr.%s r%d,r%d,r%d",
+ size_names[size], dest, source_a, source_b);
+ break;
+ case 6:
+ /* LSR instruction. */
+ if (ins & CLASS3_SOURCEB_IMMED)
+ (*info->fprintf_func) (info->stream, "lsr.%s r%d,r%d,%d",
+ size_names[size], dest, source_a, source_b);
+ else
+ (*info->fprintf_func) (info->stream, "lsr.%s r%d,r%d,r%d",
+ size_names[size], dest, source_a, source_b);
+ break;
+ case 7:
+ /* ASL instruction. */
+ if (ins & CLASS3_SOURCEB_IMMED)
+ (*info->fprintf_func) (info->stream, "asl.%s r%d,r%d,%d",
+ size_names[size], dest, source_a, source_b);
+ else
+ (*info->fprintf_func) (info->stream, "asl.%s r%d,r%d,r%d",
+ size_names[size], dest, source_a, source_b);
+ break;
+ case 8:
+ /* XOR instruction. */
+ (*info->fprintf_func) (info->stream, "xor.%s r%d,r%d,r%d",
+ size_names[size], dest, source_a, source_b);
+ break;
+ case 9:
+ /* OR instruction. */
+ if (source_b == 0)
+ (*info->fprintf_func) (info->stream, "move.%s r%d,r%d",
+ size_names[size], dest, source_a);
+ else
+ (*info->fprintf_func) (info->stream, "or.%s r%d,r%d,r%d",
+ size_names[size], dest, source_a, source_b);
+ break;
+ case 10:
+ /* AND instruction. */
+ (*info->fprintf_func) (info->stream, "and.%s r%d,r%d,r%d",
+ size_names[size], dest, source_a, source_b);
+ break;
+ case 11:
+ /* NOT instruction. */
+ (*info->fprintf_func) (info->stream, "not.%s r%d,r%d",
+ size_names[size], dest, source_a);
+ break;
+ case 12:
+ /* BRA instruction. */
+ {
+ unsigned cbf = (ins >> 27) & 0x000f;
+
+ if (size != 4)
+ goto illegal_opcode;
+
+ (*info->fprintf_func) (info->stream, "bra %s,r%d,r%d",
+ cc_names[cbf], source_a, dest);
+ }
+ break;
+ case 13:
+ /* RFLAG instruction. */
+ if (source_a || size != 4)
+ goto illegal_opcode;
+
+ (*info->fprintf_func) (info->stream, "rflag r%d", dest);
+ break;
+ case 14:
+ /* EXTB instruction. */
+ (*info->fprintf_func) (info->stream, "extb.%s r%d,r%d",
+ size_names[size], dest, source_a);
+ break;
+ case 15:
+ if (!(ins & CLASS3_SOURCEB_IMMED))
+ goto illegal_opcode;
+
+ if (ins & EAM_SELECT_MASK)
+ {
+ /* Extension arithmetic module read. */
+ int fp_ins = (ins >> 27) & 0xf;
+
+ if (size != 4)
+ goto illegal_opcode;
+
+ if (ins & FP_SELECT_MASK)
+ {
+ /* Check fsrcA <= 15 and fsrcB <= 15. */
+ if (ins & ((1 << 20) | (1 << 8)))
+ goto illegal_opcode;
+
+ switch (fp_ins)
+ {
+ case 0:
+ if (source_b)
+ goto illegal_opcode;
+
+ (*info->fprintf_func) (info->stream, "fstore r%d,f%d",
+ dest, source_a);
+ break;
+ case 10:
+ (*info->fprintf_func) (info->stream, "fcmp r%d,f%d,f%d",
+ dest, source_a, source_b);
+ break;
+ case 11:
+ (*info->fprintf_func) (info->stream, "fcmpe r%d,f%d,f%d",
+ dest, source_a, source_b);
+ break;
+ default:
+ (*info->fprintf_func) (info->stream,
+ "fpuread %d,r%d,f%d,f%d", fp_ins,
+ dest, source_a, source_b);
+ break;
+ }
+ }
+ else
+ {
+ if (fp_ins || source_a)
+ goto illegal_opcode;
+
+ switch (source_b)
+ {
+ case 0:
+ (*info->fprintf_func) (info->stream, "readmda r%d", dest);
+ break;
+ case 1:
+ (*info->fprintf_func) (info->stream, "readmdb r%d", dest);
+ break;
+ case 2:
+ (*info->fprintf_func) (info->stream, "readmdc r%d", dest);
+ break;
+ default:
+ (*info->fprintf_func) (info->stream, "eamread r%d,%d",
+ dest, source_b);
+ break;
+ }
+ }
+ }
+ else
+ {
+ if (ins & FP_SELECT_MASK)
+ goto illegal_opcode;
+
+ /* READ instruction. */
+ (*info->fprintf_func) (info->stream, "read.%s r%d,%d(r%d)",
+ size_names[size], dest, source_b, source_a);
+ }
+ break;
+ }
+
+ return 0;
+
+illegal_opcode:
+ return -1;
+
+}
+
+/* Print the visium instruction at address addr in debugged memory,
+ on info->stream. Return length of the instruction, in bytes. */
+
+int
+print_insn_visium (bfd_vma addr, disassemble_info *info)
+{
+ unsigned ins;
+ unsigned p1, p2;
+ int ans;
+ int i;
+
+ /* Stuff copied from m68k-dis.c. */
+ struct private priv;
+ bfd_byte *buffer = priv.the_buffer;
+ info->private_data = (PTR) & priv;
+ priv.max_fetched = priv.the_buffer;
+ priv.insn_start = addr;
+ if (setjmp (priv.bailout) != 0)
+ {
+ /* Error return. */
+ return -1;
+ }
+
+ /* We do return this info. */
+ info->insn_info_valid = 1;
+
+ /* Assume non branch insn. */
+ info->insn_type = dis_nonbranch;
+
+ /* Assume no delay. */
+ info->branch_delay_insns = 0;
+
+ /* Assume no target known. */
+ info->target = 0;
+
+ /* Get 32-bit instruction word. */
+ FETCH_DATA (info, buffer + 4);
+ ins = buffer[0] << 24;
+ ins |= buffer[1] << 16;
+ ins |= buffer[2] << 8;
+ ins |= buffer[3];
+
+ ans = 0;
+
+ p1 = buffer[0] ^ buffer[1] ^ buffer[2] ^ buffer[3];
+ p2 = 0;
+ for (i = 0; i < 8; i++)
+ {
+ p2 += p1 & 1;
+ p1 >>= 1;
+ }
+
+ /* Decode the instruction. */
+ if (p2 & 1)
+ ans = -1;
+ else
+ {
+ switch ((ins >> 25) & 0x3)
+ {
+ case 0:
+ ans = disassem_class0 (info, ins);
+ break;
+ case 1:
+ ans = disassem_class1 (info, ins);
+ break;
+ case 2:
+ ans = disassem_class2 (info, ins);
+ break;
+ case 3:
+ ans = disassem_class3 (info, ins);
+ break;
+ }
+ }
+
+ if (ans != 0)
+ (*info->fprintf_func) (info->stream, "err");
+
+ /* Return number of bytes consumed (always 4 for the Visium). */
+ return 4;
+}