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-rc2/or1ksim/cpu/or32
- from Rev 1753 to Rev 1765
- ↔ Reverse comparison
Rev 1753 → Rev 1765
/Makefile.in
0,0 → 1,775
# 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 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@ 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 |
am__dist_EXTRA_libarch_la_SOURCES_DIST = insnset.c |
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 = |
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) \ |
$(dist_EXTRA_libarch_la_SOURCES) $(dyngen_SOURCES) \ |
$(generate_SOURCES) |
DIST_SOURCES = $(am__libarch_la_SOURCES_DIST) \ |
$(am__dist_EXTRA_libarch_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 |
@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_FALSE@libarch_la_SOURCES = execute.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@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_TRUE@OP_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) |
@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_FALSE@dist_EXTRA_libarch_la_SOURCES = insnset.c |
|
# 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) |
|
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)/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 $@ $< |
|
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-tmp.o |
@DYNAMIC_EXECUTION_TRUE@ ./dyngen$(EXEEXT) op-tmp.o gen-ops.c gen-ops-gen.c gen-ops-rel.c gen-ops.h |
|
@DYNAMIC_EXECUTION_TRUE@op-tmp.o: op.c op-t-reg-mov-op.h op-i386.h op-arith-op.h op-comp-op.h \ |
@DYNAMIC_EXECUTION_TRUE@ op-extend-op.h op-ff1-op.h op-mac-op.h op-mftspr-op.h op-lwhb-op.h \ |
@DYNAMIC_EXECUTION_TRUE@ op-swhb-op.h |
@DYNAMIC_EXECUTION_TRUE@ $(CC) $(INCLUDES) -I$(top_builddir) $(OP_CFLAGS) -o $@ -c $< |
|
@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: |
/op-mftspr-op.h
0,0 → 1,78
/* 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. */ |
|
|
#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.c
0,0 → 1,971
/* op.c -- Micro operations for the recompiler |
|
|
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 "config.h" |
|
#ifdef HAVE_INTTYPES_H |
#include <inttypes.h> |
#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; |
} |
|
/dyn32-defs.h
0,0 → 1,139
/* dyn32-defs.h -- Definitions for the dynamic execution model |
|
|
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. */ |
|
|
#ifndef DYN32_DEFS__H |
#define DYN32_DEFS__H |
|
|
/* Package includes */ |
#include "arch.h" |
|
|
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); |
|
#endif /* DYN32_DEFS__H */ |
|
/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" |
#include "simprintf.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-swhb-op.h
0,0 → 1,57
/* 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 */ |
|
|
#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 |
/dyn-rec.c
0,0 → 1,2451
/* 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" |
#include "toplevel-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[0] == 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[0] == 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,1180
/* 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" |
#include "rsp-server.h" |
|
|
/* Includes and 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) |
|
#define INSTRUCTION(name) void name (struct iqueue_entry *current) |
|
#endif /* SIMPLE_EXECUTION */ |
|
|
/*! 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; |
#if !(DYNAMIC_EXECUTION) |
static int sbuf_buf[MAX_SBUF_LEN] = { 0 }; |
#endif |
|
static int sbuf_prev_cycles = 0; |
|
/* Variables used throughout this file to share information */ |
static int breakpoint; |
static int next_delay_insn; |
|
/* Forward declaration of static functions */ |
#if !(DYNAMIC_EXECUTION) |
static void decode_execute (struct iqueue_entry *current); |
#endif |
|
/*---------------------------------------------------------------------------*/ |
/*!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) 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() */ |
|
|
#if !(DYNAMIC_EXECUTION) |
|
/*---------------------------------------------------------------------------*/ |
/*!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() */ |
|
#endif /* !DYNAMIC_EXECUTION */ |
|
|
/*---------------------------------------------------------------------------*/ |
/*!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 =%" PRIxREG " ", |
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.rsp_enabled) |
{ |
handle_rsp (); |
} |
else if (config.debug.gdb_enabled) |
{ |
block_jtag (); |
handle_server_socket (FALSE); |
} |
else |
{ |
fprintf (stderr, "ERROR: CPU stalled and GDB connection not " |
"enabled: Invoking CLI and terminating.\n"); |
/* Dump the user into interactive mode. From there he or |
she 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); |
|
if (config.debug.rsp_enabled) |
{ |
rsp_exception (EXCEPT_TRAP); |
} |
} |
} |
|
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 |
|
|
/*---------------------------------------------------------------------------*/ |
/*!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) |
{ |
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) |
{ |
T0 = OP_CAST(T1) OP OP_CAST(OP_PARAM1) OP_EXTRA; |
} |
#endif |
|
/dyn-rec.h
0,0 → 1,70
/* dyn-rec.h -- Recompiler specific definitions |
|
|
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. */ |
|
|
#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 */ |
}; |
|
/* Function prototypes for external use */ |
extern void recompile_page(struct dyn_page *dyn); |
extern struct dyn_page *new_dp(oraddr_t page); |
extern void add_to_opq(struct op_queue *opq, int end, int op); |
extern void add_to_op_params(struct op_queue *opq, int end, unsigned long param); |
extern void *enough_host_page(struct dyn_page *dp, void *cur, unsigned int *len, |
unsigned int amount); |
extern void init_dyn_recomp(void); |
extern void run_sched_out_of_line(void); |
extern void recheck_immu(int got_en_dis); |
extern void enter_dyn_code(oraddr_t addr, struct dyn_page *dp); |
extern void dyn_checkwrite(oraddr_t addr); |
extern void dyn_main(void); |
|
/* Global variables for external use */ |
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 /* DYN_REC__H */ |
|
/simpl32-defs.h
0,0 → 1,112
/* simpl32-defs.h -- Definitions for the simple execution model |
|
Copyright (C) 1999 Damjan Lampret, lampret@opencores.org |
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 or1k_gen_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. */ |
|
|
#ifndef SIMPLE32_DEFS__H |
#define SIMPLE32_DEFS__H |
|
/* Package includes */ |
#include "abstract.h" |
|
|
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 *)); |
|
#endif /* SIMPLE32_DEFS__H */ |
/def-op-t.h
0,0 → 1,138
/* def_op_t.h -- Operation-generation strucutre definitions helpers |
|
|
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) |
|
/insnset.c
0,0 → 1,614
/* insnset.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", (char)(evalsim_reg( 3 ) & 0xff)); |
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 %" PRIdREG " (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: 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
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: 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