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