From 54cc8ed4db2ff765d53a27b3e08dee68062e74b3 Mon Sep 17 00:00:00 2001 From: Doug Evans Date: Mon, 5 Jan 1998 13:46:22 +0000 Subject: [PATCH] * 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. --- opcodes/.Sanitize | 8 ++ opcodes/ChangeLog | 9 ++ opcodes/Makefile.am | 268 ++++++++++++++++++++++++++++++++++++++ opcodes/Makefile.in | 10 ++ opcodes/configure | 2 +- opcodes/configure.in | 2 +- opcodes/txvu-dis.c | 191 +++++++++++++++++++++++++++ opcodes/txvu-opc.c | 359 +++++++++++++++++++++++++++++++++++++++++++++++++++ 8 files changed, 847 insertions(+), 2 deletions(-) create mode 100644 opcodes/Makefile.am create mode 100644 opcodes/txvu-dis.c create mode 100644 opcodes/txvu-opc.c diff --git a/opcodes/.Sanitize b/opcodes/.Sanitize index d6b7ed8..39ebf43 100644 --- a/opcodes/.Sanitize +++ b/opcodes/.Sanitize @@ -31,6 +31,14 @@ else 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 diff --git a/opcodes/ChangeLog b/opcodes/ChangeLog index c5c4aad..fa423dc 100644 --- a/opcodes/ChangeLog +++ b/opcodes/ChangeLog @@ -1,4 +1,13 @@ start-sanitize-sky +Mon Jan 5 13:41:07 1998 Doug Evans + + * 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 * configure.in: Add txvu support. diff --git a/opcodes/Makefile.am b/opcodes/Makefile.am new file mode 100644 index 0000000..28ba82b --- /dev/null +++ b/opcodes/Makefile.am @@ -0,0 +1,268 @@ +## 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 diff --git a/opcodes/Makefile.in b/opcodes/Makefile.in index 5ae42c3..efe5b51 100644 --- a/opcodes/Makefile.in +++ b/opcodes/Makefile.in @@ -173,6 +173,10 @@ ALL_MACHINES = \ 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 \ @@ -497,6 +501,12 @@ tic80-dis.lo: tic80-dis.c $(INCDIR)/dis-asm.h ../bfd/bfd.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 diff --git a/opcodes/configure b/opcodes/configure index 8e9513d..682f86b 100755 --- a/opcodes/configure +++ b/opcodes/configure @@ -1837,7 +1837,7 @@ if test x${all_targets} = xfalse ; then 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 diff --git a/opcodes/configure.in b/opcodes/configure.in index 8cb9df0..76fcd52 100644 --- a/opcodes/configure.in +++ b/opcodes/configure.in @@ -138,7 +138,7 @@ if test x${all_targets} = xfalse ; then 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 diff --git a/opcodes/txvu-dis.c b/opcodes/txvu-dis.c new file mode 100644 index 0000000..f3649e6 --- /dev/null +++ b/opcodes/txvu-dis.c @@ -0,0 +1,191 @@ +/* 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*"); +} diff --git a/opcodes/txvu-opc.c b/opcodes/txvu-opc.c new file mode 100644 index 0000000..a9d0bec --- /dev/null +++ b/opcodes/txvu-opc.c @@ -0,0 +1,359 @@ +/* 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 } +}; + +/* 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]; + +/* 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)]; +} + +/* Value of DEST in use. + Each of the registers must specify the same value. + ??? Perhaps remove the duplication? */ +static int dest; + +/* 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; +} + +/* 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"); +} + +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); +} -- 2.7.4