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

Subversion Repositories or1k

Compare Revisions

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

Rev 1753 → Rev 1765

/dlx/arch.h
0,0 → 1,28
/* arch.h -- DLX architecture specific macros
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. */
 
#define LINK_REG "r31"
#define STACK_REG "r29"
#define FRAME_REG "r30"
 
#define MAX_GPRS 32
typedef unsigned long machword;
 
/* Should args be passed on stack */
#define STACK_ARGS 1
/dlx/Makefile.in
0,0 → 1,471
# 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 DLX 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/>.
 
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@
subdir = cpu/dlx
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_OBJECTS = execute.lo
libarch_la_OBJECTS = $(am_libarch_la_OBJECTS)
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)
DIST_SOURCES = $(libarch_la_SOURCES)
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@
noinst_LTLIBRARIES = libarch.la
libarch_la_SOURCES = execute.c \
arch.h
 
all: 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/dlx/Makefile'; \
cd $(top_srcdir) && \
$(AUTOMAKE) --gnu cpu/dlx/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) $(libarch_la_OBJECTS) $(libarch_la_LIBADD) $(LIBS)
 
mostlyclean-compile:
-rm -f *.$(OBJEXT)
 
distclean-compile:
-rm -f *.tab.c
 
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/execute.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 $@ $<
 
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: check-am
all-am: Makefile $(LTLIBRARIES)
installdirs:
install: 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:
 
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."
clean: clean-am
 
clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \
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 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
 
# 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:
/dlx/Makefile.am
0,0 → 1,26
# Makefile -- Makefile for DLX 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/>.
 
 
noinst_LTLIBRARIES = libarch.la
libarch_la_SOURCES = execute.c \
arch.h
/dlx/execute.c
0,0 → 1,754
/* execute.c -- DLX dependent simulation
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. */
 
/* Most of the DLX simulation is done in this file. */
 
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
 
#include "arch.h"
 
#include "branch_predict.h"
#include "abstract.h"
#include "parse.h"
#include "trace.h"
#include "execute.h"
#include "stats.h"
 
/* General purpose registers. */
machword reg[MAX_GPRS];
 
/* Instruction queue */
struct iqueue_entry iqueue[20];
 
/* Benchmark multi issue execution */
int multissue[20];
int supercycles;
 
/* Load and store stalls */
int loadcycles, storecycles;
 
/* Result forwarding stall cycles */
int forwardingcycles;
 
/* Completition queue */
struct icomplet_entry icomplet[20];
 
/* Program counter */
unsigned long pc;
 
/* Temporary program counter */
unsigned long pctemp;
 
/* Cycles counts fetch stages */
int cycles;
 
/* Implementation specific.
Get an actual value of a specific register. */
 
machword eval_reg(char *regstr)
{
int regno;
regno = atoi(regstr + 1);
 
if (regno < MAX_GPRS)
return reg[regno];
else {
PRINTF("\nABORT: read out of registers\n");
cont_run = 0;
return 0;
}
}
 
/* Implementation specific.
Set a specific register with value. */
 
void set_reg32(char *regstr, unsigned long value)
{
int regno;
regno = atoi(regstr + 1);
 
if (regno == 0) /* gpr0 is always zero */
value = 0;
if (regno < MAX_GPRS)
reg[regno] = value;
else {
PRINTF("\nABORT: write out of registers\n");
cont_run = 0;
}
 
return;
}
 
/* Does srcoperand depend on computation of dstoperand? Return
non-zero if yes.
 
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)
*/
 
int depend_operands(char *dstoperand, char *srcoperand)
{
char dst[OPERANDNAME_LEN];
char src[OPERANDNAME_LEN];
if (!srcoperand)
return 0;
 
if (!dstoperand)
return 0;
strcpy(dst, dstoperand);
strcpy(src, srcoperand);
 
if (*src == '#') /* immediate */
return 0;
else
if (!strstr(src, "("))
if (*src == 'r') { /* src: reg direct */
if (!strstr(dst, "("))
if (*dst == 'r')
if (strcmp(dst, src) == 0)
return 1; /* dst: reg direct */
else
return 0; /* dst: reg direct */
else
return 0; /* dst: addr */
else
return 0; /* dst: reg disp */
} else
return 0; /* src: addr */
else { /* src: register disp */
char *regstr;
regstr = strstr(src, "(r") + 1; /* regstr == "rXX)" */
*strstr(regstr, ")") = '\0'; /* regstr == "rXX" */
 
if (!strstr(dst, "("))
if (*dst == 'r')
if (strcmp(dst, regstr) == 0)
return 1; /* dst: reg direct */
else
return 0; /* dst: reg direct */
else
return 0; /* dst: addr */
else
return 1; /* dst: reg disp */
}
 
return 0;
}
 
/* Implementation specific.
Get an actual value represented by operand (register direct, register
indirect (with displacement), immediate etc.).
#n - immediate n
rXX - register direct
XX - relative or absolute address (labels)
n(XX) - register indirect (with displacement) */
machword eval_operand(char *srcoperand,int* breakpoint)
{
char operand[OPERANDNAME_LEN];
strcpy(operand, srcoperand);
 
if (*operand == '#') /* immediate */
return strtoul(&operand[1], NULL, 0);
else
if (!strstr(operand, "(")) /* not indirect but ...*/
if (*operand == 'r') /* ... register direct */
return eval_reg(operand);
else /* ... rel. or abs. address */
return eval_label(operand);
else { /* register indirect */
int disp; /* with possible displacement */
char *regstr;
unsigned int memaddr;
disp = atoi(operand); /* operand == "nn(rXX)" */
regstr = strstr(operand, "(r") + 1; /* regstr == "rXX)" */
*strstr(regstr, ")") = '\0'; /* regstr == "rXX" */
memaddr = eval_reg(regstr) + disp;
return eval_mem32(memaddr,breakpoint);
}
return 0;
}
 
/* Implementation specific.
Set destination operand (register direct, register indirect
(with displacement) with value. */
void set_operand(char *dstoperand, unsigned long value,int* breakpoint)
{
char operand[OPERANDNAME_LEN];
strcpy(operand, dstoperand);
 
if (*operand == '#') /* immediate */
PRINTF("INTERNAL ERROR: Can't set immediate operand.\n");
else
if (!strstr(operand, "(")) /* not indirect but ...*/
if (*operand == 'r') /* ... register direct */
set_reg32(operand, value);
else /* ... rel. or abs. address */
PRINTF("INTERNAL ERROR: Can't set addr operand.\n");
else { /* register indirect */
int disp; /* with possible displacement */
char *regstr;
unsigned int memaddr;
disp = atoi(operand); /* operand == "nn(rXX)" */
regstr = strstr(operand, "(r") + 1; /* regstr == "rXX)" */
*strstr(regstr, ")") = '\0'; /* regstr == "rXX" */
memaddr = eval_reg(regstr) + disp;
set_mem32(memaddr, value, breakpoint);
}
return;
}
 
void reset()
{
cycles = 0;
supercycles = 0;
loadcycles = 0;
storecycles = 0;
forwardingcycles = 0;
memset(reg, 0, sizeof(reg));
memset(iqueue, 0, sizeof(iqueue));
memset(icomplet, 0, sizeof(icomplet));
pctemp = eval_label("_main");
pc = pctemp;
set_reg32(STACK_REG , MEMORY_LEN - STACK_SIZE);
}
 
void fetch()
{
/* Cycles after reset. */
cycles++;
 
/* Simulate instruction cache */
ic_simulate(pc);
/* Fetch instruction. */
strcpy(iqueue[0].insn, mem[pc].insn->insn);
strcpy(iqueue[0].op1, mem[pc].insn->op1);
strcpy(iqueue[0].op2, mem[pc].insn->op2);
strcpy(iqueue[0].op3, mem[pc].insn->op3);
iqueue[0].insn_addr = pc;
iqueue[0].dependdst = NULL;
iqueue[0].dependsrc1 = NULL;
iqueue[0].dependsrc2 = NULL;
 
/* Increment program counter. */
pc = pctemp;
pctemp += 4;
/* Check for breakpoint. */
if (mem[pc].brk)
cont_run = 0; /* Breakpoint set. */
return;
}
 
void decode(struct iqueue_entry *cur)
{
int breakpoint = 0;
 
cur->dependdst = cur->op1;
cur->dependsrc1 = cur->op2; /* for calculating register */
cur->dependsrc2 = cur->op3; /* dependency */
cur->func_unit = unknown;
if (strcmp(cur->insn, "sw") == 0) {
cur->func_unit = store;
set_operand(cur->op1, eval_operand(cur->op2,&breakpoint),&breakpoint);
} else
if (strcmp(cur->insn, "sb") == 0) {
cur->func_unit = store;
set_operand(cur->op1, (eval_operand(cur->op2,&breakpoint) << 24) + (eval_operand(cur->op1,&breakpoint) & 0xffffff),&breakpoint);
} else
if (strcmp(cur->insn, "sh") == 0) {
cur->func_unit = store;
set_operand(cur->op1, (eval_operand(cur->op2,&breakpoint) << 16) + (eval_operand(cur->op1,&breakpoint) & 0xffff),&breakpoint);
} else
if (strcmp(cur->insn, "lw") == 0) {
cur->func_unit = load;
set_operand(cur->op1, eval_operand(cur->op2,&breakpoint),&breakpoint);
} else
if (strcmp(cur->insn, "lb") == 0) {
signed char temp = (eval_operand(cur->op2,&breakpoint) >> 24);
cur->func_unit = load;
set_operand(cur->op1, temp,&breakpoint);
} else
if (strcmp(cur->insn, "lbu") == 0) {
unsigned char temp = (eval_operand(cur->op2,&breakpoint) >> 24);
cur->func_unit = load;
set_operand(cur->op1, temp,&breakpoint);
} else
if (strcmp(cur->insn, "lh") == 0) {
signed short temp = (eval_operand(cur->op2,&breakpoint) >> 16);
cur->func_unit = load;
set_operand(cur->op1, temp,&breakpoint);
} else
if (strcmp(cur->insn, "lhu") == 0) {
unsigned short temp = (eval_operand(cur->op2,&breakpoint) >> 16);
cur->func_unit = load;
set_operand(cur->op1, temp,&breakpoint);
} else
if (strcmp(cur->insn, "lwi") == 0) {
cur->func_unit = movimm;
set_operand(cur->op1, eval_operand(cur->op2,&breakpoint),&breakpoint);
} else
if (strcmp(cur->insn, "lhi") == 0) {
cur->func_unit = movimm;
set_operand(cur->op1, eval_operand(cur->op2,&breakpoint) << 16,&breakpoint);
} else
if (strcmp(cur->insn, "and") == 0) {
cur->func_unit = arith;
set_operand(cur->op1, eval_operand(cur->op2,&breakpoint) & eval_operand(cur->op3,&breakpoint),&breakpoint);
} else
if (strcmp(cur->insn, "andi") == 0) {
cur->func_unit = arith;
set_operand(cur->op1, eval_operand(cur->op2,&breakpoint) & eval_operand(cur->op3,&breakpoint),&breakpoint);
} else
if (strcmp(cur->insn, "or") == 0) {
cur->func_unit = arith;
set_operand(cur->op1, eval_operand(cur->op2,&breakpoint) | eval_operand(cur->op3,&breakpoint),&breakpoint);
} else
if (strcmp(cur->insn, "ori") == 0) {
cur->func_unit = arith;
set_operand(cur->op1, eval_operand(cur->op2,&breakpoint) | eval_operand(cur->op3,&breakpoint),&breakpoint);
} else
if (strcmp(cur->insn, "xor") == 0) {
cur->func_unit = arith;
set_operand(cur->op1, eval_operand(cur->op2,&breakpoint) ^ eval_operand(cur->op3,&breakpoint),&breakpoint);
} else
if (strcmp(cur->insn, "add") == 0) {
signed long temp3, temp2, temp1;
signed char temp4;
 
cur->func_unit = arith;
temp3 = eval_operand(cur->op3,&breakpoint);
temp2 = eval_operand(cur->op2,&breakpoint);
temp1 = temp2 + temp3;
set_operand(cur->op1, temp1,&breakpoint);
temp4 = temp1;
if (temp4 == temp1)
mstats.byteadd++;
} else
if (strcmp(cur->insn, "addi") == 0) {
signed long temp3, temp2, temp1;
signed char temp4;
cur->func_unit = arith;
temp3 = eval_operand(cur->op3,&breakpoint);
temp2 = eval_operand(cur->op2,&breakpoint);
temp1 = temp2 + temp3;
set_operand(cur->op1, temp1,&breakpoint);
temp4 = temp1;
if (temp4 == temp1)
mstats.byteadd++;
} else
if (strcmp(cur->insn, "addui") == 0) {
unsigned long temp3, temp2, temp1;
unsigned char temp4;
cur->func_unit = arith;
temp3 = eval_operand(cur->op3,&breakpoint);
temp2 = eval_operand(cur->op2,&breakpoint);
temp1 = temp2 + temp3;
set_operand(cur->op1, temp1,&breakpoint);
temp4 = temp1;
if (temp4 == temp1)
mstats.byteadd++;
} else
if (strcmp(cur->insn, "sub") == 0) {
signed long temp3, temp2, temp1;
 
cur->func_unit = arith;
temp3 = eval_operand(cur->op3,&breakpoint);
temp2 = eval_operand(cur->op2,&breakpoint);
temp1 = temp2 - temp3;
set_operand(cur->op1, temp1,&breakpoint);
} else
if (strcmp(cur->insn, "subui") == 0) {
unsigned long temp3, temp2, temp1;
 
cur->func_unit = arith;
temp3 = eval_operand(cur->op3,&breakpoint);
temp2 = eval_operand(cur->op2,&breakpoint);
temp1 = temp2 - temp3;
set_operand(cur->op1, temp1,&breakpoint);
} else
if (strcmp(cur->insn, "subi") == 0) {
signed long temp3, temp2, temp1;
 
cur->func_unit = arith;
temp3 = eval_operand(cur->op3,&breakpoint);
temp2 = eval_operand(cur->op2,&breakpoint);
temp1 = temp2 - temp3;
set_operand(cur->op1, temp1,&breakpoint);
} else
if (strcmp(cur->insn, "mul") == 0) {
signed long temp3, temp2, temp1;
 
cur->func_unit = arith;
temp3 = eval_operand(cur->op3,&breakpoint);
temp2 = eval_operand(cur->op2,&breakpoint);
temp1 = temp2 * temp3;
set_operand(cur->op1, temp1,&breakpoint);
} else
if (strcmp(cur->insn, "div") == 0) {
signed long temp3, temp2, temp1;
 
cur->func_unit = arith;
temp3 = eval_operand(cur->op3,&breakpoint);
temp2 = eval_operand(cur->op2,&breakpoint);
temp1 = temp2 / temp3;
set_operand(cur->op1, temp1,&breakpoint);
} else
if (strcmp(cur->insn, "divu") == 0) {
unsigned long temp3, temp2, temp1;
 
cur->func_unit = arith;
temp3 = eval_operand(cur->op3,&breakpoint);
temp2 = eval_operand(cur->op2,&breakpoint);
temp1 = temp2 / temp3;
set_operand(cur->op1, temp1,&breakpoint);
} else
if (strcmp(cur->insn, "slli") == 0) {
cur->func_unit = shift;
set_operand(cur->op1, eval_operand(cur->op2,&breakpoint) << eval_operand(cur->op3,&breakpoint),&breakpoint);
} else
if (strcmp(cur->insn, "sll") == 0) {
cur->func_unit = shift;
set_operand(cur->op1, eval_operand(cur->op2,&breakpoint) << eval_operand(cur->op3,&breakpoint),&breakpoint);
} else
if (strcmp(cur->insn, "srl") == 0) {
cur->func_unit = shift;
set_operand(cur->op1, eval_operand(cur->op2,&breakpoint) >> eval_operand(cur->op3,&breakpoint),&breakpoint);
} else
if (strcmp(cur->insn, "srai") == 0) {
cur->func_unit = shift;
set_operand(cur->op1, (signed)eval_operand(cur->op2,&breakpoint) / (1 << eval_operand(cur->op3,&breakpoint)),&breakpoint);
} else
if (strcmp(cur->insn, "sra") == 0) {
cur->func_unit = shift;
set_operand(cur->op1, (signed)eval_operand(cur->op2,&breakpoint) / (1 << eval_operand(cur->op3,&breakpoint)),&breakpoint);
} else
if (strcmp(cur->insn, "jal") == 0) {
cur->func_unit = jump;
pctemp = eval_operand(cur->op1,&breakpoint);
set_reg32(LINK_REG, pc + 4);
} else
if (strcmp(cur->insn, "jr") == 0) {
cur->func_unit = jump;
cur->dependsrc1 = cur->op1;
pctemp = eval_operand(cur->op1,&breakpoint);
} else
if (strcmp(cur->insn, "j") == 0) {
cur->func_unit = jump;
pctemp = eval_operand(cur->op1,&breakpoint);
} else
if (strcmp(cur->insn, "nop") == 0) {
cur->func_unit = nop;
} else
if (strcmp(cur->insn, "beqz") == 0) {
cur->func_unit = branch;
cur->dependsrc1 = cur->op1;
if (eval_operand(cur->op1,&breakpoint) == 0) {
pctemp = eval_operand(cur->op2,&breakpoint);
mstats.beqz.taken++;
bpb_update(cur->insn_addr, 1);
btic_update(pctemp);
} else {
mstats.beqz.nottaken++;
bpb_update(cur->insn_addr, 0);
btic_update(pc);
}
} else
if (strcmp(cur->insn, "bnez") == 0) {
cur->func_unit = branch;
cur->dependsrc1 = cur->op1;
if (eval_operand(cur->op1,&breakpoint) != 0) {
pctemp = eval_operand(cur->op2,&breakpoint);
mstats.bnez.taken++;
bpb_update(cur->insn_addr, 1);
btic_update(pctemp);
} else {
mstats.bnez.nottaken++;
bpb_update(cur->insn_addr, 0);
btic_update(pc);
}
} else
if (strcmp(cur->insn, "seq") == 0) {
cur->func_unit = compare;
if (eval_operand(cur->op2,&breakpoint) == eval_operand(cur->op3,&breakpoint))
set_operand(cur->op1, 1,&breakpoint);
else
set_operand(cur->op1, 0,&breakpoint);
} else
if (strcmp(cur->insn, "snei") == 0) {
cur->func_unit = compare;
if (eval_operand(cur->op2,&breakpoint) != eval_operand(cur->op3,&breakpoint))
set_operand(cur->op1, 1,&breakpoint);
else
set_operand(cur->op1, 0,&breakpoint);
} else
if (strcmp(cur->insn, "sne") == 0) {
cur->func_unit = compare;
if (eval_operand(cur->op2,&breakpoint) != eval_operand(cur->op3,&breakpoint))
set_operand(cur->op1, 1,&breakpoint);
else
set_operand(cur->op1, 0,&breakpoint);
} else
if (strcmp(cur->insn, "seqi") == 0) {
cur->func_unit = compare;
if (eval_operand(cur->op2,&breakpoint) == eval_operand(cur->op3,&breakpoint))
set_operand(cur->op1, 1,&breakpoint);
else
set_operand(cur->op1, 0,&breakpoint);
} else
if (strcmp(cur->insn, "sgt") == 0) {
cur->func_unit = compare;
if ((signed)eval_operand(cur->op2,&breakpoint) >
(signed)eval_operand(cur->op3,&breakpoint))
set_operand(cur->op1, 1,&breakpoint);
else
set_operand(cur->op1, 0,&breakpoint);
} else
if (strcmp(cur->insn, "sgtui") == 0) {
cur->func_unit = compare;
if ((unsigned)eval_operand(cur->op2,&breakpoint) >
(unsigned)eval_operand(cur->op3,&breakpoint))
set_operand(cur->op1, 1,&breakpoint);
else
set_operand(cur->op1, 0,&breakpoint);
} else
if (strcmp(cur->insn, "sgeui") == 0) {
cur->func_unit = compare;
if ((unsigned)eval_operand(cur->op2,&breakpoint) >=
(unsigned)eval_operand(cur->op3,&breakpoint))
set_operand(cur->op1, 1,&breakpoint);
else
set_operand(cur->op1, 0,&breakpoint);
} else
if (strcmp(cur->insn, "sgei") == 0) {
cur->func_unit = compare;
if ((signed)eval_operand(cur->op2,&breakpoint) >= (signed)eval_operand(cur->op3,&breakpoint))
set_operand(cur->op1, 1,&breakpoint);
else
set_operand(cur->op1, 0,&breakpoint);
} else
if (strcmp(cur->insn, "sgti") == 0) {
cur->func_unit = compare;
if ((signed)eval_operand(cur->op2,&breakpoint) >
(signed)eval_operand(cur->op3,&breakpoint))
set_operand(cur->op1, 1,&breakpoint);
else
set_operand(cur->op1, 0,&breakpoint);
} else
if (strcmp(cur->insn, "slt") == 0) {
cur->func_unit = compare;
if ((signed)eval_operand(cur->op2,&breakpoint) <
(signed)eval_operand(cur->op3,&breakpoint))
set_operand(cur->op1, 1,&breakpoint);
else
set_operand(cur->op1, 0,&breakpoint);
} else
if (strcmp(cur->insn, "slti") == 0) {
cur->func_unit = compare;
if ((signed)eval_operand(cur->op2,&breakpoint) <
(signed)eval_operand(cur->op3,&breakpoint))
set_operand(cur->op1, 1,&breakpoint);
else
set_operand(cur->op1, 0,&breakpoint);
} else
if (strcmp(cur->insn, "sle") == 0) {
cur->func_unit = compare;
if ((signed)eval_operand(cur->op2,&breakpoint) <=
(signed)eval_operand(cur->op3,&breakpoint))
set_operand(cur->op1, 1,&breakpoint);
else
set_operand(cur->op1, 0,&breakpoint);
} else
if (strcmp(cur->insn, "slei") == 0) {
cur->func_unit = compare;
if ((signed)eval_operand(cur->op2,&breakpoint) <=
(signed)eval_operand(cur->op3,&breakpoint))
set_operand(cur->op1, 1,&breakpoint);
else
set_operand(cur->op1, 0,&breakpoint);
} else
if (strcmp(cur->insn, "sleui") == 0) {
cur->func_unit = compare;
if ((unsigned)eval_operand(cur->op2,&breakpoint) <=
(unsigned)eval_operand(cur->op3,&breakpoint))
set_operand(cur->op1, 1,&breakpoint);
else
set_operand(cur->op1, 0,&breakpoint);
} else
if (strcmp(cur->insn, "sleu") == 0) {
cur->func_unit = compare;
if ((unsigned)eval_operand(cur->op2,&breakpoint) <=
(unsigned)eval_operand(cur->op3,&breakpoint))
set_operand(cur->op1, 1,&breakpoint);
else
set_operand(cur->op1, 0,&breakpoint);
} else
if (strcmp(cur->insn, "simrdtsc") == 0) {
set_operand(cur->op1, cycles+loadcycles+storecycles+forwardingcycles,&breakpoint);
} else
if (strcmp(cur->insn, "simprintf") == 0) {
unsigned long stackaddr;
stackaddr = eval_reg(FRAME_REG);
simprintf(stackaddr, 0);
/* PRINTF("simprintf %x %x %x\n", stackaddr, fmtaddr, args); */
} else {
PRINTF("\nABORT: illegal opcode %s ", cur->insn);
PRINTF("at %.8lx\n", cur->insn_addr);
cont_run = 0;
}
 
/* Dynamic, dependency stats. */
adddstats(icomplet[0].insn, iqueue[0].insn, 1, check_depend());
 
/* Dynamic, functional units stats. */
addfstats(icomplet[0].func_unit, iqueue[0].func_unit, 1, check_depend());
 
/* Dynamic, single stats. */
addsstats(iqueue[0].insn, 1, 0);
 
if (cur->func_unit == store)
storecycles += 0;
 
if (cur->func_unit == load)
loadcycles += 0;
 
if (check_depend())
forwardingcycles += 0;
/* Pseudo multiple issue benchmark */
if ((multissue[cur->func_unit] == 0) || (check_depend())) {
int i;
for (i = 0; i < 20; i++)
multissue[i] = 9;
supercycles++;
multissue[arith] = 9;
multissue[store] = 9;
multissue[load] = 9;
}
multissue[cur->func_unit]--;
return;
}
 
void execute()
{
int i;
/* Here comes real execution someday... */
/* Instruction waits in completition buffer until retired. */
strcpy(icomplet[0].insn, iqueue[0].insn);
strcpy(icomplet[0].op1, iqueue[0].op1);
strcpy(icomplet[0].op2, iqueue[0].op2);
strcpy(icomplet[0].op3, iqueue[0].op3);
icomplet[0].func_unit = iqueue[0].func_unit;
icomplet[0].insn_addr = iqueue[0].insn_addr;
 
if (iqueue[0].dependdst == iqueue[0].op1)
icomplet[0].dependdst = icomplet[0].op1;
else
if (iqueue[0].dependdst == iqueue[0].op2)
icomplet[0].dependdst = icomplet[0].op2;
else
if (iqueue[0].dependdst == iqueue[0].op3)
icomplet[0].dependdst = icomplet[0].op3;
else
icomplet[0].dependdst = NULL;
 
if (iqueue[0].dependsrc1 == iqueue[0].op1)
icomplet[0].dependsrc1 = icomplet[0].op1;
else
if (iqueue[0].dependsrc1 == iqueue[0].op2)
icomplet[0].dependsrc1 = icomplet[0].op2;
else
if (iqueue[0].dependsrc1 == iqueue[0].op3)
icomplet[0].dependsrc1 = icomplet[0].op3;
else
icomplet[0].dependsrc1 = NULL;
 
if (iqueue[0].dependsrc2 == iqueue[0].op1)
icomplet[0].dependsrc2 = icomplet[0].op1;
else
if (iqueue[0].dependsrc2 == iqueue[0].op2)
icomplet[0].dependsrc2 = icomplet[0].op2;
else
if (iqueue[0].dependsrc2 == iqueue[0].op3)
icomplet[0].dependsrc2 = icomplet[0].op3;
else
icomplet[0].dependsrc2 = NULL;
/* History of execution */
for (i = HISTEXEC_LEN - 1; i; i--)
histexec[i] = histexec[i - 1];
histexec[0] = icomplet[0].insn_addr; /* add last insn */
return;
}
 
void dumpreg()
{
int i;
PRINTF("\n\nIQ[0]:");
dumpmemory(iqueue[0].insn_addr, iqueue[0].insn_addr + 4);
PRINTF(" (just executed)\tCYCLES: %u \nSuperscalar CYCLES: %u\n", cycles, supercycles);
PRINTF("Additional LOAD CYCLES: %u STORE CYCLES: %u\n", loadcycles, storecycles);
PRINTF("Additional RESULT FORWARDING CYCLES: %u\nPC:", forwardingcycles);
dumpmemory(pc, pc + 4);
PRINTF(" (next insn)");
for(i = 0; i < MAX_GPRS; i++) {
if (i % 4 == 0)
PRINTF("\n");
PRINTF("GPR%.2u: %.8lx ", i, reg[i]);
}
}
dlx Property changes : Added: svn:ignore ## -0,0 +1 ## +Makefile Index: or32/Makefile.in =================================================================== --- or32/Makefile.in (nonexistent) +++ or32/Makefile.in (revision 1765) @@ -0,0 +1,775 @@ +# Makefile.in generated by automake 1.10.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +# Makefile -- Makefile for OR32 dependent simulation +# +# Copyright (C) 1999 Damjan Lampret, lampret@opencores.org +# Copyright (C) 2008 Embecosm Limited +# +# Contributor Jeremy Bennett +# +# 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 . + + +VPATH = @srcdir@ +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@noinst_PROGRAMS = generate$(EXEEXT) +@DYNAMIC_EXECUTION_TRUE@noinst_PROGRAMS = dyngen$(EXEEXT) +subdir = cpu/or32 +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +LTLIBRARIES = $(noinst_LTLIBRARIES) +libarch_la_LIBADD = +am__libarch_la_SOURCES_DIST = execute.c or32.c common-i386.h \ + dyn32-defs.h dyngen.h dyn-rec.h i386-regs.h op-arith-op.h \ + op-comp-op.h op-extend-op.h op-ff1-op.h op-i386.h op-lwhb-op.h \ + op-mac-op.h op-mftspr-op.h op-support.h op-swhb-op.h \ + op-t-reg-mov-op.h rec-i386.h sched-i386.h simpl32-defs.h op.c \ + dyn-rec.c op-support.c +@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_FALSE@am_libarch_la_OBJECTS = \ +@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_FALSE@ execute.lo \ +@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_FALSE@ or32.lo +@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@am_libarch_la_OBJECTS = \ +@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@ execute.lo \ +@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@ or32.lo +@DYNAMIC_EXECUTION_TRUE@am_libarch_la_OBJECTS = execute.lo or32.lo \ +@DYNAMIC_EXECUTION_TRUE@ op.lo dyn-rec.lo op-support.lo +@DYNAMIC_EXECUTION_TRUE@nodist_libarch_la_OBJECTS = gen-ops.lo \ +@DYNAMIC_EXECUTION_TRUE@ gen-ops-gen.lo gen-ops-rel.lo +am__dist_EXTRA_libarch_la_SOURCES_DIST = insnset.c +libarch_la_OBJECTS = $(am_libarch_la_OBJECTS) \ + $(nodist_libarch_la_OBJECTS) +@DYNAMIC_EXECUTION_FALSE@am_libarch_la_rpath = +@DYNAMIC_EXECUTION_TRUE@am_libarch_la_rpath = +PROGRAMS = $(noinst_PROGRAMS) +am__dyngen_SOURCES_DIST = dyngen.c dyngen-i386.c dyngen-elf.c \ + common-i386.h dyn32-defs.h dyngen.h dyn-rec.h i386-regs.h \ + op-arith-op.h op-comp-op.h op-extend-op.h op-ff1-op.h \ + op-i386.h op-lwhb-op.h op-mac-op.h op-mftspr-op.h op-support.h \ + op-swhb-op.h op-t-reg-mov-op.h rec-i386.h sched-i386.h \ + simpl32-defs.h +@DYNAMIC_EXECUTION_TRUE@am_dyngen_OBJECTS = dyngen-dyngen.$(OBJEXT) \ +@DYNAMIC_EXECUTION_TRUE@ dyngen-dyngen-i386.$(OBJEXT) \ +@DYNAMIC_EXECUTION_TRUE@ dyngen-dyngen-elf.$(OBJEXT) +dyngen_OBJECTS = $(am_dyngen_OBJECTS) +dyngen_LDADD = $(LDADD) +dyngen_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=link $(CCLD) $(dyngen_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ + $(LDFLAGS) -o $@ +am__generate_SOURCES_DIST = or32.c generate.c common-i386.h \ + dyn32-defs.h dyngen.h dyn-rec.h i386-regs.h op-arith-op.h \ + op-comp-op.h op-extend-op.h op-ff1-op.h op-i386.h op-lwhb-op.h \ + op-mac-op.h op-mftspr-op.h op-support.h op-swhb-op.h \ + op-t-reg-mov-op.h rec-i386.h sched-i386.h simpl32-defs.h +@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@am_generate_OBJECTS = generate-or32.$(OBJEXT) \ +@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@ generate-generate.$(OBJEXT) +generate_OBJECTS = $(am_generate_OBJECTS) +generate_LDADD = $(LDADD) +generate_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=link $(CCLD) $(generate_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ + $(LDFLAGS) -o $@ +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +CCLD = $(CC) +LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ + $(LDFLAGS) -o $@ +SOURCES = $(libarch_la_SOURCES) $(nodist_libarch_la_SOURCES) \ + $(dist_EXTRA_libarch_la_SOURCES) $(dyngen_SOURCES) \ + $(generate_SOURCES) +DIST_SOURCES = $(am__libarch_la_SOURCES_DIST) \ + $(am__dist_EXTRA_libarch_la_SOURCES_DIST) \ + $(am__dyngen_SOURCES_DIST) $(am__generate_SOURCES_DIST) +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AR = @AR@ +ARFLAGS = @ARFLAGS@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BUILD_DIR = @BUILD_DIR@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CPU_ARCH = @CPU_ARCH@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEBUGFLAGS = @DEBUGFLAGS@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +ECHO = @ECHO@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +F77 = @F77@ +FFLAGS = @FFLAGS@ +GREP = @GREP@ +INCLUDES = @INCLUDES@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LDFLAGS = @LDFLAGS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LN_S = @LN_S@ +LOCAL_CFLAGS = @LOCAL_CFLAGS@ +LOCAL_DEFS = @LOCAL_DEFS@ +LOCAL_LDFLAGS = @LOCAL_LDFLAGS@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +MAKE_SHELL = @MAKE_SHELL@ +MKDIR_P = @MKDIR_P@ +OBJEXT = @OBJEXT@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +POW_LIB = @POW_LIB@ +RANLIB = @RANLIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +SUMVERSION = @SUMVERSION@ +TERMCAP_LIB = @TERMCAP_LIB@ +VERSION = @VERSION@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_F77 = @ac_ct_F77@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +@DYNAMIC_EXECUTION_FALSE@noinst_LTLIBRARIES = libarch.la +@DYNAMIC_EXECUTION_TRUE@noinst_LTLIBRARIES = libarch.la +@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_FALSE@libarch_la_SOURCES = execute.c \ +@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_FALSE@ or32.c \ +@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_FALSE@ common-i386.h \ +@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_FALSE@ dyn32-defs.h \ +@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_FALSE@ dyngen.h \ +@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_FALSE@ dyn-rec.h \ +@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_FALSE@ i386-regs.h \ +@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_FALSE@ op-arith-op.h \ +@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_FALSE@ op-comp-op.h \ +@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_FALSE@ op-extend-op.h \ +@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_FALSE@ op-ff1-op.h \ +@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_FALSE@ op-i386.h \ +@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_FALSE@ op-lwhb-op.h \ +@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_FALSE@ op-mac-op.h \ +@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_FALSE@ op-mftspr-op.h \ +@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_FALSE@ op-support.h \ +@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_FALSE@ op-swhb-op.h \ +@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_FALSE@ op-t-reg-mov-op.h \ +@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_FALSE@ rec-i386.h \ +@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_FALSE@ sched-i386.h \ +@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_FALSE@ simpl32-defs.h + +@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@libarch_la_SOURCES = execute.c \ +@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@ or32.c \ +@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@ common-i386.h \ +@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@ dyn32-defs.h \ +@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@ dyngen.h \ +@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@ dyn-rec.h \ +@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@ i386-regs.h \ +@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@ op-arith-op.h \ +@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@ op-comp-op.h \ +@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@ op-extend-op.h \ +@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@ op-ff1-op.h \ +@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@ op-i386.h \ +@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@ op-lwhb-op.h \ +@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@ op-mac-op.h \ +@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@ op-mftspr-op.h \ +@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@ op-support.h \ +@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@ op-swhb-op.h \ +@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@ op-t-reg-mov-op.h \ +@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@ rec-i386.h \ +@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@ sched-i386.h \ +@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@ simpl32-defs.h + +@DYNAMIC_EXECUTION_TRUE@libarch_la_SOURCES = execute.c \ +@DYNAMIC_EXECUTION_TRUE@ or32.c \ +@DYNAMIC_EXECUTION_TRUE@ op.c \ +@DYNAMIC_EXECUTION_TRUE@ dyn-rec.c \ +@DYNAMIC_EXECUTION_TRUE@ op-support.c \ +@DYNAMIC_EXECUTION_TRUE@ common-i386.h \ +@DYNAMIC_EXECUTION_TRUE@ dyn32-defs.h \ +@DYNAMIC_EXECUTION_TRUE@ dyngen.h \ +@DYNAMIC_EXECUTION_TRUE@ dyn-rec.h \ +@DYNAMIC_EXECUTION_TRUE@ i386-regs.h \ +@DYNAMIC_EXECUTION_TRUE@ op-arith-op.h \ +@DYNAMIC_EXECUTION_TRUE@ op-comp-op.h \ +@DYNAMIC_EXECUTION_TRUE@ op-extend-op.h \ +@DYNAMIC_EXECUTION_TRUE@ op-ff1-op.h \ +@DYNAMIC_EXECUTION_TRUE@ op-i386.h \ +@DYNAMIC_EXECUTION_TRUE@ op-lwhb-op.h \ +@DYNAMIC_EXECUTION_TRUE@ op-mac-op.h \ +@DYNAMIC_EXECUTION_TRUE@ op-mftspr-op.h \ +@DYNAMIC_EXECUTION_TRUE@ op-support.h \ +@DYNAMIC_EXECUTION_TRUE@ op-swhb-op.h \ +@DYNAMIC_EXECUTION_TRUE@ op-t-reg-mov-op.h \ +@DYNAMIC_EXECUTION_TRUE@ rec-i386.h \ +@DYNAMIC_EXECUTION_TRUE@ sched-i386.h \ +@DYNAMIC_EXECUTION_TRUE@ simpl32-defs.h + +@DYNAMIC_EXECUTION_TRUE@nodist_libarch_la_SOURCES = gen-ops.h \ +@DYNAMIC_EXECUTION_TRUE@ gen-ops.c \ +@DYNAMIC_EXECUTION_TRUE@ gen-ops-gen.c \ +@DYNAMIC_EXECUTION_TRUE@ gen-ops-rel.c + +@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@BUILT_SOURCES = execgen.c +@DYNAMIC_EXECUTION_TRUE@BUILT_SOURCES = gen-ops.h \ +@DYNAMIC_EXECUTION_TRUE@ gen-ops.c \ +@DYNAMIC_EXECUTION_TRUE@ gen-ops-gen.c \ +@DYNAMIC_EXECUTION_TRUE@ gen-ops-rel.c + +@DYNAMIC_EXECUTION_TRUE@dyngen_SOURCES = dyngen.c \ +@DYNAMIC_EXECUTION_TRUE@ dyngen-i386.c \ +@DYNAMIC_EXECUTION_TRUE@ dyngen-elf.c \ +@DYNAMIC_EXECUTION_TRUE@ common-i386.h \ +@DYNAMIC_EXECUTION_TRUE@ dyn32-defs.h \ +@DYNAMIC_EXECUTION_TRUE@ dyngen.h \ +@DYNAMIC_EXECUTION_TRUE@ dyn-rec.h \ +@DYNAMIC_EXECUTION_TRUE@ i386-regs.h \ +@DYNAMIC_EXECUTION_TRUE@ op-arith-op.h \ +@DYNAMIC_EXECUTION_TRUE@ op-comp-op.h \ +@DYNAMIC_EXECUTION_TRUE@ op-extend-op.h \ +@DYNAMIC_EXECUTION_TRUE@ op-ff1-op.h \ +@DYNAMIC_EXECUTION_TRUE@ op-i386.h \ +@DYNAMIC_EXECUTION_TRUE@ op-lwhb-op.h \ +@DYNAMIC_EXECUTION_TRUE@ op-mac-op.h \ +@DYNAMIC_EXECUTION_TRUE@ op-mftspr-op.h \ +@DYNAMIC_EXECUTION_TRUE@ op-support.h \ +@DYNAMIC_EXECUTION_TRUE@ op-swhb-op.h \ +@DYNAMIC_EXECUTION_TRUE@ op-t-reg-mov-op.h \ +@DYNAMIC_EXECUTION_TRUE@ rec-i386.h \ +@DYNAMIC_EXECUTION_TRUE@ sched-i386.h \ +@DYNAMIC_EXECUTION_TRUE@ simpl32-defs.h + +@DYNAMIC_EXECUTION_TRUE@dyngen_CFLAGS = $(AM_CFLAGS) +@DYNAMIC_EXECUTION_TRUE@OP_CFLAGS = -Wall -fomit-frame-pointer -fno-reorder-blocks -O2 +@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@EXTRA_DIST = insnset.c +@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@generate_SOURCES = or32.c \ +@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@ generate.c \ +@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@ common-i386.h \ +@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@ dyn32-defs.h \ +@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@ dyngen.h \ +@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@ dyn-rec.h \ +@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@ i386-regs.h \ +@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@ op-arith-op.h \ +@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@ op-comp-op.h \ +@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@ op-extend-op.h \ +@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@ op-ff1-op.h \ +@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@ op-i386.h \ +@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@ op-lwhb-op.h \ +@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@ op-mac-op.h \ +@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@ op-mftspr-op.h \ +@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@ op-support.h \ +@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@ op-swhb-op.h \ +@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@ op-t-reg-mov-op.h \ +@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@ rec-i386.h \ +@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@ sched-i386.h \ +@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@ simpl32-defs.h + +@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@generate_CFLAGS = $(AM_CFLAGS) +@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_FALSE@dist_EXTRA_libarch_la_SOURCES = insnset.c + +# If the simulator was first built without --enable-simple and then with it, +# then also remove these two files +CLEANFILES = execgen.c \ + generate \ + gen-ops.c \ + gen-ops.h \ + gen-ops-rel.c \ + gen-ops-gen.c + +all: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \ + && exit 0; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu cpu/or32/Makefile'; \ + cd $(top_srcdir) && \ + $(AUTOMAKE) --gnu cpu/or32/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +clean-noinstLTLIBRARIES: + -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) + @list='$(noinst_LTLIBRARIES)'; for p in $$list; do \ + dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \ + test "$$dir" != "$$p" || dir=.; \ + echo "rm -f \"$${dir}/so_locations\""; \ + rm -f "$${dir}/so_locations"; \ + done +libarch.la: $(libarch_la_OBJECTS) $(libarch_la_DEPENDENCIES) + $(LINK) $(am_libarch_la_rpath) $(libarch_la_OBJECTS) $(libarch_la_LIBADD) $(LIBS) + +clean-noinstPROGRAMS: + @list='$(noinst_PROGRAMS)'; for p in $$list; do \ + f=`echo $$p|sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f $$p $$f"; \ + rm -f $$p $$f ; \ + done +dyngen$(EXEEXT): $(dyngen_OBJECTS) $(dyngen_DEPENDENCIES) + @rm -f dyngen$(EXEEXT) + $(dyngen_LINK) $(dyngen_OBJECTS) $(dyngen_LDADD) $(LIBS) +generate$(EXEEXT): $(generate_OBJECTS) $(generate_DEPENDENCIES) + @rm -f generate$(EXEEXT) + $(generate_LINK) $(generate_OBJECTS) $(generate_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dyn-rec.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dyngen-dyngen-elf.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dyngen-dyngen-i386.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dyngen-dyngen.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/execute.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gen-ops-gen.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gen-ops-rel.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gen-ops.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/generate-generate.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/generate-or32.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/insnset.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/op-support.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/op.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/or32.Plo@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c $< + +.c.obj: +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $< + +dyngen-dyngen.o: dyngen.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(dyngen_CFLAGS) $(CFLAGS) -MT dyngen-dyngen.o -MD -MP -MF $(DEPDIR)/dyngen-dyngen.Tpo -c -o dyngen-dyngen.o `test -f 'dyngen.c' || echo '$(srcdir)/'`dyngen.c +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/dyngen-dyngen.Tpo $(DEPDIR)/dyngen-dyngen.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='dyngen.c' object='dyngen-dyngen.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(dyngen_CFLAGS) $(CFLAGS) -c -o dyngen-dyngen.o `test -f 'dyngen.c' || echo '$(srcdir)/'`dyngen.c + +dyngen-dyngen.obj: dyngen.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(dyngen_CFLAGS) $(CFLAGS) -MT dyngen-dyngen.obj -MD -MP -MF $(DEPDIR)/dyngen-dyngen.Tpo -c -o dyngen-dyngen.obj `if test -f 'dyngen.c'; then $(CYGPATH_W) 'dyngen.c'; else $(CYGPATH_W) '$(srcdir)/dyngen.c'; fi` +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/dyngen-dyngen.Tpo $(DEPDIR)/dyngen-dyngen.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='dyngen.c' object='dyngen-dyngen.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(dyngen_CFLAGS) $(CFLAGS) -c -o dyngen-dyngen.obj `if test -f 'dyngen.c'; then $(CYGPATH_W) 'dyngen.c'; else $(CYGPATH_W) '$(srcdir)/dyngen.c'; fi` + +dyngen-dyngen-i386.o: dyngen-i386.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(dyngen_CFLAGS) $(CFLAGS) -MT dyngen-dyngen-i386.o -MD -MP -MF $(DEPDIR)/dyngen-dyngen-i386.Tpo -c -o dyngen-dyngen-i386.o `test -f 'dyngen-i386.c' || echo '$(srcdir)/'`dyngen-i386.c +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/dyngen-dyngen-i386.Tpo $(DEPDIR)/dyngen-dyngen-i386.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='dyngen-i386.c' object='dyngen-dyngen-i386.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(dyngen_CFLAGS) $(CFLAGS) -c -o dyngen-dyngen-i386.o `test -f 'dyngen-i386.c' || echo '$(srcdir)/'`dyngen-i386.c + +dyngen-dyngen-i386.obj: dyngen-i386.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(dyngen_CFLAGS) $(CFLAGS) -MT dyngen-dyngen-i386.obj -MD -MP -MF $(DEPDIR)/dyngen-dyngen-i386.Tpo -c -o dyngen-dyngen-i386.obj `if test -f 'dyngen-i386.c'; then $(CYGPATH_W) 'dyngen-i386.c'; else $(CYGPATH_W) '$(srcdir)/dyngen-i386.c'; fi` +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/dyngen-dyngen-i386.Tpo $(DEPDIR)/dyngen-dyngen-i386.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='dyngen-i386.c' object='dyngen-dyngen-i386.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(dyngen_CFLAGS) $(CFLAGS) -c -o dyngen-dyngen-i386.obj `if test -f 'dyngen-i386.c'; then $(CYGPATH_W) 'dyngen-i386.c'; else $(CYGPATH_W) '$(srcdir)/dyngen-i386.c'; fi` + +dyngen-dyngen-elf.o: dyngen-elf.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(dyngen_CFLAGS) $(CFLAGS) -MT dyngen-dyngen-elf.o -MD -MP -MF $(DEPDIR)/dyngen-dyngen-elf.Tpo -c -o dyngen-dyngen-elf.o `test -f 'dyngen-elf.c' || echo '$(srcdir)/'`dyngen-elf.c +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/dyngen-dyngen-elf.Tpo $(DEPDIR)/dyngen-dyngen-elf.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='dyngen-elf.c' object='dyngen-dyngen-elf.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(dyngen_CFLAGS) $(CFLAGS) -c -o dyngen-dyngen-elf.o `test -f 'dyngen-elf.c' || echo '$(srcdir)/'`dyngen-elf.c + +dyngen-dyngen-elf.obj: dyngen-elf.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(dyngen_CFLAGS) $(CFLAGS) -MT dyngen-dyngen-elf.obj -MD -MP -MF $(DEPDIR)/dyngen-dyngen-elf.Tpo -c -o dyngen-dyngen-elf.obj `if test -f 'dyngen-elf.c'; then $(CYGPATH_W) 'dyngen-elf.c'; else $(CYGPATH_W) '$(srcdir)/dyngen-elf.c'; fi` +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/dyngen-dyngen-elf.Tpo $(DEPDIR)/dyngen-dyngen-elf.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='dyngen-elf.c' object='dyngen-dyngen-elf.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(dyngen_CFLAGS) $(CFLAGS) -c -o dyngen-dyngen-elf.obj `if test -f 'dyngen-elf.c'; then $(CYGPATH_W) 'dyngen-elf.c'; else $(CYGPATH_W) '$(srcdir)/dyngen-elf.c'; fi` + +generate-or32.o: or32.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(generate_CFLAGS) $(CFLAGS) -MT generate-or32.o -MD -MP -MF $(DEPDIR)/generate-or32.Tpo -c -o generate-or32.o `test -f 'or32.c' || echo '$(srcdir)/'`or32.c +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/generate-or32.Tpo $(DEPDIR)/generate-or32.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='or32.c' object='generate-or32.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(generate_CFLAGS) $(CFLAGS) -c -o generate-or32.o `test -f 'or32.c' || echo '$(srcdir)/'`or32.c + +generate-or32.obj: or32.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(generate_CFLAGS) $(CFLAGS) -MT generate-or32.obj -MD -MP -MF $(DEPDIR)/generate-or32.Tpo -c -o generate-or32.obj `if test -f 'or32.c'; then $(CYGPATH_W) 'or32.c'; else $(CYGPATH_W) '$(srcdir)/or32.c'; fi` +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/generate-or32.Tpo $(DEPDIR)/generate-or32.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='or32.c' object='generate-or32.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(generate_CFLAGS) $(CFLAGS) -c -o generate-or32.obj `if test -f 'or32.c'; then $(CYGPATH_W) 'or32.c'; else $(CYGPATH_W) '$(srcdir)/or32.c'; fi` + +generate-generate.o: generate.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(generate_CFLAGS) $(CFLAGS) -MT generate-generate.o -MD -MP -MF $(DEPDIR)/generate-generate.Tpo -c -o generate-generate.o `test -f 'generate.c' || echo '$(srcdir)/'`generate.c +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/generate-generate.Tpo $(DEPDIR)/generate-generate.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='generate.c' object='generate-generate.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(generate_CFLAGS) $(CFLAGS) -c -o generate-generate.o `test -f 'generate.c' || echo '$(srcdir)/'`generate.c + +generate-generate.obj: generate.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(generate_CFLAGS) $(CFLAGS) -MT generate-generate.obj -MD -MP -MF $(DEPDIR)/generate-generate.Tpo -c -o generate-generate.obj `if test -f 'generate.c'; then $(CYGPATH_W) 'generate.c'; else $(CYGPATH_W) '$(srcdir)/generate.c'; fi` +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/generate-generate.Tpo $(DEPDIR)/generate-generate.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='generate.c' object='generate-generate.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(generate_CFLAGS) $(CFLAGS) -c -o generate-generate.obj `if test -f 'generate.c'; then $(CYGPATH_W) 'generate.c'; else $(CYGPATH_W) '$(srcdir)/generate.c'; fi` + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonemtpy = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$tags $$unique; \ + fi +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + test -z "$(CTAGS_ARGS)$$tags$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$tags $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && cd $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) $$here + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ + fi; \ + cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ + else \ + test -f $(distdir)/$$file \ + || cp -p $$d/$$file $(distdir)/$$file \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) check-am +all-am: Makefile $(LTLIBRARIES) $(PROGRAMS) +installdirs: +install: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." + -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES) +clean: clean-am + +clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ + clean-noinstPROGRAMS mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-exec-am: + +install-html: install-html-am + +install-info: install-info-am + +install-man: + +install-pdf: install-pdf-am + +install-ps: install-ps-am + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ + clean-libtool clean-noinstLTLIBRARIES clean-noinstPROGRAMS \ + ctags distclean distclean-compile distclean-generic \ + distclean-libtool distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am install-data \ + install-data-am install-dvi install-dvi-am install-exec \ + install-exec-am install-html install-html-am install-info \ + install-info-am install-man install-pdf install-pdf-am \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags uninstall uninstall-am + + +@DYNAMIC_EXECUTION_TRUE@gen-ops.h gen-ops.c gen-ops-gen.c gen-ops-rel.c: dyngen$(EXEEXT) op-tmp.o +@DYNAMIC_EXECUTION_TRUE@ ./dyngen$(EXEEXT) op-tmp.o gen-ops.c gen-ops-gen.c gen-ops-rel.c gen-ops.h + +@DYNAMIC_EXECUTION_TRUE@op-tmp.o: op.c op-t-reg-mov-op.h op-i386.h op-arith-op.h op-comp-op.h \ +@DYNAMIC_EXECUTION_TRUE@ op-extend-op.h op-ff1-op.h op-mac-op.h op-mftspr-op.h op-lwhb-op.h \ +@DYNAMIC_EXECUTION_TRUE@ op-swhb-op.h +@DYNAMIC_EXECUTION_TRUE@ $(CC) $(INCLUDES) -I$(top_builddir) $(OP_CFLAGS) -o $@ -c $< + +@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@execgen.c: generate$(EXEEXT) insnset.c +@DYNAMIC_EXECUTION_FALSE@@GENERATE_NEEDED_TRUE@ ./generate$(EXEEXT) $(srcdir)/insnset.c execgen.c +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: Index: or32/op-mftspr-op.h =================================================================== --- or32/op-mftspr-op.h (nonexistent) +++ or32/op-mftspr-op.h (revision 1765) @@ -0,0 +1,78 @@ +/* op-mftspr-op.h -- Micro operations template for the m{f,t}spr operations + + 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. */ + + +#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 Index: or32/op.c =================================================================== --- or32/op.c (nonexistent) +++ or32/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: or32/dyn32-defs.h =================================================================== --- or32/dyn32-defs.h (nonexistent) +++ or32/dyn32-defs.h (revision 1765) @@ -0,0 +1,139 @@ +/* dyn32-defs.h -- Definitions for the dynamic execution model + + Copyright (C) 2005 György `nog' Jeney, nog@sdf.lonestar.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 . */ + +/* This program is commented throughout in a fashion suitable for processing + with Doxygen. */ + + +#ifndef DYN32_DEFS__H +#define DYN32_DEFS__H + + +/* Package includes */ +#include "arch.h" + + +struct op_queue { + unsigned int num_ops; + unsigned int ops_len; + unsigned int *ops; + unsigned int num_ops_param; + unsigned int ops_param_len; + unsigned int *ops_param; + unsigned int jump_local; /* Parameter index that holds the location of the jump */ + oraddr_t jump_local_loc; /* Location to jump to (relative to start of page */ + unsigned int not_jump_loc; /* Location to jump if not jumping (l.bf/l.bnf) */ + int xref; /* Is this location cross referenced? */ + oraddr_t insn_addr; /* Physical address of the instruction */ + unsigned int reg_t[3]; /* Which registers are in the temporaries (after the instruction)? */ + unsigned int tflags[3]; + + int insn_index; + unsigned int param_type[5]; /* opd->type */ + orreg_t param[5]; /* Value of operand */ + unsigned int param_num; /* Number of operands */ + uint32_t insn; /* Instruction word */ + + struct op_queue *prev; + struct op_queue *next; +}; + +void gen_l_add PARAMS((struct op_queue *, int *, int)); +void gen_l_addc PARAMS((struct op_queue *, int *, int)); +void gen_l_and PARAMS((struct op_queue *, int *, int)); +void gen_l_bf PARAMS((struct op_queue *, int *, int)); +void gen_l_bnf PARAMS((struct op_queue *, int *, int)); +void gen_l_cmov PARAMS((struct op_queue *, int *, int)); +void gen_l_cust1 PARAMS((struct op_queue *, int *, int)); +void gen_l_cust2 PARAMS((struct op_queue *, int *, int)); +void gen_l_cust3 PARAMS((struct op_queue *, int *, int)); +void gen_l_cust4 PARAMS((struct op_queue *, int *, int)); +void gen_l_div PARAMS((struct op_queue *, int *, int)); +void gen_l_divu PARAMS((struct op_queue *, int *, int)); +void gen_l_extbs PARAMS((struct op_queue *, int *, int)); +void gen_l_extbz PARAMS((struct op_queue *, int *, int)); +void gen_l_exths PARAMS((struct op_queue *, int *, int)); +void gen_l_exthz PARAMS((struct op_queue *, int *, int)); +void gen_l_extws PARAMS((struct op_queue *, int *, int)); +void gen_l_extwz PARAMS((struct op_queue *, int *, int)); +void gen_l_ff1 PARAMS((struct op_queue *, int *, int)); +void gen_l_j PARAMS((struct op_queue *, int *, int)); +void gen_l_jal PARAMS((struct op_queue *, int *, int)); +void gen_l_jr PARAMS((struct op_queue *, int *, int)); +void gen_l_jalr PARAMS((struct op_queue *, int *, int)); +void gen_l_lbs PARAMS((struct op_queue *, int *, int)); +void gen_l_lbz PARAMS((struct op_queue *, int *, int)); +void gen_l_lhs PARAMS((struct op_queue *, int *, int)); +void gen_l_lhz PARAMS((struct op_queue *, int *, int)); +void gen_l_lws PARAMS((struct op_queue *, int *, int)); +void gen_l_lwz PARAMS((struct op_queue *, int *, int)); +void gen_l_mac PARAMS((struct op_queue *, int *, int)); +void gen_l_macrc PARAMS((struct op_queue *, int *, int)); +void gen_l_mfspr PARAMS((struct op_queue *, int *, int)); +void gen_l_movhi PARAMS((struct op_queue *, int *, int)); +void gen_l_msb PARAMS((struct op_queue *, int *, int)); +void gen_l_mtspr PARAMS((struct op_queue *, int *, int)); +void gen_l_mul PARAMS((struct op_queue *, int *, int)); +void gen_l_mulu PARAMS((struct op_queue *, int *, int)); +void gen_l_nop PARAMS((struct op_queue *, int *, int)); +void gen_l_or PARAMS((struct op_queue *, int *, int)); +void gen_l_rfe PARAMS((struct op_queue *, int *, int)); +void gen_l_sb PARAMS((struct op_queue *, int *, int)); +void gen_l_sh PARAMS((struct op_queue *, int *, int)); +void gen_l_sw PARAMS((struct op_queue *, int *, int)); +void gen_l_sfeq PARAMS((struct op_queue *, int *, int)); +void gen_l_sfges PARAMS((struct op_queue *, int *, int)); +void gen_l_sfgeu PARAMS((struct op_queue *, int *, int)); +void gen_l_sfgts PARAMS((struct op_queue *, int *, int)); +void gen_l_sfgtu PARAMS((struct op_queue *, int *, int)); +void gen_l_sfles PARAMS((struct op_queue *, int *, int)); +void gen_l_sfleu PARAMS((struct op_queue *, int *, int)); +void gen_l_sflts PARAMS((struct op_queue *, int *, int)); +void gen_l_sfltu PARAMS((struct op_queue *, int *, int)); +void gen_l_sfne PARAMS((struct op_queue *, int *, int)); +void gen_l_sll PARAMS((struct op_queue *, int *, int)); +void gen_l_sra PARAMS((struct op_queue *, int *, int)); +void gen_l_srl PARAMS((struct op_queue *, int *, int)); +void gen_l_sub PARAMS((struct op_queue *, int *, int)); +void gen_l_sys PARAMS((struct op_queue *, int *, int)); +void gen_l_trap PARAMS((struct op_queue *, int *, int)); +void gen_l_xor PARAMS((struct op_queue *, int *, int)); +void gen_l_invalid PARAMS((struct op_queue *, int *, int)); + +void gen_lf_add_s PARAMS((struct op_queue *, int *, int)); +void gen_lf_div_s PARAMS((struct op_queue *, int *, int)); +void gen_lf_ftoi_s PARAMS((struct op_queue *, int *, int)); +void gen_lf_itof_s PARAMS((struct op_queue *, int *, int)); +void gen_lf_madd_s PARAMS((struct op_queue *, int *, int)); +void gen_lf_mul_s PARAMS((struct op_queue *, int *, int)); +void gen_lf_rem_s PARAMS((struct op_queue *, int *, int)); +void gen_lf_sfeq_s PARAMS((struct op_queue *, int *, int)); +void gen_lf_sfge_s PARAMS((struct op_queue *, int *, int)); +void gen_lf_sfgt_s PARAMS((struct op_queue *, int *, int)); +void gen_lf_sfle_s PARAMS((struct op_queue *, int *, int)); +void gen_lf_sflt_s PARAMS((struct op_queue *, int *, int)); +void gen_lf_sfne_s PARAMS((struct op_queue *, int *, int)); +void gen_lf_sub_s PARAMS((struct op_queue *, int *, int)); +void l_none(struct op_queue *opq, int *param_t, int delay_slot); + +#endif /* DYN32_DEFS__H */ + Index: or32/op-support.c =================================================================== --- or32/op-support.c (nonexistent) +++ or32/op-support.c (revision 1765) @@ -0,0 +1,114 @@ +/* op-support.c -- Support routines for micro 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. */ + + +#include + +#include "config.h" + +#ifdef HAVE_INTTYPES_H +#include +#endif + +#include "port.h" +#include "arch.h" +#include "opcode/or32.h" +#include "sim-config.h" +#include "spr-defs.h" +#include "except.h" +#include "immu.h" +#include "abstract.h" +#include "execute.h" +#include "sched.h" +#include "i386-regs.h" +#include "dyn-rec.h" +#include "op-support.h" +#include "simprintf.h" + + +/* Stuff that is really a `micro' operation but is rather big (or for some other + * reason like calling exit()) */ + +void op_support_nop_exit(void) +{ + PRINTF("exit(%"PRIdREG")\n", cpu_state.reg[3]); + fprintf(stderr, "@reset : cycles %lld, insn #%lld\n", + runtime.sim.reset_cycles, runtime.cpu.reset_instructions); + fprintf(stderr, "@exit : cycles %lld, insn #%lld\n", runtime.sim.cycles, + runtime.cpu.instructions); + fprintf(stderr, " diff : cycles %lld, insn #%lld\n", + runtime.sim.cycles - runtime.sim.reset_cycles, + runtime.cpu.instructions - runtime.cpu.reset_instructions); + /* FIXME: Implement emulation of a stalled cpu + if (config.debug.gdb_enabled) + set_stall_state (1); + else { + handle_sim_command(); + sim_done(); + } + */ + exit(0); +} + +void op_support_nop_reset(void) +{ + PRINTF("****************** counters reset ******************\n"); + PRINTF("cycles %lld, insn #%lld\n", runtime.sim.cycles, runtime.cpu.instructions); + PRINTF("****************** counters reset ******************\n"); + runtime.sim.reset_cycles = runtime.sim.cycles; + runtime.cpu.reset_instructions = runtime.cpu.instructions; +} + +void op_support_nop_printf(void) +{ + simprintf(cpu_state.reg[4], cpu_state.reg[3]); +} + +void op_support_nop_report(void) +{ + PRINTF("report(0x%"PRIxREG");\n", cpu_state.reg[3]); +} + +void op_support_nop_report_imm(int imm) +{ + PRINTF("report %i (0x%"PRIxREG");\n", imm, cpu_state.reg[3]); +} + +/* Handles a jump */ +/* addr is a VIRTUAL address */ +/* NOTE: We can't use env since this code is compiled like the rest of the + * simulator (most likely without -fomit-frame-pointer) and thus env will point + * to some bogus value. */ +void do_jump(oraddr_t addr) +{ + cpu_state.pc = addr; + longjmp(cpu_state.excpt_loc, 0); +} + +/* Wrapper around analysis() that contains all the recompiler specific stuff */ +void op_support_analysis(void) +{ + oraddr_t off = (cpu_state.pc & immu_state->page_offset_mask) >> 2; + runtime.cpu.instructions++; + cpu_state.iqueue.insn_index = cpu_state.curr_page->insn_indexs[off]; + cpu_state.iqueue.insn = cpu_state.curr_page->insns[off]; + cpu_state.iqueue.insn_addr = cpu_state.pc; + analysis(&cpu_state.iqueue); +} + Index: or32/op-swhb-op.h =================================================================== --- or32/op-swhb-op.h (nonexistent) +++ or32/op-swhb-op.h (revision 1765) @@ -0,0 +1,57 @@ +/* op-swhb-op.h -- Micro operations template for store operations + + 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. */ + +/* FIXME: Do something with breakpoint */ + + +#ifdef OP_2T +__or_dynop void glue (glue (op_, S_OP_NAME), T) (void) +{ + int breakpoint; + S_FUNC (T0 + OP_PARAM1, T1, &breakpoint); +} +#endif + +#ifdef OP_1T +__or_dynop void glue (glue (glue (op_, S_OP_NAME), _imm), T) (void) +{ + int breakpoint; + S_FUNC (OP_PARAM1, T0, &breakpoint); +} + +__or_dynop void glue (glue (glue (op_, S_OP_NAME), _clear), T) (void) +{ + int breakpoint; + S_FUNC (T0 + OP_PARAM1, 0, &breakpoint); +} +#endif + +#if !defined(OP_1T) && !defined(OP_2T) +__or_dynop void glue (glue (op_, S_OP_NAME), _clear_imm) (void) +{ + int breakpoint; + S_FUNC (OP_PARAM1, 0, &breakpoint); +} +#endif Index: or32/dyn-rec.c =================================================================== --- or32/dyn-rec.c (nonexistent) +++ or32/dyn-rec.c (revision 1765) @@ -0,0 +1,2451 @@ +/* dyn-rec.c -- Dynamic recompiler implementation for or32 + 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 +#include + +#include "config.h" + +#ifdef HAVE_INTTYPES_H +#include +#endif + +#include "port.h" +#include "arch.h" +#include "immu.h" +#include "abstract.h" +#include "opcode/or32.h" +#include "spr-defs.h" +#include "execute.h" +#include "except.h" +#include "spr-defs.h" +#include "sim-config.h" +#include "sched.h" +#include "i386-regs.h" +#include "def-op-t.h" +#include "dyn-rec.h" +#include "gen-ops.h" +#include "op-support.h" +#include "toplevel-support.h" + + +/* NOTE: All openrisc (or) addresses in this file are *PHYSICAL* addresses */ + +/* FIXME: Optimise sorted list adding */ + +typedef void (*generic_gen_op)(struct op_queue *opq, int end); +typedef void (*imm_gen_op)(struct op_queue *opq, int end, uorreg_t imm); + +void gen_l_invalid(struct op_queue *opq, int param_t[3], int delay_slot); + +/* ttg->temporary to gpr */ +DEF_GPR_OP(generic_gen_op, gen_op_move_gpr_t, gen_op_ttg_gpr); +/* gtt->gpr to temporary */ +DEF_GPR_OP(generic_gen_op, gen_op_move_t_gpr, gen_op_gtt_gpr); + +DEF_1T_OP(imm_gen_op, calc_insn_ea_table, gen_op_calc_insn_ea); + +/* Linker stubs. This will allow the linker to link in op.o. The relocations + * that the linker does for these will be irrelevent anyway, since we patch the + * relocations during recompilation. */ +uorreg_t __op_param1; +uorreg_t __op_param2; +uorreg_t __op_param3; + +/* The number of bytes that a dynamicly recompiled page should be enlarged by */ +#define RECED_PAGE_ENLARGE_BY 51200 + +/* The number of entries that the micro operations array in op_queue should be + * enlarged by */ +#define OPS_ENLARGE_BY 5 + +#define T_NONE (-1) + +/* Temporary is used as a source operand */ +#define TFLAG_SRC 1 +/* Temporary is used as a destination operand */ +#define TFLAG_DST 2 +/* Temporary has been saved to permanent storage */ +#define TFLAG_SAVED 4 +/* Temporary contains the value of the register before the instruction execution + * occurs (either by an explicit reg->t move or implicitly being left over from + * a previous instruction) */ +#define TFLAG_SOURCED 8 + +/* FIXME: Put this into some header */ +extern int do_stats; + +static int sigsegv_state = 0; +static void *sigsegv_addr = NULL; + +void dyn_ret_stack_prot(void); + +void dyn_sigsegv_debug(int u, siginfo_t *siginf, void *dat) +{ + struct dyn_page *dp; + FILE *f; + char filen[18]; /* 18 == strlen("or_page.%08x") + 1 */ + int i; + struct sigcontext *sigc = dat; + + if(!sigsegv_state) { + sigsegv_addr = siginf->si_addr; + } else { + fprintf(stderr, "Nested SIGSEGV occured, dumping next chuck of info\n"); + sigsegv_state++; + } + + /* First dump all the data that does not need dereferenceing to get */ + switch(sigsegv_state) { + case 0: + fflush(stderr); + fprintf(stderr, "Segmentation fault on acces to %p at 0x%08lx, (or address: 0x%"PRIxADDR")\n\n", + sigsegv_addr, sigc->eip, cpu_state.pc); + sigsegv_state++; + case 1: + /* Run through the recompiled pages, dumping them to disk as we go */ + for(i = 0; i < (2 << (32 - immu_state->pagesize_log2)); i++) { + dp = cpu_state.dyn_pages[i]; + if(!dp) + continue; + fprintf(stderr, "Dumping%s page 0x%"PRIxADDR" recompiled to %p (len: %u) to disk\n", + dp->dirty ? " dirty" : "", dp->or_page, dp->host_page, + dp->host_len); + fflush(stdout); + + sprintf(filen, "or_page.%"PRIxADDR, dp->or_page); + if(!(f = fopen(filen, "w"))) { + fprintf(stderr, "Unable to open %s to dump the recompiled page to: %s\n", + filen, strerror(errno)); + continue; + } + if(fwrite(dp->host_page, dp->host_len, 1, f) < 1) + fprintf(stderr, "Unable to write recompiled data to file: %s\n", + strerror(errno)); + + fclose(f); + } + sigsegv_state++; + case 2: + sim_done(); + } +} + +struct dyn_page *new_dp(oraddr_t page) +{ + struct dyn_page *dp = malloc(sizeof(struct dyn_page)); + dp->or_page = IADDR_PAGE(page); + + dp->locs = malloc(sizeof(void *) * (immu_state->pagesize / 4)); + + dp->host_len = 0; + dp->host_page = NULL; + dp->dirty = 1; + + if(do_stats) { + dp->insns = malloc(immu_state->pagesize); + dp->insn_indexs = malloc(sizeof(unsigned int) * (immu_state->pagesize / 4)); + } + + cpu_state.dyn_pages[dp->or_page >> immu_state->pagesize_log2] = dp; + return dp; +} + +void dyn_main(void) +{ + struct dyn_page *target_dp; + oraddr_t phys_page; + + setjmp(cpu_state.excpt_loc); + for(;;) { + phys_page = immu_translate(cpu_state.pc); + +/* + printf("Recompiled code jumping out to %"PRIxADDR" from %"PRIxADDR"\n", + phys_page, cpu_state.sprs[SPR_PPC] - 4); +*/ + + /* immu_translate() adds the hit delay to runtime.sim.mem_cycles but we add + * it to the cycles when the instruction is executed so if we don't reset it + * now it will produce wrong results */ + runtime.sim.mem_cycles = 0; + + target_dp = cpu_state.dyn_pages[phys_page >> immu_state->pagesize_log2]; + + if(!target_dp) + target_dp = new_dp(phys_page); + + /* Since writes to the 0x0-0xff range do not dirtyfy a page recompile the + * 0x0 page if the jump is to that location */ + if(phys_page < 0x100) + target_dp->dirty = 1; + + if(target_dp->dirty) + recompile_page(target_dp); + + cpu_state.curr_page = target_dp; + + /* FIXME: If the page is backed by more than one type of memory, this will + * produce wrong results */ + cpu_state.cycles_dec = target_dp->delayr; + if(cpu_state.sprs[SPR_SR] & SPR_SR_IME) + /* Add the mmu hit delay to the cycle counter */ + cpu_state.cycles_dec -= immu_state->hitdelay; + + /* FIXME: ebp, ebx, esi and edi are expected to be preserved across function + * calls but the recompiled code trashes them... */ + enter_dyn_code(phys_page, target_dp); + } +} + +static void immu_retranslate(void *dat) +{ + int got_en_dis = (int)dat; + immu_translate(cpu_state.pc); + runtime.sim.mem_cycles = 0; + + /* Only update the cycle decrementer if the mmu got enabled or disabled */ + if(got_en_dis == IMMU_GOT_ENABLED) + /* Add the mmu hit delay to the cycle counter */ + cpu_state.cycles_dec = cpu_state.curr_page->delayr - immu_state->hitdelay; + else if(got_en_dis == IMMU_GOT_DISABLED) + cpu_state.cycles_dec = cpu_state.curr_page->delayr; +} + +/* This is called whenever the immu is either enabled/disabled or reconfigured + * while enabled. This checks if an itlb miss would occour and updates the immu + * hit delay counter */ +void recheck_immu(int got_en_dis) +{ + oraddr_t addr; + + if(cpu_state.delay_insn) + addr = cpu_state.pc_delay; + else + addr = cpu_state.pc + 4; + + if(IADDR_PAGE(cpu_state.pc) == IADDR_PAGE(addr)) + /* Schedule a job to do immu_translate() */ + SCHED_ADD(immu_retranslate, (void *)got_en_dis, 0); +} + +/* Runs the scheduler. Called from except_handler (and dirtyfy_page below) */ +void run_sched_out_of_line(void) +{ + oraddr_t off = (cpu_state.pc & immu_state->page_offset_mask) >> 2; + + if(do_stats) { + cpu_state.iqueue.insn_addr = cpu_state.pc; + cpu_state.iqueue.insn = cpu_state.curr_page->insns[off]; + cpu_state.iqueue.insn_index = cpu_state.curr_page->insn_indexs[off]; + runtime.cpu.instructions++; + analysis(&cpu_state.iqueue); + } + + /* Run the scheduler */ + scheduler.job_queue->time += cpu_state.cycles_dec; + runtime.sim.cycles -= cpu_state.cycles_dec; + + op_join_mem_cycles(); + if(scheduler.job_queue->time <= 0) + do_scheduler(); +} + +/* Signals a page as dirty */ +static void dirtyfy_page(struct dyn_page *dp) +{ + oraddr_t check; + + printf("Dirtyfying page 0x%"PRIxADDR"\n", dp->or_page); + + dp->dirty = 1; + + /* If the execution is currently in the page that was touched then recompile + * it now and jump back to the point of execution */ + check = cpu_state.delay_insn ? cpu_state.pc_delay : cpu_state.pc + 4; + if(IADDR_PAGE(check) == dp->or_page) { + run_sched_out_of_line(); + recompile_page(dp); + + cpu_state.delay_insn = 0; + + /* Jump out to the next instruction */ + do_jump(check); + } +} + +/* Checks to see if a write happened to a recompiled page. If so marks it as + * dirty */ +void dyn_checkwrite(oraddr_t addr) +{ + /* FIXME: Do this with mprotect() */ + struct dyn_page *dp = cpu_state.dyn_pages[addr >> immu_state->pagesize_log2]; + + /* Since the locations 0x0-0xff are nearly always written to in an exception + * handler, ignore any writes to these locations. If code ends up jumping + * out there, we'll recompile when the jump actually happens. */ + if((addr > 0x100) && dp && !dp->dirty) + dirtyfy_page(dp); +} + +/* Moves the temprary t to its permanent storage if it has been used as a + * destination register */ +static void ship_t_out(struct op_queue *opq, unsigned int t) +{ + unsigned int gpr = opq->reg_t[t]; + + for(; opq; opq = opq->prev) { + if(opq->reg_t[t] != gpr) + return; + if((opq->tflags[t] & TFLAG_DST) && !(opq->tflags[t] & TFLAG_SAVED)) { + opq->tflags[t] |= TFLAG_SAVED; + + /* FIXME: Check if this is still neccesary */ + /* Before takeing the temporaries out, temporarily remove the op_do_sched + * operation such that dyn_page->ts_bound shall be correct before the + * scheduler runs */ + if(opq->num_ops && (opq->ops[opq->num_ops - 1] == op_do_sched_indx)) { + opq->num_ops--; + gen_op_move_gpr_t[t][gpr](opq, 1); + gen_op_do_sched(opq, 1); + return; + } + + gen_op_move_gpr_t[t][gpr](opq, 1); + + return; + } + } +} + +static void ship_gprs_out_t(struct op_queue *opq) +{ + int i; + + if(!opq) + return; + + for(i = 0; i < NUM_T_REGS; i++) { + if(opq->reg_t[i] < 32) + /* Ship temporaries out in the last opq that actually touched it */ + ship_t_out(opq, i); + } +} + +/* FIXME: Look at the following instructions to make a better guess at which + * temporary to return */ +static int find_t(struct op_queue *opq, unsigned int reg) +{ + int i, j, t = -1; + + for(i = 0; i < NUM_T_REGS; i++) { + if(opq->reg_t[i] == reg) + return i; + + /* Ok, we have found an as-yet unused temporary, check if it is needed + * later in this instruction */ + for(j = 0; j < opq->param_num; j++) { + if((opq->param_type[j] & OPTYPE_REG) && (opq->param[j] == opq->reg_t[i])) + break; + } + + if(j != opq->param_num) + continue; + + /* We have found the temporary (temporarily:) fit for use */ + if((t == -1) || (opq->reg_t[i] == 32)) + t = i; + } + + return t; +} + +/* Checks if there is enough space in dp->host_page, if not grow it */ +void *enough_host_page(struct dyn_page *dp, void *cur, unsigned int *len, + unsigned int amount) +{ + unsigned int used = cur - dp->host_page; + + /* The array is long enough */ + if((used + amount) <= *len) + return cur; + + /* Reallocate */ + *len += RECED_PAGE_ENLARGE_BY; + + if(!(dp->host_page = realloc(dp->host_page, *len))) { + fprintf(stderr, "OOM\n"); + exit(1); + } + + return dp->host_page + used; +} + +/* Adds an operation to the opq */ +void add_to_opq(struct op_queue *opq, int end, int op) +{ + if(opq->num_ops == opq->ops_len) { + opq->ops_len += OPS_ENLARGE_BY; + if(!(opq->ops = realloc(opq->ops, opq->ops_len * sizeof(int)))) { + fprintf(stderr, "OOM\n"); + exit(1); + } + } + + if(end) + opq->ops[opq->num_ops] = op; + else { + /* Shift everything over by one */ + memmove(opq->ops + 1, opq->ops, opq->num_ops* sizeof(int)); + opq->ops[0] = op; + } + + opq->num_ops++; +} + +static void gen_op_mark_loc(struct op_queue *opq, int end) +{ + add_to_opq(opq, end, op_mark_loc_indx); +} + +/* Adds a parameter to the opq */ +void add_to_op_params(struct op_queue *opq, int end, unsigned long param) +{ + if(opq->num_ops_param == opq->ops_param_len) { + opq->ops_param_len += OPS_ENLARGE_BY; + if(!(opq->ops_param = realloc(opq->ops_param, opq->ops_param_len * sizeof(int)))) { + fprintf(stderr, "OOM\n"); + exit(1); + } + } + + if(end) + opq->ops_param[opq->num_ops_param] = param; + else { + /* Shift everything over by one */ + memmove(opq->ops_param + 1, opq->ops_param, opq->num_ops_param); + opq->ops_param[0] = param; + } + + opq->num_ops_param++; +} + +/* Initialises the recompiler */ +void init_dyn_recomp(void) +{ + struct sigaction sigact; + struct op_queue *opq = NULL; + unsigned int i; + + cpu_state.opqs = NULL; + + /* Allocate the operation queue list (+1 for the page chaining) */ + for(i = 0; i < (immu_state->pagesize / 4) + 1; i++) { + if(!(opq = malloc(sizeof(struct op_queue)))) { + fprintf(stderr, "OOM\n"); + exit(1); + } + + /* initialise some fields */ + opq->ops_len = 0; + opq->ops = NULL; + opq->ops_param_len = 0; + opq->ops_param = NULL; + opq->xref = 0; + + if(cpu_state.opqs) + cpu_state.opqs->prev = opq; + + opq->next = cpu_state.opqs; + cpu_state.opqs = opq; + } + + opq->prev = NULL; + + cpu_state.curr_page = NULL; + if(!(cpu_state.dyn_pages = malloc(sizeof(void *) * (2 << (32 - + immu_state->pagesize_log2))))) { + fprintf(stderr, "OOM\n"); + exit(1); + } + memset(cpu_state.dyn_pages, 0, + sizeof(void *) * (2 << (32 - immu_state->pagesize_log2))); + + /* Register our segmentation fault handler */ + sigact.sa_sigaction = dyn_sigsegv_debug; + memset(&sigact.sa_mask, 0, sizeof(sigact.sa_mask)); + sigact.sa_flags = SA_SIGINFO | SA_NOMASK; + if(sigaction(SIGSEGV, &sigact, NULL)) + printf("WARN: Unable to install SIGSEGV handler! Don't expect to be able to debug the recompiler.\n"); + + /* FIXME: Find a better place for this */ + { /* Needed by execution */ + extern int do_stats; + do_stats = config.cpu.dependstats || config.cpu.superscalar || config.cpu.dependstats + || config.sim.history || config.sim.exe_log; + } + + printf("Recompile engine up and running\n"); +} + +/* Parses instructions and their operands and populates opq with them */ +static void eval_insn_ops(struct op_queue *opq, oraddr_t addr) +{ + int breakp; + struct insn_op_struct *opd; + + for(; opq->next; opq = opq->next, addr += 4) { + opq->param_num = 0; + breakp = 0; + opq->insn = eval_insn(addr, &breakp); + + /* FIXME: If a breakpoint is set at this location, insert exception code */ + if(breakp) { + fprintf(stderr, "FIXME: Insert breakpoint code\n"); + } + + opq->insn_index = insn_decode(opq->insn); + + if(opq->insn_index == -1) + continue; + + opd = op_start[opq->insn_index]; + + do { + opq->param[opq->param_num] = eval_operand_val(opq->insn, opd); + opq->param_type[opq->param_num] = opd->type; + + opq->param_num++; + while(!(opd->type & OPTYPE_OP)) opd++; + } while(!(opd++->type & OPTYPE_LAST)); + } +} + +/* Adds code to the opq for the instruction pointed to by addr */ +static void recompile_insn(struct op_queue *opq, int delay_insn) +{ + int j, k; + int param_t[5]; /* Which temporary the parameters reside in */ + + /* Check if we have an illegal instruction */ + if(opq->insn_index == -1) { + gen_l_invalid(opq, NULL, delay_insn); + return; + } + + /* If we are recompileing an instruction that has a delay slot and is in the + * delay slot, ignore it. This is undefined behavour. */ + if(delay_insn && (or32_opcodes[opq->insn_index].flags & OR32_IF_DELAY)) + return; + + param_t[0] = T_NONE; + param_t[1] = T_NONE; + param_t[2] = T_NONE; + param_t[3] = T_NONE; + param_t[4] = T_NONE; + + /* Jump instructions are special since they have a delay slot and thus they + * need to control the exact operation sequence. Special case these here to + * avoid haveing loads of if(!(.& OR32_IF_DELAY)) below */ + if(or32_opcodes[opq->insn_index].flags & OR32_IF_DELAY) { + /* Jump instructions don't have a disposition */ + or32_opcodes[opq->insn_index].exec(opq, param_t, delay_insn); + + /* Analysis is done by the individual jump instructions */ + /* Jump instructions don't touch runtime.sim.mem_cycles */ + /* Jump instructions run their own scheduler */ + return; + } + + /* Before an exception takes place, all registers must be stored. */ + if((or32_opcodes[opq->insn_index].func_unit == it_exception)) { + ship_gprs_out_t(opq); + + or32_opcodes[opq->insn_index].exec(opq, param_t, delay_insn); + return; + } + + for(j = 0; j < opq->param_num; j++) { + if(!(opq->param_type[j] & OPTYPE_REG)) + continue; + + /* Never, ever, move r0 into a temporary */ + if(!opq->param[j]) + continue; + + k = find_t(opq, opq->param[j]); + + param_t[j] = k; + + if(opq->reg_t[k] == opq->param[j]) { + if(!(opq->param_type[j] & OPTYPE_DST) && + !(opq->tflags[k] & TFLAG_SOURCED)) { + gen_op_move_t_gpr[k][opq->reg_t[k]](opq, 0); + opq->tflags[k] |= TFLAG_SOURCED; + } + + if(opq->param_type[j] & OPTYPE_DST) + opq->tflags[k] |= TFLAG_DST; + else + opq->tflags[k] |= TFLAG_SRC; + + continue; + } + + if(opq->reg_t[k] < 32) { + /* Only ship the temporary out if it has been used as a destination + * register */ + ship_t_out(opq, k); + } + + if(opq->param_type[j] & OPTYPE_DST) + opq->tflags[k] = TFLAG_DST; + else + opq->tflags[k] = TFLAG_SRC; + + opq->reg_t[k] = opq->param[j]; + + /* Only generate code to move the register into a temporary if it is used as + * a source operand */ + if(!(opq->param_type[j] & OPTYPE_DST)) { + gen_op_move_t_gpr[k][opq->reg_t[k]](opq, 0); + opq->tflags[k] |= TFLAG_SOURCED; + } + } + + /* To get the execution log correct for instructions like l.lwz r4,0(r4) the + * effective address needs to be calculated before the instruction is + * simulated */ + if(do_stats) { + for(j = 0; j < opq->param_num; j++) { + if(!(opq->param_type[j] & OPTYPE_DIS)) + continue; + + if(!opq->param[j + 1]) + gen_op_store_insn_ea(opq, 1, opq->param[j]); + else + calc_insn_ea_table[param_t[j + 1]](opq, 1, opq->param[j]); + } + } + + or32_opcodes[opq->insn_index].exec(opq, param_t, delay_insn); + + if(do_stats) { + ship_gprs_out_t(opq); + gen_op_analysis(opq, 1); + } + + /* The call to join_mem_cycles() could be put into the individual operations + * that emulate the load/store instructions, but then it would be added to + * the cycle counter before analysis() is called, which is not how the complex + * execution model does it. */ + if((or32_opcodes[opq->insn_index].func_unit == it_load) || + (or32_opcodes[opq->insn_index].func_unit == it_store)) + gen_op_join_mem_cycles(opq, 1); + + /* Delay slot instructions get a special scheduler, thus don't generate it + * here */ + if(!delay_insn) + gen_op_do_sched(opq, 1); +} + +/* Recompiles the page associated with *dyn */ +void recompile_page(struct dyn_page *dyn) +{ + unsigned int j; + struct op_queue *opq = cpu_state.opqs; + oraddr_t rec_addr = dyn->or_page; + oraddr_t rec_page = dyn->or_page; + void **loc; + + /* The start of the next page */ + rec_page += immu_state->pagesize; + + printf("Recompileing page %"PRIxADDR"\n", rec_addr); + fflush(stdout); + + /* Mark all temporaries as not containing a register */ + for(j = 0; j < NUM_T_REGS; j++) { + opq->reg_t[j] = 32; /* Out-of-range registers */ + opq->tflags[j] = 0; + } + + dyn->delayr = -verify_memoryarea(rec_addr)->ops.delayr; + + opq->num_ops = 0; + opq->num_ops_param = 0; + + eval_insn_ops(opq, rec_addr); + + /* Insert code to check if the first instruction is exeucted in a delay slot*/ + gen_op_check_delay_slot(opq, 1, 0); + recompile_insn(opq, 1); + ship_gprs_out_t(opq); + gen_op_do_sched_delay(opq, 1); + gen_op_clear_delay_insn(opq, 1); + gen_op_do_jump_delay(opq, 1); + gen_op_do_jump(opq, 1); + gen_op_mark_loc(opq, 1); + + for(j = 0; j < NUM_T_REGS; j++) + opq->reg_t[j] = 32; /* Out-of-range registers */ + + for(; rec_addr < rec_page; rec_addr += 4, opq = opq->next) { + if(opq->prev) { + opq->num_ops = 0; + opq->num_ops_param = 0; + } + opq->jump_local = -1; + opq->not_jump_loc = -1; + + opq->insn_addr = rec_addr; + + for(j = 0; j < NUM_T_REGS; j++) + opq->tflags[j] = TFLAG_SOURCED; + + /* Check if this location is cross referenced */ + if(opq->xref) { + /* If the current address is cross-referenced, the temporaries shall be + * in an undefined state, so we must assume that no registers reside in + * them */ + /* Ship out the current set of registers from the temporaries */ + if(opq->prev) { + ship_gprs_out_t(opq->prev); + for(j = 0; j < NUM_T_REGS; j++) { + opq->reg_t[j] = 32; + opq->prev->reg_t[j] = 32; + } + } + } + + recompile_insn(opq, 0); + + /* Store the state of the temporaries */ + memcpy(opq->next->reg_t, opq->reg_t, sizeof(opq->reg_t)); + } + + dyn->dirty = 0; + + /* Ship temporaries out to the corrisponding registers */ + ship_gprs_out_t(opq->prev); + + opq->num_ops = 0; + opq->num_ops_param = 0; + opq->not_jump_loc = -1; + opq->jump_local = -1; + + /* Insert code to jump to the next page */ + gen_op_do_jump(opq, 1); + + /* Generate the code */ + gen_code(cpu_state.opqs, dyn); + + /* Fix up the locations */ + for(loc = dyn->locs; loc < &dyn->locs[immu_state->pagesize / 4]; loc++) + *loc += (unsigned int)dyn->host_page; + + cpu_state.opqs->ops_param[0] += (unsigned int)dyn->host_page; + + /* Search for page-local jumps */ + opq = cpu_state.opqs; + for(j = 0; j < (immu_state->pagesize / 4); opq = opq->next, j++) { + if(opq->jump_local != -1) + opq->ops_param[opq->jump_local] = + (unsigned int)dyn->locs[opq->jump_local_loc >> 2]; + + if(opq->not_jump_loc != -1) + opq->ops_param[opq->not_jump_loc] = (unsigned int)dyn->locs[j + 1]; + + /* Store the state of the temporaries into dyn->ts_bound */ + dyn->ts_bound[j] = 0; + if(opq->reg_t[0] < 32) + dyn->ts_bound[j] = opq->reg_t[0]; + if(opq->reg_t[1] < 32) + dyn->ts_bound[j] |= opq->reg_t[1] << 5; + if(opq->reg_t[2] < 32) + dyn->ts_bound[j] |= opq->reg_t[2] << 10; + + /* Reset for the next page to be recompiled */ + opq->xref = 0; + } + + /* Patch the relocations */ + patch_relocs(cpu_state.opqs, dyn->host_page); + + if(do_stats) { + opq = cpu_state.opqs; + for(j = 0; j < (immu_state->pagesize / 4); j++, opq = opq->next) { + dyn->insns[j] = opq->insn; + dyn->insn_indexs[j] = opq->insn_index; + } + } + + /* FIXME: Fix the issue below in a more elegent way */ + /* Since eval_insn is called to get the instruction, runtime.sim.mem_cycles is + * updated but the recompiler expectes it to start a 0, so reset it */ + runtime.sim.mem_cycles = 0; +} + +/* Recompiles a delay-slot instruction (opq is the opq of the instruction + * haveing the delay-slot) */ +static void recompile_delay_insn(struct op_queue *opq) +{ + struct op_queue delay_opq; + int i; + + /* Setup a fake opq that looks very much like the delay slot instruction */ + memcpy(&delay_opq, opq, sizeof(struct op_queue)); + /* `Fix' a couple of bits */ + for(i = 0; i < NUM_T_REGS; i++) + delay_opq.tflags[i] = TFLAG_SOURCED; + delay_opq.insn_index = opq->next->insn_index; + memcpy(delay_opq.param_type, opq->next->param_type, sizeof(delay_opq.param_type)); + memcpy(delay_opq.param, opq->next->param, sizeof(delay_opq.param)); + delay_opq.param_num = opq->next->param_num; + delay_opq.insn = opq->next->insn; + + delay_opq.xref = 0; + delay_opq.insn_addr = opq->insn_addr + 4; + delay_opq.prev = opq->prev; + delay_opq.next = NULL; + + /* Generate the delay slot instruction */ + recompile_insn(&delay_opq, 1); + + ship_gprs_out_t(&delay_opq); + + opq->num_ops = delay_opq.num_ops; + opq->ops_len = delay_opq.ops_len; + opq->ops = delay_opq.ops; + opq->num_ops_param = delay_opq.num_ops_param; + opq->ops_param_len = delay_opq.ops_param_len; + opq->ops_param = delay_opq.ops_param; + + for(i = 0; i < NUM_T_REGS; i++) + opq->reg_t[i] = 32; +} + +/* Returns non-zero if the jump is into this page, 0 otherwise */ +static int find_jump_loc(oraddr_t j_ea, struct op_queue *opq) +{ + int i; + + /* Mark the jump as non page local if the delay slot instruction is on the + * next page to the jump instruction. This should not be needed */ + if(IADDR_PAGE(j_ea) != IADDR_PAGE(opq->insn_addr)) + /* We can't do anything as the j_ea (as passed to find_jump_loc) is a + * VIRTUAL offset and the next physical page may not be the next VIRTUAL + * page */ + return 0; + + /* The jump is into the page currently undergoing dynamic recompilation */ + + /* If we haven't got to the location of the jump, everything is ok */ + if(j_ea > opq->insn_addr) { + /* Find the corissponding opq and mark it as cross referenced */ + for(i = (j_ea - opq->insn_addr) / 4; i; i--) + opq = opq->next; + opq->xref = 1; + return 1; + } + + /* Insert temporary -> register code before the jump ea and register -> + * temporary at the x-ref address */ + for(i = (opq->insn_addr - j_ea) / 4; i; i--) + opq = opq->prev; + + if(!opq->prev) + /* We're at the begining of a page, no need to do anything */ + return 1; + + /* Found location, insert code */ + + ship_gprs_out_t(opq->prev); + + for(i = 0; i < NUM_T_REGS; i++) { + if(opq->prev->reg_t[i] < 32) + /* FIXME: Ship temporaries in the begining of the opq that needs it */ + gen_op_move_t_gpr[i][opq->prev->reg_t[i]](opq, 0); + } + + opq->xref = 1; + + return 1; +} + +static void gen_j_imm(struct op_queue *opq, oraddr_t off) +{ + int jump_local; + + off <<= 2; + + if(IADDR_PAGE(opq->insn_addr) != IADDR_PAGE(opq->insn_addr + 4)) { + gen_op_set_pc_delay_imm(opq, 1, off); + gen_op_do_sched(opq, 1); + return; + } + + jump_local = find_jump_loc(opq->insn_addr + off, opq); + + gen_op_set_delay_insn(opq, 1); + gen_op_do_sched(opq, 1); + + recompile_delay_insn(opq); + + gen_op_add_pc(opq, 1, (orreg_t)off - 8); + gen_op_clear_delay_insn(opq, 1); + gen_op_do_sched_delay(opq, 1); + + if(jump_local) { + gen_op_jmp_imm(opq, 1, 0); + opq->jump_local = opq->num_ops_param - 1; + opq->jump_local_loc = (opq->insn_addr + (orreg_t)off) & immu_state->page_offset_mask; + } else + gen_op_do_jump(opq, 1); +} + +static const generic_gen_op set_pc_delay_gpr[32] = { + NULL, + gen_op_move_gpr1_pc_delay, + gen_op_move_gpr2_pc_delay, + gen_op_move_gpr3_pc_delay, + gen_op_move_gpr4_pc_delay, + gen_op_move_gpr5_pc_delay, + gen_op_move_gpr6_pc_delay, + gen_op_move_gpr7_pc_delay, + gen_op_move_gpr8_pc_delay, + gen_op_move_gpr9_pc_delay, + gen_op_move_gpr10_pc_delay, + gen_op_move_gpr11_pc_delay, + gen_op_move_gpr12_pc_delay, + gen_op_move_gpr13_pc_delay, + gen_op_move_gpr14_pc_delay, + gen_op_move_gpr15_pc_delay, + gen_op_move_gpr16_pc_delay, + gen_op_move_gpr17_pc_delay, + gen_op_move_gpr18_pc_delay, + gen_op_move_gpr19_pc_delay, + gen_op_move_gpr20_pc_delay, + gen_op_move_gpr21_pc_delay, + gen_op_move_gpr22_pc_delay, + gen_op_move_gpr23_pc_delay, + gen_op_move_gpr24_pc_delay, + gen_op_move_gpr25_pc_delay, + gen_op_move_gpr26_pc_delay, + gen_op_move_gpr27_pc_delay, + gen_op_move_gpr28_pc_delay, + gen_op_move_gpr29_pc_delay, + gen_op_move_gpr30_pc_delay, + gen_op_move_gpr31_pc_delay }; + +static void gen_j_reg(struct op_queue *opq, unsigned int gpr) +{ + int i; + + /* Ship the jump-to register out (if it exists). It requires special + * handleing */ + for(i = 0; i < NUM_T_REGS; i++) { + if(opq->reg_t[i] == opq->param[0]) + /* Ship temporary out in the last opq that used it */ + ship_t_out(opq, i); + } + + if(do_stats) + gen_op_analysis(opq, 1); + + if(!gpr) + gen_op_clear_pc_delay(opq, 1); + else + set_pc_delay_gpr[gpr](opq, 1); + + gen_op_do_sched(opq, 1); + + if(IADDR_PAGE(opq->insn_addr) != IADDR_PAGE(opq->insn_addr + 4)) + return; + + recompile_delay_insn(opq); + + gen_op_set_pc_pc_delay(opq, 1); + gen_op_clear_delay_insn(opq, 1); + gen_op_do_sched_delay(opq, 1); + + gen_op_do_jump_delay(opq, 1); + gen_op_do_jump(opq, 1); +} + +/*------------------------------[ Operation generation for an instruction ]---*/ +/* FIXME: Flag setting is not done in any instruction */ +/* FIXME: Since r0 is not moved into a temporary, check all arguments below! */ + +DEF_1T_OP(generic_gen_op, clear_t, gen_op_clear); +DEF_2T_OP_NEQ(generic_gen_op, move_t_t, gen_op_move); +DEF_1T_OP(imm_gen_op, mov_t_imm, gen_op_imm); + +DEF_2T_OP(imm_gen_op, l_add_imm_t_table, gen_op_add_imm); +DEF_3T_OP(generic_gen_op, l_add_t_table, gen_op_add); + +void gen_l_add(struct op_queue *opq, int param_t[3], int delay_slot) +{ + if(!opq->param[0]) + /* Screw this, the operation shall do nothing */ + return; + + if(!opq->param[1] && !opq->param[2]) { + /* Just clear param_t[0] */ + clear_t[param_t[0]](opq, 1); + return; + } + + if(!opq->param[2]) { + if(opq->param[0] != opq->param[1]) + /* This just moves a register */ + move_t_t[param_t[0]][param_t[1]](opq, 1); + return; + } + + if(!opq->param[1]) { + /* Check if we are moveing an immediate */ + if(param_t[2] == T_NONE) { + /* Yep, an immediate */ + mov_t_imm[param_t[0]](opq, 1, opq->param[2]); + return; + } + /* Just another move */ + if(opq->param[0] != opq->param[2]) + move_t_t[param_t[0]][param_t[2]](opq, 1); + return; + } + + /* Ok, This _IS_ an add... */ + if(param_t[2] == T_NONE) + /* immediate */ + l_add_imm_t_table[param_t[0]][param_t[1]](opq, 1, opq->param[2]); + else + l_add_t_table[param_t[0]][param_t[1]][param_t[2]](opq, 1); +} + +DEF_3T_OP(generic_gen_op, l_addc_t_table, gen_op_addc); + +void gen_l_addc(struct op_queue *opq, int param_t[3], int delay_slot) +{ + if(!opq->param[0]) + /* Screw this, the operation shall do nothing */ + return; + + /* FIXME: More optimisations !! (...and immediate...) */ + l_addc_t_table[param_t[0]][param_t[1]][param_t[2]](opq, 1); +} + +DEF_2T_OP(imm_gen_op, l_and_imm_t_table, gen_op_and_imm); +DEF_3T_OP_NEQ(generic_gen_op, l_and_t_table, gen_op_and); + +void gen_l_and(struct op_queue *opq, int param_t[3], int delay_slot) +{ + if(!opq->param[0]) + /* Screw this, the operation shall do nothing */ + return; + + if(!opq->param[1] || !opq->param[2]) { + /* Just clear param_t[0] */ + clear_t[param_t[0]](opq, 1); + return; + } + + if((opq->param[0] == opq->param[1]) && + (opq->param[0] == opq->param[2]) && + (param_t[2] != T_NONE)) + return; + + if(param_t[2] == T_NONE) + l_and_imm_t_table[param_t[0]][param_t[1]](opq, 1, opq->param[2]); + else + l_and_t_table[param_t[0]][param_t[1]][param_t[2]](opq, 1); +} + +void gen_l_bf(struct op_queue *opq, int param_t[3], int delay_slot) +{ + if(do_stats) + /* All gprs are current since this insn doesn't touch any reg */ + gen_op_analysis(opq, 1); + + /* The temporaries are expected to be shiped out after the execution of the + * branch instruction wether it branched or not */ + ship_gprs_out_t(opq->prev); + + if(IADDR_PAGE(opq->insn_addr) != IADDR_PAGE(opq->insn_addr + 4)) { + gen_op_check_flag_delay(opq, 1, opq->param[0] << 2); + gen_op_do_sched(opq, 1); + opq->not_jump_loc = -1; + return; + } + + gen_op_check_flag(opq, 1, 0); + opq->not_jump_loc = opq->num_ops_param - 1; + + gen_j_imm(opq, opq->param[0]); +} + +void gen_l_bnf(struct op_queue *opq, int param_t[3], int delay_slot) +{ + if(do_stats) + /* All gprs are current since this insn doesn't touch any reg */ + gen_op_analysis(opq, 1); + + /* The temporaries are expected to be shiped out after the execution of the + * branch instruction wether it branched or not */ + ship_gprs_out_t(opq->prev); + + if(IADDR_PAGE(opq->insn_addr) != IADDR_PAGE(opq->insn_addr + 4)) { + gen_op_check_not_flag_delay(opq, 1, opq->param[0] << 2); + gen_op_do_sched(opq, 1); + opq->not_jump_loc = -1; + return; + } + + gen_op_check_not_flag(opq, 1, 0); + opq->not_jump_loc = opq->num_ops_param - 1; + + gen_j_imm(opq, opq->param[0]); +} + +DEF_3T_OP_NEQ(generic_gen_op, l_cmov_t_table, gen_op_cmov); + +/* FIXME: Check if either opperand 1 or 2 is r0 */ +void gen_l_cmov(struct op_queue *opq, int param_t[3], int delay_slot) +{ + if(!opq->param[0]) + return; + + if(!opq->param[1] && !opq->param[2]) { + clear_t[param_t[0]](opq, 1); + return; + } + + if((opq->param[1] == opq->param[2]) && (opq->param[0] == opq->param[1])) + return; + + if(opq->param[1] == opq->param[2]) { + move_t_t[param_t[0]][param_t[1]](opq, 1); + return; + } + + l_cmov_t_table[param_t[0]][param_t[1]][param_t[2]](opq, 1); +} + +void gen_l_cust1(struct op_queue *opq, int param_t[3], int delay_slot) +{ +} + +void gen_l_cust2(struct op_queue *opq, int param_t[3], int delay_slot) +{ +} + +void gen_l_cust3(struct op_queue *opq, int param_t[3], int delay_slot) +{ +} + +void gen_l_cust4(struct op_queue *opq, int param_t[3], int delay_slot) +{ +} + +void gen_l_cust5(struct op_queue *opq, int param_t[3], int delay_slot) +{ +} + +void gen_l_cust6(struct op_queue *opq, int param_t[3], int delay_slot) +{ +} + +void gen_l_cust7(struct op_queue *opq, int param_t[3], int delay_slot) +{ +} + +void gen_l_cust8(struct op_queue *opq, int param_t[3], int delay_slot) +{ +} + +/* FIXME: All registers need to be stored before the div instructions as they + * have the potenticial to cause an exception */ + +DEF_1T_OP(generic_gen_op, check_null_excpt, gen_op_check_null_except); +DEF_1T_OP(generic_gen_op, check_null_excpt_delay, gen_op_check_null_except_delay); +DEF_3T_OP(generic_gen_op, l_div_t_table, gen_op_div); + +void gen_l_div(struct op_queue *opq, int param_t[3], int delay_slot) +{ + if(!opq->param[2]) { + /* There is no option. This _will_ cause an illeagal exception */ + if(!delay_slot) { + gen_op_illegal(opq, 1); + gen_op_do_jump(opq, 1); + } else { + gen_op_illegal(opq, 1); + gen_op_do_jump(opq, 1); + } + return; + } + + if(!delay_slot) + check_null_excpt[param_t[2]](opq, 1); + else + check_null_excpt_delay[param_t[2]](opq, 1); + + if(!opq->param[0]) + return; + + if(!opq->param[1]) { + /* Clear param_t[0] */ + clear_t[param_t[0]](opq, 1); + return; + } + + l_div_t_table[param_t[0]][param_t[1]][param_t[2]](opq, 1); +} + +DEF_3T_OP(generic_gen_op, l_divu_t_table, gen_op_divu); + +void gen_l_divu(struct op_queue *opq, int param_t[3], int delay_slot) +{ + if(!opq->param[2]) { + /* There is no option. This _will_ cause an illeagal exception */ + if(!delay_slot) { + gen_op_illegal(opq, 1); + gen_op_do_jump(opq, 1); + } else { + gen_op_illegal(opq, 1); + gen_op_do_jump(opq, 1); + } + return; + } + + if(!delay_slot) + check_null_excpt[param_t[2]](opq, 1); + else + check_null_excpt_delay[param_t[2]](opq, 1); + + if(!opq->param[0]) + return; + + if(!opq->param[1]) { + /* Clear param_t[0] */ + clear_t[param_t[0]](opq, 1); + return; + } + + l_divu_t_table[param_t[0]][param_t[1]][param_t[2]](opq, 1); +} + +DEF_2T_OP(generic_gen_op, l_extbs_t_table, gen_op_extbs); + +void gen_l_extbs(struct op_queue *opq, int param_t[3], int delay_slot) +{ + if(!opq->param[0]) + return; + + if(!opq->param[1]) { + clear_t[param_t[0]](opq, 1); + return; + } + + l_extbs_t_table[param_t[0]][param_t[1]](opq, 1); +} + +DEF_2T_OP(generic_gen_op, l_extbz_t_table, gen_op_extbz); + +void gen_l_extbz(struct op_queue *opq, int param_t[3], int delay_slot) +{ + if(!opq->param[0]) + return; + + if(!opq->param[1]) { + clear_t[param_t[0]](opq, 1); + return; + } + + l_extbz_t_table[param_t[0]][param_t[1]](opq, 1); +} + +DEF_2T_OP(generic_gen_op, l_exths_t_table, gen_op_exths); + +void gen_l_exths(struct op_queue *opq, int param_t[3], int delay_slot) +{ + if(!opq->param[0]) + return; + + if(!opq->param[1]) { + clear_t[param_t[0]](opq, 1); + return; + } + + l_exths_t_table[param_t[0]][param_t[1]](opq, 1); +} + +DEF_2T_OP(generic_gen_op, l_exthz_t_table, gen_op_exthz); + +void gen_l_exthz(struct op_queue *opq, int param_t[3], int delay_slot) +{ + if(!opq->param[0]) + return; + + if(!opq->param[1]) { + clear_t[param_t[0]](opq, 1); + return; + } + + l_exthz_t_table[param_t[0]][param_t[1]](opq, 1); +} + +void gen_l_extws(struct op_queue *opq, int param_t[3], int delay_slot) +{ + if(!opq->param[0]) + return; + + if(!opq->param[1]) { + clear_t[param_t[0]](opq, 1); + return; + } + + if(opq->param[0] == opq->param[1]) + return; + + /* In the 32-bit architechture this instruction reduces to a move */ + move_t_t[param_t[0]][param_t[1]](opq, 1); +} + +void gen_l_extwz(struct op_queue *opq, int param_t[3], int delay_slot) +{ + if(!opq->param[0]) + return; + + if(!opq->param[1]) { + clear_t[param_t[0]](opq, 1); + return; + } + + if(opq->param[0] == opq->param[1]) + return; + + /* In the 32-bit architechture this instruction reduces to a move */ + move_t_t[param_t[0]][param_t[1]](opq, 1); +} + +DEF_2T_OP(generic_gen_op, l_ff1_t_table, gen_op_ff1); + +void gen_l_ff1(struct op_queue *opq, int param_t[3], int delay_slot) +{ + if(!opq->param[0]) + return; + + if(!opq->param[1]) { + clear_t[param_t[0]](opq, 1); + return; + } + + l_ff1_t_table[param_t[0]][param_t[1]](opq, 1); +} + +void gen_l_j(struct op_queue *opq, int param_t[3], int delay_slot) +{ + if(do_stats) + /* All gprs are current since this insn doesn't touch any reg */ + gen_op_analysis(opq, 1); + + gen_j_imm(opq, opq->param[0]); +} + +void gen_l_jal(struct op_queue *opq, int param_t[3], int delay_slot) +{ + int i; + + /* In the case of a l.jal instruction, make sure that LINK_REGNO is not in + * a temporary. The problem is that the l.jal(r) instruction stores the + * `return address' in LINK_REGNO. The temporaries are shiped out only + * after the delay slot instruction has executed and so it overwrittes the + * `return address'. */ + for(i = 0; i < NUM_T_REGS; i++) { + if(opq->reg_t[i] == LINK_REGNO) { + /* Don't bother storeing the register, it is going to get clobered in this + * instruction anyway */ + opq->reg_t[i] = 32; + break; + } + } + + /* Store the return address */ + gen_op_store_link_addr_gpr(opq, 1); + + if(do_stats) + /* All gprs are current since this insn doesn't touch any reg */ + gen_op_analysis(opq, 1); + + gen_j_imm(opq, opq->param[0]); +} + +void gen_l_jr(struct op_queue *opq, int param_t[3], int delay_slot) +{ + gen_j_reg(opq, opq->param[0]); +} + +void gen_l_jalr(struct op_queue *opq, int param_t[3], int delay_slot) +{ + int i; + + /* In the case of a l.jal instruction, make sure that LINK_REGNO is not in + * a temporary. The problem is that the l.jal(r) instruction stores the + * `return address' in LINK_REGNO. The temporaries are shiped out only + * after the delay slot instruction has executed and so it overwrittes the + * `return address'. */ + for(i = 0; i < NUM_T_REGS; i++) { + if(opq->reg_t[i] == LINK_REGNO) { + /* Don't bother storeing the register, it is going to get clobered in this + * instruction anyway */ + opq->reg_t[i] = 32; + break; + } + } + + /* Store the return address */ + gen_op_store_link_addr_gpr(opq, 1); + + gen_j_reg(opq, opq->param[0]); +} + +/* FIXME: Optimise all load instruction when the disposition == 0 */ + +DEF_1T_OP(imm_gen_op, l_lbs_imm_t_table, gen_op_lbs_imm); +DEF_2T_OP(imm_gen_op, l_lbs_t_table, gen_op_lbs); + +void gen_l_lbs(struct op_queue *opq, int param_t[3], int delay_slot) +{ + if(!opq->param[0]) { + /* FIXME: This will work, but the statistics need to be updated... */ + return; + } + + /* Just in case an exception happens */ + ship_gprs_out_t(opq->prev); + + if(!opq->param[2]) { + /* Load the data from the immediate */ + l_lbs_imm_t_table[param_t[0]](opq, 1, opq->param[1]); + return; + } + + l_lbs_t_table[param_t[0]][param_t[2]](opq, 1, opq->param[1]); +} + +DEF_1T_OP(imm_gen_op, l_lbz_imm_t_table, gen_op_lbz_imm); +DEF_2T_OP(imm_gen_op, l_lbz_t_table, gen_op_lbz); + +void gen_l_lbz(struct op_queue *opq, int param_t[3], int delay_slot) +{ + if(!opq->param[0]) { + /* FIXME: This will work, but the statistics need to be updated... */ + return; + } + + /* Just in case an exception happens */ + ship_gprs_out_t(opq->prev); + + if(!opq->param[2]) { + /* Load the data from the immediate */ + l_lbz_imm_t_table[param_t[0]](opq, 1, opq->param[1]); + return; + } + + l_lbz_t_table[param_t[0]][param_t[2]](opq, 1, opq->param[1]); +} + +DEF_1T_OP(imm_gen_op, l_lhs_imm_t_table, gen_op_lhs_imm); +DEF_2T_OP(imm_gen_op, l_lhs_t_table, gen_op_lhs); + +void gen_l_lhs(struct op_queue *opq, int param_t[3], int delay_slot) +{ + if(!opq->param[0]) { + /* FIXME: This will work, but the statistics need to be updated... */ + return; + } + + /* Just in case an exception happens */ + ship_gprs_out_t(opq->prev); + + if(!opq->param[2]) { + /* Load the data from the immediate */ + l_lhs_imm_t_table[param_t[0]](opq, 1, opq->param[1]); + return; + } + + l_lhs_t_table[param_t[0]][param_t[2]](opq, 1, opq->param[1]); +} + +DEF_1T_OP(imm_gen_op, l_lhz_imm_t_table, gen_op_lhz_imm); +DEF_2T_OP(imm_gen_op, l_lhz_t_table, gen_op_lhz); + +void gen_l_lhz(struct op_queue *opq, int param_t[3], int delay_slot) +{ + if(!opq->param[0]) { + /* FIXME: This will work, but the statistics need to be updated... */ + return; + } + + /* Just in case an exception happens */ + ship_gprs_out_t(opq->prev); + + if(!opq->param[2]) { + /* Load the data from the immediate */ + l_lhz_imm_t_table[param_t[0]](opq, 1, opq->param[1]); + return; + } + + l_lhz_t_table[param_t[0]][param_t[2]](opq, 1, opq->param[1]); +} + +DEF_1T_OP(imm_gen_op, l_lws_imm_t_table, gen_op_lws_imm); +DEF_2T_OP(imm_gen_op, l_lws_t_table, gen_op_lws); + +void gen_l_lws(struct op_queue *opq, int param_t[3], int delay_slot) +{ + if(!opq->param[0]) { + /* FIXME: This will work, but the statistics need to be updated... */ + return; + } + + /* Just in case an exception happens */ + ship_gprs_out_t(opq->prev); + + if(!opq->param[2]) { + /* Load the data from the immediate */ + l_lws_imm_t_table[param_t[0]](opq, 1, opq->param[1]); + return; + } + + l_lws_t_table[param_t[0]][param_t[2]](opq, 1, opq->param[1]); +} + +DEF_1T_OP(imm_gen_op, l_lwz_imm_t_table, gen_op_lwz_imm); +DEF_2T_OP(imm_gen_op, l_lwz_t_table, gen_op_lwz); + +void gen_l_lwz(struct op_queue *opq, int param_t[3], int delay_slot) +{ + if(!opq->param[0]) { + /* FIXME: This will work, but the statistics need to be updated... */ + return; + } + + /* Just in case an exception happens */ + ship_gprs_out_t(opq->prev); + + if(!opq->param[2]) { + /* Load the data from the immediate */ + l_lwz_imm_t_table[param_t[0]](opq, 1, opq->param[1]); + return; + } + + l_lwz_t_table[param_t[0]][param_t[2]](opq, 1, opq->param[1]); +} + +DEF_1T_OP(imm_gen_op, l_mac_imm_t_table, gen_op_mac_imm); +DEF_2T_OP(generic_gen_op, l_mac_t_table, gen_op_mac); + +void gen_l_mac(struct op_queue *opq, int param_t[3], int delay_slot) +{ + if(!opq->param[0] || !opq->param[1]) + return; + + if(param_t[1] == T_NONE) + l_mac_imm_t_table[param_t[0]](opq, 1, opq->param[1]); + else + l_mac_t_table[param_t[0]][param_t[1]](opq, 1); +} + +DEF_1T_OP(generic_gen_op, l_macrc_t_table, gen_op_macrc); + +void gen_l_macrc(struct op_queue *opq, int param_t[3], int delay_slot) +{ + if(!opq->param[0]) { + gen_op_macc(opq, 1); + return; + } + + l_macrc_t_table[param_t[0]](opq, 1); +} + +DEF_1T_OP(imm_gen_op, l_mfspr_imm_t_table, gen_op_mfspr_imm); +DEF_2T_OP(imm_gen_op, l_mfspr_t_table, gen_op_mfspr); + +void gen_l_mfspr(struct op_queue *opq, int param_t[3], int delay_slot) +{ + if(!opq->param[0]) + return; + + if(!opq->param[1]) { + l_mfspr_imm_t_table[param_t[0]](opq, 1, opq->param[2]); + return; + } + + l_mfspr_t_table[param_t[0]][param_t[1]](opq, 1, opq->param[2]); +} + +void gen_l_movhi(struct op_queue *opq, int param_t[3], int delay_slot) +{ + if(!opq->param[0]) + return; + + if(!opq->param[1]) { + clear_t[param_t[0]](opq, 1); + return; + } + + mov_t_imm[param_t[0]](opq, 1, opq->param[1] << 16); +} + +DEF_2T_OP(generic_gen_op, l_msb_t_table, gen_op_msb); + +void gen_l_msb(struct op_queue *opq, int param_t[3], int delay_slot) +{ + if(!opq->param[0] || !opq->param[1]) + return; + + l_msb_t_table[param_t[0]][param_t[1]](opq, 1); +} + +DEF_1T_OP(imm_gen_op, l_mtspr_clear_t_table, gen_op_mtspr_clear); +DEF_1T_OP(imm_gen_op, l_mtspr_imm_t_table, gen_op_mtspr_imm); +DEF_2T_OP(imm_gen_op, l_mtspr_t_table, gen_op_mtspr); + +void gen_l_mtspr(struct op_queue *opq, int param_t[3], int delay_slot) +{ + /* Just in case an exception happens */ + ship_gprs_out_t(opq->prev); + + if(!opq->param[0]) { + if(!opq->param[1]) { + /* Clear the immediate SPR */ + gen_op_mtspr_imm_clear(opq, 1, opq->param[2]); + return; + } + l_mtspr_imm_t_table[param_t[1]](opq, 1, opq->param[2]); + return; + } + + if(!opq->param[1]) { + l_mtspr_clear_t_table[param_t[0]](opq, 1, opq->param[2]); + return; + } + + l_mtspr_t_table[param_t[0]][param_t[1]](opq, 1, opq->param[2]); +} + +DEF_2T_OP(imm_gen_op, l_mul_imm_t_table, gen_op_mul_imm); +DEF_3T_OP(generic_gen_op, l_mul_t_table, gen_op_mul); + +void gen_l_mul(struct op_queue *opq, int param_t[3], int delay_slot) +{ + if(!opq->param[0]) + return; + + if(!opq->param[1] || !opq->param[2]) { + clear_t[param_t[0]](opq, 1); + return; + } + + if(param_t[2] == T_NONE) + l_mul_imm_t_table[param_t[0]][param_t[1]](opq, 1, opq->param[2]); + else + l_mul_t_table[param_t[0]][param_t[1]][param_t[2]](opq, 1); +} + +DEF_3T_OP(generic_gen_op, l_mulu_t_table, gen_op_mulu); + +void gen_l_mulu(struct op_queue *opq, int param_t[3], int delay_slot) +{ + if(!opq->param[0]) + return; + + if(!opq->param[1] || !opq->param[2]) { + clear_t[param_t[0]](opq, 1); + return; + } + + l_mulu_t_table[param_t[0]][param_t[1]][param_t[2]](opq, 1); +} + +void gen_l_nop(struct op_queue *opq, int param_t[3], int delay_slot) +{ + /* Do parameter switch now */ + switch(opq->param[0]) { + case NOP_NOP: + break; + case NOP_EXIT: + ship_gprs_out_t(opq->prev); + gen_op_nop_exit(opq, 1); + break; + case NOP_CNT_RESET: + gen_op_nop_reset(opq, 1); + break; + case NOP_PRINTF: + ship_gprs_out_t(opq->prev); + gen_op_nop_printf(opq, 1); + break; + case NOP_REPORT: + ship_gprs_out_t(opq->prev); + gen_op_nop_report(opq, 1); + break; + default: + if((opq->param[0] >= NOP_REPORT_FIRST) && (opq->param[0] <= NOP_REPORT_LAST)) { + ship_gprs_out_t(opq->prev); + gen_op_nop_report_imm(opq, 1, opq->param[0] - NOP_REPORT_FIRST); + } + break; + } +} + +DEF_2T_OP(imm_gen_op, l_or_imm_t_table, gen_op_or_imm); +DEF_3T_OP_NEQ(generic_gen_op, l_or_t_table, gen_op_or); + +void gen_l_or(struct op_queue *opq, int param_t[3], int delay_slot) +{ + if(!opq->param[0]) + return; + + if((opq->param[0] == opq->param[1]) && + (opq->param[0] == opq->param[2]) && + (param_t[2] != T_NONE)) + return; + + if(!opq->param[1] && !opq->param[2]) { + clear_t[param_t[0]](opq, 1); + return; + } + + if(!opq->param[2]) { + if((param_t[2] == T_NONE) && (opq->param[0] == opq->param[1])) + return; + move_t_t[param_t[0]][param_t[1]](opq, 1); + return; + } + + if(!opq->param[1]) { + /* Check if we are moveing an immediate */ + if(param_t[2] == T_NONE) { + /* Yep, an immediate */ + mov_t_imm[param_t[0]](opq, 1, opq->param[2]); + return; + } + /* Just another move */ + move_t_t[param_t[0]][param_t[2]](opq, 1); + return; + } + + if(param_t[2] == T_NONE) + l_or_imm_t_table[param_t[0]][param_t[1]](opq, 1, opq->param[2]); + else + l_or_t_table[param_t[0]][param_t[1]][param_t[2]](opq, 1); +} + +void gen_l_rfe(struct op_queue *opq, int param_t[3], int delay_slot) +{ + if(do_stats) + /* All gprs are current since this insn doesn't touch any reg */ + gen_op_analysis(opq, 1); + + gen_op_prep_rfe(opq, 1); + /* FIXME: rename op_do_sched_delay */ + gen_op_do_sched_delay(opq, 1); + gen_op_do_jump(opq, 1); +} + +/* FIXME: All store instructions should be optimised when the disposition = 0 */ + +DEF_1T_OP(imm_gen_op, l_sb_clear_table, gen_op_sb_clear); +DEF_1T_OP(imm_gen_op, l_sb_imm_t_table, gen_op_sb_imm); +DEF_2T_OP(imm_gen_op, l_sb_t_table, gen_op_sb); + +void gen_l_sb(struct op_queue *opq, int param_t[3], int delay_slot) +{ + /* Just in case an exception happens */ + ship_gprs_out_t(opq->prev); + + if(!opq->param[2]) { + if(!opq->param[1]) { + gen_op_sb_clear_imm(opq, 1, opq->param[0]); + return; + } + l_sb_clear_table[param_t[1]](opq, 1, opq->param[0]); + return; + } + + if(!opq->param[1]) { + /* Store the data to the immediate */ + l_sb_imm_t_table[param_t[2]](opq, 1, opq->param[0]); + return; + } + + l_sb_t_table[param_t[1]][param_t[2]](opq, 1, opq->param[0]); +} + +DEF_1T_OP(imm_gen_op, l_sh_clear_table, gen_op_sh_clear); +DEF_1T_OP(imm_gen_op, l_sh_imm_t_table, gen_op_sh_imm); +DEF_2T_OP(imm_gen_op, l_sh_t_table, gen_op_sh); + +void gen_l_sh(struct op_queue *opq, int param_t[3], int delay_slot) +{ + /* Just in case an exception happens */ + ship_gprs_out_t(opq->prev); + + if(!opq->param[2]) { + if(!opq->param[1]) { + gen_op_sh_clear_imm(opq, 1, opq->param[0]); + return; + } + l_sh_clear_table[param_t[1]](opq, 1, opq->param[0]); + return; + } + + if(!opq->param[1]) { + /* Store the data to the immediate */ + l_sh_imm_t_table[param_t[2]](opq, 1, opq->param[0]); + return; + } + + l_sh_t_table[param_t[1]][param_t[2]](opq, 1, opq->param[0]); +} + +DEF_1T_OP(imm_gen_op, l_sw_clear_table, gen_op_sw_clear); +DEF_1T_OP(imm_gen_op, l_sw_imm_t_table, gen_op_sw_imm); +DEF_2T_OP(imm_gen_op, l_sw_t_table, gen_op_sw); + +void gen_l_sw(struct op_queue *opq, int param_t[3], int delay_slot) +{ + /* Just in case an exception happens */ + ship_gprs_out_t(opq->prev); + + if(!opq->param[2]) { + if(!opq->param[1]) { + gen_op_sw_clear_imm(opq, 1, opq->param[0]); + return; + } + l_sw_clear_table[param_t[1]](opq, 1, opq->param[0]); + return; + } + + if(!opq->param[1]) { + /* Store the data to the immediate */ + l_sw_imm_t_table[param_t[2]](opq, 1, opq->param[0]); + return; + } + + l_sw_t_table[param_t[1]][param_t[2]](opq, 1, opq->param[0]); +} + +DEF_1T_OP(generic_gen_op, l_sfeq_null_t_table, gen_op_sfeq_null); +DEF_1T_OP(imm_gen_op, l_sfeq_imm_t_table, gen_op_sfeq_imm); +DEF_2T_OP(generic_gen_op, l_sfeq_t_table, gen_op_sfeq); + +void gen_l_sfeq(struct op_queue *opq, int param_t[3], int delay_slot) +{ + if(!opq->param[0] && !opq->param[1]) { + gen_op_set_flag(opq, 1); + return; + } + + if(!opq->param[0]) { + if(param_t[1] == T_NONE) { + if(!opq->param[1]) + gen_op_set_flag(opq, 1); + else + gen_op_clear_flag(opq, 1); + } else + l_sfeq_null_t_table[param_t[1]](opq, 1); + return; + } + + if(!opq->param[1]) { + l_sfeq_null_t_table[param_t[0]](opq, 1); + return; + } + + if(param_t[1] == T_NONE) + l_sfeq_imm_t_table[param_t[0]](opq, 1, opq->param[1]); + else + l_sfeq_t_table[param_t[0]][param_t[1]](opq, 1); +} + +DEF_1T_OP(generic_gen_op, l_sfges_null_t_table, gen_op_sfges_null); +DEF_1T_OP(generic_gen_op, l_sfles_null_t_table, gen_op_sfles_null); +DEF_1T_OP(imm_gen_op, l_sfges_imm_t_table, gen_op_sfges_imm); +DEF_2T_OP(generic_gen_op, l_sfges_t_table, gen_op_sfges); + +void gen_l_sfges(struct op_queue *opq, int param_t[3], int delay_slot) +{ + if(!opq->param[0] && !opq->param[1]) { + gen_op_set_flag(opq, 1); + return; + } + + if(!opq->param[0]) { + /* sfles IS correct */ + if(param_t[1] == T_NONE) { + if(0 >= (orreg_t)opq->param[1]) + gen_op_set_flag(opq, 1); + else + gen_op_clear_flag(opq, 1); + } else + l_sfles_null_t_table[param_t[1]](opq, 1); + return; + } + + if(!opq->param[1]) { + l_sfges_null_t_table[param_t[0]](opq, 1); + return; + } + + if(param_t[1] == T_NONE) + l_sfges_imm_t_table[param_t[0]](opq, 1, opq->param[1]); + else + l_sfges_t_table[param_t[0]][param_t[1]](opq, 1); +} + +DEF_1T_OP(generic_gen_op, l_sfgeu_null_t_table, gen_op_sfgeu_null); +DEF_1T_OP(generic_gen_op, l_sfleu_null_t_table, gen_op_sfleu_null); +DEF_1T_OP(imm_gen_op, l_sfgeu_imm_t_table, gen_op_sfgeu_imm); +DEF_2T_OP(generic_gen_op, l_sfgeu_t_table, gen_op_sfgeu); + +void gen_l_sfgeu(struct op_queue *opq, int param_t[3], int delay_slot) +{ + if(!opq->param[0] && !opq->param[1]) { + gen_op_set_flag(opq, 1); + return; + } + + if(!opq->param[0]) { + /* sfleu IS correct */ + if(param_t[1] == T_NONE) { + if(0 >= opq->param[1]) + gen_op_set_flag(opq, 1); + else + gen_op_clear_flag(opq, 1); + } else + l_sfleu_null_t_table[param_t[1]](opq, 1); + return; + } + + if(!opq->param[1]) { + l_sfgeu_null_t_table[param_t[0]](opq, 1); + return; + } + if(param_t[1] == T_NONE) + l_sfgeu_imm_t_table[param_t[0]](opq, 1, opq->param[1]); + else + l_sfgeu_t_table[param_t[0]][param_t[1]](opq, 1); +} + +DEF_1T_OP(generic_gen_op, l_sfgts_null_t_table, gen_op_sfgts_null); +DEF_1T_OP(generic_gen_op, l_sflts_null_t_table, gen_op_sflts_null); +DEF_1T_OP(imm_gen_op, l_sfgts_imm_t_table, gen_op_sfgts_imm); +DEF_2T_OP(generic_gen_op, l_sfgts_t_table, gen_op_sfgts); + +void gen_l_sfgts(struct op_queue *opq, int param_t[3], int delay_slot) +{ + if(!opq->param[0] && !opq->param[1]) { + gen_op_clear_flag(opq, 1); + return; + } + + if(!opq->param[0]) { + /* sflts IS correct */ + if(param_t[1] == T_NONE) { + if(0 > (orreg_t)opq->param[1]) + gen_op_set_flag(opq, 1); + else + gen_op_clear_flag(opq, 1); + } else + l_sflts_null_t_table[param_t[1]](opq, 1); + return; + } + + if(!opq->param[1]) { + l_sfgts_null_t_table[param_t[0]](opq, 1); + return; + } + + if(param_t[1] == T_NONE) + l_sfgts_imm_t_table[param_t[0]](opq, 1, opq->param[1]); + else + l_sfgts_t_table[param_t[0]][param_t[1]](opq, 1); +} + +DEF_1T_OP(generic_gen_op, l_sfgtu_null_t_table, gen_op_sfgtu_null); +DEF_1T_OP(generic_gen_op, l_sfltu_null_t_table, gen_op_sfltu_null); +DEF_1T_OP(imm_gen_op, l_sfgtu_imm_t_table, gen_op_sfgtu_imm); +DEF_2T_OP(generic_gen_op, l_sfgtu_t_table, gen_op_sfgtu); + +void gen_l_sfgtu(struct op_queue *opq, int param_t[3], int delay_slot) +{ + if(!opq->param[0] && !opq->param[1]) { + gen_op_clear_flag(opq, 1); + return; + } + + if(!opq->param[0]) { + /* sfltu IS correct */ + if(param_t[1] == T_NONE) { + if(0 > opq->param[1]) + gen_op_set_flag(opq, 1); + else + gen_op_clear_flag(opq, 1); + } else + l_sfltu_null_t_table[param_t[1]](opq, 1); + return; + } + + if(!opq->param[1]) { + l_sfgtu_null_t_table[param_t[0]](opq, 1); + return; + } + + if(param_t[1] == T_NONE) + l_sfgtu_imm_t_table[param_t[0]](opq, 1, opq->param[1]); + else + l_sfgtu_t_table[param_t[0]][param_t[1]](opq, 1); +} + +DEF_1T_OP(imm_gen_op, l_sfles_imm_t_table, gen_op_sfles_imm); +DEF_2T_OP(generic_gen_op, l_sfles_t_table, gen_op_sfles); + +void gen_l_sfles(struct op_queue *opq, int param_t[3], int delay_slot) +{ + if(!opq->param[0] && !opq->param[1]) { + gen_op_set_flag(opq, 1); + return; + } + + if(!opq->param[0]) { + /* sfges IS correct */ + if(param_t[1] == T_NONE) { + if(0 <= (orreg_t)opq->param[1]) + gen_op_set_flag(opq, 1); + else + gen_op_clear_flag(opq, 1); + } else + l_sfges_null_t_table[param_t[1]](opq, 1); + return; + } + + if(!opq->param[1]) { + l_sfles_null_t_table[param_t[0]](opq, 1); + return; + } + + if(param_t[1] == T_NONE) + l_sfles_imm_t_table[param_t[0]](opq, 1, opq->param[1]); + else + l_sfles_t_table[param_t[0]][param_t[1]](opq, 1); +} + +DEF_1T_OP(imm_gen_op, l_sfleu_imm_t_table, gen_op_sfleu_imm); +DEF_2T_OP(generic_gen_op, l_sfleu_t_table, gen_op_sfleu); + +void gen_l_sfleu(struct op_queue *opq, int param_t[3], int delay_slot) +{ + if(!opq->param[0] && !opq->param[1]) { + gen_op_set_flag(opq, 1); + return; + } + + if(!opq->param[0]) { + /* sfleu IS correct */ + if(param_t[1] == T_NONE) { + if(0 <= opq->param[1]) + gen_op_set_flag(opq, 1); + else + gen_op_clear_flag(opq, 1); + } else + l_sfgeu_null_t_table[param_t[1]](opq, 1); + return; + } + + if(!opq->param[1]) { + l_sfleu_null_t_table[param_t[0]](opq, 1); + return; + } + + if(param_t[1] == T_NONE) + l_sfleu_imm_t_table[param_t[0]](opq, 1, opq->param[1]); + else + l_sfleu_t_table[param_t[0]][param_t[1]](opq, 1); +} + +DEF_1T_OP(imm_gen_op, l_sflts_imm_t_table, gen_op_sflts_imm); +DEF_2T_OP(generic_gen_op, l_sflts_t_table, gen_op_sflts); + +void gen_l_sflts(struct op_queue *opq, int param_t[3], int delay_slot) +{ + if(!opq->param[0] && !opq->param[1]) { + gen_op_clear_flag(opq, 1); + return; + } + + if(!opq->param[0]) { + /* sfgts IS correct */ + if(param_t[1] == T_NONE) { + if(0 < (orreg_t)opq->param[1]) + gen_op_set_flag(opq, 1); + else + gen_op_clear_flag(opq, 1); + } else + l_sfgts_null_t_table[param_t[1]](opq, 1); + return; + } + + if(!opq->param[1]) { + l_sflts_null_t_table[param_t[0]](opq, 1); + return; + } + + if(param_t[1] == T_NONE) + l_sflts_imm_t_table[param_t[0]](opq, 1, opq->param[1]); + else + l_sflts_t_table[param_t[0]][param_t[1]](opq, 1); +} + +DEF_1T_OP(imm_gen_op, l_sfltu_imm_t_table, gen_op_sfltu_imm); +DEF_2T_OP(generic_gen_op, l_sfltu_t_table, gen_op_sfltu); + +void gen_l_sfltu(struct op_queue *opq, int param_t[3], int delay_slot) +{ + if(!opq->param[0] && !opq->param[1]) { + gen_op_clear_flag(opq, 1); + return; + } + + if(!opq->param[0]) { + /* sfgtu IS correct */ + if(param_t[1] == T_NONE) { + if(0 < opq->param[1]) + gen_op_set_flag(opq, 1); + else + gen_op_clear_flag(opq, 1); + } else + l_sfgtu_null_t_table[param_t[1]](opq, 1); + return; + } + + if(!opq->param[1]) { + l_sfltu_null_t_table[param_t[0]](opq, 1); + return; + } + + if(param_t[1] == T_NONE) + l_sfltu_imm_t_table[param_t[0]](opq, 1, opq->param[1]); + else + l_sfltu_t_table[param_t[0]][param_t[1]](opq, 1); +} + +DEF_1T_OP(generic_gen_op, l_sfne_null_t_table, gen_op_sfne_null); +DEF_1T_OP(imm_gen_op, l_sfne_imm_t_table, gen_op_sfne_imm); +DEF_2T_OP(generic_gen_op, l_sfne_t_table, gen_op_sfne); + +void gen_l_sfne(struct op_queue *opq, int param_t[3], int delay_slot) +{ + if(!opq->param[0] && !opq->param[1]) { + gen_op_set_flag(opq, 1); + return; + } + + if(!opq->param[0]) { + if(param_t[1] == T_NONE) + if(opq->param[1]) + gen_op_set_flag(opq, 1); + else + gen_op_clear_flag(opq, 1); + else + l_sfne_null_t_table[param_t[1]](opq, 1); + return; + } + + if(!opq->param[1]) { + l_sfne_null_t_table[param_t[0]](opq, 1); + return; + } + + if(param_t[1] == T_NONE) + l_sfne_imm_t_table[param_t[0]](opq, 1, opq->param[1]); + else + l_sfne_t_table[param_t[0]][param_t[1]](opq, 1); +} + +DEF_2T_OP(imm_gen_op, l_sll_imm_t_table, gen_op_sll_imm); +DEF_3T_OP(generic_gen_op, l_sll_t_table, gen_op_sll); + +void gen_l_sll(struct op_queue *opq, int param_t[3], int delay_slot) +{ + if(!opq->param[0]) + return; + + if(!opq->param[1]) { + clear_t[param_t[0]](opq, 1); + return; + } + + if(!opq->param[2]) { + move_t_t[param_t[0]][param_t[1]](opq, 1); + return; + } + + if(param_t[2] == T_NONE) + l_sll_imm_t_table[param_t[0]][param_t[1]](opq, 1, opq->param[2]); + else + l_sll_t_table[param_t[0]][param_t[1]][param_t[2]](opq, 1); +} + +DEF_2T_OP(imm_gen_op, l_sra_imm_t_table, gen_op_sra_imm); +DEF_3T_OP(generic_gen_op, l_sra_t_table, gen_op_sra); + +void gen_l_sra(struct op_queue *opq, int param_t[3], int delay_slot) +{ + if(!opq->param[0]) + return; + + if(!opq->param[1]) { + clear_t[param_t[0]](opq, 1); + return; + } + + if(!opq->param[2]) { + move_t_t[param_t[0]][param_t[1]](opq, 1); + return; + } + + if(param_t[2] == T_NONE) + l_sra_imm_t_table[param_t[0]][param_t[1]](opq, 1, opq->param[2]); + else + l_sra_t_table[param_t[0]][param_t[1]][param_t[2]](opq, 1); +} + +DEF_2T_OP(imm_gen_op, l_srl_imm_t_table, gen_op_srl_imm); +DEF_3T_OP(generic_gen_op, l_srl_t_table, gen_op_srl); + +void gen_l_srl(struct op_queue *opq, int param_t[3], int delay_slot) +{ + if(!opq->param[0]) + return; + + if(!opq->param[1]) { + clear_t[param_t[0]](opq, 1); + return; + } + + if(!opq->param[2]) { + move_t_t[param_t[0]][param_t[1]](opq, 1); + return; + } + + if(param_t[2] == T_NONE) + l_srl_imm_t_table[param_t[0]][param_t[1]](opq, 1, opq->param[2]); + else + l_srl_t_table[param_t[0]][param_t[1]][param_t[2]](opq, 1); +} + +DEF_2T_OP(generic_gen_op, l_neg_t_table, gen_op_neg); +DEF_3T_OP(generic_gen_op, l_sub_t_table, gen_op_sub); + +void gen_l_sub(struct op_queue *opq, int param_t[3], int delay_slot) +{ + if(!opq->param[0]) + return; + + if((param_t[2] != T_NONE) && (opq->param[1] == opq->param[2])) { + clear_t[param_t[0]](opq, 1); + return; + } + + if(!opq->param[1] && !opq->param[2]) { + clear_t[param_t[0]](opq, 1); + return; + } + + if(!opq->param[1]) { + if(param_t[2] == T_NONE) + mov_t_imm[param_t[0]](opq, 1, -opq->param[2]); + else + l_neg_t_table[param_t[0]][param_t[2]](opq, 1); + return; + } + + if(!opq->param[2]) { + move_t_t[param_t[0]][param_t[1]](opq, 1); + return; + } + + l_sub_t_table[param_t[0]][param_t[1]][param_t[2]](opq, 1); +} + +/* FIXME: This will not work if the l.sys is in a delay slot */ +void gen_l_sys(struct op_queue *opq, int param_t[3], int delay_slot) +{ + if(do_stats) + /* All gprs are current since this insn doesn't touch any reg */ + gen_op_analysis(opq, 1); + + if(!delay_slot) + gen_op_prep_sys(opq, 1); + else + gen_op_prep_sys_delay(opq, 1); + + gen_op_do_sched(opq, 1); + gen_op_do_jump(opq, 1); +} + +/* FIXME: This will not work if the l.trap is in a delay slot */ +void gen_l_trap(struct op_queue *opq, int param_t[3], int delay_slot) +{ + if(do_stats) + /* All gprs are current since this insn doesn't touch any reg */ + gen_op_analysis(opq, 1); + + if(!delay_slot) + gen_op_prep_trap(opq, 1); + else + gen_op_prep_trap_delay(opq, 1); +} + +DEF_2T_OP(imm_gen_op, l_xor_imm_t_table, gen_op_xor_imm); +/* FIXME: Make unused elements NULL */ +DEF_3T_OP_NEQ(generic_gen_op, l_xor_t_table, gen_op_xor); + +void gen_l_xor(struct op_queue *opq, int param_t[3], int delay_slot) +{ + if(!opq->param[0]) + return; + + if((param_t[2] != T_NONE) && (opq->param[1] == opq->param[2])) { + clear_t[param_t[0]](opq, 1); + return; + } + + if(!opq->param[2]) { + if((param_t[2] == T_NONE) && (opq->param[0] == opq->param[1])) + return; + move_t_t[param_t[0]][param_t[1]](opq, 1); + return; + } + + if(!opq->param[1]) { + if(param_t[2] == T_NONE) { + mov_t_imm[param_t[0]](opq, 1, opq->param[2]); + return; + } + move_t_t[param_t[0]][param_t[2]](opq, 1); + return; + } + + if(param_t[2] == T_NONE) + l_xor_imm_t_table[param_t[0]][param_t[1]](opq, 1, opq->param[2]); + else + l_xor_t_table[param_t[0]][param_t[1]][param_t[2]](opq, 1); +} + +void gen_l_invalid(struct op_queue *opq, int param_t[3], int delay_slot) +{ + if(!delay_slot) { + gen_op_illegal(opq, 1); + gen_op_do_jump(opq, 1); + } else { + gen_op_illegal_delay(opq, 1); + gen_op_do_jump(opq, 1); + } +} + +/*----------------------------------[ Floating point instructions (stubs) ]---*/ +void gen_lf_add_s(struct op_queue *opq, int param_t[3], int delay_slot) +{ + gen_l_invalid(opq, param_t, delay_slot); +} + +void gen_lf_div_s(struct op_queue *opq, int param_t[3], int delay_slot) +{ + gen_l_invalid(opq, param_t, delay_slot); +} + +void gen_lf_ftoi_s(struct op_queue *opq, int param_t[3], int delay_slot) +{ + gen_l_invalid(opq, param_t, delay_slot); +} + +void gen_lf_itof_s(struct op_queue *opq, int param_t[3], int delay_slot) +{ + gen_l_invalid(opq, param_t, delay_slot); +} + +void gen_lf_madd_s(struct op_queue *opq, int param_t[3], int delay_slot) +{ + gen_l_invalid(opq, param_t, delay_slot); +} + +void gen_lf_mul_s(struct op_queue *opq, int param_t[3], int delay_slot) +{ + gen_l_invalid(opq, param_t, delay_slot); +} + +void gen_lf_rem_s(struct op_queue *opq, int param_t[3], int delay_slot) +{ + gen_l_invalid(opq, param_t, delay_slot); +} + +void gen_lf_sfeq_s(struct op_queue *opq, int param_t[3], int delay_slot) +{ + gen_l_invalid(opq, param_t, delay_slot); +} + +void gen_lf_sfge_s(struct op_queue *opq, int param_t[3], int delay_slot) +{ + gen_l_invalid(opq, param_t, delay_slot); +} + +void gen_lf_sfgt_s(struct op_queue *opq, int param_t[3], int delay_slot) +{ + gen_l_invalid(opq, param_t, delay_slot); +} + +void gen_lf_sfle_s(struct op_queue *opq, int param_t[3], int delay_slot) +{ + gen_l_invalid(opq, param_t, delay_slot); +} + +void gen_lf_sflt_s(struct op_queue *opq, int param_t[3], int delay_slot) +{ + gen_l_invalid(opq, param_t, delay_slot); +} + +void gen_lf_sfne_s(struct op_queue *opq, int param_t[3], int delay_slot) +{ + gen_l_invalid(opq, param_t, delay_slot); +} + +void gen_lf_sub_s(struct op_queue *opq, int param_t[3], int delay_slot) +{ + gen_l_invalid(opq, param_t, delay_slot); +} + Index: or32/execute.c =================================================================== --- or32/execute.c (nonexistent) +++ or32/execute.c (revision 1765) @@ -0,0 +1,1180 @@ +/* execute.c -- OR1K architecture dependent simulation + + 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 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. */ + + +/* 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 + +/* Package includes */ +#include "execute.h" +#include "toplevel-support.h" +#include "except.h" +#include "labels.h" +#include "gdbcomm.h" +#include "sched.h" +#include "stats.h" +#include "opcode/or32.h" +#include "dmmu.h" +#include "immu.h" +#include "sim-cmd.h" +#include "vapi.h" +#include "debug-unit.h" +#include "branch-predict.h" +#include "support/simprintf.h" +#include "sprs.h" +#include "rsp-server.h" + + +/* Includes and macros for simple execution */ +#if SIMPLE_EXECUTION + +#define SET_PARAM0(val) set_operand(0, val, current->insn_index, current->insn) + +#define PARAM0 eval_operand(0, current->insn_index, current->insn) +#define PARAM1 eval_operand(1, current->insn_index, current->insn) +#define PARAM2 eval_operand(2, current->insn_index, current->insn) + +#define INSTRUCTION(name) void name (struct iqueue_entry *current) + +#endif /* SIMPLE_EXECUTION */ + + +/*! Current cpu state. Globally available. */ +struct cpu_state cpu_state; + +/*! Temporary program counter. Globally available */ +oraddr_t pcnext; + +/*! Num cycles waiting for stores to complete. Globally available */ +int sbuf_wait_cyc = 0; + +/*! Number of total store cycles. Globally available */ +int sbuf_total_cyc = 0; + +/*! Whether we are doing statistical analysis. Globally available */ +int do_stats = 0; + +/*! History of execution. Globally available */ +struct hist_exec *hist_exec_tail = NULL; + +/* Benchmark multi issue execution. This file only */ +static int multissue[20]; +static int issued_per_cycle = 4; + +/* Store buffer analysis - stores are accumulated and commited when IO is + idle. This file only */ +static int sbuf_head = 0; +static int sbuf_tail = 0; +static int sbuf_count = 0; +#if !(DYNAMIC_EXECUTION) +static int sbuf_buf[MAX_SBUF_LEN] = { 0 }; +#endif + +static int sbuf_prev_cycles = 0; + +/* Variables used throughout this file to share information */ +static int breakpoint; +static int next_delay_insn; + +/* Forward declaration of static functions */ +#if !(DYNAMIC_EXECUTION) +static void decode_execute (struct iqueue_entry *current); +#endif + +/*---------------------------------------------------------------------------*/ +/*!Get an actual value of a specific register + + Implementation specific. Abort if we are given a duff register. Only used + externally to support simprintf(). + + @param[in] regno The register of interest + + @return The value of the register */ +/*---------------------------------------------------------------------------*/ +uorreg_t +evalsim_reg (unsigned int regno) +{ + if (regno < MAX_GPRS) + { +#if RAW_RANGE_STATS + int delta = (runtime.sim.cycles - raw_stats.reg[regno]); + + if ((unsigned long) delta < (unsigned long) RAW_RANGE) + { + raw_stats.range[delta]++; + } +#endif /* RAW_RANGE */ + + return cpu_state.reg[regno]; + } + else + { + PRINTF ("\nABORT: read out of registers\n"); + sim_done (); + return 0; + } +} /* evalsim_reg() */ + + +/*---------------------------------------------------------------------------*/ +/*!Set a specific register with value + + Implementation specific. Abort if we are given a duff register. + + @param[in] regno The register of interest + @param[in] value The value to be set */ +/*---------------------------------------------------------------------------*/ +void +setsim_reg (unsigned int regno, + uorreg_t value) +{ + if (regno == 0) /* gpr0 is always zero */ + { + value = 0; + } + + if (regno < MAX_GPRS) + { + cpu_state.reg[regno] = value; + } + else + { + PRINTF ("\nABORT: write out of registers\n"); + sim_done (); + } + +#if RAW_RANGE_STATS + raw_stats.reg[regno] = runtime.sim.cycles; +#endif /* RAW_RANGE */ + +} /* setsim_reg() */ + + +/*---------------------------------------------------------------------------*/ +/*!Evaluates source operand operand + + Implementation specific. Declared global, although this is only actually + required for DYNAMIC_EXECUTION, + + @param[in] insn The instruction + @param[in] opd The operand + + @return The value of the source operand */ +/*---------------------------------------------------------------------------*/ +uorreg_t +eval_operand_val (uint32_t insn, + struct insn_op_struct *opd) +{ + unsigned long operand = 0; + unsigned long sbit; + unsigned int nbits = 0; + + while (1) + { + operand |= + ((insn >> (opd->type & OPTYPE_SHR)) & ((1 << opd->data) - 1)) << + nbits; + nbits += opd->data; + + if (opd->type & OPTYPE_OP) + { + break; + } + + opd++; + } + + if (opd->type & OPTYPE_SIG) + { + sbit = (opd->type & OPTYPE_SBIT) >> OPTYPE_SBIT_SHR; + + if (operand & (1 << sbit)) + { + operand |= ~REG_C (0) << sbit; + } + } + + return operand; + +} /* eval_operand_val() */ + + +/*---------------------------------------------------------------------------*/ +/*!Does source operand depend on computation of dest operand? + + Cycle t Cycle t+1 + dst: irrelevant src: immediate always 0 + dst: reg1 direct src: reg2 direct 0 if reg1 != reg2 + dst: reg1 disp src: reg2 direct always 0 + dst: reg1 direct src: reg2 disp 0 if reg1 != reg2 + dst: reg1 disp src: reg2 disp always 1 (store must + finish before load) + dst: flag src: flag always 1 + + @param[in] prev Previous instruction + @param[in] next Next instruction + + @return Non-zero if yes. */ +/*---------------------------------------------------------------------------*/ +static int +check_depend (struct iqueue_entry *prev, + struct iqueue_entry *next) +{ + /* Find destination type. */ + unsigned long type = 0; + int prev_dis; + int next_dis; + orreg_t prev_reg_val = 0; + struct insn_op_struct *opd; + + if (or32_opcodes[prev->insn_index].flags & OR32_W_FLAG + && or32_opcodes[next->insn_index].flags & OR32_R_FLAG) + { + return 1; + } + + opd = op_start[prev->insn_index]; + prev_dis = 0; + + while (1) + { + if (opd->type & OPTYPE_DIS) + { + prev_dis = 1; + } + + if (opd->type & OPTYPE_DST) + { + type = opd->type; + + if (prev_dis) + { + type |= OPTYPE_DIS; + } + + /* Destination is always a register */ + prev_reg_val = eval_operand_val (prev->insn, opd); + break; + } + + if (opd->type & OPTYPE_LAST) + { + return 0; /* Doesn't have a destination operand */ + } + + if (opd->type & OPTYPE_OP) + { + prev_dis = 0; + } + + opd++; + } + + /* We search all source operands - if we find confict => return 1 */ + opd = op_start[next->insn_index]; + next_dis = 0; + + while (1) + { + if (opd->type & OPTYPE_DIS) + { + next_dis = 1; + } + + /* This instruction sequence also depends on order of execution: + l.lw r1, k(r1) + l.sw k(r1), r4 + Here r1 is a destination in l.sw */ + + /* FIXME: This situation is not handeld here when r1 == r2: + l.sw k(r1), r4 + l.lw r3, k(r2) */ + if (!(opd->type & OPTYPE_DST) || (next_dis && (opd->type & OPTYPE_DST))) + { + if (opd->type & OPTYPE_REG) + { + if (eval_operand_val (next->insn, opd) == prev_reg_val) + { + return 1; + } + } + } + + if (opd->type & OPTYPE_LAST) + { + break; + } + + opd++; + } + + return 0; + +} /* check_depend() */ + + +/*---------------------------------------------------------------------------*/ +/*!Should instruction NOT be executed? + + Modified by CZ 26/05/01 for new mode execution. + + @return Nonzero if instruction should NOT be executed */ +/*---------------------------------------------------------------------------*/ +static int +fetch () +{ + static int break_just_hit = 0; + + if (NULL != breakpoints) + { + /* MM: Check for breakpoint. This has to be done in fetch cycle, + because of peripheria. + MM1709: if we cannot access the memory entry, we could not set the + breakpoint earlier, so just check the breakpoint list. */ + if (has_breakpoint (peek_into_itlb (cpu_state.pc)) && !break_just_hit) + { + break_just_hit = 1; + return 1; /* Breakpoint set. */ + } + break_just_hit = 0; + } + + breakpoint = 0; + cpu_state.iqueue.insn_addr = cpu_state.pc; + cpu_state.iqueue.insn = eval_insn (cpu_state.pc, &breakpoint); + + /* Fetch instruction. */ + if (!except_pending) + { + runtime.cpu.instructions++; + } + + /* update_pc will be called after execution */ + return 0; + +} /* fetch() */ + + +/*---------------------------------------------------------------------------*/ +/*!This code actually updates the PC value */ +/*---------------------------------------------------------------------------*/ +static void +update_pc () +{ + cpu_state.delay_insn = next_delay_insn; + cpu_state.sprs[SPR_PPC] = cpu_state.pc; /* Store value for later */ + cpu_state.pc = pcnext; + pcnext = cpu_state.delay_insn ? cpu_state.pc_delay : + pcnext + 4; +} /* update_pc() */ + + +/*---------------------------------------------------------------------------*/ +/*!Perform analysis of the instruction being executed + + This could be static for SIMPLE_EXECUTION, but made global for general use. + + @param[in] current The instruction being executed */ +/*---------------------------------------------------------------------------*/ +void +analysis (struct iqueue_entry *current) +{ + if (config.cpu.dependstats) + { + /* Dynamic, dependency stats. */ + adddstats (cpu_state.icomplet.insn_index, current->insn_index, 1, + check_depend (&cpu_state.icomplet, current)); + + /* Dynamic, functional units stats. */ + addfstats (or32_opcodes[cpu_state.icomplet.insn_index].func_unit, + or32_opcodes[current->insn_index].func_unit, 1, + check_depend (&cpu_state.icomplet, current)); + + /* Dynamic, single stats. */ + addsstats (current->insn_index, 1); + } + + if (config.cpu.superscalar) + { + if ((or32_opcodes[current->insn_index].func_unit == it_branch) || + (or32_opcodes[current->insn_index].func_unit == it_jump)) + runtime.sim.storecycles += 0; + + if (or32_opcodes[current->insn_index].func_unit == it_store) + runtime.sim.storecycles += 1; + + if (or32_opcodes[current->insn_index].func_unit == it_load) + runtime.sim.loadcycles += 1; + + /* Pseudo multiple issue benchmark */ + if ((multissue[or32_opcodes[current->insn_index].func_unit] < 1) || + (check_depend (&cpu_state.icomplet, current)) + || (issued_per_cycle < 1)) + { + int i; + for (i = 0; i < 20; i++) + multissue[i] = 2; + issued_per_cycle = 2; + runtime.cpu.supercycles++; + if (check_depend (&cpu_state.icomplet, current)) + runtime.cpu.hazardwait++; + multissue[it_unknown] = 2; + multissue[it_shift] = 2; + multissue[it_compare] = 1; + multissue[it_branch] = 1; + multissue[it_jump] = 1; + multissue[it_extend] = 2; + multissue[it_nop] = 2; + multissue[it_move] = 2; + multissue[it_movimm] = 2; + multissue[it_arith] = 2; + multissue[it_store] = 2; + multissue[it_load] = 2; + } + multissue[or32_opcodes[current->insn_index].func_unit]--; + issued_per_cycle--; + } + + if (config.cpu.dependstats) + /* Instruction waits in completition buffer until retired. */ + memcpy (&cpu_state.icomplet, current, sizeof (struct iqueue_entry)); + + if (config.sim.history) + { + /* History of execution */ + hist_exec_tail = hist_exec_tail->next; + hist_exec_tail->addr = cpu_state.icomplet.insn_addr; + } + + if (config.sim.exe_log) + dump_exe_log (); + +} /* analysis() */ + + +#if !(DYNAMIC_EXECUTION) + +/*---------------------------------------------------------------------------*/ +/*!Store buffer analysis for store instructions + + Stores are accumulated and commited when IO is idle + + @param[in] cyc Number of cycles being analysed */ +/*---------------------------------------------------------------------------*/ +static void +sbuf_store (int cyc) +{ + int delta = runtime.sim.cycles - sbuf_prev_cycles; + + sbuf_total_cyc += cyc; + sbuf_prev_cycles = runtime.sim.cycles; + + /* Take stores from buffer, that occured meanwhile */ + while (sbuf_count && delta >= sbuf_buf[sbuf_tail]) + { + delta -= sbuf_buf[sbuf_tail]; + sbuf_tail = (sbuf_tail + 1) % MAX_SBUF_LEN; + sbuf_count--; + } + + if (sbuf_count) + { + sbuf_buf[sbuf_tail] -= delta; + } + + /* Store buffer is full, take one out */ + if (sbuf_count >= config.cpu.sbuf_len) + { + sbuf_wait_cyc += sbuf_buf[sbuf_tail]; + runtime.sim.mem_cycles += sbuf_buf[sbuf_tail]; + sbuf_prev_cycles += sbuf_buf[sbuf_tail]; + sbuf_tail = (sbuf_tail + 1) % MAX_SBUF_LEN; + sbuf_count--; + } + + /* Put newest store in the buffer */ + sbuf_buf[sbuf_head] = cyc; + sbuf_head = (sbuf_head + 1) % MAX_SBUF_LEN; + sbuf_count++; + +} /* sbuf_store() */ + + +/*---------------------------------------------------------------------------*/ +/*!Store buffer analysis for load instructions + + Previous stores should commit, before any load */ +/*---------------------------------------------------------------------------*/ +static void +sbuf_load () +{ + int delta = runtime.sim.cycles - sbuf_prev_cycles; + sbuf_prev_cycles = runtime.sim.cycles; + + /* Take stores from buffer, that occured meanwhile */ + while (sbuf_count && delta >= sbuf_buf[sbuf_tail]) + { + delta -= sbuf_buf[sbuf_tail]; + sbuf_tail = (sbuf_tail + 1) % MAX_SBUF_LEN; + sbuf_count--; + } + + if (sbuf_count) + { + sbuf_buf[sbuf_tail] -= delta; + } + + /* Wait for all stores to complete */ + while (sbuf_count > 0) + { + sbuf_wait_cyc += sbuf_buf[sbuf_tail]; + runtime.sim.mem_cycles += sbuf_buf[sbuf_tail]; + sbuf_prev_cycles += sbuf_buf[sbuf_tail]; + sbuf_tail = (sbuf_tail + 1) % MAX_SBUF_LEN; + sbuf_count--; + } +} /* sbuf_load() */ + +#endif /* !DYNAMIC_EXECUTION */ + + +/*---------------------------------------------------------------------------*/ +/*!Outputs dissasembled instruction */ +/*---------------------------------------------------------------------------*/ +void +dump_exe_log () +{ + oraddr_t insn_addr = cpu_state.iqueue.insn_addr; + unsigned int i; + unsigned int j; + uorreg_t operand; + + if (insn_addr == 0xffffffff) + { + return; + } + + if ((config.sim.exe_log_start <= runtime.cpu.instructions) && + ((config.sim.exe_log_end <= 0) || + (runtime.cpu.instructions <= config.sim.exe_log_end))) + { + struct label_entry *entry; + + if (config.sim.exe_log_marker && + !(runtime.cpu.instructions % config.sim.exe_log_marker)) + { + fprintf (runtime.sim.fexe_log, + "--------------------- %8lli instruction " + "---------------------\n", + runtime.cpu.instructions); + } + + switch (config.sim.exe_log_type) + { + case EXE_LOG_HARDWARE: + fprintf (runtime.sim.fexe_log, + "\nEXECUTED(%11llu): %" PRIxADDR ": ", + runtime.cpu.instructions, insn_addr); + fprintf (runtime.sim.fexe_log, "%.2x%.2x", + eval_direct8 (insn_addr, 0, 0), + eval_direct8 (insn_addr + 1, 0, 0)); + fprintf (runtime.sim.fexe_log, "%.2x%.2x", + eval_direct8 (insn_addr + 2, 0, 0), + eval_direct8 (insn_addr + 3, 0, 0)); + + for (i = 0; i < MAX_GPRS; i++) + { + if (i % 4 == 0) + { + fprintf (runtime.sim.fexe_log, "\n"); + } + + fprintf (runtime.sim.fexe_log, "GPR%2u: %" PRIxREG " ", i, + cpu_state.reg[i]); + } + + fprintf (runtime.sim.fexe_log, "\n"); + fprintf (runtime.sim.fexe_log, "SR : %.8" PRIx32 " ", + cpu_state.sprs[SPR_SR]); + fprintf (runtime.sim.fexe_log, "EPCR0: %" PRIxADDR " ", + cpu_state.sprs[SPR_EPCR_BASE]); + fprintf (runtime.sim.fexe_log, "EEAR0: %" PRIxADDR " ", + cpu_state.sprs[SPR_EEAR_BASE]); + fprintf (runtime.sim.fexe_log, "ESR0 : %.8" PRIx32 "\n", + cpu_state.sprs[SPR_ESR_BASE]); + break; + + case EXE_LOG_SIMPLE: + case EXE_LOG_SOFTWARE: + disassemble_index (cpu_state.iqueue.insn, + cpu_state.iqueue.insn_index); + + entry = get_label (insn_addr); + if (entry) + { + fprintf (runtime.sim.fexe_log, "%s:\n", entry->name); + } + + if (config.sim.exe_log_type == EXE_LOG_SOFTWARE) + { + struct insn_op_struct *opd = + op_start[cpu_state.iqueue.insn_index]; + + j = 0; + while (1) + { + operand = eval_operand_val (cpu_state.iqueue.insn, opd); + while (!(opd->type & OPTYPE_OP)) + { + opd++; + } + if (opd->type & OPTYPE_DIS) + { + fprintf (runtime.sim.fexe_log, + "EA =%" PRIxADDR " PA =%" PRIxADDR " ", + cpu_state.insn_ea, + peek_into_dtlb (cpu_state.insn_ea, 0, 0)); + opd++; /* Skip of register operand */ + j++; + } + else if ((opd->type & OPTYPE_REG) && operand) + { + fprintf (runtime.sim.fexe_log, "r%-2i=%" PRIxREG " ", + (int) operand, evalsim_reg (operand)); + } + else + { + fprintf (runtime.sim.fexe_log, " "); + } + j++; + if (opd->type & OPTYPE_LAST) + { + break; + } + opd++; + } + if (or32_opcodes[cpu_state.iqueue.insn_index].flags & OR32_R_FLAG) + { + fprintf (runtime.sim.fexe_log, "SR =%" PRIxREG " ", + cpu_state.sprs[SPR_SR]); + j++; + } + while (j < 3) + { + fprintf (runtime.sim.fexe_log, " "); + j++; + } + } + fprintf (runtime.sim.fexe_log, "%" PRIxADDR " ", insn_addr); + fprintf (runtime.sim.fexe_log, "%s\n", disassembled); + } + } +} /* dump_exe_log() */ + + +/*---------------------------------------------------------------------------*/ +/*!Dump registers + + Supports the CLI 'r' and 't' commands */ +/*---------------------------------------------------------------------------*/ +void +dumpreg () +{ + int i; + oraddr_t physical_pc; + + if ((physical_pc = peek_into_itlb (cpu_state.iqueue.insn_addr))) + { + disassemble_memory (physical_pc, physical_pc + 4, 0); + } + else + { + PRINTF ("INTERNAL SIMULATOR ERROR:\n"); + PRINTF ("no translation for currently executed instruction\n"); + } + + // generate_time_pretty (temp, runtime.sim.cycles * config.sim.clkcycle_ps); + PRINTF (" (executed) [cycle %lld, #%lld]\n", runtime.sim.cycles, + runtime.cpu.instructions); + if (config.cpu.superscalar) + { + PRINTF ("Superscalar CYCLES: %u", runtime.cpu.supercycles); + } + if (config.cpu.hazards) + { + PRINTF (" HAZARDWAIT: %u\n", runtime.cpu.hazardwait); + } + else if (config.cpu.superscalar) + { + PRINTF ("\n"); + } + + if ((physical_pc = peek_into_itlb (cpu_state.pc))) + { + disassemble_memory (physical_pc, physical_pc + 4, 0); + } + else + { + PRINTF ("%" PRIxADDR ": : xxxxxxxx ITLB miss follows", cpu_state.pc); + } + + PRINTF (" (next insn) %s", (cpu_state.delay_insn ? "(delay insn)" : "")); + + for (i = 0; i < MAX_GPRS; i++) + { + if (i % 4 == 0) + { + PRINTF ("\n"); + } + + PRINTF ("GPR%.2u: %" PRIxREG " ", i, evalsim_reg (i)); + } + + PRINTF ("flag: %u\n", cpu_state.sprs[SPR_SR] & SPR_SR_F ? 1 : 0); + +} /* dumpreg() */ + + +/*---------------------------------------------------------------------------*/ +/*!Wrapper around real decode_execute function + + Some statistics here only + + @param[in] current Instruction being executed */ +/*---------------------------------------------------------------------------*/ +static void +decode_execute_wrapper (struct iqueue_entry *current) +{ + breakpoint = 0; + +#ifndef HAVE_EXECUTION +#error HAVE_EXECUTION has to be defined in order to execute programs. +#endif + + /* FIXME: Most of this file is not needed with DYNAMIC_EXECUTION */ +#if !(DYNAMIC_EXECUTION) + decode_execute (current); +#endif + +#if SET_OV_FLAG + /* Check for range exception */ + if ((cpu_state.sprs[SPR_SR] & SPR_SR_OVE) && + (cpu_state.sprs[SPR_SR] & SPR_SR_OV)) + { + except_handle (EXCEPT_RANGE, cpu_state.sprs[SPR_EEAR_BASE]); + } +#endif + + if (breakpoint) + { + except_handle (EXCEPT_TRAP, cpu_state.sprs[SPR_EEAR_BASE]); + } +} /* decode_execute_wrapper() */ + +/*---------------------------------------------------------------------------*/ +/*!Reset the CPU */ +/*---------------------------------------------------------------------------*/ +void +cpu_reset () +{ + int i; + struct hist_exec *hist_exec_head = NULL; + struct hist_exec *hist_exec_new; + + runtime.sim.cycles = 0; + runtime.sim.loadcycles = 0; + runtime.sim.storecycles = 0; + runtime.cpu.instructions = 0; + runtime.cpu.supercycles = 0; + runtime.cpu.hazardwait = 0; + + for (i = 0; i < MAX_GPRS; i++) + { + setsim_reg (i, 0); + } + + memset (&cpu_state.iqueue, 0, sizeof (cpu_state.iqueue)); + memset (&cpu_state.icomplet, 0, sizeof (cpu_state.icomplet)); + + sbuf_head = 0; + sbuf_tail = 0; + sbuf_count = 0; + sbuf_prev_cycles = 0; + + /* Initialise execution history circular buffer */ + for (i = 0; i < HISTEXEC_LEN; i++) + { + hist_exec_new = malloc (sizeof (struct hist_exec)); + + if (!hist_exec_new) + { + fprintf (stderr, "Out-of-memory\n"); + exit (1); + } + + if (!hist_exec_head) + { + hist_exec_head = hist_exec_new; + } + else + { + hist_exec_tail->next = hist_exec_new; + } + + hist_exec_new->prev = hist_exec_tail; + hist_exec_tail = hist_exec_new; + } + + /* Make hist_exec_tail->next point to hist_exec_head */ + hist_exec_tail->next = hist_exec_head; + hist_exec_head->prev = hist_exec_tail; + + /* MM1409: All progs should start at reset vector entry! This sorted out by + setting the cpu_state.pc field below. Not clear this is very good code! */ + pcnext = 0x0; + + if (config.sim.verbose) + { + PRINTF ("Starting at 0x%" PRIxADDR "\n", pcnext); + } + + cpu_state.pc = pcnext; + pcnext += 4; + + /* MM1409: All programs should set their stack pointer! */ +#if !(DYNAMIC_EXECUTION) + except_handle (EXCEPT_RESET, 0); + update_pc (); +#endif + + except_pending = 0; + cpu_state.pc = EXCEPT_RESET; + +} /* cpu_reset() */ + + +/*---------------------------------------------------------------------------*/ +/*!Simulates one CPU clock cycle + + @return non-zero if a breakpoint is hit, zero otherwise. */ +/*---------------------------------------------------------------------------*/ +int +cpu_clock () +{ + except_pending = 0; + next_delay_insn = 0; + + if (fetch ()) + { + PRINTF ("Breakpoint hit.\n"); + return 1; + } + + if (except_pending) + { + update_pc (); + except_pending = 0; + return 0; + } + + if (breakpoint) + { + except_handle (EXCEPT_TRAP, cpu_state.sprs[SPR_EEAR_BASE]); + update_pc (); + except_pending = 0; + return 0; + } + + decode_execute_wrapper (&cpu_state.iqueue); + update_pc (); + return 0; + +} /* cpu_clock() */ + + +/*---------------------------------------------------------------------------*/ +/*!If decoding cannot be found, call this function */ +/*---------------------------------------------------------------------------*/ +#if SIMPLE_EXECUTION +void +l_invalid (struct iqueue_entry *current) +{ +#else +void +l_invalid () +{ +#endif + except_handle (EXCEPT_ILLEGAL, cpu_state.iqueue.insn_addr); + +} /* l_invalid() */ + + +/*---------------------------------------------------------------------------*/ +/*!The main execution loop */ +/*---------------------------------------------------------------------------*/ +void +exec_main () +{ + long long time_start; + + while (1) + { + time_start = runtime.sim.cycles; + if (config.debug.enabled) + { + while (runtime.cpu.stalled) + { + if (config.debug.rsp_enabled) + { + handle_rsp (); + } + else if (config.debug.gdb_enabled) + { + block_jtag (); + handle_server_socket (FALSE); + } + else + { + fprintf (stderr, "ERROR: CPU stalled and GDB connection not " + "enabled: Invoking CLI and terminating.\n"); + /* Dump the user into interactive mode. From there he or + she can decide what to do. */ + handle_sim_command (); + sim_done (); + } + if (runtime.sim.iprompt) + handle_sim_command (); + } + } + + /* Each cycle has counter of mem_cycles; this value is joined with cycles + at the end of the cycle; no sim originated memory accesses should be + performed inbetween. */ + runtime.sim.mem_cycles = 0; + + if (!config.pm.enabled || + !(config.pm.enabled & + (cpu_state.sprs[SPR_PMR] & (SPR_PMR_DME | SPR_PMR_SME)))) + { + if (cpu_clock ()) + { + /* A breakpoint has been hit, drop to interactive mode */ + handle_sim_command (); + } + } + + if (config.vapi.enabled && runtime.vapi.enabled) + { + vapi_check (); + } + + if (config.debug.gdb_enabled) + { + handle_server_socket (FALSE); /* block & check_stdin = false */ + } + + if (config.debug.enabled) + { + if (cpu_state.sprs[SPR_DMR1] & SPR_DMR1_ST) + { + set_stall_state (1); + + if (config.debug.rsp_enabled) + { + rsp_exception (EXCEPT_TRAP); + } + } + } + + runtime.sim.cycles += runtime.sim.mem_cycles; + scheduler.job_queue->time -= runtime.sim.cycles - time_start; + + if (scheduler.job_queue->time <= 0) + { + do_scheduler (); + } + } +} /* exec_main() */ + +#if COMPLEX_EXECUTION + +/* Include generated/built in decode_execute function */ +#include "execgen.c" + +#elif SIMPLE_EXECUTION + + +/*---------------------------------------------------------------------------*/ +/*!Evaluates source operand + + Implementation specific. + + @param[in] op_no The operand + @param[in] insn_index Address of the instruction + @param[in] insn The instruction + + @return The value of the operand */ +/*---------------------------------------------------------------------------*/ +static uorreg_t +eval_operand (int op_no, + unsigned long insn_index, + uint32_t insn) +{ + struct insn_op_struct *opd = op_start[insn_index]; + uorreg_t ret; + + while (op_no) + { + if (opd->type & OPTYPE_LAST) + { + fprintf (stderr, + "Instruction requested more operands than it has\n"); + exit (1); + } + + if ((opd->type & OPTYPE_OP) && !(opd->type & OPTYPE_DIS)) + { + op_no--; + } + + opd++; + } + + if (opd->type & OPTYPE_DIS) + { + ret = eval_operand_val (insn, opd); + + while (!(opd->type & OPTYPE_OP)) + { + opd++; + } + + opd++; + ret += evalsim_reg (eval_operand_val (insn, opd)); + cpu_state.insn_ea = ret; + + return ret; + } + + if (opd->type & OPTYPE_REG) + { + return evalsim_reg (eval_operand_val (insn, opd)); + } + + return eval_operand_val (insn, opd); + +} /* eval_operand() */ + + +/*---------------------------------------------------------------------------*/ +/*!Set destination operand (register direct) with value. + + Implementation specific. + + @param[in] op_no The operand + @param[in] value The value to set + @param[in] insn_index Address of the instruction + @param[in] insn The instruction */ +/*---------------------------------------------------------------------------*/ +static void +set_operand (int op_no, + orreg_t value, + unsigned long insn_index, + uint32_t insn) +{ + struct insn_op_struct *opd = op_start[insn_index]; + + while (op_no) + { + if (opd->type & OPTYPE_LAST) + { + fprintf (stderr, + "Instruction requested more operands than it has\n"); + exit (1); + } + + if ((opd->type & OPTYPE_OP) && !(opd->type & OPTYPE_DIS)) + { + op_no--; + } + + opd++; + } + + if (!(opd->type & OPTYPE_REG)) + { + fprintf (stderr, "Trying to set a non-register operand\n"); + exit (1); + } + + setsim_reg (eval_operand_val (insn, opd), value); + +} /* set_operand() */ + + +/*---------------------------------------------------------------------------*/ +/*!Simple and rather slow decoding function + + Based on built automata. + + @param[in] current The current instruction to execute */ +/*---------------------------------------------------------------------------*/ +static void +decode_execute (struct iqueue_entry *current) +{ + int insn_index; + + current->insn_index = insn_index = insn_decode (current->insn); + + if (insn_index < 0) + { + l_invalid (current); + } + else + { + or32_opcodes[insn_index].exec (current); + } + + if (do_stats) + analysis (&cpu_state.iqueue); +} + +#include "insnset.c" + +#elif defined(DYNAMIC_EXECUTION) + +#else +# error "Must define SIMPLE_EXECUTION, COMPLEX_EXECUTION or DYNAMIC_EXECUTION" +#endif Index: or32/op-arith-op.h =================================================================== --- or32/op-arith-op.h (nonexistent) +++ or32/op-arith-op.h (revision 1765) @@ -0,0 +1,33 @@ +/* op-arith-op.h -- Micro operations template for arithmetic 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. */ + +#ifdef OP_3T +__or_dynop void glue(glue(op_, OP_NAME), T)(void) +{ + T0 = OP_CAST(T1) OP OP_CAST(T2) OP_EXTRA; +} +#endif + +#ifdef OP_2T +__or_dynop void glue(glue(glue(op_, OP_NAME), _imm), T)(void) +{ + T0 = OP_CAST(T1) OP OP_CAST(OP_PARAM1) OP_EXTRA; +} +#endif + Index: or32/dyn-rec.h =================================================================== --- or32/dyn-rec.h (nonexistent) +++ or32/dyn-rec.h (revision 1765) @@ -0,0 +1,70 @@ +/* dyn-rec.h -- Recompiler specific definitions + + Copyright (C) 2005 György `nog' Jeney, nog@sdf.lonestar.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 . */ + +/* This program is commented throughout in a fashion suitable for processing + with Doxygen. */ + + +#ifndef DYN_REC__H +#define DYN_REC__H + +typedef void (*gen_code_ent)(void); + +/* Each dynamically recompiled page has one of these */ +struct dyn_page { + oraddr_t or_page; + void *host_page; + unsigned int host_len; + int dirty; /* Is recompiled page invalid? */ + int delayr; /* delayr of memory backing this page */ + uint16_t ts_bound[2049]; /* What registers the temporaries back (on the + * begining boundry of the instruction) */ + void **locs; /* Openrisc locations in the recompiled code */ + uint32_t *insns; /* Copy of instructions on this page */ + unsigned int *insn_indexs; /* Decoded instructions on this page */ +}; + +/* Function prototypes for external use */ +extern void recompile_page(struct dyn_page *dyn); +extern struct dyn_page *new_dp(oraddr_t page); +extern void add_to_opq(struct op_queue *opq, int end, int op); +extern void add_to_op_params(struct op_queue *opq, int end, unsigned long param); +extern void *enough_host_page(struct dyn_page *dp, void *cur, unsigned int *len, + unsigned int amount); +extern void init_dyn_recomp(void); +extern void run_sched_out_of_line(void); +extern void recheck_immu(int got_en_dis); +extern void enter_dyn_code(oraddr_t addr, struct dyn_page *dp); +extern void dyn_checkwrite(oraddr_t addr); +extern void dyn_main(void); + +/* Global variables for external use */ +extern void *rec_stack_base; + +#define IMMU_GOT_ENABLED 1 +#define IMMU_GOT_DISABLED 2 + +#define xglue(x, y) x ## y +#define glue(x, y) xglue(x, y) + +#endif /* DYN_REC__H */ + Index: or32/simpl32-defs.h =================================================================== --- or32/simpl32-defs.h (nonexistent) +++ or32/simpl32-defs.h (revision 1765) @@ -0,0 +1,112 @@ +/* simpl32-defs.h -- Definitions for the simple execution model + + Copyright (C) 1999 Damjan Lampret, lampret@opencores.org + Copyright (C) 2008 Embecosm Limited + + Contributed by Damjan Lampret (lampret@opencores.org). + Contributor Jeremy Bennett + + This file is part of Or1ksim, the OpenRISC 1000 Architectural Simulator. + This file is also part of or1k_gen_isa, GDB and GAS. + + This program is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by the Free + Software Foundation; either version 3 of the License, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + You should have received a copy of the GNU General Public License along + with this program. If not, see . */ + +/* This program is commented throughout in a fashion suitable for processing + with Doxygen. */ + + +#ifndef SIMPLE32_DEFS__H +#define SIMPLE32_DEFS__H + +/* Package includes */ +#include "abstract.h" + + +extern void l_invalid PARAMS((struct iqueue_entry *)); +extern void l_sfne PARAMS((struct iqueue_entry *)); +extern void l_bf PARAMS((struct iqueue_entry *)); +extern void l_add PARAMS((struct iqueue_entry *)); +extern void l_addc PARAMS((struct iqueue_entry *)); +extern void l_sw PARAMS((struct iqueue_entry *)); +extern void l_sb PARAMS((struct iqueue_entry *)); +extern void l_sh PARAMS((struct iqueue_entry *)); +extern void l_lwz PARAMS((struct iqueue_entry *)); +extern void l_lbs PARAMS((struct iqueue_entry *)); +extern void l_lbz PARAMS((struct iqueue_entry *)); +extern void l_lhs PARAMS((struct iqueue_entry *)); +extern void l_lhz PARAMS((struct iqueue_entry *)); +extern void l_movhi PARAMS((struct iqueue_entry *)); +extern void l_and PARAMS((struct iqueue_entry *)); +extern void l_or PARAMS((struct iqueue_entry *)); +extern void l_xor PARAMS((struct iqueue_entry *)); +extern void l_sub PARAMS((struct iqueue_entry *)); +extern void l_mul PARAMS((struct iqueue_entry *)); +extern void l_div PARAMS((struct iqueue_entry *)); +extern void l_divu PARAMS((struct iqueue_entry *)); +extern void l_sll PARAMS((struct iqueue_entry *)); +extern void l_sra PARAMS((struct iqueue_entry *)); +extern void l_srl PARAMS((struct iqueue_entry *)); +extern void l_j PARAMS((struct iqueue_entry *)); +extern void l_jal PARAMS((struct iqueue_entry *)); +extern void l_jalr PARAMS((struct iqueue_entry *)); +extern void l_jr PARAMS((struct iqueue_entry *)); +extern void l_rfe PARAMS((struct iqueue_entry *)); +extern void l_nop PARAMS((struct iqueue_entry *)); +extern void l_bnf PARAMS((struct iqueue_entry *)); +extern void l_sfeq PARAMS((struct iqueue_entry *)); +extern void l_sfgts PARAMS((struct iqueue_entry *)); +extern void l_sfges PARAMS((struct iqueue_entry *)); +extern void l_sflts PARAMS((struct iqueue_entry *)); +extern void l_sfles PARAMS((struct iqueue_entry *)); +extern void l_sfgtu PARAMS((struct iqueue_entry *)); +extern void l_sfgeu PARAMS()(struct iqueue_entry *); +extern void l_sfltu PARAMS((struct iqueue_entry *)); +extern void l_sfleu PARAMS((struct iqueue_entry *)); +extern void l_extbs PARAMS((struct iqueue_entry *)); +extern void l_extbz PARAMS((struct iqueue_entry *)); +extern void l_exths PARAMS((struct iqueue_entry *)); +extern void l_exthz PARAMS((struct iqueue_entry *)); +extern void l_extws PARAMS((struct iqueue_entry *)); +extern void l_extwz PARAMS((struct iqueue_entry *)); +extern void l_mtspr PARAMS((struct iqueue_entry *)); +extern void l_mfspr PARAMS((struct iqueue_entry *)); +extern void l_sys PARAMS((struct iqueue_entry *)); +extern void l_trap PARAMS((struct iqueue_entry *)); /* CZ 21/06/01 */ +extern void l_macrc PARAMS((struct iqueue_entry *)); +extern void l_mac PARAMS((struct iqueue_entry *)); +extern void l_msb PARAMS((struct iqueue_entry *)); +extern void l_invalid PARAMS((struct iqueue_entry *)); +extern void l_cmov PARAMS ((struct iqueue_entry *)); +extern void l_ff1 PARAMS ((struct iqueue_entry *)); +extern void l_cust1 PARAMS ((struct iqueue_entry *)); +extern void l_cust2 PARAMS ((struct iqueue_entry *)); +extern void l_cust3 PARAMS ((struct iqueue_entry *)); +extern void l_cust4 PARAMS ((struct iqueue_entry *)); +extern void lf_add_s PARAMS ((struct iqueue_entry *)); +extern void lf_div_s PARAMS ((struct iqueue_entry *)); +extern void lf_ftoi_s PARAMS ((struct iqueue_entry *)); +extern void lf_itof_s PARAMS ((struct iqueue_entry *)); +extern void lf_madd_s PARAMS ((struct iqueue_entry *)); +extern void lf_mul_s PARAMS ((struct iqueue_entry *)); +extern void lf_rem_s PARAMS ((struct iqueue_entry *)); +extern void lf_sfeq_s PARAMS ((struct iqueue_entry *)); +extern void lf_sfge_s PARAMS ((struct iqueue_entry *)); +extern void lf_sfgt_s PARAMS ((struct iqueue_entry *)); +extern void lf_sfle_s PARAMS ((struct iqueue_entry *)); +extern void lf_sflt_s PARAMS ((struct iqueue_entry *)); +extern void lf_sfne_s PARAMS ((struct iqueue_entry *)); +extern void lf_sub_s PARAMS((struct iqueue_entry *)); +extern void l_none PARAMS((struct iqueue_entry *)); + +#endif /* SIMPLE32_DEFS__H */ Index: or32/def-op-t.h =================================================================== --- or32/def-op-t.h (nonexistent) +++ or32/def-op-t.h (revision 1765) @@ -0,0 +1,138 @@ +/* def_op_t.h -- Operation-generation strucutre definitions helpers + Copyright (C) 2005 György `nog' Jeney, nog@sdf.lonestar.org + +This file is part of OpenRISC 1000 Architectural Simulator. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#define GPR_T(op_name, temp) \ + { NULL, \ + glue(glue(op_name, 1), temp), \ + glue(glue(op_name, 2), temp), \ + glue(glue(op_name, 3), temp), \ + glue(glue(op_name, 4), temp), \ + glue(glue(op_name, 5), temp), \ + glue(glue(op_name, 6), temp), \ + glue(glue(op_name, 7), temp), \ + glue(glue(op_name, 8), temp), \ + glue(glue(op_name, 9), temp), \ + glue(glue(op_name, 10), temp), \ + glue(glue(op_name, 11), temp), \ + glue(glue(op_name, 12), temp), \ + glue(glue(op_name, 13), temp), \ + glue(glue(op_name, 14), temp), \ + glue(glue(op_name, 15), temp), \ + glue(glue(op_name, 16), temp), \ + glue(glue(op_name, 17), temp), \ + glue(glue(op_name, 18), temp), \ + glue(glue(op_name, 19), temp), \ + glue(glue(op_name, 20), temp), \ + glue(glue(op_name, 21), temp), \ + glue(glue(op_name, 22), temp), \ + glue(glue(op_name, 23), temp), \ + glue(glue(op_name, 24), temp), \ + glue(glue(op_name, 25), temp), \ + glue(glue(op_name, 26), temp), \ + glue(glue(op_name, 27), temp), \ + glue(glue(op_name, 28), temp), \ + glue(glue(op_name, 29), temp), \ + glue(glue(op_name, 30), temp), \ + glue(glue(op_name, 31), temp) } + +#if NUM_T_REGS == 3 + +#define OP_ROW(op_name) \ + { glue(op_name, _t0), glue(op_name, _t1), glue(op_name, _t2) } + +#define OP_ROW_NEQ0(op_name) \ + { NULL, glue(op_name, _t1), glue(op_name, _t2) } + +#define OP_ROW_NEQ1(op_name) \ + { glue(op_name, _t0), NULL, glue(op_name, _t2) } + +#define OP_ROW_NEQ2(op_name) \ + { glue(op_name, _t0), glue(op_name, _t1), NULL } + +#define OP_ROW_COL(op_name) { \ + OP_ROW(glue(op_name, _t0)), \ + OP_ROW(glue(op_name, _t1)), \ + OP_ROW(glue(op_name, _t2)), } + +/* In 3D space: row, column, ??? */ +#define OP_ROW_COL_3D(op_name) { \ + OP_ROW_COL(glue(op_name, _t0)), \ + OP_ROW_COL(glue(op_name, _t1)), \ + OP_ROW_COL(glue(op_name, _t2)) } + +#define OP_ROW_COL_NEQ(op_name) { \ + OP_ROW_NEQ0(glue(op_name, _t0)), \ + OP_ROW_NEQ1(glue(op_name, _t1)), \ + OP_ROW_NEQ2(glue(op_name, _t2)) } + +#define OP_ROW_COL_NEQ0(op_name) { \ + OP_ROW_NEQ0(glue(op_name, _t0)), \ + OP_ROW(glue(op_name, _t1)), \ + OP_ROW(glue(op_name, _t2)) } + +#define OP_ROW_COL_NEQ1(op_name) { \ + OP_ROW(glue(op_name, _t0)), \ + OP_ROW_NEQ1(glue(op_name, _t1)), \ + OP_ROW(glue(op_name, _t2)) } + +#define OP_ROW_COL_NEQ2(op_name) { \ + OP_ROW(glue(op_name, _t0)), \ + OP_ROW(glue(op_name, _t1)), \ + OP_ROW_NEQ2(glue(op_name, _t2)) } + +#define OP_ROW_COL_3D_NEQ(op_name) { \ + OP_ROW_COL_NEQ0(glue(op_name, _t0)), \ + OP_ROW_COL_NEQ1(glue(op_name, _t1)), \ + OP_ROW_COL_NEQ2(glue(op_name, _t2)) } + +#define GPR_ROW_COL(op_name) { \ + GPR_T(op_name, _t0), \ + GPR_T(op_name, _t1), \ + GPR_T(op_name, _t2) } + +#else +#error Update def_op_t.h for NUM_T_REGS temporaries +#endif + +#define DEF_1T_OP(type, name, op_name) \ + static const type name[NUM_T_REGS] = \ + OP_ROW(op_name) + +#define DEF_2T_OP(type, name, op_name) \ + static const type name[NUM_T_REGS][NUM_T_REGS] = \ + OP_ROW_COL(op_name) + +#define DEF_3T_OP(type, name, op_name) \ + static const type name[NUM_T_REGS][NUM_T_REGS][NUM_T_REGS] = \ + OP_ROW_COL_3D(op_name) + +/* Same as above but put NULL in places where T0 == T1 */ +#define DEF_2T_OP_NEQ(type, name, op_name) \ + static const type name[NUM_T_REGS][NUM_T_REGS] = \ + OP_ROW_COL_NEQ(op_name) + +/* Same as above but put NULL in places where T0 == T1 == T2 */ +#define DEF_3T_OP_NEQ(type, name, op_name) \ + static const type name[NUM_T_REGS][NUM_T_REGS][NUM_T_REGS] = \ + OP_ROW_COL_3D_NEQ(op_name) + +#define DEF_GPR_OP(type, name, op_name) \ + static const generic_gen_op name[NUM_T_REGS][32] = \ + GPR_ROW_COL(op_name) + Index: or32/insnset.c =================================================================== --- or32/insnset.c (nonexistent) +++ or32/insnset.c (revision 1765) @@ -0,0 +1,614 @@ +/* insnset.c -- Instruction specific functions. + + Copyright (C) 1999 Damjan Lampret, lampret@opencores.org + 2000-2002 Marko Mlinar, markom@opencores.org + Copyright (C) 2008 Embecosm Limited + + Contributor Jeremy Bennett + + 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 . */ + +/* This program is commented throughout in a fashion suitable for processing + with Doxygen. */ + + +INSTRUCTION (l_add) { + orreg_t temp1, temp2, temp3; + int8_t temp4; + + temp2 = (orreg_t)PARAM2; + temp3 = (orreg_t)PARAM1; + temp1 = temp2 + temp3; + SET_PARAM0(temp1); + SET_OV_FLAG_FN (temp1); + if (ARITH_SET_FLAG) { + if(!temp1) + cpu_state.sprs[SPR_SR] |= SPR_SR_F; + else + cpu_state.sprs[SPR_SR] &= ~SPR_SR_F; + } + if ((uorreg_t) temp1 < (uorreg_t) temp2) + cpu_state.sprs[SPR_SR] |= SPR_SR_CY; + else + cpu_state.sprs[SPR_SR] &= ~SPR_SR_CY; + + temp4 = temp1; + if (temp4 == temp1) + or1k_mstats.byteadd++; +} +INSTRUCTION (l_addc) { + orreg_t temp1, temp2, temp3; + int8_t temp4; + + temp2 = (orreg_t)PARAM2; + temp3 = (orreg_t)PARAM1; + temp1 = temp2 + temp3; + if(cpu_state.sprs[SPR_SR] & SPR_SR_CY) + temp1++; + SET_PARAM0(temp1); + SET_OV_FLAG_FN (temp1); + if (ARITH_SET_FLAG) { + if(!temp1) + cpu_state.sprs[SPR_SR] |= SPR_SR_F; + else + cpu_state.sprs[SPR_SR] &= ~SPR_SR_F; + } + if ((uorreg_t) temp1 < (uorreg_t) temp2) + cpu_state.sprs[SPR_SR] |= SPR_SR_CY; + else + cpu_state.sprs[SPR_SR] &= ~SPR_SR_CY; + + temp4 = temp1; + if (temp4 == temp1) + or1k_mstats.byteadd++; +} +INSTRUCTION (l_sw) { + int old_cyc = 0; + if (config.cpu.sbuf_len) old_cyc = runtime.sim.mem_cycles; + set_mem32(PARAM0, PARAM1, &breakpoint); + if (config.cpu.sbuf_len) { + int t = runtime.sim.mem_cycles; + runtime.sim.mem_cycles = old_cyc; + sbuf_store (t - old_cyc); + } +} +INSTRUCTION (l_sb) { + int old_cyc = 0; + if (config.cpu.sbuf_len) old_cyc = runtime.sim.mem_cycles; + set_mem8(PARAM0, PARAM1, &breakpoint); + if (config.cpu.sbuf_len) { + int t = runtime.sim.mem_cycles; + runtime.sim.mem_cycles = old_cyc; + sbuf_store (t- old_cyc); + } +} +INSTRUCTION (l_sh) { + int old_cyc = 0; + if (config.cpu.sbuf_len) old_cyc = runtime.sim.mem_cycles; + set_mem16(PARAM0, PARAM1, &breakpoint); + if (config.cpu.sbuf_len) { + int t = runtime.sim.mem_cycles; + runtime.sim.mem_cycles = old_cyc; + sbuf_store (t - old_cyc); + } +} +INSTRUCTION (l_lwz) { + uint32_t val; + if (config.cpu.sbuf_len) sbuf_load (); + val = eval_mem32(PARAM1, &breakpoint); + /* If eval operand produced exception don't set anything. JPB changed to + trigger on breakpoint, as well as except_pending (seemed to be a bug). */ + if (!(except_pending || breakpoint)) + SET_PARAM0(val); +} +INSTRUCTION (l_lbs) { + int8_t val; + if (config.cpu.sbuf_len) sbuf_load (); + val = eval_mem8(PARAM1, &breakpoint); + /* If eval operand produced exception don't set anything. JPB changed to + trigger on breakpoint, as well as except_pending (seemed to be a bug). */ + if (!(except_pending || breakpoint)) + SET_PARAM0(val); +} +INSTRUCTION (l_lbz) { + uint8_t val; + if (config.cpu.sbuf_len) sbuf_load (); + val = eval_mem8(PARAM1, &breakpoint); + /* If eval operand produced exception don't set anything. JPB changed to + trigger on breakpoint, as well as except_pending (seemed to be a bug). */ + if (!(except_pending || breakpoint)) + SET_PARAM0(val); +} +INSTRUCTION (l_lhs) { + int16_t val; + if (config.cpu.sbuf_len) sbuf_load (); + val = eval_mem16(PARAM1, &breakpoint); + /* If eval operand produced exception don't set anything. JPB changed to + trigger on breakpoint, as well as except_pending (seemed to be a bug). */ + if (!(except_pending || breakpoint)) + SET_PARAM0(val); +} +INSTRUCTION (l_lhz) { + uint16_t val; + if (config.cpu.sbuf_len) sbuf_load (); + val = eval_mem16(PARAM1, &breakpoint); + /* If eval operand produced exception don't set anything. JPB changed to + trigger on breakpoint, as well as except_pending (seemed to be a bug). */ + if (!(except_pending || breakpoint)) + SET_PARAM0(val); +} +INSTRUCTION (l_movhi) { + SET_PARAM0(PARAM1 << 16); +} +INSTRUCTION (l_and) { + uorreg_t temp1; + temp1 = PARAM1 & PARAM2; + SET_OV_FLAG_FN (temp1); + SET_PARAM0(temp1); + if (ARITH_SET_FLAG) { + if(!temp1) + cpu_state.sprs[SPR_SR] |= SPR_SR_F; + else + cpu_state.sprs[SPR_SR] &= ~SPR_SR_F; + } +} +INSTRUCTION (l_or) { + uorreg_t temp1; + temp1 = PARAM1 | PARAM2; + SET_OV_FLAG_FN (temp1); + SET_PARAM0(temp1); +} +INSTRUCTION (l_xor) { + uorreg_t temp1; + temp1 = PARAM1 ^ PARAM2; + SET_OV_FLAG_FN (temp1); + SET_PARAM0(temp1); +} +INSTRUCTION (l_sub) { + orreg_t temp1; + temp1 = (orreg_t)PARAM1 - (orreg_t)PARAM2; + SET_OV_FLAG_FN (temp1); + SET_PARAM0(temp1); +} +/*int mcount = 0;*/ +INSTRUCTION (l_mul) { + orreg_t temp1; + + temp1 = (orreg_t)PARAM1 * (orreg_t)PARAM2; + SET_OV_FLAG_FN (temp1); + SET_PARAM0(temp1); + /*if (!(mcount++ & 1023)) { + PRINTF ("[%i]\n",mcount); + }*/ +} +INSTRUCTION (l_div) { + orreg_t temp3, temp2, temp1; + + temp3 = PARAM2; + temp2 = PARAM1; + if (temp3) + temp1 = temp2 / temp3; + else { + except_handle(EXCEPT_ILLEGAL, cpu_state.pc); + return; + } + SET_OV_FLAG_FN (temp1); + SET_PARAM0(temp1); +} +INSTRUCTION (l_divu) { + uorreg_t temp3, temp2, temp1; + + temp3 = PARAM2; + temp2 = PARAM1; + if (temp3) + temp1 = temp2 / temp3; + else { + except_handle(EXCEPT_ILLEGAL, cpu_state.pc); + return; + } + SET_OV_FLAG_FN (temp1); + SET_PARAM0(temp1); + /* runtime.sim.cycles += 16; */ +} +INSTRUCTION (l_sll) { + uorreg_t temp1; + + temp1 = PARAM1 << PARAM2; + SET_OV_FLAG_FN (temp1); + SET_PARAM0(temp1); + /* runtime.sim.cycles += 2; */ +} +INSTRUCTION (l_sra) { + orreg_t temp1; + + temp1 = (orreg_t)PARAM1 >> PARAM2; + SET_OV_FLAG_FN (temp1); + SET_PARAM0(temp1); + /* runtime.sim.cycles += 2; */ +} +INSTRUCTION (l_srl) { + uorreg_t temp1; + temp1 = PARAM1 >> PARAM2; + SET_OV_FLAG_FN (temp1); + SET_PARAM0(temp1); + /* runtime.sim.cycles += 2; */ +} +INSTRUCTION (l_bf) { + if (config.bpb.enabled) { + int fwd = (PARAM0 >= cpu_state.pc) ? 1 : 0; + or1k_mstats.bf[cpu_state.sprs[SPR_SR] & SPR_SR_F ? 1 : 0][fwd]++; + bpb_update(current->insn_addr, cpu_state.sprs[SPR_SR] & SPR_SR_F ? 1 : 0); + } + if(cpu_state.sprs[SPR_SR] & SPR_SR_F) { + cpu_state.pc_delay = cpu_state.pc + (orreg_t)PARAM0 * 4; + btic_update(pcnext); + next_delay_insn = 1; + } else { + btic_update(cpu_state.pc); + } +} +INSTRUCTION (l_bnf) { + if (config.bpb.enabled) { + int fwd = (PARAM0 >= cpu_state.pc) ? 1 : 0; + or1k_mstats.bnf[cpu_state.sprs[SPR_SR] & SPR_SR_F ? 0 : 1][fwd]++; + bpb_update(current->insn_addr, cpu_state.sprs[SPR_SR] & SPR_SR_F ? 0 : 1); + } + if (!(cpu_state.sprs[SPR_SR] & SPR_SR_F)) { + cpu_state.pc_delay = cpu_state.pc + (orreg_t)PARAM0 * 4; + btic_update(pcnext); + next_delay_insn = 1; + } else { + btic_update(cpu_state.pc); + } +} +INSTRUCTION (l_j) { + cpu_state.pc_delay = cpu_state.pc + (orreg_t)PARAM0 * 4; + next_delay_insn = 1; +} +INSTRUCTION (l_jal) { + cpu_state.pc_delay = cpu_state.pc + (orreg_t)PARAM0 * 4; + + setsim_reg(LINK_REGNO, cpu_state.pc + 8); + next_delay_insn = 1; + if (config.sim.profile) { + struct label_entry *tmp; + if (verify_memoryarea(cpu_state.pc_delay) && (tmp = get_label (cpu_state.pc_delay))) + fprintf (runtime.sim.fprof, "+%08llX %"PRIxADDR" %"PRIxADDR" %s\n", + runtime.sim.cycles, cpu_state.pc + 8, cpu_state.pc_delay, + tmp->name); + else + fprintf (runtime.sim.fprof, "+%08llX %"PRIxADDR" %"PRIxADDR" @%"PRIxADDR"\n", + runtime.sim.cycles, cpu_state.pc + 8, cpu_state.pc_delay, + cpu_state.pc_delay); + } +} +INSTRUCTION (l_jalr) { + cpu_state.pc_delay = PARAM0; + setsim_reg(LINK_REGNO, cpu_state.pc + 8); + next_delay_insn = 1; +} +INSTRUCTION (l_jr) { + cpu_state.pc_delay = PARAM0; + next_delay_insn = 1; + if (config.sim.profile) + fprintf (runtime.sim.fprof, "-%08llX %"PRIxADDR"\n", runtime.sim.cycles, + cpu_state.pc_delay); +} +INSTRUCTION (l_rfe) { + pcnext = cpu_state.sprs[SPR_EPCR_BASE]; + mtspr(SPR_SR, cpu_state.sprs[SPR_ESR_BASE]); +} +INSTRUCTION (l_nop) { + oraddr_t stackaddr; + uint32_t k = PARAM0; + switch (k) { + case NOP_NOP: + break; + case NOP_EXIT: + PRINTF("exit(%"PRIdREG")\n", evalsim_reg (3)); + fprintf(stderr, "@reset : cycles %lld, insn #%lld\n", + runtime.sim.reset_cycles, runtime.cpu.reset_instructions); + fprintf(stderr, "@exit : cycles %lld, insn #%lld\n", runtime.sim.cycles, + runtime.cpu.instructions); + fprintf(stderr, " diff : cycles %lld, insn #%lld\n", + runtime.sim.cycles - runtime.sim.reset_cycles, + runtime.cpu.instructions - runtime.cpu.reset_instructions); + if (config.debug.gdb_enabled) + set_stall_state (1); + else + sim_done(); + break; + case NOP_CNT_RESET: + PRINTF("****************** counters reset ******************\n"); + PRINTF("cycles %lld, insn #%lld\n", runtime.sim.cycles, runtime.cpu.instructions); + PRINTF("****************** counters reset ******************\n"); + runtime.sim.reset_cycles = runtime.sim.cycles; + runtime.cpu.reset_instructions = runtime.cpu.instructions; + break; + case NOP_PRINTF: + stackaddr = evalsim_reg(4); + simprintf(stackaddr, evalsim_reg(3)); + break; + case NOP_PUTC: /*JPB */ + printf( "%c", (char)(evalsim_reg( 3 ) & 0xff)); + fflush( stdout ); + break; + case NOP_REPORT: + PRINTF("report(0x%"PRIxREG");\n", evalsim_reg(3)); + default: + if (k >= NOP_REPORT_FIRST && k <= NOP_REPORT_LAST) + PRINTF("report %" PRIdREG " (0x%"PRIxREG");\n", k - NOP_REPORT_FIRST, + evalsim_reg(3)); + break; + } +} +INSTRUCTION (l_sfeq) { + if(PARAM0 == PARAM1) + cpu_state.sprs[SPR_SR] |= SPR_SR_F; + else + cpu_state.sprs[SPR_SR] &= ~SPR_SR_F; +} +INSTRUCTION (l_sfne) { + if(PARAM0 != PARAM1) + cpu_state.sprs[SPR_SR] |= SPR_SR_F; + else + cpu_state.sprs[SPR_SR] &= ~SPR_SR_F; +} +INSTRUCTION (l_sfgts) { + if((orreg_t)PARAM0 > (orreg_t)PARAM1) + cpu_state.sprs[SPR_SR] |= SPR_SR_F; + else + cpu_state.sprs[SPR_SR] &= ~SPR_SR_F; +} +INSTRUCTION (l_sfges) { + if((orreg_t)PARAM0 >= (orreg_t)PARAM1) + cpu_state.sprs[SPR_SR] |= SPR_SR_F; + else + cpu_state.sprs[SPR_SR] &= ~SPR_SR_F; +} +INSTRUCTION (l_sflts) { + if((orreg_t)PARAM0 < (orreg_t)PARAM1) + cpu_state.sprs[SPR_SR] |= SPR_SR_F; + else + cpu_state.sprs[SPR_SR] &= ~SPR_SR_F; +} +INSTRUCTION (l_sfles) { + if((orreg_t)PARAM0 <= (orreg_t)PARAM1) + cpu_state.sprs[SPR_SR] |= SPR_SR_F; + else + cpu_state.sprs[SPR_SR] &= ~SPR_SR_F; +} +INSTRUCTION (l_sfgtu) { + if(PARAM0 > PARAM1) + cpu_state.sprs[SPR_SR] |= SPR_SR_F; + else + cpu_state.sprs[SPR_SR] &= ~SPR_SR_F; +} +INSTRUCTION (l_sfgeu) { + if(PARAM0 >= PARAM1) + cpu_state.sprs[SPR_SR] |= SPR_SR_F; + else + cpu_state.sprs[SPR_SR] &= ~SPR_SR_F; +} +INSTRUCTION (l_sfltu) { + if(PARAM0 < PARAM1) + cpu_state.sprs[SPR_SR] |= SPR_SR_F; + else + cpu_state.sprs[SPR_SR] &= ~SPR_SR_F; +} +INSTRUCTION (l_sfleu) { + if(PARAM0 <= PARAM1) + cpu_state.sprs[SPR_SR] |= SPR_SR_F; + else + cpu_state.sprs[SPR_SR] &= ~SPR_SR_F; +} +INSTRUCTION (l_extbs) { + int8_t x; + x = PARAM1; + SET_PARAM0((orreg_t)x); +} +INSTRUCTION (l_extbz) { + uint8_t x; + x = PARAM1; + SET_PARAM0((uorreg_t)x); +} +INSTRUCTION (l_exths) { + int16_t x; + x = PARAM1; + SET_PARAM0((orreg_t)x); +} +INSTRUCTION (l_exthz) { + uint16_t x; + x = PARAM1; + SET_PARAM0((uorreg_t)x); +} +INSTRUCTION (l_extws) { + int32_t x; + x = PARAM1; + SET_PARAM0((orreg_t)x); +} +INSTRUCTION (l_extwz) { + uint32_t x; + x = PARAM1; + SET_PARAM0((uorreg_t)x); +} +INSTRUCTION (l_mtspr) { + uint16_t regno = PARAM0 + PARAM2; + uorreg_t value = PARAM1; + + if (cpu_state.sprs[SPR_SR] & SPR_SR_SM) + mtspr(regno, value); + else { + PRINTF("WARNING: trying to write SPR while SR[SUPV] is cleared.\n"); + sim_done(); + } +} +INSTRUCTION (l_mfspr) { + uint16_t regno = PARAM1 + PARAM2; + uorreg_t value = mfspr(regno); + + if (cpu_state.sprs[SPR_SR] & SPR_SR_SM) + SET_PARAM0(value); + else { + SET_PARAM0(0); + PRINTF("WARNING: trying to read SPR while SR[SUPV] is cleared.\n"); + sim_done(); + } +} +INSTRUCTION (l_sys) { + except_handle(EXCEPT_SYSCALL, cpu_state.sprs[SPR_EEAR_BASE]); +} +INSTRUCTION (l_trap) { + /* TODO: some SR related code here! */ + except_handle(EXCEPT_TRAP, cpu_state.sprs[SPR_EEAR_BASE]); +} +INSTRUCTION (l_mac) { + uorreg_t lo, hi; + LONGEST l; + orreg_t x, y; + + lo = cpu_state.sprs[SPR_MACLO]; + hi = cpu_state.sprs[SPR_MACHI]; + x = PARAM0; + y = PARAM1; + PRINTF ("[%"PRIxREG",%"PRIxREG"]\t", x, y); + l = (ULONGEST)lo | ((LONGEST)hi << 32); + l += (LONGEST) x * (LONGEST) y; + + /* This implementation is very fast - it needs only one cycle for mac. */ + lo = ((ULONGEST)l) & 0xFFFFFFFF; + hi = ((LONGEST)l) >> 32; + cpu_state.sprs[SPR_MACLO] = lo; + cpu_state.sprs[SPR_MACHI] = hi; + PRINTF ("(%"PRIxREG",%"PRIxREG"\n", hi, lo); +} +INSTRUCTION (l_msb) { + uorreg_t lo, hi; + LONGEST l; + orreg_t x, y; + + lo = cpu_state.sprs[SPR_MACLO]; + hi = cpu_state.sprs[SPR_MACHI]; + x = PARAM0; + y = PARAM1; + + PRINTF ("[%"PRIxREG",%"PRIxREG"]\t", x, y); + + l = (ULONGEST)lo | ((LONGEST)hi << 32); + l -= x * y; + + /* This implementation is very fast - it needs only one cycle for msb. */ + lo = ((ULONGEST)l) & 0xFFFFFFFF; + hi = ((LONGEST)l) >> 32; + cpu_state.sprs[SPR_MACLO] = lo; + cpu_state.sprs[SPR_MACHI] = hi; + PRINTF ("(%"PRIxREG",%"PRIxREG")\n", hi, lo); +} +INSTRUCTION (l_macrc) { + uorreg_t lo, hi; + LONGEST l; + /* No need for synchronization here -- all MAC instructions are 1 cycle long. */ + lo = cpu_state.sprs[SPR_MACLO]; + hi = cpu_state.sprs[SPR_MACHI]; + l = (ULONGEST) lo | ((LONGEST)hi << 32); + l >>= 28; + //PRINTF ("<%08x>\n", (unsigned long)l); + SET_PARAM0((orreg_t)l); + cpu_state.sprs[SPR_MACLO] = 0; + cpu_state.sprs[SPR_MACHI] = 0; +} +INSTRUCTION (l_cmov) { + SET_PARAM0(cpu_state.sprs[SPR_SR] & SPR_SR_F ? PARAM1 : PARAM2); +} +INSTRUCTION (l_ff1) { + SET_PARAM0(ffs(PARAM1)); +} +/******* Floating point instructions *******/ +/* Single precision */ +INSTRUCTION (lf_add_s) { + SET_PARAM0((float)PARAM1 + (float)PARAM2); +} +INSTRUCTION (lf_div_s) { + SET_PARAM0((float)PARAM1 / (float)PARAM2); +} +INSTRUCTION (lf_ftoi_s) { +// set_operand32(0, freg[get_operand(1)], &breakpoint); +} +INSTRUCTION (lf_itof_s) { +// freg[get_operand(0)] = eval_operand32(1, &breakpoint); +} +INSTRUCTION (lf_madd_s) { + SET_PARAM0((float)PARAM0 + (float)PARAM1 * (float)PARAM2); +} +INSTRUCTION (lf_mul_s) { + SET_PARAM0((float)PARAM1 * (float)PARAM2); +} +INSTRUCTION (lf_rem_s) { + float temp = (float)PARAM1 / (float)PARAM2; + SET_PARAM0(temp - (uint32_t)temp); +} +INSTRUCTION (lf_sfeq_s) { + if((float)PARAM0 == (float)PARAM1) + cpu_state.sprs[SPR_SR] |= SPR_SR_F; + else + cpu_state.sprs[SPR_SR] &= ~SPR_SR_F; +} +INSTRUCTION (lf_sfge_s) { + if((float)PARAM0 >= (float)PARAM1) + cpu_state.sprs[SPR_SR] |= SPR_SR_F; + else + cpu_state.sprs[SPR_SR] &= ~SPR_SR_F; +} +INSTRUCTION (lf_sfgt_s) { + if((float)PARAM0 > (float)PARAM1) + cpu_state.sprs[SPR_SR] |= SPR_SR_F; + else + cpu_state.sprs[SPR_SR] &= ~SPR_SR_F; +} +INSTRUCTION (lf_sfle_s) { + if((float)PARAM0 <= (float)PARAM1) + cpu_state.sprs[SPR_SR] |= SPR_SR_F; + else + cpu_state.sprs[SPR_SR] &= ~SPR_SR_F; +} +INSTRUCTION (lf_sflt_s) { + if((float)PARAM0 < (float)PARAM1) + cpu_state.sprs[SPR_SR] |= SPR_SR_F; + else + cpu_state.sprs[SPR_SR] &= ~SPR_SR_F; +} +INSTRUCTION (lf_sfne_s) { + if((float)PARAM0 != (float)PARAM1) + cpu_state.sprs[SPR_SR] |= SPR_SR_F; + else + cpu_state.sprs[SPR_SR] &= ~SPR_SR_F; +} +INSTRUCTION (lf_sub_s) { + SET_PARAM0((float)PARAM1 - (float)PARAM2); +} + +/******* Custom instructions *******/ +INSTRUCTION (l_cust1) { + /*int destr = current->insn >> 21; + int src1r = current->insn >> 15; + int src2r = current->insn >> 9;*/ +} +INSTRUCTION (l_cust2) { +} +INSTRUCTION (l_cust3) { +} +INSTRUCTION (l_cust4) { +}
or32/insnset.c Property changes : Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: or32/dyngen.c =================================================================== --- or32/dyngen.c (nonexistent) +++ or32/dyngen.c (revision 1765) @@ -0,0 +1,289 @@ +/* dyngen.c -- Generates micro operation generating functions + Copyright (C) 2005 György `nog' Jeney, nog@sdf.lonestar.org + +This file is part of OpenRISC 1000 Architectural Simulator. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + + +#include +#include +#include + +#include "dyngen.h" + +#define OP_FUNC_PREFIX "op_" +#define OP_FUNC_PARAM_PREFIX "__op_param" +/* Have to add to to make sure that the param[] is 0 */ +#define MAX_PARAMS (3 + 1) + +static const char *c_file_head = +"#include \"config.h\"\n" +"\n" +"#include \n" +"\n" +"#include \"arch.h\"\n" +"#include \"opcode/or32.h\"\n" +"#include \"spr-defs.h\"\n" +"#include \"i386-regs.h\"\n" +"#include \"abstract.h\"\n" +"\n" +"#include \"dyn-rec.h\"\n" +"#include \"%s\"\n" +"\n"; + +static const char *gen_code_proto = +"void gen_code(struct op_queue *opq, struct dyn_page *dp);\n" +"void patch_relocs(struct op_queue *opq, void *host_page);\n" +"\n"; + +static const char *c_sw_file_head = +"#include \n" +"#include \n" +"\n" +"#include \"config.h\"\n" +"\n" +"#include \n" +"\n" +"#include \"arch.h\"\n" +"#include \"opcode/or32.h\"\n" +"#include \"spr-defs.h\"\n" +"#include \"i386-regs.h\"\n" +"#include \"abstract.h\"\n" +"#include \"dyn-rec.h\"\n" +"#include \"%s\"\n" +"\n" +"void gen_code(struct op_queue *opq, struct dyn_page *dp)\n" +"{\n" +" unsigned int *ops, i;\n" +" unsigned int host_len = dp->host_len;\n" +" void *host_cur = dp->host_page;\n" +" oraddr_t pc = dp->or_page;\n" +" void **loc = dp->locs;\n" +"\n" +" while(opq) {\n" +" if(opq->next)\n" +" *loc++ = (void *)(host_cur - dp->host_page);" +"\n" +" for(i = 0, ops = opq->ops; i < opq->num_ops; i++, ops++) {\n" +" switch(*ops) {\n" +" case op_mark_loc_indx:\n" +" opq->ops_param[0] = host_cur - dp->host_page;\n" +" break;\n"; + +static const char *c_sw_file_tail = +" }\n" +" }\n" +" opq = opq->next;\n" +" pc += 4;\n" +" }\n" +"\n" +" dp->host_len = host_cur - dp->host_page;\n" +" dp->host_page = realloc(dp->host_page, dp->host_len);\n" +"}\n"; + +static const char *c_rel_file_head = +"#include /* To get printf... */\n" +"#include \n" +"\n" +"#include \"config.h\"\n" +"\n" +"#include \n" +"\n" +"#include \"arch.h\"\n" +"#include \"spr-defs.h\"\n" +"#include \"i386-regs.h\"\n" +"#include \"opcode/or32.h\"\n" +"#include \"abstract.h\"\n" +"#include \"tick.h\"\n" +"#include \"execute.h\"\n" +"#include \"sprs.h\"\n" +"#include \"dyn-rec.h\"\n" +"#include \"op-support.h\"\n" +"#include \"%s\"\n" +"\n" +"void do_scheduler(void); /* FIXME: Remove */\n" +"void do_sched_wrap(void); /* FIXME: Remove */\n" +"void do_sched_wrap_delay(void); /* FIXME: Remove */\n" +"void simprintf(oraddr_t stackaddr, unsigned long regparam); /* FIXME: Remove */\n" +"\n" +"void patch_relocs(struct op_queue *opq, void *host_page)\n" +"{\n" +" unsigned int *ops, *ops_param, i;\n" +"\n" +" while(opq) {\n" +" for(i = 0, ops = opq->ops, ops_param = opq->ops_param; i < opq->num_ops; i++, ops++) {\n" +" switch(*ops) {\n"; + +static const char *c_rel_file_tail = +" }\n" +" }\n" +" opq = opq->next;\n" +" }\n" +"}\n"; + +static void gen_func_proto(FILE *f, const char *name, int *params) +{ + int i; + + fprintf(f, "void gen_%s(struct op_queue *opq, int end", name); + for(i = 0; (i < MAX_PARAMS) && params[i]; i++) { + fprintf(f, ", uorreg_t param%i", i + 1); + } + fprintf(f, ")"); +} + +int main(int argc, char **argv) +{ + void *obj; + int i, j; + unsigned int len; + char *name; + int params[MAX_PARAMS]; + struct reloc reloc; + + FILE *c_file; + FILE *h_file; + FILE *c_sw_file; + FILE *c_rel_file; + + if(argc != 6) { + fprintf(stderr, "Usage: %s \n", argv[0]); + return 1; + } + + obj = bffs.open_obj(argv[1]); + if(!obj) { + fprintf(stderr, "Unable to open object file %s\n", argv[1]); + return 1; + } + + if(!(c_file = fopen(argv[2], "w"))) { + fprintf(stderr, "Unable to open %s for writting\n", argv[2]); + bffs.close_obj(obj); + return 1; + } + + if(!(c_sw_file = fopen(argv[3], "w"))) { + fprintf(stderr, "Unable to open %s for writting\n", argv[2]); + fclose(c_file); + bffs.close_obj(obj); + } + + if(!(c_rel_file = fopen(argv[4], "w"))) { + fprintf(stderr, "Unable to open %s for writting\n", argv[3]); + fclose(c_file); + fclose(c_sw_file); + bffs.close_obj(obj); + return 1; + } + + if(!(h_file = fopen(argv[5], "w"))) { + fprintf(stderr, "Unable to open %s for writting\n", argv[3]); + fclose(c_file); + fclose(c_sw_file); + fclose(c_rel_file); + bffs.close_obj(obj); + return 1; + } + + fprintf(c_file, c_file_head, argv[5]); + fprintf(c_sw_file, c_sw_file_head, argv[5]); + fprintf(c_rel_file, c_rel_file_head, argv[5]); + fprintf(h_file, "%s", gen_code_proto); + + /* Itterate through the functions in the object file */ + for(i = 0; (name = bffs.get_func_name(obj, i)); i++) { + if(strncmp(name, OP_FUNC_PREFIX, strlen(OP_FUNC_PREFIX))) + continue; + + /* Find all the relocations associated with this function */ + memset(params, 0, sizeof(params)); + for(j = 0; bffs.get_func_reloc(obj, i, j, &reloc); j++) { + //fprintf(stderr, "%s %i %i\n", reloc.name, reloc.func_offset, reloc.addend); + if(strncmp(reloc.name, OP_FUNC_PARAM_PREFIX, strlen(OP_FUNC_PARAM_PREFIX))) { + continue; + } + params[atoi(reloc.name + strlen(OP_FUNC_PARAM_PREFIX)) - 1] = 1; + } + + len = archfs.get_real_func_len(bffs.get_func_start(obj, i), + bffs.get_func_len(obj, i), name); + + gen_func_proto(h_file, name, params); + fprintf(h_file, ";\n"); + + if(len) { + /* Prototype the operation */ + fprintf(h_file, "void %s(void);\n", name); + fprintf(h_file, "#define %s_indx %i\n", name, i); + } + + gen_func_proto(c_file, name, params); + fprintf(c_file, "\n{\n"); + if(len) { + fprintf(c_file, " add_to_opq(opq, end, %s_indx);\n", name); + + for(j = 0; params[j]; j++) + fprintf(c_file, " add_to_op_params(opq, end, param%i);\n", j + 1); + } + fprintf(c_file, "}\n\n"); + + if(!len) { + /* If the operation is of length 0, then just ignore it */ + fprintf(stderr, "WARNING: Useless operation (size == 0): %s\n", name); + continue; + } + + fprintf(c_sw_file, " case %s_indx:\n", name); + fprintf(c_sw_file, " host_cur = enough_host_page(dp, host_cur, &host_len, %i);\n", len); + fprintf(c_sw_file, " memcpy(host_cur, %s, %i);\n", name, len); + + fprintf(c_rel_file, " case %s_indx:\n", name); + for(j = 0; bffs.get_func_reloc(obj, i, j, &reloc); j++) { + /* Ignore nameless relocations, they appear to be absolute */ + if(!*reloc.name) + continue; + if(strncmp(reloc.name, OP_FUNC_PARAM_PREFIX, strlen(OP_FUNC_PARAM_PREFIX))) { + /* We have to manually do the relocations when the relocation is + * relative to the PC as the code gets copied to a different location + * during recompilation, where the relative addresses shall be waay out. + */ + archfs.gen_func_reloc(c_rel_file, &reloc); + } else { + archfs.gen_reloc(c_rel_file, &reloc, + atoi(reloc.name + strlen(OP_FUNC_PARAM_PREFIX))); + } + } + + fprintf(c_sw_file, " host_cur += %i;\n break;\n\n", len); + fprintf(c_rel_file, " host_page += %i;\n", len); + /* Count how many parameters where used */ + for(j = 0; params[j]; j++); + fprintf(c_rel_file, " ops_param += %i;\n break;\n\n", j); + } + + fprintf(c_sw_file, "%s", c_sw_file_tail); + fprintf(c_rel_file, "%s", c_rel_file_tail); + + fprintf(h_file, "\n#define op_mark_loc_indx %i\n", i); + + fclose(h_file); + fclose(c_file); + fclose(c_sw_file); + fclose(c_rel_file); + bffs.close_obj(obj); + return 0; +} Index: or32/Makefile.am =================================================================== --- or32/Makefile.am (nonexistent) +++ or32/Makefile.am (revision 1765) @@ -0,0 +1,196 @@ +# 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 + +noinst_PROGRAMS = dyngen + +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 + +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) + +gen-ops.h gen-ops.c gen-ops-gen.c gen-ops-rel.c: dyngen$(EXEEXT) op-tmp.o + ./dyngen$(EXEEXT) op-tmp.o gen-ops.c gen-ops-gen.c gen-ops-rel.c gen-ops.h + +OP_CFLAGS = -Wall -fomit-frame-pointer -fno-reorder-blocks -O2 + +op-tmp.o: op.c op-t-reg-mov-op.h op-i386.h op-arith-op.h op-comp-op.h \ + op-extend-op.h op-ff1-op.h op-mac-op.h op-mftspr-op.h op-lwhb-op.h \ + op-swhb-op.h + $(CC) $(INCLUDES) -I$(top_builddir) $(OP_CFLAGS) -o $@ -c $< +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 \ + 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 + +dist_EXTRA_libarch_la_SOURCES = insnset.c + +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: or32/dyngen-elf.c =================================================================== --- or32/dyngen-elf.c (nonexistent) +++ or32/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], (long int)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: or32/rec-i386.h =================================================================== --- or32/rec-i386.h (nonexistent) +++ or32/rec-i386.h (revision 1765) @@ -0,0 +1,28 @@ +/* rec-i386.h -- i386 specific parts of the recompile engine + 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. */ + + +/* Gets the current stack pointer */ +static void *get_sp(void) +{ + void *stack; + asm("movl %%esp, %0" : "=rm" (stack)); + return stack; +} + Index: or32/op-2t.h =================================================================== --- or32/op-2t.h (nonexistent) +++ or32/op-2t.h (revision 1765) @@ -0,0 +1,62 @@ +/* op-2t.h -- Instantiation of operatations that work on only 2 temporary + 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 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 Index: or32/op-i386.h =================================================================== --- or32/op-i386.h (nonexistent) +++ or32/op-i386.h (revision 1765) @@ -0,0 +1,46 @@ +/* op-i386.h -- i386 specific support routines for micro operations + + 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. */ + + +#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 */ Index: or32/sched-i386.h =================================================================== --- or32/sched-i386.h (nonexistent) +++ or32/sched-i386.h (revision 1765) @@ -0,0 +1,40 @@ +/* sched-i386.h -- i386 specific support routines for the scheduler + 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. */ + + +/* 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)); +} + Index: or32/or32.c =================================================================== --- or32/or32.c (nonexistent) +++ or32/or32.c (revision 1765) @@ -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 + + 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 . */ + +/* 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 + +/* 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); +} Index: or32/op-lwhb-op.h =================================================================== --- or32/op-lwhb-op.h (nonexistent) +++ or32/op-lwhb-op.h (revision 1765) @@ -0,0 +1,38 @@ +/* op-lwhb-op.h -- Micro operations template for load 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. */ + + +/* 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 + Index: or32/op-comp-op.h =================================================================== --- or32/op-comp-op.h (nonexistent) +++ or32/op-comp-op.h (revision 1765) @@ -0,0 +1,50 @@ +/* op-comp-op.h -- Micro operations template for comparison 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. */ + +#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 + Index: or32/op-support.h =================================================================== --- or32/op-support.h (nonexistent) +++ or32/op-support.h (revision 1765) @@ -0,0 +1,28 @@ +/* op-support.h -- Definitions of support routines for 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 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); Index: or32/op-1t.h =================================================================== --- or32/op-1t.h (nonexistent) +++ or32/op-1t.h (revision 1765) @@ -0,0 +1,38 @@ +/* op-1t.h -- Instantiation of operatations that work on only 1 temporary + 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 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 Index: or32/op-3t.h =================================================================== --- or32/op-3t.h (nonexistent) +++ or32/op-3t.h (revision 1765) @@ -0,0 +1,135 @@ +/* op-3t.h -- Instantiation of operatations that work on only 3 temporary + 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 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 Index: or32/op-ff1-op.h =================================================================== --- or32/op-ff1-op.h (nonexistent) +++ or32/op-ff1-op.h (revision 1765) @@ -0,0 +1,35 @@ +/* op-ff1-op.h -- Micro operations template for the ff1 instruction + 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(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; +} + + Index: or32/op-t-reg-mov-op.h =================================================================== --- or32/op-t-reg-mov-op.h (nonexistent) +++ or32/op-t-reg-mov-op.h (revision 1765) @@ -0,0 +1,330 @@ +/* op-t-reg-mov-op.h -- Micro operations template for reg<->temporary 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(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; +} + Index: or32/dyngen-i386.c =================================================================== --- or32/dyngen-i386.c (nonexistent) +++ or32/dyngen-i386.c (revision 1765) @@ -0,0 +1,75 @@ +/* dyngen-i386.c -- i386 parts of 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 "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 +}; Index: or32/op-1t-op.h =================================================================== --- or32/op-1t-op.h (nonexistent) +++ or32/op-1t-op.h (revision 1765) @@ -0,0 +1,75 @@ +/* op-1t-op.h -- Micro operations useing only one temporary + 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_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; +} + Index: or32/op-2t-op.h =================================================================== --- or32/op-2t-op.h (nonexistent) +++ or32/op-2t-op.h (revision 1765) @@ -0,0 +1,44 @@ +/* op-1t-op.h -- Micro operations useing two 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_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; +} + Index: or32/op-3t-op.h =================================================================== --- or32/op-3t-op.h (nonexistent) +++ or32/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: or32/op-extend-op.h =================================================================== --- or32/op-extend-op.h (nonexistent) +++ or32/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: or32/common-i386.h =================================================================== --- or32/common-i386.h (nonexistent) +++ or32/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: or32/generate.c =================================================================== --- or32/generate.c (nonexistent) +++ or32/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; +} +
or32/generate.c Property changes : Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: or32/i386-regs.h =================================================================== --- or32/i386-regs.h (nonexistent) +++ or32/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: or32/op-mac-op.h =================================================================== --- or32/op-mac-op.h (nonexistent) +++ or32/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: or32/dyngen.h =================================================================== --- or32/dyngen.h (nonexistent) +++ or32/dyngen.h (revision 1765) @@ -0,0 +1,45 @@ +/* dyngen.h -- Definitions for dyngen.c + Copyright (C) 2005 György `nog' Jeney, nog@sdf.lonestar.org + +This file is part of OpenRISC 1000 Architectural Simulator. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + + +struct reloc { + unsigned int func_offset; + unsigned int addend; + int type; + const char *name; +}; + +struct bff { + void *(*open_obj)(const char *object); /* Open the object file */ + void (*close_obj)(void *); + char *(*get_func_name)(void *, unsigned int func); /* Gets the name of func */ + void *(*get_func_start)(void *, unsigned int func); + unsigned int (*get_func_len)(void *, unsigned int func); + int (*get_func_reloc)(void *, unsigned int func, unsigned int relocn, struct reloc *reloc); +}; + +extern const struct bff bffs; + +struct archf { + unsigned int (*get_real_func_len)(void *func, unsigned int len, char *name); + void (*gen_reloc)(FILE *f, struct reloc *reloc, unsigned int param); + void (*gen_func_reloc)(FILE *f, struct reloc *reloc); +}; + +extern const struct archf archfs; Index: or32 =================================================================== --- or32 (nonexistent) +++ or32 (revision 1765)
or32 Property changes : Added: svn:ignore ## -0,0 +1,3 ## +Makefile +.deps +generate Index: common/stats.c =================================================================== --- common/stats.c (nonexistent) +++ common/stats.c (revision 1765) @@ -0,0 +1,427 @@ +/* stats.c -- Various statistics about instruction scheduling etc. + + Copyright (C) 1999 Damjan Lampret, lampret@opencores.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" + +/* Package includes */ +#include "stats.h" +#include "sim-config.h" +#include "icache-model.h" +#include "spr-defs.h" +#include "execute.h" + + +#define DSTATS_LEN 3000 +#define SSTATS_LEN 300 +#define FSTATS_LEN 200 + +/* Used by safe division - increment divisor by one if it is zero */ +#define SD(X) (X != 0 ? X : 1) + +struct branchstat +{ + int taken; + int nottaken; + int forward; + int backward; +}; + +/*! @see also enum insn_type in abstract.h */ +static const char func_unit_str[30][30] = { + "unknown", + "exception", + "arith", + "shift", + "compare", + "branch", + "jump", + "load", + "store", + "movimm", + "move", + "extend", + "nop", + "mac" +}; + +struct dstats_entry +{ + int insn1; + int insn2; + int cnt_dynamic; + int depend; +}; /*!< double stats */ + +struct sstats_entry +{ + int insn; + int cnt_dynamic; +}; /*!< single stats */ + +struct fstats_entry +{ + enum insn_type insn1; + enum insn_type insn2; + int cnt_dynamic; + int depend; +}; /*!< functional units stats */ + +/* Globally visible statistics data. Renamed mstats to or1k_mstats because Mac + OS X has a lib function called mstats */ +struct mstats_entry or1k_mstats = { 0 }; /*!< misc units stats */ +struct cachestats_entry ic_stats = { 0 }; /*!< instruction cache stats */ +struct cachestats_entry dc_stats = { 0 }; /*!< data cache stats */ +struct immustats_entry immu_stats = { 0 }; /*!< insn MMU stats */ +struct dmmustats_entry dmmu_stats = { 0 }; /*!< data MMU stats */ +struct raw_stats raw_stats; /*!< RAW hazard stats */ + +/* Statistics data strutures used just here */ +static struct dstats_entry dstats[DSTATS_LEN]; /*!< dependency stats */ +static struct sstats_entry sstats[SSTATS_LEN]; /*!< single stats */ +static struct fstats_entry fstats[FSTATS_LEN]; /*!< func units stats */ + + +void +addsstats (int item, int cnt_dynamic) +{ + int i = 0; + + while (sstats[i].insn != item && sstats[i].insn >= 0 && i < SSTATS_LEN) + i++; + + if (i >= SSTATS_LEN - 1) + return; + + if (sstats[i].insn >= 0) + { + sstats[i].cnt_dynamic += cnt_dynamic; + } + else + { + sstats[i].insn = item; + sstats[i].cnt_dynamic = cnt_dynamic; + } +} + +void +adddstats (int item1, int item2, int cnt_dynamic, int depend) +{ + int i = 0; + + while ((dstats[i].insn1 != item1 || dstats[i].insn2 != item2) + && (i < DSTATS_LEN) && dstats[i].insn1 >= 0) + i++; + + if (i >= DSTATS_LEN - 1) + return; + + if (dstats[i].insn1 >= 0) + { + dstats[i].cnt_dynamic += cnt_dynamic; + dstats[i].depend += depend; + } + else + { + dstats[i].insn1 = item1; + dstats[i].insn2 = item2; + dstats[i].cnt_dynamic = cnt_dynamic; + dstats[i].depend = depend; + } +} + +void +addfstats (enum insn_type item1, enum insn_type item2, int cnt_dynamic, + int depend) +{ + int i = 0; + + while (((fstats[i].insn1 != item1) || (fstats[i].insn2 != item2)) && + (fstats[i].insn1 != it_unknown) && (i < FSTATS_LEN)) + i++; + + if (i >= FSTATS_LEN - 1) + return; + + if ((fstats[i].insn1 == item1) && (fstats[i].insn2 == item2)) + { + fstats[i].cnt_dynamic += cnt_dynamic; + fstats[i].depend += depend; + } + else + { + fstats[i].insn1 = item1; + fstats[i].insn2 = item2; + fstats[i].cnt_dynamic = cnt_dynamic; + fstats[i].depend = depend; + } +} + +void +initstats () +{ + int i; + memset (sstats, 0, sizeof (sstats)); + for (i = 0; i < SSTATS_LEN; i++) + sstats[i].insn = -1; + memset (dstats, 0, sizeof (dstats)); + for (i = 0; i < DSTATS_LEN; i++) + dstats[i].insn1 = dstats[i].insn2 = -1; + memset (fstats, 0, sizeof (fstats)); + memset (&or1k_mstats, 0, sizeof (or1k_mstats)); + memset (&ic_stats, 0, sizeof (ic_stats)); + memset (&dc_stats, 0, sizeof (dc_stats)); + memset (&raw_stats, 0, sizeof (raw_stats)); +} + +static void +printotherstats (int which) +{ + PRINTF ("\n"); + if (config.bpb.enabled) + { + struct branchstat bf; + struct branchstat bnf; + long bf_all, bnf_all; + bf.taken = or1k_mstats.bf[1][0] + or1k_mstats.bf[1][1]; + bf.nottaken = or1k_mstats.bf[0][0] + or1k_mstats.bf[0][1]; + bf.forward = or1k_mstats.bf[0][1] + or1k_mstats.bf[1][1]; + bf.backward = or1k_mstats.bf[0][0] + or1k_mstats.bf[1][0]; + bf_all = bf.forward + bf.backward; + + bnf.taken = or1k_mstats.bnf[1][0] + or1k_mstats.bf[1][1]; + bnf.nottaken = or1k_mstats.bnf[0][0] + or1k_mstats.bf[0][1]; + bnf.forward = or1k_mstats.bnf[0][1] + or1k_mstats.bf[1][1]; + bnf.backward = or1k_mstats.bnf[0][0] + or1k_mstats.bf[1][0]; + bnf_all = bnf.forward + bnf.backward; + + PRINTF ("bnf: %d (%ld%%) taken,", bf.taken, + (bf.taken * 100) / SD (bf_all)); + PRINTF (" %d (%ld%%) not taken,", bf.nottaken, + (bf.nottaken * 100) / SD (bf_all)); + PRINTF (" %d (%ld%%) forward,", bf.forward, + (bf.forward * 100) / SD (bf_all)); + PRINTF (" %d (%ld%%) backward\n", bf.backward, + (bf.backward * 100) / SD (bf_all)); + PRINTF ("bf: %d (%ld%%) taken,", bnf.taken, + (bnf.taken * 100) / SD (bnf_all)); + PRINTF (" %d (%ld%%) not taken,", bnf.nottaken, + (bnf.nottaken * 100) / SD (bnf_all)); + PRINTF (" %d (%ld%%) forward,", bnf.forward, + (bnf.forward * 100) / SD (bnf_all)); + PRINTF (" %d (%ld%%) backward\n", bnf.backward, + (bnf.backward * 100) / SD (bnf_all)); + + PRINTF ("StaticBP bnf(%s): correct %ld%%\n", + config.bpb.sbp_bnf_fwd ? "forward" : "backward", + (or1k_mstats.bnf[0][config.bpb.sbp_bnf_fwd] * 100) / + SD (bnf_all)); + PRINTF ("StaticBP bf(%s): correct %ld%%\n", + config.bpb.sbp_bf_fwd ? "forward" : "backward", + (or1k_mstats.bnf[1][config.bpb.sbp_bf_fwd] * 100) / + SD (bf_all)); + PRINTF ("BPB: hit %d (correct %d%%), miss %d\n", or1k_mstats.bpb.hit, + (or1k_mstats.bpb.correct * 100) / SD (or1k_mstats.bpb.hit), + or1k_mstats.bpb.miss); + } + else + PRINTF ("BPB simulation disabled. Enable it to see BPB analysis\n"); + + if (config.bpb.btic) + { + PRINTF ("BTIC: hit %d(%d%%), miss %d\n", or1k_mstats.btic.hit, + (or1k_mstats.btic.hit * 100) / SD (or1k_mstats.btic.hit + + or1k_mstats.btic.miss), + or1k_mstats.btic.miss); + } + else + PRINTF ("BTIC simulation disabled. Enabled it to see BTIC analysis\n"); + + if ((NULL != ic_state) && ic_state->enabled) + { + PRINTF ("IC read: hit %d(%d%%), miss %d\n", ic_stats.readhit, + (ic_stats.readhit * 100) / SD (ic_stats.readhit + + ic_stats.readmiss), + ic_stats.readmiss); + } + else + PRINTF ("No ICache. Enable it to see IC results.\n"); + + if (config.dc.enabled) + { + PRINTF ("DC read: hit %d(%d%%), miss %d\n", dc_stats.readhit, + (dc_stats.readhit * 100) / SD (dc_stats.readhit + + dc_stats.readmiss), + dc_stats.readmiss); + PRINTF ("DC write: hit %d(%d%%), miss %d\n", dc_stats.writehit, + (dc_stats.writehit * 100) / SD (dc_stats.writehit + + dc_stats.writemiss), + dc_stats.writemiss); + } + else + PRINTF ("No DCache. Enable it to see DC results.\n"); + + if (cpu_state.sprs[SPR_UPR] & SPR_UPR_IMP) + { + PRINTF ("IMMU read: hit %d(%d%%), miss %d\n", immu_stats.fetch_tlbhit, + (immu_stats.fetch_tlbhit * 100) / SD (immu_stats.fetch_tlbhit + + immu_stats.fetch_tlbmiss), + immu_stats.fetch_tlbmiss); + } + else + PRINTF ("No IMMU. Set UPR[IMP]\n"); + + if (cpu_state.sprs[SPR_UPR] & SPR_UPR_DMP) + { + PRINTF ("DMMU read: hit %d(%d%%), miss %d\n", dmmu_stats.loads_tlbhit, + (dmmu_stats.loads_tlbhit * 100) / SD (dmmu_stats.loads_tlbhit + + dmmu_stats.loads_tlbmiss), + dmmu_stats.loads_tlbmiss); + } + else + PRINTF ("No DMMU. Set UPR[DMP]\n"); + + PRINTF ("Additional LOAD CYCLES: %u STORE CYCLES: %u\n", + runtime.sim.loadcycles, runtime.sim.storecycles); +} + +void +printstats (int which) +{ + int i, all = 0, dependall = 0; + + if (which > 1 && which <= 5 && !config.cpu.dependstats) + { + PRINTF + ("Hazard analysis disabled. Enable it to see analysis results.\n"); + return; + } + + switch (which) + { + case 1: + PRINTF ("stats 1: Misc stats\n"); + printotherstats (which); + break; + case 2: + PRINTF ("stats 2: Instruction usage\n"); + for (i = 0; i < SSTATS_LEN; i++) + all += sstats[i].cnt_dynamic; + + for (i = 0; i < SSTATS_LEN; i++) + if (sstats[i].cnt_dynamic) + PRINTF (" %-15s used %6dx (%5.1f%%)\n", insn_name (sstats[i].insn), + sstats[i].cnt_dynamic, + (sstats[i].cnt_dynamic * 100.) / SD (all)); + + PRINTF ("%d instructions (dynamic, single stats)\n", all); + break; + + case 3: + PRINTF ("stats 3: Instruction dependencies\n"); + for (i = 0; i < DSTATS_LEN; i++) + { + all += dstats[i].cnt_dynamic; + dependall += dstats[i].depend; + } + + for (i = 0; i < DSTATS_LEN; i++) + if (dstats[i].cnt_dynamic) + { + char temp[100]; + sprintf (temp, "%s, %s ", insn_name (dstats[i].insn1), + insn_name (dstats[i].insn2)); + PRINTF (" %-30s %6dx (%5.1f%%)", temp, dstats[i].cnt_dynamic, + (dstats[i].cnt_dynamic * 100.) / SD (all)); + PRINTF (" depend: %5.1f%%\n", + (dstats[i].depend * 100.) / dstats[i].cnt_dynamic); + } + + PRINTF ("%d instructions (dynamic, dependency stats) depend: %d%%\n", + all, (dependall * 100) / SD (all)); + break; + + case 4: + PRINTF ("stats 4: Functional units dependencies\n"); + for (i = 0; i < FSTATS_LEN; i++) + { + all += fstats[i].cnt_dynamic; + dependall += fstats[i].depend; + } + + for (i = 0; i < FSTATS_LEN; i++) + if (fstats[i].cnt_dynamic) + { + char temp[100]; + sprintf (temp, "%s, %s", func_unit_str[fstats[i].insn1], + func_unit_str[fstats[i].insn2]); + PRINTF (" %-30s %6dx (%5.1f%%)", temp, fstats[i].cnt_dynamic, + (fstats[i].cnt_dynamic * 100.) / SD (all)); + PRINTF (" depend: %5.1f%%\n", + (fstats[i].depend * 100.) / fstats[i].cnt_dynamic); + } + PRINTF + ("%d instructions (dynamic, functional units stats) depend: %d%%\n\n", + all, (dependall * 100) / SD (all)); + break; + + case 5: + PRINTF ("stats 5: Raw register usage over time\n"); +#if RAW_RANGE_STATS + for (i = 0; (i < RAW_RANGE); i++) + PRINTF (" Register set and reused in %d. cycle: %d cases\n", i, + raw_stats.range[i]); +#endif + break; + case 6: + if (config.cpu.sbuf_len) + { + extern int sbuf_total_cyc, sbuf_wait_cyc; + PRINTF ("stats 6: Store buffer analysis\n"); + PRINTF ("Using store buffer of length %i.\n", config.cpu.sbuf_len); + PRINTF ("Number of total memory store cycles: %i/%lli\n", + sbuf_total_cyc, + runtime.sim.cycles + sbuf_total_cyc - sbuf_wait_cyc); + PRINTF ("Number of cycles waiting for memory stores: %i\n", + sbuf_wait_cyc); + PRINTF ("Number of memory cycles spared: %i\n", + sbuf_total_cyc - sbuf_wait_cyc); + PRINTF ("Store speedup %3.2f%%, total speedup %3.2f%%\n", + 100. * (sbuf_total_cyc - sbuf_wait_cyc) / sbuf_total_cyc, + 100. * (sbuf_total_cyc - + sbuf_wait_cyc) / (runtime.sim.cycles + + sbuf_total_cyc - sbuf_wait_cyc)); + } + else + PRINTF + ("Store buffer analysis disabled. Enable it to see analysis results.\n"); + break; + default: + PRINTF ("Please specify a stats group (1-6).\n"); + break; + } +} Index: common/abstract.c =================================================================== --- common/abstract.c (nonexistent) +++ common/abstract.c (revision 1765) @@ -0,0 +1,1251 @@ +/* abstract.c -- Abstract entities + + 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 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. */ + +/* Abstract memory and routines that go with this. I need to add all sorts of + other abstract entities. Currently we have only memory. */ + + +/* Autoconf and/or portability configuration */ +#include "config.h" +#include "port.h" + +/* System includes */ +#include + +/* Package includes */ +#include "abstract.h" +#include "except.h" +#include "support/profile.h" +#include "debug-unit.h" +#include "icache-model.h" +#include "dcache-model.h" +#include "labels.h" +#include "opcode/or32.h" +#include "dmmu.h" +#include "immu.h" + +#if DYNAMIC_EXECUTION +#include "dyn-rec.h" +#endif + + +/*! Global temporary variable to increase speed. */ +struct dev_memarea *cur_area; + +/* Glboal variables set by MMU if cache inhibit bit is set for current + access. */ +int data_ci; /*!< Global var: data cache inhibit bit set */ +int insn_ci; /*!< Global var: instr cache inhibit bit set */ + +/* Pointer to memory area descriptions that are assigned to individual + peripheral devices. */ +static struct dev_memarea *dev_list; + +/* Pointer to memory controller device descriptor. */ +static struct dev_memarea *mc_area = NULL; + +/* Virtual address of current access. */ +static oraddr_t cur_vadd; + +/* Forward declarations */ +static uint32_t eval_mem_32_inv (oraddr_t, void *); +static uint16_t eval_mem_16_inv (oraddr_t, void *); +static uint8_t eval_mem_8_inv (oraddr_t, void *); +static uint32_t eval_mem_32_inv_direct (oraddr_t, void *); +static uint16_t eval_mem_16_inv_direct (oraddr_t, void *); +static uint8_t eval_mem_8_inv_direct (oraddr_t, void *); +static void set_mem_32_inv (oraddr_t, uint32_t, void *); +static void set_mem_16_inv (oraddr_t, uint16_t, void *); +static void set_mem_8_inv (oraddr_t, uint8_t, void *); +static void set_mem_32_inv_direct (oraddr_t, uint32_t, void *); +static void set_mem_16_inv_direct (oraddr_t, uint16_t, void *); +static void set_mem_8_inv_direct (oraddr_t, uint8_t, void *); + +/* Calculates bit mask to fit the data */ +static unsigned int +bit_mask (uint32_t data) +{ + int i = 0; + data--; + while (data >> i) + data |= 1 << i++; + return data; +} + +/* Register read and write function for a memory area. + addr is inside the area, if addr & addr_mask == addr_compare + (used also by peripheral devices like 16450 UART etc.) */ +static struct dev_memarea * +register_memoryarea_mask (oraddr_t addr_mask, + oraddr_t addr_compare, + uint32_t size, unsigned mc_dev) +{ + struct dev_memarea **pptmp; + unsigned int size_mask = bit_mask (size); + int found_error = 0; + addr_compare &= addr_mask; + + /* Go to the end of the list. */ + for (pptmp = &dev_list; *pptmp; pptmp = &(*pptmp)->next) + if (((addr_compare >= (*pptmp)->addr_compare) && + (addr_compare < (*pptmp)->addr_compare + (*pptmp)->size)) || + ((addr_compare + size > (*pptmp)->addr_compare) && + (addr_compare < (*pptmp)->addr_compare + (*pptmp)->size))) + { + if (!found_error) + { + fprintf (stderr, "ERROR: Overlapping memory area(s):\n"); + fprintf (stderr, + "\taddr & %" PRIxADDR " == %" PRIxADDR " to %" PRIxADDR + ", size %08" PRIx32 "\n", addr_mask, addr_compare, + addr_compare | bit_mask (size), size); + } + found_error = 1; + fprintf (stderr, + "and\taddr & %" PRIxADDR " == %" PRIxADDR " to %" PRIxADDR + ", size %08" PRIx32 "\n", (*pptmp)->addr_mask, + (*pptmp)->addr_compare, + (*pptmp)->addr_compare | (*pptmp)->size_mask, + (*pptmp)->size); + } + + if (found_error) + exit (-1); + + cur_area = *pptmp = + (struct dev_memarea *) malloc (sizeof (struct dev_memarea)); + + if (mc_dev) + mc_area = *pptmp; + + (*pptmp)->addr_mask = addr_mask; + (*pptmp)->addr_compare = addr_compare; + (*pptmp)->size = size; + (*pptmp)->size_mask = size_mask; + (*pptmp)->log = NULL; + (*pptmp)->valid = 1; + (*pptmp)->next = NULL; + + return *pptmp; +} + +/* Register read and write function for a memory area. + Memory areas should be aligned. Memory area is rounded up to + fit the nearest 2^n aligment. + (used also by peripheral devices like 16450 UART etc.) + If mc_dev is 1, this device will be checked first for a match + and will be accessed in case of overlaping memory areas. + Only one device can have this set to 1 (used for memory controller) */ +struct dev_memarea * +reg_mem_area (oraddr_t addr, uint32_t size, unsigned mc_dev, + struct mem_ops *ops) +{ + unsigned int size_mask = bit_mask (size); + unsigned int addr_mask = ~size_mask; + struct dev_memarea *mem; + + mem = register_memoryarea_mask (addr_mask, addr & addr_mask, size_mask + 1, + mc_dev); + + memcpy (&mem->ops, ops, sizeof (struct mem_ops)); + memcpy (&mem->direct_ops, ops, sizeof (struct mem_ops)); + + if (!ops->readfunc32) + { + mem->ops.readfunc32 = eval_mem_32_inv; + mem->direct_ops.readfunc32 = eval_mem_32_inv_direct; + mem->direct_ops.read_dat32 = mem; + } + if (!ops->readfunc16) + { + mem->ops.readfunc16 = eval_mem_16_inv; + mem->direct_ops.readfunc16 = eval_mem_16_inv_direct; + mem->direct_ops.read_dat16 = mem; + } + if (!ops->readfunc8) + { + mem->ops.readfunc8 = eval_mem_8_inv; + mem->direct_ops.readfunc8 = eval_mem_8_inv_direct; + mem->direct_ops.read_dat8 = mem; + } + + if (!ops->writefunc32) + { + mem->ops.writefunc32 = set_mem_32_inv; + mem->direct_ops.writefunc32 = set_mem_32_inv_direct; + mem->direct_ops.write_dat32 = mem; + } + if (!ops->writefunc16) + { + mem->ops.writefunc16 = set_mem_16_inv; + mem->direct_ops.writefunc16 = set_mem_16_inv_direct; + mem->direct_ops.write_dat16 = mem; + } + if (!ops->writefunc8) + { + mem->ops.writefunc8 = set_mem_8_inv; + mem->direct_ops.writefunc8 = set_mem_8_inv_direct; + mem->direct_ops.write_dat8 = mem; + } + + if (!ops->writeprog8) + { + mem->ops.writeprog8 = mem->ops.writefunc8; + mem->ops.writeprog8_dat = mem->ops.write_dat8; + } + + if (!ops->writeprog32) + { + mem->ops.writeprog32 = mem->ops.writefunc32; + mem->ops.writeprog32_dat = mem->ops.write_dat32; + } + + if (ops->log) + { + if (!(mem->log = fopen (ops->log, "w"))) + PRINTF ("ERR: Unable to open %s to log memory acesses to\n", + ops->log); + } + + return mem; +} + +/* Check if access is to registered area of memory. */ +struct dev_memarea * +verify_memoryarea (oraddr_t addr) +{ + struct dev_memarea *ptmp; + + /* Check memory controller space first */ + if (mc_area + && (addr & mc_area->addr_mask) == + (mc_area->addr_compare & mc_area->addr_mask)) + return cur_area = mc_area; + + /* Check cached value */ + if (cur_area + && (addr & cur_area->addr_mask) == + (cur_area->addr_compare & cur_area->addr_mask)) + return cur_area; + + /* When mc is enabled, we must check valid also, otherwise we assume it is + nonzero */ + /* Check list of registered devices. */ + for (ptmp = dev_list; ptmp; ptmp = ptmp->next) + if ((addr & ptmp->addr_mask) == (ptmp->addr_compare & ptmp->addr_mask) + && ptmp->valid) + return cur_area = ptmp; + return cur_area = NULL; +} + +/* Sets the valid bit (Used only by memory controllers) */ +void +set_mem_valid (struct dev_memarea *mem, int valid) +{ + mem->valid = valid; +} + +/* Adjusts the read and write delays for the memory area pointed to by mem. */ +void +adjust_rw_delay (struct dev_memarea *mem, int delayr, int delayw) +{ + mem->ops.delayr = delayr; + mem->ops.delayw = delayw; +} + +static uint8_t +eval_mem_8_inv (oraddr_t memaddr, void *dat) +{ + except_handle (EXCEPT_BUSERR, cur_vadd); + return 0; +} + +static uint16_t +eval_mem_16_inv (oraddr_t memaddr, void *dat) +{ + except_handle (EXCEPT_BUSERR, cur_vadd); + return 0; +} + +static uint32_t +eval_mem_32_inv (oraddr_t memaddr, void *dat) +{ + except_handle (EXCEPT_BUSERR, cur_vadd); + return 0; +} + +static void +set_mem_8_inv (oraddr_t memaddr, uint8_t val, void *dat) +{ + except_handle (EXCEPT_BUSERR, cur_vadd); +} + +static void +set_mem_16_inv (oraddr_t memaddr, uint16_t val, void *dat) +{ + except_handle (EXCEPT_BUSERR, cur_vadd); +} + +static void +set_mem_32_inv (oraddr_t memaddr, uint32_t val, void *dat) +{ + except_handle (EXCEPT_BUSERR, cur_vadd); +} + +uint8_t +eval_mem_8_inv_direct (oraddr_t memaddr, void *dat) +{ + struct dev_memarea *mem = dat; + + PRINTF ("ERROR: Invalid 8-bit direct read from memory %" PRIxADDR "\n", + mem->addr_compare | memaddr); + return 0; +} + +uint16_t +eval_mem_16_inv_direct (oraddr_t memaddr, void *dat) +{ + struct dev_memarea *mem = dat; + + PRINTF ("ERROR: Invalid 16-bit direct read from memory %" PRIxADDR "\n", + mem->addr_compare | memaddr); + return 0; +} + +uint32_t +eval_mem_32_inv_direct (oraddr_t memaddr, void *dat) +{ + struct dev_memarea *mem = dat; + + PRINTF ("ERROR: Invalid 32-bit direct read from memory %" PRIxADDR "\n", + mem->addr_compare | memaddr); + return 0; +} + +void +set_mem_8_inv_direct (oraddr_t memaddr, uint8_t val, void *dat) +{ + struct dev_memarea *mem = dat; + + PRINTF ("ERROR: Invalid 32-bit direct write to memory %" PRIxADDR "\n", + mem->addr_compare | memaddr); +} + +void +set_mem_16_inv_direct (oraddr_t memaddr, uint16_t val, void *dat) +{ + struct dev_memarea *mem = dat; + + PRINTF ("ERROR: Invalid 16-bit direct write to memory %" PRIxADDR "\n", + mem->addr_compare | memaddr); +} + +void +set_mem_32_inv_direct (oraddr_t memaddr, uint32_t val, void *dat) +{ + struct dev_memarea *mem = dat; + + PRINTF ("ERROR: Invalid 32-bit direct write to memory %" PRIxADDR "\n", + mem->addr_compare | memaddr); +} + +/* For cpu accesses + * + * NOTE: This function _is_ only called from eval_mem32 below and + * {i,d}c_simulate_read. _Don't_ call it from anywere else. + */ +uint32_t +evalsim_mem32 (oraddr_t memaddr, oraddr_t vaddr) +{ + struct dev_memarea *mem; + + if ((mem = verify_memoryarea (memaddr))) + { + runtime.sim.mem_cycles += mem->ops.delayr; + return mem->ops.readfunc32 (memaddr & mem->size_mask, + mem->ops.read_dat32); + } + else + { + PRINTF ("EXCEPTION: read out of memory (32-bit access to %" PRIxADDR + ")\n", memaddr); + except_handle (EXCEPT_BUSERR, vaddr); + } + + return 0; +} + +/* For cpu accesses + * + * NOTE: This function _is_ only called from eval_mem16 below and + * {i,d}c_simulate_read. _Don't_ call it from anywere else. + */ +uint16_t +evalsim_mem16 (oraddr_t memaddr, oraddr_t vaddr) +{ + struct dev_memarea *mem; + + if ((mem = verify_memoryarea (memaddr))) + { + runtime.sim.mem_cycles += mem->ops.delayr; + return mem->ops.readfunc16 (memaddr & mem->size_mask, + mem->ops.read_dat16); + } + else + { + PRINTF ("EXCEPTION: read out of memory (16-bit access to %" PRIxADDR + ")\n", memaddr); + except_handle (EXCEPT_BUSERR, vaddr); + } + + return 0; +} + +/* For cpu accesses + * + * NOTE: This function _is_ only called from eval_mem8 below and + * {i,d}c_simulate_read. _Don't_ call it from anywere else. + */ +uint8_t +evalsim_mem8 (oraddr_t memaddr, oraddr_t vaddr) +{ + struct dev_memarea *mem; + + if ((mem = verify_memoryarea (memaddr))) + { + runtime.sim.mem_cycles += mem->ops.delayr; + return mem->ops.readfunc8 (memaddr & mem->size_mask, + mem->ops.read_dat8); + } + else + { + PRINTF ("EXCEPTION: read out of memory (8-bit access to %" PRIxADDR + ")\n", memaddr); + except_handle (EXCEPT_BUSERR, vaddr); + } + + return 0; +} + +/* Returns 32-bit values from mem array. Big endian version. + * + * STATISTICS OK (only used for cpu_access, that is architectural access) + */ +uint32_t +eval_mem32 (oraddr_t memaddr, int *breakpoint) +{ + uint32_t temp; + oraddr_t phys_memaddr; + + if (config.sim.mprofile) + mprofile (memaddr, MPROF_32 | MPROF_READ); + + if (memaddr & 3) + { + except_handle (EXCEPT_ALIGN, memaddr); + return 0; + } + + if (config.debug.enabled) + *breakpoint += check_debug_unit (DebugLoadAddress, memaddr); /* 28/05/01 CZ */ + + phys_memaddr = dmmu_translate (memaddr, 0); + if (except_pending) + return 0; + + if (config.dc.enabled) + temp = dc_simulate_read (phys_memaddr, memaddr, 4); + else + temp = evalsim_mem32 (phys_memaddr, memaddr); + + if (config.debug.enabled) + *breakpoint += check_debug_unit (DebugLoadData, temp); /* MM170901 */ + + return temp; +} + +/* for simulator accesses, the ones that cpu wouldn't do + * + * STATISTICS OK + */ +uint32_t +eval_direct32 (oraddr_t memaddr, int through_mmu, int through_dc) +{ + oraddr_t phys_memaddr; + struct dev_memarea *mem; + + if (memaddr & 3) + { + PRINTF ("%s:%d %s(): ERR unaligned access\n", __FILE__, __LINE__, + __FUNCTION__); + return 0; + } + + phys_memaddr = memaddr; + + if (through_mmu) + phys_memaddr = peek_into_dtlb (memaddr, 0, through_dc); + + if (through_dc) + return dc_simulate_read (phys_memaddr, memaddr, 4); + else + { + if ((mem = verify_memoryarea (phys_memaddr))) + return mem->direct_ops.readfunc32 (phys_memaddr & mem->size_mask, + mem->direct_ops.read_dat32); + else + PRINTF ("ERR: 32-bit read out of memory area: %" PRIxADDR + " (physical: %" PRIxADDR ")\n", memaddr, phys_memaddr); + } + + return 0; +} + + +/* Returns 32-bit values from mem array. Big endian version. + * + * STATISTICS OK (only used for cpu_access, that is architectural access) + */ +uint32_t +eval_insn (oraddr_t memaddr, int *breakpoint) +{ + uint32_t temp; + oraddr_t phys_memaddr; + + if (config.sim.mprofile) + mprofile (memaddr, MPROF_32 | MPROF_FETCH); + + phys_memaddr = memaddr; +#if !(DYNAMIC_EXECUTION) + phys_memaddr = immu_translate (memaddr); + + if (except_pending) + return 0; +#endif + + if (config.debug.enabled) + *breakpoint += check_debug_unit (DebugInstructionFetch, memaddr); + + if ((NULL != ic_state) && ic_state->enabled) + temp = ic_simulate_fetch (phys_memaddr, memaddr); + else + temp = evalsim_mem32 (phys_memaddr, memaddr); + + if (config.debug.enabled) + *breakpoint += check_debug_unit (DebugLoadData, temp); + return temp; +} + +/* Returns 16-bit values from mem array. Big endian version. + * + * STATISTICS OK (only used for cpu_access, that is architectural access) + */ +uint16_t +eval_mem16 (oraddr_t memaddr, int *breakpoint) +{ + uint16_t temp; + oraddr_t phys_memaddr; + + if (config.sim.mprofile) + mprofile (memaddr, MPROF_16 | MPROF_READ); + + if (memaddr & 1) + { + except_handle (EXCEPT_ALIGN, memaddr); + return 0; + } + + if (config.debug.enabled) + *breakpoint += check_debug_unit (DebugLoadAddress, memaddr); /* 28/05/01 CZ */ + + phys_memaddr = dmmu_translate (memaddr, 0); + if (except_pending) + return 0; + + if (config.dc.enabled) + temp = dc_simulate_read (phys_memaddr, memaddr, 2); + else + temp = evalsim_mem16 (phys_memaddr, memaddr); + + if (config.debug.enabled) + *breakpoint += check_debug_unit (DebugLoadData, temp); /* MM170901 */ + + return temp; +} + +/* for simulator accesses, the ones that cpu wouldn't do + * + * STATISTICS OK. + */ +uint16_t +eval_direct16 (oraddr_t memaddr, int through_mmu, int through_dc) +{ + oraddr_t phys_memaddr; + struct dev_memarea *mem; + + if (memaddr & 1) + { + PRINTF ("%s:%d %s(): ERR unaligned access\n", __FILE__, __LINE__, + __FUNCTION__); + return 0; + } + + phys_memaddr = memaddr; + + if (through_mmu) + phys_memaddr = peek_into_dtlb (memaddr, 0, through_dc); + + if (through_dc) + return dc_simulate_read (phys_memaddr, memaddr, 2); + else + { + if ((mem = verify_memoryarea (phys_memaddr))) + return mem->direct_ops.readfunc16 (phys_memaddr & mem->size_mask, + mem->direct_ops.read_dat16); + else + PRINTF ("ERR: 16-bit read out of memory area: %" PRIxADDR + " (physical: %" PRIxADDR "\n", memaddr, phys_memaddr); + } + + return 0; +} + +/* Returns 8-bit values from mem array. + * + * STATISTICS OK (only used for cpu_access, that is architectural access) + */ +uint8_t +eval_mem8 (oraddr_t memaddr, int *breakpoint) +{ + uint8_t temp; + oraddr_t phys_memaddr; + + if (config.sim.mprofile) + mprofile (memaddr, MPROF_8 | MPROF_READ); + + if (config.debug.enabled) + *breakpoint += check_debug_unit (DebugLoadAddress, memaddr); /* 28/05/01 CZ */ + + phys_memaddr = dmmu_translate (memaddr, 0); + if (except_pending) + return 0; + + if (config.dc.enabled) + temp = dc_simulate_read (phys_memaddr, memaddr, 1); + else + temp = evalsim_mem8 (phys_memaddr, memaddr); + + if (config.debug.enabled) + *breakpoint += check_debug_unit (DebugLoadData, temp); /* MM170901 */ + return temp; +} + +/* for simulator accesses, the ones that cpu wouldn't do + * + * STATISTICS OK. + */ +uint8_t +eval_direct8 (oraddr_t memaddr, int through_mmu, int through_dc) +{ + oraddr_t phys_memaddr; + struct dev_memarea *mem; + + phys_memaddr = memaddr; + + if (through_mmu) + phys_memaddr = peek_into_dtlb (memaddr, 0, through_dc); + + if (through_dc) + return dc_simulate_read (phys_memaddr, memaddr, 1); + else + { + if ((mem = verify_memoryarea (phys_memaddr))) + return mem->direct_ops.readfunc8 (phys_memaddr & mem->size_mask, + mem->direct_ops.read_dat8); + else + PRINTF ("ERR: 8-bit read out of memory area: %" PRIxADDR + " (physical: %" PRIxADDR "\n", memaddr, phys_memaddr); + } + + return 0; +} + +/* For cpu accesses + * + * NOTE: This function _is_ only called from set_mem32 below and + * dc_simulate_write. _Don't_ call it from anywere else. + */ +void +setsim_mem32 (oraddr_t memaddr, oraddr_t vaddr, uint32_t value) +{ + struct dev_memarea *mem; + + if ((mem = verify_memoryarea (memaddr))) + { + cur_vadd = vaddr; + runtime.sim.mem_cycles += mem->ops.delayw; + mem->ops.writefunc32 (memaddr & mem->size_mask, value, + mem->ops.write_dat32); +#if DYNAMIC_EXECUTION + dyn_checkwrite (memaddr); +#endif + } + else + { + PRINTF ("EXCEPTION: write out of memory (32-bit access to %" PRIxADDR + ")\n", memaddr); + except_handle (EXCEPT_BUSERR, vaddr); + } +} + +/* For cpu accesses + * + * NOTE: This function _is_ only called from set_mem16 below and + * dc_simulate_write. _Don't_ call it from anywere else. + */ +void +setsim_mem16 (oraddr_t memaddr, oraddr_t vaddr, uint16_t value) +{ + struct dev_memarea *mem; + + if ((mem = verify_memoryarea (memaddr))) + { + cur_vadd = vaddr; + runtime.sim.mem_cycles += mem->ops.delayw; + mem->ops.writefunc16 (memaddr & mem->size_mask, value, + mem->ops.write_dat16); +#if DYNAMIC_EXECUTION + dyn_checkwrite (memaddr); +#endif + } + else + { + PRINTF ("EXCEPTION: write out of memory (16-bit access to %" PRIxADDR + ")\n", memaddr); + except_handle (EXCEPT_BUSERR, vaddr); + } +} + +/* For cpu accesses + * + * NOTE: This function _is_ only called from set_mem8 below and + * dc_simulate_write. _Don't_ call it from anywere else. + */ +void +setsim_mem8 (oraddr_t memaddr, oraddr_t vaddr, uint8_t value) +{ + struct dev_memarea *mem; + + if ((mem = verify_memoryarea (memaddr))) + { + cur_vadd = vaddr; + runtime.sim.mem_cycles += mem->ops.delayw; + mem->ops.writefunc8 (memaddr & mem->size_mask, value, + mem->ops.write_dat8); +#if DYNAMIC_EXECUTION + dyn_checkwrite (memaddr); +#endif + } + else + { + PRINTF ("EXCEPTION: write out of memory (8-bit access to %" PRIxADDR + ")\n", memaddr); + except_handle (EXCEPT_BUSERR, vaddr); + } +} + +/* Set mem, 32-bit. Big endian version. + * + * STATISTICS OK. (the only suspicious usage is in sim-cmd.c, + * where this instruction is used for patching memory, + * wether this is cpu or architectual access is yet to + * be decided) + */ +void +set_mem32 (oraddr_t memaddr, uint32_t value, int *breakpoint) +{ + oraddr_t phys_memaddr; + + if (config.sim.mprofile) + mprofile (memaddr, MPROF_32 | MPROF_WRITE); + + if (memaddr & 3) + { + except_handle (EXCEPT_ALIGN, memaddr); + return; + } + + phys_memaddr = dmmu_translate (memaddr, 1);; + /* If we produced exception don't set anything */ + if (except_pending) + return; + + if (config.debug.enabled) + { + *breakpoint += check_debug_unit (DebugStoreAddress, memaddr); /* 28/05/01 CZ */ + *breakpoint += check_debug_unit (DebugStoreData, value); + } + + if (config.dc.enabled) + dc_simulate_write (phys_memaddr, memaddr, value, 4); + else + setsim_mem32 (phys_memaddr, memaddr, value); + + if (cur_area && cur_area->log) + fprintf (cur_area->log, "[%" PRIxADDR "] -> write %08" PRIx32 "\n", + memaddr, value); +} + +/* + * STATISTICS NOT OK. + */ +void +set_direct32 (oraddr_t memaddr, uint32_t value, int through_mmu, + int through_dc) +{ + oraddr_t phys_memaddr; + struct dev_memarea *mem; + + if (memaddr & 3) + { + PRINTF ("%s:%d %s(): ERR unaligned access\n", __FILE__, __LINE__, + __FUNCTION__); + return; + } + + phys_memaddr = memaddr; + + if (through_mmu) + { + /* 0 - no write access, we do not want a DPF exception do we ;) + */ + phys_memaddr = peek_into_dtlb (memaddr, 1, through_dc); + } + + if (through_dc) + dc_simulate_write (memaddr, memaddr, value, 4); + else + { + if ((mem = verify_memoryarea (phys_memaddr))) + mem->direct_ops.writefunc32 (phys_memaddr & mem->size_mask, value, + mem->direct_ops.write_dat32); + else + PRINTF ("ERR: 32-bit write out of memory area: %" PRIxADDR + " (physical: %" PRIxADDR ")\n", memaddr, phys_memaddr); + } + + if (cur_area && cur_area->log) + fprintf (cur_area->log, "[%" PRIxADDR "] -> DIRECT write %08" PRIx32 "\n", + memaddr, value); +} + + +/* Set mem, 16-bit. Big endian version. */ + +void +set_mem16 (oraddr_t memaddr, uint16_t value, int *breakpoint) +{ + oraddr_t phys_memaddr; + + if (config.sim.mprofile) + mprofile (memaddr, MPROF_16 | MPROF_WRITE); + + if (memaddr & 1) + { + except_handle (EXCEPT_ALIGN, memaddr); + return; + } + + phys_memaddr = dmmu_translate (memaddr, 1);; + /* If we produced exception don't set anything */ + if (except_pending) + return; + + if (config.debug.enabled) + { + *breakpoint += check_debug_unit (DebugStoreAddress, memaddr); /* 28/05/01 CZ */ + *breakpoint += check_debug_unit (DebugStoreData, value); + } + + if (config.dc.enabled) + dc_simulate_write (phys_memaddr, memaddr, value, 2); + else + setsim_mem16 (phys_memaddr, memaddr, value); + + if (cur_area && cur_area->log) + fprintf (cur_area->log, "[%" PRIxADDR "] -> write %04" PRIx16 "\n", + memaddr, value); +} + +/* + * STATISTICS NOT OK. + */ +void +set_direct16 (oraddr_t memaddr, uint16_t value, int through_mmu, + int through_dc) +{ + oraddr_t phys_memaddr; + struct dev_memarea *mem; + + if (memaddr & 1) + { + PRINTF ("%s:%d %s(): ERR unaligned access\n", __FILE__, __LINE__, + __FUNCTION__); + return; + } + + phys_memaddr = memaddr; + + if (through_mmu) + { + /* 0 - no write access, we do not want a DPF exception do we ;) + */ + phys_memaddr = peek_into_dtlb (memaddr, 0, through_dc); + } + + if (through_dc) + dc_simulate_write (memaddr, memaddr, value, 2); + else + { + if ((mem = verify_memoryarea (phys_memaddr))) + mem->direct_ops.writefunc16 (phys_memaddr & mem->size_mask, value, + mem->direct_ops.write_dat16); + else + PRINTF ("ERR: 16-bit write out of memory area: %" PRIxADDR + " (physical: %" PRIxADDR "\n", memaddr, phys_memaddr); + } + + if (cur_area && cur_area->log) + fprintf (cur_area->log, "[%" PRIxADDR "] -> DIRECT write %04" PRIx16 "\n", + memaddr, value); +} + +/* Set mem, 8-bit. */ +void +set_mem8 (oraddr_t memaddr, uint8_t value, int *breakpoint) +{ + oraddr_t phys_memaddr; + + if (config.sim.mprofile) + mprofile (memaddr, MPROF_8 | MPROF_WRITE); + + phys_memaddr = memaddr; + + phys_memaddr = dmmu_translate (memaddr, 1);; + /* If we produced exception don't set anything */ + if (except_pending) + return; + + if (config.debug.enabled) + { + *breakpoint += check_debug_unit (DebugStoreAddress, memaddr); /* 28/05/01 CZ */ + *breakpoint += check_debug_unit (DebugStoreData, value); + } + + if (config.dc.enabled) + dc_simulate_write (phys_memaddr, memaddr, value, 1); + else + setsim_mem8 (phys_memaddr, memaddr, value); + + if (cur_area && cur_area->log) + fprintf (cur_area->log, "[%" PRIxADDR "] -> write %02" PRIx8 "\n", + memaddr, value); +} + +/* + * STATISTICS NOT OK. + */ +void +set_direct8 (oraddr_t memaddr, uint8_t value, int through_mmu, int through_dc) +{ + oraddr_t phys_memaddr; + struct dev_memarea *mem; + + phys_memaddr = memaddr; + + if (through_mmu) + { + /* 0 - no write access, we do not want a DPF exception do we ;) + */ + phys_memaddr = peek_into_dtlb (memaddr, 0, through_dc); + } + + if (through_dc) + dc_simulate_write (phys_memaddr, memaddr, value, 1); + else + { + if ((mem = verify_memoryarea (phys_memaddr))) + mem->direct_ops.writefunc8 (phys_memaddr & mem->size_mask, value, + mem->direct_ops.write_dat8); + else + PRINTF ("ERR: 8-bit write out of memory area: %" PRIxADDR + " (physical: %" PRIxADDR "\n", memaddr, phys_memaddr); + } + + if (cur_area && cur_area->log) + fprintf (cur_area->log, "[%" PRIxADDR "] -> DIRECT write %02" PRIx8 "\n", + memaddr, value); +} + + +/* set_program32 - same as set_direct32, but it also writes to memory that is + * non-writeable to the rest of the sim. Used to do program + * loading. + */ +void +set_program32 (oraddr_t memaddr, uint32_t value) +{ + struct dev_memarea *mem; + + if (memaddr & 3) + { + PRINTF ("%s(): ERR unaligned 32-bit program write\n", __FUNCTION__); + return; + } + + if ((mem = verify_memoryarea (memaddr))) + { + mem->ops.writeprog32 (memaddr & mem->size_mask, value, + mem->ops.writeprog32_dat); + } + else + PRINTF ("ERR: 32-bit program load out of memory area: %" PRIxADDR "\n", + memaddr); +} + +/* set_program8 - same as set_direct8, but it also writes to memory that is + * non-writeable to the rest of the sim. Used to do program + * loading. + */ +void +set_program8 (oraddr_t memaddr, uint8_t value) +{ + struct dev_memarea *mem; + + if ((mem = verify_memoryarea (memaddr))) + { + mem->ops.writeprog8 (memaddr & mem->size_mask, value, + mem->ops.writeprog8_dat); + } + else + PRINTF ("ERR: 8-bit program load out of memory area: %" PRIxADDR "\n", + memaddr); +} + + +/*---------------------------------------------------------------------------*/ +/*!Dump memory to the current output + + Output format is hex bytes, 16 bytes per line. Start each line with its + address and (optionally) its symbolic name. Always end with a newline. + + There are all sorts of ways to trip this up, but they are unlikely. The + validity of a memory area is taken from the address of the start of a line + to be printed, so assumes the following 15 bytes are present. This could be + fooled by ridiculous memory declarations. + + @param[in] from Start address of the area of memory + @param[in] to End address of the area of memory */ +/*---------------------------------------------------------------------------*/ +void +dump_memory (oraddr_t from, oraddr_t to) +{ + const int ROW_LEN = 16; + oraddr_t i; /* Row counter */ + + for (i = from; i < to; i += ROW_LEN) + { + struct label_entry *entry = get_label (i); + oraddr_t j; /* Index in row */ + + PRINTF ("%" PRIxADDR, i); + + if (NULL != entry) + { + int padding = 11 - strlen (entry->name); + + PRINTF (" <%s>: ", entry->name); + PRINTF ("%*s ", padding < 0 ? 0 : padding, " "); + } + else + { + PRINTF (": "); + } + + + for (j = 0; j < ROW_LEN; j++) + { + if (verify_memoryarea (i + j)) + { + PRINTF ("%02" PRIx8 " ", eval_direct8 (i + j, 0, 0)); + } + else + { + /* Not a valid memory area. Print Xs as required */ + PRINTF ("XX "); + } + } + + PRINTF ("\n"); + } +} /* dump_memory() */ + + +/*---------------------------------------------------------------------------*/ +/*!Disassemble memory to the current output + + Output format is symbolic disassembly, one instruction per line. Start each + line with its address and (optionally) its symbolic name. + + There are all sorts of ways to trip this up, but they are unlikely. The + validity of a memory area is taken from the address of the start of a line + to be printed, so assumes the following 3 bytes are present. This could be + fooled by ridiculous memory declarations. + + @param[in] from Start address of the area of memory + @param[in] to End address of the area of memory + @param[in] nl If non-zero (true) print a newline at the end of each + line */ +/*---------------------------------------------------------------------------*/ +void +disassemble_memory (oraddr_t from, oraddr_t to, int nl) +{ + const int INSTR_LEN = 4; + oraddr_t i; /* Row counter */ + + for (i = from; i < to; i += INSTR_LEN) + { + struct label_entry *entry = get_label (i); + + PRINTF ("%" PRIxADDR, i); + + if (NULL != entry) + { + int padding = 11 - strlen (entry->name); + + PRINTF (" <%s>: ", entry->name); + PRINTF ("%*s ", padding < 0 ? 0 : padding, " "); + } + else + { + PRINTF (": "); + } + + if (verify_memoryarea (i)) + { + uint32_t insn = eval_direct32 (i, 0, 0); + int index = insn_decode (insn); + + PRINTF ("%08" PRIx32 " ", insn); + + if (index >= 0) + { + disassemble_insn (insn); + PRINTF (" %s", disassembled); + } + else + { + PRINTF (""); + } + + } + else + { + /* Not a valid memory area. Print Xs as required */ + PRINTF ("XXXXXXXX"); + } + + if (nl) + { + PRINTF ("\n"); + } + } +} /* disassemble_memory() */ + + +/* Closes files, etc. */ + +void +done_memory_table () +{ + struct dev_memarea *ptmp; + + /* Check list of registered devices. */ + for (ptmp = dev_list; ptmp; ptmp = ptmp->next) + { + if (ptmp->log) + fclose (ptmp->log); + } +} + +/* Displays current memory configuration */ + +void +memory_table_status (void) +{ + struct dev_memarea *ptmp; + + /* Check list of registered devices. */ + for (ptmp = dev_list; ptmp; ptmp = ptmp->next) + { + PRINTF ("addr & %" PRIxADDR " == %" PRIxADDR " to %" PRIxADDR ", size %" + PRIx32 "\n", ptmp->addr_mask, ptmp->addr_compare, + ptmp->addr_compare | bit_mask (ptmp->size), ptmp->size); + PRINTF ("\t"); + if (ptmp->ops.delayr >= 0) + PRINTF ("read delay = %i cycles, ", ptmp->ops.delayr); + else + PRINTF ("reads not possible, "); + + if (ptmp->ops.delayw >= 0) + PRINTF ("write delay = %i cycles", ptmp->ops.delayw); + else + PRINTF ("writes not possible"); + + if (ptmp->log) + PRINTF (", (logged)\n"); + else + PRINTF ("\n"); + } +} + +/* Outputs time in pretty form to dest string */ + +char * +generate_time_pretty (char *dest, long time_ps) +{ + int exp3 = 0; + if (time_ps) + { + while ((time_ps % 1000) == 0) + { + time_ps /= 1000; + exp3++; + } + } + sprintf (dest, "%li%cs", time_ps, "pnum"[exp3]); + return dest; +} Index: common/stats.h =================================================================== --- common/stats.h (nonexistent) +++ common/stats.h (revision 1765) @@ -0,0 +1,105 @@ +/* stats.h -- Header file for stats.c + + Copyright (C) 1999 Damjan Lampret, lampret@opencores.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. */ + + +#ifndef STATS__H +#define STATS__H + +/* Package includes */ +#include "opcode/or32.h" + +#define RAW_RANGE 1000 + +struct bpbstat +{ + int hit; + int miss; + int correct; + int incorrect; +}; + +struct bticstat +{ + int hit; + int miss; +}; + +struct mstats_entry +{ + int byteadd; + int bf[2][2]; /* [taken][fwd/bwd] */ + int bnf[2][2]; /* [taken][fwd/bwd] */ + struct bpbstat bpb; + struct bticstat btic; +}; /*!< misc units stats */ + +struct cachestats_entry +{ + int readhit; + int readmiss; + int writehit; + int writemiss; +}; /*!< cache stats */ + +struct immustats_entry +{ + int fetch_tlbhit; + int fetch_tlbmiss; + int fetch_pagefaults; +}; /*!< IMMU stats */ + +struct dmmustats_entry +{ + int loads_tlbhit; + int loads_tlbmiss; + int loads_pagefaults; + int stores_tlbhit; + int stores_tlbmiss; + int stores_pagefaults; +}; /*!< DMMU stats */ + +struct raw_stats +{ + int reg[64]; + int range[RAW_RANGE]; +}; /*!< RAW hazard stats */ + +/* Globally visible data structures */ +extern struct mstats_entry or1k_mstats; +extern struct cachestats_entry ic_stats; +extern struct cachestats_entry dc_stats; +extern struct immustats_entry immu_stats; +extern struct dmmustats_entry dmmu_stats; +extern struct raw_stats raw_stats; + +/* Function prototypes for external use */ +extern void addsstats (int item, int cnt_dynamic); +extern void adddstats (int item1, int item2, int cnt_dynamic, int depend); +extern void addfstats (enum insn_type item1, enum insn_type item2, + int cnt_dynamic, int depend); +extern void initstats (); +extern void printstats (); + +#endif /* STATS__H */ Index: common/execute.h =================================================================== --- common/execute.h (nonexistent) +++ common/execute.h (revision 1765) @@ -0,0 +1,117 @@ +/* execute.h -- Header file for architecture dependent execute.c + + Copyright (C) 1999 Damjan Lampret, lampret@opencores.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. */ + + +#ifndef EXECUTE__H +#define EXECUTE__H + +#include "spr-defs.h" +#include "opcode/or32.h" +#include "abstract.h" + +#if DYNAMIC_EXECUTION +#include "setjmp.h" +#include "dyn-rec.h" +#endif + + +#define CURINSN(INSN) (strcmp(cur->insn, (INSN)) == 0) + +/*! 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 + +/*!The main structure holding the current execution state of the CPU + + Not to be confused with @c runtime, which holds the state of the + simulation. + + @c insn_ea field is only used to get dump_exe_log() correct. + + @c iqueue and @c icomplet fields are only used in analysis(). + + The micro-operation queue, @c opqs, is only used to speed up + recompile_page(). */ +struct cpu_state { + uorreg_t reg[MAX_GPRS]; /*!< General purpose registers */ + uorreg_t sprs[MAX_SPRS]; /*!< Special purpose registers */ + oraddr_t insn_ea; /*!< EA of instrs that have an EA */ + int delay_insn; /*!< Is current instr in delay slot */ + oraddr_t pc; /*!< PC (and translated PC) */ + oraddr_t pc_delay; /*!< Delay instr EA register */ + uint32_t pic_lines; /*!< State of PIC lines */ + struct iqueue_entry iqueue; /*!< Decode of just executed instr */ + struct iqueue_entry icomplet; /*!< Decode of instr before this */ + +#if DYNAMIC_EXECUTION + jmp_buf excpt_loc; /*!< Longjump here for exception */ + struct dyn_page *curr_page; /*!< Current page in execution */ + struct dyn_page **dyn_pages; /*!< Pointers to recompiled pages */ + int32_t cycles_dec; + struct op_queue *opqs; /*!< Micro-operation queue */ +#endif +}; + +/*! History of execution */ +struct hist_exec +{ + oraddr_t addr; + struct hist_exec *prev; + struct hist_exec *next; +}; + +/* Globally visible data structures */ +extern struct cpu_state cpu_state; +extern oraddr_t pcnext; +extern int sbuf_wait_cyc; +extern int sbuf_total_cyc; +extern int do_stats; +extern struct hist_exec *hist_exec_tail; + + +/* Prototypes for external use */ +extern void dumpreg (); +extern void dump_exe_log (); +extern int cpu_clock (); +extern void cpu_reset (); +extern uorreg_t evalsim_reg (unsigned int regno); +extern void setsim_reg (unsigned int regno, + uorreg_t value); +extern uorreg_t eval_operand_val (uint32_t insn, + struct insn_op_struct *opd); +extern void analysis (struct iqueue_entry *current); +extern void cpu_reset (); +extern int cpu_clock (); +extern void exec_main (); +extern int depend_operands (struct iqueue_entry *prev, + struct iqueue_entry *next); +#endif /* EXECUTE__H */ Index: common/parse.c =================================================================== --- common/parse.c (nonexistent) +++ common/parse.c (revision 1765) @@ -0,0 +1,883 @@ +/* parse.c -- Architecture independent load + + Copyright (C) 1999 Damjan Lampret, lampret@opencores.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 + +/* Package includes */ +#include "parse.h" +#include "sim-config.h" +#include "debug.h" +#include "abstract.h" +#include "opcode/or32.h" +#include "coff.h" +#include "elf.h" +#include "labels.h" + + +DECLARE_DEBUG_CHANNEL (coff) + +#define MEMORY_LEN 0x100000000ULL + +/*!Whether to do immediate statistics. This seems to be for local debugging + of parse.c */ +#define IMM_STATS 0 + +/*!Unused mem memory marker. It is used when allocating program and data + memory during parsing */ +static unsigned int freemem; + +/*!Translation table provided by microkernel. Only used if simulating + microkernel. */ +static oraddr_t transl_table; + +/*!Used to signal whether during loading of programs a translation fault + occured. */ +static uint32_t transl_error; + +#if IMM_STATS +static int bcnt[33][3] = { 0 }; +static int bsum[3] = { 0 }; +static uint32_t movhi = 0; +#endif /* IMM_STATS */ + +/*---------------------------------------------------------------------------*/ +/*!Copy a string with null termination + + This function is very similar to strncpy, except it null terminates the + string. A global function also used by the CUC. + + @param[in] dst The destination string + @param[in] src The source string + @param[in] n Number of chars to copy EXCLUDING the null terminator + (i.e. dst had better have room for n+1 chars) + + @return A pointer to dst */ +/*---------------------------------------------------------------------------*/ +char * +strstrip (char *dst, + const char *src, + int n) +{ + strncpy (dst, src, n); + *(dst + n) = '\0'; + + return dst; + +} /* strstrip () */ + +/*---------------------------------------------------------------------------*/ +/*!Translate logical to physical addresses for the loader + + Used only by the simulator loader to translate logical addresses into + physical. If loadcode() is called with valid @c virtphy_transl pointer to + a table of translations then translate() performs translation otherwise + physical address is equal to logical. + + @param[in] laddr Logical address + @param[in] breakpoint Unused + + @return The physical address */ +/*---------------------------------------------------------------------------*/ +static oraddr_t +translate (oraddr_t laddr, + int *breakpoint) +{ + int i; + + /* No translation (i.e. when loading kernel into simulator) */ + if (transl_table == 0) + { + return laddr; + } + + /* Try to find our translation in the table. */ + for (i = 0; i < (MEMORY_LEN / PAGE_SIZE) * 16; i += 16) + { + if ((laddr & ~(PAGE_SIZE - 1)) == eval_direct32 (transl_table + i, 0, 0)) + { + /* Page modified */ + set_direct32 (transl_table + i + 8, -2, 0, 0); + PRINTF ("found paddr=%" PRIx32 "\n", + eval_direct32 (transl_table + i + 4, 0, 0) | + (laddr & (PAGE_SIZE - 1))); + return (oraddr_t) eval_direct32 (transl_table + i + 4, 0, 0) | + (laddr & (oraddr_t) (PAGE_SIZE - 1)); + } + } + + /* Allocate new phy page for us. */ + for (i = 0; i < (MEMORY_LEN / PAGE_SIZE) * 16; i += 16) + { + if (eval_direct32 (transl_table + i + 8, 0, 0) == 0) + { + /* VPN */ + set_direct32 (transl_table + i, laddr & ~(PAGE_SIZE - 1), 0, 0); + /* PPN */ + set_direct32 (transl_table + i + 4, (i / 16) * PAGE_SIZE, 0, 0); + /* Page modified */ + set_direct32 (transl_table + i + 8, -2, 0, 0); + PRINTF ("newly allocated ppn=%" PRIx32 "\n", + eval_direct32 (transl_table + i + 4, 0, 0)); + PRINTF ("newly allocated .ppn=%" PRIxADDR "\n", transl_table + i + 4); + PRINTF ("newly allocated ofs=%" PRIxADDR "\n", + (laddr & (PAGE_SIZE - 1))); + PRINTF ("newly allocated paddr=%" PRIx32 "\n", + eval_direct32 (transl_table + i + 4, 0, + 0) | (laddr & (PAGE_SIZE - 1))); + return (oraddr_t) eval_direct32 (transl_table + i + 4, 0, 0) | + (laddr & (oraddr_t) (PAGE_SIZE - 1)); + } + } + + /* If we come this far then all phy memory is used and we can't find our + page nor allocate new page. */ + transl_error = 1; + PRINTF ("can't translate %" PRIxADDR "\n", laddr); + exit (1); + + return -1; + +} /* translate() */ + +#if IMM_STATS +static int +bits (uint32_t val) +{ + int i = 1; + if (!val) + return 0; + while (val != 0 && (int32_t) val != -1) + { + i++; + val = (int32_t) val >> 1; + } + return i; +} + +static void +check_insn (uint32_t insn) +{ + int insn_index = insn_decode (insn); + struct insn_op_struct *opd = op_start[insn_index]; + uint32_t data = 0; + int dis = 0; + const char *name; + if (!insn || insn_index < 0) + return; + name = insn_name (insn_index); + if (strcmp (name, "l.nop") == 0 || strcmp (name, "l.sys") == 0) + return; + + while (1) + { + uint32_t tmp = 0 unsigned int nbits = 0; + while (1) + { + tmp |= + ((insn >> (opd->type & OPTYPE_SHR)) & ((1 << opd->data) - 1)) << + nbits; + nbits += opd->data; + if (opd->type & OPTYPE_OP) + break; + opd++; + } + + /* Do we have to sign extend? */ + if (opd->type & OPTYPE_SIG) + { + int sbit = (opd->type & OPTYPE_SBIT) >> OPTYPE_SBIT_SHR; + if (tmp & (1 << sbit)) + tmp |= 0xFFFFFFFF << sbit; + } + if (opd->type & OPTYPE_DIS) + { + /* We have to read register later. */ + data += tmp; + dis = 1; + } + else + { + if (!(opd->type & OPTYPE_REG) || dis) + { + if (!dis) + data = tmp; + if (strcmp (name, "l.movhi") == 0) + { + movhi = data << 16; + } + else + { + data |= movhi; + //PRINTF ("%08x %s\n", data, name); + if (!(or32_opcodes[insn_index].flags & OR32_IF_DELAY)) + { + bcnt[bits (data)][0]++; + bsum[0]++; + } + else + { + if (strcmp (name, "l.bf") == 0 + || strcmp (name, "l.bnf") == 0) + { + bcnt[bits (data)][1]++; + bsum[1]++; + } + else + { + bcnt[bits (data)][2]++; + bsum[2]++; + } + } + } + } + data = 0; + dis = 0; + } + if (opd->type & OPTYPE_LAST) + { + return; + } + opd++; + } +} +#endif + +/*---------------------------------------------------------------------------*/ +/*!Add an instruction to the program + + @note insn must be in big endian format + + @param[in] address The address to use + @param[in] insn The instruction to add + @param[in] breakpoint Not used (it is passed to the translate() function, + which also does not use it. */ +/*---------------------------------------------------------------------------*/ +static void +addprogram (oraddr_t address, + uint32_t insn, + int *breakpoint) +{ + int vaddr = (!runtime.sim.filename) ? translate (address, breakpoint) : + translate (freemem, breakpoint); + + /* We can't have set_program32 functions since it is not gauranteed that the + section we're loading is aligned on a 4-byte boundry */ + set_program8 (vaddr, (insn >> 24) & 0xff); + set_program8 (vaddr + 1, (insn >> 16) & 0xff); + set_program8 (vaddr + 2, (insn >> 8) & 0xff); + set_program8 (vaddr + 3, insn & 0xff); + +#if IMM_STATS + check_insn (insn); +#endif + + if (runtime.sim.filename) + { + freemem += insn_len (insn_decode (insn)); + } +} /* addprogram () */ + + +/*---------------------------------------------------------------------------*/ +/*!Load big-endian COFF file + + @param[in] filename File to load + @param[in] sections Number of sections in file */ +/*---------------------------------------------------------------------------*/ +static void +readfile_coff (char *filename, + short sections) +{ + FILE *inputfs; + char inputbuf[4]; + uint32_t insn; + int32_t sectsize; + COFF_AOUTHDR coffaouthdr; + struct COFF_scnhdr coffscnhdr; + int len; + int firstthree = 0; + int breakpoint = 0; + + if (!(inputfs = fopen (filename, "r"))) + { + perror ("readfile_coff"); + exit (1); + } + + if (fseek (inputfs, sizeof (struct COFF_filehdr), SEEK_SET) == -1) + { + fclose (inputfs); + perror ("readfile_coff"); + exit (1); + } + + if (fread (&coffaouthdr, sizeof (coffaouthdr), 1, inputfs) != 1) + { + fclose (inputfs); + perror ("readfile_coff"); + exit (1); + } + + while (sections--) + { + uint32_t scnhdr_pos = + sizeof (struct COFF_filehdr) + sizeof (coffaouthdr) + + sizeof (struct COFF_scnhdr) * firstthree; + if (fseek (inputfs, scnhdr_pos, SEEK_SET) == -1) + { + fclose (inputfs); + perror ("readfile_coff"); + exit (1); + } + if (fread (&coffscnhdr, sizeof (struct COFF_scnhdr), 1, inputfs) != 1) + { + fclose (inputfs); + perror ("readfile_coff"); + exit (1); + } + PRINTF ("Section: %s,", coffscnhdr.s_name); + PRINTF (" paddr: 0x%.8lx,", COFF_LONG_H (coffscnhdr.s_paddr)); + PRINTF (" vaddr: 0x%.8lx,", COFF_LONG_H (coffscnhdr.s_vaddr)); + PRINTF (" size: 0x%.8lx,", COFF_LONG_H (coffscnhdr.s_size)); + PRINTF (" scnptr: 0x%.8lx\n", COFF_LONG_H (coffscnhdr.s_scnptr)); + + sectsize = COFF_LONG_H (coffscnhdr.s_size); + ++firstthree; + + /* loading section */ + freemem = COFF_LONG_H (coffscnhdr.s_paddr); + if (fseek (inputfs, COFF_LONG_H (coffscnhdr.s_scnptr), SEEK_SET) == -1) + { + fclose (inputfs); + perror ("readfile_coff"); + exit (1); + } + while (sectsize > 0 + && (len = fread (&inputbuf, sizeof (inputbuf), 1, inputfs))) + { + insn = COFF_LONG_H (inputbuf); + len = insn_len (insn_decode (insn)); + if (len == 2) + { + fseek (inputfs, -2, SEEK_CUR); + } + + addprogram (freemem, insn, &breakpoint); + sectsize -= len; + } + } + if (firstthree < 3) + { + PRINTF ("One or more missing sections. At least"); + PRINTF (" three sections expected (.text, .data, .bss).\n"); + exit (1); + } + if (firstthree > 3) + { + PRINTF ("Warning: one or more extra sections. These"); + PRINTF (" sections were handled as .data sections.\n"); + } + + fclose (inputfs); + PRINTF ("Finished loading COFF.\n"); + return; + +} /* readfile_coff () */ + + +/* Load symbols from big-endian COFF file. */ + +static void +readsyms_coff (char *filename, uint32_t symptr, uint32_t syms) +{ + FILE *inputfs; + struct COFF_syment coffsymhdr; + int count = 0; + uint32_t nsyms = syms; + if (!(inputfs = fopen (filename, "r"))) + { + perror ("readsyms_coff"); + exit (1); + } + + if (fseek (inputfs, symptr, SEEK_SET) == -1) + { + fclose (inputfs); + perror ("readsyms_coff"); + exit (1); + } + + while (syms--) + { + int i, n; + if (fread (&coffsymhdr, COFF_SYMESZ, 1, inputfs) != 1) + { + fclose (inputfs); + perror ("readsyms_coff"); + exit (1); + } + + n = (unsigned char) coffsymhdr.e_numaux[0]; + + /* check whether this symbol belongs to a section and is external + symbol; ignore all others */ + if (COFF_SHORT_H (coffsymhdr.e_scnum) >= 0 + && coffsymhdr.e_sclass[0] == C_EXT) + { + if (*((uint32_t *) coffsymhdr.e.e.e_zeroes)) + { + if (strlen (coffsymhdr.e.e_name) + && strlen (coffsymhdr.e.e_name) < 9) + add_label (COFF_LONG_H (coffsymhdr.e_value), + coffsymhdr.e.e_name); + } + else + { + uint32_t fpos = ftell (inputfs); + + if (fseek + (inputfs, + symptr + nsyms * COFF_SYMESZ + + COFF_LONG_H (coffsymhdr.e.e.e_offset), SEEK_SET) == 0) + { + char tmp[33], *s = &tmp[0]; + while (s != &tmp[32]) + if ((*(s++) = fgetc (inputfs)) == 0) + break; + tmp[32] = 0; + add_label (COFF_LONG_H (coffsymhdr.e_value), &tmp[0]); + } + fseek (inputfs, fpos, SEEK_SET); + } + } + + for (i = 0; i < n; i++) + if (fread (&coffsymhdr, COFF_SYMESZ, 1, inputfs) != 1) + { + fclose (inputfs); + perror ("readsyms_coff3"); + exit (1); + } + syms -= n; + count += n; + } + + fclose (inputfs); + PRINTF ("Finished loading symbols.\n"); + return; +} + +static void +readfile_elf (char *filename) +{ + + FILE *inputfs; + struct elf32_hdr elfhdr; + struct elf32_phdr *elf_phdata = NULL; + struct elf32_shdr *elf_spnt, *elf_shdata; + struct elf32_sym *sym_tbl = (struct elf32_sym *) 0; + uint32_t syms = 0; + char *str_tbl = (char *) 0; + char *s_str = (char *) 0; + int breakpoint = 0; + uint32_t inputbuf; + uint32_t padd; + uint32_t insn; + int i, j, sectsize, len; + + if (!(inputfs = fopen (filename, "r"))) + { + perror ("readfile_elf"); + exit (1); + } + + if (fread (&elfhdr, sizeof (elfhdr), 1, inputfs) != 1) + { + perror ("readfile_elf"); + exit (1); + } + + if ((elf_shdata = + (struct elf32_shdr *) malloc (ELF_SHORT_H (elfhdr.e_shentsize) * + ELF_SHORT_H (elfhdr.e_shnum))) == NULL) + { + perror ("readfile_elf"); + exit (1); + } + + if (fseek (inputfs, ELF_LONG_H (elfhdr.e_shoff), SEEK_SET) != 0) + { + perror ("readfile_elf"); + exit (1); + } + + if (fread + (elf_shdata, + ELF_SHORT_H (elfhdr.e_shentsize) * ELF_SHORT_H (elfhdr.e_shnum), 1, + inputfs) != 1) + { + perror ("readfile_elf"); + exit (1); + } + + if (ELF_LONG_H (elfhdr.e_phoff)) + { + if ((elf_phdata = + (struct elf32_phdr *) malloc (ELF_SHORT_H (elfhdr.e_phnum) * + ELF_SHORT_H (elfhdr.e_phentsize))) == + NULL) + { + perror ("readfile_elf"); + exit (1); + } + + if (fseek (inputfs, ELF_LONG_H (elfhdr.e_phoff), SEEK_SET) != 0) + { + perror ("readfile_elf"); + exit (1); + } + + if (fread + (elf_phdata, + ELF_SHORT_H (elfhdr.e_phnum) * ELF_SHORT_H (elfhdr.e_phentsize), + 1, inputfs) != 1) + { + perror ("readfile_elf"); + exit (1); + } + } + + for (i = 0, elf_spnt = elf_shdata; i < ELF_SHORT_H (elfhdr.e_shnum); + i++, elf_spnt++) + { + + if (ELF_LONG_H (elf_spnt->sh_type) == SHT_STRTAB) + { + if (NULL != str_tbl) + { + free (str_tbl); + } + + if ((str_tbl = + (char *) malloc (ELF_LONG_H (elf_spnt->sh_size))) == NULL) + { + perror ("readfile_elf"); + exit (1); + } + + if (fseek (inputfs, ELF_LONG_H (elf_spnt->sh_offset), SEEK_SET) != + 0) + { + perror ("readfile_elf"); + exit (1); + } + + if (fread (str_tbl, ELF_LONG_H (elf_spnt->sh_size), 1, inputfs) != + 1) + { + perror ("readfile_elf"); + exit (1); + } + } + else if (ELF_LONG_H (elf_spnt->sh_type) == SHT_SYMTAB) + { + + if (NULL != sym_tbl) + { + free (sym_tbl); + } + + if ((sym_tbl = + (struct elf32_sym *) malloc (ELF_LONG_H (elf_spnt->sh_size))) + == NULL) + { + perror ("readfile_elf"); + exit (1); + } + + if (fseek (inputfs, ELF_LONG_H (elf_spnt->sh_offset), SEEK_SET) != + 0) + { + perror ("readfile_elf"); + exit (1); + } + + if (fread (sym_tbl, ELF_LONG_H (elf_spnt->sh_size), 1, inputfs) != + 1) + { + perror ("readfile_elf"); + exit (1); + } + + syms = + ELF_LONG_H (elf_spnt->sh_size) / + ELF_LONG_H (elf_spnt->sh_entsize); + } + } + + if (ELF_SHORT_H (elfhdr.e_shstrndx) != SHN_UNDEF) + { + elf_spnt = &elf_shdata[ELF_SHORT_H (elfhdr.e_shstrndx)]; + + if ((s_str = (char *) malloc (ELF_LONG_H (elf_spnt->sh_size))) == NULL) + { + perror ("readfile_elf"); + exit (1); + } + + if (fseek (inputfs, ELF_LONG_H (elf_spnt->sh_offset), SEEK_SET) != 0) + { + perror ("readfile_elf"); + exit (1); + } + + if (fread (s_str, ELF_LONG_H (elf_spnt->sh_size), 1, inputfs) != 1) + { + perror ("readfile_elf"); + exit (1); + } + } + + + for (i = 0, elf_spnt = elf_shdata; i < ELF_SHORT_H (elfhdr.e_shnum); + i++, elf_spnt++) + { + + if ((ELF_LONG_H (elf_spnt->sh_type) & SHT_PROGBITS) + && (ELF_LONG_H (elf_spnt->sh_flags) & SHF_ALLOC)) + { + + padd = ELF_LONG_H (elf_spnt->sh_addr); + for (j = 0; j < ELF_SHORT_H (elfhdr.e_phnum); j++) + { + if (ELF_LONG_H (elf_phdata[j].p_offset) && + ELF_LONG_H (elf_phdata[j].p_offset) <= + ELF_LONG_H (elf_spnt->sh_offset) + && (ELF_LONG_H (elf_phdata[j].p_offset) + + ELF_LONG_H (elf_phdata[j].p_memsz)) > + ELF_LONG_H (elf_spnt->sh_offset)) + padd = + ELF_LONG_H (elf_phdata[j].p_paddr) + + ELF_LONG_H (elf_spnt->sh_offset) - + ELF_LONG_H (elf_phdata[j].p_offset); + } + + + + if (ELF_LONG_H (elf_spnt->sh_name) && s_str) + PRINTF ("Section: %s,", &s_str[ELF_LONG_H (elf_spnt->sh_name)]); + else + PRINTF ("Section: noname,"); + PRINTF (" vaddr: 0x%.8lx,", ELF_LONG_H (elf_spnt->sh_addr)); + PRINTF (" paddr: 0x%" PRIx32, padd); + PRINTF (" offset: 0x%.8lx,", ELF_LONG_H (elf_spnt->sh_offset)); + PRINTF (" size: 0x%.8lx\n", ELF_LONG_H (elf_spnt->sh_size)); + + freemem = padd; + sectsize = ELF_LONG_H (elf_spnt->sh_size); + + if (fseek (inputfs, ELF_LONG_H (elf_spnt->sh_offset), SEEK_SET) != + 0) + { + perror ("readfile_elf"); + free (elf_phdata); + exit (1); + } + + while (sectsize > 0 + && (len = fread (&inputbuf, sizeof (inputbuf), 1, inputfs))) + { + insn = ELF_LONG_H (inputbuf); + addprogram (freemem, insn, &breakpoint); + sectsize -= 4; + } + } + } + + if (str_tbl) + { + i = 0; + while (syms--) + { + if (sym_tbl[i].st_name && sym_tbl[i].st_info + && ELF_SHORT_H (sym_tbl[i].st_shndx) < 0x8000) + { + add_label (ELF_LONG_H (sym_tbl[i].st_value), + &str_tbl[ELF_LONG_H (sym_tbl[i].st_name)]); + } + i++; + } + } + + if (NULL != str_tbl) + { + free (str_tbl); + } + + if (NULL != sym_tbl) + { + free (sym_tbl); + } + + free (s_str); + free (elf_phdata); + free (elf_shdata); + +} + +/* Identify file type and call appropriate readfile_X routine. It only +handles orX-coff-big executables at the moment. */ + +static void +identifyfile (char *filename) +{ + FILE *inputfs; + struct COFF_filehdr coffhdr; + struct elf32_hdr elfhdr; + + if (!(inputfs = fopen (filename, "r"))) + { + perror (filename); + fflush (stdout); + fflush (stderr); + exit (1); + } + + if (fread (&coffhdr, sizeof (coffhdr), 1, inputfs) == 1) + { + if (COFF_SHORT_H (coffhdr.f_magic) == 0x17a) + { + uint32_t opthdr_size; + PRINTF ("COFF magic: 0x%.4x\n", COFF_SHORT_H (coffhdr.f_magic)); + PRINTF ("COFF flags: 0x%.4x\n", COFF_SHORT_H (coffhdr.f_flags)); + PRINTF ("COFF symptr: 0x%.8lx\n", COFF_LONG_H (coffhdr.f_symptr)); + if ((COFF_SHORT_H (coffhdr.f_flags) & COFF_F_EXEC) != COFF_F_EXEC) + { + PRINTF ("This COFF is not an executable.\n"); + exit (1); + } + opthdr_size = COFF_SHORT_H (coffhdr.f_opthdr); + if (opthdr_size != sizeof (COFF_AOUTHDR)) + { + PRINTF ("COFF optional header is missing or not recognized.\n"); + PRINTF ("COFF f_opthdr: 0x%" PRIx32 "\n", opthdr_size); + exit (1); + } + fclose (inputfs); + readfile_coff (filename, COFF_SHORT_H (coffhdr.f_nscns)); + readsyms_coff (filename, COFF_LONG_H (coffhdr.f_symptr), + COFF_LONG_H (coffhdr.f_nsyms)); + return; + } + else + { + PRINTF ("Not COFF file format\n"); + fseek (inputfs, 0, SEEK_SET); + } + } + if (fread (&elfhdr, sizeof (elfhdr), 1, inputfs) == 1) + { + if (elfhdr.e_ident[0] == 0x7f && elfhdr.e_ident[1] == 0x45 + && elfhdr.e_ident[2] == 0x4c && elfhdr.e_ident[3] == 0x46) + { + PRINTF ("ELF type: 0x%.4x\n", ELF_SHORT_H (elfhdr.e_type)); + PRINTF ("ELF machine: 0x%.4x\n", ELF_SHORT_H (elfhdr.e_machine)); + PRINTF ("ELF version: 0x%.8lx\n", ELF_LONG_H (elfhdr.e_version)); + PRINTF ("ELF sec = %d\n", ELF_SHORT_H (elfhdr.e_shnum)); + if (ELF_SHORT_H (elfhdr.e_type) != ET_EXEC) + { + PRINTF ("This ELF is not an executable.\n"); + exit (1); + } + fclose (inputfs); + readfile_elf (filename); + return; + } + else + { + PRINTF ("Not ELF file format.\n"); + fseek (inputfs, 0, SEEK_SET); + } + } + + perror ("identifyfile2"); + fclose (inputfs); + + return; +} + + +/*---------------------------------------------------------------------------*/ +/*!Load file to memory + + Loads file to memory starting at address startaddr and returns freemem. + + @param[in] filename File to load + @param[in] startaddr Start address at which to load + @param[in] virtphy_transl Virtual to physical transation table if + required. Only used for microkernel simulation, + and not used in Ork1sim at present (set to NULL) + + @return zero on success, negative on failure. */ +/*---------------------------------------------------------------------------*/ +uint32_t +loadcode (char *filename, oraddr_t startaddr, oraddr_t virtphy_transl) +{ + int breakpoint = 0; + + transl_error = 0; + transl_table = virtphy_transl; + freemem = startaddr; + PRINTF ("loadcode: filename %s startaddr=%" PRIxADDR " virtphy_transl=%" + PRIxADDR "\n", filename, startaddr, virtphy_transl); + identifyfile (filename); + +#if IMM_STATS + { + int i = 0, a = 0, b = 0, c = 0; + PRINTF ("index:arith/branch/jump\n"); + for (i = 0; i < 33; i++) + PRINTF ("%2i:\t%3.0f%% / %3.0f%%/ %3.0f%%\t%5i / %5i / %5i\n", i, + 100. * (a += bcnt[i][0]) / bsum[0], 100. * (b += + bcnt[i][1]) / + bsum[1], 100. * (c += + bcnt[i][2]) / bsum[2], bcnt[i][0], + bcnt[i][1], bcnt[i][2]); + PRINTF ("\nsum %i %i %i\n", bsum[0], bsum[1], bsum[2]); + } +#endif + + if (transl_error) + return -1; + else + return translate (freemem, &breakpoint); + +} Index: common/trace.c =================================================================== --- common/trace.c (nonexistent) +++ common/trace.c (revision 1765) @@ -0,0 +1,66 @@ +/* trace.c -- Simulator breakpoints + + Copyright (C) 1999 Damjan Lampret, lampret@opencores.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" + +/* Package includes */ +#include "trace.h" +#include "sim-config.h" +#include "abstract.h" +#include "labels.h" + + +/*---------------------------------------------------------------------------*/ +/*!Set instruction execution breakpoint + + @param[in] addr The address for the breakpoint */ +/*---------------------------------------------------------------------------*/ +void +set_insnbrkpoint (oraddr_t addr) +{ + addr &= ~ADDR_C (3); /* 32-bit aligned */ + + if (!verify_memoryarea (addr)) + { + PRINTF + ("WARNING: This breakpoint is out of the simulated memory range.\n"); + } + + if (has_breakpoint (addr)) + { + remove_breakpoint (addr); + PRINTF ("\nBreakpoint at 0x%" PRIxADDR " cleared.\n", addr); + } + else + { + add_breakpoint (addr); + PRINTF ("\nBreakpoint at 0x%" PRIxADDR " set.\n", addr); + } + + return; + +} /* set_insnbrkpoint () */ Index: common/parse.h =================================================================== --- common/parse.h (nonexistent) +++ common/parse.h (revision 1765) @@ -0,0 +1,41 @@ +/* parse.h -- Header file for parse.c + + Copyright (C) 1999 Damjan Lampret, lampret@opencores.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 . */ + +/* Here we define some often used caharcters in assembly files. This wil + probably go into architecture dependent directory. */ + + +#ifndef PARSE__H +#define PARSE__H + +/* Package includes */ +#include "sim-config.h" + +/* Function prototypes for external use */ +char *strstrip (char *dst, + const char *src, + int n); +uint32_t loadcode (char *filename, + oraddr_t startaddr, + oraddr_t virtphy_transl); + +#endif /* PARSE__H */ Index: common/Makefile.in =================================================================== --- common/Makefile.in (nonexistent) +++ common/Makefile.in (revision 1765) @@ -0,0 +1,487 @@ +# 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 cpu architecture independent 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 . + +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@ +subdir = cpu/common +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) +libcommon_la_LIBADD = +am_libcommon_la_OBJECTS = abstract.lo parse.lo stats.lo trace.lo \ + labels.lo +libcommon_la_OBJECTS = $(am_libcommon_la_OBJECTS) +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 = $(libcommon_la_SOURCES) +DIST_SOURCES = $(libcommon_la_SOURCES) +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@ +noinst_LTLIBRARIES = libcommon.la +libcommon_la_SOURCES = abstract.c \ + parse.c \ + stats.c \ + trace.c \ + labels.c \ + abstract.h \ + coff.h \ + elf.h \ + execute.h \ + labels.h \ + parse.h \ + stats.h \ + trace.h + +all: 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/common/Makefile'; \ + cd $(top_srcdir) && \ + $(AUTOMAKE) --gnu cpu/common/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 +libcommon.la: $(libcommon_la_OBJECTS) $(libcommon_la_DEPENDENCIES) + $(LINK) $(libcommon_la_OBJECTS) $(libcommon_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/abstract.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/labels.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/parse.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stats.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/trace.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 $@ $< + +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: check-am +all-am: Makefile $(LTLIBRARIES) +installdirs: +install: 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: + +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." +clean: clean-am + +clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ + 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 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 + +# 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: Index: common/labels.c =================================================================== --- common/labels.c (nonexistent) +++ common/labels.c (revision 1765) @@ -0,0 +1,187 @@ +/* abstract.c -- Abstract entities, handling labels + + Copyright (C) 2001 Marko Mlinar, markom@opencores.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. */ + +/* Abstract memory and routines that go with this. I need to add all sorts of + other abstract entities. Currently we have only memory. */ + + +/* Autoconf and/or portability configuration */ +#include "config.h" +#include "port.h" + +/* System includes */ +#include + +/* Package includes */ +#include "labels.h" + +#define LABELS_HASH_SIZE 119 + +/* Globally visible list of breakpoints */ +struct breakpoint_entry *breakpoints; + +/* Local list of labels (symbols) */ +static struct label_entry *label_hash[LABELS_HASH_SIZE]; + + +void +init_labels () +{ + int i; + for (i = 0; i < LABELS_HASH_SIZE; i++) + label_hash[i] = NULL; +} + +void +add_label (oraddr_t addr, char *name) +{ + struct label_entry **tmp; + tmp = &(label_hash[addr % LABELS_HASH_SIZE]); + for (; *tmp; tmp = &((*tmp)->next)); + *tmp = malloc (sizeof (**tmp)); + (*tmp)->name = malloc (strlen (name) + 1); + (*tmp)->addr = addr; + strcpy ((*tmp)->name, name); + (*tmp)->next = NULL; +} + +struct label_entry * +get_label (oraddr_t addr) +{ + struct label_entry *tmp = label_hash[addr % LABELS_HASH_SIZE]; + while (tmp) + { + if (tmp->addr == addr) + return tmp; + tmp = tmp->next; + } + return NULL; +} + +struct label_entry * +find_label (char *name) +{ + int i; + for (i = 0; i < LABELS_HASH_SIZE; i++) + { + struct label_entry *tmp = label_hash[i % LABELS_HASH_SIZE]; + while (tmp) + { + if (strcmp (tmp->name, name) == 0) + return tmp; + tmp = tmp->next; + } + } + return NULL; +} + +/* Searches mem array for a particular label and returns label's address. + If label does not exist, returns 0. */ +oraddr_t +eval_label (char *name) +{ + struct label_entry *le; + char *plus; + char *minus; + int positive_offset = 0; + int negative_offset = 0; + + if ((plus = strchr (name, '+'))) + { + *plus = '\0'; + positive_offset = atoi (++plus); + } + + if ((minus = strchr (name, '-'))) + { + *minus = '\0'; + negative_offset = atoi (++minus); + } + le = find_label (name); + if (!le) + return 0; + + return le->addr + positive_offset - negative_offset; +} + +void +init_breakpoints () +{ + breakpoints = 0; +} + +void +add_breakpoint (oraddr_t addr) +{ + struct breakpoint_entry *tmp; + tmp = (struct breakpoint_entry *) malloc (sizeof (struct breakpoint_entry)); + tmp->next = breakpoints; + tmp->addr = addr; + breakpoints = tmp; +} + +void +remove_breakpoint (oraddr_t addr) +{ + struct breakpoint_entry **tmp = &breakpoints; + while (*tmp) + { + if ((*tmp)->addr == addr) + { + struct breakpoint_entry *t = *tmp; + (*tmp) = t->next; + free (t); + } + else + tmp = &((*tmp)->next); + } +} + +void +print_breakpoints () +{ + struct breakpoint_entry **tmp = &breakpoints; + int i = 1; + printf ("---[breakpoints]------------------\n"); + while (*tmp) + { + printf ("Breakpoint %i at 0x%" PRIxADDR "\n", i, (*tmp)->addr); + tmp = &((*tmp)->next); + } + printf ("---[breakpoints end]--------------\n"); +} + +int +has_breakpoint (oraddr_t addr) +{ + struct breakpoint_entry *tmp = breakpoints; + while (tmp) + { + if (tmp->addr == addr) + return 1; + tmp = tmp->next; + } + return 0; +}
common/labels.c Property changes : Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: common/trace.h =================================================================== --- common/trace.h (nonexistent) +++ common/trace.h (revision 1765) @@ -0,0 +1,36 @@ +/* trace.h -- Simulator breakpoints header + + Copyright (C) 1999 Damjan Lampret, lampret@opencores.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. */ + + +#ifndef TRACE__H +#define TRACE__H + +/* Package includes */ +#include "sim-config.h" + +/* Function prototype for external use */ +void set_insnbrkpoint (oraddr_t addr); + +#endif /* TRACE__H */ Index: common/labels.h =================================================================== --- common/labels.h (nonexistent) +++ common/labels.h (revision 1765) @@ -0,0 +1,64 @@ +/* labels.h -- Abstract entities header file handling labels + + Copyright (C) 2001 Marko Mlinar, markom@opencores.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. */ + + +#ifndef LABELS__H_ +#define LABELS__H_ + +/* Package include */ +#include "abstract.h" + +/*! Structure for holding one label per particular memory location */ +struct label_entry +{ + char *name; + oraddr_t addr; + struct label_entry *next; +}; + +/*! Structure repesenting a breakpoint */ +struct breakpoint_entry +{ + oraddr_t addr; + struct breakpoint_entry *next; +}; + +/* Globally visible variables */ +extern struct breakpoint_entry *breakpoints; + +/* Function prototypes for external use */ +extern void init_labels (); +extern void add_label (oraddr_t addr, + char *name); +extern struct label_entry *get_label (oraddr_t addr); +extern struct label_entry *find_label (char *name); +extern oraddr_t eval_label (char *name); +extern void add_breakpoint (oraddr_t addr); +extern void remove_breakpoint (oraddr_t addr); +extern void print_breakpoints (); +extern int has_breakpoint (oraddr_t addr); +extern void init_breakpoints (); + +#endif /* LABELS__H_ */
common/labels.h Property changes : Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: common/abstract.h =================================================================== --- common/abstract.h (nonexistent) +++ common/abstract.h (revision 1765) @@ -0,0 +1,189 @@ +/* abstract.h -- Abstract entities header file + + 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 . */ + +/* This program is commented throughout in a fashion suitable for processing + with Doxygen. */ + + +#ifndef ABSTRACT__H +#define ABSTRACT__H + +/* Autoconf and/or portability configuration */ +#include "port.h" + +/* System includes */ +#include + +/* Package includes */ +#include "arch.h" + +#define DEFAULT_MEMORY_START 0 +#define DEFAULT_MEMORY_LEN 0x800000 +#define STACK_SIZE 20 +#define LABELNAME_LEN 50 +#define INSNAME_LEN 15 +#define OPERANDNAME_LEN 50 +#define MAX_OPERANDS 5 + +#define OP_MEM_ACCESS 0x80000000 + +/* Cache tag types. */ +#define CT_NONE 0 +#define CT_VIRTUAL 1 +#define CT_PHYSICAL 2 + +/* History of execution */ +#define HISTEXEC_LEN 200 + +/* Added by MM */ +#ifndef LONGEST +#define LONGEST long long +#endif /* LONGEST */ + +#ifndef ULONGEST +#define ULONGEST unsigned long long +#endif /* ULONGEST */ + +/* Endianness convenience macros */ +#define LE16(x) bswap_16(x) + +/*! Instruction queue */ +struct iqueue_entry +{ + int insn_index; + uint32_t insn; + oraddr_t insn_addr; +}; + +/*! All the memory operations possible */ +struct mem_ops +{ + + /* Read functions */ + uint32_t (*readfunc32) (oraddr_t, void *); + uint16_t (*readfunc16) (oraddr_t, void *); + uint8_t (*readfunc8) (oraddr_t, void *); + + /* Read functions' data */ + void *read_dat8; + void *read_dat16; + void *read_dat32; + + /* Write functions */ + void (*writefunc32) (oraddr_t, uint32_t, void *); + void (*writefunc16) (oraddr_t, uint16_t, void *); + void (*writefunc8) (oraddr_t, uint8_t, void *); + + /* Write functions' data */ + void *write_dat8; + void *write_dat16; + void *write_dat32; + + /* Program load function. If you have unwritteable memory but you would like + * it if a program would be loaded here, make sure to set this. If this is + * not set, then writefunc8 will be called to load the program */ + void (*writeprog32) (oraddr_t, uint32_t, void *); + void (*writeprog8) (oraddr_t, uint8_t, void *); + + /* Program load functions' data */ + void *writeprog32_dat; + void *writeprog8_dat; + + /* Read/Write delays */ + int delayr; + int delayw; + + /* Name of log file */ + const char *log; +}; + +/*! Memory regions assigned to devices */ +struct dev_memarea +{ + struct dev_memarea *next; + oraddr_t addr_mask; + oraddr_t addr_compare; + uint32_t size; + oraddr_t size_mask; /* Addr mask, calculated out of size */ + int valid; /* Mirrors memory controler valid bit */ + FILE *log; /* log file (NULL if no logging) */ + struct mem_ops ops; + struct mem_ops direct_ops; +}; + +/* Externally visible data */ +extern struct dev_memarea *cur_area; +extern int data_ci; +extern int insn_ci; +extern struct hist_exec *hist_exec_tail; + +/* Function prototypes for external use */ +extern uint32_t eval_mem32 (oraddr_t memaddr, int *); +extern uint16_t eval_mem16 (oraddr_t memaddr, int *); +extern uint8_t eval_mem8 (oraddr_t memaddr, int *); +extern void set_mem32 (oraddr_t memaddr, uint32_t value, int *); +extern void set_mem16 (oraddr_t memaddr, uint16_t value, int *); +extern void set_mem8 (oraddr_t memaddr, uint8_t value, int *); +extern void dump_memory (oraddr_t from, + oraddr_t to); +extern void disassemble_memory (oraddr_t from, + oraddr_t to, + int nl); +extern uint32_t evalsim_mem32 (oraddr_t, oraddr_t); +extern uint16_t evalsim_mem16 (oraddr_t, oraddr_t); +extern uint8_t evalsim_mem8 (oraddr_t, oraddr_t); +extern void setsim_mem32 (oraddr_t, oraddr_t, uint32_t); +extern void setsim_mem16 (oraddr_t, oraddr_t, uint16_t); +extern void setsim_mem8 (oraddr_t, oraddr_t, uint8_t); +extern void done_memory_table (); +extern void memory_table_status (void); +extern struct dev_memarea *reg_mem_area (oraddr_t addr, + uint32_t size, + unsigned mc_dev, + struct mem_ops *ops); +extern void adjust_rw_delay (struct dev_memarea *mem, + int delayr, + int delayw); +extern void set_mem_valid (struct dev_memarea *mem, + int valid); +extern struct dev_memarea *verify_memoryarea (oraddr_t addr); +extern char *generate_time_pretty (char *dest, + long time_ps); +extern uint32_t eval_insn (oraddr_t, int *); +extern uint32_t eval_direct32 (oraddr_t addr, + int through_mmu, + int through_dc); +extern uint16_t eval_direct16 (oraddr_t memaddr, + int through_mmu, + int through_dc); +extern uint8_t eval_direct8 (oraddr_t memaddr, + int through_mmu, + int through_dc); +extern void set_direct8 (oraddr_t, uint8_t, int, int); +extern void set_direct16 (oraddr_t, uint16_t, int, int); +extern void set_direct32 (oraddr_t, uint32_t, int, int); +extern void set_program32 (oraddr_t memaddr, + uint32_t value); +extern void set_program8 (oraddr_t memaddr, + uint8_t value); + +#endif /* ABSTRACT__H */ Index: common/Makefile.am =================================================================== --- common/Makefile.am (nonexistent) +++ common/Makefile.am (revision 1765) @@ -0,0 +1,36 @@ +# Makefile -- Makefile for cpu architecture independent 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 . + +noinst_LTLIBRARIES = libcommon.la +libcommon_la_SOURCES = abstract.c \ + parse.c \ + stats.c \ + trace.c \ + labels.c \ + abstract.h \ + coff.h \ + elf.h \ + execute.h \ + labels.h \ + parse.h \ + stats.h \ + trace.h Index: common/elf.h =================================================================== --- common/elf.h (nonexistent) +++ common/elf.h (revision 1765) @@ -0,0 +1,447 @@ +#ifndef _LINUX_ELF_H +#define _LINUX_ELF_H + +#if HAVE_CONFIG_H +#include +#endif + +#ifdef WORDS_BIGENDIAN +#define ELF_SHORT_H +#define ELF_LONG_H +#else +/* Load a short int from the following tables with big-endian formats */ +#define ELF_SHORT_H(ps) ((((unsigned short)(ps) >> 8) & 0xff) |\ + (((unsigned short)(ps) << 8) & 0xff00)) + +/* Load a long int from the following tables with big-endian formats */ +#define ELF_LONG_H(ps) ((((unsigned long)(ps) >> 24) & 0xff) |\ + (((unsigned long)(ps) >> 8) & 0xff00)|\ + (((unsigned long)(ps) << 8) & 0xff0000)|\ + (((unsigned long)(ps) << 24) & 0xff000000)) +#endif + +#ifdef OR32_TYPES +typedef uint32_t Elf32_Addr; +typedef uint16_t Elf32_Half; +typedef uint32_t Elf32_Off; +typedef int32_t Elf32_Sword; +typedef uint32_t Elf32_Word; +#else +typedef unsigned long Elf32_Addr; +typedef unsigned short Elf32_Half; +typedef unsigned long Elf32_Off; +typedef long Elf32_Sword; +typedef unsigned long Elf32_Word; +#endif + +/* These constants are for the segment types stored in the image headers */ +#define PT_NULL 0 +#define PT_LOAD 1 +#define PT_DYNAMIC 2 +#define PT_INTERP 3 +#define PT_NOTE 4 +#define PT_SHLIB 5 +#define PT_PHDR 6 +#define PT_LOPROC 0x70000000 +#define PT_HIPROC 0x7fffffff + +/* These constants define the different elf file types */ +#define ET_NONE 0 +#define ET_REL 1 +#define ET_EXEC 2 +#define ET_DYN 3 +#define ET_CORE 4 +#define ET_LOPROC 5 +#define ET_HIPROC 6 + +/* These constants define the various ELF target machines */ +#define EM_NONE 0 +#define EM_M32 1 +#define EM_SPARC 2 +#define EM_386 3 +#define EM_68K 4 +#define EM_88K 5 +#define EM_486 6 /* Perhaps disused */ +#define EM_860 7 + +#define EM_MIPS 8 /* MIPS R3000 (officially, big-endian only) */ + +#define EM_MIPS_RS4_BE 10 /* MIPS R4000 big-endian */ + +#define EM_SPARC64 11 /* SPARC v9 (not official) 64-bit */ + +#define EM_PARISC 15 /* HPPA */ + +#define EM_SPARC32PLUS 18 /* Sun's "v8plus" */ + +#define EM_PPC 20 /* PowerPC */ + +/* + * This is an interim value that we will use until the committee comes + * up with a final number. + */ +#define EM_ALPHA 0x9026 + + +/* This is the info that is needed to parse the dynamic section of the file */ +#define DT_NULL 0 +#define DT_NEEDED 1 +#define DT_PLTRELSZ 2 +#define DT_PLTGOT 3 +#define DT_HASH 4 +#define DT_STRTAB 5 +#define DT_SYMTAB 6 +#define DT_RELA 7 +#define DT_RELASZ 8 +#define DT_RELAENT 9 +#define DT_STRSZ 10 +#define DT_SYMENT 11 +#define DT_INIT 12 +#define DT_FINI 13 +#define DT_SONAME 14 +#define DT_RPATH 15 +#define DT_SYMBOLIC 16 +#define DT_REL 17 +#define DT_RELSZ 18 +#define DT_RELENT 19 +#define DT_PLTREL 20 +#define DT_DEBUG 21 +#define DT_TEXTREL 22 +#define DT_JMPREL 23 +#define DT_LOPROC 0x70000000 +#define DT_HIPROC 0x7fffffff + +/* This info is needed when parsing the symbol table */ +#define STB_LOCAL 0 +#define STB_GLOBAL 1 +#define STB_WEAK 2 + +#define STT_NOTYPE 0 +#define STT_OBJECT 1 +#define STT_FUNC 2 +#define STT_SECTION 3 +#define STT_FILE 4 + +#define ELF32_ST_BIND(x) ((x) >> 4) +#define ELF32_ST_TYPE(x) (((unsigned int) x) & 0xf) + +/* Symbolic values for the entries in the auxiliary table + put on the initial stack */ +#define AT_NULL 0 /* end of vector */ +#define AT_IGNORE 1 /* entry should be ignored */ +#define AT_EXECFD 2 /* file descriptor of program */ +#define AT_PHDR 3 /* program headers for program */ +#define AT_PHENT 4 /* size of program header entry */ +#define AT_PHNUM 5 /* number of program headers */ +#define AT_PAGESZ 6 /* system page size */ +#define AT_BASE 7 /* base address of interpreter */ +#define AT_FLAGS 8 /* flags */ +#define AT_ENTRY 9 /* entry point of program */ +#define AT_NOTELF 10 /* program is not ELF */ +#define AT_UID 11 /* real uid */ +#define AT_EUID 12 /* effective uid */ +#define AT_GID 13 /* real gid */ +#define AT_EGID 14 /* effective gid */ + + +typedef struct dynamic{ + Elf32_Sword d_tag; + union{ + Elf32_Sword d_val; + Elf32_Addr d_ptr; + } d_un; +} Elf32_Dyn; + +typedef struct { + unsigned long long d_tag; /* entry tag value */ + union { + unsigned long long d_val; + unsigned long long d_ptr; + } d_un; +} Elf64_Dyn; + +/* The following are used with relocations */ +#define ELF32_R_SYM(x) ((x) >> 8) +#define ELF32_R_TYPE(x) ((x) & 0xff) + +#define R_386_NONE 0 +#define R_386_32 1 +#define R_386_PC32 2 +#define R_386_GOT32 3 +#define R_386_PLT32 4 +#define R_386_COPY 5 +#define R_386_GLOB_DAT 6 +#define R_386_JMP_SLOT 7 +#define R_386_RELATIVE 8 +#define R_386_GOTOFF 9 +#define R_386_GOTPC 10 +#define R_386_NUM 11 + +#define R_68K_NONE 0 +#define R_68K_32 1 +#define R_68K_16 2 +#define R_68K_8 3 +#define R_68K_PC32 4 +#define R_68K_PC16 5 +#define R_68K_PC8 6 +#define R_68K_GOT32 7 +#define R_68K_GOT16 8 +#define R_68K_GOT8 9 +#define R_68K_GOT32O 10 +#define R_68K_GOT16O 11 +#define R_68K_GOT8O 12 +#define R_68K_PLT32 13 +#define R_68K_PLT16 14 +#define R_68K_PLT8 15 +#define R_68K_PLT32O 16 +#define R_68K_PLT16O 17 +#define R_68K_PLT8O 18 +#define R_68K_COPY 19 +#define R_68K_GLOB_DAT 20 +#define R_68K_JMP_SLOT 21 +#define R_68K_RELATIVE 22 + +typedef struct elf32_rel { + Elf32_Addr r_offset; + Elf32_Word r_info; +} Elf32_Rel; + +typedef struct elf64_rel { + unsigned long long r_offset; /* Location at which to apply the action */ + unsigned long long r_info; /* index and type of relocation */ +} Elf64_Rel; + +typedef struct elf32_rela{ + Elf32_Addr r_offset; + Elf32_Word r_info; + Elf32_Sword r_addend; +} Elf32_Rela; + +typedef struct elf64_rela { + unsigned long long r_offset; /* Location at which to apply the action */ + unsigned long long r_info; /* index and type of relocation */ + unsigned long long r_addend; /* Constant addend used to compute value */ +} Elf64_Rela; + +typedef struct elf32_sym{ + Elf32_Word st_name; + Elf32_Addr st_value; + Elf32_Word st_size; + unsigned char st_info; + unsigned char st_other; + Elf32_Half st_shndx; +} Elf32_Sym; + +typedef struct elf64_sym { + unsigned int st_name; /* Symbol name, index in string tbl */ + unsigned char st_info; /* Type and binding attributes */ + unsigned char st_other; /* No defined meaning, 0 */ + unsigned short st_shndx; /* Associated section index */ + unsigned long long st_value; /* Value of the symbol */ + unsigned long long st_size; /* Associated symbol size */ +} Elf64_Sym; + + +#define EI_NIDENT 16 + +typedef struct elf32_hdr{ + unsigned char e_ident[EI_NIDENT]; + Elf32_Half e_type; + Elf32_Half e_machine; + Elf32_Word e_version; + Elf32_Addr e_entry; /* Entry point */ + Elf32_Off e_phoff; + Elf32_Off e_shoff; + Elf32_Word e_flags; + Elf32_Half e_ehsize; + Elf32_Half e_phentsize; + Elf32_Half e_phnum; + Elf32_Half e_shentsize; + Elf32_Half e_shnum; + Elf32_Half e_shstrndx; +} Elf32_Ehdr; + +typedef struct elf64_hdr { + unsigned char e_ident[16]; /* ELF "magic number" */ + short int e_type; + short unsigned int e_machine; + int e_version; + unsigned long long e_entry; /* Entry point virtual address */ + unsigned long long e_phoff; /* Program header table file offset */ + unsigned long long e_shoff; /* Section header table file offset */ + int e_flags; + short int e_ehsize; + short int e_phentsize; + short int e_phnum; + short int e_shentsize; + short int e_shnum; + short int e_shstrndx; +} Elf64_Ehdr; + +/* These constants define the permissions on sections in the program + header, p_flags. */ +#define PF_R 0x4 +#define PF_W 0x2 +#define PF_X 0x1 + +typedef struct elf32_phdr{ + Elf32_Word p_type; + Elf32_Off p_offset; + Elf32_Addr p_vaddr; + Elf32_Addr p_paddr; + Elf32_Word p_filesz; + Elf32_Word p_memsz; + Elf32_Word p_flags; + Elf32_Word p_align; +} Elf32_Phdr; + +typedef struct elf64_phdr { + int p_type; + int p_flags; + unsigned long long p_offset; /* Segment file offset */ + unsigned long long p_vaddr; /* Segment virtual address */ + unsigned long long p_paddr; /* Segment physical address */ + unsigned long long p_filesz; /* Segment size in file */ + unsigned long long p_memsz; /* Segment size in memory */ + unsigned long long p_align; /* Segment alignment, file & memory */ +} Elf64_Phdr; + +/* sh_type */ +#define SHT_NULL 0 +#define SHT_PROGBITS 1 +#define SHT_SYMTAB 2 +#define SHT_STRTAB 3 +#define SHT_RELA 4 +#define SHT_HASH 5 +#define SHT_DYNAMIC 6 +#define SHT_NOTE 7 +#define SHT_NOBITS 8 +#define SHT_REL 9 +#define SHT_SHLIB 10 +#define SHT_DYNSYM 11 +#define SHT_NUM 12 +#define SHT_LOPROC 0x70000000 +#define SHT_HIPROC 0x7fffffff +#define SHT_LOUSER 0x80000000 +#define SHT_HIUSER 0xffffffff + +/* sh_flags */ +#define SHF_WRITE 0x1 +#define SHF_ALLOC 0x2 +#define SHF_EXECINSTR 0x4 +#define SHF_MASKPROC 0xf0000000 + +/* special section indexes */ +#define SHN_UNDEF 0 +#define SHN_LORESERVE 0xff00 +#define SHN_LOPROC 0xff00 +#define SHN_HIPROC 0xff1f +#define SHN_ABS 0xfff1 +#define SHN_COMMON 0xfff2 +#define SHN_HIRESERVE 0xffff + +typedef struct elf32_shdr { + Elf32_Word sh_name; + Elf32_Word sh_type; + Elf32_Word sh_flags; + Elf32_Addr sh_addr; + Elf32_Off sh_offset; + Elf32_Word sh_size; + Elf32_Word sh_link; + Elf32_Word sh_info; + Elf32_Word sh_addralign; + Elf32_Word sh_entsize; +} Elf32_Shdr; + +typedef struct elf64_shdr { + unsigned int sh_name; /* Section name, index in string tbl */ + unsigned int sh_type; /* Type of section */ + unsigned long long sh_flags; /* Miscellaneous section attributes */ + unsigned long long sh_addr; /* Section virtual addr at execution */ + unsigned long long sh_offset; /* Section file offset */ + unsigned long long sh_size; /* Size of section in bytes */ + unsigned int sh_link; /* Index of another section */ + unsigned int sh_info; /* Additional section information */ + unsigned long long sh_addralign; /* Section alignment */ + unsigned long long sh_entsize; /* Entry size if section holds table */ +} Elf64_Shdr; + +#define EI_MAG0 0 /* e_ident[] indexes */ +#define EI_MAG1 1 +#define EI_MAG2 2 +#define EI_MAG3 3 +#define EI_CLASS 4 +#define EI_DATA 5 +#define EI_VERSION 6 +#define EI_PAD 7 + +#define ELFMAG0 0x7f /* EI_MAG */ +#define ELFMAG1 'E' +#define ELFMAG2 'L' +#define ELFMAG3 'F' +#define ELFMAG "\177ELF" +#define SELFMAG 4 + +#define ELFCLASSNONE 0 /* EI_CLASS */ +#define ELFCLASS32 1 +#define ELFCLASS64 2 +#define ELFCLASSNUM 3 + +#define ELFDATANONE 0 /* e_ident[EI_DATA] */ +#define ELFDATA2LSB 1 +#define ELFDATA2MSB 2 + +#define EV_NONE 0 /* e_version, EI_VERSION */ +#define EV_CURRENT 1 +#define EV_NUM 2 + +/* Notes used in ET_CORE */ +#define NT_PRSTATUS 1 +#define NT_PRFPREG 2 +#define NT_PRPSINFO 3 +#define NT_TASKSTRUCT 4 + +/* Note header in a PT_NOTE section */ +typedef struct elf32_note { + Elf32_Word n_namesz; /* Name size */ + Elf32_Word n_descsz; /* Content size */ + Elf32_Word n_type; /* Content type */ +} Elf32_Nhdr; + +/* Note header in a PT_NOTE section */ +/* + * For now we use the 32 bit version of the structure until we figure + * out whether we need anything better. Note - on the Alpha, "unsigned int" + * is only 32 bits. + */ +typedef struct elf64_note { + unsigned int n_namesz; /* Name size */ + unsigned int n_descsz; /* Content size */ + unsigned int n_type; /* Content type */ +} Elf64_Nhdr; + +#ifdef __mc68000__ +#define ELF_START_MMAP 0xC0000000 +#endif +#ifdef __i386__ +#define ELF_START_MMAP 0x80000000 +#endif + +#if ELF_CLASS == ELFCLASS32 + +extern Elf32_Dyn _DYNAMIC []; +#define elfhdr elf32_hdr +#define elf_phdr elf32_phdr +#define elf_note elf32_note + +#else + +extern Elf64_Dyn _DYNAMIC []; +#define elfhdr elf64_hdr +#define elf_phdr elf64_phdr +#define elf_note elf64_note + +#endif + + +#endif /* _LINUX_ELF_H */ Index: common/coff.h =================================================================== --- common/coff.h (nonexistent) +++ common/coff.h (revision 1765) @@ -0,0 +1,457 @@ +#if HAVE_CONFIG_H +#include +#endif + +/* This file is derived from the GAS 2.1.4 assembler control file. + The GAS product is under the GNU Public License, version 2 or later. + As such, this file is also under that license. + + If the file format changes in the COFF object, this file should be + subsequently updated to reflect the changes. + + The actual loader module only uses a few of these structures. The full + set is documented here because I received the full set. If you wish + more information about COFF, then O'Reilly has a very excellent book. +*/ + +#define E_SYMNMLEN 8 /* Number of characters in a symbol name */ +#define E_FILNMLEN 14 /* Number of characters in a file name */ +#define E_DIMNUM 4 /* Number of array dimensions in auxiliary entry */ + +/* + * These defines are byte order independent. There is no alignment of fields + * permitted in the structures. Therefore they are declared as characters + * and the values loaded from the character positions. It also makes it + * nice to have it "endian" independent. + */ +#if !defined(WORDS_BIGENDIAN) +/* Load a short int from the following tables with little-endian formats */ +#define COFF_SHORT_L SWAP_ENDIAN_SHORT +/* Load a long int from the following tables with little-endian formats */ +#define COFF_LONG_L SWAP_ENDIAN_LONG +/* Load a short int from the following tables with big-endian formats */ +#define COFF_SHORT_H KEEP_ENDIAN_SHORT +/* Load a long int from the following tables with big-endian formats */ +#define COFF_LONG_H KEEP_ENDIAN_LONG +#else +#define COFF_SHORT_L KEEP_ENDIAN_SHORT +#define COFF_LONG_L KEEP_ENDIAN_LONG +#define COFF_SHORT_H SWAP_ENDIAN_SHORT +#define COFF_LONG_H SWAP_ENDIAN_LONG +#endif + +#define SWAP_ENDIAN_SHORT(ps) ((short)(((unsigned short)((unsigned char)ps[1])<<8)|\ + ((unsigned short)((unsigned char)ps[0])))) + +#define SWAP_ENDIAN_LONG(ps) (((long)(((unsigned long)((unsigned char)ps[3])<<24) |\ + ((unsigned long)((unsigned char)ps[2])<<16) |\ + ((unsigned long)((unsigned char)ps[1])<<8) |\ + ((unsigned long)((unsigned char)ps[0]))))) + +#define KEEP_ENDIAN_SHORT(ps) ((short)(((unsigned short)((unsigned char)ps[0])<<8)|\ + ((unsigned short)((unsigned char)ps[1])))) + +#define KEEP_ENDIAN_LONG(ps) (((long)(((unsigned long)((unsigned char)ps[0])<<24) |\ + ((unsigned long)((unsigned char)ps[1])<<16) |\ + ((unsigned long)((unsigned char)ps[2])<<8) |\ + ((unsigned long)((unsigned char)ps[3]))))) + +/* These may be overridden later by brain dead implementations which generate + a big-endian header with little-endian data. In that case, generate a + replacement macro which tests a flag and uses either of the two above + as appropriate. */ + +#define COFF_LONG(v) COFF_LONG_L(v) +#define COFF_SHORT(v) COFF_SHORT_L(v) + +/*** coff information for Intel 386/486. */ + +/********************** FILE HEADER **********************/ + +struct COFF_filehdr { + char f_magic[2]; /* magic number */ + char f_nscns[2]; /* number of sections */ + char f_timdat[4]; /* time & date stamp */ + char f_symptr[4]; /* file pointer to symtab */ + char f_nsyms[4]; /* number of symtab entries */ + char f_opthdr[2]; /* sizeof(optional hdr) */ + char f_flags[2]; /* flags */ +}; + +/* + * Bits for f_flags: + * + * F_RELFLG relocation info stripped from file + * F_EXEC file is executable (i.e. no unresolved external + * references) + * F_LNNO line numbers stripped from file + * F_LSYMS local symbols stripped from file + * F_MINMAL this is a minimal object file (".m") output of fextract + * F_UPDATE this is a fully bound update file, output of ogen + * F_SWABD this file has had its bytes swabbed (in names) + * F_AR16WR this file has the byte ordering of an AR16WR + * (e.g. 11/70) machine + * F_AR32WR this file has the byte ordering of an AR32WR machine + * (e.g. vax and iNTEL 386) + * F_AR32W this file has the byte ordering of an AR32W machine + * (e.g. 3b,maxi) + * F_PATCH file contains "patch" list in optional header + * F_NODF (minimal file only) no decision functions for + * replaced functions + */ + +#define COFF_F_RELFLG 0000001 +#define COFF_F_EXEC 0000002 +#define COFF_F_LNNO 0000004 +#define COFF_F_LSYMS 0000010 +#define COFF_F_MINMAL 0000020 +#define COFF_F_UPDATE 0000040 +#define COFF_F_SWABD 0000100 +#define COFF_F_AR16WR 0000200 +#define COFF_F_AR32WR 0000400 +#define COFF_F_AR32W 0001000 +#define COFF_F_PATCH 0002000 +#define COFF_F_NODF 0002000 + +#define COFF_I386MAGIC 0x14c /* Linux's system */ + +#if 0 /* Perhaps, someday, these formats may be used. */ +#define COFF_I386PTXMAGIC 0x154 +#define COFF_I386AIXMAGIC 0x175 /* IBM's AIX system */ +#define COFF_I386BADMAG(x) ((COFF_SHORT((x).f_magic) != COFF_I386MAGIC) \ + && COFF_SHORT((x).f_magic) != COFF_I386PTXMAGIC \ + && COFF_SHORT((x).f_magic) != COFF_I386AIXMAGIC) +#else +#define COFF_I386BADMAG(x) (COFF_SHORT((x).f_magic) != COFF_I386MAGIC) +#endif + +#define COFF_FILHDR struct COFF_filehdr +#define COFF_FILHSZ sizeof(COFF_FILHDR) + +/********************** AOUT "OPTIONAL HEADER" **********************/ + +/* Linux COFF must have this "optional" header. Standard COFF has no entry + location for the "entry" point. They normally would start with the first + location of the .text section. This is not a good idea for linux. So, + the use of this "optional" header is not optional. It is required. + + Do not be tempted to assume that the size of the optional header is + a constant and simply index the next byte by the size of this structure. + Use the 'f_opthdr' field in the main coff header for the size of the + structure actually written to the file!! +*/ + +typedef struct +{ + char magic[2]; /* type of file */ + char vstamp[2]; /* version stamp */ + char tsize[4]; /* text size in bytes, padded to FW bdry */ + char dsize[4]; /* initialized data " " */ + char bsize[4]; /* uninitialized data " " */ + char entry[4]; /* entry pt. */ + char text_start[4]; /* base of text used for this file */ + char data_start[4]; /* base of data used for this file */ +} +COFF_AOUTHDR; + +#define COFF_AOUTSZ (sizeof(COFF_AOUTHDR)) + +#define COFF_STMAGIC 0401 +#define COFF_OMAGIC 0404 +#define COFF_JMAGIC 0407 /* dirty text and data image, can't share */ +#define COFF_DMAGIC 0410 /* dirty text segment, data aligned */ +#define COFF_ZMAGIC 0413 /* The proper magic number for executables */ +#define COFF_SHMAGIC 0443 /* shared library header */ + +/********************** STORAGE CLASSES **********************/ + +/* This used to be defined as -1, but now n_sclass is unsigned. */ +#define C_EFCN 0xff /* physical end of function */ +#define C_NULL 0 +#define C_AUTO 1 /* automatic variable */ +#define C_EXT 2 /* external symbol */ +#define C_STAT 3 /* static */ +#define C_REG 4 /* register variable */ +#define C_EXTDEF 5 /* external definition */ +#define C_LABEL 6 /* label */ +#define C_ULABEL 7 /* undefined label */ +#define C_MOS 8 /* member of structure */ +#define C_ARG 9 /* function argument */ +#define C_STRTAG 10 /* structure tag */ +#define C_MOU 11 /* member of union */ +#define C_UNTAG 12 /* union tag */ +#define C_TPDEF 13 /* type definition */ +#define C_USTATIC 14 /* undefined static */ +#define C_ENTAG 15 /* enumeration tag */ +#define C_MOE 16 /* member of enumeration */ +#define C_REGPARM 17 /* register parameter */ +#define C_FIELD 18 /* bit field */ +#define C_AUTOARG 19 /* auto argument */ +#define C_LASTENT 20 /* dummy entry (end of block) */ +#define C_BLOCK 100 /* ".bb" or ".eb" */ +#define C_FCN 101 /* ".bf" or ".ef" */ +#define C_EOS 102 /* end of structure */ +#define C_FILE 103 /* file name */ +#define C_LINE 104 /* line # reformatted as symbol table entry */ +#define C_ALIAS 105 /* duplicate tag */ +#define C_HIDDEN 106 /* ext symbol in dmert public lib */ + +#define C_WEAKEXT 127 /* weak symbol -- GNU extension */ + +/* New storage classes for TI COFF */ +#define C_UEXT 19 /* Tentative external definition */ +#define C_STATLAB 20 /* Static load time label */ +#define C_EXTLAB 21 /* External load time label */ +#define C_SYSTEM 23 /* System Wide variable */ + +/* New storage classes for WINDOWS_NT */ +#define C_SECTION 104 /* section name */ +#define C_NT_WEAK 105 /* weak external */ + + /* New storage classes for 80960 */ + +/* C_LEAFPROC is obsolete. Use C_LEAFEXT or C_LEAFSTAT */ +#define C_LEAFPROC 108 /* Leaf procedure, "call" via BAL */ + +#define C_SCALL 107 /* Procedure reachable via system call */ +#define C_LEAFEXT 108 /* External leaf */ +#define C_LEAFSTAT 113 /* Static leaf */ +#define C_OPTVAR 109 /* Optimized variable */ +#define C_DEFINE 110 /* Preprocessor #define */ +#define C_PRAGMA 111 /* Advice to compiler or linker */ +#define C_SEGMENT 112 /* 80960 segment name */ + + /* Storage classes for m88k */ +#define C_SHADOW 107 /* shadow symbol */ +#define C_VERSION 108 /* coff version symbol */ + + /* New storage classes for RS/6000 */ +#define C_HIDEXT 107 /* Un-named external symbol */ +#define C_BINCL 108 /* Marks beginning of include file */ +#define C_EINCL 109 /* Marks ending of include file */ + + /* storage classes for stab symbols for RS/6000 */ +#define C_GSYM (0x80) +#define C_LSYM (0x81) +#define C_PSYM (0x82) +#define C_RSYM (0x83) +#define C_RPSYM (0x84) +#define C_STSYM (0x85) +#define C_TCSYM (0x86) +#define C_BCOMM (0x87) +#define C_ECOML (0x88) +#define C_ECOMM (0x89) +#define C_DECL (0x8c) +#define C_ENTRY (0x8d) +#define C_FUN (0x8e) +#define C_BSTAT (0x8f) +#define C_ESTAT (0x90) + +/* Storage classes for Thumb symbols */ +#define C_THUMBEXT (128 + C_EXT) /* 130 */ +#define C_THUMBSTAT (128 + C_STAT) /* 131 */ +#define C_THUMBLABEL (128 + C_LABEL) /* 134 */ +#define C_THUMBEXTFUNC (C_THUMBEXT + 20) /* 150 */ +#define C_THUMBSTATFUNC (C_THUMBSTAT + 20) /* 151 */ + +/********************** SECTION HEADER **********************/ + +struct COFF_scnhdr { + char s_name[8]; /* section name */ + char s_paddr[4]; /* physical address, aliased s_nlib */ + char s_vaddr[4]; /* virtual address */ + char s_size[4]; /* section size */ + char s_scnptr[4]; /* file ptr to raw data for section */ + char s_relptr[4]; /* file ptr to relocation */ + char s_lnnoptr[4]; /* file ptr to line numbers */ + char s_nreloc[2]; /* number of relocation entries */ + char s_nlnno[2]; /* number of line number entries */ + char s_flags[4]; /* flags */ +}; + +#define COFF_SCNHDR struct COFF_scnhdr +#define COFF_SCNHSZ sizeof(COFF_SCNHDR) + +/* + * names of "special" sections + */ + +#define COFF_TEXT ".text" +#define COFF_DATA ".data" +#define COFF_BSS ".bss" +#define COFF_COMMENT ".comment" +#define COFF_LIB ".lib" + +#define COFF_SECT_TEXT 0 /* Section for instruction code */ +#define COFF_SECT_DATA 1 /* Section for initialized globals */ +#define COFF_SECT_BSS 2 /* Section for un-initialized globals */ +#define COFF_SECT_REQD 3 /* Minimum number of sections for good file */ + +#define COFF_STYP_REG 0x00 /* regular segment */ +#define COFF_STYP_DSECT 0x01 /* dummy segment */ +#define COFF_STYP_NOLOAD 0x02 /* no-load segment */ +#define COFF_STYP_GROUP 0x04 /* group segment */ +#define COFF_STYP_PAD 0x08 /* .pad segment */ +#define COFF_STYP_COPY 0x10 /* copy section */ +#define COFF_STYP_TEXT 0x20 /* .text segment */ +#define COFF_STYP_DATA 0x40 /* .data segment */ +#define COFF_STYP_BSS 0x80 /* .bss segment */ +#define COFF_STYP_INFO 0x200 /* .comment section */ +#define COFF_STYP_OVER 0x400 /* overlay section */ +#define COFF_STYP_LIB 0x800 /* library section */ + +/* + * Shared libraries have the following section header in the data field for + * each library. + */ + +struct COFF_slib { + char sl_entsz[4]; /* Size of this entry */ + char sl_pathndx[4]; /* size of the header field */ +}; + +#define COFF_SLIBHD struct COFF_slib +#define COFF_SLIBSZ sizeof(COFF_SLIBHD) + +/********************** LINE NUMBERS **********************/ + +/* 1 line number entry for every "breakpointable" source line in a section. + * Line numbers are grouped on a per function basis; first entry in a function + * grouping will have l_lnno = 0 and in place of physical address will be the + * symbol table index of the function name. + */ + +struct COFF_lineno { + union { + char l_symndx[4]; /* function name symbol index, iff l_lnno == 0*/ + char l_paddr[4]; /* (physical) address of line number */ + } l_addr; + char l_lnno[2]; /* line number */ +}; + +#define COFF_LINENO struct COFF_lineno +#define COFF_LINESZ 6 + +/********************** SYMBOLS **********************/ + +#define COFF_E_SYMNMLEN 8 /* # characters in a short symbol name */ +#define COFF_E_FILNMLEN 14 /* # characters in a file name */ +#define COFF_E_DIMNUM 4 /* # array dimensions in auxiliary entry */ + +/* + * All symbols and sections have the following definition + */ + +struct COFF_syment +{ + union { + char e_name[E_SYMNMLEN]; /* Symbol name (first 8 characters) */ + struct { + char e_zeroes[4]; /* Leading zeros */ + char e_offset[4]; /* Offset if this is a header section */ + } e; + } e; + + char e_value[4]; /* Value (address) of the segment */ + char e_scnum[2]; /* Section number */ + char e_type[2]; /* Type of section */ + char e_sclass[1]; /* Loader class */ + char e_numaux[1]; /* Number of auxiliary entries which follow */ +}; + +#define COFF_N_BTMASK (0xf) /* Mask for important class bits */ +#define COFF_N_TMASK (0x30) /* Mask for important type bits */ +#define COFF_N_BTSHFT (4) /* # bits to shift class field */ +#define COFF_N_TSHIFT (2) /* # bits to shift type field */ + +/* + * Auxiliary entries because the main table is too limiting. + */ + +union COFF_auxent { + +/* + * Debugger information + */ + + struct { + char x_tagndx[4]; /* str, un, or enum tag indx */ + union { + struct { + char x_lnno[2]; /* declaration line number */ + char x_size[2]; /* str/union/array size */ + } x_lnsz; + char x_fsize[4]; /* size of function */ + } x_misc; + + union { + struct { /* if ISFCN, tag, or .bb */ + char x_lnnoptr[4]; /* ptr to fcn line # */ + char x_endndx[4]; /* entry ndx past block end */ + } x_fcn; + + struct { /* if ISARY, up to 4 dimen. */ + char x_dimen[E_DIMNUM][2]; + } x_ary; + } x_fcnary; + + char x_tvndx[2]; /* tv index */ + } x_sym; + +/* + * Source file names (debugger information) + */ + + union { + char x_fname[E_FILNMLEN]; + struct { + char x_zeroes[4]; + char x_offset[4]; + } x_n; + } x_file; + +/* + * Section information + */ + + struct { + char x_scnlen[4]; /* section length */ + char x_nreloc[2]; /* # relocation entries */ + char x_nlinno[2]; /* # line numbers */ + } x_scn; + +/* + * Transfer vector (branch table) + */ + + struct { + char x_tvfill[4]; /* tv fill value */ + char x_tvlen[2]; /* length of .tv */ + char x_tvran[2][2]; /* tv range */ + } x_tv; /* info about .tv section (in auxent of symbol .tv)) */ +}; + +#define COFF_SYMENT struct COFF_syment +#define COFF_SYMESZ 18 +#define COFF_AUXENT union COFF_auxent +#define COFF_AUXESZ 18 + +#define COFF_ETEXT "etext" + +/********************** RELOCATION DIRECTIVES **********************/ + +struct COFF_reloc { + char r_vaddr[4]; /* Virtual address of item */ + char r_symndx[4]; /* Symbol index in the symtab */ + char r_type[2]; /* Relocation type */ +}; + +#define COFF_RELOC struct COFF_reloc +#define COFF_RELSZ 10 + +#define COFF_DEF_DATA_SECTION_ALIGNMENT 4 +#define COFF_DEF_BSS_SECTION_ALIGNMENT 4 +#define COFF_DEF_TEXT_SECTION_ALIGNMENT 4 + +/* For new sections we haven't heard of before */ +#define COFF_DEF_SECTION_ALIGNMENT 4 Index: common =================================================================== --- common (nonexistent) +++ common (revision 1765)
common Property changes : Added: svn:ignore ## -0,0 +1,2 ## +Makefile +.deps Index: or1k/spr-dump.c =================================================================== --- or1k/spr-dump.c (nonexistent) +++ or1k/spr-dump.c (revision 1765) @@ -0,0 +1,542 @@ +/* spr_dump.c -- Dump given spr in human readable form + + Copyright (C) 2005 György `nog' Jeney, nog@sdf.lonestar.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 . */ + +/* 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 + +/* Package includes */ +#include "arch.h" +#include "spr-defs.h" +#include "debug.h" +#include "misc.h" + + +struct spr_bit_def { + const char *name; + uorreg_t mask; +}; + +struct spr_def { + uint16_t from_spr; + uint16_t to_spr; + const char *name; + const struct spr_bit_def *bits; +}; + +/* One value spr */ +static const struct spr_bit_def spr_one_val[] = { + { "", 0xffffffff }, + { NULL, 0 } }; + +/*---------------------------------------------------------[ System group ]---*/ +/* Supervisor register */ +static const struct spr_bit_def spr_sr[] = { + { "SR_SM", SPR_SR_SM }, + { "SR_TEE", SPR_SR_TEE }, + { "SR_IEE", SPR_SR_IEE }, + { "SR_DCE", SPR_SR_DCE }, + { "SR_ICE", SPR_SR_ICE }, + { "SR_DME", SPR_SR_DME }, + { "SR_IME", SPR_SR_IME }, + { "SR_LEE", SPR_SR_IME }, + { "SR_CE", SPR_SR_CE }, + { "SR_F", SPR_SR_F }, + { "SR_CY", SPR_SR_CY }, + { "SR_OV", SPR_SR_OV }, + { "SR_OVE", SPR_SR_OVE }, + { "SR_DSX", SPR_SR_DSX }, + { "SR_EPH", SPR_SR_EPH }, + { "SR_FO", SPR_SR_FO }, + { "SR_SUMRA", SPR_SR_SUMRA }, + { "SR_RES", SPR_SR_RES }, + { "SR_CID", SPR_SR_CID }, + { NULL, 0 } }; + +/* Version register */ +static const struct spr_bit_def spr_vr[] = { + { "VR_VER", SPR_VR_VER }, + { "VR_REV", SPR_VR_REV }, + { NULL, 0 } }; + +/* upr register */ +static const struct spr_bit_def spr_upr[] = { + { "UPR_UP", SPR_UPR_UP }, + { "UPR_DCP", SPR_UPR_DCP }, + { "UPR_ICP", SPR_UPR_ICP }, + { "UPR_DMP", SPR_UPR_DMP }, + { "UPR_IMP", SPR_UPR_IMP }, + { "UPR_MP", SPR_UPR_MP }, + { "UPR_DUP", SPR_UPR_DUP }, + { "UPR_PCUP", SPR_UPR_PCUP }, + { "UPR_PMP", SPR_UPR_PMP }, + { "UPR_PICP", SPR_UPR_PICP }, + { "UPR_TTP", SPR_UPR_TTP }, + { "UPR_RES", SPR_UPR_RES }, + { "UPR_CUP", SPR_UPR_CUP }, + { NULL, 0 } }; + +/* CPUCFGR register */ +static const struct spr_bit_def spr_cpucfgr[] = { + { "CPUCFGR_OB32S", SPR_CPUCFGR_OB32S }, + { "CPUCFGR_OB64S", SPR_CPUCFGR_OB64S }, + { "CPUCFGR_OF32S", SPR_CPUCFGR_OF32S }, + { "CPUCFGR_OF64S", SPR_CPUCFGR_OF64S }, + { "CPUCFGR_OV64S", SPR_CPUCFGR_OV64S }, + { NULL, 0 } }; + +/* dmmucfgr register */ +static const struct spr_bit_def spr_dmmucfgr[] = { + { "DMMUCFGR_NTW", SPR_DMMUCFGR_NTW }, + { "DMMUCFGR_NTS", SPR_DMMUCFGR_NTS }, + { "DMMUCFGR_NAE", SPR_DMMUCFGR_NAE }, + { "DMMUCFGR_CRI", SPR_DMMUCFGR_CRI }, + { "DMMUCFGR_PRI", SPR_DMMUCFGR_PRI }, + { "DMMUCFGR_TEIRI", SPR_DMMUCFGR_TEIRI }, + { "DMMUCFGR_HTR", SPR_DMMUCFGR_HTR }, + { NULL, 0 } }; + +/* immucfgr register */ +static const struct spr_bit_def spr_immucfgr[] = { + { "IMMUCFGR_NTW", SPR_IMMUCFGR_NTW }, + { "IMMUCFGR_NTS", SPR_IMMUCFGR_NTS }, + { "IMMUCFGR_NAE", SPR_IMMUCFGR_NAE }, + { "IMMUCFGR_CRI", SPR_IMMUCFGR_CRI }, + { "IMMUCFGR_PRI", SPR_IMMUCFGR_PRI }, + { "IMMUCFGR_TEIRI", SPR_IMMUCFGR_TEIRI }, + { "IMMUCFGR_HTR", SPR_IMMUCFGR_HTR }, + { NULL, 0 } }; + +/* dccfgr register */ +static const struct spr_bit_def spr_dccfgr[] = { + { "DCCFGR_NCW", SPR_DCCFGR_NCW }, + { "DCCFGR_NCS", SPR_DCCFGR_NCS }, + { "DCCFGR_CBS", SPR_DCCFGR_CBS }, + { "DCCFGR_CWS", SPR_DCCFGR_CWS }, + { "DCCFGR_CCRI", SPR_DCCFGR_CCRI }, + { "DCCFGR_CBIRI", SPR_DCCFGR_CBIRI }, + { "DCCFGR_CBPRI", SPR_DCCFGR_CBPRI }, + { "DCCFGR_CBLRI", SPR_DCCFGR_CBLRI }, + { "DCCFGR_CBFRI", SPR_DCCFGR_CBFRI }, + { "DCCFGR_CBWBRI", SPR_DCCFGR_CBWBRI }, + { NULL, 0 } }; + +/* iccfgr register */ +static const struct spr_bit_def spr_iccfgr[] = { + { "ICCFGR_NCW", SPR_ICCFGR_NCW }, + { "ICCFGR_NCS", SPR_ICCFGR_NCS }, + { "ICCFGR_CBS", SPR_ICCFGR_CBS }, + { "ICCFGR_CCRI", SPR_ICCFGR_CCRI }, + { "ICCFGR_CBIRI", SPR_ICCFGR_CBIRI }, + { "ICCFGR_CBPRI", SPR_ICCFGR_CBPRI }, + { "ICCFGR_CBLRI", SPR_ICCFGR_CBLRI }, + { NULL, 0 } }; + +/* DCFGR register */ +static const struct spr_bit_def spr_dcfgr[] = { + { "DCFGR_NDP", SPR_DCFGR_NDP }, + { "DCFGR_WPCI", SPR_DCFGR_WPCI }, + { NULL, 0 } }; + +/* System group */ +static const struct spr_def spr_sys_group[] = { + /* 000-000 */ { 0x000, 0x000, "SPR_VR", spr_vr }, + /* 001-001 */ { 0x001, 0x001, "SPR_UPR", spr_upr }, + /* 002-002 */ { 0x002, 0x002, "SPR_CPUCFGR", spr_cpucfgr }, /* JPB */ + /* 003-003 */ { 0x003, 0x003, "SPR_DMMUCFGR", spr_dmmucfgr }, + /* 004-004 */ { 0x004, 0x004, "SPR_IMMUCFGR", spr_immucfgr }, + /* 005-005 */ { 0x005, 0x005, "SPR_DCCFGR", spr_dccfgr }, + /* 006-006 */ { 0x006, 0x006, "SPR_ICCFGR", spr_iccfgr }, + /* 007-007 */ { 0x007, 0x007, "SPR_DCFGR", spr_dcfgr }, /* JPB */ + /* 010-010 */ { 0x010, 0x010, "SPR_NPC", spr_one_val }, + /* 011-011 */ { 0x011, 0x011, "SPR_SR", spr_sr }, + /* 012-012 */ { 0x012, 0x012, "SPR_PPC", spr_one_val }, + /* 020-02f */ { 0x020, 0x02f, "SPR_EPCR(%i)", spr_one_val }, + /* 030-03f */ { 0x030, 0x03f, "SPR_EEAR(%i)", spr_one_val }, + /* 040-04f */ { 0x040, 0x04f, "SPR_ESR(%i)", spr_sr }, + /* 400-41f */ { 0x400, 0x41f, "GPR(%i)", spr_one_val }, + /* ------- */ { -1, -1, NULL, NULL } }; + +/*-----------------------------------------------------------[ DMMU group ]---*/ +/* Data MMU conrtol reg */ +static const struct spr_bit_def spr_dmmucr[] = { + { "DMMUCR_P2S", SPR_DMMUCR_P2S }, + { "DMMUCR_P1S", SPR_DMMUCR_P1S }, + { "DMMUCR_VADDR_WIDTH", SPR_DMMUCR_VADDR_WIDTH }, + { "DMMUCR_PADDR_WIDTH", SPR_DMMUCR_PADDR_WIDTH }, + { NULL, 0 } }; + +/* dtlbmr register */ +static const struct spr_bit_def spr_dtlbmr[] = { + { "DTLBMR_V", SPR_DTLBMR_V }, + { "DTLBMR_PL1", SPR_DTLBMR_PL1 }, + { "DTLBMR_CID", SPR_DTLBMR_CID }, + { "DTLBMR_LRU", SPR_DTLBMR_LRU }, + { "DTLBMR_VPN", SPR_DTLBMR_VPN }, + { NULL, 0 } }; + +/* dtlbtr register */ +static const struct spr_bit_def spr_dtlbtr[] = { + { "DTLBTR_CC", SPR_DTLBTR_CC }, + { "DTLBTR_CI", SPR_DTLBTR_CI }, + { "DTLBTR_WBC", SPR_DTLBTR_WBC }, + { "DTLBTR_WOM", SPR_DTLBTR_WOM }, + { "DTLBTR_A", SPR_DTLBTR_A }, + { "DTLBTR_D", SPR_DTLBTR_D }, + { "DTLBTR_URE", SPR_DTLBTR_URE }, + { "DTLBTR_UWE", SPR_DTLBTR_UWE }, + { "DTLBTR_SRE", SPR_DTLBTR_SRE }, + { "DTLBTR_SWE", SPR_DTLBTR_SWE }, + { "DTLBTR_PPN", SPR_DTLBTR_PPN }, + { NULL, 0 } }; + +/* DMMU group */ +static const struct spr_def spr_dmmu_group[] = { + /* 000-000 */ { 0, 0, "SPR_DMMUCR", spr_dmmucr }, + /* 200-27f */ { 0x200, 0x27f, "SPR_DTLBMR way 0 set %i", spr_dtlbmr }, + /* 280-2ff */ { 0x280, 0x2ff, "SPR_DTLBTR way 0 set %i", spr_dtlbtr }, + /* 300-37f */ { 0x300, 0x37f, "SPR_DTLBMR way 1 set %i", spr_dtlbmr }, + /* 380-3ff */ { 0x380, 0x3ff, "SPR_DTLBTR way 1 set %i", spr_dtlbtr }, + /* 400-47f */ { 0x400, 0x47f, "SPR_DTLBMR way 2 set %i", spr_dtlbmr }, + /* 480-4ff */ { 0x480, 0x4ff, "SPR_DTLBTR way 2 set %i", spr_dtlbtr }, + /* 500-57f */ { 0x500, 0x57f, "SPR_DTLBMR way 3 set %i", spr_dtlbmr }, + /* 580-5ff */ { 0x580, 0x5ff, "SPR_DTLBTR way 3 set %i", spr_dtlbtr }, + /* ------- */ { -1, -1, NULL, NULL } }; + +/*-----------------------------------------------------------[ IMMU group ]---*/ +/* Instruction MMU conrtol reg */ +static const struct spr_bit_def spr_immucr[] = { + { "IMMUCR_P2S", SPR_IMMUCR_P2S }, + { "IMMUCR_P1S", SPR_IMMUCR_P1S }, + { "IMMUCR_VADDR_WIDTH", SPR_IMMUCR_VADDR_WIDTH }, + { "IMMUCR_PADDR_WIDTH", SPR_IMMUCR_PADDR_WIDTH }, + { NULL, 0 } }; + +/* itlbmr register */ +static const struct spr_bit_def spr_itlbmr[] = { + { "ITLBMR_V", SPR_ITLBMR_V }, + { "ITLBMR_PL1", SPR_ITLBMR_PL1 }, + { "ITLBMR_CID", SPR_ITLBMR_CID }, + { "ITLBMR_LRU", SPR_ITLBMR_LRU }, + { "ITLBMR_VPN", SPR_ITLBMR_VPN }, + { NULL, 0 } }; + +/* itlbtr register */ +static const struct spr_bit_def spr_itlbtr[] = { + { "ITLBTR_CC", SPR_ITLBTR_CC }, + { "ITLBTR_CI", SPR_ITLBTR_CI }, + { "ITLBTR_WBC", SPR_ITLBTR_WBC }, + { "ITLBTR_WOM", SPR_ITLBTR_WOM }, + { "ITLBTR_A", SPR_ITLBTR_A }, + { "ITLBTR_D", SPR_ITLBTR_D }, + { "ITLBTR_URE", SPR_ITLBTR_SXE }, + { "ITLBTR_UWE", SPR_ITLBTR_UXE }, + { "ITLBTR_PPN", SPR_ITLBTR_PPN }, + { NULL, 0 } }; + +/* IMMU group */ +static const struct spr_def spr_immu_group[] = { + /* 000-000 */ { 0, 0, "SPR_IMMUCR", spr_immucr }, + /* 200-27f */ { 0x200, 0x27f, "SPR_ITLBMR way 0 set %i", spr_itlbmr }, + /* 280-2ff */ { 0x280, 0x2ff, "SPR_ITLBTR way 0 set %i", spr_itlbtr }, + /* 300-37f */ { 0x300, 0x37f, "SPR_ITLBMR way 1 set %i", spr_itlbmr }, + /* 380-3ff */ { 0x380, 0x3ff, "SPR_ITLBTR way 1 set %i", spr_itlbtr }, + /* 400-47f */ { 0x400, 0x47f, "SPR_ITLBMR way 2 set %i", spr_itlbmr }, + /* 480-4ff */ { 0x480, 0x4ff, "SPR_ITLBTR way 2 set %i", spr_itlbtr }, + /* 500-57f */ { 0x500, 0x57f, "SPR_ITLBMR way 3 set %i", spr_itlbmr }, + /* 580-5ff */ { 0x580, 0x5ff, "SPR_ITLBTR way 3 set %i", spr_itlbtr }, + /* ------- */ { -1, -1, NULL, NULL } }; + +/*-----------------------------------------------------[ Data cache group ]---*/ +static const struct spr_bit_def spr_dccr[] = { + { "DCCR_EW", SPR_DCCR_EW }, + { NULL, 0 } }; + +static const struct spr_def spr_dc_group[] = { + /* 000-000 */ { 0x000, 0x000, "SPR_DCCR", spr_dccr }, + /* 001-001 */ { 0x001, 0x001, "SPR_DCBPR", spr_one_val }, + /* 002-002 */ { 0x002, 0x002, "SPR_DCBFR", spr_one_val }, + /* 003-003 */ { 0x003, 0x003, "SPR_DCBIR", spr_one_val }, + /* 004-004 */ { 0x004, 0x004, "SPR_DCBWR", spr_one_val }, + /* 005-005 */ { 0x005, 0x005, "SPR_DCBLR", spr_one_val }, + /* 200-3ff */ { 0x200, 0x3ff, "SPR_DCR way 0 set %i", spr_one_val }, + /* 400-5ff */ { 0x400, 0x5ff, "SPR_DCR way 1 set %i", spr_one_val }, + /* 600-7ff */ { 0x600, 0x7ff, "SPR_DCR way 2 set %i", spr_one_val }, + /* 800-9ff */ { 0x800, 0x9ff, "SPR_DCR way 3 set %i", spr_one_val }, + /* ------- */ { -1, -1, NULL, NULL } }; + +/*----------------------------------------------[ Instruction cache group ]---*/ +static const struct spr_bit_def spr_iccr[] = { + { "ICCR_EW", SPR_ICCR_EW }, + { NULL, 0 } }; + +static const struct spr_def spr_ic_group[] = { + /* 000-000 */ { 0x000, 0x000, "SPR_ICCR", spr_iccr }, + /* 001-001 */ { 0x001, 0x001, "SPR_ICBPR", spr_one_val }, + /* 002-002 */ { 0x002, 0x002, "SPR_ICBFR", spr_one_val }, + /* 003-003 */ { 0x003, 0x003, "SPR_ICBIR", spr_one_val }, + /* 200-3ff */ { 0x200, 0x3ff, "SPR_ICR way 0 set %i", spr_one_val }, + /* 400-5ff */ { 0x400, 0x5ff, "SPR_ICR way 1 set %i", spr_one_val }, + /* 600-7ff */ { 0x600, 0x7ff, "SPR_ICR way 2 set %i", spr_one_val }, + /* 800-9ff */ { 0x800, 0x9ff, "SPR_ICR way 3 set %i", spr_one_val }, + /* ------- */ { -1, -1, NULL, NULL } }; + +/*------------------------------------------------------------[ MAC group ]---*/ +static const struct spr_def spr_mac_group[] = { + /* 1-1 */ { 0x1, 0x1, "SPR_MACLO", spr_one_val }, + /* 2-2 */ { 0x2, 0x2, "SPR_MACHI", spr_one_val }, + /* ------- */ { -1, -1, NULL, NULL } }; + +/*----------------------------------------------------------[ Debug group ]---*/ +/* dmr1 register */ +static const struct spr_bit_def spr_dmr1[] = { + { "DMR1_CW0", SPR_DMR1_CW0 }, + { "DMR1_CW1", SPR_DMR1_CW1 }, + { "DMR1_CW2", SPR_DMR1_CW2 }, + { "DMR1_CW3", SPR_DMR1_CW3 }, + { "DMR1_CW4", SPR_DMR1_CW4 }, + { "DMR1_CW5", SPR_DMR1_CW5 }, + { "DMR1_CW6", SPR_DMR1_CW6 }, + { "DMR1_CW7", SPR_DMR1_CW7 }, + { "DMR1_CW8", SPR_DMR1_CW8 }, + { "DMR1_CW9", SPR_DMR1_CW9 }, + { "DMR1_RES1", SPR_DMR1_RES1 }, + { "DMR1_ST", SPR_DMR1_ST }, + { "DMR1_BT", SPR_DMR1_BT }, + { "DMR1_RES2", SPR_DMR1_RES2 }, + { NULL, 0 } }; + +/* dmr2 register */ +static const struct spr_bit_def spr_dmr2[] = { + { "DMR2_WCE0", SPR_DMR2_WCE0 }, + { "DMR2_WCE1", SPR_DMR2_WCE1 }, + { "DMR2_AWTC", SPR_DMR2_AWTC }, + { "DMR2_WGB", SPR_DMR2_WGB }, + { "DMR2_WBS", SPR_DMR2_WBS }, /* JPB */ + { NULL, 0 } }; + +/* dwcr register */ +static const struct spr_bit_def spr_dwcr[] = { + { "DWCR_COUNT", SPR_DWCR_COUNT }, + { "DWCR_MATCH", SPR_DWCR_MATCH }, + { NULL, 0 } }; + +/* dsr register */ +static const struct spr_bit_def spr_dsr[] = { + { "DSR_RSTE", SPR_DSR_RSTE }, + { "DSR_BUSE", SPR_DSR_BUSEE }, + { "DSR_DPFE", SPR_DSR_DPFE }, + { "DSR_IPFE", SPR_DSR_IPFE }, + { "DSR_TTE", SPR_DSR_TTE }, + { "DSR_AE", SPR_DSR_AE }, + { "DSR_IIE", SPR_DSR_IIE }, + { "DSR_IE", SPR_DSR_IE }, + { "DSR_DME", SPR_DSR_DME }, + { "DSR_IME", SPR_DSR_IME }, + { "DSR_RE", SPR_DSR_RE }, + { "DSR_SCE", SPR_DSR_SCE }, + { "DSR_SSE", SPR_DSR_SSE }, + { "DSR_TE", SPR_DSR_TE }, + { NULL, 0 } }; + +/* drr register */ +static const struct spr_bit_def spr_drr[] = { + { "DRR_RSTE", SPR_DRR_RSTE }, + { "DRR_BUSE", SPR_DRR_BUSEE }, + { "DRR_DPFE", SPR_DRR_DPFE }, + { "DRR_IPFE", SPR_DRR_IPFE }, + { "DRR_TTE", SPR_DRR_TTE }, + { "DRR_AE", SPR_DRR_AE }, + { "DRR_IIE", SPR_DRR_IIE }, + { "DRR_IE", SPR_DRR_IE }, + { "DRR_DME", SPR_DRR_DME }, + { "DRR_IME", SPR_DRR_IME }, + { "DRR_RE", SPR_DRR_RE }, + { "DRR_SCE", SPR_DRR_SCE }, + { "DRR_TE", SPR_DRR_TE }, + { NULL, 0 } }; + +/* Debug group */ +static const struct spr_def spr_d_group[] = { +#if 0 + /* 00-07 */ { 0x00, 0x07, "SPR_DVR(%i)", spr_dvr }, + /* 08-0f */ { 0x08, 0x0f, "SPR_DCR(%i)", spr_dcr }, +#endif + /* 10-10 */ { 0x10, 0x10, "SPR_DMR1", spr_dmr1 }, + /* 11-11 */ { 0x11, 0x11, "SPR_DMR2", spr_dmr2 }, + /* 12-12 */ { 0x12, 0x12, "SPR_DWCR0", spr_dwcr }, + /* 13-13 */ { 0x13, 0x13, "SPR_DWCR1", spr_dwcr }, + /* 14-14 */ { 0x14, 0x14, "SPR_DSR", spr_dsr }, + /* 15-15 */ { 0x15, 0x15, "SPR_DRR", spr_drr }, + /* ----- */ { -1, -1, NULL, NULL } }; + +/*-------------------------------------------[ Performance counters group ]---*/ +static const struct spr_bit_def spr_pcmr[] = { + { "PCMR_CP", SPR_PCMR_CP }, + { "PCMR_UMRA", SPR_PCMR_UMRA }, + { "PCMR_CISM", SPR_PCMR_CISM }, + { "PCMR_CIUM", SPR_PCMR_CIUM }, + { "PCMR_LA", SPR_PCMR_LA }, + { "PCMR_SA", SPR_PCMR_SA }, + { "PCMR_IF", SPR_PCMR_IF }, + { "PCMR_DCM", SPR_PCMR_DCM }, + { "PCMR_ICM", SPR_PCMR_ICM }, + { "PCMR_IFS", SPR_PCMR_IFS }, + { "PCMR_LSUS", SPR_PCMR_LSUS }, + { "PCMR_BS", SPR_PCMR_BS }, + { "PCMR_DTLBM", SPR_PCMR_DTLBM }, + { "PCMR_ITLBM", SPR_PCMR_ITLBM }, + { "PCMR_DDS", SPR_PCMR_DDS }, + { "PCMR_WPE", SPR_PCMR_WPE }, + { NULL, 0 } }; + +static const struct spr_def spr_pc_group[] = { + /* 00-07 */ { 0x00, 0x07, "PCCR", spr_one_val }, + /* 08-0f */ { 0x08, 0x0f, "PCMR", spr_pcmr }, + /* ----- */ { -1, -1, NULL, NULL } }; + +/*------------------------------------------------[ Power managment group ]---*/ +static const struct spr_bit_def spr_pmr[] = { + { "PMR_SDF", SPR_PMR_SDF }, + { "PMR_DME", SPR_PMR_DME }, + { "PMR_SME", SPR_PMR_SME }, + { "PMR_DCGE", SPR_PMR_DCGE }, + { "PMR_SUME", SPR_PMR_SUME }, + { NULL, 0 } }; + +static const struct spr_def spr_pm_group[] = { + /* 0-0 */ { 0x0, 0x0, "SPR_PMR", spr_pmr }, + /* --- */ { -1, -1, NULL, NULL } }; + +/*------------------------------------------------------------[ PIC group ]---*/ +/* picmr register */ +static const struct spr_bit_def spr_picmr[] = { + { "PICMR_IUM", SPR_PICMR_IUM }, + { NULL, 0 } }; + +static const struct spr_def spr_pic_group[] = { + /* 0-0 */ { 0, 0, "PICMR", spr_picmr }, + /* 2-2 */ { 2, 2, "PICSR", spr_one_val }, + /* --- */ { -1, -1, NULL, NULL } }; + +/*-----------------------------------------------------[ Tick timer group ]---*/ +static const struct spr_bit_def spr_ttmr[] = { + { "TTMR_PERIOD", SPR_TTMR_PERIOD }, + { "TTMR_IP", SPR_TTMR_IP }, + { "TTMR_IE", SPR_TTMR_IE }, + { "TTMR_M", SPR_TTMR_M }, + { NULL, 0 } }; + +static const struct spr_def spr_tt_group[] = { + /* 0-0 */ { 0, 0, "TTMR", spr_ttmr }, + /* 1-1 */ { 0, 0, "TTCR", spr_one_val }, + /* --- */ { -1, -1, NULL, NULL } }; + +/* Spr groups */ +static const struct spr_def *spr_groups[] = { + /* 00 */ spr_sys_group, + /* 01 */ spr_dmmu_group, + /* 02 */ spr_immu_group, + /* 03 */ spr_dc_group, + /* 04 */ spr_ic_group, + /* 05 */ spr_mac_group, + /* 06 */ spr_d_group, + /* 07 */ spr_pc_group, + /* 08 */ spr_pm_group, + /* 09 */ spr_pic_group, + /* 0a */ spr_tt_group }; + +/* Should be long enough for everything */ +static char ret_spr[1000]; + +/* Dumps the given spr in nice, human readable form */ +char *dump_spr(uint16_t spr, uorreg_t spr_val) +{ + const struct spr_def *spr_def; + uint16_t spr_in_group = spr & (MAX_SPRS_PER_GRP - 1); + uint16_t spr_group = spr >> MAX_SPRS_PER_GRP_BITS; + const struct spr_bit_def *spr_bit_def; + + int first_bit = 1; + int i; + uorreg_t tmp; + + spr_def = spr_groups[spr_group]; + + /* Find the given spr */ + for(; spr_def->from_spr != 0xffff; spr_def++) { + if((spr_def->from_spr <= spr_in_group) && (spr_def->to_spr >= spr_in_group)) + break; + } + + if(spr_def->from_spr == 0xffff) { + sprintf(ret_spr, "Spr %"PRIx16", group %"PRIx16" = 0x%"PRIxREG"\n", + spr_in_group, spr_group, spr_val); + return ret_spr; + } + + /* Decode the spr bits and show them in a pretty format */ + if(spr_def->from_spr == spr_def->to_spr) + sprintf(ret_spr, "%s", spr_def->name); + else + sprintf(ret_spr, spr_def->name, spr_in_group - spr_def->from_spr); + strcat(ret_spr, " = "); + + /* First get all the single-bit bit fields and dump them */ + for(spr_bit_def = spr_def->bits; spr_bit_def->name; spr_bit_def++) { + if(!is_power2(spr_bit_def->mask)) + continue; + + if(!(spr_bit_def->mask & spr_val)) + continue; + + if(!first_bit) + strcat(ret_spr, " | "); + else + first_bit = 0; + strcat(ret_spr, spr_bit_def->name); + } + + /* Now dump all the multi-bit bit fields */ + for(spr_bit_def = spr_def->bits; spr_bit_def->name; spr_bit_def++) { + if(is_power2(spr_bit_def->mask)) + continue; + if(!first_bit) + strcat(ret_spr, " | "); + else + first_bit = 0; + for(tmp = spr_bit_def->mask, i = 0; !(tmp & 1); i++) + tmp >>= 1; + + sprintf(ret_spr, "%s%s = %" PRIxREG, ret_spr, spr_bit_def->name, + (spr_val >> i) & tmp); + } + return ret_spr; +} + Index: or1k/sprs.c =================================================================== --- or1k/sprs.c (nonexistent) +++ or1k/sprs.c (revision 1765) @@ -0,0 +1,258 @@ +/* sprs.c -- Simulation of OR1K special-purpose registers + + Copyright (C) 1999 Damjan Lampret, lampret@opencores.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 "sprs.h" +#include "sim-config.h" +#include "debug.h" +#include "execute.h" +#include "spr-defs.h" +#include "tick.h" +#include "dcache-model.h" +#include "icache-model.h" +#include "dmmu.h" +#include "immu.h" +#include "toplevel-support.h" +#include "pic.h" + + +DECLARE_DEBUG_CHANNEL(immu); + +static int audio_cnt = 0; + +static FILE *fo = 0; + +/* Set a specific SPR with a value. */ +void mtspr(uint16_t regno, const uorreg_t value) +{ + uorreg_t prev_val; + + prev_val = cpu_state.sprs[regno]; + cpu_state.sprs[regno] = value; + + /* MM: Register hooks. */ + switch (regno) { + case SPR_TTCR: + spr_write_ttcr (value); + break; + case SPR_TTMR: + spr_write_ttmr (prev_val); + break; + /* Data cache simulateing stuff */ + case SPR_DCBPR: + /* FIXME: This is not correct. The arch. manual states: "Memory accesses + * are not recorded (Unlike load or store instructions) and cannot invoke + * any exception". If the physical address is invalid a bus error will be + * generated. Also if the effective address is not resident in the mmu + * the read will happen from address 0, which is naturally not correct. */ + dc_simulate_read(peek_into_dtlb(value, 0, 1), value, 4); + cpu_state.sprs[SPR_DCBPR] = 0; + break; + case SPR_DCBFR: + dc_inv(value); + cpu_state.sprs[SPR_DCBFR] = -1; + break; + case SPR_DCBIR: + dc_inv(value); + cpu_state.sprs[SPR_DCBIR] = 0; + break; + case SPR_DCBWR: + cpu_state.sprs[SPR_DCBWR] = 0; + break; + case SPR_DCBLR: + cpu_state.sprs[SPR_DCBLR] = 0; + break; + /* Instruction cache simulateing stuff */ + case SPR_ICBPR: + /* FIXME: The arch manual does not say what happens when an invalid memory + * location is specified. I guess the same as for the DCBPR register */ + ic_simulate_fetch(peek_into_itlb(value), value); + cpu_state.sprs[SPR_ICBPR] = 0; + break; + case SPR_ICBIR: + ic_inv(value); + cpu_state.sprs[SPR_ICBIR] = 0; + break; + case SPR_ICBLR: + cpu_state.sprs[SPR_ICBLR] = 0; + break; + case SPR_SR: + cpu_state.sprs[regno] |= SPR_SR_FO; + if((value & SPR_SR_IEE) && !(prev_val & SPR_SR_IEE)) + pic_ints_en(); +#if DYNAMIC_EXECUTION + if((value & SPR_SR_IME) && !(prev_val & SPR_SR_IME)) { + TRACE_(immu)("IMMU just became enabled (%lli).\n", runtime.sim.cycles); + recheck_immu(IMMU_GOT_ENABLED); + } else if(!(value & SPR_SR_IME) && (prev_val & SPR_SR_IME)) { + TRACE_(immu)("Remove counting of mmu hit delay with cycles (%lli)\n", + runtime.sim.cycles); + recheck_immu(IMMU_GOT_DISABLED); + } +#endif + break; + case SPR_NPC: + { + /* The debugger has redirected us to a new address */ + /* This is usually done to reissue an instruction + which just caused a breakpoint exception. */ + cpu_state.pc = value; + + if(!value && config.sim.verbose) + PRINTF("WARNING: PC just set to 0!\n"); + + /* Clear any pending delay slot jumps also */ + cpu_state.delay_insn = 0; + pcnext = value + 4; + } + break; + case SPR_PICSR: + if(!config.pic.edge_trigger) + cpu_state.sprs[SPR_PICSR] = prev_val; + break; + case SPR_PICMR: + if(cpu_state.sprs[SPR_SR] & SPR_SR_IEE) + pic_ints_en(); + break; + case 0xFFFD: + fo = fopen ("audiosim.pcm", "wb+"); + if (!fo) PRINTF("Cannot open audiosim.pcm\n"); + PRINTF("Audio opened.\n"); + break; + case 0xFFFE: + if (!fo) PRINTF("audiosim.pcm not opened\n"); + fputc (value & 0xFF, fo); + if ((audio_cnt % 1024) == 0) + PRINTF("%i\n", audio_cnt); + audio_cnt++; + break; + case 0xFFFF: + fclose(fo); + PRINTF("Audio closed.\n"); + sim_done(); + break; + case SPR_PMR: + /* PMR[SDF] and PMR[DCGE] are ignored completely. */ + if (config.pm.enabled && (value & SPR_PMR_SUME)) { + PRINTF ("SUSPEND: PMR[SUME] bit was set.\n"); + sim_done(); + } + break; + default: + /* Mask reserved bits in DTLBMR and DTLBMR registers */ + if ( (regno >= SPR_DTLBMR_BASE(0)) && (regno < SPR_DTLBTR_LAST(3))) { + if((regno & 0xff) < 0x80) + cpu_state.sprs[regno] = DADDR_PAGE(value) | + (value & (SPR_DTLBMR_V | SPR_DTLBMR_PL1 | SPR_DTLBMR_CID | SPR_DTLBMR_LRU)); + else + cpu_state.sprs[regno] = DADDR_PAGE(value) | + (value & (SPR_DTLBTR_CC | SPR_DTLBTR_CI | SPR_DTLBTR_WBC | SPR_DTLBTR_WOM | + SPR_DTLBTR_A | SPR_DTLBTR_D | SPR_DTLBTR_URE | SPR_DTLBTR_UWE | SPR_DTLBTR_SRE | + SPR_DTLBTR_SWE)); + } + + /* Mask reseved bits in ITLBMR and ITLBMR registers */ + if ( (regno >= SPR_ITLBMR_BASE(0)) && (regno < SPR_ITLBTR_LAST(3))) { + if((regno & 0xff) < 0x80) + cpu_state.sprs[regno] = IADDR_PAGE(value) | + (value & (SPR_ITLBMR_V | SPR_ITLBMR_PL1 | SPR_ITLBMR_CID | SPR_ITLBMR_LRU)); + else + cpu_state.sprs[regno] = IADDR_PAGE(value) | + (value & (SPR_ITLBTR_CC | SPR_ITLBTR_CI | SPR_ITLBTR_WBC | SPR_ITLBTR_WOM | + SPR_ITLBTR_A | SPR_ITLBTR_D | SPR_ITLBTR_SXE | SPR_ITLBTR_UXE)); + +#if DYNAMIC_EXECUTION + if(cpu_state.sprs[SPR_SR] & SPR_SR_IME) { + /* The immu got reconfigured. Recheck if the current page in execution + * is resident in the immu ways. This check would be done during the + * instruction fetch but since the dynamic execution model does not do + * instruction fetchs, do it now. */ + recheck_immu(0); + } +#endif + } + + /* Links to GPRS */ + if(regno >= 0x0400 && regno < 0x0420) { + cpu_state.reg[regno - 0x0400] = value; + } + break; + } +} + +/* Get a specific SPR. */ +uorreg_t mfspr(const uint16_t regno) +{ + uorreg_t ret; + + ret = cpu_state.sprs[regno]; + + switch (regno) { + case SPR_NPC: + ret = cpu_state.pc; + break; + case SPR_TTCR: + ret = spr_read_ttcr(); + break; + default: + /* Links to GPRS */ + if(regno >= 0x0400 && regno < 0x0420) + ret = cpu_state.reg[regno - 0x0400]; + } + + return ret; +} + +/* Show status of important SPRs. */ +void sprs_status(void) +{ + PRINTF("VR : 0x%"PRIxREG" UPR : 0x%"PRIxREG"\n", cpu_state.sprs[SPR_VR], + cpu_state.sprs[SPR_UPR]); + PRINTF("SR : 0x%"PRIxREG"\n", cpu_state.sprs[SPR_SR]); + PRINTF("MACLO: 0x%"PRIxREG" MACHI: 0x%"PRIxREG"\n", + cpu_state.sprs[SPR_MACLO], cpu_state.sprs[SPR_MACHI]); + PRINTF("EPCR0: 0x%"PRIxADDR" EPCR1: 0x%"PRIxADDR"\n", + cpu_state.sprs[SPR_EPCR_BASE], cpu_state.sprs[SPR_EPCR_BASE+1]); + PRINTF("EEAR0: 0x%"PRIxADDR" EEAR1: 0x%"PRIxADDR"\n", + cpu_state.sprs[SPR_EEAR_BASE], cpu_state.sprs[SPR_EEAR_BASE+1]); + PRINTF("ESR0 : 0x%"PRIxREG" ESR1 : 0x%"PRIxREG"\n", + cpu_state.sprs[SPR_ESR_BASE], cpu_state.sprs[SPR_ESR_BASE+1]); + PRINTF("TTMR : 0x%"PRIxREG" TTCR : 0x%"PRIxREG"\n", + cpu_state.sprs[SPR_TTMR], cpu_state.sprs[SPR_TTCR]); + PRINTF("PICMR: 0x%"PRIxREG" PICSR: 0x%"PRIxREG"\n", + cpu_state.sprs[SPR_PICMR], cpu_state.sprs[SPR_PICSR]); + PRINTF("PPC: 0x%"PRIxADDR" NPC : 0x%"PRIxADDR"\n", + cpu_state.sprs[SPR_PPC], cpu_state.sprs[SPR_NPC]); +} Index: or1k/except.c =================================================================== --- or1k/except.c (nonexistent) +++ or1k/except.c (revision 1765) @@ -0,0 +1,161 @@ +/* except.c -- Simulation of OR1K exceptions + + Copyright (C) 1999 Damjan Lampret, lampret@opencores.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" + +/* Package includes */ +#include "except.h" +#include "sim-config.h" +#include "arch.h" +#include "debug.h" +#include "spr-defs.h" +#include "execute.h" +#include "debug-unit.h" + +#if DYNAMIC_EXECUTION +#include "sched.h" +#include "op-support.h" +#endif + +extern void op_join_mem_cycles(void); + + + +int except_pending = 0; + +/* Asserts OR1K exception. */ +/* WARNING: Don't expect except_handle to return. Sometimes it _may_ return at + * other times it may not. */ +void +except_handle (oraddr_t except, oraddr_t ea) +{ + oraddr_t except_vector; + + if (debug_ignore_exception (except)) + return; + +#if !(DYNAMIC_EXECUTION) + /* In the dynamic recompiler, this function never returns, so this is not + * needed. Ofcourse we could set it anyway, but then all code that checks + * this variable would break, since it is never reset */ + except_pending = 1; +#endif + + except_vector = + except + (cpu_state.sprs[SPR_SR] & SPR_SR_EPH ? 0xf0000000 : 0x00000000); + +#if !(DYNAMIC_EXECUTION) + pcnext = except_vector; +#endif + + cpu_state.sprs[SPR_EEAR_BASE] = ea; + cpu_state.sprs[SPR_ESR_BASE] = cpu_state.sprs[SPR_SR]; + + cpu_state.sprs[SPR_SR] &= ~SPR_SR_OVE; /* Disable overflow flag exception. */ + + cpu_state.sprs[SPR_SR] |= SPR_SR_SM; /* SUPV mode */ + cpu_state.sprs[SPR_SR] &= ~(SPR_SR_IEE | SPR_SR_TEE); /* Disable interrupts. */ + + /* Address translation is always disabled when starting exception. */ + cpu_state.sprs[SPR_SR] &= ~SPR_SR_DME; + +#if DYNAMIC_EXECUTION + /* If we were called from do_scheduler and there were more jobs scheduled to + * run after this, they won't run unless the following call is made since this + * function never returns. (If we weren't called from do_scheduler, then the + * job at the head of the queue will still have some time remaining) */ + if (scheduler.job_queue->time <= 0) + do_scheduler (); +#endif + + switch (except) + { + /* EPCR is irrelevent */ + case EXCEPT_RESET: + break; + /* EPCR is loaded with address of instruction that caused the exception */ + case EXCEPT_ITLBMISS: + case EXCEPT_IPF: + cpu_state.sprs[SPR_EPCR_BASE] = ea - (cpu_state.delay_insn ? 4 : 0); +#if DYNAMIC_EXECUTION + op_join_mem_cycles (); +#endif + break; + case EXCEPT_BUSERR: + case EXCEPT_DPF: + case EXCEPT_ALIGN: + case EXCEPT_ILLEGAL: + case EXCEPT_DTLBMISS: + case EXCEPT_RANGE: + case EXCEPT_TRAP: + /* All these exceptions happen during a simulated instruction */ +#if DYNAMIC_EXECUTION + /* Since these exceptions happen during a simulated instruction and this + * function jumps out to the exception vector the scheduler would never have + * a chance to run, therefore run it now */ + run_sched_out_of_line (); +#endif + cpu_state.sprs[SPR_EPCR_BASE] = + cpu_state.pc - (cpu_state.delay_insn ? 4 : 0); + break; + /* EPCR is loaded with address of next not-yet-executed instruction */ + case EXCEPT_SYSCALL: + cpu_state.sprs[SPR_EPCR_BASE] = + (cpu_state.pc + 4) - (cpu_state.delay_insn ? 4 : 0); + break; + /* These exceptions happen AFTER (or before) an instruction has been + * simulated, therefore the pc already points to the *next* instruction */ + case EXCEPT_TICK: + case EXCEPT_INT: + cpu_state.sprs[SPR_EPCR_BASE] = + cpu_state.pc - (cpu_state.delay_insn ? 4 : 0); +#if !(DYNAMIC_EXECUTION) + /* If we don't update the pc now, then it will only happen *after* the next + * instruction (There would be serious problems if the next instruction just + * happens to be a branch), when it should happen NOW. */ + cpu_state.pc = pcnext; + pcnext += 4; +#endif + break; + } + + /* Address trnaslation is here because run_sched_out_of_line calls + * eval_insn_direct which checks out the immu for the address translation but + * if it would be disabled above then there would be not much point... */ + cpu_state.sprs[SPR_SR] &= ~SPR_SR_IME; + + /* Complex/simple execution strictly don't need this because of the + * next_delay_insn thingy but in the dynamic execution modell that doesn't + * exist and thus cpu_state.delay_insn would stick in the exception handler + * causeing grief if the first instruction of the exception handler is also in + * the delay slot of the previous instruction */ + cpu_state.delay_insn = 0; + +#if DYNAMIC_EXECUTION + do_jump (except_vector); +#endif +} Index: or1k/opcode/or32.h =================================================================== --- or1k/opcode/or32.h (nonexistent) +++ or1k/opcode/or32.h (revision 1765) @@ -0,0 +1,217 @@ +/* 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 + + This file is part of Or1ksim, the OpenRISC 1000 Architectural Simulator. + This file is also part of or1k_gen_isa, GDB and GAS. + + This program is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by the Free + Software Foundation; either version 3 of the License, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + You should have received a copy of the GNU General Public License along + with this program. If not, see . */ + +/* This program is commented throughout in a fashion suitable for processing + with Doxygen. */ + +/* We treat all letters the same in encode/decode routines so + we need to assign some characteristics to them like signess etc.*/ + +#ifndef OR32_H_ISA +#define OR32_H_ISA + +#define NUM_UNSIGNED (0) +#define NUM_SIGNED (1) + +#ifndef PARAMS +#define PARAMS(x) x +#endif + +#ifndef CONST +#define CONST const +#endif + +#define MAX_GPRS 32 +#define PAGE_SIZE 8192 +#undef __HALF_WORD_INSN__ + +#define OPERAND_DELIM (',') + +#define OR32_IF_DELAY (1) +#define OR32_W_FLAG (2) +#define OR32_R_FLAG (4) + +#if defined(HAVE_EXECUTION) +# if SIMPLE_EXECUTION +# include "simpl32-defs.h" +# elif DYNAMIC_EXECUTION +# include "dyn32-defs.h" +# else +extern void l_none PARAMS((void)); +# endif +#else +extern void l_none PARAMS((void)); +#endif + + +struct or32_letter { + char letter; + int sign; + /* int reloc; relocation per letter ??*/ +}; + +enum insn_type { + it_unknown, + it_exception, + it_arith, + it_shift, + it_compare, + it_branch, + it_jump, + it_load, + it_store, + it_movimm, + it_move, + it_extend, + it_nop, + it_mac, + it_float }; + +/* Main instruction specification array. */ +struct or32_opcode { + /* Name of the instruction. */ + char *name; + + /* A string of characters which describe the operands. + Valid characters are: + ,() Itself. Characters appears in the assembly code. + rA Register operand. + rB Register operand. + rD Register operand (destination). + I An immediate operand, range -32768 to 32767. + J An immediate operand, range . (unused) + K An immediate operand, range 0 to 65535. + L An immediate operand, range 0 to 63. + M An immediate operand, range . (unused) + N An immediate operand, range -33554432 to 33554431. + O An immediate operand, range . (unused) */ + char *args; + + /* Opcode and operand encoding. */ + char *encoding; + +#ifdef HAVE_EXECUTION +# if COMPLEX_EXECUTION + char *function_name; +# elif SIMPLE_EXECUTION + void (*exec)(struct iqueue_entry *); +# else /* DYNAMIC_EXECUTION */ + void (*exec)(struct op_queue *opq, int param_t[3], int); +# endif +#else /* HAVE_EXECUTION */ + void (*exec)(void); +#endif + + unsigned int flags; + enum insn_type func_unit; +}; + +/* This operand is the last in the list */ +#define OPTYPE_LAST (0x80000000) +/* This operand marks the end of the operand sequence (for things like I(rD)) */ +#define OPTYPE_OP (0x40000000) +/* The operand specifies a register index */ +#define OPTYPE_REG (0x20000000) +/* The operand must be sign extended */ +#define OPTYPE_SIG (0x10000000) +/* Operand is a relative address, the `I' in `I(rD)' */ +#define OPTYPE_DIS (0x08000000) +/* The operand is a destination */ +#define OPTYPE_DST (0x04000000) +/* Which bit of the operand is the sign bit */ +#define OPTYPE_SBIT (0x00001F00) +/* Amount to shift the instruction word right to get the operand */ +#define OPTYPE_SHR (0x0000001F) +#define OPTYPE_SBIT_SHR (8) + +/* MM: Data how to decode operands. */ +extern struct insn_op_struct { + unsigned long type; + unsigned long data; +} **op_start; + +/* Leaf flag used in automata building */ +#define LEAF_FLAG (0x80000000) + +struct temp_insn_struct +{ + unsigned long insn; + unsigned long insn_mask; + int in_pass; +}; + +extern unsigned long *automata; +extern struct temp_insn_struct *ti; + +extern CONST struct or32_letter or32_letters[]; + +extern CONST struct or32_opcode or32_opcodes[]; + +extern CONST int num_opcodes; + +extern char *disassembled; + +/* Calculates instruction length in bytes. Always 4 for OR32. */ +extern int insn_len PARAMS((int insn_index)); + +/* Is individual insn's operand signed or unsigned? */ +extern int letter_signed PARAMS((char l)); + +/* Number of letters in the individual lettered operand. */ +extern int letter_range PARAMS((char l)); + +/* MM: Returns index of given instruction name. */ +extern int insn_index PARAMS((char *insn)); + +/* MM: Returns instruction name from index. */ +extern CONST char *insn_name PARAMS ((int index)); + +/* MM: Constructs new FSM, based on or32_opcodes. */ +extern void build_automata PARAMS ((void)); + +/* MM: Destructs FSM. */ +extern void destruct_automata PARAMS ((void)); + +/* MM: Decodes instruction using FSM. Call build_automata first. */ +extern int insn_decode PARAMS((unsigned int insn)); + +/* Disassemble one instruction from insn to disassemble. + Return the size of the instruction. */ +int disassemble_insn (unsigned long insn); + +/* Disassemble one instruction from insn index. + Return the size of the instruction. */ +int disassemble_index (unsigned long insn, int index); + +/* FOR INTERNAL USE ONLY */ +/* Automatically 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); + +/* Extracts value from opcode */ +unsigned long or32_extract(char param_ch, char *enc_initial, unsigned long insn); + +#endif + Index: or1k/except.h =================================================================== --- or1k/except.h (nonexistent) +++ or1k/except.h (revision 1765) @@ -0,0 +1,55 @@ +/* except.h -- OR1K architecture specific exceptions + + Copyright (C) 1999 Damjan Lampret, lampret@opencores.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. */ + + +#ifndef EXCEPT__H +#define EXCEPT__H + + +/* Package includes */ +#include "arch.h" + +/* Definition of OR1K exceptions */ +#define EXCEPT_NONE 0x0000 +#define EXCEPT_RESET 0x0100 +#define EXCEPT_BUSERR 0x0200 +#define EXCEPT_DPF 0x0300 +#define EXCEPT_IPF 0x0400 +#define EXCEPT_TICK 0x0500 +#define EXCEPT_ALIGN 0x0600 +#define EXCEPT_ILLEGAL 0x0700 +#define EXCEPT_INT 0x0800 +#define EXCEPT_DTLBMISS 0x0900 +#define EXCEPT_ITLBMISS 0x0a00 +#define EXCEPT_RANGE 0x0b00 +#define EXCEPT_SYSCALL 0x0c00 +#define EXCEPT_FPE 0x0d00 +#define EXCEPT_TRAP 0x0e00 + +/* Function prototypes for external use */ +extern void except_handle (oraddr_t except, oraddr_t ea); +extern int except_pending; + +#endif /* EXCEPT__H */ Index: or1k/Makefile.in =================================================================== --- or1k/Makefile.in (nonexistent) +++ or1k/Makefile.in (revision 1765) @@ -0,0 +1,480 @@ +# 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 OR1K architecture 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 . + +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@ +subdir = cpu/or1k +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) +libor1k_la_LIBADD = +am_libor1k_la_OBJECTS = sprs.lo except.lo spr-dump.lo +libor1k_la_OBJECTS = $(am_libor1k_la_OBJECTS) +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 = $(libor1k_la_SOURCES) +DIST_SOURCES = $(libor1k_la_SOURCES) +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@ +noinst_LTLIBRARIES = libor1k.la +libor1k_la_SOURCES = sprs.c \ + except.c \ + spr-dump.c \ + sprs.h \ + except.h \ + spr-dump.h \ + arch.h \ + spr-defs.h \ + opcode/or32.h + +all: 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/or1k/Makefile'; \ + cd $(top_srcdir) && \ + $(AUTOMAKE) --gnu cpu/or1k/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 +libor1k.la: $(libor1k_la_OBJECTS) $(libor1k_la_DEPENDENCIES) + $(LINK) $(libor1k_la_OBJECTS) $(libor1k_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/except.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/spr-dump.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sprs.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 $@ $< + +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: check-am +all-am: Makefile $(LTLIBRARIES) +installdirs: +install: 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: + +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." +clean: clean-am + +clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ + 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 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 + +# 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: Index: or1k/arch.h =================================================================== --- or1k/arch.h (nonexistent) +++ or1k/arch.h (revision 1765) @@ -0,0 +1,50 @@ +/* arch.h -- OR1K architecture specific macros + + Copyright (C) 1999 Damjan Lampret, lampret@opencores.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. */ + + +#ifndef ARCH__H +#define ARCH__H + +/* Autoconf and/or portability configuration */ +#include "port.h" + +/*! Index of the link register */ +#define LINK_REGNO 9 + +/* Conversion macros */ +#define ADDR_C(c) UINT32_C(c) +#define REG_C(c) UINT32_C(c) + +/* Strings for printing OpenRISC types */ +#define PRIxADDR "08" PRIx32 /*!< print an openrisc address in hex */ +#define PRIxREG "08" PRIx32 /*!< print an openrisc register in hex */ +#define PRIdREG PRId32 /*!< print an openrisc register in decimals */ + +/* Basic types for openrisc */ +typedef uint32_t oraddr_t; /*!< Address as addressed by openrisc */ +typedef uint32_t uorreg_t; /*!< An unsigned register of openrisc */ +typedef int32_t orreg_t; /*!< A signed register of openrisc */ + +#endif /* ARCH__H */ Index: or1k/Makefile.am =================================================================== --- or1k/Makefile.am (nonexistent) +++ or1k/Makefile.am (revision 1765) @@ -0,0 +1,33 @@ +# Makefile -- Makefile for OR1K architecture 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 . + + +noinst_LTLIBRARIES = libor1k.la +libor1k_la_SOURCES = sprs.c \ + except.c \ + spr-dump.c \ + sprs.h \ + except.h \ + spr-dump.h \ + arch.h \ + spr-defs.h \ + opcode/or32.h Index: or1k/spr-defs.h =================================================================== --- or1k/spr-defs.h (nonexistent) +++ or1k/spr-defs.h (revision 1765) @@ -0,0 +1,577 @@ +/* spr-defs.h -- Defines OR1K architecture specific special-purpose registers + + 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 . */ + +/* This program is commented throughout in a fashion suitable for processing + with Doxygen. */ + + +#ifndef SPR_DEFS__H +#define SPR_DEFS__H + +/* Definition of special-purpose registers (SPRs). */ + +#define MAX_GRPS (32) +#define MAX_SPRS_PER_GRP_BITS (11) +#define MAX_SPRS_PER_GRP (1 << MAX_SPRS_PER_GRP_BITS) +#define MAX_SPRS (0x10000) + +/* Base addresses for the groups */ +#define SPRGROUP_SYS (0<< MAX_SPRS_PER_GRP_BITS) +#define SPRGROUP_DMMU (1<< MAX_SPRS_PER_GRP_BITS) +#define SPRGROUP_IMMU (2<< MAX_SPRS_PER_GRP_BITS) +#define SPRGROUP_DC (3<< MAX_SPRS_PER_GRP_BITS) +#define SPRGROUP_IC (4<< MAX_SPRS_PER_GRP_BITS) +#define SPRGROUP_MAC (5<< MAX_SPRS_PER_GRP_BITS) +#define SPRGROUP_D (6<< MAX_SPRS_PER_GRP_BITS) +#define SPRGROUP_PC (7<< MAX_SPRS_PER_GRP_BITS) +#define SPRGROUP_PM (8<< MAX_SPRS_PER_GRP_BITS) +#define SPRGROUP_PIC (9<< MAX_SPRS_PER_GRP_BITS) +#define SPRGROUP_TT (10<< MAX_SPRS_PER_GRP_BITS) + +/* System control and status group */ +#define SPR_VR (SPRGROUP_SYS + 0) +#define SPR_UPR (SPRGROUP_SYS + 1) +#define SPR_CPUCFGR (SPRGROUP_SYS + 2) +#define SPR_DMMUCFGR (SPRGROUP_SYS + 3) +#define SPR_IMMUCFGR (SPRGROUP_SYS + 4) +#define SPR_DCCFGR (SPRGROUP_SYS + 5) +#define SPR_ICCFGR (SPRGROUP_SYS + 6) +#define SPR_DCFGR (SPRGROUP_SYS + 7) +#define SPR_PCCFGR (SPRGROUP_SYS + 8) +#define SPR_NPC (SPRGROUP_SYS + 16) /* CZ 21/06/01 */ +#define SPR_SR (SPRGROUP_SYS + 17) /* CZ 21/06/01 */ +#define SPR_PPC (SPRGROUP_SYS + 18) /* CZ 21/06/01 */ +#define SPR_EPCR_BASE (SPRGROUP_SYS + 32) /* CZ 21/06/01 */ +#define SPR_EPCR_LAST (SPRGROUP_SYS + 47) /* CZ 21/06/01 */ +#define SPR_EEAR_BASE (SPRGROUP_SYS + 48) +#define SPR_EEAR_LAST (SPRGROUP_SYS + 63) +#define SPR_ESR_BASE (SPRGROUP_SYS + 64) +#define SPR_ESR_LAST (SPRGROUP_SYS + 79) + +/* Data MMU group */ +#define SPR_DMMUCR (SPRGROUP_DMMU + 0) +#define SPR_DTLBMR_BASE(WAY) (SPRGROUP_DMMU + 0x200 + (WAY) * 0x100) +#define SPR_DTLBMR_LAST(WAY) (SPRGROUP_DMMU + 0x27f + (WAY) * 0x100) +#define SPR_DTLBTR_BASE(WAY) (SPRGROUP_DMMU + 0x280 + (WAY) * 0x100) +#define SPR_DTLBTR_LAST(WAY) (SPRGROUP_DMMU + 0x2ff + (WAY) * 0x100) + +/* Instruction MMU group */ +#define SPR_IMMUCR (SPRGROUP_IMMU + 0) +#define SPR_ITLBMR_BASE(WAY) (SPRGROUP_IMMU + 0x200 + (WAY) * 0x100) +#define SPR_ITLBMR_LAST(WAY) (SPRGROUP_IMMU + 0x27f + (WAY) * 0x100) +#define SPR_ITLBTR_BASE(WAY) (SPRGROUP_IMMU + 0x280 + (WAY) * 0x100) +#define SPR_ITLBTR_LAST(WAY) (SPRGROUP_IMMU + 0x2ff + (WAY) * 0x100) + +/* Data cache group */ +#define SPR_DCCR (SPRGROUP_DC + 0) +#define SPR_DCBPR (SPRGROUP_DC + 1) +#define SPR_DCBFR (SPRGROUP_DC + 2) +#define SPR_DCBIR (SPRGROUP_DC + 3) +#define SPR_DCBWR (SPRGROUP_DC + 4) +#define SPR_DCBLR (SPRGROUP_DC + 5) +#define SPR_DCR_BASE(WAY) (SPRGROUP_DC + 0x200 + (WAY) * 0x200) +#define SPR_DCR_LAST(WAY) (SPRGROUP_DC + 0x3ff + (WAY) * 0x200) + +/* Instruction cache group */ +#define SPR_ICCR (SPRGROUP_IC + 0) +#define SPR_ICBPR (SPRGROUP_IC + 1) +#define SPR_ICBIR (SPRGROUP_IC + 2) +#define SPR_ICBLR (SPRGROUP_IC + 3) +#define SPR_ICR_BASE(WAY) (SPRGROUP_IC + 0x200 + (WAY) * 0x200) +#define SPR_ICR_LAST(WAY) (SPRGROUP_IC + 0x3ff + (WAY) * 0x200) + +/* MAC group */ +#define SPR_MACLO (SPRGROUP_MAC + 1) +#define SPR_MACHI (SPRGROUP_MAC + 2) + +/* Debug group */ +#define SPR_DVR(N) (SPRGROUP_D + (N)) +#define SPR_DCR(N) (SPRGROUP_D + 8 + (N)) +#define SPR_DMR1 (SPRGROUP_D + 16) +#define SPR_DMR2 (SPRGROUP_D + 17) +#define SPR_DWCR0 (SPRGROUP_D + 18) +#define SPR_DWCR1 (SPRGROUP_D + 19) +#define SPR_DSR (SPRGROUP_D + 20) +#define SPR_DRR (SPRGROUP_D + 21) + +/* Performance counters group */ +#define SPR_PCCR(N) (SPRGROUP_PC + (N)) +#define SPR_PCMR(N) (SPRGROUP_PC + 8 + (N)) + +/* Power management group */ +#define SPR_PMR (SPRGROUP_PM + 0) + +/* PIC group */ +#define SPR_PICMR (SPRGROUP_PIC + 0) +#define SPR_PICPR (SPRGROUP_PIC + 1) +#define SPR_PICSR (SPRGROUP_PIC + 2) + +/* Tick Timer group */ +#define SPR_TTMR (SPRGROUP_TT + 0) +#define SPR_TTCR (SPRGROUP_TT + 1) + +/* + * Bit definitions for the Version Register + * + */ +#define SPR_VR_VER 0xff000000 /* Processor version */ +#define SPR_VR_CFG 0x00ff0000 /* Processor configuration */ +#define SPR_VR_RES 0x00ff0000 /* Reserved */ +#define SPR_VR_REV 0x0000003f /* Processor revision */ + +#define SPR_VR_VER_OFF 24 +#define SPR_VR_CFG_OFF 16 +#define SPR_VR_REV_OFF 0 + +/* + * Bit definitions for the Unit Present Register + * + */ +#define SPR_UPR_UP 0x00000001 /* UPR present */ +#define SPR_UPR_DCP 0x00000002 /* Data cache present */ +#define SPR_UPR_ICP 0x00000004 /* Instruction cache present */ +#define SPR_UPR_DMP 0x00000008 /* Data MMU present */ +#define SPR_UPR_IMP 0x00000010 /* Instruction MMU present */ +#define SPR_UPR_MP 0x00000020 /* MAC present */ +#define SPR_UPR_DUP 0x00000040 /* Debug unit present */ +#define SPR_UPR_PCUP 0x00000080 /* Performance counters unit present */ +#define SPR_UPR_PMP 0x00000100 /* Power management present */ +#define SPR_UPR_PICP 0x00000200 /* PIC present */ +#define SPR_UPR_TTP 0x00000400 /* Tick timer present */ +#define SPR_UPR_RES 0x00fe0000 /* Reserved */ +#define SPR_UPR_CUP 0xff000000 /* Context units present */ + +/* + * JPB: Bit definitions for the CPU configuration register + * + */ +#define SPR_CPUCFGR_NSGF 0x0000000f /* Number of shadow GPR files */ +#define SPR_CPUCFGR_CGF 0x00000010 /* Custom GPR file */ +#define SPR_CPUCFGR_OB32S 0x00000020 /* ORBIS32 supported */ +#define SPR_CPUCFGR_OB64S 0x00000040 /* ORBIS64 supported */ +#define SPR_CPUCFGR_OF32S 0x00000080 /* ORFPX32 supported */ +#define SPR_CPUCFGR_OF64S 0x00000100 /* ORFPX64 supported */ +#define SPR_CPUCFGR_OV64S 0x00000200 /* ORVDX64 supported */ +#define SPR_CPUCFGR_RES 0xfffffc00 /* Reserved */ + +/* + * JPB: Bit definitions for the Debug configuration register and other + * constants. + * + */ + +#define SPR_DCFGR_NDP 0x00000007 /* Number of matchpoints mask */ +#define SPR_DCFGR_NDP1 0x00000000 /* One matchpoint supported */ +#define SPR_DCFGR_NDP2 0x00000001 /* Two matchpoints supported */ +#define SPR_DCFGR_NDP3 0x00000002 /* Three matchpoints supported */ +#define SPR_DCFGR_NDP4 0x00000003 /* Four matchpoints supported */ +#define SPR_DCFGR_NDP5 0x00000004 /* Five matchpoints supported */ +#define SPR_DCFGR_NDP6 0x00000005 /* Six matchpoints supported */ +#define SPR_DCFGR_NDP7 0x00000006 /* Seven matchpoints supported */ +#define SPR_DCFGR_NDP8 0x00000007 /* Eight matchpoints supported */ +#define SPR_DCFGR_WPCI 0x00000008 /* Watchpoint counters implemented */ + +#define MATCHPOINTS_TO_NDP(n) (1 == n ? SPR_DCFGR_NDP1 : \ + 2 == n ? SPR_DCFGR_NDP2 : \ + 3 == n ? SPR_DCFGR_NDP3 : \ + 4 == n ? SPR_DCFGR_NDP4 : \ + 5 == n ? SPR_DCFGR_NDP5 : \ + 6 == n ? SPR_DCFGR_NDP6 : \ + 7 == n ? SPR_DCFGR_NDP7 : SPR_DCFGR_NDP8) +#define MAX_MATCHPOINTS 8 +#define MAX_WATCHPOINTS (MAX_MATCHPOINTS + 2) + +/* + * Bit definitions for the Supervision Register + * + */ +#define SPR_SR_SM 0x00000001 /* Supervisor Mode */ +#define SPR_SR_TEE 0x00000002 /* Tick timer Exception Enable */ +#define SPR_SR_IEE 0x00000004 /* Interrupt Exception Enable */ +#define SPR_SR_DCE 0x00000008 /* Data Cache Enable */ +#define SPR_SR_ICE 0x00000010 /* Instruction Cache Enable */ +#define SPR_SR_DME 0x00000020 /* Data MMU Enable */ +#define SPR_SR_IME 0x00000040 /* Instruction MMU Enable */ +#define SPR_SR_LEE 0x00000080 /* Little Endian Enable */ +#define SPR_SR_CE 0x00000100 /* CID Enable */ +#define SPR_SR_F 0x00000200 /* Condition Flag */ +#define SPR_SR_CY 0x00000400 /* Carry flag */ +#define SPR_SR_OV 0x00000800 /* Overflow flag */ +#define SPR_SR_OVE 0x00001000 /* Overflow flag Exception */ +#define SPR_SR_DSX 0x00002000 /* Delay Slot Exception */ +#define SPR_SR_EPH 0x00004000 /* Exception Prefix High */ +#define SPR_SR_FO 0x00008000 /* Fixed one */ +#define SPR_SR_SUMRA 0x00010000 /* Supervisor SPR read access */ +#define SPR_SR_RES 0x0ffe0000 /* Reserved */ +#define SPR_SR_CID 0xf0000000 /* Context ID */ + +/* + * Bit definitions for the Data MMU Control Register + * + */ +#define SPR_DMMUCR_P2S 0x0000003e /* Level 2 Page Size */ +#define SPR_DMMUCR_P1S 0x000007c0 /* Level 1 Page Size */ +#define SPR_DMMUCR_VADDR_WIDTH 0x0000f800 /* Virtual ADDR Width */ +#define SPR_DMMUCR_PADDR_WIDTH 0x000f0000 /* Physical ADDR Width */ + +/* + * Bit definitions for the Instruction MMU Control Register + * + */ +#define SPR_IMMUCR_P2S 0x0000003e /* Level 2 Page Size */ +#define SPR_IMMUCR_P1S 0x000007c0 /* Level 1 Page Size */ +#define SPR_IMMUCR_VADDR_WIDTH 0x0000f800 /* Virtual ADDR Width */ +#define SPR_IMMUCR_PADDR_WIDTH 0x000f0000 /* Physical ADDR Width */ + +/* + * Bit definitions for the Data TLB Match Register + * + */ +#define SPR_DTLBMR_V 0x00000001 /* Valid */ +#define SPR_DTLBMR_PL1 0x00000002 /* Page Level 1 (if 0 then PL2) */ +#define SPR_DTLBMR_CID 0x0000003c /* Context ID */ +#define SPR_DTLBMR_LRU 0x000000c0 /* Least Recently Used */ +#define SPR_DTLBMR_VPN 0xfffff000 /* Virtual Page Number */ + +/* + * Bit definitions for the Data TLB Translate Register + * + */ +#define SPR_DTLBTR_CC 0x00000001 /* Cache Coherency */ +#define SPR_DTLBTR_CI 0x00000002 /* Cache Inhibit */ +#define SPR_DTLBTR_WBC 0x00000004 /* Write-Back Cache */ +#define SPR_DTLBTR_WOM 0x00000008 /* Weakly-Ordered Memory */ +#define SPR_DTLBTR_A 0x00000010 /* Accessed */ +#define SPR_DTLBTR_D 0x00000020 /* Dirty */ +#define SPR_DTLBTR_URE 0x00000040 /* User Read Enable */ +#define SPR_DTLBTR_UWE 0x00000080 /* User Write Enable */ +#define SPR_DTLBTR_SRE 0x00000100 /* Supervisor Read Enable */ +#define SPR_DTLBTR_SWE 0x00000200 /* Supervisor Write Enable */ +#define SPR_DTLBTR_PPN 0xfffff000 /* Physical Page Number */ + +/* + * Bit definitions for the Instruction TLB Match Register + * + */ +#define SPR_ITLBMR_V 0x00000001 /* Valid */ +#define SPR_ITLBMR_PL1 0x00000002 /* Page Level 1 (if 0 then PL2) */ +#define SPR_ITLBMR_CID 0x0000003c /* Context ID */ +#define SPR_ITLBMR_LRU 0x000000c0 /* Least Recently Used */ +#define SPR_ITLBMR_VPN 0xfffff000 /* Virtual Page Number */ + +/* + * Bit definitions for the Instruction TLB Translate Register + * + */ +#define SPR_ITLBTR_CC 0x00000001 /* Cache Coherency */ +#define SPR_ITLBTR_CI 0x00000002 /* Cache Inhibit */ +#define SPR_ITLBTR_WBC 0x00000004 /* Write-Back Cache */ +#define SPR_ITLBTR_WOM 0x00000008 /* Weakly-Ordered Memory */ +#define SPR_ITLBTR_A 0x00000010 /* Accessed */ +#define SPR_ITLBTR_D 0x00000020 /* Dirty */ +#define SPR_ITLBTR_SXE 0x00000040 /* User Read Enable */ +#define SPR_ITLBTR_UXE 0x00000080 /* User Write Enable */ +#define SPR_ITLBTR_PPN 0xfffff000 /* Physical Page Number */ + +/* + * Bit definitions for Data Cache Control register + * + */ +#define SPR_DCCR_EW 0x000000ff /* Enable ways */ + +/* + * Bit definitions for Insn Cache Control register + * + */ +#define SPR_ICCR_EW 0x000000ff /* Enable ways */ + +/* + * Bit definitions for Data Cache Configuration Register + * + */ + +#define SPR_DCCFGR_NCW 0x00000007 +#define SPR_DCCFGR_NCS 0x00000078 +#define SPR_DCCFGR_CBS 0x00000080 +#define SPR_DCCFGR_CWS 0x00000100 +#define SPR_DCCFGR_CCRI 0x00000200 +#define SPR_DCCFGR_CBIRI 0x00000400 +#define SPR_DCCFGR_CBPRI 0x00000800 +#define SPR_DCCFGR_CBLRI 0x00001000 +#define SPR_DCCFGR_CBFRI 0x00002000 +#define SPR_DCCFGR_CBWBRI 0x00004000 + +#define SPR_DCCFGR_NCW_OFF 0 +#define SPR_DCCFGR_NCS_OFF 3 +#define SPR_DCCFGR_CBS_OFF 7 + +/* + * Bit definitions for Instruction Cache Configuration Register + * + */ +#define SPR_ICCFGR_NCW 0x00000007 +#define SPR_ICCFGR_NCS 0x00000078 +#define SPR_ICCFGR_CBS 0x00000080 +#define SPR_ICCFGR_CCRI 0x00000200 +#define SPR_ICCFGR_CBIRI 0x00000400 +#define SPR_ICCFGR_CBPRI 0x00000800 +#define SPR_ICCFGR_CBLRI 0x00001000 + +#define SPR_ICCFGR_NCW_OFF 0 +#define SPR_ICCFGR_NCS_OFF 3 +#define SPR_ICCFGR_CBS_OFF 7 + +/* + * Bit definitions for Data MMU Configuration Register + * + */ + +#define SPR_DMMUCFGR_NTW 0x00000003 +#define SPR_DMMUCFGR_NTS 0x0000001C +#define SPR_DMMUCFGR_NAE 0x000000E0 +#define SPR_DMMUCFGR_CRI 0x00000100 +#define SPR_DMMUCFGR_PRI 0x00000200 +#define SPR_DMMUCFGR_TEIRI 0x00000400 +#define SPR_DMMUCFGR_HTR 0x00000800 + +#define SPR_DMMUCFGR_NTW_OFF 0 +#define SPR_DMMUCFGR_NTS_OFF 2 + +/* + * Bit definitions for Instruction MMU Configuration Register + * + */ + +#define SPR_IMMUCFGR_NTW 0x00000003 +#define SPR_IMMUCFGR_NTS 0x0000001C +#define SPR_IMMUCFGR_NAE 0x000000E0 +#define SPR_IMMUCFGR_CRI 0x00000100 +#define SPR_IMMUCFGR_PRI 0x00000200 +#define SPR_IMMUCFGR_TEIRI 0x00000400 +#define SPR_IMMUCFGR_HTR 0x00000800 + +#define SPR_IMMUCFGR_NTW_OFF 0 +#define SPR_IMMUCFGR_NTS_OFF 2 + +/* + * Bit definitions for Debug Control registers + * + */ +#define SPR_DCR_DP 0x00000001 /* DVR/DCR present */ +#define SPR_DCR_CC 0x0000000e /* Compare condition */ +#define SPR_DCR_SC 0x00000010 /* Signed compare */ +#define SPR_DCR_CT 0x000000e0 /* Compare to */ + +/* Bit results with SPR_DCR_CC mask */ +#define SPR_DCR_CC_MASKED 0x00000000 +#define SPR_DCR_CC_EQUAL 0x00000002 +#define SPR_DCR_CC_LESS 0x00000004 +#define SPR_DCR_CC_LESSE 0x00000006 +#define SPR_DCR_CC_GREAT 0x00000008 +#define SPR_DCR_CC_GREATE 0x0000000a +#define SPR_DCR_CC_NEQUAL 0x0000000c + +/* Bit results with SPR_DCR_CT mask */ +#define SPR_DCR_CT_DISABLED 0x00000000 +#define SPR_DCR_CT_IFEA 0x00000020 +#define SPR_DCR_CT_LEA 0x00000040 +#define SPR_DCR_CT_SEA 0x00000060 +#define SPR_DCR_CT_LD 0x00000080 +#define SPR_DCR_CT_SD 0x000000a0 +#define SPR_DCR_CT_LSEA 0x000000c0 +#define SPR_DCR_CT_LSD 0x000000e0 +/* SPR_DCR_CT_LSD doesn't seem to be implemented anywhere in or1ksim. 2004-1-30 HP */ + +/* + * Bit definitions for Debug Mode 1 register + * + */ +#define SPR_DMR1_CW 0x000fffff /* Chain register pair data */ +#define SPR_DMR1_CW0_AND 0x00000001 +#define SPR_DMR1_CW0_OR 0x00000002 +#define SPR_DMR1_CW0 (SPR_DMR1_CW0_AND | SPR_DMR1_CW0_OR) +#define SPR_DMR1_CW1_AND 0x00000004 +#define SPR_DMR1_CW1_OR 0x00000008 +#define SPR_DMR1_CW1 (SPR_DMR1_CW1_AND | SPR_DMR1_CW1_OR) +#define SPR_DMR1_CW2_AND 0x00000010 +#define SPR_DMR1_CW2_OR 0x00000020 +#define SPR_DMR1_CW2 (SPR_DMR1_CW2_AND | SPR_DMR1_CW2_OR) +#define SPR_DMR1_CW3_AND 0x00000040 +#define SPR_DMR1_CW3_OR 0x00000080 +#define SPR_DMR1_CW3 (SPR_DMR1_CW3_AND | SPR_DMR1_CW3_OR) +#define SPR_DMR1_CW4_AND 0x00000100 +#define SPR_DMR1_CW4_OR 0x00000200 +#define SPR_DMR1_CW4 (SPR_DMR1_CW4_AND | SPR_DMR1_CW4_OR) +#define SPR_DMR1_CW5_AND 0x00000400 +#define SPR_DMR1_CW5_OR 0x00000800 +#define SPR_DMR1_CW5 (SPR_DMR1_CW5_AND | SPR_DMR1_CW5_OR) +#define SPR_DMR1_CW6_AND 0x00001000 +#define SPR_DMR1_CW6_OR 0x00002000 +#define SPR_DMR1_CW6 (SPR_DMR1_CW6_AND | SPR_DMR1_CW6_OR) +#define SPR_DMR1_CW7_AND 0x00004000 +#define SPR_DMR1_CW7_OR 0x00008000 +#define SPR_DMR1_CW7 (SPR_DMR1_CW7_AND | SPR_DMR1_CW7_OR) +#define SPR_DMR1_CW8_AND 0x00010000 +#define SPR_DMR1_CW8_OR 0x00020000 +#define SPR_DMR1_CW8 (SPR_DMR1_CW8_AND | SPR_DMR1_CW8_OR) +#define SPR_DMR1_CW9_AND 0x00040000 +#define SPR_DMR1_CW9_OR 0x00080000 +#define SPR_DMR1_CW9 (SPR_DMR1_CW9_AND | SPR_DMR1_CW9_OR) +#define SPR_DMR1_RES1 0x00300000 /* Reserved */ +#define SPR_DMR1_ST 0x00400000 /* Single-step trace*/ +#define SPR_DMR1_BT 0x00800000 /* Branch trace */ +#define SPR_DMR1_RES2 0xff000000 /* Reserved */ + +/* + * Bit definitions for Debug Mode 2 register. AWTC and WGB corrected by JPB + * + */ +#define SPR_DMR2_WCE0 0x00000001 /* Watchpoint counter 0 enable */ +#define SPR_DMR2_WCE1 0x00000002 /* Watchpoint counter 0 enable */ +#define SPR_DMR2_AWTC 0x00000ffc /* Assign watchpoints to counters */ +#define SPR_DMR2_AWTC_OFF 2 /* Bit offset to AWTC field */ +#define SPR_DMR2_WGB 0x003ff000 /* Watchpoints generating breakpoint */ +#define SPR_DMR2_WGB_OFF 12 /* Bit offset to WGB field */ +#define SPR_DMR2_WBS 0xffc00000 /* JPB: Watchpoint status */ +#define SPR_DMR2_WBS_OFF 22 /* Bit offset to WBS field */ + +/* + * Bit definitions for Debug watchpoint counter registers + * + */ +#define SPR_DWCR_COUNT 0x0000ffff /* Count */ +#define SPR_DWCR_MATCH 0xffff0000 /* Match */ +#define SPR_DWCR_MATCH_OFF 16 /* Match bit offset */ + +/* + * Bit definitions for Debug stop register + * + */ +#define SPR_DSR_RSTE 0x00000001 /* Reset exception */ +#define SPR_DSR_BUSEE 0x00000002 /* Bus error exception */ +#define SPR_DSR_DPFE 0x00000004 /* Data Page Fault exception */ +#define SPR_DSR_IPFE 0x00000008 /* Insn Page Fault exception */ +#define SPR_DSR_TTE 0x00000010 /* Tick Timer exception */ +#define SPR_DSR_AE 0x00000020 /* Alignment exception */ +#define SPR_DSR_IIE 0x00000040 /* Illegal Instruction exception */ +#define SPR_DSR_IE 0x00000080 /* Interrupt exception */ +#define SPR_DSR_DME 0x00000100 /* DTLB miss exception */ +#define SPR_DSR_IME 0x00000200 /* ITLB miss exception */ +#define SPR_DSR_RE 0x00000400 /* Range exception */ +#define SPR_DSR_SCE 0x00000800 /* System call exception */ +#define SPR_DSR_SSE 0x00001000 /* Single Step Exception */ +#define SPR_DSR_TE 0x00002000 /* Trap exception */ + +/* + * Bit definitions for Debug reason register + * + */ +#define SPR_DRR_RSTE 0x00000001 /* Reset exception */ +#define SPR_DRR_BUSEE 0x00000002 /* Bus error exception */ +#define SPR_DRR_DPFE 0x00000004 /* Data Page Fault exception */ +#define SPR_DRR_IPFE 0x00000008 /* Insn Page Fault exception */ +#define SPR_DRR_TTE 0x00000010 /* Tick Timer exception */ +#define SPR_DRR_AE 0x00000020 /* Alignment exception */ +#define SPR_DRR_IIE 0x00000040 /* Illegal Instruction exception */ +#define SPR_DRR_IE 0x00000080 /* Interrupt exception */ +#define SPR_DRR_DME 0x00000100 /* DTLB miss exception */ +#define SPR_DRR_IME 0x00000200 /* ITLB miss exception */ +#define SPR_DRR_RE 0x00000400 /* Range exception */ +#define SPR_DRR_SCE 0x00000800 /* System call exception */ +#define SPR_DRR_TE 0x00001000 /* Trap exception */ + +/* + * Bit definitions for Performance counters mode registers + * + */ +#define SPR_PCMR_CP 0x00000001 /* Counter present */ +#define SPR_PCMR_UMRA 0x00000002 /* User mode read access */ +#define SPR_PCMR_CISM 0x00000004 /* Count in supervisor mode */ +#define SPR_PCMR_CIUM 0x00000008 /* Count in user mode */ +#define SPR_PCMR_LA 0x00000010 /* Load access event */ +#define SPR_PCMR_SA 0x00000020 /* Store access event */ +#define SPR_PCMR_IF 0x00000040 /* Instruction fetch event*/ +#define SPR_PCMR_DCM 0x00000080 /* Data cache miss event */ +#define SPR_PCMR_ICM 0x00000100 /* Insn cache miss event */ +#define SPR_PCMR_IFS 0x00000200 /* Insn fetch stall event */ +#define SPR_PCMR_LSUS 0x00000400 /* LSU stall event */ +#define SPR_PCMR_BS 0x00000800 /* Branch stall event */ +#define SPR_PCMR_DTLBM 0x00001000 /* DTLB miss event */ +#define SPR_PCMR_ITLBM 0x00002000 /* ITLB miss event */ +#define SPR_PCMR_DDS 0x00004000 /* Data dependency stall event */ +#define SPR_PCMR_WPE 0x03ff8000 /* Watchpoint events */ + +/* + * Bit definitions for the Power management register + * + */ +#define SPR_PMR_SDF 0x0000000f /* Slow down factor */ +#define SPR_PMR_DME 0x00000010 /* Doze mode enable */ +#define SPR_PMR_SME 0x00000020 /* Sleep mode enable */ +#define SPR_PMR_DCGE 0x00000040 /* Dynamic clock gating enable */ +#define SPR_PMR_SUME 0x00000080 /* Suspend mode enable */ + +/* + * Bit definitions for PICMR + * + */ +#define SPR_PICMR_IUM 0xfffffffc /* Interrupt unmask */ + +/* + * Bit definitions for PICPR + * + */ +#define SPR_PICPR_IPRIO 0xfffffffc /* Interrupt priority */ + +/* + * Bit definitions for PICSR + * + */ +#define SPR_PICSR_IS 0xffffffff /* Interrupt status */ + +/* + * Bit definitions for Tick Timer Control Register + * + */ +#define SPR_TTCR_PERIOD 0x0fffffff /* Time Period */ +#define SPR_TTMR_PERIOD SPR_TTCR_PERIOD +#define SPR_TTMR_IP 0x10000000 /* Interrupt Pending */ +#define SPR_TTMR_IE 0x20000000 /* Interrupt Enable */ +#define SPR_TTMR_RT 0x40000000 /* Restart tick */ +#define SPR_TTMR_SR 0x80000000 /* Single run */ +#define SPR_TTMR_CR 0xc0000000 /* Continuous run */ +#define SPR_TTMR_M 0xc0000000 /* Tick mode */ + +/* + * l.nop constants + * + */ +#define NOP_NOP 0x0000 /* Normal nop instruction */ +#define NOP_EXIT 0x0001 /* End of simulation */ +#define NOP_REPORT 0x0002 /* Simple report */ +#define NOP_PRINTF 0x0003 /* Simprintf instruction */ +#define NOP_PUTC 0x0004 /* JPB: Simputc instruction */ +#define NOP_CNT_RESET 0x0005 /* Reset statistics counters */ +#define NOP_REPORT_FIRST 0x0400 /* Report with number */ +#define NOP_REPORT_LAST 0x03ff /* Report with number */ + +#endif /* SPR_DEFS__H */ Index: or1k/sprs.h =================================================================== --- or1k/sprs.h (nonexistent) +++ or1k/sprs.h (revision 1765) @@ -0,0 +1,44 @@ +/* sprs.h -- OR1K architecture specific special-purpose registers + + Copyright (C) 1999 Damjan Lampret, lampret@opencores.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. */ + + +#ifndef SPRS__H +#define SPRS__H + +/* Autoconf and/or portability configuration */ +#include "port.h" + +/* Package includes */ +#include "arch.h" + +/* Function prototypes for external use */ +extern void mtspr (uint16_t regno, + const uorreg_t value); +extern uorreg_t mfspr (const uint16_t regno); +extern void sprs_status (); +extern char *dump_spr (uint16_t spr, + uorreg_t spr_val); + +#endif /* SPRS__H */ Index: or1k/spr-dump.h =================================================================== --- or1k/spr-dump.h (nonexistent) +++ or1k/spr-dump.h (revision 1765) @@ -0,0 +1,41 @@ +/* spr_dump.h -- Dump given spr in human readable form header + + Copyright (C) 2005 György `nog' Jeney, nog@sdf.lonestar.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 . */ + +/* This program is commented throughout in a fashion suitable for processing + with Doxygen. */ + + +#ifndef SPR_DUMP__H +#define SPR_DUMP__H + +/* System includes */ +#include + +/* Package includes */ +#include "arch.h" + + +/* Function prototypes for external use */ +extern char *dump_spr (uint16_t spr, + uorreg_t spr_val); + +#endif /* SPR_DUMP__H */ Index: or1k =================================================================== --- or1k (nonexistent) +++ or1k (revision 1765)
or1k Property changes : Added: svn:ignore ## -0,0 +1,2 ## +Makefile +.deps Index: Makefile.in =================================================================== --- Makefile.in (nonexistent) +++ Makefile.in (revision 1765) @@ -0,0 +1,518 @@ +# 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 all cpu simulations +# +# 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 . +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@ +subdir = cpu +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 = +SOURCES = +DIST_SOURCES = +RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \ + html-recursive info-recursive install-data-recursive \ + install-dvi-recursive install-exec-recursive \ + install-html-recursive install-info-recursive \ + install-pdf-recursive install-ps-recursive install-recursive \ + installcheck-recursive installdirs-recursive pdf-recursive \ + ps-recursive uninstall-recursive +RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ + distclean-recursive maintainer-clean-recursive +ETAGS = etags +CTAGS = ctags +DIST_SUBDIRS = $(SUBDIRS) +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@ +SUBDIRS = common or1k $(CPU_ARCH) +all: all-recursive + +.SUFFIXES: +$(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/Makefile'; \ + cd $(top_srcdir) && \ + $(AUTOMAKE) --gnu cpu/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 + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +# This directory's subdirectories are mostly independent; you can cd +# into them and run `make' without going through this Makefile. +# To change the values of `make' variables: instead of editing Makefiles, +# (1) if the variable is set in `config.status', edit `config.status' +# (which will cause the Makefiles to be regenerated when you run `make'); +# (2) otherwise, pass the desired values on the `make' command line. +$(RECURSIVE_TARGETS): + @failcom='exit 1'; \ + for f in x $$MAKEFLAGS; do \ + case $$f in \ + *=* | --[!k]*);; \ + *k*) failcom='fail=yes';; \ + esac; \ + done; \ + dot_seen=no; \ + target=`echo $@ | sed s/-recursive//`; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + dot_seen=yes; \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || eval $$failcom; \ + done; \ + if test "$$dot_seen" = "no"; then \ + $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ + fi; test -z "$$fail" + +$(RECURSIVE_CLEAN_TARGETS): + @failcom='exit 1'; \ + for f in x $$MAKEFLAGS; do \ + case $$f in \ + *=* | --[!k]*);; \ + *k*) failcom='fail=yes';; \ + esac; \ + done; \ + dot_seen=no; \ + case "$@" in \ + distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ + *) list='$(SUBDIRS)' ;; \ + esac; \ + rev=''; for subdir in $$list; do \ + if test "$$subdir" = "."; then :; else \ + rev="$$subdir $$rev"; \ + fi; \ + done; \ + rev="$$rev ."; \ + target=`echo $@ | sed s/-recursive//`; \ + for subdir in $$rev; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || eval $$failcom; \ + done && test -z "$$fail" +tags-recursive: + list='$(SUBDIRS)'; for subdir in $$list; do \ + test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \ + done +ctags-recursive: + list='$(SUBDIRS)'; for subdir in $$list; do \ + test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \ + done + +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: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ + include_option=--etags-include; \ + empty_fix=.; \ + else \ + include_option=--include; \ + empty_fix=; \ + fi; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test ! -f $$subdir/TAGS || \ + tags="$$tags $$include_option=$$here/$$subdir/TAGS"; \ + fi; \ + done; \ + 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: ctags-recursive $(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 + list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test -d "$(distdir)/$$subdir" \ + || $(MKDIR_P) "$(distdir)/$$subdir" \ + || exit 1; \ + distdir=`$(am__cd) $(distdir) && pwd`; \ + top_distdir=`$(am__cd) $(top_distdir) && pwd`; \ + (cd $$subdir && \ + $(MAKE) $(AM_MAKEFLAGS) \ + top_distdir="$$top_distdir" \ + distdir="$$distdir/$$subdir" \ + am__remove_distdir=: \ + am__skip_length_check=: \ + distdir) \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-recursive +all-am: Makefile +installdirs: installdirs-recursive +installdirs-am: +install: install-recursive +install-exec: install-exec-recursive +install-data: install-data-recursive +uninstall: uninstall-recursive + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-recursive +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: + +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." +clean: clean-recursive + +clean-am: clean-generic clean-libtool mostlyclean-am + +distclean: distclean-recursive + -rm -f Makefile +distclean-am: clean-am distclean-generic distclean-tags + +dvi: dvi-recursive + +dvi-am: + +html: html-recursive + +info: info-recursive + +info-am: + +install-data-am: + +install-dvi: install-dvi-recursive + +install-exec-am: + +install-html: install-html-recursive + +install-info: install-info-recursive + +install-man: + +install-pdf: install-pdf-recursive + +install-ps: install-ps-recursive + +installcheck-am: + +maintainer-clean: maintainer-clean-recursive + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-recursive + +mostlyclean-am: mostlyclean-generic mostlyclean-libtool + +pdf: pdf-recursive + +pdf-am: + +ps: ps-recursive + +ps-am: + +uninstall-am: + +.MAKE: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) install-am \ + install-strip + +.PHONY: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) CTAGS GTAGS \ + all all-am check check-am clean clean-generic clean-libtool \ + ctags ctags-recursive distclean 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 installdirs-am maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-generic \ + mostlyclean-libtool pdf pdf-am ps ps-am tags tags-recursive \ + uninstall uninstall-am + +# 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: Index: Makefile.am =================================================================== --- Makefile.am (nonexistent) +++ Makefile.am (revision 1765) @@ -0,0 +1,23 @@ +# Makefile -- Makefile for all cpu simulations +# +# 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 . + +SUBDIRS = common or1k $(CPU_ARCH) Index: or16 =================================================================== --- or16 (nonexistent) +++ or16 (revision 1765)
or16 Property changes : Added: svn:ignore ## -0,0 +1 ## +Makefile Index: . =================================================================== --- . (nonexistent) +++ . (revision 1765)
. Property changes : Added: svn:ignore ## -0,0 +1,2 ## +Makefile +.deps

powered by: WebSVN 2.1.0

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