forked from Imagelibrary/binutils-gdb
Add IP2k GAS and OPCODES support.
This commit is contained in:
@@ -1,3 +1,21 @@
|
||||
2002-07-18 Denis Chertykov <denisc@overta.ru>
|
||||
Frank Ch. Eigler <fche@redhat.com>
|
||||
Alan Lehotsky <alehotsky@cygnus.com>
|
||||
matthew green <mrg@redhat.com>
|
||||
|
||||
* configure.in: Add support for ip2k.
|
||||
* configure: Regenerate.
|
||||
* Makefile.am: Add support for ip2k.
|
||||
* Makefile.in: Regenerate.
|
||||
* disassemble.c: Add support for ip2k.
|
||||
* ip2k-asm.c: New generated file.
|
||||
* ip2k-desc.c: New generated file.
|
||||
* ip2k-desc.h: New generated file.
|
||||
* ip2k-dis.c: New generated file.
|
||||
* ip2k-ibld.c: New generated file.
|
||||
* ip2k-opc.c: New generated file.
|
||||
* ip2k-opc.h: New generated file.
|
||||
|
||||
2002-07-17 David Mosberger <davidm@hpl.hp.com>
|
||||
|
||||
* ia64-opc-b.c (bWhc): New macro.
|
||||
|
||||
@@ -30,6 +30,7 @@ HFILES = \
|
||||
h8500-opc.h \
|
||||
ia64-asmtab.h \
|
||||
ia64-opc.h \
|
||||
ip2k-desc.h ip2k-opc.h \
|
||||
m32r-desc.h m32r-opc.h \
|
||||
mcore-opc.h \
|
||||
openrisc-desc.h openrisc-opc.h \
|
||||
@@ -90,6 +91,11 @@ CFILES = \
|
||||
ia64-opc.c \
|
||||
ia64-gen.c \
|
||||
ia64-asmtab.c \
|
||||
ip2k-asm.c \
|
||||
ip2k-desc.c \
|
||||
ip2k-dis.c \
|
||||
ip2k-ibld.c \
|
||||
ip2k-opc.c \
|
||||
m32r-asm.c \
|
||||
m32r-desc.c \
|
||||
m32r-dis.c \
|
||||
@@ -189,6 +195,11 @@ ALL_MACHINES = \
|
||||
i960-dis.lo \
|
||||
ia64-dis.lo \
|
||||
ia64-opc.lo \
|
||||
ip2k-asm.lo \
|
||||
ip2k-desc.lo \
|
||||
ip2k-dis.lo \
|
||||
ip2k-ibld.lo \
|
||||
ip2k-opc.lo \
|
||||
m32r-asm.lo \
|
||||
m32r-desc.lo \
|
||||
m32r-dis.lo \
|
||||
@@ -312,7 +323,7 @@ uninstall_libopcodes:
|
||||
rm -f $(DESTDIR)$(bfdincludedir)/dis-asm.h
|
||||
|
||||
CLEANFILES = \
|
||||
stamp-m32r stamp-fr30 stamp-frv stamp-openrisc \
|
||||
stamp-ip2k stamp-m32r stamp-fr30 stamp-frv stamp-openrisc \
|
||||
stamp-xstormy16 \
|
||||
libopcodes.a stamp-lib dep.sed DEP DEPA DEP1 DEP2
|
||||
|
||||
@@ -330,12 +341,14 @@ CGENDEPS = \
|
||||
cgen-asm.in cgen-dis.in cgen-ibld.in
|
||||
|
||||
if CGEN_MAINT
|
||||
IP2K_DEPS = stamp-ip2k
|
||||
M32R_DEPS = stamp-m32r
|
||||
FR30_DEPS = stamp-fr30
|
||||
FRV_DEPS = stamp-frv
|
||||
OPENRISC_DEPS = stamp-openrisc
|
||||
XSTORMY16_DEPS = stamp-xstormy16
|
||||
else
|
||||
IP2K_DEPS =
|
||||
M32R_DEPS =
|
||||
FR30_DEPS =
|
||||
FRV_DEPS =
|
||||
@@ -351,6 +364,11 @@ run-cgen:
|
||||
.PHONY: run-cgen
|
||||
|
||||
# For now, require developers to configure with --enable-cgen-maint.
|
||||
$(srcdir)/ip2k-desc.h $(srcdir)/ip2k-desc.c $(srcdir)/ip2k-opc.h $(srcdir)/ip2k-opc.c $(srcdir)/ip2k-ibld.c $(srcdir)/ip2k-asm.c $(srcdir)/ip2k-dis.c: $(IP2K_DEPS)
|
||||
@true
|
||||
stamp-ip2k: $(CGENDEPS) $(CPUDIR)/ip2k.cpu $(CPUDIR)/ip2k.opc
|
||||
$(MAKE) run-cgen arch=ip2k prefix=ip2k options= extrafiles=
|
||||
|
||||
$(srcdir)/m32r-desc.h $(srcdir)/m32r-desc.c $(srcdir)/m32r-opc.h $(srcdir)/m32r-opc.c $(srcdir)/m32r-ibld.c $(srcdir)/m32r-opinst.c $(srcdir)/m32r-asm.c $(srcdir)/m32r-dis.c: $(M32R_DEPS)
|
||||
@true
|
||||
stamp-m32r: $(CGENDEPS) $(CPUDIR)/m32r.cpu $(CPUDIR)/m32r.opc
|
||||
@@ -572,6 +590,23 @@ ia64-gen.lo: ia64-gen.c $(INCDIR)/ansidecl.h $(INCDIR)/libiberty.h \
|
||||
ia64-opc-a.c ia64-opc-i.c ia64-opc-m.c ia64-opc-b.c \
|
||||
ia64-opc-f.c ia64-opc-x.c ia64-opc-d.c
|
||||
ia64-asmtab.lo: ia64-asmtab.c
|
||||
ip2k-asm.lo: ip2k-asm.c sysdep.h config.h $(BFD_H) \
|
||||
$(INCDIR)/ansidecl.h $(INCDIR)/symcat.h ip2k-desc.h \
|
||||
$(INCDIR)/opcode/cgen.h ip2k-opc.h opintl.h
|
||||
ip2k-desc.lo: ip2k-desc.c sysdep.h config.h $(BFD_H) \
|
||||
$(INCDIR)/ansidecl.h $(INCDIR)/symcat.h ip2k-desc.h \
|
||||
$(INCDIR)/opcode/cgen.h ip2k-opc.h opintl.h
|
||||
ip2k-dis.lo: ip2k-dis.c sysdep.h config.h $(INCDIR)/dis-asm.h \
|
||||
$(BFD_H) $(INCDIR)/ansidecl.h \
|
||||
$(INCDIR)/symcat.h ip2k-desc.h $(INCDIR)/opcode/cgen.h \
|
||||
ip2k-opc.h opintl.h
|
||||
ip2k-ibld.lo: ip2k-ibld.c sysdep.h config.h $(INCDIR)/dis-asm.h \
|
||||
$(BFD_H) $(INCDIR)/ansidecl.h \
|
||||
$(INCDIR)/symcat.h ip2k-desc.h $(INCDIR)/opcode/cgen.h \
|
||||
ip2k-opc.h opintl.h
|
||||
ip2k-opc.lo: ip2k-opc.c sysdep.h config.h $(BFD_H) \
|
||||
$(INCDIR)/ansidecl.h $(INCDIR)/symcat.h ip2k-desc.h \
|
||||
$(INCDIR)/opcode/cgen.h ip2k-opc.h
|
||||
m32r-asm.lo: m32r-asm.c sysdep.h config.h $(INCDIR)/ansidecl.h \
|
||||
$(BFD_H) $(INCDIR)/symcat.h m32r-desc.h $(INCDIR)/opcode/cgen.h \
|
||||
m32r-opc.h opintl.h $(INCDIR)/xregex.h $(INCDIR)/xregex2.h \
|
||||
|
||||
@@ -140,6 +140,7 @@ HFILES = \
|
||||
h8500-opc.h \
|
||||
ia64-asmtab.h \
|
||||
ia64-opc.h \
|
||||
ip2k-desc.h ip2k-opc.h \
|
||||
m32r-desc.h m32r-opc.h \
|
||||
mcore-opc.h \
|
||||
openrisc-desc.h openrisc-opc.h \
|
||||
@@ -201,6 +202,11 @@ CFILES = \
|
||||
ia64-opc.c \
|
||||
ia64-gen.c \
|
||||
ia64-asmtab.c \
|
||||
ip2k-asm.c \
|
||||
ip2k-desc.c \
|
||||
ip2k-dis.c \
|
||||
ip2k-ibld.c \
|
||||
ip2k-opc.c \
|
||||
m32r-asm.c \
|
||||
m32r-desc.c \
|
||||
m32r-dis.c \
|
||||
@@ -301,6 +307,11 @@ ALL_MACHINES = \
|
||||
i960-dis.lo \
|
||||
ia64-dis.lo \
|
||||
ia64-opc.lo \
|
||||
ip2k-asm.lo \
|
||||
ip2k-desc.lo \
|
||||
ip2k-dis.lo \
|
||||
ip2k-ibld.lo \
|
||||
ip2k-opc.lo \
|
||||
m32r-asm.lo \
|
||||
m32r-desc.lo \
|
||||
m32r-dis.lo \
|
||||
@@ -379,7 +390,7 @@ noinst_LIBRARIES = libopcodes.a
|
||||
POTFILES = $(HFILES) $(CFILES)
|
||||
|
||||
CLEANFILES = \
|
||||
stamp-m32r stamp-fr30 stamp-frv stamp-openrisc \
|
||||
stamp-ip2k stamp-m32r stamp-fr30 stamp-frv stamp-openrisc \
|
||||
stamp-xstormy16 \
|
||||
libopcodes.a stamp-lib dep.sed DEP DEPA DEP1 DEP2
|
||||
|
||||
@@ -396,6 +407,8 @@ CGENDEPS = \
|
||||
$(CGENDIR)/opc-opinst.scm \
|
||||
cgen-asm.in cgen-dis.in cgen-ibld.in
|
||||
|
||||
@CGEN_MAINT_TRUE@IP2K_DEPS = @CGEN_MAINT_TRUE@stamp-ip2k
|
||||
@CGEN_MAINT_FALSE@IP2K_DEPS =
|
||||
@CGEN_MAINT_TRUE@M32R_DEPS = @CGEN_MAINT_TRUE@stamp-m32r
|
||||
@CGEN_MAINT_FALSE@M32R_DEPS =
|
||||
@CGEN_MAINT_TRUE@FR30_DEPS = @CGEN_MAINT_TRUE@stamp-fr30
|
||||
@@ -434,7 +447,7 @@ acinclude.m4 aclocal.m4 config.in configure configure.in
|
||||
|
||||
DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
|
||||
|
||||
TAR = tar
|
||||
TAR = gtar
|
||||
GZIP_ENV = --best
|
||||
SOURCES = libopcodes.a.c $(libopcodes_la_SOURCES)
|
||||
OBJECTS = libopcodes.a.$(OBJEXT) $(libopcodes_la_OBJECTS)
|
||||
@@ -847,6 +860,11 @@ run-cgen:
|
||||
.PHONY: run-cgen
|
||||
|
||||
# For now, require developers to configure with --enable-cgen-maint.
|
||||
$(srcdir)/ip2k-desc.h $(srcdir)/ip2k-desc.c $(srcdir)/ip2k-opc.h $(srcdir)/ip2k-opc.c $(srcdir)/ip2k-ibld.c $(srcdir)/ip2k-asm.c $(srcdir)/ip2k-dis.c: $(IP2K_DEPS)
|
||||
@true
|
||||
stamp-ip2k: $(CGENDEPS) $(CPUDIR)/ip2k.cpu $(CPUDIR)/ip2k.opc
|
||||
$(MAKE) run-cgen arch=ip2k prefix=ip2k options= extrafiles=
|
||||
|
||||
$(srcdir)/m32r-desc.h $(srcdir)/m32r-desc.c $(srcdir)/m32r-opc.h $(srcdir)/m32r-opc.c $(srcdir)/m32r-ibld.c $(srcdir)/m32r-opinst.c $(srcdir)/m32r-asm.c $(srcdir)/m32r-dis.c: $(M32R_DEPS)
|
||||
@true
|
||||
stamp-m32r: $(CGENDEPS) $(CPUDIR)/m32r.cpu $(CPUDIR)/m32r.opc
|
||||
@@ -1068,6 +1086,23 @@ ia64-gen.lo: ia64-gen.c $(INCDIR)/ansidecl.h $(INCDIR)/libiberty.h \
|
||||
ia64-opc-a.c ia64-opc-i.c ia64-opc-m.c ia64-opc-b.c \
|
||||
ia64-opc-f.c ia64-opc-x.c ia64-opc-d.c
|
||||
ia64-asmtab.lo: ia64-asmtab.c
|
||||
ip2k-asm.lo: ip2k-asm.c sysdep.h config.h $(BFD_H) \
|
||||
$(INCDIR)/ansidecl.h $(INCDIR)/symcat.h ip2k-desc.h \
|
||||
$(INCDIR)/opcode/cgen.h ip2k-opc.h opintl.h
|
||||
ip2k-desc.lo: ip2k-desc.c sysdep.h config.h $(BFD_H) \
|
||||
$(INCDIR)/ansidecl.h $(INCDIR)/symcat.h ip2k-desc.h \
|
||||
$(INCDIR)/opcode/cgen.h ip2k-opc.h opintl.h
|
||||
ip2k-dis.lo: ip2k-dis.c sysdep.h config.h $(INCDIR)/dis-asm.h \
|
||||
$(BFD_H) $(INCDIR)/ansidecl.h \
|
||||
$(INCDIR)/symcat.h ip2k-desc.h $(INCDIR)/opcode/cgen.h \
|
||||
ip2k-opc.h opintl.h
|
||||
ip2k-ibld.lo: ip2k-ibld.c sysdep.h config.h $(INCDIR)/dis-asm.h \
|
||||
$(BFD_H) $(INCDIR)/ansidecl.h \
|
||||
$(INCDIR)/symcat.h ip2k-desc.h $(INCDIR)/opcode/cgen.h \
|
||||
ip2k-opc.h opintl.h
|
||||
ip2k-opc.lo: ip2k-opc.c sysdep.h config.h $(BFD_H) \
|
||||
$(INCDIR)/ansidecl.h $(INCDIR)/symcat.h ip2k-desc.h \
|
||||
$(INCDIR)/opcode/cgen.h ip2k-opc.h
|
||||
m32r-asm.lo: m32r-asm.c sysdep.h config.h $(INCDIR)/ansidecl.h \
|
||||
$(BFD_H) $(INCDIR)/symcat.h m32r-desc.h $(INCDIR)/opcode/cgen.h \
|
||||
m32r-opc.h opintl.h $(INCDIR)/xregex.h $(INCDIR)/xregex2.h \
|
||||
|
||||
116
opcodes/configure
vendored
116
opcodes/configure
vendored
@@ -3255,7 +3255,7 @@ EOF
|
||||
|
||||
fi
|
||||
|
||||
for ac_hdr in unistd.h
|
||||
for ac_hdr in stdlib.h unistd.h sys/stat.h sys/types.h
|
||||
do
|
||||
ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
|
||||
echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
|
||||
@@ -3387,11 +3387,24 @@ else
|
||||
#include <fcntl.h>
|
||||
#include <sys/mman.h>
|
||||
|
||||
#if HAVE_SYS_TYPES_H
|
||||
# include <sys/types.h>
|
||||
#endif
|
||||
|
||||
#if HAVE_STDLIB_H
|
||||
# include <stdlib.h>
|
||||
#endif
|
||||
|
||||
#if HAVE_SYS_STAT_H
|
||||
# include <sys/stat.h>
|
||||
#endif
|
||||
|
||||
#if HAVE_UNISTD_H
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
|
||||
/* This mess was copied from the GNU getpagesize.h. */
|
||||
#ifndef HAVE_GETPAGESIZE
|
||||
# ifdef HAVE_UNISTD_H
|
||||
# include <unistd.h>
|
||||
# endif
|
||||
|
||||
/* Assume that all systems that can run configure have sys/param.h. */
|
||||
# ifndef HAVE_SYS_PARAM_H
|
||||
@@ -3499,7 +3512,7 @@ main()
|
||||
}
|
||||
|
||||
EOF
|
||||
if { (eval echo configure:3503: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
|
||||
if { (eval echo configure:3516: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
|
||||
then
|
||||
ac_cv_func_mmap_fixed_mapped=yes
|
||||
else
|
||||
@@ -3527,17 +3540,17 @@ unistd.h values.h sys/param.h
|
||||
do
|
||||
ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
|
||||
echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
|
||||
echo "configure:3531: checking for $ac_hdr" >&5
|
||||
echo "configure:3544: checking for $ac_hdr" >&5
|
||||
if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
|
||||
echo $ac_n "(cached) $ac_c" 1>&6
|
||||
else
|
||||
cat > conftest.$ac_ext <<EOF
|
||||
#line 3536 "configure"
|
||||
#line 3549 "configure"
|
||||
#include "confdefs.h"
|
||||
#include <$ac_hdr>
|
||||
EOF
|
||||
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
|
||||
{ (eval echo configure:3541: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
|
||||
{ (eval echo configure:3554: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
|
||||
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
|
||||
if test -z "$ac_err"; then
|
||||
rm -rf conftest*
|
||||
@@ -3567,12 +3580,12 @@ done
|
||||
__argz_count __argz_stringify __argz_next
|
||||
do
|
||||
echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
|
||||
echo "configure:3571: checking for $ac_func" >&5
|
||||
echo "configure:3584: checking for $ac_func" >&5
|
||||
if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
|
||||
echo $ac_n "(cached) $ac_c" 1>&6
|
||||
else
|
||||
cat > conftest.$ac_ext <<EOF
|
||||
#line 3576 "configure"
|
||||
#line 3589 "configure"
|
||||
#include "confdefs.h"
|
||||
/* System header to define __stub macros and hopefully few prototypes,
|
||||
which can conflict with char $ac_func(); below. */
|
||||
@@ -3595,7 +3608,7 @@ $ac_func();
|
||||
|
||||
; return 0; }
|
||||
EOF
|
||||
if { (eval echo configure:3599: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
|
||||
if { (eval echo configure:3612: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
|
||||
rm -rf conftest*
|
||||
eval "ac_cv_func_$ac_func=yes"
|
||||
else
|
||||
@@ -3624,12 +3637,12 @@ done
|
||||
for ac_func in stpcpy
|
||||
do
|
||||
echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
|
||||
echo "configure:3628: checking for $ac_func" >&5
|
||||
echo "configure:3641: checking for $ac_func" >&5
|
||||
if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
|
||||
echo $ac_n "(cached) $ac_c" 1>&6
|
||||
else
|
||||
cat > conftest.$ac_ext <<EOF
|
||||
#line 3633 "configure"
|
||||
#line 3646 "configure"
|
||||
#include "confdefs.h"
|
||||
/* System header to define __stub macros and hopefully few prototypes,
|
||||
which can conflict with char $ac_func(); below. */
|
||||
@@ -3652,7 +3665,7 @@ $ac_func();
|
||||
|
||||
; return 0; }
|
||||
EOF
|
||||
if { (eval echo configure:3656: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
|
||||
if { (eval echo configure:3669: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
|
||||
rm -rf conftest*
|
||||
eval "ac_cv_func_$ac_func=yes"
|
||||
else
|
||||
@@ -3686,19 +3699,19 @@ EOF
|
||||
|
||||
if test $ac_cv_header_locale_h = yes; then
|
||||
echo $ac_n "checking for LC_MESSAGES""... $ac_c" 1>&6
|
||||
echo "configure:3690: checking for LC_MESSAGES" >&5
|
||||
echo "configure:3703: checking for LC_MESSAGES" >&5
|
||||
if eval "test \"`echo '$''{'am_cv_val_LC_MESSAGES'+set}'`\" = set"; then
|
||||
echo $ac_n "(cached) $ac_c" 1>&6
|
||||
else
|
||||
cat > conftest.$ac_ext <<EOF
|
||||
#line 3695 "configure"
|
||||
#line 3708 "configure"
|
||||
#include "confdefs.h"
|
||||
#include <locale.h>
|
||||
int main() {
|
||||
return LC_MESSAGES
|
||||
; return 0; }
|
||||
EOF
|
||||
if { (eval echo configure:3702: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
|
||||
if { (eval echo configure:3715: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
|
||||
rm -rf conftest*
|
||||
am_cv_val_LC_MESSAGES=yes
|
||||
else
|
||||
@@ -3719,7 +3732,7 @@ EOF
|
||||
fi
|
||||
fi
|
||||
echo $ac_n "checking whether NLS is requested""... $ac_c" 1>&6
|
||||
echo "configure:3723: checking whether NLS is requested" >&5
|
||||
echo "configure:3736: checking whether NLS is requested" >&5
|
||||
# Check whether --enable-nls or --disable-nls was given.
|
||||
if test "${enable_nls+set}" = set; then
|
||||
enableval="$enable_nls"
|
||||
@@ -3739,7 +3752,7 @@ fi
|
||||
EOF
|
||||
|
||||
echo $ac_n "checking whether included gettext is requested""... $ac_c" 1>&6
|
||||
echo "configure:3743: checking whether included gettext is requested" >&5
|
||||
echo "configure:3756: checking whether included gettext is requested" >&5
|
||||
# Check whether --with-included-gettext or --without-included-gettext was given.
|
||||
if test "${with_included_gettext+set}" = set; then
|
||||
withval="$with_included_gettext"
|
||||
@@ -3758,17 +3771,17 @@ fi
|
||||
|
||||
ac_safe=`echo "libintl.h" | sed 'y%./+-%__p_%'`
|
||||
echo $ac_n "checking for libintl.h""... $ac_c" 1>&6
|
||||
echo "configure:3762: checking for libintl.h" >&5
|
||||
echo "configure:3775: checking for libintl.h" >&5
|
||||
if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
|
||||
echo $ac_n "(cached) $ac_c" 1>&6
|
||||
else
|
||||
cat > conftest.$ac_ext <<EOF
|
||||
#line 3767 "configure"
|
||||
#line 3780 "configure"
|
||||
#include "confdefs.h"
|
||||
#include <libintl.h>
|
||||
EOF
|
||||
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
|
||||
{ (eval echo configure:3772: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
|
||||
{ (eval echo configure:3785: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
|
||||
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
|
||||
if test -z "$ac_err"; then
|
||||
rm -rf conftest*
|
||||
@@ -3785,19 +3798,19 @@ fi
|
||||
if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
|
||||
echo "$ac_t""yes" 1>&6
|
||||
echo $ac_n "checking for gettext in libc""... $ac_c" 1>&6
|
||||
echo "configure:3789: checking for gettext in libc" >&5
|
||||
echo "configure:3802: checking for gettext in libc" >&5
|
||||
if eval "test \"`echo '$''{'gt_cv_func_gettext_libc'+set}'`\" = set"; then
|
||||
echo $ac_n "(cached) $ac_c" 1>&6
|
||||
else
|
||||
cat > conftest.$ac_ext <<EOF
|
||||
#line 3794 "configure"
|
||||
#line 3807 "configure"
|
||||
#include "confdefs.h"
|
||||
#include <libintl.h>
|
||||
int main() {
|
||||
return (int) gettext ("")
|
||||
; return 0; }
|
||||
EOF
|
||||
if { (eval echo configure:3801: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
|
||||
if { (eval echo configure:3814: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
|
||||
rm -rf conftest*
|
||||
gt_cv_func_gettext_libc=yes
|
||||
else
|
||||
@@ -3813,7 +3826,7 @@ echo "$ac_t""$gt_cv_func_gettext_libc" 1>&6
|
||||
|
||||
if test "$gt_cv_func_gettext_libc" != "yes"; then
|
||||
echo $ac_n "checking for bindtextdomain in -lintl""... $ac_c" 1>&6
|
||||
echo "configure:3817: checking for bindtextdomain in -lintl" >&5
|
||||
echo "configure:3830: checking for bindtextdomain in -lintl" >&5
|
||||
ac_lib_var=`echo intl'_'bindtextdomain | sed 'y%./+-%__p_%'`
|
||||
if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
|
||||
echo $ac_n "(cached) $ac_c" 1>&6
|
||||
@@ -3821,7 +3834,7 @@ else
|
||||
ac_save_LIBS="$LIBS"
|
||||
LIBS="-lintl $LIBS"
|
||||
cat > conftest.$ac_ext <<EOF
|
||||
#line 3825 "configure"
|
||||
#line 3838 "configure"
|
||||
#include "confdefs.h"
|
||||
/* Override any gcc2 internal prototype to avoid an error. */
|
||||
/* We use char because int might match the return type of a gcc2
|
||||
@@ -3832,7 +3845,7 @@ int main() {
|
||||
bindtextdomain()
|
||||
; return 0; }
|
||||
EOF
|
||||
if { (eval echo configure:3836: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
|
||||
if { (eval echo configure:3849: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
|
||||
rm -rf conftest*
|
||||
eval "ac_cv_lib_$ac_lib_var=yes"
|
||||
else
|
||||
@@ -3848,19 +3861,19 @@ fi
|
||||
if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
|
||||
echo "$ac_t""yes" 1>&6
|
||||
echo $ac_n "checking for gettext in libintl""... $ac_c" 1>&6
|
||||
echo "configure:3852: checking for gettext in libintl" >&5
|
||||
echo "configure:3865: checking for gettext in libintl" >&5
|
||||
if eval "test \"`echo '$''{'gt_cv_func_gettext_libintl'+set}'`\" = set"; then
|
||||
echo $ac_n "(cached) $ac_c" 1>&6
|
||||
else
|
||||
cat > conftest.$ac_ext <<EOF
|
||||
#line 3857 "configure"
|
||||
#line 3870 "configure"
|
||||
#include "confdefs.h"
|
||||
|
||||
int main() {
|
||||
return (int) gettext ("")
|
||||
; return 0; }
|
||||
EOF
|
||||
if { (eval echo configure:3864: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
|
||||
if { (eval echo configure:3877: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
|
||||
rm -rf conftest*
|
||||
gt_cv_func_gettext_libintl=yes
|
||||
else
|
||||
@@ -3888,7 +3901,7 @@ EOF
|
||||
# Extract the first word of "msgfmt", so it can be a program name with args.
|
||||
set dummy msgfmt; ac_word=$2
|
||||
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
|
||||
echo "configure:3892: checking for $ac_word" >&5
|
||||
echo "configure:3905: checking for $ac_word" >&5
|
||||
if eval "test \"`echo '$''{'ac_cv_path_MSGFMT'+set}'`\" = set"; then
|
||||
echo $ac_n "(cached) $ac_c" 1>&6
|
||||
else
|
||||
@@ -3922,12 +3935,12 @@ fi
|
||||
for ac_func in dcgettext
|
||||
do
|
||||
echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
|
||||
echo "configure:3926: checking for $ac_func" >&5
|
||||
echo "configure:3939: checking for $ac_func" >&5
|
||||
if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
|
||||
echo $ac_n "(cached) $ac_c" 1>&6
|
||||
else
|
||||
cat > conftest.$ac_ext <<EOF
|
||||
#line 3931 "configure"
|
||||
#line 3944 "configure"
|
||||
#include "confdefs.h"
|
||||
/* System header to define __stub macros and hopefully few prototypes,
|
||||
which can conflict with char $ac_func(); below. */
|
||||
@@ -3950,7 +3963,7 @@ $ac_func();
|
||||
|
||||
; return 0; }
|
||||
EOF
|
||||
if { (eval echo configure:3954: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
|
||||
if { (eval echo configure:3967: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
|
||||
rm -rf conftest*
|
||||
eval "ac_cv_func_$ac_func=yes"
|
||||
else
|
||||
@@ -3977,7 +3990,7 @@ done
|
||||
# Extract the first word of "gmsgfmt", so it can be a program name with args.
|
||||
set dummy gmsgfmt; ac_word=$2
|
||||
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
|
||||
echo "configure:3981: checking for $ac_word" >&5
|
||||
echo "configure:3994: checking for $ac_word" >&5
|
||||
if eval "test \"`echo '$''{'ac_cv_path_GMSGFMT'+set}'`\" = set"; then
|
||||
echo $ac_n "(cached) $ac_c" 1>&6
|
||||
else
|
||||
@@ -4013,7 +4026,7 @@ fi
|
||||
# Extract the first word of "xgettext", so it can be a program name with args.
|
||||
set dummy xgettext; ac_word=$2
|
||||
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
|
||||
echo "configure:4017: checking for $ac_word" >&5
|
||||
echo "configure:4030: checking for $ac_word" >&5
|
||||
if eval "test \"`echo '$''{'ac_cv_path_XGETTEXT'+set}'`\" = set"; then
|
||||
echo $ac_n "(cached) $ac_c" 1>&6
|
||||
else
|
||||
@@ -4045,7 +4058,7 @@ else
|
||||
fi
|
||||
|
||||
cat > conftest.$ac_ext <<EOF
|
||||
#line 4049 "configure"
|
||||
#line 4062 "configure"
|
||||
#include "confdefs.h"
|
||||
|
||||
int main() {
|
||||
@@ -4053,7 +4066,7 @@ extern int _nl_msg_cat_cntr;
|
||||
return _nl_msg_cat_cntr
|
||||
; return 0; }
|
||||
EOF
|
||||
if { (eval echo configure:4057: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
|
||||
if { (eval echo configure:4070: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
|
||||
rm -rf conftest*
|
||||
CATOBJEXT=.gmo
|
||||
DATADIRNAME=share
|
||||
@@ -4085,7 +4098,7 @@ fi
|
||||
# Extract the first word of "msgfmt", so it can be a program name with args.
|
||||
set dummy msgfmt; ac_word=$2
|
||||
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
|
||||
echo "configure:4089: checking for $ac_word" >&5
|
||||
echo "configure:4102: checking for $ac_word" >&5
|
||||
if eval "test \"`echo '$''{'ac_cv_path_MSGFMT'+set}'`\" = set"; then
|
||||
echo $ac_n "(cached) $ac_c" 1>&6
|
||||
else
|
||||
@@ -4119,7 +4132,7 @@ fi
|
||||
# Extract the first word of "gmsgfmt", so it can be a program name with args.
|
||||
set dummy gmsgfmt; ac_word=$2
|
||||
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
|
||||
echo "configure:4123: checking for $ac_word" >&5
|
||||
echo "configure:4136: checking for $ac_word" >&5
|
||||
if eval "test \"`echo '$''{'ac_cv_path_GMSGFMT'+set}'`\" = set"; then
|
||||
echo $ac_n "(cached) $ac_c" 1>&6
|
||||
else
|
||||
@@ -4155,7 +4168,7 @@ fi
|
||||
# Extract the first word of "xgettext", so it can be a program name with args.
|
||||
set dummy xgettext; ac_word=$2
|
||||
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
|
||||
echo "configure:4159: checking for $ac_word" >&5
|
||||
echo "configure:4172: checking for $ac_word" >&5
|
||||
if eval "test \"`echo '$''{'ac_cv_path_XGETTEXT'+set}'`\" = set"; then
|
||||
echo $ac_n "(cached) $ac_c" 1>&6
|
||||
else
|
||||
@@ -4245,7 +4258,7 @@ fi
|
||||
LINGUAS=
|
||||
else
|
||||
echo $ac_n "checking for catalogs to be installed""... $ac_c" 1>&6
|
||||
echo "configure:4249: checking for catalogs to be installed" >&5
|
||||
echo "configure:4262: checking for catalogs to be installed" >&5
|
||||
NEW_LINGUAS=
|
||||
for lang in ${LINGUAS=$ALL_LINGUAS}; do
|
||||
case "$ALL_LINGUAS" in
|
||||
@@ -4273,17 +4286,17 @@ echo "configure:4249: checking for catalogs to be installed" >&5
|
||||
if test "$CATOBJEXT" = ".cat"; then
|
||||
ac_safe=`echo "linux/version.h" | sed 'y%./+-%__p_%'`
|
||||
echo $ac_n "checking for linux/version.h""... $ac_c" 1>&6
|
||||
echo "configure:4277: checking for linux/version.h" >&5
|
||||
echo "configure:4290: checking for linux/version.h" >&5
|
||||
if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
|
||||
echo $ac_n "(cached) $ac_c" 1>&6
|
||||
else
|
||||
cat > conftest.$ac_ext <<EOF
|
||||
#line 4282 "configure"
|
||||
#line 4295 "configure"
|
||||
#include "confdefs.h"
|
||||
#include <linux/version.h>
|
||||
EOF
|
||||
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
|
||||
{ (eval echo configure:4287: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
|
||||
{ (eval echo configure:4300: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
|
||||
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
|
||||
if test -z "$ac_err"; then
|
||||
rm -rf conftest*
|
||||
@@ -4361,7 +4374,7 @@ if test "x$cross_compiling" = "xno"; then
|
||||
EXEEXT_FOR_BUILD='$(EXEEXT)'
|
||||
else
|
||||
echo $ac_n "checking for build system executable suffix""... $ac_c" 1>&6
|
||||
echo "configure:4365: checking for build system executable suffix" >&5
|
||||
echo "configure:4378: checking for build system executable suffix" >&5
|
||||
if eval "test \"`echo '$''{'bfd_cv_build_exeext'+set}'`\" = set"; then
|
||||
echo $ac_n "(cached) $ac_c" 1>&6
|
||||
else
|
||||
@@ -4398,7 +4411,7 @@ fi
|
||||
# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
|
||||
# ./install, which can be erroneously created by make from ./install.sh.
|
||||
echo $ac_n "checking for a BSD compatible install""... $ac_c" 1>&6
|
||||
echo "configure:4402: checking for a BSD compatible install" >&5
|
||||
echo "configure:4415: checking for a BSD compatible install" >&5
|
||||
if test -z "$INSTALL"; then
|
||||
if eval "test \"`echo '$''{'ac_cv_path_install'+set}'`\" = set"; then
|
||||
echo $ac_n "(cached) $ac_c" 1>&6
|
||||
@@ -4455,17 +4468,17 @@ for ac_hdr in string.h strings.h stdlib.h
|
||||
do
|
||||
ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
|
||||
echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
|
||||
echo "configure:4459: checking for $ac_hdr" >&5
|
||||
echo "configure:4472: checking for $ac_hdr" >&5
|
||||
if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
|
||||
echo $ac_n "(cached) $ac_c" 1>&6
|
||||
else
|
||||
cat > conftest.$ac_ext <<EOF
|
||||
#line 4464 "configure"
|
||||
#line 4477 "configure"
|
||||
#include "confdefs.h"
|
||||
#include <$ac_hdr>
|
||||
EOF
|
||||
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
|
||||
{ (eval echo configure:4469: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
|
||||
{ (eval echo configure:4482: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
|
||||
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
|
||||
if test -z "$ac_err"; then
|
||||
rm -rf conftest*
|
||||
@@ -4601,6 +4614,7 @@ if test x${all_targets} = xfalse ; then
|
||||
bfd_i860_arch) ta="$ta i860-dis.lo" ;;
|
||||
bfd_i960_arch) ta="$ta i960-dis.lo" ;;
|
||||
bfd_ia64_arch) ta="$ta ia64-dis.lo ia64-opc.lo" ;;
|
||||
bfd_ip2k_arch) ta="$ta ip2k-asm.lo ip2k-desc.lo ip2k-dis.lo ip2k-ibld.lo ip2k-opc.lo" using_cgen=yes ;;
|
||||
bfd_m32r_arch) ta="$ta m32r-asm.lo m32r-desc.lo m32r-dis.lo m32r-ibld.lo m32r-opc.lo m32r-opinst.lo" using_cgen=yes ;;
|
||||
bfd_m68hc11_arch) ta="$ta m68hc11-dis.lo m68hc11-opc.lo" ;;
|
||||
bfd_m68hc12_arch) ta="$ta m68hc11-dis.lo m68hc11-opc.lo" ;;
|
||||
|
||||
@@ -189,6 +189,7 @@ if test x${all_targets} = xfalse ; then
|
||||
bfd_i860_arch) ta="$ta i860-dis.lo" ;;
|
||||
bfd_i960_arch) ta="$ta i960-dis.lo" ;;
|
||||
bfd_ia64_arch) ta="$ta ia64-dis.lo ia64-opc.lo" ;;
|
||||
bfd_ip2k_arch) ta="$ta ip2k-asm.lo ip2k-desc.lo ip2k-dis.lo ip2k-ibld.lo ip2k-opc.lo" using_cgen=yes ;;
|
||||
bfd_m32r_arch) ta="$ta m32r-asm.lo m32r-desc.lo m32r-dis.lo m32r-ibld.lo m32r-opc.lo m32r-opinst.lo" using_cgen=yes ;;
|
||||
bfd_m68hc11_arch) ta="$ta m68hc11-dis.lo m68hc11-opc.lo" ;;
|
||||
bfd_m68hc12_arch) ta="$ta m68hc11-dis.lo m68hc11-opc.lo" ;;
|
||||
|
||||
@@ -36,6 +36,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
#define ARCH_i386
|
||||
#define ARCH_i860
|
||||
#define ARCH_i960
|
||||
#define ARCH_ip2k
|
||||
#define ARCH_ia64
|
||||
#define ARCH_fr30
|
||||
#define ARCH_m32r
|
||||
@@ -179,6 +180,11 @@ disassembler (abfd)
|
||||
disassemble = print_insn_ia64;
|
||||
break;
|
||||
#endif
|
||||
#ifdef ARCH_ip2k
|
||||
case bfd_arch_ip2k:
|
||||
disassemble = print_insn_ip2k;
|
||||
break;
|
||||
#endif
|
||||
#ifdef ARCH_fr30
|
||||
case bfd_arch_fr30:
|
||||
disassemble = print_insn_fr30;
|
||||
|
||||
977
opcodes/ip2k-asm.c
Normal file
977
opcodes/ip2k-asm.c
Normal file
@@ -0,0 +1,977 @@
|
||||
/* Assembler interface for targets using CGEN. -*- C -*-
|
||||
CGEN: Cpu tools GENerator
|
||||
|
||||
THIS FILE IS MACHINE GENERATED WITH CGEN.
|
||||
- the resultant file is machine generated, cgen-asm.in isn't
|
||||
|
||||
Copyright 1996, 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of the GNU Binutils and GDB, the GNU debugger.
|
||||
|
||||
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. */
|
||||
|
||||
/* ??? Eventually more and more of this stuff can go to cpu-independent files.
|
||||
Keep that in mind. */
|
||||
|
||||
#include "sysdep.h"
|
||||
#include <stdio.h>
|
||||
#include "ansidecl.h"
|
||||
#include "bfd.h"
|
||||
#include "symcat.h"
|
||||
#include "ip2k-desc.h"
|
||||
#include "ip2k-opc.h"
|
||||
#include "opintl.h"
|
||||
#include "xregex.h"
|
||||
#include "libiberty.h"
|
||||
#include "safe-ctype.h"
|
||||
|
||||
#undef min
|
||||
#define min(a,b) ((a) < (b) ? (a) : (b))
|
||||
#undef max
|
||||
#define max(a,b) ((a) > (b) ? (a) : (b))
|
||||
|
||||
static const char * parse_insn_normal
|
||||
PARAMS ((CGEN_CPU_DESC, const CGEN_INSN *, const char **, CGEN_FIELDS *));
|
||||
|
||||
/* -- assembler routines inserted here. */
|
||||
|
||||
/* -- asm.c */
|
||||
|
||||
static const char *
|
||||
parse_fr (cd, strp, opindex, valuep)
|
||||
CGEN_CPU_DESC cd;
|
||||
const char **strp;
|
||||
int opindex;
|
||||
long *valuep;
|
||||
{
|
||||
const char *errmsg;
|
||||
char *old_strp;
|
||||
char *afteroffset;
|
||||
enum cgen_parse_operand_result result_type;
|
||||
bfd_vma value;
|
||||
extern CGEN_KEYWORD ip2k_cgen_opval_register_names;
|
||||
long tempvalue;
|
||||
|
||||
old_strp = *strp;
|
||||
afteroffset = NULL;
|
||||
|
||||
|
||||
/* Check here to see if you're about to try parsing a w as the first arg */
|
||||
/* and return an error if you are. */
|
||||
if ( (strncmp(*strp,"w",1)==0) || (strncmp(*strp,"W",1)==0) )
|
||||
{
|
||||
(*strp)++;
|
||||
|
||||
if ( (strncmp(*strp,",",1)==0) || isspace(**strp) )
|
||||
{
|
||||
/* We've been passed a w. Return with an error message so that */
|
||||
/* cgen will try the next parsing option. */
|
||||
errmsg = _("W keyword invalid in FR operand slot.");
|
||||
return errmsg;
|
||||
}
|
||||
*strp = old_strp;
|
||||
}
|
||||
|
||||
|
||||
/* Attempt parse as register keyword. */
|
||||
/* old_strp = *strp; */
|
||||
|
||||
errmsg = cgen_parse_keyword (cd, strp, & ip2k_cgen_opval_register_names, valuep);
|
||||
if ( *strp != NULL )
|
||||
if (errmsg == NULL)
|
||||
return errmsg;
|
||||
|
||||
/* Attempt to parse for "(IP)" */
|
||||
afteroffset = strstr(*strp,"(IP)");
|
||||
|
||||
if ( afteroffset == NULL)
|
||||
{
|
||||
/* Make sure it's not in lower case */
|
||||
afteroffset = strstr(*strp,"(ip)");
|
||||
}
|
||||
|
||||
if ( afteroffset != NULL )
|
||||
{
|
||||
if ( afteroffset != *strp )
|
||||
{
|
||||
/* Invalid offset present.*/
|
||||
errmsg = _("offset(IP) is not a valid form");
|
||||
return errmsg;
|
||||
}
|
||||
else
|
||||
{
|
||||
*strp += 4;
|
||||
*valuep = 0;
|
||||
errmsg = NULL;
|
||||
return errmsg;
|
||||
}
|
||||
}
|
||||
|
||||
/* Attempt to parse for DP. ex: mov w, offset(DP) */
|
||||
/* mov offset(DP),w */
|
||||
|
||||
/* Try parsing it as an address and see what comes back */
|
||||
|
||||
afteroffset = strstr(*strp,"(DP)");
|
||||
|
||||
if ( afteroffset == NULL)
|
||||
{
|
||||
/* Maybe it's in lower case */
|
||||
afteroffset = strstr(*strp,"(dp)");
|
||||
}
|
||||
|
||||
if ( afteroffset != NULL )
|
||||
{
|
||||
if ( afteroffset == *strp )
|
||||
{
|
||||
/* No offset present. Use 0 by default. */
|
||||
tempvalue = 0;
|
||||
errmsg = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_IP2K_FR_OFFSET,
|
||||
& result_type, & tempvalue);
|
||||
}
|
||||
|
||||
if (errmsg == NULL)
|
||||
{
|
||||
if ( (tempvalue >= 0) && (tempvalue <= 127) )
|
||||
{
|
||||
/* Value is ok. Fix up the first 2 bits and return */
|
||||
*valuep = 0x0100 | tempvalue;
|
||||
*strp += 4; /* skip over the (DP) in *strp */
|
||||
return errmsg;
|
||||
} else
|
||||
{
|
||||
/* Found something there in front of (DP) but it's out of range. */
|
||||
errmsg = _("(DP) offset out of range.");
|
||||
return errmsg;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Attempt to parse for SP. ex: mov w, offset(SP) */
|
||||
/* mov offset(SP), w */
|
||||
|
||||
|
||||
afteroffset = strstr(*strp,"(SP)");
|
||||
|
||||
if (afteroffset == NULL)
|
||||
{
|
||||
/* Maybe it's in lower case. */
|
||||
afteroffset = strstr(*strp, "(sp)");
|
||||
}
|
||||
|
||||
if ( afteroffset != NULL )
|
||||
{
|
||||
if ( afteroffset == *strp )
|
||||
{
|
||||
/* No offset present. Use 0 by default. */
|
||||
tempvalue = 0;
|
||||
errmsg = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_IP2K_FR_OFFSET,
|
||||
& result_type, & tempvalue);
|
||||
}
|
||||
if (errmsg == NULL)
|
||||
{
|
||||
if ( (tempvalue >= 0) && (tempvalue <= 127) )
|
||||
{
|
||||
/* Value is ok. Fix up the first 2 bits and return */
|
||||
*valuep = 0x0180 | tempvalue;
|
||||
*strp += 4; /* skip over the (SP) in *strp */
|
||||
return errmsg;
|
||||
} else
|
||||
{
|
||||
/* Found something there in front of (SP) but it's out of range. */
|
||||
errmsg = _("(SP) offset out of range.");
|
||||
return errmsg;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Attempt to parse as an address. */
|
||||
*strp = old_strp;
|
||||
errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_IP2K_FR9,
|
||||
& result_type, & value);
|
||||
if (errmsg == NULL)
|
||||
{
|
||||
*valuep = value;
|
||||
|
||||
/* if a parenthesis is found, warn about invalid form */
|
||||
|
||||
if (**strp == '(')
|
||||
{
|
||||
errmsg = _("illegal use of parentheses");
|
||||
}
|
||||
/* if a numeric value is specified, ensure that it is between 1 and 255 */
|
||||
else if (result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
|
||||
{
|
||||
if (value < 0x1 || value > 0xff)
|
||||
errmsg = _("operand out of range (not between 1 and 255)");
|
||||
}
|
||||
}
|
||||
return errmsg;
|
||||
}
|
||||
|
||||
static const char *
|
||||
parse_addr16 (cd, strp, opindex, valuep)
|
||||
CGEN_CPU_DESC cd;
|
||||
const char **strp;
|
||||
int opindex;
|
||||
long *valuep;
|
||||
{
|
||||
const char *errmsg;
|
||||
enum cgen_parse_operand_result result_type;
|
||||
bfd_reloc_code_real_type code = BFD_RELOC_NONE;
|
||||
long value;
|
||||
|
||||
if ( opindex == (CGEN_OPERAND_TYPE)IP2K_OPERAND_ADDR16H )
|
||||
code = BFD_RELOC_IP2K_HI8DATA;
|
||||
else if ( opindex == (CGEN_OPERAND_TYPE)IP2K_OPERAND_ADDR16L )
|
||||
code = BFD_RELOC_IP2K_LO8DATA;
|
||||
else
|
||||
{
|
||||
/* Something is very wrong. opindex has to be one of the above. */
|
||||
errmsg = _("parse_addr16: invalid opindex.");
|
||||
return errmsg;
|
||||
}
|
||||
|
||||
errmsg = cgen_parse_address (cd, strp, opindex, code,
|
||||
& result_type, & value);
|
||||
if (errmsg == NULL)
|
||||
{
|
||||
/* We either have a relocation or a number now. */
|
||||
if ( result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER )
|
||||
{
|
||||
/* We got a number back. */
|
||||
if ( code == BFD_RELOC_IP2K_HI8DATA )
|
||||
value >>= 8;
|
||||
else /* code = BFD_RELOC_IP2K_LOW8DATA */
|
||||
value &= 0x00FF;
|
||||
}
|
||||
*valuep = value;
|
||||
}
|
||||
|
||||
return errmsg;
|
||||
}
|
||||
|
||||
|
||||
static const char *
|
||||
parse_addr16_p (cd, strp, opindex, valuep)
|
||||
CGEN_CPU_DESC cd;
|
||||
const char **strp;
|
||||
int opindex;
|
||||
long *valuep;
|
||||
{
|
||||
const char *errmsg;
|
||||
enum cgen_parse_operand_result result_type;
|
||||
bfd_reloc_code_real_type code = BFD_RELOC_IP2K_PAGE3;
|
||||
long value;
|
||||
|
||||
errmsg = cgen_parse_address (cd, strp, opindex, code,
|
||||
& result_type, & value);
|
||||
if (errmsg == NULL)
|
||||
{
|
||||
if ( result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER )
|
||||
*valuep = (value >> 13) & 0x7;
|
||||
else if ( result_type == CGEN_PARSE_OPERAND_RESULT_QUEUED )
|
||||
*valuep = value;
|
||||
}
|
||||
return errmsg;
|
||||
}
|
||||
|
||||
|
||||
static const char *
|
||||
parse_addr16_cjp (cd, strp, opindex, valuep)
|
||||
CGEN_CPU_DESC cd;
|
||||
const char **strp;
|
||||
int opindex;
|
||||
long *valuep;
|
||||
{
|
||||
const char *errmsg;
|
||||
enum cgen_parse_operand_result result_type;
|
||||
bfd_reloc_code_real_type code = BFD_RELOC_NONE;
|
||||
long value;
|
||||
|
||||
if ( opindex == (CGEN_OPERAND_TYPE)IP2K_OPERAND_ADDR16CJP )
|
||||
code = BFD_RELOC_IP2K_ADDR16CJP;
|
||||
else if ( opindex == (CGEN_OPERAND_TYPE)IP2K_OPERAND_ADDR16P )
|
||||
code = BFD_RELOC_IP2K_PAGE3;
|
||||
|
||||
errmsg = cgen_parse_address (cd, strp, opindex, code,
|
||||
& result_type, & value);
|
||||
if (errmsg == NULL)
|
||||
{
|
||||
if ( result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER )
|
||||
{
|
||||
if ( (value & 0x1) == 0) /* If the address is even .... */
|
||||
{
|
||||
if ( opindex == (CGEN_OPERAND_TYPE)IP2K_OPERAND_ADDR16CJP )
|
||||
*valuep = (value >> 1) & 0x1FFF; /* Should mask be 1FFF? */
|
||||
else if ( opindex == (CGEN_OPERAND_TYPE)IP2K_OPERAND_ADDR16P )
|
||||
*valuep = (value >> 14) & 0x7;
|
||||
}
|
||||
else
|
||||
errmsg = _("Byte address required. - must be even.");
|
||||
}else if ( result_type == CGEN_PARSE_OPERAND_RESULT_QUEUED )
|
||||
{
|
||||
/* This will happen for things like (s2-s1) where s2 and s1 */
|
||||
/* are labels. */
|
||||
*valuep = value;
|
||||
}
|
||||
else
|
||||
errmsg = _("cgen_parse_address returned a symbol. Literal required.");
|
||||
}
|
||||
return errmsg;
|
||||
}
|
||||
|
||||
|
||||
static const char *
|
||||
parse_lit8 (cd, strp, opindex, valuep)
|
||||
CGEN_CPU_DESC cd;
|
||||
const char **strp;
|
||||
int opindex;
|
||||
long *valuep;
|
||||
{
|
||||
const char *errmsg;
|
||||
enum cgen_parse_operand_result result_type;
|
||||
bfd_reloc_code_real_type code = BFD_RELOC_NONE;
|
||||
long value;
|
||||
|
||||
/* Parse %OP relocating operators. */
|
||||
if (strncmp (*strp, "%bank", 5) == 0)
|
||||
{
|
||||
*strp += 5;
|
||||
code = BFD_RELOC_IP2K_BANK;
|
||||
}
|
||||
else if (strncmp (*strp, "%lo8data", 8) == 0)
|
||||
{
|
||||
*strp += 8;
|
||||
code = BFD_RELOC_IP2K_LO8DATA;
|
||||
}
|
||||
else if (strncmp (*strp, "%hi8data", 8) == 0)
|
||||
{
|
||||
*strp += 8;
|
||||
code = BFD_RELOC_IP2K_HI8DATA;
|
||||
}
|
||||
else if (strncmp (*strp, "%ex8data", 8) == 0)
|
||||
{
|
||||
*strp += 8;
|
||||
code = BFD_RELOC_IP2K_EX8DATA;
|
||||
}
|
||||
else if (strncmp (*strp, "%lo8insn", 8) == 0)
|
||||
{
|
||||
*strp += 8;
|
||||
code = BFD_RELOC_IP2K_LO8INSN;
|
||||
}
|
||||
else if (strncmp (*strp, "%hi8insn", 8) == 0)
|
||||
{
|
||||
*strp += 8;
|
||||
code = BFD_RELOC_IP2K_HI8INSN;
|
||||
}
|
||||
|
||||
|
||||
/* Parse %op operand. */
|
||||
if (code != BFD_RELOC_NONE)
|
||||
{
|
||||
errmsg = cgen_parse_address (cd, strp, opindex, code,
|
||||
& result_type, & value);
|
||||
if ((errmsg == NULL) &&
|
||||
(result_type != CGEN_PARSE_OPERAND_RESULT_QUEUED))
|
||||
errmsg = _("%operator operand is not a symbol");
|
||||
|
||||
*valuep = value;
|
||||
}
|
||||
/* Parse as a number. */
|
||||
else
|
||||
{
|
||||
errmsg = cgen_parse_signed_integer (cd, strp, opindex, valuep);
|
||||
|
||||
/* Truncate to eight bits to accept both signed and unsigned input. */
|
||||
if (errmsg == NULL)
|
||||
*valuep &= 0xFF;
|
||||
}
|
||||
|
||||
return errmsg;
|
||||
}
|
||||
|
||||
static const char *
|
||||
parse_bit3 (cd, strp, opindex, valuep)
|
||||
CGEN_CPU_DESC cd;
|
||||
const char **strp;
|
||||
int opindex;
|
||||
long *valuep;
|
||||
{
|
||||
const char *errmsg;
|
||||
char mode = 0;
|
||||
long count = 0;
|
||||
unsigned long value;
|
||||
|
||||
if (strncmp (*strp, "%bit", 4) == 0)
|
||||
{
|
||||
*strp += 4;
|
||||
mode = 1;
|
||||
}
|
||||
else if (strncmp (*strp, "%msbbit", 7) == 0)
|
||||
{
|
||||
*strp += 7;
|
||||
mode = 1;
|
||||
}
|
||||
else if (strncmp (*strp, "%lsbbit", 7) == 0)
|
||||
{
|
||||
*strp += 7;
|
||||
mode = 2;
|
||||
}
|
||||
|
||||
errmsg = cgen_parse_signed_integer (cd, strp, opindex, valuep);
|
||||
if (errmsg) {
|
||||
return errmsg;
|
||||
}
|
||||
|
||||
if (mode) {
|
||||
value = (unsigned long) *valuep;
|
||||
if (value == 0) {
|
||||
errmsg = _("Attempt to find bit index of 0");
|
||||
return errmsg;
|
||||
}
|
||||
|
||||
if (mode == 1) {
|
||||
count = 31;
|
||||
while ((value & 0x80000000) == 0) {
|
||||
count--;
|
||||
value <<= 1;
|
||||
}
|
||||
} else if (mode == 2) {
|
||||
count = 0;
|
||||
while ((value & 0x00000001) == 0) {
|
||||
count++;
|
||||
value >>= 1;
|
||||
}
|
||||
}
|
||||
|
||||
*valuep = count;
|
||||
}
|
||||
|
||||
return errmsg;
|
||||
}
|
||||
|
||||
|
||||
/* -- dis.c */
|
||||
|
||||
const char * ip2k_cgen_parse_operand
|
||||
PARAMS ((CGEN_CPU_DESC, int, const char **, CGEN_FIELDS *));
|
||||
|
||||
/* Main entry point for operand parsing.
|
||||
|
||||
This function is basically just a big switch statement. Earlier versions
|
||||
used tables to look up the function to use, but
|
||||
- if the table contains both assembler and disassembler functions then
|
||||
the disassembler contains much of the assembler and vice-versa,
|
||||
- there's a lot of inlining possibilities as things grow,
|
||||
- using a switch statement avoids the function call overhead.
|
||||
|
||||
This function could be moved into `parse_insn_normal', but keeping it
|
||||
separate makes clear the interface between `parse_insn_normal' and each of
|
||||
the handlers. */
|
||||
|
||||
const char *
|
||||
ip2k_cgen_parse_operand (cd, opindex, strp, fields)
|
||||
CGEN_CPU_DESC cd;
|
||||
int opindex;
|
||||
const char ** strp;
|
||||
CGEN_FIELDS * fields;
|
||||
{
|
||||
const char * errmsg = NULL;
|
||||
/* Used by scalar operands that still need to be parsed. */
|
||||
long junk ATTRIBUTE_UNUSED;
|
||||
|
||||
switch (opindex)
|
||||
{
|
||||
case IP2K_OPERAND_ADDR16CJP :
|
||||
errmsg = parse_addr16_cjp (cd, strp, IP2K_OPERAND_ADDR16CJP, &fields->f_addr16cjp);
|
||||
break;
|
||||
case IP2K_OPERAND_ADDR16H :
|
||||
errmsg = parse_addr16 (cd, strp, IP2K_OPERAND_ADDR16H, &fields->f_imm8);
|
||||
break;
|
||||
case IP2K_OPERAND_ADDR16L :
|
||||
errmsg = parse_addr16 (cd, strp, IP2K_OPERAND_ADDR16L, &fields->f_imm8);
|
||||
break;
|
||||
case IP2K_OPERAND_ADDR16P :
|
||||
errmsg = parse_addr16_cjp (cd, strp, IP2K_OPERAND_ADDR16P, &fields->f_page3);
|
||||
break;
|
||||
case IP2K_OPERAND_BITNO :
|
||||
errmsg = parse_bit3 (cd, strp, IP2K_OPERAND_BITNO, &fields->f_bitno);
|
||||
break;
|
||||
case IP2K_OPERAND_CBIT :
|
||||
errmsg = cgen_parse_unsigned_integer (cd, strp, IP2K_OPERAND_CBIT, &junk);
|
||||
break;
|
||||
case IP2K_OPERAND_DCBIT :
|
||||
errmsg = cgen_parse_unsigned_integer (cd, strp, IP2K_OPERAND_DCBIT, &junk);
|
||||
break;
|
||||
case IP2K_OPERAND_FR :
|
||||
errmsg = parse_fr (cd, strp, IP2K_OPERAND_FR, &fields->f_reg);
|
||||
break;
|
||||
case IP2K_OPERAND_LIT8 :
|
||||
errmsg = parse_lit8 (cd, strp, IP2K_OPERAND_LIT8, &fields->f_imm8);
|
||||
break;
|
||||
case IP2K_OPERAND_PABITS :
|
||||
errmsg = cgen_parse_unsigned_integer (cd, strp, IP2K_OPERAND_PABITS, &junk);
|
||||
break;
|
||||
case IP2K_OPERAND_RETI3 :
|
||||
errmsg = cgen_parse_unsigned_integer (cd, strp, IP2K_OPERAND_RETI3, &fields->f_reti3);
|
||||
break;
|
||||
case IP2K_OPERAND_ZBIT :
|
||||
errmsg = cgen_parse_unsigned_integer (cd, strp, IP2K_OPERAND_ZBIT, &junk);
|
||||
break;
|
||||
|
||||
default :
|
||||
/* xgettext:c-format */
|
||||
fprintf (stderr, _("Unrecognized field %d while parsing.\n"), opindex);
|
||||
abort ();
|
||||
}
|
||||
|
||||
return errmsg;
|
||||
}
|
||||
|
||||
cgen_parse_fn * const ip2k_cgen_parse_handlers[] =
|
||||
{
|
||||
parse_insn_normal,
|
||||
};
|
||||
|
||||
void
|
||||
ip2k_cgen_init_asm (cd)
|
||||
CGEN_CPU_DESC cd;
|
||||
{
|
||||
ip2k_cgen_init_opcode_table (cd);
|
||||
ip2k_cgen_init_ibld_table (cd);
|
||||
cd->parse_handlers = & ip2k_cgen_parse_handlers[0];
|
||||
cd->parse_operand = ip2k_cgen_parse_operand;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Regex construction routine.
|
||||
|
||||
This translates an opcode syntax string into a regex string,
|
||||
by replacing any non-character syntax element (such as an
|
||||
opcode) with the pattern '.*'
|
||||
|
||||
It then compiles the regex and stores it in the opcode, for
|
||||
later use by ip2k_cgen_assemble_insn
|
||||
|
||||
Returns NULL for success, an error message for failure. */
|
||||
|
||||
char *
|
||||
ip2k_cgen_build_insn_regex (insn)
|
||||
CGEN_INSN *insn;
|
||||
{
|
||||
CGEN_OPCODE *opc = (CGEN_OPCODE *) CGEN_INSN_OPCODE (insn);
|
||||
const char *mnem = CGEN_INSN_MNEMONIC (insn);
|
||||
char rxbuf[CGEN_MAX_RX_ELEMENTS];
|
||||
char *rx = rxbuf;
|
||||
const CGEN_SYNTAX_CHAR_TYPE *syn;
|
||||
int reg_err;
|
||||
|
||||
syn = CGEN_SYNTAX_STRING (CGEN_OPCODE_SYNTAX (opc));
|
||||
|
||||
/* Mnemonics come first in the syntax string. */
|
||||
if (! CGEN_SYNTAX_MNEMONIC_P (* syn))
|
||||
return _("missing mnemonic in syntax string");
|
||||
++syn;
|
||||
|
||||
/* Generate a case sensitive regular expression that emulates case
|
||||
insensitive matching in the "C" locale. We cannot generate a case
|
||||
insensitive regular expression because in Turkish locales, 'i' and 'I'
|
||||
are not equal modulo case conversion. */
|
||||
|
||||
/* Copy the literal mnemonic out of the insn. */
|
||||
for (; *mnem; mnem++)
|
||||
{
|
||||
char c = *mnem;
|
||||
|
||||
if (ISALPHA (c))
|
||||
{
|
||||
*rx++ = '[';
|
||||
*rx++ = TOLOWER (c);
|
||||
*rx++ = TOUPPER (c);
|
||||
*rx++ = ']';
|
||||
}
|
||||
else
|
||||
*rx++ = c;
|
||||
}
|
||||
|
||||
/* Copy any remaining literals from the syntax string into the rx. */
|
||||
for(; * syn != 0 && rx <= rxbuf + (CGEN_MAX_RX_ELEMENTS - 7 - 4); ++syn)
|
||||
{
|
||||
if (CGEN_SYNTAX_CHAR_P (* syn))
|
||||
{
|
||||
char c = CGEN_SYNTAX_CHAR (* syn);
|
||||
|
||||
switch (c)
|
||||
{
|
||||
/* Escape any regex metacharacters in the syntax. */
|
||||
case '.': case '[': case '\\':
|
||||
case '*': case '^': case '$':
|
||||
|
||||
#ifdef CGEN_ESCAPE_EXTENDED_REGEX
|
||||
case '?': case '{': case '}':
|
||||
case '(': case ')': case '*':
|
||||
case '|': case '+': case ']':
|
||||
#endif
|
||||
*rx++ = '\\';
|
||||
*rx++ = c;
|
||||
break;
|
||||
|
||||
default:
|
||||
if (ISALPHA (c))
|
||||
{
|
||||
*rx++ = '[';
|
||||
*rx++ = TOLOWER (c);
|
||||
*rx++ = TOUPPER (c);
|
||||
*rx++ = ']';
|
||||
}
|
||||
else
|
||||
*rx++ = c;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Replace non-syntax fields with globs. */
|
||||
*rx++ = '.';
|
||||
*rx++ = '*';
|
||||
}
|
||||
}
|
||||
|
||||
/* Trailing whitespace ok. */
|
||||
* rx++ = '[';
|
||||
* rx++ = ' ';
|
||||
* rx++ = '\t';
|
||||
* rx++ = ']';
|
||||
* rx++ = '*';
|
||||
|
||||
/* But anchor it after that. */
|
||||
* rx++ = '$';
|
||||
* rx = '\0';
|
||||
|
||||
CGEN_INSN_RX (insn) = xmalloc (sizeof (regex_t));
|
||||
reg_err = regcomp ((regex_t *) CGEN_INSN_RX (insn), rxbuf, REG_NOSUB);
|
||||
|
||||
if (reg_err == 0)
|
||||
return NULL;
|
||||
else
|
||||
{
|
||||
static char msg[80];
|
||||
|
||||
regerror (reg_err, (regex_t *) CGEN_INSN_RX (insn), msg, 80);
|
||||
regfree ((regex_t *) CGEN_INSN_RX (insn));
|
||||
free (CGEN_INSN_RX (insn));
|
||||
(CGEN_INSN_RX (insn)) = NULL;
|
||||
return msg;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Default insn parser.
|
||||
|
||||
The syntax string is scanned and operands are parsed and stored in FIELDS.
|
||||
Relocs are queued as we go via other callbacks.
|
||||
|
||||
??? Note that this is currently an all-or-nothing parser. If we fail to
|
||||
parse the instruction, we return 0 and the caller will start over from
|
||||
the beginning. Backtracking will be necessary in parsing subexpressions,
|
||||
but that can be handled there. Not handling backtracking here may get
|
||||
expensive in the case of the m68k. Deal with later.
|
||||
|
||||
Returns NULL for success, an error message for failure. */
|
||||
|
||||
static const char *
|
||||
parse_insn_normal (cd, insn, strp, fields)
|
||||
CGEN_CPU_DESC cd;
|
||||
const CGEN_INSN *insn;
|
||||
const char **strp;
|
||||
CGEN_FIELDS *fields;
|
||||
{
|
||||
/* ??? Runtime added insns not handled yet. */
|
||||
const CGEN_SYNTAX *syntax = CGEN_INSN_SYNTAX (insn);
|
||||
const char *str = *strp;
|
||||
const char *errmsg;
|
||||
const char *p;
|
||||
const CGEN_SYNTAX_CHAR_TYPE * syn;
|
||||
#ifdef CGEN_MNEMONIC_OPERANDS
|
||||
/* FIXME: wip */
|
||||
int past_opcode_p;
|
||||
#endif
|
||||
|
||||
/* For now we assume the mnemonic is first (there are no leading operands).
|
||||
We can parse it without needing to set up operand parsing.
|
||||
GAS's input scrubber will ensure mnemonics are lowercase, but we may
|
||||
not be called from GAS. */
|
||||
p = CGEN_INSN_MNEMONIC (insn);
|
||||
while (*p && TOLOWER (*p) == TOLOWER (*str))
|
||||
++p, ++str;
|
||||
|
||||
if (* p)
|
||||
return _("unrecognized instruction");
|
||||
|
||||
#ifndef CGEN_MNEMONIC_OPERANDS
|
||||
if (* str && ! ISSPACE (* str))
|
||||
return _("unrecognized instruction");
|
||||
#endif
|
||||
|
||||
CGEN_INIT_PARSE (cd);
|
||||
cgen_init_parse_operand (cd);
|
||||
#ifdef CGEN_MNEMONIC_OPERANDS
|
||||
past_opcode_p = 0;
|
||||
#endif
|
||||
|
||||
/* We don't check for (*str != '\0') here because we want to parse
|
||||
any trailing fake arguments in the syntax string. */
|
||||
syn = CGEN_SYNTAX_STRING (syntax);
|
||||
|
||||
/* Mnemonics come first for now, ensure valid string. */
|
||||
if (! CGEN_SYNTAX_MNEMONIC_P (* syn))
|
||||
abort ();
|
||||
|
||||
++syn;
|
||||
|
||||
while (* syn != 0)
|
||||
{
|
||||
/* Non operand chars must match exactly. */
|
||||
if (CGEN_SYNTAX_CHAR_P (* syn))
|
||||
{
|
||||
/* FIXME: While we allow for non-GAS callers above, we assume the
|
||||
first char after the mnemonic part is a space. */
|
||||
/* FIXME: We also take inappropriate advantage of the fact that
|
||||
GAS's input scrubber will remove extraneous blanks. */
|
||||
if (TOLOWER (*str) == TOLOWER (CGEN_SYNTAX_CHAR (* syn)))
|
||||
{
|
||||
#ifdef CGEN_MNEMONIC_OPERANDS
|
||||
if (CGEN_SYNTAX_CHAR(* syn) == ' ')
|
||||
past_opcode_p = 1;
|
||||
#endif
|
||||
++ syn;
|
||||
++ str;
|
||||
}
|
||||
else if (*str)
|
||||
{
|
||||
/* Syntax char didn't match. Can't be this insn. */
|
||||
static char msg [80];
|
||||
|
||||
/* xgettext:c-format */
|
||||
sprintf (msg, _("syntax error (expected char `%c', found `%c')"),
|
||||
CGEN_SYNTAX_CHAR(*syn), *str);
|
||||
return msg;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Ran out of input. */
|
||||
static char msg [80];
|
||||
|
||||
/* xgettext:c-format */
|
||||
sprintf (msg, _("syntax error (expected char `%c', found end of instruction)"),
|
||||
CGEN_SYNTAX_CHAR(*syn));
|
||||
return msg;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
/* We have an operand of some sort. */
|
||||
errmsg = cd->parse_operand (cd, CGEN_SYNTAX_FIELD (*syn),
|
||||
&str, fields);
|
||||
if (errmsg)
|
||||
return errmsg;
|
||||
|
||||
/* Done with this operand, continue with next one. */
|
||||
++ syn;
|
||||
}
|
||||
|
||||
/* If we're at the end of the syntax string, we're done. */
|
||||
if (* syn == 0)
|
||||
{
|
||||
/* FIXME: For the moment we assume a valid `str' can only contain
|
||||
blanks now. IE: We needn't try again with a longer version of
|
||||
the insn and it is assumed that longer versions of insns appear
|
||||
before shorter ones (eg: lsr r2,r3,1 vs lsr r2,r3). */
|
||||
while (ISSPACE (* str))
|
||||
++ str;
|
||||
|
||||
if (* str != '\0')
|
||||
return _("junk at end of line"); /* FIXME: would like to include `str' */
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* We couldn't parse it. */
|
||||
return _("unrecognized instruction");
|
||||
}
|
||||
|
||||
/* Main entry point.
|
||||
This routine is called for each instruction to be assembled.
|
||||
STR points to the insn to be assembled.
|
||||
We assume all necessary tables have been initialized.
|
||||
The assembled instruction, less any fixups, is stored in BUF.
|
||||
Remember that if CGEN_INT_INSN_P then BUF is an int and thus the value
|
||||
still needs to be converted to target byte order, otherwise BUF is an array
|
||||
of bytes in target byte order.
|
||||
The result is a pointer to the insn's entry in the opcode table,
|
||||
or NULL if an error occured (an error message will have already been
|
||||
printed).
|
||||
|
||||
Note that when processing (non-alias) macro-insns,
|
||||
this function recurses.
|
||||
|
||||
??? It's possible to make this cpu-independent.
|
||||
One would have to deal with a few minor things.
|
||||
At this point in time doing so would be more of a curiosity than useful
|
||||
[for example this file isn't _that_ big], but keeping the possibility in
|
||||
mind helps keep the design clean. */
|
||||
|
||||
const CGEN_INSN *
|
||||
ip2k_cgen_assemble_insn (cd, str, fields, buf, errmsg)
|
||||
CGEN_CPU_DESC cd;
|
||||
const char *str;
|
||||
CGEN_FIELDS *fields;
|
||||
CGEN_INSN_BYTES_PTR buf;
|
||||
char **errmsg;
|
||||
{
|
||||
const char *start;
|
||||
CGEN_INSN_LIST *ilist;
|
||||
const char *parse_errmsg = NULL;
|
||||
const char *insert_errmsg = NULL;
|
||||
int recognized_mnemonic = 0;
|
||||
|
||||
/* Skip leading white space. */
|
||||
while (ISSPACE (* str))
|
||||
++ str;
|
||||
|
||||
/* The instructions are stored in hashed lists.
|
||||
Get the first in the list. */
|
||||
ilist = CGEN_ASM_LOOKUP_INSN (cd, str);
|
||||
|
||||
/* Keep looking until we find a match. */
|
||||
start = str;
|
||||
for ( ; ilist != NULL ; ilist = CGEN_ASM_NEXT_INSN (ilist))
|
||||
{
|
||||
const CGEN_INSN *insn = ilist->insn;
|
||||
recognized_mnemonic = 1;
|
||||
|
||||
#ifdef CGEN_VALIDATE_INSN_SUPPORTED
|
||||
/* Not usually needed as unsupported opcodes
|
||||
shouldn't be in the hash lists. */
|
||||
/* Is this insn supported by the selected cpu? */
|
||||
if (! ip2k_cgen_insn_supported (cd, insn))
|
||||
continue;
|
||||
#endif
|
||||
/* If the RELAX attribute is set, this is an insn that shouldn't be
|
||||
chosen immediately. Instead, it is used during assembler/linker
|
||||
relaxation if possible. */
|
||||
if (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_RELAX) != 0)
|
||||
continue;
|
||||
|
||||
str = start;
|
||||
|
||||
/* Skip this insn if str doesn't look right lexically. */
|
||||
if (CGEN_INSN_RX (insn) != NULL &&
|
||||
regexec ((regex_t *) CGEN_INSN_RX (insn), str, 0, NULL, 0) == REG_NOMATCH)
|
||||
continue;
|
||||
|
||||
/* Allow parse/insert handlers to obtain length of insn. */
|
||||
CGEN_FIELDS_BITSIZE (fields) = CGEN_INSN_BITSIZE (insn);
|
||||
|
||||
parse_errmsg = CGEN_PARSE_FN (cd, insn) (cd, insn, & str, fields);
|
||||
if (parse_errmsg != NULL)
|
||||
continue;
|
||||
|
||||
/* ??? 0 is passed for `pc'. */
|
||||
insert_errmsg = CGEN_INSERT_FN (cd, insn) (cd, insn, fields, buf,
|
||||
(bfd_vma) 0);
|
||||
if (insert_errmsg != NULL)
|
||||
continue;
|
||||
|
||||
/* It is up to the caller to actually output the insn and any
|
||||
queued relocs. */
|
||||
return insn;
|
||||
}
|
||||
|
||||
{
|
||||
static char errbuf[150];
|
||||
#ifdef CGEN_VERBOSE_ASSEMBLER_ERRORS
|
||||
const char *tmp_errmsg;
|
||||
|
||||
/* If requesting verbose error messages, use insert_errmsg.
|
||||
Failing that, use parse_errmsg. */
|
||||
tmp_errmsg = (insert_errmsg ? insert_errmsg :
|
||||
parse_errmsg ? parse_errmsg :
|
||||
recognized_mnemonic ?
|
||||
_("unrecognized form of instruction") :
|
||||
_("unrecognized instruction"));
|
||||
|
||||
if (strlen (start) > 50)
|
||||
/* xgettext:c-format */
|
||||
sprintf (errbuf, "%s `%.50s...'", tmp_errmsg, start);
|
||||
else
|
||||
/* xgettext:c-format */
|
||||
sprintf (errbuf, "%s `%.50s'", tmp_errmsg, start);
|
||||
#else
|
||||
if (strlen (start) > 50)
|
||||
/* xgettext:c-format */
|
||||
sprintf (errbuf, _("bad instruction `%.50s...'"), start);
|
||||
else
|
||||
/* xgettext:c-format */
|
||||
sprintf (errbuf, _("bad instruction `%.50s'"), start);
|
||||
#endif
|
||||
|
||||
*errmsg = errbuf;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
#if 0 /* This calls back to GAS which we can't do without care. */
|
||||
|
||||
/* Record each member of OPVALS in the assembler's symbol table.
|
||||
This lets GAS parse registers for us.
|
||||
??? Interesting idea but not currently used. */
|
||||
|
||||
/* Record each member of OPVALS in the assembler's symbol table.
|
||||
FIXME: Not currently used. */
|
||||
|
||||
void
|
||||
ip2k_cgen_asm_hash_keywords (cd, opvals)
|
||||
CGEN_CPU_DESC cd;
|
||||
CGEN_KEYWORD *opvals;
|
||||
{
|
||||
CGEN_KEYWORD_SEARCH search = cgen_keyword_search_init (opvals, NULL);
|
||||
const CGEN_KEYWORD_ENTRY * ke;
|
||||
|
||||
while ((ke = cgen_keyword_search_next (& search)) != NULL)
|
||||
{
|
||||
#if 0 /* Unnecessary, should be done in the search routine. */
|
||||
if (! ip2k_cgen_opval_supported (ke))
|
||||
continue;
|
||||
#endif
|
||||
cgen_asm_record_register (cd, ke->name, ke->value);
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* 0 */
|
||||
1219
opcodes/ip2k-desc.c
Normal file
1219
opcodes/ip2k-desc.c
Normal file
File diff suppressed because it is too large
Load Diff
251
opcodes/ip2k-desc.h
Normal file
251
opcodes/ip2k-desc.h
Normal file
@@ -0,0 +1,251 @@
|
||||
/* CPU data header for ip2k.
|
||||
|
||||
THIS FILE IS MACHINE GENERATED WITH CGEN.
|
||||
|
||||
Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of the GNU Binutils and/or GDB, the GNU debugger.
|
||||
|
||||
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.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef IP2K_CPU_H
|
||||
#define IP2K_CPU_H
|
||||
|
||||
#define CGEN_ARCH ip2k
|
||||
|
||||
/* Given symbol S, return ip2k_cgen_<S>. */
|
||||
#if defined (__STDC__) || defined (ALMOST_STDC) || defined (HAVE_STRINGIZE)
|
||||
#define CGEN_SYM(s) ip2k##_cgen_##s
|
||||
#else
|
||||
#define CGEN_SYM(s) ip2k/**/_cgen_/**/s
|
||||
#endif
|
||||
|
||||
|
||||
/* Selected cpu families. */
|
||||
#define HAVE_CPU_IP2KBF
|
||||
|
||||
#define CGEN_INSN_LSB0_P 1
|
||||
|
||||
/* Minimum size of any insn (in bytes). */
|
||||
#define CGEN_MIN_INSN_SIZE 2
|
||||
|
||||
/* Maximum size of any insn (in bytes). */
|
||||
#define CGEN_MAX_INSN_SIZE 2
|
||||
|
||||
#define CGEN_INT_INSN_P 1
|
||||
|
||||
/* Maximum number of syntax elements in an instruction. */
|
||||
#define CGEN_ACTUAL_MAX_SYNTAX_ELEMENTS 12
|
||||
|
||||
/* CGEN_MNEMONIC_OPERANDS is defined if mnemonics have operands.
|
||||
e.g. In "b,a foo" the ",a" is an operand. If mnemonics have operands
|
||||
we can't hash on everything up to the space. */
|
||||
#define CGEN_MNEMONIC_OPERANDS
|
||||
|
||||
/* Maximum number of fields in an instruction. */
|
||||
#define CGEN_ACTUAL_MAX_IFMT_OPERANDS 3
|
||||
|
||||
/* Enums. */
|
||||
|
||||
/* Enum declaration for op6 enums. */
|
||||
typedef enum insn_op6 {
|
||||
OP6_OTHER1, OP6_OTHER2, OP6_SUB, OP6_DEC
|
||||
, OP6_OR, OP6_AND, OP6_XOR, OP6_ADD
|
||||
, OP6_TEST, OP6_NOT, OP6_INC, OP6_DECSZ
|
||||
, OP6_RR, OP6_RL, OP6_SWAP, OP6_INCSZ
|
||||
, OP6_CSE, OP6_POP, OP6_SUBC, OP6_DECSNZ
|
||||
, OP6_MULU, OP6_MULS, OP6_INCSNZ, OP6_ADDC
|
||||
} INSN_OP6;
|
||||
|
||||
/* Enum declaration for dir enums. */
|
||||
typedef enum insn_dir {
|
||||
DIR_TO_W, DIR_NOTTO_W
|
||||
} INSN_DIR;
|
||||
|
||||
/* Enum declaration for op4 enums. */
|
||||
typedef enum insn_op4 {
|
||||
OP4_LITERAL = 7, OP4_CLRB = 8, OP4_SETB = 9, OP4_SNB = 10
|
||||
, OP4_SB = 11
|
||||
} INSN_OP4;
|
||||
|
||||
/* Enum declaration for op4mid enums. */
|
||||
typedef enum insn_op4mid {
|
||||
OP4MID_LOADH_L = 0, OP4MID_LOADL_L = 1, OP4MID_MULU_L = 2, OP4MID_MULS_L = 3
|
||||
, OP4MID_PUSH_L = 4, OP4MID_CSNE_L = 6, OP4MID_CSE_L = 7, OP4MID_RETW_L = 8
|
||||
, OP4MID_CMP_L = 9, OP4MID_SUB_L = 10, OP4MID_ADD_L = 11, OP4MID_MOV_L = 12
|
||||
, OP4MID_OR_L = 13, OP4MID_AND_L = 14, OP4MID_XOR_L = 15
|
||||
} INSN_OP4MID;
|
||||
|
||||
/* Enum declaration for op3 enums. */
|
||||
typedef enum insn_op3 {
|
||||
OP3_CALL = 6, OP3_JMP = 7
|
||||
} INSN_OP3;
|
||||
|
||||
/* Enum declaration for . */
|
||||
typedef enum register_names {
|
||||
H_REGISTERS_ADDRSEL = 2, H_REGISTERS_ADDRX = 3, H_REGISTERS_IPH = 4, H_REGISTERS_IPL = 5
|
||||
, H_REGISTERS_SPH = 6, H_REGISTERS_SPL = 7, H_REGISTERS_PCH = 8, H_REGISTERS_PCL = 9
|
||||
, H_REGISTERS_WREG = 10, H_REGISTERS_STATUS = 11, H_REGISTERS_DPH = 12, H_REGISTERS_DPL = 13
|
||||
, H_REGISTERS_SPDREG = 14, H_REGISTERS_MULH = 15, H_REGISTERS_ADDRH = 16, H_REGISTERS_ADDRL = 17
|
||||
, H_REGISTERS_DATAH = 18, H_REGISTERS_DATAL = 19, H_REGISTERS_INTVECH = 20, H_REGISTERS_INTVECL = 21
|
||||
, H_REGISTERS_INTSPD = 22, H_REGISTERS_INTF = 23, H_REGISTERS_INTE = 24, H_REGISTERS_INTED = 25
|
||||
, H_REGISTERS_FCFG = 26, H_REGISTERS_TCTRL = 27, H_REGISTERS_XCFG = 28, H_REGISTERS_EMCFG = 29
|
||||
, H_REGISTERS_IPCH = 30, H_REGISTERS_IPCL = 31, H_REGISTERS_RAIN = 32, H_REGISTERS_RAOUT = 33
|
||||
, H_REGISTERS_RADIR = 34, H_REGISTERS_LFSRH = 35, H_REGISTERS_RBIN = 36, H_REGISTERS_RBOUT = 37
|
||||
, H_REGISTERS_RBDIR = 38, H_REGISTERS_LFSRL = 39, H_REGISTERS_RCIN = 40, H_REGISTERS_RCOUT = 41
|
||||
, H_REGISTERS_RCDIR = 42, H_REGISTERS_LFSRA = 43, H_REGISTERS_RDIN = 44, H_REGISTERS_RDOUT = 45
|
||||
, H_REGISTERS_RDDIR = 46, H_REGISTERS_REIN = 48, H_REGISTERS_REOUT = 49, H_REGISTERS_REDIR = 50
|
||||
, H_REGISTERS_RFIN = 52, H_REGISTERS_RFOUT = 53, H_REGISTERS_RFDIR = 54, H_REGISTERS_RGOUT = 57
|
||||
, H_REGISTERS_RGDIR = 58, H_REGISTERS_RTTMR = 64, H_REGISTERS_RTCFG = 65, H_REGISTERS_T0TMR = 66
|
||||
, H_REGISTERS_T0CFG = 67, H_REGISTERS_T1CNTH = 68, H_REGISTERS_T1CNTL = 69, H_REGISTERS_T1CAP1H = 70
|
||||
, H_REGISTERS_T1CAP1L = 71, H_REGISTERS_T1CAP2H = 72, H_REGISTERS_T1CMP2H = 72, H_REGISTERS_T1CAP2L = 73
|
||||
, H_REGISTERS_T1CMP2L = 73, H_REGISTERS_T1CMP1H = 74, H_REGISTERS_T1CMP1L = 75, H_REGISTERS_T1CFG1H = 76
|
||||
, H_REGISTERS_T1CFG1L = 77, H_REGISTERS_T1CFG2H = 78, H_REGISTERS_T1CFG2L = 79, H_REGISTERS_ADCH = 80
|
||||
, H_REGISTERS_ADCL = 81, H_REGISTERS_ADCCFG = 82, H_REGISTERS_ADCTMR = 83, H_REGISTERS_T2CNTH = 84
|
||||
, H_REGISTERS_T2CNTL = 85, H_REGISTERS_T2CAP1H = 86, H_REGISTERS_T2CAP1L = 87, H_REGISTERS_T2CAP2H = 88
|
||||
, H_REGISTERS_T2CMP2H = 88, H_REGISTERS_T2CAP2L = 89, H_REGISTERS_T2CMP2L = 89, H_REGISTERS_T2CMP1H = 90
|
||||
, H_REGISTERS_T2CMP1L = 91, H_REGISTERS_T2CFG1H = 92, H_REGISTERS_T2CFG1L = 93, H_REGISTERS_T2CFG2H = 94
|
||||
, H_REGISTERS_T2CFG2L = 95, H_REGISTERS_S1TMRH = 96, H_REGISTERS_S1TMRL = 97, H_REGISTERS_S1TBUFH = 98
|
||||
, H_REGISTERS_S1TBUFL = 99, H_REGISTERS_S1TCFG = 100, H_REGISTERS_S1RCNT = 101, H_REGISTERS_S1RBUFH = 102
|
||||
, H_REGISTERS_S1RBUFL = 103, H_REGISTERS_S1RCFG = 104, H_REGISTERS_S1RSYNC = 105, H_REGISTERS_S1INTF = 106
|
||||
, H_REGISTERS_S1INTE = 107, H_REGISTERS_S1MODE = 108, H_REGISTERS_S1SMASK = 109, H_REGISTERS_PSPCFG = 110
|
||||
, H_REGISTERS_CMPCFG = 111, H_REGISTERS_S2TMRH = 112, H_REGISTERS_S2TMRL = 113, H_REGISTERS_S2TBUFH = 114
|
||||
, H_REGISTERS_S2TBUFL = 115, H_REGISTERS_S2TCFG = 116, H_REGISTERS_S2RCNT = 117, H_REGISTERS_S2RBUFH = 118
|
||||
, H_REGISTERS_S2RBUFL = 119, H_REGISTERS_S2RCFG = 120, H_REGISTERS_S2RSYNC = 121, H_REGISTERS_S2INTF = 122
|
||||
, H_REGISTERS_S2INTE = 123, H_REGISTERS_S2MODE = 124, H_REGISTERS_S2SMASK = 125, H_REGISTERS_CALLH = 126
|
||||
, H_REGISTERS_CALLL = 127
|
||||
} REGISTER_NAMES;
|
||||
|
||||
/* Attributes. */
|
||||
|
||||
/* Enum declaration for machine type selection. */
|
||||
typedef enum mach_attr {
|
||||
MACH_BASE, MACH_IP2022, MACH_IP2022EXT, MACH_MAX
|
||||
} MACH_ATTR;
|
||||
|
||||
/* Enum declaration for instruction set selection. */
|
||||
typedef enum isa_attr {
|
||||
ISA_IP2K, ISA_MAX
|
||||
} ISA_ATTR;
|
||||
|
||||
/* Number of architecture variants. */
|
||||
#define MAX_ISAS 1
|
||||
#define MAX_MACHS ((int) MACH_MAX)
|
||||
|
||||
/* Ifield support. */
|
||||
|
||||
extern const struct cgen_ifld ip2k_cgen_ifld_table[];
|
||||
|
||||
/* Ifield attribute indices. */
|
||||
|
||||
/* Enum declaration for cgen_ifld attrs. */
|
||||
typedef enum cgen_ifld_attr {
|
||||
CGEN_IFLD_VIRTUAL, CGEN_IFLD_PCREL_ADDR, CGEN_IFLD_ABS_ADDR, CGEN_IFLD_RESERVED
|
||||
, CGEN_IFLD_SIGN_OPT, CGEN_IFLD_SIGNED, CGEN_IFLD_END_BOOLS, CGEN_IFLD_START_NBOOLS = 31
|
||||
, CGEN_IFLD_MACH, CGEN_IFLD_END_NBOOLS
|
||||
} CGEN_IFLD_ATTR;
|
||||
|
||||
/* Number of non-boolean elements in cgen_ifld_attr. */
|
||||
#define CGEN_IFLD_NBOOL_ATTRS (CGEN_IFLD_END_NBOOLS - CGEN_IFLD_START_NBOOLS - 1)
|
||||
|
||||
/* Enum declaration for ip2k ifield types. */
|
||||
typedef enum ifield_type {
|
||||
IP2K_F_NIL, IP2K_F_ANYOF, IP2K_F_IMM8, IP2K_F_REG
|
||||
, IP2K_F_ADDR16CJP, IP2K_F_DIR, IP2K_F_BITNO, IP2K_F_OP3
|
||||
, IP2K_F_OP4, IP2K_F_OP4MID, IP2K_F_OP6, IP2K_F_OP8
|
||||
, IP2K_F_OP6_10LOW, IP2K_F_OP6_7LOW, IP2K_F_RETI3, IP2K_F_SKIPB
|
||||
, IP2K_F_PAGE3, IP2K_F_MAX
|
||||
} IFIELD_TYPE;
|
||||
|
||||
#define MAX_IFLD ((int) IP2K_F_MAX)
|
||||
|
||||
/* Hardware attribute indices. */
|
||||
|
||||
/* Enum declaration for cgen_hw attrs. */
|
||||
typedef enum cgen_hw_attr {
|
||||
CGEN_HW_VIRTUAL, CGEN_HW_CACHE_ADDR, CGEN_HW_PC, CGEN_HW_PROFILE
|
||||
, CGEN_HW_END_BOOLS, CGEN_HW_START_NBOOLS = 31, CGEN_HW_MACH, CGEN_HW_END_NBOOLS
|
||||
} CGEN_HW_ATTR;
|
||||
|
||||
/* Number of non-boolean elements in cgen_hw_attr. */
|
||||
#define CGEN_HW_NBOOL_ATTRS (CGEN_HW_END_NBOOLS - CGEN_HW_START_NBOOLS - 1)
|
||||
|
||||
/* Enum declaration for ip2k hardware types. */
|
||||
typedef enum cgen_hw_type {
|
||||
HW_H_MEMORY, HW_H_SINT, HW_H_UINT, HW_H_ADDR
|
||||
, HW_H_IADDR, HW_H_SPR, HW_H_REGISTERS, HW_H_STACK
|
||||
, HW_H_PABITS, HW_H_ZBIT, HW_H_CBIT, HW_H_DCBIT
|
||||
, HW_H_PC, HW_MAX
|
||||
} CGEN_HW_TYPE;
|
||||
|
||||
#define MAX_HW ((int) HW_MAX)
|
||||
|
||||
/* Operand attribute indices. */
|
||||
|
||||
/* Enum declaration for cgen_operand attrs. */
|
||||
typedef enum cgen_operand_attr {
|
||||
CGEN_OPERAND_VIRTUAL, CGEN_OPERAND_PCREL_ADDR, CGEN_OPERAND_ABS_ADDR, CGEN_OPERAND_SIGN_OPT
|
||||
, CGEN_OPERAND_SIGNED, CGEN_OPERAND_NEGATIVE, CGEN_OPERAND_RELAX, CGEN_OPERAND_SEM_ONLY
|
||||
, CGEN_OPERAND_END_BOOLS, CGEN_OPERAND_START_NBOOLS = 31, CGEN_OPERAND_MACH, CGEN_OPERAND_END_NBOOLS
|
||||
} CGEN_OPERAND_ATTR;
|
||||
|
||||
/* Number of non-boolean elements in cgen_operand_attr. */
|
||||
#define CGEN_OPERAND_NBOOL_ATTRS (CGEN_OPERAND_END_NBOOLS - CGEN_OPERAND_START_NBOOLS - 1)
|
||||
|
||||
/* Enum declaration for ip2k operand types. */
|
||||
typedef enum cgen_operand_type {
|
||||
IP2K_OPERAND_PC, IP2K_OPERAND_ADDR16CJP, IP2K_OPERAND_FR, IP2K_OPERAND_LIT8
|
||||
, IP2K_OPERAND_BITNO, IP2K_OPERAND_ADDR16P, IP2K_OPERAND_ADDR16H, IP2K_OPERAND_ADDR16L
|
||||
, IP2K_OPERAND_RETI3, IP2K_OPERAND_PABITS, IP2K_OPERAND_ZBIT, IP2K_OPERAND_CBIT
|
||||
, IP2K_OPERAND_DCBIT, IP2K_OPERAND_MAX
|
||||
} CGEN_OPERAND_TYPE;
|
||||
|
||||
/* Number of operands types. */
|
||||
#define MAX_OPERANDS 13
|
||||
|
||||
/* Maximum number of operands referenced by any insn. */
|
||||
#define MAX_OPERAND_INSTANCES 8
|
||||
|
||||
/* Insn attribute indices. */
|
||||
|
||||
/* Enum declaration for cgen_insn attrs. */
|
||||
typedef enum cgen_insn_attr {
|
||||
CGEN_INSN_ALIAS, CGEN_INSN_VIRTUAL, CGEN_INSN_UNCOND_CTI, CGEN_INSN_COND_CTI
|
||||
, CGEN_INSN_SKIP_CTI, CGEN_INSN_DELAY_SLOT, CGEN_INSN_RELAXABLE, CGEN_INSN_RELAX
|
||||
, CGEN_INSN_NO_DIS, CGEN_INSN_PBB, CGEN_INSN_EXT_SKIP_INSN, CGEN_INSN_SKIPA
|
||||
, CGEN_INSN_END_BOOLS, CGEN_INSN_START_NBOOLS = 31, CGEN_INSN_MACH, CGEN_INSN_END_NBOOLS
|
||||
} CGEN_INSN_ATTR;
|
||||
|
||||
/* Number of non-boolean elements in cgen_insn_attr. */
|
||||
#define CGEN_INSN_NBOOL_ATTRS (CGEN_INSN_END_NBOOLS - CGEN_INSN_START_NBOOLS - 1)
|
||||
|
||||
/* cgen.h uses things we just defined. */
|
||||
#include "opcode/cgen.h"
|
||||
|
||||
/* Attributes. */
|
||||
extern const CGEN_ATTR_TABLE ip2k_cgen_hardware_attr_table[];
|
||||
extern const CGEN_ATTR_TABLE ip2k_cgen_ifield_attr_table[];
|
||||
extern const CGEN_ATTR_TABLE ip2k_cgen_operand_attr_table[];
|
||||
extern const CGEN_ATTR_TABLE ip2k_cgen_insn_attr_table[];
|
||||
|
||||
/* Hardware decls. */
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#endif /* IP2K_CPU_H */
|
||||
743
opcodes/ip2k-dis.c
Normal file
743
opcodes/ip2k-dis.c
Normal file
@@ -0,0 +1,743 @@
|
||||
/* Disassembler interface for targets using CGEN. -*- C -*-
|
||||
CGEN: Cpu tools GENerator
|
||||
|
||||
THIS FILE IS MACHINE GENERATED WITH CGEN.
|
||||
- the resultant file is machine generated, cgen-dis.in isn't
|
||||
|
||||
Copyright 1996, 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of the GNU Binutils and GDB, the GNU debugger.
|
||||
|
||||
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. */
|
||||
|
||||
/* ??? Eventually more and more of this stuff can go to cpu-independent files.
|
||||
Keep that in mind. */
|
||||
|
||||
#include "sysdep.h"
|
||||
#include <stdio.h>
|
||||
#include "ansidecl.h"
|
||||
#include "dis-asm.h"
|
||||
#include "bfd.h"
|
||||
#include "symcat.h"
|
||||
#include "ip2k-desc.h"
|
||||
#include "ip2k-opc.h"
|
||||
#include "opintl.h"
|
||||
|
||||
/* Default text to print if an instruction isn't recognized. */
|
||||
#define UNKNOWN_INSN_MSG _("*unknown*")
|
||||
|
||||
static void print_normal
|
||||
PARAMS ((CGEN_CPU_DESC, PTR, long, unsigned int, bfd_vma, int));
|
||||
static void print_address
|
||||
PARAMS ((CGEN_CPU_DESC, PTR, bfd_vma, unsigned int, bfd_vma, int));
|
||||
static void print_keyword
|
||||
PARAMS ((CGEN_CPU_DESC, PTR, CGEN_KEYWORD *, long, unsigned int));
|
||||
static void print_insn_normal
|
||||
PARAMS ((CGEN_CPU_DESC, PTR, const CGEN_INSN *, CGEN_FIELDS *,
|
||||
bfd_vma, int));
|
||||
static int print_insn
|
||||
PARAMS ((CGEN_CPU_DESC, bfd_vma, disassemble_info *, char *, unsigned));
|
||||
static int default_print_insn
|
||||
PARAMS ((CGEN_CPU_DESC, bfd_vma, disassemble_info *));
|
||||
static int read_insn
|
||||
PARAMS ((CGEN_CPU_DESC, bfd_vma, disassemble_info *, char *, int,
|
||||
CGEN_EXTRACT_INFO *, unsigned long *));
|
||||
|
||||
/* -- disassembler routines inserted here */
|
||||
|
||||
/* -- dis.c */
|
||||
|
||||
static void
|
||||
print_fr (cd, dis_info, value, attrs, pc, length)
|
||||
CGEN_CPU_DESC cd;
|
||||
PTR dis_info;
|
||||
long value;
|
||||
unsigned int attrs;
|
||||
bfd_vma pc;
|
||||
int length;
|
||||
{
|
||||
disassemble_info *info = (disassemble_info *) dis_info;
|
||||
const CGEN_KEYWORD_ENTRY *ke;
|
||||
extern CGEN_KEYWORD ip2k_cgen_opval_register_names;
|
||||
long offsettest;
|
||||
long offsetvalue;
|
||||
|
||||
if ( value == 0 ) /* This is (IP) */
|
||||
{
|
||||
(*info->fprintf_func) (info->stream, "%s", "(IP)");
|
||||
return;
|
||||
}
|
||||
|
||||
offsettest = value >> 7;
|
||||
offsetvalue = value & 0x7F;
|
||||
|
||||
/* Check to see if first two bits are 10 -> (DP) */
|
||||
if ( offsettest == 2 )
|
||||
{
|
||||
if ( offsetvalue == 0 )
|
||||
(*info->fprintf_func) (info->stream, "%s","(DP)");
|
||||
else
|
||||
(*info->fprintf_func) (info->stream, "$%x%s",offsetvalue, "(DP)");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Check to see if first two bits are 11 -> (SP) */
|
||||
if ( offsettest == 3 )
|
||||
{
|
||||
if ( offsetvalue == 0 )
|
||||
(*info->fprintf_func) (info->stream, "%s", "(SP)");
|
||||
else
|
||||
(*info->fprintf_func) (info->stream, "$%x%s", offsetvalue,"(SP)");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Attempt to print as a register keyword. */
|
||||
ke = cgen_keyword_lookup_value (& ip2k_cgen_opval_register_names, value);
|
||||
if (ke != NULL)
|
||||
{
|
||||
(*info->fprintf_func) (info->stream, "%s", ke->name);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Print as an address literal. */
|
||||
(*info->fprintf_func) (info->stream, "$%02x", value);
|
||||
}
|
||||
|
||||
static void
|
||||
print_dollarhex (cd, dis_info, value, attrs, pc, length)
|
||||
CGEN_CPU_DESC cd;
|
||||
PTR dis_info;
|
||||
long value;
|
||||
unsigned int attrs;
|
||||
bfd_vma pc;
|
||||
int length;
|
||||
{
|
||||
disassemble_info *info = (disassemble_info *) dis_info;
|
||||
|
||||
(*info->fprintf_func) (info->stream, "$%x", value);
|
||||
}
|
||||
|
||||
static void
|
||||
print_dollarhex8 (cd, dis_info, value, attrs, pc, length)
|
||||
CGEN_CPU_DESC cd;
|
||||
PTR dis_info;
|
||||
long value;
|
||||
unsigned int attrs;
|
||||
bfd_vma pc;
|
||||
int length;
|
||||
{
|
||||
disassemble_info *info = (disassemble_info *) dis_info;
|
||||
|
||||
(*info->fprintf_func) (info->stream, "$%02x", value);
|
||||
}
|
||||
|
||||
static void
|
||||
print_dollarhex16 (cd, dis_info, value, attrs, pc, length)
|
||||
CGEN_CPU_DESC cd;
|
||||
PTR dis_info;
|
||||
long value;
|
||||
unsigned int attrs;
|
||||
bfd_vma pc;
|
||||
int length;
|
||||
{
|
||||
disassemble_info *info = (disassemble_info *) dis_info;
|
||||
|
||||
(*info->fprintf_func) (info->stream, "$%04x", value);
|
||||
}
|
||||
|
||||
static void
|
||||
print_dollarhex_addr16h (cd, dis_info, value, attrs, pc, length)
|
||||
CGEN_CPU_DESC cd;
|
||||
PTR dis_info;
|
||||
long value;
|
||||
unsigned int attrs;
|
||||
bfd_vma pc;
|
||||
int length;
|
||||
{
|
||||
disassemble_info *info = (disassemble_info *) dis_info;
|
||||
|
||||
/* This is a loadh instruction. Shift the value to the left */
|
||||
/* by 8 bits so that disassembled code will reassemble properly. */
|
||||
value = ((value << 8) & 0xFF00);
|
||||
|
||||
(*info->fprintf_func) (info->stream, "$%04x", value);
|
||||
}
|
||||
|
||||
static void
|
||||
print_dollarhex_addr16l (cd, dis_info, value, attrs, pc, length)
|
||||
CGEN_CPU_DESC cd;
|
||||
PTR dis_info;
|
||||
long value;
|
||||
unsigned int attrs;
|
||||
bfd_vma pc;
|
||||
int length;
|
||||
{
|
||||
disassemble_info *info = (disassemble_info *) dis_info;
|
||||
|
||||
(*info->fprintf_func) (info->stream, "$%04x", value);
|
||||
}
|
||||
|
||||
static void
|
||||
print_dollarhex_p (cd, dis_info, value, attrs, pc, length)
|
||||
CGEN_CPU_DESC cd;
|
||||
PTR dis_info;
|
||||
long value;
|
||||
unsigned int attrs;
|
||||
bfd_vma pc;
|
||||
int length;
|
||||
{
|
||||
disassemble_info *info = (disassemble_info *) dis_info;
|
||||
|
||||
value = ((value << 14) & 0x1C000);
|
||||
;value = (value & 0x1FFFF);
|
||||
(*info->fprintf_func) (info->stream, "$%05x", value);
|
||||
}
|
||||
|
||||
static void
|
||||
print_dollarhex_cj (cd, dis_info, value, attrs, pc, length)
|
||||
CGEN_CPU_DESC cd;
|
||||
PTR dis_info;
|
||||
long value;
|
||||
unsigned int attrs;
|
||||
bfd_vma pc;
|
||||
int length;
|
||||
{
|
||||
disassemble_info *info = (disassemble_info *) dis_info;
|
||||
|
||||
value = ((value << 1) & 0x1FFFF);
|
||||
(*info->fprintf_func) (info->stream, "$%05x", value);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
print_decimal (cd, dis_info, value, attrs, pc, length)
|
||||
CGEN_CPU_DESC cd;
|
||||
PTR dis_info;
|
||||
long value;
|
||||
unsigned int attrs;
|
||||
bfd_vma pc;
|
||||
int length;
|
||||
{
|
||||
disassemble_info *info = (disassemble_info *) dis_info;
|
||||
|
||||
(*info->fprintf_func) (info->stream, "%d", value);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* -- */
|
||||
|
||||
void ip2k_cgen_print_operand
|
||||
PARAMS ((CGEN_CPU_DESC, int, PTR, CGEN_FIELDS *,
|
||||
void const *, bfd_vma, int));
|
||||
|
||||
/* Main entry point for printing operands.
|
||||
XINFO is a `void *' and not a `disassemble_info *' to not put a requirement
|
||||
of dis-asm.h on cgen.h.
|
||||
|
||||
This function is basically just a big switch statement. Earlier versions
|
||||
used tables to look up the function to use, but
|
||||
- if the table contains both assembler and disassembler functions then
|
||||
the disassembler contains much of the assembler and vice-versa,
|
||||
- there's a lot of inlining possibilities as things grow,
|
||||
- using a switch statement avoids the function call overhead.
|
||||
|
||||
This function could be moved into `print_insn_normal', but keeping it
|
||||
separate makes clear the interface between `print_insn_normal' and each of
|
||||
the handlers. */
|
||||
|
||||
void
|
||||
ip2k_cgen_print_operand (cd, opindex, xinfo, fields, attrs, pc, length)
|
||||
CGEN_CPU_DESC cd;
|
||||
int opindex;
|
||||
PTR xinfo;
|
||||
CGEN_FIELDS *fields;
|
||||
void const *attrs ATTRIBUTE_UNUSED;
|
||||
bfd_vma pc;
|
||||
int length;
|
||||
{
|
||||
disassemble_info *info = (disassemble_info *) xinfo;
|
||||
|
||||
switch (opindex)
|
||||
{
|
||||
case IP2K_OPERAND_ADDR16CJP :
|
||||
print_dollarhex_cj (cd, info, fields->f_addr16cjp, 0|(1<<CGEN_OPERAND_ABS_ADDR), pc, length);
|
||||
break;
|
||||
case IP2K_OPERAND_ADDR16H :
|
||||
print_dollarhex_addr16h (cd, info, fields->f_imm8, 0, pc, length);
|
||||
break;
|
||||
case IP2K_OPERAND_ADDR16L :
|
||||
print_dollarhex_addr16l (cd, info, fields->f_imm8, 0, pc, length);
|
||||
break;
|
||||
case IP2K_OPERAND_ADDR16P :
|
||||
print_dollarhex_p (cd, info, fields->f_page3, 0, pc, length);
|
||||
break;
|
||||
case IP2K_OPERAND_BITNO :
|
||||
print_decimal (cd, info, fields->f_bitno, 0, pc, length);
|
||||
break;
|
||||
case IP2K_OPERAND_CBIT :
|
||||
print_normal (cd, info, 0, 0, pc, length);
|
||||
break;
|
||||
case IP2K_OPERAND_DCBIT :
|
||||
print_normal (cd, info, 0, 0, pc, length);
|
||||
break;
|
||||
case IP2K_OPERAND_FR :
|
||||
print_fr (cd, info, fields->f_reg, 0|(1<<CGEN_OPERAND_ABS_ADDR), pc, length);
|
||||
break;
|
||||
case IP2K_OPERAND_LIT8 :
|
||||
print_dollarhex8 (cd, info, fields->f_imm8, 0|(1<<CGEN_OPERAND_SIGNED), pc, length);
|
||||
break;
|
||||
case IP2K_OPERAND_PABITS :
|
||||
print_normal (cd, info, 0, 0, pc, length);
|
||||
break;
|
||||
case IP2K_OPERAND_RETI3 :
|
||||
print_dollarhex (cd, info, fields->f_reti3, 0, pc, length);
|
||||
break;
|
||||
case IP2K_OPERAND_ZBIT :
|
||||
print_normal (cd, info, 0, 0, pc, length);
|
||||
break;
|
||||
|
||||
default :
|
||||
/* xgettext:c-format */
|
||||
fprintf (stderr, _("Unrecognized field %d while printing insn.\n"),
|
||||
opindex);
|
||||
abort ();
|
||||
}
|
||||
}
|
||||
|
||||
cgen_print_fn * const ip2k_cgen_print_handlers[] =
|
||||
{
|
||||
print_insn_normal,
|
||||
};
|
||||
|
||||
|
||||
void
|
||||
ip2k_cgen_init_dis (cd)
|
||||
CGEN_CPU_DESC cd;
|
||||
{
|
||||
ip2k_cgen_init_opcode_table (cd);
|
||||
ip2k_cgen_init_ibld_table (cd);
|
||||
cd->print_handlers = & ip2k_cgen_print_handlers[0];
|
||||
cd->print_operand = ip2k_cgen_print_operand;
|
||||
}
|
||||
|
||||
|
||||
/* Default print handler. */
|
||||
|
||||
static void
|
||||
print_normal (cd, dis_info, value, attrs, pc, length)
|
||||
CGEN_CPU_DESC cd ATTRIBUTE_UNUSED;
|
||||
PTR dis_info;
|
||||
long value;
|
||||
unsigned int attrs;
|
||||
bfd_vma pc ATTRIBUTE_UNUSED;
|
||||
int length ATTRIBUTE_UNUSED;
|
||||
{
|
||||
disassemble_info *info = (disassemble_info *) dis_info;
|
||||
|
||||
#ifdef CGEN_PRINT_NORMAL
|
||||
CGEN_PRINT_NORMAL (cd, info, value, attrs, pc, length);
|
||||
#endif
|
||||
|
||||
/* Print the operand as directed by the attributes. */
|
||||
if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_SEM_ONLY))
|
||||
; /* nothing to do */
|
||||
else if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_SIGNED))
|
||||
(*info->fprintf_func) (info->stream, "%ld", value);
|
||||
else
|
||||
(*info->fprintf_func) (info->stream, "0x%lx", value);
|
||||
}
|
||||
|
||||
/* Default address handler. */
|
||||
|
||||
static void
|
||||
print_address (cd, dis_info, value, attrs, pc, length)
|
||||
CGEN_CPU_DESC cd ATTRIBUTE_UNUSED;
|
||||
PTR dis_info;
|
||||
bfd_vma value;
|
||||
unsigned int attrs;
|
||||
bfd_vma pc ATTRIBUTE_UNUSED;
|
||||
int length ATTRIBUTE_UNUSED;
|
||||
{
|
||||
disassemble_info *info = (disassemble_info *) dis_info;
|
||||
|
||||
#ifdef CGEN_PRINT_ADDRESS
|
||||
CGEN_PRINT_ADDRESS (cd, info, value, attrs, pc, length);
|
||||
#endif
|
||||
|
||||
/* Print the operand as directed by the attributes. */
|
||||
if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_SEM_ONLY))
|
||||
; /* nothing to do */
|
||||
else if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_PCREL_ADDR))
|
||||
(*info->print_address_func) (value, info);
|
||||
else if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_ABS_ADDR))
|
||||
(*info->print_address_func) (value, info);
|
||||
else if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_SIGNED))
|
||||
(*info->fprintf_func) (info->stream, "%ld", (long) value);
|
||||
else
|
||||
(*info->fprintf_func) (info->stream, "0x%lx", (long) value);
|
||||
}
|
||||
|
||||
/* Keyword print handler. */
|
||||
|
||||
static void
|
||||
print_keyword (cd, dis_info, keyword_table, value, attrs)
|
||||
CGEN_CPU_DESC cd ATTRIBUTE_UNUSED;
|
||||
PTR dis_info;
|
||||
CGEN_KEYWORD *keyword_table;
|
||||
long value;
|
||||
unsigned int attrs ATTRIBUTE_UNUSED;
|
||||
{
|
||||
disassemble_info *info = (disassemble_info *) dis_info;
|
||||
const CGEN_KEYWORD_ENTRY *ke;
|
||||
|
||||
ke = cgen_keyword_lookup_value (keyword_table, value);
|
||||
if (ke != NULL)
|
||||
(*info->fprintf_func) (info->stream, "%s", ke->name);
|
||||
else
|
||||
(*info->fprintf_func) (info->stream, "???");
|
||||
}
|
||||
|
||||
/* Default insn printer.
|
||||
|
||||
DIS_INFO is defined as `PTR' so the disassembler needn't know anything
|
||||
about disassemble_info. */
|
||||
|
||||
static void
|
||||
print_insn_normal (cd, dis_info, insn, fields, pc, length)
|
||||
CGEN_CPU_DESC cd;
|
||||
PTR dis_info;
|
||||
const CGEN_INSN *insn;
|
||||
CGEN_FIELDS *fields;
|
||||
bfd_vma pc;
|
||||
int length;
|
||||
{
|
||||
const CGEN_SYNTAX *syntax = CGEN_INSN_SYNTAX (insn);
|
||||
disassemble_info *info = (disassemble_info *) dis_info;
|
||||
const CGEN_SYNTAX_CHAR_TYPE *syn;
|
||||
|
||||
CGEN_INIT_PRINT (cd);
|
||||
|
||||
for (syn = CGEN_SYNTAX_STRING (syntax); *syn; ++syn)
|
||||
{
|
||||
if (CGEN_SYNTAX_MNEMONIC_P (*syn))
|
||||
{
|
||||
(*info->fprintf_func) (info->stream, "%s", CGEN_INSN_MNEMONIC (insn));
|
||||
continue;
|
||||
}
|
||||
if (CGEN_SYNTAX_CHAR_P (*syn))
|
||||
{
|
||||
(*info->fprintf_func) (info->stream, "%c", CGEN_SYNTAX_CHAR (*syn));
|
||||
continue;
|
||||
}
|
||||
|
||||
/* We have an operand. */
|
||||
ip2k_cgen_print_operand (cd, CGEN_SYNTAX_FIELD (*syn), info,
|
||||
fields, CGEN_INSN_ATTRS (insn), pc, length);
|
||||
}
|
||||
}
|
||||
|
||||
/* Subroutine of print_insn. Reads an insn into the given buffers and updates
|
||||
the extract info.
|
||||
Returns 0 if all is well, non-zero otherwise. */
|
||||
|
||||
static int
|
||||
read_insn (cd, pc, info, buf, buflen, ex_info, insn_value)
|
||||
CGEN_CPU_DESC cd ATTRIBUTE_UNUSED;
|
||||
bfd_vma pc;
|
||||
disassemble_info *info;
|
||||
char *buf;
|
||||
int buflen;
|
||||
CGEN_EXTRACT_INFO *ex_info;
|
||||
unsigned long *insn_value;
|
||||
{
|
||||
int status = (*info->read_memory_func) (pc, buf, buflen, info);
|
||||
if (status != 0)
|
||||
{
|
||||
(*info->memory_error_func) (status, pc, info);
|
||||
return -1;
|
||||
}
|
||||
|
||||
ex_info->dis_info = info;
|
||||
ex_info->valid = (1 << buflen) - 1;
|
||||
ex_info->insn_bytes = buf;
|
||||
|
||||
*insn_value = bfd_get_bits (buf, buflen * 8, info->endian == BFD_ENDIAN_BIG);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Utility to print an insn.
|
||||
BUF is the base part of the insn, target byte order, BUFLEN bytes long.
|
||||
The result is the size of the insn in bytes or zero for an unknown insn
|
||||
or -1 if an error occurs fetching data (memory_error_func will have
|
||||
been called). */
|
||||
|
||||
static int
|
||||
print_insn (cd, pc, info, buf, buflen)
|
||||
CGEN_CPU_DESC cd;
|
||||
bfd_vma pc;
|
||||
disassemble_info *info;
|
||||
char *buf;
|
||||
unsigned int buflen;
|
||||
{
|
||||
CGEN_INSN_INT insn_value;
|
||||
const CGEN_INSN_LIST *insn_list;
|
||||
CGEN_EXTRACT_INFO ex_info;
|
||||
int basesize;
|
||||
|
||||
/* Extract base part of instruction, just in case CGEN_DIS_* uses it. */
|
||||
basesize = cd->base_insn_bitsize < buflen * 8 ?
|
||||
cd->base_insn_bitsize : buflen * 8;
|
||||
insn_value = cgen_get_insn_value (cd, buf, basesize);
|
||||
|
||||
|
||||
/* Fill in ex_info fields like read_insn would. Don't actually call
|
||||
read_insn, since the incoming buffer is already read (and possibly
|
||||
modified a la m32r). */
|
||||
ex_info.valid = (1 << buflen) - 1;
|
||||
ex_info.dis_info = info;
|
||||
ex_info.insn_bytes = buf;
|
||||
|
||||
/* The instructions are stored in hash lists.
|
||||
Pick the first one and keep trying until we find the right one. */
|
||||
|
||||
insn_list = CGEN_DIS_LOOKUP_INSN (cd, buf, insn_value);
|
||||
while (insn_list != NULL)
|
||||
{
|
||||
const CGEN_INSN *insn = insn_list->insn;
|
||||
CGEN_FIELDS fields;
|
||||
int length;
|
||||
unsigned long insn_value_cropped;
|
||||
|
||||
#ifdef CGEN_VALIDATE_INSN_SUPPORTED
|
||||
/* Not needed as insn shouldn't be in hash lists if not supported. */
|
||||
/* Supported by this cpu? */
|
||||
if (! ip2k_cgen_insn_supported (cd, insn))
|
||||
{
|
||||
insn_list = CGEN_DIS_NEXT_INSN (insn_list);
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Basic bit mask must be correct. */
|
||||
/* ??? May wish to allow target to defer this check until the extract
|
||||
handler. */
|
||||
|
||||
/* Base size may exceed this instruction's size. Extract the
|
||||
relevant part from the buffer. */
|
||||
if ((unsigned) (CGEN_INSN_BITSIZE (insn) / 8) < buflen &&
|
||||
(unsigned) (CGEN_INSN_BITSIZE (insn) / 8) <= sizeof (unsigned long))
|
||||
insn_value_cropped = bfd_get_bits (buf, CGEN_INSN_BITSIZE (insn),
|
||||
info->endian == BFD_ENDIAN_BIG);
|
||||
else
|
||||
insn_value_cropped = insn_value;
|
||||
|
||||
if ((insn_value_cropped & CGEN_INSN_BASE_MASK (insn))
|
||||
== CGEN_INSN_BASE_VALUE (insn))
|
||||
{
|
||||
/* Printing is handled in two passes. The first pass parses the
|
||||
machine insn and extracts the fields. The second pass prints
|
||||
them. */
|
||||
|
||||
/* Make sure the entire insn is loaded into insn_value, if it
|
||||
can fit. */
|
||||
if (((unsigned) CGEN_INSN_BITSIZE (insn) > cd->base_insn_bitsize) &&
|
||||
(unsigned) (CGEN_INSN_BITSIZE (insn) / 8) <= sizeof (unsigned long))
|
||||
{
|
||||
unsigned long full_insn_value;
|
||||
int rc = read_insn (cd, pc, info, buf,
|
||||
CGEN_INSN_BITSIZE (insn) / 8,
|
||||
& ex_info, & full_insn_value);
|
||||
if (rc != 0)
|
||||
return rc;
|
||||
length = CGEN_EXTRACT_FN (cd, insn)
|
||||
(cd, insn, &ex_info, full_insn_value, &fields, pc);
|
||||
}
|
||||
else
|
||||
length = CGEN_EXTRACT_FN (cd, insn)
|
||||
(cd, insn, &ex_info, insn_value_cropped, &fields, pc);
|
||||
|
||||
/* length < 0 -> error */
|
||||
if (length < 0)
|
||||
return length;
|
||||
if (length > 0)
|
||||
{
|
||||
CGEN_PRINT_FN (cd, insn) (cd, info, insn, &fields, pc, length);
|
||||
/* length is in bits, result is in bytes */
|
||||
return length / 8;
|
||||
}
|
||||
}
|
||||
|
||||
insn_list = CGEN_DIS_NEXT_INSN (insn_list);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Default value for CGEN_PRINT_INSN.
|
||||
The result is the size of the insn in bytes or zero for an unknown insn
|
||||
or -1 if an error occured fetching bytes. */
|
||||
|
||||
#ifndef CGEN_PRINT_INSN
|
||||
#define CGEN_PRINT_INSN default_print_insn
|
||||
#endif
|
||||
|
||||
static int
|
||||
default_print_insn (cd, pc, info)
|
||||
CGEN_CPU_DESC cd;
|
||||
bfd_vma pc;
|
||||
disassemble_info *info;
|
||||
{
|
||||
char buf[CGEN_MAX_INSN_SIZE];
|
||||
int buflen;
|
||||
int status;
|
||||
|
||||
/* Attempt to read the base part of the insn. */
|
||||
buflen = cd->base_insn_bitsize / 8;
|
||||
status = (*info->read_memory_func) (pc, buf, buflen, info);
|
||||
|
||||
/* Try again with the minimum part, if min < base. */
|
||||
if (status != 0 && (cd->min_insn_bitsize < cd->base_insn_bitsize))
|
||||
{
|
||||
buflen = cd->min_insn_bitsize / 8;
|
||||
status = (*info->read_memory_func) (pc, buf, buflen, info);
|
||||
}
|
||||
|
||||
if (status != 0)
|
||||
{
|
||||
(*info->memory_error_func) (status, pc, info);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return print_insn (cd, pc, info, buf, buflen);
|
||||
}
|
||||
|
||||
/* Main entry point.
|
||||
Print one instruction from PC on INFO->STREAM.
|
||||
Return the size of the instruction (in bytes). */
|
||||
|
||||
typedef struct cpu_desc_list {
|
||||
struct cpu_desc_list *next;
|
||||
int isa;
|
||||
int mach;
|
||||
int endian;
|
||||
CGEN_CPU_DESC cd;
|
||||
} cpu_desc_list;
|
||||
|
||||
int
|
||||
print_insn_ip2k (pc, info)
|
||||
bfd_vma pc;
|
||||
disassemble_info *info;
|
||||
{
|
||||
static cpu_desc_list *cd_list = 0;
|
||||
cpu_desc_list *cl = 0;
|
||||
static CGEN_CPU_DESC cd = 0;
|
||||
static int prev_isa;
|
||||
static int prev_mach;
|
||||
static int prev_endian;
|
||||
int length;
|
||||
int isa,mach;
|
||||
int endian = (info->endian == BFD_ENDIAN_BIG
|
||||
? CGEN_ENDIAN_BIG
|
||||
: CGEN_ENDIAN_LITTLE);
|
||||
enum bfd_architecture arch;
|
||||
|
||||
/* ??? gdb will set mach but leave the architecture as "unknown" */
|
||||
#ifndef CGEN_BFD_ARCH
|
||||
#define CGEN_BFD_ARCH bfd_arch_ip2k
|
||||
#endif
|
||||
arch = info->arch;
|
||||
if (arch == bfd_arch_unknown)
|
||||
arch = CGEN_BFD_ARCH;
|
||||
|
||||
/* There's no standard way to compute the machine or isa number
|
||||
so we leave it to the target. */
|
||||
#ifdef CGEN_COMPUTE_MACH
|
||||
mach = CGEN_COMPUTE_MACH (info);
|
||||
#else
|
||||
mach = info->mach;
|
||||
#endif
|
||||
|
||||
#ifdef CGEN_COMPUTE_ISA
|
||||
isa = CGEN_COMPUTE_ISA (info);
|
||||
#else
|
||||
isa = info->insn_sets;
|
||||
#endif
|
||||
|
||||
/* If we've switched cpu's, try to find a handle we've used before */
|
||||
if (cd
|
||||
&& (isa != prev_isa
|
||||
|| mach != prev_mach
|
||||
|| endian != prev_endian))
|
||||
{
|
||||
cd = 0;
|
||||
for (cl = cd_list; cl; cl = cl->next)
|
||||
{
|
||||
if (cl->isa == isa &&
|
||||
cl->mach == mach &&
|
||||
cl->endian == endian)
|
||||
{
|
||||
cd = cl->cd;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* If we haven't initialized yet, initialize the opcode table. */
|
||||
if (! cd)
|
||||
{
|
||||
const bfd_arch_info_type *arch_type = bfd_lookup_arch (arch, mach);
|
||||
const char *mach_name;
|
||||
|
||||
if (!arch_type)
|
||||
abort ();
|
||||
mach_name = arch_type->printable_name;
|
||||
|
||||
prev_isa = isa;
|
||||
prev_mach = mach;
|
||||
prev_endian = endian;
|
||||
cd = ip2k_cgen_cpu_open (CGEN_CPU_OPEN_ISAS, prev_isa,
|
||||
CGEN_CPU_OPEN_BFDMACH, mach_name,
|
||||
CGEN_CPU_OPEN_ENDIAN, prev_endian,
|
||||
CGEN_CPU_OPEN_END);
|
||||
if (!cd)
|
||||
abort ();
|
||||
|
||||
/* save this away for future reference */
|
||||
cl = xmalloc (sizeof (struct cpu_desc_list));
|
||||
cl->cd = cd;
|
||||
cl->isa = isa;
|
||||
cl->mach = mach;
|
||||
cl->endian = endian;
|
||||
cl->next = cd_list;
|
||||
cd_list = cl;
|
||||
|
||||
ip2k_cgen_init_dis (cd);
|
||||
}
|
||||
|
||||
/* We try to have as much common code as possible.
|
||||
But at this point some targets need to take over. */
|
||||
/* ??? Some targets may need a hook elsewhere. Try to avoid this,
|
||||
but if not possible try to move this hook elsewhere rather than
|
||||
have two hooks. */
|
||||
length = CGEN_PRINT_INSN (cd, pc, info);
|
||||
if (length > 0)
|
||||
return length;
|
||||
if (length < 0)
|
||||
return -1;
|
||||
|
||||
(*info->fprintf_func) (info->stream, UNKNOWN_INSN_MSG);
|
||||
return cd->default_insn_bitsize / 8;
|
||||
}
|
||||
952
opcodes/ip2k-ibld.c
Normal file
952
opcodes/ip2k-ibld.c
Normal file
@@ -0,0 +1,952 @@
|
||||
/* Instruction building/extraction support for ip2k. -*- C -*-
|
||||
|
||||
THIS FILE IS MACHINE GENERATED WITH CGEN: Cpu tools GENerator.
|
||||
- the resultant file is machine generated, cgen-ibld.in isn't
|
||||
|
||||
Copyright 1996, 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of the GNU Binutils and GDB, the GNU debugger.
|
||||
|
||||
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. */
|
||||
|
||||
/* ??? Eventually more and more of this stuff can go to cpu-independent files.
|
||||
Keep that in mind. */
|
||||
|
||||
#include "sysdep.h"
|
||||
#include <stdio.h>
|
||||
#include "ansidecl.h"
|
||||
#include "dis-asm.h"
|
||||
#include "bfd.h"
|
||||
#include "symcat.h"
|
||||
#include "ip2k-desc.h"
|
||||
#include "ip2k-opc.h"
|
||||
#include "opintl.h"
|
||||
#include "safe-ctype.h"
|
||||
|
||||
#undef min
|
||||
#define min(a,b) ((a) < (b) ? (a) : (b))
|
||||
#undef max
|
||||
#define max(a,b) ((a) > (b) ? (a) : (b))
|
||||
|
||||
/* Used by the ifield rtx function. */
|
||||
#define FLD(f) (fields->f)
|
||||
|
||||
static const char * insert_normal
|
||||
PARAMS ((CGEN_CPU_DESC, long, unsigned int, unsigned int, unsigned int,
|
||||
unsigned int, unsigned int, unsigned int, CGEN_INSN_BYTES_PTR));
|
||||
static const char * insert_insn_normal
|
||||
PARAMS ((CGEN_CPU_DESC, const CGEN_INSN *,
|
||||
CGEN_FIELDS *, CGEN_INSN_BYTES_PTR, bfd_vma));
|
||||
static int extract_normal
|
||||
PARAMS ((CGEN_CPU_DESC, CGEN_EXTRACT_INFO *, CGEN_INSN_INT,
|
||||
unsigned int, unsigned int, unsigned int, unsigned int,
|
||||
unsigned int, unsigned int, bfd_vma, long *));
|
||||
static int extract_insn_normal
|
||||
PARAMS ((CGEN_CPU_DESC, const CGEN_INSN *, CGEN_EXTRACT_INFO *,
|
||||
CGEN_INSN_INT, CGEN_FIELDS *, bfd_vma));
|
||||
#if CGEN_INT_INSN_P
|
||||
static void put_insn_int_value
|
||||
PARAMS ((CGEN_CPU_DESC, CGEN_INSN_BYTES_PTR, int, int, CGEN_INSN_INT));
|
||||
#endif
|
||||
#if ! CGEN_INT_INSN_P
|
||||
static CGEN_INLINE void insert_1
|
||||
PARAMS ((CGEN_CPU_DESC, unsigned long, int, int, int, unsigned char *));
|
||||
static CGEN_INLINE int fill_cache
|
||||
PARAMS ((CGEN_CPU_DESC, CGEN_EXTRACT_INFO *, int, int, bfd_vma));
|
||||
static CGEN_INLINE long extract_1
|
||||
PARAMS ((CGEN_CPU_DESC, CGEN_EXTRACT_INFO *, int, int, int,
|
||||
unsigned char *, bfd_vma));
|
||||
#endif
|
||||
|
||||
/* Operand insertion. */
|
||||
|
||||
#if ! CGEN_INT_INSN_P
|
||||
|
||||
/* Subroutine of insert_normal. */
|
||||
|
||||
static CGEN_INLINE void
|
||||
insert_1 (cd, value, start, length, word_length, bufp)
|
||||
CGEN_CPU_DESC cd;
|
||||
unsigned long value;
|
||||
int start,length,word_length;
|
||||
unsigned char *bufp;
|
||||
{
|
||||
unsigned long x,mask;
|
||||
int shift;
|
||||
|
||||
x = cgen_get_insn_value (cd, bufp, word_length);
|
||||
|
||||
/* Written this way to avoid undefined behaviour. */
|
||||
mask = (((1L << (length - 1)) - 1) << 1) | 1;
|
||||
if (CGEN_INSN_LSB0_P)
|
||||
shift = (start + 1) - length;
|
||||
else
|
||||
shift = (word_length - (start + length));
|
||||
x = (x & ~(mask << shift)) | ((value & mask) << shift);
|
||||
|
||||
cgen_put_insn_value (cd, bufp, word_length, (bfd_vma) x);
|
||||
}
|
||||
|
||||
#endif /* ! CGEN_INT_INSN_P */
|
||||
|
||||
/* Default insertion routine.
|
||||
|
||||
ATTRS is a mask of the boolean attributes.
|
||||
WORD_OFFSET is the offset in bits from the start of the insn of the value.
|
||||
WORD_LENGTH is the length of the word in bits in which the value resides.
|
||||
START is the starting bit number in the word, architecture origin.
|
||||
LENGTH is the length of VALUE in bits.
|
||||
TOTAL_LENGTH is the total length of the insn in bits.
|
||||
|
||||
The result is an error message or NULL if success. */
|
||||
|
||||
/* ??? This duplicates functionality with bfd's howto table and
|
||||
bfd_install_relocation. */
|
||||
/* ??? This doesn't handle bfd_vma's. Create another function when
|
||||
necessary. */
|
||||
|
||||
static const char *
|
||||
insert_normal (cd, value, attrs, word_offset, start, length, word_length,
|
||||
total_length, buffer)
|
||||
CGEN_CPU_DESC cd;
|
||||
long value;
|
||||
unsigned int attrs;
|
||||
unsigned int word_offset, start, length, word_length, total_length;
|
||||
CGEN_INSN_BYTES_PTR buffer;
|
||||
{
|
||||
static char errbuf[100];
|
||||
/* Written this way to avoid undefined behaviour. */
|
||||
unsigned long mask = (((1L << (length - 1)) - 1) << 1) | 1;
|
||||
|
||||
/* If LENGTH is zero, this operand doesn't contribute to the value. */
|
||||
if (length == 0)
|
||||
return NULL;
|
||||
|
||||
#if 0
|
||||
if (CGEN_INT_INSN_P
|
||||
&& word_offset != 0)
|
||||
abort ();
|
||||
#endif
|
||||
|
||||
if (word_length > 32)
|
||||
abort ();
|
||||
|
||||
/* For architectures with insns smaller than the base-insn-bitsize,
|
||||
word_length may be too big. */
|
||||
if (cd->min_insn_bitsize < cd->base_insn_bitsize)
|
||||
{
|
||||
if (word_offset == 0
|
||||
&& word_length > total_length)
|
||||
word_length = total_length;
|
||||
}
|
||||
|
||||
/* Ensure VALUE will fit. */
|
||||
if (CGEN_BOOL_ATTR (attrs, CGEN_IFLD_SIGN_OPT))
|
||||
{
|
||||
long minval = - (1L << (length - 1));
|
||||
unsigned long maxval = mask;
|
||||
|
||||
if ((value > 0 && (unsigned long) value > maxval)
|
||||
|| value < minval)
|
||||
{
|
||||
/* xgettext:c-format */
|
||||
sprintf (errbuf,
|
||||
_("operand out of range (%ld not between %ld and %lu)"),
|
||||
value, minval, maxval);
|
||||
return errbuf;
|
||||
}
|
||||
}
|
||||
else if (! CGEN_BOOL_ATTR (attrs, CGEN_IFLD_SIGNED))
|
||||
{
|
||||
unsigned long maxval = mask;
|
||||
|
||||
if ((unsigned long) value > maxval)
|
||||
{
|
||||
/* xgettext:c-format */
|
||||
sprintf (errbuf,
|
||||
_("operand out of range (%lu not between 0 and %lu)"),
|
||||
value, maxval);
|
||||
return errbuf;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (! cgen_signed_overflow_ok_p (cd))
|
||||
{
|
||||
long minval = - (1L << (length - 1));
|
||||
long maxval = (1L << (length - 1)) - 1;
|
||||
|
||||
if (value < minval || value > maxval)
|
||||
{
|
||||
sprintf
|
||||
/* xgettext:c-format */
|
||||
(errbuf, _("operand out of range (%ld not between %ld and %ld)"),
|
||||
value, minval, maxval);
|
||||
return errbuf;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if CGEN_INT_INSN_P
|
||||
|
||||
{
|
||||
int shift;
|
||||
|
||||
if (CGEN_INSN_LSB0_P)
|
||||
shift = (word_offset + start + 1) - length;
|
||||
else
|
||||
shift = total_length - (word_offset + start + length);
|
||||
*buffer = (*buffer & ~(mask << shift)) | ((value & mask) << shift);
|
||||
}
|
||||
|
||||
#else /* ! CGEN_INT_INSN_P */
|
||||
|
||||
{
|
||||
unsigned char *bufp = (unsigned char *) buffer + word_offset / 8;
|
||||
|
||||
insert_1 (cd, value, start, length, word_length, bufp);
|
||||
}
|
||||
|
||||
#endif /* ! CGEN_INT_INSN_P */
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Default insn builder (insert handler).
|
||||
The instruction is recorded in CGEN_INT_INSN_P byte order (meaning
|
||||
that if CGEN_INSN_BYTES_PTR is an int * and thus, the value is
|
||||
recorded in host byte order, otherwise BUFFER is an array of bytes
|
||||
and the value is recorded in target byte order).
|
||||
The result is an error message or NULL if success. */
|
||||
|
||||
static const char *
|
||||
insert_insn_normal (cd, insn, fields, buffer, pc)
|
||||
CGEN_CPU_DESC cd;
|
||||
const CGEN_INSN * insn;
|
||||
CGEN_FIELDS * fields;
|
||||
CGEN_INSN_BYTES_PTR buffer;
|
||||
bfd_vma pc;
|
||||
{
|
||||
const CGEN_SYNTAX *syntax = CGEN_INSN_SYNTAX (insn);
|
||||
unsigned long value;
|
||||
const CGEN_SYNTAX_CHAR_TYPE * syn;
|
||||
|
||||
CGEN_INIT_INSERT (cd);
|
||||
value = CGEN_INSN_BASE_VALUE (insn);
|
||||
|
||||
/* If we're recording insns as numbers (rather than a string of bytes),
|
||||
target byte order handling is deferred until later. */
|
||||
|
||||
#if CGEN_INT_INSN_P
|
||||
|
||||
put_insn_int_value (cd, buffer, cd->base_insn_bitsize,
|
||||
CGEN_FIELDS_BITSIZE (fields), value);
|
||||
|
||||
#else
|
||||
|
||||
cgen_put_insn_value (cd, buffer, min ((unsigned) cd->base_insn_bitsize,
|
||||
(unsigned) CGEN_FIELDS_BITSIZE (fields)),
|
||||
value);
|
||||
|
||||
#endif /* ! CGEN_INT_INSN_P */
|
||||
|
||||
/* ??? It would be better to scan the format's fields.
|
||||
Still need to be able to insert a value based on the operand though;
|
||||
e.g. storing a branch displacement that got resolved later.
|
||||
Needs more thought first. */
|
||||
|
||||
for (syn = CGEN_SYNTAX_STRING (syntax); * syn; ++ syn)
|
||||
{
|
||||
const char *errmsg;
|
||||
|
||||
if (CGEN_SYNTAX_CHAR_P (* syn))
|
||||
continue;
|
||||
|
||||
errmsg = (* cd->insert_operand) (cd, CGEN_SYNTAX_FIELD (*syn),
|
||||
fields, buffer, pc);
|
||||
if (errmsg)
|
||||
return errmsg;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#if CGEN_INT_INSN_P
|
||||
/* Cover function to store an insn value into an integral insn. Must go here
|
||||
because it needs <prefix>-desc.h for CGEN_INT_INSN_P. */
|
||||
|
||||
static void
|
||||
put_insn_int_value (cd, buf, length, insn_length, value)
|
||||
CGEN_CPU_DESC cd ATTRIBUTE_UNUSED;
|
||||
CGEN_INSN_BYTES_PTR buf;
|
||||
int length;
|
||||
int insn_length;
|
||||
CGEN_INSN_INT value;
|
||||
{
|
||||
/* For architectures with insns smaller than the base-insn-bitsize,
|
||||
length may be too big. */
|
||||
if (length > insn_length)
|
||||
*buf = value;
|
||||
else
|
||||
{
|
||||
int shift = insn_length - length;
|
||||
/* Written this way to avoid undefined behaviour. */
|
||||
CGEN_INSN_INT mask = (((1L << (length - 1)) - 1) << 1) | 1;
|
||||
*buf = (*buf & ~(mask << shift)) | ((value & mask) << shift);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Operand extraction. */
|
||||
|
||||
#if ! CGEN_INT_INSN_P
|
||||
|
||||
/* Subroutine of extract_normal.
|
||||
Ensure sufficient bytes are cached in EX_INFO.
|
||||
OFFSET is the offset in bytes from the start of the insn of the value.
|
||||
BYTES is the length of the needed value.
|
||||
Returns 1 for success, 0 for failure. */
|
||||
|
||||
static CGEN_INLINE int
|
||||
fill_cache (cd, ex_info, offset, bytes, pc)
|
||||
CGEN_CPU_DESC cd ATTRIBUTE_UNUSED;
|
||||
CGEN_EXTRACT_INFO *ex_info;
|
||||
int offset, bytes;
|
||||
bfd_vma pc;
|
||||
{
|
||||
/* It's doubtful that the middle part has already been fetched so
|
||||
we don't optimize that case. kiss. */
|
||||
unsigned int mask;
|
||||
disassemble_info *info = (disassemble_info *) ex_info->dis_info;
|
||||
|
||||
/* First do a quick check. */
|
||||
mask = (1 << bytes) - 1;
|
||||
if (((ex_info->valid >> offset) & mask) == mask)
|
||||
return 1;
|
||||
|
||||
/* Search for the first byte we need to read. */
|
||||
for (mask = 1 << offset; bytes > 0; --bytes, ++offset, mask <<= 1)
|
||||
if (! (mask & ex_info->valid))
|
||||
break;
|
||||
|
||||
if (bytes)
|
||||
{
|
||||
int status;
|
||||
|
||||
pc += offset;
|
||||
status = (*info->read_memory_func)
|
||||
(pc, ex_info->insn_bytes + offset, bytes, info);
|
||||
|
||||
if (status != 0)
|
||||
{
|
||||
(*info->memory_error_func) (status, pc, info);
|
||||
return 0;
|
||||
}
|
||||
|
||||
ex_info->valid |= ((1 << bytes) - 1) << offset;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Subroutine of extract_normal. */
|
||||
|
||||
static CGEN_INLINE long
|
||||
extract_1 (cd, ex_info, start, length, word_length, bufp, pc)
|
||||
CGEN_CPU_DESC cd;
|
||||
CGEN_EXTRACT_INFO *ex_info ATTRIBUTE_UNUSED;
|
||||
int start,length,word_length;
|
||||
unsigned char *bufp;
|
||||
bfd_vma pc ATTRIBUTE_UNUSED;
|
||||
{
|
||||
unsigned long x;
|
||||
int shift;
|
||||
#if 0
|
||||
int big_p = CGEN_CPU_INSN_ENDIAN (cd) == CGEN_ENDIAN_BIG;
|
||||
#endif
|
||||
x = cgen_get_insn_value (cd, bufp, word_length);
|
||||
|
||||
if (CGEN_INSN_LSB0_P)
|
||||
shift = (start + 1) - length;
|
||||
else
|
||||
shift = (word_length - (start + length));
|
||||
return x >> shift;
|
||||
}
|
||||
|
||||
#endif /* ! CGEN_INT_INSN_P */
|
||||
|
||||
/* Default extraction routine.
|
||||
|
||||
INSN_VALUE is the first base_insn_bitsize bits of the insn in host order,
|
||||
or sometimes less for cases like the m32r where the base insn size is 32
|
||||
but some insns are 16 bits.
|
||||
ATTRS is a mask of the boolean attributes. We only need `SIGNED',
|
||||
but for generality we take a bitmask of all of them.
|
||||
WORD_OFFSET is the offset in bits from the start of the insn of the value.
|
||||
WORD_LENGTH is the length of the word in bits in which the value resides.
|
||||
START is the starting bit number in the word, architecture origin.
|
||||
LENGTH is the length of VALUE in bits.
|
||||
TOTAL_LENGTH is the total length of the insn in bits.
|
||||
|
||||
Returns 1 for success, 0 for failure. */
|
||||
|
||||
/* ??? The return code isn't properly used. wip. */
|
||||
|
||||
/* ??? This doesn't handle bfd_vma's. Create another function when
|
||||
necessary. */
|
||||
|
||||
static int
|
||||
extract_normal (cd, ex_info, insn_value, attrs, word_offset, start, length,
|
||||
word_length, total_length, pc, valuep)
|
||||
CGEN_CPU_DESC cd;
|
||||
#if ! CGEN_INT_INSN_P
|
||||
CGEN_EXTRACT_INFO *ex_info;
|
||||
#else
|
||||
CGEN_EXTRACT_INFO *ex_info ATTRIBUTE_UNUSED;
|
||||
#endif
|
||||
CGEN_INSN_INT insn_value;
|
||||
unsigned int attrs;
|
||||
unsigned int word_offset, start, length, word_length, total_length;
|
||||
#if ! CGEN_INT_INSN_P
|
||||
bfd_vma pc;
|
||||
#else
|
||||
bfd_vma pc ATTRIBUTE_UNUSED;
|
||||
#endif
|
||||
long *valuep;
|
||||
{
|
||||
long value, mask;
|
||||
|
||||
/* If LENGTH is zero, this operand doesn't contribute to the value
|
||||
so give it a standard value of zero. */
|
||||
if (length == 0)
|
||||
{
|
||||
*valuep = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
#if 0
|
||||
if (CGEN_INT_INSN_P
|
||||
&& word_offset != 0)
|
||||
abort ();
|
||||
#endif
|
||||
|
||||
if (word_length > 32)
|
||||
abort ();
|
||||
|
||||
/* For architectures with insns smaller than the insn-base-bitsize,
|
||||
word_length may be too big. */
|
||||
if (cd->min_insn_bitsize < cd->base_insn_bitsize)
|
||||
{
|
||||
if (word_offset == 0
|
||||
&& word_length > total_length)
|
||||
word_length = total_length;
|
||||
}
|
||||
|
||||
/* Does the value reside in INSN_VALUE, and at the right alignment? */
|
||||
|
||||
if (CGEN_INT_INSN_P || (word_offset == 0 && word_length == total_length))
|
||||
{
|
||||
if (CGEN_INSN_LSB0_P)
|
||||
value = insn_value >> ((word_offset + start + 1) - length);
|
||||
else
|
||||
value = insn_value >> (total_length - ( word_offset + start + length));
|
||||
}
|
||||
|
||||
#if ! CGEN_INT_INSN_P
|
||||
|
||||
else
|
||||
{
|
||||
unsigned char *bufp = ex_info->insn_bytes + word_offset / 8;
|
||||
|
||||
if (word_length > 32)
|
||||
abort ();
|
||||
|
||||
if (fill_cache (cd, ex_info, word_offset / 8, word_length / 8, pc) == 0)
|
||||
return 0;
|
||||
|
||||
value = extract_1 (cd, ex_info, start, length, word_length, bufp, pc);
|
||||
}
|
||||
|
||||
#endif /* ! CGEN_INT_INSN_P */
|
||||
|
||||
/* Written this way to avoid undefined behaviour. */
|
||||
mask = (((1L << (length - 1)) - 1) << 1) | 1;
|
||||
|
||||
value &= mask;
|
||||
/* sign extend? */
|
||||
if (CGEN_BOOL_ATTR (attrs, CGEN_IFLD_SIGNED)
|
||||
&& (value & (1L << (length - 1))))
|
||||
value |= ~mask;
|
||||
|
||||
*valuep = value;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Default insn extractor.
|
||||
|
||||
INSN_VALUE is the first base_insn_bitsize bits, translated to host order.
|
||||
The extracted fields are stored in FIELDS.
|
||||
EX_INFO is used to handle reading variable length insns.
|
||||
Return the length of the insn in bits, or 0 if no match,
|
||||
or -1 if an error occurs fetching data (memory_error_func will have
|
||||
been called). */
|
||||
|
||||
static int
|
||||
extract_insn_normal (cd, insn, ex_info, insn_value, fields, pc)
|
||||
CGEN_CPU_DESC cd;
|
||||
const CGEN_INSN *insn;
|
||||
CGEN_EXTRACT_INFO *ex_info;
|
||||
CGEN_INSN_INT insn_value;
|
||||
CGEN_FIELDS *fields;
|
||||
bfd_vma pc;
|
||||
{
|
||||
const CGEN_SYNTAX *syntax = CGEN_INSN_SYNTAX (insn);
|
||||
const CGEN_SYNTAX_CHAR_TYPE *syn;
|
||||
|
||||
CGEN_FIELDS_BITSIZE (fields) = CGEN_INSN_BITSIZE (insn);
|
||||
|
||||
CGEN_INIT_EXTRACT (cd);
|
||||
|
||||
for (syn = CGEN_SYNTAX_STRING (syntax); *syn; ++syn)
|
||||
{
|
||||
int length;
|
||||
|
||||
if (CGEN_SYNTAX_CHAR_P (*syn))
|
||||
continue;
|
||||
|
||||
length = (* cd->extract_operand) (cd, CGEN_SYNTAX_FIELD (*syn),
|
||||
ex_info, insn_value, fields, pc);
|
||||
if (length <= 0)
|
||||
return length;
|
||||
}
|
||||
|
||||
/* We recognized and successfully extracted this insn. */
|
||||
return CGEN_INSN_BITSIZE (insn);
|
||||
}
|
||||
|
||||
/* machine generated code added here */
|
||||
|
||||
const char * ip2k_cgen_insert_operand
|
||||
PARAMS ((CGEN_CPU_DESC, int, CGEN_FIELDS *, CGEN_INSN_BYTES_PTR, bfd_vma));
|
||||
|
||||
/* Main entry point for operand insertion.
|
||||
|
||||
This function is basically just a big switch statement. Earlier versions
|
||||
used tables to look up the function to use, but
|
||||
- if the table contains both assembler and disassembler functions then
|
||||
the disassembler contains much of the assembler and vice-versa,
|
||||
- there's a lot of inlining possibilities as things grow,
|
||||
- using a switch statement avoids the function call overhead.
|
||||
|
||||
This function could be moved into `parse_insn_normal', but keeping it
|
||||
separate makes clear the interface between `parse_insn_normal' and each of
|
||||
the handlers. It's also needed by GAS to insert operands that couldn't be
|
||||
resolved during parsing. */
|
||||
|
||||
const char *
|
||||
ip2k_cgen_insert_operand (cd, opindex, fields, buffer, pc)
|
||||
CGEN_CPU_DESC cd;
|
||||
int opindex;
|
||||
CGEN_FIELDS * fields;
|
||||
CGEN_INSN_BYTES_PTR buffer;
|
||||
bfd_vma pc ATTRIBUTE_UNUSED;
|
||||
{
|
||||
const char * errmsg = NULL;
|
||||
unsigned int total_length = CGEN_FIELDS_BITSIZE (fields);
|
||||
|
||||
switch (opindex)
|
||||
{
|
||||
case IP2K_OPERAND_ADDR16CJP :
|
||||
errmsg = insert_normal (cd, fields->f_addr16cjp, 0|(1<<CGEN_IFLD_ABS_ADDR), 0, 12, 13, 16, total_length, buffer);
|
||||
break;
|
||||
case IP2K_OPERAND_ADDR16H :
|
||||
errmsg = insert_normal (cd, fields->f_imm8, 0, 0, 7, 8, 16, total_length, buffer);
|
||||
break;
|
||||
case IP2K_OPERAND_ADDR16L :
|
||||
errmsg = insert_normal (cd, fields->f_imm8, 0, 0, 7, 8, 16, total_length, buffer);
|
||||
break;
|
||||
case IP2K_OPERAND_ADDR16P :
|
||||
errmsg = insert_normal (cd, fields->f_page3, 0, 0, 2, 3, 16, total_length, buffer);
|
||||
break;
|
||||
case IP2K_OPERAND_BITNO :
|
||||
errmsg = insert_normal (cd, fields->f_bitno, 0, 0, 11, 3, 16, total_length, buffer);
|
||||
break;
|
||||
case IP2K_OPERAND_CBIT :
|
||||
break;
|
||||
case IP2K_OPERAND_DCBIT :
|
||||
break;
|
||||
case IP2K_OPERAND_FR :
|
||||
errmsg = insert_normal (cd, fields->f_reg, 0|(1<<CGEN_IFLD_ABS_ADDR), 0, 8, 9, 16, total_length, buffer);
|
||||
break;
|
||||
case IP2K_OPERAND_LIT8 :
|
||||
errmsg = insert_normal (cd, fields->f_imm8, 0, 0, 7, 8, 16, total_length, buffer);
|
||||
break;
|
||||
case IP2K_OPERAND_PABITS :
|
||||
break;
|
||||
case IP2K_OPERAND_RETI3 :
|
||||
errmsg = insert_normal (cd, fields->f_reti3, 0, 0, 2, 3, 16, total_length, buffer);
|
||||
break;
|
||||
case IP2K_OPERAND_ZBIT :
|
||||
break;
|
||||
|
||||
default :
|
||||
/* xgettext:c-format */
|
||||
fprintf (stderr, _("Unrecognized field %d while building insn.\n"),
|
||||
opindex);
|
||||
abort ();
|
||||
}
|
||||
|
||||
return errmsg;
|
||||
}
|
||||
|
||||
int ip2k_cgen_extract_operand
|
||||
PARAMS ((CGEN_CPU_DESC, int, CGEN_EXTRACT_INFO *, CGEN_INSN_INT,
|
||||
CGEN_FIELDS *, bfd_vma));
|
||||
|
||||
/* Main entry point for operand extraction.
|
||||
The result is <= 0 for error, >0 for success.
|
||||
??? Actual values aren't well defined right now.
|
||||
|
||||
This function is basically just a big switch statement. Earlier versions
|
||||
used tables to look up the function to use, but
|
||||
- if the table contains both assembler and disassembler functions then
|
||||
the disassembler contains much of the assembler and vice-versa,
|
||||
- there's a lot of inlining possibilities as things grow,
|
||||
- using a switch statement avoids the function call overhead.
|
||||
|
||||
This function could be moved into `print_insn_normal', but keeping it
|
||||
separate makes clear the interface between `print_insn_normal' and each of
|
||||
the handlers. */
|
||||
|
||||
int
|
||||
ip2k_cgen_extract_operand (cd, opindex, ex_info, insn_value, fields, pc)
|
||||
CGEN_CPU_DESC cd;
|
||||
int opindex;
|
||||
CGEN_EXTRACT_INFO *ex_info;
|
||||
CGEN_INSN_INT insn_value;
|
||||
CGEN_FIELDS * fields;
|
||||
bfd_vma pc;
|
||||
{
|
||||
/* Assume success (for those operands that are nops). */
|
||||
int length = 1;
|
||||
unsigned int total_length = CGEN_FIELDS_BITSIZE (fields);
|
||||
|
||||
switch (opindex)
|
||||
{
|
||||
case IP2K_OPERAND_ADDR16CJP :
|
||||
length = extract_normal (cd, ex_info, insn_value, 0|(1<<CGEN_IFLD_ABS_ADDR), 0, 12, 13, 16, total_length, pc, & fields->f_addr16cjp);
|
||||
break;
|
||||
case IP2K_OPERAND_ADDR16H :
|
||||
length = extract_normal (cd, ex_info, insn_value, 0, 0, 7, 8, 16, total_length, pc, & fields->f_imm8);
|
||||
break;
|
||||
case IP2K_OPERAND_ADDR16L :
|
||||
length = extract_normal (cd, ex_info, insn_value, 0, 0, 7, 8, 16, total_length, pc, & fields->f_imm8);
|
||||
break;
|
||||
case IP2K_OPERAND_ADDR16P :
|
||||
length = extract_normal (cd, ex_info, insn_value, 0, 0, 2, 3, 16, total_length, pc, & fields->f_page3);
|
||||
break;
|
||||
case IP2K_OPERAND_BITNO :
|
||||
length = extract_normal (cd, ex_info, insn_value, 0, 0, 11, 3, 16, total_length, pc, & fields->f_bitno);
|
||||
break;
|
||||
case IP2K_OPERAND_CBIT :
|
||||
break;
|
||||
case IP2K_OPERAND_DCBIT :
|
||||
break;
|
||||
case IP2K_OPERAND_FR :
|
||||
length = extract_normal (cd, ex_info, insn_value, 0|(1<<CGEN_IFLD_ABS_ADDR), 0, 8, 9, 16, total_length, pc, & fields->f_reg);
|
||||
break;
|
||||
case IP2K_OPERAND_LIT8 :
|
||||
length = extract_normal (cd, ex_info, insn_value, 0, 0, 7, 8, 16, total_length, pc, & fields->f_imm8);
|
||||
break;
|
||||
case IP2K_OPERAND_PABITS :
|
||||
break;
|
||||
case IP2K_OPERAND_RETI3 :
|
||||
length = extract_normal (cd, ex_info, insn_value, 0, 0, 2, 3, 16, total_length, pc, & fields->f_reti3);
|
||||
break;
|
||||
case IP2K_OPERAND_ZBIT :
|
||||
break;
|
||||
|
||||
default :
|
||||
/* xgettext:c-format */
|
||||
fprintf (stderr, _("Unrecognized field %d while decoding insn.\n"),
|
||||
opindex);
|
||||
abort ();
|
||||
}
|
||||
|
||||
return length;
|
||||
}
|
||||
|
||||
cgen_insert_fn * const ip2k_cgen_insert_handlers[] =
|
||||
{
|
||||
insert_insn_normal,
|
||||
};
|
||||
|
||||
cgen_extract_fn * const ip2k_cgen_extract_handlers[] =
|
||||
{
|
||||
extract_insn_normal,
|
||||
};
|
||||
|
||||
int ip2k_cgen_get_int_operand
|
||||
PARAMS ((CGEN_CPU_DESC, int, const CGEN_FIELDS *));
|
||||
bfd_vma ip2k_cgen_get_vma_operand
|
||||
PARAMS ((CGEN_CPU_DESC, int, const CGEN_FIELDS *));
|
||||
|
||||
/* Getting values from cgen_fields is handled by a collection of functions.
|
||||
They are distinguished by the type of the VALUE argument they return.
|
||||
TODO: floating point, inlining support, remove cases where result type
|
||||
not appropriate. */
|
||||
|
||||
int
|
||||
ip2k_cgen_get_int_operand (cd, opindex, fields)
|
||||
CGEN_CPU_DESC cd ATTRIBUTE_UNUSED;
|
||||
int opindex;
|
||||
const CGEN_FIELDS * fields;
|
||||
{
|
||||
int value;
|
||||
|
||||
switch (opindex)
|
||||
{
|
||||
case IP2K_OPERAND_ADDR16CJP :
|
||||
value = fields->f_addr16cjp;
|
||||
break;
|
||||
case IP2K_OPERAND_ADDR16H :
|
||||
value = fields->f_imm8;
|
||||
break;
|
||||
case IP2K_OPERAND_ADDR16L :
|
||||
value = fields->f_imm8;
|
||||
break;
|
||||
case IP2K_OPERAND_ADDR16P :
|
||||
value = fields->f_page3;
|
||||
break;
|
||||
case IP2K_OPERAND_BITNO :
|
||||
value = fields->f_bitno;
|
||||
break;
|
||||
case IP2K_OPERAND_CBIT :
|
||||
value = 0;
|
||||
break;
|
||||
case IP2K_OPERAND_DCBIT :
|
||||
value = 0;
|
||||
break;
|
||||
case IP2K_OPERAND_FR :
|
||||
value = fields->f_reg;
|
||||
break;
|
||||
case IP2K_OPERAND_LIT8 :
|
||||
value = fields->f_imm8;
|
||||
break;
|
||||
case IP2K_OPERAND_PABITS :
|
||||
value = 0;
|
||||
break;
|
||||
case IP2K_OPERAND_RETI3 :
|
||||
value = fields->f_reti3;
|
||||
break;
|
||||
case IP2K_OPERAND_ZBIT :
|
||||
value = 0;
|
||||
break;
|
||||
|
||||
default :
|
||||
/* xgettext:c-format */
|
||||
fprintf (stderr, _("Unrecognized field %d while getting int operand.\n"),
|
||||
opindex);
|
||||
abort ();
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
bfd_vma
|
||||
ip2k_cgen_get_vma_operand (cd, opindex, fields)
|
||||
CGEN_CPU_DESC cd ATTRIBUTE_UNUSED;
|
||||
int opindex;
|
||||
const CGEN_FIELDS * fields;
|
||||
{
|
||||
bfd_vma value;
|
||||
|
||||
switch (opindex)
|
||||
{
|
||||
case IP2K_OPERAND_ADDR16CJP :
|
||||
value = fields->f_addr16cjp;
|
||||
break;
|
||||
case IP2K_OPERAND_ADDR16H :
|
||||
value = fields->f_imm8;
|
||||
break;
|
||||
case IP2K_OPERAND_ADDR16L :
|
||||
value = fields->f_imm8;
|
||||
break;
|
||||
case IP2K_OPERAND_ADDR16P :
|
||||
value = fields->f_page3;
|
||||
break;
|
||||
case IP2K_OPERAND_BITNO :
|
||||
value = fields->f_bitno;
|
||||
break;
|
||||
case IP2K_OPERAND_CBIT :
|
||||
value = 0;
|
||||
break;
|
||||
case IP2K_OPERAND_DCBIT :
|
||||
value = 0;
|
||||
break;
|
||||
case IP2K_OPERAND_FR :
|
||||
value = fields->f_reg;
|
||||
break;
|
||||
case IP2K_OPERAND_LIT8 :
|
||||
value = fields->f_imm8;
|
||||
break;
|
||||
case IP2K_OPERAND_PABITS :
|
||||
value = 0;
|
||||
break;
|
||||
case IP2K_OPERAND_RETI3 :
|
||||
value = fields->f_reti3;
|
||||
break;
|
||||
case IP2K_OPERAND_ZBIT :
|
||||
value = 0;
|
||||
break;
|
||||
|
||||
default :
|
||||
/* xgettext:c-format */
|
||||
fprintf (stderr, _("Unrecognized field %d while getting vma operand.\n"),
|
||||
opindex);
|
||||
abort ();
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
void ip2k_cgen_set_int_operand
|
||||
PARAMS ((CGEN_CPU_DESC, int, CGEN_FIELDS *, int));
|
||||
void ip2k_cgen_set_vma_operand
|
||||
PARAMS ((CGEN_CPU_DESC, int, CGEN_FIELDS *, bfd_vma));
|
||||
|
||||
/* Stuffing values in cgen_fields is handled by a collection of functions.
|
||||
They are distinguished by the type of the VALUE argument they accept.
|
||||
TODO: floating point, inlining support, remove cases where argument type
|
||||
not appropriate. */
|
||||
|
||||
void
|
||||
ip2k_cgen_set_int_operand (cd, opindex, fields, value)
|
||||
CGEN_CPU_DESC cd ATTRIBUTE_UNUSED;
|
||||
int opindex;
|
||||
CGEN_FIELDS * fields;
|
||||
int value;
|
||||
{
|
||||
switch (opindex)
|
||||
{
|
||||
case IP2K_OPERAND_ADDR16CJP :
|
||||
fields->f_addr16cjp = value;
|
||||
break;
|
||||
case IP2K_OPERAND_ADDR16H :
|
||||
fields->f_imm8 = value;
|
||||
break;
|
||||
case IP2K_OPERAND_ADDR16L :
|
||||
fields->f_imm8 = value;
|
||||
break;
|
||||
case IP2K_OPERAND_ADDR16P :
|
||||
fields->f_page3 = value;
|
||||
break;
|
||||
case IP2K_OPERAND_BITNO :
|
||||
fields->f_bitno = value;
|
||||
break;
|
||||
case IP2K_OPERAND_CBIT :
|
||||
break;
|
||||
case IP2K_OPERAND_DCBIT :
|
||||
break;
|
||||
case IP2K_OPERAND_FR :
|
||||
fields->f_reg = value;
|
||||
break;
|
||||
case IP2K_OPERAND_LIT8 :
|
||||
fields->f_imm8 = value;
|
||||
break;
|
||||
case IP2K_OPERAND_PABITS :
|
||||
break;
|
||||
case IP2K_OPERAND_RETI3 :
|
||||
fields->f_reti3 = value;
|
||||
break;
|
||||
case IP2K_OPERAND_ZBIT :
|
||||
break;
|
||||
|
||||
default :
|
||||
/* xgettext:c-format */
|
||||
fprintf (stderr, _("Unrecognized field %d while setting int operand.\n"),
|
||||
opindex);
|
||||
abort ();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ip2k_cgen_set_vma_operand (cd, opindex, fields, value)
|
||||
CGEN_CPU_DESC cd ATTRIBUTE_UNUSED;
|
||||
int opindex;
|
||||
CGEN_FIELDS * fields;
|
||||
bfd_vma value;
|
||||
{
|
||||
switch (opindex)
|
||||
{
|
||||
case IP2K_OPERAND_ADDR16CJP :
|
||||
fields->f_addr16cjp = value;
|
||||
break;
|
||||
case IP2K_OPERAND_ADDR16H :
|
||||
fields->f_imm8 = value;
|
||||
break;
|
||||
case IP2K_OPERAND_ADDR16L :
|
||||
fields->f_imm8 = value;
|
||||
break;
|
||||
case IP2K_OPERAND_ADDR16P :
|
||||
fields->f_page3 = value;
|
||||
break;
|
||||
case IP2K_OPERAND_BITNO :
|
||||
fields->f_bitno = value;
|
||||
break;
|
||||
case IP2K_OPERAND_CBIT :
|
||||
break;
|
||||
case IP2K_OPERAND_DCBIT :
|
||||
break;
|
||||
case IP2K_OPERAND_FR :
|
||||
fields->f_reg = value;
|
||||
break;
|
||||
case IP2K_OPERAND_LIT8 :
|
||||
fields->f_imm8 = value;
|
||||
break;
|
||||
case IP2K_OPERAND_PABITS :
|
||||
break;
|
||||
case IP2K_OPERAND_RETI3 :
|
||||
fields->f_reti3 = value;
|
||||
break;
|
||||
case IP2K_OPERAND_ZBIT :
|
||||
break;
|
||||
|
||||
default :
|
||||
/* xgettext:c-format */
|
||||
fprintf (stderr, _("Unrecognized field %d while setting vma operand.\n"),
|
||||
opindex);
|
||||
abort ();
|
||||
}
|
||||
}
|
||||
|
||||
/* Function to call before using the instruction builder tables. */
|
||||
|
||||
void
|
||||
ip2k_cgen_init_ibld_table (cd)
|
||||
CGEN_CPU_DESC cd;
|
||||
{
|
||||
cd->insert_handlers = & ip2k_cgen_insert_handlers[0];
|
||||
cd->extract_handlers = & ip2k_cgen_extract_handlers[0];
|
||||
|
||||
cd->insert_operand = ip2k_cgen_insert_operand;
|
||||
cd->extract_operand = ip2k_cgen_extract_operand;
|
||||
|
||||
cd->get_int_operand = ip2k_cgen_get_int_operand;
|
||||
cd->set_int_operand = ip2k_cgen_set_int_operand;
|
||||
cd->get_vma_operand = ip2k_cgen_get_vma_operand;
|
||||
cd->set_vma_operand = ip2k_cgen_set_vma_operand;
|
||||
}
|
||||
914
opcodes/ip2k-opc.c
Normal file
914
opcodes/ip2k-opc.c
Normal file
@@ -0,0 +1,914 @@
|
||||
/* Instruction opcode table for ip2k.
|
||||
|
||||
THIS FILE IS MACHINE GENERATED WITH CGEN.
|
||||
|
||||
Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of the GNU Binutils and/or GDB, the GNU debugger.
|
||||
|
||||
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 "sysdep.h"
|
||||
#include "ansidecl.h"
|
||||
#include "bfd.h"
|
||||
#include "symcat.h"
|
||||
#include "ip2k-desc.h"
|
||||
#include "ip2k-opc.h"
|
||||
#include "libiberty.h"
|
||||
|
||||
/* -- opc.c */
|
||||
|
||||
/* A better hash function for instruction mnemonics. */
|
||||
unsigned int
|
||||
ip2k_asm_hash (insn)
|
||||
const char* insn;
|
||||
{
|
||||
unsigned int hash;
|
||||
const char* m = insn;
|
||||
|
||||
for (hash = 0; *m && !isspace(*m); m++)
|
||||
hash = (hash * 23) ^ (0x1F & tolower(*m));
|
||||
|
||||
/* printf ("%s %d\n", insn, (hash % CGEN_ASM_HASH_SIZE)); */
|
||||
|
||||
return hash % CGEN_ASM_HASH_SIZE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/* -- asm.c */
|
||||
/* The hash functions are recorded here to help keep assembler code out of
|
||||
the disassembler and vice versa. */
|
||||
|
||||
static int asm_hash_insn_p PARAMS ((const CGEN_INSN *));
|
||||
static unsigned int asm_hash_insn PARAMS ((const char *));
|
||||
static int dis_hash_insn_p PARAMS ((const CGEN_INSN *));
|
||||
static unsigned int dis_hash_insn PARAMS ((const char *, CGEN_INSN_INT));
|
||||
|
||||
/* Instruction formats. */
|
||||
|
||||
#if defined (__STDC__) || defined (ALMOST_STDC) || defined (HAVE_STRINGIZE)
|
||||
#define F(f) & ip2k_cgen_ifld_table[IP2K_##f]
|
||||
#else
|
||||
#define F(f) & ip2k_cgen_ifld_table[IP2K_/**/f]
|
||||
#endif
|
||||
static const CGEN_IFMT ifmt_empty = {
|
||||
0, 0, 0x0, { { 0 } }
|
||||
};
|
||||
|
||||
static const CGEN_IFMT ifmt_jmp = {
|
||||
16, 16, 0xe000, { { F (F_OP3) }, { F (F_ADDR16CJP) }, { 0 } }
|
||||
};
|
||||
|
||||
static const CGEN_IFMT ifmt_sb = {
|
||||
16, 16, 0xf000, { { F (F_OP4) }, { F (F_BITNO) }, { F (F_REG) }, { 0 } }
|
||||
};
|
||||
|
||||
static const CGEN_IFMT ifmt_xorw_l = {
|
||||
16, 16, 0xff00, { { F (F_OP4) }, { F (F_OP4MID) }, { F (F_IMM8) }, { 0 } }
|
||||
};
|
||||
|
||||
static const CGEN_IFMT ifmt_loadl_a = {
|
||||
16, 16, 0xff00, { { F (F_OP4) }, { F (F_OP4MID) }, { F (F_IMM8) }, { 0 } }
|
||||
};
|
||||
|
||||
static const CGEN_IFMT ifmt_loadh_a = {
|
||||
16, 16, 0xff00, { { F (F_OP4) }, { F (F_OP4MID) }, { F (F_IMM8) }, { 0 } }
|
||||
};
|
||||
|
||||
static const CGEN_IFMT ifmt_addcfr_w = {
|
||||
16, 16, 0xfe00, { { F (F_OP6) }, { F (F_DIR) }, { F (F_REG) }, { 0 } }
|
||||
};
|
||||
|
||||
static const CGEN_IFMT ifmt_speed = {
|
||||
16, 16, 0xff00, { { F (F_OP8) }, { F (F_IMM8) }, { 0 } }
|
||||
};
|
||||
|
||||
static const CGEN_IFMT ifmt_ireadi = {
|
||||
16, 16, 0xffff, { { F (F_OP6) }, { F (F_OP6_10LOW) }, { 0 } }
|
||||
};
|
||||
|
||||
static const CGEN_IFMT ifmt_page = {
|
||||
16, 16, 0xfff8, { { F (F_OP6) }, { F (F_OP6_7LOW) }, { F (F_PAGE3) }, { 0 } }
|
||||
};
|
||||
|
||||
static const CGEN_IFMT ifmt_reti = {
|
||||
16, 16, 0xfff8, { { F (F_OP6) }, { F (F_OP6_7LOW) }, { F (F_RETI3) }, { 0 } }
|
||||
};
|
||||
|
||||
#undef F
|
||||
|
||||
#if defined (__STDC__) || defined (ALMOST_STDC) || defined (HAVE_STRINGIZE)
|
||||
#define A(a) (1 << CGEN_INSN_##a)
|
||||
#else
|
||||
#define A(a) (1 << CGEN_INSN_/**/a)
|
||||
#endif
|
||||
#if defined (__STDC__) || defined (ALMOST_STDC) || defined (HAVE_STRINGIZE)
|
||||
#define OPERAND(op) IP2K_OPERAND_##op
|
||||
#else
|
||||
#define OPERAND(op) IP2K_OPERAND_/**/op
|
||||
#endif
|
||||
#define MNEM CGEN_SYNTAX_MNEMONIC /* syntax value for mnemonic */
|
||||
#define OP(field) CGEN_SYNTAX_MAKE_FIELD (OPERAND (field))
|
||||
|
||||
/* The instruction table. */
|
||||
|
||||
static const CGEN_OPCODE ip2k_cgen_insn_opcode_table[MAX_INSNS] =
|
||||
{
|
||||
/* Special null first entry.
|
||||
A `num' value of zero is thus invalid.
|
||||
Also, the special `invalid' insn resides here. */
|
||||
{ { 0, 0, 0, 0 }, {{0}}, 0, {0}},
|
||||
/* jmp $addr16cjp */
|
||||
{
|
||||
{ 0, 0, 0, 0 },
|
||||
{ { MNEM, ' ', OP (ADDR16CJP), 0 } },
|
||||
& ifmt_jmp, { 0xe000 }
|
||||
},
|
||||
/* call $addr16cjp */
|
||||
{
|
||||
{ 0, 0, 0, 0 },
|
||||
{ { MNEM, ' ', OP (ADDR16CJP), 0 } },
|
||||
& ifmt_jmp, { 0xc000 }
|
||||
},
|
||||
/* sb $fr,$bitno */
|
||||
{
|
||||
{ 0, 0, 0, 0 },
|
||||
{ { MNEM, ' ', OP (FR), ',', OP (BITNO), 0 } },
|
||||
& ifmt_sb, { 0xb000 }
|
||||
},
|
||||
/* snb $fr,$bitno */
|
||||
{
|
||||
{ 0, 0, 0, 0 },
|
||||
{ { MNEM, ' ', OP (FR), ',', OP (BITNO), 0 } },
|
||||
& ifmt_sb, { 0xa000 }
|
||||
},
|
||||
/* setb $fr,$bitno */
|
||||
{
|
||||
{ 0, 0, 0, 0 },
|
||||
{ { MNEM, ' ', OP (FR), ',', OP (BITNO), 0 } },
|
||||
& ifmt_sb, { 0x9000 }
|
||||
},
|
||||
/* clrb $fr,$bitno */
|
||||
{
|
||||
{ 0, 0, 0, 0 },
|
||||
{ { MNEM, ' ', OP (FR), ',', OP (BITNO), 0 } },
|
||||
& ifmt_sb, { 0x8000 }
|
||||
},
|
||||
/* xor W,#$lit8 */
|
||||
{
|
||||
{ 0, 0, 0, 0 },
|
||||
{ { MNEM, ' ', 'W', ',', '#', OP (LIT8), 0 } },
|
||||
& ifmt_xorw_l, { 0x7f00 }
|
||||
},
|
||||
/* and W,#$lit8 */
|
||||
{
|
||||
{ 0, 0, 0, 0 },
|
||||
{ { MNEM, ' ', 'W', ',', '#', OP (LIT8), 0 } },
|
||||
& ifmt_xorw_l, { 0x7e00 }
|
||||
},
|
||||
/* or W,#$lit8 */
|
||||
{
|
||||
{ 0, 0, 0, 0 },
|
||||
{ { MNEM, ' ', 'W', ',', '#', OP (LIT8), 0 } },
|
||||
& ifmt_xorw_l, { 0x7d00 }
|
||||
},
|
||||
/* add W,#$lit8 */
|
||||
{
|
||||
{ 0, 0, 0, 0 },
|
||||
{ { MNEM, ' ', 'W', ',', '#', OP (LIT8), 0 } },
|
||||
& ifmt_xorw_l, { 0x7b00 }
|
||||
},
|
||||
/* sub W,#$lit8 */
|
||||
{
|
||||
{ 0, 0, 0, 0 },
|
||||
{ { MNEM, ' ', 'W', ',', '#', OP (LIT8), 0 } },
|
||||
& ifmt_xorw_l, { 0x7a00 }
|
||||
},
|
||||
/* cmp W,#$lit8 */
|
||||
{
|
||||
{ 0, 0, 0, 0 },
|
||||
{ { MNEM, ' ', 'W', ',', '#', OP (LIT8), 0 } },
|
||||
& ifmt_xorw_l, { 0x7900 }
|
||||
},
|
||||
/* retw #$lit8 */
|
||||
{
|
||||
{ 0, 0, 0, 0 },
|
||||
{ { MNEM, ' ', '#', OP (LIT8), 0 } },
|
||||
& ifmt_xorw_l, { 0x7800 }
|
||||
},
|
||||
/* cse W,#$lit8 */
|
||||
{
|
||||
{ 0, 0, 0, 0 },
|
||||
{ { MNEM, ' ', 'W', ',', '#', OP (LIT8), 0 } },
|
||||
& ifmt_xorw_l, { 0x7700 }
|
||||
},
|
||||
/* csne W,#$lit8 */
|
||||
{
|
||||
{ 0, 0, 0, 0 },
|
||||
{ { MNEM, ' ', 'W', ',', '#', OP (LIT8), 0 } },
|
||||
& ifmt_xorw_l, { 0x7600 }
|
||||
},
|
||||
/* push #$lit8 */
|
||||
{
|
||||
{ 0, 0, 0, 0 },
|
||||
{ { MNEM, ' ', '#', OP (LIT8), 0 } },
|
||||
& ifmt_xorw_l, { 0x7400 }
|
||||
},
|
||||
/* muls W,#$lit8 */
|
||||
{
|
||||
{ 0, 0, 0, 0 },
|
||||
{ { MNEM, ' ', 'W', ',', '#', OP (LIT8), 0 } },
|
||||
& ifmt_xorw_l, { 0x7300 }
|
||||
},
|
||||
/* mulu W,#$lit8 */
|
||||
{
|
||||
{ 0, 0, 0, 0 },
|
||||
{ { MNEM, ' ', 'W', ',', '#', OP (LIT8), 0 } },
|
||||
& ifmt_xorw_l, { 0x7200 }
|
||||
},
|
||||
/* loadl #$lit8 */
|
||||
{
|
||||
{ 0, 0, 0, 0 },
|
||||
{ { MNEM, ' ', '#', OP (LIT8), 0 } },
|
||||
& ifmt_xorw_l, { 0x7100 }
|
||||
},
|
||||
/* loadh #$lit8 */
|
||||
{
|
||||
{ 0, 0, 0, 0 },
|
||||
{ { MNEM, ' ', '#', OP (LIT8), 0 } },
|
||||
& ifmt_xorw_l, { 0x7000 }
|
||||
},
|
||||
/* loadl $addr16l */
|
||||
{
|
||||
{ 0, 0, 0, 0 },
|
||||
{ { MNEM, ' ', OP (ADDR16L), 0 } },
|
||||
& ifmt_loadl_a, { 0x7100 }
|
||||
},
|
||||
/* loadh $addr16h */
|
||||
{
|
||||
{ 0, 0, 0, 0 },
|
||||
{ { MNEM, ' ', OP (ADDR16H), 0 } },
|
||||
& ifmt_loadh_a, { 0x7000 }
|
||||
},
|
||||
/* addc $fr,W */
|
||||
{
|
||||
{ 0, 0, 0, 0 },
|
||||
{ { MNEM, ' ', OP (FR), ',', 'W', 0 } },
|
||||
& ifmt_addcfr_w, { 0x5e00 }
|
||||
},
|
||||
/* addc W,$fr */
|
||||
{
|
||||
{ 0, 0, 0, 0 },
|
||||
{ { MNEM, ' ', 'W', ',', OP (FR), 0 } },
|
||||
& ifmt_addcfr_w, { 0x5c00 }
|
||||
},
|
||||
/* incsnz $fr */
|
||||
{
|
||||
{ 0, 0, 0, 0 },
|
||||
{ { MNEM, ' ', OP (FR), 0 } },
|
||||
& ifmt_addcfr_w, { 0x5a00 }
|
||||
},
|
||||
/* incsnz W,$fr */
|
||||
{
|
||||
{ 0, 0, 0, 0 },
|
||||
{ { MNEM, ' ', 'W', ',', OP (FR), 0 } },
|
||||
& ifmt_addcfr_w, { 0x5800 }
|
||||
},
|
||||
/* muls W,$fr */
|
||||
{
|
||||
{ 0, 0, 0, 0 },
|
||||
{ { MNEM, ' ', 'W', ',', OP (FR), 0 } },
|
||||
& ifmt_addcfr_w, { 0x5400 }
|
||||
},
|
||||
/* mulu W,$fr */
|
||||
{
|
||||
{ 0, 0, 0, 0 },
|
||||
{ { MNEM, ' ', 'W', ',', OP (FR), 0 } },
|
||||
& ifmt_addcfr_w, { 0x5000 }
|
||||
},
|
||||
/* decsnz $fr */
|
||||
{
|
||||
{ 0, 0, 0, 0 },
|
||||
{ { MNEM, ' ', OP (FR), 0 } },
|
||||
& ifmt_addcfr_w, { 0x4e00 }
|
||||
},
|
||||
/* decsnz W,$fr */
|
||||
{
|
||||
{ 0, 0, 0, 0 },
|
||||
{ { MNEM, ' ', 'W', ',', OP (FR), 0 } },
|
||||
& ifmt_addcfr_w, { 0x4c00 }
|
||||
},
|
||||
/* subc W,$fr */
|
||||
{
|
||||
{ 0, 0, 0, 0 },
|
||||
{ { MNEM, ' ', 'W', ',', OP (FR), 0 } },
|
||||
& ifmt_addcfr_w, { 0x4800 }
|
||||
},
|
||||
/* subc $fr,W */
|
||||
{
|
||||
{ 0, 0, 0, 0 },
|
||||
{ { MNEM, ' ', OP (FR), ',', 'W', 0 } },
|
||||
& ifmt_addcfr_w, { 0x4a00 }
|
||||
},
|
||||
/* pop $fr */
|
||||
{
|
||||
{ 0, 0, 0, 0 },
|
||||
{ { MNEM, ' ', OP (FR), 0 } },
|
||||
& ifmt_addcfr_w, { 0x4600 }
|
||||
},
|
||||
/* push $fr */
|
||||
{
|
||||
{ 0, 0, 0, 0 },
|
||||
{ { MNEM, ' ', OP (FR), 0 } },
|
||||
& ifmt_addcfr_w, { 0x4400 }
|
||||
},
|
||||
/* cse W,$fr */
|
||||
{
|
||||
{ 0, 0, 0, 0 },
|
||||
{ { MNEM, ' ', 'W', ',', OP (FR), 0 } },
|
||||
& ifmt_addcfr_w, { 0x4200 }
|
||||
},
|
||||
/* csne W,$fr */
|
||||
{
|
||||
{ 0, 0, 0, 0 },
|
||||
{ { MNEM, ' ', 'W', ',', OP (FR), 0 } },
|
||||
& ifmt_addcfr_w, { 0x4000 }
|
||||
},
|
||||
/* incsz $fr */
|
||||
{
|
||||
{ 0, 0, 0, 0 },
|
||||
{ { MNEM, ' ', OP (FR), 0 } },
|
||||
& ifmt_addcfr_w, { 0x3e00 }
|
||||
},
|
||||
/* incsz W,$fr */
|
||||
{
|
||||
{ 0, 0, 0, 0 },
|
||||
{ { MNEM, ' ', 'W', ',', OP (FR), 0 } },
|
||||
& ifmt_addcfr_w, { 0x3c00 }
|
||||
},
|
||||
/* swap $fr */
|
||||
{
|
||||
{ 0, 0, 0, 0 },
|
||||
{ { MNEM, ' ', OP (FR), 0 } },
|
||||
& ifmt_addcfr_w, { 0x3a00 }
|
||||
},
|
||||
/* swap W,$fr */
|
||||
{
|
||||
{ 0, 0, 0, 0 },
|
||||
{ { MNEM, ' ', 'W', ',', OP (FR), 0 } },
|
||||
& ifmt_addcfr_w, { 0x3800 }
|
||||
},
|
||||
/* rl $fr */
|
||||
{
|
||||
{ 0, 0, 0, 0 },
|
||||
{ { MNEM, ' ', OP (FR), 0 } },
|
||||
& ifmt_addcfr_w, { 0x3600 }
|
||||
},
|
||||
/* rl W,$fr */
|
||||
{
|
||||
{ 0, 0, 0, 0 },
|
||||
{ { MNEM, ' ', 'W', ',', OP (FR), 0 } },
|
||||
& ifmt_addcfr_w, { 0x3400 }
|
||||
},
|
||||
/* rr $fr */
|
||||
{
|
||||
{ 0, 0, 0, 0 },
|
||||
{ { MNEM, ' ', OP (FR), 0 } },
|
||||
& ifmt_addcfr_w, { 0x3200 }
|
||||
},
|
||||
/* rr W,$fr */
|
||||
{
|
||||
{ 0, 0, 0, 0 },
|
||||
{ { MNEM, ' ', 'W', ',', OP (FR), 0 } },
|
||||
& ifmt_addcfr_w, { 0x3000 }
|
||||
},
|
||||
/* decsz $fr */
|
||||
{
|
||||
{ 0, 0, 0, 0 },
|
||||
{ { MNEM, ' ', OP (FR), 0 } },
|
||||
& ifmt_addcfr_w, { 0x2e00 }
|
||||
},
|
||||
/* decsz W,$fr */
|
||||
{
|
||||
{ 0, 0, 0, 0 },
|
||||
{ { MNEM, ' ', 'W', ',', OP (FR), 0 } },
|
||||
& ifmt_addcfr_w, { 0x2c00 }
|
||||
},
|
||||
/* inc $fr */
|
||||
{
|
||||
{ 0, 0, 0, 0 },
|
||||
{ { MNEM, ' ', OP (FR), 0 } },
|
||||
& ifmt_addcfr_w, { 0x2a00 }
|
||||
},
|
||||
/* inc W,$fr */
|
||||
{
|
||||
{ 0, 0, 0, 0 },
|
||||
{ { MNEM, ' ', 'W', ',', OP (FR), 0 } },
|
||||
& ifmt_addcfr_w, { 0x2800 }
|
||||
},
|
||||
/* not $fr */
|
||||
{
|
||||
{ 0, 0, 0, 0 },
|
||||
{ { MNEM, ' ', OP (FR), 0 } },
|
||||
& ifmt_addcfr_w, { 0x2600 }
|
||||
},
|
||||
/* not W,$fr */
|
||||
{
|
||||
{ 0, 0, 0, 0 },
|
||||
{ { MNEM, ' ', 'W', ',', OP (FR), 0 } },
|
||||
& ifmt_addcfr_w, { 0x2400 }
|
||||
},
|
||||
/* test $fr */
|
||||
{
|
||||
{ 0, 0, 0, 0 },
|
||||
{ { MNEM, ' ', OP (FR), 0 } },
|
||||
& ifmt_addcfr_w, { 0x2200 }
|
||||
},
|
||||
/* mov W,#$lit8 */
|
||||
{
|
||||
{ 0, 0, 0, 0 },
|
||||
{ { MNEM, ' ', 'W', ',', '#', OP (LIT8), 0 } },
|
||||
& ifmt_xorw_l, { 0x7c00 }
|
||||
},
|
||||
/* mov $fr,W */
|
||||
{
|
||||
{ 0, 0, 0, 0 },
|
||||
{ { MNEM, ' ', OP (FR), ',', 'W', 0 } },
|
||||
& ifmt_addcfr_w, { 0x200 }
|
||||
},
|
||||
/* mov W,$fr */
|
||||
{
|
||||
{ 0, 0, 0, 0 },
|
||||
{ { MNEM, ' ', 'W', ',', OP (FR), 0 } },
|
||||
& ifmt_addcfr_w, { 0x2000 }
|
||||
},
|
||||
/* add $fr,W */
|
||||
{
|
||||
{ 0, 0, 0, 0 },
|
||||
{ { MNEM, ' ', OP (FR), ',', 'W', 0 } },
|
||||
& ifmt_addcfr_w, { 0x1e00 }
|
||||
},
|
||||
/* add W,$fr */
|
||||
{
|
||||
{ 0, 0, 0, 0 },
|
||||
{ { MNEM, ' ', 'W', ',', OP (FR), 0 } },
|
||||
& ifmt_addcfr_w, { 0x1c00 }
|
||||
},
|
||||
/* xor $fr,W */
|
||||
{
|
||||
{ 0, 0, 0, 0 },
|
||||
{ { MNEM, ' ', OP (FR), ',', 'W', 0 } },
|
||||
& ifmt_addcfr_w, { 0x1a00 }
|
||||
},
|
||||
/* xor W,$fr */
|
||||
{
|
||||
{ 0, 0, 0, 0 },
|
||||
{ { MNEM, ' ', 'W', ',', OP (FR), 0 } },
|
||||
& ifmt_addcfr_w, { 0x1800 }
|
||||
},
|
||||
/* and $fr,W */
|
||||
{
|
||||
{ 0, 0, 0, 0 },
|
||||
{ { MNEM, ' ', OP (FR), ',', 'W', 0 } },
|
||||
& ifmt_addcfr_w, { 0x1600 }
|
||||
},
|
||||
/* and W,$fr */
|
||||
{
|
||||
{ 0, 0, 0, 0 },
|
||||
{ { MNEM, ' ', 'W', ',', OP (FR), 0 } },
|
||||
& ifmt_addcfr_w, { 0x1400 }
|
||||
},
|
||||
/* or $fr,W */
|
||||
{
|
||||
{ 0, 0, 0, 0 },
|
||||
{ { MNEM, ' ', OP (FR), ',', 'W', 0 } },
|
||||
& ifmt_addcfr_w, { 0x1200 }
|
||||
},
|
||||
/* or W,$fr */
|
||||
{
|
||||
{ 0, 0, 0, 0 },
|
||||
{ { MNEM, ' ', 'W', ',', OP (FR), 0 } },
|
||||
& ifmt_addcfr_w, { 0x1000 }
|
||||
},
|
||||
/* dec $fr */
|
||||
{
|
||||
{ 0, 0, 0, 0 },
|
||||
{ { MNEM, ' ', OP (FR), 0 } },
|
||||
& ifmt_addcfr_w, { 0xe00 }
|
||||
},
|
||||
/* dec W,$fr */
|
||||
{
|
||||
{ 0, 0, 0, 0 },
|
||||
{ { MNEM, ' ', 'W', ',', OP (FR), 0 } },
|
||||
& ifmt_addcfr_w, { 0xc00 }
|
||||
},
|
||||
/* sub $fr,W */
|
||||
{
|
||||
{ 0, 0, 0, 0 },
|
||||
{ { MNEM, ' ', OP (FR), ',', 'W', 0 } },
|
||||
& ifmt_addcfr_w, { 0xa00 }
|
||||
},
|
||||
/* sub W,$fr */
|
||||
{
|
||||
{ 0, 0, 0, 0 },
|
||||
{ { MNEM, ' ', 'W', ',', OP (FR), 0 } },
|
||||
& ifmt_addcfr_w, { 0x800 }
|
||||
},
|
||||
/* clr $fr */
|
||||
{
|
||||
{ 0, 0, 0, 0 },
|
||||
{ { MNEM, ' ', OP (FR), 0 } },
|
||||
& ifmt_addcfr_w, { 0x600 }
|
||||
},
|
||||
/* cmp W,$fr */
|
||||
{
|
||||
{ 0, 0, 0, 0 },
|
||||
{ { MNEM, ' ', 'W', ',', OP (FR), 0 } },
|
||||
& ifmt_addcfr_w, { 0x400 }
|
||||
},
|
||||
/* speed #$lit8 */
|
||||
{
|
||||
{ 0, 0, 0, 0 },
|
||||
{ { MNEM, ' ', '#', OP (LIT8), 0 } },
|
||||
& ifmt_speed, { 0x100 }
|
||||
},
|
||||
/* ireadi */
|
||||
{
|
||||
{ 0, 0, 0, 0 },
|
||||
{ { MNEM, 0 } },
|
||||
& ifmt_ireadi, { 0x1d }
|
||||
},
|
||||
/* iwritei */
|
||||
{
|
||||
{ 0, 0, 0, 0 },
|
||||
{ { MNEM, 0 } },
|
||||
& ifmt_ireadi, { 0x1c }
|
||||
},
|
||||
/* fread */
|
||||
{
|
||||
{ 0, 0, 0, 0 },
|
||||
{ { MNEM, 0 } },
|
||||
& ifmt_ireadi, { 0x1b }
|
||||
},
|
||||
/* fwrite */
|
||||
{
|
||||
{ 0, 0, 0, 0 },
|
||||
{ { MNEM, 0 } },
|
||||
& ifmt_ireadi, { 0x1a }
|
||||
},
|
||||
/* iread */
|
||||
{
|
||||
{ 0, 0, 0, 0 },
|
||||
{ { MNEM, 0 } },
|
||||
& ifmt_ireadi, { 0x19 }
|
||||
},
|
||||
/* iwrite */
|
||||
{
|
||||
{ 0, 0, 0, 0 },
|
||||
{ { MNEM, 0 } },
|
||||
& ifmt_ireadi, { 0x18 }
|
||||
},
|
||||
/* page $addr16p */
|
||||
{
|
||||
{ 0, 0, 0, 0 },
|
||||
{ { MNEM, ' ', OP (ADDR16P), 0 } },
|
||||
& ifmt_page, { 0x10 }
|
||||
},
|
||||
/* system */
|
||||
{
|
||||
{ 0, 0, 0, 0 },
|
||||
{ { MNEM, 0 } },
|
||||
& ifmt_ireadi, { 0xff }
|
||||
},
|
||||
/* reti #$reti3 */
|
||||
{
|
||||
{ 0, 0, 0, 0 },
|
||||
{ { MNEM, ' ', '#', OP (RETI3), 0 } },
|
||||
& ifmt_reti, { 0x8 }
|
||||
},
|
||||
/* ret */
|
||||
{
|
||||
{ 0, 0, 0, 0 },
|
||||
{ { MNEM, 0 } },
|
||||
& ifmt_ireadi, { 0x7 }
|
||||
},
|
||||
/* int */
|
||||
{
|
||||
{ 0, 0, 0, 0 },
|
||||
{ { MNEM, 0 } },
|
||||
& ifmt_ireadi, { 0x6 }
|
||||
},
|
||||
/* breakx */
|
||||
{
|
||||
{ 0, 0, 0, 0 },
|
||||
{ { MNEM, 0 } },
|
||||
& ifmt_ireadi, { 0x5 }
|
||||
},
|
||||
/* cwdt */
|
||||
{
|
||||
{ 0, 0, 0, 0 },
|
||||
{ { MNEM, 0 } },
|
||||
& ifmt_ireadi, { 0x4 }
|
||||
},
|
||||
/* ferase */
|
||||
{
|
||||
{ 0, 0, 0, 0 },
|
||||
{ { MNEM, 0 } },
|
||||
& ifmt_ireadi, { 0x3 }
|
||||
},
|
||||
/* retnp */
|
||||
{
|
||||
{ 0, 0, 0, 0 },
|
||||
{ { MNEM, 0 } },
|
||||
& ifmt_ireadi, { 0x2 }
|
||||
},
|
||||
/* break */
|
||||
{
|
||||
{ 0, 0, 0, 0 },
|
||||
{ { MNEM, 0 } },
|
||||
& ifmt_ireadi, { 0x1 }
|
||||
},
|
||||
/* nop */
|
||||
{
|
||||
{ 0, 0, 0, 0 },
|
||||
{ { MNEM, 0 } },
|
||||
& ifmt_ireadi, { 0x0 }
|
||||
},
|
||||
};
|
||||
|
||||
#undef A
|
||||
#undef OPERAND
|
||||
#undef MNEM
|
||||
#undef OP
|
||||
|
||||
/* Formats for ALIAS macro-insns. */
|
||||
|
||||
#if defined (__STDC__) || defined (ALMOST_STDC) || defined (HAVE_STRINGIZE)
|
||||
#define F(f) & ip2k_cgen_ifld_table[IP2K_##f]
|
||||
#else
|
||||
#define F(f) & ip2k_cgen_ifld_table[IP2K_/**/f]
|
||||
#endif
|
||||
static const CGEN_IFMT ifmt_sc = {
|
||||
16, 16, 0xffff, { { F (F_OP4) }, { F (F_BITNO) }, { F (F_REG) }, { 0 } }
|
||||
};
|
||||
|
||||
static const CGEN_IFMT ifmt_snc = {
|
||||
16, 16, 0xffff, { { F (F_OP4) }, { F (F_BITNO) }, { F (F_REG) }, { 0 } }
|
||||
};
|
||||
|
||||
static const CGEN_IFMT ifmt_sz = {
|
||||
16, 16, 0xffff, { { F (F_OP4) }, { F (F_BITNO) }, { F (F_REG) }, { 0 } }
|
||||
};
|
||||
|
||||
static const CGEN_IFMT ifmt_snz = {
|
||||
16, 16, 0xffff, { { F (F_OP4) }, { F (F_BITNO) }, { F (F_REG) }, { 0 } }
|
||||
};
|
||||
|
||||
static const CGEN_IFMT ifmt_skip = {
|
||||
16, 16, 0xffff, { { F (F_OP4) }, { F (F_BITNO) }, { F (F_REG) }, { 0 } }
|
||||
};
|
||||
|
||||
static const CGEN_IFMT ifmt_skipb = {
|
||||
16, 16, 0xffff, { { F (F_OP4) }, { F (F_BITNO) }, { F (F_REG) }, { 0 } }
|
||||
};
|
||||
|
||||
#undef F
|
||||
|
||||
/* Each non-simple macro entry points to an array of expansion possibilities. */
|
||||
|
||||
#if defined (__STDC__) || defined (ALMOST_STDC) || defined (HAVE_STRINGIZE)
|
||||
#define A(a) (1 << CGEN_INSN_##a)
|
||||
#else
|
||||
#define A(a) (1 << CGEN_INSN_/**/a)
|
||||
#endif
|
||||
#if defined (__STDC__) || defined (ALMOST_STDC) || defined (HAVE_STRINGIZE)
|
||||
#define OPERAND(op) IP2K_OPERAND_##op
|
||||
#else
|
||||
#define OPERAND(op) IP2K_OPERAND_/**/op
|
||||
#endif
|
||||
#define MNEM CGEN_SYNTAX_MNEMONIC /* syntax value for mnemonic */
|
||||
#define OP(field) CGEN_SYNTAX_MAKE_FIELD (OPERAND (field))
|
||||
|
||||
/* The macro instruction table. */
|
||||
|
||||
static const CGEN_IBASE ip2k_cgen_macro_insn_table[] =
|
||||
{
|
||||
/* sc */
|
||||
{
|
||||
-1, "sc", "sc", 16,
|
||||
{ 0|A(ALIAS), { (1<<MACH_BASE) } }
|
||||
},
|
||||
/* snc */
|
||||
{
|
||||
-1, "snc", "snc", 16,
|
||||
{ 0|A(ALIAS), { (1<<MACH_BASE) } }
|
||||
},
|
||||
/* sz */
|
||||
{
|
||||
-1, "sz", "sz", 16,
|
||||
{ 0|A(ALIAS), { (1<<MACH_BASE) } }
|
||||
},
|
||||
/* snz */
|
||||
{
|
||||
-1, "snz", "snz", 16,
|
||||
{ 0|A(ALIAS), { (1<<MACH_BASE) } }
|
||||
},
|
||||
/* skip */
|
||||
{
|
||||
-1, "skip", "skip", 16,
|
||||
{ 0|A(SKIPA)|A(ALIAS), { (1<<MACH_BASE) } }
|
||||
},
|
||||
/* skip */
|
||||
{
|
||||
-1, "skipb", "skip", 16,
|
||||
{ 0|A(SKIPA)|A(ALIAS), { (1<<MACH_BASE) } }
|
||||
},
|
||||
};
|
||||
|
||||
/* The macro instruction opcode table. */
|
||||
|
||||
static const CGEN_OPCODE ip2k_cgen_macro_insn_opcode_table[] =
|
||||
{
|
||||
/* sc */
|
||||
{
|
||||
{ 0, 0, 0, 0 },
|
||||
{ { MNEM, 0 } },
|
||||
& ifmt_sc, { 0xb00b }
|
||||
},
|
||||
/* snc */
|
||||
{
|
||||
{ 0, 0, 0, 0 },
|
||||
{ { MNEM, 0 } },
|
||||
& ifmt_snc, { 0xa00b }
|
||||
},
|
||||
/* sz */
|
||||
{
|
||||
{ 0, 0, 0, 0 },
|
||||
{ { MNEM, 0 } },
|
||||
& ifmt_sz, { 0xb40b }
|
||||
},
|
||||
/* snz */
|
||||
{
|
||||
{ 0, 0, 0, 0 },
|
||||
{ { MNEM, 0 } },
|
||||
& ifmt_snz, { 0xa40b }
|
||||
},
|
||||
/* skip */
|
||||
{
|
||||
{ 0, 0, 0, 0 },
|
||||
{ { MNEM, 0 } },
|
||||
& ifmt_skip, { 0xa009 }
|
||||
},
|
||||
/* skip */
|
||||
{
|
||||
{ 0, 0, 0, 0 },
|
||||
{ { MNEM, 0 } },
|
||||
& ifmt_skipb, { 0xb009 }
|
||||
},
|
||||
};
|
||||
|
||||
#undef A
|
||||
#undef OPERAND
|
||||
#undef MNEM
|
||||
#undef OP
|
||||
|
||||
#ifndef CGEN_ASM_HASH_P
|
||||
#define CGEN_ASM_HASH_P(insn) 1
|
||||
#endif
|
||||
|
||||
#ifndef CGEN_DIS_HASH_P
|
||||
#define CGEN_DIS_HASH_P(insn) 1
|
||||
#endif
|
||||
|
||||
/* Return non-zero if INSN is to be added to the hash table.
|
||||
Targets are free to override CGEN_{ASM,DIS}_HASH_P in the .opc file. */
|
||||
|
||||
static int
|
||||
asm_hash_insn_p (insn)
|
||||
const CGEN_INSN *insn ATTRIBUTE_UNUSED;
|
||||
{
|
||||
return CGEN_ASM_HASH_P (insn);
|
||||
}
|
||||
|
||||
static int
|
||||
dis_hash_insn_p (insn)
|
||||
const CGEN_INSN *insn;
|
||||
{
|
||||
/* If building the hash table and the NO-DIS attribute is present,
|
||||
ignore. */
|
||||
if (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_NO_DIS))
|
||||
return 0;
|
||||
return CGEN_DIS_HASH_P (insn);
|
||||
}
|
||||
|
||||
#ifndef CGEN_ASM_HASH
|
||||
#define CGEN_ASM_HASH_SIZE 127
|
||||
#ifdef CGEN_MNEMONIC_OPERANDS
|
||||
#define CGEN_ASM_HASH(mnem) (*(unsigned char *) (mnem) % CGEN_ASM_HASH_SIZE)
|
||||
#else
|
||||
#define CGEN_ASM_HASH(mnem) (*(unsigned char *) (mnem) % CGEN_ASM_HASH_SIZE) /*FIXME*/
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* It doesn't make much sense to provide a default here,
|
||||
but while this is under development we do.
|
||||
BUFFER is a pointer to the bytes of the insn, target order.
|
||||
VALUE is the first base_insn_bitsize bits as an int in host order. */
|
||||
|
||||
#ifndef CGEN_DIS_HASH
|
||||
#define CGEN_DIS_HASH_SIZE 256
|
||||
#define CGEN_DIS_HASH(buf, value) (*(unsigned char *) (buf))
|
||||
#endif
|
||||
|
||||
/* The result is the hash value of the insn.
|
||||
Targets are free to override CGEN_{ASM,DIS}_HASH in the .opc file. */
|
||||
|
||||
static unsigned int
|
||||
asm_hash_insn (mnem)
|
||||
const char * mnem;
|
||||
{
|
||||
return CGEN_ASM_HASH (mnem);
|
||||
}
|
||||
|
||||
/* BUF is a pointer to the bytes of the insn, target order.
|
||||
VALUE is the first base_insn_bitsize bits as an int in host order. */
|
||||
|
||||
static unsigned int
|
||||
dis_hash_insn (buf, value)
|
||||
const char * buf ATTRIBUTE_UNUSED;
|
||||
CGEN_INSN_INT value ATTRIBUTE_UNUSED;
|
||||
{
|
||||
return CGEN_DIS_HASH (buf, value);
|
||||
}
|
||||
|
||||
static void set_fields_bitsize PARAMS ((CGEN_FIELDS *, int));
|
||||
|
||||
/* Set the recorded length of the insn in the CGEN_FIELDS struct. */
|
||||
|
||||
static void
|
||||
set_fields_bitsize (fields, size)
|
||||
CGEN_FIELDS *fields;
|
||||
int size;
|
||||
{
|
||||
CGEN_FIELDS_BITSIZE (fields) = size;
|
||||
}
|
||||
|
||||
/* Function to call before using the operand instance table.
|
||||
This plugs the opcode entries and macro instructions into the cpu table. */
|
||||
|
||||
void
|
||||
ip2k_cgen_init_opcode_table (cd)
|
||||
CGEN_CPU_DESC cd;
|
||||
{
|
||||
int i;
|
||||
int num_macros = (sizeof (ip2k_cgen_macro_insn_table) /
|
||||
sizeof (ip2k_cgen_macro_insn_table[0]));
|
||||
const CGEN_IBASE *ib = & ip2k_cgen_macro_insn_table[0];
|
||||
const CGEN_OPCODE *oc = & ip2k_cgen_macro_insn_opcode_table[0];
|
||||
CGEN_INSN *insns = (CGEN_INSN *) xmalloc (num_macros * sizeof (CGEN_INSN));
|
||||
memset (insns, 0, num_macros * sizeof (CGEN_INSN));
|
||||
for (i = 0; i < num_macros; ++i)
|
||||
{
|
||||
insns[i].base = &ib[i];
|
||||
insns[i].opcode = &oc[i];
|
||||
ip2k_cgen_build_insn_regex (& insns[i]);
|
||||
}
|
||||
cd->macro_insn_table.init_entries = insns;
|
||||
cd->macro_insn_table.entry_size = sizeof (CGEN_IBASE);
|
||||
cd->macro_insn_table.num_init_entries = num_macros;
|
||||
|
||||
oc = & ip2k_cgen_insn_opcode_table[0];
|
||||
insns = (CGEN_INSN *) cd->insn_table.init_entries;
|
||||
for (i = 0; i < MAX_INSNS; ++i)
|
||||
{
|
||||
insns[i].opcode = &oc[i];
|
||||
ip2k_cgen_build_insn_regex (& insns[i]);
|
||||
}
|
||||
|
||||
cd->sizeof_fields = sizeof (CGEN_FIELDS);
|
||||
cd->set_fields_bitsize = set_fields_bitsize;
|
||||
|
||||
cd->asm_hash_p = asm_hash_insn_p;
|
||||
cd->asm_hash = asm_hash_insn;
|
||||
cd->asm_hash_size = CGEN_ASM_HASH_SIZE;
|
||||
|
||||
cd->dis_hash_p = dis_hash_insn_p;
|
||||
cd->dis_hash = dis_hash_insn;
|
||||
cd->dis_hash_size = CGEN_DIS_HASH_SIZE;
|
||||
}
|
||||
133
opcodes/ip2k-opc.h
Normal file
133
opcodes/ip2k-opc.h
Normal file
@@ -0,0 +1,133 @@
|
||||
/* Instruction opcode header for ip2k.
|
||||
|
||||
THIS FILE IS MACHINE GENERATED WITH CGEN.
|
||||
|
||||
Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of the GNU Binutils and/or GDB, the GNU debugger.
|
||||
|
||||
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.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef IP2K_OPC_H
|
||||
#define IP2K_OPC_H
|
||||
|
||||
/* -- opc.h */
|
||||
|
||||
/* Check applicability of instructions against machines. */
|
||||
#define CGEN_VALIDATE_INSN_SUPPORTED
|
||||
|
||||
/* Allows reason codes to be output when assembler errors occur. */
|
||||
#define CGEN_VERBOSE_ASSEMBLER_ERRORS
|
||||
|
||||
/* Override disassembly hashing - there are variable bits in the top
|
||||
byte of these instructions. */
|
||||
#define CGEN_DIS_HASH_SIZE 8
|
||||
#define CGEN_DIS_HASH(buf,value) (((* (unsigned char*) (buf)) >> 5) % CGEN_DIS_HASH_SIZE)
|
||||
|
||||
#define CGEN_ASM_HASH_SIZE 127
|
||||
#define CGEN_ASM_HASH(insn) ip2k_asm_hash(insn)
|
||||
|
||||
extern unsigned int ip2k_asm_hash (const char *insn);
|
||||
|
||||
|
||||
/* Special check to ensure that instruction exists for given machine. */
|
||||
static int
|
||||
ip2k_cgen_insn_supported (cd, insn)
|
||||
CGEN_CPU_DESC cd;
|
||||
CGEN_INSN *insn;
|
||||
{
|
||||
int machs = CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_MACH);
|
||||
|
||||
/* No mach attribute? Assume it's supported for all machs. */
|
||||
if (machs == 0)
|
||||
return 1;
|
||||
|
||||
return ((machs & cd->machs) != 0);
|
||||
}
|
||||
|
||||
|
||||
/* -- opc.c */
|
||||
/* Enum declaration for ip2k instruction types. */
|
||||
typedef enum cgen_insn_type {
|
||||
IP2K_INSN_INVALID, IP2K_INSN_JMP, IP2K_INSN_CALL, IP2K_INSN_SB
|
||||
, IP2K_INSN_SNB, IP2K_INSN_SETB, IP2K_INSN_CLRB, IP2K_INSN_XORW_L
|
||||
, IP2K_INSN_ANDW_L, IP2K_INSN_ORW_L, IP2K_INSN_ADDW_L, IP2K_INSN_SUBW_L
|
||||
, IP2K_INSN_CMPW_L, IP2K_INSN_RETW_L, IP2K_INSN_CSEW_L, IP2K_INSN_CSNEW_L
|
||||
, IP2K_INSN_PUSH_L, IP2K_INSN_MULSW_L, IP2K_INSN_MULUW_L, IP2K_INSN_LOADL_L
|
||||
, IP2K_INSN_LOADH_L, IP2K_INSN_LOADL_A, IP2K_INSN_LOADH_A, IP2K_INSN_ADDCFR_W
|
||||
, IP2K_INSN_ADDCW_FR, IP2K_INSN_INCSNZ_FR, IP2K_INSN_INCSNZW_FR, IP2K_INSN_MULSW_FR
|
||||
, IP2K_INSN_MULUW_FR, IP2K_INSN_DECSNZ_FR, IP2K_INSN_DECSNZW_FR, IP2K_INSN_SUBCW_FR
|
||||
, IP2K_INSN_SUBCFR_W, IP2K_INSN_POP_FR, IP2K_INSN_PUSH_FR, IP2K_INSN_CSEW_FR
|
||||
, IP2K_INSN_CSNEW_FR, IP2K_INSN_INCSZ_FR, IP2K_INSN_INCSZW_FR, IP2K_INSN_SWAP_FR
|
||||
, IP2K_INSN_SWAPW_FR, IP2K_INSN_RL_FR, IP2K_INSN_RLW_FR, IP2K_INSN_RR_FR
|
||||
, IP2K_INSN_RRW_FR, IP2K_INSN_DECSZ_FR, IP2K_INSN_DECSZW_FR, IP2K_INSN_INC_FR
|
||||
, IP2K_INSN_INCW_FR, IP2K_INSN_NOT_FR, IP2K_INSN_NOTW_FR, IP2K_INSN_TEST_FR
|
||||
, IP2K_INSN_MOVW_L, IP2K_INSN_MOVFR_W, IP2K_INSN_MOVW_FR, IP2K_INSN_ADDFR_W
|
||||
, IP2K_INSN_ADDW_FR, IP2K_INSN_XORFR_W, IP2K_INSN_XORW_FR, IP2K_INSN_ANDFR_W
|
||||
, IP2K_INSN_ANDW_FR, IP2K_INSN_ORFR_W, IP2K_INSN_ORW_FR, IP2K_INSN_DEC_FR
|
||||
, IP2K_INSN_DECW_FR, IP2K_INSN_SUBFR_W, IP2K_INSN_SUBW_FR, IP2K_INSN_CLR_FR
|
||||
, IP2K_INSN_CMPW_FR, IP2K_INSN_SPEED, IP2K_INSN_IREADI, IP2K_INSN_IWRITEI
|
||||
, IP2K_INSN_FREAD, IP2K_INSN_FWRITE, IP2K_INSN_IREAD, IP2K_INSN_IWRITE
|
||||
, IP2K_INSN_PAGE, IP2K_INSN_SYSTEM, IP2K_INSN_RETI, IP2K_INSN_RET
|
||||
, IP2K_INSN_INT, IP2K_INSN_BREAKX, IP2K_INSN_CWDT, IP2K_INSN_FERASE
|
||||
, IP2K_INSN_RETNP, IP2K_INSN_BREAK, IP2K_INSN_NOP
|
||||
} CGEN_INSN_TYPE;
|
||||
|
||||
/* Index of `invalid' insn place holder. */
|
||||
#define CGEN_INSN_INVALID IP2K_INSN_INVALID
|
||||
|
||||
/* Total number of insns in table. */
|
||||
#define MAX_INSNS ((int) IP2K_INSN_NOP + 1)
|
||||
|
||||
/* This struct records data prior to insertion or after extraction. */
|
||||
struct cgen_fields
|
||||
{
|
||||
int length;
|
||||
long f_nil;
|
||||
long f_anyof;
|
||||
long f_imm8;
|
||||
long f_reg;
|
||||
long f_addr16cjp;
|
||||
long f_dir;
|
||||
long f_bitno;
|
||||
long f_op3;
|
||||
long f_op4;
|
||||
long f_op4mid;
|
||||
long f_op6;
|
||||
long f_op8;
|
||||
long f_op6_10low;
|
||||
long f_op6_7low;
|
||||
long f_reti3;
|
||||
long f_skipb;
|
||||
long f_page3;
|
||||
};
|
||||
|
||||
#define CGEN_INIT_PARSE(od) \
|
||||
{\
|
||||
}
|
||||
#define CGEN_INIT_INSERT(od) \
|
||||
{\
|
||||
}
|
||||
#define CGEN_INIT_EXTRACT(od) \
|
||||
{\
|
||||
}
|
||||
#define CGEN_INIT_PRINT(od) \
|
||||
{\
|
||||
}
|
||||
|
||||
|
||||
#endif /* IP2K_OPC_H */
|
||||
Reference in New Issue
Block a user