OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /or1k/tags/rel-0-3-0-rc1/or1ksim/cpu/or32
    from Rev 1749 to Rev 1765
    Reverse comparison

Rev 1749 → Rev 1765

/Makefile.in
0,0 → 1,799
# Makefile.in generated by automake 1.10.1 from Makefile.am.
# @configure_input@
 
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
# 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
 
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
# PARTICULAR PURPOSE.
 
@SET_MAKE@
 
# Makefile -- Makefile for OR32 dependent simulation
#
# Copyright (C) 1999 Damjan Lampret, lampret@opencores.org
# Copyright (C) 2008 Embecosm Limited
#
# Contributor Jeremy Bennett <jeremy.bennett@embecosm.com>
#
# This file is part of OpenRISC 1000 Architectural Simulator.
#
# 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 3 of the License, or (at your option)
# any later version.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
# more details.
#
# You should have received a copy of the GNU General Public License along
# with this program. If not, see <http://www.gnu.org/licenses/>.
 
 
VPATH = @srcdir@
pkgdatadir = $(datadir)/@PACKAGE@
pkglibdir = $(libdir)/@PACKAGE@
pkgincludedir = $(includedir)/@PACKAGE@
am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
install_sh_DATA = $(install_sh) -c -m 644
install_sh_PROGRAM = $(install_sh) -c
install_sh_SCRIPT = $(install_sh) -c
INSTALL_HEADER = $(INSTALL_DATA)
transform = $(program_transform_name)
NORMAL_INSTALL = :
PRE_INSTALL = :
POST_INSTALL = :
NORMAL_UNINSTALL = :
PRE_UNINSTALL = :
POST_UNINSTALL = :
build_triplet = @build@
host_triplet = @host@
target_triplet = @target@
@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@noinst_PROGRAMS = generate$(EXEEXT)
@DYNAMIC_EXECUTION_TRUE@noinst_PROGRAMS = dyngen$(EXEEXT)
subdir = cpu/or32
DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/configure.ac
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
$(ACLOCAL_M4)
mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
CONFIG_HEADER = $(top_builddir)/config.h
CONFIG_CLEAN_FILES =
LTLIBRARIES = $(noinst_LTLIBRARIES)
libarch_la_LIBADD =
am__libarch_la_SOURCES_DIST = execute.c insnset.c or32.c common-i386.h \
dyn32-defs.h dyngen.h dyn-rec.h i386-regs.h op-arith-op.h \
op-comp-op.h op-extend-op.h op-ff1-op.h op-i386.h op-lwhb-op.h \
op-mac-op.h op-mftspr-op.h op-support.h op-swhb-op.h \
op-t-reg-mov-op.h rec-i386.h sched-i386.h simpl32-defs.h op.c \
dyn-rec.c op-support.c
@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_FALSE@am_libarch_la_OBJECTS = \
@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_FALSE@ execute.lo \
@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_FALSE@ insnset.lo \
@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_FALSE@ or32.lo
@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@am_libarch_la_OBJECTS = \
@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@ execute.lo \
@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@ or32.lo
@DYNAMIC_EXECUTION_TRUE@am_libarch_la_OBJECTS = execute.lo or32.lo \
@DYNAMIC_EXECUTION_TRUE@ op.lo dyn-rec.lo op-support.lo
@DYNAMIC_EXECUTION_TRUE@nodist_libarch_la_OBJECTS = gen-ops.lo \
@DYNAMIC_EXECUTION_TRUE@ gen-ops-gen.lo gen-ops-rel.lo
libarch_la_OBJECTS = $(am_libarch_la_OBJECTS) \
$(nodist_libarch_la_OBJECTS)
@DYNAMIC_EXECUTION_FALSE@am_libarch_la_rpath =
@DYNAMIC_EXECUTION_TRUE@am_libarch_la_rpath =
libop_la_LIBADD =
am__libop_la_SOURCES_DIST = op.c op-t-reg-mov-op.h op-i386.h \
op-arith-op.h op-comp-op.h op-extend-op.h op-mac-op.h \
op-mftspr-op.h op-lwhb-op.h op-swhb-op.h
@DYNAMIC_EXECUTION_TRUE@am_libop_la_OBJECTS = libop_la-op.lo
libop_la_OBJECTS = $(am_libop_la_OBJECTS)
libop_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
--mode=link $(CCLD) $(libop_la_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
$(LDFLAGS) -o $@
@DYNAMIC_EXECUTION_TRUE@am_libop_la_rpath =
PROGRAMS = $(noinst_PROGRAMS)
am__dyngen_SOURCES_DIST = dyngen.c dyngen-i386.c dyngen-elf.c \
common-i386.h dyn32-defs.h dyngen.h dyn-rec.h i386-regs.h \
op-arith-op.h op-comp-op.h op-extend-op.h op-ff1-op.h \
op-i386.h op-lwhb-op.h op-mac-op.h op-mftspr-op.h op-support.h \
op-swhb-op.h op-t-reg-mov-op.h rec-i386.h sched-i386.h \
simpl32-defs.h
@DYNAMIC_EXECUTION_TRUE@am_dyngen_OBJECTS = dyngen-dyngen.$(OBJEXT) \
@DYNAMIC_EXECUTION_TRUE@ dyngen-dyngen-i386.$(OBJEXT) \
@DYNAMIC_EXECUTION_TRUE@ dyngen-dyngen-elf.$(OBJEXT)
dyngen_OBJECTS = $(am_dyngen_OBJECTS)
dyngen_LDADD = $(LDADD)
dyngen_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
--mode=link $(CCLD) $(dyngen_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
$(LDFLAGS) -o $@
am__generate_SOURCES_DIST = or32.c generate.c common-i386.h \
dyn32-defs.h dyngen.h dyn-rec.h i386-regs.h op-arith-op.h \
op-comp-op.h op-extend-op.h op-ff1-op.h op-i386.h op-lwhb-op.h \
op-mac-op.h op-mftspr-op.h op-support.h op-swhb-op.h \
op-t-reg-mov-op.h rec-i386.h sched-i386.h simpl32-defs.h
@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@am_generate_OBJECTS = generate-or32.$(OBJEXT) \
@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@ generate-generate.$(OBJEXT)
generate_OBJECTS = $(am_generate_OBJECTS)
generate_LDADD = $(LDADD)
generate_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
--mode=link $(CCLD) $(generate_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
$(LDFLAGS) -o $@
DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
--mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
$(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
CCLD = $(CC)
LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
--mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
$(LDFLAGS) -o $@
SOURCES = $(libarch_la_SOURCES) $(nodist_libarch_la_SOURCES) \
$(libop_la_SOURCES) $(dyngen_SOURCES) $(generate_SOURCES)
DIST_SOURCES = $(am__libarch_la_SOURCES_DIST) \
$(am__libop_la_SOURCES_DIST) $(am__dyngen_SOURCES_DIST) \
$(am__generate_SOURCES_DIST)
ETAGS = etags
CTAGS = ctags
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
ACLOCAL = @ACLOCAL@
AMTAR = @AMTAR@
AR = @AR@
ARFLAGS = @ARFLAGS@
AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
BUILD_DIR = @BUILD_DIR@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
CFLAGS = @CFLAGS@
CPP = @CPP@
CPPFLAGS = @CPPFLAGS@
CPU_ARCH = @CPU_ARCH@
CXX = @CXX@
CXXCPP = @CXXCPP@
CXXDEPMODE = @CXXDEPMODE@
CXXFLAGS = @CXXFLAGS@
CYGPATH_W = @CYGPATH_W@
DEBUGFLAGS = @DEBUGFLAGS@
DEFS = @DEFS@
DEPDIR = @DEPDIR@
ECHO = @ECHO@
ECHO_C = @ECHO_C@
ECHO_N = @ECHO_N@
ECHO_T = @ECHO_T@
EGREP = @EGREP@
EXEEXT = @EXEEXT@
F77 = @F77@
FFLAGS = @FFLAGS@
GREP = @GREP@
INCLUDES = @INCLUDES@
INSTALL = @INSTALL@
INSTALL_DATA = @INSTALL_DATA@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_SCRIPT = @INSTALL_SCRIPT@
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
LDFLAGS = @LDFLAGS@
LIBOBJS = @LIBOBJS@
LIBS = @LIBS@
LIBTOOL = @LIBTOOL@
LN_S = @LN_S@
LOCAL_CFLAGS = @LOCAL_CFLAGS@
LOCAL_DEFS = @LOCAL_DEFS@
LOCAL_LDFLAGS = @LOCAL_LDFLAGS@
LTLIBOBJS = @LTLIBOBJS@
MAKEINFO = @MAKEINFO@
MAKE_SHELL = @MAKE_SHELL@
MKDIR_P = @MKDIR_P@
OBJEXT = @OBJEXT@
PACKAGE = @PACKAGE@
PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
PACKAGE_NAME = @PACKAGE_NAME@
PACKAGE_STRING = @PACKAGE_STRING@
PACKAGE_TARNAME = @PACKAGE_TARNAME@
PACKAGE_VERSION = @PACKAGE_VERSION@
PATH_SEPARATOR = @PATH_SEPARATOR@
POW_LIB = @POW_LIB@
RANLIB = @RANLIB@
SED = @SED@
SET_MAKE = @SET_MAKE@
SHELL = @SHELL@
STRIP = @STRIP@
SUMVERSION = @SUMVERSION@
TERMCAP_LIB = @TERMCAP_LIB@
VERSION = @VERSION@
abs_builddir = @abs_builddir@
abs_srcdir = @abs_srcdir@
abs_top_builddir = @abs_top_builddir@
abs_top_srcdir = @abs_top_srcdir@
ac_ct_CC = @ac_ct_CC@
ac_ct_CXX = @ac_ct_CXX@
ac_ct_F77 = @ac_ct_F77@
am__include = @am__include@
am__leading_dot = @am__leading_dot@
am__quote = @am__quote@
am__tar = @am__tar@
am__untar = @am__untar@
bindir = @bindir@
build = @build@
build_alias = @build_alias@
build_cpu = @build_cpu@
build_os = @build_os@
build_vendor = @build_vendor@
builddir = @builddir@
datadir = @datadir@
datarootdir = @datarootdir@
docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
host = @host@
host_alias = @host_alias@
host_cpu = @host_cpu@
host_os = @host_os@
host_vendor = @host_vendor@
htmldir = @htmldir@
includedir = @includedir@
infodir = @infodir@
install_sh = @install_sh@
libdir = @libdir@
libexecdir = @libexecdir@
localedir = @localedir@
localstatedir = @localstatedir@
mandir = @mandir@
mkdir_p = @mkdir_p@
oldincludedir = @oldincludedir@
pdfdir = @pdfdir@
prefix = @prefix@
program_transform_name = @program_transform_name@
psdir = @psdir@
sbindir = @sbindir@
sharedstatedir = @sharedstatedir@
srcdir = @srcdir@
sysconfdir = @sysconfdir@
target = @target@
target_alias = @target_alias@
target_cpu = @target_cpu@
target_os = @target_os@
target_vendor = @target_vendor@
top_builddir = @top_builddir@
top_srcdir = @top_srcdir@
@DYNAMIC_EXECUTION_FALSE@noinst_LTLIBRARIES = libarch.la
@DYNAMIC_EXECUTION_TRUE@noinst_LTLIBRARIES = libarch.la libop.la
@DYNAMIC_EXECUTION_TRUE@dyngen_SOURCES = dyngen.c \
@DYNAMIC_EXECUTION_TRUE@ dyngen-i386.c \
@DYNAMIC_EXECUTION_TRUE@ dyngen-elf.c \
@DYNAMIC_EXECUTION_TRUE@ common-i386.h \
@DYNAMIC_EXECUTION_TRUE@ dyn32-defs.h \
@DYNAMIC_EXECUTION_TRUE@ dyngen.h \
@DYNAMIC_EXECUTION_TRUE@ dyn-rec.h \
@DYNAMIC_EXECUTION_TRUE@ i386-regs.h \
@DYNAMIC_EXECUTION_TRUE@ op-arith-op.h \
@DYNAMIC_EXECUTION_TRUE@ op-comp-op.h \
@DYNAMIC_EXECUTION_TRUE@ op-extend-op.h \
@DYNAMIC_EXECUTION_TRUE@ op-ff1-op.h \
@DYNAMIC_EXECUTION_TRUE@ op-i386.h \
@DYNAMIC_EXECUTION_TRUE@ op-lwhb-op.h \
@DYNAMIC_EXECUTION_TRUE@ op-mac-op.h \
@DYNAMIC_EXECUTION_TRUE@ op-mftspr-op.h \
@DYNAMIC_EXECUTION_TRUE@ op-support.h \
@DYNAMIC_EXECUTION_TRUE@ op-swhb-op.h \
@DYNAMIC_EXECUTION_TRUE@ op-t-reg-mov-op.h \
@DYNAMIC_EXECUTION_TRUE@ rec-i386.h \
@DYNAMIC_EXECUTION_TRUE@ sched-i386.h \
@DYNAMIC_EXECUTION_TRUE@ simpl32-defs.h
 
@DYNAMIC_EXECUTION_TRUE@dyngen_CFLAGS = $(AM_CFLAGS)
@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_FALSE@libarch_la_SOURCES = execute.c \
@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_FALSE@ insnset.c \
@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_FALSE@ or32.c \
@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_FALSE@ common-i386.h \
@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_FALSE@ dyn32-defs.h \
@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_FALSE@ dyngen.h \
@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_FALSE@ dyn-rec.h \
@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_FALSE@ i386-regs.h \
@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_FALSE@ op-arith-op.h \
@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_FALSE@ op-comp-op.h \
@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_FALSE@ op-extend-op.h \
@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_FALSE@ op-ff1-op.h \
@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_FALSE@ op-i386.h \
@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_FALSE@ op-lwhb-op.h \
@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_FALSE@ op-mac-op.h \
@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_FALSE@ op-mftspr-op.h \
@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_FALSE@ op-support.h \
@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_FALSE@ op-swhb-op.h \
@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_FALSE@ op-t-reg-mov-op.h \
@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_FALSE@ rec-i386.h \
@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_FALSE@ sched-i386.h \
@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_FALSE@ simpl32-defs.h
 
@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@libarch_la_SOURCES = execute.c \
@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@ or32.c \
@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@ common-i386.h \
@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@ dyn32-defs.h \
@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@ dyngen.h \
@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@ dyn-rec.h \
@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@ i386-regs.h \
@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@ op-arith-op.h \
@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@ op-comp-op.h \
@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@ op-extend-op.h \
@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@ op-ff1-op.h \
@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@ op-i386.h \
@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@ op-lwhb-op.h \
@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@ op-mac-op.h \
@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@ op-mftspr-op.h \
@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@ op-support.h \
@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@ op-swhb-op.h \
@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@ op-t-reg-mov-op.h \
@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@ rec-i386.h \
@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@ sched-i386.h \
@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@ simpl32-defs.h
 
@DYNAMIC_EXECUTION_TRUE@libarch_la_SOURCES = execute.c \
@DYNAMIC_EXECUTION_TRUE@ or32.c \
@DYNAMIC_EXECUTION_TRUE@ op.c \
@DYNAMIC_EXECUTION_TRUE@ dyn-rec.c \
@DYNAMIC_EXECUTION_TRUE@ op-support.c \
@DYNAMIC_EXECUTION_TRUE@ common-i386.h \
@DYNAMIC_EXECUTION_TRUE@ dyn32-defs.h \
@DYNAMIC_EXECUTION_TRUE@ dyngen.h \
@DYNAMIC_EXECUTION_TRUE@ dyn-rec.h \
@DYNAMIC_EXECUTION_TRUE@ i386-regs.h \
@DYNAMIC_EXECUTION_TRUE@ op-arith-op.h \
@DYNAMIC_EXECUTION_TRUE@ op-comp-op.h \
@DYNAMIC_EXECUTION_TRUE@ op-extend-op.h \
@DYNAMIC_EXECUTION_TRUE@ op-ff1-op.h \
@DYNAMIC_EXECUTION_TRUE@ op-i386.h \
@DYNAMIC_EXECUTION_TRUE@ op-lwhb-op.h \
@DYNAMIC_EXECUTION_TRUE@ op-mac-op.h \
@DYNAMIC_EXECUTION_TRUE@ op-mftspr-op.h \
@DYNAMIC_EXECUTION_TRUE@ op-support.h \
@DYNAMIC_EXECUTION_TRUE@ op-swhb-op.h \
@DYNAMIC_EXECUTION_TRUE@ op-t-reg-mov-op.h \
@DYNAMIC_EXECUTION_TRUE@ rec-i386.h \
@DYNAMIC_EXECUTION_TRUE@ sched-i386.h \
@DYNAMIC_EXECUTION_TRUE@ simpl32-defs.h
 
@DYNAMIC_EXECUTION_TRUE@nodist_libarch_la_SOURCES = gen-ops.h \
@DYNAMIC_EXECUTION_TRUE@ gen-ops.c \
@DYNAMIC_EXECUTION_TRUE@ gen-ops-gen.c \
@DYNAMIC_EXECUTION_TRUE@ gen-ops-rel.c
 
@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@BUILT_SOURCES = execgen.c
@DYNAMIC_EXECUTION_TRUE@BUILT_SOURCES = gen-ops.h \
@DYNAMIC_EXECUTION_TRUE@ gen-ops.c \
@DYNAMIC_EXECUTION_TRUE@ gen-ops-gen.c \
@DYNAMIC_EXECUTION_TRUE@ gen-ops-rel.c
 
@DYNAMIC_EXECUTION_TRUE@libop_la_SOURCES = op.c \
@DYNAMIC_EXECUTION_TRUE@ op-t-reg-mov-op.h \
@DYNAMIC_EXECUTION_TRUE@ op-i386.h op-arith-op.h \
@DYNAMIC_EXECUTION_TRUE@ op-comp-op.h \
@DYNAMIC_EXECUTION_TRUE@ op-extend-op.h \
@DYNAMIC_EXECUTION_TRUE@ op-mac-op.h \
@DYNAMIC_EXECUTION_TRUE@ op-mftspr-op.h \
@DYNAMIC_EXECUTION_TRUE@ op-lwhb-op.h \
@DYNAMIC_EXECUTION_TRUE@ op-swhb-op.h
 
@DYNAMIC_EXECUTION_TRUE@libop_la_CFLAGS = -Wall -fomit-frame-pointer -fno-reorder-blocks -O2
@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@EXTRA_DIST = insnset.c
@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@generate_SOURCES = or32.c \
@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@ generate.c \
@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@ common-i386.h \
@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@ dyn32-defs.h \
@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@ dyngen.h \
@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@ dyn-rec.h \
@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@ i386-regs.h \
@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@ op-arith-op.h \
@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@ op-comp-op.h \
@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@ op-extend-op.h \
@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@ op-ff1-op.h \
@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@ op-i386.h \
@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@ op-lwhb-op.h \
@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@ op-mac-op.h \
@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@ op-mftspr-op.h \
@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@ op-support.h \
@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@ op-swhb-op.h \
@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@ op-t-reg-mov-op.h \
@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@ rec-i386.h \
@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@ sched-i386.h \
@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@ simpl32-defs.h
 
@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@generate_CFLAGS = $(AM_CFLAGS)
 
# If the simulator was first built without --enable-simple and then with it,
# then also remove these two files
CLEANFILES = execgen.c \
generate \
gen-ops.c \
gen-ops.h \
gen-ops-rel.c \
gen-ops-gen.c
 
all: $(BUILT_SOURCES)
$(MAKE) $(AM_MAKEFLAGS) all-am
 
.SUFFIXES:
.SUFFIXES: .c .lo .o .obj
$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
@for dep in $?; do \
case '$(am__configure_deps)' in \
*$$dep*) \
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \
&& exit 0; \
exit 1;; \
esac; \
done; \
echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu cpu/or32/Makefile'; \
cd $(top_srcdir) && \
$(AUTOMAKE) --gnu cpu/or32/Makefile
.PRECIOUS: Makefile
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
@case '$?' in \
*config.status*) \
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
*) \
echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
esac;
 
$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
 
$(top_srcdir)/configure: $(am__configure_deps)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
$(ACLOCAL_M4): $(am__aclocal_m4_deps)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
 
clean-noinstLTLIBRARIES:
-test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES)
@list='$(noinst_LTLIBRARIES)'; for p in $$list; do \
dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
test "$$dir" != "$$p" || dir=.; \
echo "rm -f \"$${dir}/so_locations\""; \
rm -f "$${dir}/so_locations"; \
done
libarch.la: $(libarch_la_OBJECTS) $(libarch_la_DEPENDENCIES)
$(LINK) $(am_libarch_la_rpath) $(libarch_la_OBJECTS) $(libarch_la_LIBADD) $(LIBS)
libop.la: $(libop_la_OBJECTS) $(libop_la_DEPENDENCIES)
$(libop_la_LINK) $(am_libop_la_rpath) $(libop_la_OBJECTS) $(libop_la_LIBADD) $(LIBS)
 
clean-noinstPROGRAMS:
@list='$(noinst_PROGRAMS)'; for p in $$list; do \
f=`echo $$p|sed 's/$(EXEEXT)$$//'`; \
echo " rm -f $$p $$f"; \
rm -f $$p $$f ; \
done
dyngen$(EXEEXT): $(dyngen_OBJECTS) $(dyngen_DEPENDENCIES)
@rm -f dyngen$(EXEEXT)
$(dyngen_LINK) $(dyngen_OBJECTS) $(dyngen_LDADD) $(LIBS)
generate$(EXEEXT): $(generate_OBJECTS) $(generate_DEPENDENCIES)
@rm -f generate$(EXEEXT)
$(generate_LINK) $(generate_OBJECTS) $(generate_LDADD) $(LIBS)
 
mostlyclean-compile:
-rm -f *.$(OBJEXT)
 
distclean-compile:
-rm -f *.tab.c
 
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dyn-rec.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dyngen-dyngen-elf.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dyngen-dyngen-i386.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dyngen-dyngen.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/execute.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gen-ops-gen.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gen-ops-rel.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gen-ops.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/generate-generate.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/generate-or32.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/insnset.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libop_la-op.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/op-support.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/op.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/or32.Plo@am__quote@
 
.c.o:
@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(COMPILE) -c $<
 
.c.obj:
@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
 
.c.lo:
@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $<
 
libop_la-op.lo: op.c
@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libop_la_CFLAGS) $(CFLAGS) -MT libop_la-op.lo -MD -MP -MF $(DEPDIR)/libop_la-op.Tpo -c -o libop_la-op.lo `test -f 'op.c' || echo '$(srcdir)/'`op.c
@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/libop_la-op.Tpo $(DEPDIR)/libop_la-op.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='op.c' object='libop_la-op.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libop_la_CFLAGS) $(CFLAGS) -c -o libop_la-op.lo `test -f 'op.c' || echo '$(srcdir)/'`op.c
 
dyngen-dyngen.o: dyngen.c
@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(dyngen_CFLAGS) $(CFLAGS) -MT dyngen-dyngen.o -MD -MP -MF $(DEPDIR)/dyngen-dyngen.Tpo -c -o dyngen-dyngen.o `test -f 'dyngen.c' || echo '$(srcdir)/'`dyngen.c
@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/dyngen-dyngen.Tpo $(DEPDIR)/dyngen-dyngen.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='dyngen.c' object='dyngen-dyngen.o' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(dyngen_CFLAGS) $(CFLAGS) -c -o dyngen-dyngen.o `test -f 'dyngen.c' || echo '$(srcdir)/'`dyngen.c
 
dyngen-dyngen.obj: dyngen.c
@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(dyngen_CFLAGS) $(CFLAGS) -MT dyngen-dyngen.obj -MD -MP -MF $(DEPDIR)/dyngen-dyngen.Tpo -c -o dyngen-dyngen.obj `if test -f 'dyngen.c'; then $(CYGPATH_W) 'dyngen.c'; else $(CYGPATH_W) '$(srcdir)/dyngen.c'; fi`
@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/dyngen-dyngen.Tpo $(DEPDIR)/dyngen-dyngen.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='dyngen.c' object='dyngen-dyngen.obj' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(dyngen_CFLAGS) $(CFLAGS) -c -o dyngen-dyngen.obj `if test -f 'dyngen.c'; then $(CYGPATH_W) 'dyngen.c'; else $(CYGPATH_W) '$(srcdir)/dyngen.c'; fi`
 
dyngen-dyngen-i386.o: dyngen-i386.c
@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(dyngen_CFLAGS) $(CFLAGS) -MT dyngen-dyngen-i386.o -MD -MP -MF $(DEPDIR)/dyngen-dyngen-i386.Tpo -c -o dyngen-dyngen-i386.o `test -f 'dyngen-i386.c' || echo '$(srcdir)/'`dyngen-i386.c
@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/dyngen-dyngen-i386.Tpo $(DEPDIR)/dyngen-dyngen-i386.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='dyngen-i386.c' object='dyngen-dyngen-i386.o' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(dyngen_CFLAGS) $(CFLAGS) -c -o dyngen-dyngen-i386.o `test -f 'dyngen-i386.c' || echo '$(srcdir)/'`dyngen-i386.c
 
dyngen-dyngen-i386.obj: dyngen-i386.c
@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(dyngen_CFLAGS) $(CFLAGS) -MT dyngen-dyngen-i386.obj -MD -MP -MF $(DEPDIR)/dyngen-dyngen-i386.Tpo -c -o dyngen-dyngen-i386.obj `if test -f 'dyngen-i386.c'; then $(CYGPATH_W) 'dyngen-i386.c'; else $(CYGPATH_W) '$(srcdir)/dyngen-i386.c'; fi`
@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/dyngen-dyngen-i386.Tpo $(DEPDIR)/dyngen-dyngen-i386.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='dyngen-i386.c' object='dyngen-dyngen-i386.obj' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(dyngen_CFLAGS) $(CFLAGS) -c -o dyngen-dyngen-i386.obj `if test -f 'dyngen-i386.c'; then $(CYGPATH_W) 'dyngen-i386.c'; else $(CYGPATH_W) '$(srcdir)/dyngen-i386.c'; fi`
 
dyngen-dyngen-elf.o: dyngen-elf.c
@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(dyngen_CFLAGS) $(CFLAGS) -MT dyngen-dyngen-elf.o -MD -MP -MF $(DEPDIR)/dyngen-dyngen-elf.Tpo -c -o dyngen-dyngen-elf.o `test -f 'dyngen-elf.c' || echo '$(srcdir)/'`dyngen-elf.c
@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/dyngen-dyngen-elf.Tpo $(DEPDIR)/dyngen-dyngen-elf.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='dyngen-elf.c' object='dyngen-dyngen-elf.o' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(dyngen_CFLAGS) $(CFLAGS) -c -o dyngen-dyngen-elf.o `test -f 'dyngen-elf.c' || echo '$(srcdir)/'`dyngen-elf.c
 
dyngen-dyngen-elf.obj: dyngen-elf.c
@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(dyngen_CFLAGS) $(CFLAGS) -MT dyngen-dyngen-elf.obj -MD -MP -MF $(DEPDIR)/dyngen-dyngen-elf.Tpo -c -o dyngen-dyngen-elf.obj `if test -f 'dyngen-elf.c'; then $(CYGPATH_W) 'dyngen-elf.c'; else $(CYGPATH_W) '$(srcdir)/dyngen-elf.c'; fi`
@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/dyngen-dyngen-elf.Tpo $(DEPDIR)/dyngen-dyngen-elf.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='dyngen-elf.c' object='dyngen-dyngen-elf.obj' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(dyngen_CFLAGS) $(CFLAGS) -c -o dyngen-dyngen-elf.obj `if test -f 'dyngen-elf.c'; then $(CYGPATH_W) 'dyngen-elf.c'; else $(CYGPATH_W) '$(srcdir)/dyngen-elf.c'; fi`
 
generate-or32.o: or32.c
@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(generate_CFLAGS) $(CFLAGS) -MT generate-or32.o -MD -MP -MF $(DEPDIR)/generate-or32.Tpo -c -o generate-or32.o `test -f 'or32.c' || echo '$(srcdir)/'`or32.c
@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/generate-or32.Tpo $(DEPDIR)/generate-or32.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='or32.c' object='generate-or32.o' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(generate_CFLAGS) $(CFLAGS) -c -o generate-or32.o `test -f 'or32.c' || echo '$(srcdir)/'`or32.c
 
generate-or32.obj: or32.c
@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(generate_CFLAGS) $(CFLAGS) -MT generate-or32.obj -MD -MP -MF $(DEPDIR)/generate-or32.Tpo -c -o generate-or32.obj `if test -f 'or32.c'; then $(CYGPATH_W) 'or32.c'; else $(CYGPATH_W) '$(srcdir)/or32.c'; fi`
@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/generate-or32.Tpo $(DEPDIR)/generate-or32.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='or32.c' object='generate-or32.obj' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(generate_CFLAGS) $(CFLAGS) -c -o generate-or32.obj `if test -f 'or32.c'; then $(CYGPATH_W) 'or32.c'; else $(CYGPATH_W) '$(srcdir)/or32.c'; fi`
 
generate-generate.o: generate.c
@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(generate_CFLAGS) $(CFLAGS) -MT generate-generate.o -MD -MP -MF $(DEPDIR)/generate-generate.Tpo -c -o generate-generate.o `test -f 'generate.c' || echo '$(srcdir)/'`generate.c
@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/generate-generate.Tpo $(DEPDIR)/generate-generate.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='generate.c' object='generate-generate.o' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(generate_CFLAGS) $(CFLAGS) -c -o generate-generate.o `test -f 'generate.c' || echo '$(srcdir)/'`generate.c
 
generate-generate.obj: generate.c
@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(generate_CFLAGS) $(CFLAGS) -MT generate-generate.obj -MD -MP -MF $(DEPDIR)/generate-generate.Tpo -c -o generate-generate.obj `if test -f 'generate.c'; then $(CYGPATH_W) 'generate.c'; else $(CYGPATH_W) '$(srcdir)/generate.c'; fi`
@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/generate-generate.Tpo $(DEPDIR)/generate-generate.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='generate.c' object='generate-generate.obj' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(generate_CFLAGS) $(CFLAGS) -c -o generate-generate.obj `if test -f 'generate.c'; then $(CYGPATH_W) 'generate.c'; else $(CYGPATH_W) '$(srcdir)/generate.c'; fi`
 
mostlyclean-libtool:
-rm -f *.lo
 
clean-libtool:
-rm -rf .libs _libs
 
ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | \
$(AWK) '{ files[$$0] = 1; nonemtpy = 1; } \
END { if (nonempty) { for (i in files) print i; }; }'`; \
mkid -fID $$unique
tags: TAGS
 
TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
$(TAGS_FILES) $(LISP)
tags=; \
here=`pwd`; \
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | \
$(AWK) '{ files[$$0] = 1; nonempty = 1; } \
END { if (nonempty) { for (i in files) print i; }; }'`; \
if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
test -n "$$unique" || unique=$$empty_fix; \
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
$$tags $$unique; \
fi
ctags: CTAGS
CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
$(TAGS_FILES) $(LISP)
tags=; \
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | \
$(AWK) '{ files[$$0] = 1; nonempty = 1; } \
END { if (nonempty) { for (i in files) print i; }; }'`; \
test -z "$(CTAGS_ARGS)$$tags$$unique" \
|| $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
$$tags $$unique
 
GTAGS:
here=`$(am__cd) $(top_builddir) && pwd` \
&& cd $(top_srcdir) \
&& gtags -i $(GTAGS_ARGS) $$here
 
distclean-tags:
-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
 
distdir: $(DISTFILES)
@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
list='$(DISTFILES)'; \
dist_files=`for file in $$list; do echo $$file; done | \
sed -e "s|^$$srcdirstrip/||;t" \
-e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
case $$dist_files in \
*/*) $(MKDIR_P) `echo "$$dist_files" | \
sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
sort -u` ;; \
esac; \
for file in $$dist_files; do \
if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
if test -d $$d/$$file; then \
dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
fi; \
cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
else \
test -f $(distdir)/$$file \
|| cp -p $$d/$$file $(distdir)/$$file \
|| exit 1; \
fi; \
done
check-am: all-am
check: $(BUILT_SOURCES)
$(MAKE) $(AM_MAKEFLAGS) check-am
all-am: Makefile $(LTLIBRARIES) $(PROGRAMS)
installdirs:
install: $(BUILT_SOURCES)
$(MAKE) $(AM_MAKEFLAGS) install-am
install-exec: install-exec-am
install-data: install-data-am
uninstall: uninstall-am
 
install-am: all-am
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
 
installcheck: installcheck-am
install-strip:
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
`test -z '$(STRIP)' || \
echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
mostlyclean-generic:
 
clean-generic:
-test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
 
distclean-generic:
-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
 
maintainer-clean-generic:
@echo "This command is intended for maintainers to use"
@echo "it deletes files that may require special tools to rebuild."
-test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES)
clean: clean-am
 
clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \
clean-noinstPROGRAMS mostlyclean-am
 
distclean: distclean-am
-rm -rf ./$(DEPDIR)
-rm -f Makefile
distclean-am: clean-am distclean-compile distclean-generic \
distclean-tags
 
dvi: dvi-am
 
dvi-am:
 
html: html-am
 
info: info-am
 
info-am:
 
install-data-am:
 
install-dvi: install-dvi-am
 
install-exec-am:
 
install-html: install-html-am
 
install-info: install-info-am
 
install-man:
 
install-pdf: install-pdf-am
 
install-ps: install-ps-am
 
installcheck-am:
 
maintainer-clean: maintainer-clean-am
-rm -rf ./$(DEPDIR)
-rm -f Makefile
maintainer-clean-am: distclean-am maintainer-clean-generic
 
mostlyclean: mostlyclean-am
 
mostlyclean-am: mostlyclean-compile mostlyclean-generic \
mostlyclean-libtool
 
pdf: pdf-am
 
pdf-am:
 
ps: ps-am
 
ps-am:
 
uninstall-am:
 
.MAKE: install-am install-strip
 
.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
clean-libtool clean-noinstLTLIBRARIES clean-noinstPROGRAMS \
ctags distclean distclean-compile distclean-generic \
distclean-libtool distclean-tags distdir dvi dvi-am html \
html-am info info-am install install-am install-data \
install-data-am install-dvi install-dvi-am install-exec \
install-exec-am install-html install-html-am install-info \
install-info-am install-man install-pdf install-pdf-am \
install-ps install-ps-am install-strip installcheck \
installcheck-am installdirs maintainer-clean \
maintainer-clean-generic mostlyclean mostlyclean-compile \
mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
tags uninstall uninstall-am
 
 
@DYNAMIC_EXECUTION_TRUE@gen-ops.h gen-ops.c gen-ops-gen.c gen-ops-rel.c: dyngen$(EXEEXT) op.lo
@DYNAMIC_EXECUTION_TRUE@ ./dyngen$(EXEEXT) op.lo gen-ops.c gen-ops-gen.c gen-ops-rel.c gen-ops.h
 
@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@execgen.c: generate$(EXEEXT) insnset.c
@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@ ./generate$(EXEEXT) $(srcdir)/insnset.c execgen.c
# Tell versions [3.59,3.63) of GNU make to not export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded.
.NOEXPORT:
/rec-i386.h
0,0 → 1,28
/* rec-i386.h -- i386 specific parts of the recompile engine
 
 
This file is part of OpenRISC 1000 Architectural Simulator.
 
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
 
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
 
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
 
 
/* Gets the current stack pointer */
static void *get_sp(void)
{
void *stack;
asm("movl %%esp, %0" : "=rm" (stack));
return stack;
}
 
/op-2t.h
0,0 → 1,62
/* op-2t.h -- Instantiation of operatations that work on only 2 temporary
 
 
This file is part of OpenRISC 1000 Architectural Simulator.
 
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
 
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
 
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
 
#define OP_2T
#define T glue(glue(glue(_, T0), _), T1)
 
#if NUM_T_REGS == 3
# define T0 t0
# define T1 t0
# include OP_FILE
# undef T1
# define T1 t1
# include OP_FILE
# undef T1
# define T1 t2
# include OP_FILE
# undef T1
# undef T0
# define T0 t1
# define T1 t0
# include OP_FILE
# undef T1
# define T1 t1
# include OP_FILE
# undef T1
# define T1 t2
# include OP_FILE
# undef T1
# undef T0
# define T0 t2
# define T1 t0
# include OP_FILE
# undef T1
# define T1 t1
# include OP_FILE
# undef T1
# define T1 t2
# include OP_FILE
# undef T1
# undef T0
#else
#error Update op_2t.h for NUM_T_REGS temporaries
#endif
 
#undef T
#undef OP_2T
/op-mftspr-op.h
0,0 → 1,82
/* op-mftspr-op.h -- Micro operations template for the m{f,t}spr operations
 
 
Copyright (C) 2008 Embecosm Limited
 
Contributor Jeremy Bennett <jeremy.bennett@embecosm.com>
 
This file is part of Or1ksim, the OpenRISC 1000 Architectural Simulator.
 
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 3 of the License, or (at your option)
any later version.
 
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
more details.
 
You should have received a copy of the GNU General Public License along
with this program. If not, see <http://www.gnu.org/licenses/>. */
 
/* This program is commented throughout in a fashion suitable for processing
with Doxygen. */
 
 
#ifndef OP_MFTSPR_OP__H
#define OP_MFTSPR_OP__H
 
 
#ifdef OP_2T
__or_dynop void glue (op_mfspr, T) (void)
{
/* FIXME: NPC/PPC Handling is br0ke */
if (env->sprs[SPR_SR] & SPR_SR_SM)
T0 = mfspr (T1 + OP_PARAM1);
}
#endif
 
#ifdef OP_1T
__or_dynop void glue (op_mfspr_imm, T) (void)
{
/* FIXME: NPC/PPC Handling is br0ke */
if (env->sprs[SPR_SR] & SPR_SR_SM)
T0 = mfspr (OP_PARAM1);
}
#endif
 
#ifdef OP_2T
__or_dynop void glue (op_mtspr, T) (void)
{
/* FIXME: NPC handling DOES NOT WORK like this */
if (env->sprs[SPR_SR] & SPR_SR_SM)
mtspr (T0 + OP_PARAM1, T1);
}
#endif
 
#ifdef OP_1T
__or_dynop void glue (op_mtspr_clear, T) (void)
{
/* FIXME: NPC handling DOES NOT WORK like this */
if (env->sprs[SPR_SR] & SPR_SR_SM)
mtspr (T0 + OP_PARAM1, 0);
}
 
__or_dynop void glue (op_mtspr_imm, T) (void)
{
/* FIXME: NPC handling DOES NOT WORK like this */
if (env->sprs[SPR_SR] & SPR_SR_SM)
mtspr (OP_PARAM1, T0);
}
#endif
 
#if !defined(OP_1T) && !defined(OP_2T)
__or_dynop void
op_mtspr_imm_clear (void)
{
/* FIXME: NPC handling DOES NOT WORK like this */
if (env->sprs[SPR_SR] & SPR_SR_SM)
mtspr (OP_PARAM1, 0);
}
#endif /* OP_MFTSPR_OP__H */
/op-i386.h
0,0 → 1,46
/* op-i386.h -- i386 specific support routines for micro operations
 
 
Copyright (C) 2008 Embecosm Limited
 
Contributor Jeremy Bennett <jeremy.bennett@embecosm.com>
 
This file is part of Or1ksim, the OpenRISC 1000 Architectural Simulator.
 
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 3 of the License, or (at your option)
any later version.
 
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
more details.
 
You should have received a copy of the GNU General Public License along
with this program. If not, see <http://www.gnu.org/licenses/>. */
 
/* This program is commented throughout in a fashion suitable for processing
with Doxygen. */
 
 
#ifndef OP_I386__H
#define OP_I386__H
 
#define OP_JUMP(x) asm("jmp *%0" : : "rm" (x))
 
#define FORCE_RET asm volatile ("")
 
/* Does a function call (with no arguments) makeing sure that gcc doesn't peddle
* the stack. (FIXME: Is this safe??) */
#define SPEEDY_CALL(func) asm("call "#func"\n")
 
/* Return out of the recompiled code */
asm (" .align 2\n"
" .p2align 4,,15\n"
".globl op_do_jump\n"
" .type op_do_jump,@function\n"
"op_do_jump:\n"
" ret\n" " ret\n" "1:\n" " .size op_do_jump,1b-op_do_jump\n");
 
#endif /* OP_I386__H */
/sched-i386.h
0,0 → 1,40
/* sched-i386.h -- i386 specific support routines for the scheduler
 
 
This file is part of OpenRISC 1000 Architectural Simulator.
 
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
 
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
 
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
 
 
/* Sets the cycle counter to a specific value */
static void set_sched_cycle(int32_t job_time)
{
union {
uint64_t val64;
union {
uint32_t low32;
uint32_t high32;
} val3232;
} time_pc;
 
asm("movq %%mm0, %0\n"
"\tmovl %2, %1\n"
"\tmovq %3, %%mm0\n"
: "=m" (time_pc.val64),
"=m" (time_pc.val3232.low32)
: "r" (job_time),
"m" (time_pc.val64));
}
 
/dyn32-defs.h
0,0 → 1,123
/* dyn32-defs.h -- Definitions for the dynamic execution model
 
 
This file is part of OpenRISC 1000 Architectural Simulator.
 
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
 
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
 
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
 
 
struct op_queue {
unsigned int num_ops;
unsigned int ops_len;
unsigned int *ops;
unsigned int num_ops_param;
unsigned int ops_param_len;
unsigned int *ops_param;
unsigned int jump_local; /* Parameter index that holds the location of the jump */
oraddr_t jump_local_loc; /* Location to jump to (relative to start of page */
unsigned int not_jump_loc; /* Location to jump if not jumping (l.bf/l.bnf) */
int xref; /* Is this location cross referenced? */
oraddr_t insn_addr; /* Physical address of the instruction */
unsigned int reg_t[3]; /* Which registers are in the temporaries (after the instruction)? */
unsigned int tflags[3];
 
int insn_index;
unsigned int param_type[5]; /* opd->type */
orreg_t param[5]; /* Value of operand */
unsigned int param_num; /* Number of operands */
uint32_t insn; /* Instruction word */
 
struct op_queue *prev;
struct op_queue *next;
};
 
void gen_l_add PARAMS((struct op_queue *, int *, int));
void gen_l_addc PARAMS((struct op_queue *, int *, int));
void gen_l_and PARAMS((struct op_queue *, int *, int));
void gen_l_bf PARAMS((struct op_queue *, int *, int));
void gen_l_bnf PARAMS((struct op_queue *, int *, int));
void gen_l_cmov PARAMS((struct op_queue *, int *, int));
void gen_l_cust1 PARAMS((struct op_queue *, int *, int));
void gen_l_cust2 PARAMS((struct op_queue *, int *, int));
void gen_l_cust3 PARAMS((struct op_queue *, int *, int));
void gen_l_cust4 PARAMS((struct op_queue *, int *, int));
void gen_l_div PARAMS((struct op_queue *, int *, int));
void gen_l_divu PARAMS((struct op_queue *, int *, int));
void gen_l_extbs PARAMS((struct op_queue *, int *, int));
void gen_l_extbz PARAMS((struct op_queue *, int *, int));
void gen_l_exths PARAMS((struct op_queue *, int *, int));
void gen_l_exthz PARAMS((struct op_queue *, int *, int));
void gen_l_extws PARAMS((struct op_queue *, int *, int));
void gen_l_extwz PARAMS((struct op_queue *, int *, int));
void gen_l_ff1 PARAMS((struct op_queue *, int *, int));
void gen_l_j PARAMS((struct op_queue *, int *, int));
void gen_l_jal PARAMS((struct op_queue *, int *, int));
void gen_l_jr PARAMS((struct op_queue *, int *, int));
void gen_l_jalr PARAMS((struct op_queue *, int *, int));
void gen_l_lbs PARAMS((struct op_queue *, int *, int));
void gen_l_lbz PARAMS((struct op_queue *, int *, int));
void gen_l_lhs PARAMS((struct op_queue *, int *, int));
void gen_l_lhz PARAMS((struct op_queue *, int *, int));
void gen_l_lws PARAMS((struct op_queue *, int *, int));
void gen_l_lwz PARAMS((struct op_queue *, int *, int));
void gen_l_mac PARAMS((struct op_queue *, int *, int));
void gen_l_macrc PARAMS((struct op_queue *, int *, int));
void gen_l_mfspr PARAMS((struct op_queue *, int *, int));
void gen_l_movhi PARAMS((struct op_queue *, int *, int));
void gen_l_msb PARAMS((struct op_queue *, int *, int));
void gen_l_mtspr PARAMS((struct op_queue *, int *, int));
void gen_l_mul PARAMS((struct op_queue *, int *, int));
void gen_l_mulu PARAMS((struct op_queue *, int *, int));
void gen_l_nop PARAMS((struct op_queue *, int *, int));
void gen_l_or PARAMS((struct op_queue *, int *, int));
void gen_l_rfe PARAMS((struct op_queue *, int *, int));
void gen_l_sb PARAMS((struct op_queue *, int *, int));
void gen_l_sh PARAMS((struct op_queue *, int *, int));
void gen_l_sw PARAMS((struct op_queue *, int *, int));
void gen_l_sfeq PARAMS((struct op_queue *, int *, int));
void gen_l_sfges PARAMS((struct op_queue *, int *, int));
void gen_l_sfgeu PARAMS((struct op_queue *, int *, int));
void gen_l_sfgts PARAMS((struct op_queue *, int *, int));
void gen_l_sfgtu PARAMS((struct op_queue *, int *, int));
void gen_l_sfles PARAMS((struct op_queue *, int *, int));
void gen_l_sfleu PARAMS((struct op_queue *, int *, int));
void gen_l_sflts PARAMS((struct op_queue *, int *, int));
void gen_l_sfltu PARAMS((struct op_queue *, int *, int));
void gen_l_sfne PARAMS((struct op_queue *, int *, int));
void gen_l_sll PARAMS((struct op_queue *, int *, int));
void gen_l_sra PARAMS((struct op_queue *, int *, int));
void gen_l_srl PARAMS((struct op_queue *, int *, int));
void gen_l_sub PARAMS((struct op_queue *, int *, int));
void gen_l_sys PARAMS((struct op_queue *, int *, int));
void gen_l_trap PARAMS((struct op_queue *, int *, int));
void gen_l_xor PARAMS((struct op_queue *, int *, int));
void gen_l_invalid PARAMS((struct op_queue *, int *, int));
 
void gen_lf_add_s PARAMS((struct op_queue *, int *, int));
void gen_lf_div_s PARAMS((struct op_queue *, int *, int));
void gen_lf_ftoi_s PARAMS((struct op_queue *, int *, int));
void gen_lf_itof_s PARAMS((struct op_queue *, int *, int));
void gen_lf_madd_s PARAMS((struct op_queue *, int *, int));
void gen_lf_mul_s PARAMS((struct op_queue *, int *, int));
void gen_lf_rem_s PARAMS((struct op_queue *, int *, int));
void gen_lf_sfeq_s PARAMS((struct op_queue *, int *, int));
void gen_lf_sfge_s PARAMS((struct op_queue *, int *, int));
void gen_lf_sfgt_s PARAMS((struct op_queue *, int *, int));
void gen_lf_sfle_s PARAMS((struct op_queue *, int *, int));
void gen_lf_sflt_s PARAMS((struct op_queue *, int *, int));
void gen_lf_sfne_s PARAMS((struct op_queue *, int *, int));
void gen_lf_sub_s PARAMS((struct op_queue *, int *, int));
void l_none(struct op_queue *opq, int *param_t, int delay_slot);
 
/or32.c
0,0 → 1,1305
/* Table of opcodes for the OpenRISC 1000 ISA.
 
Copyright 1990, 1991, 1992, 1993 Free Software Foundation, Inc.
Copyright (C) 2008 Embecosm Limited
 
Contributed by Damjan Lampret (lampret@opencores.org).
Contributor Jeremy Bennett <jeremy.bennett@embecosm.com>
This file is part of Or1ksim, the OpenRISC 1000 Architectural Simulator.
This file is also part of gen_or1k_isa, GDB and GAS.
 
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 3 of the License, or (at your option)
any later version.
 
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
more details.
 
You should have received a copy of the GNU General Public License along
with this program. If not, see <http://www.gnu.org/licenses/>. */
 
/* This program is commented throughout in a fashion suitable for processing
with Doxygen. */
 
 
/* Autoconf and/or portability configuration */
#include "config.h"
#include "port.h"
 
/* System includes */
#include <stdlib.h>
#include <stdio.h>
 
/* Package includes */
#include "opcode/or32.h"
 
/* We treat all letters the same in encode/decode routines so
we need to assign some characteristics to them like signess etc.*/
CONST struct or32_letter or32_letters[] = {
{'A', NUM_UNSIGNED},
{'B', NUM_UNSIGNED},
{'D', NUM_UNSIGNED},
{'I', NUM_SIGNED},
{'K', NUM_UNSIGNED},
{'L', NUM_UNSIGNED},
{'N', NUM_SIGNED},
{'0', NUM_UNSIGNED},
{'\0', 0} /* dummy entry */
};
 
/* Opcode encoding:
machine[31:30]: first two bits of opcode
00 - neither of source operands is GPR
01 - second source operand is GPR (rB)
10 - first source operand is GPR (rA)
11 - both source operands are GPRs (rA and rB)
machine[29:26]: next four bits of opcode
machine[25:00]: instruction operands (specific to individual instruction)
 
Recommendation: irrelevant instruction bits should be set with a value of
bits in same positions of instruction preceding current instruction in the
code (when assembling).
*/
 
#ifdef HAVE_EXECUTION
# if SIMPLE_EXECUTION
# define EFN &l_none
# define EF(func) &(func)
# define EFI &l_invalid
# elif COMPLEX_EXECUTION
# define EFN "l_none"
# define EFI "l_invalid"
# ifdef __GNUC__
# define EF(func) #func
# else
# define EF(func) "func"
# endif
# else /* DYNAMIC_EXECUTION */
# define EFN &l_none
# define EF(func) &(gen_ ##func)
# define EFI &gen_l_invalid
# endif
#else /* HAVE_EXECUTION */
# define EFN &l_none
# define EF(func) EFN
# define EFI EFN
#endif /* HAVE_EXECUTION */
 
CONST struct or32_opcode or32_opcodes[] = {
 
{"l.j", "N", "00 0x0 NNNNN NNNNN NNNN NNNN NNNN NNNN",
EF (l_j), OR32_IF_DELAY, it_jump},
{"l.jal", "N", "00 0x1 NNNNN NNNNN NNNN NNNN NNNN NNNN",
EF (l_jal), OR32_IF_DELAY, it_jump},
{"l.bnf", "N", "00 0x3 NNNNN NNNNN NNNN NNNN NNNN NNNN",
EF (l_bnf), OR32_IF_DELAY | OR32_R_FLAG, it_branch},
{"l.bf", "N", "00 0x4 NNNNN NNNNN NNNN NNNN NNNN NNNN",
EF (l_bf), OR32_IF_DELAY | OR32_R_FLAG, it_branch},
{"l.nop", "K", "00 0x5 01--- ----- KKKK KKKK KKKK KKKK",
EF (l_nop), 0, it_nop},
{"l.movhi", "rD,K", "00 0x6 DDDDD ----0 KKKK KKKK KKKK KKKK",
EF (l_movhi), 0, it_movimm},
{"l.macrc", "rD", "00 0x6 DDDDD ----1 0000 0000 0000 0000",
EF (l_macrc), 0, it_mac},
{"l.sys", "K", "00 0x8 00000 00000 KKKK KKKK KKKK KKKK",
EF (l_sys), 0, it_exception},
{"l.trap", "K", "00 0x8 01000 00000 KKKK KKKK KKKK KKKK",
EF (l_trap), 0, it_exception},
{"l.msync", "", "00 0x8 10000 00000 0000 0000 0000 0000", EFN,
0, it_unknown},
{"l.psync", "", "00 0x8 10100 00000 0000 0000 0000 0000", EFN,
0, it_unknown},
{"l.csync", "", "00 0x8 11000 00000 0000 0000 0000 0000", EFN,
0, it_unknown},
{"l.rfe", "", "00 0x9 ----- ----- ---- ---- ---- ----",
EF (l_rfe), 0, it_exception},
{"lv.all_eq.b", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x1 0x0", EFI, 0,
it_unknown},
{"lv.all_eq.h", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x1 0x1", EFI, 0,
it_unknown},
{"lv.all_ge.b", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x1 0x2", EFI, 0,
it_unknown},
{"lv.all_ge.h", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x1 0x3", EFI, 0,
it_unknown},
{"lv.all_gt.b", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x1 0x4", EFI, 0,
it_unknown},
{"lv.all_gt.h", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x1 0x5", EFI, 0,
it_unknown},
{"lv.all_le.b", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x1 0x6", EFI, 0,
it_unknown},
{"lv.all_le.h", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x1 0x7", EFI, 0,
it_unknown},
{"lv.all_lt.b", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x1 0x8", EFI, 0,
it_unknown},
{"lv.all_lt.h", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x1 0x9", EFI, 0,
it_unknown},
{"lv.all_ne.b", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x1 0xA", EFI, 0,
it_unknown},
{"lv.all_ne.h", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x1 0xB", EFI, 0,
it_unknown},
{"lv.any_eq.b", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x2 0x0", EFI, 0,
it_unknown},
{"lv.any_eq.h", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x2 0x1", EFI, 0,
it_unknown},
{"lv.any_ge.b", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x2 0x2", EFI, 0,
it_unknown},
{"lv.any_ge.h", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x2 0x3", EFI, 0,
it_unknown},
{"lv.any_gt.b", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x2 0x4", EFI, 0,
it_unknown},
{"lv.any_gt.h", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x2 0x5", EFI, 0,
it_unknown},
{"lv.any_le.b", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x2 0x6", EFI, 0,
it_unknown},
{"lv.any_le.h", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x2 0x7", EFI, 0,
it_unknown},
{"lv.any_lt.b", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x2 0x8", EFI, 0,
it_unknown},
{"lv.any_lt.h", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x2 0x9", EFI, 0,
it_unknown},
{"lv.any_ne.b", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x2 0xA", EFI, 0,
it_unknown},
{"lv.any_ne.h", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x2 0xB", EFI, 0,
it_unknown},
{"lv.add.b", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x3 0x0", EFI, 0,
it_unknown},
{"lv.add.h", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x3 0x1", EFI, 0,
it_unknown},
{"lv.adds.b", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x3 0x2", EFI, 0,
it_unknown},
{"lv.adds.h", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x3 0x3", EFI, 0,
it_unknown},
{"lv.addu.b", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x3 0x4", EFI, 0,
it_unknown},
{"lv.addu.h", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x3 0x5", EFI, 0,
it_unknown},
{"lv.addus.b", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x3 0x6", EFI, 0,
it_unknown},
{"lv.addus.h", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x3 0x7", EFI, 0,
it_unknown},
{"lv.and", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x3 0x8", EFI, 0,
it_unknown},
{"lv.avg.b", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x3 0x9", EFI, 0,
it_unknown},
{"lv.avg.h", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x3 0xA", EFI, 0,
it_unknown},
{"lv.cmp_eq.b", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x4 0x0", EFI, 0,
it_unknown},
{"lv.cmp_eq.h", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x4 0x1", EFI, 0,
it_unknown},
{"lv.cmp_ge.b", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x4 0x2", EFI, 0,
it_unknown},
{"lv.cmp_ge.h", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x4 0x3", EFI, 0,
it_unknown},
{"lv.cmp_gt.b", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x4 0x4", EFI, 0,
it_unknown},
{"lv.cmp_gt.h", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x4 0x5", EFI, 0,
it_unknown},
{"lv.cmp_le.b", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x4 0x6", EFI, 0,
it_unknown},
{"lv.cmp_le.h", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x4 0x7", EFI, 0,
it_unknown},
{"lv.cmp_lt.b", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x4 0x8", EFI, 0,
it_unknown},
{"lv.cmp_lt.h", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x4 0x9", EFI, 0,
it_unknown},
{"lv.cmp_ne.b", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x4 0xA", EFI, 0,
it_unknown},
{"lv.cmp_ne.h", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x4 0xB", EFI, 0,
it_unknown},
{"lv.madds.h", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x5 0x4", EFI, 0,
it_unknown},
{"lv.max.b", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x5 0x5", EFI, 0,
it_unknown},
{"lv.max.h", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x5 0x6", EFI, 0,
it_unknown},
{"lv.merge.b", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x5 0x7", EFI, 0,
it_unknown},
{"lv.merge.h", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x5 0x8", EFI, 0,
it_unknown},
{"lv.min.b", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x5 0x9", EFI, 0,
it_unknown},
{"lv.min.h", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x5 0xA", EFI, 0,
it_unknown},
{"lv.msubs.h", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x5 0xB", EFI, 0,
it_unknown},
{"lv.muls.h", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x5 0xC", EFI, 0,
it_unknown},
{"lv.nand", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x5 0xD", EFI, 0,
it_unknown},
{"lv.nor", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x5 0xE", EFI, 0,
it_unknown},
{"lv.or", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x5 0xF", EFI, 0,
it_unknown},
{"lv.pack.b", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x6 0x0", EFI, 0,
it_unknown},
{"lv.pack.h", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x6 0x1", EFI, 0,
it_unknown},
{"lv.packs.b", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x6 0x2", EFI, 0,
it_unknown},
{"lv.packs.h", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x6 0x3", EFI, 0,
it_unknown},
{"lv.packus.b", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x6 0x4", EFI, 0,
it_unknown},
{"lv.packus.h", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x6 0x5", EFI, 0,
it_unknown},
{"lv.perm.n", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x6 0x6", EFI, 0,
it_unknown},
{"lv.rl.b", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x6 0x7", EFI, 0,
it_unknown},
{"lv.rl.h", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x6 0x8", EFI, 0,
it_unknown},
{"lv.sll.b", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x6 0x9", EFI, 0,
it_unknown},
{"lv.sll.h", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x6 0xA", EFI, 0,
it_unknown},
{"lv.sll", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x6 0xB", EFI, 0,
it_unknown},
{"lv.srl.b", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x6 0xC", EFI, 0,
it_unknown},
{"lv.srl.h", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x6 0xD", EFI, 0,
it_unknown},
{"lv.sra.b", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x6 0xE", EFI, 0,
it_unknown},
{"lv.sra.h", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x6 0xF", EFI, 0,
it_unknown},
{"lv.srl", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x7 0x0", EFI, 0,
it_unknown},
{"lv.sub.b", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x7 0x1", EFI, 0,
it_unknown},
{"lv.sub.h", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x7 0x2", EFI, 0,
it_unknown},
{"lv.subs.b", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x7 0x3", EFI, 0,
it_unknown},
{"lv.subs.h", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x7 0x4", EFI, 0,
it_unknown},
{"lv.subu.b", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x7 0x5", EFI, 0,
it_unknown},
{"lv.subu.h", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x7 0x6", EFI, 0,
it_unknown},
{"lv.subus.b", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x7 0x7", EFI, 0,
it_unknown},
{"lv.subus.h", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x7 0x8", EFI, 0,
it_unknown},
{"lv.unpack.b", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x7 0x9", EFI, 0,
it_unknown},
{"lv.unpack.h", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x7 0xA", EFI, 0,
it_unknown},
{"lv.xor", "rD,rA,rB", "00 0xA DDDDD AAAAA BBBB B--- 0x7 0xB", EFI, 0,
it_unknown},
{"lv.cust1", "", "00 0xA ----- ----- ---- ---- 0xC ----", EFI, 0,
it_unknown},
{"lv.cust2", "", "00 0xA ----- ----- ---- ---- 0xD ----", EFI, 0,
it_unknown},
{"lv.cust3", "", "00 0xA ----- ----- ---- ---- 0xE ----", EFI, 0,
it_unknown},
{"lv.cust4", "", "00 0xA ----- ----- ---- ---- 0xF ----", EFI, 0,
it_unknown},
 
{"l.jr", "rB", "01 0x1 ----- ----- BBBB B--- ---- ----",
EF (l_jr), OR32_IF_DELAY, it_jump},
{"l.jalr", "rB", "01 0x2 ----- ----- BBBB B--- ---- ----",
EF (l_jalr), OR32_IF_DELAY, it_jump},
{"l.maci", "rA,I", "01 0x3 IIIII AAAAA ---- -III IIII IIII",
EF (l_mac), 0, it_mac},
{"l.cust1", "", "01 0xC ----- ----- ---- ---- ---- ----",
EF (l_cust1), 0, it_unknown},
{"l.cust2", "", "01 0xD ----- ----- ---- ---- ---- ----",
EF (l_cust2), 0, it_unknown},
{"l.cust3", "", "01 0xE ----- ----- ---- ---- ---- ----",
EF (l_cust3), 0, it_unknown},
{"l.cust4", "", "01 0xF ----- ----- ---- ---- ---- ----",
EF (l_cust4), 0, it_unknown},
 
{"l.ld", "rD,I(rA)", "10 0x0 DDDDD AAAAA IIII IIII IIII IIII", EFI,
0, it_load},
{"l.lwz", "rD,I(rA)", "10 0x1 DDDDD AAAAA IIII IIII IIII IIII",
EF (l_lwz), 0, it_load},
{"l.lws", "rD,I(rA)", "10 0x2 DDDDD AAAAA IIII IIII IIII IIII", EFI,
0, it_load},
{"l.lbz", "rD,I(rA)", "10 0x3 DDDDD AAAAA IIII IIII IIII IIII",
EF (l_lbz), 0, it_load},
{"l.lbs", "rD,I(rA)", "10 0x4 DDDDD AAAAA IIII IIII IIII IIII",
EF (l_lbs), 0, it_load},
{"l.lhz", "rD,I(rA)", "10 0x5 DDDDD AAAAA IIII IIII IIII IIII",
EF (l_lhz), 0, it_load},
{"l.lhs", "rD,I(rA)", "10 0x6 DDDDD AAAAA IIII IIII IIII IIII",
EF (l_lhs), 0, it_load},
 
{"l.addi", "rD,rA,I", "10 0x7 DDDDD AAAAA IIII IIII IIII IIII",
EF (l_add), OR32_W_FLAG, it_arith},
{"l.addic", "rD,rA,I", "10 0x8 DDDDD AAAAA IIII IIII IIII IIII", EFI,
0, it_arith},
{"l.andi", "rD,rA,K", "10 0x9 DDDDD AAAAA KKKK KKKK KKKK KKKK",
EF (l_and), OR32_W_FLAG, it_arith},
{"l.ori", "rD,rA,K", "10 0xA DDDDD AAAAA KKKK KKKK KKKK KKKK",
EF (l_or), 0, it_arith},
{"l.xori", "rD,rA,I", "10 0xB DDDDD AAAAA IIII IIII IIII IIII",
EF (l_xor), 0, it_arith},
{"l.muli", "rD,rA,I", "10 0xC DDDDD AAAAA IIII IIII IIII IIII",
EF (l_mul), 0, it_arith},
{"l.mfspr", "rD,rA,K", "10 0xD DDDDD AAAAA KKKK KKKK KKKK KKKK",
EF (l_mfspr), 0, it_move},
{"l.slli", "rD,rA,L", "10 0xE DDDDD AAAAA ---- ---- 00LL LLLL",
EF (l_sll), 0, it_shift},
{"l.srli", "rD,rA,L", "10 0xE DDDDD AAAAA ---- ---- 01LL LLLL",
EF (l_srl), 0, it_shift},
{"l.srai", "rD,rA,L", "10 0xE DDDDD AAAAA ---- ---- 10LL LLLL",
EF (l_sra), 0, it_shift},
{"l.rori", "rD,rA,L", "10 0xE DDDDD AAAAA ---- ---- 11LL LLLL", EFI,
0, it_shift},
 
{"l.sfeqi", "rA,I", "10 0xF 00000 AAAAA IIII IIII IIII IIII",
EF (l_sfeq), OR32_W_FLAG, it_compare},
{"l.sfnei", "rA,I", "10 0xF 00001 AAAAA IIII IIII IIII IIII",
EF (l_sfne), OR32_W_FLAG, it_compare},
{"l.sfgtui", "rA,I", "10 0xF 00010 AAAAA IIII IIII IIII IIII",
EF (l_sfgtu), OR32_W_FLAG, it_compare},
{"l.sfgeui", "rA,I", "10 0xF 00011 AAAAA IIII IIII IIII IIII",
EF (l_sfgeu), OR32_W_FLAG, it_compare},
{"l.sfltui", "rA,I", "10 0xF 00100 AAAAA IIII IIII IIII IIII",
EF (l_sfltu), OR32_W_FLAG, it_compare},
{"l.sfleui", "rA,I", "10 0xF 00101 AAAAA IIII IIII IIII IIII",
EF (l_sfleu), OR32_W_FLAG, it_compare},
{"l.sfgtsi", "rA,I", "10 0xF 01010 AAAAA IIII IIII IIII IIII",
EF (l_sfgts), OR32_W_FLAG, it_compare},
{"l.sfgesi", "rA,I", "10 0xF 01011 AAAAA IIII IIII IIII IIII",
EF (l_sfges), OR32_W_FLAG, it_compare},
{"l.sfltsi", "rA,I", "10 0xF 01100 AAAAA IIII IIII IIII IIII",
EF (l_sflts), OR32_W_FLAG, it_compare},
{"l.sflesi", "rA,I", "10 0xF 01101 AAAAA IIII IIII IIII IIII",
EF (l_sfles), OR32_W_FLAG, it_compare},
 
{"l.mtspr", "rA,rB,K", "11 0x0 KKKKK AAAAA BBBB BKKK KKKK KKKK",
EF (l_mtspr), 0, it_move},
{"l.mac", "rA,rB", "11 0x1 ----- AAAAA BBBB B--- ---- 0x1",
EF (l_mac), 0, it_mac},
{"l.msb", "rA,rB", "11 0x1 ----- AAAAA BBBB B--- ---- 0x2",
EF (l_msb), 0, it_mac},
 
{"lf.add.s", "rD,rA,rB", "11 0x2 DDDDD AAAAA BBBB B--- 0x0 0x0",
EF (lf_add_s), 0, it_float},
{"lf.sub.s", "rD,rA,rB", "11 0x2 DDDDD AAAAA BBBB B--- 0x0 0x1",
EF (lf_sub_s), 0, it_float},
{"lf.mul.s", "rD,rA,rB", "11 0x2 DDDDD AAAAA BBBB B--- 0x0 0x2",
EF (lf_mul_s), 0, it_float},
{"lf.div.s", "rD,rA,rB", "11 0x2 DDDDD AAAAA BBBB B--- 0x0 0x3",
EF (lf_div_s), 0, it_float},
{"lf.itof.s", "rD,rA", "11 0x2 DDDDD AAAAA 0000 0--- 0x0 0x4",
EF (lf_itof_s), 0, it_float},
{"lf.ftoi.s", "rD,rA", "11 0x2 DDDDD AAAAA 0000 0--- 0x0 0x5",
EF (lf_ftoi_s), 0, it_float},
{"lf.rem.s", "rD,rA,rB", "11 0x2 DDDDD AAAAA BBBB B--- 0x0 0x6",
EF (lf_rem_s), 0, it_float},
{"lf.madd.s", "rD,rA,rB", "11 0x2 DDDDD AAAAA BBBB B--- 0x0 0x7",
EF (lf_madd_s), 0, it_float},
{"lf.sfeq.s", "rA,rB", "11 0x2 ----- AAAAA BBBB B--- 0x0 0x8",
EF (lf_sfeq_s), 0, it_float},
{"lf.sfne.s", "rA,rB", "11 0x2 ----- AAAAA BBBB B--- 0x0 0x9",
EF (lf_sfne_s), 0, it_float},
{"lf.sfgt.s", "rA,rB", "11 0x2 ----- AAAAA BBBB B--- 0x0 0xA",
EF (lf_sfgt_s), 0, it_float},
{"lf.sfge.s", "rA,rB", "11 0x2 ----- AAAAA BBBB B--- 0x0 0xB",
EF (lf_sfge_s), 0, it_float},
{"lf.sflt.s", "rA,rB", "11 0x2 ----- AAAAA BBBB B--- 0x0 0xC",
EF (lf_sflt_s), 0, it_float},
{"lf.sfle.s", "rA,rB", "11 0x2 ----- AAAAA BBBB B--- 0x0 0xD",
EF (lf_sfle_s), 0, it_float},
{"lf.cust1.s", "rA,rB", "11 0x2 ----- AAAAA BBBB B--- 0xD ----", EFI,
0, it_float},
 
{"lf.add.d", "rD,rA,rB", "11 0x2 DDDDD AAAAA BBBB B--- 0x1 0x0", EFI, 0,
it_float},
{"lf.sub.d", "rD,rA,rB", "11 0x2 DDDDD AAAAA BBBB B--- 0x1 0x1", EFI, 0,
it_float},
{"lf.mul.d", "rD,rA,rB", "11 0x2 DDDDD AAAAA BBBB B--- 0x1 0x2", EFI, 0,
it_float},
{"lf.div.d", "rD,rA,rB", "11 0x2 DDDDD AAAAA BBBB B--- 0x1 0x3", EFI, 0,
it_float},
{"lf.itof.d", "rD,rA", "11 0x2 DDDDD AAAAA 0000 0--- 0x1 0x4", EFI, 0,
it_float},
{"lf.ftoi.d", "rD,rA", "11 0x2 DDDDD AAAAA 0000 0--- 0x1 0x5", EFI, 0,
it_float},
{"lf.rem.d", "rD,rA,rB", "11 0x2 DDDDD AAAAA BBBB B--- 0x1 0x6", EFI, 0,
it_float},
{"lf.madd.d", "rD,rA,rB", "11 0x2 DDDDD AAAAA BBBB B--- 0x1 0x7", EFI, 0,
it_float},
{"lf.sfeq.d", "rA,rB", "11 0x2 ----- AAAAA BBBB B--- 0x1 0x8", EFI, 0,
it_float},
{"lf.sfne.d", "rA,rB", "11 0x2 ----- AAAAA BBBB B--- 0x1 0x9", EFI, 0,
it_float},
{"lf.sfgt.d", "rA,rB", "11 0x2 ----- AAAAA BBBB B--- 0x1 0xA", EFI, 0,
it_float},
{"lf.sfge.d", "rA,rB", "11 0x2 ----- AAAAA BBBB B--- 0x1 0xB", EFI, 0,
it_float},
{"lf.sflt.d", "rA,rB", "11 0x2 ----- AAAAA BBBB B--- 0x1 0xC", EFI, 0,
it_float},
{"lf.sfle.d", "rA,rB", "11 0x2 ----- AAAAA BBBB B--- 0x1 0xD", EFI, 0,
it_float},
{"lf.cust1.d", "rA,rB", "11 0x2 ----- AAAAA BBBB B--- 0xE ----", EFI, 0,
it_float},
 
{"l.sd", "I(rA),rB", "11 0x4 IIIII AAAAA BBBB BIII IIII IIII", EFI,
0, it_store},
{"l.sw", "I(rA),rB", "11 0x5 IIIII AAAAA BBBB BIII IIII IIII",
EF (l_sw), 0, it_store},
{"l.sb", "I(rA),rB", "11 0x6 IIIII AAAAA BBBB BIII IIII IIII",
EF (l_sb), 0, it_store},
{"l.sh", "I(rA),rB", "11 0x7 IIIII AAAAA BBBB BIII IIII IIII",
EF (l_sh), 0, it_store},
 
{"l.add", "rD,rA,rB", "11 0x8 DDDDD AAAAA BBBB B-00 ---- 0x0",
EF (l_add), OR32_W_FLAG, it_arith},
{"l.addc", "rD,rA,rB", "11 0x8 DDDDD AAAAA BBBB B-00 ---- 0x1",
EF (l_addc), OR32_W_FLAG, it_arith},
{"l.sub", "rD,rA,rB", "11 0x8 DDDDD AAAAA BBBB B-00 ---- 0x2",
EF (l_sub), 0, it_arith},
{"l.and", "rD,rA,rB", "11 0x8 DDDDD AAAAA BBBB B-00 ---- 0x3",
EF (l_and), OR32_W_FLAG, it_arith},
{"l.or", "rD,rA,rB", "11 0x8 DDDDD AAAAA BBBB B-00 ---- 0x4",
EF (l_or), 0, it_arith},
{"l.xor", "rD,rA,rB", "11 0x8 DDDDD AAAAA BBBB B-00 ---- 0x5",
EF (l_xor), 0, it_arith},
{"l.mul", "rD,rA,rB", "11 0x8 DDDDD AAAAA BBBB B-11 ---- 0x6",
EF (l_mul), 0, it_arith},
 
{"l.sll", "rD,rA,rB", "11 0x8 DDDDD AAAAA BBBB B-00 00-- 0x8",
EF (l_sll), 0, it_shift},
{"l.srl", "rD,rA,rB", "11 0x8 DDDDD AAAAA BBBB B-00 01-- 0x8",
EF (l_srl), 0, it_shift},
{"l.sra", "rD,rA,rB", "11 0x8 DDDDD AAAAA BBBB B-00 10-- 0x8",
EF (l_sra), 0, it_shift},
{"l.ror", "rD,rA,rB", "11 0x8 DDDDD AAAAA BBBB B-00 11-- 0x8", EFI,
0, it_shift},
{"l.div", "rD,rA,rB", "11 0x8 DDDDD AAAAA BBBB B-11 ---- 0x9",
EF (l_div), 0, it_arith},
{"l.divu", "rD,rA,rB", "11 0x8 DDDDD AAAAA BBBB B-11 ---- 0xA",
EF (l_divu), 0, it_arith},
{"l.mulu", "rD,rA,rB", "11 0x8 DDDDD AAAAA BBBB B-11 ---- 0xB", EFI,
0, it_arith},
{"l.extbs", "rD,rA", "11 0x8 DDDDD AAAAA ---- --00 01-- 0xC",
EF (l_extbs), 0, it_move},
{"l.exths", "rD,rA", "11 0x8 DDDDD AAAAA ---- --00 00-- 0xC",
EF (l_exths), 0, it_move},
{"l.extws", "rD,rA", "11 0x8 DDDDD AAAAA ---- --00 00-- 0xD",
EF (l_extws), 0, it_move},
{"l.extbz", "rD,rA", "11 0x8 DDDDD AAAAA ---- --00 11-- 0xC",
EF (l_extbz), 0, it_move},
{"l.exthz", "rD,rA", "11 0x8 DDDDD AAAAA ---- --00 10-- 0xC",
EF (l_exthz), 0, it_move},
{"l.extwz", "rD,rA", "11 0x8 DDDDD AAAAA ---- --00 01-- 0xD",
EF (l_extwz), 0, it_move},
{"l.cmov", "rD,rA,rB", "11 0x8 DDDDD AAAAA BBBB B-00 ---- 0xE",
EF (l_cmov), OR32_R_FLAG, it_move},
{"l.ff1", "rD,rA", "11 0x8 DDDDD AAAAA ---- --00 ---- 0xF",
EF (l_ff1), 0, it_arith},
{"l.fl1", "rD,rA", "11 0x8 DDDDD AAAAA ---- --01 ---- 0xF", EFI, 0,
it_arith},
 
{"l.sfeq", "rA,rB", "11 0x9 00000 AAAAA BBBB B--- ---- ----",
EF (l_sfeq), OR32_W_FLAG, it_compare},
{"l.sfne", "rA,rB", "11 0x9 00001 AAAAA BBBB B--- ---- ----",
EF (l_sfne), OR32_W_FLAG, it_compare},
{"l.sfgtu", "rA,rB", "11 0x9 00010 AAAAA BBBB B--- ---- ----",
EF (l_sfgtu), OR32_W_FLAG, it_compare},
{"l.sfgeu", "rA,rB", "11 0x9 00011 AAAAA BBBB B--- ---- ----",
EF (l_sfgeu), OR32_W_FLAG, it_compare},
{"l.sfltu", "rA,rB", "11 0x9 00100 AAAAA BBBB B--- ---- ----",
EF (l_sfltu), OR32_W_FLAG, it_compare},
{"l.sfleu", "rA,rB", "11 0x9 00101 AAAAA BBBB B--- ---- ----",
EF (l_sfleu), OR32_W_FLAG, it_compare},
{"l.sfgts", "rA,rB", "11 0x9 01010 AAAAA BBBB B--- ---- ----",
EF (l_sfgts), OR32_W_FLAG, it_compare},
{"l.sfges", "rA,rB", "11 0x9 01011 AAAAA BBBB B--- ---- ----",
EF (l_sfges), OR32_W_FLAG, it_compare},
{"l.sflts", "rA,rB", "11 0x9 01100 AAAAA BBBB B--- ---- ----",
EF (l_sflts), OR32_W_FLAG, it_compare},
{"l.sfles", "rA,rB", "11 0x9 01101 AAAAA BBBB B--- ---- ----",
EF (l_sfles), OR32_W_FLAG, it_compare},
 
{"l.cust5", "rD,rA,rB,L,K", "11 0xC DDDDD AAAAA BBBB BLLL LLLK KKKK", EFI,
0, it_unknown},
{"l.cust6", "", "11 0xD ----- ----- ---- ---- ---- ----", EFI,
0, it_unknown},
{"l.cust7", "", "11 0xE ----- ----- ---- ---- ---- ----", EFI,
0, it_unknown},
{"l.cust8", "", "11 0xF ----- ----- ---- ---- ---- ----", EFI,
0, it_unknown},
 
/* This section should not be defined in or1ksim, since it contains duplicates,
which would cause machine builder to complain. */
#ifdef HAS_CUST
{"l.cust5_1", "rD", "11 0xC DDDDD ----- ---- ---- ---- ----", EFI,
0, it_unknown},
{"l.cust5_2", "rD,rA", "11 0xC DDDDD AAAAA ---- ---- ---- ----", EFI,
0, it_unknown},
{"l.cust5_3", "rD,rA,rB", "11 0xC DDDDD AAAAA BBBB B--- ---- ----", EFI,
0, it_unknown},
 
{"l.cust6_1", "rD", "11 0xD DDDDD ----- ---- ---- ---- ----", EFI,
0, it_unknown},
{"l.cust6_2", "rD,rA", "11 0xD DDDDD AAAAA ---- ---- ---- ----", EFI,
0, it_unknown},
{"l.cust6_3", "rD,rA,rB", "11 0xD DDDDD AAAAA BBBB B--- ---- ----", EFI,
0, it_unknown},
 
{"l.cust7_1", "rD", "11 0xE DDDDD ----- ---- ---- ---- ----", EFI,
0, it_unknown},
{"l.cust7_2", "rD,rA", "11 0xE DDDDD AAAAA ---- ---- ---- ----", EFI,
0, it_unknown},
{"l.cust7_3", "rD,rA,rB", "11 0xE DDDDD AAAAA BBBB B--- ---- ----", EFI,
0, it_unknown},
 
{"l.cust8_1", "rD", "11 0xF DDDDD ----- ---- ---- ---- ----", EFI,
0, it_unknown},
{"l.cust8_2", "rD,rA", "11 0xF DDDDD AAAAA ---- ---- ---- ----", EFI,
0, it_unknown},
{"l.cust8_3", "rD,rA,rB", "11 0xF DDDDD AAAAA BBBB B--- ---- ----", EFI,
0, it_unknown},
#endif
 
{"", "", "", EFI, 0, 0} /* Dummy entry, not included in num_opcodes. This
* lets code examine entry i+1 without checking
* if we've run off the end of the table. */
};
 
#undef EFI
#undef EFN
#undef EF
 
CONST int num_opcodes =
((sizeof (or32_opcodes)) / (sizeof (struct or32_opcode))) - 1;
 
/* Calculates instruction length in bytes. Always 4 for OR32. */
int
insn_len (int insn_index)
{
insn_index = 0; /* Just to get rid that warning. */
return 4;
}
 
/* Is individual insn's operand signed or unsigned? */
int
letter_signed (char l)
{
CONST struct or32_letter *pletter;
 
for (pletter = or32_letters; pletter->letter != '\0'; pletter++)
if (pletter->letter == l)
return pletter->sign;
 
printf ("letter_signed(%c): Unknown letter.\n", l);
return 0;
}
 
/* Simple cache for letter ranges */
static int range_cache[256] = { 0 };
 
/* Number of letters in the individual lettered operand. */
int
letter_range (char l)
{
CONST struct or32_opcode *pinsn;
char *enc;
int range = 0;
 
/* Is value cached? */
if ((range = range_cache[(unsigned char) l]))
return range;
 
for (pinsn = or32_opcodes; strlen (pinsn->name); pinsn++)
{
if (strchr (pinsn->encoding, l))
{
for (enc = pinsn->encoding; *enc != '\0'; enc++)
if ((*enc == '0') && (*(enc + 1) == 'x'))
enc += 2;
else if (*enc == l)
range++;
return range_cache[(unsigned char) l] = range;
}
}
 
printf ("\nABORT: letter_range(%c): Never used letter.\n", l);
exit (1);
}
 
/* MM: Returns index of given instruction name. */
int
insn_index (char *insn)
{
int i, found = -1;
for (i = 0; i < num_opcodes; i++)
if (!strcmp (or32_opcodes[i].name, insn))
{
found = i;
break;
}
return found;
}
 
/* Returns name of the specified instruction index */
CONST char *
insn_name (int index)
{
if (index >= 0 && index < num_opcodes)
return or32_opcodes[index].name;
else
return "???";
}
 
#if defined(HAVE_EXECUTION) && SIMPLE_EXECUTION
void
l_none (struct iqueue_entry *current)
{
}
#elif defined(HAVE_EXECUTION) && DYNAMIC_EXECUTION
void
l_none (struct op_queue *opq, int *param_t, int delay_slot)
{
}
#else
void
l_none ()
{
}
#endif
 
/*** Finite automata for instruction decoding building code ***/
 
/* Find symbols in encoding. */
unsigned long
insn_extract (param_ch, enc_initial)
char param_ch;
char *enc_initial;
{
char *enc;
unsigned long ret = 0;
unsigned opc_pos = 32;
for (enc = enc_initial; *enc != '\0';)
if ((*enc == '0') && (*(enc + 1) == 'x'))
{
unsigned long tmp = strtol (enc + 2, NULL, 16);
opc_pos -= 4;
if (param_ch == '0' || param_ch == '1')
{
if (param_ch == '0')
tmp = 15 - tmp;
ret |= tmp << opc_pos;
}
enc += 3;
}
else
{
if (*enc == '0' || *enc == '1' || *enc == '-' || isalpha (*enc))
{
opc_pos--;
if (param_ch == *enc)
ret |= 1 << opc_pos;
}
enc++;
}
return ret;
}
 
#define MAX_AUTOMATA_SIZE (1200)
#define MAX_OP_TABLE_SIZE (1200)
#define MAX_LEN (8)
 
#ifndef MIN
# define MIN(x,y) ((x) < (y) ? (x) : (y))
#endif
 
unsigned long *automata;
int nuncovered;
int curpass = 0;
 
/* MM: Struct that holds runtime build information about instructions. */
struct temp_insn_struct *ti;
 
struct insn_op_struct *op_data, **op_start;
 
static void
or32_debug (int level, const char *format, ...)
{
#if DEBUG
char *p;
va_list ap;
 
if ((p = malloc (1000)) == NULL)
return;
va_start (ap, format);
(void) vsnprintf (p, 1000, format, ap);
va_end (ap);
printf ("%s\n", p);
fflush (stdout);
free (p);
#endif
}
 
/* Recursive utility function used to find best match and to build automata. */
static unsigned long *
cover_insn (unsigned long *cur, int pass, unsigned int mask)
{
int best_first = 0, best_len = 0, i, last_match = -1, ninstr = 0;
unsigned long cur_mask = mask;
unsigned long *next;
 
for (i = 0; i < num_opcodes; i++)
if (ti[i].in_pass == pass)
{
cur_mask &= ti[i].insn_mask;
ninstr++;
last_match = i;
}
 
or32_debug (8, "%08X %08lX\n", mask, cur_mask);
if (ninstr == 0)
return 0;
if (ninstr == 1)
{
/* Leaf holds instruction index. */
or32_debug (8, "%i>I%i %s\n", cur - automata, last_match,
or32_opcodes[last_match].name);
*cur = LEAF_FLAG | last_match;
cur++;
nuncovered--;
}
else
{
/* Find longest match. */
for (i = 0; i < 32; i++)
{
int len;
for (len = best_len + 1; len < MIN (MAX_LEN, 33 - i); len++)
{
unsigned long m = (1UL << ((unsigned long) len)) - 1;
or32_debug (9, " (%i(%08lX & %08lX>>%i = %08lX, %08lX)", len, m,
cur_mask, i, (cur_mask >> (unsigned) i),
(cur_mask >> (unsigned) i) & m);
if ((m & (cur_mask >> (unsigned) i)) == m)
{
best_len = len;
best_first = i;
or32_debug (9, "!");
}
else
break;
}
}
or32_debug (9, "\n");
if (!best_len)
{
fprintf (stderr, "%i instructions match mask 0x%08X:\n", ninstr,
mask);
for (i = 0; i < num_opcodes; i++)
if (ti[i].in_pass == pass)
fprintf (stderr, "%s ", or32_opcodes[i].name);
 
fprintf (stderr, "\n");
exit (1);
}
or32_debug (8, "%i> #### %i << %i (%i) ####\n", cur - automata, best_len,
best_first, ninstr);
*cur = best_first;
cur++;
*cur = (1 << best_len) - 1;
cur++;
next = cur;
/* Allocate space for pointers. */
cur += 1 << best_len;
cur_mask = (1 << (unsigned long) best_len) - 1;
 
for (i = 0; i < (1 << (unsigned long) best_len); i++)
{
int j;
unsigned long *c;
curpass++;
for (j = 0; j < num_opcodes; j++)
if (ti[j].in_pass == pass
&& ((ti[j].insn >> best_first) & cur_mask) ==
(unsigned long) i
&& ((ti[j].insn_mask >> best_first) & cur_mask) == cur_mask)
ti[j].in_pass = curpass;
 
or32_debug (9, "%08X %08lX %i\n", mask, cur_mask, best_first);
c = cover_insn (cur, curpass, mask & (~(cur_mask << best_first)));
if (c)
{
or32_debug (8, "%i> #%X -> %u\n", next - automata, i,
cur - automata);
*next = cur - automata;
cur = c;
}
else
{
or32_debug (8, "%i> N/A\n", next - automata);
*next = 0;
}
next++;
}
}
return cur;
}
 
/* Returns number of nonzero bits. */
static int
num_ones (unsigned long value)
{
int c = 0;
while (value)
{
if (value & 1)
c++;
value >>= 1;
}
return c;
}
 
/* Utility function, which converts parameters from or32_opcode format to more binary form.
Parameters are stored in ti struct. */
 
static struct insn_op_struct *
parse_params (CONST struct or32_opcode *opcode, struct insn_op_struct *cur)
{
char *args = opcode->args;
int i, type;
int num_cur_op = 0;;
 
i = 0;
type = 0;
/* In case we don't have any parameters, we add dummy read from r0. */
if (!(*args))
{
cur->type = OPTYPE_REG | OPTYPE_OP | OPTYPE_LAST;
cur->data = 0;
or32_debug (9, "#%08lX %08lX\n", cur->type, cur->data);
cur++;
return cur;
}
 
while (*args != '\0')
{
if (*args == 'r')
{
args++;
type |= OPTYPE_REG;
if (*args == 'D')
type |= OPTYPE_DST;
}
else if (isalpha (*args))
{
unsigned long arg;
arg = insn_extract (*args, opcode->encoding);
or32_debug (9, "%s : %08lX ------\n", opcode->name, arg);
if (letter_signed (*args))
{
type |= OPTYPE_SIG;
type |= ((num_ones (arg) - 1) << OPTYPE_SBIT_SHR) & OPTYPE_SBIT;
}
 
num_cur_op = 0;
/* Split argument to sequences of consecutive ones. */
while (arg)
{
int shr = 0;
unsigned long tmp = arg, mask = 0;
while ((tmp & 1) == 0)
{
shr++;
tmp >>= 1;
}
while (tmp & 1)
{
mask++;
tmp >>= 1;
}
cur->type = type | shr;
cur->data = mask;
arg &= ~(((1 << mask) - 1) << shr);
or32_debug (6, "|%08lX %08lX\n", cur->type, cur->data);
cur++;
num_cur_op++;
}
args++;
}
else if (*args == '(')
{
/* Next param is displacement. Later we will treat them as one operand. */
/* Set the OPTYPE_DIS flag on all insn_op_structs that belong to this
* operand */
while (num_cur_op > 0)
{
cur[-num_cur_op].type |= type | OPTYPE_DIS;
num_cur_op--;
}
cur[-1].type |= OPTYPE_OP;
or32_debug (9, ">%08lX %08lX\n", cur->type, cur->data);
type = 0;
i++;
args++;
}
else if (*args == OPERAND_DELIM)
{
cur--;
cur->type = type | cur->type | OPTYPE_OP;
or32_debug (9, ">%08lX %08lX\n", cur->type, cur->data);
cur++;
type = 0;
i++;
args++;
}
else if (*args == '0')
{
cur->type = type;
cur->data = 0;
or32_debug (9, ">%08lX %08lX\n", cur->type, cur->data);
cur++;
type = 0;
i++;
args++;
}
else if (*args == ')')
args++;
else
{
fprintf (stderr, "%s : parse error in args.\n", opcode->name);
exit (1);
}
}
cur--;
cur->type = type | cur->type | OPTYPE_OP | OPTYPE_LAST;
or32_debug (9, "#%08lX %08lX\n", cur->type, cur->data);
cur++;
return cur;
}
 
/* Constructs new automata based on or32_opcodes array. */
 
void
build_automata ()
{
int i;
unsigned long *end;
struct insn_op_struct *cur;
 
automata =
(unsigned long *) malloc (MAX_AUTOMATA_SIZE * sizeof (unsigned long));
ti =
(struct temp_insn_struct *) malloc (sizeof (struct temp_insn_struct) *
num_opcodes);
 
nuncovered = num_opcodes;
 
#ifdef HAVE_EXECUTION
printf ("Building automata... ");
#endif
 
/* Build temporary information about instructions. */
for (i = 0; i < num_opcodes; i++)
{
unsigned long ones, zeros;
char *encoding = or32_opcodes[i].encoding;
ones = insn_extract ('1', encoding);
zeros = insn_extract ('0', encoding);
ti[i].insn_mask = ones | zeros;
ti[i].insn = ones;
ti[i].in_pass = curpass = 0;
/*debug(9, "%s: %s %08X %08X\n", or32_opcodes[i].name,
or32_opcodes[i].encoding, ti[i].insn_mask, ti[i].insn); */
}
 
/* Until all are covered search for best criteria to separate them. */
end = cover_insn (automata, curpass, 0xFFFFFFFF);
if (end - automata > MAX_AUTOMATA_SIZE)
{
fprintf (stderr, "Automata too large. Increase MAX_AUTOMATA_SIZE.");
exit (1);
}
#ifdef HAVE_EXECUTION
printf ("done, num uncovered: %i/%i.\n", nuncovered, num_opcodes);
#endif
 
#ifdef HAVE_EXECUTION
printf ("Parsing operands data... ");
#endif
op_data =
(struct insn_op_struct *) malloc (MAX_OP_TABLE_SIZE *
sizeof (struct insn_op_struct));
op_start =
(struct insn_op_struct **) malloc (num_opcodes *
sizeof (struct insn_op_struct *));
cur = op_data;
for (i = 0; i < num_opcodes; i++)
{
op_start[i] = cur;
cur = parse_params (&or32_opcodes[i], cur);
if (cur - op_data > MAX_OP_TABLE_SIZE)
{
fprintf (stderr,
"Operands table too small, increase MAX_OP_TABLE_SIZE.\n");
exit (1);
}
}
#ifdef HAVE_EXECUTION
printf ("done.\n");
#endif
}
 
void
destruct_automata ()
{
free (ti);
free (automata);
free (op_data);
free (op_start);
}
 
/* Decodes instruction and returns instruction index. */
int
insn_decode (unsigned int insn)
{
unsigned long *a = automata;
int i;
while (!(*a & LEAF_FLAG))
{
unsigned int first = *a;
//debug(9, "%i ", a - automata);
a++;
i = (insn >> first) & *a;
a++;
if (!*(a + i))
{ /* Invalid instruction found? */
//debug(9, "XXX\n", i);
return -1;
}
a = automata + *(a + i);
}
i = *a & ~LEAF_FLAG;
//debug(9, "%i\n", i);
/* Final check - do we have direct match?
(based on or32_opcodes this should be the only possibility,
but in case of invalid/missing instruction we must perform a check) */
if ((ti[i].insn_mask & insn) == ti[i].insn)
return i;
else
return -1;
}
 
static char disassembled_str[50];
char *disassembled = &disassembled_str[0];
 
/* Automagically does zero- or sign- extension and also finds correct
sign bit position if sign extension is correct extension. Which extension
is proper is figured out from letter description. */
 
unsigned long
extend_imm (unsigned long imm, char l)
{
unsigned long mask;
int letter_bits;
 
/* First truncate all bits above valid range for this letter
in case it is zero extend. */
letter_bits = letter_range (l);
mask = (1 << letter_bits) - 1;
imm &= mask;
 
/* Do sign extend if this is the right one. */
if (letter_signed (l) && (imm >> (letter_bits - 1)))
imm |= (~mask);
 
return imm;
}
 
unsigned long
or32_extract (param_ch, enc_initial, insn)
char param_ch;
char *enc_initial;
unsigned long insn;
{
char *enc;
unsigned long ret = 0;
int opc_pos = 0;
int param_pos = 0;
 
for (enc = enc_initial; *enc != '\0'; enc++)
if (*enc == param_ch)
{
if (enc - 2 >= enc_initial && (*(enc - 2) == '0')
&& (*(enc - 1) == 'x'))
continue;
else
param_pos++;
}
 
#if DEBUG
printf ("or32_extract: %x ", param_pos);
#endif
opc_pos = 32;
for (enc = enc_initial; *enc != '\0';)
if ((*enc == '0') && (*(enc + 1) == 'x'))
{
opc_pos -= 4;
if ((param_ch == '0') || (param_ch == '1'))
{
unsigned long tmp = strtol (enc, NULL, 16);
#if DEBUG
printf (" enc=%s, tmp=%x ", enc, tmp);
#endif
if (param_ch == '0')
tmp = 15 - tmp;
ret |= tmp << opc_pos;
}
enc += 3;
}
else if ((*enc == '0') || (*enc == '1'))
{
opc_pos--;
if (param_ch == *enc)
ret |= 1 << opc_pos;
enc++;
}
else if (*enc == param_ch)
{
opc_pos--;
param_pos--;
#if DEBUG
printf ("\n ret=%x opc_pos=%x, param_pos=%x\n", ret, opc_pos,
param_pos);
#endif
if (islower (param_ch))
ret -= ((insn >> opc_pos) & 0x1) << param_pos;
else
ret += ((insn >> opc_pos) & 0x1) << param_pos;
enc++;
}
else if (isalpha (*enc))
{
opc_pos--;
enc++;
}
else if (*enc == '-')
{
opc_pos--;
enc++;
}
else
enc++;
 
#if DEBUG
printf ("ret=%x\n", ret);
#endif
return ret;
}
 
/* Print register. Used only by print_insn. */
 
static char *
or32_print_register (dest, param_ch, encoding, insn)
char *dest;
char param_ch;
char *encoding;
unsigned long insn;
{
int regnum = or32_extract (param_ch, encoding, insn);
 
sprintf (dest, "r%d", regnum);
while (*dest)
dest++;
return dest;
}
 
/* Print immediate. Used only by print_insn. */
 
static char *
or32_print_immediate (dest, param_ch, encoding, insn)
char *dest;
char param_ch;
char *encoding;
unsigned long insn;
{
int imm = or32_extract (param_ch, encoding, insn);
 
imm = extend_imm (imm, param_ch);
 
if (letter_signed (param_ch))
{
if (imm < 0)
sprintf (dest, "%d", imm);
else
sprintf (dest, "0x%x", imm);
}
else
sprintf (dest, "%#x", imm);
while (*dest)
dest++;
return dest;
}
 
/* Disassemble one instruction from insn to disassemble.
Return the size of the instruction. */
 
int
disassemble_insn (insn)
unsigned long insn;
{
return disassemble_index (insn, insn_decode (insn));
}
 
/* Disassemble one instruction from insn index.
Return the size of the instruction. */
 
int
disassemble_index (insn, index)
unsigned long insn;
int index;
{
char *dest = disassembled;
if (index >= 0)
{
struct or32_opcode const *opcode = &or32_opcodes[index];
char *s;
 
strcpy (dest, opcode->name);
while (*dest)
dest++;
*dest++ = ' ';
*dest = 0;
 
for (s = opcode->args; *s != '\0'; ++s)
{
switch (*s)
{
case '\0':
return insn_len (insn);
 
case 'r':
dest = or32_print_register (dest, *++s, opcode->encoding, insn);
break;
 
default:
if (strchr (opcode->encoding, *s))
dest =
or32_print_immediate (dest, *s, opcode->encoding, insn);
else
{
*dest++ = *s;
*dest = 0;
}
}
}
}
else
{
/* This used to be %8x for binutils. */
sprintf (dest, ".word 0x%08lx", insn);
while (*dest)
dest++;
}
return insn_len (insn);
}
/op-support.c
0,0 → 1,114
/* op-support.c -- Support routines for micro operations
 
 
This file is part of OpenRISC 1000 Architectural Simulator.
 
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
 
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
 
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
 
 
#include <stdlib.h>
 
#include "config.h"
 
#ifdef HAVE_INTTYPES_H
#include <inttypes.h>
#endif
 
#include "port.h"
#include "arch.h"
#include "opcode/or32.h"
#include "sim-config.h"
#include "spr-defs.h"
#include "except.h"
#include "immu.h"
#include "abstract.h"
#include "execute.h"
#include "sched.h"
 
#include "i386-regs.h"
 
#include "dyn-rec.h"
#include "op-support.h"
 
/* Stuff that is really a `micro' operation but is rather big (or for some other
* reason like calling exit()) */
 
void op_support_nop_exit(void)
{
PRINTF("exit(%"PRIdREG")\n", cpu_state.reg[3]);
fprintf(stderr, "@reset : cycles %lld, insn #%lld\n",
runtime.sim.reset_cycles, runtime.cpu.reset_instructions);
fprintf(stderr, "@exit : cycles %lld, insn #%lld\n", runtime.sim.cycles,
runtime.cpu.instructions);
fprintf(stderr, " diff : cycles %lld, insn #%lld\n",
runtime.sim.cycles - runtime.sim.reset_cycles,
runtime.cpu.instructions - runtime.cpu.reset_instructions);
/* FIXME: Implement emulation of a stalled cpu
if (config.debug.gdb_enabled)
set_stall_state (1);
else {
handle_sim_command();
sim_done();
}
*/
exit(0);
}
 
void op_support_nop_reset(void)
{
PRINTF("****************** counters reset ******************\n");
PRINTF("cycles %lld, insn #%lld\n", runtime.sim.cycles, runtime.cpu.instructions);
PRINTF("****************** counters reset ******************\n");
runtime.sim.reset_cycles = runtime.sim.cycles;
runtime.cpu.reset_instructions = runtime.cpu.instructions;
}
 
void op_support_nop_printf(void)
{
simprintf(cpu_state.reg[4], cpu_state.reg[3]);
}
 
void op_support_nop_report(void)
{
PRINTF("report(0x%"PRIxREG");\n", cpu_state.reg[3]);
}
 
void op_support_nop_report_imm(int imm)
{
PRINTF("report %i (0x%"PRIxREG");\n", imm, cpu_state.reg[3]);
}
 
/* Handles a jump */
/* addr is a VIRTUAL address */
/* NOTE: We can't use env since this code is compiled like the rest of the
* simulator (most likely without -fomit-frame-pointer) and thus env will point
* to some bogus value. */
void do_jump(oraddr_t addr)
{
cpu_state.pc = addr;
longjmp(cpu_state.excpt_loc, 0);
}
 
/* Wrapper around analysis() that contains all the recompiler specific stuff */
void op_support_analysis(void)
{
oraddr_t off = (cpu_state.pc & immu_state->page_offset_mask) >> 2;
runtime.cpu.instructions++;
cpu_state.iqueue.insn_index = cpu_state.curr_page->insn_indexs[off];
cpu_state.iqueue.insn = cpu_state.curr_page->insns[off];
cpu_state.iqueue.insn_addr = cpu_state.pc;
analysis(&cpu_state.iqueue);
}
 
/op-lwhb-op.h
0,0 → 1,38
/* op-lwhb-op.h -- Micro operations template for load operations
 
 
This file is part of OpenRISC 1000 Architectural Simulator.
 
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
 
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
 
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
 
 
/* FIXME: Do something if a breakpoint is hit */
 
#ifdef OP_2T
__or_dynop void glue(glue(op_, LS_OP_NAME), T)(void)
{
int breakpoint;
T0 = LS_OP_CAST LS_OP_FUNC(T1 + OP_PARAM1, &breakpoint);
}
#endif
 
#ifdef OP_1T
__or_dynop void glue(glue(glue(op_, LS_OP_NAME), _imm), T)(void)
{
int breakpoint;
T0 = LS_OP_CAST LS_OP_FUNC(OP_PARAM1, &breakpoint);
}
#endif
 
/op-comp-op.h
0,0 → 1,50
/* op-comp-op.h -- Micro operations template for comparison operations
 
 
This file is part of OpenRISC 1000 Architectural Simulator.
 
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
 
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
 
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
 
#ifdef OP_2T
__or_dynop void glue(glue(op_, COMP_NAME), T)(void)
{
if(COMP_CAST(T0) COMP COMP_CAST(T1))
env->sprs[SPR_SR] |= SPR_SR_F;
else
env->sprs[SPR_SR] &= ~SPR_SR_F;
FORCE_RET;
}
#endif
 
#ifdef OP_1T
__or_dynop void glue(glue(glue(op_, COMP_NAME), _imm), T)(void)
{
if(COMP_CAST(T0) COMP COMP_CAST(OP_PARAM1))
env->sprs[SPR_SR] |= SPR_SR_F;
else
env->sprs[SPR_SR] &= ~SPR_SR_F;
FORCE_RET;
}
 
__or_dynop void glue(glue(glue(op_, COMP_NAME), _null), T)(void)
{
if(COMP_CAST(T0) COMP 0)
env->sprs[SPR_SR] |= SPR_SR_F;
else
env->sprs[SPR_SR] &= ~SPR_SR_F;
FORCE_RET;
}
#endif
 
/op-support.h
0,0 → 1,28
/* op-support.h -- Definitions of support routines for operations
 
 
This file is part of OpenRISC 1000 Architectural Simulator.
 
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
 
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
 
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
 
void op_support_nop_exit(void);
void op_support_nop_reset(void);
void op_support_nop_printf(void);
void op_support_nop_report(void);
void op_support_nop_report_imm(int imm);
void op_support_analysis(void);
void do_jump(oraddr_t addr);
 
void upd_reg_from_t(oraddr_t pc, int bound);
/op-swhb-op.h
0,0 → 1,62
/* op-swhb-op.h -- Micro operations template for store operations
 
 
Copyright (C) 2008 Embecosm Limited
 
Contributor Jeremy Bennett <jeremy.bennett@embecosm.com>
 
This file is part of Or1ksim, the OpenRISC 1000 Architectural Simulator.
 
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 3 of the License, or (at your option)
any later version.
 
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
more details.
 
You should have received a copy of the GNU General Public License along
with this program. If not, see <http://www.gnu.org/licenses/>. */
 
/* This program is commented throughout in a fashion suitable for processing
with Doxygen. */
 
/* FIXME: Do something with breakpoint */
 
 
#ifndef OP_SWHB_OP__H
#define OP_SWHB_OP__H
 
#ifdef OP_2T
__or_dynop void glue (glue (op_, S_OP_NAME), T) (void)
{
int breakpoint;
S_FUNC (T0 + OP_PARAM1, T1, &breakpoint);
}
#endif
 
#ifdef OP_1T
__or_dynop void glue (glue (glue (op_, S_OP_NAME), _imm), T) (void)
{
int breakpoint;
S_FUNC (OP_PARAM1, T0, &breakpoint);
}
 
__or_dynop void glue (glue (glue (op_, S_OP_NAME), _clear), T) (void)
{
int breakpoint;
S_FUNC (T0 + OP_PARAM1, 0, &breakpoint);
}
#endif
 
#if !defined(OP_1T) && !defined(OP_2T)
__or_dynop void glue (glue (op_, S_OP_NAME), _clear_imm) (void)
{
int breakpoint;
S_FUNC (OP_PARAM1, 0, &breakpoint);
}
#endif
 
#endif /* OP_SWHB_OP__H */
/dyn-rec.c
0,0 → 1,2448
/* dyn-rec.c -- Dynamic recompiler implementation for or32
 
 
This file is part of OpenRISC 1000 Architectural Simulator.
 
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
 
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
 
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
 
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>
#include <signal.h>
#include <errno.h>
#include <execinfo.h>
 
#include "config.h"
 
#ifdef HAVE_INTTYPES_H
#include <inttypes.h>
#endif
 
#include "port.h"
#include "arch.h"
#include "immu.h"
#include "abstract.h"
#include "opcode/or32.h"
#include "spr-defs.h"
#include "execute.h"
#include "except.h"
#include "spr-defs.h"
#include "sim-config.h"
#include "sched.h"
 
#include "i386-regs.h"
 
#include "def-op-t.h"
#include "dyn-rec.h"
#include "gen-ops.h"
 
#include "op-support.h"
 
/* NOTE: All openrisc (or) addresses in this file are *PHYSICAL* addresses */
 
/* FIXME: Optimise sorted list adding */
 
typedef void (*generic_gen_op)(struct op_queue *opq, int end);
typedef void (*imm_gen_op)(struct op_queue *opq, int end, uorreg_t imm);
 
void gen_l_invalid(struct op_queue *opq, int param_t[3], int delay_slot);
 
/* ttg->temporary to gpr */
DEF_GPR_OP(generic_gen_op, gen_op_move_gpr_t, gen_op_ttg_gpr);
/* gtt->gpr to temporary */
DEF_GPR_OP(generic_gen_op, gen_op_move_t_gpr, gen_op_gtt_gpr);
 
DEF_1T_OP(imm_gen_op, calc_insn_ea_table, gen_op_calc_insn_ea);
 
/* Linker stubs. This will allow the linker to link in op.o. The relocations
* that the linker does for these will be irrelevent anyway, since we patch the
* relocations during recompilation. */
uorreg_t __op_param1;
uorreg_t __op_param2;
uorreg_t __op_param3;
 
/* The number of bytes that a dynamicly recompiled page should be enlarged by */
#define RECED_PAGE_ENLARGE_BY 51200
 
/* The number of entries that the micro operations array in op_queue should be
* enlarged by */
#define OPS_ENLARGE_BY 5
 
#define T_NONE (-1)
 
/* Temporary is used as a source operand */
#define TFLAG_SRC 1
/* Temporary is used as a destination operand */
#define TFLAG_DST 2
/* Temporary has been saved to permanent storage */
#define TFLAG_SAVED 4
/* Temporary contains the value of the register before the instruction execution
* occurs (either by an explicit reg->t move or implicitly being left over from
* a previous instruction) */
#define TFLAG_SOURCED 8
 
/* FIXME: Put this into some header */
extern int do_stats;
 
static int sigsegv_state = 0;
static void *sigsegv_addr = NULL;
 
void dyn_ret_stack_prot(void);
 
void dyn_sigsegv_debug(int u, siginfo_t *siginf, void *dat)
{
struct dyn_page *dp;
FILE *f;
char filen[18]; /* 18 == strlen("or_page.%08x") + 1 */
int i;
struct sigcontext *sigc = dat;
 
if(!sigsegv_state) {
sigsegv_addr = siginf->si_addr;
} else {
fprintf(stderr, "Nested SIGSEGV occured, dumping next chuck of info\n");
sigsegv_state++;
}
 
/* First dump all the data that does not need dereferenceing to get */
switch(sigsegv_state) {
case 0:
fflush(stderr);
fprintf(stderr, "Segmentation fault on acces to %p at 0x%08lx, (or address: 0x%"PRIxADDR")\n\n",
sigsegv_addr, sigc->eip, cpu_state.pc);
sigsegv_state++;
case 1:
/* Run through the recompiled pages, dumping them to disk as we go */
for(i = 0; i < (2 << (32 - immu_state->pagesize_log2)); i++) {
dp = cpu_state.dyn_pages[i];
if(!dp)
continue;
fprintf(stderr, "Dumping%s page 0x%"PRIxADDR" recompiled to %p (len: %u) to disk\n",
dp->dirty ? " dirty" : "", dp->or_page, dp->host_page,
dp->host_len);
fflush(stdout);
 
sprintf(filen, "or_page.%"PRIxADDR, dp->or_page);
if(!(f = fopen(filen, "w"))) {
fprintf(stderr, "Unable to open %s to dump the recompiled page to: %s\n",
filen, strerror(errno));
continue;
}
if(fwrite(dp->host_page, dp->host_len, 1, f) < 1)
fprintf(stderr, "Unable to write recompiled data to file: %s\n",
strerror(errno));
 
fclose(f);
}
sigsegv_state++;
case 2:
sim_done();
}
}
 
struct dyn_page *new_dp(oraddr_t page)
{
struct dyn_page *dp = malloc(sizeof(struct dyn_page));
dp->or_page = IADDR_PAGE(page);
 
dp->locs = malloc(sizeof(void *) * (immu_state->pagesize / 4));
 
dp->host_len = 0;
dp->host_page = NULL;
dp->dirty = 1;
 
if(do_stats) {
dp->insns = malloc(immu_state->pagesize);
dp->insn_indexs = malloc(sizeof(unsigned int) * (immu_state->pagesize / 4));
}
 
cpu_state.dyn_pages[dp->or_page >> immu_state->pagesize_log2] = dp;
return dp;
}
 
void dyn_main(void)
{
struct dyn_page *target_dp;
oraddr_t phys_page;
 
setjmp(cpu_state.excpt_loc);
for(;;) {
phys_page = immu_translate(cpu_state.pc);
 
/*
printf("Recompiled code jumping out to %"PRIxADDR" from %"PRIxADDR"\n",
phys_page, cpu_state.sprs[SPR_PPC] - 4);
*/
 
/* immu_translate() adds the hit delay to runtime.sim.mem_cycles but we add
* it to the cycles when the instruction is executed so if we don't reset it
* now it will produce wrong results */
runtime.sim.mem_cycles = 0;
 
target_dp = cpu_state.dyn_pages[phys_page >> immu_state->pagesize_log2];
 
if(!target_dp)
target_dp = new_dp(phys_page);
 
/* Since writes to the 0x0-0xff range do not dirtyfy a page recompile the
* 0x0 page if the jump is to that location */
if(phys_page < 0x100)
target_dp->dirty = 1;
 
if(target_dp->dirty)
recompile_page(target_dp);
 
cpu_state.curr_page = target_dp;
 
/* FIXME: If the page is backed by more than one type of memory, this will
* produce wrong results */
cpu_state.cycles_dec = target_dp->delayr;
if(cpu_state.sprs[SPR_SR] & SPR_SR_IME)
/* Add the mmu hit delay to the cycle counter */
cpu_state.cycles_dec -= immu_state->hitdelay;
 
/* FIXME: ebp, ebx, esi and edi are expected to be preserved across function
* calls but the recompiled code trashes them... */
enter_dyn_code(phys_page, target_dp);
}
}
 
static void immu_retranslate(void *dat)
{
int got_en_dis = (int)dat;
immu_translate(cpu_state.pc);
runtime.sim.mem_cycles = 0;
 
/* Only update the cycle decrementer if the mmu got enabled or disabled */
if(got_en_dis == IMMU_GOT_ENABLED)
/* Add the mmu hit delay to the cycle counter */
cpu_state.cycles_dec = cpu_state.curr_page->delayr - immu_state->hitdelay;
else if(got_en_dis == IMMU_GOT_DISABLED)
cpu_state.cycles_dec = cpu_state.curr_page->delayr;
}
 
/* This is called whenever the immu is either enabled/disabled or reconfigured
* while enabled. This checks if an itlb miss would occour and updates the immu
* hit delay counter */
void recheck_immu(int got_en_dis)
{
oraddr_t addr;
 
if(cpu_state.delay_insn)
addr = cpu_state.pc_delay;
else
addr = cpu_state.pc + 4;
 
if(IADDR_PAGE(cpu_state.pc) == IADDR_PAGE(addr))
/* Schedule a job to do immu_translate() */
SCHED_ADD(immu_retranslate, (void *)got_en_dis, 0);
}
 
/* Runs the scheduler. Called from except_handler (and dirtyfy_page below) */
void run_sched_out_of_line(void)
{
oraddr_t off = (cpu_state.pc & immu_state->page_offset_mask) >> 2;
 
if(do_stats) {
cpu_state.iqueue.insn_addr = cpu_state.pc;
cpu_state.iqueue.insn = cpu_state.curr_page->insns[off];
cpu_state.iqueue.insn_index = cpu_state.curr_page->insn_indexs[off];
runtime.cpu.instructions++;
analysis(&cpu_state.iqueue);
}
 
/* Run the scheduler */
scheduler.job_queue->time += cpu_state.cycles_dec;
runtime.sim.cycles -= cpu_state.cycles_dec;
 
op_join_mem_cycles();
if(scheduler.job_queue->time <= 0)
do_scheduler();
}
 
/* Signals a page as dirty */
static void dirtyfy_page(struct dyn_page *dp)
{
oraddr_t check;
 
printf("Dirtyfying page 0x%"PRIxADDR"\n", dp->or_page);
 
dp->dirty = 1;
 
/* If the execution is currently in the page that was touched then recompile
* it now and jump back to the point of execution */
check = cpu_state.delay_insn ? cpu_state.pc_delay : cpu_state.pc + 4;
if(IADDR_PAGE(check) == dp->or_page) {
run_sched_out_of_line();
recompile_page(dp);
 
cpu_state.delay_insn = 0;
 
/* Jump out to the next instruction */
do_jump(check);
}
}
 
/* Checks to see if a write happened to a recompiled page. If so marks it as
* dirty */
void dyn_checkwrite(oraddr_t addr)
{
/* FIXME: Do this with mprotect() */
struct dyn_page *dp = cpu_state.dyn_pages[addr >> immu_state->pagesize_log2];
 
/* Since the locations 0x0-0xff are nearly always written to in an exception
* handler, ignore any writes to these locations. If code ends up jumping
* out there, we'll recompile when the jump actually happens. */
if((addr > 0x100) && dp && !dp->dirty)
dirtyfy_page(dp);
}
 
/* Moves the temprary t to its permanent storage if it has been used as a
* destination register */
static void ship_t_out(struct op_queue *opq, unsigned int t)
{
unsigned int gpr = opq->reg_t[t];
 
for(; opq; opq = opq->prev) {
if(opq->reg_t[t] != gpr)
return;
if((opq->tflags[t] & TFLAG_DST) && !(opq->tflags[t] & TFLAG_SAVED)) {
opq->tflags[t] |= TFLAG_SAVED;
 
/* FIXME: Check if this is still neccesary */
/* Before takeing the temporaries out, temporarily remove the op_do_sched
* operation such that dyn_page->ts_bound shall be correct before the
* scheduler runs */
if(opq->num_ops && (opq->ops[opq->num_ops - 1] == op_do_sched_indx)) {
opq->num_ops--;
gen_op_move_gpr_t[t][gpr](opq, 1);
gen_op_do_sched(opq, 1);
return;
}
 
gen_op_move_gpr_t[t][gpr](opq, 1);
 
return;
}
}
}
 
static void ship_gprs_out_t(struct op_queue *opq)
{
int i;
 
if(!opq)
return;
 
for(i = 0; i < NUM_T_REGS; i++) {
if(opq->reg_t[i] < 32)
/* Ship temporaries out in the last opq that actually touched it */
ship_t_out(opq, i);
}
}
 
/* FIXME: Look at the following instructions to make a better guess at which
* temporary to return */
static int find_t(struct op_queue *opq, unsigned int reg)
{
int i, j, t = -1;
 
for(i = 0; i < NUM_T_REGS; i++) {
if(opq->reg_t[i] == reg)
return i;
 
/* Ok, we have found an as-yet unused temporary, check if it is needed
* later in this instruction */
for(j = 0; j < opq->param_num; j++) {
if((opq->param_type[j] & OPTYPE_REG) && (opq->param[j] == opq->reg_t[i]))
break;
}
 
if(j != opq->param_num)
continue;
 
/* We have found the temporary (temporarily:) fit for use */
if((t == -1) || (opq->reg_t[i] == 32))
t = i;
}
 
return t;
}
 
/* Checks if there is enough space in dp->host_page, if not grow it */
void *enough_host_page(struct dyn_page *dp, void *cur, unsigned int *len,
unsigned int amount)
{
unsigned int used = cur - dp->host_page;
 
/* The array is long enough */
if((used + amount) <= *len)
return cur;
 
/* Reallocate */
*len += RECED_PAGE_ENLARGE_BY;
 
if(!(dp->host_page = realloc(dp->host_page, *len))) {
fprintf(stderr, "OOM\n");
exit(1);
}
 
return dp->host_page + used;
}
 
/* Adds an operation to the opq */
void add_to_opq(struct op_queue *opq, int end, int op)
{
if(opq->num_ops == opq->ops_len) {
opq->ops_len += OPS_ENLARGE_BY;
if(!(opq->ops = realloc(opq->ops, opq->ops_len * sizeof(int)))) {
fprintf(stderr, "OOM\n");
exit(1);
}
}
 
if(end)
opq->ops[opq->num_ops] = op;
else {
/* Shift everything over by one */
memmove(opq->ops + 1, opq->ops, opq->num_ops* sizeof(int));
opq->ops[0] = op;
}
 
opq->num_ops++;
}
 
static void gen_op_mark_loc(struct op_queue *opq, int end)
{
add_to_opq(opq, end, op_mark_loc_indx);
}
 
/* Adds a parameter to the opq */
void add_to_op_params(struct op_queue *opq, int end, unsigned long param)
{
if(opq->num_ops_param == opq->ops_param_len) {
opq->ops_param_len += OPS_ENLARGE_BY;
if(!(opq->ops_param = realloc(opq->ops_param, opq->ops_param_len * sizeof(int)))) {
fprintf(stderr, "OOM\n");
exit(1);
}
}
 
if(end)
opq->ops_param[opq->num_ops_param] = param;
else {
/* Shift everything over by one */
memmove(opq->ops_param + 1, opq->ops_param, opq->num_ops_param);
opq->ops_param[0] = param;
}
 
opq->num_ops_param++;
}
 
/* Initialises the recompiler */
void init_dyn_recomp(void)
{
struct sigaction sigact;
struct op_queue *opq = NULL;
unsigned int i;
 
cpu_state.opqs = NULL;
 
/* Allocate the operation queue list (+1 for the page chaining) */
for(i = 0; i < (immu_state->pagesize / 4) + 1; i++) {
if(!(opq = malloc(sizeof(struct op_queue)))) {
fprintf(stderr, "OOM\n");
exit(1);
}
 
/* initialise some fields */
opq->ops_len = 0;
opq->ops = NULL;
opq->ops_param_len = 0;
opq->ops_param = NULL;
opq->xref = 0;
 
if(cpu_state.opqs)
cpu_state.opqs->prev = opq;
 
opq->next = cpu_state.opqs;
cpu_state.opqs = opq;
}
 
opq->prev = NULL;
 
cpu_state.curr_page = NULL;
if(!(cpu_state.dyn_pages = malloc(sizeof(void *) * (2 << (32 -
immu_state->pagesize_log2))))) {
fprintf(stderr, "OOM\n");
exit(1);
}
memset(cpu_state.dyn_pages, 0,
sizeof(void *) * (2 << (32 - immu_state->pagesize_log2)));
 
/* Register our segmentation fault handler */
sigact.sa_sigaction = dyn_sigsegv_debug;
memset(&sigact.sa_mask, 0, sizeof(sigact.sa_mask));
sigact.sa_flags = SA_SIGINFO | SA_NOMASK;
if(sigaction(SIGSEGV, &sigact, NULL))
printf("WARN: Unable to install SIGSEGV handler! Don't expect to be able to debug the recompiler.\n");
 
/* FIXME: Find a better place for this */
{ /* Needed by execution */
extern int do_stats;
do_stats = config.cpu.dependstats || config.cpu.superscalar || config.cpu.dependstats
|| config.sim.history || config.sim.exe_log;
}
 
printf("Recompile engine up and running\n");
}
 
/* Parses instructions and their operands and populates opq with them */
static void eval_insn_ops(struct op_queue *opq, oraddr_t addr)
{
int breakp;
struct insn_op_struct *opd;
 
for(; opq->next; opq = opq->next, addr += 4) {
opq->param_num = 0;
breakp = 0;
opq->insn = eval_insn(addr, &breakp);
 
/* FIXME: If a breakpoint is set at this location, insert exception code */
if(breakp) {
fprintf(stderr, "FIXME: Insert breakpoint code\n");
}
 
opq->insn_index = insn_decode(opq->insn);
 
if(opq->insn_index == -1)
continue;
 
opd = op_start[opq->insn_index];
do {
opq->param[opq->param_num] = eval_operand_val(opq->insn, opd);
opq->param_type[opq->param_num] = opd->type;
 
opq->param_num++;
while(!(opd->type & OPTYPE_OP)) opd++;
} while(!(opd++->type & OPTYPE_LAST));
}
}
 
/* Adds code to the opq for the instruction pointed to by addr */
static void recompile_insn(struct op_queue *opq, int delay_insn)
{
int j, k;
int param_t[5]; /* Which temporary the parameters reside in */
 
/* Check if we have an illegal instruction */
if(opq->insn_index == -1) {
gen_l_invalid(opq, NULL, delay_insn);
return;
}
 
/* If we are recompileing an instruction that has a delay slot and is in the
* delay slot, ignore it. This is undefined behavour. */
if(delay_insn && (or32_opcodes[opq->insn_index].flags & OR32_IF_DELAY))
return;
 
param_t[0] = T_NONE;
param_t[1] = T_NONE;
param_t[2] = T_NONE;
param_t[3] = T_NONE;
param_t[4] = T_NONE;
 
/* Jump instructions are special since they have a delay slot and thus they
* need to control the exact operation sequence. Special case these here to
* avoid haveing loads of if(!(.& OR32_IF_DELAY)) below */
if(or32_opcodes[opq->insn_index].flags & OR32_IF_DELAY) {
/* Jump instructions don't have a disposition */
or32_opcodes[opq->insn_index].exec(opq, param_t, delay_insn);
 
/* Analysis is done by the individual jump instructions */
/* Jump instructions don't touch runtime.sim.mem_cycles */
/* Jump instructions run their own scheduler */
return;
}
 
/* Before an exception takes place, all registers must be stored. */
if((or32_opcodes[opq->insn_index].func_unit == it_exception)) {
ship_gprs_out_t(opq);
 
or32_opcodes[opq->insn_index].exec(opq, param_t, delay_insn);
return;
}
 
for(j = 0; j < opq->param_num; j++) {
if(!(opq->param_type[j] & OPTYPE_REG))
continue;
 
/* Never, ever, move r0 into a temporary */
if(!opq->param[j])
continue;
 
k = find_t(opq, opq->param[j]);
 
param_t[j] = k;
 
if(opq->reg_t[k] == opq->param[j]) {
if(!(opq->param_type[j] & OPTYPE_DST) &&
!(opq->tflags[k] & TFLAG_SOURCED)) {
gen_op_move_t_gpr[k][opq->reg_t[k]](opq, 0);
opq->tflags[k] |= TFLAG_SOURCED;
}
 
if(opq->param_type[j] & OPTYPE_DST)
opq->tflags[k] |= TFLAG_DST;
else
opq->tflags[k] |= TFLAG_SRC;
 
continue;
}
 
if(opq->reg_t[k] < 32) {
/* Only ship the temporary out if it has been used as a destination
* register */
ship_t_out(opq, k);
}
 
if(opq->param_type[j] & OPTYPE_DST)
opq->tflags[k] = TFLAG_DST;
else
opq->tflags[k] = TFLAG_SRC;
 
opq->reg_t[k] = opq->param[j];
 
/* Only generate code to move the register into a temporary if it is used as
* a source operand */
if(!(opq->param_type[j] & OPTYPE_DST)) {
gen_op_move_t_gpr[k][opq->reg_t[k]](opq, 0);
opq->tflags[k] |= TFLAG_SOURCED;
}
}
 
/* To get the execution log correct for instructions like l.lwz r4,0(r4) the
* effective address needs to be calculated before the instruction is
* simulated */
if(do_stats) {
for(j = 0; j < opq->param_num; j++) {
if(!(opq->param_type[j] & OPTYPE_DIS))
continue;
 
if(!opq->param[j + 1])
gen_op_store_insn_ea(opq, 1, opq->param[j]);
else
calc_insn_ea_table[param_t[j + 1]](opq, 1, opq->param[j]);
}
}
 
or32_opcodes[opq->insn_index].exec(opq, param_t, delay_insn);
 
if(do_stats) {
ship_gprs_out_t(opq);
gen_op_analysis(opq, 1);
}
 
/* The call to join_mem_cycles() could be put into the individual operations
* that emulate the load/store instructions, but then it would be added to
* the cycle counter before analysis() is called, which is not how the complex
* execution model does it. */
if((or32_opcodes[opq->insn_index].func_unit == it_load) ||
(or32_opcodes[opq->insn_index].func_unit == it_store))
gen_op_join_mem_cycles(opq, 1);
 
/* Delay slot instructions get a special scheduler, thus don't generate it
* here */
if(!delay_insn)
gen_op_do_sched(opq, 1);
}
 
/* Recompiles the page associated with *dyn */
void recompile_page(struct dyn_page *dyn)
{
unsigned int j;
struct op_queue *opq = cpu_state.opqs;
oraddr_t rec_addr = dyn->or_page;
oraddr_t rec_page = dyn->or_page;
void **loc;
 
/* The start of the next page */
rec_page += immu_state->pagesize;
 
printf("Recompileing page %"PRIxADDR"\n", rec_addr);
fflush(stdout);
 
/* Mark all temporaries as not containing a register */
for(j = 0; j < NUM_T_REGS; j++) {
opq->reg_t[j] = 32; /* Out-of-range registers */
opq->tflags[j] = 0;
}
 
dyn->delayr = -verify_memoryarea(rec_addr)->ops.delayr;
 
opq->num_ops = 0;
opq->num_ops_param = 0;
 
eval_insn_ops(opq, rec_addr);
 
/* Insert code to check if the first instruction is exeucted in a delay slot*/
gen_op_check_delay_slot(opq, 1, 0);
recompile_insn(opq, 1);
ship_gprs_out_t(opq);
gen_op_do_sched_delay(opq, 1);
gen_op_clear_delay_insn(opq, 1);
gen_op_do_jump_delay(opq, 1);
gen_op_do_jump(opq, 1);
gen_op_mark_loc(opq, 1);
 
for(j = 0; j < NUM_T_REGS; j++)
opq->reg_t[j] = 32; /* Out-of-range registers */
 
for(; rec_addr < rec_page; rec_addr += 4, opq = opq->next) {
if(opq->prev) {
opq->num_ops = 0;
opq->num_ops_param = 0;
}
opq->jump_local = -1;
opq->not_jump_loc = -1;
 
opq->insn_addr = rec_addr;
for(j = 0; j < NUM_T_REGS; j++)
opq->tflags[j] = TFLAG_SOURCED;
 
/* Check if this location is cross referenced */
if(opq->xref) {
/* If the current address is cross-referenced, the temporaries shall be
* in an undefined state, so we must assume that no registers reside in
* them */
/* Ship out the current set of registers from the temporaries */
if(opq->prev) {
ship_gprs_out_t(opq->prev);
for(j = 0; j < NUM_T_REGS; j++) {
opq->reg_t[j] = 32;
opq->prev->reg_t[j] = 32;
}
}
}
 
recompile_insn(opq, 0);
 
/* Store the state of the temporaries */
memcpy(opq->next->reg_t, opq->reg_t, sizeof(opq->reg_t));
}
 
dyn->dirty = 0;
 
/* Ship temporaries out to the corrisponding registers */
ship_gprs_out_t(opq->prev);
 
opq->num_ops = 0;
opq->num_ops_param = 0;
opq->not_jump_loc = -1;
opq->jump_local = -1;
 
/* Insert code to jump to the next page */
gen_op_do_jump(opq, 1);
 
/* Generate the code */
gen_code(cpu_state.opqs, dyn);
 
/* Fix up the locations */
for(loc = dyn->locs; loc < &dyn->locs[immu_state->pagesize / 4]; loc++)
*loc += (unsigned int)dyn->host_page;
 
cpu_state.opqs->ops_param[0] += (unsigned int)dyn->host_page;
 
/* Search for page-local jumps */
opq = cpu_state.opqs;
for(j = 0; j < (immu_state->pagesize / 4); opq = opq->next, j++) {
if(opq->jump_local != -1)
opq->ops_param[opq->jump_local] =
(unsigned int)dyn->locs[opq->jump_local_loc >> 2];
 
if(opq->not_jump_loc != -1)
opq->ops_param[opq->not_jump_loc] = (unsigned int)dyn->locs[j + 1];
 
/* Store the state of the temporaries into dyn->ts_bound */
dyn->ts_bound[j] = 0;
if(opq->reg_t[0] < 32)
dyn->ts_bound[j] = opq->reg_t[0];
if(opq->reg_t[1] < 32)
dyn->ts_bound[j] |= opq->reg_t[1] << 5;
if(opq->reg_t[2] < 32)
dyn->ts_bound[j] |= opq->reg_t[2] << 10;
 
/* Reset for the next page to be recompiled */
opq->xref = 0;
}
 
/* Patch the relocations */
patch_relocs(cpu_state.opqs, dyn->host_page);
 
if(do_stats) {
opq = cpu_state.opqs;
for(j = 0; j < (immu_state->pagesize / 4); j++, opq = opq->next) {
dyn->insns[j] = opq->insn;
dyn->insn_indexs[j] = opq->insn_index;
}
}
 
/* FIXME: Fix the issue below in a more elegent way */
/* Since eval_insn is called to get the instruction, runtime.sim.mem_cycles is
* updated but the recompiler expectes it to start a 0, so reset it */
runtime.sim.mem_cycles = 0;
}
 
/* Recompiles a delay-slot instruction (opq is the opq of the instruction
* haveing the delay-slot) */
static void recompile_delay_insn(struct op_queue *opq)
{
struct op_queue delay_opq;
int i;
 
/* Setup a fake opq that looks very much like the delay slot instruction */
memcpy(&delay_opq, opq, sizeof(struct op_queue));
/* `Fix' a couple of bits */
for(i = 0; i < NUM_T_REGS; i++)
delay_opq.tflags[i] = TFLAG_SOURCED;
delay_opq.insn_index = opq->next->insn_index;
memcpy(delay_opq.param_type, opq->next->param_type, sizeof(delay_opq.param_type));
memcpy(delay_opq.param, opq->next->param, sizeof(delay_opq.param));
delay_opq.param_num = opq->next->param_num;
delay_opq.insn = opq->next->insn;
 
delay_opq.xref = 0;
delay_opq.insn_addr = opq->insn_addr + 4;
delay_opq.prev = opq->prev;
delay_opq.next = NULL;
 
/* Generate the delay slot instruction */
recompile_insn(&delay_opq, 1);
 
ship_gprs_out_t(&delay_opq);
 
opq->num_ops = delay_opq.num_ops;
opq->ops_len = delay_opq.ops_len;
opq->ops = delay_opq.ops;
opq->num_ops_param = delay_opq.num_ops_param;
opq->ops_param_len = delay_opq.ops_param_len;
opq->ops_param = delay_opq.ops_param;
 
for(i = 0; i < NUM_T_REGS; i++)
opq->reg_t[i] = 32;
}
 
/* Returns non-zero if the jump is into this page, 0 otherwise */
static int find_jump_loc(oraddr_t j_ea, struct op_queue *opq)
{
int i;
 
/* Mark the jump as non page local if the delay slot instruction is on the
* next page to the jump instruction. This should not be needed */
if(IADDR_PAGE(j_ea) != IADDR_PAGE(opq->insn_addr))
/* We can't do anything as the j_ea (as passed to find_jump_loc) is a
* VIRTUAL offset and the next physical page may not be the next VIRTUAL
* page */
return 0;
 
/* The jump is into the page currently undergoing dynamic recompilation */
 
/* If we haven't got to the location of the jump, everything is ok */
if(j_ea > opq->insn_addr) {
/* Find the corissponding opq and mark it as cross referenced */
for(i = (j_ea - opq->insn_addr) / 4; i; i--)
opq = opq->next;
opq->xref = 1;
return 1;
}
 
/* Insert temporary -> register code before the jump ea and register ->
* temporary at the x-ref address */
for(i = (opq->insn_addr - j_ea) / 4; i; i--)
opq = opq->prev;
 
if(!opq->prev)
/* We're at the begining of a page, no need to do anything */
return 1;
 
/* Found location, insert code */
 
ship_gprs_out_t(opq->prev);
 
for(i = 0; i < NUM_T_REGS; i++) {
if(opq->prev->reg_t[i] < 32)
/* FIXME: Ship temporaries in the begining of the opq that needs it */
gen_op_move_t_gpr[i][opq->prev->reg_t[i]](opq, 0);
}
 
opq->xref = 1;
 
return 1;
}
 
static void gen_j_imm(struct op_queue *opq, oraddr_t off)
{
int jump_local;
 
off <<= 2;
 
if(IADDR_PAGE(opq->insn_addr) != IADDR_PAGE(opq->insn_addr + 4)) {
gen_op_set_pc_delay_imm(opq, 1, off);
gen_op_do_sched(opq, 1);
return;
}
 
jump_local = find_jump_loc(opq->insn_addr + off, opq);
 
gen_op_set_delay_insn(opq, 1);
gen_op_do_sched(opq, 1);
 
recompile_delay_insn(opq);
 
gen_op_add_pc(opq, 1, (orreg_t)off - 8);
gen_op_clear_delay_insn(opq, 1);
gen_op_do_sched_delay(opq, 1);
 
if(jump_local) {
gen_op_jmp_imm(opq, 1, 0);
opq->jump_local = opq->num_ops_param - 1;
opq->jump_local_loc = (opq->insn_addr + (orreg_t)off) & immu_state->page_offset_mask;
} else
gen_op_do_jump(opq, 1);
}
 
static const generic_gen_op set_pc_delay_gpr[32] = {
NULL,
gen_op_move_gpr1_pc_delay,
gen_op_move_gpr2_pc_delay,
gen_op_move_gpr3_pc_delay,
gen_op_move_gpr4_pc_delay,
gen_op_move_gpr5_pc_delay,
gen_op_move_gpr6_pc_delay,
gen_op_move_gpr7_pc_delay,
gen_op_move_gpr8_pc_delay,
gen_op_move_gpr9_pc_delay,
gen_op_move_gpr10_pc_delay,
gen_op_move_gpr11_pc_delay,
gen_op_move_gpr12_pc_delay,
gen_op_move_gpr13_pc_delay,
gen_op_move_gpr14_pc_delay,
gen_op_move_gpr15_pc_delay,
gen_op_move_gpr16_pc_delay,
gen_op_move_gpr17_pc_delay,
gen_op_move_gpr18_pc_delay,
gen_op_move_gpr19_pc_delay,
gen_op_move_gpr20_pc_delay,
gen_op_move_gpr21_pc_delay,
gen_op_move_gpr22_pc_delay,
gen_op_move_gpr23_pc_delay,
gen_op_move_gpr24_pc_delay,
gen_op_move_gpr25_pc_delay,
gen_op_move_gpr26_pc_delay,
gen_op_move_gpr27_pc_delay,
gen_op_move_gpr28_pc_delay,
gen_op_move_gpr29_pc_delay,
gen_op_move_gpr30_pc_delay,
gen_op_move_gpr31_pc_delay };
 
static void gen_j_reg(struct op_queue *opq, unsigned int gpr)
{
int i;
 
/* Ship the jump-to register out (if it exists). It requires special
* handleing */
for(i = 0; i < NUM_T_REGS; i++) {
if(opq->reg_t[i] == opq->param[0])
/* Ship temporary out in the last opq that used it */
ship_t_out(opq, i);
}
 
if(do_stats)
gen_op_analysis(opq, 1);
 
if(!gpr)
gen_op_clear_pc_delay(opq, 1);
else
set_pc_delay_gpr[gpr](opq, 1);
 
gen_op_do_sched(opq, 1);
 
if(IADDR_PAGE(opq->insn_addr) != IADDR_PAGE(opq->insn_addr + 4))
return;
 
recompile_delay_insn(opq);
 
gen_op_set_pc_pc_delay(opq, 1);
gen_op_clear_delay_insn(opq, 1);
gen_op_do_sched_delay(opq, 1);
 
gen_op_do_jump_delay(opq, 1);
gen_op_do_jump(opq, 1);
}
 
/*------------------------------[ Operation generation for an instruction ]---*/
/* FIXME: Flag setting is not done in any instruction */
/* FIXME: Since r0 is not moved into a temporary, check all arguments below! */
 
DEF_1T_OP(generic_gen_op, clear_t, gen_op_clear);
DEF_2T_OP_NEQ(generic_gen_op, move_t_t, gen_op_move);
DEF_1T_OP(imm_gen_op, mov_t_imm, gen_op_imm);
 
DEF_2T_OP(imm_gen_op, l_add_imm_t_table, gen_op_add_imm);
DEF_3T_OP(generic_gen_op, l_add_t_table, gen_op_add);
 
void gen_l_add(struct op_queue *opq, int param_t[3], int delay_slot)
{
if(!opq->param[0])
/* Screw this, the operation shall do nothing */
return;
 
if(!opq->param[1] && !opq->param[2]) {
/* Just clear param_t[0] */
clear_t[param_t[0]](opq, 1);
return;
}
 
if(!opq->param[2]) {
if(opq->param[0] != opq->param[1])
/* This just moves a register */
move_t_t[param_t[0]][param_t[1]](opq, 1);
return;
}
 
if(!opq->param[1]) {
/* Check if we are moveing an immediate */
if(param_t[2] == T_NONE) {
/* Yep, an immediate */
mov_t_imm[param_t[0]](opq, 1, opq->param[2]);
return;
}
/* Just another move */
if(opq->param[0] != opq->param[2])
move_t_t[param_t[0]][param_t[2]](opq, 1);
return;
}
 
/* Ok, This _IS_ an add... */
if(param_t[2] == T_NONE)
/* immediate */
l_add_imm_t_table[param_t[0]][param_t[1]](opq, 1, opq->param[2]);
else
l_add_t_table[param_t[0]][param_t[1]][param_t[2]](opq, 1);
}
 
DEF_3T_OP(generic_gen_op, l_addc_t_table, gen_op_addc);
 
void gen_l_addc(struct op_queue *opq, int param_t[3], int delay_slot)
{
if(!opq->param[0])
/* Screw this, the operation shall do nothing */
return;
 
/* FIXME: More optimisations !! (...and immediate...) */
l_addc_t_table[param_t[0]][param_t[1]][param_t[2]](opq, 1);
}
 
DEF_2T_OP(imm_gen_op, l_and_imm_t_table, gen_op_and_imm);
DEF_3T_OP_NEQ(generic_gen_op, l_and_t_table, gen_op_and);
 
void gen_l_and(struct op_queue *opq, int param_t[3], int delay_slot)
{
if(!opq->param[0])
/* Screw this, the operation shall do nothing */
return;
 
if(!opq->param[1] || !opq->param[2]) {
/* Just clear param_t[0] */
clear_t[param_t[0]](opq, 1);
return;
}
 
if((opq->param[0] == opq->param[1] == opq->param[2]) && (param_t[2] != T_NONE))
return;
 
if(param_t[2] == T_NONE)
l_and_imm_t_table[param_t[0]][param_t[1]](opq, 1, opq->param[2]);
else
l_and_t_table[param_t[0]][param_t[1]][param_t[2]](opq, 1);
}
 
void gen_l_bf(struct op_queue *opq, int param_t[3], int delay_slot)
{
if(do_stats)
/* All gprs are current since this insn doesn't touch any reg */
gen_op_analysis(opq, 1);
 
/* The temporaries are expected to be shiped out after the execution of the
* branch instruction wether it branched or not */
ship_gprs_out_t(opq->prev);
 
if(IADDR_PAGE(opq->insn_addr) != IADDR_PAGE(opq->insn_addr + 4)) {
gen_op_check_flag_delay(opq, 1, opq->param[0] << 2);
gen_op_do_sched(opq, 1);
opq->not_jump_loc = -1;
return;
}
gen_op_check_flag(opq, 1, 0);
opq->not_jump_loc = opq->num_ops_param - 1;
 
gen_j_imm(opq, opq->param[0]);
}
 
void gen_l_bnf(struct op_queue *opq, int param_t[3], int delay_slot)
{
if(do_stats)
/* All gprs are current since this insn doesn't touch any reg */
gen_op_analysis(opq, 1);
 
/* The temporaries are expected to be shiped out after the execution of the
* branch instruction wether it branched or not */
ship_gprs_out_t(opq->prev);
 
if(IADDR_PAGE(opq->insn_addr) != IADDR_PAGE(opq->insn_addr + 4)) {
gen_op_check_not_flag_delay(opq, 1, opq->param[0] << 2);
gen_op_do_sched(opq, 1);
opq->not_jump_loc = -1;
return;
}
 
gen_op_check_not_flag(opq, 1, 0);
opq->not_jump_loc = opq->num_ops_param - 1;
 
gen_j_imm(opq, opq->param[0]);
}
 
DEF_3T_OP_NEQ(generic_gen_op, l_cmov_t_table, gen_op_cmov);
 
/* FIXME: Check if either opperand 1 or 2 is r0 */
void gen_l_cmov(struct op_queue *opq, int param_t[3], int delay_slot)
{
if(!opq->param[0])
return;
 
if(!opq->param[1] && !opq->param[2]) {
clear_t[param_t[0]](opq, 1);
return;
}
 
if((opq->param[1] == opq->param[2]) && (opq->param[0] == opq->param[1]))
return;
 
if(opq->param[1] == opq->param[2]) {
move_t_t[param_t[0]][param_t[1]](opq, 1);
return;
}
 
l_cmov_t_table[param_t[0]][param_t[1]][param_t[2]](opq, 1);
}
 
void gen_l_cust1(struct op_queue *opq, int param_t[3], int delay_slot)
{
}
 
void gen_l_cust2(struct op_queue *opq, int param_t[3], int delay_slot)
{
}
 
void gen_l_cust3(struct op_queue *opq, int param_t[3], int delay_slot)
{
}
 
void gen_l_cust4(struct op_queue *opq, int param_t[3], int delay_slot)
{
}
 
void gen_l_cust5(struct op_queue *opq, int param_t[3], int delay_slot)
{
}
 
void gen_l_cust6(struct op_queue *opq, int param_t[3], int delay_slot)
{
}
 
void gen_l_cust7(struct op_queue *opq, int param_t[3], int delay_slot)
{
}
 
void gen_l_cust8(struct op_queue *opq, int param_t[3], int delay_slot)
{
}
 
/* FIXME: All registers need to be stored before the div instructions as they
* have the potenticial to cause an exception */
 
DEF_1T_OP(generic_gen_op, check_null_excpt, gen_op_check_null_except);
DEF_1T_OP(generic_gen_op, check_null_excpt_delay, gen_op_check_null_except_delay);
DEF_3T_OP(generic_gen_op, l_div_t_table, gen_op_div);
 
void gen_l_div(struct op_queue *opq, int param_t[3], int delay_slot)
{
if(!opq->param[2]) {
/* There is no option. This _will_ cause an illeagal exception */
if(!delay_slot) {
gen_op_illegal(opq, 1);
gen_op_do_jump(opq, 1);
} else {
gen_op_illegal(opq, 1);
gen_op_do_jump(opq, 1);
}
return;
}
 
if(!delay_slot)
check_null_excpt[param_t[2]](opq, 1);
else
check_null_excpt_delay[param_t[2]](opq, 1);
 
if(!opq->param[0])
return;
 
if(!opq->param[1]) {
/* Clear param_t[0] */
clear_t[param_t[0]](opq, 1);
return;
}
l_div_t_table[param_t[0]][param_t[1]][param_t[2]](opq, 1);
}
 
DEF_3T_OP(generic_gen_op, l_divu_t_table, gen_op_divu);
 
void gen_l_divu(struct op_queue *opq, int param_t[3], int delay_slot)
{
if(!opq->param[2]) {
/* There is no option. This _will_ cause an illeagal exception */
if(!delay_slot) {
gen_op_illegal(opq, 1);
gen_op_do_jump(opq, 1);
} else {
gen_op_illegal(opq, 1);
gen_op_do_jump(opq, 1);
}
return;
}
 
if(!delay_slot)
check_null_excpt[param_t[2]](opq, 1);
else
check_null_excpt_delay[param_t[2]](opq, 1);
 
if(!opq->param[0])
return;
 
if(!opq->param[1]) {
/* Clear param_t[0] */
clear_t[param_t[0]](opq, 1);
return;
}
l_divu_t_table[param_t[0]][param_t[1]][param_t[2]](opq, 1);
}
 
DEF_2T_OP(generic_gen_op, l_extbs_t_table, gen_op_extbs);
 
void gen_l_extbs(struct op_queue *opq, int param_t[3], int delay_slot)
{
if(!opq->param[0])
return;
 
if(!opq->param[1]) {
clear_t[param_t[0]](opq, 1);
return;
}
 
l_extbs_t_table[param_t[0]][param_t[1]](opq, 1);
}
 
DEF_2T_OP(generic_gen_op, l_extbz_t_table, gen_op_extbz);
 
void gen_l_extbz(struct op_queue *opq, int param_t[3], int delay_slot)
{
if(!opq->param[0])
return;
 
if(!opq->param[1]) {
clear_t[param_t[0]](opq, 1);
return;
}
 
l_extbz_t_table[param_t[0]][param_t[1]](opq, 1);
}
 
DEF_2T_OP(generic_gen_op, l_exths_t_table, gen_op_exths);
 
void gen_l_exths(struct op_queue *opq, int param_t[3], int delay_slot)
{
if(!opq->param[0])
return;
 
if(!opq->param[1]) {
clear_t[param_t[0]](opq, 1);
return;
}
 
l_exths_t_table[param_t[0]][param_t[1]](opq, 1);
}
 
DEF_2T_OP(generic_gen_op, l_exthz_t_table, gen_op_exthz);
 
void gen_l_exthz(struct op_queue *opq, int param_t[3], int delay_slot)
{
if(!opq->param[0])
return;
 
if(!opq->param[1]) {
clear_t[param_t[0]](opq, 1);
return;
}
 
l_exthz_t_table[param_t[0]][param_t[1]](opq, 1);
}
 
void gen_l_extws(struct op_queue *opq, int param_t[3], int delay_slot)
{
if(!opq->param[0])
return;
 
if(!opq->param[1]) {
clear_t[param_t[0]](opq, 1);
return;
}
 
if(opq->param[0] == opq->param[1])
return;
 
/* In the 32-bit architechture this instruction reduces to a move */
move_t_t[param_t[0]][param_t[1]](opq, 1);
}
 
void gen_l_extwz(struct op_queue *opq, int param_t[3], int delay_slot)
{
if(!opq->param[0])
return;
 
if(!opq->param[1]) {
clear_t[param_t[0]](opq, 1);
return;
}
 
if(opq->param[0] == opq->param[1])
return;
 
/* In the 32-bit architechture this instruction reduces to a move */
move_t_t[param_t[0]][param_t[1]](opq, 1);
}
 
DEF_2T_OP(generic_gen_op, l_ff1_t_table, gen_op_ff1);
 
void gen_l_ff1(struct op_queue *opq, int param_t[3], int delay_slot)
{
if(!opq->param[0])
return;
 
if(!opq->param[1]) {
clear_t[param_t[0]](opq, 1);
return;
}
 
l_ff1_t_table[param_t[0]][param_t[1]](opq, 1);
}
 
void gen_l_j(struct op_queue *opq, int param_t[3], int delay_slot)
{
if(do_stats)
/* All gprs are current since this insn doesn't touch any reg */
gen_op_analysis(opq, 1);
 
gen_j_imm(opq, opq->param[0]);
}
 
void gen_l_jal(struct op_queue *opq, int param_t[3], int delay_slot)
{
int i;
 
/* In the case of a l.jal instruction, make sure that LINK_REGNO is not in
* a temporary. The problem is that the l.jal(r) instruction stores the
* `return address' in LINK_REGNO. The temporaries are shiped out only
* after the delay slot instruction has executed and so it overwrittes the
* `return address'. */
for(i = 0; i < NUM_T_REGS; i++) {
if(opq->reg_t[i] == LINK_REGNO) {
/* Don't bother storeing the register, it is going to get clobered in this
* instruction anyway */
opq->reg_t[i] = 32;
break;
}
}
 
/* Store the return address */
gen_op_store_link_addr_gpr(opq, 1);
 
if(do_stats)
/* All gprs are current since this insn doesn't touch any reg */
gen_op_analysis(opq, 1);
 
gen_j_imm(opq, opq->param[0]);
}
 
void gen_l_jr(struct op_queue *opq, int param_t[3], int delay_slot)
{
gen_j_reg(opq, opq->param[0]);
}
 
void gen_l_jalr(struct op_queue *opq, int param_t[3], int delay_slot)
{
int i;
 
/* In the case of a l.jal instruction, make sure that LINK_REGNO is not in
* a temporary. The problem is that the l.jal(r) instruction stores the
* `return address' in LINK_REGNO. The temporaries are shiped out only
* after the delay slot instruction has executed and so it overwrittes the
* `return address'. */
for(i = 0; i < NUM_T_REGS; i++) {
if(opq->reg_t[i] == LINK_REGNO) {
/* Don't bother storeing the register, it is going to get clobered in this
* instruction anyway */
opq->reg_t[i] = 32;
break;
}
}
 
/* Store the return address */
gen_op_store_link_addr_gpr(opq, 1);
 
gen_j_reg(opq, opq->param[0]);
}
 
/* FIXME: Optimise all load instruction when the disposition == 0 */
 
DEF_1T_OP(imm_gen_op, l_lbs_imm_t_table, gen_op_lbs_imm);
DEF_2T_OP(imm_gen_op, l_lbs_t_table, gen_op_lbs);
 
void gen_l_lbs(struct op_queue *opq, int param_t[3], int delay_slot)
{
if(!opq->param[0]) {
/* FIXME: This will work, but the statistics need to be updated... */
return;
}
 
/* Just in case an exception happens */
ship_gprs_out_t(opq->prev);
 
if(!opq->param[2]) {
/* Load the data from the immediate */
l_lbs_imm_t_table[param_t[0]](opq, 1, opq->param[1]);
return;
}
 
l_lbs_t_table[param_t[0]][param_t[2]](opq, 1, opq->param[1]);
}
 
DEF_1T_OP(imm_gen_op, l_lbz_imm_t_table, gen_op_lbz_imm);
DEF_2T_OP(imm_gen_op, l_lbz_t_table, gen_op_lbz);
 
void gen_l_lbz(struct op_queue *opq, int param_t[3], int delay_slot)
{
if(!opq->param[0]) {
/* FIXME: This will work, but the statistics need to be updated... */
return;
}
 
/* Just in case an exception happens */
ship_gprs_out_t(opq->prev);
 
if(!opq->param[2]) {
/* Load the data from the immediate */
l_lbz_imm_t_table[param_t[0]](opq, 1, opq->param[1]);
return;
}
 
l_lbz_t_table[param_t[0]][param_t[2]](opq, 1, opq->param[1]);
}
 
DEF_1T_OP(imm_gen_op, l_lhs_imm_t_table, gen_op_lhs_imm);
DEF_2T_OP(imm_gen_op, l_lhs_t_table, gen_op_lhs);
 
void gen_l_lhs(struct op_queue *opq, int param_t[3], int delay_slot)
{
if(!opq->param[0]) {
/* FIXME: This will work, but the statistics need to be updated... */
return;
}
 
/* Just in case an exception happens */
ship_gprs_out_t(opq->prev);
 
if(!opq->param[2]) {
/* Load the data from the immediate */
l_lhs_imm_t_table[param_t[0]](opq, 1, opq->param[1]);
return;
}
 
l_lhs_t_table[param_t[0]][param_t[2]](opq, 1, opq->param[1]);
}
 
DEF_1T_OP(imm_gen_op, l_lhz_imm_t_table, gen_op_lhz_imm);
DEF_2T_OP(imm_gen_op, l_lhz_t_table, gen_op_lhz);
 
void gen_l_lhz(struct op_queue *opq, int param_t[3], int delay_slot)
{
if(!opq->param[0]) {
/* FIXME: This will work, but the statistics need to be updated... */
return;
}
 
/* Just in case an exception happens */
ship_gprs_out_t(opq->prev);
 
if(!opq->param[2]) {
/* Load the data from the immediate */
l_lhz_imm_t_table[param_t[0]](opq, 1, opq->param[1]);
return;
}
 
l_lhz_t_table[param_t[0]][param_t[2]](opq, 1, opq->param[1]);
}
 
DEF_1T_OP(imm_gen_op, l_lws_imm_t_table, gen_op_lws_imm);
DEF_2T_OP(imm_gen_op, l_lws_t_table, gen_op_lws);
 
void gen_l_lws(struct op_queue *opq, int param_t[3], int delay_slot)
{
if(!opq->param[0]) {
/* FIXME: This will work, but the statistics need to be updated... */
return;
}
 
/* Just in case an exception happens */
ship_gprs_out_t(opq->prev);
 
if(!opq->param[2]) {
/* Load the data from the immediate */
l_lws_imm_t_table[param_t[0]](opq, 1, opq->param[1]);
return;
}
 
l_lws_t_table[param_t[0]][param_t[2]](opq, 1, opq->param[1]);
}
 
DEF_1T_OP(imm_gen_op, l_lwz_imm_t_table, gen_op_lwz_imm);
DEF_2T_OP(imm_gen_op, l_lwz_t_table, gen_op_lwz);
 
void gen_l_lwz(struct op_queue *opq, int param_t[3], int delay_slot)
{
if(!opq->param[0]) {
/* FIXME: This will work, but the statistics need to be updated... */
return;
}
 
/* Just in case an exception happens */
ship_gprs_out_t(opq->prev);
 
if(!opq->param[2]) {
/* Load the data from the immediate */
l_lwz_imm_t_table[param_t[0]](opq, 1, opq->param[1]);
return;
}
 
l_lwz_t_table[param_t[0]][param_t[2]](opq, 1, opq->param[1]);
}
 
DEF_1T_OP(imm_gen_op, l_mac_imm_t_table, gen_op_mac_imm);
DEF_2T_OP(generic_gen_op, l_mac_t_table, gen_op_mac);
 
void gen_l_mac(struct op_queue *opq, int param_t[3], int delay_slot)
{
if(!opq->param[0] || !opq->param[1])
return;
 
if(param_t[1] == T_NONE)
l_mac_imm_t_table[param_t[0]](opq, 1, opq->param[1]);
else
l_mac_t_table[param_t[0]][param_t[1]](opq, 1);
}
 
DEF_1T_OP(generic_gen_op, l_macrc_t_table, gen_op_macrc);
 
void gen_l_macrc(struct op_queue *opq, int param_t[3], int delay_slot)
{
if(!opq->param[0]) {
gen_op_macc(opq, 1);
return;
}
 
l_macrc_t_table[param_t[0]](opq, 1);
}
 
DEF_1T_OP(imm_gen_op, l_mfspr_imm_t_table, gen_op_mfspr_imm);
DEF_2T_OP(imm_gen_op, l_mfspr_t_table, gen_op_mfspr);
 
void gen_l_mfspr(struct op_queue *opq, int param_t[3], int delay_slot)
{
if(!opq->param[0])
return;
 
if(!opq->param[1]) {
l_mfspr_imm_t_table[param_t[0]](opq, 1, opq->param[2]);
return;
}
 
l_mfspr_t_table[param_t[0]][param_t[1]](opq, 1, opq->param[2]);
}
 
void gen_l_movhi(struct op_queue *opq, int param_t[3], int delay_slot)
{
if(!opq->param[0])
return;
 
if(!opq->param[1]) {
clear_t[param_t[0]](opq, 1);
return;
}
 
mov_t_imm[param_t[0]](opq, 1, opq->param[1] << 16);
}
 
DEF_2T_OP(generic_gen_op, l_msb_t_table, gen_op_msb);
 
void gen_l_msb(struct op_queue *opq, int param_t[3], int delay_slot)
{
if(!opq->param[0] || !opq->param[1])
return;
 
l_msb_t_table[param_t[0]][param_t[1]](opq, 1);
}
 
DEF_1T_OP(imm_gen_op, l_mtspr_clear_t_table, gen_op_mtspr_clear);
DEF_1T_OP(imm_gen_op, l_mtspr_imm_t_table, gen_op_mtspr_imm);
DEF_2T_OP(imm_gen_op, l_mtspr_t_table, gen_op_mtspr);
 
void gen_l_mtspr(struct op_queue *opq, int param_t[3], int delay_slot)
{
/* Just in case an exception happens */
ship_gprs_out_t(opq->prev);
 
if(!opq->param[0]) {
if(!opq->param[1]) {
/* Clear the immediate SPR */
gen_op_mtspr_imm_clear(opq, 1, opq->param[2]);
return;
}
l_mtspr_imm_t_table[param_t[1]](opq, 1, opq->param[2]);
return;
}
 
if(!opq->param[1]) {
l_mtspr_clear_t_table[param_t[0]](opq, 1, opq->param[2]);
return;
}
 
l_mtspr_t_table[param_t[0]][param_t[1]](opq, 1, opq->param[2]);
}
 
DEF_2T_OP(imm_gen_op, l_mul_imm_t_table, gen_op_mul_imm);
DEF_3T_OP(generic_gen_op, l_mul_t_table, gen_op_mul);
 
void gen_l_mul(struct op_queue *opq, int param_t[3], int delay_slot)
{
if(!opq->param[0])
return;
 
if(!opq->param[1] || !opq->param[2]) {
clear_t[param_t[0]](opq, 1);
return;
}
 
if(param_t[2] == T_NONE)
l_mul_imm_t_table[param_t[0]][param_t[1]](opq, 1, opq->param[2]);
else
l_mul_t_table[param_t[0]][param_t[1]][param_t[2]](opq, 1);
}
 
DEF_3T_OP(generic_gen_op, l_mulu_t_table, gen_op_mulu);
 
void gen_l_mulu(struct op_queue *opq, int param_t[3], int delay_slot)
{
if(!opq->param[0])
return;
 
if(!opq->param[1] || !opq->param[2]) {
clear_t[param_t[0]](opq, 1);
return;
}
 
l_mulu_t_table[param_t[0]][param_t[1]][param_t[2]](opq, 1);
}
 
void gen_l_nop(struct op_queue *opq, int param_t[3], int delay_slot)
{
/* Do parameter switch now */
switch(opq->param[0]) {
case NOP_NOP:
break;
case NOP_EXIT:
ship_gprs_out_t(opq->prev);
gen_op_nop_exit(opq, 1);
break;
case NOP_CNT_RESET:
gen_op_nop_reset(opq, 1);
break;
case NOP_PRINTF:
ship_gprs_out_t(opq->prev);
gen_op_nop_printf(opq, 1);
break;
case NOP_REPORT:
ship_gprs_out_t(opq->prev);
gen_op_nop_report(opq, 1);
break;
default:
if((opq->param[0] >= NOP_REPORT_FIRST) && (opq->param[0] <= NOP_REPORT_LAST)) {
ship_gprs_out_t(opq->prev);
gen_op_nop_report_imm(opq, 1, opq->param[0] - NOP_REPORT_FIRST);
}
break;
}
}
 
DEF_2T_OP(imm_gen_op, l_or_imm_t_table, gen_op_or_imm);
DEF_3T_OP_NEQ(generic_gen_op, l_or_t_table, gen_op_or);
 
void gen_l_or(struct op_queue *opq, int param_t[3], int delay_slot)
{
if(!opq->param[0])
return;
 
if((opq->param[0] == opq->param[1] == opq->param[2]) && (param_t[2] != T_NONE))
return;
 
if(!opq->param[1] && !opq->param[2]) {
clear_t[param_t[0]](opq, 1);
return;
}
 
if(!opq->param[2]) {
if((param_t[2] == T_NONE) && (opq->param[0] == opq->param[1]))
return;
move_t_t[param_t[0]][param_t[1]](opq, 1);
return;
}
 
if(!opq->param[1]) {
/* Check if we are moveing an immediate */
if(param_t[2] == T_NONE) {
/* Yep, an immediate */
mov_t_imm[param_t[0]](opq, 1, opq->param[2]);
return;
}
/* Just another move */
move_t_t[param_t[0]][param_t[2]](opq, 1);
return;
}
 
if(param_t[2] == T_NONE)
l_or_imm_t_table[param_t[0]][param_t[1]](opq, 1, opq->param[2]);
else
l_or_t_table[param_t[0]][param_t[1]][param_t[2]](opq, 1);
}
 
void gen_l_rfe(struct op_queue *opq, int param_t[3], int delay_slot)
{
if(do_stats)
/* All gprs are current since this insn doesn't touch any reg */
gen_op_analysis(opq, 1);
 
gen_op_prep_rfe(opq, 1);
/* FIXME: rename op_do_sched_delay */
gen_op_do_sched_delay(opq, 1);
gen_op_do_jump(opq, 1);
}
 
/* FIXME: All store instructions should be optimised when the disposition = 0 */
 
DEF_1T_OP(imm_gen_op, l_sb_clear_table, gen_op_sb_clear);
DEF_1T_OP(imm_gen_op, l_sb_imm_t_table, gen_op_sb_imm);
DEF_2T_OP(imm_gen_op, l_sb_t_table, gen_op_sb);
 
void gen_l_sb(struct op_queue *opq, int param_t[3], int delay_slot)
{
/* Just in case an exception happens */
ship_gprs_out_t(opq->prev);
 
if(!opq->param[2]) {
if(!opq->param[1]) {
gen_op_sb_clear_imm(opq, 1, opq->param[0]);
return;
}
l_sb_clear_table[param_t[1]](opq, 1, opq->param[0]);
return;
}
 
if(!opq->param[1]) {
/* Store the data to the immediate */
l_sb_imm_t_table[param_t[2]](opq, 1, opq->param[0]);
return;
}
 
l_sb_t_table[param_t[1]][param_t[2]](opq, 1, opq->param[0]);
}
 
DEF_1T_OP(imm_gen_op, l_sh_clear_table, gen_op_sh_clear);
DEF_1T_OP(imm_gen_op, l_sh_imm_t_table, gen_op_sh_imm);
DEF_2T_OP(imm_gen_op, l_sh_t_table, gen_op_sh);
 
void gen_l_sh(struct op_queue *opq, int param_t[3], int delay_slot)
{
/* Just in case an exception happens */
ship_gprs_out_t(opq->prev);
 
if(!opq->param[2]) {
if(!opq->param[1]) {
gen_op_sh_clear_imm(opq, 1, opq->param[0]);
return;
}
l_sh_clear_table[param_t[1]](opq, 1, opq->param[0]);
return;
}
 
if(!opq->param[1]) {
/* Store the data to the immediate */
l_sh_imm_t_table[param_t[2]](opq, 1, opq->param[0]);
return;
}
 
l_sh_t_table[param_t[1]][param_t[2]](opq, 1, opq->param[0]);
}
 
DEF_1T_OP(imm_gen_op, l_sw_clear_table, gen_op_sw_clear);
DEF_1T_OP(imm_gen_op, l_sw_imm_t_table, gen_op_sw_imm);
DEF_2T_OP(imm_gen_op, l_sw_t_table, gen_op_sw);
 
void gen_l_sw(struct op_queue *opq, int param_t[3], int delay_slot)
{
/* Just in case an exception happens */
ship_gprs_out_t(opq->prev);
 
if(!opq->param[2]) {
if(!opq->param[1]) {
gen_op_sw_clear_imm(opq, 1, opq->param[0]);
return;
}
l_sw_clear_table[param_t[1]](opq, 1, opq->param[0]);
return;
}
 
if(!opq->param[1]) {
/* Store the data to the immediate */
l_sw_imm_t_table[param_t[2]](opq, 1, opq->param[0]);
return;
}
 
l_sw_t_table[param_t[1]][param_t[2]](opq, 1, opq->param[0]);
}
 
DEF_1T_OP(generic_gen_op, l_sfeq_null_t_table, gen_op_sfeq_null);
DEF_1T_OP(imm_gen_op, l_sfeq_imm_t_table, gen_op_sfeq_imm);
DEF_2T_OP(generic_gen_op, l_sfeq_t_table, gen_op_sfeq);
 
void gen_l_sfeq(struct op_queue *opq, int param_t[3], int delay_slot)
{
if(!opq->param[0] && !opq->param[1]) {
gen_op_set_flag(opq, 1);
return;
}
 
if(!opq->param[0]) {
if(param_t[1] == T_NONE) {
if(!opq->param[1])
gen_op_set_flag(opq, 1);
else
gen_op_clear_flag(opq, 1);
} else
l_sfeq_null_t_table[param_t[1]](opq, 1);
return;
}
 
if(!opq->param[1]) {
l_sfeq_null_t_table[param_t[0]](opq, 1);
return;
}
 
if(param_t[1] == T_NONE)
l_sfeq_imm_t_table[param_t[0]](opq, 1, opq->param[1]);
else
l_sfeq_t_table[param_t[0]][param_t[1]](opq, 1);
}
 
DEF_1T_OP(generic_gen_op, l_sfges_null_t_table, gen_op_sfges_null);
DEF_1T_OP(generic_gen_op, l_sfles_null_t_table, gen_op_sfles_null);
DEF_1T_OP(imm_gen_op, l_sfges_imm_t_table, gen_op_sfges_imm);
DEF_2T_OP(generic_gen_op, l_sfges_t_table, gen_op_sfges);
 
void gen_l_sfges(struct op_queue *opq, int param_t[3], int delay_slot)
{
if(!opq->param[0] && !opq->param[1]) {
gen_op_set_flag(opq, 1);
return;
}
 
if(!opq->param[0]) {
/* sfles IS correct */
if(param_t[1] == T_NONE) {
if(0 >= (orreg_t)opq->param[1])
gen_op_set_flag(opq, 1);
else
gen_op_clear_flag(opq, 1);
} else
l_sfles_null_t_table[param_t[1]](opq, 1);
return;
}
 
if(!opq->param[1]) {
l_sfges_null_t_table[param_t[0]](opq, 1);
return;
}
 
if(param_t[1] == T_NONE)
l_sfges_imm_t_table[param_t[0]](opq, 1, opq->param[1]);
else
l_sfges_t_table[param_t[0]][param_t[1]](opq, 1);
}
 
DEF_1T_OP(generic_gen_op, l_sfgeu_null_t_table, gen_op_sfgeu_null);
DEF_1T_OP(generic_gen_op, l_sfleu_null_t_table, gen_op_sfleu_null);
DEF_1T_OP(imm_gen_op, l_sfgeu_imm_t_table, gen_op_sfgeu_imm);
DEF_2T_OP(generic_gen_op, l_sfgeu_t_table, gen_op_sfgeu);
 
void gen_l_sfgeu(struct op_queue *opq, int param_t[3], int delay_slot)
{
if(!opq->param[0] && !opq->param[1]) {
gen_op_set_flag(opq, 1);
return;
}
 
if(!opq->param[0]) {
/* sfleu IS correct */
if(param_t[1] == T_NONE) {
if(0 >= opq->param[1])
gen_op_set_flag(opq, 1);
else
gen_op_clear_flag(opq, 1);
} else
l_sfleu_null_t_table[param_t[1]](opq, 1);
return;
}
 
if(!opq->param[1]) {
l_sfgeu_null_t_table[param_t[0]](opq, 1);
return;
}
if(param_t[1] == T_NONE)
l_sfgeu_imm_t_table[param_t[0]](opq, 1, opq->param[1]);
else
l_sfgeu_t_table[param_t[0]][param_t[1]](opq, 1);
}
 
DEF_1T_OP(generic_gen_op, l_sfgts_null_t_table, gen_op_sfgts_null);
DEF_1T_OP(generic_gen_op, l_sflts_null_t_table, gen_op_sflts_null);
DEF_1T_OP(imm_gen_op, l_sfgts_imm_t_table, gen_op_sfgts_imm);
DEF_2T_OP(generic_gen_op, l_sfgts_t_table, gen_op_sfgts);
 
void gen_l_sfgts(struct op_queue *opq, int param_t[3], int delay_slot)
{
if(!opq->param[0] && !opq->param[1]) {
gen_op_clear_flag(opq, 1);
return;
}
 
if(!opq->param[0]) {
/* sflts IS correct */
if(param_t[1] == T_NONE) {
if(0 > (orreg_t)opq->param[1])
gen_op_set_flag(opq, 1);
else
gen_op_clear_flag(opq, 1);
} else
l_sflts_null_t_table[param_t[1]](opq, 1);
return;
}
 
if(!opq->param[1]) {
l_sfgts_null_t_table[param_t[0]](opq, 1);
return;
}
 
if(param_t[1] == T_NONE)
l_sfgts_imm_t_table[param_t[0]](opq, 1, opq->param[1]);
else
l_sfgts_t_table[param_t[0]][param_t[1]](opq, 1);
}
 
DEF_1T_OP(generic_gen_op, l_sfgtu_null_t_table, gen_op_sfgtu_null);
DEF_1T_OP(generic_gen_op, l_sfltu_null_t_table, gen_op_sfltu_null);
DEF_1T_OP(imm_gen_op, l_sfgtu_imm_t_table, gen_op_sfgtu_imm);
DEF_2T_OP(generic_gen_op, l_sfgtu_t_table, gen_op_sfgtu);
 
void gen_l_sfgtu(struct op_queue *opq, int param_t[3], int delay_slot)
{
if(!opq->param[0] && !opq->param[1]) {
gen_op_clear_flag(opq, 1);
return;
}
 
if(!opq->param[0]) {
/* sfltu IS correct */
if(param_t[1] == T_NONE) {
if(0 > opq->param[1])
gen_op_set_flag(opq, 1);
else
gen_op_clear_flag(opq, 1);
} else
l_sfltu_null_t_table[param_t[1]](opq, 1);
return;
}
 
if(!opq->param[1]) {
l_sfgtu_null_t_table[param_t[0]](opq, 1);
return;
}
 
if(param_t[1] == T_NONE)
l_sfgtu_imm_t_table[param_t[0]](opq, 1, opq->param[1]);
else
l_sfgtu_t_table[param_t[0]][param_t[1]](opq, 1);
}
 
DEF_1T_OP(imm_gen_op, l_sfles_imm_t_table, gen_op_sfles_imm);
DEF_2T_OP(generic_gen_op, l_sfles_t_table, gen_op_sfles);
 
void gen_l_sfles(struct op_queue *opq, int param_t[3], int delay_slot)
{
if(!opq->param[0] && !opq->param[1]) {
gen_op_set_flag(opq, 1);
return;
}
 
if(!opq->param[0]) {
/* sfges IS correct */
if(param_t[1] == T_NONE) {
if(0 <= (orreg_t)opq->param[1])
gen_op_set_flag(opq, 1);
else
gen_op_clear_flag(opq, 1);
} else
l_sfges_null_t_table[param_t[1]](opq, 1);
return;
}
 
if(!opq->param[1]) {
l_sfles_null_t_table[param_t[0]](opq, 1);
return;
}
 
if(param_t[1] == T_NONE)
l_sfles_imm_t_table[param_t[0]](opq, 1, opq->param[1]);
else
l_sfles_t_table[param_t[0]][param_t[1]](opq, 1);
}
 
DEF_1T_OP(imm_gen_op, l_sfleu_imm_t_table, gen_op_sfleu_imm);
DEF_2T_OP(generic_gen_op, l_sfleu_t_table, gen_op_sfleu);
 
void gen_l_sfleu(struct op_queue *opq, int param_t[3], int delay_slot)
{
if(!opq->param[0] && !opq->param[1]) {
gen_op_set_flag(opq, 1);
return;
}
 
if(!opq->param[0]) {
/* sfleu IS correct */
if(param_t[1] == T_NONE) {
if(0 <= opq->param[1])
gen_op_set_flag(opq, 1);
else
gen_op_clear_flag(opq, 1);
} else
l_sfgeu_null_t_table[param_t[1]](opq, 1);
return;
}
 
if(!opq->param[1]) {
l_sfleu_null_t_table[param_t[0]](opq, 1);
return;
}
 
if(param_t[1] == T_NONE)
l_sfleu_imm_t_table[param_t[0]](opq, 1, opq->param[1]);
else
l_sfleu_t_table[param_t[0]][param_t[1]](opq, 1);
}
 
DEF_1T_OP(imm_gen_op, l_sflts_imm_t_table, gen_op_sflts_imm);
DEF_2T_OP(generic_gen_op, l_sflts_t_table, gen_op_sflts);
 
void gen_l_sflts(struct op_queue *opq, int param_t[3], int delay_slot)
{
if(!opq->param[0] && !opq->param[1]) {
gen_op_clear_flag(opq, 1);
return;
}
 
if(!opq->param[0]) {
/* sfgts IS correct */
if(param_t[1] == T_NONE) {
if(0 < (orreg_t)opq->param[1])
gen_op_set_flag(opq, 1);
else
gen_op_clear_flag(opq, 1);
} else
l_sfgts_null_t_table[param_t[1]](opq, 1);
return;
}
 
if(!opq->param[1]) {
l_sflts_null_t_table[param_t[0]](opq, 1);
return;
}
 
if(param_t[1] == T_NONE)
l_sflts_imm_t_table[param_t[0]](opq, 1, opq->param[1]);
else
l_sflts_t_table[param_t[0]][param_t[1]](opq, 1);
}
 
DEF_1T_OP(imm_gen_op, l_sfltu_imm_t_table, gen_op_sfltu_imm);
DEF_2T_OP(generic_gen_op, l_sfltu_t_table, gen_op_sfltu);
 
void gen_l_sfltu(struct op_queue *opq, int param_t[3], int delay_slot)
{
if(!opq->param[0] && !opq->param[1]) {
gen_op_clear_flag(opq, 1);
return;
}
 
if(!opq->param[0]) {
/* sfgtu IS correct */
if(param_t[1] == T_NONE) {
if(0 < opq->param[1])
gen_op_set_flag(opq, 1);
else
gen_op_clear_flag(opq, 1);
} else
l_sfgtu_null_t_table[param_t[1]](opq, 1);
return;
}
 
if(!opq->param[1]) {
l_sfltu_null_t_table[param_t[0]](opq, 1);
return;
}
 
if(param_t[1] == T_NONE)
l_sfltu_imm_t_table[param_t[0]](opq, 1, opq->param[1]);
else
l_sfltu_t_table[param_t[0]][param_t[1]](opq, 1);
}
 
DEF_1T_OP(generic_gen_op, l_sfne_null_t_table, gen_op_sfne_null);
DEF_1T_OP(imm_gen_op, l_sfne_imm_t_table, gen_op_sfne_imm);
DEF_2T_OP(generic_gen_op, l_sfne_t_table, gen_op_sfne);
 
void gen_l_sfne(struct op_queue *opq, int param_t[3], int delay_slot)
{
if(!opq->param[0] && !opq->param[1]) {
gen_op_set_flag(opq, 1);
return;
}
 
if(!opq->param[0]) {
if(param_t[1] == T_NONE)
if(opq->param[1])
gen_op_set_flag(opq, 1);
else
gen_op_clear_flag(opq, 1);
else
l_sfne_null_t_table[param_t[1]](opq, 1);
return;
}
 
if(!opq->param[1]) {
l_sfne_null_t_table[param_t[0]](opq, 1);
return;
}
 
if(param_t[1] == T_NONE)
l_sfne_imm_t_table[param_t[0]](opq, 1, opq->param[1]);
else
l_sfne_t_table[param_t[0]][param_t[1]](opq, 1);
}
 
DEF_2T_OP(imm_gen_op, l_sll_imm_t_table, gen_op_sll_imm);
DEF_3T_OP(generic_gen_op, l_sll_t_table, gen_op_sll);
 
void gen_l_sll(struct op_queue *opq, int param_t[3], int delay_slot)
{
if(!opq->param[0])
return;
 
if(!opq->param[1]) {
clear_t[param_t[0]](opq, 1);
return;
}
 
if(!opq->param[2]) {
move_t_t[param_t[0]][param_t[1]](opq, 1);
return;
}
 
if(param_t[2] == T_NONE)
l_sll_imm_t_table[param_t[0]][param_t[1]](opq, 1, opq->param[2]);
else
l_sll_t_table[param_t[0]][param_t[1]][param_t[2]](opq, 1);
}
 
DEF_2T_OP(imm_gen_op, l_sra_imm_t_table, gen_op_sra_imm);
DEF_3T_OP(generic_gen_op, l_sra_t_table, gen_op_sra);
 
void gen_l_sra(struct op_queue *opq, int param_t[3], int delay_slot)
{
if(!opq->param[0])
return;
 
if(!opq->param[1]) {
clear_t[param_t[0]](opq, 1);
return;
}
 
if(!opq->param[2]) {
move_t_t[param_t[0]][param_t[1]](opq, 1);
return;
}
 
if(param_t[2] == T_NONE)
l_sra_imm_t_table[param_t[0]][param_t[1]](opq, 1, opq->param[2]);
else
l_sra_t_table[param_t[0]][param_t[1]][param_t[2]](opq, 1);
}
 
DEF_2T_OP(imm_gen_op, l_srl_imm_t_table, gen_op_srl_imm);
DEF_3T_OP(generic_gen_op, l_srl_t_table, gen_op_srl);
 
void gen_l_srl(struct op_queue *opq, int param_t[3], int delay_slot)
{
if(!opq->param[0])
return;
 
if(!opq->param[1]) {
clear_t[param_t[0]](opq, 1);
return;
}
 
if(!opq->param[2]) {
move_t_t[param_t[0]][param_t[1]](opq, 1);
return;
}
 
if(param_t[2] == T_NONE)
l_srl_imm_t_table[param_t[0]][param_t[1]](opq, 1, opq->param[2]);
else
l_srl_t_table[param_t[0]][param_t[1]][param_t[2]](opq, 1);
}
 
DEF_2T_OP(generic_gen_op, l_neg_t_table, gen_op_neg);
DEF_3T_OP(generic_gen_op, l_sub_t_table, gen_op_sub);
 
void gen_l_sub(struct op_queue *opq, int param_t[3], int delay_slot)
{
if(!opq->param[0])
return;
 
if((param_t[2] != T_NONE) && (opq->param[1] == opq->param[2])) {
clear_t[param_t[0]](opq, 1);
return;
}
 
if(!opq->param[1] && !opq->param[2]) {
clear_t[param_t[0]](opq, 1);
return;
}
 
if(!opq->param[1]) {
if(param_t[2] == T_NONE)
mov_t_imm[param_t[0]](opq, 1, -opq->param[2]);
else
l_neg_t_table[param_t[0]][param_t[2]](opq, 1);
return;
}
 
if(!opq->param[2]) {
move_t_t[param_t[0]][param_t[1]](opq, 1);
return;
}
 
l_sub_t_table[param_t[0]][param_t[1]][param_t[2]](opq, 1);
}
 
/* FIXME: This will not work if the l.sys is in a delay slot */
void gen_l_sys(struct op_queue *opq, int param_t[3], int delay_slot)
{
if(do_stats)
/* All gprs are current since this insn doesn't touch any reg */
gen_op_analysis(opq, 1);
 
if(!delay_slot)
gen_op_prep_sys(opq, 1);
else
gen_op_prep_sys_delay(opq, 1);
 
gen_op_do_sched(opq, 1);
gen_op_do_jump(opq, 1);
}
 
/* FIXME: This will not work if the l.trap is in a delay slot */
void gen_l_trap(struct op_queue *opq, int param_t[3], int delay_slot)
{
if(do_stats)
/* All gprs are current since this insn doesn't touch any reg */
gen_op_analysis(opq, 1);
 
if(!delay_slot)
gen_op_prep_trap(opq, 1);
else
gen_op_prep_trap_delay(opq, 1);
}
 
DEF_2T_OP(imm_gen_op, l_xor_imm_t_table, gen_op_xor_imm);
/* FIXME: Make unused elements NULL */
DEF_3T_OP_NEQ(generic_gen_op, l_xor_t_table, gen_op_xor);
 
void gen_l_xor(struct op_queue *opq, int param_t[3], int delay_slot)
{
if(!opq->param[0])
return;
 
if((param_t[2] != T_NONE) && (opq->param[1] == opq->param[2])) {
clear_t[param_t[0]](opq, 1);
return;
}
if(!opq->param[2]) {
if((param_t[2] == T_NONE) && (opq->param[0] == opq->param[1]))
return;
move_t_t[param_t[0]][param_t[1]](opq, 1);
return;
}
 
if(!opq->param[1]) {
if(param_t[2] == T_NONE) {
mov_t_imm[param_t[0]](opq, 1, opq->param[2]);
return;
}
move_t_t[param_t[0]][param_t[2]](opq, 1);
return;
}
 
if(param_t[2] == T_NONE)
l_xor_imm_t_table[param_t[0]][param_t[1]](opq, 1, opq->param[2]);
else
l_xor_t_table[param_t[0]][param_t[1]][param_t[2]](opq, 1);
}
 
void gen_l_invalid(struct op_queue *opq, int param_t[3], int delay_slot)
{
if(!delay_slot) {
gen_op_illegal(opq, 1);
gen_op_do_jump(opq, 1);
} else {
gen_op_illegal_delay(opq, 1);
gen_op_do_jump(opq, 1);
}
}
 
/*----------------------------------[ Floating point instructions (stubs) ]---*/
void gen_lf_add_s(struct op_queue *opq, int param_t[3], int delay_slot)
{
gen_l_invalid(opq, param_t, delay_slot);
}
 
void gen_lf_div_s(struct op_queue *opq, int param_t[3], int delay_slot)
{
gen_l_invalid(opq, param_t, delay_slot);
}
 
void gen_lf_ftoi_s(struct op_queue *opq, int param_t[3], int delay_slot)
{
gen_l_invalid(opq, param_t, delay_slot);
}
 
void gen_lf_itof_s(struct op_queue *opq, int param_t[3], int delay_slot)
{
gen_l_invalid(opq, param_t, delay_slot);
}
 
void gen_lf_madd_s(struct op_queue *opq, int param_t[3], int delay_slot)
{
gen_l_invalid(opq, param_t, delay_slot);
}
 
void gen_lf_mul_s(struct op_queue *opq, int param_t[3], int delay_slot)
{
gen_l_invalid(opq, param_t, delay_slot);
}
 
void gen_lf_rem_s(struct op_queue *opq, int param_t[3], int delay_slot)
{
gen_l_invalid(opq, param_t, delay_slot);
}
 
void gen_lf_sfeq_s(struct op_queue *opq, int param_t[3], int delay_slot)
{
gen_l_invalid(opq, param_t, delay_slot);
}
 
void gen_lf_sfge_s(struct op_queue *opq, int param_t[3], int delay_slot)
{
gen_l_invalid(opq, param_t, delay_slot);
}
 
void gen_lf_sfgt_s(struct op_queue *opq, int param_t[3], int delay_slot)
{
gen_l_invalid(opq, param_t, delay_slot);
}
 
void gen_lf_sfle_s(struct op_queue *opq, int param_t[3], int delay_slot)
{
gen_l_invalid(opq, param_t, delay_slot);
}
 
void gen_lf_sflt_s(struct op_queue *opq, int param_t[3], int delay_slot)
{
gen_l_invalid(opq, param_t, delay_slot);
}
 
void gen_lf_sfne_s(struct op_queue *opq, int param_t[3], int delay_slot)
{
gen_l_invalid(opq, param_t, delay_slot);
}
 
void gen_lf_sub_s(struct op_queue *opq, int param_t[3], int delay_slot)
{
gen_l_invalid(opq, param_t, delay_slot);
}
 
/execute.c
0,0 → 1,1169
/* execute.c -- OR1K architecture dependent simulation
 
Copyright (C) 1999 Damjan Lampret, lampret@opencores.org
 
Copyright (C) 2008 Embecosm Limited
Contributor Jeremy Bennett <jeremy.bennett@embecosm.com>
This file is part of OpenRISC 1000 Architectural Simulator.
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 3 of the License, or (at your option)
any later version.
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
more details.
You should have received a copy of the GNU General Public License along
with this program. If not, see <http://www.gnu.org/licenses/>. */
 
/* This program is commented throughout in a fashion suitable for processing
with Doxygen. */
 
 
/* Most of the OR1K simulation is done in here.
 
When SIMPLE_EXECUTION is defined below a file insnset.c is included!
*/
 
/* Autoconf and/or portability configuration */
#include "config.h"
#include "port.h"
 
/* System includes */
#include <stdlib.h>
 
/* Package includes */
#include "execute.h"
#include "toplevel-support.h"
#include "except.h"
#include "labels.h"
#include "gdbcomm.h"
#include "sched.h"
#include "stats.h"
#include "opcode/or32.h"
#include "dmmu.h"
#include "immu.h"
#include "sim-cmd.h"
#include "vapi.h"
#include "debug-unit.h"
#include "branch-predict.h"
#include "support/simprintf.h"
#include "sprs.h"
 
 
/* Sets a new SPR_SR_OV value, based on next register value */
#if SET_OV_FLAG
#define SET_OV_FLAG_FN(value) \
if((value) & 0x80000000) \
cpu_state.sprs[SPR_SR] |= SPR_SR_OV; \
else \
cpu_state.sprs[SPR_SR] &= ~SPR_SR_OV
#else
#define SET_OV_FLAG_FN(value)
#endif
 
/* Macros for simple execution */
#if SIMPLE_EXECUTION
#define SET_PARAM0(val) set_operand(0, val, current->insn_index, current->insn)
 
#define PARAM0 eval_operand(0, current->insn_index, current->insn)
#define PARAM1 eval_operand(1, current->insn_index, current->insn)
#define PARAM2 eval_operand(2, current->insn_index, current->insn)
#endif
 
/*! Current cpu state. Globally available. */
struct cpu_state cpu_state;
 
/*! Temporary program counter. Globally available */
oraddr_t pcnext;
 
/*! Num cycles waiting for stores to complete. Globally available */
int sbuf_wait_cyc = 0;
 
/*! Number of total store cycles. Globally available */
int sbuf_total_cyc = 0;
 
/*! Whether we are doing statistical analysis. Globally available */
int do_stats = 0;
 
/*! History of execution. Globally available */
struct hist_exec *hist_exec_tail = NULL;
 
/* Benchmark multi issue execution. This file only */
static int multissue[20];
static int issued_per_cycle = 4;
 
/* Store buffer analysis - stores are accumulated and commited when IO is
idle. This file only */
static int sbuf_head = 0;
static int sbuf_tail = 0;
static int sbuf_count = 0;
static int sbuf_buf[MAX_SBUF_LEN] = { 0 };
 
static int sbuf_prev_cycles = 0;
 
/* Local data needed for execution. */
static int next_delay_insn;
static int breakpoint;
 
/* Forward declaration of static functions */
static void decode_execute (struct iqueue_entry *current);
 
/*---------------------------------------------------------------------------*/
/*!Get an actual value of a specific register
 
Implementation specific. Abort if we are given a duff register. Only used
externally to support simprintf().
 
@param[in] regno The register of interest
 
@return The value of the register */
/*---------------------------------------------------------------------------*/
uorreg_t
evalsim_reg (unsigned int regno)
{
if (regno < MAX_GPRS)
{
#if RAW_RANGE_STATS
int delta = (runtime.sim.cycles - raw_stats.reg[regno]);
 
if ((unsigned long) delta < (unsigned long) MAX_RAW_RANGE)
{
raw_stats.range[delta]++;
}
#endif /* RAW_RANGE */
 
return cpu_state.reg[regno];
}
else
{
PRINTF ("\nABORT: read out of registers\n");
sim_done ();
return 0;
}
} /* evalsim_reg() */
 
 
/*---------------------------------------------------------------------------*/
/*!Set a specific register with value
 
Implementation specific. Abort if we are given a duff register.
 
@param[in] regno The register of interest
@param[in] value The value to be set */
/*---------------------------------------------------------------------------*/
void
setsim_reg (unsigned int regno,
uorreg_t value)
{
if (regno == 0) /* gpr0 is always zero */
{
value = 0;
}
 
if (regno < MAX_GPRS)
{
cpu_state.reg[regno] = value;
}
else
{
PRINTF ("\nABORT: write out of registers\n");
sim_done ();
}
 
#if RAW_RANGE_STATS
raw_stats.reg[regno] = runtime.sim.cycles;
#endif /* RAW_RANGE */
 
} /* setsim_reg() */
 
 
/*---------------------------------------------------------------------------*/
/*!Evaluates source operand operand
 
Implementation specific. Declared global, although this is only actually
required for DYNAMIC_EXECUTION,
 
@param[in] insn The instruction
@param[in] opd The operand
 
@return The value of the source operand */
/*---------------------------------------------------------------------------*/
uorreg_t
eval_operand_val (uint32_t insn,
struct insn_op_struct *opd)
{
unsigned long operand = 0;
unsigned long sbit;
unsigned int nbits = 0;
 
while (1)
{
operand |=
((insn >> (opd->type & OPTYPE_SHR)) & ((1 << opd->data) - 1)) <<
nbits;
nbits += opd->data;
 
if (opd->type & OPTYPE_OP)
{
break;
}
 
opd++;
}
 
if (opd->type & OPTYPE_SIG)
{
sbit = (opd->type & OPTYPE_SBIT) >> OPTYPE_SBIT_SHR;
 
if (operand & (1 << sbit))
{
operand |= ~REG_C (0) << sbit;
}
}
 
return operand;
 
} /* eval_operand_val() */
 
 
/*---------------------------------------------------------------------------*/
/*!Does source operand depend on computation of dest operand?
 
Cycle t Cycle t+1
dst: irrelevant src: immediate always 0
dst: reg1 direct src: reg2 direct 0 if reg1 != reg2
dst: reg1 disp src: reg2 direct always 0
dst: reg1 direct src: reg2 disp 0 if reg1 != reg2
dst: reg1 disp src: reg2 disp always 1 (store must
finish before load)
dst: flag src: flag always 1
 
@param[in] prev Previous instruction
@param[in] next Next instruction
 
@return Non-zero if yes. */
/*---------------------------------------------------------------------------*/
static int
check_depend (struct iqueue_entry *prev,
struct iqueue_entry *next)
{
/* Find destination type. */
unsigned long type = 0;
int prev_dis;
int next_dis;
orreg_t prev_reg_val = 0;
struct insn_op_struct *opd;
 
if (or32_opcodes[prev->insn_index].flags & OR32_W_FLAG
&& or32_opcodes[next->insn_index].flags & OR32_R_FLAG)
{
return 1;
}
 
opd = op_start[prev->insn_index];
prev_dis = 0;
 
while (1)
{
if (opd->type & OPTYPE_DIS)
{
prev_dis = 1;
}
 
if (opd->type & OPTYPE_DST)
{
type = opd->type;
 
if (prev_dis)
{
type |= OPTYPE_DIS;
}
 
/* Destination is always a register */
prev_reg_val = eval_operand_val (prev->insn, opd);
break;
}
 
if (opd->type & OPTYPE_LAST)
{
return 0; /* Doesn't have a destination operand */
}
 
if (opd->type & OPTYPE_OP)
{
prev_dis = 0;
}
 
opd++;
}
 
/* We search all source operands - if we find confict => return 1 */
opd = op_start[next->insn_index];
next_dis = 0;
 
while (1)
{
if (opd->type & OPTYPE_DIS)
{
next_dis = 1;
}
 
/* This instruction sequence also depends on order of execution:
l.lw r1, k(r1)
l.sw k(r1), r4
Here r1 is a destination in l.sw */
/* FIXME: This situation is not handeld here when r1 == r2:
l.sw k(r1), r4
l.lw r3, k(r2) */
if (!(opd->type & OPTYPE_DST) || (next_dis && (opd->type & OPTYPE_DST)))
{
if (opd->type & OPTYPE_REG)
{
if (eval_operand_val (next->insn, opd) == prev_reg_val)
{
return 1;
}
}
}
 
if (opd->type & OPTYPE_LAST)
{
break;
}
 
opd++;
}
 
return 0;
 
} /* check_depend() */
 
 
/*---------------------------------------------------------------------------*/
/*!Should instruction NOT be executed?
 
Modified by CZ 26/05/01 for new mode execution.
 
@return Nonzero if instruction should NOT be executed */
/*---------------------------------------------------------------------------*/
static int
fetch ()
{
static int break_just_hit = 0;
 
if (NULL != breakpoints)
{
/* MM: Check for breakpoint. This has to be done in fetch cycle,
because of peripheria.
MM1709: if we cannot access the memory entry, we could not set the
breakpoint earlier, so just check the breakpoint list. */
if (has_breakpoint (peek_into_itlb (cpu_state.pc)) && !break_just_hit)
{
break_just_hit = 1;
return 1; /* Breakpoint set. */
}
break_just_hit = 0;
}
 
breakpoint = 0;
cpu_state.iqueue.insn_addr = cpu_state.pc;
cpu_state.iqueue.insn = eval_insn (cpu_state.pc, &breakpoint);
 
/* Fetch instruction. */
if (!except_pending)
{
runtime.cpu.instructions++;
}
 
/* update_pc will be called after execution */
return 0;
 
} /* fetch() */
 
 
/*---------------------------------------------------------------------------*/
/*!This code actually updates the PC value */
/*---------------------------------------------------------------------------*/
static void
update_pc ()
{
cpu_state.delay_insn = next_delay_insn;
cpu_state.sprs[SPR_PPC] = cpu_state.pc; /* Store value for later */
cpu_state.pc = pcnext;
pcnext = cpu_state.delay_insn ? cpu_state.pc_delay :
pcnext + 4;
} /* update_pc() */
 
 
/*---------------------------------------------------------------------------*/
/*!Perform analysis of the instruction being executed
 
This could be static for SIMPLE_EXECUTION, but made global for general use.
 
@param[in] current The instruction being executed */
/*---------------------------------------------------------------------------*/
void
analysis (struct iqueue_entry *current)
{
if (config.cpu.dependstats)
{
/* Dynamic, dependency stats. */
adddstats (cpu_state.icomplet.insn_index, current->insn_index, 1,
check_depend (&cpu_state.icomplet, current));
 
/* Dynamic, functional units stats. */
addfstats (or32_opcodes[cpu_state.icomplet.insn_index].func_unit,
or32_opcodes[current->insn_index].func_unit, 1,
check_depend (&cpu_state.icomplet, current));
 
/* Dynamic, single stats. */
addsstats (current->insn_index, 1);
}
 
if (config.cpu.superscalar)
{
if ((or32_opcodes[current->insn_index].func_unit == it_branch) ||
(or32_opcodes[current->insn_index].func_unit == it_jump))
runtime.sim.storecycles += 0;
 
if (or32_opcodes[current->insn_index].func_unit == it_store)
runtime.sim.storecycles += 1;
 
if (or32_opcodes[current->insn_index].func_unit == it_load)
runtime.sim.loadcycles += 1;
 
/* Pseudo multiple issue benchmark */
if ((multissue[or32_opcodes[current->insn_index].func_unit] < 1) ||
(check_depend (&cpu_state.icomplet, current))
|| (issued_per_cycle < 1))
{
int i;
for (i = 0; i < 20; i++)
multissue[i] = 2;
issued_per_cycle = 2;
runtime.cpu.supercycles++;
if (check_depend (&cpu_state.icomplet, current))
runtime.cpu.hazardwait++;
multissue[it_unknown] = 2;
multissue[it_shift] = 2;
multissue[it_compare] = 1;
multissue[it_branch] = 1;
multissue[it_jump] = 1;
multissue[it_extend] = 2;
multissue[it_nop] = 2;
multissue[it_move] = 2;
multissue[it_movimm] = 2;
multissue[it_arith] = 2;
multissue[it_store] = 2;
multissue[it_load] = 2;
}
multissue[or32_opcodes[current->insn_index].func_unit]--;
issued_per_cycle--;
}
 
if (config.cpu.dependstats)
/* Instruction waits in completition buffer until retired. */
memcpy (&cpu_state.icomplet, current, sizeof (struct iqueue_entry));
 
if (config.sim.history)
{
/* History of execution */
hist_exec_tail = hist_exec_tail->next;
hist_exec_tail->addr = cpu_state.icomplet.insn_addr;
}
 
if (config.sim.exe_log)
dump_exe_log ();
 
} /* analysis() */
 
/*---------------------------------------------------------------------------*/
/*!Store buffer analysis for store instructions
 
Stores are accumulated and commited when IO is idle
 
@param[in] cyc Number of cycles being analysed */
/*---------------------------------------------------------------------------*/
static void
sbuf_store (int cyc)
{
int delta = runtime.sim.cycles - sbuf_prev_cycles;
 
sbuf_total_cyc += cyc;
sbuf_prev_cycles = runtime.sim.cycles;
 
/* Take stores from buffer, that occured meanwhile */
while (sbuf_count && delta >= sbuf_buf[sbuf_tail])
{
delta -= sbuf_buf[sbuf_tail];
sbuf_tail = (sbuf_tail + 1) % MAX_SBUF_LEN;
sbuf_count--;
}
 
if (sbuf_count)
{
sbuf_buf[sbuf_tail] -= delta;
}
 
/* Store buffer is full, take one out */
if (sbuf_count >= config.cpu.sbuf_len)
{
sbuf_wait_cyc += sbuf_buf[sbuf_tail];
runtime.sim.mem_cycles += sbuf_buf[sbuf_tail];
sbuf_prev_cycles += sbuf_buf[sbuf_tail];
sbuf_tail = (sbuf_tail + 1) % MAX_SBUF_LEN;
sbuf_count--;
}
 
/* Put newest store in the buffer */
sbuf_buf[sbuf_head] = cyc;
sbuf_head = (sbuf_head + 1) % MAX_SBUF_LEN;
sbuf_count++;
 
} /* sbuf_store() */
 
 
/*---------------------------------------------------------------------------*/
/*!Store buffer analysis for load instructions
 
Previous stores should commit, before any load */
/*---------------------------------------------------------------------------*/
static void
sbuf_load ()
{
int delta = runtime.sim.cycles - sbuf_prev_cycles;
sbuf_prev_cycles = runtime.sim.cycles;
 
/* Take stores from buffer, that occured meanwhile */
while (sbuf_count && delta >= sbuf_buf[sbuf_tail])
{
delta -= sbuf_buf[sbuf_tail];
sbuf_tail = (sbuf_tail + 1) % MAX_SBUF_LEN;
sbuf_count--;
}
 
if (sbuf_count)
{
sbuf_buf[sbuf_tail] -= delta;
}
 
/* Wait for all stores to complete */
while (sbuf_count > 0)
{
sbuf_wait_cyc += sbuf_buf[sbuf_tail];
runtime.sim.mem_cycles += sbuf_buf[sbuf_tail];
sbuf_prev_cycles += sbuf_buf[sbuf_tail];
sbuf_tail = (sbuf_tail + 1) % MAX_SBUF_LEN;
sbuf_count--;
}
} /* sbuf_load() */
 
 
/*---------------------------------------------------------------------------*/
/*!Outputs dissasembled instruction */
/*---------------------------------------------------------------------------*/
void
dump_exe_log ()
{
oraddr_t insn_addr = cpu_state.iqueue.insn_addr;
unsigned int i;
unsigned int j;
uorreg_t operand;
 
if (insn_addr == 0xffffffff)
{
return;
}
 
if ((config.sim.exe_log_start <= runtime.cpu.instructions) &&
((config.sim.exe_log_end <= 0) ||
(runtime.cpu.instructions <= config.sim.exe_log_end)))
{
struct label_entry *entry;
 
if (config.sim.exe_log_marker &&
!(runtime.cpu.instructions % config.sim.exe_log_marker))
{
fprintf (runtime.sim.fexe_log,
"--------------------- %8lli instruction "
"---------------------\n",
runtime.cpu.instructions);
}
 
switch (config.sim.exe_log_type)
{
case EXE_LOG_HARDWARE:
fprintf (runtime.sim.fexe_log,
"\nEXECUTED(%11llu): %" PRIxADDR ": ",
runtime.cpu.instructions, insn_addr);
fprintf (runtime.sim.fexe_log, "%.2x%.2x",
eval_direct8 (insn_addr, 0, 0),
eval_direct8 (insn_addr + 1, 0, 0));
fprintf (runtime.sim.fexe_log, "%.2x%.2x",
eval_direct8 (insn_addr + 2, 0, 0),
eval_direct8 (insn_addr + 3, 0, 0));
 
for (i = 0; i < MAX_GPRS; i++)
{
if (i % 4 == 0)
{
fprintf (runtime.sim.fexe_log, "\n");
}
 
fprintf (runtime.sim.fexe_log, "GPR%2u: %" PRIxREG " ", i,
cpu_state.reg[i]);
}
 
fprintf (runtime.sim.fexe_log, "\n");
fprintf (runtime.sim.fexe_log, "SR : %.8" PRIx32 " ",
cpu_state.sprs[SPR_SR]);
fprintf (runtime.sim.fexe_log, "EPCR0: %" PRIxADDR " ",
cpu_state.sprs[SPR_EPCR_BASE]);
fprintf (runtime.sim.fexe_log, "EEAR0: %" PRIxADDR " ",
cpu_state.sprs[SPR_EEAR_BASE]);
fprintf (runtime.sim.fexe_log, "ESR0 : %.8" PRIx32 "\n",
cpu_state.sprs[SPR_ESR_BASE]);
break;
 
case EXE_LOG_SIMPLE:
case EXE_LOG_SOFTWARE:
disassemble_index (cpu_state.iqueue.insn,
cpu_state.iqueue.insn_index);
 
entry = get_label (insn_addr);
if (entry)
{
fprintf (runtime.sim.fexe_log, "%s:\n", entry->name);
}
if (config.sim.exe_log_type == EXE_LOG_SOFTWARE)
{
struct insn_op_struct *opd =
op_start[cpu_state.iqueue.insn_index];
 
j = 0;
while (1)
{
operand = eval_operand_val (cpu_state.iqueue.insn, opd);
while (!(opd->type & OPTYPE_OP))
{
opd++;
}
if (opd->type & OPTYPE_DIS)
{
fprintf (runtime.sim.fexe_log,
"EA =%" PRIxADDR " PA =%" PRIxADDR " ",
cpu_state.insn_ea,
peek_into_dtlb (cpu_state.insn_ea, 0, 0));
opd++; /* Skip of register operand */
j++;
}
else if ((opd->type & OPTYPE_REG) && operand)
{
fprintf (runtime.sim.fexe_log, "r%-2i=%" PRIxREG " ",
(int) operand, evalsim_reg (operand));
}
else
{
fprintf (runtime.sim.fexe_log, " ");
}
j++;
if (opd->type & OPTYPE_LAST)
{
break;
}
opd++;
}
if (or32_opcodes[cpu_state.iqueue.insn_index].flags & OR32_R_FLAG)
{
fprintf (runtime.sim.fexe_log, "SR =%08x ",
cpu_state.sprs[SPR_SR]);
j++;
}
while (j < 3)
{
fprintf (runtime.sim.fexe_log, " ");
j++;
}
}
fprintf (runtime.sim.fexe_log, "%" PRIxADDR " ", insn_addr);
fprintf (runtime.sim.fexe_log, "%s\n", disassembled);
}
}
} /* dump_exe_log() */
 
 
/*---------------------------------------------------------------------------*/
/*!Dump registers
 
Supports the CLI 'r' and 't' commands */
/*---------------------------------------------------------------------------*/
void
dumpreg ()
{
int i;
oraddr_t physical_pc;
 
if ((physical_pc = peek_into_itlb (cpu_state.iqueue.insn_addr)))
{
disassemble_memory (physical_pc, physical_pc + 4, 0);
}
else
{
PRINTF ("INTERNAL SIMULATOR ERROR:\n");
PRINTF ("no translation for currently executed instruction\n");
}
 
// generate_time_pretty (temp, runtime.sim.cycles * config.sim.clkcycle_ps);
PRINTF (" (executed) [cycle %lld, #%lld]\n", runtime.sim.cycles,
runtime.cpu.instructions);
if (config.cpu.superscalar)
{
PRINTF ("Superscalar CYCLES: %u", runtime.cpu.supercycles);
}
if (config.cpu.hazards)
{
PRINTF (" HAZARDWAIT: %u\n", runtime.cpu.hazardwait);
}
else if (config.cpu.superscalar)
{
PRINTF ("\n");
}
 
if ((physical_pc = peek_into_itlb (cpu_state.pc)))
{
disassemble_memory (physical_pc, physical_pc + 4, 0);
}
else
{
PRINTF ("%" PRIxADDR ": : xxxxxxxx ITLB miss follows", cpu_state.pc);
}
 
PRINTF (" (next insn) %s", (cpu_state.delay_insn ? "(delay insn)" : ""));
 
for (i = 0; i < MAX_GPRS; i++)
{
if (i % 4 == 0)
{
PRINTF ("\n");
}
 
PRINTF ("GPR%.2u: %" PRIxREG " ", i, evalsim_reg (i));
}
 
PRINTF ("flag: %u\n", cpu_state.sprs[SPR_SR] & SPR_SR_F ? 1 : 0);
 
} /* dumpreg() */
 
 
/*---------------------------------------------------------------------------*/
/*!Wrapper around real decode_execute function
 
Some statistics here only
 
@param[in] current Instruction being executed */
/*---------------------------------------------------------------------------*/
static void
decode_execute_wrapper (struct iqueue_entry *current)
{
breakpoint = 0;
 
#ifndef HAVE_EXECUTION
#error HAVE_EXECUTION has to be defined in order to execute programs.
#endif
 
/* FIXME: Most of this file is not needed with DYNAMIC_EXECUTION */
#if !(DYNAMIC_EXECUTION)
decode_execute (current);
#endif
 
#if SET_OV_FLAG
/* Check for range exception */
if ((cpu_state.sprs[SPR_SR] & SPR_SR_OVE) &&
(cpu_state.sprs[SPR_SR] & SPR_SR_OV))
{
except_handle (EXCEPT_RANGE, cpu_state.sprs[SPR_EEAR_BASE]);
}
#endif
 
if (breakpoint)
{
except_handle (EXCEPT_TRAP, cpu_state.sprs[SPR_EEAR_BASE]);
}
} /* decode_execute_wrapper() */
 
/*---------------------------------------------------------------------------*/
/*!Reset the CPU */
/*---------------------------------------------------------------------------*/
void
cpu_reset ()
{
int i;
struct hist_exec *hist_exec_head = NULL;
struct hist_exec *hist_exec_new;
 
runtime.sim.cycles = 0;
runtime.sim.loadcycles = 0;
runtime.sim.storecycles = 0;
runtime.cpu.instructions = 0;
runtime.cpu.supercycles = 0;
runtime.cpu.hazardwait = 0;
 
for (i = 0; i < MAX_GPRS; i++)
{
setsim_reg (i, 0);
}
 
memset (&cpu_state.iqueue, 0, sizeof (cpu_state.iqueue));
memset (&cpu_state.icomplet, 0, sizeof (cpu_state.icomplet));
 
sbuf_head = 0;
sbuf_tail = 0;
sbuf_count = 0;
sbuf_prev_cycles = 0;
 
/* Initialise execution history circular buffer */
for (i = 0; i < HISTEXEC_LEN; i++)
{
hist_exec_new = malloc (sizeof (struct hist_exec));
 
if (!hist_exec_new)
{
fprintf (stderr, "Out-of-memory\n");
exit (1);
}
 
if (!hist_exec_head)
{
hist_exec_head = hist_exec_new;
}
else
{
hist_exec_tail->next = hist_exec_new;
}
 
hist_exec_new->prev = hist_exec_tail;
hist_exec_tail = hist_exec_new;
}
 
/* Make hist_exec_tail->next point to hist_exec_head */
hist_exec_tail->next = hist_exec_head;
hist_exec_head->prev = hist_exec_tail;
 
/* MM1409: All progs should start at reset vector entry! This sorted out by
setting the cpu_state.pc field below. Not clear this is very good code! */
pcnext = 0x0;
 
if (config.sim.verbose)
{
PRINTF ("Starting at 0x%" PRIxADDR "\n", pcnext);
}
 
cpu_state.pc = pcnext;
pcnext += 4;
 
/* MM1409: All programs should set their stack pointer! */
#if !(DYNAMIC_EXECUTION)
except_handle (EXCEPT_RESET, 0);
update_pc ();
#endif
 
except_pending = 0;
cpu_state.pc = EXCEPT_RESET;
 
} /* cpu_reset() */
 
 
/*---------------------------------------------------------------------------*/
/*!Simulates one CPU clock cycle
@return non-zero if a breakpoint is hit, zero otherwise. */
/*---------------------------------------------------------------------------*/
int
cpu_clock ()
{
except_pending = 0;
next_delay_insn = 0;
 
if (fetch ())
{
PRINTF ("Breakpoint hit.\n");
return 1;
}
 
if (except_pending)
{
update_pc ();
except_pending = 0;
return 0;
}
 
if (breakpoint)
{
except_handle (EXCEPT_TRAP, cpu_state.sprs[SPR_EEAR_BASE]);
update_pc ();
except_pending = 0;
return 0;
}
 
decode_execute_wrapper (&cpu_state.iqueue);
update_pc ();
return 0;
 
} /* cpu_clock() */
 
 
/*---------------------------------------------------------------------------*/
/*!If decoding cannot be found, call this function */
/*---------------------------------------------------------------------------*/
#if SIMPLE_EXECUTION
void
l_invalid (struct iqueue_entry *current)
{
#else
void
l_invalid ()
{
#endif
except_handle (EXCEPT_ILLEGAL, cpu_state.iqueue.insn_addr);
 
} /* l_invalid() */
 
 
/*---------------------------------------------------------------------------*/
/*!The main execution loop */
/*---------------------------------------------------------------------------*/
void
exec_main ()
{
long long time_start;
 
while (1)
{
time_start = runtime.sim.cycles;
if (config.debug.enabled)
{
while (runtime.cpu.stalled)
{
if (config.debug.gdb_enabled)
{
block_jtag ();
handle_server_socket (FALSE);
}
else
{
fprintf (stderr,
"WARNING: CPU stalled and gdb connection not enabled.\n");
/* Dump the user into interactive mode. From there he can decide what
* to do. */
handle_sim_command ();
sim_done ();
}
if (runtime.sim.iprompt)
handle_sim_command ();
}
}
 
/* Each cycle has counter of mem_cycles; this value is joined with cycles
at the end of the cycle; no sim originated memory accesses should be
performed inbetween. */
runtime.sim.mem_cycles = 0;
 
if (!config.pm.enabled ||
!(config.pm.enabled &
(cpu_state.sprs[SPR_PMR] & (SPR_PMR_DME | SPR_PMR_SME))))
{
if (cpu_clock ())
{
/* A breakpoint has been hit, drop to interactive mode */
handle_sim_command ();
}
}
 
if (config.vapi.enabled && runtime.vapi.enabled)
{
vapi_check ();
}
 
if (config.debug.gdb_enabled)
{
handle_server_socket (FALSE); /* block & check_stdin = false */
}
 
if (config.debug.enabled)
{
if (cpu_state.sprs[SPR_DMR1] & SPR_DMR1_ST)
{
set_stall_state (1);
}
}
 
runtime.sim.cycles += runtime.sim.mem_cycles;
scheduler.job_queue->time -= runtime.sim.cycles - time_start;
 
if (scheduler.job_queue->time <= 0)
{
do_scheduler ();
}
}
} /* exec_main() */
 
#if COMPLEX_EXECUTION
 
/* Include generated/built in decode_execute function */
#include "execgen.c"
 
#elif SIMPLE_EXECUTION
 
 
#define INSTRUCTION(name) void name (struct iqueue_entry *current)
 
/*---------------------------------------------------------------------------*/
/*!Evaluates source operand
 
Implementation specific.
 
@param[in] op_no The operand
@param[in] insn_index Address of the instruction
@param[in] insn The instruction
 
@return The value of the operand */
/*---------------------------------------------------------------------------*/
static uorreg_t
eval_operand (int op_no,
unsigned long insn_index,
uint32_t insn)
{
struct insn_op_struct *opd = op_start[insn_index];
uorreg_t ret;
 
while (op_no)
{
if (opd->type & OPTYPE_LAST)
{
fprintf (stderr,
"Instruction requested more operands than it has\n");
exit (1);
}
 
if ((opd->type & OPTYPE_OP) && !(opd->type & OPTYPE_DIS))
{
op_no--;
}
 
opd++;
}
 
if (opd->type & OPTYPE_DIS)
{
ret = eval_operand_val (insn, opd);
 
while (!(opd->type & OPTYPE_OP))
{
opd++;
}
 
opd++;
ret += evalsim_reg (eval_operand_val (insn, opd));
cpu_state.insn_ea = ret;
 
return ret;
}
 
if (opd->type & OPTYPE_REG)
{
return evalsim_reg (eval_operand_val (insn, opd));
}
 
return eval_operand_val (insn, opd);
 
} /* eval_operand() */
 
 
/*---------------------------------------------------------------------------*/
/*!Set destination operand (register direct) with value.
 
Implementation specific.
 
@param[in] op_no The operand
@param[in] value The value to set
@param[in] insn_index Address of the instruction
@param[in] insn The instruction */
/*---------------------------------------------------------------------------*/
static void
set_operand (int op_no,
orreg_t value,
unsigned long insn_index,
uint32_t insn)
{
struct insn_op_struct *opd = op_start[insn_index];
 
while (op_no)
{
if (opd->type & OPTYPE_LAST)
{
fprintf (stderr,
"Instruction requested more operands than it has\n");
exit (1);
}
 
if ((opd->type & OPTYPE_OP) && !(opd->type & OPTYPE_DIS))
{
op_no--;
}
 
opd++;
}
 
if (!(opd->type & OPTYPE_REG))
{
fprintf (stderr, "Trying to set a non-register operand\n");
exit (1);
}
 
setsim_reg (eval_operand_val (insn, opd), value);
 
} /* set_operand() */
 
 
/*---------------------------------------------------------------------------*/
/*!Simple and rather slow decoding function
 
Based on built automata.
 
@param[in] current The current instruction to execute */
/*---------------------------------------------------------------------------*/
static void
decode_execute (struct iqueue_entry *current)
{
int insn_index;
 
current->insn_index = insn_index = insn_decode (current->insn);
 
if (insn_index < 0)
{
l_invalid (current);
}
else
{
or32_opcodes[insn_index].exec (current);
}
 
if (do_stats)
analysis (&cpu_state.iqueue);
}
 
#include "insnset.c"
 
#elif defined(DYNAMIC_EXECUTION)
 
#else
# error "Must define SIMPLE_EXECUTION, COMPLEX_EXECUTION or DYNAMIC_EXECUTION"
#endif
/op-arith-op.h
0,0 → 1,33
/* op-arith-op.h -- Micro operations template for arithmetic operations
 
 
This file is part of OpenRISC 1000 Architectural Simulator.
 
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
 
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
 
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
 
#ifdef OP_3T
__or_dynop void glue(glue(op_, OP_NAME), T)(void)
{
OP_CAST(T0) = OP_CAST(T1) OP OP_CAST(T2) OP_EXTRA;
}
#endif
 
#ifdef OP_2T
__or_dynop void glue(glue(glue(op_, OP_NAME), _imm), T)(void)
{
OP_CAST(T0) = OP_CAST(T1) OP OP_CAST(OP_PARAM1) OP_EXTRA;
}
#endif
 
/op-1t.h
0,0 → 1,38
/* op-1t.h -- Instantiation of operatations that work on only 1 temporary
 
 
This file is part of OpenRISC 1000 Architectural Simulator.
 
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
 
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
 
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
 
#define OP_1T
#define T glue(_, T0)
 
#if NUM_T_REGS == 3
#define T0 t0
#include OP_FILE
#undef T0
#define T0 t1
#include OP_FILE
#undef T0
#define T0 t2
#include OP_FILE
#undef T0
#else
#error Update op_1t.h for NUM_T_REGS temporaries
#endif
 
#undef T
#undef OP_1T
/dyn-rec.h
0,0 → 1,61
/* dyn-rec.h -- Recompiler specific definitions
 
 
This file is part of OpenRISC 1000 Architectural Simulator.
 
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
 
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
 
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
 
 
#ifndef DYN_REC_H
#define DYN_REC_H
 
typedef void (*gen_code_ent)(void);
 
/* Each dynamically recompiled page has one of these */
struct dyn_page {
oraddr_t or_page;
void *host_page;
unsigned int host_len;
int dirty; /* Is recompiled page invalid? */
int delayr; /* delayr of memory backing this page */
uint16_t ts_bound[2049]; /* What registers the temporaries back (on the
* begining boundry of the instruction) */
void **locs; /* Openrisc locations in the recompiled code */
uint32_t *insns; /* Copy of instructions on this page */
unsigned int *insn_indexs; /* Decoded instructions on this page */
};
 
void recompile_page(struct dyn_page *dyn);
struct dyn_page *new_dp(oraddr_t page);
void add_to_opq(struct op_queue *opq, int end, int op);
void add_to_op_params(struct op_queue *opq, int end, unsigned long param);
void *enough_host_page(struct dyn_page *dp, void *cur, unsigned int *len,
unsigned int amount);
void init_dyn_recomp(void);
void run_sched_out_of_line(void);
void recheck_immu(int got_en_dis);
void enter_dyn_code(oraddr_t addr, struct dyn_page *dp);
void dyn_checkwrite(oraddr_t addr);
void dyn_main(void);
 
extern void *rec_stack_base;
 
#define IMMU_GOT_ENABLED 1
#define IMMU_GOT_DISABLED 2
 
#define xglue(x, y) x ## y
#define glue(x, y) xglue(x, y)
 
#endif
/op-3t.h
0,0 → 1,135
/* op-3t.h -- Instantiation of operatations that work on only 3 temporary
 
 
This file is part of OpenRISC 1000 Architectural Simulator.
 
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
 
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
 
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
 
 
#define OP_3T
#define T glue(glue(glue(glue(glue(_, T0), _), T1), _), T2)
 
#if NUM_T_REGS == 3
# define T0 t0
# define T1 t0
# define T2 t0
# include OP_FILE
# undef T2
# define T2 t1
# include OP_FILE
# undef T2
# define T2 t2
# include OP_FILE
# undef T2
# undef T1
# define T1 t1
# define T2 t0
# include OP_FILE
# undef T2
# define T2 t1
# include OP_FILE
# undef T2
# define T2 t2
# include OP_FILE
# undef T2
# undef T1
# define T1 t2
# define T2 t0
# include OP_FILE
# undef T2
# define T2 t1
# include OP_FILE
# undef T2
# define T2 t2
# include OP_FILE
# undef T2
# undef T1
# undef T0
# define T0 t1
# define T1 t0
# define T2 t0
# include OP_FILE
# undef T2
# define T2 t1
# include OP_FILE
# undef T2
# define T2 t2
# include OP_FILE
# undef T2
# undef T1
# define T1 t1
# define T2 t0
# include OP_FILE
# undef T2
# define T2 t1
# include OP_FILE
# undef T2
# define T2 t2
# include OP_FILE
# undef T2
# undef T1
# define T1 t2
# define T2 t0
# include OP_FILE
# undef T2
# define T2 t1
# include OP_FILE
# undef T2
# define T2 t2
# include OP_FILE
# undef T2
# undef T1
# undef T0
# define T0 t2
# define T1 t0
# define T2 t0
# include OP_FILE
# undef T2
# define T2 t1
# include OP_FILE
# undef T2
# define T2 t2
# include OP_FILE
# undef T2
# undef T1
# define T1 t1
# define T2 t0
# include OP_FILE
# undef T2
# define T2 t1
# include OP_FILE
# undef T2
# define T2 t2
# include OP_FILE
# undef T2
# undef T1
# define T1 t2
# define T2 t0
# include OP_FILE
# undef T2
# define T2 t1
# include OP_FILE
# undef T2
# define T2 t2
# include OP_FILE
# undef T2
# undef T1
# undef T0
#else
#error Update op_3t.h for NUM_T_REGS temporaries
#endif
 
#undef T
#undef OP_3T
/op-ff1-op.h
0,0 → 1,35
/* op-ff1-op.h -- Micro operations template for the ff1 instruction
 
 
This file is part of OpenRISC 1000 Architectural Simulator.
 
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
 
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
 
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
 
 
__or_dynop void glue(glue(glue(op_ff1_, DST_T), _), SRC_T)(void)
{
int i;
 
for(i = 0; i < 32; i++, SRC_T >>= 1) {
if(SRC_T & 1) {
DST_T = i;
break;
}
}
 
FORCE_RET;
}
 
 
/op-t-reg-mov-op.h
0,0 → 1,330
/* op-t-reg-mov-op.h -- Micro operations template for reg<->temporary operations
 
 
This file is part of OpenRISC 1000 Architectural Simulator.
 
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
 
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
 
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
 
 
__or_dynop void glue(op_gtt_gpr1, T)(void)
{
T0 = env->reg[1];
}
 
__or_dynop void glue(op_gtt_gpr2, T)(void)
{
T0 = env->reg[2];
}
 
__or_dynop void glue(op_gtt_gpr3, T)(void)
{
T0 = env->reg[3];
}
 
__or_dynop void glue(op_gtt_gpr4, T)(void)
{
T0 = env->reg[4];
}
 
__or_dynop void glue(op_gtt_gpr5, T)(void)
{
T0 = env->reg[5];
}
 
__or_dynop void glue(op_gtt_gpr6, T)(void)
{
T0 = env->reg[6];
}
 
__or_dynop void glue(op_gtt_gpr7, T)(void)
{
T0 = env->reg[7];
}
 
__or_dynop void glue(op_gtt_gpr8, T)(void)
{
T0 = env->reg[8];
}
 
__or_dynop void glue(op_gtt_gpr9, T)(void)
{
T0 = env->reg[9];
}
 
__or_dynop void glue(op_gtt_gpr10, T)(void)
{
T0 = env->reg[10];
}
 
__or_dynop void glue(op_gtt_gpr11, T)(void)
{
T0 = env->reg[11];
}
 
__or_dynop void glue(op_gtt_gpr12, T)(void)
{
T0 = env->reg[12];
}
 
__or_dynop void glue(op_gtt_gpr13, T)(void)
{
T0 = env->reg[13];
}
 
__or_dynop void glue(op_gtt_gpr14, T)(void)
{
T0 = env->reg[14];
}
 
__or_dynop void glue(op_gtt_gpr15, T)(void)
{
T0 = env->reg[15];
}
 
__or_dynop void glue(op_gtt_gpr16, T)(void)
{
T0 = env->reg[16];
}
 
__or_dynop void glue(op_gtt_gpr17, T)(void)
{
T0 = env->reg[17];
}
 
__or_dynop void glue(op_gtt_gpr18, T)(void)
{
T0 = env->reg[18];
}
 
__or_dynop void glue(op_gtt_gpr19, T)(void)
{
T0 = env->reg[19];
}
 
__or_dynop void glue(op_gtt_gpr20, T)(void)
{
T0 = env->reg[20];
}
 
__or_dynop void glue(op_gtt_gpr21, T)(void)
{
T0 = env->reg[21];
}
 
__or_dynop void glue(op_gtt_gpr22, T)(void)
{
T0 = env->reg[22];
}
 
__or_dynop void glue(op_gtt_gpr23, T)(void)
{
T0 = env->reg[23];
}
 
__or_dynop void glue(op_gtt_gpr24, T)(void)
{
T0 = env->reg[24];
}
 
__or_dynop void glue(op_gtt_gpr25, T)(void)
{
T0 = env->reg[25];
}
 
__or_dynop void glue(op_gtt_gpr26, T)(void)
{
T0 = env->reg[26];
}
 
__or_dynop void glue(op_gtt_gpr27, T)(void)
{
T0 = env->reg[27];
}
 
__or_dynop void glue(op_gtt_gpr28, T)(void)
{
T0 = env->reg[28];
}
 
__or_dynop void glue(op_gtt_gpr29, T)(void)
{
T0 = env->reg[29];
}
 
__or_dynop void glue(op_gtt_gpr30, T)(void)
{
T0 = env->reg[30];
}
 
__or_dynop void glue(op_gtt_gpr31, T)(void)
{
T0 = env->reg[31];
}
 
__or_dynop void glue(op_ttg_gpr1, T)(void)
{
env->reg[1] = T0;
}
 
__or_dynop void glue(op_ttg_gpr2, T)(void)
{
env->reg[2] = T0;
}
 
__or_dynop void glue(op_ttg_gpr3, T)(void)
{
env->reg[3] = T0;
}
 
__or_dynop void glue(op_ttg_gpr4, T)(void)
{
env->reg[4] = T0;
}
 
__or_dynop void glue(op_ttg_gpr5, T)(void)
{
env->reg[5] = T0;
}
 
__or_dynop void glue(op_ttg_gpr6, T)(void)
{
env->reg[6] = T0;
}
 
__or_dynop void glue(op_ttg_gpr7, T)(void)
{
env->reg[7] = T0;
}
 
__or_dynop void glue(op_ttg_gpr8, T)(void)
{
env->reg[8] = T0;
}
 
__or_dynop void glue(op_ttg_gpr9, T)(void)
{
env->reg[9] = T0;
}
 
__or_dynop void glue(op_ttg_gpr10, T)(void)
{
env->reg[10] = T0;
}
 
__or_dynop void glue(op_ttg_gpr11, T)(void)
{
env->reg[11] = T0;
}
 
__or_dynop void glue(op_ttg_gpr12, T)(void)
{
env->reg[12] = T0;
}
 
__or_dynop void glue(op_ttg_gpr13, T)(void)
{
env->reg[13] = T0;
}
 
__or_dynop void glue(op_ttg_gpr14, T)(void)
{
env->reg[14] = T0;
}
 
__or_dynop void glue(op_ttg_gpr15, T)(void)
{
env->reg[15] = T0;
}
 
__or_dynop void glue(op_ttg_gpr16, T)(void)
{
env->reg[16] = T0;
}
 
__or_dynop void glue(op_ttg_gpr17, T)(void)
{
env->reg[17] = T0;
}
 
__or_dynop void glue(op_ttg_gpr18, T)(void)
{
env->reg[18] = T0;
}
 
__or_dynop void glue(op_ttg_gpr19, T)(void)
{
env->reg[19] = T0;
}
 
__or_dynop void glue(op_ttg_gpr20, T)(void)
{
env->reg[20] = T0;
}
 
__or_dynop void glue(op_ttg_gpr21, T)(void)
{
env->reg[21] = T0;
}
 
__or_dynop void glue(op_ttg_gpr22, T)(void)
{
env->reg[22] = T0;
}
 
__or_dynop void glue(op_ttg_gpr23, T)(void)
{
env->reg[23] = T0;
}
 
__or_dynop void glue(op_ttg_gpr24, T)(void)
{
env->reg[24] = T0;
}
 
__or_dynop void glue(op_ttg_gpr25, T)(void)
{
env->reg[25] = T0;
}
 
__or_dynop void glue(op_ttg_gpr26, T)(void)
{
env->reg[26] = T0;
}
 
__or_dynop void glue(op_ttg_gpr27, T)(void)
{
env->reg[27] = T0;
}
 
__or_dynop void glue(op_ttg_gpr28, T)(void)
{
env->reg[28] = T0;
}
 
__or_dynop void glue(op_ttg_gpr29, T)(void)
{
env->reg[29] = T0;
}
 
__or_dynop void glue(op_ttg_gpr30, T)(void)
{
env->reg[30] = T0;
}
 
__or_dynop void glue(op_ttg_gpr31, T)(void)
{
env->reg[31] = T0;
}
 
/dyngen-i386.c
0,0 → 1,75
/* dyngen-i386.c -- i386 parts of dyngen
 
 
This file is part of OpenRISC 1000 Architectural Simulator.
 
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
 
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
 
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
 
 
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
 
#include <elf.h>
 
#include "dyngen.h"
 
#define RET_OPCODE 0xc3
 
unsigned int i386_get_real_func_len(void *f_start, unsigned int f_len, char *name)
{
if(((uint8_t *)f_start)[f_len - 1] != RET_OPCODE) {
fprintf(stderr, "`%s' does not have a ret at the end!\n", name);
exit(1);
}
 
return f_len - 1;
}
 
void i386_gen_reloc(FILE *f, struct reloc *reloc, unsigned int param)
{
switch(reloc->type) {
case R_386_32:
fprintf(f, " *(uint32_t *)(host_page + %d) = *(ops_param + %u) + %d;\n",
reloc->func_offset, param - 1, reloc->addend);
break;
default:
fprintf(stderr, "Unknown i386 relocation: %i (%s)\n", reloc->type,
reloc->name);
}
}
 
void i386_gen_func_reloc(FILE *f, struct reloc *reloc)
{
switch(reloc->type) {
case R_386_32:
/* This relocation is absolute. There is nothing to relocate (The linker
* handles this fine). */
break;
case R_386_PC32:
fprintf(f, " *(uint32_t *)(host_page + %d) = (uint32_t)((%s + %d) - (unsigned int)(host_page + %d));\n",
reloc->func_offset, reloc->name, reloc->addend, reloc->func_offset);
break;
default:
fprintf(stderr, "Unknown i386 relocation: %i (symbol: %s)\n", reloc->type,
reloc->name);
}
}
 
const struct archf archfs = {
i386_get_real_func_len,
i386_gen_reloc,
i386_gen_func_reloc
};
/simpl32-defs.h
0,0 → 1,95
/* simpl32-defs.h -- Definitions for the simple execution model
Copyright (C) 1999 Damjan Lampret, lampret@opencores.org
 
This file is part of OpenRISC 1000 Architectural Simulator.
 
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
 
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
 
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
 
extern void l_invalid PARAMS((struct iqueue_entry *));
extern void l_sfne PARAMS((struct iqueue_entry *));
extern void l_bf PARAMS((struct iqueue_entry *));
extern void l_add PARAMS((struct iqueue_entry *));
extern void l_addc PARAMS((struct iqueue_entry *));
extern void l_sw PARAMS((struct iqueue_entry *));
extern void l_sb PARAMS((struct iqueue_entry *));
extern void l_sh PARAMS((struct iqueue_entry *));
extern void l_lwz PARAMS((struct iqueue_entry *));
extern void l_lbs PARAMS((struct iqueue_entry *));
extern void l_lbz PARAMS((struct iqueue_entry *));
extern void l_lhs PARAMS((struct iqueue_entry *));
extern void l_lhz PARAMS((struct iqueue_entry *));
extern void l_movhi PARAMS((struct iqueue_entry *));
extern void l_and PARAMS((struct iqueue_entry *));
extern void l_or PARAMS((struct iqueue_entry *));
extern void l_xor PARAMS((struct iqueue_entry *));
extern void l_sub PARAMS((struct iqueue_entry *));
extern void l_mul PARAMS((struct iqueue_entry *));
extern void l_div PARAMS((struct iqueue_entry *));
extern void l_divu PARAMS((struct iqueue_entry *));
extern void l_sll PARAMS((struct iqueue_entry *));
extern void l_sra PARAMS((struct iqueue_entry *));
extern void l_srl PARAMS((struct iqueue_entry *));
extern void l_j PARAMS((struct iqueue_entry *));
extern void l_jal PARAMS((struct iqueue_entry *));
extern void l_jalr PARAMS((struct iqueue_entry *));
extern void l_jr PARAMS((struct iqueue_entry *));
extern void l_rfe PARAMS((struct iqueue_entry *));
extern void l_nop PARAMS((struct iqueue_entry *));
extern void l_bnf PARAMS((struct iqueue_entry *));
extern void l_sfeq PARAMS((struct iqueue_entry *));
extern void l_sfgts PARAMS((struct iqueue_entry *));
extern void l_sfges PARAMS((struct iqueue_entry *));
extern void l_sflts PARAMS((struct iqueue_entry *));
extern void l_sfles PARAMS((struct iqueue_entry *));
extern void l_sfgtu PARAMS((struct iqueue_entry *));
extern void l_sfgeu PARAMS()(struct iqueue_entry *);
extern void l_sfltu PARAMS((struct iqueue_entry *));
extern void l_sfleu PARAMS((struct iqueue_entry *));
extern void l_extbs PARAMS((struct iqueue_entry *));
extern void l_extbz PARAMS((struct iqueue_entry *));
extern void l_exths PARAMS((struct iqueue_entry *));
extern void l_exthz PARAMS((struct iqueue_entry *));
extern void l_extws PARAMS((struct iqueue_entry *));
extern void l_extwz PARAMS((struct iqueue_entry *));
extern void l_mtspr PARAMS((struct iqueue_entry *));
extern void l_mfspr PARAMS((struct iqueue_entry *));
extern void l_sys PARAMS((struct iqueue_entry *));
extern void l_trap PARAMS((struct iqueue_entry *)); /* CZ 21/06/01 */
extern void l_macrc PARAMS((struct iqueue_entry *));
extern void l_mac PARAMS((struct iqueue_entry *));
extern void l_msb PARAMS((struct iqueue_entry *));
extern void l_invalid PARAMS((struct iqueue_entry *));
extern void l_cmov PARAMS ((struct iqueue_entry *));
extern void l_ff1 PARAMS ((struct iqueue_entry *));
extern void l_cust1 PARAMS ((struct iqueue_entry *));
extern void l_cust2 PARAMS ((struct iqueue_entry *));
extern void l_cust3 PARAMS ((struct iqueue_entry *));
extern void l_cust4 PARAMS ((struct iqueue_entry *));
extern void lf_add_s PARAMS ((struct iqueue_entry *));
extern void lf_div_s PARAMS ((struct iqueue_entry *));
extern void lf_ftoi_s PARAMS ((struct iqueue_entry *));
extern void lf_itof_s PARAMS ((struct iqueue_entry *));
extern void lf_madd_s PARAMS ((struct iqueue_entry *));
extern void lf_mul_s PARAMS ((struct iqueue_entry *));
extern void lf_rem_s PARAMS ((struct iqueue_entry *));
extern void lf_sfeq_s PARAMS ((struct iqueue_entry *));
extern void lf_sfge_s PARAMS ((struct iqueue_entry *));
extern void lf_sfgt_s PARAMS ((struct iqueue_entry *));
extern void lf_sfle_s PARAMS ((struct iqueue_entry *));
extern void lf_sflt_s PARAMS ((struct iqueue_entry *));
extern void lf_sfne_s PARAMS ((struct iqueue_entry *));
extern void lf_sub_s PARAMS((struct iqueue_entry *));
extern void l_none PARAMS((struct iqueue_entry *));
 
/op-1t-op.h
0,0 → 1,75
/* op-1t-op.h -- Micro operations useing only one temporary
 
 
This file is part of OpenRISC 1000 Architectural Simulator.
 
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
 
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
 
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
 
__or_dynop void glue(op_imm, T)(void)
{
T0 = OP_PARAM1;
}
 
__or_dynop void glue(op_clear, T)(void)
{
T0 = 0;
}
 
__or_dynop void glue(op_check_null_except_delay, T)(void)
{
if(!T0) {
/* Do exception */
env->sprs[SPR_EEAR_BASE] = env->pc - 4;
env->delay_insn = 0;
do_jump(EXCEPT_ILLEGAL);
}
}
 
__or_dynop void glue(op_check_null_except, T)(void)
{
if(!T0) {
/* Do exception */
env->sprs[SPR_EEAR_BASE] = env->pc;
do_jump(EXCEPT_ILLEGAL);
}
}
 
__or_dynop void glue(op_calc_insn_ea, T)(void)
{
env->insn_ea = T0 + OP_PARAM1;
}
 
__or_dynop void glue(op_macrc, T)(void)
{
/* FIXME: How is this supposed to work? The architechture manual says that
* the low 32-bits shall be saved into rD. I have just copied this code from
* insnset.c to make testbench/mul pass */
int64_t temp = env->sprs[SPR_MACLO] | ((int64_t)env->sprs[SPR_MACHI] << 32);
 
T0 = (orreg_t)(temp >> 28);
env->sprs[SPR_MACLO] = 0;
env->sprs[SPR_MACHI] = 0;
}
 
__or_dynop void glue(op_mac_imm, T)(void)
{
int64_t temp = env->sprs[SPR_MACLO] | ((int64_t)env->sprs[SPR_MACHI] << 32);
 
temp += (int64_t)T0 * (int64_t)OP_PARAM1;
 
env->sprs[SPR_MACLO] = temp & 0xffffffff;
env->sprs[SPR_MACHI] = temp >> 32;
}
 
/op-2t-op.h
0,0 → 1,44
/* op-1t-op.h -- Micro operations useing two temporaries
 
 
This file is part of OpenRISC 1000 Architectural Simulator.
 
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
 
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
 
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
 
__or_dynop void glue(op_move, T)(void)
{
T0 = T1;
}
 
__or_dynop void glue(op_ff1, T)(void)
{
int i;
 
for(i = 0; i < 32; i++, T0 >>= 1) {
if(T0 & 1) {
T1 = i;
break;
}
}
 
FORCE_RET;
}
 
 
__or_dynop void glue(op_neg, T)(void)
{
T0 = -T1;
}
 
/insnset.c
0,0 → 1,614
/* execute.c -- Instruction specific functions.
 
Copyright (C) 1999 Damjan Lampret, lampret@opencores.org
2000-2002 Marko Mlinar, markom@opencores.org
Copyright (C) 2008 Embecosm Limited
Contributor Jeremy Bennett <jeremy.bennett@embecosm.com>
This file is part of OpenRISC 1000 Architectural Simulator.
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 3 of the License, or (at your option)
any later version.
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
more details.
You should have received a copy of the GNU General Public License along
with this program. If not, see <http://www.gnu.org/licenses/>. */
 
/* This program is commented throughout in a fashion suitable for processing
with Doxygen. */
 
 
INSTRUCTION (l_add) {
orreg_t temp1, temp2, temp3;
int8_t temp4;
temp2 = (orreg_t)PARAM2;
temp3 = (orreg_t)PARAM1;
temp1 = temp2 + temp3;
SET_PARAM0(temp1);
SET_OV_FLAG_FN (temp1);
if (ARITH_SET_FLAG) {
if(!temp1)
cpu_state.sprs[SPR_SR] |= SPR_SR_F;
else
cpu_state.sprs[SPR_SR] &= ~SPR_SR_F;
}
if ((uorreg_t) temp1 < (uorreg_t) temp2)
cpu_state.sprs[SPR_SR] |= SPR_SR_CY;
else
cpu_state.sprs[SPR_SR] &= ~SPR_SR_CY;
 
temp4 = temp1;
if (temp4 == temp1)
or1k_mstats.byteadd++;
}
INSTRUCTION (l_addc) {
orreg_t temp1, temp2, temp3;
int8_t temp4;
temp2 = (orreg_t)PARAM2;
temp3 = (orreg_t)PARAM1;
temp1 = temp2 + temp3;
if(cpu_state.sprs[SPR_SR] & SPR_SR_CY)
temp1++;
SET_PARAM0(temp1);
SET_OV_FLAG_FN (temp1);
if (ARITH_SET_FLAG) {
if(!temp1)
cpu_state.sprs[SPR_SR] |= SPR_SR_F;
else
cpu_state.sprs[SPR_SR] &= ~SPR_SR_F;
}
if ((uorreg_t) temp1 < (uorreg_t) temp2)
cpu_state.sprs[SPR_SR] |= SPR_SR_CY;
else
cpu_state.sprs[SPR_SR] &= ~SPR_SR_CY;
 
temp4 = temp1;
if (temp4 == temp1)
or1k_mstats.byteadd++;
}
INSTRUCTION (l_sw) {
int old_cyc = 0;
if (config.cpu.sbuf_len) old_cyc = runtime.sim.mem_cycles;
set_mem32(PARAM0, PARAM1, &breakpoint);
if (config.cpu.sbuf_len) {
int t = runtime.sim.mem_cycles;
runtime.sim.mem_cycles = old_cyc;
sbuf_store (t - old_cyc);
}
}
INSTRUCTION (l_sb) {
int old_cyc = 0;
if (config.cpu.sbuf_len) old_cyc = runtime.sim.mem_cycles;
set_mem8(PARAM0, PARAM1, &breakpoint);
if (config.cpu.sbuf_len) {
int t = runtime.sim.mem_cycles;
runtime.sim.mem_cycles = old_cyc;
sbuf_store (t- old_cyc);
}
}
INSTRUCTION (l_sh) {
int old_cyc = 0;
if (config.cpu.sbuf_len) old_cyc = runtime.sim.mem_cycles;
set_mem16(PARAM0, PARAM1, &breakpoint);
if (config.cpu.sbuf_len) {
int t = runtime.sim.mem_cycles;
runtime.sim.mem_cycles = old_cyc;
sbuf_store (t - old_cyc);
}
}
INSTRUCTION (l_lwz) {
uint32_t val;
if (config.cpu.sbuf_len) sbuf_load ();
val = eval_mem32(PARAM1, &breakpoint);
/* If eval operand produced exception don't set anything. JPB changed to
trigger on breakpoint, as well as except_pending (seemed to be a bug). */
if (!(except_pending || breakpoint))
SET_PARAM0(val);
}
INSTRUCTION (l_lbs) {
int8_t val;
if (config.cpu.sbuf_len) sbuf_load ();
val = eval_mem8(PARAM1, &breakpoint);
/* If eval operand produced exception don't set anything. JPB changed to
trigger on breakpoint, as well as except_pending (seemed to be a bug). */
if (!(except_pending || breakpoint))
SET_PARAM0(val);
}
INSTRUCTION (l_lbz) {
uint8_t val;
if (config.cpu.sbuf_len) sbuf_load ();
val = eval_mem8(PARAM1, &breakpoint);
/* If eval operand produced exception don't set anything. JPB changed to
trigger on breakpoint, as well as except_pending (seemed to be a bug). */
if (!(except_pending || breakpoint))
SET_PARAM0(val);
}
INSTRUCTION (l_lhs) {
int16_t val;
if (config.cpu.sbuf_len) sbuf_load ();
val = eval_mem16(PARAM1, &breakpoint);
/* If eval operand produced exception don't set anything. JPB changed to
trigger on breakpoint, as well as except_pending (seemed to be a bug). */
if (!(except_pending || breakpoint))
SET_PARAM0(val);
}
INSTRUCTION (l_lhz) {
uint16_t val;
if (config.cpu.sbuf_len) sbuf_load ();
val = eval_mem16(PARAM1, &breakpoint);
/* If eval operand produced exception don't set anything. JPB changed to
trigger on breakpoint, as well as except_pending (seemed to be a bug). */
if (!(except_pending || breakpoint))
SET_PARAM0(val);
}
INSTRUCTION (l_movhi) {
SET_PARAM0(PARAM1 << 16);
}
INSTRUCTION (l_and) {
uorreg_t temp1;
temp1 = PARAM1 & PARAM2;
SET_OV_FLAG_FN (temp1);
SET_PARAM0(temp1);
if (ARITH_SET_FLAG) {
if(!temp1)
cpu_state.sprs[SPR_SR] |= SPR_SR_F;
else
cpu_state.sprs[SPR_SR] &= ~SPR_SR_F;
}
}
INSTRUCTION (l_or) {
uorreg_t temp1;
temp1 = PARAM1 | PARAM2;
SET_OV_FLAG_FN (temp1);
SET_PARAM0(temp1);
}
INSTRUCTION (l_xor) {
uorreg_t temp1;
temp1 = PARAM1 ^ PARAM2;
SET_OV_FLAG_FN (temp1);
SET_PARAM0(temp1);
}
INSTRUCTION (l_sub) {
orreg_t temp1;
temp1 = (orreg_t)PARAM1 - (orreg_t)PARAM2;
SET_OV_FLAG_FN (temp1);
SET_PARAM0(temp1);
}
/*int mcount = 0;*/
INSTRUCTION (l_mul) {
orreg_t temp1;
temp1 = (orreg_t)PARAM1 * (orreg_t)PARAM2;
SET_OV_FLAG_FN (temp1);
SET_PARAM0(temp1);
/*if (!(mcount++ & 1023)) {
PRINTF ("[%i]\n",mcount);
}*/
}
INSTRUCTION (l_div) {
orreg_t temp3, temp2, temp1;
temp3 = PARAM2;
temp2 = PARAM1;
if (temp3)
temp1 = temp2 / temp3;
else {
except_handle(EXCEPT_ILLEGAL, cpu_state.pc);
return;
}
SET_OV_FLAG_FN (temp1);
SET_PARAM0(temp1);
}
INSTRUCTION (l_divu) {
uorreg_t temp3, temp2, temp1;
temp3 = PARAM2;
temp2 = PARAM1;
if (temp3)
temp1 = temp2 / temp3;
else {
except_handle(EXCEPT_ILLEGAL, cpu_state.pc);
return;
}
SET_OV_FLAG_FN (temp1);
SET_PARAM0(temp1);
/* runtime.sim.cycles += 16; */
}
INSTRUCTION (l_sll) {
uorreg_t temp1;
 
temp1 = PARAM1 << PARAM2;
SET_OV_FLAG_FN (temp1);
SET_PARAM0(temp1);
/* runtime.sim.cycles += 2; */
}
INSTRUCTION (l_sra) {
orreg_t temp1;
temp1 = (orreg_t)PARAM1 >> PARAM2;
SET_OV_FLAG_FN (temp1);
SET_PARAM0(temp1);
/* runtime.sim.cycles += 2; */
}
INSTRUCTION (l_srl) {
uorreg_t temp1;
temp1 = PARAM1 >> PARAM2;
SET_OV_FLAG_FN (temp1);
SET_PARAM0(temp1);
/* runtime.sim.cycles += 2; */
}
INSTRUCTION (l_bf) {
if (config.bpb.enabled) {
int fwd = (PARAM0 >= cpu_state.pc) ? 1 : 0;
or1k_mstats.bf[cpu_state.sprs[SPR_SR] & SPR_SR_F ? 1 : 0][fwd]++;
bpb_update(current->insn_addr, cpu_state.sprs[SPR_SR] & SPR_SR_F ? 1 : 0);
}
if(cpu_state.sprs[SPR_SR] & SPR_SR_F) {
cpu_state.pc_delay = cpu_state.pc + (orreg_t)PARAM0 * 4;
btic_update(pcnext);
next_delay_insn = 1;
} else {
btic_update(cpu_state.pc);
}
}
INSTRUCTION (l_bnf) {
if (config.bpb.enabled) {
int fwd = (PARAM0 >= cpu_state.pc) ? 1 : 0;
or1k_mstats.bnf[cpu_state.sprs[SPR_SR] & SPR_SR_F ? 0 : 1][fwd]++;
bpb_update(current->insn_addr, cpu_state.sprs[SPR_SR] & SPR_SR_F ? 0 : 1);
}
if (!(cpu_state.sprs[SPR_SR] & SPR_SR_F)) {
cpu_state.pc_delay = cpu_state.pc + (orreg_t)PARAM0 * 4;
btic_update(pcnext);
next_delay_insn = 1;
} else {
btic_update(cpu_state.pc);
}
}
INSTRUCTION (l_j) {
cpu_state.pc_delay = cpu_state.pc + (orreg_t)PARAM0 * 4;
next_delay_insn = 1;
}
INSTRUCTION (l_jal) {
cpu_state.pc_delay = cpu_state.pc + (orreg_t)PARAM0 * 4;
setsim_reg(LINK_REGNO, cpu_state.pc + 8);
next_delay_insn = 1;
if (config.sim.profile) {
struct label_entry *tmp;
if (verify_memoryarea(cpu_state.pc_delay) && (tmp = get_label (cpu_state.pc_delay)))
fprintf (runtime.sim.fprof, "+%08llX %"PRIxADDR" %"PRIxADDR" %s\n",
runtime.sim.cycles, cpu_state.pc + 8, cpu_state.pc_delay,
tmp->name);
else
fprintf (runtime.sim.fprof, "+%08llX %"PRIxADDR" %"PRIxADDR" @%"PRIxADDR"\n",
runtime.sim.cycles, cpu_state.pc + 8, cpu_state.pc_delay,
cpu_state.pc_delay);
}
}
INSTRUCTION (l_jalr) {
cpu_state.pc_delay = PARAM0;
setsim_reg(LINK_REGNO, cpu_state.pc + 8);
next_delay_insn = 1;
}
INSTRUCTION (l_jr) {
cpu_state.pc_delay = PARAM0;
next_delay_insn = 1;
if (config.sim.profile)
fprintf (runtime.sim.fprof, "-%08llX %"PRIxADDR"\n", runtime.sim.cycles,
cpu_state.pc_delay);
}
INSTRUCTION (l_rfe) {
pcnext = cpu_state.sprs[SPR_EPCR_BASE];
mtspr(SPR_SR, cpu_state.sprs[SPR_ESR_BASE]);
}
INSTRUCTION (l_nop) {
oraddr_t stackaddr;
uint32_t k = PARAM0;
switch (k) {
case NOP_NOP:
break;
case NOP_EXIT:
PRINTF("exit(%"PRIdREG")\n", evalsim_reg (3));
fprintf(stderr, "@reset : cycles %lld, insn #%lld\n",
runtime.sim.reset_cycles, runtime.cpu.reset_instructions);
fprintf(stderr, "@exit : cycles %lld, insn #%lld\n", runtime.sim.cycles,
runtime.cpu.instructions);
fprintf(stderr, " diff : cycles %lld, insn #%lld\n",
runtime.sim.cycles - runtime.sim.reset_cycles,
runtime.cpu.instructions - runtime.cpu.reset_instructions);
if (config.debug.gdb_enabled)
set_stall_state (1);
else
sim_done();
break;
case NOP_CNT_RESET:
PRINTF("****************** counters reset ******************\n");
PRINTF("cycles %lld, insn #%lld\n", runtime.sim.cycles, runtime.cpu.instructions);
PRINTF("****************** counters reset ******************\n");
runtime.sim.reset_cycles = runtime.sim.cycles;
runtime.cpu.reset_instructions = runtime.cpu.instructions;
break;
case NOP_PRINTF:
stackaddr = evalsim_reg(4);
simprintf(stackaddr, evalsim_reg(3));
break;
case NOP_PUTC: /*JPB */
printf( "%c", evalsim_reg( 3 ));
fflush( stdout );
break;
case NOP_REPORT:
PRINTF("report(0x%"PRIxREG");\n", evalsim_reg(3));
default:
if (k >= NOP_REPORT_FIRST && k <= NOP_REPORT_LAST)
PRINTF("report %i (0x%"PRIxREG");\n", k - NOP_REPORT_FIRST,
evalsim_reg(3));
break;
}
}
INSTRUCTION (l_sfeq) {
if(PARAM0 == PARAM1)
cpu_state.sprs[SPR_SR] |= SPR_SR_F;
else
cpu_state.sprs[SPR_SR] &= ~SPR_SR_F;
}
INSTRUCTION (l_sfne) {
if(PARAM0 != PARAM1)
cpu_state.sprs[SPR_SR] |= SPR_SR_F;
else
cpu_state.sprs[SPR_SR] &= ~SPR_SR_F;
}
INSTRUCTION (l_sfgts) {
if((orreg_t)PARAM0 > (orreg_t)PARAM1)
cpu_state.sprs[SPR_SR] |= SPR_SR_F;
else
cpu_state.sprs[SPR_SR] &= ~SPR_SR_F;
}
INSTRUCTION (l_sfges) {
if((orreg_t)PARAM0 >= (orreg_t)PARAM1)
cpu_state.sprs[SPR_SR] |= SPR_SR_F;
else
cpu_state.sprs[SPR_SR] &= ~SPR_SR_F;
}
INSTRUCTION (l_sflts) {
if((orreg_t)PARAM0 < (orreg_t)PARAM1)
cpu_state.sprs[SPR_SR] |= SPR_SR_F;
else
cpu_state.sprs[SPR_SR] &= ~SPR_SR_F;
}
INSTRUCTION (l_sfles) {
if((orreg_t)PARAM0 <= (orreg_t)PARAM1)
cpu_state.sprs[SPR_SR] |= SPR_SR_F;
else
cpu_state.sprs[SPR_SR] &= ~SPR_SR_F;
}
INSTRUCTION (l_sfgtu) {
if(PARAM0 > PARAM1)
cpu_state.sprs[SPR_SR] |= SPR_SR_F;
else
cpu_state.sprs[SPR_SR] &= ~SPR_SR_F;
}
INSTRUCTION (l_sfgeu) {
if(PARAM0 >= PARAM1)
cpu_state.sprs[SPR_SR] |= SPR_SR_F;
else
cpu_state.sprs[SPR_SR] &= ~SPR_SR_F;
}
INSTRUCTION (l_sfltu) {
if(PARAM0 < PARAM1)
cpu_state.sprs[SPR_SR] |= SPR_SR_F;
else
cpu_state.sprs[SPR_SR] &= ~SPR_SR_F;
}
INSTRUCTION (l_sfleu) {
if(PARAM0 <= PARAM1)
cpu_state.sprs[SPR_SR] |= SPR_SR_F;
else
cpu_state.sprs[SPR_SR] &= ~SPR_SR_F;
}
INSTRUCTION (l_extbs) {
int8_t x;
x = PARAM1;
SET_PARAM0((orreg_t)x);
}
INSTRUCTION (l_extbz) {
uint8_t x;
x = PARAM1;
SET_PARAM0((uorreg_t)x);
}
INSTRUCTION (l_exths) {
int16_t x;
x = PARAM1;
SET_PARAM0((orreg_t)x);
}
INSTRUCTION (l_exthz) {
uint16_t x;
x = PARAM1;
SET_PARAM0((uorreg_t)x);
}
INSTRUCTION (l_extws) {
int32_t x;
x = PARAM1;
SET_PARAM0((orreg_t)x);
}
INSTRUCTION (l_extwz) {
uint32_t x;
x = PARAM1;
SET_PARAM0((uorreg_t)x);
}
INSTRUCTION (l_mtspr) {
uint16_t regno = PARAM0 + PARAM2;
uorreg_t value = PARAM1;
 
if (cpu_state.sprs[SPR_SR] & SPR_SR_SM)
mtspr(regno, value);
else {
PRINTF("WARNING: trying to write SPR while SR[SUPV] is cleared.\n");
sim_done();
}
}
INSTRUCTION (l_mfspr) {
uint16_t regno = PARAM1 + PARAM2;
uorreg_t value = mfspr(regno);
 
if (cpu_state.sprs[SPR_SR] & SPR_SR_SM)
SET_PARAM0(value);
else {
SET_PARAM0(0);
PRINTF("WARNING: trying to read SPR while SR[SUPV] is cleared.\n");
sim_done();
}
}
INSTRUCTION (l_sys) {
except_handle(EXCEPT_SYSCALL, cpu_state.sprs[SPR_EEAR_BASE]);
}
INSTRUCTION (l_trap) {
/* TODO: some SR related code here! */
except_handle(EXCEPT_TRAP, cpu_state.sprs[SPR_EEAR_BASE]);
}
INSTRUCTION (l_mac) {
uorreg_t lo, hi;
LONGEST l;
orreg_t x, y;
 
lo = cpu_state.sprs[SPR_MACLO];
hi = cpu_state.sprs[SPR_MACHI];
x = PARAM0;
y = PARAM1;
PRINTF ("[%"PRIxREG",%"PRIxREG"]\t", x, y);
l = (ULONGEST)lo | ((LONGEST)hi << 32);
l += (LONGEST) x * (LONGEST) y;
 
/* This implementation is very fast - it needs only one cycle for mac. */
lo = ((ULONGEST)l) & 0xFFFFFFFF;
hi = ((LONGEST)l) >> 32;
cpu_state.sprs[SPR_MACLO] = lo;
cpu_state.sprs[SPR_MACHI] = hi;
PRINTF ("(%"PRIxREG",%"PRIxREG"\n", hi, lo);
}
INSTRUCTION (l_msb) {
uorreg_t lo, hi;
LONGEST l;
orreg_t x, y;
 
lo = cpu_state.sprs[SPR_MACLO];
hi = cpu_state.sprs[SPR_MACHI];
x = PARAM0;
y = PARAM1;
 
PRINTF ("[%"PRIxREG",%"PRIxREG"]\t", x, y);
 
l = (ULONGEST)lo | ((LONGEST)hi << 32);
l -= x * y;
 
/* This implementation is very fast - it needs only one cycle for msb. */
lo = ((ULONGEST)l) & 0xFFFFFFFF;
hi = ((LONGEST)l) >> 32;
cpu_state.sprs[SPR_MACLO] = lo;
cpu_state.sprs[SPR_MACHI] = hi;
PRINTF ("(%"PRIxREG",%"PRIxREG")\n", hi, lo);
}
INSTRUCTION (l_macrc) {
uorreg_t lo, hi;
LONGEST l;
/* No need for synchronization here -- all MAC instructions are 1 cycle long. */
lo = cpu_state.sprs[SPR_MACLO];
hi = cpu_state.sprs[SPR_MACHI];
l = (ULONGEST) lo | ((LONGEST)hi << 32);
l >>= 28;
//PRINTF ("<%08x>\n", (unsigned long)l);
SET_PARAM0((orreg_t)l);
cpu_state.sprs[SPR_MACLO] = 0;
cpu_state.sprs[SPR_MACHI] = 0;
}
INSTRUCTION (l_cmov) {
SET_PARAM0(cpu_state.sprs[SPR_SR] & SPR_SR_F ? PARAM1 : PARAM2);
}
INSTRUCTION (l_ff1) {
SET_PARAM0(ffs(PARAM1));
}
/******* Floating point instructions *******/
/* Single precision */
INSTRUCTION (lf_add_s) {
SET_PARAM0((float)PARAM1 + (float)PARAM2);
}
INSTRUCTION (lf_div_s) {
SET_PARAM0((float)PARAM1 / (float)PARAM2);
}
INSTRUCTION (lf_ftoi_s) {
// set_operand32(0, freg[get_operand(1)], &breakpoint);
}
INSTRUCTION (lf_itof_s) {
// freg[get_operand(0)] = eval_operand32(1, &breakpoint);
}
INSTRUCTION (lf_madd_s) {
SET_PARAM0((float)PARAM0 + (float)PARAM1 * (float)PARAM2);
}
INSTRUCTION (lf_mul_s) {
SET_PARAM0((float)PARAM1 * (float)PARAM2);
}
INSTRUCTION (lf_rem_s) {
float temp = (float)PARAM1 / (float)PARAM2;
SET_PARAM0(temp - (uint32_t)temp);
}
INSTRUCTION (lf_sfeq_s) {
if((float)PARAM0 == (float)PARAM1)
cpu_state.sprs[SPR_SR] |= SPR_SR_F;
else
cpu_state.sprs[SPR_SR] &= ~SPR_SR_F;
}
INSTRUCTION (lf_sfge_s) {
if((float)PARAM0 >= (float)PARAM1)
cpu_state.sprs[SPR_SR] |= SPR_SR_F;
else
cpu_state.sprs[SPR_SR] &= ~SPR_SR_F;
}
INSTRUCTION (lf_sfgt_s) {
if((float)PARAM0 > (float)PARAM1)
cpu_state.sprs[SPR_SR] |= SPR_SR_F;
else
cpu_state.sprs[SPR_SR] &= ~SPR_SR_F;
}
INSTRUCTION (lf_sfle_s) {
if((float)PARAM0 <= (float)PARAM1)
cpu_state.sprs[SPR_SR] |= SPR_SR_F;
else
cpu_state.sprs[SPR_SR] &= ~SPR_SR_F;
}
INSTRUCTION (lf_sflt_s) {
if((float)PARAM0 < (float)PARAM1)
cpu_state.sprs[SPR_SR] |= SPR_SR_F;
else
cpu_state.sprs[SPR_SR] &= ~SPR_SR_F;
}
INSTRUCTION (lf_sfne_s) {
if((float)PARAM0 != (float)PARAM1)
cpu_state.sprs[SPR_SR] |= SPR_SR_F;
else
cpu_state.sprs[SPR_SR] &= ~SPR_SR_F;
}
INSTRUCTION (lf_sub_s) {
SET_PARAM0((float)PARAM1 - (float)PARAM2);
}
 
/******* Custom instructions *******/
INSTRUCTION (l_cust1) {
/*int destr = current->insn >> 21;
int src1r = current->insn >> 15;
int src2r = current->insn >> 9;*/
}
INSTRUCTION (l_cust2) {
}
INSTRUCTION (l_cust3) {
}
INSTRUCTION (l_cust4) {
}
insnset.c Property changes : Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: op-3t-op.h =================================================================== --- op-3t-op.h (nonexistent) +++ op-3t-op.h (revision 1765) @@ -0,0 +1,25 @@ +/* op-3t-op.h -- Micro operations useing three temporaries + Copyright (C) 2005 György `nog' Jeney, nog@sdf.lonestar.org + +This file is part of OpenRISC 1000 Architectural Simulator. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + + +__or_dynop void glue(op_cmov, T)(void) +{ + T0 = env->sprs[SPR_SR] & SPR_SR_F ? T1 : T2; +} + Index: op-extend-op.h =================================================================== --- op-extend-op.h (nonexistent) +++ op-extend-op.h (revision 1765) @@ -0,0 +1,27 @@ +/* op-extend-op.h -- Micro operations template for sign extention operations + Copyright (C) 2005 György `nog' Jeney, nog@sdf.lonestar.org + +This file is part of OpenRISC 1000 Architectural Simulator. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + + +void glue(glue(op_, EXT_NAME), T)(void) +{ + register EXT_TYPE x; + x = T1; + T0 = EXT_CAST x; +} + Index: common-i386.h =================================================================== --- common-i386.h (nonexistent) +++ common-i386.h (revision 1765) @@ -0,0 +1,63 @@ +/* common-i386.h -- Assembler routines used in rec_i386.h and op_i386.h + Copyright (C) 2005 György `nog' Jeney, nog@sdf.lonestar.org + +This file is part of OpenRISC 1000 Architectural Simulator. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + + +/* This is needed because we can't move an mmx register to a general purpose + * register. */ +static union { + struct { + uint32_t low32; + uint32_t high32; + } val3232; + uint64_t val64; +} useless_x86; + +/* Sets the PC with a specified value */ +static void set_pc(oraddr_t pc) +{ + /* I could just use pc as a memory argument, but if I do that then gcc may put + * the value of pc onto the stack, in which case gcc would also shift the + * stack twice, which would result in two add 4, %esp instructions and a + * mov %eax, *%esp, which would not only be slow but it would take up more + * space. */ + asm("movq %%mm0, %0\n" + "\tmovl %2, %1\n" + "\tmovq %3, %%mm0" + : "=m" (useless_x86.val64), + "=m" (useless_x86.val3232.high32) + : "r" (pc), + "m" (useless_x86.val64)); +} + +/* Returns the current value of the pc */ +static oraddr_t get_pc(void) +{ + asm("movq %%mm0, %0" : "=m" (useless_x86.val64)); + return useless_x86.val3232.high32; +} + +/* Updates the runtime.sim.cycles counter */ +static void upd_sim_cycles(void) +{ + asm volatile ("movq %%mm0, %0\n" : "=m" (useless_x86.val64)); + runtime.sim.cycles += scheduler.job_queue->time - useless_x86.val3232.low32; + scheduler.job_queue->time = useless_x86.val3232.low32; + cpu_state.pc = useless_x86.val3232.high32; +} + Index: Makefile.am =================================================================== --- Makefile.am (nonexistent) +++ Makefile.am (revision 1765) @@ -0,0 +1,201 @@ +# Makefile -- Makefile for OR32 dependent simulation +# +# Copyright (C) 1999 Damjan Lampret, lampret@opencores.org +# Copyright (C) 2008 Embecosm Limited +# +# Contributor Jeremy Bennett +# +# This file is part of OpenRISC 1000 Architectural Simulator. +# +# 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 3 of the License, or (at your option) +# any later version. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +# more details. +# +# You should have received a copy of the GNU General Public License along +# with this program. If not, see . + + +if DYNAMIC_EXECUTION + +noinst_LTLIBRARIES = libarch.la libop.la + +noinst_PROGRAMS = dyngen + +dyngen_SOURCES = dyngen.c \ + dyngen-i386.c \ + dyngen-elf.c \ + common-i386.h \ + dyn32-defs.h \ + dyngen.h \ + dyn-rec.h \ + i386-regs.h \ + op-arith-op.h \ + op-comp-op.h \ + op-extend-op.h \ + op-ff1-op.h \ + op-i386.h \ + op-lwhb-op.h \ + op-mac-op.h \ + op-mftspr-op.h \ + op-support.h \ + op-swhb-op.h \ + op-t-reg-mov-op.h \ + rec-i386.h \ + sched-i386.h \ + simpl32-defs.h +dyngen_CFLAGS = $(AM_CFLAGS) + +libarch_la_SOURCES = execute.c \ + or32.c \ + op.c \ + dyn-rec.c \ + op-support.c \ + common-i386.h \ + dyn32-defs.h \ + dyngen.h \ + dyn-rec.h \ + i386-regs.h \ + op-arith-op.h \ + op-comp-op.h \ + op-extend-op.h \ + op-ff1-op.h \ + op-i386.h \ + op-lwhb-op.h \ + op-mac-op.h \ + op-mftspr-op.h \ + op-support.h \ + op-swhb-op.h \ + op-t-reg-mov-op.h \ + rec-i386.h \ + sched-i386.h \ + simpl32-defs.h + +nodist_libarch_la_SOURCES = gen-ops.h \ + gen-ops.c \ + gen-ops-gen.c \ + gen-ops-rel.c + +BUILT_SOURCES = gen-ops.h \ + gen-ops.c \ + gen-ops-gen.c \ + gen-ops-rel.c + +libop_la_SOURCES = op.c \ + op-t-reg-mov-op.h \ + op-i386.h op-arith-op.h \ + op-comp-op.h \ + op-extend-op.h \ + op-mac-op.h \ + op-mftspr-op.h \ + op-lwhb-op.h \ + op-swhb-op.h + +libop_la_CFLAGS = -Wall -fomit-frame-pointer -fno-reorder-blocks -O2 + +gen-ops.h gen-ops.c gen-ops-gen.c gen-ops-rel.c: dyngen$(EXEEXT) op.lo + ./dyngen$(EXEEXT) op.lo gen-ops.c gen-ops-gen.c gen-ops-rel.c gen-ops.h + +else + +noinst_LTLIBRARIES = libarch.la + +if GENERATE_NEEDED + +EXTRA_DIST = insnset.c + +libarch_la_SOURCES = execute.c \ + or32.c \ + common-i386.h \ + dyn32-defs.h \ + dyngen.h \ + dyn-rec.h \ + i386-regs.h \ + op-arith-op.h \ + op-comp-op.h \ + op-extend-op.h \ + op-ff1-op.h \ + op-i386.h \ + op-lwhb-op.h \ + op-mac-op.h \ + op-mftspr-op.h \ + op-support.h \ + op-swhb-op.h \ + op-t-reg-mov-op.h \ + rec-i386.h \ + sched-i386.h \ + simpl32-defs.h + +BUILT_SOURCES = execgen.c + +noinst_PROGRAMS = generate$(EXEEXT) + +generate_SOURCES = or32.c \ + generate.c \ + common-i386.h \ + dyn32-defs.h \ + dyngen.h \ + dyn-rec.h \ + i386-regs.h \ + op-arith-op.h \ + op-comp-op.h \ + op-extend-op.h \ + op-ff1-op.h \ + op-i386.h \ + op-lwhb-op.h \ + op-mac-op.h \ + op-mftspr-op.h \ + op-support.h \ + op-swhb-op.h \ + op-t-reg-mov-op.h \ + rec-i386.h \ + sched-i386.h \ + simpl32-defs.h + +generate_CFLAGS = $(AM_CFLAGS) + +execgen.c: generate$(EXEEXT) insnset.c + ./generate$(EXEEXT) $(srcdir)/insnset.c execgen.c + +else + +libarch_la_SOURCES = execute.c \ + insnset.c \ + or32.c \ + common-i386.h \ + dyn32-defs.h \ + dyngen.h \ + dyn-rec.h \ + i386-regs.h \ + op-arith-op.h \ + op-comp-op.h \ + op-extend-op.h \ + op-ff1-op.h \ + op-i386.h \ + op-lwhb-op.h \ + op-mac-op.h \ + op-mftspr-op.h \ + op-support.h \ + op-swhb-op.h \ + op-t-reg-mov-op.h \ + rec-i386.h \ + sched-i386.h \ + simpl32-defs.h + +endif +endif + +# If the simulator was first built without --enable-simple and then with it, +# then also remove these two files + +CLEANFILES = execgen.c \ + generate \ + gen-ops.c \ + gen-ops.h \ + gen-ops-rel.c \ + gen-ops-gen.c Index: dyngen-elf.c =================================================================== --- dyngen-elf.c (nonexistent) +++ dyngen-elf.c (revision 1765) @@ -0,0 +1,359 @@ +/* dyngen-elf.c -- Elf parser for dyngen + Copyright (C) 2005 György `nog' Jeney, nog@sdf.lonestar.org + +This file is part of OpenRISC 1000 Architectural Simulator. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + + +#include +#include +#include +#include + +#include + +#include "dyngen.h" + +struct elf_obj { + Elf32_Ehdr e_hdr; + Elf32_Shdr *e_shdrs; + void **e_sections; + Elf32_Sym *e_syms; /* The symbol table in the elf file */ + unsigned int e_sym_num; /* The number of symbols */ + unsigned int e_sym_str_tab; /* The string-table associated with symbols */ + Elf32_Rel *e_rels; + unsigned int e_rel_num; /* The number of relocations (in e_rel) */ + unsigned int e_rel_sym; + unsigned int e_rel_sec; /* The section to modify */ + Elf32_Rela *e_relas; + unsigned int e_rela_num; /* The number of relocations (in e_rela) */ + unsigned int e_rela_sym; + unsigned int e_rela_sec; /* The section to modify */ +}; + +void *elf_open_obj(const char *file) +{ + struct elf_obj *obj; + FILE *f; + int i; + + if(!(obj = malloc(sizeof(struct elf_obj)))) { + fprintf(stderr, "OOM\n"); + return NULL; + } + + if(!(f = fopen(file, "r"))) { + free(obj); + return NULL; + } + + fread(&obj->e_hdr, sizeof(Elf32_Ehdr), 1, f); + + /* Do some sanity checks */ + if((obj->e_hdr.e_ident[EI_MAG0] != ELFMAG0) || + (obj->e_hdr.e_ident[EI_MAG1] != ELFMAG1) || + (obj->e_hdr.e_ident[EI_MAG2] != ELFMAG2) || + (obj->e_hdr.e_ident[EI_MAG3] != ELFMAG3)) { + fprintf(stderr, "%s is not an elf file!\n", file); + goto error_load; + } + + if(obj->e_hdr.e_ident[EI_CLASS] == ELFCLASSNONE) { + fprintf(stderr, "Invalid class in ELF header\n"); + goto error_load; + } + + if(obj->e_hdr.e_ident[EI_DATA] == ELFDATANONE) { + fprintf(stderr, "Invalid data format in ELF header\n"); + goto error_load; + } + + /* FIXME: Swap data as necessary */ + + if((obj->e_hdr.e_ident[EI_VERSION] != 1) || + (obj->e_hdr.e_version != 1)) { + fprintf(stderr, "Unexpected elf version found: %i (%li)\n", + obj->e_hdr.e_ident[EI_VERSION], obj->e_hdr.e_version); + goto error_load; + } + + if(obj->e_hdr.e_type != ET_REL) { + fprintf(stderr, "Appears that we did not receive a object file\n"); + goto error_load; + } + + if(obj->e_hdr.e_phoff) { + fprintf(stderr, "What am I supposed to do with a program header??\n"); + goto error_load; + } + + if(obj->e_hdr.e_ehsize != sizeof(Elf32_Ehdr)) { + fprintf(stderr, "Unknown size of elf header\n"); + goto error_load; + } + + if(!obj->e_hdr.e_shoff || !obj->e_hdr.e_shnum) { + fprintf(stderr, "The elf file contains no sections!\n"); + goto error_load; + } + + if(obj->e_hdr.e_shentsize != sizeof(Elf32_Shdr)) { + fprintf(stderr, "Unknown section header size %i\n", obj->e_hdr.e_shentsize); + goto error_load; + } + + /* Load the section headers */ + if(!(obj->e_shdrs = malloc(obj->e_hdr.e_shentsize * obj->e_hdr.e_shnum))){ + fprintf(stderr, "OOM\n"); + goto error_load; + } + + fseek(f, obj->e_hdr.e_shoff, SEEK_SET); + fread(obj->e_shdrs, obj->e_hdr.e_shentsize, obj->e_hdr.e_shnum, f); + + /* FIXME: swap data */ + + /* Load the sections */ + if(!(obj->e_sections = calloc(obj->e_hdr.e_shnum, sizeof(void *)))) { + fprintf(stderr, "OOM\n"); + free(obj->e_shdrs); + goto error_load; + } + + for(i = 0; i < obj->e_hdr.e_shnum; i++) { + if(obj->e_shdrs[i].sh_type == SHT_NOBITS) + continue; + if(!(obj->e_sections[i] = malloc(obj->e_shdrs[i].sh_size))) { + fprintf(stderr, "OOM\n"); + goto post_sec_error_load; + } + fseek(f, obj->e_shdrs[i].sh_offset, SEEK_SET); + fread(obj->e_sections[i], obj->e_shdrs[i].sh_size, 1, f); + } + + obj->e_rels = NULL; + obj->e_syms = NULL; + obj->e_relas = NULL; + + /* Find the symbol table and relocation table(s) */ + for(i = 0; i < obj->e_hdr.e_shnum; i++) { + switch(obj->e_shdrs[i].sh_type) { + case SHT_SYMTAB: + if(obj->e_syms) { + fprintf(stderr, "ELF file has more than one symbol table\n"); + goto post_sec_error_load; + } + if(obj->e_shdrs[i].sh_entsize != sizeof(Elf32_Sym)) { + fprintf(stderr, "ELF symbol table entry size is unknown\n"); + goto post_sec_error_load; + } + if((obj->e_shdrs[i].sh_size % obj->e_shdrs[i].sh_entsize)) { + fprintf(stderr, "Symbol table's length is not a multiple of sizeof(Elf32_Sym\n"); + goto post_sec_error_load; + } + obj->e_syms = obj->e_sections[i]; + obj->e_sym_num = obj->e_shdrs[i].sh_size / obj->e_shdrs[i].sh_entsize; + obj->e_sym_str_tab = obj->e_shdrs[i].sh_link; + break; + case SHT_REL: + if(obj->e_rels) { + fprintf(stderr, "ELF file has more than one relocation table\n"); + goto post_sec_error_load; + } + if(obj->e_shdrs[i].sh_entsize != sizeof(Elf32_Rel)) { + fprintf(stderr, "ELF relocation table entry size is unknown\n"); + goto post_sec_error_load; + } + if((obj->e_shdrs[i].sh_size % obj->e_shdrs[i].sh_entsize)) { + fprintf(stderr, "Relocation table's length is not a multiple of sizeof(Elf32_Rel\n"); + goto post_sec_error_load; + } + obj->e_rels = obj->e_sections[i]; + obj->e_rel_sec = obj->e_shdrs[i].sh_info; + obj->e_rel_sym = obj->e_shdrs[i].sh_link; + obj->e_rel_num = obj->e_shdrs[i].sh_size / obj->e_shdrs[i].sh_entsize; + break; + case SHT_RELA: + if(obj->e_relas) { + fprintf(stderr, "ELF file has more than one a-relocation table\n"); + goto post_sec_error_load; + } + if(obj->e_shdrs[i].sh_entsize != sizeof(Elf32_Rela)) { + fprintf(stderr, "ELF a-relocation table entry size is unknown\n"); + goto post_sec_error_load; + } + if((obj->e_shdrs[i].sh_size % obj->e_shdrs[i].sh_entsize)) { + fprintf(stderr, "Relocation table's length is not a multiple of sizeof(Elf32_Rela)\n"); + goto post_sec_error_load; + } + obj->e_relas = obj->e_sections[i]; + obj->e_rela_sec = obj->e_shdrs[i].sh_info; + obj->e_rela_sym = obj->e_shdrs[i].sh_link; + obj->e_rela_num = obj->e_shdrs[i].sh_size / obj->e_shdrs[i].sh_entsize; + break; + } + } + + fclose(f); + return obj; + +post_sec_error_load: + for(i = 0; i < obj->e_hdr.e_shnum; i++) { + if(obj->e_sections[i]) + free(obj->e_sections[i]); + } + free(obj->e_sections); + free(obj->e_shdrs); +error_load: + free(obj); + fclose(f); + return NULL; +} + +void elf_close_obj(void *e_obj) +{ + struct elf_obj *obj = e_obj; + int i; + + for(i = 0; i < obj->e_hdr.e_shnum; i++) { + if(obj->e_sections[i]) + free(obj->e_sections[i]); + } + free(obj->e_sections); + free(obj->e_shdrs); + free(obj); +} + +static Elf32_Sym *elf_find_func(struct elf_obj *obj, unsigned int func) +{ + int i, j; + Elf32_Sym *cur; + + for(i = 0, j = 0, cur = obj->e_syms; i < obj->e_sym_num; i++, cur++) { + if(ELF32_ST_BIND(cur->st_info) != STB_GLOBAL) + continue; + if(ELF32_ST_TYPE(cur->st_info) != STT_FUNC) + continue; + if(j == func) + return cur; + j++; + } + return NULL; +} + +char *elf_get_func_name(void *e_obj, unsigned int func) +{ + struct elf_obj *obj = e_obj; + Elf32_Sym *func_sym = elf_find_func(obj, func); + + if(func_sym) + return obj->e_sections[obj->e_sym_str_tab] + func_sym->st_name; + + return NULL; +} + +unsigned int elf_get_func_len(void *e_obj, unsigned int func) +{ + struct elf_obj *obj = e_obj; + Elf32_Sym *func_sym = elf_find_func(obj, func); + + if(func_sym) + return func_sym->st_size; + return 0; +} + +void *elf_get_func_start(void *e_obj, unsigned int func) +{ + struct elf_obj *obj = e_obj; + Elf32_Sym *func_sym = elf_find_func(obj, func); + + if(!func_sym) + return NULL; + + if(func_sym->st_shndx == SHN_COMMON) { + fprintf(stderr, "Don't know how to handle SHN_COMMON section header\n"); + return NULL; + } + + return obj->e_sections[func_sym->st_shndx] + func_sym->st_value; +} + +static char *elf_get_sym_name(struct elf_obj *obj, unsigned int sym) +{ + char *name; + + name = obj->e_sections[obj->e_sym_str_tab]; + name += obj->e_syms[sym].st_name; + + return name; +} + +int elf_get_func_reloc(void *e_obj, unsigned int func, unsigned int relocn, + struct reloc *reloc) +{ + struct elf_obj *obj = e_obj; + Elf32_Sym *func_sym = elf_find_func(obj, func); + Elf32_Rel *cur; + Elf32_Rela *cura; + int i, j; + +/* + if(obj->e_rel_sec != func_sym->st_shndx) { + fprintf(stderr, "Don't know what to do: Function does not have a relocation table\n"); + return 0; + } +*/ + + for(i = 0, j = 0, cur = obj->e_rels; i < obj->e_rel_num; i++, cur++) { + if((cur->r_offset - func_sym->st_value) > func_sym->st_size) + continue; + if(relocn == j) { + reloc->name = elf_get_sym_name(obj, ELF32_R_SYM(cur->r_info)); + reloc->func_offset = cur->r_offset - func_sym->st_value; + reloc->type = ELF32_R_TYPE(cur->r_info); + /* FIXME: Byte-swap */ + reloc->addend = *(uint32_t *)(obj->e_sections[obj->e_rel_sec] + cur->r_offset); + return 1; + } + j++; + } + + if(!obj->e_relas) + return 0; + + for(i = 0, cura = obj->e_relas; i < obj->e_rela_num; i++, cura++) { + if((cura->r_offset - func_sym->st_value) > func_sym->st_size) + continue; + if(relocn == j) { + reloc->name = elf_get_sym_name(obj, ELF32_R_SYM(cur->r_info)); + reloc->func_offset = cura->r_offset - func_sym->st_value; + reloc->type = ELF32_R_TYPE(cur->r_info); + reloc->addend = cura->r_addend; + return 1; + } + j++; + } + + return 0; +} + +const struct bff bffs = { + elf_open_obj, + elf_close_obj, + elf_get_func_name, + elf_get_func_start, + elf_get_func_len, + elf_get_func_reloc }; Index: generate.c =================================================================== --- generate.c (nonexistent) +++ generate.c (revision 1765) @@ -0,0 +1,412 @@ +/* generate.c -- generates file execgen.c from instruction set + + Copyright (C) 1999 Damjan Lampret, lampret@opencores.org + Copyright (C) 2005 György `nog' Jeney, nog@sdf.lonestar.org + Copyright (C) 2008 Embecosm Limited + + Contributor Jeremy Bennett + + This file is part of Or1ksim, the OpenRISC 1000 Architectural Simulator. + + 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 3 of the License, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + You should have received a copy of the GNU General Public License along + with this program. If not, see . */ + +/* This program is commented throughout in a fashion suitable for processing + with Doxygen. */ + + +/* Autoconf and/or portability configuration */ +#include "config.h" +#include "port.h" + +/* System includes */ +#include +#include +#include + +/* Package includes */ +#include "opcode/or32.h" + +static char *in_file; +static char *out_file; + +/* Whether this instruction stores something in register */ +static int write_to_reg; + +static int out_lines = 0; + +static int shift_fprintf(int level, FILE *f, const char *fmt, ...) +{ + va_list ap; + int i; + + va_start(ap, fmt); + for(i = 0; i < level; i++) + fprintf(f, " "); + + i = vfprintf(f, fmt, ap); + va_end(ap); + + out_lines++; + return i + (level * 2); +} + +/* Generates a execute sequence for one instruction */ +int output_function (FILE *fo, const char *func_name, int level) +{ + FILE *fi; + int olevel; + int line_num = 0; + + if ((fi = fopen (in_file, "rt")) == NULL) { + printf("could not open file\n"); + return 1; + } + + while (!feof (fi)) { + char line[10000], *str = line; + fgets (str, sizeof (line), fi); + line[sizeof (line) - 1] = 0; + line_num++; + if (strncmp (str, "INSTRUCTION (", 13) == 0) { + char *s; + str += 13; + while (isspace (*str)) str++; + s = str; + while (*s && *s != ')') s++; + *s = 0; + while (isspace(*(s - 1))) s--; + *s = 0; + if (strcmp (str, func_name) == 0) { + olevel = 1; + str += strlen (str) + 1; + while (isspace (*str)) str++; + s = str; + while (*s && *s != '\n' && *s != '\r') s++; + *s = 0; + while (isspace(*(s - 1))) s--; + *s = 0; + /*shift_fprintf (level, fo, "#line %i \"%s\"\n", line_num, in_file);*/ + shift_fprintf (level, fo, "%s", str); + shift_fprintf (level, fo, " /* \"%s\" */\n", func_name); + do { + fgets (line, sizeof (line), fi); + line[sizeof(line) - 1] = 0; + for (str = line; *str; str++) { + if (*str == '{') olevel++; + else if (*str == '}') olevel--; + } + shift_fprintf (level, fo, "%s", line); + } while (olevel); + fclose(fi); + /*shift_fprintf (level, fo, "#line %i \"%s\"\n", out_lines, out_file);*/ + return 0; + } + } + } + shift_fprintf (level, fo, "%s ();\n", func_name); + + fclose(fi); + return 0; +} + +/* Parses operands. */ + +static int +gen_eval_operands (FILE *fo, int insn_index, int level) +{ + struct insn_op_struct *opd = op_start[insn_index]; + int i; + int num_ops; + int nbits = 0; + int set_param = 0; + int dis = 0; + int sbit; + int dis_op = -1; + + write_to_reg = 0; + + shift_fprintf (level, fo, "uorreg_t "); + + /* Count number of operands */ + for (i = 0, num_ops = 0;; i++) { + if (!(opd[i].type & OPTYPE_OP)) + continue; + if (opd[i].type & OPTYPE_DIS) + continue; + if (num_ops) + fprintf(fo, ", "); + fprintf(fo, "%c", 'a' + num_ops); + num_ops++; + if (opd[i].type & OPTYPE_LAST) + break; + } + + fprintf (fo, ";\n"); + + shift_fprintf (level, fo, "/* Number of operands: %i */\n", num_ops); + + i = 0; + num_ops = 0; + do { +/* + printf("opd[%i].type = %c\n", i, opd->type & OPTYPE_LAST ? '1' : '0'); printf("opd[%i].type = %c\n", i, opd->type & OPTYPE_OP ? '1' : '0'); + printf("opd[%i].type = %c\n", i, opd->type & OPTYPE_REG ? '1' : '0'); + printf("opd[%i].type = %c\n", i, opd->type & OPTYPE_SIG ? '1' : '0'); + printf("opd[%i].type = %c\n", i, opd->type & OPTYPE_DIS ? '1' : '0'); + printf("opd[%i].type = %i\n", i, opd->type & OPTYPE_SHR); + printf("opd[%i].type = %i\n", i, (opd->type & OPTYPE_SBIT) >> OPTYPE_SBIT_SHR); + printf("opd[%i].data = %i\n", i, opd->data); +*/ + + if (!nbits) + shift_fprintf (level, fo, "%c = (insn >> %i) & 0x%x;\n", 'a' + num_ops, + opd->type & OPTYPE_SHR, (1 << opd->data) - 1); + else + shift_fprintf (level, fo, "%c |= ((insn >> %i) & 0x%x) << %i;\n", + 'a' + num_ops, opd->type & OPTYPE_SHR, + (1 << opd->data) - 1, nbits); + + nbits += opd->data; + + if ((opd->type & OPTYPE_DIS) && (opd->type & OPTYPE_OP)) { + sbit = (opd->type & OPTYPE_SBIT) >> OPTYPE_SBIT_SHR; + if (opd->type & OPTYPE_SIG) + shift_fprintf (level, fo, "if(%c & 0x%08x) %c |= 0x%x;\n", + 'a' + num_ops, 1 << sbit, 'a' + num_ops, + 0xffffffff << sbit); + opd++; + shift_fprintf (level, fo, "*(orreg_t *)&%c += (orreg_t)cpu_state.reg[(insn >> %i) & 0x%x];\n", + 'a' + num_ops, opd->type & OPTYPE_SHR, + (1 << opd->data) - 1); + dis = 1; + dis_op = num_ops; + } + + if (opd->type & OPTYPE_OP) { + sbit = (opd->type & OPTYPE_SBIT) >> OPTYPE_SBIT_SHR; + if (opd->type & OPTYPE_SIG) + shift_fprintf (level, fo, "if(%c & 0x%08x) %c |= 0x%x;\n", + 'a' + num_ops, 1 << sbit, 'a' + num_ops, + 0xffffffff << sbit); + if ((opd->type & OPTYPE_REG) && !dis) { + if(!i) { + shift_fprintf (level, fo, "#define SET_PARAM0(val) cpu_state.reg[a] = val\n"); + set_param = 1; + } + shift_fprintf (level, fo, "#define PARAM%i cpu_state.reg[%c]\n", num_ops, + 'a' + num_ops); + if(opd->type & OPTYPE_DST) + write_to_reg = 1; + } else { + shift_fprintf (level, fo, "#define PARAM%i %c\n", num_ops, + 'a' + num_ops); + } + num_ops++; + nbits = 0; + dis = 0; + } + + if ((opd->type & OPTYPE_LAST)) + break; + opd++; + i++; + } while (1); + + output_function (fo, or32_opcodes[insn_index].function_name, level); + + if (set_param) + shift_fprintf (level, fo, "#undef SET_PARAM\n"); + + for (i = 0; i < num_ops; i++) + shift_fprintf (level, fo, "#undef PARAM%i\n", i); + + return dis_op; +} + +/* Generates decode and execute for one instruction instance */ +static int output_call (FILE *fo, int index, int level) +{ + int dis_op = -1; + + /*printf ("%i:%s\n", index, insn_name (index));*/ + + shift_fprintf (level++, fo, "{\n"); + + if (index >= 0) + dis_op = gen_eval_operands (fo, index, level); + + if (index < 0) output_function (fo, "l_invalid", level); + + fprintf (fo, "\n"); + + shift_fprintf (level++, fo, "if (do_stats) {\n"); + + if (dis_op >= 0) + shift_fprintf (level, fo, "cpu_state.insn_ea = %c;\n", 'a' + dis_op); + + shift_fprintf (level, fo, "current->insn_index = %i; /* \"%s\" */\n", index, + insn_name (index)); + + shift_fprintf (level, fo, "analysis(current);\n"); + shift_fprintf (--level, fo, "}\n"); + + if (write_to_reg) + shift_fprintf (level, fo, "cpu_state.reg[0] = 0; /* Repair in case we changed it */\n"); + shift_fprintf (--level, fo, "}\n"); + return 0; +} + +/* Generates .c file header */ +static int generate_header (FILE *fo) +{ + fprintf (fo, "/* execgen.c -- Automatically generated decoder\n"); + fprintf (fo, "\n"); + fprintf (fo, " Copyright (C) 1999 Damjan Lampret, lampret@opencores.org\n"); + fprintf (fo, " Copyright (C) 2008 Embecosm Limited\n"); + fprintf (fo, "\n"); + fprintf (fo, " Contributor Jeremy Bennett \n"); + fprintf (fo, "\n"); + fprintf (fo, " This file is part of Or1ksim, the OpenRISC 1000 Architectural Simulator.\n"); + fprintf (fo, "\n"); + fprintf (fo, " This program is free software; you can redistribute it and/or modify it\n"); + fprintf (fo, " under the terms of the GNU General Public License as published by the Free\n"); + fprintf (fo, " Software Foundation; either version 3 of the License, or (at your option)\n"); + fprintf (fo, " any later version.\n"); + fprintf (fo, "\n"); + fprintf (fo, " This program is distributed in the hope that it will be useful, but WITHOUT\n"); + fprintf (fo, " ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or\n"); + fprintf (fo, " FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for\n"); + fprintf (fo, " more details.\n"); + fprintf (fo, "\n"); + fprintf (fo, " You should have received a copy of the GNU General Public License along\n"); + fprintf (fo, " with this program. If not, see . */\n"); + fprintf (fo, "\n"); + fprintf (fo, "/* This program is commented throughout in a fashion suitable for processing\n"); + fprintf (fo, " with Doxygen. */\n"); + fprintf (fo, "\n"); + + fprintf (fo, "/* This file was automatically generated by generate (see\n"); + fprintf (fo, " cpu/or32/generate.c) */\n\n"); + fprintf (fo, "static void decode_execute (struct iqueue_entry *current)\n{\n"); + fprintf (fo, " uint32_t insn = current->insn;\n"); + out_lines = 5; + return 0; +} + +/* Generates .c file footer */ +static int generate_footer (FILE *fo) +{ + fprintf (fo, "}\n"); + return 0; +} + +/* Decodes all instructions and generates code for that. This function + is similar to insn_decode, except it decodes all instructions. */ +static int generate_body (FILE *fo, unsigned long *a, unsigned long cur_mask, int level) +{ + unsigned long shift = *a; + unsigned long mask; + int i; + int prev_inv = 0; + + if (!(*a & LEAF_FLAG)) { + shift = *a++; + mask = *a++; + shift_fprintf (level, fo, "switch((insn >> %i) & 0x%x) {\n", shift, + mask); + for (i = 0; i <= mask; i++, a++) { + if (!*a) { + shift_fprintf (level, fo, "case 0x%x:\n", i); + prev_inv = 1; + } else { + if(prev_inv) { + shift_fprintf (++level, fo, "/* Invalid instruction(s) */\n"); + shift_fprintf (level--, fo, "break;\n"); + } + shift_fprintf (level, fo, "case 0x%x:\n", i); + generate_body (fo, automata + *a, cur_mask | (mask << shift), ++level); + shift_fprintf (level--, fo, "break;\n"); + prev_inv = 0; + } + } + if (prev_inv) { + shift_fprintf (++level, fo, "/* Invalid instruction(s) */\n"); + shift_fprintf (level--, fo, "break;\n"); + } + shift_fprintf (level, fo, "}\n"); + } else { + i = *a & ~LEAF_FLAG; + + /* Final check - do we have direct match? + (based on or32_opcodes this should be the only possibility, + but in case of invalid/missing instruction we must perform a check) */ + + if (ti[i].insn_mask != cur_mask) { + shift_fprintf (level, fo, "/* Not unique: real mask %08lx and current mask %08lx differ - do final check */\n", ti[i].insn_mask, cur_mask); + shift_fprintf (level++, fo, "if((insn & 0x%x) == 0x%x) {\n", + ti[i].insn_mask, ti[i].insn); + } + shift_fprintf (level, fo, "/* Instruction: %s */\n", or32_opcodes[i].name); + + output_call (fo, i, level); + + if (ti[i].insn_mask != cur_mask) { + shift_fprintf (--level, fo, "} else {\n"); + shift_fprintf (++level, fo, "/* Invalid insn */\n"); + output_call (fo, -1, level); + shift_fprintf (--level, fo, "}\n"); + } + } + return 0; +} + +/* Main function; it takes two parameters: + input_file(possibly insnset.c) output_file(possibly execgen.c)*/ +int main (int argc, char *argv[]) +{ + FILE *fo; + + if (argc != 3) { + fprintf (stderr, "USAGE: generate input_file(possibly insnset.c) output_file(possibly execgen.c)\n"); + exit (-1); + } + + in_file = argv[1]; + out_file = argv[2]; + if (!(fo = fopen (argv[2], "wt+"))) { + fprintf (stderr, "Cannot create '%s'.\n", argv[2]); + exit (1); + } + + build_automata (); + if (generate_header (fo)) { + fprintf (stderr, "generate_header\n"); + return 1; + } + + if (generate_body (fo, automata, 0, 1)) { + fprintf (stderr, "generate_body\n"); + return 1; + } + + if (generate_footer (fo)) { + fprintf (stderr, "generate_footer\n"); + return 1; + } + + fclose (fo); + destruct_automata (); + return 0; +} +
generate.c Property changes : Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: i386-regs.h =================================================================== --- i386-regs.h (nonexistent) +++ i386-regs.h (revision 1765) @@ -0,0 +1,26 @@ +/* i386_regs.h -- Register definitions for i386 + Copyright (C) 2005 György `nog' Jeney, nog@sdf.lonestar.org + +This file is part of OpenRISC 1000 Architectural Simulator. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + + +#define CPU_STATE_REG "ebp" +#define T0_REG "ebx" +#define T1_REG "esi" +#define T2_REG "edi" + +#define NUM_T_REGS 3 Index: op-mac-op.h =================================================================== --- op-mac-op.h (nonexistent) +++ op-mac-op.h (revision 1765) @@ -0,0 +1,30 @@ +/* op-mac-op.h -- Micro operations template for mac operations + Copyright (C) 2005 György `nog' Jeney, nog@sdf.lonestar.org + +This file is part of OpenRISC 1000 Architectural Simulator. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + + +__or_dynop void glue(glue(op_, OP_NAME), T)(void) +{ + int64_t temp = env->sprs[SPR_MACLO] | ((int64_t)env->sprs[SPR_MACHI] << 32); + + temp OP (int64_t)T0 * (int64_t)T1; + + env->sprs[SPR_MACLO] = temp & 0xffffffff; + env->sprs[SPR_MACHI] = temp >> 32; +} + Index: op.c =================================================================== --- op.c (nonexistent) +++ op.c (revision 1765) @@ -0,0 +1,971 @@ +/* op.c -- Micro operations for the recompiler + Copyright (C) 2005 György `nog' Jeney, nog@sdf.lonestar.org + +This file is part of OpenRISC 1000 Architectural Simulator. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + + +#include +#include +#include + +#include "config.h" + +#ifdef HAVE_INTTYPES_H +#include +#endif + +#include "port.h" +#include "arch.h" +#include "spr_defs.h" +#include "opcode/or32.h" +#include "sim-config.h" +#include "except.h" +#include "abstract.h" +#include "execute.h" +#include "sprs.h" +#include "sched.h" +#include "immu.h" + +#include "op_support.h" + +#include "i386_regs.h" + +#include "dyn_rec.h" + +register struct cpu_state *env asm(CPU_STATE_REG); + +#include "op_i386.h" + +/* + * WARNING: Before going of and wildly editing everything in this file remember + * the following about its contents: + * 1) The `functions' don't EVER return. In otherwords haveing return state- + * ments _anywere_ in this file is likely not to work. This is because + * dyngen just strips away the ret from the end of the function and just uses + * the function `body'. If a ret statement is executed _anyware_ inside the + * dynamicly generated code, then it is undefined were we shall jump to. + * 2) Because of 1), try not to have overly complicated functions. In too + * complicated functions, gcc may decide to generate premature `exits'. This + * is what passing the -fno-reorder-blocks command line switch to gcc helps + * with. This is ofcourse not desired and is rather flaky as we don't (and + * can't) control the kind of code that gcc generates: It may work for one + * and break for another. The less branches there are the less likely it is + * that a premature return shall occur. + * 3) If gcc decides that it is going to be a basterd then it will optimise a + * very simple condition (if/switch) with a premature exit. But gcc can't + * fuck ME over! Just stick a FORCE_RET; at the END of the offending + * function. + * 4) All operations must start with `op_'. dyngen ignores all other functions. + * 5) Local variables are depriciated: They hinder performance. + * 6) Function calls are expensive as the stack has to be shifted (twice). + */ + +/*#define __or_dynop __attribute__((noreturn))*/ +#define __or_dynop + +/* Temporaries to hold the (simulated) registers in */ +register uint32_t t0 asm(T0_REG); +register uint32_t t1 asm(T1_REG); +register uint32_t t2 asm(T2_REG); + +#define OP_PARAM1 ((uorreg_t)(&__op_param1)) +#define OP_PARAM2 ((uorreg_t)(&__op_param2)) +#define OP_PARAM3 ((uorreg_t)(&__op_param3)) + +extern uorreg_t __op_param1; +extern uorreg_t __op_param2; +extern uorreg_t __op_param3; + + +static inline void save_t_bound(oraddr_t pc) +{ + int reg; + + pc = (pc & immu_state->page_offset_mask) / 4; + reg = env->curr_page->ts_bound[pc]; + + if(reg & 0x1f) + env->reg[reg & 0x1f] = t0; + + if((reg >> 5) & 0x1f) + env->reg[(reg >> 5) & 0x1f] = t1; + + if((reg >> 10) & 0x1f) + env->reg[(reg >> 10) & 0x1f] = t2; +} + +void do_sched_wrap(void) +{ + env->pc += 4; + //runtime.cpu.instructions++; + runtime.sim.cycles -= env->cycles_dec; + scheduler.job_queue->time += env->cycles_dec; + if(scheduler.job_queue->time <= 0) { + save_t_bound(env->pc - 4); + do_scheduler(); + } +} + +/* do_scheduler wrapper for instructions that are in the delay slot */ +void do_sched_wrap_delay(void) +{ + /* FIXME: Can't this be eliminated? */ + env->pc += 4; + //runtime.cpu.instructions++; + runtime.sim.cycles -= env->cycles_dec; + scheduler.job_queue->time += env->cycles_dec; + if(scheduler.job_queue->time <= 0) + do_scheduler(); +} + +void enter_dyn_code(oraddr_t addr, struct dyn_page *dp) +{ + uint16_t reg = 0; + uint32_t t0_reg = t0, t1_reg = t1, t2_reg = t2; + struct cpu_state *cpu_reg = env; + + addr &= immu_state->page_offset_mask; + addr >>= 2; + + if(addr) + reg = dp->ts_bound[addr - 1]; + + t0 = cpu_state.reg[reg & 0x1f]; + t1 = cpu_state.reg[(reg >> 5) & 0x1f]; + + /* Don't we all love gcc? For some heavenly reason gcc 3.2 _knows_ that if I + * don't put a condition around the assignment of t2, _all_ the assignments to + * t{0,1,2} are useless and not needed. I'm pleasently happy that gcc is so + * bright, but on the other hand, t{0,1,2} are globals (!) how can you assume + * that the value of a global won't be used in a function further up or + * further down the stack?? */ + if(addr) + t2 = cpu_state.reg[(reg >> 10) & 0x1f]; + + env = &cpu_state; + + ((gen_code_ent *)dp->locs)[addr](); + t0 = t0_reg; + t1 = t1_reg; + t2 = t2_reg; + env = (struct cpu_state *)cpu_reg; +} + +__or_dynop void op_set_pc_pc_delay(void) +{ + env->sprs[SPR_PPC] = env->pc; + /* pc_delay is pulled back 4 since imediatly after this is run, the scheduler + * runs which also increments it by 4 */ + env->pc = env->pc_delay - 4; +} + +__or_dynop void op_set_pc_delay_imm(void) +{ + env->pc_delay = env->pc + (orreg_t)OP_PARAM1; + env->delay_insn = 1; +} + +__or_dynop void op_set_pc_delay_pc(void) +{ + env->pc_delay = env->pc; + env->delay_insn = 1; +} + +__or_dynop void op_clear_pc_delay(void) +{ + env->pc_delay = 0; + env->delay_insn = 1; +} + +__or_dynop void op_do_jump_delay(void) +{ + env->pc = env->pc_delay; +} + +__or_dynop void op_clear_delay_insn(void) +{ + env->delay_insn = 0; +} + +__or_dynop void op_set_delay_insn(void) +{ + env->delay_insn = 1; +} + +__or_dynop void op_check_delay_slot(void) +{ + if(!env->delay_insn) + OP_JUMP(OP_PARAM1); +} + +__or_dynop void op_jmp_imm(void) +{ + OP_JUMP(OP_PARAM1); +} + +__or_dynop void op_set_flag(void) +{ + env->sprs[SPR_SR] |= SPR_SR_F; +} + +__or_dynop void op_clear_flag(void) +{ + env->sprs[SPR_SR] &= ~SPR_SR_F; +} + +/* Used for the l.bf instruction. Therefore if the flag is not set, jump over + * all the jumping stuff */ +__or_dynop void op_check_flag(void) +{ + if(!(env->sprs[SPR_SR] & SPR_SR_F)) { + SPEEDY_CALL(do_sched_wrap); + OP_JUMP(OP_PARAM1); + } +} + +/* Used for l.bf if the delay slot instruction is on another page */ +__or_dynop void op_check_flag_delay(void) +{ + if(env->sprs[SPR_SR] & SPR_SR_F) { + env->delay_insn = 1; + env->pc_delay = env->pc + (orreg_t)OP_PARAM1; + } +} + +/* Used for the l.bnf instruction. Therefore if the flag is set, jump over all + * the jumping stuff */ +__or_dynop void op_check_not_flag(void) +{ + if(env->sprs[SPR_SR] & SPR_SR_F) { + SPEEDY_CALL(do_sched_wrap); + OP_JUMP(OP_PARAM1); + } +} + +/* Used for l.bnf if the delay slot instruction is on another page */ +__or_dynop void op_check_not_flag_delay(void) +{ + if(!(env->sprs[SPR_SR] & SPR_SR_F)) { + env->delay_insn = 1; + env->pc_delay = env->pc + (orreg_t)OP_PARAM1; + } +} + +__or_dynop void op_add_pc(void) +{ + env->pc += OP_PARAM1; +} + +__or_dynop void op_nop_exit(void) +{ + op_support_nop_exit(); + FORCE_RET; +} + +__or_dynop void op_nop_reset(void) +{ + op_support_nop_reset(); + FORCE_RET; +} + +__or_dynop void op_nop_printf(void) +{ + op_support_nop_printf(); + FORCE_RET; +} + +__or_dynop void op_nop_report(void) +{ + op_support_nop_report(); + FORCE_RET; +} + +__or_dynop void op_nop_report_imm(void) +{ + op_support_nop_report_imm(OP_PARAM1); +} + +/* FIXME: Create another 2 sched functions that to the actual analysis call + * instead of bloating the recompiled code with this */ +__or_dynop void op_analysis(void) +{ + SPEEDY_CALL(op_support_analysis); +} + +__or_dynop void op_move_gpr1_pc_delay(void) +{ + env->pc_delay = env->reg[1]; + env->delay_insn = 1; +} + +__or_dynop void op_move_gpr2_pc_delay(void) +{ + env->pc_delay = env->reg[2]; + env->delay_insn = 1; +} + +__or_dynop void op_move_gpr3_pc_delay(void) +{ + env->pc_delay = env->reg[3]; + env->delay_insn = 1; +} + +__or_dynop void op_move_gpr4_pc_delay(void) +{ + env->pc_delay = env->reg[4]; + env->delay_insn = 1; +} + +__or_dynop void op_move_gpr5_pc_delay(void) +{ + env->pc_delay = env->reg[5]; + env->delay_insn = 1; +} + +__or_dynop void op_move_gpr6_pc_delay(void) +{ + env->pc_delay = env->reg[6]; + env->delay_insn = 1; +} + +__or_dynop void op_move_gpr7_pc_delay(void) +{ + env->pc_delay = env->reg[7]; + env->delay_insn = 1; +} + +__or_dynop void op_move_gpr8_pc_delay(void) +{ + env->pc_delay = env->reg[8]; + env->delay_insn = 1; +} + +__or_dynop void op_move_gpr9_pc_delay(void) +{ + env->pc_delay = env->reg[9]; + env->delay_insn = 1; +} + +__or_dynop void op_move_gpr10_pc_delay(void) +{ + env->pc_delay = env->reg[10]; + env->delay_insn = 1; +} + +__or_dynop void op_move_gpr11_pc_delay(void) +{ + env->pc_delay = env->reg[11]; + env->delay_insn = 1; +} + +__or_dynop void op_move_gpr12_pc_delay(void) +{ + env->pc_delay = env->reg[12]; + env->delay_insn = 1; +} + +__or_dynop void op_move_gpr13_pc_delay(void) +{ + env->pc_delay = env->reg[13]; + env->delay_insn = 1; +} + +__or_dynop void op_move_gpr14_pc_delay(void) +{ + env->pc_delay = env->reg[14]; + env->delay_insn = 1; +} + +__or_dynop void op_move_gpr15_pc_delay(void) +{ + env->pc_delay = env->reg[15]; + env->delay_insn = 1; +} + +__or_dynop void op_move_gpr16_pc_delay(void) +{ + env->pc_delay = env->reg[16]; + env->delay_insn = 1; +} + +__or_dynop void op_move_gpr17_pc_delay(void) +{ + env->pc_delay = env->reg[17]; + env->delay_insn = 1; +} + +__or_dynop void op_move_gpr18_pc_delay(void) +{ + env->pc_delay = env->reg[18]; + env->delay_insn = 1; +} + +__or_dynop void op_move_gpr19_pc_delay(void) +{ + env->pc_delay = env->reg[19]; + env->delay_insn = 1; +} + +__or_dynop void op_move_gpr20_pc_delay(void) +{ + env->pc_delay = env->reg[20]; + env->delay_insn = 1; +} + +__or_dynop void op_move_gpr21_pc_delay(void) +{ + env->pc_delay = env->reg[21]; + env->delay_insn = 1; +} + +__or_dynop void op_move_gpr22_pc_delay(void) +{ + env->pc_delay = env->reg[22]; + env->delay_insn = 1; +} + +__or_dynop void op_move_gpr23_pc_delay(void) +{ + env->pc_delay = env->reg[23]; + env->delay_insn = 1; +} + +__or_dynop void op_move_gpr24_pc_delay(void) +{ + env->pc_delay = env->reg[24]; + env->delay_insn = 1; +} + +__or_dynop void op_move_gpr25_pc_delay(void) +{ + env->pc_delay = env->reg[25]; + env->delay_insn = 1; +} + +__or_dynop void op_move_gpr26_pc_delay(void) +{ + env->pc_delay = env->reg[26]; + env->delay_insn = 1; +} + +__or_dynop void op_move_gpr27_pc_delay(void) +{ + env->pc_delay = env->reg[27]; + env->delay_insn = 1; +} + +__or_dynop void op_move_gpr28_pc_delay(void) +{ + env->pc_delay = env->reg[28]; + env->delay_insn = 1; +} + +__or_dynop void op_move_gpr29_pc_delay(void) +{ + env->pc_delay = env->reg[29]; + env->delay_insn = 1; +} + +__or_dynop void op_move_gpr30_pc_delay(void) +{ + env->pc_delay = env->reg[30]; + env->delay_insn = 1; +} + +__or_dynop void op_move_gpr31_pc_delay(void) +{ + env->pc_delay = env->reg[31]; + env->delay_insn = 1; +} + +#define OP_FILE "op_1t_op.h" +#include "op_1t.h" +#undef OP_FILE + +#define OP_FILE "op_2t_op.h" +#include "op_2t.h" +#undef OP_FILE + +#define OP_FILE "op_3t_op.h" +#include "op_3t.h" +#undef OP_FILE + +#define OP_FILE "op_arith_op.h" +#define OP_EXTRA + +#define OP / +#define OP_CAST(x) (orreg_t)(x) +#define OP_NAME div +#include "op_3t.h" +#undef OP_NAME +#undef OP_CAST +#undef OP + +#define OP / +#define OP_CAST(x) (x) +#define OP_NAME divu +#include "op_3t.h" +#undef OP_NAME +#undef OP_CAST +#undef OP + +#define OP * +#define OP_CAST(x) (x) +#define OP_NAME mulu +#include "op_3t.h" +#undef OP_NAME +#undef OP_CAST +#undef OP + +#define OP - +#define OP_CAST(x) (orreg_t)(x) +#define OP_NAME sub +#include "op_3t.h" +#undef OP_NAME +#undef OP_CAST +#undef OP + +#undef OP_EXTRA + +#define OP_EXTRA + ((env->sprs[SPR_SR] & SPR_SR_CY) >> 10) +#define OP + +#define OP_CAST(x) (orreg_t)(x) +#define OP_NAME addc +#include "op_3t.h" +#include "op_2t.h" +#undef OP_NAME +#undef OP_CAST +#undef OP + +#undef OP_EXTRA +#define OP_EXTRA + +#define OP + +#define OP_CAST(x) (orreg_t)(x) +#define OP_NAME add +#include "op_3t.h" +#include "op_2t.h" +#undef OP_NAME +#undef OP_CAST +#undef OP + +#define OP & +#define OP_CAST(x) (x) +#define OP_NAME and +#include "op_3t.h" +#include "op_2t.h" +#undef OP_NAME +#undef OP_CAST +#undef OP + +#define OP * +#define OP_CAST(x) (orreg_t)(x) +#define OP_NAME mul +#include "op_3t.h" +#include "op_2t.h" +#undef OP_NAME +#undef OP_CAST +#undef OP + +#define OP | +#define OP_CAST(x) (x) +#define OP_NAME or +#include "op_3t.h" +#include "op_2t.h" +#undef OP_NAME +#undef OP_CAST +#undef OP + +#define OP << +#define OP_CAST(x) (x) +#define OP_NAME sll +#include "op_3t.h" +#include "op_2t.h" +#undef OP_NAME +#undef OP_CAST +#undef OP + +#define OP >> +#define OP_CAST(x) (orreg_t)(x) +#define OP_NAME sra +#include "op_3t.h" +#include "op_2t.h" +#undef OP_NAME +#undef OP_CAST +#undef OP + +#define OP >> +#define OP_CAST(x) (x) +#define OP_NAME srl +#include "op_3t.h" +#include "op_2t.h" +#undef OP_NAME +#undef OP_CAST +#undef OP + +#define OP ^ +#define OP_CAST(x) (x) +#define OP_NAME xor +#include "op_3t.h" +#include "op_2t.h" +#undef OP_NAME +#undef OP_CAST +#undef OP + +#undef OP_EXTRA +#undef OP_FILE + +#define OP_FILE "op_extend_op.h" + +#define EXT_NAME extbs +#define EXT_TYPE int8_t +#define EXT_CAST (orreg_t) +#include "op_2t.h" +#undef EXT_CAST +#undef EXT_TYPE +#undef EXT_NAME + +#define EXT_NAME extbz +#define EXT_TYPE uint8_t +#define EXT_CAST (uorreg_t) +#include "op_2t.h" +#undef EXT_CAST +#undef EXT_TYPE +#undef EXT_NAME + +#define EXT_NAME exths +#define EXT_TYPE int16_t +#define EXT_CAST (orreg_t) +#include "op_2t.h" +#undef EXT_CAST +#undef EXT_TYPE +#undef EXT_NAME + +#define EXT_NAME exthz +#define EXT_TYPE uint16_t +#define EXT_CAST (uorreg_t) +#include "op_2t.h" +#undef EXT_CAST +#undef EXT_TYPE +#undef EXT_NAME + +#undef OP_FILE + +#define OP_FILE "op_comp_op.h" + +#define COMP == +#define COMP_NAME sfeq +#define COMP_CAST(x) (x) +#include "op_2t.h" +#include "op_1t.h" +#undef COMP_CAST +#undef COMP_NAME +#undef COMP + +#define COMP != +#define COMP_NAME sfne +#define COMP_CAST(x) (x) +#include "op_2t.h" +#include "op_1t.h" +#undef COMP_CAST +#undef COMP_NAME +#undef COMP + +#define COMP > +#define COMP_NAME sfgtu +#define COMP_CAST(x) (x) +#include "op_2t.h" +#include "op_1t.h" +#undef COMP_CAST +#undef COMP_NAME +#undef COMP + +#define COMP >= +#define COMP_NAME sfgeu +#define COMP_CAST(x) (x) +#include "op_2t.h" +#include "op_1t.h" +#undef COMP_CAST +#undef COMP_NAME +#undef COMP + +#define COMP < +#define COMP_NAME sfltu +#define COMP_CAST(x) (x) +#include "op_2t.h" +#include "op_1t.h" +#undef COMP_CAST +#undef COMP_NAME +#undef COMP + +#define COMP <= +#define COMP_NAME sfleu +#define COMP_CAST(x) (x) +#include "op_2t.h" +#include "op_1t.h" +#undef COMP_CAST +#undef COMP_NAME +#undef COMP + +#define COMP > +#define COMP_NAME sfgts +#define COMP_CAST(x) (orreg_t)(x) +#include "op_2t.h" +#include "op_1t.h" +#undef COMP_CAST +#undef COMP_NAME +#undef COMP + +#define COMP >= +#define COMP_NAME sfges +#define COMP_CAST(x) (orreg_t)(x) +#include "op_2t.h" +#include "op_1t.h" +#undef COMP_CAST +#undef COMP_NAME +#undef COMP + +#define COMP < +#define COMP_NAME sflts +#define COMP_CAST(x) (orreg_t)(x) +#include "op_2t.h" +#include "op_1t.h" +#undef COMP_CAST +#undef COMP_NAME +#undef COMP + +#define COMP <= +#define COMP_NAME sfles +#define COMP_CAST(x) (orreg_t)(x) +#include "op_2t.h" +#include "op_1t.h" +#undef COMP_CAST +#undef COMP_NAME +#undef COMP + +#undef OP_FILE + +#define OP_FILE "op_t_reg_mov_op.h" +#include "op_1t.h" +#undef OP_FILE + +#define OP_FILE "op_mftspr_op.h" +#include "op_1t.h" +#include "op_2t.h" +#undef OP_FILE +#include "op_mftspr_op.h" + +#define OP_FILE "op_mac_op.h" + +#define OP += +#define OP_NAME mac +#include "op_2t.h" +#undef OP_NAME +#undef OP + +#define OP -= +#define OP_NAME msb +#include "op_2t.h" +#undef OP_NAME +#undef OP + +#undef OP_FILE + +#define OP_FILE "op_lwhb_op.h" + +#define LS_OP_NAME lbz +#define LS_OP_CAST +#define LS_OP_FUNC eval_mem8 +#include "op_2t.h" +#include "op_1t.h" +#undef LS_OP_FUNC +#undef LS_OP_CAST +#undef LS_OP_NAME + +#define LS_OP_NAME lbs +#define LS_OP_CAST (int8_t) +#define LS_OP_FUNC eval_mem8 +#include "op_2t.h" +#include "op_1t.h" +#undef LS_OP_FUNC +#undef LS_OP_CAST +#undef LS_OP_NAME + +#define LS_OP_NAME lhz +#define LS_OP_CAST +#define LS_OP_FUNC eval_mem16 +#include "op_2t.h" +#include "op_1t.h" +#undef LS_OP_FUNC +#undef LS_OP_CAST +#undef LS_OP_NAME + +#define LS_OP_NAME lhs +#define LS_OP_CAST (int16_t) +#define LS_OP_FUNC eval_mem16 +#include "op_2t.h" +#include "op_1t.h" +#undef LS_OP_FUNC +#undef LS_OP_CAST +#undef LS_OP_NAME + +#define LS_OP_NAME lwz +#define LS_OP_CAST +#define LS_OP_FUNC eval_mem32 +#include "op_2t.h" +#include "op_1t.h" +#undef LS_OP_FUNC +#undef LS_OP_CAST +#undef LS_OP_NAME + +#define LS_OP_NAME lws +#define LS_OP_CAST (int32_t) +#define LS_OP_FUNC eval_mem32 +#include "op_2t.h" +#include "op_1t.h" +#undef LS_OP_FUNC +#undef LS_OP_CAST +#undef LS_OP_NAME + +#undef OP_FILE + +#define OP_FILE "op_swhb_op.h" + +#define S_OP_NAME sb +#define S_FUNC set_mem8 +#include "op_swhb_op.h" +#include "op_2t.h" +#include "op_1t.h" +#undef S_FUNC +#undef S_OP_NAME + +#define S_OP_NAME sh +#define S_FUNC set_mem16 +#include "op_swhb_op.h" +#include "op_2t.h" +#include "op_1t.h" +#undef S_FUNC +#undef S_OP_NAME + +#define S_OP_NAME sw +#define S_FUNC set_mem32 +#include "op_swhb_op.h" +#include "op_2t.h" +#include "op_1t.h" +#undef S_FUNC +#undef S_OP_NAME + +__or_dynop void op_join_mem_cycles(void) +{ + runtime.sim.cycles += runtime.sim.mem_cycles; + scheduler.job_queue->time -= runtime.sim.mem_cycles; + runtime.sim.mem_cycles = 0; +} + +__or_dynop void op_store_link_addr_gpr(void) +{ + env->reg[LINK_REGNO] = env->pc + 8; +} + +__or_dynop void op_prep_rfe(void) +{ + env->sprs[SPR_SR] = env->sprs[SPR_ESR_BASE] | SPR_SR_FO; + env->sprs[SPR_PPC] = env->pc; + env->pc = env->sprs[SPR_EPCR_BASE] - 4; +} + +static inline void prep_except(oraddr_t epcr_base) +{ + env->sprs[SPR_EPCR_BASE] = epcr_base; + + env->sprs[SPR_ESR_BASE] = env->sprs[SPR_SR]; + + /* Address translation is always disabled when starting exception. */ + env->sprs[SPR_SR] &= ~SPR_SR_DME; + env->sprs[SPR_SR] &= ~SPR_SR_IME; + + env->sprs[SPR_SR] &= ~SPR_SR_OVE; /* Disable overflow flag exception. */ + + env->sprs[SPR_SR] |= SPR_SR_SM; /* SUPV mode */ + env->sprs[SPR_SR] &= ~(SPR_SR_IEE | SPR_SR_TEE); /* Disable interrupts. */ +} + +/* Before the code in op_{sys,trap}{,_delay} gets run, the scheduler runs. + * Therefore the pc will point to the instruction after the l.sys or l.trap + * instruction */ +__or_dynop void op_prep_sys_delay(void) +{ + env->delay_insn = 0; + prep_except(env->pc - 4); + env->pc = EXCEPT_SYSCALL - 4; +} + +__or_dynop void op_prep_sys(void) +{ + prep_except(env->pc + 4); + env->pc = EXCEPT_SYSCALL - 4; +} + +__or_dynop void op_prep_trap_delay(void) +{ + env->delay_insn = 0; + prep_except(env->pc - 4); + env->pc = EXCEPT_TRAP - 4; +} + +__or_dynop void op_prep_trap(void) +{ + prep_except(env->pc); + env->pc = EXCEPT_TRAP - 4; +} + +/* FIXME: This `instruction' should be split up like the l.trap and l.sys + * instructions are done */ +__or_dynop void op_illegal_delay(void) +{ + env->delay_insn = 0; + env->sprs[SPR_EEAR_BASE] = env->pc - 4; + env->pc = EXCEPT_ILLEGAL - 4; +} + +__or_dynop void op_illegal(void) +{ + env->sprs[SPR_EEAR_BASE] = env->pc; + env->pc = EXCEPT_ILLEGAL; +} + +__or_dynop void op_do_sched(void) +{ + SPEEDY_CALL(do_sched_wrap); +} + +__or_dynop void op_do_sched_delay(void) +{ + SPEEDY_CALL(do_sched_wrap_delay); +} + +__or_dynop void op_macc(void) +{ + env->sprs[SPR_MACLO] = 0; + env->sprs[SPR_MACHI] = 0; +} + +__or_dynop void op_store_insn_ea(void) +{ + env->insn_ea = OP_PARAM1; +} + Index: dyngen.c =================================================================== --- dyngen.c (nonexistent) +++ dyngen.c (revision 1765) @@ -0,0 +1,289 @@ +/* dyngen.c -- Generates micro operation generating functions + Copyright (C) 2005 György `nog' Jeney, nog@sdf.lonestar.org + +This file is part of OpenRISC 1000 Architectural Simulator. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + + +#include +#include +#include + +#include "dyngen.h" + +#define OP_FUNC_PREFIX "op_" +#define OP_FUNC_PARAM_PREFIX "__op_param" +/* Have to add to to make sure that the param[] is 0 */ +#define MAX_PARAMS (3 + 1) + +static const char *c_file_head = +"#include \"config.h\"\n" +"\n" +"#include \n" +"\n" +"#include \"arch.h\"\n" +"#include \"opcode/or32.h\"\n" +"#include \"spr_defs.h\"\n" +"#include \"i386_regs.h\"\n" +"#include \"abstract.h\"\n" +"\n" +"#include \"dyn_rec.h\"\n" +"#include \"%s\"\n" +"\n"; + +static const char *gen_code_proto = +"void gen_code(struct op_queue *opq, struct dyn_page *dp);\n" +"void patch_relocs(struct op_queue *opq, void *host_page);\n" +"\n"; + +static const char *c_sw_file_head = +"#include \n" +"#include \n" +"\n" +"#include \"config.h\"\n" +"\n" +"#include \n" +"\n" +"#include \"arch.h\"\n" +"#include \"opcode/or32.h\"\n" +"#include \"spr_defs.h\"\n" +"#include \"i386_regs.h\"\n" +"#include \"abstract.h\"\n" +"#include \"dyn_rec.h\"\n" +"#include \"%s\"\n" +"\n" +"void gen_code(struct op_queue *opq, struct dyn_page *dp)\n" +"{\n" +" unsigned int *ops, i;\n" +" unsigned int host_len = dp->host_len;\n" +" void *host_cur = dp->host_page;\n" +" oraddr_t pc = dp->or_page;\n" +" void **loc = dp->locs;\n" +"\n" +" while(opq) {\n" +" if(opq->next)\n" +" *loc++ = (void *)(host_cur - dp->host_page);" +"\n" +" for(i = 0, ops = opq->ops; i < opq->num_ops; i++, ops++) {\n" +" switch(*ops) {\n" +" case op_mark_loc_indx:\n" +" opq->ops_param[0] = host_cur - dp->host_page;\n" +" break;\n"; + +static const char *c_sw_file_tail = +" }\n" +" }\n" +" opq = opq->next;\n" +" pc += 4;\n" +" }\n" +"\n" +" dp->host_len = host_cur - dp->host_page;\n" +" dp->host_page = realloc(dp->host_page, dp->host_len);\n" +"}\n"; + +static const char *c_rel_file_head = +"#include /* To get printf... */\n" +"#include \n" +"\n" +"#include \"config.h\"\n" +"\n" +"#include \n" +"\n" +"#include \"arch.h\"\n" +"#include \"spr_defs.h\"\n" +"#include \"i386_regs.h\"\n" +"#include \"opcode/or32.h\"\n" +"#include \"abstract.h\"\n" +"#include \"tick.h\"\n" +"#include \"execute.h\"\n" +"#include \"sprs.h\"\n" +"#include \"dyn_rec.h\"\n" +"#include \"op_support.h\"\n" +"#include \"%s\"\n" +"\n" +"void do_scheduler(void); /* FIXME: Remove */\n" +"void do_sched_wrap(void); /* FIXME: Remove */\n" +"void do_sched_wrap_delay(void); /* FIXME: Remove */\n" +"void simprintf(oraddr_t stackaddr, unsigned long regparam); /* FIXME: Remove */\n" +"\n" +"void patch_relocs(struct op_queue *opq, void *host_page)\n" +"{\n" +" unsigned int *ops, *ops_param, i;\n" +"\n" +" while(opq) {\n" +" for(i = 0, ops = opq->ops, ops_param = opq->ops_param; i < opq->num_ops; i++, ops++) {\n" +" switch(*ops) {\n"; + +static const char *c_rel_file_tail = +" }\n" +" }\n" +" opq = opq->next;\n" +" }\n" +"}\n"; + +static void gen_func_proto(FILE *f, const char *name, int *params) +{ + int i; + + fprintf(f, "void gen_%s(struct op_queue *opq, int end", name); + for(i = 0; (i < MAX_PARAMS) && params[i]; i++) { + fprintf(f, ", uorreg_t param%i", i + 1); + } + fprintf(f, ")"); +} + +int main(int argc, char **argv) +{ + void *obj; + int i, j; + unsigned int len; + char *name; + int params[MAX_PARAMS]; + struct reloc reloc; + + FILE *c_file; + FILE *h_file; + FILE *c_sw_file; + FILE *c_rel_file; + + if(argc != 6) { + fprintf(stderr, "Usage: %s \n", argv[0]); + return 1; + } + + obj = bffs.open_obj(argv[1]); + if(!obj) { + fprintf(stderr, "Unable to open object file %s\n", argv[1]); + return 1; + } + + if(!(c_file = fopen(argv[2], "w"))) { + fprintf(stderr, "Unable to open %s for writting\n", argv[2]); + bffs.close_obj(obj); + return 1; + } + + if(!(c_sw_file = fopen(argv[3], "w"))) { + fprintf(stderr, "Unable to open %s for writting\n", argv[2]); + fclose(c_file); + bffs.close_obj(obj); + } + + if(!(c_rel_file = fopen(argv[4], "w"))) { + fprintf(stderr, "Unable to open %s for writting\n", argv[3]); + fclose(c_file); + fclose(c_sw_file); + bffs.close_obj(obj); + return 1; + } + + if(!(h_file = fopen(argv[5], "w"))) { + fprintf(stderr, "Unable to open %s for writting\n", argv[3]); + fclose(c_file); + fclose(c_sw_file); + fclose(c_rel_file); + bffs.close_obj(obj); + return 1; + } + + fprintf(c_file, c_file_head, argv[5]); + fprintf(c_sw_file, c_sw_file_head, argv[5]); + fprintf(c_rel_file, c_rel_file_head, argv[5]); + fprintf(h_file, "%s", gen_code_proto); + + /* Itterate through the functions in the object file */ + for(i = 0; (name = bffs.get_func_name(obj, i)); i++) { + if(strncmp(name, OP_FUNC_PREFIX, strlen(OP_FUNC_PREFIX))) + continue; + + /* Find all the relocations associated with this function */ + memset(params, 0, sizeof(params)); + for(j = 0; bffs.get_func_reloc(obj, i, j, &reloc); j++) { + //fprintf(stderr, "%s %i %i\n", reloc.name, reloc.func_offset, reloc.addend); + if(strncmp(reloc.name, OP_FUNC_PARAM_PREFIX, strlen(OP_FUNC_PARAM_PREFIX))) { + continue; + } + params[atoi(reloc.name + strlen(OP_FUNC_PARAM_PREFIX)) - 1] = 1; + } + + len = archfs.get_real_func_len(bffs.get_func_start(obj, i), + bffs.get_func_len(obj, i), name); + + gen_func_proto(h_file, name, params); + fprintf(h_file, ";\n"); + + if(len) { + /* Prototype the operation */ + fprintf(h_file, "void %s(void);\n", name); + fprintf(h_file, "#define %s_indx %i\n", name, i); + } + + gen_func_proto(c_file, name, params); + fprintf(c_file, "\n{\n"); + if(len) { + fprintf(c_file, " add_to_opq(opq, end, %s_indx);\n", name); + + for(j = 0; params[j]; j++) + fprintf(c_file, " add_to_op_params(opq, end, param%i);\n", j + 1); + } + fprintf(c_file, "}\n\n"); + + if(!len) { + /* If the operation is of length 0, then just ignore it */ + fprintf(stderr, "WARNING: Useless operation (size == 0): %s\n", name); + continue; + } + + fprintf(c_sw_file, " case %s_indx:\n", name); + fprintf(c_sw_file, " host_cur = enough_host_page(dp, host_cur, &host_len, %i);\n", len); + fprintf(c_sw_file, " memcpy(host_cur, %s, %i);\n", name, len); + + fprintf(c_rel_file, " case %s_indx:\n", name); + for(j = 0; bffs.get_func_reloc(obj, i, j, &reloc); j++) { + /* Ignore nameless relocations, they appear to be absolute */ + if(!*reloc.name) + continue; + if(strncmp(reloc.name, OP_FUNC_PARAM_PREFIX, strlen(OP_FUNC_PARAM_PREFIX))) { + /* We have to manually do the relocations when the relocation is + * relative to the PC as the code gets copied to a different location + * during recompilation, where the relative addresses shall be waay out. + */ + archfs.gen_func_reloc(c_rel_file, &reloc); + } else { + archfs.gen_reloc(c_rel_file, &reloc, + atoi(reloc.name + strlen(OP_FUNC_PARAM_PREFIX))); + } + } + + fprintf(c_sw_file, " host_cur += %i;\n break;\n\n", len); + fprintf(c_rel_file, " host_page += %i;\n", len); + /* Count how many parameters where used */ + for(j = 0; params[j]; j++); + fprintf(c_rel_file, " ops_param += %i;\n break;\n\n", j); + } + + fprintf(c_sw_file, "%s", c_sw_file_tail); + fprintf(c_rel_file, "%s", c_rel_file_tail); + + fprintf(h_file, "\n#define op_mark_loc_indx %i\n", i); + + fclose(h_file); + fclose(c_file); + fclose(c_sw_file); + fclose(c_rel_file); + bffs.close_obj(obj); + return 0; +} Index: def_op_t.h =================================================================== --- def_op_t.h (nonexistent) +++ def_op_t.h (revision 1765) @@ -0,0 +1,138 @@ +/* def_op_t.h -- Operation-generation strucutre definitions helpers + Copyright (C) 2005 György `nog' Jeney, nog@sdf.lonestar.org + +This file is part of OpenRISC 1000 Architectural Simulator. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#define GPR_T(op_name, temp) \ + { NULL, \ + glue(glue(op_name, 1), temp), \ + glue(glue(op_name, 2), temp), \ + glue(glue(op_name, 3), temp), \ + glue(glue(op_name, 4), temp), \ + glue(glue(op_name, 5), temp), \ + glue(glue(op_name, 6), temp), \ + glue(glue(op_name, 7), temp), \ + glue(glue(op_name, 8), temp), \ + glue(glue(op_name, 9), temp), \ + glue(glue(op_name, 10), temp), \ + glue(glue(op_name, 11), temp), \ + glue(glue(op_name, 12), temp), \ + glue(glue(op_name, 13), temp), \ + glue(glue(op_name, 14), temp), \ + glue(glue(op_name, 15), temp), \ + glue(glue(op_name, 16), temp), \ + glue(glue(op_name, 17), temp), \ + glue(glue(op_name, 18), temp), \ + glue(glue(op_name, 19), temp), \ + glue(glue(op_name, 20), temp), \ + glue(glue(op_name, 21), temp), \ + glue(glue(op_name, 22), temp), \ + glue(glue(op_name, 23), temp), \ + glue(glue(op_name, 24), temp), \ + glue(glue(op_name, 25), temp), \ + glue(glue(op_name, 26), temp), \ + glue(glue(op_name, 27), temp), \ + glue(glue(op_name, 28), temp), \ + glue(glue(op_name, 29), temp), \ + glue(glue(op_name, 30), temp), \ + glue(glue(op_name, 31), temp) } + +#if NUM_T_REGS == 3 + +#define OP_ROW(op_name) \ + { glue(op_name, _t0), glue(op_name, _t1), glue(op_name, _t2) } + +#define OP_ROW_NEQ0(op_name) \ + { NULL, glue(op_name, _t1), glue(op_name, _t2) } + +#define OP_ROW_NEQ1(op_name) \ + { glue(op_name, _t0), NULL, glue(op_name, _t2) } + +#define OP_ROW_NEQ2(op_name) \ + { glue(op_name, _t0), glue(op_name, _t1), NULL } + +#define OP_ROW_COL(op_name) { \ + OP_ROW(glue(op_name, _t0)), \ + OP_ROW(glue(op_name, _t1)), \ + OP_ROW(glue(op_name, _t2)), } + +/* In 3D space: row, column, ??? */ +#define OP_ROW_COL_3D(op_name) { \ + OP_ROW_COL(glue(op_name, _t0)), \ + OP_ROW_COL(glue(op_name, _t1)), \ + OP_ROW_COL(glue(op_name, _t2)) } + +#define OP_ROW_COL_NEQ(op_name) { \ + OP_ROW_NEQ0(glue(op_name, _t0)), \ + OP_ROW_NEQ1(glue(op_name, _t1)), \ + OP_ROW_NEQ2(glue(op_name, _t2)) } + +#define OP_ROW_COL_NEQ0(op_name) { \ + OP_ROW_NEQ0(glue(op_name, _t0)), \ + OP_ROW(glue(op_name, _t1)), \ + OP_ROW(glue(op_name, _t2)) } + +#define OP_ROW_COL_NEQ1(op_name) { \ + OP_ROW(glue(op_name, _t0)), \ + OP_ROW_NEQ1(glue(op_name, _t1)), \ + OP_ROW(glue(op_name, _t2)) } + +#define OP_ROW_COL_NEQ2(op_name) { \ + OP_ROW(glue(op_name, _t0)), \ + OP_ROW(glue(op_name, _t1)), \ + OP_ROW_NEQ2(glue(op_name, _t2)) } + +#define OP_ROW_COL_3D_NEQ(op_name) { \ + OP_ROW_COL_NEQ0(glue(op_name, _t0)), \ + OP_ROW_COL_NEQ1(glue(op_name, _t1)), \ + OP_ROW_COL_NEQ2(glue(op_name, _t2)) } + +#define GPR_ROW_COL(op_name) { \ + GPR_T(op_name, _t0), \ + GPR_T(op_name, _t1), \ + GPR_T(op_name, _t2) } + +#else +#error Update def_op_t.h for NUM_T_REGS temporaries +#endif + +#define DEF_1T_OP(type, name, op_name) \ + static const type name[NUM_T_REGS] = \ + OP_ROW(op_name) + +#define DEF_2T_OP(type, name, op_name) \ + static const type name[NUM_T_REGS][NUM_T_REGS] = \ + OP_ROW_COL(op_name) + +#define DEF_3T_OP(type, name, op_name) \ + static const type name[NUM_T_REGS][NUM_T_REGS][NUM_T_REGS] = \ + OP_ROW_COL_3D(op_name) + +/* Same as above but put NULL in places where T0 == T1 */ +#define DEF_2T_OP_NEQ(type, name, op_name) \ + static const type name[NUM_T_REGS][NUM_T_REGS] = \ + OP_ROW_COL_NEQ(op_name) + +/* Same as above but put NULL in places where T0 == T1 == T2 */ +#define DEF_3T_OP_NEQ(type, name, op_name) \ + static const type name[NUM_T_REGS][NUM_T_REGS][NUM_T_REGS] = \ + OP_ROW_COL_3D_NEQ(op_name) + +#define DEF_GPR_OP(type, name, op_name) \ + static const generic_gen_op name[NUM_T_REGS][32] = \ + GPR_ROW_COL(op_name) + Index: dyngen.h =================================================================== --- dyngen.h (nonexistent) +++ dyngen.h (revision 1765) @@ -0,0 +1,45 @@ +/* dyngen.h -- Definitions for dyngen.c + Copyright (C) 2005 György `nog' Jeney, nog@sdf.lonestar.org + +This file is part of OpenRISC 1000 Architectural Simulator. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + + +struct reloc { + unsigned int func_offset; + unsigned int addend; + int type; + const char *name; +}; + +struct bff { + void *(*open_obj)(const char *object); /* Open the object file */ + void (*close_obj)(void *); + char *(*get_func_name)(void *, unsigned int func); /* Gets the name of func */ + void *(*get_func_start)(void *, unsigned int func); + unsigned int (*get_func_len)(void *, unsigned int func); + int (*get_func_reloc)(void *, unsigned int func, unsigned int relocn, struct reloc *reloc); +}; + +extern const struct bff bffs; + +struct archf { + unsigned int (*get_real_func_len)(void *func, unsigned int len, char *name); + void (*gen_reloc)(FILE *f, struct reloc *reloc, unsigned int param); + void (*gen_func_reloc)(FILE *f, struct reloc *reloc); +}; + +extern const struct archf archfs; Index: . =================================================================== --- . (nonexistent) +++ . (revision 1765)
. Property changes : Added: svn:ignore ## -0,0 +1,3 ## +Makefile +.deps +generate

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.