aboutsummaryrefslogtreecommitdiff
path: root/opcodes
diff options
context:
space:
mode:
Diffstat (limited to 'opcodes')
-rw-r--r--opcodes/ChangeLog13
-rw-r--r--opcodes/Makefile.am2
-rw-r--r--opcodes/Makefile.in4
-rwxr-xr-xopcodes/configure1
-rw-r--r--opcodes/configure.ac1
-rw-r--r--opcodes/disassemble.c6
-rw-r--r--opcodes/po/POTFILES.in2
-rw-r--r--opcodes/visium-dis.c834
-rw-r--r--opcodes/visium-opc.c23
9 files changed, 886 insertions, 0 deletions
diff --git a/opcodes/ChangeLog b/opcodes/ChangeLog
index 00bb53a..d64d138 100644
--- a/opcodes/ChangeLog
+++ b/opcodes/ChangeLog
@@ -1,3 +1,16 @@
+2014-12-06 Eric Botcazou <ebotcazou@adacore.com>
+
+ * 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.
+
2014-11-30 Alan Modra <amodra@gmail.com>
* ppc-opc.c (powerpc_opcodes): Make mftb* generate mfspr for
diff --git a/opcodes/Makefile.am b/opcodes/Makefile.am
index 4acc436..9b76239 100644
--- a/opcodes/Makefile.am
+++ b/opcodes/Makefile.am
@@ -250,6 +250,8 @@ TARGET_LIBOPCODES_CFILES = \
v850-dis.c \
v850-opc.c \
vax-dis.c \
+ visium-dis.c \
+ visium-opc.c \
w65-dis.c \
xc16x-asm.c \
xc16x-desc.c \
diff --git a/opcodes/Makefile.in b/opcodes/Makefile.in
index 46ef017..4f02d81 100644
--- a/opcodes/Makefile.in
+++ b/opcodes/Makefile.in
@@ -523,6 +523,8 @@ TARGET_LIBOPCODES_CFILES = \
v850-dis.c \
v850-opc.c \
vax-dis.c \
+ visium-dis.c \
+ visium-opc.c \
w65-dis.c \
xc16x-asm.c \
xc16x-desc.c \
@@ -923,6 +925,8 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/v850-dis.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/v850-opc.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vax-dis.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/visium-dis.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/visium-opc.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/w65-dis.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xc16x-asm.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xc16x-desc.Plo@am__quote@
diff --git a/opcodes/configure b/opcodes/configure
index 7f13699..c97bdf6 100755
--- a/opcodes/configure
+++ b/opcodes/configure
@@ -12626,6 +12626,7 @@ if test x${all_targets} = xfalse ; then
bfd_v850ea_arch) ta="$ta v850-opc.lo v850-dis.lo" ;;
bfd_v850_rh850_arch) ta="$ta v850-opc.lo v850-dis.lo" ;;
bfd_vax_arch) ta="$ta vax-dis.lo" ;;
+ bfd_visium_arch) ta="$ta visium-dis.lo visium-opc.lo" ;;
bfd_w65_arch) ta="$ta w65-dis.lo" ;;
bfd_we32k_arch) ;;
bfd_xc16x_arch) ta="$ta xc16x-asm.lo xc16x-desc.lo xc16x-dis.lo xc16x-ibld.lo xc16x-opc.lo" using_cgen=yes ;;
diff --git a/opcodes/configure.ac b/opcodes/configure.ac
index b93e855..39eb2fb 100644
--- a/opcodes/configure.ac
+++ b/opcodes/configure.ac
@@ -343,6 +343,7 @@ if test x${all_targets} = xfalse ; then
bfd_v850ea_arch) ta="$ta v850-opc.lo v850-dis.lo" ;;
bfd_v850_rh850_arch) ta="$ta v850-opc.lo v850-dis.lo" ;;
bfd_vax_arch) ta="$ta vax-dis.lo" ;;
+ bfd_visium_arch) ta="$ta visium-dis.lo visium-opc.lo" ;;
bfd_w65_arch) ta="$ta w65-dis.lo" ;;
bfd_we32k_arch) ;;
bfd_xc16x_arch) ta="$ta xc16x-asm.lo xc16x-desc.lo xc16x-dis.lo xc16x-ibld.lo xc16x-opc.lo" using_cgen=yes ;;
diff --git a/opcodes/disassemble.c b/opcodes/disassemble.c
index 0a0814e..63103bb 100644
--- a/opcodes/disassemble.c
+++ b/opcodes/disassemble.c
@@ -89,6 +89,7 @@
#define ARCH_tilepro
#define ARCH_v850
#define ARCH_vax
+#define ARCH_visium
#define ARCH_w65
#define ARCH_xstormy16
#define ARCH_xc16x
@@ -493,6 +494,11 @@ disassembler (abfd)
disassemble = print_insn_vax;
break;
#endif
+#ifdef ARCH_visium
+ case bfd_arch_visium:
+ disassemble = print_insn_visium;
+ break;
+#endif
#ifdef ARCH_frv
case bfd_arch_frv:
disassemble = print_insn_frv;
diff --git a/opcodes/po/POTFILES.in b/opcodes/po/POTFILES.in
index 0212748..8e8e122 100644
--- a/opcodes/po/POTFILES.in
+++ b/opcodes/po/POTFILES.in
@@ -207,6 +207,8 @@ tilepro-opc.c
v850-dis.c
v850-opc.c
vax-dis.c
+visium-dis.c
+visium-opc.c
w65-dis.c
w65-opc.h
xc16x-asm.c
diff --git a/opcodes/visium-dis.c b/opcodes/visium-dis.c
new file mode 100644
index 0000000..96be972
--- /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;
+}
diff --git a/opcodes/visium-opc.c b/opcodes/visium-opc.c
new file mode 100644
index 0000000..742452c
--- /dev/null
+++ b/opcodes/visium-opc.c
@@ -0,0 +1,23 @@
+/* Opcode table 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 "ansidecl.h"
+#include "opcode/visium.h"