* configure.in: Compile them.
* configure: Regenerate.
* Makefile.am (ALL_MACHINES): Add txvu-{dis,opc}.lo.
(txvu-dis.lo,txvu-opc.lo): Add rules for.
* Makefile.in: Regenerate.
lose_these_too="${tic80_files} ${lose_these_too}"
fi
+sky_files="txvu-opc.c txvu-dis.c"
+
+if ( echo $* | grep keep\-sky > /dev/null ) ; then
+ keep_these_too="${sky_files} ${keep_these_too}"
+else
+ lose_these_too="${sky_files} ${lose_these_too}"
+fi
+
# All files listed between the "Things-to-keep:" line and the
# "Files-to-sed:" line will be kept. All other files will be removed.
# Directories listed in this section will have their own Sanitize
start-sanitize-sky
+Mon Jan 5 13:41:07 1998 Doug Evans <devans@seba.cygnus.com>
+
+ * txvu-dis.c, txvu-opc.c: New files.
+ * configure.in: Compile them.
+ * configure: Regenerate.
+ * Makefile.am (ALL_MACHINES): Add txvu-{dis,opc}.lo.
+ (txvu-dis.lo,txvu-opc.lo): Add rules for.
+ * Makefile.in: Regenerate.
+
Mon Dec 22 17:17:03 1997 Doug Evans <devans@canuck.cygnus.com>
* configure.in: Add txvu support.
--- /dev/null
+## Process this file with automake to generate Makefile.in
+
+INCDIR = $(srcdir)/../include
+BFDDIR = $(srcdir)/../bfd
+DEP = mkdep
+
+lib_LTLIBRARIES = libopcodes.la
+
+# This is where bfd.h lives.
+BFD_H = ../bfd/bfd.h
+
+# Header files.
+HFILES = \
+ arm-opc.h \
+ h8500-opc.h \
+ sh-opc.h \
+ sysdep.h \
+ w65-opc.h \
+ z8k-opc.h
+
+# C source files that correspond to .o's.
+CFILES = \
+ a29k-dis.c \
+ alpha-dis.c \
+ alpha-opc.c \
+ arm-dis.c \
+ cgen-asm.c \
+ cgen-dis.c \
+ cgen-opc.c \
+ d10v-dis.c \
+ d10v-opc.c \
+ dis-buf.c \
+ disassemble.c \
+ h8300-dis.c \
+ h8500-dis.c \
+ hppa-dis.c \
+ i386-dis.c \
+ i960-dis.c \
+ m32r-asm.c \
+ m32r-dis.c \
+ m32r-opc.c \
+ m68k-dis.c \
+ m68k-opc.c \
+ m88k-dis.c \
+ mips-dis.c \
+ mips-opc.c \
+ mips16-opc.c \
+ m10200-dis.c \
+ m10200-opc.c \
+ m10300-dis.c \
+ m10300-opc.c \
+ ns32k-dis.c \
+ ppc-dis.c \
+ ppc-opc.c \
+ sh-dis.c \
+ sparc-dis.c \
+ sparc-opc.c \
+ w65-dis.c \
+ z8k-dis.c \
+ z8kgen.c
+
+ALL_MACHINES = \
+ a29k-dis.lo \
+ alpha-dis.lo \
+ alpha-opc.lo \
+ arc-dis.lo \
+ arc-opc.lo \
+ arm-dis.lo \
+ cgen-asm.lo \
+ cgen-dis.lo \
+ cgen-opc.lo \
+ d10v-dis.lo \
+ d10v-opc.lo \
+ $(start-sanitize-d30v) \
+ d30v-dis.lo \
+ d30v-opc.lo \
+ $(end-sanitize-d30v) \
+ h8300-dis.lo \
+ h8500-dis.lo \
+ hppa-dis.lo \
+ i386-dis.lo \
+ i960-dis.lo \
+ m32r-asm.lo \
+ m32r-dis.lo \
+ m32r-opc.lo \
+ m68k-dis.lo \
+ m68k-opc.lo \
+ m88k-dis.lo \
+ m10200-dis.lo \
+ m10200-opc.lo \
+ m10300-dis.lo \
+ m10300-opc.lo \
+ mips-dis.lo \
+ mips-opc.lo \
+ mips16-opc.lo \
+ ppc-dis.lo \
+ ppc-opc.lo \
+ ns32k-dis.lo \
+ sh-dis.lo \
+ sparc-dis.lo \
+ sparc-opc.lo \
+ $(start-sanitize-tic80) \
+ tic80-dis.lo \
+ tic80-opc.lo \
+ $(end-sanitize-tic80) \
+ $(start-sanitize-sky) \
+ txvu-dis.lo \
+ txvu-opc.lo \
+ $(end-sanitize-sky) \
+ v850-dis.lo \
+ v850-opc.lo \
+ w65-dis.lo \
+ z8k-dis.lo
+
+OFILES = @BFD_MACHINES@
+
+INCLUDES = -D_GNU_SOURCE -I. -I$(srcdir) -I../bfd -I$(INCDIR) -I$(BFDDIR) @HDEFINES@
+
+disassemble.lo: disassemble.c $(INCDIR)/dis-asm.h
+ $(LIBTOOL) --mode=compile $(COMPILE) -c @archdefs@ $(srcdir)/disassemble.c
+
+libopcodes_la_SOURCES = dis-buf.c disassemble.c
+libopcodes_la_DEPENDENCIES = $(OFILES)
+libopcodes_la_LIBADD = $(OFILES)
+
+# libtool will build .libs/libopcodes.a. We create libopcodes.a in
+# the build directory so that we don't have to convert all the
+# programs that use libopcodes.a simultaneously. This is a hack which
+# should be removed if everything else starts using libtool. FIXME.
+
+noinst_LIBRARIES = libopcodes.a
+
+stamp-lib: libopcodes.la
+ cp .libs/libopcodes.a libopcodes.tmp
+ $(SHELL) $(srcdir)/../move-if-change libopcodes.tmp libopcodes.a
+ touch stamp-lib
+
+libopcodes.a: stamp-lib ; @true
+
+CLEANFILES = libopcodes.a stamp-lib dep.sed .dep .dep1
+
+# start-sanitize-tic80
+tic80-dis.lo: tic80-dis.c $(INCDIR)/dis-asm.h ../bfd/bfd.h \
+ $(INCDIR)/opcode/tic80.h
+tic80-opc.lo: tic80-opc.c $(INCDIR)/opcode/tic80.h
+# end-sanitize-tic80
+
+# start-sanitize-sky
+txvu-dis.lo: txvu-dis.c $(INCDIR)/dis-asm.h ../bfd/bfd.h \
+ $(INCDIR)/opcode/txvu.h
+txvu-opc.lo: txvu-opc.c $(INCDIR)/opcode/txvu.h
+# end-sanitize-sky
+
+# This dependency stuff is copied from BFD.
+
+.dep: dep.sed $(CFILES) $(HFILES) config.h
+ rm -f .dep1
+ $(MAKE) DEP=$(DEP) .dep1
+ sed -f dep.sed < .dep1 > .dep
+
+.dep1: $(CFILES)
+ rm -f .dep2 .dep2a
+ echo '# DO NOT DELETE THIS LINE -- mkdep uses it.' > .dep2
+ echo > .dep2a
+ $(DEP) -f .dep2a $(INCLUDES) $(CFLAGS) $?
+ sed -e '/DO NOT DELETE/d' -e '/^$$/d' < .dep2a >> .dep2
+ rm -f .dep2a
+ $(srcdir)/../move-if-change .dep2 .dep1
+
+dep.sed: dep-in.sed config.status
+ sed <$(srcdir)/dep-in.sed >dep.sed \
+ -e 's!@BFD_H@!$(BFD_H)!' \
+ -e 's!@INCDIR@!$(INCDIR)!' \
+ -e 's!@BFDDIR@!$(BFDDIR)!' \
+ -e 's!@SRCDIR@!$(srcdir)!'
+
+dep: .dep
+ sed -e '/^..DO NOT DELETE THIS LINE/,$$d' < Makefile > tmp-Makefile
+ cat .dep >> tmp-Makefile
+ $(srcdir)/../move-if-change tmp-Makefile Makefile
+
+dep-in: .dep
+ sed -e '/^..DO NOT DELETE THIS LINE/,$$d' < $(srcdir)/Makefile.in > tmp-Makefile.in
+ cat .dep >> tmp-Makefile.in
+ $(srcdir)/../move-if-change tmp-Makefile.in $(srcdir)/Makefile.in
+
+dep-am: .dep
+ sed -e '/^..DO NOT DELETE THIS LINE/,$$d' < $(srcdir)/Makefile.am > tmp-Makefile.am
+ cat .dep >> tmp-Makefile.am
+ $(srcdir)/../move-if-change tmp-Makefile.am $(srcdir)/Makefile.am
+
+.PHONY: dep dep-in dep-am
+
+# What appears below is generated by a hacked mkdep using gcc -MM.
+
+# DO NOT DELETE THIS LINE -- mkdep uses it.
+# DO NOT PUT ANYTHING AFTER THIS LINE, IT WILL GO AWAY.
+a29k-dis.lo: a29k-dis.c $(INCDIR)/dis-asm.h $(BFD_H) \
+ $(INCDIR)/ansidecl.h $(INCDIR)/opcode/a29k.h
+alpha-dis.lo: alpha-dis.c $(INCDIR)/ansidecl.h sysdep.h \
+ config.h $(INCDIR)/dis-asm.h $(BFD_H) $(INCDIR)/opcode/alpha.h
+alpha-opc.lo: alpha-opc.c $(INCDIR)/ansidecl.h $(INCDIR)/opcode/alpha.h \
+ $(BFD_H)
+arm-dis.lo: arm-dis.c $(INCDIR)/dis-asm.h $(BFD_H) \
+ $(INCDIR)/ansidecl.h arm-opc.h
+cgen-asm.lo: cgen-asm.c sysdep.h config.h $(INCDIR)/libiberty.h \
+ $(BFD_H) $(INCDIR)/opcode/cgen.h
+cgen-dis.lo: cgen-dis.c sysdep.h config.h $(INCDIR)/libiberty.h \
+ $(BFD_H) $(INCDIR)/opcode/cgen.h
+cgen-opc.lo: cgen-opc.c sysdep.h config.h $(INCDIR)/libiberty.h \
+ $(BFD_H) $(INCDIR)/opcode/cgen.h
+d10v-dis.lo: d10v-dis.c $(INCDIR)/ansidecl.h $(INCDIR)/opcode/d10v.h \
+ $(INCDIR)/dis-asm.h $(BFD_H)
+d10v-opc.lo: d10v-opc.c $(INCDIR)/ansidecl.h $(INCDIR)/opcode/d10v.h
+dis-buf.lo: dis-buf.c sysdep.h config.h $(INCDIR)/dis-asm.h \
+ $(BFD_H)
+disassemble.lo: disassemble.c $(INCDIR)/ansidecl.h \
+ $(INCDIR)/dis-asm.h $(BFD_H)
+h8300-dis.lo: h8300-dis.c $(INCDIR)/opcode/h8300.h \
+ $(INCDIR)/dis-asm.h $(BFD_H) $(INCDIR)/ansidecl.h
+h8500-dis.lo: h8500-dis.c h8500-opc.h $(INCDIR)/dis-asm.h \
+ $(BFD_H) $(INCDIR)/ansidecl.h
+hppa-dis.lo: hppa-dis.c sysdep.h config.h $(INCDIR)/dis-asm.h \
+ $(BFD_H) $(BFDDIR)/libhppa.h $(INCDIR)/opcode/hppa.h
+i386-dis.lo: i386-dis.c $(INCDIR)/dis-asm.h $(BFD_H) \
+ $(INCDIR)/ansidecl.h sysdep.h config.h
+i960-dis.lo: i960-dis.c $(INCDIR)/dis-asm.h $(BFD_H) \
+ $(INCDIR)/ansidecl.h
+m32r-asm.lo: m32r-asm.c sysdep.h config.h $(BFD_H) \
+ m32r-opc.h $(INCDIR)/opcode/cgen.h
+m32r-dis.lo: m32r-dis.c sysdep.h config.h $(INCDIR)/dis-asm.h \
+ $(BFD_H) m32r-opc.h $(INCDIR)/opcode/cgen.h
+m32r-opc.lo: m32r-opc.c sysdep.h config.h $(INCDIR)/libiberty.h \
+ $(BFD_H) m32r-opc.h $(INCDIR)/opcode/cgen.h
+m68k-dis.lo: m68k-dis.c $(INCDIR)/dis-asm.h $(BFD_H) \
+ $(INCDIR)/ansidecl.h $(INCDIR)/floatformat.h $(INCDIR)/opcode/m68k.h
+m68k-opc.lo: m68k-opc.c $(INCDIR)/ansidecl.h $(INCDIR)/opcode/m68k.h
+m88k-dis.lo: m88k-dis.c $(INCDIR)/dis-asm.h $(BFD_H) \
+ $(INCDIR)/ansidecl.h $(INCDIR)/opcode/m88k.h
+mips-dis.lo: mips-dis.c sysdep.h config.h $(INCDIR)/dis-asm.h \
+ $(BFD_H) $(INCDIR)/opcode/mips.h $(BFDDIR)/elf-bfd.h \
+ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
+ $(INCDIR)/bfdlink.h $(INCDIR)/elf/mips.h
+mips-opc.lo: mips-opc.c $(INCDIR)/ansidecl.h $(INCDIR)/opcode/mips.h
+mips16-opc.lo: mips16-opc.c $(INCDIR)/ansidecl.h $(INCDIR)/opcode/mips.h
+m10200-dis.lo: m10200-dis.c $(INCDIR)/ansidecl.h $(INCDIR)/opcode/mn10200.h \
+ $(INCDIR)/dis-asm.h $(BFD_H)
+m10200-opc.lo: m10200-opc.c $(INCDIR)/ansidecl.h $(INCDIR)/opcode/mn10200.h
+m10300-dis.lo: m10300-dis.c $(INCDIR)/ansidecl.h $(INCDIR)/opcode/mn10300.h \
+ $(INCDIR)/dis-asm.h $(BFD_H)
+m10300-opc.lo: m10300-opc.c $(INCDIR)/ansidecl.h $(INCDIR)/opcode/mn10300.h
+ns32k-dis.lo: ns32k-dis.c $(BFD_H) $(INCDIR)/ansidecl.h \
+ sysdep.h config.h $(INCDIR)/dis-asm.h $(INCDIR)/opcode/ns32k.h
+ppc-dis.lo: ppc-dis.c $(INCDIR)/ansidecl.h sysdep.h \
+ config.h $(INCDIR)/dis-asm.h $(BFD_H) $(INCDIR)/opcode/ppc.h
+ppc-opc.lo: ppc-opc.c $(INCDIR)/ansidecl.h $(INCDIR)/opcode/ppc.h
+sh-dis.lo: sh-dis.c sh-opc.h $(INCDIR)/dis-asm.h $(BFD_H) \
+ $(INCDIR)/ansidecl.h
+sparc-dis.lo: sparc-dis.c $(INCDIR)/ansidecl.h sysdep.h \
+ config.h $(INCDIR)/opcode/sparc.h $(INCDIR)/dis-asm.h \
+ $(BFD_H) $(INCDIR)/libiberty.h
+sparc-opc.lo: sparc-opc.c $(INCDIR)/ansidecl.h $(INCDIR)/opcode/sparc.h
+w65-dis.lo: w65-dis.c w65-opc.h $(INCDIR)/dis-asm.h \
+ $(BFD_H) $(INCDIR)/ansidecl.h
+z8k-dis.lo: z8k-dis.c sysdep.h config.h $(INCDIR)/dis-asm.h \
+ $(BFD_H) z8k-opc.h
+z8kgen.lo: z8kgen.c sysdep.h config.h
+# IF YOU PUT ANYTHING HERE IT WILL GO AWAY
tic80-dis.lo \
tic80-opc.lo \
$(end-sanitize-tic80) \
+ $(start-sanitize-sky) \
+ txvu-dis.lo \
+ txvu-opc.lo \
+ $(end-sanitize-sky) \
v850-dis.lo \
v850-opc.lo \
w65-dis.lo \
tic80-opc.lo: tic80-opc.c $(INCDIR)/opcode/tic80.h
# end-sanitize-tic80
+# start-sanitize-sky
+txvu-dis.lo: txvu-dis.c $(INCDIR)/dis-asm.h ../bfd/bfd.h \
+ $(INCDIR)/opcode/txvu.h
+txvu-opc.lo: txvu-opc.c $(INCDIR)/opcode/txvu.h
+# end-sanitize-sky
+
# This dependency stuff is copied from BFD.
.dep: dep.sed $(CFILES) $(HFILES) config.h
bfd_tic80_arch) ta="$ta tic80-dis.lo tic80-opc.lo" ;;
# end-sanitize-tic80
# start-sanitize-sky
- bfd_txvu_arch) ta="$ta" ;;
+ bfd_txvu_arch) ta="$ta txvu-dis.lo txvu-opc.lo" ;;
# end-sanitize-sky
bfd_v850_arch) ta="$ta v850-opc.lo v850-dis.lo" ;;
# start-sanitize-v850e
bfd_tic80_arch) ta="$ta tic80-dis.lo tic80-opc.lo" ;;
# end-sanitize-tic80
# start-sanitize-sky
- bfd_txvu_arch) ta="$ta" ;;
+ bfd_txvu_arch) ta="$ta txvu-dis.lo txvu-opc.lo" ;;
# end-sanitize-sky
bfd_v850_arch) ta="$ta v850-opc.lo v850-dis.lo" ;;
# start-sanitize-v850e
--- /dev/null
+/* Instruction printing code for the TXVU
+ Copyright (C) 1998 Free Software Foundation, Inc.
+
+ This program 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 2 of the License, or
+ (at your option) any later version.
+
+ This program 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.,
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "dis-asm.h"
+#include "opcode/txvu.h"
+#include "elf-bfd.h"
+#include "elf/txvu.h"
+
+static void print_insn PARAMS ((bfd_vma, disassemble_info *, TXVU_INSN, int));
+
+/* Print one instruction from PC on INFO->STREAM.
+ Return the size of the instruction. */
+
+int
+print_insn_txvu (pc, info)
+ bfd_vma pc;
+ disassemble_info *info;
+{
+ bfd_byte buffer[8];
+ void *stream = info->stream;
+ fprintf_ftype func = info->fprintf_func;
+ int status;
+ /* First element is upper, second is lower. */
+ TXVU_INSN upper,lower;
+ static int initialized = 0;
+
+ if (!initialized)
+ {
+ initialized = 1;
+ txvu_opcode_init_tables (0);
+ }
+
+ status = (*info->read_memory_func) (pc, buffer, 8, info);
+ if (status != 0)
+ {
+ (*info->memory_error_func) (status, pc, info);
+ return -1;
+ }
+ upper = bfd_getl32 (buffer);
+ lower = bfd_getl32 (buffer + 4);
+
+ /* FIXME: This will need revisiting. */
+ print_insn (pc, info, upper, 0);
+ (*func) (stream, " || ");
+ print_insn (pc, info, lower, 1);
+
+ return 8;
+}
+
+/* Print one instruction.
+ LOWER_P is non-zero if disassembling a lower slot insn. */
+
+static void
+print_insn (pc, info, insn, lower_p)
+ bfd_vma pc;
+ disassemble_info *info;
+ TXVU_INSN insn;
+ int lower_p;
+{
+ const struct txvu_opcode *opcode;
+ void *stream = info->stream;
+ fprintf_ftype func = info->fprintf_func;
+
+ /* The instructions are stored in lists hashed by the insn code
+ (though we needn't care how they're hashed). */
+
+ if (lower_p)
+ opcode = txvu_lower_opcode_lookup_dis (insn);
+ else
+ opcode = txvu_upper_opcode_lookup_dis (insn);
+ for ( ; opcode != NULL; opcode = TXVU_OPCODE_NEXT_DIS (opcode))
+ {
+ const unsigned char *syn;
+ int mods,invalid,num_operands;
+ long value;
+ const struct txvu_operand *operand;
+
+ /* Basic bit mask must be correct. */
+ if ((insn & opcode->mask) != opcode->value)
+ continue;
+
+ /* Make two passes over the operands. First see if any of them
+ have extraction functions, and, if they do, make sure the
+ instruction is valid. */
+
+ txvu_opcode_init_print ();
+ invalid = 0;
+
+ for (syn = opcode->syntax; *syn; ++syn)
+ {
+ int index;
+
+ if (*syn < 128)
+ continue;
+
+ mods = 0;
+ index = TXVU_OPERAND_INDEX (*syn);
+ while (TXVU_MOD_P (txvu_operands[index].flags))
+ {
+ mods |= txvu_operands[index].flags & TXVU_MOD_BITS;
+ ++syn;
+ index = TXVU_OPERAND_INDEX (*syn);
+ }
+ operand = txvu_operands + index;
+ if (operand->extract)
+ (*operand->extract) (insn, operand, mods, &invalid);
+ }
+ if (invalid)
+ continue;
+
+ /* The instruction is valid. */
+
+ (*func) (stream, "%s", opcode->mnemonic);
+ num_operands = 0;
+ for (syn = opcode->syntax; *syn; ++syn)
+ {
+ int index;
+
+ if (*syn < 128)
+ {
+ (*func) (stream, "%c", *syn);
+ continue;
+ }
+
+ /* We have an operand. Fetch any special modifiers. */
+ mods = 0;
+ index = TXVU_OPERAND_INDEX (*syn);
+ while (TXVU_MOD_P (txvu_operands[index].flags))
+ {
+ mods |= txvu_operands[index].flags & TXVU_MOD_BITS;
+ ++syn;
+ index = TXVU_OPERAND_INDEX (*syn);
+ }
+ operand = txvu_operands + index;
+
+ /* Extract the value from the instruction. */
+ if (operand->extract)
+ {
+ value = (*operand->extract) (insn, operand, mods, (int *) NULL);
+ }
+ else
+ {
+ value = (insn >> operand->shift) & ((1 << operand->bits) - 1);
+ if ((operand->flags & TXVU_OPERAND_SIGNED)
+ && (value & (1 << (operand->bits - 1))))
+ value -= 1 << operand->bits;
+ }
+
+ /* If second or later operand, print a comma. */
+ if (num_operands > 0)
+ (*func) (stream, ",");
+
+ /* Print the operand as directed by the flags. */
+ if (operand->print)
+ (*operand->print) (info, insn, value);
+ else if (operand->flags & TXVU_OPERAND_FAKE)
+ ; /* nothing to do (??? at least not yet) */
+ else if (operand->flags & TXVU_OPERAND_RELATIVE_BRANCH)
+ (*info->print_address_func) (pc + value, info);
+ /* ??? Not all cases of this are currently caught. */
+ else if (operand->flags & TXVU_OPERAND_ABSOLUTE_BRANCH)
+ (*info->print_address_func) ((bfd_vma) value & 0xffffffff, info);
+ else if (operand->flags & TXVU_OPERAND_ADDRESS)
+ (*info->print_address_func) ((bfd_vma) value & 0xffffffff, info);
+ else
+ (*func) (stream, "%ld", value);
+
+ if (! (operand->flags & TXVU_OPERAND_SUFFIX))
+ ++num_operands;
+ }
+
+ /* We have found and printed an instruction; return. */
+ return;
+ }
+
+ (*func) (stream, "*unknown*");
+}
--- /dev/null
+/* Opcode table for the TXVU
+ Copyright 1998 Free Software Foundation, Inc.
+
+ This program 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 2, or (at your option)
+ any later version.
+
+ This program 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.,
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "ansidecl.h"
+#include "dis-asm.h"
+#include "opcode/txvu.h"
+
+#ifndef NULL
+#define NULL 0
+#endif
+
+#if defined (__STDC__) || defined (ALMOST_STDC)
+#define XCONCAT2(a,b) a##b
+#else
+#define XCONCAT2(a,b) a/**/b
+#endif
+#define CONCAT2(a,b) XCONCAT2(a,b)
+
+/* ??? One can argue it's preferable to have the PARSE_FN support in tc-vxvu.c
+ and the PRINT_FN support in txvu-dis.c. For this project I like having
+ them all in one place. */
+
+#define PARSE_FN(fn) \
+static long CONCAT2 (parse_,fn) \
+ PARAMS ((char **, const char **));
+#define INSERT_FN(fn) \
+static TXVU_INSN CONCAT2 (insert_,fn) \
+ PARAMS ((TXVU_INSN, const struct txvu_operand *, \
+ int, long, const char **))
+#define EXTRACT_FN(fn) \
+static long CONCAT2 (extract_,fn) \
+ PARAMS ((TXVU_INSN, const struct txvu_operand *, \
+ int, int *))
+#define PRINT_FN(fn) \
+static void CONCAT2 (print_,fn) \
+ PARAMS ((disassemble_info *, TXVU_INSN, long));
+
+PARSE_FN (dotdest);
+PRINT_FN (dotdest);
+
+PARSE_FN (reg);
+PRINT_FN (reg);
+
+/* Various types of ARC operands, including insn suffixes.
+
+ Fields are:
+
+ BITS SHIFT FLAGS PARSE_FN INSERT_FN EXTRACT_FN PRINT_FN
+
+ Operand values are 128 + table index. This allows ASCII chars to be
+ included in the syntax spec. */
+
+const struct txvu_operand txvu_operands[] =
+{
+/* place holder (??? not sure if needed) */
+#define UNUSED 128
+ { 0 },
+
+/* Destination indicator, with leading '.'. */
+#define DOTDEST (UNUSED + 1)
+ { 4, TXVU_SHIFT_DEST, TXVU_OPERAND_SUFFIX,
+ parse_dotdest, 0, 0, print_dotdest },
+
+/* ft reg */
+#define FTREG (DOTDEST + 1)
+ { 5, TXVU_SHIFT_FTREG, 0, parse_reg, 0, 0, print_reg },
+
+/* fs reg */
+#define FSREG (FTREG + 1)
+ { 5, TXVU_SHIFT_FSREG, 0, parse_reg, 0, 0, print_reg },
+
+/* fd reg */
+#define FDREG (FSREG + 1)
+ { 5, TXVU_SHIFT_FDREG, 0, parse_reg, 0, 0, print_reg },
+
+/* end of list place holder */
+ { 0 }
+};
+\f
+/* Macros to put a field's value into the right place. */
+#define FT(x) (((x) & TXVU_MASK_REG) << TXVU_SHIFT_FTREG)
+#define FS(x) (((x) & TXVU_MASK_REG) << TXVU_SHIFT_FSREG)
+#define FD(x) (((x) & TXVU_MASK_REG) << TXVU_SHIFT_FDREG)
+#define R(x,b,m) (((x) & (m)) << (b)) /* value X, mask M, at bit B */
+
+/* TXVU instructions.
+ [??? some of these comments are left over from the ARC port from which
+ this code is borrowed, delete in time]
+
+ Longer versions of insns must appear before shorter ones (if gas sees
+ "lsr r2,r3,1" when it's parsing "lsr %a,%b" it will think the ",1" is
+ junk). This isn't necessary for `ld' because of the trailing ']'.
+
+ Instructions that are really macros based on other insns must appear
+ before the real insn so they're chosen when disassembling. Eg: The `mov'
+ insn is really the `and' insn.
+
+ This table is best viewed on a wide screen (161 columns). I'd prefer to
+ keep it this way. The rest of the file, however, should be viewable on an
+ 80 column terminal. */
+
+/* ??? This table also includes macros: asl, lsl, and mov. The ppc port has
+ a more general facility for dealing with macros which could be used if
+ we need to. */
+
+/* These tables can't be `const' because members `next_asm' and `next_dis' are
+ computed at run-time. We could split this into two, as that would put the
+ constant stuff into a readonly section. */
+
+struct txvu_opcode txvu_upper_opcodes[] = {
+
+ /* Macros appear first. */
+ /* ??? Any aliases? */
+
+ /* The rest of these needn't be sorted, but it helps to find them if they
+ are. */
+ { "abs", { DOTDEST, ' ', FTREG, FSREG }, 0xfe0001ff, 0x1fd, 0 },
+ { "add", { DOTDEST, ' ', FDREG, FSREG, FTREG }, 0xfe00003f, 0x28, 0 },
+};
+const int txvu_upper_opcodes_count = sizeof (txvu_upper_opcodes) / sizeof (txvu_opcodes[0]);
+
+struct txvu_opcode txvu_lower_opcodes[] = {
+
+ /* Macros appear first. */
+ /* ??? Any aliases? */
+
+ /* The rest of these needn't be sorted, but it helps to find them if they
+ are. */
+ { "waitp", { 0 }, 0xffffffff, 0x800007bf, 0 },
+ { "waitq", { 0 }, 0xffffffff, 0x800003bf, 0 },
+};
+const int txvu_lower_opcodes_count = sizeof (txvu_lower_opcodes) / sizeof (txvu_opcodes[0]);
+
+/* Indexed by first letter of opcode. Points to chain of opcodes with same
+ first letter. */
+/* ??? One can certainly use a better hash. Later. */
+static struct txvu_opcode *upper_opcode_map[26 + 1];
+static struct txvu_opcode *lower_opcode_map[26 + 1];
+
+/* Indexed by insn code. Points to chain of opcodes with same insn code. */
+static struct txvu_opcode *upper_icode_map[64];
+static struct txvu_opcode *lower_icode_map[64];
+\f
+/* Initialize any tables that need it.
+ Must be called once at start up (or when first needed).
+
+ FLAGS is currently unused but is intended to control initialization. */
+
+void
+txvu_opcode_init_tables (flags)
+ int flags;
+{
+ static int init_p = 0;
+
+ /* We may be intentionally called more than once (for example gdb will call
+ us each time the user switches cpu). These tables only need to be init'd
+ once though. */
+ /* ??? We can remove the need for txvu_opcode_supported by taking it into
+ account here, but I'm not sure I want to do that yet (if ever). */
+ if (!init_p)
+ {
+ int i,n;
+
+ memset (upper_opcode_map, 0, sizeof (upper_opcode_map));
+ memset (upper_icode_map, 0, sizeof (upper_icode_map));
+
+ /* Scan the table backwards so macros appear at the front. */
+ for (i = txvu_upper_opcodes_count - 1; i >= 0; --i)
+ {
+ int opcode_hash = TXVU_HASH_UPPER_OPCODE (txvu_upper_opcodes[i].mnemonic);
+ int icode_hash = TXVU_HASH_UPPER_ICODE (txvu_upper_opcodes[i].value);
+
+ txvu_upper_opcodes[i].next_asm = upper_opcode_map[opcode_hash];
+ upper_opcode_map[opcode_hash] = &txvu_upper_opcodes[i];
+
+ txvu_upper_opcodes[i].next_dis = upper_icode_map[icode_hash];
+ upper_icode_map[icode_hash] = &txvu_upper_opcodes[i];
+ }
+
+ memset (lower_opcode_map, 0, sizeof (lower_opcode_map));
+ memset (lower_icode_map, 0, sizeof (lower_icode_map));
+
+ /* Scan the table backwards so macros appear at the front. */
+ for (i = txvu_lower_opcodes_count - 1; i >= 0; --i)
+ {
+ int opcode_hash = TXVU_HASH_LOWER_OPCODE (txvu_lower_opcodes[i].mnemonic);
+ int icode_hash = TXVU_HASH_LOWER_ICODE (txvu_lower_opcodes[i].value);
+
+ txvu_lower_opcodes[i].next_asm = lower_opcode_map[opcode_hash];
+ lower_opcode_map[opcode_hash] = &txvu_lower_opcodes[i];
+
+ txvu_lower_opcodes[i].next_dis = lower_icode_map[icode_hash];
+ lower_icode_map[icode_hash] = &txvu_lower_opcodes[i];
+ }
+
+ init_p = 1;
+ }
+}
+
+/* Return the first insn in the chain for assembling upper INSN. */
+
+const struct txvu_opcode *
+txvu_upper_opcode_lookup_asm (insn)
+ const char *insn;
+{
+ return upper_opcode_map[TXVU_HASH_UPPER_OPCODE (insn)];
+}
+
+/* Return the first insn in the chain for assembling lower INSN. */
+
+const struct txvu_opcode *
+txvu_lower_opcode_lookup_asm (insn)
+ const char *insn;
+{
+ return lower_opcode_map[TXVU_HASH_LOWER_OPCODE (insn)];
+}
+
+/* Return the first insn in the chain for disassembling upper INSN. */
+
+const struct txvu_opcode *
+txvu_upper_opcode_lookup_dis (insn)
+ TXVU_INSN insn;
+{
+ return upper_icode_map[TXVU_HASH_UPPER_ICODE (insn)];
+}
+
+/* Return the first insn in the chain for disassembling lower INSN. */
+
+const struct txvu_opcode *
+txvu_lower_opcode_lookup_dis (insn)
+ TXVU_INSN insn;
+{
+ return lower_icode_map[TXVU_HASH_LOWER_ICODE (insn)];
+}
+\f
+/* Value of DEST in use.
+ Each of the registers must specify the same value.
+ ??? Perhaps remove the duplication? */
+static int dest;
+\f
+/* Init fns.
+ These are called before doing each of the respective activities. */
+
+/* Called by the assembler before parsing an instruction. */
+
+void
+txvu_opcode_init_parse ()
+{
+ dest = -1;
+}
+
+/* Called by the disassembler before printing an instruction. */
+
+void
+txvu_opcode_init_print ()
+{
+ dest = -1;
+}
+\f
+/* Destination choice support.
+ The "dest" string selects any combination of x,y,z,w.
+ [The letters are ordered that way to follow the manual's style.] */
+
+static long
+parse_dotdest (pstr, errmsg)
+ char **pstr;
+ const char **errmsg;
+{
+ long dest = 0;
+
+ if (**pstr != '.')
+ {
+ *errmsg = "missing `.'";
+ return 0;
+ }
+
+ ++*pstr;
+ while (**pstr)
+ {
+ switch (**pstr)
+ {
+ case 'x' : case 'X' : dest |= TXVU_DEST_X; break;
+ case 'y' : case 'Y' : dest |= TXVU_DEST_Y; break;
+ case 'z' : case 'Z' : dest |= TXVU_DEST_Z; break;
+ case 'w' : case 'W' : dest |= TXVU_DEST_W; break;
+ default : *errmsg = "unknown dest letter"; return 0;
+ }
+ ++*pstr;
+ }
+
+ *errmsg = NULL;
+ return dest;
+}
+
+static void
+print_dotdest (info, insn, value)
+ disassemble_info *info;
+ TXVU_INSN insn;
+ long value;
+{
+ (*info->fprintf_func) (info->stream, ".");
+ if (value & TXVU_DEST_X)
+ (*info->fprintf_func) (info->stream, "x");
+ if (value & TXVU_DEST_Y)
+ (*info->fprintf_func) (info->stream, "y");
+ if (value & TXVU_DEST_Z)
+ (*info->fprintf_func) (info->stream, "z");
+ if (value & TXVU_DEST_W)
+ (*info->fprintf_func) (info->stream, "w");
+}
+\f
+static long
+parse_reg (pstr, errmsg)
+ char **pstr;
+ const char **errmsg;
+{
+ char *str = *pstr;
+ char *start;
+ long reg;
+
+ if (tolower (str[0]) != 'v'
+ || tolower (str[1]) != 'f')
+ {
+ *errmsg = "unknown register";
+ return 0;
+ }
+
+ /* FIXME: quick hack until the framework works. */
+ start = str = str + 2;
+ while (*str && isdigit (*str))
+ ++str;
+ reg = atoi (start);
+ *pstr = str;
+ *errmsg = NULL;
+ return reg;
+}
+
+static void
+print_reg (info, insn, value)
+ disassemble_info *info;
+ TXVU_INSN insn;
+ long value;
+{
+ (*info->fprintf_func) (info->stream, "vf%ld", value);
+}