* 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.
This commit is contained in:
Doug Evans
1998-01-05 13:46:22 +00:00
parent 70e4ceaccb
commit 54cc8ed4db
8 changed files with 847 additions and 2 deletions

View File

@ -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

View File

@ -1,4 +1,13 @@
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.

268
opcodes/Makefile.am Normal file
View File

@ -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

View File

@ -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

2
opcodes/configure vendored
View File

@ -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

View File

@ -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

191
opcodes/txvu-dis.c Normal file
View File

@ -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*");
}

359
opcodes/txvu-opc.c Normal file
View File

@ -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);
}